Loading drivers/net/ethernet/sfc/efx.c +21 −15 Original line number Diff line number Diff line Loading @@ -656,12 +656,16 @@ static void efx_stop_datapath(struct efx_nic *efx) struct efx_channel *channel; struct efx_tx_queue *tx_queue; struct efx_rx_queue *rx_queue; struct pci_dev *dev = efx->pci_dev; int rc; EFX_ASSERT_RESET_SERIALISED(efx); BUG_ON(efx->port_enabled); /* Only perform flush if dma is enabled */ if (dev->is_busmaster) { rc = efx_nic_flush_queues(efx); if (rc && EFX_WORKAROUND_7803(efx)) { /* Schedule a reset to recover from the flush failure. The * descriptor caches reference memory we're about to free, Loading @@ -676,6 +680,7 @@ static void efx_stop_datapath(struct efx_nic *efx) netif_dbg(efx, drv, efx->net_dev, "successfully flushed all queues\n"); } } efx_for_each_channel(channel, efx) { /* RX packet processing is pipelined, so wait for the Loading Loading @@ -2492,8 +2497,8 @@ static void efx_pci_remove(struct pci_dev *pci_dev) efx_fini_io(efx); netif_dbg(efx, drv, efx->net_dev, "shutdown successful\n"); pci_set_drvdata(pci_dev, NULL); efx_fini_struct(efx); pci_set_drvdata(pci_dev, NULL); free_netdev(efx->net_dev); }; Loading Loading @@ -2695,6 +2700,7 @@ static int __devinit efx_pci_probe(struct pci_dev *pci_dev, fail2: efx_fini_struct(efx); fail1: pci_set_drvdata(pci_dev, NULL); WARN_ON(rc > 0); netif_dbg(efx, drv, efx->net_dev, "initialisation failed. rc=%d\n", rc); free_netdev(net_dev); Loading drivers/net/ethernet/sfc/ethtool.c +35 −0 Original line number Diff line number Diff line Loading @@ -1108,6 +1108,39 @@ static int efx_ethtool_set_rxfh_indir(struct net_device *net_dev, return 0; } static int efx_ethtool_get_module_eeprom(struct net_device *net_dev, struct ethtool_eeprom *ee, u8 *data) { struct efx_nic *efx = netdev_priv(net_dev); int ret; if (!efx->phy_op || !efx->phy_op->get_module_eeprom) return -EOPNOTSUPP; mutex_lock(&efx->mac_lock); ret = efx->phy_op->get_module_eeprom(efx, ee, data); mutex_unlock(&efx->mac_lock); return ret; } static int efx_ethtool_get_module_info(struct net_device *net_dev, struct ethtool_modinfo *modinfo) { struct efx_nic *efx = netdev_priv(net_dev); int ret; if (!efx->phy_op || !efx->phy_op->get_module_info) return -EOPNOTSUPP; mutex_lock(&efx->mac_lock); ret = efx->phy_op->get_module_info(efx, modinfo); mutex_unlock(&efx->mac_lock); return ret; } const struct ethtool_ops efx_ethtool_ops = { .get_settings = efx_ethtool_get_settings, .set_settings = efx_ethtool_set_settings, Loading Loading @@ -1137,4 +1170,6 @@ const struct ethtool_ops efx_ethtool_ops = { .get_rxfh_indir_size = efx_ethtool_get_rxfh_indir_size, .get_rxfh_indir = efx_ethtool_get_rxfh_indir, .set_rxfh_indir = efx_ethtool_set_rxfh_indir, .get_module_info = efx_ethtool_get_module_info, .get_module_eeprom = efx_ethtool_get_module_eeprom, }; drivers/net/ethernet/sfc/mcdi_phy.c +76 −0 Original line number Diff line number Diff line Loading @@ -739,6 +739,80 @@ static const char *efx_mcdi_phy_test_name(struct efx_nic *efx, return NULL; } #define SFP_PAGE_SIZE 128 #define SFP_NUM_PAGES 2 static int efx_mcdi_phy_get_module_eeprom(struct efx_nic *efx, struct ethtool_eeprom *ee, u8 *data) { u8 outbuf[MC_CMD_GET_PHY_MEDIA_INFO_OUT_LENMAX]; u8 inbuf[MC_CMD_GET_PHY_MEDIA_INFO_IN_LEN]; size_t outlen; int rc; unsigned int payload_len; unsigned int space_remaining = ee->len; unsigned int page; unsigned int page_off; unsigned int to_copy; u8 *user_data = data; BUILD_BUG_ON(SFP_PAGE_SIZE * SFP_NUM_PAGES != ETH_MODULE_SFF_8079_LEN); page_off = ee->offset % SFP_PAGE_SIZE; page = ee->offset / SFP_PAGE_SIZE; while (space_remaining && (page < SFP_NUM_PAGES)) { MCDI_SET_DWORD(inbuf, GET_PHY_MEDIA_INFO_IN_PAGE, page); rc = efx_mcdi_rpc(efx, MC_CMD_GET_PHY_MEDIA_INFO, inbuf, sizeof(inbuf), outbuf, sizeof(outbuf), &outlen); if (rc) return rc; if (outlen < (MC_CMD_GET_PHY_MEDIA_INFO_OUT_DATA_OFST + SFP_PAGE_SIZE)) return -EIO; payload_len = MCDI_DWORD(outbuf, GET_PHY_MEDIA_INFO_OUT_DATALEN); if (payload_len != SFP_PAGE_SIZE) return -EIO; /* Copy as much as we can into data */ payload_len -= page_off; to_copy = (space_remaining < payload_len) ? space_remaining : payload_len; memcpy(user_data, outbuf + page_off + MC_CMD_GET_PHY_MEDIA_INFO_OUT_DATA_OFST, to_copy); space_remaining -= to_copy; user_data += to_copy; page_off = 0; page++; } return 0; } static int efx_mcdi_phy_get_module_info(struct efx_nic *efx, struct ethtool_modinfo *modinfo) { struct efx_mcdi_phy_data *phy_cfg = efx->phy_data; switch (phy_cfg->media) { case MC_CMD_MEDIA_SFP_PLUS: modinfo->type = ETH_MODULE_SFF_8079; modinfo->eeprom_len = ETH_MODULE_SFF_8079_LEN; return 0; default: return -EOPNOTSUPP; } } const struct efx_phy_operations efx_mcdi_phy_ops = { .probe = efx_mcdi_phy_probe, .init = efx_port_dummy_op_int, Loading @@ -751,4 +825,6 @@ const struct efx_phy_operations efx_mcdi_phy_ops = { .test_alive = efx_mcdi_phy_test_alive, .run_tests = efx_mcdi_phy_run_tests, .test_name = efx_mcdi_phy_test_name, .get_module_eeprom = efx_mcdi_phy_get_module_eeprom, .get_module_info = efx_mcdi_phy_get_module_info, }; drivers/net/ethernet/sfc/net_driver.h +5 −3 Original line number Diff line number Diff line Loading @@ -252,8 +252,6 @@ struct efx_rx_page_state { * @max_fill: RX descriptor maximum fill level (<= ring size) * @fast_fill_trigger: RX descriptor fill level that will trigger a fast fill * (<= @max_fill) * @fast_fill_limit: The level to which a fast fill will fill * (@fast_fill_trigger <= @fast_fill_limit <= @max_fill) * @min_fill: RX descriptor minimum non-zero fill level. * This records the minimum fill level observed when a ring * refill was triggered. Loading @@ -274,7 +272,6 @@ struct efx_rx_queue { int removed_count; unsigned int max_fill; unsigned int fast_fill_trigger; unsigned int fast_fill_limit; unsigned int min_fill; unsigned int min_overfill; unsigned int alloc_page_count; Loading Loading @@ -522,6 +519,11 @@ struct efx_phy_operations { int (*test_alive) (struct efx_nic *efx); const char *(*test_name) (struct efx_nic *efx, unsigned int index); int (*run_tests) (struct efx_nic *efx, int *results, unsigned flags); int (*get_module_eeprom) (struct efx_nic *efx, struct ethtool_eeprom *ee, u8 *data); int (*get_module_info) (struct efx_nic *efx, struct ethtool_modinfo *modinfo); }; /** Loading drivers/net/ethernet/sfc/qt202x_phy.c +33 −0 Original line number Diff line number Diff line Loading @@ -449,6 +449,37 @@ static void qt202x_phy_remove(struct efx_nic *efx) efx->phy_data = NULL; } static int qt202x_phy_get_module_info(struct efx_nic *efx, struct ethtool_modinfo *modinfo) { modinfo->type = ETH_MODULE_SFF_8079; modinfo->eeprom_len = ETH_MODULE_SFF_8079_LEN; return 0; } static int qt202x_phy_get_module_eeprom(struct efx_nic *efx, struct ethtool_eeprom *ee, u8 *data) { int mmd, reg_base, rc, i; if (efx->phy_type == PHY_TYPE_QT2025C) { mmd = MDIO_MMD_PCS; reg_base = 0xd000; } else { mmd = MDIO_MMD_PMAPMD; reg_base = 0x8007; } for (i = 0; i < ee->len; i++) { rc = efx_mdio_read(efx, mmd, reg_base + ee->offset + i); if (rc < 0) return rc; data[i] = rc; } return 0; } const struct efx_phy_operations falcon_qt202x_phy_ops = { .probe = qt202x_phy_probe, .init = qt202x_phy_init, Loading @@ -459,4 +490,6 @@ const struct efx_phy_operations falcon_qt202x_phy_ops = { .get_settings = qt202x_phy_get_settings, .set_settings = efx_mdio_set_settings, .test_alive = efx_mdio_test_alive, .get_module_eeprom = qt202x_phy_get_module_eeprom, .get_module_info = qt202x_phy_get_module_info, }; Loading
drivers/net/ethernet/sfc/efx.c +21 −15 Original line number Diff line number Diff line Loading @@ -656,12 +656,16 @@ static void efx_stop_datapath(struct efx_nic *efx) struct efx_channel *channel; struct efx_tx_queue *tx_queue; struct efx_rx_queue *rx_queue; struct pci_dev *dev = efx->pci_dev; int rc; EFX_ASSERT_RESET_SERIALISED(efx); BUG_ON(efx->port_enabled); /* Only perform flush if dma is enabled */ if (dev->is_busmaster) { rc = efx_nic_flush_queues(efx); if (rc && EFX_WORKAROUND_7803(efx)) { /* Schedule a reset to recover from the flush failure. The * descriptor caches reference memory we're about to free, Loading @@ -676,6 +680,7 @@ static void efx_stop_datapath(struct efx_nic *efx) netif_dbg(efx, drv, efx->net_dev, "successfully flushed all queues\n"); } } efx_for_each_channel(channel, efx) { /* RX packet processing is pipelined, so wait for the Loading Loading @@ -2492,8 +2497,8 @@ static void efx_pci_remove(struct pci_dev *pci_dev) efx_fini_io(efx); netif_dbg(efx, drv, efx->net_dev, "shutdown successful\n"); pci_set_drvdata(pci_dev, NULL); efx_fini_struct(efx); pci_set_drvdata(pci_dev, NULL); free_netdev(efx->net_dev); }; Loading Loading @@ -2695,6 +2700,7 @@ static int __devinit efx_pci_probe(struct pci_dev *pci_dev, fail2: efx_fini_struct(efx); fail1: pci_set_drvdata(pci_dev, NULL); WARN_ON(rc > 0); netif_dbg(efx, drv, efx->net_dev, "initialisation failed. rc=%d\n", rc); free_netdev(net_dev); Loading
drivers/net/ethernet/sfc/ethtool.c +35 −0 Original line number Diff line number Diff line Loading @@ -1108,6 +1108,39 @@ static int efx_ethtool_set_rxfh_indir(struct net_device *net_dev, return 0; } static int efx_ethtool_get_module_eeprom(struct net_device *net_dev, struct ethtool_eeprom *ee, u8 *data) { struct efx_nic *efx = netdev_priv(net_dev); int ret; if (!efx->phy_op || !efx->phy_op->get_module_eeprom) return -EOPNOTSUPP; mutex_lock(&efx->mac_lock); ret = efx->phy_op->get_module_eeprom(efx, ee, data); mutex_unlock(&efx->mac_lock); return ret; } static int efx_ethtool_get_module_info(struct net_device *net_dev, struct ethtool_modinfo *modinfo) { struct efx_nic *efx = netdev_priv(net_dev); int ret; if (!efx->phy_op || !efx->phy_op->get_module_info) return -EOPNOTSUPP; mutex_lock(&efx->mac_lock); ret = efx->phy_op->get_module_info(efx, modinfo); mutex_unlock(&efx->mac_lock); return ret; } const struct ethtool_ops efx_ethtool_ops = { .get_settings = efx_ethtool_get_settings, .set_settings = efx_ethtool_set_settings, Loading Loading @@ -1137,4 +1170,6 @@ const struct ethtool_ops efx_ethtool_ops = { .get_rxfh_indir_size = efx_ethtool_get_rxfh_indir_size, .get_rxfh_indir = efx_ethtool_get_rxfh_indir, .set_rxfh_indir = efx_ethtool_set_rxfh_indir, .get_module_info = efx_ethtool_get_module_info, .get_module_eeprom = efx_ethtool_get_module_eeprom, };
drivers/net/ethernet/sfc/mcdi_phy.c +76 −0 Original line number Diff line number Diff line Loading @@ -739,6 +739,80 @@ static const char *efx_mcdi_phy_test_name(struct efx_nic *efx, return NULL; } #define SFP_PAGE_SIZE 128 #define SFP_NUM_PAGES 2 static int efx_mcdi_phy_get_module_eeprom(struct efx_nic *efx, struct ethtool_eeprom *ee, u8 *data) { u8 outbuf[MC_CMD_GET_PHY_MEDIA_INFO_OUT_LENMAX]; u8 inbuf[MC_CMD_GET_PHY_MEDIA_INFO_IN_LEN]; size_t outlen; int rc; unsigned int payload_len; unsigned int space_remaining = ee->len; unsigned int page; unsigned int page_off; unsigned int to_copy; u8 *user_data = data; BUILD_BUG_ON(SFP_PAGE_SIZE * SFP_NUM_PAGES != ETH_MODULE_SFF_8079_LEN); page_off = ee->offset % SFP_PAGE_SIZE; page = ee->offset / SFP_PAGE_SIZE; while (space_remaining && (page < SFP_NUM_PAGES)) { MCDI_SET_DWORD(inbuf, GET_PHY_MEDIA_INFO_IN_PAGE, page); rc = efx_mcdi_rpc(efx, MC_CMD_GET_PHY_MEDIA_INFO, inbuf, sizeof(inbuf), outbuf, sizeof(outbuf), &outlen); if (rc) return rc; if (outlen < (MC_CMD_GET_PHY_MEDIA_INFO_OUT_DATA_OFST + SFP_PAGE_SIZE)) return -EIO; payload_len = MCDI_DWORD(outbuf, GET_PHY_MEDIA_INFO_OUT_DATALEN); if (payload_len != SFP_PAGE_SIZE) return -EIO; /* Copy as much as we can into data */ payload_len -= page_off; to_copy = (space_remaining < payload_len) ? space_remaining : payload_len; memcpy(user_data, outbuf + page_off + MC_CMD_GET_PHY_MEDIA_INFO_OUT_DATA_OFST, to_copy); space_remaining -= to_copy; user_data += to_copy; page_off = 0; page++; } return 0; } static int efx_mcdi_phy_get_module_info(struct efx_nic *efx, struct ethtool_modinfo *modinfo) { struct efx_mcdi_phy_data *phy_cfg = efx->phy_data; switch (phy_cfg->media) { case MC_CMD_MEDIA_SFP_PLUS: modinfo->type = ETH_MODULE_SFF_8079; modinfo->eeprom_len = ETH_MODULE_SFF_8079_LEN; return 0; default: return -EOPNOTSUPP; } } const struct efx_phy_operations efx_mcdi_phy_ops = { .probe = efx_mcdi_phy_probe, .init = efx_port_dummy_op_int, Loading @@ -751,4 +825,6 @@ const struct efx_phy_operations efx_mcdi_phy_ops = { .test_alive = efx_mcdi_phy_test_alive, .run_tests = efx_mcdi_phy_run_tests, .test_name = efx_mcdi_phy_test_name, .get_module_eeprom = efx_mcdi_phy_get_module_eeprom, .get_module_info = efx_mcdi_phy_get_module_info, };
drivers/net/ethernet/sfc/net_driver.h +5 −3 Original line number Diff line number Diff line Loading @@ -252,8 +252,6 @@ struct efx_rx_page_state { * @max_fill: RX descriptor maximum fill level (<= ring size) * @fast_fill_trigger: RX descriptor fill level that will trigger a fast fill * (<= @max_fill) * @fast_fill_limit: The level to which a fast fill will fill * (@fast_fill_trigger <= @fast_fill_limit <= @max_fill) * @min_fill: RX descriptor minimum non-zero fill level. * This records the minimum fill level observed when a ring * refill was triggered. Loading @@ -274,7 +272,6 @@ struct efx_rx_queue { int removed_count; unsigned int max_fill; unsigned int fast_fill_trigger; unsigned int fast_fill_limit; unsigned int min_fill; unsigned int min_overfill; unsigned int alloc_page_count; Loading Loading @@ -522,6 +519,11 @@ struct efx_phy_operations { int (*test_alive) (struct efx_nic *efx); const char *(*test_name) (struct efx_nic *efx, unsigned int index); int (*run_tests) (struct efx_nic *efx, int *results, unsigned flags); int (*get_module_eeprom) (struct efx_nic *efx, struct ethtool_eeprom *ee, u8 *data); int (*get_module_info) (struct efx_nic *efx, struct ethtool_modinfo *modinfo); }; /** Loading
drivers/net/ethernet/sfc/qt202x_phy.c +33 −0 Original line number Diff line number Diff line Loading @@ -449,6 +449,37 @@ static void qt202x_phy_remove(struct efx_nic *efx) efx->phy_data = NULL; } static int qt202x_phy_get_module_info(struct efx_nic *efx, struct ethtool_modinfo *modinfo) { modinfo->type = ETH_MODULE_SFF_8079; modinfo->eeprom_len = ETH_MODULE_SFF_8079_LEN; return 0; } static int qt202x_phy_get_module_eeprom(struct efx_nic *efx, struct ethtool_eeprom *ee, u8 *data) { int mmd, reg_base, rc, i; if (efx->phy_type == PHY_TYPE_QT2025C) { mmd = MDIO_MMD_PCS; reg_base = 0xd000; } else { mmd = MDIO_MMD_PMAPMD; reg_base = 0x8007; } for (i = 0; i < ee->len; i++) { rc = efx_mdio_read(efx, mmd, reg_base + ee->offset + i); if (rc < 0) return rc; data[i] = rc; } return 0; } const struct efx_phy_operations falcon_qt202x_phy_ops = { .probe = qt202x_phy_probe, .init = qt202x_phy_init, Loading @@ -459,4 +490,6 @@ const struct efx_phy_operations falcon_qt202x_phy_ops = { .get_settings = qt202x_phy_get_settings, .set_settings = efx_mdio_set_settings, .test_alive = efx_mdio_test_alive, .get_module_eeprom = qt202x_phy_get_module_eeprom, .get_module_info = qt202x_phy_get_module_info, };