net/sfc: support Rx descriptor status API
authorIvan Malov <ivan.malov@oktetlabs.ru>
Wed, 30 Aug 2017 09:08:46 +0000 (10:08 +0100)
committerFerruh Yigit <ferruh.yigit@intel.com>
Fri, 6 Oct 2017 00:49:47 +0000 (02:49 +0200)
Support for the feature is added to EFX Rx datapath

Signed-off-by: Ivan Malov <ivan.malov@oktetlabs.ru>
Signed-off-by: Andrew Rybchenko <arybchenko@solarflare.com>
doc/guides/nics/features/sfc_efx.ini
drivers/net/sfc/sfc_dp_rx.h
drivers/net/sfc/sfc_ef10_rx.c
drivers/net/sfc/sfc_ethdev.c
drivers/net/sfc/sfc_rx.c

index 1db7f67..0a5c143 100644 (file)
@@ -25,6 +25,7 @@ VLAN offload         = P
 L3 checksum offload  = Y
 L4 checksum offload  = Y
 Packet type parsing  = Y
+Rx descriptor status = Y
 Basic stats          = Y
 Extended stats       = Y
 FW version           = Y
index a7b8278..3f6a604 100644 (file)
@@ -155,6 +155,10 @@ typedef const uint32_t * (sfc_dp_rx_supported_ptypes_get_t)(void);
 /** Get number of pending Rx descriptors */
 typedef unsigned int (sfc_dp_rx_qdesc_npending_t)(struct sfc_dp_rxq *dp_rxq);
 
+/** Check Rx descriptor status */
+typedef int (sfc_dp_rx_qdesc_status_t)(struct sfc_dp_rxq *dp_rxq,
+                                      uint16_t offset);
+
 /** Receive datapath definition */
 struct sfc_dp_rx {
        struct sfc_dp                           dp;
@@ -170,6 +174,7 @@ struct sfc_dp_rx {
        sfc_dp_rx_qpurge_t                      *qpurge;
        sfc_dp_rx_supported_ptypes_get_t        *supported_ptypes_get;
        sfc_dp_rx_qdesc_npending_t              *qdesc_npending;
+       sfc_dp_rx_qdesc_status_t                *qdesc_status;
        eth_rx_burst_t                          pkt_burst;
 };
 
index 60812cb..500d652 100644 (file)
@@ -544,6 +544,14 @@ sfc_ef10_rx_qdesc_npending(__rte_unused struct sfc_dp_rxq *dp_rxq)
        return -ENOTSUP;
 }
 
+static sfc_dp_rx_qdesc_status_t sfc_ef10_rx_qdesc_status;
+static int
+sfc_ef10_rx_qdesc_status(__rte_unused struct sfc_dp_rxq *dp_rxq,
+                        __rte_unused uint16_t offset)
+{
+       return -ENOTSUP;
+}
+
 
 static uint64_t
 sfc_ef10_mk_mbuf_rearm_data(uint16_t port_id, uint16_t prefix_size)
@@ -708,5 +716,6 @@ struct sfc_dp_rx sfc_ef10_rx = {
        .qpurge                 = sfc_ef10_rx_qpurge,
        .supported_ptypes_get   = sfc_ef10_supported_ptypes_get,
        .qdesc_npending         = sfc_ef10_rx_qdesc_npending,
+       .qdesc_status           = sfc_ef10_rx_qdesc_status,
        .pkt_burst              = sfc_ef10_recv_pkts,
 };
index 12bcd6f..fe9ca30 100644 (file)
@@ -1086,6 +1086,15 @@ sfc_rx_descriptor_done(void *queue, uint16_t offset)
        return sfc_rx_qdesc_done(dp_rxq, offset);
 }
 
+static int
+sfc_rx_descriptor_status(void *queue, uint16_t offset)
+{
+       struct sfc_dp_rxq *dp_rxq = queue;
+       struct sfc_rxq *rxq = sfc_rxq_by_dp_rxq(dp_rxq);
+
+       return rxq->evq->sa->dp_rx->qdesc_status(dp_rxq, offset);
+}
+
 static int
 sfc_rx_queue_start(struct rte_eth_dev *dev, uint16_t rx_queue_id)
 {
@@ -1469,6 +1478,7 @@ static const struct eth_dev_ops sfc_eth_dev_ops = {
        .rx_queue_release               = sfc_rx_queue_release,
        .rx_queue_count                 = sfc_rx_queue_count,
        .rx_descriptor_done             = sfc_rx_descriptor_done,
+       .rx_descriptor_status           = sfc_rx_descriptor_status,
        .tx_queue_setup                 = sfc_tx_queue_setup,
        .tx_queue_release               = sfc_tx_queue_release,
        .flow_ctrl_get                  = sfc_flow_ctrl_get,
index 364f718..3b17b9a 100644 (file)
@@ -349,6 +349,43 @@ sfc_efx_rx_qdesc_npending(struct sfc_dp_rxq *dp_rxq)
        return rxq->pending - rxq->completed;
 }
 
+static sfc_dp_rx_qdesc_status_t sfc_efx_rx_qdesc_status;
+static int
+sfc_efx_rx_qdesc_status(struct sfc_dp_rxq *dp_rxq, uint16_t offset)
+{
+       struct sfc_efx_rxq *rxq = sfc_efx_rxq_by_dp_rxq(dp_rxq);
+
+       if (unlikely(offset > rxq->ptr_mask))
+               return -EINVAL;
+
+       /*
+        * Poll EvQ to derive up-to-date 'rxq->pending' figure;
+        * it is required for the queue to be running, but the
+        * check is omitted because API design assumes that it
+        * is the duty of the caller to satisfy all conditions
+        */
+       SFC_ASSERT((rxq->flags & SFC_EFX_RXQ_FLAG_RUNNING) ==
+                  SFC_EFX_RXQ_FLAG_RUNNING);
+       sfc_ev_qpoll(rxq->evq);
+
+       /*
+        * There is a handful of reserved entries in the ring,
+        * but an explicit check whether the offset points to
+        * a reserved entry is neglected since the two checks
+        * below rely on the figures which take the HW limits
+        * into account and thus if an entry is reserved, the
+        * checks will fail and UNAVAIL code will be returned
+        */
+
+       if (offset < (rxq->pending - rxq->completed))
+               return RTE_ETH_RX_DESC_DONE;
+
+       if (offset < (rxq->added - rxq->completed))
+               return RTE_ETH_RX_DESC_AVAIL;
+
+       return RTE_ETH_RX_DESC_UNAVAIL;
+}
+
 struct sfc_rxq *
 sfc_rxq_by_dp_rxq(const struct sfc_dp_rxq *dp_rxq)
 {
@@ -498,6 +535,7 @@ struct sfc_dp_rx sfc_efx_rx = {
        .qpurge                 = sfc_efx_rx_qpurge,
        .supported_ptypes_get   = sfc_efx_supported_ptypes_get,
        .qdesc_npending         = sfc_efx_rx_qdesc_npending,
+       .qdesc_status           = sfc_efx_rx_qdesc_status,
        .pkt_burst              = sfc_efx_recv_pkts,
 };