aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMark McLoughlin <markmc@redhat.com>2009-01-19 20:09:49 -0500
committerDavid S. Miller <davem@davemloft.net>2009-01-21 17:34:53 -0500
commit9f4d26d0f3016cf8813977d624751b94465fa317 (patch)
treeac17805553ff3b3bc570ed73027b150e7ba3b88b
parent357fe2c6d2b12482abd1c3f24a086a2f507f03fc (diff)
virtio_net: add link status handling
Allow the host to inform us that the link is down by adding a VIRTIO_NET_F_STATUS which indicates that device status is available in virtio_net config. This is currently useful for simulating link down conditions (e.g. using proposed qemu 'set_link' monitor command) but would also be needed if we were to support device assignment via virtio. Signed-off-by: Mark McLoughlin <markmc@redhat.com> Signed-off-by: Rusty Russell <rusty@rustcorp.com.au> (added future masking) Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/virtio_net.c43
-rw-r--r--include/linux/virtio_net.h5
2 files changed, 47 insertions, 1 deletions
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index 30ae6d9a12af..9b33d6ebf542 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -42,6 +42,7 @@ struct virtnet_info
42 struct virtqueue *rvq, *svq; 42 struct virtqueue *rvq, *svq;
43 struct net_device *dev; 43 struct net_device *dev;
44 struct napi_struct napi; 44 struct napi_struct napi;
45 unsigned int status;
45 46
46 /* The skb we couldn't send because buffers were full. */ 47 /* The skb we couldn't send because buffers were full. */
47 struct sk_buff *last_xmit_skb; 48 struct sk_buff *last_xmit_skb;
@@ -611,6 +612,7 @@ static struct ethtool_ops virtnet_ethtool_ops = {
611 .set_tx_csum = virtnet_set_tx_csum, 612 .set_tx_csum = virtnet_set_tx_csum,
612 .set_sg = ethtool_op_set_sg, 613 .set_sg = ethtool_op_set_sg,
613 .set_tso = ethtool_op_set_tso, 614 .set_tso = ethtool_op_set_tso,
615 .get_link = ethtool_op_get_link,
614}; 616};
615 617
616#define MIN_MTU 68 618#define MIN_MTU 68
@@ -636,6 +638,41 @@ static const struct net_device_ops virtnet_netdev = {
636#endif 638#endif
637}; 639};
638 640
641static void virtnet_update_status(struct virtnet_info *vi)
642{
643 u16 v;
644
645 if (!virtio_has_feature(vi->vdev, VIRTIO_NET_F_STATUS))
646 return;
647
648 vi->vdev->config->get(vi->vdev,
649 offsetof(struct virtio_net_config, status),
650 &v, sizeof(v));
651
652 /* Ignore unknown (future) status bits */
653 v &= VIRTIO_NET_S_LINK_UP;
654
655 if (vi->status == v)
656 return;
657
658 vi->status = v;
659
660 if (vi->status & VIRTIO_NET_S_LINK_UP) {
661 netif_carrier_on(vi->dev);
662 netif_wake_queue(vi->dev);
663 } else {
664 netif_carrier_off(vi->dev);
665 netif_stop_queue(vi->dev);
666 }
667}
668
669static void virtnet_config_changed(struct virtio_device *vdev)
670{
671 struct virtnet_info *vi = vdev->priv;
672
673 virtnet_update_status(vi);
674}
675
639static int virtnet_probe(struct virtio_device *vdev) 676static int virtnet_probe(struct virtio_device *vdev)
640{ 677{
641 int err; 678 int err;
@@ -738,6 +775,9 @@ static int virtnet_probe(struct virtio_device *vdev)
738 goto unregister; 775 goto unregister;
739 } 776 }
740 777
778 vi->status = VIRTIO_NET_S_LINK_UP;
779 virtnet_update_status(vi);
780
741 pr_debug("virtnet: registered device %s\n", dev->name); 781 pr_debug("virtnet: registered device %s\n", dev->name);
742 return 0; 782 return 0;
743 783
@@ -793,7 +833,7 @@ static unsigned int features[] = {
793 VIRTIO_NET_F_HOST_TSO4, VIRTIO_NET_F_HOST_UFO, VIRTIO_NET_F_HOST_TSO6, 833 VIRTIO_NET_F_HOST_TSO4, VIRTIO_NET_F_HOST_UFO, VIRTIO_NET_F_HOST_TSO6,
794 VIRTIO_NET_F_HOST_ECN, VIRTIO_NET_F_GUEST_TSO4, VIRTIO_NET_F_GUEST_TSO6, 834 VIRTIO_NET_F_HOST_ECN, VIRTIO_NET_F_GUEST_TSO4, VIRTIO_NET_F_GUEST_TSO6,
795 VIRTIO_NET_F_GUEST_ECN, /* We don't yet handle UFO input. */ 835 VIRTIO_NET_F_GUEST_ECN, /* We don't yet handle UFO input. */
796 VIRTIO_NET_F_MRG_RXBUF, 836 VIRTIO_NET_F_MRG_RXBUF, VIRTIO_NET_F_STATUS,
797 VIRTIO_F_NOTIFY_ON_EMPTY, 837 VIRTIO_F_NOTIFY_ON_EMPTY,
798}; 838};
799 839
@@ -805,6 +845,7 @@ static struct virtio_driver virtio_net = {
805 .id_table = id_table, 845 .id_table = id_table,
806 .probe = virtnet_probe, 846 .probe = virtnet_probe,
807 .remove = __devexit_p(virtnet_remove), 847 .remove = __devexit_p(virtnet_remove),
848 .config_changed = virtnet_config_changed,
808}; 849};
809 850
810static int __init init(void) 851static int __init init(void)
diff --git a/include/linux/virtio_net.h b/include/linux/virtio_net.h
index 5cdd0aa8bde9..f76bd4a753ef 100644
--- a/include/linux/virtio_net.h
+++ b/include/linux/virtio_net.h
@@ -21,11 +21,16 @@
21#define VIRTIO_NET_F_HOST_ECN 13 /* Host can handle TSO[6] w/ ECN in. */ 21#define VIRTIO_NET_F_HOST_ECN 13 /* Host can handle TSO[6] w/ ECN in. */
22#define VIRTIO_NET_F_HOST_UFO 14 /* Host can handle UFO in. */ 22#define VIRTIO_NET_F_HOST_UFO 14 /* Host can handle UFO in. */
23#define VIRTIO_NET_F_MRG_RXBUF 15 /* Host can merge receive buffers. */ 23#define VIRTIO_NET_F_MRG_RXBUF 15 /* Host can merge receive buffers. */
24#define VIRTIO_NET_F_STATUS 16 /* virtio_net_config.status available */
25
26#define VIRTIO_NET_S_LINK_UP 1 /* Link is up */
24 27
25struct virtio_net_config 28struct virtio_net_config
26{ 29{
27 /* The config defining mac address (if VIRTIO_NET_F_MAC) */ 30 /* The config defining mac address (if VIRTIO_NET_F_MAC) */
28 __u8 mac[6]; 31 __u8 mac[6];
32 /* See VIRTIO_NET_F_STATUS and VIRTIO_NET_S_* above */
33 __u16 status;
29} __attribute__((packed)); 34} __attribute__((packed));
30 35
31/* This is the first element of the scatter-gather list. If you don't 36/* This is the first element of the scatter-gather list. If you don't