2 * PCI Frontend Xenbus Setup - handles setup with backend (imports page/evtchn)
4 * Author: Ryan Wilson <hap9@epoch.ncsc.mil>
6 #include <linux/module.h>
7 #include <linux/init.h>
9 #include <xen/xenbus.h>
10 #include <xen/gnttab.h>
13 #define INVALID_GRANT_REF (0)
14 #define INVALID_EVTCHN (-1)
16 static struct pcifront_device *alloc_pdev(struct xenbus_device *xdev)
18 struct pcifront_device *pdev;
20 pdev = kmalloc(sizeof(struct pcifront_device), GFP_KERNEL);
25 (struct xen_pci_sharedinfo *)__get_free_page(GFP_KERNEL);
26 if (pdev->sh_info == NULL) {
31 pdev->sh_info->flags = 0;
33 xdev->dev.driver_data = pdev;
36 INIT_LIST_HEAD(&pdev->root_buses);
38 spin_lock_init(&pdev->dev_lock);
39 spin_lock_init(&pdev->sh_info_lock);
41 pdev->evtchn = INVALID_EVTCHN;
42 pdev->gnt_ref = INVALID_GRANT_REF;
44 dev_dbg(&xdev->dev, "Allocated pdev @ 0x%p pdev->sh_info @ 0x%p\n",
50 static void free_pdev(struct pcifront_device *pdev)
52 dev_dbg(&pdev->xdev->dev, "freeing pdev @ 0x%p\n", pdev);
54 pcifront_free_roots(pdev);
56 if (pdev->evtchn != INVALID_EVTCHN)
57 xenbus_free_evtchn(pdev->xdev, pdev->evtchn);
59 if (pdev->gnt_ref != INVALID_GRANT_REF)
60 gnttab_end_foreign_access(pdev->gnt_ref, 0,
61 (unsigned long)pdev->sh_info);
63 pdev->xdev->dev.driver_data = NULL;
68 static int pcifront_publish_info(struct pcifront_device *pdev)
71 struct xenbus_transaction trans;
73 err = xenbus_grant_ring(pdev->xdev, virt_to_mfn(pdev->sh_info));
79 err = xenbus_alloc_evtchn(pdev->xdev, &pdev->evtchn);
84 err = xenbus_transaction_start(&trans);
86 xenbus_dev_fatal(pdev->xdev, err,
87 "Error writing configuration for backend "
88 "(start transaction)");
92 err = xenbus_printf(trans, pdev->xdev->nodename,
93 "pci-op-ref", "%u", pdev->gnt_ref);
95 err = xenbus_printf(trans, pdev->xdev->nodename,
96 "event-channel", "%u", pdev->evtchn);
98 err = xenbus_printf(trans, pdev->xdev->nodename,
99 "magic", XEN_PCI_MAGIC);
102 xenbus_transaction_end(trans, 1);
103 xenbus_dev_fatal(pdev->xdev, err,
104 "Error writing configuration for backend");
107 err = xenbus_transaction_end(trans, 0);
111 xenbus_dev_fatal(pdev->xdev, err,
112 "Error completing transaction "
118 xenbus_switch_state(pdev->xdev, XenbusStateInitialised);
120 dev_dbg(&pdev->xdev->dev, "publishing successful!\n");
126 static int pcifront_try_connect(struct pcifront_device *pdev)
129 int i, num_roots, len;
131 unsigned int domain, bus;
133 spin_lock(&pdev->dev_lock);
135 /* Only connect once */
136 if (xenbus_read_driver_state(pdev->xdev->nodename) !=
137 XenbusStateInitialised)
140 err = pcifront_connect(pdev);
142 xenbus_dev_fatal(pdev->xdev, err,
143 "Error connecting PCI Frontend");
147 err = xenbus_scanf(XBT_NIL, pdev->xdev->otherend,
148 "root_num", "%d", &num_roots);
149 if (err == -ENOENT) {
150 xenbus_dev_error(pdev->xdev, err,
151 "No PCI Roots found, trying 0000:00");
152 err = pcifront_scan_root(pdev, 0, 0);
154 } else if (err != 1) {
157 xenbus_dev_fatal(pdev->xdev, err,
158 "Error reading number of PCI roots");
162 for (i = 0; i < num_roots; i++) {
163 len = snprintf(str, sizeof(str), "root-%d", i);
164 if (unlikely(len >= (sizeof(str) - 1))) {
169 err = xenbus_scanf(XBT_NIL, pdev->xdev->otherend, str,
170 "%x:%x", &domain, &bus);
174 xenbus_dev_fatal(pdev->xdev, err,
175 "Error reading PCI root %d", i);
179 err = pcifront_scan_root(pdev, domain, bus);
181 xenbus_dev_fatal(pdev->xdev, err,
182 "Error scanning PCI root %04x:%02x",
188 err = xenbus_switch_state(pdev->xdev, XenbusStateConnected);
193 spin_unlock(&pdev->dev_lock);
197 static int pcifront_try_disconnect(struct pcifront_device *pdev)
200 enum xenbus_state prev_state;
202 spin_lock(&pdev->dev_lock);
204 prev_state = xenbus_read_driver_state(pdev->xdev->nodename);
206 if (prev_state < XenbusStateClosing)
207 err = xenbus_switch_state(pdev->xdev, XenbusStateClosing);
209 if (!err && prev_state == XenbusStateConnected)
210 pcifront_disconnect(pdev);
212 spin_unlock(&pdev->dev_lock);
217 static void pcifront_backend_changed(struct xenbus_device *xdev,
218 enum xenbus_state be_state)
220 struct pcifront_device *pdev = xdev->dev.driver_data;
223 case XenbusStateClosing:
224 dev_warn(&xdev->dev, "backend going away!\n");
225 pcifront_try_disconnect(pdev);
228 case XenbusStateClosed:
229 dev_warn(&xdev->dev, "backend went away!\n");
230 pcifront_try_disconnect(pdev);
232 device_unregister(&pdev->xdev->dev);
235 case XenbusStateConnected:
236 pcifront_try_connect(pdev);
244 static int pcifront_xenbus_probe(struct xenbus_device *xdev,
245 const struct xenbus_device_id *id)
248 struct pcifront_device *pdev = alloc_pdev(xdev);
252 xenbus_dev_fatal(xdev, err,
253 "Error allocating pcifront_device struct");
257 err = pcifront_publish_info(pdev);
263 static int pcifront_xenbus_remove(struct xenbus_device *xdev)
265 if (xdev->dev.driver_data)
266 free_pdev(xdev->dev.driver_data);
271 static struct xenbus_device_id xenpci_ids[] = {
276 static struct xenbus_driver xenbus_pcifront_driver = {
278 .owner = THIS_MODULE,
280 .probe = pcifront_xenbus_probe,
281 .remove = pcifront_xenbus_remove,
282 .otherend_changed = pcifront_backend_changed,
285 static int __init pcifront_init(void)
287 if (!is_running_on_xen())
290 return xenbus_register_frontend(&xenbus_pcifront_driver);
293 /* Initialize after the Xen PCI Frontend Stub is initialized */
294 subsys_initcall(pcifront_init);