IB/core: Enhance ib_map_mr_sg()
[deliverable/linux.git] / drivers / infiniband / ulp / srp / ib_srp.c
index b6bf2049602107befe1f49eedee4494336f85e28..54f4c131089761a0e7d60746652c8acb022998e5 100644 (file)
@@ -316,7 +316,7 @@ static struct ib_fmr_pool *srp_alloc_fmr_pool(struct srp_target_port *target)
        struct ib_fmr_pool_param fmr_param;
 
        memset(&fmr_param, 0, sizeof(fmr_param));
-       fmr_param.pool_size         = target->scsi_host->can_queue;
+       fmr_param.pool_size         = target->mr_pool_size;
        fmr_param.dirty_watermark   = fmr_param.pool_size / 4;
        fmr_param.cache             = 1;
        fmr_param.max_pages_per_fmr = dev->max_pages_per_mr;
@@ -441,23 +441,22 @@ static struct srp_fr_pool *srp_alloc_fr_pool(struct srp_target_port *target)
 {
        struct srp_device *dev = target->srp_host->srp_dev;
 
-       return srp_create_fr_pool(dev->dev, dev->pd,
-                                 target->scsi_host->can_queue,
+       return srp_create_fr_pool(dev->dev, dev->pd, target->mr_pool_size,
                                  dev->max_pages_per_mr);
 }
 
 /**
  * srp_destroy_qp() - destroy an RDMA queue pair
- * @ch: SRP RDMA channel.
+ * @qp: RDMA queue pair.
  *
  * Drain the qp before destroying it.  This avoids that the receive
  * completion handler can access the queue pair while it is
  * being destroyed.
  */
-static void srp_destroy_qp(struct srp_rdma_ch *ch)
+static void srp_destroy_qp(struct ib_qp *qp)
 {
-       ib_drain_rq(ch->qp);
-       ib_destroy_qp(ch->qp);
+       ib_drain_rq(qp);
+       ib_destroy_qp(qp);
 }
 
 static int srp_create_ch_ib(struct srp_rdma_ch *ch)
@@ -530,7 +529,7 @@ static int srp_create_ch_ib(struct srp_rdma_ch *ch)
        }
 
        if (ch->qp)
-               srp_destroy_qp(ch);
+               srp_destroy_qp(ch->qp);
        if (ch->recv_cq)
                ib_free_cq(ch->recv_cq);
        if (ch->send_cq)
@@ -554,7 +553,7 @@ static int srp_create_ch_ib(struct srp_rdma_ch *ch)
        return 0;
 
 err_qp:
-       srp_destroy_qp(ch);
+       srp_destroy_qp(qp);
 
 err_send_cq:
        ib_free_cq(send_cq);
@@ -597,7 +596,7 @@ static void srp_free_ch_ib(struct srp_target_port *target,
                        ib_destroy_fmr_pool(ch->fmr_pool);
        }
 
-       srp_destroy_qp(ch);
+       srp_destroy_qp(ch->qp);
        ib_free_cq(ch->send_cq);
        ib_free_cq(ch->recv_cq);
 
@@ -1112,7 +1111,7 @@ static struct scsi_cmnd *srp_claim_req(struct srp_rdma_ch *ch,
 }
 
 /**
- * srp_free_req() - Unmap data and add request to the free request list.
+ * srp_free_req() - Unmap data and adjust ch->req_lim.
  * @ch:     SRP RDMA channel.
  * @req:    Request to be freed.
  * @scmnd:  SCSI command associated with @req.
@@ -1316,9 +1315,6 @@ static int srp_map_finish_fr(struct srp_map_state *state,
 
        WARN_ON_ONCE(!dev->use_fast_reg);
 
-       if (sg_nents == 0)
-               return 0;
-
        if (sg_nents == 1 && target->global_mr) {
                srp_map_desc(state, sg_dma_address(state->sg),
                             sg_dma_len(state->sg),
@@ -1333,9 +1329,14 @@ static int srp_map_finish_fr(struct srp_map_state *state,
        rkey = ib_inc_rkey(desc->mr->rkey);
        ib_update_fast_reg_key(desc->mr, rkey);
 
-       n = ib_map_mr_sg(desc->mr, state->sg, sg_nents, dev->mr_page_size);
-       if (unlikely(n < 0))
+       n = ib_map_mr_sg(desc->mr, state->sg, sg_nents, NULL, dev->mr_page_size);
+       if (unlikely(n < 0)) {
+               srp_fr_pool_put(ch->fr_pool, &desc, 1);
+               pr_debug("%s: ib_map_mr_sg(%d) returned %d.\n",
+                        dev_name(&req->scmnd->device->sdev_gendev), sg_nents,
+                        n);
                return n;
+       }
 
        req->reg_cqe.done = srp_reg_mr_err_done;
 
@@ -1398,7 +1399,7 @@ static int srp_map_sg_entry(struct srp_map_state *state,
        /*
         * If the last entry of the MR wasn't a full page, then we need to
         * close it out and start a new one -- we can only merge at page
-        * boundries.
+        * boundaries.
         */
        ret = 0;
        if (len != dev->mr_page_size)
@@ -1413,7 +1414,6 @@ static int srp_map_sg_fmr(struct srp_map_state *state, struct srp_rdma_ch *ch,
        struct scatterlist *sg;
        int i, ret;
 
-       state->desc = req->indirect_desc;
        state->pages = req->map_page;
        state->fmr.next = req->fmr_list;
        state->fmr.end = req->fmr_list + ch->target->cmd_sg_cnt;
@@ -1428,8 +1428,6 @@ static int srp_map_sg_fmr(struct srp_map_state *state, struct srp_rdma_ch *ch,
        if (ret)
                return ret;
 
-       req->nmdesc = state->nmdesc;
-
        return 0;
 }
 
@@ -1442,6 +1440,9 @@ static int srp_map_sg_fr(struct srp_map_state *state, struct srp_rdma_ch *ch,
        state->fr.end = req->fr_list + ch->target->cmd_sg_cnt;
        state->sg = scat;
 
+       if (count == 0)
+               return 0;
+
        while (count) {
                int i, n;
 
@@ -1454,8 +1455,6 @@ static int srp_map_sg_fr(struct srp_map_state *state, struct srp_rdma_ch *ch,
                        state->sg = sg_next(state->sg);
        }
 
-       req->nmdesc = state->nmdesc;
-
        return 0;
 }
 
@@ -1475,8 +1474,6 @@ static int srp_map_sg_dma(struct srp_map_state *state, struct srp_rdma_ch *ch,
                             target->global_mr->rkey);
        }
 
-       req->nmdesc = state->nmdesc;
-
        return 0;
 }
 
@@ -1534,6 +1531,15 @@ static int srp_map_idb(struct srp_rdma_ch *ch, struct srp_request *req,
        return 0;
 }
 
+/**
+ * srp_map_data() - map SCSI data buffer onto an SRP request
+ * @scmnd: SCSI command to map
+ * @ch: SRP RDMA channel
+ * @req: SRP request
+ *
+ * Returns the length in bytes of the SRP_CMD IU or a negative value if
+ * mapping failed.
+ */
 static int srp_map_data(struct scsi_cmnd *scmnd, struct srp_rdma_ch *ch,
                        struct srp_request *req)
 {
@@ -1601,11 +1607,14 @@ static int srp_map_data(struct scsi_cmnd *scmnd, struct srp_rdma_ch *ch,
 
        memset(&state, 0, sizeof(state));
        if (dev->use_fast_reg)
-               srp_map_sg_fr(&state, ch, req, scat, count);
+               ret = srp_map_sg_fr(&state, ch, req, scat, count);
        else if (dev->use_fmr)
-               srp_map_sg_fmr(&state, ch, req, scat, count);
+               ret = srp_map_sg_fmr(&state, ch, req, scat, count);
        else
-               srp_map_sg_dma(&state, ch, req, scat, count);
+               ret = srp_map_sg_dma(&state, ch, req, scat, count);
+       req->nmdesc = state.nmdesc;
+       if (ret < 0)
+               goto unmap;
 
        /* We've mapped the request, now pull as much of the indirect
         * descriptor table as we can into the command buffer. If this
@@ -1628,7 +1637,8 @@ static int srp_map_data(struct scsi_cmnd *scmnd, struct srp_rdma_ch *ch,
                                                !target->allow_ext_sg)) {
                shost_printk(KERN_ERR, target->scsi_host,
                             "Could not fit S/G list into SRP_CMD\n");
-               return -EIO;
+               ret = -EIO;
+               goto unmap;
        }
 
        count = min(state.ndesc, target->cmd_sg_cnt);
@@ -1646,7 +1656,7 @@ static int srp_map_data(struct scsi_cmnd *scmnd, struct srp_rdma_ch *ch,
                ret = srp_map_idb(ch, req, state.gen.next, state.gen.end,
                                  idb_len, &idb_rkey);
                if (ret < 0)
-                       return ret;
+                       goto unmap;
                req->nmdesc++;
        } else {
                idb_rkey = cpu_to_be32(target->global_mr->rkey);
@@ -1672,6 +1682,12 @@ map_complete:
                cmd->buf_fmt = fmt;
 
        return len;
+
+unmap:
+       srp_unmap_data(scmnd, ch, req);
+       if (ret == -ENOMEM && req->nmdesc >= target->mr_pool_size)
+               ret = -E2BIG;
+       return ret;
 }
 
 /*
@@ -2829,7 +2845,7 @@ static int srp_add_target(struct srp_host *host, struct srp_target_port *target)
                goto out;
        }
 
-       pr_debug(PFX "%s: SCSI scan succeeded - detected %d LUNs\n",
+       pr_debug("%s: SCSI scan succeeded - detected %d LUNs\n",
                 dev_name(&target->scsi_host->shost_gendev),
                 srp_sdev_count(target->scsi_host));
 
@@ -3218,6 +3234,7 @@ static ssize_t srp_create_target(struct device *dev,
        }
 
        target_host->sg_tablesize = target->sg_tablesize;
+       target->mr_pool_size = target->scsi_host->can_queue;
        target->indirect_size = target->sg_tablesize *
                                sizeof (struct srp_direct_buf);
        target->max_iu_len = sizeof (struct srp_cmd) +
This page took 0.029466 seconds and 5 git commands to generate.