diff options
author | Eric W. Biederman <ebiederm@xmission.com> | 2006-10-04 05:16:59 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-10-04 10:55:29 -0400 |
commit | 3b7d1921f4cdd6d6ddb7899ae7a8d413991c5cf4 (patch) | |
tree | 5f809e0c4310f60dfa6f65d54fbaf9f01e2ebff9 /drivers/pci/msi-apic.c | |
parent | 277bc33bc2479707e88b0b2ae6fe56e8e4aabe81 (diff) |
[PATCH] msi: refactor and move the msi irq_chip into the arch code
It turns out msi_ops was simply not enough to abstract the architecture
specific details of msi. So I have moved the resposibility of constructing
the struct irq_chip to the architectures, and have two architecture specific
functions arch_setup_msi_irq, and arch_teardown_msi_irq.
For simple architectures those functions can do all of the work. For
architectures with platform dependencies they can call into the appropriate
platform code.
With this msi.c is finally free of assuming you have an apic, and this
actually takes less code.
The helpers for the architecture specific code are declared in the linux/msi.h
to keep them separate from the msi functions used by drivers in linux/pci.h
Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Tony Luck <tony.luck@intel.com>
Cc: Andi Kleen <ak@suse.de>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Greg KH <greg@kroah.com>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'drivers/pci/msi-apic.c')
-rw-r--r-- | drivers/pci/msi-apic.c | 86 |
1 files changed, 64 insertions, 22 deletions
diff --git a/drivers/pci/msi-apic.c b/drivers/pci/msi-apic.c index afc0ed13aa89..822e59a1b822 100644 --- a/drivers/pci/msi-apic.c +++ b/drivers/pci/msi-apic.c | |||
@@ -4,10 +4,9 @@ | |||
4 | 4 | ||
5 | #include <linux/pci.h> | 5 | #include <linux/pci.h> |
6 | #include <linux/irq.h> | 6 | #include <linux/irq.h> |
7 | #include <linux/msi.h> | ||
7 | #include <asm/smp.h> | 8 | #include <asm/smp.h> |
8 | 9 | ||
9 | #include "msi.h" | ||
10 | |||
11 | /* | 10 | /* |
12 | * Shifts for APIC-based data | 11 | * Shifts for APIC-based data |
13 | */ | 12 | */ |
@@ -31,6 +30,7 @@ | |||
31 | * Shift/mask fields for APIC-based bus address | 30 | * Shift/mask fields for APIC-based bus address |
32 | */ | 31 | */ |
33 | 32 | ||
33 | #define MSI_TARGET_CPU_SHIFT 4 | ||
34 | #define MSI_ADDR_HEADER 0xfee00000 | 34 | #define MSI_ADDR_HEADER 0xfee00000 |
35 | 35 | ||
36 | #define MSI_ADDR_DESTID_MASK 0xfff0000f | 36 | #define MSI_ADDR_DESTID_MASK 0xfff0000f |
@@ -44,58 +44,100 @@ | |||
44 | #define MSI_ADDR_REDIRECTION_CPU (0 << MSI_ADDR_REDIRECTION_SHIFT) | 44 | #define MSI_ADDR_REDIRECTION_CPU (0 << MSI_ADDR_REDIRECTION_SHIFT) |
45 | #define MSI_ADDR_REDIRECTION_LOWPRI (1 << MSI_ADDR_REDIRECTION_SHIFT) | 45 | #define MSI_ADDR_REDIRECTION_LOWPRI (1 << MSI_ADDR_REDIRECTION_SHIFT) |
46 | 46 | ||
47 | static struct irq_chip ia64_msi_chip; | ||
47 | 48 | ||
48 | static void | 49 | #ifdef CONFIG_SMP |
49 | msi_target_apic(unsigned int irq, cpumask_t cpu_mask, struct msi_msg *msg) | 50 | static void ia64_set_msi_irq_affinity(unsigned int irq, cpumask_t cpu_mask) |
50 | { | 51 | { |
51 | u32 addr = msg->address_lo; | 52 | struct msi_msg msg; |
53 | u32 addr; | ||
54 | |||
55 | read_msi_msg(irq, &msg); | ||
52 | 56 | ||
57 | addr = msg.address_lo; | ||
53 | addr &= MSI_ADDR_DESTID_MASK; | 58 | addr &= MSI_ADDR_DESTID_MASK; |
54 | addr |= MSI_ADDR_DESTID_CPU(cpu_physical_id(first_cpu(cpu_mask))); | 59 | addr |= MSI_ADDR_DESTID_CPU(cpu_physical_id(first_cpu(cpu_mask))); |
60 | msg.address_lo = addr; | ||
55 | 61 | ||
56 | msg->address_lo = addr; | 62 | write_msi_msg(irq, &msg); |
63 | set_native_irq_info(irq, cpu_mask); | ||
57 | } | 64 | } |
65 | #endif /* CONFIG_SMP */ | ||
58 | 66 | ||
59 | static int | 67 | int ia64_setup_msi_irq(unsigned int irq, struct pci_dev *pdev) |
60 | msi_setup_apic(struct pci_dev *pdev, /* unused in generic */ | ||
61 | unsigned int irq, | ||
62 | struct msi_msg *msg) | ||
63 | { | 68 | { |
69 | struct msi_msg msg; | ||
64 | unsigned long dest_phys_id; | 70 | unsigned long dest_phys_id; |
65 | unsigned int vector; | 71 | unsigned int vector; |
66 | 72 | ||
67 | dest_phys_id = cpu_physical_id(first_cpu(cpu_online_map)); | 73 | dest_phys_id = cpu_physical_id(first_cpu(cpu_online_map)); |
68 | vector = irq; | 74 | vector = irq; |
69 | 75 | ||
70 | msg->address_hi = 0; | 76 | msg.address_hi = 0; |
71 | msg->address_lo = | 77 | msg.address_lo = |
72 | MSI_ADDR_HEADER | | 78 | MSI_ADDR_HEADER | |
73 | MSI_ADDR_DESTMODE_PHYS | | 79 | MSI_ADDR_DESTMODE_PHYS | |
74 | MSI_ADDR_REDIRECTION_CPU | | 80 | MSI_ADDR_REDIRECTION_CPU | |
75 | MSI_ADDR_DESTID_CPU(dest_phys_id); | 81 | MSI_ADDR_DESTID_CPU(dest_phys_id); |
76 | 82 | ||
77 | msg->data = | 83 | msg.data = |
78 | MSI_DATA_TRIGGER_EDGE | | 84 | MSI_DATA_TRIGGER_EDGE | |
79 | MSI_DATA_LEVEL_ASSERT | | 85 | MSI_DATA_LEVEL_ASSERT | |
80 | MSI_DATA_DELIVERY_FIXED | | 86 | MSI_DATA_DELIVERY_FIXED | |
81 | MSI_DATA_VECTOR(vector); | 87 | MSI_DATA_VECTOR(vector); |
82 | 88 | ||
89 | write_msi_msg(irq, &msg); | ||
90 | set_irq_chip_and_handler(irq, &ia64_msi_chip, handle_edge_irq); | ||
91 | |||
83 | return 0; | 92 | return 0; |
84 | } | 93 | } |
85 | 94 | ||
86 | static void | 95 | void ia64_teardown_msi_irq(unsigned int irq) |
87 | msi_teardown_apic(unsigned int irq) | ||
88 | { | 96 | { |
89 | return; /* no-op */ | 97 | return; /* no-op */ |
90 | } | 98 | } |
91 | 99 | ||
100 | static void ia64_ack_msi_irq(unsigned int irq) | ||
101 | { | ||
102 | move_native_irq(irq); | ||
103 | ia64_eoi(); | ||
104 | } | ||
105 | |||
106 | static int ia64_msi_retrigger_irq(unsigned int irq) | ||
107 | { | ||
108 | unsigned int vector = irq; | ||
109 | ia64_resend_irq(vector); | ||
110 | |||
111 | return 1; | ||
112 | } | ||
113 | |||
92 | /* | 114 | /* |
93 | * Generic ops used on most IA archs/platforms. Set with msi_register() | 115 | * Generic ops used on most IA64 platforms. |
94 | */ | 116 | */ |
95 | 117 | static struct irq_chip ia64_msi_chip = { | |
96 | struct msi_ops msi_apic_ops = { | 118 | .name = "PCI-MSI", |
97 | .needs_64bit_address = 0, | 119 | .mask = mask_msi_irq, |
98 | .setup = msi_setup_apic, | 120 | .unmask = unmask_msi_irq, |
99 | .teardown = msi_teardown_apic, | 121 | .ack = ia64_ack_msi_irq, |
100 | .target = msi_target_apic, | 122 | #ifdef CONFIG_SMP |
123 | .set_affinity = ia64_set_msi_irq_affinity, | ||
124 | #endif | ||
125 | .retrigger = ia64_msi_retrigger_irq, | ||
101 | }; | 126 | }; |
127 | |||
128 | |||
129 | int arch_setup_msi_irq(unsigned int irq, struct pci_dev *pdev) | ||
130 | { | ||
131 | if (platform_setup_msi_irq) | ||
132 | return platform_setup_msi_irq(irq, pdev); | ||
133 | |||
134 | return ia64_setup_msi_irq(irq, pdev); | ||
135 | } | ||
136 | |||
137 | void arch_teardown_msi_irq(unsigned int irq) | ||
138 | { | ||
139 | if (platform_teardown_msi_irq) | ||
140 | return platform_teardown_msi_irq(irq); | ||
141 | |||
142 | return ia64_teardown_msi_irq(irq); | ||
143 | } | ||