[openib-general] Re: [PATCH] [SRP] Fix CM redirection in SRP
Roland Dreier
rolandd at cisco.com
Mon Sep 12 09:33:09 PDT 2005
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,
More information about the general
mailing list