Date: Wed, 27 Oct 2010 17:20:19 +0000 (UTC) From: Pyun YongHyeon <yongari@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r214428 - head/sys/dev/bge Message-ID: <201010271720.o9RHKJYK016013@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: yongari Date: Wed Oct 27 17:20:19 2010 New Revision: 214428 URL: http://svn.freebsd.org/changeset/base/214428 Log: Add initial BCM5718 family support. The BCM5718 family includes the dual port BCM5717 and BCM5718 devices which are intended for mainstream workstation and entry-level server designs and represents the twelfth generation of NetXtreme Ethernet controllers. This family is the successor to the BCM5714/BCM5715 family and supports IPv4/IPv6 checksum offloading, TSO, VLAN hardware tagging, jumbo frames, MSI/MSIX, IOV, RSS and TSS. This change set supports all hardware features except IOV and RSS/TSS. Unlike its predecessors, only extended RX buffer descriptors can be posted to the jumbo producer ring. Single RX buffer descriptors for jumbo frame are not supported. RSS requires a more substantial set of changes and will apply to a larger set of NetXtreme devices so RSS/TSS multi-queue support will be implemented in a future releases. Special thanks to Broadcom who kindly sent a sample board to me and to davidch who gave provided the initial support code. Submitted by: davidch (initial version) HW donated by: Broadcom Modified: head/sys/dev/bge/if_bge.c head/sys/dev/bge/if_bgereg.h Modified: head/sys/dev/bge/if_bge.c ============================================================================== --- head/sys/dev/bge/if_bge.c Wed Oct 27 17:16:40 2010 (r214427) +++ head/sys/dev/bge/if_bge.c Wed Oct 27 17:20:19 2010 (r214428) @@ -169,6 +169,8 @@ static const struct bge_type { { BCOM_VENDORID, BCOM_DEVICEID_BCM5714S }, { BCOM_VENDORID, BCOM_DEVICEID_BCM5715 }, { BCOM_VENDORID, BCOM_DEVICEID_BCM5715S }, + { BCOM_VENDORID, BCOM_DEVICEID_BCM5717 }, + { BCOM_VENDORID, BCOM_DEVICEID_BCM5718 }, { BCOM_VENDORID, BCOM_DEVICEID_BCM5720 }, { BCOM_VENDORID, BCOM_DEVICEID_BCM5721 }, { BCOM_VENDORID, BCOM_DEVICEID_BCM5722 }, @@ -289,6 +291,8 @@ static const struct bge_revision { { BGE_CHIPID_BCM5715_A0, "BCM5715 A0" }, { BGE_CHIPID_BCM5715_A1, "BCM5715 A1" }, { BGE_CHIPID_BCM5715_A3, "BCM5715 A3" }, + { BGE_CHIPID_BCM5717_A0, "BCM5717 A0" }, + { BGE_CHIPID_BCM5717_B0, "BCM5717 B0" }, { BGE_CHIPID_BCM5755_A0, "BCM5755 A0" }, { BGE_CHIPID_BCM5755_A1, "BCM5755 A1" }, { BGE_CHIPID_BCM5755_A2, "BCM5755 A2" }, @@ -332,6 +336,7 @@ static const struct bge_revision bge_maj { BGE_ASICREV_BCM5787, "unknown BCM5754/5787" }, { BGE_ASICREV_BCM5906, "unknown BCM5906" }, { BGE_ASICREV_BCM57780, "unknown BCM57780" }, + { BGE_ASICREV_BCM5717, "unknown BCM5717" }, { 0, NULL } }; @@ -342,6 +347,7 @@ static const struct bge_revision bge_maj #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) +#define BGE_IS_5717_PLUS(sc) ((sc)->bge_flags & BGE_FLAG_5717_PLUS) const struct bge_revision * bge_lookup_rev(uint32_t); const struct bge_vendor * bge_lookup_vendor(uint16_t); @@ -367,6 +373,7 @@ static int bge_get_eaddr_eeprom(struct b static int bge_get_eaddr(struct bge_softc *, uint8_t[]); static void bge_txeof(struct bge_softc *, uint16_t); +static void bge_rxcsum(struct bge_softc *, struct bge_rx_bd *, struct mbuf *); static int bge_rxeof(struct bge_softc *, uint16_t, int); static void bge_asf_driver_up (struct bge_softc *); @@ -376,7 +383,7 @@ static void bge_stats_update(struct bge_ static void bge_stats_update_regs(struct bge_softc *); static struct mbuf *bge_check_short_dma(struct mbuf *); static struct mbuf *bge_setup_tso(struct bge_softc *, struct mbuf *, - uint16_t *); + uint16_t *, uint16_t *); static int bge_encap(struct bge_softc *, struct mbuf **, uint32_t *); static void bge_intr(void *); @@ -1349,12 +1356,15 @@ bge_stop_fw(struct bge_softc *sc) static int bge_chipinit(struct bge_softc *sc) { - uint32_t dma_rw_ctl; + uint32_t dma_rw_ctl, misc_ctl; uint16_t val; int i; /* Set endianness before we access any non-PCI registers. */ - pci_write_config(sc->bge_dev, BGE_PCI_MISC_CTL, BGE_INIT, 4); + misc_ctl = BGE_INIT; + if (sc->bge_flags & BGE_FLAG_TAGGED_STATUS) + misc_ctl |= BGE_PCIMISCCTL_TAGGED_STATUS; + pci_write_config(sc->bge_dev, BGE_PCI_MISC_CTL, misc_ctl, 4); /* Clear the MAC control register */ CSR_WRITE_4(sc, BGE_MAC_MODE, 0); @@ -1446,6 +1456,8 @@ bge_chipinit(struct bge_softc *sc) if (sc->bge_asicrev == BGE_ASICREV_BCM5703 || sc->bge_asicrev == BGE_ASICREV_BCM5704) dma_rw_ctl &= ~BGE_PCIDMARWCTL_MINDMA; + if (BGE_IS_5717_PLUS(sc)) + dma_rw_ctl &= ~BGE_PCIDMARWCTL_DIS_CACHE_ALIGNMENT; pci_write_config(sc->bge_dev, BGE_PCI_DMA_RW_CTL, dma_rw_ctl, 4); /* @@ -1529,7 +1541,16 @@ bge_blockinit(struct bge_softc *sc) } /* Configure mbuf pool watermarks */ - if (!BGE_IS_5705_PLUS(sc)) { + if (sc->bge_asicrev == BGE_ASICREV_BCM5717) { + CSR_WRITE_4(sc, BGE_BMAN_MBUFPOOL_READDMA_LOWAT, 0x0); + if (sc->bge_ifp->if_mtu > ETHERMTU) { + CSR_WRITE_4(sc, BGE_BMAN_MBUFPOOL_MACRX_LOWAT, 0x7e); + CSR_WRITE_4(sc, BGE_BMAN_MBUFPOOL_HIWAT, 0xea); + } else { + CSR_WRITE_4(sc, BGE_BMAN_MBUFPOOL_MACRX_LOWAT, 0x2a); + CSR_WRITE_4(sc, BGE_BMAN_MBUFPOOL_HIWAT, 0xa0); + } + } else if (!BGE_IS_5705_PLUS(sc)) { CSR_WRITE_4(sc, BGE_BMAN_MBUFPOOL_READDMA_LOWAT, 0x50); CSR_WRITE_4(sc, BGE_BMAN_MBUFPOOL_MACRX_LOWAT, 0x20); CSR_WRITE_4(sc, BGE_BMAN_MBUFPOOL_HIWAT, 0x60); @@ -1621,7 +1642,16 @@ bge_blockinit(struct bge_softc *sc) BGE_ADDR_HI(sc->bge_ldata.bge_rx_std_ring_paddr); bus_dmamap_sync(sc->bge_cdata.bge_rx_std_ring_tag, sc->bge_cdata.bge_rx_std_ring_map, BUS_DMASYNC_PREREAD); - if (BGE_IS_5705_PLUS(sc)) { + if (BGE_IS_5717_PLUS(sc)) { + /* + * Bits 31-16: Programmable ring size (2048, 1024, 512, .., 32) + * Bits 15-2 : Maximum RX frame size + * Bit 1 : 1 = Ring Disabled, 0 = Ring ENabled + * Bit 0 : Reserved + */ + rcb->bge_maxlen_flags = + BGE_RCB_MAXLEN_FLAGS(512, BGE_MAX_FRAMELEN << 2); + } else if (BGE_IS_5705_PLUS(sc)) { /* * Bits 31-16: Programmable ring size (512, 256, 128, 64, 32) * Bits 15-2 : Reserved (should be 0) @@ -1640,7 +1670,10 @@ bge_blockinit(struct bge_softc *sc) rcb->bge_maxlen_flags = BGE_RCB_MAXLEN_FLAGS(BGE_MAX_FRAMELEN, 0); } - rcb->bge_nicaddr = BGE_STD_RX_RINGS; + if (sc->bge_asicrev == BGE_ASICREV_BCM5717) + rcb->bge_nicaddr = BGE_STD_RX_RINGS_5717; + else + rcb->bge_nicaddr = BGE_STD_RX_RINGS; /* Write the standard receive producer ring control block. */ CSR_WRITE_4(sc, BGE_RX_STD_RCB_HADDR_HI, rcb->bge_hostaddr.bge_addr_hi); CSR_WRITE_4(sc, BGE_RX_STD_RCB_HADDR_LO, rcb->bge_hostaddr.bge_addr_lo); @@ -1669,7 +1702,10 @@ bge_blockinit(struct bge_softc *sc) BUS_DMASYNC_PREREAD); rcb->bge_maxlen_flags = BGE_RCB_MAXLEN_FLAGS(0, BGE_RCB_FLAG_USE_EXT_RX_BD | BGE_RCB_FLAG_RING_DISABLED); - rcb->bge_nicaddr = BGE_JUMBO_RX_RINGS; + if (sc->bge_asicrev == BGE_ASICREV_BCM5717) + rcb->bge_nicaddr = BGE_JUMBO_RX_RINGS_5717; + else + rcb->bge_nicaddr = BGE_JUMBO_RX_RINGS; CSR_WRITE_4(sc, BGE_RX_JUMBO_RCB_HADDR_HI, rcb->bge_hostaddr.bge_addr_hi); CSR_WRITE_4(sc, BGE_RX_JUMBO_RCB_HADDR_LO, @@ -1726,6 +1762,10 @@ bge_blockinit(struct bge_softc *sc) if (BGE_IS_JUMBO_CAPABLE(sc)) CSR_WRITE_4(sc, BGE_RBDI_JUMBO_REPL_THRESH, BGE_JUMBO_RX_RING_CNT/8); + if (BGE_IS_5717_PLUS(sc)) { + CSR_WRITE_4(sc, BGE_STD_REPLENISH_LWM, 32); + CSR_WRITE_4(sc, BGE_JMB_REPLENISH_LWM, 16); + } /* * Disable all send rings by setting the 'ring disabled' bit @@ -1750,8 +1790,11 @@ bge_blockinit(struct bge_softc *sc) BGE_HOSTADDR(taddr, sc->bge_ldata.bge_tx_ring_paddr); RCB_WRITE_4(sc, vrcb, bge_hostaddr.bge_addr_hi, taddr.bge_addr_hi); RCB_WRITE_4(sc, vrcb, bge_hostaddr.bge_addr_lo, taddr.bge_addr_lo); - RCB_WRITE_4(sc, vrcb, bge_nicaddr, - BGE_NIC_TXRING_ADDR(0, BGE_TX_RING_CNT)); + if (sc->bge_asicrev == BGE_ASICREV_BCM5717) + RCB_WRITE_4(sc, vrcb, bge_nicaddr, BGE_SEND_RING_5717); + else + RCB_WRITE_4(sc, vrcb, bge_nicaddr, + BGE_NIC_TXRING_ADDR(0, BGE_TX_RING_CNT)); RCB_WRITE_4(sc, vrcb, bge_maxlen_flags, BGE_RCB_MAXLEN_FLAGS(BGE_TX_RING_CNT, 0)); @@ -1760,7 +1803,10 @@ bge_blockinit(struct bge_softc *sc) * 'ring diabled' bit in the flags field of all the receive * return ring control blocks, located in NIC memory. */ - if (!BGE_IS_5705_PLUS(sc)) + if (sc->bge_asicrev == BGE_ASICREV_BCM5717) { + /* Should be 17, use 16 until we get an SRAM map. */ + limit = 16; + } else if (!BGE_IS_5705_PLUS(sc)) limit = BGE_RX_RINGS_MAX; else if (sc->bge_asicrev == BGE_ASICREV_BCM5755) limit = 4; @@ -1936,6 +1982,10 @@ bge_blockinit(struct bge_softc *sc) /* Turn on read DMA state machine */ val = BGE_RDMAMODE_ENABLE | BGE_RDMAMODE_ALL_ATTNS; + + if (sc->bge_asicrev == BGE_ASICREV_BCM5717) + val |= BGE_RDMAMODE_MULT_DMA_RD_DIS; + if (sc->bge_asicrev == BGE_ASICREV_BCM5784 || sc->bge_asicrev == BGE_ASICREV_BCM5785 || sc->bge_asicrev == BGE_ASICREV_BCM57780) @@ -1944,16 +1994,18 @@ bge_blockinit(struct bge_softc *sc) BGE_RDMAMODE_MBUF_SBD_CRPT_ATTN; if (sc->bge_flags & BGE_FLAG_PCIE) val |= BGE_RDMAMODE_FIFO_LONG_BURST; - if (sc->bge_flags & BGE_FLAG_TSO) { + if (sc->bge_flags & (BGE_FLAG_TSO | BGE_FLAG_TSO3)) { val |= BGE_RDMAMODE_TSO4_ENABLE; - if (sc->bge_asicrev == BGE_ASICREV_BCM5785 || + if (sc->bge_flags & BGE_FLAG_TSO3 || + sc->bge_asicrev == BGE_ASICREV_BCM5785 || sc->bge_asicrev == BGE_ASICREV_BCM57780) val |= BGE_RDMAMODE_TSO6_ENABLE; } if (sc->bge_asicrev == BGE_ASICREV_BCM5761 || sc->bge_asicrev == BGE_ASICREV_BCM5784 || sc->bge_asicrev == BGE_ASICREV_BCM5785 || - sc->bge_asicrev == BGE_ASICREV_BCM57780) { + sc->bge_asicrev == BGE_ASICREV_BCM57780 || + BGE_IS_5717_PLUS(sc)) { /* * Enable fix for read DMA FIFO overruns. * The fix is to limit the number of RX BDs @@ -1989,8 +2041,9 @@ bge_blockinit(struct bge_softc *sc) CSR_WRITE_4(sc, BGE_SDC_MODE, val); /* Turn on send data initiator state machine */ - if (sc->bge_flags & BGE_FLAG_TSO) - CSR_WRITE_4(sc, BGE_SDI_MODE, BGE_SDIMODE_ENABLE | 0x08); + if (sc->bge_flags & (BGE_FLAG_TSO | BGE_FLAG_TSO3)) + CSR_WRITE_4(sc, BGE_SDI_MODE, BGE_SDIMODE_ENABLE | + BGE_SDIMODE_HW_LSO_PRE_DMA); else CSR_WRITE_4(sc, BGE_SDI_MODE, BGE_SDIMODE_ENABLE); @@ -2104,9 +2157,22 @@ bge_probe(device_t dev) id = pci_read_config(dev, BGE_PCI_MISC_CTL, 4) >> BGE_PCIMISCCTL_ASICREV_SHIFT; - if (BGE_ASICREV(id) == BGE_ASICREV_USE_PRODID_REG) - id = pci_read_config(dev, - BGE_PCI_PRODID_ASICREV, 4); + if (BGE_ASICREV(id) == BGE_ASICREV_USE_PRODID_REG) { + /* + * Find the ASCI revision. Different chips + * use different registers. + */ + switch (pci_get_device(dev)) { + case BCOM_DEVICEID_BCM5717: + case BCOM_DEVICEID_BCM5718: + id = pci_read_config(dev, + BGE_PCI_GEN2_PRODID_ASICREV, 4); + break; + default: + id = pci_read_config(dev, + BGE_PCI_PRODID_ASICREV, 4); + } + } br = bge_lookup_rev(id); v = bge_lookup_vendor(vid); { @@ -2423,7 +2489,7 @@ bge_dma_alloc(struct bge_softc *sc) return (ENOMEM); } /* Create tag for Tx mbufs. */ - if (sc->bge_flags & BGE_FLAG_TSO) { + if (sc->bge_flags & (BGE_FLAG_TSO | BGE_FLAG_TSO3)) { txsegsz = BGE_TSOSEG_SZ; txmaxsegsz = 65535 + sizeof(struct ether_vlan_header); } else { @@ -2539,6 +2605,10 @@ bge_can_use_msi(struct bge_softc *sc) { int can_use_msi = 0; + /* Disable MSI for polling(4). */ +#ifdef DEVICE_POLLING + return (0); +#endif switch (sc->bge_asicrev) { case BGE_ASICREV_BCM5714_A0: case BGE_ASICREV_BCM5714: @@ -2568,7 +2638,7 @@ bge_attach(device_t dev) struct bge_softc *sc; uint32_t hwcfg = 0, misccfg; u_char eaddr[ETHER_ADDR_LEN]; - int error, msicount, phy_addr, reg, rid, trys; + int error, f, msicount, phy_addr, reg, rid, trys; sc = device_get_softc(dev); sc->bge_dev = dev; @@ -2594,14 +2664,55 @@ bge_attach(device_t dev) sc->bge_chipid = 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); + if (BGE_ASICREV(sc->bge_chipid) == BGE_ASICREV_USE_PRODID_REG) { + /* + * Find the ASCI revision. Different chips use different + * registers. + */ + switch (pci_get_device(dev)) { + case BCOM_DEVICEID_BCM5717: + case BCOM_DEVICEID_BCM5718: + sc->bge_chipid = pci_read_config(dev, + BGE_PCI_GEN2_PRODID_ASICREV, 4); + break; + default: + 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); /* Set default PHY address. */ phy_addr = 1; + /* + * PHY address mapping for various devices. + * + * | F0 Cu | F0 Sr | F1 Cu | F1 Sr | + * ---------+-------+-------+-------+-------+ + * BCM57XX | 1 | X | X | X | + * BCM5704 | 1 | X | 1 | X | + * BCM5717 | 1 | 8 | 2 | 9 | + * + * Other addresses may respond but they are not + * IEEE compliant PHYs and should be ignored. + */ + if (sc->bge_asicrev == BGE_ASICREV_BCM5717) { + f = pci_get_function(dev); + if (sc->bge_chipid == BGE_CHIPID_BCM5717_A0) { + if (CSR_READ_4(sc, BGE_SGDIG_STS) & + BGE_SGDIGSTS_IS_SERDES) + phy_addr = f + 8; + else + phy_addr = f + 1; + } else if (sc->bge_chipid == BGE_CHIPID_BCM5717_B0) { + if (CSR_READ_4(sc, BGE_CPMU_PHY_STRAP) & + BGE_CPMU_PHY_STRAP_IS_SERDES) + phy_addr = f + 8; + else + phy_addr = f + 1; + } + } /* * Don't enable Ethernet@WireSpeed for the 5700, 5906, or the @@ -2610,7 +2721,8 @@ bge_attach(device_t dev) if (sc->bge_asicrev != BGE_ASICREV_BCM5700 && sc->bge_asicrev != BGE_ASICREV_BCM5906 && sc->bge_chipid != BGE_CHIPID_BCM5705_A0 && - sc->bge_chipid != BGE_CHIPID_BCM5705_A1) + sc->bge_chipid != BGE_CHIPID_BCM5705_A1 && + !BGE_IS_5717_PLUS(sc)) sc->bge_phy_flags |= BGE_PHY_WIRESPEED; if (bge_has_eaddr(sc)) @@ -2618,6 +2730,11 @@ bge_attach(device_t dev) /* Save chipset family. */ switch (sc->bge_asicrev) { + case BGE_ASICREV_BCM5717: + sc->bge_flags |= BGE_FLAG_5717_PLUS | BGE_FLAG_5755_PLUS | + BGE_FLAG_575X_PLUS | BGE_FLAG_5705_PLUS | BGE_FLAG_JUMBO | + BGE_FLAG_SHORT_DMA_BUG | BGE_FLAG_JUMBO_FRAME; + break; case BGE_ASICREV_BCM5755: case BGE_ASICREV_BCM5761: case BGE_ASICREV_BCM5784: @@ -2663,6 +2780,7 @@ bge_attach(device_t dev) sc->bge_phy_flags |= BGE_PHY_NO_3LED; if ((BGE_IS_5705_PLUS(sc)) && sc->bge_asicrev != BGE_ASICREV_BCM5906 && + sc->bge_asicrev != BGE_ASICREV_BCM5717 && sc->bge_asicrev != BGE_ASICREV_BCM5785 && sc->bge_asicrev != BGE_ASICREV_BCM57780) { if (sc->bge_asicrev == BGE_ASICREV_BCM5755 || @@ -2679,7 +2797,8 @@ bge_attach(device_t dev) } /* Identify the chips that use an CPMU. */ - if (sc->bge_asicrev == BGE_ASICREV_BCM5784 || + if (BGE_IS_5717_PLUS(sc) || + sc->bge_asicrev == BGE_ASICREV_BCM5784 || sc->bge_asicrev == BGE_ASICREV_BCM5761 || sc->bge_asicrev == BGE_ASICREV_BCM5785 || sc->bge_asicrev == BGE_ASICREV_BCM57780) @@ -2722,7 +2841,10 @@ bge_attach(device_t dev) * the TSO to the controllers that are not affected TSO issues * (e.g. 5755 or higher). */ - if (BGE_IS_5755_PLUS(sc)) { + if (BGE_IS_5717_PLUS(sc)) { + /* BCM5717 requires different TSO configuration. */ + sc->bge_flags |= BGE_FLAG_TSO3; + } else if (BGE_IS_5755_PLUS(sc)) { /* * BCM5754 and BCM5787 shares the same ASIC id so * explicit device id check is required. @@ -2785,6 +2907,16 @@ bge_attach(device_t dev) } } + /* + * All controllers except BCM5700 supports tagged status but + * we use tagged status only for MSI case on BCM5717. Otherwise + * MSI on BCM5717 does not work. + */ +#ifndef DEVICE_POLLING + if (sc->bge_flags & BGE_FLAG_MSI && BGE_IS_5717_PLUS(sc)) + sc->bge_flags |= BGE_FLAG_TAGGED_STATUS; +#endif + sc->bge_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_SHAREABLE | RF_ACTIVE); @@ -2848,7 +2980,9 @@ bge_attach(device_t dev) } /* 5705 limits RX return ring to 512 entries. */ - if (BGE_IS_5705_PLUS(sc)) + if (BGE_IS_5717_PLUS(sc)) + sc->bge_return_ring_cnt = BGE_RETURN_RING_CNT; + else if (BGE_IS_5705_PLUS(sc)) sc->bge_return_ring_cnt = BGE_RETURN_RING_CNT_5705; else sc->bge_return_ring_cnt = BGE_RETURN_RING_CNT; @@ -2893,7 +3027,7 @@ bge_attach(device_t dev) ifp->if_hwassist = sc->bge_csum_features; ifp->if_capabilities = IFCAP_HWCSUM | IFCAP_VLAN_HWTAGGING | IFCAP_VLAN_MTU; - if ((sc->bge_flags & BGE_FLAG_TSO) != 0) { + if ((sc->bge_flags & (BGE_FLAG_TSO | BGE_FLAG_TSO3)) != 0) { ifp->if_hwassist |= CSUM_TSO; ifp->if_capabilities |= IFCAP_TSO4 | IFCAP_VLAN_HWTSO; } @@ -3340,6 +3474,7 @@ bge_reset(struct bge_softc *sc) /* XXX: Broadcom Linux driver. */ if (sc->bge_flags & BGE_FLAG_PCIE && + sc->bge_asicrev != BGE_ASICREV_BCM5717 && sc->bge_chipid != BGE_CHIPID_BCM5750_A0 && sc->bge_asicrev != BGE_ASICREV_BCM5785) { /* Enable Data FIFO protection. */ @@ -3480,20 +3615,8 @@ bge_rxeof(struct bge_softc *sc, uint16_t m->m_pkthdr.len = m->m_len = cur_rx->bge_len - ETHER_CRC_LEN; m->m_pkthdr.rcvif = ifp; - if (ifp->if_capenable & IFCAP_RXCSUM) { - if (cur_rx->bge_flags & BGE_RXBDFLAG_IP_CSUM) { - m->m_pkthdr.csum_flags |= CSUM_IP_CHECKED; - if ((cur_rx->bge_ip_csum ^ 0xFFFF) == 0) - m->m_pkthdr.csum_flags |= CSUM_IP_VALID; - } - if (cur_rx->bge_flags & BGE_RXBDFLAG_TCP_UDP_CSUM && - m->m_pkthdr.len >= ETHER_MIN_NOPAD) { - m->m_pkthdr.csum_data = - cur_rx->bge_tcp_udp_csum; - m->m_pkthdr.csum_flags |= - CSUM_DATA_VALID | CSUM_PSEUDO_HDR; - } - } + if (ifp->if_capenable & IFCAP_RXCSUM) + bge_rxcsum(sc, cur_rx, m); /* * If we received a packet with a vlan tag, @@ -3552,6 +3675,41 @@ bge_rxeof(struct bge_softc *sc, uint16_t } static void +bge_rxcsum(struct bge_softc *sc, struct bge_rx_bd *cur_rx, struct mbuf *m) +{ + + if (BGE_IS_5717_PLUS(sc)) { + if ((cur_rx->bge_flags & BGE_RXBDFLAG_IPV6) == 0) { + if (cur_rx->bge_flags & BGE_RXBDFLAG_IP_CSUM) { + m->m_pkthdr.csum_flags |= CSUM_IP_CHECKED; + if ((cur_rx->bge_error_flag & + BGE_RXERRFLAG_IP_CSUM_NOK) == 0) + m->m_pkthdr.csum_flags |= CSUM_IP_VALID; + } + if (cur_rx->bge_flags & BGE_RXBDFLAG_TCP_UDP_CSUM) { + m->m_pkthdr.csum_data = + cur_rx->bge_tcp_udp_csum; + m->m_pkthdr.csum_flags |= CSUM_DATA_VALID | + CSUM_PSEUDO_HDR; + } + } + } else { + if (cur_rx->bge_flags & BGE_RXBDFLAG_IP_CSUM) { + m->m_pkthdr.csum_flags |= CSUM_IP_CHECKED; + if ((cur_rx->bge_ip_csum ^ 0xFFFF) == 0) + m->m_pkthdr.csum_flags |= CSUM_IP_VALID; + } + if (cur_rx->bge_flags & BGE_RXBDFLAG_TCP_UDP_CSUM && + m->m_pkthdr.len >= ETHER_MIN_NOPAD) { + m->m_pkthdr.csum_data = + cur_rx->bge_tcp_udp_csum; + m->m_pkthdr.csum_flags |= CSUM_DATA_VALID | + CSUM_PSEUDO_HDR; + } + } +} + +static void bge_txeof(struct bge_softc *sc, uint16_t tx_cons) { struct bge_tx_bd *cur_tx; @@ -3668,7 +3826,7 @@ bge_intr_task(void *arg, int pending) { struct bge_softc *sc; struct ifnet *ifp; - uint32_t status; + uint32_t status, status_tag; uint16_t rx_prod, tx_cons; sc = (struct bge_softc *)arg; @@ -3689,16 +3847,19 @@ bge_intr_task(void *arg, int pending) rx_prod = sc->bge_ldata.bge_status_block->bge_idx[0].bge_rx_prod_idx; tx_cons = sc->bge_ldata.bge_status_block->bge_idx[0].bge_tx_cons_idx; status = sc->bge_ldata.bge_status_block->bge_status; + status_tag = sc->bge_ldata.bge_status_block->bge_status_tag << 24; sc->bge_ldata.bge_status_block->bge_status = 0; bus_dmamap_sync(sc->bge_cdata.bge_status_tag, sc->bge_cdata.bge_status_map, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); + if ((sc->bge_flags & BGE_FLAG_TAGGED_STATUS) == 0) + status_tag = 0; if ((status & BGE_STATFLAG_LINKSTATE_CHANGED) != 0) bge_link_upd(sc); /* Let controller work. */ - bge_writembx(sc, BGE_MBX_IRQ0_LO, 0); + bge_writembx(sc, BGE_MBX_IRQ0_LO, status_tag); if (ifp->if_drv_flags & IFF_DRV_RUNNING && sc->bge_rx_saved_considx != rx_prod) { @@ -4104,7 +4265,8 @@ bge_check_short_dma(struct mbuf *m) } static struct mbuf * -bge_setup_tso(struct bge_softc *sc, struct mbuf *m, uint16_t *mss) +bge_setup_tso(struct bge_softc *sc, struct mbuf *m, uint16_t *mss, + uint16_t *flags) { struct ip *ip; struct tcphdr *tcp; @@ -4147,14 +4309,30 @@ bge_setup_tso(struct bge_softc *sc, stru * Broadcom controllers uses different descriptor format for * TSO depending on ASIC revision. Due to TSO-capable firmware * license issue and lower performance of firmware based TSO - * we only support hardware based TSO which is applicable for - * BCM5755 or newer controllers. Hardware based TSO uses 11 - * bits to store MSS and upper 5 bits are used to store IP/TCP - * header length(including IP/TCP options). The header length - * is expressed as 32 bits unit. + * we only support hardware based TSO. */ + /* Calculate header length, incl. TCP/IP options, in 32 bit units. */ hlen = ((ip->ip_hl << 2) + (tcp->th_off << 2)) >> 2; - *mss |= (hlen << 11); + if (sc->bge_flags & BGE_FLAG_TSO3) { + /* + * For BCM5717 and newer controllers, hardware based TSO + * uses the 14 lower bits of the bge_mss field to store the + * MSS and the upper 2 bits to store the lowest 2 bits of + * the IP/TCP header length. The upper 6 bits of the header + * length are stored in the bge_flags[14:10,4] field. Jumbo + * frames are supported. + */ + *mss |= ((hlen & 0x3) << 14); + *flags |= ((hlen & 0xF8) << 7) | ((hlen & 0x4) << 2); + } else { + /* + * For BCM5755 and newer controllers, hardware based TSO uses + * the lower 11 bits to store the MSS and the upper 5 bits to + * store the IP/TCP header length. Jumbo frames are not + * supported. + */ + *mss |= (hlen << 11); + } return (m); } @@ -4184,7 +4362,7 @@ bge_encap(struct bge_softc *sc, struct m m = *m_head; } if ((m->m_pkthdr.csum_flags & CSUM_TSO) != 0) { - *m_head = m = bge_setup_tso(sc, m, &mss); + *m_head = m = bge_setup_tso(sc, m, &mss, &csum_flags); if (*m_head == NULL) return (ENOBUFS); csum_flags |= BGE_TXBDFLAG_CPU_PRE_DMA | @@ -4207,21 +4385,26 @@ bge_encap(struct bge_softc *sc, struct m csum_flags |= BGE_TXBDFLAG_IP_FRAG; } - if ((m->m_pkthdr.csum_flags & CSUM_TSO) == 0 && - sc->bge_forced_collapse > 0 && - (sc->bge_flags & BGE_FLAG_PCIE) != 0 && m->m_next != NULL) { - /* - * Forcedly collapse mbuf chains to overcome hardware - * limitation which only support a single outstanding - * DMA read operation. - */ - if (sc->bge_forced_collapse == 1) - m = m_defrag(m, M_DONTWAIT); - else - m = m_collapse(m, M_DONTWAIT, sc->bge_forced_collapse); - if (m == NULL) - m = *m_head; - *m_head = m; + if ((m->m_pkthdr.csum_flags & CSUM_TSO) == 0) { + if (sc->bge_flags & BGE_FLAG_JUMBO_FRAME && + m->m_pkthdr.len > ETHER_MAX_LEN) + csum_flags |= BGE_TXBDFLAG_JUMBO_FRAME; + if (sc->bge_forced_collapse > 0 && + (sc->bge_flags & BGE_FLAG_PCIE) != 0 && m->m_next != NULL) { + /* + * Forcedly collapse mbuf chains to overcome hardware + * limitation which only support a single outstanding + * DMA read operation. + */ + if (sc->bge_forced_collapse == 1) + m = m_defrag(m, M_DONTWAIT); + else + m = m_collapse(m, M_DONTWAIT, + sc->bge_forced_collapse); + if (m == NULL) + m = *m_head; + *m_head = m; + } } map = sc->bge_cdata.bge_tx_dmamap[idx]; Modified: head/sys/dev/bge/if_bgereg.h ============================================================================== --- head/sys/dev/bge/if_bgereg.h Wed Oct 27 17:16:40 2010 (r214427) +++ head/sys/dev/bge/if_bgereg.h Wed Oct 27 17:20:19 2010 (r214428) @@ -82,6 +82,7 @@ #define BGE_UNMAPPED_END 0x00001FFF #define BGE_DMA_DESCRIPTORS 0x00002000 #define BGE_DMA_DESCRIPTORS_END 0x00003FFF +#define BGE_SEND_RING_5717 0x00004000 #define BGE_SEND_RING_1_TO_4 0x00004000 #define BGE_SEND_RING_1_TO_4_END 0x00005FFF @@ -100,6 +101,8 @@ #define BGE_BUFFPOOL_2_END 0x00017FFF #define BGE_BUFFPOOL_3 0x00018000 /* or expansion ROM */ #define BGE_BUFFPOOL_3_END 0x0001FFFF +#define BGE_STD_RX_RINGS_5717 0x00040000 +#define BGE_JUMBO_RX_RINGS_5717 0x00044400 /* Mappings for external SSRAM configurations */ #define BGE_SEND_RING_5_TO_6 0x00006000 @@ -219,6 +222,7 @@ #define BGE_PCI_ISR_MBX_HI 0xB0 #define BGE_PCI_ISR_MBX_LO 0xB4 #define BGE_PCI_PRODID_ASICREV 0xBC +#define BGE_PCI_GEN2_PRODID_ASICREV 0xF4 /* PCI Misc. Host control register */ #define BGE_PCIMISCCTL_CLEAR_INTA 0x00000001 @@ -229,6 +233,7 @@ #define BGE_PCIMISCCTL_CLOCKCTL_RW 0x00000020 #define BGE_PCIMISCCTL_REG_WORDSWAP 0x00000040 #define BGE_PCIMISCCTL_INDIRECT_ACCESS 0x00000080 +#define BGE_PCIMISCCTL_TAGGED_STATUS 0x00000200 #define BGE_PCIMISCCTL_ASICREV 0xFFFF0000 #define BGE_PCIMISCCTL_ASICREV_SHIFT 16 @@ -311,6 +316,8 @@ #define BGE_CHIPID_BCM5906_A2 0xc002 #define BGE_CHIPID_BCM57780_A0 0x57780000 #define BGE_CHIPID_BCM57780_A1 0x57780001 +#define BGE_CHIPID_BCM5717_A0 0x05717000 +#define BGE_CHIPID_BCM5717_B0 0x05717100 /* shorthand one */ #define BGE_ASICREV(x) ((x) >> 12) @@ -331,6 +338,7 @@ /* Should consult BGE_PCI_PRODID_ASICREV for ChipID */ #define BGE_ASICREV_USE_PRODID_REG 0x0f /* BGE_PCI_PRODID_ASICREV ASIC rev. identifiers. */ +#define BGE_ASICREV_BCM5717 0x5717 #define BGE_ASICREV_BCM5761 0x5761 #define BGE_ASICREV_BCM5784 0x5784 #define BGE_ASICREV_BCM5785 0x5785 @@ -348,11 +356,14 @@ #define BGE_CHIPREV_5750_AX 0x40 #define BGE_CHIPREV_5750_BX 0x41 /* BGE_PCI_PRODID_ASICREV chip rev. identifiers. */ +#define BGE_CHIPREV_5717_AX 0x57170 +#define BGE_CHIPREV_5717_BX 0x57171 #define BGE_CHIPREV_5761_AX 0x57611 #define BGE_CHIPREV_5784_AX 0x57841 /* PCI DMA Read/Write Control register */ #define BGE_PCIDMARWCTL_MINDMA 0x000000FF +#define BGE_PCIDMARWCTL_DIS_CACHE_ALIGNMENT 0x00000001 #define BGE_PCIDMARWCTL_RDADRR_BNDRY 0x00000700 #define BGE_PCIDMARWCTL_WRADDR_BNDRY 0x00003800 #define BGE_PCIDMARWCTL_ONEDMA_ATONCE 0x0000C000 @@ -566,6 +577,7 @@ #define BGE_TX_RINGS_MAX 4 #define BGE_TX_RINGS_EXTSSRAM_MAX 16 #define BGE_RX_RINGS_MAX 16 +#define BGE_RX_RINGS_MAX_5717 17 /* Ethernet MAC control registers */ #define BGE_MAC_MODE 0x0400 @@ -843,9 +855,10 @@ #define BGE_SGDIGCFG_AUTO 0x80000000 /* SGDIG status (not documented) */ +#define BGE_SGDIGSTS_DONE 0x00000002 +#define BGE_SGDIGSTS_IS_SERDES 0x00000100 #define BGE_SGDIGSTS_PAUSE_CAP 0x00080000 #define BGE_SGDIGSTS_ASYM_PAUSE 0x00100000 -#define BGE_SGDIGSTS_DONE 0x00000002 /* MI communication register */ @@ -911,6 +924,7 @@ #define BGE_SDIMODE_RESET 0x00000001 #define BGE_SDIMODE_ENABLE 0x00000002 #define BGE_SDIMODE_STATS_OFLOW_ATTN 0x00000004 +#define BGE_SDIMODE_HW_LSO_PRE_DMA 0x00000008 /* Send Data Initiator stats register */ #define BGE_SDISTAT_STATS_OFLOW_ATTN 0x00000004 @@ -1188,6 +1202,9 @@ #define BGE_RBDI_STD_REPL_THRESH 0x2C18 #define BGE_RBDI_JUMBO_REPL_THRESH 0x2C1C +#define BGE_STD_REPLENISH_LWM 0x2D00 +#define BGE_JMB_REPLENISH_LWM 0x2D04 + /* Receive BD Initiator Mode register */ #define BGE_RBDIMODE_RESET 0x00000001 #define BGE_RBDIMODE_ENABLE 0x00000002 @@ -1501,6 +1518,7 @@ #define BGE_RDMAMODE_MBUF_SBD_CRPT_ATTN 0x00002000 #define BGE_RDMAMODE_FIFO_SIZE_128 0x00020000 #define BGE_RDMAMODE_FIFO_LONG_BURST 0x00030000 +#define BGE_RDMAMODE_MULT_DMA_RD_DIS 0x01000000 #define BGE_RDMAMODE_TSO4_ENABLE 0x08000000 #define BGE_RDMAMODE_TSO6_ENABLE 0x10000000 @@ -2068,15 +2086,27 @@ struct bge_tx_bd { #define BGE_TXBDFLAG_IP_CSUM 0x0002 #define BGE_TXBDFLAG_END 0x0004 #define BGE_TXBDFLAG_IP_FRAG 0x0008 +#define BGE_TXBDFLAG_JUMBO_FRAME 0x0008 /* 5717 */ #define BGE_TXBDFLAG_IP_FRAG_END 0x0010 +#define BGE_TXBDFLAG_HDRLEN_BIT2 0x0010 /* 5717 */ +#define BGE_TXBDFLAG_SNAP 0x0020 /* 5717 */ #define BGE_TXBDFLAG_VLAN_TAG 0x0040 #define BGE_TXBDFLAG_COAL_NOW 0x0080 #define BGE_TXBDFLAG_CPU_PRE_DMA 0x0100 #define BGE_TXBDFLAG_CPU_POST_DMA 0x0200 +#define BGE_TXBDFLAG_HDRLEN_BIT3 0x0400 /* 5717 */ +#define BGE_TXBDFLAG_HDRLEN_BIT4 0x0800 /* 5717 */ #define BGE_TXBDFLAG_INSERT_SRC_ADDR 0x1000 +#define BGE_TXBDFLAG_HDRLEN_BIT5 0x1000 /* 5717 */ +#define BGE_TXBDFLAG_HDRLEN_BIT6 0x2000 /* 5717 */ +#define BGE_TXBDFLAG_HDRLEN_BIT7 0x4000 /* 5717 */ #define BGE_TXBDFLAG_CHOOSE_SRC_ADDR 0x6000 #define BGE_TXBDFLAG_NO_CRC 0x8000 +#define BGE_TXBDFLAG_MSS_SIZE_MASK 0x3FFF /* 5717 */ +/* Bits [1:0] of the MSS header length. */ +#define BGE_TXBDFLAG_MSS_HDRLEN_MASK 0xC000 /* 5717 */ + #define BGE_NIC_TXRING_ADDR(ringno, size) \ BGE_SEND_RING_1_TO_4 + \ ((ringno * sizeof(struct bge_tx_bd) * size) / 4) @@ -2153,6 +2183,7 @@ struct bge_extrx_bd { #define BGE_RXBDFLAG_IP_CSUM 0x1000 #define BGE_RXBDFLAG_TCP_UDP_CSUM 0x2000 #define BGE_RXBDFLAG_TCP_UDP_IS_TCP 0x4000 +#define BGE_RXBDFLAG_IPV6 0x8000 #define BGE_RXERRFLAG_BAD_CRC 0x0001 #define BGE_RXERRFLAG_COLL_DETECT 0x0002 @@ -2162,6 +2193,7 @@ struct bge_extrx_bd { #define BGE_RXERRFLAG_RUNT 0x0020 #define BGE_RXERRFLAG_TRUNC_NO_RSRCS 0x0040 #define BGE_RXERRFLAG_GIANT 0x0080 +#define BGE_RXERRFLAG_IP_CSUM_NOK 0x1000 /* 5717 */ struct bge_sts_idx { #if BYTE_ORDER == LITTLE_ENDIAN @@ -2175,7 +2207,7 @@ struct bge_sts_idx { struct bge_status_block { uint32_t bge_status; - uint32_t bge_rsvd0; + uint32_t bge_status_tag; #if BYTE_ORDER == LITTLE_ENDIAN uint16_t bge_rx_jumbo_cons_idx; uint16_t bge_rx_std_cons_idx; @@ -2221,6 +2253,8 @@ struct bge_status_block { #define BCOM_DEVICEID_BCM5714S 0x1669 #define BCOM_DEVICEID_BCM5715 0x1678 #define BCOM_DEVICEID_BCM5715S 0x1679 +#define BCOM_DEVICEID_BCM5717 0x1655 +#define BCOM_DEVICEID_BCM5718 0x1656 #define BCOM_DEVICEID_BCM5720 0x1658 #define BCOM_DEVICEID_BCM5721 0x1659 #define BCOM_DEVICEID_BCM5722 0x165A @@ -2717,16 +2751,20 @@ struct bge_softc { #define BGE_FLAG_EADDR 0x00000008 #define BGE_FLAG_MII_SERDES 0x00000010 #define BGE_FLAG_CPMU_PRESENT 0x00000020 +#define BGE_FLAG_TAGGED_STATUS 0x00000040 #define BGE_FLAG_MSI 0x00000100 #define BGE_FLAG_PCIX 0x00000200 #define BGE_FLAG_PCIE 0x00000400 #define BGE_FLAG_TSO 0x00000800 +#define BGE_FLAG_TSO3 0x00001000 +#define BGE_FLAG_JUMBO_FRAME 0x00002000 #define BGE_FLAG_5700_FAMILY 0x00010000 #define BGE_FLAG_5705_PLUS 0x00020000 #define BGE_FLAG_5714_FAMILY 0x00040000 #define BGE_FLAG_575X_PLUS 0x00080000 #define BGE_FLAG_5755_PLUS 0x00100000 #define BGE_FLAG_5788 0x00200000 +#define BGE_FLAG_5717_PLUS 0x00400000 #define BGE_FLAG_40BIT_BUG 0x01000000 #define BGE_FLAG_4G_BNDRY_BUG 0x02000000 #define BGE_FLAG_RX_ALIGNBUG 0x04000000
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201010271720.o9RHKJYK016013>