diff options
Diffstat (limited to 'drivers/net/virtio_net.c')
| -rw-r--r-- | drivers/net/virtio_net.c | 91 |
1 files changed, 77 insertions, 14 deletions
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index f926b5ab3d09..4452306d5328 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c | |||
| @@ -44,9 +44,16 @@ struct virtnet_info | |||
| 44 | /* The skb we couldn't send because buffers were full. */ | 44 | /* The skb we couldn't send because buffers were full. */ |
| 45 | struct sk_buff *last_xmit_skb; | 45 | struct sk_buff *last_xmit_skb; |
| 46 | 46 | ||
| 47 | /* If we need to free in a timer, this is it. */ | ||
| 48 | struct timer_list xmit_free_timer; | ||
| 49 | |||
| 47 | /* Number of input buffers, and max we've ever had. */ | 50 | /* Number of input buffers, and max we've ever had. */ |
| 48 | unsigned int num, max; | 51 | unsigned int num, max; |
| 49 | 52 | ||
| 53 | /* For cleaning up after transmission. */ | ||
| 54 | struct tasklet_struct tasklet; | ||
| 55 | bool free_in_tasklet; | ||
| 56 | |||
| 50 | /* Receive & send queues. */ | 57 | /* Receive & send queues. */ |
| 51 | struct sk_buff_head recv; | 58 | struct sk_buff_head recv; |
| 52 | struct sk_buff_head send; | 59 | struct sk_buff_head send; |
| @@ -68,8 +75,13 @@ static void skb_xmit_done(struct virtqueue *svq) | |||
| 68 | 75 | ||
| 69 | /* Suppress further interrupts. */ | 76 | /* Suppress further interrupts. */ |
| 70 | svq->vq_ops->disable_cb(svq); | 77 | svq->vq_ops->disable_cb(svq); |
| 71 | /* We were waiting for more output buffers. */ | 78 | |
| 79 | /* We were probably waiting for more output buffers. */ | ||
| 72 | netif_wake_queue(vi->dev); | 80 | netif_wake_queue(vi->dev); |
| 81 | |||
| 82 | /* Make sure we re-xmit last_xmit_skb: if there are no more packets | ||
| 83 | * queued, start_xmit won't be called. */ | ||
| 84 | tasklet_schedule(&vi->tasklet); | ||
| 73 | } | 85 | } |
| 74 | 86 | ||
| 75 | static void receive_skb(struct net_device *dev, struct sk_buff *skb, | 87 | static void receive_skb(struct net_device *dev, struct sk_buff *skb, |
| @@ -86,9 +98,7 @@ static void receive_skb(struct net_device *dev, struct sk_buff *skb, | |||
| 86 | BUG_ON(len > MAX_PACKET_LEN); | 98 | BUG_ON(len > MAX_PACKET_LEN); |
| 87 | 99 | ||
| 88 | skb_trim(skb, len); | 100 | skb_trim(skb, len); |
| 89 | skb->protocol = eth_type_trans(skb, dev); | 101 | |
| 90 | pr_debug("Receiving skb proto 0x%04x len %i type %i\n", | ||
| 91 | ntohs(skb->protocol), skb->len, skb->pkt_type); | ||
| 92 | dev->stats.rx_bytes += skb->len; | 102 | dev->stats.rx_bytes += skb->len; |
| 93 | dev->stats.rx_packets++; | 103 | dev->stats.rx_packets++; |
| 94 | 104 | ||
| @@ -98,6 +108,10 @@ static void receive_skb(struct net_device *dev, struct sk_buff *skb, | |||
| 98 | goto frame_err; | 108 | goto frame_err; |
| 99 | } | 109 | } |
| 100 | 110 | ||
| 111 | skb->protocol = eth_type_trans(skb, dev); | ||
| 112 | pr_debug("Receiving skb proto 0x%04x len %i type %i\n", | ||
| 113 | ntohs(skb->protocol), skb->len, skb->pkt_type); | ||
| 114 | |||
| 101 | if (hdr->gso_type != VIRTIO_NET_HDR_GSO_NONE) { | 115 | if (hdr->gso_type != VIRTIO_NET_HDR_GSO_NONE) { |
| 102 | pr_debug("GSO!\n"); | 116 | pr_debug("GSO!\n"); |
| 103 | switch (hdr->gso_type & ~VIRTIO_NET_HDR_GSO_ECN) { | 117 | switch (hdr->gso_type & ~VIRTIO_NET_HDR_GSO_ECN) { |
| @@ -230,9 +244,25 @@ static void free_old_xmit_skbs(struct virtnet_info *vi) | |||
| 230 | } | 244 | } |
| 231 | } | 245 | } |
| 232 | 246 | ||
| 247 | /* If the virtio transport doesn't always notify us when all in-flight packets | ||
| 248 | * are consumed, we fall back to using this function on a timer to free them. */ | ||
| 249 | static void xmit_free(unsigned long data) | ||
| 250 | { | ||
| 251 | struct virtnet_info *vi = (void *)data; | ||
| 252 | |||
| 253 | netif_tx_lock(vi->dev); | ||
| 254 | |||
| 255 | free_old_xmit_skbs(vi); | ||
| 256 | |||
| 257 | if (!skb_queue_empty(&vi->send)) | ||
| 258 | mod_timer(&vi->xmit_free_timer, jiffies + (HZ/10)); | ||
| 259 | |||
| 260 | netif_tx_unlock(vi->dev); | ||
| 261 | } | ||
| 262 | |||
| 233 | static int xmit_skb(struct virtnet_info *vi, struct sk_buff *skb) | 263 | static int xmit_skb(struct virtnet_info *vi, struct sk_buff *skb) |
| 234 | { | 264 | { |
| 235 | int num; | 265 | int num, err; |
| 236 | struct scatterlist sg[2+MAX_SKB_FRAGS]; | 266 | struct scatterlist sg[2+MAX_SKB_FRAGS]; |
| 237 | struct virtio_net_hdr *hdr; | 267 | struct virtio_net_hdr *hdr; |
| 238 | const unsigned char *dest = ((struct ethhdr *)skb->data)->h_dest; | 268 | const unsigned char *dest = ((struct ethhdr *)skb->data)->h_dest; |
| @@ -275,7 +305,25 @@ static int xmit_skb(struct virtnet_info *vi, struct sk_buff *skb) | |||
| 275 | vnet_hdr_to_sg(sg, skb); | 305 | vnet_hdr_to_sg(sg, skb); |
| 276 | num = skb_to_sgvec(skb, sg+1, 0, skb->len) + 1; | 306 | num = skb_to_sgvec(skb, sg+1, 0, skb->len) + 1; |
| 277 | 307 | ||
| 278 | return vi->svq->vq_ops->add_buf(vi->svq, sg, num, 0, skb); | 308 | err = vi->svq->vq_ops->add_buf(vi->svq, sg, num, 0, skb); |
| 309 | if (!err && !vi->free_in_tasklet) | ||
| 310 | mod_timer(&vi->xmit_free_timer, jiffies + (HZ/10)); | ||
| 311 | |||
| 312 | return err; | ||
| 313 | } | ||
| 314 | |||
| 315 | static void xmit_tasklet(unsigned long data) | ||
| 316 | { | ||
| 317 | struct virtnet_info *vi = (void *)data; | ||
| 318 | |||
| 319 | netif_tx_lock_bh(vi->dev); | ||
| 320 | if (vi->last_xmit_skb && xmit_skb(vi, vi->last_xmit_skb) == 0) { | ||
| 321 | vi->svq->vq_ops->kick(vi->svq); | ||
| 322 | vi->last_xmit_skb = NULL; | ||
| 323 | } | ||
| 324 | if (vi->free_in_tasklet) | ||
| 325 | free_old_xmit_skbs(vi); | ||
| 326 | netif_tx_unlock_bh(vi->dev); | ||
| 279 | } | 327 | } |
| 280 | 328 | ||
| 281 | static int start_xmit(struct sk_buff *skb, struct net_device *dev) | 329 | static int start_xmit(struct sk_buff *skb, struct net_device *dev) |
| @@ -287,21 +335,25 @@ again: | |||
| 287 | free_old_xmit_skbs(vi); | 335 | free_old_xmit_skbs(vi); |
| 288 | 336 | ||
| 289 | /* If we has a buffer left over from last time, send it now. */ | 337 | /* If we has a buffer left over from last time, send it now. */ |
| 290 | if (vi->last_xmit_skb) { | 338 | if (unlikely(vi->last_xmit_skb)) { |
| 291 | if (xmit_skb(vi, vi->last_xmit_skb) != 0) { | 339 | if (xmit_skb(vi, vi->last_xmit_skb) != 0) { |
| 292 | /* Drop this skb: we only queue one. */ | 340 | /* Drop this skb: we only queue one. */ |
| 293 | vi->dev->stats.tx_dropped++; | 341 | vi->dev->stats.tx_dropped++; |
| 294 | kfree_skb(skb); | 342 | kfree_skb(skb); |
| 343 | skb = NULL; | ||
| 295 | goto stop_queue; | 344 | goto stop_queue; |
| 296 | } | 345 | } |
| 297 | vi->last_xmit_skb = NULL; | 346 | vi->last_xmit_skb = NULL; |
| 298 | } | 347 | } |
| 299 | 348 | ||
| 300 | /* Put new one in send queue and do transmit */ | 349 | /* Put new one in send queue and do transmit */ |
| 301 | __skb_queue_head(&vi->send, skb); | 350 | if (likely(skb)) { |
| 302 | if (xmit_skb(vi, skb) != 0) { | 351 | __skb_queue_head(&vi->send, skb); |
| 303 | vi->last_xmit_skb = skb; | 352 | if (xmit_skb(vi, skb) != 0) { |
| 304 | goto stop_queue; | 353 | vi->last_xmit_skb = skb; |
| 354 | skb = NULL; | ||
| 355 | goto stop_queue; | ||
| 356 | } | ||
| 305 | } | 357 | } |
| 306 | done: | 358 | done: |
| 307 | vi->svq->vq_ops->kick(vi->svq); | 359 | vi->svq->vq_ops->kick(vi->svq); |
| @@ -411,6 +463,10 @@ static int virtnet_probe(struct virtio_device *vdev) | |||
| 411 | vi->vdev = vdev; | 463 | vi->vdev = vdev; |
| 412 | vdev->priv = vi; | 464 | vdev->priv = vi; |
| 413 | 465 | ||
| 466 | /* If they give us a callback when all buffers are done, we don't need | ||
| 467 | * the timer. */ | ||
| 468 | vi->free_in_tasklet = virtio_has_feature(vdev,VIRTIO_F_NOTIFY_ON_EMPTY); | ||
| 469 | |||
| 414 | /* We expect two virtqueues, receive then send. */ | 470 | /* We expect two virtqueues, receive then send. */ |
| 415 | vi->rvq = vdev->config->find_vq(vdev, 0, skb_recv_done); | 471 | vi->rvq = vdev->config->find_vq(vdev, 0, skb_recv_done); |
| 416 | if (IS_ERR(vi->rvq)) { | 472 | if (IS_ERR(vi->rvq)) { |
| @@ -428,6 +484,11 @@ static int virtnet_probe(struct virtio_device *vdev) | |||
| 428 | skb_queue_head_init(&vi->recv); | 484 | skb_queue_head_init(&vi->recv); |
| 429 | skb_queue_head_init(&vi->send); | 485 | skb_queue_head_init(&vi->send); |
| 430 | 486 | ||
| 487 | tasklet_init(&vi->tasklet, xmit_tasklet, (unsigned long)vi); | ||
| 488 | |||
| 489 | if (!vi->free_in_tasklet) | ||
| 490 | setup_timer(&vi->xmit_free_timer, xmit_free, (unsigned long)vi); | ||
| 491 | |||
| 431 | err = register_netdev(dev); | 492 | err = register_netdev(dev); |
| 432 | if (err) { | 493 | if (err) { |
| 433 | pr_debug("virtio_net: registering device failed\n"); | 494 | pr_debug("virtio_net: registering device failed\n"); |
| @@ -465,13 +526,15 @@ static void virtnet_remove(struct virtio_device *vdev) | |||
| 465 | /* Stop all the virtqueues. */ | 526 | /* Stop all the virtqueues. */ |
| 466 | vdev->config->reset(vdev); | 527 | vdev->config->reset(vdev); |
| 467 | 528 | ||
| 529 | if (!vi->free_in_tasklet) | ||
| 530 | del_timer_sync(&vi->xmit_free_timer); | ||
| 531 | |||
| 468 | /* Free our skbs in send and recv queues, if any. */ | 532 | /* Free our skbs in send and recv queues, if any. */ |
| 469 | while ((skb = __skb_dequeue(&vi->recv)) != NULL) { | 533 | while ((skb = __skb_dequeue(&vi->recv)) != NULL) { |
| 470 | kfree_skb(skb); | 534 | kfree_skb(skb); |
| 471 | vi->num--; | 535 | vi->num--; |
| 472 | } | 536 | } |
| 473 | while ((skb = __skb_dequeue(&vi->send)) != NULL) | 537 | __skb_queue_purge(&vi->send); |
| 474 | kfree_skb(skb); | ||
| 475 | 538 | ||
| 476 | BUG_ON(vi->num != 0); | 539 | BUG_ON(vi->num != 0); |
| 477 | 540 | ||
| @@ -489,7 +552,7 @@ static struct virtio_device_id id_table[] = { | |||
| 489 | static unsigned int features[] = { | 552 | static unsigned int features[] = { |
| 490 | VIRTIO_NET_F_CSUM, VIRTIO_NET_F_GSO, VIRTIO_NET_F_MAC, | 553 | VIRTIO_NET_F_CSUM, VIRTIO_NET_F_GSO, VIRTIO_NET_F_MAC, |
| 491 | VIRTIO_NET_F_HOST_TSO4, VIRTIO_NET_F_HOST_UFO, VIRTIO_NET_F_HOST_TSO6, | 554 | VIRTIO_NET_F_HOST_TSO4, VIRTIO_NET_F_HOST_UFO, VIRTIO_NET_F_HOST_TSO6, |
| 492 | VIRTIO_NET_F_HOST_ECN, | 555 | VIRTIO_NET_F_HOST_ECN, VIRTIO_F_NOTIFY_ON_EMPTY, |
| 493 | }; | 556 | }; |
| 494 | 557 | ||
| 495 | static struct virtio_driver virtio_net = { | 558 | static struct virtio_driver virtio_net = { |
