aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/infiniband/hw/ipath/ipath_driver.c
diff options
context:
space:
mode:
authorBryan O'Sullivan <bos@pathscale.com>2006-07-01 07:36:05 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2006-07-01 12:56:00 -0400
commitf5f99929ac584126ef3f47d805dc619abc54768c (patch)
tree31c6030139a2094915d5fd3ac1d57d491fa437b0 /drivers/infiniband/hw/ipath/ipath_driver.c
parent13aef4942c291742064c1d5ac71df6493c4a00a9 (diff)
[PATCH] IB/ipath: fixed bug 9776 for real
The problem was that I was updating the head register multiple times in the rcvhdrq processing loop, and setting the counter on each update. Since that meant that the tail register was ahead of head for all but the last update, we would get extra interrupts. The fix was to not write the counter value except on the last update. I also changed to update rcvhdrhead and rcvegrindexhead at most every 16 packets, if there were lots of packets in the queue (and of course, on the last packet, regardless). I also made some small cleanups while debugging this. With these changes, xeon/monty typically sees two openib packets per interrupt on sdp and ipoib, opteron/monty is about 1.25 pkts/intr. I'm seeing about 3800 Mbit/s monty/xeon, and 5000-5100 opteron/monty with netperf sdp. Netpipe doesn't show as good as that, peaking at about 4400 on opteron/monty sdp. Plain ipoib xeon is about 2100+ netperf, opteron 2900+, at 128KB Signed-off-by: olson@eng-12.pathscale.com Signed-off-by: Bryan O'Sullivan <bos@pathscale.com> Cc: "Michael S. Tsirkin" <mst@mellanox.co.il> Cc: Roland Dreier <rolandd@cisco.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'drivers/infiniband/hw/ipath/ipath_driver.c')
-rw-r--r--drivers/infiniband/hw/ipath/ipath_driver.c33
1 files changed, 22 insertions, 11 deletions
diff --git a/drivers/infiniband/hw/ipath/ipath_driver.c b/drivers/infiniband/hw/ipath/ipath_driver.c
index eb745234d8c3..e2b0bc8ebaf4 100644
--- a/drivers/infiniband/hw/ipath/ipath_driver.c
+++ b/drivers/infiniband/hw/ipath/ipath_driver.c
@@ -870,7 +870,7 @@ void ipath_kreceive(struct ipath_devdata *dd)
870 const u32 maxcnt = dd->ipath_rcvhdrcnt * rsize; /* words */ 870 const u32 maxcnt = dd->ipath_rcvhdrcnt * rsize; /* words */
871 u32 etail = -1, l, hdrqtail; 871 u32 etail = -1, l, hdrqtail;
872 struct ips_message_header *hdr; 872 struct ips_message_header *hdr;
873 u32 eflags, i, etype, tlen, pkttot = 0; 873 u32 eflags, i, etype, tlen, pkttot = 0, updegr=0;
874 static u64 totcalls; /* stats, may eventually remove */ 874 static u64 totcalls; /* stats, may eventually remove */
875 char emsg[128]; 875 char emsg[128];
876 876
@@ -884,14 +884,14 @@ void ipath_kreceive(struct ipath_devdata *dd)
884 if (test_and_set_bit(0, &dd->ipath_rcv_pending)) 884 if (test_and_set_bit(0, &dd->ipath_rcv_pending))
885 goto bail; 885 goto bail;
886 886
887 if (dd->ipath_port0head == 887 l = dd->ipath_port0head;
888 (u32)le64_to_cpu(*dd->ipath_hdrqtailptr)) 888 if (l == (u32)le64_to_cpu(*dd->ipath_hdrqtailptr))
889 goto done; 889 goto done;
890 890
891 /* read only once at start for performance */ 891 /* read only once at start for performance */
892 hdrqtail = (u32)le64_to_cpu(*dd->ipath_hdrqtailptr); 892 hdrqtail = (u32)le64_to_cpu(*dd->ipath_hdrqtailptr);
893 893
894 for (i = 0, l = dd->ipath_port0head; l != hdrqtail; i++) { 894 for (i = 0; l != hdrqtail; i++) {
895 u32 qp; 895 u32 qp;
896 u8 *bthbytes; 896 u8 *bthbytes;
897 897
@@ -1002,15 +1002,26 @@ void ipath_kreceive(struct ipath_devdata *dd)
1002 l += rsize; 1002 l += rsize;
1003 if (l >= maxcnt) 1003 if (l >= maxcnt)
1004 l = 0; 1004 l = 0;
1005 if (etype != RCVHQ_RCV_TYPE_EXPECTED)
1006 updegr = 1;
1005 /* 1007 /*
1006 * update for each packet, to help prevent overflows if we 1008 * update head regs on last packet, and every 16 packets.
1007 * have lots of packets. 1009 * Reduce bus traffic, while still trying to prevent
1010 * rcvhdrq overflows, for when the queue is nearly full
1008 */ 1011 */
1009 (void)ipath_write_ureg(dd, ur_rcvhdrhead, 1012 if (l == hdrqtail || (i && !(i&0xf))) {
1010 dd->ipath_rhdrhead_intr_off | l, 0); 1013 u64 lval;
1011 if (etype != RCVHQ_RCV_TYPE_EXPECTED) 1014 if (l == hdrqtail) /* want interrupt only on last */
1012 (void)ipath_write_ureg(dd, ur_rcvegrindexhead, 1015 lval = dd->ipath_rhdrhead_intr_off | l;
1013 etail, 0); 1016 else
1017 lval = l;
1018 (void)ipath_write_ureg(dd, ur_rcvhdrhead, lval, 0);
1019 if (updegr) {
1020 (void)ipath_write_ureg(dd, ur_rcvegrindexhead,
1021 etail, 0);
1022 updegr = 0;
1023 }
1024 }
1014 } 1025 }
1015 1026
1016 pkttot += i; 1027 pkttot += i;