[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>
This commit is contained in:
committed by
Ralf Baechle
parent
0751752922
commit
455cc256eb
@ -37,8 +37,11 @@
|
||||
#include <linux/pci.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/interrupt.h>
|
||||
|
||||
#include <asm/addrspace.h>
|
||||
#include <asm/txx9irq.h>
|
||||
#include <asm/txx9/pci.h>
|
||||
#include <asm/txx9/tx3927.h>
|
||||
|
||||
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,
|
||||
PCI_COMMAND_PARITY | PCI_COMMAND_SERR;
|
||||
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 @@
|
||||
* option) any later version.
|
||||
*/
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <asm/txx9/pci.h>
|
||||
#include <asm/txx9/tx4927pcic.h>
|
||||
|
||||
static struct {
|
||||
@ -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
|
||||
static void __init tx4927_quirk_slc90e66_bridge(struct pci_dev *dev)
|
||||
{
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include <linux/init.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <asm/txx9/generic.h>
|
||||
#include <asm/txx9/tx4927.h>
|
||||
|
||||
@ -81,3 +82,12 @@ int __init tx4927_pciclk66_setup(void)
|
||||
pciclk = -1;
|
||||
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 @@
|
||||
#include <linux/init.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <asm/txx9/generic.h>
|
||||
#include <asm/txx9/tx4938.h>
|
||||
|
||||
@ -132,3 +133,12 @@ int tx4938_pcic1_map_irq(const struct pci_dev *dev, u8 slot)
|
||||
}
|
||||
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");
|
||||
}
|
||||
|
Reference in New Issue
Block a user