]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - net/sunrpc/xprtrdma/svc_rdma_transport.c
svcrdma: Remove unneeded spin locks from __svc_rdma_free
[linux-2.6-omap-h63xx.git] / net / sunrpc / xprtrdma / svc_rdma_transport.c
index e132509d1db06285e6af8695c0e5171db0d9f766..7647789a1f6867773dc4688384e1de06fb84d2fd 100644 (file)
@@ -150,6 +150,19 @@ struct svc_rdma_op_ctxt *svc_rdma_get_context(struct svcxprt_rdma *xprt)
        return ctxt;
 }
 
+static void svc_rdma_unmap_dma(struct svc_rdma_op_ctxt *ctxt)
+{
+       struct svcxprt_rdma *xprt = ctxt->xprt;
+       int i;
+       for (i = 0; i < ctxt->count && ctxt->sge[i].length; i++) {
+               atomic_dec(&xprt->sc_dma_used);
+               ib_dma_unmap_single(xprt->sc_cm_id->device,
+                                   ctxt->sge[i].addr,
+                                   ctxt->sge[i].length,
+                                   ctxt->direction);
+       }
+}
+
 void svc_rdma_put_context(struct svc_rdma_op_ctxt *ctxt, int free_pages)
 {
        struct svcxprt_rdma *xprt;
@@ -161,18 +174,38 @@ void svc_rdma_put_context(struct svc_rdma_op_ctxt *ctxt, int free_pages)
                for (i = 0; i < ctxt->count; i++)
                        put_page(ctxt->pages[i]);
 
-       for (i = 0; i < ctxt->count; i++)
-               ib_dma_unmap_single(xprt->sc_cm_id->device,
-                                   ctxt->sge[i].addr,
-                                   ctxt->sge[i].length,
-                                   ctxt->direction);
-
        spin_lock_bh(&xprt->sc_ctxt_lock);
        list_add(&ctxt->free_list, &xprt->sc_ctxt_free);
        spin_unlock_bh(&xprt->sc_ctxt_lock);
        atomic_dec(&xprt->sc_ctxt_used);
 }
 
+/* Temporary NFS request map cache. Created in svc_rdma.c  */
+extern struct kmem_cache *svc_rdma_map_cachep;
+
+/*
+ * Temporary NFS req mappings are shared across all transport
+ * instances. These are short lived and should be bounded by the number
+ * of concurrent server threads * depth of the SQ.
+ */
+struct svc_rdma_req_map *svc_rdma_get_req_map(void)
+{
+       struct svc_rdma_req_map *map;
+       while (1) {
+               map = kmem_cache_alloc(svc_rdma_map_cachep, GFP_KERNEL);
+               if (map)
+                       break;
+               schedule_timeout_uninterruptible(msecs_to_jiffies(500));
+       }
+       map->count = 0;
+       return map;
+}
+
+void svc_rdma_put_req_map(struct svc_rdma_req_map *map)
+{
+       kmem_cache_free(svc_rdma_map_cachep, map);
+}
+
 /* ib_cq event handler */
 static void cq_event_handler(struct ib_event *event, void *context)
 {
@@ -302,6 +335,7 @@ static void rq_cq_reap(struct svcxprt_rdma *xprt)
                ctxt = (struct svc_rdma_op_ctxt *)(unsigned long)wc.wr_id;
                ctxt->wc_status = wc.status;
                ctxt->byte_len = wc.byte_len;
+               svc_rdma_unmap_dma(ctxt);
                if (wc.status != IB_WC_SUCCESS) {
                        /* Close the transport */
                        dprintk("svcrdma: transport closing putting ctxt %p\n", ctxt);
@@ -351,6 +385,7 @@ static void sq_cq_reap(struct svcxprt_rdma *xprt)
                ctxt = (struct svc_rdma_op_ctxt *)(unsigned long)wc.wr_id;
                xprt = ctxt->xprt;
 
+               svc_rdma_unmap_dma(ctxt);
                if (wc.status != IB_WC_SUCCESS)
                        /* Close the transport */
                        set_bit(XPT_CLOSE, &xprt->sc_xprt.xpt_flags);
@@ -361,10 +396,13 @@ static void sq_cq_reap(struct svcxprt_rdma *xprt)
 
                switch (ctxt->wr_op) {
                case IB_WR_SEND:
-               case IB_WR_RDMA_WRITE:
                        svc_rdma_put_context(ctxt, 1);
                        break;
 
+               case IB_WR_RDMA_WRITE:
+                       svc_rdma_put_context(ctxt, 0);
+                       break;
+
                case IB_WR_RDMA_READ:
                        if (test_bit(RDMACTXT_F_LAST_CTXT, &ctxt->flags)) {
                                struct svc_rdma_op_ctxt *read_hdr = ctxt->read_hdr;
@@ -482,6 +520,7 @@ static struct svcxprt_rdma *rdma_create_xprt(struct svc_serv *serv,
        cma_xprt->sc_max_requests = svcrdma_max_requests;
        cma_xprt->sc_sq_depth = svcrdma_max_requests * RPCRDMA_SQ_DEPTH_MULT;
        atomic_set(&cma_xprt->sc_sq_count, 0);
+       atomic_set(&cma_xprt->sc_ctxt_used, 0);
 
        if (!listener) {
                int reqs = cma_xprt->sc_max_requests;
@@ -532,6 +571,7 @@ int svc_rdma_post_recv(struct svcxprt_rdma *xprt)
                BUG_ON(sge_no >= xprt->sc_max_sge);
                page = svc_rdma_get_page();
                ctxt->pages[sge_no] = page;
+               atomic_inc(&xprt->sc_dma_used);
                pa = ib_dma_map_page(xprt->sc_cm_id->device,
                                     page, 0, PAGE_SIZE,
                                     DMA_FROM_DEVICE);
@@ -987,7 +1027,6 @@ static void __svc_rdma_free(struct work_struct *work)
         * cm_id because the device ptr is needed to unmap the dma in
         * svc_rdma_put_context.
         */
-       spin_lock_bh(&rdma->sc_read_complete_lock);
        while (!list_empty(&rdma->sc_read_complete_q)) {
                struct svc_rdma_op_ctxt *ctxt;
                ctxt = list_entry(rdma->sc_read_complete_q.next,
@@ -996,10 +1035,8 @@ static void __svc_rdma_free(struct work_struct *work)
                list_del_init(&ctxt->dto_q);
                svc_rdma_put_context(ctxt, 1);
        }
-       spin_unlock_bh(&rdma->sc_read_complete_lock);
 
        /* Destroy queued, but not processed recv completions */
-       spin_lock_bh(&rdma->sc_rq_dto_lock);
        while (!list_empty(&rdma->sc_rq_dto_q)) {
                struct svc_rdma_op_ctxt *ctxt;
                ctxt = list_entry(rdma->sc_rq_dto_q.next,
@@ -1008,10 +1045,10 @@ static void __svc_rdma_free(struct work_struct *work)
                list_del_init(&ctxt->dto_q);
                svc_rdma_put_context(ctxt, 1);
        }
-       spin_unlock_bh(&rdma->sc_rq_dto_lock);
 
        /* Warn if we leaked a resource or under-referenced */
        WARN_ON(atomic_read(&rdma->sc_ctxt_used) != 0);
+       WARN_ON(atomic_read(&rdma->sc_dma_used) != 0);
 
        /* Destroy the QP if present (not a listener) */
        if (rdma->sc_qp && !IS_ERR(rdma->sc_qp))
@@ -1132,6 +1169,7 @@ void svc_rdma_send_error(struct svcxprt_rdma *xprt, struct rpcrdma_msg *rmsgp,
        length = svc_rdma_xdr_encode_error(xprt, rmsgp, err, va);
 
        /* Prepare SGE for local address */
+       atomic_inc(&xprt->sc_dma_used);
        sge.addr = ib_dma_map_page(xprt->sc_cm_id->device,
                                   p, 0, PAGE_SIZE, DMA_FROM_DEVICE);
        sge.lkey = xprt->sc_phys_mr->lkey;