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 /include | |
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>
Diffstat (limited to 'include')
-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 |
4 files changed, 73 insertions, 67 deletions
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. */ |