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 | |
| 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>
| -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; |
