diff options
| author | Thomas Gleixner <tglx@linutronix.de> | 2011-03-23 17:08:44 -0400 |
|---|---|---|
| committer | Ralf Baechle <ralf@linux-mips.org> | 2011-03-25 13:45:14 -0400 |
| commit | d24c1a26ca952264d92ccf6acafe38912e05b1f8 (patch) | |
| tree | 648268263206986a80355b2a0b2b6e1013dcee50 /arch | |
| parent | 786a5e02802a02c6e0bd132f4fc188a5854ab41f (diff) | |
MIPS: Alchemy: Convert to new irq chip functions
Fix the deadlock in set_type() while at it:
The code called set_irq_chip_and_handler_name() resp. set_irq_chip()
from the set_type() callback. That only works on UP and lock debugging
disabled. Otherwise it would dead lock on desc->lock.
__irq_set_chip_handler_name_locked() avoids that.
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
To: linux-mips@linux-mips.org
Patchwork: https://patchwork.linux-mips.org/patch/2173/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'arch')
| -rw-r--r-- | arch/mips/alchemy/common/irq.c | 98 | ||||
| -rw-r--r-- | arch/mips/alchemy/devboards/bcsr.c | 18 |
2 files changed, 59 insertions, 57 deletions
diff --git a/arch/mips/alchemy/common/irq.c b/arch/mips/alchemy/common/irq.c index 9f78ada83b3c..55dd7c888517 100644 --- a/arch/mips/alchemy/common/irq.c +++ b/arch/mips/alchemy/common/irq.c | |||
| @@ -39,7 +39,7 @@ | |||
| 39 | #include <asm/mach-pb1x00/pb1000.h> | 39 | #include <asm/mach-pb1x00/pb1000.h> |
| 40 | #endif | 40 | #endif |
| 41 | 41 | ||
| 42 | static int au1x_ic_settype(unsigned int irq, unsigned int flow_type); | 42 | static int au1x_ic_settype(struct irq_data *d, unsigned int flow_type); |
| 43 | 43 | ||
| 44 | /* NOTE on interrupt priorities: The original writers of this code said: | 44 | /* NOTE on interrupt priorities: The original writers of this code said: |
| 45 | * | 45 | * |
| @@ -218,17 +218,17 @@ struct au1xxx_irqmap au1200_irqmap[] __initdata = { | |||
| 218 | }; | 218 | }; |
| 219 | 219 | ||
| 220 | 220 | ||
| 221 | static void au1x_ic0_unmask(unsigned int irq_nr) | 221 | static void au1x_ic0_unmask(struct irq_data *d) |
| 222 | { | 222 | { |
| 223 | unsigned int bit = irq_nr - AU1000_INTC0_INT_BASE; | 223 | unsigned int bit = d->irq - AU1000_INTC0_INT_BASE; |
| 224 | au_writel(1 << bit, IC0_MASKSET); | 224 | au_writel(1 << bit, IC0_MASKSET); |
| 225 | au_writel(1 << bit, IC0_WAKESET); | 225 | au_writel(1 << bit, IC0_WAKESET); |
| 226 | au_sync(); | 226 | au_sync(); |
| 227 | } | 227 | } |
| 228 | 228 | ||
| 229 | static void au1x_ic1_unmask(unsigned int irq_nr) | 229 | static void au1x_ic1_unmask(struct irq_data *d) |
| 230 | { | 230 | { |
| 231 | unsigned int bit = irq_nr - AU1000_INTC1_INT_BASE; | 231 | unsigned int bit = d->irq - AU1000_INTC1_INT_BASE; |
| 232 | au_writel(1 << bit, IC1_MASKSET); | 232 | au_writel(1 << bit, IC1_MASKSET); |
| 233 | au_writel(1 << bit, IC1_WAKESET); | 233 | au_writel(1 << bit, IC1_WAKESET); |
| 234 | 234 | ||
| @@ -236,31 +236,31 @@ static void au1x_ic1_unmask(unsigned int irq_nr) | |||
| 236 | * nowhere in the current kernel sources is it disabled. --mlau | 236 | * nowhere in the current kernel sources is it disabled. --mlau |
| 237 | */ | 237 | */ |
| 238 | #if defined(CONFIG_MIPS_PB1000) | 238 | #if defined(CONFIG_MIPS_PB1000) |
| 239 | if (irq_nr == AU1000_GPIO15_INT) | 239 | if (d->irq == AU1000_GPIO15_INT) |
| 240 | au_writel(0x4000, PB1000_MDR); /* enable int */ | 240 | au_writel(0x4000, PB1000_MDR); /* enable int */ |
| 241 | #endif | 241 | #endif |
| 242 | au_sync(); | 242 | au_sync(); |
| 243 | } | 243 | } |
| 244 | 244 | ||
| 245 | static void au1x_ic0_mask(unsigned int irq_nr) | 245 | static void au1x_ic0_mask(struct irq_data *d) |
| 246 | { | 246 | { |
| 247 | unsigned int bit = irq_nr - AU1000_INTC0_INT_BASE; | 247 | unsigned int bit = d->irq - AU1000_INTC0_INT_BASE; |
| 248 | au_writel(1 << bit, IC0_MASKCLR); | 248 | au_writel(1 << bit, IC0_MASKCLR); |
| 249 | au_writel(1 << bit, IC0_WAKECLR); | 249 | au_writel(1 << bit, IC0_WAKECLR); |
| 250 | au_sync(); | 250 | au_sync(); |
| 251 | } | 251 | } |
| 252 | 252 | ||
| 253 | static void au1x_ic1_mask(unsigned int irq_nr) | 253 | static void au1x_ic1_mask(struct irq_data *d) |
| 254 | { | 254 | { |
| 255 | unsigned int bit = irq_nr - AU1000_INTC1_INT_BASE; | 255 | unsigned int bit = d->irq - AU1000_INTC1_INT_BASE; |
| 256 | au_writel(1 << bit, IC1_MASKCLR); | 256 | au_writel(1 << bit, IC1_MASKCLR); |
| 257 | au_writel(1 << bit, IC1_WAKECLR); | 257 | au_writel(1 << bit, IC1_WAKECLR); |
| 258 | au_sync(); | 258 | au_sync(); |
| 259 | } | 259 | } |
| 260 | 260 | ||
| 261 | static void au1x_ic0_ack(unsigned int irq_nr) | 261 | static void au1x_ic0_ack(struct irq_data *d) |
| 262 | { | 262 | { |
| 263 | unsigned int bit = irq_nr - AU1000_INTC0_INT_BASE; | 263 | unsigned int bit = d->irq - AU1000_INTC0_INT_BASE; |
| 264 | 264 | ||
| 265 | /* | 265 | /* |
| 266 | * This may assume that we don't get interrupts from | 266 | * This may assume that we don't get interrupts from |
| @@ -271,9 +271,9 @@ static void au1x_ic0_ack(unsigned int irq_nr) | |||
| 271 | au_sync(); | 271 | au_sync(); |
| 272 | } | 272 | } |
| 273 | 273 | ||
| 274 | static void au1x_ic1_ack(unsigned int irq_nr) | 274 | static void au1x_ic1_ack(struct irq_data *d) |
| 275 | { | 275 | { |
| 276 | unsigned int bit = irq_nr - AU1000_INTC1_INT_BASE; | 276 | unsigned int bit = d->irq - AU1000_INTC1_INT_BASE; |
| 277 | 277 | ||
| 278 | /* | 278 | /* |
| 279 | * This may assume that we don't get interrupts from | 279 | * This may assume that we don't get interrupts from |
| @@ -284,9 +284,9 @@ static void au1x_ic1_ack(unsigned int irq_nr) | |||
| 284 | au_sync(); | 284 | au_sync(); |
| 285 | } | 285 | } |
| 286 | 286 | ||
| 287 | static void au1x_ic0_maskack(unsigned int irq_nr) | 287 | static void au1x_ic0_maskack(struct irq_data *d) |
| 288 | { | 288 | { |
| 289 | unsigned int bit = irq_nr - AU1000_INTC0_INT_BASE; | 289 | unsigned int bit = d->irq - AU1000_INTC0_INT_BASE; |
| 290 | 290 | ||
| 291 | au_writel(1 << bit, IC0_WAKECLR); | 291 | au_writel(1 << bit, IC0_WAKECLR); |
| 292 | au_writel(1 << bit, IC0_MASKCLR); | 292 | au_writel(1 << bit, IC0_MASKCLR); |
| @@ -295,9 +295,9 @@ static void au1x_ic0_maskack(unsigned int irq_nr) | |||
| 295 | au_sync(); | 295 | au_sync(); |
| 296 | } | 296 | } |
| 297 | 297 | ||
| 298 | static void au1x_ic1_maskack(unsigned int irq_nr) | 298 | static void au1x_ic1_maskack(struct irq_data *d) |
| 299 | { | 299 | { |
| 300 | unsigned int bit = irq_nr - AU1000_INTC1_INT_BASE; | 300 | unsigned int bit = d->irq - AU1000_INTC1_INT_BASE; |
| 301 | 301 | ||
| 302 | au_writel(1 << bit, IC1_WAKECLR); | 302 | au_writel(1 << bit, IC1_WAKECLR); |
| 303 | au_writel(1 << bit, IC1_MASKCLR); | 303 | au_writel(1 << bit, IC1_MASKCLR); |
| @@ -306,9 +306,9 @@ static void au1x_ic1_maskack(unsigned int irq_nr) | |||
| 306 | au_sync(); | 306 | au_sync(); |
| 307 | } | 307 | } |
| 308 | 308 | ||
| 309 | static int au1x_ic1_setwake(unsigned int irq, unsigned int on) | 309 | static int au1x_ic1_setwake(struct irq_data *d, unsigned int on) |
| 310 | { | 310 | { |
| 311 | int bit = irq - AU1000_INTC1_INT_BASE; | 311 | int bit = d->irq - AU1000_INTC1_INT_BASE; |
| 312 | unsigned long wakemsk, flags; | 312 | unsigned long wakemsk, flags; |
| 313 | 313 | ||
| 314 | /* only GPIO 0-7 can act as wakeup source. Fortunately these | 314 | /* only GPIO 0-7 can act as wakeup source. Fortunately these |
| @@ -336,28 +336,30 @@ static int au1x_ic1_setwake(unsigned int irq, unsigned int on) | |||
| 336 | */ | 336 | */ |
| 337 | static struct irq_chip au1x_ic0_chip = { | 337 | static struct irq_chip au1x_ic0_chip = { |
| 338 | .name = "Alchemy-IC0", | 338 | .name = "Alchemy-IC0", |
| 339 | .ack = au1x_ic0_ack, | 339 | .irq_ack = au1x_ic0_ack, |
| 340 | .mask = au1x_ic0_mask, | 340 | .irq_mask = au1x_ic0_mask, |
| 341 | .mask_ack = au1x_ic0_maskack, | 341 | .irq_mask_ack = au1x_ic0_maskack, |
| 342 | .unmask = au1x_ic0_unmask, | 342 | .irq_unmask = au1x_ic0_unmask, |
| 343 | .set_type = au1x_ic_settype, | 343 | .irq_set_type = au1x_ic_settype, |
| 344 | }; | 344 | }; |
| 345 | 345 | ||
| 346 | static struct irq_chip au1x_ic1_chip = { | 346 | static struct irq_chip au1x_ic1_chip = { |
| 347 | .name = "Alchemy-IC1", | 347 | .name = "Alchemy-IC1", |
| 348 | .ack = au1x_ic1_ack, | 348 | .irq_ack = au1x_ic1_ack, |
| 349 | .mask = au1x_ic1_mask, | 349 | .irq_mask = au1x_ic1_mask, |
| 350 | .mask_ack = au1x_ic1_maskack, | 350 | .irq_mask_ack = au1x_ic1_maskack, |
| 351 | .unmask = au1x_ic1_unmask, | 351 | .irq_unmask = au1x_ic1_unmask, |
| 352 | .set_type = au1x_ic_settype, | 352 | .irq_set_type = au1x_ic_settype, |
| 353 | .set_wake = au1x_ic1_setwake, | 353 | .irq_set_wake = au1x_ic1_setwake, |
| 354 | }; | 354 | }; |
| 355 | 355 | ||
| 356 | static int au1x_ic_settype(unsigned int irq, unsigned int flow_type) | 356 | static int au1x_ic_settype(struct irq_data *d, unsigned int flow_type) |
| 357 | { | 357 | { |
| 358 | struct irq_chip *chip; | 358 | struct irq_chip *chip; |
| 359 | unsigned long icr[6]; | 359 | unsigned long icr[6]; |
| 360 | unsigned int bit, ic; | 360 | unsigned int bit, ic, irq = d->irq; |
| 361 | irq_flow_handler_t handler = NULL; | ||
| 362 | unsigned char *name = NULL; | ||
| 361 | int ret; | 363 | int ret; |
| 362 | 364 | ||
| 363 | if (irq >= AU1000_INTC1_INT_BASE) { | 365 | if (irq >= AU1000_INTC1_INT_BASE) { |
| @@ -387,47 +389,47 @@ static int au1x_ic_settype(unsigned int irq, unsigned int flow_type) | |||
| 387 | au_writel(1 << bit, icr[5]); | 389 | au_writel(1 << bit, icr[5]); |
| 388 | au_writel(1 << bit, icr[4]); | 390 | au_writel(1 << bit, icr[4]); |
| 389 | au_writel(1 << bit, icr[0]); | 391 | au_writel(1 << bit, icr[0]); |
| 390 | set_irq_chip_and_handler_name(irq, chip, | 392 | handler = handle_edge_irq; |
| 391 | handle_edge_irq, "riseedge"); | 393 | name = "riseedge"; |
| 392 | break; | 394 | break; |
| 393 | case IRQ_TYPE_EDGE_FALLING: /* 0:1:0 */ | 395 | case IRQ_TYPE_EDGE_FALLING: /* 0:1:0 */ |
| 394 | au_writel(1 << bit, icr[5]); | 396 | au_writel(1 << bit, icr[5]); |
| 395 | au_writel(1 << bit, icr[1]); | 397 | au_writel(1 << bit, icr[1]); |
| 396 | au_writel(1 << bit, icr[3]); | 398 | au_writel(1 << bit, icr[3]); |
| 397 | set_irq_chip_and_handler_name(irq, chip, | 399 | handler = handle_edge_irq; |
| 398 | handle_edge_irq, "falledge"); | 400 | name = "falledge"; |
| 399 | break; | 401 | break; |
| 400 | case IRQ_TYPE_EDGE_BOTH: /* 0:1:1 */ | 402 | case IRQ_TYPE_EDGE_BOTH: /* 0:1:1 */ |
| 401 | au_writel(1 << bit, icr[5]); | 403 | au_writel(1 << bit, icr[5]); |
| 402 | au_writel(1 << bit, icr[1]); | 404 | au_writel(1 << bit, icr[1]); |
| 403 | au_writel(1 << bit, icr[0]); | 405 | au_writel(1 << bit, icr[0]); |
| 404 | set_irq_chip_and_handler_name(irq, chip, | 406 | handler = handle_edge_irq; |
| 405 | handle_edge_irq, "bothedge"); | 407 | name = "bothedge"; |
| 406 | break; | 408 | break; |
| 407 | case IRQ_TYPE_LEVEL_HIGH: /* 1:0:1 */ | 409 | case IRQ_TYPE_LEVEL_HIGH: /* 1:0:1 */ |
| 408 | au_writel(1 << bit, icr[2]); | 410 | au_writel(1 << bit, icr[2]); |
| 409 | au_writel(1 << bit, icr[4]); | 411 | au_writel(1 << bit, icr[4]); |
| 410 | au_writel(1 << bit, icr[0]); | 412 | au_writel(1 << bit, icr[0]); |
| 411 | set_irq_chip_and_handler_name(irq, chip, | 413 | handler = handle_level_irq; |
| 412 | handle_level_irq, "hilevel"); | 414 | name = "hilevel"; |
| 413 | break; | 415 | break; |
| 414 | case IRQ_TYPE_LEVEL_LOW: /* 1:1:0 */ | 416 | case IRQ_TYPE_LEVEL_LOW: /* 1:1:0 */ |
| 415 | au_writel(1 << bit, icr[2]); | 417 | au_writel(1 << bit, icr[2]); |
| 416 | au_writel(1 << bit, icr[1]); | 418 | au_writel(1 << bit, icr[1]); |
| 417 | au_writel(1 << bit, icr[3]); | 419 | au_writel(1 << bit, icr[3]); |
| 418 | set_irq_chip_and_handler_name(irq, chip, | 420 | handler = handle_level_irq; |
| 419 | handle_level_irq, "lowlevel"); | 421 | name = "lowlevel"; |
| 420 | break; | 422 | break; |
| 421 | case IRQ_TYPE_NONE: /* 0:0:0 */ | 423 | case IRQ_TYPE_NONE: /* 0:0:0 */ |
| 422 | au_writel(1 << bit, icr[5]); | 424 | au_writel(1 << bit, icr[5]); |
| 423 | au_writel(1 << bit, icr[4]); | 425 | au_writel(1 << bit, icr[4]); |
| 424 | au_writel(1 << bit, icr[3]); | 426 | au_writel(1 << bit, icr[3]); |
| 425 | /* set at least chip so we can call set_irq_type() on it */ | ||
| 426 | set_irq_chip(irq, chip); | ||
| 427 | break; | 427 | break; |
| 428 | default: | 428 | default: |
| 429 | ret = -EINVAL; | 429 | ret = -EINVAL; |
| 430 | } | 430 | } |
| 431 | __irq_set_chip_handler_name_locked(d->irq, chip, handler, name); | ||
| 432 | |||
| 431 | au_sync(); | 433 | au_sync(); |
| 432 | 434 | ||
| 433 | return ret; | 435 | return ret; |
| @@ -504,11 +506,11 @@ static void __init au1000_init_irq(struct au1xxx_irqmap *map) | |||
| 504 | */ | 506 | */ |
| 505 | for (i = AU1000_INTC0_INT_BASE; | 507 | for (i = AU1000_INTC0_INT_BASE; |
| 506 | (i < AU1000_INTC0_INT_BASE + 32); i++) | 508 | (i < AU1000_INTC0_INT_BASE + 32); i++) |
| 507 | au1x_ic_settype(i, IRQ_TYPE_NONE); | 509 | au1x_ic_settype(irq_get_irq_data(i), IRQ_TYPE_NONE); |
| 508 | 510 | ||
| 509 | for (i = AU1000_INTC1_INT_BASE; | 511 | for (i = AU1000_INTC1_INT_BASE; |
| 510 | (i < AU1000_INTC1_INT_BASE + 32); i++) | 512 | (i < AU1000_INTC1_INT_BASE + 32); i++) |
| 511 | au1x_ic_settype(i, IRQ_TYPE_NONE); | 513 | au1x_ic_settype(irq_get_irq_data(i), IRQ_TYPE_NONE); |
| 512 | 514 | ||
| 513 | /* | 515 | /* |
| 514 | * Initialize IC0, which is fixed per processor. | 516 | * Initialize IC0, which is fixed per processor. |
| @@ -526,7 +528,7 @@ static void __init au1000_init_irq(struct au1xxx_irqmap *map) | |||
| 526 | au_writel(1 << bit, IC0_ASSIGNSET); | 528 | au_writel(1 << bit, IC0_ASSIGNSET); |
| 527 | } | 529 | } |
| 528 | 530 | ||
| 529 | au1x_ic_settype(irq_nr, map->im_type); | 531 | au1x_ic_settype(irq_get_irq_data(irq_nr), map->im_type); |
| 530 | ++map; | 532 | ++map; |
| 531 | } | 533 | } |
| 532 | 534 | ||
diff --git a/arch/mips/alchemy/devboards/bcsr.c b/arch/mips/alchemy/devboards/bcsr.c index c52af8821da0..f91c43a7d5dc 100644 --- a/arch/mips/alchemy/devboards/bcsr.c +++ b/arch/mips/alchemy/devboards/bcsr.c | |||
| @@ -97,26 +97,26 @@ static void bcsr_csc_handler(unsigned int irq, struct irq_desc *d) | |||
| 97 | * CPLD generates tons of spurious interrupts (at least on my DB1200). | 97 | * CPLD generates tons of spurious interrupts (at least on my DB1200). |
| 98 | * -- mlau | 98 | * -- mlau |
| 99 | */ | 99 | */ |
| 100 | static void bcsr_irq_mask(unsigned int irq_nr) | 100 | static void bcsr_irq_mask(struct irq_data *d) |
| 101 | { | 101 | { |
| 102 | unsigned short v = 1 << (irq_nr - bcsr_csc_base); | 102 | unsigned short v = 1 << (d->irq - bcsr_csc_base); |
| 103 | __raw_writew(v, bcsr_virt + BCSR_REG_INTCLR); | 103 | __raw_writew(v, bcsr_virt + BCSR_REG_INTCLR); |
| 104 | __raw_writew(v, bcsr_virt + BCSR_REG_MASKCLR); | 104 | __raw_writew(v, bcsr_virt + BCSR_REG_MASKCLR); |
| 105 | wmb(); | 105 | wmb(); |
| 106 | } | 106 | } |
| 107 | 107 | ||
| 108 | static void bcsr_irq_maskack(unsigned int irq_nr) | 108 | static void bcsr_irq_maskack(struct irq_data *d) |
| 109 | { | 109 | { |
| 110 | unsigned short v = 1 << (irq_nr - bcsr_csc_base); | 110 | unsigned short v = 1 << (d->irq - bcsr_csc_base); |
| 111 | __raw_writew(v, bcsr_virt + BCSR_REG_INTCLR); | 111 | __raw_writew(v, bcsr_virt + BCSR_REG_INTCLR); |
| 112 | __raw_writew(v, bcsr_virt + BCSR_REG_MASKCLR); | 112 | __raw_writew(v, bcsr_virt + BCSR_REG_MASKCLR); |
| 113 | __raw_writew(v, bcsr_virt + BCSR_REG_INTSTAT); /* ack */ | 113 | __raw_writew(v, bcsr_virt + BCSR_REG_INTSTAT); /* ack */ |
| 114 | wmb(); | 114 | wmb(); |
| 115 | } | 115 | } |
| 116 | 116 | ||
| 117 | static void bcsr_irq_unmask(unsigned int irq_nr) | 117 | static void bcsr_irq_unmask(struct irq_data *d) |
| 118 | { | 118 | { |
| 119 | unsigned short v = 1 << (irq_nr - bcsr_csc_base); | 119 | unsigned short v = 1 << (d->irq - bcsr_csc_base); |
| 120 | __raw_writew(v, bcsr_virt + BCSR_REG_INTSET); | 120 | __raw_writew(v, bcsr_virt + BCSR_REG_INTSET); |
| 121 | __raw_writew(v, bcsr_virt + BCSR_REG_MASKSET); | 121 | __raw_writew(v, bcsr_virt + BCSR_REG_MASKSET); |
| 122 | wmb(); | 122 | wmb(); |
| @@ -124,9 +124,9 @@ static void bcsr_irq_unmask(unsigned int irq_nr) | |||
| 124 | 124 | ||
| 125 | static struct irq_chip bcsr_irq_type = { | 125 | static struct irq_chip bcsr_irq_type = { |
| 126 | .name = "CPLD", | 126 | .name = "CPLD", |
| 127 | .mask = bcsr_irq_mask, | 127 | .irq_mask = bcsr_irq_mask, |
| 128 | .mask_ack = bcsr_irq_maskack, | 128 | .irq_mask_ack = bcsr_irq_maskack, |
| 129 | .unmask = bcsr_irq_unmask, | 129 | .irq_unmask = bcsr_irq_unmask, |
| 130 | }; | 130 | }; |
| 131 | 131 | ||
| 132 | void __init bcsr_init_irq(int csc_start, int csc_end, int hook_irq) | 132 | void __init bcsr_init_irq(int csc_start, int csc_end, int hook_irq) |
