Commit 9f4d26d0 authored by Mark McLoughlin's avatar Mark McLoughlin Committed by David S. Miller

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: default avatarMark McLoughlin <markmc@redhat.com>
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au> (added future masking)
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 357fe2c6
...@@ -42,6 +42,7 @@ struct virtnet_info ...@@ -42,6 +42,7 @@ struct virtnet_info
struct virtqueue *rvq, *svq; struct virtqueue *rvq, *svq;
struct net_device *dev; struct net_device *dev;
struct napi_struct napi; struct napi_struct napi;
unsigned int status;
/* The skb we couldn't send because buffers were full. */ /* The skb we couldn't send because buffers were full. */
struct sk_buff *last_xmit_skb; struct sk_buff *last_xmit_skb;
...@@ -611,6 +612,7 @@ static struct ethtool_ops virtnet_ethtool_ops = { ...@@ -611,6 +612,7 @@ static struct ethtool_ops virtnet_ethtool_ops = {
.set_tx_csum = virtnet_set_tx_csum, .set_tx_csum = virtnet_set_tx_csum,
.set_sg = ethtool_op_set_sg, .set_sg = ethtool_op_set_sg,
.set_tso = ethtool_op_set_tso, .set_tso = ethtool_op_set_tso,
.get_link = ethtool_op_get_link,
}; };
#define MIN_MTU 68 #define MIN_MTU 68
...@@ -636,6 +638,41 @@ static const struct net_device_ops virtnet_netdev = { ...@@ -636,6 +638,41 @@ static const struct net_device_ops virtnet_netdev = {
#endif #endif
}; };
static void virtnet_update_status(struct virtnet_info *vi)
{
u16 v;
if (!virtio_has_feature(vi->vdev, VIRTIO_NET_F_STATUS))
return;
vi->vdev->config->get(vi->vdev,
offsetof(struct virtio_net_config, status),
&v, sizeof(v));
/* Ignore unknown (future) status bits */
v &= VIRTIO_NET_S_LINK_UP;
if (vi->status == v)
return;
vi->status = v;
if (vi->status & VIRTIO_NET_S_LINK_UP) {
netif_carrier_on(vi->dev);
netif_wake_queue(vi->dev);
} else {
netif_carrier_off(vi->dev);
netif_stop_queue(vi->dev);
}
}
static void virtnet_config_changed(struct virtio_device *vdev)
{
struct virtnet_info *vi = vdev->priv;
virtnet_update_status(vi);
}
static int virtnet_probe(struct virtio_device *vdev) static int virtnet_probe(struct virtio_device *vdev)
{ {
int err; int err;
...@@ -738,6 +775,9 @@ static int virtnet_probe(struct virtio_device *vdev) ...@@ -738,6 +775,9 @@ static int virtnet_probe(struct virtio_device *vdev)
goto unregister; goto unregister;
} }
vi->status = VIRTIO_NET_S_LINK_UP;
virtnet_update_status(vi);
pr_debug("virtnet: registered device %s\n", dev->name); pr_debug("virtnet: registered device %s\n", dev->name);
return 0; return 0;
...@@ -793,7 +833,7 @@ static unsigned int features[] = { ...@@ -793,7 +833,7 @@ static unsigned int features[] = {
VIRTIO_NET_F_HOST_TSO4, VIRTIO_NET_F_HOST_UFO, VIRTIO_NET_F_HOST_TSO6, VIRTIO_NET_F_HOST_TSO4, VIRTIO_NET_F_HOST_UFO, VIRTIO_NET_F_HOST_TSO6,
VIRTIO_NET_F_HOST_ECN, VIRTIO_NET_F_GUEST_TSO4, VIRTIO_NET_F_GUEST_TSO6, VIRTIO_NET_F_HOST_ECN, VIRTIO_NET_F_GUEST_TSO4, VIRTIO_NET_F_GUEST_TSO6,
VIRTIO_NET_F_GUEST_ECN, /* We don't yet handle UFO input. */ VIRTIO_NET_F_GUEST_ECN, /* We don't yet handle UFO input. */
VIRTIO_NET_F_MRG_RXBUF, VIRTIO_NET_F_MRG_RXBUF, VIRTIO_NET_F_STATUS,
VIRTIO_F_NOTIFY_ON_EMPTY, VIRTIO_F_NOTIFY_ON_EMPTY,
}; };
...@@ -805,6 +845,7 @@ static struct virtio_driver virtio_net = { ...@@ -805,6 +845,7 @@ static struct virtio_driver virtio_net = {
.id_table = id_table, .id_table = id_table,
.probe = virtnet_probe, .probe = virtnet_probe,
.remove = __devexit_p(virtnet_remove), .remove = __devexit_p(virtnet_remove),
.config_changed = virtnet_config_changed,
}; };
static int __init init(void) static int __init init(void)
......
...@@ -21,11 +21,16 @@ ...@@ -21,11 +21,16 @@
#define VIRTIO_NET_F_HOST_ECN 13 /* Host can handle TSO[6] w/ ECN in. */ #define VIRTIO_NET_F_HOST_ECN 13 /* Host can handle TSO[6] w/ ECN in. */
#define VIRTIO_NET_F_HOST_UFO 14 /* Host can handle UFO in. */ #define VIRTIO_NET_F_HOST_UFO 14 /* Host can handle UFO in. */
#define VIRTIO_NET_F_MRG_RXBUF 15 /* Host can merge receive buffers. */ #define VIRTIO_NET_F_MRG_RXBUF 15 /* Host can merge receive buffers. */
#define VIRTIO_NET_F_STATUS 16 /* virtio_net_config.status available */
#define VIRTIO_NET_S_LINK_UP 1 /* Link is up */
struct virtio_net_config struct virtio_net_config
{ {
/* The config defining mac address (if VIRTIO_NET_F_MAC) */ /* The config defining mac address (if VIRTIO_NET_F_MAC) */
__u8 mac[6]; __u8 mac[6];
/* See VIRTIO_NET_F_STATUS and VIRTIO_NET_S_* above */
__u16 status;
} __attribute__((packed)); } __attribute__((packed));
/* This is the first element of the scatter-gather list. If you don't /* This is the first element of the scatter-gather list. If you don't
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment