提交 c4bce803 编写于 作者: D Dave Olson 提交者: Roland Dreier

IB/ipath: Add new chip-specific functions to older chips, consistent init

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: NDave Olson <dave.olson@qlogic.com>
Signed-off-by: NRoland Dreier <rolandd@cisco.com>
上级 73872733
...@@ -81,6 +81,16 @@ ...@@ -81,6 +81,16 @@
#define IPATH_IB_LINK_LOOPBACK 6 /* enable local loopback */ #define IPATH_IB_LINK_LOOPBACK 6 /* enable local loopback */
#define IPATH_IB_LINK_EXTERNAL 7 /* normal, disable 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 * stats maintained by the driver. For now, at least, this is global
* to all minor devices. * to all minor devices.
......
...@@ -329,6 +329,9 @@ static const struct ipath_cregs ipath_ht_cregs = { ...@@ -329,6 +329,9 @@ static const struct ipath_cregs ipath_ht_cregs = {
#define INFINIPATH_HWE_HTAPLL_RFSLIP 0x1000000000000000ULL #define INFINIPATH_HWE_HTAPLL_RFSLIP 0x1000000000000000ULL
#define INFINIPATH_HWE_SERDESPLLFAILED 0x2000000000000000ULL #define INFINIPATH_HWE_SERDESPLLFAILED 0x2000000000000000ULL
#define IBA6110_IBCS_LINKTRAININGSTATE_MASK 0xf
#define IBA6110_IBCS_LINKSTATE_SHIFT 4
/* kr_extstatus bits */ /* kr_extstatus bits */
#define INFINIPATH_EXTS_FREQSEL 0x2 #define INFINIPATH_EXTS_FREQSEL 0x2
#define INFINIPATH_EXTS_SERDESSEL 0x4 #define INFINIPATH_EXTS_SERDESSEL 0x4
...@@ -705,7 +708,6 @@ static int ipath_ht_boardname(struct ipath_devdata *dd, char *name, ...@@ -705,7 +708,6 @@ static int ipath_ht_boardname(struct ipath_devdata *dd, char *name,
"with ID %u\n", boardrev); "with ID %u\n", boardrev);
snprintf(name, namelen, "Unknown_InfiniPath_QHT7xxx_%u", snprintf(name, namelen, "Unknown_InfiniPath_QHT7xxx_%u",
boardrev); boardrev);
ret = 1;
break; break;
} }
if (n) if (n)
...@@ -1137,11 +1139,49 @@ static void ipath_setup_ht_setextled(struct ipath_devdata *dd, ...@@ -1137,11 +1139,49 @@ static void ipath_setup_ht_setextled(struct ipath_devdata *dd,
static void ipath_init_ht_variables(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_sda_num = _IPATH_GPIO_SDA_NUM;
dd->ipath_gpio_scl_num = _IPATH_GPIO_SCL_NUM; dd->ipath_gpio_scl_num = _IPATH_GPIO_SCL_NUM;
dd->ipath_gpio_sda = IPATH_GPIO_SDA; dd->ipath_gpio_sda = IPATH_GPIO_SDA;
dd->ipath_gpio_scl = IPATH_GPIO_SCL; 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. */ /* Fill in shifts for RcvCtrl. */
dd->ipath_r_portenable_shift = INFINIPATH_R_PORTENABLE_SHIFT; dd->ipath_r_portenable_shift = INFINIPATH_R_PORTENABLE_SHIFT;
dd->ipath_r_intravail_shift = INFINIPATH_R_INTRAVAIL_SHIFT; dd->ipath_r_intravail_shift = INFINIPATH_R_INTRAVAIL_SHIFT;
...@@ -1204,6 +1244,8 @@ static void ipath_init_ht_variables(struct ipath_devdata *dd) ...@@ -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_rcvavail_mask = INFINIPATH_I_RCVAVAIL_MASK;
dd->ipath_i_rcvurg_mask = INFINIPATH_I_RCVURG_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. * 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) ...@@ -1217,9 +1259,17 @@ static void ipath_init_ht_variables(struct ipath_devdata *dd)
INFINIPATH_HWE_RXEMEMPARITYERR_MASK << INFINIPATH_HWE_RXEMEMPARITYERR_MASK <<
INFINIPATH_HWE_RXEMEMPARITYERR_SHIFT; INFINIPATH_HWE_RXEMEMPARITYERR_SHIFT;
dd->ipath_eep_st_masks[2].errs_to_log = dd->ipath_eep_st_masks[2].errs_to_log = INFINIPATH_E_RESET;
INFINIPATH_E_INVALIDADDR | 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) ...@@ -1281,6 +1331,9 @@ static void ipath_ht_init_hwerrors(struct ipath_devdata *dd)
dd->ipath_hwerrmask = val; dd->ipath_hwerrmask = val;
} }
/** /**
* ipath_ht_bringup_serdes - bring up the serdes * ipath_ht_bringup_serdes - bring up the serdes
* @dd: the infinipath device * @dd: the infinipath device
...@@ -1439,6 +1492,7 @@ static void ipath_ht_put_tid(struct ipath_devdata *dd, ...@@ -1439,6 +1492,7 @@ static void ipath_ht_put_tid(struct ipath_devdata *dd,
pa |= lenvalid | INFINIPATH_RT_VALID; pa |= lenvalid | INFINIPATH_RT_VALID;
} }
} }
writeq(pa, tidptr); writeq(pa, tidptr);
} }
...@@ -1644,6 +1698,13 @@ static void ipath_ht_free_irq(struct ipath_devdata *dd) ...@@ -1644,6 +1698,13 @@ static void ipath_ht_free_irq(struct ipath_devdata *dd)
dd->ipath_intconfig = 0; 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) static void ipath_ht_config_ports(struct ipath_devdata *dd, ushort cfgports)
{ {
dd->ipath_portcnt = dd->ipath_portcnt =
...@@ -1757,6 +1818,90 @@ static void ipath_ht_read_counters(struct ipath_devdata *dd, ...@@ -1757,6 +1818,90 @@ static void ipath_ht_read_counters(struct ipath_devdata *dd,
cntrs->RxDlidFltrCnt = 0; 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 * ipath_init_iba6110_funcs - set up the chip-specific function pointers
* @dd: the infinipath device * @dd: the infinipath device
...@@ -1781,24 +1926,19 @@ void ipath_init_iba6110_funcs(struct ipath_devdata *dd) ...@@ -1781,24 +1926,19 @@ void ipath_init_iba6110_funcs(struct ipath_devdata *dd)
dd->ipath_f_setextled = ipath_setup_ht_setextled; dd->ipath_f_setextled = ipath_setup_ht_setextled;
dd->ipath_f_get_base_info = ipath_ht_get_base_info; dd->ipath_f_get_base_info = ipath_ht_get_base_info;
dd->ipath_f_free_irq = ipath_ht_free_irq; 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_config_ports = ipath_ht_config_ports;
dd->ipath_f_read_counters = ipath_ht_read_counters; 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 * 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); ipath_init_ht_variables(dd);
} }
...@@ -329,6 +329,9 @@ static const struct ipath_cregs ipath_pe_cregs = { ...@@ -329,6 +329,9 @@ static const struct ipath_cregs ipath_pe_cregs = {
#define INFINIPATH_HWE_PCIE0PLLFAILED 0x0800000000000000ULL #define INFINIPATH_HWE_PCIE0PLLFAILED 0x0800000000000000ULL
#define INFINIPATH_HWE_SERDESPLLFAILED 0x1000000000000000ULL #define INFINIPATH_HWE_SERDESPLLFAILED 0x1000000000000000ULL
#define IBA6120_IBCS_LINKTRAININGSTATE_MASK 0xf
#define IBA6120_IBCS_LINKSTATE_SHIFT 4
/* kr_extstatus bits */ /* kr_extstatus bits */
#define INFINIPATH_EXTS_FREQSEL 0x2 #define INFINIPATH_EXTS_FREQSEL 0x2
#define INFINIPATH_EXTS_SERDESSEL 0x4 #define INFINIPATH_EXTS_SERDESSEL 0x4
...@@ -936,11 +939,26 @@ static int ipath_setup_pe_config(struct ipath_devdata *dd, ...@@ -936,11 +939,26 @@ static int ipath_setup_pe_config(struct ipath_devdata *dd,
else else
ipath_dev_err(dd, "Can't find PCI Express " ipath_dev_err(dd, "Can't find PCI Express "
"capability!\n"); "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; return 0;
} }
static void ipath_init_pe_variables(struct ipath_devdata *dd) 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, * bits for selecting i2c direction and values,
* used for I2C serial flash * used for I2C serial flash
...@@ -950,6 +968,37 @@ static void ipath_init_pe_variables(struct ipath_devdata *dd) ...@@ -950,6 +968,37 @@ static void ipath_init_pe_variables(struct ipath_devdata *dd)
dd->ipath_gpio_sda = IPATH_GPIO_SDA; dd->ipath_gpio_sda = IPATH_GPIO_SDA;
dd->ipath_gpio_scl = IPATH_GPIO_SCL; 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. */ /* Fill in shifts for RcvCtrl. */
dd->ipath_r_portenable_shift = INFINIPATH_R_PORTENABLE_SHIFT; dd->ipath_r_portenable_shift = INFINIPATH_R_PORTENABLE_SHIFT;
dd->ipath_r_intravail_shift = INFINIPATH_R_INTRAVAIL_SHIFT; dd->ipath_r_intravail_shift = INFINIPATH_R_INTRAVAIL_SHIFT;
...@@ -1003,6 +1052,8 @@ static void ipath_init_pe_variables(struct ipath_devdata *dd) ...@@ -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_rcvavail_mask = INFINIPATH_I_RCVAVAIL_MASK;
dd->ipath_i_rcvurg_mask = INFINIPATH_I_RCVURG_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. * 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) ...@@ -1024,6 +1075,7 @@ static void ipath_init_pe_variables(struct ipath_devdata *dd)
INFINIPATH_E_INVALIDADDR | INFINIPATH_E_RESET; 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 /* 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) ...@@ -1329,6 +1381,9 @@ static int ipath_pe_early_init(struct ipath_devdata *dd)
*/ */
dd->ipath_rcvhdrentsize = 24; dd->ipath_rcvhdrentsize = 24;
dd->ipath_rcvhdrsize = IPATH_DFLT_RCVHDRSIZE; 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 * 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) ...@@ -1399,6 +1454,14 @@ static void ipath_pe_free_irq(struct ipath_devdata *dd)
dd->ipath_irq = 0; 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) static void ipath_pe_config_ports(struct ipath_devdata *dd, ushort cfgports)
{ {
dd->ipath_portcnt = dd->ipath_portcnt =
...@@ -1534,6 +1597,88 @@ static int ipath_pe_txe_recover(struct ipath_devdata *dd) ...@@ -1534,6 +1597,88 @@ static int ipath_pe_txe_recover(struct ipath_devdata *dd)
return 1; 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 * ipath_init_iba6120_funcs - set up the chip-specific function pointers
* @dd: the infinipath device * @dd: the infinipath device
...@@ -1554,7 +1699,7 @@ void ipath_init_iba6120_funcs(struct ipath_devdata *dd) ...@@ -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_bringup_serdes = ipath_pe_bringup_serdes;
dd->ipath_f_clear_tids = ipath_pe_clear_tids; 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 * but we start with the safe version for all revs
*/ */
dd->ipath_f_put_tid = ipath_pe_put_tid; dd->ipath_f_put_tid = ipath_pe_put_tid;
...@@ -1562,19 +1707,19 @@ void ipath_init_iba6120_funcs(struct ipath_devdata *dd) ...@@ -1562,19 +1707,19 @@ void ipath_init_iba6120_funcs(struct ipath_devdata *dd)
dd->ipath_f_setextled = ipath_setup_pe_setextled; dd->ipath_f_setextled = ipath_setup_pe_setextled;
dd->ipath_f_get_base_info = ipath_pe_get_base_info; dd->ipath_f_get_base_info = ipath_pe_get_base_info;
dd->ipath_f_free_irq = ipath_pe_free_irq; dd->ipath_f_free_irq = ipath_pe_free_irq;
/* initialize chip-specific variables */
dd->ipath_f_tidtemplate = ipath_pe_tidtemplate; 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_config_ports = ipath_pe_config_ports;
dd->ipath_f_read_counters = ipath_pe_read_counters; 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); ipath_init_pe_variables(dd);
} }
...@@ -191,6 +191,22 @@ struct ipath_skbinfo { ...@@ -191,6 +191,22 @@ struct ipath_skbinfo {
dma_addr_t phys; 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 ipath_devdata {
struct list_head ipath_list; struct list_head ipath_list;
...@@ -231,6 +247,8 @@ struct ipath_devdata { ...@@ -231,6 +247,8 @@ struct ipath_devdata {
struct _ipath_layer ipath_layer; struct _ipath_layer ipath_layer;
/* setup intr */ /* setup intr */
int (*ipath_f_intrsetup)(struct ipath_devdata *); 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 */ /* setup on-chip bus config */
int (*ipath_f_bus)(struct ipath_devdata *, struct pci_dev *); int (*ipath_f_bus)(struct ipath_devdata *, struct pci_dev *);
/* hard reset chip */ /* hard reset chip */
...@@ -253,9 +271,18 @@ struct ipath_devdata { ...@@ -253,9 +271,18 @@ struct ipath_devdata {
int (*ipath_f_get_base_info)(struct ipath_portdata *, void *); int (*ipath_f_get_base_info)(struct ipath_portdata *, void *);
/* free irq */ /* free irq */
void (*ipath_f_free_irq)(struct ipath_devdata *); 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); 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 *, 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 ipath_ibdev *verbs_dev;
struct timer_list verbs_timer; struct timer_list verbs_timer;
/* total dwords sent (summed from counter) */ /* total dwords sent (summed from counter) */
...@@ -375,6 +402,7 @@ struct ipath_devdata { ...@@ -375,6 +402,7 @@ struct ipath_devdata {
struct page **ipath_pageshadow; struct page **ipath_pageshadow;
/* shadow copy of dma handles for exp tid pages */ /* shadow copy of dma handles for exp tid pages */
dma_addr_t *ipath_physshadow; dma_addr_t *ipath_physshadow;
u64 __iomem *ipath_egrtidbase;
/* lock to workaround chip bug 9437 */ /* lock to workaround chip bug 9437 */
spinlock_t ipath_tid_lock; spinlock_t ipath_tid_lock;
spinlock_t ipath_sendctrl_lock; spinlock_t ipath_sendctrl_lock;
...@@ -565,6 +593,14 @@ struct ipath_devdata { ...@@ -565,6 +593,14 @@ struct ipath_devdata {
u8 ipath_pci_cacheline; u8 ipath_pci_cacheline;
/* LID mask control */ /* LID mask control */
u8 ipath_lmc; 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) */ /* Rx Polarity inversion (compensate for ~tx on partner) */
u8 ipath_rx_pol_inv; u8 ipath_rx_pol_inv;
...@@ -599,6 +635,8 @@ struct ipath_devdata { ...@@ -599,6 +635,8 @@ struct ipath_devdata {
*/ */
u32 ipath_i_rcvavail_mask; u32 ipath_i_rcvavail_mask;
u32 ipath_i_rcvurg_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 * Register bits for selecting i2c direction and values, used for
...@@ -612,6 +650,29 @@ struct ipath_devdata { ...@@ -612,6 +650,29 @@ struct ipath_devdata {
/* lock for doing RMW of shadows/regs for ExtCtrl and GPIO */ /* lock for doing RMW of shadows/regs for ExtCtrl and GPIO */
spinlock_t ipath_gpio_lock; 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 */ /* used to override LED behavior */
u8 ipath_led_override; /* Substituted for normal value, if non-zero */ u8 ipath_led_override; /* Substituted for normal value, if non-zero */
u16 ipath_led_override_timeoff; /* delta to next timer event */ u16 ipath_led_override_timeoff; /* delta to next timer event */
...@@ -639,6 +700,10 @@ struct ipath_devdata { ...@@ -639,6 +700,10 @@ struct ipath_devdata {
* each of the counters to increment. * each of the counters to increment.
*/ */
struct ipath_eep_log_mask ipath_eep_st_masks[IPATH_EEP_LOG_CNT]; 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 */ /* Private data for file operations */
...@@ -937,6 +1002,27 @@ static inline u64 ipath_read_ireg(const struct ipath_devdata *dd, ipath_kreg r) ...@@ -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); 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. * sysfs interface.
*/ */
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册