Commit 30fc5c31 authored by Bryan O'Sullivan's avatar Bryan O'Sullivan Committed by Roland Dreier

IB/ipath: control receive polarity inversion

Signed-off-by: default avatarBryan O'Sullivan <bryan.osullivan@qlogic.com>
Signed-off-by: default avatarRoland Dreier <rolandd@cisco.com>
parent e35d710d
...@@ -2116,5 +2116,22 @@ int ipath_reset_device(int unit) ...@@ -2116,5 +2116,22 @@ int ipath_reset_device(int unit)
return ret; return ret;
} }
int ipath_set_rx_pol_inv(struct ipath_devdata *dd, u8 new_pol_inv)
{
u64 val;
if ( new_pol_inv > INFINIPATH_XGXS_RX_POL_MASK ) {
return -1;
}
if ( dd->ipath_rx_pol_inv != new_pol_inv ) {
dd->ipath_rx_pol_inv = new_pol_inv;
val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_xgxsconfig);
val &= ~(INFINIPATH_XGXS_RX_POL_MASK <<
INFINIPATH_XGXS_RX_POL_SHIFT);
val |= ((u64)dd->ipath_rx_pol_inv) <<
INFINIPATH_XGXS_RX_POL_SHIFT;
ipath_write_kreg(dd, dd->ipath_kregs->kr_xgxsconfig, val);
}
return 0;
}
module_init(infinipath_init); module_init(infinipath_init);
module_exit(infinipath_cleanup); module_exit(infinipath_cleanup);
...@@ -1290,6 +1290,15 @@ static int ipath_ht_bringup_serdes(struct ipath_devdata *dd) ...@@ -1290,6 +1290,15 @@ static int ipath_ht_bringup_serdes(struct ipath_devdata *dd)
val &= ~INFINIPATH_XGXS_RESET; val &= ~INFINIPATH_XGXS_RESET;
change = 1; change = 1;
} }
if (((val >> INFINIPATH_XGXS_RX_POL_SHIFT) &
INFINIPATH_XGXS_RX_POL_MASK) != dd->ipath_rx_pol_inv ) {
/* need to compensate for Tx inversion in partner */
val &= ~(INFINIPATH_XGXS_RX_POL_MASK <<
INFINIPATH_XGXS_RX_POL_SHIFT);
val |= dd->ipath_rx_pol_inv <<
INFINIPATH_XGXS_RX_POL_SHIFT;
change = 1;
}
if (change) if (change)
ipath_write_kreg(dd, dd->ipath_kregs->kr_xgxsconfig, val); ipath_write_kreg(dd, dd->ipath_kregs->kr_xgxsconfig, val);
......
...@@ -654,6 +654,15 @@ static int ipath_pe_bringup_serdes(struct ipath_devdata *dd) ...@@ -654,6 +654,15 @@ static int ipath_pe_bringup_serdes(struct ipath_devdata *dd)
val &= ~INFINIPATH_XGXS_RESET; val &= ~INFINIPATH_XGXS_RESET;
change = 1; change = 1;
} }
if (((val >> INFINIPATH_XGXS_RX_POL_SHIFT) &
INFINIPATH_XGXS_RX_POL_MASK) != dd->ipath_rx_pol_inv ) {
/* need to compensate for Tx inversion in partner */
val &= ~(INFINIPATH_XGXS_RX_POL_MASK <<
INFINIPATH_XGXS_RX_POL_SHIFT);
val |= dd->ipath_rx_pol_inv <<
INFINIPATH_XGXS_RX_POL_SHIFT;
change = 1;
}
if (change) if (change)
ipath_write_kreg(dd, dd->ipath_kregs->kr_xgxsconfig, val); ipath_write_kreg(dd, dd->ipath_kregs->kr_xgxsconfig, val);
......
...@@ -503,6 +503,8 @@ struct ipath_devdata { ...@@ -503,6 +503,8 @@ struct ipath_devdata {
u8 ipath_pci_cacheline; u8 ipath_pci_cacheline;
/* LID mask control */ /* LID mask control */
u8 ipath_lmc; u8 ipath_lmc;
/* Rx Polarity inversion (compensate for ~tx on partner) */
u8 ipath_rx_pol_inv;
/* local link integrity counter */ /* local link integrity counter */
u32 ipath_lli_counter; u32 ipath_lli_counter;
...@@ -567,6 +569,7 @@ void ipath_get_faststats(unsigned long); ...@@ -567,6 +569,7 @@ void ipath_get_faststats(unsigned long);
int ipath_set_linkstate(struct ipath_devdata *, u8); int ipath_set_linkstate(struct ipath_devdata *, u8);
int ipath_set_mtu(struct ipath_devdata *, u16); int ipath_set_mtu(struct ipath_devdata *, u16);
int ipath_set_lid(struct ipath_devdata *, u32, u8); int ipath_set_lid(struct ipath_devdata *, u32, u8);
int ipath_set_rx_pol_inv(struct ipath_devdata *dd, u8 new_pol_inv);
/* for use in system calls, where we want to know device type, etc. */ /* for use in system calls, where we want to know device type, etc. */
#define port_fp(fp) ((struct ipath_portdata *) (fp)->private_data) #define port_fp(fp) ((struct ipath_portdata *) (fp)->private_data)
......
...@@ -282,6 +282,8 @@ ...@@ -282,6 +282,8 @@
#define INFINIPATH_XGXS_RESET 0x7ULL #define INFINIPATH_XGXS_RESET 0x7ULL
#define INFINIPATH_XGXS_MDIOADDR_MASK 0xfULL #define INFINIPATH_XGXS_MDIOADDR_MASK 0xfULL
#define INFINIPATH_XGXS_MDIOADDR_SHIFT 4 #define INFINIPATH_XGXS_MDIOADDR_SHIFT 4
#define INFINIPATH_XGXS_RX_POL_SHIFT 19
#define INFINIPATH_XGXS_RX_POL_MASK 0xfULL
#define INFINIPATH_RT_ADDR_MASK 0xFFFFFFFFFFULL /* 40 bits valid */ #define INFINIPATH_RT_ADDR_MASK 0xFFFFFFFFFFULL /* 40 bits valid */
......
...@@ -561,6 +561,33 @@ static ssize_t store_enabled(struct device *dev, ...@@ -561,6 +561,33 @@ static ssize_t store_enabled(struct device *dev,
return ret; return ret;
} }
static ssize_t store_rx_pol_inv(struct device *dev,
struct device_attribute *attr,
const char *buf,
size_t count)
{
struct ipath_devdata *dd = dev_get_drvdata(dev);
int ret, r;
u16 val;
ret = ipath_parse_ushort(buf, &val);
if (ret < 0)
goto invalid;
r = ipath_set_rx_pol_inv(dd, val);
if (r < 0) {
ret = r;
goto bail;
}
goto bail;
invalid:
ipath_dev_err(dd, "attempt to set invalid Rx Polarity invert\n");
bail:
return ret;
}
static DRIVER_ATTR(num_units, S_IRUGO, show_num_units, NULL); static DRIVER_ATTR(num_units, S_IRUGO, show_num_units, NULL);
static DRIVER_ATTR(version, S_IRUGO, show_version, NULL); static DRIVER_ATTR(version, S_IRUGO, show_version, NULL);
...@@ -587,6 +614,7 @@ static DEVICE_ATTR(status, S_IRUGO, show_status, NULL); ...@@ -587,6 +614,7 @@ static DEVICE_ATTR(status, S_IRUGO, show_status, NULL);
static DEVICE_ATTR(status_str, S_IRUGO, show_status_str, NULL); static DEVICE_ATTR(status_str, S_IRUGO, show_status_str, NULL);
static DEVICE_ATTR(boardversion, S_IRUGO, show_boardversion, NULL); static DEVICE_ATTR(boardversion, S_IRUGO, show_boardversion, NULL);
static DEVICE_ATTR(unit, S_IRUGO, show_unit, NULL); static DEVICE_ATTR(unit, S_IRUGO, show_unit, NULL);
static DEVICE_ATTR(rx_pol_inv, S_IWUSR, NULL, store_rx_pol_inv);
static struct attribute *dev_attributes[] = { static struct attribute *dev_attributes[] = {
&dev_attr_guid.attr, &dev_attr_guid.attr,
...@@ -601,6 +629,7 @@ static struct attribute *dev_attributes[] = { ...@@ -601,6 +629,7 @@ static struct attribute *dev_attributes[] = {
&dev_attr_boardversion.attr, &dev_attr_boardversion.attr,
&dev_attr_unit.attr, &dev_attr_unit.attr,
&dev_attr_enabled.attr, &dev_attr_enabled.attr,
&dev_attr_rx_pol_inv.attr,
NULL NULL
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment