Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.28-rc2 217 lines 6.1 kB view raw
1#include <linux/virtio.h> 2#include <linux/spinlock.h> 3#include <linux/virtio_config.h> 4 5/* Unique numbering for virtio devices. */ 6static unsigned int dev_index; 7 8static ssize_t device_show(struct device *_d, 9 struct device_attribute *attr, char *buf) 10{ 11 struct virtio_device *dev = container_of(_d,struct virtio_device,dev); 12 return sprintf(buf, "%hu", dev->id.device); 13} 14static ssize_t vendor_show(struct device *_d, 15 struct device_attribute *attr, char *buf) 16{ 17 struct virtio_device *dev = container_of(_d,struct virtio_device,dev); 18 return sprintf(buf, "%hu", dev->id.vendor); 19} 20static ssize_t status_show(struct device *_d, 21 struct device_attribute *attr, char *buf) 22{ 23 struct virtio_device *dev = container_of(_d,struct virtio_device,dev); 24 return sprintf(buf, "0x%08x", dev->config->get_status(dev)); 25} 26static ssize_t modalias_show(struct device *_d, 27 struct device_attribute *attr, char *buf) 28{ 29 struct virtio_device *dev = container_of(_d,struct virtio_device,dev); 30 31 return sprintf(buf, "virtio:d%08Xv%08X\n", 32 dev->id.device, dev->id.vendor); 33} 34static struct device_attribute virtio_dev_attrs[] = { 35 __ATTR_RO(device), 36 __ATTR_RO(vendor), 37 __ATTR_RO(status), 38 __ATTR_RO(modalias), 39 __ATTR_NULL 40}; 41 42static inline int virtio_id_match(const struct virtio_device *dev, 43 const struct virtio_device_id *id) 44{ 45 if (id->device != dev->id.device) 46 return 0; 47 48 return id->vendor == VIRTIO_DEV_ANY_ID || id->vendor != dev->id.vendor; 49} 50 51/* This looks through all the IDs a driver claims to support. If any of them 52 * match, we return 1 and the kernel will call virtio_dev_probe(). */ 53static int virtio_dev_match(struct device *_dv, struct device_driver *_dr) 54{ 55 unsigned int i; 56 struct virtio_device *dev = container_of(_dv,struct virtio_device,dev); 57 const struct virtio_device_id *ids; 58 59 ids = container_of(_dr, struct virtio_driver, driver)->id_table; 60 for (i = 0; ids[i].device; i++) 61 if (virtio_id_match(dev, &ids[i])) 62 return 1; 63 return 0; 64} 65 66static int virtio_uevent(struct device *_dv, struct kobj_uevent_env *env) 67{ 68 struct virtio_device *dev = container_of(_dv,struct virtio_device,dev); 69 70 return add_uevent_var(env, "MODALIAS=virtio:d%08Xv%08X", 71 dev->id.device, dev->id.vendor); 72} 73 74static void add_status(struct virtio_device *dev, unsigned status) 75{ 76 dev->config->set_status(dev, dev->config->get_status(dev) | status); 77} 78 79void virtio_check_driver_offered_feature(const struct virtio_device *vdev, 80 unsigned int fbit) 81{ 82 unsigned int i; 83 struct virtio_driver *drv = container_of(vdev->dev.driver, 84 struct virtio_driver, driver); 85 86 for (i = 0; i < drv->feature_table_size; i++) 87 if (drv->feature_table[i] == fbit) 88 return; 89 BUG(); 90} 91EXPORT_SYMBOL_GPL(virtio_check_driver_offered_feature); 92 93static int virtio_dev_probe(struct device *_d) 94{ 95 int err, i; 96 struct virtio_device *dev = container_of(_d,struct virtio_device,dev); 97 struct virtio_driver *drv = container_of(dev->dev.driver, 98 struct virtio_driver, driver); 99 u32 device_features; 100 101 /* We have a driver! */ 102 add_status(dev, VIRTIO_CONFIG_S_DRIVER); 103 104 /* Figure out what features the device supports. */ 105 device_features = dev->config->get_features(dev); 106 107 /* Features supported by both device and driver into dev->features. */ 108 memset(dev->features, 0, sizeof(dev->features)); 109 for (i = 0; i < drv->feature_table_size; i++) { 110 unsigned int f = drv->feature_table[i]; 111 BUG_ON(f >= 32); 112 if (device_features & (1 << f)) 113 set_bit(f, dev->features); 114 } 115 116 /* Transport features always preserved to pass to finalize_features. */ 117 for (i = VIRTIO_TRANSPORT_F_START; i < VIRTIO_TRANSPORT_F_END; i++) 118 if (device_features & (1 << i)) 119 set_bit(i, dev->features); 120 121 err = drv->probe(dev); 122 if (err) 123 add_status(dev, VIRTIO_CONFIG_S_FAILED); 124 else { 125 dev->config->finalize_features(dev); 126 add_status(dev, VIRTIO_CONFIG_S_DRIVER_OK); 127 } 128 return err; 129} 130 131static int virtio_dev_remove(struct device *_d) 132{ 133 struct virtio_device *dev = container_of(_d,struct virtio_device,dev); 134 struct virtio_driver *drv = container_of(dev->dev.driver, 135 struct virtio_driver, driver); 136 137 drv->remove(dev); 138 139 /* Driver should have reset device. */ 140 BUG_ON(dev->config->get_status(dev)); 141 142 /* Acknowledge the device's existence again. */ 143 add_status(dev, VIRTIO_CONFIG_S_ACKNOWLEDGE); 144 return 0; 145} 146 147static struct bus_type virtio_bus = { 148 .name = "virtio", 149 .match = virtio_dev_match, 150 .dev_attrs = virtio_dev_attrs, 151 .uevent = virtio_uevent, 152 .probe = virtio_dev_probe, 153 .remove = virtio_dev_remove, 154}; 155 156int register_virtio_driver(struct virtio_driver *driver) 157{ 158 /* Catch this early. */ 159 BUG_ON(driver->feature_table_size && !driver->feature_table); 160 driver->driver.bus = &virtio_bus; 161 return driver_register(&driver->driver); 162} 163EXPORT_SYMBOL_GPL(register_virtio_driver); 164 165void unregister_virtio_driver(struct virtio_driver *driver) 166{ 167 driver_unregister(&driver->driver); 168} 169EXPORT_SYMBOL_GPL(unregister_virtio_driver); 170 171int register_virtio_device(struct virtio_device *dev) 172{ 173 int err; 174 175 dev->dev.bus = &virtio_bus; 176 177 /* Assign a unique device index and hence name. */ 178 dev->index = dev_index++; 179 sprintf(dev->dev.bus_id, "virtio%u", dev->index); 180 181 /* We always start by resetting the device, in case a previous 182 * driver messed it up. This also tests that code path a little. */ 183 dev->config->reset(dev); 184 185 /* Acknowledge that we've seen the device. */ 186 add_status(dev, VIRTIO_CONFIG_S_ACKNOWLEDGE); 187 188 /* device_register() causes the bus infrastructure to look for a 189 * matching driver. */ 190 err = device_register(&dev->dev); 191 if (err) 192 add_status(dev, VIRTIO_CONFIG_S_FAILED); 193 return err; 194} 195EXPORT_SYMBOL_GPL(register_virtio_device); 196 197void unregister_virtio_device(struct virtio_device *dev) 198{ 199 device_unregister(&dev->dev); 200} 201EXPORT_SYMBOL_GPL(unregister_virtio_device); 202 203static int virtio_init(void) 204{ 205 if (bus_register(&virtio_bus) != 0) 206 panic("virtio bus registration failed"); 207 return 0; 208} 209 210static void __exit virtio_exit(void) 211{ 212 bus_unregister(&virtio_bus); 213} 214core_initcall(virtio_init); 215module_exit(virtio_exit); 216 217MODULE_LICENSE("GPL");