Module Name: src Committed By: msaitoh Date: Thu Mar 28 02:50:27 UTC 2019
Modified Files: src/sys/dev/pci: if_bnx.c if_bnxvar.h Log Message: - Remove extra cast (from OpenBSD rev. 1.95) - Add support flow control (from OpenBSD rev. 1.97 and 1.100). The main difference between NetBSD and other *BSDs is that the flow control does really works. The lower 8bit of BNX_L2CTX_CTX_TYPE should be 0xff (from Linux). Note that I have NetXtremeII-PG203-R.pdf and it says the field is reserved and should be 0. To generate a diff of this commit: cvs rdiff -u -r1.71 -r1.72 src/sys/dev/pci/if_bnx.c cvs rdiff -u -r1.7 -r1.8 src/sys/dev/pci/if_bnxvar.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/dev/pci/if_bnx.c diff -u src/sys/dev/pci/if_bnx.c:1.71 src/sys/dev/pci/if_bnx.c:1.72 --- src/sys/dev/pci/if_bnx.c:1.71 Wed Mar 27 03:37:32 2019 +++ src/sys/dev/pci/if_bnx.c Thu Mar 28 02:50:27 2019 @@ -1,5 +1,5 @@ -/* $NetBSD: if_bnx.c,v 1.71 2019/03/27 03:37:32 msaitoh Exp $ */ -/* $OpenBSD: if_bnx.c,v 1.94 2011/04/18 04:27:31 dlg Exp $ */ +/* $NetBSD: if_bnx.c,v 1.72 2019/03/28 02:50:27 msaitoh Exp $ */ +/* $OpenBSD: if_bnx.c,v 1.100 2013/01/13 05:45:10 brad Exp $ */ /*- * Copyright (c) 2006-2010 Broadcom Corporation @@ -35,7 +35,7 @@ #if 0 __FBSDID("$FreeBSD: src/sys/dev/bce/if_bce.c,v 1.3 2006/04/13 14:12:26 ru Exp $"); #endif -__KERNEL_RCSID(0, "$NetBSD: if_bnx.c,v 1.71 2019/03/27 03:37:32 msaitoh Exp $"); +__KERNEL_RCSID(0, "$NetBSD: if_bnx.c,v 1.72 2019/03/28 02:50:27 msaitoh Exp $"); /* * The following controllers are supported by this driver: @@ -380,6 +380,7 @@ int bnx_tx_encap(struct bnx_softc *, str void bnx_start(struct ifnet *); int bnx_ioctl(struct ifnet *, u_long, void *); void bnx_watchdog(struct ifnet *); +void bnx_ifmedia_sts(struct ifnet *, struct ifmediareq *); int bnx_init(struct ifnet *); void bnx_init_context(struct bnx_softc *); @@ -819,7 +820,7 @@ bnx_attach(device_t parent, device_t sel sc->bnx_ec.ec_mii = &sc->bnx_mii; ifmedia_init(&sc->bnx_mii.mii_media, 0, ether_mediachange, - ether_mediastatus); + bnx_ifmedia_sts); /* set phyflags and chipid before mii_attach() */ dict = device_properties(self); @@ -831,6 +832,7 @@ bnx_attach(device_t parent, device_t sel /* Print some useful adapter info */ bnx_print_adapter_info(sc); + mii_flags |= MIIF_DOPAUSE; if (sc->bnx_phy_flags & BNX_PHY_SERDES_FLAG) mii_flags |= MIIF_HAVEFIBER; mii_attach(self, &sc->bnx_mii, 0xffffffff, @@ -1188,6 +1190,7 @@ bnx_miibus_statchg(struct ifnet *ifp) { struct bnx_softc *sc = ifp->if_softc; struct mii_data *mii = &sc->bnx_mii; + uint32_t rx_mode = sc->rx_mode; int val; val = REG_RD(sc, BNX_EMAC_MODE); @@ -1195,6 +1198,15 @@ bnx_miibus_statchg(struct ifnet *ifp) BNX_EMAC_MODE_MAC_LOOP | BNX_EMAC_MODE_FORCE_LINK | BNX_EMAC_MODE_25G); + /* + * Get flow control negotiation result. + */ + if (IFM_SUBTYPE(mii->mii_media.ifm_cur->ifm_media) == IFM_AUTO && + (mii->mii_media_active & IFM_ETH_FMASK) != sc->bnx_flowflags) { + sc->bnx_flowflags = mii->mii_media_active & IFM_ETH_FMASK; + mii->mii_media_active &= ~IFM_ETH_FMASK; + } + /* Set MII or GMII interface based on the speed * negotiated by the PHY. */ @@ -1235,6 +1247,36 @@ bnx_miibus_statchg(struct ifnet *ifp) } REG_WR(sc, BNX_EMAC_MODE, val); + + /* + * 802.3x flow control + */ + if (sc->bnx_flowflags & IFM_ETH_RXPAUSE) { + DBPRINT(sc, BNX_INFO, "Enabling RX mode flow control.\n"); + rx_mode |= BNX_EMAC_RX_MODE_FLOW_EN; + } else { + DBPRINT(sc, BNX_INFO, "Disabling RX mode flow control.\n"); + rx_mode &= ~BNX_EMAC_RX_MODE_FLOW_EN; + } + + if (sc->bnx_flowflags & IFM_ETH_TXPAUSE) { + DBPRINT(sc, BNX_INFO, "Enabling TX mode flow control.\n"); + BNX_SETBIT(sc, BNX_EMAC_TX_MODE, BNX_EMAC_TX_MODE_FLOW_EN); + } else { + DBPRINT(sc, BNX_INFO, "Disabling TX mode flow control.\n"); + BNX_CLRBIT(sc, BNX_EMAC_TX_MODE, BNX_EMAC_TX_MODE_FLOW_EN); + } + + /* Only make changes if the recive mode has actually changed. */ + if (rx_mode != sc->rx_mode) { + DBPRINT(sc, BNX_VERBOSE, "Enabling new receive mode: 0x%08X\n", + rx_mode); + + sc->rx_mode = rx_mode; + REG_WR(sc, BNX_EMAC_RX_MODE, rx_mode); + + bnx_init_rx_context(sc); + } } /****************************************************************************/ @@ -4147,7 +4189,7 @@ bnx_free_tx_chain(struct bnx_softc *sc) /* Clear each TX chain page. */ for (i = 0; i < TX_PAGES; i++) { - memset((char *)sc->tx_bd_chain[i], 0, BNX_TX_CHAIN_PAGE_SZ); + memset(sc->tx_bd_chain[i], 0, BNX_TX_CHAIN_PAGE_SZ); bus_dmamap_sync(sc->bnx_dmatag, sc->tx_bd_chain_map[i], 0, BNX_TX_CHAIN_PAGE_SZ, BUS_DMASYNC_PREWRITE); } @@ -4178,22 +4220,8 @@ bnx_init_rx_context(struct bnx_softc *sc val = BNX_L2CTX_CTX_TYPE_CTX_BD_CHN_TYPE_VALUE | BNX_L2CTX_CTX_TYPE_SIZE_L2 | (0x02 << 8); - if (BNX_CHIP_NUM(sc) == BNX_CHIP_NUM_5709) { - uint32_t lo_water, hi_water; - - lo_water = BNX_L2CTX_RX_LO_WATER_MARK_DEFAULT; - hi_water = USABLE_RX_BD / 4; - - lo_water /= BNX_L2CTX_RX_LO_WATER_MARK_SCALE; - hi_water /= BNX_L2CTX_RX_HI_WATER_MARK_SCALE; - - if (hi_water > 0xf) - hi_water = 0xf; - else if (hi_water == 0) - lo_water = 0; - val |= lo_water | - (hi_water << BNX_L2CTX_RX_HI_WATER_MARK_SHIFT); - } + if (sc->bnx_flowflags & IFM_ETH_TXPAUSE) + val |= 0x000000ff; CTX_WR(sc, GET_CID_ADDR(RX_CID), BNX_L2CTX_CTX_TYPE, val); @@ -4319,7 +4347,7 @@ bnx_free_rx_chain(struct bnx_softc *sc) /* Clear each RX chain page. */ for (i = 0; i < RX_PAGES; i++) - memset((char *)sc->rx_bd_chain[i], 0, BNX_RX_CHAIN_PAGE_SZ); + memset(sc->rx_bd_chain[i], 0, BNX_RX_CHAIN_PAGE_SZ); sc->free_rx_bd = sc->max_rx_bd; @@ -4333,6 +4361,33 @@ bnx_free_rx_chain(struct bnx_softc *sc) } /****************************************************************************/ +/* Reports current media status. */ +/* */ +/* Returns: */ +/* Nothing. */ +/****************************************************************************/ +void +bnx_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr) +{ + struct bnx_softc *sc; + struct mii_data *mii; + int s; + + sc = ifp->if_softc; + + s = splnet(); + + mii = &sc->bnx_mii; + + mii_pollstat(mii); + ifmr->ifm_status = mii->mii_media_status; + ifmr->ifm_active = (mii->mii_media_active & ~IFM_ETH_FMASK) | + sc->bnx_flowflags; + + splx(s); +} + +/****************************************************************************/ /* Handles PHY generated interrupt events. */ /* */ /* Returns: */ @@ -5200,6 +5255,20 @@ bnx_ioctl(struct ifnet *ifp, u_long comm break; case SIOCSIFMEDIA: + /* Flow control requires full-duplex mode. */ + if (IFM_SUBTYPE(ifr->ifr_media) == IFM_AUTO || + (ifr->ifr_media & IFM_FDX) == 0) + ifr->ifr_media &= ~IFM_ETH_FMASK; + + if (IFM_SUBTYPE(ifr->ifr_media) != IFM_AUTO) { + if ((ifr->ifr_media & IFM_ETH_FMASK) == IFM_FLOW) { + /* We can do both TXPAUSE and RXPAUSE. */ + ifr->ifr_media |= + IFM_ETH_TXPAUSE | IFM_ETH_RXPAUSE; + } + sc->bnx_flowflags = ifr->ifr_media & IFM_ETH_FMASK; + } + /* FALLTHROUGH */ case SIOCGIFMEDIA: DBPRINT(sc, BNX_VERBOSE, "bnx_phy_flags = 0x%08X\n", sc->bnx_phy_flags); Index: src/sys/dev/pci/if_bnxvar.h diff -u src/sys/dev/pci/if_bnxvar.h:1.7 src/sys/dev/pci/if_bnxvar.h:1.8 --- src/sys/dev/pci/if_bnxvar.h:1.7 Tue May 8 04:11:09 2018 +++ src/sys/dev/pci/if_bnxvar.h Thu Mar 28 02:50:27 2019 @@ -149,6 +149,8 @@ struct bnx_softc uint32_t bnx_shared_hw_cfg; uint32_t bnx_port_hw_cfg; + int bnx_flowflags; + uint16_t bus_speed_mhz; /* PCI bus speed */ uint16_t link_width; /* PCIe link width */ uint16_t link_speed; /* PCIe link speed */