aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/infiniband
diff options
context:
space:
mode:
authorDave Olson <dave.olson@qlogic.com>2008-12-05 14:13:19 -0500
committerRoland Dreier <rolandd@cisco.com>2008-12-05 14:13:19 -0500
commit60e845035a066e81af1a29047530088d59150d8b (patch)
treeb824466835b3d6cf1c8489544094b025d1142f4a /drivers/infiniband
parent890fccb2427d53b48ab9d009fd87d55bcb173f62 (diff)
IB/ipath: Don't count IB symbol and link errors unless link is UP
Implement the ignoring of ibsymbol errors and linkrecover errors while the link is at less than INIT (long needed), to get accurate counts. Particularly an issue when doing non-IBTA DDR negotiation with chips from vendors that do not support IBTA mode negotiation. If the driver is unloaded, and there is a delta, the adjusted counters are written back to the chip, so they stay adjusted across driver reload. Signed-off-by: Dave Olson <dave.olson@qlogic.com> Signed-off-by: Roland Dreier <rolandd@cisco.com>
Diffstat (limited to 'drivers/infiniband')
-rw-r--r--drivers/infiniband/hw/ipath/ipath_iba6120.c61
-rw-r--r--drivers/infiniband/hw/ipath/ipath_iba7220.c76
-rw-r--r--drivers/infiniband/hw/ipath/ipath_kernel.h13
-rw-r--r--drivers/infiniband/hw/ipath/ipath_stats.c8
4 files changed, 155 insertions, 3 deletions
diff --git a/drivers/infiniband/hw/ipath/ipath_iba6120.c b/drivers/infiniband/hw/ipath/ipath_iba6120.c
index 421cc2af891f..fbf8c5379ea8 100644
--- a/drivers/infiniband/hw/ipath/ipath_iba6120.c
+++ b/drivers/infiniband/hw/ipath/ipath_iba6120.c
@@ -721,6 +721,12 @@ static int ipath_pe_bringup_serdes(struct ipath_devdata *dd)
721 INFINIPATH_HWE_SERDESPLLFAILED); 721 INFINIPATH_HWE_SERDESPLLFAILED);
722 } 722 }
723 723
724 dd->ibdeltainprog = 1;
725 dd->ibsymsnap =
726 ipath_read_creg32(dd, dd->ipath_cregs->cr_ibsymbolerrcnt);
727 dd->iblnkerrsnap =
728 ipath_read_creg32(dd, dd->ipath_cregs->cr_iblinkerrrecovcnt);
729
724 val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_serdesconfig0); 730 val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_serdesconfig0);
725 config1 = ipath_read_kreg64(dd, dd->ipath_kregs->kr_serdesconfig1); 731 config1 = ipath_read_kreg64(dd, dd->ipath_kregs->kr_serdesconfig1);
726 732
@@ -810,6 +816,36 @@ static void ipath_pe_quiet_serdes(struct ipath_devdata *dd)
810{ 816{
811 u64 val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_serdesconfig0); 817 u64 val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_serdesconfig0);
812 818
819 if (dd->ibsymdelta || dd->iblnkerrdelta ||
820 dd->ibdeltainprog) {
821 u64 diagc;
822 /* enable counter writes */
823 diagc = ipath_read_kreg64(dd, dd->ipath_kregs->kr_hwdiagctrl);
824 ipath_write_kreg(dd, dd->ipath_kregs->kr_hwdiagctrl,
825 diagc | INFINIPATH_DC_COUNTERWREN);
826
827 if (dd->ibsymdelta || dd->ibdeltainprog) {
828 val = ipath_read_creg32(dd,
829 dd->ipath_cregs->cr_ibsymbolerrcnt);
830 if (dd->ibdeltainprog)
831 val -= val - dd->ibsymsnap;
832 val -= dd->ibsymdelta;
833 ipath_write_creg(dd,
834 dd->ipath_cregs->cr_ibsymbolerrcnt, val);
835 }
836 if (dd->iblnkerrdelta || dd->ibdeltainprog) {
837 val = ipath_read_creg32(dd,
838 dd->ipath_cregs->cr_iblinkerrrecovcnt);
839 if (dd->ibdeltainprog)
840 val -= val - dd->iblnkerrsnap;
841 val -= dd->iblnkerrdelta;
842 ipath_write_creg(dd,
843 dd->ipath_cregs->cr_iblinkerrrecovcnt, val);
844 }
845
846 /* and disable counter writes */
847 ipath_write_kreg(dd, dd->ipath_kregs->kr_hwdiagctrl, diagc);
848 }
813 val |= INFINIPATH_SERDC0_TXIDLE; 849 val |= INFINIPATH_SERDC0_TXIDLE;
814 ipath_dbg("Setting TxIdleEn on serdes (config0 = %llx)\n", 850 ipath_dbg("Setting TxIdleEn on serdes (config0 = %llx)\n",
815 (unsigned long long) val); 851 (unsigned long long) val);
@@ -1749,6 +1785,31 @@ static void ipath_pe_config_jint(struct ipath_devdata *dd, u16 a, u16 b)
1749 1785
1750static int ipath_pe_ib_updown(struct ipath_devdata *dd, int ibup, u64 ibcs) 1786static int ipath_pe_ib_updown(struct ipath_devdata *dd, int ibup, u64 ibcs)
1751{ 1787{
1788 if (ibup) {
1789 if (dd->ibdeltainprog) {
1790 dd->ibdeltainprog = 0;
1791 dd->ibsymdelta +=
1792 ipath_read_creg32(dd,
1793 dd->ipath_cregs->cr_ibsymbolerrcnt) -
1794 dd->ibsymsnap;
1795 dd->iblnkerrdelta +=
1796 ipath_read_creg32(dd,
1797 dd->ipath_cregs->cr_iblinkerrrecovcnt) -
1798 dd->iblnkerrsnap;
1799 }
1800 } else {
1801 dd->ipath_lli_counter = 0;
1802 if (!dd->ibdeltainprog) {
1803 dd->ibdeltainprog = 1;
1804 dd->ibsymsnap =
1805 ipath_read_creg32(dd,
1806 dd->ipath_cregs->cr_ibsymbolerrcnt);
1807 dd->iblnkerrsnap =
1808 ipath_read_creg32(dd,
1809 dd->ipath_cregs->cr_iblinkerrrecovcnt);
1810 }
1811 }
1812
1752 ipath_setup_pe_setextled(dd, ipath_ib_linkstate(dd, ibcs), 1813 ipath_setup_pe_setextled(dd, ipath_ib_linkstate(dd, ibcs),
1753 ipath_ib_linktrstate(dd, ibcs)); 1814 ipath_ib_linktrstate(dd, ibcs));
1754 return 0; 1815 return 0;
diff --git a/drivers/infiniband/hw/ipath/ipath_iba7220.c b/drivers/infiniband/hw/ipath/ipath_iba7220.c
index 9839e20119bc..3b38bc9a331d 100644
--- a/drivers/infiniband/hw/ipath/ipath_iba7220.c
+++ b/drivers/infiniband/hw/ipath/ipath_iba7220.c
@@ -951,6 +951,12 @@ static int ipath_7220_bringup_serdes(struct ipath_devdata *dd)
951 INFINIPATH_HWE_SERDESPLLFAILED); 951 INFINIPATH_HWE_SERDESPLLFAILED);
952 } 952 }
953 953
954 dd->ibdeltainprog = 1;
955 dd->ibsymsnap =
956 ipath_read_creg32(dd, dd->ipath_cregs->cr_ibsymbolerrcnt);
957 dd->iblnkerrsnap =
958 ipath_read_creg32(dd, dd->ipath_cregs->cr_iblinkerrrecovcnt);
959
954 if (!dd->ipath_ibcddrctrl) { 960 if (!dd->ipath_ibcddrctrl) {
955 /* not on re-init after reset */ 961 /* not on re-init after reset */
956 dd->ipath_ibcddrctrl = 962 dd->ipath_ibcddrctrl =
@@ -1084,6 +1090,37 @@ static void ipath_7220_config_jint(struct ipath_devdata *dd,
1084static void ipath_7220_quiet_serdes(struct ipath_devdata *dd) 1090static void ipath_7220_quiet_serdes(struct ipath_devdata *dd)
1085{ 1091{
1086 u64 val; 1092 u64 val;
1093 if (dd->ibsymdelta || dd->iblnkerrdelta ||
1094 dd->ibdeltainprog) {
1095 u64 diagc;
1096 /* enable counter writes */
1097 diagc = ipath_read_kreg64(dd, dd->ipath_kregs->kr_hwdiagctrl);
1098 ipath_write_kreg(dd, dd->ipath_kregs->kr_hwdiagctrl,
1099 diagc | INFINIPATH_DC_COUNTERWREN);
1100
1101 if (dd->ibsymdelta || dd->ibdeltainprog) {
1102 val = ipath_read_creg32(dd,
1103 dd->ipath_cregs->cr_ibsymbolerrcnt);
1104 if (dd->ibdeltainprog)
1105 val -= val - dd->ibsymsnap;
1106 val -= dd->ibsymdelta;
1107 ipath_write_creg(dd,
1108 dd->ipath_cregs->cr_ibsymbolerrcnt, val);
1109 }
1110 if (dd->iblnkerrdelta || dd->ibdeltainprog) {
1111 val = ipath_read_creg32(dd,
1112 dd->ipath_cregs->cr_iblinkerrrecovcnt);
1113 if (dd->ibdeltainprog)
1114 val -= val - dd->iblnkerrsnap;
1115 val -= dd->iblnkerrdelta;
1116 ipath_write_creg(dd,
1117 dd->ipath_cregs->cr_iblinkerrrecovcnt, val);
1118 }
1119
1120 /* and disable counter writes */
1121 ipath_write_kreg(dd, dd->ipath_kregs->kr_hwdiagctrl, diagc);
1122 }
1123
1087 dd->ipath_flags &= ~IPATH_IB_AUTONEG_INPROG; 1124 dd->ipath_flags &= ~IPATH_IB_AUTONEG_INPROG;
1088 wake_up(&dd->ipath_autoneg_wait); 1125 wake_up(&dd->ipath_autoneg_wait);
1089 cancel_delayed_work(&dd->ipath_autoneg_work); 1126 cancel_delayed_work(&dd->ipath_autoneg_work);
@@ -2325,7 +2362,7 @@ static void try_auto_neg(struct ipath_devdata *dd)
2325 2362
2326static int ipath_7220_ib_updown(struct ipath_devdata *dd, int ibup, u64 ibcs) 2363static int ipath_7220_ib_updown(struct ipath_devdata *dd, int ibup, u64 ibcs)
2327{ 2364{
2328 int ret = 0; 2365 int ret = 0, symadj = 0;
2329 u32 ltstate = ipath_ib_linkstate(dd, ibcs); 2366 u32 ltstate = ipath_ib_linkstate(dd, ibcs);
2330 2367
2331 dd->ipath_link_width_active = 2368 dd->ipath_link_width_active =
@@ -2368,6 +2405,13 @@ static int ipath_7220_ib_updown(struct ipath_devdata *dd, int ibup, u64 ibcs)
2368 ipath_dbg("DDR negotiation try, %u/%u\n", 2405 ipath_dbg("DDR negotiation try, %u/%u\n",
2369 dd->ipath_autoneg_tries, 2406 dd->ipath_autoneg_tries,
2370 IPATH_AUTONEG_TRIES); 2407 IPATH_AUTONEG_TRIES);
2408 if (!dd->ibdeltainprog) {
2409 dd->ibdeltainprog = 1;
2410 dd->ibsymsnap = ipath_read_creg32(dd,
2411 dd->ipath_cregs->cr_ibsymbolerrcnt);
2412 dd->iblnkerrsnap = ipath_read_creg32(dd,
2413 dd->ipath_cregs->cr_iblinkerrrecovcnt);
2414 }
2371 try_auto_neg(dd); 2415 try_auto_neg(dd);
2372 ret = 1; /* no other IB status change processing */ 2416 ret = 1; /* no other IB status change processing */
2373 } else if ((dd->ipath_flags & IPATH_IB_AUTONEG_INPROG) 2417 } else if ((dd->ipath_flags & IPATH_IB_AUTONEG_INPROG)
@@ -2388,6 +2432,7 @@ static int ipath_7220_ib_updown(struct ipath_devdata *dd, int ibup, u64 ibcs)
2388 set_speed_fast(dd, 2432 set_speed_fast(dd,
2389 dd->ipath_link_speed_enabled); 2433 dd->ipath_link_speed_enabled);
2390 wake_up(&dd->ipath_autoneg_wait); 2434 wake_up(&dd->ipath_autoneg_wait);
2435 symadj = 1;
2391 } else if (dd->ipath_flags & IPATH_IB_AUTONEG_FAILED) { 2436 } else if (dd->ipath_flags & IPATH_IB_AUTONEG_FAILED) {
2392 /* 2437 /*
2393 * clear autoneg failure flag, and do setup 2438 * clear autoneg failure flag, and do setup
@@ -2403,6 +2448,7 @@ static int ipath_7220_ib_updown(struct ipath_devdata *dd, int ibup, u64 ibcs)
2403 IBA7220_IBC_IBTA_1_2_MASK; 2448 IBA7220_IBC_IBTA_1_2_MASK;
2404 ipath_write_kreg(dd, 2449 ipath_write_kreg(dd,
2405 IPATH_KREG_OFFSET(IBNCModeCtrl), 0); 2450 IPATH_KREG_OFFSET(IBNCModeCtrl), 0);
2451 symadj = 1;
2406 } 2452 }
2407 } 2453 }
2408 /* 2454 /*
@@ -2416,9 +2462,13 @@ static int ipath_7220_ib_updown(struct ipath_devdata *dd, int ibup, u64 ibcs)
2416 IB_WIDTH_4X)) == (IB_WIDTH_1X | IB_WIDTH_4X) 2462 IB_WIDTH_4X)) == (IB_WIDTH_1X | IB_WIDTH_4X)
2417 && dd->ipath_link_width_active == IB_WIDTH_1X 2463 && dd->ipath_link_width_active == IB_WIDTH_1X
2418 && dd->ipath_x1_fix_tries < 3) { 2464 && dd->ipath_x1_fix_tries < 3) {
2419 if (++dd->ipath_x1_fix_tries == 3) 2465 if (++dd->ipath_x1_fix_tries == 3) {
2420 dev_info(&dd->pcidev->dev, 2466 dev_info(&dd->pcidev->dev,
2421 "IB link is in 1X mode\n"); 2467 "IB link is in 1X mode\n");
2468 if (!(dd->ipath_flags &
2469 IPATH_IB_AUTONEG_INPROG))
2470 symadj = 1;
2471 }
2422 else { 2472 else {
2423 ipath_cdbg(VERBOSE, "IB 1X in " 2473 ipath_cdbg(VERBOSE, "IB 1X in "
2424 "auto-width, try %u to be " 2474 "auto-width, try %u to be "
@@ -2429,7 +2479,8 @@ static int ipath_7220_ib_updown(struct ipath_devdata *dd, int ibup, u64 ibcs)
2429 dd->ipath_f_xgxs_reset(dd); 2479 dd->ipath_f_xgxs_reset(dd);
2430 ret = 1; /* skip other processing */ 2480 ret = 1; /* skip other processing */
2431 } 2481 }
2432 } 2482 } else if (!(dd->ipath_flags & IPATH_IB_AUTONEG_INPROG))
2483 symadj = 1;
2433 2484
2434 if (!ret) { 2485 if (!ret) {
2435 dd->delay_mult = rate_to_delay 2486 dd->delay_mult = rate_to_delay
@@ -2440,6 +2491,25 @@ static int ipath_7220_ib_updown(struct ipath_devdata *dd, int ibup, u64 ibcs)
2440 } 2491 }
2441 } 2492 }
2442 2493
2494 if (symadj) {
2495 if (dd->ibdeltainprog) {
2496 dd->ibdeltainprog = 0;
2497 dd->ibsymdelta += ipath_read_creg32(dd,
2498 dd->ipath_cregs->cr_ibsymbolerrcnt) -
2499 dd->ibsymsnap;
2500 dd->iblnkerrdelta += ipath_read_creg32(dd,
2501 dd->ipath_cregs->cr_iblinkerrrecovcnt) -
2502 dd->iblnkerrsnap;
2503 }
2504 } else if (!ibup && !dd->ibdeltainprog
2505 && !(dd->ipath_flags & IPATH_IB_AUTONEG_INPROG)) {
2506 dd->ibdeltainprog = 1;
2507 dd->ibsymsnap = ipath_read_creg32(dd,
2508 dd->ipath_cregs->cr_ibsymbolerrcnt);
2509 dd->iblnkerrsnap = ipath_read_creg32(dd,
2510 dd->ipath_cregs->cr_iblinkerrrecovcnt);
2511 }
2512
2443 if (!ret) 2513 if (!ret)
2444 ipath_setup_7220_setextled(dd, ipath_ib_linkstate(dd, ibcs), 2514 ipath_setup_7220_setextled(dd, ipath_ib_linkstate(dd, ibcs),
2445 ltstate); 2515 ltstate);
diff --git a/drivers/infiniband/hw/ipath/ipath_kernel.h b/drivers/infiniband/hw/ipath/ipath_kernel.h
index 0bd8bcb184a1..aa84153b731b 100644
--- a/drivers/infiniband/hw/ipath/ipath_kernel.h
+++ b/drivers/infiniband/hw/ipath/ipath_kernel.h
@@ -355,6 +355,19 @@ struct ipath_devdata {
355 /* errors masked because they occur too fast */ 355 /* errors masked because they occur too fast */
356 ipath_err_t ipath_maskederrs; 356 ipath_err_t ipath_maskederrs;
357 u64 ipath_lastlinkrecov; /* link recoveries at last ACTIVE */ 357 u64 ipath_lastlinkrecov; /* link recoveries at last ACTIVE */
358 /* these 5 fields are used to establish deltas for IB Symbol
359 * errors and linkrecovery errors. They can be reported on
360 * some chips during link negotiation prior to INIT, and with
361 * DDR when faking DDR negotiations with non-IBTA switches.
362 * The chip counters are adjusted at driver unload if there is
363 * a non-zero delta.
364 */
365 u64 ibdeltainprog;
366 u64 ibsymdelta;
367 u64 ibsymsnap;
368 u64 iblnkerrdelta;
369 u64 iblnkerrsnap;
370
358 /* time in jiffies at which to re-enable maskederrs */ 371 /* time in jiffies at which to re-enable maskederrs */
359 unsigned long ipath_unmasktime; 372 unsigned long ipath_unmasktime;
360 /* count of egrfull errors, combined for all ports */ 373 /* count of egrfull errors, combined for all ports */
diff --git a/drivers/infiniband/hw/ipath/ipath_stats.c b/drivers/infiniband/hw/ipath/ipath_stats.c
index c8e3d65f0de8..f63e143e3292 100644
--- a/drivers/infiniband/hw/ipath/ipath_stats.c
+++ b/drivers/infiniband/hw/ipath/ipath_stats.c
@@ -112,6 +112,14 @@ u64 ipath_snap_cntr(struct ipath_devdata *dd, ipath_creg creg)
112 dd->ipath_lastrpkts = val; 112 dd->ipath_lastrpkts = val;
113 } 113 }
114 val64 = dd->ipath_rpkts; 114 val64 = dd->ipath_rpkts;
115 } else if (creg == dd->ipath_cregs->cr_ibsymbolerrcnt) {
116 if (dd->ibdeltainprog)
117 val64 -= val64 - dd->ibsymsnap;
118 val64 -= dd->ibsymdelta;
119 } else if (creg == dd->ipath_cregs->cr_iblinkerrrecovcnt) {
120 if (dd->ibdeltainprog)
121 val64 -= val64 - dd->iblnkerrsnap;
122 val64 -= dd->iblnkerrdelta;
115 } else 123 } else
116 val64 = (u64) val; 124 val64 = (u64) val;
117 125