[S390] dasd: remove uid from devmap

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>
diff --git a/drivers/s390/block/dasd_alias.c b/drivers/s390/block/dasd_alias.c
index a564b99..4155805 100644
--- a/drivers/s390/block/dasd_alias.c
+++ b/drivers/s390/block/dasd_alias.c
@@ -190,20 +190,21 @@
 	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 @@
 		}
 	}
 
-	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 @@
 	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 @@
 	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 @@
 	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 @@
 			_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 @@
  * 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 @@
 		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 @@
 	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 @@
 
 	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 @@
 	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 @@
 		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 @@
 	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);
 	}
diff --git a/drivers/s390/block/dasd_devmap.c b/drivers/s390/block/dasd_devmap.c
index eff9c81..34d51dd 100644
--- a/drivers/s390/block/dasd_devmap.c
+++ b/drivers/s390/block/dasd_devmap.c
@@ -49,7 +49,6 @@
         unsigned int devindex;
         unsigned short features;
 	struct dasd_device *device;
-	struct dasd_uid uid;
 };
 
 /*
@@ -936,42 +935,46 @@
 
 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 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");
+	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);
 	}
-	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;
-	}
-	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 @@
 };
 
 /*
- * 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
diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c
index 4305c23..5b1cd8d 100644
--- a/drivers/s390/block/dasd_eckd.c
+++ b/drivers/s390/block/dasd_eckd.c
@@ -692,18 +692,20 @@
 /*
  * 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 @@
 				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 @@
 {
 	struct dasd_eckd_private *private;
 	struct dasd_block *block;
+	struct dasd_uid temp_uid;
 	int is_known, rc;
 	int readonly;
 
@@ -1124,13 +1143,13 @@
 	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 @@
 	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 @@
 {
 	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 @@
 	.freeze = dasd_eckd_pm_freeze,
 	.restore = dasd_eckd_restore_device,
 	.reload = dasd_eckd_reload_device,
+	.get_uid = dasd_eckd_get_uid,
 };
 
 static int __init
diff --git a/drivers/s390/block/dasd_int.h b/drivers/s390/block/dasd_int.h
index 1ae7b12..32fac18 100644
--- a/drivers/s390/block/dasd_int.h
+++ b/drivers/s390/block/dasd_int.h
@@ -81,6 +81,10 @@
 #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 @@
 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 @@
 
 	/* 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 @@
 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);