diff options
Diffstat (limited to 'drivers/net/ethernet/wangxun/txgbe')
| -rw-r--r-- | drivers/net/ethernet/wangxun/txgbe/txgbe_aml.c | 298 | ||||
| -rw-r--r-- | drivers/net/ethernet/wangxun/txgbe/txgbe_aml.h | 5 | ||||
| -rw-r--r-- | drivers/net/ethernet/wangxun/txgbe/txgbe_ethtool.c | 38 | ||||
| -rw-r--r-- | drivers/net/ethernet/wangxun/txgbe/txgbe_irq.c | 10 | ||||
| -rw-r--r-- | drivers/net/ethernet/wangxun/txgbe/txgbe_main.c | 28 | ||||
| -rw-r--r-- | drivers/net/ethernet/wangxun/txgbe/txgbe_phy.c | 2 | ||||
| -rw-r--r-- | drivers/net/ethernet/wangxun/txgbe/txgbe_type.h | 39 |
7 files changed, 306 insertions, 114 deletions
diff --git a/drivers/net/ethernet/wangxun/txgbe/txgbe_aml.c b/drivers/net/ethernet/wangxun/txgbe/txgbe_aml.c index dc87ccad9652..62d7f47d4f8d 100644 --- a/drivers/net/ethernet/wangxun/txgbe/txgbe_aml.c +++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_aml.c @@ -17,10 +17,15 @@ void txgbe_gpio_init_aml(struct wx *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_INTTYPE_LEVEL, TXGBE_GPIOBIT_2 | TXGBE_GPIOBIT_3); - wr32(wx, WX_GPIO_INTEN, TXGBE_GPIOBIT_2 | TXGBE_GPIOBIT_3); + 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,20 +38,20 @@ 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) { - set_bit(WX_FLAG_NEED_SFP_RESET, wx->flags); - wr32(wx, WX_GPIO_EOI, TXGBE_GPIOBIT_2); + if (status & mod_rst) { + set_bit(WX_FLAG_NEED_MODULE_RESET, wx->flags); + wr32(wx, WX_GPIO_EOI, mod_rst); wx_service_event_schedule(wx); } - if (status & TXGBE_GPIOBIT_3) { - set_bit(WX_FLAG_NEED_LINK_CONFIG, wx->flags); - wx_service_event_schedule(wx); - wr32(wx, WX_GPIO_EOI, TXGBE_GPIOBIT_3); - } wr32(wx, WX_GPIO_INTMASK, 0); return IRQ_HANDLED; @@ -56,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; @@ -68,15 +73,49 @@ int txgbe_test_hostif(struct wx *wx) WX_HI_COMMAND_TIMEOUT, true); } -static int txgbe_identify_sfp_hostif(struct wx *wx, struct txgbe_hic_i2c_read *buffer) +int txgbe_read_eeprom_hostif(struct wx *wx, + struct txgbe_hic_i2c_read *buffer, + u32 length, u8 *data) { - buffer->hdr.cmd = FW_READ_SFP_INFO_CMD; + u32 dword_len, offset, value, i; + int err; + + buffer->hdr.cmd = FW_READ_EEPROM_CMD; buffer->hdr.buf_len = sizeof(struct txgbe_hic_i2c_read) - sizeof(struct wx_hic_hdr); buffer->hdr.cmd_or_resp.cmd_resv = FW_CEM_CMD_RESERVED; + err = wx_host_interface_command(wx, (u32 *)buffer, + sizeof(struct txgbe_hic_i2c_read), + WX_HI_COMMAND_TIMEOUT, false); + if (err != 0) + return err; + + /* buffer length offset to read return data */ + offset = sizeof(struct txgbe_hic_i2c_read) >> 2; + dword_len = round_up(length, 4) >> 2; + + for (i = 0; i < dword_len; i++) { + value = rd32a(wx, WX_FW2SW_MBOX, i + offset); + le32_to_cpus(&value); + + memcpy(data, &value, 4); + data += 4; + } + + return 0; +} + +static int txgbe_identify_module_hostif(struct wx *wx, + struct txgbe_hic_get_module_info *buffer) +{ + buffer->hdr.cmd = FW_GET_MODULE_INFO_CMD; + buffer->hdr.buf_len = sizeof(struct txgbe_hic_get_module_info) - + sizeof(struct wx_hic_hdr); + buffer->hdr.cmd_or_resp.cmd_resv = FW_CEM_CMD_RESERVED; + return wx_host_interface_command(wx, (u32 *)buffer, - sizeof(struct txgbe_hic_i2c_read), + sizeof(struct txgbe_hic_get_module_info), WX_HI_COMMAND_TIMEOUT, true); } @@ -90,12 +129,18 @@ 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; case SPEED_10000: buffer.speed = TXGBE_LINK_SPEED_10GB_FULL; break; + default: + buffer.speed = TXGBE_LINK_SPEED_UNKNOWN; + break; } buffer.fec_mode = TXGBE_PHY_FEC_AUTO; @@ -106,28 +151,33 @@ static int txgbe_set_phy_link_hostif(struct wx *wx, int speed, int autoneg, int WX_HI_COMMAND_TIMEOUT, true); } -static void txgbe_get_link_capabilities(struct wx *wx) +static void txgbe_get_link_capabilities(struct wx *wx, int *speed, + int *autoneg, int *duplex) { struct txgbe *txgbe = wx->priv; - if (test_bit(PHY_INTERFACE_MODE_25GBASER, txgbe->sfp_interfaces)) - wx->adv_speed = SPEED_25000; - else if (test_bit(PHY_INTERFACE_MODE_10GBASER, txgbe->sfp_interfaces)) - wx->adv_speed = SPEED_10000; + 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; else - wx->adv_speed = SPEED_UNKNOWN; + *speed = SPEED_UNKNOWN; - wx->adv_duplex = wx->adv_speed == SPEED_UNKNOWN ? - DUPLEX_HALF : DUPLEX_FULL; + *autoneg = phylink_test(txgbe->advertising, Autoneg); + *duplex = *speed == SPEED_UNKNOWN ? DUPLEX_HALF : DUPLEX_FULL; } -static void txgbe_get_phy_link(struct wx *wx, int *speed) +static void txgbe_get_mac_link(struct wx *wx, int *speed) { u32 status; 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) @@ -138,23 +188,11 @@ static void txgbe_get_phy_link(struct wx *wx, int *speed) int txgbe_set_phy_link(struct wx *wx) { - int speed, err; - u32 gpio; + int speed, autoneg, duplex, err; - /* Check RX signal */ - gpio = rd32(wx, WX_GPIO_EXT); - if (gpio & TXGBE_GPIOBIT_3) - return -ENODEV; + txgbe_get_link_capabilities(wx, &speed, &autoneg, &duplex); - txgbe_get_link_capabilities(wx); - if (wx->adv_speed == SPEED_UNKNOWN) - return -ENODEV; - - txgbe_get_phy_link(wx, &speed); - if (speed == wx->adv_speed) - return 0; - - err = txgbe_set_phy_link_hostif(wx, wx->adv_speed, 0, wx->adv_duplex); + err = txgbe_set_phy_link_hostif(wx, speed, autoneg, duplex); if (err) { wx_err(wx, "Failed to setup link\n"); return err; @@ -163,40 +201,128 @@ int txgbe_set_phy_link(struct wx *wx) return 0; } -static int txgbe_sfp_to_linkmodes(struct wx *wx, struct txgbe_sfp_id *id) +static int txgbe_sfp_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->com_25g_code & (TXGBE_SFF_25GBASESR_CAPABLE | - TXGBE_SFF_25GBASEER_CAPABLE | - TXGBE_SFF_25GBASELR_CAPABLE)) { - phylink_set(modes, 25000baseSR_Full); + if (id->cable_tech & TXGBE_SFF_DA_PASSIVE_CABLE) { + txgbe->link_port = PORT_DA; + phylink_set(modes, Autoneg); + if (id->com_25g_code == TXGBE_SFF_25GBASECR_91FEC || + id->com_25g_code == TXGBE_SFF_25GBASECR_74FEC || + id->com_25g_code == TXGBE_SFF_25GBASECR_NOFEC) { + phylink_set(modes, 25000baseCR_Full); + phylink_set(modes, 10000baseCR_Full); + __set_bit(PHY_INTERFACE_MODE_25GBASER, interfaces); + __set_bit(PHY_INTERFACE_MODE_10GBASER, interfaces); + } else { + phylink_set(modes, 10000baseCR_Full); + __set_bit(PHY_INTERFACE_MODE_10GBASER, interfaces); + } + } else if (id->cable_tech & TXGBE_SFF_DA_ACTIVE_CABLE) { + txgbe->link_port = PORT_DA; + phylink_set(modes, Autoneg); + phylink_set(modes, 25000baseCR_Full); __set_bit(PHY_INTERFACE_MODE_25GBASER, interfaces); + } else { + if (id->com_25g_code == TXGBE_SFF_25GBASESR_CAPABLE || + id->com_25g_code == TXGBE_SFF_25GBASEER_CAPABLE || + id->com_25g_code == TXGBE_SFF_25GBASELR_CAPABLE) { + txgbe->link_port = PORT_FIBRE; + phylink_set(modes, 25000baseSR_Full); + __set_bit(PHY_INTERFACE_MODE_25GBASER, interfaces); + } + if (id->com_10g_code & TXGBE_SFF_10GBASESR_CAPABLE) { + txgbe->link_port = PORT_FIBRE; + phylink_set(modes, 10000baseSR_Full); + __set_bit(PHY_INTERFACE_MODE_10GBASER, interfaces); + } + if (id->com_10g_code & TXGBE_SFF_10GBASELR_CAPABLE) { + txgbe->link_port = PORT_FIBRE; + phylink_set(modes, 10000baseLR_Full); + __set_bit(PHY_INTERFACE_MODE_10GBASER, interfaces); + } } - if (id->com_10g_code & TXGBE_SFF_10GBASESR_CAPABLE) { - phylink_set(modes, 10000baseSR_Full); - __set_bit(PHY_INTERFACE_MODE_10GBASER, interfaces); + + if (phy_interface_empty(interfaces)) { + wx_err(wx, "unsupported SFP module\n"); + return -EINVAL; } - if (id->com_10g_code & TXGBE_SFF_10GBASELR_CAPABLE) { - phylink_set(modes, 10000baseLR_Full); + + 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; +} + +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 SFP module\n"); + wx_err(wx, "unsupported QSFP module\n"); return -EINVAL; } phylink_set(modes, Pause); phylink_set(modes, Asym_Pause); phylink_set(modes, FIBRE); - txgbe->link_port = PORT_FIBRE; - if (!linkmode_equal(txgbe->sfp_support, modes)) { - linkmode_copy(txgbe->sfp_support, modes); - phy_interface_and(txgbe->sfp_interfaces, + 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); @@ -207,47 +333,53 @@ static int txgbe_sfp_to_linkmodes(struct wx *wx, struct txgbe_sfp_id *id) return 0; } -int txgbe_identify_sfp(struct wx *wx) +int txgbe_identify_module(struct wx *wx) { - struct txgbe_hic_i2c_read buffer; - struct txgbe_sfp_id *id; + 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_sfp_hostif(wx, &buffer); + err = txgbe_identify_module_hostif(wx, &buffer); if (err) { - wx_err(wx, "Failed to identify SFP module\n"); + wx_err(wx, "Failed to identify module\n"); return err; } 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; } - err = txgbe_sfp_to_linkmodes(wx, id); - if (err) - return err; - - if (gpio & TXGBE_GPIOBIT_3) - set_bit(WX_FLAG_NEED_LINK_CONFIG, wx->flags); + if (id->transceiver_type == 0xFF) + return txgbe_sfp_to_linkmodes(wx, id); - return 0; + return txgbe_qsfp_to_linkmodes(wx, id); } void txgbe_setup_link(struct wx *wx) { struct txgbe *txgbe = wx->priv; - phy_interface_zero(txgbe->sfp_interfaces); - linkmode_zero(txgbe->sfp_support); + phy_interface_zero(txgbe->link_interfaces); + linkmode_zero(txgbe->link_support); - txgbe_identify_sfp(wx); + set_bit(WX_FLAG_NEED_MODULE_RESET, wx->flags); + wx_service_event_schedule(wx); } static void txgbe_get_link_state(struct phylink_config *config, @@ -256,7 +388,7 @@ static void txgbe_get_link_state(struct phylink_config *config, struct wx *wx = phylink_to_wx(config); int speed; - txgbe_get_phy_link(wx, &speed); + txgbe_get_mac_link(wx, &speed); state->link = speed != SPEED_UNKNOWN; state->speed = speed; state->duplex = state->link ? DUPLEX_FULL : DUPLEX_UNKNOWN; @@ -300,6 +432,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; @@ -364,7 +499,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); @@ -372,8 +518,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"); diff --git a/drivers/net/ethernet/wangxun/txgbe/txgbe_aml.h b/drivers/net/ethernet/wangxun/txgbe/txgbe_aml.h index 25d4971ca0d9..4f6df0ee860b 100644 --- a/drivers/net/ethernet/wangxun/txgbe/txgbe_aml.h +++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_aml.h @@ -7,8 +7,11 @@ void txgbe_gpio_init_aml(struct wx *wx); irqreturn_t txgbe_gpio_irq_handler_aml(int irq, void *data); int txgbe_test_hostif(struct wx *wx); +int txgbe_read_eeprom_hostif(struct wx *wx, + struct txgbe_hic_i2c_read *buffer, + u32 length, u8 *data); int txgbe_set_phy_link(struct wx *wx); -int txgbe_identify_sfp(struct wx *wx); +int txgbe_identify_module(struct wx *wx); void txgbe_setup_link(struct wx *wx); int txgbe_phylink_init_aml(struct txgbe *txgbe); diff --git a/drivers/net/ethernet/wangxun/txgbe/txgbe_ethtool.c b/drivers/net/ethernet/wangxun/txgbe/txgbe_ethtool.c index e285b088c7b2..f3cb00109529 100644 --- a/drivers/net/ethernet/wangxun/txgbe/txgbe_ethtool.c +++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_ethtool.c @@ -10,6 +10,7 @@ #include "../libwx/wx_lib.h" #include "txgbe_type.h" #include "txgbe_fdir.h" +#include "txgbe_aml.h" #include "txgbe_ethtool.h" int txgbe_get_link_ksettings(struct net_device *netdev, @@ -19,9 +20,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; @@ -30,8 +28,9 @@ int txgbe_get_link_ksettings(struct net_device *netdev, return 0; cmd->base.port = txgbe->link_port; - cmd->base.autoneg = AUTONEG_DISABLE; - linkmode_copy(cmd->link_modes.supported, txgbe->sfp_support); + cmd->base.autoneg = phylink_test(txgbe->advertising, Autoneg) ? + AUTONEG_ENABLE : AUTONEG_DISABLE; + linkmode_copy(cmd->link_modes.supported, txgbe->link_support); linkmode_copy(cmd->link_modes.advertising, txgbe->advertising); return 0; @@ -536,6 +535,34 @@ static int txgbe_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd) return ret; } +static int +txgbe_get_module_eeprom_by_page(struct net_device *netdev, + const struct ethtool_module_eeprom *page_data, + struct netlink_ext_ack *extack) +{ + struct wx *wx = netdev_priv(netdev); + struct txgbe_hic_i2c_read buffer; + int err; + + if (!test_bit(WX_FLAG_SWFW_RING, wx->flags)) + return -EOPNOTSUPP; + + buffer.length = cpu_to_be32(page_data->length); + buffer.offset = cpu_to_be32(page_data->offset); + buffer.page = page_data->page; + buffer.bank = page_data->bank; + buffer.i2c_address = page_data->i2c_address; + + err = txgbe_read_eeprom_hostif(wx, &buffer, page_data->length, + page_data->data); + if (err) { + wx_err(wx, "Failed to read module EEPROM\n"); + return err; + } + + return page_data->length; +} + static const struct ethtool_ops txgbe_ethtool_ops = { .supported_coalesce_params = ETHTOOL_COALESCE_USECS | ETHTOOL_COALESCE_TX_MAX_FRAMES_IRQ | @@ -570,6 +597,7 @@ static const struct ethtool_ops txgbe_ethtool_ops = { .set_msglevel = wx_set_msglevel, .get_ts_info = wx_get_ts_info, .get_ts_stats = wx_get_ptp_stats, + .get_module_eeprom_by_page = txgbe_get_module_eeprom_by_page, }; void txgbe_set_ethtool_ops(struct net_device *netdev) diff --git a/drivers/net/ethernet/wangxun/txgbe/txgbe_irq.c b/drivers/net/ethernet/wangxun/txgbe/txgbe_irq.c index 3885283681ec..aa14958d439a 100644 --- a/drivers/net/ethernet/wangxun/txgbe/txgbe_irq.c +++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_irq.c @@ -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); diff --git a/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c b/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c index c4c4d70d8466..0de051450a82 100644 --- a/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c +++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c @@ -89,21 +89,21 @@ static int txgbe_enumerate_functions(struct wx *wx) return physfns; } -static void txgbe_sfp_detection_subtask(struct wx *wx) +static void txgbe_module_detection_subtask(struct wx *wx) { int err; - if (!test_bit(WX_FLAG_NEED_SFP_RESET, wx->flags)) + if (!test_bit(WX_FLAG_NEED_MODULE_RESET, wx->flags)) return; - /* wait for SFP module ready */ + /* wait for SFF module ready */ msleep(200); - err = txgbe_identify_sfp(wx); + err = txgbe_identify_module(wx); if (err) return; - clear_bit(WX_FLAG_NEED_SFP_RESET, wx->flags); + clear_bit(WX_FLAG_NEED_MODULE_RESET, wx->flags); } static void txgbe_link_config_subtask(struct wx *wx) @@ -128,7 +128,7 @@ static void txgbe_service_task(struct work_struct *work) { struct wx *wx = container_of(work, struct wx, service_task); - txgbe_sfp_detection_subtask(wx); + txgbe_module_detection_subtask(wx); txgbe_link_config_subtask(wx); wx_service_event_complete(wx); @@ -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); @@ -398,6 +393,7 @@ static int txgbe_sw_init(struct wx *wx) wx->configure_fdir = txgbe_configure_fdir; set_bit(WX_FLAG_RSC_CAPABLE, wx->flags); + set_bit(WX_FLAG_RSC_ENABLED, wx->flags); set_bit(WX_FLAG_MULTI_64_FUNC, wx->flags); /* enable itr by default in dynamic mode */ @@ -423,6 +419,8 @@ static int txgbe_sw_init(struct wx *wx) break; case wx_mac_aml: case wx_mac_aml40: + set_bit(WX_FLAG_RX_MERGE_ENABLED, wx->flags); + set_bit(WX_FLAG_TXHEAD_WB_ENABLED, wx->flags); set_bit(WX_FLAG_SWFW_RING, wx->flags); wx->swfw_index = 0; break; @@ -801,6 +799,8 @@ static int txgbe_probe(struct pci_dev *pdev, netdev->features |= NETIF_F_HIGHDMA; netdev->hw_features |= NETIF_F_GRO; netdev->features |= NETIF_F_GRO; + netdev->hw_features |= NETIF_F_LRO; + netdev->features |= NETIF_F_LRO; netdev->features |= NETIF_F_RX_UDP_TUNNEL_PORT; netdev->priv_flags |= IFF_UNICAST_FLT; diff --git a/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.c b/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.c index 03f1b9bc604d..8ea7aa07ae4e 100644 --- a/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.c +++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.c @@ -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; diff --git a/drivers/net/ethernet/wangxun/txgbe/txgbe_type.h b/drivers/net/ethernet/wangxun/txgbe/txgbe_type.h index 41915d7dd372..82433e9cb0e3 100644 --- a/drivers/net/ethernet/wangxun/txgbe/txgbe_type.h +++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_type.h @@ -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 @@ -314,10 +315,15 @@ void txgbe_up(struct wx *wx); int txgbe_setup_tc(struct net_device *dev, u8 tc); 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 @@ -330,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) @@ -340,9 +352,10 @@ void txgbe_do_reset(struct net_device *netdev); #define FW_PHY_GET_LINK_CMD 0xC0 #define FW_PHY_SET_LINK_CMD 0xC1 -#define FW_READ_SFP_INFO_CMD 0xC5 +#define FW_GET_MODULE_INFO_CMD 0xC5 +#define FW_READ_EEPROM_CMD 0xC6 -struct txgbe_sfp_id { +struct txgbe_sff_id { u8 identifier; /* A0H 0x00 */ u8 com_1g_code; /* A0H 0x06 */ u8 com_10g_code; /* A0H 0x03 */ @@ -352,12 +365,14 @@ struct txgbe_sfp_id { u8 vendor_oui0; /* A0H 0x25 */ u8 vendor_oui1; /* A0H 0x26 */ u8 vendor_oui2; /* A0H 0x27 */ - u8 reserved[3]; + u8 transceiver_type; /* A0H 0x83 */ + u8 sff_opt1; /* A0H 0xC0 */ + u8 reserved[5]; }; -struct txgbe_hic_i2c_read { +struct txgbe_hic_get_module_info { struct wx_hic_hdr hdr; - struct txgbe_sfp_id id; + struct txgbe_sff_id id; }; struct txgbe_hic_ephy_setlink { @@ -380,6 +395,16 @@ struct txgbe_hic_ephy_getlink { u8 resv[6]; }; +struct txgbe_hic_i2c_read { + struct wx_hic_hdr hdr; + __be32 offset; + __be32 length; + u8 page; + u8 bank; + u8 i2c_address; + u8 resv; +}; + #define NODE_PROP(_NAME, _PROP) \ (const struct software_node) { \ .name = _NAME, \ @@ -448,8 +473,8 @@ struct txgbe { int fdir_filter_count; spinlock_t fdir_perfect_lock; /* spinlock for FDIR */ - DECLARE_PHY_INTERFACE_MASK(sfp_interfaces); - __ETHTOOL_DECLARE_LINK_MODE_MASK(sfp_support); + DECLARE_PHY_INTERFACE_MASK(link_interfaces); + __ETHTOOL_DECLARE_LINK_MODE_MASK(link_support); __ETHTOOL_DECLARE_LINK_MODE_MASK(advertising); u8 link_port; }; |