[S390] dasd: remove uid from devmap
authorStefan Haberland <stefan.haberland@de.ibm.com>
Mon, 17 May 2010 08:00:11 +0000 (10:00 +0200)
committerMartin Schwidefsky <sky@mschwide.boeblingen.de.ibm.com>
Mon, 17 May 2010 08:00:16 +0000 (10:00 +0200)
Remove the duplicate of the DASD uid from the devmap structure.
Use the uid from the device private structure instead.
This also removes a lockdep warning complaining about a possible
SOFTIRQ-safe -> SOFTIRQ-unsafe lock order.

Signed-off-by: Stefan Haberland <stefan.haberland@de.ibm.com>
Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
drivers/s390/block/dasd_alias.c
drivers/s390/block/dasd_devmap.c
drivers/s390/block/dasd_eckd.c
drivers/s390/block/dasd_int.h

index a564b99..4155805 100644 (file)
@@ -190,20 +190,21 @@ int dasd_alias_make_device_known_to_lcu(struct dasd_device *device)
        struct alias_server *server, *newserver;
        struct alias_lcu *lcu, *newlcu;
        int is_lcu_known;
-       struct dasd_uid *uid;
+       struct dasd_uid uid;
 
        private = (struct dasd_eckd_private *) device->private;
-       uid = &private->uid;
+
+       device->discipline->get_uid(device, &uid);
        spin_lock_irqsave(&aliastree.lock, flags);
        is_lcu_known = 1;
-       server = _find_server(uid);
+       server = _find_server(&uid);
        if (!server) {
                spin_unlock_irqrestore(&aliastree.lock, flags);
-               newserver = _allocate_server(uid);
+               newserver = _allocate_server(&uid);
                if (IS_ERR(newserver))
                        return PTR_ERR(newserver);
                spin_lock_irqsave(&aliastree.lock, flags);
-               server = _find_server(uid);
+               server = _find_server(&uid);
                if (!server) {
                        list_add(&newserver->server, &aliastree.serverlist);
                        server = newserver;
@@ -214,14 +215,14 @@ int dasd_alias_make_device_known_to_lcu(struct dasd_device *device)
                }
        }
 
-       lcu = _find_lcu(server, uid);
+       lcu = _find_lcu(server, &uid);
        if (!lcu) {
                spin_unlock_irqrestore(&aliastree.lock, flags);
-               newlcu = _allocate_lcu(uid);
+               newlcu = _allocate_lcu(&uid);
                if (IS_ERR(newlcu))
                        return PTR_ERR(newlcu);
                spin_lock_irqsave(&aliastree.lock, flags);
-               lcu = _find_lcu(server, uid);
+               lcu = _find_lcu(server, &uid);
                if (!lcu) {
                        list_add(&newlcu->lcu, &server->lculist);
                        lcu = newlcu;
@@ -256,20 +257,20 @@ void dasd_alias_lcu_setup_complete(struct dasd_device *device)
        unsigned long flags;
        struct alias_server *server;
        struct alias_lcu *lcu;
-       struct dasd_uid *uid;
+       struct dasd_uid uid;
 
        private = (struct dasd_eckd_private *) device->private;
-       uid = &private->uid;
+       device->discipline->get_uid(device, &uid);
        lcu = NULL;
        spin_lock_irqsave(&aliastree.lock, flags);
-       server = _find_server(uid);
+       server = _find_server(&uid);
        if (server)
-               lcu = _find_lcu(server, uid);
+               lcu = _find_lcu(server, &uid);
        spin_unlock_irqrestore(&aliastree.lock, flags);
        if (!lcu) {
                DBF_EVENT_DEVID(DBF_ERR, device->cdev,
                                "could not find lcu for %04x %02x",
-                               uid->ssid, uid->real_unit_addr);
+                               uid.ssid, uid.real_unit_addr);
                WARN_ON(1);
                return;
        }
@@ -282,20 +283,20 @@ void dasd_alias_wait_for_lcu_setup(struct dasd_device *device)
        unsigned long flags;
        struct alias_server *server;
        struct alias_lcu *lcu;
-       struct dasd_uid *uid;
+       struct dasd_uid uid;
 
        private = (struct dasd_eckd_private *) device->private;
-       uid = &private->uid;
+       device->discipline->get_uid(device, &uid);
        lcu = NULL;
        spin_lock_irqsave(&aliastree.lock, flags);
-       server = _find_server(uid);
+       server = _find_server(&uid);
        if (server)
-               lcu = _find_lcu(server, uid);
+               lcu = _find_lcu(server, &uid);
        spin_unlock_irqrestore(&aliastree.lock, flags);
        if (!lcu) {
                DBF_EVENT_DEVID(DBF_ERR, device->cdev,
                                "could not find lcu for %04x %02x",
-                               uid->ssid, uid->real_unit_addr);
+                               uid.ssid, uid.real_unit_addr);
                WARN_ON(1);
                return;
        }
@@ -314,9 +315,11 @@ void dasd_alias_disconnect_device_from_lcu(struct dasd_device *device)
        struct alias_lcu *lcu;
        struct alias_server *server;
        int was_pending;
+       struct dasd_uid uid;
 
        private = (struct dasd_eckd_private *) device->private;
        lcu = private->lcu;
+       device->discipline->get_uid(device, &uid);
        spin_lock_irqsave(&lcu->lock, flags);
        list_del_init(&device->alias_list);
        /* make sure that the workers don't use this device */
@@ -353,7 +356,7 @@ void dasd_alias_disconnect_device_from_lcu(struct dasd_device *device)
                        _schedule_lcu_update(lcu, NULL);
                spin_unlock(&lcu->lock);
        }
-       server = _find_server(&private->uid);
+       server = _find_server(&uid);
        if (server && list_empty(&server->lculist)) {
                list_del(&server->server);
                _free_server(server);
@@ -366,19 +369,30 @@ void dasd_alias_disconnect_device_from_lcu(struct dasd_device *device)
  * in the lcu is up to date and will update the device uid before
  * adding it to a pav group.
  */
+
 static int _add_device_to_lcu(struct alias_lcu *lcu,
-                             struct dasd_device *device)
+                             struct dasd_device *device,
+                             struct dasd_device *pos)
 {
 
        struct dasd_eckd_private *private;
        struct alias_pav_group *group;
-       struct dasd_uid *uid;
+       struct dasd_uid uid;
+       unsigned long flags;
 
        private = (struct dasd_eckd_private *) device->private;
-       uid = &private->uid;
-       uid->type = lcu->uac->unit[uid->real_unit_addr].ua_type;
-       uid->base_unit_addr = lcu->uac->unit[uid->real_unit_addr].base_ua;
-       dasd_set_uid(device->cdev, &private->uid);
+
+       /* only lock if not already locked */
+       if (device != pos)
+               spin_lock_irqsave_nested(get_ccwdev_lock(device->cdev), flags,
+                                        CDEV_NESTED_SECOND);
+       private->uid.type = lcu->uac->unit[private->uid.real_unit_addr].ua_type;
+       private->uid.base_unit_addr =
+               lcu->uac->unit[private->uid.real_unit_addr].base_ua;
+       uid = private->uid;
+
+       if (device != pos)
+               spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags);
 
        /* if we have no PAV anyway, we don't need to bother with PAV groups */
        if (lcu->pav == NO_PAV) {
@@ -386,25 +400,25 @@ static int _add_device_to_lcu(struct alias_lcu *lcu,
                return 0;
        }
 
-       group = _find_group(lcu, uid);
+       group = _find_group(lcu, &uid);
        if (!group) {
                group = kzalloc(sizeof(*group), GFP_ATOMIC);
                if (!group)
                        return -ENOMEM;
-               memcpy(group->uid.vendor, uid->vendor, sizeof(uid->vendor));
-               memcpy(group->uid.serial, uid->serial, sizeof(uid->serial));
-               group->uid.ssid = uid->ssid;
-               if (uid->type == UA_BASE_DEVICE)
-                       group->uid.base_unit_addr = uid->real_unit_addr;
+               memcpy(group->uid.vendor, uid.vendor, sizeof(uid.vendor));
+               memcpy(group->uid.serial, uid.serial, sizeof(uid.serial));
+               group->uid.ssid = uid.ssid;
+               if (uid.type == UA_BASE_DEVICE)
+                       group->uid.base_unit_addr = uid.real_unit_addr;
                else
-                       group->uid.base_unit_addr = uid->base_unit_addr;
-               memcpy(group->uid.vduit, uid->vduit, sizeof(uid->vduit));
+                       group->uid.base_unit_addr = uid.base_unit_addr;
+               memcpy(group->uid.vduit, uid.vduit, sizeof(uid.vduit));
                INIT_LIST_HEAD(&group->group);
                INIT_LIST_HEAD(&group->baselist);
                INIT_LIST_HEAD(&group->aliaslist);
                list_add(&group->group, &lcu->grouplist);
        }
-       if (uid->type == UA_BASE_DEVICE)
+       if (uid.type == UA_BASE_DEVICE)
                list_move(&device->alias_list, &group->baselist);
        else
                list_move(&device->alias_list, &group->aliaslist);
@@ -525,7 +539,10 @@ static int _lcu_update(struct dasd_device *refdev, struct alias_lcu *lcu)
        if (rc)
                return rc;
 
-       spin_lock_irqsave(&lcu->lock, flags);
+       /* need to take cdev lock before lcu lock */
+       spin_lock_irqsave_nested(get_ccwdev_lock(refdev->cdev), flags,
+                                CDEV_NESTED_FIRST);
+       spin_lock(&lcu->lock);
        lcu->pav = NO_PAV;
        for (i = 0; i < MAX_DEVICES_PER_LCU; ++i) {
                switch (lcu->uac->unit[i].ua_type) {
@@ -542,9 +559,10 @@ static int _lcu_update(struct dasd_device *refdev, struct alias_lcu *lcu)
 
        list_for_each_entry_safe(device, tempdev, &lcu->active_devices,
                                 alias_list) {
-               _add_device_to_lcu(lcu, device);
+               _add_device_to_lcu(lcu, device, refdev);
        }
-       spin_unlock_irqrestore(&lcu->lock, flags);
+       spin_unlock(&lcu->lock);
+       spin_unlock_irqrestore(get_ccwdev_lock(refdev->cdev), flags);
        return 0;
 }
 
@@ -628,9 +646,12 @@ int dasd_alias_add_device(struct dasd_device *device)
        private = (struct dasd_eckd_private *) device->private;
        lcu = private->lcu;
        rc = 0;
-       spin_lock_irqsave(&lcu->lock, flags);
+
+       /* need to take cdev lock before lcu lock */
+       spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags);
+       spin_lock(&lcu->lock);
        if (!(lcu->flags & UPDATE_PENDING)) {
-               rc = _add_device_to_lcu(lcu, device);
+               rc = _add_device_to_lcu(lcu, device, device);
                if (rc)
                        lcu->flags |= UPDATE_PENDING;
        }
@@ -638,7 +659,8 @@ int dasd_alias_add_device(struct dasd_device *device)
                list_move(&device->alias_list, &lcu->active_devices);
                _schedule_lcu_update(lcu, device);
        }
-       spin_unlock_irqrestore(&lcu->lock, flags);
+       spin_unlock(&lcu->lock);
+       spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags);
        return rc;
 }
 
@@ -748,19 +770,30 @@ static void _restart_all_base_devices_on_lcu(struct alias_lcu *lcu)
        struct alias_pav_group *pavgroup;
        struct dasd_device *device;
        struct dasd_eckd_private *private;
+       unsigned long flags;
 
        /* active and inactive list can contain alias as well as base devices */
        list_for_each_entry(device, &lcu->active_devices, alias_list) {
                private = (struct dasd_eckd_private *) device->private;
-               if (private->uid.type != UA_BASE_DEVICE)
+               spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags);
+               if (private->uid.type != UA_BASE_DEVICE) {
+                       spin_unlock_irqrestore(get_ccwdev_lock(device->cdev),
+                                              flags);
                        continue;
+               }
+               spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags);
                dasd_schedule_block_bh(device->block);
                dasd_schedule_device_bh(device);
        }
        list_for_each_entry(device, &lcu->inactive_devices, alias_list) {
                private = (struct dasd_eckd_private *) device->private;
-               if (private->uid.type != UA_BASE_DEVICE)
+               spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags);
+               if (private->uid.type != UA_BASE_DEVICE) {
+                       spin_unlock_irqrestore(get_ccwdev_lock(device->cdev),
+                                              flags);
                        continue;
+               }
+               spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags);
                dasd_schedule_block_bh(device->block);
                dasd_schedule_device_bh(device);
        }
index eff9c81..34d51dd 100644 (file)
@@ -49,7 +49,6 @@ struct dasd_devmap {
         unsigned int devindex;
         unsigned short features;
        struct dasd_device *device;
-       struct dasd_uid uid;
 };
 
 /*
@@ -936,42 +935,46 @@ dasd_device_status_show(struct device *dev, struct device_attribute *attr,
 
 static DEVICE_ATTR(status, 0444, dasd_device_status_show, NULL);
 
-static ssize_t
-dasd_alias_show(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t dasd_alias_show(struct device *dev,
+                              struct device_attribute *attr, char *buf)
 {
-       struct dasd_devmap *devmap;
-       int alias;
+       struct dasd_device *device;
+       struct dasd_uid uid;
 
-       devmap = dasd_find_busid(dev_name(dev));
-       spin_lock(&dasd_devmap_lock);
-       if (IS_ERR(devmap) || strlen(devmap->uid.vendor) == 0) {
-               spin_unlock(&dasd_devmap_lock);
+       device = dasd_device_from_cdev(to_ccwdev(dev));
+       if (IS_ERR(device))
                return sprintf(buf, "0\n");
+
+       if (device->discipline && device->discipline->get_uid &&
+           !device->discipline->get_uid(device, &uid)) {
+               if (uid.type == UA_BASE_PAV_ALIAS ||
+                   uid.type == UA_HYPER_PAV_ALIAS)
+                       return sprintf(buf, "1\n");
        }
-       if (devmap->uid.type == UA_BASE_PAV_ALIAS ||
-           devmap->uid.type == UA_HYPER_PAV_ALIAS)
-               alias = 1;
-       else
-               alias = 0;
-       spin_unlock(&dasd_devmap_lock);
-       return sprintf(buf, alias ? "1\n" : "0\n");
+       dasd_put_device(device);
+
+       return sprintf(buf, "0\n");
 }
 
 static DEVICE_ATTR(alias, 0444, dasd_alias_show, NULL);
 
-static ssize_t
-dasd_vendor_show(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t dasd_vendor_show(struct device *dev,
+                               struct device_attribute *attr, char *buf)
 {
-       struct dasd_devmap *devmap;
+       struct dasd_device *device;
+       struct dasd_uid uid;
        char *vendor;
 
-       devmap = dasd_find_busid(dev_name(dev));
-       spin_lock(&dasd_devmap_lock);
-       if (!IS_ERR(devmap) && strlen(devmap->uid.vendor) > 0)
-               vendor = devmap->uid.vendor;
-       else
-               vendor = "";
-       spin_unlock(&dasd_devmap_lock);
+       device = dasd_device_from_cdev(to_ccwdev(dev));
+       vendor = "";
+       if (IS_ERR(device))
+               return snprintf(buf, PAGE_SIZE, "%s\n", vendor);
+
+       if (device->discipline && device->discipline->get_uid &&
+           !device->discipline->get_uid(device, &uid))
+                       vendor = uid.vendor;
+
+       dasd_put_device(device);
 
        return snprintf(buf, PAGE_SIZE, "%s\n", vendor);
 }
@@ -985,48 +988,51 @@ static DEVICE_ATTR(vendor, 0444, dasd_vendor_show, NULL);
 static ssize_t
 dasd_uid_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
-       struct dasd_devmap *devmap;
+       struct dasd_device *device;
+       struct dasd_uid uid;
        char uid_string[UID_STRLEN];
        char ua_string[3];
-       struct dasd_uid *uid;
 
-       devmap = dasd_find_busid(dev_name(dev));
-       spin_lock(&dasd_devmap_lock);
-       if (IS_ERR(devmap) || strlen(devmap->uid.vendor) == 0) {
-               spin_unlock(&dasd_devmap_lock);
-               return sprintf(buf, "\n");
-       }
-       uid = &devmap->uid;
-       switch (uid->type) {
-       case UA_BASE_DEVICE:
-               sprintf(ua_string, "%02x", uid->real_unit_addr);
-               break;
-       case UA_BASE_PAV_ALIAS:
-               sprintf(ua_string, "%02x", uid->base_unit_addr);
-               break;
-       case UA_HYPER_PAV_ALIAS:
-               sprintf(ua_string, "xx");
-               break;
-       default:
-               /* should not happen, treat like base device */
-               sprintf(ua_string, "%02x", uid->real_unit_addr);
-               break;
+       device = dasd_device_from_cdev(to_ccwdev(dev));
+       uid_string[0] = 0;
+       if (IS_ERR(device))
+               return snprintf(buf, PAGE_SIZE, "%s\n", uid_string);
+
+       if (device->discipline && device->discipline->get_uid &&
+           !device->discipline->get_uid(device, &uid)) {
+               switch (uid.type) {
+               case UA_BASE_DEVICE:
+                       snprintf(ua_string, sizeof(ua_string), "%02x",
+                                uid.real_unit_addr);
+                       break;
+               case UA_BASE_PAV_ALIAS:
+                       snprintf(ua_string, sizeof(ua_string), "%02x",
+                                uid.base_unit_addr);
+                       break;
+               case UA_HYPER_PAV_ALIAS:
+                       snprintf(ua_string, sizeof(ua_string), "xx");
+                       break;
+               default:
+                       /* should not happen, treat like base device */
+                       snprintf(ua_string, sizeof(ua_string), "%02x",
+                                uid.real_unit_addr);
+                       break;
+               }
+
+               if (strlen(uid.vduit) > 0)
+                       snprintf(uid_string, sizeof(uid_string),
+                                "%s.%s.%04x.%s.%s",
+                                uid.vendor, uid.serial, uid.ssid, ua_string,
+                                uid.vduit);
+               else
+                       snprintf(uid_string, sizeof(uid_string),
+                                "%s.%s.%04x.%s",
+                                uid.vendor, uid.serial, uid.ssid, ua_string);
        }
-       if (strlen(uid->vduit) > 0)
-               snprintf(uid_string, sizeof(uid_string),
-                        "%s.%s.%04x.%s.%s",
-                        uid->vendor, uid->serial,
-                        uid->ssid, ua_string,
-                        uid->vduit);
-       else
-               snprintf(uid_string, sizeof(uid_string),
-                        "%s.%s.%04x.%s",
-                        uid->vendor, uid->serial,
-                        uid->ssid, ua_string);
-       spin_unlock(&dasd_devmap_lock);
+       dasd_put_device(device);
+
        return snprintf(buf, PAGE_SIZE, "%s\n", uid_string);
 }
-
 static DEVICE_ATTR(uid, 0444, dasd_uid_show, NULL);
 
 /*
@@ -1094,50 +1100,6 @@ static struct attribute_group dasd_attr_group = {
 };
 
 /*
- * Return copy of the device unique identifier.
- */
-int
-dasd_get_uid(struct ccw_device *cdev, struct dasd_uid *uid)
-{
-       struct dasd_devmap *devmap;
-
-       devmap = dasd_find_busid(dev_name(&cdev->dev));
-       if (IS_ERR(devmap))
-               return PTR_ERR(devmap);
-       spin_lock(&dasd_devmap_lock);
-       *uid = devmap->uid;
-       spin_unlock(&dasd_devmap_lock);
-       return 0;
-}
-EXPORT_SYMBOL_GPL(dasd_get_uid);
-
-/*
- * Register the given device unique identifier into devmap struct.
- * In addition check if the related storage server subsystem ID is already
- * contained in the dasd_server_ssid_list. If subsystem ID is not contained,
- * create new entry.
- * Return 0 if server was already in serverlist,
- *       1 if the server was added successful
- *      <0 in case of error.
- */
-int
-dasd_set_uid(struct ccw_device *cdev, struct dasd_uid *uid)
-{
-       struct dasd_devmap *devmap;
-
-       devmap = dasd_find_busid(dev_name(&cdev->dev));
-       if (IS_ERR(devmap))
-               return PTR_ERR(devmap);
-
-       spin_lock(&dasd_devmap_lock);
-       devmap->uid = *uid;
-       spin_unlock(&dasd_devmap_lock);
-
-       return 0;
-}
-EXPORT_SYMBOL_GPL(dasd_set_uid);
-
-/*
  * Return value of the specified feature.
  */
 int
index 4305c23..5b1cd8d 100644 (file)
@@ -692,18 +692,20 @@ dasd_eckd_cdl_reclen(int recid)
 /*
  * Generate device unique id that specifies the physical device.
  */
-static int dasd_eckd_generate_uid(struct dasd_device *device,
-                                 struct dasd_uid *uid)
+static int dasd_eckd_generate_uid(struct dasd_device *device)
 {
        struct dasd_eckd_private *private;
+       struct dasd_uid *uid;
        int count;
+       unsigned long flags;
 
        private = (struct dasd_eckd_private *) device->private;
        if (!private)
                return -ENODEV;
        if (!private->ned || !private->gneq)
                return -ENODEV;
-
+       uid = &private->uid;
+       spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags);
        memset(uid, 0, sizeof(struct dasd_uid));
        memcpy(uid->vendor, private->ned->HDA_manufacturer,
               sizeof(uid->vendor) - 1);
@@ -726,9 +728,25 @@ static int dasd_eckd_generate_uid(struct dasd_device *device,
                                private->vdsneq->uit[count]);
                }
        }
+       spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags);
        return 0;
 }
 
+static int dasd_eckd_get_uid(struct dasd_device *device, struct dasd_uid *uid)
+{
+       struct dasd_eckd_private *private;
+       unsigned long flags;
+
+       if (device->private) {
+               private = (struct dasd_eckd_private *)device->private;
+               spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags);
+               *uid = private->uid;
+               spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags);
+               return 0;
+       }
+       return -EINVAL;
+}
+
 static struct dasd_ccw_req *dasd_eckd_build_rcd_lpm(struct dasd_device *device,
                                                    void *rcd_buffer,
                                                    struct ciw *ciw, __u8 lpm)
@@ -1088,6 +1106,7 @@ dasd_eckd_check_characteristics(struct dasd_device *device)
 {
        struct dasd_eckd_private *private;
        struct dasd_block *block;
+       struct dasd_uid temp_uid;
        int is_known, rc;
        int readonly;
 
@@ -1124,13 +1143,13 @@ dasd_eckd_check_characteristics(struct dasd_device *device)
        if (rc)
                goto out_err1;
 
-       /* Generate device unique id and register in devmap */
-       rc = dasd_eckd_generate_uid(device, &private->uid);
+       /* Generate device unique id */
+       rc = dasd_eckd_generate_uid(device);
        if (rc)
                goto out_err1;
-       dasd_set_uid(device->cdev, &private->uid);
 
-       if (private->uid.type == UA_BASE_DEVICE) {
+       dasd_eckd_get_uid(device, &temp_uid);
+       if (temp_uid.type == UA_BASE_DEVICE) {
                block = dasd_alloc_block();
                if (IS_ERR(block)) {
                        DBF_EVENT_DEVID(DBF_WARNING, device->cdev, "%s",
@@ -3305,15 +3324,16 @@ static int dasd_eckd_restore_device(struct dasd_device *device)
        if (rc)
                goto out_err;
 
-       /* Generate device unique id and register in devmap */
-       rc = dasd_eckd_generate_uid(device, &private->uid);
-       dasd_get_uid(device->cdev, &temp_uid);
+       dasd_eckd_get_uid(device, &temp_uid);
+       /* Generate device unique id */
+       rc = dasd_eckd_generate_uid(device);
+       spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags);
        if (memcmp(&private->uid, &temp_uid, sizeof(struct dasd_uid)) != 0)
                dev_err(&device->cdev->dev, "The UID of the DASD has "
                        "changed\n");
+       spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags);
        if (rc)
                goto out_err;
-       dasd_set_uid(device->cdev, &private->uid);
 
        /* register lcu with alias handling, enable PAV if this is a new lcu */
        is_known = dasd_alias_make_device_known_to_lcu(device);
@@ -3358,42 +3378,45 @@ static int dasd_eckd_reload_device(struct dasd_device *device)
 {
        struct dasd_eckd_private *private;
        int rc, old_base;
-       char uid[60];
+       char print_uid[60];
+       struct dasd_uid uid;
+       unsigned long flags;
 
        private = (struct dasd_eckd_private *) device->private;
+
+       spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags);
        old_base = private->uid.base_unit_addr;
+       spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags);
+
        /* Read Configuration Data */
        rc = dasd_eckd_read_conf(device);
        if (rc)
                goto out_err;
 
-       rc = dasd_eckd_generate_uid(device, &private->uid);
+       rc = dasd_eckd_generate_uid(device);
        if (rc)
                goto out_err;
-
-       dasd_set_uid(device->cdev, &private->uid);
-
        /*
         * update unit address configuration and
         * add device to alias management
         */
        dasd_alias_update_add_device(device);
 
-       if (old_base != private->uid.base_unit_addr) {
-               if (strlen(private->uid.vduit) > 0)
-                       snprintf(uid, 60, "%s.%s.%04x.%02x.%s",
-                                private->uid.vendor, private->uid.serial,
-                                private->uid.ssid, private->uid.base_unit_addr,
-                                private->uid.vduit);
+       dasd_eckd_get_uid(device, &uid);
+
+       if (old_base != uid.base_unit_addr) {
+               if (strlen(uid.vduit) > 0)
+                       snprintf(print_uid, sizeof(print_uid),
+                                "%s.%s.%04x.%02x.%s", uid.vendor, uid.serial,
+                                uid.ssid, uid.base_unit_addr, uid.vduit);
                else
-                       snprintf(uid, 60, "%s.%s.%04x.%02x",
-                                private->uid.vendor, private->uid.serial,
-                                private->uid.ssid,
-                                private->uid.base_unit_addr);
+                       snprintf(print_uid, sizeof(print_uid),
+                                "%s.%s.%04x.%02x", uid.vendor, uid.serial,
+                                uid.ssid, uid.base_unit_addr);
 
                dev_info(&device->cdev->dev,
                         "An Alias device was reassigned to a new base device "
-                        "with UID: %s\n", uid);
+                        "with UID: %s\n", print_uid);
        }
        return 0;
 
@@ -3455,6 +3478,7 @@ static struct dasd_discipline dasd_eckd_discipline = {
        .freeze = dasd_eckd_pm_freeze,
        .restore = dasd_eckd_restore_device,
        .reload = dasd_eckd_reload_device,
+       .get_uid = dasd_eckd_get_uid,
 };
 
 static int __init
index 1ae7b12..32fac18 100644 (file)
@@ -81,6 +81,10 @@ struct dasd_block;
 #define DASD_SIM_MSG_TO_OP 0x03
 #define DASD_SIM_LOG 0x0C
 
+/* lock class for nested cdev lock */
+#define CDEV_NESTED_FIRST 1
+#define CDEV_NESTED_SECOND 2
+
 /*
  * SECTION: MACROs for klogd and s390 debug feature (dbf)
  */
@@ -229,6 +233,24 @@ struct dasd_ccw_req {
 typedef struct dasd_ccw_req *(*dasd_erp_fn_t) (struct dasd_ccw_req *);
 
 /*
+ * Unique identifier for dasd device.
+ */
+#define UA_NOT_CONFIGURED  0x00
+#define UA_BASE_DEVICE    0x01
+#define UA_BASE_PAV_ALIAS  0x02
+#define UA_HYPER_PAV_ALIAS 0x03
+
+struct dasd_uid {
+       __u8 type;
+       char vendor[4];
+       char serial[15];
+       __u16 ssid;
+       __u8 real_unit_addr;
+       __u8 base_unit_addr;
+       char vduit[33];
+};
+
+/*
  * the struct dasd_discipline is
  * sth like a table of virtual functions, if you think of dasd_eckd
  * inheriting dasd...
@@ -315,29 +337,13 @@ struct dasd_discipline {
 
        /* reload device after state change */
        int (*reload) (struct dasd_device *);
+
+       int (*get_uid) (struct dasd_device *, struct dasd_uid *);
 };
 
 extern struct dasd_discipline *dasd_diag_discipline_pointer;
 
 /*
- * Unique identifier for dasd device.
- */
-#define UA_NOT_CONFIGURED  0x00
-#define UA_BASE_DEVICE    0x01
-#define UA_BASE_PAV_ALIAS  0x02
-#define UA_HYPER_PAV_ALIAS 0x03
-
-struct dasd_uid {
-       __u8 type;
-       char vendor[4];
-       char serial[15];
-       __u16 ssid;
-       __u8 real_unit_addr;
-       __u8 base_unit_addr;
-       char vduit[33];
-};
-
-/*
  * Notification numbers for extended error reporting notifications:
  * The DASD_EER_DISABLE notification is sent before a dasd_device (and it's
  * eer pointer) is freed. The error reporting module needs to do all necessary
@@ -634,8 +640,6 @@ void dasd_devmap_exit(void);
 struct dasd_device *dasd_create_device(struct ccw_device *);
 void dasd_delete_device(struct dasd_device *);
 
-int dasd_get_uid(struct ccw_device *, struct dasd_uid *);
-int dasd_set_uid(struct ccw_device *, struct dasd_uid *);
 int dasd_get_feature(struct ccw_device *, int);
 int dasd_set_feature(struct ccw_device *, int, int);