diff options
Diffstat (limited to 'drivers/net/virtio_net.c')
-rw-r--r-- | drivers/net/virtio_net.c | 56 |
1 files changed, 38 insertions, 18 deletions
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index 0c7321c35ad4..6ee8410443c4 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c | |||
@@ -143,18 +143,16 @@ static void skb_xmit_done(struct virtqueue *svq) | |||
143 | static void set_skb_frag(struct sk_buff *skb, struct page *page, | 143 | static void set_skb_frag(struct sk_buff *skb, struct page *page, |
144 | unsigned int offset, unsigned int *len) | 144 | unsigned int offset, unsigned int *len) |
145 | { | 145 | { |
146 | int size = min((unsigned)PAGE_SIZE - offset, *len); | ||
146 | int i = skb_shinfo(skb)->nr_frags; | 147 | int i = skb_shinfo(skb)->nr_frags; |
147 | skb_frag_t *f; | ||
148 | 148 | ||
149 | f = &skb_shinfo(skb)->frags[i]; | 149 | __skb_fill_page_desc(skb, i, page, offset, size); |
150 | f->size = min((unsigned)PAGE_SIZE - offset, *len); | ||
151 | f->page_offset = offset; | ||
152 | f->page = page; | ||
153 | 150 | ||
154 | skb->data_len += f->size; | 151 | skb->data_len += size; |
155 | skb->len += f->size; | 152 | skb->len += size; |
153 | skb->truesize += PAGE_SIZE; | ||
156 | skb_shinfo(skb)->nr_frags++; | 154 | skb_shinfo(skb)->nr_frags++; |
157 | *len -= f->size; | 155 | *len -= size; |
158 | } | 156 | } |
159 | 157 | ||
160 | static struct sk_buff *page_to_skb(struct virtnet_info *vi, | 158 | static struct sk_buff *page_to_skb(struct virtnet_info *vi, |
@@ -195,6 +193,19 @@ static struct sk_buff *page_to_skb(struct virtnet_info *vi, | |||
195 | len -= copy; | 193 | len -= copy; |
196 | offset += copy; | 194 | offset += copy; |
197 | 195 | ||
196 | /* | ||
197 | * Verify that we can indeed put this data into a skb. | ||
198 | * This is here to handle cases when the device erroneously | ||
199 | * tries to receive more than is possible. This is usually | ||
200 | * the case of a broken device. | ||
201 | */ | ||
202 | if (unlikely(len > MAX_SKB_FRAGS * PAGE_SIZE)) { | ||
203 | if (net_ratelimit()) | ||
204 | pr_debug("%s: too much data\n", skb->dev->name); | ||
205 | dev_kfree_skb(skb); | ||
206 | return NULL; | ||
207 | } | ||
208 | |||
198 | while (len) { | 209 | while (len) { |
199 | set_skb_frag(skb, page, offset, &len); | 210 | set_skb_frag(skb, page, offset, &len); |
200 | page = (struct page *)page->private; | 211 | page = (struct page *)page->private; |
@@ -277,7 +288,6 @@ static void receive_buf(struct net_device *dev, void *buf, unsigned int len) | |||
277 | } | 288 | } |
278 | 289 | ||
279 | hdr = skb_vnet_hdr(skb); | 290 | hdr = skb_vnet_hdr(skb); |
280 | skb->truesize += skb->data_len; | ||
281 | 291 | ||
282 | u64_stats_update_begin(&stats->syncp); | 292 | u64_stats_update_begin(&stats->syncp); |
283 | stats->rx_bytes += skb->len; | 293 | stats->rx_bytes += skb->len; |
@@ -867,8 +877,21 @@ static void virtnet_vlan_rx_kill_vid(struct net_device *dev, u16 vid) | |||
867 | dev_warn(&dev->dev, "Failed to kill VLAN ID %d.\n", vid); | 877 | dev_warn(&dev->dev, "Failed to kill VLAN ID %d.\n", vid); |
868 | } | 878 | } |
869 | 879 | ||
880 | static void virtnet_get_ringparam(struct net_device *dev, | ||
881 | struct ethtool_ringparam *ring) | ||
882 | { | ||
883 | struct virtnet_info *vi = netdev_priv(dev); | ||
884 | |||
885 | ring->rx_max_pending = virtqueue_get_vring_size(vi->rvq); | ||
886 | ring->tx_max_pending = virtqueue_get_vring_size(vi->svq); | ||
887 | ring->rx_pending = ring->rx_max_pending; | ||
888 | ring->tx_pending = ring->tx_max_pending; | ||
889 | |||
890 | } | ||
891 | |||
870 | static const struct ethtool_ops virtnet_ethtool_ops = { | 892 | static const struct ethtool_ops virtnet_ethtool_ops = { |
871 | .get_link = ethtool_op_get_link, | 893 | .get_link = ethtool_op_get_link, |
894 | .get_ringparam = virtnet_get_ringparam, | ||
872 | }; | 895 | }; |
873 | 896 | ||
874 | #define MIN_MTU 68 | 897 | #define MIN_MTU 68 |
@@ -902,12 +925,10 @@ static void virtnet_update_status(struct virtnet_info *vi) | |||
902 | { | 925 | { |
903 | u16 v; | 926 | u16 v; |
904 | 927 | ||
905 | if (!virtio_has_feature(vi->vdev, VIRTIO_NET_F_STATUS)) | 928 | if (virtio_config_val(vi->vdev, VIRTIO_NET_F_STATUS, |
906 | return; | ||
907 | |||
908 | vi->vdev->config->get(vi->vdev, | ||
909 | offsetof(struct virtio_net_config, status), | 929 | offsetof(struct virtio_net_config, status), |
910 | &v, sizeof(v)); | 930 | &v) < 0) |
931 | return; | ||
911 | 932 | ||
912 | /* Ignore unknown (future) status bits */ | 933 | /* Ignore unknown (future) status bits */ |
913 | v &= VIRTIO_NET_S_LINK_UP; | 934 | v &= VIRTIO_NET_S_LINK_UP; |
@@ -949,6 +970,7 @@ static int virtnet_probe(struct virtio_device *vdev) | |||
949 | return -ENOMEM; | 970 | return -ENOMEM; |
950 | 971 | ||
951 | /* Set up network device as normal. */ | 972 | /* Set up network device as normal. */ |
973 | dev->priv_flags |= IFF_UNICAST_FLT; | ||
952 | dev->netdev_ops = &virtnet_netdev; | 974 | dev->netdev_ops = &virtnet_netdev; |
953 | dev->features = NETIF_F_HIGHDMA; | 975 | dev->features = NETIF_F_HIGHDMA; |
954 | 976 | ||
@@ -982,11 +1004,9 @@ static int virtnet_probe(struct virtio_device *vdev) | |||
982 | } | 1004 | } |
983 | 1005 | ||
984 | /* Configuration may specify what MAC to use. Otherwise random. */ | 1006 | /* Configuration may specify what MAC to use. Otherwise random. */ |
985 | if (virtio_has_feature(vdev, VIRTIO_NET_F_MAC)) { | 1007 | if (virtio_config_val_len(vdev, VIRTIO_NET_F_MAC, |
986 | vdev->config->get(vdev, | ||
987 | offsetof(struct virtio_net_config, mac), | 1008 | offsetof(struct virtio_net_config, mac), |
988 | dev->dev_addr, dev->addr_len); | 1009 | dev->dev_addr, dev->addr_len) < 0) |
989 | } else | ||
990 | random_ether_addr(dev->dev_addr); | 1010 | random_ether_addr(dev->dev_addr); |
991 | 1011 | ||
992 | /* Set up our device-specific information */ | 1012 | /* Set up our device-specific information */ |