headers: remove sched.h from interrupt.h
[safe/jmp/linux-2.6] / drivers / infiniband / hw / ipath / ipath_iba7220.c
index 5f693de..a805402 100644 (file)
@@ -37,6 +37,7 @@
 
 #include <linux/interrupt.h>
 #include <linux/pci.h>
+#include <linux/sched.h>
 #include <linux/delay.h>
 #include <linux/io.h>
 #include <rdma/ib_verbs.h>
@@ -528,7 +529,7 @@ static const struct ipath_cregs ipath_7220_cregs = {
 
 static char int_type[16] = "auto";
 module_param_string(interrupt_type, int_type, sizeof(int_type), 0444);
-MODULE_PARM_DESC(int_type, " interrupt_type=auto|force_msi|force_intx\n");
+MODULE_PARM_DESC(int_type, " interrupt_type=auto|force_msi|force_intx");
 
 /* packet rate matching delay; chip has support */
 static u8 rate_to_delay[2][2] = {
@@ -595,7 +596,7 @@ static void ipath_7220_txe_recover(struct ipath_devdata *dd)
 
        dev_info(&dd->pcidev->dev,
                "Recovering from TXE PIO parity error\n");
-       ipath_disarm_senderrbufs(dd, 1);
+       ipath_disarm_senderrbufs(dd);
 }
 
 
@@ -675,10 +676,8 @@ static void ipath_7220_handle_hwerrors(struct ipath_devdata *dd, char *msg,
        ctrl = ipath_read_kreg32(dd, dd->ipath_kregs->kr_control);
        if ((ctrl & INFINIPATH_C_FREEZEMODE) && !ipath_diag_inuse) {
                /*
-                * Parity errors in send memory are recoverable,
-                * just cancel the send (if indicated in * sendbuffererror),
-                * count the occurrence, unfreeze (if no other handled
-                * hardware error bits are set), and continue.
+                * Parity errors in send memory are recoverable by h/w
+                * just do housekeeping, exit freeze mode and continue.
                 */
                if (hwerrs & ((INFINIPATH_HWE_TXEMEMPARITYERR_PIOBUF |
                               INFINIPATH_HWE_TXEMEMPARITYERR_PIOPBC)
@@ -687,13 +686,6 @@ static void ipath_7220_handle_hwerrors(struct ipath_devdata *dd, char *msg,
                        hwerrs &= ~((INFINIPATH_HWE_TXEMEMPARITYERR_PIOBUF |
                                     INFINIPATH_HWE_TXEMEMPARITYERR_PIOPBC)
                                    << INFINIPATH_HWE_TXEMEMPARITYERR_SHIFT);
-                       if (!hwerrs) {
-                               /* else leave in freeze mode */
-                               ipath_write_kreg(dd,
-                                                dd->ipath_kregs->kr_control,
-                                                dd->ipath_control);
-                               goto bail;
-                       }
                }
                if (hwerrs) {
                        /*
@@ -723,8 +715,8 @@ static void ipath_7220_handle_hwerrors(struct ipath_devdata *dd, char *msg,
                        *dd->ipath_statusp |= IPATH_STATUS_HWERROR;
                        dd->ipath_flags &= ~IPATH_INITTED;
                } else {
-                       ipath_dbg("Clearing freezemode on ignored hardware "
-                                 "error\n");
+                       ipath_dbg("Clearing freezemode on ignored or "
+                               "recovered hardware error\n");
                        ipath_clear_freeze(dd);
                }
        }
@@ -960,6 +952,12 @@ static int ipath_7220_bringup_serdes(struct ipath_devdata *dd)
                                 INFINIPATH_HWE_SERDESPLLFAILED);
        }
 
+       dd->ibdeltainprog = 1;
+       dd->ibsymsnap =
+            ipath_read_creg32(dd, dd->ipath_cregs->cr_ibsymbolerrcnt);
+       dd->iblnkerrsnap =
+            ipath_read_creg32(dd, dd->ipath_cregs->cr_iblinkerrrecovcnt);
+
        if (!dd->ipath_ibcddrctrl) {
                /* not on re-init after reset */
                dd->ipath_ibcddrctrl =
@@ -1041,7 +1039,7 @@ static int ipath_7220_bringup_serdes(struct ipath_devdata *dd)
        ipath_cdbg(VERBOSE, "done: xgxs=%llx from %llx\n",
                   (unsigned long long)
                   ipath_read_kreg64(dd, dd->ipath_kregs->kr_xgxsconfig),
-                  prev_val);
+                  (unsigned long long) prev_val);
 
        guid = be64_to_cpu(dd->ipath_guid);
 
@@ -1051,7 +1049,8 @@ static int ipath_7220_bringup_serdes(struct ipath_devdata *dd)
                ipath_dbg("No GUID for heartbeat, faking %llx\n",
                        (unsigned long long)guid);
        } else
-               ipath_cdbg(VERBOSE, "Wrote %llX to HRTBT_GUID\n", guid);
+               ipath_cdbg(VERBOSE, "Wrote %llX to HRTBT_GUID\n",
+                       (unsigned long long) guid);
        ipath_write_kreg(dd, dd->ipath_kregs->kr_hrtbt_guid, guid);
        return ret;
 }
@@ -1092,6 +1091,37 @@ static void ipath_7220_config_jint(struct ipath_devdata *dd,
 static void ipath_7220_quiet_serdes(struct ipath_devdata *dd)
 {
        u64 val;
+       if (dd->ibsymdelta || dd->iblnkerrdelta ||
+           dd->ibdeltainprog) {
+               u64 diagc;
+               /* enable counter writes */
+               diagc = ipath_read_kreg64(dd, dd->ipath_kregs->kr_hwdiagctrl);
+               ipath_write_kreg(dd, dd->ipath_kregs->kr_hwdiagctrl,
+                                diagc | INFINIPATH_DC_COUNTERWREN);
+
+               if (dd->ibsymdelta || dd->ibdeltainprog) {
+                       val = ipath_read_creg32(dd,
+                                       dd->ipath_cregs->cr_ibsymbolerrcnt);
+                       if (dd->ibdeltainprog)
+                               val -= val - dd->ibsymsnap;
+                       val -= dd->ibsymdelta;
+                       ipath_write_creg(dd,
+                                 dd->ipath_cregs->cr_ibsymbolerrcnt, val);
+               }
+               if (dd->iblnkerrdelta || dd->ibdeltainprog) {
+                       val = ipath_read_creg32(dd,
+                                       dd->ipath_cregs->cr_iblinkerrrecovcnt);
+                       if (dd->ibdeltainprog)
+                               val -= val - dd->iblnkerrsnap;
+                       val -= dd->iblnkerrdelta;
+                       ipath_write_creg(dd,
+                                  dd->ipath_cregs->cr_iblinkerrrecovcnt, val);
+            }
+
+            /* and disable counter writes */
+            ipath_write_kreg(dd, dd->ipath_kregs->kr_hwdiagctrl, diagc);
+       }
+
        dd->ipath_flags &= ~IPATH_IB_AUTONEG_INPROG;
        wake_up(&dd->ipath_autoneg_wait);
        cancel_delayed_work(&dd->ipath_autoneg_work);
@@ -1728,7 +1758,7 @@ static void ipath_7220_put_tid(struct ipath_devdata *dd, u64 __iomem *tidptr,
                                 "not 2KB aligned!\n", pa);
                        return;
                }
-               if (pa >= (1UL << IBA7220_TID_SZ_SHIFT)) {
+               if (chippa >= (1UL << IBA7220_TID_SZ_SHIFT)) {
                        ipath_dev_err(dd,
                                      "BUG: Physical page address 0x%lx "
                                      "larger than supported\n", pa);
@@ -1967,7 +1997,7 @@ static void ipath_7220_config_ports(struct ipath_devdata *dd, ushort cfgports)
                         dd->ipath_rcvctrl);
        dd->ipath_p0_rcvegrcnt = 2048; /* always */
        if (dd->ipath_flags & IPATH_HAS_SEND_DMA)
-               dd->ipath_pioreserved = 1; /* reserve a buffer */
+               dd->ipath_pioreserved = 3; /* kpiobufs used for PIO */
 }
 
 
@@ -2237,8 +2267,8 @@ static void ipath_autoneg_send(struct ipath_devdata *dd, int which)
                0xffffffff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
                0x40000001, 0x1388, 0x15e, /* rest 0's */
                };
-       dcnt = sizeof(madpayload_start)/sizeof(madpayload_start[0]);
-       hcnt = sizeof(hdr)/sizeof(hdr[0]);
+       dcnt = ARRAY_SIZE(madpayload_start);
+       hcnt = ARRAY_SIZE(hdr);
        if (!swapped) {
                /* for maintainability, do it at runtime */
                for (i = 0; i < hcnt; i++) {
@@ -2333,7 +2363,7 @@ static void try_auto_neg(struct ipath_devdata *dd)
 
 static int ipath_7220_ib_updown(struct ipath_devdata *dd, int ibup, u64 ibcs)
 {
-       int ret = 0;
+       int ret = 0, symadj = 0;
        u32 ltstate = ipath_ib_linkstate(dd, ibcs);
 
        dd->ipath_link_width_active =
@@ -2376,6 +2406,13 @@ static int ipath_7220_ib_updown(struct ipath_devdata *dd, int ibup, u64 ibcs)
                        ipath_dbg("DDR negotiation try, %u/%u\n",
                                dd->ipath_autoneg_tries,
                                IPATH_AUTONEG_TRIES);
+                       if (!dd->ibdeltainprog) {
+                               dd->ibdeltainprog = 1;
+                               dd->ibsymsnap = ipath_read_creg32(dd,
+                                       dd->ipath_cregs->cr_ibsymbolerrcnt);
+                               dd->iblnkerrsnap = ipath_read_creg32(dd,
+                                       dd->ipath_cregs->cr_iblinkerrrecovcnt);
+                       }
                        try_auto_neg(dd);
                        ret = 1; /* no other IB status change processing */
                } else if ((dd->ipath_flags & IPATH_IB_AUTONEG_INPROG)
@@ -2396,6 +2433,7 @@ static int ipath_7220_ib_updown(struct ipath_devdata *dd, int ibup, u64 ibcs)
                                set_speed_fast(dd,
                                        dd->ipath_link_speed_enabled);
                                wake_up(&dd->ipath_autoneg_wait);
+                               symadj = 1;
                        } else if (dd->ipath_flags & IPATH_IB_AUTONEG_FAILED) {
                                /*
                                 * clear autoneg failure flag, and do setup
@@ -2411,22 +2449,28 @@ static int ipath_7220_ib_updown(struct ipath_devdata *dd, int ibup, u64 ibcs)
                                        IBA7220_IBC_IBTA_1_2_MASK;
                                ipath_write_kreg(dd,
                                        IPATH_KREG_OFFSET(IBNCModeCtrl), 0);
+                               symadj = 1;
                        }
                }
                /*
-                * if we are in 1X, and are in autoneg width, it
-                * could be due to an xgxs problem, so if we haven't
+                * if we are in 1X on rev1 only, and are in autoneg width,
+                * it could be due to an xgxs problem, so if we haven't
                 * already tried, try twice to get to 4X; if we
                 * tried, and couldn't, report it, since it will
                 * probably not be what is desired.
                 */
-               if ((dd->ipath_link_width_enabled & (IB_WIDTH_1X |
+               if (dd->ipath_minrev == 1 &&
+                   (dd->ipath_link_width_enabled & (IB_WIDTH_1X |
                        IB_WIDTH_4X)) == (IB_WIDTH_1X | IB_WIDTH_4X)
                        && dd->ipath_link_width_active == IB_WIDTH_1X
                        && dd->ipath_x1_fix_tries < 3) {
-                       if (++dd->ipath_x1_fix_tries == 3)
+                    if (++dd->ipath_x1_fix_tries == 3) {
                                dev_info(&dd->pcidev->dev,
                                        "IB link is in 1X mode\n");
+                               if (!(dd->ipath_flags &
+                                     IPATH_IB_AUTONEG_INPROG))
+                                       symadj = 1;
+                    }
                        else {
                                ipath_cdbg(VERBOSE, "IB 1X in "
                                        "auto-width, try %u to be "
@@ -2437,7 +2481,8 @@ static int ipath_7220_ib_updown(struct ipath_devdata *dd, int ibup, u64 ibcs)
                                dd->ipath_f_xgxs_reset(dd);
                                ret = 1; /* skip other processing */
                        }
-               }
+               } else if (!(dd->ipath_flags & IPATH_IB_AUTONEG_INPROG))
+                       symadj = 1;
 
                if (!ret) {
                        dd->delay_mult = rate_to_delay
@@ -2448,6 +2493,25 @@ static int ipath_7220_ib_updown(struct ipath_devdata *dd, int ibup, u64 ibcs)
                }
        }
 
+       if (symadj) {
+               if (dd->ibdeltainprog) {
+                       dd->ibdeltainprog = 0;
+                       dd->ibsymdelta += ipath_read_creg32(dd,
+                               dd->ipath_cregs->cr_ibsymbolerrcnt) -
+                               dd->ibsymsnap;
+                       dd->iblnkerrdelta += ipath_read_creg32(dd,
+                               dd->ipath_cregs->cr_iblinkerrrecovcnt) -
+                               dd->iblnkerrsnap;
+               }
+       } else if (!ibup && !dd->ibdeltainprog
+                  && !(dd->ipath_flags & IPATH_IB_AUTONEG_INPROG)) {
+               dd->ibdeltainprog = 1;
+               dd->ibsymsnap = ipath_read_creg32(dd,
+                                    dd->ipath_cregs->cr_ibsymbolerrcnt);
+               dd->iblnkerrsnap = ipath_read_creg32(dd,
+                                    dd->ipath_cregs->cr_iblinkerrrecovcnt);
+       }
+
        if (!ret)
                ipath_setup_7220_setextled(dd, ipath_ib_linkstate(dd, ibcs),
                        ltstate);
@@ -2514,7 +2578,7 @@ done:
        if (dd->ipath_flags & IPATH_IB_AUTONEG_INPROG) {
                ipath_dbg("Did not get to DDR INIT (%x) after %Lu msecs\n",
                        ipath_ib_state(dd, dd->ipath_lastibcstat),
-                       jiffies_to_msecs(jiffies)-startms);
+                       (unsigned long long) jiffies_to_msecs(jiffies)-startms);
                dd->ipath_flags &= ~IPATH_IB_AUTONEG_INPROG;
                if (dd->ipath_autoneg_tries == IPATH_AUTONEG_TRIES) {
                        dd->ipath_flags |= IPATH_IB_AUTONEG_FAILED;