diff options
Diffstat (limited to 'drivers/s390')
-rw-r--r-- | drivers/s390/scsi/zfcp_aux.c | 11 | ||||
-rw-r--r-- | drivers/s390/scsi/zfcp_ccw.c | 1 | ||||
-rw-r--r-- | drivers/s390/scsi/zfcp_cfdc.c | 3 | ||||
-rw-r--r-- | drivers/s390/scsi/zfcp_def.h | 2 | ||||
-rw-r--r-- | drivers/s390/scsi/zfcp_erp.c | 60 | ||||
-rw-r--r-- | drivers/s390/scsi/zfcp_ext.h | 2 | ||||
-rw-r--r-- | drivers/s390/scsi/zfcp_fc.c | 33 | ||||
-rw-r--r-- | drivers/s390/scsi/zfcp_fsf.c | 59 | ||||
-rw-r--r-- | drivers/s390/scsi/zfcp_scsi.c | 44 | ||||
-rw-r--r-- | drivers/s390/scsi/zfcp_sysfs.c | 21 |
10 files changed, 122 insertions, 114 deletions
diff --git a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c index 616c60ffcf2c..3ac27ee47396 100644 --- a/drivers/s390/scsi/zfcp_aux.c +++ b/drivers/s390/scsi/zfcp_aux.c | |||
@@ -97,9 +97,7 @@ static void __init zfcp_init_device_configure(char *busid, u64 wwpn, u64 lun) | |||
97 | ccw_device_set_online(adapter->ccw_device); | 97 | ccw_device_set_online(adapter->ccw_device); |
98 | 98 | ||
99 | zfcp_erp_wait(adapter); | 99 | zfcp_erp_wait(adapter); |
100 | wait_event(adapter->erp_done_wqh, | 100 | flush_work(&unit->scsi_work); |
101 | !(atomic_read(&unit->status) & | ||
102 | ZFCP_STATUS_UNIT_SCSI_WORK_PENDING)); | ||
103 | 101 | ||
104 | down(&zfcp_data.config_sema); | 102 | down(&zfcp_data.config_sema); |
105 | zfcp_unit_put(unit); | 103 | zfcp_unit_put(unit); |
@@ -279,6 +277,7 @@ struct zfcp_unit *zfcp_unit_enqueue(struct zfcp_port *port, u64 fcp_lun) | |||
279 | 277 | ||
280 | atomic_set(&unit->refcount, 0); | 278 | atomic_set(&unit->refcount, 0); |
281 | init_waitqueue_head(&unit->remove_wq); | 279 | init_waitqueue_head(&unit->remove_wq); |
280 | INIT_WORK(&unit->scsi_work, zfcp_scsi_scan); | ||
282 | 281 | ||
283 | unit->port = port; | 282 | unit->port = port; |
284 | unit->fcp_lun = fcp_lun; | 283 | unit->fcp_lun = fcp_lun; |
@@ -525,6 +524,8 @@ int zfcp_adapter_enqueue(struct ccw_device *ccw_device) | |||
525 | 524 | ||
526 | atomic_clear_mask(ZFCP_STATUS_COMMON_REMOVE, &adapter->status); | 525 | atomic_clear_mask(ZFCP_STATUS_COMMON_REMOVE, &adapter->status); |
527 | 526 | ||
527 | zfcp_fc_nameserver_init(adapter); | ||
528 | |||
528 | if (!zfcp_adapter_scsi_register(adapter)) | 529 | if (!zfcp_adapter_scsi_register(adapter)) |
529 | return 0; | 530 | return 0; |
530 | 531 | ||
@@ -553,7 +554,6 @@ void zfcp_adapter_dequeue(struct zfcp_adapter *adapter) | |||
553 | 554 | ||
554 | cancel_work_sync(&adapter->scan_work); | 555 | cancel_work_sync(&adapter->scan_work); |
555 | cancel_work_sync(&adapter->stat_work); | 556 | cancel_work_sync(&adapter->stat_work); |
556 | cancel_delayed_work_sync(&adapter->nsp.work); | ||
557 | zfcp_adapter_scsi_unregister(adapter); | 557 | zfcp_adapter_scsi_unregister(adapter); |
558 | sysfs_remove_group(&adapter->ccw_device->dev.kobj, | 558 | sysfs_remove_group(&adapter->ccw_device->dev.kobj, |
559 | &zfcp_sysfs_adapter_attrs); | 559 | &zfcp_sysfs_adapter_attrs); |
@@ -671,8 +671,7 @@ void zfcp_port_dequeue(struct zfcp_port *port) | |||
671 | list_del(&port->list); | 671 | list_del(&port->list); |
672 | write_unlock_irq(&zfcp_data.config_lock); | 672 | write_unlock_irq(&zfcp_data.config_lock); |
673 | if (port->rport) | 673 | if (port->rport) |
674 | fc_remote_port_delete(port->rport); | 674 | port->rport->dd_data = NULL; |
675 | port->rport = NULL; | ||
676 | zfcp_adapter_put(port->adapter); | 675 | zfcp_adapter_put(port->adapter); |
677 | sysfs_remove_group(&port->sysfs_device.kobj, &zfcp_sysfs_port_attrs); | 676 | sysfs_remove_group(&port->sysfs_device.kobj, &zfcp_sysfs_port_attrs); |
678 | device_unregister(&port->sysfs_device); | 677 | device_unregister(&port->sysfs_device); |
diff --git a/drivers/s390/scsi/zfcp_ccw.c b/drivers/s390/scsi/zfcp_ccw.c index cfb0dcb6e3ff..733fe3bf6285 100644 --- a/drivers/s390/scsi/zfcp_ccw.c +++ b/drivers/s390/scsi/zfcp_ccw.c | |||
@@ -108,7 +108,6 @@ static int zfcp_ccw_set_online(struct ccw_device *ccw_device) | |||
108 | /* initialize request counter */ | 108 | /* initialize request counter */ |
109 | BUG_ON(!zfcp_reqlist_isempty(adapter)); | 109 | BUG_ON(!zfcp_reqlist_isempty(adapter)); |
110 | adapter->req_no = 0; | 110 | adapter->req_no = 0; |
111 | zfcp_fc_nameserver_init(adapter); | ||
112 | 111 | ||
113 | zfcp_erp_modify_adapter_status(adapter, "ccsonl1", NULL, | 112 | zfcp_erp_modify_adapter_status(adapter, "ccsonl1", NULL, |
114 | ZFCP_STATUS_COMMON_RUNNING, ZFCP_SET); | 113 | ZFCP_STATUS_COMMON_RUNNING, ZFCP_SET); |
diff --git a/drivers/s390/scsi/zfcp_cfdc.c b/drivers/s390/scsi/zfcp_cfdc.c index 10cbfd172a28..8305c874e86f 100644 --- a/drivers/s390/scsi/zfcp_cfdc.c +++ b/drivers/s390/scsi/zfcp_cfdc.c | |||
@@ -4,7 +4,7 @@ | |||
4 | * Userspace interface for accessing the | 4 | * Userspace interface for accessing the |
5 | * Access Control Lists / Control File Data Channel | 5 | * Access Control Lists / Control File Data Channel |
6 | * | 6 | * |
7 | * Copyright IBM Corporation 2008 | 7 | * Copyright IBM Corporation 2008, 2009 |
8 | */ | 8 | */ |
9 | 9 | ||
10 | #define KMSG_COMPONENT "zfcp" | 10 | #define KMSG_COMPONENT "zfcp" |
@@ -197,6 +197,7 @@ static long zfcp_cfdc_dev_ioctl(struct file *file, unsigned int command, | |||
197 | retval = -ENXIO; | 197 | retval = -ENXIO; |
198 | goto free_buffer; | 198 | goto free_buffer; |
199 | } | 199 | } |
200 | zfcp_adapter_get(adapter); | ||
200 | 201 | ||
201 | retval = zfcp_cfdc_sg_setup(data->command, fsf_cfdc->sg, | 202 | retval = zfcp_cfdc_sg_setup(data->command, fsf_cfdc->sg, |
202 | data_user->control_file); | 203 | data_user->control_file); |
diff --git a/drivers/s390/scsi/zfcp_def.h b/drivers/s390/scsi/zfcp_def.h index a0318630f047..4c362a9069f0 100644 --- a/drivers/s390/scsi/zfcp_def.h +++ b/drivers/s390/scsi/zfcp_def.h | |||
@@ -255,7 +255,6 @@ enum zfcp_wka_status { | |||
255 | /* logical unit status */ | 255 | /* logical unit status */ |
256 | #define ZFCP_STATUS_UNIT_SHARED 0x00000004 | 256 | #define ZFCP_STATUS_UNIT_SHARED 0x00000004 |
257 | #define ZFCP_STATUS_UNIT_READONLY 0x00000008 | 257 | #define ZFCP_STATUS_UNIT_READONLY 0x00000008 |
258 | #define ZFCP_STATUS_UNIT_SCSI_WORK_PENDING 0x00000020 | ||
259 | 258 | ||
260 | /* FSF request status (this does not have a common part) */ | 259 | /* FSF request status (this does not have a common part) */ |
261 | #define ZFCP_STATUS_FSFREQ_TASK_MANAGEMENT 0x00000002 | 260 | #define ZFCP_STATUS_FSFREQ_TASK_MANAGEMENT 0x00000002 |
@@ -530,6 +529,7 @@ struct zfcp_unit { | |||
530 | struct zfcp_erp_action erp_action; /* pending error recovery */ | 529 | struct zfcp_erp_action erp_action; /* pending error recovery */ |
531 | atomic_t erp_counter; | 530 | atomic_t erp_counter; |
532 | struct zfcp_latencies latencies; | 531 | struct zfcp_latencies latencies; |
532 | struct work_struct scsi_work; | ||
533 | }; | 533 | }; |
534 | 534 | ||
535 | /* FSF request */ | 535 | /* FSF request */ |
diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c index 631bdb1dfd6c..fdc9b4352a64 100644 --- a/drivers/s390/scsi/zfcp_erp.c +++ b/drivers/s390/scsi/zfcp_erp.c | |||
@@ -719,6 +719,7 @@ static void zfcp_erp_adapter_strategy_close(struct zfcp_erp_action *act) | |||
719 | zfcp_qdio_close(adapter); | 719 | zfcp_qdio_close(adapter); |
720 | zfcp_fsf_req_dismiss_all(adapter); | 720 | zfcp_fsf_req_dismiss_all(adapter); |
721 | adapter->fsf_req_seq_no = 0; | 721 | adapter->fsf_req_seq_no = 0; |
722 | zfcp_fc_wka_port_force_offline(&adapter->nsp); | ||
722 | /* all ports and units are closed */ | 723 | /* all ports and units are closed */ |
723 | zfcp_erp_modify_adapter_status(adapter, "erascl1", NULL, | 724 | zfcp_erp_modify_adapter_status(adapter, "erascl1", NULL, |
724 | ZFCP_STATUS_COMMON_OPEN, ZFCP_CLEAR); | 725 | ZFCP_STATUS_COMMON_OPEN, ZFCP_CLEAR); |
@@ -1176,48 +1177,6 @@ static void zfcp_erp_action_dequeue(struct zfcp_erp_action *erp_action) | |||
1176 | } | 1177 | } |
1177 | } | 1178 | } |
1178 | 1179 | ||
1179 | struct zfcp_erp_add_work { | ||
1180 | struct zfcp_unit *unit; | ||
1181 | struct work_struct work; | ||
1182 | }; | ||
1183 | |||
1184 | static void zfcp_erp_scsi_scan(struct work_struct *work) | ||
1185 | { | ||
1186 | struct zfcp_erp_add_work *p = | ||
1187 | container_of(work, struct zfcp_erp_add_work, work); | ||
1188 | struct zfcp_unit *unit = p->unit; | ||
1189 | struct fc_rport *rport = unit->port->rport; | ||
1190 | |||
1191 | if (rport && rport->port_state == FC_PORTSTATE_ONLINE) | ||
1192 | scsi_scan_target(&rport->dev, 0, rport->scsi_target_id, | ||
1193 | scsilun_to_int((struct scsi_lun *)&unit->fcp_lun), 0); | ||
1194 | atomic_clear_mask(ZFCP_STATUS_UNIT_SCSI_WORK_PENDING, &unit->status); | ||
1195 | zfcp_unit_put(unit); | ||
1196 | wake_up(&unit->port->adapter->erp_done_wqh); | ||
1197 | kfree(p); | ||
1198 | } | ||
1199 | |||
1200 | static void zfcp_erp_schedule_work(struct zfcp_unit *unit) | ||
1201 | { | ||
1202 | struct zfcp_erp_add_work *p; | ||
1203 | |||
1204 | p = kzalloc(sizeof(*p), GFP_KERNEL); | ||
1205 | if (!p) { | ||
1206 | dev_err(&unit->port->adapter->ccw_device->dev, | ||
1207 | "Registering unit 0x%016Lx on port 0x%016Lx failed\n", | ||
1208 | (unsigned long long)unit->fcp_lun, | ||
1209 | (unsigned long long)unit->port->wwpn); | ||
1210 | return; | ||
1211 | } | ||
1212 | |||
1213 | zfcp_unit_get(unit); | ||
1214 | atomic_set_mask(ZFCP_STATUS_UNIT_SCSI_WORK_PENDING, &unit->status); | ||
1215 | INIT_WORK(&p->work, zfcp_erp_scsi_scan); | ||
1216 | p->unit = unit; | ||
1217 | if (!queue_work(zfcp_data.work_queue, &p->work)) | ||
1218 | zfcp_unit_put(unit); | ||
1219 | } | ||
1220 | |||
1221 | static void zfcp_erp_action_cleanup(struct zfcp_erp_action *act, int result) | 1180 | static void zfcp_erp_action_cleanup(struct zfcp_erp_action *act, int result) |
1222 | { | 1181 | { |
1223 | struct zfcp_adapter *adapter = act->adapter; | 1182 | struct zfcp_adapter *adapter = act->adapter; |
@@ -1226,11 +1185,11 @@ static void zfcp_erp_action_cleanup(struct zfcp_erp_action *act, int result) | |||
1226 | 1185 | ||
1227 | switch (act->action) { | 1186 | switch (act->action) { |
1228 | case ZFCP_ERP_ACTION_REOPEN_UNIT: | 1187 | case ZFCP_ERP_ACTION_REOPEN_UNIT: |
1229 | flush_work(&port->rport_work); | ||
1230 | if ((result == ZFCP_ERP_SUCCEEDED) && !unit->device) { | 1188 | if ((result == ZFCP_ERP_SUCCEEDED) && !unit->device) { |
1231 | if (!(atomic_read(&unit->status) & | 1189 | zfcp_unit_get(unit); |
1232 | ZFCP_STATUS_UNIT_SCSI_WORK_PENDING)) | 1190 | if (scsi_queue_work(unit->port->adapter->scsi_host, |
1233 | zfcp_erp_schedule_work(unit); | 1191 | &unit->scsi_work) <= 0) |
1192 | zfcp_unit_put(unit); | ||
1234 | } | 1193 | } |
1235 | zfcp_unit_put(unit); | 1194 | zfcp_unit_put(unit); |
1236 | break; | 1195 | break; |
@@ -1352,6 +1311,11 @@ static int zfcp_erp_thread(void *data) | |||
1352 | 1311 | ||
1353 | while (!(atomic_read(&adapter->status) & | 1312 | while (!(atomic_read(&adapter->status) & |
1354 | ZFCP_STATUS_ADAPTER_ERP_THREAD_KILL)) { | 1313 | ZFCP_STATUS_ADAPTER_ERP_THREAD_KILL)) { |
1314 | |||
1315 | zfcp_rec_dbf_event_thread_lock("erthrd1", adapter); | ||
1316 | ignore = down_interruptible(&adapter->erp_ready_sem); | ||
1317 | zfcp_rec_dbf_event_thread_lock("erthrd2", adapter); | ||
1318 | |||
1355 | write_lock_irqsave(&adapter->erp_lock, flags); | 1319 | write_lock_irqsave(&adapter->erp_lock, flags); |
1356 | next = adapter->erp_ready_head.next; | 1320 | next = adapter->erp_ready_head.next; |
1357 | write_unlock_irqrestore(&adapter->erp_lock, flags); | 1321 | write_unlock_irqrestore(&adapter->erp_lock, flags); |
@@ -1363,10 +1327,6 @@ static int zfcp_erp_thread(void *data) | |||
1363 | if (zfcp_erp_strategy(act) != ZFCP_ERP_DISMISSED) | 1327 | if (zfcp_erp_strategy(act) != ZFCP_ERP_DISMISSED) |
1364 | zfcp_erp_wakeup(adapter); | 1328 | zfcp_erp_wakeup(adapter); |
1365 | } | 1329 | } |
1366 | |||
1367 | zfcp_rec_dbf_event_thread_lock("erthrd1", adapter); | ||
1368 | ignore = down_interruptible(&adapter->erp_ready_sem); | ||
1369 | zfcp_rec_dbf_event_thread_lock("erthrd2", adapter); | ||
1370 | } | 1330 | } |
1371 | 1331 | ||
1372 | atomic_clear_mask(ZFCP_STATUS_ADAPTER_ERP_THREAD_UP, &adapter->status); | 1332 | atomic_clear_mask(ZFCP_STATUS_ADAPTER_ERP_THREAD_UP, &adapter->status); |
diff --git a/drivers/s390/scsi/zfcp_ext.h b/drivers/s390/scsi/zfcp_ext.h index f6399ca97bcb..2e31b536548c 100644 --- a/drivers/s390/scsi/zfcp_ext.h +++ b/drivers/s390/scsi/zfcp_ext.h | |||
@@ -106,6 +106,7 @@ extern void zfcp_fc_plogi_evaluate(struct zfcp_port *, struct fsf_plogi *); | |||
106 | extern void zfcp_test_link(struct zfcp_port *); | 106 | extern void zfcp_test_link(struct zfcp_port *); |
107 | extern void zfcp_fc_link_test_work(struct work_struct *); | 107 | extern void zfcp_fc_link_test_work(struct work_struct *); |
108 | extern void zfcp_fc_nameserver_init(struct zfcp_adapter *); | 108 | extern void zfcp_fc_nameserver_init(struct zfcp_adapter *); |
109 | extern void zfcp_fc_wka_port_force_offline(struct zfcp_wka_port *); | ||
109 | 110 | ||
110 | /* zfcp_fsf.c */ | 111 | /* zfcp_fsf.c */ |
111 | extern int zfcp_fsf_open_port(struct zfcp_erp_action *); | 112 | extern int zfcp_fsf_open_port(struct zfcp_erp_action *); |
@@ -158,6 +159,7 @@ extern void zfcp_scsi_rport_work(struct work_struct *); | |||
158 | extern void zfcp_scsi_schedule_rport_register(struct zfcp_port *); | 159 | extern void zfcp_scsi_schedule_rport_register(struct zfcp_port *); |
159 | extern void zfcp_scsi_schedule_rport_block(struct zfcp_port *); | 160 | extern void zfcp_scsi_schedule_rport_block(struct zfcp_port *); |
160 | extern void zfcp_scsi_schedule_rports_block(struct zfcp_adapter *); | 161 | extern void zfcp_scsi_schedule_rports_block(struct zfcp_adapter *); |
162 | extern void zfcp_scsi_scan(struct work_struct *); | ||
161 | 163 | ||
162 | /* zfcp_sysfs.c */ | 164 | /* zfcp_sysfs.c */ |
163 | extern struct attribute_group zfcp_sysfs_unit_attrs; | 165 | extern struct attribute_group zfcp_sysfs_unit_attrs; |
diff --git a/drivers/s390/scsi/zfcp_fc.c b/drivers/s390/scsi/zfcp_fc.c index e8d032b9dfbd..19ae0842047c 100644 --- a/drivers/s390/scsi/zfcp_fc.c +++ b/drivers/s390/scsi/zfcp_fc.c | |||
@@ -98,13 +98,6 @@ static void zfcp_wka_port_offline(struct work_struct *work) | |||
98 | struct zfcp_wka_port *wka_port = | 98 | struct zfcp_wka_port *wka_port = |
99 | container_of(dw, struct zfcp_wka_port, work); | 99 | container_of(dw, struct zfcp_wka_port, work); |
100 | 100 | ||
101 | /* Don't wait forvever. If the wka_port is too busy take it offline | ||
102 | through a new call later */ | ||
103 | if (!wait_event_timeout(wka_port->completion_wq, | ||
104 | atomic_read(&wka_port->refcount) == 0, | ||
105 | HZ >> 1)) | ||
106 | return; | ||
107 | |||
108 | mutex_lock(&wka_port->mutex); | 101 | mutex_lock(&wka_port->mutex); |
109 | if ((atomic_read(&wka_port->refcount) != 0) || | 102 | if ((atomic_read(&wka_port->refcount) != 0) || |
110 | (wka_port->status != ZFCP_WKA_PORT_ONLINE)) | 103 | (wka_port->status != ZFCP_WKA_PORT_ONLINE)) |
@@ -142,6 +135,14 @@ void zfcp_fc_nameserver_init(struct zfcp_adapter *adapter) | |||
142 | INIT_DELAYED_WORK(&wka_port->work, zfcp_wka_port_offline); | 135 | INIT_DELAYED_WORK(&wka_port->work, zfcp_wka_port_offline); |
143 | } | 136 | } |
144 | 137 | ||
138 | void zfcp_fc_wka_port_force_offline(struct zfcp_wka_port *wka) | ||
139 | { | ||
140 | cancel_delayed_work_sync(&wka->work); | ||
141 | mutex_lock(&wka->mutex); | ||
142 | wka->status = ZFCP_WKA_PORT_OFFLINE; | ||
143 | mutex_unlock(&wka->mutex); | ||
144 | } | ||
145 | |||
145 | static void _zfcp_fc_incoming_rscn(struct zfcp_fsf_req *fsf_req, u32 range, | 146 | static void _zfcp_fc_incoming_rscn(struct zfcp_fsf_req *fsf_req, u32 range, |
146 | struct fcp_rscn_element *elem) | 147 | struct fcp_rscn_element *elem) |
147 | { | 148 | { |
@@ -372,7 +373,8 @@ static void zfcp_fc_adisc_handler(unsigned long data) | |||
372 | 373 | ||
373 | if (adisc->els.status) { | 374 | if (adisc->els.status) { |
374 | /* request rejected or timed out */ | 375 | /* request rejected or timed out */ |
375 | zfcp_erp_port_forced_reopen(port, 0, "fcadh_1", NULL); | 376 | zfcp_erp_port_forced_reopen(port, ZFCP_STATUS_COMMON_ERP_FAILED, |
377 | "fcadh_1", NULL); | ||
376 | goto out; | 378 | goto out; |
377 | } | 379 | } |
378 | 380 | ||
@@ -431,11 +433,6 @@ void zfcp_fc_link_test_work(struct work_struct *work) | |||
431 | container_of(work, struct zfcp_port, test_link_work); | 433 | container_of(work, struct zfcp_port, test_link_work); |
432 | int retval; | 434 | int retval; |
433 | 435 | ||
434 | if (!(atomic_read(&port->status) & ZFCP_STATUS_COMMON_UNBLOCKED)) { | ||
435 | zfcp_port_put(port); | ||
436 | return; /* port erp is running and will update rport status */ | ||
437 | } | ||
438 | |||
439 | zfcp_port_get(port); | 436 | zfcp_port_get(port); |
440 | port->rport_task = RPORT_DEL; | 437 | port->rport_task = RPORT_DEL; |
441 | zfcp_scsi_rport_work(&port->rport_work); | 438 | zfcp_scsi_rport_work(&port->rport_work); |
@@ -542,6 +539,9 @@ static void zfcp_validate_port(struct zfcp_port *port) | |||
542 | { | 539 | { |
543 | struct zfcp_adapter *adapter = port->adapter; | 540 | struct zfcp_adapter *adapter = port->adapter; |
544 | 541 | ||
542 | if (!(atomic_read(&port->status) & ZFCP_STATUS_COMMON_NOESC)) | ||
543 | return; | ||
544 | |||
545 | atomic_clear_mask(ZFCP_STATUS_COMMON_NOESC, &port->status); | 545 | atomic_clear_mask(ZFCP_STATUS_COMMON_NOESC, &port->status); |
546 | 546 | ||
547 | if ((port->supported_classes != 0) || | 547 | if ((port->supported_classes != 0) || |
@@ -602,10 +602,8 @@ static int zfcp_scan_eval_gpn_ft(struct zfcp_gpn_ft *gpn_ft, int max_entries) | |||
602 | if (acc->wwpn == fc_host_port_name(adapter->scsi_host)) | 602 | if (acc->wwpn == fc_host_port_name(adapter->scsi_host)) |
603 | continue; | 603 | continue; |
604 | port = zfcp_get_port_by_wwpn(adapter, acc->wwpn); | 604 | port = zfcp_get_port_by_wwpn(adapter, acc->wwpn); |
605 | if (port) { | 605 | if (port) |
606 | zfcp_port_get(port); | ||
607 | continue; | 606 | continue; |
608 | } | ||
609 | 607 | ||
610 | port = zfcp_port_enqueue(adapter, acc->wwpn, | 608 | port = zfcp_port_enqueue(adapter, acc->wwpn, |
611 | ZFCP_STATUS_COMMON_NOESC, d_id); | 609 | ZFCP_STATUS_COMMON_NOESC, d_id); |
@@ -637,7 +635,8 @@ int zfcp_scan_ports(struct zfcp_adapter *adapter) | |||
637 | max_entries = chain ? ZFCP_GPN_FT_MAX_ENTRIES : ZFCP_GPN_FT_ENTRIES; | 635 | max_entries = chain ? ZFCP_GPN_FT_MAX_ENTRIES : ZFCP_GPN_FT_ENTRIES; |
638 | max_bytes = chain ? ZFCP_GPN_FT_MAX_SIZE : ZFCP_CT_SIZE_ONE_PAGE; | 636 | max_bytes = chain ? ZFCP_GPN_FT_MAX_SIZE : ZFCP_CT_SIZE_ONE_PAGE; |
639 | 637 | ||
640 | if (fc_host_port_type(adapter->scsi_host) != FC_PORTTYPE_NPORT) | 638 | if (fc_host_port_type(adapter->scsi_host) != FC_PORTTYPE_NPORT && |
639 | fc_host_port_type(adapter->scsi_host) != FC_PORTTYPE_NPIV) | ||
641 | return 0; | 640 | return 0; |
642 | 641 | ||
643 | ret = zfcp_wka_port_get(&adapter->nsp); | 642 | ret = zfcp_wka_port_get(&adapter->nsp); |
diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c index b29f3121b666..74dee32afba8 100644 --- a/drivers/s390/scsi/zfcp_fsf.c +++ b/drivers/s390/scsi/zfcp_fsf.c | |||
@@ -172,12 +172,16 @@ static void zfcp_fsf_link_down_info_eval(struct zfcp_fsf_req *req, char *id, | |||
172 | struct fsf_link_down_info *link_down) | 172 | struct fsf_link_down_info *link_down) |
173 | { | 173 | { |
174 | struct zfcp_adapter *adapter = req->adapter; | 174 | struct zfcp_adapter *adapter = req->adapter; |
175 | unsigned long flags; | ||
175 | 176 | ||
176 | if (atomic_read(&adapter->status) & ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED) | 177 | if (atomic_read(&adapter->status) & ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED) |
177 | return; | 178 | return; |
178 | 179 | ||
179 | atomic_set_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED, &adapter->status); | 180 | atomic_set_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED, &adapter->status); |
181 | |||
182 | read_lock_irqsave(&zfcp_data.config_lock, flags); | ||
180 | zfcp_scsi_schedule_rports_block(adapter); | 183 | zfcp_scsi_schedule_rports_block(adapter); |
184 | read_unlock_irqrestore(&zfcp_data.config_lock, flags); | ||
181 | 185 | ||
182 | if (!link_down) | 186 | if (!link_down) |
183 | goto out; | 187 | goto out; |
@@ -645,30 +649,30 @@ static void zfcp_fsf_exchange_port_data_handler(struct zfcp_fsf_req *req) | |||
645 | } | 649 | } |
646 | } | 650 | } |
647 | 651 | ||
648 | static int zfcp_fsf_req_sbal_get(struct zfcp_adapter *adapter) | 652 | static int zfcp_fsf_sbal_check(struct zfcp_adapter *adapter) |
649 | __releases(&adapter->req_q_lock) | ||
650 | __acquires(&adapter->req_q_lock) | ||
651 | { | 653 | { |
652 | struct zfcp_qdio_queue *req_q = &adapter->req_q; | 654 | struct zfcp_qdio_queue *req_q = &adapter->req_q; |
653 | long ret; | ||
654 | 655 | ||
655 | if (atomic_read(&req_q->count) <= -REQUEST_LIST_SIZE) | 656 | spin_lock_bh(&adapter->req_q_lock); |
656 | return -EIO; | 657 | if (atomic_read(&req_q->count)) |
657 | if (atomic_read(&req_q->count) > 0) | 658 | return 1; |
658 | return 0; | 659 | spin_unlock_bh(&adapter->req_q_lock); |
660 | return 0; | ||
661 | } | ||
662 | |||
663 | static int zfcp_fsf_req_sbal_get(struct zfcp_adapter *adapter) | ||
664 | { | ||
665 | long ret; | ||
659 | 666 | ||
660 | atomic_dec(&req_q->count); | ||
661 | spin_unlock_bh(&adapter->req_q_lock); | 667 | spin_unlock_bh(&adapter->req_q_lock); |
662 | ret = wait_event_interruptible_timeout(adapter->request_wq, | 668 | ret = wait_event_interruptible_timeout(adapter->request_wq, |
663 | atomic_read(&req_q->count) >= 0, | 669 | zfcp_fsf_sbal_check(adapter), 5 * HZ); |
664 | 5 * HZ); | ||
665 | spin_lock_bh(&adapter->req_q_lock); | ||
666 | atomic_inc(&req_q->count); | ||
667 | |||
668 | if (ret > 0) | 670 | if (ret > 0) |
669 | return 0; | 671 | return 0; |
670 | if (!ret) | 672 | if (!ret) |
671 | atomic_inc(&adapter->qdio_outb_full); | 673 | atomic_inc(&adapter->qdio_outb_full); |
674 | |||
675 | spin_lock_bh(&adapter->req_q_lock); | ||
672 | return -EIO; | 676 | return -EIO; |
673 | } | 677 | } |
674 | 678 | ||
@@ -766,8 +770,9 @@ static struct zfcp_fsf_req *zfcp_fsf_req_create(struct zfcp_adapter *adapter, | |||
766 | static int zfcp_fsf_req_send(struct zfcp_fsf_req *req) | 770 | static int zfcp_fsf_req_send(struct zfcp_fsf_req *req) |
767 | { | 771 | { |
768 | struct zfcp_adapter *adapter = req->adapter; | 772 | struct zfcp_adapter *adapter = req->adapter; |
769 | unsigned long flags; | 773 | unsigned long flags; |
770 | int idx; | 774 | int idx; |
775 | int with_qtcb = (req->qtcb != NULL); | ||
771 | 776 | ||
772 | /* put allocated FSF request into hash table */ | 777 | /* put allocated FSF request into hash table */ |
773 | spin_lock_irqsave(&adapter->req_list_lock, flags); | 778 | spin_lock_irqsave(&adapter->req_list_lock, flags); |
@@ -789,7 +794,7 @@ static int zfcp_fsf_req_send(struct zfcp_fsf_req *req) | |||
789 | } | 794 | } |
790 | 795 | ||
791 | /* Don't increase for unsolicited status */ | 796 | /* Don't increase for unsolicited status */ |
792 | if (req->qtcb) | 797 | if (with_qtcb) |
793 | adapter->fsf_req_seq_no++; | 798 | adapter->fsf_req_seq_no++; |
794 | adapter->req_no++; | 799 | adapter->req_no++; |
795 | 800 | ||
@@ -1253,13 +1258,13 @@ int zfcp_fsf_exchange_config_data_sync(struct zfcp_adapter *adapter, | |||
1253 | 1258 | ||
1254 | spin_lock_bh(&adapter->req_q_lock); | 1259 | spin_lock_bh(&adapter->req_q_lock); |
1255 | if (zfcp_fsf_req_sbal_get(adapter)) | 1260 | if (zfcp_fsf_req_sbal_get(adapter)) |
1256 | goto out; | 1261 | goto out_unlock; |
1257 | 1262 | ||
1258 | req = zfcp_fsf_req_create(adapter, FSF_QTCB_EXCHANGE_CONFIG_DATA, | 1263 | req = zfcp_fsf_req_create(adapter, FSF_QTCB_EXCHANGE_CONFIG_DATA, |
1259 | 0, NULL); | 1264 | 0, NULL); |
1260 | if (IS_ERR(req)) { | 1265 | if (IS_ERR(req)) { |
1261 | retval = PTR_ERR(req); | 1266 | retval = PTR_ERR(req); |
1262 | goto out; | 1267 | goto out_unlock; |
1263 | } | 1268 | } |
1264 | 1269 | ||
1265 | sbale = zfcp_qdio_sbale_req(req); | 1270 | sbale = zfcp_qdio_sbale_req(req); |
@@ -1278,14 +1283,16 @@ int zfcp_fsf_exchange_config_data_sync(struct zfcp_adapter *adapter, | |||
1278 | 1283 | ||
1279 | zfcp_fsf_start_timer(req, ZFCP_FSF_REQUEST_TIMEOUT); | 1284 | zfcp_fsf_start_timer(req, ZFCP_FSF_REQUEST_TIMEOUT); |
1280 | retval = zfcp_fsf_req_send(req); | 1285 | retval = zfcp_fsf_req_send(req); |
1281 | out: | ||
1282 | spin_unlock_bh(&adapter->req_q_lock); | 1286 | spin_unlock_bh(&adapter->req_q_lock); |
1283 | if (!retval) | 1287 | if (!retval) |
1284 | wait_event(req->completion_wq, | 1288 | wait_event(req->completion_wq, |
1285 | req->status & ZFCP_STATUS_FSFREQ_COMPLETED); | 1289 | req->status & ZFCP_STATUS_FSFREQ_COMPLETED); |
1286 | 1290 | ||
1287 | zfcp_fsf_req_free(req); | 1291 | zfcp_fsf_req_free(req); |
1292 | return retval; | ||
1288 | 1293 | ||
1294 | out_unlock: | ||
1295 | spin_unlock_bh(&adapter->req_q_lock); | ||
1289 | return retval; | 1296 | return retval; |
1290 | } | 1297 | } |
1291 | 1298 | ||
@@ -1352,13 +1359,13 @@ int zfcp_fsf_exchange_port_data_sync(struct zfcp_adapter *adapter, | |||
1352 | 1359 | ||
1353 | spin_lock_bh(&adapter->req_q_lock); | 1360 | spin_lock_bh(&adapter->req_q_lock); |
1354 | if (zfcp_fsf_req_sbal_get(adapter)) | 1361 | if (zfcp_fsf_req_sbal_get(adapter)) |
1355 | goto out; | 1362 | goto out_unlock; |
1356 | 1363 | ||
1357 | req = zfcp_fsf_req_create(adapter, FSF_QTCB_EXCHANGE_PORT_DATA, 0, | 1364 | req = zfcp_fsf_req_create(adapter, FSF_QTCB_EXCHANGE_PORT_DATA, 0, |
1358 | NULL); | 1365 | NULL); |
1359 | if (IS_ERR(req)) { | 1366 | if (IS_ERR(req)) { |
1360 | retval = PTR_ERR(req); | 1367 | retval = PTR_ERR(req); |
1361 | goto out; | 1368 | goto out_unlock; |
1362 | } | 1369 | } |
1363 | 1370 | ||
1364 | if (data) | 1371 | if (data) |
@@ -1371,14 +1378,18 @@ int zfcp_fsf_exchange_port_data_sync(struct zfcp_adapter *adapter, | |||
1371 | req->handler = zfcp_fsf_exchange_port_data_handler; | 1378 | req->handler = zfcp_fsf_exchange_port_data_handler; |
1372 | zfcp_fsf_start_timer(req, ZFCP_FSF_REQUEST_TIMEOUT); | 1379 | zfcp_fsf_start_timer(req, ZFCP_FSF_REQUEST_TIMEOUT); |
1373 | retval = zfcp_fsf_req_send(req); | 1380 | retval = zfcp_fsf_req_send(req); |
1374 | out: | ||
1375 | spin_unlock_bh(&adapter->req_q_lock); | 1381 | spin_unlock_bh(&adapter->req_q_lock); |
1382 | |||
1376 | if (!retval) | 1383 | if (!retval) |
1377 | wait_event(req->completion_wq, | 1384 | wait_event(req->completion_wq, |
1378 | req->status & ZFCP_STATUS_FSFREQ_COMPLETED); | 1385 | req->status & ZFCP_STATUS_FSFREQ_COMPLETED); |
1379 | zfcp_fsf_req_free(req); | 1386 | zfcp_fsf_req_free(req); |
1380 | 1387 | ||
1381 | return retval; | 1388 | return retval; |
1389 | |||
1390 | out_unlock: | ||
1391 | spin_unlock_bh(&adapter->req_q_lock); | ||
1392 | return retval; | ||
1382 | } | 1393 | } |
1383 | 1394 | ||
1384 | static void zfcp_fsf_open_port_handler(struct zfcp_fsf_req *req) | 1395 | static void zfcp_fsf_open_port_handler(struct zfcp_fsf_req *req) |
@@ -2472,8 +2483,6 @@ out: | |||
2472 | 2483 | ||
2473 | static void zfcp_fsf_control_file_handler(struct zfcp_fsf_req *req) | 2484 | static void zfcp_fsf_control_file_handler(struct zfcp_fsf_req *req) |
2474 | { | 2485 | { |
2475 | if (req->qtcb->header.fsf_status != FSF_GOOD) | ||
2476 | req->status |= ZFCP_STATUS_FSFREQ_ERROR; | ||
2477 | } | 2486 | } |
2478 | 2487 | ||
2479 | /** | 2488 | /** |
diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c index 58201e1ae478..e8fbeaeb5fbf 100644 --- a/drivers/s390/scsi/zfcp_scsi.c +++ b/drivers/s390/scsi/zfcp_scsi.c | |||
@@ -171,7 +171,7 @@ static int zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt) | |||
171 | write_unlock_irqrestore(&adapter->abort_lock, flags); | 171 | write_unlock_irqrestore(&adapter->abort_lock, flags); |
172 | zfcp_scsi_dbf_event_abort("lte1", adapter, scpnt, NULL, | 172 | zfcp_scsi_dbf_event_abort("lte1", adapter, scpnt, NULL, |
173 | old_req_id); | 173 | old_req_id); |
174 | return SUCCESS; | 174 | return FAILED; /* completion could be in progress */ |
175 | } | 175 | } |
176 | old_req->data = NULL; | 176 | old_req->data = NULL; |
177 | 177 | ||
@@ -486,10 +486,12 @@ static void zfcp_set_rport_dev_loss_tmo(struct fc_rport *rport, u32 timeout) | |||
486 | */ | 486 | */ |
487 | static void zfcp_scsi_dev_loss_tmo_callbk(struct fc_rport *rport) | 487 | static void zfcp_scsi_dev_loss_tmo_callbk(struct fc_rport *rport) |
488 | { | 488 | { |
489 | struct zfcp_port *port = rport->dd_data; | 489 | struct zfcp_port *port; |
490 | 490 | ||
491 | write_lock_irq(&zfcp_data.config_lock); | 491 | write_lock_irq(&zfcp_data.config_lock); |
492 | port->rport = NULL; | 492 | port = rport->dd_data; |
493 | if (port) | ||
494 | port->rport = NULL; | ||
493 | write_unlock_irq(&zfcp_data.config_lock); | 495 | write_unlock_irq(&zfcp_data.config_lock); |
494 | } | 496 | } |
495 | 497 | ||
@@ -503,9 +505,18 @@ static void zfcp_scsi_dev_loss_tmo_callbk(struct fc_rport *rport) | |||
503 | */ | 505 | */ |
504 | static void zfcp_scsi_terminate_rport_io(struct fc_rport *rport) | 506 | static void zfcp_scsi_terminate_rport_io(struct fc_rport *rport) |
505 | { | 507 | { |
506 | struct zfcp_port *port = rport->dd_data; | 508 | struct zfcp_port *port; |
509 | |||
510 | write_lock_irq(&zfcp_data.config_lock); | ||
511 | port = rport->dd_data; | ||
512 | if (port) | ||
513 | zfcp_port_get(port); | ||
514 | write_unlock_irq(&zfcp_data.config_lock); | ||
507 | 515 | ||
508 | zfcp_erp_port_reopen(port, 0, "sctrpi1", NULL); | 516 | if (port) { |
517 | zfcp_erp_port_reopen(port, 0, "sctrpi1", NULL); | ||
518 | zfcp_port_put(port); | ||
519 | } | ||
509 | } | 520 | } |
510 | 521 | ||
511 | static void zfcp_scsi_rport_register(struct zfcp_port *port) | 522 | static void zfcp_scsi_rport_register(struct zfcp_port *port) |
@@ -534,8 +545,10 @@ static void zfcp_scsi_rport_register(struct zfcp_port *port) | |||
534 | 545 | ||
535 | static void zfcp_scsi_rport_block(struct zfcp_port *port) | 546 | static void zfcp_scsi_rport_block(struct zfcp_port *port) |
536 | { | 547 | { |
537 | if (port->rport) | 548 | struct fc_rport *rport = port->rport; |
538 | fc_remote_port_delete(port->rport); | 549 | |
550 | if (rport) | ||
551 | fc_remote_port_delete(rport); | ||
539 | } | 552 | } |
540 | 553 | ||
541 | void zfcp_scsi_schedule_rport_register(struct zfcp_port *port) | 554 | void zfcp_scsi_schedule_rport_register(struct zfcp_port *port) |
@@ -583,6 +596,23 @@ void zfcp_scsi_rport_work(struct work_struct *work) | |||
583 | } | 596 | } |
584 | 597 | ||
585 | 598 | ||
599 | void zfcp_scsi_scan(struct work_struct *work) | ||
600 | { | ||
601 | struct zfcp_unit *unit = container_of(work, struct zfcp_unit, | ||
602 | scsi_work); | ||
603 | struct fc_rport *rport; | ||
604 | |||
605 | flush_work(&unit->port->rport_work); | ||
606 | rport = unit->port->rport; | ||
607 | |||
608 | if (rport && rport->port_state == FC_PORTSTATE_ONLINE) | ||
609 | scsi_scan_target(&rport->dev, 0, rport->scsi_target_id, | ||
610 | scsilun_to_int((struct scsi_lun *) | ||
611 | &unit->fcp_lun), 0); | ||
612 | |||
613 | zfcp_unit_put(unit); | ||
614 | } | ||
615 | |||
586 | struct fc_function_template zfcp_transport_functions = { | 616 | struct fc_function_template zfcp_transport_functions = { |
587 | .show_starget_port_id = 1, | 617 | .show_starget_port_id = 1, |
588 | .show_starget_port_name = 1, | 618 | .show_starget_port_name = 1, |
diff --git a/drivers/s390/scsi/zfcp_sysfs.c b/drivers/s390/scsi/zfcp_sysfs.c index 9a3b8e261c0a..3e51e64d1108 100644 --- a/drivers/s390/scsi/zfcp_sysfs.c +++ b/drivers/s390/scsi/zfcp_sysfs.c | |||
@@ -254,12 +254,21 @@ static ssize_t zfcp_sysfs_unit_remove_store(struct device *dev, | |||
254 | 254 | ||
255 | write_lock_irq(&zfcp_data.config_lock); | 255 | write_lock_irq(&zfcp_data.config_lock); |
256 | unit = zfcp_get_unit_by_lun(port, fcp_lun); | 256 | unit = zfcp_get_unit_by_lun(port, fcp_lun); |
257 | if (unit && (atomic_read(&unit->refcount) == 0)) { | 257 | if (unit) { |
258 | zfcp_unit_get(unit); | 258 | write_unlock_irq(&zfcp_data.config_lock); |
259 | atomic_set_mask(ZFCP_STATUS_COMMON_REMOVE, &unit->status); | 259 | /* wait for possible timeout during SCSI probe */ |
260 | list_move(&unit->list, &unit_remove_lh); | 260 | flush_work(&unit->scsi_work); |
261 | } else | 261 | write_lock_irq(&zfcp_data.config_lock); |
262 | unit = NULL; | 262 | |
263 | if (atomic_read(&unit->refcount) == 0) { | ||
264 | zfcp_unit_get(unit); | ||
265 | atomic_set_mask(ZFCP_STATUS_COMMON_REMOVE, | ||
266 | &unit->status); | ||
267 | list_move(&unit->list, &unit_remove_lh); | ||
268 | } else { | ||
269 | unit = NULL; | ||
270 | } | ||
271 | } | ||
263 | 272 | ||
264 | write_unlock_irq(&zfcp_data.config_lock); | 273 | write_unlock_irq(&zfcp_data.config_lock); |
265 | 274 | ||