IB/srp: Don't wait for response when QP is in error state.
authorIshai Rabinovitz <ishai@mellanox.co.il>
Tue, 16 Jan 2007 15:26:22 +0000 (17:26 +0200)
committerRoland Dreier <rolandd@cisco.com>
Sun, 4 Feb 2007 22:11:56 +0000 (14:11 -0800)
When there is a call to send_tsk_mgmt SRP posts a send and waits for 5
seconds to get a response.

When the QP is in the error state it is obvious that there will be no
response so it is quite useless to wait.  In fact, the timeout causes
SRP to wait a long time to reconnect when a QP error occurs. (Each
abort and each reset_device calls send_tsk_mgmt, which waits for the
timeout).  The following patch solves this problem by identifying the
failure and returning an immediate error code.

Signed-off-by: Ishai Rabinovitz <ishai@mellanox.co.il>
Signed-off-by: Roland Dreier <rolandd@cisco.com>
drivers/infiniband/ulp/srp/ib_srp.c
drivers/infiniband/ulp/srp/ib_srp.h

index 72611fd15103302631a074a26f2cd2c0312d9b6d..5e8ac577f0ad1c33dd9cf65a71d18dd149848822 100644 (file)
@@ -548,6 +548,7 @@ static int srp_reconnect_target(struct srp_target_port *target)
        target->tx_head  = 0;
        target->tx_tail  = 0;
 
+       target->qp_in_error = 0;
        ret = srp_connect_target(target);
        if (ret)
                goto err;
@@ -878,6 +879,7 @@ static void srp_completion(struct ib_cq *cq, void *target_ptr)
                        printk(KERN_ERR PFX "failed %s status %d\n",
                               wc.wr_id & SRP_OP_RECV ? "receive" : "send",
                               wc.status);
+                       target->qp_in_error = 1;
                        break;
                }
 
@@ -1337,6 +1339,8 @@ static int srp_abort(struct scsi_cmnd *scmnd)
 
        printk(KERN_ERR "SRP abort called\n");
 
+       if (target->qp_in_error)
+               return FAILED;
        if (srp_find_req(target, scmnd, &req))
                return FAILED;
        if (srp_send_tsk_mgmt(target, req, SRP_TSK_ABORT_TASK))
@@ -1365,6 +1369,8 @@ static int srp_reset_device(struct scsi_cmnd *scmnd)
 
        printk(KERN_ERR "SRP reset_device called\n");
 
+       if (target->qp_in_error)
+               return FAILED;
        if (srp_find_req(target, scmnd, &req))
                return FAILED;
        if (srp_send_tsk_mgmt(target, req, SRP_TSK_LUN_RESET))
@@ -1801,6 +1807,7 @@ static ssize_t srp_create_target(struct class_device *class_dev,
                goto err_free;
        }
 
+       target->qp_in_error = 0;
        ret = srp_connect_target(target);
        if (ret) {
                printk(KERN_ERR PFX "Connection failed\n");
index c21772317b86957796a1d0163f571c9716285af0..2f3319c719a57a630fd1f39b74ec3c50ceab2a99 100644 (file)
@@ -158,6 +158,7 @@ struct srp_target_port {
        struct completion       done;
        int                     status;
        enum srp_target_state   state;
+       int                     qp_in_error;
 };
 
 struct srp_iu {