mirror of
https://github.com/torvalds/linux.git
synced 2026-05-27 08:33:17 +02:00
net: txgbe: improve functions of AML 40G devices
Support to identify QSFP modules for AML 40G devices. The definition of GPIO pins follows the design of the QSFP modules, and TXGBE_GPIOBIT_4 is used for module present. Meanwhile, implement phylink in XLGMII mode by default, and get the link state from MAC link. Signed-off-by: Jiawen Wu <jiawenwu@trustnetic.com> Link: https://patch.msgid.link/20251118080259.24676-4-jiawenwu@trustnetic.com Signed-off-by: Paolo Abeni <pabeni@redhat.com>
This commit is contained in:
parent
dbba6b7a47
commit
57d39faed4
|
|
@ -240,9 +240,6 @@ int wx_nway_reset(struct net_device *netdev)
|
|||
{
|
||||
struct wx *wx = netdev_priv(netdev);
|
||||
|
||||
if (wx->mac.type == wx_mac_aml40)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
return phylink_ethtool_nway_reset(wx->phylink);
|
||||
}
|
||||
EXPORT_SYMBOL(wx_nway_reset);
|
||||
|
|
@ -261,9 +258,6 @@ int wx_set_link_ksettings(struct net_device *netdev,
|
|||
{
|
||||
struct wx *wx = netdev_priv(netdev);
|
||||
|
||||
if (wx->mac.type == wx_mac_aml40)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
return phylink_ethtool_ksettings_set(wx->phylink, cmd);
|
||||
}
|
||||
EXPORT_SYMBOL(wx_set_link_ksettings);
|
||||
|
|
@ -273,9 +267,6 @@ void wx_get_pauseparam(struct net_device *netdev,
|
|||
{
|
||||
struct wx *wx = netdev_priv(netdev);
|
||||
|
||||
if (wx->mac.type == wx_mac_aml40)
|
||||
return;
|
||||
|
||||
phylink_ethtool_get_pauseparam(wx->phylink, pause);
|
||||
}
|
||||
EXPORT_SYMBOL(wx_get_pauseparam);
|
||||
|
|
@ -285,9 +276,6 @@ int wx_set_pauseparam(struct net_device *netdev,
|
|||
{
|
||||
struct wx *wx = netdev_priv(netdev);
|
||||
|
||||
if (wx->mac.type == wx_mac_aml40)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
return phylink_ethtool_set_pauseparam(wx->phylink, pause);
|
||||
}
|
||||
EXPORT_SYMBOL(wx_set_pauseparam);
|
||||
|
|
|
|||
|
|
@ -17,10 +17,15 @@
|
|||
|
||||
void txgbe_gpio_init_aml(struct wx *wx)
|
||||
{
|
||||
u32 status;
|
||||
u32 status, mod_rst;
|
||||
|
||||
wr32(wx, WX_GPIO_INTTYPE_LEVEL, TXGBE_GPIOBIT_2);
|
||||
wr32(wx, WX_GPIO_INTEN, TXGBE_GPIOBIT_2);
|
||||
if (wx->mac.type == wx_mac_aml40)
|
||||
mod_rst = TXGBE_GPIOBIT_4;
|
||||
else
|
||||
mod_rst = TXGBE_GPIOBIT_2;
|
||||
|
||||
wr32(wx, WX_GPIO_INTTYPE_LEVEL, mod_rst);
|
||||
wr32(wx, WX_GPIO_INTEN, mod_rst);
|
||||
|
||||
status = rd32(wx, WX_GPIO_INTSTATUS);
|
||||
for (int i = 0; i < 6; i++) {
|
||||
|
|
@ -33,13 +38,18 @@ irqreturn_t txgbe_gpio_irq_handler_aml(int irq, void *data)
|
|||
{
|
||||
struct txgbe *txgbe = data;
|
||||
struct wx *wx = txgbe->wx;
|
||||
u32 status;
|
||||
u32 status, mod_rst;
|
||||
|
||||
if (wx->mac.type == wx_mac_aml40)
|
||||
mod_rst = TXGBE_GPIOBIT_4;
|
||||
else
|
||||
mod_rst = TXGBE_GPIOBIT_2;
|
||||
|
||||
wr32(wx, WX_GPIO_INTMASK, 0xFF);
|
||||
status = rd32(wx, WX_GPIO_INTSTATUS);
|
||||
if (status & TXGBE_GPIOBIT_2) {
|
||||
if (status & mod_rst) {
|
||||
set_bit(WX_FLAG_NEED_MODULE_RESET, wx->flags);
|
||||
wr32(wx, WX_GPIO_EOI, TXGBE_GPIOBIT_2);
|
||||
wr32(wx, WX_GPIO_EOI, mod_rst);
|
||||
wx_service_event_schedule(wx);
|
||||
}
|
||||
|
||||
|
|
@ -51,7 +61,7 @@ int txgbe_test_hostif(struct wx *wx)
|
|||
{
|
||||
struct txgbe_hic_ephy_getlink buffer;
|
||||
|
||||
if (wx->mac.type != wx_mac_aml)
|
||||
if (wx->mac.type == wx_mac_sp)
|
||||
return 0;
|
||||
|
||||
buffer.hdr.cmd = FW_PHY_GET_LINK_CMD;
|
||||
|
|
@ -86,6 +96,9 @@ static int txgbe_set_phy_link_hostif(struct wx *wx, int speed, int autoneg, int
|
|||
buffer.hdr.cmd_or_resp.cmd_resv = FW_CEM_CMD_RESERVED;
|
||||
|
||||
switch (speed) {
|
||||
case SPEED_40000:
|
||||
buffer.speed = TXGBE_LINK_SPEED_40GB_FULL;
|
||||
break;
|
||||
case SPEED_25000:
|
||||
buffer.speed = TXGBE_LINK_SPEED_25GB_FULL;
|
||||
break;
|
||||
|
|
@ -110,7 +123,9 @@ static void txgbe_get_link_capabilities(struct wx *wx, int *speed,
|
|||
{
|
||||
struct txgbe *txgbe = wx->priv;
|
||||
|
||||
if (test_bit(PHY_INTERFACE_MODE_25GBASER, txgbe->link_interfaces))
|
||||
if (test_bit(PHY_INTERFACE_MODE_XLGMII, txgbe->link_interfaces))
|
||||
*speed = SPEED_40000;
|
||||
else if (test_bit(PHY_INTERFACE_MODE_25GBASER, txgbe->link_interfaces))
|
||||
*speed = SPEED_25000;
|
||||
else if (test_bit(PHY_INTERFACE_MODE_10GBASER, txgbe->link_interfaces))
|
||||
*speed = SPEED_10000;
|
||||
|
|
@ -128,6 +143,8 @@ static void txgbe_get_mac_link(struct wx *wx, int *speed)
|
|||
status = rd32(wx, TXGBE_CFG_PORT_ST);
|
||||
if (!(status & TXGBE_CFG_PORT_ST_LINK_UP))
|
||||
*speed = SPEED_UNKNOWN;
|
||||
else if (status & TXGBE_CFG_PORT_ST_LINK_AML_40G)
|
||||
*speed = SPEED_40000;
|
||||
else if (status & TXGBE_CFG_PORT_ST_LINK_AML_25G)
|
||||
*speed = SPEED_25000;
|
||||
else if (status & TXGBE_CFG_PORT_ST_LINK_AML_10G)
|
||||
|
|
@ -218,15 +235,86 @@ static int txgbe_sfp_to_linkmodes(struct wx *wx, struct txgbe_sff_id *id)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int txgbe_qsfp_to_linkmodes(struct wx *wx, struct txgbe_sff_id *id)
|
||||
{
|
||||
__ETHTOOL_DECLARE_LINK_MODE_MASK(modes) = { 0, };
|
||||
DECLARE_PHY_INTERFACE_MASK(interfaces);
|
||||
struct txgbe *txgbe = wx->priv;
|
||||
|
||||
if (id->transceiver_type & TXGBE_SFF_ETHERNET_40G_CR4) {
|
||||
txgbe->link_port = PORT_DA;
|
||||
phylink_set(modes, Autoneg);
|
||||
phylink_set(modes, 40000baseCR4_Full);
|
||||
phylink_set(modes, 10000baseCR_Full);
|
||||
__set_bit(PHY_INTERFACE_MODE_XLGMII, interfaces);
|
||||
__set_bit(PHY_INTERFACE_MODE_10GBASER, interfaces);
|
||||
}
|
||||
if (id->transceiver_type & TXGBE_SFF_ETHERNET_40G_SR4) {
|
||||
txgbe->link_port = PORT_FIBRE;
|
||||
phylink_set(modes, 40000baseSR4_Full);
|
||||
__set_bit(PHY_INTERFACE_MODE_XLGMII, interfaces);
|
||||
}
|
||||
if (id->transceiver_type & TXGBE_SFF_ETHERNET_40G_LR4) {
|
||||
txgbe->link_port = PORT_FIBRE;
|
||||
phylink_set(modes, 40000baseLR4_Full);
|
||||
__set_bit(PHY_INTERFACE_MODE_XLGMII, interfaces);
|
||||
}
|
||||
if (id->transceiver_type & TXGBE_SFF_ETHERNET_40G_ACTIVE) {
|
||||
txgbe->link_port = PORT_DA;
|
||||
phylink_set(modes, Autoneg);
|
||||
phylink_set(modes, 40000baseCR4_Full);
|
||||
__set_bit(PHY_INTERFACE_MODE_XLGMII, interfaces);
|
||||
}
|
||||
if (id->transceiver_type & TXGBE_SFF_ETHERNET_RSRVD) {
|
||||
if (id->sff_opt1 & TXGBE_SFF_ETHERNET_100G_CR4) {
|
||||
txgbe->link_port = PORT_DA;
|
||||
phylink_set(modes, Autoneg);
|
||||
phylink_set(modes, 40000baseCR4_Full);
|
||||
phylink_set(modes, 25000baseCR_Full);
|
||||
phylink_set(modes, 10000baseCR_Full);
|
||||
__set_bit(PHY_INTERFACE_MODE_XLGMII, interfaces);
|
||||
__set_bit(PHY_INTERFACE_MODE_25GBASER, interfaces);
|
||||
__set_bit(PHY_INTERFACE_MODE_10GBASER, interfaces);
|
||||
}
|
||||
}
|
||||
|
||||
if (phy_interface_empty(interfaces)) {
|
||||
wx_err(wx, "unsupported QSFP module\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
phylink_set(modes, Pause);
|
||||
phylink_set(modes, Asym_Pause);
|
||||
phylink_set(modes, FIBRE);
|
||||
|
||||
if (!linkmode_equal(txgbe->link_support, modes)) {
|
||||
linkmode_copy(txgbe->link_support, modes);
|
||||
phy_interface_and(txgbe->link_interfaces,
|
||||
wx->phylink_config.supported_interfaces,
|
||||
interfaces);
|
||||
linkmode_copy(txgbe->advertising, modes);
|
||||
|
||||
set_bit(WX_FLAG_NEED_LINK_CONFIG, wx->flags);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int txgbe_identify_module(struct wx *wx)
|
||||
{
|
||||
struct txgbe_hic_get_module_info buffer;
|
||||
struct txgbe_sff_id *id;
|
||||
int err = 0;
|
||||
u32 mod_abs;
|
||||
u32 gpio;
|
||||
|
||||
if (wx->mac.type == wx_mac_aml40)
|
||||
mod_abs = TXGBE_GPIOBIT_4;
|
||||
else
|
||||
mod_abs = TXGBE_GPIOBIT_2;
|
||||
|
||||
gpio = rd32(wx, WX_GPIO_EXT);
|
||||
if (gpio & TXGBE_GPIOBIT_2)
|
||||
if (gpio & mod_abs)
|
||||
return -ENODEV;
|
||||
|
||||
err = txgbe_identify_module_hostif(wx, &buffer);
|
||||
|
|
@ -236,12 +324,18 @@ int txgbe_identify_module(struct wx *wx)
|
|||
}
|
||||
|
||||
id = &buffer.id;
|
||||
if (id->identifier != TXGBE_SFF_IDENTIFIER_SFP) {
|
||||
wx_err(wx, "Invalid SFP module\n");
|
||||
if (id->identifier != TXGBE_SFF_IDENTIFIER_SFP &&
|
||||
id->identifier != TXGBE_SFF_IDENTIFIER_QSFP &&
|
||||
id->identifier != TXGBE_SFF_IDENTIFIER_QSFP_PLUS &&
|
||||
id->identifier != TXGBE_SFF_IDENTIFIER_QSFP28) {
|
||||
wx_err(wx, "Invalid module\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
return txgbe_sfp_to_linkmodes(wx, id);
|
||||
if (id->transceiver_type == 0xFF)
|
||||
return txgbe_sfp_to_linkmodes(wx, id);
|
||||
|
||||
return txgbe_qsfp_to_linkmodes(wx, id);
|
||||
}
|
||||
|
||||
void txgbe_setup_link(struct wx *wx)
|
||||
|
|
@ -304,6 +398,9 @@ static void txgbe_mac_link_up_aml(struct phylink_config *config,
|
|||
txcfg &= ~TXGBE_AML_MAC_TX_CFG_SPEED_MASK;
|
||||
|
||||
switch (speed) {
|
||||
case SPEED_40000:
|
||||
txcfg |= TXGBE_AML_MAC_TX_CFG_SPEED_40G;
|
||||
break;
|
||||
case SPEED_25000:
|
||||
txcfg |= TXGBE_AML_MAC_TX_CFG_SPEED_25G;
|
||||
break;
|
||||
|
|
@ -368,7 +465,18 @@ int txgbe_phylink_init_aml(struct txgbe *txgbe)
|
|||
MAC_SYM_PAUSE | MAC_ASYM_PAUSE;
|
||||
config->get_fixed_state = txgbe_get_link_state;
|
||||
|
||||
phy_mode = PHY_INTERFACE_MODE_25GBASER;
|
||||
if (wx->mac.type == wx_mac_aml40) {
|
||||
config->mac_capabilities |= MAC_40000FD;
|
||||
phy_mode = PHY_INTERFACE_MODE_XLGMII;
|
||||
__set_bit(PHY_INTERFACE_MODE_XLGMII, config->supported_interfaces);
|
||||
state.speed = SPEED_40000;
|
||||
state.duplex = DUPLEX_FULL;
|
||||
} else {
|
||||
phy_mode = PHY_INTERFACE_MODE_25GBASER;
|
||||
state.speed = SPEED_25000;
|
||||
state.duplex = DUPLEX_FULL;
|
||||
}
|
||||
|
||||
__set_bit(PHY_INTERFACE_MODE_25GBASER, config->supported_interfaces);
|
||||
__set_bit(PHY_INTERFACE_MODE_10GBASER, config->supported_interfaces);
|
||||
|
||||
|
|
@ -376,8 +484,6 @@ int txgbe_phylink_init_aml(struct txgbe *txgbe)
|
|||
if (IS_ERR(phylink))
|
||||
return PTR_ERR(phylink);
|
||||
|
||||
state.speed = SPEED_25000;
|
||||
state.duplex = DUPLEX_FULL;
|
||||
err = phylink_set_fixed_link(phylink, &state);
|
||||
if (err) {
|
||||
wx_err(wx, "Failed to set fixed link\n");
|
||||
|
|
|
|||
|
|
@ -19,9 +19,6 @@ int txgbe_get_link_ksettings(struct net_device *netdev,
|
|||
struct txgbe *txgbe = wx->priv;
|
||||
int err;
|
||||
|
||||
if (wx->mac.type == wx_mac_aml40)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
err = wx_get_link_ksettings(netdev, cmd);
|
||||
if (err)
|
||||
return err;
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ void txgbe_irq_enable(struct wx *wx, bool queues)
|
|||
{
|
||||
u32 misc_ien = TXGBE_PX_MISC_IEN_MASK;
|
||||
|
||||
if (wx->mac.type == wx_mac_aml) {
|
||||
if (wx->mac.type != wx_mac_sp) {
|
||||
misc_ien |= TXGBE_PX_MISC_GPIO;
|
||||
txgbe_gpio_init_aml(wx);
|
||||
}
|
||||
|
|
@ -201,10 +201,7 @@ static void txgbe_del_irq_domain(struct txgbe *txgbe)
|
|||
|
||||
void txgbe_free_misc_irq(struct txgbe *txgbe)
|
||||
{
|
||||
if (txgbe->wx->mac.type == wx_mac_aml40)
|
||||
return;
|
||||
|
||||
if (txgbe->wx->mac.type == wx_mac_aml)
|
||||
if (txgbe->wx->mac.type != wx_mac_sp)
|
||||
free_irq(txgbe->gpio_irq, txgbe);
|
||||
|
||||
free_irq(txgbe->link_irq, txgbe);
|
||||
|
|
@ -219,9 +216,6 @@ int txgbe_setup_misc_irq(struct txgbe *txgbe)
|
|||
struct wx *wx = txgbe->wx;
|
||||
int hwirq, err;
|
||||
|
||||
if (wx->mac.type == wx_mac_aml40)
|
||||
goto skip_sp_irq;
|
||||
|
||||
txgbe->misc.nirqs = TXGBE_IRQ_MAX;
|
||||
txgbe->misc.domain = irq_domain_create_simple(NULL, txgbe->misc.nirqs, 0,
|
||||
&txgbe_misc_irq_domain_ops, txgbe);
|
||||
|
|
|
|||
|
|
@ -144,7 +144,6 @@ static void txgbe_init_service(struct wx *wx)
|
|||
static void txgbe_up_complete(struct wx *wx)
|
||||
{
|
||||
struct net_device *netdev = wx->netdev;
|
||||
u32 reg;
|
||||
|
||||
wx_control_hw(wx, true);
|
||||
wx_configure_vectors(wx);
|
||||
|
|
@ -155,12 +154,8 @@ static void txgbe_up_complete(struct wx *wx)
|
|||
|
||||
switch (wx->mac.type) {
|
||||
case wx_mac_aml40:
|
||||
reg = rd32(wx, TXGBE_AML_MAC_TX_CFG);
|
||||
reg &= ~TXGBE_AML_MAC_TX_CFG_SPEED_MASK;
|
||||
reg |= TXGBE_AML_MAC_TX_CFG_SPEED_40G;
|
||||
wr32(wx, WX_MAC_TX_CFG, reg);
|
||||
txgbe_enable_sec_tx_path(wx);
|
||||
netif_carrier_on(wx->netdev);
|
||||
txgbe_setup_link(wx);
|
||||
phylink_start(wx->phylink);
|
||||
break;
|
||||
case wx_mac_aml:
|
||||
/* Enable TX laser */
|
||||
|
|
@ -276,7 +271,7 @@ void txgbe_down(struct wx *wx)
|
|||
|
||||
switch (wx->mac.type) {
|
||||
case wx_mac_aml40:
|
||||
netif_carrier_off(wx->netdev);
|
||||
phylink_stop(wx->phylink);
|
||||
break;
|
||||
case wx_mac_aml:
|
||||
phylink_stop(wx->phylink);
|
||||
|
|
|
|||
|
|
@ -579,7 +579,6 @@ int txgbe_init_phy(struct txgbe *txgbe)
|
|||
|
||||
switch (wx->mac.type) {
|
||||
case wx_mac_aml40:
|
||||
return 0;
|
||||
case wx_mac_aml:
|
||||
return txgbe_phylink_init_aml(txgbe);
|
||||
case wx_mac_sp:
|
||||
|
|
@ -653,7 +652,6 @@ void txgbe_remove_phy(struct txgbe *txgbe)
|
|||
{
|
||||
switch (txgbe->wx->mac.type) {
|
||||
case wx_mac_aml40:
|
||||
return;
|
||||
case wx_mac_aml:
|
||||
phylink_destroy(txgbe->wx->phylink);
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -98,6 +98,7 @@
|
|||
/* Port cfg registers */
|
||||
#define TXGBE_CFG_PORT_ST 0x14404
|
||||
#define TXGBE_CFG_PORT_ST_LINK_UP BIT(0)
|
||||
#define TXGBE_CFG_PORT_ST_LINK_AML_40G BIT(2)
|
||||
#define TXGBE_CFG_PORT_ST_LINK_AML_25G BIT(3)
|
||||
#define TXGBE_CFG_PORT_ST_LINK_AML_10G BIT(4)
|
||||
#define TXGBE_CFG_VXLAN 0x14410
|
||||
|
|
@ -317,8 +318,12 @@ void txgbe_do_reset(struct net_device *netdev);
|
|||
#define TXGBE_LINK_SPEED_UNKNOWN 0
|
||||
#define TXGBE_LINK_SPEED_10GB_FULL 4
|
||||
#define TXGBE_LINK_SPEED_25GB_FULL 0x10
|
||||
#define TXGBE_LINK_SPEED_40GB_FULL 0x20
|
||||
|
||||
#define TXGBE_SFF_IDENTIFIER_SFP 0x3
|
||||
#define TXGBE_SFF_IDENTIFIER_QSFP 0xC
|
||||
#define TXGBE_SFF_IDENTIFIER_QSFP_PLUS 0xD
|
||||
#define TXGBE_SFF_IDENTIFIER_QSFP28 0x11
|
||||
#define TXGBE_SFF_DA_PASSIVE_CABLE 0x4
|
||||
#define TXGBE_SFF_DA_ACTIVE_CABLE 0x8
|
||||
#define TXGBE_SFF_DA_SPEC_ACTIVE_LIMIT 0x4
|
||||
|
|
@ -331,6 +336,12 @@ void txgbe_do_reset(struct net_device *netdev);
|
|||
#define TXGBE_SFF_25GBASECR_91FEC 0xB
|
||||
#define TXGBE_SFF_25GBASECR_74FEC 0xC
|
||||
#define TXGBE_SFF_25GBASECR_NOFEC 0xD
|
||||
#define TXGBE_SFF_ETHERNET_RSRVD BIT(7)
|
||||
#define TXGBE_SFF_ETHERNET_40G_CR4 BIT(3)
|
||||
#define TXGBE_SFF_ETHERNET_40G_SR4 BIT(2)
|
||||
#define TXGBE_SFF_ETHERNET_40G_LR4 BIT(1)
|
||||
#define TXGBE_SFF_ETHERNET_40G_ACTIVE BIT(0)
|
||||
#define TXGBE_SFF_ETHERNET_100G_CR4 0xB
|
||||
|
||||
#define TXGBE_PHY_FEC_RS BIT(0)
|
||||
#define TXGBE_PHY_FEC_BASER BIT(1)
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user