diff options
author | Rusty Russell <rusty@rustcorp.com.au> | 2008-02-04 23:49:56 -0500 |
---|---|---|
committer | Rusty Russell <rusty@rustcorp.com.au> | 2008-02-04 07:49:57 -0500 |
commit | a586d4f6016f7139d8c26df0e6927131168d3b5b (patch) | |
tree | 1c47e1a6b6b8fb18baa42f32980f29c4ae9cbbdc | |
parent | f35d9d8aae08940b7fdd1bb8110619da2ece6b28 (diff) |
virtio: simplify config mechanism.
Previously we used a type/len pair within the config space, but this
seems overkill. We now simply define a structure which represents the
layout in the config space: the config space can now only be extended
at the end.
The main driver-visible changes:
1) We indicate what fields are present with an explicit feature bit.
2) Virtqueues are explicitly numbered, and not in the config space.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
-rw-r--r-- | Documentation/lguest/lguest.c | 176 | ||||
-rw-r--r-- | drivers/block/virtio_blk.c | 35 | ||||
-rw-r--r-- | drivers/char/virtio_console.c | 4 | ||||
-rw-r--r-- | drivers/lguest/lguest_device.c | 132 | ||||
-rw-r--r-- | drivers/net/virtio_net.c | 25 | ||||
-rw-r--r-- | drivers/virtio/virtio.c | 45 | ||||
-rw-r--r-- | include/linux/lguest_launcher.h | 9 | ||||
-rw-r--r-- | include/linux/virtio_blk.h | 22 | ||||
-rw-r--r-- | include/linux/virtio_config.h | 98 | ||||
-rw-r--r-- | include/linux/virtio_net.h | 11 | ||||
-rw-r--r-- | net/9p/trans_virtio.c | 4 |
11 files changed, 280 insertions, 281 deletions
diff --git a/Documentation/lguest/lguest.c b/Documentation/lguest/lguest.c index 6c8a2386cd50..4df1804169dc 100644 --- a/Documentation/lguest/lguest.c +++ b/Documentation/lguest/lguest.c | |||
@@ -34,6 +34,8 @@ | |||
34 | #include <zlib.h> | 34 | #include <zlib.h> |
35 | #include <assert.h> | 35 | #include <assert.h> |
36 | #include <sched.h> | 36 | #include <sched.h> |
37 | #include <limits.h> | ||
38 | #include <stddef.h> | ||
37 | #include "linux/lguest_launcher.h" | 39 | #include "linux/lguest_launcher.h" |
38 | #include "linux/virtio_config.h" | 40 | #include "linux/virtio_config.h" |
39 | #include "linux/virtio_net.h" | 41 | #include "linux/virtio_net.h" |
@@ -99,13 +101,11 @@ struct device_list | |||
99 | /* The descriptor page for the devices. */ | 101 | /* The descriptor page for the devices. */ |
100 | u8 *descpage; | 102 | u8 *descpage; |
101 | 103 | ||
102 | /* The tail of the last descriptor. */ | ||
103 | unsigned int desc_used; | ||
104 | |||
105 | /* A single linked list of devices. */ | 104 | /* A single linked list of devices. */ |
106 | struct device *dev; | 105 | struct device *dev; |
107 | /* ... And an end pointer so we can easily append new devices */ | 106 | /* And a pointer to the last device for easy append and also for |
108 | struct device **lastdev; | 107 | * configuration appending. */ |
108 | struct device *lastdev; | ||
109 | }; | 109 | }; |
110 | 110 | ||
111 | /* The list of Guest devices, based on command line arguments. */ | 111 | /* The list of Guest devices, based on command line arguments. */ |
@@ -191,7 +191,7 @@ static void *_convert(struct iovec *iov, size_t size, size_t align, | |||
191 | #define cpu_to_le64(v64) (v64) | 191 | #define cpu_to_le64(v64) (v64) |
192 | #define le16_to_cpu(v16) (v16) | 192 | #define le16_to_cpu(v16) (v16) |
193 | #define le32_to_cpu(v32) (v32) | 193 | #define le32_to_cpu(v32) (v32) |
194 | #define le64_to_cpu(v32) (v64) | 194 | #define le64_to_cpu(v64) (v64) |
195 | 195 | ||
196 | /*L:100 The Launcher code itself takes us out into userspace, that scary place | 196 | /*L:100 The Launcher code itself takes us out into userspace, that scary place |
197 | * where pointers run wild and free! Unfortunately, like most userspace | 197 | * where pointers run wild and free! Unfortunately, like most userspace |
@@ -986,54 +986,44 @@ static void handle_input(int fd) | |||
986 | * | 986 | * |
987 | * All devices need a descriptor so the Guest knows it exists, and a "struct | 987 | * All devices need a descriptor so the Guest knows it exists, and a "struct |
988 | * device" so the Launcher can keep track of it. We have common helper | 988 | * device" so the Launcher can keep track of it. We have common helper |
989 | * routines to allocate them. | 989 | * routines to allocate and manage them. */ |
990 | * | ||
991 | * This routine allocates a new "struct lguest_device_desc" from descriptor | ||
992 | * table just above the Guest's normal memory. It returns a pointer to that | ||
993 | * descriptor. */ | ||
994 | static struct lguest_device_desc *new_dev_desc(u16 type) | ||
995 | { | ||
996 | struct lguest_device_desc *d; | ||
997 | 990 | ||
998 | /* We only have one page for all the descriptors. */ | 991 | /* The layout of the device page is a "struct lguest_device_desc" followed by a |
999 | if (devices.desc_used + sizeof(*d) > getpagesize()) | 992 | * number of virtqueue descriptors, then two sets of feature bits, then an |
1000 | errx(1, "Too many devices"); | 993 | * array of configuration bytes. This routine returns the configuration |
1001 | 994 | * pointer. */ | |
1002 | /* We don't need to set config_len or status: page is 0 already. */ | 995 | static u8 *device_config(const struct device *dev) |
1003 | d = (void *)devices.descpage + devices.desc_used; | 996 | { |
1004 | d->type = type; | 997 | return (void *)(dev->desc + 1) |
1005 | devices.desc_used += sizeof(*d); | 998 | + dev->desc->num_vq * sizeof(struct lguest_vqconfig) |
1006 | 999 | + dev->desc->feature_len * 2; | |
1007 | return d; | ||
1008 | } | 1000 | } |
1009 | 1001 | ||
1010 | /* Each device descriptor is followed by some configuration information. | 1002 | /* This routine allocates a new "struct lguest_device_desc" from descriptor |
1011 | * Each configuration field looks like: u8 type, u8 len, [... len bytes...]. | 1003 | * table page just above the Guest's normal memory. It returns a pointer to |
1012 | * | 1004 | * that descriptor. */ |
1013 | * This routine adds a new field to an existing device's descriptor. It only | 1005 | static struct lguest_device_desc *new_dev_desc(u16 type) |
1014 | * works for the last device, but that's OK because that's how we use it. */ | ||
1015 | static void add_desc_field(struct device *dev, u8 type, u8 len, const void *c) | ||
1016 | { | 1006 | { |
1017 | /* This is the last descriptor, right? */ | 1007 | struct lguest_device_desc d = { .type = type }; |
1018 | assert(devices.descpage + devices.desc_used | 1008 | void *p; |
1019 | == (u8 *)(dev->desc + 1) + dev->desc->config_len); | ||
1020 | 1009 | ||
1021 | /* We only have one page of device descriptions. */ | 1010 | /* Figure out where the next device config is, based on the last one. */ |
1022 | if (devices.desc_used + 2 + len > getpagesize()) | 1011 | if (devices.lastdev) |
1023 | errx(1, "Too many devices"); | 1012 | p = device_config(devices.lastdev) |
1013 | + devices.lastdev->desc->config_len; | ||
1014 | else | ||
1015 | p = devices.descpage; | ||
1024 | 1016 | ||
1025 | /* Copy in the new config header: type then length. */ | 1017 | /* We only have one page for all the descriptors. */ |
1026 | devices.descpage[devices.desc_used++] = type; | 1018 | if (p + sizeof(d) > (void *)devices.descpage + getpagesize()) |
1027 | devices.descpage[devices.desc_used++] = len; | 1019 | errx(1, "Too many devices"); |
1028 | memcpy(devices.descpage + devices.desc_used, c, len); | ||
1029 | devices.desc_used += len; | ||
1030 | 1020 | ||
1031 | /* Update the device descriptor length: two byte head then data. */ | 1021 | /* p might not be aligned, so we memcpy in. */ |
1032 | dev->desc->config_len += 2 + len; | 1022 | return memcpy(p, &d, sizeof(d)); |
1033 | } | 1023 | } |
1034 | 1024 | ||
1035 | /* This routine adds a virtqueue to a device. We specify how many descriptors | 1025 | /* Each device descriptor is followed by the description of its virtqueues. We |
1036 | * the virtqueue is to have. */ | 1026 | * specify how many descriptors the virtqueue is to have. */ |
1037 | static void add_virtqueue(struct device *dev, unsigned int num_descs, | 1027 | static void add_virtqueue(struct device *dev, unsigned int num_descs, |
1038 | void (*handle_output)(int fd, struct virtqueue *me)) | 1028 | void (*handle_output)(int fd, struct virtqueue *me)) |
1039 | { | 1029 | { |
@@ -1059,9 +1049,15 @@ static void add_virtqueue(struct device *dev, unsigned int num_descs, | |||
1059 | /* Initialize the vring. */ | 1049 | /* Initialize the vring. */ |
1060 | vring_init(&vq->vring, num_descs, p, getpagesize()); | 1050 | vring_init(&vq->vring, num_descs, p, getpagesize()); |
1061 | 1051 | ||
1062 | /* Add the configuration information to this device's descriptor. */ | 1052 | /* Append virtqueue to this device's descriptor. We use |
1063 | add_desc_field(dev, VIRTIO_CONFIG_F_VIRTQUEUE, | 1053 | * device_config() to get the end of the device's current virtqueues; |
1064 | sizeof(vq->config), &vq->config); | 1054 | * we check that we haven't added any config or feature information |
1055 | * yet, otherwise we'd be overwriting them. */ | ||
1056 | assert(dev->desc->config_len == 0 && dev->desc->feature_len == 0); | ||
1057 | memcpy(device_config(dev), &vq->config, sizeof(vq->config)); | ||
1058 | dev->desc->num_vq++; | ||
1059 | |||
1060 | verbose("Virtqueue page %#lx\n", to_guest_phys(p)); | ||
1065 | 1061 | ||
1066 | /* Add to tail of list, so dev->vq is first vq, dev->vq->next is | 1062 | /* Add to tail of list, so dev->vq is first vq, dev->vq->next is |
1067 | * second. */ | 1063 | * second. */ |
@@ -1077,6 +1073,37 @@ static void add_virtqueue(struct device *dev, unsigned int num_descs, | |||
1077 | vq->vring.used->flags = VRING_USED_F_NO_NOTIFY; | 1073 | vq->vring.used->flags = VRING_USED_F_NO_NOTIFY; |
1078 | } | 1074 | } |
1079 | 1075 | ||
1076 | /* The virtqueue descriptors are followed by feature bytes. */ | ||
1077 | static void add_feature(struct device *dev, unsigned bit) | ||
1078 | { | ||
1079 | u8 *features; | ||
1080 | |||
1081 | /* We can't extend the feature bits once we've added config bytes */ | ||
1082 | if (dev->desc->feature_len <= bit / CHAR_BIT) { | ||
1083 | assert(dev->desc->config_len == 0); | ||
1084 | dev->desc->feature_len = (bit / CHAR_BIT) + 1; | ||
1085 | } | ||
1086 | |||
1087 | features = (u8 *)(dev->desc + 1) | ||
1088 | + dev->desc->num_vq * sizeof(struct lguest_vqconfig); | ||
1089 | |||
1090 | features[bit / CHAR_BIT] |= (1 << (bit % CHAR_BIT)); | ||
1091 | } | ||
1092 | |||
1093 | /* This routine sets the configuration fields for an existing device's | ||
1094 | * descriptor. It only works for the last device, but that's OK because that's | ||
1095 | * how we use it. */ | ||
1096 | static void set_config(struct device *dev, unsigned len, const void *conf) | ||
1097 | { | ||
1098 | /* Check we haven't overflowed our single page. */ | ||
1099 | if (device_config(dev) + len > devices.descpage + getpagesize()) | ||
1100 | errx(1, "Too many devices"); | ||
1101 | |||
1102 | /* Copy in the config information, and store the length. */ | ||
1103 | memcpy(device_config(dev), conf, len); | ||
1104 | dev->desc->config_len = len; | ||
1105 | } | ||
1106 | |||
1080 | /* This routine does all the creation and setup of a new device, including | 1107 | /* This routine does all the creation and setup of a new device, including |
1081 | * calling new_dev_desc() to allocate the descriptor and device memory. */ | 1108 | * calling new_dev_desc() to allocate the descriptor and device memory. */ |
1082 | static struct device *new_device(const char *name, u16 type, int fd, | 1109 | static struct device *new_device(const char *name, u16 type, int fd, |
@@ -1084,14 +1111,6 @@ static struct device *new_device(const char *name, u16 type, int fd, | |||
1084 | { | 1111 | { |
1085 | struct device *dev = malloc(sizeof(*dev)); | 1112 | struct device *dev = malloc(sizeof(*dev)); |
1086 | 1113 | ||
1087 | /* Append to device list. Prepending to a single-linked list is | ||
1088 | * easier, but the user expects the devices to be arranged on the bus | ||
1089 | * in command-line order. The first network device on the command line | ||
1090 | * is eth0, the first block device /dev/vda, etc. */ | ||
1091 | *devices.lastdev = dev; | ||
1092 | dev->next = NULL; | ||
1093 | devices.lastdev = &dev->next; | ||
1094 | |||
1095 | /* Now we populate the fields one at a time. */ | 1114 | /* Now we populate the fields one at a time. */ |
1096 | dev->fd = fd; | 1115 | dev->fd = fd; |
1097 | /* If we have an input handler for this file descriptor, then we add it | 1116 | /* If we have an input handler for this file descriptor, then we add it |
@@ -1102,6 +1121,17 @@ static struct device *new_device(const char *name, u16 type, int fd, | |||
1102 | dev->handle_input = handle_input; | 1121 | dev->handle_input = handle_input; |
1103 | dev->name = name; | 1122 | dev->name = name; |
1104 | dev->vq = NULL; | 1123 | dev->vq = NULL; |
1124 | |||
1125 | /* Append to device list. Prepending to a single-linked list is | ||
1126 | * easier, but the user expects the devices to be arranged on the bus | ||
1127 | * in command-line order. The first network device on the command line | ||
1128 | * is eth0, the first block device /dev/vda, etc. */ | ||
1129 | if (devices.lastdev) | ||
1130 | devices.lastdev->next = dev; | ||
1131 | else | ||
1132 | devices.dev = dev; | ||
1133 | devices.lastdev = dev; | ||
1134 | |||
1105 | return dev; | 1135 | return dev; |
1106 | } | 1136 | } |
1107 | 1137 | ||
@@ -1226,7 +1256,7 @@ static void setup_tun_net(const char *arg) | |||
1226 | int netfd, ipfd; | 1256 | int netfd, ipfd; |
1227 | u32 ip; | 1257 | u32 ip; |
1228 | const char *br_name = NULL; | 1258 | const char *br_name = NULL; |
1229 | u8 hwaddr[6]; | 1259 | struct virtio_net_config conf; |
1230 | 1260 | ||
1231 | /* We open the /dev/net/tun device and tell it we want a tap device. A | 1261 | /* We open the /dev/net/tun device and tell it we want a tap device. A |
1232 | * tap device is like a tun device, only somehow different. To tell | 1262 | * tap device is like a tun device, only somehow different. To tell |
@@ -1265,12 +1295,13 @@ static void setup_tun_net(const char *arg) | |||
1265 | ip = str2ip(arg); | 1295 | ip = str2ip(arg); |
1266 | 1296 | ||
1267 | /* Set up the tun device, and get the mac address for the interface. */ | 1297 | /* Set up the tun device, and get the mac address for the interface. */ |
1268 | configure_device(ipfd, ifr.ifr_name, ip, hwaddr); | 1298 | configure_device(ipfd, ifr.ifr_name, ip, conf.mac); |
1269 | 1299 | ||
1270 | /* Tell Guest what MAC address to use. */ | 1300 | /* Tell Guest what MAC address to use. */ |
1271 | add_desc_field(dev, VIRTIO_CONFIG_NET_MAC_F, sizeof(hwaddr), hwaddr); | 1301 | add_feature(dev, VIRTIO_NET_F_MAC); |
1302 | set_config(dev, sizeof(conf), &conf); | ||
1272 | 1303 | ||
1273 | /* We don't seed the socket any more; setup is done. */ | 1304 | /* We don't need the socket any more; setup is done. */ |
1274 | close(ipfd); | 1305 | close(ipfd); |
1275 | 1306 | ||
1276 | verbose("device %u: tun net %u.%u.%u.%u\n", | 1307 | verbose("device %u: tun net %u.%u.%u.%u\n", |
@@ -1458,8 +1489,7 @@ static void setup_block_file(const char *filename) | |||
1458 | struct device *dev; | 1489 | struct device *dev; |
1459 | struct vblk_info *vblk; | 1490 | struct vblk_info *vblk; |
1460 | void *stack; | 1491 | void *stack; |
1461 | u64 cap; | 1492 | struct virtio_blk_config conf; |
1462 | unsigned int val; | ||
1463 | 1493 | ||
1464 | /* This is the pipe the I/O thread will use to tell us I/O is done. */ | 1494 | /* This is the pipe the I/O thread will use to tell us I/O is done. */ |
1465 | pipe(p); | 1495 | pipe(p); |
@@ -1477,14 +1507,18 @@ static void setup_block_file(const char *filename) | |||
1477 | vblk->fd = open_or_die(filename, O_RDWR|O_LARGEFILE); | 1507 | vblk->fd = open_or_die(filename, O_RDWR|O_LARGEFILE); |
1478 | vblk->len = lseek64(vblk->fd, 0, SEEK_END); | 1508 | vblk->len = lseek64(vblk->fd, 0, SEEK_END); |
1479 | 1509 | ||
1510 | /* We support barriers. */ | ||
1511 | add_feature(dev, VIRTIO_BLK_F_BARRIER); | ||
1512 | |||
1480 | /* Tell Guest how many sectors this device has. */ | 1513 | /* Tell Guest how many sectors this device has. */ |
1481 | cap = cpu_to_le64(vblk->len / 512); | 1514 | conf.capacity = cpu_to_le64(vblk->len / 512); |
1482 | add_desc_field(dev, VIRTIO_CONFIG_BLK_F_CAPACITY, sizeof(cap), &cap); | ||
1483 | 1515 | ||
1484 | /* Tell Guest not to put in too many descriptors at once: two are used | 1516 | /* Tell Guest not to put in too many descriptors at once: two are used |
1485 | * for the in and out elements. */ | 1517 | * for the in and out elements. */ |
1486 | val = cpu_to_le32(VIRTQUEUE_NUM - 2); | 1518 | add_feature(dev, VIRTIO_BLK_F_SEG_MAX); |
1487 | add_desc_field(dev, VIRTIO_CONFIG_BLK_F_SEG_MAX, sizeof(val), &val); | 1519 | conf.seg_max = cpu_to_le32(VIRTQUEUE_NUM - 2); |
1520 | |||
1521 | set_config(dev, sizeof(conf), &conf); | ||
1488 | 1522 | ||
1489 | /* The I/O thread writes to this end of the pipe when done. */ | 1523 | /* The I/O thread writes to this end of the pipe when done. */ |
1490 | vblk->done_fd = p[1]; | 1524 | vblk->done_fd = p[1]; |
@@ -1505,7 +1539,7 @@ static void setup_block_file(const char *filename) | |||
1505 | close(vblk->workpipe[0]); | 1539 | close(vblk->workpipe[0]); |
1506 | 1540 | ||
1507 | verbose("device %u: virtblock %llu sectors\n", | 1541 | verbose("device %u: virtblock %llu sectors\n", |
1508 | devices.device_num, cap); | 1542 | devices.device_num, le64_to_cpu(conf.capacity)); |
1509 | } | 1543 | } |
1510 | /* That's the end of device setup. :*/ | 1544 | /* That's the end of device setup. :*/ |
1511 | 1545 | ||
@@ -1610,12 +1644,12 @@ int main(int argc, char *argv[]) | |||
1610 | /* First we initialize the device list. Since console and network | 1644 | /* First we initialize the device list. Since console and network |
1611 | * device receive input from a file descriptor, we keep an fdset | 1645 | * device receive input from a file descriptor, we keep an fdset |
1612 | * (infds) and the maximum fd number (max_infd) with the head of the | 1646 | * (infds) and the maximum fd number (max_infd) with the head of the |
1613 | * list. We also keep a pointer to the last device, for easy appending | 1647 | * list. We also keep a pointer to the last device. Finally, we keep |
1614 | * to the list. Finally, we keep the next interrupt number to hand out | 1648 | * the next interrupt number to hand out (1: remember that 0 is used by |
1615 | * (1: remember that 0 is used by the timer). */ | 1649 | * the timer). */ |
1616 | FD_ZERO(&devices.infds); | 1650 | FD_ZERO(&devices.infds); |
1617 | devices.max_infd = -1; | 1651 | devices.max_infd = -1; |
1618 | devices.lastdev = &devices.dev; | 1652 | devices.lastdev = NULL; |
1619 | devices.next_irq = 1; | 1653 | devices.next_irq = 1; |
1620 | 1654 | ||
1621 | cpu_id = 0; | 1655 | cpu_id = 0; |
diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c index 924ddd8bccd2..1c63d5b64c20 100644 --- a/drivers/block/virtio_blk.c +++ b/drivers/block/virtio_blk.c | |||
@@ -162,8 +162,6 @@ static int virtblk_probe(struct virtio_device *vdev) | |||
162 | { | 162 | { |
163 | struct virtio_blk *vblk; | 163 | struct virtio_blk *vblk; |
164 | int err, major; | 164 | int err, major; |
165 | void *token; | ||
166 | unsigned int len; | ||
167 | u64 cap; | 165 | u64 cap; |
168 | u32 v; | 166 | u32 v; |
169 | 167 | ||
@@ -178,7 +176,7 @@ static int virtblk_probe(struct virtio_device *vdev) | |||
178 | vblk->vdev = vdev; | 176 | vblk->vdev = vdev; |
179 | 177 | ||
180 | /* We expect one virtqueue, for output. */ | 178 | /* We expect one virtqueue, for output. */ |
181 | vblk->vq = vdev->config->find_vq(vdev, blk_done); | 179 | vblk->vq = vdev->config->find_vq(vdev, 0, blk_done); |
182 | if (IS_ERR(vblk->vq)) { | 180 | if (IS_ERR(vblk->vq)) { |
183 | err = PTR_ERR(vblk->vq); | 181 | err = PTR_ERR(vblk->vq); |
184 | goto out_free_vblk; | 182 | goto out_free_vblk; |
@@ -216,15 +214,12 @@ static int virtblk_probe(struct virtio_device *vdev) | |||
216 | vblk->disk->fops = &virtblk_fops; | 214 | vblk->disk->fops = &virtblk_fops; |
217 | 215 | ||
218 | /* If barriers are supported, tell block layer that queue is ordered */ | 216 | /* If barriers are supported, tell block layer that queue is ordered */ |
219 | token = vdev->config->find(vdev, VIRTIO_CONFIG_BLK_F, &len); | 217 | if (vdev->config->feature(vdev, VIRTIO_BLK_F_BARRIER)) |
220 | if (virtio_use_bit(vdev, token, len, VIRTIO_BLK_F_BARRIER)) | ||
221 | blk_queue_ordered(vblk->disk->queue, QUEUE_ORDERED_TAG, NULL); | 218 | blk_queue_ordered(vblk->disk->queue, QUEUE_ORDERED_TAG, NULL); |
222 | 219 | ||
223 | err = virtio_config_val(vdev, VIRTIO_CONFIG_BLK_F_CAPACITY, &cap); | 220 | /* Host must always specify the capacity. */ |
224 | if (err) { | 221 | __virtio_config_val(vdev, offsetof(struct virtio_blk_config, capacity), |
225 | dev_err(&vdev->dev, "Bad/missing capacity in config\n"); | 222 | &cap); |
226 | goto out_cleanup_queue; | ||
227 | } | ||
228 | 223 | ||
229 | /* If capacity is too big, truncate with warning. */ | 224 | /* If capacity is too big, truncate with warning. */ |
230 | if ((sector_t)cap != cap) { | 225 | if ((sector_t)cap != cap) { |
@@ -234,27 +229,23 @@ static int virtblk_probe(struct virtio_device *vdev) | |||
234 | } | 229 | } |
235 | set_capacity(vblk->disk, cap); | 230 | set_capacity(vblk->disk, cap); |
236 | 231 | ||
237 | err = virtio_config_val(vdev, VIRTIO_CONFIG_BLK_F_SIZE_MAX, &v); | 232 | /* Host can optionally specify maximum segment size and number of |
233 | * segments. */ | ||
234 | err = virtio_config_val(vdev, VIRTIO_BLK_F_SIZE_MAX, | ||
235 | offsetof(struct virtio_blk_config, size_max), | ||
236 | &v); | ||
238 | if (!err) | 237 | if (!err) |
239 | blk_queue_max_segment_size(vblk->disk->queue, v); | 238 | blk_queue_max_segment_size(vblk->disk->queue, v); |
240 | else if (err != -ENOENT) { | ||
241 | dev_err(&vdev->dev, "Bad SIZE_MAX in config\n"); | ||
242 | goto out_cleanup_queue; | ||
243 | } | ||
244 | 239 | ||
245 | err = virtio_config_val(vdev, VIRTIO_CONFIG_BLK_F_SEG_MAX, &v); | 240 | err = virtio_config_val(vdev, VIRTIO_BLK_F_SEG_MAX, |
241 | offsetof(struct virtio_blk_config, seg_max), | ||
242 | &v); | ||
246 | if (!err) | 243 | if (!err) |
247 | blk_queue_max_hw_segments(vblk->disk->queue, v); | 244 | blk_queue_max_hw_segments(vblk->disk->queue, v); |
248 | else if (err != -ENOENT) { | ||
249 | dev_err(&vdev->dev, "Bad SEG_MAX in config\n"); | ||
250 | goto out_cleanup_queue; | ||
251 | } | ||
252 | 245 | ||
253 | add_disk(vblk->disk); | 246 | add_disk(vblk->disk); |
254 | return 0; | 247 | return 0; |
255 | 248 | ||
256 | out_cleanup_queue: | ||
257 | blk_cleanup_queue(vblk->disk->queue); | ||
258 | out_put_disk: | 249 | out_put_disk: |
259 | put_disk(vblk->disk); | 250 | put_disk(vblk->disk); |
260 | out_unregister_blkdev: | 251 | out_unregister_blkdev: |
diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c index e34da5c97196..dc17fe3a88bc 100644 --- a/drivers/char/virtio_console.c +++ b/drivers/char/virtio_console.c | |||
@@ -158,13 +158,13 @@ static int __devinit virtcons_probe(struct virtio_device *dev) | |||
158 | /* Find the input queue. */ | 158 | /* Find the input queue. */ |
159 | /* FIXME: This is why we want to wean off hvc: we do nothing | 159 | /* FIXME: This is why we want to wean off hvc: we do nothing |
160 | * when input comes in. */ | 160 | * when input comes in. */ |
161 | in_vq = vdev->config->find_vq(vdev, NULL); | 161 | in_vq = vdev->config->find_vq(vdev, 0, NULL); |
162 | if (IS_ERR(in_vq)) { | 162 | if (IS_ERR(in_vq)) { |
163 | err = PTR_ERR(in_vq); | 163 | err = PTR_ERR(in_vq); |
164 | goto free; | 164 | goto free; |
165 | } | 165 | } |
166 | 166 | ||
167 | out_vq = vdev->config->find_vq(vdev, NULL); | 167 | out_vq = vdev->config->find_vq(vdev, 1, NULL); |
168 | if (IS_ERR(out_vq)) { | 168 | if (IS_ERR(out_vq)) { |
169 | err = PTR_ERR(out_vq); | 169 | err = PTR_ERR(out_vq); |
170 | goto free_in_vq; | 170 | goto free_in_vq; |
diff --git a/drivers/lguest/lguest_device.c b/drivers/lguest/lguest_device.c index e2eec38c83c2..07f57a53658b 100644 --- a/drivers/lguest/lguest_device.c +++ b/drivers/lguest/lguest_device.c | |||
@@ -52,57 +52,82 @@ struct lguest_device { | |||
52 | /*D:130 | 52 | /*D:130 |
53 | * Device configurations | 53 | * Device configurations |
54 | * | 54 | * |
55 | * The configuration information for a device consists of a series of fields. | 55 | * The configuration information for a device consists of one or more |
56 | * We don't really care what they are: the Launcher set them up, and the driver | 56 | * virtqueues, a feature bitmaks, and some configuration bytes. The |
57 | * will look at them during setup. | 57 | * configuration bytes don't really matter to us: the Launcher set them up, and |
58 | * the driver will look at them during setup. | ||
58 | * | 59 | * |
59 | * For us these fields come immediately after that device's descriptor in the | 60 | * A convenient routine to return the device's virtqueue config array: |
60 | * lguest_devices page. | 61 | * immediately after the descriptor. */ |
61 | * | 62 | static struct lguest_vqconfig *lg_vq(const struct lguest_device_desc *desc) |
62 | * Each field starts with a "type" byte, a "length" byte, then that number of | 63 | { |
63 | * bytes of configuration information. The device descriptor tells us the | 64 | return (void *)(desc + 1); |
64 | * total configuration length so we know when we've reached the last field. */ | 65 | } |
65 | 66 | ||
66 | /* type + length bytes */ | 67 | /* The features come immediately after the virtqueues. */ |
67 | #define FHDR_LEN 2 | 68 | static u8 *lg_features(const struct lguest_device_desc *desc) |
69 | { | ||
70 | return (void *)(lg_vq(desc) + desc->num_vq); | ||
71 | } | ||
68 | 72 | ||
69 | /* This finds the first field of a given type for a device's configuration. */ | 73 | /* The config space comes after the two feature bitmasks. */ |
70 | static void *lg_find(struct virtio_device *vdev, u8 type, unsigned int *len) | 74 | static u8 *lg_config(const struct lguest_device_desc *desc) |
71 | { | 75 | { |
72 | struct lguest_device_desc *desc = to_lgdev(vdev)->desc; | 76 | return lg_features(desc) + desc->feature_len * 2; |
73 | int i; | 77 | } |
74 | |||
75 | for (i = 0; i < desc->config_len; i += FHDR_LEN + desc->config[i+1]) { | ||
76 | if (desc->config[i] == type) { | ||
77 | /* Mark it used, so Host can know we looked at it, and | ||
78 | * also so we won't find the same one twice. */ | ||
79 | desc->config[i] |= 0x80; | ||
80 | /* Remember, the second byte is the length. */ | ||
81 | *len = desc->config[i+1]; | ||
82 | /* We return a pointer to the field header. */ | ||
83 | return desc->config + i; | ||
84 | } | ||
85 | } | ||
86 | 78 | ||
87 | /* Not found: return NULL for failure. */ | 79 | /* The total size of the config page used by this device (incl. desc) */ |
88 | return NULL; | 80 | static unsigned desc_size(const struct lguest_device_desc *desc) |
81 | { | ||
82 | return sizeof(*desc) | ||
83 | + desc->num_vq * sizeof(struct lguest_vqconfig) | ||
84 | + desc->feature_len * 2 | ||
85 | + desc->config_len; | ||
86 | } | ||
87 | |||
88 | /* This tests (and acknowleges) a feature bit. */ | ||
89 | static bool lg_feature(struct virtio_device *vdev, unsigned fbit) | ||
90 | { | ||
91 | struct lguest_device_desc *desc = to_lgdev(vdev)->desc; | ||
92 | u8 *features; | ||
93 | |||
94 | /* Obviously if they ask for a feature off the end of our feature | ||
95 | * bitmap, it's not set. */ | ||
96 | if (fbit / 8 > desc->feature_len) | ||
97 | return false; | ||
98 | |||
99 | /* The feature bitmap comes after the virtqueues. */ | ||
100 | features = lg_features(desc); | ||
101 | if (!(features[fbit / 8] & (1 << (fbit % 8)))) | ||
102 | return false; | ||
103 | |||
104 | /* We set the matching bit in the other half of the bitmap to tell the | ||
105 | * Host we want to use this feature. We don't use this yet, but we | ||
106 | * could in future. */ | ||
107 | features[desc->feature_len + fbit / 8] |= (1 << (fbit % 8)); | ||
108 | return true; | ||
89 | } | 109 | } |
90 | 110 | ||
91 | /* Once they've found a field, getting a copy of it is easy. */ | 111 | /* Once they've found a field, getting a copy of it is easy. */ |
92 | static void lg_get(struct virtio_device *vdev, void *token, | 112 | static void lg_get(struct virtio_device *vdev, unsigned int offset, |
93 | void *buf, unsigned len) | 113 | void *buf, unsigned len) |
94 | { | 114 | { |
95 | /* Check they didn't ask for more than the length of the field! */ | 115 | struct lguest_device_desc *desc = to_lgdev(vdev)->desc; |
96 | BUG_ON(len > ((u8 *)token)[1]); | 116 | |
97 | memcpy(buf, token + FHDR_LEN, len); | 117 | /* Check they didn't ask for more than the length of the config! */ |
118 | BUG_ON(offset + len > desc->config_len); | ||
119 | memcpy(buf, lg_config(desc) + offset, len); | ||
98 | } | 120 | } |
99 | 121 | ||
100 | /* Setting the contents is also trivial. */ | 122 | /* Setting the contents is also trivial. */ |
101 | static void lg_set(struct virtio_device *vdev, void *token, | 123 | static void lg_set(struct virtio_device *vdev, unsigned int offset, |
102 | const void *buf, unsigned len) | 124 | const void *buf, unsigned len) |
103 | { | 125 | { |
104 | BUG_ON(len > ((u8 *)token)[1]); | 126 | struct lguest_device_desc *desc = to_lgdev(vdev)->desc; |
105 | memcpy(token + FHDR_LEN, buf, len); | 127 | |
128 | /* Check they didn't ask for more than the length of the config! */ | ||
129 | BUG_ON(offset + len > desc->config_len); | ||
130 | memcpy(lg_config(desc) + offset, buf, len); | ||
106 | } | 131 | } |
107 | 132 | ||
108 | /* The operations to get and set the status word just access the status field | 133 | /* The operations to get and set the status word just access the status field |
@@ -165,39 +190,29 @@ static void lg_notify(struct virtqueue *vq) | |||
165 | * | 190 | * |
166 | * So we provide devices with a "find virtqueue and set it up" function. */ | 191 | * So we provide devices with a "find virtqueue and set it up" function. */ |
167 | static struct virtqueue *lg_find_vq(struct virtio_device *vdev, | 192 | static struct virtqueue *lg_find_vq(struct virtio_device *vdev, |
193 | unsigned index, | ||
168 | bool (*callback)(struct virtqueue *vq)) | 194 | bool (*callback)(struct virtqueue *vq)) |
169 | { | 195 | { |
196 | struct lguest_device *ldev = to_lgdev(vdev); | ||
170 | struct lguest_vq_info *lvq; | 197 | struct lguest_vq_info *lvq; |
171 | struct virtqueue *vq; | 198 | struct virtqueue *vq; |
172 | unsigned int len; | ||
173 | void *token; | ||
174 | int err; | 199 | int err; |
175 | 200 | ||
176 | /* Look for a field of the correct type to mark a virtqueue. Note that | 201 | /* We must have this many virtqueues. */ |
177 | * if this succeeds, then the type will be changed so it won't be found | 202 | if (index >= ldev->desc->num_vq) |
178 | * again, and future lg_find_vq() calls will find the next | ||
179 | * virtqueue (if any). */ | ||
180 | token = vdev->config->find(vdev, VIRTIO_CONFIG_F_VIRTQUEUE, &len); | ||
181 | if (!token) | ||
182 | return ERR_PTR(-ENOENT); | 203 | return ERR_PTR(-ENOENT); |
183 | 204 | ||
184 | lvq = kmalloc(sizeof(*lvq), GFP_KERNEL); | 205 | lvq = kmalloc(sizeof(*lvq), GFP_KERNEL); |
185 | if (!lvq) | 206 | if (!lvq) |
186 | return ERR_PTR(-ENOMEM); | 207 | return ERR_PTR(-ENOMEM); |
187 | 208 | ||
188 | /* Note: we could use a configuration space inside here, just like we | 209 | /* Make a copy of the "struct lguest_vqconfig" entry, which sits after |
189 | * do for the device. This would allow expansion in future, because | 210 | * the descriptor. We need a copy because the config space might not |
190 | * our configuration system is designed to be expansible. But this is | 211 | * be aligned correctly. */ |
191 | * way easier. */ | 212 | memcpy(&lvq->config, lg_vq(ldev->desc)+index, sizeof(lvq->config)); |
192 | if (len != sizeof(lvq->config)) { | ||
193 | dev_err(&vdev->dev, "Unexpected virtio config len %u\n", len); | ||
194 | err = -EIO; | ||
195 | goto free_lvq; | ||
196 | } | ||
197 | /* Make a copy of the "struct lguest_vqconfig" field. We need a copy | ||
198 | * because the config space might not be aligned correctly. */ | ||
199 | vdev->config->get(vdev, token, &lvq->config, sizeof(lvq->config)); | ||
200 | 213 | ||
214 | printk("Mapping virtqueue %i addr %lx\n", index, | ||
215 | (unsigned long)lvq->config.pfn << PAGE_SHIFT); | ||
201 | /* Figure out how many pages the ring will take, and map that memory */ | 216 | /* Figure out how many pages the ring will take, and map that memory */ |
202 | lvq->pages = lguest_map((unsigned long)lvq->config.pfn << PAGE_SHIFT, | 217 | lvq->pages = lguest_map((unsigned long)lvq->config.pfn << PAGE_SHIFT, |
203 | DIV_ROUND_UP(vring_size(lvq->config.num, | 218 | DIV_ROUND_UP(vring_size(lvq->config.num, |
@@ -259,7 +274,7 @@ static void lg_del_vq(struct virtqueue *vq) | |||
259 | 274 | ||
260 | /* The ops structure which hooks everything together. */ | 275 | /* The ops structure which hooks everything together. */ |
261 | static struct virtio_config_ops lguest_config_ops = { | 276 | static struct virtio_config_ops lguest_config_ops = { |
262 | .find = lg_find, | 277 | .feature = lg_feature, |
263 | .get = lg_get, | 278 | .get = lg_get, |
264 | .set = lg_set, | 279 | .set = lg_set, |
265 | .get_status = lg_get_status, | 280 | .get_status = lg_get_status, |
@@ -329,13 +344,14 @@ static void scan_devices(void) | |||
329 | struct lguest_device_desc *d; | 344 | struct lguest_device_desc *d; |
330 | 345 | ||
331 | /* We start at the page beginning, and skip over each entry. */ | 346 | /* We start at the page beginning, and skip over each entry. */ |
332 | for (i = 0; i < PAGE_SIZE; i += sizeof(*d) + d->config_len) { | 347 | for (i = 0; i < PAGE_SIZE; i += desc_size(d)) { |
333 | d = lguest_devices + i; | 348 | d = lguest_devices + i; |
334 | 349 | ||
335 | /* Once we hit a zero, stop. */ | 350 | /* Once we hit a zero, stop. */ |
336 | if (d->type == 0) | 351 | if (d->type == 0) |
337 | break; | 352 | break; |
338 | 353 | ||
354 | printk("Device at %i has size %u\n", i, desc_size(d)); | ||
339 | add_lguest_device(d); | 355 | add_lguest_device(d); |
340 | } | 356 | } |
341 | } | 357 | } |
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index a60505c8f82a..4b8138312750 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c | |||
@@ -311,10 +311,8 @@ static int virtnet_close(struct net_device *dev) | |||
311 | static int virtnet_probe(struct virtio_device *vdev) | 311 | static int virtnet_probe(struct virtio_device *vdev) |
312 | { | 312 | { |
313 | int err; | 313 | int err; |
314 | unsigned int len; | ||
315 | struct net_device *dev; | 314 | struct net_device *dev; |
316 | struct virtnet_info *vi; | 315 | struct virtnet_info *vi; |
317 | void *token; | ||
318 | 316 | ||
319 | /* Allocate ourselves a network device with room for our info */ | 317 | /* Allocate ourselves a network device with room for our info */ |
320 | dev = alloc_etherdev(sizeof(struct virtnet_info)); | 318 | dev = alloc_etherdev(sizeof(struct virtnet_info)); |
@@ -330,25 +328,24 @@ static int virtnet_probe(struct virtio_device *vdev) | |||
330 | SET_NETDEV_DEV(dev, &vdev->dev); | 328 | SET_NETDEV_DEV(dev, &vdev->dev); |
331 | 329 | ||
332 | /* Do we support "hardware" checksums? */ | 330 | /* Do we support "hardware" checksums? */ |
333 | token = vdev->config->find(vdev, VIRTIO_CONFIG_NET_F, &len); | 331 | if (vdev->config->feature(vdev, VIRTIO_NET_F_NO_CSUM)) { |
334 | if (virtio_use_bit(vdev, token, len, VIRTIO_NET_F_NO_CSUM)) { | ||
335 | /* This opens up the world of extra features. */ | 332 | /* This opens up the world of extra features. */ |
336 | dev->features |= NETIF_F_HW_CSUM|NETIF_F_SG|NETIF_F_FRAGLIST; | 333 | dev->features |= NETIF_F_HW_CSUM|NETIF_F_SG|NETIF_F_FRAGLIST; |
337 | if (virtio_use_bit(vdev, token, len, VIRTIO_NET_F_TSO4)) | 334 | if (vdev->config->feature(vdev, VIRTIO_NET_F_TSO4)) |
338 | dev->features |= NETIF_F_TSO; | 335 | dev->features |= NETIF_F_TSO; |
339 | if (virtio_use_bit(vdev, token, len, VIRTIO_NET_F_UFO)) | 336 | if (vdev->config->feature(vdev, VIRTIO_NET_F_UFO)) |
340 | dev->features |= NETIF_F_UFO; | 337 | dev->features |= NETIF_F_UFO; |
341 | if (virtio_use_bit(vdev, token, len, VIRTIO_NET_F_TSO4_ECN)) | 338 | if (vdev->config->feature(vdev, VIRTIO_NET_F_TSO4_ECN)) |
342 | dev->features |= NETIF_F_TSO_ECN; | 339 | dev->features |= NETIF_F_TSO_ECN; |
343 | if (virtio_use_bit(vdev, token, len, VIRTIO_NET_F_TSO6)) | 340 | if (vdev->config->feature(vdev, VIRTIO_NET_F_TSO6)) |
344 | dev->features |= NETIF_F_TSO6; | 341 | dev->features |= NETIF_F_TSO6; |
345 | } | 342 | } |
346 | 343 | ||
347 | /* Configuration may specify what MAC to use. Otherwise random. */ | 344 | /* Configuration may specify what MAC to use. Otherwise random. */ |
348 | token = vdev->config->find(vdev, VIRTIO_CONFIG_NET_MAC_F, &len); | 345 | if (vdev->config->feature(vdev, VIRTIO_NET_F_MAC)) { |
349 | if (token) { | 346 | vdev->config->get(vdev, |
350 | dev->addr_len = len; | 347 | offsetof(struct virtio_net_config, mac), |
351 | vdev->config->get(vdev, token, dev->dev_addr, len); | 348 | dev->dev_addr, dev->addr_len); |
352 | } else | 349 | } else |
353 | random_ether_addr(dev->dev_addr); | 350 | random_ether_addr(dev->dev_addr); |
354 | 351 | ||
@@ -359,13 +356,13 @@ static int virtnet_probe(struct virtio_device *vdev) | |||
359 | vi->vdev = vdev; | 356 | vi->vdev = vdev; |
360 | 357 | ||
361 | /* We expect two virtqueues, receive then send. */ | 358 | /* We expect two virtqueues, receive then send. */ |
362 | vi->rvq = vdev->config->find_vq(vdev, skb_recv_done); | 359 | vi->rvq = vdev->config->find_vq(vdev, 0, skb_recv_done); |
363 | if (IS_ERR(vi->rvq)) { | 360 | if (IS_ERR(vi->rvq)) { |
364 | err = PTR_ERR(vi->rvq); | 361 | err = PTR_ERR(vi->rvq); |
365 | goto free; | 362 | goto free; |
366 | } | 363 | } |
367 | 364 | ||
368 | vi->svq = vdev->config->find_vq(vdev, skb_xmit_done); | 365 | vi->svq = vdev->config->find_vq(vdev, 1, skb_xmit_done); |
369 | if (IS_ERR(vi->svq)) { | 366 | if (IS_ERR(vi->svq)) { |
370 | err = PTR_ERR(vi->svq); | 367 | err = PTR_ERR(vi->svq); |
371 | goto free_recv; | 368 | goto free_recv; |
diff --git a/drivers/virtio/virtio.c b/drivers/virtio/virtio.c index 69d7ea02cd48..303cb6f90108 100644 --- a/drivers/virtio/virtio.c +++ b/drivers/virtio/virtio.c | |||
@@ -148,51 +148,6 @@ void unregister_virtio_device(struct virtio_device *dev) | |||
148 | } | 148 | } |
149 | EXPORT_SYMBOL_GPL(unregister_virtio_device); | 149 | EXPORT_SYMBOL_GPL(unregister_virtio_device); |
150 | 150 | ||
151 | int __virtio_config_val(struct virtio_device *vdev, | ||
152 | u8 type, void *val, size_t size) | ||
153 | { | ||
154 | void *token; | ||
155 | unsigned int len; | ||
156 | |||
157 | token = vdev->config->find(vdev, type, &len); | ||
158 | if (!token) | ||
159 | return -ENOENT; | ||
160 | |||
161 | if (len != size) | ||
162 | return -EIO; | ||
163 | |||
164 | vdev->config->get(vdev, token, val, size); | ||
165 | return 0; | ||
166 | } | ||
167 | EXPORT_SYMBOL_GPL(__virtio_config_val); | ||
168 | |||
169 | int virtio_use_bit(struct virtio_device *vdev, | ||
170 | void *token, unsigned int len, unsigned int bitnum) | ||
171 | { | ||
172 | unsigned long bits[16]; | ||
173 | |||
174 | /* This makes it convenient to pass-through find() results. */ | ||
175 | if (!token) | ||
176 | return 0; | ||
177 | |||
178 | /* bit not in range of this bitfield? */ | ||
179 | if (bitnum * 8 >= len / 2) | ||
180 | return 0; | ||
181 | |||
182 | /* Giant feature bitfields are silly. */ | ||
183 | BUG_ON(len > sizeof(bits)); | ||
184 | vdev->config->get(vdev, token, bits, len); | ||
185 | |||
186 | if (!test_bit(bitnum, bits)) | ||
187 | return 0; | ||
188 | |||
189 | /* Set acknowledge bit, and write it back. */ | ||
190 | set_bit(bitnum + len * 8 / 2, bits); | ||
191 | vdev->config->set(vdev, token, bits, len); | ||
192 | return 1; | ||
193 | } | ||
194 | EXPORT_SYMBOL_GPL(virtio_use_bit); | ||
195 | |||
196 | static int virtio_init(void) | 151 | static int virtio_init(void) |
197 | { | 152 | { |
198 | if (bus_register(&virtio_bus) != 0) | 153 | if (bus_register(&virtio_bus) != 0) |
diff --git a/include/linux/lguest_launcher.h b/include/linux/lguest_launcher.h index 697104da91f1..589be3e1f3ac 100644 --- a/include/linux/lguest_launcher.h +++ b/include/linux/lguest_launcher.h | |||
@@ -23,7 +23,12 @@ | |||
23 | struct lguest_device_desc { | 23 | struct lguest_device_desc { |
24 | /* The device type: console, network, disk etc. Type 0 terminates. */ | 24 | /* The device type: console, network, disk etc. Type 0 terminates. */ |
25 | __u8 type; | 25 | __u8 type; |
26 | /* The number of bytes of the config array. */ | 26 | /* The number of virtqueues (first in config array) */ |
27 | __u8 num_vq; | ||
28 | /* The number of bytes of feature bits. Multiply by 2: one for host | ||
29 | * features and one for guest acknowledgements. */ | ||
30 | __u8 feature_len; | ||
31 | /* The number of bytes of the config array after virtqueues. */ | ||
27 | __u8 config_len; | 32 | __u8 config_len; |
28 | /* A status byte, written by the Guest. */ | 33 | /* A status byte, written by the Guest. */ |
29 | __u8 status; | 34 | __u8 status; |
@@ -31,7 +36,7 @@ struct lguest_device_desc { | |||
31 | }; | 36 | }; |
32 | 37 | ||
33 | /*D:135 This is how we expect the device configuration field for a virtqueue | 38 | /*D:135 This is how we expect the device configuration field for a virtqueue |
34 | * (type VIRTIO_CONFIG_F_VIRTQUEUE) to be laid out: */ | 39 | * to be laid out in config space. */ |
35 | struct lguest_vqconfig { | 40 | struct lguest_vqconfig { |
36 | /* The number of entries in the virtio_ring */ | 41 | /* The number of entries in the virtio_ring */ |
37 | __u16 num; | 42 | __u16 num; |
diff --git a/include/linux/virtio_blk.h b/include/linux/virtio_blk.h index 7bd2bce0cfd9..e54635666f2c 100644 --- a/include/linux/virtio_blk.h +++ b/include/linux/virtio_blk.h | |||
@@ -6,15 +6,19 @@ | |||
6 | #define VIRTIO_ID_BLOCK 2 | 6 | #define VIRTIO_ID_BLOCK 2 |
7 | 7 | ||
8 | /* Feature bits */ | 8 | /* Feature bits */ |
9 | #define VIRTIO_CONFIG_BLK_F 0x40 | 9 | #define VIRTIO_BLK_F_BARRIER 0 /* Does host support barriers? */ |
10 | #define VIRTIO_BLK_F_BARRIER 1 /* Does host support barriers? */ | 10 | #define VIRTIO_BLK_F_SIZE_MAX 1 /* Indicates maximum segment size */ |
11 | 11 | #define VIRTIO_BLK_F_SEG_MAX 2 /* Indicates maximum # of segments */ | |
12 | /* The capacity (in 512-byte sectors). */ | 12 | |
13 | #define VIRTIO_CONFIG_BLK_F_CAPACITY 0x41 | 13 | struct virtio_blk_config |
14 | /* The maximum segment size. */ | 14 | { |
15 | #define VIRTIO_CONFIG_BLK_F_SIZE_MAX 0x42 | 15 | /* The capacity (in 512-byte sectors). */ |
16 | /* The maximum number of segments. */ | 16 | __le64 capacity; |
17 | #define VIRTIO_CONFIG_BLK_F_SEG_MAX 0x43 | 17 | /* The maximum segment size (if VIRTIO_BLK_F_SIZE_MAX) */ |
18 | __le32 size_max; | ||
19 | /* The maximum number of segments (if VIRTIO_BLK_F_SEG_MAX) */ | ||
20 | __le32 seg_max; | ||
21 | } __attribute__((packed)); | ||
18 | 22 | ||
19 | /* These two define direction. */ | 23 | /* These two define direction. */ |
20 | #define VIRTIO_BLK_T_IN 0 | 24 | #define VIRTIO_BLK_T_IN 0 |
diff --git a/include/linux/virtio_config.h b/include/linux/virtio_config.h index bcc01888df78..70bb26062d76 100644 --- a/include/linux/virtio_config.h +++ b/include/linux/virtio_config.h | |||
@@ -5,7 +5,7 @@ | |||
5 | * store and access that space differently. */ | 5 | * store and access that space differently. */ |
6 | #include <linux/types.h> | 6 | #include <linux/types.h> |
7 | 7 | ||
8 | /* Status byte for guest to report progress, and synchronize config. */ | 8 | /* Status byte for guest to report progress, and synchronize features. */ |
9 | /* We have seen device and processed generic fields (VIRTIO_CONFIG_F_VIRTIO) */ | 9 | /* We have seen device and processed generic fields (VIRTIO_CONFIG_F_VIRTIO) */ |
10 | #define VIRTIO_CONFIG_S_ACKNOWLEDGE 1 | 10 | #define VIRTIO_CONFIG_S_ACKNOWLEDGE 1 |
11 | /* We have found a driver for the device. */ | 11 | /* We have found a driver for the device. */ |
@@ -15,34 +15,27 @@ | |||
15 | /* We've given up on this device. */ | 15 | /* We've given up on this device. */ |
16 | #define VIRTIO_CONFIG_S_FAILED 0x80 | 16 | #define VIRTIO_CONFIG_S_FAILED 0x80 |
17 | 17 | ||
18 | /* Feature byte (actually 7 bits availabe): */ | ||
19 | /* Requirements/features of the virtio implementation. */ | ||
20 | #define VIRTIO_CONFIG_F_VIRTIO 1 | ||
21 | /* Requirements/features of the virtqueue (may have more than one). */ | ||
22 | #define VIRTIO_CONFIG_F_VIRTQUEUE 2 | ||
23 | |||
24 | #ifdef __KERNEL__ | 18 | #ifdef __KERNEL__ |
25 | struct virtio_device; | 19 | struct virtio_device; |
26 | 20 | ||
27 | /** | 21 | /** |
28 | * virtio_config_ops - operations for configuring a virtio device | 22 | * virtio_config_ops - operations for configuring a virtio device |
29 | * @find: search for the next configuration field of the given type. | 23 | * @feature: search for a feature in this config |
30 | * vdev: the virtio_device | 24 | * vdev: the virtio_device |
31 | * type: the feature type | 25 | * bit: the feature bit |
32 | * len: the (returned) length of the field if found. | 26 | * Returns true if the feature is supported. Acknowledges the feature |
33 | * Returns a token if found, or NULL. Never returnes the same field twice | 27 | * so the host can see it. |
34 | * (ie. it's used up). | 28 | * @get: read the value of a configuration field |
35 | * @get: read the value of a configuration field after find(). | ||
36 | * vdev: the virtio_device | 29 | * vdev: the virtio_device |
37 | * token: the token returned from find(). | 30 | * offset: the offset of the configuration field |
38 | * buf: the buffer to write the field value into. | 31 | * buf: the buffer to write the field value into. |
39 | * len: the length of the buffer (given by find()). | 32 | * len: the length of the buffer |
40 | * Note that contents are conventionally little-endian. | 33 | * Note that contents are conventionally little-endian. |
41 | * @set: write the value of a configuration field after find(). | 34 | * @set: write the value of a configuration field |
42 | * vdev: the virtio_device | 35 | * vdev: the virtio_device |
43 | * token: the token returned from find(). | 36 | * offset: the offset of the configuration field |
44 | * buf: the buffer to read the field value from. | 37 | * buf: the buffer to read the field value from. |
45 | * len: the length of the buffer (given by find()). | 38 | * len: the length of the buffer |
46 | * Note that contents are conventionally little-endian. | 39 | * Note that contents are conventionally little-endian. |
47 | * @get_status: read the status byte | 40 | * @get_status: read the status byte |
48 | * vdev: the virtio_device | 41 | * vdev: the virtio_device |
@@ -50,62 +43,63 @@ struct virtio_device; | |||
50 | * @set_status: write the status byte | 43 | * @set_status: write the status byte |
51 | * vdev: the virtio_device | 44 | * vdev: the virtio_device |
52 | * status: the new status byte | 45 | * status: the new status byte |
53 | * @find_vq: find the first VIRTIO_CONFIG_F_VIRTQUEUE and create a virtqueue. | 46 | * @find_vq: find a virtqueue and instantiate it. |
54 | * vdev: the virtio_device | 47 | * vdev: the virtio_device |
48 | * index: the 0-based virtqueue number in case there's more than one. | ||
55 | * callback: the virqtueue callback | 49 | * callback: the virqtueue callback |
56 | * Returns the new virtqueue or ERR_PTR(). | 50 | * Returns the new virtqueue or ERR_PTR() (eg. -ENOENT). |
57 | * @del_vq: free a virtqueue found by find_vq(). | 51 | * @del_vq: free a virtqueue found by find_vq(). |
58 | */ | 52 | */ |
59 | struct virtio_config_ops | 53 | struct virtio_config_ops |
60 | { | 54 | { |
61 | void *(*find)(struct virtio_device *vdev, u8 type, unsigned *len); | 55 | bool (*feature)(struct virtio_device *vdev, unsigned bit); |
62 | void (*get)(struct virtio_device *vdev, void *token, | 56 | void (*get)(struct virtio_device *vdev, unsigned offset, |
63 | void *buf, unsigned len); | 57 | void *buf, unsigned len); |
64 | void (*set)(struct virtio_device *vdev, void *token, | 58 | void (*set)(struct virtio_device *vdev, unsigned offset, |
65 | const void *buf, unsigned len); | 59 | const void *buf, unsigned len); |
66 | u8 (*get_status)(struct virtio_device *vdev); | 60 | u8 (*get_status)(struct virtio_device *vdev); |
67 | void (*set_status)(struct virtio_device *vdev, u8 status); | 61 | void (*set_status)(struct virtio_device *vdev, u8 status); |
68 | struct virtqueue *(*find_vq)(struct virtio_device *vdev, | 62 | struct virtqueue *(*find_vq)(struct virtio_device *vdev, |
63 | unsigned index, | ||
69 | bool (*callback)(struct virtqueue *)); | 64 | bool (*callback)(struct virtqueue *)); |
70 | void (*del_vq)(struct virtqueue *vq); | 65 | void (*del_vq)(struct virtqueue *vq); |
71 | }; | 66 | }; |
72 | 67 | ||
73 | /** | 68 | /** |
74 | * virtio_config_val - get a single virtio config and mark it used. | 69 | * virtio_config_val - look for a feature and get a single virtio config. |
75 | * @config: the virtio config space | 70 | * @vdev: the virtio device |
76 | * @type: the type to search for. | 71 | * @fbit: the feature bit |
72 | * @offset: the type to search for. | ||
77 | * @val: a pointer to the value to fill in. | 73 | * @val: a pointer to the value to fill in. |
78 | * | 74 | * |
79 | * Once used, the config type is marked with VIRTIO_CONFIG_F_USED so it can't | 75 | * The return value is -ENOENT if the feature doesn't exist. Otherwise |
80 | * be found again. This version does endian conversion. */ | 76 | * the value is endian-corrected and returned in v. */ |
81 | #define virtio_config_val(vdev, type, v) ({ \ | 77 | #define virtio_config_val(vdev, fbit, offset, v) ({ \ |
82 | int _err = __virtio_config_val((vdev),(type),(v),sizeof(*(v))); \ | 78 | int _err; \ |
83 | \ | 79 | if ((vdev)->config->feature((vdev), (fbit))) { \ |
84 | BUILD_BUG_ON(sizeof(*(v)) != 1 && sizeof(*(v)) != 2 \ | 80 | __virtio_config_val((vdev), (offset), (v)); \ |
85 | && sizeof(*(v)) != 4 && sizeof(*(v)) != 8); \ | 81 | _err = 0; \ |
86 | if (!_err) { \ | 82 | } else \ |
87 | switch (sizeof(*(v))) { \ | 83 | _err = -ENOENT; \ |
88 | case 2: le16_to_cpus((__u16 *) v); break; \ | ||
89 | case 4: le32_to_cpus((__u32 *) v); break; \ | ||
90 | case 8: le64_to_cpus((__u64 *) v); break; \ | ||
91 | } \ | ||
92 | } \ | ||
93 | _err; \ | 84 | _err; \ |
94 | }) | 85 | }) |
95 | 86 | ||
96 | int __virtio_config_val(struct virtio_device *dev, | ||
97 | u8 type, void *val, size_t size); | ||
98 | |||
99 | /** | 87 | /** |
100 | * virtio_use_bit - helper to use a feature bit in a bitfield value. | 88 | * __virtio_config_val - get a single virtio config without feature check. |
101 | * @dev: the virtio device | 89 | * @vdev: the virtio device |
102 | * @token: the token as returned from vdev->config->find(). | 90 | * @offset: the type to search for. |
103 | * @len: the length of the field. | 91 | * @val: a pointer to the value to fill in. |
104 | * @bitnum: the bit to test. | ||
105 | * | 92 | * |
106 | * If handed a NULL token, it returns false, otherwise returns bit status. | 93 | * The value is endian-corrected and returned in v. */ |
107 | * If it's one, it sets the mirroring acknowledgement bit. */ | 94 | #define __virtio_config_val(vdev, offset, v) do { \ |
108 | int virtio_use_bit(struct virtio_device *vdev, | 95 | BUILD_BUG_ON(sizeof(*(v)) != 1 && sizeof(*(v)) != 2 \ |
109 | void *token, unsigned int len, unsigned int bitnum); | 96 | && sizeof(*(v)) != 4 && sizeof(*(v)) != 8); \ |
97 | (vdev)->config->get((vdev), (offset), (v), sizeof(*(v))); \ | ||
98 | switch (sizeof(*(v))) { \ | ||
99 | case 2: le16_to_cpus((__u16 *) v); break; \ | ||
100 | case 4: le32_to_cpus((__u32 *) v); break; \ | ||
101 | case 8: le64_to_cpus((__u64 *) v); break; \ | ||
102 | } \ | ||
103 | } while(0) | ||
110 | #endif /* __KERNEL__ */ | 104 | #endif /* __KERNEL__ */ |
111 | #endif /* _LINUX_VIRTIO_CONFIG_H */ | 105 | #endif /* _LINUX_VIRTIO_CONFIG_H */ |
diff --git a/include/linux/virtio_net.h b/include/linux/virtio_net.h index ae469ae55d36..6e8fdfea8cd0 100644 --- a/include/linux/virtio_net.h +++ b/include/linux/virtio_net.h | |||
@@ -5,16 +5,19 @@ | |||
5 | /* The ID for virtio_net */ | 5 | /* The ID for virtio_net */ |
6 | #define VIRTIO_ID_NET 1 | 6 | #define VIRTIO_ID_NET 1 |
7 | 7 | ||
8 | /* The bitmap of config for virtio net */ | 8 | /* The feature bitmap for virtio net */ |
9 | #define VIRTIO_CONFIG_NET_F 0x40 | ||
10 | #define VIRTIO_NET_F_NO_CSUM 0 | 9 | #define VIRTIO_NET_F_NO_CSUM 0 |
11 | #define VIRTIO_NET_F_TSO4 1 | 10 | #define VIRTIO_NET_F_TSO4 1 |
12 | #define VIRTIO_NET_F_UFO 2 | 11 | #define VIRTIO_NET_F_UFO 2 |
13 | #define VIRTIO_NET_F_TSO4_ECN 3 | 12 | #define VIRTIO_NET_F_TSO4_ECN 3 |
14 | #define VIRTIO_NET_F_TSO6 4 | 13 | #define VIRTIO_NET_F_TSO6 4 |
14 | #define VIRTIO_NET_F_MAC 5 | ||
15 | 15 | ||
16 | /* The config defining mac address. */ | 16 | struct virtio_net_config |
17 | #define VIRTIO_CONFIG_NET_MAC_F 0x41 | 17 | { |
18 | /* The config defining mac address (if VIRTIO_NET_F_MAC) */ | ||
19 | __u8 mac[6]; | ||
20 | } __attribute__((packed)); | ||
18 | 21 | ||
19 | /* This is the first element of the scatter-gather list. If you don't | 22 | /* This is the first element of the scatter-gather list. If you don't |
20 | * specify GSO or CSUM features, you can simply ignore the header. */ | 23 | * specify GSO or CSUM features, you can simply ignore the header. */ |
diff --git a/net/9p/trans_virtio.c b/net/9p/trans_virtio.c index 40b71a29fc3f..78d7946f81fe 100644 --- a/net/9p/trans_virtio.c +++ b/net/9p/trans_virtio.c | |||
@@ -236,13 +236,13 @@ static int p9_virtio_probe(struct virtio_device *dev) | |||
236 | 236 | ||
237 | /* Find the input queue. */ | 237 | /* Find the input queue. */ |
238 | dev->priv = chan; | 238 | dev->priv = chan; |
239 | chan->in_vq = dev->config->find_vq(dev, p9_virtio_intr); | 239 | chan->in_vq = dev->config->find_vq(dev, 0, p9_virtio_intr); |
240 | if (IS_ERR(chan->in_vq)) { | 240 | if (IS_ERR(chan->in_vq)) { |
241 | err = PTR_ERR(chan->in_vq); | 241 | err = PTR_ERR(chan->in_vq); |
242 | goto free; | 242 | goto free; |
243 | } | 243 | } |
244 | 244 | ||
245 | chan->out_vq = dev->config->find_vq(dev, NULL); | 245 | chan->out_vq = dev->config->find_vq(dev, 1, NULL); |
246 | if (IS_ERR(chan->out_vq)) { | 246 | if (IS_ERR(chan->out_vq)) { |
247 | err = PTR_ERR(chan->out_vq); | 247 | err = PTR_ERR(chan->out_vq); |
248 | goto free_in_vq; | 248 | goto free_in_vq; |