X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=lib%2Flibrte_pmd_e1000%2Figb_ethdev.c;h=2a268b8d89f17453b58457f243b9e11dea6b6eae;hb=b0920f481ae5643a257fc32f3b98462626830b03;hp=ae7e03b9e5f071fda89646ad31f3c89892dcd377;hpb=70bdb18657da9dc7d3a71fe9ac3522c7640fa629;p=dpdk.git diff --git a/lib/librte_pmd_e1000/igb_ethdev.c b/lib/librte_pmd_e1000/igb_ethdev.c index ae7e03b9e5..2a268b8d89 100644 --- a/lib/librte_pmd_e1000/igb_ethdev.c +++ b/lib/librte_pmd_e1000/igb_ethdev.c @@ -57,6 +57,24 @@ #include "e1000/e1000_api.h" #include "e1000_ethdev.h" +/* + * Default values for port configuration + */ +#define IGB_DEFAULT_RX_FREE_THRESH 32 +#define IGB_DEFAULT_RX_PTHRESH 8 +#define IGB_DEFAULT_RX_HTHRESH 8 +#define IGB_DEFAULT_RX_WTHRESH 0 + +#define IGB_DEFAULT_TX_PTHRESH 32 +#define IGB_DEFAULT_TX_HTHRESH 0 +#define IGB_DEFAULT_TX_WTHRESH 0 + +/* 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) +#define IGB_8_BIT_WIDTH CHAR_BIT +#define IGB_8_BIT_MASK UINT8_MAX + 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); @@ -71,7 +89,11 @@ static void eth_igb_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *rte_stats); static void eth_igb_stats_reset(struct rte_eth_dev *dev); static void eth_igb_infos_get(struct rte_eth_dev *dev, + struct rte_eth_dev_info *dev_info); +static void eth_igbvf_infos_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info); +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); @@ -85,6 +107,8 @@ static void igb_hw_control_release(struct e1000_hw *hw); static void igb_init_manageability(struct e1000_hw *hw); static void igb_release_manageability(struct e1000_hw *hw); +static int eth_igb_mtu_set(struct rte_eth_dev *dev, uint16_t mtu); + static int eth_igb_vlan_filter_set(struct rte_eth_dev *dev, uint16_t vlan_id, int on); static void eth_igb_vlan_tpid_set(struct rte_eth_dev *dev, uint16_t tpid_id); @@ -120,23 +144,16 @@ static int igbvf_vlan_filter_set(struct rte_eth_dev *dev, 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 int eth_igb_rss_reta_update(struct rte_eth_dev *dev, - struct rte_eth_rss_reta *reta_conf); + struct rte_eth_rss_reta_entry64 *reta_conf, + uint16_t reta_size); static int eth_igb_rss_reta_query(struct rte_eth_dev *dev, - struct rte_eth_rss_reta *reta_conf); - + struct rte_eth_rss_reta_entry64 *reta_conf, + uint16_t reta_size); static int eth_igb_add_syn_filter(struct rte_eth_dev *dev, struct rte_syn_filter *filter, uint16_t rx_queue); static int eth_igb_remove_syn_filter(struct rte_eth_dev *dev); static int eth_igb_get_syn_filter(struct rte_eth_dev *dev, struct rte_syn_filter *filter, uint16_t *rx_queue); -static int eth_igb_add_ethertype_filter(struct rte_eth_dev *dev, - uint16_t index, - struct rte_ethertype_filter *filter, uint16_t rx_queue); -static int eth_igb_remove_ethertype_filter(struct rte_eth_dev *dev, - uint16_t index); -static int eth_igb_get_ethertype_filter(struct rte_eth_dev *dev, - uint16_t index, - struct rte_ethertype_filter *filter, uint16_t *rx_queue); static int eth_igb_add_2tuple_filter(struct rte_eth_dev *dev, uint16_t index, struct rte_2tuple_filter *filter, uint16_t rx_queue); @@ -161,6 +178,18 @@ static int eth_igb_remove_5tuple_filter(struct rte_eth_dev *dev, static int eth_igb_get_5tuple_filter(struct rte_eth_dev *dev, uint16_t index, struct rte_5tuple_filter *filter, uint16_t *rx_queue); +static int igb_add_del_ethertype_filter(struct rte_eth_dev *dev, + struct rte_eth_ethertype_filter *filter, + bool add); +static int igb_ethertype_filter_handle(struct rte_eth_dev *dev, + enum rte_filter_op filter_op, + void *arg); +static int igb_get_ethertype_filter(struct rte_eth_dev *dev, + struct rte_eth_ethertype_filter *filter); +static int eth_igb_filter_ctrl(struct rte_eth_dev *dev, + enum rte_filter_type filter_type, + enum rte_filter_op filter_op, + void *arg); /* * Define VF Stats MACRO for Non "cleared on read" register @@ -216,6 +245,7 @@ static struct eth_dev_ops eth_igb_ops = { .stats_get = eth_igb_stats_get, .stats_reset = eth_igb_stats_reset, .dev_infos_get = eth_igb_infos_get, + .mtu_set = eth_igb_mtu_set, .vlan_filter_set = eth_igb_vlan_filter_set, .vlan_tpid_set = eth_igb_vlan_tpid_set, .vlan_offload_set = eth_igb_vlan_offload_set, @@ -227,6 +257,7 @@ static struct eth_dev_ops eth_igb_ops = { .tx_queue_release = eth_igb_tx_queue_release, .dev_led_on = eth_igb_led_on, .dev_led_off = eth_igb_led_off, + .flow_ctrl_get = eth_igb_flow_ctrl_get, .flow_ctrl_set = eth_igb_flow_ctrl_set, .mac_addr_add = eth_igb_rar_set, .mac_addr_remove = eth_igb_rar_clear, @@ -237,9 +268,6 @@ static struct eth_dev_ops eth_igb_ops = { .add_syn_filter = eth_igb_add_syn_filter, .remove_syn_filter = eth_igb_remove_syn_filter, .get_syn_filter = eth_igb_get_syn_filter, - .add_ethertype_filter = eth_igb_add_ethertype_filter, - .remove_ethertype_filter = eth_igb_remove_ethertype_filter, - .get_ethertype_filter = eth_igb_get_ethertype_filter, .add_2tuple_filter = eth_igb_add_2tuple_filter, .remove_2tuple_filter = eth_igb_remove_2tuple_filter, .get_2tuple_filter = eth_igb_get_2tuple_filter, @@ -249,6 +277,7 @@ static struct eth_dev_ops eth_igb_ops = { .add_5tuple_filter = eth_igb_add_5tuple_filter, .remove_5tuple_filter = eth_igb_remove_5tuple_filter, .get_5tuple_filter = eth_igb_get_5tuple_filter, + .filter_ctrl = eth_igb_filter_ctrl, }; /* @@ -264,7 +293,7 @@ static struct eth_dev_ops igbvf_eth_dev_ops = { .stats_get = eth_igbvf_stats_get, .stats_reset = eth_igbvf_stats_reset, .vlan_filter_set = igbvf_vlan_filter_set, - .dev_infos_get = eth_igb_infos_get, + .dev_infos_get = eth_igbvf_infos_get, .rx_queue_setup = eth_igb_rx_queue_setup, .rx_queue_release = eth_igb_rx_queue_release, .tx_queue_setup = eth_igb_tx_queue_setup, @@ -394,7 +423,7 @@ igb_reset_swfw_lock(struct e1000_hw *hw) * So force the release of the faulty lock. */ if (e1000_get_hw_semaphore_generic(hw) < 0) { - DEBUGOUT("SMBI lock released"); + PMD_DRV_LOG(DEBUG, "SMBI lock released"); } e1000_put_hw_semaphore_generic(hw); @@ -410,7 +439,8 @@ igb_reset_swfw_lock(struct e1000_hw *hw) if (hw->bus.func > E1000_FUNC_1) mask <<= 2; if (hw->mac.ops.acquire_swfw_sync(hw, mask) < 0) { - DEBUGOUT1("SWFW phy%d lock released", hw->bus.func); + PMD_DRV_LOG(DEBUG, "SWFW phy%d lock released", + hw->bus.func); } hw->mac.ops.release_swfw_sync(hw, mask); @@ -422,7 +452,7 @@ igb_reset_swfw_lock(struct e1000_hw *hw) */ mask = E1000_SWFW_EEP_SM; if (hw->mac.ops.acquire_swfw_sync(hw, mask) < 0) { - DEBUGOUT("SWFW common locks released"); + PMD_DRV_LOG(DEBUG, "SWFW common locks released"); } hw->mac.ops.release_swfw_sync(hw, mask); } @@ -558,7 +588,7 @@ eth_igb_dev_init(__attribute__((unused)) struct eth_driver *eth_drv, E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext); E1000_WRITE_FLUSH(hw); - PMD_INIT_LOG(INFO, "port_id %d vendorID=0x%x deviceID=0x%x\n", + PMD_INIT_LOG(INFO, "port_id %d vendorID=0x%x deviceID=0x%x", eth_dev->data->port_id, pci_dev->id.vendor_id, pci_dev->id.device_id); @@ -591,7 +621,7 @@ eth_igbvf_dev_init(__attribute__((unused)) struct eth_driver *eth_drv, E1000_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private); int diag; - PMD_INIT_LOG(DEBUG, "eth_igbvf_dev_init"); + PMD_INIT_FUNC_TRACE(); eth_dev->dev_ops = &igbvf_eth_dev_ops; eth_dev->rx_pkt_burst = ð_igb_recv_pkts; @@ -612,7 +642,7 @@ eth_igbvf_dev_init(__attribute__((unused)) struct eth_driver *eth_drv, hw->vendor_id = pci_dev->id.vendor_id; hw->hw_addr = (void *)pci_dev->mem_resource[0].addr; - /* Initialize the shared code */ + /* Initialize the shared code (base driver) */ diag = e1000_setup_init_funcs(hw, TRUE); if (diag != 0) { PMD_INIT_LOG(ERR, "Shared code init failed for igbvf: %d", @@ -643,11 +673,10 @@ eth_igbvf_dev_init(__attribute__((unused)) struct eth_driver *eth_drv, ether_addr_copy((struct ether_addr *) hw->mac.perm_addr, ð_dev->data->mac_addrs[0]); - PMD_INIT_LOG(DEBUG, "\nport %d vendorID=0x%x deviceID=0x%x " - "mac.type=%s\n", - eth_dev->data->port_id, pci_dev->id.vendor_id, - pci_dev->id.device_id, - "igb_mac_82576_vf"); + PMD_INIT_LOG(DEBUG, "port %d vendorID=0x%x deviceID=0x%x " + "mac.type=%s", + eth_dev->data->port_id, pci_dev->id.vendor_id, + pci_dev->id.device_id, "igb_mac_82576_vf"); return 0; } @@ -656,7 +685,7 @@ static struct eth_driver rte_igb_pmd = { { .name = "rte_igb_pmd", .id_table = pci_id_igb_map, - .drv_flags = RTE_PCI_DRV_NEED_MAPPING, + .drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC, }, .eth_dev_init = eth_igb_dev_init, .dev_private_size = sizeof(struct e1000_adapter), @@ -701,7 +730,7 @@ igb_vmdq_vlan_hw_filter_enable(struct rte_eth_dev *dev) static int rte_igbvf_pmd_init(const char *name __rte_unused, const char *params __rte_unused) { - DEBUGFUNC("rte_igbvf_pmd_init"); + PMD_INIT_FUNC_TRACE(); rte_eth_driver_register(&rte_igbvf_pmd); return (0); @@ -713,11 +742,9 @@ eth_igb_configure(struct rte_eth_dev *dev) struct e1000_interrupt *intr = E1000_DEV_PRIVATE_TO_INTR(dev->data->dev_private); - PMD_INIT_LOG(DEBUG, ">>"); - + PMD_INIT_FUNC_TRACE(); intr->flags |= E1000_FLAG_NEED_LINK_UPDATE; - - PMD_INIT_LOG(DEBUG, "<<"); + PMD_INIT_FUNC_TRACE(); return (0); } @@ -730,7 +757,7 @@ eth_igb_start(struct rte_eth_dev *dev) int ret, i, mask; uint32_t ctrl_ext; - PMD_INIT_LOG(DEBUG, ">>"); + PMD_INIT_FUNC_TRACE(); /* Power up the phy. Needed to make the link go Up */ e1000_power_up_phy(hw); @@ -812,7 +839,8 @@ eth_igb_start(struct rte_eth_dev *dev) * value of Write-Back Threshold registers. */ if ((hw->mac.type == e1000_82576) || (hw->mac.type == e1000_82580) || - (hw->mac.type == e1000_i350) || (hw->mac.type == e1000_i210)) { + (hw->mac.type == e1000_i350) || (hw->mac.type == e1000_i210) || + (hw->mac.type == e1000_i211)) { uint32_t ivar; /* Enable all RX & TX queues in the IVAR registers */ @@ -881,9 +909,9 @@ eth_igb_start(struct rte_eth_dev *dev) return (0); error_invalid_config: - PMD_INIT_LOG(ERR, "Invalid link_speed/link_duplex (%u/%u) for port %u\n", - dev->data->dev_conf.link_speed, - dev->data->dev_conf.link_duplex, dev->data->port_id); + PMD_INIT_LOG(ERR, "Invalid link_speed/link_duplex (%u/%u) for port %u", + dev->data->dev_conf.link_speed, + dev->data->dev_conf.link_duplex, dev->data->port_id); igb_dev_clear_queues(dev); return (-EINVAL); } @@ -960,7 +988,7 @@ igb_get_rx_buffer_size(struct e1000_hw *hw) rx_buf_size = (E1000_READ_REG(hw, E1000_RXPBS) & 0xf); rx_buf_size = (uint32_t) e1000_rxpbs_adjust_82580(rx_buf_size); rx_buf_size = (rx_buf_size << 10); - } else if (hw->mac.type == e1000_i210) { + } else if (hw->mac.type == e1000_i210 || hw->mac.type == e1000_i211) { rx_buf_size = (E1000_READ_REG(hw, E1000_RXPBS) & 0x3f) << 10; } else { rx_buf_size = (E1000_READ_REG(hw, E1000_PBA) & 0xffff) << 10; @@ -1222,7 +1250,6 @@ eth_igbvf_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *rte_stats) if (rte_stats == NULL) return; - memset(rte_stats, 0, sizeof(*rte_stats)); rte_stats->ipackets = hw_stats->gprc; rte_stats->ibytes = hw_stats->gorc; rte_stats->opackets = hw_stats->gptc; @@ -1251,8 +1278,7 @@ eth_igbvf_stats_reset(struct rte_eth_dev *dev) } static void -eth_igb_infos_get(struct rte_eth_dev *dev, - struct rte_eth_dev_info *dev_info) +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); @@ -1282,18 +1308,21 @@ eth_igb_infos_get(struct rte_eth_dev *dev, dev_info->max_rx_queues = 16; dev_info->max_tx_queues = 16; dev_info->max_vmdq_pools = ETH_8_POOLS; + dev_info->vmdq_queue_num = 16; break; case e1000_82580: dev_info->max_rx_queues = 8; dev_info->max_tx_queues = 8; dev_info->max_vmdq_pools = ETH_8_POOLS; + dev_info->vmdq_queue_num = 8; break; case e1000_i350: dev_info->max_rx_queues = 8; dev_info->max_tx_queues = 8; dev_info->max_vmdq_pools = ETH_8_POOLS; + dev_info->vmdq_queue_num = 8; break; case e1000_i354: @@ -1307,24 +1336,87 @@ eth_igb_infos_get(struct rte_eth_dev *dev, dev_info->max_vmdq_pools = 0; break; - case e1000_vfadapt: + case e1000_i211: dev_info->max_rx_queues = 2; dev_info->max_tx_queues = 2; dev_info->max_vmdq_pools = 0; break; + default: + /* Should not happen */ + break; + } + dev_info->reta_size = ETH_RSS_RETA_SIZE_128; + + dev_info->default_rxconf = (struct rte_eth_rxconf) { + .rx_thresh = { + .pthresh = IGB_DEFAULT_RX_PTHRESH, + .hthresh = IGB_DEFAULT_RX_HTHRESH, + .wthresh = IGB_DEFAULT_RX_WTHRESH, + }, + .rx_free_thresh = IGB_DEFAULT_RX_FREE_THRESH, + .rx_drop_en = 0, + }; + + dev_info->default_txconf = (struct rte_eth_txconf) { + .tx_thresh = { + .pthresh = IGB_DEFAULT_TX_PTHRESH, + .hthresh = IGB_DEFAULT_TX_HTHRESH, + .wthresh = IGB_DEFAULT_TX_WTHRESH, + }, + .txq_flags = 0, + }; +} + +static void +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->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; + switch (hw->mac.type) { + case e1000_vfadapt: + dev_info->max_rx_queues = 2; + dev_info->max_tx_queues = 2; + break; case e1000_vfadapt_i350: dev_info->max_rx_queues = 1; dev_info->max_tx_queues = 1; - dev_info->max_vmdq_pools = 0; break; - default: /* Should not happen */ - dev_info->max_rx_queues = 0; - dev_info->max_tx_queues = 0; - dev_info->max_vmdq_pools = 0; + break; } + + dev_info->default_rxconf = (struct rte_eth_rxconf) { + .rx_thresh = { + .pthresh = IGB_DEFAULT_RX_PTHRESH, + .hthresh = IGB_DEFAULT_RX_HTHRESH, + .wthresh = IGB_DEFAULT_RX_WTHRESH, + }, + .rx_free_thresh = IGB_DEFAULT_RX_FREE_THRESH, + .rx_drop_en = 0, + }; + + dev_info->default_txconf = (struct rte_eth_txconf) { + .tx_thresh = { + .pthresh = IGB_DEFAULT_TX_PTHRESH, + .hthresh = IGB_DEFAULT_TX_HTHRESH, + .wthresh = IGB_DEFAULT_TX_WTHRESH, + }, + .txq_flags = 0, + }; } /* return 0 means link status changed, -1 means not changed */ @@ -1783,19 +1875,20 @@ eth_igb_interrupt_action(struct rte_eth_dev *dev) rte_igb_dev_atomic_read_link_status(dev, &link); if (link.link_status) { PMD_INIT_LOG(INFO, - " Port %d: Link Up - speed %u Mbps - %s\n", - dev->data->port_id, (unsigned)link.link_speed, - link.link_duplex == ETH_LINK_FULL_DUPLEX ? - "full-duplex" : "half-duplex"); + " Port %d: Link Up - speed %u Mbps - %s", + dev->data->port_id, + (unsigned)link.link_speed, + link.link_duplex == ETH_LINK_FULL_DUPLEX ? + "full-duplex" : "half-duplex"); } else { - PMD_INIT_LOG(INFO, " Port %d: Link Down\n", - dev->data->port_id); + PMD_INIT_LOG(INFO, " Port %d: Link Down", + dev->data->port_id); } PMD_INIT_LOG(INFO, "PCI Address: %04d:%02d:%02d:%d", - dev->pci_dev->addr.domain, - dev->pci_dev->addr.bus, - dev->pci_dev->addr.devid, - dev->pci_dev->addr.function); + dev->pci_dev->addr.domain, + dev->pci_dev->addr.bus, + dev->pci_dev->addr.devid, + dev->pci_dev->addr.function); tctl = E1000_READ_REG(hw, E1000_TCTL); rctl = E1000_READ_REG(hw, E1000_RCTL); if (link.link_status) { @@ -1855,6 +1948,48 @@ eth_igb_led_off(struct rte_eth_dev *dev) return (e1000_led_off(hw) == E1000_SUCCESS ? 0 : -ENOTSUP); } +static int +eth_igb_flow_ctrl_get(struct rte_eth_dev *dev, struct rte_eth_fc_conf *fc_conf) +{ + struct e1000_hw *hw; + uint32_t ctrl; + int tx_pause; + int rx_pause; + + hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); + fc_conf->pause_time = hw->fc.pause_time; + fc_conf->high_water = hw->fc.high_water; + fc_conf->low_water = hw->fc.low_water; + fc_conf->send_xon = hw->fc.send_xon; + fc_conf->autoneg = hw->mac.autoneg; + + /* + * Return rx_pause and tx_pause status according to actual setting of + * the TFCE and RFCE bits in the CTRL register. + */ + ctrl = E1000_READ_REG(hw, E1000_CTRL); + if (ctrl & E1000_CTRL_TFCE) + tx_pause = 1; + else + tx_pause = 0; + + if (ctrl & E1000_CTRL_RFCE) + rx_pause = 1; + else + rx_pause = 0; + + if (rx_pause && tx_pause) + fc_conf->mode = RTE_FC_FULL; + else if (rx_pause) + fc_conf->mode = RTE_FC_RX_PAUSE; + else if (tx_pause) + fc_conf->mode = RTE_FC_TX_PAUSE; + else + fc_conf->mode = RTE_FC_NONE; + + return 0; +} + static int eth_igb_flow_ctrl_set(struct rte_eth_dev *dev, struct rte_eth_fc_conf *fc_conf) { @@ -1871,15 +2006,17 @@ eth_igb_flow_ctrl_set(struct rte_eth_dev *dev, struct rte_eth_fc_conf *fc_conf) uint32_t rctl; hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); + if (fc_conf->autoneg != hw->mac.autoneg) + return -ENOTSUP; rx_buf_size = igb_get_rx_buffer_size(hw); - PMD_INIT_LOG(DEBUG, "Rx packet buffer size = 0x%x \n", rx_buf_size); + PMD_INIT_LOG(DEBUG, "Rx packet buffer size = 0x%x", rx_buf_size); /* At least reserve one Ethernet frame for watermark */ max_high_water = rx_buf_size - ETHER_MAX_LEN; if ((fc_conf->high_water > max_high_water) || - (fc_conf->high_water < fc_conf->low_water)) { - PMD_INIT_LOG(ERR, "e1000 incorrect high/low water value \n"); - PMD_INIT_LOG(ERR, "high water must <= 0x%x \n", max_high_water); + (fc_conf->high_water < fc_conf->low_water)) { + PMD_INIT_LOG(ERR, "e1000 incorrect high/low water value"); + PMD_INIT_LOG(ERR, "high water must <= 0x%x", max_high_water); return (-EINVAL); } @@ -1909,7 +2046,7 @@ eth_igb_flow_ctrl_set(struct rte_eth_dev *dev, struct rte_eth_fc_conf *fc_conf) return 0; } - PMD_INIT_LOG(ERR, "e1000_setup_link_generic = 0x%x \n", err); + PMD_INIT_LOG(ERR, "e1000_setup_link_generic = 0x%x", err); return (-EIO); } @@ -1944,7 +2081,7 @@ eth_igb_rar_clear(struct rte_eth_dev *dev, uint32_t index) static void igbvf_intr_disable(struct e1000_hw *hw) { - PMD_INIT_LOG(DEBUG, "igbvf_intr_disable"); + PMD_INIT_FUNC_TRACE(); /* Clear interrupt mask to stop from interrupts being generated */ E1000_WRITE_REG(hw, E1000_EIMC, 0xFFFF); @@ -1961,7 +2098,7 @@ igbvf_stop_adapter(struct rte_eth_dev *dev) struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); memset(&dev_info, 0, sizeof(dev_info)); - eth_igb_infos_get(dev, &dev_info); + eth_igbvf_infos_get(dev, &dev_info); /* Clear interrupt mask to stop from interrupts being generated */ igbvf_intr_disable(hw); @@ -2026,8 +2163,8 @@ igbvf_dev_configure(struct rte_eth_dev *dev) { struct rte_eth_conf* conf = &dev->data->dev_conf; - PMD_INIT_LOG(DEBUG, "\nConfigured Virtual Function port id: %d\n", - dev->data->port_id); + PMD_INIT_LOG(DEBUG, "Configured Virtual Function port id: %d", + dev->data->port_id); /* * VF has no ability to enable/disable HW CRC @@ -2035,12 +2172,12 @@ igbvf_dev_configure(struct rte_eth_dev *dev) */ #ifndef RTE_LIBRTE_E1000_PF_DISABLE_STRIP_CRC if (!conf->rxmode.hw_strip_crc) { - PMD_INIT_LOG(INFO, "VF can't disable HW CRC Strip\n"); + PMD_INIT_LOG(INFO, "VF can't disable HW CRC Strip"); conf->rxmode.hw_strip_crc = 1; } #else if (conf->rxmode.hw_strip_crc) { - PMD_INIT_LOG(INFO, "VF can't enable HW CRC Strip\n"); + PMD_INIT_LOG(INFO, "VF can't enable HW CRC Strip"); conf->rxmode.hw_strip_crc = 0; } #endif @@ -2055,7 +2192,7 @@ igbvf_dev_start(struct rte_eth_dev *dev) E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); int ret; - PMD_INIT_LOG(DEBUG, "igbvf_dev_start"); + PMD_INIT_FUNC_TRACE(); hw->mac.ops.reset_hw(hw); @@ -2078,7 +2215,7 @@ igbvf_dev_start(struct rte_eth_dev *dev) static void igbvf_dev_stop(struct rte_eth_dev *dev) { - PMD_INIT_LOG(DEBUG, "igbvf_dev_stop"); + PMD_INIT_FUNC_TRACE(); igbvf_stop_adapter(dev); @@ -2096,7 +2233,7 @@ igbvf_dev_close(struct rte_eth_dev *dev) { struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); - PMD_INIT_LOG(DEBUG, "igbvf_dev_close"); + PMD_INIT_FUNC_TRACE(); e1000_reset_hw(hw); @@ -2152,7 +2289,7 @@ igbvf_vlan_filter_set(struct rte_eth_dev *dev, uint16_t vlan_id, int on) uint32_t vid_bit = 0; int ret = 0; - PMD_INIT_LOG(DEBUG, "igbvf_vlan_filter_set"); + PMD_INIT_FUNC_TRACE(); /*vind is not used in VF driver, set to 0, check ixgbe_set_vfta_vf*/ ret = igbvf_set_vfta(hw, vlan_id, !!on); @@ -2174,38 +2311,40 @@ igbvf_vlan_filter_set(struct rte_eth_dev *dev, uint16_t vlan_id, int on) static int eth_igb_rss_reta_update(struct rte_eth_dev *dev, - struct rte_eth_rss_reta *reta_conf) + struct rte_eth_rss_reta_entry64 *reta_conf, + uint16_t reta_size) { - uint8_t i,j,mask; - uint32_t reta; - struct e1000_hw *hw = - E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); + uint8_t i, j, mask; + uint32_t reta, r; + uint16_t idx, shift; + struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); - /* - * Update Redirection Table RETA[n],n=0...31,The redirection table has - * 128-entries in 32 registers - */ - for(i = 0; i < ETH_RSS_RETA_NUM_ENTRIES; i += 4) { - if (i < ETH_RSS_RETA_NUM_ENTRIES/2) - mask = (uint8_t)((reta_conf->mask_lo >> i) & 0xF); + if (reta_size != 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)\n", reta_size, ETH_RSS_RETA_SIZE_128); + return -EINVAL; + } + + for (i = 0; i < reta_size; i += IGB_4_BIT_WIDTH) { + idx = i / RTE_RETA_GROUP_SIZE; + shift = i % RTE_RETA_GROUP_SIZE; + mask = (uint8_t)((reta_conf[idx].mask >> shift) & + IGB_4_BIT_MASK); + if (!mask) + continue; + if (mask == IGB_4_BIT_MASK) + r = 0; else - mask = (uint8_t)((reta_conf->mask_hi >> - (i - ETH_RSS_RETA_NUM_ENTRIES/2)) & 0xF); - if (mask != 0) { - reta = 0; - /* If all 4 entries were set,don't need read RETA register */ - if (mask != 0xF) - reta = E1000_READ_REG(hw,E1000_RETA(i >> 2)); - - for (j = 0; j < 4; j++) { - if (mask & (0x1 << j)) { - if (mask != 0xF) - reta &= ~(0xFF << 8 * j); - reta |= reta_conf->reta[i + j] << 8 * j; - } - } - E1000_WRITE_REG(hw, E1000_RETA(i >> 2),reta); + r = E1000_READ_REG(hw, E1000_RETA(i >> 2)); + for (j = 0, reta = 0; j < IGB_4_BIT_WIDTH; j++) { + if (mask & (0x1 << j)) + reta |= reta_conf[idx].reta[shift + j] << + (CHAR_BIT * j); + else + reta |= r & (IGB_8_BIT_MASK << (CHAR_BIT * j)); } + E1000_WRITE_REG(hw, E1000_RETA(i >> 2), reta); } return 0; @@ -2213,31 +2352,34 @@ eth_igb_rss_reta_update(struct rte_eth_dev *dev, static int eth_igb_rss_reta_query(struct rte_eth_dev *dev, - struct rte_eth_rss_reta *reta_conf) + struct rte_eth_rss_reta_entry64 *reta_conf, + uint16_t reta_size) { - uint8_t i,j,mask; + uint8_t i, j, mask; uint32_t reta; - struct e1000_hw *hw = - E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); + uint16_t idx, shift; + struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); - /* - * Read Redirection Table RETA[n],n=0...31,The redirection table has - * 128-entries in 32 registers - */ - for(i = 0; i < ETH_RSS_RETA_NUM_ENTRIES; i += 4) { - if (i < ETH_RSS_RETA_NUM_ENTRIES/2) - mask = (uint8_t)((reta_conf->mask_lo >> i) & 0xF); - else - mask = (uint8_t)((reta_conf->mask_hi >> - (i - ETH_RSS_RETA_NUM_ENTRIES/2)) & 0xF); - - if (mask != 0) { - reta = E1000_READ_REG(hw,E1000_RETA(i >> 2)); - for (j = 0; j < 4; j++) { - if (mask & (0x1 << j)) - reta_conf->reta[i + j] = - (uint8_t)((reta >> 8 * j) & 0xFF); - } + if (reta_size != 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)\n", reta_size, ETH_RSS_RETA_SIZE_128); + return -EINVAL; + } + + for (i = 0; i < reta_size; i += IGB_4_BIT_WIDTH) { + idx = i / RTE_RETA_GROUP_SIZE; + shift = i % RTE_RETA_GROUP_SIZE; + mask = (uint8_t)((reta_conf[idx].mask >> shift) & + IGB_4_BIT_MASK); + if (!mask) + continue; + reta = E1000_READ_REG(hw, E1000_RETA(i >> 2)); + for (j = 0; j < IGB_4_BIT_WIDTH; j++) { + if (mask & (0x1 << j)) + reta_conf[idx].reta[shift + j] = + ((reta >> (CHAR_BIT * j)) & + IGB_8_BIT_MASK); } } @@ -2247,7 +2389,7 @@ eth_igb_rss_reta_query(struct rte_eth_dev *dev, #define MAC_TYPE_FILTER_SUP(type) do {\ if ((type) != e1000_82580 && (type) != e1000_i350 &&\ (type) != e1000_82576)\ - return -ENOSYS;\ + return -ENOTSUP;\ } while (0) /* @@ -2344,111 +2486,6 @@ eth_igb_get_syn_filter(struct rte_eth_dev *dev, return -ENOENT; } -/* - * add an ethertype filter - * - * @param - * dev: Pointer to struct rte_eth_dev. - * index: the index the filter allocates. - * filter: ponter to the filter that will be added. - * rx_queue: the queue id the filter assigned to. - * - * @return - * - On success, zero. - * - On failure, a negative value. - */ -static int -eth_igb_add_ethertype_filter(struct rte_eth_dev *dev, uint16_t index, - struct rte_ethertype_filter *filter, uint16_t rx_queue) -{ - struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); - uint32_t etqf; - - MAC_TYPE_FILTER_SUP(hw->mac.type); - - if (index >= E1000_MAX_ETQF_FILTERS || rx_queue >= IGB_MAX_RX_QUEUE_NUM) - return -EINVAL; - - etqf = E1000_READ_REG(hw, E1000_ETQF(index)); - if (etqf & E1000_ETQF_FILTER_ENABLE) - return -EINVAL; /* filter index is in use. */ - else - etqf = 0; - - etqf |= E1000_ETQF_FILTER_ENABLE | E1000_ETQF_QUEUE_ENABLE; - etqf |= (uint32_t)(filter->ethertype & E1000_ETQF_ETHERTYPE); - etqf |= rx_queue << E1000_ETQF_QUEUE_SHIFT; - - if (filter->priority_en) { - PMD_INIT_LOG(ERR, "vlan and priority (%d) is not supported" - " in E1000.", filter->priority); - return -EINVAL; - } - - E1000_WRITE_REG(hw, E1000_ETQF(index), etqf); - return 0; -} - -/* - * remove an ethertype filter - * - * @param - * dev: Pointer to struct rte_eth_dev. - * index: the index the filter allocates. - * - * @return - * - On success, zero. - * - On failure, a negative value. - */ -static int -eth_igb_remove_ethertype_filter(struct rte_eth_dev *dev, uint16_t index) -{ - struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); - - MAC_TYPE_FILTER_SUP(hw->mac.type); - - if (index >= E1000_MAX_ETQF_FILTERS) - return -EINVAL; - - E1000_WRITE_REG(hw, E1000_ETQF(index), 0); - return 0; -} - -/* - * get an ethertype filter - * - * @param - * dev: Pointer to struct rte_eth_dev. - * index: the index the filter allocates. - * filter: ponter to the filter that will be gotten. - * *rx_queue: the ponited of the queue id the filter assigned to. - * - * @return - * - On success, zero. - * - On failure, a negative value. - */ -static int -eth_igb_get_ethertype_filter(struct rte_eth_dev *dev, uint16_t index, - struct rte_ethertype_filter *filter, uint16_t *rx_queue) -{ - struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); - uint32_t etqf; - - MAC_TYPE_FILTER_SUP(hw->mac.type); - - if (index >= E1000_MAX_ETQF_FILTERS) - return -EINVAL; - - etqf = E1000_READ_REG(hw, E1000_ETQF(index)); - if (etqf & E1000_ETQF_FILTER_ENABLE) { - filter->ethertype = etqf & E1000_ETQF_ETHERTYPE; - filter->priority_en = 0; - *rx_queue = (etqf & E1000_ETQF_QUEUE) >> E1000_ETQF_QUEUE_SHIFT; - return 0; - } - return -ENOENT; -} - #define MAC_TYPE_FILTER_SUP_EXT(type) do {\ if ((type) != e1000_82580 && (type) != e1000_i350)\ return -ENOSYS; \ @@ -2958,6 +2995,257 @@ eth_igb_get_5tuple_filter(struct rte_eth_dev *dev, uint16_t index, return -ENOENT; } +static int +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); + + hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); + +#ifdef RTE_LIBRTE_82571_SUPPORT + /* XXX: not bigger than max_rx_pktlen */ + if (hw->mac.type == e1000_82571) + return -ENOTSUP; +#endif + eth_igb_infos_get(dev, &dev_info); + + /* check that mtu is within the allowed range */ + if ((mtu < ETHER_MIN_MTU) || + (frame_size > dev_info.max_rx_pktlen)) + return -EINVAL; + + /* refuse mtu that requires the support of scattered packets when this + * feature has not been enabled before. */ + if (!dev->data->scattered_rx && + frame_size > dev->data->min_rx_buf_size - RTE_PKTMBUF_HEADROOM) + return -EINVAL; + + rctl = E1000_READ_REG(hw, E1000_RCTL); + + /* switch to jumbo mode if needed */ + if (frame_size > ETHER_MAX_LEN) { + dev->data->dev_conf.rxmode.jumbo_frame = 1; + rctl |= E1000_RCTL_LPE; + } else { + dev->data->dev_conf.rxmode.jumbo_frame = 0; + rctl &= ~E1000_RCTL_LPE; + } + E1000_WRITE_REG(hw, E1000_RCTL, rctl); + + /* update max frame size */ + dev->data->dev_conf.rxmode.max_rx_pkt_len = frame_size; + + E1000_WRITE_REG(hw, E1000_RLPML, + dev->data->dev_conf.rxmode.max_rx_pkt_len); + + return 0; +} + +static inline int +igb_ethertype_filter_lookup(struct e1000_filter_info *filter_info, + uint16_t ethertype) +{ + int i; + + for (i = 0; i < E1000_MAX_ETQF_FILTERS; i++) { + if (filter_info->ethertype_filters[i] == ethertype && + (filter_info->ethertype_mask & (1 << i))) + return i; + } + return -1; +} + +static inline int +igb_ethertype_filter_insert(struct e1000_filter_info *filter_info, + uint16_t ethertype) +{ + int i; + + for (i = 0; i < E1000_MAX_ETQF_FILTERS; i++) { + if (!(filter_info->ethertype_mask & (1 << i))) { + filter_info->ethertype_mask |= 1 << i; + filter_info->ethertype_filters[i] = ethertype; + return i; + } + } + return -1; +} + +static inline int +igb_ethertype_filter_remove(struct e1000_filter_info *filter_info, + uint8_t idx) +{ + if (idx >= E1000_MAX_ETQF_FILTERS) + return -1; + filter_info->ethertype_mask &= ~(1 << idx); + filter_info->ethertype_filters[idx] = 0; + return idx; +} + + +static int +igb_add_del_ethertype_filter(struct rte_eth_dev *dev, + struct rte_eth_ethertype_filter *filter, + bool add) +{ + struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); + struct e1000_filter_info *filter_info = + E1000_DEV_PRIVATE_TO_FILTER_INFO(dev->data->dev_private); + uint32_t etqf = 0; + int ret; + + if (filter->ether_type == ETHER_TYPE_IPv4 || + filter->ether_type == ETHER_TYPE_IPv6) { + PMD_DRV_LOG(ERR, "unsupported ether_type(0x%04x) in" + " ethertype filter.", filter->ether_type); + return -EINVAL; + } + + if (filter->flags & RTE_ETHTYPE_FLAGS_MAC) { + PMD_DRV_LOG(ERR, "mac compare is unsupported."); + return -EINVAL; + } + if (filter->flags & RTE_ETHTYPE_FLAGS_DROP) { + PMD_DRV_LOG(ERR, "drop option is unsupported."); + return -EINVAL; + } + + ret = igb_ethertype_filter_lookup(filter_info, filter->ether_type); + if (ret >= 0 && add) { + PMD_DRV_LOG(ERR, "ethertype (0x%04x) filter exists.", + filter->ether_type); + return -EEXIST; + } + if (ret < 0 && !add) { + PMD_DRV_LOG(ERR, "ethertype (0x%04x) filter doesn't exist.", + filter->ether_type); + return -ENOENT; + } + + if (add) { + ret = igb_ethertype_filter_insert(filter_info, + filter->ether_type); + if (ret < 0) { + PMD_DRV_LOG(ERR, "ethertype filters are full."); + return -ENOSYS; + } + + etqf |= E1000_ETQF_FILTER_ENABLE | E1000_ETQF_QUEUE_ENABLE; + etqf |= (uint32_t)(filter->ether_type & E1000_ETQF_ETHERTYPE); + etqf |= filter->queue << E1000_ETQF_QUEUE_SHIFT; + } else { + ret = igb_ethertype_filter_remove(filter_info, (uint8_t)ret); + if (ret < 0) + return -ENOSYS; + } + E1000_WRITE_REG(hw, E1000_ETQF(ret), etqf); + E1000_WRITE_FLUSH(hw); + + return 0; +} + +static int +igb_get_ethertype_filter(struct rte_eth_dev *dev, + struct rte_eth_ethertype_filter *filter) +{ + struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); + struct e1000_filter_info *filter_info = + E1000_DEV_PRIVATE_TO_FILTER_INFO(dev->data->dev_private); + uint32_t etqf; + int ret; + + ret = igb_ethertype_filter_lookup(filter_info, filter->ether_type); + if (ret < 0) { + PMD_DRV_LOG(ERR, "ethertype (0x%04x) filter doesn't exist.", + filter->ether_type); + return -ENOENT; + } + + etqf = E1000_READ_REG(hw, E1000_ETQF(ret)); + if (etqf & E1000_ETQF_FILTER_ENABLE) { + filter->ether_type = etqf & E1000_ETQF_ETHERTYPE; + filter->flags = 0; + filter->queue = (etqf & E1000_ETQF_QUEUE) >> + E1000_ETQF_QUEUE_SHIFT; + return 0; + } + + return -ENOENT; +} + +/* + * igb_ethertype_filter_handle - Handle operations for ethertype filter. + * @dev: pointer to rte_eth_dev structure + * @filter_op:operation will be taken. + * @arg: a pointer to specific structure corresponding to the filter_op + */ +static int +igb_ethertype_filter_handle(struct rte_eth_dev *dev, + enum rte_filter_op filter_op, + void *arg) +{ + struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); + int ret; + + MAC_TYPE_FILTER_SUP(hw->mac.type); + + if (filter_op == RTE_ETH_FILTER_NOP) + return 0; + + if (arg == NULL) { + PMD_DRV_LOG(ERR, "arg shouldn't be NULL for operation %u.", + filter_op); + return -EINVAL; + } + + switch (filter_op) { + case RTE_ETH_FILTER_ADD: + ret = igb_add_del_ethertype_filter(dev, + (struct rte_eth_ethertype_filter *)arg, + TRUE); + break; + case RTE_ETH_FILTER_DELETE: + ret = igb_add_del_ethertype_filter(dev, + (struct rte_eth_ethertype_filter *)arg, + FALSE); + break; + case RTE_ETH_FILTER_GET: + ret = igb_get_ethertype_filter(dev, + (struct rte_eth_ethertype_filter *)arg); + break; + default: + PMD_DRV_LOG(ERR, "unsupported operation %u.", filter_op); + ret = -EINVAL; + break; + } + return ret; +} + +static int +eth_igb_filter_ctrl(struct rte_eth_dev *dev, + enum rte_filter_type filter_type, + enum rte_filter_op filter_op, + void *arg) +{ + int ret = -EINVAL; + + switch (filter_type) { + case RTE_ETH_FILTER_ETHERTYPE: + ret = igb_ethertype_filter_handle(dev, filter_op, arg); + break; + default: + PMD_DRV_LOG(WARNING, "Filter type (%d) not supported", + filter_type); + break; + } + + return ret; +} + static struct rte_driver pmd_igb_drv = { .type = PMD_PDEV, .init = rte_igb_pmd_init,