Blame view

drivers/virtio/virtio_pci_common.c 15.2 KB
3343660d8   Anthony Liguori   virtio: PCI device
1
  /*
a90fdce9d   Michael S. Tsirkin   virtio_pci: updat...
2
   * Virtio PCI driver - common functionality for all device versions
3343660d8   Anthony Liguori   virtio: PCI device
3
4
5
6
7
   *
   * This module allows virtio devices to be used over a virtual PCI device.
   * This can be used with QEMU based VMMs like KVM or Xen.
   *
   * Copyright IBM Corp. 2007
a90fdce9d   Michael S. Tsirkin   virtio_pci: updat...
8
   * Copyright Red Hat, Inc. 2014
3343660d8   Anthony Liguori   virtio: PCI device
9
10
11
   *
   * Authors:
   *  Anthony Liguori  <aliguori@us.ibm.com>
a90fdce9d   Michael S. Tsirkin   virtio_pci: updat...
12
13
   *  Rusty Russell <rusty@rustcorp.com.au>
   *  Michael S. Tsirkin <mst@redhat.com>
3343660d8   Anthony Liguori   virtio: PCI device
14
15
16
17
18
   *
   * This work is licensed under the terms of the GNU GPL, version 2 or later.
   * See the COPYING file in the top-level directory.
   *
   */
5f4c97608   Michael S. Tsirkin   virtio_pci: renam...
19
  #include "virtio_pci_common.h"
3343660d8   Anthony Liguori   virtio: PCI device
20

ac399d8f3   Michael S. Tsirkin   virtio_pci: add m...
21
22
23
24
25
26
27
  static bool force_legacy = false;
  
  #if IS_ENABLED(CONFIG_VIRTIO_PCI_LEGACY)
  module_param(force_legacy, bool, 0444);
  MODULE_PARM_DESC(force_legacy,
  		 "Force legacy mode for transitional virtio 1 devices");
  #endif
e6af578c5   Michael S. Tsirkin   virtio-pci: make ...
28
  /* wait for pending irq handlers */
38eb4a29a   Michael S. Tsirkin   virtio_pci: split...
29
  void vp_synchronize_vectors(struct virtio_device *vdev)
e6af578c5   Michael S. Tsirkin   virtio-pci: make ...
30
31
32
  {
  	struct virtio_pci_device *vp_dev = to_vp_device(vdev);
  	int i;
0b0f9dc52   Michael S. Tsirkin   Revert "virtio_pc...
33
34
35
36
  	if (vp_dev->intx_enabled)
  		synchronize_irq(vp_dev->pci_dev->irq);
  
  	for (i = 0; i < vp_dev->msix_vectors; ++i)
fa3a32793   Christoph Hellwig   virtio_pci: use p...
37
  		synchronize_irq(pci_irq_vector(vp_dev->pci_dev, i));
e6af578c5   Michael S. Tsirkin   virtio-pci: make ...
38
  }
3343660d8   Anthony Liguori   virtio: PCI device
39
  /* the notify function used when creating a virt queue */
38eb4a29a   Michael S. Tsirkin   virtio_pci: split...
40
  bool vp_notify(struct virtqueue *vq)
3343660d8   Anthony Liguori   virtio: PCI device
41
  {
3343660d8   Anthony Liguori   virtio: PCI device
42
43
  	/* we write the queue's selector into the notification register to
  	 * signal the other end */
f30eaf4a0   Michael S. Tsirkin   virtio_pci: use p...
44
  	iowrite16(vq->index, (void __iomem *)vq->priv);
46f9c2b92   Heinz Graalfs   virtio_ring: chan...
45
  	return true;
3343660d8   Anthony Liguori   virtio: PCI device
46
  }
77cf52465   Michael S. Tsirkin   virtio_pci: split...
47
48
49
50
  /* Handle a configuration change: Tell driver if it wants to know. */
  static irqreturn_t vp_config_changed(int irq, void *opaque)
  {
  	struct virtio_pci_device *vp_dev = opaque;
77cf52465   Michael S. Tsirkin   virtio_pci: split...
51

016c98c6f   Michael S. Tsirkin   virtio: unify con...
52
  	virtio_config_changed(&vp_dev->vdev);
77cf52465   Michael S. Tsirkin   virtio_pci: split...
53
54
55
56
57
58
59
  	return IRQ_HANDLED;
  }
  
  /* Notify all virtqueues on an interrupt. */
  static irqreturn_t vp_vring_interrupt(int irq, void *opaque)
  {
  	struct virtio_pci_device *vp_dev = opaque;
0a9b3f47d   Michael S. Tsirkin   Revert "virtio_pc...
60
  	struct virtio_pci_vq_info *info;
77cf52465   Michael S. Tsirkin   virtio_pci: split...
61
  	irqreturn_t ret = IRQ_NONE;
0a9b3f47d   Michael S. Tsirkin   Revert "virtio_pc...
62
  	unsigned long flags;
77cf52465   Michael S. Tsirkin   virtio_pci: split...
63

0a9b3f47d   Michael S. Tsirkin   Revert "virtio_pc...
64
65
66
  	spin_lock_irqsave(&vp_dev->lock, flags);
  	list_for_each_entry(info, &vp_dev->virtqueues, node) {
  		if (vring_interrupt(irq, info->vq) == IRQ_HANDLED)
77cf52465   Michael S. Tsirkin   virtio_pci: split...
67
68
  			ret = IRQ_HANDLED;
  	}
0a9b3f47d   Michael S. Tsirkin   Revert "virtio_pc...
69
  	spin_unlock_irqrestore(&vp_dev->lock, flags);
77cf52465   Michael S. Tsirkin   virtio_pci: split...
70
71
72
  
  	return ret;
  }
3343660d8   Anthony Liguori   virtio: PCI device
73
74
75
76
77
78
79
80
81
  /* A small wrapper to also acknowledge the interrupt when it's handled.
   * I really need an EIO hook for the vring so I can ack the interrupt once we
   * know that we'll be handling the IRQ but before we invoke the callback since
   * the callback may notify the host which results in the host attempting to
   * raise an interrupt that we would then mask once we acknowledged the
   * interrupt. */
  static irqreturn_t vp_interrupt(int irq, void *opaque)
  {
  	struct virtio_pci_device *vp_dev = opaque;
3343660d8   Anthony Liguori   virtio: PCI device
82
83
84
85
  	u8 isr;
  
  	/* reading the ISR has the effect of also clearing it so it's very
  	 * important to save off the value. */
af535722f   Michael S. Tsirkin   virtio_pci: add i...
86
  	isr = ioread8(vp_dev->isr);
3343660d8   Anthony Liguori   virtio: PCI device
87
88
89
90
91
92
  
  	/* It's definitely not us if the ISR was not high */
  	if (!isr)
  		return IRQ_NONE;
  
  	/* Configuration change?  Tell driver if it wants to know. */
77cf52465   Michael S. Tsirkin   virtio_pci: split...
93
94
  	if (isr & VIRTIO_PCI_ISR_CONFIG)
  		vp_config_changed(irq, opaque);
3343660d8   Anthony Liguori   virtio: PCI device
95

77cf52465   Michael S. Tsirkin   virtio_pci: split...
96
  	return vp_vring_interrupt(irq, opaque);
3343660d8   Anthony Liguori   virtio: PCI device
97
  }
0b0f9dc52   Michael S. Tsirkin   Revert "virtio_pc...
98
99
100
101
102
  static int vp_request_msix_vectors(struct virtio_device *vdev, int nvectors,
  				   bool per_vq_vectors, struct irq_affinity *desc)
  {
  	struct virtio_pci_device *vp_dev = to_vp_device(vdev);
  	const char *name = dev_name(&vp_dev->vdev.dev);
ba74b6f7f   Christoph Hellwig   virtio_pci: fix c...
103
  	unsigned flags = PCI_IRQ_MSIX;
0b0f9dc52   Michael S. Tsirkin   Revert "virtio_pc...
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
  	unsigned i, v;
  	int err = -ENOMEM;
  
  	vp_dev->msix_vectors = nvectors;
  
  	vp_dev->msix_names = kmalloc(nvectors * sizeof *vp_dev->msix_names,
  				     GFP_KERNEL);
  	if (!vp_dev->msix_names)
  		goto error;
  	vp_dev->msix_affinity_masks
  		= kzalloc(nvectors * sizeof *vp_dev->msix_affinity_masks,
  			  GFP_KERNEL);
  	if (!vp_dev->msix_affinity_masks)
  		goto error;
  	for (i = 0; i < nvectors; ++i)
  		if (!alloc_cpumask_var(&vp_dev->msix_affinity_masks[i],
  					GFP_KERNEL))
  			goto error;
ba74b6f7f   Christoph Hellwig   virtio_pci: fix c...
122
123
124
125
  	if (desc) {
  		flags |= PCI_IRQ_AFFINITY;
  		desc->pre_vectors++; /* virtio config vector */
  	}
0b0f9dc52   Michael S. Tsirkin   Revert "virtio_pc...
126
  	err = pci_alloc_irq_vectors_affinity(vp_dev->pci_dev, nvectors,
ba74b6f7f   Christoph Hellwig   virtio_pci: fix c...
127
  					     nvectors, flags, desc);
0b0f9dc52   Michael S. Tsirkin   Revert "virtio_pc...
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
  	if (err < 0)
  		goto error;
  	vp_dev->msix_enabled = 1;
  
  	/* Set the vector used for configuration */
  	v = vp_dev->msix_used_vectors;
  	snprintf(vp_dev->msix_names[v], sizeof *vp_dev->msix_names,
  		 "%s-config", name);
  	err = request_irq(pci_irq_vector(vp_dev->pci_dev, v),
  			  vp_config_changed, 0, vp_dev->msix_names[v],
  			  vp_dev);
  	if (err)
  		goto error;
  	++vp_dev->msix_used_vectors;
  
  	v = vp_dev->config_vector(vp_dev, v);
  	/* Verify we had enough resources to assign the vector */
  	if (v == VIRTIO_MSI_NO_VECTOR) {
  		err = -EBUSY;
  		goto error;
  	}
  
  	if (!per_vq_vectors) {
  		/* Shared vector for all VQs */
  		v = vp_dev->msix_used_vectors;
  		snprintf(vp_dev->msix_names[v], sizeof *vp_dev->msix_names,
  			 "%s-virtqueues", name);
  		err = request_irq(pci_irq_vector(vp_dev->pci_dev, v),
  				  vp_vring_interrupt, 0, vp_dev->msix_names[v],
  				  vp_dev);
  		if (err)
  			goto error;
  		++vp_dev->msix_used_vectors;
  	}
  	return 0;
  error:
  	return err;
  }
0a9b3f47d   Michael S. Tsirkin   Revert "virtio_pc...
166
167
168
  static struct virtqueue *vp_setup_vq(struct virtio_device *vdev, unsigned index,
  				     void (*callback)(struct virtqueue *vq),
  				     const char *name,
f94682dde   Michael S. Tsirkin   virtio: add conte...
169
  				     bool ctx,
0a9b3f47d   Michael S. Tsirkin   Revert "virtio_pc...
170
171
172
173
174
175
176
177
178
179
  				     u16 msix_vec)
  {
  	struct virtio_pci_device *vp_dev = to_vp_device(vdev);
  	struct virtio_pci_vq_info *info = kmalloc(sizeof *info, GFP_KERNEL);
  	struct virtqueue *vq;
  	unsigned long flags;
  
  	/* fill out our structure that represents an active queue */
  	if (!info)
  		return ERR_PTR(-ENOMEM);
f94682dde   Michael S. Tsirkin   virtio: add conte...
180
  	vq = vp_dev->setup_vq(vp_dev, info, index, callback, name, ctx,
0a9b3f47d   Michael S. Tsirkin   Revert "virtio_pc...
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
  			      msix_vec);
  	if (IS_ERR(vq))
  		goto out_info;
  
  	info->vq = vq;
  	if (callback) {
  		spin_lock_irqsave(&vp_dev->lock, flags);
  		list_add(&info->node, &vp_dev->virtqueues);
  		spin_unlock_irqrestore(&vp_dev->lock, flags);
  	} else {
  		INIT_LIST_HEAD(&info->node);
  	}
  
  	vp_dev->vqs[index] = info;
  	return vq;
  
  out_info:
  	kfree(info);
  	return vq;
  }
  
  static void vp_del_vq(struct virtqueue *vq)
  {
  	struct virtio_pci_device *vp_dev = to_vp_device(vq->vdev);
  	struct virtio_pci_vq_info *info = vp_dev->vqs[vq->index];
  	unsigned long flags;
  
  	spin_lock_irqsave(&vp_dev->lock, flags);
  	list_del(&info->node);
  	spin_unlock_irqrestore(&vp_dev->lock, flags);
  
  	vp_dev->del_vq(info);
  	kfree(info);
  }
0b0f9dc52   Michael S. Tsirkin   Revert "virtio_pc...
215
216
  /* the config->del_vqs() implementation */
  void vp_del_vqs(struct virtio_device *vdev)
d2a7ddda9   Michael S. Tsirkin   virtio: find_vqs/...
217
  {
e969fed54   Michael S. Tsirkin   virtio: refactor ...
218
  	struct virtio_pci_device *vp_dev = to_vp_device(vdev);
d2a7ddda9   Michael S. Tsirkin   virtio: find_vqs/...
219
  	struct virtqueue *vq, *n;
0b0f9dc52   Michael S. Tsirkin   Revert "virtio_pc...
220
  	int i;
d2a7ddda9   Michael S. Tsirkin   virtio: find_vqs/...
221

e969fed54   Michael S. Tsirkin   virtio: refactor ...
222
  	list_for_each_entry_safe(vq, n, &vdev->vqs, list) {
0a9b3f47d   Michael S. Tsirkin   Revert "virtio_pc...
223
224
  		if (vp_dev->per_vq_vectors) {
  			int v = vp_dev->vqs[vq->index]->msix_vector;
fa3a32793   Christoph Hellwig   virtio_pci: use p...
225

2f8dc3a01   Marc Zyngier   virtio-pci: Remov...
226
227
228
229
230
231
  			if (v != VIRTIO_MSI_NO_VECTOR) {
  				int irq = pci_irq_vector(vp_dev->pci_dev, v);
  
  				irq_set_affinity_hint(irq, NULL);
  				free_irq(irq, vq);
  			}
fa3a32793   Christoph Hellwig   virtio_pci: use p...
232
  		}
0a9b3f47d   Michael S. Tsirkin   Revert "virtio_pc...
233
  		vp_del_vq(vq);
e969fed54   Michael S. Tsirkin   virtio: refactor ...
234
  	}
0a9b3f47d   Michael S. Tsirkin   Revert "virtio_pc...
235
  	vp_dev->per_vq_vectors = false;
82af8ce84   Michael S. Tsirkin   virtio_pci: optio...
236

0b0f9dc52   Michael S. Tsirkin   Revert "virtio_pc...
237
238
239
240
  	if (vp_dev->intx_enabled) {
  		free_irq(vp_dev->pci_dev->irq, vp_dev);
  		vp_dev->intx_enabled = 0;
  	}
66f2f5554   Christoph Hellwig   virtio_pci: merge...
241

0b0f9dc52   Michael S. Tsirkin   Revert "virtio_pc...
242
243
  	for (i = 0; i < vp_dev->msix_used_vectors; ++i)
  		free_irq(pci_irq_vector(vp_dev->pci_dev, i), vp_dev);
66f2f5554   Christoph Hellwig   virtio_pci: merge...
244

0b0f9dc52   Michael S. Tsirkin   Revert "virtio_pc...
245
246
  	for (i = 0; i < vp_dev->msix_vectors; i++)
  		if (vp_dev->msix_affinity_masks[i])
07ec51480   Christoph Hellwig   virtio_pci: use s...
247
  			free_cpumask_var(vp_dev->msix_affinity_masks[i]);
0b0f9dc52   Michael S. Tsirkin   Revert "virtio_pc...
248
  	if (vp_dev->msix_enabled) {
66f2f5554   Christoph Hellwig   virtio_pci: merge...
249
250
  		/* Disable the vector used for configuration */
  		vp_dev->config_vector(vp_dev, VIRTIO_MSI_NO_VECTOR);
0b0f9dc52   Michael S. Tsirkin   Revert "virtio_pc...
251
252
  		pci_free_irq_vectors(vp_dev->pci_dev);
  		vp_dev->msix_enabled = 0;
66f2f5554   Christoph Hellwig   virtio_pci: merge...
253
  	}
0b0f9dc52   Michael S. Tsirkin   Revert "virtio_pc...
254
255
256
257
258
259
  	vp_dev->msix_vectors = 0;
  	vp_dev->msix_used_vectors = 0;
  	kfree(vp_dev->msix_names);
  	vp_dev->msix_names = NULL;
  	kfree(vp_dev->msix_affinity_masks);
  	vp_dev->msix_affinity_masks = NULL;
0a9b3f47d   Michael S. Tsirkin   Revert "virtio_pc...
260
261
  	kfree(vp_dev->vqs);
  	vp_dev->vqs = NULL;
d2a7ddda9   Michael S. Tsirkin   virtio: find_vqs/...
262
  }
a3cbec697   Christoph Hellwig   virtio_pci: split...
263
  static int vp_find_vqs_msix(struct virtio_device *vdev, unsigned nvqs,
52a615161   Christoph Hellwig   virtio_pci: simpl...
264
  		struct virtqueue *vqs[], vq_callback_t *callbacks[],
bf951b104   Michael S. Tsirkin   Revert "virtio_pc...
265
  		const char * const names[], bool per_vq_vectors,
f94682dde   Michael S. Tsirkin   virtio: add conte...
266
  		const bool *ctx,
bf951b104   Michael S. Tsirkin   Revert "virtio_pc...
267
  		struct irq_affinity *desc)
d2a7ddda9   Michael S. Tsirkin   virtio: find_vqs/...
268
  {
e969fed54   Michael S. Tsirkin   virtio: refactor ...
269
  	struct virtio_pci_device *vp_dev = to_vp_device(vdev);
f68d24082   Rusty Russell   virtio_pci: minor...
270
  	u16 msix_vec;
0b0f9dc52   Michael S. Tsirkin   Revert "virtio_pc...
271
  	int i, err, nvectors, allocated_vectors;
82af8ce84   Michael S. Tsirkin   virtio_pci: optio...
272

0a9b3f47d   Michael S. Tsirkin   Revert "virtio_pc...
273
274
275
  	vp_dev->vqs = kcalloc(nvqs, sizeof(*vp_dev->vqs), GFP_KERNEL);
  	if (!vp_dev->vqs)
  		return -ENOMEM;
bf951b104   Michael S. Tsirkin   Revert "virtio_pc...
276
  	if (per_vq_vectors) {
0b0f9dc52   Michael S. Tsirkin   Revert "virtio_pc...
277
278
279
280
281
  		/* Best option: one for change interrupt, one per vq. */
  		nvectors = 1;
  		for (i = 0; i < nvqs; ++i)
  			if (callbacks[i])
  				++nvectors;
bf951b104   Michael S. Tsirkin   Revert "virtio_pc...
282
  	} else {
0b0f9dc52   Michael S. Tsirkin   Revert "virtio_pc...
283
284
  		/* Second best: one for change, shared for all vqs. */
  		nvectors = 2;
07ec51480   Christoph Hellwig   virtio_pci: use s...
285
  	}
0b0f9dc52   Michael S. Tsirkin   Revert "virtio_pc...
286
287
  	err = vp_request_msix_vectors(vdev, nvectors, per_vq_vectors,
  				      per_vq_vectors ? desc : NULL);
a3cbec697   Christoph Hellwig   virtio_pci: split...
288
  	if (err)
0b0f9dc52   Michael S. Tsirkin   Revert "virtio_pc...
289
  		goto error_find;
a3cbec697   Christoph Hellwig   virtio_pci: split...
290

0a9b3f47d   Michael S. Tsirkin   Revert "virtio_pc...
291
  	vp_dev->per_vq_vectors = per_vq_vectors;
0b0f9dc52   Michael S. Tsirkin   Revert "virtio_pc...
292
  	allocated_vectors = vp_dev->msix_used_vectors;
d2a7ddda9   Michael S. Tsirkin   virtio: find_vqs/...
293
  	for (i = 0; i < nvqs; ++i) {
6457f126c   Michael S. Tsirkin   virtio: support r...
294
295
296
  		if (!names[i]) {
  			vqs[i] = NULL;
  			continue;
a3cbec697   Christoph Hellwig   virtio_pci: split...
297
  		}
0b0f9dc52   Michael S. Tsirkin   Revert "virtio_pc...
298
  		if (!callbacks[i])
07ec51480   Christoph Hellwig   virtio_pci: use s...
299
  			msix_vec = VIRTIO_MSI_NO_VECTOR;
0a9b3f47d   Michael S. Tsirkin   Revert "virtio_pc...
300
  		else if (vp_dev->per_vq_vectors)
0b0f9dc52   Michael S. Tsirkin   Revert "virtio_pc...
301
302
303
  			msix_vec = allocated_vectors++;
  		else
  			msix_vec = VP_MSIX_VQ_VECTOR;
0a9b3f47d   Michael S. Tsirkin   Revert "virtio_pc...
304
  		vqs[i] = vp_setup_vq(vdev, i, callbacks[i], names[i],
f94682dde   Michael S. Tsirkin   virtio: add conte...
305
  				     ctx ? ctx[i] : false,
0a9b3f47d   Michael S. Tsirkin   Revert "virtio_pc...
306
  				     msix_vec);
e969fed54   Michael S. Tsirkin   virtio: refactor ...
307
308
  		if (IS_ERR(vqs[i])) {
  			err = PTR_ERR(vqs[i]);
0b0f9dc52   Michael S. Tsirkin   Revert "virtio_pc...
309
  			goto error_find;
e969fed54   Michael S. Tsirkin   virtio: refactor ...
310
  		}
0b22bd0ba   Michael S. Tsirkin   virtio-pci: fix p...
311

0a9b3f47d   Michael S. Tsirkin   Revert "virtio_pc...
312
  		if (!vp_dev->per_vq_vectors || msix_vec == VIRTIO_MSI_NO_VECTOR)
5c34d002d   Christoph Hellwig   virtio_pci: remov...
313
  			continue;
5c34d002d   Christoph Hellwig   virtio_pci: remov...
314

0b0f9dc52   Michael S. Tsirkin   Revert "virtio_pc...
315
316
317
318
  		/* allocate per-vq irq if available and necessary */
  		snprintf(vp_dev->msix_names[msix_vec],
  			 sizeof *vp_dev->msix_names,
  			 "%s-%s",
0b22bd0ba   Michael S. Tsirkin   virtio-pci: fix p...
319
  			 dev_name(&vp_dev->vdev.dev), names[i]);
fa3a32793   Christoph Hellwig   virtio_pci: use p...
320
  		err = request_irq(pci_irq_vector(vp_dev->pci_dev, msix_vec),
0b0f9dc52   Michael S. Tsirkin   Revert "virtio_pc...
321
322
323
  				  vring_interrupt, 0,
  				  vp_dev->msix_names[msix_vec],
  				  vqs[i]);
0a9b3f47d   Michael S. Tsirkin   Revert "virtio_pc...
324
  		if (err)
0b0f9dc52   Michael S. Tsirkin   Revert "virtio_pc...
325
  			goto error_find;
d2a7ddda9   Michael S. Tsirkin   virtio: find_vqs/...
326
327
  	}
  	return 0;
0b0f9dc52   Michael S. Tsirkin   Revert "virtio_pc...
328
329
  error_find:
  	vp_del_vqs(vdev);
e969fed54   Michael S. Tsirkin   virtio: refactor ...
330
331
  	return err;
  }
a3cbec697   Christoph Hellwig   virtio_pci: split...
332
333
  static int vp_find_vqs_intx(struct virtio_device *vdev, unsigned nvqs,
  		struct virtqueue *vqs[], vq_callback_t *callbacks[],
f94682dde   Michael S. Tsirkin   virtio: add conte...
334
  		const char * const names[], const bool *ctx)
a3cbec697   Christoph Hellwig   virtio_pci: split...
335
336
337
  {
  	struct virtio_pci_device *vp_dev = to_vp_device(vdev);
  	int i, err;
0a9b3f47d   Michael S. Tsirkin   Revert "virtio_pc...
338
339
340
  	vp_dev->vqs = kcalloc(nvqs, sizeof(*vp_dev->vqs), GFP_KERNEL);
  	if (!vp_dev->vqs)
  		return -ENOMEM;
a3cbec697   Christoph Hellwig   virtio_pci: split...
341
342
343
  	err = request_irq(vp_dev->pci_dev->irq, vp_interrupt, IRQF_SHARED,
  			dev_name(&vdev->dev), vp_dev);
  	if (err)
0b0f9dc52   Michael S. Tsirkin   Revert "virtio_pc...
344
  		goto out_del_vqs;
a3cbec697   Christoph Hellwig   virtio_pci: split...
345

0b0f9dc52   Michael S. Tsirkin   Revert "virtio_pc...
346
  	vp_dev->intx_enabled = 1;
0a9b3f47d   Michael S. Tsirkin   Revert "virtio_pc...
347
  	vp_dev->per_vq_vectors = false;
a3cbec697   Christoph Hellwig   virtio_pci: split...
348
349
350
351
352
  	for (i = 0; i < nvqs; ++i) {
  		if (!names[i]) {
  			vqs[i] = NULL;
  			continue;
  		}
0a9b3f47d   Michael S. Tsirkin   Revert "virtio_pc...
353
  		vqs[i] = vp_setup_vq(vdev, i, callbacks[i], names[i],
f94682dde   Michael S. Tsirkin   virtio: add conte...
354
  				     ctx ? ctx[i] : false,
0a9b3f47d   Michael S. Tsirkin   Revert "virtio_pc...
355
  				     VIRTIO_MSI_NO_VECTOR);
a3cbec697   Christoph Hellwig   virtio_pci: split...
356
357
  		if (IS_ERR(vqs[i])) {
  			err = PTR_ERR(vqs[i]);
0b0f9dc52   Michael S. Tsirkin   Revert "virtio_pc...
358
  			goto out_del_vqs;
a3cbec697   Christoph Hellwig   virtio_pci: split...
359
360
361
362
  		}
  	}
  
  	return 0;
0b0f9dc52   Michael S. Tsirkin   Revert "virtio_pc...
363
364
  out_del_vqs:
  	vp_del_vqs(vdev);
a3cbec697   Christoph Hellwig   virtio_pci: split...
365
366
  	return err;
  }
e969fed54   Michael S. Tsirkin   virtio: refactor ...
367
  /* the config->find_vqs() implementation */
38eb4a29a   Michael S. Tsirkin   virtio_pci: split...
368
  int vp_find_vqs(struct virtio_device *vdev, unsigned nvqs,
fb5e31d97   Christoph Hellwig   virtio: allow dri...
369
  		struct virtqueue *vqs[], vq_callback_t *callbacks[],
f94682dde   Michael S. Tsirkin   virtio: add conte...
370
371
  		const char * const names[], const bool *ctx,
  		struct irq_affinity *desc)
e969fed54   Michael S. Tsirkin   virtio: refactor ...
372
  {
f68d24082   Rusty Russell   virtio_pci: minor...
373
  	int err;
e969fed54   Michael S. Tsirkin   virtio: refactor ...
374

bf951b104   Michael S. Tsirkin   Revert "virtio_pc...
375
  	/* Try MSI-X with one vector per queue. */
f94682dde   Michael S. Tsirkin   virtio: add conte...
376
  	err = vp_find_vqs_msix(vdev, nvqs, vqs, callbacks, names, true, ctx, desc);
bf951b104   Michael S. Tsirkin   Revert "virtio_pc...
377
378
379
  	if (!err)
  		return 0;
  	/* Fallback: MSI-X with one vector for config, one shared for queues. */
f94682dde   Michael S. Tsirkin   virtio: add conte...
380
  	err = vp_find_vqs_msix(vdev, nvqs, vqs, callbacks, names, false, ctx, desc);
e969fed54   Michael S. Tsirkin   virtio: refactor ...
381
382
  	if (!err)
  		return 0;
bf951b104   Michael S. Tsirkin   Revert "virtio_pc...
383
  	/* Finally fall back to regular interrupts. */
f94682dde   Michael S. Tsirkin   virtio: add conte...
384
  	return vp_find_vqs_intx(vdev, nvqs, vqs, callbacks, names, ctx);
d2a7ddda9   Michael S. Tsirkin   virtio: find_vqs/...
385
  }
38eb4a29a   Michael S. Tsirkin   virtio_pci: split...
386
  const char *vp_bus_name(struct virtio_device *vdev)
66846048f   Rick Jones   enable virtio_net...
387
388
389
390
391
  {
  	struct virtio_pci_device *vp_dev = to_vp_device(vdev);
  
  	return pci_name(vp_dev->pci_dev);
  }
75a0a52be   Jason Wang   virtio: introduce...
392
393
394
395
396
  /* Setup the affinity for a virtqueue:
   * - force the affinity for per vq vector
   * - OR over all affinities for shared MSI
   * - ignore the affinity request if we're using INTX
   */
38eb4a29a   Michael S. Tsirkin   virtio_pci: split...
397
  int vp_set_vq_affinity(struct virtqueue *vq, int cpu)
75a0a52be   Jason Wang   virtio: introduce...
398
399
400
  {
  	struct virtio_device *vdev = vq->vdev;
  	struct virtio_pci_device *vp_dev = to_vp_device(vdev);
0a9b3f47d   Michael S. Tsirkin   Revert "virtio_pc...
401
402
403
  	struct virtio_pci_vq_info *info = vp_dev->vqs[vq->index];
  	struct cpumask *mask;
  	unsigned int irq;
75a0a52be   Jason Wang   virtio: introduce...
404
405
406
  
  	if (!vq->callback)
  		return -EINVAL;
2008c1544   Michael S. Tsirkin   Revert "virtio_pc...
407
  	if (vp_dev->msix_enabled) {
0a9b3f47d   Michael S. Tsirkin   Revert "virtio_pc...
408
409
  		mask = vp_dev->msix_affinity_masks[info->msix_vector];
  		irq = pci_irq_vector(vp_dev->pci_dev, info->msix_vector);
75a0a52be   Jason Wang   virtio: introduce...
410
411
412
  		if (cpu == -1)
  			irq_set_affinity_hint(irq, NULL);
  		else {
210d150e1   Jiang Liu   virtio_pci: Clear...
413
  			cpumask_clear(mask);
75a0a52be   Jason Wang   virtio: introduce...
414
415
416
417
418
419
  			cpumask_set_cpu(cpu, mask);
  			irq_set_affinity_hint(irq, mask);
  		}
  	}
  	return 0;
  }
bbaba4795   Christoph Hellwig   virtio: provide a...
420
421
422
  const struct cpumask *vp_get_vq_affinity(struct virtio_device *vdev, int index)
  {
  	struct virtio_pci_device *vp_dev = to_vp_device(vdev);
bbaba4795   Christoph Hellwig   virtio: provide a...
423

0a9b3f47d   Michael S. Tsirkin   Revert "virtio_pc...
424
425
  	if (!vp_dev->per_vq_vectors ||
  	    vp_dev->vqs[index]->msix_vector == VIRTIO_MSI_NO_VECTOR)
bbaba4795   Christoph Hellwig   virtio: provide a...
426
  		return NULL;
0a9b3f47d   Michael S. Tsirkin   Revert "virtio_pc...
427
428
  	return pci_irq_get_affinity(vp_dev->pci_dev,
  				    vp_dev->vqs[index]->msix_vector);
bbaba4795   Christoph Hellwig   virtio: provide a...
429
  }
9e266ece2   Aaron Lu   virtio_pci: pm: U...
430
  #ifdef CONFIG_PM_SLEEP
f0fe6f115   Amit Shah   virtio: pci: add ...
431
432
433
434
  static int virtio_pci_freeze(struct device *dev)
  {
  	struct pci_dev *pci_dev = to_pci_dev(dev);
  	struct virtio_pci_device *vp_dev = pci_get_drvdata(pci_dev);
f0fe6f115   Amit Shah   virtio: pci: add ...
435
  	int ret;
c6716bae5   Michael S. Tsirkin   virtio-pci: move ...
436
  	ret = virtio_device_freeze(&vp_dev->vdev);
f0fe6f115   Amit Shah   virtio: pci: add ...
437
438
439
440
441
  
  	if (!ret)
  		pci_disable_device(pci_dev);
  	return ret;
  }
0517fdd15   Amit Shah   virtio-pci: drop ...
442
  static int virtio_pci_restore(struct device *dev)
f0fe6f115   Amit Shah   virtio: pci: add ...
443
444
445
446
447
448
449
450
  {
  	struct pci_dev *pci_dev = to_pci_dev(dev);
  	struct virtio_pci_device *vp_dev = pci_get_drvdata(pci_dev);
  	int ret;
  
  	ret = pci_enable_device(pci_dev);
  	if (ret)
  		return ret;
0517fdd15   Amit Shah   virtio-pci: drop ...
451

f0fe6f115   Amit Shah   virtio: pci: add ...
452
  	pci_set_master(pci_dev);
c6716bae5   Michael S. Tsirkin   virtio-pci: move ...
453
  	return virtio_device_restore(&vp_dev->vdev);
f0fe6f115   Amit Shah   virtio: pci: add ...
454
  }
9a4253db0   Michael S. Tsirkin   virtio_pci: move ...
455
  static const struct dev_pm_ops virtio_pci_pm_ops = {
f878d0be2   Amit Shah   virtio-pci: switc...
456
  	SET_SYSTEM_SLEEP_PM_OPS(virtio_pci_freeze, virtio_pci_restore)
d07753638   Amit Shah   virtio: pci: swit...
457
  };
3343660d8   Anthony Liguori   virtio: PCI device
458
  #endif
9a4253db0   Michael S. Tsirkin   virtio_pci: move ...
459
460
461
462
  
  
  /* Qumranet donated their vendor ID for devices 0x1000 thru 0x10FF. */
  static const struct pci_device_id virtio_pci_id_table[] = {
caf02abf9   Robin H. Johnson   PCI: Add QEMU top...
463
  	{ PCI_DEVICE(PCI_VENDOR_ID_REDHAT_QUMRANET, PCI_ANY_ID) },
9a4253db0   Michael S. Tsirkin   virtio_pci: move ...
464
465
466
467
  	{ 0 }
  };
  
  MODULE_DEVICE_TABLE(pci, virtio_pci_id_table);
ff31d2e28   Michael S. Tsirkin   virtio_pci: move ...
468
469
470
471
472
473
474
475
476
477
  static void virtio_pci_release_dev(struct device *_d)
  {
  	struct virtio_device *vdev = dev_to_virtio(_d);
  	struct virtio_pci_device *vp_dev = to_vp_device(vdev);
  
  	/* As struct device is a kobject, it's not safe to
  	 * free the memory (including the reference counter itself)
  	 * until it's release callback. */
  	kfree(vp_dev);
  }
9a4253db0   Michael S. Tsirkin   virtio_pci: move ...
478
479
480
  static int virtio_pci_probe(struct pci_dev *pci_dev,
  			    const struct pci_device_id *id)
  {
ff31d2e28   Michael S. Tsirkin   virtio_pci: move ...
481
482
483
484
485
486
487
488
489
490
491
492
  	struct virtio_pci_device *vp_dev;
  	int rc;
  
  	/* allocate our structure and fill it out */
  	vp_dev = kzalloc(sizeof(struct virtio_pci_device), GFP_KERNEL);
  	if (!vp_dev)
  		return -ENOMEM;
  
  	pci_set_drvdata(pci_dev, vp_dev);
  	vp_dev->vdev.dev.parent = &pci_dev->dev;
  	vp_dev->vdev.dev.release = virtio_pci_release_dev;
  	vp_dev->pci_dev = pci_dev;
0a9b3f47d   Michael S. Tsirkin   Revert "virtio_pc...
493
494
  	INIT_LIST_HEAD(&vp_dev->virtqueues);
  	spin_lock_init(&vp_dev->lock);
ff31d2e28   Michael S. Tsirkin   virtio_pci: move ...
495

ff31d2e28   Michael S. Tsirkin   virtio_pci: move ...
496
497
498
499
  	/* enable the device */
  	rc = pci_enable_device(pci_dev);
  	if (rc)
  		goto err_enable_device;
ac399d8f3   Michael S. Tsirkin   virtio_pci: add m...
500
  	if (force_legacy) {
1fcf0512c   Michael S. Tsirkin   virtio_pci: moder...
501
  		rc = virtio_pci_legacy_probe(vp_dev);
ac399d8f3   Michael S. Tsirkin   virtio_pci: add m...
502
503
504
505
506
507
508
509
510
511
512
513
  		/* Also try modern mode if we can't map BAR0 (no IO space). */
  		if (rc == -ENODEV || rc == -ENOMEM)
  			rc = virtio_pci_modern_probe(vp_dev);
  		if (rc)
  			goto err_probe;
  	} else {
  		rc = virtio_pci_modern_probe(vp_dev);
  		if (rc == -ENODEV)
  			rc = virtio_pci_legacy_probe(vp_dev);
  		if (rc)
  			goto err_probe;
  	}
ff31d2e28   Michael S. Tsirkin   virtio_pci: move ...
514
515
516
517
518
519
520
521
522
523
  
  	pci_set_master(pci_dev);
  
  	rc = register_virtio_device(&vp_dev->vdev);
  	if (rc)
  		goto err_register;
  
  	return 0;
  
  err_register:
1fcf0512c   Michael S. Tsirkin   virtio_pci: moder...
524
525
526
527
  	if (vp_dev->ioaddr)
  	     virtio_pci_legacy_remove(vp_dev);
  	else
  	     virtio_pci_modern_remove(vp_dev);
ff31d2e28   Michael S. Tsirkin   virtio_pci: move ...
528
  err_probe:
ff31d2e28   Michael S. Tsirkin   virtio_pci: move ...
529
530
531
532
  	pci_disable_device(pci_dev);
  err_enable_device:
  	kfree(vp_dev);
  	return rc;
9a4253db0   Michael S. Tsirkin   virtio_pci: move ...
533
534
535
536
  }
  
  static void virtio_pci_remove(struct pci_dev *pci_dev)
  {
ff31d2e28   Michael S. Tsirkin   virtio_pci: move ...
537
  	struct virtio_pci_device *vp_dev = pci_get_drvdata(pci_dev);
2989be09a   Michael S. Tsirkin   virtio_pci: fix u...
538
  	struct device *dev = get_device(&vp_dev->vdev.dev);
ff31d2e28   Michael S. Tsirkin   virtio_pci: move ...
539
540
  
  	unregister_virtio_device(&vp_dev->vdev);
1fcf0512c   Michael S. Tsirkin   virtio_pci: moder...
541
542
543
544
  	if (vp_dev->ioaddr)
  		virtio_pci_legacy_remove(vp_dev);
  	else
  		virtio_pci_modern_remove(vp_dev);
ff31d2e28   Michael S. Tsirkin   virtio_pci: move ...
545

ff31d2e28   Michael S. Tsirkin   virtio_pci: move ...
546
  	pci_disable_device(pci_dev);
2989be09a   Michael S. Tsirkin   virtio_pci: fix u...
547
  	put_device(dev);
9a4253db0   Michael S. Tsirkin   virtio_pci: move ...
548
549
550
551
552
553
554
555
556
557
558
559
560
  }
  
  static struct pci_driver virtio_pci_driver = {
  	.name		= "virtio-pci",
  	.id_table	= virtio_pci_id_table,
  	.probe		= virtio_pci_probe,
  	.remove		= virtio_pci_remove,
  #ifdef CONFIG_PM_SLEEP
  	.driver.pm	= &virtio_pci_pm_ops,
  #endif
  };
  
  module_pci_driver(virtio_pci_driver);
5ff16110c   Herbert Xu   virtio_pci: resto...
561
562
563
564
565
  
  MODULE_AUTHOR("Anthony Liguori <aliguori@us.ibm.com>");
  MODULE_DESCRIPTION("virtio-pci");
  MODULE_LICENSE("GPL");
  MODULE_VERSION("1");