net/ixgbe: implement descriptor status API
[dpdk.git] / drivers / net / ixgbe / ixgbe_rxtx.c
index 4d71992..52e5c97 100644 (file)
@@ -1466,17 +1466,19 @@ ixgbe_rx_scan_hw_ring(struct ixgbe_rx_queue *rxq)
        for (i = 0; i < RTE_PMD_IXGBE_RX_MAX_BURST;
             i += LOOK_AHEAD, rxdp += LOOK_AHEAD, rxep += LOOK_AHEAD) {
                /* Read desc statuses backwards to avoid race condition */
-               for (j = LOOK_AHEAD-1; j >= 0; --j)
+               for (j = 0; j < LOOK_AHEAD; j++)
                        s[j] = rte_le_to_cpu_32(rxdp[j].wb.upper.status_error);
 
-               for (j = LOOK_AHEAD - 1; j >= 0; --j)
-                       pkt_info[j] = rte_le_to_cpu_32(rxdp[j].wb.lower.
-                                                      lo_dword.data);
+               rte_smp_rmb();
 
                /* Compute how many status bits were set */
-               nb_dd = 0;
-               for (j = 0; j < LOOK_AHEAD; ++j)
-                       nb_dd += s[j] & IXGBE_RXDADV_STAT_DD;
+               for (nb_dd = 0; nb_dd < LOOK_AHEAD &&
+                               (s[nb_dd] & IXGBE_RXDADV_STAT_DD); nb_dd++)
+                       ;
+
+               for (j = 0; j < nb_dd; j++)
+                       pkt_info[j] = rte_le_to_cpu_32(rxdp[j].wb.lower.
+                                                      lo_dword.data);
 
                nb_rx += nb_dd;
 
@@ -2909,11 +2911,6 @@ ixgbe_dev_rx_queue_count(struct rte_eth_dev *dev, uint16_t rx_queue_id)
        struct ixgbe_rx_queue *rxq;
        uint32_t desc = 0;
 
-       if (rx_queue_id >= dev->data->nb_rx_queues) {
-               PMD_RX_LOG(ERR, "Invalid RX queue id=%d", rx_queue_id);
-               return 0;
-       }
-
        rxq = dev->data->rx_queues[rx_queue_id];
        rxdp = &(rxq->rx_ring[rxq->rx_tail]);
 
@@ -2948,6 +2945,63 @@ ixgbe_dev_rx_descriptor_done(void *rx_queue, uint16_t offset)
                        rte_cpu_to_le_32(IXGBE_RXDADV_STAT_DD));
 }
 
+int
+ixgbe_dev_rx_descriptor_status(void *rx_queue, uint16_t offset)
+{
+       struct ixgbe_rx_queue *rxq = rx_queue;
+       volatile uint32_t *status;
+       uint32_t nb_hold, desc;
+
+       if (unlikely(offset >= rxq->nb_rx_desc))
+               return -EINVAL;
+
+#ifdef RTE_IXGBE_INC_VECTOR
+       if (rxq->rx_using_sse)
+               nb_hold = rxq->rxrearm_nb;
+       else
+#endif
+               nb_hold = rxq->nb_rx_hold;
+       if (offset >= rxq->nb_rx_desc - nb_hold)
+               return RTE_ETH_RX_DESC_UNAVAIL;
+
+       desc = rxq->rx_tail + offset;
+       if (desc >= rxq->nb_rx_desc)
+               desc -= rxq->nb_rx_desc;
+
+       status = &rxq->rx_ring[desc].wb.upper.status_error;
+       if (*status & rte_cpu_to_le_32(IXGBE_RXDADV_STAT_DD))
+               return RTE_ETH_RX_DESC_DONE;
+
+       return RTE_ETH_RX_DESC_AVAIL;
+}
+
+int
+ixgbe_dev_tx_descriptor_status(void *tx_queue, uint16_t offset)
+{
+       struct ixgbe_tx_queue *txq = tx_queue;
+       volatile uint32_t *status;
+       uint32_t desc;
+
+       if (unlikely(offset >= txq->nb_tx_desc))
+               return -EINVAL;
+
+       desc = txq->tx_tail + offset;
+       /* go to next desc that has the RS bit */
+       desc = ((desc + txq->tx_rs_thresh - 1) / txq->tx_rs_thresh) *
+               txq->tx_rs_thresh;
+       if (desc >= txq->nb_tx_desc) {
+               desc -= txq->nb_tx_desc;
+               if (desc >= txq->nb_tx_desc)
+                       desc -= txq->nb_tx_desc;
+       }
+
+       status = &txq->tx_ring[desc].wb.status;
+       if (*status & rte_cpu_to_le_32(IXGBE_ADVTXD_STAT_DD))
+               return RTE_ETH_TX_DESC_DONE;
+
+       return RTE_ETH_TX_DESC_FULL;
+}
+
 void __attribute__((cold))
 ixgbe_dev_clear_queues(struct rte_eth_dev *dev)
 {