diff options
Diffstat (limited to 'drivers/virtio/virtio.c')
| -rw-r--r-- | drivers/virtio/virtio.c | 29 |
1 files changed, 24 insertions, 5 deletions
diff --git a/drivers/virtio/virtio.c b/drivers/virtio/virtio.c index 018c070a357f..3a43ebf83a49 100644 --- a/drivers/virtio/virtio.c +++ b/drivers/virtio/virtio.c | |||
| @@ -31,21 +31,37 @@ static ssize_t modalias_show(struct device *_d, | |||
| 31 | return sprintf(buf, "virtio:d%08Xv%08X\n", | 31 | return sprintf(buf, "virtio:d%08Xv%08X\n", |
| 32 | dev->id.device, dev->id.vendor); | 32 | dev->id.device, dev->id.vendor); |
| 33 | } | 33 | } |
| 34 | static ssize_t features_show(struct device *_d, | ||
| 35 | struct device_attribute *attr, char *buf) | ||
| 36 | { | ||
| 37 | struct virtio_device *dev = container_of(_d, struct virtio_device, dev); | ||
| 38 | unsigned int i; | ||
| 39 | ssize_t len = 0; | ||
| 40 | |||
| 41 | /* We actually represent this as a bitstring, as it could be | ||
| 42 | * arbitrary length in future. */ | ||
| 43 | for (i = 0; i < ARRAY_SIZE(dev->features)*BITS_PER_LONG; i++) | ||
| 44 | len += sprintf(buf+len, "%c", | ||
| 45 | test_bit(i, dev->features) ? '1' : '0'); | ||
| 46 | len += sprintf(buf+len, "\n"); | ||
| 47 | return len; | ||
| 48 | } | ||
| 34 | static struct device_attribute virtio_dev_attrs[] = { | 49 | static struct device_attribute virtio_dev_attrs[] = { |
| 35 | __ATTR_RO(device), | 50 | __ATTR_RO(device), |
| 36 | __ATTR_RO(vendor), | 51 | __ATTR_RO(vendor), |
| 37 | __ATTR_RO(status), | 52 | __ATTR_RO(status), |
| 38 | __ATTR_RO(modalias), | 53 | __ATTR_RO(modalias), |
| 54 | __ATTR_RO(features), | ||
| 39 | __ATTR_NULL | 55 | __ATTR_NULL |
| 40 | }; | 56 | }; |
| 41 | 57 | ||
| 42 | static inline int virtio_id_match(const struct virtio_device *dev, | 58 | static inline int virtio_id_match(const struct virtio_device *dev, |
| 43 | const struct virtio_device_id *id) | 59 | const struct virtio_device_id *id) |
| 44 | { | 60 | { |
| 45 | if (id->device != dev->id.device) | 61 | if (id->device != dev->id.device && id->device != VIRTIO_DEV_ANY_ID) |
| 46 | return 0; | 62 | return 0; |
| 47 | 63 | ||
| 48 | return id->vendor == VIRTIO_DEV_ANY_ID || id->vendor != dev->id.vendor; | 64 | return id->vendor == VIRTIO_DEV_ANY_ID || id->vendor == dev->id.vendor; |
| 49 | } | 65 | } |
| 50 | 66 | ||
| 51 | /* This looks through all the IDs a driver claims to support. If any of them | 67 | /* This looks through all the IDs a driver claims to support. If any of them |
| @@ -118,13 +134,14 @@ static int virtio_dev_probe(struct device *_d) | |||
| 118 | if (device_features & (1 << i)) | 134 | if (device_features & (1 << i)) |
| 119 | set_bit(i, dev->features); | 135 | set_bit(i, dev->features); |
| 120 | 136 | ||
| 137 | dev->config->finalize_features(dev); | ||
| 138 | |||
| 121 | err = drv->probe(dev); | 139 | err = drv->probe(dev); |
| 122 | if (err) | 140 | if (err) |
| 123 | add_status(dev, VIRTIO_CONFIG_S_FAILED); | 141 | add_status(dev, VIRTIO_CONFIG_S_FAILED); |
| 124 | else { | 142 | else |
| 125 | dev->config->finalize_features(dev); | ||
| 126 | add_status(dev, VIRTIO_CONFIG_S_DRIVER_OK); | 143 | add_status(dev, VIRTIO_CONFIG_S_DRIVER_OK); |
| 127 | } | 144 | |
| 128 | return err; | 145 | return err; |
| 129 | } | 146 | } |
| 130 | 147 | ||
| @@ -185,6 +202,8 @@ int register_virtio_device(struct virtio_device *dev) | |||
| 185 | /* Acknowledge that we've seen the device. */ | 202 | /* Acknowledge that we've seen the device. */ |
| 186 | add_status(dev, VIRTIO_CONFIG_S_ACKNOWLEDGE); | 203 | add_status(dev, VIRTIO_CONFIG_S_ACKNOWLEDGE); |
| 187 | 204 | ||
| 205 | INIT_LIST_HEAD(&dev->vqs); | ||
| 206 | |||
| 188 | /* device_register() causes the bus infrastructure to look for a | 207 | /* device_register() causes the bus infrastructure to look for a |
| 189 | * matching driver. */ | 208 | * matching driver. */ |
| 190 | err = device_register(&dev->dev); | 209 | err = device_register(&dev->dev); |
