diff options
author | David S. Miller <davem@davemloft.net> | 2006-06-20 04:22:35 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2006-06-20 04:22:35 -0400 |
commit | 8047e247c899f80c33a23ad7e9e250224f0d26a5 (patch) | |
tree | 253a7ba3c902730928214df5c2b5630d7875cc11 /arch/sparc64/kernel/pci_schizo.c | |
parent | 37cdcd9e82108f9b899f1631f66ade2e45738a6e (diff) |
[SPARC64]: Virtualize IRQ numbers.
Inspired by PowerPC XICS interrupt support code.
All IRQs are virtualized in order to keep NR_IRQS from needing
to be too large. Interrupts on sparc64 are arbitrary 11-bit
values, but we don't need to define NR_IRQS to 2048 if we
virtualize the IRQs.
As PCI and SBUS controller drivers build device IRQs, we divy
out virtual IRQ numbers incrementally starting at 1. Zero is
a special virtual IRQ used for the timer interrupt.
So device drivers all see virtual IRQs, and all the normal
interfaces such as request_irq(), enable_irq(), etc. translate
that into a real IRQ number in order to configure the IRQ.
At this point knowledge of the struct ino_bucket is almost
entirely contained within arch/sparc64/kernel/irq.c There are
a few small bits in the PCI controller drivers that need to
be swept away before we can remove ino_bucket's definition
out of asm-sparc64/irq.h and privately into kernel/irq.c
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'arch/sparc64/kernel/pci_schizo.c')
-rw-r--r-- | arch/sparc64/kernel/pci_schizo.c | 86 |
1 files changed, 41 insertions, 45 deletions
diff --git a/arch/sparc64/kernel/pci_schizo.c b/arch/sparc64/kernel/pci_schizo.c index ca49ef08236d..0c400b5fa5bd 100644 --- a/arch/sparc64/kernel/pci_schizo.c +++ b/arch/sparc64/kernel/pci_schizo.c | |||
@@ -270,25 +270,33 @@ static void tomatillo_wsync_handler(struct ino_bucket *bucket, void *_arg1, void | |||
270 | } | 270 | } |
271 | } | 271 | } |
272 | 272 | ||
273 | static unsigned long schizo_ino_to_iclr(struct pci_pbm_info *pbm, | ||
274 | unsigned int ino) | ||
275 | { | ||
276 | ino &= PCI_IRQ_INO; | ||
277 | return pbm->pbm_regs + schizo_iclr_offset(ino) + 4; | ||
278 | } | ||
279 | |||
280 | static unsigned long schizo_ino_to_imap(struct pci_pbm_info *pbm, | ||
281 | unsigned int ino) | ||
282 | { | ||
283 | ino &= PCI_IRQ_INO; | ||
284 | return pbm->pbm_regs + schizo_imap_offset(ino) + 4; | ||
285 | } | ||
286 | |||
273 | static unsigned int schizo_irq_build(struct pci_pbm_info *pbm, | 287 | static unsigned int schizo_irq_build(struct pci_pbm_info *pbm, |
274 | struct pci_dev *pdev, | 288 | struct pci_dev *pdev, |
275 | unsigned int ino) | 289 | unsigned int ino) |
276 | { | 290 | { |
277 | struct ino_bucket *bucket; | ||
278 | unsigned long imap, iclr; | 291 | unsigned long imap, iclr; |
279 | unsigned long imap_off, iclr_off; | ||
280 | int ign_fixup; | 292 | int ign_fixup; |
293 | int virt_irq; | ||
281 | 294 | ||
282 | ino &= PCI_IRQ_INO; | 295 | ino &= PCI_IRQ_INO; |
283 | imap_off = schizo_imap_offset(ino); | ||
284 | 296 | ||
285 | /* Now build the IRQ bucket. */ | 297 | /* Now build the IRQ bucket. */ |
286 | imap = pbm->pbm_regs + imap_off; | 298 | imap = schizo_ino_to_imap(pbm, ino); |
287 | imap += 4; | 299 | iclr = schizo_ino_to_iclr(pbm, ino); |
288 | |||
289 | iclr_off = schizo_iclr_offset(ino); | ||
290 | iclr = pbm->pbm_regs + iclr_off; | ||
291 | iclr += 4; | ||
292 | 300 | ||
293 | /* On Schizo, no inofixup occurs. This is because each | 301 | /* On Schizo, no inofixup occurs. This is because each |
294 | * INO has it's own IMAP register. On Psycho and Sabre | 302 | * INO has it's own IMAP register. On Psycho and Sabre |
@@ -305,19 +313,17 @@ static unsigned int schizo_irq_build(struct pci_pbm_info *pbm, | |||
305 | ign_fixup = (1 << 6); | 313 | ign_fixup = (1 << 6); |
306 | } | 314 | } |
307 | 315 | ||
308 | bucket = __bucket(build_irq(ign_fixup, iclr, imap)); | 316 | virt_irq = build_irq(ign_fixup, iclr, imap, IBF_PCI); |
309 | bucket->flags |= IBF_PCI; | ||
310 | 317 | ||
311 | if (pdev && pbm->chip_type == PBM_CHIP_TYPE_TOMATILLO) { | 318 | if (pdev && pbm->chip_type == PBM_CHIP_TYPE_TOMATILLO) { |
312 | struct irq_desc *p = bucket->irq_info; | 319 | irq_install_pre_handler(virt_irq, |
313 | 320 | tomatillo_wsync_handler, | |
314 | p->pre_handler = tomatillo_wsync_handler; | 321 | ((pbm->chip_version <= 4) ? |
315 | p->pre_handler_arg1 = ((pbm->chip_version <= 4) ? | 322 | (void *) 1 : (void *) 0), |
316 | (void *) 1 : (void *) 0); | 323 | (void *) pbm->sync_reg); |
317 | p->pre_handler_arg2 = (void *) pbm->sync_reg; | ||
318 | } | 324 | } |
319 | 325 | ||
320 | return __irq(bucket); | 326 | return virt_irq; |
321 | } | 327 | } |
322 | 328 | ||
323 | /* SCHIZO error handling support. */ | 329 | /* SCHIZO error handling support. */ |
@@ -358,7 +364,6 @@ struct pci_pbm_info *pbm_for_ino(struct pci_controller_info *p, u32 ino) | |||
358 | static void schizo_clear_other_err_intr(struct pci_controller_info *p, int irq) | 364 | static void schizo_clear_other_err_intr(struct pci_controller_info *p, int irq) |
359 | { | 365 | { |
360 | struct pci_pbm_info *pbm; | 366 | struct pci_pbm_info *pbm; |
361 | struct ino_bucket *bucket; | ||
362 | unsigned long iclr; | 367 | unsigned long iclr; |
363 | 368 | ||
364 | /* Do not clear the interrupt for the other PCI bus. | 369 | /* Do not clear the interrupt for the other PCI bus. |
@@ -376,11 +381,11 @@ static void schizo_clear_other_err_intr(struct pci_controller_info *p, int irq) | |||
376 | else | 381 | else |
377 | pbm = &p->pbm_A; | 382 | pbm = &p->pbm_A; |
378 | 383 | ||
379 | irq = schizo_irq_build(pbm, NULL, | 384 | schizo_irq_build(pbm, NULL, |
380 | (pbm->portid << 6) | (irq & IMAP_INO)); | 385 | (pbm->portid << 6) | (irq & IMAP_INO)); |
381 | bucket = __bucket(irq); | ||
382 | iclr = bucket->iclr; | ||
383 | 386 | ||
387 | iclr = schizo_ino_to_iclr(pbm, | ||
388 | (pbm->portid << 6) | (irq & IMAP_INO)); | ||
384 | upa_writel(ICLR_IDLE, iclr); | 389 | upa_writel(ICLR_IDLE, iclr); |
385 | } | 390 | } |
386 | 391 | ||
@@ -1125,7 +1130,6 @@ static void tomatillo_register_error_handlers(struct pci_controller_info *p) | |||
1125 | { | 1130 | { |
1126 | struct pci_pbm_info *pbm; | 1131 | struct pci_pbm_info *pbm; |
1127 | unsigned int irq; | 1132 | unsigned int irq; |
1128 | struct ino_bucket *bucket; | ||
1129 | u64 tmp, err_mask, err_no_mask; | 1133 | u64 tmp, err_mask, err_no_mask; |
1130 | 1134 | ||
1131 | /* Build IRQs and register handlers. */ | 1135 | /* Build IRQs and register handlers. */ |
@@ -1137,8 +1141,7 @@ static void tomatillo_register_error_handlers(struct pci_controller_info *p) | |||
1137 | pbm->name); | 1141 | pbm->name); |
1138 | prom_halt(); | 1142 | prom_halt(); |
1139 | } | 1143 | } |
1140 | bucket = __bucket(irq); | 1144 | tmp = upa_readl(schizo_ino_to_imap(pbm, (pbm->portid << 6) | SCHIZO_UE_INO)); |
1141 | tmp = upa_readl(bucket->imap); | ||
1142 | upa_writel(tmp, (pbm->pbm_regs + | 1145 | upa_writel(tmp, (pbm->pbm_regs + |
1143 | schizo_imap_offset(SCHIZO_UE_INO) + 4)); | 1146 | schizo_imap_offset(SCHIZO_UE_INO) + 4)); |
1144 | 1147 | ||
@@ -1150,8 +1153,7 @@ static void tomatillo_register_error_handlers(struct pci_controller_info *p) | |||
1150 | pbm->name); | 1153 | pbm->name); |
1151 | prom_halt(); | 1154 | prom_halt(); |
1152 | } | 1155 | } |
1153 | bucket = __bucket(irq); | 1156 | tmp = upa_readl(schizo_ino_to_imap(pbm, (pbm->portid << 6) | SCHIZO_CE_INO)); |
1154 | tmp = upa_readl(bucket->imap); | ||
1155 | upa_writel(tmp, (pbm->pbm_regs + | 1157 | upa_writel(tmp, (pbm->pbm_regs + |
1156 | schizo_imap_offset(SCHIZO_CE_INO) + 4)); | 1158 | schizo_imap_offset(SCHIZO_CE_INO) + 4)); |
1157 | 1159 | ||
@@ -1164,8 +1166,8 @@ static void tomatillo_register_error_handlers(struct pci_controller_info *p) | |||
1164 | pbm->name); | 1166 | pbm->name); |
1165 | prom_halt(); | 1167 | prom_halt(); |
1166 | } | 1168 | } |
1167 | bucket = __bucket(irq); | 1169 | tmp = upa_readl(schizo_ino_to_imap(pbm, ((pbm->portid << 6) | |
1168 | tmp = upa_readl(bucket->imap); | 1170 | SCHIZO_PCIERR_A_INO))); |
1169 | upa_writel(tmp, (pbm->pbm_regs + | 1171 | upa_writel(tmp, (pbm->pbm_regs + |
1170 | schizo_imap_offset(SCHIZO_PCIERR_A_INO) + 4)); | 1172 | schizo_imap_offset(SCHIZO_PCIERR_A_INO) + 4)); |
1171 | 1173 | ||
@@ -1178,8 +1180,8 @@ static void tomatillo_register_error_handlers(struct pci_controller_info *p) | |||
1178 | pbm->name); | 1180 | pbm->name); |
1179 | prom_halt(); | 1181 | prom_halt(); |
1180 | } | 1182 | } |
1181 | bucket = __bucket(irq); | 1183 | tmp = upa_readl(schizo_ino_to_imap(pbm, ((pbm->portid << 6) | |
1182 | tmp = upa_readl(bucket->imap); | 1184 | SCHIZO_PCIERR_B_INO))); |
1183 | upa_writel(tmp, (pbm->pbm_regs + | 1185 | upa_writel(tmp, (pbm->pbm_regs + |
1184 | schizo_imap_offset(SCHIZO_PCIERR_B_INO) + 4)); | 1186 | schizo_imap_offset(SCHIZO_PCIERR_B_INO) + 4)); |
1185 | 1187 | ||
@@ -1191,8 +1193,8 @@ static void tomatillo_register_error_handlers(struct pci_controller_info *p) | |||
1191 | pbm->name); | 1193 | pbm->name); |
1192 | prom_halt(); | 1194 | prom_halt(); |
1193 | } | 1195 | } |
1194 | bucket = __bucket(irq); | 1196 | tmp = upa_readl(schizo_ino_to_imap(pbm, ((pbm->portid << 6) | |
1195 | tmp = upa_readl(bucket->imap); | 1197 | SCHIZO_SERR_INO))); |
1196 | upa_writel(tmp, (pbm->pbm_regs + | 1198 | upa_writel(tmp, (pbm->pbm_regs + |
1197 | schizo_imap_offset(SCHIZO_SERR_INO) + 4)); | 1199 | schizo_imap_offset(SCHIZO_SERR_INO) + 4)); |
1198 | 1200 | ||
@@ -1263,7 +1265,6 @@ static void schizo_register_error_handlers(struct pci_controller_info *p) | |||
1263 | { | 1265 | { |
1264 | struct pci_pbm_info *pbm; | 1266 | struct pci_pbm_info *pbm; |
1265 | unsigned int irq; | 1267 | unsigned int irq; |
1266 | struct ino_bucket *bucket; | ||
1267 | u64 tmp, err_mask, err_no_mask; | 1268 | u64 tmp, err_mask, err_no_mask; |
1268 | 1269 | ||
1269 | /* Build IRQs and register handlers. */ | 1270 | /* Build IRQs and register handlers. */ |
@@ -1275,8 +1276,7 @@ static void schizo_register_error_handlers(struct pci_controller_info *p) | |||
1275 | pbm->name); | 1276 | pbm->name); |
1276 | prom_halt(); | 1277 | prom_halt(); |
1277 | } | 1278 | } |
1278 | bucket = __bucket(irq); | 1279 | tmp = upa_readl(schizo_ino_to_imap(pbm, (pbm->portid << 6) | SCHIZO_UE_INO)); |
1279 | tmp = upa_readl(bucket->imap); | ||
1280 | upa_writel(tmp, (pbm->pbm_regs + schizo_imap_offset(SCHIZO_UE_INO) + 4)); | 1280 | upa_writel(tmp, (pbm->pbm_regs + schizo_imap_offset(SCHIZO_UE_INO) + 4)); |
1281 | 1281 | ||
1282 | pbm = pbm_for_ino(p, SCHIZO_CE_INO); | 1282 | pbm = pbm_for_ino(p, SCHIZO_CE_INO); |
@@ -1287,8 +1287,7 @@ static void schizo_register_error_handlers(struct pci_controller_info *p) | |||
1287 | pbm->name); | 1287 | pbm->name); |
1288 | prom_halt(); | 1288 | prom_halt(); |
1289 | } | 1289 | } |
1290 | bucket = __bucket(irq); | 1290 | tmp = upa_readl(schizo_ino_to_imap(pbm, (pbm->portid << 6) | SCHIZO_CE_INO)); |
1291 | tmp = upa_readl(bucket->imap); | ||
1292 | upa_writel(tmp, (pbm->pbm_regs + schizo_imap_offset(SCHIZO_CE_INO) + 4)); | 1291 | upa_writel(tmp, (pbm->pbm_regs + schizo_imap_offset(SCHIZO_CE_INO) + 4)); |
1293 | 1292 | ||
1294 | pbm = pbm_for_ino(p, SCHIZO_PCIERR_A_INO); | 1293 | pbm = pbm_for_ino(p, SCHIZO_PCIERR_A_INO); |
@@ -1299,8 +1298,7 @@ static void schizo_register_error_handlers(struct pci_controller_info *p) | |||
1299 | pbm->name); | 1298 | pbm->name); |
1300 | prom_halt(); | 1299 | prom_halt(); |
1301 | } | 1300 | } |
1302 | bucket = __bucket(irq); | 1301 | tmp = upa_readl(schizo_ino_to_imap(pbm, (pbm->portid << 6) | SCHIZO_PCIERR_A_INO)); |
1303 | tmp = upa_readl(bucket->imap); | ||
1304 | upa_writel(tmp, (pbm->pbm_regs + schizo_imap_offset(SCHIZO_PCIERR_A_INO) + 4)); | 1302 | upa_writel(tmp, (pbm->pbm_regs + schizo_imap_offset(SCHIZO_PCIERR_A_INO) + 4)); |
1305 | 1303 | ||
1306 | pbm = pbm_for_ino(p, SCHIZO_PCIERR_B_INO); | 1304 | pbm = pbm_for_ino(p, SCHIZO_PCIERR_B_INO); |
@@ -1311,8 +1309,7 @@ static void schizo_register_error_handlers(struct pci_controller_info *p) | |||
1311 | pbm->name); | 1309 | pbm->name); |
1312 | prom_halt(); | 1310 | prom_halt(); |
1313 | } | 1311 | } |
1314 | bucket = __bucket(irq); | 1312 | tmp = upa_readl(schizo_ino_to_imap(pbm, (pbm->portid << 6) | SCHIZO_PCIERR_B_INO)); |
1315 | tmp = upa_readl(bucket->imap); | ||
1316 | upa_writel(tmp, (pbm->pbm_regs + schizo_imap_offset(SCHIZO_PCIERR_B_INO) + 4)); | 1313 | upa_writel(tmp, (pbm->pbm_regs + schizo_imap_offset(SCHIZO_PCIERR_B_INO) + 4)); |
1317 | 1314 | ||
1318 | pbm = pbm_for_ino(p, SCHIZO_SERR_INO); | 1315 | pbm = pbm_for_ino(p, SCHIZO_SERR_INO); |
@@ -1323,8 +1320,7 @@ static void schizo_register_error_handlers(struct pci_controller_info *p) | |||
1323 | pbm->name); | 1320 | pbm->name); |
1324 | prom_halt(); | 1321 | prom_halt(); |
1325 | } | 1322 | } |
1326 | bucket = __bucket(irq); | 1323 | tmp = upa_readl(schizo_ino_to_imap(pbm, (pbm->portid << 6) | SCHIZO_SERR_INO)); |
1327 | tmp = upa_readl(bucket->imap); | ||
1328 | upa_writel(tmp, (pbm->pbm_regs + schizo_imap_offset(SCHIZO_SERR_INO) + 4)); | 1324 | upa_writel(tmp, (pbm->pbm_regs + schizo_imap_offset(SCHIZO_SERR_INO) + 4)); |
1329 | 1325 | ||
1330 | /* Enable UE and CE interrupts for controller. */ | 1326 | /* Enable UE and CE interrupts for controller. */ |