mirror of
https://github.com/torvalds/linux.git
synced 2026-05-31 18:43:33 +02:00
fbnic: Retire "AUTO" flags and cleanup handling of FW link settings
There were several issues in the way we were handling the link info coming from firmware. First is the fact that we were carrying around "AUTO" flags to indicate that we needed to populate the values. We can just drop this and assume that we will always be populating the settings from firmware. With this we can also clean up the masking as the "AUTO" flags were just there to be stripped anyway. Second since we are getting rid of the "AUTO" setting we still need a way to report that the link is not configured. We convert the link_mode "AUTO" to "UNKNOWN" to do this. With this we can avoid reporting link up in the phylink_pcs_get_state call as we will just set link to 0 and return without updating the link speed. This is preferred versus the driver just forcing 50G which makes it harder to recover when the FW does start providing valid settings. With this the plan is to eventually replace the link_mode we use with the interface_mode from phylink for all intents and purposes and have the two be interchangeable. At that point we can convert the FW provided settings over to something closer to link partner settings and give phylink greater control of the interface allowing for user override of the settings and an asynchronous setup of the link versus having to pull early settings from firmware. Signed-off-by: Alexander Duyck <alexanderduyck@fb.com> Link: https://patch.msgid.link/175028445548.625704.1367708155813490215.stgit@ahduyck-xeon-server.home.arpa Signed-off-by: Paolo Abeni <pabeni@redhat.com>
This commit is contained in:
parent
3b180b227e
commit
a6bbbc5bc4
|
|
@ -452,7 +452,7 @@ static u32 __fbnic_mac_cmd_config_asic(struct fbnic_dev *fbd,
|
|||
command_config |= FBNIC_MAC_COMMAND_CONFIG_RX_PAUSE_DIS;
|
||||
|
||||
/* Disable fault handling if no FEC is requested */
|
||||
if ((fbn->fec & FBNIC_FEC_MODE_MASK) == FBNIC_FEC_OFF)
|
||||
if (fbn->fec == FBNIC_FEC_OFF)
|
||||
command_config |= FBNIC_MAC_COMMAND_CONFIG_FLT_HDL_DIS;
|
||||
|
||||
return command_config;
|
||||
|
|
@ -468,7 +468,7 @@ static bool fbnic_mac_get_pcs_link_status(struct fbnic_dev *fbd)
|
|||
return false;
|
||||
|
||||
/* Define the expected lane mask for the status bits we need to check */
|
||||
switch (fbn->link_mode & FBNIC_LINK_MODE_MASK) {
|
||||
switch (fbn->link_mode) {
|
||||
case FBNIC_LINK_100R2:
|
||||
lane_mask = 0xf;
|
||||
break;
|
||||
|
|
@ -476,7 +476,7 @@ static bool fbnic_mac_get_pcs_link_status(struct fbnic_dev *fbd)
|
|||
lane_mask = 3;
|
||||
break;
|
||||
case FBNIC_LINK_50R2:
|
||||
switch (fbn->fec & FBNIC_FEC_MODE_MASK) {
|
||||
switch (fbn->fec) {
|
||||
case FBNIC_FEC_OFF:
|
||||
lane_mask = 0x63;
|
||||
break;
|
||||
|
|
@ -494,7 +494,7 @@ static bool fbnic_mac_get_pcs_link_status(struct fbnic_dev *fbd)
|
|||
}
|
||||
|
||||
/* Use an XOR to remove the bits we expect to see set */
|
||||
switch (fbn->fec & FBNIC_FEC_MODE_MASK) {
|
||||
switch (fbn->fec) {
|
||||
case FBNIC_FEC_OFF:
|
||||
lane_mask ^= FIELD_GET(FBNIC_SIG_PCS_OUT0_BLOCK_LOCK,
|
||||
pcs_status);
|
||||
|
|
@ -540,64 +540,55 @@ static bool fbnic_pcs_get_link_asic(struct fbnic_dev *fbd)
|
|||
return link;
|
||||
}
|
||||
|
||||
static void fbnic_pcs_get_fw_settings(struct fbnic_dev *fbd)
|
||||
static void
|
||||
fbnic_mac_get_fw_settings(struct fbnic_dev *fbd, u8 *link_mode, u8 *fec)
|
||||
{
|
||||
struct fbnic_net *fbn = netdev_priv(fbd->netdev);
|
||||
u8 link_mode = fbn->link_mode;
|
||||
u8 fec = fbn->fec;
|
||||
|
||||
/* Update FEC first to reflect FW current mode */
|
||||
if (fbn->fec & FBNIC_FEC_AUTO) {
|
||||
switch (fbd->fw_cap.link_fec) {
|
||||
case FBNIC_FW_LINK_FEC_NONE:
|
||||
fec = FBNIC_FEC_OFF;
|
||||
break;
|
||||
case FBNIC_FW_LINK_FEC_RS:
|
||||
fec = FBNIC_FEC_RS;
|
||||
break;
|
||||
case FBNIC_FW_LINK_FEC_BASER:
|
||||
fec = FBNIC_FEC_BASER;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
fbn->fec = fec;
|
||||
/* Retrieve default speed from FW */
|
||||
switch (fbd->fw_cap.link_speed) {
|
||||
case FBNIC_FW_LINK_SPEED_25R1:
|
||||
*link_mode = FBNIC_LINK_25R1;
|
||||
break;
|
||||
case FBNIC_FW_LINK_SPEED_50R2:
|
||||
*link_mode = FBNIC_LINK_50R2;
|
||||
break;
|
||||
case FBNIC_FW_LINK_SPEED_50R1:
|
||||
*link_mode = FBNIC_LINK_50R1;
|
||||
*fec = FBNIC_FEC_RS;
|
||||
return;
|
||||
case FBNIC_FW_LINK_SPEED_100R2:
|
||||
*link_mode = FBNIC_LINK_100R2;
|
||||
*fec = FBNIC_FEC_RS;
|
||||
return;
|
||||
default:
|
||||
*link_mode = FBNIC_LINK_UNKONWN;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Do nothing if AUTO mode is not engaged */
|
||||
if (fbn->link_mode & FBNIC_LINK_AUTO) {
|
||||
switch (fbd->fw_cap.link_speed) {
|
||||
case FBNIC_FW_LINK_SPEED_25R1:
|
||||
link_mode = FBNIC_LINK_25R1;
|
||||
break;
|
||||
case FBNIC_FW_LINK_SPEED_50R2:
|
||||
link_mode = FBNIC_LINK_50R2;
|
||||
break;
|
||||
case FBNIC_FW_LINK_SPEED_50R1:
|
||||
link_mode = FBNIC_LINK_50R1;
|
||||
fec = FBNIC_FEC_RS;
|
||||
break;
|
||||
case FBNIC_FW_LINK_SPEED_100R2:
|
||||
link_mode = FBNIC_LINK_100R2;
|
||||
fec = FBNIC_FEC_RS;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
fbn->link_mode = link_mode;
|
||||
/* Update FEC first to reflect FW current mode */
|
||||
switch (fbd->fw_cap.link_fec) {
|
||||
case FBNIC_FW_LINK_FEC_NONE:
|
||||
*fec = FBNIC_FEC_OFF;
|
||||
break;
|
||||
case FBNIC_FW_LINK_FEC_RS:
|
||||
default:
|
||||
*fec = FBNIC_FEC_RS;
|
||||
break;
|
||||
case FBNIC_FW_LINK_FEC_BASER:
|
||||
*fec = FBNIC_FEC_BASER;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static int fbnic_pcs_enable_asic(struct fbnic_dev *fbd)
|
||||
{
|
||||
struct fbnic_net *fbn = netdev_priv(fbd->netdev);
|
||||
|
||||
/* Mask and clear the PCS interrupt, will be enabled by link handler */
|
||||
wr32(fbd, FBNIC_SIG_PCS_INTR_MASK, ~0);
|
||||
wr32(fbd, FBNIC_SIG_PCS_INTR_STS, ~0);
|
||||
|
||||
/* Pull in settings from FW */
|
||||
fbnic_pcs_get_fw_settings(fbd);
|
||||
fbnic_mac_get_fw_settings(fbd, &fbn->link_mode, &fbn->fec);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,11 +25,8 @@ enum {
|
|||
FBNIC_FEC_OFF = 0,
|
||||
FBNIC_FEC_RS = 1,
|
||||
FBNIC_FEC_BASER = 2,
|
||||
FBNIC_FEC_AUTO = 4,
|
||||
};
|
||||
|
||||
#define FBNIC_FEC_MODE_MASK (FBNIC_FEC_AUTO - 1)
|
||||
|
||||
/* Treat the link modes as a set of modulation/lanes bitmask:
|
||||
* Bit 0: Lane Count, 0 = R1, 1 = R2
|
||||
* Bit 1: Modulation, 0 = NRZ, 1 = PAM4
|
||||
|
|
@ -40,12 +37,11 @@ enum {
|
|||
FBNIC_LINK_50R2 = 1,
|
||||
FBNIC_LINK_50R1 = 2,
|
||||
FBNIC_LINK_100R2 = 3,
|
||||
FBNIC_LINK_AUTO = 4,
|
||||
FBNIC_LINK_UNKONWN = 4,
|
||||
};
|
||||
|
||||
#define FBNIC_LINK_MODE_R2 (FBNIC_LINK_50R2)
|
||||
#define FBNIC_LINK_MODE_PAM4 (FBNIC_LINK_50R1)
|
||||
#define FBNIC_LINK_MODE_MASK (FBNIC_LINK_AUTO - 1)
|
||||
|
||||
enum fbnic_sensor_id {
|
||||
FBNIC_SENSOR_TEMP, /* Temp in millidegrees Centigrade */
|
||||
|
|
|
|||
|
|
@ -736,8 +736,6 @@ struct net_device *fbnic_netdev_alloc(struct fbnic_dev *fbd)
|
|||
*/
|
||||
netdev->ethtool->wol_enabled = true;
|
||||
|
||||
fbn->fec = FBNIC_FEC_AUTO | FBNIC_FEC_RS;
|
||||
fbn->link_mode = FBNIC_LINK_AUTO | FBNIC_LINK_50R2;
|
||||
netif_carrier_off(netdev);
|
||||
|
||||
netif_tx_stop_all_queues(netdev);
|
||||
|
|
|
|||
|
|
@ -21,23 +21,20 @@ fbnic_phylink_pcs_get_state(struct phylink_pcs *pcs, unsigned int neg_mode,
|
|||
struct fbnic_net *fbn = fbnic_pcs_to_net(pcs);
|
||||
struct fbnic_dev *fbd = fbn->fbd;
|
||||
|
||||
/* For now we use hard-coded defaults and FW config to determine
|
||||
* the current values. In future patches we will add support for
|
||||
* reconfiguring these values and changing link settings.
|
||||
*/
|
||||
switch (fbd->fw_cap.link_speed) {
|
||||
case FBNIC_FW_LINK_SPEED_25R1:
|
||||
switch (fbn->link_mode) {
|
||||
case FBNIC_LINK_25R1:
|
||||
state->speed = SPEED_25000;
|
||||
break;
|
||||
case FBNIC_FW_LINK_SPEED_50R2:
|
||||
case FBNIC_LINK_50R2:
|
||||
case FBNIC_LINK_50R1:
|
||||
state->speed = SPEED_50000;
|
||||
break;
|
||||
case FBNIC_FW_LINK_SPEED_100R2:
|
||||
case FBNIC_LINK_100R2:
|
||||
state->speed = SPEED_100000;
|
||||
break;
|
||||
default:
|
||||
state->speed = SPEED_UNKNOWN;
|
||||
break;
|
||||
state->link = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
state->duplex = DUPLEX_FULL;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user