Blame view

include/linux/virtio_config.h 11.9 KB
ec3d41c4d   Rusty Russell   Virtio interface
1
2
  #ifndef _LINUX_VIRTIO_CONFIG_H
  #define _LINUX_VIRTIO_CONFIG_H
b4f68be6c   Rusty Russell   virtio: force cal...
3

d2a7ddda9   Michael S. Tsirkin   virtio: find_vqs/...
4
  #include <linux/err.h>
187f1882b   Paul Gortmaker   BUG: headers with...
5
  #include <linux/bug.h>
72e61eb40   Rusty Russell   virtio: change co...
6
  #include <linux/virtio.h>
eef960a04   Michael S. Tsirkin   virtio: memory ac...
7
  #include <linux/virtio_byteorder.h>
607ca46e9   David Howells   UAPI: (Scripted) ...
8
  #include <uapi/linux/virtio_config.h>
ec3d41c4d   Rusty Russell   Virtio interface
9
10
11
  
  /**
   * virtio_config_ops - operations for configuring a virtio device
a586d4f60   Rusty Russell   virtio: simplify ...
12
   * @get: read the value of a configuration field
ec3d41c4d   Rusty Russell   Virtio interface
13
   *	vdev: the virtio_device
a586d4f60   Rusty Russell   virtio: simplify ...
14
   *	offset: the offset of the configuration field
ec3d41c4d   Rusty Russell   Virtio interface
15
   *	buf: the buffer to write the field value into.
a586d4f60   Rusty Russell   virtio: simplify ...
16
   *	len: the length of the buffer
a586d4f60   Rusty Russell   virtio: simplify ...
17
   * @set: write the value of a configuration field
ec3d41c4d   Rusty Russell   Virtio interface
18
   *	vdev: the virtio_device
a586d4f60   Rusty Russell   virtio: simplify ...
19
   *	offset: the offset of the configuration field
ec3d41c4d   Rusty Russell   Virtio interface
20
   *	buf: the buffer to read the field value from.
a586d4f60   Rusty Russell   virtio: simplify ...
21
   *	len: the length of the buffer
d71de9ec6   Michael S. Tsirkin   virtio: core supp...
22
23
24
   * @generation: config generation counter
   *	vdev: the virtio_device
   *	Returns the config generation counter
ec3d41c4d   Rusty Russell   Virtio interface
25
26
27
28
29
30
   * @get_status: read the status byte
   *	vdev: the virtio_device
   *	Returns the status byte
   * @set_status: write the status byte
   *	vdev: the virtio_device
   *	status: the new status byte
6e5aa7efb   Rusty Russell   virtio: reset fun...
31
32
33
   * @reset: reset the device
   *	vdev: the virtio device
   *	After this, status and feature negotiation must be done again
e6af578c5   Michael S. Tsirkin   virtio-pci: make ...
34
35
   *	Device must not be reset from its vq/config callbacks, or in
   *	parallel with being added/removed.
d2a7ddda9   Michael S. Tsirkin   virtio: find_vqs/...
36
   * @find_vqs: find virtqueues and instantiate them.
ec3d41c4d   Rusty Russell   Virtio interface
37
   *	vdev: the virtio_device
d2a7ddda9   Michael S. Tsirkin   virtio: find_vqs/...
38
39
40
   *	nvqs: the number of virtqueues to find
   *	vqs: on success, includes new virtqueues
   *	callbacks: array of callbacks, for each virtqueue
6457f126c   Michael S. Tsirkin   virtio: support r...
41
   *		include a NULL entry for vqs that do not need a callback
d2a7ddda9   Michael S. Tsirkin   virtio: find_vqs/...
42
   *	names: array of virtqueue names (mainly for debugging)
6457f126c   Michael S. Tsirkin   virtio: support r...
43
   *		include a NULL entry for vqs unused by driver
d2a7ddda9   Michael S. Tsirkin   virtio: find_vqs/...
44
45
   *	Returns 0 on success or error status
   * @del_vqs: free virtqueues found by find_vqs().
c45a6816c   Rusty Russell   virtio: explicit ...
46
47
48
   * @get_features: get the array of feature bits for this device.
   *	vdev: the virtio_device
   *	Returns the first 32 feature bits (all we currently need).
c624896e4   Rusty Russell   virtio: Rename se...
49
   * @finalize_features: confirm what device features we'll be using.
c45a6816c   Rusty Russell   virtio: explicit ...
50
   *	vdev: the virtio_device
c624896e4   Rusty Russell   virtio: Rename se...
51
52
   *	This gives the final feature bits for the device: it can change
   *	the dev->feature bits if it wants.
5c609a5ef   Michael S. Tsirkin   virtio: allow fin...
53
   *	Returns 0 on success or error status
66846048f   Rick Jones   enable virtio_net...
54
55
56
57
   * @bus_name: return the bus name associated with the device
   *	vdev: the virtio_device
   *      This returns a pointer to the bus name a la pci_name from which
   *      the caller can then copy.
75a0a52be   Jason Wang   virtio: introduce...
58
   * @set_vq_affinity: set the affinity for a virtqueue.
ec3d41c4d   Rusty Russell   Virtio interface
59
   */
d2a7ddda9   Michael S. Tsirkin   virtio: find_vqs/...
60
  typedef void vq_callback_t(struct virtqueue *);
1842f23c0   Rusty Russell   lguest and virtio...
61
  struct virtio_config_ops {
a586d4f60   Rusty Russell   virtio: simplify ...
62
  	void (*get)(struct virtio_device *vdev, unsigned offset,
ec3d41c4d   Rusty Russell   Virtio interface
63
  		    void *buf, unsigned len);
a586d4f60   Rusty Russell   virtio: simplify ...
64
  	void (*set)(struct virtio_device *vdev, unsigned offset,
ec3d41c4d   Rusty Russell   Virtio interface
65
  		    const void *buf, unsigned len);
d71de9ec6   Michael S. Tsirkin   virtio: core supp...
66
  	u32 (*generation)(struct virtio_device *vdev);
ec3d41c4d   Rusty Russell   Virtio interface
67
68
  	u8 (*get_status)(struct virtio_device *vdev);
  	void (*set_status)(struct virtio_device *vdev, u8 status);
6e5aa7efb   Rusty Russell   virtio: reset fun...
69
  	void (*reset)(struct virtio_device *vdev);
d2a7ddda9   Michael S. Tsirkin   virtio: find_vqs/...
70
71
72
  	int (*find_vqs)(struct virtio_device *, unsigned nvqs,
  			struct virtqueue *vqs[],
  			vq_callback_t *callbacks[],
f7ad26ff9   Stefan Hajnoczi   virtio: make find...
73
  			const char * const names[]);
d2a7ddda9   Michael S. Tsirkin   virtio: find_vqs/...
74
  	void (*del_vqs)(struct virtio_device *);
d02547736   Michael S. Tsirkin   virtio: add suppo...
75
  	u64 (*get_features)(struct virtio_device *vdev);
5c609a5ef   Michael S. Tsirkin   virtio: allow fin...
76
  	int (*finalize_features)(struct virtio_device *vdev);
66846048f   Rick Jones   enable virtio_net...
77
  	const char *(*bus_name)(struct virtio_device *vdev);
75a0a52be   Jason Wang   virtio: introduce...
78
  	int (*set_vq_affinity)(struct virtqueue *vq, int cpu);
ec3d41c4d   Rusty Russell   Virtio interface
79
  };
c45a6816c   Rusty Russell   virtio: explicit ...
80
81
82
83
84
  /* If driver didn't advertise the feature, it will never appear. */
  void virtio_check_driver_offered_feature(const struct virtio_device *vdev,
  					 unsigned int fbit);
  
  /**
d4024af56   Michael S. Tsirkin   virtio: add low-l...
85
86
87
   * __virtio_test_bit - helper to test feature bits. For use by transports.
   *                     Devices should normally use virtio_has_feature,
   *                     which includes more checks.
c45a6816c   Rusty Russell   virtio: explicit ...
88
89
90
   * @vdev: the device
   * @fbit: the feature bit
   */
d4024af56   Michael S. Tsirkin   virtio: add low-l...
91
92
93
94
95
  static inline bool __virtio_test_bit(const struct virtio_device *vdev,
  				     unsigned int fbit)
  {
  	/* Did you forget to fix assumptions on max features? */
  	if (__builtin_constant_p(fbit))
d02547736   Michael S. Tsirkin   virtio: add suppo...
96
  		BUILD_BUG_ON(fbit >= 64);
d4024af56   Michael S. Tsirkin   virtio: add low-l...
97
  	else
d02547736   Michael S. Tsirkin   virtio: add suppo...
98
  		BUG_ON(fbit >= 64);
d4024af56   Michael S. Tsirkin   virtio: add low-l...
99

d02547736   Michael S. Tsirkin   virtio: add suppo...
100
  	return vdev->features & BIT_ULL(fbit);
d4024af56   Michael S. Tsirkin   virtio: add low-l...
101
102
103
104
105
106
107
108
109
110
111
112
  }
  
  /**
   * __virtio_set_bit - helper to set feature bits. For use by transports.
   * @vdev: the device
   * @fbit: the feature bit
   */
  static inline void __virtio_set_bit(struct virtio_device *vdev,
  				    unsigned int fbit)
  {
  	/* Did you forget to fix assumptions on max features? */
  	if (__builtin_constant_p(fbit))
d02547736   Michael S. Tsirkin   virtio: add suppo...
113
  		BUILD_BUG_ON(fbit >= 64);
d4024af56   Michael S. Tsirkin   virtio: add low-l...
114
  	else
d02547736   Michael S. Tsirkin   virtio: add suppo...
115
  		BUG_ON(fbit >= 64);
d4024af56   Michael S. Tsirkin   virtio: add low-l...
116

d02547736   Michael S. Tsirkin   virtio: add suppo...
117
  	vdev->features |= BIT_ULL(fbit);
d4024af56   Michael S. Tsirkin   virtio: add low-l...
118
119
120
121
122
123
124
125
  }
  
  /**
   * __virtio_clear_bit - helper to clear feature bits. For use by transports.
   * @vdev: the device
   * @fbit: the feature bit
   */
  static inline void __virtio_clear_bit(struct virtio_device *vdev,
c45a6816c   Rusty Russell   virtio: explicit ...
126
127
128
  				      unsigned int fbit)
  {
  	/* Did you forget to fix assumptions on max features? */
1765e3a49   Rusty Russell   Remove MAYBE_BUIL...
129
  	if (__builtin_constant_p(fbit))
d02547736   Michael S. Tsirkin   virtio: add suppo...
130
  		BUILD_BUG_ON(fbit >= 64);
1765e3a49   Rusty Russell   Remove MAYBE_BUIL...
131
  	else
d02547736   Michael S. Tsirkin   virtio: add suppo...
132
  		BUG_ON(fbit >= 64);
c45a6816c   Rusty Russell   virtio: explicit ...
133

d02547736   Michael S. Tsirkin   virtio: add suppo...
134
  	vdev->features &= ~BIT_ULL(fbit);
d4024af56   Michael S. Tsirkin   virtio: add low-l...
135
136
137
138
139
140
141
142
143
144
  }
  
  /**
   * virtio_has_feature - helper to determine if this device has this feature.
   * @vdev: the device
   * @fbit: the feature bit
   */
  static inline bool virtio_has_feature(const struct virtio_device *vdev,
  				      unsigned int fbit)
  {
ee006b353   Mark McLoughlin   virtio: teach vir...
145
146
  	if (fbit < VIRTIO_TRANSPORT_F_START)
  		virtio_check_driver_offered_feature(vdev, fbit);
d4024af56   Michael S. Tsirkin   virtio: add low-l...
147
  	return __virtio_test_bit(vdev, fbit);
c45a6816c   Rusty Russell   virtio: explicit ...
148
  }
1a9376939   Michael S. Tsirkin   virtio: new featu...
149
150
151
152
153
154
155
156
157
158
159
160
  /**
   * virtio_has_iommu_quirk - determine whether this device has the iommu quirk
   * @vdev: the device
   */
  static inline bool virtio_has_iommu_quirk(const struct virtio_device *vdev)
  {
  	/*
  	 * Note the reverse polarity of the quirk feature (compared to most
  	 * other features), this is for compatibility with legacy systems.
  	 */
  	return !virtio_has_feature(vdev, VIRTIO_F_IOMMU_PLATFORM);
  }
d2a7ddda9   Michael S. Tsirkin   virtio: find_vqs/...
161
162
163
164
165
166
167
168
169
170
171
172
  static inline
  struct virtqueue *virtio_find_single_vq(struct virtio_device *vdev,
  					vq_callback_t *c, const char *n)
  {
  	vq_callback_t *callbacks[] = { c };
  	const char *names[] = { n };
  	struct virtqueue *vq;
  	int err = vdev->config->find_vqs(vdev, 1, &vq, callbacks, names);
  	if (err < 0)
  		return ERR_PTR(err);
  	return vq;
  }
66846048f   Rick Jones   enable virtio_net...
173

3569db593   Michael S. Tsirkin   virtio: add API t...
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
  /**
   * virtio_device_ready - enable vq use in probe function
   * @vdev: the device
   *
   * Driver must call this to use vqs in the probe function.
   *
   * Note: vqs are enabled automatically after probe returns.
   */
  static inline
  void virtio_device_ready(struct virtio_device *dev)
  {
  	unsigned status = dev->config->get_status(dev);
  
  	BUG_ON(status & VIRTIO_CONFIG_S_DRIVER_OK);
  	dev->config->set_status(dev, status | VIRTIO_CONFIG_S_DRIVER_OK);
  }
66846048f   Rick Jones   enable virtio_net...
190
191
192
193
194
195
196
  static inline
  const char *virtio_bus_name(struct virtio_device *vdev)
  {
  	if (!vdev->config->bus_name)
  		return "virtio";
  	return vdev->config->bus_name(vdev);
  }
75a0a52be   Jason Wang   virtio: introduce...
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
  /**
   * virtqueue_set_affinity - setting affinity for a virtqueue
   * @vq: the virtqueue
   * @cpu: the cpu no.
   *
   * Pay attention the function are best-effort: the affinity hint may not be set
   * due to config support, irq type and sharing.
   *
   */
  static inline
  int virtqueue_set_affinity(struct virtqueue *vq, int cpu)
  {
  	struct virtio_device *vdev = vq->vdev;
  	if (vdev->config->set_vq_affinity)
  		return vdev->config->set_vq_affinity(vq, cpu);
  	return 0;
  }
cf561f0d2   Greg Kurz   virtio: introduce...
214
215
  static inline bool virtio_is_little_endian(struct virtio_device *vdev)
  {
7d8241095   Greg Kurz   virtio: add expli...
216
217
  	return virtio_has_feature(vdev, VIRTIO_F_VERSION_1) ||
  		virtio_legacy_is_little_endian();
cf561f0d2   Greg Kurz   virtio: introduce...
218
  }
eef960a04   Michael S. Tsirkin   virtio: memory ac...
219
220
221
  /* Memory accessors */
  static inline u16 virtio16_to_cpu(struct virtio_device *vdev, __virtio16 val)
  {
cf561f0d2   Greg Kurz   virtio: introduce...
222
  	return __virtio16_to_cpu(virtio_is_little_endian(vdev), val);
eef960a04   Michael S. Tsirkin   virtio: memory ac...
223
224
225
226
  }
  
  static inline __virtio16 cpu_to_virtio16(struct virtio_device *vdev, u16 val)
  {
cf561f0d2   Greg Kurz   virtio: introduce...
227
  	return __cpu_to_virtio16(virtio_is_little_endian(vdev), val);
eef960a04   Michael S. Tsirkin   virtio: memory ac...
228
229
230
231
  }
  
  static inline u32 virtio32_to_cpu(struct virtio_device *vdev, __virtio32 val)
  {
cf561f0d2   Greg Kurz   virtio: introduce...
232
  	return __virtio32_to_cpu(virtio_is_little_endian(vdev), val);
eef960a04   Michael S. Tsirkin   virtio: memory ac...
233
234
235
236
  }
  
  static inline __virtio32 cpu_to_virtio32(struct virtio_device *vdev, u32 val)
  {
cf561f0d2   Greg Kurz   virtio: introduce...
237
  	return __cpu_to_virtio32(virtio_is_little_endian(vdev), val);
eef960a04   Michael S. Tsirkin   virtio: memory ac...
238
239
240
241
  }
  
  static inline u64 virtio64_to_cpu(struct virtio_device *vdev, __virtio64 val)
  {
cf561f0d2   Greg Kurz   virtio: introduce...
242
  	return __virtio64_to_cpu(virtio_is_little_endian(vdev), val);
eef960a04   Michael S. Tsirkin   virtio: memory ac...
243
244
245
246
  }
  
  static inline __virtio64 cpu_to_virtio64(struct virtio_device *vdev, u64 val)
  {
cf561f0d2   Greg Kurz   virtio: introduce...
247
  	return __cpu_to_virtio64(virtio_is_little_endian(vdev), val);
eef960a04   Michael S. Tsirkin   virtio: memory ac...
248
  }
0b90d0622   Rusty Russell   virtio_config: in...
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
  /* Config space accessors. */
  #define virtio_cread(vdev, structname, member, ptr)			\
  	do {								\
  		/* Must match the member's type, and be integer */	\
  		if (!typecheck(typeof((((structname*)0)->member)), *(ptr))) \
  			(*ptr) = 1;					\
  									\
  		switch (sizeof(*ptr)) {					\
  		case 1:							\
  			*(ptr) = virtio_cread8(vdev,			\
  					       offsetof(structname, member)); \
  			break;						\
  		case 2:							\
  			*(ptr) = virtio_cread16(vdev,			\
  						offsetof(structname, member)); \
  			break;						\
  		case 4:							\
  			*(ptr) = virtio_cread32(vdev,			\
  						offsetof(structname, member)); \
  			break;						\
  		case 8:							\
  			*(ptr) = virtio_cread64(vdev,			\
  						offsetof(structname, member)); \
  			break;						\
  		default:						\
  			BUG();						\
  		}							\
  	} while(0)
  
  /* Config space accessors. */
  #define virtio_cwrite(vdev, structname, member, ptr)			\
  	do {								\
  		/* Must match the member's type, and be integer */	\
  		if (!typecheck(typeof((((structname*)0)->member)), *(ptr))) \
  			BUG_ON((*ptr) == 1);				\
  									\
  		switch (sizeof(*ptr)) {					\
  		case 1:							\
  			virtio_cwrite8(vdev,				\
  				       offsetof(structname, member),	\
  				       *(ptr));				\
  			break;						\
  		case 2:							\
  			virtio_cwrite16(vdev,				\
  					offsetof(structname, member),	\
  					*(ptr));			\
  			break;						\
  		case 4:							\
  			virtio_cwrite32(vdev,				\
  					offsetof(structname, member),	\
  					*(ptr));			\
  			break;						\
  		case 8:							\
  			virtio_cwrite64(vdev,				\
  					offsetof(structname, member),	\
  					*(ptr));			\
  			break;						\
  		default:						\
  			BUG();						\
  		}							\
  	} while(0)
d71de9ec6   Michael S. Tsirkin   virtio: core supp...
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
  /* Read @count fields, @bytes each. */
  static inline void __virtio_cread_many(struct virtio_device *vdev,
  				       unsigned int offset,
  				       void *buf, size_t count, size_t bytes)
  {
  	u32 old, gen = vdev->config->generation ?
  		vdev->config->generation(vdev) : 0;
  	int i;
  
  	do {
  		old = gen;
  
  		for (i = 0; i < count; i++)
  			vdev->config->get(vdev, offset + bytes * i,
  					  buf + i * bytes, bytes);
  
  		gen = vdev->config->generation ?
  			vdev->config->generation(vdev) : 0;
  	} while (gen != old);
  }
0b90d0622   Rusty Russell   virtio_config: in...
330
331
332
333
  static inline void virtio_cread_bytes(struct virtio_device *vdev,
  				      unsigned int offset,
  				      void *buf, size_t len)
  {
d71de9ec6   Michael S. Tsirkin   virtio: core supp...
334
  	__virtio_cread_many(vdev, offset, buf, len, 1);
0b90d0622   Rusty Russell   virtio_config: in...
335
  }
caa0e2d0e   Michael S. Tsirkin   virtio_config: re...
336
337
338
339
340
341
  static inline u8 virtio_cread8(struct virtio_device *vdev, unsigned int offset)
  {
  	u8 ret;
  	vdev->config->get(vdev, offset, &ret, sizeof(ret));
  	return ret;
  }
0b90d0622   Rusty Russell   virtio_config: in...
342
343
344
345
346
347
348
349
350
351
352
  static inline void virtio_cwrite8(struct virtio_device *vdev,
  				  unsigned int offset, u8 val)
  {
  	vdev->config->set(vdev, offset, &val, sizeof(val));
  }
  
  static inline u16 virtio_cread16(struct virtio_device *vdev,
  				 unsigned int offset)
  {
  	u16 ret;
  	vdev->config->get(vdev, offset, &ret, sizeof(ret));
92e6d7438   Michael S. Tsirkin   virtio_config: en...
353
  	return virtio16_to_cpu(vdev, (__force __virtio16)ret);
0b90d0622   Rusty Russell   virtio_config: in...
354
355
356
357
358
  }
  
  static inline void virtio_cwrite16(struct virtio_device *vdev,
  				   unsigned int offset, u16 val)
  {
92e6d7438   Michael S. Tsirkin   virtio_config: en...
359
  	val = (__force u16)cpu_to_virtio16(vdev, val);
0b90d0622   Rusty Russell   virtio_config: in...
360
361
362
363
364
365
366
367
  	vdev->config->set(vdev, offset, &val, sizeof(val));
  }
  
  static inline u32 virtio_cread32(struct virtio_device *vdev,
  				 unsigned int offset)
  {
  	u32 ret;
  	vdev->config->get(vdev, offset, &ret, sizeof(ret));
92e6d7438   Michael S. Tsirkin   virtio_config: en...
368
  	return virtio32_to_cpu(vdev, (__force __virtio32)ret);
0b90d0622   Rusty Russell   virtio_config: in...
369
370
371
372
373
  }
  
  static inline void virtio_cwrite32(struct virtio_device *vdev,
  				   unsigned int offset, u32 val)
  {
92e6d7438   Michael S. Tsirkin   virtio_config: en...
374
  	val = (__force u32)cpu_to_virtio32(vdev, val);
0b90d0622   Rusty Russell   virtio_config: in...
375
376
377
378
379
380
381
  	vdev->config->set(vdev, offset, &val, sizeof(val));
  }
  
  static inline u64 virtio_cread64(struct virtio_device *vdev,
  				 unsigned int offset)
  {
  	u64 ret;
d71de9ec6   Michael S. Tsirkin   virtio: core supp...
382
  	__virtio_cread_many(vdev, offset, &ret, 1, sizeof(ret));
92e6d7438   Michael S. Tsirkin   virtio_config: en...
383
  	return virtio64_to_cpu(vdev, (__force __virtio64)ret);
0b90d0622   Rusty Russell   virtio_config: in...
384
385
386
387
388
  }
  
  static inline void virtio_cwrite64(struct virtio_device *vdev,
  				   unsigned int offset, u64 val)
  {
92e6d7438   Michael S. Tsirkin   virtio_config: en...
389
  	val = (__force u64)cpu_to_virtio64(vdev, val);
0b90d0622   Rusty Russell   virtio_config: in...
390
391
392
393
394
395
396
397
398
399
400
401
402
  	vdev->config->set(vdev, offset, &val, sizeof(val));
  }
  
  /* Conditional config space accessors. */
  #define virtio_cread_feature(vdev, fbit, structname, member, ptr)	\
  	({								\
  		int _r = 0;						\
  		if (!virtio_has_feature(vdev, fbit))			\
  			_r = -ENOENT;					\
  		else							\
  			virtio_cread((vdev), structname, member, ptr);	\
  		_r;							\
  	})
75a0a52be   Jason Wang   virtio: introduce...
403

ec3d41c4d   Rusty Russell   Virtio interface
404
  #endif /* _LINUX_VIRTIO_CONFIG_H */