16c8d8eccSSepherosa Ziehau /* 26c8d8eccSSepherosa Ziehau * Copyright (c) 2001 Wind River Systems 36c8d8eccSSepherosa Ziehau * Copyright (c) 1997, 1998, 1999, 2001 46c8d8eccSSepherosa Ziehau * Bill Paul <wpaul@windriver.com>. All rights reserved. 56c8d8eccSSepherosa Ziehau * 66c8d8eccSSepherosa Ziehau * Redistribution and use in source and binary forms, with or without 76c8d8eccSSepherosa Ziehau * modification, are permitted provided that the following conditions 86c8d8eccSSepherosa Ziehau * are met: 96c8d8eccSSepherosa Ziehau * 1. Redistributions of source code must retain the above copyright 106c8d8eccSSepherosa Ziehau * notice, this list of conditions and the following disclaimer. 116c8d8eccSSepherosa Ziehau * 2. Redistributions in binary form must reproduce the above copyright 126c8d8eccSSepherosa Ziehau * notice, this list of conditions and the following disclaimer in the 136c8d8eccSSepherosa Ziehau * documentation and/or other materials provided with the distribution. 146c8d8eccSSepherosa Ziehau * 3. All advertising materials mentioning features or use of this software 156c8d8eccSSepherosa Ziehau * must display the following acknowledgement: 166c8d8eccSSepherosa Ziehau * This product includes software developed by Bill Paul. 176c8d8eccSSepherosa Ziehau * 4. Neither the name of the author nor the names of any co-contributors 186c8d8eccSSepherosa Ziehau * may be used to endorse or promote products derived from this software 196c8d8eccSSepherosa Ziehau * without specific prior written permission. 206c8d8eccSSepherosa Ziehau * 216c8d8eccSSepherosa Ziehau * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND 226c8d8eccSSepherosa Ziehau * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 236c8d8eccSSepherosa Ziehau * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 246c8d8eccSSepherosa Ziehau * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD 256c8d8eccSSepherosa Ziehau * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 266c8d8eccSSepherosa Ziehau * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 276c8d8eccSSepherosa Ziehau * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 286c8d8eccSSepherosa Ziehau * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 296c8d8eccSSepherosa Ziehau * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 306c8d8eccSSepherosa Ziehau * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 316c8d8eccSSepherosa Ziehau * THE POSSIBILITY OF SUCH DAMAGE. 326c8d8eccSSepherosa Ziehau * 336c8d8eccSSepherosa Ziehau * $FreeBSD: src/sys/dev/bge/if_bge.c,v 1.3.2.39 2005/07/03 03:41:18 silby Exp $ 346c8d8eccSSepherosa Ziehau */ 356c8d8eccSSepherosa Ziehau 3666deb1c1SSepherosa Ziehau #include "opt_bnx.h" 3739a8d43aSSepherosa Ziehau #include "opt_ifpoll.h" 386c8d8eccSSepherosa Ziehau 396c8d8eccSSepherosa Ziehau #include <sys/param.h> 406c8d8eccSSepherosa Ziehau #include <sys/bus.h> 416c8d8eccSSepherosa Ziehau #include <sys/endian.h> 426c8d8eccSSepherosa Ziehau #include <sys/kernel.h> 436c8d8eccSSepherosa Ziehau #include <sys/interrupt.h> 446c8d8eccSSepherosa Ziehau #include <sys/mbuf.h> 456c8d8eccSSepherosa Ziehau #include <sys/malloc.h> 466c8d8eccSSepherosa Ziehau #include <sys/queue.h> 476c8d8eccSSepherosa Ziehau #include <sys/rman.h> 486c8d8eccSSepherosa Ziehau #include <sys/serialize.h> 496c8d8eccSSepherosa Ziehau #include <sys/socket.h> 506c8d8eccSSepherosa Ziehau #include <sys/sockio.h> 516c8d8eccSSepherosa Ziehau #include <sys/sysctl.h> 526c8d8eccSSepherosa Ziehau 5366deb1c1SSepherosa Ziehau #include <netinet/ip.h> 5466deb1c1SSepherosa Ziehau #include <netinet/tcp.h> 5566deb1c1SSepherosa Ziehau 566c8d8eccSSepherosa Ziehau #include <net/bpf.h> 576c8d8eccSSepherosa Ziehau #include <net/ethernet.h> 586c8d8eccSSepherosa Ziehau #include <net/if.h> 596c8d8eccSSepherosa Ziehau #include <net/if_arp.h> 606c8d8eccSSepherosa Ziehau #include <net/if_dl.h> 616c8d8eccSSepherosa Ziehau #include <net/if_media.h> 6239a8d43aSSepherosa Ziehau #include <net/if_poll.h> 636c8d8eccSSepherosa Ziehau #include <net/if_types.h> 646c8d8eccSSepherosa Ziehau #include <net/ifq_var.h> 65*695a8586SSepherosa Ziehau #include <net/toeplitz.h> 66*695a8586SSepherosa Ziehau #include <net/toeplitz2.h> 676c8d8eccSSepherosa Ziehau #include <net/vlan/if_vlan_var.h> 686c8d8eccSSepherosa Ziehau #include <net/vlan/if_vlan_ether.h> 696c8d8eccSSepherosa Ziehau 706c8d8eccSSepherosa Ziehau #include <dev/netif/mii_layer/mii.h> 716c8d8eccSSepherosa Ziehau #include <dev/netif/mii_layer/miivar.h> 726c8d8eccSSepherosa Ziehau #include <dev/netif/mii_layer/brgphyreg.h> 736c8d8eccSSepherosa Ziehau 746c8d8eccSSepherosa Ziehau #include <bus/pci/pcidevs.h> 756c8d8eccSSepherosa Ziehau #include <bus/pci/pcireg.h> 766c8d8eccSSepherosa Ziehau #include <bus/pci/pcivar.h> 776c8d8eccSSepherosa Ziehau 786c8d8eccSSepherosa Ziehau #include <dev/netif/bge/if_bgereg.h> 796c8d8eccSSepherosa Ziehau #include <dev/netif/bnx/if_bnxvar.h> 806c8d8eccSSepherosa Ziehau 816c8d8eccSSepherosa Ziehau /* "device miibus" required. See GENERIC if you get errors here. */ 826c8d8eccSSepherosa Ziehau #include "miibus_if.h" 836c8d8eccSSepherosa Ziehau 843b18363fSSepherosa Ziehau #define BNX_CSUM_FEATURES (CSUM_IP | CSUM_TCP | CSUM_UDP) 856c8d8eccSSepherosa Ziehau 86df9ccc98SSepherosa Ziehau #define BNX_INTR_CKINTVL ((10 * hz) / 1000) /* 10ms */ 87df9ccc98SSepherosa Ziehau 88*695a8586SSepherosa Ziehau #ifdef BNX_RSS_DEBUG 89*695a8586SSepherosa Ziehau #define BNX_RSS_DPRINTF(sc, lvl, fmt, ...) \ 90*695a8586SSepherosa Ziehau do { \ 91*695a8586SSepherosa Ziehau if (sc->bnx_rss_debug >= lvl) \ 92*695a8586SSepherosa Ziehau if_printf(&sc->arpcom.ac_if, fmt, __VA_ARGS__); \ 93*695a8586SSepherosa Ziehau } while (0) 94*695a8586SSepherosa Ziehau #else /* !BNX_RSS_DEBUG */ 95*695a8586SSepherosa Ziehau #define BNX_RSS_DPRINTF(sc, lvl, fmt, ...) ((void)0) 96*695a8586SSepherosa Ziehau #endif /* BNX_RSS_DEBUG */ 97*695a8586SSepherosa Ziehau 986c8d8eccSSepherosa Ziehau static const struct bnx_type { 996c8d8eccSSepherosa Ziehau uint16_t bnx_vid; 1006c8d8eccSSepherosa Ziehau uint16_t bnx_did; 1016c8d8eccSSepherosa Ziehau char *bnx_name; 1026c8d8eccSSepherosa Ziehau } bnx_devs[] = { 1036c8d8eccSSepherosa Ziehau { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM5717, 1046c8d8eccSSepherosa Ziehau "Broadcom BCM5717 Gigabit Ethernet" }, 105d79f5d8fSSepherosa Ziehau { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM5717C, 106d79f5d8fSSepherosa Ziehau "Broadcom BCM5717C Gigabit Ethernet" }, 1076c8d8eccSSepherosa Ziehau { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM5718, 1086c8d8eccSSepherosa Ziehau "Broadcom BCM5718 Gigabit Ethernet" }, 1096c8d8eccSSepherosa Ziehau { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM5719, 1106c8d8eccSSepherosa Ziehau "Broadcom BCM5719 Gigabit Ethernet" }, 1116c8d8eccSSepherosa Ziehau { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM5720_ALT, 1126c8d8eccSSepherosa Ziehau "Broadcom BCM5720 Gigabit Ethernet" }, 1136c8d8eccSSepherosa Ziehau 114b96cbbb6SSepherosa Ziehau { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM5725, 115b96cbbb6SSepherosa Ziehau "Broadcom BCM5725 Gigabit Ethernet" }, 116b96cbbb6SSepherosa Ziehau { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM5727, 117b96cbbb6SSepherosa Ziehau "Broadcom BCM5727 Gigabit Ethernet" }, 118b96cbbb6SSepherosa Ziehau { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM5762, 119b96cbbb6SSepherosa Ziehau "Broadcom BCM5762 Gigabit Ethernet" }, 120b96cbbb6SSepherosa Ziehau 1216c8d8eccSSepherosa Ziehau { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM57761, 1226c8d8eccSSepherosa Ziehau "Broadcom BCM57761 Gigabit Ethernet" }, 12332ff3c80SSepherosa Ziehau { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM57762, 12432ff3c80SSepherosa Ziehau "Broadcom BCM57762 Gigabit Ethernet" }, 1256c8d8eccSSepherosa Ziehau { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM57765, 1266c8d8eccSSepherosa Ziehau "Broadcom BCM57765 Gigabit Ethernet" }, 12732ff3c80SSepherosa Ziehau { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM57766, 12832ff3c80SSepherosa Ziehau "Broadcom BCM57766 Gigabit Ethernet" }, 12932ff3c80SSepherosa Ziehau { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM57781, 13032ff3c80SSepherosa Ziehau "Broadcom BCM57781 Gigabit Ethernet" }, 13132ff3c80SSepherosa Ziehau { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM57782, 13232ff3c80SSepherosa Ziehau "Broadcom BCM57782 Gigabit Ethernet" }, 1336c8d8eccSSepherosa Ziehau { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM57785, 1346c8d8eccSSepherosa Ziehau "Broadcom BCM57785 Gigabit Ethernet" }, 13532ff3c80SSepherosa Ziehau { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM57786, 13632ff3c80SSepherosa Ziehau "Broadcom BCM57786 Gigabit Ethernet" }, 13732ff3c80SSepherosa Ziehau { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM57791, 13832ff3c80SSepherosa Ziehau "Broadcom BCM57791 Fast Ethernet" }, 1396c8d8eccSSepherosa Ziehau { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM57795, 1406c8d8eccSSepherosa Ziehau "Broadcom BCM57795 Fast Ethernet" }, 1416c8d8eccSSepherosa Ziehau 1426c8d8eccSSepherosa Ziehau { 0, 0, NULL } 1436c8d8eccSSepherosa Ziehau }; 1446c8d8eccSSepherosa Ziehau 1451c9d03f6SSepherosa Ziehau static const int bnx_tx_mailbox[BNX_TX_RING_MAX] = { 1461c9d03f6SSepherosa Ziehau BGE_MBX_TX_HOST_PROD0_LO, 1471c9d03f6SSepherosa Ziehau BGE_MBX_TX_HOST_PROD0_HI, 1481c9d03f6SSepherosa Ziehau BGE_MBX_TX_HOST_PROD1_LO, 1491c9d03f6SSepherosa Ziehau BGE_MBX_TX_HOST_PROD1_HI 1501c9d03f6SSepherosa Ziehau }; 1511c9d03f6SSepherosa Ziehau 1526c8d8eccSSepherosa Ziehau #define BNX_IS_JUMBO_CAPABLE(sc) ((sc)->bnx_flags & BNX_FLAG_JUMBO) 1536c8d8eccSSepherosa Ziehau #define BNX_IS_5717_PLUS(sc) ((sc)->bnx_flags & BNX_FLAG_5717_PLUS) 154f368d0d9SSepherosa Ziehau #define BNX_IS_57765_PLUS(sc) ((sc)->bnx_flags & BNX_FLAG_57765_PLUS) 155f368d0d9SSepherosa Ziehau #define BNX_IS_57765_FAMILY(sc) \ 156f368d0d9SSepherosa Ziehau ((sc)->bnx_flags & BNX_FLAG_57765_FAMILY) 1576c8d8eccSSepherosa Ziehau 1586c8d8eccSSepherosa Ziehau typedef int (*bnx_eaddr_fcn_t)(struct bnx_softc *, uint8_t[]); 1596c8d8eccSSepherosa Ziehau 1606c8d8eccSSepherosa Ziehau static int bnx_probe(device_t); 1616c8d8eccSSepherosa Ziehau static int bnx_attach(device_t); 1626c8d8eccSSepherosa Ziehau static int bnx_detach(device_t); 1636c8d8eccSSepherosa Ziehau static void bnx_shutdown(device_t); 1646c8d8eccSSepherosa Ziehau static int bnx_suspend(device_t); 1656c8d8eccSSepherosa Ziehau static int bnx_resume(device_t); 1666c8d8eccSSepherosa Ziehau static int bnx_miibus_readreg(device_t, int, int); 1676c8d8eccSSepherosa Ziehau static int bnx_miibus_writereg(device_t, int, int, int); 1686c8d8eccSSepherosa Ziehau static void bnx_miibus_statchg(device_t); 1696c8d8eccSSepherosa Ziehau 170*695a8586SSepherosa Ziehau static void bnx_handle_status(struct bnx_softc *); 17139a8d43aSSepherosa Ziehau #ifdef IFPOLL_ENABLE 17239a8d43aSSepherosa Ziehau static void bnx_npoll(struct ifnet *, struct ifpoll_info *); 1734fa38985SSepherosa Ziehau static void bnx_npoll_rx(struct ifnet *, void *, int); 1744fa38985SSepherosa Ziehau static void bnx_npoll_tx(struct ifnet *, void *, int); 175*695a8586SSepherosa Ziehau static void bnx_npoll_tx_notag(struct ifnet *, void *, int); 1764fa38985SSepherosa Ziehau static void bnx_npoll_status(struct ifnet *); 177*695a8586SSepherosa Ziehau static void bnx_npoll_status_notag(struct ifnet *); 1786c8d8eccSSepherosa Ziehau #endif 1796c8d8eccSSepherosa Ziehau static void bnx_intr_legacy(void *); 18003cc99fdSSepherosa Ziehau static void bnx_msi(void *); 1816c8d8eccSSepherosa Ziehau static void bnx_intr(struct bnx_softc *); 182*695a8586SSepherosa Ziehau static void bnx_msix_status(void *); 183*695a8586SSepherosa Ziehau static void bnx_msix_tx_status(void *); 184*695a8586SSepherosa Ziehau static void bnx_msix_rx(void *); 185*695a8586SSepherosa Ziehau static void bnx_msix_rxtx(void *); 1866c8d8eccSSepherosa Ziehau static void bnx_enable_intr(struct bnx_softc *); 1876c8d8eccSSepherosa Ziehau static void bnx_disable_intr(struct bnx_softc *); 18833a04907SSepherosa Ziehau static void bnx_txeof(struct bnx_tx_ring *, uint16_t); 189beedf5beSSepherosa Ziehau static void bnx_rxeof(struct bnx_rx_ret_ring *, uint16_t, int); 1900c7da01dSSepherosa Ziehau static int bnx_alloc_intr(struct bnx_softc *); 1910c7da01dSSepherosa Ziehau static int bnx_setup_intr(struct bnx_softc *); 1920c7da01dSSepherosa Ziehau static void bnx_free_intr(struct bnx_softc *); 193f33ac8a4SSepherosa Ziehau static void bnx_teardown_intr(struct bnx_softc *, int); 194*695a8586SSepherosa Ziehau static int bnx_alloc_msix(struct bnx_softc *); 195*695a8586SSepherosa Ziehau static void bnx_free_msix(struct bnx_softc *, boolean_t); 196*695a8586SSepherosa Ziehau static void bnx_check_intr_rxtx(void *); 197*695a8586SSepherosa Ziehau static void bnx_check_intr_rx(void *); 198*695a8586SSepherosa Ziehau static void bnx_check_intr_tx(void *); 199841cdf08SSepherosa Ziehau static void bnx_rx_std_refill_ithread(void *); 200841cdf08SSepherosa Ziehau static void bnx_rx_std_refill(void *, void *); 201*695a8586SSepherosa Ziehau static void bnx_rx_std_refill_sched_ipi(void *); 202*695a8586SSepherosa Ziehau static void bnx_rx_std_refill_stop(void *); 203*695a8586SSepherosa Ziehau static void bnx_rx_std_refill_sched(struct bnx_rx_ret_ring *, 204*695a8586SSepherosa Ziehau struct bnx_rx_std_ring *); 2056c8d8eccSSepherosa Ziehau 206f0a26983SSepherosa Ziehau static void bnx_start(struct ifnet *, struct ifaltq_subque *); 2076c8d8eccSSepherosa Ziehau static int bnx_ioctl(struct ifnet *, u_long, caddr_t, struct ucred *); 2086c8d8eccSSepherosa Ziehau static void bnx_init(void *); 2096c8d8eccSSepherosa Ziehau static void bnx_stop(struct bnx_softc *); 2103397dea6SSepherosa Ziehau static void bnx_watchdog(struct ifaltq_subque *); 2116c8d8eccSSepherosa Ziehau static int bnx_ifmedia_upd(struct ifnet *); 2126c8d8eccSSepherosa Ziehau static void bnx_ifmedia_sts(struct ifnet *, struct ifmediareq *); 2136c8d8eccSSepherosa Ziehau static void bnx_tick(void *); 214329f9016SSepherosa Ziehau static void bnx_serialize(struct ifnet *, enum ifnet_serialize); 215329f9016SSepherosa Ziehau static void bnx_deserialize(struct ifnet *, enum ifnet_serialize); 216329f9016SSepherosa Ziehau static int bnx_tryserialize(struct ifnet *, enum ifnet_serialize); 217329f9016SSepherosa Ziehau #ifdef INVARIANTS 218329f9016SSepherosa Ziehau static void bnx_serialize_assert(struct ifnet *, enum ifnet_serialize, 219329f9016SSepherosa Ziehau boolean_t); 220329f9016SSepherosa Ziehau #endif 221*695a8586SSepherosa Ziehau static void bnx_serialize_skipmain(struct bnx_softc *); 222*695a8586SSepherosa Ziehau static void bnx_deserialize_skipmain(struct bnx_softc *sc); 2236c8d8eccSSepherosa Ziehau 2246c8d8eccSSepherosa Ziehau static int bnx_alloc_jumbo_mem(struct bnx_softc *); 2256c8d8eccSSepherosa Ziehau static void bnx_free_jumbo_mem(struct bnx_softc *); 2266c8d8eccSSepherosa Ziehau static struct bnx_jslot 2276c8d8eccSSepherosa Ziehau *bnx_jalloc(struct bnx_softc *); 2286c8d8eccSSepherosa Ziehau static void bnx_jfree(void *); 2296c8d8eccSSepherosa Ziehau static void bnx_jref(void *); 230beedf5beSSepherosa Ziehau static int bnx_newbuf_std(struct bnx_rx_ret_ring *, int, int); 2316c8d8eccSSepherosa Ziehau static int bnx_newbuf_jumbo(struct bnx_softc *, int, int); 232beedf5beSSepherosa Ziehau static void bnx_setup_rxdesc_std(struct bnx_rx_std_ring *, int); 2336c8d8eccSSepherosa Ziehau static void bnx_setup_rxdesc_jumbo(struct bnx_softc *, int); 234beedf5beSSepherosa Ziehau static int bnx_init_rx_ring_std(struct bnx_rx_std_ring *); 235beedf5beSSepherosa Ziehau static void bnx_free_rx_ring_std(struct bnx_rx_std_ring *); 2366c8d8eccSSepherosa Ziehau static int bnx_init_rx_ring_jumbo(struct bnx_softc *); 2376c8d8eccSSepherosa Ziehau static void bnx_free_rx_ring_jumbo(struct bnx_softc *); 23833a04907SSepherosa Ziehau static void bnx_free_tx_ring(struct bnx_tx_ring *); 23933a04907SSepherosa Ziehau static int bnx_init_tx_ring(struct bnx_tx_ring *); 24033a04907SSepherosa Ziehau static int bnx_create_tx_ring(struct bnx_tx_ring *); 24133a04907SSepherosa Ziehau static void bnx_destroy_tx_ring(struct bnx_tx_ring *); 242beedf5beSSepherosa Ziehau static int bnx_create_rx_ret_ring(struct bnx_rx_ret_ring *); 243beedf5beSSepherosa Ziehau static void bnx_destroy_rx_ret_ring(struct bnx_rx_ret_ring *); 244beedf5beSSepherosa Ziehau static int bnx_dma_alloc(device_t); 2456c8d8eccSSepherosa Ziehau static void bnx_dma_free(struct bnx_softc *); 2466c8d8eccSSepherosa Ziehau static int bnx_dma_block_alloc(struct bnx_softc *, bus_size_t, 2476c8d8eccSSepherosa Ziehau bus_dma_tag_t *, bus_dmamap_t *, void **, bus_addr_t *); 2486c8d8eccSSepherosa Ziehau static void bnx_dma_block_free(bus_dma_tag_t, bus_dmamap_t, void *); 2496c8d8eccSSepherosa Ziehau static struct mbuf * 2506c8d8eccSSepherosa Ziehau bnx_defrag_shortdma(struct mbuf *); 25133a04907SSepherosa Ziehau static int bnx_encap(struct bnx_tx_ring *, struct mbuf **, 252c9b7f592SSepherosa Ziehau uint32_t *, int *); 25333a04907SSepherosa Ziehau static int bnx_setup_tso(struct bnx_tx_ring *, struct mbuf **, 25466deb1c1SSepherosa Ziehau uint16_t *, uint16_t *); 255329f9016SSepherosa Ziehau static void bnx_setup_serialize(struct bnx_softc *); 2567dbaa833SSepherosa Ziehau static void bnx_set_tick_cpuid(struct bnx_softc *, boolean_t); 257*695a8586SSepherosa Ziehau static void bnx_setup_ring_cnt(struct bnx_softc *); 2586c8d8eccSSepherosa Ziehau 259*695a8586SSepherosa Ziehau static void bnx_init_rss(struct bnx_softc *); 2606c8d8eccSSepherosa Ziehau static void bnx_reset(struct bnx_softc *); 2616c8d8eccSSepherosa Ziehau static int bnx_chipinit(struct bnx_softc *); 2626c8d8eccSSepherosa Ziehau static int bnx_blockinit(struct bnx_softc *); 2636c8d8eccSSepherosa Ziehau static void bnx_stop_block(struct bnx_softc *, bus_size_t, uint32_t); 264*695a8586SSepherosa Ziehau static void bnx_enable_msi(struct bnx_softc *, boolean_t); 2656c8d8eccSSepherosa Ziehau static void bnx_setmulti(struct bnx_softc *); 2666c8d8eccSSepherosa Ziehau static void bnx_setpromisc(struct bnx_softc *); 2676c8d8eccSSepherosa Ziehau static void bnx_stats_update_regs(struct bnx_softc *); 2686c8d8eccSSepherosa Ziehau static uint32_t bnx_dma_swap_options(struct bnx_softc *); 2696c8d8eccSSepherosa Ziehau 2706c8d8eccSSepherosa Ziehau static uint32_t bnx_readmem_ind(struct bnx_softc *, uint32_t); 2716c8d8eccSSepherosa Ziehau static void bnx_writemem_ind(struct bnx_softc *, uint32_t, uint32_t); 2726c8d8eccSSepherosa Ziehau #ifdef notdef 2736c8d8eccSSepherosa Ziehau static uint32_t bnx_readreg_ind(struct bnx_softc *, uint32_t); 2746c8d8eccSSepherosa Ziehau #endif 2756c8d8eccSSepherosa Ziehau static void bnx_writemem_direct(struct bnx_softc *, uint32_t, uint32_t); 2766c8d8eccSSepherosa Ziehau static void bnx_writembx(struct bnx_softc *, int, int); 2776c8d8eccSSepherosa Ziehau static int bnx_read_nvram(struct bnx_softc *, caddr_t, int, int); 2786c8d8eccSSepherosa Ziehau static uint8_t bnx_eeprom_getbyte(struct bnx_softc *, uint32_t, uint8_t *); 2796c8d8eccSSepherosa Ziehau static int bnx_read_eeprom(struct bnx_softc *, caddr_t, uint32_t, size_t); 2806c8d8eccSSepherosa Ziehau 2816c8d8eccSSepherosa Ziehau static void bnx_tbi_link_upd(struct bnx_softc *, uint32_t); 2826c8d8eccSSepherosa Ziehau static void bnx_copper_link_upd(struct bnx_softc *, uint32_t); 2836c8d8eccSSepherosa Ziehau static void bnx_autopoll_link_upd(struct bnx_softc *, uint32_t); 2846c8d8eccSSepherosa Ziehau static void bnx_link_poll(struct bnx_softc *); 2856c8d8eccSSepherosa Ziehau 2866c8d8eccSSepherosa Ziehau static int bnx_get_eaddr_mem(struct bnx_softc *, uint8_t[]); 2876c8d8eccSSepherosa Ziehau static int bnx_get_eaddr_nvram(struct bnx_softc *, uint8_t[]); 2886c8d8eccSSepherosa Ziehau static int bnx_get_eaddr_eeprom(struct bnx_softc *, uint8_t[]); 2896c8d8eccSSepherosa Ziehau static int bnx_get_eaddr(struct bnx_softc *, uint8_t[]); 2906c8d8eccSSepherosa Ziehau 2916c8d8eccSSepherosa Ziehau static void bnx_coal_change(struct bnx_softc *); 292aad4de2bSSepherosa Ziehau static int bnx_sysctl_force_defrag(SYSCTL_HANDLER_ARGS); 293472c99c8SSepherosa Ziehau static int bnx_sysctl_tx_wreg(SYSCTL_HANDLER_ARGS); 2946c8d8eccSSepherosa Ziehau static int bnx_sysctl_rx_coal_ticks(SYSCTL_HANDLER_ARGS); 2956c8d8eccSSepherosa Ziehau static int bnx_sysctl_tx_coal_ticks(SYSCTL_HANDLER_ARGS); 2966c8d8eccSSepherosa Ziehau static int bnx_sysctl_rx_coal_bds(SYSCTL_HANDLER_ARGS); 2976c8d8eccSSepherosa Ziehau static int bnx_sysctl_tx_coal_bds(SYSCTL_HANDLER_ARGS); 2986c8d8eccSSepherosa Ziehau static int bnx_sysctl_rx_coal_bds_int(SYSCTL_HANDLER_ARGS); 2996c8d8eccSSepherosa Ziehau static int bnx_sysctl_tx_coal_bds_int(SYSCTL_HANDLER_ARGS); 3006c8d8eccSSepherosa Ziehau static int bnx_sysctl_coal_chg(SYSCTL_HANDLER_ARGS, uint32_t *, 3016c8d8eccSSepherosa Ziehau int, int, uint32_t); 3024fa38985SSepherosa Ziehau #ifdef IFPOLL_ENABLE 3034fa38985SSepherosa Ziehau static int bnx_sysctl_npoll_offset(SYSCTL_HANDLER_ARGS); 3044fa38985SSepherosa Ziehau static int bnx_sysctl_npoll_rxoff(SYSCTL_HANDLER_ARGS); 3054fa38985SSepherosa Ziehau static int bnx_sysctl_npoll_txoff(SYSCTL_HANDLER_ARGS); 3064fa38985SSepherosa Ziehau #endif 307841cdf08SSepherosa Ziehau static int bnx_sysctl_std_refill(SYSCTL_HANDLER_ARGS); 3086c8d8eccSSepherosa Ziehau 3096c8d8eccSSepherosa Ziehau static int bnx_msi_enable = 1; 310*695a8586SSepherosa Ziehau static int bnx_msix_enable = 1; 311*695a8586SSepherosa Ziehau 312*695a8586SSepherosa Ziehau static int bnx_rx_rings = 0; /* auto */ 313*695a8586SSepherosa Ziehau static int bnx_tx_rings = 0; /* auto */ 314*695a8586SSepherosa Ziehau 3156c8d8eccSSepherosa Ziehau TUNABLE_INT("hw.bnx.msi.enable", &bnx_msi_enable); 316*695a8586SSepherosa Ziehau TUNABLE_INT("hw.bnx.msix.enable", &bnx_msix_enable); 317*695a8586SSepherosa Ziehau TUNABLE_INT("hw.bnx.rx_rings", &bnx_rx_rings); 318*695a8586SSepherosa Ziehau TUNABLE_INT("hw.bnx.tx_rings", &bnx_tx_rings); 3196c8d8eccSSepherosa Ziehau 3206c8d8eccSSepherosa Ziehau static device_method_t bnx_methods[] = { 3216c8d8eccSSepherosa Ziehau /* Device interface */ 3226c8d8eccSSepherosa Ziehau DEVMETHOD(device_probe, bnx_probe), 3236c8d8eccSSepherosa Ziehau DEVMETHOD(device_attach, bnx_attach), 3246c8d8eccSSepherosa Ziehau DEVMETHOD(device_detach, bnx_detach), 3256c8d8eccSSepherosa Ziehau DEVMETHOD(device_shutdown, bnx_shutdown), 3266c8d8eccSSepherosa Ziehau DEVMETHOD(device_suspend, bnx_suspend), 3276c8d8eccSSepherosa Ziehau DEVMETHOD(device_resume, bnx_resume), 3286c8d8eccSSepherosa Ziehau 3296c8d8eccSSepherosa Ziehau /* bus interface */ 3306c8d8eccSSepherosa Ziehau DEVMETHOD(bus_print_child, bus_generic_print_child), 3316c8d8eccSSepherosa Ziehau DEVMETHOD(bus_driver_added, bus_generic_driver_added), 3326c8d8eccSSepherosa Ziehau 3336c8d8eccSSepherosa Ziehau /* MII interface */ 3346c8d8eccSSepherosa Ziehau DEVMETHOD(miibus_readreg, bnx_miibus_readreg), 3356c8d8eccSSepherosa Ziehau DEVMETHOD(miibus_writereg, bnx_miibus_writereg), 3366c8d8eccSSepherosa Ziehau DEVMETHOD(miibus_statchg, bnx_miibus_statchg), 3376c8d8eccSSepherosa Ziehau 338d3c9c58eSSascha Wildner DEVMETHOD_END 3396c8d8eccSSepherosa Ziehau }; 3406c8d8eccSSepherosa Ziehau 3416c8d8eccSSepherosa Ziehau static DEFINE_CLASS_0(bnx, bnx_driver, bnx_methods, sizeof(struct bnx_softc)); 3426c8d8eccSSepherosa Ziehau static devclass_t bnx_devclass; 3436c8d8eccSSepherosa Ziehau 3446c8d8eccSSepherosa Ziehau DECLARE_DUMMY_MODULE(if_bnx); 3456c8d8eccSSepherosa Ziehau DRIVER_MODULE(if_bnx, pci, bnx_driver, bnx_devclass, NULL, NULL); 3466c8d8eccSSepherosa Ziehau DRIVER_MODULE(miibus, bnx, miibus_driver, miibus_devclass, NULL, NULL); 3476c8d8eccSSepherosa Ziehau 3486c8d8eccSSepherosa Ziehau static uint32_t 3496c8d8eccSSepherosa Ziehau bnx_readmem_ind(struct bnx_softc *sc, uint32_t off) 3506c8d8eccSSepherosa Ziehau { 3516c8d8eccSSepherosa Ziehau device_t dev = sc->bnx_dev; 3526c8d8eccSSepherosa Ziehau uint32_t val; 3536c8d8eccSSepherosa Ziehau 3546c8d8eccSSepherosa Ziehau pci_write_config(dev, BGE_PCI_MEMWIN_BASEADDR, off, 4); 3556c8d8eccSSepherosa Ziehau val = pci_read_config(dev, BGE_PCI_MEMWIN_DATA, 4); 3566c8d8eccSSepherosa Ziehau pci_write_config(dev, BGE_PCI_MEMWIN_BASEADDR, 0, 4); 3576c8d8eccSSepherosa Ziehau return (val); 3586c8d8eccSSepherosa Ziehau } 3596c8d8eccSSepherosa Ziehau 3606c8d8eccSSepherosa Ziehau static void 3616c8d8eccSSepherosa Ziehau bnx_writemem_ind(struct bnx_softc *sc, uint32_t off, uint32_t val) 3626c8d8eccSSepherosa Ziehau { 3636c8d8eccSSepherosa Ziehau device_t dev = sc->bnx_dev; 3646c8d8eccSSepherosa Ziehau 3656c8d8eccSSepherosa Ziehau pci_write_config(dev, BGE_PCI_MEMWIN_BASEADDR, off, 4); 3666c8d8eccSSepherosa Ziehau pci_write_config(dev, BGE_PCI_MEMWIN_DATA, val, 4); 3676c8d8eccSSepherosa Ziehau pci_write_config(dev, BGE_PCI_MEMWIN_BASEADDR, 0, 4); 3686c8d8eccSSepherosa Ziehau } 3696c8d8eccSSepherosa Ziehau 3706c8d8eccSSepherosa Ziehau static void 3716c8d8eccSSepherosa Ziehau bnx_writemem_direct(struct bnx_softc *sc, uint32_t off, uint32_t val) 3726c8d8eccSSepherosa Ziehau { 3736c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, off, val); 3746c8d8eccSSepherosa Ziehau } 3756c8d8eccSSepherosa Ziehau 3766c8d8eccSSepherosa Ziehau static void 3776c8d8eccSSepherosa Ziehau bnx_writembx(struct bnx_softc *sc, int off, int val) 3786c8d8eccSSepherosa Ziehau { 3796c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, off, val); 3806c8d8eccSSepherosa Ziehau } 3816c8d8eccSSepherosa Ziehau 3826c8d8eccSSepherosa Ziehau /* 3836c8d8eccSSepherosa Ziehau * Read a sequence of bytes from NVRAM. 3846c8d8eccSSepherosa Ziehau */ 3856c8d8eccSSepherosa Ziehau static int 3866c8d8eccSSepherosa Ziehau bnx_read_nvram(struct bnx_softc *sc, caddr_t dest, int off, int cnt) 3876c8d8eccSSepherosa Ziehau { 3886c8d8eccSSepherosa Ziehau return (1); 3896c8d8eccSSepherosa Ziehau } 3906c8d8eccSSepherosa Ziehau 3916c8d8eccSSepherosa Ziehau /* 3926c8d8eccSSepherosa Ziehau * Read a byte of data stored in the EEPROM at address 'addr.' The 3936c8d8eccSSepherosa Ziehau * BCM570x supports both the traditional bitbang interface and an 3946c8d8eccSSepherosa Ziehau * auto access interface for reading the EEPROM. We use the auto 3956c8d8eccSSepherosa Ziehau * access method. 3966c8d8eccSSepherosa Ziehau */ 3976c8d8eccSSepherosa Ziehau static uint8_t 3986c8d8eccSSepherosa Ziehau bnx_eeprom_getbyte(struct bnx_softc *sc, uint32_t addr, uint8_t *dest) 3996c8d8eccSSepherosa Ziehau { 4006c8d8eccSSepherosa Ziehau int i; 4016c8d8eccSSepherosa Ziehau uint32_t byte = 0; 4026c8d8eccSSepherosa Ziehau 4036c8d8eccSSepherosa Ziehau /* 4046c8d8eccSSepherosa Ziehau * Enable use of auto EEPROM access so we can avoid 4056c8d8eccSSepherosa Ziehau * having to use the bitbang method. 4066c8d8eccSSepherosa Ziehau */ 4076c8d8eccSSepherosa Ziehau BNX_SETBIT(sc, BGE_MISC_LOCAL_CTL, BGE_MLC_AUTO_EEPROM); 4086c8d8eccSSepherosa Ziehau 4096c8d8eccSSepherosa Ziehau /* Reset the EEPROM, load the clock period. */ 4106c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_EE_ADDR, 4116c8d8eccSSepherosa Ziehau BGE_EEADDR_RESET|BGE_EEHALFCLK(BGE_HALFCLK_384SCL)); 4126c8d8eccSSepherosa Ziehau DELAY(20); 4136c8d8eccSSepherosa Ziehau 4146c8d8eccSSepherosa Ziehau /* Issue the read EEPROM command. */ 4156c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_EE_ADDR, BGE_EE_READCMD | addr); 4166c8d8eccSSepherosa Ziehau 4176c8d8eccSSepherosa Ziehau /* Wait for completion */ 4186c8d8eccSSepherosa Ziehau for(i = 0; i < BNX_TIMEOUT * 10; i++) { 4196c8d8eccSSepherosa Ziehau DELAY(10); 4206c8d8eccSSepherosa Ziehau if (CSR_READ_4(sc, BGE_EE_ADDR) & BGE_EEADDR_DONE) 4216c8d8eccSSepherosa Ziehau break; 4226c8d8eccSSepherosa Ziehau } 4236c8d8eccSSepherosa Ziehau 4246c8d8eccSSepherosa Ziehau if (i == BNX_TIMEOUT) { 4256c8d8eccSSepherosa Ziehau if_printf(&sc->arpcom.ac_if, "eeprom read timed out\n"); 4266c8d8eccSSepherosa Ziehau return(1); 4276c8d8eccSSepherosa Ziehau } 4286c8d8eccSSepherosa Ziehau 4296c8d8eccSSepherosa Ziehau /* Get result. */ 4306c8d8eccSSepherosa Ziehau byte = CSR_READ_4(sc, BGE_EE_DATA); 4316c8d8eccSSepherosa Ziehau 4326c8d8eccSSepherosa Ziehau *dest = (byte >> ((addr % 4) * 8)) & 0xFF; 4336c8d8eccSSepherosa Ziehau 4346c8d8eccSSepherosa Ziehau return(0); 4356c8d8eccSSepherosa Ziehau } 4366c8d8eccSSepherosa Ziehau 4376c8d8eccSSepherosa Ziehau /* 4386c8d8eccSSepherosa Ziehau * Read a sequence of bytes from the EEPROM. 4396c8d8eccSSepherosa Ziehau */ 4406c8d8eccSSepherosa Ziehau static int 4416c8d8eccSSepherosa Ziehau bnx_read_eeprom(struct bnx_softc *sc, caddr_t dest, uint32_t off, size_t len) 4426c8d8eccSSepherosa Ziehau { 4436c8d8eccSSepherosa Ziehau size_t i; 4446c8d8eccSSepherosa Ziehau int err; 4456c8d8eccSSepherosa Ziehau uint8_t byte; 4466c8d8eccSSepherosa Ziehau 4476c8d8eccSSepherosa Ziehau for (byte = 0, err = 0, i = 0; i < len; i++) { 4486c8d8eccSSepherosa Ziehau err = bnx_eeprom_getbyte(sc, off + i, &byte); 4496c8d8eccSSepherosa Ziehau if (err) 4506c8d8eccSSepherosa Ziehau break; 4516c8d8eccSSepherosa Ziehau *(dest + i) = byte; 4526c8d8eccSSepherosa Ziehau } 4536c8d8eccSSepherosa Ziehau 4546c8d8eccSSepherosa Ziehau return(err ? 1 : 0); 4556c8d8eccSSepherosa Ziehau } 4566c8d8eccSSepherosa Ziehau 4576c8d8eccSSepherosa Ziehau static int 4586c8d8eccSSepherosa Ziehau bnx_miibus_readreg(device_t dev, int phy, int reg) 4596c8d8eccSSepherosa Ziehau { 4606c8d8eccSSepherosa Ziehau struct bnx_softc *sc = device_get_softc(dev); 4616c8d8eccSSepherosa Ziehau uint32_t val; 4626c8d8eccSSepherosa Ziehau int i; 4636c8d8eccSSepherosa Ziehau 4646c8d8eccSSepherosa Ziehau KASSERT(phy == sc->bnx_phyno, 4656c8d8eccSSepherosa Ziehau ("invalid phyno %d, should be %d", phy, sc->bnx_phyno)); 4666c8d8eccSSepherosa Ziehau 4676c8d8eccSSepherosa Ziehau /* Clear the autopoll bit if set, otherwise may trigger PCI errors. */ 4686c8d8eccSSepherosa Ziehau if (sc->bnx_mi_mode & BGE_MIMODE_AUTOPOLL) { 4696c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_MI_MODE, 4706c8d8eccSSepherosa Ziehau sc->bnx_mi_mode & ~BGE_MIMODE_AUTOPOLL); 4716c8d8eccSSepherosa Ziehau DELAY(80); 4726c8d8eccSSepherosa Ziehau } 4736c8d8eccSSepherosa Ziehau 4746c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_MI_COMM, BGE_MICMD_READ | BGE_MICOMM_BUSY | 4756c8d8eccSSepherosa Ziehau BGE_MIPHY(phy) | BGE_MIREG(reg)); 4766c8d8eccSSepherosa Ziehau 4776c8d8eccSSepherosa Ziehau /* Poll for the PHY register access to complete. */ 4786c8d8eccSSepherosa Ziehau for (i = 0; i < BNX_TIMEOUT; i++) { 4796c8d8eccSSepherosa Ziehau DELAY(10); 4806c8d8eccSSepherosa Ziehau val = CSR_READ_4(sc, BGE_MI_COMM); 4816c8d8eccSSepherosa Ziehau if ((val & BGE_MICOMM_BUSY) == 0) { 4826c8d8eccSSepherosa Ziehau DELAY(5); 4836c8d8eccSSepherosa Ziehau val = CSR_READ_4(sc, BGE_MI_COMM); 4846c8d8eccSSepherosa Ziehau break; 4856c8d8eccSSepherosa Ziehau } 4866c8d8eccSSepherosa Ziehau } 4876c8d8eccSSepherosa Ziehau if (i == BNX_TIMEOUT) { 4886c8d8eccSSepherosa Ziehau if_printf(&sc->arpcom.ac_if, "PHY read timed out " 4896c8d8eccSSepherosa Ziehau "(phy %d, reg %d, val 0x%08x)\n", phy, reg, val); 4906c8d8eccSSepherosa Ziehau val = 0; 4916c8d8eccSSepherosa Ziehau } 4926c8d8eccSSepherosa Ziehau 4936c8d8eccSSepherosa Ziehau /* Restore the autopoll bit if necessary. */ 4946c8d8eccSSepherosa Ziehau if (sc->bnx_mi_mode & BGE_MIMODE_AUTOPOLL) { 4956c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_MI_MODE, sc->bnx_mi_mode); 4966c8d8eccSSepherosa Ziehau DELAY(80); 4976c8d8eccSSepherosa Ziehau } 4986c8d8eccSSepherosa Ziehau 4996c8d8eccSSepherosa Ziehau if (val & BGE_MICOMM_READFAIL) 5006c8d8eccSSepherosa Ziehau return 0; 5016c8d8eccSSepherosa Ziehau 5026c8d8eccSSepherosa Ziehau return (val & 0xFFFF); 5036c8d8eccSSepherosa Ziehau } 5046c8d8eccSSepherosa Ziehau 5056c8d8eccSSepherosa Ziehau static int 5066c8d8eccSSepherosa Ziehau bnx_miibus_writereg(device_t dev, int phy, int reg, int val) 5076c8d8eccSSepherosa Ziehau { 5086c8d8eccSSepherosa Ziehau struct bnx_softc *sc = device_get_softc(dev); 5096c8d8eccSSepherosa Ziehau int i; 5106c8d8eccSSepherosa Ziehau 5116c8d8eccSSepherosa Ziehau KASSERT(phy == sc->bnx_phyno, 5126c8d8eccSSepherosa Ziehau ("invalid phyno %d, should be %d", phy, sc->bnx_phyno)); 5136c8d8eccSSepherosa Ziehau 5146c8d8eccSSepherosa Ziehau /* Clear the autopoll bit if set, otherwise may trigger PCI errors. */ 5156c8d8eccSSepherosa Ziehau if (sc->bnx_mi_mode & BGE_MIMODE_AUTOPOLL) { 5166c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_MI_MODE, 5176c8d8eccSSepherosa Ziehau sc->bnx_mi_mode & ~BGE_MIMODE_AUTOPOLL); 5186c8d8eccSSepherosa Ziehau DELAY(80); 5196c8d8eccSSepherosa Ziehau } 5206c8d8eccSSepherosa Ziehau 5216c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_MI_COMM, BGE_MICMD_WRITE | BGE_MICOMM_BUSY | 5226c8d8eccSSepherosa Ziehau BGE_MIPHY(phy) | BGE_MIREG(reg) | val); 5236c8d8eccSSepherosa Ziehau 5246c8d8eccSSepherosa Ziehau for (i = 0; i < BNX_TIMEOUT; i++) { 5256c8d8eccSSepherosa Ziehau DELAY(10); 5266c8d8eccSSepherosa Ziehau if (!(CSR_READ_4(sc, BGE_MI_COMM) & BGE_MICOMM_BUSY)) { 5276c8d8eccSSepherosa Ziehau DELAY(5); 5286c8d8eccSSepherosa Ziehau CSR_READ_4(sc, BGE_MI_COMM); /* dummy read */ 5296c8d8eccSSepherosa Ziehau break; 5306c8d8eccSSepherosa Ziehau } 5316c8d8eccSSepherosa Ziehau } 5326c8d8eccSSepherosa Ziehau if (i == BNX_TIMEOUT) { 5336c8d8eccSSepherosa Ziehau if_printf(&sc->arpcom.ac_if, "PHY write timed out " 5346c8d8eccSSepherosa Ziehau "(phy %d, reg %d, val %d)\n", phy, reg, val); 5356c8d8eccSSepherosa Ziehau } 5366c8d8eccSSepherosa Ziehau 5376c8d8eccSSepherosa Ziehau /* Restore the autopoll bit if necessary. */ 5386c8d8eccSSepherosa Ziehau if (sc->bnx_mi_mode & BGE_MIMODE_AUTOPOLL) { 5396c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_MI_MODE, sc->bnx_mi_mode); 5406c8d8eccSSepherosa Ziehau DELAY(80); 5416c8d8eccSSepherosa Ziehau } 5426c8d8eccSSepherosa Ziehau 5436c8d8eccSSepherosa Ziehau return 0; 5446c8d8eccSSepherosa Ziehau } 5456c8d8eccSSepherosa Ziehau 5466c8d8eccSSepherosa Ziehau static void 5476c8d8eccSSepherosa Ziehau bnx_miibus_statchg(device_t dev) 5486c8d8eccSSepherosa Ziehau { 5496c8d8eccSSepherosa Ziehau struct bnx_softc *sc; 5506c8d8eccSSepherosa Ziehau struct mii_data *mii; 5516c8d8eccSSepherosa Ziehau 5526c8d8eccSSepherosa Ziehau sc = device_get_softc(dev); 5536c8d8eccSSepherosa Ziehau mii = device_get_softc(sc->bnx_miibus); 5546c8d8eccSSepherosa Ziehau 5556c8d8eccSSepherosa Ziehau if ((mii->mii_media_status & (IFM_ACTIVE | IFM_AVALID)) == 5566c8d8eccSSepherosa Ziehau (IFM_ACTIVE | IFM_AVALID)) { 5576c8d8eccSSepherosa Ziehau switch (IFM_SUBTYPE(mii->mii_media_active)) { 5586c8d8eccSSepherosa Ziehau case IFM_10_T: 5596c8d8eccSSepherosa Ziehau case IFM_100_TX: 5606c8d8eccSSepherosa Ziehau sc->bnx_link = 1; 5616c8d8eccSSepherosa Ziehau break; 5626c8d8eccSSepherosa Ziehau case IFM_1000_T: 5636c8d8eccSSepherosa Ziehau case IFM_1000_SX: 5646c8d8eccSSepherosa Ziehau case IFM_2500_SX: 5656c8d8eccSSepherosa Ziehau sc->bnx_link = 1; 5666c8d8eccSSepherosa Ziehau break; 5676c8d8eccSSepherosa Ziehau default: 5686c8d8eccSSepherosa Ziehau sc->bnx_link = 0; 5696c8d8eccSSepherosa Ziehau break; 5706c8d8eccSSepherosa Ziehau } 5716c8d8eccSSepherosa Ziehau } else { 5726c8d8eccSSepherosa Ziehau sc->bnx_link = 0; 5736c8d8eccSSepherosa Ziehau } 5746c8d8eccSSepherosa Ziehau if (sc->bnx_link == 0) 5756c8d8eccSSepherosa Ziehau return; 5766c8d8eccSSepherosa Ziehau 5776c8d8eccSSepherosa Ziehau BNX_CLRBIT(sc, BGE_MAC_MODE, BGE_MACMODE_PORTMODE); 5786c8d8eccSSepherosa Ziehau if (IFM_SUBTYPE(mii->mii_media_active) == IFM_1000_T || 5796c8d8eccSSepherosa Ziehau IFM_SUBTYPE(mii->mii_media_active) == IFM_1000_SX) { 5806c8d8eccSSepherosa Ziehau BNX_SETBIT(sc, BGE_MAC_MODE, BGE_PORTMODE_GMII); 5816c8d8eccSSepherosa Ziehau } else { 5826c8d8eccSSepherosa Ziehau BNX_SETBIT(sc, BGE_MAC_MODE, BGE_PORTMODE_MII); 5836c8d8eccSSepherosa Ziehau } 5846c8d8eccSSepherosa Ziehau 5856c8d8eccSSepherosa Ziehau if ((mii->mii_media_active & IFM_GMASK) == IFM_FDX) { 5866c8d8eccSSepherosa Ziehau BNX_CLRBIT(sc, BGE_MAC_MODE, BGE_MACMODE_HALF_DUPLEX); 5876c8d8eccSSepherosa Ziehau } else { 5886c8d8eccSSepherosa Ziehau BNX_SETBIT(sc, BGE_MAC_MODE, BGE_MACMODE_HALF_DUPLEX); 5896c8d8eccSSepherosa Ziehau } 5906c8d8eccSSepherosa Ziehau } 5916c8d8eccSSepherosa Ziehau 5926c8d8eccSSepherosa Ziehau /* 5936c8d8eccSSepherosa Ziehau * Memory management for jumbo frames. 5946c8d8eccSSepherosa Ziehau */ 5956c8d8eccSSepherosa Ziehau static int 5966c8d8eccSSepherosa Ziehau bnx_alloc_jumbo_mem(struct bnx_softc *sc) 5976c8d8eccSSepherosa Ziehau { 5986c8d8eccSSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if; 5996c8d8eccSSepherosa Ziehau struct bnx_jslot *entry; 6006c8d8eccSSepherosa Ziehau uint8_t *ptr; 6016c8d8eccSSepherosa Ziehau bus_addr_t paddr; 6026c8d8eccSSepherosa Ziehau int i, error; 6036c8d8eccSSepherosa Ziehau 6046c8d8eccSSepherosa Ziehau /* 6056c8d8eccSSepherosa Ziehau * Create tag for jumbo mbufs. 6066c8d8eccSSepherosa Ziehau * This is really a bit of a kludge. We allocate a special 6076c8d8eccSSepherosa Ziehau * jumbo buffer pool which (thanks to the way our DMA 6086c8d8eccSSepherosa Ziehau * memory allocation works) will consist of contiguous 6096c8d8eccSSepherosa Ziehau * pages. This means that even though a jumbo buffer might 6106c8d8eccSSepherosa Ziehau * be larger than a page size, we don't really need to 6116c8d8eccSSepherosa Ziehau * map it into more than one DMA segment. However, the 6126c8d8eccSSepherosa Ziehau * default mbuf tag will result in multi-segment mappings, 6136c8d8eccSSepherosa Ziehau * so we have to create a special jumbo mbuf tag that 6146c8d8eccSSepherosa Ziehau * lets us get away with mapping the jumbo buffers as 6156c8d8eccSSepherosa Ziehau * a single segment. I think eventually the driver should 6166c8d8eccSSepherosa Ziehau * be changed so that it uses ordinary mbufs and cluster 6176c8d8eccSSepherosa Ziehau * buffers, i.e. jumbo frames can span multiple DMA 6186c8d8eccSSepherosa Ziehau * descriptors. But that's a project for another day. 6196c8d8eccSSepherosa Ziehau */ 6206c8d8eccSSepherosa Ziehau 6216c8d8eccSSepherosa Ziehau /* 6226c8d8eccSSepherosa Ziehau * Create DMA stuffs for jumbo RX ring. 6236c8d8eccSSepherosa Ziehau */ 6246c8d8eccSSepherosa Ziehau error = bnx_dma_block_alloc(sc, BGE_JUMBO_RX_RING_SZ, 6256c8d8eccSSepherosa Ziehau &sc->bnx_cdata.bnx_rx_jumbo_ring_tag, 6266c8d8eccSSepherosa Ziehau &sc->bnx_cdata.bnx_rx_jumbo_ring_map, 6276c8d8eccSSepherosa Ziehau (void *)&sc->bnx_ldata.bnx_rx_jumbo_ring, 6286c8d8eccSSepherosa Ziehau &sc->bnx_ldata.bnx_rx_jumbo_ring_paddr); 6296c8d8eccSSepherosa Ziehau if (error) { 6306c8d8eccSSepherosa Ziehau if_printf(ifp, "could not create jumbo RX ring\n"); 6316c8d8eccSSepherosa Ziehau return error; 6326c8d8eccSSepherosa Ziehau } 6336c8d8eccSSepherosa Ziehau 6346c8d8eccSSepherosa Ziehau /* 6356c8d8eccSSepherosa Ziehau * Create DMA stuffs for jumbo buffer block. 6366c8d8eccSSepherosa Ziehau */ 6376c8d8eccSSepherosa Ziehau error = bnx_dma_block_alloc(sc, BNX_JMEM, 6386c8d8eccSSepherosa Ziehau &sc->bnx_cdata.bnx_jumbo_tag, 6396c8d8eccSSepherosa Ziehau &sc->bnx_cdata.bnx_jumbo_map, 6406c8d8eccSSepherosa Ziehau (void **)&sc->bnx_ldata.bnx_jumbo_buf, 6416c8d8eccSSepherosa Ziehau &paddr); 6426c8d8eccSSepherosa Ziehau if (error) { 6436c8d8eccSSepherosa Ziehau if_printf(ifp, "could not create jumbo buffer\n"); 6446c8d8eccSSepherosa Ziehau return error; 6456c8d8eccSSepherosa Ziehau } 6466c8d8eccSSepherosa Ziehau 6476c8d8eccSSepherosa Ziehau SLIST_INIT(&sc->bnx_jfree_listhead); 6486c8d8eccSSepherosa Ziehau 6496c8d8eccSSepherosa Ziehau /* 6506c8d8eccSSepherosa Ziehau * Now divide it up into 9K pieces and save the addresses 6516c8d8eccSSepherosa Ziehau * in an array. Note that we play an evil trick here by using 6526c8d8eccSSepherosa Ziehau * the first few bytes in the buffer to hold the the address 6536c8d8eccSSepherosa Ziehau * of the softc structure for this interface. This is because 6546c8d8eccSSepherosa Ziehau * bnx_jfree() needs it, but it is called by the mbuf management 6556c8d8eccSSepherosa Ziehau * code which will not pass it to us explicitly. 6566c8d8eccSSepherosa Ziehau */ 6576c8d8eccSSepherosa Ziehau for (i = 0, ptr = sc->bnx_ldata.bnx_jumbo_buf; i < BNX_JSLOTS; i++) { 6586c8d8eccSSepherosa Ziehau entry = &sc->bnx_cdata.bnx_jslots[i]; 6596c8d8eccSSepherosa Ziehau entry->bnx_sc = sc; 6606c8d8eccSSepherosa Ziehau entry->bnx_buf = ptr; 6616c8d8eccSSepherosa Ziehau entry->bnx_paddr = paddr; 6626c8d8eccSSepherosa Ziehau entry->bnx_inuse = 0; 6636c8d8eccSSepherosa Ziehau entry->bnx_slot = i; 6646c8d8eccSSepherosa Ziehau SLIST_INSERT_HEAD(&sc->bnx_jfree_listhead, entry, jslot_link); 6656c8d8eccSSepherosa Ziehau 6666c8d8eccSSepherosa Ziehau ptr += BNX_JLEN; 6676c8d8eccSSepherosa Ziehau paddr += BNX_JLEN; 6686c8d8eccSSepherosa Ziehau } 6696c8d8eccSSepherosa Ziehau return 0; 6706c8d8eccSSepherosa Ziehau } 6716c8d8eccSSepherosa Ziehau 6726c8d8eccSSepherosa Ziehau static void 6736c8d8eccSSepherosa Ziehau bnx_free_jumbo_mem(struct bnx_softc *sc) 6746c8d8eccSSepherosa Ziehau { 6756c8d8eccSSepherosa Ziehau /* Destroy jumbo RX ring. */ 6766c8d8eccSSepherosa Ziehau bnx_dma_block_free(sc->bnx_cdata.bnx_rx_jumbo_ring_tag, 6776c8d8eccSSepherosa Ziehau sc->bnx_cdata.bnx_rx_jumbo_ring_map, 6786c8d8eccSSepherosa Ziehau sc->bnx_ldata.bnx_rx_jumbo_ring); 6796c8d8eccSSepherosa Ziehau 6806c8d8eccSSepherosa Ziehau /* Destroy jumbo buffer block. */ 6816c8d8eccSSepherosa Ziehau bnx_dma_block_free(sc->bnx_cdata.bnx_jumbo_tag, 6826c8d8eccSSepherosa Ziehau sc->bnx_cdata.bnx_jumbo_map, 6836c8d8eccSSepherosa Ziehau sc->bnx_ldata.bnx_jumbo_buf); 6846c8d8eccSSepherosa Ziehau } 6856c8d8eccSSepherosa Ziehau 6866c8d8eccSSepherosa Ziehau /* 6876c8d8eccSSepherosa Ziehau * Allocate a jumbo buffer. 6886c8d8eccSSepherosa Ziehau */ 6896c8d8eccSSepherosa Ziehau static struct bnx_jslot * 6906c8d8eccSSepherosa Ziehau bnx_jalloc(struct bnx_softc *sc) 6916c8d8eccSSepherosa Ziehau { 6926c8d8eccSSepherosa Ziehau struct bnx_jslot *entry; 6936c8d8eccSSepherosa Ziehau 6946c8d8eccSSepherosa Ziehau lwkt_serialize_enter(&sc->bnx_jslot_serializer); 6956c8d8eccSSepherosa Ziehau entry = SLIST_FIRST(&sc->bnx_jfree_listhead); 6966c8d8eccSSepherosa Ziehau if (entry) { 6976c8d8eccSSepherosa Ziehau SLIST_REMOVE_HEAD(&sc->bnx_jfree_listhead, jslot_link); 6986c8d8eccSSepherosa Ziehau entry->bnx_inuse = 1; 6996c8d8eccSSepherosa Ziehau } else { 7006c8d8eccSSepherosa Ziehau if_printf(&sc->arpcom.ac_if, "no free jumbo buffers\n"); 7016c8d8eccSSepherosa Ziehau } 7026c8d8eccSSepherosa Ziehau lwkt_serialize_exit(&sc->bnx_jslot_serializer); 7036c8d8eccSSepherosa Ziehau return(entry); 7046c8d8eccSSepherosa Ziehau } 7056c8d8eccSSepherosa Ziehau 7066c8d8eccSSepherosa Ziehau /* 7076c8d8eccSSepherosa Ziehau * Adjust usage count on a jumbo buffer. 7086c8d8eccSSepherosa Ziehau */ 7096c8d8eccSSepherosa Ziehau static void 7106c8d8eccSSepherosa Ziehau bnx_jref(void *arg) 7116c8d8eccSSepherosa Ziehau { 7126c8d8eccSSepherosa Ziehau struct bnx_jslot *entry = (struct bnx_jslot *)arg; 7136c8d8eccSSepherosa Ziehau struct bnx_softc *sc = entry->bnx_sc; 7146c8d8eccSSepherosa Ziehau 7156c8d8eccSSepherosa Ziehau if (sc == NULL) 7166c8d8eccSSepherosa Ziehau panic("bnx_jref: can't find softc pointer!"); 7176c8d8eccSSepherosa Ziehau 7186c8d8eccSSepherosa Ziehau if (&sc->bnx_cdata.bnx_jslots[entry->bnx_slot] != entry) { 7196c8d8eccSSepherosa Ziehau panic("bnx_jref: asked to reference buffer " 7206c8d8eccSSepherosa Ziehau "that we don't manage!"); 7216c8d8eccSSepherosa Ziehau } else if (entry->bnx_inuse == 0) { 7226c8d8eccSSepherosa Ziehau panic("bnx_jref: buffer already free!"); 7236c8d8eccSSepherosa Ziehau } else { 7246c8d8eccSSepherosa Ziehau atomic_add_int(&entry->bnx_inuse, 1); 7256c8d8eccSSepherosa Ziehau } 7266c8d8eccSSepherosa Ziehau } 7276c8d8eccSSepherosa Ziehau 7286c8d8eccSSepherosa Ziehau /* 7296c8d8eccSSepherosa Ziehau * Release a jumbo buffer. 7306c8d8eccSSepherosa Ziehau */ 7316c8d8eccSSepherosa Ziehau static void 7326c8d8eccSSepherosa Ziehau bnx_jfree(void *arg) 7336c8d8eccSSepherosa Ziehau { 7346c8d8eccSSepherosa Ziehau struct bnx_jslot *entry = (struct bnx_jslot *)arg; 7356c8d8eccSSepherosa Ziehau struct bnx_softc *sc = entry->bnx_sc; 7366c8d8eccSSepherosa Ziehau 7376c8d8eccSSepherosa Ziehau if (sc == NULL) 7386c8d8eccSSepherosa Ziehau panic("bnx_jfree: can't find softc pointer!"); 7396c8d8eccSSepherosa Ziehau 7406c8d8eccSSepherosa Ziehau if (&sc->bnx_cdata.bnx_jslots[entry->bnx_slot] != entry) { 7416c8d8eccSSepherosa Ziehau panic("bnx_jfree: asked to free buffer that we don't manage!"); 7426c8d8eccSSepherosa Ziehau } else if (entry->bnx_inuse == 0) { 7436c8d8eccSSepherosa Ziehau panic("bnx_jfree: buffer already free!"); 7446c8d8eccSSepherosa Ziehau } else { 7456c8d8eccSSepherosa Ziehau /* 7466c8d8eccSSepherosa Ziehau * Possible MP race to 0, use the serializer. The atomic insn 7476c8d8eccSSepherosa Ziehau * is still needed for races against bnx_jref(). 7486c8d8eccSSepherosa Ziehau */ 7496c8d8eccSSepherosa Ziehau lwkt_serialize_enter(&sc->bnx_jslot_serializer); 7506c8d8eccSSepherosa Ziehau atomic_subtract_int(&entry->bnx_inuse, 1); 7516c8d8eccSSepherosa Ziehau if (entry->bnx_inuse == 0) { 7526c8d8eccSSepherosa Ziehau SLIST_INSERT_HEAD(&sc->bnx_jfree_listhead, 7536c8d8eccSSepherosa Ziehau entry, jslot_link); 7546c8d8eccSSepherosa Ziehau } 7556c8d8eccSSepherosa Ziehau lwkt_serialize_exit(&sc->bnx_jslot_serializer); 7566c8d8eccSSepherosa Ziehau } 7576c8d8eccSSepherosa Ziehau } 7586c8d8eccSSepherosa Ziehau 7596c8d8eccSSepherosa Ziehau 7606c8d8eccSSepherosa Ziehau /* 7616c8d8eccSSepherosa Ziehau * Intialize a standard receive ring descriptor. 7626c8d8eccSSepherosa Ziehau */ 7636c8d8eccSSepherosa Ziehau static int 764beedf5beSSepherosa Ziehau bnx_newbuf_std(struct bnx_rx_ret_ring *ret, int i, int init) 7656c8d8eccSSepherosa Ziehau { 7666c8d8eccSSepherosa Ziehau struct mbuf *m_new = NULL; 7676c8d8eccSSepherosa Ziehau bus_dma_segment_t seg; 7686c8d8eccSSepherosa Ziehau bus_dmamap_t map; 7696c8d8eccSSepherosa Ziehau int error, nsegs; 770beedf5beSSepherosa Ziehau struct bnx_rx_buf *rb; 7716c8d8eccSSepherosa Ziehau 772841cdf08SSepherosa Ziehau rb = &ret->bnx_std->bnx_rx_std_buf[i]; 773841cdf08SSepherosa Ziehau KASSERT(!rb->bnx_rx_refilled, ("RX buf %dth has been refilled", i)); 774841cdf08SSepherosa Ziehau 7756c8d8eccSSepherosa Ziehau m_new = m_getcl(init ? MB_WAIT : MB_DONTWAIT, MT_DATA, M_PKTHDR); 776841cdf08SSepherosa Ziehau if (m_new == NULL) { 777841cdf08SSepherosa Ziehau error = ENOBUFS; 778841cdf08SSepherosa Ziehau goto back; 779841cdf08SSepherosa Ziehau } 7806c8d8eccSSepherosa Ziehau m_new->m_len = m_new->m_pkthdr.len = MCLBYTES; 7816c8d8eccSSepherosa Ziehau m_adj(m_new, ETHER_ALIGN); 7826c8d8eccSSepherosa Ziehau 783beedf5beSSepherosa Ziehau error = bus_dmamap_load_mbuf_segment(ret->bnx_rx_mtag, 784beedf5beSSepherosa Ziehau ret->bnx_rx_tmpmap, m_new, &seg, 1, &nsegs, BUS_DMA_NOWAIT); 7856c8d8eccSSepherosa Ziehau if (error) { 7866c8d8eccSSepherosa Ziehau m_freem(m_new); 787841cdf08SSepherosa Ziehau goto back; 7886c8d8eccSSepherosa Ziehau } 7896c8d8eccSSepherosa Ziehau 7906c8d8eccSSepherosa Ziehau if (!init) { 791beedf5beSSepherosa Ziehau bus_dmamap_sync(ret->bnx_rx_mtag, rb->bnx_rx_dmamap, 7926c8d8eccSSepherosa Ziehau BUS_DMASYNC_POSTREAD); 793beedf5beSSepherosa Ziehau bus_dmamap_unload(ret->bnx_rx_mtag, rb->bnx_rx_dmamap); 7946c8d8eccSSepherosa Ziehau } 7956c8d8eccSSepherosa Ziehau 796beedf5beSSepherosa Ziehau map = ret->bnx_rx_tmpmap; 797beedf5beSSepherosa Ziehau ret->bnx_rx_tmpmap = rb->bnx_rx_dmamap; 7986c8d8eccSSepherosa Ziehau 799841cdf08SSepherosa Ziehau rb->bnx_rx_dmamap = map; 800beedf5beSSepherosa Ziehau rb->bnx_rx_mbuf = m_new; 801beedf5beSSepherosa Ziehau rb->bnx_rx_paddr = seg.ds_addr; 802*695a8586SSepherosa Ziehau rb->bnx_rx_len = m_new->m_len; 803841cdf08SSepherosa Ziehau back: 804841cdf08SSepherosa Ziehau cpu_sfence(); 805841cdf08SSepherosa Ziehau rb->bnx_rx_refilled = 1; 806841cdf08SSepherosa Ziehau return error; 8076c8d8eccSSepherosa Ziehau } 8086c8d8eccSSepherosa Ziehau 8096c8d8eccSSepherosa Ziehau static void 810beedf5beSSepherosa Ziehau bnx_setup_rxdesc_std(struct bnx_rx_std_ring *std, int i) 8116c8d8eccSSepherosa Ziehau { 812841cdf08SSepherosa Ziehau struct bnx_rx_buf *rb; 8136c8d8eccSSepherosa Ziehau struct bge_rx_bd *r; 814*695a8586SSepherosa Ziehau bus_addr_t paddr; 815*695a8586SSepherosa Ziehau int len; 8166c8d8eccSSepherosa Ziehau 817beedf5beSSepherosa Ziehau rb = &std->bnx_rx_std_buf[i]; 818841cdf08SSepherosa Ziehau KASSERT(rb->bnx_rx_refilled, ("RX buf %dth is not refilled", i)); 819*695a8586SSepherosa Ziehau 820*695a8586SSepherosa Ziehau paddr = rb->bnx_rx_paddr; 821*695a8586SSepherosa Ziehau len = rb->bnx_rx_len; 822*695a8586SSepherosa Ziehau 823*695a8586SSepherosa Ziehau cpu_mfence(); 824*695a8586SSepherosa Ziehau 825841cdf08SSepherosa Ziehau rb->bnx_rx_refilled = 0; 8266c8d8eccSSepherosa Ziehau 827841cdf08SSepherosa Ziehau r = &std->bnx_rx_std_ring[i]; 828*695a8586SSepherosa Ziehau r->bge_addr.bge_addr_lo = BGE_ADDR_LO(paddr); 829*695a8586SSepherosa Ziehau r->bge_addr.bge_addr_hi = BGE_ADDR_HI(paddr); 830*695a8586SSepherosa Ziehau r->bge_len = len; 8316c8d8eccSSepherosa Ziehau r->bge_idx = i; 8326c8d8eccSSepherosa Ziehau r->bge_flags = BGE_RXBDFLAG_END; 8336c8d8eccSSepherosa Ziehau } 8346c8d8eccSSepherosa Ziehau 8356c8d8eccSSepherosa Ziehau /* 8366c8d8eccSSepherosa Ziehau * Initialize a jumbo receive ring descriptor. This allocates 8376c8d8eccSSepherosa Ziehau * a jumbo buffer from the pool managed internally by the driver. 8386c8d8eccSSepherosa Ziehau */ 8396c8d8eccSSepherosa Ziehau static int 8406c8d8eccSSepherosa Ziehau bnx_newbuf_jumbo(struct bnx_softc *sc, int i, int init) 8416c8d8eccSSepherosa Ziehau { 8426c8d8eccSSepherosa Ziehau struct mbuf *m_new = NULL; 8436c8d8eccSSepherosa Ziehau struct bnx_jslot *buf; 8446c8d8eccSSepherosa Ziehau bus_addr_t paddr; 8456c8d8eccSSepherosa Ziehau 8466c8d8eccSSepherosa Ziehau /* Allocate the mbuf. */ 8476c8d8eccSSepherosa Ziehau MGETHDR(m_new, init ? MB_WAIT : MB_DONTWAIT, MT_DATA); 8486c8d8eccSSepherosa Ziehau if (m_new == NULL) 8496c8d8eccSSepherosa Ziehau return ENOBUFS; 8506c8d8eccSSepherosa Ziehau 8516c8d8eccSSepherosa Ziehau /* Allocate the jumbo buffer */ 8526c8d8eccSSepherosa Ziehau buf = bnx_jalloc(sc); 8536c8d8eccSSepherosa Ziehau if (buf == NULL) { 8546c8d8eccSSepherosa Ziehau m_freem(m_new); 8556c8d8eccSSepherosa Ziehau return ENOBUFS; 8566c8d8eccSSepherosa Ziehau } 8576c8d8eccSSepherosa Ziehau 8586c8d8eccSSepherosa Ziehau /* Attach the buffer to the mbuf. */ 8596c8d8eccSSepherosa Ziehau m_new->m_ext.ext_arg = buf; 8606c8d8eccSSepherosa Ziehau m_new->m_ext.ext_buf = buf->bnx_buf; 8616c8d8eccSSepherosa Ziehau m_new->m_ext.ext_free = bnx_jfree; 8626c8d8eccSSepherosa Ziehau m_new->m_ext.ext_ref = bnx_jref; 8636c8d8eccSSepherosa Ziehau m_new->m_ext.ext_size = BNX_JUMBO_FRAMELEN; 8646c8d8eccSSepherosa Ziehau 8656c8d8eccSSepherosa Ziehau m_new->m_flags |= M_EXT; 8666c8d8eccSSepherosa Ziehau 8676c8d8eccSSepherosa Ziehau m_new->m_data = m_new->m_ext.ext_buf; 8686c8d8eccSSepherosa Ziehau m_new->m_len = m_new->m_pkthdr.len = m_new->m_ext.ext_size; 8696c8d8eccSSepherosa Ziehau 8706c8d8eccSSepherosa Ziehau paddr = buf->bnx_paddr; 8716c8d8eccSSepherosa Ziehau m_adj(m_new, ETHER_ALIGN); 8726c8d8eccSSepherosa Ziehau paddr += ETHER_ALIGN; 8736c8d8eccSSepherosa Ziehau 8746c8d8eccSSepherosa Ziehau /* Save necessary information */ 875beedf5beSSepherosa Ziehau sc->bnx_cdata.bnx_rx_jumbo_chain[i].bnx_rx_mbuf = m_new; 876beedf5beSSepherosa Ziehau sc->bnx_cdata.bnx_rx_jumbo_chain[i].bnx_rx_paddr = paddr; 8776c8d8eccSSepherosa Ziehau 8786c8d8eccSSepherosa Ziehau /* Set up the descriptor. */ 8796c8d8eccSSepherosa Ziehau bnx_setup_rxdesc_jumbo(sc, i); 8806c8d8eccSSepherosa Ziehau return 0; 8816c8d8eccSSepherosa Ziehau } 8826c8d8eccSSepherosa Ziehau 8836c8d8eccSSepherosa Ziehau static void 8846c8d8eccSSepherosa Ziehau bnx_setup_rxdesc_jumbo(struct bnx_softc *sc, int i) 8856c8d8eccSSepherosa Ziehau { 8866c8d8eccSSepherosa Ziehau struct bge_rx_bd *r; 887beedf5beSSepherosa Ziehau struct bnx_rx_buf *rc; 8886c8d8eccSSepherosa Ziehau 8896c8d8eccSSepherosa Ziehau r = &sc->bnx_ldata.bnx_rx_jumbo_ring[i]; 8906c8d8eccSSepherosa Ziehau rc = &sc->bnx_cdata.bnx_rx_jumbo_chain[i]; 8916c8d8eccSSepherosa Ziehau 892beedf5beSSepherosa Ziehau r->bge_addr.bge_addr_lo = BGE_ADDR_LO(rc->bnx_rx_paddr); 893beedf5beSSepherosa Ziehau r->bge_addr.bge_addr_hi = BGE_ADDR_HI(rc->bnx_rx_paddr); 894beedf5beSSepherosa Ziehau r->bge_len = rc->bnx_rx_mbuf->m_len; 8956c8d8eccSSepherosa Ziehau r->bge_idx = i; 8966c8d8eccSSepherosa Ziehau r->bge_flags = BGE_RXBDFLAG_END|BGE_RXBDFLAG_JUMBO_RING; 8976c8d8eccSSepherosa Ziehau } 8986c8d8eccSSepherosa Ziehau 8996c8d8eccSSepherosa Ziehau static int 900beedf5beSSepherosa Ziehau bnx_init_rx_ring_std(struct bnx_rx_std_ring *std) 9016c8d8eccSSepherosa Ziehau { 9026c8d8eccSSepherosa Ziehau int i, error; 9036c8d8eccSSepherosa Ziehau 9046c8d8eccSSepherosa Ziehau for (i = 0; i < BGE_STD_RX_RING_CNT; i++) { 905beedf5beSSepherosa Ziehau /* Use the first RX return ring's tmp RX mbuf DMA map */ 906beedf5beSSepherosa Ziehau error = bnx_newbuf_std(&std->bnx_sc->bnx_rx_ret_ring[0], i, 1); 9076c8d8eccSSepherosa Ziehau if (error) 9086c8d8eccSSepherosa Ziehau return error; 909841cdf08SSepherosa Ziehau bnx_setup_rxdesc_std(std, i); 91087c7a7cfSSascha Wildner } 9116c8d8eccSSepherosa Ziehau 912841cdf08SSepherosa Ziehau std->bnx_rx_std_refill = 0; 913841cdf08SSepherosa Ziehau std->bnx_rx_std_running = 0; 914841cdf08SSepherosa Ziehau cpu_sfence(); 915841cdf08SSepherosa Ziehau lwkt_serialize_handler_enable(&std->bnx_rx_std_serialize); 916841cdf08SSepherosa Ziehau 917beedf5beSSepherosa Ziehau std->bnx_rx_std = BGE_STD_RX_RING_CNT - 1; 918beedf5beSSepherosa Ziehau bnx_writembx(std->bnx_sc, BGE_MBX_RX_STD_PROD_LO, std->bnx_rx_std); 9196c8d8eccSSepherosa Ziehau 9206c8d8eccSSepherosa Ziehau return(0); 9216c8d8eccSSepherosa Ziehau } 9226c8d8eccSSepherosa Ziehau 9236c8d8eccSSepherosa Ziehau static void 924beedf5beSSepherosa Ziehau bnx_free_rx_ring_std(struct bnx_rx_std_ring *std) 9256c8d8eccSSepherosa Ziehau { 9266c8d8eccSSepherosa Ziehau int i; 9276c8d8eccSSepherosa Ziehau 928841cdf08SSepherosa Ziehau lwkt_serialize_handler_disable(&std->bnx_rx_std_serialize); 929841cdf08SSepherosa Ziehau 9306c8d8eccSSepherosa Ziehau for (i = 0; i < BGE_STD_RX_RING_CNT; i++) { 931beedf5beSSepherosa Ziehau struct bnx_rx_buf *rb = &std->bnx_rx_std_buf[i]; 9326c8d8eccSSepherosa Ziehau 933841cdf08SSepherosa Ziehau rb->bnx_rx_refilled = 0; 934beedf5beSSepherosa Ziehau if (rb->bnx_rx_mbuf != NULL) { 935beedf5beSSepherosa Ziehau bus_dmamap_unload(std->bnx_rx_mtag, rb->bnx_rx_dmamap); 936beedf5beSSepherosa Ziehau m_freem(rb->bnx_rx_mbuf); 937beedf5beSSepherosa Ziehau rb->bnx_rx_mbuf = NULL; 9386c8d8eccSSepherosa Ziehau } 939beedf5beSSepherosa Ziehau bzero(&std->bnx_rx_std_ring[i], sizeof(struct bge_rx_bd)); 9406c8d8eccSSepherosa Ziehau } 9416c8d8eccSSepherosa Ziehau } 9426c8d8eccSSepherosa Ziehau 9436c8d8eccSSepherosa Ziehau static int 9446c8d8eccSSepherosa Ziehau bnx_init_rx_ring_jumbo(struct bnx_softc *sc) 9456c8d8eccSSepherosa Ziehau { 9466c8d8eccSSepherosa Ziehau struct bge_rcb *rcb; 9476c8d8eccSSepherosa Ziehau int i, error; 9486c8d8eccSSepherosa Ziehau 9496c8d8eccSSepherosa Ziehau for (i = 0; i < BGE_JUMBO_RX_RING_CNT; i++) { 9506c8d8eccSSepherosa Ziehau error = bnx_newbuf_jumbo(sc, i, 1); 9516c8d8eccSSepherosa Ziehau if (error) 9526c8d8eccSSepherosa Ziehau return error; 95387c7a7cfSSascha Wildner } 9546c8d8eccSSepherosa Ziehau 9556c8d8eccSSepherosa Ziehau sc->bnx_jumbo = BGE_JUMBO_RX_RING_CNT - 1; 9566c8d8eccSSepherosa Ziehau 9576c8d8eccSSepherosa Ziehau rcb = &sc->bnx_ldata.bnx_info.bnx_jumbo_rx_rcb; 9586c8d8eccSSepherosa Ziehau rcb->bge_maxlen_flags = BGE_RCB_MAXLEN_FLAGS(0, 0); 9596c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_RX_JUMBO_RCB_MAXLEN_FLAGS, rcb->bge_maxlen_flags); 9606c8d8eccSSepherosa Ziehau 9616c8d8eccSSepherosa Ziehau bnx_writembx(sc, BGE_MBX_RX_JUMBO_PROD_LO, sc->bnx_jumbo); 9626c8d8eccSSepherosa Ziehau 9636c8d8eccSSepherosa Ziehau return(0); 9646c8d8eccSSepherosa Ziehau } 9656c8d8eccSSepherosa Ziehau 9666c8d8eccSSepherosa Ziehau static void 9676c8d8eccSSepherosa Ziehau bnx_free_rx_ring_jumbo(struct bnx_softc *sc) 9686c8d8eccSSepherosa Ziehau { 9696c8d8eccSSepherosa Ziehau int i; 9706c8d8eccSSepherosa Ziehau 9716c8d8eccSSepherosa Ziehau for (i = 0; i < BGE_JUMBO_RX_RING_CNT; i++) { 972beedf5beSSepherosa Ziehau struct bnx_rx_buf *rc = &sc->bnx_cdata.bnx_rx_jumbo_chain[i]; 9736c8d8eccSSepherosa Ziehau 974beedf5beSSepherosa Ziehau if (rc->bnx_rx_mbuf != NULL) { 975beedf5beSSepherosa Ziehau m_freem(rc->bnx_rx_mbuf); 976beedf5beSSepherosa Ziehau rc->bnx_rx_mbuf = NULL; 9776c8d8eccSSepherosa Ziehau } 9786c8d8eccSSepherosa Ziehau bzero(&sc->bnx_ldata.bnx_rx_jumbo_ring[i], 9796c8d8eccSSepherosa Ziehau sizeof(struct bge_rx_bd)); 9806c8d8eccSSepherosa Ziehau } 9816c8d8eccSSepherosa Ziehau } 9826c8d8eccSSepherosa Ziehau 9836c8d8eccSSepherosa Ziehau static void 98433a04907SSepherosa Ziehau bnx_free_tx_ring(struct bnx_tx_ring *txr) 9856c8d8eccSSepherosa Ziehau { 9866c8d8eccSSepherosa Ziehau int i; 9876c8d8eccSSepherosa Ziehau 9886c8d8eccSSepherosa Ziehau for (i = 0; i < BGE_TX_RING_CNT; i++) { 989fa4b1067SSepherosa Ziehau struct bnx_tx_buf *buf = &txr->bnx_tx_buf[i]; 990fa4b1067SSepherosa Ziehau 991fa4b1067SSepherosa Ziehau if (buf->bnx_tx_mbuf != NULL) { 99233a04907SSepherosa Ziehau bus_dmamap_unload(txr->bnx_tx_mtag, 993fa4b1067SSepherosa Ziehau buf->bnx_tx_dmamap); 994fa4b1067SSepherosa Ziehau m_freem(buf->bnx_tx_mbuf); 995fa4b1067SSepherosa Ziehau buf->bnx_tx_mbuf = NULL; 9966c8d8eccSSepherosa Ziehau } 99733a04907SSepherosa Ziehau bzero(&txr->bnx_tx_ring[i], sizeof(struct bge_tx_bd)); 9986c8d8eccSSepherosa Ziehau } 99933a04907SSepherosa Ziehau txr->bnx_tx_saved_considx = BNX_TXCONS_UNSET; 10006c8d8eccSSepherosa Ziehau } 10016c8d8eccSSepherosa Ziehau 10026c8d8eccSSepherosa Ziehau static int 100333a04907SSepherosa Ziehau bnx_init_tx_ring(struct bnx_tx_ring *txr) 10046c8d8eccSSepherosa Ziehau { 1005fa639b88SSepherosa Ziehau txr->bnx_tx_cnt = 0; 100633a04907SSepherosa Ziehau txr->bnx_tx_saved_considx = 0; 100733a04907SSepherosa Ziehau txr->bnx_tx_prodidx = 0; 10086c8d8eccSSepherosa Ziehau 10096c8d8eccSSepherosa Ziehau /* Initialize transmit producer index for host-memory send ring. */ 10108bd43d5dSSepherosa Ziehau bnx_writembx(txr->bnx_sc, txr->bnx_tx_mbx, txr->bnx_tx_prodidx); 10116c8d8eccSSepherosa Ziehau 10126c8d8eccSSepherosa Ziehau return(0); 10136c8d8eccSSepherosa Ziehau } 10146c8d8eccSSepherosa Ziehau 10156c8d8eccSSepherosa Ziehau static void 10166c8d8eccSSepherosa Ziehau bnx_setmulti(struct bnx_softc *sc) 10176c8d8eccSSepherosa Ziehau { 10186c8d8eccSSepherosa Ziehau struct ifnet *ifp; 10196c8d8eccSSepherosa Ziehau struct ifmultiaddr *ifma; 10206c8d8eccSSepherosa Ziehau uint32_t hashes[4] = { 0, 0, 0, 0 }; 10216c8d8eccSSepherosa Ziehau int h, i; 10226c8d8eccSSepherosa Ziehau 10236c8d8eccSSepherosa Ziehau ifp = &sc->arpcom.ac_if; 10246c8d8eccSSepherosa Ziehau 10256c8d8eccSSepherosa Ziehau if (ifp->if_flags & IFF_ALLMULTI || ifp->if_flags & IFF_PROMISC) { 10266c8d8eccSSepherosa Ziehau for (i = 0; i < 4; i++) 10276c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_MAR0 + (i * 4), 0xFFFFFFFF); 10286c8d8eccSSepherosa Ziehau return; 10296c8d8eccSSepherosa Ziehau } 10306c8d8eccSSepherosa Ziehau 10316c8d8eccSSepherosa Ziehau /* First, zot all the existing filters. */ 10326c8d8eccSSepherosa Ziehau for (i = 0; i < 4; i++) 10336c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_MAR0 + (i * 4), 0); 10346c8d8eccSSepherosa Ziehau 10356c8d8eccSSepherosa Ziehau /* Now program new ones. */ 10366c8d8eccSSepherosa Ziehau TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { 10376c8d8eccSSepherosa Ziehau if (ifma->ifma_addr->sa_family != AF_LINK) 10386c8d8eccSSepherosa Ziehau continue; 10396c8d8eccSSepherosa Ziehau h = ether_crc32_le( 10406c8d8eccSSepherosa Ziehau LLADDR((struct sockaddr_dl *)ifma->ifma_addr), 10416c8d8eccSSepherosa Ziehau ETHER_ADDR_LEN) & 0x7f; 10426c8d8eccSSepherosa Ziehau hashes[(h & 0x60) >> 5] |= 1 << (h & 0x1F); 10436c8d8eccSSepherosa Ziehau } 10446c8d8eccSSepherosa Ziehau 10456c8d8eccSSepherosa Ziehau for (i = 0; i < 4; i++) 10466c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_MAR0 + (i * 4), hashes[i]); 10476c8d8eccSSepherosa Ziehau } 10486c8d8eccSSepherosa Ziehau 10496c8d8eccSSepherosa Ziehau /* 10506c8d8eccSSepherosa Ziehau * Do endian, PCI and DMA initialization. Also check the on-board ROM 10516c8d8eccSSepherosa Ziehau * self-test results. 10526c8d8eccSSepherosa Ziehau */ 10536c8d8eccSSepherosa Ziehau static int 10546c8d8eccSSepherosa Ziehau bnx_chipinit(struct bnx_softc *sc) 10556c8d8eccSSepherosa Ziehau { 10566c8d8eccSSepherosa Ziehau uint32_t dma_rw_ctl, mode_ctl; 10576c8d8eccSSepherosa Ziehau int i; 10586c8d8eccSSepherosa Ziehau 10596c8d8eccSSepherosa Ziehau /* Set endian type before we access any non-PCI registers. */ 10606c8d8eccSSepherosa Ziehau pci_write_config(sc->bnx_dev, BGE_PCI_MISC_CTL, 10616c8d8eccSSepherosa Ziehau BGE_INIT | BGE_PCIMISCCTL_TAGGED_STATUS, 4); 10626c8d8eccSSepherosa Ziehau 10636c8d8eccSSepherosa Ziehau /* Clear the MAC control register */ 10646c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_MAC_MODE, 0); 10656c8d8eccSSepherosa Ziehau 10666c8d8eccSSepherosa Ziehau /* 10676c8d8eccSSepherosa Ziehau * Clear the MAC statistics block in the NIC's 10686c8d8eccSSepherosa Ziehau * internal memory. 10696c8d8eccSSepherosa Ziehau */ 10706c8d8eccSSepherosa Ziehau for (i = BGE_STATS_BLOCK; 10716c8d8eccSSepherosa Ziehau i < BGE_STATS_BLOCK_END + 1; i += sizeof(uint32_t)) 10726c8d8eccSSepherosa Ziehau BNX_MEMWIN_WRITE(sc, i, 0); 10736c8d8eccSSepherosa Ziehau 10746c8d8eccSSepherosa Ziehau for (i = BGE_STATUS_BLOCK; 10756c8d8eccSSepherosa Ziehau i < BGE_STATUS_BLOCK_END + 1; i += sizeof(uint32_t)) 10766c8d8eccSSepherosa Ziehau BNX_MEMWIN_WRITE(sc, i, 0); 10776c8d8eccSSepherosa Ziehau 1078d7872545SSepherosa Ziehau if (BNX_IS_57765_FAMILY(sc)) { 1079d7872545SSepherosa Ziehau uint32_t val; 1080d7872545SSepherosa Ziehau 1081d7872545SSepherosa Ziehau if (sc->bnx_chipid == BGE_CHIPID_BCM57765_A0) { 1082d7872545SSepherosa Ziehau mode_ctl = CSR_READ_4(sc, BGE_MODE_CTL); 1083d7872545SSepherosa Ziehau val = mode_ctl & ~BGE_MODECTL_PCIE_PORTS; 1084d7872545SSepherosa Ziehau 1085d7872545SSepherosa Ziehau /* Access the lower 1K of PL PCI-E block registers. */ 1086d7872545SSepherosa Ziehau CSR_WRITE_4(sc, BGE_MODE_CTL, 1087d7872545SSepherosa Ziehau val | BGE_MODECTL_PCIE_PL_SEL); 1088d7872545SSepherosa Ziehau 1089d7872545SSepherosa Ziehau val = CSR_READ_4(sc, BGE_PCIE_PL_LO_PHYCTL5); 1090d7872545SSepherosa Ziehau val |= BGE_PCIE_PL_LO_PHYCTL5_DIS_L2CLKREQ; 1091d7872545SSepherosa Ziehau CSR_WRITE_4(sc, BGE_PCIE_PL_LO_PHYCTL5, val); 1092d7872545SSepherosa Ziehau 1093d7872545SSepherosa Ziehau CSR_WRITE_4(sc, BGE_MODE_CTL, mode_ctl); 1094d7872545SSepherosa Ziehau } 1095d7872545SSepherosa Ziehau if (sc->bnx_chiprev != BGE_CHIPREV_57765_AX) { 10961749651bSSepherosa Ziehau /* Fix transmit hangs */ 10971749651bSSepherosa Ziehau val = CSR_READ_4(sc, BGE_CPMU_PADRNG_CTL); 10981749651bSSepherosa Ziehau val |= BGE_CPMU_PADRNG_CTL_RDIV2; 10991749651bSSepherosa Ziehau CSR_WRITE_4(sc, BGE_CPMU_PADRNG_CTL, val); 11001749651bSSepherosa Ziehau 1101d7872545SSepherosa Ziehau mode_ctl = CSR_READ_4(sc, BGE_MODE_CTL); 1102d7872545SSepherosa Ziehau val = mode_ctl & ~BGE_MODECTL_PCIE_PORTS; 1103d7872545SSepherosa Ziehau 1104d7872545SSepherosa Ziehau /* Access the lower 1K of DL PCI-E block registers. */ 1105d7872545SSepherosa Ziehau CSR_WRITE_4(sc, BGE_MODE_CTL, 1106d7872545SSepherosa Ziehau val | BGE_MODECTL_PCIE_DL_SEL); 1107d7872545SSepherosa Ziehau 1108d7872545SSepherosa Ziehau val = CSR_READ_4(sc, BGE_PCIE_DL_LO_FTSMAX); 1109d7872545SSepherosa Ziehau val &= ~BGE_PCIE_DL_LO_FTSMAX_MASK; 1110d7872545SSepherosa Ziehau val |= BGE_PCIE_DL_LO_FTSMAX_VAL; 1111d7872545SSepherosa Ziehau CSR_WRITE_4(sc, BGE_PCIE_DL_LO_FTSMAX, val); 1112d7872545SSepherosa Ziehau 1113d7872545SSepherosa Ziehau CSR_WRITE_4(sc, BGE_MODE_CTL, mode_ctl); 1114d7872545SSepherosa Ziehau } 1115d7872545SSepherosa Ziehau 1116d7872545SSepherosa Ziehau val = CSR_READ_4(sc, BGE_CPMU_LSPD_10MB_CLK); 1117d7872545SSepherosa Ziehau val &= ~BGE_CPMU_LSPD_10MB_MACCLK_MASK; 1118d7872545SSepherosa Ziehau val |= BGE_CPMU_LSPD_10MB_MACCLK_6_25; 1119d7872545SSepherosa Ziehau CSR_WRITE_4(sc, BGE_CPMU_LSPD_10MB_CLK, val); 1120d7872545SSepherosa Ziehau } 1121d7872545SSepherosa Ziehau 11222890cca3SSepherosa Ziehau /* 11232890cca3SSepherosa Ziehau * Set up the PCI DMA control register. 11242890cca3SSepherosa Ziehau */ 11252890cca3SSepherosa Ziehau dma_rw_ctl = pci_read_config(sc->bnx_dev, BGE_PCI_DMA_RW_CTL, 4); 11262890cca3SSepherosa Ziehau /* 11272890cca3SSepherosa Ziehau * Disable 32bytes cache alignment for DMA write to host memory 11282890cca3SSepherosa Ziehau * 11292890cca3SSepherosa Ziehau * NOTE: 11302890cca3SSepherosa Ziehau * 64bytes cache alignment for DMA write to host memory is still 11312890cca3SSepherosa Ziehau * enabled. 11322890cca3SSepherosa Ziehau */ 11332890cca3SSepherosa Ziehau dma_rw_ctl |= BGE_PCIDMARWCTL_DIS_CACHE_ALIGNMENT; 11346c8d8eccSSepherosa Ziehau if (sc->bnx_chipid == BGE_CHIPID_BCM57765_A0) 11356c8d8eccSSepherosa Ziehau dma_rw_ctl &= ~BGE_PCIDMARWCTL_CRDRDR_RDMA_MRRS_MSK; 11366c8d8eccSSepherosa Ziehau /* 11376c8d8eccSSepherosa Ziehau * Enable HW workaround for controllers that misinterpret 11386c8d8eccSSepherosa Ziehau * a status tag update and leave interrupts permanently 11396c8d8eccSSepherosa Ziehau * disabled. 11406c8d8eccSSepherosa Ziehau */ 11416c8d8eccSSepherosa Ziehau if (sc->bnx_asicrev != BGE_ASICREV_BCM5717 && 1142b96cbbb6SSepherosa Ziehau sc->bnx_asicrev != BGE_ASICREV_BCM5762 && 11432890cca3SSepherosa Ziehau !BNX_IS_57765_FAMILY(sc)) 11446c8d8eccSSepherosa Ziehau dma_rw_ctl |= BGE_PCIDMARWCTL_TAGGED_STATUS_WA; 11452890cca3SSepherosa Ziehau if (bootverbose) { 11462890cca3SSepherosa Ziehau if_printf(&sc->arpcom.ac_if, "DMA read/write %#x\n", 11472890cca3SSepherosa Ziehau dma_rw_ctl); 11486c8d8eccSSepherosa Ziehau } 11496c8d8eccSSepherosa Ziehau pci_write_config(sc->bnx_dev, BGE_PCI_DMA_RW_CTL, dma_rw_ctl, 4); 11506c8d8eccSSepherosa Ziehau 11516c8d8eccSSepherosa Ziehau /* 11526c8d8eccSSepherosa Ziehau * Set up general mode register. 11536c8d8eccSSepherosa Ziehau */ 11546c8d8eccSSepherosa Ziehau mode_ctl = bnx_dma_swap_options(sc) | BGE_MODECTL_MAC_ATTN_INTR | 11556c8d8eccSSepherosa Ziehau BGE_MODECTL_HOST_SEND_BDS | BGE_MODECTL_TX_NO_PHDR_CSUM; 11566c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_MODE_CTL, mode_ctl); 11576c8d8eccSSepherosa Ziehau 11586c8d8eccSSepherosa Ziehau /* 11596c8d8eccSSepherosa Ziehau * Disable memory write invalidate. Apparently it is not supported 11606c8d8eccSSepherosa Ziehau * properly by these devices. Also ensure that INTx isn't disabled, 11616c8d8eccSSepherosa Ziehau * as these chips need it even when using MSI. 11626c8d8eccSSepherosa Ziehau */ 11636c8d8eccSSepherosa Ziehau PCI_CLRBIT(sc->bnx_dev, BGE_PCI_CMD, 11646c8d8eccSSepherosa Ziehau (PCIM_CMD_MWRICEN | PCIM_CMD_INTxDIS), 4); 11656c8d8eccSSepherosa Ziehau 11666c8d8eccSSepherosa Ziehau /* Set the timer prescaler (always 66Mhz) */ 11676c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_MISC_CFG, 65 << 1/*BGE_32BITTIME_66MHZ*/); 11686c8d8eccSSepherosa Ziehau 11696c8d8eccSSepherosa Ziehau return(0); 11706c8d8eccSSepherosa Ziehau } 11716c8d8eccSSepherosa Ziehau 11726c8d8eccSSepherosa Ziehau static int 11736c8d8eccSSepherosa Ziehau bnx_blockinit(struct bnx_softc *sc) 11746c8d8eccSSepherosa Ziehau { 1175*695a8586SSepherosa Ziehau struct bnx_intr_data *intr; 11766c8d8eccSSepherosa Ziehau struct bge_rcb *rcb; 11776c8d8eccSSepherosa Ziehau bus_size_t vrcb; 11786c8d8eccSSepherosa Ziehau bge_hostaddr taddr; 11796c8d8eccSSepherosa Ziehau uint32_t val; 11806c8d8eccSSepherosa Ziehau int i, limit; 11816c8d8eccSSepherosa Ziehau 11826c8d8eccSSepherosa Ziehau /* 11836c8d8eccSSepherosa Ziehau * Initialize the memory window pointer register so that 11846c8d8eccSSepherosa Ziehau * we can access the first 32K of internal NIC RAM. This will 11856c8d8eccSSepherosa Ziehau * allow us to set up the TX send ring RCBs and the RX return 11866c8d8eccSSepherosa Ziehau * ring RCBs, plus other things which live in NIC memory. 11876c8d8eccSSepherosa Ziehau */ 11886c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_PCI_MEMWIN_BASEADDR, 0); 11896c8d8eccSSepherosa Ziehau 11906c8d8eccSSepherosa Ziehau /* Configure mbuf pool watermarks */ 1191f368d0d9SSepherosa Ziehau if (BNX_IS_57765_PLUS(sc)) { 11926c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_BMAN_MBUFPOOL_READDMA_LOWAT, 0x0); 11936c8d8eccSSepherosa Ziehau if (sc->arpcom.ac_if.if_mtu > ETHERMTU) { 11946c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_BMAN_MBUFPOOL_MACRX_LOWAT, 0x7e); 11956c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_BMAN_MBUFPOOL_HIWAT, 0xea); 11966c8d8eccSSepherosa Ziehau } else { 11976c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_BMAN_MBUFPOOL_MACRX_LOWAT, 0x2a); 11986c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_BMAN_MBUFPOOL_HIWAT, 0xa0); 11996c8d8eccSSepherosa Ziehau } 12006c8d8eccSSepherosa Ziehau } else { 12016c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_BMAN_MBUFPOOL_READDMA_LOWAT, 0x0); 12026c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_BMAN_MBUFPOOL_MACRX_LOWAT, 0x10); 12036c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_BMAN_MBUFPOOL_HIWAT, 0x60); 12046c8d8eccSSepherosa Ziehau } 12056c8d8eccSSepherosa Ziehau 12066c8d8eccSSepherosa Ziehau /* Configure DMA resource watermarks */ 12076c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_BMAN_DMA_DESCPOOL_LOWAT, 5); 12086c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_BMAN_DMA_DESCPOOL_HIWAT, 10); 12096c8d8eccSSepherosa Ziehau 12106c8d8eccSSepherosa Ziehau /* Enable buffer manager */ 12116c8d8eccSSepherosa Ziehau val = BGE_BMANMODE_ENABLE | BGE_BMANMODE_LOMBUF_ATTN; 12126c8d8eccSSepherosa Ziehau /* 12136c8d8eccSSepherosa Ziehau * Change the arbitration algorithm of TXMBUF read request to 12146c8d8eccSSepherosa Ziehau * round-robin instead of priority based for BCM5719. When 12156c8d8eccSSepherosa Ziehau * TXFIFO is almost empty, RDMA will hold its request until 12166c8d8eccSSepherosa Ziehau * TXFIFO is not almost empty. 12176c8d8eccSSepherosa Ziehau */ 12186c8d8eccSSepherosa Ziehau if (sc->bnx_asicrev == BGE_ASICREV_BCM5719) 12196c8d8eccSSepherosa Ziehau val |= BGE_BMANMODE_NO_TX_UNDERRUN; 1220e5eebe34SSepherosa Ziehau if (sc->bnx_asicrev == BGE_ASICREV_BCM5717 || 1221e5eebe34SSepherosa Ziehau sc->bnx_chipid == BGE_CHIPID_BCM5719_A0 || 1222e5eebe34SSepherosa Ziehau sc->bnx_chipid == BGE_CHIPID_BCM5720_A0) 1223e5eebe34SSepherosa Ziehau val |= BGE_BMANMODE_LOMBUF_ATTN; 12246c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_BMAN_MODE, val); 12256c8d8eccSSepherosa Ziehau 12266c8d8eccSSepherosa Ziehau /* Poll for buffer manager start indication */ 12276c8d8eccSSepherosa Ziehau for (i = 0; i < BNX_TIMEOUT; i++) { 12286c8d8eccSSepherosa Ziehau if (CSR_READ_4(sc, BGE_BMAN_MODE) & BGE_BMANMODE_ENABLE) 12296c8d8eccSSepherosa Ziehau break; 12306c8d8eccSSepherosa Ziehau DELAY(10); 12316c8d8eccSSepherosa Ziehau } 12326c8d8eccSSepherosa Ziehau 12336c8d8eccSSepherosa Ziehau if (i == BNX_TIMEOUT) { 12346c8d8eccSSepherosa Ziehau if_printf(&sc->arpcom.ac_if, 12356c8d8eccSSepherosa Ziehau "buffer manager failed to start\n"); 12366c8d8eccSSepherosa Ziehau return(ENXIO); 12376c8d8eccSSepherosa Ziehau } 12386c8d8eccSSepherosa Ziehau 12396c8d8eccSSepherosa Ziehau /* Enable flow-through queues */ 12406c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_FTQ_RESET, 0xFFFFFFFF); 12416c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_FTQ_RESET, 0); 12426c8d8eccSSepherosa Ziehau 12436c8d8eccSSepherosa Ziehau /* Wait until queue initialization is complete */ 12446c8d8eccSSepherosa Ziehau for (i = 0; i < BNX_TIMEOUT; i++) { 12456c8d8eccSSepherosa Ziehau if (CSR_READ_4(sc, BGE_FTQ_RESET) == 0) 12466c8d8eccSSepherosa Ziehau break; 12476c8d8eccSSepherosa Ziehau DELAY(10); 12486c8d8eccSSepherosa Ziehau } 12496c8d8eccSSepherosa Ziehau 12506c8d8eccSSepherosa Ziehau if (i == BNX_TIMEOUT) { 12516c8d8eccSSepherosa Ziehau if_printf(&sc->arpcom.ac_if, 12526c8d8eccSSepherosa Ziehau "flow-through queue init failed\n"); 12536c8d8eccSSepherosa Ziehau return(ENXIO); 12546c8d8eccSSepherosa Ziehau } 12556c8d8eccSSepherosa Ziehau 12566c8d8eccSSepherosa Ziehau /* 12576c8d8eccSSepherosa Ziehau * Summary of rings supported by the controller: 12586c8d8eccSSepherosa Ziehau * 12596c8d8eccSSepherosa Ziehau * Standard Receive Producer Ring 12606c8d8eccSSepherosa Ziehau * - This ring is used to feed receive buffers for "standard" 12616c8d8eccSSepherosa Ziehau * sized frames (typically 1536 bytes) to the controller. 12626c8d8eccSSepherosa Ziehau * 12636c8d8eccSSepherosa Ziehau * Jumbo Receive Producer Ring 12646c8d8eccSSepherosa Ziehau * - This ring is used to feed receive buffers for jumbo sized 12656c8d8eccSSepherosa Ziehau * frames (i.e. anything bigger than the "standard" frames) 12666c8d8eccSSepherosa Ziehau * to the controller. 12676c8d8eccSSepherosa Ziehau * 12686c8d8eccSSepherosa Ziehau * Mini Receive Producer Ring 12696c8d8eccSSepherosa Ziehau * - This ring is used to feed receive buffers for "mini" 12706c8d8eccSSepherosa Ziehau * sized frames to the controller. 12716c8d8eccSSepherosa Ziehau * - This feature required external memory for the controller 12726c8d8eccSSepherosa Ziehau * but was never used in a production system. Should always 12736c8d8eccSSepherosa Ziehau * be disabled. 12746c8d8eccSSepherosa Ziehau * 12756c8d8eccSSepherosa Ziehau * Receive Return Ring 12766c8d8eccSSepherosa Ziehau * - After the controller has placed an incoming frame into a 12776c8d8eccSSepherosa Ziehau * receive buffer that buffer is moved into a receive return 12786c8d8eccSSepherosa Ziehau * ring. The driver is then responsible to passing the 12796c8d8eccSSepherosa Ziehau * buffer up to the stack. Many versions of the controller 12806c8d8eccSSepherosa Ziehau * support multiple RR rings. 12816c8d8eccSSepherosa Ziehau * 12826c8d8eccSSepherosa Ziehau * Send Ring 12836c8d8eccSSepherosa Ziehau * - This ring is used for outgoing frames. Many versions of 12846c8d8eccSSepherosa Ziehau * the controller support multiple send rings. 12856c8d8eccSSepherosa Ziehau */ 12866c8d8eccSSepherosa Ziehau 12876c8d8eccSSepherosa Ziehau /* Initialize the standard receive producer ring control block. */ 12886c8d8eccSSepherosa Ziehau rcb = &sc->bnx_ldata.bnx_info.bnx_std_rx_rcb; 12896c8d8eccSSepherosa Ziehau rcb->bge_hostaddr.bge_addr_lo = 1290beedf5beSSepherosa Ziehau BGE_ADDR_LO(sc->bnx_rx_std_ring.bnx_rx_std_ring_paddr); 12916c8d8eccSSepherosa Ziehau rcb->bge_hostaddr.bge_addr_hi = 1292beedf5beSSepherosa Ziehau BGE_ADDR_HI(sc->bnx_rx_std_ring.bnx_rx_std_ring_paddr); 1293f368d0d9SSepherosa Ziehau if (BNX_IS_57765_PLUS(sc)) { 12946c8d8eccSSepherosa Ziehau /* 12956c8d8eccSSepherosa Ziehau * Bits 31-16: Programmable ring size (2048, 1024, 512, .., 32) 12966c8d8eccSSepherosa Ziehau * Bits 15-2 : Maximum RX frame size 12976c8d8eccSSepherosa Ziehau * Bit 1 : 1 = Ring Disabled, 0 = Ring ENabled 12986c8d8eccSSepherosa Ziehau * Bit 0 : Reserved 12996c8d8eccSSepherosa Ziehau */ 13006c8d8eccSSepherosa Ziehau rcb->bge_maxlen_flags = 13016c8d8eccSSepherosa Ziehau BGE_RCB_MAXLEN_FLAGS(512, BNX_MAX_FRAMELEN << 2); 13026c8d8eccSSepherosa Ziehau } else { 13036c8d8eccSSepherosa Ziehau /* 13046c8d8eccSSepherosa Ziehau * Bits 31-16: Programmable ring size (512, 256, 128, 64, 32) 13056c8d8eccSSepherosa Ziehau * Bits 15-2 : Reserved (should be 0) 13066c8d8eccSSepherosa Ziehau * Bit 1 : 1 = Ring Disabled, 0 = Ring Enabled 13076c8d8eccSSepherosa Ziehau * Bit 0 : Reserved 13086c8d8eccSSepherosa Ziehau */ 13096c8d8eccSSepherosa Ziehau rcb->bge_maxlen_flags = BGE_RCB_MAXLEN_FLAGS(512, 0); 13106c8d8eccSSepherosa Ziehau } 1311303fdc72SSepherosa Ziehau if (BNX_IS_5717_PLUS(sc)) 13126c8d8eccSSepherosa Ziehau rcb->bge_nicaddr = BGE_STD_RX_RINGS_5717; 13136c8d8eccSSepherosa Ziehau else 13146c8d8eccSSepherosa Ziehau rcb->bge_nicaddr = BGE_STD_RX_RINGS; 13156c8d8eccSSepherosa Ziehau /* Write the standard receive producer ring control block. */ 13166c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_RX_STD_RCB_HADDR_HI, rcb->bge_hostaddr.bge_addr_hi); 13176c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_RX_STD_RCB_HADDR_LO, rcb->bge_hostaddr.bge_addr_lo); 13186c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_RX_STD_RCB_MAXLEN_FLAGS, rcb->bge_maxlen_flags); 1319*695a8586SSepherosa Ziehau if (!BNX_IS_5717_PLUS(sc)) 13206c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_RX_STD_RCB_NICADDR, rcb->bge_nicaddr); 13216c8d8eccSSepherosa Ziehau /* Reset the standard receive producer ring producer index. */ 13226c8d8eccSSepherosa Ziehau bnx_writembx(sc, BGE_MBX_RX_STD_PROD_LO, 0); 13236c8d8eccSSepherosa Ziehau 13246c8d8eccSSepherosa Ziehau /* 13256c8d8eccSSepherosa Ziehau * Initialize the jumbo RX producer ring control 13266c8d8eccSSepherosa Ziehau * block. We set the 'ring disabled' bit in the 13276c8d8eccSSepherosa Ziehau * flags field until we're actually ready to start 13286c8d8eccSSepherosa Ziehau * using this ring (i.e. once we set the MTU 13296c8d8eccSSepherosa Ziehau * high enough to require it). 13306c8d8eccSSepherosa Ziehau */ 13316c8d8eccSSepherosa Ziehau if (BNX_IS_JUMBO_CAPABLE(sc)) { 13326c8d8eccSSepherosa Ziehau rcb = &sc->bnx_ldata.bnx_info.bnx_jumbo_rx_rcb; 13336c8d8eccSSepherosa Ziehau /* Get the jumbo receive producer ring RCB parameters. */ 13346c8d8eccSSepherosa Ziehau rcb->bge_hostaddr.bge_addr_lo = 13356c8d8eccSSepherosa Ziehau BGE_ADDR_LO(sc->bnx_ldata.bnx_rx_jumbo_ring_paddr); 13366c8d8eccSSepherosa Ziehau rcb->bge_hostaddr.bge_addr_hi = 13376c8d8eccSSepherosa Ziehau BGE_ADDR_HI(sc->bnx_ldata.bnx_rx_jumbo_ring_paddr); 13386c8d8eccSSepherosa Ziehau rcb->bge_maxlen_flags = 13396c8d8eccSSepherosa Ziehau BGE_RCB_MAXLEN_FLAGS(BNX_MAX_FRAMELEN, 13406c8d8eccSSepherosa Ziehau BGE_RCB_FLAG_RING_DISABLED); 1341303fdc72SSepherosa Ziehau if (BNX_IS_5717_PLUS(sc)) 13426c8d8eccSSepherosa Ziehau rcb->bge_nicaddr = BGE_JUMBO_RX_RINGS_5717; 13436c8d8eccSSepherosa Ziehau else 13446c8d8eccSSepherosa Ziehau rcb->bge_nicaddr = BGE_JUMBO_RX_RINGS; 13456c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_RX_JUMBO_RCB_HADDR_HI, 13466c8d8eccSSepherosa Ziehau rcb->bge_hostaddr.bge_addr_hi); 13476c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_RX_JUMBO_RCB_HADDR_LO, 13486c8d8eccSSepherosa Ziehau rcb->bge_hostaddr.bge_addr_lo); 13496c8d8eccSSepherosa Ziehau /* Program the jumbo receive producer ring RCB parameters. */ 13506c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_RX_JUMBO_RCB_MAXLEN_FLAGS, 13516c8d8eccSSepherosa Ziehau rcb->bge_maxlen_flags); 13526c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_RX_JUMBO_RCB_NICADDR, rcb->bge_nicaddr); 13536c8d8eccSSepherosa Ziehau /* Reset the jumbo receive producer ring producer index. */ 13546c8d8eccSSepherosa Ziehau bnx_writembx(sc, BGE_MBX_RX_JUMBO_PROD_LO, 0); 13556c8d8eccSSepherosa Ziehau } 13566c8d8eccSSepherosa Ziehau 13576c8d8eccSSepherosa Ziehau /* 13586c8d8eccSSepherosa Ziehau * The BD ring replenish thresholds control how often the 13596c8d8eccSSepherosa Ziehau * hardware fetches new BD's from the producer rings in host 13606c8d8eccSSepherosa Ziehau * memory. Setting the value too low on a busy system can 13616c8d8eccSSepherosa Ziehau * starve the hardware and recue the throughpout. 13626c8d8eccSSepherosa Ziehau * 13636c8d8eccSSepherosa Ziehau * Set the BD ring replentish thresholds. The recommended 13646c8d8eccSSepherosa Ziehau * values are 1/8th the number of descriptors allocated to 13656c8d8eccSSepherosa Ziehau * each ring. 13666c8d8eccSSepherosa Ziehau */ 13676c8d8eccSSepherosa Ziehau val = 8; 13686c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_RBDI_STD_REPL_THRESH, val); 13696c8d8eccSSepherosa Ziehau if (BNX_IS_JUMBO_CAPABLE(sc)) { 13706c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_RBDI_JUMBO_REPL_THRESH, 13716c8d8eccSSepherosa Ziehau BGE_JUMBO_RX_RING_CNT/8); 13726c8d8eccSSepherosa Ziehau } 1373f368d0d9SSepherosa Ziehau if (BNX_IS_57765_PLUS(sc)) { 13746c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_STD_REPLENISH_LWM, 32); 13756c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_JMB_REPLENISH_LWM, 16); 13766c8d8eccSSepherosa Ziehau } 13776c8d8eccSSepherosa Ziehau 13786c8d8eccSSepherosa Ziehau /* 13796c8d8eccSSepherosa Ziehau * Disable all send rings by setting the 'ring disabled' bit 13806c8d8eccSSepherosa Ziehau * in the flags field of all the TX send ring control blocks, 13816c8d8eccSSepherosa Ziehau * located in NIC memory. 13826c8d8eccSSepherosa Ziehau */ 138380969639SSepherosa Ziehau if (BNX_IS_5717_PLUS(sc)) 138480969639SSepherosa Ziehau limit = 4; 1385b96cbbb6SSepherosa Ziehau else if (BNX_IS_57765_FAMILY(sc) || 1386b96cbbb6SSepherosa Ziehau sc->bnx_asicrev == BGE_ASICREV_BCM5762) 13874f23029eSSepherosa Ziehau limit = 2; 138880969639SSepherosa Ziehau else 13896c8d8eccSSepherosa Ziehau limit = 1; 13906c8d8eccSSepherosa Ziehau vrcb = BGE_MEMWIN_START + BGE_SEND_RING_RCB; 13916c8d8eccSSepherosa Ziehau for (i = 0; i < limit; i++) { 13926c8d8eccSSepherosa Ziehau RCB_WRITE_4(sc, vrcb, bge_maxlen_flags, 13936c8d8eccSSepherosa Ziehau BGE_RCB_MAXLEN_FLAGS(0, BGE_RCB_FLAG_RING_DISABLED)); 13946c8d8eccSSepherosa Ziehau vrcb += sizeof(struct bge_rcb); 13956c8d8eccSSepherosa Ziehau } 13966c8d8eccSSepherosa Ziehau 1397*695a8586SSepherosa Ziehau /* 1398*695a8586SSepherosa Ziehau * Configure send ring RCBs 1399*695a8586SSepherosa Ziehau */ 14006c8d8eccSSepherosa Ziehau vrcb = BGE_MEMWIN_START + BGE_SEND_RING_RCB; 1401*695a8586SSepherosa Ziehau for (i = 0; i < sc->bnx_tx_ringcnt; ++i) { 1402*695a8586SSepherosa Ziehau struct bnx_tx_ring *txr = &sc->bnx_tx_ring[i]; 1403*695a8586SSepherosa Ziehau 140433a04907SSepherosa Ziehau BGE_HOSTADDR(taddr, txr->bnx_tx_ring_paddr); 1405*695a8586SSepherosa Ziehau RCB_WRITE_4(sc, vrcb, bge_hostaddr.bge_addr_hi, 1406*695a8586SSepherosa Ziehau taddr.bge_addr_hi); 1407*695a8586SSepherosa Ziehau RCB_WRITE_4(sc, vrcb, bge_hostaddr.bge_addr_lo, 1408*695a8586SSepherosa Ziehau taddr.bge_addr_lo); 14096c8d8eccSSepherosa Ziehau RCB_WRITE_4(sc, vrcb, bge_maxlen_flags, 14106c8d8eccSSepherosa Ziehau BGE_RCB_MAXLEN_FLAGS(BGE_TX_RING_CNT, 0)); 1411*695a8586SSepherosa Ziehau vrcb += sizeof(struct bge_rcb); 1412*695a8586SSepherosa Ziehau } 14136c8d8eccSSepherosa Ziehau 14146c8d8eccSSepherosa Ziehau /* 14156c8d8eccSSepherosa Ziehau * Disable all receive return rings by setting the 14166c8d8eccSSepherosa Ziehau * 'ring disabled' bit in the flags field of all the receive 14176c8d8eccSSepherosa Ziehau * return ring control blocks, located in NIC memory. 14186c8d8eccSSepherosa Ziehau */ 141980969639SSepherosa Ziehau if (BNX_IS_5717_PLUS(sc)) { 14206c8d8eccSSepherosa Ziehau /* Should be 17, use 16 until we get an SRAM map. */ 14216c8d8eccSSepherosa Ziehau limit = 16; 1422b96cbbb6SSepherosa Ziehau } else if (BNX_IS_57765_FAMILY(sc) || 1423b96cbbb6SSepherosa Ziehau sc->bnx_asicrev == BGE_ASICREV_BCM5762) { 14246c8d8eccSSepherosa Ziehau limit = 4; 14256c8d8eccSSepherosa Ziehau } else { 14266c8d8eccSSepherosa Ziehau limit = 1; 14276c8d8eccSSepherosa Ziehau } 14286c8d8eccSSepherosa Ziehau /* Disable all receive return rings. */ 14296c8d8eccSSepherosa Ziehau vrcb = BGE_MEMWIN_START + BGE_RX_RETURN_RING_RCB; 14306c8d8eccSSepherosa Ziehau for (i = 0; i < limit; i++) { 14316c8d8eccSSepherosa Ziehau RCB_WRITE_4(sc, vrcb, bge_hostaddr.bge_addr_hi, 0); 14326c8d8eccSSepherosa Ziehau RCB_WRITE_4(sc, vrcb, bge_hostaddr.bge_addr_lo, 0); 14336c8d8eccSSepherosa Ziehau RCB_WRITE_4(sc, vrcb, bge_maxlen_flags, 14346c8d8eccSSepherosa Ziehau BGE_RCB_FLAG_RING_DISABLED); 14356c8d8eccSSepherosa Ziehau bnx_writembx(sc, BGE_MBX_RX_CONS0_LO + 14366c8d8eccSSepherosa Ziehau (i * (sizeof(uint64_t))), 0); 14376c8d8eccSSepherosa Ziehau vrcb += sizeof(struct bge_rcb); 14386c8d8eccSSepherosa Ziehau } 14396c8d8eccSSepherosa Ziehau 14406c8d8eccSSepherosa Ziehau /* 1441*695a8586SSepherosa Ziehau * Set up receive return rings. Note that the NIC address 14426c8d8eccSSepherosa Ziehau * for RX return rings is 0x0. The return rings live entirely 14436c8d8eccSSepherosa Ziehau * within the host, so the nicaddr field in the RCB isn't used. 14446c8d8eccSSepherosa Ziehau */ 14456c8d8eccSSepherosa Ziehau vrcb = BGE_MEMWIN_START + BGE_RX_RETURN_RING_RCB; 1446*695a8586SSepherosa Ziehau for (i = 0; i < sc->bnx_rx_retcnt; ++i) { 1447*695a8586SSepherosa Ziehau struct bnx_rx_ret_ring *ret = &sc->bnx_rx_ret_ring[i]; 1448*695a8586SSepherosa Ziehau 1449beedf5beSSepherosa Ziehau BGE_HOSTADDR(taddr, ret->bnx_rx_ret_ring_paddr); 1450*695a8586SSepherosa Ziehau RCB_WRITE_4(sc, vrcb, bge_hostaddr.bge_addr_hi, 1451*695a8586SSepherosa Ziehau taddr.bge_addr_hi); 1452*695a8586SSepherosa Ziehau RCB_WRITE_4(sc, vrcb, bge_hostaddr.bge_addr_lo, 1453*695a8586SSepherosa Ziehau taddr.bge_addr_lo); 14546c8d8eccSSepherosa Ziehau RCB_WRITE_4(sc, vrcb, bge_maxlen_flags, 1455e0f74fc8SSepherosa Ziehau BGE_RCB_MAXLEN_FLAGS(BNX_RETURN_RING_CNT, 0)); 1456*695a8586SSepherosa Ziehau vrcb += sizeof(struct bge_rcb); 1457*695a8586SSepherosa Ziehau } 14586c8d8eccSSepherosa Ziehau 14596c8d8eccSSepherosa Ziehau /* Set random backoff seed for TX */ 14606c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_TX_RANDOM_BACKOFF, 14616c8d8eccSSepherosa Ziehau sc->arpcom.ac_enaddr[0] + sc->arpcom.ac_enaddr[1] + 14626c8d8eccSSepherosa Ziehau sc->arpcom.ac_enaddr[2] + sc->arpcom.ac_enaddr[3] + 14636c8d8eccSSepherosa Ziehau sc->arpcom.ac_enaddr[4] + sc->arpcom.ac_enaddr[5] + 14646c8d8eccSSepherosa Ziehau BGE_TX_BACKOFF_SEED_MASK); 14656c8d8eccSSepherosa Ziehau 14666c8d8eccSSepherosa Ziehau /* Set inter-packet gap */ 14676c8d8eccSSepherosa Ziehau val = 0x2620; 1468b96cbbb6SSepherosa Ziehau if (sc->bnx_asicrev == BGE_ASICREV_BCM5720 || 1469b96cbbb6SSepherosa Ziehau sc->bnx_asicrev == BGE_ASICREV_BCM5762) { 14706c8d8eccSSepherosa Ziehau val |= CSR_READ_4(sc, BGE_TX_LENGTHS) & 14716c8d8eccSSepherosa Ziehau (BGE_TXLEN_JMB_FRM_LEN_MSK | BGE_TXLEN_CNT_DN_VAL_MSK); 14726c8d8eccSSepherosa Ziehau } 14736c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_TX_LENGTHS, val); 14746c8d8eccSSepherosa Ziehau 14756c8d8eccSSepherosa Ziehau /* 14766c8d8eccSSepherosa Ziehau * Specify which ring to use for packets that don't match 14776c8d8eccSSepherosa Ziehau * any RX rules. 14786c8d8eccSSepherosa Ziehau */ 14796c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_RX_RULES_CFG, 0x08); 14806c8d8eccSSepherosa Ziehau 14816c8d8eccSSepherosa Ziehau /* 14826c8d8eccSSepherosa Ziehau * Configure number of RX lists. One interrupt distribution 14836c8d8eccSSepherosa Ziehau * list, sixteen active lists, one bad frames class. 14846c8d8eccSSepherosa Ziehau */ 14856c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_RXLP_CFG, 0x181); 14866c8d8eccSSepherosa Ziehau 14876c8d8eccSSepherosa Ziehau /* Inialize RX list placement stats mask. */ 14886c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_RXLP_STATS_ENABLE_MASK, 0x007FFFFF); 14896c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_RXLP_STATS_CTL, 0x1); 14906c8d8eccSSepherosa Ziehau 14916c8d8eccSSepherosa Ziehau /* Disable host coalescing until we get it set up */ 14926c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_HCC_MODE, 0x00000000); 14936c8d8eccSSepherosa Ziehau 14946c8d8eccSSepherosa Ziehau /* Poll to make sure it's shut down. */ 14956c8d8eccSSepherosa Ziehau for (i = 0; i < BNX_TIMEOUT; i++) { 14966c8d8eccSSepherosa Ziehau if (!(CSR_READ_4(sc, BGE_HCC_MODE) & BGE_HCCMODE_ENABLE)) 14976c8d8eccSSepherosa Ziehau break; 14986c8d8eccSSepherosa Ziehau DELAY(10); 14996c8d8eccSSepherosa Ziehau } 15006c8d8eccSSepherosa Ziehau 15016c8d8eccSSepherosa Ziehau if (i == BNX_TIMEOUT) { 15026c8d8eccSSepherosa Ziehau if_printf(&sc->arpcom.ac_if, 15036c8d8eccSSepherosa Ziehau "host coalescing engine failed to idle\n"); 15046c8d8eccSSepherosa Ziehau return(ENXIO); 15056c8d8eccSSepherosa Ziehau } 15066c8d8eccSSepherosa Ziehau 15076c8d8eccSSepherosa Ziehau /* Set up host coalescing defaults */ 1508*695a8586SSepherosa Ziehau sc->bnx_coal_chg = BNX_RX_COAL_TICKS_CHG | 1509*695a8586SSepherosa Ziehau BNX_TX_COAL_TICKS_CHG | 1510*695a8586SSepherosa Ziehau BNX_RX_COAL_BDS_CHG | 1511*695a8586SSepherosa Ziehau BNX_TX_COAL_BDS_CHG | 1512*695a8586SSepherosa Ziehau BNX_RX_COAL_BDS_INT_CHG | 1513*695a8586SSepherosa Ziehau BNX_TX_COAL_BDS_INT_CHG; 1514*695a8586SSepherosa Ziehau bnx_coal_change(sc); 15156c8d8eccSSepherosa Ziehau 1516*695a8586SSepherosa Ziehau /* 1517*695a8586SSepherosa Ziehau * Set up addresses of status blocks 1518*695a8586SSepherosa Ziehau */ 1519*695a8586SSepherosa Ziehau intr = &sc->bnx_intr_data[0]; 15200a806e3aSSepherosa Ziehau bzero(intr->bnx_status_block, BGE_STATUS_BLK_SZ); 15216c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_HCC_STATUSBLK_ADDR_HI, 15220a806e3aSSepherosa Ziehau BGE_ADDR_HI(intr->bnx_status_block_paddr)); 15236c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_HCC_STATUSBLK_ADDR_LO, 15240a806e3aSSepherosa Ziehau BGE_ADDR_LO(intr->bnx_status_block_paddr)); 1525*695a8586SSepherosa Ziehau for (i = 1; i < sc->bnx_intr_cnt; ++i) { 1526*695a8586SSepherosa Ziehau intr = &sc->bnx_intr_data[i]; 1527*695a8586SSepherosa Ziehau bzero(intr->bnx_status_block, BGE_STATUS_BLK_SZ); 1528*695a8586SSepherosa Ziehau CSR_WRITE_4(sc, BGE_VEC1_STATUSBLK_ADDR_HI + ((i - 1) * 8), 1529*695a8586SSepherosa Ziehau BGE_ADDR_HI(intr->bnx_status_block_paddr)); 1530*695a8586SSepherosa Ziehau CSR_WRITE_4(sc, BGE_VEC1_STATUSBLK_ADDR_LO + ((i - 1) * 8), 1531*695a8586SSepherosa Ziehau BGE_ADDR_LO(intr->bnx_status_block_paddr)); 1532*695a8586SSepherosa Ziehau } 15336c8d8eccSSepherosa Ziehau 15346c8d8eccSSepherosa Ziehau /* Set up status block partail update size. */ 15356c8d8eccSSepherosa Ziehau val = BGE_STATBLKSZ_32BYTE; 15366c8d8eccSSepherosa Ziehau #if 0 15376c8d8eccSSepherosa Ziehau /* 15386c8d8eccSSepherosa Ziehau * Does not seem to have visible effect in both 15396c8d8eccSSepherosa Ziehau * bulk data (1472B UDP datagram) and tiny data 15406c8d8eccSSepherosa Ziehau * (18B UDP datagram) TX tests. 15416c8d8eccSSepherosa Ziehau */ 15426c8d8eccSSepherosa Ziehau val |= BGE_HCCMODE_CLRTICK_TX; 15436c8d8eccSSepherosa Ziehau #endif 15446c8d8eccSSepherosa Ziehau /* Turn on host coalescing state machine */ 15456c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_HCC_MODE, val | BGE_HCCMODE_ENABLE); 15466c8d8eccSSepherosa Ziehau 15476c8d8eccSSepherosa Ziehau /* Turn on RX BD completion state machine and enable attentions */ 15486c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_RBDC_MODE, 15496c8d8eccSSepherosa Ziehau BGE_RBDCMODE_ENABLE|BGE_RBDCMODE_ATTN); 15506c8d8eccSSepherosa Ziehau 15516c8d8eccSSepherosa Ziehau /* Turn on RX list placement state machine */ 15526c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_RXLP_MODE, BGE_RXLPMODE_ENABLE); 15536c8d8eccSSepherosa Ziehau 15546c8d8eccSSepherosa Ziehau val = BGE_MACMODE_TXDMA_ENB | BGE_MACMODE_RXDMA_ENB | 15556c8d8eccSSepherosa Ziehau BGE_MACMODE_RX_STATS_CLEAR | BGE_MACMODE_TX_STATS_CLEAR | 15566c8d8eccSSepherosa Ziehau BGE_MACMODE_RX_STATS_ENB | BGE_MACMODE_TX_STATS_ENB | 15576c8d8eccSSepherosa Ziehau BGE_MACMODE_FRMHDR_DMA_ENB; 15586c8d8eccSSepherosa Ziehau 15596c8d8eccSSepherosa Ziehau if (sc->bnx_flags & BNX_FLAG_TBI) 15606c8d8eccSSepherosa Ziehau val |= BGE_PORTMODE_TBI; 15616c8d8eccSSepherosa Ziehau else if (sc->bnx_flags & BNX_FLAG_MII_SERDES) 15626c8d8eccSSepherosa Ziehau val |= BGE_PORTMODE_GMII; 15636c8d8eccSSepherosa Ziehau else 15646c8d8eccSSepherosa Ziehau val |= BGE_PORTMODE_MII; 15656c8d8eccSSepherosa Ziehau 15666c8d8eccSSepherosa Ziehau /* Turn on DMA, clear stats */ 15676c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_MAC_MODE, val); 15686c8d8eccSSepherosa Ziehau 15696c8d8eccSSepherosa Ziehau /* Set misc. local control, enable interrupts on attentions */ 15706c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_MISC_LOCAL_CTL, BGE_MLC_INTR_ONATTN); 15716c8d8eccSSepherosa Ziehau 15726c8d8eccSSepherosa Ziehau #ifdef notdef 15736c8d8eccSSepherosa Ziehau /* Assert GPIO pins for PHY reset */ 15746c8d8eccSSepherosa Ziehau BNX_SETBIT(sc, BGE_MISC_LOCAL_CTL, BGE_MLC_MISCIO_OUT0| 15756c8d8eccSSepherosa Ziehau BGE_MLC_MISCIO_OUT1|BGE_MLC_MISCIO_OUT2); 15766c8d8eccSSepherosa Ziehau BNX_SETBIT(sc, BGE_MISC_LOCAL_CTL, BGE_MLC_MISCIO_OUTEN0| 15776c8d8eccSSepherosa Ziehau BGE_MLC_MISCIO_OUTEN1|BGE_MLC_MISCIO_OUTEN2); 15786c8d8eccSSepherosa Ziehau #endif 15796c8d8eccSSepherosa Ziehau 1580*695a8586SSepherosa Ziehau if (sc->bnx_intr_type == PCI_INTR_TYPE_MSIX) 1581*695a8586SSepherosa Ziehau bnx_enable_msi(sc, TRUE); 1582*695a8586SSepherosa Ziehau 15836c8d8eccSSepherosa Ziehau /* Turn on write DMA state machine */ 15846c8d8eccSSepherosa Ziehau val = BGE_WDMAMODE_ENABLE|BGE_WDMAMODE_ALL_ATTNS; 15856c8d8eccSSepherosa Ziehau /* Enable host coalescing bug fix. */ 15866c8d8eccSSepherosa Ziehau val |= BGE_WDMAMODE_STATUS_TAG_FIX; 15876c8d8eccSSepherosa Ziehau if (sc->bnx_asicrev == BGE_ASICREV_BCM5785) { 15886c8d8eccSSepherosa Ziehau /* Request larger DMA burst size to get better performance. */ 15896c8d8eccSSepherosa Ziehau val |= BGE_WDMAMODE_BURST_ALL_DATA; 15906c8d8eccSSepherosa Ziehau } 15916c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_WDMA_MODE, val); 15926c8d8eccSSepherosa Ziehau DELAY(40); 15936c8d8eccSSepherosa Ziehau 15943730a14dSSepherosa Ziehau if (BNX_IS_57765_PLUS(sc)) { 1595b96cbbb6SSepherosa Ziehau uint32_t dmactl, dmactl_reg; 15966c8d8eccSSepherosa Ziehau 1597b96cbbb6SSepherosa Ziehau if (sc->bnx_asicrev == BGE_ASICREV_BCM5762) 1598b96cbbb6SSepherosa Ziehau dmactl_reg = BGE_RDMA_RSRVCTRL2; 1599b96cbbb6SSepherosa Ziehau else 1600b96cbbb6SSepherosa Ziehau dmactl_reg = BGE_RDMA_RSRVCTRL; 1601b96cbbb6SSepherosa Ziehau 1602b96cbbb6SSepherosa Ziehau dmactl = CSR_READ_4(sc, dmactl_reg); 16036c8d8eccSSepherosa Ziehau /* 16046c8d8eccSSepherosa Ziehau * Adjust tx margin to prevent TX data corruption and 16056c8d8eccSSepherosa Ziehau * fix internal FIFO overflow. 16066c8d8eccSSepherosa Ziehau */ 16076c8d8eccSSepherosa Ziehau if (sc->bnx_asicrev == BGE_ASICREV_BCM5719 || 1608b96cbbb6SSepherosa Ziehau sc->bnx_asicrev == BGE_ASICREV_BCM5720 || 1609b96cbbb6SSepherosa Ziehau sc->bnx_asicrev == BGE_ASICREV_BCM5762) { 16106c8d8eccSSepherosa Ziehau dmactl &= ~(BGE_RDMA_RSRVCTRL_FIFO_LWM_MASK | 16116c8d8eccSSepherosa Ziehau BGE_RDMA_RSRVCTRL_FIFO_HWM_MASK | 16126c8d8eccSSepherosa Ziehau BGE_RDMA_RSRVCTRL_TXMRGN_MASK); 16136c8d8eccSSepherosa Ziehau dmactl |= BGE_RDMA_RSRVCTRL_FIFO_LWM_1_5K | 16146c8d8eccSSepherosa Ziehau BGE_RDMA_RSRVCTRL_FIFO_HWM_1_5K | 16156c8d8eccSSepherosa Ziehau BGE_RDMA_RSRVCTRL_TXMRGN_320B; 16166c8d8eccSSepherosa Ziehau } 16176c8d8eccSSepherosa Ziehau /* 16186c8d8eccSSepherosa Ziehau * Enable fix for read DMA FIFO overruns. 16196c8d8eccSSepherosa Ziehau * The fix is to limit the number of RX BDs 16206c8d8eccSSepherosa Ziehau * the hardware would fetch at a fime. 16216c8d8eccSSepherosa Ziehau */ 1622b96cbbb6SSepherosa Ziehau CSR_WRITE_4(sc, dmactl_reg, 16236c8d8eccSSepherosa Ziehau dmactl | BGE_RDMA_RSRVCTRL_FIFO_OFLW_FIX); 16246c8d8eccSSepherosa Ziehau } 16256c8d8eccSSepherosa Ziehau 16266c8d8eccSSepherosa Ziehau if (sc->bnx_asicrev == BGE_ASICREV_BCM5719) { 16276c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_RDMA_LSO_CRPTEN_CTRL, 16286c8d8eccSSepherosa Ziehau CSR_READ_4(sc, BGE_RDMA_LSO_CRPTEN_CTRL) | 16296c8d8eccSSepherosa Ziehau BGE_RDMA_LSO_CRPTEN_CTRL_BLEN_BD_4K | 16306c8d8eccSSepherosa Ziehau BGE_RDMA_LSO_CRPTEN_CTRL_BLEN_LSO_4K); 1631b96cbbb6SSepherosa Ziehau } else if (sc->bnx_asicrev == BGE_ASICREV_BCM5720 || 1632b96cbbb6SSepherosa Ziehau sc->bnx_asicrev == BGE_ASICREV_BCM5762) { 1633b96cbbb6SSepherosa Ziehau uint32_t ctrl_reg; 1634b96cbbb6SSepherosa Ziehau 1635b96cbbb6SSepherosa Ziehau if (sc->bnx_asicrev == BGE_ASICREV_BCM5762) 1636b96cbbb6SSepherosa Ziehau ctrl_reg = BGE_RDMA_LSO_CRPTEN_CTRL2; 1637b96cbbb6SSepherosa Ziehau else 1638b96cbbb6SSepherosa Ziehau ctrl_reg = BGE_RDMA_LSO_CRPTEN_CTRL; 1639b96cbbb6SSepherosa Ziehau 16406c8d8eccSSepherosa Ziehau /* 16416c8d8eccSSepherosa Ziehau * Allow 4KB burst length reads for non-LSO frames. 16426c8d8eccSSepherosa Ziehau * Enable 512B burst length reads for buffer descriptors. 16436c8d8eccSSepherosa Ziehau */ 1644b96cbbb6SSepherosa Ziehau CSR_WRITE_4(sc, ctrl_reg, 1645b96cbbb6SSepherosa Ziehau CSR_READ_4(sc, ctrl_reg) | 16466c8d8eccSSepherosa Ziehau BGE_RDMA_LSO_CRPTEN_CTRL_BLEN_BD_512 | 16476c8d8eccSSepherosa Ziehau BGE_RDMA_LSO_CRPTEN_CTRL_BLEN_LSO_4K); 16486c8d8eccSSepherosa Ziehau } 16496c8d8eccSSepherosa Ziehau 16506c8d8eccSSepherosa Ziehau /* Turn on read DMA state machine */ 16516c8d8eccSSepherosa Ziehau val = BGE_RDMAMODE_ENABLE | BGE_RDMAMODE_ALL_ATTNS; 16526c8d8eccSSepherosa Ziehau if (sc->bnx_asicrev == BGE_ASICREV_BCM5717) 16536c8d8eccSSepherosa Ziehau val |= BGE_RDMAMODE_MULT_DMA_RD_DIS; 16546c8d8eccSSepherosa Ziehau if (sc->bnx_asicrev == BGE_ASICREV_BCM5784 || 16556c8d8eccSSepherosa Ziehau sc->bnx_asicrev == BGE_ASICREV_BCM5785 || 16566c8d8eccSSepherosa Ziehau sc->bnx_asicrev == BGE_ASICREV_BCM57780) { 16576c8d8eccSSepherosa Ziehau val |= BGE_RDMAMODE_BD_SBD_CRPT_ATTN | 16586c8d8eccSSepherosa Ziehau BGE_RDMAMODE_MBUF_RBD_CRPT_ATTN | 16596c8d8eccSSepherosa Ziehau BGE_RDMAMODE_MBUF_SBD_CRPT_ATTN; 16606c8d8eccSSepherosa Ziehau } 1661b96cbbb6SSepherosa Ziehau if (sc->bnx_asicrev == BGE_ASICREV_BCM5720 || 1662b96cbbb6SSepherosa Ziehau sc->bnx_asicrev == BGE_ASICREV_BCM5762) { 16636c8d8eccSSepherosa Ziehau val |= CSR_READ_4(sc, BGE_RDMA_MODE) & 16646c8d8eccSSepherosa Ziehau BGE_RDMAMODE_H2BNC_VLAN_DET; 16656c8d8eccSSepherosa Ziehau /* 16666c8d8eccSSepherosa Ziehau * Allow multiple outstanding read requests from 16676c8d8eccSSepherosa Ziehau * non-LSO read DMA engine. 16686c8d8eccSSepherosa Ziehau */ 16696c8d8eccSSepherosa Ziehau val &= ~BGE_RDMAMODE_MULT_DMA_RD_DIS; 16706c8d8eccSSepherosa Ziehau } 167160e67e3fSSepherosa Ziehau if (sc->bnx_asicrev == BGE_ASICREV_BCM57766) 167260e67e3fSSepherosa Ziehau val |= BGE_RDMAMODE_JMB_2K_MMRR; 167366deb1c1SSepherosa Ziehau if (sc->bnx_flags & BNX_FLAG_TSO) 167466deb1c1SSepherosa Ziehau val |= BGE_RDMAMODE_TSO4_ENABLE; 16756c8d8eccSSepherosa Ziehau val |= BGE_RDMAMODE_FIFO_LONG_BURST; 16766c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_RDMA_MODE, val); 16776c8d8eccSSepherosa Ziehau DELAY(40); 16786c8d8eccSSepherosa Ziehau 16796c8d8eccSSepherosa Ziehau /* Turn on RX data completion state machine */ 16806c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_RDC_MODE, BGE_RDCMODE_ENABLE); 16816c8d8eccSSepherosa Ziehau 16826c8d8eccSSepherosa Ziehau /* Turn on RX BD initiator state machine */ 16836c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_RBDI_MODE, BGE_RBDIMODE_ENABLE); 16846c8d8eccSSepherosa Ziehau 16856c8d8eccSSepherosa Ziehau /* Turn on RX data and RX BD initiator state machine */ 16866c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_RDBDI_MODE, BGE_RDBDIMODE_ENABLE); 16876c8d8eccSSepherosa Ziehau 16886c8d8eccSSepherosa Ziehau /* Turn on send BD completion state machine */ 16896c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_SBDC_MODE, BGE_SBDCMODE_ENABLE); 16906c8d8eccSSepherosa Ziehau 16916c8d8eccSSepherosa Ziehau /* Turn on send data completion state machine */ 16926c8d8eccSSepherosa Ziehau val = BGE_SDCMODE_ENABLE; 16936c8d8eccSSepherosa Ziehau if (sc->bnx_asicrev == BGE_ASICREV_BCM5761) 16946c8d8eccSSepherosa Ziehau val |= BGE_SDCMODE_CDELAY; 16956c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_SDC_MODE, val); 16966c8d8eccSSepherosa Ziehau 16976c8d8eccSSepherosa Ziehau /* Turn on send data initiator state machine */ 169866deb1c1SSepherosa Ziehau if (sc->bnx_flags & BNX_FLAG_TSO) { 169966deb1c1SSepherosa Ziehau CSR_WRITE_4(sc, BGE_SDI_MODE, BGE_SDIMODE_ENABLE | 170066deb1c1SSepherosa Ziehau BGE_SDIMODE_HW_LSO_PRE_DMA); 170166deb1c1SSepherosa Ziehau } else { 17026c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_SDI_MODE, BGE_SDIMODE_ENABLE); 170366deb1c1SSepherosa Ziehau } 17046c8d8eccSSepherosa Ziehau 17056c8d8eccSSepherosa Ziehau /* Turn on send BD initiator state machine */ 1706*695a8586SSepherosa Ziehau val = BGE_SBDIMODE_ENABLE; 1707*695a8586SSepherosa Ziehau if (sc->bnx_tx_ringcnt > 1) 1708*695a8586SSepherosa Ziehau val |= BGE_SBDIMODE_MULTI_TXR; 1709*695a8586SSepherosa Ziehau CSR_WRITE_4(sc, BGE_SBDI_MODE, val); 17106c8d8eccSSepherosa Ziehau 17116c8d8eccSSepherosa Ziehau /* Turn on send BD selector state machine */ 17126c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_SRS_MODE, BGE_SRSMODE_ENABLE); 17136c8d8eccSSepherosa Ziehau 17146c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_SDI_STATS_ENABLE_MASK, 0x007FFFFF); 17156c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_SDI_STATS_CTL, 17166c8d8eccSSepherosa Ziehau BGE_SDISTATSCTL_ENABLE|BGE_SDISTATSCTL_FASTER); 17176c8d8eccSSepherosa Ziehau 17186c8d8eccSSepherosa Ziehau /* ack/clear link change events */ 17196c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_MAC_STS, BGE_MACSTAT_SYNC_CHANGED| 17206c8d8eccSSepherosa Ziehau BGE_MACSTAT_CFG_CHANGED|BGE_MACSTAT_MI_COMPLETE| 17216c8d8eccSSepherosa Ziehau BGE_MACSTAT_LINK_CHANGED); 17226c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_MI_STS, 0); 17236c8d8eccSSepherosa Ziehau 17246c8d8eccSSepherosa Ziehau /* 17256c8d8eccSSepherosa Ziehau * Enable attention when the link has changed state for 17266c8d8eccSSepherosa Ziehau * devices that use auto polling. 17276c8d8eccSSepherosa Ziehau */ 17286c8d8eccSSepherosa Ziehau if (sc->bnx_flags & BNX_FLAG_TBI) { 17296c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_MI_STS, BGE_MISTS_LINK); 17306c8d8eccSSepherosa Ziehau } else { 17316c8d8eccSSepherosa Ziehau if (sc->bnx_mi_mode & BGE_MIMODE_AUTOPOLL) { 17326c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_MI_MODE, sc->bnx_mi_mode); 17336c8d8eccSSepherosa Ziehau DELAY(80); 17346c8d8eccSSepherosa Ziehau } 17356c8d8eccSSepherosa Ziehau } 17366c8d8eccSSepherosa Ziehau 17376c8d8eccSSepherosa Ziehau /* 17386c8d8eccSSepherosa Ziehau * Clear any pending link state attention. 17396c8d8eccSSepherosa Ziehau * Otherwise some link state change events may be lost until attention 17406c8d8eccSSepherosa Ziehau * is cleared by bnx_intr() -> bnx_softc.bnx_link_upd() sequence. 17416c8d8eccSSepherosa Ziehau * It's not necessary on newer BCM chips - perhaps enabling link 17426c8d8eccSSepherosa Ziehau * state change attentions implies clearing pending attention. 17436c8d8eccSSepherosa Ziehau */ 17446c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_MAC_STS, BGE_MACSTAT_SYNC_CHANGED| 17456c8d8eccSSepherosa Ziehau BGE_MACSTAT_CFG_CHANGED|BGE_MACSTAT_MI_COMPLETE| 17466c8d8eccSSepherosa Ziehau BGE_MACSTAT_LINK_CHANGED); 17476c8d8eccSSepherosa Ziehau 17486c8d8eccSSepherosa Ziehau /* Enable link state change attentions. */ 17496c8d8eccSSepherosa Ziehau BNX_SETBIT(sc, BGE_MAC_EVT_ENB, BGE_EVTENB_LINK_CHANGED); 17506c8d8eccSSepherosa Ziehau 17516c8d8eccSSepherosa Ziehau return(0); 17526c8d8eccSSepherosa Ziehau } 17536c8d8eccSSepherosa Ziehau 17546c8d8eccSSepherosa Ziehau /* 17556c8d8eccSSepherosa Ziehau * Probe for a Broadcom chip. Check the PCI vendor and device IDs 17566c8d8eccSSepherosa Ziehau * against our list and return its name if we find a match. Note 17576c8d8eccSSepherosa Ziehau * that since the Broadcom controller contains VPD support, we 17586c8d8eccSSepherosa Ziehau * can get the device name string from the controller itself instead 17596c8d8eccSSepherosa Ziehau * of the compiled-in string. This is a little slow, but it guarantees 17606c8d8eccSSepherosa Ziehau * we'll always announce the right product name. 17616c8d8eccSSepherosa Ziehau */ 17626c8d8eccSSepherosa Ziehau static int 17636c8d8eccSSepherosa Ziehau bnx_probe(device_t dev) 17646c8d8eccSSepherosa Ziehau { 17656c8d8eccSSepherosa Ziehau const struct bnx_type *t; 17666c8d8eccSSepherosa Ziehau uint16_t product, vendor; 17676c8d8eccSSepherosa Ziehau 17686c8d8eccSSepherosa Ziehau if (!pci_is_pcie(dev)) 17696c8d8eccSSepherosa Ziehau return ENXIO; 17706c8d8eccSSepherosa Ziehau 17716c8d8eccSSepherosa Ziehau product = pci_get_device(dev); 17726c8d8eccSSepherosa Ziehau vendor = pci_get_vendor(dev); 17736c8d8eccSSepherosa Ziehau 17746c8d8eccSSepherosa Ziehau for (t = bnx_devs; t->bnx_name != NULL; t++) { 17756c8d8eccSSepherosa Ziehau if (vendor == t->bnx_vid && product == t->bnx_did) 17766c8d8eccSSepherosa Ziehau break; 17776c8d8eccSSepherosa Ziehau } 17786c8d8eccSSepherosa Ziehau if (t->bnx_name == NULL) 17796c8d8eccSSepherosa Ziehau return ENXIO; 17806c8d8eccSSepherosa Ziehau 17816c8d8eccSSepherosa Ziehau device_set_desc(dev, t->bnx_name); 17826c8d8eccSSepherosa Ziehau return 0; 17836c8d8eccSSepherosa Ziehau } 17846c8d8eccSSepherosa Ziehau 17856c8d8eccSSepherosa Ziehau static int 17866c8d8eccSSepherosa Ziehau bnx_attach(device_t dev) 17876c8d8eccSSepherosa Ziehau { 17886c8d8eccSSepherosa Ziehau struct ifnet *ifp; 17896c8d8eccSSepherosa Ziehau struct bnx_softc *sc; 1790841cdf08SSepherosa Ziehau struct bnx_rx_std_ring *std; 1791e594b5c4SSepherosa Ziehau uint32_t hwcfg = 0; 1792841cdf08SSepherosa Ziehau int error = 0, rid, capmask, i, std_cpuid, std_cpuid_def; 17936c8d8eccSSepherosa Ziehau uint8_t ether_addr[ETHER_ADDR_LEN]; 179407e9f7c0SSascha Wildner uint16_t product; 17956c8d8eccSSepherosa Ziehau uintptr_t mii_priv = 0; 1796*695a8586SSepherosa Ziehau #if defined(BNX_TSO_DEBUG) || defined(BNX_RSS_DEBUG) || defined(BNX_TSS_DEBUG) 179766deb1c1SSepherosa Ziehau char desc[32]; 179866deb1c1SSepherosa Ziehau #endif 17994fa38985SSepherosa Ziehau #ifdef IFPOLL_ENABLE 18004fa38985SSepherosa Ziehau int offset, offset_def; 18014fa38985SSepherosa Ziehau #endif 18026c8d8eccSSepherosa Ziehau 18036c8d8eccSSepherosa Ziehau sc = device_get_softc(dev); 18046c8d8eccSSepherosa Ziehau sc->bnx_dev = dev; 18057dbaa833SSepherosa Ziehau callout_init_mp(&sc->bnx_tick_timer); 18066c8d8eccSSepherosa Ziehau lwkt_serialize_init(&sc->bnx_jslot_serializer); 1807f33ac8a4SSepherosa Ziehau lwkt_serialize_init(&sc->bnx_main_serialize); 18086c8d8eccSSepherosa Ziehau 1809*695a8586SSepherosa Ziehau /* Always setup interrupt mailboxes */ 1810*695a8586SSepherosa Ziehau for (i = 0; i < BNX_INTR_MAX; ++i) { 1811*695a8586SSepherosa Ziehau callout_init_mp(&sc->bnx_intr_data[i].bnx_intr_timer); 1812*695a8586SSepherosa Ziehau sc->bnx_intr_data[i].bnx_sc = sc; 1813*695a8586SSepherosa Ziehau sc->bnx_intr_data[i].bnx_intr_mbx = BGE_MBX_IRQ0_LO + (i * 8); 1814*695a8586SSepherosa Ziehau sc->bnx_intr_data[i].bnx_intr_rid = -1; 1815*695a8586SSepherosa Ziehau sc->bnx_intr_data[i].bnx_intr_cpuid = -1; 1816*695a8586SSepherosa Ziehau } 1817*695a8586SSepherosa Ziehau 18186c8d8eccSSepherosa Ziehau product = pci_get_device(dev); 18196c8d8eccSSepherosa Ziehau 18206c8d8eccSSepherosa Ziehau #ifndef BURN_BRIDGES 18216c8d8eccSSepherosa Ziehau if (pci_get_powerstate(dev) != PCI_POWERSTATE_D0) { 18226c8d8eccSSepherosa Ziehau uint32_t irq, mem; 18236c8d8eccSSepherosa Ziehau 18246c8d8eccSSepherosa Ziehau irq = pci_read_config(dev, PCIR_INTLINE, 4); 18256c8d8eccSSepherosa Ziehau mem = pci_read_config(dev, BGE_PCI_BAR0, 4); 18266c8d8eccSSepherosa Ziehau 18276c8d8eccSSepherosa Ziehau device_printf(dev, "chip is in D%d power mode " 18286c8d8eccSSepherosa Ziehau "-- setting to D0\n", pci_get_powerstate(dev)); 18296c8d8eccSSepherosa Ziehau 18306c8d8eccSSepherosa Ziehau pci_set_powerstate(dev, PCI_POWERSTATE_D0); 18316c8d8eccSSepherosa Ziehau 18326c8d8eccSSepherosa Ziehau pci_write_config(dev, PCIR_INTLINE, irq, 4); 18336c8d8eccSSepherosa Ziehau pci_write_config(dev, BGE_PCI_BAR0, mem, 4); 18346c8d8eccSSepherosa Ziehau } 18356c8d8eccSSepherosa Ziehau #endif /* !BURN_BRIDGE */ 18366c8d8eccSSepherosa Ziehau 18376c8d8eccSSepherosa Ziehau /* 18386c8d8eccSSepherosa Ziehau * Map control/status registers. 18396c8d8eccSSepherosa Ziehau */ 18406c8d8eccSSepherosa Ziehau pci_enable_busmaster(dev); 18416c8d8eccSSepherosa Ziehau 18426c8d8eccSSepherosa Ziehau rid = BGE_PCI_BAR0; 18436c8d8eccSSepherosa Ziehau sc->bnx_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, 18446c8d8eccSSepherosa Ziehau RF_ACTIVE); 18456c8d8eccSSepherosa Ziehau 18466c8d8eccSSepherosa Ziehau if (sc->bnx_res == NULL) { 18476c8d8eccSSepherosa Ziehau device_printf(dev, "couldn't map memory\n"); 18486c8d8eccSSepherosa Ziehau return ENXIO; 18496c8d8eccSSepherosa Ziehau } 18506c8d8eccSSepherosa Ziehau 18516c8d8eccSSepherosa Ziehau sc->bnx_btag = rman_get_bustag(sc->bnx_res); 18526c8d8eccSSepherosa Ziehau sc->bnx_bhandle = rman_get_bushandle(sc->bnx_res); 18536c8d8eccSSepherosa Ziehau 18546c8d8eccSSepherosa Ziehau /* Save various chip information */ 18556c8d8eccSSepherosa Ziehau sc->bnx_chipid = 18566c8d8eccSSepherosa Ziehau pci_read_config(dev, BGE_PCI_MISC_CTL, 4) >> 18576c8d8eccSSepherosa Ziehau BGE_PCIMISCCTL_ASICREV_SHIFT; 18586c8d8eccSSepherosa Ziehau if (BGE_ASICREV(sc->bnx_chipid) == BGE_ASICREV_USE_PRODID_REG) { 18596c8d8eccSSepherosa Ziehau /* All chips having dedicated ASICREV register have CPMU */ 18606c8d8eccSSepherosa Ziehau sc->bnx_flags |= BNX_FLAG_CPMU; 18616c8d8eccSSepherosa Ziehau 18626c8d8eccSSepherosa Ziehau switch (product) { 18636c8d8eccSSepherosa Ziehau case PCI_PRODUCT_BROADCOM_BCM5717: 1864d79f5d8fSSepherosa Ziehau case PCI_PRODUCT_BROADCOM_BCM5717C: 18656c8d8eccSSepherosa Ziehau case PCI_PRODUCT_BROADCOM_BCM5718: 18666c8d8eccSSepherosa Ziehau case PCI_PRODUCT_BROADCOM_BCM5719: 18676c8d8eccSSepherosa Ziehau case PCI_PRODUCT_BROADCOM_BCM5720_ALT: 1868b96cbbb6SSepherosa Ziehau case PCI_PRODUCT_BROADCOM_BCM5725: 1869b96cbbb6SSepherosa Ziehau case PCI_PRODUCT_BROADCOM_BCM5727: 1870b96cbbb6SSepherosa Ziehau case PCI_PRODUCT_BROADCOM_BCM5762: 18716c8d8eccSSepherosa Ziehau sc->bnx_chipid = pci_read_config(dev, 18726c8d8eccSSepherosa Ziehau BGE_PCI_GEN2_PRODID_ASICREV, 4); 18736c8d8eccSSepherosa Ziehau break; 18746c8d8eccSSepherosa Ziehau 18756c8d8eccSSepherosa Ziehau case PCI_PRODUCT_BROADCOM_BCM57761: 187632ff3c80SSepherosa Ziehau case PCI_PRODUCT_BROADCOM_BCM57762: 18776c8d8eccSSepherosa Ziehau case PCI_PRODUCT_BROADCOM_BCM57765: 187832ff3c80SSepherosa Ziehau case PCI_PRODUCT_BROADCOM_BCM57766: 18796c8d8eccSSepherosa Ziehau case PCI_PRODUCT_BROADCOM_BCM57781: 188032ff3c80SSepherosa Ziehau case PCI_PRODUCT_BROADCOM_BCM57782: 18816c8d8eccSSepherosa Ziehau case PCI_PRODUCT_BROADCOM_BCM57785: 188232ff3c80SSepherosa Ziehau case PCI_PRODUCT_BROADCOM_BCM57786: 18836c8d8eccSSepherosa Ziehau case PCI_PRODUCT_BROADCOM_BCM57791: 18846c8d8eccSSepherosa Ziehau case PCI_PRODUCT_BROADCOM_BCM57795: 18856c8d8eccSSepherosa Ziehau sc->bnx_chipid = pci_read_config(dev, 18866c8d8eccSSepherosa Ziehau BGE_PCI_GEN15_PRODID_ASICREV, 4); 18876c8d8eccSSepherosa Ziehau break; 18886c8d8eccSSepherosa Ziehau 18896c8d8eccSSepherosa Ziehau default: 18906c8d8eccSSepherosa Ziehau sc->bnx_chipid = pci_read_config(dev, 18916c8d8eccSSepherosa Ziehau BGE_PCI_PRODID_ASICREV, 4); 18926c8d8eccSSepherosa Ziehau break; 18936c8d8eccSSepherosa Ziehau } 18946c8d8eccSSepherosa Ziehau } 1895d79f5d8fSSepherosa Ziehau if (sc->bnx_chipid == BGE_CHIPID_BCM5717_C0) 1896d79f5d8fSSepherosa Ziehau sc->bnx_chipid = BGE_CHIPID_BCM5720_A0; 1897d79f5d8fSSepherosa Ziehau 18986c8d8eccSSepherosa Ziehau sc->bnx_asicrev = BGE_ASICREV(sc->bnx_chipid); 18996c8d8eccSSepherosa Ziehau sc->bnx_chiprev = BGE_CHIPREV(sc->bnx_chipid); 19006c8d8eccSSepherosa Ziehau 19016c8d8eccSSepherosa Ziehau switch (sc->bnx_asicrev) { 19026c8d8eccSSepherosa Ziehau case BGE_ASICREV_BCM5717: 19036c8d8eccSSepherosa Ziehau case BGE_ASICREV_BCM5719: 19046c8d8eccSSepherosa Ziehau case BGE_ASICREV_BCM5720: 1905f368d0d9SSepherosa Ziehau sc->bnx_flags |= BNX_FLAG_5717_PLUS | BNX_FLAG_57765_PLUS; 1906f368d0d9SSepherosa Ziehau break; 1907f368d0d9SSepherosa Ziehau 1908b96cbbb6SSepherosa Ziehau case BGE_ASICREV_BCM5762: 1909b96cbbb6SSepherosa Ziehau sc->bnx_flags |= BNX_FLAG_57765_PLUS; 1910b96cbbb6SSepherosa Ziehau break; 1911b96cbbb6SSepherosa Ziehau 19126c8d8eccSSepherosa Ziehau case BGE_ASICREV_BCM57765: 191332ff3c80SSepherosa Ziehau case BGE_ASICREV_BCM57766: 1914f368d0d9SSepherosa Ziehau sc->bnx_flags |= BNX_FLAG_57765_FAMILY | BNX_FLAG_57765_PLUS; 19156c8d8eccSSepherosa Ziehau break; 19166c8d8eccSSepherosa Ziehau } 19176c8d8eccSSepherosa Ziehau 191866deb1c1SSepherosa Ziehau sc->bnx_flags |= BNX_FLAG_TSO; 191966deb1c1SSepherosa Ziehau if (sc->bnx_asicrev == BGE_ASICREV_BCM5719 && 192066deb1c1SSepherosa Ziehau sc->bnx_chipid == BGE_CHIPID_BCM5719_A0) 192166deb1c1SSepherosa Ziehau sc->bnx_flags &= ~BNX_FLAG_TSO; 192266deb1c1SSepherosa Ziehau 1923df9ccc98SSepherosa Ziehau if (sc->bnx_asicrev == BGE_ASICREV_BCM5717 || 1924df9ccc98SSepherosa Ziehau BNX_IS_57765_FAMILY(sc)) { 1925df9ccc98SSepherosa Ziehau /* 1926df9ccc98SSepherosa Ziehau * All BCM57785 and BCM5718 families chips have a bug that 1927df9ccc98SSepherosa Ziehau * under certain situation interrupt will not be enabled 192897ba8fc5SSepherosa Ziehau * even if status tag is written to interrupt mailbox. 1929df9ccc98SSepherosa Ziehau * 1930df9ccc98SSepherosa Ziehau * While BCM5719 and BCM5720 have a hardware workaround 1931df9ccc98SSepherosa Ziehau * which could fix the above bug. 1932df9ccc98SSepherosa Ziehau * See the comment near BGE_PCIDMARWCTL_TAGGED_STATUS_WA in 1933df9ccc98SSepherosa Ziehau * bnx_chipinit(). 1934df9ccc98SSepherosa Ziehau * 1935df9ccc98SSepherosa Ziehau * For the rest of the chips in these two families, we will 1936df9ccc98SSepherosa Ziehau * have to poll the status block at high rate (10ms currently) 1937df9ccc98SSepherosa Ziehau * to check whether the interrupt is hosed or not. 1938*695a8586SSepherosa Ziehau * See bnx_check_intr_*() for details. 1939df9ccc98SSepherosa Ziehau */ 1940df9ccc98SSepherosa Ziehau sc->bnx_flags |= BNX_FLAG_STATUSTAG_BUG; 1941df9ccc98SSepherosa Ziehau } 1942df9ccc98SSepherosa Ziehau 19436c8d8eccSSepherosa Ziehau sc->bnx_pciecap = pci_get_pciecap_ptr(sc->bnx_dev); 19446c8d8eccSSepherosa Ziehau if (sc->bnx_asicrev == BGE_ASICREV_BCM5719 || 19456c8d8eccSSepherosa Ziehau sc->bnx_asicrev == BGE_ASICREV_BCM5720) 19466c8d8eccSSepherosa Ziehau pcie_set_max_readrq(dev, PCIEM_DEVCTL_MAX_READRQ_2048); 19476c8d8eccSSepherosa Ziehau else 19486c8d8eccSSepherosa Ziehau pcie_set_max_readrq(dev, PCIEM_DEVCTL_MAX_READRQ_4096); 19496c8d8eccSSepherosa Ziehau device_printf(dev, "CHIP ID 0x%08x; " 19506c8d8eccSSepherosa Ziehau "ASIC REV 0x%02x; CHIP REV 0x%02x\n", 19516c8d8eccSSepherosa Ziehau sc->bnx_chipid, sc->bnx_asicrev, sc->bnx_chiprev); 19526c8d8eccSSepherosa Ziehau 19536c8d8eccSSepherosa Ziehau /* 19546c8d8eccSSepherosa Ziehau * Set various PHY quirk flags. 19556c8d8eccSSepherosa Ziehau */ 19566c8d8eccSSepherosa Ziehau 19576c8d8eccSSepherosa Ziehau capmask = MII_CAPMASK_DEFAULT; 195846283a40SSepherosa Ziehau if (product == PCI_PRODUCT_BROADCOM_BCM57791 || 195946283a40SSepherosa Ziehau product == PCI_PRODUCT_BROADCOM_BCM57795) { 19606c8d8eccSSepherosa Ziehau /* 10/100 only */ 19616c8d8eccSSepherosa Ziehau capmask &= ~BMSR_EXTSTAT; 19626c8d8eccSSepherosa Ziehau } 19636c8d8eccSSepherosa Ziehau 19646c8d8eccSSepherosa Ziehau mii_priv |= BRGPHY_FLAG_WIRESPEED; 1965b96cbbb6SSepherosa Ziehau if (sc->bnx_chipid == BGE_CHIPID_BCM5762_A0) 1966b96cbbb6SSepherosa Ziehau mii_priv |= BRGPHY_FLAG_5762_A0; 19676c8d8eccSSepherosa Ziehau 19686c8d8eccSSepherosa Ziehau /* Initialize if_name earlier, so if_printf could be used */ 19696c8d8eccSSepherosa Ziehau ifp = &sc->arpcom.ac_if; 19706c8d8eccSSepherosa Ziehau if_initname(ifp, device_get_name(dev), device_get_unit(dev)); 19716c8d8eccSSepherosa Ziehau 19726c8d8eccSSepherosa Ziehau /* Try to reset the chip. */ 19736c8d8eccSSepherosa Ziehau bnx_reset(sc); 19746c8d8eccSSepherosa Ziehau 19756c8d8eccSSepherosa Ziehau if (bnx_chipinit(sc)) { 19766c8d8eccSSepherosa Ziehau device_printf(dev, "chip initialization failed\n"); 19776c8d8eccSSepherosa Ziehau error = ENXIO; 19786c8d8eccSSepherosa Ziehau goto fail; 19796c8d8eccSSepherosa Ziehau } 19806c8d8eccSSepherosa Ziehau 19816c8d8eccSSepherosa Ziehau /* 19826c8d8eccSSepherosa Ziehau * Get station address 19836c8d8eccSSepherosa Ziehau */ 19846c8d8eccSSepherosa Ziehau error = bnx_get_eaddr(sc, ether_addr); 19856c8d8eccSSepherosa Ziehau if (error) { 19866c8d8eccSSepherosa Ziehau device_printf(dev, "failed to read station address\n"); 19876c8d8eccSSepherosa Ziehau goto fail; 19886c8d8eccSSepherosa Ziehau } 19896c8d8eccSSepherosa Ziehau 1990*695a8586SSepherosa Ziehau /* Setup RX/TX and interrupt count */ 1991*695a8586SSepherosa Ziehau bnx_setup_ring_cnt(sc); 199233a04907SSepherosa Ziehau 19934fa38985SSepherosa Ziehau if ((sc->bnx_rx_retcnt == 1 && sc->bnx_tx_ringcnt == 1) || 19944fa38985SSepherosa Ziehau (sc->bnx_rx_retcnt > 1 && sc->bnx_tx_ringcnt > 1)) { 19954fa38985SSepherosa Ziehau /* 19964fa38985SSepherosa Ziehau * The RX ring and the corresponding TX ring processing 19974fa38985SSepherosa Ziehau * should be on the same CPU, since they share the same 19984fa38985SSepherosa Ziehau * status block. 19994fa38985SSepherosa Ziehau */ 20004fa38985SSepherosa Ziehau sc->bnx_flags |= BNX_FLAG_RXTX_BUNDLE; 20014fa38985SSepherosa Ziehau if (bootverbose) 20024fa38985SSepherosa Ziehau device_printf(dev, "RX/TX bundle\n"); 2003*695a8586SSepherosa Ziehau if (sc->bnx_tx_ringcnt > 1) { 2004*695a8586SSepherosa Ziehau /* 2005*695a8586SSepherosa Ziehau * Multiple TX rings do not share status block 2006*695a8586SSepherosa Ziehau * with link status, so link status will have 2007*695a8586SSepherosa Ziehau * to save its own status_tag. 2008*695a8586SSepherosa Ziehau */ 2009*695a8586SSepherosa Ziehau sc->bnx_flags |= BNX_FLAG_STATUS_HASTAG; 2010*695a8586SSepherosa Ziehau if (bootverbose) 2011*695a8586SSepherosa Ziehau device_printf(dev, "status needs tag\n"); 2012*695a8586SSepherosa Ziehau } 20134fa38985SSepherosa Ziehau } else { 20144fa38985SSepherosa Ziehau KKASSERT(sc->bnx_rx_retcnt > 1 && sc->bnx_tx_ringcnt == 1); 2015*695a8586SSepherosa Ziehau if (bootverbose) 2016*695a8586SSepherosa Ziehau device_printf(dev, "RX/TX not bundled\n"); 20174fa38985SSepherosa Ziehau } 20184fa38985SSepherosa Ziehau 2019beedf5beSSepherosa Ziehau error = bnx_dma_alloc(dev); 20206c8d8eccSSepherosa Ziehau if (error) 20216c8d8eccSSepherosa Ziehau goto fail; 20226c8d8eccSSepherosa Ziehau 20234fa38985SSepherosa Ziehau #ifdef IFPOLL_ENABLE 20244fa38985SSepherosa Ziehau if (sc->bnx_flags & BNX_FLAG_RXTX_BUNDLE) { 20254fa38985SSepherosa Ziehau /* 20264fa38985SSepherosa Ziehau * NPOLLING RX/TX CPU offset 20274fa38985SSepherosa Ziehau */ 20284fa38985SSepherosa Ziehau if (sc->bnx_rx_retcnt == ncpus2) { 20294fa38985SSepherosa Ziehau offset = 0; 20304fa38985SSepherosa Ziehau } else { 20314fa38985SSepherosa Ziehau offset_def = 20324fa38985SSepherosa Ziehau (sc->bnx_rx_retcnt * device_get_unit(dev)) % ncpus2; 20334fa38985SSepherosa Ziehau offset = device_getenv_int(dev, "npoll.offset", 20344fa38985SSepherosa Ziehau offset_def); 20354fa38985SSepherosa Ziehau if (offset >= ncpus2 || 20364fa38985SSepherosa Ziehau offset % sc->bnx_rx_retcnt != 0) { 20374fa38985SSepherosa Ziehau device_printf(dev, "invalid npoll.offset %d, " 20384fa38985SSepherosa Ziehau "use %d\n", offset, offset_def); 20394fa38985SSepherosa Ziehau offset = offset_def; 20404fa38985SSepherosa Ziehau } 20414fa38985SSepherosa Ziehau } 20424fa38985SSepherosa Ziehau sc->bnx_npoll_rxoff = offset; 20434fa38985SSepherosa Ziehau sc->bnx_npoll_txoff = offset; 20444fa38985SSepherosa Ziehau } else { 20454fa38985SSepherosa Ziehau /* 20464fa38985SSepherosa Ziehau * NPOLLING RX CPU offset 20474fa38985SSepherosa Ziehau */ 20484fa38985SSepherosa Ziehau if (sc->bnx_rx_retcnt == ncpus2) { 20494fa38985SSepherosa Ziehau offset = 0; 20504fa38985SSepherosa Ziehau } else { 20514fa38985SSepherosa Ziehau offset_def = 20524fa38985SSepherosa Ziehau (sc->bnx_rx_retcnt * device_get_unit(dev)) % ncpus2; 20534fa38985SSepherosa Ziehau offset = device_getenv_int(dev, "npoll.rxoff", 20544fa38985SSepherosa Ziehau offset_def); 20554fa38985SSepherosa Ziehau if (offset >= ncpus2 || 20564fa38985SSepherosa Ziehau offset % sc->bnx_rx_retcnt != 0) { 20574fa38985SSepherosa Ziehau device_printf(dev, "invalid npoll.rxoff %d, " 20584fa38985SSepherosa Ziehau "use %d\n", offset, offset_def); 20594fa38985SSepherosa Ziehau offset = offset_def; 20604fa38985SSepherosa Ziehau } 20614fa38985SSepherosa Ziehau } 20624fa38985SSepherosa Ziehau sc->bnx_npoll_rxoff = offset; 20634fa38985SSepherosa Ziehau 20644fa38985SSepherosa Ziehau /* 20654fa38985SSepherosa Ziehau * NPOLLING TX CPU offset 20664fa38985SSepherosa Ziehau */ 20674fa38985SSepherosa Ziehau offset_def = device_get_unit(dev) % ncpus2; 20684fa38985SSepherosa Ziehau offset = device_getenv_int(dev, "npoll.txoff", offset_def); 20694fa38985SSepherosa Ziehau if (offset >= ncpus2) { 20704fa38985SSepherosa Ziehau device_printf(dev, "invalid npoll.txoff %d, use %d\n", 20714fa38985SSepherosa Ziehau offset, offset_def); 20724fa38985SSepherosa Ziehau offset = offset_def; 20734fa38985SSepherosa Ziehau } 20744fa38985SSepherosa Ziehau sc->bnx_npoll_txoff = offset; 20754fa38985SSepherosa Ziehau } 20764fa38985SSepherosa Ziehau #endif /* IFPOLL_ENABLE */ 20774fa38985SSepherosa Ziehau 207816b32c4cSSepherosa Ziehau /* 207916b32c4cSSepherosa Ziehau * Allocate interrupt 208016b32c4cSSepherosa Ziehau */ 20810c7da01dSSepherosa Ziehau error = bnx_alloc_intr(sc); 20820c7da01dSSepherosa Ziehau if (error) 208316b32c4cSSepherosa Ziehau goto fail; 208416b32c4cSSepherosa Ziehau 2085329f9016SSepherosa Ziehau /* Setup serializers */ 2086329f9016SSepherosa Ziehau bnx_setup_serialize(sc); 2087329f9016SSepherosa Ziehau 20886c8d8eccSSepherosa Ziehau /* Set default tuneable values. */ 20896c8d8eccSSepherosa Ziehau sc->bnx_rx_coal_ticks = BNX_RX_COAL_TICKS_DEF; 20906c8d8eccSSepherosa Ziehau sc->bnx_tx_coal_ticks = BNX_TX_COAL_TICKS_DEF; 20916c8d8eccSSepherosa Ziehau sc->bnx_rx_coal_bds = BNX_RX_COAL_BDS_DEF; 20926c8d8eccSSepherosa Ziehau sc->bnx_tx_coal_bds = BNX_TX_COAL_BDS_DEF; 2093306e5498SSepherosa Ziehau sc->bnx_rx_coal_bds_int = BNX_RX_COAL_BDS_INT_DEF; 2094306e5498SSepherosa Ziehau sc->bnx_tx_coal_bds_int = BNX_TX_COAL_BDS_INT_DEF; 20956c8d8eccSSepherosa Ziehau 20966c8d8eccSSepherosa Ziehau /* Set up ifnet structure */ 20976c8d8eccSSepherosa Ziehau ifp->if_softc = sc; 20986c8d8eccSSepherosa Ziehau ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; 20996c8d8eccSSepherosa Ziehau ifp->if_ioctl = bnx_ioctl; 21006c8d8eccSSepherosa Ziehau ifp->if_start = bnx_start; 210139a8d43aSSepherosa Ziehau #ifdef IFPOLL_ENABLE 210239a8d43aSSepherosa Ziehau ifp->if_npoll = bnx_npoll; 21036c8d8eccSSepherosa Ziehau #endif 21046c8d8eccSSepherosa Ziehau ifp->if_init = bnx_init; 2105329f9016SSepherosa Ziehau ifp->if_serialize = bnx_serialize; 2106329f9016SSepherosa Ziehau ifp->if_deserialize = bnx_deserialize; 2107329f9016SSepherosa Ziehau ifp->if_tryserialize = bnx_tryserialize; 2108329f9016SSepherosa Ziehau #ifdef INVARIANTS 2109329f9016SSepherosa Ziehau ifp->if_serialize_assert = bnx_serialize_assert; 2110329f9016SSepherosa Ziehau #endif 21116c8d8eccSSepherosa Ziehau ifp->if_mtu = ETHERMTU; 21126c8d8eccSSepherosa Ziehau ifp->if_capabilities = IFCAP_VLAN_HWTAGGING | IFCAP_VLAN_MTU; 21136c8d8eccSSepherosa Ziehau 21146c8d8eccSSepherosa Ziehau ifp->if_capabilities |= IFCAP_HWCSUM; 21156c8d8eccSSepherosa Ziehau ifp->if_hwassist = BNX_CSUM_FEATURES; 211666deb1c1SSepherosa Ziehau if (sc->bnx_flags & BNX_FLAG_TSO) { 211766deb1c1SSepherosa Ziehau ifp->if_capabilities |= IFCAP_TSO; 211866deb1c1SSepherosa Ziehau ifp->if_hwassist |= CSUM_TSO; 211966deb1c1SSepherosa Ziehau } 21206c8d8eccSSepherosa Ziehau ifp->if_capenable = ifp->if_capabilities; 21216c8d8eccSSepherosa Ziehau 2122329f9016SSepherosa Ziehau ifq_set_maxlen(&ifp->if_snd, BGE_TX_RING_CNT - 1); 2123329f9016SSepherosa Ziehau ifq_set_ready(&ifp->if_snd); 2124329f9016SSepherosa Ziehau ifq_set_subq_cnt(&ifp->if_snd, sc->bnx_tx_ringcnt); 2125329f9016SSepherosa Ziehau 2126*695a8586SSepherosa Ziehau if (sc->bnx_tx_ringcnt > 1) { 2127*695a8586SSepherosa Ziehau ifp->if_mapsubq = ifq_mapsubq_mask; 2128*695a8586SSepherosa Ziehau ifq_set_subq_mask(&ifp->if_snd, sc->bnx_tx_ringcnt - 1); 2129*695a8586SSepherosa Ziehau } 2130*695a8586SSepherosa Ziehau 21316c8d8eccSSepherosa Ziehau /* 21326c8d8eccSSepherosa Ziehau * Figure out what sort of media we have by checking the 21336c8d8eccSSepherosa Ziehau * hardware config word in the first 32k of NIC internal memory, 21346c8d8eccSSepherosa Ziehau * or fall back to examining the EEPROM if necessary. 21356c8d8eccSSepherosa Ziehau * Note: on some BCM5700 cards, this value appears to be unset. 21366c8d8eccSSepherosa Ziehau * If that's the case, we have to rely on identifying the NIC 21376c8d8eccSSepherosa Ziehau * by its PCI subsystem ID, as we do below for the SysKonnect 21386c8d8eccSSepherosa Ziehau * SK-9D41. 21396c8d8eccSSepherosa Ziehau */ 21406c8d8eccSSepherosa Ziehau if (bnx_readmem_ind(sc, BGE_SOFTWARE_GENCOMM_SIG) == BGE_MAGIC_NUMBER) { 21416c8d8eccSSepherosa Ziehau hwcfg = bnx_readmem_ind(sc, BGE_SOFTWARE_GENCOMM_NICCFG); 21426c8d8eccSSepherosa Ziehau } else { 21436c8d8eccSSepherosa Ziehau if (bnx_read_eeprom(sc, (caddr_t)&hwcfg, BGE_EE_HWCFG_OFFSET, 21446c8d8eccSSepherosa Ziehau sizeof(hwcfg))) { 21456c8d8eccSSepherosa Ziehau device_printf(dev, "failed to read EEPROM\n"); 21466c8d8eccSSepherosa Ziehau error = ENXIO; 21476c8d8eccSSepherosa Ziehau goto fail; 21486c8d8eccSSepherosa Ziehau } 21496c8d8eccSSepherosa Ziehau hwcfg = ntohl(hwcfg); 21506c8d8eccSSepherosa Ziehau } 21516c8d8eccSSepherosa Ziehau 21526c8d8eccSSepherosa Ziehau /* The SysKonnect SK-9D41 is a 1000baseSX card. */ 21536c8d8eccSSepherosa Ziehau if (pci_get_subvendor(dev) == PCI_PRODUCT_SCHNEIDERKOCH_SK_9D41 || 21546c8d8eccSSepherosa Ziehau (hwcfg & BGE_HWCFG_MEDIA) == BGE_MEDIA_FIBER) 21556c8d8eccSSepherosa Ziehau sc->bnx_flags |= BNX_FLAG_TBI; 21566c8d8eccSSepherosa Ziehau 21576c8d8eccSSepherosa Ziehau /* Setup MI MODE */ 21586c8d8eccSSepherosa Ziehau if (sc->bnx_flags & BNX_FLAG_CPMU) 21596c8d8eccSSepherosa Ziehau sc->bnx_mi_mode = BGE_MIMODE_500KHZ_CONST; 21606c8d8eccSSepherosa Ziehau else 21616c8d8eccSSepherosa Ziehau sc->bnx_mi_mode = BGE_MIMODE_BASE; 21626c8d8eccSSepherosa Ziehau 21636c8d8eccSSepherosa Ziehau /* Setup link status update stuffs */ 21646c8d8eccSSepherosa Ziehau if (sc->bnx_flags & BNX_FLAG_TBI) { 21656c8d8eccSSepherosa Ziehau sc->bnx_link_upd = bnx_tbi_link_upd; 21666c8d8eccSSepherosa Ziehau sc->bnx_link_chg = BGE_MACSTAT_LINK_CHANGED; 21676c8d8eccSSepherosa Ziehau } else if (sc->bnx_mi_mode & BGE_MIMODE_AUTOPOLL) { 21686c8d8eccSSepherosa Ziehau sc->bnx_link_upd = bnx_autopoll_link_upd; 21696c8d8eccSSepherosa Ziehau sc->bnx_link_chg = BGE_MACSTAT_LINK_CHANGED; 21706c8d8eccSSepherosa Ziehau } else { 21716c8d8eccSSepherosa Ziehau sc->bnx_link_upd = bnx_copper_link_upd; 21726c8d8eccSSepherosa Ziehau sc->bnx_link_chg = BGE_MACSTAT_LINK_CHANGED; 21736c8d8eccSSepherosa Ziehau } 21746c8d8eccSSepherosa Ziehau 21756c8d8eccSSepherosa Ziehau /* Set default PHY address */ 21766c8d8eccSSepherosa Ziehau sc->bnx_phyno = 1; 21776c8d8eccSSepherosa Ziehau 21786c8d8eccSSepherosa Ziehau /* 21796c8d8eccSSepherosa Ziehau * PHY address mapping for various devices. 21806c8d8eccSSepherosa Ziehau * 21816c8d8eccSSepherosa Ziehau * | F0 Cu | F0 Sr | F1 Cu | F1 Sr | 21826c8d8eccSSepherosa Ziehau * ---------+-------+-------+-------+-------+ 21836c8d8eccSSepherosa Ziehau * BCM57XX | 1 | X | X | X | 21846c8d8eccSSepherosa Ziehau * BCM5704 | 1 | X | 1 | X | 21856c8d8eccSSepherosa Ziehau * BCM5717 | 1 | 8 | 2 | 9 | 21866c8d8eccSSepherosa Ziehau * BCM5719 | 1 | 8 | 2 | 9 | 21876c8d8eccSSepherosa Ziehau * BCM5720 | 1 | 8 | 2 | 9 | 21886c8d8eccSSepherosa Ziehau * 21896c8d8eccSSepherosa Ziehau * Other addresses may respond but they are not 21906c8d8eccSSepherosa Ziehau * IEEE compliant PHYs and should be ignored. 21916c8d8eccSSepherosa Ziehau */ 219280969639SSepherosa Ziehau if (BNX_IS_5717_PLUS(sc)) { 21936c8d8eccSSepherosa Ziehau int f; 21946c8d8eccSSepherosa Ziehau 21956c8d8eccSSepherosa Ziehau f = pci_get_function(dev); 21966c8d8eccSSepherosa Ziehau if (sc->bnx_chipid == BGE_CHIPID_BCM5717_A0) { 21976c8d8eccSSepherosa Ziehau if (CSR_READ_4(sc, BGE_SGDIG_STS) & 21986c8d8eccSSepherosa Ziehau BGE_SGDIGSTS_IS_SERDES) 21996c8d8eccSSepherosa Ziehau sc->bnx_phyno = f + 8; 22006c8d8eccSSepherosa Ziehau else 22016c8d8eccSSepherosa Ziehau sc->bnx_phyno = f + 1; 22026c8d8eccSSepherosa Ziehau } else { 22036c8d8eccSSepherosa Ziehau if (CSR_READ_4(sc, BGE_CPMU_PHY_STRAP) & 22046c8d8eccSSepherosa Ziehau BGE_CPMU_PHY_STRAP_IS_SERDES) 22056c8d8eccSSepherosa Ziehau sc->bnx_phyno = f + 8; 22066c8d8eccSSepherosa Ziehau else 22076c8d8eccSSepherosa Ziehau sc->bnx_phyno = f + 1; 22086c8d8eccSSepherosa Ziehau } 22096c8d8eccSSepherosa Ziehau } 22106c8d8eccSSepherosa Ziehau 22116c8d8eccSSepherosa Ziehau if (sc->bnx_flags & BNX_FLAG_TBI) { 22126c8d8eccSSepherosa Ziehau ifmedia_init(&sc->bnx_ifmedia, IFM_IMASK, 22136c8d8eccSSepherosa Ziehau bnx_ifmedia_upd, bnx_ifmedia_sts); 22146c8d8eccSSepherosa Ziehau ifmedia_add(&sc->bnx_ifmedia, IFM_ETHER|IFM_1000_SX, 0, NULL); 22156c8d8eccSSepherosa Ziehau ifmedia_add(&sc->bnx_ifmedia, 22166c8d8eccSSepherosa Ziehau IFM_ETHER|IFM_1000_SX|IFM_FDX, 0, NULL); 22176c8d8eccSSepherosa Ziehau ifmedia_add(&sc->bnx_ifmedia, IFM_ETHER|IFM_AUTO, 0, NULL); 22186c8d8eccSSepherosa Ziehau ifmedia_set(&sc->bnx_ifmedia, IFM_ETHER|IFM_AUTO); 22196c8d8eccSSepherosa Ziehau sc->bnx_ifmedia.ifm_media = sc->bnx_ifmedia.ifm_cur->ifm_media; 22206c8d8eccSSepherosa Ziehau } else { 22216c8d8eccSSepherosa Ziehau struct mii_probe_args mii_args; 22226c8d8eccSSepherosa Ziehau 22236c8d8eccSSepherosa Ziehau mii_probe_args_init(&mii_args, bnx_ifmedia_upd, bnx_ifmedia_sts); 22246c8d8eccSSepherosa Ziehau mii_args.mii_probemask = 1 << sc->bnx_phyno; 22256c8d8eccSSepherosa Ziehau mii_args.mii_capmask = capmask; 22266c8d8eccSSepherosa Ziehau mii_args.mii_privtag = MII_PRIVTAG_BRGPHY; 22276c8d8eccSSepherosa Ziehau mii_args.mii_priv = mii_priv; 22286c8d8eccSSepherosa Ziehau 22296c8d8eccSSepherosa Ziehau error = mii_probe(dev, &sc->bnx_miibus, &mii_args); 22306c8d8eccSSepherosa Ziehau if (error) { 22316c8d8eccSSepherosa Ziehau device_printf(dev, "MII without any PHY!\n"); 22326c8d8eccSSepherosa Ziehau goto fail; 22336c8d8eccSSepherosa Ziehau } 22346c8d8eccSSepherosa Ziehau } 22356c8d8eccSSepherosa Ziehau 22366c8d8eccSSepherosa Ziehau /* 22376c8d8eccSSepherosa Ziehau * Create sysctl nodes. 22386c8d8eccSSepherosa Ziehau */ 22396c8d8eccSSepherosa Ziehau sysctl_ctx_init(&sc->bnx_sysctl_ctx); 22406c8d8eccSSepherosa Ziehau sc->bnx_sysctl_tree = SYSCTL_ADD_NODE(&sc->bnx_sysctl_ctx, 22416c8d8eccSSepherosa Ziehau SYSCTL_STATIC_CHILDREN(_hw), 22426c8d8eccSSepherosa Ziehau OID_AUTO, 22436c8d8eccSSepherosa Ziehau device_get_nameunit(dev), 22446c8d8eccSSepherosa Ziehau CTLFLAG_RD, 0, ""); 22456c8d8eccSSepherosa Ziehau if (sc->bnx_sysctl_tree == NULL) { 22466c8d8eccSSepherosa Ziehau device_printf(dev, "can't add sysctl node\n"); 22476c8d8eccSSepherosa Ziehau error = ENXIO; 22486c8d8eccSSepherosa Ziehau goto fail; 22496c8d8eccSSepherosa Ziehau } 22506c8d8eccSSepherosa Ziehau 225193146551SSepherosa Ziehau SYSCTL_ADD_INT(&sc->bnx_sysctl_ctx, 225293146551SSepherosa Ziehau SYSCTL_CHILDREN(sc->bnx_sysctl_tree), OID_AUTO, 225393146551SSepherosa Ziehau "rx_rings", CTLFLAG_RD, &sc->bnx_rx_retcnt, 0, "# of RX rings"); 225493146551SSepherosa Ziehau SYSCTL_ADD_INT(&sc->bnx_sysctl_ctx, 225593146551SSepherosa Ziehau SYSCTL_CHILDREN(sc->bnx_sysctl_tree), OID_AUTO, 225693146551SSepherosa Ziehau "tx_rings", CTLFLAG_RD, &sc->bnx_tx_ringcnt, 0, "# of TX rings"); 225793146551SSepherosa Ziehau 22586c8d8eccSSepherosa Ziehau SYSCTL_ADD_PROC(&sc->bnx_sysctl_ctx, 22596c8d8eccSSepherosa Ziehau SYSCTL_CHILDREN(sc->bnx_sysctl_tree), 22606c8d8eccSSepherosa Ziehau OID_AUTO, "rx_coal_ticks", 22616c8d8eccSSepherosa Ziehau CTLTYPE_INT | CTLFLAG_RW, 22626c8d8eccSSepherosa Ziehau sc, 0, bnx_sysctl_rx_coal_ticks, "I", 22636c8d8eccSSepherosa Ziehau "Receive coalescing ticks (usec)."); 22646c8d8eccSSepherosa Ziehau SYSCTL_ADD_PROC(&sc->bnx_sysctl_ctx, 22656c8d8eccSSepherosa Ziehau SYSCTL_CHILDREN(sc->bnx_sysctl_tree), 22666c8d8eccSSepherosa Ziehau OID_AUTO, "tx_coal_ticks", 22676c8d8eccSSepherosa Ziehau CTLTYPE_INT | CTLFLAG_RW, 22686c8d8eccSSepherosa Ziehau sc, 0, bnx_sysctl_tx_coal_ticks, "I", 22696c8d8eccSSepherosa Ziehau "Transmit coalescing ticks (usec)."); 22706c8d8eccSSepherosa Ziehau SYSCTL_ADD_PROC(&sc->bnx_sysctl_ctx, 22716c8d8eccSSepherosa Ziehau SYSCTL_CHILDREN(sc->bnx_sysctl_tree), 22726c8d8eccSSepherosa Ziehau OID_AUTO, "rx_coal_bds", 22736c8d8eccSSepherosa Ziehau CTLTYPE_INT | CTLFLAG_RW, 22746c8d8eccSSepherosa Ziehau sc, 0, bnx_sysctl_rx_coal_bds, "I", 22756c8d8eccSSepherosa Ziehau "Receive max coalesced BD count."); 22766c8d8eccSSepherosa Ziehau SYSCTL_ADD_PROC(&sc->bnx_sysctl_ctx, 22776c8d8eccSSepherosa Ziehau SYSCTL_CHILDREN(sc->bnx_sysctl_tree), 22786c8d8eccSSepherosa Ziehau OID_AUTO, "tx_coal_bds", 22796c8d8eccSSepherosa Ziehau CTLTYPE_INT | CTLFLAG_RW, 22806c8d8eccSSepherosa Ziehau sc, 0, bnx_sysctl_tx_coal_bds, "I", 22816c8d8eccSSepherosa Ziehau "Transmit max coalesced BD count."); 22826c8d8eccSSepherosa Ziehau /* 22836c8d8eccSSepherosa Ziehau * A common design characteristic for many Broadcom 22846c8d8eccSSepherosa Ziehau * client controllers is that they only support a 22856c8d8eccSSepherosa Ziehau * single outstanding DMA read operation on the PCIe 22866c8d8eccSSepherosa Ziehau * bus. This means that it will take twice as long to 22876c8d8eccSSepherosa Ziehau * fetch a TX frame that is split into header and 22886c8d8eccSSepherosa Ziehau * payload buffers as it does to fetch a single, 22896c8d8eccSSepherosa Ziehau * contiguous TX frame (2 reads vs. 1 read). For these 22906c8d8eccSSepherosa Ziehau * controllers, coalescing buffers to reduce the number 22916c8d8eccSSepherosa Ziehau * of memory reads is effective way to get maximum 22926c8d8eccSSepherosa Ziehau * performance(about 940Mbps). Without collapsing TX 22936c8d8eccSSepherosa Ziehau * buffers the maximum TCP bulk transfer performance 22946c8d8eccSSepherosa Ziehau * is about 850Mbps. However forcing coalescing mbufs 22956c8d8eccSSepherosa Ziehau * consumes a lot of CPU cycles, so leave it off by 22966c8d8eccSSepherosa Ziehau * default. 22976c8d8eccSSepherosa Ziehau */ 2298aad4de2bSSepherosa Ziehau SYSCTL_ADD_PROC(&sc->bnx_sysctl_ctx, 22996c8d8eccSSepherosa Ziehau SYSCTL_CHILDREN(sc->bnx_sysctl_tree), OID_AUTO, 2300aad4de2bSSepherosa Ziehau "force_defrag", CTLTYPE_INT | CTLFLAG_RW, 2301aad4de2bSSepherosa Ziehau sc, 0, bnx_sysctl_force_defrag, "I", 23026c8d8eccSSepherosa Ziehau "Force defragment on TX path"); 23036c8d8eccSSepherosa Ziehau 2304472c99c8SSepherosa Ziehau SYSCTL_ADD_PROC(&sc->bnx_sysctl_ctx, 2305c9b7f592SSepherosa Ziehau SYSCTL_CHILDREN(sc->bnx_sysctl_tree), OID_AUTO, 2306472c99c8SSepherosa Ziehau "tx_wreg", CTLTYPE_INT | CTLFLAG_RW, 2307472c99c8SSepherosa Ziehau sc, 0, bnx_sysctl_tx_wreg, "I", 2308c9b7f592SSepherosa Ziehau "# of segments before writing to hardware register"); 2309c9b7f592SSepherosa Ziehau 23106c8d8eccSSepherosa Ziehau SYSCTL_ADD_PROC(&sc->bnx_sysctl_ctx, 23116c8d8eccSSepherosa Ziehau SYSCTL_CHILDREN(sc->bnx_sysctl_tree), OID_AUTO, 2312841cdf08SSepherosa Ziehau "std_refill", CTLTYPE_INT | CTLFLAG_RW, 2313841cdf08SSepherosa Ziehau sc, 0, bnx_sysctl_std_refill, "I", 2314841cdf08SSepherosa Ziehau "# of packets received before scheduling standard refilling"); 2315841cdf08SSepherosa Ziehau 2316841cdf08SSepherosa Ziehau SYSCTL_ADD_PROC(&sc->bnx_sysctl_ctx, 2317841cdf08SSepherosa Ziehau SYSCTL_CHILDREN(sc->bnx_sysctl_tree), OID_AUTO, 23186c8d8eccSSepherosa Ziehau "rx_coal_bds_int", CTLTYPE_INT | CTLFLAG_RW, 23196c8d8eccSSepherosa Ziehau sc, 0, bnx_sysctl_rx_coal_bds_int, "I", 23206c8d8eccSSepherosa Ziehau "Receive max coalesced BD count during interrupt."); 23216c8d8eccSSepherosa Ziehau SYSCTL_ADD_PROC(&sc->bnx_sysctl_ctx, 23226c8d8eccSSepherosa Ziehau SYSCTL_CHILDREN(sc->bnx_sysctl_tree), OID_AUTO, 23236c8d8eccSSepherosa Ziehau "tx_coal_bds_int", CTLTYPE_INT | CTLFLAG_RW, 23246c8d8eccSSepherosa Ziehau sc, 0, bnx_sysctl_tx_coal_bds_int, "I", 23256c8d8eccSSepherosa Ziehau "Transmit max coalesced BD count during interrupt."); 23266c8d8eccSSepherosa Ziehau 23274fa38985SSepherosa Ziehau #ifdef IFPOLL_ENABLE 23284fa38985SSepherosa Ziehau if (sc->bnx_flags & BNX_FLAG_RXTX_BUNDLE) { 23294fa38985SSepherosa Ziehau SYSCTL_ADD_PROC(&sc->bnx_sysctl_ctx, 23304fa38985SSepherosa Ziehau SYSCTL_CHILDREN(sc->bnx_sysctl_tree), OID_AUTO, 23314fa38985SSepherosa Ziehau "npoll_offset", CTLTYPE_INT | CTLFLAG_RW, 23324fa38985SSepherosa Ziehau sc, 0, bnx_sysctl_npoll_offset, "I", 23334fa38985SSepherosa Ziehau "NPOLLING cpu offset"); 23344fa38985SSepherosa Ziehau } else { 23354fa38985SSepherosa Ziehau SYSCTL_ADD_PROC(&sc->bnx_sysctl_ctx, 23364fa38985SSepherosa Ziehau SYSCTL_CHILDREN(sc->bnx_sysctl_tree), OID_AUTO, 23374fa38985SSepherosa Ziehau "npoll_rxoff", CTLTYPE_INT | CTLFLAG_RW, 23384fa38985SSepherosa Ziehau sc, 0, bnx_sysctl_npoll_rxoff, "I", 23394fa38985SSepherosa Ziehau "NPOLLING RX cpu offset"); 23404fa38985SSepherosa Ziehau SYSCTL_ADD_PROC(&sc->bnx_sysctl_ctx, 23414fa38985SSepherosa Ziehau SYSCTL_CHILDREN(sc->bnx_sysctl_tree), OID_AUTO, 23424fa38985SSepherosa Ziehau "npoll_txoff", CTLTYPE_INT | CTLFLAG_RW, 23434fa38985SSepherosa Ziehau sc, 0, bnx_sysctl_npoll_txoff, "I", 23444fa38985SSepherosa Ziehau "NPOLLING TX cpu offset"); 23454fa38985SSepherosa Ziehau } 23464fa38985SSepherosa Ziehau #endif 23474fa38985SSepherosa Ziehau 2348*695a8586SSepherosa Ziehau #ifdef BNX_RSS_DEBUG 2349*695a8586SSepherosa Ziehau SYSCTL_ADD_INT(&sc->bnx_sysctl_ctx, 2350*695a8586SSepherosa Ziehau SYSCTL_CHILDREN(sc->bnx_sysctl_tree), OID_AUTO, 2351*695a8586SSepherosa Ziehau "std_refill_mask", CTLFLAG_RD, 2352*695a8586SSepherosa Ziehau &sc->bnx_rx_std_ring.bnx_rx_std_refill, 0, ""); 2353*695a8586SSepherosa Ziehau SYSCTL_ADD_INT(&sc->bnx_sysctl_ctx, 2354*695a8586SSepherosa Ziehau SYSCTL_CHILDREN(sc->bnx_sysctl_tree), OID_AUTO, 2355*695a8586SSepherosa Ziehau "rss_debug", CTLFLAG_RW, &sc->bnx_rss_debug, 0, ""); 2356*695a8586SSepherosa Ziehau for (i = 0; i < sc->bnx_rx_retcnt; ++i) { 2357*695a8586SSepherosa Ziehau ksnprintf(desc, sizeof(desc), "rx_pkt%d", i); 2358*695a8586SSepherosa Ziehau SYSCTL_ADD_ULONG(&sc->bnx_sysctl_ctx, 2359*695a8586SSepherosa Ziehau SYSCTL_CHILDREN(sc->bnx_sysctl_tree), OID_AUTO, 2360*695a8586SSepherosa Ziehau desc, CTLFLAG_RW, &sc->bnx_rx_ret_ring[i].bnx_rx_pkt, ""); 2361*695a8586SSepherosa Ziehau } 2362*695a8586SSepherosa Ziehau #endif 2363*695a8586SSepherosa Ziehau #ifdef BNX_TSS_DEBUG 2364*695a8586SSepherosa Ziehau for (i = 0; i < sc->bnx_tx_ringcnt; ++i) { 2365*695a8586SSepherosa Ziehau ksnprintf(desc, sizeof(desc), "tx_pkt%d", i); 2366*695a8586SSepherosa Ziehau SYSCTL_ADD_ULONG(&sc->bnx_sysctl_ctx, 2367*695a8586SSepherosa Ziehau SYSCTL_CHILDREN(sc->bnx_sysctl_tree), OID_AUTO, 2368*695a8586SSepherosa Ziehau desc, CTLFLAG_RW, &sc->bnx_tx_ring[i].bnx_tx_pkt, ""); 2369*695a8586SSepherosa Ziehau } 2370*695a8586SSepherosa Ziehau #endif 2371*695a8586SSepherosa Ziehau 2372*695a8586SSepherosa Ziehau SYSCTL_ADD_ULONG(&sc->bnx_sysctl_ctx, 2373*695a8586SSepherosa Ziehau SYSCTL_CHILDREN(sc->bnx_sysctl_tree), OID_AUTO, 2374*695a8586SSepherosa Ziehau "norxbds", CTLFLAG_RW, &sc->bnx_norxbds, ""); 2375*695a8586SSepherosa Ziehau 2376*695a8586SSepherosa Ziehau SYSCTL_ADD_ULONG(&sc->bnx_sysctl_ctx, 2377*695a8586SSepherosa Ziehau SYSCTL_CHILDREN(sc->bnx_sysctl_tree), OID_AUTO, 2378*695a8586SSepherosa Ziehau "errors", CTLFLAG_RW, &sc->bnx_errors, ""); 2379*695a8586SSepherosa Ziehau 238066deb1c1SSepherosa Ziehau #ifdef BNX_TSO_DEBUG 238166deb1c1SSepherosa Ziehau for (i = 0; i < BNX_TSO_NSTATS; ++i) { 238266deb1c1SSepherosa Ziehau ksnprintf(desc, sizeof(desc), "tso%d", i + 1); 238366deb1c1SSepherosa Ziehau SYSCTL_ADD_ULONG(&sc->bnx_sysctl_ctx, 238466deb1c1SSepherosa Ziehau SYSCTL_CHILDREN(sc->bnx_sysctl_tree), OID_AUTO, 238566deb1c1SSepherosa Ziehau desc, CTLFLAG_RW, &sc->bnx_tsosegs[i], ""); 238666deb1c1SSepherosa Ziehau } 238766deb1c1SSepherosa Ziehau #endif 238866deb1c1SSepherosa Ziehau 23896c8d8eccSSepherosa Ziehau /* 23906c8d8eccSSepherosa Ziehau * Call MI attach routine. 23916c8d8eccSSepherosa Ziehau */ 2392329f9016SSepherosa Ziehau ether_ifattach(ifp, ether_addr, NULL); 23936c8d8eccSSepherosa Ziehau 2394329f9016SSepherosa Ziehau /* Setup TX rings and subqueues */ 2395329f9016SSepherosa Ziehau for (i = 0; i < sc->bnx_tx_ringcnt; ++i) { 2396329f9016SSepherosa Ziehau struct ifaltq_subque *ifsq = ifq_get_subq(&ifp->if_snd, i); 2397329f9016SSepherosa Ziehau struct bnx_tx_ring *txr = &sc->bnx_tx_ring[i]; 2398329f9016SSepherosa Ziehau 2399329f9016SSepherosa Ziehau ifsq_set_cpuid(ifsq, txr->bnx_tx_cpuid); 2400329f9016SSepherosa Ziehau ifsq_set_hw_serialize(ifsq, &txr->bnx_tx_serialize); 2401329f9016SSepherosa Ziehau ifsq_set_priv(ifsq, txr); 24023397dea6SSepherosa Ziehau txr->bnx_ifsq = ifsq; 2403329f9016SSepherosa Ziehau 24043397dea6SSepherosa Ziehau ifsq_watchdog_init(&txr->bnx_tx_watchdog, ifsq, bnx_watchdog); 2405*695a8586SSepherosa Ziehau 2406*695a8586SSepherosa Ziehau if (bootverbose) { 2407*695a8586SSepherosa Ziehau device_printf(dev, "txr %d -> cpu%d\n", i, 2408*695a8586SSepherosa Ziehau txr->bnx_tx_cpuid); 2409*695a8586SSepherosa Ziehau } 2410329f9016SSepherosa Ziehau } 24114c77af2dSSepherosa Ziehau 24120c7da01dSSepherosa Ziehau error = bnx_setup_intr(sc); 24136c8d8eccSSepherosa Ziehau if (error) { 24146c8d8eccSSepherosa Ziehau ether_ifdetach(ifp); 24156c8d8eccSSepherosa Ziehau goto fail; 24166c8d8eccSSepherosa Ziehau } 24177dbaa833SSepherosa Ziehau bnx_set_tick_cpuid(sc, FALSE); 24188ca0f604SSepherosa Ziehau 2419841cdf08SSepherosa Ziehau /* 2420841cdf08SSepherosa Ziehau * Create RX standard ring refilling thread 2421841cdf08SSepherosa Ziehau */ 2422841cdf08SSepherosa Ziehau std_cpuid_def = device_get_unit(dev) % ncpus; 2423841cdf08SSepherosa Ziehau std_cpuid = device_getenv_int(dev, "std.cpuid", std_cpuid_def); 2424841cdf08SSepherosa Ziehau if (std_cpuid < 0 || std_cpuid >= ncpus) { 2425841cdf08SSepherosa Ziehau device_printf(dev, "invalid std.cpuid %d, use %d\n", 2426841cdf08SSepherosa Ziehau std_cpuid, std_cpuid_def); 2427841cdf08SSepherosa Ziehau std_cpuid = std_cpuid_def; 2428841cdf08SSepherosa Ziehau } 2429841cdf08SSepherosa Ziehau 2430841cdf08SSepherosa Ziehau std = &sc->bnx_rx_std_ring; 2431841cdf08SSepherosa Ziehau lwkt_create(bnx_rx_std_refill_ithread, std, NULL, 2432841cdf08SSepherosa Ziehau &std->bnx_rx_std_ithread, TDF_NOSTART | TDF_INTTHREAD, std_cpuid, 2433841cdf08SSepherosa Ziehau "%s std", device_get_nameunit(dev)); 2434841cdf08SSepherosa Ziehau lwkt_setpri(&std->bnx_rx_std_ithread, TDPRI_INT_MED); 2435841cdf08SSepherosa Ziehau std->bnx_rx_std_ithread.td_preemptable = lwkt_preempt; 2436841cdf08SSepherosa Ziehau sc->bnx_flags |= BNX_FLAG_STD_THREAD; 2437841cdf08SSepherosa Ziehau 24386c8d8eccSSepherosa Ziehau return(0); 24396c8d8eccSSepherosa Ziehau fail: 24406c8d8eccSSepherosa Ziehau bnx_detach(dev); 24416c8d8eccSSepherosa Ziehau return(error); 24426c8d8eccSSepherosa Ziehau } 24436c8d8eccSSepherosa Ziehau 24446c8d8eccSSepherosa Ziehau static int 24456c8d8eccSSepherosa Ziehau bnx_detach(device_t dev) 24466c8d8eccSSepherosa Ziehau { 24476c8d8eccSSepherosa Ziehau struct bnx_softc *sc = device_get_softc(dev); 24486c8d8eccSSepherosa Ziehau 24496c8d8eccSSepherosa Ziehau if (device_is_attached(dev)) { 24506c8d8eccSSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if; 24516c8d8eccSSepherosa Ziehau 2452329f9016SSepherosa Ziehau ifnet_serialize_all(ifp); 24536c8d8eccSSepherosa Ziehau bnx_stop(sc); 24546c8d8eccSSepherosa Ziehau bnx_reset(sc); 2455f33ac8a4SSepherosa Ziehau bnx_teardown_intr(sc, sc->bnx_intr_cnt); 2456329f9016SSepherosa Ziehau ifnet_deserialize_all(ifp); 24576c8d8eccSSepherosa Ziehau 24586c8d8eccSSepherosa Ziehau ether_ifdetach(ifp); 24596c8d8eccSSepherosa Ziehau } 24606c8d8eccSSepherosa Ziehau 2461841cdf08SSepherosa Ziehau if (sc->bnx_flags & BNX_FLAG_STD_THREAD) { 2462841cdf08SSepherosa Ziehau struct bnx_rx_std_ring *std = &sc->bnx_rx_std_ring; 2463841cdf08SSepherosa Ziehau 2464841cdf08SSepherosa Ziehau tsleep_interlock(std, 0); 2465*695a8586SSepherosa Ziehau 2466*695a8586SSepherosa Ziehau if (std->bnx_rx_std_ithread.td_gd == mycpu) { 2467*695a8586SSepherosa Ziehau bnx_rx_std_refill_stop(std); 2468*695a8586SSepherosa Ziehau } else { 2469*695a8586SSepherosa Ziehau lwkt_send_ipiq(std->bnx_rx_std_ithread.td_gd, 2470*695a8586SSepherosa Ziehau bnx_rx_std_refill_stop, std); 2471*695a8586SSepherosa Ziehau } 2472*695a8586SSepherosa Ziehau 2473841cdf08SSepherosa Ziehau tsleep(std, PINTERLOCKED, "bnx_detach", 0); 2474841cdf08SSepherosa Ziehau if (bootverbose) 2475841cdf08SSepherosa Ziehau device_printf(dev, "RX std ithread exited\n"); 2476*695a8586SSepherosa Ziehau 2477*695a8586SSepherosa Ziehau lwkt_synchronize_ipiqs("bnx_detach_ipiq"); 2478841cdf08SSepherosa Ziehau } 2479841cdf08SSepherosa Ziehau 24806c8d8eccSSepherosa Ziehau if (sc->bnx_flags & BNX_FLAG_TBI) 24816c8d8eccSSepherosa Ziehau ifmedia_removeall(&sc->bnx_ifmedia); 24826c8d8eccSSepherosa Ziehau if (sc->bnx_miibus) 24836c8d8eccSSepherosa Ziehau device_delete_child(dev, sc->bnx_miibus); 24846c8d8eccSSepherosa Ziehau bus_generic_detach(dev); 24856c8d8eccSSepherosa Ziehau 24860c7da01dSSepherosa Ziehau bnx_free_intr(sc); 24876c8d8eccSSepherosa Ziehau 2488*695a8586SSepherosa Ziehau if (sc->bnx_msix_mem_res != NULL) { 2489*695a8586SSepherosa Ziehau bus_release_resource(dev, SYS_RES_MEMORY, sc->bnx_msix_mem_rid, 2490*695a8586SSepherosa Ziehau sc->bnx_msix_mem_res); 2491*695a8586SSepherosa Ziehau } 24926c8d8eccSSepherosa Ziehau if (sc->bnx_res != NULL) { 24936c8d8eccSSepherosa Ziehau bus_release_resource(dev, SYS_RES_MEMORY, 24946c8d8eccSSepherosa Ziehau BGE_PCI_BAR0, sc->bnx_res); 24956c8d8eccSSepherosa Ziehau } 24966c8d8eccSSepherosa Ziehau 24976c8d8eccSSepherosa Ziehau if (sc->bnx_sysctl_tree != NULL) 24986c8d8eccSSepherosa Ziehau sysctl_ctx_free(&sc->bnx_sysctl_ctx); 24996c8d8eccSSepherosa Ziehau 25006c8d8eccSSepherosa Ziehau bnx_dma_free(sc); 25016c8d8eccSSepherosa Ziehau 2502329f9016SSepherosa Ziehau if (sc->bnx_serialize != NULL) 2503329f9016SSepherosa Ziehau kfree(sc->bnx_serialize, M_DEVBUF); 2504329f9016SSepherosa Ziehau 25056c8d8eccSSepherosa Ziehau return 0; 25066c8d8eccSSepherosa Ziehau } 25076c8d8eccSSepherosa Ziehau 25086c8d8eccSSepherosa Ziehau static void 25096c8d8eccSSepherosa Ziehau bnx_reset(struct bnx_softc *sc) 25106c8d8eccSSepherosa Ziehau { 25116c8d8eccSSepherosa Ziehau device_t dev; 25126c8d8eccSSepherosa Ziehau uint32_t cachesize, command, pcistate, reset; 25136c8d8eccSSepherosa Ziehau void (*write_op)(struct bnx_softc *, uint32_t, uint32_t); 25146c8d8eccSSepherosa Ziehau int i, val = 0; 25156c8d8eccSSepherosa Ziehau uint16_t devctl; 25166c8d8eccSSepherosa Ziehau 25176c8d8eccSSepherosa Ziehau dev = sc->bnx_dev; 25186c8d8eccSSepherosa Ziehau 25196c8d8eccSSepherosa Ziehau write_op = bnx_writemem_direct; 25206c8d8eccSSepherosa Ziehau 25216c8d8eccSSepherosa Ziehau /* Save some important PCI state. */ 25226c8d8eccSSepherosa Ziehau cachesize = pci_read_config(dev, BGE_PCI_CACHESZ, 4); 25236c8d8eccSSepherosa Ziehau command = pci_read_config(dev, BGE_PCI_CMD, 4); 25246c8d8eccSSepherosa Ziehau pcistate = pci_read_config(dev, BGE_PCI_PCISTATE, 4); 25256c8d8eccSSepherosa Ziehau 25266c8d8eccSSepherosa Ziehau pci_write_config(dev, BGE_PCI_MISC_CTL, 25276c8d8eccSSepherosa Ziehau BGE_PCIMISCCTL_INDIRECT_ACCESS|BGE_PCIMISCCTL_MASK_PCI_INTR| 25286c8d8eccSSepherosa Ziehau BGE_HIF_SWAP_OPTIONS|BGE_PCIMISCCTL_PCISTATE_RW| 25296c8d8eccSSepherosa Ziehau BGE_PCIMISCCTL_TAGGED_STATUS, 4); 25306c8d8eccSSepherosa Ziehau 25316c8d8eccSSepherosa Ziehau /* Disable fastboot on controllers that support it. */ 25326c8d8eccSSepherosa Ziehau if (bootverbose) 25336c8d8eccSSepherosa Ziehau if_printf(&sc->arpcom.ac_if, "Disabling fastboot\n"); 25346c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_FASTBOOT_PC, 0x0); 25356c8d8eccSSepherosa Ziehau 25366c8d8eccSSepherosa Ziehau /* 25376c8d8eccSSepherosa Ziehau * Write the magic number to SRAM at offset 0xB50. 25386c8d8eccSSepherosa Ziehau * When firmware finishes its initialization it will 25396c8d8eccSSepherosa Ziehau * write ~BGE_MAGIC_NUMBER to the same location. 25406c8d8eccSSepherosa Ziehau */ 25416c8d8eccSSepherosa Ziehau bnx_writemem_ind(sc, BGE_SOFTWARE_GENCOMM, BGE_MAGIC_NUMBER); 25426c8d8eccSSepherosa Ziehau 25436c8d8eccSSepherosa Ziehau reset = BGE_MISCCFG_RESET_CORE_CLOCKS|(65<<1); 25446c8d8eccSSepherosa Ziehau 25456c8d8eccSSepherosa Ziehau /* XXX: Broadcom Linux driver. */ 25466c8d8eccSSepherosa Ziehau /* Force PCI-E 1.0a mode */ 25473730a14dSSepherosa Ziehau if (!BNX_IS_57765_PLUS(sc) && 25486c8d8eccSSepherosa Ziehau CSR_READ_4(sc, BGE_PCIE_PHY_TSTCTL) == 25496c8d8eccSSepherosa Ziehau (BGE_PCIE_PHY_TSTCTL_PSCRAM | 25506c8d8eccSSepherosa Ziehau BGE_PCIE_PHY_TSTCTL_PCIE10)) { 25516c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_PCIE_PHY_TSTCTL, 25526c8d8eccSSepherosa Ziehau BGE_PCIE_PHY_TSTCTL_PSCRAM); 25536c8d8eccSSepherosa Ziehau } 25546c8d8eccSSepherosa Ziehau if (sc->bnx_chipid != BGE_CHIPID_BCM5750_A0) { 25556c8d8eccSSepherosa Ziehau /* Prevent PCIE link training during global reset */ 25566c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_MISC_CFG, (1<<29)); 25576c8d8eccSSepherosa Ziehau reset |= (1<<29); 25586c8d8eccSSepherosa Ziehau } 25596c8d8eccSSepherosa Ziehau 25606c8d8eccSSepherosa Ziehau /* 25616c8d8eccSSepherosa Ziehau * Set GPHY Power Down Override to leave GPHY 25626c8d8eccSSepherosa Ziehau * powered up in D0 uninitialized. 25636c8d8eccSSepherosa Ziehau */ 25646c8d8eccSSepherosa Ziehau if ((sc->bnx_flags & BNX_FLAG_CPMU) == 0) 25656c8d8eccSSepherosa Ziehau reset |= BGE_MISCCFG_GPHY_PD_OVERRIDE; 25666c8d8eccSSepherosa Ziehau 25676c8d8eccSSepherosa Ziehau /* Issue global reset */ 25686c8d8eccSSepherosa Ziehau write_op(sc, BGE_MISC_CFG, reset); 25696c8d8eccSSepherosa Ziehau 25706c8d8eccSSepherosa Ziehau DELAY(1000); 25716c8d8eccSSepherosa Ziehau 25726c8d8eccSSepherosa Ziehau /* XXX: Broadcom Linux driver. */ 25736c8d8eccSSepherosa Ziehau if (sc->bnx_chipid == BGE_CHIPID_BCM5750_A0) { 25746c8d8eccSSepherosa Ziehau uint32_t v; 25756c8d8eccSSepherosa Ziehau 25766c8d8eccSSepherosa Ziehau DELAY(500000); /* wait for link training to complete */ 25776c8d8eccSSepherosa Ziehau v = pci_read_config(dev, 0xc4, 4); 25786c8d8eccSSepherosa Ziehau pci_write_config(dev, 0xc4, v | (1<<15), 4); 25796c8d8eccSSepherosa Ziehau } 25806c8d8eccSSepherosa Ziehau 25816c8d8eccSSepherosa Ziehau devctl = pci_read_config(dev, sc->bnx_pciecap + PCIER_DEVCTRL, 2); 25826c8d8eccSSepherosa Ziehau 25836c8d8eccSSepherosa Ziehau /* Disable no snoop and disable relaxed ordering. */ 25846c8d8eccSSepherosa Ziehau devctl &= ~(PCIEM_DEVCTL_RELAX_ORDER | PCIEM_DEVCTL_NOSNOOP); 25856c8d8eccSSepherosa Ziehau 25866c8d8eccSSepherosa Ziehau /* Old PCI-E chips only support 128 bytes Max PayLoad Size. */ 25876c8d8eccSSepherosa Ziehau if ((sc->bnx_flags & BNX_FLAG_CPMU) == 0) { 25886c8d8eccSSepherosa Ziehau devctl &= ~PCIEM_DEVCTL_MAX_PAYLOAD_MASK; 25896c8d8eccSSepherosa Ziehau devctl |= PCIEM_DEVCTL_MAX_PAYLOAD_128; 25906c8d8eccSSepherosa Ziehau } 25916c8d8eccSSepherosa Ziehau 25926c8d8eccSSepherosa Ziehau pci_write_config(dev, sc->bnx_pciecap + PCIER_DEVCTRL, 25936c8d8eccSSepherosa Ziehau devctl, 2); 25946c8d8eccSSepherosa Ziehau 25956c8d8eccSSepherosa Ziehau /* Clear error status. */ 25966c8d8eccSSepherosa Ziehau pci_write_config(dev, sc->bnx_pciecap + PCIER_DEVSTS, 25976c8d8eccSSepherosa Ziehau PCIEM_DEVSTS_CORR_ERR | 25986c8d8eccSSepherosa Ziehau PCIEM_DEVSTS_NFATAL_ERR | 25996c8d8eccSSepherosa Ziehau PCIEM_DEVSTS_FATAL_ERR | 26006c8d8eccSSepherosa Ziehau PCIEM_DEVSTS_UNSUPP_REQ, 2); 26016c8d8eccSSepherosa Ziehau 26026c8d8eccSSepherosa Ziehau /* Reset some of the PCI state that got zapped by reset */ 26036c8d8eccSSepherosa Ziehau pci_write_config(dev, BGE_PCI_MISC_CTL, 26046c8d8eccSSepherosa Ziehau BGE_PCIMISCCTL_INDIRECT_ACCESS|BGE_PCIMISCCTL_MASK_PCI_INTR| 26056c8d8eccSSepherosa Ziehau BGE_HIF_SWAP_OPTIONS|BGE_PCIMISCCTL_PCISTATE_RW| 26066c8d8eccSSepherosa Ziehau BGE_PCIMISCCTL_TAGGED_STATUS, 4); 26076c8d8eccSSepherosa Ziehau pci_write_config(dev, BGE_PCI_CACHESZ, cachesize, 4); 26086c8d8eccSSepherosa Ziehau pci_write_config(dev, BGE_PCI_CMD, command, 4); 26096c8d8eccSSepherosa Ziehau write_op(sc, BGE_MISC_CFG, (65 << 1)); 26106c8d8eccSSepherosa Ziehau 26116c8d8eccSSepherosa Ziehau /* Enable memory arbiter */ 26126c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_MARB_MODE, BGE_MARBMODE_ENABLE); 26136c8d8eccSSepherosa Ziehau 26146c8d8eccSSepherosa Ziehau /* 26156c8d8eccSSepherosa Ziehau * Poll until we see the 1's complement of the magic number. 2616ddd93a5cSSepherosa Ziehau * This indicates that the firmware initialization is complete. 26176c8d8eccSSepherosa Ziehau */ 26186c8d8eccSSepherosa Ziehau for (i = 0; i < BNX_FIRMWARE_TIMEOUT; i++) { 26196c8d8eccSSepherosa Ziehau val = bnx_readmem_ind(sc, BGE_SOFTWARE_GENCOMM); 26206c8d8eccSSepherosa Ziehau if (val == ~BGE_MAGIC_NUMBER) 26216c8d8eccSSepherosa Ziehau break; 26226c8d8eccSSepherosa Ziehau DELAY(10); 26236c8d8eccSSepherosa Ziehau } 26246c8d8eccSSepherosa Ziehau if (i == BNX_FIRMWARE_TIMEOUT) { 26256c8d8eccSSepherosa Ziehau if_printf(&sc->arpcom.ac_if, "firmware handshake " 26266c8d8eccSSepherosa Ziehau "timed out, found 0x%08x\n", val); 26276c8d8eccSSepherosa Ziehau } 26286c8d8eccSSepherosa Ziehau 26296c8d8eccSSepherosa Ziehau /* BCM57765 A0 needs additional time before accessing. */ 26306c8d8eccSSepherosa Ziehau if (sc->bnx_chipid == BGE_CHIPID_BCM57765_A0) 26316c8d8eccSSepherosa Ziehau DELAY(10 * 1000); 26326c8d8eccSSepherosa Ziehau 26336c8d8eccSSepherosa Ziehau /* 26346c8d8eccSSepherosa Ziehau * XXX Wait for the value of the PCISTATE register to 26356c8d8eccSSepherosa Ziehau * return to its original pre-reset state. This is a 26366c8d8eccSSepherosa Ziehau * fairly good indicator of reset completion. If we don't 26376c8d8eccSSepherosa Ziehau * wait for the reset to fully complete, trying to read 26386c8d8eccSSepherosa Ziehau * from the device's non-PCI registers may yield garbage 26396c8d8eccSSepherosa Ziehau * results. 26406c8d8eccSSepherosa Ziehau */ 26416c8d8eccSSepherosa Ziehau for (i = 0; i < BNX_TIMEOUT; i++) { 26426c8d8eccSSepherosa Ziehau if (pci_read_config(dev, BGE_PCI_PCISTATE, 4) == pcistate) 26436c8d8eccSSepherosa Ziehau break; 26446c8d8eccSSepherosa Ziehau DELAY(10); 26456c8d8eccSSepherosa Ziehau } 26466c8d8eccSSepherosa Ziehau 26476c8d8eccSSepherosa Ziehau /* Fix up byte swapping */ 26486c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_MODE_CTL, bnx_dma_swap_options(sc)); 26496c8d8eccSSepherosa Ziehau 26506c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_MAC_MODE, 0); 26516c8d8eccSSepherosa Ziehau 26526c8d8eccSSepherosa Ziehau /* 26536c8d8eccSSepherosa Ziehau * The 5704 in TBI mode apparently needs some special 26546c8d8eccSSepherosa Ziehau * adjustment to insure the SERDES drive level is set 26556c8d8eccSSepherosa Ziehau * to 1.2V. 26566c8d8eccSSepherosa Ziehau */ 26576c8d8eccSSepherosa Ziehau if (sc->bnx_asicrev == BGE_ASICREV_BCM5704 && 26586c8d8eccSSepherosa Ziehau (sc->bnx_flags & BNX_FLAG_TBI)) { 26596c8d8eccSSepherosa Ziehau uint32_t serdescfg; 26606c8d8eccSSepherosa Ziehau 26616c8d8eccSSepherosa Ziehau serdescfg = CSR_READ_4(sc, BGE_SERDES_CFG); 26626c8d8eccSSepherosa Ziehau serdescfg = (serdescfg & ~0xFFF) | 0x880; 26636c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_SERDES_CFG, serdescfg); 26646c8d8eccSSepherosa Ziehau } 26656c8d8eccSSepherosa Ziehau 26667892075dSSepherosa Ziehau CSR_WRITE_4(sc, BGE_MI_MODE, 26677892075dSSepherosa Ziehau sc->bnx_mi_mode & ~BGE_MIMODE_AUTOPOLL); 26687892075dSSepherosa Ziehau DELAY(80); 26697892075dSSepherosa Ziehau 26706c8d8eccSSepherosa Ziehau /* XXX: Broadcom Linux driver. */ 26713730a14dSSepherosa Ziehau if (!BNX_IS_57765_PLUS(sc)) { 26726c8d8eccSSepherosa Ziehau uint32_t v; 26736c8d8eccSSepherosa Ziehau 26746c8d8eccSSepherosa Ziehau /* Enable Data FIFO protection. */ 2675f1f34fc4SSepherosa Ziehau v = CSR_READ_4(sc, BGE_PCIE_TLDLPL_PORT); 2676f1f34fc4SSepherosa Ziehau CSR_WRITE_4(sc, BGE_PCIE_TLDLPL_PORT, v | (1 << 25)); 26776c8d8eccSSepherosa Ziehau } 26786c8d8eccSSepherosa Ziehau 26796c8d8eccSSepherosa Ziehau DELAY(10000); 26806c8d8eccSSepherosa Ziehau 26816c8d8eccSSepherosa Ziehau if (sc->bnx_asicrev == BGE_ASICREV_BCM5720) { 26826c8d8eccSSepherosa Ziehau BNX_CLRBIT(sc, BGE_CPMU_CLCK_ORIDE, 26836c8d8eccSSepherosa Ziehau CPMU_CLCK_ORIDE_MAC_ORIDE_EN); 26846c8d8eccSSepherosa Ziehau } 26856c8d8eccSSepherosa Ziehau } 26866c8d8eccSSepherosa Ziehau 26876c8d8eccSSepherosa Ziehau /* 26886c8d8eccSSepherosa Ziehau * Frame reception handling. This is called if there's a frame 26896c8d8eccSSepherosa Ziehau * on the receive return list. 26906c8d8eccSSepherosa Ziehau * 26916c8d8eccSSepherosa Ziehau * Note: we have to be able to handle two possibilities here: 26926c8d8eccSSepherosa Ziehau * 1) the frame is from the jumbo recieve ring 26936c8d8eccSSepherosa Ziehau * 2) the frame is from the standard receive ring 26946c8d8eccSSepherosa Ziehau */ 26956c8d8eccSSepherosa Ziehau 26966c8d8eccSSepherosa Ziehau static void 2697beedf5beSSepherosa Ziehau bnx_rxeof(struct bnx_rx_ret_ring *ret, uint16_t rx_prod, int count) 26986c8d8eccSSepherosa Ziehau { 2699beedf5beSSepherosa Ziehau struct bnx_softc *sc = ret->bnx_sc; 2700beedf5beSSepherosa Ziehau struct bnx_rx_std_ring *std = ret->bnx_std; 2701beedf5beSSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if; 27026c8d8eccSSepherosa Ziehau 2703beedf5beSSepherosa Ziehau while (ret->bnx_rx_saved_considx != rx_prod && count != 0) { 27046c8d8eccSSepherosa Ziehau struct bge_rx_bd *cur_rx; 2705841cdf08SSepherosa Ziehau struct bnx_rx_buf *rb; 27066c8d8eccSSepherosa Ziehau uint32_t rxidx; 27076c8d8eccSSepherosa Ziehau struct mbuf *m = NULL; 27086c8d8eccSSepherosa Ziehau uint16_t vlan_tag = 0; 27096c8d8eccSSepherosa Ziehau int have_tag = 0; 27106c8d8eccSSepherosa Ziehau 271197381780SSepherosa Ziehau --count; 271297381780SSepherosa Ziehau 2713beedf5beSSepherosa Ziehau cur_rx = &ret->bnx_rx_ret_ring[ret->bnx_rx_saved_considx]; 27146c8d8eccSSepherosa Ziehau 27156c8d8eccSSepherosa Ziehau rxidx = cur_rx->bge_idx; 2716*695a8586SSepherosa Ziehau KKASSERT(rxidx < BGE_STD_RX_RING_CNT); 2717*695a8586SSepherosa Ziehau 2718beedf5beSSepherosa Ziehau BNX_INC(ret->bnx_rx_saved_considx, BNX_RETURN_RING_CNT); 2719*695a8586SSepherosa Ziehau #ifdef BNX_RSS_DEBUG 2720*695a8586SSepherosa Ziehau ret->bnx_rx_pkt++; 2721*695a8586SSepherosa Ziehau #endif 27226c8d8eccSSepherosa Ziehau 27236c8d8eccSSepherosa Ziehau if (cur_rx->bge_flags & BGE_RXBDFLAG_VLAN_TAG) { 27246c8d8eccSSepherosa Ziehau have_tag = 1; 27256c8d8eccSSepherosa Ziehau vlan_tag = cur_rx->bge_vlan_tag; 27266c8d8eccSSepherosa Ziehau } 27276c8d8eccSSepherosa Ziehau 2728*695a8586SSepherosa Ziehau if (ret->bnx_rx_cnt >= ret->bnx_rx_cntmax) 2729*695a8586SSepherosa Ziehau bnx_rx_std_refill_sched(ret, std); 2730841cdf08SSepherosa Ziehau ret->bnx_rx_cnt++; 27316c8d8eccSSepherosa Ziehau 2732841cdf08SSepherosa Ziehau rb = &std->bnx_rx_std_buf[rxidx]; 2733841cdf08SSepherosa Ziehau m = rb->bnx_rx_mbuf; 27346c8d8eccSSepherosa Ziehau if (cur_rx->bge_flags & BGE_RXBDFLAG_ERROR) { 2735d40991efSSepherosa Ziehau IFNET_STAT_INC(ifp, ierrors, 1); 2736841cdf08SSepherosa Ziehau cpu_sfence(); 2737841cdf08SSepherosa Ziehau rb->bnx_rx_refilled = 1; 27386c8d8eccSSepherosa Ziehau continue; 27396c8d8eccSSepherosa Ziehau } 2740841cdf08SSepherosa Ziehau if (bnx_newbuf_std(ret, rxidx, 0)) { 2741d40991efSSepherosa Ziehau IFNET_STAT_INC(ifp, ierrors, 1); 27426c8d8eccSSepherosa Ziehau continue; 27436c8d8eccSSepherosa Ziehau } 27446c8d8eccSSepherosa Ziehau 2745d40991efSSepherosa Ziehau IFNET_STAT_INC(ifp, ipackets, 1); 27466c8d8eccSSepherosa Ziehau m->m_pkthdr.len = m->m_len = cur_rx->bge_len - ETHER_CRC_LEN; 27476c8d8eccSSepherosa Ziehau m->m_pkthdr.rcvif = ifp; 27486c8d8eccSSepherosa Ziehau 27496c8d8eccSSepherosa Ziehau if ((ifp->if_capenable & IFCAP_RXCSUM) && 27506c8d8eccSSepherosa Ziehau (cur_rx->bge_flags & BGE_RXBDFLAG_IPV6) == 0) { 27516c8d8eccSSepherosa Ziehau if (cur_rx->bge_flags & BGE_RXBDFLAG_IP_CSUM) { 27526c8d8eccSSepherosa Ziehau m->m_pkthdr.csum_flags |= CSUM_IP_CHECKED; 27536c8d8eccSSepherosa Ziehau if ((cur_rx->bge_error_flag & 27546c8d8eccSSepherosa Ziehau BGE_RXERRFLAG_IP_CSUM_NOK) == 0) 27556c8d8eccSSepherosa Ziehau m->m_pkthdr.csum_flags |= CSUM_IP_VALID; 27566c8d8eccSSepherosa Ziehau } 27576c8d8eccSSepherosa Ziehau if (cur_rx->bge_flags & BGE_RXBDFLAG_TCP_UDP_CSUM) { 27586c8d8eccSSepherosa Ziehau m->m_pkthdr.csum_data = 27596c8d8eccSSepherosa Ziehau cur_rx->bge_tcp_udp_csum; 27606c8d8eccSSepherosa Ziehau m->m_pkthdr.csum_flags |= CSUM_DATA_VALID | 27616c8d8eccSSepherosa Ziehau CSUM_PSEUDO_HDR; 27626c8d8eccSSepherosa Ziehau } 27636c8d8eccSSepherosa Ziehau } 27646c8d8eccSSepherosa Ziehau 27656c8d8eccSSepherosa Ziehau /* 27666c8d8eccSSepherosa Ziehau * If we received a packet with a vlan tag, pass it 27676c8d8eccSSepherosa Ziehau * to vlan_input() instead of ether_input(). 27686c8d8eccSSepherosa Ziehau */ 27696c8d8eccSSepherosa Ziehau if (have_tag) { 27706c8d8eccSSepherosa Ziehau m->m_flags |= M_VLANTAG; 27716c8d8eccSSepherosa Ziehau m->m_pkthdr.ether_vlantag = vlan_tag; 27726c8d8eccSSepherosa Ziehau } 27736c8d8eccSSepherosa Ziehau ifp->if_input(ifp, m); 27746c8d8eccSSepherosa Ziehau } 2775ac2936fdSSepherosa Ziehau bnx_writembx(sc, ret->bnx_rx_mbx, ret->bnx_rx_saved_considx); 2776*695a8586SSepherosa Ziehau 2777*695a8586SSepherosa Ziehau if (ret->bnx_rx_cnt > 0) 2778*695a8586SSepherosa Ziehau bnx_rx_std_refill_sched(ret, std); 27796c8d8eccSSepherosa Ziehau } 27806c8d8eccSSepherosa Ziehau 27816c8d8eccSSepherosa Ziehau static void 278233a04907SSepherosa Ziehau bnx_txeof(struct bnx_tx_ring *txr, uint16_t tx_cons) 27836c8d8eccSSepherosa Ziehau { 278433a04907SSepherosa Ziehau struct ifnet *ifp = &txr->bnx_sc->arpcom.ac_if; 27856c8d8eccSSepherosa Ziehau 27866c8d8eccSSepherosa Ziehau /* 27876c8d8eccSSepherosa Ziehau * Go through our tx ring and free mbufs for those 27886c8d8eccSSepherosa Ziehau * frames that have been sent. 27896c8d8eccSSepherosa Ziehau */ 279033a04907SSepherosa Ziehau while (txr->bnx_tx_saved_considx != tx_cons) { 2791fa4b1067SSepherosa Ziehau struct bnx_tx_buf *buf; 27926c8d8eccSSepherosa Ziehau uint32_t idx = 0; 27936c8d8eccSSepherosa Ziehau 279433a04907SSepherosa Ziehau idx = txr->bnx_tx_saved_considx; 2795fa4b1067SSepherosa Ziehau buf = &txr->bnx_tx_buf[idx]; 2796fa4b1067SSepherosa Ziehau if (buf->bnx_tx_mbuf != NULL) { 2797d40991efSSepherosa Ziehau IFNET_STAT_INC(ifp, opackets, 1); 2798*695a8586SSepherosa Ziehau #ifdef BNX_TSS_DEBUG 2799*695a8586SSepherosa Ziehau txr->bnx_tx_pkt++; 2800*695a8586SSepherosa Ziehau #endif 280133a04907SSepherosa Ziehau bus_dmamap_unload(txr->bnx_tx_mtag, 2802fa4b1067SSepherosa Ziehau buf->bnx_tx_dmamap); 2803fa4b1067SSepherosa Ziehau m_freem(buf->bnx_tx_mbuf); 2804fa4b1067SSepherosa Ziehau buf->bnx_tx_mbuf = NULL; 28056c8d8eccSSepherosa Ziehau } 2806fa639b88SSepherosa Ziehau txr->bnx_tx_cnt--; 280733a04907SSepherosa Ziehau BNX_INC(txr->bnx_tx_saved_considx, BGE_TX_RING_CNT); 28086c8d8eccSSepherosa Ziehau } 28096c8d8eccSSepherosa Ziehau 2810fa639b88SSepherosa Ziehau if ((BGE_TX_RING_CNT - txr->bnx_tx_cnt) >= 28116c8d8eccSSepherosa Ziehau (BNX_NSEG_RSVD + BNX_NSEG_SPARE)) 28123397dea6SSepherosa Ziehau ifsq_clr_oactive(txr->bnx_ifsq); 28136c8d8eccSSepherosa Ziehau 2814fa639b88SSepherosa Ziehau if (txr->bnx_tx_cnt == 0) 28153397dea6SSepherosa Ziehau txr->bnx_tx_watchdog.wd_timer = 0; 28166c8d8eccSSepherosa Ziehau 28173397dea6SSepherosa Ziehau if (!ifsq_is_empty(txr->bnx_ifsq)) 28183397dea6SSepherosa Ziehau ifsq_devstart(txr->bnx_ifsq); 28196c8d8eccSSepherosa Ziehau } 28206c8d8eccSSepherosa Ziehau 2821*695a8586SSepherosa Ziehau static void 2822*695a8586SSepherosa Ziehau bnx_handle_status(struct bnx_softc *sc) 2823*695a8586SSepherosa Ziehau { 2824*695a8586SSepherosa Ziehau uint32_t status; 2825*695a8586SSepherosa Ziehau 2826*695a8586SSepherosa Ziehau status = *sc->bnx_hw_status; 2827*695a8586SSepherosa Ziehau 2828*695a8586SSepherosa Ziehau if (status & BGE_STATFLAG_ERROR) { 2829*695a8586SSepherosa Ziehau uint32_t val; 2830*695a8586SSepherosa Ziehau int reset = 0; 2831*695a8586SSepherosa Ziehau 2832*695a8586SSepherosa Ziehau sc->bnx_errors++; 2833*695a8586SSepherosa Ziehau 2834*695a8586SSepherosa Ziehau val = CSR_READ_4(sc, BGE_FLOW_ATTN); 2835*695a8586SSepherosa Ziehau if (val & ~BGE_FLOWATTN_MB_LOWAT) { 2836*695a8586SSepherosa Ziehau if_printf(&sc->arpcom.ac_if, 2837*695a8586SSepherosa Ziehau "flow attn 0x%08x\n", val); 2838*695a8586SSepherosa Ziehau reset = 1; 2839*695a8586SSepherosa Ziehau } 2840*695a8586SSepherosa Ziehau 2841*695a8586SSepherosa Ziehau val = CSR_READ_4(sc, BGE_MSI_STATUS); 2842*695a8586SSepherosa Ziehau if (val & ~BGE_MSISTAT_MSI_PCI_REQ) { 2843*695a8586SSepherosa Ziehau if_printf(&sc->arpcom.ac_if, 2844*695a8586SSepherosa Ziehau "msi status 0x%08x\n", val); 2845*695a8586SSepherosa Ziehau reset = 1; 2846*695a8586SSepherosa Ziehau } 2847*695a8586SSepherosa Ziehau 2848*695a8586SSepherosa Ziehau val = CSR_READ_4(sc, BGE_RDMA_STATUS); 2849*695a8586SSepherosa Ziehau if (val) { 2850*695a8586SSepherosa Ziehau if_printf(&sc->arpcom.ac_if, 2851*695a8586SSepherosa Ziehau "rmda status 0x%08x\n", val); 2852*695a8586SSepherosa Ziehau reset = 1; 2853*695a8586SSepherosa Ziehau } 2854*695a8586SSepherosa Ziehau 2855*695a8586SSepherosa Ziehau val = CSR_READ_4(sc, BGE_WDMA_STATUS); 2856*695a8586SSepherosa Ziehau if (val) { 2857*695a8586SSepherosa Ziehau if_printf(&sc->arpcom.ac_if, 2858*695a8586SSepherosa Ziehau "wdma status 0x%08x\n", val); 2859*695a8586SSepherosa Ziehau reset = 1; 2860*695a8586SSepherosa Ziehau } 2861*695a8586SSepherosa Ziehau 2862*695a8586SSepherosa Ziehau if (reset) { 2863*695a8586SSepherosa Ziehau bnx_serialize_skipmain(sc); 2864*695a8586SSepherosa Ziehau bnx_init(sc); 2865*695a8586SSepherosa Ziehau bnx_deserialize_skipmain(sc); 2866*695a8586SSepherosa Ziehau } 2867*695a8586SSepherosa Ziehau } 2868*695a8586SSepherosa Ziehau 2869*695a8586SSepherosa Ziehau if ((status & BGE_STATFLAG_LINKSTATE_CHANGED) || sc->bnx_link_evt) 2870*695a8586SSepherosa Ziehau bnx_link_poll(sc); 2871*695a8586SSepherosa Ziehau } 2872*695a8586SSepherosa Ziehau 287339a8d43aSSepherosa Ziehau #ifdef IFPOLL_ENABLE 28746c8d8eccSSepherosa Ziehau 28756c8d8eccSSepherosa Ziehau static void 28764fa38985SSepherosa Ziehau bnx_npoll_rx(struct ifnet *ifp __unused, void *xret, int cycle) 28774fa38985SSepherosa Ziehau { 28784fa38985SSepherosa Ziehau struct bnx_rx_ret_ring *ret = xret; 28794fa38985SSepherosa Ziehau uint16_t rx_prod; 28804fa38985SSepherosa Ziehau 28814fa38985SSepherosa Ziehau ASSERT_SERIALIZED(&ret->bnx_rx_ret_serialize); 28824fa38985SSepherosa Ziehau 28834fa38985SSepherosa Ziehau ret->bnx_saved_status_tag = *ret->bnx_hw_status_tag; 28844fa38985SSepherosa Ziehau cpu_lfence(); 28854fa38985SSepherosa Ziehau 28864fa38985SSepherosa Ziehau rx_prod = *ret->bnx_rx_considx; 28874fa38985SSepherosa Ziehau if (ret->bnx_rx_saved_considx != rx_prod) 28884fa38985SSepherosa Ziehau bnx_rxeof(ret, rx_prod, cycle); 28894fa38985SSepherosa Ziehau } 28904fa38985SSepherosa Ziehau 28914fa38985SSepherosa Ziehau static void 2892*695a8586SSepherosa Ziehau bnx_npoll_tx_notag(struct ifnet *ifp __unused, void *xtxr, int cycle __unused) 28934fa38985SSepherosa Ziehau { 28944fa38985SSepherosa Ziehau struct bnx_tx_ring *txr = xtxr; 28954fa38985SSepherosa Ziehau uint16_t tx_cons; 28964fa38985SSepherosa Ziehau 28974fa38985SSepherosa Ziehau ASSERT_SERIALIZED(&txr->bnx_tx_serialize); 28984fa38985SSepherosa Ziehau 28994fa38985SSepherosa Ziehau tx_cons = *txr->bnx_tx_considx; 29004fa38985SSepherosa Ziehau if (txr->bnx_tx_saved_considx != tx_cons) 29014fa38985SSepherosa Ziehau bnx_txeof(txr, tx_cons); 29024fa38985SSepherosa Ziehau } 29034fa38985SSepherosa Ziehau 29044fa38985SSepherosa Ziehau static void 2905*695a8586SSepherosa Ziehau bnx_npoll_tx(struct ifnet *ifp, void *xtxr, int cycle) 2906*695a8586SSepherosa Ziehau { 2907*695a8586SSepherosa Ziehau struct bnx_tx_ring *txr = xtxr; 2908*695a8586SSepherosa Ziehau 2909*695a8586SSepherosa Ziehau ASSERT_SERIALIZED(&txr->bnx_tx_serialize); 2910*695a8586SSepherosa Ziehau 2911*695a8586SSepherosa Ziehau txr->bnx_saved_status_tag = *txr->bnx_hw_status_tag; 2912*695a8586SSepherosa Ziehau cpu_lfence(); 2913*695a8586SSepherosa Ziehau bnx_npoll_tx_notag(ifp, txr, cycle); 2914*695a8586SSepherosa Ziehau } 2915*695a8586SSepherosa Ziehau 2916*695a8586SSepherosa Ziehau static void 2917*695a8586SSepherosa Ziehau bnx_npoll_status_notag(struct ifnet *ifp) 29184fa38985SSepherosa Ziehau { 29194fa38985SSepherosa Ziehau struct bnx_softc *sc = ifp->if_softc; 29204fa38985SSepherosa Ziehau 29214fa38985SSepherosa Ziehau ASSERT_SERIALIZED(&sc->bnx_main_serialize); 29224fa38985SSepherosa Ziehau 2923*695a8586SSepherosa Ziehau bnx_handle_status(sc); 2924*695a8586SSepherosa Ziehau } 2925*695a8586SSepherosa Ziehau 2926*695a8586SSepherosa Ziehau static void 2927*695a8586SSepherosa Ziehau bnx_npoll_status(struct ifnet *ifp) 2928*695a8586SSepherosa Ziehau { 2929*695a8586SSepherosa Ziehau struct bnx_softc *sc = ifp->if_softc; 2930*695a8586SSepherosa Ziehau 2931*695a8586SSepherosa Ziehau ASSERT_SERIALIZED(&sc->bnx_main_serialize); 2932*695a8586SSepherosa Ziehau 2933*695a8586SSepherosa Ziehau sc->bnx_saved_status_tag = *sc->bnx_hw_status_tag; 2934*695a8586SSepherosa Ziehau cpu_lfence(); 2935*695a8586SSepherosa Ziehau bnx_npoll_status_notag(ifp); 29364fa38985SSepherosa Ziehau } 29374fa38985SSepherosa Ziehau 29384fa38985SSepherosa Ziehau static void 293939a8d43aSSepherosa Ziehau bnx_npoll(struct ifnet *ifp, struct ifpoll_info *info) 294039a8d43aSSepherosa Ziehau { 294139a8d43aSSepherosa Ziehau struct bnx_softc *sc = ifp->if_softc; 29424fa38985SSepherosa Ziehau int i; 294339a8d43aSSepherosa Ziehau 2944329f9016SSepherosa Ziehau ASSERT_IFNET_SERIALIZED_ALL(ifp); 294539a8d43aSSepherosa Ziehau 294639a8d43aSSepherosa Ziehau if (info != NULL) { 2947*695a8586SSepherosa Ziehau if (sc->bnx_flags & BNX_FLAG_STATUS_HASTAG) 29484fa38985SSepherosa Ziehau info->ifpi_status.status_func = bnx_npoll_status; 2949*695a8586SSepherosa Ziehau else 2950*695a8586SSepherosa Ziehau info->ifpi_status.status_func = bnx_npoll_status_notag; 29514fa38985SSepherosa Ziehau info->ifpi_status.serializer = &sc->bnx_main_serialize; 295239a8d43aSSepherosa Ziehau 29534fa38985SSepherosa Ziehau for (i = 0; i < sc->bnx_tx_ringcnt; ++i) { 29544fa38985SSepherosa Ziehau struct bnx_tx_ring *txr = &sc->bnx_tx_ring[i]; 29554fa38985SSepherosa Ziehau int idx = i + sc->bnx_npoll_txoff; 29564fa38985SSepherosa Ziehau 29574fa38985SSepherosa Ziehau KKASSERT(idx < ncpus2); 2958*695a8586SSepherosa Ziehau if (sc->bnx_flags & BNX_FLAG_RXTX_BUNDLE) { 2959*695a8586SSepherosa Ziehau info->ifpi_tx[idx].poll_func = 2960*695a8586SSepherosa Ziehau bnx_npoll_tx_notag; 2961*695a8586SSepherosa Ziehau } else { 29624fa38985SSepherosa Ziehau info->ifpi_tx[idx].poll_func = bnx_npoll_tx; 2963*695a8586SSepherosa Ziehau } 29644fa38985SSepherosa Ziehau info->ifpi_tx[idx].arg = txr; 29654fa38985SSepherosa Ziehau info->ifpi_tx[idx].serializer = &txr->bnx_tx_serialize; 29664fa38985SSepherosa Ziehau ifsq_set_cpuid(txr->bnx_ifsq, idx); 29674fa38985SSepherosa Ziehau } 29684fa38985SSepherosa Ziehau 29694fa38985SSepherosa Ziehau for (i = 0; i < sc->bnx_rx_retcnt; ++i) { 29704fa38985SSepherosa Ziehau struct bnx_rx_ret_ring *ret = &sc->bnx_rx_ret_ring[i]; 29714fa38985SSepherosa Ziehau int idx = i + sc->bnx_npoll_rxoff; 29724fa38985SSepherosa Ziehau 29734fa38985SSepherosa Ziehau KKASSERT(idx < ncpus2); 29744fa38985SSepherosa Ziehau info->ifpi_rx[idx].poll_func = bnx_npoll_rx; 29754fa38985SSepherosa Ziehau info->ifpi_rx[idx].arg = ret; 29764fa38985SSepherosa Ziehau info->ifpi_rx[idx].serializer = 29774fa38985SSepherosa Ziehau &ret->bnx_rx_ret_serialize; 29784fa38985SSepherosa Ziehau } 297939a8d43aSSepherosa Ziehau 29807dbaa833SSepherosa Ziehau if (ifp->if_flags & IFF_RUNNING) { 298139a8d43aSSepherosa Ziehau bnx_disable_intr(sc); 29827dbaa833SSepherosa Ziehau bnx_set_tick_cpuid(sc, TRUE); 29837dbaa833SSepherosa Ziehau } 298439a8d43aSSepherosa Ziehau } else { 29854fa38985SSepherosa Ziehau for (i = 0; i < sc->bnx_tx_ringcnt; ++i) { 29864fa38985SSepherosa Ziehau ifsq_set_cpuid(sc->bnx_tx_ring[i].bnx_ifsq, 29874fa38985SSepherosa Ziehau sc->bnx_tx_ring[i].bnx_tx_cpuid); 29884fa38985SSepherosa Ziehau } 29897dbaa833SSepherosa Ziehau if (ifp->if_flags & IFF_RUNNING) { 299039a8d43aSSepherosa Ziehau bnx_enable_intr(sc); 29917dbaa833SSepherosa Ziehau bnx_set_tick_cpuid(sc, FALSE); 29927dbaa833SSepherosa Ziehau } 299339a8d43aSSepherosa Ziehau } 299439a8d43aSSepherosa Ziehau } 299539a8d43aSSepherosa Ziehau 299639a8d43aSSepherosa Ziehau #endif /* IFPOLL_ENABLE */ 29976c8d8eccSSepherosa Ziehau 29986c8d8eccSSepherosa Ziehau static void 29996c8d8eccSSepherosa Ziehau bnx_intr_legacy(void *xsc) 30006c8d8eccSSepherosa Ziehau { 30016c8d8eccSSepherosa Ziehau struct bnx_softc *sc = xsc; 30024fa38985SSepherosa Ziehau struct bnx_rx_ret_ring *ret = &sc->bnx_rx_ret_ring[0]; 30036c8d8eccSSepherosa Ziehau 30044fa38985SSepherosa Ziehau if (ret->bnx_saved_status_tag == *ret->bnx_hw_status_tag) { 30056c8d8eccSSepherosa Ziehau uint32_t val; 30066c8d8eccSSepherosa Ziehau 30076c8d8eccSSepherosa Ziehau val = pci_read_config(sc->bnx_dev, BGE_PCI_PCISTATE, 4); 30086c8d8eccSSepherosa Ziehau if (val & BGE_PCISTAT_INTR_NOTACT) 30096c8d8eccSSepherosa Ziehau return; 30106c8d8eccSSepherosa Ziehau } 30116c8d8eccSSepherosa Ziehau 30126c8d8eccSSepherosa Ziehau /* 30136c8d8eccSSepherosa Ziehau * NOTE: 30146c8d8eccSSepherosa Ziehau * Interrupt will have to be disabled if tagged status 30156c8d8eccSSepherosa Ziehau * is used, else interrupt will always be asserted on 30166c8d8eccSSepherosa Ziehau * certain chips (at least on BCM5750 AX/BX). 30176c8d8eccSSepherosa Ziehau */ 30186c8d8eccSSepherosa Ziehau bnx_writembx(sc, BGE_MBX_IRQ0_LO, 1); 30196c8d8eccSSepherosa Ziehau 30206c8d8eccSSepherosa Ziehau bnx_intr(sc); 30216c8d8eccSSepherosa Ziehau } 30226c8d8eccSSepherosa Ziehau 30236c8d8eccSSepherosa Ziehau static void 302403cc99fdSSepherosa Ziehau bnx_msi(void *xsc) 30256c8d8eccSSepherosa Ziehau { 30266c8d8eccSSepherosa Ziehau bnx_intr(xsc); 30276c8d8eccSSepherosa Ziehau } 30286c8d8eccSSepherosa Ziehau 30296c8d8eccSSepherosa Ziehau static void 30306c8d8eccSSepherosa Ziehau bnx_intr(struct bnx_softc *sc) 30316c8d8eccSSepherosa Ziehau { 30326c8d8eccSSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if; 30334fa38985SSepherosa Ziehau struct bnx_rx_ret_ring *ret = &sc->bnx_rx_ret_ring[0]; 30346c8d8eccSSepherosa Ziehau 3035329f9016SSepherosa Ziehau ASSERT_SERIALIZED(&sc->bnx_main_serialize); 3036329f9016SSepherosa Ziehau 30374fa38985SSepherosa Ziehau ret->bnx_saved_status_tag = *ret->bnx_hw_status_tag; 30386c8d8eccSSepherosa Ziehau /* 30396c8d8eccSSepherosa Ziehau * Use a load fence to ensure that status_tag is saved 30406c8d8eccSSepherosa Ziehau * before rx_prod, tx_cons and status. 30416c8d8eccSSepherosa Ziehau */ 30426c8d8eccSSepherosa Ziehau cpu_lfence(); 30436c8d8eccSSepherosa Ziehau 3044*695a8586SSepherosa Ziehau bnx_handle_status(sc); 30456c8d8eccSSepherosa Ziehau 30466c8d8eccSSepherosa Ziehau if (ifp->if_flags & IFF_RUNNING) { 30474fa38985SSepherosa Ziehau struct bnx_tx_ring *txr = &sc->bnx_tx_ring[0]; 30483a16b7b8SSepherosa Ziehau uint16_t rx_prod, tx_cons; 30493a16b7b8SSepherosa Ziehau 3050329f9016SSepherosa Ziehau lwkt_serialize_enter(&ret->bnx_rx_ret_serialize); 30513a16b7b8SSepherosa Ziehau rx_prod = *ret->bnx_rx_considx; 3052beedf5beSSepherosa Ziehau if (ret->bnx_rx_saved_considx != rx_prod) 3053beedf5beSSepherosa Ziehau bnx_rxeof(ret, rx_prod, -1); 3054329f9016SSepherosa Ziehau lwkt_serialize_exit(&ret->bnx_rx_ret_serialize); 30556c8d8eccSSepherosa Ziehau 3056329f9016SSepherosa Ziehau lwkt_serialize_enter(&txr->bnx_tx_serialize); 3057329f9016SSepherosa Ziehau tx_cons = *txr->bnx_tx_considx; 305833a04907SSepherosa Ziehau if (txr->bnx_tx_saved_considx != tx_cons) 305933a04907SSepherosa Ziehau bnx_txeof(txr, tx_cons); 3060329f9016SSepherosa Ziehau lwkt_serialize_exit(&txr->bnx_tx_serialize); 30616c8d8eccSSepherosa Ziehau } 30626c8d8eccSSepherosa Ziehau 30634fa38985SSepherosa Ziehau bnx_writembx(sc, BGE_MBX_IRQ0_LO, ret->bnx_saved_status_tag << 24); 30646c8d8eccSSepherosa Ziehau } 30656c8d8eccSSepherosa Ziehau 30666c8d8eccSSepherosa Ziehau static void 3067*695a8586SSepherosa Ziehau bnx_msix_tx_status(void *xtxr) 3068*695a8586SSepherosa Ziehau { 3069*695a8586SSepherosa Ziehau struct bnx_tx_ring *txr = xtxr; 3070*695a8586SSepherosa Ziehau struct bnx_softc *sc = txr->bnx_sc; 3071*695a8586SSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if; 3072*695a8586SSepherosa Ziehau 3073*695a8586SSepherosa Ziehau ASSERT_SERIALIZED(&sc->bnx_main_serialize); 3074*695a8586SSepherosa Ziehau 3075*695a8586SSepherosa Ziehau txr->bnx_saved_status_tag = *txr->bnx_hw_status_tag; 3076*695a8586SSepherosa Ziehau /* 3077*695a8586SSepherosa Ziehau * Use a load fence to ensure that status_tag is saved 3078*695a8586SSepherosa Ziehau * before tx_cons and status. 3079*695a8586SSepherosa Ziehau */ 3080*695a8586SSepherosa Ziehau cpu_lfence(); 3081*695a8586SSepherosa Ziehau 3082*695a8586SSepherosa Ziehau bnx_handle_status(sc); 3083*695a8586SSepherosa Ziehau 3084*695a8586SSepherosa Ziehau if (ifp->if_flags & IFF_RUNNING) { 3085*695a8586SSepherosa Ziehau uint16_t tx_cons; 3086*695a8586SSepherosa Ziehau 3087*695a8586SSepherosa Ziehau lwkt_serialize_enter(&txr->bnx_tx_serialize); 3088*695a8586SSepherosa Ziehau tx_cons = *txr->bnx_tx_considx; 3089*695a8586SSepherosa Ziehau if (txr->bnx_tx_saved_considx != tx_cons) 3090*695a8586SSepherosa Ziehau bnx_txeof(txr, tx_cons); 3091*695a8586SSepherosa Ziehau lwkt_serialize_exit(&txr->bnx_tx_serialize); 3092*695a8586SSepherosa Ziehau } 3093*695a8586SSepherosa Ziehau 3094*695a8586SSepherosa Ziehau bnx_writembx(sc, BGE_MBX_IRQ0_LO, txr->bnx_saved_status_tag << 24); 3095*695a8586SSepherosa Ziehau } 3096*695a8586SSepherosa Ziehau 3097*695a8586SSepherosa Ziehau static void 3098*695a8586SSepherosa Ziehau bnx_msix_rx(void *xret) 3099*695a8586SSepherosa Ziehau { 3100*695a8586SSepherosa Ziehau struct bnx_rx_ret_ring *ret = xret; 3101*695a8586SSepherosa Ziehau uint16_t rx_prod; 3102*695a8586SSepherosa Ziehau 3103*695a8586SSepherosa Ziehau ASSERT_SERIALIZED(&ret->bnx_rx_ret_serialize); 3104*695a8586SSepherosa Ziehau 3105*695a8586SSepherosa Ziehau ret->bnx_saved_status_tag = *ret->bnx_hw_status_tag; 3106*695a8586SSepherosa Ziehau /* 3107*695a8586SSepherosa Ziehau * Use a load fence to ensure that status_tag is saved 3108*695a8586SSepherosa Ziehau * before rx_prod. 3109*695a8586SSepherosa Ziehau */ 3110*695a8586SSepherosa Ziehau cpu_lfence(); 3111*695a8586SSepherosa Ziehau 3112*695a8586SSepherosa Ziehau rx_prod = *ret->bnx_rx_considx; 3113*695a8586SSepherosa Ziehau if (ret->bnx_rx_saved_considx != rx_prod) 3114*695a8586SSepherosa Ziehau bnx_rxeof(ret, rx_prod, -1); 3115*695a8586SSepherosa Ziehau 3116*695a8586SSepherosa Ziehau bnx_writembx(ret->bnx_sc, ret->bnx_msix_mbx, 3117*695a8586SSepherosa Ziehau ret->bnx_saved_status_tag << 24); 3118*695a8586SSepherosa Ziehau } 3119*695a8586SSepherosa Ziehau 3120*695a8586SSepherosa Ziehau static void 3121*695a8586SSepherosa Ziehau bnx_msix_rxtx(void *xret) 3122*695a8586SSepherosa Ziehau { 3123*695a8586SSepherosa Ziehau struct bnx_rx_ret_ring *ret = xret; 3124*695a8586SSepherosa Ziehau struct bnx_tx_ring *txr = ret->bnx_txr; 3125*695a8586SSepherosa Ziehau uint16_t rx_prod, tx_cons; 3126*695a8586SSepherosa Ziehau 3127*695a8586SSepherosa Ziehau ASSERT_SERIALIZED(&ret->bnx_rx_ret_serialize); 3128*695a8586SSepherosa Ziehau 3129*695a8586SSepherosa Ziehau ret->bnx_saved_status_tag = *ret->bnx_hw_status_tag; 3130*695a8586SSepherosa Ziehau /* 3131*695a8586SSepherosa Ziehau * Use a load fence to ensure that status_tag is saved 3132*695a8586SSepherosa Ziehau * before rx_prod and tx_cons. 3133*695a8586SSepherosa Ziehau */ 3134*695a8586SSepherosa Ziehau cpu_lfence(); 3135*695a8586SSepherosa Ziehau 3136*695a8586SSepherosa Ziehau rx_prod = *ret->bnx_rx_considx; 3137*695a8586SSepherosa Ziehau if (ret->bnx_rx_saved_considx != rx_prod) 3138*695a8586SSepherosa Ziehau bnx_rxeof(ret, rx_prod, -1); 3139*695a8586SSepherosa Ziehau 3140*695a8586SSepherosa Ziehau lwkt_serialize_enter(&txr->bnx_tx_serialize); 3141*695a8586SSepherosa Ziehau tx_cons = *txr->bnx_tx_considx; 3142*695a8586SSepherosa Ziehau if (txr->bnx_tx_saved_considx != tx_cons) 3143*695a8586SSepherosa Ziehau bnx_txeof(txr, tx_cons); 3144*695a8586SSepherosa Ziehau lwkt_serialize_exit(&txr->bnx_tx_serialize); 3145*695a8586SSepherosa Ziehau 3146*695a8586SSepherosa Ziehau bnx_writembx(ret->bnx_sc, ret->bnx_msix_mbx, 3147*695a8586SSepherosa Ziehau ret->bnx_saved_status_tag << 24); 3148*695a8586SSepherosa Ziehau } 3149*695a8586SSepherosa Ziehau 3150*695a8586SSepherosa Ziehau static void 3151*695a8586SSepherosa Ziehau bnx_msix_status(void *xsc) 3152*695a8586SSepherosa Ziehau { 3153*695a8586SSepherosa Ziehau struct bnx_softc *sc = xsc; 3154*695a8586SSepherosa Ziehau 3155*695a8586SSepherosa Ziehau ASSERT_SERIALIZED(&sc->bnx_main_serialize); 3156*695a8586SSepherosa Ziehau 3157*695a8586SSepherosa Ziehau sc->bnx_saved_status_tag = *sc->bnx_hw_status_tag; 3158*695a8586SSepherosa Ziehau /* 3159*695a8586SSepherosa Ziehau * Use a load fence to ensure that status_tag is saved 3160*695a8586SSepherosa Ziehau * before status. 3161*695a8586SSepherosa Ziehau */ 3162*695a8586SSepherosa Ziehau cpu_lfence(); 3163*695a8586SSepherosa Ziehau 3164*695a8586SSepherosa Ziehau bnx_handle_status(sc); 3165*695a8586SSepherosa Ziehau 3166*695a8586SSepherosa Ziehau bnx_writembx(sc, BGE_MBX_IRQ0_LO, sc->bnx_saved_status_tag << 24); 3167*695a8586SSepherosa Ziehau } 3168*695a8586SSepherosa Ziehau 3169*695a8586SSepherosa Ziehau static void 31706c8d8eccSSepherosa Ziehau bnx_tick(void *xsc) 31716c8d8eccSSepherosa Ziehau { 31726c8d8eccSSepherosa Ziehau struct bnx_softc *sc = xsc; 31736c8d8eccSSepherosa Ziehau 3174329f9016SSepherosa Ziehau lwkt_serialize_enter(&sc->bnx_main_serialize); 31756c8d8eccSSepherosa Ziehau 31766c8d8eccSSepherosa Ziehau bnx_stats_update_regs(sc); 31776c8d8eccSSepherosa Ziehau 31786c8d8eccSSepherosa Ziehau if (sc->bnx_flags & BNX_FLAG_TBI) { 31796c8d8eccSSepherosa Ziehau /* 31806c8d8eccSSepherosa Ziehau * Since in TBI mode auto-polling can't be used we should poll 31816c8d8eccSSepherosa Ziehau * link status manually. Here we register pending link event 31826c8d8eccSSepherosa Ziehau * and trigger interrupt. 31836c8d8eccSSepherosa Ziehau */ 31846c8d8eccSSepherosa Ziehau sc->bnx_link_evt++; 31856c8d8eccSSepherosa Ziehau BNX_SETBIT(sc, BGE_HCC_MODE, BGE_HCCMODE_COAL_NOW); 31866c8d8eccSSepherosa Ziehau } else if (!sc->bnx_link) { 31876c8d8eccSSepherosa Ziehau mii_tick(device_get_softc(sc->bnx_miibus)); 31886c8d8eccSSepherosa Ziehau } 31896c8d8eccSSepherosa Ziehau 31907dbaa833SSepherosa Ziehau callout_reset_bycpu(&sc->bnx_tick_timer, hz, bnx_tick, sc, 31917dbaa833SSepherosa Ziehau sc->bnx_tick_cpuid); 31926c8d8eccSSepherosa Ziehau 3193329f9016SSepherosa Ziehau lwkt_serialize_exit(&sc->bnx_main_serialize); 31946c8d8eccSSepherosa Ziehau } 31956c8d8eccSSepherosa Ziehau 31966c8d8eccSSepherosa Ziehau static void 31976c8d8eccSSepherosa Ziehau bnx_stats_update_regs(struct bnx_softc *sc) 31986c8d8eccSSepherosa Ziehau { 31996c8d8eccSSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if; 32006c8d8eccSSepherosa Ziehau struct bge_mac_stats_regs stats; 3201*695a8586SSepherosa Ziehau uint32_t *s, val; 32026c8d8eccSSepherosa Ziehau int i; 32036c8d8eccSSepherosa Ziehau 32046c8d8eccSSepherosa Ziehau s = (uint32_t *)&stats; 32056c8d8eccSSepherosa Ziehau for (i = 0; i < sizeof(struct bge_mac_stats_regs); i += 4) { 32066c8d8eccSSepherosa Ziehau *s = CSR_READ_4(sc, BGE_RX_STATS + i); 32076c8d8eccSSepherosa Ziehau s++; 32086c8d8eccSSepherosa Ziehau } 32096c8d8eccSSepherosa Ziehau 3210d40991efSSepherosa Ziehau IFNET_STAT_SET(ifp, collisions, 32116c8d8eccSSepherosa Ziehau (stats.dot3StatsSingleCollisionFrames + 32126c8d8eccSSepherosa Ziehau stats.dot3StatsMultipleCollisionFrames + 32136c8d8eccSSepherosa Ziehau stats.dot3StatsExcessiveCollisions + 3214d40991efSSepherosa Ziehau stats.dot3StatsLateCollisions)); 3215*695a8586SSepherosa Ziehau 3216*695a8586SSepherosa Ziehau val = CSR_READ_4(sc, BGE_RXLP_LOCSTAT_OUT_OF_BDS); 3217*695a8586SSepherosa Ziehau sc->bnx_norxbds += val; 32186c8d8eccSSepherosa Ziehau } 32196c8d8eccSSepherosa Ziehau 32206c8d8eccSSepherosa Ziehau /* 32216c8d8eccSSepherosa Ziehau * Encapsulate an mbuf chain in the tx ring by coupling the mbuf data 32226c8d8eccSSepherosa Ziehau * pointers to descriptors. 32236c8d8eccSSepherosa Ziehau */ 32246c8d8eccSSepherosa Ziehau static int 322533a04907SSepherosa Ziehau bnx_encap(struct bnx_tx_ring *txr, struct mbuf **m_head0, uint32_t *txidx, 3226c9b7f592SSepherosa Ziehau int *segs_used) 32276c8d8eccSSepherosa Ziehau { 32286c8d8eccSSepherosa Ziehau struct bge_tx_bd *d = NULL; 322966deb1c1SSepherosa Ziehau uint16_t csum_flags = 0, vlan_tag = 0, mss = 0; 32306c8d8eccSSepherosa Ziehau bus_dma_segment_t segs[BNX_NSEG_NEW]; 32316c8d8eccSSepherosa Ziehau bus_dmamap_t map; 32326c8d8eccSSepherosa Ziehau int error, maxsegs, nsegs, idx, i; 32336c8d8eccSSepherosa Ziehau struct mbuf *m_head = *m_head0, *m_new; 32346c8d8eccSSepherosa Ziehau 323566deb1c1SSepherosa Ziehau if (m_head->m_pkthdr.csum_flags & CSUM_TSO) { 323666deb1c1SSepherosa Ziehau #ifdef BNX_TSO_DEBUG 323766deb1c1SSepherosa Ziehau int tso_nsegs; 323866deb1c1SSepherosa Ziehau #endif 323966deb1c1SSepherosa Ziehau 324033a04907SSepherosa Ziehau error = bnx_setup_tso(txr, m_head0, &mss, &csum_flags); 324166deb1c1SSepherosa Ziehau if (error) 324266deb1c1SSepherosa Ziehau return error; 324366deb1c1SSepherosa Ziehau m_head = *m_head0; 324466deb1c1SSepherosa Ziehau 324566deb1c1SSepherosa Ziehau #ifdef BNX_TSO_DEBUG 3246f0336d39SSepherosa Ziehau tso_nsegs = (m_head->m_pkthdr.len / 3247f0336d39SSepherosa Ziehau m_head->m_pkthdr.tso_segsz) - 1; 324866deb1c1SSepherosa Ziehau if (tso_nsegs > (BNX_TSO_NSTATS - 1)) 324966deb1c1SSepherosa Ziehau tso_nsegs = BNX_TSO_NSTATS - 1; 325066deb1c1SSepherosa Ziehau else if (tso_nsegs < 0) 325166deb1c1SSepherosa Ziehau tso_nsegs = 0; 32525a0c3c3aSSascha Wildner txr->bnx_sc->bnx_tsosegs[tso_nsegs]++; 325366deb1c1SSepherosa Ziehau #endif 325466deb1c1SSepherosa Ziehau } else if (m_head->m_pkthdr.csum_flags & BNX_CSUM_FEATURES) { 32556c8d8eccSSepherosa Ziehau if (m_head->m_pkthdr.csum_flags & CSUM_IP) 32566c8d8eccSSepherosa Ziehau csum_flags |= BGE_TXBDFLAG_IP_CSUM; 32576c8d8eccSSepherosa Ziehau if (m_head->m_pkthdr.csum_flags & (CSUM_TCP | CSUM_UDP)) 32586c8d8eccSSepherosa Ziehau csum_flags |= BGE_TXBDFLAG_TCP_UDP_CSUM; 32596c8d8eccSSepherosa Ziehau if (m_head->m_flags & M_LASTFRAG) 32606c8d8eccSSepherosa Ziehau csum_flags |= BGE_TXBDFLAG_IP_FRAG_END; 32616c8d8eccSSepherosa Ziehau else if (m_head->m_flags & M_FRAG) 32626c8d8eccSSepherosa Ziehau csum_flags |= BGE_TXBDFLAG_IP_FRAG; 32636c8d8eccSSepherosa Ziehau } 326466deb1c1SSepherosa Ziehau if (m_head->m_flags & M_VLANTAG) { 326566deb1c1SSepherosa Ziehau csum_flags |= BGE_TXBDFLAG_VLAN_TAG; 326666deb1c1SSepherosa Ziehau vlan_tag = m_head->m_pkthdr.ether_vlantag; 326766deb1c1SSepherosa Ziehau } 32686c8d8eccSSepherosa Ziehau 32696c8d8eccSSepherosa Ziehau idx = *txidx; 3270fa4b1067SSepherosa Ziehau map = txr->bnx_tx_buf[idx].bnx_tx_dmamap; 32716c8d8eccSSepherosa Ziehau 3272fa639b88SSepherosa Ziehau maxsegs = (BGE_TX_RING_CNT - txr->bnx_tx_cnt) - BNX_NSEG_RSVD; 32736c8d8eccSSepherosa Ziehau KASSERT(maxsegs >= BNX_NSEG_SPARE, 32746c8d8eccSSepherosa Ziehau ("not enough segments %d", maxsegs)); 32756c8d8eccSSepherosa Ziehau 32766c8d8eccSSepherosa Ziehau if (maxsegs > BNX_NSEG_NEW) 32776c8d8eccSSepherosa Ziehau maxsegs = BNX_NSEG_NEW; 32786c8d8eccSSepherosa Ziehau 32796c8d8eccSSepherosa Ziehau /* 32806c8d8eccSSepherosa Ziehau * Pad outbound frame to BGE_MIN_FRAMELEN for an unusual reason. 32816c8d8eccSSepherosa Ziehau * The bge hardware will pad out Tx runts to BGE_MIN_FRAMELEN, 32826c8d8eccSSepherosa Ziehau * but when such padded frames employ the bge IP/TCP checksum 32836c8d8eccSSepherosa Ziehau * offload, the hardware checksum assist gives incorrect results 32846c8d8eccSSepherosa Ziehau * (possibly from incorporating its own padding into the UDP/TCP 32856c8d8eccSSepherosa Ziehau * checksum; who knows). If we pad such runts with zeros, the 32866c8d8eccSSepherosa Ziehau * onboard checksum comes out correct. 32876c8d8eccSSepherosa Ziehau */ 32886c8d8eccSSepherosa Ziehau if ((csum_flags & BGE_TXBDFLAG_TCP_UDP_CSUM) && 32896c8d8eccSSepherosa Ziehau m_head->m_pkthdr.len < BNX_MIN_FRAMELEN) { 32906c8d8eccSSepherosa Ziehau error = m_devpad(m_head, BNX_MIN_FRAMELEN); 32916c8d8eccSSepherosa Ziehau if (error) 32926c8d8eccSSepherosa Ziehau goto back; 32936c8d8eccSSepherosa Ziehau } 32946c8d8eccSSepherosa Ziehau 329579a64343SSepherosa Ziehau if ((txr->bnx_tx_flags & BNX_TX_FLAG_SHORTDMA) && 329633a04907SSepherosa Ziehau m_head->m_next != NULL) { 32976c8d8eccSSepherosa Ziehau m_new = bnx_defrag_shortdma(m_head); 32986c8d8eccSSepherosa Ziehau if (m_new == NULL) { 32996c8d8eccSSepherosa Ziehau error = ENOBUFS; 33006c8d8eccSSepherosa Ziehau goto back; 33016c8d8eccSSepherosa Ziehau } 33026c8d8eccSSepherosa Ziehau *m_head0 = m_head = m_new; 33036c8d8eccSSepherosa Ziehau } 330466deb1c1SSepherosa Ziehau if ((m_head->m_pkthdr.csum_flags & CSUM_TSO) == 0 && 3305aad4de2bSSepherosa Ziehau (txr->bnx_tx_flags & BNX_TX_FLAG_FORCE_DEFRAG) && 3306aad4de2bSSepherosa Ziehau m_head->m_next != NULL) { 33076c8d8eccSSepherosa Ziehau /* 33086c8d8eccSSepherosa Ziehau * Forcefully defragment mbuf chain to overcome hardware 33096c8d8eccSSepherosa Ziehau * limitation which only support a single outstanding 33106c8d8eccSSepherosa Ziehau * DMA read operation. If it fails, keep moving on using 33116c8d8eccSSepherosa Ziehau * the original mbuf chain. 33126c8d8eccSSepherosa Ziehau */ 33136c8d8eccSSepherosa Ziehau m_new = m_defrag(m_head, MB_DONTWAIT); 33146c8d8eccSSepherosa Ziehau if (m_new != NULL) 33156c8d8eccSSepherosa Ziehau *m_head0 = m_head = m_new; 33166c8d8eccSSepherosa Ziehau } 33176c8d8eccSSepherosa Ziehau 331833a04907SSepherosa Ziehau error = bus_dmamap_load_mbuf_defrag(txr->bnx_tx_mtag, map, 33196c8d8eccSSepherosa Ziehau m_head0, segs, maxsegs, &nsegs, BUS_DMA_NOWAIT); 33206c8d8eccSSepherosa Ziehau if (error) 33216c8d8eccSSepherosa Ziehau goto back; 3322c9b7f592SSepherosa Ziehau *segs_used += nsegs; 33236c8d8eccSSepherosa Ziehau 33246c8d8eccSSepherosa Ziehau m_head = *m_head0; 332533a04907SSepherosa Ziehau bus_dmamap_sync(txr->bnx_tx_mtag, map, BUS_DMASYNC_PREWRITE); 33266c8d8eccSSepherosa Ziehau 33276c8d8eccSSepherosa Ziehau for (i = 0; ; i++) { 332833a04907SSepherosa Ziehau d = &txr->bnx_tx_ring[idx]; 33296c8d8eccSSepherosa Ziehau 33306c8d8eccSSepherosa Ziehau d->bge_addr.bge_addr_lo = BGE_ADDR_LO(segs[i].ds_addr); 33316c8d8eccSSepherosa Ziehau d->bge_addr.bge_addr_hi = BGE_ADDR_HI(segs[i].ds_addr); 33326c8d8eccSSepherosa Ziehau d->bge_len = segs[i].ds_len; 33336c8d8eccSSepherosa Ziehau d->bge_flags = csum_flags; 333466deb1c1SSepherosa Ziehau d->bge_vlan_tag = vlan_tag; 333566deb1c1SSepherosa Ziehau d->bge_mss = mss; 33366c8d8eccSSepherosa Ziehau 33376c8d8eccSSepherosa Ziehau if (i == nsegs - 1) 33386c8d8eccSSepherosa Ziehau break; 33396c8d8eccSSepherosa Ziehau BNX_INC(idx, BGE_TX_RING_CNT); 33406c8d8eccSSepherosa Ziehau } 33416c8d8eccSSepherosa Ziehau /* Mark the last segment as end of packet... */ 33426c8d8eccSSepherosa Ziehau d->bge_flags |= BGE_TXBDFLAG_END; 33436c8d8eccSSepherosa Ziehau 33446c8d8eccSSepherosa Ziehau /* 33456c8d8eccSSepherosa Ziehau * Insure that the map for this transmission is placed at 33466c8d8eccSSepherosa Ziehau * the array index of the last descriptor in this chain. 33476c8d8eccSSepherosa Ziehau */ 3348fa4b1067SSepherosa Ziehau txr->bnx_tx_buf[*txidx].bnx_tx_dmamap = txr->bnx_tx_buf[idx].bnx_tx_dmamap; 3349fa4b1067SSepherosa Ziehau txr->bnx_tx_buf[idx].bnx_tx_dmamap = map; 3350fa4b1067SSepherosa Ziehau txr->bnx_tx_buf[idx].bnx_tx_mbuf = m_head; 3351fa639b88SSepherosa Ziehau txr->bnx_tx_cnt += nsegs; 33526c8d8eccSSepherosa Ziehau 33536c8d8eccSSepherosa Ziehau BNX_INC(idx, BGE_TX_RING_CNT); 33546c8d8eccSSepherosa Ziehau *txidx = idx; 33556c8d8eccSSepherosa Ziehau back: 33566c8d8eccSSepherosa Ziehau if (error) { 33576c8d8eccSSepherosa Ziehau m_freem(*m_head0); 33586c8d8eccSSepherosa Ziehau *m_head0 = NULL; 33596c8d8eccSSepherosa Ziehau } 33606c8d8eccSSepherosa Ziehau return error; 33616c8d8eccSSepherosa Ziehau } 33626c8d8eccSSepherosa Ziehau 33636c8d8eccSSepherosa Ziehau /* 33646c8d8eccSSepherosa Ziehau * Main transmit routine. To avoid having to do mbuf copies, we put pointers 33656c8d8eccSSepherosa Ziehau * to the mbuf data regions directly in the transmit descriptors. 33666c8d8eccSSepherosa Ziehau */ 33676c8d8eccSSepherosa Ziehau static void 3368f0a26983SSepherosa Ziehau bnx_start(struct ifnet *ifp, struct ifaltq_subque *ifsq) 33696c8d8eccSSepherosa Ziehau { 33703397dea6SSepherosa Ziehau struct bnx_tx_ring *txr = ifsq_get_priv(ifsq); 33716c8d8eccSSepherosa Ziehau struct mbuf *m_head = NULL; 33726c8d8eccSSepherosa Ziehau uint32_t prodidx; 3373c9b7f592SSepherosa Ziehau int nsegs = 0; 33746c8d8eccSSepherosa Ziehau 33753397dea6SSepherosa Ziehau KKASSERT(txr->bnx_ifsq == ifsq); 3376329f9016SSepherosa Ziehau ASSERT_SERIALIZED(&txr->bnx_tx_serialize); 3377f0a26983SSepherosa Ziehau 33783397dea6SSepherosa Ziehau if ((ifp->if_flags & IFF_RUNNING) == 0 || ifsq_is_oactive(ifsq)) 33796c8d8eccSSepherosa Ziehau return; 33806c8d8eccSSepherosa Ziehau 338133a04907SSepherosa Ziehau prodidx = txr->bnx_tx_prodidx; 33826c8d8eccSSepherosa Ziehau 3383fa4b1067SSepherosa Ziehau while (txr->bnx_tx_buf[prodidx].bnx_tx_mbuf == NULL) { 33846c8d8eccSSepherosa Ziehau /* 33856c8d8eccSSepherosa Ziehau * Sanity check: avoid coming within BGE_NSEG_RSVD 33866c8d8eccSSepherosa Ziehau * descriptors of the end of the ring. Also make 33876c8d8eccSSepherosa Ziehau * sure there are BGE_NSEG_SPARE descriptors for 3388a1bd58c9SSepherosa Ziehau * jumbo buffers' or TSO segments' defragmentation. 33896c8d8eccSSepherosa Ziehau */ 3390fa639b88SSepherosa Ziehau if ((BGE_TX_RING_CNT - txr->bnx_tx_cnt) < 33916c8d8eccSSepherosa Ziehau (BNX_NSEG_RSVD + BNX_NSEG_SPARE)) { 33923397dea6SSepherosa Ziehau ifsq_set_oactive(ifsq); 33936c8d8eccSSepherosa Ziehau break; 33946c8d8eccSSepherosa Ziehau } 33956c8d8eccSSepherosa Ziehau 33963397dea6SSepherosa Ziehau m_head = ifsq_dequeue(ifsq, NULL); 3397a1bd58c9SSepherosa Ziehau if (m_head == NULL) 3398a1bd58c9SSepherosa Ziehau break; 3399a1bd58c9SSepherosa Ziehau 34006c8d8eccSSepherosa Ziehau /* 34016c8d8eccSSepherosa Ziehau * Pack the data into the transmit ring. If we 34026c8d8eccSSepherosa Ziehau * don't have room, set the OACTIVE flag and wait 34036c8d8eccSSepherosa Ziehau * for the NIC to drain the ring. 34046c8d8eccSSepherosa Ziehau */ 340533a04907SSepherosa Ziehau if (bnx_encap(txr, &m_head, &prodidx, &nsegs)) { 34063397dea6SSepherosa Ziehau ifsq_set_oactive(ifsq); 3407d40991efSSepherosa Ziehau IFNET_STAT_INC(ifp, oerrors, 1); 34086c8d8eccSSepherosa Ziehau break; 34096c8d8eccSSepherosa Ziehau } 34106c8d8eccSSepherosa Ziehau 341133a04907SSepherosa Ziehau if (nsegs >= txr->bnx_tx_wreg) { 34126c8d8eccSSepherosa Ziehau /* Transmit */ 34138bd43d5dSSepherosa Ziehau bnx_writembx(txr->bnx_sc, txr->bnx_tx_mbx, prodidx); 3414c9b7f592SSepherosa Ziehau nsegs = 0; 3415c9b7f592SSepherosa Ziehau } 34166c8d8eccSSepherosa Ziehau 3417c9b7f592SSepherosa Ziehau ETHER_BPF_MTAP(ifp, m_head); 34186c8d8eccSSepherosa Ziehau 34196c8d8eccSSepherosa Ziehau /* 34206c8d8eccSSepherosa Ziehau * Set a timeout in case the chip goes out to lunch. 34216c8d8eccSSepherosa Ziehau */ 34223397dea6SSepherosa Ziehau txr->bnx_tx_watchdog.wd_timer = 5; 34236c8d8eccSSepherosa Ziehau } 34246c8d8eccSSepherosa Ziehau 3425c9b7f592SSepherosa Ziehau if (nsegs > 0) { 3426c9b7f592SSepherosa Ziehau /* Transmit */ 34278bd43d5dSSepherosa Ziehau bnx_writembx(txr->bnx_sc, txr->bnx_tx_mbx, prodidx); 3428c9b7f592SSepherosa Ziehau } 342933a04907SSepherosa Ziehau txr->bnx_tx_prodidx = prodidx; 3430c9b7f592SSepherosa Ziehau } 3431c9b7f592SSepherosa Ziehau 34326c8d8eccSSepherosa Ziehau static void 34336c8d8eccSSepherosa Ziehau bnx_init(void *xsc) 34346c8d8eccSSepherosa Ziehau { 34356c8d8eccSSepherosa Ziehau struct bnx_softc *sc = xsc; 34366c8d8eccSSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if; 34376c8d8eccSSepherosa Ziehau uint16_t *m; 34386c8d8eccSSepherosa Ziehau uint32_t mode; 343933a04907SSepherosa Ziehau int i; 34407dbaa833SSepherosa Ziehau boolean_t polling; 34416c8d8eccSSepherosa Ziehau 3442329f9016SSepherosa Ziehau ASSERT_IFNET_SERIALIZED_ALL(ifp); 34436c8d8eccSSepherosa Ziehau 34446c8d8eccSSepherosa Ziehau /* Cancel pending I/O and flush buffers. */ 34456c8d8eccSSepherosa Ziehau bnx_stop(sc); 34466c8d8eccSSepherosa Ziehau bnx_reset(sc); 34476c8d8eccSSepherosa Ziehau bnx_chipinit(sc); 34486c8d8eccSSepherosa Ziehau 34496c8d8eccSSepherosa Ziehau /* 34506c8d8eccSSepherosa Ziehau * Init the various state machines, ring 34516c8d8eccSSepherosa Ziehau * control blocks and firmware. 34526c8d8eccSSepherosa Ziehau */ 34536c8d8eccSSepherosa Ziehau if (bnx_blockinit(sc)) { 34546c8d8eccSSepherosa Ziehau if_printf(ifp, "initialization failure\n"); 34556c8d8eccSSepherosa Ziehau bnx_stop(sc); 34566c8d8eccSSepherosa Ziehau return; 34576c8d8eccSSepherosa Ziehau } 34586c8d8eccSSepherosa Ziehau 34596c8d8eccSSepherosa Ziehau /* Specify MTU. */ 34606c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_RX_MTU, ifp->if_mtu + 34616c8d8eccSSepherosa Ziehau ETHER_HDR_LEN + ETHER_CRC_LEN + EVL_ENCAPLEN); 34626c8d8eccSSepherosa Ziehau 34636c8d8eccSSepherosa Ziehau /* Load our MAC address. */ 34646c8d8eccSSepherosa Ziehau m = (uint16_t *)&sc->arpcom.ac_enaddr[0]; 34656c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_MAC_ADDR1_LO, htons(m[0])); 34666c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_MAC_ADDR1_HI, (htons(m[1]) << 16) | htons(m[2])); 34676c8d8eccSSepherosa Ziehau 34686c8d8eccSSepherosa Ziehau /* Enable or disable promiscuous mode as needed. */ 34696c8d8eccSSepherosa Ziehau bnx_setpromisc(sc); 34706c8d8eccSSepherosa Ziehau 34716c8d8eccSSepherosa Ziehau /* Program multicast filter. */ 34726c8d8eccSSepherosa Ziehau bnx_setmulti(sc); 34736c8d8eccSSepherosa Ziehau 34746c8d8eccSSepherosa Ziehau /* Init RX ring. */ 3475beedf5beSSepherosa Ziehau if (bnx_init_rx_ring_std(&sc->bnx_rx_std_ring)) { 34766c8d8eccSSepherosa Ziehau if_printf(ifp, "RX ring initialization failed\n"); 34776c8d8eccSSepherosa Ziehau bnx_stop(sc); 34786c8d8eccSSepherosa Ziehau return; 34796c8d8eccSSepherosa Ziehau } 34806c8d8eccSSepherosa Ziehau 34816c8d8eccSSepherosa Ziehau /* Init jumbo RX ring. */ 34826c8d8eccSSepherosa Ziehau if (ifp->if_mtu > (ETHERMTU + ETHER_HDR_LEN + ETHER_CRC_LEN)) { 34836c8d8eccSSepherosa Ziehau if (bnx_init_rx_ring_jumbo(sc)) { 34846c8d8eccSSepherosa Ziehau if_printf(ifp, "Jumbo RX ring initialization failed\n"); 34856c8d8eccSSepherosa Ziehau bnx_stop(sc); 34866c8d8eccSSepherosa Ziehau return; 34876c8d8eccSSepherosa Ziehau } 34886c8d8eccSSepherosa Ziehau } 34896c8d8eccSSepherosa Ziehau 34906c8d8eccSSepherosa Ziehau /* Init our RX return ring index */ 3491841cdf08SSepherosa Ziehau for (i = 0; i < sc->bnx_rx_retcnt; ++i) { 3492841cdf08SSepherosa Ziehau struct bnx_rx_ret_ring *ret = &sc->bnx_rx_ret_ring[i]; 3493841cdf08SSepherosa Ziehau 3494841cdf08SSepherosa Ziehau ret->bnx_rx_saved_considx = 0; 3495841cdf08SSepherosa Ziehau ret->bnx_rx_cnt = 0; 3496841cdf08SSepherosa Ziehau } 34976c8d8eccSSepherosa Ziehau 34986c8d8eccSSepherosa Ziehau /* Init TX ring. */ 349933a04907SSepherosa Ziehau for (i = 0; i < sc->bnx_tx_ringcnt; ++i) 350033a04907SSepherosa Ziehau bnx_init_tx_ring(&sc->bnx_tx_ring[i]); 35016c8d8eccSSepherosa Ziehau 35026c8d8eccSSepherosa Ziehau /* Enable TX MAC state machine lockup fix. */ 35036c8d8eccSSepherosa Ziehau mode = CSR_READ_4(sc, BGE_TX_MODE); 35046c8d8eccSSepherosa Ziehau mode |= BGE_TXMODE_MBUF_LOCKUP_FIX; 3505b96cbbb6SSepherosa Ziehau if (sc->bnx_asicrev == BGE_ASICREV_BCM5720 || 3506b96cbbb6SSepherosa Ziehau sc->bnx_asicrev == BGE_ASICREV_BCM5762) { 35076c8d8eccSSepherosa Ziehau mode &= ~(BGE_TXMODE_JMB_FRM_LEN | BGE_TXMODE_CNT_DN_MODE); 35086c8d8eccSSepherosa Ziehau mode |= CSR_READ_4(sc, BGE_TX_MODE) & 35096c8d8eccSSepherosa Ziehau (BGE_TXMODE_JMB_FRM_LEN | BGE_TXMODE_CNT_DN_MODE); 35106c8d8eccSSepherosa Ziehau } 35116c8d8eccSSepherosa Ziehau /* Turn on transmitter */ 35126c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_TX_MODE, mode | BGE_TXMODE_ENABLE); 35136c8d8eccSSepherosa Ziehau 3514*695a8586SSepherosa Ziehau /* Initialize RSS */ 3515*695a8586SSepherosa Ziehau mode = BGE_RXMODE_ENABLE; 3516*695a8586SSepherosa Ziehau if (BNX_RSS_ENABLED(sc)) { 3517*695a8586SSepherosa Ziehau bnx_init_rss(sc); 3518*695a8586SSepherosa Ziehau mode |= BGE_RXMODE_RSS_ENABLE | 3519*695a8586SSepherosa Ziehau BGE_RXMODE_RSS_HASH_MASK_BITS | 3520*695a8586SSepherosa Ziehau BGE_RXMODE_RSS_IPV4_HASH | 3521*695a8586SSepherosa Ziehau BGE_RXMODE_RSS_TCP_IPV4_HASH; 3522*695a8586SSepherosa Ziehau } 35236c8d8eccSSepherosa Ziehau /* Turn on receiver */ 3524*695a8586SSepherosa Ziehau BNX_SETBIT(sc, BGE_RX_MODE, mode); 35256c8d8eccSSepherosa Ziehau 35266c8d8eccSSepherosa Ziehau /* 35276c8d8eccSSepherosa Ziehau * Set the number of good frames to receive after RX MBUF 35286c8d8eccSSepherosa Ziehau * Low Watermark has been reached. After the RX MAC receives 35296c8d8eccSSepherosa Ziehau * this number of frames, it will drop subsequent incoming 35306c8d8eccSSepherosa Ziehau * frames until the MBUF High Watermark is reached. 35316c8d8eccSSepherosa Ziehau */ 3532bcb29629SSepherosa Ziehau if (BNX_IS_57765_FAMILY(sc)) 35336c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_MAX_RX_FRAME_LOWAT, 1); 35346c8d8eccSSepherosa Ziehau else 35356c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_MAX_RX_FRAME_LOWAT, 2); 35366c8d8eccSSepherosa Ziehau 3537*695a8586SSepherosa Ziehau if (sc->bnx_intr_type == PCI_INTR_TYPE_MSI || 3538*695a8586SSepherosa Ziehau sc->bnx_intr_type == PCI_INTR_TYPE_MSIX) { 35396c8d8eccSSepherosa Ziehau if (bootverbose) { 35406c8d8eccSSepherosa Ziehau if_printf(ifp, "MSI_MODE: %#x\n", 35416c8d8eccSSepherosa Ziehau CSR_READ_4(sc, BGE_MSI_MODE)); 35426c8d8eccSSepherosa Ziehau } 35436c8d8eccSSepherosa Ziehau } 35446c8d8eccSSepherosa Ziehau 35456c8d8eccSSepherosa Ziehau /* Tell firmware we're alive. */ 35466c8d8eccSSepherosa Ziehau BNX_SETBIT(sc, BGE_MODE_CTL, BGE_MODECTL_STACKUP); 35476c8d8eccSSepherosa Ziehau 35486c8d8eccSSepherosa Ziehau /* Enable host interrupts if polling(4) is not enabled. */ 35496c8d8eccSSepherosa Ziehau PCI_SETBIT(sc->bnx_dev, BGE_PCI_MISC_CTL, BGE_PCIMISCCTL_CLEAR_INTA, 4); 35507dbaa833SSepherosa Ziehau 35517dbaa833SSepherosa Ziehau polling = FALSE; 355239a8d43aSSepherosa Ziehau #ifdef IFPOLL_ENABLE 355339a8d43aSSepherosa Ziehau if (ifp->if_flags & IFF_NPOLLING) 35547dbaa833SSepherosa Ziehau polling = TRUE; 35557dbaa833SSepherosa Ziehau #endif 35567dbaa833SSepherosa Ziehau if (polling) 35576c8d8eccSSepherosa Ziehau bnx_disable_intr(sc); 35586c8d8eccSSepherosa Ziehau else 35596c8d8eccSSepherosa Ziehau bnx_enable_intr(sc); 35607dbaa833SSepherosa Ziehau bnx_set_tick_cpuid(sc, polling); 35616c8d8eccSSepherosa Ziehau 35626c8d8eccSSepherosa Ziehau bnx_ifmedia_upd(ifp); 35636c8d8eccSSepherosa Ziehau 35646c8d8eccSSepherosa Ziehau ifp->if_flags |= IFF_RUNNING; 35653397dea6SSepherosa Ziehau for (i = 0; i < sc->bnx_tx_ringcnt; ++i) { 35663397dea6SSepherosa Ziehau struct bnx_tx_ring *txr = &sc->bnx_tx_ring[i]; 35673397dea6SSepherosa Ziehau 35683397dea6SSepherosa Ziehau ifsq_clr_oactive(txr->bnx_ifsq); 35693397dea6SSepherosa Ziehau ifsq_watchdog_start(&txr->bnx_tx_watchdog); 35703397dea6SSepherosa Ziehau } 35716c8d8eccSSepherosa Ziehau 35727dbaa833SSepherosa Ziehau callout_reset_bycpu(&sc->bnx_tick_timer, hz, bnx_tick, sc, 35737dbaa833SSepherosa Ziehau sc->bnx_tick_cpuid); 35746c8d8eccSSepherosa Ziehau } 35756c8d8eccSSepherosa Ziehau 35766c8d8eccSSepherosa Ziehau /* 35776c8d8eccSSepherosa Ziehau * Set media options. 35786c8d8eccSSepherosa Ziehau */ 35796c8d8eccSSepherosa Ziehau static int 35806c8d8eccSSepherosa Ziehau bnx_ifmedia_upd(struct ifnet *ifp) 35816c8d8eccSSepherosa Ziehau { 35826c8d8eccSSepherosa Ziehau struct bnx_softc *sc = ifp->if_softc; 35836c8d8eccSSepherosa Ziehau 35846c8d8eccSSepherosa Ziehau /* If this is a 1000baseX NIC, enable the TBI port. */ 35856c8d8eccSSepherosa Ziehau if (sc->bnx_flags & BNX_FLAG_TBI) { 35866c8d8eccSSepherosa Ziehau struct ifmedia *ifm = &sc->bnx_ifmedia; 35876c8d8eccSSepherosa Ziehau 35886c8d8eccSSepherosa Ziehau if (IFM_TYPE(ifm->ifm_media) != IFM_ETHER) 35896c8d8eccSSepherosa Ziehau return(EINVAL); 35906c8d8eccSSepherosa Ziehau 35916c8d8eccSSepherosa Ziehau switch(IFM_SUBTYPE(ifm->ifm_media)) { 35926c8d8eccSSepherosa Ziehau case IFM_AUTO: 35936c8d8eccSSepherosa Ziehau break; 35946c8d8eccSSepherosa Ziehau 35956c8d8eccSSepherosa Ziehau case IFM_1000_SX: 35966c8d8eccSSepherosa Ziehau if ((ifm->ifm_media & IFM_GMASK) == IFM_FDX) { 35976c8d8eccSSepherosa Ziehau BNX_CLRBIT(sc, BGE_MAC_MODE, 35986c8d8eccSSepherosa Ziehau BGE_MACMODE_HALF_DUPLEX); 35996c8d8eccSSepherosa Ziehau } else { 36006c8d8eccSSepherosa Ziehau BNX_SETBIT(sc, BGE_MAC_MODE, 36016c8d8eccSSepherosa Ziehau BGE_MACMODE_HALF_DUPLEX); 36026c8d8eccSSepherosa Ziehau } 36036c8d8eccSSepherosa Ziehau break; 36046c8d8eccSSepherosa Ziehau default: 36056c8d8eccSSepherosa Ziehau return(EINVAL); 36066c8d8eccSSepherosa Ziehau } 36076c8d8eccSSepherosa Ziehau } else { 36086c8d8eccSSepherosa Ziehau struct mii_data *mii = device_get_softc(sc->bnx_miibus); 36096c8d8eccSSepherosa Ziehau 36106c8d8eccSSepherosa Ziehau sc->bnx_link_evt++; 36116c8d8eccSSepherosa Ziehau sc->bnx_link = 0; 36126c8d8eccSSepherosa Ziehau if (mii->mii_instance) { 36136c8d8eccSSepherosa Ziehau struct mii_softc *miisc; 36146c8d8eccSSepherosa Ziehau 36156c8d8eccSSepherosa Ziehau LIST_FOREACH(miisc, &mii->mii_phys, mii_list) 36166c8d8eccSSepherosa Ziehau mii_phy_reset(miisc); 36176c8d8eccSSepherosa Ziehau } 36186c8d8eccSSepherosa Ziehau mii_mediachg(mii); 36196c8d8eccSSepherosa Ziehau 36206c8d8eccSSepherosa Ziehau /* 36216c8d8eccSSepherosa Ziehau * Force an interrupt so that we will call bnx_link_upd 36226c8d8eccSSepherosa Ziehau * if needed and clear any pending link state attention. 36236c8d8eccSSepherosa Ziehau * Without this we are not getting any further interrupts 36246c8d8eccSSepherosa Ziehau * for link state changes and thus will not UP the link and 36256c8d8eccSSepherosa Ziehau * not be able to send in bnx_start. The only way to get 36266c8d8eccSSepherosa Ziehau * things working was to receive a packet and get an RX 36276c8d8eccSSepherosa Ziehau * intr. 36286c8d8eccSSepherosa Ziehau * 36296c8d8eccSSepherosa Ziehau * bnx_tick should help for fiber cards and we might not 36306c8d8eccSSepherosa Ziehau * need to do this here if BNX_FLAG_TBI is set but as 36316c8d8eccSSepherosa Ziehau * we poll for fiber anyway it should not harm. 36326c8d8eccSSepherosa Ziehau */ 36336c8d8eccSSepherosa Ziehau BNX_SETBIT(sc, BGE_HCC_MODE, BGE_HCCMODE_COAL_NOW); 36346c8d8eccSSepherosa Ziehau } 36356c8d8eccSSepherosa Ziehau return(0); 36366c8d8eccSSepherosa Ziehau } 36376c8d8eccSSepherosa Ziehau 36386c8d8eccSSepherosa Ziehau /* 36396c8d8eccSSepherosa Ziehau * Report current media status. 36406c8d8eccSSepherosa Ziehau */ 36416c8d8eccSSepherosa Ziehau static void 36426c8d8eccSSepherosa Ziehau bnx_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr) 36436c8d8eccSSepherosa Ziehau { 36446c8d8eccSSepherosa Ziehau struct bnx_softc *sc = ifp->if_softc; 36456c8d8eccSSepherosa Ziehau 36466c8d8eccSSepherosa Ziehau if (sc->bnx_flags & BNX_FLAG_TBI) { 36476c8d8eccSSepherosa Ziehau ifmr->ifm_status = IFM_AVALID; 36486c8d8eccSSepherosa Ziehau ifmr->ifm_active = IFM_ETHER; 36496c8d8eccSSepherosa Ziehau if (CSR_READ_4(sc, BGE_MAC_STS) & 36506c8d8eccSSepherosa Ziehau BGE_MACSTAT_TBI_PCS_SYNCHED) { 36516c8d8eccSSepherosa Ziehau ifmr->ifm_status |= IFM_ACTIVE; 36526c8d8eccSSepherosa Ziehau } else { 36536c8d8eccSSepherosa Ziehau ifmr->ifm_active |= IFM_NONE; 36546c8d8eccSSepherosa Ziehau return; 36556c8d8eccSSepherosa Ziehau } 36566c8d8eccSSepherosa Ziehau 36576c8d8eccSSepherosa Ziehau ifmr->ifm_active |= IFM_1000_SX; 36586c8d8eccSSepherosa Ziehau if (CSR_READ_4(sc, BGE_MAC_MODE) & BGE_MACMODE_HALF_DUPLEX) 36596c8d8eccSSepherosa Ziehau ifmr->ifm_active |= IFM_HDX; 36606c8d8eccSSepherosa Ziehau else 36616c8d8eccSSepherosa Ziehau ifmr->ifm_active |= IFM_FDX; 36626c8d8eccSSepherosa Ziehau } else { 36636c8d8eccSSepherosa Ziehau struct mii_data *mii = device_get_softc(sc->bnx_miibus); 36646c8d8eccSSepherosa Ziehau 36656c8d8eccSSepherosa Ziehau mii_pollstat(mii); 36666c8d8eccSSepherosa Ziehau ifmr->ifm_active = mii->mii_media_active; 36676c8d8eccSSepherosa Ziehau ifmr->ifm_status = mii->mii_media_status; 36686c8d8eccSSepherosa Ziehau } 36696c8d8eccSSepherosa Ziehau } 36706c8d8eccSSepherosa Ziehau 36716c8d8eccSSepherosa Ziehau static int 36726c8d8eccSSepherosa Ziehau bnx_ioctl(struct ifnet *ifp, u_long command, caddr_t data, struct ucred *cr) 36736c8d8eccSSepherosa Ziehau { 36746c8d8eccSSepherosa Ziehau struct bnx_softc *sc = ifp->if_softc; 36756c8d8eccSSepherosa Ziehau struct ifreq *ifr = (struct ifreq *)data; 36766c8d8eccSSepherosa Ziehau int mask, error = 0; 36776c8d8eccSSepherosa Ziehau 3678329f9016SSepherosa Ziehau ASSERT_IFNET_SERIALIZED_ALL(ifp); 36796c8d8eccSSepherosa Ziehau 36806c8d8eccSSepherosa Ziehau switch (command) { 36816c8d8eccSSepherosa Ziehau case SIOCSIFMTU: 36826c8d8eccSSepherosa Ziehau if ((!BNX_IS_JUMBO_CAPABLE(sc) && ifr->ifr_mtu > ETHERMTU) || 36836c8d8eccSSepherosa Ziehau (BNX_IS_JUMBO_CAPABLE(sc) && 36846c8d8eccSSepherosa Ziehau ifr->ifr_mtu > BNX_JUMBO_MTU)) { 36856c8d8eccSSepherosa Ziehau error = EINVAL; 36866c8d8eccSSepherosa Ziehau } else if (ifp->if_mtu != ifr->ifr_mtu) { 36876c8d8eccSSepherosa Ziehau ifp->if_mtu = ifr->ifr_mtu; 36886c8d8eccSSepherosa Ziehau if (ifp->if_flags & IFF_RUNNING) 36896c8d8eccSSepherosa Ziehau bnx_init(sc); 36906c8d8eccSSepherosa Ziehau } 36916c8d8eccSSepherosa Ziehau break; 36926c8d8eccSSepherosa Ziehau case SIOCSIFFLAGS: 36936c8d8eccSSepherosa Ziehau if (ifp->if_flags & IFF_UP) { 36946c8d8eccSSepherosa Ziehau if (ifp->if_flags & IFF_RUNNING) { 36956c8d8eccSSepherosa Ziehau mask = ifp->if_flags ^ sc->bnx_if_flags; 36966c8d8eccSSepherosa Ziehau 36976c8d8eccSSepherosa Ziehau /* 36986c8d8eccSSepherosa Ziehau * If only the state of the PROMISC flag 36996c8d8eccSSepherosa Ziehau * changed, then just use the 'set promisc 37006c8d8eccSSepherosa Ziehau * mode' command instead of reinitializing 37016c8d8eccSSepherosa Ziehau * the entire NIC. Doing a full re-init 37026c8d8eccSSepherosa Ziehau * means reloading the firmware and waiting 37036c8d8eccSSepherosa Ziehau * for it to start up, which may take a 37046c8d8eccSSepherosa Ziehau * second or two. Similarly for ALLMULTI. 37056c8d8eccSSepherosa Ziehau */ 37066c8d8eccSSepherosa Ziehau if (mask & IFF_PROMISC) 37076c8d8eccSSepherosa Ziehau bnx_setpromisc(sc); 37086c8d8eccSSepherosa Ziehau if (mask & IFF_ALLMULTI) 37096c8d8eccSSepherosa Ziehau bnx_setmulti(sc); 37106c8d8eccSSepherosa Ziehau } else { 37116c8d8eccSSepherosa Ziehau bnx_init(sc); 37126c8d8eccSSepherosa Ziehau } 37136c8d8eccSSepherosa Ziehau } else if (ifp->if_flags & IFF_RUNNING) { 37146c8d8eccSSepherosa Ziehau bnx_stop(sc); 37156c8d8eccSSepherosa Ziehau } 37166c8d8eccSSepherosa Ziehau sc->bnx_if_flags = ifp->if_flags; 37176c8d8eccSSepherosa Ziehau break; 37186c8d8eccSSepherosa Ziehau case SIOCADDMULTI: 37196c8d8eccSSepherosa Ziehau case SIOCDELMULTI: 37206c8d8eccSSepherosa Ziehau if (ifp->if_flags & IFF_RUNNING) 37216c8d8eccSSepherosa Ziehau bnx_setmulti(sc); 37226c8d8eccSSepherosa Ziehau break; 37236c8d8eccSSepherosa Ziehau case SIOCSIFMEDIA: 37246c8d8eccSSepherosa Ziehau case SIOCGIFMEDIA: 37256c8d8eccSSepherosa Ziehau if (sc->bnx_flags & BNX_FLAG_TBI) { 37266c8d8eccSSepherosa Ziehau error = ifmedia_ioctl(ifp, ifr, 37276c8d8eccSSepherosa Ziehau &sc->bnx_ifmedia, command); 37286c8d8eccSSepherosa Ziehau } else { 37296c8d8eccSSepherosa Ziehau struct mii_data *mii; 37306c8d8eccSSepherosa Ziehau 37316c8d8eccSSepherosa Ziehau mii = device_get_softc(sc->bnx_miibus); 37326c8d8eccSSepherosa Ziehau error = ifmedia_ioctl(ifp, ifr, 37336c8d8eccSSepherosa Ziehau &mii->mii_media, command); 37346c8d8eccSSepherosa Ziehau } 37356c8d8eccSSepherosa Ziehau break; 37366c8d8eccSSepherosa Ziehau case SIOCSIFCAP: 37376c8d8eccSSepherosa Ziehau mask = ifr->ifr_reqcap ^ ifp->if_capenable; 37386c8d8eccSSepherosa Ziehau if (mask & IFCAP_HWCSUM) { 37396c8d8eccSSepherosa Ziehau ifp->if_capenable ^= (mask & IFCAP_HWCSUM); 374066deb1c1SSepherosa Ziehau if (ifp->if_capenable & IFCAP_TXCSUM) 374166deb1c1SSepherosa Ziehau ifp->if_hwassist |= BNX_CSUM_FEATURES; 37426c8d8eccSSepherosa Ziehau else 374366deb1c1SSepherosa Ziehau ifp->if_hwassist &= ~BNX_CSUM_FEATURES; 374466deb1c1SSepherosa Ziehau } 374566deb1c1SSepherosa Ziehau if (mask & IFCAP_TSO) { 374666deb1c1SSepherosa Ziehau ifp->if_capenable ^= (mask & IFCAP_TSO); 374766deb1c1SSepherosa Ziehau if (ifp->if_capenable & IFCAP_TSO) 374866deb1c1SSepherosa Ziehau ifp->if_hwassist |= CSUM_TSO; 374966deb1c1SSepherosa Ziehau else 375066deb1c1SSepherosa Ziehau ifp->if_hwassist &= ~CSUM_TSO; 37516c8d8eccSSepherosa Ziehau } 37526c8d8eccSSepherosa Ziehau break; 37536c8d8eccSSepherosa Ziehau default: 37546c8d8eccSSepherosa Ziehau error = ether_ioctl(ifp, command, data); 37556c8d8eccSSepherosa Ziehau break; 37566c8d8eccSSepherosa Ziehau } 37576c8d8eccSSepherosa Ziehau return error; 37586c8d8eccSSepherosa Ziehau } 37596c8d8eccSSepherosa Ziehau 37606c8d8eccSSepherosa Ziehau static void 37613397dea6SSepherosa Ziehau bnx_watchdog(struct ifaltq_subque *ifsq) 37626c8d8eccSSepherosa Ziehau { 37633397dea6SSepherosa Ziehau struct ifnet *ifp = ifsq_get_ifp(ifsq); 37646c8d8eccSSepherosa Ziehau struct bnx_softc *sc = ifp->if_softc; 37653397dea6SSepherosa Ziehau int i; 37663397dea6SSepherosa Ziehau 37673397dea6SSepherosa Ziehau ASSERT_IFNET_SERIALIZED_ALL(ifp); 37686c8d8eccSSepherosa Ziehau 37696c8d8eccSSepherosa Ziehau if_printf(ifp, "watchdog timeout -- resetting\n"); 37706c8d8eccSSepherosa Ziehau 37716c8d8eccSSepherosa Ziehau bnx_init(sc); 37726c8d8eccSSepherosa Ziehau 3773d40991efSSepherosa Ziehau IFNET_STAT_INC(ifp, oerrors, 1); 37746c8d8eccSSepherosa Ziehau 37753397dea6SSepherosa Ziehau for (i = 0; i < sc->bnx_tx_ringcnt; ++i) 37763397dea6SSepherosa Ziehau ifsq_devstart_sched(sc->bnx_tx_ring[i].bnx_ifsq); 37776c8d8eccSSepherosa Ziehau } 37786c8d8eccSSepherosa Ziehau 37796c8d8eccSSepherosa Ziehau /* 37806c8d8eccSSepherosa Ziehau * Stop the adapter and free any mbufs allocated to the 37816c8d8eccSSepherosa Ziehau * RX and TX lists. 37826c8d8eccSSepherosa Ziehau */ 37836c8d8eccSSepherosa Ziehau static void 37846c8d8eccSSepherosa Ziehau bnx_stop(struct bnx_softc *sc) 37856c8d8eccSSepherosa Ziehau { 37866c8d8eccSSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if; 378733a04907SSepherosa Ziehau int i; 37886c8d8eccSSepherosa Ziehau 3789329f9016SSepherosa Ziehau ASSERT_IFNET_SERIALIZED_ALL(ifp); 37906c8d8eccSSepherosa Ziehau 37917dbaa833SSepherosa Ziehau callout_stop(&sc->bnx_tick_timer); 37926c8d8eccSSepherosa Ziehau 37936c8d8eccSSepherosa Ziehau /* 37946c8d8eccSSepherosa Ziehau * Disable all of the receiver blocks 37956c8d8eccSSepherosa Ziehau */ 37966c8d8eccSSepherosa Ziehau bnx_stop_block(sc, BGE_RX_MODE, BGE_RXMODE_ENABLE); 37976c8d8eccSSepherosa Ziehau bnx_stop_block(sc, BGE_RBDI_MODE, BGE_RBDIMODE_ENABLE); 37986c8d8eccSSepherosa Ziehau bnx_stop_block(sc, BGE_RXLP_MODE, BGE_RXLPMODE_ENABLE); 37996c8d8eccSSepherosa Ziehau bnx_stop_block(sc, BGE_RDBDI_MODE, BGE_RBDIMODE_ENABLE); 38006c8d8eccSSepherosa Ziehau bnx_stop_block(sc, BGE_RDC_MODE, BGE_RDCMODE_ENABLE); 38016c8d8eccSSepherosa Ziehau bnx_stop_block(sc, BGE_RBDC_MODE, BGE_RBDCMODE_ENABLE); 38026c8d8eccSSepherosa Ziehau 38036c8d8eccSSepherosa Ziehau /* 38046c8d8eccSSepherosa Ziehau * Disable all of the transmit blocks 38056c8d8eccSSepherosa Ziehau */ 38066c8d8eccSSepherosa Ziehau bnx_stop_block(sc, BGE_SRS_MODE, BGE_SRSMODE_ENABLE); 38076c8d8eccSSepherosa Ziehau bnx_stop_block(sc, BGE_SBDI_MODE, BGE_SBDIMODE_ENABLE); 38086c8d8eccSSepherosa Ziehau bnx_stop_block(sc, BGE_SDI_MODE, BGE_SDIMODE_ENABLE); 38096c8d8eccSSepherosa Ziehau bnx_stop_block(sc, BGE_RDMA_MODE, BGE_RDMAMODE_ENABLE); 38106c8d8eccSSepherosa Ziehau bnx_stop_block(sc, BGE_SDC_MODE, BGE_SDCMODE_ENABLE); 38116c8d8eccSSepherosa Ziehau bnx_stop_block(sc, BGE_SBDC_MODE, BGE_SBDCMODE_ENABLE); 38126c8d8eccSSepherosa Ziehau 38136c8d8eccSSepherosa Ziehau /* 38146c8d8eccSSepherosa Ziehau * Shut down all of the memory managers and related 38156c8d8eccSSepherosa Ziehau * state machines. 38166c8d8eccSSepherosa Ziehau */ 38176c8d8eccSSepherosa Ziehau bnx_stop_block(sc, BGE_HCC_MODE, BGE_HCCMODE_ENABLE); 38186c8d8eccSSepherosa Ziehau bnx_stop_block(sc, BGE_WDMA_MODE, BGE_WDMAMODE_ENABLE); 38196c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_FTQ_RESET, 0xFFFFFFFF); 38206c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_FTQ_RESET, 0); 38216c8d8eccSSepherosa Ziehau 38226c8d8eccSSepherosa Ziehau /* Disable host interrupts. */ 38236c8d8eccSSepherosa Ziehau bnx_disable_intr(sc); 38246c8d8eccSSepherosa Ziehau 38256c8d8eccSSepherosa Ziehau /* 38266c8d8eccSSepherosa Ziehau * Tell firmware we're shutting down. 38276c8d8eccSSepherosa Ziehau */ 38286c8d8eccSSepherosa Ziehau BNX_CLRBIT(sc, BGE_MODE_CTL, BGE_MODECTL_STACKUP); 38296c8d8eccSSepherosa Ziehau 38306c8d8eccSSepherosa Ziehau /* Free the RX lists. */ 3831beedf5beSSepherosa Ziehau bnx_free_rx_ring_std(&sc->bnx_rx_std_ring); 38326c8d8eccSSepherosa Ziehau 38336c8d8eccSSepherosa Ziehau /* Free jumbo RX list. */ 38346c8d8eccSSepherosa Ziehau if (BNX_IS_JUMBO_CAPABLE(sc)) 38356c8d8eccSSepherosa Ziehau bnx_free_rx_ring_jumbo(sc); 38366c8d8eccSSepherosa Ziehau 38376c8d8eccSSepherosa Ziehau /* Free TX buffers. */ 38384fa38985SSepherosa Ziehau for (i = 0; i < sc->bnx_tx_ringcnt; ++i) { 38394fa38985SSepherosa Ziehau struct bnx_tx_ring *txr = &sc->bnx_tx_ring[i]; 38406c8d8eccSSepherosa Ziehau 38414fa38985SSepherosa Ziehau txr->bnx_saved_status_tag = 0; 38424fa38985SSepherosa Ziehau bnx_free_tx_ring(txr); 38434fa38985SSepherosa Ziehau } 38444fa38985SSepherosa Ziehau 38454fa38985SSepherosa Ziehau /* Clear saved status tag */ 38464fa38985SSepherosa Ziehau for (i = 0; i < sc->bnx_rx_retcnt; ++i) 38474fa38985SSepherosa Ziehau sc->bnx_rx_ret_ring[i].bnx_saved_status_tag = 0; 38484fa38985SSepherosa Ziehau 38496c8d8eccSSepherosa Ziehau sc->bnx_link = 0; 38506c8d8eccSSepherosa Ziehau sc->bnx_coal_chg = 0; 38516c8d8eccSSepherosa Ziehau 38529ed293e0SSepherosa Ziehau ifp->if_flags &= ~IFF_RUNNING; 38533397dea6SSepherosa Ziehau for (i = 0; i < sc->bnx_tx_ringcnt; ++i) { 38543397dea6SSepherosa Ziehau struct bnx_tx_ring *txr = &sc->bnx_tx_ring[i]; 38553397dea6SSepherosa Ziehau 38563397dea6SSepherosa Ziehau ifsq_clr_oactive(txr->bnx_ifsq); 38573397dea6SSepherosa Ziehau ifsq_watchdog_stop(&txr->bnx_tx_watchdog); 38583397dea6SSepherosa Ziehau } 38596c8d8eccSSepherosa Ziehau } 38606c8d8eccSSepherosa Ziehau 38616c8d8eccSSepherosa Ziehau /* 38626c8d8eccSSepherosa Ziehau * Stop all chip I/O so that the kernel's probe routines don't 38636c8d8eccSSepherosa Ziehau * get confused by errant DMAs when rebooting. 38646c8d8eccSSepherosa Ziehau */ 38656c8d8eccSSepherosa Ziehau static void 38666c8d8eccSSepherosa Ziehau bnx_shutdown(device_t dev) 38676c8d8eccSSepherosa Ziehau { 38686c8d8eccSSepherosa Ziehau struct bnx_softc *sc = device_get_softc(dev); 38696c8d8eccSSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if; 38706c8d8eccSSepherosa Ziehau 3871329f9016SSepherosa Ziehau ifnet_serialize_all(ifp); 38726c8d8eccSSepherosa Ziehau bnx_stop(sc); 38736c8d8eccSSepherosa Ziehau bnx_reset(sc); 3874329f9016SSepherosa Ziehau ifnet_deserialize_all(ifp); 38756c8d8eccSSepherosa Ziehau } 38766c8d8eccSSepherosa Ziehau 38776c8d8eccSSepherosa Ziehau static int 38786c8d8eccSSepherosa Ziehau bnx_suspend(device_t dev) 38796c8d8eccSSepherosa Ziehau { 38806c8d8eccSSepherosa Ziehau struct bnx_softc *sc = device_get_softc(dev); 38816c8d8eccSSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if; 38826c8d8eccSSepherosa Ziehau 3883329f9016SSepherosa Ziehau ifnet_serialize_all(ifp); 38846c8d8eccSSepherosa Ziehau bnx_stop(sc); 3885329f9016SSepherosa Ziehau ifnet_deserialize_all(ifp); 38866c8d8eccSSepherosa Ziehau 38876c8d8eccSSepherosa Ziehau return 0; 38886c8d8eccSSepherosa Ziehau } 38896c8d8eccSSepherosa Ziehau 38906c8d8eccSSepherosa Ziehau static int 38916c8d8eccSSepherosa Ziehau bnx_resume(device_t dev) 38926c8d8eccSSepherosa Ziehau { 38936c8d8eccSSepherosa Ziehau struct bnx_softc *sc = device_get_softc(dev); 38946c8d8eccSSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if; 38956c8d8eccSSepherosa Ziehau 3896329f9016SSepherosa Ziehau ifnet_serialize_all(ifp); 38976c8d8eccSSepherosa Ziehau 38986c8d8eccSSepherosa Ziehau if (ifp->if_flags & IFF_UP) { 38993397dea6SSepherosa Ziehau int i; 39006c8d8eccSSepherosa Ziehau 39013397dea6SSepherosa Ziehau bnx_init(sc); 39023397dea6SSepherosa Ziehau for (i = 0; i < sc->bnx_tx_ringcnt; ++i) 39033397dea6SSepherosa Ziehau ifsq_devstart_sched(sc->bnx_tx_ring[i].bnx_ifsq); 39046c8d8eccSSepherosa Ziehau } 39056c8d8eccSSepherosa Ziehau 3906329f9016SSepherosa Ziehau ifnet_deserialize_all(ifp); 39076c8d8eccSSepherosa Ziehau 39086c8d8eccSSepherosa Ziehau return 0; 39096c8d8eccSSepherosa Ziehau } 39106c8d8eccSSepherosa Ziehau 39116c8d8eccSSepherosa Ziehau static void 39126c8d8eccSSepherosa Ziehau bnx_setpromisc(struct bnx_softc *sc) 39136c8d8eccSSepherosa Ziehau { 39146c8d8eccSSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if; 39156c8d8eccSSepherosa Ziehau 39166c8d8eccSSepherosa Ziehau if (ifp->if_flags & IFF_PROMISC) 39176c8d8eccSSepherosa Ziehau BNX_SETBIT(sc, BGE_RX_MODE, BGE_RXMODE_RX_PROMISC); 39186c8d8eccSSepherosa Ziehau else 39196c8d8eccSSepherosa Ziehau BNX_CLRBIT(sc, BGE_RX_MODE, BGE_RXMODE_RX_PROMISC); 39206c8d8eccSSepherosa Ziehau } 39216c8d8eccSSepherosa Ziehau 39226c8d8eccSSepherosa Ziehau static void 39236c8d8eccSSepherosa Ziehau bnx_dma_free(struct bnx_softc *sc) 39246c8d8eccSSepherosa Ziehau { 3925beedf5beSSepherosa Ziehau struct bnx_rx_std_ring *std = &sc->bnx_rx_std_ring; 39266c8d8eccSSepherosa Ziehau int i; 39276c8d8eccSSepherosa Ziehau 3928beedf5beSSepherosa Ziehau /* Destroy RX return rings */ 3929beedf5beSSepherosa Ziehau if (sc->bnx_rx_ret_ring != NULL) { 3930beedf5beSSepherosa Ziehau for (i = 0; i < sc->bnx_rx_retcnt; ++i) 3931beedf5beSSepherosa Ziehau bnx_destroy_rx_ret_ring(&sc->bnx_rx_ret_ring[i]); 3932beedf5beSSepherosa Ziehau kfree(sc->bnx_rx_ret_ring, M_DEVBUF); 3933beedf5beSSepherosa Ziehau } 3934beedf5beSSepherosa Ziehau 39356c8d8eccSSepherosa Ziehau /* Destroy RX mbuf DMA stuffs. */ 3936beedf5beSSepherosa Ziehau if (std->bnx_rx_mtag != NULL) { 39376c8d8eccSSepherosa Ziehau for (i = 0; i < BGE_STD_RX_RING_CNT; i++) { 3938beedf5beSSepherosa Ziehau KKASSERT(std->bnx_rx_std_buf[i].bnx_rx_mbuf == NULL); 3939beedf5beSSepherosa Ziehau bus_dmamap_destroy(std->bnx_rx_mtag, 3940beedf5beSSepherosa Ziehau std->bnx_rx_std_buf[i].bnx_rx_dmamap); 39416c8d8eccSSepherosa Ziehau } 3942beedf5beSSepherosa Ziehau bus_dma_tag_destroy(std->bnx_rx_mtag); 39436c8d8eccSSepherosa Ziehau } 39446c8d8eccSSepherosa Ziehau 3945beedf5beSSepherosa Ziehau /* Destroy standard RX ring */ 3946beedf5beSSepherosa Ziehau bnx_dma_block_free(std->bnx_rx_std_ring_tag, 3947beedf5beSSepherosa Ziehau std->bnx_rx_std_ring_map, std->bnx_rx_std_ring); 3948beedf5beSSepherosa Ziehau 394933a04907SSepherosa Ziehau /* Destroy TX rings */ 395033a04907SSepherosa Ziehau if (sc->bnx_tx_ring != NULL) { 395133a04907SSepherosa Ziehau for (i = 0; i < sc->bnx_tx_ringcnt; ++i) 395233a04907SSepherosa Ziehau bnx_destroy_tx_ring(&sc->bnx_tx_ring[i]); 395333a04907SSepherosa Ziehau kfree(sc->bnx_tx_ring, M_DEVBUF); 39546c8d8eccSSepherosa Ziehau } 39556c8d8eccSSepherosa Ziehau 39566c8d8eccSSepherosa Ziehau if (BNX_IS_JUMBO_CAPABLE(sc)) 39576c8d8eccSSepherosa Ziehau bnx_free_jumbo_mem(sc); 39586c8d8eccSSepherosa Ziehau 39590a806e3aSSepherosa Ziehau /* Destroy status blocks */ 39600a806e3aSSepherosa Ziehau for (i = 0; i < sc->bnx_intr_cnt; ++i) { 39610a806e3aSSepherosa Ziehau struct bnx_intr_data *intr = &sc->bnx_intr_data[i]; 39620a806e3aSSepherosa Ziehau 39630a806e3aSSepherosa Ziehau bnx_dma_block_free(intr->bnx_status_tag, 39640a806e3aSSepherosa Ziehau intr->bnx_status_map, intr->bnx_status_block); 39650a806e3aSSepherosa Ziehau } 39666c8d8eccSSepherosa Ziehau 39676c8d8eccSSepherosa Ziehau /* Destroy the parent tag */ 39686c8d8eccSSepherosa Ziehau if (sc->bnx_cdata.bnx_parent_tag != NULL) 39696c8d8eccSSepherosa Ziehau bus_dma_tag_destroy(sc->bnx_cdata.bnx_parent_tag); 39706c8d8eccSSepherosa Ziehau } 39716c8d8eccSSepherosa Ziehau 39726c8d8eccSSepherosa Ziehau static int 3973beedf5beSSepherosa Ziehau bnx_dma_alloc(device_t dev) 39746c8d8eccSSepherosa Ziehau { 3975beedf5beSSepherosa Ziehau struct bnx_softc *sc = device_get_softc(dev); 3976beedf5beSSepherosa Ziehau struct bnx_rx_std_ring *std = &sc->bnx_rx_std_ring; 3977ac2936fdSSepherosa Ziehau int i, error, mbx; 39786c8d8eccSSepherosa Ziehau 39796c8d8eccSSepherosa Ziehau /* 39806c8d8eccSSepherosa Ziehau * Allocate the parent bus DMA tag appropriate for PCI. 39816c8d8eccSSepherosa Ziehau * 39826c8d8eccSSepherosa Ziehau * All of the NetExtreme/NetLink controllers have 4GB boundary 39836c8d8eccSSepherosa Ziehau * DMA bug. 39846c8d8eccSSepherosa Ziehau * Whenever an address crosses a multiple of the 4GB boundary 39856c8d8eccSSepherosa Ziehau * (including 4GB, 8Gb, 12Gb, etc.) and makes the transition 39866c8d8eccSSepherosa Ziehau * from 0xX_FFFF_FFFF to 0x(X+1)_0000_0000 an internal DMA 39876c8d8eccSSepherosa Ziehau * state machine will lockup and cause the device to hang. 39886c8d8eccSSepherosa Ziehau */ 39896c8d8eccSSepherosa Ziehau error = bus_dma_tag_create(NULL, 1, BGE_DMA_BOUNDARY_4G, 3990beedf5beSSepherosa Ziehau BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL, NULL, 3991beedf5beSSepherosa Ziehau BUS_SPACE_MAXSIZE_32BIT, 0, BUS_SPACE_MAXSIZE_32BIT, 39926c8d8eccSSepherosa Ziehau 0, &sc->bnx_cdata.bnx_parent_tag); 39936c8d8eccSSepherosa Ziehau if (error) { 3994beedf5beSSepherosa Ziehau device_printf(dev, "could not create parent DMA tag\n"); 39956c8d8eccSSepherosa Ziehau return error; 39966c8d8eccSSepherosa Ziehau } 39976c8d8eccSSepherosa Ziehau 39986c8d8eccSSepherosa Ziehau /* 39990a806e3aSSepherosa Ziehau * Create DMA stuffs for status blocks. 40006c8d8eccSSepherosa Ziehau */ 40010a806e3aSSepherosa Ziehau for (i = 0; i < sc->bnx_intr_cnt; ++i) { 40020a806e3aSSepherosa Ziehau struct bnx_intr_data *intr = &sc->bnx_intr_data[i]; 40030a806e3aSSepherosa Ziehau 4004*695a8586SSepherosa Ziehau error = bnx_dma_block_alloc(sc, 4005*695a8586SSepherosa Ziehau __VM_CACHELINE_ALIGN(BGE_STATUS_BLK_SZ), 40060a806e3aSSepherosa Ziehau &intr->bnx_status_tag, &intr->bnx_status_map, 40070a806e3aSSepherosa Ziehau (void *)&intr->bnx_status_block, 40080a806e3aSSepherosa Ziehau &intr->bnx_status_block_paddr); 40096c8d8eccSSepherosa Ziehau if (error) { 40100a806e3aSSepherosa Ziehau device_printf(dev, 40110a806e3aSSepherosa Ziehau "could not create %dth status block\n", i); 40126c8d8eccSSepherosa Ziehau return error; 40136c8d8eccSSepherosa Ziehau } 40140a806e3aSSepherosa Ziehau } 4015*695a8586SSepherosa Ziehau sc->bnx_hw_status = &sc->bnx_intr_data[0].bnx_status_block->bge_status; 4016*695a8586SSepherosa Ziehau if (sc->bnx_flags & BNX_FLAG_STATUS_HASTAG) { 4017*695a8586SSepherosa Ziehau sc->bnx_hw_status_tag = 4018*695a8586SSepherosa Ziehau &sc->bnx_intr_data[0].bnx_status_block->bge_status_tag; 4019*695a8586SSepherosa Ziehau } 40206c8d8eccSSepherosa Ziehau 4021beedf5beSSepherosa Ziehau /* 4022beedf5beSSepherosa Ziehau * Create DMA tag and maps for RX mbufs. 4023beedf5beSSepherosa Ziehau */ 4024beedf5beSSepherosa Ziehau std->bnx_sc = sc; 4025329f9016SSepherosa Ziehau lwkt_serialize_init(&std->bnx_rx_std_serialize); 4026beedf5beSSepherosa Ziehau error = bus_dma_tag_create(sc->bnx_cdata.bnx_parent_tag, 1, 0, 4027beedf5beSSepherosa Ziehau BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, 4028beedf5beSSepherosa Ziehau NULL, NULL, MCLBYTES, 1, MCLBYTES, 4029beedf5beSSepherosa Ziehau BUS_DMA_ALLOCNOW | BUS_DMA_WAITOK, &std->bnx_rx_mtag); 4030beedf5beSSepherosa Ziehau if (error) { 4031beedf5beSSepherosa Ziehau device_printf(dev, "could not create RX mbuf DMA tag\n"); 4032beedf5beSSepherosa Ziehau return error; 4033beedf5beSSepherosa Ziehau } 4034beedf5beSSepherosa Ziehau 4035beedf5beSSepherosa Ziehau for (i = 0; i < BGE_STD_RX_RING_CNT; ++i) { 4036beedf5beSSepherosa Ziehau error = bus_dmamap_create(std->bnx_rx_mtag, BUS_DMA_WAITOK, 4037beedf5beSSepherosa Ziehau &std->bnx_rx_std_buf[i].bnx_rx_dmamap); 4038beedf5beSSepherosa Ziehau if (error) { 4039beedf5beSSepherosa Ziehau int j; 4040beedf5beSSepherosa Ziehau 4041beedf5beSSepherosa Ziehau for (j = 0; j < i; ++j) { 4042beedf5beSSepherosa Ziehau bus_dmamap_destroy(std->bnx_rx_mtag, 4043beedf5beSSepherosa Ziehau std->bnx_rx_std_buf[j].bnx_rx_dmamap); 4044beedf5beSSepherosa Ziehau } 4045beedf5beSSepherosa Ziehau bus_dma_tag_destroy(std->bnx_rx_mtag); 4046beedf5beSSepherosa Ziehau std->bnx_rx_mtag = NULL; 4047beedf5beSSepherosa Ziehau 4048beedf5beSSepherosa Ziehau device_printf(dev, 4049beedf5beSSepherosa Ziehau "could not create %dth RX mbuf DMA map\n", i); 4050beedf5beSSepherosa Ziehau return error; 4051beedf5beSSepherosa Ziehau } 4052beedf5beSSepherosa Ziehau } 4053beedf5beSSepherosa Ziehau 4054beedf5beSSepherosa Ziehau /* 4055beedf5beSSepherosa Ziehau * Create DMA stuffs for standard RX ring. 4056beedf5beSSepherosa Ziehau */ 4057beedf5beSSepherosa Ziehau error = bnx_dma_block_alloc(sc, BGE_STD_RX_RING_SZ, 4058beedf5beSSepherosa Ziehau &std->bnx_rx_std_ring_tag, 4059beedf5beSSepherosa Ziehau &std->bnx_rx_std_ring_map, 4060beedf5beSSepherosa Ziehau (void *)&std->bnx_rx_std_ring, 4061beedf5beSSepherosa Ziehau &std->bnx_rx_std_ring_paddr); 4062beedf5beSSepherosa Ziehau if (error) { 4063beedf5beSSepherosa Ziehau device_printf(dev, "could not create std RX ring\n"); 4064beedf5beSSepherosa Ziehau return error; 4065beedf5beSSepherosa Ziehau } 4066beedf5beSSepherosa Ziehau 4067beedf5beSSepherosa Ziehau /* 4068beedf5beSSepherosa Ziehau * Create RX return rings 4069beedf5beSSepherosa Ziehau */ 4070ac2936fdSSepherosa Ziehau mbx = BGE_MBX_RX_CONS0_LO; 4071beedf5beSSepherosa Ziehau sc->bnx_rx_ret_ring = kmalloc_cachealign( 4072beedf5beSSepherosa Ziehau sizeof(struct bnx_rx_ret_ring) * sc->bnx_rx_retcnt, M_DEVBUF, 4073beedf5beSSepherosa Ziehau M_WAITOK | M_ZERO); 4074beedf5beSSepherosa Ziehau for (i = 0; i < sc->bnx_rx_retcnt; ++i) { 4075beedf5beSSepherosa Ziehau struct bnx_rx_ret_ring *ret = &sc->bnx_rx_ret_ring[i]; 40760a806e3aSSepherosa Ziehau struct bnx_intr_data *intr; 4077beedf5beSSepherosa Ziehau 4078beedf5beSSepherosa Ziehau ret->bnx_sc = sc; 4079beedf5beSSepherosa Ziehau ret->bnx_std = std; 4080ac2936fdSSepherosa Ziehau ret->bnx_rx_mbx = mbx; 4081841cdf08SSepherosa Ziehau ret->bnx_rx_cntmax = (BGE_STD_RX_RING_CNT / 4) / 4082841cdf08SSepherosa Ziehau sc->bnx_rx_retcnt; 4083841cdf08SSepherosa Ziehau ret->bnx_rx_mask = 1 << i; 40843a16b7b8SSepherosa Ziehau 4085*695a8586SSepherosa Ziehau if (!BNX_RSS_ENABLED(sc)) { 40860a806e3aSSepherosa Ziehau intr = &sc->bnx_intr_data[0]; 40870a806e3aSSepherosa Ziehau } else { 40880a806e3aSSepherosa Ziehau KKASSERT(i + 1 < sc->bnx_intr_cnt); 40890a806e3aSSepherosa Ziehau intr = &sc->bnx_intr_data[i + 1]; 40900a806e3aSSepherosa Ziehau } 40910a806e3aSSepherosa Ziehau 4092*695a8586SSepherosa Ziehau if (i == 0) { 40933a16b7b8SSepherosa Ziehau ret->bnx_rx_considx = 40940a806e3aSSepherosa Ziehau &intr->bnx_status_block->bge_idx[0].bge_rx_prod_idx; 4095*695a8586SSepherosa Ziehau } else if (i == 1) { 4096*695a8586SSepherosa Ziehau ret->bnx_rx_considx = 4097*695a8586SSepherosa Ziehau &intr->bnx_status_block->bge_rx_jumbo_cons_idx; 4098*695a8586SSepherosa Ziehau } else if (i == 2) { 4099*695a8586SSepherosa Ziehau ret->bnx_rx_considx = 4100*695a8586SSepherosa Ziehau &intr->bnx_status_block->bge_rsvd1; 4101*695a8586SSepherosa Ziehau } else if (i == 3) { 4102*695a8586SSepherosa Ziehau ret->bnx_rx_considx = 4103*695a8586SSepherosa Ziehau &intr->bnx_status_block->bge_rx_mini_cons_idx; 4104*695a8586SSepherosa Ziehau } else { 4105*695a8586SSepherosa Ziehau panic("unknown RX return ring %d\n", i); 4106*695a8586SSepherosa Ziehau } 41074fa38985SSepherosa Ziehau ret->bnx_hw_status_tag = 41080a806e3aSSepherosa Ziehau &intr->bnx_status_block->bge_status_tag; 41093a16b7b8SSepherosa Ziehau 4110beedf5beSSepherosa Ziehau error = bnx_create_rx_ret_ring(ret); 4111beedf5beSSepherosa Ziehau if (error) { 4112beedf5beSSepherosa Ziehau device_printf(dev, 4113beedf5beSSepherosa Ziehau "could not create %dth RX ret ring\n", i); 4114beedf5beSSepherosa Ziehau return error; 4115beedf5beSSepherosa Ziehau } 4116ac2936fdSSepherosa Ziehau mbx += 8; 4117beedf5beSSepherosa Ziehau } 4118beedf5beSSepherosa Ziehau 4119beedf5beSSepherosa Ziehau /* 4120beedf5beSSepherosa Ziehau * Create TX rings 4121beedf5beSSepherosa Ziehau */ 412233a04907SSepherosa Ziehau sc->bnx_tx_ring = kmalloc_cachealign( 412333a04907SSepherosa Ziehau sizeof(struct bnx_tx_ring) * sc->bnx_tx_ringcnt, M_DEVBUF, 412433a04907SSepherosa Ziehau M_WAITOK | M_ZERO); 412533a04907SSepherosa Ziehau for (i = 0; i < sc->bnx_tx_ringcnt; ++i) { 412633a04907SSepherosa Ziehau struct bnx_tx_ring *txr = &sc->bnx_tx_ring[i]; 41270a806e3aSSepherosa Ziehau struct bnx_intr_data *intr; 412833a04907SSepherosa Ziehau 412933a04907SSepherosa Ziehau txr->bnx_sc = sc; 41301c9d03f6SSepherosa Ziehau txr->bnx_tx_mbx = bnx_tx_mailbox[i]; 41318bd43d5dSSepherosa Ziehau 41320a806e3aSSepherosa Ziehau if (sc->bnx_tx_ringcnt == 1) { 41330a806e3aSSepherosa Ziehau intr = &sc->bnx_intr_data[0]; 41340a806e3aSSepherosa Ziehau } else { 41350a806e3aSSepherosa Ziehau KKASSERT(i + 1 < sc->bnx_intr_cnt); 41360a806e3aSSepherosa Ziehau intr = &sc->bnx_intr_data[i + 1]; 41370a806e3aSSepherosa Ziehau } 41380a806e3aSSepherosa Ziehau 4139*695a8586SSepherosa Ziehau if ((sc->bnx_flags & BNX_FLAG_RXTX_BUNDLE) == 0) { 4140*695a8586SSepherosa Ziehau txr->bnx_hw_status_tag = 4141*695a8586SSepherosa Ziehau &intr->bnx_status_block->bge_status_tag; 4142*695a8586SSepherosa Ziehau } 41433a16b7b8SSepherosa Ziehau txr->bnx_tx_considx = 41440a806e3aSSepherosa Ziehau &intr->bnx_status_block->bge_idx[0].bge_tx_cons_idx; 41453a16b7b8SSepherosa Ziehau 414633a04907SSepherosa Ziehau error = bnx_create_tx_ring(txr); 414733a04907SSepherosa Ziehau if (error) { 4148beedf5beSSepherosa Ziehau device_printf(dev, 4149beedf5beSSepherosa Ziehau "could not create %dth TX ring\n", i); 4150beedf5beSSepherosa Ziehau return error; 4151beedf5beSSepherosa Ziehau } 4152beedf5beSSepherosa Ziehau } 4153beedf5beSSepherosa Ziehau 4154beedf5beSSepherosa Ziehau /* 4155beedf5beSSepherosa Ziehau * Create jumbo buffer pool. 4156beedf5beSSepherosa Ziehau */ 4157beedf5beSSepherosa Ziehau if (BNX_IS_JUMBO_CAPABLE(sc)) { 4158beedf5beSSepherosa Ziehau error = bnx_alloc_jumbo_mem(sc); 4159beedf5beSSepherosa Ziehau if (error) { 4160beedf5beSSepherosa Ziehau device_printf(dev, 4161beedf5beSSepherosa Ziehau "could not create jumbo buffer pool\n"); 416233a04907SSepherosa Ziehau return error; 416333a04907SSepherosa Ziehau } 416433a04907SSepherosa Ziehau } 416533a04907SSepherosa Ziehau 41666c8d8eccSSepherosa Ziehau return 0; 41676c8d8eccSSepherosa Ziehau } 41686c8d8eccSSepherosa Ziehau 41696c8d8eccSSepherosa Ziehau static int 41706c8d8eccSSepherosa Ziehau bnx_dma_block_alloc(struct bnx_softc *sc, bus_size_t size, bus_dma_tag_t *tag, 41716c8d8eccSSepherosa Ziehau bus_dmamap_t *map, void **addr, bus_addr_t *paddr) 41726c8d8eccSSepherosa Ziehau { 41736c8d8eccSSepherosa Ziehau bus_dmamem_t dmem; 41746c8d8eccSSepherosa Ziehau int error; 41756c8d8eccSSepherosa Ziehau 41766c8d8eccSSepherosa Ziehau error = bus_dmamem_coherent(sc->bnx_cdata.bnx_parent_tag, PAGE_SIZE, 0, 41776c8d8eccSSepherosa Ziehau BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, 41786c8d8eccSSepherosa Ziehau size, BUS_DMA_WAITOK | BUS_DMA_ZERO, &dmem); 41796c8d8eccSSepherosa Ziehau if (error) 41806c8d8eccSSepherosa Ziehau return error; 41816c8d8eccSSepherosa Ziehau 41826c8d8eccSSepherosa Ziehau *tag = dmem.dmem_tag; 41836c8d8eccSSepherosa Ziehau *map = dmem.dmem_map; 41846c8d8eccSSepherosa Ziehau *addr = dmem.dmem_addr; 41856c8d8eccSSepherosa Ziehau *paddr = dmem.dmem_busaddr; 41866c8d8eccSSepherosa Ziehau 41876c8d8eccSSepherosa Ziehau return 0; 41886c8d8eccSSepherosa Ziehau } 41896c8d8eccSSepherosa Ziehau 41906c8d8eccSSepherosa Ziehau static void 41916c8d8eccSSepherosa Ziehau bnx_dma_block_free(bus_dma_tag_t tag, bus_dmamap_t map, void *addr) 41926c8d8eccSSepherosa Ziehau { 41936c8d8eccSSepherosa Ziehau if (tag != NULL) { 41946c8d8eccSSepherosa Ziehau bus_dmamap_unload(tag, map); 41956c8d8eccSSepherosa Ziehau bus_dmamem_free(tag, addr, map); 41966c8d8eccSSepherosa Ziehau bus_dma_tag_destroy(tag); 41976c8d8eccSSepherosa Ziehau } 41986c8d8eccSSepherosa Ziehau } 41996c8d8eccSSepherosa Ziehau 42006c8d8eccSSepherosa Ziehau static void 42016c8d8eccSSepherosa Ziehau bnx_tbi_link_upd(struct bnx_softc *sc, uint32_t status) 42026c8d8eccSSepherosa Ziehau { 42036c8d8eccSSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if; 42046c8d8eccSSepherosa Ziehau 42056c8d8eccSSepherosa Ziehau #define PCS_ENCODE_ERR (BGE_MACSTAT_PORT_DECODE_ERROR|BGE_MACSTAT_MI_COMPLETE) 42066c8d8eccSSepherosa Ziehau 42076c8d8eccSSepherosa Ziehau /* 42086c8d8eccSSepherosa Ziehau * Sometimes PCS encoding errors are detected in 42096c8d8eccSSepherosa Ziehau * TBI mode (on fiber NICs), and for some reason 42106c8d8eccSSepherosa Ziehau * the chip will signal them as link changes. 42116c8d8eccSSepherosa Ziehau * If we get a link change event, but the 'PCS 42126c8d8eccSSepherosa Ziehau * encoding error' bit in the MAC status register 42136c8d8eccSSepherosa Ziehau * is set, don't bother doing a link check. 42146c8d8eccSSepherosa Ziehau * This avoids spurious "gigabit link up" messages 42156c8d8eccSSepherosa Ziehau * that sometimes appear on fiber NICs during 42166c8d8eccSSepherosa Ziehau * periods of heavy traffic. 42176c8d8eccSSepherosa Ziehau */ 42186c8d8eccSSepherosa Ziehau if (status & BGE_MACSTAT_TBI_PCS_SYNCHED) { 42196c8d8eccSSepherosa Ziehau if (!sc->bnx_link) { 42206c8d8eccSSepherosa Ziehau sc->bnx_link++; 42216c8d8eccSSepherosa Ziehau if (sc->bnx_asicrev == BGE_ASICREV_BCM5704) { 42226c8d8eccSSepherosa Ziehau BNX_CLRBIT(sc, BGE_MAC_MODE, 42236c8d8eccSSepherosa Ziehau BGE_MACMODE_TBI_SEND_CFGS); 42246c8d8eccSSepherosa Ziehau } 42256c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_MAC_STS, 0xFFFFFFFF); 42266c8d8eccSSepherosa Ziehau 42276c8d8eccSSepherosa Ziehau if (bootverbose) 42286c8d8eccSSepherosa Ziehau if_printf(ifp, "link UP\n"); 42296c8d8eccSSepherosa Ziehau 42306c8d8eccSSepherosa Ziehau ifp->if_link_state = LINK_STATE_UP; 42316c8d8eccSSepherosa Ziehau if_link_state_change(ifp); 42326c8d8eccSSepherosa Ziehau } 42336c8d8eccSSepherosa Ziehau } else if ((status & PCS_ENCODE_ERR) != PCS_ENCODE_ERR) { 42346c8d8eccSSepherosa Ziehau if (sc->bnx_link) { 42356c8d8eccSSepherosa Ziehau sc->bnx_link = 0; 42366c8d8eccSSepherosa Ziehau 42376c8d8eccSSepherosa Ziehau if (bootverbose) 42386c8d8eccSSepherosa Ziehau if_printf(ifp, "link DOWN\n"); 42396c8d8eccSSepherosa Ziehau 42406c8d8eccSSepherosa Ziehau ifp->if_link_state = LINK_STATE_DOWN; 42416c8d8eccSSepherosa Ziehau if_link_state_change(ifp); 42426c8d8eccSSepherosa Ziehau } 42436c8d8eccSSepherosa Ziehau } 42446c8d8eccSSepherosa Ziehau 42456c8d8eccSSepherosa Ziehau #undef PCS_ENCODE_ERR 42466c8d8eccSSepherosa Ziehau 42476c8d8eccSSepherosa Ziehau /* Clear the attention. */ 42486c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_MAC_STS, BGE_MACSTAT_SYNC_CHANGED | 42496c8d8eccSSepherosa Ziehau BGE_MACSTAT_CFG_CHANGED | BGE_MACSTAT_MI_COMPLETE | 42506c8d8eccSSepherosa Ziehau BGE_MACSTAT_LINK_CHANGED); 42516c8d8eccSSepherosa Ziehau } 42526c8d8eccSSepherosa Ziehau 42536c8d8eccSSepherosa Ziehau static void 42546c8d8eccSSepherosa Ziehau bnx_copper_link_upd(struct bnx_softc *sc, uint32_t status __unused) 42556c8d8eccSSepherosa Ziehau { 42566c8d8eccSSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if; 42576c8d8eccSSepherosa Ziehau struct mii_data *mii = device_get_softc(sc->bnx_miibus); 42586c8d8eccSSepherosa Ziehau 42596c8d8eccSSepherosa Ziehau mii_pollstat(mii); 42606c8d8eccSSepherosa Ziehau bnx_miibus_statchg(sc->bnx_dev); 42616c8d8eccSSepherosa Ziehau 42626c8d8eccSSepherosa Ziehau if (bootverbose) { 42636c8d8eccSSepherosa Ziehau if (sc->bnx_link) 42646c8d8eccSSepherosa Ziehau if_printf(ifp, "link UP\n"); 42656c8d8eccSSepherosa Ziehau else 42666c8d8eccSSepherosa Ziehau if_printf(ifp, "link DOWN\n"); 42676c8d8eccSSepherosa Ziehau } 42686c8d8eccSSepherosa Ziehau 42696c8d8eccSSepherosa Ziehau /* Clear the attention. */ 42706c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_MAC_STS, BGE_MACSTAT_SYNC_CHANGED | 42716c8d8eccSSepherosa Ziehau BGE_MACSTAT_CFG_CHANGED | BGE_MACSTAT_MI_COMPLETE | 42726c8d8eccSSepherosa Ziehau BGE_MACSTAT_LINK_CHANGED); 42736c8d8eccSSepherosa Ziehau } 42746c8d8eccSSepherosa Ziehau 42756c8d8eccSSepherosa Ziehau static void 42766c8d8eccSSepherosa Ziehau bnx_autopoll_link_upd(struct bnx_softc *sc, uint32_t status __unused) 42776c8d8eccSSepherosa Ziehau { 42786c8d8eccSSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if; 42796c8d8eccSSepherosa Ziehau struct mii_data *mii = device_get_softc(sc->bnx_miibus); 42806c8d8eccSSepherosa Ziehau 42816c8d8eccSSepherosa Ziehau mii_pollstat(mii); 42826c8d8eccSSepherosa Ziehau 42836c8d8eccSSepherosa Ziehau if (!sc->bnx_link && 42846c8d8eccSSepherosa Ziehau (mii->mii_media_status & IFM_ACTIVE) && 42856c8d8eccSSepherosa Ziehau IFM_SUBTYPE(mii->mii_media_active) != IFM_NONE) { 42866c8d8eccSSepherosa Ziehau sc->bnx_link++; 42876c8d8eccSSepherosa Ziehau if (bootverbose) 42886c8d8eccSSepherosa Ziehau if_printf(ifp, "link UP\n"); 42896c8d8eccSSepherosa Ziehau } else if (sc->bnx_link && 42906c8d8eccSSepherosa Ziehau (!(mii->mii_media_status & IFM_ACTIVE) || 42916c8d8eccSSepherosa Ziehau IFM_SUBTYPE(mii->mii_media_active) == IFM_NONE)) { 42926c8d8eccSSepherosa Ziehau sc->bnx_link = 0; 42936c8d8eccSSepherosa Ziehau if (bootverbose) 42946c8d8eccSSepherosa Ziehau if_printf(ifp, "link DOWN\n"); 42956c8d8eccSSepherosa Ziehau } 42966c8d8eccSSepherosa Ziehau 42976c8d8eccSSepherosa Ziehau /* Clear the attention. */ 42986c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_MAC_STS, BGE_MACSTAT_SYNC_CHANGED | 42996c8d8eccSSepherosa Ziehau BGE_MACSTAT_CFG_CHANGED | BGE_MACSTAT_MI_COMPLETE | 43006c8d8eccSSepherosa Ziehau BGE_MACSTAT_LINK_CHANGED); 43016c8d8eccSSepherosa Ziehau } 43026c8d8eccSSepherosa Ziehau 43036c8d8eccSSepherosa Ziehau static int 43046c8d8eccSSepherosa Ziehau bnx_sysctl_rx_coal_ticks(SYSCTL_HANDLER_ARGS) 43056c8d8eccSSepherosa Ziehau { 43066c8d8eccSSepherosa Ziehau struct bnx_softc *sc = arg1; 43076c8d8eccSSepherosa Ziehau 43086c8d8eccSSepherosa Ziehau return bnx_sysctl_coal_chg(oidp, arg1, arg2, req, 43096c8d8eccSSepherosa Ziehau &sc->bnx_rx_coal_ticks, 43106c8d8eccSSepherosa Ziehau BNX_RX_COAL_TICKS_MIN, BNX_RX_COAL_TICKS_MAX, 43116c8d8eccSSepherosa Ziehau BNX_RX_COAL_TICKS_CHG); 43126c8d8eccSSepherosa Ziehau } 43136c8d8eccSSepherosa Ziehau 43146c8d8eccSSepherosa Ziehau static int 43156c8d8eccSSepherosa Ziehau bnx_sysctl_tx_coal_ticks(SYSCTL_HANDLER_ARGS) 43166c8d8eccSSepherosa Ziehau { 43176c8d8eccSSepherosa Ziehau struct bnx_softc *sc = arg1; 43186c8d8eccSSepherosa Ziehau 43196c8d8eccSSepherosa Ziehau return bnx_sysctl_coal_chg(oidp, arg1, arg2, req, 43206c8d8eccSSepherosa Ziehau &sc->bnx_tx_coal_ticks, 43216c8d8eccSSepherosa Ziehau BNX_TX_COAL_TICKS_MIN, BNX_TX_COAL_TICKS_MAX, 43226c8d8eccSSepherosa Ziehau BNX_TX_COAL_TICKS_CHG); 43236c8d8eccSSepherosa Ziehau } 43246c8d8eccSSepherosa Ziehau 43256c8d8eccSSepherosa Ziehau static int 43266c8d8eccSSepherosa Ziehau bnx_sysctl_rx_coal_bds(SYSCTL_HANDLER_ARGS) 43276c8d8eccSSepherosa Ziehau { 43286c8d8eccSSepherosa Ziehau struct bnx_softc *sc = arg1; 43296c8d8eccSSepherosa Ziehau 43306c8d8eccSSepherosa Ziehau return bnx_sysctl_coal_chg(oidp, arg1, arg2, req, 43316c8d8eccSSepherosa Ziehau &sc->bnx_rx_coal_bds, 43326c8d8eccSSepherosa Ziehau BNX_RX_COAL_BDS_MIN, BNX_RX_COAL_BDS_MAX, 43336c8d8eccSSepherosa Ziehau BNX_RX_COAL_BDS_CHG); 43346c8d8eccSSepherosa Ziehau } 43356c8d8eccSSepherosa Ziehau 43366c8d8eccSSepherosa Ziehau static int 43376c8d8eccSSepherosa Ziehau bnx_sysctl_tx_coal_bds(SYSCTL_HANDLER_ARGS) 43386c8d8eccSSepherosa Ziehau { 43396c8d8eccSSepherosa Ziehau struct bnx_softc *sc = arg1; 43406c8d8eccSSepherosa Ziehau 43416c8d8eccSSepherosa Ziehau return bnx_sysctl_coal_chg(oidp, arg1, arg2, req, 43426c8d8eccSSepherosa Ziehau &sc->bnx_tx_coal_bds, 43436c8d8eccSSepherosa Ziehau BNX_TX_COAL_BDS_MIN, BNX_TX_COAL_BDS_MAX, 43446c8d8eccSSepherosa Ziehau BNX_TX_COAL_BDS_CHG); 43456c8d8eccSSepherosa Ziehau } 43466c8d8eccSSepherosa Ziehau 43476c8d8eccSSepherosa Ziehau static int 43486c8d8eccSSepherosa Ziehau bnx_sysctl_rx_coal_bds_int(SYSCTL_HANDLER_ARGS) 43496c8d8eccSSepherosa Ziehau { 43506c8d8eccSSepherosa Ziehau struct bnx_softc *sc = arg1; 43516c8d8eccSSepherosa Ziehau 43526c8d8eccSSepherosa Ziehau return bnx_sysctl_coal_chg(oidp, arg1, arg2, req, 43536c8d8eccSSepherosa Ziehau &sc->bnx_rx_coal_bds_int, 43546c8d8eccSSepherosa Ziehau BNX_RX_COAL_BDS_MIN, BNX_RX_COAL_BDS_MAX, 43556c8d8eccSSepherosa Ziehau BNX_RX_COAL_BDS_INT_CHG); 43566c8d8eccSSepherosa Ziehau } 43576c8d8eccSSepherosa Ziehau 43586c8d8eccSSepherosa Ziehau static int 43596c8d8eccSSepherosa Ziehau bnx_sysctl_tx_coal_bds_int(SYSCTL_HANDLER_ARGS) 43606c8d8eccSSepherosa Ziehau { 43616c8d8eccSSepherosa Ziehau struct bnx_softc *sc = arg1; 43626c8d8eccSSepherosa Ziehau 43636c8d8eccSSepherosa Ziehau return bnx_sysctl_coal_chg(oidp, arg1, arg2, req, 43646c8d8eccSSepherosa Ziehau &sc->bnx_tx_coal_bds_int, 43656c8d8eccSSepherosa Ziehau BNX_TX_COAL_BDS_MIN, BNX_TX_COAL_BDS_MAX, 43666c8d8eccSSepherosa Ziehau BNX_TX_COAL_BDS_INT_CHG); 43676c8d8eccSSepherosa Ziehau } 43686c8d8eccSSepherosa Ziehau 43696c8d8eccSSepherosa Ziehau static int 43706c8d8eccSSepherosa Ziehau bnx_sysctl_coal_chg(SYSCTL_HANDLER_ARGS, uint32_t *coal, 43716c8d8eccSSepherosa Ziehau int coal_min, int coal_max, uint32_t coal_chg_mask) 43726c8d8eccSSepherosa Ziehau { 43736c8d8eccSSepherosa Ziehau struct bnx_softc *sc = arg1; 43746c8d8eccSSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if; 43756c8d8eccSSepherosa Ziehau int error = 0, v; 43766c8d8eccSSepherosa Ziehau 4377329f9016SSepherosa Ziehau ifnet_serialize_all(ifp); 43786c8d8eccSSepherosa Ziehau 43796c8d8eccSSepherosa Ziehau v = *coal; 43806c8d8eccSSepherosa Ziehau error = sysctl_handle_int(oidp, &v, 0, req); 43816c8d8eccSSepherosa Ziehau if (!error && req->newptr != NULL) { 43826c8d8eccSSepherosa Ziehau if (v < coal_min || v > coal_max) { 43836c8d8eccSSepherosa Ziehau error = EINVAL; 43846c8d8eccSSepherosa Ziehau } else { 43856c8d8eccSSepherosa Ziehau *coal = v; 43866c8d8eccSSepherosa Ziehau sc->bnx_coal_chg |= coal_chg_mask; 4387f5014362SSepherosa Ziehau 4388f5014362SSepherosa Ziehau /* Commit changes */ 4389f5014362SSepherosa Ziehau bnx_coal_change(sc); 43906c8d8eccSSepherosa Ziehau } 43916c8d8eccSSepherosa Ziehau } 43926c8d8eccSSepherosa Ziehau 4393329f9016SSepherosa Ziehau ifnet_deserialize_all(ifp); 43946c8d8eccSSepherosa Ziehau return error; 43956c8d8eccSSepherosa Ziehau } 43966c8d8eccSSepherosa Ziehau 43976c8d8eccSSepherosa Ziehau static void 43986c8d8eccSSepherosa Ziehau bnx_coal_change(struct bnx_softc *sc) 43996c8d8eccSSepherosa Ziehau { 44006c8d8eccSSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if; 4401*695a8586SSepherosa Ziehau int i; 44026c8d8eccSSepherosa Ziehau 4403329f9016SSepherosa Ziehau ASSERT_IFNET_SERIALIZED_ALL(ifp); 44046c8d8eccSSepherosa Ziehau 44056c8d8eccSSepherosa Ziehau if (sc->bnx_coal_chg & BNX_RX_COAL_TICKS_CHG) { 4406*695a8586SSepherosa Ziehau if (sc->bnx_rx_retcnt == 1) { 44076c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_HCC_RX_COAL_TICKS, 44086c8d8eccSSepherosa Ziehau sc->bnx_rx_coal_ticks); 4409*695a8586SSepherosa Ziehau i = 0; 4410*695a8586SSepherosa Ziehau } else { 4411*695a8586SSepherosa Ziehau CSR_WRITE_4(sc, BGE_HCC_RX_COAL_TICKS, 0); 4412*695a8586SSepherosa Ziehau for (i = 0; i < sc->bnx_rx_retcnt; ++i) { 4413*695a8586SSepherosa Ziehau CSR_WRITE_4(sc, BGE_VEC1_RX_COAL_TICKS + 4414*695a8586SSepherosa Ziehau (i * BGE_VEC_COALSET_SIZE), 4415*695a8586SSepherosa Ziehau sc->bnx_rx_coal_ticks); 4416*695a8586SSepherosa Ziehau } 4417*695a8586SSepherosa Ziehau } 4418*695a8586SSepherosa Ziehau for (; i < BNX_INTR_MAX - 1; ++i) { 4419*695a8586SSepherosa Ziehau CSR_WRITE_4(sc, BGE_VEC1_RX_COAL_TICKS + 4420*695a8586SSepherosa Ziehau (i * BGE_VEC_COALSET_SIZE), 0); 4421*695a8586SSepherosa Ziehau } 44226c8d8eccSSepherosa Ziehau if (bootverbose) { 44236c8d8eccSSepherosa Ziehau if_printf(ifp, "rx_coal_ticks -> %u\n", 44246c8d8eccSSepherosa Ziehau sc->bnx_rx_coal_ticks); 44256c8d8eccSSepherosa Ziehau } 44266c8d8eccSSepherosa Ziehau } 44276c8d8eccSSepherosa Ziehau 44286c8d8eccSSepherosa Ziehau if (sc->bnx_coal_chg & BNX_TX_COAL_TICKS_CHG) { 4429*695a8586SSepherosa Ziehau if (sc->bnx_tx_ringcnt == 1) { 44306c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_HCC_TX_COAL_TICKS, 44316c8d8eccSSepherosa Ziehau sc->bnx_tx_coal_ticks); 4432*695a8586SSepherosa Ziehau i = 0; 4433*695a8586SSepherosa Ziehau } else { 4434*695a8586SSepherosa Ziehau CSR_WRITE_4(sc, BGE_HCC_TX_COAL_TICKS, 0); 4435*695a8586SSepherosa Ziehau for (i = 0; i < sc->bnx_tx_ringcnt; ++i) { 4436*695a8586SSepherosa Ziehau CSR_WRITE_4(sc, BGE_VEC1_TX_COAL_TICKS + 4437*695a8586SSepherosa Ziehau (i * BGE_VEC_COALSET_SIZE), 4438*695a8586SSepherosa Ziehau sc->bnx_tx_coal_ticks); 4439*695a8586SSepherosa Ziehau } 4440*695a8586SSepherosa Ziehau } 4441*695a8586SSepherosa Ziehau for (; i < BNX_INTR_MAX - 1; ++i) { 4442*695a8586SSepherosa Ziehau CSR_WRITE_4(sc, BGE_VEC1_TX_COAL_TICKS + 4443*695a8586SSepherosa Ziehau (i * BGE_VEC_COALSET_SIZE), 0); 4444*695a8586SSepherosa Ziehau } 44456c8d8eccSSepherosa Ziehau if (bootverbose) { 44466c8d8eccSSepherosa Ziehau if_printf(ifp, "tx_coal_ticks -> %u\n", 44476c8d8eccSSepherosa Ziehau sc->bnx_tx_coal_ticks); 44486c8d8eccSSepherosa Ziehau } 44496c8d8eccSSepherosa Ziehau } 44506c8d8eccSSepherosa Ziehau 44516c8d8eccSSepherosa Ziehau if (sc->bnx_coal_chg & BNX_RX_COAL_BDS_CHG) { 4452*695a8586SSepherosa Ziehau if (sc->bnx_rx_retcnt == 1) { 44536c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_HCC_RX_MAX_COAL_BDS, 44546c8d8eccSSepherosa Ziehau sc->bnx_rx_coal_bds); 4455*695a8586SSepherosa Ziehau i = 0; 4456*695a8586SSepherosa Ziehau } else { 4457*695a8586SSepherosa Ziehau CSR_WRITE_4(sc, BGE_HCC_RX_MAX_COAL_BDS, 0); 4458*695a8586SSepherosa Ziehau for (i = 0; i < sc->bnx_rx_retcnt; ++i) { 4459*695a8586SSepherosa Ziehau CSR_WRITE_4(sc, BGE_VEC1_RX_MAX_COAL_BDS + 4460*695a8586SSepherosa Ziehau (i * BGE_VEC_COALSET_SIZE), 4461*695a8586SSepherosa Ziehau sc->bnx_rx_coal_bds); 4462*695a8586SSepherosa Ziehau } 4463*695a8586SSepherosa Ziehau } 4464*695a8586SSepherosa Ziehau for (; i < BNX_INTR_MAX - 1; ++i) { 4465*695a8586SSepherosa Ziehau CSR_WRITE_4(sc, BGE_VEC1_RX_MAX_COAL_BDS + 4466*695a8586SSepherosa Ziehau (i * BGE_VEC_COALSET_SIZE), 0); 4467*695a8586SSepherosa Ziehau } 44686c8d8eccSSepherosa Ziehau if (bootverbose) { 44696c8d8eccSSepherosa Ziehau if_printf(ifp, "rx_coal_bds -> %u\n", 44706c8d8eccSSepherosa Ziehau sc->bnx_rx_coal_bds); 44716c8d8eccSSepherosa Ziehau } 44726c8d8eccSSepherosa Ziehau } 44736c8d8eccSSepherosa Ziehau 44746c8d8eccSSepherosa Ziehau if (sc->bnx_coal_chg & BNX_TX_COAL_BDS_CHG) { 4475*695a8586SSepherosa Ziehau if (sc->bnx_tx_ringcnt == 1) { 44766c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_HCC_TX_MAX_COAL_BDS, 44776c8d8eccSSepherosa Ziehau sc->bnx_tx_coal_bds); 4478*695a8586SSepherosa Ziehau i = 0; 4479*695a8586SSepherosa Ziehau } else { 4480*695a8586SSepherosa Ziehau CSR_WRITE_4(sc, BGE_HCC_TX_MAX_COAL_BDS, 0); 4481*695a8586SSepherosa Ziehau for (i = 0; i < sc->bnx_tx_ringcnt; ++i) { 4482*695a8586SSepherosa Ziehau CSR_WRITE_4(sc, BGE_VEC1_TX_MAX_COAL_BDS + 4483*695a8586SSepherosa Ziehau (i * BGE_VEC_COALSET_SIZE), 4484*695a8586SSepherosa Ziehau sc->bnx_tx_coal_bds); 4485*695a8586SSepherosa Ziehau } 4486*695a8586SSepherosa Ziehau } 4487*695a8586SSepherosa Ziehau for (; i < BNX_INTR_MAX - 1; ++i) { 4488*695a8586SSepherosa Ziehau CSR_WRITE_4(sc, BGE_VEC1_TX_MAX_COAL_BDS + 4489*695a8586SSepherosa Ziehau (i * BGE_VEC_COALSET_SIZE), 0); 4490*695a8586SSepherosa Ziehau } 44916c8d8eccSSepherosa Ziehau if (bootverbose) { 4492cc98a7c2SSepherosa Ziehau if_printf(ifp, "tx_coal_bds -> %u\n", 44936c8d8eccSSepherosa Ziehau sc->bnx_tx_coal_bds); 44946c8d8eccSSepherosa Ziehau } 44956c8d8eccSSepherosa Ziehau } 44966c8d8eccSSepherosa Ziehau 44976c8d8eccSSepherosa Ziehau if (sc->bnx_coal_chg & BNX_RX_COAL_BDS_INT_CHG) { 4498*695a8586SSepherosa Ziehau if (sc->bnx_rx_retcnt == 1) { 44996c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_HCC_RX_MAX_COAL_BDS_INT, 45006c8d8eccSSepherosa Ziehau sc->bnx_rx_coal_bds_int); 4501*695a8586SSepherosa Ziehau i = 0; 4502*695a8586SSepherosa Ziehau } else { 4503*695a8586SSepherosa Ziehau CSR_WRITE_4(sc, BGE_HCC_RX_MAX_COAL_BDS_INT, 0); 4504*695a8586SSepherosa Ziehau for (i = 0; i < sc->bnx_rx_retcnt; ++i) { 4505*695a8586SSepherosa Ziehau CSR_WRITE_4(sc, BGE_VEC1_RX_MAX_COAL_BDS_INT + 4506*695a8586SSepherosa Ziehau (i * BGE_VEC_COALSET_SIZE), 4507*695a8586SSepherosa Ziehau sc->bnx_rx_coal_bds_int); 4508*695a8586SSepherosa Ziehau } 4509*695a8586SSepherosa Ziehau } 4510*695a8586SSepherosa Ziehau for (; i < BNX_INTR_MAX - 1; ++i) { 4511*695a8586SSepherosa Ziehau CSR_WRITE_4(sc, BGE_VEC1_RX_MAX_COAL_BDS_INT + 4512*695a8586SSepherosa Ziehau (i * BGE_VEC_COALSET_SIZE), 0); 4513*695a8586SSepherosa Ziehau } 45146c8d8eccSSepherosa Ziehau if (bootverbose) { 45156c8d8eccSSepherosa Ziehau if_printf(ifp, "rx_coal_bds_int -> %u\n", 45166c8d8eccSSepherosa Ziehau sc->bnx_rx_coal_bds_int); 45176c8d8eccSSepherosa Ziehau } 45186c8d8eccSSepherosa Ziehau } 45196c8d8eccSSepherosa Ziehau 45206c8d8eccSSepherosa Ziehau if (sc->bnx_coal_chg & BNX_TX_COAL_BDS_INT_CHG) { 4521*695a8586SSepherosa Ziehau if (sc->bnx_tx_ringcnt == 1) { 45226c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_HCC_TX_MAX_COAL_BDS_INT, 45236c8d8eccSSepherosa Ziehau sc->bnx_tx_coal_bds_int); 4524*695a8586SSepherosa Ziehau i = 0; 4525*695a8586SSepherosa Ziehau } else { 4526*695a8586SSepherosa Ziehau CSR_WRITE_4(sc, BGE_HCC_TX_MAX_COAL_BDS_INT, 0); 4527*695a8586SSepherosa Ziehau for (i = 0; i < sc->bnx_tx_ringcnt; ++i) { 4528*695a8586SSepherosa Ziehau CSR_WRITE_4(sc, BGE_VEC1_TX_MAX_COAL_BDS_INT + 4529*695a8586SSepherosa Ziehau (i * BGE_VEC_COALSET_SIZE), 4530*695a8586SSepherosa Ziehau sc->bnx_tx_coal_bds_int); 4531*695a8586SSepherosa Ziehau } 4532*695a8586SSepherosa Ziehau } 4533*695a8586SSepherosa Ziehau for (; i < BNX_INTR_MAX - 1; ++i) { 4534*695a8586SSepherosa Ziehau CSR_WRITE_4(sc, BGE_VEC1_TX_MAX_COAL_BDS_INT + 4535*695a8586SSepherosa Ziehau (i * BGE_VEC_COALSET_SIZE), 0); 4536*695a8586SSepherosa Ziehau } 45376c8d8eccSSepherosa Ziehau if (bootverbose) { 45386c8d8eccSSepherosa Ziehau if_printf(ifp, "tx_coal_bds_int -> %u\n", 45396c8d8eccSSepherosa Ziehau sc->bnx_tx_coal_bds_int); 45406c8d8eccSSepherosa Ziehau } 45416c8d8eccSSepherosa Ziehau } 45426c8d8eccSSepherosa Ziehau 45436c8d8eccSSepherosa Ziehau sc->bnx_coal_chg = 0; 45446c8d8eccSSepherosa Ziehau } 45456c8d8eccSSepherosa Ziehau 45466c8d8eccSSepherosa Ziehau static void 4547*695a8586SSepherosa Ziehau bnx_check_intr_rxtx(void *xintr) 4548df9ccc98SSepherosa Ziehau { 4549f33ac8a4SSepherosa Ziehau struct bnx_intr_data *intr = xintr; 4550f33ac8a4SSepherosa Ziehau struct bnx_rx_ret_ring *ret; 4551f33ac8a4SSepherosa Ziehau struct bnx_tx_ring *txr; 4552f33ac8a4SSepherosa Ziehau struct ifnet *ifp; 4553df9ccc98SSepherosa Ziehau 4554f33ac8a4SSepherosa Ziehau lwkt_serialize_enter(intr->bnx_intr_serialize); 4555df9ccc98SSepherosa Ziehau 4556f33ac8a4SSepherosa Ziehau KKASSERT(mycpuid == intr->bnx_intr_cpuid); 4557df9ccc98SSepherosa Ziehau 4558f33ac8a4SSepherosa Ziehau ifp = &intr->bnx_sc->arpcom.ac_if; 455939a8d43aSSepherosa Ziehau if ((ifp->if_flags & (IFF_RUNNING | IFF_NPOLLING)) != IFF_RUNNING) { 4560f33ac8a4SSepherosa Ziehau lwkt_serialize_exit(intr->bnx_intr_serialize); 4561df9ccc98SSepherosa Ziehau return; 4562df9ccc98SSepherosa Ziehau } 4563df9ccc98SSepherosa Ziehau 4564f33ac8a4SSepherosa Ziehau txr = intr->bnx_txr; 4565f33ac8a4SSepherosa Ziehau ret = intr->bnx_ret; 4566f33ac8a4SSepherosa Ziehau 45673a16b7b8SSepherosa Ziehau if (*ret->bnx_rx_considx != ret->bnx_rx_saved_considx || 45683a16b7b8SSepherosa Ziehau *txr->bnx_tx_considx != txr->bnx_tx_saved_considx) { 4569f33ac8a4SSepherosa Ziehau if (intr->bnx_rx_check_considx == ret->bnx_rx_saved_considx && 4570f33ac8a4SSepherosa Ziehau intr->bnx_tx_check_considx == txr->bnx_tx_saved_considx) { 4571f33ac8a4SSepherosa Ziehau if (!intr->bnx_intr_maylose) { 4572f33ac8a4SSepherosa Ziehau intr->bnx_intr_maylose = TRUE; 4573df9ccc98SSepherosa Ziehau goto done; 4574df9ccc98SSepherosa Ziehau } 4575df9ccc98SSepherosa Ziehau if (bootverbose) 4576df9ccc98SSepherosa Ziehau if_printf(ifp, "lost interrupt\n"); 4577f33ac8a4SSepherosa Ziehau intr->bnx_intr_func(intr->bnx_intr_arg); 4578df9ccc98SSepherosa Ziehau } 4579df9ccc98SSepherosa Ziehau } 4580f33ac8a4SSepherosa Ziehau intr->bnx_intr_maylose = FALSE; 4581f33ac8a4SSepherosa Ziehau intr->bnx_rx_check_considx = ret->bnx_rx_saved_considx; 4582f33ac8a4SSepherosa Ziehau intr->bnx_tx_check_considx = txr->bnx_tx_saved_considx; 4583df9ccc98SSepherosa Ziehau 4584df9ccc98SSepherosa Ziehau done: 4585f33ac8a4SSepherosa Ziehau callout_reset(&intr->bnx_intr_timer, BNX_INTR_CKINTVL, 4586f33ac8a4SSepherosa Ziehau intr->bnx_intr_check, intr); 4587f33ac8a4SSepherosa Ziehau lwkt_serialize_exit(intr->bnx_intr_serialize); 4588df9ccc98SSepherosa Ziehau } 4589df9ccc98SSepherosa Ziehau 4590df9ccc98SSepherosa Ziehau static void 4591*695a8586SSepherosa Ziehau bnx_check_intr_tx(void *xintr) 4592*695a8586SSepherosa Ziehau { 4593*695a8586SSepherosa Ziehau struct bnx_intr_data *intr = xintr; 4594*695a8586SSepherosa Ziehau struct bnx_tx_ring *txr; 4595*695a8586SSepherosa Ziehau struct ifnet *ifp; 4596*695a8586SSepherosa Ziehau 4597*695a8586SSepherosa Ziehau lwkt_serialize_enter(intr->bnx_intr_serialize); 4598*695a8586SSepherosa Ziehau 4599*695a8586SSepherosa Ziehau KKASSERT(mycpuid == intr->bnx_intr_cpuid); 4600*695a8586SSepherosa Ziehau 4601*695a8586SSepherosa Ziehau ifp = &intr->bnx_sc->arpcom.ac_if; 4602*695a8586SSepherosa Ziehau if ((ifp->if_flags & (IFF_RUNNING | IFF_NPOLLING)) != IFF_RUNNING) { 4603*695a8586SSepherosa Ziehau lwkt_serialize_exit(intr->bnx_intr_serialize); 4604*695a8586SSepherosa Ziehau return; 4605*695a8586SSepherosa Ziehau } 4606*695a8586SSepherosa Ziehau 4607*695a8586SSepherosa Ziehau txr = intr->bnx_txr; 4608*695a8586SSepherosa Ziehau 4609*695a8586SSepherosa Ziehau if (*txr->bnx_tx_considx != txr->bnx_tx_saved_considx) { 4610*695a8586SSepherosa Ziehau if (intr->bnx_tx_check_considx == txr->bnx_tx_saved_considx) { 4611*695a8586SSepherosa Ziehau if (!intr->bnx_intr_maylose) { 4612*695a8586SSepherosa Ziehau intr->bnx_intr_maylose = TRUE; 4613*695a8586SSepherosa Ziehau goto done; 4614*695a8586SSepherosa Ziehau } 4615*695a8586SSepherosa Ziehau if (bootverbose) 4616*695a8586SSepherosa Ziehau if_printf(ifp, "lost interrupt\n"); 4617*695a8586SSepherosa Ziehau intr->bnx_intr_func(intr->bnx_intr_arg); 4618*695a8586SSepherosa Ziehau } 4619*695a8586SSepherosa Ziehau } 4620*695a8586SSepherosa Ziehau intr->bnx_intr_maylose = FALSE; 4621*695a8586SSepherosa Ziehau intr->bnx_tx_check_considx = txr->bnx_tx_saved_considx; 4622*695a8586SSepherosa Ziehau 4623*695a8586SSepherosa Ziehau done: 4624*695a8586SSepherosa Ziehau callout_reset(&intr->bnx_intr_timer, BNX_INTR_CKINTVL, 4625*695a8586SSepherosa Ziehau intr->bnx_intr_check, intr); 4626*695a8586SSepherosa Ziehau lwkt_serialize_exit(intr->bnx_intr_serialize); 4627*695a8586SSepherosa Ziehau } 4628*695a8586SSepherosa Ziehau 4629*695a8586SSepherosa Ziehau static void 4630*695a8586SSepherosa Ziehau bnx_check_intr_rx(void *xintr) 4631*695a8586SSepherosa Ziehau { 4632*695a8586SSepherosa Ziehau struct bnx_intr_data *intr = xintr; 4633*695a8586SSepherosa Ziehau struct bnx_rx_ret_ring *ret; 4634*695a8586SSepherosa Ziehau struct ifnet *ifp; 4635*695a8586SSepherosa Ziehau 4636*695a8586SSepherosa Ziehau lwkt_serialize_enter(intr->bnx_intr_serialize); 4637*695a8586SSepherosa Ziehau 4638*695a8586SSepherosa Ziehau KKASSERT(mycpuid == intr->bnx_intr_cpuid); 4639*695a8586SSepherosa Ziehau 4640*695a8586SSepherosa Ziehau ifp = &intr->bnx_sc->arpcom.ac_if; 4641*695a8586SSepherosa Ziehau if ((ifp->if_flags & (IFF_RUNNING | IFF_NPOLLING)) != IFF_RUNNING) { 4642*695a8586SSepherosa Ziehau lwkt_serialize_exit(intr->bnx_intr_serialize); 4643*695a8586SSepherosa Ziehau return; 4644*695a8586SSepherosa Ziehau } 4645*695a8586SSepherosa Ziehau 4646*695a8586SSepherosa Ziehau ret = intr->bnx_ret; 4647*695a8586SSepherosa Ziehau 4648*695a8586SSepherosa Ziehau if (*ret->bnx_rx_considx != ret->bnx_rx_saved_considx) { 4649*695a8586SSepherosa Ziehau if (intr->bnx_rx_check_considx == ret->bnx_rx_saved_considx) { 4650*695a8586SSepherosa Ziehau if (!intr->bnx_intr_maylose) { 4651*695a8586SSepherosa Ziehau intr->bnx_intr_maylose = TRUE; 4652*695a8586SSepherosa Ziehau goto done; 4653*695a8586SSepherosa Ziehau } 4654*695a8586SSepherosa Ziehau if (bootverbose) 4655*695a8586SSepherosa Ziehau if_printf(ifp, "lost interrupt\n"); 4656*695a8586SSepherosa Ziehau intr->bnx_intr_func(intr->bnx_intr_arg); 4657*695a8586SSepherosa Ziehau } 4658*695a8586SSepherosa Ziehau } 4659*695a8586SSepherosa Ziehau intr->bnx_intr_maylose = FALSE; 4660*695a8586SSepherosa Ziehau intr->bnx_rx_check_considx = ret->bnx_rx_saved_considx; 4661*695a8586SSepherosa Ziehau 4662*695a8586SSepherosa Ziehau done: 4663*695a8586SSepherosa Ziehau callout_reset(&intr->bnx_intr_timer, BNX_INTR_CKINTVL, 4664*695a8586SSepherosa Ziehau intr->bnx_intr_check, intr); 4665*695a8586SSepherosa Ziehau lwkt_serialize_exit(intr->bnx_intr_serialize); 4666*695a8586SSepherosa Ziehau } 4667*695a8586SSepherosa Ziehau 4668*695a8586SSepherosa Ziehau static void 46696c8d8eccSSepherosa Ziehau bnx_enable_intr(struct bnx_softc *sc) 46706c8d8eccSSepherosa Ziehau { 46716c8d8eccSSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if; 4672f33ac8a4SSepherosa Ziehau int i; 46736c8d8eccSSepherosa Ziehau 4674f33ac8a4SSepherosa Ziehau for (i = 0; i < sc->bnx_intr_cnt; ++i) { 4675f33ac8a4SSepherosa Ziehau lwkt_serialize_handler_enable( 4676f33ac8a4SSepherosa Ziehau sc->bnx_intr_data[i].bnx_intr_serialize); 4677f33ac8a4SSepherosa Ziehau } 46786c8d8eccSSepherosa Ziehau 46796c8d8eccSSepherosa Ziehau /* 46806c8d8eccSSepherosa Ziehau * Enable interrupt. 46816c8d8eccSSepherosa Ziehau */ 468297ba8fc5SSepherosa Ziehau for (i = 0; i < sc->bnx_intr_cnt; ++i) { 468397ba8fc5SSepherosa Ziehau struct bnx_intr_data *intr = &sc->bnx_intr_data[i]; 468497ba8fc5SSepherosa Ziehau 468597ba8fc5SSepherosa Ziehau bnx_writembx(sc, intr->bnx_intr_mbx, 468697ba8fc5SSepherosa Ziehau (*intr->bnx_saved_status_tag) << 24); 46876c8d8eccSSepherosa Ziehau /* XXX Linux driver */ 468897ba8fc5SSepherosa Ziehau bnx_writembx(sc, intr->bnx_intr_mbx, 468997ba8fc5SSepherosa Ziehau (*intr->bnx_saved_status_tag) << 24); 469097ba8fc5SSepherosa Ziehau } 46916c8d8eccSSepherosa Ziehau 46926c8d8eccSSepherosa Ziehau /* 46936c8d8eccSSepherosa Ziehau * Unmask the interrupt when we stop polling. 46946c8d8eccSSepherosa Ziehau */ 46956c8d8eccSSepherosa Ziehau PCI_CLRBIT(sc->bnx_dev, BGE_PCI_MISC_CTL, 46966c8d8eccSSepherosa Ziehau BGE_PCIMISCCTL_MASK_PCI_INTR, 4); 46976c8d8eccSSepherosa Ziehau 46986c8d8eccSSepherosa Ziehau /* 46996c8d8eccSSepherosa Ziehau * Trigger another interrupt, since above writing 47006c8d8eccSSepherosa Ziehau * to interrupt mailbox0 may acknowledge pending 47016c8d8eccSSepherosa Ziehau * interrupt. 47026c8d8eccSSepherosa Ziehau */ 47036c8d8eccSSepherosa Ziehau BNX_SETBIT(sc, BGE_MISC_LOCAL_CTL, BGE_MLC_INTR_SET); 4704df9ccc98SSepherosa Ziehau 4705df9ccc98SSepherosa Ziehau if (sc->bnx_flags & BNX_FLAG_STATUSTAG_BUG) { 4706df9ccc98SSepherosa Ziehau if (bootverbose) 4707df9ccc98SSepherosa Ziehau if_printf(ifp, "status tag bug workaround\n"); 4708df9ccc98SSepherosa Ziehau 4709f33ac8a4SSepherosa Ziehau for (i = 0; i < sc->bnx_intr_cnt; ++i) { 471097ba8fc5SSepherosa Ziehau struct bnx_intr_data *intr = &sc->bnx_intr_data[i]; 471197ba8fc5SSepherosa Ziehau 4712*695a8586SSepherosa Ziehau if (intr->bnx_intr_check == NULL) 4713*695a8586SSepherosa Ziehau continue; 4714f33ac8a4SSepherosa Ziehau intr->bnx_intr_maylose = FALSE; 4715f33ac8a4SSepherosa Ziehau intr->bnx_rx_check_considx = 0; 4716f33ac8a4SSepherosa Ziehau intr->bnx_tx_check_considx = 0; 4717f33ac8a4SSepherosa Ziehau callout_reset_bycpu(&intr->bnx_intr_timer, 4718f33ac8a4SSepherosa Ziehau BNX_INTR_CKINTVL, intr->bnx_intr_check, intr, 4719f33ac8a4SSepherosa Ziehau intr->bnx_intr_cpuid); 4720f33ac8a4SSepherosa Ziehau } 4721df9ccc98SSepherosa Ziehau } 47226c8d8eccSSepherosa Ziehau } 47236c8d8eccSSepherosa Ziehau 47246c8d8eccSSepherosa Ziehau static void 47256c8d8eccSSepherosa Ziehau bnx_disable_intr(struct bnx_softc *sc) 47266c8d8eccSSepherosa Ziehau { 4727f33ac8a4SSepherosa Ziehau int i; 4728f33ac8a4SSepherosa Ziehau 4729f33ac8a4SSepherosa Ziehau for (i = 0; i < sc->bnx_intr_cnt; ++i) { 4730f33ac8a4SSepherosa Ziehau struct bnx_intr_data *intr = &sc->bnx_intr_data[i]; 4731f33ac8a4SSepherosa Ziehau 4732f33ac8a4SSepherosa Ziehau callout_stop(&intr->bnx_intr_timer); 4733f33ac8a4SSepherosa Ziehau intr->bnx_intr_maylose = FALSE; 4734f33ac8a4SSepherosa Ziehau intr->bnx_rx_check_considx = 0; 4735f33ac8a4SSepherosa Ziehau intr->bnx_tx_check_considx = 0; 4736f33ac8a4SSepherosa Ziehau } 47376c8d8eccSSepherosa Ziehau 47386c8d8eccSSepherosa Ziehau /* 47396c8d8eccSSepherosa Ziehau * Mask the interrupt when we start polling. 47406c8d8eccSSepherosa Ziehau */ 47416c8d8eccSSepherosa Ziehau PCI_SETBIT(sc->bnx_dev, BGE_PCI_MISC_CTL, 47426c8d8eccSSepherosa Ziehau BGE_PCIMISCCTL_MASK_PCI_INTR, 4); 47436c8d8eccSSepherosa Ziehau 47446c8d8eccSSepherosa Ziehau /* 47456c8d8eccSSepherosa Ziehau * Acknowledge possible asserted interrupt. 47466c8d8eccSSepherosa Ziehau */ 4747*695a8586SSepherosa Ziehau for (i = 0; i < BNX_INTR_MAX; ++i) 474897ba8fc5SSepherosa Ziehau bnx_writembx(sc, sc->bnx_intr_data[i].bnx_intr_mbx, 1); 47496c8d8eccSSepherosa Ziehau 4750f33ac8a4SSepherosa Ziehau for (i = 0; i < sc->bnx_intr_cnt; ++i) { 4751f33ac8a4SSepherosa Ziehau lwkt_serialize_handler_disable( 4752f33ac8a4SSepherosa Ziehau sc->bnx_intr_data[i].bnx_intr_serialize); 4753f33ac8a4SSepherosa Ziehau } 47546c8d8eccSSepherosa Ziehau } 47556c8d8eccSSepherosa Ziehau 47566c8d8eccSSepherosa Ziehau static int 47576c8d8eccSSepherosa Ziehau bnx_get_eaddr_mem(struct bnx_softc *sc, uint8_t ether_addr[]) 47586c8d8eccSSepherosa Ziehau { 47596c8d8eccSSepherosa Ziehau uint32_t mac_addr; 47606c8d8eccSSepherosa Ziehau int ret = 1; 47616c8d8eccSSepherosa Ziehau 47626c8d8eccSSepherosa Ziehau mac_addr = bnx_readmem_ind(sc, 0x0c14); 47636c8d8eccSSepherosa Ziehau if ((mac_addr >> 16) == 0x484b) { 47646c8d8eccSSepherosa Ziehau ether_addr[0] = (uint8_t)(mac_addr >> 8); 47656c8d8eccSSepherosa Ziehau ether_addr[1] = (uint8_t)mac_addr; 47666c8d8eccSSepherosa Ziehau mac_addr = bnx_readmem_ind(sc, 0x0c18); 47676c8d8eccSSepherosa Ziehau ether_addr[2] = (uint8_t)(mac_addr >> 24); 47686c8d8eccSSepherosa Ziehau ether_addr[3] = (uint8_t)(mac_addr >> 16); 47696c8d8eccSSepherosa Ziehau ether_addr[4] = (uint8_t)(mac_addr >> 8); 47706c8d8eccSSepherosa Ziehau ether_addr[5] = (uint8_t)mac_addr; 47716c8d8eccSSepherosa Ziehau ret = 0; 47726c8d8eccSSepherosa Ziehau } 47736c8d8eccSSepherosa Ziehau return ret; 47746c8d8eccSSepherosa Ziehau } 47756c8d8eccSSepherosa Ziehau 47766c8d8eccSSepherosa Ziehau static int 47776c8d8eccSSepherosa Ziehau bnx_get_eaddr_nvram(struct bnx_softc *sc, uint8_t ether_addr[]) 47786c8d8eccSSepherosa Ziehau { 47796c8d8eccSSepherosa Ziehau int mac_offset = BGE_EE_MAC_OFFSET; 47806c8d8eccSSepherosa Ziehau 478180969639SSepherosa Ziehau if (BNX_IS_5717_PLUS(sc)) { 478280969639SSepherosa Ziehau int f; 478380969639SSepherosa Ziehau 478480969639SSepherosa Ziehau f = pci_get_function(sc->bnx_dev); 478580969639SSepherosa Ziehau if (f & 1) 478680969639SSepherosa Ziehau mac_offset = BGE_EE_MAC_OFFSET_5717; 478780969639SSepherosa Ziehau if (f > 1) 478880969639SSepherosa Ziehau mac_offset += BGE_EE_MAC_OFFSET_5717_OFF; 478980969639SSepherosa Ziehau } 47906c8d8eccSSepherosa Ziehau 47916c8d8eccSSepherosa Ziehau return bnx_read_nvram(sc, ether_addr, mac_offset + 2, ETHER_ADDR_LEN); 47926c8d8eccSSepherosa Ziehau } 47936c8d8eccSSepherosa Ziehau 47946c8d8eccSSepherosa Ziehau static int 47956c8d8eccSSepherosa Ziehau bnx_get_eaddr_eeprom(struct bnx_softc *sc, uint8_t ether_addr[]) 47966c8d8eccSSepherosa Ziehau { 47976c8d8eccSSepherosa Ziehau if (sc->bnx_flags & BNX_FLAG_NO_EEPROM) 47986c8d8eccSSepherosa Ziehau return 1; 47996c8d8eccSSepherosa Ziehau 48006c8d8eccSSepherosa Ziehau return bnx_read_eeprom(sc, ether_addr, BGE_EE_MAC_OFFSET + 2, 48016c8d8eccSSepherosa Ziehau ETHER_ADDR_LEN); 48026c8d8eccSSepherosa Ziehau } 48036c8d8eccSSepherosa Ziehau 48046c8d8eccSSepherosa Ziehau static int 48056c8d8eccSSepherosa Ziehau bnx_get_eaddr(struct bnx_softc *sc, uint8_t eaddr[]) 48066c8d8eccSSepherosa Ziehau { 48076c8d8eccSSepherosa Ziehau static const bnx_eaddr_fcn_t bnx_eaddr_funcs[] = { 48086c8d8eccSSepherosa Ziehau /* NOTE: Order is critical */ 48096c8d8eccSSepherosa Ziehau bnx_get_eaddr_mem, 48106c8d8eccSSepherosa Ziehau bnx_get_eaddr_nvram, 48116c8d8eccSSepherosa Ziehau bnx_get_eaddr_eeprom, 48126c8d8eccSSepherosa Ziehau NULL 48136c8d8eccSSepherosa Ziehau }; 48146c8d8eccSSepherosa Ziehau const bnx_eaddr_fcn_t *func; 48156c8d8eccSSepherosa Ziehau 48166c8d8eccSSepherosa Ziehau for (func = bnx_eaddr_funcs; *func != NULL; ++func) { 48176c8d8eccSSepherosa Ziehau if ((*func)(sc, eaddr) == 0) 48186c8d8eccSSepherosa Ziehau break; 48196c8d8eccSSepherosa Ziehau } 48206c8d8eccSSepherosa Ziehau return (*func == NULL ? ENXIO : 0); 48216c8d8eccSSepherosa Ziehau } 48226c8d8eccSSepherosa Ziehau 48236c8d8eccSSepherosa Ziehau /* 48246c8d8eccSSepherosa Ziehau * NOTE: 'm' is not freed upon failure 48256c8d8eccSSepherosa Ziehau */ 48266c8d8eccSSepherosa Ziehau struct mbuf * 48276c8d8eccSSepherosa Ziehau bnx_defrag_shortdma(struct mbuf *m) 48286c8d8eccSSepherosa Ziehau { 48296c8d8eccSSepherosa Ziehau struct mbuf *n; 48306c8d8eccSSepherosa Ziehau int found; 48316c8d8eccSSepherosa Ziehau 48326c8d8eccSSepherosa Ziehau /* 48336c8d8eccSSepherosa Ziehau * If device receive two back-to-back send BDs with less than 48346c8d8eccSSepherosa Ziehau * or equal to 8 total bytes then the device may hang. The two 48356c8d8eccSSepherosa Ziehau * back-to-back send BDs must in the same frame for this failure 48366c8d8eccSSepherosa Ziehau * to occur. Scan mbuf chains and see whether two back-to-back 48376c8d8eccSSepherosa Ziehau * send BDs are there. If this is the case, allocate new mbuf 48386c8d8eccSSepherosa Ziehau * and copy the frame to workaround the silicon bug. 48396c8d8eccSSepherosa Ziehau */ 48406c8d8eccSSepherosa Ziehau for (n = m, found = 0; n != NULL; n = n->m_next) { 48416c8d8eccSSepherosa Ziehau if (n->m_len < 8) { 48426c8d8eccSSepherosa Ziehau found++; 48436c8d8eccSSepherosa Ziehau if (found > 1) 48446c8d8eccSSepherosa Ziehau break; 48456c8d8eccSSepherosa Ziehau continue; 48466c8d8eccSSepherosa Ziehau } 48476c8d8eccSSepherosa Ziehau found = 0; 48486c8d8eccSSepherosa Ziehau } 48496c8d8eccSSepherosa Ziehau 48506c8d8eccSSepherosa Ziehau if (found > 1) 48516c8d8eccSSepherosa Ziehau n = m_defrag(m, MB_DONTWAIT); 48526c8d8eccSSepherosa Ziehau else 48536c8d8eccSSepherosa Ziehau n = m; 48546c8d8eccSSepherosa Ziehau return n; 48556c8d8eccSSepherosa Ziehau } 48566c8d8eccSSepherosa Ziehau 48576c8d8eccSSepherosa Ziehau static void 48586c8d8eccSSepherosa Ziehau bnx_stop_block(struct bnx_softc *sc, bus_size_t reg, uint32_t bit) 48596c8d8eccSSepherosa Ziehau { 48606c8d8eccSSepherosa Ziehau int i; 48616c8d8eccSSepherosa Ziehau 48626c8d8eccSSepherosa Ziehau BNX_CLRBIT(sc, reg, bit); 48636c8d8eccSSepherosa Ziehau for (i = 0; i < BNX_TIMEOUT; i++) { 48646c8d8eccSSepherosa Ziehau if ((CSR_READ_4(sc, reg) & bit) == 0) 48656c8d8eccSSepherosa Ziehau return; 48666c8d8eccSSepherosa Ziehau DELAY(100); 48676c8d8eccSSepherosa Ziehau } 48686c8d8eccSSepherosa Ziehau } 48696c8d8eccSSepherosa Ziehau 48706c8d8eccSSepherosa Ziehau static void 48716c8d8eccSSepherosa Ziehau bnx_link_poll(struct bnx_softc *sc) 48726c8d8eccSSepherosa Ziehau { 48736c8d8eccSSepherosa Ziehau uint32_t status; 48746c8d8eccSSepherosa Ziehau 48756c8d8eccSSepherosa Ziehau status = CSR_READ_4(sc, BGE_MAC_STS); 48766c8d8eccSSepherosa Ziehau if ((status & sc->bnx_link_chg) || sc->bnx_link_evt) { 48776c8d8eccSSepherosa Ziehau sc->bnx_link_evt = 0; 48786c8d8eccSSepherosa Ziehau sc->bnx_link_upd(sc, status); 48796c8d8eccSSepherosa Ziehau } 48806c8d8eccSSepherosa Ziehau } 48816c8d8eccSSepherosa Ziehau 48826c8d8eccSSepherosa Ziehau static void 4883*695a8586SSepherosa Ziehau bnx_enable_msi(struct bnx_softc *sc, boolean_t is_msix) 48846c8d8eccSSepherosa Ziehau { 48856c8d8eccSSepherosa Ziehau uint32_t msi_mode; 48866c8d8eccSSepherosa Ziehau 48876c8d8eccSSepherosa Ziehau msi_mode = CSR_READ_4(sc, BGE_MSI_MODE); 48886c8d8eccSSepherosa Ziehau msi_mode |= BGE_MSIMODE_ENABLE; 48896c8d8eccSSepherosa Ziehau /* 48906c8d8eccSSepherosa Ziehau * NOTE: 48910b4feeacSSepherosa Ziehau * 5718-PG105-R says that "one shot" mode does not work 48920b4feeacSSepherosa Ziehau * if MSI is used, however, it obviously works. 48936c8d8eccSSepherosa Ziehau */ 48946c8d8eccSSepherosa Ziehau msi_mode &= ~BGE_MSIMODE_ONESHOT_DISABLE; 4895*695a8586SSepherosa Ziehau if (is_msix) 4896*695a8586SSepherosa Ziehau msi_mode |= BGE_MSIMODE_MSIX_MULTIMODE; 4897*695a8586SSepherosa Ziehau else 4898*695a8586SSepherosa Ziehau msi_mode &= ~BGE_MSIMODE_MSIX_MULTIMODE; 48996c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_MSI_MODE, msi_mode); 49006c8d8eccSSepherosa Ziehau } 49016c8d8eccSSepherosa Ziehau 49026c8d8eccSSepherosa Ziehau static uint32_t 49036c8d8eccSSepherosa Ziehau bnx_dma_swap_options(struct bnx_softc *sc) 49046c8d8eccSSepherosa Ziehau { 49056c8d8eccSSepherosa Ziehau uint32_t dma_options; 49066c8d8eccSSepherosa Ziehau 49076c8d8eccSSepherosa Ziehau dma_options = BGE_MODECTL_WORDSWAP_NONFRAME | 49086c8d8eccSSepherosa Ziehau BGE_MODECTL_BYTESWAP_DATA | BGE_MODECTL_WORDSWAP_DATA; 49096c8d8eccSSepherosa Ziehau #if BYTE_ORDER == BIG_ENDIAN 49106c8d8eccSSepherosa Ziehau dma_options |= BGE_MODECTL_BYTESWAP_NONFRAME; 49116c8d8eccSSepherosa Ziehau #endif 4912b96cbbb6SSepherosa Ziehau if (sc->bnx_asicrev == BGE_ASICREV_BCM5720 || 4913b96cbbb6SSepherosa Ziehau sc->bnx_asicrev == BGE_ASICREV_BCM5762) { 49146c8d8eccSSepherosa Ziehau dma_options |= BGE_MODECTL_BYTESWAP_B2HRX_DATA | 49156c8d8eccSSepherosa Ziehau BGE_MODECTL_WORDSWAP_B2HRX_DATA | BGE_MODECTL_B2HRX_ENABLE | 49166c8d8eccSSepherosa Ziehau BGE_MODECTL_HTX2B_ENABLE; 49176c8d8eccSSepherosa Ziehau } 49186c8d8eccSSepherosa Ziehau return dma_options; 49196c8d8eccSSepherosa Ziehau } 492066deb1c1SSepherosa Ziehau 492166deb1c1SSepherosa Ziehau static int 492233a04907SSepherosa Ziehau bnx_setup_tso(struct bnx_tx_ring *txr, struct mbuf **mp, 492366deb1c1SSepherosa Ziehau uint16_t *mss0, uint16_t *flags0) 492466deb1c1SSepherosa Ziehau { 492566deb1c1SSepherosa Ziehau struct mbuf *m; 492666deb1c1SSepherosa Ziehau struct ip *ip; 492766deb1c1SSepherosa Ziehau struct tcphdr *th; 492866deb1c1SSepherosa Ziehau int thoff, iphlen, hoff, hlen; 492966deb1c1SSepherosa Ziehau uint16_t flags, mss; 493066deb1c1SSepherosa Ziehau 4931f7a2269aSSepherosa Ziehau m = *mp; 4932f7a2269aSSepherosa Ziehau KASSERT(M_WRITABLE(m), ("TSO mbuf not writable")); 4933f7a2269aSSepherosa Ziehau 4934f7a2269aSSepherosa Ziehau hoff = m->m_pkthdr.csum_lhlen; 4935f7a2269aSSepherosa Ziehau iphlen = m->m_pkthdr.csum_iphlen; 4936f7a2269aSSepherosa Ziehau thoff = m->m_pkthdr.csum_thlen; 4937f7a2269aSSepherosa Ziehau 4938f7a2269aSSepherosa Ziehau KASSERT(hoff > 0, ("invalid ether header len")); 4939f7a2269aSSepherosa Ziehau KASSERT(iphlen > 0, ("invalid ip header len")); 4940f7a2269aSSepherosa Ziehau KASSERT(thoff > 0, ("invalid tcp header len")); 4941f7a2269aSSepherosa Ziehau 4942f7a2269aSSepherosa Ziehau if (__predict_false(m->m_len < hoff + iphlen + thoff)) { 4943f7a2269aSSepherosa Ziehau m = m_pullup(m, hoff + iphlen + thoff); 4944f7a2269aSSepherosa Ziehau if (m == NULL) { 4945f7a2269aSSepherosa Ziehau *mp = NULL; 4946f7a2269aSSepherosa Ziehau return ENOBUFS; 4947f7a2269aSSepherosa Ziehau } 4948f7a2269aSSepherosa Ziehau *mp = m; 4949f7a2269aSSepherosa Ziehau } 4950f7a2269aSSepherosa Ziehau ip = mtodoff(m, struct ip *, hoff); 4951f7a2269aSSepherosa Ziehau th = mtodoff(m, struct tcphdr *, hoff + iphlen); 4952f7a2269aSSepherosa Ziehau 4953f0336d39SSepherosa Ziehau mss = m->m_pkthdr.tso_segsz; 495466deb1c1SSepherosa Ziehau flags = BGE_TXBDFLAG_CPU_PRE_DMA | BGE_TXBDFLAG_CPU_POST_DMA; 495566deb1c1SSepherosa Ziehau 495666deb1c1SSepherosa Ziehau ip->ip_len = htons(mss + iphlen + thoff); 495766deb1c1SSepherosa Ziehau th->th_sum = 0; 495866deb1c1SSepherosa Ziehau 495966deb1c1SSepherosa Ziehau hlen = (iphlen + thoff) >> 2; 496066deb1c1SSepherosa Ziehau mss |= ((hlen & 0x3) << 14); 496166deb1c1SSepherosa Ziehau flags |= ((hlen & 0xf8) << 7) | ((hlen & 0x4) << 2); 496266deb1c1SSepherosa Ziehau 496366deb1c1SSepherosa Ziehau *mss0 = mss; 496466deb1c1SSepherosa Ziehau *flags0 = flags; 496566deb1c1SSepherosa Ziehau 496666deb1c1SSepherosa Ziehau return 0; 496766deb1c1SSepherosa Ziehau } 496833a04907SSepherosa Ziehau 496933a04907SSepherosa Ziehau static int 497033a04907SSepherosa Ziehau bnx_create_tx_ring(struct bnx_tx_ring *txr) 497133a04907SSepherosa Ziehau { 497233a04907SSepherosa Ziehau bus_size_t txmaxsz, txmaxsegsz; 497333a04907SSepherosa Ziehau int i, error; 497433a04907SSepherosa Ziehau 4975329f9016SSepherosa Ziehau lwkt_serialize_init(&txr->bnx_tx_serialize); 4976329f9016SSepherosa Ziehau 497733a04907SSepherosa Ziehau /* 497833a04907SSepherosa Ziehau * Create DMA tag and maps for TX mbufs. 497933a04907SSepherosa Ziehau */ 498033a04907SSepherosa Ziehau if (txr->bnx_sc->bnx_flags & BNX_FLAG_TSO) 498133a04907SSepherosa Ziehau txmaxsz = IP_MAXPACKET + sizeof(struct ether_vlan_header); 498233a04907SSepherosa Ziehau else 498333a04907SSepherosa Ziehau txmaxsz = BNX_JUMBO_FRAMELEN; 498433a04907SSepherosa Ziehau if (txr->bnx_sc->bnx_asicrev == BGE_ASICREV_BCM57766) 498533a04907SSepherosa Ziehau txmaxsegsz = MCLBYTES; 498633a04907SSepherosa Ziehau else 498733a04907SSepherosa Ziehau txmaxsegsz = PAGE_SIZE; 498833a04907SSepherosa Ziehau error = bus_dma_tag_create(txr->bnx_sc->bnx_cdata.bnx_parent_tag, 498933a04907SSepherosa Ziehau 1, 0, BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL, NULL, 499033a04907SSepherosa Ziehau txmaxsz, BNX_NSEG_NEW, txmaxsegsz, 499133a04907SSepherosa Ziehau BUS_DMA_ALLOCNOW | BUS_DMA_WAITOK | BUS_DMA_ONEBPAGE, 499233a04907SSepherosa Ziehau &txr->bnx_tx_mtag); 499333a04907SSepherosa Ziehau if (error) { 499433a04907SSepherosa Ziehau device_printf(txr->bnx_sc->bnx_dev, 4995beedf5beSSepherosa Ziehau "could not create TX mbuf DMA tag\n"); 499633a04907SSepherosa Ziehau return error; 499733a04907SSepherosa Ziehau } 499833a04907SSepherosa Ziehau 499933a04907SSepherosa Ziehau for (i = 0; i < BGE_TX_RING_CNT; i++) { 500033a04907SSepherosa Ziehau error = bus_dmamap_create(txr->bnx_tx_mtag, 500133a04907SSepherosa Ziehau BUS_DMA_WAITOK | BUS_DMA_ONEBPAGE, 5002fa4b1067SSepherosa Ziehau &txr->bnx_tx_buf[i].bnx_tx_dmamap); 500333a04907SSepherosa Ziehau if (error) { 500433a04907SSepherosa Ziehau int j; 500533a04907SSepherosa Ziehau 500633a04907SSepherosa Ziehau for (j = 0; j < i; ++j) { 500733a04907SSepherosa Ziehau bus_dmamap_destroy(txr->bnx_tx_mtag, 5008fa4b1067SSepherosa Ziehau txr->bnx_tx_buf[j].bnx_tx_dmamap); 500933a04907SSepherosa Ziehau } 501033a04907SSepherosa Ziehau bus_dma_tag_destroy(txr->bnx_tx_mtag); 501133a04907SSepherosa Ziehau txr->bnx_tx_mtag = NULL; 501233a04907SSepherosa Ziehau 501333a04907SSepherosa Ziehau device_printf(txr->bnx_sc->bnx_dev, 5014beedf5beSSepherosa Ziehau "could not create TX mbuf DMA map\n"); 501533a04907SSepherosa Ziehau return error; 501633a04907SSepherosa Ziehau } 501733a04907SSepherosa Ziehau } 501833a04907SSepherosa Ziehau 501933a04907SSepherosa Ziehau /* 502033a04907SSepherosa Ziehau * Create DMA stuffs for TX ring. 502133a04907SSepherosa Ziehau */ 502233a04907SSepherosa Ziehau error = bnx_dma_block_alloc(txr->bnx_sc, BGE_TX_RING_SZ, 5023beedf5beSSepherosa Ziehau &txr->bnx_tx_ring_tag, 5024beedf5beSSepherosa Ziehau &txr->bnx_tx_ring_map, 5025beedf5beSSepherosa Ziehau (void *)&txr->bnx_tx_ring, 5026beedf5beSSepherosa Ziehau &txr->bnx_tx_ring_paddr); 502733a04907SSepherosa Ziehau if (error) { 502833a04907SSepherosa Ziehau device_printf(txr->bnx_sc->bnx_dev, 502933a04907SSepherosa Ziehau "could not create TX ring\n"); 503033a04907SSepherosa Ziehau return error; 503133a04907SSepherosa Ziehau } 503233a04907SSepherosa Ziehau 503379a64343SSepherosa Ziehau txr->bnx_tx_flags |= BNX_TX_FLAG_SHORTDMA; 503433a04907SSepherosa Ziehau txr->bnx_tx_wreg = BNX_TX_WREG_NSEGS; 503533a04907SSepherosa Ziehau 503633a04907SSepherosa Ziehau return 0; 503733a04907SSepherosa Ziehau } 503833a04907SSepherosa Ziehau 503933a04907SSepherosa Ziehau static void 504033a04907SSepherosa Ziehau bnx_destroy_tx_ring(struct bnx_tx_ring *txr) 504133a04907SSepherosa Ziehau { 504233a04907SSepherosa Ziehau /* Destroy TX mbuf DMA stuffs. */ 504333a04907SSepherosa Ziehau if (txr->bnx_tx_mtag != NULL) { 504433a04907SSepherosa Ziehau int i; 504533a04907SSepherosa Ziehau 504633a04907SSepherosa Ziehau for (i = 0; i < BGE_TX_RING_CNT; i++) { 5047fa4b1067SSepherosa Ziehau KKASSERT(txr->bnx_tx_buf[i].bnx_tx_mbuf == NULL); 504833a04907SSepherosa Ziehau bus_dmamap_destroy(txr->bnx_tx_mtag, 5049fa4b1067SSepherosa Ziehau txr->bnx_tx_buf[i].bnx_tx_dmamap); 505033a04907SSepherosa Ziehau } 505133a04907SSepherosa Ziehau bus_dma_tag_destroy(txr->bnx_tx_mtag); 505233a04907SSepherosa Ziehau } 505333a04907SSepherosa Ziehau 505433a04907SSepherosa Ziehau /* Destroy TX ring */ 505533a04907SSepherosa Ziehau bnx_dma_block_free(txr->bnx_tx_ring_tag, 505633a04907SSepherosa Ziehau txr->bnx_tx_ring_map, txr->bnx_tx_ring); 505733a04907SSepherosa Ziehau } 5058aad4de2bSSepherosa Ziehau 5059aad4de2bSSepherosa Ziehau static int 5060aad4de2bSSepherosa Ziehau bnx_sysctl_force_defrag(SYSCTL_HANDLER_ARGS) 5061aad4de2bSSepherosa Ziehau { 5062aad4de2bSSepherosa Ziehau struct bnx_softc *sc = (void *)arg1; 5063aad4de2bSSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if; 5064aad4de2bSSepherosa Ziehau struct bnx_tx_ring *txr = &sc->bnx_tx_ring[0]; 5065aad4de2bSSepherosa Ziehau int error, defrag, i; 5066aad4de2bSSepherosa Ziehau 5067aad4de2bSSepherosa Ziehau if (txr->bnx_tx_flags & BNX_TX_FLAG_FORCE_DEFRAG) 5068aad4de2bSSepherosa Ziehau defrag = 1; 5069aad4de2bSSepherosa Ziehau else 5070aad4de2bSSepherosa Ziehau defrag = 0; 5071aad4de2bSSepherosa Ziehau 5072aad4de2bSSepherosa Ziehau error = sysctl_handle_int(oidp, &defrag, 0, req); 5073aad4de2bSSepherosa Ziehau if (error || req->newptr == NULL) 5074aad4de2bSSepherosa Ziehau return error; 5075aad4de2bSSepherosa Ziehau 5076329f9016SSepherosa Ziehau ifnet_serialize_all(ifp); 5077aad4de2bSSepherosa Ziehau for (i = 0; i < sc->bnx_tx_ringcnt; ++i) { 5078aad4de2bSSepherosa Ziehau txr = &sc->bnx_tx_ring[i]; 5079aad4de2bSSepherosa Ziehau if (defrag) 5080aad4de2bSSepherosa Ziehau txr->bnx_tx_flags |= BNX_TX_FLAG_FORCE_DEFRAG; 5081aad4de2bSSepherosa Ziehau else 5082aad4de2bSSepherosa Ziehau txr->bnx_tx_flags &= ~BNX_TX_FLAG_FORCE_DEFRAG; 5083aad4de2bSSepherosa Ziehau } 5084329f9016SSepherosa Ziehau ifnet_deserialize_all(ifp); 5085aad4de2bSSepherosa Ziehau 5086aad4de2bSSepherosa Ziehau return 0; 5087aad4de2bSSepherosa Ziehau } 5088472c99c8SSepherosa Ziehau 5089472c99c8SSepherosa Ziehau static int 5090472c99c8SSepherosa Ziehau bnx_sysctl_tx_wreg(SYSCTL_HANDLER_ARGS) 5091472c99c8SSepherosa Ziehau { 5092472c99c8SSepherosa Ziehau struct bnx_softc *sc = (void *)arg1; 5093472c99c8SSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if; 5094472c99c8SSepherosa Ziehau struct bnx_tx_ring *txr = &sc->bnx_tx_ring[0]; 5095472c99c8SSepherosa Ziehau int error, tx_wreg, i; 5096472c99c8SSepherosa Ziehau 5097472c99c8SSepherosa Ziehau tx_wreg = txr->bnx_tx_wreg; 5098472c99c8SSepherosa Ziehau error = sysctl_handle_int(oidp, &tx_wreg, 0, req); 5099472c99c8SSepherosa Ziehau if (error || req->newptr == NULL) 5100472c99c8SSepherosa Ziehau return error; 5101472c99c8SSepherosa Ziehau 5102329f9016SSepherosa Ziehau ifnet_serialize_all(ifp); 5103472c99c8SSepherosa Ziehau for (i = 0; i < sc->bnx_tx_ringcnt; ++i) 5104472c99c8SSepherosa Ziehau sc->bnx_tx_ring[i].bnx_tx_wreg = tx_wreg; 5105329f9016SSepherosa Ziehau ifnet_deserialize_all(ifp); 5106472c99c8SSepherosa Ziehau 5107472c99c8SSepherosa Ziehau return 0; 5108472c99c8SSepherosa Ziehau } 5109beedf5beSSepherosa Ziehau 5110beedf5beSSepherosa Ziehau static int 5111beedf5beSSepherosa Ziehau bnx_create_rx_ret_ring(struct bnx_rx_ret_ring *ret) 5112beedf5beSSepherosa Ziehau { 5113beedf5beSSepherosa Ziehau int error; 5114beedf5beSSepherosa Ziehau 5115329f9016SSepherosa Ziehau lwkt_serialize_init(&ret->bnx_rx_ret_serialize); 5116329f9016SSepherosa Ziehau 5117beedf5beSSepherosa Ziehau /* 5118beedf5beSSepherosa Ziehau * Create DMA stuffs for RX return ring. 5119beedf5beSSepherosa Ziehau */ 5120beedf5beSSepherosa Ziehau error = bnx_dma_block_alloc(ret->bnx_sc, 5121beedf5beSSepherosa Ziehau BGE_RX_RTN_RING_SZ(BNX_RETURN_RING_CNT), 5122beedf5beSSepherosa Ziehau &ret->bnx_rx_ret_ring_tag, 5123beedf5beSSepherosa Ziehau &ret->bnx_rx_ret_ring_map, 5124beedf5beSSepherosa Ziehau (void *)&ret->bnx_rx_ret_ring, 5125beedf5beSSepherosa Ziehau &ret->bnx_rx_ret_ring_paddr); 5126beedf5beSSepherosa Ziehau if (error) { 5127beedf5beSSepherosa Ziehau device_printf(ret->bnx_sc->bnx_dev, 5128beedf5beSSepherosa Ziehau "could not create RX ret ring\n"); 5129beedf5beSSepherosa Ziehau return error; 5130beedf5beSSepherosa Ziehau } 5131beedf5beSSepherosa Ziehau 5132beedf5beSSepherosa Ziehau /* Shadow standard ring's RX mbuf DMA tag */ 5133beedf5beSSepherosa Ziehau ret->bnx_rx_mtag = ret->bnx_std->bnx_rx_mtag; 5134beedf5beSSepherosa Ziehau 5135beedf5beSSepherosa Ziehau /* 5136beedf5beSSepherosa Ziehau * Create tmp DMA map for RX mbufs. 5137beedf5beSSepherosa Ziehau */ 5138beedf5beSSepherosa Ziehau error = bus_dmamap_create(ret->bnx_rx_mtag, BUS_DMA_WAITOK, 5139beedf5beSSepherosa Ziehau &ret->bnx_rx_tmpmap); 5140beedf5beSSepherosa Ziehau if (error) { 5141beedf5beSSepherosa Ziehau device_printf(ret->bnx_sc->bnx_dev, 5142beedf5beSSepherosa Ziehau "could not create tmp RX mbuf DMA map\n"); 5143beedf5beSSepherosa Ziehau ret->bnx_rx_mtag = NULL; 5144beedf5beSSepherosa Ziehau return error; 5145beedf5beSSepherosa Ziehau } 5146beedf5beSSepherosa Ziehau return 0; 5147beedf5beSSepherosa Ziehau } 5148beedf5beSSepherosa Ziehau 5149beedf5beSSepherosa Ziehau static void 5150beedf5beSSepherosa Ziehau bnx_destroy_rx_ret_ring(struct bnx_rx_ret_ring *ret) 5151beedf5beSSepherosa Ziehau { 5152beedf5beSSepherosa Ziehau /* Destroy tmp RX mbuf DMA map */ 5153beedf5beSSepherosa Ziehau if (ret->bnx_rx_mtag != NULL) 5154beedf5beSSepherosa Ziehau bus_dmamap_destroy(ret->bnx_rx_mtag, ret->bnx_rx_tmpmap); 5155beedf5beSSepherosa Ziehau 5156beedf5beSSepherosa Ziehau /* Destroy RX return ring */ 5157beedf5beSSepherosa Ziehau bnx_dma_block_free(ret->bnx_rx_ret_ring_tag, 5158beedf5beSSepherosa Ziehau ret->bnx_rx_ret_ring_map, ret->bnx_rx_ret_ring); 5159beedf5beSSepherosa Ziehau } 51600c7da01dSSepherosa Ziehau 51610c7da01dSSepherosa Ziehau static int 51620c7da01dSSepherosa Ziehau bnx_alloc_intr(struct bnx_softc *sc) 51630c7da01dSSepherosa Ziehau { 5164f33ac8a4SSepherosa Ziehau struct bnx_intr_data *intr; 51650c7da01dSSepherosa Ziehau u_int intr_flags; 5166*695a8586SSepherosa Ziehau int error; 5167*695a8586SSepherosa Ziehau 5168*695a8586SSepherosa Ziehau if (sc->bnx_intr_cnt > 1) { 5169*695a8586SSepherosa Ziehau error = bnx_alloc_msix(sc); 5170*695a8586SSepherosa Ziehau if (error) 5171*695a8586SSepherosa Ziehau return error; 5172*695a8586SSepherosa Ziehau KKASSERT(sc->bnx_intr_type == PCI_INTR_TYPE_MSIX); 5173*695a8586SSepherosa Ziehau return 0; 5174*695a8586SSepherosa Ziehau } 51750c7da01dSSepherosa Ziehau 51760a806e3aSSepherosa Ziehau KKASSERT(sc->bnx_intr_cnt == 1); 51770c7da01dSSepherosa Ziehau 5178f33ac8a4SSepherosa Ziehau intr = &sc->bnx_intr_data[0]; 5179f33ac8a4SSepherosa Ziehau intr->bnx_ret = &sc->bnx_rx_ret_ring[0]; 5180f33ac8a4SSepherosa Ziehau intr->bnx_txr = &sc->bnx_tx_ring[0]; 5181f33ac8a4SSepherosa Ziehau intr->bnx_intr_serialize = &sc->bnx_main_serialize; 5182*695a8586SSepherosa Ziehau intr->bnx_intr_check = bnx_check_intr_rxtx; 51834fa38985SSepherosa Ziehau intr->bnx_saved_status_tag = &intr->bnx_ret->bnx_saved_status_tag; 5184f33ac8a4SSepherosa Ziehau 5185f33ac8a4SSepherosa Ziehau sc->bnx_intr_type = pci_alloc_1intr(sc->bnx_dev, bnx_msi_enable, 5186f33ac8a4SSepherosa Ziehau &intr->bnx_intr_rid, &intr_flags); 5187f33ac8a4SSepherosa Ziehau 5188f33ac8a4SSepherosa Ziehau intr->bnx_intr_res = bus_alloc_resource_any(sc->bnx_dev, SYS_RES_IRQ, 5189f33ac8a4SSepherosa Ziehau &intr->bnx_intr_rid, intr_flags); 5190f33ac8a4SSepherosa Ziehau if (intr->bnx_intr_res == NULL) { 51910c7da01dSSepherosa Ziehau device_printf(sc->bnx_dev, "could not alloc interrupt\n"); 51920c7da01dSSepherosa Ziehau return ENXIO; 51930c7da01dSSepherosa Ziehau } 51940c7da01dSSepherosa Ziehau 5195f33ac8a4SSepherosa Ziehau if (sc->bnx_intr_type == PCI_INTR_TYPE_MSI) { 5196*695a8586SSepherosa Ziehau bnx_enable_msi(sc, FALSE); 519703cc99fdSSepherosa Ziehau intr->bnx_intr_func = bnx_msi; 5198f33ac8a4SSepherosa Ziehau if (bootverbose) 5199f33ac8a4SSepherosa Ziehau device_printf(sc->bnx_dev, "oneshot MSI\n"); 5200f33ac8a4SSepherosa Ziehau } else { 5201f33ac8a4SSepherosa Ziehau intr->bnx_intr_func = bnx_intr_legacy; 5202f33ac8a4SSepherosa Ziehau } 5203f33ac8a4SSepherosa Ziehau intr->bnx_intr_arg = sc; 5204f33ac8a4SSepherosa Ziehau intr->bnx_intr_cpuid = rman_get_cpuid(intr->bnx_intr_res); 5205f33ac8a4SSepherosa Ziehau 5206f33ac8a4SSepherosa Ziehau intr->bnx_txr->bnx_tx_cpuid = intr->bnx_intr_cpuid; 5207f33ac8a4SSepherosa Ziehau 52080c7da01dSSepherosa Ziehau return 0; 52090c7da01dSSepherosa Ziehau } 52100c7da01dSSepherosa Ziehau 52110c7da01dSSepherosa Ziehau static int 52120c7da01dSSepherosa Ziehau bnx_setup_intr(struct bnx_softc *sc) 52130c7da01dSSepherosa Ziehau { 5214f33ac8a4SSepherosa Ziehau int error, i; 52150c7da01dSSepherosa Ziehau 5216f33ac8a4SSepherosa Ziehau for (i = 0; i < sc->bnx_intr_cnt; ++i) { 5217f33ac8a4SSepherosa Ziehau struct bnx_intr_data *intr = &sc->bnx_intr_data[i]; 5218f33ac8a4SSepherosa Ziehau 5219f33ac8a4SSepherosa Ziehau error = bus_setup_intr_descr(sc->bnx_dev, intr->bnx_intr_res, 5220f33ac8a4SSepherosa Ziehau INTR_MPSAFE, intr->bnx_intr_func, intr->bnx_intr_arg, 5221f33ac8a4SSepherosa Ziehau &intr->bnx_intr_hand, intr->bnx_intr_serialize, 5222f33ac8a4SSepherosa Ziehau intr->bnx_intr_desc); 52230c7da01dSSepherosa Ziehau if (error) { 5224f33ac8a4SSepherosa Ziehau device_printf(sc->bnx_dev, 5225f33ac8a4SSepherosa Ziehau "could not set up %dth intr\n", i); 5226f33ac8a4SSepherosa Ziehau bnx_teardown_intr(sc, i); 52270c7da01dSSepherosa Ziehau return error; 52280c7da01dSSepherosa Ziehau } 5229f33ac8a4SSepherosa Ziehau } 52300c7da01dSSepherosa Ziehau return 0; 52310c7da01dSSepherosa Ziehau } 52320c7da01dSSepherosa Ziehau 52330c7da01dSSepherosa Ziehau static void 5234f33ac8a4SSepherosa Ziehau bnx_teardown_intr(struct bnx_softc *sc, int cnt) 5235f33ac8a4SSepherosa Ziehau { 5236f33ac8a4SSepherosa Ziehau int i; 5237f33ac8a4SSepherosa Ziehau 5238f33ac8a4SSepherosa Ziehau for (i = 0; i < cnt; ++i) { 5239f33ac8a4SSepherosa Ziehau struct bnx_intr_data *intr = &sc->bnx_intr_data[i]; 5240f33ac8a4SSepherosa Ziehau 5241f33ac8a4SSepherosa Ziehau bus_teardown_intr(sc->bnx_dev, intr->bnx_intr_res, 5242f33ac8a4SSepherosa Ziehau intr->bnx_intr_hand); 5243f33ac8a4SSepherosa Ziehau } 5244f33ac8a4SSepherosa Ziehau } 5245f33ac8a4SSepherosa Ziehau 5246f33ac8a4SSepherosa Ziehau static void 52470c7da01dSSepherosa Ziehau bnx_free_intr(struct bnx_softc *sc) 52480c7da01dSSepherosa Ziehau { 5249*695a8586SSepherosa Ziehau if (sc->bnx_intr_type != PCI_INTR_TYPE_MSIX) { 5250f33ac8a4SSepherosa Ziehau struct bnx_intr_data *intr; 5251f33ac8a4SSepherosa Ziehau 5252f33ac8a4SSepherosa Ziehau KKASSERT(sc->bnx_intr_cnt <= 1); 5253f33ac8a4SSepherosa Ziehau intr = &sc->bnx_intr_data[0]; 5254f33ac8a4SSepherosa Ziehau 5255f33ac8a4SSepherosa Ziehau if (intr->bnx_intr_res != NULL) { 52560c7da01dSSepherosa Ziehau bus_release_resource(sc->bnx_dev, SYS_RES_IRQ, 5257f33ac8a4SSepherosa Ziehau intr->bnx_intr_rid, intr->bnx_intr_res); 52580c7da01dSSepherosa Ziehau } 5259f33ac8a4SSepherosa Ziehau if (sc->bnx_intr_type == PCI_INTR_TYPE_MSI) 52600c7da01dSSepherosa Ziehau pci_release_msi(sc->bnx_dev); 5261*695a8586SSepherosa Ziehau } else { 5262*695a8586SSepherosa Ziehau bnx_free_msix(sc, TRUE); 5263*695a8586SSepherosa Ziehau } 52640c7da01dSSepherosa Ziehau } 5265329f9016SSepherosa Ziehau 5266329f9016SSepherosa Ziehau static void 5267329f9016SSepherosa Ziehau bnx_setup_serialize(struct bnx_softc *sc) 5268329f9016SSepherosa Ziehau { 5269329f9016SSepherosa Ziehau int i, j; 5270329f9016SSepherosa Ziehau 5271329f9016SSepherosa Ziehau /* 5272329f9016SSepherosa Ziehau * Allocate serializer array 5273329f9016SSepherosa Ziehau */ 5274329f9016SSepherosa Ziehau 5275329f9016SSepherosa Ziehau /* Main + RX STD + TX + RX RET */ 5276329f9016SSepherosa Ziehau sc->bnx_serialize_cnt = 1 + 1 + sc->bnx_tx_ringcnt + sc->bnx_rx_retcnt; 5277329f9016SSepherosa Ziehau 5278329f9016SSepherosa Ziehau sc->bnx_serialize = 5279329f9016SSepherosa Ziehau kmalloc(sc->bnx_serialize_cnt * sizeof(struct lwkt_serialize *), 5280329f9016SSepherosa Ziehau M_DEVBUF, M_WAITOK | M_ZERO); 5281329f9016SSepherosa Ziehau 5282329f9016SSepherosa Ziehau /* 5283329f9016SSepherosa Ziehau * Setup serializers 5284329f9016SSepherosa Ziehau * 5285329f9016SSepherosa Ziehau * NOTE: Order is critical 5286329f9016SSepherosa Ziehau */ 5287329f9016SSepherosa Ziehau 5288329f9016SSepherosa Ziehau i = 0; 5289329f9016SSepherosa Ziehau 5290329f9016SSepherosa Ziehau KKASSERT(i < sc->bnx_serialize_cnt); 5291329f9016SSepherosa Ziehau sc->bnx_serialize[i++] = &sc->bnx_main_serialize; 5292329f9016SSepherosa Ziehau 5293329f9016SSepherosa Ziehau KKASSERT(i < sc->bnx_serialize_cnt); 5294329f9016SSepherosa Ziehau sc->bnx_serialize[i++] = &sc->bnx_rx_std_ring.bnx_rx_std_serialize; 5295329f9016SSepherosa Ziehau 5296329f9016SSepherosa Ziehau for (j = 0; j < sc->bnx_rx_retcnt; ++j) { 5297329f9016SSepherosa Ziehau KKASSERT(i < sc->bnx_serialize_cnt); 5298329f9016SSepherosa Ziehau sc->bnx_serialize[i++] = 5299329f9016SSepherosa Ziehau &sc->bnx_rx_ret_ring[j].bnx_rx_ret_serialize; 5300329f9016SSepherosa Ziehau } 5301329f9016SSepherosa Ziehau 5302329f9016SSepherosa Ziehau for (j = 0; j < sc->bnx_tx_ringcnt; ++j) { 5303329f9016SSepherosa Ziehau KKASSERT(i < sc->bnx_serialize_cnt); 5304329f9016SSepherosa Ziehau sc->bnx_serialize[i++] = 5305329f9016SSepherosa Ziehau &sc->bnx_tx_ring[j].bnx_tx_serialize; 5306329f9016SSepherosa Ziehau } 5307329f9016SSepherosa Ziehau 5308329f9016SSepherosa Ziehau KKASSERT(i == sc->bnx_serialize_cnt); 5309329f9016SSepherosa Ziehau } 5310329f9016SSepherosa Ziehau 5311329f9016SSepherosa Ziehau static void 5312329f9016SSepherosa Ziehau bnx_serialize(struct ifnet *ifp, enum ifnet_serialize slz) 5313329f9016SSepherosa Ziehau { 5314329f9016SSepherosa Ziehau struct bnx_softc *sc = ifp->if_softc; 5315329f9016SSepherosa Ziehau 5316329f9016SSepherosa Ziehau ifnet_serialize_array_enter(sc->bnx_serialize, 5317329f9016SSepherosa Ziehau sc->bnx_serialize_cnt, slz); 5318329f9016SSepherosa Ziehau } 5319329f9016SSepherosa Ziehau 5320329f9016SSepherosa Ziehau static void 5321329f9016SSepherosa Ziehau bnx_deserialize(struct ifnet *ifp, enum ifnet_serialize slz) 5322329f9016SSepherosa Ziehau { 5323329f9016SSepherosa Ziehau struct bnx_softc *sc = ifp->if_softc; 5324329f9016SSepherosa Ziehau 5325329f9016SSepherosa Ziehau ifnet_serialize_array_exit(sc->bnx_serialize, 5326329f9016SSepherosa Ziehau sc->bnx_serialize_cnt, slz); 5327329f9016SSepherosa Ziehau } 5328329f9016SSepherosa Ziehau 5329329f9016SSepherosa Ziehau static int 5330329f9016SSepherosa Ziehau bnx_tryserialize(struct ifnet *ifp, enum ifnet_serialize slz) 5331329f9016SSepherosa Ziehau { 5332329f9016SSepherosa Ziehau struct bnx_softc *sc = ifp->if_softc; 5333329f9016SSepherosa Ziehau 5334329f9016SSepherosa Ziehau return ifnet_serialize_array_try(sc->bnx_serialize, 5335329f9016SSepherosa Ziehau sc->bnx_serialize_cnt, slz); 5336329f9016SSepherosa Ziehau } 5337329f9016SSepherosa Ziehau 5338329f9016SSepherosa Ziehau #ifdef INVARIANTS 5339329f9016SSepherosa Ziehau 5340329f9016SSepherosa Ziehau static void 5341329f9016SSepherosa Ziehau bnx_serialize_assert(struct ifnet *ifp, enum ifnet_serialize slz, 5342329f9016SSepherosa Ziehau boolean_t serialized) 5343329f9016SSepherosa Ziehau { 5344329f9016SSepherosa Ziehau struct bnx_softc *sc = ifp->if_softc; 5345329f9016SSepherosa Ziehau 5346329f9016SSepherosa Ziehau ifnet_serialize_array_assert(sc->bnx_serialize, sc->bnx_serialize_cnt, 5347329f9016SSepherosa Ziehau slz, serialized); 5348329f9016SSepherosa Ziehau } 5349329f9016SSepherosa Ziehau 5350329f9016SSepherosa Ziehau #endif /* INVARIANTS */ 53514fa38985SSepherosa Ziehau 53524fa38985SSepherosa Ziehau #ifdef IFPOLL_ENABLE 53534fa38985SSepherosa Ziehau 53544fa38985SSepherosa Ziehau static int 53554fa38985SSepherosa Ziehau bnx_sysctl_npoll_offset(SYSCTL_HANDLER_ARGS) 53564fa38985SSepherosa Ziehau { 53574fa38985SSepherosa Ziehau struct bnx_softc *sc = (void *)arg1; 53584fa38985SSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if; 53594fa38985SSepherosa Ziehau int error, off; 53604fa38985SSepherosa Ziehau 53614fa38985SSepherosa Ziehau off = sc->bnx_npoll_rxoff; 53624fa38985SSepherosa Ziehau error = sysctl_handle_int(oidp, &off, 0, req); 53634fa38985SSepherosa Ziehau if (error || req->newptr == NULL) 53644fa38985SSepherosa Ziehau return error; 53654fa38985SSepherosa Ziehau if (off < 0) 53664fa38985SSepherosa Ziehau return EINVAL; 53674fa38985SSepherosa Ziehau 53684fa38985SSepherosa Ziehau ifnet_serialize_all(ifp); 53694fa38985SSepherosa Ziehau if (off >= ncpus2 || off % sc->bnx_rx_retcnt != 0) { 53704fa38985SSepherosa Ziehau error = EINVAL; 53714fa38985SSepherosa Ziehau } else { 53724fa38985SSepherosa Ziehau error = 0; 53734fa38985SSepherosa Ziehau sc->bnx_npoll_txoff = off; 53744fa38985SSepherosa Ziehau sc->bnx_npoll_rxoff = off; 53754fa38985SSepherosa Ziehau } 53764fa38985SSepherosa Ziehau ifnet_deserialize_all(ifp); 53774fa38985SSepherosa Ziehau 53784fa38985SSepherosa Ziehau return error; 53794fa38985SSepherosa Ziehau } 53804fa38985SSepherosa Ziehau 53814fa38985SSepherosa Ziehau static int 53824fa38985SSepherosa Ziehau bnx_sysctl_npoll_rxoff(SYSCTL_HANDLER_ARGS) 53834fa38985SSepherosa Ziehau { 53844fa38985SSepherosa Ziehau struct bnx_softc *sc = (void *)arg1; 53854fa38985SSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if; 53864fa38985SSepherosa Ziehau int error, off; 53874fa38985SSepherosa Ziehau 53884fa38985SSepherosa Ziehau off = sc->bnx_npoll_rxoff; 53894fa38985SSepherosa Ziehau error = sysctl_handle_int(oidp, &off, 0, req); 53904fa38985SSepherosa Ziehau if (error || req->newptr == NULL) 53914fa38985SSepherosa Ziehau return error; 53924fa38985SSepherosa Ziehau if (off < 0) 53934fa38985SSepherosa Ziehau return EINVAL; 53944fa38985SSepherosa Ziehau 53954fa38985SSepherosa Ziehau ifnet_serialize_all(ifp); 53964fa38985SSepherosa Ziehau if (off >= ncpus2 || off % sc->bnx_rx_retcnt != 0) { 53974fa38985SSepherosa Ziehau error = EINVAL; 53984fa38985SSepherosa Ziehau } else { 53994fa38985SSepherosa Ziehau error = 0; 54004fa38985SSepherosa Ziehau sc->bnx_npoll_rxoff = off; 54014fa38985SSepherosa Ziehau } 54024fa38985SSepherosa Ziehau ifnet_deserialize_all(ifp); 54034fa38985SSepherosa Ziehau 54044fa38985SSepherosa Ziehau return error; 54054fa38985SSepherosa Ziehau } 54064fa38985SSepherosa Ziehau 54074fa38985SSepherosa Ziehau static int 54084fa38985SSepherosa Ziehau bnx_sysctl_npoll_txoff(SYSCTL_HANDLER_ARGS) 54094fa38985SSepherosa Ziehau { 54104fa38985SSepherosa Ziehau struct bnx_softc *sc = (void *)arg1; 54114fa38985SSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if; 54124fa38985SSepherosa Ziehau int error, off; 54134fa38985SSepherosa Ziehau 54144fa38985SSepherosa Ziehau off = sc->bnx_npoll_txoff; 54154fa38985SSepherosa Ziehau error = sysctl_handle_int(oidp, &off, 0, req); 54164fa38985SSepherosa Ziehau if (error || req->newptr == NULL) 54174fa38985SSepherosa Ziehau return error; 54184fa38985SSepherosa Ziehau if (off < 0) 54194fa38985SSepherosa Ziehau return EINVAL; 54204fa38985SSepherosa Ziehau 54214fa38985SSepherosa Ziehau ifnet_serialize_all(ifp); 54224fa38985SSepherosa Ziehau if (off >= ncpus2) { 54234fa38985SSepherosa Ziehau error = EINVAL; 54244fa38985SSepherosa Ziehau } else { 54254fa38985SSepherosa Ziehau error = 0; 54264fa38985SSepherosa Ziehau sc->bnx_npoll_txoff = off; 54274fa38985SSepherosa Ziehau } 54284fa38985SSepherosa Ziehau ifnet_deserialize_all(ifp); 54294fa38985SSepherosa Ziehau 54304fa38985SSepherosa Ziehau return error; 54314fa38985SSepherosa Ziehau } 54324fa38985SSepherosa Ziehau 54334fa38985SSepherosa Ziehau #endif /* IFPOLL_ENABLE */ 54347dbaa833SSepherosa Ziehau 54357dbaa833SSepherosa Ziehau static void 54367dbaa833SSepherosa Ziehau bnx_set_tick_cpuid(struct bnx_softc *sc, boolean_t polling) 54377dbaa833SSepherosa Ziehau { 54387dbaa833SSepherosa Ziehau if (polling) 54397dbaa833SSepherosa Ziehau sc->bnx_tick_cpuid = 0; /* XXX */ 54407dbaa833SSepherosa Ziehau else 54417dbaa833SSepherosa Ziehau sc->bnx_tick_cpuid = sc->bnx_intr_data[0].bnx_intr_cpuid; 54427dbaa833SSepherosa Ziehau } 5443841cdf08SSepherosa Ziehau 5444841cdf08SSepherosa Ziehau static void 5445841cdf08SSepherosa Ziehau bnx_rx_std_refill_ithread(void *xstd) 5446841cdf08SSepherosa Ziehau { 5447841cdf08SSepherosa Ziehau struct bnx_rx_std_ring *std = xstd; 5448841cdf08SSepherosa Ziehau struct globaldata *gd = mycpu; 5449841cdf08SSepherosa Ziehau 5450841cdf08SSepherosa Ziehau crit_enter_gd(gd); 5451841cdf08SSepherosa Ziehau 5452841cdf08SSepherosa Ziehau while (!std->bnx_rx_std_stop) { 5453841cdf08SSepherosa Ziehau if (std->bnx_rx_std_refill) { 5454841cdf08SSepherosa Ziehau lwkt_serialize_handler_call( 5455841cdf08SSepherosa Ziehau &std->bnx_rx_std_serialize, 5456841cdf08SSepherosa Ziehau bnx_rx_std_refill, std, NULL); 5457841cdf08SSepherosa Ziehau } 5458841cdf08SSepherosa Ziehau 5459841cdf08SSepherosa Ziehau crit_exit_gd(gd); 5460841cdf08SSepherosa Ziehau crit_enter_gd(gd); 5461841cdf08SSepherosa Ziehau 5462*695a8586SSepherosa Ziehau atomic_poll_release_int(&std->bnx_rx_std_running); 5463*695a8586SSepherosa Ziehau cpu_mfence(); 5464*695a8586SSepherosa Ziehau 5465841cdf08SSepherosa Ziehau if (!std->bnx_rx_std_refill && !std->bnx_rx_std_stop) { 5466841cdf08SSepherosa Ziehau lwkt_deschedule_self(gd->gd_curthread); 5467841cdf08SSepherosa Ziehau lwkt_switch(); 5468841cdf08SSepherosa Ziehau } 5469841cdf08SSepherosa Ziehau } 5470841cdf08SSepherosa Ziehau 5471841cdf08SSepherosa Ziehau crit_exit_gd(gd); 5472841cdf08SSepherosa Ziehau 5473841cdf08SSepherosa Ziehau wakeup(std); 5474841cdf08SSepherosa Ziehau 5475841cdf08SSepherosa Ziehau lwkt_exit(); 5476841cdf08SSepherosa Ziehau } 5477841cdf08SSepherosa Ziehau 5478841cdf08SSepherosa Ziehau static void 5479841cdf08SSepherosa Ziehau bnx_rx_std_refill(void *xstd, void *frame __unused) 5480841cdf08SSepherosa Ziehau { 5481841cdf08SSepherosa Ziehau struct bnx_rx_std_ring *std = xstd; 5482*695a8586SSepherosa Ziehau int cnt, refill_mask; 5483841cdf08SSepherosa Ziehau 5484841cdf08SSepherosa Ziehau again: 5485841cdf08SSepherosa Ziehau cnt = 0; 5486841cdf08SSepherosa Ziehau 5487841cdf08SSepherosa Ziehau cpu_lfence(); 5488*695a8586SSepherosa Ziehau refill_mask = std->bnx_rx_std_refill; 5489*695a8586SSepherosa Ziehau atomic_clear_int(&std->bnx_rx_std_refill, refill_mask); 5490841cdf08SSepherosa Ziehau 5491*695a8586SSepherosa Ziehau while (refill_mask) { 5492*695a8586SSepherosa Ziehau uint16_t check_idx = std->bnx_rx_std; 5493*695a8586SSepherosa Ziehau int ret_idx; 5494*695a8586SSepherosa Ziehau 5495*695a8586SSepherosa Ziehau ret_idx = bsfl(refill_mask); 5496841cdf08SSepherosa Ziehau for (;;) { 5497841cdf08SSepherosa Ziehau struct bnx_rx_buf *rb; 5498*695a8586SSepherosa Ziehau int refilled; 5499841cdf08SSepherosa Ziehau 5500841cdf08SSepherosa Ziehau BNX_INC(check_idx, BGE_STD_RX_RING_CNT); 5501841cdf08SSepherosa Ziehau rb = &std->bnx_rx_std_buf[check_idx]; 5502*695a8586SSepherosa Ziehau refilled = rb->bnx_rx_refilled; 5503841cdf08SSepherosa Ziehau cpu_lfence(); 5504*695a8586SSepherosa Ziehau if (refilled) { 5505841cdf08SSepherosa Ziehau bnx_setup_rxdesc_std(std, check_idx); 5506841cdf08SSepherosa Ziehau std->bnx_rx_std = check_idx; 5507841cdf08SSepherosa Ziehau ++cnt; 5508*695a8586SSepherosa Ziehau if (cnt >= 8) { 5509*695a8586SSepherosa Ziehau bnx_writembx(std->bnx_sc, 5510*695a8586SSepherosa Ziehau BGE_MBX_RX_STD_PROD_LO, 5511*695a8586SSepherosa Ziehau std->bnx_rx_std); 5512*695a8586SSepherosa Ziehau cnt = 0; 5513*695a8586SSepherosa Ziehau } 5514841cdf08SSepherosa Ziehau } else { 5515841cdf08SSepherosa Ziehau break; 5516841cdf08SSepherosa Ziehau } 5517841cdf08SSepherosa Ziehau } 5518*695a8586SSepherosa Ziehau refill_mask &= ~(1 << ret_idx); 5519*695a8586SSepherosa Ziehau } 5520841cdf08SSepherosa Ziehau 5521841cdf08SSepherosa Ziehau if (cnt) { 5522841cdf08SSepherosa Ziehau bnx_writembx(std->bnx_sc, BGE_MBX_RX_STD_PROD_LO, 5523841cdf08SSepherosa Ziehau std->bnx_rx_std); 5524841cdf08SSepherosa Ziehau } 5525841cdf08SSepherosa Ziehau 5526841cdf08SSepherosa Ziehau if (std->bnx_rx_std_refill) 5527841cdf08SSepherosa Ziehau goto again; 5528841cdf08SSepherosa Ziehau 5529841cdf08SSepherosa Ziehau atomic_poll_release_int(&std->bnx_rx_std_running); 5530841cdf08SSepherosa Ziehau cpu_mfence(); 5531841cdf08SSepherosa Ziehau 5532841cdf08SSepherosa Ziehau if (std->bnx_rx_std_refill) 5533841cdf08SSepherosa Ziehau goto again; 5534841cdf08SSepherosa Ziehau } 5535841cdf08SSepherosa Ziehau 5536841cdf08SSepherosa Ziehau static int 5537841cdf08SSepherosa Ziehau bnx_sysctl_std_refill(SYSCTL_HANDLER_ARGS) 5538841cdf08SSepherosa Ziehau { 5539841cdf08SSepherosa Ziehau struct bnx_softc *sc = (void *)arg1; 5540841cdf08SSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if; 5541841cdf08SSepherosa Ziehau struct bnx_rx_ret_ring *ret = &sc->bnx_rx_ret_ring[0]; 5542841cdf08SSepherosa Ziehau int error, cntmax, i; 5543841cdf08SSepherosa Ziehau 5544841cdf08SSepherosa Ziehau cntmax = ret->bnx_rx_cntmax; 5545841cdf08SSepherosa Ziehau error = sysctl_handle_int(oidp, &cntmax, 0, req); 5546841cdf08SSepherosa Ziehau if (error || req->newptr == NULL) 5547841cdf08SSepherosa Ziehau return error; 5548841cdf08SSepherosa Ziehau 5549841cdf08SSepherosa Ziehau ifnet_serialize_all(ifp); 5550841cdf08SSepherosa Ziehau 5551841cdf08SSepherosa Ziehau if ((cntmax * sc->bnx_rx_retcnt) > BGE_STD_RX_RING_CNT / 2) { 5552841cdf08SSepherosa Ziehau error = EINVAL; 5553841cdf08SSepherosa Ziehau goto back; 5554841cdf08SSepherosa Ziehau } 5555841cdf08SSepherosa Ziehau 5556841cdf08SSepherosa Ziehau for (i = 0; i < sc->bnx_tx_ringcnt; ++i) 5557841cdf08SSepherosa Ziehau sc->bnx_rx_ret_ring[i].bnx_rx_cntmax = cntmax; 5558841cdf08SSepherosa Ziehau error = 0; 5559841cdf08SSepherosa Ziehau 5560841cdf08SSepherosa Ziehau back: 5561841cdf08SSepherosa Ziehau ifnet_deserialize_all(ifp); 5562841cdf08SSepherosa Ziehau 5563841cdf08SSepherosa Ziehau return error; 5564841cdf08SSepherosa Ziehau } 5565*695a8586SSepherosa Ziehau 5566*695a8586SSepherosa Ziehau static void 5567*695a8586SSepherosa Ziehau bnx_init_rss(struct bnx_softc *sc) 5568*695a8586SSepherosa Ziehau { 5569*695a8586SSepherosa Ziehau uint8_t key[BGE_RSS_KEYREG_CNT * BGE_RSS_KEYREG_SIZE]; 5570*695a8586SSepherosa Ziehau int i, j, r; 5571*695a8586SSepherosa Ziehau 5572*695a8586SSepherosa Ziehau KKASSERT(BNX_RSS_ENABLED(sc)); 5573*695a8586SSepherosa Ziehau 5574*695a8586SSepherosa Ziehau r = 0; 5575*695a8586SSepherosa Ziehau for (j = 0; j < BGE_RSS_INDIR_TBL_CNT; ++j) { 5576*695a8586SSepherosa Ziehau uint32_t tbl = 0; 5577*695a8586SSepherosa Ziehau 5578*695a8586SSepherosa Ziehau for (i = 0; i < BGE_RSS_INDIR_TBLENT_CNT; ++i) { 5579*695a8586SSepherosa Ziehau uint32_t q; 5580*695a8586SSepherosa Ziehau 5581*695a8586SSepherosa Ziehau q = r % sc->bnx_rx_retcnt; 5582*695a8586SSepherosa Ziehau tbl |= q << (BGE_RSS_INDIR_TBLENT_SHIFT * 5583*695a8586SSepherosa Ziehau (BGE_RSS_INDIR_TBLENT_CNT - i - 1)); 5584*695a8586SSepherosa Ziehau ++r; 5585*695a8586SSepherosa Ziehau } 5586*695a8586SSepherosa Ziehau 5587*695a8586SSepherosa Ziehau BNX_RSS_DPRINTF(sc, 1, "tbl%d %08x\n", j, tbl); 5588*695a8586SSepherosa Ziehau CSR_WRITE_4(sc, BGE_RSS_INDIR_TBL(j), tbl); 5589*695a8586SSepherosa Ziehau } 5590*695a8586SSepherosa Ziehau 5591*695a8586SSepherosa Ziehau toeplitz_get_key(key, sizeof(key)); 5592*695a8586SSepherosa Ziehau for (i = 0; i < BGE_RSS_KEYREG_CNT; ++i) { 5593*695a8586SSepherosa Ziehau uint32_t keyreg; 5594*695a8586SSepherosa Ziehau 5595*695a8586SSepherosa Ziehau keyreg = BGE_RSS_KEYREG_VAL(key, i); 5596*695a8586SSepherosa Ziehau 5597*695a8586SSepherosa Ziehau BNX_RSS_DPRINTF(sc, 1, "key%d %08x\n", i, keyreg); 5598*695a8586SSepherosa Ziehau CSR_WRITE_4(sc, BGE_RSS_KEYREG(i), keyreg); 5599*695a8586SSepherosa Ziehau } 5600*695a8586SSepherosa Ziehau } 5601*695a8586SSepherosa Ziehau 5602*695a8586SSepherosa Ziehau static void 5603*695a8586SSepherosa Ziehau bnx_setup_ring_cnt(struct bnx_softc *sc) 5604*695a8586SSepherosa Ziehau { 5605*695a8586SSepherosa Ziehau int msix_enable, i, msix_cnt, msix_cnt2, ring_max; 5606*695a8586SSepherosa Ziehau 5607*695a8586SSepherosa Ziehau sc->bnx_tx_ringcnt = 1; 5608*695a8586SSepherosa Ziehau sc->bnx_rx_retcnt = 1; 5609*695a8586SSepherosa Ziehau sc->bnx_intr_cnt = 1; 5610*695a8586SSepherosa Ziehau 5611*695a8586SSepherosa Ziehau msix_enable = device_getenv_int(sc->bnx_dev, "msix.enable", 5612*695a8586SSepherosa Ziehau bnx_msix_enable); 5613*695a8586SSepherosa Ziehau if (!msix_enable) 5614*695a8586SSepherosa Ziehau return; 5615*695a8586SSepherosa Ziehau 5616*695a8586SSepherosa Ziehau if (ncpus2 == 1) 5617*695a8586SSepherosa Ziehau return; 5618*695a8586SSepherosa Ziehau 5619*695a8586SSepherosa Ziehau msix_cnt = pci_msix_count(sc->bnx_dev); 5620*695a8586SSepherosa Ziehau if (msix_cnt <= 1) 5621*695a8586SSepherosa Ziehau return; 5622*695a8586SSepherosa Ziehau 5623*695a8586SSepherosa Ziehau i = 0; 5624*695a8586SSepherosa Ziehau while ((1 << (i + 1)) <= msix_cnt) 5625*695a8586SSepherosa Ziehau ++i; 5626*695a8586SSepherosa Ziehau msix_cnt2 = 1 << i; 5627*695a8586SSepherosa Ziehau 5628*695a8586SSepherosa Ziehau /* 5629*695a8586SSepherosa Ziehau * One MSI-X vector is dedicated to status or single TX queue, 5630*695a8586SSepherosa Ziehau * so make sure that there are enough MSI-X vectors. 5631*695a8586SSepherosa Ziehau */ 5632*695a8586SSepherosa Ziehau if (msix_cnt == msix_cnt2) { 5633*695a8586SSepherosa Ziehau /* 5634*695a8586SSepherosa Ziehau * XXX 5635*695a8586SSepherosa Ziehau * This probably will not happen; 57785/5718 families 5636*695a8586SSepherosa Ziehau * come with at least 5 MSI-X vectors. 5637*695a8586SSepherosa Ziehau */ 5638*695a8586SSepherosa Ziehau msix_cnt2 >>= 1; 5639*695a8586SSepherosa Ziehau if (msix_cnt2 <= 1) { 5640*695a8586SSepherosa Ziehau device_printf(sc->bnx_dev, 5641*695a8586SSepherosa Ziehau "MSI-X count %d could not be used\n", msix_cnt); 5642*695a8586SSepherosa Ziehau return; 5643*695a8586SSepherosa Ziehau } 5644*695a8586SSepherosa Ziehau device_printf(sc->bnx_dev, "MSI-X count %d is power of 2\n", 5645*695a8586SSepherosa Ziehau msix_cnt); 5646*695a8586SSepherosa Ziehau } 5647*695a8586SSepherosa Ziehau 5648*695a8586SSepherosa Ziehau /* 5649*695a8586SSepherosa Ziehau * Setup RX ring count 5650*695a8586SSepherosa Ziehau */ 5651*695a8586SSepherosa Ziehau ring_max = BNX_RX_RING_MAX; 5652*695a8586SSepherosa Ziehau if (ring_max > msix_cnt2) 5653*695a8586SSepherosa Ziehau ring_max = msix_cnt2; 5654*695a8586SSepherosa Ziehau sc->bnx_rx_retcnt = device_getenv_int(sc->bnx_dev, "rx_rings", 5655*695a8586SSepherosa Ziehau bnx_rx_rings); 5656*695a8586SSepherosa Ziehau sc->bnx_rx_retcnt = if_ring_count2(sc->bnx_rx_retcnt, ring_max); 5657*695a8586SSepherosa Ziehau 5658*695a8586SSepherosa Ziehau if (sc->bnx_rx_retcnt == 1) 5659*695a8586SSepherosa Ziehau return; 5660*695a8586SSepherosa Ziehau 5661*695a8586SSepherosa Ziehau /* 5662*695a8586SSepherosa Ziehau * We need one extra MSI-X vector for link status or 5663*695a8586SSepherosa Ziehau * TX ring (if only one TX ring is enabled). 5664*695a8586SSepherosa Ziehau */ 5665*695a8586SSepherosa Ziehau sc->bnx_intr_cnt = sc->bnx_rx_retcnt + 1; 5666*695a8586SSepherosa Ziehau 5667*695a8586SSepherosa Ziehau /* 5668*695a8586SSepherosa Ziehau * Setup TX ring count 5669*695a8586SSepherosa Ziehau * 5670*695a8586SSepherosa Ziehau * Currently only BCM5719 and BCM5720 support multiple TX rings 5671*695a8586SSepherosa Ziehau * and the TX ring count must be less than the RX ring count. 5672*695a8586SSepherosa Ziehau */ 5673*695a8586SSepherosa Ziehau if (sc->bnx_asicrev == BGE_ASICREV_BCM5719 || 5674*695a8586SSepherosa Ziehau sc->bnx_asicrev == BGE_ASICREV_BCM5720) { 5675*695a8586SSepherosa Ziehau ring_max = BNX_TX_RING_MAX; 5676*695a8586SSepherosa Ziehau if (ring_max > msix_cnt2) 5677*695a8586SSepherosa Ziehau ring_max = msix_cnt2; 5678*695a8586SSepherosa Ziehau if (ring_max > sc->bnx_rx_retcnt) 5679*695a8586SSepherosa Ziehau ring_max = sc->bnx_rx_retcnt; 5680*695a8586SSepherosa Ziehau sc->bnx_tx_ringcnt = device_getenv_int(sc->bnx_dev, "tx_rings", 5681*695a8586SSepherosa Ziehau bnx_tx_rings); 5682*695a8586SSepherosa Ziehau sc->bnx_tx_ringcnt = if_ring_count2(sc->bnx_tx_ringcnt, 5683*695a8586SSepherosa Ziehau ring_max); 5684*695a8586SSepherosa Ziehau } 5685*695a8586SSepherosa Ziehau } 5686*695a8586SSepherosa Ziehau 5687*695a8586SSepherosa Ziehau static int 5688*695a8586SSepherosa Ziehau bnx_alloc_msix(struct bnx_softc *sc) 5689*695a8586SSepherosa Ziehau { 5690*695a8586SSepherosa Ziehau struct bnx_intr_data *intr; 5691*695a8586SSepherosa Ziehau boolean_t setup = FALSE; 5692*695a8586SSepherosa Ziehau int error, i, offset, offset_def; 5693*695a8586SSepherosa Ziehau 5694*695a8586SSepherosa Ziehau KKASSERT(sc->bnx_intr_cnt > 1); 5695*695a8586SSepherosa Ziehau KKASSERT(sc->bnx_intr_cnt == sc->bnx_rx_retcnt + 1); 5696*695a8586SSepherosa Ziehau 5697*695a8586SSepherosa Ziehau if (sc->bnx_flags & BNX_FLAG_RXTX_BUNDLE) { 5698*695a8586SSepherosa Ziehau /* 5699*695a8586SSepherosa Ziehau * Link status 5700*695a8586SSepherosa Ziehau */ 5701*695a8586SSepherosa Ziehau intr = &sc->bnx_intr_data[0]; 5702*695a8586SSepherosa Ziehau 5703*695a8586SSepherosa Ziehau intr->bnx_intr_serialize = &sc->bnx_main_serialize; 5704*695a8586SSepherosa Ziehau intr->bnx_saved_status_tag = &sc->bnx_saved_status_tag; 5705*695a8586SSepherosa Ziehau 5706*695a8586SSepherosa Ziehau intr->bnx_intr_func = bnx_msix_status; 5707*695a8586SSepherosa Ziehau intr->bnx_intr_arg = sc; 5708*695a8586SSepherosa Ziehau intr->bnx_intr_cpuid = 0; /* XXX */ 5709*695a8586SSepherosa Ziehau 5710*695a8586SSepherosa Ziehau ksnprintf(intr->bnx_intr_desc0, sizeof(intr->bnx_intr_desc0), 5711*695a8586SSepherosa Ziehau "%s sts", device_get_nameunit(sc->bnx_dev)); 5712*695a8586SSepherosa Ziehau intr->bnx_intr_desc = intr->bnx_intr_desc0; 5713*695a8586SSepherosa Ziehau 5714*695a8586SSepherosa Ziehau /* 5715*695a8586SSepherosa Ziehau * RX/TX rings 5716*695a8586SSepherosa Ziehau */ 5717*695a8586SSepherosa Ziehau if (sc->bnx_rx_retcnt == ncpus2) { 5718*695a8586SSepherosa Ziehau offset = 0; 5719*695a8586SSepherosa Ziehau } else { 5720*695a8586SSepherosa Ziehau offset_def = (sc->bnx_rx_retcnt * 5721*695a8586SSepherosa Ziehau device_get_unit(sc->bnx_dev)) % ncpus2; 5722*695a8586SSepherosa Ziehau 5723*695a8586SSepherosa Ziehau offset = device_getenv_int(sc->bnx_dev, 5724*695a8586SSepherosa Ziehau "msix.offset", offset_def); 5725*695a8586SSepherosa Ziehau if (offset >= ncpus2 || 5726*695a8586SSepherosa Ziehau offset % sc->bnx_rx_retcnt != 0) { 5727*695a8586SSepherosa Ziehau device_printf(sc->bnx_dev, 5728*695a8586SSepherosa Ziehau "invalid msix.offset %d, use %d\n", 5729*695a8586SSepherosa Ziehau offset, offset_def); 5730*695a8586SSepherosa Ziehau offset = offset_def; 5731*695a8586SSepherosa Ziehau } 5732*695a8586SSepherosa Ziehau } 5733*695a8586SSepherosa Ziehau 5734*695a8586SSepherosa Ziehau for (i = 1; i < sc->bnx_intr_cnt; ++i) { 5735*695a8586SSepherosa Ziehau int idx = i - 1; 5736*695a8586SSepherosa Ziehau 5737*695a8586SSepherosa Ziehau intr = &sc->bnx_intr_data[i]; 5738*695a8586SSepherosa Ziehau 5739*695a8586SSepherosa Ziehau KKASSERT(idx < sc->bnx_rx_retcnt); 5740*695a8586SSepherosa Ziehau intr->bnx_ret = &sc->bnx_rx_ret_ring[idx]; 5741*695a8586SSepherosa Ziehau if (idx < sc->bnx_tx_ringcnt) { 5742*695a8586SSepherosa Ziehau intr->bnx_txr = &sc->bnx_tx_ring[idx]; 5743*695a8586SSepherosa Ziehau intr->bnx_ret->bnx_txr = intr->bnx_txr; 5744*695a8586SSepherosa Ziehau } 5745*695a8586SSepherosa Ziehau 5746*695a8586SSepherosa Ziehau intr->bnx_intr_serialize = 5747*695a8586SSepherosa Ziehau &intr->bnx_ret->bnx_rx_ret_serialize; 5748*695a8586SSepherosa Ziehau intr->bnx_saved_status_tag = 5749*695a8586SSepherosa Ziehau &intr->bnx_ret->bnx_saved_status_tag; 5750*695a8586SSepherosa Ziehau 5751*695a8586SSepherosa Ziehau intr->bnx_intr_arg = intr->bnx_ret; 5752*695a8586SSepherosa Ziehau KKASSERT(idx + offset < ncpus2); 5753*695a8586SSepherosa Ziehau intr->bnx_intr_cpuid = idx + offset; 5754*695a8586SSepherosa Ziehau 5755*695a8586SSepherosa Ziehau if (intr->bnx_txr == NULL) { 5756*695a8586SSepherosa Ziehau intr->bnx_intr_check = bnx_check_intr_rx; 5757*695a8586SSepherosa Ziehau intr->bnx_intr_func = bnx_msix_rx; 5758*695a8586SSepherosa Ziehau ksnprintf(intr->bnx_intr_desc0, 5759*695a8586SSepherosa Ziehau sizeof(intr->bnx_intr_desc0), "%s rx%d", 5760*695a8586SSepherosa Ziehau device_get_nameunit(sc->bnx_dev), idx); 5761*695a8586SSepherosa Ziehau } else { 5762*695a8586SSepherosa Ziehau intr->bnx_intr_check = bnx_check_intr_rxtx; 5763*695a8586SSepherosa Ziehau intr->bnx_intr_func = bnx_msix_rxtx; 5764*695a8586SSepherosa Ziehau ksnprintf(intr->bnx_intr_desc0, 5765*695a8586SSepherosa Ziehau sizeof(intr->bnx_intr_desc0), "%s rxtx%d", 5766*695a8586SSepherosa Ziehau device_get_nameunit(sc->bnx_dev), idx); 5767*695a8586SSepherosa Ziehau 5768*695a8586SSepherosa Ziehau intr->bnx_txr->bnx_tx_cpuid = 5769*695a8586SSepherosa Ziehau intr->bnx_intr_cpuid; 5770*695a8586SSepherosa Ziehau } 5771*695a8586SSepherosa Ziehau intr->bnx_intr_desc = intr->bnx_intr_desc0; 5772*695a8586SSepherosa Ziehau 5773*695a8586SSepherosa Ziehau intr->bnx_ret->bnx_msix_mbx = intr->bnx_intr_mbx; 5774*695a8586SSepherosa Ziehau } 5775*695a8586SSepherosa Ziehau } else { 5776*695a8586SSepherosa Ziehau /* 5777*695a8586SSepherosa Ziehau * TX ring and link status 5778*695a8586SSepherosa Ziehau */ 5779*695a8586SSepherosa Ziehau offset_def = device_get_unit(sc->bnx_dev) % ncpus2; 5780*695a8586SSepherosa Ziehau offset = device_getenv_int(sc->bnx_dev, "msix.txoff", 5781*695a8586SSepherosa Ziehau offset_def); 5782*695a8586SSepherosa Ziehau if (offset >= ncpus2) { 5783*695a8586SSepherosa Ziehau device_printf(sc->bnx_dev, 5784*695a8586SSepherosa Ziehau "invalid msix.txoff %d, use %d\n", 5785*695a8586SSepherosa Ziehau offset, offset_def); 5786*695a8586SSepherosa Ziehau offset = offset_def; 5787*695a8586SSepherosa Ziehau } 5788*695a8586SSepherosa Ziehau 5789*695a8586SSepherosa Ziehau intr = &sc->bnx_intr_data[0]; 5790*695a8586SSepherosa Ziehau 5791*695a8586SSepherosa Ziehau intr->bnx_txr = &sc->bnx_tx_ring[0]; 5792*695a8586SSepherosa Ziehau intr->bnx_intr_serialize = &sc->bnx_main_serialize; 5793*695a8586SSepherosa Ziehau intr->bnx_intr_check = bnx_check_intr_tx; 5794*695a8586SSepherosa Ziehau intr->bnx_saved_status_tag = 5795*695a8586SSepherosa Ziehau &intr->bnx_txr->bnx_saved_status_tag; 5796*695a8586SSepherosa Ziehau 5797*695a8586SSepherosa Ziehau intr->bnx_intr_func = bnx_msix_tx_status; 5798*695a8586SSepherosa Ziehau intr->bnx_intr_arg = intr->bnx_txr; 5799*695a8586SSepherosa Ziehau intr->bnx_intr_cpuid = offset; 5800*695a8586SSepherosa Ziehau 5801*695a8586SSepherosa Ziehau ksnprintf(intr->bnx_intr_desc0, sizeof(intr->bnx_intr_desc0), 5802*695a8586SSepherosa Ziehau "%s ststx", device_get_nameunit(sc->bnx_dev)); 5803*695a8586SSepherosa Ziehau intr->bnx_intr_desc = intr->bnx_intr_desc0; 5804*695a8586SSepherosa Ziehau 5805*695a8586SSepherosa Ziehau intr->bnx_txr->bnx_tx_cpuid = intr->bnx_intr_cpuid; 5806*695a8586SSepherosa Ziehau 5807*695a8586SSepherosa Ziehau /* 5808*695a8586SSepherosa Ziehau * RX rings 5809*695a8586SSepherosa Ziehau */ 5810*695a8586SSepherosa Ziehau if (sc->bnx_rx_retcnt == ncpus2) { 5811*695a8586SSepherosa Ziehau offset = 0; 5812*695a8586SSepherosa Ziehau } else { 5813*695a8586SSepherosa Ziehau offset_def = (sc->bnx_rx_retcnt * 5814*695a8586SSepherosa Ziehau device_get_unit(sc->bnx_dev)) % ncpus2; 5815*695a8586SSepherosa Ziehau 5816*695a8586SSepherosa Ziehau offset = device_getenv_int(sc->bnx_dev, 5817*695a8586SSepherosa Ziehau "msix.rxoff", offset_def); 5818*695a8586SSepherosa Ziehau if (offset >= ncpus2 || 5819*695a8586SSepherosa Ziehau offset % sc->bnx_rx_retcnt != 0) { 5820*695a8586SSepherosa Ziehau device_printf(sc->bnx_dev, 5821*695a8586SSepherosa Ziehau "invalid msix.rxoff %d, use %d\n", 5822*695a8586SSepherosa Ziehau offset, offset_def); 5823*695a8586SSepherosa Ziehau offset = offset_def; 5824*695a8586SSepherosa Ziehau } 5825*695a8586SSepherosa Ziehau } 5826*695a8586SSepherosa Ziehau 5827*695a8586SSepherosa Ziehau for (i = 1; i < sc->bnx_intr_cnt; ++i) { 5828*695a8586SSepherosa Ziehau int idx = i - 1; 5829*695a8586SSepherosa Ziehau 5830*695a8586SSepherosa Ziehau intr = &sc->bnx_intr_data[i]; 5831*695a8586SSepherosa Ziehau 5832*695a8586SSepherosa Ziehau KKASSERT(idx < sc->bnx_rx_retcnt); 5833*695a8586SSepherosa Ziehau intr->bnx_ret = &sc->bnx_rx_ret_ring[idx]; 5834*695a8586SSepherosa Ziehau intr->bnx_intr_serialize = 5835*695a8586SSepherosa Ziehau &intr->bnx_ret->bnx_rx_ret_serialize; 5836*695a8586SSepherosa Ziehau intr->bnx_intr_check = bnx_check_intr_rx; 5837*695a8586SSepherosa Ziehau intr->bnx_saved_status_tag = 5838*695a8586SSepherosa Ziehau &intr->bnx_ret->bnx_saved_status_tag; 5839*695a8586SSepherosa Ziehau 5840*695a8586SSepherosa Ziehau intr->bnx_intr_func = bnx_msix_rx; 5841*695a8586SSepherosa Ziehau intr->bnx_intr_arg = intr->bnx_ret; 5842*695a8586SSepherosa Ziehau KKASSERT(idx + offset < ncpus2); 5843*695a8586SSepherosa Ziehau intr->bnx_intr_cpuid = idx + offset; 5844*695a8586SSepherosa Ziehau 5845*695a8586SSepherosa Ziehau ksnprintf(intr->bnx_intr_desc0, 5846*695a8586SSepherosa Ziehau sizeof(intr->bnx_intr_desc0), "%s rx%d", 5847*695a8586SSepherosa Ziehau device_get_nameunit(sc->bnx_dev), idx); 5848*695a8586SSepherosa Ziehau intr->bnx_intr_desc = intr->bnx_intr_desc0; 5849*695a8586SSepherosa Ziehau 5850*695a8586SSepherosa Ziehau intr->bnx_ret->bnx_msix_mbx = intr->bnx_intr_mbx; 5851*695a8586SSepherosa Ziehau } 5852*695a8586SSepherosa Ziehau } 5853*695a8586SSepherosa Ziehau 5854*695a8586SSepherosa Ziehau sc->bnx_msix_mem_rid = PCIR_BAR(4); 5855*695a8586SSepherosa Ziehau sc->bnx_msix_mem_res = bus_alloc_resource_any(sc->bnx_dev, 5856*695a8586SSepherosa Ziehau SYS_RES_MEMORY, &sc->bnx_msix_mem_rid, RF_ACTIVE); 5857*695a8586SSepherosa Ziehau if (sc->bnx_msix_mem_res == NULL) { 5858*695a8586SSepherosa Ziehau device_printf(sc->bnx_dev, "could not alloc MSI-X table\n"); 5859*695a8586SSepherosa Ziehau return ENXIO; 5860*695a8586SSepherosa Ziehau } 5861*695a8586SSepherosa Ziehau 5862*695a8586SSepherosa Ziehau bnx_enable_msi(sc, TRUE); 5863*695a8586SSepherosa Ziehau 5864*695a8586SSepherosa Ziehau error = pci_setup_msix(sc->bnx_dev); 5865*695a8586SSepherosa Ziehau if (error) { 5866*695a8586SSepherosa Ziehau device_printf(sc->bnx_dev, "could not setup MSI-X\n"); 5867*695a8586SSepherosa Ziehau goto back; 5868*695a8586SSepherosa Ziehau } 5869*695a8586SSepherosa Ziehau setup = TRUE; 5870*695a8586SSepherosa Ziehau 5871*695a8586SSepherosa Ziehau for (i = 0; i < sc->bnx_intr_cnt; ++i) { 5872*695a8586SSepherosa Ziehau intr = &sc->bnx_intr_data[i]; 5873*695a8586SSepherosa Ziehau 5874*695a8586SSepherosa Ziehau error = pci_alloc_msix_vector(sc->bnx_dev, i, 5875*695a8586SSepherosa Ziehau &intr->bnx_intr_rid, intr->bnx_intr_cpuid); 5876*695a8586SSepherosa Ziehau if (error) { 5877*695a8586SSepherosa Ziehau device_printf(sc->bnx_dev, 5878*695a8586SSepherosa Ziehau "could not alloc MSI-X %d on cpu%d\n", 5879*695a8586SSepherosa Ziehau i, intr->bnx_intr_cpuid); 5880*695a8586SSepherosa Ziehau goto back; 5881*695a8586SSepherosa Ziehau } 5882*695a8586SSepherosa Ziehau 5883*695a8586SSepherosa Ziehau intr->bnx_intr_res = bus_alloc_resource_any(sc->bnx_dev, 5884*695a8586SSepherosa Ziehau SYS_RES_IRQ, &intr->bnx_intr_rid, RF_ACTIVE); 5885*695a8586SSepherosa Ziehau if (intr->bnx_intr_res == NULL) { 5886*695a8586SSepherosa Ziehau device_printf(sc->bnx_dev, 5887*695a8586SSepherosa Ziehau "could not alloc MSI-X %d resource\n", i); 5888*695a8586SSepherosa Ziehau error = ENXIO; 5889*695a8586SSepherosa Ziehau goto back; 5890*695a8586SSepherosa Ziehau } 5891*695a8586SSepherosa Ziehau } 5892*695a8586SSepherosa Ziehau 5893*695a8586SSepherosa Ziehau pci_enable_msix(sc->bnx_dev); 5894*695a8586SSepherosa Ziehau sc->bnx_intr_type = PCI_INTR_TYPE_MSIX; 5895*695a8586SSepherosa Ziehau back: 5896*695a8586SSepherosa Ziehau if (error) 5897*695a8586SSepherosa Ziehau bnx_free_msix(sc, setup); 5898*695a8586SSepherosa Ziehau return error; 5899*695a8586SSepherosa Ziehau } 5900*695a8586SSepherosa Ziehau 5901*695a8586SSepherosa Ziehau static void 5902*695a8586SSepherosa Ziehau bnx_free_msix(struct bnx_softc *sc, boolean_t setup) 5903*695a8586SSepherosa Ziehau { 5904*695a8586SSepherosa Ziehau int i; 5905*695a8586SSepherosa Ziehau 5906*695a8586SSepherosa Ziehau KKASSERT(sc->bnx_intr_cnt > 1); 5907*695a8586SSepherosa Ziehau 5908*695a8586SSepherosa Ziehau for (i = 0; i < sc->bnx_intr_cnt; ++i) { 5909*695a8586SSepherosa Ziehau struct bnx_intr_data *intr = &sc->bnx_intr_data[i]; 5910*695a8586SSepherosa Ziehau 5911*695a8586SSepherosa Ziehau if (intr->bnx_intr_res != NULL) { 5912*695a8586SSepherosa Ziehau bus_release_resource(sc->bnx_dev, SYS_RES_IRQ, 5913*695a8586SSepherosa Ziehau intr->bnx_intr_rid, intr->bnx_intr_res); 5914*695a8586SSepherosa Ziehau } 5915*695a8586SSepherosa Ziehau if (intr->bnx_intr_rid >= 0) { 5916*695a8586SSepherosa Ziehau pci_release_msix_vector(sc->bnx_dev, 5917*695a8586SSepherosa Ziehau intr->bnx_intr_rid); 5918*695a8586SSepherosa Ziehau } 5919*695a8586SSepherosa Ziehau } 5920*695a8586SSepherosa Ziehau if (setup) 5921*695a8586SSepherosa Ziehau pci_teardown_msix(sc->bnx_dev); 5922*695a8586SSepherosa Ziehau } 5923*695a8586SSepherosa Ziehau 5924*695a8586SSepherosa Ziehau static void 5925*695a8586SSepherosa Ziehau bnx_rx_std_refill_sched_ipi(void *xret) 5926*695a8586SSepherosa Ziehau { 5927*695a8586SSepherosa Ziehau struct bnx_rx_ret_ring *ret = xret; 5928*695a8586SSepherosa Ziehau struct bnx_rx_std_ring *std = ret->bnx_std; 5929*695a8586SSepherosa Ziehau struct globaldata *gd = mycpu; 5930*695a8586SSepherosa Ziehau 5931*695a8586SSepherosa Ziehau crit_enter_gd(gd); 5932*695a8586SSepherosa Ziehau 5933*695a8586SSepherosa Ziehau atomic_set_int(&std->bnx_rx_std_refill, ret->bnx_rx_mask); 5934*695a8586SSepherosa Ziehau cpu_sfence(); 5935*695a8586SSepherosa Ziehau 5936*695a8586SSepherosa Ziehau KKASSERT(std->bnx_rx_std_ithread.td_gd == gd); 5937*695a8586SSepherosa Ziehau lwkt_schedule(&std->bnx_rx_std_ithread); 5938*695a8586SSepherosa Ziehau 5939*695a8586SSepherosa Ziehau crit_exit_gd(gd); 5940*695a8586SSepherosa Ziehau } 5941*695a8586SSepherosa Ziehau 5942*695a8586SSepherosa Ziehau static void 5943*695a8586SSepherosa Ziehau bnx_rx_std_refill_stop(void *xstd) 5944*695a8586SSepherosa Ziehau { 5945*695a8586SSepherosa Ziehau struct bnx_rx_std_ring *std = xstd; 5946*695a8586SSepherosa Ziehau struct globaldata *gd = mycpu; 5947*695a8586SSepherosa Ziehau 5948*695a8586SSepherosa Ziehau crit_enter_gd(gd); 5949*695a8586SSepherosa Ziehau 5950*695a8586SSepherosa Ziehau std->bnx_rx_std_stop = 1; 5951*695a8586SSepherosa Ziehau cpu_sfence(); 5952*695a8586SSepherosa Ziehau 5953*695a8586SSepherosa Ziehau KKASSERT(std->bnx_rx_std_ithread.td_gd == gd); 5954*695a8586SSepherosa Ziehau lwkt_schedule(&std->bnx_rx_std_ithread); 5955*695a8586SSepherosa Ziehau 5956*695a8586SSepherosa Ziehau crit_exit_gd(gd); 5957*695a8586SSepherosa Ziehau } 5958*695a8586SSepherosa Ziehau 5959*695a8586SSepherosa Ziehau static void 5960*695a8586SSepherosa Ziehau bnx_serialize_skipmain(struct bnx_softc *sc) 5961*695a8586SSepherosa Ziehau { 5962*695a8586SSepherosa Ziehau lwkt_serialize_array_enter(sc->bnx_serialize, 5963*695a8586SSepherosa Ziehau sc->bnx_serialize_cnt, 1); 5964*695a8586SSepherosa Ziehau } 5965*695a8586SSepherosa Ziehau 5966*695a8586SSepherosa Ziehau static void 5967*695a8586SSepherosa Ziehau bnx_deserialize_skipmain(struct bnx_softc *sc) 5968*695a8586SSepherosa Ziehau { 5969*695a8586SSepherosa Ziehau lwkt_serialize_array_exit(sc->bnx_serialize, 5970*695a8586SSepherosa Ziehau sc->bnx_serialize_cnt, 1); 5971*695a8586SSepherosa Ziehau } 5972*695a8586SSepherosa Ziehau 5973*695a8586SSepherosa Ziehau static void 5974*695a8586SSepherosa Ziehau bnx_rx_std_refill_sched(struct bnx_rx_ret_ring *ret, 5975*695a8586SSepherosa Ziehau struct bnx_rx_std_ring *std) 5976*695a8586SSepherosa Ziehau { 5977*695a8586SSepherosa Ziehau struct globaldata *gd = mycpu; 5978*695a8586SSepherosa Ziehau 5979*695a8586SSepherosa Ziehau ret->bnx_rx_cnt = 0; 5980*695a8586SSepherosa Ziehau cpu_sfence(); 5981*695a8586SSepherosa Ziehau 5982*695a8586SSepherosa Ziehau crit_enter_gd(gd); 5983*695a8586SSepherosa Ziehau 5984*695a8586SSepherosa Ziehau atomic_set_int(&std->bnx_rx_std_refill, ret->bnx_rx_mask); 5985*695a8586SSepherosa Ziehau cpu_sfence(); 5986*695a8586SSepherosa Ziehau if (atomic_poll_acquire_int(&std->bnx_rx_std_running)) { 5987*695a8586SSepherosa Ziehau if (std->bnx_rx_std_ithread.td_gd == gd) { 5988*695a8586SSepherosa Ziehau lwkt_schedule(&std->bnx_rx_std_ithread); 5989*695a8586SSepherosa Ziehau } else { 5990*695a8586SSepherosa Ziehau lwkt_send_ipiq( 5991*695a8586SSepherosa Ziehau std->bnx_rx_std_ithread.td_gd, 5992*695a8586SSepherosa Ziehau bnx_rx_std_refill_sched_ipi, ret); 5993*695a8586SSepherosa Ziehau } 5994*695a8586SSepherosa Ziehau } 5995*695a8586SSepherosa Ziehau 5996*695a8586SSepherosa Ziehau crit_exit_gd(gd); 5997*695a8586SSepherosa Ziehau } 5998