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>
This commit is contained in:
committed by
David S. Miller
parent
357fe2c6d2
commit
9f4d26d0f3
@@ -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 = {
|
|||||||
.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 = {
|
|||||||
#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)
|
|||||||
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[] = {
|
|||||||
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 = {
|
|||||||
.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 @@
|
|||||||
#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
|
||||||
|
Reference in New Issue
Block a user