forked from Minki/linux
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: Sunil Goutham <sgoutham@cavium.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
5e848e4c5d
commit
0dada88b8c
@ -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,
|
|||||||
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,
|
|||||||
(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,
|
|||||||
* 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,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* 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,
|
|||||||
{
|
{
|
||||||
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 @@ loop:
|
|||||||
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 @@ loop:
|
|||||||
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 @@ loop:
|
|||||||
}
|
}
|
||||||
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 @@ loop:
|
|||||||
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)
|
|||||||
/* 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)
|
|||||||
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;
|
||||||
|
Loading…
Reference in New Issue
Block a user