net/liquidio: add Tx data path for single segment
authorShijith Thotton <shijith.thotton@caviumnetworks.com>
Sat, 25 Mar 2017 06:24:38 +0000 (11:54 +0530)
committerFerruh Yigit <ferruh.yigit@intel.com>
Tue, 4 Apr 2017 16:59:49 +0000 (18:59 +0200)
Signed-off-by: Shijith Thotton <shijith.thotton@caviumnetworks.com>
Signed-off-by: Jerin Jacob <jerin.jacob@caviumnetworks.com>
Signed-off-by: Derek Chickles <derek.chickles@caviumnetworks.com>
Signed-off-by: Venkat Koppula <venkat.koppula@caviumnetworks.com>
Signed-off-by: Srisivasubramanian S <ssrinivasan@caviumnetworks.com>
Signed-off-by: Mallesham Jatharakonda <mjatharakonda@oneconvergence.com>
drivers/net/liquidio/base/lio_hw_defs.h
drivers/net/liquidio/lio_ethdev.c
drivers/net/liquidio/lio_rxtx.c
drivers/net/liquidio/lio_rxtx.h

index 2db7085..1c1ad8e 100644 (file)
@@ -108,6 +108,7 @@ enum octeon_tag_type {
 
 /* pre-defined host->NIC tag values */
 #define LIO_CONTROL    (0x11111110)
+#define LIO_DATA(i)    (0x11111111 + (i))
 
 /* used for NIC operations */
 #define LIO_OPCODE     1
index b2e7a29..5c5aade 100644 (file)
@@ -529,6 +529,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;
 }
@@ -542,6 +543,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)
@@ -577,6 +579,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;
        }
 
index 63d8896..14113e1 100644 (file)
@@ -1384,3 +1384,92 @@ lio_delete_instruction_queue(struct lio_device *lio_dev, int iq_no)
        lio_dev->instr_queue[iq_no] = NULL;
        lio_dev->num_iqs--;
 }
+
+/** Send data packet to the device
+ *  @param lio_dev - lio device pointer
+ *  @param ndata   - control structure with queueing, and buffer information
+ *
+ *  @returns IQ_FAILED if it failed to add to the input queue. IQ_STOP if it the
+ *  queue should be stopped, and LIO_IQ_SEND_OK if it sent okay.
+ */
+static inline int
+lio_send_data_pkt(struct lio_device *lio_dev, struct lio_data_pkt *ndata)
+{
+       return lio_send_command(lio_dev, ndata->q_no, &ndata->cmd,
+                               ndata->buf, ndata->datasize, ndata->reqtype);
+}
+
+uint16_t
+lio_dev_xmit_pkts(void *tx_queue, struct rte_mbuf **pkts, uint16_t nb_pkts)
+{
+       struct lio_instr_queue *txq = tx_queue;
+       union lio_cmd_setup cmdsetup;
+       struct lio_device *lio_dev;
+       struct lio_data_pkt ndata;
+       int i, processed = 0;
+       struct rte_mbuf *m;
+       uint32_t tag = 0;
+       int status = 0;
+       int iq_no;
+
+       lio_dev = txq->lio_dev;
+       iq_no = txq->txpciq.s.q_no;
+
+       if (!lio_dev->linfo.link.s.link_up) {
+               PMD_TX_LOG(lio_dev, ERR, "Transmit failed link_status : %d\n",
+                          lio_dev->linfo.link.s.link_up);
+               goto xmit_failed;
+       }
+
+       for (i = 0; i < nb_pkts; i++) {
+               uint32_t pkt_len = 0;
+
+               m = pkts[i];
+
+               /* Prepare the attributes for the data to be passed to BASE. */
+               memset(&ndata, 0, sizeof(struct lio_data_pkt));
+
+               ndata.buf = m;
+
+               ndata.q_no = iq_no;
+
+               cmdsetup.cmd_setup64 = 0;
+               cmdsetup.s.iq_no = iq_no;
+
+               /* check checksum offload flags to form cmd */
+               if (m->ol_flags & PKT_TX_IP_CKSUM)
+                       cmdsetup.s.ip_csum = 1;
+
+               if ((m->ol_flags & PKT_TX_TCP_CKSUM) ||
+                               (m->ol_flags & PKT_TX_UDP_CKSUM))
+                       cmdsetup.s.transport_csum = 1;
+
+               if (m->nb_segs == 1) {
+                       pkt_len = rte_pktmbuf_data_len(m);
+                       cmdsetup.s.u.datasize = pkt_len;
+                       lio_prepare_pci_cmd(lio_dev, &ndata.cmd,
+                                           &cmdsetup, tag);
+                       ndata.cmd.cmd3.dptr = rte_mbuf_data_dma_addr(m);
+                       ndata.reqtype = LIO_REQTYPE_NORESP_NET;
+               }
+
+               ndata.datasize = pkt_len;
+
+               status = lio_send_data_pkt(lio_dev, &ndata);
+
+               if (unlikely(status == LIO_IQ_SEND_FAILED)) {
+                       PMD_TX_LOG(lio_dev, ERR, "send failed\n");
+                       break;
+               }
+
+               if (unlikely(status == LIO_IQ_SEND_STOP))
+                       PMD_TX_LOG(lio_dev, DEBUG, "iq full\n");
+
+               processed++;
+       }
+
+xmit_failed:
+
+       return processed;
+}
+
index 10bca4c..6813aea 100644 (file)
@@ -249,6 +249,50 @@ union octeon_cmd {
 
 #define OCTEON_CMD_SIZE (sizeof(union octeon_cmd))
 
+/** Structure of data information passed by driver to the BASE
+ *  layer when forwarding data to Octeon device software.
+ */
+struct lio_data_pkt {
+       /** Pointer to information maintained by NIC module for this packet. The
+        *  BASE layer passes this as-is to the driver.
+        */
+       void *buf;
+
+       /** Type of buffer passed in "buf" above. */
+       uint32_t reqtype;
+
+       /** Total data bytes to be transferred in this command. */
+       uint32_t datasize;
+
+       /** Command to be passed to the Octeon device software. */
+       union lio_instr_64B cmd;
+
+       /** Input queue to use to send this command. */
+       uint32_t q_no;
+};
+
+/** Structure passed by driver to BASE layer to prepare a command to send
+ *  network data to Octeon.
+ */
+union lio_cmd_setup {
+       struct {
+               uint32_t iq_no : 8;
+               uint32_t gather : 1;
+               uint32_t timestamp : 1;
+               uint32_t ip_csum : 1;
+               uint32_t transport_csum : 1;
+               uint32_t tnl_csum : 1;
+               uint32_t rsvd : 19;
+
+               union {
+                       uint32_t datasize;
+                       uint32_t gatherptrs;
+               } u;
+       } s;
+
+       uint64_t cmd_setup64;
+};
+
 /* Instruction Header */
 struct octeon_instr_ih3 {
 #if RTE_BYTE_ORDER == RTE_BIG_ENDIAN
@@ -418,6 +462,98 @@ struct octeon_instr_rdp {
 #endif
 };
 
+union octeon_packet_params {
+       uint32_t pkt_params32;
+       struct {
+#if RTE_BYTE_ORDER == RTE_BIG_ENDIAN
+               uint32_t reserved : 24;
+               uint32_t ip_csum : 1; /* Perform IP header checksum(s) */
+               /* Perform Outer transport header checksum */
+               uint32_t transport_csum : 1;
+               /* Find tunnel, and perform transport csum. */
+               uint32_t tnl_csum : 1;
+               uint32_t tsflag : 1;   /* Timestamp this packet */
+               uint32_t ipsec_ops : 4; /* IPsec operation */
+#else
+               uint32_t ipsec_ops : 4;
+               uint32_t tsflag : 1;
+               uint32_t tnl_csum : 1;
+               uint32_t transport_csum : 1;
+               uint32_t ip_csum : 1;
+               uint32_t reserved : 7;
+#endif
+       } s;
+};
+
+/** Utility function to prepare a 64B NIC instruction based on a setup command
+ * @param cmd - pointer to instruction to be filled in.
+ * @param setup - pointer to the setup structure
+ * @param q_no - which queue for back pressure
+ *
+ * Assumes the cmd instruction is pre-allocated, but no fields are filled in.
+ */
+static inline void
+lio_prepare_pci_cmd(struct lio_device *lio_dev,
+                   union lio_instr_64B *cmd,
+                   union lio_cmd_setup *setup,
+                   uint32_t tag)
+{
+       union octeon_packet_params packet_params;
+       struct octeon_instr_pki_ih3 *pki_ih3;
+       struct octeon_instr_irh *irh;
+       struct octeon_instr_ih3 *ih3;
+       int port;
+
+       memset(cmd, 0, sizeof(union lio_instr_64B));
+
+       ih3 = (struct octeon_instr_ih3 *)&cmd->cmd3.ih3;
+       pki_ih3 = (struct octeon_instr_pki_ih3 *)&cmd->cmd3.pki_ih3;
+
+       /* assume that rflag is cleared so therefore front data will only have
+        * irh and ossp[1] and ossp[2] for a total of 24 bytes
+        */
+       ih3->pkind = lio_dev->instr_queue[setup->s.iq_no]->txpciq.s.pkind;
+       /* PKI IH */
+       ih3->fsz = OCTEON_PCI_CMD_O3;
+
+       if (!setup->s.gather) {
+               ih3->dlengsz = setup->s.u.datasize;
+       } else {
+               ih3->gather = 1;
+               ih3->dlengsz = setup->s.u.gatherptrs;
+       }
+
+       pki_ih3->w = 1;
+       pki_ih3->raw = 0;
+       pki_ih3->utag = 0;
+       pki_ih3->utt = 1;
+       pki_ih3->uqpg = lio_dev->instr_queue[setup->s.iq_no]->txpciq.s.use_qpg;
+
+       port = (int)lio_dev->instr_queue[setup->s.iq_no]->txpciq.s.port;
+
+       if (tag)
+               pki_ih3->tag = tag;
+       else
+               pki_ih3->tag = LIO_DATA(port);
+
+       pki_ih3->tagtype = OCTEON_ORDERED_TAG;
+       pki_ih3->qpg = lio_dev->instr_queue[setup->s.iq_no]->txpciq.s.qpg;
+       pki_ih3->pm = 0x0; /* parse from L2 */
+       pki_ih3->sl = 32;  /* sl will be sizeof(pki_ih3) + irh + ossp0 + ossp1*/
+
+       irh = (struct octeon_instr_irh *)&cmd->cmd3.irh;
+
+       irh->opcode = LIO_OPCODE;
+       irh->subcode = LIO_OPCODE_NW_DATA;
+
+       packet_params.pkt_params32 = 0;
+       packet_params.s.ip_csum = setup->s.ip_csum;
+       packet_params.s.transport_csum = setup->s.transport_csum;
+       packet_params.s.tsflag = setup->s.timestamp;
+
+       irh->ossp = packet_params.pkt_params32;
+}
+
 int lio_setup_sc_buffer_pool(struct lio_device *lio_dev);
 void lio_free_sc_buffer_pool(struct lio_device *lio_dev);
 
@@ -554,6 +690,8 @@ void lio_delete_droq_queue(struct lio_device *lio_dev, int oq_no);
 
 int lio_setup_sglists(struct lio_device *lio_dev, int iq_no,
                      int fw_mapped_iq, int num_descs, unsigned int socket_id);
+uint16_t lio_dev_xmit_pkts(void *tx_queue, struct rte_mbuf **pkts,
+                          uint16_t nb_pkts);
 int lio_setup_iq(struct lio_device *lio_dev, int q_index,
                 union octeon_txpciq iq_no, uint32_t num_descs, void *app_ctx,
                 unsigned int socket_id);