net/liquidio: add API to flush IQ
[dpdk.git] / drivers / net / liquidio / lio_ethdev.c
index ebfdf7a..b8baa4f 100644 (file)
@@ -121,6 +121,101 @@ lio_dev_rx_queue_setup(struct rte_eth_dev *eth_dev, uint16_t q_no,
        return 0;
 }
 
+/**
+ * Release the receive queue/ringbuffer. Called by
+ * the upper layers.
+ *
+ * @param rxq
+ *    Opaque pointer to the receive queue to release
+ *
+ * @return
+ *    - nothing
+ */
+static void
+lio_dev_rx_queue_release(void *rxq)
+{
+       struct lio_droq *droq = rxq;
+       struct lio_device *lio_dev = droq->lio_dev;
+       int oq_no;
+
+       /* Run time queue deletion not supported */
+       if (lio_dev->port_configured)
+               return;
+
+       if (droq != NULL) {
+               oq_no = droq->q_no;
+               lio_delete_droq_queue(droq->lio_dev, oq_no);
+       }
+}
+
+/**
+ * Allocate and initialize SW ring. Initialize associated HW registers.
+ *
+ * @param eth_dev
+ *   Pointer to structure rte_eth_dev
+ *
+ * @param q_no
+ *   Queue number
+ *
+ * @param num_tx_descs
+ *   Number of ringbuffer descriptors
+ *
+ * @param socket_id
+ *   NUMA socket id, used for memory allocations
+ *
+ * @param tx_conf
+ *   Pointer to the structure rte_eth_txconf
+ *
+ * @return
+ *   - On success, return 0
+ *   - On failure, return -errno value
+ */
+static int
+lio_dev_tx_queue_setup(struct rte_eth_dev *eth_dev, uint16_t q_no,
+                      uint16_t num_tx_descs, unsigned int socket_id,
+                      const struct rte_eth_txconf *tx_conf __rte_unused)
+{
+       struct lio_device *lio_dev = LIO_DEV(eth_dev);
+       int fw_mapped_iq = lio_dev->linfo.txpciq[q_no].s.q_no;
+       int retval;
+
+       if (q_no >= lio_dev->nb_tx_queues) {
+               lio_dev_err(lio_dev, "Invalid tx queue number %u\n", q_no);
+               return -EINVAL;
+       }
+
+       lio_dev_dbg(lio_dev, "setting up tx queue %u\n", q_no);
+
+       if ((lio_dev->instr_queue[fw_mapped_iq] != NULL) &&
+           (num_tx_descs != lio_dev->instr_queue[fw_mapped_iq]->max_count)) {
+               lio_dev_err(lio_dev,
+                           "Reconfiguring Tx descs not supported. Configure descs to same value %u or restart application\n",
+                           lio_dev->instr_queue[fw_mapped_iq]->max_count);
+               return -ENOTSUP;
+       }
+
+       retval = lio_setup_iq(lio_dev, q_no, lio_dev->linfo.txpciq[q_no],
+                             num_tx_descs, lio_dev, socket_id);
+
+       if (retval) {
+               lio_dev_err(lio_dev, "Runtime IQ(TxQ) creation failed.\n");
+               return retval;
+       }
+
+       retval = lio_setup_sglists(lio_dev, q_no, fw_mapped_iq,
+                               lio_dev->instr_queue[fw_mapped_iq]->max_count,
+                               socket_id);
+
+       if (retval) {
+               lio_delete_instruction_queue(lio_dev, fw_mapped_iq);
+               return retval;
+       }
+
+       eth_dev->data->tx_queues[q_no] = lio_dev->instr_queue[fw_mapped_iq];
+
+       return 0;
+}
+
 static int lio_dev_configure(struct rte_eth_dev *eth_dev)
 {
        struct lio_device *lio_dev = LIO_DEV(eth_dev);
@@ -186,6 +281,7 @@ static int lio_dev_configure(struct rte_eth_dev *eth_dev)
         * response arrived or timed-out.
         */
        while ((*sc->status_word == LIO_COMPLETION_WORD_INIT) && --timeout) {
+               lio_flush_iq(lio_dev, lio_dev->instr_queue[sc->iq_no]);
                lio_process_ordered_list(lio_dev);
                rte_delay_ms(1);
        }
@@ -248,10 +344,33 @@ static int lio_dev_configure(struct rte_eth_dev *eth_dev)
        /* Copy the permanent MAC address */
        ether_addr_copy((struct ether_addr *)mac, &eth_dev->data->mac_addrs[0]);
 
+       lio_dev->glist_lock =
+           rte_zmalloc(NULL, sizeof(*lio_dev->glist_lock) * num_iqueues, 0);
+       if (lio_dev->glist_lock == NULL)
+               return -ENOMEM;
+
+       lio_dev->glist_head =
+               rte_zmalloc(NULL, sizeof(*lio_dev->glist_head) * num_iqueues,
+                           0);
+       if (lio_dev->glist_head == NULL) {
+               rte_free(lio_dev->glist_lock);
+               lio_dev->glist_lock = NULL;
+               return -ENOMEM;
+       }
+
        lio_dev->port_configured = 1;
 
        lio_free_soft_command(sc);
 
+       /* Disable iq_0 for reconf */
+       lio_dev->fn_list.disable_io_queues(lio_dev);
+
+       /* Reset ioq regs */
+       lio_dev->fn_list.setup_device_regs(lio_dev);
+
+       /* Free iq_0 used during init */
+       lio_free_instr_queue0(lio_dev);
+
        return 0;
 
 nic_config_fail:
@@ -266,6 +385,8 @@ nic_config_fail:
 static const struct eth_dev_ops liovf_eth_dev_ops = {
        .dev_configure          = lio_dev_configure,
        .rx_queue_setup         = lio_dev_rx_queue_setup,
+       .rx_queue_release       = lio_dev_rx_queue_release,
+       .tx_queue_setup         = lio_dev_tx_queue_setup,
 };
 
 static void
@@ -376,6 +497,10 @@ lio_first_time_init(struct lio_device *lio_dev,
        lio_dev->max_tx_queues = dpdk_queues;
        lio_dev->max_rx_queues = dpdk_queues;
 
+       /* Enable input and output queues for this device */
+       if (lio_dev->fn_list.enable_io_queues(lio_dev))
+               goto error;
+
        return 0;
 
 error:
@@ -405,6 +530,7 @@ lio_eth_dev_uninit(struct rte_eth_dev *eth_dev)
        eth_dev->data->mac_addrs = NULL;
 
        eth_dev->rx_pkt_burst = NULL;
+       eth_dev->tx_pkt_burst = NULL;
 
        return 0;
 }
@@ -418,6 +544,7 @@ lio_eth_dev_init(struct rte_eth_dev *eth_dev)
        PMD_INIT_FUNC_TRACE();
 
        eth_dev->rx_pkt_burst = &lio_dev_recv_pkts;
+       eth_dev->tx_pkt_burst = &lio_dev_xmit_pkts;
 
        /* Primary does the initialization. */
        if (rte_eal_process_type() != RTE_PROC_PRIMARY)
@@ -453,6 +580,7 @@ lio_eth_dev_init(struct rte_eth_dev *eth_dev)
                            "MAC addresses memory allocation failed\n");
                eth_dev->dev_ops = NULL;
                eth_dev->rx_pkt_burst = NULL;
+               eth_dev->tx_pkt_burst = NULL;
                return -ENOMEM;
        }