diff options
Diffstat (limited to 'arch/x86/pci/xen.c')
| -rw-r--r-- | arch/x86/pci/xen.c | 135 |
1 files changed, 135 insertions, 0 deletions
diff --git a/arch/x86/pci/xen.c b/arch/x86/pci/xen.c index b5bd6420851e..dd0b5fdb27b9 100644 --- a/arch/x86/pci/xen.c +++ b/arch/x86/pci/xen.c | |||
| @@ -257,3 +257,138 @@ int __init pci_xen_hvm_init(void) | |||
| 257 | #endif | 257 | #endif |
| 258 | return 0; | 258 | return 0; |
| 259 | } | 259 | } |
| 260 | |||
| 261 | #ifdef CONFIG_XEN_DOM0 | ||
| 262 | static int xen_register_pirq(u32 gsi, int triggering) | ||
| 263 | { | ||
| 264 | int rc, irq; | ||
| 265 | struct physdev_map_pirq map_irq; | ||
| 266 | int shareable = 0; | ||
| 267 | char *name; | ||
| 268 | |||
| 269 | if (!xen_pv_domain()) | ||
| 270 | return -1; | ||
| 271 | |||
| 272 | if (triggering == ACPI_EDGE_SENSITIVE) { | ||
| 273 | shareable = 0; | ||
| 274 | name = "ioapic-edge"; | ||
| 275 | } else { | ||
| 276 | shareable = 1; | ||
| 277 | name = "ioapic-level"; | ||
| 278 | } | ||
| 279 | |||
| 280 | irq = xen_allocate_pirq(gsi, shareable, name); | ||
| 281 | |||
| 282 | printk(KERN_DEBUG "xen: --> irq=%d\n", irq); | ||
| 283 | |||
| 284 | if (irq < 0) | ||
| 285 | goto out; | ||
| 286 | |||
| 287 | map_irq.domid = DOMID_SELF; | ||
| 288 | map_irq.type = MAP_PIRQ_TYPE_GSI; | ||
| 289 | map_irq.index = gsi; | ||
| 290 | map_irq.pirq = irq; | ||
| 291 | |||
| 292 | rc = HYPERVISOR_physdev_op(PHYSDEVOP_map_pirq, &map_irq); | ||
| 293 | if (rc) { | ||
| 294 | printk(KERN_WARNING "xen map irq failed %d\n", rc); | ||
| 295 | return -1; | ||
| 296 | } | ||
| 297 | |||
| 298 | out: | ||
| 299 | return irq; | ||
| 300 | } | ||
| 301 | |||
| 302 | static int xen_register_gsi(u32 gsi, int triggering, int polarity) | ||
| 303 | { | ||
| 304 | int rc, irq; | ||
| 305 | struct physdev_setup_gsi setup_gsi; | ||
| 306 | |||
| 307 | if (!xen_pv_domain()) | ||
| 308 | return -1; | ||
| 309 | |||
| 310 | printk(KERN_DEBUG "xen: registering gsi %u triggering %d polarity %d\n", | ||
| 311 | gsi, triggering, polarity); | ||
| 312 | |||
| 313 | irq = xen_register_pirq(gsi, triggering); | ||
| 314 | |||
| 315 | setup_gsi.gsi = gsi; | ||
| 316 | setup_gsi.triggering = (triggering == ACPI_EDGE_SENSITIVE ? 0 : 1); | ||
| 317 | setup_gsi.polarity = (polarity == ACPI_ACTIVE_HIGH ? 0 : 1); | ||
| 318 | |||
| 319 | rc = HYPERVISOR_physdev_op(PHYSDEVOP_setup_gsi, &setup_gsi); | ||
| 320 | if (rc == -EEXIST) | ||
| 321 | printk(KERN_INFO "Already setup the GSI :%d\n", gsi); | ||
| 322 | else if (rc) { | ||
| 323 | printk(KERN_ERR "Failed to setup GSI :%d, err_code:%d\n", | ||
| 324 | gsi, rc); | ||
| 325 | } | ||
| 326 | |||
| 327 | return irq; | ||
| 328 | } | ||
| 329 | |||
| 330 | static __init void xen_setup_acpi_sci(void) | ||
| 331 | { | ||
| 332 | int rc; | ||
| 333 | int trigger, polarity; | ||
| 334 | int gsi = acpi_sci_override_gsi; | ||
| 335 | |||
| 336 | if (!gsi) | ||
| 337 | return; | ||
| 338 | |||
| 339 | rc = acpi_get_override_irq(gsi, &trigger, &polarity); | ||
| 340 | if (rc) { | ||
| 341 | printk(KERN_WARNING "xen: acpi_get_override_irq failed for acpi" | ||
| 342 | " sci, rc=%d\n", rc); | ||
| 343 | return; | ||
| 344 | } | ||
| 345 | trigger = trigger ? ACPI_LEVEL_SENSITIVE : ACPI_EDGE_SENSITIVE; | ||
| 346 | polarity = polarity ? ACPI_ACTIVE_LOW : ACPI_ACTIVE_HIGH; | ||
| 347 | |||
| 348 | printk(KERN_INFO "xen: sci override: global_irq=%d trigger=%d " | ||
| 349 | "polarity=%d\n", gsi, trigger, polarity); | ||
| 350 | |||
| 351 | gsi = xen_register_gsi(gsi, trigger, polarity); | ||
| 352 | printk(KERN_INFO "xen: acpi sci %d\n", gsi); | ||
| 353 | |||
| 354 | return; | ||
| 355 | } | ||
| 356 | |||
| 357 | static int acpi_register_gsi_xen(struct device *dev, u32 gsi, | ||
| 358 | int trigger, int polarity) | ||
| 359 | { | ||
| 360 | return xen_register_gsi(gsi, trigger, polarity); | ||
| 361 | } | ||
| 362 | |||
| 363 | static int __init pci_xen_initial_domain(void) | ||
| 364 | { | ||
| 365 | xen_setup_acpi_sci(); | ||
| 366 | __acpi_register_gsi = acpi_register_gsi_xen; | ||
| 367 | |||
| 368 | return 0; | ||
| 369 | } | ||
| 370 | |||
| 371 | void __init xen_setup_pirqs(void) | ||
| 372 | { | ||
| 373 | int irq; | ||
| 374 | |||
| 375 | pci_xen_initial_domain(); | ||
| 376 | |||
| 377 | if (0 == nr_ioapics) { | ||
| 378 | for (irq = 0; irq < NR_IRQS_LEGACY; irq++) | ||
| 379 | xen_allocate_pirq(irq, 0, "xt-pic"); | ||
| 380 | return; | ||
| 381 | } | ||
| 382 | |||
| 383 | /* Pre-allocate legacy irqs */ | ||
| 384 | for (irq = 0; irq < NR_IRQS_LEGACY; irq++) { | ||
| 385 | int trigger, polarity; | ||
| 386 | |||
| 387 | if (acpi_get_override_irq(irq, &trigger, &polarity) == -1) | ||
| 388 | continue; | ||
| 389 | |||
| 390 | xen_register_pirq(irq, | ||
| 391 | trigger ? ACPI_LEVEL_SENSITIVE : ACPI_EDGE_SENSITIVE); | ||
| 392 | } | ||
| 393 | } | ||
| 394 | #endif | ||
