Date: Mon, 26 Mar 2012 04:39:11 +0000 (UTC) From: Pyun YongHyeon <yongari@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-7@freebsd.org Subject: svn commit: r233497 - stable/7/sys/dev/bge Message-ID: <201203260439.q2Q4dB4v015099@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: yongari Date: Mon Mar 26 04:39:10 2012 New Revision: 233497 URL: http://svn.freebsd.org/changeset/base/233497 Log: MFC r232848: 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 > Modified: stable/7/sys/dev/bge/if_bge.c stable/7/sys/dev/bge/if_bgereg.h Directory Properties: stable/7/sys/ (props changed) stable/7/sys/cddl/contrib/opensolaris/ (props changed) stable/7/sys/contrib/dev/acpica/ (props changed) stable/7/sys/contrib/pf/ (props changed) Modified: stable/7/sys/dev/bge/if_bge.c ============================================================================== --- stable/7/sys/dev/bge/if_bge.c Mon Mar 26 04:37:42 2012 (r233496) +++ stable/7/sys/dev/bge/if_bge.c Mon Mar 26 04:39:10 2012 (r233497) @@ -380,6 +380,8 @@ static void bge_dma_free(struct bge_soft 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[]); @@ -639,6 +641,8 @@ bge_writembx(struct bge_softc *sc, int o 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); } /* @@ -2613,10 +2617,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), @@ -2779,6 +2783,56 @@ bge_can_use_msi(struct bge_softc *sc) } 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) { struct ifnet *ifp; @@ -3098,6 +3152,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 * normal operation. Modified: stable/7/sys/dev/bge/if_bgereg.h ============================================================================== --- stable/7/sys/dev/bge/if_bgereg.h Mon Mar 26 04:37:42 2012 (r233496) +++ stable/7/sys/dev/bge/if_bgereg.h Mon Mar 26 04:39:10 2012 (r233497) @@ -2828,6 +2828,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
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201203260439.q2Q4dB4v015099>