diff options
Diffstat (limited to 'arch/powerpc/platforms/iseries/irq.c')
-rw-r--r-- | arch/powerpc/platforms/iseries/irq.c | 110 |
1 files changed, 66 insertions, 44 deletions
diff --git a/arch/powerpc/platforms/iseries/irq.c b/arch/powerpc/platforms/iseries/irq.c index 62bbbcf5ded3..2275e64f3152 100644 --- a/arch/powerpc/platforms/iseries/irq.c +++ b/arch/powerpc/platforms/iseries/irq.c | |||
@@ -23,7 +23,6 @@ | |||
23 | * Created, December 13, 2000 by Wayne Holm | 23 | * Created, December 13, 2000 by Wayne Holm |
24 | * End Change Activity | 24 | * End Change Activity |
25 | */ | 25 | */ |
26 | #include <linux/config.h> | ||
27 | #include <linux/pci.h> | 26 | #include <linux/pci.h> |
28 | #include <linux/init.h> | 27 | #include <linux/init.h> |
29 | #include <linux/threads.h> | 28 | #include <linux/threads.h> |
@@ -163,27 +162,6 @@ static void pci_event_handler(struct HvLpEvent *event, struct pt_regs *regs) | |||
163 | printk(KERN_ERR "pci_event_handler: NULL event received\n"); | 162 | printk(KERN_ERR "pci_event_handler: NULL event received\n"); |
164 | } | 163 | } |
165 | 164 | ||
166 | /* | ||
167 | * This is called by init_IRQ. set in ppc_md.init_IRQ by iSeries_setup.c | ||
168 | * It must be called before the bus walk. | ||
169 | */ | ||
170 | void __init iSeries_init_IRQ(void) | ||
171 | { | ||
172 | /* Register PCI event handler and open an event path */ | ||
173 | int ret; | ||
174 | |||
175 | ret = HvLpEvent_registerHandler(HvLpEvent_Type_PciIo, | ||
176 | &pci_event_handler); | ||
177 | if (ret == 0) { | ||
178 | ret = HvLpEvent_openPath(HvLpEvent_Type_PciIo, 0); | ||
179 | if (ret != 0) | ||
180 | printk(KERN_ERR "iseries_init_IRQ: open event path " | ||
181 | "failed with rc 0x%x\n", ret); | ||
182 | } else | ||
183 | printk(KERN_ERR "iseries_init_IRQ: register handler " | ||
184 | "failed with rc 0x%x\n", ret); | ||
185 | } | ||
186 | |||
187 | #define REAL_IRQ_TO_SUBBUS(irq) (((irq) >> 14) & 0xff) | 165 | #define REAL_IRQ_TO_SUBBUS(irq) (((irq) >> 14) & 0xff) |
188 | #define REAL_IRQ_TO_BUS(irq) ((((irq) >> 6) & 0xff) + 1) | 166 | #define REAL_IRQ_TO_BUS(irq) ((((irq) >> 6) & 0xff) + 1) |
189 | #define REAL_IRQ_TO_IDSEL(irq) ((((irq) >> 3) & 7) + 1) | 167 | #define REAL_IRQ_TO_IDSEL(irq) ((((irq) >> 3) & 7) + 1) |
@@ -197,7 +175,7 @@ static void iseries_enable_IRQ(unsigned int irq) | |||
197 | { | 175 | { |
198 | u32 bus, dev_id, function, mask; | 176 | u32 bus, dev_id, function, mask; |
199 | const u32 sub_bus = 0; | 177 | const u32 sub_bus = 0; |
200 | unsigned int rirq = virt_irq_to_real_map[irq]; | 178 | unsigned int rirq = (unsigned int)irq_map[irq].hwirq; |
201 | 179 | ||
202 | /* The IRQ has already been locked by the caller */ | 180 | /* The IRQ has already been locked by the caller */ |
203 | bus = REAL_IRQ_TO_BUS(rirq); | 181 | bus = REAL_IRQ_TO_BUS(rirq); |
@@ -214,7 +192,7 @@ static unsigned int iseries_startup_IRQ(unsigned int irq) | |||
214 | { | 192 | { |
215 | u32 bus, dev_id, function, mask; | 193 | u32 bus, dev_id, function, mask; |
216 | const u32 sub_bus = 0; | 194 | const u32 sub_bus = 0; |
217 | unsigned int rirq = virt_irq_to_real_map[irq]; | 195 | unsigned int rirq = (unsigned int)irq_map[irq].hwirq; |
218 | 196 | ||
219 | bus = REAL_IRQ_TO_BUS(rirq); | 197 | bus = REAL_IRQ_TO_BUS(rirq); |
220 | function = REAL_IRQ_TO_FUNC(rirq); | 198 | function = REAL_IRQ_TO_FUNC(rirq); |
@@ -242,9 +220,9 @@ void __init iSeries_activate_IRQs() | |||
242 | for_each_irq (irq) { | 220 | for_each_irq (irq) { |
243 | irq_desc_t *desc = get_irq_desc(irq); | 221 | irq_desc_t *desc = get_irq_desc(irq); |
244 | 222 | ||
245 | if (desc && desc->handler && desc->handler->startup) { | 223 | if (desc && desc->chip && desc->chip->startup) { |
246 | spin_lock_irqsave(&desc->lock, flags); | 224 | spin_lock_irqsave(&desc->lock, flags); |
247 | desc->handler->startup(irq); | 225 | desc->chip->startup(irq); |
248 | spin_unlock_irqrestore(&desc->lock, flags); | 226 | spin_unlock_irqrestore(&desc->lock, flags); |
249 | } | 227 | } |
250 | } | 228 | } |
@@ -255,7 +233,7 @@ static void iseries_shutdown_IRQ(unsigned int irq) | |||
255 | { | 233 | { |
256 | u32 bus, dev_id, function, mask; | 234 | u32 bus, dev_id, function, mask; |
257 | const u32 sub_bus = 0; | 235 | const u32 sub_bus = 0; |
258 | unsigned int rirq = virt_irq_to_real_map[irq]; | 236 | unsigned int rirq = (unsigned int)irq_map[irq].hwirq; |
259 | 237 | ||
260 | /* irq should be locked by the caller */ | 238 | /* irq should be locked by the caller */ |
261 | bus = REAL_IRQ_TO_BUS(rirq); | 239 | bus = REAL_IRQ_TO_BUS(rirq); |
@@ -278,7 +256,7 @@ static void iseries_disable_IRQ(unsigned int irq) | |||
278 | { | 256 | { |
279 | u32 bus, dev_id, function, mask; | 257 | u32 bus, dev_id, function, mask; |
280 | const u32 sub_bus = 0; | 258 | const u32 sub_bus = 0; |
281 | unsigned int rirq = virt_irq_to_real_map[irq]; | 259 | unsigned int rirq = (unsigned int)irq_map[irq].hwirq; |
282 | 260 | ||
283 | /* The IRQ has already been locked by the caller */ | 261 | /* The IRQ has already been locked by the caller */ |
284 | bus = REAL_IRQ_TO_BUS(rirq); | 262 | bus = REAL_IRQ_TO_BUS(rirq); |
@@ -292,19 +270,19 @@ static void iseries_disable_IRQ(unsigned int irq) | |||
292 | 270 | ||
293 | static void iseries_end_IRQ(unsigned int irq) | 271 | static void iseries_end_IRQ(unsigned int irq) |
294 | { | 272 | { |
295 | unsigned int rirq = virt_irq_to_real_map[irq]; | 273 | unsigned int rirq = (unsigned int)irq_map[irq].hwirq; |
296 | 274 | ||
297 | HvCallPci_eoi(REAL_IRQ_TO_BUS(rirq), REAL_IRQ_TO_SUBBUS(rirq), | 275 | HvCallPci_eoi(REAL_IRQ_TO_BUS(rirq), REAL_IRQ_TO_SUBBUS(rirq), |
298 | (REAL_IRQ_TO_IDSEL(rirq) << 4) + REAL_IRQ_TO_FUNC(rirq)); | 276 | (REAL_IRQ_TO_IDSEL(rirq) << 4) + REAL_IRQ_TO_FUNC(rirq)); |
299 | } | 277 | } |
300 | 278 | ||
301 | static hw_irq_controller iSeries_IRQ_handler = { | 279 | static struct irq_chip iseries_pic = { |
302 | .typename = "iSeries irq controller", | 280 | .typename = "iSeries irq controller", |
303 | .startup = iseries_startup_IRQ, | 281 | .startup = iseries_startup_IRQ, |
304 | .shutdown = iseries_shutdown_IRQ, | 282 | .shutdown = iseries_shutdown_IRQ, |
305 | .enable = iseries_enable_IRQ, | 283 | .unmask = iseries_enable_IRQ, |
306 | .disable = iseries_disable_IRQ, | 284 | .mask = iseries_disable_IRQ, |
307 | .end = iseries_end_IRQ | 285 | .eoi = iseries_end_IRQ |
308 | }; | 286 | }; |
309 | 287 | ||
310 | /* | 288 | /* |
@@ -315,17 +293,14 @@ static hw_irq_controller iSeries_IRQ_handler = { | |||
315 | int __init iSeries_allocate_IRQ(HvBusNumber bus, | 293 | int __init iSeries_allocate_IRQ(HvBusNumber bus, |
316 | HvSubBusNumber sub_bus, u32 bsubbus) | 294 | HvSubBusNumber sub_bus, u32 bsubbus) |
317 | { | 295 | { |
318 | int virtirq; | ||
319 | unsigned int realirq; | 296 | unsigned int realirq; |
320 | u8 idsel = ISERIES_GET_DEVICE_FROM_SUBBUS(bsubbus); | 297 | u8 idsel = ISERIES_GET_DEVICE_FROM_SUBBUS(bsubbus); |
321 | u8 function = ISERIES_GET_FUNCTION_FROM_SUBBUS(bsubbus); | 298 | u8 function = ISERIES_GET_FUNCTION_FROM_SUBBUS(bsubbus); |
322 | 299 | ||
323 | realirq = (((((sub_bus << 8) + (bus - 1)) << 3) + (idsel - 1)) << 3) | 300 | realirq = (((((sub_bus << 8) + (bus - 1)) << 3) + (idsel - 1)) << 3) |
324 | + function; | 301 | + function; |
325 | virtirq = virt_irq_create_mapping(realirq); | ||
326 | 302 | ||
327 | irq_desc[virtirq].handler = &iSeries_IRQ_handler; | 303 | return irq_create_mapping(NULL, realirq, IRQ_TYPE_NONE); |
328 | return virtirq; | ||
329 | } | 304 | } |
330 | 305 | ||
331 | #endif /* CONFIG_PCI */ | 306 | #endif /* CONFIG_PCI */ |
@@ -333,10 +308,9 @@ int __init iSeries_allocate_IRQ(HvBusNumber bus, | |||
333 | /* | 308 | /* |
334 | * Get the next pending IRQ. | 309 | * Get the next pending IRQ. |
335 | */ | 310 | */ |
336 | int iSeries_get_irq(struct pt_regs *regs) | 311 | unsigned int iSeries_get_irq(struct pt_regs *regs) |
337 | { | 312 | { |
338 | /* -2 means ignore this interrupt */ | 313 | int irq = NO_IRQ_IGNORE; |
339 | int irq = -2; | ||
340 | 314 | ||
341 | #ifdef CONFIG_SMP | 315 | #ifdef CONFIG_SMP |
342 | if (get_lppaca()->int_dword.fields.ipi_cnt) { | 316 | if (get_lppaca()->int_dword.fields.ipi_cnt) { |
@@ -359,9 +333,57 @@ int iSeries_get_irq(struct pt_regs *regs) | |||
359 | } | 333 | } |
360 | spin_unlock(&pending_irqs_lock); | 334 | spin_unlock(&pending_irqs_lock); |
361 | if (irq >= NR_IRQS) | 335 | if (irq >= NR_IRQS) |
362 | irq = -2; | 336 | irq = NO_IRQ_IGNORE; |
363 | } | 337 | } |
364 | #endif | 338 | #endif |
365 | 339 | ||
366 | return irq; | 340 | return irq; |
367 | } | 341 | } |
342 | |||
343 | static int iseries_irq_host_map(struct irq_host *h, unsigned int virq, | ||
344 | irq_hw_number_t hw, unsigned int flags) | ||
345 | { | ||
346 | set_irq_chip_and_handler(virq, &iseries_pic, handle_fasteoi_irq); | ||
347 | |||
348 | return 0; | ||
349 | } | ||
350 | |||
351 | static struct irq_host_ops iseries_irq_host_ops = { | ||
352 | .map = iseries_irq_host_map, | ||
353 | }; | ||
354 | |||
355 | /* | ||
356 | * This is called by init_IRQ. set in ppc_md.init_IRQ by iSeries_setup.c | ||
357 | * It must be called before the bus walk. | ||
358 | */ | ||
359 | void __init iSeries_init_IRQ(void) | ||
360 | { | ||
361 | /* Register PCI event handler and open an event path */ | ||
362 | struct irq_host *host; | ||
363 | int ret; | ||
364 | |||
365 | /* | ||
366 | * The Hypervisor only allows us up to 256 interrupt | ||
367 | * sources (the irq number is passed in a u8). | ||
368 | */ | ||
369 | irq_set_virq_count(256); | ||
370 | |||
371 | /* Create irq host. No need for a revmap since HV will give us | ||
372 | * back our virtual irq number | ||
373 | */ | ||
374 | host = irq_alloc_host(IRQ_HOST_MAP_NOMAP, 0, &iseries_irq_host_ops, 0); | ||
375 | BUG_ON(host == NULL); | ||
376 | irq_set_default_host(host); | ||
377 | |||
378 | ret = HvLpEvent_registerHandler(HvLpEvent_Type_PciIo, | ||
379 | &pci_event_handler); | ||
380 | if (ret == 0) { | ||
381 | ret = HvLpEvent_openPath(HvLpEvent_Type_PciIo, 0); | ||
382 | if (ret != 0) | ||
383 | printk(KERN_ERR "iseries_init_IRQ: open event path " | ||
384 | "failed with rc 0x%x\n", ret); | ||
385 | } else | ||
386 | printk(KERN_ERR "iseries_init_IRQ: register handler " | ||
387 | "failed with rc 0x%x\n", ret); | ||
388 | } | ||
389 | |||