Branch data Line data Source code
1 : : // SPDX-License-Identifier: GPL-2.0-or-later
2 : : /*
3 : : * Virtio PCI driver - common functionality for all device versions
4 : : *
5 : : * This module allows virtio devices to be used over a virtual PCI device.
6 : : * This can be used with QEMU based VMMs like KVM or Xen.
7 : : *
8 : : * Copyright IBM Corp. 2007
9 : : * Copyright Red Hat, Inc. 2014
10 : : *
11 : : * Authors:
12 : : * Anthony Liguori <aliguori@us.ibm.com>
13 : : * Rusty Russell <rusty@rustcorp.com.au>
14 : : * Michael S. Tsirkin <mst@redhat.com>
15 : : */
16 : :
17 : : #include "virtio_pci_common.h"
18 : :
19 : : static bool force_legacy = false;
20 : :
21 : : #if IS_ENABLED(CONFIG_VIRTIO_PCI_LEGACY)
22 : : module_param(force_legacy, bool, 0444);
23 : : MODULE_PARM_DESC(force_legacy,
24 : : "Force legacy mode for transitional virtio 1 devices");
25 : : #endif
26 : :
27 : : /* wait for pending irq handlers */
28 : 0 : void vp_synchronize_vectors(struct virtio_device *vdev)
29 : : {
30 [ # # ]: 0 : struct virtio_pci_device *vp_dev = to_vp_device(vdev);
31 : 0 : int i;
32 : :
33 [ # # ]: 0 : if (vp_dev->intx_enabled)
34 : 0 : synchronize_irq(vp_dev->pci_dev->irq);
35 : :
36 [ # # ]: 0 : for (i = 0; i < vp_dev->msix_vectors; ++i)
37 : 0 : synchronize_irq(pci_irq_vector(vp_dev->pci_dev, i));
38 : 0 : }
39 : :
40 : : /* the notify function used when creating a virt queue */
41 : 0 : bool vp_notify(struct virtqueue *vq)
42 : : {
43 : : /* we write the queue's selector into the notification register to
44 : : * signal the other end */
45 : 0 : iowrite16(vq->index, (void __iomem *)vq->priv);
46 : 0 : return true;
47 : : }
48 : :
49 : : /* Handle a configuration change: Tell driver if it wants to know. */
50 : 0 : static irqreturn_t vp_config_changed(int irq, void *opaque)
51 : : {
52 : 0 : struct virtio_pci_device *vp_dev = opaque;
53 : :
54 : 0 : virtio_config_changed(&vp_dev->vdev);
55 : 0 : return IRQ_HANDLED;
56 : : }
57 : :
58 : : /* Notify all virtqueues on an interrupt. */
59 : 0 : static irqreturn_t vp_vring_interrupt(int irq, void *opaque)
60 : : {
61 : 0 : struct virtio_pci_device *vp_dev = opaque;
62 : 0 : struct virtio_pci_vq_info *info;
63 : 0 : irqreturn_t ret = IRQ_NONE;
64 : 0 : unsigned long flags;
65 : :
66 : 0 : spin_lock_irqsave(&vp_dev->lock, flags);
67 [ # # ]: 0 : list_for_each_entry(info, &vp_dev->virtqueues, node) {
68 [ # # ]: 0 : if (vring_interrupt(irq, info->vq) == IRQ_HANDLED)
69 : 0 : ret = IRQ_HANDLED;
70 : : }
71 : 0 : spin_unlock_irqrestore(&vp_dev->lock, flags);
72 : :
73 : 0 : return ret;
74 : : }
75 : :
76 : : /* A small wrapper to also acknowledge the interrupt when it's handled.
77 : : * I really need an EIO hook for the vring so I can ack the interrupt once we
78 : : * know that we'll be handling the IRQ but before we invoke the callback since
79 : : * the callback may notify the host which results in the host attempting to
80 : : * raise an interrupt that we would then mask once we acknowledged the
81 : : * interrupt. */
82 : 0 : static irqreturn_t vp_interrupt(int irq, void *opaque)
83 : : {
84 : 0 : struct virtio_pci_device *vp_dev = opaque;
85 : 0 : u8 isr;
86 : :
87 : : /* reading the ISR has the effect of also clearing it so it's very
88 : : * important to save off the value. */
89 : 0 : isr = ioread8(vp_dev->isr);
90 : :
91 : : /* It's definitely not us if the ISR was not high */
92 [ # # ]: 0 : if (!isr)
93 : : return IRQ_NONE;
94 : :
95 : : /* Configuration change? Tell driver if it wants to know. */
96 [ # # ]: 0 : if (isr & VIRTIO_PCI_ISR_CONFIG)
97 : 0 : vp_config_changed(irq, opaque);
98 : :
99 : 0 : return vp_vring_interrupt(irq, opaque);
100 : : }
101 : :
102 : 0 : static int vp_request_msix_vectors(struct virtio_device *vdev, int nvectors,
103 : : bool per_vq_vectors, struct irq_affinity *desc)
104 : : {
105 [ # # ]: 0 : struct virtio_pci_device *vp_dev = to_vp_device(vdev);
106 [ # # ]: 0 : const char *name = dev_name(&vp_dev->vdev.dev);
107 : 0 : unsigned flags = PCI_IRQ_MSIX;
108 : 0 : unsigned i, v;
109 : 0 : int err = -ENOMEM;
110 : :
111 : 0 : vp_dev->msix_vectors = nvectors;
112 : :
113 : 0 : vp_dev->msix_names = kmalloc_array(nvectors,
114 : : sizeof(*vp_dev->msix_names),
115 : : GFP_KERNEL);
116 [ # # ]: 0 : if (!vp_dev->msix_names)
117 : 0 : goto error;
118 : 0 : vp_dev->msix_affinity_masks
119 : 0 : = kcalloc(nvectors, sizeof(*vp_dev->msix_affinity_masks),
120 : : GFP_KERNEL);
121 [ # # ]: 0 : if (!vp_dev->msix_affinity_masks)
122 : 0 : goto error;
123 : 0 : for (i = 0; i < nvectors; ++i)
124 : : if (!alloc_cpumask_var(&vp_dev->msix_affinity_masks[i],
125 : : GFP_KERNEL))
126 : : goto error;
127 : :
128 [ # # ]: 0 : if (desc) {
129 : 0 : flags |= PCI_IRQ_AFFINITY;
130 : 0 : desc->pre_vectors++; /* virtio config vector */
131 : : }
132 : :
133 : 0 : err = pci_alloc_irq_vectors_affinity(vp_dev->pci_dev, nvectors,
134 : : nvectors, flags, desc);
135 [ # # ]: 0 : if (err < 0)
136 : 0 : goto error;
137 : 0 : vp_dev->msix_enabled = 1;
138 : :
139 : : /* Set the vector used for configuration */
140 : 0 : v = vp_dev->msix_used_vectors;
141 : 0 : snprintf(vp_dev->msix_names[v], sizeof *vp_dev->msix_names,
142 : : "%s-config", name);
143 : 0 : err = request_irq(pci_irq_vector(vp_dev->pci_dev, v),
144 : 0 : vp_config_changed, 0, vp_dev->msix_names[v],
145 : : vp_dev);
146 [ # # ]: 0 : if (err)
147 : 0 : goto error;
148 : 0 : ++vp_dev->msix_used_vectors;
149 : :
150 : 0 : v = vp_dev->config_vector(vp_dev, v);
151 : : /* Verify we had enough resources to assign the vector */
152 [ # # ]: 0 : if (v == VIRTIO_MSI_NO_VECTOR) {
153 : 0 : err = -EBUSY;
154 : 0 : goto error;
155 : : }
156 : :
157 [ # # ]: 0 : if (!per_vq_vectors) {
158 : : /* Shared vector for all VQs */
159 : 0 : v = vp_dev->msix_used_vectors;
160 : 0 : snprintf(vp_dev->msix_names[v], sizeof *vp_dev->msix_names,
161 : : "%s-virtqueues", name);
162 : 0 : err = request_irq(pci_irq_vector(vp_dev->pci_dev, v),
163 : 0 : vp_vring_interrupt, 0, vp_dev->msix_names[v],
164 : : vp_dev);
165 [ # # ]: 0 : if (err)
166 : 0 : goto error;
167 : 0 : ++vp_dev->msix_used_vectors;
168 : : }
169 : : return 0;
170 : : error:
171 : : return err;
172 : : }
173 : :
174 : 0 : static struct virtqueue *vp_setup_vq(struct virtio_device *vdev, unsigned index,
175 : : void (*callback)(struct virtqueue *vq),
176 : : const char *name,
177 : : bool ctx,
178 : : u16 msix_vec)
179 : : {
180 : 0 : struct virtio_pci_device *vp_dev = to_vp_device(vdev);
181 : 0 : struct virtio_pci_vq_info *info = kmalloc(sizeof *info, GFP_KERNEL);
182 : 0 : struct virtqueue *vq;
183 : 0 : unsigned long flags;
184 : :
185 : : /* fill out our structure that represents an active queue */
186 [ # # ]: 0 : if (!info)
187 : : return ERR_PTR(-ENOMEM);
188 : :
189 : 0 : vq = vp_dev->setup_vq(vp_dev, info, index, callback, name, ctx,
190 : : msix_vec);
191 [ # # ]: 0 : if (IS_ERR(vq))
192 : 0 : goto out_info;
193 : :
194 : 0 : info->vq = vq;
195 [ # # ]: 0 : if (callback) {
196 : 0 : spin_lock_irqsave(&vp_dev->lock, flags);
197 : 0 : list_add(&info->node, &vp_dev->virtqueues);
198 : 0 : spin_unlock_irqrestore(&vp_dev->lock, flags);
199 : : } else {
200 : 0 : INIT_LIST_HEAD(&info->node);
201 : : }
202 : :
203 : 0 : vp_dev->vqs[index] = info;
204 : 0 : return vq;
205 : :
206 : : out_info:
207 : 0 : kfree(info);
208 : 0 : return vq;
209 : : }
210 : :
211 : : static void vp_del_vq(struct virtqueue *vq)
212 : : {
213 : : struct virtio_pci_device *vp_dev = to_vp_device(vq->vdev);
214 : : struct virtio_pci_vq_info *info = vp_dev->vqs[vq->index];
215 : : unsigned long flags;
216 : :
217 : : spin_lock_irqsave(&vp_dev->lock, flags);
218 : : list_del(&info->node);
219 : : spin_unlock_irqrestore(&vp_dev->lock, flags);
220 : :
221 : : vp_dev->del_vq(info);
222 : : kfree(info);
223 : : }
224 : :
225 : : /* the config->del_vqs() implementation */
226 : 0 : void vp_del_vqs(struct virtio_device *vdev)
227 : : {
228 : 0 : struct virtio_pci_device *vp_dev = to_vp_device(vdev);
229 : 0 : struct virtqueue *vq, *n;
230 : 0 : int i;
231 : :
232 [ # # ]: 0 : list_for_each_entry_safe(vq, n, &vdev->vqs, list) {
233 [ # # ]: 0 : if (vp_dev->per_vq_vectors) {
234 : 0 : int v = vp_dev->vqs[vq->index]->msix_vector;
235 : :
236 [ # # ]: 0 : if (v != VIRTIO_MSI_NO_VECTOR) {
237 : 0 : int irq = pci_irq_vector(vp_dev->pci_dev, v);
238 : :
239 : 0 : irq_set_affinity_hint(irq, NULL);
240 : 0 : free_irq(irq, vq);
241 : : }
242 : : }
243 : 0 : vp_del_vq(vq);
244 : : }
245 : 0 : vp_dev->per_vq_vectors = false;
246 : :
247 [ # # ]: 0 : if (vp_dev->intx_enabled) {
248 : 0 : free_irq(vp_dev->pci_dev->irq, vp_dev);
249 : 0 : vp_dev->intx_enabled = 0;
250 : : }
251 : :
252 [ # # ]: 0 : for (i = 0; i < vp_dev->msix_used_vectors; ++i)
253 : 0 : free_irq(pci_irq_vector(vp_dev->pci_dev, i), vp_dev);
254 : :
255 [ # # ]: 0 : if (vp_dev->msix_affinity_masks) {
256 [ # # ]: 0 : for (i = 0; i < vp_dev->msix_vectors; i++)
257 : 0 : if (vp_dev->msix_affinity_masks[i])
258 : : free_cpumask_var(vp_dev->msix_affinity_masks[i]);
259 : : }
260 : :
261 [ # # ]: 0 : if (vp_dev->msix_enabled) {
262 : : /* Disable the vector used for configuration */
263 : 0 : vp_dev->config_vector(vp_dev, VIRTIO_MSI_NO_VECTOR);
264 : :
265 : 0 : pci_free_irq_vectors(vp_dev->pci_dev);
266 : 0 : vp_dev->msix_enabled = 0;
267 : : }
268 : :
269 : 0 : vp_dev->msix_vectors = 0;
270 : 0 : vp_dev->msix_used_vectors = 0;
271 : 0 : kfree(vp_dev->msix_names);
272 : 0 : vp_dev->msix_names = NULL;
273 : 0 : kfree(vp_dev->msix_affinity_masks);
274 : 0 : vp_dev->msix_affinity_masks = NULL;
275 : 0 : kfree(vp_dev->vqs);
276 : 0 : vp_dev->vqs = NULL;
277 : 0 : }
278 : :
279 : 0 : static int vp_find_vqs_msix(struct virtio_device *vdev, unsigned nvqs,
280 : : struct virtqueue *vqs[], vq_callback_t *callbacks[],
281 : : const char * const names[], bool per_vq_vectors,
282 : : const bool *ctx,
283 : : struct irq_affinity *desc)
284 : : {
285 : 0 : struct virtio_pci_device *vp_dev = to_vp_device(vdev);
286 : 0 : u16 msix_vec;
287 : 0 : int i, err, nvectors, allocated_vectors, queue_idx = 0;
288 : :
289 : 0 : vp_dev->vqs = kcalloc(nvqs, sizeof(*vp_dev->vqs), GFP_KERNEL);
290 [ # # ]: 0 : if (!vp_dev->vqs)
291 : : return -ENOMEM;
292 : :
293 [ # # ]: 0 : if (per_vq_vectors) {
294 : : /* Best option: one for change interrupt, one per vq. */
295 : : nvectors = 1;
296 [ # # ]: 0 : for (i = 0; i < nvqs; ++i)
297 [ # # # # ]: 0 : if (names[i] && callbacks[i])
298 : 0 : ++nvectors;
299 : : } else {
300 : : /* Second best: one for change, shared for all vqs. */
301 : : nvectors = 2;
302 : : }
303 : :
304 [ # # ]: 0 : err = vp_request_msix_vectors(vdev, nvectors, per_vq_vectors,
305 : : per_vq_vectors ? desc : NULL);
306 [ # # ]: 0 : if (err)
307 : 0 : goto error_find;
308 : :
309 : 0 : vp_dev->per_vq_vectors = per_vq_vectors;
310 : 0 : allocated_vectors = vp_dev->msix_used_vectors;
311 [ # # ]: 0 : for (i = 0; i < nvqs; ++i) {
312 [ # # ]: 0 : if (!names[i]) {
313 : 0 : vqs[i] = NULL;
314 : 0 : continue;
315 : : }
316 : :
317 [ # # ]: 0 : if (!callbacks[i])
318 : : msix_vec = VIRTIO_MSI_NO_VECTOR;
319 [ # # ]: 0 : else if (vp_dev->per_vq_vectors)
320 : 0 : msix_vec = allocated_vectors++;
321 : : else
322 : : msix_vec = VP_MSIX_VQ_VECTOR;
323 : 0 : vqs[i] = vp_setup_vq(vdev, queue_idx++, callbacks[i], names[i],
324 [ # # # # ]: 0 : ctx ? ctx[i] : false,
325 : : msix_vec);
326 [ # # ]: 0 : if (IS_ERR(vqs[i])) {
327 : 0 : err = PTR_ERR(vqs[i]);
328 : 0 : goto error_find;
329 : : }
330 : :
331 [ # # # # ]: 0 : if (!vp_dev->per_vq_vectors || msix_vec == VIRTIO_MSI_NO_VECTOR)
332 : 0 : continue;
333 : :
334 : : /* allocate per-vq irq if available and necessary */
335 [ # # ]: 0 : snprintf(vp_dev->msix_names[msix_vec],
336 : : sizeof *vp_dev->msix_names,
337 : : "%s-%s",
338 : : dev_name(&vp_dev->vdev.dev), names[i]);
339 : 0 : err = request_irq(pci_irq_vector(vp_dev->pci_dev, msix_vec),
340 : : vring_interrupt, 0,
341 : 0 : vp_dev->msix_names[msix_vec],
342 : : vqs[i]);
343 [ # # ]: 0 : if (err)
344 : 0 : goto error_find;
345 : : }
346 : : return 0;
347 : :
348 : 0 : error_find:
349 : 0 : vp_del_vqs(vdev);
350 : 0 : return err;
351 : : }
352 : :
353 : 0 : static int vp_find_vqs_intx(struct virtio_device *vdev, unsigned nvqs,
354 : : struct virtqueue *vqs[], vq_callback_t *callbacks[],
355 : : const char * const names[], const bool *ctx)
356 : : {
357 : 0 : struct virtio_pci_device *vp_dev = to_vp_device(vdev);
358 : 0 : int i, err, queue_idx = 0;
359 : :
360 : 0 : vp_dev->vqs = kcalloc(nvqs, sizeof(*vp_dev->vqs), GFP_KERNEL);
361 [ # # ]: 0 : if (!vp_dev->vqs)
362 : : return -ENOMEM;
363 : :
364 [ # # ]: 0 : err = request_irq(vp_dev->pci_dev->irq, vp_interrupt, IRQF_SHARED,
365 : : dev_name(&vdev->dev), vp_dev);
366 [ # # ]: 0 : if (err)
367 : 0 : goto out_del_vqs;
368 : :
369 : 0 : vp_dev->intx_enabled = 1;
370 : 0 : vp_dev->per_vq_vectors = false;
371 [ # # ]: 0 : for (i = 0; i < nvqs; ++i) {
372 [ # # ]: 0 : if (!names[i]) {
373 : 0 : vqs[i] = NULL;
374 : 0 : continue;
375 : : }
376 : 0 : vqs[i] = vp_setup_vq(vdev, queue_idx++, callbacks[i], names[i],
377 [ # # # # ]: 0 : ctx ? ctx[i] : false,
378 : : VIRTIO_MSI_NO_VECTOR);
379 [ # # ]: 0 : if (IS_ERR(vqs[i])) {
380 : 0 : err = PTR_ERR(vqs[i]);
381 : 0 : goto out_del_vqs;
382 : : }
383 : : }
384 : :
385 : : return 0;
386 : 0 : out_del_vqs:
387 : 0 : vp_del_vqs(vdev);
388 : 0 : return err;
389 : : }
390 : :
391 : : /* the config->find_vqs() implementation */
392 : 0 : int vp_find_vqs(struct virtio_device *vdev, unsigned nvqs,
393 : : struct virtqueue *vqs[], vq_callback_t *callbacks[],
394 : : const char * const names[], const bool *ctx,
395 : : struct irq_affinity *desc)
396 : : {
397 : 0 : int err;
398 : :
399 : : /* Try MSI-X with one vector per queue. */
400 : 0 : err = vp_find_vqs_msix(vdev, nvqs, vqs, callbacks, names, true, ctx, desc);
401 [ # # ]: 0 : if (!err)
402 : : return 0;
403 : : /* Fallback: MSI-X with one vector for config, one shared for queues. */
404 : 0 : err = vp_find_vqs_msix(vdev, nvqs, vqs, callbacks, names, false, ctx, desc);
405 [ # # ]: 0 : if (!err)
406 : : return 0;
407 : : /* Finally fall back to regular interrupts. */
408 : 0 : return vp_find_vqs_intx(vdev, nvqs, vqs, callbacks, names, ctx);
409 : : }
410 : :
411 : 0 : const char *vp_bus_name(struct virtio_device *vdev)
412 : : {
413 [ # # ]: 0 : struct virtio_pci_device *vp_dev = to_vp_device(vdev);
414 : :
415 [ # # ]: 0 : return pci_name(vp_dev->pci_dev);
416 : : }
417 : :
418 : : /* Setup the affinity for a virtqueue:
419 : : * - force the affinity for per vq vector
420 : : * - OR over all affinities for shared MSI
421 : : * - ignore the affinity request if we're using INTX
422 : : */
423 : 0 : int vp_set_vq_affinity(struct virtqueue *vq, const struct cpumask *cpu_mask)
424 : : {
425 : 0 : struct virtio_device *vdev = vq->vdev;
426 [ # # ]: 0 : struct virtio_pci_device *vp_dev = to_vp_device(vdev);
427 : 0 : struct virtio_pci_vq_info *info = vp_dev->vqs[vq->index];
428 : 0 : struct cpumask *mask;
429 : 0 : unsigned int irq;
430 : :
431 [ # # ]: 0 : if (!vq->callback)
432 : : return -EINVAL;
433 : :
434 [ # # ]: 0 : if (vp_dev->msix_enabled) {
435 : 0 : mask = vp_dev->msix_affinity_masks[info->msix_vector];
436 : 0 : irq = pci_irq_vector(vp_dev->pci_dev, info->msix_vector);
437 [ # # ]: 0 : if (!cpu_mask)
438 : 0 : irq_set_affinity_hint(irq, NULL);
439 : : else {
440 : 0 : cpumask_copy(mask, cpu_mask);
441 : 0 : irq_set_affinity_hint(irq, mask);
442 : : }
443 : : }
444 : : return 0;
445 : : }
446 : :
447 : 0 : const struct cpumask *vp_get_vq_affinity(struct virtio_device *vdev, int index)
448 : : {
449 [ # # ]: 0 : struct virtio_pci_device *vp_dev = to_vp_device(vdev);
450 : :
451 [ # # ]: 0 : if (!vp_dev->per_vq_vectors ||
452 [ # # ]: 0 : vp_dev->vqs[index]->msix_vector == VIRTIO_MSI_NO_VECTOR)
453 : : return NULL;
454 : :
455 : 0 : return pci_irq_get_affinity(vp_dev->pci_dev,
456 : : vp_dev->vqs[index]->msix_vector);
457 : : }
458 : :
459 : : #ifdef CONFIG_PM_SLEEP
460 : 0 : static int virtio_pci_freeze(struct device *dev)
461 : : {
462 : 0 : struct pci_dev *pci_dev = to_pci_dev(dev);
463 : 0 : struct virtio_pci_device *vp_dev = pci_get_drvdata(pci_dev);
464 : 0 : int ret;
465 : :
466 : 0 : ret = virtio_device_freeze(&vp_dev->vdev);
467 : :
468 [ # # ]: 0 : if (!ret)
469 : 0 : pci_disable_device(pci_dev);
470 : 0 : return ret;
471 : : }
472 : :
473 : 0 : static int virtio_pci_restore(struct device *dev)
474 : : {
475 : 0 : struct pci_dev *pci_dev = to_pci_dev(dev);
476 : 0 : struct virtio_pci_device *vp_dev = pci_get_drvdata(pci_dev);
477 : 0 : int ret;
478 : :
479 : 0 : ret = pci_enable_device(pci_dev);
480 [ # # ]: 0 : if (ret)
481 : : return ret;
482 : :
483 : 0 : pci_set_master(pci_dev);
484 : 0 : return virtio_device_restore(&vp_dev->vdev);
485 : : }
486 : :
487 : : static const struct dev_pm_ops virtio_pci_pm_ops = {
488 : : SET_SYSTEM_SLEEP_PM_OPS(virtio_pci_freeze, virtio_pci_restore)
489 : : };
490 : : #endif
491 : :
492 : :
493 : : /* Qumranet donated their vendor ID for devices 0x1000 thru 0x10FF. */
494 : : static const struct pci_device_id virtio_pci_id_table[] = {
495 : : { PCI_DEVICE(PCI_VENDOR_ID_REDHAT_QUMRANET, PCI_ANY_ID) },
496 : : { 0 }
497 : : };
498 : :
499 : : MODULE_DEVICE_TABLE(pci, virtio_pci_id_table);
500 : :
501 : 0 : static void virtio_pci_release_dev(struct device *_d)
502 : : {
503 : 0 : struct virtio_device *vdev = dev_to_virtio(_d);
504 : 0 : struct virtio_pci_device *vp_dev = to_vp_device(vdev);
505 : :
506 : : /* As struct device is a kobject, it's not safe to
507 : : * free the memory (including the reference counter itself)
508 : : * until it's release callback. */
509 : 0 : kfree(vp_dev);
510 : 0 : }
511 : :
512 : 0 : static int virtio_pci_probe(struct pci_dev *pci_dev,
513 : : const struct pci_device_id *id)
514 : : {
515 : 0 : struct virtio_pci_device *vp_dev, *reg_dev = NULL;
516 : 0 : int rc;
517 : :
518 : : /* allocate our structure and fill it out */
519 : 0 : vp_dev = kzalloc(sizeof(struct virtio_pci_device), GFP_KERNEL);
520 [ # # ]: 0 : if (!vp_dev)
521 : : return -ENOMEM;
522 : :
523 : 0 : pci_set_drvdata(pci_dev, vp_dev);
524 : 0 : vp_dev->vdev.dev.parent = &pci_dev->dev;
525 : 0 : vp_dev->vdev.dev.release = virtio_pci_release_dev;
526 : 0 : vp_dev->pci_dev = pci_dev;
527 : 0 : INIT_LIST_HEAD(&vp_dev->virtqueues);
528 : 0 : spin_lock_init(&vp_dev->lock);
529 : :
530 : : /* enable the device */
531 : 0 : rc = pci_enable_device(pci_dev);
532 [ # # ]: 0 : if (rc)
533 : 0 : goto err_enable_device;
534 : :
535 [ # # ]: 0 : if (force_legacy) {
536 : 0 : rc = virtio_pci_legacy_probe(vp_dev);
537 : : /* Also try modern mode if we can't map BAR0 (no IO space). */
538 [ # # ]: 0 : if (rc == -ENODEV || rc == -ENOMEM)
539 : 0 : rc = virtio_pci_modern_probe(vp_dev);
540 [ # # ]: 0 : if (rc)
541 : 0 : goto err_probe;
542 : : } else {
543 : 0 : rc = virtio_pci_modern_probe(vp_dev);
544 [ # # ]: 0 : if (rc == -ENODEV)
545 : 0 : rc = virtio_pci_legacy_probe(vp_dev);
546 [ # # ]: 0 : if (rc)
547 : 0 : goto err_probe;
548 : : }
549 : :
550 : 0 : pci_set_master(pci_dev);
551 : :
552 : 0 : rc = register_virtio_device(&vp_dev->vdev);
553 : 0 : reg_dev = vp_dev;
554 [ # # ]: 0 : if (rc)
555 : 0 : goto err_register;
556 : :
557 : : return 0;
558 : :
559 : : err_register:
560 [ # # ]: 0 : if (vp_dev->ioaddr)
561 : 0 : virtio_pci_legacy_remove(vp_dev);
562 : : else
563 : 0 : virtio_pci_modern_remove(vp_dev);
564 : 0 : err_probe:
565 : 0 : pci_disable_device(pci_dev);
566 : : err_enable_device:
567 [ # # ]: 0 : if (reg_dev)
568 : 0 : put_device(&vp_dev->vdev.dev);
569 : : else
570 : 0 : kfree(vp_dev);
571 : : return rc;
572 : : }
573 : :
574 : 0 : static void virtio_pci_remove(struct pci_dev *pci_dev)
575 : : {
576 : 0 : struct virtio_pci_device *vp_dev = pci_get_drvdata(pci_dev);
577 : 0 : struct device *dev = get_device(&vp_dev->vdev.dev);
578 : :
579 : 0 : pci_disable_sriov(pci_dev);
580 : :
581 : 0 : unregister_virtio_device(&vp_dev->vdev);
582 : :
583 [ # # ]: 0 : if (vp_dev->ioaddr)
584 : 0 : virtio_pci_legacy_remove(vp_dev);
585 : : else
586 : 0 : virtio_pci_modern_remove(vp_dev);
587 : :
588 : 0 : pci_disable_device(pci_dev);
589 : 0 : put_device(dev);
590 : 0 : }
591 : :
592 : 0 : static int virtio_pci_sriov_configure(struct pci_dev *pci_dev, int num_vfs)
593 : : {
594 : 0 : struct virtio_pci_device *vp_dev = pci_get_drvdata(pci_dev);
595 : 0 : struct virtio_device *vdev = &vp_dev->vdev;
596 : 0 : int ret;
597 : :
598 [ # # ]: 0 : if (!(vdev->config->get_status(vdev) & VIRTIO_CONFIG_S_DRIVER_OK))
599 : : return -EBUSY;
600 : :
601 [ # # ]: 0 : if (!__virtio_test_bit(vdev, VIRTIO_F_SR_IOV))
602 : : return -EINVAL;
603 : :
604 [ # # ]: 0 : if (pci_vfs_assigned(pci_dev))
605 : : return -EPERM;
606 : :
607 [ # # ]: 0 : if (num_vfs == 0) {
608 : : pci_disable_sriov(pci_dev);
609 : : return 0;
610 : : }
611 : :
612 : 0 : ret = pci_enable_sriov(pci_dev, num_vfs);
613 : 0 : if (ret < 0)
614 : 0 : return ret;
615 : :
616 : : return num_vfs;
617 : : }
618 : :
619 : : static struct pci_driver virtio_pci_driver = {
620 : : .name = "virtio-pci",
621 : : .id_table = virtio_pci_id_table,
622 : : .probe = virtio_pci_probe,
623 : : .remove = virtio_pci_remove,
624 : : #ifdef CONFIG_PM_SLEEP
625 : : .driver.pm = &virtio_pci_pm_ops,
626 : : #endif
627 : : .sriov_configure = virtio_pci_sriov_configure,
628 : : };
629 : :
630 : 3 : module_pci_driver(virtio_pci_driver);
631 : :
632 : : MODULE_AUTHOR("Anthony Liguori <aliguori@us.ibm.com>");
633 : : MODULE_DESCRIPTION("virtio-pci");
634 : : MODULE_LICENSE("GPL");
635 : : MODULE_VERSION("1");
|