summaryrefslogtreecommitdiffstats
path: root/sys/dev/bge
diff options
context:
space:
mode:
authoryongari <yongari@FreeBSD.org>2010-10-27 17:20:19 +0000
committeryongari <yongari@FreeBSD.org>2010-10-27 17:20:19 +0000
commitd3a1fbe16a8cdea57e3c9f83e2ce71936e4de376 (patch)
treed193a75a01cc4f94a7a48b335509e9c1fd867ee9 /sys/dev/bge
parentec8554fc0edb20f4044a274cdc0f32d147c1f0c5 (diff)
downloadFreeBSD-src-d3a1fbe16a8cdea57e3c9f83e2ce71936e4de376.zip
FreeBSD-src-d3a1fbe16a8cdea57e3c9f83e2ce71936e4de376.tar.gz
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
Diffstat (limited to 'sys/dev/bge')
-rw-r--r--sys/dev/bge/if_bge.c317
-rw-r--r--sys/dev/bge/if_bgereg.h42
2 files changed, 290 insertions, 69 deletions
diff --git a/sys/dev/bge/if_bge.c b/sys/dev/bge/if_bge.c
index 63c4c5d..59ce673 100644
--- a/sys/dev/bge/if_bge.c
+++ b/sys/dev/bge/if_bge.c
@@ -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_majorrevs[] = {
{ 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_majorrevs[] = {
#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 bge_softc *, uint8_t[]);
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_softc *);
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 rx_prod, int holdlck)
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 rx_prod, int holdlck)
}
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, struct mbuf *m, uint16_t *mss)
* 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 mbuf **m_head, uint32_t *txidx)
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 mbuf **m_head, uint32_t *txidx)
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];
diff --git a/sys/dev/bge/if_bgereg.h b/sys/dev/bge/if_bgereg.h
index a50bf59..6a9c2e8 100644
--- a/sys/dev/bge/if_bgereg.h
+++ b/sys/dev/bge/if_bgereg.h
@@ -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
OpenPOWER on IntegriCloud