Commit eba8ff66 authored by Chuck Lever's avatar Chuck Lever Committed by Anna Schumaker

xprtrdma: Move credit update to RPC reply handler

Reduce work in the receive CQ handler, which can be run at hardware
interrupt level, by moving the RPC/RDMA credit update logic to the
RPC reply handler.

This has some additional benefits: More header sanity checking is
done before trusting the incoming credit value, and the receive CQ
handler no longer touches the RPC/RDMA header (the CPU stalls while
waiting for the header contents to be brought into the cache).

This further extends work begun by commit e7ce710a ("xprtrdma:
Avoid deadlock when credit window is reset").
Signed-off-by: default avatarChuck Lever <chuck.lever@oracle.com>
Reviewed-by: default avatarSteve Wise <swise@opengridcomputing.com>
Signed-off-by: default avatarAnna Schumaker <Anna.Schumaker@Netapp.com>
parent 3eb35810
...@@ -736,7 +736,7 @@ rpcrdma_reply_handler(struct rpcrdma_rep *rep) ...@@ -736,7 +736,7 @@ rpcrdma_reply_handler(struct rpcrdma_rep *rep)
struct rpc_xprt *xprt = rep->rr_xprt; struct rpc_xprt *xprt = rep->rr_xprt;
struct rpcrdma_xprt *r_xprt = rpcx_to_rdmax(xprt); struct rpcrdma_xprt *r_xprt = rpcx_to_rdmax(xprt);
__be32 *iptr; __be32 *iptr;
int rdmalen, status; int credits, rdmalen, status;
unsigned long cwnd; unsigned long cwnd;
/* Check status. If bad, signal disconnect and return rep to pool */ /* Check status. If bad, signal disconnect and return rep to pool */
...@@ -871,8 +871,14 @@ rpcrdma_reply_handler(struct rpcrdma_rep *rep) ...@@ -871,8 +871,14 @@ rpcrdma_reply_handler(struct rpcrdma_rep *rep)
break; break;
} }
credits = be32_to_cpu(headerp->rm_credit);
if (credits == 0)
credits = 1; /* don't deadlock */
else if (credits > r_xprt->rx_buf.rb_max_requests)
credits = r_xprt->rx_buf.rb_max_requests;
cwnd = xprt->cwnd; cwnd = xprt->cwnd;
xprt->cwnd = atomic_read(&r_xprt->rx_buf.rb_credits) << RPC_CWNDSHIFT; xprt->cwnd = credits << RPC_CWNDSHIFT;
if (xprt->cwnd > cwnd) if (xprt->cwnd > cwnd)
xprt_release_rqst_cong(rqst->rq_task); xprt_release_rqst_cong(rqst->rq_task);
......
...@@ -49,6 +49,7 @@ ...@@ -49,6 +49,7 @@
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/prefetch.h>
#include <asm/bitops.h> #include <asm/bitops.h>
#include "xprt_rdma.h" #include "xprt_rdma.h"
...@@ -298,17 +299,7 @@ rpcrdma_recvcq_process_wc(struct ib_wc *wc, struct list_head *sched_list) ...@@ -298,17 +299,7 @@ rpcrdma_recvcq_process_wc(struct ib_wc *wc, struct list_head *sched_list)
rep->rr_len = wc->byte_len; rep->rr_len = wc->byte_len;
ib_dma_sync_single_for_cpu(rdmab_to_ia(rep->rr_buffer)->ri_id->device, ib_dma_sync_single_for_cpu(rdmab_to_ia(rep->rr_buffer)->ri_id->device,
rep->rr_iov.addr, rep->rr_len, DMA_FROM_DEVICE); rep->rr_iov.addr, rep->rr_len, DMA_FROM_DEVICE);
prefetch(rep->rr_base);
if (rep->rr_len >= 16) {
struct rpcrdma_msg *p = (struct rpcrdma_msg *)rep->rr_base;
unsigned int credits = ntohl(p->rm_credit);
if (credits == 0)
credits = 1; /* don't deadlock */
else if (credits > rep->rr_buffer->rb_max_requests)
credits = rep->rr_buffer->rb_max_requests;
atomic_set(&rep->rr_buffer->rb_credits, credits);
}
out_schedule: out_schedule:
list_add_tail(&rep->rr_list, sched_list); list_add_tail(&rep->rr_list, sched_list);
...@@ -480,7 +471,6 @@ rpcrdma_conn_upcall(struct rdma_cm_id *id, struct rdma_cm_event *event) ...@@ -480,7 +471,6 @@ rpcrdma_conn_upcall(struct rdma_cm_id *id, struct rdma_cm_event *event)
case RDMA_CM_EVENT_DEVICE_REMOVAL: case RDMA_CM_EVENT_DEVICE_REMOVAL:
connstate = -ENODEV; connstate = -ENODEV;
connected: connected:
atomic_set(&rpcx_to_rdmax(ep->rep_xprt)->rx_buf.rb_credits, 1);
dprintk("RPC: %s: %sconnected\n", dprintk("RPC: %s: %sconnected\n",
__func__, connstate > 0 ? "" : "dis"); __func__, connstate > 0 ? "" : "dis");
ep->rep_connected = connstate; ep->rep_connected = connstate;
...@@ -1186,7 +1176,6 @@ rpcrdma_buffer_create(struct rpcrdma_buffer *buf, struct rpcrdma_ep *ep, ...@@ -1186,7 +1176,6 @@ rpcrdma_buffer_create(struct rpcrdma_buffer *buf, struct rpcrdma_ep *ep,
buf->rb_max_requests = cdata->max_requests; buf->rb_max_requests = cdata->max_requests;
spin_lock_init(&buf->rb_lock); spin_lock_init(&buf->rb_lock);
atomic_set(&buf->rb_credits, 1);
/* Need to allocate: /* Need to allocate:
* 1. arrays for send and recv pointers * 1. arrays for send and recv pointers
......
...@@ -248,7 +248,6 @@ struct rpcrdma_req { ...@@ -248,7 +248,6 @@ struct rpcrdma_req {
*/ */
struct rpcrdma_buffer { struct rpcrdma_buffer {
spinlock_t rb_lock; /* protects indexes */ spinlock_t rb_lock; /* protects indexes */
atomic_t rb_credits; /* most recent server credits */
int rb_max_requests;/* client max requests */ int rb_max_requests;/* client max requests */
struct list_head rb_mws; /* optional memory windows/fmrs/frmrs */ struct list_head rb_mws; /* optional memory windows/fmrs/frmrs */
struct list_head rb_all; struct list_head rb_all;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment