[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>
This commit is contained in:
parent
501183f2ed
commit
2dedf0d9ea
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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");
|
||||
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);
|
||||
|
||||
/*
|
||||
|
@ -1093,50 +1099,6 @@ static struct attribute_group dasd_attr_group = {
|
|||
.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.
|
||||
*/
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
*/
|
||||
|
@ -228,6 +232,24 @@ struct dasd_ccw_req {
|
|||
/* Signature for error recovery functions. */
|
||||
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
|
||||
|
@ -315,28 +337,12 @@ 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
|
||||
|
@ -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);
|
||||
|
||||
|
|
Loading…
Reference in New Issue