]> git.karo-electronics.de Git - mv-sheeva.git/blobdiff - net/rds/rdma.c
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wirel...
[mv-sheeva.git] / net / rds / rdma.c
index 1929cb8f17d78f2c6adc601b8e55a8d45072b33d..1a41debca1ce6aa6d57d7c6fda1e135c7babdf30 100644 (file)
@@ -440,28 +440,44 @@ void rds_rdma_unuse(struct rds_sock *rs, u32 r_key, int force)
        rds_mr_put(mr);
 }
 
-void rds_rdma_free_op(struct rds_rdma_op *ro)
+void rds_rdma_free_op(struct rm_rdma_op *ro)
 {
        unsigned int i;
 
-       for (i = 0; i < ro->r_nents; i++) {
-               struct page *page = sg_page(&ro->r_sg[i]);
+       for (i = 0; i < ro->op_nents; i++) {
+               struct page *page = sg_page(&ro->op_sg[i]);
 
                /* Mark page dirty if it was possibly modified, which
                 * is the case for a RDMA_READ which copies from remote
                 * to local memory */
-               if (!ro->r_write) {
+               if (!ro->op_write) {
                        BUG_ON(irqs_disabled());
                        set_page_dirty(page);
                }
                put_page(page);
        }
 
-       kfree(ro->r_notifier);
-       ro->r_notifier = NULL;
-       ro->r_active = 0;
+       kfree(ro->op_notifier);
+       ro->op_notifier = NULL;
+       ro->op_active = 0;
 }
 
+void rds_atomic_free_op(struct rm_atomic_op *ao)
+{
+       struct page *page = sg_page(ao->op_sg);
+
+       /* Mark page dirty if it was possibly modified, which
+        * is the case for a RDMA_READ which copies from remote
+        * to local memory */
+       set_page_dirty(page);
+       put_page(page);
+
+       kfree(ao->op_notifier);
+       ao->op_notifier = NULL;
+       ao->op_active = 0;
+}
+
+
 /*
  * Count the number of pages needed to describe an incoming iovec.
  */
@@ -497,15 +513,16 @@ int rds_rdma_extra_size(struct rds_rdma_args *args)
 }
 
 /*
- * args is a pointer to an in-kernel copy in the sendmsg cmsg.
+ * The application asks for a RDMA transfer.
+ * Extract all arguments and set up the rdma_op
  */
-static int rds_rdma_prepare(struct rds_message *rm,
-                           struct rds_sock *rs,
-                           struct rds_rdma_args *args)
+int rds_cmsg_rdma_args(struct rds_sock *rs, struct rds_message *rm,
+                         struct cmsghdr *cmsg)
 {
+       struct rds_rdma_args *args;
        struct rds_iovec vec;
-       struct rds_rdma_op *op = &rm->rdma.m_rdma_op;
-       unsigned int nr_pages;
+       struct rm_rdma_op *op = &rm->rdma;
+       int nr_pages;
        unsigned int nr_bytes;
        struct page **pages = NULL;
        struct rds_iovec __user *local_vec;
@@ -513,6 +530,11 @@ static int rds_rdma_prepare(struct rds_message *rm,
        unsigned int i, j;
        int ret = 0;
 
+       if (cmsg->cmsg_len < CMSG_LEN(sizeof(struct rds_rdma_args))
+           || rm->rdma.op_active)
+               return -EINVAL;
+
+       args = CMSG_DATA(cmsg);
 
        if (rs->rs_bound_addr == 0) {
                ret = -ENOTCONN; /* XXX not a great errno */
@@ -534,27 +556,28 @@ static int rds_rdma_prepare(struct rds_message *rm,
                goto out;
        }
 
-       op->r_write = !!(args->flags & RDS_RDMA_READWRITE);
-       op->r_fence = !!(args->flags & RDS_RDMA_FENCE);
-       op->r_notify = !!(args->flags & RDS_RDMA_NOTIFY_ME);
-       op->r_active = 1;
-       op->r_recverr = rs->rs_recverr;
+       op->op_write = !!(args->flags & RDS_RDMA_READWRITE);
+       op->op_fence = !!(args->flags & RDS_RDMA_FENCE);
+       op->op_notify = !!(args->flags & RDS_RDMA_NOTIFY_ME);
+       op->op_silent = !!(args->flags & RDS_RDMA_SILENT);
+       op->op_active = 1;
+       op->op_recverr = rs->rs_recverr;
        WARN_ON(!nr_pages);
-       op->r_sg = rds_message_alloc_sgs(rm, nr_pages);
+       op->op_sg = rds_message_alloc_sgs(rm, nr_pages);
 
-       if (op->r_notify || op->r_recverr) {
+       if (op->op_notify || op->op_recverr) {
                /* We allocate an uninitialized notifier here, because
                 * we don't want to do that in the completion handler. We
                 * would have to use GFP_ATOMIC there, and don't want to deal
                 * with failed allocations.
                 */
-               op->r_notifier = kmalloc(sizeof(struct rds_notifier), GFP_KERNEL);
-               if (!op->r_notifier) {
+               op->op_notifier = kmalloc(sizeof(struct rds_notifier), GFP_KERNEL);
+               if (!op->op_notifier) {
                        ret = -ENOMEM;
                        goto out;
                }
-               op->r_notifier->n_user_token = args->user_token;
-               op->r_notifier->n_status = RDS_RDMA_SUCCESS;
+               op->op_notifier->n_user_token = args->user_token;
+               op->op_notifier->n_status = RDS_RDMA_SUCCESS;
        }
 
        /* The cookie contains the R_Key of the remote memory region, and
@@ -564,15 +587,15 @@ static int rds_rdma_prepare(struct rds_message *rm,
         * destination address (which is really an offset into the MR)
         * FIXME: We may want to move this into ib_rdma.c
         */
-       op->r_key = rds_rdma_cookie_key(args->cookie);
-       op->r_remote_addr = args->remote_vec.addr + rds_rdma_cookie_offset(args->cookie);
+       op->op_rkey = rds_rdma_cookie_key(args->cookie);
+       op->op_remote_addr = args->remote_vec.addr + rds_rdma_cookie_offset(args->cookie);
 
        nr_bytes = 0;
 
        rdsdebug("RDS: rdma prepare nr_local %llu rva %llx rkey %x\n",
               (unsigned long long)args->nr_local,
               (unsigned long long)args->remote_vec.addr,
-              op->r_key);
+              op->op_rkey);
 
        local_vec = (struct rds_iovec __user *)(unsigned long) args->local_vec_addr;
 
@@ -595,7 +618,7 @@ static int rds_rdma_prepare(struct rds_message *rm,
                /* If it's a WRITE operation, we want to pin the pages for reading.
                 * If it's a READ operation, we need to pin the pages for writing.
                 */
-               ret = rds_pin_pages(vec.addr, nr, pages, !op->r_write);
+               ret = rds_pin_pages(vec.addr, nr, pages, !op->op_write);
                if (ret < 0)
                        goto out;
 
@@ -608,7 +631,7 @@ static int rds_rdma_prepare(struct rds_message *rm,
                        unsigned int offset = vec.addr & ~PAGE_MASK;
                        struct scatterlist *sg;
 
-                       sg = &op->r_sg[op->r_nents + j];
+                       sg = &op->op_sg[op->op_nents + j];
                        sg_set_page(sg, pages[j],
                                        min_t(unsigned int, vec.bytes, PAGE_SIZE - offset),
                                        offset);
@@ -620,10 +643,9 @@ static int rds_rdma_prepare(struct rds_message *rm,
                        vec.bytes -= sg->length;
                }
 
-               op->r_nents += nr;
+               op->op_nents += nr;
        }
 
-
        if (nr_bytes > args->remote_vec.bytes) {
                rdsdebug("RDS nr_bytes %u remote_bytes %u do not match\n",
                                nr_bytes,
@@ -631,7 +653,7 @@ static int rds_rdma_prepare(struct rds_message *rm,
                ret = -EINVAL;
                goto out;
        }
-       op->r_bytes = nr_bytes;
+       op->op_bytes = nr_bytes;
 
        ret = 0;
 out:
@@ -639,28 +661,9 @@ out:
        if (ret)
                rds_rdma_free_op(op);
 
-       return ret;
-}
-
-/*
- * The application asks for a RDMA transfer.
- * Extract all arguments and set up the rdma_op
- */
-int rds_cmsg_rdma_args(struct rds_sock *rs, struct rds_message *rm,
-                         struct cmsghdr *cmsg)
-{
-       int ret;
-
-       if (cmsg->cmsg_len < CMSG_LEN(sizeof(struct rds_rdma_args)) ||
-           rm->rdma.m_rdma_op.r_active)
-               return -EINVAL;
-
-       ret = rds_rdma_prepare(rm, rs, CMSG_DATA(cmsg));
-       if (ret)
-               return ret;
-
        rds_stats_inc(s_send_rdma);
-       return 0;
+
+       return ret;
 }
 
 /*
@@ -688,7 +691,6 @@ int rds_cmsg_rdma_dest(struct rds_sock *rs, struct rds_message *rm,
         */
        r_key = rds_rdma_cookie_key(rm->m_rdma_cookie);
 
-
        spin_lock_irqsave(&rs->rs_rdma_lock, flags);
        mr = rds_mr_tree_walk(&rs->rs_rdma_keys, r_key, NULL);
        if (!mr)
@@ -699,7 +701,7 @@ int rds_cmsg_rdma_dest(struct rds_sock *rs, struct rds_message *rm,
 
        if (mr) {
                mr->r_trans->sync_mr(mr->r_trans_private, DMA_TO_DEVICE);
-               rm->rdma.m_rdma_mr = mr;
+               rm->rdma.op_rdma_mr = mr;
        }
        return err;
 }
@@ -717,7 +719,7 @@ int rds_cmsg_rdma_map(struct rds_sock *rs, struct rds_message *rm,
            rm->m_rdma_cookie != 0)
                return -EINVAL;
 
-       return __rds_rdma_map(rs, CMSG_DATA(cmsg), &rm->m_rdma_cookie, &rm->rdma.m_rdma_mr);
+       return __rds_rdma_map(rs, CMSG_DATA(cmsg), &rm->m_rdma_cookie, &rm->rdma.op_rdma_mr);
 }
 
 /*
@@ -736,16 +738,39 @@ int rds_cmsg_atomic(struct rds_sock *rs, struct rds_message *rm,
 
        args = CMSG_DATA(cmsg);
 
-       if (cmsg->cmsg_type == RDS_CMSG_ATOMIC_CSWP) {
-               rm->atomic.op_type = RDS_ATOMIC_TYPE_CSWP;
-               rm->atomic.op_swap_add = args->cswp.swap;
-               rm->atomic.op_compare = args->cswp.compare;
-       } else {
+       /* Nonmasked & masked cmsg ops converted to masked hw ops */
+       switch (cmsg->cmsg_type) {
+       case RDS_CMSG_ATOMIC_FADD:
+               rm->atomic.op_type = RDS_ATOMIC_TYPE_FADD;
+               rm->atomic.op_m_fadd.add = args->fadd.add;
+               rm->atomic.op_m_fadd.nocarry_mask = 0;
+               break;
+       case RDS_CMSG_MASKED_ATOMIC_FADD:
                rm->atomic.op_type = RDS_ATOMIC_TYPE_FADD;
-               rm->atomic.op_swap_add = args->fadd.add;
+               rm->atomic.op_m_fadd.add = args->m_fadd.add;
+               rm->atomic.op_m_fadd.nocarry_mask = args->m_fadd.nocarry_mask;
+               break;
+       case RDS_CMSG_ATOMIC_CSWP:
+               rm->atomic.op_type = RDS_ATOMIC_TYPE_CSWP;
+               rm->atomic.op_m_cswp.compare = args->cswp.compare;
+               rm->atomic.op_m_cswp.swap = args->cswp.swap;
+               rm->atomic.op_m_cswp.compare_mask = ~0;
+               rm->atomic.op_m_cswp.swap_mask = ~0;
+               break;
+       case RDS_CMSG_MASKED_ATOMIC_CSWP:
+               rm->atomic.op_type = RDS_ATOMIC_TYPE_CSWP;
+               rm->atomic.op_m_cswp.compare = args->m_cswp.compare;
+               rm->atomic.op_m_cswp.swap = args->m_cswp.swap;
+               rm->atomic.op_m_cswp.compare_mask = args->m_cswp.compare_mask;
+               rm->atomic.op_m_cswp.swap_mask = args->m_cswp.swap_mask;
+               break;
+       default:
+               BUG(); /* should never happen */
        }
 
        rm->atomic.op_notify = !!(args->flags & RDS_RDMA_NOTIFY_ME);
+       rm->atomic.op_silent = !!(args->flags & RDS_RDMA_SILENT);
+       rm->atomic.op_active = 1;
        rm->atomic.op_recverr = rs->rs_recverr;
        rm->atomic.op_sg = rds_message_alloc_sgs(rm, 1);
 
@@ -781,8 +806,6 @@ int rds_cmsg_atomic(struct rds_sock *rs, struct rds_message *rm,
        rm->atomic.op_rkey = rds_rdma_cookie_key(args->cookie);
        rm->atomic.op_remote_addr = args->remote_addr + rds_rdma_cookie_offset(args->cookie);
 
-       rm->atomic.op_active = 1;
-
        return ret;
 err:
        if (page)