diff options
-rw-r--r-- | drivers/infiniband/hw/ipath/ipath_iba6110.c | 11 | ||||
-rw-r--r-- | drivers/infiniband/hw/ipath/ipath_iba6120.c | 11 | ||||
-rw-r--r-- | drivers/infiniband/hw/ipath/ipath_intr.c | 77 | ||||
-rw-r--r-- | drivers/infiniband/hw/ipath/ipath_kernel.h | 1 |
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 | */ | ||
788 | void 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 | ||
765 | static void ipath_bad_intr(struct ipath_devdata *dd, u32 * unexpectp) | 842 | static 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); | |||
645 | void ipath_disable_wc(struct ipath_devdata *dd); | 645 | void ipath_disable_wc(struct ipath_devdata *dd); |
646 | int ipath_count_units(int *npresentp, int *nupp, u32 *maxportsp); | 646 | int ipath_count_units(int *npresentp, int *nupp, u32 *maxportsp); |
647 | void ipath_shutdown_device(struct ipath_devdata *); | 647 | void ipath_shutdown_device(struct ipath_devdata *); |
648 | void ipath_clear_freeze(struct ipath_devdata *); | ||
648 | 649 | ||
649 | struct file_operations; | 650 | struct file_operations; |
650 | int ipath_cdev_init(int minor, char *name, const struct file_operations *fops, | 651 | int ipath_cdev_init(int minor, char *name, const struct file_operations *fops, |