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