net/ena: add stop and uninit routines
[dpdk.git] / drivers / net / ena / ena_ethdev.c
index 190ed40..4ca19c5 100644 (file)
@@ -114,6 +114,12 @@ struct ena_stats {
 #define ENA_STAT_GLOBAL_ENTRY(stat) \
        ENA_STAT_ENTRY(stat, dev)
 
+/*
+ * Each rte_memzone should have unique name.
+ * To satisfy it, count number of allocation and add it to name.
+ */
+uint32_t ena_alloc_cnt;
+
 static const struct ena_stats ena_stats_global_strings[] = {
        ENA_STAT_GLOBAL_ENTRY(tx_timeout),
        ENA_STAT_GLOBAL_ENTRY(io_suspend),
@@ -195,6 +201,8 @@ static const struct rte_pci_id pci_id_ena_map[] = {
        { .device_id = 0 },
 };
 
+static struct ena_aenq_handlers empty_aenq_handlers;
+
 static int ena_device_init(struct ena_com_dev *ena_dev,
                           struct ena_com_dev_get_features_ctx *get_feat_ctx);
 static int ena_dev_configure(struct rte_eth_dev *dev);
@@ -215,6 +223,7 @@ static int ena_populate_rx_queue(struct ena_ring *rxq, unsigned int count);
 static void ena_init_rings(struct ena_adapter *adapter);
 static int ena_mtu_set(struct rte_eth_dev *dev, uint16_t mtu);
 static int ena_start(struct rte_eth_dev *dev);
+static void ena_stop(struct rte_eth_dev *dev);
 static void ena_close(struct rte_eth_dev *dev);
 static int ena_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats);
 static void ena_rx_queue_release_all(struct rte_eth_dev *dev);
@@ -238,6 +247,7 @@ static int ena_rss_reta_query(struct rte_eth_dev *dev,
                              struct rte_eth_rss_reta_entry64 *reta_conf,
                              uint16_t reta_size);
 static int ena_get_sset_count(struct rte_eth_dev *dev, int sset);
+static void ena_interrupt_handler_rte(void *cb_arg);
 
 static const struct eth_dev_ops ena_dev_ops = {
        .dev_configure        = ena_dev_configure,
@@ -245,6 +255,7 @@ static const struct eth_dev_ops ena_dev_ops = {
        .rx_queue_setup       = ena_rx_queue_setup,
        .tx_queue_setup       = ena_tx_queue_setup,
        .dev_start            = ena_start,
+       .dev_stop             = ena_stop,
        .link_update          = ena_link_update,
        .stats_get            = ena_stats_get,
        .mtu_set              = ena_mtu_set,
@@ -346,9 +357,6 @@ static inline void ena_tx_mbuf_prepare(struct rte_mbuf *mbuf,
                ena_meta->mss = mbuf->tso_segsz;
                ena_meta->l3_hdr_len = mbuf->l3_len;
                ena_meta->l3_hdr_offset = mbuf->l2_len;
-               /* this param needed only for TSO */
-               ena_meta->l3_outer_hdr_len = 0;
-               ena_meta->l3_outer_hdr_offset = 0;
 
                ena_tx_ctx->meta_valid = true;
        } else {
@@ -388,7 +396,7 @@ static void ena_config_host_info(struct ena_com_dev *ena_dev)
        rc = ena_com_set_host_attributes(ena_dev);
        if (rc) {
                RTE_LOG(ERR, PMD, "Cannot set host attributes\n");
-               if (rc != -EPERM)
+               if (rc != -ENA_COM_UNSUPPORTED)
                        goto err;
        }
 
@@ -441,7 +449,7 @@ static void ena_config_debug_area(struct ena_adapter *adapter)
        rc = ena_com_set_host_attributes(&adapter->ena_dev);
        if (rc) {
                RTE_LOG(WARNING, PMD, "Cannot set host attributes\n");
-               if (rc != -EPERM)
+               if (rc != -ENA_COM_UNSUPPORTED)
                        goto err;
        }
 
@@ -455,7 +463,8 @@ static void ena_close(struct rte_eth_dev *dev)
        struct ena_adapter *adapter =
                (struct ena_adapter *)(dev->data->dev_private);
 
-       adapter->state = ENA_ADAPTER_STATE_STOPPED;
+       ena_stop(dev);
+       adapter->state = ENA_ADAPTER_STATE_CLOSED;
 
        ena_rx_queue_release_all(dev);
        ena_tx_queue_release_all(dev);
@@ -496,7 +505,7 @@ static int ena_rss_reta_update(struct rte_eth_dev *dev,
                        ret = ena_com_indirect_table_fill_entry(ena_dev,
                                                                i,
                                                                entry_value);
-                       if (unlikely(ret && (ret != ENA_COM_PERMISSION))) {
+                       if (unlikely(ret && (ret != ENA_COM_UNSUPPORTED))) {
                                RTE_LOG(ERR, PMD,
                                        "Cannot fill indirect table\n");
                                ret = -ENOTSUP;
@@ -506,7 +515,7 @@ static int ena_rss_reta_update(struct rte_eth_dev *dev,
        }
 
        ret = ena_com_indirect_table_set(ena_dev);
-       if (unlikely(ret && (ret != ENA_COM_PERMISSION))) {
+       if (unlikely(ret && (ret != ENA_COM_UNSUPPORTED))) {
                RTE_LOG(ERR, PMD, "Cannot flush the indirect table\n");
                ret = -ENOTSUP;
                goto err;
@@ -537,7 +546,7 @@ static int ena_rss_reta_query(struct rte_eth_dev *dev,
                return -EINVAL;
 
        ret = ena_com_indirect_table_get(ena_dev, indirect_table);
-       if (unlikely(ret && (ret != ENA_COM_PERMISSION))) {
+       if (unlikely(ret && (ret != ENA_COM_UNSUPPORTED))) {
                RTE_LOG(ERR, PMD, "cannot get indirect table\n");
                ret = -ENOTSUP;
                goto err;
@@ -571,7 +580,7 @@ static int ena_rss_init_default(struct ena_adapter *adapter)
                val = i % nb_rx_queues;
                rc = ena_com_indirect_table_fill_entry(ena_dev, i,
                                                       ENA_IO_RXQ_IDX(val));
-               if (unlikely(rc && (rc != ENA_COM_PERMISSION))) {
+               if (unlikely(rc && (rc != ENA_COM_UNSUPPORTED))) {
                        RTE_LOG(ERR, PMD, "Cannot fill indirect table\n");
                        goto err_fill_indir;
                }
@@ -579,19 +588,19 @@ static int ena_rss_init_default(struct ena_adapter *adapter)
 
        rc = ena_com_fill_hash_function(ena_dev, ENA_ADMIN_CRC32, NULL,
                                        ENA_HASH_KEY_SIZE, 0xFFFFFFFF);
-       if (unlikely(rc && (rc != ENA_COM_PERMISSION))) {
+       if (unlikely(rc && (rc != ENA_COM_UNSUPPORTED))) {
                RTE_LOG(INFO, PMD, "Cannot fill hash function\n");
                goto err_fill_indir;
        }
 
        rc = ena_com_set_default_hash_ctrl(ena_dev);
-       if (unlikely(rc && (rc != ENA_COM_PERMISSION))) {
+       if (unlikely(rc && (rc != ENA_COM_UNSUPPORTED))) {
                RTE_LOG(INFO, PMD, "Cannot fill hash control\n");
                goto err_fill_indir;
        }
 
        rc = ena_com_indirect_table_set(ena_dev);
-       if (unlikely(rc && (rc != ENA_COM_PERMISSION))) {
+       if (unlikely(rc && (rc != ENA_COM_UNSUPPORTED))) {
                RTE_LOG(ERR, PMD, "Cannot flush the indirect table\n");
                goto err_fill_indir;
        }
@@ -905,12 +914,6 @@ static int ena_start(struct rte_eth_dev *dev)
                (struct ena_adapter *)(dev->data->dev_private);
        int rc = 0;
 
-       if (!(adapter->state == ENA_ADAPTER_STATE_CONFIG ||
-             adapter->state == ENA_ADAPTER_STATE_STOPPED)) {
-               PMD_INIT_LOG(ERR, "API violation");
-               return -1;
-       }
-
        rc = ena_check_valid_conf(adapter);
        if (rc)
                return rc;
@@ -937,6 +940,14 @@ static int ena_start(struct rte_eth_dev *dev)
        return 0;
 }
 
+static void ena_stop(struct rte_eth_dev *dev)
+{
+       struct ena_adapter *adapter =
+               (struct ena_adapter *)(dev->data->dev_private);
+
+       adapter->state = ENA_ADAPTER_STATE_STOPPED;
+}
+
 static int ena_queue_restart(struct ena_ring *ring)
 {
        int rc, bufs_num;
@@ -1236,7 +1247,7 @@ static int ena_device_init(struct ena_com_dev *ena_dev,
        ena_com_set_mmio_read_mode(ena_dev, readless_supported);
 
        /* reset device */
-       rc = ena_com_dev_reset(ena_dev);
+       rc = ena_com_dev_reset(ena_dev, ENA_REGS_RESET_NORMAL);
        if (rc) {
                RTE_LOG(ERR, PMD, "cannot reset device\n");
                goto err_mmio_read_less;
@@ -1252,7 +1263,7 @@ static int ena_device_init(struct ena_com_dev *ena_dev,
        ena_dev->dma_addr_bits = ena_com_get_dma_width(ena_dev);
 
        /* ENA device administration layer init */
-       rc = ena_com_admin_init(ena_dev, NULL, true);
+       rc = ena_com_admin_init(ena_dev, &empty_aenq_handlers, true);
        if (rc) {
                RTE_LOG(ERR, PMD,
                        "cannot initialize ena admin queue with device\n");
@@ -1286,9 +1297,18 @@ err_mmio_read_less:
        return rc;
 }
 
+static void ena_interrupt_handler_rte(__rte_unused void *cb_arg)
+{
+       struct ena_adapter *adapter = (struct ena_adapter *)cb_arg;
+       struct ena_com_dev *ena_dev = &adapter->ena_dev;
+
+       ena_com_admin_q_comp_intr_handler(ena_dev);
+}
+
 static int eth_ena_dev_init(struct rte_eth_dev *eth_dev)
 {
        struct rte_pci_device *pci_dev;
+       struct rte_intr_handle *intr_handle;
        struct ena_adapter *adapter =
                (struct ena_adapter *)(eth_dev->data->dev_private);
        struct ena_com_dev *ena_dev = &adapter->ena_dev;
@@ -1319,19 +1339,16 @@ static int eth_ena_dev_init(struct rte_eth_dev *eth_dev)
                     pci_dev->addr.devid,
                     pci_dev->addr.function);
 
+       intr_handle = &pci_dev->intr_handle;
+
        adapter->regs = pci_dev->mem_resource[ENA_REGS_BAR].addr;
        adapter->dev_mem_base = pci_dev->mem_resource[ENA_MEM_BAR].addr;
 
-       /* Present ENA_MEM_BAR indicates available LLQ mode.
-        * Use corresponding policy
-        */
-       if (adapter->dev_mem_base)
-               ena_dev->tx_mem_queue_type = ENA_ADMIN_PLACEMENT_POLICY_DEV;
-       else if (adapter->regs)
-               ena_dev->tx_mem_queue_type = ENA_ADMIN_PLACEMENT_POLICY_HOST;
-       else
+       if (!adapter->regs) {
                PMD_INIT_LOG(CRIT, "Failed to access registers BAR(%d)",
                             ENA_REGS_BAR);
+               return -ENXIO;
+       }
 
        ena_dev->reg_bar = adapter->regs;
        ena_dev->dmadev = adapter->pdev;
@@ -1348,22 +1365,8 @@ static int eth_ena_dev_init(struct rte_eth_dev *eth_dev)
                return -1;
        }
 
-       if (ena_dev->tx_mem_queue_type == ENA_ADMIN_PLACEMENT_POLICY_DEV) {
-               if (get_feat_ctx.max_queues.max_llq_num == 0) {
-                       PMD_INIT_LOG(ERR,
-                                    "Trying to use LLQ but llq_num is 0.\n"
-                                    "Fall back into regular queues.");
-                       ena_dev->tx_mem_queue_type =
-                               ENA_ADMIN_PLACEMENT_POLICY_HOST;
-                       adapter->num_queues =
-                               get_feat_ctx.max_queues.max_sq_num;
-               } else {
-                       adapter->num_queues =
-                               get_feat_ctx.max_queues.max_llq_num;
-               }
-       } else {
-               adapter->num_queues = get_feat_ctx.max_queues.max_sq_num;
-       }
+       ena_dev->tx_mem_queue_type = ENA_ADMIN_PLACEMENT_POLICY_HOST;
+       adapter->num_queues = get_feat_ctx.max_queues.max_sq_num;
 
        queue_size = ena_calc_queue_size(ena_dev, &get_feat_ctx);
        if ((queue_size <= 0) || (adapter->num_queues <= 0))
@@ -1397,36 +1400,55 @@ static int eth_ena_dev_init(struct rte_eth_dev *eth_dev)
                return -ENOMEM;
        }
 
+       rte_intr_callback_register(intr_handle,
+                                  ena_interrupt_handler_rte,
+                                  adapter);
+       rte_intr_enable(intr_handle);
+       ena_com_set_admin_polling_mode(ena_dev, false);
+
        adapters_found++;
        adapter->state = ENA_ADAPTER_STATE_INIT;
 
        return 0;
 }
 
+static int eth_ena_dev_uninit(struct rte_eth_dev *eth_dev)
+{
+       struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev);
+       struct rte_intr_handle *intr_handle = &pci_dev->intr_handle;
+       struct ena_adapter *adapter =
+               (struct ena_adapter *)(eth_dev->data->dev_private);
+
+       if (rte_eal_process_type() != RTE_PROC_PRIMARY)
+               return -EPERM;
+
+       if (adapter->state != ENA_ADAPTER_STATE_CLOSED)
+               ena_close(eth_dev);
+
+       eth_dev->dev_ops = NULL;
+       eth_dev->rx_pkt_burst = NULL;
+       eth_dev->tx_pkt_burst = NULL;
+       eth_dev->tx_pkt_prepare = NULL;
+
+       rte_free(adapter->drv_stats);
+       adapter->drv_stats = NULL;
+
+       rte_intr_disable(intr_handle);
+       rte_intr_callback_unregister(intr_handle,
+                                    ena_interrupt_handler_rte,
+                                    adapter);
+
+       adapter->state = ENA_ADAPTER_STATE_FREE;
+
+       return 0;
+}
+
 static int ena_dev_configure(struct rte_eth_dev *dev)
 {
        struct ena_adapter *adapter =
                (struct ena_adapter *)(dev->data->dev_private);
 
-       if (!(adapter->state == ENA_ADAPTER_STATE_INIT ||
-             adapter->state == ENA_ADAPTER_STATE_STOPPED)) {
-               PMD_INIT_LOG(ERR, "Illegal adapter state: %d",
-                            adapter->state);
-               return -1;
-       }
-
-       switch (adapter->state) {
-       case ENA_ADAPTER_STATE_INIT:
-       case ENA_ADAPTER_STATE_STOPPED:
-               adapter->state = ENA_ADAPTER_STATE_CONFIG;
-               break;
-       case ENA_ADAPTER_STATE_CONFIG:
-               RTE_LOG(WARNING, PMD,
-                       "Ivalid driver state while trying to configure device\n");
-               break;
-       default:
-               break;
-       }
+       adapter->state = ENA_ADAPTER_STATE_CONFIG;
 
        adapter->tx_selected_offloads = dev->data->dev_conf.txmode.offloads;
        adapter->rx_selected_offloads = dev->data->dev_conf.rxmode.offloads;
@@ -1829,7 +1851,7 @@ static int eth_ena_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,
 
 static int eth_ena_pci_remove(struct rte_pci_device *pci_dev)
 {
-       return rte_eth_dev_pci_generic_remove(pci_dev, NULL);
+       return rte_eth_dev_pci_generic_remove(pci_dev, eth_ena_dev_uninit);
 }
 
 static struct rte_pci_driver rte_ena_pmd = {
@@ -1854,3 +1876,24 @@ ena_init_log(void)
        if (ena_logtype_driver >= 0)
                rte_log_set_level(ena_logtype_driver, RTE_LOG_NOTICE);
 }
+
+/******************************************************************************
+ ******************************** AENQ Handlers *******************************
+ *****************************************************************************/
+/**
+ * This handler will called for unknown event group or unimplemented handlers
+ **/
+static void unimplemented_aenq_handler(__rte_unused void *data,
+                                      __rte_unused struct ena_admin_aenq_entry *aenq_e)
+{
+       // Unimplemented handler
+}
+
+static struct ena_aenq_handlers empty_aenq_handlers = {
+       .handlers = {
+               [ENA_ADMIN_LINK_CHANGE] = unimplemented_aenq_handler,
+               [ENA_ADMIN_NOTIFICATION] = unimplemented_aenq_handler,
+               [ENA_ADMIN_KEEP_ALIVE] = unimplemented_aenq_handler
+       },
+       .unimplemented_handler = unimplemented_aenq_handler
+};