Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[POWERPC] ipic: ack only for edge interrupts

Only external interrupts in edge detect mode support ack operation.
Therefore, in most cases ack is not needed. The patch makes ipic
ack only when it's needed. This could boost over all system performance.

Signed-off-by: Li Yang <leoli@freescale.com>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Signed-off-by: Kumar Gala <galak@kernel.crashing.org>

authored by

Li Yang and committed by
Kumar Gala
77d4309e ea082fa9

+45 -74
+43 -70
arch/powerpc/sysdev/ipic.c
··· 30 30 #include "ipic.h" 31 31 32 32 static struct ipic * primary_ipic; 33 + static struct irq_chip ipic_level_irq_chip, ipic_edge_irq_chip; 33 34 static DEFINE_SPINLOCK(ipic_lock); 34 35 35 36 static struct ipic_info ipic_info[] = { 36 37 [1] = { 37 - .pend = IPIC_SIPNR_H, 38 38 .mask = IPIC_SIMSR_H, 39 39 .prio = IPIC_SIPRR_C, 40 40 .force = IPIC_SIFCR_H, ··· 42 42 .prio_mask = 0, 43 43 }, 44 44 [2] = { 45 - .pend = IPIC_SIPNR_H, 46 45 .mask = IPIC_SIMSR_H, 47 46 .prio = IPIC_SIPRR_C, 48 47 .force = IPIC_SIFCR_H, ··· 49 50 .prio_mask = 1, 50 51 }, 51 52 [4] = { 52 - .pend = IPIC_SIPNR_H, 53 53 .mask = IPIC_SIMSR_H, 54 54 .prio = IPIC_SIPRR_C, 55 55 .force = IPIC_SIFCR_H, ··· 56 58 .prio_mask = 3, 57 59 }, 58 60 [9] = { 59 - .pend = IPIC_SIPNR_H, 60 61 .mask = IPIC_SIMSR_H, 61 62 .prio = IPIC_SIPRR_D, 62 63 .force = IPIC_SIFCR_H, ··· 63 66 .prio_mask = 0, 64 67 }, 65 68 [10] = { 66 - .pend = IPIC_SIPNR_H, 67 69 .mask = IPIC_SIMSR_H, 68 70 .prio = IPIC_SIPRR_D, 69 71 .force = IPIC_SIFCR_H, ··· 70 74 .prio_mask = 1, 71 75 }, 72 76 [11] = { 73 - .pend = IPIC_SIPNR_H, 74 77 .mask = IPIC_SIMSR_H, 75 78 .prio = IPIC_SIPRR_D, 76 79 .force = IPIC_SIFCR_H, ··· 77 82 .prio_mask = 2, 78 83 }, 79 84 [12] = { 80 - .pend = IPIC_SIPNR_H, 81 85 .mask = IPIC_SIMSR_H, 82 86 .prio = IPIC_SIPRR_D, 83 87 .force = IPIC_SIFCR_H, ··· 84 90 .prio_mask = 3, 85 91 }, 86 92 [13] = { 87 - .pend = IPIC_SIPNR_H, 88 93 .mask = IPIC_SIMSR_H, 89 94 .prio = IPIC_SIPRR_D, 90 95 .force = IPIC_SIFCR_H, ··· 91 98 .prio_mask = 4, 92 99 }, 93 100 [14] = { 94 - .pend = IPIC_SIPNR_H, 95 101 .mask = IPIC_SIMSR_H, 96 102 .prio = IPIC_SIPRR_D, 97 103 .force = IPIC_SIFCR_H, ··· 98 106 .prio_mask = 5, 99 107 }, 100 108 [15] = { 101 - .pend = IPIC_SIPNR_H, 102 109 .mask = IPIC_SIMSR_H, 103 110 .prio = IPIC_SIPRR_D, 104 111 .force = IPIC_SIFCR_H, ··· 105 114 .prio_mask = 6, 106 115 }, 107 116 [16] = { 108 - .pend = IPIC_SIPNR_H, 109 117 .mask = IPIC_SIMSR_H, 110 118 .prio = IPIC_SIPRR_D, 111 119 .force = IPIC_SIFCR_H, ··· 112 122 .prio_mask = 7, 113 123 }, 114 124 [17] = { 115 - .pend = IPIC_SEPNR, 125 + .ack = IPIC_SEPNR, 116 126 .mask = IPIC_SEMSR, 117 127 .prio = IPIC_SMPRR_A, 118 128 .force = IPIC_SEFCR, ··· 120 130 .prio_mask = 5, 121 131 }, 122 132 [18] = { 123 - .pend = IPIC_SEPNR, 133 + .ack = IPIC_SEPNR, 124 134 .mask = IPIC_SEMSR, 125 135 .prio = IPIC_SMPRR_A, 126 136 .force = IPIC_SEFCR, ··· 128 138 .prio_mask = 6, 129 139 }, 130 140 [19] = { 131 - .pend = IPIC_SEPNR, 141 + .ack = IPIC_SEPNR, 132 142 .mask = IPIC_SEMSR, 133 143 .prio = IPIC_SMPRR_A, 134 144 .force = IPIC_SEFCR, ··· 136 146 .prio_mask = 7, 137 147 }, 138 148 [20] = { 139 - .pend = IPIC_SEPNR, 149 + .ack = IPIC_SEPNR, 140 150 .mask = IPIC_SEMSR, 141 151 .prio = IPIC_SMPRR_B, 142 152 .force = IPIC_SEFCR, ··· 144 154 .prio_mask = 4, 145 155 }, 146 156 [21] = { 147 - .pend = IPIC_SEPNR, 157 + .ack = IPIC_SEPNR, 148 158 .mask = IPIC_SEMSR, 149 159 .prio = IPIC_SMPRR_B, 150 160 .force = IPIC_SEFCR, ··· 152 162 .prio_mask = 5, 153 163 }, 154 164 [22] = { 155 - .pend = IPIC_SEPNR, 165 + .ack = IPIC_SEPNR, 156 166 .mask = IPIC_SEMSR, 157 167 .prio = IPIC_SMPRR_B, 158 168 .force = IPIC_SEFCR, ··· 160 170 .prio_mask = 6, 161 171 }, 162 172 [23] = { 163 - .pend = IPIC_SEPNR, 173 + .ack = IPIC_SEPNR, 164 174 .mask = IPIC_SEMSR, 165 175 .prio = IPIC_SMPRR_B, 166 176 .force = IPIC_SEFCR, ··· 168 178 .prio_mask = 7, 169 179 }, 170 180 [32] = { 171 - .pend = IPIC_SIPNR_H, 172 181 .mask = IPIC_SIMSR_H, 173 182 .prio = IPIC_SIPRR_A, 174 183 .force = IPIC_SIFCR_H, ··· 175 186 .prio_mask = 0, 176 187 }, 177 188 [33] = { 178 - .pend = IPIC_SIPNR_H, 179 189 .mask = IPIC_SIMSR_H, 180 190 .prio = IPIC_SIPRR_A, 181 191 .force = IPIC_SIFCR_H, ··· 182 194 .prio_mask = 1, 183 195 }, 184 196 [34] = { 185 - .pend = IPIC_SIPNR_H, 186 197 .mask = IPIC_SIMSR_H, 187 198 .prio = IPIC_SIPRR_A, 188 199 .force = IPIC_SIFCR_H, ··· 189 202 .prio_mask = 2, 190 203 }, 191 204 [35] = { 192 - .pend = IPIC_SIPNR_H, 193 205 .mask = IPIC_SIMSR_H, 194 206 .prio = IPIC_SIPRR_A, 195 207 .force = IPIC_SIFCR_H, ··· 196 210 .prio_mask = 3, 197 211 }, 198 212 [36] = { 199 - .pend = IPIC_SIPNR_H, 200 213 .mask = IPIC_SIMSR_H, 201 214 .prio = IPIC_SIPRR_A, 202 215 .force = IPIC_SIFCR_H, ··· 203 218 .prio_mask = 4, 204 219 }, 205 220 [37] = { 206 - .pend = IPIC_SIPNR_H, 207 221 .mask = IPIC_SIMSR_H, 208 222 .prio = IPIC_SIPRR_A, 209 223 .force = IPIC_SIFCR_H, ··· 210 226 .prio_mask = 5, 211 227 }, 212 228 [38] = { 213 - .pend = IPIC_SIPNR_H, 214 229 .mask = IPIC_SIMSR_H, 215 230 .prio = IPIC_SIPRR_A, 216 231 .force = IPIC_SIFCR_H, ··· 217 234 .prio_mask = 6, 218 235 }, 219 236 [39] = { 220 - .pend = IPIC_SIPNR_H, 221 237 .mask = IPIC_SIMSR_H, 222 238 .prio = IPIC_SIPRR_A, 223 239 .force = IPIC_SIFCR_H, ··· 224 242 .prio_mask = 7, 225 243 }, 226 244 [42] = { 227 - .pend = IPIC_SIPNR_H, 228 245 .mask = IPIC_SIMSR_H, 229 246 .prio = IPIC_SIPRR_B, 230 247 .force = IPIC_SIFCR_H, ··· 231 250 .prio_mask = 2, 232 251 }, 233 252 [44] = { 234 - .pend = IPIC_SIPNR_H, 235 253 .mask = IPIC_SIMSR_H, 236 254 .prio = IPIC_SIPRR_B, 237 255 .force = IPIC_SIFCR_H, ··· 238 258 .prio_mask = 4, 239 259 }, 240 260 [45] = { 241 - .pend = IPIC_SIPNR_H, 242 261 .mask = IPIC_SIMSR_H, 243 262 .prio = IPIC_SIPRR_B, 244 263 .force = IPIC_SIFCR_H, ··· 245 266 .prio_mask = 5, 246 267 }, 247 268 [46] = { 248 - .pend = IPIC_SIPNR_H, 249 269 .mask = IPIC_SIMSR_H, 250 270 .prio = IPIC_SIPRR_B, 251 271 .force = IPIC_SIFCR_H, ··· 252 274 .prio_mask = 6, 253 275 }, 254 276 [47] = { 255 - .pend = IPIC_SIPNR_H, 256 277 .mask = IPIC_SIMSR_H, 257 278 .prio = IPIC_SIPRR_B, 258 279 .force = IPIC_SIFCR_H, ··· 259 282 .prio_mask = 7, 260 283 }, 261 284 [48] = { 262 - .pend = IPIC_SEPNR, 263 285 .mask = IPIC_SEMSR, 264 286 .prio = IPIC_SMPRR_A, 265 287 .force = IPIC_SEFCR, ··· 266 290 .prio_mask = 4, 267 291 }, 268 292 [64] = { 269 - .pend = IPIC_SIPNR_L, 270 293 .mask = IPIC_SIMSR_L, 271 294 .prio = IPIC_SMPRR_A, 272 295 .force = IPIC_SIFCR_L, ··· 273 298 .prio_mask = 0, 274 299 }, 275 300 [65] = { 276 - .pend = IPIC_SIPNR_L, 277 301 .mask = IPIC_SIMSR_L, 278 302 .prio = IPIC_SMPRR_A, 279 303 .force = IPIC_SIFCR_L, ··· 280 306 .prio_mask = 1, 281 307 }, 282 308 [66] = { 283 - .pend = IPIC_SIPNR_L, 284 309 .mask = IPIC_SIMSR_L, 285 310 .prio = IPIC_SMPRR_A, 286 311 .force = IPIC_SIFCR_L, ··· 287 314 .prio_mask = 2, 288 315 }, 289 316 [67] = { 290 - .pend = IPIC_SIPNR_L, 291 317 .mask = IPIC_SIMSR_L, 292 318 .prio = IPIC_SMPRR_A, 293 319 .force = IPIC_SIFCR_L, ··· 294 322 .prio_mask = 3, 295 323 }, 296 324 [68] = { 297 - .pend = IPIC_SIPNR_L, 298 325 .mask = IPIC_SIMSR_L, 299 326 .prio = IPIC_SMPRR_B, 300 327 .force = IPIC_SIFCR_L, ··· 301 330 .prio_mask = 0, 302 331 }, 303 332 [69] = { 304 - .pend = IPIC_SIPNR_L, 305 333 .mask = IPIC_SIMSR_L, 306 334 .prio = IPIC_SMPRR_B, 307 335 .force = IPIC_SIFCR_L, ··· 308 338 .prio_mask = 1, 309 339 }, 310 340 [70] = { 311 - .pend = IPIC_SIPNR_L, 312 341 .mask = IPIC_SIMSR_L, 313 342 .prio = IPIC_SMPRR_B, 314 343 .force = IPIC_SIFCR_L, ··· 315 346 .prio_mask = 2, 316 347 }, 317 348 [71] = { 318 - .pend = IPIC_SIPNR_L, 319 349 .mask = IPIC_SIMSR_L, 320 350 .prio = IPIC_SMPRR_B, 321 351 .force = IPIC_SIFCR_L, ··· 322 354 .prio_mask = 3, 323 355 }, 324 356 [72] = { 325 - .pend = IPIC_SIPNR_L, 326 357 .mask = IPIC_SIMSR_L, 327 358 .prio = 0, 328 359 .force = IPIC_SIFCR_L, 329 360 .bit = 8, 330 361 }, 331 362 [73] = { 332 - .pend = IPIC_SIPNR_L, 333 363 .mask = IPIC_SIMSR_L, 334 364 .prio = 0, 335 365 .force = IPIC_SIFCR_L, 336 366 .bit = 9, 337 367 }, 338 368 [74] = { 339 - .pend = IPIC_SIPNR_L, 340 369 .mask = IPIC_SIMSR_L, 341 370 .prio = 0, 342 371 .force = IPIC_SIFCR_L, 343 372 .bit = 10, 344 373 }, 345 374 [75] = { 346 - .pend = IPIC_SIPNR_L, 347 375 .mask = IPIC_SIMSR_L, 348 376 .prio = 0, 349 377 .force = IPIC_SIFCR_L, 350 378 .bit = 11, 351 379 }, 352 380 [76] = { 353 - .pend = IPIC_SIPNR_L, 354 381 .mask = IPIC_SIMSR_L, 355 382 .prio = 0, 356 383 .force = IPIC_SIFCR_L, 357 384 .bit = 12, 358 385 }, 359 386 [77] = { 360 - .pend = IPIC_SIPNR_L, 361 387 .mask = IPIC_SIMSR_L, 362 388 .prio = 0, 363 389 .force = IPIC_SIFCR_L, 364 390 .bit = 13, 365 391 }, 366 392 [78] = { 367 - .pend = IPIC_SIPNR_L, 368 393 .mask = IPIC_SIMSR_L, 369 394 .prio = 0, 370 395 .force = IPIC_SIFCR_L, 371 396 .bit = 14, 372 397 }, 373 398 [79] = { 374 - .pend = IPIC_SIPNR_L, 375 399 .mask = IPIC_SIMSR_L, 376 400 .prio = 0, 377 401 .force = IPIC_SIFCR_L, 378 402 .bit = 15, 379 403 }, 380 404 [80] = { 381 - .pend = IPIC_SIPNR_L, 382 405 .mask = IPIC_SIMSR_L, 383 406 .prio = 0, 384 407 .force = IPIC_SIFCR_L, 385 408 .bit = 16, 386 409 }, 387 410 [81] = { 388 - .pend = IPIC_SIPNR_L, 389 411 .mask = IPIC_SIMSR_L, 390 412 .prio = 0, 391 413 .force = IPIC_SIFCR_L, 392 414 .bit = 17, 393 415 }, 394 416 [82] = { 395 - .pend = IPIC_SIPNR_L, 396 417 .mask = IPIC_SIMSR_L, 397 418 .prio = 0, 398 419 .force = IPIC_SIFCR_L, 399 420 .bit = 18, 400 421 }, 401 422 [84] = { 402 - .pend = IPIC_SIPNR_L, 403 423 .mask = IPIC_SIMSR_L, 404 424 .prio = 0, 405 425 .force = IPIC_SIFCR_L, 406 426 .bit = 20, 407 427 }, 408 428 [85] = { 409 - .pend = IPIC_SIPNR_L, 410 429 .mask = IPIC_SIMSR_L, 411 430 .prio = 0, 412 431 .force = IPIC_SIFCR_L, 413 432 .bit = 21, 414 433 }, 415 434 [86] = { 416 - .pend = IPIC_SIPNR_L, 417 435 .mask = IPIC_SIMSR_L, 418 436 .prio = 0, 419 437 .force = IPIC_SIFCR_L, 420 438 .bit = 22, 421 439 }, 422 440 [87] = { 423 - .pend = IPIC_SIPNR_L, 424 441 .mask = IPIC_SIMSR_L, 425 442 .prio = 0, 426 443 .force = IPIC_SIFCR_L, 427 444 .bit = 23, 428 445 }, 429 446 [88] = { 430 - .pend = IPIC_SIPNR_L, 431 447 .mask = IPIC_SIMSR_L, 432 448 .prio = 0, 433 449 .force = IPIC_SIFCR_L, 434 450 .bit = 24, 435 451 }, 436 452 [89] = { 437 - .pend = IPIC_SIPNR_L, 438 453 .mask = IPIC_SIMSR_L, 439 454 .prio = 0, 440 455 .force = IPIC_SIFCR_L, 441 456 .bit = 25, 442 457 }, 443 458 [90] = { 444 - .pend = IPIC_SIPNR_L, 445 459 .mask = IPIC_SIMSR_L, 446 460 .prio = 0, 447 461 .force = IPIC_SIFCR_L, 448 462 .bit = 26, 449 463 }, 450 464 [91] = { 451 - .pend = IPIC_SIPNR_L, 452 465 .mask = IPIC_SIMSR_L, 453 466 .prio = 0, 454 467 .force = IPIC_SIFCR_L, ··· 483 534 temp &= ~(1 << (31 - ipic_info[src].bit)); 484 535 ipic_write(ipic->regs, ipic_info[src].mask, temp); 485 536 537 + /* mb() can't guarantee that masking is finished. But it does finish 538 + * for nearly all cases. */ 539 + mb(); 540 + 486 541 spin_unlock_irqrestore(&ipic_lock, flags); 487 542 } 488 543 ··· 499 546 500 547 spin_lock_irqsave(&ipic_lock, flags); 501 548 502 - temp = ipic_read(ipic->regs, ipic_info[src].pend); 549 + temp = ipic_read(ipic->regs, ipic_info[src].ack); 503 550 temp |= (1 << (31 - ipic_info[src].bit)); 504 - ipic_write(ipic->regs, ipic_info[src].pend, temp); 551 + ipic_write(ipic->regs, ipic_info[src].ack, temp); 552 + 553 + /* mb() can't guarantee that ack is finished. But it does finish 554 + * for nearly all cases. */ 555 + mb(); 505 556 506 557 spin_unlock_irqrestore(&ipic_lock, flags); 507 558 } ··· 523 566 temp &= ~(1 << (31 - ipic_info[src].bit)); 524 567 ipic_write(ipic->regs, ipic_info[src].mask, temp); 525 568 526 - temp = ipic_read(ipic->regs, ipic_info[src].pend); 569 + temp = ipic_read(ipic->regs, ipic_info[src].ack); 527 570 temp |= (1 << (31 - ipic_info[src].bit)); 528 - ipic_write(ipic->regs, ipic_info[src].pend, temp); 571 + ipic_write(ipic->regs, ipic_info[src].ack, temp); 572 + 573 + /* mb() can't guarantee that ack is finished. But it does finish 574 + * for nearly all cases. */ 575 + mb(); 529 576 530 577 spin_unlock_irqrestore(&ipic_lock, flags); 531 578 } ··· 551 590 flow_type); 552 591 return -EINVAL; 553 592 } 593 + /* ipic supports only edge mode on external interrupts */ 594 + if ((flow_type & IRQ_TYPE_EDGE_FALLING) && !ipic_info[src].ack) { 595 + printk(KERN_ERR "ipic: edge sense not supported on internal " 596 + "interrupts\n"); 597 + return -EINVAL; 598 + } 554 599 555 600 desc->status &= ~(IRQ_TYPE_SENSE_MASK | IRQ_LEVEL); 556 601 desc->status |= flow_type & IRQ_TYPE_SENSE_MASK; 557 602 if (flow_type & IRQ_TYPE_LEVEL_LOW) { 558 603 desc->status |= IRQ_LEVEL; 559 604 desc->handle_irq = handle_level_irq; 605 + desc->chip = &ipic_level_irq_chip; 560 606 } else { 561 607 desc->handle_irq = handle_edge_irq; 608 + desc->chip = &ipic_edge_irq_chip; 562 609 } 563 610 564 611 /* only EXT IRQ senses are programmable on ipic ··· 591 622 return 0; 592 623 } 593 624 594 - static struct irq_chip ipic_irq_chip = { 625 + /* level interrupts and edge interrupts have different ack operations */ 626 + static struct irq_chip ipic_level_irq_chip = { 627 + .typename = " IPIC ", 628 + .unmask = ipic_unmask_irq, 629 + .mask = ipic_mask_irq, 630 + .mask_ack = ipic_mask_irq, 631 + .set_type = ipic_set_irq_type, 632 + }; 633 + 634 + static struct irq_chip ipic_edge_irq_chip = { 595 635 .typename = " IPIC ", 596 636 .unmask = ipic_unmask_irq, 597 637 .mask = ipic_mask_irq, ··· 619 641 irq_hw_number_t hw) 620 642 { 621 643 struct ipic *ipic = h->host_data; 622 - struct irq_chip *chip; 623 - 624 - /* Default chip */ 625 - chip = &ipic->hc_irq; 626 644 627 645 set_irq_chip_data(virq, ipic); 628 - set_irq_chip_and_handler(virq, chip, handle_level_irq); 646 + set_irq_chip_and_handler(virq, &ipic_level_irq_chip, handle_level_irq); 629 647 630 648 /* Set default irq type */ 631 649 set_irq_type(virq, IRQ_TYPE_NONE); ··· 680 706 ipic->regs = ioremap(res.start, res.end - res.start + 1); 681 707 682 708 ipic->irqhost->host_data = ipic; 683 - ipic->hc_irq = ipic_irq_chip; 684 709 685 710 /* init hw */ 686 711 ipic_write(ipic->regs, IPIC_SICNR, 0x0);
+2 -4
arch/powerpc/sysdev/ipic.h
··· 44 44 45 45 /* The remapper for this IPIC */ 46 46 struct irq_host *irqhost; 47 - 48 - /* The "linux" controller struct */ 49 - struct irq_chip hc_irq; 50 47 }; 51 48 52 49 struct ipic_info { 53 - u8 pend; /* pending register offset from base */ 50 + u8 ack; /* pending register offset from base if the irq 51 + supports ack operation */ 54 52 u8 mask; /* mask register offset from base */ 55 53 u8 prio; /* priority register offset from base */ 56 54 u8 force; /* force register offset from base */