mirror of
https://git.FreeBSD.org/src.git
synced 2024-12-23 11:18:54 +00:00
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
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=232848
@ -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,
|
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 *);
|
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_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_mem(struct bge_softc *, uint8_t[]);
|
||||||
static int bge_get_eaddr_nvram(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;
|
off += BGE_LPMBX_IRQ0_HI - BGE_MBX_IRQ0_HI;
|
||||||
|
|
||||||
CSR_WRITE_4(sc, off, val);
|
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
|
* XXX
|
||||||
* watchdog timeout issue was observed on BCM5704 which
|
* watchdog timeout issue was observed on BCM5704 which
|
||||||
* lives behind PCI-X bridge(e.g AMD 8131 PCI-X bridge).
|
* lives behind PCI-X bridge(e.g AMD 8131 PCI-X bridge).
|
||||||
* Limiting DMA address space to 32bits seems to address
|
* Both limiting DMA address space to 32bits and flushing
|
||||||
* it.
|
* mailbox write seem to address the issue.
|
||||||
*/
|
*/
|
||||||
if (sc->bge_flags & BGE_FLAG_PCIX)
|
if (sc->bge_pcixcap != 0)
|
||||||
lowaddr = BUS_SPACE_MAXADDR_32BIT;
|
lowaddr = BUS_SPACE_MAXADDR_32BIT;
|
||||||
}
|
}
|
||||||
error = bus_dma_tag_create(bus_get_dma_tag(sc->bge_dev), 1, 0, lowaddr,
|
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);
|
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
|
static int
|
||||||
bge_attach(device_t dev)
|
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))
|
if (BGE_IS_5714_FAMILY(sc) && (sc->bge_flags & BGE_FLAG_PCIX))
|
||||||
sc->bge_flags |= BGE_FLAG_40BIT_BUG;
|
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
|
* Allocate the interrupt, using MSI if possible. These devices
|
||||||
* support 8 MSI messages, but only the first one is used in
|
* 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_RX_ALIGNBUG 0x04000000
|
||||||
#define BGE_FLAG_SHORT_DMA_BUG 0x08000000
|
#define BGE_FLAG_SHORT_DMA_BUG 0x08000000
|
||||||
#define BGE_FLAG_4K_RDMA_BUG 0x10000000
|
#define BGE_FLAG_4K_RDMA_BUG 0x10000000
|
||||||
|
#define BGE_FLAG_MBOX_REORDER 0x20000000
|
||||||
uint32_t bge_phy_flags;
|
uint32_t bge_phy_flags;
|
||||||
#define BGE_PHY_NO_WIRESPEED 0x00000001
|
#define BGE_PHY_NO_WIRESPEED 0x00000001
|
||||||
#define BGE_PHY_ADC_BUG 0x00000002
|
#define BGE_PHY_ADC_BUG 0x00000002
|
||||||
|
Loading…
Reference in New Issue
Block a user