IB/qib: Fix a possible data corruption when receiving packets
Ram Vepa [Fri, 23 Dec 2011 13:01:43 +0000 (08:01 -0500)]
commit eddfb675256f49d14e8c5763098afe3eb2c93701 upstream.

Prevent a receive data corruption by ensuring that the write to update
the rcvhdrheadn register to generate an interrupt is at the very end
of the receive processing.

Signed-off-by: Ramkrishna Vepa <ram.vepa@qlogic.com>
Signed-off-by: Mike Marciniszyn <mike.marciniszyn@qlogic.com>
Signed-off-by: Roland Dreier <roland@purestorage.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>

drivers/infiniband/hw/qib/qib_iba6120.c
drivers/infiniband/hw/qib/qib_iba7220.c
drivers/infiniband/hw/qib/qib_iba7322.c

index d8ca0a0..65df26c 100644 (file)
@@ -2076,9 +2076,11 @@ static void qib_6120_config_ctxts(struct qib_devdata *dd)
 static void qib_update_6120_usrhead(struct qib_ctxtdata *rcd, u64 hd,
                                    u32 updegr, u32 egrhd, u32 npkts)
 {
-       qib_write_ureg(rcd->dd, ur_rcvhdrhead, hd, rcd->ctxt);
        if (updegr)
                qib_write_ureg(rcd->dd, ur_rcvegrindexhead, egrhd, rcd->ctxt);
+       mmiowb();
+       qib_write_ureg(rcd->dd, ur_rcvhdrhead, hd, rcd->ctxt);
+       mmiowb();
 }
 
 static u32 qib_6120_hdrqempty(struct qib_ctxtdata *rcd)
index e1f9474..4250c05 100644 (file)
@@ -2724,9 +2724,11 @@ static int qib_7220_set_loopback(struct qib_pportdata *ppd, const char *what)
 static void qib_update_7220_usrhead(struct qib_ctxtdata *rcd, u64 hd,
                                    u32 updegr, u32 egrhd, u32 npkts)
 {
-       qib_write_ureg(rcd->dd, ur_rcvhdrhead, hd, rcd->ctxt);
        if (updegr)
                qib_write_ureg(rcd->dd, ur_rcvegrindexhead, egrhd, rcd->ctxt);
+       mmiowb();
+       qib_write_ureg(rcd->dd, ur_rcvhdrhead, hd, rcd->ctxt);
+       mmiowb();
 }
 
 static u32 qib_7220_hdrqempty(struct qib_ctxtdata *rcd)
index 5ea9ece..b7c3c7d 100644 (file)
@@ -4084,10 +4084,12 @@ static void qib_update_7322_usrhead(struct qib_ctxtdata *rcd, u64 hd,
         */
        if (hd >> IBA7322_HDRHEAD_PKTINT_SHIFT)
                adjust_rcv_timeout(rcd, npkts);
-       qib_write_ureg(rcd->dd, ur_rcvhdrhead, hd, rcd->ctxt);
-       qib_write_ureg(rcd->dd, ur_rcvhdrhead, hd, rcd->ctxt);
        if (updegr)
                qib_write_ureg(rcd->dd, ur_rcvegrindexhead, egrhd, rcd->ctxt);
+       mmiowb();
+       qib_write_ureg(rcd->dd, ur_rcvhdrhead, hd, rcd->ctxt);
+       qib_write_ureg(rcd->dd, ur_rcvhdrhead, hd, rcd->ctxt);
+       mmiowb();
 }
 
 static u32 qib_7322_hdrqempty(struct qib_ctxtdata *rcd)