Commit 88d3c6a5 authored by Kai Germaschewski's avatar Kai Germaschewski Committed by Kai Germaschewski

[PATCH] 2.5.3 ISDN work around buggy hw

the appended patch works around a bug in the PLX9050 chip. This chip is
used in various PCI ISDN adapters (it's an PCI interface chip) and has
an erratum when the BAR 0/1 has bit 7 set (the size of the region is
0x80, so aligning it to 0x80 is legal and really happens for people).

This workaround has been tested by a user who hit this problem with a
Gazel card. Basically the same fix has been done for Elsa cards, but it's
untested.
parent 4e8cbe30
...@@ -396,7 +396,8 @@ elsa_interrupt_ipac(int intno, void *dev_id, struct pt_regs *regs) ...@@ -396,7 +396,8 @@ elsa_interrupt_ipac(int intno, void *dev_id, struct pt_regs *regs)
} }
if (cs->subtyp == ELSA_QS1000PCI || cs->subtyp == ELSA_QS3000PCI) { if (cs->subtyp == ELSA_QS1000PCI || cs->subtyp == ELSA_QS3000PCI) {
val = bytein(cs->hw.elsa.cfg + 0x4c); /* PCI IRQ */ val = bytein(cs->hw.elsa.cfg + 0x4c); /* PCI IRQ */
if (!(val & ELSA_PCI_IRQ_MASK)) if (!test_bit(FLG_BUGGY_PLX9050, &cs->HW_Flags) &&
!(val & ELSA_PCI_IRQ_MASK))
return; return;
} }
#if ARCOFI_USE #if ARCOFI_USE
...@@ -868,7 +869,7 @@ setup_elsa(struct IsdnCard *card) ...@@ -868,7 +869,7 @@ setup_elsa(struct IsdnCard *card)
{ {
long flags; long flags;
int bytecnt; int bytecnt;
u_char val; u_char val, pci_rev;
struct IsdnCardState *cs = card->cs; struct IsdnCardState *cs = card->cs;
char tmp[64]; char tmp[64];
...@@ -992,6 +993,7 @@ setup_elsa(struct IsdnCard *card) ...@@ -992,6 +993,7 @@ setup_elsa(struct IsdnCard *card)
cs->irq = dev_qs1000->irq; cs->irq = dev_qs1000->irq;
cs->hw.elsa.cfg = pci_resource_start(dev_qs1000, 1); cs->hw.elsa.cfg = pci_resource_start(dev_qs1000, 1);
cs->hw.elsa.base = pci_resource_start(dev_qs1000, 3); cs->hw.elsa.base = pci_resource_start(dev_qs1000, 3);
pci_read_config_byte(dev_qs1000, PCI_REVISION_ID, &pci_rev);
} else if ((dev_qs3000 = pci_find_device(PCI_VENDOR_ID_ELSA, } else if ((dev_qs3000 = pci_find_device(PCI_VENDOR_ID_ELSA,
PCI_DEVICE_ID_ELSA_QS3000, dev_qs3000))) { PCI_DEVICE_ID_ELSA_QS3000, dev_qs3000))) {
if (pci_enable_device(dev_qs3000)) if (pci_enable_device(dev_qs3000))
...@@ -1000,6 +1002,7 @@ setup_elsa(struct IsdnCard *card) ...@@ -1000,6 +1002,7 @@ setup_elsa(struct IsdnCard *card)
cs->irq = dev_qs3000->irq; cs->irq = dev_qs3000->irq;
cs->hw.elsa.cfg = pci_resource_start(dev_qs3000, 1); cs->hw.elsa.cfg = pci_resource_start(dev_qs3000, 1);
cs->hw.elsa.base = pci_resource_start(dev_qs3000, 3); cs->hw.elsa.base = pci_resource_start(dev_qs3000, 3);
pci_read_config_byte(dev_qs1000, PCI_REVISION_ID, &pci_rev);
} else { } else {
printk(KERN_WARNING "Elsa: No PCI card found\n"); printk(KERN_WARNING "Elsa: No PCI card found\n");
return(0); return(0);
...@@ -1013,15 +1016,9 @@ setup_elsa(struct IsdnCard *card) ...@@ -1013,15 +1016,9 @@ setup_elsa(struct IsdnCard *card)
printk(KERN_WARNING "Elsa: No IO-Adr for PCI card found\n"); printk(KERN_WARNING "Elsa: No IO-Adr for PCI card found\n");
return(0); return(0);
} }
if ((cs->hw.elsa.cfg & 0xff) || (cs->hw.elsa.base & 0xf)) { if (cs->hw.elsa.cfg & 0x80 && pci_rev == 1) {
printk(KERN_WARNING "Elsa: You may have a wrong PCI bios\n"); printk(KERN_INFO "Elsa: PLX9050 rev1 workaround activated");
printk(KERN_WARNING "Elsa: If your system hangs now, read\n"); set_bit(FLG_BUGGY_PLX9050, &cs->HW_Flags);
printk(KERN_WARNING "Elsa: Documentation/isdn/README.HiSax\n");
printk(KERN_WARNING "Elsa: Waiting 5 sec to sync discs\n");
save_flags(flags);
sti();
HZDELAY(500); /* wait 500*10 ms */
restore_flags(flags);
} }
cs->hw.elsa.ale = cs->hw.elsa.base; cs->hw.elsa.ale = cs->hw.elsa.base;
cs->hw.elsa.isac = cs->hw.elsa.base +1; cs->hw.elsa.isac = cs->hw.elsa.base +1;
......
...@@ -382,12 +382,16 @@ reset_gazel(struct IsdnCardState *cs) ...@@ -382,12 +382,16 @@ reset_gazel(struct IsdnCardState *cs)
outb(INT_ISAC_EN + INT_HSCX_EN + INT_PCI_EN, addr + PLX_INCSR); outb(INT_ISAC_EN + INT_HSCX_EN + INT_PCI_EN, addr + PLX_INCSR);
break; break;
case R753: case R753:
if (test_bit(FLG_BUGGY_PLX9050, &cs->HW_Flags))
/* we can't read, assume the default */
plxcntrl = 0x18784db6;
else
plxcntrl = inl(addr + PLX_CNTRL); plxcntrl = inl(addr + PLX_CNTRL);
plxcntrl |= (RESET_9050 + RESET_GAZEL); plxcntrl |= (RESET_9050 + RESET_GAZEL);
outl(plxcntrl, addr + PLX_CNTRL); outl(plxcntrl, addr + PLX_CNTRL);
plxcntrl &= ~(RESET_9050 + RESET_GAZEL);
WriteISAC(cs, IPAC_POTA2 - 0x80, 0x20); WriteISAC(cs, IPAC_POTA2 - 0x80, 0x20);
HZDELAY(4); HZDELAY(4);
plxcntrl &= ~(RESET_9050 + RESET_GAZEL);
outl(plxcntrl, addr + PLX_CNTRL); outl(plxcntrl, addr + PLX_CNTRL);
HZDELAY(10); HZDELAY(10);
WriteISAC(cs, IPAC_POTA2 - 0x80, 0x00); WriteISAC(cs, IPAC_POTA2 - 0x80, 0x00);
...@@ -549,6 +553,7 @@ setup_gazelpci(struct IsdnCardState *cs) ...@@ -549,6 +553,7 @@ setup_gazelpci(struct IsdnCardState *cs)
u_int pci_ioaddr0 = 0, pci_ioaddr1 = 0; u_int pci_ioaddr0 = 0, pci_ioaddr1 = 0;
u_char pci_irq = 0, found; u_char pci_irq = 0, found;
u_int nbseek, seekcard; u_int nbseek, seekcard;
u_char pci_rev;
printk(KERN_WARNING "Gazel: PCI card automatic recognition\n"); printk(KERN_WARNING "Gazel: PCI card automatic recognition\n");
...@@ -623,6 +628,18 @@ setup_gazelpci(struct IsdnCardState *cs) ...@@ -623,6 +628,18 @@ setup_gazelpci(struct IsdnCardState *cs)
printk(KERN_INFO printk(KERN_INFO
"Gazel: config irq:%d ipac:0x%X cfg:0x%X\n", "Gazel: config irq:%d ipac:0x%X cfg:0x%X\n",
cs->irq, cs->hw.gazel.ipac, cs->hw.gazel.cfg_reg); cs->irq, cs->hw.gazel.ipac, cs->hw.gazel.cfg_reg);
/*
* Erratum for PLX9050, revision 1:
* If bit 7 of BAR 0/1 is set, local config registers
* can not be read (write is okay)
*/
if (cs->hw.gazel.cfg_reg & 0x80) {
pci_read_config_byte(dev_tel, PCI_REVISION_ID, &pci_rev);
if (pci_rev == 1) {
printk(KERN_INFO "Gazel: PLX9050 rev1 workaround activated");
set_bit(FLG_BUGGY_PLX9050, &cs->HW_Flags);
}
}
break; break;
} }
......
...@@ -859,6 +859,7 @@ struct icc_chip { ...@@ -859,6 +859,7 @@ struct icc_chip {
#define FLG_ARCOFI_TIMER 8 #define FLG_ARCOFI_TIMER 8
#define FLG_ARCOFI_ERROR 9 #define FLG_ARCOFI_ERROR 9
#define FLG_HW_L1_UINT 10 #define FLG_HW_L1_UINT 10
#define FLG_BUGGY_PLX9050 11
struct IsdnCardState { struct IsdnCardState {
unsigned char typ; unsigned char typ;
......
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