aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sparc64/kernel/pci_schizo.c
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2006-06-20 04:22:35 -0400
committerDavid S. Miller <davem@davemloft.net>2006-06-20 04:22:35 -0400
commit8047e247c899f80c33a23ad7e9e250224f0d26a5 (patch)
tree253a7ba3c902730928214df5c2b5630d7875cc11 /arch/sparc64/kernel/pci_schizo.c
parent37cdcd9e82108f9b899f1631f66ade2e45738a6e (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.c86
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
273static 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
280static 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
273static unsigned int schizo_irq_build(struct pci_pbm_info *pbm, 287static 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)
358static void schizo_clear_other_err_intr(struct pci_controller_info *p, int irq) 364static 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. */