aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/virtio_net.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/virtio_net.c')
-rw-r--r--drivers/net/virtio_net.c55
1 files changed, 48 insertions, 7 deletions
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index c68808336c8c..fe576e75a538 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -43,6 +43,7 @@ struct virtnet_info
43 struct virtqueue *rvq, *svq; 43 struct virtqueue *rvq, *svq;
44 struct net_device *dev; 44 struct net_device *dev;
45 struct napi_struct napi; 45 struct napi_struct napi;
46 unsigned int status;
46 47
47 /* The skb we couldn't send because buffers were full. */ 48 /* The skb we couldn't send because buffers were full. */
48 struct sk_buff *last_xmit_skb; 49 struct sk_buff *last_xmit_skb;
@@ -375,9 +376,9 @@ static void skb_recv_done(struct virtqueue *rvq)
375{ 376{
376 struct virtnet_info *vi = rvq->vdev->priv; 377 struct virtnet_info *vi = rvq->vdev->priv;
377 /* Schedule NAPI, Suppress further interrupts if successful. */ 378 /* Schedule NAPI, Suppress further interrupts if successful. */
378 if (netif_rx_schedule_prep(&vi->napi)) { 379 if (napi_schedule_prep(&vi->napi)) {
379 rvq->vq_ops->disable_cb(rvq); 380 rvq->vq_ops->disable_cb(rvq);
380 __netif_rx_schedule(&vi->napi); 381 __napi_schedule(&vi->napi);
381 } 382 }
382} 383}
383 384
@@ -403,11 +404,11 @@ again:
403 404
404 /* Out of packets? */ 405 /* Out of packets? */
405 if (received < budget) { 406 if (received < budget) {
406 netif_rx_complete(napi); 407 napi_complete(napi);
407 if (unlikely(!vi->rvq->vq_ops->enable_cb(vi->rvq)) 408 if (unlikely(!vi->rvq->vq_ops->enable_cb(vi->rvq))
408 && napi_schedule_prep(napi)) { 409 && napi_schedule_prep(napi)) {
409 vi->rvq->vq_ops->disable_cb(vi->rvq); 410 vi->rvq->vq_ops->disable_cb(vi->rvq);
410 __netif_rx_schedule(napi); 411 __napi_schedule(napi);
411 goto again; 412 goto again;
412 } 413 }
413 } 414 }
@@ -581,9 +582,9 @@ static int virtnet_open(struct net_device *dev)
581 * won't get another interrupt, so process any outstanding packets 582 * won't get another interrupt, so process any outstanding packets
582 * now. virtnet_poll wants re-enable the queue, so we disable here. 583 * now. virtnet_poll wants re-enable the queue, so we disable here.
583 * We synchronize against interrupts via NAPI_STATE_SCHED */ 584 * We synchronize against interrupts via NAPI_STATE_SCHED */
584 if (netif_rx_schedule_prep(&vi->napi)) { 585 if (napi_schedule_prep(&vi->napi)) {
585 vi->rvq->vq_ops->disable_cb(vi->rvq); 586 vi->rvq->vq_ops->disable_cb(vi->rvq);
586 __netif_rx_schedule(&vi->napi); 587 __napi_schedule(&vi->napi);
587 } 588 }
588 return 0; 589 return 0;
589} 590}
@@ -612,6 +613,7 @@ static struct ethtool_ops virtnet_ethtool_ops = {
612 .set_tx_csum = virtnet_set_tx_csum, 613 .set_tx_csum = virtnet_set_tx_csum,
613 .set_sg = ethtool_op_set_sg, 614 .set_sg = ethtool_op_set_sg,
614 .set_tso = ethtool_op_set_tso, 615 .set_tso = ethtool_op_set_tso,
616 .get_link = ethtool_op_get_link,
615}; 617};
616 618
617#define MIN_MTU 68 619#define MIN_MTU 68
@@ -637,6 +639,41 @@ static const struct net_device_ops virtnet_netdev = {
637#endif 639#endif
638}; 640};
639 641
642static void virtnet_update_status(struct virtnet_info *vi)
643{
644 u16 v;
645
646 if (!virtio_has_feature(vi->vdev, VIRTIO_NET_F_STATUS))
647 return;
648
649 vi->vdev->config->get(vi->vdev,
650 offsetof(struct virtio_net_config, status),
651 &v, sizeof(v));
652
653 /* Ignore unknown (future) status bits */
654 v &= VIRTIO_NET_S_LINK_UP;
655
656 if (vi->status == v)
657 return;
658
659 vi->status = v;
660
661 if (vi->status & VIRTIO_NET_S_LINK_UP) {
662 netif_carrier_on(vi->dev);
663 netif_wake_queue(vi->dev);
664 } else {
665 netif_carrier_off(vi->dev);
666 netif_stop_queue(vi->dev);
667 }
668}
669
670static void virtnet_config_changed(struct virtio_device *vdev)
671{
672 struct virtnet_info *vi = vdev->priv;
673
674 virtnet_update_status(vi);
675}
676
640static int virtnet_probe(struct virtio_device *vdev) 677static int virtnet_probe(struct virtio_device *vdev)
641{ 678{
642 int err; 679 int err;
@@ -739,6 +776,9 @@ static int virtnet_probe(struct virtio_device *vdev)
739 goto unregister; 776 goto unregister;
740 } 777 }
741 778
779 vi->status = VIRTIO_NET_S_LINK_UP;
780 virtnet_update_status(vi);
781
742 pr_debug("virtnet: registered device %s\n", dev->name); 782 pr_debug("virtnet: registered device %s\n", dev->name);
743 return 0; 783 return 0;
744 784
@@ -794,7 +834,7 @@ static unsigned int features[] = {
794 VIRTIO_NET_F_HOST_TSO4, VIRTIO_NET_F_HOST_UFO, VIRTIO_NET_F_HOST_TSO6, 834 VIRTIO_NET_F_HOST_TSO4, VIRTIO_NET_F_HOST_UFO, VIRTIO_NET_F_HOST_TSO6,
795 VIRTIO_NET_F_HOST_ECN, VIRTIO_NET_F_GUEST_TSO4, VIRTIO_NET_F_GUEST_TSO6, 835 VIRTIO_NET_F_HOST_ECN, VIRTIO_NET_F_GUEST_TSO4, VIRTIO_NET_F_GUEST_TSO6,
796 VIRTIO_NET_F_GUEST_ECN, /* We don't yet handle UFO input. */ 836 VIRTIO_NET_F_GUEST_ECN, /* We don't yet handle UFO input. */
797 VIRTIO_NET_F_MRG_RXBUF, 837 VIRTIO_NET_F_MRG_RXBUF, VIRTIO_NET_F_STATUS,
798 VIRTIO_F_NOTIFY_ON_EMPTY, 838 VIRTIO_F_NOTIFY_ON_EMPTY,
799}; 839};
800 840
@@ -806,6 +846,7 @@ static struct virtio_driver virtio_net = {
806 .id_table = id_table, 846 .id_table = id_table,
807 .probe = virtnet_probe, 847 .probe = virtnet_probe,
808 .remove = __devexit_p(virtnet_remove), 848 .remove = __devexit_p(virtnet_remove),
849 .config_changed = virtnet_config_changed,
809}; 850};
810 851
811static int __init init(void) 852static int __init init(void)