X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=drivers%2Fnet%2Fe1000%2Figb_ethdev.c;h=03047afa7417a05b75d0d6b918ffc2585fcf193f;hb=538da7a1cad25fbdffe298c8ca76fc4dbd262d1b;hp=da03d9bb348ea6a1c2eac5ac1282b7190f78617b;hpb=d6af1a13d7a14d062d11b37f6e31caa0f3823fe0;p=dpdk.git diff --git a/drivers/net/e1000/igb_ethdev.c b/drivers/net/e1000/igb_ethdev.c index da03d9bb34..03047afa74 100644 --- a/drivers/net/e1000/igb_ethdev.c +++ b/drivers/net/e1000/igb_ethdev.c @@ -1,34 +1,5 @@ -/*- - * BSD LICENSE - * - * Copyright(c) 2010-2016 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2010-2016 Intel Corporation */ #include @@ -37,19 +8,19 @@ #include #include +#include #include #include #include #include #include #include +#include #include -#include +#include #include #include -#include #include -#include #include #include @@ -71,8 +42,6 @@ #define IGB_DEFAULT_TX_HTHRESH 1 #define IGB_DEFAULT_TX_WTHRESH ((hw->mac.type == e1000_82576) ? 1 : 16) -#define IGB_HKEY_MAX_INDEX 10 - /* Bit shift and mask */ #define IGB_4_BIT_WIDTH (CHAR_BIT / 2) #define IGB_4_BIT_MASK RTE_LEN2MASK(IGB_4_BIT_WIDTH, uint8_t) @@ -100,19 +69,23 @@ #define E1000_VET_VET_EXT 0xFFFF0000 #define E1000_VET_VET_EXT_SHIFT 16 +/* MSI-X other interrupt vector */ +#define IGB_MSIX_OTHER_INTR_VEC 0 + static int eth_igb_configure(struct rte_eth_dev *dev); static int eth_igb_start(struct rte_eth_dev *dev); static void eth_igb_stop(struct rte_eth_dev *dev); static int eth_igb_dev_set_link_up(struct rte_eth_dev *dev); static int eth_igb_dev_set_link_down(struct rte_eth_dev *dev); static void eth_igb_close(struct rte_eth_dev *dev); +static int eth_igb_reset(struct rte_eth_dev *dev); static void eth_igb_promiscuous_enable(struct rte_eth_dev *dev); static void eth_igb_promiscuous_disable(struct rte_eth_dev *dev); static void eth_igb_allmulticast_enable(struct rte_eth_dev *dev); static void eth_igb_allmulticast_disable(struct rte_eth_dev *dev); static int eth_igb_link_update(struct rte_eth_dev *dev, int wait_to_complete); -static void eth_igb_stats_get(struct rte_eth_dev *dev, +static int eth_igb_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *rte_stats); static int eth_igb_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstat *xstats, unsigned n); @@ -138,7 +111,7 @@ static int eth_igb_flow_ctrl_get(struct rte_eth_dev *dev, struct rte_eth_fc_conf *fc_conf); static int eth_igb_flow_ctrl_set(struct rte_eth_dev *dev, struct rte_eth_fc_conf *fc_conf); -static int eth_igb_lsc_interrupt_setup(struct rte_eth_dev *dev); +static int eth_igb_lsc_interrupt_setup(struct rte_eth_dev *dev, uint8_t on); static int eth_igb_rxq_interrupt_setup(struct rte_eth_dev *dev); static int eth_igb_interrupt_get_status(struct rte_eth_dev *dev); static int eth_igb_interrupt_action(struct rte_eth_dev *dev, @@ -157,7 +130,7 @@ static int eth_igb_vlan_filter_set(struct rte_eth_dev *dev, static int eth_igb_vlan_tpid_set(struct rte_eth_dev *dev, enum rte_vlan_type vlan_type, uint16_t tpid_id); -static void eth_igb_vlan_offload_set(struct rte_eth_dev *dev, int mask); +static int eth_igb_vlan_offload_set(struct rte_eth_dev *dev, int mask); static void igb_vlan_hw_filter_enable(struct rte_eth_dev *dev); static void igb_vlan_hw_filter_disable(struct rte_eth_dev *dev); @@ -169,14 +142,14 @@ static void igb_vlan_hw_extend_disable(struct rte_eth_dev *dev); static int eth_igb_led_on(struct rte_eth_dev *dev); static int eth_igb_led_off(struct rte_eth_dev *dev); -static void igb_intr_disable(struct e1000_hw *hw); +static void igb_intr_disable(struct rte_eth_dev *dev); static int igb_get_rx_buffer_size(struct e1000_hw *hw); static int eth_igb_rar_set(struct rte_eth_dev *dev, - struct ether_addr *mac_addr, + struct rte_ether_addr *mac_addr, uint32_t index, uint32_t pool); static void eth_igb_rar_clear(struct rte_eth_dev *dev, uint32_t index); -static void eth_igb_default_mac_addr_set(struct rte_eth_dev *dev, - struct ether_addr *addr); +static int eth_igb_default_mac_addr_set(struct rte_eth_dev *dev, + struct rte_ether_addr *addr); static void igbvf_intr_disable(struct e1000_hw *hw); static int igbvf_dev_configure(struct rte_eth_dev *dev); @@ -188,7 +161,7 @@ static void igbvf_promiscuous_disable(struct rte_eth_dev *dev); static void igbvf_allmulticast_enable(struct rte_eth_dev *dev); static void igbvf_allmulticast_disable(struct rte_eth_dev *dev); static int eth_igbvf_link_update(struct e1000_hw *hw); -static void eth_igbvf_stats_get(struct rte_eth_dev *dev, +static int eth_igbvf_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *rte_stats); static int eth_igbvf_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstat *xstats, unsigned n); @@ -200,8 +173,8 @@ static int igbvf_vlan_filter_set(struct rte_eth_dev *dev, uint16_t vlan_id, int on); static int igbvf_set_vfta(struct e1000_hw *hw, uint16_t vid, bool on); static void igbvf_set_vfta_all(struct rte_eth_dev *dev, bool on); -static void igbvf_default_mac_addr_set(struct rte_eth_dev *dev, - struct ether_addr *addr); +static int igbvf_default_mac_addr_set(struct rte_eth_dev *dev, + struct rte_ether_addr *addr); static int igbvf_get_reg_length(struct rte_eth_dev *dev); static int igbvf_get_regs(struct rte_eth_dev *dev, struct rte_dev_reg_info *regs); @@ -253,8 +226,12 @@ static int eth_igb_get_eeprom(struct rte_eth_dev *dev, struct rte_dev_eeprom_info *eeprom); static int eth_igb_set_eeprom(struct rte_eth_dev *dev, struct rte_dev_eeprom_info *eeprom); +static int eth_igb_get_module_info(struct rte_eth_dev *dev, + struct rte_eth_dev_module_info *modinfo); +static int eth_igb_get_module_eeprom(struct rte_eth_dev *dev, + struct rte_dev_eeprom_info *info); static int eth_igb_set_mc_addr_list(struct rte_eth_dev *dev, - struct ether_addr *mc_addr_set, + struct rte_ether_addr *mc_addr_set, uint32_t nb_mc_addr); static int igb_timesync_enable(struct rte_eth_dev *dev); static int igb_timesync_disable(struct rte_eth_dev *dev); @@ -334,6 +311,8 @@ static const struct rte_pci_id pci_id_igb_map[] = { { RTE_PCI_DEVICE(E1000_INTEL_VENDOR_ID, E1000_DEV_ID_I210_FIBER) }, { RTE_PCI_DEVICE(E1000_INTEL_VENDOR_ID, E1000_DEV_ID_I210_SERDES) }, { RTE_PCI_DEVICE(E1000_INTEL_VENDOR_ID, E1000_DEV_ID_I210_SGMII) }, + { RTE_PCI_DEVICE(E1000_INTEL_VENDOR_ID, E1000_DEV_ID_I210_COPPER_FLASHLESS) }, + { RTE_PCI_DEVICE(E1000_INTEL_VENDOR_ID, E1000_DEV_ID_I210_SERDES_FLASHLESS) }, { RTE_PCI_DEVICE(E1000_INTEL_VENDOR_ID, E1000_DEV_ID_I211_COPPER) }, { RTE_PCI_DEVICE(E1000_INTEL_VENDOR_ID, E1000_DEV_ID_I354_BACKPLANE_1GBPS) }, { RTE_PCI_DEVICE(E1000_INTEL_VENDOR_ID, E1000_DEV_ID_I354_SGMII) }, @@ -377,6 +356,7 @@ static const struct eth_dev_ops eth_igb_ops = { .dev_set_link_up = eth_igb_dev_set_link_up, .dev_set_link_down = eth_igb_dev_set_link_down, .dev_close = eth_igb_close, + .dev_reset = eth_igb_reset, .promiscuous_enable = eth_igb_promiscuous_enable, .promiscuous_disable = eth_igb_promiscuous_disable, .allmulticast_enable = eth_igb_allmulticast_enable, @@ -430,6 +410,8 @@ static const struct eth_dev_ops eth_igb_ops = { .get_eeprom_length = eth_igb_get_eeprom_length, .get_eeprom = eth_igb_get_eeprom, .set_eeprom = eth_igb_set_eeprom, + .get_module_info = eth_igb_get_module_info, + .get_module_eeprom = eth_igb_get_module_eeprom, .timesync_adjust_time = igb_timesync_adjust_time, .timesync_read_time = igb_timesync_read_time, .timesync_write_time = igb_timesync_write_time, @@ -459,6 +441,9 @@ static const struct eth_dev_ops igbvf_eth_dev_ops = { .dev_supported_ptypes_get = eth_igb_supported_ptypes_get, .rx_queue_setup = eth_igb_rx_queue_setup, .rx_queue_release = eth_igb_rx_queue_release, + .rx_descriptor_done = eth_igb_rx_descriptor_done, + .rx_descriptor_status = eth_igb_rx_descriptor_status, + .tx_descriptor_status = eth_igb_tx_descriptor_status, .tx_queue_setup = eth_igb_tx_queue_setup, .tx_queue_release = eth_igb_tx_queue_release, .set_mc_addr_list = eth_igb_set_mc_addr_list, @@ -549,57 +534,6 @@ static const struct rte_igb_xstats_name_off rte_igbvf_stats_strings[] = { #define IGBVF_NB_XSTATS (sizeof(rte_igbvf_stats_strings) / \ sizeof(rte_igbvf_stats_strings[0])) -/** - * Atomically reads the link status information from global - * structure rte_eth_dev. - * - * @param dev - * - Pointer to the structure rte_eth_dev to read from. - * - Pointer to the buffer to be saved with the link status. - * - * @return - * - On success, zero. - * - On failure, negative value. - */ -static inline int -rte_igb_dev_atomic_read_link_status(struct rte_eth_dev *dev, - struct rte_eth_link *link) -{ - struct rte_eth_link *dst = link; - struct rte_eth_link *src = &(dev->data->dev_link); - - if (rte_atomic64_cmpset((uint64_t *)dst, *(uint64_t *)dst, - *(uint64_t *)src) == 0) - return -1; - - return 0; -} - -/** - * Atomically writes the link status information into global - * structure rte_eth_dev. - * - * @param dev - * - Pointer to the structure rte_eth_dev to read from. - * - Pointer to the buffer to be saved with the link status. - * - * @return - * - On success, zero. - * - On failure, negative value. - */ -static inline int -rte_igb_dev_atomic_write_link_status(struct rte_eth_dev *dev, - struct rte_eth_link *link) -{ - struct rte_eth_link *dst = &(dev->data->dev_link); - struct rte_eth_link *src = link; - - if (rte_atomic64_cmpset((uint64_t *)dst, *(uint64_t *)dst, - *(uint64_t *)src) == 0) - return -1; - - return 0; -} static inline void igb_intr_enable(struct rte_eth_dev *dev) @@ -608,14 +542,31 @@ igb_intr_enable(struct rte_eth_dev *dev) E1000_DEV_PRIVATE_TO_INTR(dev->data->dev_private); struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); + struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev); + struct rte_intr_handle *intr_handle = &pci_dev->intr_handle; + + if (rte_intr_allow_others(intr_handle) && + dev->data->dev_conf.intr_conf.lsc != 0) { + E1000_WRITE_REG(hw, E1000_EIMS, 1 << IGB_MSIX_OTHER_INTR_VEC); + } E1000_WRITE_REG(hw, E1000_IMS, intr->mask); E1000_WRITE_FLUSH(hw); } static void -igb_intr_disable(struct e1000_hw *hw) +igb_intr_disable(struct rte_eth_dev *dev) { + struct e1000_hw *hw = + E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); + struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev); + struct rte_intr_handle *intr_handle = &pci_dev->intr_handle; + + if (rte_intr_allow_others(intr_handle) && + dev->data->dev_conf.intr_conf.lsc != 0) { + E1000_WRITE_REG(hw, E1000_EIMC, 1 << IGB_MSIX_OTHER_INTR_VEC); + } + E1000_WRITE_REG(hw, E1000_IMC, ~0); E1000_WRITE_FLUSH(hw); } @@ -816,7 +767,6 @@ eth_igb_dev_init(struct rte_eth_dev *eth_dev) } rte_eth_copy_pci_info(eth_dev, pci_dev); - eth_dev->data->dev_flags |= RTE_ETH_DEV_DETACHABLE; hw->hw_addr= (void *)pci_dev->mem_resource[0].addr; @@ -890,7 +840,8 @@ eth_igb_dev_init(struct rte_eth_dev *eth_dev) } /* Copy the permanent MAC address */ - ether_addr_copy((struct ether_addr *)hw->mac.addr, ð_dev->data->mac_addrs[0]); + rte_ether_addr_copy((struct rte_ether_addr *)hw->mac.addr, + ð_dev->data->mac_addrs[0]); /* initialize the vfta */ memset(shadow_vfta, 0, sizeof(*shadow_vfta)); @@ -947,6 +898,7 @@ eth_igb_dev_init(struct rte_eth_dev *eth_dev) TAILQ_INIT(&igb_filter_ethertype_list); TAILQ_INIT(&igb_filter_syn_list); TAILQ_INIT(&igb_filter_flex_list); + TAILQ_INIT(&igb_filter_rss_list); TAILQ_INIT(&igb_flow_list); return 0; @@ -987,9 +939,6 @@ eth_igb_dev_uninit(struct rte_eth_dev *eth_dev) /* Reset any pending lock */ igb_reset_swfw_lock(hw); - rte_free(eth_dev->data->mac_addrs); - eth_dev->data->mac_addrs = NULL; - /* uninitialize PF if max_vfs not zero */ igb_pf_host_uninit(eth_dev); @@ -1006,6 +955,10 @@ eth_igb_dev_uninit(struct rte_eth_dev *eth_dev) memset(filter_info->ethertype_filters, 0, E1000_MAX_ETQF_FILTERS * sizeof(struct igb_ethertype_filter)); + /* clear the rss filter info */ + memset(&filter_info->rss_info, 0, + sizeof(struct igb_rte_flow_rss_conf)); + /* remove all ntuple filters of the device */ igb_ntuple_filter_uninit(eth_dev); @@ -1031,7 +984,8 @@ eth_igbvf_dev_init(struct rte_eth_dev *eth_dev) struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private); int diag; - struct ether_addr *perm_addr = (struct ether_addr *)hw->mac.perm_addr; + struct rte_ether_addr *perm_addr = + (struct rte_ether_addr *)hw->mac.perm_addr; PMD_INIT_FUNC_TRACE(); @@ -1051,7 +1005,6 @@ eth_igbvf_dev_init(struct rte_eth_dev *eth_dev) pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev); rte_eth_copy_pci_info(eth_dev, pci_dev); - eth_dev->data->dev_flags |= RTE_ETH_DEV_DETACHABLE; hw->device_id = pci_dev->id.device_id; hw->vendor_id = pci_dev->id.vendor_id; @@ -1086,8 +1039,8 @@ eth_igbvf_dev_init(struct rte_eth_dev *eth_dev) } /* Generate a random MAC address, if none was assigned by PF. */ - if (is_zero_ether_addr(perm_addr)) { - eth_random_addr(perm_addr->addr_bytes); + if (rte_is_zero_ether_addr(perm_addr)) { + rte_eth_random_addr(perm_addr->addr_bytes); PMD_INIT_LOG(INFO, "\tVF MAC address not assigned by Host PF"); PMD_INIT_LOG(INFO, "\tAssign randomly generated MAC address " "%02x:%02x:%02x:%02x:%02x:%02x", @@ -1106,7 +1059,7 @@ eth_igbvf_dev_init(struct rte_eth_dev *eth_dev) return diag; } /* Copy the permanent MAC address */ - ether_addr_copy((struct ether_addr *) hw->mac.perm_addr, + rte_ether_addr_copy((struct rte_ether_addr *)hw->mac.perm_addr, ð_dev->data->mac_addrs[0]); PMD_INIT_LOG(DEBUG, "port %d vendorID=0x%x deviceID=0x%x " @@ -1140,9 +1093,6 @@ eth_igbvf_dev_uninit(struct rte_eth_dev *eth_dev) eth_dev->rx_pkt_burst = NULL; eth_dev->tx_pkt_burst = NULL; - rte_free(eth_dev->data->mac_addrs); - eth_dev->data->mac_addrs = NULL; - /* disable uio intr before callback unregister */ rte_intr_disable(&pci_dev->intr_handle); rte_intr_callback_unregister(&pci_dev->intr_handle, @@ -1166,7 +1116,8 @@ static int eth_igb_pci_remove(struct rte_pci_device *pci_dev) static struct rte_pci_driver rte_igb_pmd = { .id_table = pci_id_igb_map, - .drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC, + .drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC | + RTE_PCI_DRV_IOVA_AS_VA, .probe = eth_igb_pci_probe, .remove = eth_igb_pci_remove, }; @@ -1189,7 +1140,7 @@ static int eth_igbvf_pci_remove(struct rte_pci_device *pci_dev) */ static struct rte_pci_driver rte_igbvf_pmd = { .id_table = pci_id_igbvf_map, - .drv_flags = RTE_PCI_DRV_NEED_MAPPING, + .drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_IOVA_AS_VA, .probe = eth_igbvf_pci_probe, .remove = eth_igbvf_pci_remove, }; @@ -1211,7 +1162,7 @@ igb_check_mq_mode(struct rte_eth_dev *dev) enum rte_eth_rx_mq_mode rx_mq_mode = dev->data->dev_conf.rxmode.mq_mode; enum rte_eth_tx_mq_mode tx_mq_mode = dev->data->dev_conf.txmode.mq_mode; uint16_t nb_rx_q = dev->data->nb_rx_queues; - uint16_t nb_tx_q = dev->data->nb_rx_queues; + uint16_t nb_tx_q = dev->data->nb_tx_queues; if ((rx_mq_mode & ETH_MQ_RX_DCB_FLAG) || tx_mq_mode == ETH_MQ_TX_DCB || @@ -1300,6 +1251,31 @@ eth_igb_configure(struct rte_eth_dev *dev) return 0; } +static void +eth_igb_rxtx_control(struct rte_eth_dev *dev, + bool enable) +{ + struct e1000_hw *hw = + E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); + uint32_t tctl, rctl; + + tctl = E1000_READ_REG(hw, E1000_TCTL); + rctl = E1000_READ_REG(hw, E1000_RCTL); + + if (enable) { + /* enable Tx/Rx */ + tctl |= E1000_TCTL_EN; + rctl |= E1000_RCTL_EN; + } else { + /* disable Tx/Rx */ + tctl &= ~E1000_TCTL_EN; + rctl &= ~E1000_RCTL_EN; + } + E1000_WRITE_REG(hw, E1000_TCTL, tctl); + E1000_WRITE_REG(hw, E1000_RCTL, rctl); + E1000_WRITE_FLUSH(hw); +} + static int eth_igb_start(struct rte_eth_dev *dev) { @@ -1400,7 +1376,12 @@ eth_igb_start(struct rte_eth_dev *dev) */ mask = ETH_VLAN_STRIP_MASK | ETH_VLAN_FILTER_MASK | \ ETH_VLAN_EXTEND_MASK; - eth_igb_vlan_offload_set(dev, mask); + ret = eth_igb_vlan_offload_set(dev, mask); + if (ret) { + PMD_INIT_LOG(ERR, "Unable to set vlan offload"); + igb_dev_clear_queues(dev); + return ret; + } if (dev->data->dev_conf.rxmode.mq_mode == ETH_MQ_RX_VMDQ_ONLY) { /* Enable VLAN filter since VMDq always use VLAN filter */ @@ -1472,7 +1453,9 @@ eth_igb_start(struct rte_eth_dev *dev) if (rte_intr_allow_others(intr_handle)) { /* check if lsc interrupt is enabled */ if (dev->data->dev_conf.intr_conf.lsc != 0) - eth_igb_lsc_interrupt_setup(dev); + eth_igb_lsc_interrupt_setup(dev, TRUE); + else + eth_igb_lsc_interrupt_setup(dev, FALSE); } else { rte_intr_callback_unregister(intr_handle, eth_igb_interrupt_handler, @@ -1496,6 +1479,9 @@ eth_igb_start(struct rte_eth_dev *dev) /* restore all types filter */ igb_filter_restore(dev); + eth_igb_rxtx_control(dev, true); + eth_igb_link_update(dev, 0); + PMD_INIT_LOG(DEBUG, "<<"); return 0; @@ -1521,7 +1507,9 @@ eth_igb_stop(struct rte_eth_dev *dev) struct rte_eth_link link; struct rte_intr_handle *intr_handle = &pci_dev->intr_handle; - igb_intr_disable(hw); + eth_igb_rxtx_control(dev, false); + + igb_intr_disable(dev); /* disable intr eventfd mapping */ rte_intr_disable(intr_handle); @@ -1545,7 +1533,7 @@ eth_igb_stop(struct rte_eth_dev *dev) /* clear the recorded link status */ memset(&link, 0, sizeof(link)); - rte_igb_dev_atomic_write_link_status(dev, &link); + rte_eth_linkstatus_set(dev, &link); if (!rte_intr_allow_others(intr_handle)) /* resume to the default handler */ @@ -1621,9 +1609,36 @@ eth_igb_close(struct rte_eth_dev *dev) } memset(&link, 0, sizeof(link)); - rte_igb_dev_atomic_write_link_status(dev, &link); + rte_eth_linkstatus_set(dev, &link); } +/* + * Reset PF device. + */ +static int +eth_igb_reset(struct rte_eth_dev *dev) +{ + int ret; + + /* When a DPDK PMD PF begin to reset PF port, it should notify all + * its VF to make them align with it. The detailed notification + * mechanism is PMD specific and is currently not implemented. + * To avoid unexpected behavior in VF, currently reset of PF with + * SR-IOV activation is not supported. It might be supported later. + */ + if (dev->data->sriov.active) + return -ENOTSUP; + + ret = eth_igb_dev_uninit(dev); + if (ret) + return ret; + + ret = eth_igb_dev_init(dev); + + return ret; +} + + static int igb_get_rx_buffer_size(struct e1000_hw *hw) { @@ -1826,7 +1841,7 @@ igb_read_stats_registers(struct e1000_hw *hw, struct e1000_hw_stats *stats) stats->tsctfc += E1000_READ_REG(hw, E1000_TSCTFC); } -static void +static int eth_igb_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *rte_stats) { struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); @@ -1836,7 +1851,7 @@ eth_igb_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *rte_stats) igb_read_stats_registers(hw, stats); if (rte_stats == NULL) - return; + return -EINVAL; /* Rx Errors */ rte_stats->imissed = stats->mpc; @@ -1851,6 +1866,7 @@ eth_igb_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *rte_stats) rte_stats->opackets = stats->gptc; rte_stats->ibytes = stats->gorc; rte_stats->obytes = stats->gotc; + return 0; } static void @@ -1891,8 +1907,8 @@ static int eth_igb_xstats_get_names(__rte_unused struct rte_eth_dev *dev, /* Note: limit checked in rte_eth_xstats_names() */ for (i = 0; i < IGB_NB_XSTATS; i++) { - snprintf(xstats_names[i].name, sizeof(xstats_names[i].name), - "%s", rte_igb_stats_strings[i].name); + strlcpy(xstats_names[i].name, rte_igb_stats_strings[i].name, + sizeof(xstats_names[i].name)); } return IGB_NB_XSTATS; @@ -1909,9 +1925,9 @@ static int eth_igb_xstats_get_names_by_id(struct rte_eth_dev *dev, return IGB_NB_XSTATS; for (i = 0; i < IGB_NB_XSTATS; i++) - snprintf(xstats_names[i].name, - sizeof(xstats_names[i].name), - "%s", rte_igb_stats_strings[i].name); + strlcpy(xstats_names[i].name, + rte_igb_stats_strings[i].name, + sizeof(xstats_names[i].name)); return IGB_NB_XSTATS; @@ -2058,9 +2074,9 @@ static int eth_igbvf_xstats_get_names(__rte_unused struct rte_eth_dev *dev, if (xstats_names != NULL) for (i = 0; i < IGBVF_NB_XSTATS; i++) { - snprintf(xstats_names[i].name, - sizeof(xstats_names[i].name), "%s", - rte_igbvf_stats_strings[i].name); + strlcpy(xstats_names[i].name, + rte_igbvf_stats_strings[i].name, + sizeof(xstats_names[i].name)); } return IGBVF_NB_XSTATS; } @@ -2091,7 +2107,7 @@ eth_igbvf_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstat *xstats, return IGBVF_NB_XSTATS; } -static void +static int eth_igbvf_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *rte_stats) { struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); @@ -2101,12 +2117,13 @@ eth_igbvf_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *rte_stats) igbvf_read_stats_registers(hw, hw_stats); if (rte_stats == NULL) - return; + return -EINVAL; rte_stats->ipackets = hw_stats->gprc; rte_stats->ibytes = hw_stats->gorc; rte_stats->opackets = hw_stats->gptc; rte_stats->obytes = hw_stats->gotc; + return 0; } static void @@ -2180,22 +2197,15 @@ eth_igb_infos_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info) { struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); - dev_info->pci_dev = RTE_ETH_DEV_TO_PCI(dev); dev_info->min_rx_bufsize = 256; /* See BSIZE field of RCTL register. */ dev_info->max_rx_pktlen = 0x3FFF; /* See RLPML register. */ dev_info->max_mac_addrs = hw->mac.rar_entry_count; - dev_info->rx_offload_capa = - DEV_RX_OFFLOAD_VLAN_STRIP | - DEV_RX_OFFLOAD_IPV4_CKSUM | - DEV_RX_OFFLOAD_UDP_CKSUM | - DEV_RX_OFFLOAD_TCP_CKSUM; - dev_info->tx_offload_capa = - DEV_TX_OFFLOAD_VLAN_INSERT | - DEV_TX_OFFLOAD_IPV4_CKSUM | - DEV_TX_OFFLOAD_UDP_CKSUM | - DEV_TX_OFFLOAD_TCP_CKSUM | - DEV_TX_OFFLOAD_SCTP_CKSUM | - DEV_TX_OFFLOAD_TCP_TSO; + dev_info->rx_queue_offload_capa = igb_get_rx_queue_offloads_capa(dev); + dev_info->rx_offload_capa = igb_get_rx_port_offloads_capa(dev) | + dev_info->rx_queue_offload_capa; + dev_info->tx_queue_offload_capa = igb_get_tx_queue_offloads_capa(dev); + dev_info->tx_offload_capa = igb_get_tx_port_offloads_capa(dev) | + dev_info->tx_queue_offload_capa; switch (hw->mac.type) { case e1000_82575: @@ -2258,6 +2268,7 @@ eth_igb_infos_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info) }, .rx_free_thresh = IGB_DEFAULT_RX_FREE_THRESH, .rx_drop_en = 0, + .offloads = 0, }; dev_info->default_txconf = (struct rte_eth_txconf) { @@ -2266,7 +2277,7 @@ eth_igb_infos_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info) .hthresh = IGB_DEFAULT_TX_HTHRESH, .wthresh = IGB_DEFAULT_TX_WTHRESH, }, - .txq_flags = 0, + .offloads = 0, }; dev_info->rx_desc_lim = rx_desc_lim; @@ -2275,6 +2286,10 @@ eth_igb_infos_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info) dev_info->speed_capa = ETH_LINK_SPEED_10M_HD | ETH_LINK_SPEED_10M | ETH_LINK_SPEED_100M_HD | ETH_LINK_SPEED_100M | ETH_LINK_SPEED_1G; + + dev_info->max_mtu = dev_info->max_rx_pktlen - E1000_ETH_OVERHEAD; + dev_info->min_mtu = ETHER_MIN_MTU; + } static const uint32_t * @@ -2309,14 +2324,9 @@ eth_igbvf_infos_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info) { struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); - dev_info->pci_dev = RTE_ETH_DEV_TO_PCI(dev); dev_info->min_rx_bufsize = 256; /* See BSIZE field of RCTL register. */ dev_info->max_rx_pktlen = 0x3FFF; /* See RLPML register. */ dev_info->max_mac_addrs = hw->mac.rar_entry_count; - dev_info->rx_offload_capa = DEV_RX_OFFLOAD_VLAN_STRIP | - DEV_RX_OFFLOAD_IPV4_CKSUM | - DEV_RX_OFFLOAD_UDP_CKSUM | - DEV_RX_OFFLOAD_TCP_CKSUM; dev_info->tx_offload_capa = DEV_TX_OFFLOAD_VLAN_INSERT | DEV_TX_OFFLOAD_IPV4_CKSUM | DEV_TX_OFFLOAD_UDP_CKSUM | @@ -2337,6 +2347,13 @@ eth_igbvf_infos_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info) break; } + dev_info->rx_queue_offload_capa = igb_get_rx_queue_offloads_capa(dev); + dev_info->rx_offload_capa = igb_get_rx_port_offloads_capa(dev) | + dev_info->rx_queue_offload_capa; + dev_info->tx_queue_offload_capa = igb_get_tx_queue_offloads_capa(dev); + dev_info->tx_offload_capa = igb_get_tx_port_offloads_capa(dev) | + dev_info->tx_queue_offload_capa; + dev_info->default_rxconf = (struct rte_eth_rxconf) { .rx_thresh = { .pthresh = IGB_DEFAULT_RX_PTHRESH, @@ -2345,6 +2362,7 @@ eth_igbvf_infos_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info) }, .rx_free_thresh = IGB_DEFAULT_RX_FREE_THRESH, .rx_drop_en = 0, + .offloads = 0, }; dev_info->default_txconf = (struct rte_eth_txconf) { @@ -2353,7 +2371,7 @@ eth_igbvf_infos_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info) .hthresh = IGB_DEFAULT_TX_HTHRESH, .wthresh = IGB_DEFAULT_TX_WTHRESH, }, - .txq_flags = 0, + .offloads = 0, }; dev_info->rx_desc_lim = rx_desc_lim; @@ -2366,7 +2384,7 @@ eth_igb_link_update(struct rte_eth_dev *dev, int wait_to_complete) { struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); - struct rte_eth_link link, old; + struct rte_eth_link link; int link_check, count; link_check = 0; @@ -2407,8 +2425,6 @@ eth_igb_link_update(struct rte_eth_dev *dev, int wait_to_complete) rte_delay_ms(IGB_LINK_UPDATE_CHECK_INTERVAL); } memset(&link, 0, sizeof(link)); - rte_igb_dev_atomic_read_link_status(dev, &link); - old = link; /* Now we check if a transition has happened */ if (link_check) { @@ -2425,16 +2441,10 @@ eth_igb_link_update(struct rte_eth_dev *dev, int wait_to_complete) link.link_speed = 0; link.link_duplex = ETH_LINK_HALF_DUPLEX; link.link_status = ETH_LINK_DOWN; - link.link_autoneg = ETH_LINK_SPEED_FIXED; + link.link_autoneg = ETH_LINK_FIXED; } - rte_igb_dev_atomic_write_link_status(dev, &link); - - /* not changed */ - if (old.link_status == link.link_status) - return -1; - /* changed */ - return 0; + return rte_eth_linkstatus_set(dev, &link); } /* @@ -2688,7 +2698,7 @@ igb_vlan_hw_extend_disable(struct rte_eth_dev *dev) E1000_WRITE_REG(hw, E1000_CTRL_EXT, reg); /* Update maximum packet length */ - if (dev->data->dev_conf.rxmode.jumbo_frame == 1) + if (dev->data->dev_conf.rxmode.offloads & DEV_RX_OFFLOAD_JUMBO_FRAME) E1000_WRITE_REG(hw, E1000_RLPML, dev->data->dev_conf.rxmode.max_rx_pkt_len + VLAN_TAG_SIZE); @@ -2707,35 +2717,40 @@ igb_vlan_hw_extend_enable(struct rte_eth_dev *dev) E1000_WRITE_REG(hw, E1000_CTRL_EXT, reg); /* Update maximum packet length */ - if (dev->data->dev_conf.rxmode.jumbo_frame == 1) + if (dev->data->dev_conf.rxmode.offloads & DEV_RX_OFFLOAD_JUMBO_FRAME) E1000_WRITE_REG(hw, E1000_RLPML, dev->data->dev_conf.rxmode.max_rx_pkt_len + 2 * VLAN_TAG_SIZE); } -static void +static int eth_igb_vlan_offload_set(struct rte_eth_dev *dev, int mask) { + struct rte_eth_rxmode *rxmode; + + rxmode = &dev->data->dev_conf.rxmode; if(mask & ETH_VLAN_STRIP_MASK){ - if (dev->data->dev_conf.rxmode.hw_vlan_strip) + if (rxmode->offloads & DEV_RX_OFFLOAD_VLAN_STRIP) igb_vlan_hw_strip_enable(dev); else igb_vlan_hw_strip_disable(dev); } if(mask & ETH_VLAN_FILTER_MASK){ - if (dev->data->dev_conf.rxmode.hw_vlan_filter) + if (rxmode->offloads & DEV_RX_OFFLOAD_VLAN_FILTER) igb_vlan_hw_filter_enable(dev); else igb_vlan_hw_filter_disable(dev); } if(mask & ETH_VLAN_EXTEND_MASK){ - if (dev->data->dev_conf.rxmode.hw_vlan_extend) + if (rxmode->offloads & DEV_RX_OFFLOAD_VLAN_EXTEND) igb_vlan_hw_extend_enable(dev); else igb_vlan_hw_extend_disable(dev); } + + return 0; } @@ -2744,18 +2759,23 @@ eth_igb_vlan_offload_set(struct rte_eth_dev *dev, int mask) * * @param dev * Pointer to struct rte_eth_dev. + * @param on + * Enable or Disable * * @return * - On success, zero. * - On failure, a negative value. */ static int -eth_igb_lsc_interrupt_setup(struct rte_eth_dev *dev) +eth_igb_lsc_interrupt_setup(struct rte_eth_dev *dev, uint8_t on) { struct e1000_interrupt *intr = E1000_DEV_PRIVATE_TO_INTR(dev->data->dev_private); - intr->mask |= E1000_ICR_LSC; + if (on) + intr->mask |= E1000_ICR_LSC; + else + intr->mask &= ~E1000_ICR_LSC; return 0; } @@ -2775,12 +2795,15 @@ static int eth_igb_rxq_interrupt_setup(struct rte_eth_dev *dev) uint32_t mask, regval; struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); + struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev); + struct rte_intr_handle *intr_handle = &pci_dev->intr_handle; + int misc_shift = rte_intr_allow_others(intr_handle) ? 1 : 0; struct rte_eth_dev_info dev_info; memset(&dev_info, 0, sizeof(dev_info)); eth_igb_infos_get(dev, &dev_info); - mask = 0xFFFFFFFF >> (32 - dev_info.max_rx_queues); + mask = (0xFFFFFFFF >> (32 - dev_info.max_rx_queues)) << misc_shift; regval = E1000_READ_REG(hw, E1000_EIMS); E1000_WRITE_REG(hw, E1000_EIMS, regval | mask); @@ -2807,7 +2830,7 @@ eth_igb_interrupt_get_status(struct rte_eth_dev *dev) struct e1000_interrupt *intr = E1000_DEV_PRIVATE_TO_INTR(dev->data->dev_private); - igb_intr_disable(hw); + igb_intr_disable(dev); /* read-on-clear nic registers here */ icr = E1000_READ_REG(hw, E1000_ICR); @@ -2842,7 +2865,6 @@ eth_igb_interrupt_action(struct rte_eth_dev *dev, struct e1000_interrupt *intr = E1000_DEV_PRIVATE_TO_INTR(dev->data->dev_private); struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev); - uint32_t tctl, rctl; struct rte_eth_link link; int ret; @@ -2865,8 +2887,7 @@ eth_igb_interrupt_action(struct rte_eth_dev *dev, if (ret < 0) return 0; - memset(&link, 0, sizeof(link)); - rte_igb_dev_atomic_read_link_status(dev, &link); + rte_eth_linkstatus_get(dev, &link); if (link.link_status) { PMD_INIT_LOG(INFO, " Port %d: Link Up - speed %u Mbps - %s", @@ -2884,22 +2905,8 @@ eth_igb_interrupt_action(struct rte_eth_dev *dev, pci_dev->addr.bus, pci_dev->addr.devid, pci_dev->addr.function); - tctl = E1000_READ_REG(hw, E1000_TCTL); - rctl = E1000_READ_REG(hw, E1000_RCTL); - if (link.link_status) { - /* enable Tx/Rx */ - tctl |= E1000_TCTL_EN; - rctl |= E1000_RCTL_EN; - } else { - /* disable Tx/Rx */ - tctl &= ~E1000_TCTL_EN; - rctl &= ~E1000_RCTL_EN; - } - E1000_WRITE_REG(hw, E1000_TCTL, tctl); - E1000_WRITE_REG(hw, E1000_RCTL, rctl); - E1000_WRITE_FLUSH(hw); _rte_eth_dev_callback_process(dev, RTE_ETH_EVENT_INTR_LSC, - NULL, NULL); + NULL); } return 0; @@ -2953,13 +2960,17 @@ void igbvf_mbx_process(struct rte_eth_dev *dev) struct e1000_mbx_info *mbx = &hw->mbx; u32 in_msg = 0; - if (mbx->ops.read(hw, &in_msg, 1, 0)) - return; + /* peek the message first */ + in_msg = E1000_READ_REG(hw, E1000_VMBMEM(0)); /* PF reset VF event */ - if (in_msg == E1000_PF_CONTROL_MSG) + if (in_msg == E1000_PF_CONTROL_MSG) { + /* dummy mbx read to ack pf */ + if (mbx->ops.read(hw, &in_msg, 1, 0)) + return; _rte_eth_dev_callback_process(dev, RTE_ETH_EVENT_INTR_RESET, - NULL, NULL); + NULL); + } } static int @@ -3110,7 +3121,7 @@ eth_igb_flow_ctrl_set(struct rte_eth_dev *dev, struct rte_eth_fc_conf *fc_conf) #define E1000_RAH_POOLSEL_SHIFT (18) static int -eth_igb_rar_set(struct rte_eth_dev *dev, struct ether_addr *mac_addr, +eth_igb_rar_set(struct rte_eth_dev *dev, struct rte_ether_addr *mac_addr, uint32_t index, uint32_t pool) { struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); @@ -3134,13 +3145,14 @@ eth_igb_rar_clear(struct rte_eth_dev *dev, uint32_t index) e1000_rar_set(hw, addr, index); } -static void +static int eth_igb_default_mac_addr_set(struct rte_eth_dev *dev, - struct ether_addr *addr) + struct rte_ether_addr *addr) { eth_igb_rar_clear(dev, 0); - eth_igb_rar_set(dev, (void *)addr, 0, 0); + + return 0; } /* * Virtual Function operations @@ -3238,14 +3250,14 @@ igbvf_dev_configure(struct rte_eth_dev *dev) * Keep the persistent behavior the same as Host PF */ #ifndef RTE_LIBRTE_E1000_PF_DISABLE_STRIP_CRC - if (!conf->rxmode.hw_strip_crc) { + if (conf->rxmode.offloads & DEV_RX_OFFLOAD_KEEP_CRC) { PMD_INIT_LOG(NOTICE, "VF can't disable HW CRC Strip"); - conf->rxmode.hw_strip_crc = 1; + conf->rxmode.offloads &= ~DEV_RX_OFFLOAD_KEEP_CRC; } #else - if (conf->rxmode.hw_strip_crc) { + if (!(conf->rxmode.offloads & DEV_RX_OFFLOAD_KEEP_CRC)) { PMD_INIT_LOG(NOTICE, "VF can't enable HW CRC Strip"); - conf->rxmode.hw_strip_crc = 0; + conf->rxmode.offloads |= DEV_RX_OFFLOAD_KEEP_CRC; } #endif @@ -3283,7 +3295,8 @@ igbvf_dev_start(struct rte_eth_dev *dev) } /* check and configure queue intr-vector mapping */ - if (dev->data->dev_conf.intr_conf.rxq != 0) { + if (rte_intr_cap_multiple(intr_handle) && + dev->data->dev_conf.intr_conf.rxq) { intr_vector = dev->data->nb_rx_queues; ret = rte_intr_efd_enable(intr_handle, intr_vector); if (ret) @@ -3347,7 +3360,7 @@ igbvf_dev_close(struct rte_eth_dev *dev) struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); struct e1000_adapter *adapter = E1000_DEV_PRIVATE(dev->data->dev_private); - struct ether_addr addr; + struct rte_ether_addr addr; PMD_INIT_FUNC_TRACE(); @@ -3491,14 +3504,15 @@ igbvf_vlan_filter_set(struct rte_eth_dev *dev, uint16_t vlan_id, int on) return 0; } -static void -igbvf_default_mac_addr_set(struct rte_eth_dev *dev, struct ether_addr *addr) +static int +igbvf_default_mac_addr_set(struct rte_eth_dev *dev, struct rte_ether_addr *addr) { struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); /* index is not used by rar_set() */ hw->mac.ops.rar_set(hw, (void *)addr, 0); + return 0; } @@ -4087,7 +4101,7 @@ eth_igb_get_flex_filter(struct rte_eth_dev *dev, flex_filter.filter_info.priority = filter->priority; memcpy(flex_filter.filter_info.dwords, filter->bytes, filter->len); memcpy(flex_filter.filter_info.mask, filter->mask, - RTE_ALIGN(filter->len, sizeof(char)) / sizeof(char)); + RTE_ALIGN(filter->len, CHAR_BIT) / CHAR_BIT); it = eth_igb_flex_filter_lookup(&filter_info->flex_list, &flex_filter.filter_info); @@ -4459,8 +4473,7 @@ eth_igb_mtu_set(struct rte_eth_dev *dev, uint16_t mtu) uint32_t rctl; struct e1000_hw *hw; struct rte_eth_dev_info dev_info; - uint32_t frame_size = mtu + (ETHER_HDR_LEN + ETHER_CRC_LEN + - VLAN_TAG_SIZE); + uint32_t frame_size = mtu + E1000_ETH_OVERHEAD; hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); @@ -4486,10 +4499,12 @@ eth_igb_mtu_set(struct rte_eth_dev *dev, uint16_t mtu) /* switch to jumbo mode if needed */ if (frame_size > ETHER_MAX_LEN) { - dev->data->dev_conf.rxmode.jumbo_frame = 1; + dev->data->dev_conf.rxmode.offloads |= + DEV_RX_OFFLOAD_JUMBO_FRAME; rctl |= E1000_RCTL_LPE; } else { - dev->data->dev_conf.rxmode.jumbo_frame = 0; + dev->data->dev_conf.rxmode.offloads &= + ~DEV_RX_OFFLOAD_JUMBO_FRAME; rctl &= ~E1000_RCTL_LPE; } E1000_WRITE_REG(hw, E1000_RCTL, rctl); @@ -4892,7 +4907,7 @@ eth_igb_filter_ctrl(struct rte_eth_dev *dev, static int eth_igb_set_mc_addr_list(struct rte_eth_dev *dev, - struct ether_addr *mc_addr_set, + struct rte_ether_addr *mc_addr_set, uint32_t nb_mc_addr) { struct e1000_hw *hw; @@ -5370,12 +5385,99 @@ eth_igb_set_eeprom(struct rte_eth_dev *dev, return nvm->ops.write(hw, first, length, data); } +static int +eth_igb_get_module_info(struct rte_eth_dev *dev, + struct rte_eth_dev_module_info *modinfo) +{ + struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); + + uint32_t status = 0; + uint16_t sff8472_rev, addr_mode; + bool page_swap = false; + + if (hw->phy.media_type == e1000_media_type_copper || + hw->phy.media_type == e1000_media_type_unknown) + return -EOPNOTSUPP; + + /* Check whether we support SFF-8472 or not */ + status = e1000_read_phy_reg_i2c(hw, IGB_SFF_8472_COMP, &sff8472_rev); + if (status) + return -EIO; + + /* addressing mode is not supported */ + status = e1000_read_phy_reg_i2c(hw, IGB_SFF_8472_SWAP, &addr_mode); + if (status) + return -EIO; + + /* addressing mode is not supported */ + if ((addr_mode & 0xFF) & IGB_SFF_ADDRESSING_MODE) { + PMD_DRV_LOG(ERR, + "Address change required to access page 0xA2, " + "but not supported. Please report the module " + "type to the driver maintainers.\n"); + page_swap = true; + } + + if ((sff8472_rev & 0xFF) == IGB_SFF_8472_UNSUP || page_swap) { + /* We have an SFP, but it does not support SFF-8472 */ + modinfo->type = RTE_ETH_MODULE_SFF_8079; + modinfo->eeprom_len = RTE_ETH_MODULE_SFF_8079_LEN; + } else { + /* We have an SFP which supports a revision of SFF-8472 */ + modinfo->type = RTE_ETH_MODULE_SFF_8472; + modinfo->eeprom_len = RTE_ETH_MODULE_SFF_8472_LEN; + } + + return 0; +} + +static int +eth_igb_get_module_eeprom(struct rte_eth_dev *dev, + struct rte_dev_eeprom_info *info) +{ + struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); + + uint32_t status = 0; + uint16_t dataword[RTE_ETH_MODULE_SFF_8472_LEN / 2 + 1]; + u16 first_word, last_word; + int i = 0; + + if (info->length == 0) + return -EINVAL; + + first_word = info->offset >> 1; + last_word = (info->offset + info->length - 1) >> 1; + + /* Read EEPROM block, SFF-8079/SFF-8472, word at a time */ + for (i = 0; i < last_word - first_word + 1; i++) { + status = e1000_read_phy_reg_i2c(hw, (first_word + i) * 2, + &dataword[i]); + if (status) { + /* Error occurred while reading module */ + return -EIO; + } + + dataword[i] = rte_be_to_cpu_16(dataword[i]); + } + + memcpy(info->data, (u8 *)dataword + (info->offset & 1), info->length); + + return 0; +} + static int eth_igb_rx_queue_intr_disable(struct rte_eth_dev *dev, uint16_t queue_id) { struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); - uint32_t mask = 1 << queue_id; + struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev); + struct rte_intr_handle *intr_handle = &pci_dev->intr_handle; + uint32_t vec = E1000_MISC_VEC_ID; + + if (rte_intr_allow_others(intr_handle)) + vec = E1000_RX_VEC_START; + + uint32_t mask = 1 << (queue_id + vec); E1000_WRITE_REG(hw, E1000_EIMC, mask); E1000_WRITE_FLUSH(hw); @@ -5390,7 +5492,12 @@ eth_igb_rx_queue_intr_enable(struct rte_eth_dev *dev, uint16_t queue_id) E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev); struct rte_intr_handle *intr_handle = &pci_dev->intr_handle; - uint32_t mask = 1 << queue_id; + uint32_t vec = E1000_MISC_VEC_ID; + + if (rte_intr_allow_others(intr_handle)) + vec = E1000_RX_VEC_START; + + uint32_t mask = 1 << (queue_id + vec); uint32_t regval; regval = E1000_READ_REG(hw, E1000_EIMS); @@ -5505,13 +5612,17 @@ eth_igb_configure_msix_intr(struct rte_eth_dev *dev) E1000_GPIE_NSICR); intr_mask = RTE_LEN2MASK(intr_handle->nb_efd, uint32_t) << misc_shift; + + if (dev->data->dev_conf.intr_conf.lsc != 0) + intr_mask |= (1 << IGB_MSIX_OTHER_INTR_VEC); + regval = E1000_READ_REG(hw, E1000_EIAC); E1000_WRITE_REG(hw, E1000_EIAC, regval | intr_mask); /* enable msix_other interrupt */ regval = E1000_READ_REG(hw, E1000_EIMS); E1000_WRITE_REG(hw, E1000_EIMS, regval | intr_mask); - tmpval = (dev->data->nb_rx_queues | E1000_IVAR_VALID) << 8; + tmpval = (IGB_MSIX_OTHER_INTR_VEC | E1000_IVAR_VALID) << 8; E1000_WRITE_REG(hw, E1000_IVAR_MISC, tmpval); } @@ -5520,6 +5631,10 @@ eth_igb_configure_msix_intr(struct rte_eth_dev *dev) */ intr_mask = RTE_LEN2MASK(intr_handle->nb_efd, uint32_t) << misc_shift; + + if (dev->data->dev_conf.intr_conf.lsc != 0) + intr_mask |= (1 << IGB_MSIX_OTHER_INTR_VEC); + regval = E1000_READ_REG(hw, E1000_EIAM); E1000_WRITE_REG(hw, E1000_EIAM, regval | intr_mask); @@ -5599,6 +5714,17 @@ igb_flex_filter_restore(struct rte_eth_dev *dev) } } +/* restore rss filter */ +static inline void +igb_rss_filter_restore(struct rte_eth_dev *dev) +{ + struct e1000_filter_info *filter_info = + E1000_DEV_PRIVATE_TO_FILTER_INFO(dev->data->dev_private); + + if (filter_info->rss_info.conf.queue_num) + igb_config_rss_filter(dev, &filter_info->rss_info, TRUE); +} + /* restore all types filter */ static int igb_filter_restore(struct rte_eth_dev *dev) @@ -5607,6 +5733,7 @@ igb_filter_restore(struct rte_eth_dev *dev) igb_ethertype_filter_restore(dev); igb_syn_filter_restore(dev); igb_flex_filter_restore(dev); + igb_rss_filter_restore(dev); return 0; } @@ -5617,3 +5744,9 @@ RTE_PMD_REGISTER_KMOD_DEP(net_e1000_igb, "* igb_uio | uio_pci_generic | vfio-pci RTE_PMD_REGISTER_PCI(net_e1000_igb_vf, rte_igbvf_pmd); RTE_PMD_REGISTER_PCI_TABLE(net_e1000_igb_vf, pci_id_igbvf_map); RTE_PMD_REGISTER_KMOD_DEP(net_e1000_igb_vf, "* igb_uio | vfio-pci"); + +/* see e1000_logs.c */ +RTE_INIT(e1000_init_log) +{ + e1000_igb_init_log(); +}