bge: Limit BCM5701 B5 to 32-bit mode
[dragonfly.git] / sys / dev / netif / bge / if_bge.c
index fcd0b89..6f44e62 100644 (file)
@@ -31,8 +31,6 @@
  * THE POSSIBILITY OF SUCH DAMAGE.
  *
  * $FreeBSD: src/sys/dev/bge/if_bge.c,v 1.3.2.39 2005/07/03 03:41:18 silby Exp $
- * $DragonFly: src/sys/dev/netif/bge/if_bge.c,v 1.111 2008/10/22 14:24:24 sephe Exp $
- *
  */
 
 /*
@@ -181,6 +179,8 @@ static const struct bge_type bge_devs[] = {
                "Broadcom BCM5721 Gigabit Ethernet" },
        { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM5722,
                "Broadcom BCM5722 Gigabit Ethernet" },
+       { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM5723,
+               "Broadcom BCM5723 Gigabit Ethernet" },
        { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM5750,
                "Broadcom BCM5750 Gigabit Ethernet" },
        { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM5750M,
@@ -211,6 +211,16 @@ static const struct bge_type bge_devs[] = {
                "Broadcom BCM5755M Gigabit Ethernet" },
        { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM5756,
                "Broadcom BCM5756 Gigabit Ethernet" },
+       { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM5761,
+               "Broadcom BCM5761 Gigabit Ethernet" },
+       { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM5761E,
+               "Broadcom BCM5761E Gigabit Ethernet" },
+       { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM5761S,
+               "Broadcom BCM5761S Gigabit Ethernet" },
+       { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM5761SE,
+               "Broadcom BCM5761SE Gigabit Ethernet" },
+       { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM5764,
+               "Broadcom BCM5764 Gigabit Ethernet" },
        { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM5780,
                "Broadcom BCM5780 Gigabit Ethernet" },
        { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM5780S,
@@ -219,6 +229,12 @@ static const struct bge_type bge_devs[] = {
                "Broadcom BCM5781 Gigabit Ethernet" },
        { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM5782,
                "Broadcom BCM5782 Gigabit Ethernet" },
+       { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM5784,
+               "Broadcom BCM5784 Gigabit Ethernet" },
+       { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM5785F,
+               "Broadcom BCM5785F Gigabit Ethernet" },
+       { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM5785G,
+               "Broadcom BCM5785G Gigabit Ethernet" },
        { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM5786,
                "Broadcom BCM5786 Gigabit Ethernet" },
        { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM5787,
@@ -241,7 +257,14 @@ static const struct bge_type bge_devs[] = {
                "Broadcom BCM5906 Fast Ethernet"},
        { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM5906M,
                "Broadcom BCM5906M Fast Ethernet"},
-
+       { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM57760,
+               "Broadcom BCM57760 Gigabit Ethernet"},
+       { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM57780,
+               "Broadcom BCM57780 Gigabit Ethernet"},
+       { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM57788,
+               "Broadcom BCM57788 Gigabit Ethernet"},
+       { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM57790,
+               "Broadcom BCM57790 Gigabit Ethernet"},
        { PCI_VENDOR_SCHNEIDERKOCH, PCI_PRODUCT_SCHNEIDERKOCH_SK_9DX1,
                "SysKonnect Gigabit Ethernet" },
 
@@ -253,6 +276,7 @@ static const struct bge_type bge_devs[] = {
 #define BGE_IS_5705_PLUS(sc)           ((sc)->bge_flags & BGE_FLAG_5705_PLUS)
 #define BGE_IS_5714_FAMILY(sc)         ((sc)->bge_flags & BGE_FLAG_5714_FAMILY)
 #define BGE_IS_575X_PLUS(sc)           ((sc)->bge_flags & BGE_FLAG_575X_PLUS)
+#define BGE_IS_5755_PLUS(sc)           ((sc)->bge_flags & BGE_FLAG_5755_PLUS)
 
 typedef int    (*bge_eaddr_fcn_t)(struct bge_softc *, uint8_t[]);
 
@@ -372,9 +396,9 @@ TUNABLE_INT("hw.bge.tx_max_coal_bds", &bge_tx_max_coal_bds);
 #define KTR_IF_BGE     KTR_ALL
 #endif
 KTR_INFO_MASTER(if_bge);
-KTR_INFO(KTR_IF_BGE, if_bge, intr, 0, "intr", 0);
-KTR_INFO(KTR_IF_BGE, if_bge, rx_pkt, 1, "rx_pkt", 0);
-KTR_INFO(KTR_IF_BGE, if_bge, tx_pkt, 2, "tx_pkt", 0);
+KTR_INFO(KTR_IF_BGE, if_bge, intr, 0, "intr");
+KTR_INFO(KTR_IF_BGE, if_bge, rx_pkt, 1, "rx_pkt");
+KTR_INFO(KTR_IF_BGE, if_bge, tx_pkt, 2, "tx_pkt");
 #define logif(name)    KTR_LOG(if_bge_ ## name)
 
 static device_method_t bge_methods[] = {
@@ -402,8 +426,8 @@ static DEFINE_CLASS_0(bge, bge_driver, bge_methods, sizeof(struct bge_softc));
 static devclass_t bge_devclass;
 
 DECLARE_DUMMY_MODULE(if_bge);
-DRIVER_MODULE(if_bge, pci, bge_driver, bge_devclass, 0, 0);
-DRIVER_MODULE(miibus, bge, miibus_driver, miibus_devclass, 0, 0);
+DRIVER_MODULE(if_bge, pci, bge_driver, bge_devclass, NULL, NULL);
+DRIVER_MODULE(miibus, bge, miibus_driver, miibus_devclass, NULL, NULL);
 
 static uint32_t
 bge_readmem_ind(struct bge_softc *sc, uint32_t off)
@@ -767,7 +791,7 @@ bge_alloc_jumbo_mem(struct bge_softc *sc)
        error = bge_dma_block_alloc(sc, BGE_JUMBO_RX_RING_SZ,
                                    &sc->bge_cdata.bge_rx_jumbo_ring_tag,
                                    &sc->bge_cdata.bge_rx_jumbo_ring_map,
-                                   (void **)&sc->bge_ldata.bge_rx_jumbo_ring,
+                                   (void *)&sc->bge_ldata.bge_rx_jumbo_ring,
                                    &sc->bge_ldata.bge_rx_jumbo_ring_paddr);
        if (error) {
                if_printf(ifp, "could not create jumbo RX ring\n");
@@ -1164,7 +1188,7 @@ bge_setmulti(struct bge_softc *sc)
                CSR_WRITE_4(sc, BGE_MAR0 + (i * 4), 0);
 
        /* Now program new ones. */
-       LIST_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
+       TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
                if (ifma->ifma_addr->sa_family != AF_LINK)
                        continue;
                h = ether_crc32_le(
@@ -1271,6 +1295,16 @@ bge_chipinit(struct bge_softc *sc)
            BGE_MODECTL_MAC_ATTN_INTR|BGE_MODECTL_HOST_SEND_BDS|
            BGE_MODECTL_TX_NO_PHDR_CSUM);
 
+       /*
+        * BCM5701 B5 have a bug causing data corruption when using
+        * 64-bit DMA reads, which can be terminated early and then
+        * completed later as 32-bit accesses, in combination with
+        * certain bridges.
+        */
+       if (sc->bge_asicrev == BGE_ASICREV_BCM5701 &&
+           sc->bge_chipid == BGE_CHIPID_BCM5701_B5)
+               BGE_SETBIT(sc, BGE_MODE_CTL, BGE_MODECTL_FORCE_PCI32);
+
        /*
         * Disable memory write invalidate.  Apparently it is not supported
         * properly by these devices.
@@ -1614,14 +1648,19 @@ bge_blockinit(struct bge_softc *sc)
 
        /* Turn on write DMA state machine */
        val = BGE_WDMAMODE_ENABLE|BGE_WDMAMODE_ALL_ATTNS;
-       if (sc->bge_asicrev == BGE_ASICREV_BCM5755 ||
-           sc->bge_asicrev == BGE_ASICREV_BCM5787)
+       if (BGE_IS_5755_PLUS(sc))
                val |= (1 << 29);       /* Enable host coalescing bug fix. */
        CSR_WRITE_4(sc, BGE_WDMA_MODE, val);
        DELAY(40);
 
        /* Turn on read DMA state machine */
        val = BGE_RDMAMODE_ENABLE | BGE_RDMAMODE_ALL_ATTNS;
+        if (sc->bge_asicrev == BGE_ASICREV_BCM5784 ||
+            sc->bge_asicrev == BGE_ASICREV_BCM5785 ||
+            sc->bge_asicrev == BGE_ASICREV_BCM57780)
+               val |= BGE_RDMAMODE_BD_SBD_CRPT_ATTN |
+                  BGE_RDMAMODE_MBUF_RBD_CRPT_ATTN |
+                  BGE_RDMAMODE_MBUF_SBD_CRPT_ATTN;
        if (sc->bge_flags & BGE_FLAG_PCIE)
                val |= BGE_RDMAMODE_FIFO_LONG_BURST;
        CSR_WRITE_4(sc, BGE_RDMA_MODE, val);
@@ -1644,7 +1683,10 @@ bge_blockinit(struct bge_softc *sc)
        CSR_WRITE_4(sc, BGE_SBDC_MODE, BGE_SBDCMODE_ENABLE);
 
        /* Turn on send data completion state machine */
-       CSR_WRITE_4(sc, BGE_SDC_MODE, BGE_SDCMODE_ENABLE);
+       val = BGE_SDCMODE_ENABLE;
+       if (sc->bge_asicrev == BGE_ASICREV_BCM5761)
+               val |= BGE_SDCMODE_CDELAY; 
+       CSR_WRITE_4(sc, BGE_SDC_MODE, val);
 
        /* Turn on send data initiator state machine */
        CSR_WRITE_4(sc, BGE_SDI_MODE, BGE_SDIMODE_ENABLE);
@@ -1776,13 +1818,25 @@ bge_attach(device_t dev)
 
        /* Save various chip information */
        sc->bge_chipid =
-           pci_read_config(dev, BGE_PCI_MISC_CTL, 4) &
-           BGE_PCIMISCCTL_ASICREV;
+           pci_read_config(dev, BGE_PCI_MISC_CTL, 4) >>
+           BGE_PCIMISCCTL_ASICREV_SHIFT;
+        if (BGE_ASICREV(sc->bge_chipid) == BGE_ASICREV_USE_PRODID_REG)
+               sc->bge_chipid = pci_read_config(dev, BGE_PCI_PRODID_ASICREV, 4);
        sc->bge_asicrev = BGE_ASICREV(sc->bge_chipid);
        sc->bge_chiprev = BGE_CHIPREV(sc->bge_chipid);
 
        /* Save chipset family. */
        switch (sc->bge_asicrev) {
+       case BGE_ASICREV_BCM5755:
+       case BGE_ASICREV_BCM5761:
+       case BGE_ASICREV_BCM5784:
+       case BGE_ASICREV_BCM5785:
+       case BGE_ASICREV_BCM5787:
+       case BGE_ASICREV_BCM57780:
+           sc->bge_flags |= BGE_FLAG_5755_PLUS | BGE_FLAG_575X_PLUS |
+               BGE_FLAG_5705_PLUS;
+           break;
+
        case BGE_ASICREV_BCM5700:
        case BGE_ASICREV_BCM5701:
        case BGE_ASICREV_BCM5703:
@@ -1798,8 +1852,6 @@ bge_attach(device_t dev)
 
        case BGE_ASICREV_BCM5750:
        case BGE_ASICREV_BCM5752:
-       case BGE_ASICREV_BCM5755:
-       case BGE_ASICREV_BCM5787:
        case BGE_ASICREV_BCM5906:
                sc->bge_flags |= BGE_FLAG_575X_PLUS;
                /* Fall through */
@@ -1835,16 +1887,14 @@ bge_attach(device_t dev)
        if (sc->bge_chipid == BGE_CHIPID_BCM5704_A0)
                sc->bge_flags |= BGE_FLAG_5704_A0_BUG;
 
-       if (BGE_IS_5705_PLUS(sc)) {
+       if (BGE_IS_5705_PLUS(sc) &&
+               !(sc->bge_flags & BGE_FLAG_ADJUST_TRIM)) {
                if (sc->bge_asicrev == BGE_ASICREV_BCM5755 ||
+                   sc->bge_asicrev == BGE_ASICREV_BCM5761 ||
+                   sc->bge_asicrev == BGE_ASICREV_BCM5784 ||
                    sc->bge_asicrev == BGE_ASICREV_BCM5787) {
-                       uint32_t product = pci_get_device(dev);
-
-                       if (product != PCI_PRODUCT_BROADCOM_BCM5722 &&
-                           product != PCI_PRODUCT_BROADCOM_BCM5756)
-                               sc->bge_flags |= BGE_FLAG_JITTER_BUG;
-                       if (product == PCI_PRODUCT_BROADCOM_BCM5755M)
-                               sc->bge_flags |= BGE_FLAG_ADJUST_TRIM;
+                       if (sc->bge_chipid != BGE_CHIPID_BCM5722_A0)
+                           sc->bge_flags |= BGE_FLAG_JITTER_BUG;
                } else if (sc->bge_asicrev != BGE_ASICREV_BCM5906) {
                        sc->bge_flags |= BGE_FLAG_BER_BUG;
                }
@@ -2077,7 +2127,7 @@ bge_attach(device_t dev)
                goto fail;
        }
 
-       ifp->if_cpuid = ithread_cpuid(rman_get_start(sc->bge_irq));
+       ifp->if_cpuid = rman_get_cpuid(sc->bge_irq);
        KKASSERT(ifp->if_cpuid >= 0 && ifp->if_cpuid < ncpus);
 
        return(0);
@@ -2334,14 +2384,11 @@ bge_rxeof(struct bge_softc *sc)
 {
        struct ifnet *ifp;
        int stdcnt = 0, jumbocnt = 0;
-       struct mbuf_chain chain[MAXCPU];
 
        if (sc->bge_rx_saved_considx ==
            sc->bge_ldata.bge_status_block->bge_idx[0].bge_rx_prod_idx)
                return;
 
-       ether_input_chain_init(chain);
-
        ifp = &sc->arpcom.ac_if;
 
        while (sc->bge_rx_saved_considx !=
@@ -2453,11 +2500,9 @@ bge_rxeof(struct bge_softc *sc)
                        m->m_pkthdr.ether_vlantag = vlan_tag;
                        have_tag = vlan_tag = 0;
                }
-               ether_input_chain(ifp, m, NULL, chain);
+               ifp->if_input(ifp, m);
        }
 
-       ether_input_dispatch(chain);
-
        bge_writembx(sc, BGE_MBX_RX_CONS0_LO, sc->bge_rx_saved_considx);
        if (stdcnt)
                bge_writembx(sc, BGE_MBX_RX_STD_PROD_LO, sc->bge_std);
@@ -2716,7 +2761,7 @@ bge_encap(struct bge_softc *sc, struct mbuf **m_head0, uint32_t *txidx)
 
        maxsegs = (BGE_TX_RING_CNT - sc->bge_txcnt) - BGE_NSEG_RSVD;
        KASSERT(maxsegs >= BGE_NSEG_SPARE,
-               ("not enough segments %d\n", maxsegs));
+               ("not enough segments %d", maxsegs));
 
        if (maxsegs > BGE_NSEG_NEW)
                maxsegs = BGE_NSEG_NEW;
@@ -3506,7 +3551,7 @@ bge_dma_alloc(struct bge_softc *sc)
        error = bge_dma_block_alloc(sc, BGE_STD_RX_RING_SZ,
                                    &sc->bge_cdata.bge_rx_std_ring_tag,
                                    &sc->bge_cdata.bge_rx_std_ring_map,
-                                   (void **)&sc->bge_ldata.bge_rx_std_ring,
+                                   (void *)&sc->bge_ldata.bge_rx_std_ring,
                                    &sc->bge_ldata.bge_rx_std_ring_paddr);
        if (error) {
                if_printf(ifp, "could not create std RX ring\n");
@@ -3530,7 +3575,7 @@ bge_dma_alloc(struct bge_softc *sc)
        error = bge_dma_block_alloc(sc, BGE_RX_RTN_RING_SZ(sc),
                                    &sc->bge_cdata.bge_rx_return_ring_tag,
                                    &sc->bge_cdata.bge_rx_return_ring_map,
-                                   (void **)&sc->bge_ldata.bge_rx_return_ring,
+                                   (void *)&sc->bge_ldata.bge_rx_return_ring,
                                    &sc->bge_ldata.bge_rx_return_ring_paddr);
        if (error) {
                if_printf(ifp, "could not create RX ret ring\n");
@@ -3543,7 +3588,7 @@ bge_dma_alloc(struct bge_softc *sc)
        error = bge_dma_block_alloc(sc, BGE_TX_RING_SZ,
                                    &sc->bge_cdata.bge_tx_ring_tag,
                                    &sc->bge_cdata.bge_tx_ring_map,
-                                   (void **)&sc->bge_ldata.bge_tx_ring,
+                                   (void *)&sc->bge_ldata.bge_tx_ring,
                                    &sc->bge_ldata.bge_tx_ring_paddr);
        if (error) {
                if_printf(ifp, "could not create TX ring\n");
@@ -3556,7 +3601,7 @@ bge_dma_alloc(struct bge_softc *sc)
        error = bge_dma_block_alloc(sc, BGE_STATUS_BLK_SZ,
                                    &sc->bge_cdata.bge_status_tag,
                                    &sc->bge_cdata.bge_status_map,
-                                   (void **)&sc->bge_ldata.bge_status_block,
+                                   (void *)&sc->bge_ldata.bge_status_block,
                                    &sc->bge_ldata.bge_status_block_paddr);
        if (error) {
                if_printf(ifp, "could not create status block\n");
@@ -3569,7 +3614,7 @@ bge_dma_alloc(struct bge_softc *sc)
        error = bge_dma_block_alloc(sc, BGE_STATS_SZ,
                                    &sc->bge_cdata.bge_stats_tag,
                                    &sc->bge_cdata.bge_stats_map,
-                                   (void **)&sc->bge_ldata.bge_stats,
+                                   (void *)&sc->bge_ldata.bge_stats,
                                    &sc->bge_ldata.bge_stats_paddr);
        if (error) {
                if_printf(ifp, "could not create stats block\n");