[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:
committed by
Martin Schwidefsky
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_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);
|
||||||
}
|
}
|
||||||
|
@@ -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);
|
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);
|
|||||||
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 &&
|
||||||
|
!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;
|
dasd_put_device(device);
|
||||||
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);
|
|
||||||
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 = {
|
|||||||
.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)
|
|||||||
/*
|
/*
|
||||||
* 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
|
||||||
|
@@ -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);
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user