Merge to Fedora kernel-2.6.18-1.2224_FC5 patched with stable patch-2.6.18.1-vs2.0...
[linux-2.6.git] / drivers / xen / pcifront / xenbus.c
1 /*
2  * PCI Frontend Xenbus Setup - handles setup with backend (imports page/evtchn)
3  *
4  *   Author: Ryan Wilson <hap9@epoch.ncsc.mil>
5  */
6 #include <linux/module.h>
7 #include <linux/init.h>
8 #include <linux/mm.h>
9 #include <xen/xenbus.h>
10 #include <xen/gnttab.h>
11 #include "pcifront.h"
12
13 #define INVALID_GRANT_REF (0)
14 #define INVALID_EVTCHN    (-1)
15
16 static struct pcifront_device *alloc_pdev(struct xenbus_device *xdev)
17 {
18         struct pcifront_device *pdev;
19
20         pdev = kmalloc(sizeof(struct pcifront_device), GFP_KERNEL);
21         if (pdev == NULL)
22                 goto out;
23
24         pdev->sh_info =
25             (struct xen_pci_sharedinfo *)__get_free_page(GFP_KERNEL);
26         if (pdev->sh_info == NULL) {
27                 kfree(pdev);
28                 pdev = NULL;
29                 goto out;
30         }
31         pdev->sh_info->flags = 0;
32
33         xdev->dev.driver_data = pdev;
34         pdev->xdev = xdev;
35
36         INIT_LIST_HEAD(&pdev->root_buses);
37
38         spin_lock_init(&pdev->dev_lock);
39         spin_lock_init(&pdev->sh_info_lock);
40
41         pdev->evtchn = INVALID_EVTCHN;
42         pdev->gnt_ref = INVALID_GRANT_REF;
43
44         dev_dbg(&xdev->dev, "Allocated pdev @ 0x%p pdev->sh_info @ 0x%p\n",
45                 pdev, pdev->sh_info);
46       out:
47         return pdev;
48 }
49
50 static void free_pdev(struct pcifront_device *pdev)
51 {
52         dev_dbg(&pdev->xdev->dev, "freeing pdev @ 0x%p\n", pdev);
53
54         pcifront_free_roots(pdev);
55
56         if (pdev->evtchn != INVALID_EVTCHN)
57                 xenbus_free_evtchn(pdev->xdev, pdev->evtchn);
58
59         if (pdev->gnt_ref != INVALID_GRANT_REF)
60                 gnttab_end_foreign_access(pdev->gnt_ref, 0,
61                                           (unsigned long)pdev->sh_info);
62
63         pdev->xdev->dev.driver_data = NULL;
64
65         kfree(pdev);
66 }
67
68 static int pcifront_publish_info(struct pcifront_device *pdev)
69 {
70         int err = 0;
71         struct xenbus_transaction trans;
72
73         err = xenbus_grant_ring(pdev->xdev, virt_to_mfn(pdev->sh_info));
74         if (err < 0)
75                 goto out;
76
77         pdev->gnt_ref = err;
78
79         err = xenbus_alloc_evtchn(pdev->xdev, &pdev->evtchn);
80         if (err)
81                 goto out;
82
83       do_publish:
84         err = xenbus_transaction_start(&trans);
85         if (err) {
86                 xenbus_dev_fatal(pdev->xdev, err,
87                                  "Error writing configuration for backend "
88                                  "(start transaction)");
89                 goto out;
90         }
91
92         err = xenbus_printf(trans, pdev->xdev->nodename,
93                             "pci-op-ref", "%u", pdev->gnt_ref);
94         if (!err)
95                 err = xenbus_printf(trans, pdev->xdev->nodename,
96                                     "event-channel", "%u", pdev->evtchn);
97         if (!err)
98                 err = xenbus_printf(trans, pdev->xdev->nodename,
99                                     "magic", XEN_PCI_MAGIC);
100
101         if (err) {
102                 xenbus_transaction_end(trans, 1);
103                 xenbus_dev_fatal(pdev->xdev, err,
104                                  "Error writing configuration for backend");
105                 goto out;
106         } else {
107                 err = xenbus_transaction_end(trans, 0);
108                 if (err == -EAGAIN)
109                         goto do_publish;
110                 else if (err) {
111                         xenbus_dev_fatal(pdev->xdev, err,
112                                          "Error completing transaction "
113                                          "for backend");
114                         goto out;
115                 }
116         }
117
118         xenbus_switch_state(pdev->xdev, XenbusStateInitialised);
119
120         dev_dbg(&pdev->xdev->dev, "publishing successful!\n");
121
122       out:
123         return err;
124 }
125
126 static int pcifront_try_connect(struct pcifront_device *pdev)
127 {
128         int err = -EFAULT;
129         int i, num_roots, len;
130         char str[64];
131         unsigned int domain, bus;
132
133         spin_lock(&pdev->dev_lock);
134
135         /* Only connect once */
136         if (xenbus_read_driver_state(pdev->xdev->nodename) !=
137             XenbusStateInitialised)
138                 goto out;
139
140         err = pcifront_connect(pdev);
141         if (err) {
142                 xenbus_dev_fatal(pdev->xdev, err,
143                                  "Error connecting PCI Frontend");
144                 goto out;
145         }
146
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);
153                 num_roots = 0;
154         } else if (err != 1) {
155                 if (err == 0)
156                         err = -EINVAL;
157                 xenbus_dev_fatal(pdev->xdev, err,
158                                  "Error reading number of PCI roots");
159                 goto out;
160         }
161
162         for (i = 0; i < num_roots; i++) {
163                 len = snprintf(str, sizeof(str), "root-%d", i);
164                 if (unlikely(len >= (sizeof(str) - 1))) {
165                         err = -ENOMEM;
166                         goto out;
167                 }
168
169                 err = xenbus_scanf(XBT_NIL, pdev->xdev->otherend, str,
170                                    "%x:%x", &domain, &bus);
171                 if (err != 2) {
172                         if (err >= 0)
173                                 err = -EINVAL;
174                         xenbus_dev_fatal(pdev->xdev, err,
175                                          "Error reading PCI root %d", i);
176                         goto out;
177                 }
178
179                 err = pcifront_scan_root(pdev, domain, bus);
180                 if (err) {
181                         xenbus_dev_fatal(pdev->xdev, err,
182                                          "Error scanning PCI root %04x:%02x",
183                                          domain, bus);
184                         goto out;
185                 }
186         }
187
188         err = xenbus_switch_state(pdev->xdev, XenbusStateConnected);
189         if (err)
190                 goto out;
191
192       out:
193         spin_unlock(&pdev->dev_lock);
194         return err;
195 }
196
197 static int pcifront_try_disconnect(struct pcifront_device *pdev)
198 {
199         int err = 0;
200         enum xenbus_state prev_state;
201
202         spin_lock(&pdev->dev_lock);
203
204         prev_state = xenbus_read_driver_state(pdev->xdev->nodename);
205
206         if (prev_state < XenbusStateClosing)
207                 err = xenbus_switch_state(pdev->xdev, XenbusStateClosing);
208
209         if (!err && prev_state == XenbusStateConnected)
210                 pcifront_disconnect(pdev);
211
212         spin_unlock(&pdev->dev_lock);
213
214         return err;
215 }
216
217 static void pcifront_backend_changed(struct xenbus_device *xdev,
218                                      enum xenbus_state be_state)
219 {
220         struct pcifront_device *pdev = xdev->dev.driver_data;
221
222         switch (be_state) {
223         case XenbusStateClosing:
224                 dev_warn(&xdev->dev, "backend going away!\n");
225                 pcifront_try_disconnect(pdev);
226                 break;
227
228         case XenbusStateUnknown:
229         case XenbusStateClosed:
230                 dev_warn(&xdev->dev, "backend went away!\n");
231                 pcifront_try_disconnect(pdev);
232
233                 device_unregister(&pdev->xdev->dev);
234                 break;
235
236         case XenbusStateConnected:
237                 pcifront_try_connect(pdev);
238                 break;
239
240         default:
241                 break;
242         }
243 }
244
245 static int pcifront_xenbus_probe(struct xenbus_device *xdev,
246                                  const struct xenbus_device_id *id)
247 {
248         int err = 0;
249         struct pcifront_device *pdev = alloc_pdev(xdev);
250
251         if (pdev == NULL) {
252                 err = -ENOMEM;
253                 xenbus_dev_fatal(xdev, err,
254                                  "Error allocating pcifront_device struct");
255                 goto out;
256         }
257
258         err = pcifront_publish_info(pdev);
259
260       out:
261         return err;
262 }
263
264 static int pcifront_xenbus_remove(struct xenbus_device *xdev)
265 {
266         if (xdev->dev.driver_data)
267                 free_pdev(xdev->dev.driver_data);
268
269         return 0;
270 }
271
272 static struct xenbus_device_id xenpci_ids[] = {
273         {"pci"},
274         {{0}},
275 };
276
277 static struct xenbus_driver xenbus_pcifront_driver = {
278         .name                   = "pcifront",
279         .owner                  = THIS_MODULE,
280         .ids                    = xenpci_ids,
281         .probe                  = pcifront_xenbus_probe,
282         .remove                 = pcifront_xenbus_remove,
283         .otherend_changed       = pcifront_backend_changed,
284 };
285
286 static int __init pcifront_init(void)
287 {
288         if (!is_running_on_xen())
289                 return -ENODEV;
290
291         return xenbus_register_frontend(&xenbus_pcifront_driver);
292 }
293
294 /* Initialize after the Xen PCI Frontend Stub is initialized */
295 subsys_initcall(pcifront_init);