aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/infiniband/hw/ipath/ipath_iba6110.c11
-rw-r--r--drivers/infiniband/hw/ipath/ipath_iba6120.c11
-rw-r--r--drivers/infiniband/hw/ipath/ipath_intr.c77
-rw-r--r--drivers/infiniband/hw/ipath/ipath_kernel.h1
4 files changed, 80 insertions, 20 deletions
diff --git a/drivers/infiniband/hw/ipath/ipath_iba6110.c b/drivers/infiniband/hw/ipath/ipath_iba6110.c
index 87b18e928c79..fdfa95d0dd72 100644
--- a/drivers/infiniband/hw/ipath/ipath_iba6110.c
+++ b/drivers/infiniband/hw/ipath/ipath_iba6110.c
@@ -509,16 +509,7 @@ static void ipath_ht_handle_hwerrors(struct ipath_devdata *dd, char *msg,
509 if (!hwerrs) { 509 if (!hwerrs) {
510 ipath_dbg("Clearing freezemode on ignored or " 510 ipath_dbg("Clearing freezemode on ignored or "
511 "recovered hardware error\n"); 511 "recovered hardware error\n");
512 /* 512 ipath_clear_freeze(dd);
513 * clear all sends, becauase they have may been
514 * completed by usercode while in freeze mode, and
515 * therefore would not be sent, and eventually
516 * might cause the process to run out of bufs
517 */
518 ipath_cancel_sends(dd);
519 ctrl &= ~INFINIPATH_C_FREEZEMODE;
520 ipath_write_kreg(dd, dd->ipath_kregs->kr_control,
521 ctrl);
522 } 513 }
523 } 514 }
524 515
diff --git a/drivers/infiniband/hw/ipath/ipath_iba6120.c b/drivers/infiniband/hw/ipath/ipath_iba6120.c
index e67e4a89fcc4..9868ccda5f26 100644
--- a/drivers/infiniband/hw/ipath/ipath_iba6120.c
+++ b/drivers/infiniband/hw/ipath/ipath_iba6120.c
@@ -435,16 +435,7 @@ static void ipath_pe_handle_hwerrors(struct ipath_devdata *dd, char *msg,
435 freeze_cnt++; 435 freeze_cnt++;
436 ipath_dbg("Clearing freezemode on ignored or recovered " 436 ipath_dbg("Clearing freezemode on ignored or recovered "
437 "hardware error (%u)\n", freeze_cnt); 437 "hardware error (%u)\n", freeze_cnt);
438 /* 438 ipath_clear_freeze(dd);
439 * clear all sends, becauase they have may been
440 * completed by usercode while in freeze mode, and
441 * therefore would not be sent, and eventually
442 * might cause the process to run out of bufs
443 */
444 ipath_cancel_sends(dd);
445 ctrl &= ~INFINIPATH_C_FREEZEMODE;
446 ipath_write_kreg(dd, dd->ipath_kregs->kr_control,
447 dd->ipath_control);
448 } 439 }
449 } 440 }
450 441
diff --git a/drivers/infiniband/hw/ipath/ipath_intr.c b/drivers/infiniband/hw/ipath/ipath_intr.c
index e86a23a05919..ce490235c24f 100644
--- a/drivers/infiniband/hw/ipath/ipath_intr.c
+++ b/drivers/infiniband/hw/ipath/ipath_intr.c
@@ -133,6 +133,17 @@ void ipath_disarm_senderrbufs(struct ipath_devdata *dd, int rewrite)
133 INFINIPATH_E_INVALIDADDR) 133 INFINIPATH_E_INVALIDADDR)
134 134
135/* 135/*
136 * this is similar to E_SUM_ERRS, but can't ignore armlaunch, don't ignore
137 * errors not related to freeze and cancelling buffers. Can't ignore
138 * armlaunch because could get more while still cleaning up, and need
139 * to cancel those as they happen.
140 */
141#define E_SPKT_ERRS_IGNORE \
142 (INFINIPATH_E_SDROPPEDDATAPKT | INFINIPATH_E_SDROPPEDSMPPKT | \
143 INFINIPATH_E_SMAXPKTLEN | INFINIPATH_E_SMINPKTLEN | \
144 INFINIPATH_E_SPKTLEN)
145
146/*
136 * these are errors that can occur when the link changes state while 147 * these are errors that can occur when the link changes state while
137 * a packet is being sent or received. This doesn't cover things 148 * a packet is being sent or received. This doesn't cover things
138 * like EBP or VCRC that can be the result of a sending having the 149 * like EBP or VCRC that can be the result of a sending having the
@@ -760,6 +771,72 @@ static int handle_errors(struct ipath_devdata *dd, ipath_err_t errs)
760 return chkerrpkts; 771 return chkerrpkts;
761} 772}
762 773
774
775/*
776 * try to cleanup as much as possible for anything that might have gone
777 * wrong while in freeze mode, such as pio buffers being written by user
778 * processes (causing armlaunch), send errors due to going into freeze mode,
779 * etc., and try to avoid causing extra interrupts while doing so.
780 * Forcibly update the in-memory pioavail register copies after cleanup
781 * because the chip won't do it for anything changing while in freeze mode
782 * (we don't want to wait for the next pio buffer state change).
783 * Make sure that we don't lose any important interrupts by using the chip
784 * feature that says that writing 0 to a bit in *clear that is set in
785 * *status will cause an interrupt to be generated again (if allowed by
786 * the *mask value).
787 */
788void ipath_clear_freeze(struct ipath_devdata *dd)
789{
790 int i, im;
791 __le64 val;
792
793 /* disable error interrupts, to avoid confusion */
794 ipath_write_kreg(dd, dd->ipath_kregs->kr_errormask, 0ULL);
795
796 /*
797 * clear all sends, because they have may been
798 * completed by usercode while in freeze mode, and
799 * therefore would not be sent, and eventually
800 * might cause the process to run out of bufs
801 */
802 ipath_cancel_sends(dd);
803 ipath_write_kreg(dd, dd->ipath_kregs->kr_control,
804 dd->ipath_control);
805
806 /* ensure pio avail updates continue */
807 ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl,
808 dd->ipath_sendctrl & ~IPATH_S_PIOBUFAVAILUPD);
809 ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch);
810 ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl,
811 dd->ipath_sendctrl);
812
813 /*
814 * We just enabled pioavailupdate, so dma copy is almost certainly
815 * not yet right, so read the registers directly. Similar to init
816 */
817 for (i = 0; i < dd->ipath_pioavregs; i++) {
818 /* deal with 6110 chip bug */
819 im = i > 3 ? ((i&1) ? i-1 : i+1) : i;
820 val = ipath_read_kreg64(dd, 0x1000+(im*sizeof(u64)));
821 dd->ipath_pioavailregs_dma[i] = dd->ipath_pioavailshadow[i]
822 = le64_to_cpu(val);
823 }
824
825 /*
826 * force new interrupt if any hwerr, error or interrupt bits are
827 * still set, and clear "safe" send packet errors related to freeze
828 * and cancelling sends. Re-enable error interrupts before possible
829 * force of re-interrupt on pending interrupts.
830 */
831 ipath_write_kreg(dd, dd->ipath_kregs->kr_hwerrclear, 0ULL);
832 ipath_write_kreg(dd, dd->ipath_kregs->kr_errorclear,
833 E_SPKT_ERRS_IGNORE);
834 ipath_write_kreg(dd, dd->ipath_kregs->kr_errormask,
835 ~dd->ipath_maskederrs);
836 ipath_write_kreg(dd, dd->ipath_kregs->kr_intclear, 0ULL);
837}
838
839
763/* this is separate to allow for better optimization of ipath_intr() */ 840/* this is separate to allow for better optimization of ipath_intr() */
764 841
765static void ipath_bad_intr(struct ipath_devdata *dd, u32 * unexpectp) 842static void ipath_bad_intr(struct ipath_devdata *dd, u32 * unexpectp)
diff --git a/drivers/infiniband/hw/ipath/ipath_kernel.h b/drivers/infiniband/hw/ipath/ipath_kernel.h
index f1f812759ee3..8bad3e3c5550 100644
--- a/drivers/infiniband/hw/ipath/ipath_kernel.h
+++ b/drivers/infiniband/hw/ipath/ipath_kernel.h
@@ -645,6 +645,7 @@ int ipath_enable_wc(struct ipath_devdata *dd);
645void ipath_disable_wc(struct ipath_devdata *dd); 645void ipath_disable_wc(struct ipath_devdata *dd);
646int ipath_count_units(int *npresentp, int *nupp, u32 *maxportsp); 646int ipath_count_units(int *npresentp, int *nupp, u32 *maxportsp);
647void ipath_shutdown_device(struct ipath_devdata *); 647void ipath_shutdown_device(struct ipath_devdata *);
648void ipath_clear_freeze(struct ipath_devdata *);
648 649
649struct file_operations; 650struct file_operations;
650int ipath_cdev_init(int minor, char *name, const struct file_operations *fops, 651int ipath_cdev_init(int minor, char *name, const struct file_operations *fops,