Skip to content

Commit

Permalink
amd-xgbe: Only use the SFP supported transceiver signals
Browse files Browse the repository at this point in the history
The SFP eeprom indicates the transceiver signals (Rx LOS, Tx Fault, etc.)
that it supports.  Update the driver to include checking the eeprom data
when deciding whether to use a transceiver signal.

Signed-off-by: Tom Lendacky <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
  • Loading branch information
tlendacky authored and davem330 committed Apr 24, 2018
1 parent 96f4d43 commit 117df65
Showing 1 changed file with 54 additions and 17 deletions.
71 changes: 54 additions & 17 deletions drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,10 @@ enum xgbe_sfp_speed {
#define XGBE_SFP_BASE_VENDOR_SN 4
#define XGBE_SFP_BASE_VENDOR_SN_LEN 16

#define XGBE_SFP_EXTD_OPT1 1
#define XGBE_SFP_EXTD_OPT1_RX_LOS BIT(1)
#define XGBE_SFP_EXTD_OPT1_TX_FAULT BIT(3)

#define XGBE_SFP_EXTD_DIAG 28
#define XGBE_SFP_EXTD_DIAG_ADDR_CHANGE BIT(2)

Expand Down Expand Up @@ -332,6 +336,7 @@ struct xgbe_phy_data {

unsigned int sfp_gpio_address;
unsigned int sfp_gpio_mask;
unsigned int sfp_gpio_inputs;
unsigned int sfp_gpio_rx_los;
unsigned int sfp_gpio_tx_fault;
unsigned int sfp_gpio_mod_absent;
Expand Down Expand Up @@ -986,6 +991,49 @@ static void xgbe_phy_sfp_external_phy(struct xgbe_prv_data *pdata)
phy_data->sfp_phy_avail = 1;
}

static bool xgbe_phy_check_sfp_rx_los(struct xgbe_phy_data *phy_data)
{
u8 *sfp_extd = phy_data->sfp_eeprom.extd;

if (!(sfp_extd[XGBE_SFP_EXTD_OPT1] & XGBE_SFP_EXTD_OPT1_RX_LOS))
return false;

if (phy_data->sfp_gpio_mask & XGBE_GPIO_NO_RX_LOS)
return false;

if (phy_data->sfp_gpio_inputs & (1 << phy_data->sfp_gpio_rx_los))
return true;

return false;
}

static bool xgbe_phy_check_sfp_tx_fault(struct xgbe_phy_data *phy_data)
{
u8 *sfp_extd = phy_data->sfp_eeprom.extd;

if (!(sfp_extd[XGBE_SFP_EXTD_OPT1] & XGBE_SFP_EXTD_OPT1_TX_FAULT))
return false;

if (phy_data->sfp_gpio_mask & XGBE_GPIO_NO_TX_FAULT)
return false;

if (phy_data->sfp_gpio_inputs & (1 << phy_data->sfp_gpio_tx_fault))
return true;

return false;
}

static bool xgbe_phy_check_sfp_mod_absent(struct xgbe_phy_data *phy_data)
{
if (phy_data->sfp_gpio_mask & XGBE_GPIO_NO_MOD_ABSENT)
return false;

if (phy_data->sfp_gpio_inputs & (1 << phy_data->sfp_gpio_mod_absent))
return true;

return false;
}

static bool xgbe_phy_belfuse_parse_quirks(struct xgbe_prv_data *pdata)
{
struct xgbe_phy_data *phy_data = pdata->phy_data;
Expand Down Expand Up @@ -1031,6 +1079,10 @@ static void xgbe_phy_sfp_parse_eeprom(struct xgbe_prv_data *pdata)
if (sfp_base[XGBE_SFP_BASE_EXT_ID] != XGBE_SFP_EXT_ID_SFP)
return;

/* Update transceiver signals (eeprom extd/options) */
phy_data->sfp_tx_fault = xgbe_phy_check_sfp_tx_fault(phy_data);
phy_data->sfp_rx_los = xgbe_phy_check_sfp_rx_los(phy_data);

if (xgbe_phy_sfp_parse_quirks(pdata))
return;

Expand Down Expand Up @@ -1196,7 +1248,6 @@ static int xgbe_phy_sfp_read_eeprom(struct xgbe_prv_data *pdata)
static void xgbe_phy_sfp_signals(struct xgbe_prv_data *pdata)
{
struct xgbe_phy_data *phy_data = pdata->phy_data;
unsigned int gpio_input;
u8 gpio_reg, gpio_ports[2];
int ret;

Expand All @@ -1211,23 +1262,9 @@ static void xgbe_phy_sfp_signals(struct xgbe_prv_data *pdata)
return;
}

gpio_input = (gpio_ports[1] << 8) | gpio_ports[0];

if (phy_data->sfp_gpio_mask & XGBE_GPIO_NO_MOD_ABSENT) {
/* No GPIO, just assume the module is present for now */
phy_data->sfp_mod_absent = 0;
} else {
if (!(gpio_input & (1 << phy_data->sfp_gpio_mod_absent)))
phy_data->sfp_mod_absent = 0;
}

if (!(phy_data->sfp_gpio_mask & XGBE_GPIO_NO_RX_LOS) &&
(gpio_input & (1 << phy_data->sfp_gpio_rx_los)))
phy_data->sfp_rx_los = 1;
phy_data->sfp_gpio_inputs = (gpio_ports[1] << 8) | gpio_ports[0];

if (!(phy_data->sfp_gpio_mask & XGBE_GPIO_NO_TX_FAULT) &&
(gpio_input & (1 << phy_data->sfp_gpio_tx_fault)))
phy_data->sfp_tx_fault = 1;
phy_data->sfp_mod_absent = xgbe_phy_check_sfp_mod_absent(phy_data);
}

static void xgbe_phy_sfp_mod_absent(struct xgbe_prv_data *pdata)
Expand Down

0 comments on commit 117df65

Please sign in to comment.