Commit 9f764898 authored by Vishal Kulkarni's avatar Vishal Kulkarni Committed by David S. Miller

cxgb4/cxgb4vf: Display advertised FEC in ethtool

This patch advertises Forward Error Correction in ethtool
Signed-off-by: default avatarCasey Leedom <leedom@chelsio.com>
Signed-off-by: default avatarVishal Kulkarni <vishal@chelsio.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 5d10de34
......@@ -1575,9 +1575,11 @@ int t4_slow_intr_handler(struct adapter *adapter);
int t4_wait_dev_ready(void __iomem *regs);
fw_port_cap32_t t4_link_acaps(struct adapter *adapter, unsigned int port,
struct link_config *lc);
int t4_link_l1cfg_core(struct adapter *adap, unsigned int mbox,
unsigned int port, struct link_config *lc,
bool sleep_ok, int timeout);
u8 sleep_ok, int timeout);
static inline int t4_link_l1cfg(struct adapter *adapter, unsigned int mbox,
unsigned int port, struct link_config *lc)
......
......@@ -442,7 +442,7 @@ static unsigned int speed_to_fw_caps(int speed)
* Link Mode Mask.
*/
static void fw_caps_to_lmm(enum fw_port_type port_type,
unsigned int fw_caps,
fw_port_cap32_t fw_caps,
unsigned long *link_mode_mask)
{
#define SET_LMM(__lmm_name) \
......@@ -632,7 +632,10 @@ static int get_link_ksettings(struct net_device *dev,
fw_caps_to_lmm(pi->port_type, pi->link_cfg.pcaps,
link_ksettings->link_modes.supported);
fw_caps_to_lmm(pi->port_type, pi->link_cfg.acaps,
fw_caps_to_lmm(pi->port_type,
t4_link_acaps(pi->adapter,
pi->lport,
&pi->link_cfg),
link_ksettings->link_modes.advertising);
fw_caps_to_lmm(pi->port_type, pi->link_cfg.lpacaps,
link_ksettings->link_modes.lp_advertising);
......@@ -642,22 +645,6 @@ static int get_link_ksettings(struct net_device *dev,
: SPEED_UNKNOWN);
base->duplex = DUPLEX_FULL;
if (pi->link_cfg.fc & PAUSE_RX) {
if (pi->link_cfg.fc & PAUSE_TX) {
ethtool_link_ksettings_add_link_mode(link_ksettings,
advertising,
Pause);
} else {
ethtool_link_ksettings_add_link_mode(link_ksettings,
advertising,
Asym_Pause);
}
} else if (pi->link_cfg.fc & PAUSE_TX) {
ethtool_link_ksettings_add_link_mode(link_ksettings,
advertising,
Asym_Pause);
}
base->autoneg = pi->link_cfg.autoneg;
if (pi->link_cfg.pcaps & FW_PORT_CAP32_ANEG)
ethtool_link_ksettings_add_link_mode(link_ksettings,
......
......@@ -3964,6 +3964,14 @@ void t4_ulprx_read_la(struct adapter *adap, u32 *la_buf)
}
}
/* The ADVERT_MASK is used to mask out all of the Advertised Firmware Port
* Capabilities which we control with separate controls -- see, for instance,
* Pause Frames and Forward Error Correction. In order to determine what the
* full set of Advertised Port Capabilities are, the base Advertised Port
* Capabilities (masked by ADVERT_MASK) must be combined with the Advertised
* Port Capabilities associated with those other controls. See
* t4_link_acaps() for how this is done.
*/
#define ADVERT_MASK (FW_PORT_CAP32_SPEED_V(FW_PORT_CAP32_SPEED_M) | \
FW_PORT_CAP32_ANEG)
......@@ -4061,6 +4069,9 @@ static inline enum cc_pause fwcap_to_cc_pause(fw_port_cap32_t fw_pause)
/* Translate Common Code Pause specification into Firmware Port Capabilities */
static inline fw_port_cap32_t cc_to_fwcap_pause(enum cc_pause cc_pause)
{
/* Translate orthogonal RX/TX Pause Controls for L1 Configure
* commands, etc.
*/
fw_port_cap32_t fw_pause = 0;
if (cc_pause & PAUSE_RX)
......@@ -4070,6 +4081,19 @@ static inline fw_port_cap32_t cc_to_fwcap_pause(enum cc_pause cc_pause)
if (!(cc_pause & PAUSE_AUTONEG))
fw_pause |= FW_PORT_CAP32_FORCE_PAUSE;
/* Translate orthogonal Pause controls into IEEE 802.3 Pause,
* Asymetrical Pause for use in reporting to upper layer OS code, etc.
* Note that these bits are ignored in L1 Configure commands.
*/
if (cc_pause & PAUSE_RX) {
if (cc_pause & PAUSE_TX)
fw_pause |= FW_PORT_CAP32_802_3_PAUSE;
else
fw_pause |= FW_PORT_CAP32_802_3_ASM_DIR;
} else if (cc_pause & PAUSE_TX) {
fw_pause |= FW_PORT_CAP32_802_3_ASM_DIR;
}
return fw_pause;
}
......@@ -4100,31 +4124,22 @@ static inline fw_port_cap32_t cc_to_fwcap_fec(enum cc_fec cc_fec)
}
/**
* t4_link_l1cfg - apply link configuration to MAC/PHY
* t4_link_acaps - compute Link Advertised Port Capabilities
* @adapter: the adapter
* @mbox: the Firmware Mailbox to use
* @port: the Port ID
* @lc: the Port's Link Configuration
* @sleep_ok: if true we may sleep while awaiting command completion
* @timeout: time to wait for command to finish before timing out
* (negative implies @sleep_ok=false)
*
* Set up a port's MAC and PHY according to a desired link configuration.
* - If the PHY can auto-negotiate first decide what to advertise, then
* enable/disable auto-negotiation as desired, and reset.
* - If the PHY does not auto-negotiate just reset it.
* - If auto-negotiation is off set the MAC to the proper speed/duplex/FC,
* otherwise do it later based on the outcome of auto-negotiation.
* Synthesize the Advertised Port Capabilities we'll be using based on
* the base Advertised Port Capabilities (which have been filtered by
* ADVERT_MASK) plus the individual controls for things like Pause
* Frames, Forward Error Correction, MDI, etc.
*/
int t4_link_l1cfg_core(struct adapter *adapter, unsigned int mbox,
unsigned int port, struct link_config *lc,
bool sleep_ok, int timeout)
fw_port_cap32_t t4_link_acaps(struct adapter *adapter, unsigned int port,
struct link_config *lc)
{
unsigned int fw_caps = adapter->params.fw_caps_support;
fw_port_cap32_t fw_fc, cc_fec, fw_fec, rcap;
struct fw_port_cmd cmd;
fw_port_cap32_t fw_fc, fw_fec, acaps;
unsigned int fw_mdi;
int ret;
char cc_fec;
fw_mdi = (FW_PORT_CAP32_MDI_V(FW_PORT_CAP32_MDI_AUTO) & lc->pcaps);
......@@ -4151,18 +4166,15 @@ int t4_link_l1cfg_core(struct adapter *adapter, unsigned int mbox,
* init_link_config().
*/
if (!(lc->pcaps & FW_PORT_CAP32_ANEG)) {
if (lc->autoneg == AUTONEG_ENABLE)
return -EINVAL;
rcap = lc->acaps | fw_fc | fw_fec;
acaps = lc->acaps | fw_fc | fw_fec;
lc->fc = lc->requested_fc & ~PAUSE_AUTONEG;
lc->fec = cc_fec;
} else if (lc->autoneg == AUTONEG_DISABLE) {
rcap = lc->speed_caps | fw_fc | fw_fec | fw_mdi;
acaps = lc->speed_caps | fw_fc | fw_fec | fw_mdi;
lc->fc = lc->requested_fc & ~PAUSE_AUTONEG;
lc->fec = cc_fec;
} else {
rcap = lc->acaps | fw_fc | fw_fec | fw_mdi;
acaps = lc->acaps | fw_fc | fw_fec | fw_mdi;
}
/* Some Requested Port Capabilities are trivially wrong if they exceed
......@@ -4173,15 +4185,50 @@ int t4_link_l1cfg_core(struct adapter *adapter, unsigned int mbox,
* we need to exclude this from this check in order to maintain
* compatibility ...
*/
if ((rcap & ~lc->pcaps) & ~FW_PORT_CAP32_FORCE_PAUSE) {
dev_err(adapter->pdev_dev,
"Requested Port Capabilities %#x exceed Physical Port Capabilities %#x\n",
rcap, lc->pcaps);
if ((acaps & ~lc->pcaps) & ~FW_PORT_CAP32_FORCE_PAUSE) {
dev_err(adapter->pdev_dev, "Requested Port Capabilities %#x exceed Physical Port Capabilities %#x\n",
acaps, lc->pcaps);
return -EINVAL;
}
return acaps;
}
/**
* t4_link_l1cfg_core - apply link configuration to MAC/PHY
* @adapter: the adapter
* @mbox: the Firmware Mailbox to use
* @port: the Port ID
* @lc: the Port's Link Configuration
* @sleep_ok: if true we may sleep while awaiting command completion
* @timeout: time to wait for command to finish before timing out
* (negative implies @sleep_ok=false)
*
* Set up a port's MAC and PHY according to a desired link configuration.
* - If the PHY can auto-negotiate first decide what to advertise, then
* enable/disable auto-negotiation as desired, and reset.
* - If the PHY does not auto-negotiate just reset it.
* - If auto-negotiation is off set the MAC to the proper speed/duplex/FC,
* otherwise do it later based on the outcome of auto-negotiation.
*/
int t4_link_l1cfg_core(struct adapter *adapter, unsigned int mbox,
unsigned int port, struct link_config *lc,
u8 sleep_ok, int timeout)
{
unsigned int fw_caps = adapter->params.fw_caps_support;
struct fw_port_cmd cmd;
fw_port_cap32_t rcap;
int ret;
if (!(lc->pcaps & FW_PORT_CAP32_ANEG) &&
lc->autoneg == AUTONEG_ENABLE) {
return -EINVAL;
}
/* And send that on to the Firmware ...
/* Compute our Requested Port Capabilities and send that on to the
* Firmware.
*/
rcap = t4_link_acaps(adapter, port, lc);
memset(&cmd, 0, sizeof(cmd));
cmd.op_to_portid = cpu_to_be32(FW_CMD_OP_V(FW_PORT_CMD) |
FW_CMD_REQUEST_F | FW_CMD_EXEC_F |
......@@ -4211,7 +4258,7 @@ int t4_link_l1cfg_core(struct adapter *adapter, unsigned int mbox,
rcap, -ret);
return ret;
}
return ret;
return 0;
}
/**
......
......@@ -1479,22 +1479,6 @@ static int cxgb4vf_get_link_ksettings(struct net_device *dev,
base->duplex = DUPLEX_UNKNOWN;
}
if (pi->link_cfg.fc & PAUSE_RX) {
if (pi->link_cfg.fc & PAUSE_TX) {
ethtool_link_ksettings_add_link_mode(link_ksettings,
advertising,
Pause);
} else {
ethtool_link_ksettings_add_link_mode(link_ksettings,
advertising,
Asym_Pause);
}
} else if (pi->link_cfg.fc & PAUSE_TX) {
ethtool_link_ksettings_add_link_mode(link_ksettings,
advertising,
Asym_Pause);
}
base->autoneg = pi->link_cfg.autoneg;
if (pi->link_cfg.pcaps & FW_PORT_CAP32_ANEG)
ethtool_link_ksettings_add_link_mode(link_ksettings,
......
......@@ -313,7 +313,17 @@ int t4vf_wr_mbox_core(struct adapter *adapter, const void *cmd, int size,
return ret;
}
/* In the Physical Function Driver Common Code, the ADVERT_MASK is used to
* mask out bits in the Advertised Port Capabilities which are managed via
* separate controls, like Pause Frames and Forward Error Correction. In the
* Virtual Function Common Code, since we never perform L1 Configuration on
* the Link, the only things we really need to filter out are things which
* we decode and report separately like Speed.
*/
#define ADVERT_MASK (FW_PORT_CAP32_SPEED_V(FW_PORT_CAP32_SPEED_M) | \
FW_PORT_CAP32_802_3_PAUSE | \
FW_PORT_CAP32_802_3_ASM_DIR | \
FW_PORT_CAP32_FEC_V(FW_PORT_CAP32_FEC_M) | \
FW_PORT_CAP32_ANEG)
/**
......
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