提交 f6061a05 编写于 作者: Y Yunsheng Lin 提交者: David S. Miller

net: hns3: batch tx doorbell operation

Use netdev_xmit_more() to defer the tx doorbell operation when
the skb is passed to the driver continuously. By doing this we
can improve the overall xmit performance by avoid some doorbell
operations.

Also, the tx_err_cnt stat is not used, so rename it to tx_more
stat.
Signed-off-by: NYunsheng Lin <linyunsheng@huawei.com>
Signed-off-by: NHuazhong Tan <tanhuazhong@huawei.com>
Signed-off-by: NDavid S. Miller <davem@davemloft.net>
上级 aeda9bf8
...@@ -1383,6 +1383,27 @@ static int hns3_fill_skb_to_desc(struct hns3_enet_ring *ring, ...@@ -1383,6 +1383,27 @@ static int hns3_fill_skb_to_desc(struct hns3_enet_ring *ring,
return bd_num; 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) netdev_tx_t hns3_nic_net_xmit(struct sk_buff *skb, struct net_device *netdev)
{ {
struct hns3_nic_priv *priv = netdev_priv(netdev); struct hns3_nic_priv *priv = netdev_priv(netdev);
...@@ -1391,11 +1412,14 @@ netdev_tx_t hns3_nic_net_xmit(struct sk_buff *skb, struct net_device *netdev) ...@@ -1391,11 +1412,14 @@ netdev_tx_t hns3_nic_net_xmit(struct sk_buff *skb, struct net_device *netdev)
int pre_ntu, next_to_use_head; int pre_ntu, next_to_use_head;
struct sk_buff *frag_skb; struct sk_buff *frag_skb;
int bd_num = 0; int bd_num = 0;
bool doorbell;
int ret; int ret;
/* Hardware can only handle short frames above 32 bytes */ /* 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; return NETDEV_TX_OK;
}
/* Prefetch the data used later */ /* Prefetch the data used later */
prefetch(skb->data); prefetch(skb->data);
...@@ -1406,6 +1430,7 @@ netdev_tx_t hns3_nic_net_xmit(struct sk_buff *skb, struct net_device *netdev) ...@@ -1406,6 +1430,7 @@ netdev_tx_t hns3_nic_net_xmit(struct sk_buff *skb, struct net_device *netdev)
u64_stats_update_begin(&ring->syncp); u64_stats_update_begin(&ring->syncp);
ring->stats.tx_busy++; ring->stats.tx_busy++;
u64_stats_update_end(&ring->syncp); u64_stats_update_end(&ring->syncp);
hns3_tx_doorbell(ring, 0, true);
return NETDEV_TX_BUSY; return NETDEV_TX_BUSY;
} else if (ret == -ENOMEM) { } else if (ret == -ENOMEM) {
u64_stats_update_begin(&ring->syncp); u64_stats_update_begin(&ring->syncp);
...@@ -1446,11 +1471,9 @@ netdev_tx_t hns3_nic_net_xmit(struct sk_buff *skb, struct net_device *netdev) ...@@ -1446,11 +1471,9 @@ netdev_tx_t hns3_nic_net_xmit(struct sk_buff *skb, struct net_device *netdev)
/* Complete translate all packets */ /* Complete translate all packets */
dev_queue = netdev_get_tx_queue(netdev, ring->queue_index); dev_queue = netdev_get_tx_queue(netdev, ring->queue_index);
netdev_tx_sent_queue(dev_queue, skb->len); doorbell = __netdev_tx_sent_queue(dev_queue, skb->len,
netdev_xmit_more());
wmb(); /* Commit all data before submit */ hns3_tx_doorbell(ring, bd_num, doorbell);
hnae3_queue_xmit(ring->tqp, bd_num);
return NETDEV_TX_OK; return NETDEV_TX_OK;
...@@ -1459,6 +1482,7 @@ netdev_tx_t hns3_nic_net_xmit(struct sk_buff *skb, struct net_device *netdev) ...@@ -1459,6 +1482,7 @@ netdev_tx_t hns3_nic_net_xmit(struct sk_buff *skb, struct net_device *netdev)
out_err_tx_ok: out_err_tx_ok:
dev_kfree_skb_any(skb); dev_kfree_skb_any(skb);
hns3_tx_doorbell(ring, 0, !netdev_xmit_more());
return NETDEV_TX_OK; return NETDEV_TX_OK;
} }
...@@ -1839,13 +1863,14 @@ static bool hns3_get_tx_timeo_queue_info(struct net_device *ndev) ...@@ -1839,13 +1863,14 @@ static bool hns3_get_tx_timeo_queue_info(struct net_device *ndev)
tx_ring->next_to_clean, napi->state); tx_ring->next_to_clean, napi->state);
netdev_info(ndev, 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.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, netdev_info(ndev,
"seg_pkt_cnt: %llu, tx_err_cnt: %llu, restart_queue: %llu, tx_busy: %llu\n", "seg_pkt_cnt: %llu, tx_more: %llu, restart_queue: %llu, tx_busy: %llu\n",
tx_ring->stats.seg_pkt_cnt, tx_ring->stats.tx_err_cnt, tx_ring->stats.seg_pkt_cnt, tx_ring->stats.tx_more,
tx_ring->stats.restart_queue, tx_ring->stats.tx_busy); tx_ring->stats.restart_queue, tx_ring->stats.tx_busy);
/* When mac received many pause frames continuous, it's unable to send /* When mac received many pause frames continuous, it's unable to send
...@@ -4181,6 +4206,8 @@ static void hns3_clear_tx_ring(struct hns3_enet_ring *ring) ...@@ -4181,6 +4206,8 @@ static void hns3_clear_tx_ring(struct hns3_enet_ring *ring)
hns3_free_buffer_detach(ring, ring->next_to_clean); hns3_free_buffer_detach(ring, ring->next_to_clean);
ring_ptr_move_fw(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) static int hns3_clear_rx_ring(struct hns3_enet_ring *ring)
......
...@@ -351,7 +351,7 @@ struct ring_stats { ...@@ -351,7 +351,7 @@ struct ring_stats {
struct { struct {
u64 tx_pkts; u64 tx_pkts;
u64 tx_bytes; u64 tx_bytes;
u64 tx_err_cnt; u64 tx_more;
u64 restart_queue; u64 restart_queue;
u64 tx_busy; u64 tx_busy;
u64 tx_copy; u64 tx_copy;
......
...@@ -32,7 +32,7 @@ static const struct hns3_stats hns3_txq_stats[] = { ...@@ -32,7 +32,7 @@ static const struct hns3_stats hns3_txq_stats[] = {
HNS3_TQP_STAT("seg_pkt_cnt", seg_pkt_cnt), HNS3_TQP_STAT("seg_pkt_cnt", seg_pkt_cnt),
HNS3_TQP_STAT("packets", tx_pkts), HNS3_TQP_STAT("packets", tx_pkts),
HNS3_TQP_STAT("bytes", tx_bytes), 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("wake", restart_queue),
HNS3_TQP_STAT("busy", tx_busy), HNS3_TQP_STAT("busy", tx_busy),
HNS3_TQP_STAT("copy", tx_copy), HNS3_TQP_STAT("copy", tx_copy),
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册