]> git.karo-electronics.de Git - mv-sheeva.git/blob - arch/x86/pci/xen.c
ba4077b73047354e4cd479524655ce5ecbf3d857
[mv-sheeva.git] / arch / x86 / pci / xen.c
1 /*
2  * Xen PCI Frontend Stub - puts some "dummy" functions in to the Linux
3  *                         x86 PCI core to support the Xen PCI Frontend
4  *
5  *   Author: Ryan Wilson <hap9@epoch.ncsc.mil>
6  */
7 #include <linux/module.h>
8 #include <linux/init.h>
9 #include <linux/pci.h>
10 #include <linux/acpi.h>
11
12 #include <linux/io.h>
13 #include <asm/io_apic.h>
14 #include <asm/pci_x86.h>
15
16 #include <asm/xen/hypervisor.h>
17
18 #include <xen/features.h>
19 #include <xen/events.h>
20 #include <asm/xen/pci.h>
21
22 static int xen_pcifront_enable_irq(struct pci_dev *dev)
23 {
24         int rc;
25         int share = 1;
26         int pirq;
27         u8 gsi;
28
29         rc = pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &gsi);
30         if (rc < 0) {
31                 dev_warn(&dev->dev, "Xen PCI: failed to read interrupt line: %d\n",
32                          rc);
33                 return rc;
34         }
35
36         rc = xen_allocate_pirq_gsi(gsi);
37         if (rc < 0) {
38                 dev_warn(&dev->dev, "Xen PCI: failed to allocate a PIRQ for GSI%d: %d\n",
39                          gsi, rc);
40                 return rc;
41         }
42         pirq = rc;
43
44         if (gsi < NR_IRQS_LEGACY)
45                 share = 0;
46
47         rc = xen_bind_pirq_gsi_to_irq(gsi, pirq, share, "pcifront");
48         if (rc < 0) {
49                 dev_warn(&dev->dev, "Xen PCI: failed to bind GSI%d (PIRQ%d) to IRQ: %d\n",
50                          gsi, pirq, rc);
51                 return rc;
52         }
53
54         dev->irq = rc;
55         dev_info(&dev->dev, "Xen PCI mapped GSI%d to IRQ%d\n", gsi, dev->irq);
56         return 0;
57 }
58
59 #ifdef CONFIG_ACPI
60 static int acpi_register_gsi_xen_hvm(struct device *dev, u32 gsi,
61                                  int trigger, int polarity)
62 {
63         int rc, irq;
64         struct physdev_map_pirq map_irq;
65         int shareable = 0;
66         char *name;
67
68         if (!xen_hvm_domain())
69                 return -1;
70
71         map_irq.domid = DOMID_SELF;
72         map_irq.type = MAP_PIRQ_TYPE_GSI;
73         map_irq.index = gsi;
74         map_irq.pirq = -1;
75
76         rc = HYPERVISOR_physdev_op(PHYSDEVOP_map_pirq, &map_irq);
77         if (rc) {
78                 printk(KERN_WARNING "xen map irq failed %d\n", rc);
79                 return -1;
80         }
81
82         if (trigger == ACPI_EDGE_SENSITIVE) {
83                 shareable = 0;
84                 name = "ioapic-edge";
85         } else {
86                 shareable = 1;
87                 name = "ioapic-level";
88         }
89
90         irq = xen_bind_pirq_gsi_to_irq(gsi, map_irq.pirq, shareable, name);
91
92         printk(KERN_DEBUG "xen: --> irq=%d, pirq=%d\n", irq, map_irq.pirq);
93
94         return irq;
95 }
96 #endif
97
98 #ifdef CONFIG_XEN_DOM0
99 static int xen_register_pirq(u32 gsi, int gsi_override, int triggering)
100 {
101         int rc, pirq, irq = -1;
102         struct physdev_map_pirq map_irq;
103         int shareable = 0;
104         char *name;
105
106         if (!xen_pv_domain())
107                 return -1;
108
109         if (triggering == ACPI_EDGE_SENSITIVE) {
110                 shareable = 0;
111                 name = "ioapic-edge";
112         } else {
113                 shareable = 1;
114                 name = "ioapic-level";
115         }
116         pirq = xen_allocate_pirq_gsi(gsi);
117         if (pirq < 0)
118                 goto out;
119
120         if (gsi_override >= 0)
121                 irq = xen_bind_pirq_gsi_to_irq(gsi_override, pirq, shareable, name);
122         else
123                 irq = xen_bind_pirq_gsi_to_irq(gsi, pirq, shareable, name);
124         if (irq < 0)
125                 goto out;
126
127         printk(KERN_DEBUG "xen: --> pirq=%d -> irq=%d (gsi=%d)\n", pirq, irq, gsi);
128
129         map_irq.domid = DOMID_SELF;
130         map_irq.type = MAP_PIRQ_TYPE_GSI;
131         map_irq.index = gsi;
132         map_irq.pirq = pirq;
133
134         rc = HYPERVISOR_physdev_op(PHYSDEVOP_map_pirq, &map_irq);
135         if (rc) {
136                 printk(KERN_WARNING "xen map irq failed %d\n", rc);
137                 return -1;
138         }
139
140 out:
141         return irq;
142 }
143
144 static int xen_register_gsi(u32 gsi, int gsi_override, int triggering, int polarity)
145 {
146         int rc, irq;
147         struct physdev_setup_gsi setup_gsi;
148
149         if (!xen_pv_domain())
150                 return -1;
151
152         printk(KERN_DEBUG "xen: registering gsi %u triggering %d polarity %d\n",
153                         gsi, triggering, polarity);
154
155         irq = xen_register_pirq(gsi, gsi_override, triggering);
156
157         setup_gsi.gsi = gsi;
158         setup_gsi.triggering = (triggering == ACPI_EDGE_SENSITIVE ? 0 : 1);
159         setup_gsi.polarity = (polarity == ACPI_ACTIVE_HIGH ? 0 : 1);
160
161         rc = HYPERVISOR_physdev_op(PHYSDEVOP_setup_gsi, &setup_gsi);
162         if (rc == -EEXIST)
163                 printk(KERN_INFO "Already setup the GSI :%d\n", gsi);
164         else if (rc) {
165                 printk(KERN_ERR "Failed to setup GSI :%d, err_code:%d\n",
166                                 gsi, rc);
167         }
168
169         return irq;
170 }
171
172 static int acpi_register_gsi_xen(struct device *dev, u32 gsi,
173                                  int trigger, int polarity)
174 {
175         return xen_register_gsi(gsi, -1 /* no GSI override */, trigger, polarity);
176 }
177 #endif
178
179 #if defined(CONFIG_PCI_MSI)
180 #include <linux/msi.h>
181 #include <asm/msidef.h>
182
183 struct xen_pci_frontend_ops *xen_pci_frontend;
184 EXPORT_SYMBOL_GPL(xen_pci_frontend);
185
186 /*
187  * For MSI interrupts we have to use drivers/xen/event.s functions to
188  * allocate an irq_desc and setup the right */
189 static int xen_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
190 {
191         int irq, ret, i;
192         struct msi_desc *msidesc;
193         int *v;
194
195         v = kzalloc(sizeof(int) * max(1, nvec), GFP_KERNEL);
196         if (!v)
197                 return -ENOMEM;
198
199         if (type == PCI_CAP_ID_MSIX)
200                 ret = xen_pci_frontend_enable_msix(dev, v, nvec);
201         else
202                 ret = xen_pci_frontend_enable_msi(dev, v);
203         if (ret)
204                 goto error;
205         i = 0;
206         list_for_each_entry(msidesc, &dev->msi_list, list) {
207                 irq = xen_bind_pirq_msi_to_irq(dev, msidesc, v[i], 0,
208                                                (type == PCI_CAP_ID_MSIX) ?
209                                                "pcifront-msi-x" :
210                                                "pcifront-msi",
211                                                 DOMID_SELF);
212                 if (irq < 0)
213                         goto free;
214                 i++;
215         }
216         kfree(v);
217         return 0;
218
219 error:
220         dev_err(&dev->dev, "Xen PCI frontend has not registered MSI/MSI-X support!\n");
221 free:
222         kfree(v);
223         return ret;
224 }
225
226 #define XEN_PIRQ_MSI_DATA  (MSI_DATA_TRIGGER_EDGE | \
227                 MSI_DATA_LEVEL_ASSERT | (3 << 8) | MSI_DATA_VECTOR(0))
228
229 static void xen_msi_compose_msg(struct pci_dev *pdev, unsigned int pirq,
230                 struct msi_msg *msg)
231 {
232         /* We set vector == 0 to tell the hypervisor we don't care about it,
233          * but we want a pirq setup instead.
234          * We use the dest_id field to pass the pirq that we want. */
235         msg->address_hi = MSI_ADDR_BASE_HI | MSI_ADDR_EXT_DEST_ID(pirq);
236         msg->address_lo =
237                 MSI_ADDR_BASE_LO |
238                 MSI_ADDR_DEST_MODE_PHYSICAL |
239                 MSI_ADDR_REDIRECTION_CPU |
240                 MSI_ADDR_DEST_ID(pirq);
241
242         msg->data = XEN_PIRQ_MSI_DATA;
243 }
244
245 static int xen_hvm_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
246 {
247         int irq, pirq;
248         struct msi_desc *msidesc;
249         struct msi_msg msg;
250
251         list_for_each_entry(msidesc, &dev->msi_list, list) {
252                 __read_msi_msg(msidesc, &msg);
253                 pirq = MSI_ADDR_EXT_DEST_ID(msg.address_hi) |
254                         ((msg.address_lo >> MSI_ADDR_DEST_ID_SHIFT) & 0xff);
255                 if (msg.data != XEN_PIRQ_MSI_DATA ||
256                     xen_irq_from_pirq(pirq) < 0) {
257                         pirq = xen_allocate_pirq_msi(dev, msidesc);
258                         if (pirq < 0)
259                                 goto error;
260                         xen_msi_compose_msg(dev, pirq, &msg);
261                         __write_msi_msg(msidesc, &msg);
262                         dev_dbg(&dev->dev, "xen: msi bound to pirq=%d\n", pirq);
263                 } else {
264                         dev_dbg(&dev->dev,
265                                 "xen: msi already bound to pirq=%d\n", pirq);
266                 }
267                 irq = xen_bind_pirq_msi_to_irq(dev, msidesc, pirq, 0,
268                                                (type == PCI_CAP_ID_MSIX) ?
269                                                "msi-x" : "msi",
270                                                DOMID_SELF);
271                 if (irq < 0)
272                         goto error;
273                 dev_dbg(&dev->dev,
274                         "xen: msi --> pirq=%d --> irq=%d\n", pirq, irq);
275         }
276         return 0;
277
278 error:
279         dev_err(&dev->dev,
280                 "Xen PCI frontend has not registered MSI/MSI-X support!\n");
281         return -ENODEV;
282 }
283
284 #ifdef CONFIG_XEN_DOM0
285 static int xen_initdom_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
286 {
287         int ret = 0;
288         struct msi_desc *msidesc;
289
290         list_for_each_entry(msidesc, &dev->msi_list, list) {
291                 struct physdev_map_pirq map_irq;
292                 domid_t domid;
293
294                 domid = ret = xen_find_device_domain_owner(dev);
295                 /* N.B. Casting int's -ENODEV to uint16_t results in 0xFFED,
296                  * hence check ret value for < 0. */
297                 if (ret < 0)
298                         domid = DOMID_SELF;
299
300                 memset(&map_irq, 0, sizeof(map_irq));
301                 map_irq.domid = domid;
302                 map_irq.type = MAP_PIRQ_TYPE_MSI;
303                 map_irq.index = -1;
304                 map_irq.pirq = -1;
305                 map_irq.bus = dev->bus->number;
306                 map_irq.devfn = dev->devfn;
307
308                 if (type == PCI_CAP_ID_MSIX) {
309                         int pos;
310                         u32 table_offset, bir;
311
312                         pos = pci_find_capability(dev, PCI_CAP_ID_MSIX);
313
314                         pci_read_config_dword(dev, pos + PCI_MSIX_TABLE,
315                                               &table_offset);
316                         bir = (u8)(table_offset & PCI_MSIX_FLAGS_BIRMASK);
317
318                         map_irq.table_base = pci_resource_start(dev, bir);
319                         map_irq.entry_nr = msidesc->msi_attrib.entry_nr;
320                 }
321
322                 ret = HYPERVISOR_physdev_op(PHYSDEVOP_map_pirq, &map_irq);
323                 if (ret) {
324                         dev_warn(&dev->dev, "xen map irq failed %d for %d domain\n",
325                                  ret, domid);
326                         goto out;
327                 }
328
329                 ret = xen_bind_pirq_msi_to_irq(dev, msidesc,
330                                                map_irq.pirq, map_irq.index,
331                                                (type == PCI_CAP_ID_MSIX) ?
332                                                "msi-x" : "msi",
333                                                 domid);
334                 if (ret < 0)
335                         goto out;
336         }
337         ret = 0;
338 out:
339         return ret;
340 }
341 #endif
342
343 static void xen_teardown_msi_irqs(struct pci_dev *dev)
344 {
345         struct msi_desc *msidesc;
346
347         msidesc = list_entry(dev->msi_list.next, struct msi_desc, list);
348         if (msidesc->msi_attrib.is_msix)
349                 xen_pci_frontend_disable_msix(dev);
350         else
351                 xen_pci_frontend_disable_msi(dev);
352
353         /* Free the IRQ's and the msidesc using the generic code. */
354         default_teardown_msi_irqs(dev);
355 }
356
357 static void xen_teardown_msi_irq(unsigned int irq)
358 {
359         xen_destroy_irq(irq);
360 }
361
362 #endif
363
364
365 int __init pci_xen_init(void)
366 {
367         if (!xen_pv_domain() || xen_initial_domain())
368                 return -ENODEV;
369
370         printk(KERN_INFO "PCI: setting up Xen PCI frontend stub\n");
371
372         pcibios_set_cache_line_size();
373
374         pcibios_enable_irq = xen_pcifront_enable_irq;
375         pcibios_disable_irq = NULL;
376
377 #ifdef CONFIG_ACPI
378         /* Keep ACPI out of the picture */
379         acpi_noirq = 1;
380 #endif
381
382 #ifdef CONFIG_PCI_MSI
383         x86_msi.setup_msi_irqs = xen_setup_msi_irqs;
384         x86_msi.teardown_msi_irq = xen_teardown_msi_irq;
385         x86_msi.teardown_msi_irqs = xen_teardown_msi_irqs;
386 #endif
387         return 0;
388 }
389
390 int __init pci_xen_hvm_init(void)
391 {
392         if (!xen_feature(XENFEAT_hvm_pirqs))
393                 return 0;
394
395 #ifdef CONFIG_ACPI
396         /*
397          * We don't want to change the actual ACPI delivery model,
398          * just how GSIs get registered.
399          */
400         __acpi_register_gsi = acpi_register_gsi_xen_hvm;
401 #endif
402
403 #ifdef CONFIG_PCI_MSI
404         x86_msi.setup_msi_irqs = xen_hvm_setup_msi_irqs;
405         x86_msi.teardown_msi_irq = xen_teardown_msi_irq;
406 #endif
407         return 0;
408 }
409
410 #ifdef CONFIG_XEN_DOM0
411 static __init void xen_setup_acpi_sci(void)
412 {
413         int rc;
414         int trigger, polarity;
415         int gsi = acpi_sci_override_gsi;
416         int irq = -1;
417         int gsi_override = -1;
418
419         if (!gsi)
420                 return;
421
422         rc = acpi_get_override_irq(gsi, &trigger, &polarity);
423         if (rc) {
424                 printk(KERN_WARNING "xen: acpi_get_override_irq failed for acpi"
425                                 " sci, rc=%d\n", rc);
426                 return;
427         }
428         trigger = trigger ? ACPI_LEVEL_SENSITIVE : ACPI_EDGE_SENSITIVE;
429         polarity = polarity ? ACPI_ACTIVE_LOW : ACPI_ACTIVE_HIGH;
430         
431         printk(KERN_INFO "xen: sci override: global_irq=%d trigger=%d "
432                         "polarity=%d\n", gsi, trigger, polarity);
433
434         /* Before we bind the GSI to a Linux IRQ, check whether
435          * we need to override it with bus_irq (IRQ) value. Usually for
436          * IRQs below IRQ_LEGACY_IRQ this holds IRQ == GSI, as so:
437          *  ACPI: INT_SRC_OVR (bus 0 bus_irq 9 global_irq 9 low level)
438          * but there are oddballs where the IRQ != GSI:
439          *  ACPI: INT_SRC_OVR (bus 0 bus_irq 9 global_irq 20 low level)
440          * which ends up being: gsi_to_irq[9] == 20
441          * (which is what acpi_gsi_to_irq ends up calling when starting the
442          * the ACPI interpreter and keels over since IRQ 9 has not been
443          * setup as we had setup IRQ 20 for it).
444          */
445         /* Check whether the GSI != IRQ */
446         if (acpi_gsi_to_irq(gsi, &irq) == 0) {
447                 if (irq >= 0 && irq != gsi)
448                         /* Bugger, we MUST have that IRQ. */
449                         gsi_override = irq;
450         }
451
452         gsi = xen_register_gsi(gsi, gsi_override, trigger, polarity);
453         printk(KERN_INFO "xen: acpi sci %d\n", gsi);
454
455         return;
456 }
457
458 static int __init pci_xen_initial_domain(void)
459 {
460 #ifdef CONFIG_PCI_MSI
461         x86_msi.setup_msi_irqs = xen_initdom_setup_msi_irqs;
462         x86_msi.teardown_msi_irq = xen_teardown_msi_irq;
463 #endif
464         xen_setup_acpi_sci();
465         __acpi_register_gsi = acpi_register_gsi_xen;
466
467         return 0;
468 }
469
470 void __init xen_setup_pirqs(void)
471 {
472         int pirq, irq;
473
474         pci_xen_initial_domain();
475
476         if (0 == nr_ioapics) {
477                 for (irq = 0; irq < NR_IRQS_LEGACY; irq++) {
478                         pirq = xen_allocate_pirq_gsi(irq);
479                         if (WARN(pirq < 0,
480                                  "Could not allocate PIRQ for legacy interrupt\n"))
481                                 break;
482                         irq = xen_bind_pirq_gsi_to_irq(irq, pirq, 0, "xt-pic");
483                 }
484                 return;
485         }
486
487         /* Pre-allocate legacy irqs */
488         for (irq = 0; irq < NR_IRQS_LEGACY; irq++) {
489                 int trigger, polarity;
490
491                 if (acpi_get_override_irq(irq, &trigger, &polarity) == -1)
492                         continue;
493
494                 xen_register_pirq(irq, -1 /* no GSI override */,
495                         trigger ? ACPI_LEVEL_SENSITIVE : ACPI_EDGE_SENSITIVE);
496         }
497 }
498
499 struct xen_device_domain_owner {
500         domid_t domain;
501         struct pci_dev *dev;
502         struct list_head list;
503 };
504
505 static DEFINE_SPINLOCK(dev_domain_list_spinlock);
506 static struct list_head dev_domain_list = LIST_HEAD_INIT(dev_domain_list);
507
508 static struct xen_device_domain_owner *find_device(struct pci_dev *dev)
509 {
510         struct xen_device_domain_owner *owner;
511
512         list_for_each_entry(owner, &dev_domain_list, list) {
513                 if (owner->dev == dev)
514                         return owner;
515         }
516         return NULL;
517 }
518
519 int xen_find_device_domain_owner(struct pci_dev *dev)
520 {
521         struct xen_device_domain_owner *owner;
522         int domain = -ENODEV;
523
524         spin_lock(&dev_domain_list_spinlock);
525         owner = find_device(dev);
526         if (owner)
527                 domain = owner->domain;
528         spin_unlock(&dev_domain_list_spinlock);
529         return domain;
530 }
531 EXPORT_SYMBOL_GPL(xen_find_device_domain_owner);
532
533 int xen_register_device_domain_owner(struct pci_dev *dev, uint16_t domain)
534 {
535         struct xen_device_domain_owner *owner;
536
537         owner = kzalloc(sizeof(struct xen_device_domain_owner), GFP_KERNEL);
538         if (!owner)
539                 return -ENODEV;
540
541         spin_lock(&dev_domain_list_spinlock);
542         if (find_device(dev)) {
543                 spin_unlock(&dev_domain_list_spinlock);
544                 kfree(owner);
545                 return -EEXIST;
546         }
547         owner->domain = domain;
548         owner->dev = dev;
549         list_add_tail(&owner->list, &dev_domain_list);
550         spin_unlock(&dev_domain_list_spinlock);
551         return 0;
552 }
553 EXPORT_SYMBOL_GPL(xen_register_device_domain_owner);
554
555 int xen_unregister_device_domain_owner(struct pci_dev *dev)
556 {
557         struct xen_device_domain_owner *owner;
558
559         spin_lock(&dev_domain_list_spinlock);
560         owner = find_device(dev);
561         if (!owner) {
562                 spin_unlock(&dev_domain_list_spinlock);
563                 return -ENODEV;
564         }
565         list_del(&owner->list);
566         spin_unlock(&dev_domain_list_spinlock);
567         kfree(owner);
568         return 0;
569 }
570 EXPORT_SYMBOL_GPL(xen_unregister_device_domain_owner);
571 #endif