aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390/scsi/zfcp_fc.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/s390/scsi/zfcp_fc.c')
-rw-r--r--drivers/s390/scsi/zfcp_fc.c82
1 files changed, 51 insertions, 31 deletions
diff --git a/drivers/s390/scsi/zfcp_fc.c b/drivers/s390/scsi/zfcp_fc.c
index eabdfe24456e..aab8123c5966 100644
--- a/drivers/s390/scsi/zfcp_fc.c
+++ b/drivers/s390/scsi/zfcp_fc.c
@@ -3,7 +3,7 @@
3 * 3 *
4 * Fibre Channel related functions for the zfcp device driver. 4 * Fibre Channel related functions for the zfcp device driver.
5 * 5 *
6 * Copyright IBM Corporation 2008 6 * Copyright IBM Corporation 2008, 2009
7 */ 7 */
8 8
9#define KMSG_COMPONENT "zfcp" 9#define KMSG_COMPONENT "zfcp"
@@ -98,8 +98,12 @@ 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 wait_event(wka_port->completion_wq, 101 /* Don't wait forvever. If the wka_port is too busy take it offline
102 atomic_read(&wka_port->refcount) == 0); 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;
103 107
104 mutex_lock(&wka_port->mutex); 108 mutex_lock(&wka_port->mutex);
105 if ((atomic_read(&wka_port->refcount) != 0) || 109 if ((atomic_read(&wka_port->refcount) != 0) ||
@@ -145,16 +149,10 @@ static void _zfcp_fc_incoming_rscn(struct zfcp_fsf_req *fsf_req, u32 range,
145 struct zfcp_port *port; 149 struct zfcp_port *port;
146 150
147 read_lock_irqsave(&zfcp_data.config_lock, flags); 151 read_lock_irqsave(&zfcp_data.config_lock, flags);
148 list_for_each_entry(port, &fsf_req->adapter->port_list_head, list) { 152 list_for_each_entry(port, &fsf_req->adapter->port_list_head, list)
149 if (!(atomic_read(&port->status) & ZFCP_STATUS_PORT_PHYS_OPEN)) 153 if ((port->d_id & range) == (elem->nport_did & range))
150 /* Try to connect to unused ports anyway. */
151 zfcp_erp_port_reopen(port,
152 ZFCP_STATUS_COMMON_ERP_FAILED,
153 82, fsf_req);
154 else if ((port->d_id & range) == (elem->nport_did & range))
155 /* Check connection status for connected ports */
156 zfcp_test_link(port); 154 zfcp_test_link(port);
157 } 155
158 read_unlock_irqrestore(&zfcp_data.config_lock, flags); 156 read_unlock_irqrestore(&zfcp_data.config_lock, flags);
159} 157}
160 158
@@ -196,7 +194,7 @@ static void zfcp_fc_incoming_wwpn(struct zfcp_fsf_req *req, u64 wwpn)
196 read_unlock_irqrestore(&zfcp_data.config_lock, flags); 194 read_unlock_irqrestore(&zfcp_data.config_lock, flags);
197 195
198 if (port && (port->wwpn == wwpn)) 196 if (port && (port->wwpn == wwpn))
199 zfcp_erp_port_forced_reopen(port, 0, 83, req); 197 zfcp_erp_port_forced_reopen(port, 0, "fciwwp1", req);
200} 198}
201 199
202static void zfcp_fc_incoming_plogi(struct zfcp_fsf_req *req) 200static void zfcp_fc_incoming_plogi(struct zfcp_fsf_req *req)
@@ -259,10 +257,9 @@ static void zfcp_fc_ns_gid_pn_eval(unsigned long data)
259 257
260 if (ct->status) 258 if (ct->status)
261 return; 259 return;
262 if (ct_iu_resp->header.cmd_rsp_code != ZFCP_CT_ACCEPT) { 260 if (ct_iu_resp->header.cmd_rsp_code != ZFCP_CT_ACCEPT)
263 atomic_set_mask(ZFCP_STATUS_PORT_INVALID_WWPN, &port->status);
264 return; 261 return;
265 } 262
266 /* paranoia */ 263 /* paranoia */
267 if (ct_iu_req->wwpn != port->wwpn) 264 if (ct_iu_req->wwpn != port->wwpn)
268 return; 265 return;
@@ -375,16 +372,22 @@ static void zfcp_fc_adisc_handler(unsigned long data)
375 372
376 if (adisc->els.status) { 373 if (adisc->els.status) {
377 /* request rejected or timed out */ 374 /* request rejected or timed out */
378 zfcp_erp_port_forced_reopen(port, 0, 63, NULL); 375 zfcp_erp_port_forced_reopen(port, 0, "fcadh_1", NULL);
379 goto out; 376 goto out;
380 } 377 }
381 378
382 if (!port->wwnn) 379 if (!port->wwnn)
383 port->wwnn = ls_adisc->wwnn; 380 port->wwnn = ls_adisc->wwnn;
384 381
385 if (port->wwpn != ls_adisc->wwpn) 382 if ((port->wwpn != ls_adisc->wwpn) ||
386 zfcp_erp_port_reopen(port, 0, 64, NULL); 383 !(atomic_read(&port->status) & ZFCP_STATUS_COMMON_OPEN)) {
384 zfcp_erp_port_reopen(port, ZFCP_STATUS_COMMON_ERP_FAILED,
385 "fcadh_2", NULL);
386 goto out;
387 }
387 388
389 /* port is good, unblock rport without going through erp */
390 zfcp_scsi_schedule_rport_register(port);
388 out: 391 out:
389 zfcp_port_put(port); 392 zfcp_port_put(port);
390 kfree(adisc); 393 kfree(adisc);
@@ -422,6 +425,31 @@ static int zfcp_fc_adisc(struct zfcp_port *port)
422 return zfcp_fsf_send_els(&adisc->els); 425 return zfcp_fsf_send_els(&adisc->els);
423} 426}
424 427
428void zfcp_fc_link_test_work(struct work_struct *work)
429{
430 struct zfcp_port *port =
431 container_of(work, struct zfcp_port, test_link_work);
432 int retval;
433
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);
440 port->rport_task = RPORT_DEL;
441 zfcp_scsi_rport_work(&port->rport_work);
442
443 retval = zfcp_fc_adisc(port);
444 if (retval == 0)
445 return;
446
447 /* send of ADISC was not possible */
448 zfcp_erp_port_forced_reopen(port, 0, "fcltwk1", NULL);
449
450 zfcp_port_put(port);
451}
452
425/** 453/**
426 * zfcp_test_link - lightweight link test procedure 454 * zfcp_test_link - lightweight link test procedure
427 * @port: port to be tested 455 * @port: port to be tested
@@ -432,17 +460,9 @@ static int zfcp_fc_adisc(struct zfcp_port *port)
432 */ 460 */
433void zfcp_test_link(struct zfcp_port *port) 461void zfcp_test_link(struct zfcp_port *port)
434{ 462{
435 int retval;
436
437 zfcp_port_get(port); 463 zfcp_port_get(port);
438 retval = zfcp_fc_adisc(port); 464 if (!queue_work(zfcp_data.work_queue, &port->test_link_work))
439 if (retval == 0) 465 zfcp_port_put(port);
440 return;
441
442 /* send of ADISC was not possible */
443 zfcp_port_put(port);
444 if (retval != -EBUSY)
445 zfcp_erp_port_forced_reopen(port, 0, 65, NULL);
446} 466}
447 467
448static void zfcp_free_sg_env(struct zfcp_gpn_ft *gpn_ft, int buf_num) 468static void zfcp_free_sg_env(struct zfcp_gpn_ft *gpn_ft, int buf_num)
@@ -529,7 +549,7 @@ static void zfcp_validate_port(struct zfcp_port *port)
529 zfcp_port_put(port); 549 zfcp_port_put(port);
530 return; 550 return;
531 } 551 }
532 zfcp_erp_port_shutdown(port, 0, 151, NULL); 552 zfcp_erp_port_shutdown(port, 0, "fcpval1", NULL);
533 zfcp_erp_wait(adapter); 553 zfcp_erp_wait(adapter);
534 zfcp_port_put(port); 554 zfcp_port_put(port);
535 zfcp_port_dequeue(port); 555 zfcp_port_dequeue(port);
@@ -592,7 +612,7 @@ static int zfcp_scan_eval_gpn_ft(struct zfcp_gpn_ft *gpn_ft, int max_entries)
592 if (IS_ERR(port)) 612 if (IS_ERR(port))
593 ret = PTR_ERR(port); 613 ret = PTR_ERR(port);
594 else 614 else
595 zfcp_erp_port_reopen(port, 0, 149, NULL); 615 zfcp_erp_port_reopen(port, 0, "fcegpf1", NULL);
596 } 616 }
597 617
598 zfcp_erp_wait(adapter); 618 zfcp_erp_wait(adapter);