diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_cae/hns3_cae_stat.c b/drivers/net/ethernet/hisilicon/hns3/hns3_cae/hns3_cae_stat.c index ea69639b3d8645de84bc7fdf55cc2907351f57fb..9d4d16109bb3bc4a2c6403091d88e4f403a33b1f 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_cae/hns3_cae_stat.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_cae/hns3_cae_stat.c @@ -9,7 +9,7 @@ const struct ring_stats_name hns3_ring_stats_name[] = { {"seg_pkt_cnt", SEG_PKT_CNT}, {"tx_pkts", TX_PKTS}, {"tx_bytes", TX_BYTES}, - {"tx_err_cnt", TX_ERR_CNT}, + {"tx_more", TX_MORE}, {"restart_queue", RESTART_QUEUE}, {"tx_busy", TX_BUSY}, {"rx_pkts", RX_PKTS}, @@ -58,8 +58,8 @@ static int hns3_get_stat_val(struct ring_stats *r_stats, char *val_name, case TX_BYTES: *val = &r_stats->tx_bytes; break; - case TX_ERR_CNT: - *val = &r_stats->tx_err_cnt; + case TX_MORE: + *val = &r_stats->tx_more; break; case RESTART_QUEUE: *val = &r_stats->restart_queue; diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_cae/hns3_cae_stat.h b/drivers/net/ethernet/hisilicon/hns3/hns3_cae/hns3_cae_stat.h index a54ef8e34bf555c6f7fa826127356f8f9b5823bb..47c3faf44ebb711dfc6d01f5d5ac121cfc133a3c 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_cae/hns3_cae_stat.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_cae/hns3_cae_stat.h @@ -24,7 +24,7 @@ enum stats_name_type { SEG_PKT_CNT, TX_PKTS, TX_BYTES, - TX_ERR_CNT, + TX_MORE, RESTART_QUEUE, TX_BUSY, RX_PKTS, diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c index b9c0f36cda6b1da2b460043e989e8060fcdf8a75..a9417ec2556c6eb6c70380793db411331ec0b671 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c @@ -1388,6 +1388,27 @@ static int hns3_fill_skb_to_desc(struct hns3_enet_ring *ring, return bd_num; } +static void hns3_tx_doorbell(struct hns3_enet_ring *ring, int num, + bool doorbell) +{ + ring->pending_buf += num; + + if (!doorbell) { + u64_stats_update_begin(&ring->syncp); + ring->stats.tx_more++; + u64_stats_update_end(&ring->syncp); + return; + } + + if (!ring->pending_buf) + return; + + wmb(); /* Commit all data before submit */ + + hnae3_queue_xmit(ring->tqp, ring->pending_buf); + ring->pending_buf = 0; +} + netdev_tx_t hns3_nic_net_xmit(struct sk_buff *skb, struct net_device *netdev) { struct hns3_nic_priv *priv = netdev_priv(netdev); @@ -1399,8 +1420,10 @@ netdev_tx_t hns3_nic_net_xmit(struct sk_buff *skb, struct net_device *netdev) int ret; /* Hardware can only handle short frames above 32 bytes */ - if (skb_put_padto(skb, HNS3_MIN_TX_LEN)) + if (skb_put_padto(skb, HNS3_MIN_TX_LEN)) { + hns3_tx_doorbell(ring, 0, !netdev_xmit_more()); return NETDEV_TX_OK; + } /* Prefetch the data used later */ prefetch(skb->data); @@ -1411,6 +1434,7 @@ netdev_tx_t hns3_nic_net_xmit(struct sk_buff *skb, struct net_device *netdev) u64_stats_update_begin(&ring->syncp); ring->stats.tx_busy++; u64_stats_update_end(&ring->syncp); + hns3_tx_doorbell(ring, 0, true); return NETDEV_TX_BUSY; } else if (ret == -ENOMEM) { u64_stats_update_begin(&ring->syncp); @@ -1453,11 +1477,14 @@ netdev_tx_t hns3_nic_net_xmit(struct sk_buff *skb, struct net_device *netdev) /* Complete translate all packets */ dev_queue = netdev_get_tx_queue(netdev, ring->queue_index); - netdev_tx_sent_queue(dev_queue, skb->len); - - wmb(); /* Commit all data before submit */ - - hnae3_queue_xmit(ring->tqp, bd_num); + if (!netdev_xmit_more()) { + netdev_tx_sent_queue(dev_queue, skb->len); + hns3_tx_doorbell(ring, bd_num, true); + } else { + dql_queued(&dev_queue->dql, skb->len); + hns3_tx_doorbell(ring, bd_num, + netif_tx_queue_stopped(dev_queue)); + } return NETDEV_TX_OK; @@ -1466,6 +1493,7 @@ netdev_tx_t hns3_nic_net_xmit(struct sk_buff *skb, struct net_device *netdev) out_err_tx_ok: dev_kfree_skb_any(skb); + hns3_tx_doorbell(ring, 0, !netdev_xmit_more()); return NETDEV_TX_OK; } @@ -1896,13 +1924,14 @@ bool hns3_get_tx_timeo_queue_info(struct net_device *ndev) tx_ring->next_to_clean, napi->state); netdev_info(ndev, - "tx_pkts: %llu, tx_bytes: %llu, io_err_cnt: %llu, sw_err_cnt: %llu\n", + "tx_pkts: %llu, tx_bytes: %llu, io_err_cnt: %llu, sw_err_cnt: %llu, tx_pending: %d\n", tx_ring->stats.tx_pkts, tx_ring->stats.tx_bytes, - tx_ring->stats.io_err_cnt, tx_ring->stats.sw_err_cnt); + tx_ring->stats.io_err_cnt, tx_ring->stats.sw_err_cnt, + tx_ring->pending_buf); netdev_info(ndev, - "seg_pkt_cnt: %llu, tx_err_cnt: %llu, restart_queue: %llu, tx_busy: %llu\n", - tx_ring->stats.seg_pkt_cnt, tx_ring->stats.tx_err_cnt, + "seg_pkt_cnt: %llu, tx_more: %llu, restart_queue: %llu, tx_busy: %llu\n", + tx_ring->stats.seg_pkt_cnt, tx_ring->stats.tx_more, tx_ring->stats.restart_queue, tx_ring->stats.tx_busy); /* When mac received many pause frames continuous, it's unable to send @@ -4285,6 +4314,8 @@ static void hns3_clear_tx_ring(struct hns3_enet_ring *ring) hns3_free_buffer_detach(ring, ring->next_to_clean); ring_ptr_move_fw(ring, next_to_clean); } + + ring->pending_buf = 0; } static int hns3_clear_rx_ring(struct hns3_enet_ring *ring) diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h index 8fa37d9d1359a6971dade6edff946f082a9c58b3..90b991962fb99153337290ed9f6b4a10929febd7 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h @@ -377,7 +377,7 @@ struct ring_stats { struct { u64 tx_pkts; u64 tx_bytes; - u64 tx_err_cnt; + u64 tx_more; u64 restart_queue; u64 tx_busy; u64 tx_copy; diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c b/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c index d04a61e39b68e9c3c80b36a221d165125a7c171c..d6788923e30be9f85226c967b06f863964759bba 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c @@ -36,7 +36,7 @@ static const struct hns3_stats hns3_txq_stats[] = { HNS3_TQP_STAT("seg_pkt_cnt", seg_pkt_cnt), HNS3_TQP_STAT("packets", tx_pkts), HNS3_TQP_STAT("bytes", tx_bytes), - HNS3_TQP_STAT("errors", tx_err_cnt), + HNS3_TQP_STAT("more", tx_more), HNS3_TQP_STAT("wake", restart_queue), HNS3_TQP_STAT("busy", tx_busy), HNS3_TQP_STAT("copy", tx_copy),