aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJiang Liu <jiang.liu@linux.intel.com>2014-10-27 04:12:02 -0400
committerThomas Gleixner <tglx@linutronix.de>2014-12-16 08:08:17 -0500
commit443809828cb5ee0eae09060aa8d4b42b79dd4e0b (patch)
tree834d204734b505fc30b33b64830fcdf1d297463e
parent849d3569bbaf2dfdea41a6073bc0e25a0578c380 (diff)
x86, irq: Move PCI MSI related code from io_apic.c into msi.c
Create arch/x86/kernel/apic/msi.c to host MSI related code, preparing for enabling hierarchy irqdomain. Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com> Cc: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com> Cc: Tony Luck <tony.luck@intel.com> Cc: Joerg Roedel <joro@8bytes.org> Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org> Cc: Rafael J. Wysocki <rjw@rjwysocki.net> Cc: Bjorn Helgaas <bhelgaas@google.com> Cc: Randy Dunlap <rdunlap@infradead.org> Cc: Yinghai Lu <yinghai@kernel.org> Cc: Borislav Petkov <bp@alien8.de> Cc: Rafael J. Wysocki <rafael.j.wysocki@intel.com> Cc: Grant Likely <grant.likely@linaro.org> Cc: Prarit Bhargava <prarit@redhat.com> Link: http://lkml.kernel.org/r/1414397531-28254-12-git-send-email-jiang.liu@linux.intel.com Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
-rw-r--r--arch/x86/include/asm/io_apic.h4
-rw-r--r--arch/x86/include/asm/pci.h3
-rw-r--r--arch/x86/kernel/apic/Makefile1
-rw-r--r--arch/x86/kernel/apic/io_apic.c272
-rw-r--r--arch/x86/kernel/apic/msi.c286
5 files changed, 290 insertions, 276 deletions
diff --git a/arch/x86/include/asm/io_apic.h b/arch/x86/include/asm/io_apic.h
index 0db2b7037e4b..bdd45c25023a 100644
--- a/arch/x86/include/asm/io_apic.h
+++ b/arch/x86/include/asm/io_apic.h
@@ -148,9 +148,6 @@ extern int native_setup_ioapic_entry(int, struct IO_APIC_route_entry *,
148 struct io_apic_irq_attr *); 148 struct io_apic_irq_attr *);
149extern void eoi_ioapic_irq(unsigned int irq, struct irq_cfg *cfg); 149extern void eoi_ioapic_irq(unsigned int irq, struct irq_cfg *cfg);
150 150
151extern void native_compose_msi_msg(struct pci_dev *pdev,
152 unsigned int irq, unsigned int dest,
153 struct msi_msg *msg, u8 hpet_id);
154extern void native_eoi_ioapic_pin(int apic, int pin, int vector); 151extern void native_eoi_ioapic_pin(int apic, int pin, int vector);
155 152
156extern int save_ioapic_entries(void); 153extern int save_ioapic_entries(void);
@@ -261,7 +258,6 @@ static inline void disable_ioapic_support(void) { }
261#define native_io_apic_print_entries NULL 258#define native_io_apic_print_entries NULL
262#define native_ioapic_set_affinity NULL 259#define native_ioapic_set_affinity NULL
263#define native_setup_ioapic_entry NULL 260#define native_setup_ioapic_entry NULL
264#define native_compose_msi_msg NULL
265#define native_eoi_ioapic_pin NULL 261#define native_eoi_ioapic_pin NULL
266#endif 262#endif
267 263
diff --git a/arch/x86/include/asm/pci.h b/arch/x86/include/asm/pci.h
index 0892ea0e683f..4e370a5d8117 100644
--- a/arch/x86/include/asm/pci.h
+++ b/arch/x86/include/asm/pci.h
@@ -96,12 +96,15 @@ extern void pci_iommu_alloc(void);
96#ifdef CONFIG_PCI_MSI 96#ifdef CONFIG_PCI_MSI
97/* implemented in arch/x86/kernel/apic/io_apic. */ 97/* implemented in arch/x86/kernel/apic/io_apic. */
98struct msi_desc; 98struct msi_desc;
99void native_compose_msi_msg(struct pci_dev *pdev, unsigned int irq,
100 unsigned int dest, struct msi_msg *msg, u8 hpet_id);
99int native_setup_msi_irqs(struct pci_dev *dev, int nvec, int type); 101int native_setup_msi_irqs(struct pci_dev *dev, int nvec, int type);
100void native_teardown_msi_irq(unsigned int irq); 102void native_teardown_msi_irq(unsigned int irq);
101void native_restore_msi_irqs(struct pci_dev *dev); 103void native_restore_msi_irqs(struct pci_dev *dev);
102int setup_msi_irq(struct pci_dev *dev, struct msi_desc *msidesc, 104int setup_msi_irq(struct pci_dev *dev, struct msi_desc *msidesc,
103 unsigned int irq_base, unsigned int irq_offset); 105 unsigned int irq_base, unsigned int irq_offset);
104#else 106#else
107#define native_compose_msi_msg NULL
105#define native_setup_msi_irqs NULL 108#define native_setup_msi_irqs NULL
106#define native_teardown_msi_irq NULL 109#define native_teardown_msi_irq NULL
107#endif 110#endif
diff --git a/arch/x86/kernel/apic/Makefile b/arch/x86/kernel/apic/Makefile
index 84299e5d10dc..aac300750f0e 100644
--- a/arch/x86/kernel/apic/Makefile
+++ b/arch/x86/kernel/apic/Makefile
@@ -6,6 +6,7 @@ obj-$(CONFIG_X86_LOCAL_APIC) += apic.o apic_noop.o ipi.o vector.o
6obj-y += hw_nmi.o 6obj-y += hw_nmi.o
7 7
8obj-$(CONFIG_X86_IO_APIC) += io_apic.o 8obj-$(CONFIG_X86_IO_APIC) += io_apic.o
9obj-$(CONFIG_PCI_MSI) += msi.o
9obj-$(CONFIG_SMP) += ipi.o 10obj-$(CONFIG_SMP) += ipi.o
10 11
11ifeq ($(CONFIG_X86_64),y) 12ifeq ($(CONFIG_X86_64),y)
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c
index 677044df2d7a..653fe211e4ca 100644
--- a/arch/x86/kernel/apic/io_apic.c
+++ b/arch/x86/kernel/apic/io_apic.c
@@ -32,15 +32,12 @@
32#include <linux/module.h> 32#include <linux/module.h>
33#include <linux/syscore_ops.h> 33#include <linux/syscore_ops.h>
34#include <linux/irqdomain.h> 34#include <linux/irqdomain.h>
35#include <linux/msi.h>
36#include <linux/htirq.h> 35#include <linux/htirq.h>
37#include <linux/freezer.h> 36#include <linux/freezer.h>
38#include <linux/kthread.h> 37#include <linux/kthread.h>
39#include <linux/jiffies.h> /* time_after() */ 38#include <linux/jiffies.h> /* time_after() */
40#include <linux/slab.h> 39#include <linux/slab.h>
41#include <linux/bootmem.h> 40#include <linux/bootmem.h>
42#include <linux/dmar.h>
43#include <linux/hpet.h>
44 41
45#include <asm/idle.h> 42#include <asm/idle.h>
46#include <asm/io.h> 43#include <asm/io.h>
@@ -52,11 +49,9 @@
52#include <asm/dma.h> 49#include <asm/dma.h>
53#include <asm/timer.h> 50#include <asm/timer.h>
54#include <asm/i8259.h> 51#include <asm/i8259.h>
55#include <asm/msidef.h>
56#include <asm/hypertransport.h> 52#include <asm/hypertransport.h>
57#include <asm/setup.h> 53#include <asm/setup.h>
58#include <asm/irq_remapping.h> 54#include <asm/irq_remapping.h>
59#include <asm/hpet.h>
60#include <asm/hw_irq.h> 55#include <asm/hw_irq.h>
61 56
62#include <asm/apic.h> 57#include <asm/apic.h>
@@ -2456,273 +2451,6 @@ static int __init ioapic_init_ops(void)
2456device_initcall(ioapic_init_ops); 2451device_initcall(ioapic_init_ops);
2457 2452
2458/* 2453/*
2459 * MSI message composition
2460 */
2461void native_compose_msi_msg(struct pci_dev *pdev,
2462 unsigned int irq, unsigned int dest,
2463 struct msi_msg *msg, u8 hpet_id)
2464{
2465 struct irq_cfg *cfg = irq_cfg(irq);
2466
2467 msg->address_hi = MSI_ADDR_BASE_HI;
2468
2469 if (x2apic_enabled())
2470 msg->address_hi |= MSI_ADDR_EXT_DEST_ID(dest);
2471
2472 msg->address_lo =
2473 MSI_ADDR_BASE_LO |
2474 ((apic->irq_dest_mode == 0) ?
2475 MSI_ADDR_DEST_MODE_PHYSICAL:
2476 MSI_ADDR_DEST_MODE_LOGICAL) |
2477 ((apic->irq_delivery_mode != dest_LowestPrio) ?
2478 MSI_ADDR_REDIRECTION_CPU:
2479 MSI_ADDR_REDIRECTION_LOWPRI) |
2480 MSI_ADDR_DEST_ID(dest);
2481
2482 msg->data =
2483 MSI_DATA_TRIGGER_EDGE |
2484 MSI_DATA_LEVEL_ASSERT |
2485 ((apic->irq_delivery_mode != dest_LowestPrio) ?
2486 MSI_DATA_DELIVERY_FIXED:
2487 MSI_DATA_DELIVERY_LOWPRI) |
2488 MSI_DATA_VECTOR(cfg->vector);
2489}
2490
2491#ifdef CONFIG_PCI_MSI
2492static int msi_compose_msg(struct pci_dev *pdev, unsigned int irq,
2493 struct msi_msg *msg, u8 hpet_id)
2494{
2495 struct irq_cfg *cfg;
2496 int err;
2497 unsigned dest;
2498
2499 if (disable_apic)
2500 return -ENXIO;
2501
2502 cfg = irq_cfg(irq);
2503 err = assign_irq_vector(irq, cfg, apic->target_cpus());
2504 if (err)
2505 return err;
2506
2507 err = apic->cpu_mask_to_apicid_and(cfg->domain,
2508 apic->target_cpus(), &dest);
2509 if (err)
2510 return err;
2511
2512 x86_msi.compose_msi_msg(pdev, irq, dest, msg, hpet_id);
2513
2514 return 0;
2515}
2516
2517static int
2518msi_set_affinity(struct irq_data *data, const struct cpumask *mask, bool force)
2519{
2520 struct irq_cfg *cfg = data->chip_data;
2521 struct msi_msg msg;
2522 unsigned int dest;
2523 int ret;
2524
2525 ret = apic_set_affinity(data, mask, &dest);
2526 if (ret)
2527 return ret;
2528
2529 __get_cached_msi_msg(data->msi_desc, &msg);
2530
2531 msg.data &= ~MSI_DATA_VECTOR_MASK;
2532 msg.data |= MSI_DATA_VECTOR(cfg->vector);
2533 msg.address_lo &= ~MSI_ADDR_DEST_ID_MASK;
2534 msg.address_lo |= MSI_ADDR_DEST_ID(dest);
2535
2536 __pci_write_msi_msg(data->msi_desc, &msg);
2537
2538 return IRQ_SET_MASK_OK_NOCOPY;
2539}
2540
2541/*
2542 * IRQ Chip for MSI PCI/PCI-X/PCI-Express Devices,
2543 * which implement the MSI or MSI-X Capability Structure.
2544 */
2545static struct irq_chip msi_chip = {
2546 .name = "PCI-MSI",
2547 .irq_unmask = pci_msi_unmask_irq,
2548 .irq_mask = pci_msi_mask_irq,
2549 .irq_ack = apic_ack_edge,
2550 .irq_set_affinity = msi_set_affinity,
2551 .irq_retrigger = apic_retrigger_irq,
2552 .flags = IRQCHIP_SKIP_SET_WAKE,
2553};
2554
2555int setup_msi_irq(struct pci_dev *dev, struct msi_desc *msidesc,
2556 unsigned int irq_base, unsigned int irq_offset)
2557{
2558 struct irq_chip *chip = &msi_chip;
2559 struct msi_msg msg;
2560 unsigned int irq = irq_base + irq_offset;
2561 int ret;
2562
2563 ret = msi_compose_msg(dev, irq, &msg, -1);
2564 if (ret < 0)
2565 return ret;
2566
2567 irq_set_msi_desc_off(irq_base, irq_offset, msidesc);
2568
2569 /*
2570 * MSI-X message is written per-IRQ, the offset is always 0.
2571 * MSI message denotes a contiguous group of IRQs, written for 0th IRQ.
2572 */
2573 if (!irq_offset)
2574 pci_write_msi_msg(irq, &msg);
2575
2576 setup_remapped_irq(irq, irq_cfg(irq), chip);
2577
2578 irq_set_chip_and_handler_name(irq, chip, handle_edge_irq, "edge");
2579
2580 dev_printk(KERN_DEBUG, &dev->dev, "irq %d for MSI/MSI-X\n", irq);
2581
2582 return 0;
2583}
2584
2585int native_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
2586{
2587 struct msi_desc *msidesc;
2588 unsigned int irq;
2589 int node, ret;
2590
2591 /* Multiple MSI vectors only supported with interrupt remapping */
2592 if (type == PCI_CAP_ID_MSI && nvec > 1)
2593 return 1;
2594
2595 node = dev_to_node(&dev->dev);
2596
2597 list_for_each_entry(msidesc, &dev->msi_list, list) {
2598 irq = irq_alloc_hwirq(node);
2599 if (!irq)
2600 return -ENOSPC;
2601
2602 ret = setup_msi_irq(dev, msidesc, irq, 0);
2603 if (ret < 0) {
2604 irq_free_hwirq(irq);
2605 return ret;
2606 }
2607
2608 }
2609 return 0;
2610}
2611
2612void native_teardown_msi_irq(unsigned int irq)
2613{
2614 irq_free_hwirq(irq);
2615}
2616
2617#ifdef CONFIG_DMAR_TABLE
2618static int
2619dmar_msi_set_affinity(struct irq_data *data, const struct cpumask *mask,
2620 bool force)
2621{
2622 struct irq_cfg *cfg = data->chip_data;
2623 unsigned int dest, irq = data->irq;
2624 struct msi_msg msg;
2625 int ret;
2626
2627 ret = apic_set_affinity(data, mask, &dest);
2628 if (ret)
2629 return ret;
2630
2631 dmar_msi_read(irq, &msg);
2632
2633 msg.data &= ~MSI_DATA_VECTOR_MASK;
2634 msg.data |= MSI_DATA_VECTOR(cfg->vector);
2635 msg.address_lo &= ~MSI_ADDR_DEST_ID_MASK;
2636 msg.address_lo |= MSI_ADDR_DEST_ID(dest);
2637 msg.address_hi = MSI_ADDR_BASE_HI | MSI_ADDR_EXT_DEST_ID(dest);
2638
2639 dmar_msi_write(irq, &msg);
2640
2641 return IRQ_SET_MASK_OK_NOCOPY;
2642}
2643
2644static struct irq_chip dmar_msi_type = {
2645 .name = "DMAR_MSI",
2646 .irq_unmask = dmar_msi_unmask,
2647 .irq_mask = dmar_msi_mask,
2648 .irq_ack = apic_ack_edge,
2649 .irq_set_affinity = dmar_msi_set_affinity,
2650 .irq_retrigger = apic_retrigger_irq,
2651 .flags = IRQCHIP_SKIP_SET_WAKE,
2652};
2653
2654int arch_setup_dmar_msi(unsigned int irq)
2655{
2656 int ret;
2657 struct msi_msg msg;
2658
2659 ret = msi_compose_msg(NULL, irq, &msg, -1);
2660 if (ret < 0)
2661 return ret;
2662 dmar_msi_write(irq, &msg);
2663 irq_set_chip_and_handler_name(irq, &dmar_msi_type, handle_edge_irq,
2664 "edge");
2665 return 0;
2666}
2667#endif
2668
2669#ifdef CONFIG_HPET_TIMER
2670
2671static int hpet_msi_set_affinity(struct irq_data *data,
2672 const struct cpumask *mask, bool force)
2673{
2674 struct irq_cfg *cfg = data->chip_data;
2675 struct msi_msg msg;
2676 unsigned int dest;
2677 int ret;
2678
2679 ret = apic_set_affinity(data, mask, &dest);
2680 if (ret)
2681 return ret;
2682
2683 hpet_msi_read(data->handler_data, &msg);
2684
2685 msg.data &= ~MSI_DATA_VECTOR_MASK;
2686 msg.data |= MSI_DATA_VECTOR(cfg->vector);
2687 msg.address_lo &= ~MSI_ADDR_DEST_ID_MASK;
2688 msg.address_lo |= MSI_ADDR_DEST_ID(dest);
2689
2690 hpet_msi_write(data->handler_data, &msg);
2691
2692 return IRQ_SET_MASK_OK_NOCOPY;
2693}
2694
2695static struct irq_chip hpet_msi_type = {
2696 .name = "HPET_MSI",
2697 .irq_unmask = hpet_msi_unmask,
2698 .irq_mask = hpet_msi_mask,
2699 .irq_ack = apic_ack_edge,
2700 .irq_set_affinity = hpet_msi_set_affinity,
2701 .irq_retrigger = apic_retrigger_irq,
2702 .flags = IRQCHIP_SKIP_SET_WAKE,
2703};
2704
2705int default_setup_hpet_msi(unsigned int irq, unsigned int id)
2706{
2707 struct irq_chip *chip = &hpet_msi_type;
2708 struct msi_msg msg;
2709 int ret;
2710
2711 ret = msi_compose_msg(NULL, irq, &msg, id);
2712 if (ret < 0)
2713 return ret;
2714
2715 hpet_msi_write(irq_get_handler_data(irq), &msg);
2716 irq_set_status_flags(irq, IRQ_MOVE_PCNTXT);
2717 setup_remapped_irq(irq, irq_cfg(irq), chip);
2718
2719 irq_set_chip_and_handler_name(irq, chip, handle_edge_irq, "edge");
2720 return 0;
2721}
2722#endif
2723
2724#endif /* CONFIG_PCI_MSI */
2725/*
2726 * Hypertransport interrupt support 2454 * Hypertransport interrupt support
2727 */ 2455 */
2728#ifdef CONFIG_HT_IRQ 2456#ifdef CONFIG_HT_IRQ
diff --git a/arch/x86/kernel/apic/msi.c b/arch/x86/kernel/apic/msi.c
new file mode 100644
index 000000000000..ddb28f1dab4d
--- /dev/null
+++ b/arch/x86/kernel/apic/msi.c
@@ -0,0 +1,286 @@
1/*
2 * Support of MSI, HPET and DMAR interrupts.
3 *
4 * Copyright (C) 1997, 1998, 1999, 2000, 2009 Ingo Molnar, Hajnalka Szabo
5 * Moved from arch/x86/kernel/apic/io_apic.c.
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 */
11#include <linux/mm.h>
12#include <linux/interrupt.h>
13#include <linux/pci.h>
14#include <linux/dmar.h>
15#include <linux/hpet.h>
16#include <linux/msi.h>
17#include <asm/msidef.h>
18#include <asm/hpet.h>
19#include <asm/hw_irq.h>
20#include <asm/apic.h>
21#include <asm/irq_remapping.h>
22
23void native_compose_msi_msg(struct pci_dev *pdev,
24 unsigned int irq, unsigned int dest,
25 struct msi_msg *msg, u8 hpet_id)
26{
27 struct irq_cfg *cfg = irq_cfg(irq);
28
29 msg->address_hi = MSI_ADDR_BASE_HI;
30
31 if (x2apic_enabled())
32 msg->address_hi |= MSI_ADDR_EXT_DEST_ID(dest);
33
34 msg->address_lo =
35 MSI_ADDR_BASE_LO |
36 ((apic->irq_dest_mode == 0) ?
37 MSI_ADDR_DEST_MODE_PHYSICAL :
38 MSI_ADDR_DEST_MODE_LOGICAL) |
39 ((apic->irq_delivery_mode != dest_LowestPrio) ?
40 MSI_ADDR_REDIRECTION_CPU :
41 MSI_ADDR_REDIRECTION_LOWPRI) |
42 MSI_ADDR_DEST_ID(dest);
43
44 msg->data =
45 MSI_DATA_TRIGGER_EDGE |
46 MSI_DATA_LEVEL_ASSERT |
47 ((apic->irq_delivery_mode != dest_LowestPrio) ?
48 MSI_DATA_DELIVERY_FIXED :
49 MSI_DATA_DELIVERY_LOWPRI) |
50 MSI_DATA_VECTOR(cfg->vector);
51}
52
53static int msi_compose_msg(struct pci_dev *pdev, unsigned int irq,
54 struct msi_msg *msg, u8 hpet_id)
55{
56 struct irq_cfg *cfg;
57 int err;
58 unsigned dest;
59
60 if (disable_apic)
61 return -ENXIO;
62
63 cfg = irq_cfg(irq);
64 err = assign_irq_vector(irq, cfg, apic->target_cpus());
65 if (err)
66 return err;
67
68 err = apic->cpu_mask_to_apicid_and(cfg->domain,
69 apic->target_cpus(), &dest);
70 if (err)
71 return err;
72
73 x86_msi.compose_msi_msg(pdev, irq, dest, msg, hpet_id);
74
75 return 0;
76}
77
78static int
79msi_set_affinity(struct irq_data *data, const struct cpumask *mask, bool force)
80{
81 struct irq_cfg *cfg = data->chip_data;
82 struct msi_msg msg;
83 unsigned int dest;
84 int ret;
85
86 ret = apic_set_affinity(data, mask, &dest);
87 if (ret)
88 return ret;
89
90 __get_cached_msi_msg(data->msi_desc, &msg);
91
92 msg.data &= ~MSI_DATA_VECTOR_MASK;
93 msg.data |= MSI_DATA_VECTOR(cfg->vector);
94 msg.address_lo &= ~MSI_ADDR_DEST_ID_MASK;
95 msg.address_lo |= MSI_ADDR_DEST_ID(dest);
96
97 __pci_write_msi_msg(data->msi_desc, &msg);
98
99 return IRQ_SET_MASK_OK_NOCOPY;
100}
101
102/*
103 * IRQ Chip for MSI PCI/PCI-X/PCI-Express Devices,
104 * which implement the MSI or MSI-X Capability Structure.
105 */
106static struct irq_chip msi_chip = {
107 .name = "PCI-MSI",
108 .irq_unmask = pci_msi_unmask_irq,
109 .irq_mask = pci_msi_mask_irq,
110 .irq_ack = apic_ack_edge,
111 .irq_set_affinity = msi_set_affinity,
112 .irq_retrigger = apic_retrigger_irq,
113 .flags = IRQCHIP_SKIP_SET_WAKE,
114};
115
116int setup_msi_irq(struct pci_dev *dev, struct msi_desc *msidesc,
117 unsigned int irq_base, unsigned int irq_offset)
118{
119 struct irq_chip *chip = &msi_chip;
120 struct msi_msg msg;
121 unsigned int irq = irq_base + irq_offset;
122 int ret;
123
124 ret = msi_compose_msg(dev, irq, &msg, -1);
125 if (ret < 0)
126 return ret;
127
128 irq_set_msi_desc_off(irq_base, irq_offset, msidesc);
129
130 /*
131 * MSI-X message is written per-IRQ, the offset is always 0.
132 * MSI message denotes a contiguous group of IRQs, written for 0th IRQ.
133 */
134 if (!irq_offset)
135 pci_write_msi_msg(irq, &msg);
136
137 setup_remapped_irq(irq, irq_cfg(irq), chip);
138
139 irq_set_chip_and_handler_name(irq, chip, handle_edge_irq, "edge");
140
141 dev_dbg(&dev->dev, "irq %d for MSI/MSI-X\n", irq);
142
143 return 0;
144}
145
146int native_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
147{
148 struct msi_desc *msidesc;
149 unsigned int irq;
150 int node, ret;
151
152 /* Multiple MSI vectors only supported with interrupt remapping */
153 if (type == PCI_CAP_ID_MSI && nvec > 1)
154 return 1;
155
156 node = dev_to_node(&dev->dev);
157
158 list_for_each_entry(msidesc, &dev->msi_list, list) {
159 irq = irq_alloc_hwirq(node);
160 if (!irq)
161 return -ENOSPC;
162
163 ret = setup_msi_irq(dev, msidesc, irq, 0);
164 if (ret < 0) {
165 irq_free_hwirq(irq);
166 return ret;
167 }
168
169 }
170 return 0;
171}
172
173void native_teardown_msi_irq(unsigned int irq)
174{
175 irq_free_hwirq(irq);
176}
177
178#ifdef CONFIG_DMAR_TABLE
179static int
180dmar_msi_set_affinity(struct irq_data *data, const struct cpumask *mask,
181 bool force)
182{
183 struct irq_cfg *cfg = data->chip_data;
184 unsigned int dest, irq = data->irq;
185 struct msi_msg msg;
186 int ret;
187
188 ret = apic_set_affinity(data, mask, &dest);
189 if (ret)
190 return ret;
191
192 dmar_msi_read(irq, &msg);
193
194 msg.data &= ~MSI_DATA_VECTOR_MASK;
195 msg.data |= MSI_DATA_VECTOR(cfg->vector);
196 msg.address_lo &= ~MSI_ADDR_DEST_ID_MASK;
197 msg.address_lo |= MSI_ADDR_DEST_ID(dest);
198 msg.address_hi = MSI_ADDR_BASE_HI | MSI_ADDR_EXT_DEST_ID(dest);
199
200 dmar_msi_write(irq, &msg);
201
202 return IRQ_SET_MASK_OK_NOCOPY;
203}
204
205static struct irq_chip dmar_msi_type = {
206 .name = "DMAR_MSI",
207 .irq_unmask = dmar_msi_unmask,
208 .irq_mask = dmar_msi_mask,
209 .irq_ack = apic_ack_edge,
210 .irq_set_affinity = dmar_msi_set_affinity,
211 .irq_retrigger = apic_retrigger_irq,
212 .flags = IRQCHIP_SKIP_SET_WAKE,
213};
214
215int arch_setup_dmar_msi(unsigned int irq)
216{
217 int ret;
218 struct msi_msg msg;
219
220 ret = msi_compose_msg(NULL, irq, &msg, -1);
221 if (ret < 0)
222 return ret;
223 dmar_msi_write(irq, &msg);
224 irq_set_chip_and_handler_name(irq, &dmar_msi_type, handle_edge_irq,
225 "edge");
226 return 0;
227}
228#endif
229
230/*
231 * MSI message composition
232 */
233#ifdef CONFIG_HPET_TIMER
234
235static int hpet_msi_set_affinity(struct irq_data *data,
236 const struct cpumask *mask, bool force)
237{
238 struct irq_cfg *cfg = data->chip_data;
239 struct msi_msg msg;
240 unsigned int dest;
241 int ret;
242
243 ret = apic_set_affinity(data, mask, &dest);
244 if (ret)
245 return ret;
246
247 hpet_msi_read(data->handler_data, &msg);
248
249 msg.data &= ~MSI_DATA_VECTOR_MASK;
250 msg.data |= MSI_DATA_VECTOR(cfg->vector);
251 msg.address_lo &= ~MSI_ADDR_DEST_ID_MASK;
252 msg.address_lo |= MSI_ADDR_DEST_ID(dest);
253
254 hpet_msi_write(data->handler_data, &msg);
255
256 return IRQ_SET_MASK_OK_NOCOPY;
257}
258
259static struct irq_chip hpet_msi_type = {
260 .name = "HPET_MSI",
261 .irq_unmask = hpet_msi_unmask,
262 .irq_mask = hpet_msi_mask,
263 .irq_ack = apic_ack_edge,
264 .irq_set_affinity = hpet_msi_set_affinity,
265 .irq_retrigger = apic_retrigger_irq,
266 .flags = IRQCHIP_SKIP_SET_WAKE,
267};
268
269int default_setup_hpet_msi(unsigned int irq, unsigned int id)
270{
271 struct irq_chip *chip = &hpet_msi_type;
272 struct msi_msg msg;
273 int ret;
274
275 ret = msi_compose_msg(NULL, irq, &msg, id);
276 if (ret < 0)
277 return ret;
278
279 hpet_msi_write(irq_get_handler_data(irq), &msg);
280 irq_set_status_flags(irq, IRQ_MOVE_PCNTXT);
281 setup_remapped_irq(irq, irq_cfg(irq), chip);
282
283 irq_set_chip_and_handler_name(irq, chip, handle_edge_irq, "edge");
284 return 0;
285}
286#endif