pcifront.c revision 227843
1/*
2 * Copyright (c) 2006, Cisco Systems, Inc.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * 1. Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 *    notice, this list of conditions and the following disclaimer in the
13 *    documentation and/or other materials provided with the distribution.
14 * 3. Neither the name of Cisco Systems, Inc. nor the names of its contributors
15 *    may be used to endorse or promote products derived from this software
16 *    without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
22 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 * POSSIBILITY OF SUCH DAMAGE.
29 */
30
31#include <sys/cdefs.h>
32__FBSDID("$FreeBSD: head/sys/dev/xen/pcifront/pcifront.c 227843 2011-11-22 21:28:20Z marius $");
33
34#include <sys/param.h>
35#include <sys/module.h>
36#include <sys/systm.h>
37#include <sys/mbuf.h>
38#include <sys/malloc.h>
39#include <sys/kernel.h>
40#include <sys/socket.h>
41#include <sys/queue.h>
42
43#include <machine/vmparam.h>
44#include <vm/vm.h>
45#include <vm/pmap.h>
46
47#include <machine/bus.h>
48#include <machine/resource.h>
49#include <machine/frame.h>
50
51#include <sys/bus.h>
52#include <sys/rman.h>
53
54#include <machine/intr_machdep.h>
55
56#include <machine/xen-os.h>
57#include <machine/hypervisor.h>
58#include <machine/hypervisor-ifs.h>
59#include <machine/xen_intr.h>
60#include <machine/evtchn.h>
61#include <machine/xenbus.h>
62#include <machine/gnttab.h>
63#include <machine/xen-public/memory.h>
64#include <machine/xen-public/io/pciif.h>
65
66#include <sys/pciio.h>
67#include <dev/pci/pcivar.h>
68#include "pcib_if.h"
69
70#ifdef XEN_PCIDEV_FE_DEBUG
71#define DPRINTF(fmt, args...) \
72    printf("pcifront (%s:%d): " fmt, __FUNCTION__, __LINE__, ##args)
73#else
74#define DPRINTF(fmt, args...) ((void)0)
75#endif
76#define WPRINTF(fmt, args...) \
77    printf("pcifront (%s:%d): " fmt, __FUNCTION__, __LINE__, ##args)
78
79#define INVALID_GRANT_REF (0)
80#define INVALID_EVTCHN    (-1)
81#define virt_to_mfn(x) (vtomach(x) >> PAGE_SHIFT)
82
83struct pcifront_device {
84	STAILQ_ENTRY(pcifront_device) next;
85
86	struct xenbus_device *xdev;
87
88	int unit;
89	int evtchn;
90	int gnt_ref;
91
92	/* Lock this when doing any operations in sh_info */
93	struct mtx sh_info_lock;
94	struct xen_pci_sharedinfo *sh_info;
95
96	device_t ndev;
97
98	int ref_cnt;
99};
100
101static STAILQ_HEAD(pcifront_dlist, pcifront_device) pdev_list = STAILQ_HEAD_INITIALIZER(pdev_list);
102
103struct xpcib_softc {
104	int domain;
105	int bus;
106	struct pcifront_device *pdev;
107};
108
109/* Allocate a PCI device structure */
110static struct pcifront_device *
111alloc_pdev(struct xenbus_device *xdev)
112{
113	struct pcifront_device *pdev = NULL;
114	int err, unit;
115
116	err = sscanf(xdev->nodename, "device/pci/%d", &unit);
117	if (err != 1) {
118		if (err == 0)
119			err = -EINVAL;
120		xenbus_dev_fatal(pdev->xdev, err, "Error scanning pci device instance number");
121		goto out;
122	}
123
124	pdev = (struct pcifront_device *)malloc(sizeof(struct pcifront_device), M_DEVBUF, M_NOWAIT);
125	if (pdev == NULL) {
126		err = -ENOMEM;
127		xenbus_dev_fatal(xdev, err, "Error allocating pcifront_device struct");
128		goto out;
129	}
130	pdev->unit = unit;
131	pdev->xdev = xdev;
132	pdev->ref_cnt = 1;
133
134	pdev->sh_info = (struct xen_pci_sharedinfo *)malloc(PAGE_SIZE, M_DEVBUF, M_NOWAIT);
135	if (pdev->sh_info == NULL) {
136		free(pdev, M_DEVBUF);
137		pdev = NULL;
138		err = -ENOMEM;
139		xenbus_dev_fatal(xdev, err, "Error allocating sh_info struct");
140		goto out;
141	}
142	pdev->sh_info->flags = 0;
143
144	xdev->data = pdev;
145
146	mtx_init(&pdev->sh_info_lock, "info_lock", "pci shared dev info lock", MTX_DEF);
147
148	pdev->evtchn = INVALID_EVTCHN;
149	pdev->gnt_ref = INVALID_GRANT_REF;
150
151	STAILQ_INSERT_TAIL(&pdev_list, pdev, next);
152
153	DPRINTF("Allocated pdev @ 0x%p (unit=%d)\n", pdev, unit);
154
155 out:
156	return pdev;
157}
158
159/* Hold a reference to a pcifront device */
160static void
161get_pdev(struct pcifront_device *pdev)
162{
163	pdev->ref_cnt++;
164}
165
166/* Release a reference to a pcifront device */
167static void
168put_pdev(struct pcifront_device *pdev)
169{
170	if (--pdev->ref_cnt > 0)
171		return;
172
173	DPRINTF("freeing pdev @ 0x%p (ref_cnt=%d)\n", pdev, pdev->ref_cnt);
174
175	if (pdev->evtchn != INVALID_EVTCHN)
176		xenbus_free_evtchn(pdev->xdev, pdev->evtchn);
177
178	if (pdev->gnt_ref != INVALID_GRANT_REF)
179		gnttab_end_foreign_access(pdev->gnt_ref, 0, (void *)pdev->sh_info);
180
181	pdev->xdev->data = NULL;
182
183	free(pdev, M_DEVBUF);
184}
185
186
187/* Write to the xenbus info needed by backend */
188static int
189pcifront_publish_info(struct pcifront_device *pdev)
190{
191	int err = 0;
192	struct xenbus_transaction *trans;
193
194	err = xenbus_grant_ring(pdev->xdev, virt_to_mfn(pdev->sh_info));
195	if (err < 0) {
196		WPRINTF("error granting access to ring page\n");
197		goto out;
198	}
199
200	pdev->gnt_ref = err;
201
202	err = xenbus_alloc_evtchn(pdev->xdev, &pdev->evtchn);
203	if (err)
204		goto out;
205
206 do_publish:
207	trans = xenbus_transaction_start();
208	if (IS_ERR(trans)) {
209		xenbus_dev_fatal(pdev->xdev, err,
210						 "Error writing configuration for backend "
211						 "(start transaction)");
212		goto out;
213	}
214
215	err = xenbus_printf(trans, pdev->xdev->nodename,
216						"pci-op-ref", "%u", pdev->gnt_ref);
217	if (!err)
218		err = xenbus_printf(trans, pdev->xdev->nodename,
219							"event-channel", "%u", pdev->evtchn);
220	if (!err)
221		err = xenbus_printf(trans, pdev->xdev->nodename,
222							"magic", XEN_PCI_MAGIC);
223	if (!err)
224		err = xenbus_switch_state(pdev->xdev, trans,
225								  XenbusStateInitialised);
226
227	if (err) {
228		xenbus_transaction_end(trans, 1);
229		xenbus_dev_fatal(pdev->xdev, err,
230						 "Error writing configuration for backend");
231		goto out;
232	} else {
233		err = xenbus_transaction_end(trans, 0);
234		if (err == -EAGAIN)
235			goto do_publish;
236		else if (err) {
237			xenbus_dev_fatal(pdev->xdev, err,
238							 "Error completing transaction for backend");
239			goto out;
240		}
241	}
242
243 out:
244	return err;
245}
246
247/* The backend is now connected so complete the connection process on our side */
248static int
249pcifront_connect(struct pcifront_device *pdev)
250{
251	device_t nexus;
252	devclass_t nexus_devclass;
253
254	/* We will add our device as a child of the nexus0 device */
255	if (!(nexus_devclass = devclass_find("nexus")) ||
256		!(nexus = devclass_get_device(nexus_devclass, 0))) {
257		WPRINTF("could not find nexus0!\n");
258		return -1;
259	}
260
261	/* Create a newbus device representing this frontend instance */
262	pdev->ndev = BUS_ADD_CHILD(nexus, 0, "xpcife", pdev->unit);
263	if (!pdev->ndev) {
264		WPRINTF("could not create xpcife%d!\n", pdev->unit);
265		return -EFAULT;
266	}
267	get_pdev(pdev);
268	device_set_ivars(pdev->ndev, pdev);
269
270	/* Good to go connected now */
271	xenbus_switch_state(pdev->xdev, NULL, XenbusStateConnected);
272
273	printf("pcifront: connected to %s\n", pdev->xdev->nodename);
274
275	mtx_lock(&Giant);
276	device_probe_and_attach(pdev->ndev);
277	mtx_unlock(&Giant);
278
279	return 0;
280}
281
282/* The backend is closing so process a disconnect */
283static int
284pcifront_disconnect(struct pcifront_device *pdev)
285{
286	int err = 0;
287	XenbusState prev_state;
288
289	prev_state = xenbus_read_driver_state(pdev->xdev->nodename);
290
291	if (prev_state < XenbusStateClosing) {
292		err = xenbus_switch_state(pdev->xdev, NULL, XenbusStateClosing);
293		if (!err && prev_state == XenbusStateConnected) {
294			/* TODO - need to detach the newbus devices */
295		}
296	}
297
298	return err;
299}
300
301/* Process a probe from the xenbus */
302static int
303pcifront_probe(struct xenbus_device *xdev,
304			   const struct xenbus_device_id *id)
305{
306	int err = 0;
307	struct pcifront_device *pdev;
308
309	DPRINTF("xenbus probing\n");
310
311	if ((pdev = alloc_pdev(xdev)) == NULL)
312		goto out;
313
314	err = pcifront_publish_info(pdev);
315
316 out:
317	if (err)
318		put_pdev(pdev);
319	return err;
320}
321
322/* Remove the xenbus PCI device */
323static int
324pcifront_remove(struct xenbus_device *xdev)
325{
326	DPRINTF("removing xenbus device node (%s)\n", xdev->nodename);
327	if (xdev->data)
328		put_pdev(xdev->data);
329	return 0;
330}
331
332/* Called by xenbus when our backend node changes state */
333static void
334pcifront_backend_changed(struct xenbus_device *xdev,
335						 XenbusState be_state)
336{
337	struct pcifront_device *pdev = xdev->data;
338
339	switch (be_state) {
340	case XenbusStateClosing:
341		DPRINTF("backend closing (%s)\n", xdev->nodename);
342		pcifront_disconnect(pdev);
343		break;
344
345	case XenbusStateClosed:
346		DPRINTF("backend closed (%s)\n", xdev->nodename);
347		pcifront_disconnect(pdev);
348		break;
349
350	case XenbusStateConnected:
351		DPRINTF("backend connected (%s)\n", xdev->nodename);
352		pcifront_connect(pdev);
353		break;
354
355	default:
356		break;
357	}
358}
359
360/* Process PCI operation */
361static int
362do_pci_op(struct pcifront_device *pdev, struct xen_pci_op *op)
363{
364	int err = 0;
365	struct xen_pci_op *active_op = &pdev->sh_info->op;
366	evtchn_port_t port = pdev->evtchn;
367	time_t timeout;
368
369	mtx_lock(&pdev->sh_info_lock);
370
371	memcpy(active_op, op, sizeof(struct xen_pci_op));
372
373	/* Go */
374	wmb();
375	set_bit(_XEN_PCIF_active, (unsigned long *)&pdev->sh_info->flags);
376	notify_remote_via_evtchn(port);
377
378	timeout = time_uptime + 2;
379
380	clear_evtchn(port);
381
382	/* Spin while waiting for the answer */
383	while (test_bit
384	       (_XEN_PCIF_active, (unsigned long *)&pdev->sh_info->flags)) {
385		int err = HYPERVISOR_poll(&port, 1, 3 * hz);
386		if (err)
387			panic("Failed HYPERVISOR_poll: err=%d", err);
388		clear_evtchn(port);
389		if (time_uptime > timeout) {
390			WPRINTF("pciback not responding!!!\n");
391			clear_bit(_XEN_PCIF_active,
392				  (unsigned long *)&pdev->sh_info->flags);
393			err = XEN_PCI_ERR_dev_not_found;
394			goto out;
395		}
396	}
397
398	memcpy(op, active_op, sizeof(struct xen_pci_op));
399
400	err = op->err;
401 out:
402	mtx_unlock(&pdev->sh_info_lock);
403	return err;
404}
405
406/* ** XenBus Driver registration ** */
407
408static struct xenbus_device_id pcifront_ids[] = {
409	{ "pci" },
410	{ "" }
411};
412
413static struct xenbus_driver pcifront = {
414	.name = "pcifront",
415	.ids = pcifront_ids,
416	.probe = pcifront_probe,
417	.remove = pcifront_remove,
418	.otherend_changed = pcifront_backend_changed,
419};
420
421/* Register the driver with xenbus during sys init */
422static void
423pcifront_init(void *unused)
424{
425	if ((xen_start_info->flags & SIF_INITDOMAIN))
426		return;
427
428	DPRINTF("xenbus registering\n");
429
430	xenbus_register_frontend(&pcifront);
431}
432
433SYSINIT(pciif, SI_SUB_PSEUDO, SI_ORDER_ANY, pcifront_init, NULL)
434
435
436/* Newbus xpcife device driver probe */
437static int
438xpcife_probe(device_t dev)
439{
440#ifdef XEN_PCIDEV_FE_DEBUG
441	struct pcifront_device *pdev = (struct pcifront_device *)device_get_ivars(dev);
442	DPRINTF("xpcife probe (unit=%d)\n", pdev->unit);
443#endif
444	return 0;
445}
446
447/* Newbus xpcife device driver attach */
448static int
449xpcife_attach(device_t dev)
450{
451	struct pcifront_device *pdev = (struct pcifront_device *)device_get_ivars(dev);
452	int i, num_roots, len, err;
453	char str[64];
454	unsigned int domain, bus;
455
456	DPRINTF("xpcife attach (unit=%d)\n", pdev->unit);
457
458	err = xenbus_scanf(NULL, pdev->xdev->otherend,
459					   "root_num", "%d", &num_roots);
460	if (err != 1) {
461		if (err == 0)
462			err = -EINVAL;
463		xenbus_dev_fatal(pdev->xdev, err,
464						 "Error reading number of PCI roots");
465		goto out;
466	}
467
468	/* Add a pcib device for each root */
469	for (i = 0; i < num_roots; i++) {
470		device_t child;
471
472		len = snprintf(str, sizeof(str), "root-%d", i);
473		if (unlikely(len >= (sizeof(str) - 1))) {
474			err = -ENOMEM;
475			goto out;
476		}
477
478		err = xenbus_scanf(NULL, pdev->xdev->otherend, str,
479						   "%x:%x", &domain, &bus);
480		if (err != 2) {
481			if (err >= 0)
482				err = -EINVAL;
483			xenbus_dev_fatal(pdev->xdev, err,
484							 "Error reading PCI root %d", i);
485			goto out;
486		}
487		err = 0;
488		if (domain != pdev->xdev->otherend_id) {
489			err = -EINVAL;
490			xenbus_dev_fatal(pdev->xdev, err,
491							 "Domain mismatch %d != %d", domain, pdev->xdev->otherend_id);
492			goto out;
493		}
494
495		child = device_add_child(dev, "pcib", bus);
496		if (!child) {
497			err = -ENOMEM;
498			xenbus_dev_fatal(pdev->xdev, err,
499							 "Unable to create pcib%d", bus);
500			goto out;
501		}
502	}
503
504 out:
505	return bus_generic_attach(dev);
506}
507
508static devclass_t xpcife_devclass;
509
510static device_method_t xpcife_methods[] = {
511	/* Device interface */
512	DEVMETHOD(device_probe, xpcife_probe),
513	DEVMETHOD(device_attach, xpcife_attach),
514	DEVMETHOD(device_detach,	bus_generic_detach),
515	DEVMETHOD(device_shutdown,	bus_generic_shutdown),
516	DEVMETHOD(device_suspend,	bus_generic_suspend),
517	DEVMETHOD(device_resume,	bus_generic_resume),
518    /* Bus interface */
519    DEVMETHOD(bus_alloc_resource,	bus_generic_alloc_resource),
520    DEVMETHOD(bus_release_resource,	bus_generic_release_resource),
521    DEVMETHOD(bus_activate_resource,	bus_generic_activate_resource),
522    DEVMETHOD(bus_deactivate_resource,	bus_generic_deactivate_resource),
523    DEVMETHOD(bus_setup_intr,		bus_generic_setup_intr),
524    DEVMETHOD(bus_teardown_intr,	bus_generic_teardown_intr),
525
526	DEVMETHOD_END
527};
528
529static driver_t xpcife_driver = {
530	"xpcife",
531	xpcife_methods,
532	0,
533};
534
535DRIVER_MODULE(xpcife, nexus, xpcife_driver, xpcife_devclass, 0, 0);
536
537
538/* Newbus xen pcib device driver probe */
539static int
540xpcib_probe(device_t dev)
541{
542	struct xpcib_softc *sc = (struct xpcib_softc *)device_get_softc(dev);
543	struct pcifront_device *pdev = (struct pcifront_device *)device_get_ivars(device_get_parent(dev));
544
545	DPRINTF("xpcib probe (bus=%d)\n", device_get_unit(dev));
546
547	sc->domain = pdev->xdev->otherend_id;
548	sc->bus = device_get_unit(dev);
549	sc->pdev = pdev;
550
551	return 0;
552}
553
554/* Newbus xen pcib device driver attach */
555static int
556xpcib_attach(device_t dev)
557{
558	struct xpcib_softc *sc = (struct xpcib_softc *)device_get_softc(dev);
559
560	DPRINTF("xpcib attach (bus=%d)\n", sc->bus);
561
562	device_add_child(dev, "pci", sc->bus);
563	return bus_generic_attach(dev);
564}
565
566static int
567xpcib_read_ivar(device_t dev, device_t child, int which, uintptr_t *result)
568{
569	struct xpcib_softc *sc = (struct xpcib_softc *)device_get_softc(dev);
570	switch (which) {
571	case  PCIB_IVAR_BUS:
572		*result = sc->bus;
573		return 0;
574	}
575	return ENOENT;
576}
577
578/* Return the number of slots supported */
579static int
580xpcib_maxslots(device_t dev)
581{
582	return 31;
583}
584
585#define PCI_DEVFN(slot,func)	((((slot) & 0x1f) << 3) | ((func) & 0x07))
586
587/* Read configuration space register */
588static u_int32_t
589xpcib_read_config(device_t dev, int bus, int slot, int func,
590				  int reg, int bytes)
591{
592	struct xpcib_softc *sc = (struct xpcib_softc *)device_get_softc(dev);
593	struct xen_pci_op op = {
594		.cmd    = XEN_PCI_OP_conf_read,
595		.domain = sc->domain,
596		.bus    = sc->bus,
597		.devfn  = PCI_DEVFN(slot, func),
598		.offset = reg,
599		.size   = bytes,
600	};
601	int err;
602
603	err = do_pci_op(sc->pdev, &op);
604
605	DPRINTF("read config (b=%d, s=%d, f=%d, reg=%d, len=%d, val=%x, err=%d)\n",
606			bus, slot, func, reg, bytes, op.value, err);
607
608	if (err)
609		op.value = ~0;
610
611	return op.value;
612}
613
614/* Write configuration space register */
615static void
616xpcib_write_config(device_t dev, int bus, int slot, int func,
617				   int reg, u_int32_t data, int bytes)
618{
619	struct xpcib_softc *sc = (struct xpcib_softc *)device_get_softc(dev);
620	struct xen_pci_op op = {
621		.cmd    = XEN_PCI_OP_conf_write,
622		.domain = sc->domain,
623		.bus    = sc->bus,
624		.devfn  = PCI_DEVFN(slot, func),
625		.offset = reg,
626		.size   = bytes,
627		.value  = data,
628	};
629	int err;
630
631	err = do_pci_op(sc->pdev, &op);
632
633	DPRINTF("write config (b=%d, s=%d, f=%d, reg=%d, len=%d, val=%x, err=%d)\n",
634			bus, slot, func, reg, bytes, data, err);
635}
636
637static int
638xpcib_route_interrupt(device_t pcib, device_t dev, int pin)
639{
640	struct pci_devinfo *dinfo = device_get_ivars(dev);
641	pcicfgregs *cfg = &dinfo->cfg;
642
643	DPRINTF("route intr (pin=%d, line=%d)\n", pin, cfg->intline);
644
645	return cfg->intline;
646}
647
648static device_method_t xpcib_methods[] = {
649    /* Device interface */
650    DEVMETHOD(device_probe,		xpcib_probe),
651    DEVMETHOD(device_attach,		xpcib_attach),
652    DEVMETHOD(device_detach,		bus_generic_detach),
653    DEVMETHOD(device_shutdown,		bus_generic_shutdown),
654    DEVMETHOD(device_suspend,		bus_generic_suspend),
655    DEVMETHOD(device_resume,		bus_generic_resume),
656
657    /* Bus interface */
658    DEVMETHOD(bus_read_ivar,		xpcib_read_ivar),
659    DEVMETHOD(bus_alloc_resource,	bus_generic_alloc_resource),
660    DEVMETHOD(bus_activate_resource,	bus_generic_activate_resource),
661    DEVMETHOD(bus_release_resource,	bus_generic_release_resource),
662    DEVMETHOD(bus_deactivate_resource,	bus_generic_deactivate_resource),
663    DEVMETHOD(bus_setup_intr,		bus_generic_setup_intr),
664    DEVMETHOD(bus_teardown_intr,	bus_generic_teardown_intr),
665
666    /* pcib interface */
667    DEVMETHOD(pcib_maxslots,		xpcib_maxslots),
668    DEVMETHOD(pcib_read_config,		xpcib_read_config),
669    DEVMETHOD(pcib_write_config,	xpcib_write_config),
670    DEVMETHOD(pcib_route_interrupt,	xpcib_route_interrupt),
671
672    DEVMETHOD_END
673};
674
675static devclass_t xpcib_devclass;
676
677DEFINE_CLASS_0(pcib, xpcib_driver, xpcib_methods, sizeof(struct xpcib_softc));
678DRIVER_MODULE(pcib, xpcife, xpcib_driver, xpcib_devclass, 0, 0);
679
680/*
681 * Local variables:
682 * mode: C
683 * c-set-style: "BSD"
684 * c-basic-offset: 4
685 * tab-width: 4
686 * indent-tabs-mode: t
687 * End:
688 */
689