virtio_pci.c revision 1.16
1/*	$OpenBSD: virtio_pci.c,v 1.16 2017/01/13 14:37:32 reyk Exp $	*/
2/*	$NetBSD: virtio.c,v 1.3 2011/11/02 23:05:52 njoly Exp $	*/
3
4/*
5 * Copyright (c) 2012 Stefan Fritsch.
6 * Copyright (c) 2010 Minoura Makoto.
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 *    notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 *    notice, this list of conditions and the following disclaimer in the
16 *    documentation and/or other materials provided with the distribution.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30#include <sys/param.h>
31#include <sys/systm.h>
32#include <sys/device.h>
33#include <sys/mutex.h>
34
35#include <dev/pci/pcidevs.h>
36#include <dev/pci/pcireg.h>
37#include <dev/pci/pcivar.h>
38
39#include <dev/pci/virtioreg.h>
40#include <dev/pci/virtiovar.h>
41
42/*
43 * XXX: Before being used on big endian arches, the access to config registers
44 * XXX: needs to be reviewed/fixed. The non-device specific registers are
45 * XXX: PCI-endian while the device specific registers are native endian.
46 */
47
48#define MAX_MSIX_VECS	8
49#define virtio_set_status(sc, s) virtio_pci_set_status(sc, s)
50#define virtio_device_reset(sc) virtio_set_status((sc), 0)
51
52struct virtio_pci_softc;
53
54int		virtio_pci_match(struct device *, void *, void *);
55void		virtio_pci_attach(struct device *, struct device *, void *);
56int		virtio_pci_detach(struct device *, int);
57
58void		virtio_pci_kick(struct virtio_softc *, uint16_t);
59uint8_t		virtio_pci_read_device_config_1(struct virtio_softc *, int);
60uint16_t	virtio_pci_read_device_config_2(struct virtio_softc *, int);
61uint32_t	virtio_pci_read_device_config_4(struct virtio_softc *, int);
62uint64_t	virtio_pci_read_device_config_8(struct virtio_softc *, int);
63void		virtio_pci_write_device_config_1(struct virtio_softc *, int, uint8_t);
64void		virtio_pci_write_device_config_2(struct virtio_softc *, int, uint16_t);
65void		virtio_pci_write_device_config_4(struct virtio_softc *, int, uint32_t);
66void		virtio_pci_write_device_config_8(struct virtio_softc *, int, uint64_t);
67uint16_t	virtio_pci_read_queue_size(struct virtio_softc *, uint16_t);
68void		virtio_pci_setup_queue(struct virtio_softc *, uint16_t, uint32_t);
69void		virtio_pci_set_status(struct virtio_softc *, int);
70uint32_t	virtio_pci_negotiate_features(struct virtio_softc *, uint32_t,
71					      const struct virtio_feature_name *);
72int		virtio_pci_msix_establish(struct virtio_pci_softc *, struct pci_attach_args *, int, int (*)(void *), void *);
73int		virtio_pci_setup_msix(struct virtio_pci_softc *, struct pci_attach_args *, int);
74void		virtio_pci_free_irqs(struct virtio_pci_softc *);
75int		virtio_pci_poll_intr(void *);
76int		virtio_pci_legacy_intr(void *);
77int		virtio_pci_config_intr(void *);
78int		virtio_pci_queue_intr(void *);
79int		virtio_pci_shared_queue_intr(void *);
80
81enum irq_type {
82	IRQ_NO_MSIX,
83	IRQ_MSIX_SHARED, /* vec 0: config irq, vec 1 shared by all vqs */
84	IRQ_MSIX_PER_VQ, /* vec 0: config irq, vec n: irq of vq[n-1] */
85};
86
87struct virtio_pci_softc {
88	struct virtio_softc	sc_sc;
89	pci_chipset_tag_t	sc_pc;
90
91	bus_space_tag_t		sc_iot;
92	bus_space_handle_t	sc_ioh;
93	bus_size_t		sc_iosize;
94
95	void			*sc_ih[MAX_MSIX_VECS];
96
97	int			sc_config_offset;
98	enum irq_type		sc_irq_type;
99};
100
101struct cfattach virtio_pci_ca = {
102	sizeof(struct virtio_pci_softc),
103	virtio_pci_match,
104	virtio_pci_attach,
105	virtio_pci_detach,
106	NULL
107};
108
109struct virtio_ops virtio_pci_ops = {
110	virtio_pci_kick,
111	virtio_pci_read_device_config_1,
112	virtio_pci_read_device_config_2,
113	virtio_pci_read_device_config_4,
114	virtio_pci_read_device_config_8,
115	virtio_pci_write_device_config_1,
116	virtio_pci_write_device_config_2,
117	virtio_pci_write_device_config_4,
118	virtio_pci_write_device_config_8,
119	virtio_pci_read_queue_size,
120	virtio_pci_setup_queue,
121	virtio_pci_set_status,
122	virtio_pci_negotiate_features,
123	virtio_pci_poll_intr,
124};
125
126uint16_t
127virtio_pci_read_queue_size(struct virtio_softc *vsc, uint16_t idx)
128{
129	struct virtio_pci_softc *sc = (struct virtio_pci_softc *)vsc;
130	bus_space_write_2(sc->sc_iot, sc->sc_ioh, VIRTIO_CONFIG_QUEUE_SELECT,
131	    idx);
132	return bus_space_read_2(sc->sc_iot, sc->sc_ioh,
133	    VIRTIO_CONFIG_QUEUE_SIZE);
134}
135
136void
137virtio_pci_setup_queue(struct virtio_softc *vsc, uint16_t idx, uint32_t addr)
138{
139	struct virtio_pci_softc *sc = (struct virtio_pci_softc *)vsc;
140	bus_space_write_2(sc->sc_iot, sc->sc_ioh, VIRTIO_CONFIG_QUEUE_SELECT,
141	    idx);
142	bus_space_write_4(sc->sc_iot, sc->sc_ioh, VIRTIO_CONFIG_QUEUE_ADDRESS,
143	    addr);
144
145	/*
146	 * This path is only executed if this function is called after
147	 * the child's attach function has finished. In other cases,
148	 * it's done in virtio_pci_setup_msix().
149	 */
150	if (sc->sc_irq_type != IRQ_NO_MSIX) {
151		int vec = 1;
152		if (sc->sc_irq_type == IRQ_MSIX_PER_VQ)
153		       vec += idx;
154		bus_space_write_2(sc->sc_iot, sc->sc_ioh,
155		    VIRTIO_MSI_QUEUE_VECTOR, vec);
156	}
157}
158
159void
160virtio_pci_set_status(struct virtio_softc *vsc, int status)
161{
162	struct virtio_pci_softc *sc = (struct virtio_pci_softc *)vsc;
163	int old = 0;
164
165	if (status != 0)
166		old = bus_space_read_1(sc->sc_iot, sc->sc_ioh,
167				       VIRTIO_CONFIG_DEVICE_STATUS);
168	bus_space_write_1(sc->sc_iot, sc->sc_ioh, VIRTIO_CONFIG_DEVICE_STATUS,
169			  status|old);
170}
171
172int
173virtio_pci_match(struct device *parent, void *match, void *aux)
174{
175	struct pci_attach_args *pa;
176
177	pa = (struct pci_attach_args *)aux;
178	if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_QUMRANET &&
179	    PCI_PRODUCT(pa->pa_id) >= 0x1000 &&
180	    PCI_PRODUCT(pa->pa_id) <= 0x103f &&
181	    PCI_REVISION(pa->pa_class) == 0)
182		return 1;
183	if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_OPENBSD &&
184	    PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_OPENBSD_CONTROL)
185		return 1;
186	return 0;
187}
188
189void
190virtio_pci_attach(struct device *parent, struct device *self, void *aux)
191{
192	struct virtio_pci_softc *sc = (struct virtio_pci_softc *)self;
193	struct virtio_softc *vsc = &sc->sc_sc;
194	struct pci_attach_args *pa = (struct pci_attach_args *)aux;
195	pci_chipset_tag_t pc = pa->pa_pc;
196	pcitag_t tag = pa->pa_tag;
197	int revision;
198	pcireg_t id;
199	char const *intrstr;
200	pci_intr_handle_t ih;
201
202	revision = PCI_REVISION(pa->pa_class);
203	if (revision != 0) {
204		printf("unknown revision 0x%02x; giving up\n", revision);
205		return;
206	}
207
208	/* subsystem ID shows what I am */
209	id = PCI_PRODUCT(pci_conf_read(pc, tag, PCI_SUBSYS_ID_REG));
210
211	printf("\n");
212
213	vsc->sc_ops = &virtio_pci_ops;
214	sc->sc_pc = pc;
215	vsc->sc_dmat = pa->pa_dmat;
216	sc->sc_config_offset = VIRTIO_CONFIG_DEVICE_CONFIG_NOMSI;
217	sc->sc_irq_type = IRQ_NO_MSIX;
218
219	/*
220	 * For virtio, ignore normal MSI black/white-listing depending on the
221	 * PCI bridge but enable it unconditionally.
222	 */
223	pa->pa_flags |= PCI_FLAGS_MSI_ENABLED;
224
225	if (pci_mapreg_map(pa, PCI_MAPREG_START, PCI_MAPREG_TYPE_IO, 0,
226	    &sc->sc_iot, &sc->sc_ioh, NULL, &sc->sc_iosize, 0)) {
227		printf("%s: can't map i/o space\n", vsc->sc_dev.dv_xname);
228		return;
229	}
230
231	virtio_device_reset(vsc);
232	virtio_pci_set_status(vsc, VIRTIO_CONFIG_DEVICE_STATUS_ACK);
233	virtio_pci_set_status(vsc, VIRTIO_CONFIG_DEVICE_STATUS_DRIVER);
234
235	/* XXX: use softc as aux... */
236	vsc->sc_childdevid = id;
237	vsc->sc_child = NULL;
238	config_found(self, sc, NULL);
239	if (vsc->sc_child == NULL) {
240		printf("%s: no matching child driver; not configured\n",
241		    vsc->sc_dev.dv_xname);
242		goto fail_1;
243	}
244	if (vsc->sc_child == VIRTIO_CHILD_ERROR) {
245		printf("%s: virtio configuration failed\n",
246		    vsc->sc_dev.dv_xname);
247		goto fail_1;
248	}
249
250	if (virtio_pci_setup_msix(sc, pa, 0) == 0) {
251		sc->sc_irq_type = IRQ_MSIX_PER_VQ;
252		intrstr = "msix per-VQ";
253	} else if (virtio_pci_setup_msix(sc, pa, 1) == 0) {
254		sc->sc_irq_type = IRQ_MSIX_SHARED;
255		intrstr = "msix shared";
256	} else {
257		if (pci_intr_map_msi(pa, &ih) != 0 && pci_intr_map(pa, &ih) != 0) {
258			printf("%s: couldn't map interrupt\n", vsc->sc_dev.dv_xname);
259			goto fail_2;
260		}
261		intrstr = pci_intr_string(pc, ih);
262		/*
263		 * We always set the IPL_MPSAFE flag in order to do the relatively
264		 * expensive ISR read without lock, and then grab the kernel lock in
265		 * the interrupt handler.
266		 * For now, we don't support IPL_MPSAFE vq_done functions.
267		 */
268		KASSERT((vsc->sc_ipl & IPL_MPSAFE) == 0);
269		sc->sc_ih[0] = pci_intr_establish(pc, ih, vsc->sc_ipl | IPL_MPSAFE,
270		    virtio_pci_legacy_intr, sc, vsc->sc_dev.dv_xname);
271		if (sc->sc_ih[0] == NULL) {
272			printf("%s: couldn't establish interrupt", vsc->sc_dev.dv_xname);
273			if (intrstr != NULL)
274				printf(" at %s", intrstr);
275			printf("\n");
276			goto fail_2;
277		}
278	}
279	printf("%s: %s\n", vsc->sc_dev.dv_xname, intrstr);
280
281	virtio_set_status(vsc, VIRTIO_CONFIG_DEVICE_STATUS_DRIVER_OK);
282	return;
283
284fail_2:
285	config_detach(vsc->sc_child, 0);
286fail_1:
287	/* no pci_mapreg_unmap() or pci_intr_unmap() */
288	virtio_set_status(vsc, VIRTIO_CONFIG_DEVICE_STATUS_FAILED);
289}
290
291int
292virtio_pci_detach(struct device *self, int flags)
293{
294	struct virtio_pci_softc *sc = (struct virtio_pci_softc *)self;
295	struct virtio_softc *vsc = &sc->sc_sc;
296	int r;
297
298	if (vsc->sc_child != 0 && vsc->sc_child != VIRTIO_CHILD_ERROR) {
299		r = config_detach(vsc->sc_child, flags);
300		if (r)
301			return r;
302	}
303	KASSERT(vsc->sc_child == 0 || vsc->sc_child == VIRTIO_CHILD_ERROR);
304	KASSERT(vsc->sc_vqs == 0);
305	virtio_pci_free_irqs(sc);
306	if (sc->sc_iosize)
307		bus_space_unmap(sc->sc_iot, sc->sc_ioh, sc->sc_iosize);
308	sc->sc_iosize = 0;
309
310	return 0;
311}
312
313/*
314 * Feature negotiation.
315 * Prints available / negotiated features if guest_feature_names != NULL and
316 * VIRTIO_DEBUG is 1
317 */
318uint32_t
319virtio_pci_negotiate_features(struct virtio_softc *vsc, uint32_t guest_features,
320    const struct virtio_feature_name *guest_feature_names)
321{
322	struct virtio_pci_softc *sc = (struct virtio_pci_softc *)vsc;
323	uint32_t host, neg;
324
325	/*
326	 * indirect descriptors can be switched off by setting bit 1 in the
327	 * driver flags, see config(8)
328	 */
329	if (!(vsc->sc_dev.dv_cfdata->cf_flags & 1) &&
330	    !(vsc->sc_child->dv_cfdata->cf_flags & 1)) {
331		guest_features |= VIRTIO_F_RING_INDIRECT_DESC;
332	} else {
333		printf("RingIndirectDesc disabled by UKC\n");
334	}
335	host = bus_space_read_4(sc->sc_iot, sc->sc_ioh,
336				VIRTIO_CONFIG_DEVICE_FEATURES);
337	neg = host & guest_features;
338#if VIRTIO_DEBUG
339	if (guest_feature_names)
340		virtio_log_features(host, neg, guest_feature_names);
341#endif
342	bus_space_write_4(sc->sc_iot, sc->sc_ioh,
343			  VIRTIO_CONFIG_GUEST_FEATURES, neg);
344	vsc->sc_features = neg;
345	if (neg & VIRTIO_F_RING_INDIRECT_DESC)
346		vsc->sc_indirect = 1;
347	else
348		vsc->sc_indirect = 0;
349
350	return neg;
351}
352
353/*
354 * Device configuration registers.
355 */
356uint8_t
357virtio_pci_read_device_config_1(struct virtio_softc *vsc, int index)
358{
359	struct virtio_pci_softc *sc = (struct virtio_pci_softc *)vsc;
360	return bus_space_read_1(sc->sc_iot, sc->sc_ioh,
361	    sc->sc_config_offset + index);
362}
363
364uint16_t
365virtio_pci_read_device_config_2(struct virtio_softc *vsc, int index)
366{
367	struct virtio_pci_softc *sc = (struct virtio_pci_softc *)vsc;
368	return bus_space_read_2(sc->sc_iot, sc->sc_ioh,
369	    sc->sc_config_offset + index);
370}
371
372uint32_t
373virtio_pci_read_device_config_4(struct virtio_softc *vsc, int index)
374{
375	struct virtio_pci_softc *sc = (struct virtio_pci_softc *)vsc;
376	return bus_space_read_4(sc->sc_iot, sc->sc_ioh,
377	    sc->sc_config_offset + index);
378}
379
380uint64_t
381virtio_pci_read_device_config_8(struct virtio_softc *vsc, int index)
382{
383	struct virtio_pci_softc *sc = (struct virtio_pci_softc *)vsc;
384	uint64_t r;
385
386	r = bus_space_read_4(sc->sc_iot, sc->sc_ioh,
387	    sc->sc_config_offset + index + sizeof(uint32_t));
388	r <<= 32;
389	r += bus_space_read_4(sc->sc_iot, sc->sc_ioh,
390	    sc->sc_config_offset + index);
391	return r;
392}
393
394void
395virtio_pci_write_device_config_1(struct virtio_softc *vsc, int index,
396    uint8_t value)
397{
398	struct virtio_pci_softc *sc = (struct virtio_pci_softc *)vsc;
399	bus_space_write_1(sc->sc_iot, sc->sc_ioh,
400	    sc->sc_config_offset + index, value);
401}
402
403void
404virtio_pci_write_device_config_2(struct virtio_softc *vsc, int index,
405    uint16_t value)
406{
407	struct virtio_pci_softc *sc = (struct virtio_pci_softc *)vsc;
408	bus_space_write_2(sc->sc_iot, sc->sc_ioh,
409	    sc->sc_config_offset + index, value);
410}
411
412void
413virtio_pci_write_device_config_4(struct virtio_softc *vsc,
414			     int index, uint32_t value)
415{
416	struct virtio_pci_softc *sc = (struct virtio_pci_softc *)vsc;
417	bus_space_write_4(sc->sc_iot, sc->sc_ioh,
418	    sc->sc_config_offset + index, value);
419}
420
421void
422virtio_pci_write_device_config_8(struct virtio_softc *vsc,
423			     int index, uint64_t value)
424{
425	struct virtio_pci_softc *sc = (struct virtio_pci_softc *)vsc;
426	bus_space_write_4(sc->sc_iot, sc->sc_ioh,
427	    sc->sc_config_offset + index, value & 0xffffffff);
428	bus_space_write_4(sc->sc_iot, sc->sc_ioh,
429	    sc->sc_config_offset + index + sizeof(uint32_t), value >> 32);
430}
431
432int
433virtio_pci_msix_establish(struct virtio_pci_softc *sc,
434    struct pci_attach_args *pa, int idx, int (*handler)(void *), void *ih_arg)
435{
436	struct virtio_softc *vsc = &sc->sc_sc;
437	pci_intr_handle_t ih;
438
439	if (pci_intr_map_msix(pa, idx, &ih) != 0) {
440#if VIRTIO_DEBUG
441		printf("%s[%d]: pci_intr_map_msix failed\n",
442		    vsc->sc_dev.dv_xname, idx);
443#endif
444		return 1;
445	}
446	sc->sc_ih[idx] = pci_intr_establish(sc->sc_pc, ih, vsc->sc_ipl,
447	    handler, ih_arg, vsc->sc_dev.dv_xname);
448	if (sc->sc_ih[idx] == NULL) {
449		printf("%s[%d]: couldn't establish msix interrupt\n",
450		    vsc->sc_dev.dv_xname, idx);
451		return 1;
452	}
453	return 0;
454}
455
456void
457virtio_pci_free_irqs(struct virtio_pci_softc *sc)
458{
459	struct virtio_softc *vsc = &sc->sc_sc;
460	int i;
461
462	if (sc->sc_config_offset == VIRTIO_CONFIG_DEVICE_CONFIG_MSI) {
463		for (i = 0; i < vsc->sc_nvqs; i++) {
464			bus_space_write_2(sc->sc_iot, sc->sc_ioh,
465			    VIRTIO_CONFIG_QUEUE_SELECT, i);
466			bus_space_write_2(sc->sc_iot, sc->sc_ioh,
467			    VIRTIO_MSI_QUEUE_VECTOR, VIRTIO_MSI_NO_VECTOR);
468		}
469	}
470
471	for (i = 0; i < MAX_MSIX_VECS; i++) {
472		if (sc->sc_ih[i]) {
473			pci_intr_disestablish(sc->sc_pc, sc->sc_ih[i]);
474			sc->sc_ih[i] = NULL;
475		}
476	}
477
478	sc->sc_config_offset = VIRTIO_CONFIG_DEVICE_CONFIG_NOMSI;
479}
480
481int
482virtio_pci_setup_msix(struct virtio_pci_softc *sc, struct pci_attach_args *pa,
483    int shared)
484{
485	struct virtio_softc *vsc = &sc->sc_sc;
486	int i;
487
488	if (virtio_pci_msix_establish(sc, pa, 0, virtio_pci_config_intr, vsc))
489		return 1;
490	sc->sc_config_offset = VIRTIO_CONFIG_DEVICE_CONFIG_MSI;
491	bus_space_write_2(sc->sc_iot, sc->sc_ioh, VIRTIO_MSI_CONFIG_VECTOR, 0);
492
493	if (shared) {
494		if (virtio_pci_msix_establish(sc, pa, 1,
495		    virtio_pci_shared_queue_intr, vsc)) {
496			goto fail;
497		}
498
499		for (i = 0; i < vsc->sc_nvqs; i++) {
500			bus_space_write_2(sc->sc_iot, sc->sc_ioh,
501			    VIRTIO_CONFIG_QUEUE_SELECT, i);
502			bus_space_write_2(sc->sc_iot, sc->sc_ioh,
503			    VIRTIO_MSI_QUEUE_VECTOR, 1);
504		}
505	} else {
506		for (i = 0; i <= vsc->sc_nvqs; i++) {
507			if (virtio_pci_msix_establish(sc, pa, i + 1,
508			    virtio_pci_queue_intr, &vsc->sc_vqs[i])) {
509				goto fail;
510			}
511			bus_space_write_2(sc->sc_iot, sc->sc_ioh,
512			    VIRTIO_CONFIG_QUEUE_SELECT, i);
513			bus_space_write_2(sc->sc_iot, sc->sc_ioh,
514			    VIRTIO_MSI_QUEUE_VECTOR, i + 1);
515		}
516	}
517
518	return 0;
519fail:
520	virtio_pci_free_irqs(sc);
521	return 1;
522}
523
524/*
525 * Interrupt handler.
526 */
527
528/*
529 * Only used without MSI-X
530 */
531int
532virtio_pci_legacy_intr(void *arg)
533{
534	struct virtio_pci_softc *sc = arg;
535	struct virtio_softc *vsc = &sc->sc_sc;
536	int isr, r = 0;
537
538	/* check and ack the interrupt */
539	isr = bus_space_read_1(sc->sc_iot, sc->sc_ioh,
540	    VIRTIO_CONFIG_ISR_STATUS);
541	if (isr == 0)
542		return 0;
543	KERNEL_LOCK();
544	if ((isr & VIRTIO_CONFIG_ISR_CONFIG_CHANGE) &&
545	    (vsc->sc_config_change != NULL)) {
546		r = (vsc->sc_config_change)(vsc);
547	}
548	r |= virtio_check_vqs(vsc);
549	KERNEL_UNLOCK();
550
551	return r;
552}
553
554/*
555 * Only used with MSI-X
556 */
557int
558virtio_pci_config_intr(void *arg)
559{
560	struct virtio_softc *vsc = arg;
561
562	if (vsc->sc_config_change != NULL)
563		return vsc->sc_config_change(vsc);
564	return 0;
565}
566
567/*
568 * Only used with MSI-X
569 */
570int
571virtio_pci_queue_intr(void *arg)
572{
573	struct virtqueue *vq = arg;
574
575	if (vq->vq_done)
576		return (vq->vq_done)(vq);
577	return 0;
578}
579
580int
581virtio_pci_shared_queue_intr(void *arg)
582{
583	struct virtio_softc *vsc = arg;
584
585	return virtio_check_vqs(vsc);
586}
587
588/*
589 * Interrupt handler to be used when polling.
590 * We cannot use isr here because it is not defined in MSI-X mode.
591 */
592int
593virtio_pci_poll_intr(void *arg)
594{
595	struct virtio_pci_softc *sc = arg;
596	struct virtio_softc *vsc = &sc->sc_sc;
597	int r = 0;
598
599	if (vsc->sc_config_change != NULL)
600		r = (vsc->sc_config_change)(vsc);
601
602	r |= virtio_check_vqs(vsc);
603
604	return r;
605}
606
607
608void
609virtio_pci_kick(struct virtio_softc *vsc, uint16_t idx)
610{
611	struct virtio_pci_softc *sc = (struct virtio_pci_softc *)vsc;
612	bus_space_write_2(sc->sc_iot, sc->sc_ioh, VIRTIO_CONFIG_QUEUE_NOTIFY,
613	    idx);
614}
615