X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=drivers%2Fnet%2Fngbe%2Fngbe_ethdev.c;h=80715f8bdc6500797a158d6876393725648978df;hb=0779d7f6199143c6103609f8a4359e6920c96897;hp=0e588eeccef8a1ecd0cb541951ef33030d7732a9;hpb=b83372a03045458ecec9bdb6fca463bf326de751;p=dpdk.git diff --git a/drivers/net/ngbe/ngbe_ethdev.c b/drivers/net/ngbe/ngbe_ethdev.c index 0e588eecce..80715f8bdc 100644 --- a/drivers/net/ngbe/ngbe_ethdev.c +++ b/drivers/net/ngbe/ngbe_ethdev.c @@ -807,6 +807,9 @@ ngbe_dev_configure(struct rte_eth_dev *dev) PMD_INIT_FUNC_TRACE(); + if (dev->data->dev_conf.rxmode.mq_mode & RTE_ETH_MQ_RX_RSS_FLAG) + dev->data->dev_conf.rxmode.offloads |= RTE_ETH_RX_OFFLOAD_RSS_HASH; + /* set flag to update link status after init */ intr->flags |= NGBE_FLAG_NEED_LINK_UPDATE; @@ -924,6 +927,10 @@ ngbe_dev_start(struct rte_eth_dev *dev) goto error; } + /* Skip link setup if loopback mode is enabled. */ + if (hw->is_pf && dev->data->dev_conf.lpbk_mode) + goto skip_link_setup; + err = hw->mac.check_link(hw, &speed, &link_up, 0); if (err != 0) goto error; @@ -967,6 +974,8 @@ ngbe_dev_start(struct rte_eth_dev *dev) if (err != 0) goto error; +skip_link_setup: + if (rte_intr_allow_others(intr_handle)) { ngbe_dev_misc_interrupt_setup(dev); /* check if lsc interrupt is enabled */ @@ -1025,6 +1034,7 @@ static int ngbe_dev_stop(struct rte_eth_dev *dev) { struct rte_eth_link link; + struct ngbe_adapter *adapter = ngbe_dev_adapter(dev); struct ngbe_hw *hw = ngbe_dev_hw(dev); struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev); struct rte_intr_handle *intr_handle = pci_dev->intr_handle; @@ -1069,6 +1079,8 @@ ngbe_dev_stop(struct rte_eth_dev *dev) rte_intr_efd_disable(intr_handle); rte_intr_vec_list_free(intr_handle); + adapter->rss_reta_updated = 0; + hw->adapter_stopped = true; dev->data->dev_started = 0; @@ -1595,15 +1607,37 @@ ngbe_dev_xstats_reset(struct rte_eth_dev *dev) return 0; } +static int +ngbe_fw_version_get(struct rte_eth_dev *dev, char *fw_version, size_t fw_size) +{ + struct ngbe_hw *hw = ngbe_dev_hw(dev); + int ret; + + ret = snprintf(fw_version, fw_size, "0x%08x", hw->eeprom_id); + + if (ret < 0) + return -EINVAL; + + ret += 1; /* add the size of '\0' */ + if (fw_size < (size_t)ret) + return ret; + + return 0; +} + static int ngbe_dev_info_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info) { + struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev); struct ngbe_hw *hw = ngbe_dev_hw(dev); dev_info->max_rx_queues = (uint16_t)hw->mac.max_rx_queues; dev_info->max_tx_queues = (uint16_t)hw->mac.max_tx_queues; dev_info->min_rx_bufsize = 1024; dev_info->max_rx_pktlen = 15872; + dev_info->max_mac_addrs = hw->mac.num_rar_entries; + dev_info->max_hash_mac_addrs = NGBE_VMDQ_NUM_UC_MAC; + dev_info->max_vfs = pci_dev->max_vfs; dev_info->rx_queue_offload_capa = ngbe_get_rx_queue_offloads(dev); dev_info->rx_offload_capa = (ngbe_get_rx_port_offloads(dev) | dev_info->rx_queue_offload_capa); @@ -1634,6 +1668,10 @@ ngbe_dev_info_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info) dev_info->rx_desc_lim = rx_desc_lim; dev_info->tx_desc_lim = tx_desc_lim; + dev_info->hash_key_size = NGBE_HKEY_MAX_INDEX * sizeof(uint32_t); + dev_info->reta_size = RTE_ETH_RSS_RETA_SIZE_128; + dev_info->flow_type_rss_offloads = NGBE_RSS_OFFLOAD_ALL; + dev_info->speed_capa = RTE_ETH_LINK_SPEED_1G | RTE_ETH_LINK_SPEED_100M | RTE_ETH_LINK_SPEED_10M; @@ -2100,6 +2138,121 @@ ngbe_dev_interrupt_handler(void *param) ngbe_dev_interrupt_action(dev); } +int +ngbe_dev_rss_reta_update(struct rte_eth_dev *dev, + struct rte_eth_rss_reta_entry64 *reta_conf, + uint16_t reta_size) +{ + uint8_t i, j, mask; + uint32_t reta; + uint16_t idx, shift; + struct ngbe_adapter *adapter = ngbe_dev_adapter(dev); + struct ngbe_hw *hw = ngbe_dev_hw(dev); + + PMD_INIT_FUNC_TRACE(); + + if (!hw->is_pf) { + PMD_DRV_LOG(ERR, "RSS reta update is not supported on this " + "NIC."); + return -ENOTSUP; + } + + if (reta_size != RTE_ETH_RSS_RETA_SIZE_128) { + PMD_DRV_LOG(ERR, "The size of hash lookup table configured " + "(%d) doesn't match the number hardware can supported " + "(%d)", reta_size, RTE_ETH_RSS_RETA_SIZE_128); + return -EINVAL; + } + + for (i = 0; i < reta_size; i += 4) { + idx = i / RTE_ETH_RETA_GROUP_SIZE; + shift = i % RTE_ETH_RETA_GROUP_SIZE; + mask = (uint8_t)RS64(reta_conf[idx].mask, shift, 0xF); + if (!mask) + continue; + + reta = rd32a(hw, NGBE_REG_RSSTBL, i >> 2); + for (j = 0; j < 4; j++) { + if (RS8(mask, j, 0x1)) { + reta &= ~(MS32(8 * j, 0xFF)); + reta |= LS32(reta_conf[idx].reta[shift + j], + 8 * j, 0xFF); + } + } + wr32a(hw, NGBE_REG_RSSTBL, i >> 2, reta); + } + adapter->rss_reta_updated = 1; + + return 0; +} + +int +ngbe_dev_rss_reta_query(struct rte_eth_dev *dev, + struct rte_eth_rss_reta_entry64 *reta_conf, + uint16_t reta_size) +{ + struct ngbe_hw *hw = ngbe_dev_hw(dev); + uint8_t i, j, mask; + uint32_t reta; + uint16_t idx, shift; + + PMD_INIT_FUNC_TRACE(); + + if (reta_size != RTE_ETH_RSS_RETA_SIZE_128) { + PMD_DRV_LOG(ERR, "The size of hash lookup table configured " + "(%d) doesn't match the number hardware can supported " + "(%d)", reta_size, RTE_ETH_RSS_RETA_SIZE_128); + return -EINVAL; + } + + for (i = 0; i < reta_size; i += 4) { + idx = i / RTE_ETH_RETA_GROUP_SIZE; + shift = i % RTE_ETH_RETA_GROUP_SIZE; + mask = (uint8_t)RS64(reta_conf[idx].mask, shift, 0xF); + if (!mask) + continue; + + reta = rd32a(hw, NGBE_REG_RSSTBL, i >> 2); + for (j = 0; j < 4; j++) { + if (RS8(mask, j, 0x1)) + reta_conf[idx].reta[shift + j] = + (uint16_t)RS32(reta, 8 * j, 0xFF); + } + } + + return 0; +} + +static int +ngbe_add_rar(struct rte_eth_dev *dev, struct rte_ether_addr *mac_addr, + uint32_t index, uint32_t pool) +{ + struct ngbe_hw *hw = ngbe_dev_hw(dev); + uint32_t enable_addr = 1; + + return ngbe_set_rar(hw, index, mac_addr->addr_bytes, + pool, enable_addr); +} + +static void +ngbe_remove_rar(struct rte_eth_dev *dev, uint32_t index) +{ + struct ngbe_hw *hw = ngbe_dev_hw(dev); + + ngbe_clear_rar(hw, index); +} + +static int +ngbe_set_default_mac_addr(struct rte_eth_dev *dev, struct rte_ether_addr *addr) +{ + struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev); + + ngbe_remove_rar(dev, 0); + ngbe_add_rar(dev, addr, 0, pci_dev->max_vfs); + + return 0; +} + static int ngbe_dev_mtu_set(struct rte_eth_dev *dev, uint16_t mtu) { @@ -2127,6 +2280,116 @@ ngbe_dev_mtu_set(struct rte_eth_dev *dev, uint16_t mtu) return 0; } +static uint32_t +ngbe_uta_vector(struct ngbe_hw *hw, struct rte_ether_addr *uc_addr) +{ + uint32_t vector = 0; + + switch (hw->mac.mc_filter_type) { + case 0: /* use bits [47:36] of the address */ + vector = ((uc_addr->addr_bytes[4] >> 4) | + (((uint16_t)uc_addr->addr_bytes[5]) << 4)); + break; + case 1: /* use bits [46:35] of the address */ + vector = ((uc_addr->addr_bytes[4] >> 3) | + (((uint16_t)uc_addr->addr_bytes[5]) << 5)); + break; + case 2: /* use bits [45:34] of the address */ + vector = ((uc_addr->addr_bytes[4] >> 2) | + (((uint16_t)uc_addr->addr_bytes[5]) << 6)); + break; + case 3: /* use bits [43:32] of the address */ + vector = ((uc_addr->addr_bytes[4]) | + (((uint16_t)uc_addr->addr_bytes[5]) << 8)); + break; + default: /* Invalid mc_filter_type */ + break; + } + + /* vector can only be 12-bits or boundary will be exceeded */ + vector &= 0xFFF; + return vector; +} + +static int +ngbe_uc_hash_table_set(struct rte_eth_dev *dev, + struct rte_ether_addr *mac_addr, uint8_t on) +{ + uint32_t vector; + uint32_t uta_idx; + uint32_t reg_val; + uint32_t uta_mask; + uint32_t psrctl; + + struct ngbe_hw *hw = ngbe_dev_hw(dev); + struct ngbe_uta_info *uta_info = NGBE_DEV_UTA_INFO(dev); + + vector = ngbe_uta_vector(hw, mac_addr); + uta_idx = (vector >> 5) & 0x7F; + uta_mask = 0x1UL << (vector & 0x1F); + + if (!!on == !!(uta_info->uta_shadow[uta_idx] & uta_mask)) + return 0; + + reg_val = rd32(hw, NGBE_UCADDRTBL(uta_idx)); + if (on) { + uta_info->uta_in_use++; + reg_val |= uta_mask; + uta_info->uta_shadow[uta_idx] |= uta_mask; + } else { + uta_info->uta_in_use--; + reg_val &= ~uta_mask; + uta_info->uta_shadow[uta_idx] &= ~uta_mask; + } + + wr32(hw, NGBE_UCADDRTBL(uta_idx), reg_val); + + psrctl = rd32(hw, NGBE_PSRCTL); + if (uta_info->uta_in_use > 0) + psrctl |= NGBE_PSRCTL_UCHFENA; + else + psrctl &= ~NGBE_PSRCTL_UCHFENA; + + psrctl &= ~NGBE_PSRCTL_ADHF12_MASK; + psrctl |= NGBE_PSRCTL_ADHF12(hw->mac.mc_filter_type); + wr32(hw, NGBE_PSRCTL, psrctl); + + return 0; +} + +static int +ngbe_uc_all_hash_table_set(struct rte_eth_dev *dev, uint8_t on) +{ + struct ngbe_hw *hw = ngbe_dev_hw(dev); + struct ngbe_uta_info *uta_info = NGBE_DEV_UTA_INFO(dev); + uint32_t psrctl; + int i; + + if (on) { + for (i = 0; i < RTE_ETH_VMDQ_NUM_UC_HASH_ARRAY; i++) { + uta_info->uta_shadow[i] = ~0; + wr32(hw, NGBE_UCADDRTBL(i), ~0); + } + } else { + for (i = 0; i < RTE_ETH_VMDQ_NUM_UC_HASH_ARRAY; i++) { + uta_info->uta_shadow[i] = 0; + wr32(hw, NGBE_UCADDRTBL(i), 0); + } + } + + psrctl = rd32(hw, NGBE_PSRCTL); + if (on) + psrctl |= NGBE_PSRCTL_UCHFENA; + else + psrctl &= ~NGBE_PSRCTL_UCHFENA; + + psrctl &= ~NGBE_PSRCTL_ADHF12_MASK; + psrctl |= NGBE_PSRCTL_ADHF12(hw->mac.mc_filter_type); + wr32(hw, NGBE_PSRCTL, psrctl); + + return 0; +} + /** * Set the IVAR registers, mapping interrupt causes to vectors * @param hw @@ -2221,6 +2484,31 @@ ngbe_configure_msix(struct rte_eth_dev *dev) | NGBE_ITR_WRDSA); } +static u8 * +ngbe_dev_addr_list_itr(__rte_unused struct ngbe_hw *hw, + u8 **mc_addr_ptr, u32 *vmdq) +{ + u8 *mc_addr; + + *vmdq = 0; + mc_addr = *mc_addr_ptr; + *mc_addr_ptr = (mc_addr + sizeof(struct rte_ether_addr)); + return mc_addr; +} + +int +ngbe_dev_set_mc_addr_list(struct rte_eth_dev *dev, + struct rte_ether_addr *mc_addr_set, + uint32_t nb_mc_addr) +{ + struct ngbe_hw *hw = ngbe_dev_hw(dev); + u8 *mc_addr_list; + + mc_addr_list = (u8 *)mc_addr_set; + return hw->mac.update_mc_addr_list(hw, mc_addr_list, nb_mc_addr, + ngbe_dev_addr_list_itr, TRUE); +} + static const struct eth_dev_ops ngbe_eth_dev_ops = { .dev_configure = ngbe_dev_configure, .dev_infos_get = ngbe_dev_info_get, @@ -2240,6 +2528,7 @@ static const struct eth_dev_ops ngbe_eth_dev_ops = { .xstats_reset = ngbe_dev_xstats_reset, .xstats_get_names = ngbe_dev_xstats_get_names, .xstats_get_names_by_id = ngbe_dev_xstats_get_names_by_id, + .fw_version_get = ngbe_fw_version_get, .dev_supported_ptypes_get = ngbe_dev_supported_ptypes_get, .mtu_set = ngbe_dev_mtu_set, .vlan_filter_set = ngbe_vlan_filter_set, @@ -2254,6 +2543,16 @@ static const struct eth_dev_ops ngbe_eth_dev_ops = { .rx_queue_release = ngbe_dev_rx_queue_release, .tx_queue_setup = ngbe_dev_tx_queue_setup, .tx_queue_release = ngbe_dev_tx_queue_release, + .mac_addr_add = ngbe_add_rar, + .mac_addr_remove = ngbe_remove_rar, + .mac_addr_set = ngbe_set_default_mac_addr, + .uc_hash_table_set = ngbe_uc_hash_table_set, + .uc_all_hash_table_set = ngbe_uc_all_hash_table_set, + .reta_update = ngbe_dev_rss_reta_update, + .reta_query = ngbe_dev_rss_reta_query, + .rss_hash_update = ngbe_dev_rss_hash_update, + .rss_hash_conf_get = ngbe_dev_rss_hash_conf_get, + .set_mc_addr_list = ngbe_dev_set_mc_addr_list, .rx_burst_mode_get = ngbe_rx_burst_mode_get, .tx_burst_mode_get = ngbe_tx_burst_mode_get, };