@@ -18,6 +18,20 @@ struct virtio_shm_region {
18
18
19
19
typedef void vq_callback_t (struct virtqueue * );
20
20
21
+ /**
22
+ * struct virtqueue_info - Info for a virtqueue passed to find_vqs().
23
+ * @name: virtqueue description. Used mainly for debugging, NULL for
24
+ * a virtqueue unused by the driver.
25
+ * @callback: A callback to invoke on a used buffer notification.
26
+ * NULL for a virtqueue that does not need a callback.
27
+ * @ctx: A flag to indicate to maintain an extra context per virtqueue.
28
+ */
29
+ struct virtqueue_info {
30
+ const char * name ;
31
+ vq_callback_t * callback ;
32
+ bool ctx ;
33
+ };
34
+
21
35
/**
22
36
* struct virtio_config_ops - operations for configuring a virtio device
23
37
* Note: Do not assume that a transport implements all of the operations
@@ -58,6 +72,12 @@ typedef void vq_callback_t(struct virtqueue *);
58
72
* names: array of virtqueue names (mainly for debugging)
59
73
* include a NULL entry for vqs unused by driver
60
74
* Returns 0 on success or error status
75
+ * @find_vqs_info: find virtqueues and instantiate them.
76
+ * vdev: the virtio_device
77
+ * nvqs: the number of virtqueues to find
78
+ * vqs: on success, includes new virtqueues
79
+ * vqs_info: array of virtqueue info structures
80
+ * Returns 0 on success or error status
61
81
* @del_vqs: free virtqueues found by find_vqs().
62
82
* @synchronize_cbs: synchronize with the virtqueue callbacks (optional)
63
83
* The function guarantees that all memory operations on the
@@ -109,6 +129,10 @@ struct virtio_config_ops {
109
129
struct virtqueue * vqs [], vq_callback_t * callbacks [],
110
130
const char * const names [], const bool * ctx ,
111
131
struct irq_affinity * desc );
132
+ int (* find_vqs_info )(struct virtio_device * vdev , unsigned int nvqs ,
133
+ struct virtqueue * vqs [],
134
+ struct virtqueue_info vqs_info [],
135
+ struct irq_affinity * desc );
112
136
void (* del_vqs )(struct virtio_device * );
113
137
void (* synchronize_cbs )(struct virtio_device * );
114
138
u64 (* get_features )(struct virtio_device * vdev );
@@ -117,7 +141,7 @@ struct virtio_config_ops {
117
141
int (* set_vq_affinity )(struct virtqueue * vq ,
118
142
const struct cpumask * cpu_mask );
119
143
const struct cpumask * (* get_vq_affinity )(struct virtio_device * vdev ,
120
- int index );
144
+ int index );
121
145
bool (* get_shm_region )(struct virtio_device * vdev ,
122
146
struct virtio_shm_region * region , u8 id );
123
147
int (* disable_vq_and_reset )(struct virtqueue * vq );
@@ -210,14 +234,39 @@ static inline bool virtio_has_dma_quirk(const struct virtio_device *vdev)
210
234
return !virtio_has_feature (vdev , VIRTIO_F_ACCESS_PLATFORM );
211
235
}
212
236
237
+ static inline
238
+ int virtio_find_vqs_info (struct virtio_device * vdev , unsigned int nvqs ,
239
+ struct virtqueue * vqs [],
240
+ struct virtqueue_info vqs_info [],
241
+ struct irq_affinity * desc )
242
+ {
243
+ return vdev -> config -> find_vqs_info (vdev , nvqs , vqs , vqs_info , desc );
244
+ }
245
+
213
246
static inline
214
247
int virtio_find_vqs_ctx (struct virtio_device * vdev , unsigned nvqs ,
215
248
struct virtqueue * vqs [], vq_callback_t * callbacks [],
216
249
const char * const names [], const bool * ctx ,
217
250
struct irq_affinity * desc )
218
251
{
219
- return vdev -> config -> find_vqs (vdev , nvqs , vqs , callbacks , names , ctx ,
220
- desc );
252
+ struct virtqueue_info * vqs_info ;
253
+ int err , i ;
254
+
255
+ if (!vdev -> config -> find_vqs_info )
256
+ return vdev -> config -> find_vqs (vdev , nvqs , vqs , callbacks ,
257
+ names , ctx , desc );
258
+
259
+ vqs_info = kmalloc_array (nvqs , sizeof (* vqs_info ), GFP_KERNEL );
260
+ if (!vqs_info )
261
+ return - ENOMEM ;
262
+ for (i = 0 ; i < nvqs ; i ++ ) {
263
+ vqs_info [i ].name = names [i ];
264
+ vqs_info [i ].callback = callbacks [i ];
265
+ vqs_info [i ].ctx = ctx ? ctx [i ] : false;
266
+ }
267
+ err = virtio_find_vqs_info (vdev , nvqs , vqs , vqs_info , desc );
268
+ kfree (vqs_info );
269
+ return err ;
221
270
}
222
271
223
272
static inline
0 commit comments