diff options
author | Rusty Russell <rusty@rustcorp.com.au> | 2008-05-02 22:50:50 -0400 |
---|---|---|
committer | Rusty Russell <rusty@rustcorp.com.au> | 2008-05-02 07:50:50 -0400 |
commit | c45a6816c19dee67b8f725e6646d428901a6dc24 (patch) | |
tree | 096e3263fd14e140685bcc3082394ff15f5aeddb /drivers/net/virtio_net.c | |
parent | 72e61eb40b55dd57031ec5971e810649f82b0259 (diff) |
virtio: explicit advertisement of driver features
A recent proposed feature addition to the virtio block driver revealed
some flaws in the API: in particular, we assume that feature
negotiation is complete once a driver's probe function returns.
There is nothing in the API to require this, however, and even I
didn't notice when it was violated.
So instead, we require the driver to specify what features it supports
in a table, we can then move the feature negotiation into the virtio
core. The intersection of device and driver features are presented in
a new 'features' bitmap in the struct virtio_device.
Note that this highlights the difference between Linux unsigned-long
bitmaps where each unsigned long is in native endian, and a
straight-forward little-endian array of bytes.
Drivers can still remove feature bits in their probe routine if they
really have to.
API changes:
- dev->config->feature() no longer gets and acks a feature.
- drivers should advertise their features in the 'feature_table' field
- use virtio_has_feature() for extra sanity when checking feature bits
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Diffstat (limited to 'drivers/net/virtio_net.c')
-rw-r--r-- | drivers/net/virtio_net.c | 22 |
1 files changed, 15 insertions, 7 deletions
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index ad43421ab6f1..f926b5ab3d09 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c | |||
@@ -378,26 +378,26 @@ static int virtnet_probe(struct virtio_device *vdev) | |||
378 | SET_NETDEV_DEV(dev, &vdev->dev); | 378 | SET_NETDEV_DEV(dev, &vdev->dev); |
379 | 379 | ||
380 | /* Do we support "hardware" checksums? */ | 380 | /* Do we support "hardware" checksums? */ |
381 | if (csum && vdev->config->feature(vdev, VIRTIO_NET_F_CSUM)) { | 381 | if (csum && virtio_has_feature(vdev, VIRTIO_NET_F_CSUM)) { |
382 | /* This opens up the world of extra features. */ | 382 | /* This opens up the world of extra features. */ |
383 | dev->features |= NETIF_F_HW_CSUM|NETIF_F_SG|NETIF_F_FRAGLIST; | 383 | dev->features |= NETIF_F_HW_CSUM|NETIF_F_SG|NETIF_F_FRAGLIST; |
384 | if (gso && vdev->config->feature(vdev, VIRTIO_NET_F_GSO)) { | 384 | if (gso && virtio_has_feature(vdev, VIRTIO_NET_F_GSO)) { |
385 | dev->features |= NETIF_F_TSO | NETIF_F_UFO | 385 | dev->features |= NETIF_F_TSO | NETIF_F_UFO |
386 | | NETIF_F_TSO_ECN | NETIF_F_TSO6; | 386 | | NETIF_F_TSO_ECN | NETIF_F_TSO6; |
387 | } | 387 | } |
388 | /* Individual feature bits: what can host handle? */ | 388 | /* Individual feature bits: what can host handle? */ |
389 | if (gso && vdev->config->feature(vdev, VIRTIO_NET_F_HOST_TSO4)) | 389 | if (gso && virtio_has_feature(vdev, VIRTIO_NET_F_HOST_TSO4)) |
390 | dev->features |= NETIF_F_TSO; | 390 | dev->features |= NETIF_F_TSO; |
391 | if (gso && vdev->config->feature(vdev, VIRTIO_NET_F_HOST_TSO6)) | 391 | if (gso && virtio_has_feature(vdev, VIRTIO_NET_F_HOST_TSO6)) |
392 | dev->features |= NETIF_F_TSO6; | 392 | dev->features |= NETIF_F_TSO6; |
393 | if (gso && vdev->config->feature(vdev, VIRTIO_NET_F_HOST_ECN)) | 393 | if (gso && virtio_has_feature(vdev, VIRTIO_NET_F_HOST_ECN)) |
394 | dev->features |= NETIF_F_TSO_ECN; | 394 | dev->features |= NETIF_F_TSO_ECN; |
395 | if (gso && vdev->config->feature(vdev, VIRTIO_NET_F_HOST_UFO)) | 395 | if (gso && virtio_has_feature(vdev, VIRTIO_NET_F_HOST_UFO)) |
396 | dev->features |= NETIF_F_UFO; | 396 | dev->features |= NETIF_F_UFO; |
397 | } | 397 | } |
398 | 398 | ||
399 | /* Configuration may specify what MAC to use. Otherwise random. */ | 399 | /* Configuration may specify what MAC to use. Otherwise random. */ |
400 | if (vdev->config->feature(vdev, VIRTIO_NET_F_MAC)) { | 400 | if (virtio_has_feature(vdev, VIRTIO_NET_F_MAC)) { |
401 | vdev->config->get(vdev, | 401 | vdev->config->get(vdev, |
402 | offsetof(struct virtio_net_config, mac), | 402 | offsetof(struct virtio_net_config, mac), |
403 | dev->dev_addr, dev->addr_len); | 403 | dev->dev_addr, dev->addr_len); |
@@ -486,7 +486,15 @@ static struct virtio_device_id id_table[] = { | |||
486 | { 0 }, | 486 | { 0 }, |
487 | }; | 487 | }; |
488 | 488 | ||
489 | static unsigned int features[] = { | ||
490 | 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, | ||
492 | VIRTIO_NET_F_HOST_ECN, | ||
493 | }; | ||
494 | |||
489 | static struct virtio_driver virtio_net = { | 495 | static struct virtio_driver virtio_net = { |
496 | .feature_table = features, | ||
497 | .feature_table_size = ARRAY_SIZE(features), | ||
490 | .driver.name = KBUILD_MODNAME, | 498 | .driver.name = KBUILD_MODNAME, |
491 | .driver.owner = THIS_MODULE, | 499 | .driver.owner = THIS_MODULE, |
492 | .id_table = id_table, | 500 | .id_table = id_table, |