At SRP login, the client indicates to the target a requested maximum
initiator to target IU (it_iu) length.  If the target cannot handle
this length, it rejects the login.  If the target can handle the
requested length, on the other hand, it will accept the login and
respond with its own maximum it_iu length.  Currently, ib_srp does not
utilize the maximum it_iu length suggested by the target, and if the
target rejects the value used by ib_srp, no connection will be made. 

This patch adds the ability for ib_srp to retry a login if the target
rejects the login because the maximum it_iu value used by ib_srp is
too large.  The ib_srp client will reduce its requested maximum it_iu
length to a minimum value and retry the login.  

On a successful login, the ib_srp client will set the maximum it_iu
length it will use to the maximum it_iu length requested by the
target, within the bounds of the minimum and maximum it_iu lengths it
can support.

The size of the indirect memory descriptor table built by ib_srp is
established at build time, based on an internal maximum iu size.  In
order to accomodate the changes described above, this patch modifies
ib_srp so that if the maximum it_iu length established with the target
is less than the internal maximum iu size specified when ib_srp was
built, only those indirect memory descriptors that will fit in the
established maximum it_iu length (the partial descriptor list) will be
sent to the target.  Any indirect memory descriptors beyond that must
be retrieved by the target via rdma read, as described in the SRP 
documentation.

The patch has been tested with our target.

Signed-off-by: John Kingman <[EMAIL PROTECTED]>

Index: ib_srp.h
===================================================================
--- ib_srp.h    (revision 3914)
+++ ib_srp.h    (working copy)
@@ -53,8 +53,10 @@ enum {
 
        SRP_PORT_REDIRECT       = 1,
        SRP_DLID_REDIRECT       = 2,
+       SRP_LOGIN_RETRY         = 3,
 
-       SRP_MAX_IU_LEN          = 256,
+       SRP_MAX_IU_LEN          = 1024,     /* our maximum it_iu size */
+       SRP_REQ_IU_LEN          = 256,      /* it_iu size to request initially 
*/
 
        SRP_RQ_SHIFT            = 6,
        SRP_RQ_SIZE             = 1 << SRP_RQ_SHIFT,
@@ -65,9 +67,11 @@ enum {
 };
 
 #define SRP_OP_RECV            (1 << 31)
-#define SRP_MAX_INDIRECT       ((SRP_MAX_IU_LEN -                      \
-                                 sizeof (struct srp_cmd) -             \
-                                 sizeof (struct srp_indirect_buf)) / 16)
+#define SRP_MIN_IU_LEN          (sizeof (struct srp_cmd) +          \
+                                sizeof (struct srp_indirect_buf))
+#define SRP_NUM_PARTIALS(x)                                         \
+       (((x) - SRP_MIN_IU_LEN) / sizeof (struct srp_direct_buf))
+#define SRP_MAX_INDIRECT        SRP_NUM_PARTIALS(SRP_MAX_IU_LEN)
 
 enum srp_target_state {
        SRP_TARGET_LIVE,
@@ -117,8 +121,10 @@ struct srp_target_port {
        struct ib_cm_id        *cm_id;
        struct ib_cq           *cq;
        struct ib_qp           *qp;
-
        int                     max_ti_iu_len;
+       int                     max_it_iu_len;
+       int                     req_it_iu_len;
+       int                     max_partial_desc;
        s32                     req_lim;
 
        unsigned                rx_head;

Index: ib_srp.c
===================================================================
--- ib_srp.c    (revision 3914)
+++ ib_srp.c    (working copy)
@@ -295,7 +297,7 @@ static int srp_send_req(struct srp_targe
 
        req->priv.opcode        = SRP_LOGIN_REQ;
        req->priv.tag           = 0;
-       req->priv.req_it_iu_len = cpu_to_be32(SRP_MAX_IU_LEN);
+       req->priv.req_it_iu_len = cpu_to_be32(target->req_it_iu_len);
        req->priv.req_buf_fmt   = cpu_to_be16(SRP_BUF_FORMAT_DIRECT |
                                              SRP_BUF_FORMAT_INDIRECT);
        memcpy(req->priv.initiator_port_id, 
target->srp_host->initiator_port_id, 16);
@@ -386,6 +388,7 @@ static int srp_connect_target(struct srp
                                return ret;
                        break;
 
+               case SRP_LOGIN_RETRY:
                case SRP_DLID_REDIRECT:
                        break;
 
@@ -528,11 +531,6 @@ static int srp_map_data(struct scsi_cmnd
 
                        fmt = SRP_DATA_DESC_INDIRECT;
 
-                       if (scmnd->sc_data_direction == DMA_TO_DEVICE)
-                               cmd->data_out_desc_cnt = n;
-                       else
-                               cmd->data_in_desc_cnt = n;
-
                        buf->table_desc.va  = cpu_to_be64(req->cmd->dma +
                                                          sizeof *cmd +
                                                          sizeof *buf);
@@ -552,6 +550,20 @@ static int srp_map_data(struct scsi_cmnd
 
                        buf->len = cpu_to_be32(datalen);
 
+                       /*
+                        * buf->len includes the SRP indirect descriptor table.
+                        * We only include in the descriptor count (n) and len 
+                        * the descriptors that fit in partial descriptor list
+                        * of the it_iu. Any beyond that will be rdma read by 
+                        * the target.
+                        */
+                       n = min(target->max_partial_desc, n);
+
+                       if (scmnd->sc_data_direction == DMA_TO_DEVICE)
+                               cmd->data_out_desc_cnt = n;
+                       else
+                               cmd->data_in_desc_cnt = n;
+
                        len = sizeof (struct srp_cmd) +
                                sizeof (struct srp_indirect_buf) +
                                n * sizeof (struct srp_direct_buf);
@@ -1003,10 +1015,19 @@ static void srp_cm_rej_handler(struct ib
                        struct srp_login_rej *rej = event->private_data;
                        u32 reason = be32_to_cpu(rej->reason);
 
-                       if (reason == SRP_LOGIN_REJ_REQ_IT_IU_LENGTH_TOO_LARGE)
-                               printk(KERN_WARNING PFX
+                       if (reason == SRP_LOGIN_REJ_REQ_IT_IU_LENGTH_TOO_LARGE) 
{
+                               printk(KERN_DEBUG PFX
                                       "SRP_LOGIN_REJ: requested max_it_iu_len 
too large\n");
-                       else
+                               /* 
+                                * Retry with minimum it_iu length and let 
target 
+                                * suggest max it_iu length. 
+                                */
+                               if (target->req_it_iu_len > SRP_MIN_IU_LEN) {
+                                       target->req_it_iu_len = SRP_MIN_IU_LEN;
+                                       target->status = SRP_LOGIN_RETRY;
+                                       break;
+                               }
+                       } else
                                printk(KERN_WARNING PFX
                                       "SRP LOGIN REJECTED, reason 0x%08x\n", 
reason);
                } else
@@ -1045,6 +1066,17 @@ static int srp_cm_handler(struct ib_cm_i
                        struct srp_login_rsp *rsp = event->private_data;
 
                        target->max_ti_iu_len = be32_to_cpu(rsp->max_ti_iu_len);
+                       target->max_it_iu_len = be32_to_cpu(rsp->max_it_iu_len);
+                       if (target->max_it_iu_len > SRP_MAX_IU_LEN)
+                           target->max_it_iu_len = SRP_MAX_IU_LEN;
+                       else if (target->max_it_iu_len < SRP_MIN_IU_LEN) {
+                               printk(KERN_ERR PFX "Invalid 
rsp->max_it_iu_len: %d\n", 
+                                       target->max_it_iu_len);
+                               target->status = -ECONNRESET;
+                               break;
+                       }
+                       target->max_partial_desc = 
+                               SRP_NUM_PARTIALS(target->max_it_iu_len);
                        target->req_lim       = be32_to_cpu(rsp->req_lim_delta);
 
                        target->scsi_host->can_queue = min(target->req_lim,
@@ -1227,7 +1259,8 @@ static struct scsi_host_template srp_tem
        .eh_host_reset_handler          = srp_reset_host,
        .can_queue                      = SRP_SQ_SIZE,
        .this_id                        = -1,
-       .sg_tablesize                   = SRP_MAX_INDIRECT,
+       .sg_tablesize                   = (SRP_MAX_INDIRECT < SG_ALL ? 
+                                          SRP_MAX_INDIRECT : SG_ALL),
        .cmd_per_lun                    = SRP_SQ_SIZE,
        .use_clustering                 = ENABLE_CLUSTERING
 };
@@ -1434,6 +1467,8 @@ static ssize_t srp_create_target(struct 
                ret = PTR_ERR(target->cm_id);
                goto err_free;
        }
+       target->req_it_iu_len = SRP_REQ_IU_LEN;
+       target->max_partial_desc = SRP_NUM_PARTIALS(SRP_REQ_IU_LEN);
 
        ret = srp_connect_target(target);
        if (ret) {
_______________________________________________
openib-general mailing list
[email protected]
http://openib.org/mailman/listinfo/openib-general

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

Reply via email to