From f5f99929ac584126ef3f47d805dc619abc54768c Mon Sep 17 00:00:00 2001 From: Bryan O'Sullivan Date: Sat, 1 Jul 2006 04:36:05 -0700 Subject: [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 Cc: "Michael S. Tsirkin" Cc: Roland Dreier Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/infiniband/hw/ipath/ipath_driver.c | 33 ++++++++++++++++++++---------- 1 file changed, 22 insertions(+), 11 deletions(-) (limited to 'drivers/infiniband/hw/ipath/ipath_driver.c') 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) const u32 maxcnt = dd->ipath_rcvhdrcnt * rsize; /* words */ u32 etail = -1, l, hdrqtail; struct ips_message_header *hdr; - u32 eflags, i, etype, tlen, pkttot = 0; + u32 eflags, i, etype, tlen, pkttot = 0, updegr=0; static u64 totcalls; /* stats, may eventually remove */ char emsg[128]; @@ -884,14 +884,14 @@ void ipath_kreceive(struct ipath_devdata *dd) if (test_and_set_bit(0, &dd->ipath_rcv_pending)) goto bail; - if (dd->ipath_port0head == - (u32)le64_to_cpu(*dd->ipath_hdrqtailptr)) + l = dd->ipath_port0head; + if (l == (u32)le64_to_cpu(*dd->ipath_hdrqtailptr)) goto done; /* read only once at start for performance */ hdrqtail = (u32)le64_to_cpu(*dd->ipath_hdrqtailptr); - for (i = 0, l = dd->ipath_port0head; l != hdrqtail; i++) { + for (i = 0; l != hdrqtail; i++) { u32 qp; u8 *bthbytes; @@ -1002,15 +1002,26 @@ void ipath_kreceive(struct ipath_devdata *dd) l += rsize; if (l >= maxcnt) l = 0; + if (etype != RCVHQ_RCV_TYPE_EXPECTED) + updegr = 1; /* - * update for each packet, to help prevent overflows if we - * have lots of packets. + * update head regs on last packet, and every 16 packets. + * Reduce bus traffic, while still trying to prevent + * rcvhdrq overflows, for when the queue is nearly full */ - (void)ipath_write_ureg(dd, ur_rcvhdrhead, - dd->ipath_rhdrhead_intr_off | l, 0); - if (etype != RCVHQ_RCV_TYPE_EXPECTED) - (void)ipath_write_ureg(dd, ur_rcvegrindexhead, - etail, 0); + if (l == hdrqtail || (i && !(i&0xf))) { + u64 lval; + if (l == hdrqtail) /* want interrupt only on last */ + lval = dd->ipath_rhdrhead_intr_off | l; + else + lval = l; + (void)ipath_write_ureg(dd, ur_rcvhdrhead, lval, 0); + if (updegr) { + (void)ipath_write_ureg(dd, ur_rcvegrindexhead, + etail, 0); + updegr = 0; + } + } } pkttot += i; -- cgit v1.2.2