diff options
author | Bart Van Assche <bvanassche@acm.org> | 2013-10-26 08:35:08 -0400 |
---|---|---|
committer | Roland Dreier <roland@purestorage.com> | 2013-11-08 17:43:15 -0500 |
commit | c1120f8981fe8ac8dd21092afaf664ba030a76cd (patch) | |
tree | d0d821d18c9f2999b2d1619d4c87b308ea57fa15 /drivers/infiniband/ulp/srp | |
parent | ed9b2264fb393327a6c8a4229d8df55df596188e (diff) |
IB/srp: Start timers if a transport layer error occurs
Start the reconnect timer, fast_io_fail timer and dev_loss timers if a
transport layer error occurs.
Signed-off-by: Bart Van Assche <bvanassche@acm.org>
Acked-by: David Dillow <dillowda@ornl.gov>
Signed-off-by: Roland Dreier <roland@purestorage.com>
Diffstat (limited to 'drivers/infiniband/ulp/srp')
-rw-r--r-- | drivers/infiniband/ulp/srp/ib_srp.c | 19 | ||||
-rw-r--r-- | drivers/infiniband/ulp/srp/ib_srp.h | 1 |
2 files changed, 20 insertions, 0 deletions
diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c index 15b4d2ce4989..076a3ab7f779 100644 --- a/drivers/infiniband/ulp/srp/ib_srp.c +++ b/drivers/infiniband/ulp/srp/ib_srp.c | |||
@@ -593,6 +593,7 @@ static void srp_remove_target(struct srp_target_port *target) | |||
593 | srp_disconnect_target(target); | 593 | srp_disconnect_target(target); |
594 | ib_destroy_cm_id(target->cm_id); | 594 | ib_destroy_cm_id(target->cm_id); |
595 | srp_free_target_ib(target); | 595 | srp_free_target_ib(target); |
596 | cancel_work_sync(&target->tl_err_work); | ||
596 | srp_rport_put(target->rport); | 597 | srp_rport_put(target->rport); |
597 | srp_free_req_data(target); | 598 | srp_free_req_data(target); |
598 | scsi_host_put(target->scsi_host); | 599 | scsi_host_put(target->scsi_host); |
@@ -1362,6 +1363,21 @@ static void srp_handle_recv(struct srp_target_port *target, struct ib_wc *wc) | |||
1362 | PFX "Recv failed with error code %d\n", res); | 1363 | PFX "Recv failed with error code %d\n", res); |
1363 | } | 1364 | } |
1364 | 1365 | ||
1366 | /** | ||
1367 | * srp_tl_err_work() - handle a transport layer error | ||
1368 | * | ||
1369 | * Note: This function may get invoked before the rport has been created, | ||
1370 | * hence the target->rport test. | ||
1371 | */ | ||
1372 | static void srp_tl_err_work(struct work_struct *work) | ||
1373 | { | ||
1374 | struct srp_target_port *target; | ||
1375 | |||
1376 | target = container_of(work, struct srp_target_port, tl_err_work); | ||
1377 | if (target->rport) | ||
1378 | srp_start_tl_fail_timers(target->rport); | ||
1379 | } | ||
1380 | |||
1365 | static void srp_handle_qp_err(enum ib_wc_status wc_status, | 1381 | static void srp_handle_qp_err(enum ib_wc_status wc_status, |
1366 | enum ib_wc_opcode wc_opcode, | 1382 | enum ib_wc_opcode wc_opcode, |
1367 | struct srp_target_port *target) | 1383 | struct srp_target_port *target) |
@@ -1371,6 +1387,7 @@ static void srp_handle_qp_err(enum ib_wc_status wc_status, | |||
1371 | PFX "failed %s status %d\n", | 1387 | PFX "failed %s status %d\n", |
1372 | wc_opcode & IB_WC_RECV ? "receive" : "send", | 1388 | wc_opcode & IB_WC_RECV ? "receive" : "send", |
1373 | wc_status); | 1389 | wc_status); |
1390 | queue_work(system_long_wq, &target->tl_err_work); | ||
1374 | } | 1391 | } |
1375 | target->qp_in_error = true; | 1392 | target->qp_in_error = true; |
1376 | } | 1393 | } |
@@ -1733,6 +1750,7 @@ static int srp_cm_handler(struct ib_cm_id *cm_id, struct ib_cm_event *event) | |||
1733 | if (ib_send_cm_drep(cm_id, NULL, 0)) | 1750 | if (ib_send_cm_drep(cm_id, NULL, 0)) |
1734 | shost_printk(KERN_ERR, target->scsi_host, | 1751 | shost_printk(KERN_ERR, target->scsi_host, |
1735 | PFX "Sending CM DREP failed\n"); | 1752 | PFX "Sending CM DREP failed\n"); |
1753 | queue_work(system_long_wq, &target->tl_err_work); | ||
1736 | break; | 1754 | break; |
1737 | 1755 | ||
1738 | case IB_CM_TIMEWAIT_EXIT: | 1756 | case IB_CM_TIMEWAIT_EXIT: |
@@ -2419,6 +2437,7 @@ static ssize_t srp_create_target(struct device *dev, | |||
2419 | sizeof (struct srp_indirect_buf) + | 2437 | sizeof (struct srp_indirect_buf) + |
2420 | target->cmd_sg_cnt * sizeof (struct srp_direct_buf); | 2438 | target->cmd_sg_cnt * sizeof (struct srp_direct_buf); |
2421 | 2439 | ||
2440 | INIT_WORK(&target->tl_err_work, srp_tl_err_work); | ||
2422 | INIT_WORK(&target->remove_work, srp_remove_work); | 2441 | INIT_WORK(&target->remove_work, srp_remove_work); |
2423 | spin_lock_init(&target->lock); | 2442 | spin_lock_init(&target->lock); |
2424 | INIT_LIST_HEAD(&target->free_tx); | 2443 | INIT_LIST_HEAD(&target->free_tx); |
diff --git a/drivers/infiniband/ulp/srp/ib_srp.h b/drivers/infiniband/ulp/srp/ib_srp.h index fd1817e48ad4..446b0452107b 100644 --- a/drivers/infiniband/ulp/srp/ib_srp.h +++ b/drivers/infiniband/ulp/srp/ib_srp.h | |||
@@ -177,6 +177,7 @@ struct srp_target_port { | |||
177 | struct srp_iu *rx_ring[SRP_RQ_SIZE]; | 177 | struct srp_iu *rx_ring[SRP_RQ_SIZE]; |
178 | struct srp_request req_ring[SRP_CMD_SQ_SIZE]; | 178 | struct srp_request req_ring[SRP_CMD_SQ_SIZE]; |
179 | 179 | ||
180 | struct work_struct tl_err_work; | ||
180 | struct work_struct remove_work; | 181 | struct work_struct remove_work; |
181 | 182 | ||
182 | struct list_head list; | 183 | struct list_head list; |