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

[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
...@@ -190,20 +190,21 @@ int dasd_alias_make_device_known_to_lcu(struct dasd_device *device) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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, ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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);
} }
......
...@@ -49,7 +49,6 @@ struct dasd_devmap { ...@@ -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, ...@@ -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); vendor = "";
if (!IS_ERR(devmap) && strlen(devmap->uid.vendor) > 0) if (IS_ERR(device))
vendor = devmap->uid.vendor; return snprintf(buf, PAGE_SIZE, "%s\n", vendor);
else
vendor = ""; if (device->discipline && device->discipline->get_uid &&
spin_unlock(&dasd_devmap_lock); !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); ...@@ -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",
break; uid.real_unit_addr);
case UA_BASE_PAV_ALIAS: break;
sprintf(ua_string, "%02x", uid->base_unit_addr); case UA_BASE_PAV_ALIAS:
break; snprintf(ua_string, sizeof(ua_string), "%02x",
case UA_HYPER_PAV_ALIAS: uid.base_unit_addr);
sprintf(ua_string, "xx"); break;
break; case UA_HYPER_PAV_ALIAS:
default: snprintf(ua_string, sizeof(ua_string), "xx");
/* should not happen, treat like base device */ break;
sprintf(ua_string, "%02x", uid->real_unit_addr); default:
break; /* 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) dasd_put_device(device);
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);
return snprintf(buf, PAGE_SIZE, "%s\n", uid_string); 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 = { ...@@ -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.
*/ */
......
...@@ -692,18 +692,20 @@ dasd_eckd_cdl_reclen(int recid) ...@@ -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, ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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 = { ...@@ -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
......
...@@ -81,6 +81,10 @@ struct dasd_block; ...@@ -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 { ...@@ -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 { ...@@ -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); ...@@ -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);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment