diff options
| author | Atsushi Nemoto <anemo@mba.ocn.ne.jp> | 2008-07-25 10:01:35 -0400 |
|---|---|---|
| committer | Ralf Baechle <ralf@linux-mips.org> | 2008-07-30 16:54:38 -0400 |
| commit | 455cc256eb23915100e203fb33ee143afd127954 (patch) | |
| tree | 1ad0c410fef0f7d82587347c3d3e4d4c9646dcee /arch/mips/pci | |
| parent | 07517529225ae4ce770271f83d8cd1004733a01d (diff) | |
[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>
Diffstat (limited to 'arch/mips/pci')
| -rw-r--r-- | arch/mips/pci/ops-tx3927.c | 34 | ||||
| -rw-r--r-- | arch/mips/pci/ops-tx4927.c | 62 | ||||
| -rw-r--r-- | arch/mips/pci/pci-tx4927.c | 10 | ||||
| -rw-r--r-- | arch/mips/pci/pci-tx4938.c | 10 |
4 files changed, 116 insertions, 0 deletions
diff --git a/arch/mips/pci/ops-tx3927.c b/arch/mips/pci/ops-tx3927.c index c6bd79e71e26..31c150196595 100644 --- a/arch/mips/pci/ops-tx3927.c +++ b/arch/mips/pci/ops-tx3927.c | |||
| @@ -37,8 +37,11 @@ | |||
| 37 | #include <linux/pci.h> | 37 | #include <linux/pci.h> |
| 38 | #include <linux/kernel.h> | 38 | #include <linux/kernel.h> |
| 39 | #include <linux/init.h> | 39 | #include <linux/init.h> |
| 40 | #include <linux/interrupt.h> | ||
| 40 | 41 | ||
| 41 | #include <asm/addrspace.h> | 42 | #include <asm/addrspace.h> |
| 43 | #include <asm/txx9irq.h> | ||
| 44 | #include <asm/txx9/pci.h> | ||
| 42 | #include <asm/txx9/tx3927.h> | 45 | #include <asm/txx9/tx3927.h> |
| 43 | 46 | ||
| 44 | static int mkaddr(struct pci_bus *bus, unsigned char devfn, unsigned char where) | 47 | static int mkaddr(struct pci_bus *bus, unsigned char devfn, unsigned char where) |
| @@ -194,3 +197,34 @@ void __init tx3927_pcic_setup(struct pci_controller *channel, | |||
| 194 | PCI_COMMAND_PARITY | PCI_COMMAND_SERR; | 197 | PCI_COMMAND_PARITY | PCI_COMMAND_SERR; |
| 195 | local_irq_restore(flags); | 198 | local_irq_restore(flags); |
| 196 | } | 199 | } |
| 200 | |||
| 201 | static irqreturn_t tx3927_pcierr_interrupt(int irq, void *dev_id) | ||
| 202 | { | ||
| 203 | struct pt_regs *regs = get_irq_regs(); | ||
| 204 | |||
| 205 | if (txx9_pci_err_action != TXX9_PCI_ERR_IGNORE) { | ||
| 206 | printk(KERN_WARNING "PCI error interrupt at 0x%08lx.\n", | ||
| 207 | regs->cp0_epc); | ||
| 208 | printk(KERN_WARNING "pcistat:%02x, lbstat:%04lx\n", | ||
| 209 | tx3927_pcicptr->pcistat, tx3927_pcicptr->lbstat); | ||
| 210 | } | ||
| 211 | if (txx9_pci_err_action != TXX9_PCI_ERR_PANIC) { | ||
| 212 | /* clear all pci errors */ | ||
| 213 | tx3927_pcicptr->pcistat |= TX3927_PCIC_PCISTATIM_ALL; | ||
| 214 | tx3927_pcicptr->istat = TX3927_PCIC_IIM_ALL; | ||
| 215 | tx3927_pcicptr->tstat = TX3927_PCIC_TIM_ALL; | ||
| 216 | tx3927_pcicptr->lbstat = TX3927_PCIC_LBIM_ALL; | ||
| 217 | return IRQ_HANDLED; | ||
| 218 | } | ||
| 219 | console_verbose(); | ||
| 220 | panic("PCI error."); | ||
| 221 | } | ||
| 222 | |||
| 223 | void __init tx3927_setup_pcierr_irq(void) | ||
| 224 | { | ||
| 225 | if (request_irq(TXX9_IRQ_BASE + TX3927_IR_PCI, | ||
| 226 | tx3927_pcierr_interrupt, | ||
| 227 | IRQF_DISABLED, "PCI error", | ||
| 228 | (void *)TX3927_PCIC_REG)) | ||
| 229 | printk(KERN_WARNING "Failed to request irq for PCIERR\n"); | ||
| 230 | } | ||
diff --git a/arch/mips/pci/ops-tx4927.c b/arch/mips/pci/ops-tx4927.c index 038e311b069d..5989e747527f 100644 --- a/arch/mips/pci/ops-tx4927.c +++ b/arch/mips/pci/ops-tx4927.c | |||
| @@ -16,6 +16,8 @@ | |||
| 16 | * option) any later version. | 16 | * option) any later version. |
| 17 | */ | 17 | */ |
| 18 | #include <linux/kernel.h> | 18 | #include <linux/kernel.h> |
| 19 | #include <linux/interrupt.h> | ||
| 20 | #include <asm/txx9/pci.h> | ||
| 19 | #include <asm/txx9/tx4927pcic.h> | 21 | #include <asm/txx9/tx4927pcic.h> |
| 20 | 22 | ||
| 21 | static struct { | 23 | static struct { |
| @@ -431,6 +433,66 @@ void tx4927_report_pcic_status(void) | |||
| 431 | } | 433 | } |
| 432 | } | 434 | } |
| 433 | 435 | ||
| 436 | static void tx4927_dump_pcic_settings1(struct tx4927_pcic_reg __iomem *pcicptr) | ||
| 437 | { | ||
| 438 | int i; | ||
| 439 | __u32 __iomem *preg = (__u32 __iomem *)pcicptr; | ||
| 440 | |||
| 441 | printk(KERN_INFO "tx4927 pcic (0x%p) settings:", pcicptr); | ||
| 442 | for (i = 0; i < sizeof(struct tx4927_pcic_reg); i += 4, preg++) { | ||
| 443 | if (i % 32 == 0) { | ||
| 444 | printk(KERN_CONT "\n"); | ||
| 445 | printk(KERN_INFO "%04x:", i); | ||
| 446 | } | ||
| 447 | /* skip registers with side-effects */ | ||
| 448 | if (i == offsetof(struct tx4927_pcic_reg, g2pintack) | ||
| 449 | || i == offsetof(struct tx4927_pcic_reg, g2pspc) | ||
| 450 | || i == offsetof(struct tx4927_pcic_reg, g2pcfgadrs) | ||
| 451 | || i == offsetof(struct tx4927_pcic_reg, g2pcfgdata)) { | ||
| 452 | printk(KERN_CONT " XXXXXXXX"); | ||
| 453 | continue; | ||
| 454 | } | ||
| 455 | printk(KERN_CONT " %08x", __raw_readl(preg)); | ||
| 456 | } | ||
| 457 | printk(KERN_CONT "\n"); | ||
| 458 | } | ||
| 459 | |||
| 460 | void tx4927_dump_pcic_settings(void) | ||
| 461 | { | ||
| 462 | int i; | ||
| 463 | |||
| 464 | for (i = 0; i < ARRAY_SIZE(pcicptrs); i++) { | ||
| 465 | if (pcicptrs[i].pcicptr) | ||
| 466 | tx4927_dump_pcic_settings1(pcicptrs[i].pcicptr); | ||
| 467 | } | ||
| 468 | } | ||
| 469 | |||
| 470 | irqreturn_t tx4927_pcierr_interrupt(int irq, void *dev_id) | ||
| 471 | { | ||
| 472 | struct pt_regs *regs = get_irq_regs(); | ||
| 473 | struct tx4927_pcic_reg __iomem *pcicptr = | ||
| 474 | (struct tx4927_pcic_reg __iomem *)(unsigned long)dev_id; | ||
| 475 | |||
| 476 | if (txx9_pci_err_action != TXX9_PCI_ERR_IGNORE) { | ||
| 477 | printk(KERN_WARNING "PCIERR interrupt at 0x%0*lx\n", | ||
| 478 | (int)(2 * sizeof(unsigned long)), regs->cp0_epc); | ||
| 479 | tx4927_report_pcic_status1(pcicptr); | ||
| 480 | } | ||
| 481 | if (txx9_pci_err_action != TXX9_PCI_ERR_PANIC) { | ||
| 482 | /* clear all pci errors */ | ||
| 483 | __raw_writel((__raw_readl(&pcicptr->pcistatus) & 0x0000ffff) | ||
| 484 | | (TX4927_PCIC_PCISTATUS_ALL << 16), | ||
| 485 | &pcicptr->pcistatus); | ||
| 486 | __raw_writel(TX4927_PCIC_G2PSTATUS_ALL, &pcicptr->g2pstatus); | ||
| 487 | __raw_writel(TX4927_PCIC_PBASTATUS_ALL, &pcicptr->pbastatus); | ||
| 488 | __raw_writel(TX4927_PCIC_PCICSTATUS_ALL, &pcicptr->pcicstatus); | ||
| 489 | return IRQ_HANDLED; | ||
| 490 | } | ||
| 491 | console_verbose(); | ||
| 492 | tx4927_dump_pcic_settings1(pcicptr); | ||
| 493 | panic("PCI error."); | ||
| 494 | } | ||
| 495 | |||
| 434 | #ifdef CONFIG_TOSHIBA_FPCIB0 | 496 | #ifdef CONFIG_TOSHIBA_FPCIB0 |
| 435 | static void __init tx4927_quirk_slc90e66_bridge(struct pci_dev *dev) | 497 | static void __init tx4927_quirk_slc90e66_bridge(struct pci_dev *dev) |
| 436 | { | 498 | { |
diff --git a/arch/mips/pci/pci-tx4927.c b/arch/mips/pci/pci-tx4927.c index 27e86a09dd41..aaa900596792 100644 --- a/arch/mips/pci/pci-tx4927.c +++ b/arch/mips/pci/pci-tx4927.c | |||
| @@ -15,6 +15,7 @@ | |||
| 15 | #include <linux/init.h> | 15 | #include <linux/init.h> |
| 16 | #include <linux/pci.h> | 16 | #include <linux/pci.h> |
| 17 | #include <linux/kernel.h> | 17 | #include <linux/kernel.h> |
| 18 | #include <linux/interrupt.h> | ||
| 18 | #include <asm/txx9/generic.h> | 19 | #include <asm/txx9/generic.h> |
| 19 | #include <asm/txx9/tx4927.h> | 20 | #include <asm/txx9/tx4927.h> |
| 20 | 21 | ||
| @@ -81,3 +82,12 @@ int __init tx4927_pciclk66_setup(void) | |||
| 81 | pciclk = -1; | 82 | pciclk = -1; |
| 82 | return pciclk; | 83 | return pciclk; |
| 83 | } | 84 | } |
| 85 | |||
| 86 | void __init tx4927_setup_pcierr_irq(void) | ||
| 87 | { | ||
| 88 | if (request_irq(TXX9_IRQ_BASE + TX4927_IR_PCIERR, | ||
| 89 | tx4927_pcierr_interrupt, | ||
| 90 | IRQF_DISABLED, "PCI error", | ||
| 91 | (void *)TX4927_PCIC_REG)) | ||
| 92 | printk(KERN_WARNING "Failed to request irq for PCIERR\n"); | ||
| 93 | } | ||
diff --git a/arch/mips/pci/pci-tx4938.c b/arch/mips/pci/pci-tx4938.c index e5375511c2b7..60e2c52c2c5e 100644 --- a/arch/mips/pci/pci-tx4938.c +++ b/arch/mips/pci/pci-tx4938.c | |||
| @@ -15,6 +15,7 @@ | |||
| 15 | #include <linux/init.h> | 15 | #include <linux/init.h> |
| 16 | #include <linux/pci.h> | 16 | #include <linux/pci.h> |
| 17 | #include <linux/kernel.h> | 17 | #include <linux/kernel.h> |
| 18 | #include <linux/interrupt.h> | ||
| 18 | #include <asm/txx9/generic.h> | 19 | #include <asm/txx9/generic.h> |
| 19 | #include <asm/txx9/tx4938.h> | 20 | #include <asm/txx9/tx4938.h> |
| 20 | 21 | ||
| @@ -132,3 +133,12 @@ int tx4938_pcic1_map_irq(const struct pci_dev *dev, u8 slot) | |||
| 132 | } | 133 | } |
| 133 | return -1; | 134 | return -1; |
| 134 | } | 135 | } |
| 136 | |||
| 137 | void __init tx4938_setup_pcierr_irq(void) | ||
| 138 | { | ||
| 139 | if (request_irq(TXX9_IRQ_BASE + TX4938_IR_PCIERR, | ||
| 140 | tx4927_pcierr_interrupt, | ||
| 141 | IRQF_DISABLED, "PCI error", | ||
| 142 | (void *)TX4927_PCIC_REG)) | ||
| 143 | printk(KERN_WARNING "Failed to request irq for PCIERR\n"); | ||
| 144 | } | ||
