diff options
Diffstat (limited to 'drivers/infiniband')
-rw-r--r-- | drivers/infiniband/hw/ipath/ipath_driver.c | 33 | ||||
-rw-r--r-- | drivers/infiniband/hw/ipath/ipath_intr.c | 40 |
2 files changed, 42 insertions, 31 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; |
diff --git a/drivers/infiniband/hw/ipath/ipath_intr.c b/drivers/infiniband/hw/ipath/ipath_intr.c index e8c8a25cd922..bad20a395265 100644 --- a/drivers/infiniband/hw/ipath/ipath_intr.c +++ b/drivers/infiniband/hw/ipath/ipath_intr.c | |||
@@ -383,7 +383,7 @@ static unsigned handle_frequent_errors(struct ipath_devdata *dd, | |||
383 | return supp_msgs; | 383 | return supp_msgs; |
384 | } | 384 | } |
385 | 385 | ||
386 | static void handle_errors(struct ipath_devdata *dd, ipath_err_t errs) | 386 | static int handle_errors(struct ipath_devdata *dd, ipath_err_t errs) |
387 | { | 387 | { |
388 | char msg[512]; | 388 | char msg[512]; |
389 | u64 ignore_this_time = 0; | 389 | u64 ignore_this_time = 0; |
@@ -480,7 +480,7 @@ static void handle_errors(struct ipath_devdata *dd, ipath_err_t errs) | |||
480 | INFINIPATH_E_IBSTATUSCHANGED); | 480 | INFINIPATH_E_IBSTATUSCHANGED); |
481 | } | 481 | } |
482 | if (!errs) | 482 | if (!errs) |
483 | return; | 483 | return 0; |
484 | 484 | ||
485 | if (!noprint) | 485 | if (!noprint) |
486 | /* | 486 | /* |
@@ -604,9 +604,7 @@ static void handle_errors(struct ipath_devdata *dd, ipath_err_t errs) | |||
604 | wake_up_interruptible(&ipath_sma_state_wait); | 604 | wake_up_interruptible(&ipath_sma_state_wait); |
605 | } | 605 | } |
606 | 606 | ||
607 | if (chkerrpkts) | 607 | return chkerrpkts; |
608 | /* process possible error packets in hdrq */ | ||
609 | ipath_kreceive(dd); | ||
610 | } | 608 | } |
611 | 609 | ||
612 | /* this is separate to allow for better optimization of ipath_intr() */ | 610 | /* this is separate to allow for better optimization of ipath_intr() */ |
@@ -765,10 +763,10 @@ static void handle_urcv(struct ipath_devdata *dd, u32 istat) | |||
765 | irqreturn_t ipath_intr(int irq, void *data, struct pt_regs *regs) | 763 | irqreturn_t ipath_intr(int irq, void *data, struct pt_regs *regs) |
766 | { | 764 | { |
767 | struct ipath_devdata *dd = data; | 765 | struct ipath_devdata *dd = data; |
768 | u32 istat; | 766 | u32 istat, chk0rcv = 0; |
769 | ipath_err_t estat = 0; | 767 | ipath_err_t estat = 0; |
770 | irqreturn_t ret; | 768 | irqreturn_t ret; |
771 | u32 p0bits; | 769 | u32 p0bits, oldhead; |
772 | static unsigned unexpected = 0; | 770 | static unsigned unexpected = 0; |
773 | static const u32 port0rbits = (1U<<INFINIPATH_I_RCVAVAIL_SHIFT) | | 771 | static const u32 port0rbits = (1U<<INFINIPATH_I_RCVAVAIL_SHIFT) | |
774 | (1U<<INFINIPATH_I_RCVURG_SHIFT); | 772 | (1U<<INFINIPATH_I_RCVURG_SHIFT); |
@@ -810,9 +808,8 @@ irqreturn_t ipath_intr(int irq, void *data, struct pt_regs *regs) | |||
810 | * interrupts. We clear the interrupts first so that we don't | 808 | * interrupts. We clear the interrupts first so that we don't |
811 | * lose intr for later packets that arrive while we are processing. | 809 | * lose intr for later packets that arrive while we are processing. |
812 | */ | 810 | */ |
813 | if (dd->ipath_port0head != | 811 | oldhead = dd->ipath_port0head; |
814 | (u32)le64_to_cpu(*dd->ipath_hdrqtailptr)) { | 812 | if (oldhead != (u32) le64_to_cpu(*dd->ipath_hdrqtailptr)) { |
815 | u32 oldhead = dd->ipath_port0head; | ||
816 | if (dd->ipath_flags & IPATH_GPIO_INTR) { | 813 | if (dd->ipath_flags & IPATH_GPIO_INTR) { |
817 | ipath_write_kreg(dd, dd->ipath_kregs->kr_gpio_clear, | 814 | ipath_write_kreg(dd, dd->ipath_kregs->kr_gpio_clear, |
818 | (u64) (1 << 2)); | 815 | (u64) (1 << 2)); |
@@ -830,6 +827,8 @@ irqreturn_t ipath_intr(int irq, void *data, struct pt_regs *regs) | |||
830 | } | 827 | } |
831 | 828 | ||
832 | istat = ipath_read_kreg32(dd, dd->ipath_kregs->kr_intstatus); | 829 | istat = ipath_read_kreg32(dd, dd->ipath_kregs->kr_intstatus); |
830 | p0bits = port0rbits; | ||
831 | |||
833 | if (unlikely(!istat)) { | 832 | if (unlikely(!istat)) { |
834 | ipath_stats.sps_nullintr++; | 833 | ipath_stats.sps_nullintr++; |
835 | ret = IRQ_NONE; /* not our interrupt, or already handled */ | 834 | ret = IRQ_NONE; /* not our interrupt, or already handled */ |
@@ -867,10 +866,11 @@ irqreturn_t ipath_intr(int irq, void *data, struct pt_regs *regs) | |||
867 | ipath_dev_err(dd, "Read of error status failed " | 866 | ipath_dev_err(dd, "Read of error status failed " |
868 | "(all bits set); ignoring\n"); | 867 | "(all bits set); ignoring\n"); |
869 | else | 868 | else |
870 | handle_errors(dd, estat); | 869 | if (handle_errors(dd, estat)) |
870 | /* force calling ipath_kreceive() */ | ||
871 | chk0rcv = 1; | ||
871 | } | 872 | } |
872 | 873 | ||
873 | p0bits = port0rbits; | ||
874 | if (istat & INFINIPATH_I_GPIO) { | 874 | if (istat & INFINIPATH_I_GPIO) { |
875 | /* | 875 | /* |
876 | * Packets are available in the port 0 rcv queue. | 876 | * Packets are available in the port 0 rcv queue. |
@@ -892,8 +892,10 @@ irqreturn_t ipath_intr(int irq, void *data, struct pt_regs *regs) | |||
892 | ipath_write_kreg(dd, dd->ipath_kregs->kr_gpio_clear, | 892 | ipath_write_kreg(dd, dd->ipath_kregs->kr_gpio_clear, |
893 | (u64) (1 << 2)); | 893 | (u64) (1 << 2)); |
894 | p0bits |= INFINIPATH_I_GPIO; | 894 | p0bits |= INFINIPATH_I_GPIO; |
895 | chk0rcv = 1; | ||
895 | } | 896 | } |
896 | } | 897 | } |
898 | chk0rcv |= istat & p0bits; | ||
897 | 899 | ||
898 | /* | 900 | /* |
899 | * clear the ones we will deal with on this round | 901 | * clear the ones we will deal with on this round |
@@ -905,18 +907,16 @@ irqreturn_t ipath_intr(int irq, void *data, struct pt_regs *regs) | |||
905 | ipath_write_kreg(dd, dd->ipath_kregs->kr_intclear, istat); | 907 | ipath_write_kreg(dd, dd->ipath_kregs->kr_intclear, istat); |
906 | 908 | ||
907 | /* | 909 | /* |
908 | * we check for both transition from empty to non-empty, and urgent | 910 | * handle port0 receive before checking for pio buffers available, |
909 | * packets (those with the interrupt bit set in the header), and | 911 | * since receives can overflow; piobuf waiters can afford a few |
910 | * if enabled, the GPIO bit 2 interrupt used for port0 on some | 912 | * extra cycles, since they were waiting anyway, and user's waiting |
911 | * HT-400 boards. | 913 | * for receive are at the bottom. |
912 | * Do this before checking for pio buffers available, since | ||
913 | * receives can overflow; piobuf waiters can afford a few | ||
914 | * extra cycles, since they were waiting anyway. | ||
915 | */ | 914 | */ |
916 | if (istat & p0bits) { | 915 | if (chk0rcv) { |
917 | ipath_kreceive(dd); | 916 | ipath_kreceive(dd); |
918 | istat &= ~port0rbits; | 917 | istat &= ~port0rbits; |
919 | } | 918 | } |
919 | |||
920 | if (istat & ((infinipath_i_rcvavail_mask << | 920 | if (istat & ((infinipath_i_rcvavail_mask << |
921 | INFINIPATH_I_RCVAVAIL_SHIFT) | 921 | INFINIPATH_I_RCVAVAIL_SHIFT) |
922 | | (infinipath_i_rcvurg_mask << | 922 | | (infinipath_i_rcvurg_mask << |