cxgb4/cxgb4vf: Link management changes
1) Speed should be supported by Physical Port Capabilities. 2) report Forward Error Correction mode which are available. 3) Added few comments. Signed-off-by: Casey Leedom <leedom@chelsio.com> Signed-off-by: Vishal Kulkarni <vishal@chelsio.com> Signed-off-by: Arjun Vynipadath <arjun@chelsio.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
a9f8f40a8f
commit
95eb7882df
|
@ -446,8 +446,10 @@ static void fw_caps_to_lmm(enum fw_port_type port_type,
|
||||||
unsigned long *link_mode_mask)
|
unsigned long *link_mode_mask)
|
||||||
{
|
{
|
||||||
#define SET_LMM(__lmm_name) \
|
#define SET_LMM(__lmm_name) \
|
||||||
__set_bit(ETHTOOL_LINK_MODE_ ## __lmm_name ## _BIT, \
|
do { \
|
||||||
link_mode_mask)
|
__set_bit(ETHTOOL_LINK_MODE_ ## __lmm_name ## _BIT, \
|
||||||
|
link_mode_mask); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
#define FW_CAPS_TO_LMM(__fw_name, __lmm_name) \
|
#define FW_CAPS_TO_LMM(__fw_name, __lmm_name) \
|
||||||
do { \
|
do { \
|
||||||
|
@ -541,7 +543,7 @@ static void fw_caps_to_lmm(enum fw_port_type port_type,
|
||||||
case FW_PORT_TYPE_CR4_QSFP:
|
case FW_PORT_TYPE_CR4_QSFP:
|
||||||
SET_LMM(FIBRE);
|
SET_LMM(FIBRE);
|
||||||
FW_CAPS_TO_LMM(SPEED_1G, 1000baseT_Full);
|
FW_CAPS_TO_LMM(SPEED_1G, 1000baseT_Full);
|
||||||
FW_CAPS_TO_LMM(SPEED_10G, 10000baseSR_Full);
|
FW_CAPS_TO_LMM(SPEED_10G, 10000baseKR_Full);
|
||||||
FW_CAPS_TO_LMM(SPEED_40G, 40000baseSR4_Full);
|
FW_CAPS_TO_LMM(SPEED_40G, 40000baseSR4_Full);
|
||||||
FW_CAPS_TO_LMM(SPEED_25G, 25000baseCR_Full);
|
FW_CAPS_TO_LMM(SPEED_25G, 25000baseCR_Full);
|
||||||
FW_CAPS_TO_LMM(SPEED_50G, 50000baseCR2_Full);
|
FW_CAPS_TO_LMM(SPEED_50G, 50000baseCR2_Full);
|
||||||
|
@ -552,6 +554,13 @@ static void fw_caps_to_lmm(enum fw_port_type port_type,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (fw_caps & FW_PORT_CAP32_FEC_V(FW_PORT_CAP32_FEC_M)) {
|
||||||
|
FW_CAPS_TO_LMM(FEC_RS, FEC_RS);
|
||||||
|
FW_CAPS_TO_LMM(FEC_BASER_RS, FEC_BASER);
|
||||||
|
} else {
|
||||||
|
SET_LMM(FEC_NONE);
|
||||||
|
}
|
||||||
|
|
||||||
FW_CAPS_TO_LMM(ANEG, Autoneg);
|
FW_CAPS_TO_LMM(ANEG, Autoneg);
|
||||||
FW_CAPS_TO_LMM(802_3_PAUSE, Pause);
|
FW_CAPS_TO_LMM(802_3_PAUSE, Pause);
|
||||||
FW_CAPS_TO_LMM(802_3_ASM_DIR, Asym_Pause);
|
FW_CAPS_TO_LMM(802_3_ASM_DIR, Asym_Pause);
|
||||||
|
@ -679,18 +688,15 @@ static int set_link_ksettings(struct net_device *dev,
|
||||||
base->autoneg == AUTONEG_DISABLE) {
|
base->autoneg == AUTONEG_DISABLE) {
|
||||||
fw_caps = speed_to_fw_caps(base->speed);
|
fw_caps = speed_to_fw_caps(base->speed);
|
||||||
|
|
||||||
/* Must only specify a single speed which must be supported
|
/* Speed must be supported by Physical Port Capabilities. */
|
||||||
* as part of the Physical Port Capabilities.
|
if (!(lc->pcaps & fw_caps))
|
||||||
*/
|
|
||||||
if ((fw_caps & (fw_caps - 1)) != 0 ||
|
|
||||||
!(lc->pcaps & fw_caps))
|
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
lc->speed_caps = fw_caps;
|
lc->speed_caps = fw_caps;
|
||||||
lc->acaps = fw_caps;
|
lc->acaps = fw_caps;
|
||||||
} else {
|
} else {
|
||||||
fw_caps =
|
fw_caps =
|
||||||
lmm_to_fw_caps(link_ksettings->link_modes.advertising);
|
lmm_to_fw_caps(link_ksettings->link_modes.advertising);
|
||||||
if (!(lc->pcaps & fw_caps))
|
if (!(lc->pcaps & fw_caps))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
lc->speed_caps = 0;
|
lc->speed_caps = 0;
|
||||||
|
|
|
@ -4105,6 +4105,9 @@ static inline fw_port_cap32_t cc_to_fwcap_fec(enum cc_fec cc_fec)
|
||||||
* @mbox: the Firmware Mailbox to use
|
* @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.
|
* 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
|
* - If the PHY can auto-negotiate first decide what to advertise, then
|
||||||
|
@ -4124,6 +4127,7 @@ int t4_link_l1cfg_core(struct adapter *adapter, unsigned int mbox,
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
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);
|
||||||
|
|
||||||
/* Convert driver coding of Pause Frame Flow Control settings into the
|
/* Convert driver coding of Pause Frame Flow Control settings into the
|
||||||
* Firmware's API.
|
* Firmware's API.
|
||||||
*/
|
*/
|
||||||
|
@ -4143,8 +4147,13 @@ int t4_link_l1cfg_core(struct adapter *adapter, unsigned int mbox,
|
||||||
fw_fec = cc_to_fwcap_fec(cc_fec);
|
fw_fec = cc_to_fwcap_fec(cc_fec);
|
||||||
|
|
||||||
/* Figure out what our Requested Port Capabilities are going to be.
|
/* Figure out what our Requested Port Capabilities are going to be.
|
||||||
|
* Note parallel structure in t4_handle_get_port_info() and
|
||||||
|
* init_link_config().
|
||||||
*/
|
*/
|
||||||
if (!(lc->pcaps & FW_PORT_CAP32_ANEG)) {
|
if (!(lc->pcaps & FW_PORT_CAP32_ANEG)) {
|
||||||
|
if (lc->autoneg == AUTONEG_ENABLE)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
rcap = lc->acaps | fw_fc | fw_fec;
|
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;
|
||||||
|
@ -4156,7 +4165,11 @@ int t4_link_l1cfg_core(struct adapter *adapter, unsigned int mbox,
|
||||||
rcap = lc->acaps | fw_fc | fw_fec | fw_mdi;
|
rcap = lc->acaps | fw_fc | fw_fec | fw_mdi;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Note that older Firmware doesn't have FW_PORT_CAP32_FORCE_PAUSE, so
|
/* Some Requested Port Capabilities are trivially wrong if they exceed
|
||||||
|
* the Physical Port Capabilities. We can check that here and provide
|
||||||
|
* moderately useful feedback in the system log.
|
||||||
|
*
|
||||||
|
* Note that older Firmware doesn't have FW_PORT_CAP32_FORCE_PAUSE, so
|
||||||
* 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 ...
|
||||||
*/
|
*/
|
||||||
|
@ -4185,6 +4198,13 @@ int t4_link_l1cfg_core(struct adapter *adapter, unsigned int mbox,
|
||||||
|
|
||||||
ret = t4_wr_mbox_meat_timeout(adapter, mbox, &cmd, sizeof(cmd), NULL,
|
ret = t4_wr_mbox_meat_timeout(adapter, mbox, &cmd, sizeof(cmd), NULL,
|
||||||
sleep_ok, timeout);
|
sleep_ok, timeout);
|
||||||
|
|
||||||
|
/* Unfortunately, even if the Requested Port Capabilities "fit" within
|
||||||
|
* the Physical Port Capabilities, some combinations of features may
|
||||||
|
* still not be leagal. For example, 40Gb/s and Reed-Solomon Forward
|
||||||
|
* Error Correction. So if the Firmware rejects the L1 Configure
|
||||||
|
* request, flag that here.
|
||||||
|
*/
|
||||||
if (ret) {
|
if (ret) {
|
||||||
dev_err(adapter->pdev_dev,
|
dev_err(adapter->pdev_dev,
|
||||||
"Requested Port Capabilities %#x rejected, error %d\n",
|
"Requested Port Capabilities %#x rejected, error %d\n",
|
||||||
|
@ -8461,6 +8481,10 @@ void t4_handle_get_port_info(struct port_info *pi, const __be64 *rpl)
|
||||||
fc = fwcap_to_cc_pause(linkattr);
|
fc = fwcap_to_cc_pause(linkattr);
|
||||||
speed = fwcap_to_speed(linkattr);
|
speed = fwcap_to_speed(linkattr);
|
||||||
|
|
||||||
|
/* Reset state for communicating new Transceiver Module status and
|
||||||
|
* whether the OS-dependent layer wants us to redo the current
|
||||||
|
* "sticky" L1 Configure Link Parameters.
|
||||||
|
*/
|
||||||
lc->new_module = false;
|
lc->new_module = false;
|
||||||
lc->redo_l1cfg = false;
|
lc->redo_l1cfg = false;
|
||||||
|
|
||||||
|
@ -8497,9 +8521,15 @@ void t4_handle_get_port_info(struct port_info *pi, const __be64 *rpl)
|
||||||
*/
|
*/
|
||||||
pi->port_type = port_type;
|
pi->port_type = port_type;
|
||||||
|
|
||||||
|
/* Record new Module Type information.
|
||||||
|
*/
|
||||||
pi->mod_type = mod_type;
|
pi->mod_type = mod_type;
|
||||||
|
|
||||||
|
/* Let the OS-dependent layer know if we have a new
|
||||||
|
* Transceiver Module inserted.
|
||||||
|
*/
|
||||||
lc->new_module = t4_is_inserted_mod_type(mod_type);
|
lc->new_module = t4_is_inserted_mod_type(mod_type);
|
||||||
|
|
||||||
t4_os_portmod_changed(adapter, pi->port_id);
|
t4_os_portmod_changed(adapter, pi->port_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8507,8 +8537,10 @@ void t4_handle_get_port_info(struct port_info *pi, const __be64 *rpl)
|
||||||
fc != lc->fc || fec != lc->fec) { /* something changed */
|
fc != lc->fc || fec != lc->fec) { /* something changed */
|
||||||
if (!link_ok && lc->link_ok) {
|
if (!link_ok && lc->link_ok) {
|
||||||
lc->link_down_rc = linkdnrc;
|
lc->link_down_rc = linkdnrc;
|
||||||
dev_warn(adapter->pdev_dev, "Port %d link down, reason: %s\n",
|
dev_warn_ratelimited(adapter->pdev_dev,
|
||||||
pi->tx_chan, t4_link_down_rc_str(linkdnrc));
|
"Port %d link down, reason: %s\n",
|
||||||
|
pi->tx_chan,
|
||||||
|
t4_link_down_rc_str(linkdnrc));
|
||||||
}
|
}
|
||||||
lc->link_ok = link_ok;
|
lc->link_ok = link_ok;
|
||||||
lc->speed = speed;
|
lc->speed = speed;
|
||||||
|
@ -8518,6 +8550,11 @@ void t4_handle_get_port_info(struct port_info *pi, const __be64 *rpl)
|
||||||
lc->lpacaps = lpacaps;
|
lc->lpacaps = lpacaps;
|
||||||
lc->acaps = acaps & ADVERT_MASK;
|
lc->acaps = acaps & ADVERT_MASK;
|
||||||
|
|
||||||
|
/* If we're not physically capable of Auto-Negotiation, note
|
||||||
|
* this as Auto-Negotiation disabled. Otherwise, we track
|
||||||
|
* what Auto-Negotiation settings we have. Note parallel
|
||||||
|
* structure in t4_link_l1cfg_core() and init_link_config().
|
||||||
|
*/
|
||||||
if (!(lc->acaps & FW_PORT_CAP32_ANEG)) {
|
if (!(lc->acaps & FW_PORT_CAP32_ANEG)) {
|
||||||
lc->autoneg = AUTONEG_DISABLE;
|
lc->autoneg = AUTONEG_DISABLE;
|
||||||
} else if (lc->acaps & FW_PORT_CAP32_ANEG) {
|
} else if (lc->acaps & FW_PORT_CAP32_ANEG) {
|
||||||
|
@ -8535,6 +8572,10 @@ void t4_handle_get_port_info(struct port_info *pi, const __be64 *rpl)
|
||||||
t4_os_link_changed(adapter, pi->port_id, link_ok);
|
t4_os_link_changed(adapter, pi->port_id, link_ok);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* If we have a new Transceiver Module and the OS-dependent code has
|
||||||
|
* told us that it wants us to redo whatever "sticky" L1 Configuration
|
||||||
|
* Link Parameters are set, do that now.
|
||||||
|
*/
|
||||||
if (lc->new_module && lc->redo_l1cfg) {
|
if (lc->new_module && lc->redo_l1cfg) {
|
||||||
struct link_config old_lc;
|
struct link_config old_lc;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
|
@ -2005,8 +2005,10 @@ static void t4vf_handle_get_port_info(struct port_info *pi,
|
||||||
fc != lc->fc || fec != lc->fec) { /* something changed */
|
fc != lc->fc || fec != lc->fec) { /* something changed */
|
||||||
if (!link_ok && lc->link_ok) {
|
if (!link_ok && lc->link_ok) {
|
||||||
lc->link_down_rc = linkdnrc;
|
lc->link_down_rc = linkdnrc;
|
||||||
dev_warn(adapter->pdev_dev, "Port %d link down, reason: %s\n",
|
dev_warn_ratelimited(adapter->pdev_dev,
|
||||||
pi->port_id, t4vf_link_down_rc_str(linkdnrc));
|
"Port %d link down, reason: %s\n",
|
||||||
|
pi->port_id,
|
||||||
|
t4vf_link_down_rc_str(linkdnrc));
|
||||||
}
|
}
|
||||||
lc->link_ok = link_ok;
|
lc->link_ok = link_ok;
|
||||||
lc->speed = speed;
|
lc->speed = speed;
|
||||||
|
|
Loading…
Reference in New Issue