aboutsummaryrefslogtreecommitdiff
path: root/drivers/s390/scsi/zfcp_unit.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/s390/scsi/zfcp_unit.c')
-rw-r--r--drivers/s390/scsi/zfcp_unit.c41
1 files changed, 26 insertions, 15 deletions
diff --git a/drivers/s390/scsi/zfcp_unit.c b/drivers/s390/scsi/zfcp_unit.c
index 20796ebc33c..39f5446f721 100644
--- a/drivers/s390/scsi/zfcp_unit.c
+++ b/drivers/s390/scsi/zfcp_unit.c
@@ -4,7 +4,7 @@
* Tracking of manually configured LUNs and helper functions to
* register the LUNs with the SCSI midlayer.
*
- * Copyright IBM Corporation 2010
+ * Copyright IBM Corp. 2010
*/
#include "zfcp_def.h"
@@ -104,7 +104,7 @@ static void zfcp_unit_release(struct device *dev)
{
struct zfcp_unit *unit = container_of(dev, struct zfcp_unit, dev);
- put_device(&unit->port->dev);
+ atomic_dec(&unit->port->units);
kfree(unit);
}
@@ -119,40 +119,49 @@ static void zfcp_unit_release(struct device *dev)
int zfcp_unit_add(struct zfcp_port *port, u64 fcp_lun)
{
struct zfcp_unit *unit;
+ int retval = 0;
+
+ mutex_lock(&zfcp_sysfs_port_units_mutex);
+ if (atomic_read(&port->units) == -1) {
+ /* port is already gone */
+ retval = -ENODEV;
+ goto out;
+ }
unit = zfcp_unit_find(port, fcp_lun);
if (unit) {
put_device(&unit->dev);
- return -EEXIST;
+ retval = -EEXIST;
+ goto out;
}
unit = kzalloc(sizeof(struct zfcp_unit), GFP_KERNEL);
- if (!unit)
- return -ENOMEM;
+ if (!unit) {
+ retval = -ENOMEM;
+ goto out;
+ }
unit->port = port;
unit->fcp_lun = fcp_lun;
unit->dev.parent = &port->dev;
unit->dev.release = zfcp_unit_release;
+ unit->dev.groups = zfcp_unit_attr_groups;
INIT_WORK(&unit->scsi_work, zfcp_unit_scsi_scan_work);
if (dev_set_name(&unit->dev, "0x%016llx",
(unsigned long long) fcp_lun)) {
kfree(unit);
- return -ENOMEM;
+ retval = -ENOMEM;
+ goto out;
}
- get_device(&port->dev);
-
if (device_register(&unit->dev)) {
put_device(&unit->dev);
- return -ENOMEM;
+ retval = -ENOMEM;
+ goto out;
}
- if (sysfs_create_group(&unit->dev.kobj, &zfcp_sysfs_unit_attrs)) {
- device_unregister(&unit->dev);
- return -EINVAL;
- }
+ atomic_inc(&port->units); /* under zfcp_sysfs_port_units_mutex ! */
write_lock_irq(&port->unit_list_lock);
list_add_tail(&unit->list, &port->unit_list);
@@ -160,7 +169,9 @@ int zfcp_unit_add(struct zfcp_port *port, u64 fcp_lun)
zfcp_unit_scsi_scan(unit);
- return 0;
+out:
+ mutex_unlock(&zfcp_sysfs_port_units_mutex);
+ return retval;
}
/**
@@ -238,7 +249,7 @@ int zfcp_unit_remove(struct zfcp_port *port, u64 fcp_lun)
put_device(&unit->dev);
- zfcp_device_unregister(&unit->dev, &zfcp_sysfs_unit_attrs);
+ device_unregister(&unit->dev);
return 0;
}