net/cxgbe: support updating RSS hash configuration and key
[dpdk.git] / drivers / net / cxgbe / cxgbe_ethdev.c
index 981dd47..b67dcb7 100644 (file)
 #include <rte_log.h>
 #include <rte_debug.h>
 #include <rte_pci.h>
+#include <rte_bus_pci.h>
 #include <rte_atomic.h>
 #include <rte_branch_prediction.h>
 #include <rte_memory.h>
-#include <rte_memzone.h>
 #include <rte_tailq.h>
 #include <rte_eal.h>
 #include <rte_alarm.h>
 #include <rte_ether.h>
-#include <rte_ethdev.h>
+#include <rte_ethdev_driver.h>
 #include <rte_ethdev_pci.h>
-#include <rte_atomic.h>
 #include <rte_malloc.h>
 #include <rte_random.h>
 #include <rte_dev.h>
@@ -172,6 +171,8 @@ static void cxgbe_dev_info_get(struct rte_eth_dev *eth_dev,
                                       DEV_TX_OFFLOAD_TCP_TSO;
 
        device_info->reta_size = pi->rss_size;
+       device_info->hash_key_size = CXGBE_DEFAULT_RSS_KEY_LEN;
+       device_info->flow_type_rss_offloads = CXGBE_RSS_HF_ALL;
 
        device_info->rx_desc_lim = cxgbe_desc_lim;
        device_info->tx_desc_lim = cxgbe_desc_lim;
@@ -648,7 +649,7 @@ static void cxgbe_dev_rx_queue_release(void *q)
 /*
  * Get port statistics.
  */
-static void cxgbe_dev_stats_get(struct rte_eth_dev *eth_dev,
+static int cxgbe_dev_stats_get(struct rte_eth_dev *eth_dev,
                                struct rte_eth_stats *eth_stats)
 {
        struct port_info *pi = (struct port_info *)(eth_dev->data->dev_private);
@@ -691,6 +692,7 @@ static void cxgbe_dev_stats_get(struct rte_eth_dev *eth_dev,
                eth_stats->q_obytes[i] = txq->stats.tx_bytes;
                eth_stats->q_errors[i] = txq->stats.mapping_err;
        }
+       return 0;
 }
 
 /*
@@ -787,6 +789,36 @@ cxgbe_dev_supported_ptypes_get(struct rte_eth_dev *eth_dev)
        return NULL;
 }
 
+/* Update RSS hash configuration
+ */
+static int cxgbe_dev_rss_hash_update(struct rte_eth_dev *dev,
+                                    struct rte_eth_rss_conf *rss_conf)
+{
+       struct port_info *pi = (struct port_info *)(dev->data->dev_private);
+       struct adapter *adapter = pi->adapter;
+       int err;
+
+       err = cxgbe_write_rss_conf(pi, rss_conf->rss_hf);
+       if (err)
+               return err;
+
+       pi->rss_hf = rss_conf->rss_hf;
+
+       if (rss_conf->rss_key) {
+               u32 key[10], mod_key[10];
+               int i, j;
+
+               memcpy(key, rss_conf->rss_key, CXGBE_DEFAULT_RSS_KEY_LEN);
+
+               for (i = 9, j = 0; i >= 0; i--, j++)
+                       mod_key[j] = cpu_to_be32(key[i]);
+
+               t4_write_rss_key(adapter, mod_key, -1);
+       }
+
+       return 0;
+}
+
 static int cxgbe_get_eeprom_length(struct rte_eth_dev *dev)
 {
        RTE_SET_USED(dev);
@@ -985,6 +1017,7 @@ static const struct eth_dev_ops cxgbe_eth_dev_ops = {
        .get_eeprom             = cxgbe_get_eeprom,
        .set_eeprom             = cxgbe_set_eeprom,
        .get_reg                = cxgbe_get_regs,
+       .rss_hash_update        = cxgbe_dev_rss_hash_update,
 };
 
 /*
@@ -1004,14 +1037,33 @@ static int eth_cxgbe_dev_init(struct rte_eth_dev *eth_dev)
        eth_dev->dev_ops = &cxgbe_eth_dev_ops;
        eth_dev->rx_pkt_burst = &cxgbe_recv_pkts;
        eth_dev->tx_pkt_burst = &cxgbe_xmit_pkts;
+       pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev);
 
-       /* for secondary processes, we don't initialise any further as primary
-        * has already done this work.
+       /* for secondary processes, we attach to ethdevs allocated by primary
+        * and do minimal initialization.
         */
-       if (rte_eal_process_type() != RTE_PROC_PRIMARY)
+       if (rte_eal_process_type() != RTE_PROC_PRIMARY) {
+               int i;
+
+               for (i = 1; i < MAX_NPORTS; i++) {
+                       struct rte_eth_dev *rest_eth_dev;
+                       char namei[RTE_ETH_NAME_MAX_LEN];
+
+                       snprintf(namei, sizeof(namei), "%s_%d",
+                                pci_dev->device.name, i);
+                       rest_eth_dev = rte_eth_dev_attach_secondary(namei);
+                       if (rest_eth_dev) {
+                               rest_eth_dev->device = &pci_dev->device;
+                               rest_eth_dev->dev_ops =
+                                       eth_dev->dev_ops;
+                               rest_eth_dev->rx_pkt_burst =
+                                       eth_dev->rx_pkt_burst;
+                               rest_eth_dev->tx_pkt_burst =
+                                       eth_dev->tx_pkt_burst;
+                       }
+               }
                return 0;
-
-       pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev);
+       }
 
        snprintf(name, sizeof(name), "cxgbeadapter%d", eth_dev->data->port_id);
        adapter = rte_zmalloc(name, sizeof(*adapter), 0);