bge: Proper configure PCI-X for BCM5703/5704 devices
authorSepherosa Ziehau <sephe@dragonflybsd.org>
Thu, 28 Jun 2012 06:55:18 +0000 (14:55 +0800)
committerSepherosa Ziehau <sephe@dragonflybsd.org>
Thu, 28 Jun 2012 06:58:40 +0000 (14:58 +0800)
Set maximum read byte count to 2048.  Also disable relaxed ordering
as recommended by data sheet for PCI-X devices.  For PCI-X BCM5704,
set maximum outstanding split transactions to 0 as indicated by
datasheet.

Obtained-from: FreeBSD 204978

sys/dev/netif/bge/if_bge.c
sys/dev/netif/bge/if_bgereg.h

index deeaf39..119ceb0 100644 (file)
@@ -1954,8 +1954,10 @@ bge_attach(device_t dev)
                 * (This bit is not valid on PCI Express controllers.)
                 */
                if ((pci_read_config(sc->bge_dev, BGE_PCI_PCISTATE, 4) &
-                   BGE_PCISTATE_PCI_BUSMODE) == 0)
+                   BGE_PCISTATE_PCI_BUSMODE) == 0) {
                        sc->bge_flags |= BGE_FLAG_PCIX;
+                       sc->bge_pcixcap = pci_get_pcixcap_ptr(sc->bge_dev);
+               }
        }
 
        device_printf(dev, "CHIP ID 0x%08x; "
@@ -2325,6 +2327,29 @@ bge_reset(struct bge_softc *sc)
        pci_write_config(dev, BGE_PCI_CMD, command, 4);
        write_op(sc, BGE_MISC_CFG, (65 << 1));
 
+       /*
+        * Disable PCI-X relaxed ordering to ensure status block update
+        * comes first then packet buffer DMA. Otherwise driver may
+        * read stale status block.
+        */
+       if (sc->bge_flags & BGE_FLAG_PCIX) {
+               uint16_t devctl;
+
+               devctl = pci_read_config(dev,
+                   sc->bge_pcixcap + PCIXR_COMMAND, 2);
+               devctl &= ~PCIXM_COMMAND_ERO;
+               if (sc->bge_asicrev == BGE_ASICREV_BCM5703) {
+                       devctl &= ~PCIXM_COMMAND_MAX_READ;
+                       devctl |= PCIXM_COMMAND_MAX_READ_2048;
+               } else if (sc->bge_asicrev == BGE_ASICREV_BCM5704) {
+                       devctl &= ~(PCIXM_COMMAND_MAX_SPLITS |
+                           PCIXM_COMMAND_MAX_READ);
+                       devctl |= PCIXM_COMMAND_MAX_READ_2048;
+               }
+               pci_write_config(dev, sc->bge_pcixcap + PCIXR_COMMAND,
+                   devctl, 2);
+       }
+
        /* Enable memory arbiter. */
        if (BGE_IS_5714_FAMILY(sc)) {
                uint32_t val;
index 1dcb4f7..4668b0a 100644 (file)
@@ -2451,6 +2451,7 @@ struct bge_softc {
        struct resource         *bge_irq;
        struct resource         *bge_res;
        struct ifmedia          bge_ifmedia;    /* TBI media info */
+       int                     bge_pcixcap;
        uint32_t                bge_flags;
 #define BGE_FLAG_TBI           0x00000001
 #define BGE_FLAG_JUMBO         0x00000002