aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-10-02 22:01:32 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2012-10-02 22:01:32 -0400
commit3151367f8778a1789d6f6e6f6c642681b6cd6d64 (patch)
tree1869d5429a25abd994ae94079808b8db060ec6f3 /drivers/s390
parent16642a2e7be23bbda013fc32d8f6c68982eab603 (diff)
parentfe709ed827d370e6b0c0a9f9456da1c22bdcd118 (diff)
Merge tag 'scsi-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi
Pull first round of SCSI updates from James Bottomley: "This is a large set of updates, mostly for drivers (qla2xxx [including support for new 83xx based card], qla4xxx, mpt2sas, bfa, zfcp, hpsa, be2iscsi, isci, lpfc, ipr, ibmvfc, ibmvscsi, megaraid_sas). There's also a rework for tape adding virtually unlimited numbers of tape drives plus a set of dif fixes for sd and a fix for a live lock on hot remove of SCSI devices. This round includes a signed tag pull of isci-for-3.6 Signed-off-by: James Bottomley <JBottomley@Parallels.com>" Fix up trivial conflict in drivers/scsi/qla2xxx/qla_nx.c due to new PCI helper function use in a function that was removed by this pull. * tag 'scsi-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi: (198 commits) [SCSI] st: remove st_mutex [SCSI] sd: Ensure we correctly disable devices with unknown protection type [SCSI] hpsa: gen8plus Smart Array IDs [SCSI] qla4xxx: Update driver version to 5.03.00-k1 [SCSI] qla4xxx: Disable generating pause frames for ISP83XX [SCSI] qla4xxx: Fix double clearing of risc_intr for ISP83XX [SCSI] qla4xxx: IDC implementation for Loopback [SCSI] qla4xxx: update copyrights in LICENSE.qla4xxx [SCSI] qla4xxx: Fix panic while rmmod [SCSI] qla4xxx: Fail probe_adapter if IRQ allocation fails [SCSI] qla4xxx: Prevent MSI/MSI-X falling back to INTx for ISP82XX [SCSI] qla4xxx: Update idc reg in case of PCI AER [SCSI] qla4xxx: Fix double IDC locking in qla4_8xxx_error_recovery [SCSI] qla4xxx: Clear interrupt while unloading driver for ISP83XX [SCSI] qla4xxx: Print correct IDC version [SCSI] qla4xxx: Added new mbox cmd to pass driver version to FW [SCSI] scsi_dh_alua: Enable STPG for unavailable ports [SCSI] scsi_remove_target: fix softlockup regression on hot remove [SCSI] ibmvscsi: Fix host config length field overflow [SCSI] ibmvscsi: Remove backend abstraction ...
Diffstat (limited to 'drivers/s390')
-rw-r--r--drivers/s390/scsi/zfcp_aux.c1
-rw-r--r--drivers/s390/scsi/zfcp_ccw.c80
-rw-r--r--drivers/s390/scsi/zfcp_cfdc.c2
-rw-r--r--drivers/s390/scsi/zfcp_dbf.c22
-rw-r--r--drivers/s390/scsi/zfcp_dbf.h1
-rw-r--r--drivers/s390/scsi/zfcp_def.h2
-rw-r--r--drivers/s390/scsi/zfcp_erp.c2
-rw-r--r--drivers/s390/scsi/zfcp_ext.h4
-rw-r--r--drivers/s390/scsi/zfcp_fc.c23
-rw-r--r--drivers/s390/scsi/zfcp_fsf.c59
-rw-r--r--drivers/s390/scsi/zfcp_qdio.c16
-rw-r--r--drivers/s390/scsi/zfcp_sysfs.c18
-rw-r--r--drivers/s390/scsi/zfcp_unit.c36
13 files changed, 223 insertions, 43 deletions
diff --git a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c
index aff8621de806..f6adde44f226 100644
--- a/drivers/s390/scsi/zfcp_aux.c
+++ b/drivers/s390/scsi/zfcp_aux.c
@@ -519,6 +519,7 @@ struct zfcp_port *zfcp_port_enqueue(struct zfcp_adapter *adapter, u64 wwpn,
519 519
520 rwlock_init(&port->unit_list_lock); 520 rwlock_init(&port->unit_list_lock);
521 INIT_LIST_HEAD(&port->unit_list); 521 INIT_LIST_HEAD(&port->unit_list);
522 atomic_set(&port->units, 0);
522 523
523 INIT_WORK(&port->gid_pn_work, zfcp_fc_port_did_lookup); 524 INIT_WORK(&port->gid_pn_work, zfcp_fc_port_did_lookup);
524 INIT_WORK(&port->test_link_work, zfcp_fc_link_test_work); 525 INIT_WORK(&port->test_link_work, zfcp_fc_link_test_work);
diff --git a/drivers/s390/scsi/zfcp_ccw.c b/drivers/s390/scsi/zfcp_ccw.c
index e37f04551948..f2dd3a0a39eb 100644
--- a/drivers/s390/scsi/zfcp_ccw.c
+++ b/drivers/s390/scsi/zfcp_ccw.c
@@ -39,19 +39,25 @@ void zfcp_ccw_adapter_put(struct zfcp_adapter *adapter)
39 spin_unlock_irqrestore(&zfcp_ccw_adapter_ref_lock, flags); 39 spin_unlock_irqrestore(&zfcp_ccw_adapter_ref_lock, flags);
40} 40}
41 41
42static int zfcp_ccw_activate(struct ccw_device *cdev) 42/**
43 43 * zfcp_ccw_activate - activate adapter and wait for it to finish
44 * @cdev: pointer to belonging ccw device
45 * @clear: Status flags to clear.
46 * @tag: s390dbf trace record tag
47 */
48static int zfcp_ccw_activate(struct ccw_device *cdev, int clear, char *tag)
44{ 49{
45 struct zfcp_adapter *adapter = zfcp_ccw_adapter_by_cdev(cdev); 50 struct zfcp_adapter *adapter = zfcp_ccw_adapter_by_cdev(cdev);
46 51
47 if (!adapter) 52 if (!adapter)
48 return 0; 53 return 0;
49 54
55 zfcp_erp_clear_adapter_status(adapter, clear);
50 zfcp_erp_set_adapter_status(adapter, ZFCP_STATUS_COMMON_RUNNING); 56 zfcp_erp_set_adapter_status(adapter, ZFCP_STATUS_COMMON_RUNNING);
51 zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED, 57 zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED,
52 "ccresu2"); 58 tag);
53 zfcp_erp_wait(adapter); 59 zfcp_erp_wait(adapter);
54 flush_work(&adapter->scan_work); 60 flush_work(&adapter->scan_work); /* ok to call even if nothing queued */
55 61
56 zfcp_ccw_adapter_put(adapter); 62 zfcp_ccw_adapter_put(adapter);
57 63
@@ -164,26 +170,34 @@ static int zfcp_ccw_set_online(struct ccw_device *cdev)
164 BUG_ON(!zfcp_reqlist_isempty(adapter->req_list)); 170 BUG_ON(!zfcp_reqlist_isempty(adapter->req_list));
165 adapter->req_no = 0; 171 adapter->req_no = 0;
166 172
167 zfcp_ccw_activate(cdev); 173 zfcp_ccw_activate(cdev, 0, "ccsonl1");
174 /* scan for remote ports
175 either at the end of any successful adapter recovery
176 or only after the adapter recovery for setting a device online */
177 zfcp_fc_inverse_conditional_port_scan(adapter);
178 flush_work(&adapter->scan_work); /* ok to call even if nothing queued */
168 zfcp_ccw_adapter_put(adapter); 179 zfcp_ccw_adapter_put(adapter);
169 return 0; 180 return 0;
170} 181}
171 182
172/** 183/**
173 * zfcp_ccw_set_offline - set_offline function of zfcp driver 184 * zfcp_ccw_offline_sync - shut down adapter and wait for it to finish
174 * @cdev: pointer to belonging ccw device 185 * @cdev: pointer to belonging ccw device
186 * @set: Status flags to set.
187 * @tag: s390dbf trace record tag
175 * 188 *
176 * This function gets called by the common i/o layer and sets an adapter 189 * This function gets called by the common i/o layer and sets an adapter
177 * into state offline. 190 * into state offline.
178 */ 191 */
179static int zfcp_ccw_set_offline(struct ccw_device *cdev) 192static int zfcp_ccw_offline_sync(struct ccw_device *cdev, int set, char *tag)
180{ 193{
181 struct zfcp_adapter *adapter = zfcp_ccw_adapter_by_cdev(cdev); 194 struct zfcp_adapter *adapter = zfcp_ccw_adapter_by_cdev(cdev);
182 195
183 if (!adapter) 196 if (!adapter)
184 return 0; 197 return 0;
185 198
186 zfcp_erp_adapter_shutdown(adapter, 0, "ccsoff1"); 199 zfcp_erp_set_adapter_status(adapter, set);
200 zfcp_erp_adapter_shutdown(adapter, 0, tag);
187 zfcp_erp_wait(adapter); 201 zfcp_erp_wait(adapter);
188 202
189 zfcp_ccw_adapter_put(adapter); 203 zfcp_ccw_adapter_put(adapter);
@@ -191,6 +205,18 @@ static int zfcp_ccw_set_offline(struct ccw_device *cdev)
191} 205}
192 206
193/** 207/**
208 * zfcp_ccw_set_offline - set_offline function of zfcp driver
209 * @cdev: pointer to belonging ccw device
210 *
211 * This function gets called by the common i/o layer and sets an adapter
212 * into state offline.
213 */
214static int zfcp_ccw_set_offline(struct ccw_device *cdev)
215{
216 return zfcp_ccw_offline_sync(cdev, 0, "ccsoff1");
217}
218
219/**
194 * zfcp_ccw_notify - ccw notify function 220 * zfcp_ccw_notify - ccw notify function
195 * @cdev: pointer to belonging ccw device 221 * @cdev: pointer to belonging ccw device
196 * @event: indicates if adapter was detached or attached 222 * @event: indicates if adapter was detached or attached
@@ -207,6 +233,11 @@ static int zfcp_ccw_notify(struct ccw_device *cdev, int event)
207 233
208 switch (event) { 234 switch (event) {
209 case CIO_GONE: 235 case CIO_GONE:
236 if (atomic_read(&adapter->status) &
237 ZFCP_STATUS_ADAPTER_SUSPENDED) { /* notification ignore */
238 zfcp_dbf_hba_basic("ccnigo1", adapter);
239 break;
240 }
210 dev_warn(&cdev->dev, "The FCP device has been detached\n"); 241 dev_warn(&cdev->dev, "The FCP device has been detached\n");
211 zfcp_erp_adapter_shutdown(adapter, 0, "ccnoti1"); 242 zfcp_erp_adapter_shutdown(adapter, 0, "ccnoti1");
212 break; 243 break;
@@ -216,6 +247,11 @@ static int zfcp_ccw_notify(struct ccw_device *cdev, int event)
216 zfcp_erp_adapter_shutdown(adapter, 0, "ccnoti2"); 247 zfcp_erp_adapter_shutdown(adapter, 0, "ccnoti2");
217 break; 248 break;
218 case CIO_OPER: 249 case CIO_OPER:
250 if (atomic_read(&adapter->status) &
251 ZFCP_STATUS_ADAPTER_SUSPENDED) { /* notification ignore */
252 zfcp_dbf_hba_basic("ccniop1", adapter);
253 break;
254 }
219 dev_info(&cdev->dev, "The FCP device is operational again\n"); 255 dev_info(&cdev->dev, "The FCP device is operational again\n");
220 zfcp_erp_set_adapter_status(adapter, 256 zfcp_erp_set_adapter_status(adapter,
221 ZFCP_STATUS_COMMON_RUNNING); 257 ZFCP_STATUS_COMMON_RUNNING);
@@ -251,6 +287,28 @@ static void zfcp_ccw_shutdown(struct ccw_device *cdev)
251 zfcp_ccw_adapter_put(adapter); 287 zfcp_ccw_adapter_put(adapter);
252} 288}
253 289
290static int zfcp_ccw_suspend(struct ccw_device *cdev)
291{
292 zfcp_ccw_offline_sync(cdev, ZFCP_STATUS_ADAPTER_SUSPENDED, "ccsusp1");
293 return 0;
294}
295
296static int zfcp_ccw_thaw(struct ccw_device *cdev)
297{
298 /* trace records for thaw and final shutdown during suspend
299 can only be found in system dump until the end of suspend
300 but not after resume because it's based on the memory image
301 right after the very first suspend (freeze) callback */
302 zfcp_ccw_activate(cdev, 0, "ccthaw1");
303 return 0;
304}
305
306static int zfcp_ccw_resume(struct ccw_device *cdev)
307{
308 zfcp_ccw_activate(cdev, ZFCP_STATUS_ADAPTER_SUSPENDED, "ccresu1");
309 return 0;
310}
311
254struct ccw_driver zfcp_ccw_driver = { 312struct ccw_driver zfcp_ccw_driver = {
255 .driver = { 313 .driver = {
256 .owner = THIS_MODULE, 314 .owner = THIS_MODULE,
@@ -263,7 +321,7 @@ struct ccw_driver zfcp_ccw_driver = {
263 .set_offline = zfcp_ccw_set_offline, 321 .set_offline = zfcp_ccw_set_offline,
264 .notify = zfcp_ccw_notify, 322 .notify = zfcp_ccw_notify,
265 .shutdown = zfcp_ccw_shutdown, 323 .shutdown = zfcp_ccw_shutdown,
266 .freeze = zfcp_ccw_set_offline, 324 .freeze = zfcp_ccw_suspend,
267 .thaw = zfcp_ccw_activate, 325 .thaw = zfcp_ccw_thaw,
268 .restore = zfcp_ccw_activate, 326 .restore = zfcp_ccw_resume,
269}; 327};
diff --git a/drivers/s390/scsi/zfcp_cfdc.c b/drivers/s390/scsi/zfcp_cfdc.c
index fbd8b4db6025..49b82e46629e 100644
--- a/drivers/s390/scsi/zfcp_cfdc.c
+++ b/drivers/s390/scsi/zfcp_cfdc.c
@@ -293,7 +293,7 @@ void zfcp_cfdc_adapter_access_changed(struct zfcp_adapter *adapter)
293 } 293 }
294 read_unlock_irqrestore(&adapter->port_list_lock, flags); 294 read_unlock_irqrestore(&adapter->port_list_lock, flags);
295 295
296 shost_for_each_device(sdev, port->adapter->scsi_host) { 296 shost_for_each_device(sdev, adapter->scsi_host) {
297 zfcp_sdev = sdev_to_zfcp(sdev); 297 zfcp_sdev = sdev_to_zfcp(sdev);
298 status = atomic_read(&zfcp_sdev->status); 298 status = atomic_read(&zfcp_sdev->status);
299 if ((status & ZFCP_STATUS_COMMON_ACCESS_DENIED) || 299 if ((status & ZFCP_STATUS_COMMON_ACCESS_DENIED) ||
diff --git a/drivers/s390/scsi/zfcp_dbf.c b/drivers/s390/scsi/zfcp_dbf.c
index 3c1d22097ad0..e1a8cc2526e7 100644
--- a/drivers/s390/scsi/zfcp_dbf.c
+++ b/drivers/s390/scsi/zfcp_dbf.c
@@ -191,7 +191,7 @@ void zfcp_dbf_hba_def_err(struct zfcp_adapter *adapter, u64 req_id, u16 scount,
191 length = min((u16)sizeof(struct qdio_buffer), 191 length = min((u16)sizeof(struct qdio_buffer),
192 (u16)ZFCP_DBF_PAY_MAX_REC); 192 (u16)ZFCP_DBF_PAY_MAX_REC);
193 193
194 while ((char *)pl[payload->counter] && payload->counter < scount) { 194 while (payload->counter < scount && (char *)pl[payload->counter]) {
195 memcpy(payload->data, (char *)pl[payload->counter], length); 195 memcpy(payload->data, (char *)pl[payload->counter], length);
196 debug_event(dbf->pay, 1, payload, zfcp_dbf_plen(length)); 196 debug_event(dbf->pay, 1, payload, zfcp_dbf_plen(length));
197 payload->counter++; 197 payload->counter++;
@@ -200,6 +200,26 @@ void zfcp_dbf_hba_def_err(struct zfcp_adapter *adapter, u64 req_id, u16 scount,
200 spin_unlock_irqrestore(&dbf->pay_lock, flags); 200 spin_unlock_irqrestore(&dbf->pay_lock, flags);
201} 201}
202 202
203/**
204 * zfcp_dbf_hba_basic - trace event for basic adapter events
205 * @adapter: pointer to struct zfcp_adapter
206 */
207void zfcp_dbf_hba_basic(char *tag, struct zfcp_adapter *adapter)
208{
209 struct zfcp_dbf *dbf = adapter->dbf;
210 struct zfcp_dbf_hba *rec = &dbf->hba_buf;
211 unsigned long flags;
212
213 spin_lock_irqsave(&dbf->hba_lock, flags);
214 memset(rec, 0, sizeof(*rec));
215
216 memcpy(rec->tag, tag, ZFCP_DBF_TAG_LEN);
217 rec->id = ZFCP_DBF_HBA_BASIC;
218
219 debug_event(dbf->hba, 1, rec, sizeof(*rec));
220 spin_unlock_irqrestore(&dbf->hba_lock, flags);
221}
222
203static void zfcp_dbf_set_common(struct zfcp_dbf_rec *rec, 223static void zfcp_dbf_set_common(struct zfcp_dbf_rec *rec,
204 struct zfcp_adapter *adapter, 224 struct zfcp_adapter *adapter,
205 struct zfcp_port *port, 225 struct zfcp_port *port,
diff --git a/drivers/s390/scsi/zfcp_dbf.h b/drivers/s390/scsi/zfcp_dbf.h
index 714f087eb7a9..3ac7a4b30dd9 100644
--- a/drivers/s390/scsi/zfcp_dbf.h
+++ b/drivers/s390/scsi/zfcp_dbf.h
@@ -154,6 +154,7 @@ enum zfcp_dbf_hba_id {
154 ZFCP_DBF_HBA_RES = 1, 154 ZFCP_DBF_HBA_RES = 1,
155 ZFCP_DBF_HBA_USS = 2, 155 ZFCP_DBF_HBA_USS = 2,
156 ZFCP_DBF_HBA_BIT = 3, 156 ZFCP_DBF_HBA_BIT = 3,
157 ZFCP_DBF_HBA_BASIC = 4,
157}; 158};
158 159
159/** 160/**
diff --git a/drivers/s390/scsi/zfcp_def.h b/drivers/s390/scsi/zfcp_def.h
index 2955e1a3deaf..1305955cbf59 100644
--- a/drivers/s390/scsi/zfcp_def.h
+++ b/drivers/s390/scsi/zfcp_def.h
@@ -77,6 +77,7 @@ struct zfcp_reqlist;
77#define ZFCP_STATUS_ADAPTER_SIOSL_ISSUED 0x00000004 77#define ZFCP_STATUS_ADAPTER_SIOSL_ISSUED 0x00000004
78#define ZFCP_STATUS_ADAPTER_XCONFIG_OK 0x00000008 78#define ZFCP_STATUS_ADAPTER_XCONFIG_OK 0x00000008
79#define ZFCP_STATUS_ADAPTER_HOST_CON_INIT 0x00000010 79#define ZFCP_STATUS_ADAPTER_HOST_CON_INIT 0x00000010
80#define ZFCP_STATUS_ADAPTER_SUSPENDED 0x00000040
80#define ZFCP_STATUS_ADAPTER_ERP_PENDING 0x00000100 81#define ZFCP_STATUS_ADAPTER_ERP_PENDING 0x00000100
81#define ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED 0x00000200 82#define ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED 0x00000200
82#define ZFCP_STATUS_ADAPTER_DATA_DIV_ENABLED 0x00000400 83#define ZFCP_STATUS_ADAPTER_DATA_DIV_ENABLED 0x00000400
@@ -204,6 +205,7 @@ struct zfcp_port {
204 struct zfcp_adapter *adapter; /* adapter used to access port */ 205 struct zfcp_adapter *adapter; /* adapter used to access port */
205 struct list_head unit_list; /* head of logical unit list */ 206 struct list_head unit_list; /* head of logical unit list */
206 rwlock_t unit_list_lock; /* unit list lock */ 207 rwlock_t unit_list_lock; /* unit list lock */
208 atomic_t units; /* zfcp_unit count */
207 atomic_t status; /* status of this remote port */ 209 atomic_t status; /* status of this remote port */
208 u64 wwnn; /* WWNN if known */ 210 u64 wwnn; /* WWNN if known */
209 u64 wwpn; /* WWPN */ 211 u64 wwpn; /* WWPN */
diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c
index 92d3df6ac8ba..4133ab6e20f1 100644
--- a/drivers/s390/scsi/zfcp_erp.c
+++ b/drivers/s390/scsi/zfcp_erp.c
@@ -1230,7 +1230,7 @@ static void zfcp_erp_action_cleanup(struct zfcp_erp_action *act, int result)
1230 case ZFCP_ERP_ACTION_REOPEN_ADAPTER: 1230 case ZFCP_ERP_ACTION_REOPEN_ADAPTER:
1231 if (result == ZFCP_ERP_SUCCEEDED) { 1231 if (result == ZFCP_ERP_SUCCEEDED) {
1232 register_service_level(&adapter->service_level); 1232 register_service_level(&adapter->service_level);
1233 queue_work(adapter->work_queue, &adapter->scan_work); 1233 zfcp_fc_conditional_port_scan(adapter);
1234 queue_work(adapter->work_queue, &adapter->ns_up_work); 1234 queue_work(adapter->work_queue, &adapter->ns_up_work);
1235 } else 1235 } else
1236 unregister_service_level(&adapter->service_level); 1236 unregister_service_level(&adapter->service_level);
diff --git a/drivers/s390/scsi/zfcp_ext.h b/drivers/s390/scsi/zfcp_ext.h
index 36f422770ff5..1d3dd3f7d699 100644
--- a/drivers/s390/scsi/zfcp_ext.h
+++ b/drivers/s390/scsi/zfcp_ext.h
@@ -54,6 +54,7 @@ extern void zfcp_dbf_hba_fsf_res(char *, struct zfcp_fsf_req *);
54extern void zfcp_dbf_hba_bit_err(char *, struct zfcp_fsf_req *); 54extern void zfcp_dbf_hba_bit_err(char *, struct zfcp_fsf_req *);
55extern void zfcp_dbf_hba_berr(struct zfcp_dbf *, struct zfcp_fsf_req *); 55extern void zfcp_dbf_hba_berr(struct zfcp_dbf *, struct zfcp_fsf_req *);
56extern void zfcp_dbf_hba_def_err(struct zfcp_adapter *, u64, u16, void **); 56extern void zfcp_dbf_hba_def_err(struct zfcp_adapter *, u64, u16, void **);
57extern void zfcp_dbf_hba_basic(char *, struct zfcp_adapter *);
57extern void zfcp_dbf_san_req(char *, struct zfcp_fsf_req *, u32); 58extern void zfcp_dbf_san_req(char *, struct zfcp_fsf_req *, u32);
58extern void zfcp_dbf_san_res(char *, struct zfcp_fsf_req *); 59extern void zfcp_dbf_san_res(char *, struct zfcp_fsf_req *);
59extern void zfcp_dbf_san_in_els(char *, struct zfcp_fsf_req *); 60extern void zfcp_dbf_san_in_els(char *, struct zfcp_fsf_req *);
@@ -98,6 +99,8 @@ extern void zfcp_fc_gs_destroy(struct zfcp_adapter *);
98extern int zfcp_fc_exec_bsg_job(struct fc_bsg_job *); 99extern int zfcp_fc_exec_bsg_job(struct fc_bsg_job *);
99extern int zfcp_fc_timeout_bsg_job(struct fc_bsg_job *); 100extern int zfcp_fc_timeout_bsg_job(struct fc_bsg_job *);
100extern void zfcp_fc_sym_name_update(struct work_struct *); 101extern void zfcp_fc_sym_name_update(struct work_struct *);
102extern void zfcp_fc_conditional_port_scan(struct zfcp_adapter *);
103extern void zfcp_fc_inverse_conditional_port_scan(struct zfcp_adapter *);
101 104
102/* zfcp_fsf.c */ 105/* zfcp_fsf.c */
103extern struct kmem_cache *zfcp_fsf_qtcb_cache; 106extern struct kmem_cache *zfcp_fsf_qtcb_cache;
@@ -158,6 +161,7 @@ extern void zfcp_scsi_dif_sense_error(struct scsi_cmnd *, int);
158extern struct attribute_group zfcp_sysfs_unit_attrs; 161extern struct attribute_group zfcp_sysfs_unit_attrs;
159extern struct attribute_group zfcp_sysfs_adapter_attrs; 162extern struct attribute_group zfcp_sysfs_adapter_attrs;
160extern struct attribute_group zfcp_sysfs_port_attrs; 163extern struct attribute_group zfcp_sysfs_port_attrs;
164extern struct mutex zfcp_sysfs_port_units_mutex;
161extern struct device_attribute *zfcp_sysfs_sdev_attrs[]; 165extern struct device_attribute *zfcp_sysfs_sdev_attrs[];
162extern struct device_attribute *zfcp_sysfs_shost_attrs[]; 166extern struct device_attribute *zfcp_sysfs_shost_attrs[];
163 167
diff --git a/drivers/s390/scsi/zfcp_fc.c b/drivers/s390/scsi/zfcp_fc.c
index 88688a80b2c1..ff598cd68b2d 100644
--- a/drivers/s390/scsi/zfcp_fc.c
+++ b/drivers/s390/scsi/zfcp_fc.c
@@ -26,6 +26,27 @@ static u32 zfcp_fc_rscn_range_mask[] = {
26 [ELS_ADDR_FMT_FAB] = 0x000000, 26 [ELS_ADDR_FMT_FAB] = 0x000000,
27}; 27};
28 28
29static bool no_auto_port_rescan;
30module_param_named(no_auto_port_rescan, no_auto_port_rescan, bool, 0600);
31MODULE_PARM_DESC(no_auto_port_rescan,
32 "no automatic port_rescan (default off)");
33
34void zfcp_fc_conditional_port_scan(struct zfcp_adapter *adapter)
35{
36 if (no_auto_port_rescan)
37 return;
38
39 queue_work(adapter->work_queue, &adapter->scan_work);
40}
41
42void zfcp_fc_inverse_conditional_port_scan(struct zfcp_adapter *adapter)
43{
44 if (!no_auto_port_rescan)
45 return;
46
47 queue_work(adapter->work_queue, &adapter->scan_work);
48}
49
29/** 50/**
30 * zfcp_fc_post_event - post event to userspace via fc_transport 51 * zfcp_fc_post_event - post event to userspace via fc_transport
31 * @work: work struct with enqueued events 52 * @work: work struct with enqueued events
@@ -206,7 +227,7 @@ static void zfcp_fc_incoming_rscn(struct zfcp_fsf_req *fsf_req)
206 zfcp_fc_enqueue_event(fsf_req->adapter, FCH_EVT_RSCN, 227 zfcp_fc_enqueue_event(fsf_req->adapter, FCH_EVT_RSCN,
207 *(u32 *)page); 228 *(u32 *)page);
208 } 229 }
209 queue_work(fsf_req->adapter->work_queue, &fsf_req->adapter->scan_work); 230 zfcp_fc_conditional_port_scan(fsf_req->adapter);
210} 231}
211 232
212static void zfcp_fc_incoming_wwpn(struct zfcp_fsf_req *req, u64 wwpn) 233static void zfcp_fc_incoming_wwpn(struct zfcp_fsf_req *req, u64 wwpn)
diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c
index e1c1efc2c5a0..c96320d79fbc 100644
--- a/drivers/s390/scsi/zfcp_fsf.c
+++ b/drivers/s390/scsi/zfcp_fsf.c
@@ -219,7 +219,7 @@ static void zfcp_fsf_status_read_handler(struct zfcp_fsf_req *req)
219 return; 219 return;
220 } 220 }
221 221
222 zfcp_dbf_hba_fsf_uss("fssrh_2", req); 222 zfcp_dbf_hba_fsf_uss("fssrh_4", req);
223 223
224 switch (sr_buf->status_type) { 224 switch (sr_buf->status_type) {
225 case FSF_STATUS_READ_PORT_CLOSED: 225 case FSF_STATUS_READ_PORT_CLOSED:
@@ -257,7 +257,7 @@ static void zfcp_fsf_status_read_handler(struct zfcp_fsf_req *req)
257 if (sr_buf->status_subtype & FSF_STATUS_READ_SUB_ACT_UPDATED) 257 if (sr_buf->status_subtype & FSF_STATUS_READ_SUB_ACT_UPDATED)
258 zfcp_cfdc_adapter_access_changed(adapter); 258 zfcp_cfdc_adapter_access_changed(adapter);
259 if (sr_buf->status_subtype & FSF_STATUS_READ_SUB_INCOMING_ELS) 259 if (sr_buf->status_subtype & FSF_STATUS_READ_SUB_INCOMING_ELS)
260 queue_work(adapter->work_queue, &adapter->scan_work); 260 zfcp_fc_conditional_port_scan(adapter);
261 break; 261 break;
262 case FSF_STATUS_READ_CFDC_UPDATED: 262 case FSF_STATUS_READ_CFDC_UPDATED:
263 zfcp_cfdc_adapter_access_changed(adapter); 263 zfcp_cfdc_adapter_access_changed(adapter);
@@ -437,6 +437,34 @@ void zfcp_fsf_req_dismiss_all(struct zfcp_adapter *adapter)
437 } 437 }
438} 438}
439 439
440#define ZFCP_FSF_PORTSPEED_1GBIT (1 << 0)
441#define ZFCP_FSF_PORTSPEED_2GBIT (1 << 1)
442#define ZFCP_FSF_PORTSPEED_4GBIT (1 << 2)
443#define ZFCP_FSF_PORTSPEED_10GBIT (1 << 3)
444#define ZFCP_FSF_PORTSPEED_8GBIT (1 << 4)
445#define ZFCP_FSF_PORTSPEED_16GBIT (1 << 5)
446#define ZFCP_FSF_PORTSPEED_NOT_NEGOTIATED (1 << 15)
447
448static u32 zfcp_fsf_convert_portspeed(u32 fsf_speed)
449{
450 u32 fdmi_speed = 0;
451 if (fsf_speed & ZFCP_FSF_PORTSPEED_1GBIT)
452 fdmi_speed |= FC_PORTSPEED_1GBIT;
453 if (fsf_speed & ZFCP_FSF_PORTSPEED_2GBIT)
454 fdmi_speed |= FC_PORTSPEED_2GBIT;
455 if (fsf_speed & ZFCP_FSF_PORTSPEED_4GBIT)
456 fdmi_speed |= FC_PORTSPEED_4GBIT;
457 if (fsf_speed & ZFCP_FSF_PORTSPEED_10GBIT)
458 fdmi_speed |= FC_PORTSPEED_10GBIT;
459 if (fsf_speed & ZFCP_FSF_PORTSPEED_8GBIT)
460 fdmi_speed |= FC_PORTSPEED_8GBIT;
461 if (fsf_speed & ZFCP_FSF_PORTSPEED_16GBIT)
462 fdmi_speed |= FC_PORTSPEED_16GBIT;
463 if (fsf_speed & ZFCP_FSF_PORTSPEED_NOT_NEGOTIATED)
464 fdmi_speed |= FC_PORTSPEED_NOT_NEGOTIATED;
465 return fdmi_speed;
466}
467
440static int zfcp_fsf_exchange_config_evaluate(struct zfcp_fsf_req *req) 468static int zfcp_fsf_exchange_config_evaluate(struct zfcp_fsf_req *req)
441{ 469{
442 struct fsf_qtcb_bottom_config *bottom = &req->qtcb->bottom.config; 470 struct fsf_qtcb_bottom_config *bottom = &req->qtcb->bottom.config;
@@ -456,7 +484,8 @@ static int zfcp_fsf_exchange_config_evaluate(struct zfcp_fsf_req *req)
456 fc_host_port_name(shost) = nsp->fl_wwpn; 484 fc_host_port_name(shost) = nsp->fl_wwpn;
457 fc_host_node_name(shost) = nsp->fl_wwnn; 485 fc_host_node_name(shost) = nsp->fl_wwnn;
458 fc_host_port_id(shost) = ntoh24(bottom->s_id); 486 fc_host_port_id(shost) = ntoh24(bottom->s_id);
459 fc_host_speed(shost) = bottom->fc_link_speed; 487 fc_host_speed(shost) =
488 zfcp_fsf_convert_portspeed(bottom->fc_link_speed);
460 fc_host_supported_classes(shost) = FC_COS_CLASS2 | FC_COS_CLASS3; 489 fc_host_supported_classes(shost) = FC_COS_CLASS2 | FC_COS_CLASS3;
461 490
462 adapter->hydra_version = bottom->adapter_type; 491 adapter->hydra_version = bottom->adapter_type;
@@ -580,7 +609,8 @@ static void zfcp_fsf_exchange_port_evaluate(struct zfcp_fsf_req *req)
580 } else 609 } else
581 fc_host_permanent_port_name(shost) = fc_host_port_name(shost); 610 fc_host_permanent_port_name(shost) = fc_host_port_name(shost);
582 fc_host_maxframe_size(shost) = bottom->maximum_frame_size; 611 fc_host_maxframe_size(shost) = bottom->maximum_frame_size;
583 fc_host_supported_speeds(shost) = bottom->supported_speed; 612 fc_host_supported_speeds(shost) =
613 zfcp_fsf_convert_portspeed(bottom->supported_speed);
584 memcpy(fc_host_supported_fc4s(shost), bottom->supported_fc4_types, 614 memcpy(fc_host_supported_fc4s(shost), bottom->supported_fc4_types,
585 FC_FC4_LIST_SIZE); 615 FC_FC4_LIST_SIZE);
586 memcpy(fc_host_active_fc4s(shost), bottom->active_fc4_types, 616 memcpy(fc_host_active_fc4s(shost), bottom->active_fc4_types,
@@ -771,12 +801,14 @@ out:
771static void zfcp_fsf_abort_fcp_command_handler(struct zfcp_fsf_req *req) 801static void zfcp_fsf_abort_fcp_command_handler(struct zfcp_fsf_req *req)
772{ 802{
773 struct scsi_device *sdev = req->data; 803 struct scsi_device *sdev = req->data;
774 struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev); 804 struct zfcp_scsi_dev *zfcp_sdev;
775 union fsf_status_qual *fsq = &req->qtcb->header.fsf_status_qual; 805 union fsf_status_qual *fsq = &req->qtcb->header.fsf_status_qual;
776 806
777 if (req->status & ZFCP_STATUS_FSFREQ_ERROR) 807 if (req->status & ZFCP_STATUS_FSFREQ_ERROR)
778 return; 808 return;
779 809
810 zfcp_sdev = sdev_to_zfcp(sdev);
811
780 switch (req->qtcb->header.fsf_status) { 812 switch (req->qtcb->header.fsf_status) {
781 case FSF_PORT_HANDLE_NOT_VALID: 813 case FSF_PORT_HANDLE_NOT_VALID:
782 if (fsq->word[0] == fsq->word[1]) { 814 if (fsq->word[0] == fsq->word[1]) {
@@ -885,7 +917,7 @@ static void zfcp_fsf_send_ct_handler(struct zfcp_fsf_req *req)
885 917
886 switch (header->fsf_status) { 918 switch (header->fsf_status) {
887 case FSF_GOOD: 919 case FSF_GOOD:
888 zfcp_dbf_san_res("fsscth1", req); 920 zfcp_dbf_san_res("fsscth2", req);
889 ct->status = 0; 921 ct->status = 0;
890 break; 922 break;
891 case FSF_SERVICE_CLASS_NOT_SUPPORTED: 923 case FSF_SERVICE_CLASS_NOT_SUPPORTED:
@@ -1739,13 +1771,15 @@ static void zfcp_fsf_open_lun_handler(struct zfcp_fsf_req *req)
1739{ 1771{
1740 struct zfcp_adapter *adapter = req->adapter; 1772 struct zfcp_adapter *adapter = req->adapter;
1741 struct scsi_device *sdev = req->data; 1773 struct scsi_device *sdev = req->data;
1742 struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev); 1774 struct zfcp_scsi_dev *zfcp_sdev;
1743 struct fsf_qtcb_header *header = &req->qtcb->header; 1775 struct fsf_qtcb_header *header = &req->qtcb->header;
1744 struct fsf_qtcb_bottom_support *bottom = &req->qtcb->bottom.support; 1776 struct fsf_qtcb_bottom_support *bottom = &req->qtcb->bottom.support;
1745 1777
1746 if (req->status & ZFCP_STATUS_FSFREQ_ERROR) 1778 if (req->status & ZFCP_STATUS_FSFREQ_ERROR)
1747 return; 1779 return;
1748 1780
1781 zfcp_sdev = sdev_to_zfcp(sdev);
1782
1749 atomic_clear_mask(ZFCP_STATUS_COMMON_ACCESS_DENIED | 1783 atomic_clear_mask(ZFCP_STATUS_COMMON_ACCESS_DENIED |
1750 ZFCP_STATUS_COMMON_ACCESS_BOXED | 1784 ZFCP_STATUS_COMMON_ACCESS_BOXED |
1751 ZFCP_STATUS_LUN_SHARED | 1785 ZFCP_STATUS_LUN_SHARED |
@@ -1856,11 +1890,13 @@ out:
1856static void zfcp_fsf_close_lun_handler(struct zfcp_fsf_req *req) 1890static void zfcp_fsf_close_lun_handler(struct zfcp_fsf_req *req)
1857{ 1891{
1858 struct scsi_device *sdev = req->data; 1892 struct scsi_device *sdev = req->data;
1859 struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev); 1893 struct zfcp_scsi_dev *zfcp_sdev;
1860 1894
1861 if (req->status & ZFCP_STATUS_FSFREQ_ERROR) 1895 if (req->status & ZFCP_STATUS_FSFREQ_ERROR)
1862 return; 1896 return;
1863 1897
1898 zfcp_sdev = sdev_to_zfcp(sdev);
1899
1864 switch (req->qtcb->header.fsf_status) { 1900 switch (req->qtcb->header.fsf_status) {
1865 case FSF_PORT_HANDLE_NOT_VALID: 1901 case FSF_PORT_HANDLE_NOT_VALID:
1866 zfcp_erp_adapter_reopen(zfcp_sdev->port->adapter, 0, "fscuh_1"); 1902 zfcp_erp_adapter_reopen(zfcp_sdev->port->adapter, 0, "fscuh_1");
@@ -1950,7 +1986,7 @@ static void zfcp_fsf_req_trace(struct zfcp_fsf_req *req, struct scsi_cmnd *scsi)
1950{ 1986{
1951 struct fsf_qual_latency_info *lat_in; 1987 struct fsf_qual_latency_info *lat_in;
1952 struct latency_cont *lat = NULL; 1988 struct latency_cont *lat = NULL;
1953 struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(scsi->device); 1989 struct zfcp_scsi_dev *zfcp_sdev;
1954 struct zfcp_blk_drv_data blktrc; 1990 struct zfcp_blk_drv_data blktrc;
1955 int ticks = req->adapter->timer_ticks; 1991 int ticks = req->adapter->timer_ticks;
1956 1992
@@ -1965,6 +2001,7 @@ static void zfcp_fsf_req_trace(struct zfcp_fsf_req *req, struct scsi_cmnd *scsi)
1965 2001
1966 if (req->adapter->adapter_features & FSF_FEATURE_MEASUREMENT_DATA && 2002 if (req->adapter->adapter_features & FSF_FEATURE_MEASUREMENT_DATA &&
1967 !(req->status & ZFCP_STATUS_FSFREQ_ERROR)) { 2003 !(req->status & ZFCP_STATUS_FSFREQ_ERROR)) {
2004 zfcp_sdev = sdev_to_zfcp(scsi->device);
1968 blktrc.flags |= ZFCP_BLK_LAT_VALID; 2005 blktrc.flags |= ZFCP_BLK_LAT_VALID;
1969 blktrc.channel_lat = lat_in->channel_lat * ticks; 2006 blktrc.channel_lat = lat_in->channel_lat * ticks;
1970 blktrc.fabric_lat = lat_in->fabric_lat * ticks; 2007 blktrc.fabric_lat = lat_in->fabric_lat * ticks;
@@ -2002,12 +2039,14 @@ static void zfcp_fsf_fcp_handler_common(struct zfcp_fsf_req *req)
2002{ 2039{
2003 struct scsi_cmnd *scmnd = req->data; 2040 struct scsi_cmnd *scmnd = req->data;
2004 struct scsi_device *sdev = scmnd->device; 2041 struct scsi_device *sdev = scmnd->device;
2005 struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev); 2042 struct zfcp_scsi_dev *zfcp_sdev;
2006 struct fsf_qtcb_header *header = &req->qtcb->header; 2043 struct fsf_qtcb_header *header = &req->qtcb->header;
2007 2044
2008 if (unlikely(req->status & ZFCP_STATUS_FSFREQ_ERROR)) 2045 if (unlikely(req->status & ZFCP_STATUS_FSFREQ_ERROR))
2009 return; 2046 return;
2010 2047
2048 zfcp_sdev = sdev_to_zfcp(sdev);
2049
2011 switch (header->fsf_status) { 2050 switch (header->fsf_status) {
2012 case FSF_HANDLE_MISMATCH: 2051 case FSF_HANDLE_MISMATCH:
2013 case FSF_PORT_HANDLE_NOT_VALID: 2052 case FSF_PORT_HANDLE_NOT_VALID:
diff --git a/drivers/s390/scsi/zfcp_qdio.c b/drivers/s390/scsi/zfcp_qdio.c
index b9fffc8d94a7..50b5615848f6 100644
--- a/drivers/s390/scsi/zfcp_qdio.c
+++ b/drivers/s390/scsi/zfcp_qdio.c
@@ -102,18 +102,22 @@ static void zfcp_qdio_int_resp(struct ccw_device *cdev, unsigned int qdio_err,
102{ 102{
103 struct zfcp_qdio *qdio = (struct zfcp_qdio *) parm; 103 struct zfcp_qdio *qdio = (struct zfcp_qdio *) parm;
104 struct zfcp_adapter *adapter = qdio->adapter; 104 struct zfcp_adapter *adapter = qdio->adapter;
105 struct qdio_buffer_element *sbale;
106 int sbal_no, sbal_idx; 105 int sbal_no, sbal_idx;
107 void *pl[ZFCP_QDIO_MAX_SBALS_PER_REQ + 1];
108 u64 req_id;
109 u8 scount;
110 106
111 if (unlikely(qdio_err)) { 107 if (unlikely(qdio_err)) {
112 memset(pl, 0, ZFCP_QDIO_MAX_SBALS_PER_REQ * sizeof(void *));
113 if (zfcp_adapter_multi_buffer_active(adapter)) { 108 if (zfcp_adapter_multi_buffer_active(adapter)) {
109 void *pl[ZFCP_QDIO_MAX_SBALS_PER_REQ + 1];
110 struct qdio_buffer_element *sbale;
111 u64 req_id;
112 u8 scount;
113
114 memset(pl, 0,
115 ZFCP_QDIO_MAX_SBALS_PER_REQ * sizeof(void *));
114 sbale = qdio->res_q[idx]->element; 116 sbale = qdio->res_q[idx]->element;
115 req_id = (u64) sbale->addr; 117 req_id = (u64) sbale->addr;
116 scount = sbale->scount + 1; /* incl. signaling SBAL */ 118 scount = min(sbale->scount + 1,
119 ZFCP_QDIO_MAX_SBALS_PER_REQ + 1);
120 /* incl. signaling SBAL */
117 121
118 for (sbal_no = 0; sbal_no < scount; sbal_no++) { 122 for (sbal_no = 0; sbal_no < scount; sbal_no++) {
119 sbal_idx = (idx + sbal_no) % 123 sbal_idx = (idx + sbal_no) %
diff --git a/drivers/s390/scsi/zfcp_sysfs.c b/drivers/s390/scsi/zfcp_sysfs.c
index c66af27b230b..1e0eb089dfba 100644
--- a/drivers/s390/scsi/zfcp_sysfs.c
+++ b/drivers/s390/scsi/zfcp_sysfs.c
@@ -227,6 +227,8 @@ static ssize_t zfcp_sysfs_port_rescan_store(struct device *dev,
227static ZFCP_DEV_ATTR(adapter, port_rescan, S_IWUSR, NULL, 227static ZFCP_DEV_ATTR(adapter, port_rescan, S_IWUSR, NULL,
228 zfcp_sysfs_port_rescan_store); 228 zfcp_sysfs_port_rescan_store);
229 229
230DEFINE_MUTEX(zfcp_sysfs_port_units_mutex);
231
230static ssize_t zfcp_sysfs_port_remove_store(struct device *dev, 232static ssize_t zfcp_sysfs_port_remove_store(struct device *dev,
231 struct device_attribute *attr, 233 struct device_attribute *attr,
232 const char *buf, size_t count) 234 const char *buf, size_t count)
@@ -249,6 +251,16 @@ static ssize_t zfcp_sysfs_port_remove_store(struct device *dev,
249 else 251 else
250 retval = 0; 252 retval = 0;
251 253
254 mutex_lock(&zfcp_sysfs_port_units_mutex);
255 if (atomic_read(&port->units) > 0) {
256 retval = -EBUSY;
257 mutex_unlock(&zfcp_sysfs_port_units_mutex);
258 goto out;
259 }
260 /* port is about to be removed, so no more unit_add */
261 atomic_set(&port->units, -1);
262 mutex_unlock(&zfcp_sysfs_port_units_mutex);
263
252 write_lock_irq(&adapter->port_list_lock); 264 write_lock_irq(&adapter->port_list_lock);
253 list_del(&port->list); 265 list_del(&port->list);
254 write_unlock_irq(&adapter->port_list_lock); 266 write_unlock_irq(&adapter->port_list_lock);
@@ -289,12 +301,14 @@ static ssize_t zfcp_sysfs_unit_add_store(struct device *dev,
289{ 301{
290 struct zfcp_port *port = container_of(dev, struct zfcp_port, dev); 302 struct zfcp_port *port = container_of(dev, struct zfcp_port, dev);
291 u64 fcp_lun; 303 u64 fcp_lun;
304 int retval;
292 305
293 if (strict_strtoull(buf, 0, (unsigned long long *) &fcp_lun)) 306 if (strict_strtoull(buf, 0, (unsigned long long *) &fcp_lun))
294 return -EINVAL; 307 return -EINVAL;
295 308
296 if (zfcp_unit_add(port, fcp_lun)) 309 retval = zfcp_unit_add(port, fcp_lun);
297 return -EINVAL; 310 if (retval)
311 return retval;
298 312
299 return count; 313 return count;
300} 314}
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/**