Branch data Line data Source code
1 : : #ifndef _LINUX_VIRTIO_CONFIG_H
2 : : #define _LINUX_VIRTIO_CONFIG_H
3 : :
4 : : #include <linux/err.h>
5 : : #include <linux/bug.h>
6 : : #include <linux/virtio.h>
7 : : #include <uapi/linux/virtio_config.h>
8 : :
9 : : /**
10 : : * virtio_config_ops - operations for configuring a virtio device
11 : : * @get: read the value of a configuration field
12 : : * vdev: the virtio_device
13 : : * offset: the offset of the configuration field
14 : : * buf: the buffer to write the field value into.
15 : : * len: the length of the buffer
16 : : * @set: write the value of a configuration field
17 : : * vdev: the virtio_device
18 : : * offset: the offset of the configuration field
19 : : * buf: the buffer to read the field value from.
20 : : * len: the length of the buffer
21 : : * @get_status: read the status byte
22 : : * vdev: the virtio_device
23 : : * Returns the status byte
24 : : * @set_status: write the status byte
25 : : * vdev: the virtio_device
26 : : * status: the new status byte
27 : : * @reset: reset the device
28 : : * vdev: the virtio device
29 : : * After this, status and feature negotiation must be done again
30 : : * Device must not be reset from its vq/config callbacks, or in
31 : : * parallel with being added/removed.
32 : : * @find_vqs: find virtqueues and instantiate them.
33 : : * vdev: the virtio_device
34 : : * nvqs: the number of virtqueues to find
35 : : * vqs: on success, includes new virtqueues
36 : : * callbacks: array of callbacks, for each virtqueue
37 : : * include a NULL entry for vqs that do not need a callback
38 : : * names: array of virtqueue names (mainly for debugging)
39 : : * include a NULL entry for vqs unused by driver
40 : : * Returns 0 on success or error status
41 : : * @del_vqs: free virtqueues found by find_vqs().
42 : : * @get_features: get the array of feature bits for this device.
43 : : * vdev: the virtio_device
44 : : * Returns the first 32 feature bits (all we currently need).
45 : : * @finalize_features: confirm what device features we'll be using.
46 : : * vdev: the virtio_device
47 : : * This gives the final feature bits for the device: it can change
48 : : * the dev->feature bits if it wants.
49 : : * @bus_name: return the bus name associated with the device
50 : : * vdev: the virtio_device
51 : : * This returns a pointer to the bus name a la pci_name from which
52 : : * the caller can then copy.
53 : : * @set_vq_affinity: set the affinity for a virtqueue.
54 : : */
55 : : typedef void vq_callback_t(struct virtqueue *);
56 : : struct virtio_config_ops {
57 : : void (*get)(struct virtio_device *vdev, unsigned offset,
58 : : void *buf, unsigned len);
59 : : void (*set)(struct virtio_device *vdev, unsigned offset,
60 : : const void *buf, unsigned len);
61 : : u8 (*get_status)(struct virtio_device *vdev);
62 : : void (*set_status)(struct virtio_device *vdev, u8 status);
63 : : void (*reset)(struct virtio_device *vdev);
64 : : int (*find_vqs)(struct virtio_device *, unsigned nvqs,
65 : : struct virtqueue *vqs[],
66 : : vq_callback_t *callbacks[],
67 : : const char *names[]);
68 : : void (*del_vqs)(struct virtio_device *);
69 : : u32 (*get_features)(struct virtio_device *vdev);
70 : : void (*finalize_features)(struct virtio_device *vdev);
71 : : const char *(*bus_name)(struct virtio_device *vdev);
72 : : int (*set_vq_affinity)(struct virtqueue *vq, int cpu);
73 : : };
74 : :
75 : : /* If driver didn't advertise the feature, it will never appear. */
76 : : void virtio_check_driver_offered_feature(const struct virtio_device *vdev,
77 : : unsigned int fbit);
78 : :
79 : : /**
80 : : * virtio_has_feature - helper to determine if this device has this feature.
81 : : * @vdev: the device
82 : : * @fbit: the feature bit
83 : : */
84 : : static inline bool virtio_has_feature(const struct virtio_device *vdev,
85 : : unsigned int fbit)
86 : : {
87 : : /* Did you forget to fix assumptions on max features? */
88 : : if (__builtin_constant_p(fbit))
89 : : BUILD_BUG_ON(fbit >= 32);
90 : : else
91 : : BUG_ON(fbit >= 32);
92 : :
93 : : if (fbit < VIRTIO_TRANSPORT_F_START)
94 : 0 : virtio_check_driver_offered_feature(vdev, fbit);
95 : :
96 : 0 : return test_bit(fbit, vdev->features);
97 : : }
98 : :
99 : : static inline
100 : : struct virtqueue *virtio_find_single_vq(struct virtio_device *vdev,
101 : : vq_callback_t *c, const char *n)
102 : : {
103 : 0 : vq_callback_t *callbacks[] = { c };
104 : 0 : const char *names[] = { n };
105 : : struct virtqueue *vq;
106 : 0 : int err = vdev->config->find_vqs(vdev, 1, &vq, callbacks, names);
107 [ # # ]: 0 : if (err < 0)
108 : : return ERR_PTR(err);
109 : 0 : return vq;
110 : : }
111 : :
112 : : static inline
113 : : const char *virtio_bus_name(struct virtio_device *vdev)
114 : : {
115 : : if (!vdev->config->bus_name)
116 : : return "virtio";
117 : : return vdev->config->bus_name(vdev);
118 : : }
119 : :
120 : : /**
121 : : * virtqueue_set_affinity - setting affinity for a virtqueue
122 : : * @vq: the virtqueue
123 : : * @cpu: the cpu no.
124 : : *
125 : : * Pay attention the function are best-effort: the affinity hint may not be set
126 : : * due to config support, irq type and sharing.
127 : : *
128 : : */
129 : : static inline
130 : : int virtqueue_set_affinity(struct virtqueue *vq, int cpu)
131 : : {
132 : : struct virtio_device *vdev = vq->vdev;
133 : : if (vdev->config->set_vq_affinity)
134 : : return vdev->config->set_vq_affinity(vq, cpu);
135 : : return 0;
136 : : }
137 : :
138 : : /* Config space accessors. */
139 : : #define virtio_cread(vdev, structname, member, ptr) \
140 : : do { \
141 : : /* Must match the member's type, and be integer */ \
142 : : if (!typecheck(typeof((((structname*)0)->member)), *(ptr))) \
143 : : (*ptr) = 1; \
144 : : \
145 : : switch (sizeof(*ptr)) { \
146 : : case 1: \
147 : : *(ptr) = virtio_cread8(vdev, \
148 : : offsetof(structname, member)); \
149 : : break; \
150 : : case 2: \
151 : : *(ptr) = virtio_cread16(vdev, \
152 : : offsetof(structname, member)); \
153 : : break; \
154 : : case 4: \
155 : : *(ptr) = virtio_cread32(vdev, \
156 : : offsetof(structname, member)); \
157 : : break; \
158 : : case 8: \
159 : : *(ptr) = virtio_cread64(vdev, \
160 : : offsetof(structname, member)); \
161 : : break; \
162 : : default: \
163 : : BUG(); \
164 : : } \
165 : : } while(0)
166 : :
167 : : /* Config space accessors. */
168 : : #define virtio_cwrite(vdev, structname, member, ptr) \
169 : : do { \
170 : : /* Must match the member's type, and be integer */ \
171 : : if (!typecheck(typeof((((structname*)0)->member)), *(ptr))) \
172 : : BUG_ON((*ptr) == 1); \
173 : : \
174 : : switch (sizeof(*ptr)) { \
175 : : case 1: \
176 : : virtio_cwrite8(vdev, \
177 : : offsetof(structname, member), \
178 : : *(ptr)); \
179 : : break; \
180 : : case 2: \
181 : : virtio_cwrite16(vdev, \
182 : : offsetof(structname, member), \
183 : : *(ptr)); \
184 : : break; \
185 : : case 4: \
186 : : virtio_cwrite32(vdev, \
187 : : offsetof(structname, member), \
188 : : *(ptr)); \
189 : : break; \
190 : : case 8: \
191 : : virtio_cwrite64(vdev, \
192 : : offsetof(structname, member), \
193 : : *(ptr)); \
194 : : break; \
195 : : default: \
196 : : BUG(); \
197 : : } \
198 : : } while(0)
199 : :
200 : : static inline u8 virtio_cread8(struct virtio_device *vdev, unsigned int offset)
201 : : {
202 : : u8 ret;
203 : 0 : vdev->config->get(vdev, offset, &ret, sizeof(ret));
204 : 0 : return ret;
205 : : }
206 : :
207 : : static inline void virtio_cread_bytes(struct virtio_device *vdev,
208 : : unsigned int offset,
209 : : void *buf, size_t len)
210 : : {
211 : : vdev->config->get(vdev, offset, buf, len);
212 : : }
213 : :
214 : : static inline void virtio_cwrite8(struct virtio_device *vdev,
215 : : unsigned int offset, u8 val)
216 : : {
217 : 0 : vdev->config->set(vdev, offset, &val, sizeof(val));
218 : : }
219 : :
220 : : static inline u16 virtio_cread16(struct virtio_device *vdev,
221 : : unsigned int offset)
222 : : {
223 : : u16 ret;
224 : 0 : vdev->config->get(vdev, offset, &ret, sizeof(ret));
225 : 0 : return ret;
226 : : }
227 : :
228 : : static inline void virtio_cwrite16(struct virtio_device *vdev,
229 : : unsigned int offset, u16 val)
230 : : {
231 : : vdev->config->set(vdev, offset, &val, sizeof(val));
232 : : }
233 : :
234 : : static inline u32 virtio_cread32(struct virtio_device *vdev,
235 : : unsigned int offset)
236 : : {
237 : : u32 ret;
238 : 0 : vdev->config->get(vdev, offset, &ret, sizeof(ret));
239 : 0 : return ret;
240 : : }
241 : :
242 : : static inline void virtio_cwrite32(struct virtio_device *vdev,
243 : : unsigned int offset, u32 val)
244 : : {
245 : : vdev->config->set(vdev, offset, &val, sizeof(val));
246 : : }
247 : :
248 : : static inline u64 virtio_cread64(struct virtio_device *vdev,
249 : : unsigned int offset)
250 : : {
251 : : u64 ret;
252 : 0 : vdev->config->get(vdev, offset, &ret, sizeof(ret));
253 : 0 : return ret;
254 : : }
255 : :
256 : : static inline void virtio_cwrite64(struct virtio_device *vdev,
257 : : unsigned int offset, u64 val)
258 : : {
259 : : vdev->config->set(vdev, offset, &val, sizeof(val));
260 : : }
261 : :
262 : : /* Conditional config space accessors. */
263 : : #define virtio_cread_feature(vdev, fbit, structname, member, ptr) \
264 : : ({ \
265 : : int _r = 0; \
266 : : if (!virtio_has_feature(vdev, fbit)) \
267 : : _r = -ENOENT; \
268 : : else \
269 : : virtio_cread((vdev), structname, member, ptr); \
270 : : _r; \
271 : : })
272 : :
273 : : #endif /* _LINUX_VIRTIO_CONFIG_H */
|