#include <rte_malloc.h>
#include "bnxt.h"
-#include "bnxt_cpr.h"
#include "bnxt_ring.h"
#include "bnxt_txq.h"
#include "bnxt_txr.h"
struct tx_bd_long **last_txbd)
{
struct bnxt_tx_ring_info *txr = txq->tx_ring;
+ uint32_t outer_tpid_bd = 0;
struct tx_bd_long *txbd;
struct tx_bd_long_hi *txbd1 = NULL;
uint32_t vlan_tag_flags, cfa_action;
TX_BD_LONG_FLAGS_LHINT_LT2K
};
+ if (unlikely(is_bnxt_in_error(txq->bp)))
+ return -EIO;
+
if (tx_pkt->ol_flags & (PKT_TX_TCP_SEG | PKT_TX_TCP_CKSUM |
PKT_TX_UDP_CKSUM | PKT_TX_IP_CKSUM |
PKT_TX_VLAN_PKT | PKT_TX_OUTER_IP_CKSUM |
PKT_TX_TUNNEL_GRE | PKT_TX_TUNNEL_VXLAN |
- PKT_TX_TUNNEL_GENEVE))
+ PKT_TX_TUNNEL_GENEVE | PKT_TX_IEEE1588_TMST |
+ PKT_TX_QINQ_PKT))
long_bd = true;
nr_bds = long_bd + tx_pkt->nb_segs;
txbd->flags_type |= TX_BD_LONG_TYPE_TX_BD_LONG;
vlan_tag_flags = 0;
cfa_action = 0;
- if (tx_buf->mbuf->ol_flags & PKT_TX_VLAN_PKT) {
+ /* HW can accelerate only outer vlan in QinQ mode */
+ if (tx_buf->mbuf->ol_flags & PKT_TX_QINQ_PKT) {
+ vlan_tag_flags = TX_BD_LONG_CFA_META_KEY_VLAN_TAG |
+ tx_buf->mbuf->vlan_tci_outer;
+ outer_tpid_bd = txq->bp->outer_tpid_bd &
+ BNXT_OUTER_TPID_BD_MASK;
+ vlan_tag_flags |= outer_tpid_bd;
+ } else if (tx_buf->mbuf->ol_flags & PKT_TX_VLAN_PKT) {
/* shurd: Should this mask at
* TX_BD_LONG_CFA_META_VLAN_VID_MASK?
*/
txbd1->lflags |= TX_BD_LONG_LFLAGS_LSO |
TX_BD_LONG_LFLAGS_T_IPID;
hdr_size = tx_pkt->l2_len + tx_pkt->l3_len +
- tx_pkt->l4_len + tx_pkt->outer_l2_len +
- tx_pkt->outer_l3_len;
+ tx_pkt->l4_len;
+ hdr_size += (tx_pkt->ol_flags & PKT_TX_TUNNEL_MASK) ?
+ tx_pkt->outer_l2_len +
+ tx_pkt->outer_l3_len : 0;
/* The hdr_size is multiple of 16bit units not 8bit.
* Hence divide by 2.
*/
/* IP CSO */
txbd1->lflags |= TX_BD_LONG_LFLAGS_T_IP_CHKSUM;
txbd1->mss = 0;
+ } else if ((tx_pkt->ol_flags & PKT_TX_IEEE1588_TMST) ==
+ PKT_TX_IEEE1588_TMST) {
+ /* PTP */
+ txbd1->lflags |= TX_BD_LONG_LFLAGS_STAMP;
+ txbd1->mss = 0;
}
} else {
txbd->flags_type |= TX_BD_SHORT_TYPE_TX_BD_SHORT;
if (nb_tx_pkts) {
bnxt_tx_cmp(txq, nb_tx_pkts);
cpr->cp_raw_cons = raw_cons;
- B_CP_DB(cpr, cpr->cp_raw_cons, ring_mask);
+ bnxt_db_cq(cpr);
}
return nb_tx_pkts;
bnxt_handle_tx_cp(txq);
/* Tx queue was stopped; wait for it to be restarted */
- if (txq->tx_deferred_start) {
+ if (unlikely(!txq->tx_started)) {
PMD_DRV_LOG(DEBUG, "Tx q stopped;return\n");
return 0;
}
if (likely(nb_tx_pkts)) {
/* Request a completion on the last packet */
last_txbd->flags_type &= ~TX_BD_LONG_FLAGS_NO_CMPL;
- B_TX_DB(txq->tx_ring->tx_doorbell, txq->tx_ring->tx_prod);
+ bnxt_db_write(&txq->tx_ring->tx_db, txq->tx_ring->tx_prod);
}
return nb_tx_pkts;
}
+/*
+ * Dummy DPDK callback for TX.
+ *
+ * This function is used to temporarily replace the real callback during
+ * unsafe control operations on the queue, or in case of error.
+ */
+uint16_t
+bnxt_dummy_xmit_pkts(void *tx_queue __rte_unused,
+ struct rte_mbuf **tx_pkts __rte_unused,
+ uint16_t nb_pkts __rte_unused)
+{
+ return 0;
+}
+
int bnxt_tx_queue_start(struct rte_eth_dev *dev, uint16_t tx_queue_id)
{
- struct bnxt *bp = (struct bnxt *)dev->data->dev_private;
+ struct bnxt *bp = dev->data->dev_private;
struct bnxt_tx_queue *txq = bp->tx_queues[tx_queue_id];
+ int rc = 0;
+
+ rc = is_bnxt_in_error(bp);
+ if (rc)
+ return rc;
dev->data->tx_queue_state[tx_queue_id] = RTE_ETH_QUEUE_STATE_STARTED;
- txq->tx_deferred_start = false;
+ txq->tx_started = true;
PMD_DRV_LOG(DEBUG, "Tx queue started\n");
return 0;
int bnxt_tx_queue_stop(struct rte_eth_dev *dev, uint16_t tx_queue_id)
{
- struct bnxt *bp = (struct bnxt *)dev->data->dev_private;
+ struct bnxt *bp = dev->data->dev_private;
struct bnxt_tx_queue *txq = bp->tx_queues[tx_queue_id];
+ int rc = 0;
+
+ rc = is_bnxt_in_error(bp);
+ if (rc)
+ return rc;
/* Handle TX completions */
bnxt_handle_tx_cp(txq);
dev->data->tx_queue_state[tx_queue_id] = RTE_ETH_QUEUE_STATE_STOPPED;
- txq->tx_deferred_start = true;
+ txq->tx_started = false;
PMD_DRV_LOG(DEBUG, "Tx queue stopped\n");
return 0;