@@ -18,6 +18,20 @@ struct virtio_shm_region {
1818
1919typedef void vq_callback_t (struct virtqueue * );
2020
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+
2135/**
2236 * struct virtio_config_ops - operations for configuring a virtio device
2337 * Note: Do not assume that a transport implements all of the operations
@@ -58,6 +72,12 @@ typedef void vq_callback_t(struct virtqueue *);
5872 * names: array of virtqueue names (mainly for debugging)
5973 * include a NULL entry for vqs unused by driver
6074 * 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
6181 * @del_vqs: free virtqueues found by find_vqs().
6282 * @synchronize_cbs: synchronize with the virtqueue callbacks (optional)
6383 * The function guarantees that all memory operations on the
@@ -109,6 +129,10 @@ struct virtio_config_ops {
109129 struct virtqueue * vqs [], vq_callback_t * callbacks [],
110130 const char * const names [], const bool * ctx ,
111131 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 );
112136 void (* del_vqs )(struct virtio_device * );
113137 void (* synchronize_cbs )(struct virtio_device * );
114138 u64 (* get_features )(struct virtio_device * vdev );
@@ -117,7 +141,7 @@ struct virtio_config_ops {
117141 int (* set_vq_affinity )(struct virtqueue * vq ,
118142 const struct cpumask * cpu_mask );
119143 const struct cpumask * (* get_vq_affinity )(struct virtio_device * vdev ,
120- int index );
144+ int index );
121145 bool (* get_shm_region )(struct virtio_device * vdev ,
122146 struct virtio_shm_region * region , u8 id );
123147 int (* disable_vq_and_reset )(struct virtqueue * vq );
@@ -210,14 +234,39 @@ static inline bool virtio_has_dma_quirk(const struct virtio_device *vdev)
210234 return !virtio_has_feature (vdev , VIRTIO_F_ACCESS_PLATFORM );
211235}
212236
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+
213246static inline
214247int virtio_find_vqs_ctx (struct virtio_device * vdev , unsigned nvqs ,
215248 struct virtqueue * vqs [], vq_callback_t * callbacks [],
216249 const char * const names [], const bool * ctx ,
217250 struct irq_affinity * desc )
218251{
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 ;
221270}
222271
223272static inline
0 commit comments