Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files. =================================================================== RCS file: /ftp/cvs/cvsroot/src/sys/dev/pci/if_bge.c,v rcsdiff: /ftp/cvs/cvsroot/src/sys/dev/pci/if_bge.c,v: warning: Unknown phrases like `commitid ...;' are present. retrieving revision 1.109.8.1 retrieving revision 1.109.8.2 diff -u -p -r1.109.8.1 -r1.109.8.2 --- src/sys/dev/pci/if_bge.c 2006/10/22 06:06:16 1.109.8.1 +++ src/sys/dev/pci/if_bge.c 2006/12/10 07:17:43 1.109.8.2 @@ -1,4 +1,4 @@ -/* $NetBSD: if_bge.c,v 1.109.8.1 2006/10/22 06:06:16 yamt Exp $ */ +/* $NetBSD: if_bge.c,v 1.109.8.2 2006/12/10 07:17:43 yamt Exp $ */ /* * Copyright (c) 2001 Wind River Systems @@ -79,7 +79,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: if_bge.c,v 1.109.8.1 2006/10/22 06:06:16 yamt Exp $"); +__KERNEL_RCSID(0, "$NetBSD: if_bge.c,v 1.109.8.2 2006/12/10 07:17:43 yamt Exp $"); #include "bpfilter.h" #include "vlan.h" @@ -270,9 +270,9 @@ int bge_tso_debug = 0; * (defined here until the thought is done). */ #define BGE_IS_5714_FAMILY(sc) \ - (BGE_ASICREV(sc->bge_chipid) == BGE_ASICREV_BCM5714 || \ + (BGE_ASICREV(sc->bge_chipid) == BGE_ASICREV_BCM5714_A0 || \ BGE_ASICREV(sc->bge_chipid) == BGE_ASICREV_BCM5780 || \ - BGE_ASICREV(sc->bge_chipid) == BGE_ASICREV_BCM5715 ) + BGE_ASICREV(sc->bge_chipid) == BGE_ASICREV_BCM5714 ) #define BGE_IS_5750_OR_BEYOND(sc) \ (BGE_ASICREV(sc->bge_chipid) == BGE_ASICREV_BCM5750 || \ @@ -669,7 +669,7 @@ bge_update_all_threshes(int lvl) * Handle events that have triggered interrupts. */ static void -bge_handle_events(struct bge_softc *sc __unused) +bge_handle_events(struct bge_softc *sc) { return; @@ -794,7 +794,7 @@ bge_jalloc(struct bge_softc *sc) * Release a jumbo buffer. */ static void -bge_jfree(struct mbuf *m, caddr_t buf, size_t size __unused, void *arg) +bge_jfree(struct mbuf *m, caddr_t buf, size_t size, void *arg) { struct bge_jpool_entry *entry; struct bge_softc *sc; @@ -1881,6 +1881,10 @@ static const struct bge_revision { BGE_QUIRK_LINK_STATE_BROKEN|BGE_QUIRK_5700_COMMON, "BCM5700 B2" }, + { BGE_CHIPID_BCM5700_B3, + BGE_QUIRK_LINK_STATE_BROKEN|BGE_QUIRK_5700_COMMON, + "BCM5700 B3" }, + /* This is treated like a BCM5700 Bx */ { BGE_CHIPID_BCM5700_ALTIMA, BGE_QUIRK_LINK_STATE_BROKEN|BGE_QUIRK_5700_COMMON, @@ -1899,7 +1903,7 @@ static const struct bge_revision { "BCM5701 B0" }, { BGE_CHIPID_BCM5701_B2, - BGE_QUIRK_PCIX_DMA_ALIGN_BUG, + BGE_QUIRK_ONLY_PHY_1|BGE_QUIRK_PCIX_DMA_ALIGN_BUG, "BCM5701 B2" }, { BGE_CHIPID_BCM5701_B5, @@ -1922,6 +1926,10 @@ static const struct bge_revision { BGE_QUIRK_ONLY_PHY_1, "BCM5703 A3" }, + { BGE_CHIPID_BCM5703_B0, + BGE_QUIRK_ONLY_PHY_1, + "BCM5703 B0" }, + { BGE_CHIPID_BCM5704_A0, BGE_QUIRK_ONLY_PHY_1|BGE_QUIRK_FEWER_MBUFS, "BCM5704 A0" }, @@ -1956,7 +1964,7 @@ static const struct bge_revision { { BGE_CHIPID_BCM5750_A0, BGE_QUIRK_ONLY_PHY_1|BGE_QUIRK_5705_CORE, - "BCM5750 A1" }, + "BCM5750 A0" }, { BGE_CHIPID_BCM5750_A1, BGE_QUIRK_ONLY_PHY_1|BGE_QUIRK_5705_CORE, @@ -1966,6 +1974,18 @@ static const struct bge_revision { BGE_QUIRK_ONLY_PHY_1|BGE_QUIRK_5705_CORE, "BCM5751 A1" }, + { BGE_CHIPID_BCM5752_A0, + BGE_QUIRK_ONLY_PHY_1|BGE_QUIRK_5705_CORE, + "BCM5752 A0" }, + + { BGE_CHIPID_BCM5752_A1, + BGE_QUIRK_ONLY_PHY_1|BGE_QUIRK_5705_CORE, + "BCM5752 A1" }, + + { BGE_CHIPID_BCM5752_A2, + BGE_QUIRK_ONLY_PHY_1|BGE_QUIRK_5705_CORE, + "BCM5752 A2" }, + { 0, 0, NULL } }; @@ -1998,6 +2018,10 @@ static const struct bge_revision bge_maj BGE_QUIRK_ONLY_PHY_1|BGE_QUIRK_5705_CORE, "unknown BCM575x family" }, + { BGE_ASICREV_BCM5714_A0, + BGE_QUIRK_ONLY_PHY_1|BGE_QUIRK_5705_CORE, + "unknown BCM5714" }, + { BGE_ASICREV_BCM5714, BGE_QUIRK_ONLY_PHY_1|BGE_QUIRK_5705_CORE, "unknown BCM5714" }, @@ -2011,10 +2035,6 @@ static const struct bge_revision bge_maj BGE_QUIRK_ONLY_PHY_1|BGE_QUIRK_5705_CORE, "unknown BCM5780" }, - { BGE_ASICREV_BCM5715, - BGE_QUIRK_ONLY_PHY_1|BGE_QUIRK_5705_CORE, - "unknown BCM5715" }, - { 0, 0, NULL } @@ -2097,8 +2117,8 @@ static const struct bge_product { "Broadcom BCM5703X Gigabit Ethernet", }, { PCI_VENDOR_BROADCOM, - PCI_PRODUCT_BROADCOM_BCM5703A3, - "Broadcom BCM5703A3 Gigabit Ethernet", + PCI_PRODUCT_BROADCOM_BCM5703_ALT, + "Broadcom BCM5703 Gigabit Ethernet", }, { PCI_VENDOR_BROADCOM, @@ -2119,11 +2139,11 @@ static const struct bge_product { "Broadcom BCM5705K Gigabit Ethernet", }, { PCI_VENDOR_BROADCOM, - PCI_PRODUCT_BROADCOM_BCM5705_ALT, - "Broadcom BCM5705 Gigabit Ethernet", + PCI_PRODUCT_BROADCOM_BCM5705M, + "Broadcom BCM5705M Gigabit Ethernet", }, { PCI_VENDOR_BROADCOM, - PCI_PRODUCT_BROADCOM_BCM5705M, + PCI_PRODUCT_BROADCOM_BCM5705M_ALT, "Broadcom BCM5705M Gigabit Ethernet", }, @@ -2166,6 +2186,11 @@ static const struct bge_product { "Broadcom BCM5752 Gigabit Ethernet", }, + { PCI_VENDOR_BROADCOM, + PCI_PRODUCT_BROADCOM_BCM5752M, + "Broadcom BCM5752M Gigabit Ethernet", + }, + { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM5780, "Broadcom BCM5780 Gigabit Ethernet", @@ -2229,7 +2254,7 @@ bge_lookup(const struct pci_attach_args } static int -bge_setpowerstate(struct bge_softc *sc __unused, int powerlevel __unused) +bge_setpowerstate(struct bge_softc *sc, int powerlevel) { #ifdef NOTYET u_int32_t pm_ctl = 0; @@ -2284,7 +2309,7 @@ bge_setpowerstate(struct bge_softc *sc _ * we'll always announce the right product name. */ static int -bge_probe(device_t parent __unused, cfdata_t match __unused, void *aux) +bge_probe(device_t parent, cfdata_t match, void *aux) { struct pci_attach_args *pa = (struct pci_attach_args *)aux; @@ -2295,7 +2320,7 @@ bge_probe(device_t parent __unused, cfda } static void -bge_attach(device_t parent __unused, device_t self, void *aux) +bge_attach(device_t parent, device_t self, void *aux) { struct bge_softc *sc = (struct bge_softc *)self; struct pci_attach_args *pa = aux; @@ -2539,7 +2564,7 @@ bge_attach(device_t parent __unused, dev ifp->if_watchdog = bge_watchdog; IFQ_SET_MAXLEN(&ifp->if_snd, max(BGE_TX_RING_CNT - 1, IFQ_MAXLEN)); IFQ_SET_READY(&ifp->if_snd); - DPRINTFN(5, ("bcopy\n")); + DPRINTFN(5, ("strcpy if_xname\n")); strcpy(ifp->if_xname, sc->bge_dev.dv_xname); if ((sc->bge_quirks & BGE_QUIRK_CSUM_BROKEN) == 0) @@ -2692,6 +2717,13 @@ bge_reset(struct bge_softc *sc) BGE_PCIMISCCTL_INDIRECT_ACCESS|BGE_PCIMISCCTL_MASK_PCI_INTR| BGE_HIF_SWAP_OPTIONS|BGE_PCIMISCCTL_PCISTATE_RW); + /* + * Disable the firmware fastboot feature on 5752 ASIC + * to avoid firmware timeout. + */ + if (BGE_ASICREV(sc->bge_chipid) == BGE_ASICREV_BCM5752) + CSR_WRITE_4(sc, BGE_FASTBOOT_PC, 0); + val = BGE_MISCCFG_RESET_CORE_CLOCKS | (65<<1); /* * XXX: from FreeBSD/Linux; no documentation @@ -3274,7 +3306,7 @@ bge_cksum_pad(struct mbuf *pkt) /* if there's only the packet-header and we can pad there, use it. */ if (pkt->m_pkthdr.len == pkt->m_len && - !M_READONLY(pkt) && M_TRAILINGSPACE(pkt) >= padlen) { + M_TRAILINGSPACE(pkt) >= padlen) { last = pkt; } else { /* @@ -3283,13 +3315,11 @@ bge_cksum_pad(struct mbuf *pkt) * (thus perhaps avoiding the bcm5700 dma-min bug). */ for (last = pkt; last->m_next != NULL; last = last->m_next) { - (void) 0; /* do nothing*/ + continue; /* do nothing */ } /* `last' now points to last in chain. */ - if (!M_READONLY(last) && M_TRAILINGSPACE(last) >= padlen) { - (void) 0; /* we can pad here, in-place. */ - } else { + if (M_TRAILINGSPACE(last) < padlen) { /* Allocate new empty mbuf, pad it. Compact later. */ struct mbuf *n; MGET(n, M_DONTWAIT, MT_DATA); @@ -3299,10 +3329,9 @@ bge_cksum_pad(struct mbuf *pkt) } } -#ifdef DEBUG - /*KASSERT(M_WRITABLE(last), ("to-pad mbuf not writeable\n"));*/ - KASSERT(M_TRAILINGSPACE(last) >= padlen /*, ("insufficient space to pad\n")*/ ); -#endif + KDASSERT(!M_READONLY(last)); + KDASSERT(M_TRAILINGSPACE(last) >= padlen); + /* Now zero the pad area, to avoid the bge cksum-assist bug */ memset(mtod(last, caddr_t) + last->m_len, 0, padlen); last->m_len += padlen; @@ -3340,11 +3369,8 @@ bge_compact_dma_runt(struct mbuf *pkt) */ /* Internal frag. If fits in prev, copy it there. */ - if (prev && !M_READONLY(prev) && - M_TRAILINGSPACE(prev) >= m->m_len) { - bcopy(m->m_data, - prev->m_data+prev->m_len, - mlen); + if (prev && M_TRAILINGSPACE(prev) >= m->m_len) { + memcpy(prev->m_data + prev->m_len, m->m_data, mlen); prev->m_len += mlen; m->m_len = 0; /* XXX stitch chain */ @@ -3352,14 +3378,13 @@ bge_compact_dma_runt(struct mbuf *pkt) m = prev; continue; } - else if (m->m_next != NULL && !M_READONLY(m) && + else if (m->m_next != NULL && M_TRAILINGSPACE(m) >= shortfall && m->m_next->m_len >= (8 + shortfall)) { /* m is writable and have enough data in next, pull up. */ - bcopy(m->m_next->m_data, - m->m_data+m->m_len, - shortfall); + memcpy(m->m_data + m->m_len, m->m_next->m_data, + shortfall); m->m_len += shortfall; m->m_next->m_len -= shortfall; m->m_next->m_data += shortfall; @@ -3401,13 +3426,15 @@ bge_compact_dma_runt(struct mbuf *pkt) ("runt %d +prev %d too big\n", m->m_len, shortfall)*/); /* first copy the data we're stealing from prev */ - bcopy(prev->m_data + newprevlen, n->m_data, shortfall); + memcpy(n->m_data, prev->m_data + newprevlen, + shortfall); /* update prev->m_len accordingly */ prev->m_len -= shortfall; /* copy data from runt m */ - bcopy(m->m_data, n->m_data + shortfall, m->m_len); + memcpy(n->m_data + shortfall, m->m_data, + m->m_len); /* n holds what we stole from prev, plus m */ n->m_len = shortfall + m->m_len; @@ -3434,7 +3461,7 @@ static int bge_encap(struct bge_softc *sc, struct mbuf *m_head, u_int32_t *txidx) { struct bge_tx_bd *f = NULL; - u_int32_t frag, cur, cnt = 0; + u_int32_t frag, cur; u_int16_t csum_flags = 0; u_int16_t txbd_tso_flags = 0; struct txdmamap_pool_entry *dma; @@ -3632,6 +3659,16 @@ doit: if (error) { return(ENOBUFS); } + /* + * Sanity check: avoid coming within 16 descriptors + * of the end of the ring. + */ + if (dmamap->dm_nsegs > (BGE_TX_RING_CNT - sc->bge_txcnt - 16)) { + BGE_TSO_PRINTF(("%s: " + " dmamap_load_mbuf too close to ring wrap\n", + sc->bge_dev.dv_xname)); + goto fail_unload; + } mtag = sc->ethercom.ec_nvlans ? m_tag_find(m_head, PACKET_TAG_VLAN, NULL) : NULL; @@ -3672,25 +3709,14 @@ doit: } else { f->bge_vlan_tag = 0; } - /* - * Sanity check: avoid coming within 16 descriptors - * of the end of the ring. - */ - if ((BGE_TX_RING_CNT - (sc->bge_txcnt + cnt)) < 16) { - BGE_TSO_PRINTF(("%s: " - " dmamap_load_mbuf too close to ring wrap\n", - sc->bge_dev.dv_xname)); - return(ENOBUFS); - } cur = frag; BGE_INC(frag, BGE_TX_RING_CNT); - cnt++; } if (i < dmamap->dm_nsegs) { BGE_TSO_PRINTF(("%s: reached %d < dm_nsegs %d\n", sc->bge_dev.dv_xname, i, dmamap->dm_nsegs)); - return ENOBUFS; + goto fail_unload; } bus_dmamap_sync(sc->bge_dmatag, dmamap, 0, dmamap->dm_mapsize, @@ -3700,18 +3726,23 @@ doit: BGE_TSO_PRINTF(("%s: frag %d = wrapped id %d?\n", sc->bge_dev.dv_xname, frag, sc->bge_tx_saved_considx)); - return(ENOBUFS); + goto fail_unload; } sc->bge_rdata->bge_tx_ring[cur].bge_flags |= BGE_TXBDFLAG_END; sc->bge_cdata.bge_tx_chain[cur] = m_head; SLIST_REMOVE_HEAD(&sc->txdma_list, link); sc->txdma[cur] = dma; - sc->bge_txcnt += cnt; + sc->bge_txcnt += dmamap->dm_nsegs; *txidx = frag; return(0); + + fail_unload: + bus_dmamap_unload(sc->bge_dmatag, dmamap); + + return ENOBUFS; } /*