Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2dedf0d9 authored by Stefan Haberland's avatar Stefan Haberland Committed by Martin Schwidefsky
Browse files

[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: default avatarStefan Haberland <stefan.haberland@de.ibm.com>
Signed-off-by: default avatarHeiko Carstens <heiko.carstens@de.ibm.com>
Signed-off-by: default avatarMartin Schwidefsky <schwidefsky@de.ibm.com>
parent 501183f2
Loading
Loading
Loading
Loading
+75 −42
Original line number Original line Diff line number Diff line
@@ -190,20 +190,21 @@ int dasd_alias_make_device_known_to_lcu(struct dasd_device *device)
	struct alias_server *server, *newserver;
	struct alias_server *server, *newserver;
	struct alias_lcu *lcu, *newlcu;
	struct alias_lcu *lcu, *newlcu;
	int is_lcu_known;
	int is_lcu_known;
	struct dasd_uid *uid;
	struct dasd_uid uid;


	private = (struct dasd_eckd_private *) device->private;
	private = (struct dasd_eckd_private *) device->private;
	uid = &private->uid;

	device->discipline->get_uid(device, &uid);
	spin_lock_irqsave(&aliastree.lock, flags);
	spin_lock_irqsave(&aliastree.lock, flags);
	is_lcu_known = 1;
	is_lcu_known = 1;
	server = _find_server(uid);
	server = _find_server(&uid);
	if (!server) {
	if (!server) {
		spin_unlock_irqrestore(&aliastree.lock, flags);
		spin_unlock_irqrestore(&aliastree.lock, flags);
		newserver = _allocate_server(uid);
		newserver = _allocate_server(&uid);
		if (IS_ERR(newserver))
		if (IS_ERR(newserver))
			return PTR_ERR(newserver);
			return PTR_ERR(newserver);
		spin_lock_irqsave(&aliastree.lock, flags);
		spin_lock_irqsave(&aliastree.lock, flags);
		server = _find_server(uid);
		server = _find_server(&uid);
		if (!server) {
		if (!server) {
			list_add(&newserver->server, &aliastree.serverlist);
			list_add(&newserver->server, &aliastree.serverlist);
			server = newserver;
			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) {
	if (!lcu) {
		spin_unlock_irqrestore(&aliastree.lock, flags);
		spin_unlock_irqrestore(&aliastree.lock, flags);
		newlcu = _allocate_lcu(uid);
		newlcu = _allocate_lcu(&uid);
		if (IS_ERR(newlcu))
		if (IS_ERR(newlcu))
			return PTR_ERR(newlcu);
			return PTR_ERR(newlcu);
		spin_lock_irqsave(&aliastree.lock, flags);
		spin_lock_irqsave(&aliastree.lock, flags);
		lcu = _find_lcu(server, uid);
		lcu = _find_lcu(server, &uid);
		if (!lcu) {
		if (!lcu) {
			list_add(&newlcu->lcu, &server->lculist);
			list_add(&newlcu->lcu, &server->lculist);
			lcu = newlcu;
			lcu = newlcu;
@@ -256,20 +257,20 @@ void dasd_alias_lcu_setup_complete(struct dasd_device *device)
	unsigned long flags;
	unsigned long flags;
	struct alias_server *server;
	struct alias_server *server;
	struct alias_lcu *lcu;
	struct alias_lcu *lcu;
	struct dasd_uid *uid;
	struct dasd_uid uid;


	private = (struct dasd_eckd_private *) device->private;
	private = (struct dasd_eckd_private *) device->private;
	uid = &private->uid;
	device->discipline->get_uid(device, &uid);
	lcu = NULL;
	lcu = NULL;
	spin_lock_irqsave(&aliastree.lock, flags);
	spin_lock_irqsave(&aliastree.lock, flags);
	server = _find_server(uid);
	server = _find_server(&uid);
	if (server)
	if (server)
		lcu = _find_lcu(server, uid);
		lcu = _find_lcu(server, &uid);
	spin_unlock_irqrestore(&aliastree.lock, flags);
	spin_unlock_irqrestore(&aliastree.lock, flags);
	if (!lcu) {
	if (!lcu) {
		DBF_EVENT_DEVID(DBF_ERR, device->cdev,
		DBF_EVENT_DEVID(DBF_ERR, device->cdev,
				"could not find lcu for %04x %02x",
				"could not find lcu for %04x %02x",
				uid->ssid, uid->real_unit_addr);
				uid.ssid, uid.real_unit_addr);
		WARN_ON(1);
		WARN_ON(1);
		return;
		return;
	}
	}
@@ -282,20 +283,20 @@ void dasd_alias_wait_for_lcu_setup(struct dasd_device *device)
	unsigned long flags;
	unsigned long flags;
	struct alias_server *server;
	struct alias_server *server;
	struct alias_lcu *lcu;
	struct alias_lcu *lcu;
	struct dasd_uid *uid;
	struct dasd_uid uid;


	private = (struct dasd_eckd_private *) device->private;
	private = (struct dasd_eckd_private *) device->private;
	uid = &private->uid;
	device->discipline->get_uid(device, &uid);
	lcu = NULL;
	lcu = NULL;
	spin_lock_irqsave(&aliastree.lock, flags);
	spin_lock_irqsave(&aliastree.lock, flags);
	server = _find_server(uid);
	server = _find_server(&uid);
	if (server)
	if (server)
		lcu = _find_lcu(server, uid);
		lcu = _find_lcu(server, &uid);
	spin_unlock_irqrestore(&aliastree.lock, flags);
	spin_unlock_irqrestore(&aliastree.lock, flags);
	if (!lcu) {
	if (!lcu) {
		DBF_EVENT_DEVID(DBF_ERR, device->cdev,
		DBF_EVENT_DEVID(DBF_ERR, device->cdev,
				"could not find lcu for %04x %02x",
				"could not find lcu for %04x %02x",
				uid->ssid, uid->real_unit_addr);
				uid.ssid, uid.real_unit_addr);
		WARN_ON(1);
		WARN_ON(1);
		return;
		return;
	}
	}
@@ -314,9 +315,11 @@ void dasd_alias_disconnect_device_from_lcu(struct dasd_device *device)
	struct alias_lcu *lcu;
	struct alias_lcu *lcu;
	struct alias_server *server;
	struct alias_server *server;
	int was_pending;
	int was_pending;
	struct dasd_uid uid;


	private = (struct dasd_eckd_private *) device->private;
	private = (struct dasd_eckd_private *) device->private;
	lcu = private->lcu;
	lcu = private->lcu;
	device->discipline->get_uid(device, &uid);
	spin_lock_irqsave(&lcu->lock, flags);
	spin_lock_irqsave(&lcu->lock, flags);
	list_del_init(&device->alias_list);
	list_del_init(&device->alias_list);
	/* make sure that the workers don't use this device */
	/* 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);
			_schedule_lcu_update(lcu, NULL);
		spin_unlock(&lcu->lock);
		spin_unlock(&lcu->lock);
	}
	}
	server = _find_server(&private->uid);
	server = _find_server(&uid);
	if (server && list_empty(&server->lculist)) {
	if (server && list_empty(&server->lculist)) {
		list_del(&server->server);
		list_del(&server->server);
		_free_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
 * in the lcu is up to date and will update the device uid before
 * adding it to a pav group.
 * adding it to a pav group.
 */
 */

static int _add_device_to_lcu(struct alias_lcu *lcu,
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 dasd_eckd_private *private;
	struct alias_pav_group *group;
	struct alias_pav_group *group;
	struct dasd_uid *uid;
	struct dasd_uid uid;
	unsigned long flags;


	private = (struct dasd_eckd_private *) device->private;
	private = (struct dasd_eckd_private *) device->private;
	uid = &private->uid;

	uid->type = lcu->uac->unit[uid->real_unit_addr].ua_type;
	/* only lock if not already locked */
	uid->base_unit_addr = lcu->uac->unit[uid->real_unit_addr].base_ua;
	if (device != pos)
	dasd_set_uid(device->cdev, &private->uid);
		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 we have no PAV anyway, we don't need to bother with PAV groups */
	if (lcu->pav == NO_PAV) {
	if (lcu->pav == NO_PAV) {
@@ -386,25 +400,25 @@ static int _add_device_to_lcu(struct alias_lcu *lcu,
		return 0;
		return 0;
	}
	}


	group = _find_group(lcu, uid);
	group = _find_group(lcu, &uid);
	if (!group) {
	if (!group) {
		group = kzalloc(sizeof(*group), GFP_ATOMIC);
		group = kzalloc(sizeof(*group), GFP_ATOMIC);
		if (!group)
		if (!group)
			return -ENOMEM;
			return -ENOMEM;
		memcpy(group->uid.vendor, uid->vendor, sizeof(uid->vendor));
		memcpy(group->uid.vendor, uid.vendor, sizeof(uid.vendor));
		memcpy(group->uid.serial, uid->serial, sizeof(uid->serial));
		memcpy(group->uid.serial, uid.serial, sizeof(uid.serial));
		group->uid.ssid = uid->ssid;
		group->uid.ssid = uid.ssid;
		if (uid->type == UA_BASE_DEVICE)
		if (uid.type == UA_BASE_DEVICE)
			group->uid.base_unit_addr = uid->real_unit_addr;
			group->uid.base_unit_addr = uid.real_unit_addr;
		else
		else
			group->uid.base_unit_addr = uid->base_unit_addr;
			group->uid.base_unit_addr = uid.base_unit_addr;
		memcpy(group->uid.vduit, uid->vduit, sizeof(uid->vduit));
		memcpy(group->uid.vduit, uid.vduit, sizeof(uid.vduit));
		INIT_LIST_HEAD(&group->group);
		INIT_LIST_HEAD(&group->group);
		INIT_LIST_HEAD(&group->baselist);
		INIT_LIST_HEAD(&group->baselist);
		INIT_LIST_HEAD(&group->aliaslist);
		INIT_LIST_HEAD(&group->aliaslist);
		list_add(&group->group, &lcu->grouplist);
		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);
		list_move(&device->alias_list, &group->baselist);
	else
	else
		list_move(&device->alias_list, &group->aliaslist);
		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)
	if (rc)
		return 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;
	lcu->pav = NO_PAV;
	for (i = 0; i < MAX_DEVICES_PER_LCU; ++i) {
	for (i = 0; i < MAX_DEVICES_PER_LCU; ++i) {
		switch (lcu->uac->unit[i].ua_type) {
		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,
	list_for_each_entry_safe(device, tempdev, &lcu->active_devices,
				 alias_list) {
				 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;
	return 0;
}
}


@@ -628,9 +646,12 @@ int dasd_alias_add_device(struct dasd_device *device)
	private = (struct dasd_eckd_private *) device->private;
	private = (struct dasd_eckd_private *) device->private;
	lcu = private->lcu;
	lcu = private->lcu;
	rc = 0;
	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)) {
	if (!(lcu->flags & UPDATE_PENDING)) {
		rc = _add_device_to_lcu(lcu, device);
		rc = _add_device_to_lcu(lcu, device, device);
		if (rc)
		if (rc)
			lcu->flags |= UPDATE_PENDING;
			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);
		list_move(&device->alias_list, &lcu->active_devices);
		_schedule_lcu_update(lcu, device);
		_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;
	return rc;
}
}


@@ -748,19 +770,30 @@ static void _restart_all_base_devices_on_lcu(struct alias_lcu *lcu)
	struct alias_pav_group *pavgroup;
	struct alias_pav_group *pavgroup;
	struct dasd_device *device;
	struct dasd_device *device;
	struct dasd_eckd_private *private;
	struct dasd_eckd_private *private;
	unsigned long flags;


	/* active and inactive list can contain alias as well as base devices */
	/* active and inactive list can contain alias as well as base devices */
	list_for_each_entry(device, &lcu->active_devices, alias_list) {
	list_for_each_entry(device, &lcu->active_devices, alias_list) {
		private = (struct dasd_eckd_private *) device->private;
		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;
			continue;
		}
		spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags);
		dasd_schedule_block_bh(device->block);
		dasd_schedule_block_bh(device->block);
		dasd_schedule_device_bh(device);
		dasd_schedule_device_bh(device);
	}
	}
	list_for_each_entry(device, &lcu->inactive_devices, alias_list) {
	list_for_each_entry(device, &lcu->inactive_devices, alias_list) {
		private = (struct dasd_eckd_private *) device->private;
		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;
			continue;
		}
		spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags);
		dasd_schedule_block_bh(device->block);
		dasd_schedule_block_bh(device->block);
		dasd_schedule_device_bh(device);
		dasd_schedule_device_bh(device);
	}
	}
+68 −106
Original line number Original line Diff line number Diff line
@@ -49,7 +49,6 @@ struct dasd_devmap {
        unsigned int devindex;
        unsigned int devindex;
        unsigned short features;
        unsigned short features;
	struct dasd_device *device;
	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 DEVICE_ATTR(status, 0444, dasd_device_status_show, NULL);


static ssize_t
static ssize_t dasd_alias_show(struct device *dev,
dasd_alias_show(struct device *dev, struct device_attribute *attr, char *buf)
			       struct device_attribute *attr, char *buf)
{
{
	struct dasd_devmap *devmap;
	struct dasd_device *device;
	int alias;
	struct dasd_uid uid;


	devmap = dasd_find_busid(dev_name(dev));
	device = dasd_device_from_cdev(to_ccwdev(dev));
	spin_lock(&dasd_devmap_lock);
	if (IS_ERR(device))
	if (IS_ERR(devmap) || strlen(devmap->uid.vendor) == 0) {
		spin_unlock(&dasd_devmap_lock);
		return sprintf(buf, "0\n");
		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 ||
	dasd_put_device(device);
	    devmap->uid.type == UA_HYPER_PAV_ALIAS)

		alias = 1;
	return sprintf(buf, "0\n");
	else
		alias = 0;
	spin_unlock(&dasd_devmap_lock);
	return sprintf(buf, alias ? "1\n" : "0\n");
}
}


static DEVICE_ATTR(alias, 0444, dasd_alias_show, NULL);
static DEVICE_ATTR(alias, 0444, dasd_alias_show, NULL);


static ssize_t
static ssize_t dasd_vendor_show(struct device *dev,
dasd_vendor_show(struct device *dev, struct device_attribute *attr, char *buf)
				struct device_attribute *attr, char *buf)
{
{
	struct dasd_devmap *devmap;
	struct dasd_device *device;
	struct dasd_uid uid;
	char *vendor;
	char *vendor;


	devmap = dasd_find_busid(dev_name(dev));
	device = dasd_device_from_cdev(to_ccwdev(dev));
	spin_lock(&dasd_devmap_lock);
	if (!IS_ERR(devmap) && strlen(devmap->uid.vendor) > 0)
		vendor = devmap->uid.vendor;
	else
	vendor = "";
	vendor = "";
	spin_unlock(&dasd_devmap_lock);
	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);
	return snprintf(buf, PAGE_SIZE, "%s\n", vendor);
}
}
@@ -985,48 +988,51 @@ static DEVICE_ATTR(vendor, 0444, dasd_vendor_show, NULL);
static ssize_t
static ssize_t
dasd_uid_show(struct device *dev, struct device_attribute *attr, char *buf)
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 uid_string[UID_STRLEN];
	char ua_string[3];
	char ua_string[3];
	struct dasd_uid *uid;


	devmap = dasd_find_busid(dev_name(dev));
	device = dasd_device_from_cdev(to_ccwdev(dev));
	spin_lock(&dasd_devmap_lock);
	uid_string[0] = 0;
	if (IS_ERR(devmap) || strlen(devmap->uid.vendor) == 0) {
	if (IS_ERR(device))
		spin_unlock(&dasd_devmap_lock);
		return snprintf(buf, PAGE_SIZE, "%s\n", uid_string);
		return sprintf(buf, "\n");

	}
	if (device->discipline && device->discipline->get_uid &&
	uid = &devmap->uid;
	    !device->discipline->get_uid(device, &uid)) {
	switch (uid->type) {
		switch (uid.type) {
		case UA_BASE_DEVICE:
		case UA_BASE_DEVICE:
		sprintf(ua_string, "%02x", uid->real_unit_addr);
			snprintf(ua_string, sizeof(ua_string), "%02x",
				 uid.real_unit_addr);
			break;
			break;
		case UA_BASE_PAV_ALIAS:
		case UA_BASE_PAV_ALIAS:
		sprintf(ua_string, "%02x", uid->base_unit_addr);
			snprintf(ua_string, sizeof(ua_string), "%02x",
				 uid.base_unit_addr);
			break;
			break;
		case UA_HYPER_PAV_ALIAS:
		case UA_HYPER_PAV_ALIAS:
		sprintf(ua_string, "xx");
			snprintf(ua_string, sizeof(ua_string), "xx");
			break;
			break;
		default:
		default:
			/* should not happen, treat like base device */
			/* should not happen, treat like base device */
		sprintf(ua_string, "%02x", uid->real_unit_addr);
			snprintf(ua_string, sizeof(ua_string), "%02x",
				 uid.real_unit_addr);
			break;
			break;
		}
		}
	if (strlen(uid->vduit) > 0)

		if (strlen(uid.vduit) > 0)
			snprintf(uid_string, sizeof(uid_string),
			snprintf(uid_string, sizeof(uid_string),
				 "%s.%s.%04x.%s.%s",
				 "%s.%s.%04x.%s.%s",
			 uid->vendor, uid->serial,
				 uid.vendor, uid.serial, uid.ssid, ua_string,
			 uid->ssid, ua_string,
				 uid.vduit);
			 uid->vduit);
		else
		else
			snprintf(uid_string, sizeof(uid_string),
			snprintf(uid_string, sizeof(uid_string),
				 "%s.%s.%04x.%s",
				 "%s.%s.%04x.%s",
			 uid->vendor, uid->serial,
				 uid.vendor, uid.serial, uid.ssid, ua_string);
			 uid->ssid, ua_string);
	spin_unlock(&dasd_devmap_lock);
	return snprintf(buf, PAGE_SIZE, "%s\n", uid_string);
	}
	}
	dasd_put_device(device);


	return snprintf(buf, PAGE_SIZE, "%s\n", uid_string);
}
static DEVICE_ATTR(uid, 0444, dasd_uid_show, NULL);
static DEVICE_ATTR(uid, 0444, dasd_uid_show, NULL);


/*
/*
@@ -1093,50 +1099,6 @@ static struct attribute_group dasd_attr_group = {
	.attrs = dasd_attrs,
	.attrs = dasd_attrs,
};
};


/*
 * 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.
 * Return value of the specified feature.
 */
 */
+51 −27
Original line number Original line Diff line number Diff line
@@ -692,18 +692,20 @@ dasd_eckd_cdl_reclen(int recid)
/*
/*
 * Generate device unique id that specifies the physical device.
 * Generate device unique id that specifies the physical device.
 */
 */
static int dasd_eckd_generate_uid(struct dasd_device *device,
static int dasd_eckd_generate_uid(struct dasd_device *device)
				  struct dasd_uid *uid)
{
{
	struct dasd_eckd_private *private;
	struct dasd_eckd_private *private;
	struct dasd_uid *uid;
	int count;
	int count;
	unsigned long flags;


	private = (struct dasd_eckd_private *) device->private;
	private = (struct dasd_eckd_private *) device->private;
	if (!private)
	if (!private)
		return -ENODEV;
		return -ENODEV;
	if (!private->ned || !private->gneq)
	if (!private->ned || !private->gneq)
		return -ENODEV;
		return -ENODEV;

	uid = &private->uid;
	spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags);
	memset(uid, 0, sizeof(struct dasd_uid));
	memset(uid, 0, sizeof(struct dasd_uid));
	memcpy(uid->vendor, private->ned->HDA_manufacturer,
	memcpy(uid->vendor, private->ned->HDA_manufacturer,
	       sizeof(uid->vendor) - 1);
	       sizeof(uid->vendor) - 1);
@@ -726,9 +728,25 @@ static int dasd_eckd_generate_uid(struct dasd_device *device,
				private->vdsneq->uit[count]);
				private->vdsneq->uit[count]);
		}
		}
	}
	}
	spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags);
	return 0;
	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,
static struct dasd_ccw_req *dasd_eckd_build_rcd_lpm(struct dasd_device *device,
						    void *rcd_buffer,
						    void *rcd_buffer,
						    struct ciw *ciw, __u8 lpm)
						    struct ciw *ciw, __u8 lpm)
@@ -1088,6 +1106,7 @@ dasd_eckd_check_characteristics(struct dasd_device *device)
{
{
	struct dasd_eckd_private *private;
	struct dasd_eckd_private *private;
	struct dasd_block *block;
	struct dasd_block *block;
	struct dasd_uid temp_uid;
	int is_known, rc;
	int is_known, rc;
	int readonly;
	int readonly;


@@ -1124,13 +1143,13 @@ dasd_eckd_check_characteristics(struct dasd_device *device)
	if (rc)
	if (rc)
		goto out_err1;
		goto out_err1;


	/* Generate device unique id and register in devmap */
	/* Generate device unique id */
	rc = dasd_eckd_generate_uid(device, &private->uid);
	rc = dasd_eckd_generate_uid(device);
	if (rc)
	if (rc)
		goto out_err1;
		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();
		block = dasd_alloc_block();
		if (IS_ERR(block)) {
		if (IS_ERR(block)) {
			DBF_EVENT_DEVID(DBF_WARNING, device->cdev, "%s",
			DBF_EVENT_DEVID(DBF_WARNING, device->cdev, "%s",
@@ -3305,15 +3324,16 @@ static int dasd_eckd_restore_device(struct dasd_device *device)
	if (rc)
	if (rc)
		goto out_err;
		goto out_err;


	/* Generate device unique id and register in devmap */
	dasd_eckd_get_uid(device, &temp_uid);
	rc = dasd_eckd_generate_uid(device, &private->uid);
	/* Generate device unique id */
	dasd_get_uid(device->cdev, &temp_uid);
	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)
	if (memcmp(&private->uid, &temp_uid, sizeof(struct dasd_uid)) != 0)
		dev_err(&device->cdev->dev, "The UID of the DASD has "
		dev_err(&device->cdev->dev, "The UID of the DASD has "
			"changed\n");
			"changed\n");
	spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags);
	if (rc)
	if (rc)
		goto out_err;
		goto out_err;
	dasd_set_uid(device->cdev, &private->uid);


	/* register lcu with alias handling, enable PAV if this is a new lcu */
	/* register lcu with alias handling, enable PAV if this is a new lcu */
	is_known = dasd_alias_make_device_known_to_lcu(device);
	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;
	struct dasd_eckd_private *private;
	int rc, old_base;
	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;
	private = (struct dasd_eckd_private *) device->private;

	spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags);
	old_base = private->uid.base_unit_addr;
	old_base = private->uid.base_unit_addr;
	spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags);

	/* Read Configuration Data */
	/* Read Configuration Data */
	rc = dasd_eckd_read_conf(device);
	rc = dasd_eckd_read_conf(device);
	if (rc)
	if (rc)
		goto out_err;
		goto out_err;


	rc = dasd_eckd_generate_uid(device, &private->uid);
	rc = dasd_eckd_generate_uid(device);
	if (rc)
	if (rc)
		goto out_err;
		goto out_err;

	dasd_set_uid(device->cdev, &private->uid);

	/*
	/*
	 * update unit address configuration and
	 * update unit address configuration and
	 * add device to alias management
	 * add device to alias management
	 */
	 */
	dasd_alias_update_add_device(device);
	dasd_alias_update_add_device(device);


	if (old_base != private->uid.base_unit_addr) {
	dasd_eckd_get_uid(device, &uid);
		if (strlen(private->uid.vduit) > 0)

			snprintf(uid, 60, "%s.%s.%04x.%02x.%s",
	if (old_base != uid.base_unit_addr) {
				 private->uid.vendor, private->uid.serial,
		if (strlen(uid.vduit) > 0)
				 private->uid.ssid, private->uid.base_unit_addr,
			snprintf(print_uid, sizeof(print_uid),
				 private->uid.vduit);
				 "%s.%s.%04x.%02x.%s", uid.vendor, uid.serial,
				 uid.ssid, uid.base_unit_addr, uid.vduit);
		else
		else
			snprintf(uid, 60, "%s.%s.%04x.%02x",
			snprintf(print_uid, sizeof(print_uid),
				 private->uid.vendor, private->uid.serial,
				 "%s.%s.%04x.%02x", uid.vendor, uid.serial,
				 private->uid.ssid,
				 uid.ssid, uid.base_unit_addr);
				 private->uid.base_unit_addr);


		dev_info(&device->cdev->dev,
		dev_info(&device->cdev->dev,
			 "An Alias device was reassigned to a new base device "
			 "An Alias device was reassigned to a new base device "
			 "with UID: %s\n", uid);
			 "with UID: %s\n", print_uid);
	}
	}
	return 0;
	return 0;


@@ -3455,6 +3478,7 @@ static struct dasd_discipline dasd_eckd_discipline = {
	.freeze = dasd_eckd_pm_freeze,
	.freeze = dasd_eckd_pm_freeze,
	.restore = dasd_eckd_restore_device,
	.restore = dasd_eckd_restore_device,
	.reload = dasd_eckd_reload_device,
	.reload = dasd_eckd_reload_device,
	.get_uid = dasd_eckd_get_uid,
};
};


static int __init
static int __init
+24 −20
Original line number Original line Diff line number Diff line
@@ -81,6 +81,10 @@ struct dasd_block;
#define DASD_SIM_MSG_TO_OP 0x03
#define DASD_SIM_MSG_TO_OP 0x03
#define DASD_SIM_LOG 0x0C
#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)
 * SECTION: MACROs for klogd and s390 debug feature (dbf)
 */
 */
@@ -228,6 +232,24 @@ struct dasd_ccw_req {
/* Signature for error recovery functions. */
/* Signature for error recovery functions. */
typedef struct dasd_ccw_req *(*dasd_erp_fn_t) (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
 * the struct dasd_discipline is
 * sth like a table of virtual functions, if you think of dasd_eckd
 * sth like a table of virtual functions, if you think of dasd_eckd
@@ -315,28 +337,12 @@ struct dasd_discipline {


	/* reload device after state change */
	/* reload device after state change */
	int (*reload) (struct dasd_device *);
	int (*reload) (struct dasd_device *);

	int (*get_uid) (struct dasd_device *, struct dasd_uid *);
};
};


extern struct dasd_discipline *dasd_diag_discipline_pointer;
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:
 * Notification numbers for extended error reporting notifications:
 * The DASD_EER_DISABLE notification is sent before a dasd_device (and it's
 * The DASD_EER_DISABLE notification is sent before a dasd_device (and it's
@@ -634,8 +640,6 @@ void dasd_devmap_exit(void);
struct dasd_device *dasd_create_device(struct ccw_device *);
struct dasd_device *dasd_create_device(struct ccw_device *);
void dasd_delete_device(struct dasd_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_get_feature(struct ccw_device *, int);
int dasd_set_feature(struct ccw_device *, int, int);
int dasd_set_feature(struct ccw_device *, int, int);