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); ...@@ -1575,9 +1575,11 @@ int t4_slow_intr_handler(struct adapter *adapter);
int t4_wait_dev_ready(void __iomem *regs); 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, int t4_link_l1cfg_core(struct adapter *adap, unsigned int mbox,
unsigned int port, struct link_config *lc, 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, static inline int t4_link_l1cfg(struct adapter *adapter, unsigned int mbox,
unsigned int port, struct link_config *lc) unsigned int port, struct link_config *lc)
......
...@@ -442,7 +442,7 @@ static unsigned int speed_to_fw_caps(int speed) ...@@ -442,7 +442,7 @@ static unsigned int speed_to_fw_caps(int speed)
* Link Mode Mask. * Link Mode Mask.
*/ */
static void fw_caps_to_lmm(enum fw_port_type port_type, 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) unsigned long *link_mode_mask)
{ {
#define SET_LMM(__lmm_name) \ #define SET_LMM(__lmm_name) \
...@@ -632,7 +632,10 @@ static int get_link_ksettings(struct net_device *dev, ...@@ -632,7 +632,10 @@ static int get_link_ksettings(struct net_device *dev,
fw_caps_to_lmm(pi->port_type, pi->link_cfg.pcaps, fw_caps_to_lmm(pi->port_type, pi->link_cfg.pcaps,
link_ksettings->link_modes.supported); 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); link_ksettings->link_modes.advertising);
fw_caps_to_lmm(pi->port_type, pi->link_cfg.lpacaps, fw_caps_to_lmm(pi->port_type, pi->link_cfg.lpacaps,
link_ksettings->link_modes.lp_advertising); link_ksettings->link_modes.lp_advertising);
...@@ -642,22 +645,6 @@ static int get_link_ksettings(struct net_device *dev, ...@@ -642,22 +645,6 @@ static int get_link_ksettings(struct net_device *dev,
: SPEED_UNKNOWN); : SPEED_UNKNOWN);
base->duplex = DUPLEX_FULL; 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; base->autoneg = pi->link_cfg.autoneg;
if (pi->link_cfg.pcaps & FW_PORT_CAP32_ANEG) if (pi->link_cfg.pcaps & FW_PORT_CAP32_ANEG)
ethtool_link_ksettings_add_link_mode(link_ksettings, ethtool_link_ksettings_add_link_mode(link_ksettings,
......
...@@ -3964,6 +3964,14 @@ void t4_ulprx_read_la(struct adapter *adap, u32 *la_buf) ...@@ -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) | \ #define ADVERT_MASK (FW_PORT_CAP32_SPEED_V(FW_PORT_CAP32_SPEED_M) | \
FW_PORT_CAP32_ANEG) FW_PORT_CAP32_ANEG)
...@@ -4061,6 +4069,9 @@ static inline enum cc_pause fwcap_to_cc_pause(fw_port_cap32_t fw_pause) ...@@ -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 */ /* Translate Common Code Pause specification into Firmware Port Capabilities */
static inline fw_port_cap32_t cc_to_fwcap_pause(enum cc_pause cc_pause) 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; fw_port_cap32_t fw_pause = 0;
if (cc_pause & PAUSE_RX) if (cc_pause & PAUSE_RX)
...@@ -4070,6 +4081,19 @@ static inline fw_port_cap32_t cc_to_fwcap_pause(enum cc_pause cc_pause) ...@@ -4070,6 +4081,19 @@ static inline fw_port_cap32_t cc_to_fwcap_pause(enum cc_pause cc_pause)
if (!(cc_pause & PAUSE_AUTONEG)) if (!(cc_pause & PAUSE_AUTONEG))
fw_pause |= FW_PORT_CAP32_FORCE_PAUSE; 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; return fw_pause;
} }
...@@ -4100,31 +4124,22 @@ static inline fw_port_cap32_t cc_to_fwcap_fec(enum cc_fec cc_fec) ...@@ -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 * @adapter: the adapter
* @mbox: the Firmware Mailbox to use
* @port: the Port ID * @port: the Port ID
* @lc: the Port's Link Configuration * @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. * Synthesize the Advertised Port Capabilities we'll be using based on
* - If the PHY can auto-negotiate first decide what to advertise, then * the base Advertised Port Capabilities (which have been filtered by
* enable/disable auto-negotiation as desired, and reset. * ADVERT_MASK) plus the individual controls for things like Pause
* - If the PHY does not auto-negotiate just reset it. * Frames, Forward Error Correction, MDI, etc.
* - 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, fw_port_cap32_t t4_link_acaps(struct adapter *adapter, unsigned int port,
unsigned int port, struct link_config *lc, struct link_config *lc)
bool sleep_ok, int timeout)
{ {
unsigned int fw_caps = adapter->params.fw_caps_support; fw_port_cap32_t fw_fc, fw_fec, acaps;
fw_port_cap32_t fw_fc, cc_fec, fw_fec, rcap;
struct fw_port_cmd cmd;
unsigned int fw_mdi; unsigned int fw_mdi;
int ret; char cc_fec;
fw_mdi = (FW_PORT_CAP32_MDI_V(FW_PORT_CAP32_MDI_AUTO) & lc->pcaps); 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, ...@@ -4151,18 +4166,15 @@ int t4_link_l1cfg_core(struct adapter *adapter, unsigned int mbox,
* init_link_config(). * init_link_config().
*/ */
if (!(lc->pcaps & FW_PORT_CAP32_ANEG)) { if (!(lc->pcaps & FW_PORT_CAP32_ANEG)) {
if (lc->autoneg == AUTONEG_ENABLE) acaps = lc->acaps | fw_fc | fw_fec;
return -EINVAL;
rcap = lc->acaps | fw_fc | fw_fec;
lc->fc = lc->requested_fc & ~PAUSE_AUTONEG; lc->fc = lc->requested_fc & ~PAUSE_AUTONEG;
lc->fec = cc_fec; lc->fec = cc_fec;
} else if (lc->autoneg == AUTONEG_DISABLE) { } 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->fc = lc->requested_fc & ~PAUSE_AUTONEG;
lc->fec = cc_fec; lc->fec = cc_fec;
} else { } 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 /* 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, ...@@ -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 * we need to exclude this from this check in order to maintain
* compatibility ... * compatibility ...
*/ */
if ((rcap & ~lc->pcaps) & ~FW_PORT_CAP32_FORCE_PAUSE) { if ((acaps & ~lc->pcaps) & ~FW_PORT_CAP32_FORCE_PAUSE) {
dev_err(adapter->pdev_dev, dev_err(adapter->pdev_dev, "Requested Port Capabilities %#x exceed Physical Port Capabilities %#x\n",
"Requested Port Capabilities %#x exceed Physical Port Capabilities %#x\n", acaps, lc->pcaps);
rcap, lc->pcaps);
return -EINVAL; return -EINVAL;
} }
/* And send that on to the Firmware ... 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;
}
/* Compute our Requested Port Capabilities and send that on to the
* Firmware.
*/
rcap = t4_link_acaps(adapter, port, lc);
memset(&cmd, 0, sizeof(cmd)); memset(&cmd, 0, sizeof(cmd));
cmd.op_to_portid = cpu_to_be32(FW_CMD_OP_V(FW_PORT_CMD) | cmd.op_to_portid = cpu_to_be32(FW_CMD_OP_V(FW_PORT_CMD) |
FW_CMD_REQUEST_F | FW_CMD_EXEC_F | FW_CMD_REQUEST_F | FW_CMD_EXEC_F |
...@@ -4211,7 +4258,7 @@ int t4_link_l1cfg_core(struct adapter *adapter, unsigned int mbox, ...@@ -4211,7 +4258,7 @@ int t4_link_l1cfg_core(struct adapter *adapter, unsigned int mbox,
rcap, -ret); rcap, -ret);
return ret; return ret;
} }
return ret; return 0;
} }
/** /**
......
...@@ -1479,22 +1479,6 @@ static int cxgb4vf_get_link_ksettings(struct net_device *dev, ...@@ -1479,22 +1479,6 @@ static int cxgb4vf_get_link_ksettings(struct net_device *dev,
base->duplex = DUPLEX_UNKNOWN; 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; base->autoneg = pi->link_cfg.autoneg;
if (pi->link_cfg.pcaps & FW_PORT_CAP32_ANEG) if (pi->link_cfg.pcaps & FW_PORT_CAP32_ANEG)
ethtool_link_ksettings_add_link_mode(link_ksettings, 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, ...@@ -313,7 +313,17 @@ int t4vf_wr_mbox_core(struct adapter *adapter, const void *cmd, int size,
return ret; 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) | \ #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) 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