ethdev: add device flag to bypass auto-filled queue xstats
[dpdk.git] / drivers / net / cxgbe / cxgbe_ethdev.c
index 329b7cb..98d0362 100644 (file)
@@ -318,7 +318,7 @@ int cxgbe_dev_mtu_set(struct rte_eth_dev *eth_dev, uint16_t mtu)
 /*
  * Stop device.
  */
-void cxgbe_dev_close(struct rte_eth_dev *eth_dev)
+int cxgbe_dev_close(struct rte_eth_dev *eth_dev)
 {
        struct port_info *temp_pi, *pi = eth_dev->data->dev_private;
        struct adapter *adapter = pi->adapter;
@@ -326,11 +326,14 @@ void cxgbe_dev_close(struct rte_eth_dev *eth_dev)
 
        CXGBE_FUNC_TRACE();
 
+       if (rte_eal_process_type() != RTE_PROC_PRIMARY)
+               return 0;
+
        if (!(adapter->flags & FULL_INIT_DONE))
-               return;
+               return 0;
 
        if (!pi->viid)
-               return;
+               return 0;
 
        cxgbe_down(pi);
        t4_sge_eth_release_queues(pi);
@@ -343,11 +346,13 @@ void cxgbe_dev_close(struct rte_eth_dev *eth_dev)
        for_each_port(adapter, i) {
                temp_pi = adap2pinfo(adapter, i);
                if (temp_pi->viid)
-                       return;
+                       return 0;
        }
 
        cxgbe_close(adapter);
        rte_free(adapter);
+
+       return 0;
 }
 
 /* Start the device.
@@ -411,7 +416,7 @@ out:
 /*
  * Stop device: disable rx and tx functions to allow for reconfiguring.
  */
-void cxgbe_dev_stop(struct rte_eth_dev *eth_dev)
+int cxgbe_dev_stop(struct rte_eth_dev *eth_dev)
 {
        struct port_info *pi = eth_dev->data->dev_private;
        struct adapter *adapter = pi->adapter;
@@ -419,7 +424,7 @@ void cxgbe_dev_stop(struct rte_eth_dev *eth_dev)
        CXGBE_FUNC_TRACE();
 
        if (!(adapter->flags & FULL_INIT_DONE))
-               return;
+               return 0;
 
        cxgbe_down(pi);
 
@@ -429,6 +434,8 @@ void cxgbe_dev_stop(struct rte_eth_dev *eth_dev)
         */
        t4_sge_eth_clear_queues(pi);
        eth_dev->data->scattered_rx = 0;
+
+       return 0;
 }
 
 int cxgbe_dev_configure(struct rte_eth_dev *eth_dev)
@@ -562,17 +569,16 @@ void cxgbe_dev_tx_queue_release(void *q)
 
 int cxgbe_dev_rx_queue_start(struct rte_eth_dev *eth_dev, uint16_t rx_queue_id)
 {
-       int ret;
        struct port_info *pi = eth_dev->data->dev_private;
        struct adapter *adap = pi->adapter;
-       struct sge_rspq *q;
+       struct sge_eth_rxq *rxq;
+       int ret;
 
        dev_debug(adapter, "%s: pi->port_id = %d; rx_queue_id = %d\n",
                  __func__, pi->port_id, rx_queue_id);
 
-       q = eth_dev->data->rx_queues[rx_queue_id];
-
-       ret = t4_sge_eth_rxq_start(adap, q);
+       rxq = eth_dev->data->rx_queues[rx_queue_id];
+       ret = t4_sge_eth_rxq_start(adap, rxq);
        if (ret == 0)
                eth_dev->data->rx_queue_state[rx_queue_id] = RTE_ETH_QUEUE_STATE_STARTED;
 
@@ -581,16 +587,16 @@ int cxgbe_dev_rx_queue_start(struct rte_eth_dev *eth_dev, uint16_t rx_queue_id)
 
 int cxgbe_dev_rx_queue_stop(struct rte_eth_dev *eth_dev, uint16_t rx_queue_id)
 {
-       int ret;
        struct port_info *pi = eth_dev->data->dev_private;
        struct adapter *adap = pi->adapter;
-       struct sge_rspq *q;
+       struct sge_eth_rxq *rxq;
+       int ret;
 
        dev_debug(adapter, "%s: pi->port_id = %d; rx_queue_id = %d\n",
                  __func__, pi->port_id, rx_queue_id);
 
-       q = eth_dev->data->rx_queues[rx_queue_id];
-       ret = t4_sge_eth_rxq_stop(adap, q);
+       rxq = eth_dev->data->rx_queues[rx_queue_id];
+       ret = t4_sge_eth_rxq_stop(adap, rxq);
        if (ret == 0)
                eth_dev->data->rx_queue_state[rx_queue_id] = RTE_ETH_QUEUE_STATE_STOPPED;
 
@@ -924,6 +930,69 @@ static int cxgbe_dev_rss_hash_conf_get(struct rte_eth_dev *dev,
        return 0;
 }
 
+static int cxgbe_dev_rss_reta_update(struct rte_eth_dev *dev,
+                                    struct rte_eth_rss_reta_entry64 *reta_conf,
+                                    uint16_t reta_size)
+{
+       struct port_info *pi = dev->data->dev_private;
+       struct adapter *adapter = pi->adapter;
+       u16 i, idx, shift, *rss;
+       int ret;
+
+       if (!(adapter->flags & FULL_INIT_DONE))
+               return -ENOMEM;
+
+       if (!reta_size || reta_size > pi->rss_size)
+               return -EINVAL;
+
+       rss = rte_calloc(NULL, pi->rss_size, sizeof(u16), 0);
+       if (!rss)
+               return -ENOMEM;
+
+       rte_memcpy(rss, pi->rss, pi->rss_size * sizeof(u16));
+       for (i = 0; i < reta_size; i++) {
+               idx = i / RTE_RETA_GROUP_SIZE;
+               shift = i % RTE_RETA_GROUP_SIZE;
+               if (!(reta_conf[idx].mask & (1ULL << shift)))
+                       continue;
+
+               rss[i] = reta_conf[idx].reta[shift];
+       }
+
+       ret = cxgbe_write_rss(pi, rss);
+       if (!ret)
+               rte_memcpy(pi->rss, rss, pi->rss_size * sizeof(u16));
+
+       rte_free(rss);
+       return ret;
+}
+
+static int cxgbe_dev_rss_reta_query(struct rte_eth_dev *dev,
+                                   struct rte_eth_rss_reta_entry64 *reta_conf,
+                                   uint16_t reta_size)
+{
+       struct port_info *pi = dev->data->dev_private;
+       struct adapter *adapter = pi->adapter;
+       u16 i, idx, shift;
+
+       if (!(adapter->flags & FULL_INIT_DONE))
+               return -ENOMEM;
+
+       if (!reta_size || reta_size > pi->rss_size)
+               return -EINVAL;
+
+       for (i = 0; i < reta_size; i++) {
+               idx = i / RTE_RETA_GROUP_SIZE;
+               shift = i % RTE_RETA_GROUP_SIZE;
+               if (!(reta_conf[idx].mask & (1ULL << shift)))
+                       continue;
+
+               reta_conf[idx].reta[shift] = pi->rss[i];
+       }
+
+       return 0;
+}
+
 static int cxgbe_get_eeprom_length(struct rte_eth_dev *dev)
 {
        RTE_SET_USED(dev);
@@ -1143,6 +1212,8 @@ static const struct eth_dev_ops cxgbe_eth_dev_ops = {
        .rss_hash_update        = cxgbe_dev_rss_hash_update,
        .rss_hash_conf_get      = cxgbe_dev_rss_hash_conf_get,
        .mac_addr_set           = cxgbe_mac_addr_set,
+       .reta_update            = cxgbe_dev_rss_reta_update,
+       .reta_query             = cxgbe_dev_rss_reta_query,
 };
 
 /*
@@ -1191,6 +1262,8 @@ static int eth_cxgbe_dev_init(struct rte_eth_dev *eth_dev)
                return 0;
        }
 
+       eth_dev->data->dev_flags |= RTE_ETH_DEV_AUTOFILL_QUEUE_XSTATS;
+
        snprintf(name, sizeof(name), "cxgbeadapter%d", eth_dev->data->port_id);
        adapter = rte_zmalloc(name, sizeof(*adapter), 0);
        if (!adapter)
@@ -1227,12 +1300,13 @@ static int eth_cxgbe_dev_uninit(struct rte_eth_dev *eth_dev)
 {
        struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev);
        uint16_t port_id;
+       int err = 0;
 
        /* Free up other ports and all resources */
        RTE_ETH_FOREACH_DEV_OF(port_id, &pci_dev->device)
-               rte_eth_dev_close(port_id);
+               err |= rte_eth_dev_close(port_id);
 
-       return 0;
+       return err == 0 ? 0 : -EIO;
 }
 
 static int eth_cxgbe_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,