static void rpcrdma_recvcq_process_wc(struct ib_wc *wc) { struct rpcrdma_rep *rep = (struct rpcrdma_rep *)(unsigned long)wc->wr_id; /* WARNING: Only wr_id and status are reliable at this point */ if (wc->status != IB_WC_SUCCESS) goto out_fail; /* status == SUCCESS means all fields in wc are trustworthy */ if (wc->opcode != IB_WC_RECV) return; dprintk("RPC: %s: rep %p opcode 'recv', length %u: success\n", __func__, rep, wc->byte_len); rep->rr_len = wc->byte_len; ib_dma_sync_single_for_cpu(rep->rr_device, rdmab_addr(rep->rr_rdmabuf), rep->rr_len, DMA_FROM_DEVICE); prefetch(rdmab_to_msg(rep->rr_rdmabuf)); out_schedule: queue_work(rpcrdma_receive_wq, &rep->rr_work); return; out_fail: if (wc->status != IB_WC_WR_FLUSH_ERR) pr_err("RPC: %s: rep %p: %s\n", __func__, rep, ib_wc_status_msg(wc->status)); rep->rr_len = RPCRDMA_BAD_LEN; goto out_schedule; }
/* Perform basic sanity checking to avoid using garbage * to update the credit grant value. */ static void rpcrdma_update_granted_credits(struct rpcrdma_rep *rep) { struct rpcrdma_msg *rmsgp = rdmab_to_msg(rep->rr_rdmabuf); struct rpcrdma_buffer *buffer = &rep->rr_rxprt->rx_buf; u32 credits; if (rep->rr_len < RPCRDMA_HDRLEN_ERR) return; credits = be32_to_cpu(rmsgp->rm_credit); if (credits == 0) credits = 1; /* don't deadlock */ else if (credits > buffer->rb_max_requests) credits = buffer->rb_max_requests; atomic_set(&buffer->rb_credits, credits); }