IB/ipath: Add new chip-specific functions to older chips, consistent init
authorDave Olson <dave.olson@qlogic.com>
Tue, 8 Jan 2008 10:36:46 +0000 (02:36 -0800)
committerRoland Dreier <rolandd@cisco.com>
Fri, 25 Jan 2008 22:15:45 +0000 (14:15 -0800)
This adds the new (sometimes empty) chip-specific functions to the older
chips, and makes the initialization and related functions consistent across
all 3 chips.

Signed-off-by: Dave Olson <dave.olson@qlogic.com>
Signed-off-by: Roland Dreier <rolandd@cisco.com>
drivers/infiniband/hw/ipath/ipath_common.h
drivers/infiniband/hw/ipath/ipath_iba6110.c
drivers/infiniband/hw/ipath/ipath_iba6120.c
drivers/infiniband/hw/ipath/ipath_kernel.h

index aa780e7f24180853bd4ac448ba29e78643e5d19b..0fa43ba25b7e27c6e30ff2059f623807a35c2466 100644 (file)
 #define IPATH_IB_LINK_LOOPBACK 6 /* enable local loopback */
 #define IPATH_IB_LINK_EXTERNAL 7 /* normal, disable local loopback */
 
+/*
+ * These 3 values (SDR and DDR may be ORed for auto-speed
+ * negotiation) are used for the 3rd argument to path_f_set_ib_cfg
+ * with cmd IPATH_IB_CFG_SPD_ENB, by direct calls or via sysfs.  They
+ * are also the the possible values for ipath_link_speed_enabled and active
+ * The values were chosen to match values used within the IB spec.
+ */
+#define IPATH_IB_SDR 1
+#define IPATH_IB_DDR 2
+
 /*
  * stats maintained by the driver.  For now, at least, this is global
  * to all minor devices.
index ac436c630bcc4f501899527cb2bcc9b8393f25af..9e2ced3cdc5e656af160b48cd5b53ba8753f19c6 100644 (file)
@@ -329,6 +329,9 @@ static const struct ipath_cregs ipath_ht_cregs = {
 #define INFINIPATH_HWE_HTAPLL_RFSLIP        0x1000000000000000ULL
 #define INFINIPATH_HWE_SERDESPLLFAILED      0x2000000000000000ULL
 
+#define IBA6110_IBCS_LINKTRAININGSTATE_MASK 0xf
+#define IBA6110_IBCS_LINKSTATE_SHIFT 4
+
 /* kr_extstatus bits */
 #define INFINIPATH_EXTS_FREQSEL 0x2
 #define INFINIPATH_EXTS_SERDESSEL 0x4
@@ -705,7 +708,6 @@ static int ipath_ht_boardname(struct ipath_devdata *dd, char *name,
                              "with ID %u\n", boardrev);
                snprintf(name, namelen, "Unknown_InfiniPath_QHT7xxx_%u",
                         boardrev);
-               ret = 1;
                break;
        }
        if (n)
@@ -1137,11 +1139,49 @@ static void ipath_setup_ht_setextled(struct ipath_devdata *dd,
 
 static void ipath_init_ht_variables(struct ipath_devdata *dd)
 {
+       /*
+        * setup the register offsets, since they are different for each
+        * chip
+        */
+       dd->ipath_kregs = &ipath_ht_kregs;
+       dd->ipath_cregs = &ipath_ht_cregs;
+
        dd->ipath_gpio_sda_num = _IPATH_GPIO_SDA_NUM;
        dd->ipath_gpio_scl_num = _IPATH_GPIO_SCL_NUM;
        dd->ipath_gpio_sda = IPATH_GPIO_SDA;
        dd->ipath_gpio_scl = IPATH_GPIO_SCL;
 
+       /*
+        * Fill in data for field-values that change in newer chips.
+        * We dynamically specify only the mask for LINKTRAININGSTATE
+        * and only the shift for LINKSTATE, as they are the only ones
+        * that change.  Also precalculate the 3 link states of interest
+        * and the combined mask.
+        */
+       dd->ibcs_ls_shift = IBA6110_IBCS_LINKSTATE_SHIFT;
+       dd->ibcs_lts_mask = IBA6110_IBCS_LINKTRAININGSTATE_MASK;
+       dd->ibcs_mask = (INFINIPATH_IBCS_LINKSTATE_MASK <<
+               dd->ibcs_ls_shift) | dd->ibcs_lts_mask;
+       dd->ib_init = (INFINIPATH_IBCS_LT_STATE_LINKUP <<
+               INFINIPATH_IBCS_LINKTRAININGSTATE_SHIFT) |
+               (INFINIPATH_IBCS_L_STATE_INIT << dd->ibcs_ls_shift);
+       dd->ib_arm = (INFINIPATH_IBCS_LT_STATE_LINKUP <<
+               INFINIPATH_IBCS_LINKTRAININGSTATE_SHIFT) |
+               (INFINIPATH_IBCS_L_STATE_ARM << dd->ibcs_ls_shift);
+       dd->ib_active = (INFINIPATH_IBCS_LT_STATE_LINKUP <<
+               INFINIPATH_IBCS_LINKTRAININGSTATE_SHIFT) |
+               (INFINIPATH_IBCS_L_STATE_ACTIVE << dd->ibcs_ls_shift);
+
+       /*
+        * Fill in data for ibcc field-values that change in newer chips.
+        * We dynamically specify only the mask for LINKINITCMD
+        * and only the shift for LINKCMD and MAXPKTLEN, as they are
+        * the only ones that change.
+        */
+       dd->ibcc_lic_mask = INFINIPATH_IBCC_LINKINITCMD_MASK;
+       dd->ibcc_lc_shift = INFINIPATH_IBCC_LINKCMD_SHIFT;
+       dd->ibcc_mpl_shift = INFINIPATH_IBCC_MAXPKTLEN_SHIFT;
+
        /* Fill in shifts for RcvCtrl. */
        dd->ipath_r_portenable_shift = INFINIPATH_R_PORTENABLE_SHIFT;
        dd->ipath_r_intravail_shift = INFINIPATH_R_INTRAVAIL_SHIFT;
@@ -1204,6 +1244,8 @@ static void ipath_init_ht_variables(struct ipath_devdata *dd)
 
        dd->ipath_i_rcvavail_mask = INFINIPATH_I_RCVAVAIL_MASK;
        dd->ipath_i_rcvurg_mask = INFINIPATH_I_RCVURG_MASK;
+       dd->ipath_i_rcvavail_shift = INFINIPATH_I_RCVAVAIL_SHIFT;
+       dd->ipath_i_rcvurg_shift = INFINIPATH_I_RCVURG_SHIFT;
 
        /*
         * EEPROM error log 0 is TXE Parity errors. 1 is RXE Parity.
@@ -1217,9 +1259,17 @@ static void ipath_init_ht_variables(struct ipath_devdata *dd)
                INFINIPATH_HWE_RXEMEMPARITYERR_MASK <<
                INFINIPATH_HWE_RXEMEMPARITYERR_SHIFT;
 
-       dd->ipath_eep_st_masks[2].errs_to_log =
-               INFINIPATH_E_INVALIDADDR | INFINIPATH_E_RESET;
+       dd->ipath_eep_st_masks[2].errs_to_log = INFINIPATH_E_RESET;
 
+       dd->delay_mult = 2; /* SDR, 4X, can't change */
+
+       dd->ipath_link_width_supported = IB_WIDTH_1X | IB_WIDTH_4X;
+       dd->ipath_link_speed_supported = IPATH_IB_SDR;
+       dd->ipath_link_width_enabled = IB_WIDTH_4X;
+       dd->ipath_link_speed_enabled = dd->ipath_link_speed_supported;
+       /* these can't change for this chip, so set once */
+       dd->ipath_link_width_active = dd->ipath_link_width_enabled;
+       dd->ipath_link_speed_active = dd->ipath_link_speed_enabled;
 }
 
 /**
@@ -1281,6 +1331,9 @@ static void ipath_ht_init_hwerrors(struct ipath_devdata *dd)
        dd->ipath_hwerrmask = val;
 }
 
+
+
+
 /**
  * ipath_ht_bringup_serdes - bring up the serdes
  * @dd: the infinipath device
@@ -1439,6 +1492,7 @@ static void ipath_ht_put_tid(struct ipath_devdata *dd,
                        pa |= lenvalid | INFINIPATH_RT_VALID;
                }
        }
+
        writeq(pa, tidptr);
 }
 
@@ -1644,6 +1698,13 @@ static void ipath_ht_free_irq(struct ipath_devdata *dd)
        dd->ipath_intconfig = 0;
 }
 
+static struct ipath_message_header *
+ipath_ht_get_msgheader(struct ipath_devdata *dd, __le32 *rhf_addr)
+{
+       return (struct ipath_message_header *)
+               &rhf_addr[sizeof(u64) / sizeof(u32)];
+}
+
 static void ipath_ht_config_ports(struct ipath_devdata *dd, ushort cfgports)
 {
        dd->ipath_portcnt =
@@ -1757,6 +1818,90 @@ static void ipath_ht_read_counters(struct ipath_devdata *dd,
        cntrs->RxDlidFltrCnt = 0;
 }
 
+
+/* no interrupt fallback for these chips */
+static int ipath_ht_nointr_fallback(struct ipath_devdata *dd)
+{
+       return 0;
+}
+
+
+/*
+ * reset the XGXS (between serdes and IBC).  Slightly less intrusive
+ * than resetting the IBC or external link state, and useful in some
+ * cases to cause some retraining.  To do this right, we reset IBC
+ * as well.
+ */
+static void ipath_ht_xgxs_reset(struct ipath_devdata *dd)
+{
+       u64 val, prev_val;
+
+       prev_val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_xgxsconfig);
+       val = prev_val | INFINIPATH_XGXS_RESET;
+       prev_val &= ~INFINIPATH_XGXS_RESET; /* be sure */
+       ipath_write_kreg(dd, dd->ipath_kregs->kr_control,
+                        dd->ipath_control & ~INFINIPATH_C_LINKENABLE);
+       ipath_write_kreg(dd, dd->ipath_kregs->kr_xgxsconfig, val);
+       ipath_read_kreg32(dd, dd->ipath_kregs->kr_scratch);
+       ipath_write_kreg(dd, dd->ipath_kregs->kr_xgxsconfig, prev_val);
+       ipath_write_kreg(dd, dd->ipath_kregs->kr_control,
+                        dd->ipath_control);
+}
+
+
+static int ipath_ht_get_ib_cfg(struct ipath_devdata *dd, int which)
+{
+       int ret;
+
+       switch (which) {
+       case IPATH_IB_CFG_LWID:
+               ret = dd->ipath_link_width_active;
+               break;
+       case IPATH_IB_CFG_SPD:
+               ret = dd->ipath_link_speed_active;
+               break;
+       case IPATH_IB_CFG_LWID_ENB:
+               ret = dd->ipath_link_width_enabled;
+               break;
+       case IPATH_IB_CFG_SPD_ENB:
+               ret = dd->ipath_link_speed_enabled;
+               break;
+       default:
+               ret =  -ENOTSUPP;
+               break;
+       }
+       return ret;
+}
+
+
+/* we assume range checking is already done, if needed */
+static int ipath_ht_set_ib_cfg(struct ipath_devdata *dd, int which, u32 val)
+{
+       int ret = 0;
+
+       if (which == IPATH_IB_CFG_LWID_ENB)
+               dd->ipath_link_width_enabled = val;
+       else if (which == IPATH_IB_CFG_SPD_ENB)
+               dd->ipath_link_speed_enabled = val;
+       else
+               ret = -ENOTSUPP;
+       return ret;
+}
+
+
+static void ipath_ht_config_jint(struct ipath_devdata *dd, u16 a, u16 b)
+{
+}
+
+
+static int ipath_ht_ib_updown(struct ipath_devdata *dd, int ibup, u64 ibcs)
+{
+       ipath_setup_ht_setextled(dd, ipath_ib_linkstate(dd, ibcs),
+               ipath_ib_linktrstate(dd, ibcs));
+       return 0;
+}
+
+
 /**
  * ipath_init_iba6110_funcs - set up the chip-specific function pointers
  * @dd: the infinipath device
@@ -1781,24 +1926,19 @@ void ipath_init_iba6110_funcs(struct ipath_devdata *dd)
        dd->ipath_f_setextled = ipath_setup_ht_setextled;
        dd->ipath_f_get_base_info = ipath_ht_get_base_info;
        dd->ipath_f_free_irq = ipath_ht_free_irq;
+       dd->ipath_f_tidtemplate = ipath_ht_tidtemplate;
+       dd->ipath_f_intr_fallback = ipath_ht_nointr_fallback;
+       dd->ipath_f_get_msgheader = ipath_ht_get_msgheader;
        dd->ipath_f_config_ports = ipath_ht_config_ports;
        dd->ipath_f_read_counters = ipath_ht_read_counters;
+       dd->ipath_f_xgxs_reset = ipath_ht_xgxs_reset;
+       dd->ipath_f_get_ib_cfg = ipath_ht_get_ib_cfg;
+       dd->ipath_f_set_ib_cfg = ipath_ht_set_ib_cfg;
+       dd->ipath_f_config_jint = ipath_ht_config_jint;
+       dd->ipath_f_ib_updown = ipath_ht_ib_updown;
 
        /*
         * initialize chip-specific variables
         */
-       dd->ipath_f_tidtemplate = ipath_ht_tidtemplate;
-
-       /*
-        * setup the register offsets, since they are different for each
-        * chip
-        */
-       dd->ipath_kregs = &ipath_ht_kregs;
-       dd->ipath_cregs = &ipath_ht_cregs;
-
-       /*
-        * do very early init that is needed before ipath_f_bus is
-        * called
-        */
        ipath_init_ht_variables(dd);
 }
index 57915fd718e24bbda69bc30ca940fb4d396faeac..597192e912de414b77e53811d5d1a8cc72ae1abd 100644 (file)
@@ -329,6 +329,9 @@ static const struct ipath_cregs ipath_pe_cregs = {
 #define INFINIPATH_HWE_PCIE0PLLFAILED       0x0800000000000000ULL
 #define INFINIPATH_HWE_SERDESPLLFAILED      0x1000000000000000ULL
 
+#define IBA6120_IBCS_LINKTRAININGSTATE_MASK 0xf
+#define IBA6120_IBCS_LINKSTATE_SHIFT 4
+
 /* kr_extstatus bits */
 #define INFINIPATH_EXTS_FREQSEL 0x2
 #define INFINIPATH_EXTS_SERDESSEL 0x4
@@ -936,11 +939,26 @@ static int ipath_setup_pe_config(struct ipath_devdata *dd,
        else
                ipath_dev_err(dd, "Can't find PCI Express "
                              "capability!\n");
+
+       dd->ipath_link_width_supported = IB_WIDTH_1X | IB_WIDTH_4X;
+       dd->ipath_link_speed_supported = IPATH_IB_SDR;
+       dd->ipath_link_width_enabled = IB_WIDTH_4X;
+       dd->ipath_link_speed_enabled = dd->ipath_link_speed_supported;
+       /* these can't change for this chip, so set once */
+       dd->ipath_link_width_active = dd->ipath_link_width_enabled;
+       dd->ipath_link_speed_active = dd->ipath_link_speed_enabled;
        return 0;
 }
 
 static void ipath_init_pe_variables(struct ipath_devdata *dd)
 {
+       /*
+        * setup the register offsets, since they are different for each
+        * chip
+        */
+       dd->ipath_kregs = &ipath_pe_kregs;
+       dd->ipath_cregs = &ipath_pe_cregs;
+
        /*
         * bits for selecting i2c direction and values,
         * used for I2C serial flash
@@ -950,6 +968,37 @@ static void ipath_init_pe_variables(struct ipath_devdata *dd)
        dd->ipath_gpio_sda = IPATH_GPIO_SDA;
        dd->ipath_gpio_scl = IPATH_GPIO_SCL;
 
+       /*
+        * Fill in data for field-values that change in newer chips.
+        * We dynamically specify only the mask for LINKTRAININGSTATE
+        * and only the shift for LINKSTATE, as they are the only ones
+        * that change.  Also precalculate the 3 link states of interest
+        * and the combined mask.
+        */
+       dd->ibcs_ls_shift = IBA6120_IBCS_LINKSTATE_SHIFT;
+       dd->ibcs_lts_mask = IBA6120_IBCS_LINKTRAININGSTATE_MASK;
+       dd->ibcs_mask = (INFINIPATH_IBCS_LINKSTATE_MASK <<
+               dd->ibcs_ls_shift) | dd->ibcs_lts_mask;
+       dd->ib_init = (INFINIPATH_IBCS_LT_STATE_LINKUP <<
+               INFINIPATH_IBCS_LINKTRAININGSTATE_SHIFT) |
+               (INFINIPATH_IBCS_L_STATE_INIT << dd->ibcs_ls_shift);
+       dd->ib_arm = (INFINIPATH_IBCS_LT_STATE_LINKUP <<
+               INFINIPATH_IBCS_LINKTRAININGSTATE_SHIFT) |
+               (INFINIPATH_IBCS_L_STATE_ARM << dd->ibcs_ls_shift);
+       dd->ib_active = (INFINIPATH_IBCS_LT_STATE_LINKUP <<
+               INFINIPATH_IBCS_LINKTRAININGSTATE_SHIFT) |
+               (INFINIPATH_IBCS_L_STATE_ACTIVE << dd->ibcs_ls_shift);
+
+       /*
+        * Fill in data for ibcc field-values that change in newer chips.
+        * We dynamically specify only the mask for LINKINITCMD
+        * and only the shift for LINKCMD and MAXPKTLEN, as they are
+        * the only ones that change.
+        */
+       dd->ibcc_lic_mask = INFINIPATH_IBCC_LINKINITCMD_MASK;
+       dd->ibcc_lc_shift = INFINIPATH_IBCC_LINKCMD_SHIFT;
+       dd->ibcc_mpl_shift = INFINIPATH_IBCC_MAXPKTLEN_SHIFT;
+
        /* Fill in shifts for RcvCtrl. */
        dd->ipath_r_portenable_shift = INFINIPATH_R_PORTENABLE_SHIFT;
        dd->ipath_r_intravail_shift = INFINIPATH_R_INTRAVAIL_SHIFT;
@@ -1003,6 +1052,8 @@ static void ipath_init_pe_variables(struct ipath_devdata *dd)
 
        dd->ipath_i_rcvavail_mask = INFINIPATH_I_RCVAVAIL_MASK;
        dd->ipath_i_rcvurg_mask = INFINIPATH_I_RCVURG_MASK;
+       dd->ipath_i_rcvavail_shift = INFINIPATH_I_RCVAVAIL_SHIFT;
+       dd->ipath_i_rcvurg_shift = INFINIPATH_I_RCVURG_SHIFT;
 
        /*
         * EEPROM error log 0 is TXE Parity errors. 1 is RXE Parity.
@@ -1024,6 +1075,7 @@ static void ipath_init_pe_variables(struct ipath_devdata *dd)
                INFINIPATH_E_INVALIDADDR | INFINIPATH_E_RESET;
 
 
+       dd->delay_mult = 2; /* SDR, 4X, can't change */
 }
 
 /* setup the MSI stuff again after a reset.  I'd like to just call
@@ -1329,6 +1381,9 @@ static int ipath_pe_early_init(struct ipath_devdata *dd)
         */
        dd->ipath_rcvhdrentsize = 24;
        dd->ipath_rcvhdrsize = IPATH_DFLT_RCVHDRSIZE;
+       dd->ipath_rhf_offset = 0;
+       dd->ipath_egrtidbase = (u64 __iomem *)
+               ((char __iomem *) dd->ipath_kregbase + dd->ipath_rcvegrbase);
 
        /*
         * To truly support a 4KB MTU (for usermode), we need to
@@ -1399,6 +1454,14 @@ static void ipath_pe_free_irq(struct ipath_devdata *dd)
        dd->ipath_irq = 0;
 }
 
+
+static struct ipath_message_header *
+ipath_pe_get_msgheader(struct ipath_devdata *dd, __le32 *rhf_addr)
+{
+       return (struct ipath_message_header *)
+               &rhf_addr[sizeof(u64) / sizeof(u32)];
+}
+
 static void ipath_pe_config_ports(struct ipath_devdata *dd, ushort cfgports)
 {
        dd->ipath_portcnt =
@@ -1534,6 +1597,88 @@ static int ipath_pe_txe_recover(struct ipath_devdata *dd)
        return 1;
 }
 
+/* no interrupt fallback for these chips */
+static int ipath_pe_nointr_fallback(struct ipath_devdata *dd)
+{
+       return 0;
+}
+
+
+/*
+ * reset the XGXS (between serdes and IBC).  Slightly less intrusive
+ * than resetting the IBC or external link state, and useful in some
+ * cases to cause some retraining.  To do this right, we reset IBC
+ * as well.
+ */
+static void ipath_pe_xgxs_reset(struct ipath_devdata *dd)
+{
+       u64 val, prev_val;
+
+       prev_val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_xgxsconfig);
+       val = prev_val | INFINIPATH_XGXS_RESET;
+       prev_val &= ~INFINIPATH_XGXS_RESET; /* be sure */
+       ipath_write_kreg(dd, dd->ipath_kregs->kr_control,
+                        dd->ipath_control & ~INFINIPATH_C_LINKENABLE);
+       ipath_write_kreg(dd, dd->ipath_kregs->kr_xgxsconfig, val);
+       ipath_read_kreg32(dd, dd->ipath_kregs->kr_scratch);
+       ipath_write_kreg(dd, dd->ipath_kregs->kr_xgxsconfig, prev_val);
+       ipath_write_kreg(dd, dd->ipath_kregs->kr_control,
+                        dd->ipath_control);
+}
+
+
+static int ipath_pe_get_ib_cfg(struct ipath_devdata *dd, int which)
+{
+       int ret;
+
+       switch (which) {
+       case IPATH_IB_CFG_LWID:
+               ret = dd->ipath_link_width_active;
+               break;
+       case IPATH_IB_CFG_SPD:
+               ret = dd->ipath_link_speed_active;
+               break;
+       case IPATH_IB_CFG_LWID_ENB:
+               ret = dd->ipath_link_width_enabled;
+               break;
+       case IPATH_IB_CFG_SPD_ENB:
+               ret = dd->ipath_link_speed_enabled;
+               break;
+       default:
+               ret =  -ENOTSUPP;
+               break;
+       }
+       return ret;
+}
+
+
+/* we assume range checking is already done, if needed */
+static int ipath_pe_set_ib_cfg(struct ipath_devdata *dd, int which, u32 val)
+{
+       int ret = 0;
+
+       if (which == IPATH_IB_CFG_LWID_ENB)
+               dd->ipath_link_width_enabled = val;
+       else if (which == IPATH_IB_CFG_SPD_ENB)
+               dd->ipath_link_speed_enabled = val;
+       else
+               ret = -ENOTSUPP;
+       return ret;
+}
+
+static void ipath_pe_config_jint(struct ipath_devdata *dd, u16 a, u16 b)
+{
+}
+
+
+static int ipath_pe_ib_updown(struct ipath_devdata *dd, int ibup, u64 ibcs)
+{
+       ipath_setup_pe_setextled(dd, ipath_ib_linkstate(dd, ibcs),
+               ipath_ib_linktrstate(dd, ibcs));
+       return 0;
+}
+
+
 /**
  * ipath_init_iba6120_funcs - set up the chip-specific function pointers
  * @dd: the infinipath device
@@ -1554,7 +1699,7 @@ void ipath_init_iba6120_funcs(struct ipath_devdata *dd)
        dd->ipath_f_bringup_serdes = ipath_pe_bringup_serdes;
        dd->ipath_f_clear_tids = ipath_pe_clear_tids;
        /*
-        * this may get changed after we read the chip revision,
+        * _f_put_tid may get changed after we read the chip revision,
         * but we start with the safe version for all revs
         */
        dd->ipath_f_put_tid = ipath_pe_put_tid;
@@ -1562,19 +1707,19 @@ void ipath_init_iba6120_funcs(struct ipath_devdata *dd)
        dd->ipath_f_setextled = ipath_setup_pe_setextled;
        dd->ipath_f_get_base_info = ipath_pe_get_base_info;
        dd->ipath_f_free_irq = ipath_pe_free_irq;
-
-       /* initialize chip-specific variables */
        dd->ipath_f_tidtemplate = ipath_pe_tidtemplate;
+       dd->ipath_f_intr_fallback = ipath_pe_nointr_fallback;
+       dd->ipath_f_xgxs_reset = ipath_pe_xgxs_reset;
+       dd->ipath_f_get_msgheader = ipath_pe_get_msgheader;
        dd->ipath_f_config_ports = ipath_pe_config_ports;
        dd->ipath_f_read_counters = ipath_pe_read_counters;
+       dd->ipath_f_get_ib_cfg = ipath_pe_get_ib_cfg;
+       dd->ipath_f_set_ib_cfg = ipath_pe_set_ib_cfg;
+       dd->ipath_f_config_jint = ipath_pe_config_jint;
+       dd->ipath_f_ib_updown = ipath_pe_ib_updown;
 
-       /*
-        * setup the register offsets, since they are different for each
-        * chip
-        */
-       dd->ipath_kregs = &ipath_pe_kregs;
-       dd->ipath_cregs = &ipath_pe_cregs;
 
+       /* initialize chip-specific variables */
        ipath_init_pe_variables(dd);
 }
 
index c0ecda35f2d98c455f1fc14af4b5c1e98f57e913..6a5fe0157330fa9e2dba44de5874c8ec4a3e6a7d 100644 (file)
@@ -191,6 +191,22 @@ struct ipath_skbinfo {
        dma_addr_t phys;
 };
 
+/*
+ * Possible IB config parameters for ipath_f_get/set_ib_cfg()
+ */
+#define IPATH_IB_CFG_LIDLMC 0 /* Get/set LID (LS16b) and Mask (MS16b) */
+#define IPATH_IB_CFG_HRTBT 1 /* Get/set Heartbeat off/enable/auto */
+#define IPATH_IB_HRTBT_ON 3 /* Heartbeat enabled, sent every 100msec */
+#define IPATH_IB_HRTBT_OFF 0 /* Heartbeat off */
+#define IPATH_IB_CFG_LWID_ENB 2 /* Get/set allowed Link-width */
+#define IPATH_IB_CFG_LWID 3 /* Get currently active Link-width */
+#define IPATH_IB_CFG_SPD_ENB 4 /* Get/set allowed Link speeds */
+#define IPATH_IB_CFG_SPD 5 /* Get current Link spd */
+#define IPATH_IB_CFG_RXPOL_ENB 6 /* Get/set Auto-RX-polarity enable */
+#define IPATH_IB_CFG_LREV_ENB 7 /* Get/set Auto-Lane-reversal enable */
+#define IPATH_IB_CFG_LINKLATENCY 8 /* Get Auto-Lane-reversal enable */
+
+
 struct ipath_devdata {
        struct list_head ipath_list;
 
@@ -231,6 +247,8 @@ struct ipath_devdata {
        struct _ipath_layer ipath_layer;
        /* setup intr */
        int (*ipath_f_intrsetup)(struct ipath_devdata *);
+       /* fallback to alternate interrupt type if possible */
+       int (*ipath_f_intr_fallback)(struct ipath_devdata *);
        /* setup on-chip bus config */
        int (*ipath_f_bus)(struct ipath_devdata *, struct pci_dev *);
        /* hard reset chip */
@@ -253,9 +271,18 @@ struct ipath_devdata {
        int (*ipath_f_get_base_info)(struct ipath_portdata *, void *);
        /* free irq */
        void (*ipath_f_free_irq)(struct ipath_devdata *);
+       struct ipath_message_header *(*ipath_f_get_msgheader)
+                                       (struct ipath_devdata *, __le32 *);
        void (*ipath_f_config_ports)(struct ipath_devdata *, ushort);
+       int (*ipath_f_get_ib_cfg)(struct ipath_devdata *, int);
+       int (*ipath_f_set_ib_cfg)(struct ipath_devdata *, int, u32);
+       void (*ipath_f_config_jint)(struct ipath_devdata *, u16 , u16);
        void (*ipath_f_read_counters)(struct ipath_devdata *,
-                                     struct infinipath_counters *);
+                                       struct infinipath_counters *);
+       void (*ipath_f_xgxs_reset)(struct ipath_devdata *);
+       /* per chip actions needed for IB Link up/down changes */
+       int (*ipath_f_ib_updown)(struct ipath_devdata *, int, u64);
+
        struct ipath_ibdev *verbs_dev;
        struct timer_list verbs_timer;
        /* total dwords sent (summed from counter) */
@@ -375,6 +402,7 @@ struct ipath_devdata {
        struct page **ipath_pageshadow;
        /* shadow copy of dma handles for exp tid pages */
        dma_addr_t *ipath_physshadow;
+       u64 __iomem *ipath_egrtidbase;
        /* lock to workaround chip bug 9437 */
        spinlock_t ipath_tid_lock;
        spinlock_t ipath_sendctrl_lock;
@@ -565,6 +593,14 @@ struct ipath_devdata {
        u8 ipath_pci_cacheline;
        /* LID mask control */
        u8 ipath_lmc;
+       /* link width supported */
+       u8 ipath_link_width_supported;
+       /* link speed supported */
+       u8 ipath_link_speed_supported;
+       u8 ipath_link_width_enabled;
+       u8 ipath_link_speed_enabled;
+       u8 ipath_link_width_active;
+       u8 ipath_link_speed_active;
        /* Rx Polarity inversion (compensate for ~tx on partner) */
        u8 ipath_rx_pol_inv;
 
@@ -599,6 +635,8 @@ struct ipath_devdata {
         */
        u32 ipath_i_rcvavail_mask;
        u32 ipath_i_rcvurg_mask;
+       u16 ipath_i_rcvurg_shift;
+       u16 ipath_i_rcvavail_shift;
 
        /*
         * Register bits for selecting i2c direction and values, used for
@@ -612,6 +650,29 @@ struct ipath_devdata {
        /* lock for doing RMW of shadows/regs for ExtCtrl and GPIO */
        spinlock_t ipath_gpio_lock;
 
+       /*
+        * IB link and linktraining states and masks that vary per chip in
+        * some way.  Set at init, to avoid each IB status change interrupt
+        */
+       u8 ibcs_ls_shift;
+       u8 ibcs_lts_mask;
+       u32 ibcs_mask;
+       u32 ib_init;
+       u32 ib_arm;
+       u32 ib_active;
+
+       u16 ipath_rhf_offset; /* offset of RHF within receive header entry */
+
+       /*
+        * shift/mask for linkcmd, linkinitcmd, maxpktlen in ibccontol
+        * reg. Changes for IBA7220
+        */
+       u8 ibcc_lic_mask; /* LinkInitCmd */
+       u8 ibcc_lc_shift; /* LinkCmd */
+       u8 ibcc_mpl_shift; /* Maxpktlen */
+
+       u8 delay_mult;
+
        /* used to override LED behavior */
        u8 ipath_led_override;  /* Substituted for normal value, if non-zero */
        u16 ipath_led_override_timeoff; /* delta to next timer event */
@@ -639,6 +700,10 @@ struct ipath_devdata {
         * each of the counters to increment.
         */
        struct ipath_eep_log_mask ipath_eep_st_masks[IPATH_EEP_LOG_CNT];
+
+       /* interrupt mitigation reload register info */
+       u16 ipath_jint_idle_ticks;      /* idle clock ticks */
+       u16 ipath_jint_max_packets;     /* max packets across all ports */
 };
 
 /* Private data for file operations */
@@ -937,6 +1002,27 @@ static inline u64 ipath_read_ireg(const struct ipath_devdata *dd, ipath_kreg r)
                ipath_read_kreg64(dd, r) : ipath_read_kreg32(dd, r);
 }
 
+/*
+ * from contents of IBCStatus (or a saved copy), return linkstate
+ * Report ACTIVE_DEFER as ACTIVE, because we treat them the same
+ * everywhere, anyway (and should be, for almost all purposes).
+ */
+static inline u32 ipath_ib_linkstate(struct ipath_devdata *dd, u64 ibcs)
+{
+       u32 state = (u32)(ibcs >> dd->ibcs_ls_shift) &
+               INFINIPATH_IBCS_LINKSTATE_MASK;
+       if (state == INFINIPATH_IBCS_L_STATE_ACT_DEFER)
+               state = INFINIPATH_IBCS_L_STATE_ACTIVE;
+       return state;
+}
+
+/* from contents of IBCStatus (or a saved copy), return linktrainingstate */
+static inline u32 ipath_ib_linktrstate(struct ipath_devdata *dd, u64 ibcs)
+{
+       return (u32)(ibcs >> INFINIPATH_IBCS_LINKTRAININGSTATE_SHIFT) &
+               dd->ibcs_lts_mask;
+}
+
 /*
  * sysfs interface.
  */