Commit 455cc256 authored by Atsushi Nemoto's avatar Atsushi Nemoto Committed by Ralf Baechle

[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: default avatarAtsushi Nemoto <anemo@mba.ocn.ne.jp>
Signed-off-by: default avatarRalf Baechle <ralf@linux-mips.org>
parent 07517529
...@@ -37,8 +37,11 @@ ...@@ -37,8 +37,11 @@
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/interrupt.h>
#include <asm/addrspace.h> #include <asm/addrspace.h>
#include <asm/txx9irq.h>
#include <asm/txx9/pci.h>
#include <asm/txx9/tx3927.h> #include <asm/txx9/tx3927.h>
static int mkaddr(struct pci_bus *bus, unsigned char devfn, unsigned char where) 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,3 +197,34 @@ void __init tx3927_pcic_setup(struct pci_controller *channel,
PCI_COMMAND_PARITY | PCI_COMMAND_SERR; PCI_COMMAND_PARITY | PCI_COMMAND_SERR;
local_irq_restore(flags); local_irq_restore(flags);
} }
static irqreturn_t tx3927_pcierr_interrupt(int irq, void *dev_id)
{
struct pt_regs *regs = get_irq_regs();
if (txx9_pci_err_action != TXX9_PCI_ERR_IGNORE) {
printk(KERN_WARNING "PCI error interrupt at 0x%08lx.\n",
regs->cp0_epc);
printk(KERN_WARNING "pcistat:%02x, lbstat:%04lx\n",
tx3927_pcicptr->pcistat, tx3927_pcicptr->lbstat);
}
if (txx9_pci_err_action != TXX9_PCI_ERR_PANIC) {
/* clear all pci errors */
tx3927_pcicptr->pcistat |= TX3927_PCIC_PCISTATIM_ALL;
tx3927_pcicptr->istat = TX3927_PCIC_IIM_ALL;
tx3927_pcicptr->tstat = TX3927_PCIC_TIM_ALL;
tx3927_pcicptr->lbstat = TX3927_PCIC_LBIM_ALL;
return IRQ_HANDLED;
}
console_verbose();
panic("PCI error.");
}
void __init tx3927_setup_pcierr_irq(void)
{
if (request_irq(TXX9_IRQ_BASE + TX3927_IR_PCI,
tx3927_pcierr_interrupt,
IRQF_DISABLED, "PCI error",
(void *)TX3927_PCIC_REG))
printk(KERN_WARNING "Failed to request irq for PCIERR\n");
}
...@@ -16,6 +16,8 @@ ...@@ -16,6 +16,8 @@
* option) any later version. * option) any later version.
*/ */
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/interrupt.h>
#include <asm/txx9/pci.h>
#include <asm/txx9/tx4927pcic.h> #include <asm/txx9/tx4927pcic.h>
static struct { static struct {
...@@ -431,6 +433,66 @@ void tx4927_report_pcic_status(void) ...@@ -431,6 +433,66 @@ void tx4927_report_pcic_status(void)
} }
} }
static void tx4927_dump_pcic_settings1(struct tx4927_pcic_reg __iomem *pcicptr)
{
int i;
__u32 __iomem *preg = (__u32 __iomem *)pcicptr;
printk(KERN_INFO "tx4927 pcic (0x%p) settings:", pcicptr);
for (i = 0; i < sizeof(struct tx4927_pcic_reg); i += 4, preg++) {
if (i % 32 == 0) {
printk(KERN_CONT "\n");
printk(KERN_INFO "%04x:", i);
}
/* skip registers with side-effects */
if (i == offsetof(struct tx4927_pcic_reg, g2pintack)
|| i == offsetof(struct tx4927_pcic_reg, g2pspc)
|| i == offsetof(struct tx4927_pcic_reg, g2pcfgadrs)
|| i == offsetof(struct tx4927_pcic_reg, g2pcfgdata)) {
printk(KERN_CONT " XXXXXXXX");
continue;
}
printk(KERN_CONT " %08x", __raw_readl(preg));
}
printk(KERN_CONT "\n");
}
void tx4927_dump_pcic_settings(void)
{
int i;
for (i = 0; i < ARRAY_SIZE(pcicptrs); i++) {
if (pcicptrs[i].pcicptr)
tx4927_dump_pcic_settings1(pcicptrs[i].pcicptr);
}
}
irqreturn_t tx4927_pcierr_interrupt(int irq, void *dev_id)
{
struct pt_regs *regs = get_irq_regs();
struct tx4927_pcic_reg __iomem *pcicptr =
(struct tx4927_pcic_reg __iomem *)(unsigned long)dev_id;
if (txx9_pci_err_action != TXX9_PCI_ERR_IGNORE) {
printk(KERN_WARNING "PCIERR interrupt at 0x%0*lx\n",
(int)(2 * sizeof(unsigned long)), regs->cp0_epc);
tx4927_report_pcic_status1(pcicptr);
}
if (txx9_pci_err_action != TXX9_PCI_ERR_PANIC) {
/* clear all pci errors */
__raw_writel((__raw_readl(&pcicptr->pcistatus) & 0x0000ffff)
| (TX4927_PCIC_PCISTATUS_ALL << 16),
&pcicptr->pcistatus);
__raw_writel(TX4927_PCIC_G2PSTATUS_ALL, &pcicptr->g2pstatus);
__raw_writel(TX4927_PCIC_PBASTATUS_ALL, &pcicptr->pbastatus);
__raw_writel(TX4927_PCIC_PCICSTATUS_ALL, &pcicptr->pcicstatus);
return IRQ_HANDLED;
}
console_verbose();
tx4927_dump_pcic_settings1(pcicptr);
panic("PCI error.");
}
#ifdef CONFIG_TOSHIBA_FPCIB0 #ifdef CONFIG_TOSHIBA_FPCIB0
static void __init tx4927_quirk_slc90e66_bridge(struct pci_dev *dev) static void __init tx4927_quirk_slc90e66_bridge(struct pci_dev *dev)
{ {
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/interrupt.h>
#include <asm/txx9/generic.h> #include <asm/txx9/generic.h>
#include <asm/txx9/tx4927.h> #include <asm/txx9/tx4927.h>
...@@ -81,3 +82,12 @@ int __init tx4927_pciclk66_setup(void) ...@@ -81,3 +82,12 @@ int __init tx4927_pciclk66_setup(void)
pciclk = -1; pciclk = -1;
return pciclk; return pciclk;
} }
void __init tx4927_setup_pcierr_irq(void)
{
if (request_irq(TXX9_IRQ_BASE + TX4927_IR_PCIERR,
tx4927_pcierr_interrupt,
IRQF_DISABLED, "PCI error",
(void *)TX4927_PCIC_REG))
printk(KERN_WARNING "Failed to request irq for PCIERR\n");
}
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/interrupt.h>
#include <asm/txx9/generic.h> #include <asm/txx9/generic.h>
#include <asm/txx9/tx4938.h> #include <asm/txx9/tx4938.h>
...@@ -132,3 +133,12 @@ int tx4938_pcic1_map_irq(const struct pci_dev *dev, u8 slot) ...@@ -132,3 +133,12 @@ int tx4938_pcic1_map_irq(const struct pci_dev *dev, u8 slot)
} }
return -1; return -1;
} }
void __init tx4938_setup_pcierr_irq(void)
{
if (request_irq(TXX9_IRQ_BASE + TX4938_IR_PCIERR,
tx4927_pcierr_interrupt,
IRQF_DISABLED, "PCI error",
(void *)TX4927_PCIC_REG))
printk(KERN_WARNING "Failed to request irq for PCIERR\n");
}
...@@ -103,22 +103,6 @@ static int jmr3927_irq_dispatch(int pending) ...@@ -103,22 +103,6 @@ static int jmr3927_irq_dispatch(int pending)
return irq; return irq;
} }
#ifdef CONFIG_PCI
static irqreturn_t jmr3927_pcierr_interrupt(int irq, void *dev_id)
{
printk(KERN_WARNING "PCI error interrupt (irq 0x%x).\n", irq);
printk(KERN_WARNING "pcistat:%02x, lbstat:%04lx\n",
tx3927_pcicptr->pcistat, tx3927_pcicptr->lbstat);
return IRQ_HANDLED;
}
static struct irqaction pcierr_action = {
.handler = jmr3927_pcierr_interrupt,
.mask = CPU_MASK_NONE,
.name = "PCI error",
};
#endif
static void __init jmr3927_irq_init(void); static void __init jmr3927_irq_init(void);
void __init jmr3927_irq_setup(void) void __init jmr3927_irq_setup(void)
...@@ -143,10 +127,6 @@ void __init jmr3927_irq_setup(void) ...@@ -143,10 +127,6 @@ void __init jmr3927_irq_setup(void)
/* setup IOC interrupt 1 (PCI, MODEM) */ /* setup IOC interrupt 1 (PCI, MODEM) */
set_irq_chained_handler(JMR3927_IRQ_IOCINT, handle_simple_irq); set_irq_chained_handler(JMR3927_IRQ_IOCINT, handle_simple_irq);
#ifdef CONFIG_PCI
setup_irq(JMR3927_IRQ_IRC_PCI, &pcierr_action);
#endif
/* enable all CPU interrupt bits. */ /* enable all CPU interrupt bits. */
set_c0_status(ST0_IM); /* IE bit is still 0. */ set_c0_status(ST0_IM); /* IE bit is still 0. */
} }
......
...@@ -199,6 +199,7 @@ static void __init jmr3927_pci_setup(void) ...@@ -199,6 +199,7 @@ static void __init jmr3927_pci_setup(void)
jmr3927_ioc_reg_out(0, JMR3927_IOC_RESET_ADDR); jmr3927_ioc_reg_out(0, JMR3927_IOC_RESET_ADDR);
} }
tx3927_pcic_setup(c, JMR3927_SDRAM_SIZE, extarb); tx3927_pcic_setup(c, JMR3927_SDRAM_SIZE, extarb);
tx3927_setup_pcierr_irq();
#endif /* CONFIG_PCI */ #endif /* CONFIG_PCI */
} }
......
...@@ -103,6 +103,7 @@ static void __init tx4927_pci_setup(void) ...@@ -103,6 +103,7 @@ static void __init tx4927_pci_setup(void)
tx4927_report_pciclk(); tx4927_report_pciclk();
tx4927_pcic_setup(tx4927_pcicptr, c, extarb); tx4927_pcic_setup(tx4927_pcicptr, c, extarb);
} }
tx4927_setup_pcierr_irq();
} }
static void __init tx4937_pci_setup(void) static void __init tx4937_pci_setup(void)
...@@ -149,6 +150,7 @@ static void __init tx4937_pci_setup(void) ...@@ -149,6 +150,7 @@ static void __init tx4937_pci_setup(void)
tx4938_report_pciclk(); tx4938_report_pciclk();
tx4927_pcic_setup(tx4938_pcicptr, c, extarb); tx4927_pcic_setup(tx4938_pcicptr, c, extarb);
} }
tx4938_setup_pcierr_irq();
} }
static void __init rbtx4927_arch_init(void) static void __init rbtx4927_arch_init(void)
......
...@@ -121,6 +121,7 @@ static void __init rbtx4938_pci_setup(void) ...@@ -121,6 +121,7 @@ static void __init rbtx4938_pci_setup(void)
register_pci_controller(c); register_pci_controller(c);
tx4927_pcic_setup(tx4938_pcic1ptr, c, 0); tx4927_pcic_setup(tx4938_pcic1ptr, c, 0);
} }
tx4938_setup_pcierr_irq();
#endif /* CONFIG_PCI */ #endif /* CONFIG_PCI */
} }
......
...@@ -236,11 +236,17 @@ struct tx3927_ccfg_reg { ...@@ -236,11 +236,17 @@ struct tx3927_ccfg_reg {
/* see PCI_STATUS_XXX in linux/pci.h */ /* see PCI_STATUS_XXX in linux/pci.h */
#define PCI_STATUS_NEW_CAP 0x0010 #define PCI_STATUS_NEW_CAP 0x0010
/* bits for ISTAT/IIM */
#define TX3927_PCIC_IIM_ALL 0x00001600
/* bits for TC */ /* bits for TC */
#define TX3927_PCIC_TC_OF16E 0x00000020 #define TX3927_PCIC_TC_OF16E 0x00000020
#define TX3927_PCIC_TC_IF8E 0x00000010 #define TX3927_PCIC_TC_IF8E 0x00000010
#define TX3927_PCIC_TC_OF8E 0x00000008 #define TX3927_PCIC_TC_OF8E 0x00000008
/* bits for TSTAT/TIM */
#define TX3927_PCIC_TIM_ALL 0x0003ffff
/* bits for IOBA/MBA */ /* bits for IOBA/MBA */
/* see PCI_BASE_ADDRESS_XXX in linux/pci.h */ /* see PCI_BASE_ADDRESS_XXX in linux/pci.h */
...@@ -320,5 +326,6 @@ struct tx3927_ccfg_reg { ...@@ -320,5 +326,6 @@ struct tx3927_ccfg_reg {
struct pci_controller; struct pci_controller;
void __init tx3927_pcic_setup(struct pci_controller *channel, void __init tx3927_pcic_setup(struct pci_controller *channel,
unsigned long sdram_size, int extarb); unsigned long sdram_size, int extarb);
void tx3927_setup_pcierr_irq(void);
#endif /* __ASM_TXX9_TX3927_H */ #endif /* __ASM_TXX9_TX3927_H */
...@@ -249,6 +249,7 @@ void tx4927_time_init(unsigned int tmrnr); ...@@ -249,6 +249,7 @@ void tx4927_time_init(unsigned int tmrnr);
void tx4927_setup_serial(void); void tx4927_setup_serial(void);
int tx4927_report_pciclk(void); int tx4927_report_pciclk(void);
int tx4927_pciclk66_setup(void); int tx4927_pciclk66_setup(void);
void tx4927_setup_pcierr_irq(void);
void tx4927_irq_init(void); void tx4927_irq_init(void);
#endif /* __ASM_TXX9_TX4927_H */ #endif /* __ASM_TXX9_TX4927_H */
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#define __ASM_TXX9_TX4927PCIC_H #define __ASM_TXX9_TX4927PCIC_H
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/irqreturn.h>
struct tx4927_pcic_reg { struct tx4927_pcic_reg {
u32 pciid; u32 pciid;
...@@ -196,5 +197,7 @@ void __init tx4927_pcic_setup(struct tx4927_pcic_reg __iomem *pcicptr, ...@@ -196,5 +197,7 @@ void __init tx4927_pcic_setup(struct tx4927_pcic_reg __iomem *pcicptr,
struct pci_controller *channel, int extarb); struct pci_controller *channel, int extarb);
void tx4927_report_pcic_status(void); void tx4927_report_pcic_status(void);
char *tx4927_pcibios_setup(char *str); char *tx4927_pcibios_setup(char *str);
void tx4927_dump_pcic_settings(void);
irqreturn_t tx4927_pcierr_interrupt(int irq, void *dev_id);
#endif /* __ASM_TXX9_TX4927PCIC_H */ #endif /* __ASM_TXX9_TX4927PCIC_H */
...@@ -285,6 +285,7 @@ void tx4938_report_pci1clk(void); ...@@ -285,6 +285,7 @@ void tx4938_report_pci1clk(void);
int tx4938_pciclk66_setup(void); int tx4938_pciclk66_setup(void);
struct pci_dev; struct pci_dev;
int tx4938_pcic1_map_irq(const struct pci_dev *dev, u8 slot); int tx4938_pcic1_map_irq(const struct pci_dev *dev, u8 slot);
void tx4938_setup_pcierr_irq(void);
void tx4938_irq_init(void); void tx4938_irq_init(void);
#endif #endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment