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

[MIPS] TXx9: PCI error handling

From: Atsushi Nemoto <anemo@mba.ocn.ne.jp>
Date: Thu, 24 Jul 2008 00:25:16 +0900
Subject: [PATCH] txx9: PCI error handling

Add more control and detailed report on PCI error interrupt.

Signed-off-by: Atsushi Nemoto <anemo@mba.ocn.ne.jp>
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>

authored by

Atsushi Nemoto and committed by
Ralf Baechle
455cc256 07517529

+132 -20
+34
arch/mips/pci/ops-tx3927.c
··· 37 37 #include <linux/pci.h> 38 38 #include <linux/kernel.h> 39 39 #include <linux/init.h> 40 + #include <linux/interrupt.h> 40 41 41 42 #include <asm/addrspace.h> 43 + #include <asm/txx9irq.h> 44 + #include <asm/txx9/pci.h> 42 45 #include <asm/txx9/tx3927.h> 43 46 44 47 static int mkaddr(struct pci_bus *bus, unsigned char devfn, unsigned char where) ··· 196 193 PCI_COMMAND_IO | 197 194 PCI_COMMAND_PARITY | PCI_COMMAND_SERR; 198 195 local_irq_restore(flags); 196 + } 197 + 198 + static irqreturn_t tx3927_pcierr_interrupt(int irq, void *dev_id) 199 + { 200 + struct pt_regs *regs = get_irq_regs(); 201 + 202 + if (txx9_pci_err_action != TXX9_PCI_ERR_IGNORE) { 203 + printk(KERN_WARNING "PCI error interrupt at 0x%08lx.\n", 204 + regs->cp0_epc); 205 + printk(KERN_WARNING "pcistat:%02x, lbstat:%04lx\n", 206 + tx3927_pcicptr->pcistat, tx3927_pcicptr->lbstat); 207 + } 208 + if (txx9_pci_err_action != TXX9_PCI_ERR_PANIC) { 209 + /* clear all pci errors */ 210 + tx3927_pcicptr->pcistat |= TX3927_PCIC_PCISTATIM_ALL; 211 + tx3927_pcicptr->istat = TX3927_PCIC_IIM_ALL; 212 + tx3927_pcicptr->tstat = TX3927_PCIC_TIM_ALL; 213 + tx3927_pcicptr->lbstat = TX3927_PCIC_LBIM_ALL; 214 + return IRQ_HANDLED; 215 + } 216 + console_verbose(); 217 + panic("PCI error."); 218 + } 219 + 220 + void __init tx3927_setup_pcierr_irq(void) 221 + { 222 + if (request_irq(TXX9_IRQ_BASE + TX3927_IR_PCI, 223 + tx3927_pcierr_interrupt, 224 + IRQF_DISABLED, "PCI error", 225 + (void *)TX3927_PCIC_REG)) 226 + printk(KERN_WARNING "Failed to request irq for PCIERR\n"); 199 227 }
+62
arch/mips/pci/ops-tx4927.c
··· 16 16 * option) any later version. 17 17 */ 18 18 #include <linux/kernel.h> 19 + #include <linux/interrupt.h> 20 + #include <asm/txx9/pci.h> 19 21 #include <asm/txx9/tx4927pcic.h> 20 22 21 23 static struct { ··· 431 429 if (pcicptrs[i].pcicptr) 432 430 tx4927_report_pcic_status1(pcicptrs[i].pcicptr); 433 431 } 432 + } 433 + 434 + static void tx4927_dump_pcic_settings1(struct tx4927_pcic_reg __iomem *pcicptr) 435 + { 436 + int i; 437 + __u32 __iomem *preg = (__u32 __iomem *)pcicptr; 438 + 439 + printk(KERN_INFO "tx4927 pcic (0x%p) settings:", pcicptr); 440 + for (i = 0; i < sizeof(struct tx4927_pcic_reg); i += 4, preg++) { 441 + if (i % 32 == 0) { 442 + printk(KERN_CONT "\n"); 443 + printk(KERN_INFO "%04x:", i); 444 + } 445 + /* skip registers with side-effects */ 446 + if (i == offsetof(struct tx4927_pcic_reg, g2pintack) 447 + || i == offsetof(struct tx4927_pcic_reg, g2pspc) 448 + || i == offsetof(struct tx4927_pcic_reg, g2pcfgadrs) 449 + || i == offsetof(struct tx4927_pcic_reg, g2pcfgdata)) { 450 + printk(KERN_CONT " XXXXXXXX"); 451 + continue; 452 + } 453 + printk(KERN_CONT " %08x", __raw_readl(preg)); 454 + } 455 + printk(KERN_CONT "\n"); 456 + } 457 + 458 + void tx4927_dump_pcic_settings(void) 459 + { 460 + int i; 461 + 462 + for (i = 0; i < ARRAY_SIZE(pcicptrs); i++) { 463 + if (pcicptrs[i].pcicptr) 464 + tx4927_dump_pcic_settings1(pcicptrs[i].pcicptr); 465 + } 466 + } 467 + 468 + irqreturn_t tx4927_pcierr_interrupt(int irq, void *dev_id) 469 + { 470 + struct pt_regs *regs = get_irq_regs(); 471 + struct tx4927_pcic_reg __iomem *pcicptr = 472 + (struct tx4927_pcic_reg __iomem *)(unsigned long)dev_id; 473 + 474 + if (txx9_pci_err_action != TXX9_PCI_ERR_IGNORE) { 475 + printk(KERN_WARNING "PCIERR interrupt at 0x%0*lx\n", 476 + (int)(2 * sizeof(unsigned long)), regs->cp0_epc); 477 + tx4927_report_pcic_status1(pcicptr); 478 + } 479 + if (txx9_pci_err_action != TXX9_PCI_ERR_PANIC) { 480 + /* clear all pci errors */ 481 + __raw_writel((__raw_readl(&pcicptr->pcistatus) & 0x0000ffff) 482 + | (TX4927_PCIC_PCISTATUS_ALL << 16), 483 + &pcicptr->pcistatus); 484 + __raw_writel(TX4927_PCIC_G2PSTATUS_ALL, &pcicptr->g2pstatus); 485 + __raw_writel(TX4927_PCIC_PBASTATUS_ALL, &pcicptr->pbastatus); 486 + __raw_writel(TX4927_PCIC_PCICSTATUS_ALL, &pcicptr->pcicstatus); 487 + return IRQ_HANDLED; 488 + } 489 + console_verbose(); 490 + tx4927_dump_pcic_settings1(pcicptr); 491 + panic("PCI error."); 434 492 } 435 493 436 494 #ifdef CONFIG_TOSHIBA_FPCIB0
+10
arch/mips/pci/pci-tx4927.c
··· 15 15 #include <linux/init.h> 16 16 #include <linux/pci.h> 17 17 #include <linux/kernel.h> 18 + #include <linux/interrupt.h> 18 19 #include <asm/txx9/generic.h> 19 20 #include <asm/txx9/tx4927.h> 20 21 ··· 81 80 } else 82 81 pciclk = -1; 83 82 return pciclk; 83 + } 84 + 85 + void __init tx4927_setup_pcierr_irq(void) 86 + { 87 + if (request_irq(TXX9_IRQ_BASE + TX4927_IR_PCIERR, 88 + tx4927_pcierr_interrupt, 89 + IRQF_DISABLED, "PCI error", 90 + (void *)TX4927_PCIC_REG)) 91 + printk(KERN_WARNING "Failed to request irq for PCIERR\n"); 84 92 }
+10
arch/mips/pci/pci-tx4938.c
··· 15 15 #include <linux/init.h> 16 16 #include <linux/pci.h> 17 17 #include <linux/kernel.h> 18 + #include <linux/interrupt.h> 18 19 #include <asm/txx9/generic.h> 19 20 #include <asm/txx9/tx4938.h> 20 21 ··· 132 131 return 0; 133 132 } 134 133 return -1; 134 + } 135 + 136 + void __init tx4938_setup_pcierr_irq(void) 137 + { 138 + if (request_irq(TXX9_IRQ_BASE + TX4938_IR_PCIERR, 139 + tx4927_pcierr_interrupt, 140 + IRQF_DISABLED, "PCI error", 141 + (void *)TX4927_PCIC_REG)) 142 + printk(KERN_WARNING "Failed to request irq for PCIERR\n"); 135 143 }
-20
arch/mips/txx9/jmr3927/irq.c
··· 103 103 return irq; 104 104 } 105 105 106 - #ifdef CONFIG_PCI 107 - static irqreturn_t jmr3927_pcierr_interrupt(int irq, void *dev_id) 108 - { 109 - printk(KERN_WARNING "PCI error interrupt (irq 0x%x).\n", irq); 110 - printk(KERN_WARNING "pcistat:%02x, lbstat:%04lx\n", 111 - tx3927_pcicptr->pcistat, tx3927_pcicptr->lbstat); 112 - 113 - return IRQ_HANDLED; 114 - } 115 - static struct irqaction pcierr_action = { 116 - .handler = jmr3927_pcierr_interrupt, 117 - .mask = CPU_MASK_NONE, 118 - .name = "PCI error", 119 - }; 120 - #endif 121 - 122 106 static void __init jmr3927_irq_init(void); 123 107 124 108 void __init jmr3927_irq_setup(void) ··· 126 142 127 143 /* setup IOC interrupt 1 (PCI, MODEM) */ 128 144 set_irq_chained_handler(JMR3927_IRQ_IOCINT, handle_simple_irq); 129 - 130 - #ifdef CONFIG_PCI 131 - setup_irq(JMR3927_IRQ_IRC_PCI, &pcierr_action); 132 - #endif 133 145 134 146 /* enable all CPU interrupt bits. */ 135 147 set_c0_status(ST0_IM); /* IE bit is still 0. */
+1
arch/mips/txx9/jmr3927/setup.c
··· 199 199 jmr3927_ioc_reg_out(0, JMR3927_IOC_RESET_ADDR); 200 200 } 201 201 tx3927_pcic_setup(c, JMR3927_SDRAM_SIZE, extarb); 202 + tx3927_setup_pcierr_irq(); 202 203 #endif /* CONFIG_PCI */ 203 204 } 204 205
+2
arch/mips/txx9/rbtx4927/setup.c
··· 103 103 tx4927_report_pciclk(); 104 104 tx4927_pcic_setup(tx4927_pcicptr, c, extarb); 105 105 } 106 + tx4927_setup_pcierr_irq(); 106 107 } 107 108 108 109 static void __init tx4937_pci_setup(void) ··· 150 149 tx4938_report_pciclk(); 151 150 tx4927_pcic_setup(tx4938_pcicptr, c, extarb); 152 151 } 152 + tx4938_setup_pcierr_irq(); 153 153 } 154 154 155 155 static void __init rbtx4927_arch_init(void)
+1
arch/mips/txx9/rbtx4938/setup.c
··· 121 121 register_pci_controller(c); 122 122 tx4927_pcic_setup(tx4938_pcic1ptr, c, 0); 123 123 } 124 + tx4938_setup_pcierr_irq(); 124 125 #endif /* CONFIG_PCI */ 125 126 } 126 127
+7
include/asm-mips/txx9/tx3927.h
··· 236 236 /* see PCI_STATUS_XXX in linux/pci.h */ 237 237 #define PCI_STATUS_NEW_CAP 0x0010 238 238 239 + /* bits for ISTAT/IIM */ 240 + #define TX3927_PCIC_IIM_ALL 0x00001600 241 + 239 242 /* bits for TC */ 240 243 #define TX3927_PCIC_TC_OF16E 0x00000020 241 244 #define TX3927_PCIC_TC_IF8E 0x00000010 242 245 #define TX3927_PCIC_TC_OF8E 0x00000008 246 + 247 + /* bits for TSTAT/TIM */ 248 + #define TX3927_PCIC_TIM_ALL 0x0003ffff 243 249 244 250 /* bits for IOBA/MBA */ 245 251 /* see PCI_BASE_ADDRESS_XXX in linux/pci.h */ ··· 326 320 struct pci_controller; 327 321 void __init tx3927_pcic_setup(struct pci_controller *channel, 328 322 unsigned long sdram_size, int extarb); 323 + void tx3927_setup_pcierr_irq(void); 329 324 330 325 #endif /* __ASM_TXX9_TX3927_H */
+1
include/asm-mips/txx9/tx4927.h
··· 249 249 void tx4927_setup_serial(void); 250 250 int tx4927_report_pciclk(void); 251 251 int tx4927_pciclk66_setup(void); 252 + void tx4927_setup_pcierr_irq(void); 252 253 void tx4927_irq_init(void); 253 254 254 255 #endif /* __ASM_TXX9_TX4927_H */
+3
include/asm-mips/txx9/tx4927pcic.h
··· 10 10 #define __ASM_TXX9_TX4927PCIC_H 11 11 12 12 #include <linux/pci.h> 13 + #include <linux/irqreturn.h> 13 14 14 15 struct tx4927_pcic_reg { 15 16 u32 pciid; ··· 197 196 struct pci_controller *channel, int extarb); 198 197 void tx4927_report_pcic_status(void); 199 198 char *tx4927_pcibios_setup(char *str); 199 + void tx4927_dump_pcic_settings(void); 200 + irqreturn_t tx4927_pcierr_interrupt(int irq, void *dev_id); 200 201 201 202 #endif /* __ASM_TXX9_TX4927PCIC_H */
+1
include/asm-mips/txx9/tx4938.h
··· 285 285 int tx4938_pciclk66_setup(void); 286 286 struct pci_dev; 287 287 int tx4938_pcic1_map_irq(const struct pci_dev *dev, u8 slot); 288 + void tx4938_setup_pcierr_irq(void); 288 289 void tx4938_irq_init(void); 289 290 290 291 #endif