aboutsummaryrefslogtreecommitdiffstats
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.c36
1 files changed, 26 insertions, 10 deletions
diff --git a/drivers/s390/scsi/zfcp_unit.c b/drivers/s390/scsi/zfcp_unit.c
index 3f2bff0d3aa2..1cd2b99ab256 100644
--- a/drivers/s390/scsi/zfcp_unit.c
+++ b/drivers/s390/scsi/zfcp_unit.c
@@ -104,7 +104,7 @@ static void zfcp_unit_release(struct device *dev)
104{ 104{
105 struct zfcp_unit *unit = container_of(dev, struct zfcp_unit, dev); 105 struct zfcp_unit *unit = container_of(dev, struct zfcp_unit, dev);
106 106
107 put_device(&unit->port->dev); 107 atomic_dec(&unit->port->units);
108 kfree(unit); 108 kfree(unit);
109} 109}
110 110
@@ -119,16 +119,27 @@ static void zfcp_unit_release(struct device *dev)
119int zfcp_unit_add(struct zfcp_port *port, u64 fcp_lun) 119int zfcp_unit_add(struct zfcp_port *port, u64 fcp_lun)
120{ 120{
121 struct zfcp_unit *unit; 121 struct zfcp_unit *unit;
122 int retval = 0;
123
124 mutex_lock(&zfcp_sysfs_port_units_mutex);
125 if (atomic_read(&port->units) == -1) {
126 /* port is already gone */
127 retval = -ENODEV;
128 goto out;
129 }
122 130
123 unit = zfcp_unit_find(port, fcp_lun); 131 unit = zfcp_unit_find(port, fcp_lun);
124 if (unit) { 132 if (unit) {
125 put_device(&unit->dev); 133 put_device(&unit->dev);
126 return -EEXIST; 134 retval = -EEXIST;
135 goto out;
127 } 136 }
128 137
129 unit = kzalloc(sizeof(struct zfcp_unit), GFP_KERNEL); 138 unit = kzalloc(sizeof(struct zfcp_unit), GFP_KERNEL);
130 if (!unit) 139 if (!unit) {
131 return -ENOMEM; 140 retval = -ENOMEM;
141 goto out;
142 }
132 143
133 unit->port = port; 144 unit->port = port;
134 unit->fcp_lun = fcp_lun; 145 unit->fcp_lun = fcp_lun;
@@ -139,28 +150,33 @@ int zfcp_unit_add(struct zfcp_port *port, u64 fcp_lun)
139 if (dev_set_name(&unit->dev, "0x%016llx", 150 if (dev_set_name(&unit->dev, "0x%016llx",
140 (unsigned long long) fcp_lun)) { 151 (unsigned long long) fcp_lun)) {
141 kfree(unit); 152 kfree(unit);
142 return -ENOMEM; 153 retval = -ENOMEM;
154 goto out;
143 } 155 }
144 156
145 get_device(&port->dev);
146
147 if (device_register(&unit->dev)) { 157 if (device_register(&unit->dev)) {
148 put_device(&unit->dev); 158 put_device(&unit->dev);
149 return -ENOMEM; 159 retval = -ENOMEM;
160 goto out;
150 } 161 }
151 162
152 if (sysfs_create_group(&unit->dev.kobj, &zfcp_sysfs_unit_attrs)) { 163 if (sysfs_create_group(&unit->dev.kobj, &zfcp_sysfs_unit_attrs)) {
153 device_unregister(&unit->dev); 164 device_unregister(&unit->dev);
154 return -EINVAL; 165 retval = -EINVAL;
166 goto out;
155 } 167 }
156 168
169 atomic_inc(&port->units); /* under zfcp_sysfs_port_units_mutex ! */
170
157 write_lock_irq(&port->unit_list_lock); 171 write_lock_irq(&port->unit_list_lock);
158 list_add_tail(&unit->list, &port->unit_list); 172 list_add_tail(&unit->list, &port->unit_list);
159 write_unlock_irq(&port->unit_list_lock); 173 write_unlock_irq(&port->unit_list_lock);
160 174
161 zfcp_unit_scsi_scan(unit); 175 zfcp_unit_scsi_scan(unit);
162 176
163 return 0; 177out:
178 mutex_unlock(&zfcp_sysfs_port_units_mutex);
179 return retval;
164} 180}
165 181
166/** 182/**