From: Amir Vadai Date: Tue, 14 Dec 2010 06:48:42 +0000 (+0200) Subject: sdp: RdmaRdCompl not sent sometimes X-Git-Tag: v4.1.12-92~264^2~5^2~57 X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=651199b144968e9829615567e016f9db109d3fe6;p=users%2Fjedix%2Flinux-maple.git sdp: RdmaRdCompl not sent sometimes When SrcAvailCancel is handled after RDMA finshed and before sending RdmaRdCompl, RdmaRdCompl won't be sent, and a data corruption will occur. Made sure that all sdp_abort_rx_srcavail will send RdmaRdCompl if needed. Signed-off-by: Amir Vadai --- diff --git a/drivers/infiniband/ulp/sdp/sdp.h b/drivers/infiniband/ulp/sdp/sdp.h index 2c967384adfd9..5bce6caa1c650 100644 --- a/drivers/infiniband/ulp/sdp/sdp.h +++ b/drivers/infiniband/ulp/sdp/sdp.h @@ -259,6 +259,7 @@ struct rx_srcavail_state { /* Advertised buffer stuff */ u32 mseq; u32 reported; + u32 copied; u32 len; u32 rkey; u64 vaddr; @@ -909,6 +910,7 @@ void sdp_reset(struct sock *sk); int sdp_tx_wait_memory(struct sdp_sock *ssk, long *timeo_p, int *credits_needed); void sdp_skb_entail(struct sock *sk, struct sk_buff *skb); void sdp_start_cma_timewait_timeout(struct sdp_sock *ssk, int timeo); +int sdp_abort_rx_srcavail(struct sock *sk); extern struct rw_semaphore device_removal_lock; /* sdp_proc.c */ @@ -945,10 +947,10 @@ void sdp_handle_sendsm(struct sdp_sock *ssk, u32 mseq_ack); void sdp_handle_rdma_read_compl(struct sdp_sock *ssk, u32 mseq_ack, u32 bytes_completed); int sdp_handle_rdma_read_cqe(struct sdp_sock *ssk); -int sdp_rdma_to_iovec(struct sock *sk, struct iovec *iov, struct sk_buff *skb, - unsigned long *used, u32 offset); +int sdp_rdma_to_iovec(struct sock *sk, struct iovec *iov, int msg_iovlen, + struct sk_buff *skb, unsigned long *used, u32 offset); int sdp_post_rdma_rd_compl(struct sock *sk, - struct rx_srcavail_state *rx_sa, u32 offset); + struct rx_srcavail_state *rx_sa); int sdp_post_sendsm(struct sock *sk); void sdp_abort_srcavail(struct sock *sk); void sdp_abort_rdma_read(struct sock *sk); diff --git a/drivers/infiniband/ulp/sdp/sdp_main.c b/drivers/infiniband/ulp/sdp/sdp_main.c index 113946376b879..616fb72b5f4c2 100644 --- a/drivers/infiniband/ulp/sdp/sdp_main.c +++ b/drivers/infiniband/ulp/sdp/sdp_main.c @@ -125,8 +125,6 @@ spinlock_t sock_list_lock; DECLARE_RWSEM(device_removal_lock); -static inline int sdp_abort_rx_srcavail(struct sock *sk); - static inline unsigned int sdp_keepalive_time_when(const struct sdp_sock *ssk) { return ssk->keepalive_time ? : sdp_keepalive_time; @@ -2169,7 +2167,7 @@ fin: return err; } -static inline int sdp_abort_rx_srcavail(struct sock *sk) +int sdp_abort_rx_srcavail(struct sock *sk) { struct sdp_sock *ssk = sdp_sk(sk); struct sdp_bsdh *h = @@ -2179,6 +2177,11 @@ static inline int sdp_abort_rx_srcavail(struct sock *sk) h->mid = SDP_MID_DATA; + if (sdp_post_rdma_rd_compl(sk, ssk->rx_sa)) { + sdp_warn(sk, "Couldn't send RdmaRdComp - " + "data corruption might occur\n"); + } + RX_SRCAVAIL_STATE(ssk->rx_sa->skb) = NULL; kfree(ssk->rx_sa); ssk->rx_sa = NULL; @@ -2458,7 +2461,7 @@ sdp_mid_data: if (rx_sa && offset >= skb->len) { /* No more payload - start rdma copy */ sdp_dbg_data(sk, "RDMA copy of 0x%lx bytes\n", used); - err = sdp_rdma_to_iovec(sk, msg->msg_iov, skb, + err = sdp_rdma_to_iovec(sk, msg->msg_iov, msg->msg_iovlen, skb, &used, offset); if (unlikely(err)) { /* ssk->rx_sa might had been freed when @@ -2482,6 +2485,7 @@ sdp_mid_data: /* TODO: skip header? */ msg->msg_iov, used); if (rx_sa && !(flags & MSG_PEEK)) { + rx_sa->copied += used; rx_sa->reported += used; } } @@ -2509,7 +2513,7 @@ skip_copy: if (rx_sa && !(flags & MSG_PEEK)) { - rc = sdp_post_rdma_rd_compl(sk, rx_sa, offset); + rc = sdp_post_rdma_rd_compl(sk, rx_sa); if (unlikely(rc)) { sdp_abort_rx_srcavail(sk); rx_sa = NULL; diff --git a/drivers/infiniband/ulp/sdp/sdp_rx.c b/drivers/infiniband/ulp/sdp/sdp_rx.c index 1bba5db535ecf..5de64928146dd 100644 --- a/drivers/infiniband/ulp/sdp/sdp_rx.c +++ b/drivers/infiniband/ulp/sdp/sdp_rx.c @@ -503,10 +503,7 @@ static int sdp_process_rx_ctl_skb(struct sdp_sock *ssk, struct sk_buff *skb) case SDP_MID_SRCAVAIL_CANCEL: if (ssk->rx_sa && after(ntohl(h->mseq), ssk->rx_sa->mseq) && !ssk->tx_ring.rdma_inflight) { - sdp_dbg(sk, "Handling SrcAvailCancel - post SendSM\n"); - RX_SRCAVAIL_STATE(ssk->rx_sa->skb) = NULL; - kfree(ssk->rx_sa); - ssk->rx_sa = NULL; + sdp_abort_rx_srcavail(sk); sdp_post_sendsm(sk); } break; diff --git a/drivers/infiniband/ulp/sdp/sdp_zcopy.c b/drivers/infiniband/ulp/sdp/sdp_zcopy.c index df8607d8cd6c9..b80e52c19bc49 100644 --- a/drivers/infiniband/ulp/sdp/sdp_zcopy.c +++ b/drivers/infiniband/ulp/sdp/sdp_zcopy.c @@ -274,22 +274,21 @@ static int sdp_wait_rdma_wr_finished(struct sdp_sock *ssk) return rc; } -int sdp_post_rdma_rd_compl(struct sock *sk, - struct rx_srcavail_state *rx_sa, u32 offset) +int sdp_post_rdma_rd_compl(struct sock *sk, struct rx_srcavail_state *rx_sa) { struct sk_buff *skb; - int copied = offset - rx_sa->reported; + int unreported = rx_sa->copied - rx_sa->reported; - if (offset <= rx_sa->reported) + if (rx_sa->copied <= rx_sa->reported) return 0; - skb = sdp_alloc_skb_rdmardcompl(sk, copied, 0); + skb = sdp_alloc_skb_rdmardcompl(sk, unreported, 0); if (unlikely(!skb)) return -ENOMEM; sdp_skb_entail(sk, skb); - rx_sa->reported += copied; + rx_sa->reported += unreported; sdp_post_sends(sdp_sk(sk), 0); @@ -561,20 +560,24 @@ static int sdp_post_rdma_read(struct sock *sk, struct rx_srcavail_state *rx_sa, return rc; } -int sdp_rdma_to_iovec(struct sock *sk, struct iovec *iov, struct sk_buff *skb, - unsigned long *used, u32 offset) +int sdp_rdma_to_iovec(struct sock *sk, struct iovec *iov, int msg_iovlen, + struct sk_buff *skb, unsigned long *used, u32 offset) { struct sdp_sock *ssk = sdp_sk(sk); struct rx_srcavail_state *rx_sa = RX_SRCAVAIL_STATE(skb); int rc = 0; int len = *used; int copied; + int i = 0; if (unlikely(!ssk->ib_device)) return -ENODEV; - while (!iov->iov_len) + while (!iov->iov_len) { ++iov; + i++; + } + WARN_ON(i >= msg_iovlen); sdp_dbg_data(sk_ssk(ssk), "preparing RDMA read." " len: 0x%x. buffer len: 0x%zx\n", len, iov->iov_len); @@ -613,6 +616,7 @@ int sdp_rdma_to_iovec(struct sock *sk, struct iovec *iov, struct sk_buff *skb, sdp_update_iov_used(sk, iov, copied); atomic_add(copied, &ssk->rcv_nxt); *used = copied; + rx_sa->copied += copied; err_wait: ssk->tx_ring.rdma_inflight = NULL;