X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=drivers%2Fnet%2Figc%2Figc_txrx.c;h=b5489eedd220735da01e5b536ea58f2c66068f3b;hb=902fa8b50d609150f717394ba0c5b72890c66d9b;hp=0bdc3f4a8ceb90f143c577d070973bf6e3f87527;hpb=8938c4e1ee01384d922a4664fe23eed5e64cdb24;p=dpdk.git diff --git a/drivers/net/igc/igc_txrx.c b/drivers/net/igc/igc_txrx.c index 0bdc3f4a8c..b5489eedd2 100644 --- a/drivers/net/igc/igc_txrx.c +++ b/drivers/net/igc/igc_txrx.c @@ -3,8 +3,9 @@ */ #include +#include #include -#include +#include #include #include "igc_logs.h" @@ -836,7 +837,7 @@ static uint8_t default_rss_key[40] = { 0x6A, 0x42, 0xB7, 0x3B, 0xBE, 0xAC, 0x01, 0xFA, }; -static void +void igc_rss_disable(struct rte_eth_dev *dev) { struct igc_hw *hw = IGC_DEV_PRIVATE_HW(dev); @@ -917,6 +918,135 @@ igc_rss_configure(struct rte_eth_dev *dev) igc_hw_rss_hash_set(hw, &rss_conf); } +int +igc_del_rss_filter(struct rte_eth_dev *dev) +{ + struct igc_rss_filter *rss_filter = IGC_DEV_PRIVATE_RSS_FILTER(dev); + + if (rss_filter->enable) { + /* recover default RSS configuration */ + igc_rss_configure(dev); + + /* disable RSS logic and clear filter data */ + igc_rss_disable(dev); + memset(rss_filter, 0, sizeof(*rss_filter)); + return 0; + } + PMD_DRV_LOG(ERR, "filter not exist!"); + return -ENOENT; +} + +/* Initiate the filter structure by the structure of rte_flow_action_rss */ +void +igc_rss_conf_set(struct igc_rss_filter *out, + const struct rte_flow_action_rss *rss) +{ + out->conf.func = rss->func; + out->conf.level = rss->level; + out->conf.types = rss->types; + + if (rss->key_len == sizeof(out->key)) { + memcpy(out->key, rss->key, rss->key_len); + out->conf.key = out->key; + out->conf.key_len = rss->key_len; + } else { + out->conf.key = NULL; + out->conf.key_len = 0; + } + + if (rss->queue_num <= IGC_RSS_RDT_SIZD) { + memcpy(out->queue, rss->queue, + sizeof(*out->queue) * rss->queue_num); + out->conf.queue = out->queue; + out->conf.queue_num = rss->queue_num; + } else { + out->conf.queue = NULL; + out->conf.queue_num = 0; + } +} + +int +igc_add_rss_filter(struct rte_eth_dev *dev, struct igc_rss_filter *rss) +{ + struct rte_eth_rss_conf rss_conf = { + .rss_key = rss->conf.key_len ? + (void *)(uintptr_t)rss->conf.key : NULL, + .rss_key_len = rss->conf.key_len, + .rss_hf = rss->conf.types, + }; + struct igc_hw *hw = IGC_DEV_PRIVATE_HW(dev); + struct igc_rss_filter *rss_filter = IGC_DEV_PRIVATE_RSS_FILTER(dev); + uint32_t i, j; + + /* check RSS type is valid */ + if ((rss_conf.rss_hf & IGC_RSS_OFFLOAD_ALL) == 0) { + PMD_DRV_LOG(ERR, + "RSS type(0x%" PRIx64 ") error!, only 0x%" PRIx64 + " been supported", rss_conf.rss_hf, + (uint64_t)IGC_RSS_OFFLOAD_ALL); + return -EINVAL; + } + + /* check queue count is not zero */ + if (!rss->conf.queue_num) { + PMD_DRV_LOG(ERR, "Queue number should not be 0!"); + return -EINVAL; + } + + /* check queue id is valid */ + for (i = 0; i < rss->conf.queue_num; i++) + if (rss->conf.queue[i] >= dev->data->nb_rx_queues) { + PMD_DRV_LOG(ERR, "Queue id %u is invalid!", + rss->conf.queue[i]); + return -EINVAL; + } + + /* only support one filter */ + if (rss_filter->enable) { + PMD_DRV_LOG(ERR, "Only support one RSS filter!"); + return -ENOTSUP; + } + rss_filter->enable = 1; + + igc_rss_conf_set(rss_filter, &rss->conf); + + /* Fill in redirection table. */ + for (i = 0, j = 0; i < IGC_RSS_RDT_SIZD; i++, j++) { + union igc_rss_reta_reg reta; + uint16_t q_idx, reta_idx; + + if (j == rss->conf.queue_num) + j = 0; + q_idx = rss->conf.queue[j]; + reta_idx = i % sizeof(reta); + reta.bytes[reta_idx] = q_idx; + if (reta_idx == sizeof(reta) - 1) + IGC_WRITE_REG_LE_VALUE(hw, + IGC_RETA(i / sizeof(reta)), reta.dword); + } + + if (rss_conf.rss_key == NULL) + rss_conf.rss_key = default_rss_key; + igc_hw_rss_hash_set(hw, &rss_conf); + return 0; +} + +void +igc_clear_rss_filter(struct rte_eth_dev *dev) +{ + struct igc_rss_filter *rss_filter = IGC_DEV_PRIVATE_RSS_FILTER(dev); + + if (!rss_filter->enable) + return; + + /* recover default RSS configuration */ + igc_rss_configure(dev); + + /* disable RSS logic and clear filter data */ + igc_rss_disable(dev); + memset(rss_filter, 0, sizeof(*rss_filter)); +} + static int igc_dev_mq_rx_configure(struct rte_eth_dev *dev) { @@ -1161,20 +1291,24 @@ igc_rx_init(struct rte_eth_dev *dev) * This needs to be done after enable. */ for (i = 0; i < dev->data->nb_rx_queues; i++) { + uint32_t dvmolr; + rxq = dev->data->rx_queues[i]; IGC_WRITE_REG(hw, IGC_RDH(rxq->reg_idx), 0); - IGC_WRITE_REG(hw, IGC_RDT(rxq->reg_idx), - rxq->nb_rx_desc - 1); + IGC_WRITE_REG(hw, IGC_RDT(rxq->reg_idx), rxq->nb_rx_desc - 1); - /* strip queue vlan offload */ - if (rxq->offloads & DEV_RX_OFFLOAD_VLAN_STRIP) { - uint32_t dvmolr; - dvmolr = IGC_READ_REG(hw, IGC_DVMOLR(rxq->queue_id)); + dvmolr = IGC_READ_REG(hw, IGC_DVMOLR(rxq->reg_idx)); + if (rxq->offloads & DEV_RX_OFFLOAD_VLAN_STRIP) + dvmolr |= IGC_DVMOLR_STRVLAN; + else + dvmolr &= ~IGC_DVMOLR_STRVLAN; - /* If vlan been stripped off, the CRC is meaningless. */ - dvmolr |= IGC_DVMOLR_STRVLAN | IGC_DVMOLR_STRCRC; - IGC_WRITE_REG(hw, IGC_DVMOLR(rxq->reg_idx), dvmolr); - } + if (offloads & DEV_RX_OFFLOAD_KEEP_CRC) + dvmolr &= ~IGC_DVMOLR_STRCRC; + else + dvmolr |= IGC_DVMOLR_STRCRC; + + IGC_WRITE_REG(hw, IGC_DVMOLR(rxq->reg_idx), dvmolr); } return 0; @@ -1305,7 +1439,7 @@ eth_igc_prep_pkts(__rte_unused void *tx_queue, struct rte_mbuf **tx_pkts, return i; } -#ifdef RTE_LIBRTE_ETHDEV_DEBUG +#ifdef RTE_ETHDEV_DEBUG_TX ret = rte_validate_tx_offload(m); if (ret != 0) { rte_errno = -ret; @@ -2137,12 +2271,10 @@ eth_igc_vlan_strip_queue_set(struct rte_eth_dev *dev, reg_val = IGC_READ_REG(hw, IGC_DVMOLR(rx_queue_id)); if (on) { - /* If vlan been stripped off, the CRC is meaningless. */ - reg_val |= IGC_DVMOLR_STRVLAN | IGC_DVMOLR_STRCRC; + reg_val |= IGC_DVMOLR_STRVLAN; rxq->offloads |= DEV_RX_OFFLOAD_VLAN_STRIP; } else { - reg_val &= ~(IGC_DVMOLR_STRVLAN | IGC_DVMOLR_HIDVLAN | - IGC_DVMOLR_STRCRC); + reg_val &= ~(IGC_DVMOLR_STRVLAN | IGC_DVMOLR_HIDVLAN); rxq->offloads &= ~DEV_RX_OFFLOAD_VLAN_STRIP; }