Commit 39770264 authored by Bryan O'Sullivan's avatar Bryan O'Sullivan Committed by Roland Dreier

IB/ipath: fix null deref during rdma ops

The problem was that node A's sending thread, which handles sending RDMA
read response data, would write the trigger word, the last packet would
be sent, node B would send a new RDMA read request, node A's interrupt
handler would initialize s_rdma_sge, then node A's sending thread would
update s_rdma_sge.  This didn't happen very often naturally but was more
frequent with 1 byte RDMA reads.  Rather than adding more locking or
increasing the QP structure size and copying sge data, I modified the
copy routine to update the pointers before writing the trigger word to
avoid the update race.
Signed-off-by: default avatarRalph Campbell <ralphc@pathscale.com>
Signed-off-by: default avatarBryan O'Sullivan <bos@pathscale.com>
Signed-off-by: default avatarRoland Dreier <rolandd@cisco.com>
parent 41c75a19
...@@ -872,12 +872,13 @@ static void copy_io(u32 __iomem *piobuf, struct ipath_sge_state *ss, ...@@ -872,12 +872,13 @@ static void copy_io(u32 __iomem *piobuf, struct ipath_sge_state *ss,
update_sge(ss, len); update_sge(ss, len);
length -= len; length -= len;
} }
/* Update address before sending packet. */
update_sge(ss, length);
/* must flush early everything before trigger word */ /* must flush early everything before trigger word */
ipath_flush_wc(); ipath_flush_wc();
__raw_writel(last, piobuf); __raw_writel(last, piobuf);
/* be sure trigger word is written */ /* be sure trigger word is written */
ipath_flush_wc(); ipath_flush_wc();
update_sge(ss, length);
} }
/** /**
...@@ -943,17 +944,18 @@ int ipath_verbs_send(struct ipath_devdata *dd, u32 hdrwords, ...@@ -943,17 +944,18 @@ int ipath_verbs_send(struct ipath_devdata *dd, u32 hdrwords,
if (likely(ss->num_sge == 1 && len <= ss->sge.length && if (likely(ss->num_sge == 1 && len <= ss->sge.length &&
!((unsigned long)ss->sge.vaddr & (sizeof(u32) - 1)))) { !((unsigned long)ss->sge.vaddr & (sizeof(u32) - 1)))) {
u32 w; u32 w;
u32 *addr = (u32 *) ss->sge.vaddr;
/* Update address before sending packet. */
update_sge(ss, len);
/* Need to round up for the last dword in the packet. */ /* Need to round up for the last dword in the packet. */
w = (len + 3) >> 2; w = (len + 3) >> 2;
__iowrite32_copy(piobuf, ss->sge.vaddr, w - 1); __iowrite32_copy(piobuf, addr, w - 1);
/* must flush early everything before trigger word */ /* must flush early everything before trigger word */
ipath_flush_wc(); ipath_flush_wc();
__raw_writel(((u32 *) ss->sge.vaddr)[w - 1], __raw_writel(addr[w - 1], piobuf + w - 1);
piobuf + w - 1);
/* be sure trigger word is written */ /* be sure trigger word is written */
ipath_flush_wc(); ipath_flush_wc();
update_sge(ss, len);
ret = 0; ret = 0;
goto bail; goto bail;
} }
......
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