From: Mark McLoughlin <markmc@redhat.com> Date: Tue, 21 Oct 2008 10:44:05 +0100 Subject: [xen] virtio_net: some relatively minor fixes Message-id: 1224582245.708.24.camel@blaa O-Subject: [RHEL5.3 PATCH 0/4] virtio_net: some relatively minor fixes Bugzilla: 468034 RH-Acked-by: Rik van Riel <riel@redhat.com> RH-Acked-by: Don Dutile <ddutile@redhat.com> RH-Acked-by: Bill Burns <bburns@redhat.com> RH-Acked-by: Herbert Xu <herbert.xu@redhat.com> RH-Acked-by: Chris Wright <chrisw@redhat.com> https://bugzilla.redhat.com/446214 What follows are four relatively minor fixes to the backported virtio_net drivers which were added in 2.6.18-110.el5. They can either be committed as a single patch or four individual patches. The patches are: 1) Fix leaked netdev->refcnt - it can often be impossible to unload the virtio_net driver with rmmod because of a device refcount leak. The bug does not exist upstream because it is in code added as part of the backport. 2) Support ethtool offload queries - a simple and safe ethtool change needed because of differences between 2.6.18 and upstream. 3) Make use of napi_weight module param - the backport caused the napi_weight module param to be ignored. 4) Recycle some more rx buffer pages - trivial, safe optimization which will be in 2.6.28. We have tested all these patches quite extensively as part of our general testing efforts around RHEL5 virtio drivers. Signed-off-by: Mark McLoughlin <markmc@redhat.com> diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index d743b1e..8e8da1d 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -84,6 +84,16 @@ static void give_a_page(struct virtnet_info *vi, struct page *page) vi->pages = page; } +static void trim_pages(struct virtnet_info *vi, struct sk_buff *skb) +{ + unsigned int i; + + for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) + give_a_page(vi, skb_shinfo(skb)->frags[i].page); + skb_shinfo(skb)->nr_frags = 0; + skb->data_len = 0; +} + static struct page *get_a_page(struct virtnet_info *vi, gfp_t gfp_mask) { struct page *p = vi->pages; @@ -124,14 +134,8 @@ static void receive_skb(struct net_device *dev, struct sk_buff *skb, } len -= sizeof(struct virtio_net_hdr); - if (len <= MAX_PACKET_LEN) { - unsigned int i; - - for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) - give_a_page(dev->priv, skb_shinfo(skb)->frags[i].page); - skb->data_len = 0; - skb_shinfo(skb)->nr_frags = 0; - } + if (len <= MAX_PACKET_LEN) + trim_pages(dev->priv, skb); err = pskb_trim(skb, len); if (err) { @@ -231,6 +235,7 @@ static void try_fill_recv(struct virtnet_info *vi) err = vi->rvq->vq_ops->add_buf(vi->rvq, sg, 0, num, skb); if (err) { skb_unlink(skb, &vi->recv); + trim_pages(vi, skb); kfree_skb(skb); break; } @@ -286,6 +291,7 @@ again: if (!no_work && netif_rx_schedule_prep(vi->dev)) { vi->rvq->vq_ops->disable_cb(vi->rvq); __netif_rx_schedule(vi->dev); + dev_put(vi->dev); goto again; } @@ -492,7 +498,11 @@ static int virtnet_set_tx_csum(struct net_device *dev, u32 data) static struct ethtool_ops virtnet_ethtool_ops = { .set_tx_csum = virtnet_set_tx_csum, + .get_tx_csum = ethtool_op_get_tx_csum, .set_sg = ethtool_op_set_sg, + .get_sg = ethtool_op_get_sg, + .set_tso = ethtool_op_set_tso, + .get_tso = ethtool_op_get_tso, }; static int virtnet_probe(struct virtio_device *vdev) @@ -548,7 +558,7 @@ static int virtnet_probe(struct virtio_device *vdev) /* Set up our device-specific information */ vi = netdev_priv(dev); dev->poll = virtnet_poll; - dev->weight = 16; + dev->weight = napi_weight; vi->dev = dev; vi->vdev = vdev; vdev->priv = vi;