I rewrote your patch to fix a few things:

 - I believe we always need to copy the redirect GID, even if the
   redirect LID is non-zero; otherwise we will end up putting the GID
   of the original port in our CM REQ.  From my reading of the
   description of ClassPortInfo in the IB spec, I think the redirect
   GID must always be valid if redirection is being done.

 - I moved the connect handling into a new function
   srp_connect_target(), so that both the initial connect and future
   reconnects get handling for port and DLID redirection.

 - I got rid of the change for CM REJ reason 25 -- that reject code
   does not carry a ClassPortInfo in the ARI, but rather just the
   GID at offset 0.

By the way, it's not that critical for SRP, since it's not in the
upstream kernel yet, but I don't think we should use obfuscated email
addresses in Signed-off-by lines:

    > Signed-off-by: John Kingman <kingman <at> storagegear.com>

Just put the '@' in there -- I think there are much bigger spam
sources to worry about.

Anyway, here's the updated patch.  Does this look OK to you?

 - R.

Index: infiniband/ulp/srp/ib_srp.c
===================================================================
--- infiniband/ulp/srp/ib_srp.c (revision 3372)
+++ infiniband/ulp/srp/ib_srp.c (working copy)
@@ -386,11 +386,48 @@ static void srp_remove_work(void *target
        scsi_host_put(target->scsi_host);
 }
 
+static int srp_connect_target(struct srp_target_port *target)
+{
+       int ret;
+
+       while (1) {
+               init_completion(&target->done);
+               ret = srp_send_req(target);
+               if (ret)
+                       return ret;
+               wait_for_completion(&target->done);
+
+               /*
+                * The CM event handling code will set status to
+                * SRP_PORT_REDIRECT if we get a port redirect REJ
+                * back, or SRP_DLID_REDIRECT if we get a lid/qp
+                * redirect REJ back.
+                */
+               switch (target->status) {
+               case 0:
+                       return 0;
+
+               case SRP_PORT_REDIRECT:
+                       ret = srp_lookup_path(target);
+                       if (ret)
+                               return ret;
+                       break;
+
+               case SRP_DLID_REDIRECT:
+                       break;
+
+               default:
+                       return target->status;
+               }
+       }
+}
+
 static int srp_reconnect_target(struct srp_target_port *target)
 {
        struct ib_qp_attr qp_attr;
        struct srp_request *req;
        struct ib_wc wc;
+       u32 remote_cm_qpn;
        int ret;
        int i;
 
@@ -402,6 +439,8 @@ static int srp_reconnect_target(struct s
        target->state = SRP_TARGET_CONNECTING;
        spin_unlock_irq(target->scsi_host->host_lock);
 
+       remote_cm_qpn = target->cm_id->remote_cm_qpn;
+
        srp_disconnect_target(target);
 
        target->cm_id = ib_create_cm_id(srp_cm_handler, target);
@@ -411,6 +450,8 @@ static int srp_reconnect_target(struct s
                goto err;
        }
 
+       target->cm_id->remote_cm_qpn = remote_cm_qpn;
+
        qp_attr.qp_state = IB_QPS_RESET;
        ret = ib_modify_qp(target->qp, &qp_attr, IB_QP_STATE);
        if (ret)
@@ -438,24 +479,9 @@ static int srp_reconnect_target(struct s
        target->req_ring[SRP_SQ_SIZE - 1].next = -1;
        INIT_LIST_HEAD(&target->req_queue);
 
-retry_connect:
-       init_completion(&target->done);
-       ret = srp_send_req(target);
+       ret = srp_connect_target(target);
        if (ret)
                goto err;
-       wait_for_completion(&target->done);
-
-       /*
-        * The CM event handling code will set status to
-        * SRP_PORT_REDIRECT if we get a port redirect REJ back.
-        */
-       if (target->status == SRP_PORT_REDIRECT) {
-               ret = srp_lookup_path(target);
-               if (ret)
-                       goto err;
-               goto retry_connect;
-       } else if (target->status < 0)
-               goto err;
 
        spin_lock_irq(target->scsi_host->host_lock);
        if (target->state == SRP_TARGET_CONNECTING) {
@@ -1031,8 +1057,13 @@ static int srp_cm_handler(struct ib_cm_i
 
                if (event->param.rej_rcvd.reason == IB_CM_REJ_PORT_CM_REDIRECT) 
{
                        cpi = event->param.rej_rcvd.ari;
+                       target->path.dlid = cpi->redirect_lid;
+                       target->path.pkey = cpi->redirect_pkey;
+                       cm_id->remote_cm_qpn = be32_to_cpu(cpi->redirect_qp) & 
0x00ffffff;
                        memcpy(target->path.dgid.raw, cpi->redirect_gid, 16);
-                       target->status = SRP_PORT_REDIRECT;
+
+                       target->status = target->path.dlid ?
+                               SRP_DLID_REDIRECT : SRP_PORT_REDIRECT;
                } else if (topspin_workarounds &&
                           !memcmp(&target->ioc_guid, topspin_oui, 3) &&
                           event->param.rej_rcvd.reason == 
IB_CM_REJ_PORT_REDIRECT) {
@@ -1042,7 +1073,7 @@ static int srp_cm_handler(struct ib_cm_i
                         * (port redirect).
                         */
                        memcpy(target->path.dgid.raw,
-                              event->param.rej_rcvd.ari + 0, 16);
+                              event->param.rej_rcvd.ari, 16);
 
                        printk(KERN_DEBUG PFX "Topspin/Cisco redirect to target 
port GID %016llx%016llx\n",
                               (unsigned long long) 
be64_to_cpu(target->path.dgid.global.subnet_prefix),
@@ -1386,28 +1417,15 @@ static ssize_t srp_create_target(struct 
               (int) be16_to_cpu(*(__be16 *) &target->path.dgid.raw[12]),
               (int) be16_to_cpu(*(__be16 *) &target->path.dgid.raw[14]));
 
-retry_path:
        ret = srp_lookup_path(target);
        if (ret) {
                ib_destroy_cm_id(target->cm_id);
                goto err;
        }
 
-       init_completion(&target->done);
-       ret = srp_send_req(target);
-       if (ret)
-               goto err;
-       wait_for_completion(&target->done);
-
-       /*
-        * The CM event handling code will set status to
-        * SRP_PORT_REDIRECT if we get a port redirect REJ back.
-        */
-       if (target->status == SRP_PORT_REDIRECT)
-               goto retry_path;
-       else if (target->status < 0) {
+       ret = srp_connect_target(target);
+       if (ret) {
                printk(KERN_ERR PFX "Connection failed\n");
-               ret = target->status;
                goto err;
        }
 
Index: infiniband/ulp/srp/ib_srp.h
===================================================================
--- infiniband/ulp/srp/ib_srp.h (revision 3372)
+++ infiniband/ulp/srp/ib_srp.h (working copy)
@@ -52,6 +52,7 @@ enum {
        SRP_ABORT_TIMEOUT_MS    = 5000,
 
        SRP_PORT_REDIRECT       = 1,
+       SRP_DLID_REDIRECT       = 2,
 
        SRP_MAX_IU_LEN          = 256,
 
_______________________________________________
openib-general mailing list
openib-general@openib.org
http://openib.org/mailman/listinfo/openib-general

To unsubscribe, please visit http://openib.org/mailman/listinfo/openib-general

Reply via email to