Commit 0dada88b authored by Sunil Goutham's avatar Sunil Goutham Committed by David S. Miller

net: thunderx: Optimize CQE_TX handling

Optimized CQE handling with below changes
- Feeing descriptors back to SQ in bulk i.e once per NAPI
  instance instead for every CQE_TX, this will reduce number
  of atomic updates to 'sq->free_cnt'.
- Checking errors in CQE_TX and CQE_RX before calling appropriate
  fn()s to update error stats i.e reduce branching.

Also removed debug messages in packet handling path which otherwise
causes issues if DEBUG is enabled.
Signed-off-by: default avatarSunil Goutham <sgoutham@cavium.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 5e848e4c
...@@ -498,7 +498,7 @@ static int nicvf_init_resources(struct nicvf *nic) ...@@ -498,7 +498,7 @@ static int nicvf_init_resources(struct nicvf *nic)
static void nicvf_snd_pkt_handler(struct net_device *netdev, static void nicvf_snd_pkt_handler(struct net_device *netdev,
struct cqe_send_t *cqe_tx, struct cqe_send_t *cqe_tx,
int cqe_type, int budget, int budget, int *subdesc_cnt,
unsigned int *tx_pkts, unsigned int *tx_bytes) unsigned int *tx_pkts, unsigned int *tx_bytes)
{ {
struct sk_buff *skb = NULL; struct sk_buff *skb = NULL;
...@@ -513,12 +513,10 @@ static void nicvf_snd_pkt_handler(struct net_device *netdev, ...@@ -513,12 +513,10 @@ static void nicvf_snd_pkt_handler(struct net_device *netdev,
if (hdr->subdesc_type != SQ_DESC_TYPE_HEADER) if (hdr->subdesc_type != SQ_DESC_TYPE_HEADER)
return; return;
netdev_dbg(nic->netdev, /* Check for errors */
"%s Qset #%d SQ #%d SQ ptr #%d subdesc count %d\n", if (cqe_tx->send_status)
__func__, cqe_tx->sq_qs, cqe_tx->sq_idx, nicvf_check_cqe_tx_errs(nic->pnicvf, cqe_tx);
cqe_tx->sqe_ptr, hdr->subdesc_cnt);
nicvf_check_cqe_tx_errs(nic, cqe_tx);
skb = (struct sk_buff *)sq->skbuff[cqe_tx->sqe_ptr]; skb = (struct sk_buff *)sq->skbuff[cqe_tx->sqe_ptr];
if (skb) { if (skb) {
/* Check for dummy descriptor used for HW TSO offload on 88xx */ /* Check for dummy descriptor used for HW TSO offload on 88xx */
...@@ -528,12 +526,12 @@ static void nicvf_snd_pkt_handler(struct net_device *netdev, ...@@ -528,12 +526,12 @@ static void nicvf_snd_pkt_handler(struct net_device *netdev,
(struct sq_hdr_subdesc *)GET_SQ_DESC(sq, hdr->rsvd2); (struct sq_hdr_subdesc *)GET_SQ_DESC(sq, hdr->rsvd2);
nicvf_unmap_sndq_buffers(nic, sq, hdr->rsvd2, nicvf_unmap_sndq_buffers(nic, sq, hdr->rsvd2,
tso_sqe->subdesc_cnt); tso_sqe->subdesc_cnt);
nicvf_put_sq_desc(sq, tso_sqe->subdesc_cnt + 1); *subdesc_cnt += tso_sqe->subdesc_cnt + 1;
} else { } else {
nicvf_unmap_sndq_buffers(nic, sq, cqe_tx->sqe_ptr, nicvf_unmap_sndq_buffers(nic, sq, cqe_tx->sqe_ptr,
hdr->subdesc_cnt); hdr->subdesc_cnt);
} }
nicvf_put_sq_desc(sq, hdr->subdesc_cnt + 1); *subdesc_cnt += hdr->subdesc_cnt + 1;
prefetch(skb); prefetch(skb);
(*tx_pkts)++; (*tx_pkts)++;
*tx_bytes += skb->len; *tx_bytes += skb->len;
...@@ -544,7 +542,7 @@ static void nicvf_snd_pkt_handler(struct net_device *netdev, ...@@ -544,7 +542,7 @@ static void nicvf_snd_pkt_handler(struct net_device *netdev,
* a SKB attached, so just free SQEs here. * a SKB attached, so just free SQEs here.
*/ */
if (!nic->hw_tso) if (!nic->hw_tso)
nicvf_put_sq_desc(sq, hdr->subdesc_cnt + 1); *subdesc_cnt += hdr->subdesc_cnt + 1;
} }
} }
...@@ -595,9 +593,11 @@ static void nicvf_rcv_pkt_handler(struct net_device *netdev, ...@@ -595,9 +593,11 @@ static void nicvf_rcv_pkt_handler(struct net_device *netdev,
} }
/* Check for errors */ /* Check for errors */
if (cqe_rx->err_level || cqe_rx->err_opcode) {
err = nicvf_check_cqe_rx_errs(nic, cqe_rx); err = nicvf_check_cqe_rx_errs(nic, cqe_rx);
if (err && !cqe_rx->rb_cnt) if (err && !cqe_rx->rb_cnt)
return; return;
}
skb = nicvf_get_rcv_skb(snic, cqe_rx); skb = nicvf_get_rcv_skb(snic, cqe_rx);
if (!skb) { if (!skb) {
...@@ -646,6 +646,7 @@ static int nicvf_cq_intr_handler(struct net_device *netdev, u8 cq_idx, ...@@ -646,6 +646,7 @@ static int nicvf_cq_intr_handler(struct net_device *netdev, u8 cq_idx,
{ {
int processed_cqe, work_done = 0, tx_done = 0; int processed_cqe, work_done = 0, tx_done = 0;
int cqe_count, cqe_head; int cqe_count, cqe_head;
int subdesc_cnt = 0;
struct nicvf *nic = netdev_priv(netdev); struct nicvf *nic = netdev_priv(netdev);
struct queue_set *qs = nic->qs; struct queue_set *qs = nic->qs;
struct cmp_queue *cq = &qs->cq[cq_idx]; struct cmp_queue *cq = &qs->cq[cq_idx];
...@@ -667,8 +668,6 @@ static int nicvf_cq_intr_handler(struct net_device *netdev, u8 cq_idx, ...@@ -667,8 +668,6 @@ static int nicvf_cq_intr_handler(struct net_device *netdev, u8 cq_idx,
cqe_head = nicvf_queue_reg_read(nic, NIC_QSET_CQ_0_7_HEAD, cq_idx) >> 9; cqe_head = nicvf_queue_reg_read(nic, NIC_QSET_CQ_0_7_HEAD, cq_idx) >> 9;
cqe_head &= 0xFFFF; cqe_head &= 0xFFFF;
netdev_dbg(nic->netdev, "%s CQ%d cqe_count %d cqe_head %d\n",
__func__, cq_idx, cqe_count, cqe_head);
while (processed_cqe < cqe_count) { while (processed_cqe < cqe_count) {
/* Get the CQ descriptor */ /* Get the CQ descriptor */
cq_desc = (struct cqe_rx_t *)GET_CQ_DESC(cq, cqe_head); cq_desc = (struct cqe_rx_t *)GET_CQ_DESC(cq, cqe_head);
...@@ -682,17 +681,15 @@ static int nicvf_cq_intr_handler(struct net_device *netdev, u8 cq_idx, ...@@ -682,17 +681,15 @@ static int nicvf_cq_intr_handler(struct net_device *netdev, u8 cq_idx,
break; break;
} }
netdev_dbg(nic->netdev, "CQ%d cq_desc->cqe_type %d\n",
cq_idx, cq_desc->cqe_type);
switch (cq_desc->cqe_type) { switch (cq_desc->cqe_type) {
case CQE_TYPE_RX: case CQE_TYPE_RX:
nicvf_rcv_pkt_handler(netdev, napi, cq_desc); nicvf_rcv_pkt_handler(netdev, napi, cq_desc);
work_done++; work_done++;
break; break;
case CQE_TYPE_SEND: case CQE_TYPE_SEND:
nicvf_snd_pkt_handler(netdev, nicvf_snd_pkt_handler(netdev, (void *)cq_desc,
(void *)cq_desc, CQE_TYPE_SEND, budget, &subdesc_cnt,
budget, &tx_pkts, &tx_bytes); &tx_pkts, &tx_bytes);
tx_done++; tx_done++;
break; break;
case CQE_TYPE_INVALID: case CQE_TYPE_INVALID:
...@@ -704,9 +701,6 @@ static int nicvf_cq_intr_handler(struct net_device *netdev, u8 cq_idx, ...@@ -704,9 +701,6 @@ static int nicvf_cq_intr_handler(struct net_device *netdev, u8 cq_idx,
} }
processed_cqe++; processed_cqe++;
} }
netdev_dbg(nic->netdev,
"%s CQ%d processed_cqe %d work_done %d budget %d\n",
__func__, cq_idx, processed_cqe, work_done, budget);
/* Ring doorbell to inform H/W to reuse processed CQEs */ /* Ring doorbell to inform H/W to reuse processed CQEs */
nicvf_queue_reg_write(nic, NIC_QSET_CQ_0_7_DOOR, nicvf_queue_reg_write(nic, NIC_QSET_CQ_0_7_DOOR,
...@@ -716,8 +710,12 @@ static int nicvf_cq_intr_handler(struct net_device *netdev, u8 cq_idx, ...@@ -716,8 +710,12 @@ static int nicvf_cq_intr_handler(struct net_device *netdev, u8 cq_idx,
goto loop; goto loop;
done: done:
/* Wakeup TXQ if its stopped earlier due to SQ full */
sq = &nic->qs->sq[cq_idx]; sq = &nic->qs->sq[cq_idx];
/* Update SQ's descriptor free count */
if (subdesc_cnt)
nicvf_put_sq_desc(sq, subdesc_cnt);
/* Wakeup TXQ if its stopped earlier due to SQ full */
if (tx_done || if (tx_done ||
(atomic_read(&sq->free_cnt) >= MIN_SQ_DESC_PER_PKT_XMIT)) { (atomic_read(&sq->free_cnt) >= MIN_SQ_DESC_PER_PKT_XMIT)) {
netdev = nic->pnicvf->netdev; netdev = nic->pnicvf->netdev;
......
...@@ -1640,9 +1640,6 @@ void nicvf_update_sq_stats(struct nicvf *nic, int sq_idx) ...@@ -1640,9 +1640,6 @@ void nicvf_update_sq_stats(struct nicvf *nic, int sq_idx)
/* Check for errors in the receive cmp.queue entry */ /* Check for errors in the receive cmp.queue entry */
int nicvf_check_cqe_rx_errs(struct nicvf *nic, struct cqe_rx_t *cqe_rx) int nicvf_check_cqe_rx_errs(struct nicvf *nic, struct cqe_rx_t *cqe_rx)
{ {
if (!cqe_rx->err_level && !cqe_rx->err_opcode)
return 0;
if (netif_msg_rx_err(nic)) if (netif_msg_rx_err(nic))
netdev_err(nic->netdev, netdev_err(nic->netdev,
"%s: RX error CQE err_level 0x%x err_opcode 0x%x\n", "%s: RX error CQE err_level 0x%x err_opcode 0x%x\n",
...@@ -1731,8 +1728,6 @@ int nicvf_check_cqe_rx_errs(struct nicvf *nic, struct cqe_rx_t *cqe_rx) ...@@ -1731,8 +1728,6 @@ int nicvf_check_cqe_rx_errs(struct nicvf *nic, struct cqe_rx_t *cqe_rx)
int nicvf_check_cqe_tx_errs(struct nicvf *nic, struct cqe_send_t *cqe_tx) int nicvf_check_cqe_tx_errs(struct nicvf *nic, struct cqe_send_t *cqe_tx)
{ {
switch (cqe_tx->send_status) { switch (cqe_tx->send_status) {
case CQ_TX_ERROP_GOOD:
return 0;
case CQ_TX_ERROP_DESC_FAULT: case CQ_TX_ERROP_DESC_FAULT:
this_cpu_inc(nic->drv_stats->tx_desc_fault); this_cpu_inc(nic->drv_stats->tx_desc_fault);
break; break;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment