aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/infiniband/hw/ipath/ipath_intr.c
diff options
context:
space:
mode:
authorDave Olson <dave.olson@qlogic.com>2007-07-06 15:48:33 -0400
committerRoland Dreier <rolandd@cisco.com>2007-07-09 23:12:26 -0400
commit0f4fc5ebd9a68ede20ca365576a6df2df2fefc4c (patch)
tree0b41785bfd9ca49fa365d1b34ae2c81bce5c3caf /drivers/infiniband/hw/ipath/ipath_intr.c
parent4fc570bcbe77f823aae183dd824869f79e74cc97 (diff)
IB/ipath: Be more cautious about coming out of freeze mode
We are more careful to be sure that we don't lose information about changes that occurred while we were in freeze mode, when the chip will not notify us, and try to avoid false error interrupts while doing cleanup. Put all of this logic in a new function ipath_clear_freeze(). Signed-off-by: Dave Olson <dave.olson@qlogic.com> Signed-off-by: Roland Dreier <rolandd@cisco.com>
Diffstat (limited to 'drivers/infiniband/hw/ipath/ipath_intr.c')
-rw-r--r--drivers/infiniband/hw/ipath/ipath_intr.c77
1 files changed, 77 insertions, 0 deletions
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)