aboutsummaryrefslogtreecommitdiffstats
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
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>
-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,