Branch data Line data Source code
1 : : /* SPDX-License-Identifier: GPL-2.0 */
2 : : #ifndef _LINUX_VIRTIO_CONFIG_H
3 : : #define _LINUX_VIRTIO_CONFIG_H
4 : :
5 : : #include <linux/err.h>
6 : : #include <linux/bug.h>
7 : : #include <linux/virtio.h>
8 : : #include <linux/virtio_byteorder.h>
9 : : #include <uapi/linux/virtio_config.h>
10 : :
11 : : struct irq_affinity;
12 : :
13 : : /**
14 : : * virtio_config_ops - operations for configuring a virtio device
15 : : * Note: Do not assume that a transport implements all of the operations
16 : : * getting/setting a value as a simple read/write! Generally speaking,
17 : : * any of @get/@set, @get_status/@set_status, or @get_features/
18 : : * @finalize_features are NOT safe to be called from an atomic
19 : : * context.
20 : : * @get: read the value of a configuration field
21 : : * vdev: the virtio_device
22 : : * offset: the offset of the configuration field
23 : : * buf: the buffer to write the field value into.
24 : : * len: the length of the buffer
25 : : * @set: write the value of a configuration field
26 : : * vdev: the virtio_device
27 : : * offset: the offset of the configuration field
28 : : * buf: the buffer to read the field value from.
29 : : * len: the length of the buffer
30 : : * @generation: config generation counter (optional)
31 : : * vdev: the virtio_device
32 : : * Returns the config generation counter
33 : : * @get_status: read the status byte
34 : : * vdev: the virtio_device
35 : : * Returns the status byte
36 : : * @set_status: write the status byte
37 : : * vdev: the virtio_device
38 : : * status: the new status byte
39 : : * @reset: reset the device
40 : : * vdev: the virtio device
41 : : * After this, status and feature negotiation must be done again
42 : : * Device must not be reset from its vq/config callbacks, or in
43 : : * parallel with being added/removed.
44 : : * @find_vqs: find virtqueues and instantiate them.
45 : : * vdev: the virtio_device
46 : : * nvqs: the number of virtqueues to find
47 : : * vqs: on success, includes new virtqueues
48 : : * callbacks: array of callbacks, for each virtqueue
49 : : * include a NULL entry for vqs that do not need a callback
50 : : * names: array of virtqueue names (mainly for debugging)
51 : : * include a NULL entry for vqs unused by driver
52 : : * Returns 0 on success or error status
53 : : * @del_vqs: free virtqueues found by find_vqs().
54 : : * @get_features: get the array of feature bits for this device.
55 : : * vdev: the virtio_device
56 : : * Returns the first 64 feature bits (all we currently need).
57 : : * @finalize_features: confirm what device features we'll be using.
58 : : * vdev: the virtio_device
59 : : * This gives the final feature bits for the device: it can change
60 : : * the dev->feature bits if it wants.
61 : : * Returns 0 on success or error status
62 : : * @bus_name: return the bus name associated with the device (optional)
63 : : * vdev: the virtio_device
64 : : * This returns a pointer to the bus name a la pci_name from which
65 : : * the caller can then copy.
66 : : * @set_vq_affinity: set the affinity for a virtqueue (optional).
67 : : * @get_vq_affinity: get the affinity for a virtqueue (optional).
68 : : */
69 : : typedef void vq_callback_t(struct virtqueue *);
70 : : struct virtio_config_ops {
71 : : void (*get)(struct virtio_device *vdev, unsigned offset,
72 : : void *buf, unsigned len);
73 : : void (*set)(struct virtio_device *vdev, unsigned offset,
74 : : const void *buf, unsigned len);
75 : : u32 (*generation)(struct virtio_device *vdev);
76 : : u8 (*get_status)(struct virtio_device *vdev);
77 : : void (*set_status)(struct virtio_device *vdev, u8 status);
78 : : void (*reset)(struct virtio_device *vdev);
79 : : int (*find_vqs)(struct virtio_device *, unsigned nvqs,
80 : : struct virtqueue *vqs[], vq_callback_t *callbacks[],
81 : : const char * const names[], const bool *ctx,
82 : : struct irq_affinity *desc);
83 : : void (*del_vqs)(struct virtio_device *);
84 : : u64 (*get_features)(struct virtio_device *vdev);
85 : : int (*finalize_features)(struct virtio_device *vdev);
86 : : const char *(*bus_name)(struct virtio_device *vdev);
87 : : int (*set_vq_affinity)(struct virtqueue *vq,
88 : : const struct cpumask *cpu_mask);
89 : : const struct cpumask *(*get_vq_affinity)(struct virtio_device *vdev,
90 : : int index);
91 : : };
92 : :
93 : : /* If driver didn't advertise the feature, it will never appear. */
94 : : void virtio_check_driver_offered_feature(const struct virtio_device *vdev,
95 : : unsigned int fbit);
96 : :
97 : : /**
98 : : * __virtio_test_bit - helper to test feature bits. For use by transports.
99 : : * Devices should normally use virtio_has_feature,
100 : : * which includes more checks.
101 : : * @vdev: the device
102 : : * @fbit: the feature bit
103 : : */
104 : 0 : static inline bool __virtio_test_bit(const struct virtio_device *vdev,
105 : : unsigned int fbit)
106 : : {
107 : : /* Did you forget to fix assumptions on max features? */
108 : 0 : if (__builtin_constant_p(fbit))
109 : : BUILD_BUG_ON(fbit >= 64);
110 : : else
111 : 0 : BUG_ON(fbit >= 64);
112 : :
113 [ # # # # : 0 : return vdev->features & BIT_ULL(fbit);
# # # # #
# # # # #
# # # # #
# # # ]
114 : : }
115 : :
116 : : /**
117 : : * __virtio_set_bit - helper to set feature bits. For use by transports.
118 : : * @vdev: the device
119 : : * @fbit: the feature bit
120 : : */
121 : 0 : static inline void __virtio_set_bit(struct virtio_device *vdev,
122 : : unsigned int fbit)
123 : : {
124 : : /* Did you forget to fix assumptions on max features? */
125 : 0 : if (__builtin_constant_p(fbit))
126 : : BUILD_BUG_ON(fbit >= 64);
127 : : else
128 : 0 : BUG_ON(fbit >= 64);
129 : :
130 : 0 : vdev->features |= BIT_ULL(fbit);
131 : 0 : }
132 : :
133 : : /**
134 : : * __virtio_clear_bit - helper to clear feature bits. For use by transports.
135 : : * @vdev: the device
136 : : * @fbit: the feature bit
137 : : */
138 : 0 : static inline void __virtio_clear_bit(struct virtio_device *vdev,
139 : : unsigned int fbit)
140 : : {
141 : : /* Did you forget to fix assumptions on max features? */
142 : 0 : if (__builtin_constant_p(fbit))
143 : : BUILD_BUG_ON(fbit >= 64);
144 : : else
145 : 0 : BUG_ON(fbit >= 64);
146 : :
147 [ # # ]: 0 : vdev->features &= ~BIT_ULL(fbit);
148 : 0 : }
149 : :
150 : : /**
151 : : * virtio_has_feature - helper to determine if this device has this feature.
152 : : * @vdev: the device
153 : : * @fbit: the feature bit
154 : : */
155 : 0 : static inline bool virtio_has_feature(const struct virtio_device *vdev,
156 : : unsigned int fbit)
157 : : {
158 [ # # ]: 0 : if (fbit < VIRTIO_TRANSPORT_F_START)
159 : 0 : virtio_check_driver_offered_feature(vdev, fbit);
160 : :
161 : 0 : return __virtio_test_bit(vdev, fbit);
162 : : }
163 : :
164 : : /**
165 : : * virtio_has_iommu_quirk - determine whether this device has the iommu quirk
166 : : * @vdev: the device
167 : : */
168 : 0 : static inline bool virtio_has_iommu_quirk(const struct virtio_device *vdev)
169 : : {
170 : : /*
171 : : * Note the reverse polarity of the quirk feature (compared to most
172 : : * other features), this is for compatibility with legacy systems.
173 : : */
174 : 0 : return !virtio_has_feature(vdev, VIRTIO_F_IOMMU_PLATFORM);
175 : : }
176 : :
177 : : static inline
178 : 0 : struct virtqueue *virtio_find_single_vq(struct virtio_device *vdev,
179 : : vq_callback_t *c, const char *n)
180 : : {
181 : 0 : vq_callback_t *callbacks[] = { c };
182 : 0 : const char *names[] = { n };
183 : 0 : struct virtqueue *vq;
184 : 0 : int err = vdev->config->find_vqs(vdev, 1, &vq, callbacks, names, NULL,
185 : : NULL);
186 [ # # ]: 0 : if (err < 0)
187 : 0 : return ERR_PTR(err);
188 : 0 : return vq;
189 : : }
190 : :
191 : : static inline
192 : 0 : int virtio_find_vqs(struct virtio_device *vdev, unsigned nvqs,
193 : : struct virtqueue *vqs[], vq_callback_t *callbacks[],
194 : : const char * const names[],
195 : : struct irq_affinity *desc)
196 : : {
197 : 0 : return vdev->config->find_vqs(vdev, nvqs, vqs, callbacks, names, NULL, desc);
198 : : }
199 : :
200 : : static inline
201 : : int virtio_find_vqs_ctx(struct virtio_device *vdev, unsigned nvqs,
202 : : struct virtqueue *vqs[], vq_callback_t *callbacks[],
203 : : const char * const names[], const bool *ctx,
204 : : struct irq_affinity *desc)
205 : : {
206 : : return vdev->config->find_vqs(vdev, nvqs, vqs, callbacks, names, ctx,
207 : : desc);
208 : : }
209 : :
210 : : /**
211 : : * virtio_device_ready - enable vq use in probe function
212 : : * @vdev: the device
213 : : *
214 : : * Driver must call this to use vqs in the probe function.
215 : : *
216 : : * Note: vqs are enabled automatically after probe returns.
217 : : */
218 : : static inline
219 : 0 : void virtio_device_ready(struct virtio_device *dev)
220 : : {
221 : 0 : unsigned status = dev->config->get_status(dev);
222 : :
223 [ # # ]: 0 : BUG_ON(status & VIRTIO_CONFIG_S_DRIVER_OK);
224 : 0 : dev->config->set_status(dev, status | VIRTIO_CONFIG_S_DRIVER_OK);
225 : 0 : }
226 : :
227 : : static inline
228 : 0 : const char *virtio_bus_name(struct virtio_device *vdev)
229 : : {
230 [ # # ]: 0 : if (!vdev->config->bus_name)
231 : : return "virtio";
232 : 0 : return vdev->config->bus_name(vdev);
233 : : }
234 : :
235 : : /**
236 : : * virtqueue_set_affinity - setting affinity for a virtqueue
237 : : * @vq: the virtqueue
238 : : * @cpu: the cpu no.
239 : : *
240 : : * Pay attention the function are best-effort: the affinity hint may not be set
241 : : * due to config support, irq type and sharing.
242 : : *
243 : : */
244 : : static inline
245 : 0 : int virtqueue_set_affinity(struct virtqueue *vq, const struct cpumask *cpu_mask)
246 : : {
247 : 0 : struct virtio_device *vdev = vq->vdev;
248 [ # # # # : 0 : if (vdev->config->set_vq_affinity)
# # # # ]
249 : 0 : return vdev->config->set_vq_affinity(vq, cpu_mask);
250 : : return 0;
251 : : }
252 : :
253 : 0 : static inline bool virtio_is_little_endian(struct virtio_device *vdev)
254 : : {
255 : 0 : return virtio_has_feature(vdev, VIRTIO_F_VERSION_1) ||
256 : : virtio_legacy_is_little_endian();
257 : : }
258 : :
259 : : /* Memory accessors */
260 : 0 : static inline u16 virtio16_to_cpu(struct virtio_device *vdev, __virtio16 val)
261 : : {
262 : 0 : return __virtio16_to_cpu(virtio_is_little_endian(vdev), val);
263 : : }
264 : :
265 : 0 : static inline __virtio16 cpu_to_virtio16(struct virtio_device *vdev, u16 val)
266 : : {
267 : 0 : return __cpu_to_virtio16(virtio_is_little_endian(vdev), val);
268 : : }
269 : :
270 : 0 : static inline u32 virtio32_to_cpu(struct virtio_device *vdev, __virtio32 val)
271 : : {
272 : 0 : return __virtio32_to_cpu(virtio_is_little_endian(vdev), val);
273 : : }
274 : :
275 : 0 : static inline __virtio32 cpu_to_virtio32(struct virtio_device *vdev, u32 val)
276 : : {
277 : 0 : return __cpu_to_virtio32(virtio_is_little_endian(vdev), val);
278 : : }
279 : :
280 : 0 : static inline u64 virtio64_to_cpu(struct virtio_device *vdev, __virtio64 val)
281 : : {
282 : 0 : return __virtio64_to_cpu(virtio_is_little_endian(vdev), val);
283 : : }
284 : :
285 : 0 : static inline __virtio64 cpu_to_virtio64(struct virtio_device *vdev, u64 val)
286 : : {
287 : 0 : return __cpu_to_virtio64(virtio_is_little_endian(vdev), val);
288 : : }
289 : :
290 : : /* Config space accessors. */
291 : : #define virtio_cread(vdev, structname, member, ptr) \
292 : : do { \
293 : : might_sleep(); \
294 : : /* Must match the member's type, and be integer */ \
295 : : if (!typecheck(typeof((((structname*)0)->member)), *(ptr))) \
296 : : (*ptr) = 1; \
297 : : \
298 : : switch (sizeof(*ptr)) { \
299 : : case 1: \
300 : : *(ptr) = virtio_cread8(vdev, \
301 : : offsetof(structname, member)); \
302 : : break; \
303 : : case 2: \
304 : : *(ptr) = virtio_cread16(vdev, \
305 : : offsetof(structname, member)); \
306 : : break; \
307 : : case 4: \
308 : : *(ptr) = virtio_cread32(vdev, \
309 : : offsetof(structname, member)); \
310 : : break; \
311 : : case 8: \
312 : : *(ptr) = virtio_cread64(vdev, \
313 : : offsetof(structname, member)); \
314 : : break; \
315 : : default: \
316 : : BUG(); \
317 : : } \
318 : : } while(0)
319 : :
320 : : /* Config space accessors. */
321 : : #define virtio_cwrite(vdev, structname, member, ptr) \
322 : : do { \
323 : : might_sleep(); \
324 : : /* Must match the member's type, and be integer */ \
325 : : if (!typecheck(typeof((((structname*)0)->member)), *(ptr))) \
326 : : BUG_ON((*ptr) == 1); \
327 : : \
328 : : switch (sizeof(*ptr)) { \
329 : : case 1: \
330 : : virtio_cwrite8(vdev, \
331 : : offsetof(structname, member), \
332 : : *(ptr)); \
333 : : break; \
334 : : case 2: \
335 : : virtio_cwrite16(vdev, \
336 : : offsetof(structname, member), \
337 : : *(ptr)); \
338 : : break; \
339 : : case 4: \
340 : : virtio_cwrite32(vdev, \
341 : : offsetof(structname, member), \
342 : : *(ptr)); \
343 : : break; \
344 : : case 8: \
345 : : virtio_cwrite64(vdev, \
346 : : offsetof(structname, member), \
347 : : *(ptr)); \
348 : : break; \
349 : : default: \
350 : : BUG(); \
351 : : } \
352 : : } while(0)
353 : :
354 : : /* Read @count fields, @bytes each. */
355 : 0 : static inline void __virtio_cread_many(struct virtio_device *vdev,
356 : : unsigned int offset,
357 : : void *buf, size_t count, size_t bytes)
358 : : {
359 : 0 : u32 old, gen = vdev->config->generation ?
360 [ # # ]: 0 : vdev->config->generation(vdev) : 0;
361 : 0 : int i;
362 : :
363 : 0 : might_sleep();
364 : 0 : do {
365 : 0 : old = gen;
366 : :
367 [ # # ]: 0 : for (i = 0; i < count; i++)
368 : 0 : vdev->config->get(vdev, offset + bytes * i,
369 : 0 : buf + i * bytes, bytes);
370 : :
371 : 0 : gen = vdev->config->generation ?
372 [ # # ]: 0 : vdev->config->generation(vdev) : 0;
373 [ # # ]: 0 : } while (gen != old);
374 : 0 : }
375 : :
376 : 0 : static inline void virtio_cread_bytes(struct virtio_device *vdev,
377 : : unsigned int offset,
378 : : void *buf, size_t len)
379 : : {
380 : 0 : __virtio_cread_many(vdev, offset, buf, len, 1);
381 : 0 : }
382 : :
383 : 0 : static inline u8 virtio_cread8(struct virtio_device *vdev, unsigned int offset)
384 : : {
385 : 0 : u8 ret;
386 : :
387 : 0 : might_sleep();
388 : 0 : vdev->config->get(vdev, offset, &ret, sizeof(ret));
389 [ # # # # ]: 0 : return ret;
390 : : }
391 : :
392 : 0 : static inline void virtio_cwrite8(struct virtio_device *vdev,
393 : : unsigned int offset, u8 val)
394 : : {
395 : 0 : might_sleep();
396 : 0 : vdev->config->set(vdev, offset, &val, sizeof(val));
397 : : }
398 : :
399 : 0 : static inline u16 virtio_cread16(struct virtio_device *vdev,
400 : : unsigned int offset)
401 : : {
402 : 0 : u16 ret;
403 : :
404 : 0 : might_sleep();
405 : 0 : vdev->config->get(vdev, offset, &ret, sizeof(ret));
406 : 0 : return virtio16_to_cpu(vdev, (__force __virtio16)ret);
407 : : }
408 : :
409 : : static inline void virtio_cwrite16(struct virtio_device *vdev,
410 : : unsigned int offset, u16 val)
411 : : {
412 : : might_sleep();
413 : : val = (__force u16)cpu_to_virtio16(vdev, val);
414 : : vdev->config->set(vdev, offset, &val, sizeof(val));
415 : : }
416 : :
417 : 0 : static inline u32 virtio_cread32(struct virtio_device *vdev,
418 : : unsigned int offset)
419 : : {
420 : 0 : u32 ret;
421 : :
422 : 0 : might_sleep();
423 : 0 : vdev->config->get(vdev, offset, &ret, sizeof(ret));
424 : 0 : return virtio32_to_cpu(vdev, (__force __virtio32)ret);
425 : : }
426 : :
427 : 0 : static inline void virtio_cwrite32(struct virtio_device *vdev,
428 : : unsigned int offset, u32 val)
429 : : {
430 : 0 : might_sleep();
431 : 0 : val = (__force u32)cpu_to_virtio32(vdev, val);
432 : 0 : vdev->config->set(vdev, offset, &val, sizeof(val));
433 : 0 : }
434 : :
435 : 0 : static inline u64 virtio_cread64(struct virtio_device *vdev,
436 : : unsigned int offset)
437 : : {
438 : 0 : u64 ret;
439 : 0 : __virtio_cread_many(vdev, offset, &ret, 1, sizeof(ret));
440 : 0 : return virtio64_to_cpu(vdev, (__force __virtio64)ret);
441 : : }
442 : :
443 : : static inline void virtio_cwrite64(struct virtio_device *vdev,
444 : : unsigned int offset, u64 val)
445 : : {
446 : : might_sleep();
447 : : val = (__force u64)cpu_to_virtio64(vdev, val);
448 : : vdev->config->set(vdev, offset, &val, sizeof(val));
449 : : }
450 : :
451 : : /* Conditional config space accessors. */
452 : : #define virtio_cread_feature(vdev, fbit, structname, member, ptr) \
453 : : ({ \
454 : : int _r = 0; \
455 : : if (!virtio_has_feature(vdev, fbit)) \
456 : : _r = -ENOENT; \
457 : : else \
458 : : virtio_cread((vdev), structname, member, ptr); \
459 : : _r; \
460 : : })
461 : :
462 : : #endif /* _LINUX_VIRTIO_CONFIG_H */
|