Add workaround for PCI-X BCM5704 controller that live behind
AMD-8131 PCI-X bridge. The bridge seems to reorder write access to mailbox registers such that it caused watchdog timeouts by out-of-order TX completions. Tested by: Michael L. Squires <mikes <> siralan dot org > Reviewed by: jhb
This commit is contained in:
parent
2a0fa68aca
commit
062af0b00e
@ -380,6 +380,8 @@ static void bge_dma_free(struct bge_softc *);
|
||||
static int bge_dma_ring_alloc(struct bge_softc *, bus_size_t, bus_size_t,
|
||||
bus_dma_tag_t *, uint8_t **, bus_dmamap_t *, bus_addr_t *, const char *);
|
||||
|
||||
static int bge_mbox_reorder(struct bge_softc *);
|
||||
|
||||
static int bge_get_eaddr_fw(struct bge_softc *sc, uint8_t ether_addr[]);
|
||||
static int bge_get_eaddr_mem(struct bge_softc *, uint8_t[]);
|
||||
static int bge_get_eaddr_nvram(struct bge_softc *, uint8_t[]);
|
||||
@ -635,6 +637,8 @@ bge_writembx(struct bge_softc *sc, int off, int val)
|
||||
off += BGE_LPMBX_IRQ0_HI - BGE_MBX_IRQ0_HI;
|
||||
|
||||
CSR_WRITE_4(sc, off, val);
|
||||
if ((sc->bge_flags & BGE_FLAG_MBOX_REORDER) != 0)
|
||||
CSR_READ_4(sc, off);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -2584,10 +2588,10 @@ bge_dma_alloc(struct bge_softc *sc)
|
||||
* XXX
|
||||
* watchdog timeout issue was observed on BCM5704 which
|
||||
* lives behind PCI-X bridge(e.g AMD 8131 PCI-X bridge).
|
||||
* Limiting DMA address space to 32bits seems to address
|
||||
* it.
|
||||
* Both limiting DMA address space to 32bits and flushing
|
||||
* mailbox write seem to address the issue.
|
||||
*/
|
||||
if (sc->bge_flags & BGE_FLAG_PCIX)
|
||||
if (sc->bge_pcixcap != 0)
|
||||
lowaddr = BUS_SPACE_MAXADDR_32BIT;
|
||||
}
|
||||
error = bus_dma_tag_create(bus_get_dma_tag(sc->bge_dev), 1, 0, lowaddr,
|
||||
@ -2749,6 +2753,56 @@ bge_can_use_msi(struct bge_softc *sc)
|
||||
return (can_use_msi);
|
||||
}
|
||||
|
||||
static int
|
||||
bge_mbox_reorder(struct bge_softc *sc)
|
||||
{
|
||||
/* Lists of PCI bridges that are known to reorder mailbox writes. */
|
||||
static const struct mbox_reorder {
|
||||
const uint16_t vendor;
|
||||
const uint16_t device;
|
||||
const char *desc;
|
||||
} const mbox_reorder_lists[] = {
|
||||
{ 0x1022, 0x7450, "AMD-8131 PCI-X Bridge" },
|
||||
};
|
||||
devclass_t pci, pcib;
|
||||
device_t bus, dev;
|
||||
int count, i;
|
||||
|
||||
count = sizeof(mbox_reorder_lists) / sizeof(mbox_reorder_lists[0]);
|
||||
pci = devclass_find("pci");
|
||||
pcib = devclass_find("pcib");
|
||||
dev = sc->bge_dev;
|
||||
bus = device_get_parent(dev);
|
||||
for (;;) {
|
||||
dev = device_get_parent(bus);
|
||||
bus = device_get_parent(dev);
|
||||
device_printf(sc->bge_dev, "dev : %s%d, bus : %s%d\n",
|
||||
device_get_name(dev), device_get_unit(dev),
|
||||
device_get_name(bus), device_get_unit(bus));
|
||||
if (device_get_devclass(dev) != pcib)
|
||||
break;
|
||||
for (i = 0; i < count; i++) {
|
||||
device_printf(sc->bge_dev,
|
||||
"probing dev : %s%d, vendor : 0x%04x "
|
||||
"device : 0x%04x\n",
|
||||
device_get_name(dev), device_get_unit(dev),
|
||||
pci_get_vendor(dev), pci_get_device(dev));
|
||||
if (pci_get_vendor(dev) ==
|
||||
mbox_reorder_lists[i].vendor &&
|
||||
pci_get_device(dev) ==
|
||||
mbox_reorder_lists[i].device) {
|
||||
device_printf(sc->bge_dev,
|
||||
"enabling MBOX workaround for %s\n",
|
||||
mbox_reorder_lists[i].desc);
|
||||
return (1);
|
||||
}
|
||||
}
|
||||
if (device_get_devclass(bus) != pci)
|
||||
break;
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
bge_attach(device_t dev)
|
||||
{
|
||||
@ -3068,6 +3122,16 @@ bge_attach(device_t dev)
|
||||
*/
|
||||
if (BGE_IS_5714_FAMILY(sc) && (sc->bge_flags & BGE_FLAG_PCIX))
|
||||
sc->bge_flags |= BGE_FLAG_40BIT_BUG;
|
||||
/*
|
||||
* Some PCI-X bridges are known to trigger write reordering to
|
||||
* the mailbox registers. Typical phenomena is watchdog timeouts
|
||||
* caused by out-of-order TX completions. Enable workaround for
|
||||
* PCI-X devices that live behind these bridges.
|
||||
* Note, PCI-X controllers can run in PCI mode so we can't use
|
||||
* BGE_FLAG_PCIX flag to detect PCI-X controllers.
|
||||
*/
|
||||
if (sc->bge_pcixcap != 0 && bge_mbox_reorder(sc) != 0)
|
||||
sc->bge_flags |= BGE_FLAG_MBOX_REORDER;
|
||||
/*
|
||||
* Allocate the interrupt, using MSI if possible. These devices
|
||||
* support 8 MSI messages, but only the first one is used in
|
||||
|
@ -2818,6 +2818,7 @@ struct bge_softc {
|
||||
#define BGE_FLAG_RX_ALIGNBUG 0x04000000
|
||||
#define BGE_FLAG_SHORT_DMA_BUG 0x08000000
|
||||
#define BGE_FLAG_4K_RDMA_BUG 0x10000000
|
||||
#define BGE_FLAG_MBOX_REORDER 0x20000000
|
||||
uint32_t bge_phy_flags;
|
||||
#define BGE_PHY_NO_WIRESPEED 0x00000001
|
||||
#define BGE_PHY_ADC_BUG 0x00000002
|
||||
|
Loading…
Reference in New Issue
Block a user