mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2025-01-16 01:57:18 +07:00
Merge branch 'virtio-net-busy-poll'
Jason Wang says: ==================== rx busy polling support for virtio-net This series introduces the support for rx busy polling support. This was useful for reducing the latency for a kvm guest. Instead of introducing new states and spinlocks, this series re-uses NAPI state to synchonrize between NAPI and busy polling. This grealy simplified the codes and reduce the overheads of spinlocks for normal NAPI fast path. Test was done between a kvm guest and an external host. Two hosts were connected through 40gb mlx4 cards. With both busy_poll and busy_read are set to 50 in guest, 1 byte netperf tcp_rr shows 127% improvement: transaction rate was increased from 8353.33 to 18966.87. Changes from V2: - Avoid introducing new states and spinlocks by reusuing the NAPI state - Fix the budget calculation in virtnet_poll() - Drop patch 1/3 from V2 since it was useless Changes from V1: - split the patch info smaller ones - add more details about test setup/configuration ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
92bab4e715
@ -27,6 +27,7 @@
|
||||
#include <linux/slab.h>
|
||||
#include <linux/cpu.h>
|
||||
#include <linux/average.h>
|
||||
#include <net/busy_poll.h>
|
||||
|
||||
static int napi_weight = NAPI_POLL_WEIGHT;
|
||||
module_param(napi_weight, int, 0444);
|
||||
@ -521,6 +522,8 @@ static void receive_buf(struct receive_queue *rq, void *buf, unsigned int len)
|
||||
skb_shinfo(skb)->gso_segs = 0;
|
||||
}
|
||||
|
||||
skb_mark_napi_id(skb, &rq->napi);
|
||||
|
||||
netif_receive_skb(skb);
|
||||
return;
|
||||
|
||||
@ -725,15 +728,12 @@ static void refill_work(struct work_struct *work)
|
||||
}
|
||||
}
|
||||
|
||||
static int virtnet_poll(struct napi_struct *napi, int budget)
|
||||
static int virtnet_receive(struct receive_queue *rq, int budget)
|
||||
{
|
||||
struct receive_queue *rq =
|
||||
container_of(napi, struct receive_queue, napi);
|
||||
struct virtnet_info *vi = rq->vq->vdev->priv;
|
||||
unsigned int len, received = 0;
|
||||
void *buf;
|
||||
unsigned int r, len, received = 0;
|
||||
|
||||
again:
|
||||
while (received < budget &&
|
||||
(buf = virtqueue_get_buf(rq->vq, &len)) != NULL) {
|
||||
receive_buf(rq, buf, len);
|
||||
@ -745,6 +745,18 @@ static int virtnet_poll(struct napi_struct *napi, int budget)
|
||||
schedule_delayed_work(&vi->refill, 0);
|
||||
}
|
||||
|
||||
return received;
|
||||
}
|
||||
|
||||
static int virtnet_poll(struct napi_struct *napi, int budget)
|
||||
{
|
||||
struct receive_queue *rq =
|
||||
container_of(napi, struct receive_queue, napi);
|
||||
unsigned int r, received = 0;
|
||||
|
||||
again:
|
||||
received += virtnet_receive(rq, budget - received);
|
||||
|
||||
/* Out of packets? */
|
||||
if (received < budget) {
|
||||
r = virtqueue_enable_cb_prepare(rq->vq);
|
||||
@ -760,6 +772,43 @@ static int virtnet_poll(struct napi_struct *napi, int budget)
|
||||
return received;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_NET_RX_BUSY_POLL
|
||||
/* must be called with local_bh_disable()d */
|
||||
static int virtnet_busy_poll(struct napi_struct *napi)
|
||||
{
|
||||
struct receive_queue *rq =
|
||||
container_of(napi, struct receive_queue, napi);
|
||||
struct virtnet_info *vi = rq->vq->vdev->priv;
|
||||
int r, received = 0, budget = 4;
|
||||
|
||||
if (!(vi->status & VIRTIO_NET_S_LINK_UP))
|
||||
return LL_FLUSH_FAILED;
|
||||
|
||||
if (!napi_schedule_prep(napi))
|
||||
return LL_FLUSH_BUSY;
|
||||
|
||||
virtqueue_disable_cb(rq->vq);
|
||||
|
||||
again:
|
||||
received += virtnet_receive(rq, budget);
|
||||
|
||||
r = virtqueue_enable_cb_prepare(rq->vq);
|
||||
clear_bit(NAPI_STATE_SCHED, &napi->state);
|
||||
if (unlikely(virtqueue_poll(rq->vq, r)) &&
|
||||
napi_schedule_prep(napi)) {
|
||||
virtqueue_disable_cb(rq->vq);
|
||||
if (received < budget) {
|
||||
budget -= received;
|
||||
goto again;
|
||||
} else {
|
||||
__napi_schedule(napi);
|
||||
}
|
||||
}
|
||||
|
||||
return received;
|
||||
}
|
||||
#endif /* CONFIG_NET_RX_BUSY_POLL */
|
||||
|
||||
static int virtnet_open(struct net_device *dev)
|
||||
{
|
||||
struct virtnet_info *vi = netdev_priv(dev);
|
||||
@ -1347,6 +1396,9 @@ static const struct net_device_ops virtnet_netdev = {
|
||||
#ifdef CONFIG_NET_POLL_CONTROLLER
|
||||
.ndo_poll_controller = virtnet_netpoll,
|
||||
#endif
|
||||
#ifdef CONFIG_NET_RX_BUSY_POLL
|
||||
.ndo_busy_poll = virtnet_busy_poll,
|
||||
#endif
|
||||
};
|
||||
|
||||
static void virtnet_config_changed_work(struct work_struct *work)
|
||||
@ -1552,6 +1604,7 @@ static int virtnet_alloc_queues(struct virtnet_info *vi)
|
||||
vi->rq[i].pages = NULL;
|
||||
netif_napi_add(vi->dev, &vi->rq[i].napi, virtnet_poll,
|
||||
napi_weight);
|
||||
napi_hash_add(&vi->rq[i].napi);
|
||||
|
||||
sg_init_table(vi->rq[i].sg, ARRAY_SIZE(vi->rq[i].sg));
|
||||
ewma_init(&vi->rq[i].mrg_avg_pkt_len, 1, RECEIVE_AVG_WEIGHT);
|
||||
@ -1853,11 +1906,13 @@ static int virtnet_freeze(struct virtio_device *vdev)
|
||||
netif_device_detach(vi->dev);
|
||||
cancel_delayed_work_sync(&vi->refill);
|
||||
|
||||
if (netif_running(vi->dev))
|
||||
if (netif_running(vi->dev)) {
|
||||
for (i = 0; i < vi->max_queue_pairs; i++) {
|
||||
napi_disable(&vi->rq[i].napi);
|
||||
napi_hash_del(&vi->rq[i].napi);
|
||||
netif_napi_del(&vi->rq[i].napi);
|
||||
}
|
||||
}
|
||||
|
||||
remove_vq_common(vi);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user