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> 65695a8586SSepherosa Ziehau #include <net/toeplitz.h> 66695a8586SSepherosa 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 74dcb4b80dSSascha Wildner #include "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 864aa71e73SSepherosa Ziehau #define BNX_RESET_SHUTDOWN 0 874aa71e73SSepherosa Ziehau #define BNX_RESET_START 1 884aa71e73SSepherosa Ziehau #define BNX_RESET_SUSPEND 2 894aa71e73SSepherosa Ziehau 90df9ccc98SSepherosa Ziehau #define BNX_INTR_CKINTVL ((10 * hz) / 1000) /* 10ms */ 91df9ccc98SSepherosa Ziehau 92695a8586SSepherosa Ziehau #ifdef BNX_RSS_DEBUG 93695a8586SSepherosa Ziehau #define BNX_RSS_DPRINTF(sc, lvl, fmt, ...) \ 94695a8586SSepherosa Ziehau do { \ 95695a8586SSepherosa Ziehau if (sc->bnx_rss_debug >= lvl) \ 96695a8586SSepherosa Ziehau if_printf(&sc->arpcom.ac_if, fmt, __VA_ARGS__); \ 97695a8586SSepherosa Ziehau } while (0) 98695a8586SSepherosa Ziehau #else /* !BNX_RSS_DEBUG */ 99695a8586SSepherosa Ziehau #define BNX_RSS_DPRINTF(sc, lvl, fmt, ...) ((void)0) 100695a8586SSepherosa Ziehau #endif /* BNX_RSS_DEBUG */ 101695a8586SSepherosa Ziehau 1026c8d8eccSSepherosa Ziehau static const struct bnx_type { 1036c8d8eccSSepherosa Ziehau uint16_t bnx_vid; 1046c8d8eccSSepherosa Ziehau uint16_t bnx_did; 1056c8d8eccSSepherosa Ziehau char *bnx_name; 1066c8d8eccSSepherosa Ziehau } bnx_devs[] = { 1076c8d8eccSSepherosa Ziehau { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM5717, 1086c8d8eccSSepherosa Ziehau "Broadcom BCM5717 Gigabit Ethernet" }, 109d79f5d8fSSepherosa Ziehau { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM5717C, 110d79f5d8fSSepherosa Ziehau "Broadcom BCM5717C Gigabit Ethernet" }, 1116c8d8eccSSepherosa Ziehau { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM5718, 1126c8d8eccSSepherosa Ziehau "Broadcom BCM5718 Gigabit Ethernet" }, 1136c8d8eccSSepherosa Ziehau { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM5719, 1146c8d8eccSSepherosa Ziehau "Broadcom BCM5719 Gigabit Ethernet" }, 1156c8d8eccSSepherosa Ziehau { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM5720_ALT, 1166c8d8eccSSepherosa Ziehau "Broadcom BCM5720 Gigabit Ethernet" }, 1176c8d8eccSSepherosa Ziehau 118b96cbbb6SSepherosa Ziehau { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM5725, 119b96cbbb6SSepherosa Ziehau "Broadcom BCM5725 Gigabit Ethernet" }, 120b96cbbb6SSepherosa Ziehau { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM5727, 121b96cbbb6SSepherosa Ziehau "Broadcom BCM5727 Gigabit Ethernet" }, 122b96cbbb6SSepherosa Ziehau { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM5762, 123b96cbbb6SSepherosa Ziehau "Broadcom BCM5762 Gigabit Ethernet" }, 124b96cbbb6SSepherosa Ziehau 1256c8d8eccSSepherosa Ziehau { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM57761, 1266c8d8eccSSepherosa Ziehau "Broadcom BCM57761 Gigabit Ethernet" }, 12732ff3c80SSepherosa Ziehau { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM57762, 12832ff3c80SSepherosa Ziehau "Broadcom BCM57762 Gigabit Ethernet" }, 1296c8d8eccSSepherosa Ziehau { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM57765, 1306c8d8eccSSepherosa Ziehau "Broadcom BCM57765 Gigabit Ethernet" }, 13132ff3c80SSepherosa Ziehau { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM57766, 13232ff3c80SSepherosa Ziehau "Broadcom BCM57766 Gigabit Ethernet" }, 13332ff3c80SSepherosa Ziehau { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM57781, 13432ff3c80SSepherosa Ziehau "Broadcom BCM57781 Gigabit Ethernet" }, 13532ff3c80SSepherosa Ziehau { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM57782, 13632ff3c80SSepherosa Ziehau "Broadcom BCM57782 Gigabit Ethernet" }, 1376c8d8eccSSepherosa Ziehau { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM57785, 1386c8d8eccSSepherosa Ziehau "Broadcom BCM57785 Gigabit Ethernet" }, 13932ff3c80SSepherosa Ziehau { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM57786, 14032ff3c80SSepherosa Ziehau "Broadcom BCM57786 Gigabit Ethernet" }, 14132ff3c80SSepherosa Ziehau { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM57791, 14232ff3c80SSepherosa Ziehau "Broadcom BCM57791 Fast Ethernet" }, 1436c8d8eccSSepherosa Ziehau { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM57795, 1446c8d8eccSSepherosa Ziehau "Broadcom BCM57795 Fast Ethernet" }, 1456c8d8eccSSepherosa Ziehau 1466c8d8eccSSepherosa Ziehau { 0, 0, NULL } 1476c8d8eccSSepherosa Ziehau }; 1486c8d8eccSSepherosa Ziehau 1491c9d03f6SSepherosa Ziehau static const int bnx_tx_mailbox[BNX_TX_RING_MAX] = { 1501c9d03f6SSepherosa Ziehau BGE_MBX_TX_HOST_PROD0_LO, 1511c9d03f6SSepherosa Ziehau BGE_MBX_TX_HOST_PROD0_HI, 1521c9d03f6SSepherosa Ziehau BGE_MBX_TX_HOST_PROD1_LO, 1531c9d03f6SSepherosa Ziehau BGE_MBX_TX_HOST_PROD1_HI 1541c9d03f6SSepherosa Ziehau }; 1551c9d03f6SSepherosa Ziehau 1566c8d8eccSSepherosa Ziehau #define BNX_IS_JUMBO_CAPABLE(sc) ((sc)->bnx_flags & BNX_FLAG_JUMBO) 1576c8d8eccSSepherosa Ziehau #define BNX_IS_5717_PLUS(sc) ((sc)->bnx_flags & BNX_FLAG_5717_PLUS) 158f368d0d9SSepherosa Ziehau #define BNX_IS_57765_PLUS(sc) ((sc)->bnx_flags & BNX_FLAG_57765_PLUS) 159f368d0d9SSepherosa Ziehau #define BNX_IS_57765_FAMILY(sc) \ 160f368d0d9SSepherosa Ziehau ((sc)->bnx_flags & BNX_FLAG_57765_FAMILY) 1616c8d8eccSSepherosa Ziehau 1626c8d8eccSSepherosa Ziehau typedef int (*bnx_eaddr_fcn_t)(struct bnx_softc *, uint8_t[]); 1636c8d8eccSSepherosa Ziehau 1646c8d8eccSSepherosa Ziehau static int bnx_probe(device_t); 1656c8d8eccSSepherosa Ziehau static int bnx_attach(device_t); 1666c8d8eccSSepherosa Ziehau static int bnx_detach(device_t); 1676c8d8eccSSepherosa Ziehau static void bnx_shutdown(device_t); 1686c8d8eccSSepherosa Ziehau static int bnx_suspend(device_t); 1696c8d8eccSSepherosa Ziehau static int bnx_resume(device_t); 1706c8d8eccSSepherosa Ziehau static int bnx_miibus_readreg(device_t, int, int); 1716c8d8eccSSepherosa Ziehau static int bnx_miibus_writereg(device_t, int, int, int); 1726c8d8eccSSepherosa Ziehau static void bnx_miibus_statchg(device_t); 1736c8d8eccSSepherosa Ziehau 17424e16e4bSSepherosa Ziehau static int bnx_handle_status(struct bnx_softc *); 17539a8d43aSSepherosa Ziehau #ifdef IFPOLL_ENABLE 17639a8d43aSSepherosa Ziehau static void bnx_npoll(struct ifnet *, struct ifpoll_info *); 1774fa38985SSepherosa Ziehau static void bnx_npoll_rx(struct ifnet *, void *, int); 1784fa38985SSepherosa Ziehau static void bnx_npoll_tx(struct ifnet *, void *, int); 179695a8586SSepherosa Ziehau static void bnx_npoll_tx_notag(struct ifnet *, void *, int); 1804fa38985SSepherosa Ziehau static void bnx_npoll_status(struct ifnet *); 181695a8586SSepherosa Ziehau static void bnx_npoll_status_notag(struct ifnet *); 1826c8d8eccSSepherosa Ziehau #endif 1836c8d8eccSSepherosa Ziehau static void bnx_intr_legacy(void *); 18403cc99fdSSepherosa Ziehau static void bnx_msi(void *); 1856c8d8eccSSepherosa Ziehau static void bnx_intr(struct bnx_softc *); 186695a8586SSepherosa Ziehau static void bnx_msix_status(void *); 187695a8586SSepherosa Ziehau static void bnx_msix_tx_status(void *); 188695a8586SSepherosa Ziehau static void bnx_msix_rx(void *); 189695a8586SSepherosa Ziehau static void bnx_msix_rxtx(void *); 1906c8d8eccSSepherosa Ziehau static void bnx_enable_intr(struct bnx_softc *); 1916c8d8eccSSepherosa Ziehau static void bnx_disable_intr(struct bnx_softc *); 19233a04907SSepherosa Ziehau static void bnx_txeof(struct bnx_tx_ring *, uint16_t); 193beedf5beSSepherosa Ziehau static void bnx_rxeof(struct bnx_rx_ret_ring *, uint16_t, int); 1940c7da01dSSepherosa Ziehau static int bnx_alloc_intr(struct bnx_softc *); 1950c7da01dSSepherosa Ziehau static int bnx_setup_intr(struct bnx_softc *); 1960c7da01dSSepherosa Ziehau static void bnx_free_intr(struct bnx_softc *); 197f33ac8a4SSepherosa Ziehau static void bnx_teardown_intr(struct bnx_softc *, int); 198695a8586SSepherosa Ziehau static int bnx_alloc_msix(struct bnx_softc *); 199695a8586SSepherosa Ziehau static void bnx_free_msix(struct bnx_softc *, boolean_t); 200695a8586SSepherosa Ziehau static void bnx_check_intr_rxtx(void *); 201695a8586SSepherosa Ziehau static void bnx_check_intr_rx(void *); 202695a8586SSepherosa Ziehau static void bnx_check_intr_tx(void *); 203841cdf08SSepherosa Ziehau static void bnx_rx_std_refill_ithread(void *); 204841cdf08SSepherosa Ziehau static void bnx_rx_std_refill(void *, void *); 205695a8586SSepherosa Ziehau static void bnx_rx_std_refill_sched_ipi(void *); 206695a8586SSepherosa Ziehau static void bnx_rx_std_refill_stop(void *); 207695a8586SSepherosa Ziehau static void bnx_rx_std_refill_sched(struct bnx_rx_ret_ring *, 208695a8586SSepherosa Ziehau struct bnx_rx_std_ring *); 2096c8d8eccSSepherosa Ziehau 210f0a26983SSepherosa Ziehau static void bnx_start(struct ifnet *, struct ifaltq_subque *); 2116c8d8eccSSepherosa Ziehau static int bnx_ioctl(struct ifnet *, u_long, caddr_t, struct ucred *); 2126c8d8eccSSepherosa Ziehau static void bnx_init(void *); 2136c8d8eccSSepherosa Ziehau static void bnx_stop(struct bnx_softc *); 2143397dea6SSepherosa Ziehau static void bnx_watchdog(struct ifaltq_subque *); 2156c8d8eccSSepherosa Ziehau static int bnx_ifmedia_upd(struct ifnet *); 2166c8d8eccSSepherosa Ziehau static void bnx_ifmedia_sts(struct ifnet *, struct ifmediareq *); 2176c8d8eccSSepherosa Ziehau static void bnx_tick(void *); 218329f9016SSepherosa Ziehau static void bnx_serialize(struct ifnet *, enum ifnet_serialize); 219329f9016SSepherosa Ziehau static void bnx_deserialize(struct ifnet *, enum ifnet_serialize); 220329f9016SSepherosa Ziehau static int bnx_tryserialize(struct ifnet *, enum ifnet_serialize); 221329f9016SSepherosa Ziehau #ifdef INVARIANTS 222329f9016SSepherosa Ziehau static void bnx_serialize_assert(struct ifnet *, enum ifnet_serialize, 223329f9016SSepherosa Ziehau boolean_t); 224329f9016SSepherosa Ziehau #endif 225695a8586SSepherosa Ziehau static void bnx_serialize_skipmain(struct bnx_softc *); 226695a8586SSepherosa Ziehau static void bnx_deserialize_skipmain(struct bnx_softc *sc); 2276c8d8eccSSepherosa Ziehau 2286c8d8eccSSepherosa Ziehau static int bnx_alloc_jumbo_mem(struct bnx_softc *); 2296c8d8eccSSepherosa Ziehau static void bnx_free_jumbo_mem(struct bnx_softc *); 2306c8d8eccSSepherosa Ziehau static struct bnx_jslot 2316c8d8eccSSepherosa Ziehau *bnx_jalloc(struct bnx_softc *); 2326c8d8eccSSepherosa Ziehau static void bnx_jfree(void *); 2336c8d8eccSSepherosa Ziehau static void bnx_jref(void *); 234beedf5beSSepherosa Ziehau static int bnx_newbuf_std(struct bnx_rx_ret_ring *, int, int); 2356c8d8eccSSepherosa Ziehau static int bnx_newbuf_jumbo(struct bnx_softc *, int, int); 236beedf5beSSepherosa Ziehau static void bnx_setup_rxdesc_std(struct bnx_rx_std_ring *, int); 2376c8d8eccSSepherosa Ziehau static void bnx_setup_rxdesc_jumbo(struct bnx_softc *, int); 238beedf5beSSepherosa Ziehau static int bnx_init_rx_ring_std(struct bnx_rx_std_ring *); 239beedf5beSSepherosa Ziehau static void bnx_free_rx_ring_std(struct bnx_rx_std_ring *); 2406c8d8eccSSepherosa Ziehau static int bnx_init_rx_ring_jumbo(struct bnx_softc *); 2416c8d8eccSSepherosa Ziehau static void bnx_free_rx_ring_jumbo(struct bnx_softc *); 24233a04907SSepherosa Ziehau static void bnx_free_tx_ring(struct bnx_tx_ring *); 24333a04907SSepherosa Ziehau static int bnx_init_tx_ring(struct bnx_tx_ring *); 24433a04907SSepherosa Ziehau static int bnx_create_tx_ring(struct bnx_tx_ring *); 24533a04907SSepherosa Ziehau static void bnx_destroy_tx_ring(struct bnx_tx_ring *); 246beedf5beSSepherosa Ziehau static int bnx_create_rx_ret_ring(struct bnx_rx_ret_ring *); 247beedf5beSSepherosa Ziehau static void bnx_destroy_rx_ret_ring(struct bnx_rx_ret_ring *); 248beedf5beSSepherosa Ziehau static int bnx_dma_alloc(device_t); 2496c8d8eccSSepherosa Ziehau static void bnx_dma_free(struct bnx_softc *); 2506c8d8eccSSepherosa Ziehau static int bnx_dma_block_alloc(struct bnx_softc *, bus_size_t, 2516c8d8eccSSepherosa Ziehau bus_dma_tag_t *, bus_dmamap_t *, void **, bus_addr_t *); 2526c8d8eccSSepherosa Ziehau static void bnx_dma_block_free(bus_dma_tag_t, bus_dmamap_t, void *); 2536c8d8eccSSepherosa Ziehau static struct mbuf * 2546c8d8eccSSepherosa Ziehau bnx_defrag_shortdma(struct mbuf *); 25533a04907SSepherosa Ziehau static int bnx_encap(struct bnx_tx_ring *, struct mbuf **, 256c9b7f592SSepherosa Ziehau uint32_t *, int *); 25733a04907SSepherosa Ziehau static int bnx_setup_tso(struct bnx_tx_ring *, struct mbuf **, 25866deb1c1SSepherosa Ziehau uint16_t *, uint16_t *); 259329f9016SSepherosa Ziehau static void bnx_setup_serialize(struct bnx_softc *); 2607dbaa833SSepherosa Ziehau static void bnx_set_tick_cpuid(struct bnx_softc *, boolean_t); 261695a8586SSepherosa Ziehau static void bnx_setup_ring_cnt(struct bnx_softc *); 2626c8d8eccSSepherosa Ziehau 263b19ddf7eSSepherosa Ziehau static struct pktinfo *bnx_rss_info(struct pktinfo *, 264b19ddf7eSSepherosa Ziehau const struct bge_rx_bd *); 265695a8586SSepherosa Ziehau static void bnx_init_rss(struct bnx_softc *); 2666c8d8eccSSepherosa Ziehau static void bnx_reset(struct bnx_softc *); 2676c8d8eccSSepherosa Ziehau static int bnx_chipinit(struct bnx_softc *); 2686c8d8eccSSepherosa Ziehau static int bnx_blockinit(struct bnx_softc *); 2696c8d8eccSSepherosa Ziehau static void bnx_stop_block(struct bnx_softc *, bus_size_t, uint32_t); 270695a8586SSepherosa Ziehau static void bnx_enable_msi(struct bnx_softc *, boolean_t); 2716c8d8eccSSepherosa Ziehau static void bnx_setmulti(struct bnx_softc *); 2726c8d8eccSSepherosa Ziehau static void bnx_setpromisc(struct bnx_softc *); 2736c8d8eccSSepherosa Ziehau static void bnx_stats_update_regs(struct bnx_softc *); 2746c8d8eccSSepherosa Ziehau static uint32_t bnx_dma_swap_options(struct bnx_softc *); 2756c8d8eccSSepherosa Ziehau 2766c8d8eccSSepherosa Ziehau static uint32_t bnx_readmem_ind(struct bnx_softc *, uint32_t); 2776c8d8eccSSepherosa Ziehau static void bnx_writemem_ind(struct bnx_softc *, uint32_t, uint32_t); 2786c8d8eccSSepherosa Ziehau #ifdef notdef 2796c8d8eccSSepherosa Ziehau static uint32_t bnx_readreg_ind(struct bnx_softc *, uint32_t); 2806c8d8eccSSepherosa Ziehau #endif 2816c8d8eccSSepherosa Ziehau static void bnx_writemem_direct(struct bnx_softc *, uint32_t, uint32_t); 2826c8d8eccSSepherosa Ziehau static void bnx_writembx(struct bnx_softc *, int, int); 2836c8d8eccSSepherosa Ziehau static int bnx_read_nvram(struct bnx_softc *, caddr_t, int, int); 2846c8d8eccSSepherosa Ziehau static uint8_t bnx_eeprom_getbyte(struct bnx_softc *, uint32_t, uint8_t *); 2856c8d8eccSSepherosa Ziehau static int bnx_read_eeprom(struct bnx_softc *, caddr_t, uint32_t, size_t); 2866c8d8eccSSepherosa Ziehau 2876c8d8eccSSepherosa Ziehau static void bnx_tbi_link_upd(struct bnx_softc *, uint32_t); 2886c8d8eccSSepherosa Ziehau static void bnx_copper_link_upd(struct bnx_softc *, uint32_t); 2896c8d8eccSSepherosa Ziehau static void bnx_autopoll_link_upd(struct bnx_softc *, uint32_t); 2906c8d8eccSSepherosa Ziehau static void bnx_link_poll(struct bnx_softc *); 2916c8d8eccSSepherosa Ziehau 2926c8d8eccSSepherosa Ziehau static int bnx_get_eaddr_mem(struct bnx_softc *, uint8_t[]); 2936c8d8eccSSepherosa Ziehau static int bnx_get_eaddr_nvram(struct bnx_softc *, uint8_t[]); 2946c8d8eccSSepherosa Ziehau static int bnx_get_eaddr_eeprom(struct bnx_softc *, uint8_t[]); 2956c8d8eccSSepherosa Ziehau static int bnx_get_eaddr(struct bnx_softc *, uint8_t[]); 2966c8d8eccSSepherosa Ziehau 2976c8d8eccSSepherosa Ziehau static void bnx_coal_change(struct bnx_softc *); 298aad4de2bSSepherosa Ziehau static int bnx_sysctl_force_defrag(SYSCTL_HANDLER_ARGS); 299472c99c8SSepherosa Ziehau static int bnx_sysctl_tx_wreg(SYSCTL_HANDLER_ARGS); 3006c8d8eccSSepherosa Ziehau static int bnx_sysctl_rx_coal_ticks(SYSCTL_HANDLER_ARGS); 3016c8d8eccSSepherosa Ziehau static int bnx_sysctl_tx_coal_ticks(SYSCTL_HANDLER_ARGS); 3026c8d8eccSSepherosa Ziehau static int bnx_sysctl_rx_coal_bds(SYSCTL_HANDLER_ARGS); 303a86cc105SSepherosa Ziehau static int bnx_sysctl_rx_coal_bds_poll(SYSCTL_HANDLER_ARGS); 3046c8d8eccSSepherosa Ziehau static int bnx_sysctl_tx_coal_bds(SYSCTL_HANDLER_ARGS); 30527357d84SSepherosa Ziehau static int bnx_sysctl_tx_coal_bds_poll(SYSCTL_HANDLER_ARGS); 3066c8d8eccSSepherosa Ziehau static int bnx_sysctl_rx_coal_bds_int(SYSCTL_HANDLER_ARGS); 3076c8d8eccSSepherosa Ziehau static int bnx_sysctl_tx_coal_bds_int(SYSCTL_HANDLER_ARGS); 3086c8d8eccSSepherosa Ziehau static int bnx_sysctl_coal_chg(SYSCTL_HANDLER_ARGS, uint32_t *, 3096c8d8eccSSepherosa Ziehau int, int, uint32_t); 3104fa38985SSepherosa Ziehau #ifdef IFPOLL_ENABLE 3114fa38985SSepherosa Ziehau static int bnx_sysctl_npoll_offset(SYSCTL_HANDLER_ARGS); 3124fa38985SSepherosa Ziehau static int bnx_sysctl_npoll_rxoff(SYSCTL_HANDLER_ARGS); 3134fa38985SSepherosa Ziehau static int bnx_sysctl_npoll_txoff(SYSCTL_HANDLER_ARGS); 3144fa38985SSepherosa Ziehau #endif 315841cdf08SSepherosa Ziehau static int bnx_sysctl_std_refill(SYSCTL_HANDLER_ARGS); 3166c8d8eccSSepherosa Ziehau 3174aa71e73SSepherosa Ziehau static void bnx_sig_post_reset(struct bnx_softc *, int); 3184aa71e73SSepherosa Ziehau static void bnx_sig_pre_reset(struct bnx_softc *, int); 3199f5082d5SSepherosa Ziehau static void bnx_ape_lock_init(struct bnx_softc *); 3209f5082d5SSepherosa Ziehau static void bnx_ape_read_fw_ver(struct bnx_softc *); 3219f5082d5SSepherosa Ziehau static int bnx_ape_lock(struct bnx_softc *, int); 3229f5082d5SSepherosa Ziehau static void bnx_ape_unlock(struct bnx_softc *, int); 3239f5082d5SSepherosa Ziehau static void bnx_ape_send_event(struct bnx_softc *, uint32_t); 3249f5082d5SSepherosa Ziehau static void bnx_ape_driver_state_change(struct bnx_softc *, int); 3254aa71e73SSepherosa Ziehau 3266c8d8eccSSepherosa Ziehau static int bnx_msi_enable = 1; 327695a8586SSepherosa Ziehau static int bnx_msix_enable = 1; 328695a8586SSepherosa Ziehau 329695a8586SSepherosa Ziehau static int bnx_rx_rings = 0; /* auto */ 330695a8586SSepherosa Ziehau static int bnx_tx_rings = 0; /* auto */ 331695a8586SSepherosa Ziehau 3326c8d8eccSSepherosa Ziehau TUNABLE_INT("hw.bnx.msi.enable", &bnx_msi_enable); 333695a8586SSepherosa Ziehau TUNABLE_INT("hw.bnx.msix.enable", &bnx_msix_enable); 334695a8586SSepherosa Ziehau TUNABLE_INT("hw.bnx.rx_rings", &bnx_rx_rings); 335695a8586SSepherosa Ziehau TUNABLE_INT("hw.bnx.tx_rings", &bnx_tx_rings); 3366c8d8eccSSepherosa Ziehau 3376c8d8eccSSepherosa Ziehau static device_method_t bnx_methods[] = { 3386c8d8eccSSepherosa Ziehau /* Device interface */ 3396c8d8eccSSepherosa Ziehau DEVMETHOD(device_probe, bnx_probe), 3406c8d8eccSSepherosa Ziehau DEVMETHOD(device_attach, bnx_attach), 3416c8d8eccSSepherosa Ziehau DEVMETHOD(device_detach, bnx_detach), 3426c8d8eccSSepherosa Ziehau DEVMETHOD(device_shutdown, bnx_shutdown), 3436c8d8eccSSepherosa Ziehau DEVMETHOD(device_suspend, bnx_suspend), 3446c8d8eccSSepherosa Ziehau DEVMETHOD(device_resume, bnx_resume), 3456c8d8eccSSepherosa Ziehau 3466c8d8eccSSepherosa Ziehau /* bus interface */ 3476c8d8eccSSepherosa Ziehau DEVMETHOD(bus_print_child, bus_generic_print_child), 3486c8d8eccSSepherosa Ziehau DEVMETHOD(bus_driver_added, bus_generic_driver_added), 3496c8d8eccSSepherosa Ziehau 3506c8d8eccSSepherosa Ziehau /* MII interface */ 3516c8d8eccSSepherosa Ziehau DEVMETHOD(miibus_readreg, bnx_miibus_readreg), 3526c8d8eccSSepherosa Ziehau DEVMETHOD(miibus_writereg, bnx_miibus_writereg), 3536c8d8eccSSepherosa Ziehau DEVMETHOD(miibus_statchg, bnx_miibus_statchg), 3546c8d8eccSSepherosa Ziehau 355d3c9c58eSSascha Wildner DEVMETHOD_END 3566c8d8eccSSepherosa Ziehau }; 3576c8d8eccSSepherosa Ziehau 3586c8d8eccSSepherosa Ziehau static DEFINE_CLASS_0(bnx, bnx_driver, bnx_methods, sizeof(struct bnx_softc)); 3596c8d8eccSSepherosa Ziehau static devclass_t bnx_devclass; 3606c8d8eccSSepherosa Ziehau 3616c8d8eccSSepherosa Ziehau DECLARE_DUMMY_MODULE(if_bnx); 3626c8d8eccSSepherosa Ziehau DRIVER_MODULE(if_bnx, pci, bnx_driver, bnx_devclass, NULL, NULL); 3636c8d8eccSSepherosa Ziehau DRIVER_MODULE(miibus, bnx, miibus_driver, miibus_devclass, NULL, NULL); 3646c8d8eccSSepherosa Ziehau 3656c8d8eccSSepherosa Ziehau static uint32_t 3666c8d8eccSSepherosa Ziehau bnx_readmem_ind(struct bnx_softc *sc, uint32_t off) 3676c8d8eccSSepherosa Ziehau { 3686c8d8eccSSepherosa Ziehau device_t dev = sc->bnx_dev; 3696c8d8eccSSepherosa Ziehau uint32_t val; 3706c8d8eccSSepherosa Ziehau 3716c8d8eccSSepherosa Ziehau pci_write_config(dev, BGE_PCI_MEMWIN_BASEADDR, off, 4); 3726c8d8eccSSepherosa Ziehau val = pci_read_config(dev, BGE_PCI_MEMWIN_DATA, 4); 3736c8d8eccSSepherosa Ziehau pci_write_config(dev, BGE_PCI_MEMWIN_BASEADDR, 0, 4); 3746c8d8eccSSepherosa Ziehau return (val); 3756c8d8eccSSepherosa Ziehau } 3766c8d8eccSSepherosa Ziehau 3776c8d8eccSSepherosa Ziehau static void 3786c8d8eccSSepherosa Ziehau bnx_writemem_ind(struct bnx_softc *sc, uint32_t off, uint32_t val) 3796c8d8eccSSepherosa Ziehau { 3806c8d8eccSSepherosa Ziehau device_t dev = sc->bnx_dev; 3816c8d8eccSSepherosa Ziehau 3826c8d8eccSSepherosa Ziehau pci_write_config(dev, BGE_PCI_MEMWIN_BASEADDR, off, 4); 3836c8d8eccSSepherosa Ziehau pci_write_config(dev, BGE_PCI_MEMWIN_DATA, val, 4); 3846c8d8eccSSepherosa Ziehau pci_write_config(dev, BGE_PCI_MEMWIN_BASEADDR, 0, 4); 3856c8d8eccSSepherosa Ziehau } 3866c8d8eccSSepherosa Ziehau 3876c8d8eccSSepherosa Ziehau static void 3886c8d8eccSSepherosa Ziehau bnx_writemem_direct(struct bnx_softc *sc, uint32_t off, uint32_t val) 3896c8d8eccSSepherosa Ziehau { 3906c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, off, val); 3916c8d8eccSSepherosa Ziehau } 3926c8d8eccSSepherosa Ziehau 3936c8d8eccSSepherosa Ziehau static void 3946c8d8eccSSepherosa Ziehau bnx_writembx(struct bnx_softc *sc, int off, int val) 3956c8d8eccSSepherosa Ziehau { 3966c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, off, val); 3976c8d8eccSSepherosa Ziehau } 3986c8d8eccSSepherosa Ziehau 3996c8d8eccSSepherosa Ziehau /* 4006c8d8eccSSepherosa Ziehau * Read a sequence of bytes from NVRAM. 4016c8d8eccSSepherosa Ziehau */ 4026c8d8eccSSepherosa Ziehau static int 4036c8d8eccSSepherosa Ziehau bnx_read_nvram(struct bnx_softc *sc, caddr_t dest, int off, int cnt) 4046c8d8eccSSepherosa Ziehau { 4056c8d8eccSSepherosa Ziehau return (1); 4066c8d8eccSSepherosa Ziehau } 4076c8d8eccSSepherosa Ziehau 4086c8d8eccSSepherosa Ziehau /* 4096c8d8eccSSepherosa Ziehau * Read a byte of data stored in the EEPROM at address 'addr.' The 4106c8d8eccSSepherosa Ziehau * BCM570x supports both the traditional bitbang interface and an 4116c8d8eccSSepherosa Ziehau * auto access interface for reading the EEPROM. We use the auto 4126c8d8eccSSepherosa Ziehau * access method. 4136c8d8eccSSepherosa Ziehau */ 4146c8d8eccSSepherosa Ziehau static uint8_t 4156c8d8eccSSepherosa Ziehau bnx_eeprom_getbyte(struct bnx_softc *sc, uint32_t addr, uint8_t *dest) 4166c8d8eccSSepherosa Ziehau { 4176c8d8eccSSepherosa Ziehau int i; 4186c8d8eccSSepherosa Ziehau uint32_t byte = 0; 4196c8d8eccSSepherosa Ziehau 4206c8d8eccSSepherosa Ziehau /* 4216c8d8eccSSepherosa Ziehau * Enable use of auto EEPROM access so we can avoid 4226c8d8eccSSepherosa Ziehau * having to use the bitbang method. 4236c8d8eccSSepherosa Ziehau */ 4246c8d8eccSSepherosa Ziehau BNX_SETBIT(sc, BGE_MISC_LOCAL_CTL, BGE_MLC_AUTO_EEPROM); 4256c8d8eccSSepherosa Ziehau 4266c8d8eccSSepherosa Ziehau /* Reset the EEPROM, load the clock period. */ 4276c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_EE_ADDR, 4286c8d8eccSSepherosa Ziehau BGE_EEADDR_RESET|BGE_EEHALFCLK(BGE_HALFCLK_384SCL)); 4296c8d8eccSSepherosa Ziehau DELAY(20); 4306c8d8eccSSepherosa Ziehau 4316c8d8eccSSepherosa Ziehau /* Issue the read EEPROM command. */ 4326c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_EE_ADDR, BGE_EE_READCMD | addr); 4336c8d8eccSSepherosa Ziehau 4346c8d8eccSSepherosa Ziehau /* Wait for completion */ 4356c8d8eccSSepherosa Ziehau for(i = 0; i < BNX_TIMEOUT * 10; i++) { 4366c8d8eccSSepherosa Ziehau DELAY(10); 4376c8d8eccSSepherosa Ziehau if (CSR_READ_4(sc, BGE_EE_ADDR) & BGE_EEADDR_DONE) 4386c8d8eccSSepherosa Ziehau break; 4396c8d8eccSSepherosa Ziehau } 4406c8d8eccSSepherosa Ziehau 4416c8d8eccSSepherosa Ziehau if (i == BNX_TIMEOUT) { 4426c8d8eccSSepherosa Ziehau if_printf(&sc->arpcom.ac_if, "eeprom read timed out\n"); 4436c8d8eccSSepherosa Ziehau return(1); 4446c8d8eccSSepherosa Ziehau } 4456c8d8eccSSepherosa Ziehau 4466c8d8eccSSepherosa Ziehau /* Get result. */ 4476c8d8eccSSepherosa Ziehau byte = CSR_READ_4(sc, BGE_EE_DATA); 4486c8d8eccSSepherosa Ziehau 4496c8d8eccSSepherosa Ziehau *dest = (byte >> ((addr % 4) * 8)) & 0xFF; 4506c8d8eccSSepherosa Ziehau 4516c8d8eccSSepherosa Ziehau return(0); 4526c8d8eccSSepherosa Ziehau } 4536c8d8eccSSepherosa Ziehau 4546c8d8eccSSepherosa Ziehau /* 4556c8d8eccSSepherosa Ziehau * Read a sequence of bytes from the EEPROM. 4566c8d8eccSSepherosa Ziehau */ 4576c8d8eccSSepherosa Ziehau static int 4586c8d8eccSSepherosa Ziehau bnx_read_eeprom(struct bnx_softc *sc, caddr_t dest, uint32_t off, size_t len) 4596c8d8eccSSepherosa Ziehau { 4606c8d8eccSSepherosa Ziehau size_t i; 4616c8d8eccSSepherosa Ziehau int err; 4626c8d8eccSSepherosa Ziehau uint8_t byte; 4636c8d8eccSSepherosa Ziehau 4646c8d8eccSSepherosa Ziehau for (byte = 0, err = 0, i = 0; i < len; i++) { 4656c8d8eccSSepherosa Ziehau err = bnx_eeprom_getbyte(sc, off + i, &byte); 4666c8d8eccSSepherosa Ziehau if (err) 4676c8d8eccSSepherosa Ziehau break; 4686c8d8eccSSepherosa Ziehau *(dest + i) = byte; 4696c8d8eccSSepherosa Ziehau } 4706c8d8eccSSepherosa Ziehau 4716c8d8eccSSepherosa Ziehau return(err ? 1 : 0); 4726c8d8eccSSepherosa Ziehau } 4736c8d8eccSSepherosa Ziehau 4746c8d8eccSSepherosa Ziehau static int 4756c8d8eccSSepherosa Ziehau bnx_miibus_readreg(device_t dev, int phy, int reg) 4766c8d8eccSSepherosa Ziehau { 4776c8d8eccSSepherosa Ziehau struct bnx_softc *sc = device_get_softc(dev); 4786c8d8eccSSepherosa Ziehau uint32_t val; 4796c8d8eccSSepherosa Ziehau int i; 4806c8d8eccSSepherosa Ziehau 4816c8d8eccSSepherosa Ziehau KASSERT(phy == sc->bnx_phyno, 4826c8d8eccSSepherosa Ziehau ("invalid phyno %d, should be %d", phy, sc->bnx_phyno)); 4836c8d8eccSSepherosa Ziehau 4849f5082d5SSepherosa Ziehau if (bnx_ape_lock(sc, sc->bnx_phy_ape_lock) != 0) 4859f5082d5SSepherosa Ziehau return 0; 4869f5082d5SSepherosa Ziehau 4876c8d8eccSSepherosa Ziehau /* Clear the autopoll bit if set, otherwise may trigger PCI errors. */ 4886c8d8eccSSepherosa Ziehau if (sc->bnx_mi_mode & BGE_MIMODE_AUTOPOLL) { 4896c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_MI_MODE, 4906c8d8eccSSepherosa Ziehau sc->bnx_mi_mode & ~BGE_MIMODE_AUTOPOLL); 4916c8d8eccSSepherosa Ziehau DELAY(80); 4926c8d8eccSSepherosa Ziehau } 4936c8d8eccSSepherosa Ziehau 4946c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_MI_COMM, BGE_MICMD_READ | BGE_MICOMM_BUSY | 4956c8d8eccSSepherosa Ziehau BGE_MIPHY(phy) | BGE_MIREG(reg)); 4966c8d8eccSSepherosa Ziehau 4976c8d8eccSSepherosa Ziehau /* Poll for the PHY register access to complete. */ 4986c8d8eccSSepherosa Ziehau for (i = 0; i < BNX_TIMEOUT; i++) { 4996c8d8eccSSepherosa Ziehau DELAY(10); 5006c8d8eccSSepherosa Ziehau val = CSR_READ_4(sc, BGE_MI_COMM); 5016c8d8eccSSepherosa Ziehau if ((val & BGE_MICOMM_BUSY) == 0) { 5026c8d8eccSSepherosa Ziehau DELAY(5); 5036c8d8eccSSepherosa Ziehau val = CSR_READ_4(sc, BGE_MI_COMM); 5046c8d8eccSSepherosa Ziehau break; 5056c8d8eccSSepherosa Ziehau } 5066c8d8eccSSepherosa Ziehau } 5076c8d8eccSSepherosa Ziehau if (i == BNX_TIMEOUT) { 5086c8d8eccSSepherosa Ziehau if_printf(&sc->arpcom.ac_if, "PHY read timed out " 5096c8d8eccSSepherosa Ziehau "(phy %d, reg %d, val 0x%08x)\n", phy, reg, val); 5106c8d8eccSSepherosa Ziehau val = 0; 5116c8d8eccSSepherosa Ziehau } 5126c8d8eccSSepherosa Ziehau 5136c8d8eccSSepherosa Ziehau /* Restore the autopoll bit if necessary. */ 5146c8d8eccSSepherosa Ziehau if (sc->bnx_mi_mode & BGE_MIMODE_AUTOPOLL) { 5156c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_MI_MODE, sc->bnx_mi_mode); 5166c8d8eccSSepherosa Ziehau DELAY(80); 5176c8d8eccSSepherosa Ziehau } 5186c8d8eccSSepherosa Ziehau 5199f5082d5SSepherosa Ziehau bnx_ape_unlock(sc, sc->bnx_phy_ape_lock); 5209f5082d5SSepherosa Ziehau 5216c8d8eccSSepherosa Ziehau if (val & BGE_MICOMM_READFAIL) 5226c8d8eccSSepherosa Ziehau return 0; 5236c8d8eccSSepherosa Ziehau 5246c8d8eccSSepherosa Ziehau return (val & 0xFFFF); 5256c8d8eccSSepherosa Ziehau } 5266c8d8eccSSepherosa Ziehau 5276c8d8eccSSepherosa Ziehau static int 5286c8d8eccSSepherosa Ziehau bnx_miibus_writereg(device_t dev, int phy, int reg, int val) 5296c8d8eccSSepherosa Ziehau { 5306c8d8eccSSepherosa Ziehau struct bnx_softc *sc = device_get_softc(dev); 5316c8d8eccSSepherosa Ziehau int i; 5326c8d8eccSSepherosa Ziehau 5336c8d8eccSSepherosa Ziehau KASSERT(phy == sc->bnx_phyno, 5346c8d8eccSSepherosa Ziehau ("invalid phyno %d, should be %d", phy, sc->bnx_phyno)); 5356c8d8eccSSepherosa Ziehau 5369f5082d5SSepherosa Ziehau if (bnx_ape_lock(sc, sc->bnx_phy_ape_lock) != 0) 5379f5082d5SSepherosa Ziehau return 0; 5389f5082d5SSepherosa Ziehau 5396c8d8eccSSepherosa Ziehau /* Clear the autopoll bit if set, otherwise may trigger PCI errors. */ 5406c8d8eccSSepherosa Ziehau if (sc->bnx_mi_mode & BGE_MIMODE_AUTOPOLL) { 5416c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_MI_MODE, 5426c8d8eccSSepherosa Ziehau sc->bnx_mi_mode & ~BGE_MIMODE_AUTOPOLL); 5436c8d8eccSSepherosa Ziehau DELAY(80); 5446c8d8eccSSepherosa Ziehau } 5456c8d8eccSSepherosa Ziehau 5466c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_MI_COMM, BGE_MICMD_WRITE | BGE_MICOMM_BUSY | 5476c8d8eccSSepherosa Ziehau BGE_MIPHY(phy) | BGE_MIREG(reg) | val); 5486c8d8eccSSepherosa Ziehau 5496c8d8eccSSepherosa Ziehau for (i = 0; i < BNX_TIMEOUT; i++) { 5506c8d8eccSSepherosa Ziehau DELAY(10); 5516c8d8eccSSepherosa Ziehau if (!(CSR_READ_4(sc, BGE_MI_COMM) & BGE_MICOMM_BUSY)) { 5526c8d8eccSSepherosa Ziehau DELAY(5); 5536c8d8eccSSepherosa Ziehau CSR_READ_4(sc, BGE_MI_COMM); /* dummy read */ 5546c8d8eccSSepherosa Ziehau break; 5556c8d8eccSSepherosa Ziehau } 5566c8d8eccSSepherosa Ziehau } 5576c8d8eccSSepherosa Ziehau if (i == BNX_TIMEOUT) { 5586c8d8eccSSepherosa Ziehau if_printf(&sc->arpcom.ac_if, "PHY write timed out " 5596c8d8eccSSepherosa Ziehau "(phy %d, reg %d, val %d)\n", phy, reg, val); 5606c8d8eccSSepherosa Ziehau } 5616c8d8eccSSepherosa Ziehau 5626c8d8eccSSepherosa Ziehau /* Restore the autopoll bit if necessary. */ 5636c8d8eccSSepherosa Ziehau if (sc->bnx_mi_mode & BGE_MIMODE_AUTOPOLL) { 5646c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_MI_MODE, sc->bnx_mi_mode); 5656c8d8eccSSepherosa Ziehau DELAY(80); 5666c8d8eccSSepherosa Ziehau } 5676c8d8eccSSepherosa Ziehau 5689f5082d5SSepherosa Ziehau bnx_ape_unlock(sc, sc->bnx_phy_ape_lock); 5699f5082d5SSepherosa Ziehau 5706c8d8eccSSepherosa Ziehau return 0; 5716c8d8eccSSepherosa Ziehau } 5726c8d8eccSSepherosa Ziehau 5736c8d8eccSSepherosa Ziehau static void 5746c8d8eccSSepherosa Ziehau bnx_miibus_statchg(device_t dev) 5756c8d8eccSSepherosa Ziehau { 5766c8d8eccSSepherosa Ziehau struct bnx_softc *sc; 5776c8d8eccSSepherosa Ziehau struct mii_data *mii; 5784aa71e73SSepherosa Ziehau uint32_t mac_mode; 5796c8d8eccSSepherosa Ziehau 5806c8d8eccSSepherosa Ziehau sc = device_get_softc(dev); 5814aa71e73SSepherosa Ziehau if ((sc->arpcom.ac_if.if_flags & IFF_RUNNING) == 0) 5824aa71e73SSepherosa Ziehau return; 5834aa71e73SSepherosa Ziehau 5846c8d8eccSSepherosa Ziehau mii = device_get_softc(sc->bnx_miibus); 5856c8d8eccSSepherosa Ziehau 5866c8d8eccSSepherosa Ziehau if ((mii->mii_media_status & (IFM_ACTIVE | IFM_AVALID)) == 5876c8d8eccSSepherosa Ziehau (IFM_ACTIVE | IFM_AVALID)) { 5886c8d8eccSSepherosa Ziehau switch (IFM_SUBTYPE(mii->mii_media_active)) { 5896c8d8eccSSepherosa Ziehau case IFM_10_T: 5906c8d8eccSSepherosa Ziehau case IFM_100_TX: 5916c8d8eccSSepherosa Ziehau sc->bnx_link = 1; 5926c8d8eccSSepherosa Ziehau break; 5936c8d8eccSSepherosa Ziehau case IFM_1000_T: 5946c8d8eccSSepherosa Ziehau case IFM_1000_SX: 5956c8d8eccSSepherosa Ziehau case IFM_2500_SX: 5966c8d8eccSSepherosa Ziehau sc->bnx_link = 1; 5976c8d8eccSSepherosa Ziehau break; 5986c8d8eccSSepherosa Ziehau default: 5996c8d8eccSSepherosa Ziehau sc->bnx_link = 0; 6006c8d8eccSSepherosa Ziehau break; 6016c8d8eccSSepherosa Ziehau } 6026c8d8eccSSepherosa Ziehau } else { 6036c8d8eccSSepherosa Ziehau sc->bnx_link = 0; 6046c8d8eccSSepherosa Ziehau } 6056c8d8eccSSepherosa Ziehau if (sc->bnx_link == 0) 6066c8d8eccSSepherosa Ziehau return; 6076c8d8eccSSepherosa Ziehau 6084aa71e73SSepherosa Ziehau /* 6094aa71e73SSepherosa Ziehau * APE firmware touches these registers to keep the MAC 6104aa71e73SSepherosa Ziehau * connected to the outside world. Try to keep the 6114aa71e73SSepherosa Ziehau * accesses atomic. 6124aa71e73SSepherosa Ziehau */ 6136c8d8eccSSepherosa Ziehau 6144aa71e73SSepherosa Ziehau mac_mode = CSR_READ_4(sc, BGE_MAC_MODE) & 6154aa71e73SSepherosa Ziehau ~(BGE_MACMODE_PORTMODE | BGE_MACMODE_HALF_DUPLEX); 6164aa71e73SSepherosa Ziehau 6174aa71e73SSepherosa Ziehau if (IFM_SUBTYPE(mii->mii_media_active) == IFM_1000_T || 6184aa71e73SSepherosa Ziehau IFM_SUBTYPE(mii->mii_media_active) == IFM_1000_SX) 6194aa71e73SSepherosa Ziehau mac_mode |= BGE_PORTMODE_GMII; 6204aa71e73SSepherosa Ziehau else 6214aa71e73SSepherosa Ziehau mac_mode |= BGE_PORTMODE_MII; 6224aa71e73SSepherosa Ziehau 6234aa71e73SSepherosa Ziehau if ((mii->mii_media_active & IFM_GMASK) != IFM_FDX) 6244aa71e73SSepherosa Ziehau mac_mode |= BGE_MACMODE_HALF_DUPLEX; 6254aa71e73SSepherosa Ziehau 6264aa71e73SSepherosa Ziehau CSR_WRITE_4(sc, BGE_MAC_MODE, mac_mode); 6274aa71e73SSepherosa Ziehau DELAY(40); 6286c8d8eccSSepherosa Ziehau } 6296c8d8eccSSepherosa Ziehau 6306c8d8eccSSepherosa Ziehau /* 6316c8d8eccSSepherosa Ziehau * Memory management for jumbo frames. 6326c8d8eccSSepherosa Ziehau */ 6336c8d8eccSSepherosa Ziehau static int 6346c8d8eccSSepherosa Ziehau bnx_alloc_jumbo_mem(struct bnx_softc *sc) 6356c8d8eccSSepherosa Ziehau { 6366c8d8eccSSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if; 6376c8d8eccSSepherosa Ziehau struct bnx_jslot *entry; 6386c8d8eccSSepherosa Ziehau uint8_t *ptr; 6396c8d8eccSSepherosa Ziehau bus_addr_t paddr; 6406c8d8eccSSepherosa Ziehau int i, error; 6416c8d8eccSSepherosa Ziehau 6426c8d8eccSSepherosa Ziehau /* 6436c8d8eccSSepherosa Ziehau * Create tag for jumbo mbufs. 6446c8d8eccSSepherosa Ziehau * This is really a bit of a kludge. We allocate a special 6456c8d8eccSSepherosa Ziehau * jumbo buffer pool which (thanks to the way our DMA 6466c8d8eccSSepherosa Ziehau * memory allocation works) will consist of contiguous 6476c8d8eccSSepherosa Ziehau * pages. This means that even though a jumbo buffer might 6486c8d8eccSSepherosa Ziehau * be larger than a page size, we don't really need to 6496c8d8eccSSepherosa Ziehau * map it into more than one DMA segment. However, the 6506c8d8eccSSepherosa Ziehau * default mbuf tag will result in multi-segment mappings, 6516c8d8eccSSepherosa Ziehau * so we have to create a special jumbo mbuf tag that 6526c8d8eccSSepherosa Ziehau * lets us get away with mapping the jumbo buffers as 6536c8d8eccSSepherosa Ziehau * a single segment. I think eventually the driver should 6546c8d8eccSSepherosa Ziehau * be changed so that it uses ordinary mbufs and cluster 6556c8d8eccSSepherosa Ziehau * buffers, i.e. jumbo frames can span multiple DMA 6566c8d8eccSSepherosa Ziehau * descriptors. But that's a project for another day. 6576c8d8eccSSepherosa Ziehau */ 6586c8d8eccSSepherosa Ziehau 6596c8d8eccSSepherosa Ziehau /* 6606c8d8eccSSepherosa Ziehau * Create DMA stuffs for jumbo RX ring. 6616c8d8eccSSepherosa Ziehau */ 6626c8d8eccSSepherosa Ziehau error = bnx_dma_block_alloc(sc, BGE_JUMBO_RX_RING_SZ, 6636c8d8eccSSepherosa Ziehau &sc->bnx_cdata.bnx_rx_jumbo_ring_tag, 6646c8d8eccSSepherosa Ziehau &sc->bnx_cdata.bnx_rx_jumbo_ring_map, 6656c8d8eccSSepherosa Ziehau (void *)&sc->bnx_ldata.bnx_rx_jumbo_ring, 6666c8d8eccSSepherosa Ziehau &sc->bnx_ldata.bnx_rx_jumbo_ring_paddr); 6676c8d8eccSSepherosa Ziehau if (error) { 6686c8d8eccSSepherosa Ziehau if_printf(ifp, "could not create jumbo RX ring\n"); 6696c8d8eccSSepherosa Ziehau return error; 6706c8d8eccSSepherosa Ziehau } 6716c8d8eccSSepherosa Ziehau 6726c8d8eccSSepherosa Ziehau /* 6736c8d8eccSSepherosa Ziehau * Create DMA stuffs for jumbo buffer block. 6746c8d8eccSSepherosa Ziehau */ 6756c8d8eccSSepherosa Ziehau error = bnx_dma_block_alloc(sc, BNX_JMEM, 6766c8d8eccSSepherosa Ziehau &sc->bnx_cdata.bnx_jumbo_tag, 6776c8d8eccSSepherosa Ziehau &sc->bnx_cdata.bnx_jumbo_map, 6786c8d8eccSSepherosa Ziehau (void **)&sc->bnx_ldata.bnx_jumbo_buf, 6796c8d8eccSSepherosa Ziehau &paddr); 6806c8d8eccSSepherosa Ziehau if (error) { 6816c8d8eccSSepherosa Ziehau if_printf(ifp, "could not create jumbo buffer\n"); 6826c8d8eccSSepherosa Ziehau return error; 6836c8d8eccSSepherosa Ziehau } 6846c8d8eccSSepherosa Ziehau 6856c8d8eccSSepherosa Ziehau SLIST_INIT(&sc->bnx_jfree_listhead); 6866c8d8eccSSepherosa Ziehau 6876c8d8eccSSepherosa Ziehau /* 6886c8d8eccSSepherosa Ziehau * Now divide it up into 9K pieces and save the addresses 6896c8d8eccSSepherosa Ziehau * in an array. Note that we play an evil trick here by using 6906c8d8eccSSepherosa Ziehau * the first few bytes in the buffer to hold the the address 6916c8d8eccSSepherosa Ziehau * of the softc structure for this interface. This is because 6926c8d8eccSSepherosa Ziehau * bnx_jfree() needs it, but it is called by the mbuf management 6936c8d8eccSSepherosa Ziehau * code which will not pass it to us explicitly. 6946c8d8eccSSepherosa Ziehau */ 6956c8d8eccSSepherosa Ziehau for (i = 0, ptr = sc->bnx_ldata.bnx_jumbo_buf; i < BNX_JSLOTS; i++) { 6966c8d8eccSSepherosa Ziehau entry = &sc->bnx_cdata.bnx_jslots[i]; 6976c8d8eccSSepherosa Ziehau entry->bnx_sc = sc; 6986c8d8eccSSepherosa Ziehau entry->bnx_buf = ptr; 6996c8d8eccSSepherosa Ziehau entry->bnx_paddr = paddr; 7006c8d8eccSSepherosa Ziehau entry->bnx_inuse = 0; 7016c8d8eccSSepherosa Ziehau entry->bnx_slot = i; 7026c8d8eccSSepherosa Ziehau SLIST_INSERT_HEAD(&sc->bnx_jfree_listhead, entry, jslot_link); 7036c8d8eccSSepherosa Ziehau 7046c8d8eccSSepherosa Ziehau ptr += BNX_JLEN; 7056c8d8eccSSepherosa Ziehau paddr += BNX_JLEN; 7066c8d8eccSSepherosa Ziehau } 7076c8d8eccSSepherosa Ziehau return 0; 7086c8d8eccSSepherosa Ziehau } 7096c8d8eccSSepherosa Ziehau 7106c8d8eccSSepherosa Ziehau static void 7116c8d8eccSSepherosa Ziehau bnx_free_jumbo_mem(struct bnx_softc *sc) 7126c8d8eccSSepherosa Ziehau { 7136c8d8eccSSepherosa Ziehau /* Destroy jumbo RX ring. */ 7146c8d8eccSSepherosa Ziehau bnx_dma_block_free(sc->bnx_cdata.bnx_rx_jumbo_ring_tag, 7156c8d8eccSSepherosa Ziehau sc->bnx_cdata.bnx_rx_jumbo_ring_map, 7166c8d8eccSSepherosa Ziehau sc->bnx_ldata.bnx_rx_jumbo_ring); 7176c8d8eccSSepherosa Ziehau 7186c8d8eccSSepherosa Ziehau /* Destroy jumbo buffer block. */ 7196c8d8eccSSepherosa Ziehau bnx_dma_block_free(sc->bnx_cdata.bnx_jumbo_tag, 7206c8d8eccSSepherosa Ziehau sc->bnx_cdata.bnx_jumbo_map, 7216c8d8eccSSepherosa Ziehau sc->bnx_ldata.bnx_jumbo_buf); 7226c8d8eccSSepherosa Ziehau } 7236c8d8eccSSepherosa Ziehau 7246c8d8eccSSepherosa Ziehau /* 7256c8d8eccSSepherosa Ziehau * Allocate a jumbo buffer. 7266c8d8eccSSepherosa Ziehau */ 7276c8d8eccSSepherosa Ziehau static struct bnx_jslot * 7286c8d8eccSSepherosa Ziehau bnx_jalloc(struct bnx_softc *sc) 7296c8d8eccSSepherosa Ziehau { 7306c8d8eccSSepherosa Ziehau struct bnx_jslot *entry; 7316c8d8eccSSepherosa Ziehau 7326c8d8eccSSepherosa Ziehau lwkt_serialize_enter(&sc->bnx_jslot_serializer); 7336c8d8eccSSepherosa Ziehau entry = SLIST_FIRST(&sc->bnx_jfree_listhead); 7346c8d8eccSSepherosa Ziehau if (entry) { 7356c8d8eccSSepherosa Ziehau SLIST_REMOVE_HEAD(&sc->bnx_jfree_listhead, jslot_link); 7366c8d8eccSSepherosa Ziehau entry->bnx_inuse = 1; 7376c8d8eccSSepherosa Ziehau } else { 7386c8d8eccSSepherosa Ziehau if_printf(&sc->arpcom.ac_if, "no free jumbo buffers\n"); 7396c8d8eccSSepherosa Ziehau } 7406c8d8eccSSepherosa Ziehau lwkt_serialize_exit(&sc->bnx_jslot_serializer); 7416c8d8eccSSepherosa Ziehau return(entry); 7426c8d8eccSSepherosa Ziehau } 7436c8d8eccSSepherosa Ziehau 7446c8d8eccSSepherosa Ziehau /* 7456c8d8eccSSepherosa Ziehau * Adjust usage count on a jumbo buffer. 7466c8d8eccSSepherosa Ziehau */ 7476c8d8eccSSepherosa Ziehau static void 7486c8d8eccSSepherosa Ziehau bnx_jref(void *arg) 7496c8d8eccSSepherosa Ziehau { 7506c8d8eccSSepherosa Ziehau struct bnx_jslot *entry = (struct bnx_jslot *)arg; 7516c8d8eccSSepherosa Ziehau struct bnx_softc *sc = entry->bnx_sc; 7526c8d8eccSSepherosa Ziehau 7536c8d8eccSSepherosa Ziehau if (sc == NULL) 7546c8d8eccSSepherosa Ziehau panic("bnx_jref: can't find softc pointer!"); 7556c8d8eccSSepherosa Ziehau 7566c8d8eccSSepherosa Ziehau if (&sc->bnx_cdata.bnx_jslots[entry->bnx_slot] != entry) { 7576c8d8eccSSepherosa Ziehau panic("bnx_jref: asked to reference buffer " 7586c8d8eccSSepherosa Ziehau "that we don't manage!"); 7596c8d8eccSSepherosa Ziehau } else if (entry->bnx_inuse == 0) { 7606c8d8eccSSepherosa Ziehau panic("bnx_jref: buffer already free!"); 7616c8d8eccSSepherosa Ziehau } else { 7626c8d8eccSSepherosa Ziehau atomic_add_int(&entry->bnx_inuse, 1); 7636c8d8eccSSepherosa Ziehau } 7646c8d8eccSSepherosa Ziehau } 7656c8d8eccSSepherosa Ziehau 7666c8d8eccSSepherosa Ziehau /* 7676c8d8eccSSepherosa Ziehau * Release a jumbo buffer. 7686c8d8eccSSepherosa Ziehau */ 7696c8d8eccSSepherosa Ziehau static void 7706c8d8eccSSepherosa Ziehau bnx_jfree(void *arg) 7716c8d8eccSSepherosa Ziehau { 7726c8d8eccSSepherosa Ziehau struct bnx_jslot *entry = (struct bnx_jslot *)arg; 7736c8d8eccSSepherosa Ziehau struct bnx_softc *sc = entry->bnx_sc; 7746c8d8eccSSepherosa Ziehau 7756c8d8eccSSepherosa Ziehau if (sc == NULL) 7766c8d8eccSSepherosa Ziehau panic("bnx_jfree: can't find softc pointer!"); 7776c8d8eccSSepherosa Ziehau 7786c8d8eccSSepherosa Ziehau if (&sc->bnx_cdata.bnx_jslots[entry->bnx_slot] != entry) { 7796c8d8eccSSepherosa Ziehau panic("bnx_jfree: asked to free buffer that we don't manage!"); 7806c8d8eccSSepherosa Ziehau } else if (entry->bnx_inuse == 0) { 7816c8d8eccSSepherosa Ziehau panic("bnx_jfree: buffer already free!"); 7826c8d8eccSSepherosa Ziehau } else { 7836c8d8eccSSepherosa Ziehau /* 7846c8d8eccSSepherosa Ziehau * Possible MP race to 0, use the serializer. The atomic insn 7856c8d8eccSSepherosa Ziehau * is still needed for races against bnx_jref(). 7866c8d8eccSSepherosa Ziehau */ 7876c8d8eccSSepherosa Ziehau lwkt_serialize_enter(&sc->bnx_jslot_serializer); 7886c8d8eccSSepherosa Ziehau atomic_subtract_int(&entry->bnx_inuse, 1); 7896c8d8eccSSepherosa Ziehau if (entry->bnx_inuse == 0) { 7906c8d8eccSSepherosa Ziehau SLIST_INSERT_HEAD(&sc->bnx_jfree_listhead, 7916c8d8eccSSepherosa Ziehau entry, jslot_link); 7926c8d8eccSSepherosa Ziehau } 7936c8d8eccSSepherosa Ziehau lwkt_serialize_exit(&sc->bnx_jslot_serializer); 7946c8d8eccSSepherosa Ziehau } 7956c8d8eccSSepherosa Ziehau } 7966c8d8eccSSepherosa Ziehau 7976c8d8eccSSepherosa Ziehau 7986c8d8eccSSepherosa Ziehau /* 7996c8d8eccSSepherosa Ziehau * Intialize a standard receive ring descriptor. 8006c8d8eccSSepherosa Ziehau */ 8016c8d8eccSSepherosa Ziehau static int 802beedf5beSSepherosa Ziehau bnx_newbuf_std(struct bnx_rx_ret_ring *ret, int i, int init) 8036c8d8eccSSepherosa Ziehau { 8046c8d8eccSSepherosa Ziehau struct mbuf *m_new = NULL; 8056c8d8eccSSepherosa Ziehau bus_dma_segment_t seg; 8066c8d8eccSSepherosa Ziehau bus_dmamap_t map; 8076c8d8eccSSepherosa Ziehau int error, nsegs; 808beedf5beSSepherosa Ziehau struct bnx_rx_buf *rb; 8096c8d8eccSSepherosa Ziehau 810841cdf08SSepherosa Ziehau rb = &ret->bnx_std->bnx_rx_std_buf[i]; 811841cdf08SSepherosa Ziehau KASSERT(!rb->bnx_rx_refilled, ("RX buf %dth has been refilled", i)); 812841cdf08SSepherosa Ziehau 8136c8d8eccSSepherosa Ziehau m_new = m_getcl(init ? MB_WAIT : MB_DONTWAIT, MT_DATA, M_PKTHDR); 814841cdf08SSepherosa Ziehau if (m_new == NULL) { 815841cdf08SSepherosa Ziehau error = ENOBUFS; 816841cdf08SSepherosa Ziehau goto back; 817841cdf08SSepherosa Ziehau } 8186c8d8eccSSepherosa Ziehau m_new->m_len = m_new->m_pkthdr.len = MCLBYTES; 8196c8d8eccSSepherosa Ziehau m_adj(m_new, ETHER_ALIGN); 8206c8d8eccSSepherosa Ziehau 821beedf5beSSepherosa Ziehau error = bus_dmamap_load_mbuf_segment(ret->bnx_rx_mtag, 822beedf5beSSepherosa Ziehau ret->bnx_rx_tmpmap, m_new, &seg, 1, &nsegs, BUS_DMA_NOWAIT); 8236c8d8eccSSepherosa Ziehau if (error) { 8246c8d8eccSSepherosa Ziehau m_freem(m_new); 825841cdf08SSepherosa Ziehau goto back; 8266c8d8eccSSepherosa Ziehau } 8276c8d8eccSSepherosa Ziehau 8286c8d8eccSSepherosa Ziehau if (!init) { 829beedf5beSSepherosa Ziehau bus_dmamap_sync(ret->bnx_rx_mtag, rb->bnx_rx_dmamap, 8306c8d8eccSSepherosa Ziehau BUS_DMASYNC_POSTREAD); 831beedf5beSSepherosa Ziehau bus_dmamap_unload(ret->bnx_rx_mtag, rb->bnx_rx_dmamap); 8326c8d8eccSSepherosa Ziehau } 8336c8d8eccSSepherosa Ziehau 834beedf5beSSepherosa Ziehau map = ret->bnx_rx_tmpmap; 835beedf5beSSepherosa Ziehau ret->bnx_rx_tmpmap = rb->bnx_rx_dmamap; 8366c8d8eccSSepherosa Ziehau 837841cdf08SSepherosa Ziehau rb->bnx_rx_dmamap = map; 838beedf5beSSepherosa Ziehau rb->bnx_rx_mbuf = m_new; 839beedf5beSSepherosa Ziehau rb->bnx_rx_paddr = seg.ds_addr; 840695a8586SSepherosa Ziehau rb->bnx_rx_len = m_new->m_len; 841841cdf08SSepherosa Ziehau back: 842841cdf08SSepherosa Ziehau cpu_sfence(); 843841cdf08SSepherosa Ziehau rb->bnx_rx_refilled = 1; 844841cdf08SSepherosa Ziehau return error; 8456c8d8eccSSepherosa Ziehau } 8466c8d8eccSSepherosa Ziehau 8476c8d8eccSSepherosa Ziehau static void 848beedf5beSSepherosa Ziehau bnx_setup_rxdesc_std(struct bnx_rx_std_ring *std, int i) 8496c8d8eccSSepherosa Ziehau { 850841cdf08SSepherosa Ziehau struct bnx_rx_buf *rb; 8516c8d8eccSSepherosa Ziehau struct bge_rx_bd *r; 852695a8586SSepherosa Ziehau bus_addr_t paddr; 853695a8586SSepherosa Ziehau int len; 8546c8d8eccSSepherosa Ziehau 855beedf5beSSepherosa Ziehau rb = &std->bnx_rx_std_buf[i]; 856841cdf08SSepherosa Ziehau KASSERT(rb->bnx_rx_refilled, ("RX buf %dth is not refilled", i)); 857695a8586SSepherosa Ziehau 858695a8586SSepherosa Ziehau paddr = rb->bnx_rx_paddr; 859695a8586SSepherosa Ziehau len = rb->bnx_rx_len; 860695a8586SSepherosa Ziehau 861695a8586SSepherosa Ziehau cpu_mfence(); 862695a8586SSepherosa Ziehau 863841cdf08SSepherosa Ziehau rb->bnx_rx_refilled = 0; 8646c8d8eccSSepherosa Ziehau 865841cdf08SSepherosa Ziehau r = &std->bnx_rx_std_ring[i]; 866695a8586SSepherosa Ziehau r->bge_addr.bge_addr_lo = BGE_ADDR_LO(paddr); 867695a8586SSepherosa Ziehau r->bge_addr.bge_addr_hi = BGE_ADDR_HI(paddr); 868695a8586SSepherosa Ziehau r->bge_len = len; 8696c8d8eccSSepherosa Ziehau r->bge_idx = i; 8706c8d8eccSSepherosa Ziehau r->bge_flags = BGE_RXBDFLAG_END; 8716c8d8eccSSepherosa Ziehau } 8726c8d8eccSSepherosa Ziehau 8736c8d8eccSSepherosa Ziehau /* 8746c8d8eccSSepherosa Ziehau * Initialize a jumbo receive ring descriptor. This allocates 8756c8d8eccSSepherosa Ziehau * a jumbo buffer from the pool managed internally by the driver. 8766c8d8eccSSepherosa Ziehau */ 8776c8d8eccSSepherosa Ziehau static int 8786c8d8eccSSepherosa Ziehau bnx_newbuf_jumbo(struct bnx_softc *sc, int i, int init) 8796c8d8eccSSepherosa Ziehau { 8806c8d8eccSSepherosa Ziehau struct mbuf *m_new = NULL; 8816c8d8eccSSepherosa Ziehau struct bnx_jslot *buf; 8826c8d8eccSSepherosa Ziehau bus_addr_t paddr; 8836c8d8eccSSepherosa Ziehau 8846c8d8eccSSepherosa Ziehau /* Allocate the mbuf. */ 8856c8d8eccSSepherosa Ziehau MGETHDR(m_new, init ? MB_WAIT : MB_DONTWAIT, MT_DATA); 8866c8d8eccSSepherosa Ziehau if (m_new == NULL) 8876c8d8eccSSepherosa Ziehau return ENOBUFS; 8886c8d8eccSSepherosa Ziehau 8896c8d8eccSSepherosa Ziehau /* Allocate the jumbo buffer */ 8906c8d8eccSSepherosa Ziehau buf = bnx_jalloc(sc); 8916c8d8eccSSepherosa Ziehau if (buf == NULL) { 8926c8d8eccSSepherosa Ziehau m_freem(m_new); 8936c8d8eccSSepherosa Ziehau return ENOBUFS; 8946c8d8eccSSepherosa Ziehau } 8956c8d8eccSSepherosa Ziehau 8966c8d8eccSSepherosa Ziehau /* Attach the buffer to the mbuf. */ 8976c8d8eccSSepherosa Ziehau m_new->m_ext.ext_arg = buf; 8986c8d8eccSSepherosa Ziehau m_new->m_ext.ext_buf = buf->bnx_buf; 8996c8d8eccSSepherosa Ziehau m_new->m_ext.ext_free = bnx_jfree; 9006c8d8eccSSepherosa Ziehau m_new->m_ext.ext_ref = bnx_jref; 9016c8d8eccSSepherosa Ziehau m_new->m_ext.ext_size = BNX_JUMBO_FRAMELEN; 9026c8d8eccSSepherosa Ziehau 9036c8d8eccSSepherosa Ziehau m_new->m_flags |= M_EXT; 9046c8d8eccSSepherosa Ziehau 9056c8d8eccSSepherosa Ziehau m_new->m_data = m_new->m_ext.ext_buf; 9066c8d8eccSSepherosa Ziehau m_new->m_len = m_new->m_pkthdr.len = m_new->m_ext.ext_size; 9076c8d8eccSSepherosa Ziehau 9086c8d8eccSSepherosa Ziehau paddr = buf->bnx_paddr; 9096c8d8eccSSepherosa Ziehau m_adj(m_new, ETHER_ALIGN); 9106c8d8eccSSepherosa Ziehau paddr += ETHER_ALIGN; 9116c8d8eccSSepherosa Ziehau 9126c8d8eccSSepherosa Ziehau /* Save necessary information */ 913beedf5beSSepherosa Ziehau sc->bnx_cdata.bnx_rx_jumbo_chain[i].bnx_rx_mbuf = m_new; 914beedf5beSSepherosa Ziehau sc->bnx_cdata.bnx_rx_jumbo_chain[i].bnx_rx_paddr = paddr; 9156c8d8eccSSepherosa Ziehau 9166c8d8eccSSepherosa Ziehau /* Set up the descriptor. */ 9176c8d8eccSSepherosa Ziehau bnx_setup_rxdesc_jumbo(sc, i); 9186c8d8eccSSepherosa Ziehau return 0; 9196c8d8eccSSepherosa Ziehau } 9206c8d8eccSSepherosa Ziehau 9216c8d8eccSSepherosa Ziehau static void 9226c8d8eccSSepherosa Ziehau bnx_setup_rxdesc_jumbo(struct bnx_softc *sc, int i) 9236c8d8eccSSepherosa Ziehau { 9246c8d8eccSSepherosa Ziehau struct bge_rx_bd *r; 925beedf5beSSepherosa Ziehau struct bnx_rx_buf *rc; 9266c8d8eccSSepherosa Ziehau 9276c8d8eccSSepherosa Ziehau r = &sc->bnx_ldata.bnx_rx_jumbo_ring[i]; 9286c8d8eccSSepherosa Ziehau rc = &sc->bnx_cdata.bnx_rx_jumbo_chain[i]; 9296c8d8eccSSepherosa Ziehau 930beedf5beSSepherosa Ziehau r->bge_addr.bge_addr_lo = BGE_ADDR_LO(rc->bnx_rx_paddr); 931beedf5beSSepherosa Ziehau r->bge_addr.bge_addr_hi = BGE_ADDR_HI(rc->bnx_rx_paddr); 932beedf5beSSepherosa Ziehau r->bge_len = rc->bnx_rx_mbuf->m_len; 9336c8d8eccSSepherosa Ziehau r->bge_idx = i; 9346c8d8eccSSepherosa Ziehau r->bge_flags = BGE_RXBDFLAG_END|BGE_RXBDFLAG_JUMBO_RING; 9356c8d8eccSSepherosa Ziehau } 9366c8d8eccSSepherosa Ziehau 9376c8d8eccSSepherosa Ziehau static int 938beedf5beSSepherosa Ziehau bnx_init_rx_ring_std(struct bnx_rx_std_ring *std) 9396c8d8eccSSepherosa Ziehau { 9406c8d8eccSSepherosa Ziehau int i, error; 9416c8d8eccSSepherosa Ziehau 9426c8d8eccSSepherosa Ziehau for (i = 0; i < BGE_STD_RX_RING_CNT; i++) { 943beedf5beSSepherosa Ziehau /* Use the first RX return ring's tmp RX mbuf DMA map */ 944beedf5beSSepherosa Ziehau error = bnx_newbuf_std(&std->bnx_sc->bnx_rx_ret_ring[0], i, 1); 9456c8d8eccSSepherosa Ziehau if (error) 9466c8d8eccSSepherosa Ziehau return error; 947841cdf08SSepherosa Ziehau bnx_setup_rxdesc_std(std, i); 94887c7a7cfSSascha Wildner } 9496c8d8eccSSepherosa Ziehau 950625c3ba3SSepherosa Ziehau std->bnx_rx_std_used = 0; 951841cdf08SSepherosa Ziehau std->bnx_rx_std_refill = 0; 952841cdf08SSepherosa Ziehau std->bnx_rx_std_running = 0; 953841cdf08SSepherosa Ziehau cpu_sfence(); 954841cdf08SSepherosa Ziehau lwkt_serialize_handler_enable(&std->bnx_rx_std_serialize); 955841cdf08SSepherosa Ziehau 956beedf5beSSepherosa Ziehau std->bnx_rx_std = BGE_STD_RX_RING_CNT - 1; 957beedf5beSSepherosa Ziehau bnx_writembx(std->bnx_sc, BGE_MBX_RX_STD_PROD_LO, std->bnx_rx_std); 9586c8d8eccSSepherosa Ziehau 9596c8d8eccSSepherosa Ziehau return(0); 9606c8d8eccSSepherosa Ziehau } 9616c8d8eccSSepherosa Ziehau 9626c8d8eccSSepherosa Ziehau static void 963beedf5beSSepherosa Ziehau bnx_free_rx_ring_std(struct bnx_rx_std_ring *std) 9646c8d8eccSSepherosa Ziehau { 9656c8d8eccSSepherosa Ziehau int i; 9666c8d8eccSSepherosa Ziehau 967841cdf08SSepherosa Ziehau lwkt_serialize_handler_disable(&std->bnx_rx_std_serialize); 968841cdf08SSepherosa Ziehau 9696c8d8eccSSepherosa Ziehau for (i = 0; i < BGE_STD_RX_RING_CNT; i++) { 970beedf5beSSepherosa Ziehau struct bnx_rx_buf *rb = &std->bnx_rx_std_buf[i]; 9716c8d8eccSSepherosa Ziehau 972841cdf08SSepherosa Ziehau rb->bnx_rx_refilled = 0; 973beedf5beSSepherosa Ziehau if (rb->bnx_rx_mbuf != NULL) { 974beedf5beSSepherosa Ziehau bus_dmamap_unload(std->bnx_rx_mtag, rb->bnx_rx_dmamap); 975beedf5beSSepherosa Ziehau m_freem(rb->bnx_rx_mbuf); 976beedf5beSSepherosa Ziehau rb->bnx_rx_mbuf = NULL; 9776c8d8eccSSepherosa Ziehau } 978beedf5beSSepherosa Ziehau bzero(&std->bnx_rx_std_ring[i], sizeof(struct bge_rx_bd)); 9796c8d8eccSSepherosa Ziehau } 9806c8d8eccSSepherosa Ziehau } 9816c8d8eccSSepherosa Ziehau 9826c8d8eccSSepherosa Ziehau static int 9836c8d8eccSSepherosa Ziehau bnx_init_rx_ring_jumbo(struct bnx_softc *sc) 9846c8d8eccSSepherosa Ziehau { 9856c8d8eccSSepherosa Ziehau struct bge_rcb *rcb; 9866c8d8eccSSepherosa Ziehau int i, error; 9876c8d8eccSSepherosa Ziehau 9886c8d8eccSSepherosa Ziehau for (i = 0; i < BGE_JUMBO_RX_RING_CNT; i++) { 9896c8d8eccSSepherosa Ziehau error = bnx_newbuf_jumbo(sc, i, 1); 9906c8d8eccSSepherosa Ziehau if (error) 9916c8d8eccSSepherosa Ziehau return error; 99287c7a7cfSSascha Wildner } 9936c8d8eccSSepherosa Ziehau 9946c8d8eccSSepherosa Ziehau sc->bnx_jumbo = BGE_JUMBO_RX_RING_CNT - 1; 9956c8d8eccSSepherosa Ziehau 9966c8d8eccSSepherosa Ziehau rcb = &sc->bnx_ldata.bnx_info.bnx_jumbo_rx_rcb; 9976c8d8eccSSepherosa Ziehau rcb->bge_maxlen_flags = BGE_RCB_MAXLEN_FLAGS(0, 0); 9986c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_RX_JUMBO_RCB_MAXLEN_FLAGS, rcb->bge_maxlen_flags); 9996c8d8eccSSepherosa Ziehau 10006c8d8eccSSepherosa Ziehau bnx_writembx(sc, BGE_MBX_RX_JUMBO_PROD_LO, sc->bnx_jumbo); 10016c8d8eccSSepherosa Ziehau 10026c8d8eccSSepherosa Ziehau return(0); 10036c8d8eccSSepherosa Ziehau } 10046c8d8eccSSepherosa Ziehau 10056c8d8eccSSepherosa Ziehau static void 10066c8d8eccSSepherosa Ziehau bnx_free_rx_ring_jumbo(struct bnx_softc *sc) 10076c8d8eccSSepherosa Ziehau { 10086c8d8eccSSepherosa Ziehau int i; 10096c8d8eccSSepherosa Ziehau 10106c8d8eccSSepherosa Ziehau for (i = 0; i < BGE_JUMBO_RX_RING_CNT; i++) { 1011beedf5beSSepherosa Ziehau struct bnx_rx_buf *rc = &sc->bnx_cdata.bnx_rx_jumbo_chain[i]; 10126c8d8eccSSepherosa Ziehau 1013beedf5beSSepherosa Ziehau if (rc->bnx_rx_mbuf != NULL) { 1014beedf5beSSepherosa Ziehau m_freem(rc->bnx_rx_mbuf); 1015beedf5beSSepherosa Ziehau rc->bnx_rx_mbuf = NULL; 10166c8d8eccSSepherosa Ziehau } 10176c8d8eccSSepherosa Ziehau bzero(&sc->bnx_ldata.bnx_rx_jumbo_ring[i], 10186c8d8eccSSepherosa Ziehau sizeof(struct bge_rx_bd)); 10196c8d8eccSSepherosa Ziehau } 10206c8d8eccSSepherosa Ziehau } 10216c8d8eccSSepherosa Ziehau 10226c8d8eccSSepherosa Ziehau static void 102333a04907SSepherosa Ziehau bnx_free_tx_ring(struct bnx_tx_ring *txr) 10246c8d8eccSSepherosa Ziehau { 10256c8d8eccSSepherosa Ziehau int i; 10266c8d8eccSSepherosa Ziehau 10276c8d8eccSSepherosa Ziehau for (i = 0; i < BGE_TX_RING_CNT; i++) { 1028fa4b1067SSepherosa Ziehau struct bnx_tx_buf *buf = &txr->bnx_tx_buf[i]; 1029fa4b1067SSepherosa Ziehau 1030fa4b1067SSepherosa Ziehau if (buf->bnx_tx_mbuf != NULL) { 103133a04907SSepherosa Ziehau bus_dmamap_unload(txr->bnx_tx_mtag, 1032fa4b1067SSepherosa Ziehau buf->bnx_tx_dmamap); 1033fa4b1067SSepherosa Ziehau m_freem(buf->bnx_tx_mbuf); 1034fa4b1067SSepherosa Ziehau buf->bnx_tx_mbuf = NULL; 10356c8d8eccSSepherosa Ziehau } 103633a04907SSepherosa Ziehau bzero(&txr->bnx_tx_ring[i], sizeof(struct bge_tx_bd)); 10376c8d8eccSSepherosa Ziehau } 103833a04907SSepherosa Ziehau txr->bnx_tx_saved_considx = BNX_TXCONS_UNSET; 10396c8d8eccSSepherosa Ziehau } 10406c8d8eccSSepherosa Ziehau 10416c8d8eccSSepherosa Ziehau static int 104233a04907SSepherosa Ziehau bnx_init_tx_ring(struct bnx_tx_ring *txr) 10436c8d8eccSSepherosa Ziehau { 1044fa639b88SSepherosa Ziehau txr->bnx_tx_cnt = 0; 104533a04907SSepherosa Ziehau txr->bnx_tx_saved_considx = 0; 104633a04907SSepherosa Ziehau txr->bnx_tx_prodidx = 0; 10476c8d8eccSSepherosa Ziehau 10486c8d8eccSSepherosa Ziehau /* Initialize transmit producer index for host-memory send ring. */ 10498bd43d5dSSepherosa Ziehau bnx_writembx(txr->bnx_sc, txr->bnx_tx_mbx, txr->bnx_tx_prodidx); 10506c8d8eccSSepherosa Ziehau 10516c8d8eccSSepherosa Ziehau return(0); 10526c8d8eccSSepherosa Ziehau } 10536c8d8eccSSepherosa Ziehau 10546c8d8eccSSepherosa Ziehau static void 10556c8d8eccSSepherosa Ziehau bnx_setmulti(struct bnx_softc *sc) 10566c8d8eccSSepherosa Ziehau { 10576c8d8eccSSepherosa Ziehau struct ifnet *ifp; 10586c8d8eccSSepherosa Ziehau struct ifmultiaddr *ifma; 10596c8d8eccSSepherosa Ziehau uint32_t hashes[4] = { 0, 0, 0, 0 }; 10606c8d8eccSSepherosa Ziehau int h, i; 10616c8d8eccSSepherosa Ziehau 10626c8d8eccSSepherosa Ziehau ifp = &sc->arpcom.ac_if; 10636c8d8eccSSepherosa Ziehau 10646c8d8eccSSepherosa Ziehau if (ifp->if_flags & IFF_ALLMULTI || ifp->if_flags & IFF_PROMISC) { 10656c8d8eccSSepherosa Ziehau for (i = 0; i < 4; i++) 10666c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_MAR0 + (i * 4), 0xFFFFFFFF); 10676c8d8eccSSepherosa Ziehau return; 10686c8d8eccSSepherosa Ziehau } 10696c8d8eccSSepherosa Ziehau 10706c8d8eccSSepherosa Ziehau /* First, zot all the existing filters. */ 10716c8d8eccSSepherosa Ziehau for (i = 0; i < 4; i++) 10726c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_MAR0 + (i * 4), 0); 10736c8d8eccSSepherosa Ziehau 10746c8d8eccSSepherosa Ziehau /* Now program new ones. */ 10756c8d8eccSSepherosa Ziehau TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { 10766c8d8eccSSepherosa Ziehau if (ifma->ifma_addr->sa_family != AF_LINK) 10776c8d8eccSSepherosa Ziehau continue; 10786c8d8eccSSepherosa Ziehau h = ether_crc32_le( 10796c8d8eccSSepherosa Ziehau LLADDR((struct sockaddr_dl *)ifma->ifma_addr), 10806c8d8eccSSepherosa Ziehau ETHER_ADDR_LEN) & 0x7f; 10816c8d8eccSSepherosa Ziehau hashes[(h & 0x60) >> 5] |= 1 << (h & 0x1F); 10826c8d8eccSSepherosa Ziehau } 10836c8d8eccSSepherosa Ziehau 10846c8d8eccSSepherosa Ziehau for (i = 0; i < 4; i++) 10856c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_MAR0 + (i * 4), hashes[i]); 10866c8d8eccSSepherosa Ziehau } 10876c8d8eccSSepherosa Ziehau 10886c8d8eccSSepherosa Ziehau /* 10896c8d8eccSSepherosa Ziehau * Do endian, PCI and DMA initialization. Also check the on-board ROM 10906c8d8eccSSepherosa Ziehau * self-test results. 10916c8d8eccSSepherosa Ziehau */ 10926c8d8eccSSepherosa Ziehau static int 10936c8d8eccSSepherosa Ziehau bnx_chipinit(struct bnx_softc *sc) 10946c8d8eccSSepherosa Ziehau { 10956c8d8eccSSepherosa Ziehau uint32_t dma_rw_ctl, mode_ctl; 10966c8d8eccSSepherosa Ziehau int i; 10976c8d8eccSSepherosa Ziehau 10986c8d8eccSSepherosa Ziehau /* Set endian type before we access any non-PCI registers. */ 10996c8d8eccSSepherosa Ziehau pci_write_config(sc->bnx_dev, BGE_PCI_MISC_CTL, 11006c8d8eccSSepherosa Ziehau BGE_INIT | BGE_PCIMISCCTL_TAGGED_STATUS, 4); 11016c8d8eccSSepherosa Ziehau 11026c8d8eccSSepherosa Ziehau /* 11036c8d8eccSSepherosa Ziehau * Clear the MAC statistics block in the NIC's 11046c8d8eccSSepherosa Ziehau * internal memory. 11056c8d8eccSSepherosa Ziehau */ 11066c8d8eccSSepherosa Ziehau for (i = BGE_STATS_BLOCK; 11076c8d8eccSSepherosa Ziehau i < BGE_STATS_BLOCK_END + 1; i += sizeof(uint32_t)) 11086c8d8eccSSepherosa Ziehau BNX_MEMWIN_WRITE(sc, i, 0); 11096c8d8eccSSepherosa Ziehau 11106c8d8eccSSepherosa Ziehau for (i = BGE_STATUS_BLOCK; 11116c8d8eccSSepherosa Ziehau i < BGE_STATUS_BLOCK_END + 1; i += sizeof(uint32_t)) 11126c8d8eccSSepherosa Ziehau BNX_MEMWIN_WRITE(sc, i, 0); 11136c8d8eccSSepherosa Ziehau 1114d7872545SSepherosa Ziehau if (BNX_IS_57765_FAMILY(sc)) { 1115d7872545SSepherosa Ziehau uint32_t val; 1116d7872545SSepherosa Ziehau 1117d7872545SSepherosa Ziehau if (sc->bnx_chipid == BGE_CHIPID_BCM57765_A0) { 1118d7872545SSepherosa Ziehau mode_ctl = CSR_READ_4(sc, BGE_MODE_CTL); 1119d7872545SSepherosa Ziehau val = mode_ctl & ~BGE_MODECTL_PCIE_PORTS; 1120d7872545SSepherosa Ziehau 1121d7872545SSepherosa Ziehau /* Access the lower 1K of PL PCI-E block registers. */ 1122d7872545SSepherosa Ziehau CSR_WRITE_4(sc, BGE_MODE_CTL, 1123d7872545SSepherosa Ziehau val | BGE_MODECTL_PCIE_PL_SEL); 1124d7872545SSepherosa Ziehau 1125d7872545SSepherosa Ziehau val = CSR_READ_4(sc, BGE_PCIE_PL_LO_PHYCTL5); 1126d7872545SSepherosa Ziehau val |= BGE_PCIE_PL_LO_PHYCTL5_DIS_L2CLKREQ; 1127d7872545SSepherosa Ziehau CSR_WRITE_4(sc, BGE_PCIE_PL_LO_PHYCTL5, val); 1128d7872545SSepherosa Ziehau 1129d7872545SSepherosa Ziehau CSR_WRITE_4(sc, BGE_MODE_CTL, mode_ctl); 1130d7872545SSepherosa Ziehau } 1131d7872545SSepherosa Ziehau if (sc->bnx_chiprev != BGE_CHIPREV_57765_AX) { 11321749651bSSepherosa Ziehau /* Fix transmit hangs */ 11331749651bSSepherosa Ziehau val = CSR_READ_4(sc, BGE_CPMU_PADRNG_CTL); 11341749651bSSepherosa Ziehau val |= BGE_CPMU_PADRNG_CTL_RDIV2; 11351749651bSSepherosa Ziehau CSR_WRITE_4(sc, BGE_CPMU_PADRNG_CTL, val); 11361749651bSSepherosa Ziehau 1137d7872545SSepherosa Ziehau mode_ctl = CSR_READ_4(sc, BGE_MODE_CTL); 1138d7872545SSepherosa Ziehau val = mode_ctl & ~BGE_MODECTL_PCIE_PORTS; 1139d7872545SSepherosa Ziehau 1140d7872545SSepherosa Ziehau /* Access the lower 1K of DL PCI-E block registers. */ 1141d7872545SSepherosa Ziehau CSR_WRITE_4(sc, BGE_MODE_CTL, 1142d7872545SSepherosa Ziehau val | BGE_MODECTL_PCIE_DL_SEL); 1143d7872545SSepherosa Ziehau 1144d7872545SSepherosa Ziehau val = CSR_READ_4(sc, BGE_PCIE_DL_LO_FTSMAX); 1145d7872545SSepherosa Ziehau val &= ~BGE_PCIE_DL_LO_FTSMAX_MASK; 1146d7872545SSepherosa Ziehau val |= BGE_PCIE_DL_LO_FTSMAX_VAL; 1147d7872545SSepherosa Ziehau CSR_WRITE_4(sc, BGE_PCIE_DL_LO_FTSMAX, val); 1148d7872545SSepherosa Ziehau 1149d7872545SSepherosa Ziehau CSR_WRITE_4(sc, BGE_MODE_CTL, mode_ctl); 1150d7872545SSepherosa Ziehau } 1151d7872545SSepherosa Ziehau 1152d7872545SSepherosa Ziehau val = CSR_READ_4(sc, BGE_CPMU_LSPD_10MB_CLK); 1153d7872545SSepherosa Ziehau val &= ~BGE_CPMU_LSPD_10MB_MACCLK_MASK; 1154d7872545SSepherosa Ziehau val |= BGE_CPMU_LSPD_10MB_MACCLK_6_25; 1155d7872545SSepherosa Ziehau CSR_WRITE_4(sc, BGE_CPMU_LSPD_10MB_CLK, val); 1156d7872545SSepherosa Ziehau } 1157d7872545SSepherosa Ziehau 11582890cca3SSepherosa Ziehau /* 11592890cca3SSepherosa Ziehau * Set up the PCI DMA control register. 11602890cca3SSepherosa Ziehau */ 11612890cca3SSepherosa Ziehau dma_rw_ctl = pci_read_config(sc->bnx_dev, BGE_PCI_DMA_RW_CTL, 4); 11622890cca3SSepherosa Ziehau /* 11632890cca3SSepherosa Ziehau * Disable 32bytes cache alignment for DMA write to host memory 11642890cca3SSepherosa Ziehau * 11652890cca3SSepherosa Ziehau * NOTE: 11662890cca3SSepherosa Ziehau * 64bytes cache alignment for DMA write to host memory is still 11672890cca3SSepherosa Ziehau * enabled. 11682890cca3SSepherosa Ziehau */ 11692890cca3SSepherosa Ziehau dma_rw_ctl |= BGE_PCIDMARWCTL_DIS_CACHE_ALIGNMENT; 11706c8d8eccSSepherosa Ziehau if (sc->bnx_chipid == BGE_CHIPID_BCM57765_A0) 11716c8d8eccSSepherosa Ziehau dma_rw_ctl &= ~BGE_PCIDMARWCTL_CRDRDR_RDMA_MRRS_MSK; 11726c8d8eccSSepherosa Ziehau /* 11736c8d8eccSSepherosa Ziehau * Enable HW workaround for controllers that misinterpret 11746c8d8eccSSepherosa Ziehau * a status tag update and leave interrupts permanently 11756c8d8eccSSepherosa Ziehau * disabled. 11766c8d8eccSSepherosa Ziehau */ 11776c8d8eccSSepherosa Ziehau if (sc->bnx_asicrev != BGE_ASICREV_BCM5717 && 1178b96cbbb6SSepherosa Ziehau sc->bnx_asicrev != BGE_ASICREV_BCM5762 && 11792890cca3SSepherosa Ziehau !BNX_IS_57765_FAMILY(sc)) 11806c8d8eccSSepherosa Ziehau dma_rw_ctl |= BGE_PCIDMARWCTL_TAGGED_STATUS_WA; 11812890cca3SSepherosa Ziehau if (bootverbose) { 11822890cca3SSepherosa Ziehau if_printf(&sc->arpcom.ac_if, "DMA read/write %#x\n", 11832890cca3SSepherosa Ziehau dma_rw_ctl); 11846c8d8eccSSepherosa Ziehau } 11856c8d8eccSSepherosa Ziehau pci_write_config(sc->bnx_dev, BGE_PCI_DMA_RW_CTL, dma_rw_ctl, 4); 11866c8d8eccSSepherosa Ziehau 11876c8d8eccSSepherosa Ziehau /* 11886c8d8eccSSepherosa Ziehau * Set up general mode register. 11896c8d8eccSSepherosa Ziehau */ 11909f5082d5SSepherosa Ziehau mode_ctl = bnx_dma_swap_options(sc); 11919f5082d5SSepherosa Ziehau if (sc->bnx_asicrev == BGE_ASICREV_BCM5720 || 11929f5082d5SSepherosa Ziehau sc->bnx_asicrev == BGE_ASICREV_BCM5762) { 11939f5082d5SSepherosa Ziehau /* Retain Host-2-BMC settings written by APE firmware. */ 11949f5082d5SSepherosa Ziehau mode_ctl |= CSR_READ_4(sc, BGE_MODE_CTL) & 11959f5082d5SSepherosa Ziehau (BGE_MODECTL_BYTESWAP_B2HRX_DATA | 11969f5082d5SSepherosa Ziehau BGE_MODECTL_WORDSWAP_B2HRX_DATA | 11979f5082d5SSepherosa Ziehau BGE_MODECTL_B2HRX_ENABLE | BGE_MODECTL_HTX2B_ENABLE); 11989f5082d5SSepherosa Ziehau } 11999f5082d5SSepherosa Ziehau mode_ctl |= BGE_MODECTL_MAC_ATTN_INTR | 12006c8d8eccSSepherosa Ziehau BGE_MODECTL_HOST_SEND_BDS | BGE_MODECTL_TX_NO_PHDR_CSUM; 12016c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_MODE_CTL, mode_ctl); 12026c8d8eccSSepherosa Ziehau 12036c8d8eccSSepherosa Ziehau /* 12046c8d8eccSSepherosa Ziehau * Disable memory write invalidate. Apparently it is not supported 12056c8d8eccSSepherosa Ziehau * properly by these devices. Also ensure that INTx isn't disabled, 12066c8d8eccSSepherosa Ziehau * as these chips need it even when using MSI. 12076c8d8eccSSepherosa Ziehau */ 12086c8d8eccSSepherosa Ziehau PCI_CLRBIT(sc->bnx_dev, BGE_PCI_CMD, 12096c8d8eccSSepherosa Ziehau (PCIM_CMD_MWRICEN | PCIM_CMD_INTxDIS), 4); 12106c8d8eccSSepherosa Ziehau 12116c8d8eccSSepherosa Ziehau /* Set the timer prescaler (always 66Mhz) */ 12126c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_MISC_CFG, 65 << 1/*BGE_32BITTIME_66MHZ*/); 12136c8d8eccSSepherosa Ziehau 12146c8d8eccSSepherosa Ziehau return(0); 12156c8d8eccSSepherosa Ziehau } 12166c8d8eccSSepherosa Ziehau 12176c8d8eccSSepherosa Ziehau static int 12186c8d8eccSSepherosa Ziehau bnx_blockinit(struct bnx_softc *sc) 12196c8d8eccSSepherosa Ziehau { 1220695a8586SSepherosa Ziehau struct bnx_intr_data *intr; 12216c8d8eccSSepherosa Ziehau struct bge_rcb *rcb; 12226c8d8eccSSepherosa Ziehau bus_size_t vrcb; 12236c8d8eccSSepherosa Ziehau bge_hostaddr taddr; 12246c8d8eccSSepherosa Ziehau uint32_t val; 12256c8d8eccSSepherosa Ziehau int i, limit; 12266c8d8eccSSepherosa Ziehau 12276c8d8eccSSepherosa Ziehau /* 12286c8d8eccSSepherosa Ziehau * Initialize the memory window pointer register so that 12296c8d8eccSSepherosa Ziehau * we can access the first 32K of internal NIC RAM. This will 12306c8d8eccSSepherosa Ziehau * allow us to set up the TX send ring RCBs and the RX return 12316c8d8eccSSepherosa Ziehau * ring RCBs, plus other things which live in NIC memory. 12326c8d8eccSSepherosa Ziehau */ 12336c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_PCI_MEMWIN_BASEADDR, 0); 12346c8d8eccSSepherosa Ziehau 12356c8d8eccSSepherosa Ziehau /* Configure mbuf pool watermarks */ 1236f368d0d9SSepherosa Ziehau if (BNX_IS_57765_PLUS(sc)) { 12376c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_BMAN_MBUFPOOL_READDMA_LOWAT, 0x0); 12386c8d8eccSSepherosa Ziehau if (sc->arpcom.ac_if.if_mtu > ETHERMTU) { 12396c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_BMAN_MBUFPOOL_MACRX_LOWAT, 0x7e); 12406c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_BMAN_MBUFPOOL_HIWAT, 0xea); 12416c8d8eccSSepherosa Ziehau } else { 12426c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_BMAN_MBUFPOOL_MACRX_LOWAT, 0x2a); 12436c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_BMAN_MBUFPOOL_HIWAT, 0xa0); 12446c8d8eccSSepherosa Ziehau } 12456c8d8eccSSepherosa Ziehau } else { 12466c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_BMAN_MBUFPOOL_READDMA_LOWAT, 0x0); 12476c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_BMAN_MBUFPOOL_MACRX_LOWAT, 0x10); 12486c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_BMAN_MBUFPOOL_HIWAT, 0x60); 12496c8d8eccSSepherosa Ziehau } 12506c8d8eccSSepherosa Ziehau 12516c8d8eccSSepherosa Ziehau /* Configure DMA resource watermarks */ 12526c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_BMAN_DMA_DESCPOOL_LOWAT, 5); 12536c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_BMAN_DMA_DESCPOOL_HIWAT, 10); 12546c8d8eccSSepherosa Ziehau 12556c8d8eccSSepherosa Ziehau /* Enable buffer manager */ 12566c8d8eccSSepherosa Ziehau val = BGE_BMANMODE_ENABLE | BGE_BMANMODE_LOMBUF_ATTN; 12576c8d8eccSSepherosa Ziehau /* 12586c8d8eccSSepherosa Ziehau * Change the arbitration algorithm of TXMBUF read request to 12596c8d8eccSSepherosa Ziehau * round-robin instead of priority based for BCM5719. When 12606c8d8eccSSepherosa Ziehau * TXFIFO is almost empty, RDMA will hold its request until 12616c8d8eccSSepherosa Ziehau * TXFIFO is not almost empty. 12626c8d8eccSSepherosa Ziehau */ 12636c8d8eccSSepherosa Ziehau if (sc->bnx_asicrev == BGE_ASICREV_BCM5719) 12646c8d8eccSSepherosa Ziehau val |= BGE_BMANMODE_NO_TX_UNDERRUN; 1265e5eebe34SSepherosa Ziehau if (sc->bnx_asicrev == BGE_ASICREV_BCM5717 || 1266e5eebe34SSepherosa Ziehau sc->bnx_chipid == BGE_CHIPID_BCM5719_A0 || 1267e5eebe34SSepherosa Ziehau sc->bnx_chipid == BGE_CHIPID_BCM5720_A0) 1268e5eebe34SSepherosa Ziehau val |= BGE_BMANMODE_LOMBUF_ATTN; 12696c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_BMAN_MODE, val); 12706c8d8eccSSepherosa Ziehau 12716c8d8eccSSepherosa Ziehau /* Poll for buffer manager start indication */ 12726c8d8eccSSepherosa Ziehau for (i = 0; i < BNX_TIMEOUT; i++) { 12736c8d8eccSSepherosa Ziehau if (CSR_READ_4(sc, BGE_BMAN_MODE) & BGE_BMANMODE_ENABLE) 12746c8d8eccSSepherosa Ziehau break; 12756c8d8eccSSepherosa Ziehau DELAY(10); 12766c8d8eccSSepherosa Ziehau } 12776c8d8eccSSepherosa Ziehau 12786c8d8eccSSepherosa Ziehau if (i == BNX_TIMEOUT) { 12796c8d8eccSSepherosa Ziehau if_printf(&sc->arpcom.ac_if, 12806c8d8eccSSepherosa Ziehau "buffer manager failed to start\n"); 12816c8d8eccSSepherosa Ziehau return(ENXIO); 12826c8d8eccSSepherosa Ziehau } 12836c8d8eccSSepherosa Ziehau 12846c8d8eccSSepherosa Ziehau /* Enable flow-through queues */ 12856c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_FTQ_RESET, 0xFFFFFFFF); 12866c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_FTQ_RESET, 0); 12876c8d8eccSSepherosa Ziehau 12886c8d8eccSSepherosa Ziehau /* Wait until queue initialization is complete */ 12896c8d8eccSSepherosa Ziehau for (i = 0; i < BNX_TIMEOUT; i++) { 12906c8d8eccSSepherosa Ziehau if (CSR_READ_4(sc, BGE_FTQ_RESET) == 0) 12916c8d8eccSSepherosa Ziehau break; 12926c8d8eccSSepherosa Ziehau DELAY(10); 12936c8d8eccSSepherosa Ziehau } 12946c8d8eccSSepherosa Ziehau 12956c8d8eccSSepherosa Ziehau if (i == BNX_TIMEOUT) { 12966c8d8eccSSepherosa Ziehau if_printf(&sc->arpcom.ac_if, 12976c8d8eccSSepherosa Ziehau "flow-through queue init failed\n"); 12986c8d8eccSSepherosa Ziehau return(ENXIO); 12996c8d8eccSSepherosa Ziehau } 13006c8d8eccSSepherosa Ziehau 13016c8d8eccSSepherosa Ziehau /* 13026c8d8eccSSepherosa Ziehau * Summary of rings supported by the controller: 13036c8d8eccSSepherosa Ziehau * 13046c8d8eccSSepherosa Ziehau * Standard Receive Producer Ring 13056c8d8eccSSepherosa Ziehau * - This ring is used to feed receive buffers for "standard" 13066c8d8eccSSepherosa Ziehau * sized frames (typically 1536 bytes) to the controller. 13076c8d8eccSSepherosa Ziehau * 13086c8d8eccSSepherosa Ziehau * Jumbo Receive Producer Ring 13096c8d8eccSSepherosa Ziehau * - This ring is used to feed receive buffers for jumbo sized 13106c8d8eccSSepherosa Ziehau * frames (i.e. anything bigger than the "standard" frames) 13116c8d8eccSSepherosa Ziehau * to the controller. 13126c8d8eccSSepherosa Ziehau * 13136c8d8eccSSepherosa Ziehau * Mini Receive Producer Ring 13146c8d8eccSSepherosa Ziehau * - This ring is used to feed receive buffers for "mini" 13156c8d8eccSSepherosa Ziehau * sized frames to the controller. 13166c8d8eccSSepherosa Ziehau * - This feature required external memory for the controller 13176c8d8eccSSepherosa Ziehau * but was never used in a production system. Should always 13186c8d8eccSSepherosa Ziehau * be disabled. 13196c8d8eccSSepherosa Ziehau * 13206c8d8eccSSepherosa Ziehau * Receive Return Ring 13216c8d8eccSSepherosa Ziehau * - After the controller has placed an incoming frame into a 13226c8d8eccSSepherosa Ziehau * receive buffer that buffer is moved into a receive return 13236c8d8eccSSepherosa Ziehau * ring. The driver is then responsible to passing the 13242a581495SSepherosa Ziehau * buffer up to the stack. BCM5718/BCM57785 families support 13252a581495SSepherosa Ziehau * multiple receive return rings. 13266c8d8eccSSepherosa Ziehau * 13276c8d8eccSSepherosa Ziehau * Send Ring 13282a581495SSepherosa Ziehau * - This ring is used for outgoing frames. BCM5719/BCM5720 13292a581495SSepherosa Ziehau * support multiple send rings. 13306c8d8eccSSepherosa Ziehau */ 13316c8d8eccSSepherosa Ziehau 13326c8d8eccSSepherosa Ziehau /* Initialize the standard receive producer ring control block. */ 13336c8d8eccSSepherosa Ziehau rcb = &sc->bnx_ldata.bnx_info.bnx_std_rx_rcb; 13346c8d8eccSSepherosa Ziehau rcb->bge_hostaddr.bge_addr_lo = 1335beedf5beSSepherosa Ziehau BGE_ADDR_LO(sc->bnx_rx_std_ring.bnx_rx_std_ring_paddr); 13366c8d8eccSSepherosa Ziehau rcb->bge_hostaddr.bge_addr_hi = 1337beedf5beSSepherosa Ziehau BGE_ADDR_HI(sc->bnx_rx_std_ring.bnx_rx_std_ring_paddr); 1338f368d0d9SSepherosa Ziehau if (BNX_IS_57765_PLUS(sc)) { 13396c8d8eccSSepherosa Ziehau /* 13406c8d8eccSSepherosa Ziehau * Bits 31-16: Programmable ring size (2048, 1024, 512, .., 32) 13416c8d8eccSSepherosa Ziehau * Bits 15-2 : Maximum RX frame size 13426c8d8eccSSepherosa Ziehau * Bit 1 : 1 = Ring Disabled, 0 = Ring ENabled 13436c8d8eccSSepherosa Ziehau * Bit 0 : Reserved 13446c8d8eccSSepherosa Ziehau */ 13456c8d8eccSSepherosa Ziehau rcb->bge_maxlen_flags = 13466c8d8eccSSepherosa Ziehau BGE_RCB_MAXLEN_FLAGS(512, BNX_MAX_FRAMELEN << 2); 13476c8d8eccSSepherosa Ziehau } else { 13486c8d8eccSSepherosa Ziehau /* 13496c8d8eccSSepherosa Ziehau * Bits 31-16: Programmable ring size (512, 256, 128, 64, 32) 13506c8d8eccSSepherosa Ziehau * Bits 15-2 : Reserved (should be 0) 13516c8d8eccSSepherosa Ziehau * Bit 1 : 1 = Ring Disabled, 0 = Ring Enabled 13526c8d8eccSSepherosa Ziehau * Bit 0 : Reserved 13536c8d8eccSSepherosa Ziehau */ 13546c8d8eccSSepherosa Ziehau rcb->bge_maxlen_flags = BGE_RCB_MAXLEN_FLAGS(512, 0); 13556c8d8eccSSepherosa Ziehau } 1356303fdc72SSepherosa Ziehau if (BNX_IS_5717_PLUS(sc)) 13576c8d8eccSSepherosa Ziehau rcb->bge_nicaddr = BGE_STD_RX_RINGS_5717; 13586c8d8eccSSepherosa Ziehau else 13596c8d8eccSSepherosa Ziehau rcb->bge_nicaddr = BGE_STD_RX_RINGS; 13606c8d8eccSSepherosa Ziehau /* Write the standard receive producer ring control block. */ 13616c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_RX_STD_RCB_HADDR_HI, rcb->bge_hostaddr.bge_addr_hi); 13626c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_RX_STD_RCB_HADDR_LO, rcb->bge_hostaddr.bge_addr_lo); 13636c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_RX_STD_RCB_MAXLEN_FLAGS, rcb->bge_maxlen_flags); 1364695a8586SSepherosa Ziehau if (!BNX_IS_5717_PLUS(sc)) 13656c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_RX_STD_RCB_NICADDR, rcb->bge_nicaddr); 13666c8d8eccSSepherosa Ziehau /* Reset the standard receive producer ring producer index. */ 13676c8d8eccSSepherosa Ziehau bnx_writembx(sc, BGE_MBX_RX_STD_PROD_LO, 0); 13686c8d8eccSSepherosa Ziehau 13696c8d8eccSSepherosa Ziehau /* 13706c8d8eccSSepherosa Ziehau * Initialize the jumbo RX producer ring control 13716c8d8eccSSepherosa Ziehau * block. We set the 'ring disabled' bit in the 13726c8d8eccSSepherosa Ziehau * flags field until we're actually ready to start 13736c8d8eccSSepherosa Ziehau * using this ring (i.e. once we set the MTU 13746c8d8eccSSepherosa Ziehau * high enough to require it). 13756c8d8eccSSepherosa Ziehau */ 13766c8d8eccSSepherosa Ziehau if (BNX_IS_JUMBO_CAPABLE(sc)) { 13776c8d8eccSSepherosa Ziehau rcb = &sc->bnx_ldata.bnx_info.bnx_jumbo_rx_rcb; 13786c8d8eccSSepherosa Ziehau /* Get the jumbo receive producer ring RCB parameters. */ 13796c8d8eccSSepherosa Ziehau rcb->bge_hostaddr.bge_addr_lo = 13806c8d8eccSSepherosa Ziehau BGE_ADDR_LO(sc->bnx_ldata.bnx_rx_jumbo_ring_paddr); 13816c8d8eccSSepherosa Ziehau rcb->bge_hostaddr.bge_addr_hi = 13826c8d8eccSSepherosa Ziehau BGE_ADDR_HI(sc->bnx_ldata.bnx_rx_jumbo_ring_paddr); 13836c8d8eccSSepherosa Ziehau rcb->bge_maxlen_flags = 13846c8d8eccSSepherosa Ziehau BGE_RCB_MAXLEN_FLAGS(BNX_MAX_FRAMELEN, 13856c8d8eccSSepherosa Ziehau BGE_RCB_FLAG_RING_DISABLED); 1386303fdc72SSepherosa Ziehau if (BNX_IS_5717_PLUS(sc)) 13876c8d8eccSSepherosa Ziehau rcb->bge_nicaddr = BGE_JUMBO_RX_RINGS_5717; 13886c8d8eccSSepherosa Ziehau else 13896c8d8eccSSepherosa Ziehau rcb->bge_nicaddr = BGE_JUMBO_RX_RINGS; 13906c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_RX_JUMBO_RCB_HADDR_HI, 13916c8d8eccSSepherosa Ziehau rcb->bge_hostaddr.bge_addr_hi); 13926c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_RX_JUMBO_RCB_HADDR_LO, 13936c8d8eccSSepherosa Ziehau rcb->bge_hostaddr.bge_addr_lo); 13946c8d8eccSSepherosa Ziehau /* Program the jumbo receive producer ring RCB parameters. */ 13956c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_RX_JUMBO_RCB_MAXLEN_FLAGS, 13966c8d8eccSSepherosa Ziehau rcb->bge_maxlen_flags); 13976c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_RX_JUMBO_RCB_NICADDR, rcb->bge_nicaddr); 13986c8d8eccSSepherosa Ziehau /* Reset the jumbo receive producer ring producer index. */ 13996c8d8eccSSepherosa Ziehau bnx_writembx(sc, BGE_MBX_RX_JUMBO_PROD_LO, 0); 14006c8d8eccSSepherosa Ziehau } 14016c8d8eccSSepherosa Ziehau 14026c8d8eccSSepherosa Ziehau /* 14036c8d8eccSSepherosa Ziehau * The BD ring replenish thresholds control how often the 14046c8d8eccSSepherosa Ziehau * hardware fetches new BD's from the producer rings in host 14056c8d8eccSSepherosa Ziehau * memory. Setting the value too low on a busy system can 14066c8d8eccSSepherosa Ziehau * starve the hardware and recue the throughpout. 14076c8d8eccSSepherosa Ziehau * 14086c8d8eccSSepherosa Ziehau * Set the BD ring replentish thresholds. The recommended 14096c8d8eccSSepherosa Ziehau * values are 1/8th the number of descriptors allocated to 14106c8d8eccSSepherosa Ziehau * each ring. 14116c8d8eccSSepherosa Ziehau */ 14126c8d8eccSSepherosa Ziehau val = 8; 14136c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_RBDI_STD_REPL_THRESH, val); 14146c8d8eccSSepherosa Ziehau if (BNX_IS_JUMBO_CAPABLE(sc)) { 14156c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_RBDI_JUMBO_REPL_THRESH, 14166c8d8eccSSepherosa Ziehau BGE_JUMBO_RX_RING_CNT/8); 14176c8d8eccSSepherosa Ziehau } 1418f368d0d9SSepherosa Ziehau if (BNX_IS_57765_PLUS(sc)) { 14196c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_STD_REPLENISH_LWM, 32); 14206c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_JMB_REPLENISH_LWM, 16); 14216c8d8eccSSepherosa Ziehau } 14226c8d8eccSSepherosa Ziehau 14236c8d8eccSSepherosa Ziehau /* 14246c8d8eccSSepherosa Ziehau * Disable all send rings by setting the 'ring disabled' bit 14256c8d8eccSSepherosa Ziehau * in the flags field of all the TX send ring control blocks, 14266c8d8eccSSepherosa Ziehau * located in NIC memory. 14276c8d8eccSSepherosa Ziehau */ 142880969639SSepherosa Ziehau if (BNX_IS_5717_PLUS(sc)) 142980969639SSepherosa Ziehau limit = 4; 1430b96cbbb6SSepherosa Ziehau else if (BNX_IS_57765_FAMILY(sc) || 1431b96cbbb6SSepherosa Ziehau sc->bnx_asicrev == BGE_ASICREV_BCM5762) 14324f23029eSSepherosa Ziehau limit = 2; 143380969639SSepherosa Ziehau else 14346c8d8eccSSepherosa Ziehau limit = 1; 14356c8d8eccSSepherosa Ziehau vrcb = BGE_MEMWIN_START + BGE_SEND_RING_RCB; 14366c8d8eccSSepherosa Ziehau for (i = 0; i < limit; i++) { 14376c8d8eccSSepherosa Ziehau RCB_WRITE_4(sc, vrcb, bge_maxlen_flags, 14386c8d8eccSSepherosa Ziehau BGE_RCB_MAXLEN_FLAGS(0, BGE_RCB_FLAG_RING_DISABLED)); 14396c8d8eccSSepherosa Ziehau vrcb += sizeof(struct bge_rcb); 14406c8d8eccSSepherosa Ziehau } 14416c8d8eccSSepherosa Ziehau 1442695a8586SSepherosa Ziehau /* 1443695a8586SSepherosa Ziehau * Configure send ring RCBs 1444695a8586SSepherosa Ziehau */ 14456c8d8eccSSepherosa Ziehau vrcb = BGE_MEMWIN_START + BGE_SEND_RING_RCB; 1446695a8586SSepherosa Ziehau for (i = 0; i < sc->bnx_tx_ringcnt; ++i) { 1447695a8586SSepherosa Ziehau struct bnx_tx_ring *txr = &sc->bnx_tx_ring[i]; 1448695a8586SSepherosa Ziehau 144933a04907SSepherosa Ziehau BGE_HOSTADDR(taddr, txr->bnx_tx_ring_paddr); 1450695a8586SSepherosa Ziehau RCB_WRITE_4(sc, vrcb, bge_hostaddr.bge_addr_hi, 1451695a8586SSepherosa Ziehau taddr.bge_addr_hi); 1452695a8586SSepherosa Ziehau RCB_WRITE_4(sc, vrcb, bge_hostaddr.bge_addr_lo, 1453695a8586SSepherosa Ziehau taddr.bge_addr_lo); 14546c8d8eccSSepherosa Ziehau RCB_WRITE_4(sc, vrcb, bge_maxlen_flags, 14556c8d8eccSSepherosa Ziehau BGE_RCB_MAXLEN_FLAGS(BGE_TX_RING_CNT, 0)); 1456695a8586SSepherosa Ziehau vrcb += sizeof(struct bge_rcb); 1457695a8586SSepherosa Ziehau } 14586c8d8eccSSepherosa Ziehau 14596c8d8eccSSepherosa Ziehau /* 14606c8d8eccSSepherosa Ziehau * Disable all receive return rings by setting the 14616c8d8eccSSepherosa Ziehau * 'ring disabled' bit in the flags field of all the receive 14626c8d8eccSSepherosa Ziehau * return ring control blocks, located in NIC memory. 14636c8d8eccSSepherosa Ziehau */ 146480969639SSepherosa Ziehau if (BNX_IS_5717_PLUS(sc)) { 14656c8d8eccSSepherosa Ziehau /* Should be 17, use 16 until we get an SRAM map. */ 14666c8d8eccSSepherosa Ziehau limit = 16; 1467b96cbbb6SSepherosa Ziehau } else if (BNX_IS_57765_FAMILY(sc) || 1468b96cbbb6SSepherosa Ziehau sc->bnx_asicrev == BGE_ASICREV_BCM5762) { 14696c8d8eccSSepherosa Ziehau limit = 4; 14706c8d8eccSSepherosa Ziehau } else { 14716c8d8eccSSepherosa Ziehau limit = 1; 14726c8d8eccSSepherosa Ziehau } 14736c8d8eccSSepherosa Ziehau /* Disable all receive return rings. */ 14746c8d8eccSSepherosa Ziehau vrcb = BGE_MEMWIN_START + BGE_RX_RETURN_RING_RCB; 14756c8d8eccSSepherosa Ziehau for (i = 0; i < limit; i++) { 14766c8d8eccSSepherosa Ziehau RCB_WRITE_4(sc, vrcb, bge_hostaddr.bge_addr_hi, 0); 14776c8d8eccSSepherosa Ziehau RCB_WRITE_4(sc, vrcb, bge_hostaddr.bge_addr_lo, 0); 14786c8d8eccSSepherosa Ziehau RCB_WRITE_4(sc, vrcb, bge_maxlen_flags, 14796c8d8eccSSepherosa Ziehau BGE_RCB_FLAG_RING_DISABLED); 14806c8d8eccSSepherosa Ziehau bnx_writembx(sc, BGE_MBX_RX_CONS0_LO + 14816c8d8eccSSepherosa Ziehau (i * (sizeof(uint64_t))), 0); 14826c8d8eccSSepherosa Ziehau vrcb += sizeof(struct bge_rcb); 14836c8d8eccSSepherosa Ziehau } 14846c8d8eccSSepherosa Ziehau 14856c8d8eccSSepherosa Ziehau /* 14862a581495SSepherosa Ziehau * Set up receive return rings. 14876c8d8eccSSepherosa Ziehau */ 14886c8d8eccSSepherosa Ziehau vrcb = BGE_MEMWIN_START + BGE_RX_RETURN_RING_RCB; 1489695a8586SSepherosa Ziehau for (i = 0; i < sc->bnx_rx_retcnt; ++i) { 1490695a8586SSepherosa Ziehau struct bnx_rx_ret_ring *ret = &sc->bnx_rx_ret_ring[i]; 1491695a8586SSepherosa Ziehau 1492beedf5beSSepherosa Ziehau BGE_HOSTADDR(taddr, ret->bnx_rx_ret_ring_paddr); 1493695a8586SSepherosa Ziehau RCB_WRITE_4(sc, vrcb, bge_hostaddr.bge_addr_hi, 1494695a8586SSepherosa Ziehau taddr.bge_addr_hi); 1495695a8586SSepherosa Ziehau RCB_WRITE_4(sc, vrcb, bge_hostaddr.bge_addr_lo, 1496695a8586SSepherosa Ziehau taddr.bge_addr_lo); 14976c8d8eccSSepherosa Ziehau RCB_WRITE_4(sc, vrcb, bge_maxlen_flags, 1498e0f74fc8SSepherosa Ziehau BGE_RCB_MAXLEN_FLAGS(BNX_RETURN_RING_CNT, 0)); 1499695a8586SSepherosa Ziehau vrcb += sizeof(struct bge_rcb); 1500695a8586SSepherosa Ziehau } 15016c8d8eccSSepherosa Ziehau 15026c8d8eccSSepherosa Ziehau /* Set random backoff seed for TX */ 15036c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_TX_RANDOM_BACKOFF, 15044aa71e73SSepherosa Ziehau (sc->arpcom.ac_enaddr[0] + sc->arpcom.ac_enaddr[1] + 15056c8d8eccSSepherosa Ziehau sc->arpcom.ac_enaddr[2] + sc->arpcom.ac_enaddr[3] + 15064aa71e73SSepherosa Ziehau sc->arpcom.ac_enaddr[4] + sc->arpcom.ac_enaddr[5]) & 15076c8d8eccSSepherosa Ziehau BGE_TX_BACKOFF_SEED_MASK); 15086c8d8eccSSepherosa Ziehau 15096c8d8eccSSepherosa Ziehau /* Set inter-packet gap */ 15106c8d8eccSSepherosa Ziehau val = 0x2620; 1511b96cbbb6SSepherosa Ziehau if (sc->bnx_asicrev == BGE_ASICREV_BCM5720 || 1512b96cbbb6SSepherosa Ziehau sc->bnx_asicrev == BGE_ASICREV_BCM5762) { 15136c8d8eccSSepherosa Ziehau val |= CSR_READ_4(sc, BGE_TX_LENGTHS) & 15146c8d8eccSSepherosa Ziehau (BGE_TXLEN_JMB_FRM_LEN_MSK | BGE_TXLEN_CNT_DN_VAL_MSK); 15156c8d8eccSSepherosa Ziehau } 15166c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_TX_LENGTHS, val); 15176c8d8eccSSepherosa Ziehau 15186c8d8eccSSepherosa Ziehau /* 15196c8d8eccSSepherosa Ziehau * Specify which ring to use for packets that don't match 15206c8d8eccSSepherosa Ziehau * any RX rules. 15216c8d8eccSSepherosa Ziehau */ 15226c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_RX_RULES_CFG, 0x08); 15236c8d8eccSSepherosa Ziehau 15246c8d8eccSSepherosa Ziehau /* 15256c8d8eccSSepherosa Ziehau * Configure number of RX lists. One interrupt distribution 15266c8d8eccSSepherosa Ziehau * list, sixteen active lists, one bad frames class. 15276c8d8eccSSepherosa Ziehau */ 15286c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_RXLP_CFG, 0x181); 15296c8d8eccSSepherosa Ziehau 15306c8d8eccSSepherosa Ziehau /* Inialize RX list placement stats mask. */ 15316c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_RXLP_STATS_ENABLE_MASK, 0x007FFFFF); 15326c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_RXLP_STATS_CTL, 0x1); 15336c8d8eccSSepherosa Ziehau 15346c8d8eccSSepherosa Ziehau /* Disable host coalescing until we get it set up */ 15356c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_HCC_MODE, 0x00000000); 15366c8d8eccSSepherosa Ziehau 15376c8d8eccSSepherosa Ziehau /* Poll to make sure it's shut down. */ 15386c8d8eccSSepherosa Ziehau for (i = 0; i < BNX_TIMEOUT; i++) { 15396c8d8eccSSepherosa Ziehau if (!(CSR_READ_4(sc, BGE_HCC_MODE) & BGE_HCCMODE_ENABLE)) 15406c8d8eccSSepherosa Ziehau break; 15416c8d8eccSSepherosa Ziehau DELAY(10); 15426c8d8eccSSepherosa Ziehau } 15436c8d8eccSSepherosa Ziehau 15446c8d8eccSSepherosa Ziehau if (i == BNX_TIMEOUT) { 15456c8d8eccSSepherosa Ziehau if_printf(&sc->arpcom.ac_if, 15466c8d8eccSSepherosa Ziehau "host coalescing engine failed to idle\n"); 15476c8d8eccSSepherosa Ziehau return(ENXIO); 15486c8d8eccSSepherosa Ziehau } 15496c8d8eccSSepherosa Ziehau 15506c8d8eccSSepherosa Ziehau /* Set up host coalescing defaults */ 1551695a8586SSepherosa Ziehau sc->bnx_coal_chg = BNX_RX_COAL_TICKS_CHG | 1552695a8586SSepherosa Ziehau BNX_TX_COAL_TICKS_CHG | 1553695a8586SSepherosa Ziehau BNX_RX_COAL_BDS_CHG | 1554695a8586SSepherosa Ziehau BNX_TX_COAL_BDS_CHG | 1555695a8586SSepherosa Ziehau BNX_RX_COAL_BDS_INT_CHG | 1556695a8586SSepherosa Ziehau BNX_TX_COAL_BDS_INT_CHG; 1557695a8586SSepherosa Ziehau bnx_coal_change(sc); 15586c8d8eccSSepherosa Ziehau 1559695a8586SSepherosa Ziehau /* 1560695a8586SSepherosa Ziehau * Set up addresses of status blocks 1561695a8586SSepherosa Ziehau */ 1562695a8586SSepherosa Ziehau intr = &sc->bnx_intr_data[0]; 15630a806e3aSSepherosa Ziehau bzero(intr->bnx_status_block, BGE_STATUS_BLK_SZ); 15646c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_HCC_STATUSBLK_ADDR_HI, 15650a806e3aSSepherosa Ziehau BGE_ADDR_HI(intr->bnx_status_block_paddr)); 15666c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_HCC_STATUSBLK_ADDR_LO, 15670a806e3aSSepherosa Ziehau BGE_ADDR_LO(intr->bnx_status_block_paddr)); 1568695a8586SSepherosa Ziehau for (i = 1; i < sc->bnx_intr_cnt; ++i) { 1569695a8586SSepherosa Ziehau intr = &sc->bnx_intr_data[i]; 1570695a8586SSepherosa Ziehau bzero(intr->bnx_status_block, BGE_STATUS_BLK_SZ); 1571695a8586SSepherosa Ziehau CSR_WRITE_4(sc, BGE_VEC1_STATUSBLK_ADDR_HI + ((i - 1) * 8), 1572695a8586SSepherosa Ziehau BGE_ADDR_HI(intr->bnx_status_block_paddr)); 1573695a8586SSepherosa Ziehau CSR_WRITE_4(sc, BGE_VEC1_STATUSBLK_ADDR_LO + ((i - 1) * 8), 1574695a8586SSepherosa Ziehau BGE_ADDR_LO(intr->bnx_status_block_paddr)); 1575695a8586SSepherosa Ziehau } 15766c8d8eccSSepherosa Ziehau 15776c8d8eccSSepherosa Ziehau /* Set up status block partail update size. */ 15786c8d8eccSSepherosa Ziehau val = BGE_STATBLKSZ_32BYTE; 15796c8d8eccSSepherosa Ziehau #if 0 15806c8d8eccSSepherosa Ziehau /* 15816c8d8eccSSepherosa Ziehau * Does not seem to have visible effect in both 15826c8d8eccSSepherosa Ziehau * bulk data (1472B UDP datagram) and tiny data 15836c8d8eccSSepherosa Ziehau * (18B UDP datagram) TX tests. 15846c8d8eccSSepherosa Ziehau */ 15856c8d8eccSSepherosa Ziehau val |= BGE_HCCMODE_CLRTICK_TX; 15866c8d8eccSSepherosa Ziehau #endif 15876c8d8eccSSepherosa Ziehau /* Turn on host coalescing state machine */ 15886c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_HCC_MODE, val | BGE_HCCMODE_ENABLE); 15896c8d8eccSSepherosa Ziehau 15906c8d8eccSSepherosa Ziehau /* Turn on RX BD completion state machine and enable attentions */ 15916c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_RBDC_MODE, 15926c8d8eccSSepherosa Ziehau BGE_RBDCMODE_ENABLE|BGE_RBDCMODE_ATTN); 15936c8d8eccSSepherosa Ziehau 15946c8d8eccSSepherosa Ziehau /* Turn on RX list placement state machine */ 15956c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_RXLP_MODE, BGE_RXLPMODE_ENABLE); 15966c8d8eccSSepherosa Ziehau 15976c8d8eccSSepherosa Ziehau val = BGE_MACMODE_TXDMA_ENB | BGE_MACMODE_RXDMA_ENB | 15986c8d8eccSSepherosa Ziehau BGE_MACMODE_RX_STATS_CLEAR | BGE_MACMODE_TX_STATS_CLEAR | 15996c8d8eccSSepherosa Ziehau BGE_MACMODE_RX_STATS_ENB | BGE_MACMODE_TX_STATS_ENB | 16006c8d8eccSSepherosa Ziehau BGE_MACMODE_FRMHDR_DMA_ENB; 16016c8d8eccSSepherosa Ziehau 16026c8d8eccSSepherosa Ziehau if (sc->bnx_flags & BNX_FLAG_TBI) 16036c8d8eccSSepherosa Ziehau val |= BGE_PORTMODE_TBI; 16046c8d8eccSSepherosa Ziehau else if (sc->bnx_flags & BNX_FLAG_MII_SERDES) 16056c8d8eccSSepherosa Ziehau val |= BGE_PORTMODE_GMII; 16066c8d8eccSSepherosa Ziehau else 16076c8d8eccSSepherosa Ziehau val |= BGE_PORTMODE_MII; 16086c8d8eccSSepherosa Ziehau 16099f5082d5SSepherosa Ziehau /* Allow APE to send/receive frames. */ 16109f5082d5SSepherosa Ziehau if (sc->bnx_mfw_flags & BNX_MFW_ON_APE) 16119f5082d5SSepherosa Ziehau val |= BGE_MACMODE_APE_RX_EN | BGE_MACMODE_APE_TX_EN; 16129f5082d5SSepherosa Ziehau 16136c8d8eccSSepherosa Ziehau /* Turn on DMA, clear stats */ 16146c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_MAC_MODE, val); 16154aa71e73SSepherosa Ziehau DELAY(40); 16166c8d8eccSSepherosa Ziehau 16176c8d8eccSSepherosa Ziehau /* Set misc. local control, enable interrupts on attentions */ 16184aa71e73SSepherosa Ziehau BNX_SETBIT(sc, BGE_MISC_LOCAL_CTL, BGE_MLC_INTR_ONATTN); 16196c8d8eccSSepherosa Ziehau 16206c8d8eccSSepherosa Ziehau #ifdef notdef 16216c8d8eccSSepherosa Ziehau /* Assert GPIO pins for PHY reset */ 16226c8d8eccSSepherosa Ziehau BNX_SETBIT(sc, BGE_MISC_LOCAL_CTL, BGE_MLC_MISCIO_OUT0| 16236c8d8eccSSepherosa Ziehau BGE_MLC_MISCIO_OUT1|BGE_MLC_MISCIO_OUT2); 16246c8d8eccSSepherosa Ziehau BNX_SETBIT(sc, BGE_MISC_LOCAL_CTL, BGE_MLC_MISCIO_OUTEN0| 16256c8d8eccSSepherosa Ziehau BGE_MLC_MISCIO_OUTEN1|BGE_MLC_MISCIO_OUTEN2); 16266c8d8eccSSepherosa Ziehau #endif 16276c8d8eccSSepherosa Ziehau 1628695a8586SSepherosa Ziehau if (sc->bnx_intr_type == PCI_INTR_TYPE_MSIX) 1629695a8586SSepherosa Ziehau bnx_enable_msi(sc, TRUE); 1630695a8586SSepherosa Ziehau 16316c8d8eccSSepherosa Ziehau /* Turn on write DMA state machine */ 16326c8d8eccSSepherosa Ziehau val = BGE_WDMAMODE_ENABLE|BGE_WDMAMODE_ALL_ATTNS; 16336c8d8eccSSepherosa Ziehau /* Enable host coalescing bug fix. */ 16346c8d8eccSSepherosa Ziehau val |= BGE_WDMAMODE_STATUS_TAG_FIX; 16356c8d8eccSSepherosa Ziehau if (sc->bnx_asicrev == BGE_ASICREV_BCM5785) { 16366c8d8eccSSepherosa Ziehau /* Request larger DMA burst size to get better performance. */ 16376c8d8eccSSepherosa Ziehau val |= BGE_WDMAMODE_BURST_ALL_DATA; 16386c8d8eccSSepherosa Ziehau } 16396c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_WDMA_MODE, val); 16406c8d8eccSSepherosa Ziehau DELAY(40); 16416c8d8eccSSepherosa Ziehau 16423730a14dSSepherosa Ziehau if (BNX_IS_57765_PLUS(sc)) { 1643b96cbbb6SSepherosa Ziehau uint32_t dmactl, dmactl_reg; 16446c8d8eccSSepherosa Ziehau 1645b96cbbb6SSepherosa Ziehau if (sc->bnx_asicrev == BGE_ASICREV_BCM5762) 1646b96cbbb6SSepherosa Ziehau dmactl_reg = BGE_RDMA_RSRVCTRL2; 1647b96cbbb6SSepherosa Ziehau else 1648b96cbbb6SSepherosa Ziehau dmactl_reg = BGE_RDMA_RSRVCTRL; 1649b96cbbb6SSepherosa Ziehau 1650b96cbbb6SSepherosa Ziehau dmactl = CSR_READ_4(sc, dmactl_reg); 16516c8d8eccSSepherosa Ziehau /* 16526c8d8eccSSepherosa Ziehau * Adjust tx margin to prevent TX data corruption and 16536c8d8eccSSepherosa Ziehau * fix internal FIFO overflow. 16546c8d8eccSSepherosa Ziehau */ 16556c8d8eccSSepherosa Ziehau if (sc->bnx_asicrev == BGE_ASICREV_BCM5719 || 1656b96cbbb6SSepherosa Ziehau sc->bnx_asicrev == BGE_ASICREV_BCM5720 || 1657b96cbbb6SSepherosa Ziehau sc->bnx_asicrev == BGE_ASICREV_BCM5762) { 16586c8d8eccSSepherosa Ziehau dmactl &= ~(BGE_RDMA_RSRVCTRL_FIFO_LWM_MASK | 16596c8d8eccSSepherosa Ziehau BGE_RDMA_RSRVCTRL_FIFO_HWM_MASK | 16606c8d8eccSSepherosa Ziehau BGE_RDMA_RSRVCTRL_TXMRGN_MASK); 16616c8d8eccSSepherosa Ziehau dmactl |= BGE_RDMA_RSRVCTRL_FIFO_LWM_1_5K | 16626c8d8eccSSepherosa Ziehau BGE_RDMA_RSRVCTRL_FIFO_HWM_1_5K | 16636c8d8eccSSepherosa Ziehau BGE_RDMA_RSRVCTRL_TXMRGN_320B; 16646c8d8eccSSepherosa Ziehau } 16656c8d8eccSSepherosa Ziehau /* 16666c8d8eccSSepherosa Ziehau * Enable fix for read DMA FIFO overruns. 16676c8d8eccSSepherosa Ziehau * The fix is to limit the number of RX BDs 16686c8d8eccSSepherosa Ziehau * the hardware would fetch at a fime. 16696c8d8eccSSepherosa Ziehau */ 1670b96cbbb6SSepherosa Ziehau CSR_WRITE_4(sc, dmactl_reg, 16716c8d8eccSSepherosa Ziehau dmactl | BGE_RDMA_RSRVCTRL_FIFO_OFLW_FIX); 16726c8d8eccSSepherosa Ziehau } 16736c8d8eccSSepherosa Ziehau 16746c8d8eccSSepherosa Ziehau if (sc->bnx_asicrev == BGE_ASICREV_BCM5719) { 16756c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_RDMA_LSO_CRPTEN_CTRL, 16766c8d8eccSSepherosa Ziehau CSR_READ_4(sc, BGE_RDMA_LSO_CRPTEN_CTRL) | 16776c8d8eccSSepherosa Ziehau BGE_RDMA_LSO_CRPTEN_CTRL_BLEN_BD_4K | 16786c8d8eccSSepherosa Ziehau BGE_RDMA_LSO_CRPTEN_CTRL_BLEN_LSO_4K); 1679b96cbbb6SSepherosa Ziehau } else if (sc->bnx_asicrev == BGE_ASICREV_BCM5720 || 1680b96cbbb6SSepherosa Ziehau sc->bnx_asicrev == BGE_ASICREV_BCM5762) { 1681b96cbbb6SSepherosa Ziehau uint32_t ctrl_reg; 1682b96cbbb6SSepherosa Ziehau 1683b96cbbb6SSepherosa Ziehau if (sc->bnx_asicrev == BGE_ASICREV_BCM5762) 1684b96cbbb6SSepherosa Ziehau ctrl_reg = BGE_RDMA_LSO_CRPTEN_CTRL2; 1685b96cbbb6SSepherosa Ziehau else 1686b96cbbb6SSepherosa Ziehau ctrl_reg = BGE_RDMA_LSO_CRPTEN_CTRL; 1687b96cbbb6SSepherosa Ziehau 16886c8d8eccSSepherosa Ziehau /* 16896c8d8eccSSepherosa Ziehau * Allow 4KB burst length reads for non-LSO frames. 16906c8d8eccSSepherosa Ziehau * Enable 512B burst length reads for buffer descriptors. 16916c8d8eccSSepherosa Ziehau */ 1692b96cbbb6SSepherosa Ziehau CSR_WRITE_4(sc, ctrl_reg, 1693b96cbbb6SSepherosa Ziehau CSR_READ_4(sc, ctrl_reg) | 16946c8d8eccSSepherosa Ziehau BGE_RDMA_LSO_CRPTEN_CTRL_BLEN_BD_512 | 16956c8d8eccSSepherosa Ziehau BGE_RDMA_LSO_CRPTEN_CTRL_BLEN_LSO_4K); 16966c8d8eccSSepherosa Ziehau } 16976c8d8eccSSepherosa Ziehau 16986c8d8eccSSepherosa Ziehau /* Turn on read DMA state machine */ 16996c8d8eccSSepherosa Ziehau val = BGE_RDMAMODE_ENABLE | BGE_RDMAMODE_ALL_ATTNS; 17006c8d8eccSSepherosa Ziehau if (sc->bnx_asicrev == BGE_ASICREV_BCM5717) 17016c8d8eccSSepherosa Ziehau val |= BGE_RDMAMODE_MULT_DMA_RD_DIS; 17026c8d8eccSSepherosa Ziehau if (sc->bnx_asicrev == BGE_ASICREV_BCM5784 || 17036c8d8eccSSepherosa Ziehau sc->bnx_asicrev == BGE_ASICREV_BCM5785 || 17046c8d8eccSSepherosa Ziehau sc->bnx_asicrev == BGE_ASICREV_BCM57780) { 17056c8d8eccSSepherosa Ziehau val |= BGE_RDMAMODE_BD_SBD_CRPT_ATTN | 17066c8d8eccSSepherosa Ziehau BGE_RDMAMODE_MBUF_RBD_CRPT_ATTN | 17076c8d8eccSSepherosa Ziehau BGE_RDMAMODE_MBUF_SBD_CRPT_ATTN; 17086c8d8eccSSepherosa Ziehau } 1709b96cbbb6SSepherosa Ziehau if (sc->bnx_asicrev == BGE_ASICREV_BCM5720 || 1710b96cbbb6SSepherosa Ziehau sc->bnx_asicrev == BGE_ASICREV_BCM5762) { 17116c8d8eccSSepherosa Ziehau val |= CSR_READ_4(sc, BGE_RDMA_MODE) & 17126c8d8eccSSepherosa Ziehau BGE_RDMAMODE_H2BNC_VLAN_DET; 17136c8d8eccSSepherosa Ziehau /* 17146c8d8eccSSepherosa Ziehau * Allow multiple outstanding read requests from 17156c8d8eccSSepherosa Ziehau * non-LSO read DMA engine. 17166c8d8eccSSepherosa Ziehau */ 17176c8d8eccSSepherosa Ziehau val &= ~BGE_RDMAMODE_MULT_DMA_RD_DIS; 17186c8d8eccSSepherosa Ziehau } 171960e67e3fSSepherosa Ziehau if (sc->bnx_asicrev == BGE_ASICREV_BCM57766) 172060e67e3fSSepherosa Ziehau val |= BGE_RDMAMODE_JMB_2K_MMRR; 172166deb1c1SSepherosa Ziehau if (sc->bnx_flags & BNX_FLAG_TSO) 172266deb1c1SSepherosa Ziehau val |= BGE_RDMAMODE_TSO4_ENABLE; 17236c8d8eccSSepherosa Ziehau val |= BGE_RDMAMODE_FIFO_LONG_BURST; 17246c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_RDMA_MODE, val); 17256c8d8eccSSepherosa Ziehau DELAY(40); 17266c8d8eccSSepherosa Ziehau 17276c8d8eccSSepherosa Ziehau /* Turn on RX data completion state machine */ 17286c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_RDC_MODE, BGE_RDCMODE_ENABLE); 17296c8d8eccSSepherosa Ziehau 17306c8d8eccSSepherosa Ziehau /* Turn on RX BD initiator state machine */ 17316c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_RBDI_MODE, BGE_RBDIMODE_ENABLE); 17326c8d8eccSSepherosa Ziehau 17336c8d8eccSSepherosa Ziehau /* Turn on RX data and RX BD initiator state machine */ 17346c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_RDBDI_MODE, BGE_RDBDIMODE_ENABLE); 17356c8d8eccSSepherosa Ziehau 17366c8d8eccSSepherosa Ziehau /* Turn on send BD completion state machine */ 17376c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_SBDC_MODE, BGE_SBDCMODE_ENABLE); 17386c8d8eccSSepherosa Ziehau 17396c8d8eccSSepherosa Ziehau /* Turn on send data completion state machine */ 17406c8d8eccSSepherosa Ziehau val = BGE_SDCMODE_ENABLE; 17416c8d8eccSSepherosa Ziehau if (sc->bnx_asicrev == BGE_ASICREV_BCM5761) 17426c8d8eccSSepherosa Ziehau val |= BGE_SDCMODE_CDELAY; 17436c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_SDC_MODE, val); 17446c8d8eccSSepherosa Ziehau 17456c8d8eccSSepherosa Ziehau /* Turn on send data initiator state machine */ 174666deb1c1SSepherosa Ziehau if (sc->bnx_flags & BNX_FLAG_TSO) { 174766deb1c1SSepherosa Ziehau CSR_WRITE_4(sc, BGE_SDI_MODE, BGE_SDIMODE_ENABLE | 174866deb1c1SSepherosa Ziehau BGE_SDIMODE_HW_LSO_PRE_DMA); 174966deb1c1SSepherosa Ziehau } else { 17506c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_SDI_MODE, BGE_SDIMODE_ENABLE); 175166deb1c1SSepherosa Ziehau } 17526c8d8eccSSepherosa Ziehau 17536c8d8eccSSepherosa Ziehau /* Turn on send BD initiator state machine */ 1754695a8586SSepherosa Ziehau val = BGE_SBDIMODE_ENABLE; 1755695a8586SSepherosa Ziehau if (sc->bnx_tx_ringcnt > 1) 1756695a8586SSepherosa Ziehau val |= BGE_SBDIMODE_MULTI_TXR; 1757695a8586SSepherosa Ziehau CSR_WRITE_4(sc, BGE_SBDI_MODE, val); 17586c8d8eccSSepherosa Ziehau 17596c8d8eccSSepherosa Ziehau /* Turn on send BD selector state machine */ 17606c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_SRS_MODE, BGE_SRSMODE_ENABLE); 17616c8d8eccSSepherosa Ziehau 17626c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_SDI_STATS_ENABLE_MASK, 0x007FFFFF); 17636c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_SDI_STATS_CTL, 17646c8d8eccSSepherosa Ziehau BGE_SDISTATSCTL_ENABLE|BGE_SDISTATSCTL_FASTER); 17656c8d8eccSSepherosa Ziehau 17666c8d8eccSSepherosa Ziehau /* ack/clear link change events */ 17676c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_MAC_STS, BGE_MACSTAT_SYNC_CHANGED| 17686c8d8eccSSepherosa Ziehau BGE_MACSTAT_CFG_CHANGED|BGE_MACSTAT_MI_COMPLETE| 17696c8d8eccSSepherosa Ziehau BGE_MACSTAT_LINK_CHANGED); 17706c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_MI_STS, 0); 17716c8d8eccSSepherosa Ziehau 17726c8d8eccSSepherosa Ziehau /* 17736c8d8eccSSepherosa Ziehau * Enable attention when the link has changed state for 17746c8d8eccSSepherosa Ziehau * devices that use auto polling. 17756c8d8eccSSepherosa Ziehau */ 17766c8d8eccSSepherosa Ziehau if (sc->bnx_flags & BNX_FLAG_TBI) { 17776c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_MI_STS, BGE_MISTS_LINK); 17786c8d8eccSSepherosa Ziehau } else { 17796c8d8eccSSepherosa Ziehau if (sc->bnx_mi_mode & BGE_MIMODE_AUTOPOLL) { 17806c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_MI_MODE, sc->bnx_mi_mode); 17816c8d8eccSSepherosa Ziehau DELAY(80); 17826c8d8eccSSepherosa Ziehau } 17836c8d8eccSSepherosa Ziehau } 17846c8d8eccSSepherosa Ziehau 17856c8d8eccSSepherosa Ziehau /* 17866c8d8eccSSepherosa Ziehau * Clear any pending link state attention. 17876c8d8eccSSepherosa Ziehau * Otherwise some link state change events may be lost until attention 17886c8d8eccSSepherosa Ziehau * is cleared by bnx_intr() -> bnx_softc.bnx_link_upd() sequence. 17896c8d8eccSSepherosa Ziehau * It's not necessary on newer BCM chips - perhaps enabling link 17906c8d8eccSSepherosa Ziehau * state change attentions implies clearing pending attention. 17916c8d8eccSSepherosa Ziehau */ 17926c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_MAC_STS, BGE_MACSTAT_SYNC_CHANGED| 17936c8d8eccSSepherosa Ziehau BGE_MACSTAT_CFG_CHANGED|BGE_MACSTAT_MI_COMPLETE| 17946c8d8eccSSepherosa Ziehau BGE_MACSTAT_LINK_CHANGED); 17956c8d8eccSSepherosa Ziehau 17966c8d8eccSSepherosa Ziehau /* Enable link state change attentions. */ 17976c8d8eccSSepherosa Ziehau BNX_SETBIT(sc, BGE_MAC_EVT_ENB, BGE_EVTENB_LINK_CHANGED); 17986c8d8eccSSepherosa Ziehau 17996c8d8eccSSepherosa Ziehau return(0); 18006c8d8eccSSepherosa Ziehau } 18016c8d8eccSSepherosa Ziehau 18026c8d8eccSSepherosa Ziehau /* 18036c8d8eccSSepherosa Ziehau * Probe for a Broadcom chip. Check the PCI vendor and device IDs 18046c8d8eccSSepherosa Ziehau * against our list and return its name if we find a match. Note 18056c8d8eccSSepherosa Ziehau * that since the Broadcom controller contains VPD support, we 18066c8d8eccSSepherosa Ziehau * can get the device name string from the controller itself instead 18076c8d8eccSSepherosa Ziehau * of the compiled-in string. This is a little slow, but it guarantees 18086c8d8eccSSepherosa Ziehau * we'll always announce the right product name. 18096c8d8eccSSepherosa Ziehau */ 18106c8d8eccSSepherosa Ziehau static int 18116c8d8eccSSepherosa Ziehau bnx_probe(device_t dev) 18126c8d8eccSSepherosa Ziehau { 18136c8d8eccSSepherosa Ziehau const struct bnx_type *t; 18146c8d8eccSSepherosa Ziehau uint16_t product, vendor; 18156c8d8eccSSepherosa Ziehau 18166c8d8eccSSepherosa Ziehau if (!pci_is_pcie(dev)) 18176c8d8eccSSepherosa Ziehau return ENXIO; 18186c8d8eccSSepherosa Ziehau 18196c8d8eccSSepherosa Ziehau product = pci_get_device(dev); 18206c8d8eccSSepherosa Ziehau vendor = pci_get_vendor(dev); 18216c8d8eccSSepherosa Ziehau 18226c8d8eccSSepherosa Ziehau for (t = bnx_devs; t->bnx_name != NULL; t++) { 18236c8d8eccSSepherosa Ziehau if (vendor == t->bnx_vid && product == t->bnx_did) 18246c8d8eccSSepherosa Ziehau break; 18256c8d8eccSSepherosa Ziehau } 18266c8d8eccSSepherosa Ziehau if (t->bnx_name == NULL) 18276c8d8eccSSepherosa Ziehau return ENXIO; 18286c8d8eccSSepherosa Ziehau 18296c8d8eccSSepherosa Ziehau device_set_desc(dev, t->bnx_name); 18306c8d8eccSSepherosa Ziehau return 0; 18316c8d8eccSSepherosa Ziehau } 18326c8d8eccSSepherosa Ziehau 18336c8d8eccSSepherosa Ziehau static int 18346c8d8eccSSepherosa Ziehau bnx_attach(device_t dev) 18356c8d8eccSSepherosa Ziehau { 18366c8d8eccSSepherosa Ziehau struct ifnet *ifp; 18376c8d8eccSSepherosa Ziehau struct bnx_softc *sc; 1838841cdf08SSepherosa Ziehau struct bnx_rx_std_ring *std; 1839e594b5c4SSepherosa Ziehau uint32_t hwcfg = 0; 1840841cdf08SSepherosa Ziehau int error = 0, rid, capmask, i, std_cpuid, std_cpuid_def; 18416c8d8eccSSepherosa Ziehau uint8_t ether_addr[ETHER_ADDR_LEN]; 184207e9f7c0SSascha Wildner uint16_t product; 18436c8d8eccSSepherosa Ziehau uintptr_t mii_priv = 0; 1844695a8586SSepherosa Ziehau #if defined(BNX_TSO_DEBUG) || defined(BNX_RSS_DEBUG) || defined(BNX_TSS_DEBUG) 184566deb1c1SSepherosa Ziehau char desc[32]; 184666deb1c1SSepherosa Ziehau #endif 18474fa38985SSepherosa Ziehau #ifdef IFPOLL_ENABLE 18484fa38985SSepherosa Ziehau int offset, offset_def; 18494fa38985SSepherosa Ziehau #endif 18506c8d8eccSSepherosa Ziehau 18516c8d8eccSSepherosa Ziehau sc = device_get_softc(dev); 18526c8d8eccSSepherosa Ziehau sc->bnx_dev = dev; 18537dbaa833SSepherosa Ziehau callout_init_mp(&sc->bnx_tick_timer); 18546c8d8eccSSepherosa Ziehau lwkt_serialize_init(&sc->bnx_jslot_serializer); 1855f33ac8a4SSepherosa Ziehau lwkt_serialize_init(&sc->bnx_main_serialize); 18566c8d8eccSSepherosa Ziehau 1857695a8586SSepherosa Ziehau /* Always setup interrupt mailboxes */ 1858695a8586SSepherosa Ziehau for (i = 0; i < BNX_INTR_MAX; ++i) { 1859695a8586SSepherosa Ziehau callout_init_mp(&sc->bnx_intr_data[i].bnx_intr_timer); 1860695a8586SSepherosa Ziehau sc->bnx_intr_data[i].bnx_sc = sc; 1861695a8586SSepherosa Ziehau sc->bnx_intr_data[i].bnx_intr_mbx = BGE_MBX_IRQ0_LO + (i * 8); 1862695a8586SSepherosa Ziehau sc->bnx_intr_data[i].bnx_intr_rid = -1; 1863695a8586SSepherosa Ziehau sc->bnx_intr_data[i].bnx_intr_cpuid = -1; 1864695a8586SSepherosa Ziehau } 1865695a8586SSepherosa Ziehau 18669f5082d5SSepherosa Ziehau sc->bnx_func_addr = pci_get_function(dev); 18676c8d8eccSSepherosa Ziehau product = pci_get_device(dev); 18686c8d8eccSSepherosa Ziehau 18696c8d8eccSSepherosa Ziehau #ifndef BURN_BRIDGES 18706c8d8eccSSepherosa Ziehau if (pci_get_powerstate(dev) != PCI_POWERSTATE_D0) { 18716c8d8eccSSepherosa Ziehau uint32_t irq, mem; 18726c8d8eccSSepherosa Ziehau 18736c8d8eccSSepherosa Ziehau irq = pci_read_config(dev, PCIR_INTLINE, 4); 18746c8d8eccSSepherosa Ziehau mem = pci_read_config(dev, BGE_PCI_BAR0, 4); 18756c8d8eccSSepherosa Ziehau 18766c8d8eccSSepherosa Ziehau device_printf(dev, "chip is in D%d power mode " 18776c8d8eccSSepherosa Ziehau "-- setting to D0\n", pci_get_powerstate(dev)); 18786c8d8eccSSepherosa Ziehau 18796c8d8eccSSepherosa Ziehau pci_set_powerstate(dev, PCI_POWERSTATE_D0); 18806c8d8eccSSepherosa Ziehau 18816c8d8eccSSepherosa Ziehau pci_write_config(dev, PCIR_INTLINE, irq, 4); 18826c8d8eccSSepherosa Ziehau pci_write_config(dev, BGE_PCI_BAR0, mem, 4); 18836c8d8eccSSepherosa Ziehau } 18846c8d8eccSSepherosa Ziehau #endif /* !BURN_BRIDGE */ 18856c8d8eccSSepherosa Ziehau 18866c8d8eccSSepherosa Ziehau /* 18876c8d8eccSSepherosa Ziehau * Map control/status registers. 18886c8d8eccSSepherosa Ziehau */ 18896c8d8eccSSepherosa Ziehau pci_enable_busmaster(dev); 18906c8d8eccSSepherosa Ziehau 18916c8d8eccSSepherosa Ziehau rid = BGE_PCI_BAR0; 18926c8d8eccSSepherosa Ziehau sc->bnx_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, 18936c8d8eccSSepherosa Ziehau RF_ACTIVE); 18946c8d8eccSSepherosa Ziehau 18956c8d8eccSSepherosa Ziehau if (sc->bnx_res == NULL) { 18966c8d8eccSSepherosa Ziehau device_printf(dev, "couldn't map memory\n"); 18976c8d8eccSSepherosa Ziehau return ENXIO; 18986c8d8eccSSepherosa Ziehau } 18996c8d8eccSSepherosa Ziehau 19006c8d8eccSSepherosa Ziehau sc->bnx_btag = rman_get_bustag(sc->bnx_res); 19016c8d8eccSSepherosa Ziehau sc->bnx_bhandle = rman_get_bushandle(sc->bnx_res); 19026c8d8eccSSepherosa Ziehau 19036c8d8eccSSepherosa Ziehau /* Save various chip information */ 19046c8d8eccSSepherosa Ziehau sc->bnx_chipid = 19056c8d8eccSSepherosa Ziehau pci_read_config(dev, BGE_PCI_MISC_CTL, 4) >> 19066c8d8eccSSepherosa Ziehau BGE_PCIMISCCTL_ASICREV_SHIFT; 19076c8d8eccSSepherosa Ziehau if (BGE_ASICREV(sc->bnx_chipid) == BGE_ASICREV_USE_PRODID_REG) { 19086c8d8eccSSepherosa Ziehau /* All chips having dedicated ASICREV register have CPMU */ 19096c8d8eccSSepherosa Ziehau sc->bnx_flags |= BNX_FLAG_CPMU; 19106c8d8eccSSepherosa Ziehau 19116c8d8eccSSepherosa Ziehau switch (product) { 19126c8d8eccSSepherosa Ziehau case PCI_PRODUCT_BROADCOM_BCM5717: 1913d79f5d8fSSepherosa Ziehau case PCI_PRODUCT_BROADCOM_BCM5717C: 19146c8d8eccSSepherosa Ziehau case PCI_PRODUCT_BROADCOM_BCM5718: 19156c8d8eccSSepherosa Ziehau case PCI_PRODUCT_BROADCOM_BCM5719: 19166c8d8eccSSepherosa Ziehau case PCI_PRODUCT_BROADCOM_BCM5720_ALT: 1917b96cbbb6SSepherosa Ziehau case PCI_PRODUCT_BROADCOM_BCM5725: 1918b96cbbb6SSepherosa Ziehau case PCI_PRODUCT_BROADCOM_BCM5727: 1919b96cbbb6SSepherosa Ziehau case PCI_PRODUCT_BROADCOM_BCM5762: 19206c8d8eccSSepherosa Ziehau sc->bnx_chipid = pci_read_config(dev, 19216c8d8eccSSepherosa Ziehau BGE_PCI_GEN2_PRODID_ASICREV, 4); 19226c8d8eccSSepherosa Ziehau break; 19236c8d8eccSSepherosa Ziehau 19246c8d8eccSSepherosa Ziehau case PCI_PRODUCT_BROADCOM_BCM57761: 192532ff3c80SSepherosa Ziehau case PCI_PRODUCT_BROADCOM_BCM57762: 19266c8d8eccSSepherosa Ziehau case PCI_PRODUCT_BROADCOM_BCM57765: 192732ff3c80SSepherosa Ziehau case PCI_PRODUCT_BROADCOM_BCM57766: 19286c8d8eccSSepherosa Ziehau case PCI_PRODUCT_BROADCOM_BCM57781: 192932ff3c80SSepherosa Ziehau case PCI_PRODUCT_BROADCOM_BCM57782: 19306c8d8eccSSepherosa Ziehau case PCI_PRODUCT_BROADCOM_BCM57785: 193132ff3c80SSepherosa Ziehau case PCI_PRODUCT_BROADCOM_BCM57786: 19326c8d8eccSSepherosa Ziehau case PCI_PRODUCT_BROADCOM_BCM57791: 19336c8d8eccSSepherosa Ziehau case PCI_PRODUCT_BROADCOM_BCM57795: 19346c8d8eccSSepherosa Ziehau sc->bnx_chipid = pci_read_config(dev, 19356c8d8eccSSepherosa Ziehau BGE_PCI_GEN15_PRODID_ASICREV, 4); 19366c8d8eccSSepherosa Ziehau break; 19376c8d8eccSSepherosa Ziehau 19386c8d8eccSSepherosa Ziehau default: 19396c8d8eccSSepherosa Ziehau sc->bnx_chipid = pci_read_config(dev, 19406c8d8eccSSepherosa Ziehau BGE_PCI_PRODID_ASICREV, 4); 19416c8d8eccSSepherosa Ziehau break; 19426c8d8eccSSepherosa Ziehau } 19436c8d8eccSSepherosa Ziehau } 1944d79f5d8fSSepherosa Ziehau if (sc->bnx_chipid == BGE_CHIPID_BCM5717_C0) 1945d79f5d8fSSepherosa Ziehau sc->bnx_chipid = BGE_CHIPID_BCM5720_A0; 1946d79f5d8fSSepherosa Ziehau 19476c8d8eccSSepherosa Ziehau sc->bnx_asicrev = BGE_ASICREV(sc->bnx_chipid); 19486c8d8eccSSepherosa Ziehau sc->bnx_chiprev = BGE_CHIPREV(sc->bnx_chipid); 19496c8d8eccSSepherosa Ziehau 19506c8d8eccSSepherosa Ziehau switch (sc->bnx_asicrev) { 19516c8d8eccSSepherosa Ziehau case BGE_ASICREV_BCM5717: 19526c8d8eccSSepherosa Ziehau case BGE_ASICREV_BCM5719: 19536c8d8eccSSepherosa Ziehau case BGE_ASICREV_BCM5720: 1954f368d0d9SSepherosa Ziehau sc->bnx_flags |= BNX_FLAG_5717_PLUS | BNX_FLAG_57765_PLUS; 1955f368d0d9SSepherosa Ziehau break; 1956f368d0d9SSepherosa Ziehau 1957b96cbbb6SSepherosa Ziehau case BGE_ASICREV_BCM5762: 1958b96cbbb6SSepherosa Ziehau sc->bnx_flags |= BNX_FLAG_57765_PLUS; 1959b96cbbb6SSepherosa Ziehau break; 1960b96cbbb6SSepherosa Ziehau 19616c8d8eccSSepherosa Ziehau case BGE_ASICREV_BCM57765: 196232ff3c80SSepherosa Ziehau case BGE_ASICREV_BCM57766: 1963f368d0d9SSepherosa Ziehau sc->bnx_flags |= BNX_FLAG_57765_FAMILY | BNX_FLAG_57765_PLUS; 19646c8d8eccSSepherosa Ziehau break; 19656c8d8eccSSepherosa Ziehau } 19666c8d8eccSSepherosa Ziehau 19674aa71e73SSepherosa Ziehau if (sc->bnx_asicrev == BGE_ASICREV_BCM5717 || 19684aa71e73SSepherosa Ziehau sc->bnx_asicrev == BGE_ASICREV_BCM5719 || 19694aa71e73SSepherosa Ziehau sc->bnx_asicrev == BGE_ASICREV_BCM5720 || 19704aa71e73SSepherosa Ziehau sc->bnx_asicrev == BGE_ASICREV_BCM5762) 19714aa71e73SSepherosa Ziehau sc->bnx_flags |= BNX_FLAG_APE; 19724aa71e73SSepherosa Ziehau 197366deb1c1SSepherosa Ziehau sc->bnx_flags |= BNX_FLAG_TSO; 197466deb1c1SSepherosa Ziehau if (sc->bnx_asicrev == BGE_ASICREV_BCM5719 && 197566deb1c1SSepherosa Ziehau sc->bnx_chipid == BGE_CHIPID_BCM5719_A0) 197666deb1c1SSepherosa Ziehau sc->bnx_flags &= ~BNX_FLAG_TSO; 197766deb1c1SSepherosa Ziehau 1978df9ccc98SSepherosa Ziehau if (sc->bnx_asicrev == BGE_ASICREV_BCM5717 || 1979df9ccc98SSepherosa Ziehau BNX_IS_57765_FAMILY(sc)) { 1980df9ccc98SSepherosa Ziehau /* 1981df9ccc98SSepherosa Ziehau * All BCM57785 and BCM5718 families chips have a bug that 1982df9ccc98SSepherosa Ziehau * under certain situation interrupt will not be enabled 198397ba8fc5SSepherosa Ziehau * even if status tag is written to interrupt mailbox. 1984df9ccc98SSepherosa Ziehau * 1985df9ccc98SSepherosa Ziehau * While BCM5719 and BCM5720 have a hardware workaround 1986df9ccc98SSepherosa Ziehau * which could fix the above bug. 1987df9ccc98SSepherosa Ziehau * See the comment near BGE_PCIDMARWCTL_TAGGED_STATUS_WA in 1988df9ccc98SSepherosa Ziehau * bnx_chipinit(). 1989df9ccc98SSepherosa Ziehau * 1990df9ccc98SSepherosa Ziehau * For the rest of the chips in these two families, we will 1991df9ccc98SSepherosa Ziehau * have to poll the status block at high rate (10ms currently) 1992df9ccc98SSepherosa Ziehau * to check whether the interrupt is hosed or not. 1993695a8586SSepherosa Ziehau * See bnx_check_intr_*() for details. 1994df9ccc98SSepherosa Ziehau */ 1995df9ccc98SSepherosa Ziehau sc->bnx_flags |= BNX_FLAG_STATUSTAG_BUG; 1996df9ccc98SSepherosa Ziehau } 1997df9ccc98SSepherosa Ziehau 19986c8d8eccSSepherosa Ziehau sc->bnx_pciecap = pci_get_pciecap_ptr(sc->bnx_dev); 19996c8d8eccSSepherosa Ziehau if (sc->bnx_asicrev == BGE_ASICREV_BCM5719 || 20006c8d8eccSSepherosa Ziehau sc->bnx_asicrev == BGE_ASICREV_BCM5720) 20016c8d8eccSSepherosa Ziehau pcie_set_max_readrq(dev, PCIEM_DEVCTL_MAX_READRQ_2048); 20026c8d8eccSSepherosa Ziehau else 20036c8d8eccSSepherosa Ziehau pcie_set_max_readrq(dev, PCIEM_DEVCTL_MAX_READRQ_4096); 20046c8d8eccSSepherosa Ziehau device_printf(dev, "CHIP ID 0x%08x; " 20056c8d8eccSSepherosa Ziehau "ASIC REV 0x%02x; CHIP REV 0x%02x\n", 20066c8d8eccSSepherosa Ziehau sc->bnx_chipid, sc->bnx_asicrev, sc->bnx_chiprev); 20076c8d8eccSSepherosa Ziehau 20086c8d8eccSSepherosa Ziehau /* 20096c8d8eccSSepherosa Ziehau * Set various PHY quirk flags. 20106c8d8eccSSepherosa Ziehau */ 20116c8d8eccSSepherosa Ziehau 20126c8d8eccSSepherosa Ziehau capmask = MII_CAPMASK_DEFAULT; 201346283a40SSepherosa Ziehau if (product == PCI_PRODUCT_BROADCOM_BCM57791 || 201446283a40SSepherosa Ziehau product == PCI_PRODUCT_BROADCOM_BCM57795) { 20156c8d8eccSSepherosa Ziehau /* 10/100 only */ 20166c8d8eccSSepherosa Ziehau capmask &= ~BMSR_EXTSTAT; 20176c8d8eccSSepherosa Ziehau } 20186c8d8eccSSepherosa Ziehau 20196c8d8eccSSepherosa Ziehau mii_priv |= BRGPHY_FLAG_WIRESPEED; 2020b96cbbb6SSepherosa Ziehau if (sc->bnx_chipid == BGE_CHIPID_BCM5762_A0) 2021b96cbbb6SSepherosa Ziehau mii_priv |= BRGPHY_FLAG_5762_A0; 20226c8d8eccSSepherosa Ziehau 20239f5082d5SSepherosa Ziehau /* 20249f5082d5SSepherosa Ziehau * Chips with APE need BAR2 access for APE registers/memory. 20259f5082d5SSepherosa Ziehau */ 20269f5082d5SSepherosa Ziehau if (sc->bnx_flags & BNX_FLAG_APE) { 20279f5082d5SSepherosa Ziehau uint32_t pcistate; 20289f5082d5SSepherosa Ziehau 20299f5082d5SSepherosa Ziehau rid = PCIR_BAR(2); 20309f5082d5SSepherosa Ziehau sc->bnx_res2 = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, 20319f5082d5SSepherosa Ziehau RF_ACTIVE); 20329f5082d5SSepherosa Ziehau if (sc->bnx_res2 == NULL) { 20339f5082d5SSepherosa Ziehau device_printf(dev, "couldn't map BAR2 memory\n"); 20349f5082d5SSepherosa Ziehau error = ENXIO; 20359f5082d5SSepherosa Ziehau goto fail; 20369f5082d5SSepherosa Ziehau } 20379f5082d5SSepherosa Ziehau 20389f5082d5SSepherosa Ziehau /* Enable APE register/memory access by host driver. */ 20399f5082d5SSepherosa Ziehau pcistate = pci_read_config(dev, BGE_PCI_PCISTATE, 4); 20409f5082d5SSepherosa Ziehau pcistate |= BGE_PCISTATE_ALLOW_APE_CTLSPC_WR | 20419f5082d5SSepherosa Ziehau BGE_PCISTATE_ALLOW_APE_SHMEM_WR | 20429f5082d5SSepherosa Ziehau BGE_PCISTATE_ALLOW_APE_PSPACE_WR; 20439f5082d5SSepherosa Ziehau pci_write_config(dev, BGE_PCI_PCISTATE, pcistate, 4); 20449f5082d5SSepherosa Ziehau 20459f5082d5SSepherosa Ziehau bnx_ape_lock_init(sc); 20469f5082d5SSepherosa Ziehau bnx_ape_read_fw_ver(sc); 20479f5082d5SSepherosa Ziehau } 20489f5082d5SSepherosa Ziehau 20496c8d8eccSSepherosa Ziehau /* Initialize if_name earlier, so if_printf could be used */ 20506c8d8eccSSepherosa Ziehau ifp = &sc->arpcom.ac_if; 20516c8d8eccSSepherosa Ziehau if_initname(ifp, device_get_name(dev), device_get_unit(dev)); 20526c8d8eccSSepherosa Ziehau 20534aa71e73SSepherosa Ziehau /* 20544aa71e73SSepherosa Ziehau * Try to reset the chip. 20554aa71e73SSepherosa Ziehau */ 20564aa71e73SSepherosa Ziehau bnx_sig_pre_reset(sc, BNX_RESET_SHUTDOWN); 20576c8d8eccSSepherosa Ziehau bnx_reset(sc); 20584aa71e73SSepherosa Ziehau bnx_sig_post_reset(sc, BNX_RESET_SHUTDOWN); 20596c8d8eccSSepherosa Ziehau 20606c8d8eccSSepherosa Ziehau if (bnx_chipinit(sc)) { 20616c8d8eccSSepherosa Ziehau device_printf(dev, "chip initialization failed\n"); 20626c8d8eccSSepherosa Ziehau error = ENXIO; 20636c8d8eccSSepherosa Ziehau goto fail; 20646c8d8eccSSepherosa Ziehau } 20656c8d8eccSSepherosa Ziehau 20666c8d8eccSSepherosa Ziehau /* 20676c8d8eccSSepherosa Ziehau * Get station address 20686c8d8eccSSepherosa Ziehau */ 20696c8d8eccSSepherosa Ziehau error = bnx_get_eaddr(sc, ether_addr); 20706c8d8eccSSepherosa Ziehau if (error) { 20716c8d8eccSSepherosa Ziehau device_printf(dev, "failed to read station address\n"); 20726c8d8eccSSepherosa Ziehau goto fail; 20736c8d8eccSSepherosa Ziehau } 20746c8d8eccSSepherosa Ziehau 2075695a8586SSepherosa Ziehau /* Setup RX/TX and interrupt count */ 2076695a8586SSepherosa Ziehau bnx_setup_ring_cnt(sc); 207733a04907SSepherosa Ziehau 20784fa38985SSepherosa Ziehau if ((sc->bnx_rx_retcnt == 1 && sc->bnx_tx_ringcnt == 1) || 20794fa38985SSepherosa Ziehau (sc->bnx_rx_retcnt > 1 && sc->bnx_tx_ringcnt > 1)) { 20804fa38985SSepherosa Ziehau /* 20814fa38985SSepherosa Ziehau * The RX ring and the corresponding TX ring processing 20824fa38985SSepherosa Ziehau * should be on the same CPU, since they share the same 20834fa38985SSepherosa Ziehau * status block. 20844fa38985SSepherosa Ziehau */ 20854fa38985SSepherosa Ziehau sc->bnx_flags |= BNX_FLAG_RXTX_BUNDLE; 20864fa38985SSepherosa Ziehau if (bootverbose) 20874fa38985SSepherosa Ziehau device_printf(dev, "RX/TX bundle\n"); 2088695a8586SSepherosa Ziehau if (sc->bnx_tx_ringcnt > 1) { 2089695a8586SSepherosa Ziehau /* 2090695a8586SSepherosa Ziehau * Multiple TX rings do not share status block 2091695a8586SSepherosa Ziehau * with link status, so link status will have 2092695a8586SSepherosa Ziehau * to save its own status_tag. 2093695a8586SSepherosa Ziehau */ 2094695a8586SSepherosa Ziehau sc->bnx_flags |= BNX_FLAG_STATUS_HASTAG; 2095695a8586SSepherosa Ziehau if (bootverbose) 2096695a8586SSepherosa Ziehau device_printf(dev, "status needs tag\n"); 2097695a8586SSepherosa Ziehau } 20984fa38985SSepherosa Ziehau } else { 20994fa38985SSepherosa Ziehau KKASSERT(sc->bnx_rx_retcnt > 1 && sc->bnx_tx_ringcnt == 1); 2100695a8586SSepherosa Ziehau if (bootverbose) 2101695a8586SSepherosa Ziehau device_printf(dev, "RX/TX not bundled\n"); 21024fa38985SSepherosa Ziehau } 21034fa38985SSepherosa Ziehau 2104beedf5beSSepherosa Ziehau error = bnx_dma_alloc(dev); 21056c8d8eccSSepherosa Ziehau if (error) 21066c8d8eccSSepherosa Ziehau goto fail; 21076c8d8eccSSepherosa Ziehau 21084fa38985SSepherosa Ziehau #ifdef IFPOLL_ENABLE 21094fa38985SSepherosa Ziehau if (sc->bnx_flags & BNX_FLAG_RXTX_BUNDLE) { 21104fa38985SSepherosa Ziehau /* 21114fa38985SSepherosa Ziehau * NPOLLING RX/TX CPU offset 21124fa38985SSepherosa Ziehau */ 21134fa38985SSepherosa Ziehau if (sc->bnx_rx_retcnt == ncpus2) { 21144fa38985SSepherosa Ziehau offset = 0; 21154fa38985SSepherosa Ziehau } else { 21164fa38985SSepherosa Ziehau offset_def = 21174fa38985SSepherosa Ziehau (sc->bnx_rx_retcnt * device_get_unit(dev)) % ncpus2; 21184fa38985SSepherosa Ziehau offset = device_getenv_int(dev, "npoll.offset", 21194fa38985SSepherosa Ziehau offset_def); 21204fa38985SSepherosa Ziehau if (offset >= ncpus2 || 21214fa38985SSepherosa Ziehau offset % sc->bnx_rx_retcnt != 0) { 21224fa38985SSepherosa Ziehau device_printf(dev, "invalid npoll.offset %d, " 21234fa38985SSepherosa Ziehau "use %d\n", offset, offset_def); 21244fa38985SSepherosa Ziehau offset = offset_def; 21254fa38985SSepherosa Ziehau } 21264fa38985SSepherosa Ziehau } 21274fa38985SSepherosa Ziehau sc->bnx_npoll_rxoff = offset; 21284fa38985SSepherosa Ziehau sc->bnx_npoll_txoff = offset; 21294fa38985SSepherosa Ziehau } else { 21304fa38985SSepherosa Ziehau /* 21314fa38985SSepherosa Ziehau * NPOLLING RX CPU offset 21324fa38985SSepherosa Ziehau */ 21334fa38985SSepherosa Ziehau if (sc->bnx_rx_retcnt == ncpus2) { 21344fa38985SSepherosa Ziehau offset = 0; 21354fa38985SSepherosa Ziehau } else { 21364fa38985SSepherosa Ziehau offset_def = 21374fa38985SSepherosa Ziehau (sc->bnx_rx_retcnt * device_get_unit(dev)) % ncpus2; 21384fa38985SSepherosa Ziehau offset = device_getenv_int(dev, "npoll.rxoff", 21394fa38985SSepherosa Ziehau offset_def); 21404fa38985SSepherosa Ziehau if (offset >= ncpus2 || 21414fa38985SSepherosa Ziehau offset % sc->bnx_rx_retcnt != 0) { 21424fa38985SSepherosa Ziehau device_printf(dev, "invalid npoll.rxoff %d, " 21434fa38985SSepherosa Ziehau "use %d\n", offset, offset_def); 21444fa38985SSepherosa Ziehau offset = offset_def; 21454fa38985SSepherosa Ziehau } 21464fa38985SSepherosa Ziehau } 21474fa38985SSepherosa Ziehau sc->bnx_npoll_rxoff = offset; 21484fa38985SSepherosa Ziehau 21494fa38985SSepherosa Ziehau /* 21504fa38985SSepherosa Ziehau * NPOLLING TX CPU offset 21514fa38985SSepherosa Ziehau */ 21524fa38985SSepherosa Ziehau offset_def = device_get_unit(dev) % ncpus2; 21534fa38985SSepherosa Ziehau offset = device_getenv_int(dev, "npoll.txoff", offset_def); 21544fa38985SSepherosa Ziehau if (offset >= ncpus2) { 21554fa38985SSepherosa Ziehau device_printf(dev, "invalid npoll.txoff %d, use %d\n", 21564fa38985SSepherosa Ziehau offset, offset_def); 21574fa38985SSepherosa Ziehau offset = offset_def; 21584fa38985SSepherosa Ziehau } 21594fa38985SSepherosa Ziehau sc->bnx_npoll_txoff = offset; 21604fa38985SSepherosa Ziehau } 21614fa38985SSepherosa Ziehau #endif /* IFPOLL_ENABLE */ 21624fa38985SSepherosa Ziehau 216316b32c4cSSepherosa Ziehau /* 216416b32c4cSSepherosa Ziehau * Allocate interrupt 216516b32c4cSSepherosa Ziehau */ 21660c7da01dSSepherosa Ziehau error = bnx_alloc_intr(sc); 21670c7da01dSSepherosa Ziehau if (error) 216816b32c4cSSepherosa Ziehau goto fail; 216916b32c4cSSepherosa Ziehau 2170329f9016SSepherosa Ziehau /* Setup serializers */ 2171329f9016SSepherosa Ziehau bnx_setup_serialize(sc); 2172329f9016SSepherosa Ziehau 21736c8d8eccSSepherosa Ziehau /* Set default tuneable values. */ 21746c8d8eccSSepherosa Ziehau sc->bnx_rx_coal_ticks = BNX_RX_COAL_TICKS_DEF; 21756c8d8eccSSepherosa Ziehau sc->bnx_tx_coal_ticks = BNX_TX_COAL_TICKS_DEF; 21766c8d8eccSSepherosa Ziehau sc->bnx_rx_coal_bds = BNX_RX_COAL_BDS_DEF; 2177a86cc105SSepherosa Ziehau sc->bnx_rx_coal_bds_poll = sc->bnx_rx_ret_ring[0].bnx_rx_cntmax; 21786c8d8eccSSepherosa Ziehau sc->bnx_tx_coal_bds = BNX_TX_COAL_BDS_DEF; 217927357d84SSepherosa Ziehau sc->bnx_tx_coal_bds_poll = BNX_TX_COAL_BDS_POLL_DEF; 2180306e5498SSepherosa Ziehau sc->bnx_rx_coal_bds_int = BNX_RX_COAL_BDS_INT_DEF; 2181306e5498SSepherosa Ziehau sc->bnx_tx_coal_bds_int = BNX_TX_COAL_BDS_INT_DEF; 21826c8d8eccSSepherosa Ziehau 21836c8d8eccSSepherosa Ziehau /* Set up ifnet structure */ 21846c8d8eccSSepherosa Ziehau ifp->if_softc = sc; 21856c8d8eccSSepherosa Ziehau ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; 21866c8d8eccSSepherosa Ziehau ifp->if_ioctl = bnx_ioctl; 21876c8d8eccSSepherosa Ziehau ifp->if_start = bnx_start; 218839a8d43aSSepherosa Ziehau #ifdef IFPOLL_ENABLE 218939a8d43aSSepherosa Ziehau ifp->if_npoll = bnx_npoll; 21906c8d8eccSSepherosa Ziehau #endif 21916c8d8eccSSepherosa Ziehau ifp->if_init = bnx_init; 2192329f9016SSepherosa Ziehau ifp->if_serialize = bnx_serialize; 2193329f9016SSepherosa Ziehau ifp->if_deserialize = bnx_deserialize; 2194329f9016SSepherosa Ziehau ifp->if_tryserialize = bnx_tryserialize; 2195329f9016SSepherosa Ziehau #ifdef INVARIANTS 2196329f9016SSepherosa Ziehau ifp->if_serialize_assert = bnx_serialize_assert; 2197329f9016SSepherosa Ziehau #endif 21986c8d8eccSSepherosa Ziehau ifp->if_mtu = ETHERMTU; 21996c8d8eccSSepherosa Ziehau ifp->if_capabilities = IFCAP_VLAN_HWTAGGING | IFCAP_VLAN_MTU; 22006c8d8eccSSepherosa Ziehau 22016c8d8eccSSepherosa Ziehau ifp->if_capabilities |= IFCAP_HWCSUM; 22026c8d8eccSSepherosa Ziehau ifp->if_hwassist = BNX_CSUM_FEATURES; 220366deb1c1SSepherosa Ziehau if (sc->bnx_flags & BNX_FLAG_TSO) { 220466deb1c1SSepherosa Ziehau ifp->if_capabilities |= IFCAP_TSO; 220566deb1c1SSepherosa Ziehau ifp->if_hwassist |= CSUM_TSO; 220666deb1c1SSepherosa Ziehau } 2207b19ddf7eSSepherosa Ziehau if (BNX_RSS_ENABLED(sc)) 2208b19ddf7eSSepherosa Ziehau ifp->if_capabilities |= IFCAP_RSS; 22096c8d8eccSSepherosa Ziehau ifp->if_capenable = ifp->if_capabilities; 22106c8d8eccSSepherosa Ziehau 2211329f9016SSepherosa Ziehau ifq_set_maxlen(&ifp->if_snd, BGE_TX_RING_CNT - 1); 2212329f9016SSepherosa Ziehau ifq_set_ready(&ifp->if_snd); 2213329f9016SSepherosa Ziehau ifq_set_subq_cnt(&ifp->if_snd, sc->bnx_tx_ringcnt); 2214329f9016SSepherosa Ziehau 2215695a8586SSepherosa Ziehau if (sc->bnx_tx_ringcnt > 1) { 2216695a8586SSepherosa Ziehau ifp->if_mapsubq = ifq_mapsubq_mask; 2217695a8586SSepherosa Ziehau ifq_set_subq_mask(&ifp->if_snd, sc->bnx_tx_ringcnt - 1); 2218695a8586SSepherosa Ziehau } 2219695a8586SSepherosa Ziehau 22206c8d8eccSSepherosa Ziehau /* 22216c8d8eccSSepherosa Ziehau * Figure out what sort of media we have by checking the 22226c8d8eccSSepherosa Ziehau * hardware config word in the first 32k of NIC internal memory, 22236c8d8eccSSepherosa Ziehau * or fall back to examining the EEPROM if necessary. 22246c8d8eccSSepherosa Ziehau * Note: on some BCM5700 cards, this value appears to be unset. 22256c8d8eccSSepherosa Ziehau * If that's the case, we have to rely on identifying the NIC 22266c8d8eccSSepherosa Ziehau * by its PCI subsystem ID, as we do below for the SysKonnect 22276c8d8eccSSepherosa Ziehau * SK-9D41. 22286c8d8eccSSepherosa Ziehau */ 22290551ac06SSepherosa Ziehau if (bnx_readmem_ind(sc, BGE_SRAM_DATA_SIG) == BGE_SRAM_DATA_SIG_MAGIC) { 22300551ac06SSepherosa Ziehau hwcfg = bnx_readmem_ind(sc, BGE_SRAM_DATA_CFG); 22316c8d8eccSSepherosa Ziehau } else { 22326c8d8eccSSepherosa Ziehau if (bnx_read_eeprom(sc, (caddr_t)&hwcfg, BGE_EE_HWCFG_OFFSET, 22336c8d8eccSSepherosa Ziehau sizeof(hwcfg))) { 22346c8d8eccSSepherosa Ziehau device_printf(dev, "failed to read EEPROM\n"); 22356c8d8eccSSepherosa Ziehau error = ENXIO; 22366c8d8eccSSepherosa Ziehau goto fail; 22376c8d8eccSSepherosa Ziehau } 22386c8d8eccSSepherosa Ziehau hwcfg = ntohl(hwcfg); 22396c8d8eccSSepherosa Ziehau } 22406c8d8eccSSepherosa Ziehau 22416c8d8eccSSepherosa Ziehau /* The SysKonnect SK-9D41 is a 1000baseSX card. */ 22426c8d8eccSSepherosa Ziehau if (pci_get_subvendor(dev) == PCI_PRODUCT_SCHNEIDERKOCH_SK_9D41 || 22436c8d8eccSSepherosa Ziehau (hwcfg & BGE_HWCFG_MEDIA) == BGE_MEDIA_FIBER) 22446c8d8eccSSepherosa Ziehau sc->bnx_flags |= BNX_FLAG_TBI; 22456c8d8eccSSepherosa Ziehau 22466c8d8eccSSepherosa Ziehau /* Setup MI MODE */ 22476c8d8eccSSepherosa Ziehau if (sc->bnx_flags & BNX_FLAG_CPMU) 22486c8d8eccSSepherosa Ziehau sc->bnx_mi_mode = BGE_MIMODE_500KHZ_CONST; 22496c8d8eccSSepherosa Ziehau else 22506c8d8eccSSepherosa Ziehau sc->bnx_mi_mode = BGE_MIMODE_BASE; 22516c8d8eccSSepherosa Ziehau 22526c8d8eccSSepherosa Ziehau /* Setup link status update stuffs */ 22536c8d8eccSSepherosa Ziehau if (sc->bnx_flags & BNX_FLAG_TBI) { 22546c8d8eccSSepherosa Ziehau sc->bnx_link_upd = bnx_tbi_link_upd; 22556c8d8eccSSepherosa Ziehau sc->bnx_link_chg = BGE_MACSTAT_LINK_CHANGED; 22566c8d8eccSSepherosa Ziehau } else if (sc->bnx_mi_mode & BGE_MIMODE_AUTOPOLL) { 22576c8d8eccSSepherosa Ziehau sc->bnx_link_upd = bnx_autopoll_link_upd; 22586c8d8eccSSepherosa Ziehau sc->bnx_link_chg = BGE_MACSTAT_LINK_CHANGED; 22596c8d8eccSSepherosa Ziehau } else { 22606c8d8eccSSepherosa Ziehau sc->bnx_link_upd = bnx_copper_link_upd; 22616c8d8eccSSepherosa Ziehau sc->bnx_link_chg = BGE_MACSTAT_LINK_CHANGED; 22626c8d8eccSSepherosa Ziehau } 22636c8d8eccSSepherosa Ziehau 22646c8d8eccSSepherosa Ziehau /* Set default PHY address */ 22656c8d8eccSSepherosa Ziehau sc->bnx_phyno = 1; 22666c8d8eccSSepherosa Ziehau 22676c8d8eccSSepherosa Ziehau /* 22686c8d8eccSSepherosa Ziehau * PHY address mapping for various devices. 22696c8d8eccSSepherosa Ziehau * 22706c8d8eccSSepherosa Ziehau * | F0 Cu | F0 Sr | F1 Cu | F1 Sr | 22716c8d8eccSSepherosa Ziehau * ---------+-------+-------+-------+-------+ 22726c8d8eccSSepherosa Ziehau * BCM57XX | 1 | X | X | X | 22736c8d8eccSSepherosa Ziehau * BCM5717 | 1 | 8 | 2 | 9 | 22746c8d8eccSSepherosa Ziehau * BCM5719 | 1 | 8 | 2 | 9 | 22756c8d8eccSSepherosa Ziehau * BCM5720 | 1 | 8 | 2 | 9 | 22766c8d8eccSSepherosa Ziehau * 22779f5082d5SSepherosa Ziehau * | F2 Cu | F2 Sr | F3 Cu | F3 Sr | 22789f5082d5SSepherosa Ziehau * ---------+-------+-------+-------+-------+ 22799f5082d5SSepherosa Ziehau * BCM57XX | X | X | X | X | 22809f5082d5SSepherosa Ziehau * BCM5717 | X | X | X | X | 22819f5082d5SSepherosa Ziehau * BCM5719 | 3 | 10 | 4 | 11 | 22829f5082d5SSepherosa Ziehau * BCM5720 | X | X | X | X | 22839f5082d5SSepherosa Ziehau * 22846c8d8eccSSepherosa Ziehau * Other addresses may respond but they are not 22856c8d8eccSSepherosa Ziehau * IEEE compliant PHYs and should be ignored. 22866c8d8eccSSepherosa Ziehau */ 228780969639SSepherosa Ziehau if (BNX_IS_5717_PLUS(sc)) { 22886c8d8eccSSepherosa Ziehau if (sc->bnx_chipid == BGE_CHIPID_BCM5717_A0) { 22896c8d8eccSSepherosa Ziehau if (CSR_READ_4(sc, BGE_SGDIG_STS) & 22906c8d8eccSSepherosa Ziehau BGE_SGDIGSTS_IS_SERDES) 22919f5082d5SSepherosa Ziehau sc->bnx_phyno = sc->bnx_func_addr + 8; 22926c8d8eccSSepherosa Ziehau else 22939f5082d5SSepherosa Ziehau sc->bnx_phyno = sc->bnx_func_addr + 1; 22946c8d8eccSSepherosa Ziehau } else { 22956c8d8eccSSepherosa Ziehau if (CSR_READ_4(sc, BGE_CPMU_PHY_STRAP) & 22966c8d8eccSSepherosa Ziehau BGE_CPMU_PHY_STRAP_IS_SERDES) 22979f5082d5SSepherosa Ziehau sc->bnx_phyno = sc->bnx_func_addr + 8; 22986c8d8eccSSepherosa Ziehau else 22999f5082d5SSepherosa Ziehau sc->bnx_phyno = sc->bnx_func_addr + 1; 23006c8d8eccSSepherosa Ziehau } 23016c8d8eccSSepherosa Ziehau } 23026c8d8eccSSepherosa Ziehau 23036c8d8eccSSepherosa Ziehau if (sc->bnx_flags & BNX_FLAG_TBI) { 23046c8d8eccSSepherosa Ziehau ifmedia_init(&sc->bnx_ifmedia, IFM_IMASK, 23056c8d8eccSSepherosa Ziehau bnx_ifmedia_upd, bnx_ifmedia_sts); 23066c8d8eccSSepherosa Ziehau ifmedia_add(&sc->bnx_ifmedia, IFM_ETHER|IFM_1000_SX, 0, NULL); 23076c8d8eccSSepherosa Ziehau ifmedia_add(&sc->bnx_ifmedia, 23086c8d8eccSSepherosa Ziehau IFM_ETHER|IFM_1000_SX|IFM_FDX, 0, NULL); 23096c8d8eccSSepherosa Ziehau ifmedia_add(&sc->bnx_ifmedia, IFM_ETHER|IFM_AUTO, 0, NULL); 23106c8d8eccSSepherosa Ziehau ifmedia_set(&sc->bnx_ifmedia, IFM_ETHER|IFM_AUTO); 23116c8d8eccSSepherosa Ziehau sc->bnx_ifmedia.ifm_media = sc->bnx_ifmedia.ifm_cur->ifm_media; 23126c8d8eccSSepherosa Ziehau } else { 23136c8d8eccSSepherosa Ziehau struct mii_probe_args mii_args; 23146c8d8eccSSepherosa Ziehau 23156c8d8eccSSepherosa Ziehau mii_probe_args_init(&mii_args, bnx_ifmedia_upd, bnx_ifmedia_sts); 23166c8d8eccSSepherosa Ziehau mii_args.mii_probemask = 1 << sc->bnx_phyno; 23176c8d8eccSSepherosa Ziehau mii_args.mii_capmask = capmask; 23186c8d8eccSSepherosa Ziehau mii_args.mii_privtag = MII_PRIVTAG_BRGPHY; 23196c8d8eccSSepherosa Ziehau mii_args.mii_priv = mii_priv; 23206c8d8eccSSepherosa Ziehau 23216c8d8eccSSepherosa Ziehau error = mii_probe(dev, &sc->bnx_miibus, &mii_args); 23226c8d8eccSSepherosa Ziehau if (error) { 23236c8d8eccSSepherosa Ziehau device_printf(dev, "MII without any PHY!\n"); 23246c8d8eccSSepherosa Ziehau goto fail; 23256c8d8eccSSepherosa Ziehau } 23266c8d8eccSSepherosa Ziehau } 23276c8d8eccSSepherosa Ziehau 23286c8d8eccSSepherosa Ziehau /* 23296c8d8eccSSepherosa Ziehau * Create sysctl nodes. 23306c8d8eccSSepherosa Ziehau */ 23316c8d8eccSSepherosa Ziehau sysctl_ctx_init(&sc->bnx_sysctl_ctx); 23326c8d8eccSSepherosa Ziehau sc->bnx_sysctl_tree = SYSCTL_ADD_NODE(&sc->bnx_sysctl_ctx, 23336c8d8eccSSepherosa Ziehau SYSCTL_STATIC_CHILDREN(_hw), 23346c8d8eccSSepherosa Ziehau OID_AUTO, 23356c8d8eccSSepherosa Ziehau device_get_nameunit(dev), 23366c8d8eccSSepherosa Ziehau CTLFLAG_RD, 0, ""); 23376c8d8eccSSepherosa Ziehau if (sc->bnx_sysctl_tree == NULL) { 23386c8d8eccSSepherosa Ziehau device_printf(dev, "can't add sysctl node\n"); 23396c8d8eccSSepherosa Ziehau error = ENXIO; 23406c8d8eccSSepherosa Ziehau goto fail; 23416c8d8eccSSepherosa Ziehau } 23426c8d8eccSSepherosa Ziehau 234393146551SSepherosa Ziehau SYSCTL_ADD_INT(&sc->bnx_sysctl_ctx, 234493146551SSepherosa Ziehau SYSCTL_CHILDREN(sc->bnx_sysctl_tree), OID_AUTO, 234593146551SSepherosa Ziehau "rx_rings", CTLFLAG_RD, &sc->bnx_rx_retcnt, 0, "# of RX rings"); 234693146551SSepherosa Ziehau SYSCTL_ADD_INT(&sc->bnx_sysctl_ctx, 234793146551SSepherosa Ziehau SYSCTL_CHILDREN(sc->bnx_sysctl_tree), OID_AUTO, 234893146551SSepherosa Ziehau "tx_rings", CTLFLAG_RD, &sc->bnx_tx_ringcnt, 0, "# of TX rings"); 234993146551SSepherosa Ziehau 23506c8d8eccSSepherosa Ziehau SYSCTL_ADD_PROC(&sc->bnx_sysctl_ctx, 23516c8d8eccSSepherosa Ziehau SYSCTL_CHILDREN(sc->bnx_sysctl_tree), 23526c8d8eccSSepherosa Ziehau OID_AUTO, "rx_coal_ticks", 23536c8d8eccSSepherosa Ziehau CTLTYPE_INT | CTLFLAG_RW, 23546c8d8eccSSepherosa Ziehau sc, 0, bnx_sysctl_rx_coal_ticks, "I", 23556c8d8eccSSepherosa Ziehau "Receive coalescing ticks (usec)."); 23566c8d8eccSSepherosa Ziehau SYSCTL_ADD_PROC(&sc->bnx_sysctl_ctx, 23576c8d8eccSSepherosa Ziehau SYSCTL_CHILDREN(sc->bnx_sysctl_tree), 23586c8d8eccSSepherosa Ziehau OID_AUTO, "tx_coal_ticks", 23596c8d8eccSSepherosa Ziehau CTLTYPE_INT | CTLFLAG_RW, 23606c8d8eccSSepherosa Ziehau sc, 0, bnx_sysctl_tx_coal_ticks, "I", 23616c8d8eccSSepherosa Ziehau "Transmit coalescing ticks (usec)."); 23626c8d8eccSSepherosa Ziehau SYSCTL_ADD_PROC(&sc->bnx_sysctl_ctx, 23636c8d8eccSSepherosa Ziehau SYSCTL_CHILDREN(sc->bnx_sysctl_tree), 23646c8d8eccSSepherosa Ziehau OID_AUTO, "rx_coal_bds", 23656c8d8eccSSepherosa Ziehau CTLTYPE_INT | CTLFLAG_RW, 23666c8d8eccSSepherosa Ziehau sc, 0, bnx_sysctl_rx_coal_bds, "I", 23676c8d8eccSSepherosa Ziehau "Receive max coalesced BD count."); 23686c8d8eccSSepherosa Ziehau SYSCTL_ADD_PROC(&sc->bnx_sysctl_ctx, 23696c8d8eccSSepherosa Ziehau SYSCTL_CHILDREN(sc->bnx_sysctl_tree), 2370a86cc105SSepherosa Ziehau OID_AUTO, "rx_coal_bds_poll", 2371a86cc105SSepherosa Ziehau CTLTYPE_INT | CTLFLAG_RW, 2372a86cc105SSepherosa Ziehau sc, 0, bnx_sysctl_rx_coal_bds_poll, "I", 2373a86cc105SSepherosa Ziehau "Receive max coalesced BD count in polling."); 2374a86cc105SSepherosa Ziehau SYSCTL_ADD_PROC(&sc->bnx_sysctl_ctx, 2375a86cc105SSepherosa Ziehau SYSCTL_CHILDREN(sc->bnx_sysctl_tree), 23766c8d8eccSSepherosa Ziehau OID_AUTO, "tx_coal_bds", 23776c8d8eccSSepherosa Ziehau CTLTYPE_INT | CTLFLAG_RW, 23786c8d8eccSSepherosa Ziehau sc, 0, bnx_sysctl_tx_coal_bds, "I", 23796c8d8eccSSepherosa Ziehau "Transmit max coalesced BD count."); 238027357d84SSepherosa Ziehau SYSCTL_ADD_PROC(&sc->bnx_sysctl_ctx, 238127357d84SSepherosa Ziehau SYSCTL_CHILDREN(sc->bnx_sysctl_tree), 238227357d84SSepherosa Ziehau OID_AUTO, "tx_coal_bds_poll", 238327357d84SSepherosa Ziehau CTLTYPE_INT | CTLFLAG_RW, 238427357d84SSepherosa Ziehau sc, 0, bnx_sysctl_tx_coal_bds_poll, "I", 238527357d84SSepherosa Ziehau "Transmit max coalesced BD count in polling."); 23866c8d8eccSSepherosa Ziehau /* 23876c8d8eccSSepherosa Ziehau * A common design characteristic for many Broadcom 23886c8d8eccSSepherosa Ziehau * client controllers is that they only support a 23896c8d8eccSSepherosa Ziehau * single outstanding DMA read operation on the PCIe 23906c8d8eccSSepherosa Ziehau * bus. This means that it will take twice as long to 23916c8d8eccSSepherosa Ziehau * fetch a TX frame that is split into header and 23926c8d8eccSSepherosa Ziehau * payload buffers as it does to fetch a single, 23936c8d8eccSSepherosa Ziehau * contiguous TX frame (2 reads vs. 1 read). For these 23946c8d8eccSSepherosa Ziehau * controllers, coalescing buffers to reduce the number 23956c8d8eccSSepherosa Ziehau * of memory reads is effective way to get maximum 23966c8d8eccSSepherosa Ziehau * performance(about 940Mbps). Without collapsing TX 23976c8d8eccSSepherosa Ziehau * buffers the maximum TCP bulk transfer performance 23986c8d8eccSSepherosa Ziehau * is about 850Mbps. However forcing coalescing mbufs 23996c8d8eccSSepherosa Ziehau * consumes a lot of CPU cycles, so leave it off by 24006c8d8eccSSepherosa Ziehau * default. 24016c8d8eccSSepherosa Ziehau */ 2402aad4de2bSSepherosa Ziehau SYSCTL_ADD_PROC(&sc->bnx_sysctl_ctx, 24036c8d8eccSSepherosa Ziehau SYSCTL_CHILDREN(sc->bnx_sysctl_tree), OID_AUTO, 2404aad4de2bSSepherosa Ziehau "force_defrag", CTLTYPE_INT | CTLFLAG_RW, 2405aad4de2bSSepherosa Ziehau sc, 0, bnx_sysctl_force_defrag, "I", 24066c8d8eccSSepherosa Ziehau "Force defragment on TX path"); 24076c8d8eccSSepherosa Ziehau 2408472c99c8SSepherosa Ziehau SYSCTL_ADD_PROC(&sc->bnx_sysctl_ctx, 2409c9b7f592SSepherosa Ziehau SYSCTL_CHILDREN(sc->bnx_sysctl_tree), OID_AUTO, 2410472c99c8SSepherosa Ziehau "tx_wreg", CTLTYPE_INT | CTLFLAG_RW, 2411472c99c8SSepherosa Ziehau sc, 0, bnx_sysctl_tx_wreg, "I", 2412c9b7f592SSepherosa Ziehau "# of segments before writing to hardware register"); 2413c9b7f592SSepherosa Ziehau 24146c8d8eccSSepherosa Ziehau SYSCTL_ADD_PROC(&sc->bnx_sysctl_ctx, 24156c8d8eccSSepherosa Ziehau SYSCTL_CHILDREN(sc->bnx_sysctl_tree), OID_AUTO, 2416841cdf08SSepherosa Ziehau "std_refill", CTLTYPE_INT | CTLFLAG_RW, 2417841cdf08SSepherosa Ziehau sc, 0, bnx_sysctl_std_refill, "I", 2418841cdf08SSepherosa Ziehau "# of packets received before scheduling standard refilling"); 2419841cdf08SSepherosa Ziehau 2420841cdf08SSepherosa Ziehau SYSCTL_ADD_PROC(&sc->bnx_sysctl_ctx, 2421841cdf08SSepherosa Ziehau SYSCTL_CHILDREN(sc->bnx_sysctl_tree), OID_AUTO, 24226c8d8eccSSepherosa Ziehau "rx_coal_bds_int", CTLTYPE_INT | CTLFLAG_RW, 24236c8d8eccSSepherosa Ziehau sc, 0, bnx_sysctl_rx_coal_bds_int, "I", 24246c8d8eccSSepherosa Ziehau "Receive max coalesced BD count during interrupt."); 24256c8d8eccSSepherosa Ziehau SYSCTL_ADD_PROC(&sc->bnx_sysctl_ctx, 24266c8d8eccSSepherosa Ziehau SYSCTL_CHILDREN(sc->bnx_sysctl_tree), OID_AUTO, 24276c8d8eccSSepherosa Ziehau "tx_coal_bds_int", CTLTYPE_INT | CTLFLAG_RW, 24286c8d8eccSSepherosa Ziehau sc, 0, bnx_sysctl_tx_coal_bds_int, "I", 24296c8d8eccSSepherosa Ziehau "Transmit max coalesced BD count during interrupt."); 24306c8d8eccSSepherosa Ziehau 24314fa38985SSepherosa Ziehau #ifdef IFPOLL_ENABLE 24324fa38985SSepherosa Ziehau if (sc->bnx_flags & BNX_FLAG_RXTX_BUNDLE) { 24334fa38985SSepherosa Ziehau SYSCTL_ADD_PROC(&sc->bnx_sysctl_ctx, 24344fa38985SSepherosa Ziehau SYSCTL_CHILDREN(sc->bnx_sysctl_tree), OID_AUTO, 24354fa38985SSepherosa Ziehau "npoll_offset", CTLTYPE_INT | CTLFLAG_RW, 24364fa38985SSepherosa Ziehau sc, 0, bnx_sysctl_npoll_offset, "I", 24374fa38985SSepherosa Ziehau "NPOLLING cpu offset"); 24384fa38985SSepherosa Ziehau } else { 24394fa38985SSepherosa Ziehau SYSCTL_ADD_PROC(&sc->bnx_sysctl_ctx, 24404fa38985SSepherosa Ziehau SYSCTL_CHILDREN(sc->bnx_sysctl_tree), OID_AUTO, 24414fa38985SSepherosa Ziehau "npoll_rxoff", CTLTYPE_INT | CTLFLAG_RW, 24424fa38985SSepherosa Ziehau sc, 0, bnx_sysctl_npoll_rxoff, "I", 24434fa38985SSepherosa Ziehau "NPOLLING RX cpu offset"); 24444fa38985SSepherosa Ziehau SYSCTL_ADD_PROC(&sc->bnx_sysctl_ctx, 24454fa38985SSepherosa Ziehau SYSCTL_CHILDREN(sc->bnx_sysctl_tree), OID_AUTO, 24464fa38985SSepherosa Ziehau "npoll_txoff", CTLTYPE_INT | CTLFLAG_RW, 24474fa38985SSepherosa Ziehau sc, 0, bnx_sysctl_npoll_txoff, "I", 24484fa38985SSepherosa Ziehau "NPOLLING TX cpu offset"); 24494fa38985SSepherosa Ziehau } 24504fa38985SSepherosa Ziehau #endif 24514fa38985SSepherosa Ziehau 2452695a8586SSepherosa Ziehau #ifdef BNX_RSS_DEBUG 2453695a8586SSepherosa Ziehau SYSCTL_ADD_INT(&sc->bnx_sysctl_ctx, 2454695a8586SSepherosa Ziehau SYSCTL_CHILDREN(sc->bnx_sysctl_tree), OID_AUTO, 2455695a8586SSepherosa Ziehau "std_refill_mask", CTLFLAG_RD, 2456695a8586SSepherosa Ziehau &sc->bnx_rx_std_ring.bnx_rx_std_refill, 0, ""); 2457695a8586SSepherosa Ziehau SYSCTL_ADD_INT(&sc->bnx_sysctl_ctx, 2458695a8586SSepherosa Ziehau SYSCTL_CHILDREN(sc->bnx_sysctl_tree), OID_AUTO, 2459625c3ba3SSepherosa Ziehau "std_used", CTLFLAG_RD, 2460625c3ba3SSepherosa Ziehau &sc->bnx_rx_std_ring.bnx_rx_std_used, 0, ""); 2461625c3ba3SSepherosa Ziehau SYSCTL_ADD_INT(&sc->bnx_sysctl_ctx, 2462625c3ba3SSepherosa Ziehau SYSCTL_CHILDREN(sc->bnx_sysctl_tree), OID_AUTO, 2463695a8586SSepherosa Ziehau "rss_debug", CTLFLAG_RW, &sc->bnx_rss_debug, 0, ""); 2464695a8586SSepherosa Ziehau for (i = 0; i < sc->bnx_rx_retcnt; ++i) { 2465695a8586SSepherosa Ziehau ksnprintf(desc, sizeof(desc), "rx_pkt%d", i); 2466695a8586SSepherosa Ziehau SYSCTL_ADD_ULONG(&sc->bnx_sysctl_ctx, 2467695a8586SSepherosa Ziehau SYSCTL_CHILDREN(sc->bnx_sysctl_tree), OID_AUTO, 2468695a8586SSepherosa Ziehau desc, CTLFLAG_RW, &sc->bnx_rx_ret_ring[i].bnx_rx_pkt, ""); 2469625c3ba3SSepherosa Ziehau 2470625c3ba3SSepherosa Ziehau ksnprintf(desc, sizeof(desc), "rx_force_sched%d", i); 2471625c3ba3SSepherosa Ziehau SYSCTL_ADD_ULONG(&sc->bnx_sysctl_ctx, 2472625c3ba3SSepherosa Ziehau SYSCTL_CHILDREN(sc->bnx_sysctl_tree), OID_AUTO, 2473625c3ba3SSepherosa Ziehau desc, CTLFLAG_RW, 2474625c3ba3SSepherosa Ziehau &sc->bnx_rx_ret_ring[i].bnx_rx_force_sched, ""); 2475695a8586SSepherosa Ziehau } 2476695a8586SSepherosa Ziehau #endif 2477695a8586SSepherosa Ziehau #ifdef BNX_TSS_DEBUG 2478695a8586SSepherosa Ziehau for (i = 0; i < sc->bnx_tx_ringcnt; ++i) { 2479695a8586SSepherosa Ziehau ksnprintf(desc, sizeof(desc), "tx_pkt%d", i); 2480695a8586SSepherosa Ziehau SYSCTL_ADD_ULONG(&sc->bnx_sysctl_ctx, 2481695a8586SSepherosa Ziehau SYSCTL_CHILDREN(sc->bnx_sysctl_tree), OID_AUTO, 2482695a8586SSepherosa Ziehau desc, CTLFLAG_RW, &sc->bnx_tx_ring[i].bnx_tx_pkt, ""); 2483695a8586SSepherosa Ziehau } 2484695a8586SSepherosa Ziehau #endif 2485695a8586SSepherosa Ziehau 2486695a8586SSepherosa Ziehau SYSCTL_ADD_ULONG(&sc->bnx_sysctl_ctx, 2487695a8586SSepherosa Ziehau SYSCTL_CHILDREN(sc->bnx_sysctl_tree), OID_AUTO, 2488695a8586SSepherosa Ziehau "norxbds", CTLFLAG_RW, &sc->bnx_norxbds, ""); 2489695a8586SSepherosa Ziehau 2490695a8586SSepherosa Ziehau SYSCTL_ADD_ULONG(&sc->bnx_sysctl_ctx, 2491695a8586SSepherosa Ziehau SYSCTL_CHILDREN(sc->bnx_sysctl_tree), OID_AUTO, 2492695a8586SSepherosa Ziehau "errors", CTLFLAG_RW, &sc->bnx_errors, ""); 2493695a8586SSepherosa Ziehau 249466deb1c1SSepherosa Ziehau #ifdef BNX_TSO_DEBUG 249566deb1c1SSepherosa Ziehau for (i = 0; i < BNX_TSO_NSTATS; ++i) { 249666deb1c1SSepherosa Ziehau ksnprintf(desc, sizeof(desc), "tso%d", i + 1); 249766deb1c1SSepherosa Ziehau SYSCTL_ADD_ULONG(&sc->bnx_sysctl_ctx, 249866deb1c1SSepherosa Ziehau SYSCTL_CHILDREN(sc->bnx_sysctl_tree), OID_AUTO, 249966deb1c1SSepherosa Ziehau desc, CTLFLAG_RW, &sc->bnx_tsosegs[i], ""); 250066deb1c1SSepherosa Ziehau } 250166deb1c1SSepherosa Ziehau #endif 250266deb1c1SSepherosa Ziehau 25036c8d8eccSSepherosa Ziehau /* 25046c8d8eccSSepherosa Ziehau * Call MI attach routine. 25056c8d8eccSSepherosa Ziehau */ 2506329f9016SSepherosa Ziehau ether_ifattach(ifp, ether_addr, NULL); 25076c8d8eccSSepherosa Ziehau 2508329f9016SSepherosa Ziehau /* Setup TX rings and subqueues */ 2509329f9016SSepherosa Ziehau for (i = 0; i < sc->bnx_tx_ringcnt; ++i) { 2510329f9016SSepherosa Ziehau struct ifaltq_subque *ifsq = ifq_get_subq(&ifp->if_snd, i); 2511329f9016SSepherosa Ziehau struct bnx_tx_ring *txr = &sc->bnx_tx_ring[i]; 2512329f9016SSepherosa Ziehau 2513329f9016SSepherosa Ziehau ifsq_set_cpuid(ifsq, txr->bnx_tx_cpuid); 2514329f9016SSepherosa Ziehau ifsq_set_hw_serialize(ifsq, &txr->bnx_tx_serialize); 2515329f9016SSepherosa Ziehau ifsq_set_priv(ifsq, txr); 25163397dea6SSepherosa Ziehau txr->bnx_ifsq = ifsq; 2517329f9016SSepherosa Ziehau 25183397dea6SSepherosa Ziehau ifsq_watchdog_init(&txr->bnx_tx_watchdog, ifsq, bnx_watchdog); 2519695a8586SSepherosa Ziehau 2520695a8586SSepherosa Ziehau if (bootverbose) { 2521695a8586SSepherosa Ziehau device_printf(dev, "txr %d -> cpu%d\n", i, 2522695a8586SSepherosa Ziehau txr->bnx_tx_cpuid); 2523695a8586SSepherosa Ziehau } 2524329f9016SSepherosa Ziehau } 25254c77af2dSSepherosa Ziehau 25260c7da01dSSepherosa Ziehau error = bnx_setup_intr(sc); 25276c8d8eccSSepherosa Ziehau if (error) { 25286c8d8eccSSepherosa Ziehau ether_ifdetach(ifp); 25296c8d8eccSSepherosa Ziehau goto fail; 25306c8d8eccSSepherosa Ziehau } 25317dbaa833SSepherosa Ziehau bnx_set_tick_cpuid(sc, FALSE); 25328ca0f604SSepherosa Ziehau 2533841cdf08SSepherosa Ziehau /* 2534841cdf08SSepherosa Ziehau * Create RX standard ring refilling thread 2535841cdf08SSepherosa Ziehau */ 2536841cdf08SSepherosa Ziehau std_cpuid_def = device_get_unit(dev) % ncpus; 2537841cdf08SSepherosa Ziehau std_cpuid = device_getenv_int(dev, "std.cpuid", std_cpuid_def); 2538841cdf08SSepherosa Ziehau if (std_cpuid < 0 || std_cpuid >= ncpus) { 2539841cdf08SSepherosa Ziehau device_printf(dev, "invalid std.cpuid %d, use %d\n", 2540841cdf08SSepherosa Ziehau std_cpuid, std_cpuid_def); 2541841cdf08SSepherosa Ziehau std_cpuid = std_cpuid_def; 2542841cdf08SSepherosa Ziehau } 2543841cdf08SSepherosa Ziehau 2544841cdf08SSepherosa Ziehau std = &sc->bnx_rx_std_ring; 2545841cdf08SSepherosa Ziehau lwkt_create(bnx_rx_std_refill_ithread, std, NULL, 2546841cdf08SSepherosa Ziehau &std->bnx_rx_std_ithread, TDF_NOSTART | TDF_INTTHREAD, std_cpuid, 2547841cdf08SSepherosa Ziehau "%s std", device_get_nameunit(dev)); 2548841cdf08SSepherosa Ziehau lwkt_setpri(&std->bnx_rx_std_ithread, TDPRI_INT_MED); 2549841cdf08SSepherosa Ziehau std->bnx_rx_std_ithread.td_preemptable = lwkt_preempt; 2550841cdf08SSepherosa Ziehau sc->bnx_flags |= BNX_FLAG_STD_THREAD; 2551841cdf08SSepherosa Ziehau 25526c8d8eccSSepherosa Ziehau return(0); 25536c8d8eccSSepherosa Ziehau fail: 25546c8d8eccSSepherosa Ziehau bnx_detach(dev); 25556c8d8eccSSepherosa Ziehau return(error); 25566c8d8eccSSepherosa Ziehau } 25576c8d8eccSSepherosa Ziehau 25586c8d8eccSSepherosa Ziehau static int 25596c8d8eccSSepherosa Ziehau bnx_detach(device_t dev) 25606c8d8eccSSepherosa Ziehau { 25616c8d8eccSSepherosa Ziehau struct bnx_softc *sc = device_get_softc(dev); 25626c8d8eccSSepherosa Ziehau 25636c8d8eccSSepherosa Ziehau if (device_is_attached(dev)) { 25646c8d8eccSSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if; 25656c8d8eccSSepherosa Ziehau 2566329f9016SSepherosa Ziehau ifnet_serialize_all(ifp); 25676c8d8eccSSepherosa Ziehau bnx_stop(sc); 2568f33ac8a4SSepherosa Ziehau bnx_teardown_intr(sc, sc->bnx_intr_cnt); 2569329f9016SSepherosa Ziehau ifnet_deserialize_all(ifp); 25706c8d8eccSSepherosa Ziehau 25716c8d8eccSSepherosa Ziehau ether_ifdetach(ifp); 25726c8d8eccSSepherosa Ziehau } 25736c8d8eccSSepherosa Ziehau 2574841cdf08SSepherosa Ziehau if (sc->bnx_flags & BNX_FLAG_STD_THREAD) { 2575841cdf08SSepherosa Ziehau struct bnx_rx_std_ring *std = &sc->bnx_rx_std_ring; 2576841cdf08SSepherosa Ziehau 2577841cdf08SSepherosa Ziehau tsleep_interlock(std, 0); 2578695a8586SSepherosa Ziehau 2579695a8586SSepherosa Ziehau if (std->bnx_rx_std_ithread.td_gd == mycpu) { 2580695a8586SSepherosa Ziehau bnx_rx_std_refill_stop(std); 2581695a8586SSepherosa Ziehau } else { 2582695a8586SSepherosa Ziehau lwkt_send_ipiq(std->bnx_rx_std_ithread.td_gd, 2583695a8586SSepherosa Ziehau bnx_rx_std_refill_stop, std); 2584695a8586SSepherosa Ziehau } 2585695a8586SSepherosa Ziehau 2586841cdf08SSepherosa Ziehau tsleep(std, PINTERLOCKED, "bnx_detach", 0); 2587841cdf08SSepherosa Ziehau if (bootverbose) 2588841cdf08SSepherosa Ziehau device_printf(dev, "RX std ithread exited\n"); 2589695a8586SSepherosa Ziehau 2590695a8586SSepherosa Ziehau lwkt_synchronize_ipiqs("bnx_detach_ipiq"); 2591841cdf08SSepherosa Ziehau } 2592841cdf08SSepherosa Ziehau 25936c8d8eccSSepherosa Ziehau if (sc->bnx_flags & BNX_FLAG_TBI) 25946c8d8eccSSepherosa Ziehau ifmedia_removeall(&sc->bnx_ifmedia); 25956c8d8eccSSepherosa Ziehau if (sc->bnx_miibus) 25966c8d8eccSSepherosa Ziehau device_delete_child(dev, sc->bnx_miibus); 25976c8d8eccSSepherosa Ziehau bus_generic_detach(dev); 25986c8d8eccSSepherosa Ziehau 25990c7da01dSSepherosa Ziehau bnx_free_intr(sc); 26006c8d8eccSSepherosa Ziehau 2601695a8586SSepherosa Ziehau if (sc->bnx_msix_mem_res != NULL) { 2602695a8586SSepherosa Ziehau bus_release_resource(dev, SYS_RES_MEMORY, sc->bnx_msix_mem_rid, 2603695a8586SSepherosa Ziehau sc->bnx_msix_mem_res); 2604695a8586SSepherosa Ziehau } 26056c8d8eccSSepherosa Ziehau if (sc->bnx_res != NULL) { 26066c8d8eccSSepherosa Ziehau bus_release_resource(dev, SYS_RES_MEMORY, 26076c8d8eccSSepherosa Ziehau BGE_PCI_BAR0, sc->bnx_res); 26086c8d8eccSSepherosa Ziehau } 26099f5082d5SSepherosa Ziehau if (sc->bnx_res2 != NULL) { 26109f5082d5SSepherosa Ziehau bus_release_resource(dev, SYS_RES_MEMORY, 26119f5082d5SSepherosa Ziehau PCIR_BAR(2), sc->bnx_res2); 26129f5082d5SSepherosa Ziehau } 26136c8d8eccSSepherosa Ziehau 26146c8d8eccSSepherosa Ziehau if (sc->bnx_sysctl_tree != NULL) 26156c8d8eccSSepherosa Ziehau sysctl_ctx_free(&sc->bnx_sysctl_ctx); 26166c8d8eccSSepherosa Ziehau 26176c8d8eccSSepherosa Ziehau bnx_dma_free(sc); 26186c8d8eccSSepherosa Ziehau 2619329f9016SSepherosa Ziehau if (sc->bnx_serialize != NULL) 2620329f9016SSepherosa Ziehau kfree(sc->bnx_serialize, M_DEVBUF); 2621329f9016SSepherosa Ziehau 26226c8d8eccSSepherosa Ziehau return 0; 26236c8d8eccSSepherosa Ziehau } 26246c8d8eccSSepherosa Ziehau 26256c8d8eccSSepherosa Ziehau static void 26266c8d8eccSSepherosa Ziehau bnx_reset(struct bnx_softc *sc) 26276c8d8eccSSepherosa Ziehau { 26284aa71e73SSepherosa Ziehau device_t dev = sc->bnx_dev; 26294aa71e73SSepherosa Ziehau uint32_t cachesize, command, reset, mac_mode, mac_mode_mask; 26306c8d8eccSSepherosa Ziehau void (*write_op)(struct bnx_softc *, uint32_t, uint32_t); 26316c8d8eccSSepherosa Ziehau int i, val = 0; 26326c8d8eccSSepherosa Ziehau uint16_t devctl; 26336c8d8eccSSepherosa Ziehau 26344aa71e73SSepherosa Ziehau mac_mode_mask = BGE_MACMODE_HALF_DUPLEX | BGE_MACMODE_PORTMODE; 26359f5082d5SSepherosa Ziehau if (sc->bnx_mfw_flags & BNX_MFW_ON_APE) 26369f5082d5SSepherosa Ziehau mac_mode_mask |= BGE_MACMODE_APE_RX_EN | BGE_MACMODE_APE_TX_EN; 26374aa71e73SSepherosa Ziehau mac_mode = CSR_READ_4(sc, BGE_MAC_MODE) & mac_mode_mask; 26386c8d8eccSSepherosa Ziehau 26396c8d8eccSSepherosa Ziehau write_op = bnx_writemem_direct; 26406c8d8eccSSepherosa Ziehau 26419f5082d5SSepherosa Ziehau CSR_WRITE_4(sc, BGE_NVRAM_SWARB, BGE_NVRAMSWARB_SET1); 26429f5082d5SSepherosa Ziehau for (i = 0; i < 8000; i++) { 26439f5082d5SSepherosa Ziehau if (CSR_READ_4(sc, BGE_NVRAM_SWARB) & BGE_NVRAMSWARB_GNT1) 26449f5082d5SSepherosa Ziehau break; 26459f5082d5SSepherosa Ziehau DELAY(20); 26469f5082d5SSepherosa Ziehau } 26479f5082d5SSepherosa Ziehau if (i == 8000) 26489f5082d5SSepherosa Ziehau if_printf(&sc->arpcom.ac_if, "NVRAM lock timedout!\n"); 26499f5082d5SSepherosa Ziehau 26509f5082d5SSepherosa Ziehau /* Take APE lock when performing reset. */ 26519f5082d5SSepherosa Ziehau bnx_ape_lock(sc, BGE_APE_LOCK_GRC); 26529f5082d5SSepherosa Ziehau 26536c8d8eccSSepherosa Ziehau /* Save some important PCI state. */ 26546c8d8eccSSepherosa Ziehau cachesize = pci_read_config(dev, BGE_PCI_CACHESZ, 4); 26556c8d8eccSSepherosa Ziehau command = pci_read_config(dev, BGE_PCI_CMD, 4); 26566c8d8eccSSepherosa Ziehau 26576c8d8eccSSepherosa Ziehau pci_write_config(dev, BGE_PCI_MISC_CTL, 26586c8d8eccSSepherosa Ziehau BGE_PCIMISCCTL_INDIRECT_ACCESS|BGE_PCIMISCCTL_MASK_PCI_INTR| 26596c8d8eccSSepherosa Ziehau BGE_HIF_SWAP_OPTIONS|BGE_PCIMISCCTL_PCISTATE_RW| 26606c8d8eccSSepherosa Ziehau BGE_PCIMISCCTL_TAGGED_STATUS, 4); 26616c8d8eccSSepherosa Ziehau 26626c8d8eccSSepherosa Ziehau /* Disable fastboot on controllers that support it. */ 26636c8d8eccSSepherosa Ziehau if (bootverbose) 26646c8d8eccSSepherosa Ziehau if_printf(&sc->arpcom.ac_if, "Disabling fastboot\n"); 26656c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_FASTBOOT_PC, 0x0); 26666c8d8eccSSepherosa Ziehau 26676c8d8eccSSepherosa Ziehau /* 26686c8d8eccSSepherosa Ziehau * Write the magic number to SRAM at offset 0xB50. 26696c8d8eccSSepherosa Ziehau * When firmware finishes its initialization it will 26700551ac06SSepherosa Ziehau * write ~BGE_SRAM_FW_MB_MAGIC to the same location. 26716c8d8eccSSepherosa Ziehau */ 26720551ac06SSepherosa Ziehau bnx_writemem_ind(sc, BGE_SRAM_FW_MB, BGE_SRAM_FW_MB_MAGIC); 26736c8d8eccSSepherosa Ziehau 26746c8d8eccSSepherosa Ziehau reset = BGE_MISCCFG_RESET_CORE_CLOCKS|(65<<1); 26756c8d8eccSSepherosa Ziehau 26766c8d8eccSSepherosa Ziehau /* XXX: Broadcom Linux driver. */ 26776c8d8eccSSepherosa Ziehau /* Force PCI-E 1.0a mode */ 26783730a14dSSepherosa Ziehau if (!BNX_IS_57765_PLUS(sc) && 26796c8d8eccSSepherosa Ziehau CSR_READ_4(sc, BGE_PCIE_PHY_TSTCTL) == 26806c8d8eccSSepherosa Ziehau (BGE_PCIE_PHY_TSTCTL_PSCRAM | 26816c8d8eccSSepherosa Ziehau BGE_PCIE_PHY_TSTCTL_PCIE10)) { 26826c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_PCIE_PHY_TSTCTL, 26836c8d8eccSSepherosa Ziehau BGE_PCIE_PHY_TSTCTL_PSCRAM); 26846c8d8eccSSepherosa Ziehau } 26856c8d8eccSSepherosa Ziehau if (sc->bnx_chipid != BGE_CHIPID_BCM5750_A0) { 26866c8d8eccSSepherosa Ziehau /* Prevent PCIE link training during global reset */ 26876c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_MISC_CFG, (1<<29)); 26886c8d8eccSSepherosa Ziehau reset |= (1<<29); 26896c8d8eccSSepherosa Ziehau } 26906c8d8eccSSepherosa Ziehau 26916c8d8eccSSepherosa Ziehau /* 26926c8d8eccSSepherosa Ziehau * Set GPHY Power Down Override to leave GPHY 26936c8d8eccSSepherosa Ziehau * powered up in D0 uninitialized. 26946c8d8eccSSepherosa Ziehau */ 26956c8d8eccSSepherosa Ziehau if ((sc->bnx_flags & BNX_FLAG_CPMU) == 0) 26966c8d8eccSSepherosa Ziehau reset |= BGE_MISCCFG_GPHY_PD_OVERRIDE; 26976c8d8eccSSepherosa Ziehau 26986c8d8eccSSepherosa Ziehau /* Issue global reset */ 26996c8d8eccSSepherosa Ziehau write_op(sc, BGE_MISC_CFG, reset); 27006c8d8eccSSepherosa Ziehau 27014aa71e73SSepherosa Ziehau DELAY(100 * 1000); 27026c8d8eccSSepherosa Ziehau 27036c8d8eccSSepherosa Ziehau /* XXX: Broadcom Linux driver. */ 27046c8d8eccSSepherosa Ziehau if (sc->bnx_chipid == BGE_CHIPID_BCM5750_A0) { 27056c8d8eccSSepherosa Ziehau uint32_t v; 27066c8d8eccSSepherosa Ziehau 27076c8d8eccSSepherosa Ziehau DELAY(500000); /* wait for link training to complete */ 27086c8d8eccSSepherosa Ziehau v = pci_read_config(dev, 0xc4, 4); 27096c8d8eccSSepherosa Ziehau pci_write_config(dev, 0xc4, v | (1<<15), 4); 27106c8d8eccSSepherosa Ziehau } 27116c8d8eccSSepherosa Ziehau 27126c8d8eccSSepherosa Ziehau devctl = pci_read_config(dev, sc->bnx_pciecap + PCIER_DEVCTRL, 2); 27136c8d8eccSSepherosa Ziehau 27146c8d8eccSSepherosa Ziehau /* Disable no snoop and disable relaxed ordering. */ 27156c8d8eccSSepherosa Ziehau devctl &= ~(PCIEM_DEVCTL_RELAX_ORDER | PCIEM_DEVCTL_NOSNOOP); 27166c8d8eccSSepherosa Ziehau 27176c8d8eccSSepherosa Ziehau /* Old PCI-E chips only support 128 bytes Max PayLoad Size. */ 27186c8d8eccSSepherosa Ziehau if ((sc->bnx_flags & BNX_FLAG_CPMU) == 0) { 27196c8d8eccSSepherosa Ziehau devctl &= ~PCIEM_DEVCTL_MAX_PAYLOAD_MASK; 27206c8d8eccSSepherosa Ziehau devctl |= PCIEM_DEVCTL_MAX_PAYLOAD_128; 27216c8d8eccSSepherosa Ziehau } 27226c8d8eccSSepherosa Ziehau 27236c8d8eccSSepherosa Ziehau pci_write_config(dev, sc->bnx_pciecap + PCIER_DEVCTRL, 27246c8d8eccSSepherosa Ziehau devctl, 2); 27256c8d8eccSSepherosa Ziehau 27266c8d8eccSSepherosa Ziehau /* Clear error status. */ 27276c8d8eccSSepherosa Ziehau pci_write_config(dev, sc->bnx_pciecap + PCIER_DEVSTS, 27286c8d8eccSSepherosa Ziehau PCIEM_DEVSTS_CORR_ERR | 27296c8d8eccSSepherosa Ziehau PCIEM_DEVSTS_NFATAL_ERR | 27306c8d8eccSSepherosa Ziehau PCIEM_DEVSTS_FATAL_ERR | 27316c8d8eccSSepherosa Ziehau PCIEM_DEVSTS_UNSUPP_REQ, 2); 27326c8d8eccSSepherosa Ziehau 27336c8d8eccSSepherosa Ziehau /* Reset some of the PCI state that got zapped by reset */ 27346c8d8eccSSepherosa Ziehau pci_write_config(dev, BGE_PCI_MISC_CTL, 27356c8d8eccSSepherosa Ziehau BGE_PCIMISCCTL_INDIRECT_ACCESS|BGE_PCIMISCCTL_MASK_PCI_INTR| 27366c8d8eccSSepherosa Ziehau BGE_HIF_SWAP_OPTIONS|BGE_PCIMISCCTL_PCISTATE_RW| 27376c8d8eccSSepherosa Ziehau BGE_PCIMISCCTL_TAGGED_STATUS, 4); 27384aa71e73SSepherosa Ziehau val = BGE_PCISTATE_ROM_ENABLE | BGE_PCISTATE_ROM_RETRY_ENABLE; 27399f5082d5SSepherosa Ziehau if (sc->bnx_mfw_flags & BNX_MFW_ON_APE) { 27409f5082d5SSepherosa Ziehau val |= BGE_PCISTATE_ALLOW_APE_CTLSPC_WR | 27419f5082d5SSepherosa Ziehau BGE_PCISTATE_ALLOW_APE_SHMEM_WR | 27429f5082d5SSepherosa Ziehau BGE_PCISTATE_ALLOW_APE_PSPACE_WR; 27439f5082d5SSepherosa Ziehau } 27444aa71e73SSepherosa Ziehau pci_write_config(dev, BGE_PCI_PCISTATE, val, 4); 27456c8d8eccSSepherosa Ziehau pci_write_config(dev, BGE_PCI_CACHESZ, cachesize, 4); 27466c8d8eccSSepherosa Ziehau pci_write_config(dev, BGE_PCI_CMD, command, 4); 27476c8d8eccSSepherosa Ziehau 27486c8d8eccSSepherosa Ziehau /* Enable memory arbiter */ 27496c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_MARB_MODE, BGE_MARBMODE_ENABLE); 27506c8d8eccSSepherosa Ziehau 27514aa71e73SSepherosa Ziehau /* Fix up byte swapping */ 27524aa71e73SSepherosa Ziehau CSR_WRITE_4(sc, BGE_MODE_CTL, bnx_dma_swap_options(sc)); 27534aa71e73SSepherosa Ziehau 27544aa71e73SSepherosa Ziehau val = CSR_READ_4(sc, BGE_MAC_MODE); 27554aa71e73SSepherosa Ziehau val = (val & ~mac_mode_mask) | mac_mode; 27564aa71e73SSepherosa Ziehau CSR_WRITE_4(sc, BGE_MAC_MODE, val); 27574aa71e73SSepherosa Ziehau DELAY(40); 27584aa71e73SSepherosa Ziehau 27599f5082d5SSepherosa Ziehau bnx_ape_unlock(sc, BGE_APE_LOCK_GRC); 27609f5082d5SSepherosa Ziehau 27616c8d8eccSSepherosa Ziehau /* 27626c8d8eccSSepherosa Ziehau * Poll until we see the 1's complement of the magic number. 2763ddd93a5cSSepherosa Ziehau * This indicates that the firmware initialization is complete. 27646c8d8eccSSepherosa Ziehau */ 27656c8d8eccSSepherosa Ziehau for (i = 0; i < BNX_FIRMWARE_TIMEOUT; i++) { 27660551ac06SSepherosa Ziehau val = bnx_readmem_ind(sc, BGE_SRAM_FW_MB); 27670551ac06SSepherosa Ziehau if (val == ~BGE_SRAM_FW_MB_MAGIC) 27686c8d8eccSSepherosa Ziehau break; 27696c8d8eccSSepherosa Ziehau DELAY(10); 27706c8d8eccSSepherosa Ziehau } 27716c8d8eccSSepherosa Ziehau if (i == BNX_FIRMWARE_TIMEOUT) { 27726c8d8eccSSepherosa Ziehau if_printf(&sc->arpcom.ac_if, "firmware handshake " 27736c8d8eccSSepherosa Ziehau "timed out, found 0x%08x\n", val); 27746c8d8eccSSepherosa Ziehau } 27756c8d8eccSSepherosa Ziehau 27766c8d8eccSSepherosa Ziehau /* BCM57765 A0 needs additional time before accessing. */ 27776c8d8eccSSepherosa Ziehau if (sc->bnx_chipid == BGE_CHIPID_BCM57765_A0) 27786c8d8eccSSepherosa Ziehau DELAY(10 * 1000); 27796c8d8eccSSepherosa Ziehau 27806c8d8eccSSepherosa Ziehau /* 27816c8d8eccSSepherosa Ziehau * The 5704 in TBI mode apparently needs some special 27826c8d8eccSSepherosa Ziehau * adjustment to insure the SERDES drive level is set 27836c8d8eccSSepherosa Ziehau * to 1.2V. 27846c8d8eccSSepherosa Ziehau */ 27856c8d8eccSSepherosa Ziehau if (sc->bnx_asicrev == BGE_ASICREV_BCM5704 && 27866c8d8eccSSepherosa Ziehau (sc->bnx_flags & BNX_FLAG_TBI)) { 27876c8d8eccSSepherosa Ziehau uint32_t serdescfg; 27886c8d8eccSSepherosa Ziehau 27896c8d8eccSSepherosa Ziehau serdescfg = CSR_READ_4(sc, BGE_SERDES_CFG); 27906c8d8eccSSepherosa Ziehau serdescfg = (serdescfg & ~0xFFF) | 0x880; 27916c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_SERDES_CFG, serdescfg); 27926c8d8eccSSepherosa Ziehau } 27936c8d8eccSSepherosa Ziehau 27947892075dSSepherosa Ziehau CSR_WRITE_4(sc, BGE_MI_MODE, 27957892075dSSepherosa Ziehau sc->bnx_mi_mode & ~BGE_MIMODE_AUTOPOLL); 27967892075dSSepherosa Ziehau DELAY(80); 27977892075dSSepherosa Ziehau 27986c8d8eccSSepherosa Ziehau /* XXX: Broadcom Linux driver. */ 27993730a14dSSepherosa Ziehau if (!BNX_IS_57765_PLUS(sc)) { 28006c8d8eccSSepherosa Ziehau uint32_t v; 28016c8d8eccSSepherosa Ziehau 28026c8d8eccSSepherosa Ziehau /* Enable Data FIFO protection. */ 2803f1f34fc4SSepherosa Ziehau v = CSR_READ_4(sc, BGE_PCIE_TLDLPL_PORT); 2804f1f34fc4SSepherosa Ziehau CSR_WRITE_4(sc, BGE_PCIE_TLDLPL_PORT, v | (1 << 25)); 28056c8d8eccSSepherosa Ziehau } 28066c8d8eccSSepherosa Ziehau 28076c8d8eccSSepherosa Ziehau DELAY(10000); 28086c8d8eccSSepherosa Ziehau 28096c8d8eccSSepherosa Ziehau if (sc->bnx_asicrev == BGE_ASICREV_BCM5720) { 28106c8d8eccSSepherosa Ziehau BNX_CLRBIT(sc, BGE_CPMU_CLCK_ORIDE, 28116c8d8eccSSepherosa Ziehau CPMU_CLCK_ORIDE_MAC_ORIDE_EN); 28126c8d8eccSSepherosa Ziehau } 28136c8d8eccSSepherosa Ziehau } 28146c8d8eccSSepherosa Ziehau 28156c8d8eccSSepherosa Ziehau /* 28166c8d8eccSSepherosa Ziehau * Frame reception handling. This is called if there's a frame 28176c8d8eccSSepherosa Ziehau * on the receive return list. 28186c8d8eccSSepherosa Ziehau * 28196c8d8eccSSepherosa Ziehau * Note: we have to be able to handle two possibilities here: 28206c8d8eccSSepherosa Ziehau * 1) the frame is from the jumbo recieve ring 28216c8d8eccSSepherosa Ziehau * 2) the frame is from the standard receive ring 28226c8d8eccSSepherosa Ziehau */ 28236c8d8eccSSepherosa Ziehau 28246c8d8eccSSepherosa Ziehau static void 2825beedf5beSSepherosa Ziehau bnx_rxeof(struct bnx_rx_ret_ring *ret, uint16_t rx_prod, int count) 28266c8d8eccSSepherosa Ziehau { 2827beedf5beSSepherosa Ziehau struct bnx_softc *sc = ret->bnx_sc; 2828beedf5beSSepherosa Ziehau struct bnx_rx_std_ring *std = ret->bnx_std; 2829beedf5beSSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if; 2830*ff37a356SSepherosa Ziehau int std_used = 0, cpuid = mycpuid; 28316c8d8eccSSepherosa Ziehau 2832beedf5beSSepherosa Ziehau while (ret->bnx_rx_saved_considx != rx_prod && count != 0) { 2833b19ddf7eSSepherosa Ziehau struct pktinfo pi0, *pi = NULL; 28346c8d8eccSSepherosa Ziehau struct bge_rx_bd *cur_rx; 2835841cdf08SSepherosa Ziehau struct bnx_rx_buf *rb; 28366c8d8eccSSepherosa Ziehau uint32_t rxidx; 28376c8d8eccSSepherosa Ziehau struct mbuf *m = NULL; 28386c8d8eccSSepherosa Ziehau uint16_t vlan_tag = 0; 28396c8d8eccSSepherosa Ziehau int have_tag = 0; 28406c8d8eccSSepherosa Ziehau 284197381780SSepherosa Ziehau --count; 284297381780SSepherosa Ziehau 2843beedf5beSSepherosa Ziehau cur_rx = &ret->bnx_rx_ret_ring[ret->bnx_rx_saved_considx]; 28446c8d8eccSSepherosa Ziehau 28456c8d8eccSSepherosa Ziehau rxidx = cur_rx->bge_idx; 2846695a8586SSepherosa Ziehau KKASSERT(rxidx < BGE_STD_RX_RING_CNT); 2847695a8586SSepherosa Ziehau 2848beedf5beSSepherosa Ziehau BNX_INC(ret->bnx_rx_saved_considx, BNX_RETURN_RING_CNT); 2849695a8586SSepherosa Ziehau #ifdef BNX_RSS_DEBUG 2850695a8586SSepherosa Ziehau ret->bnx_rx_pkt++; 2851695a8586SSepherosa Ziehau #endif 28526c8d8eccSSepherosa Ziehau 28536c8d8eccSSepherosa Ziehau if (cur_rx->bge_flags & BGE_RXBDFLAG_VLAN_TAG) { 28546c8d8eccSSepherosa Ziehau have_tag = 1; 28556c8d8eccSSepherosa Ziehau vlan_tag = cur_rx->bge_vlan_tag; 28566c8d8eccSSepherosa Ziehau } 28576c8d8eccSSepherosa Ziehau 2858625c3ba3SSepherosa Ziehau if (ret->bnx_rx_cnt >= ret->bnx_rx_cntmax) { 2859625c3ba3SSepherosa Ziehau atomic_add_int(&std->bnx_rx_std_used, std_used); 2860625c3ba3SSepherosa Ziehau std_used = 0; 2861625c3ba3SSepherosa Ziehau 2862695a8586SSepherosa Ziehau bnx_rx_std_refill_sched(ret, std); 2863625c3ba3SSepherosa Ziehau } 2864841cdf08SSepherosa Ziehau ret->bnx_rx_cnt++; 2865625c3ba3SSepherosa Ziehau ++std_used; 28666c8d8eccSSepherosa Ziehau 2867841cdf08SSepherosa Ziehau rb = &std->bnx_rx_std_buf[rxidx]; 2868841cdf08SSepherosa Ziehau m = rb->bnx_rx_mbuf; 28696c8d8eccSSepherosa Ziehau if (cur_rx->bge_flags & BGE_RXBDFLAG_ERROR) { 2870d40991efSSepherosa Ziehau IFNET_STAT_INC(ifp, ierrors, 1); 2871841cdf08SSepherosa Ziehau cpu_sfence(); 2872841cdf08SSepherosa Ziehau rb->bnx_rx_refilled = 1; 28736c8d8eccSSepherosa Ziehau continue; 28746c8d8eccSSepherosa Ziehau } 2875841cdf08SSepherosa Ziehau if (bnx_newbuf_std(ret, rxidx, 0)) { 2876d40991efSSepherosa Ziehau IFNET_STAT_INC(ifp, ierrors, 1); 28776c8d8eccSSepherosa Ziehau continue; 28786c8d8eccSSepherosa Ziehau } 28796c8d8eccSSepherosa Ziehau 2880d40991efSSepherosa Ziehau IFNET_STAT_INC(ifp, ipackets, 1); 28816c8d8eccSSepherosa Ziehau m->m_pkthdr.len = m->m_len = cur_rx->bge_len - ETHER_CRC_LEN; 28826c8d8eccSSepherosa Ziehau m->m_pkthdr.rcvif = ifp; 28836c8d8eccSSepherosa Ziehau 28846c8d8eccSSepherosa Ziehau if ((ifp->if_capenable & IFCAP_RXCSUM) && 28856c8d8eccSSepherosa Ziehau (cur_rx->bge_flags & BGE_RXBDFLAG_IPV6) == 0) { 28866c8d8eccSSepherosa Ziehau if (cur_rx->bge_flags & BGE_RXBDFLAG_IP_CSUM) { 28876c8d8eccSSepherosa Ziehau m->m_pkthdr.csum_flags |= CSUM_IP_CHECKED; 28886c8d8eccSSepherosa Ziehau if ((cur_rx->bge_error_flag & 28896c8d8eccSSepherosa Ziehau BGE_RXERRFLAG_IP_CSUM_NOK) == 0) 28906c8d8eccSSepherosa Ziehau m->m_pkthdr.csum_flags |= CSUM_IP_VALID; 28916c8d8eccSSepherosa Ziehau } 28926c8d8eccSSepherosa Ziehau if (cur_rx->bge_flags & BGE_RXBDFLAG_TCP_UDP_CSUM) { 28936c8d8eccSSepherosa Ziehau m->m_pkthdr.csum_data = 28946c8d8eccSSepherosa Ziehau cur_rx->bge_tcp_udp_csum; 28956c8d8eccSSepherosa Ziehau m->m_pkthdr.csum_flags |= CSUM_DATA_VALID | 28966c8d8eccSSepherosa Ziehau CSUM_PSEUDO_HDR; 28976c8d8eccSSepherosa Ziehau } 28986c8d8eccSSepherosa Ziehau } 2899b19ddf7eSSepherosa Ziehau if (ifp->if_capenable & IFCAP_RSS) { 2900b19ddf7eSSepherosa Ziehau pi = bnx_rss_info(&pi0, cur_rx); 2901b19ddf7eSSepherosa Ziehau if (pi != NULL && 2902b19ddf7eSSepherosa Ziehau (cur_rx->bge_flags & BGE_RXBDFLAG_RSS_HASH)) { 2903b19ddf7eSSepherosa Ziehau m->m_flags |= M_HASH; 2904b19ddf7eSSepherosa Ziehau m->m_pkthdr.hash = 2905b19ddf7eSSepherosa Ziehau toeplitz_hash(cur_rx->bge_hash); 2906b19ddf7eSSepherosa Ziehau } 2907b19ddf7eSSepherosa Ziehau } 29086c8d8eccSSepherosa Ziehau 29096c8d8eccSSepherosa Ziehau /* 29106c8d8eccSSepherosa Ziehau * If we received a packet with a vlan tag, pass it 29116c8d8eccSSepherosa Ziehau * to vlan_input() instead of ether_input(). 29126c8d8eccSSepherosa Ziehau */ 29136c8d8eccSSepherosa Ziehau if (have_tag) { 29146c8d8eccSSepherosa Ziehau m->m_flags |= M_VLANTAG; 29156c8d8eccSSepherosa Ziehau m->m_pkthdr.ether_vlantag = vlan_tag; 29166c8d8eccSSepherosa Ziehau } 2917*ff37a356SSepherosa Ziehau ether_input_pkt(ifp, m, pi, cpuid); 29186c8d8eccSSepherosa Ziehau } 2919ac2936fdSSepherosa Ziehau bnx_writembx(sc, ret->bnx_rx_mbx, ret->bnx_rx_saved_considx); 2920695a8586SSepherosa Ziehau 2921625c3ba3SSepherosa Ziehau if (std_used > 0) { 2922625c3ba3SSepherosa Ziehau int cur_std_used; 2923625c3ba3SSepherosa Ziehau 2924625c3ba3SSepherosa Ziehau cur_std_used = atomic_fetchadd_int(&std->bnx_rx_std_used, 2925625c3ba3SSepherosa Ziehau std_used); 2926625c3ba3SSepherosa Ziehau if (cur_std_used + std_used >= (BGE_STD_RX_RING_CNT / 2)) { 2927625c3ba3SSepherosa Ziehau #ifdef BNX_RSS_DEBUG 2928625c3ba3SSepherosa Ziehau ret->bnx_rx_force_sched++; 2929625c3ba3SSepherosa Ziehau #endif 2930695a8586SSepherosa Ziehau bnx_rx_std_refill_sched(ret, std); 29316c8d8eccSSepherosa Ziehau } 2932625c3ba3SSepherosa Ziehau } 2933625c3ba3SSepherosa Ziehau } 29346c8d8eccSSepherosa Ziehau 29356c8d8eccSSepherosa Ziehau static void 293633a04907SSepherosa Ziehau bnx_txeof(struct bnx_tx_ring *txr, uint16_t tx_cons) 29376c8d8eccSSepherosa Ziehau { 293833a04907SSepherosa Ziehau struct ifnet *ifp = &txr->bnx_sc->arpcom.ac_if; 29396c8d8eccSSepherosa Ziehau 29406c8d8eccSSepherosa Ziehau /* 29416c8d8eccSSepherosa Ziehau * Go through our tx ring and free mbufs for those 29426c8d8eccSSepherosa Ziehau * frames that have been sent. 29436c8d8eccSSepherosa Ziehau */ 294433a04907SSepherosa Ziehau while (txr->bnx_tx_saved_considx != tx_cons) { 2945fa4b1067SSepherosa Ziehau struct bnx_tx_buf *buf; 29466c8d8eccSSepherosa Ziehau uint32_t idx = 0; 29476c8d8eccSSepherosa Ziehau 294833a04907SSepherosa Ziehau idx = txr->bnx_tx_saved_considx; 2949fa4b1067SSepherosa Ziehau buf = &txr->bnx_tx_buf[idx]; 2950fa4b1067SSepherosa Ziehau if (buf->bnx_tx_mbuf != NULL) { 2951d40991efSSepherosa Ziehau IFNET_STAT_INC(ifp, opackets, 1); 2952695a8586SSepherosa Ziehau #ifdef BNX_TSS_DEBUG 2953695a8586SSepherosa Ziehau txr->bnx_tx_pkt++; 2954695a8586SSepherosa Ziehau #endif 295533a04907SSepherosa Ziehau bus_dmamap_unload(txr->bnx_tx_mtag, 2956fa4b1067SSepherosa Ziehau buf->bnx_tx_dmamap); 2957fa4b1067SSepherosa Ziehau m_freem(buf->bnx_tx_mbuf); 2958fa4b1067SSepherosa Ziehau buf->bnx_tx_mbuf = NULL; 29596c8d8eccSSepherosa Ziehau } 2960fa639b88SSepherosa Ziehau txr->bnx_tx_cnt--; 296133a04907SSepherosa Ziehau BNX_INC(txr->bnx_tx_saved_considx, BGE_TX_RING_CNT); 29626c8d8eccSSepherosa Ziehau } 29636c8d8eccSSepherosa Ziehau 2964fa639b88SSepherosa Ziehau if ((BGE_TX_RING_CNT - txr->bnx_tx_cnt) >= 29656c8d8eccSSepherosa Ziehau (BNX_NSEG_RSVD + BNX_NSEG_SPARE)) 29663397dea6SSepherosa Ziehau ifsq_clr_oactive(txr->bnx_ifsq); 29676c8d8eccSSepherosa Ziehau 2968fa639b88SSepherosa Ziehau if (txr->bnx_tx_cnt == 0) 29693397dea6SSepherosa Ziehau txr->bnx_tx_watchdog.wd_timer = 0; 29706c8d8eccSSepherosa Ziehau 29713397dea6SSepherosa Ziehau if (!ifsq_is_empty(txr->bnx_ifsq)) 29723397dea6SSepherosa Ziehau ifsq_devstart(txr->bnx_ifsq); 29736c8d8eccSSepherosa Ziehau } 29746c8d8eccSSepherosa Ziehau 297524e16e4bSSepherosa Ziehau static int 2976695a8586SSepherosa Ziehau bnx_handle_status(struct bnx_softc *sc) 2977695a8586SSepherosa Ziehau { 2978695a8586SSepherosa Ziehau uint32_t status; 297924e16e4bSSepherosa Ziehau int handle = 0; 2980695a8586SSepherosa Ziehau 2981695a8586SSepherosa Ziehau status = *sc->bnx_hw_status; 2982695a8586SSepherosa Ziehau 2983695a8586SSepherosa Ziehau if (status & BGE_STATFLAG_ERROR) { 2984695a8586SSepherosa Ziehau uint32_t val; 2985695a8586SSepherosa Ziehau int reset = 0; 2986695a8586SSepherosa Ziehau 2987695a8586SSepherosa Ziehau sc->bnx_errors++; 2988695a8586SSepherosa Ziehau 2989695a8586SSepherosa Ziehau val = CSR_READ_4(sc, BGE_FLOW_ATTN); 2990695a8586SSepherosa Ziehau if (val & ~BGE_FLOWATTN_MB_LOWAT) { 2991695a8586SSepherosa Ziehau if_printf(&sc->arpcom.ac_if, 2992695a8586SSepherosa Ziehau "flow attn 0x%08x\n", val); 2993695a8586SSepherosa Ziehau reset = 1; 2994695a8586SSepherosa Ziehau } 2995695a8586SSepherosa Ziehau 2996695a8586SSepherosa Ziehau val = CSR_READ_4(sc, BGE_MSI_STATUS); 2997695a8586SSepherosa Ziehau if (val & ~BGE_MSISTAT_MSI_PCI_REQ) { 2998695a8586SSepherosa Ziehau if_printf(&sc->arpcom.ac_if, 2999695a8586SSepherosa Ziehau "msi status 0x%08x\n", val); 3000695a8586SSepherosa Ziehau reset = 1; 3001695a8586SSepherosa Ziehau } 3002695a8586SSepherosa Ziehau 3003695a8586SSepherosa Ziehau val = CSR_READ_4(sc, BGE_RDMA_STATUS); 3004695a8586SSepherosa Ziehau if (val) { 3005695a8586SSepherosa Ziehau if_printf(&sc->arpcom.ac_if, 3006695a8586SSepherosa Ziehau "rmda status 0x%08x\n", val); 3007695a8586SSepherosa Ziehau reset = 1; 3008695a8586SSepherosa Ziehau } 3009695a8586SSepherosa Ziehau 3010695a8586SSepherosa Ziehau val = CSR_READ_4(sc, BGE_WDMA_STATUS); 3011695a8586SSepherosa Ziehau if (val) { 3012695a8586SSepherosa Ziehau if_printf(&sc->arpcom.ac_if, 3013695a8586SSepherosa Ziehau "wdma status 0x%08x\n", val); 3014695a8586SSepherosa Ziehau reset = 1; 3015695a8586SSepherosa Ziehau } 3016695a8586SSepherosa Ziehau 3017695a8586SSepherosa Ziehau if (reset) { 3018695a8586SSepherosa Ziehau bnx_serialize_skipmain(sc); 3019695a8586SSepherosa Ziehau bnx_init(sc); 3020695a8586SSepherosa Ziehau bnx_deserialize_skipmain(sc); 3021695a8586SSepherosa Ziehau } 302224e16e4bSSepherosa Ziehau handle = 1; 3023695a8586SSepherosa Ziehau } 3024695a8586SSepherosa Ziehau 302524e16e4bSSepherosa Ziehau if ((status & BGE_STATFLAG_LINKSTATE_CHANGED) || sc->bnx_link_evt) { 302624e16e4bSSepherosa Ziehau if (bootverbose) { 302724e16e4bSSepherosa Ziehau if_printf(&sc->arpcom.ac_if, "link change, " 302824e16e4bSSepherosa Ziehau "link_evt %d\n", sc->bnx_link_evt); 302924e16e4bSSepherosa Ziehau } 3030695a8586SSepherosa Ziehau bnx_link_poll(sc); 303124e16e4bSSepherosa Ziehau handle = 1; 303224e16e4bSSepherosa Ziehau } 303324e16e4bSSepherosa Ziehau 303424e16e4bSSepherosa Ziehau return handle; 3035695a8586SSepherosa Ziehau } 3036695a8586SSepherosa Ziehau 303739a8d43aSSepherosa Ziehau #ifdef IFPOLL_ENABLE 30386c8d8eccSSepherosa Ziehau 30396c8d8eccSSepherosa Ziehau static void 30404fa38985SSepherosa Ziehau bnx_npoll_rx(struct ifnet *ifp __unused, void *xret, int cycle) 30414fa38985SSepherosa Ziehau { 30424fa38985SSepherosa Ziehau struct bnx_rx_ret_ring *ret = xret; 30434fa38985SSepherosa Ziehau uint16_t rx_prod; 30444fa38985SSepherosa Ziehau 30454fa38985SSepherosa Ziehau ASSERT_SERIALIZED(&ret->bnx_rx_ret_serialize); 30464fa38985SSepherosa Ziehau 30474fa38985SSepherosa Ziehau ret->bnx_saved_status_tag = *ret->bnx_hw_status_tag; 30484fa38985SSepherosa Ziehau cpu_lfence(); 30494fa38985SSepherosa Ziehau 30504fa38985SSepherosa Ziehau rx_prod = *ret->bnx_rx_considx; 30514fa38985SSepherosa Ziehau if (ret->bnx_rx_saved_considx != rx_prod) 30524fa38985SSepherosa Ziehau bnx_rxeof(ret, rx_prod, cycle); 30534fa38985SSepherosa Ziehau } 30544fa38985SSepherosa Ziehau 30554fa38985SSepherosa Ziehau static void 3056695a8586SSepherosa Ziehau bnx_npoll_tx_notag(struct ifnet *ifp __unused, void *xtxr, int cycle __unused) 30574fa38985SSepherosa Ziehau { 30584fa38985SSepherosa Ziehau struct bnx_tx_ring *txr = xtxr; 30594fa38985SSepherosa Ziehau uint16_t tx_cons; 30604fa38985SSepherosa Ziehau 30614fa38985SSepherosa Ziehau ASSERT_SERIALIZED(&txr->bnx_tx_serialize); 30624fa38985SSepherosa Ziehau 30634fa38985SSepherosa Ziehau tx_cons = *txr->bnx_tx_considx; 30644fa38985SSepherosa Ziehau if (txr->bnx_tx_saved_considx != tx_cons) 30654fa38985SSepherosa Ziehau bnx_txeof(txr, tx_cons); 30664fa38985SSepherosa Ziehau } 30674fa38985SSepherosa Ziehau 30684fa38985SSepherosa Ziehau static void 3069695a8586SSepherosa Ziehau bnx_npoll_tx(struct ifnet *ifp, void *xtxr, int cycle) 3070695a8586SSepherosa Ziehau { 3071695a8586SSepherosa Ziehau struct bnx_tx_ring *txr = xtxr; 3072695a8586SSepherosa Ziehau 3073695a8586SSepherosa Ziehau ASSERT_SERIALIZED(&txr->bnx_tx_serialize); 3074695a8586SSepherosa Ziehau 3075695a8586SSepherosa Ziehau txr->bnx_saved_status_tag = *txr->bnx_hw_status_tag; 3076695a8586SSepherosa Ziehau cpu_lfence(); 3077695a8586SSepherosa Ziehau bnx_npoll_tx_notag(ifp, txr, cycle); 3078695a8586SSepherosa Ziehau } 3079695a8586SSepherosa Ziehau 3080695a8586SSepherosa Ziehau static void 3081695a8586SSepherosa Ziehau bnx_npoll_status_notag(struct ifnet *ifp) 30824fa38985SSepherosa Ziehau { 30834fa38985SSepherosa Ziehau struct bnx_softc *sc = ifp->if_softc; 30844fa38985SSepherosa Ziehau 30854fa38985SSepherosa Ziehau ASSERT_SERIALIZED(&sc->bnx_main_serialize); 30864fa38985SSepherosa Ziehau 308724e16e4bSSepherosa Ziehau if (bnx_handle_status(sc)) { 308824e16e4bSSepherosa Ziehau /* 308924e16e4bSSepherosa Ziehau * Status changes are handled; force the chip to 309024e16e4bSSepherosa Ziehau * update the status block to reflect whether there 309124e16e4bSSepherosa Ziehau * are more status changes or not, else staled status 309224e16e4bSSepherosa Ziehau * changes are always seen. 309324e16e4bSSepherosa Ziehau */ 309424e16e4bSSepherosa Ziehau BNX_SETBIT(sc, BGE_HCC_MODE, BGE_HCCMODE_COAL_NOW); 309524e16e4bSSepherosa Ziehau } 3096695a8586SSepherosa Ziehau } 3097695a8586SSepherosa Ziehau 3098695a8586SSepherosa Ziehau static void 3099695a8586SSepherosa Ziehau bnx_npoll_status(struct ifnet *ifp) 3100695a8586SSepherosa Ziehau { 3101695a8586SSepherosa Ziehau struct bnx_softc *sc = ifp->if_softc; 3102695a8586SSepherosa Ziehau 3103695a8586SSepherosa Ziehau ASSERT_SERIALIZED(&sc->bnx_main_serialize); 3104695a8586SSepherosa Ziehau 3105695a8586SSepherosa Ziehau sc->bnx_saved_status_tag = *sc->bnx_hw_status_tag; 3106695a8586SSepherosa Ziehau cpu_lfence(); 3107695a8586SSepherosa Ziehau bnx_npoll_status_notag(ifp); 31084fa38985SSepherosa Ziehau } 31094fa38985SSepherosa Ziehau 31104fa38985SSepherosa Ziehau static void 311139a8d43aSSepherosa Ziehau bnx_npoll(struct ifnet *ifp, struct ifpoll_info *info) 311239a8d43aSSepherosa Ziehau { 311339a8d43aSSepherosa Ziehau struct bnx_softc *sc = ifp->if_softc; 31144fa38985SSepherosa Ziehau int i; 311539a8d43aSSepherosa Ziehau 3116329f9016SSepherosa Ziehau ASSERT_IFNET_SERIALIZED_ALL(ifp); 311739a8d43aSSepherosa Ziehau 311839a8d43aSSepherosa Ziehau if (info != NULL) { 3119695a8586SSepherosa Ziehau if (sc->bnx_flags & BNX_FLAG_STATUS_HASTAG) 31204fa38985SSepherosa Ziehau info->ifpi_status.status_func = bnx_npoll_status; 3121695a8586SSepherosa Ziehau else 3122695a8586SSepherosa Ziehau info->ifpi_status.status_func = bnx_npoll_status_notag; 31234fa38985SSepherosa Ziehau info->ifpi_status.serializer = &sc->bnx_main_serialize; 312439a8d43aSSepherosa Ziehau 31254fa38985SSepherosa Ziehau for (i = 0; i < sc->bnx_tx_ringcnt; ++i) { 31264fa38985SSepherosa Ziehau struct bnx_tx_ring *txr = &sc->bnx_tx_ring[i]; 31274fa38985SSepherosa Ziehau int idx = i + sc->bnx_npoll_txoff; 31284fa38985SSepherosa Ziehau 31294fa38985SSepherosa Ziehau KKASSERT(idx < ncpus2); 3130695a8586SSepherosa Ziehau if (sc->bnx_flags & BNX_FLAG_RXTX_BUNDLE) { 3131695a8586SSepherosa Ziehau info->ifpi_tx[idx].poll_func = 3132695a8586SSepherosa Ziehau bnx_npoll_tx_notag; 3133695a8586SSepherosa Ziehau } else { 31344fa38985SSepherosa Ziehau info->ifpi_tx[idx].poll_func = bnx_npoll_tx; 3135695a8586SSepherosa Ziehau } 31364fa38985SSepherosa Ziehau info->ifpi_tx[idx].arg = txr; 31374fa38985SSepherosa Ziehau info->ifpi_tx[idx].serializer = &txr->bnx_tx_serialize; 31384fa38985SSepherosa Ziehau ifsq_set_cpuid(txr->bnx_ifsq, idx); 31394fa38985SSepherosa Ziehau } 31404fa38985SSepherosa Ziehau 31414fa38985SSepherosa Ziehau for (i = 0; i < sc->bnx_rx_retcnt; ++i) { 31424fa38985SSepherosa Ziehau struct bnx_rx_ret_ring *ret = &sc->bnx_rx_ret_ring[i]; 31434fa38985SSepherosa Ziehau int idx = i + sc->bnx_npoll_rxoff; 31444fa38985SSepherosa Ziehau 31454fa38985SSepherosa Ziehau KKASSERT(idx < ncpus2); 31464fa38985SSepherosa Ziehau info->ifpi_rx[idx].poll_func = bnx_npoll_rx; 31474fa38985SSepherosa Ziehau info->ifpi_rx[idx].arg = ret; 31484fa38985SSepherosa Ziehau info->ifpi_rx[idx].serializer = 31494fa38985SSepherosa Ziehau &ret->bnx_rx_ret_serialize; 31504fa38985SSepherosa Ziehau } 315139a8d43aSSepherosa Ziehau 31527dbaa833SSepherosa Ziehau if (ifp->if_flags & IFF_RUNNING) { 315339a8d43aSSepherosa Ziehau bnx_disable_intr(sc); 31547dbaa833SSepherosa Ziehau bnx_set_tick_cpuid(sc, TRUE); 315527357d84SSepherosa Ziehau 3156a86cc105SSepherosa Ziehau sc->bnx_coal_chg = BNX_TX_COAL_BDS_CHG | 3157a86cc105SSepherosa Ziehau BNX_RX_COAL_BDS_CHG; 315827357d84SSepherosa Ziehau bnx_coal_change(sc); 31597dbaa833SSepherosa Ziehau } 316039a8d43aSSepherosa Ziehau } else { 31614fa38985SSepherosa Ziehau for (i = 0; i < sc->bnx_tx_ringcnt; ++i) { 31624fa38985SSepherosa Ziehau ifsq_set_cpuid(sc->bnx_tx_ring[i].bnx_ifsq, 31634fa38985SSepherosa Ziehau sc->bnx_tx_ring[i].bnx_tx_cpuid); 31644fa38985SSepherosa Ziehau } 31657dbaa833SSepherosa Ziehau if (ifp->if_flags & IFF_RUNNING) { 3166a86cc105SSepherosa Ziehau sc->bnx_coal_chg = BNX_TX_COAL_BDS_CHG | 3167a86cc105SSepherosa Ziehau BNX_RX_COAL_BDS_CHG; 316827357d84SSepherosa Ziehau bnx_coal_change(sc); 316927357d84SSepherosa Ziehau 317039a8d43aSSepherosa Ziehau bnx_enable_intr(sc); 31717dbaa833SSepherosa Ziehau bnx_set_tick_cpuid(sc, FALSE); 31727dbaa833SSepherosa Ziehau } 317339a8d43aSSepherosa Ziehau } 317439a8d43aSSepherosa Ziehau } 317539a8d43aSSepherosa Ziehau 317639a8d43aSSepherosa Ziehau #endif /* IFPOLL_ENABLE */ 31776c8d8eccSSepherosa Ziehau 31786c8d8eccSSepherosa Ziehau static void 31796c8d8eccSSepherosa Ziehau bnx_intr_legacy(void *xsc) 31806c8d8eccSSepherosa Ziehau { 31816c8d8eccSSepherosa Ziehau struct bnx_softc *sc = xsc; 31824fa38985SSepherosa Ziehau struct bnx_rx_ret_ring *ret = &sc->bnx_rx_ret_ring[0]; 31836c8d8eccSSepherosa Ziehau 31844fa38985SSepherosa Ziehau if (ret->bnx_saved_status_tag == *ret->bnx_hw_status_tag) { 31856c8d8eccSSepherosa Ziehau uint32_t val; 31866c8d8eccSSepherosa Ziehau 31876c8d8eccSSepherosa Ziehau val = pci_read_config(sc->bnx_dev, BGE_PCI_PCISTATE, 4); 31886c8d8eccSSepherosa Ziehau if (val & BGE_PCISTAT_INTR_NOTACT) 31896c8d8eccSSepherosa Ziehau return; 31906c8d8eccSSepherosa Ziehau } 31916c8d8eccSSepherosa Ziehau 31926c8d8eccSSepherosa Ziehau /* 31936c8d8eccSSepherosa Ziehau * NOTE: 31946c8d8eccSSepherosa Ziehau * Interrupt will have to be disabled if tagged status 31956c8d8eccSSepherosa Ziehau * is used, else interrupt will always be asserted on 31966c8d8eccSSepherosa Ziehau * certain chips (at least on BCM5750 AX/BX). 31976c8d8eccSSepherosa Ziehau */ 31986c8d8eccSSepherosa Ziehau bnx_writembx(sc, BGE_MBX_IRQ0_LO, 1); 31996c8d8eccSSepherosa Ziehau 32006c8d8eccSSepherosa Ziehau bnx_intr(sc); 32016c8d8eccSSepherosa Ziehau } 32026c8d8eccSSepherosa Ziehau 32036c8d8eccSSepherosa Ziehau static void 320403cc99fdSSepherosa Ziehau bnx_msi(void *xsc) 32056c8d8eccSSepherosa Ziehau { 32066c8d8eccSSepherosa Ziehau bnx_intr(xsc); 32076c8d8eccSSepherosa Ziehau } 32086c8d8eccSSepherosa Ziehau 32096c8d8eccSSepherosa Ziehau static void 32106c8d8eccSSepherosa Ziehau bnx_intr(struct bnx_softc *sc) 32116c8d8eccSSepherosa Ziehau { 32126c8d8eccSSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if; 32134fa38985SSepherosa Ziehau struct bnx_rx_ret_ring *ret = &sc->bnx_rx_ret_ring[0]; 32146c8d8eccSSepherosa Ziehau 3215329f9016SSepherosa Ziehau ASSERT_SERIALIZED(&sc->bnx_main_serialize); 3216329f9016SSepherosa Ziehau 32174fa38985SSepherosa Ziehau ret->bnx_saved_status_tag = *ret->bnx_hw_status_tag; 32186c8d8eccSSepherosa Ziehau /* 32196c8d8eccSSepherosa Ziehau * Use a load fence to ensure that status_tag is saved 32206c8d8eccSSepherosa Ziehau * before rx_prod, tx_cons and status. 32216c8d8eccSSepherosa Ziehau */ 32226c8d8eccSSepherosa Ziehau cpu_lfence(); 32236c8d8eccSSepherosa Ziehau 3224695a8586SSepherosa Ziehau bnx_handle_status(sc); 32256c8d8eccSSepherosa Ziehau 32266c8d8eccSSepherosa Ziehau if (ifp->if_flags & IFF_RUNNING) { 32274fa38985SSepherosa Ziehau struct bnx_tx_ring *txr = &sc->bnx_tx_ring[0]; 32283a16b7b8SSepherosa Ziehau uint16_t rx_prod, tx_cons; 32293a16b7b8SSepherosa Ziehau 3230329f9016SSepherosa Ziehau lwkt_serialize_enter(&ret->bnx_rx_ret_serialize); 32313a16b7b8SSepherosa Ziehau rx_prod = *ret->bnx_rx_considx; 3232beedf5beSSepherosa Ziehau if (ret->bnx_rx_saved_considx != rx_prod) 3233beedf5beSSepherosa Ziehau bnx_rxeof(ret, rx_prod, -1); 3234329f9016SSepherosa Ziehau lwkt_serialize_exit(&ret->bnx_rx_ret_serialize); 32356c8d8eccSSepherosa Ziehau 3236329f9016SSepherosa Ziehau lwkt_serialize_enter(&txr->bnx_tx_serialize); 3237329f9016SSepherosa Ziehau tx_cons = *txr->bnx_tx_considx; 323833a04907SSepherosa Ziehau if (txr->bnx_tx_saved_considx != tx_cons) 323933a04907SSepherosa Ziehau bnx_txeof(txr, tx_cons); 3240329f9016SSepherosa Ziehau lwkt_serialize_exit(&txr->bnx_tx_serialize); 32416c8d8eccSSepherosa Ziehau } 32426c8d8eccSSepherosa Ziehau 32434fa38985SSepherosa Ziehau bnx_writembx(sc, BGE_MBX_IRQ0_LO, ret->bnx_saved_status_tag << 24); 32446c8d8eccSSepherosa Ziehau } 32456c8d8eccSSepherosa Ziehau 32466c8d8eccSSepherosa Ziehau static void 3247695a8586SSepherosa Ziehau bnx_msix_tx_status(void *xtxr) 3248695a8586SSepherosa Ziehau { 3249695a8586SSepherosa Ziehau struct bnx_tx_ring *txr = xtxr; 3250695a8586SSepherosa Ziehau struct bnx_softc *sc = txr->bnx_sc; 3251695a8586SSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if; 3252695a8586SSepherosa Ziehau 3253695a8586SSepherosa Ziehau ASSERT_SERIALIZED(&sc->bnx_main_serialize); 3254695a8586SSepherosa Ziehau 3255695a8586SSepherosa Ziehau txr->bnx_saved_status_tag = *txr->bnx_hw_status_tag; 3256695a8586SSepherosa Ziehau /* 3257695a8586SSepherosa Ziehau * Use a load fence to ensure that status_tag is saved 3258695a8586SSepherosa Ziehau * before tx_cons and status. 3259695a8586SSepherosa Ziehau */ 3260695a8586SSepherosa Ziehau cpu_lfence(); 3261695a8586SSepherosa Ziehau 3262695a8586SSepherosa Ziehau bnx_handle_status(sc); 3263695a8586SSepherosa Ziehau 3264695a8586SSepherosa Ziehau if (ifp->if_flags & IFF_RUNNING) { 3265695a8586SSepherosa Ziehau uint16_t tx_cons; 3266695a8586SSepherosa Ziehau 3267695a8586SSepherosa Ziehau lwkt_serialize_enter(&txr->bnx_tx_serialize); 3268695a8586SSepherosa Ziehau tx_cons = *txr->bnx_tx_considx; 3269695a8586SSepherosa Ziehau if (txr->bnx_tx_saved_considx != tx_cons) 3270695a8586SSepherosa Ziehau bnx_txeof(txr, tx_cons); 3271695a8586SSepherosa Ziehau lwkt_serialize_exit(&txr->bnx_tx_serialize); 3272695a8586SSepherosa Ziehau } 3273695a8586SSepherosa Ziehau 3274695a8586SSepherosa Ziehau bnx_writembx(sc, BGE_MBX_IRQ0_LO, txr->bnx_saved_status_tag << 24); 3275695a8586SSepherosa Ziehau } 3276695a8586SSepherosa Ziehau 3277695a8586SSepherosa Ziehau static void 3278695a8586SSepherosa Ziehau bnx_msix_rx(void *xret) 3279695a8586SSepherosa Ziehau { 3280695a8586SSepherosa Ziehau struct bnx_rx_ret_ring *ret = xret; 3281695a8586SSepherosa Ziehau uint16_t rx_prod; 3282695a8586SSepherosa Ziehau 3283695a8586SSepherosa Ziehau ASSERT_SERIALIZED(&ret->bnx_rx_ret_serialize); 3284695a8586SSepherosa Ziehau 3285695a8586SSepherosa Ziehau ret->bnx_saved_status_tag = *ret->bnx_hw_status_tag; 3286695a8586SSepherosa Ziehau /* 3287695a8586SSepherosa Ziehau * Use a load fence to ensure that status_tag is saved 3288695a8586SSepherosa Ziehau * before rx_prod. 3289695a8586SSepherosa Ziehau */ 3290695a8586SSepherosa Ziehau cpu_lfence(); 3291695a8586SSepherosa Ziehau 3292695a8586SSepherosa Ziehau rx_prod = *ret->bnx_rx_considx; 3293695a8586SSepherosa Ziehau if (ret->bnx_rx_saved_considx != rx_prod) 3294695a8586SSepherosa Ziehau bnx_rxeof(ret, rx_prod, -1); 3295695a8586SSepherosa Ziehau 3296695a8586SSepherosa Ziehau bnx_writembx(ret->bnx_sc, ret->bnx_msix_mbx, 3297695a8586SSepherosa Ziehau ret->bnx_saved_status_tag << 24); 3298695a8586SSepherosa Ziehau } 3299695a8586SSepherosa Ziehau 3300695a8586SSepherosa Ziehau static void 3301695a8586SSepherosa Ziehau bnx_msix_rxtx(void *xret) 3302695a8586SSepherosa Ziehau { 3303695a8586SSepherosa Ziehau struct bnx_rx_ret_ring *ret = xret; 3304695a8586SSepherosa Ziehau struct bnx_tx_ring *txr = ret->bnx_txr; 3305695a8586SSepherosa Ziehau uint16_t rx_prod, tx_cons; 3306695a8586SSepherosa Ziehau 3307695a8586SSepherosa Ziehau ASSERT_SERIALIZED(&ret->bnx_rx_ret_serialize); 3308695a8586SSepherosa Ziehau 3309695a8586SSepherosa Ziehau ret->bnx_saved_status_tag = *ret->bnx_hw_status_tag; 3310695a8586SSepherosa Ziehau /* 3311695a8586SSepherosa Ziehau * Use a load fence to ensure that status_tag is saved 3312695a8586SSepherosa Ziehau * before rx_prod and tx_cons. 3313695a8586SSepherosa Ziehau */ 3314695a8586SSepherosa Ziehau cpu_lfence(); 3315695a8586SSepherosa Ziehau 3316695a8586SSepherosa Ziehau rx_prod = *ret->bnx_rx_considx; 3317695a8586SSepherosa Ziehau if (ret->bnx_rx_saved_considx != rx_prod) 3318695a8586SSepherosa Ziehau bnx_rxeof(ret, rx_prod, -1); 3319695a8586SSepherosa Ziehau 3320695a8586SSepherosa Ziehau lwkt_serialize_enter(&txr->bnx_tx_serialize); 3321695a8586SSepherosa Ziehau tx_cons = *txr->bnx_tx_considx; 3322695a8586SSepherosa Ziehau if (txr->bnx_tx_saved_considx != tx_cons) 3323695a8586SSepherosa Ziehau bnx_txeof(txr, tx_cons); 3324695a8586SSepherosa Ziehau lwkt_serialize_exit(&txr->bnx_tx_serialize); 3325695a8586SSepherosa Ziehau 3326695a8586SSepherosa Ziehau bnx_writembx(ret->bnx_sc, ret->bnx_msix_mbx, 3327695a8586SSepherosa Ziehau ret->bnx_saved_status_tag << 24); 3328695a8586SSepherosa Ziehau } 3329695a8586SSepherosa Ziehau 3330695a8586SSepherosa Ziehau static void 3331695a8586SSepherosa Ziehau bnx_msix_status(void *xsc) 3332695a8586SSepherosa Ziehau { 3333695a8586SSepherosa Ziehau struct bnx_softc *sc = xsc; 3334695a8586SSepherosa Ziehau 3335695a8586SSepherosa Ziehau ASSERT_SERIALIZED(&sc->bnx_main_serialize); 3336695a8586SSepherosa Ziehau 3337695a8586SSepherosa Ziehau sc->bnx_saved_status_tag = *sc->bnx_hw_status_tag; 3338695a8586SSepherosa Ziehau /* 3339695a8586SSepherosa Ziehau * Use a load fence to ensure that status_tag is saved 3340695a8586SSepherosa Ziehau * before status. 3341695a8586SSepherosa Ziehau */ 3342695a8586SSepherosa Ziehau cpu_lfence(); 3343695a8586SSepherosa Ziehau 3344695a8586SSepherosa Ziehau bnx_handle_status(sc); 3345695a8586SSepherosa Ziehau 3346695a8586SSepherosa Ziehau bnx_writembx(sc, BGE_MBX_IRQ0_LO, sc->bnx_saved_status_tag << 24); 3347695a8586SSepherosa Ziehau } 3348695a8586SSepherosa Ziehau 3349695a8586SSepherosa Ziehau static void 33506c8d8eccSSepherosa Ziehau bnx_tick(void *xsc) 33516c8d8eccSSepherosa Ziehau { 33526c8d8eccSSepherosa Ziehau struct bnx_softc *sc = xsc; 33536c8d8eccSSepherosa Ziehau 3354329f9016SSepherosa Ziehau lwkt_serialize_enter(&sc->bnx_main_serialize); 33556c8d8eccSSepherosa Ziehau 33566c8d8eccSSepherosa Ziehau bnx_stats_update_regs(sc); 33576c8d8eccSSepherosa Ziehau 33586c8d8eccSSepherosa Ziehau if (sc->bnx_flags & BNX_FLAG_TBI) { 33596c8d8eccSSepherosa Ziehau /* 33606c8d8eccSSepherosa Ziehau * Since in TBI mode auto-polling can't be used we should poll 33616c8d8eccSSepherosa Ziehau * link status manually. Here we register pending link event 33626c8d8eccSSepherosa Ziehau * and trigger interrupt. 33636c8d8eccSSepherosa Ziehau */ 33646c8d8eccSSepherosa Ziehau sc->bnx_link_evt++; 33656c8d8eccSSepherosa Ziehau BNX_SETBIT(sc, BGE_HCC_MODE, BGE_HCCMODE_COAL_NOW); 33666c8d8eccSSepherosa Ziehau } else if (!sc->bnx_link) { 33676c8d8eccSSepherosa Ziehau mii_tick(device_get_softc(sc->bnx_miibus)); 33686c8d8eccSSepherosa Ziehau } 33696c8d8eccSSepherosa Ziehau 33707dbaa833SSepherosa Ziehau callout_reset_bycpu(&sc->bnx_tick_timer, hz, bnx_tick, sc, 33717dbaa833SSepherosa Ziehau sc->bnx_tick_cpuid); 33726c8d8eccSSepherosa Ziehau 3373329f9016SSepherosa Ziehau lwkt_serialize_exit(&sc->bnx_main_serialize); 33746c8d8eccSSepherosa Ziehau } 33756c8d8eccSSepherosa Ziehau 33766c8d8eccSSepherosa Ziehau static void 33776c8d8eccSSepherosa Ziehau bnx_stats_update_regs(struct bnx_softc *sc) 33786c8d8eccSSepherosa Ziehau { 33796c8d8eccSSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if; 33806c8d8eccSSepherosa Ziehau struct bge_mac_stats_regs stats; 3381695a8586SSepherosa Ziehau uint32_t *s, val; 33826c8d8eccSSepherosa Ziehau int i; 33836c8d8eccSSepherosa Ziehau 33846c8d8eccSSepherosa Ziehau s = (uint32_t *)&stats; 33856c8d8eccSSepherosa Ziehau for (i = 0; i < sizeof(struct bge_mac_stats_regs); i += 4) { 33866c8d8eccSSepherosa Ziehau *s = CSR_READ_4(sc, BGE_RX_STATS + i); 33876c8d8eccSSepherosa Ziehau s++; 33886c8d8eccSSepherosa Ziehau } 33896c8d8eccSSepherosa Ziehau 3390d40991efSSepherosa Ziehau IFNET_STAT_SET(ifp, collisions, 33916c8d8eccSSepherosa Ziehau (stats.dot3StatsSingleCollisionFrames + 33926c8d8eccSSepherosa Ziehau stats.dot3StatsMultipleCollisionFrames + 33936c8d8eccSSepherosa Ziehau stats.dot3StatsExcessiveCollisions + 3394d40991efSSepherosa Ziehau stats.dot3StatsLateCollisions)); 3395695a8586SSepherosa Ziehau 3396695a8586SSepherosa Ziehau val = CSR_READ_4(sc, BGE_RXLP_LOCSTAT_OUT_OF_BDS); 3397695a8586SSepherosa Ziehau sc->bnx_norxbds += val; 33986c8d8eccSSepherosa Ziehau } 33996c8d8eccSSepherosa Ziehau 34006c8d8eccSSepherosa Ziehau /* 34016c8d8eccSSepherosa Ziehau * Encapsulate an mbuf chain in the tx ring by coupling the mbuf data 34026c8d8eccSSepherosa Ziehau * pointers to descriptors. 34036c8d8eccSSepherosa Ziehau */ 34046c8d8eccSSepherosa Ziehau static int 340533a04907SSepherosa Ziehau bnx_encap(struct bnx_tx_ring *txr, struct mbuf **m_head0, uint32_t *txidx, 3406c9b7f592SSepherosa Ziehau int *segs_used) 34076c8d8eccSSepherosa Ziehau { 34086c8d8eccSSepherosa Ziehau struct bge_tx_bd *d = NULL; 340966deb1c1SSepherosa Ziehau uint16_t csum_flags = 0, vlan_tag = 0, mss = 0; 34106c8d8eccSSepherosa Ziehau bus_dma_segment_t segs[BNX_NSEG_NEW]; 34116c8d8eccSSepherosa Ziehau bus_dmamap_t map; 34126c8d8eccSSepherosa Ziehau int error, maxsegs, nsegs, idx, i; 34136c8d8eccSSepherosa Ziehau struct mbuf *m_head = *m_head0, *m_new; 34146c8d8eccSSepherosa Ziehau 341566deb1c1SSepherosa Ziehau if (m_head->m_pkthdr.csum_flags & CSUM_TSO) { 341666deb1c1SSepherosa Ziehau #ifdef BNX_TSO_DEBUG 341766deb1c1SSepherosa Ziehau int tso_nsegs; 341866deb1c1SSepherosa Ziehau #endif 341966deb1c1SSepherosa Ziehau 342033a04907SSepherosa Ziehau error = bnx_setup_tso(txr, m_head0, &mss, &csum_flags); 342166deb1c1SSepherosa Ziehau if (error) 342266deb1c1SSepherosa Ziehau return error; 342366deb1c1SSepherosa Ziehau m_head = *m_head0; 342466deb1c1SSepherosa Ziehau 342566deb1c1SSepherosa Ziehau #ifdef BNX_TSO_DEBUG 3426f0336d39SSepherosa Ziehau tso_nsegs = (m_head->m_pkthdr.len / 3427f0336d39SSepherosa Ziehau m_head->m_pkthdr.tso_segsz) - 1; 342866deb1c1SSepherosa Ziehau if (tso_nsegs > (BNX_TSO_NSTATS - 1)) 342966deb1c1SSepherosa Ziehau tso_nsegs = BNX_TSO_NSTATS - 1; 343066deb1c1SSepherosa Ziehau else if (tso_nsegs < 0) 343166deb1c1SSepherosa Ziehau tso_nsegs = 0; 34325a0c3c3aSSascha Wildner txr->bnx_sc->bnx_tsosegs[tso_nsegs]++; 343366deb1c1SSepherosa Ziehau #endif 343466deb1c1SSepherosa Ziehau } else if (m_head->m_pkthdr.csum_flags & BNX_CSUM_FEATURES) { 34356c8d8eccSSepherosa Ziehau if (m_head->m_pkthdr.csum_flags & CSUM_IP) 34366c8d8eccSSepherosa Ziehau csum_flags |= BGE_TXBDFLAG_IP_CSUM; 34376c8d8eccSSepherosa Ziehau if (m_head->m_pkthdr.csum_flags & (CSUM_TCP | CSUM_UDP)) 34386c8d8eccSSepherosa Ziehau csum_flags |= BGE_TXBDFLAG_TCP_UDP_CSUM; 34396c8d8eccSSepherosa Ziehau if (m_head->m_flags & M_LASTFRAG) 34406c8d8eccSSepherosa Ziehau csum_flags |= BGE_TXBDFLAG_IP_FRAG_END; 34416c8d8eccSSepherosa Ziehau else if (m_head->m_flags & M_FRAG) 34426c8d8eccSSepherosa Ziehau csum_flags |= BGE_TXBDFLAG_IP_FRAG; 34436c8d8eccSSepherosa Ziehau } 344466deb1c1SSepherosa Ziehau if (m_head->m_flags & M_VLANTAG) { 344566deb1c1SSepherosa Ziehau csum_flags |= BGE_TXBDFLAG_VLAN_TAG; 344666deb1c1SSepherosa Ziehau vlan_tag = m_head->m_pkthdr.ether_vlantag; 344766deb1c1SSepherosa Ziehau } 34486c8d8eccSSepherosa Ziehau 34496c8d8eccSSepherosa Ziehau idx = *txidx; 3450fa4b1067SSepherosa Ziehau map = txr->bnx_tx_buf[idx].bnx_tx_dmamap; 34516c8d8eccSSepherosa Ziehau 3452fa639b88SSepherosa Ziehau maxsegs = (BGE_TX_RING_CNT - txr->bnx_tx_cnt) - BNX_NSEG_RSVD; 34536c8d8eccSSepherosa Ziehau KASSERT(maxsegs >= BNX_NSEG_SPARE, 34546c8d8eccSSepherosa Ziehau ("not enough segments %d", maxsegs)); 34556c8d8eccSSepherosa Ziehau 34566c8d8eccSSepherosa Ziehau if (maxsegs > BNX_NSEG_NEW) 34576c8d8eccSSepherosa Ziehau maxsegs = BNX_NSEG_NEW; 34586c8d8eccSSepherosa Ziehau 34596c8d8eccSSepherosa Ziehau /* 34606c8d8eccSSepherosa Ziehau * Pad outbound frame to BGE_MIN_FRAMELEN for an unusual reason. 34616c8d8eccSSepherosa Ziehau * The bge hardware will pad out Tx runts to BGE_MIN_FRAMELEN, 34626c8d8eccSSepherosa Ziehau * but when such padded frames employ the bge IP/TCP checksum 34636c8d8eccSSepherosa Ziehau * offload, the hardware checksum assist gives incorrect results 34646c8d8eccSSepherosa Ziehau * (possibly from incorporating its own padding into the UDP/TCP 34656c8d8eccSSepherosa Ziehau * checksum; who knows). If we pad such runts with zeros, the 34666c8d8eccSSepherosa Ziehau * onboard checksum comes out correct. 34676c8d8eccSSepherosa Ziehau */ 34686c8d8eccSSepherosa Ziehau if ((csum_flags & BGE_TXBDFLAG_TCP_UDP_CSUM) && 34696c8d8eccSSepherosa Ziehau m_head->m_pkthdr.len < BNX_MIN_FRAMELEN) { 34706c8d8eccSSepherosa Ziehau error = m_devpad(m_head, BNX_MIN_FRAMELEN); 34716c8d8eccSSepherosa Ziehau if (error) 34726c8d8eccSSepherosa Ziehau goto back; 34736c8d8eccSSepherosa Ziehau } 34746c8d8eccSSepherosa Ziehau 347579a64343SSepherosa Ziehau if ((txr->bnx_tx_flags & BNX_TX_FLAG_SHORTDMA) && 347633a04907SSepherosa Ziehau m_head->m_next != NULL) { 34776c8d8eccSSepherosa Ziehau m_new = bnx_defrag_shortdma(m_head); 34786c8d8eccSSepherosa Ziehau if (m_new == NULL) { 34796c8d8eccSSepherosa Ziehau error = ENOBUFS; 34806c8d8eccSSepherosa Ziehau goto back; 34816c8d8eccSSepherosa Ziehau } 34826c8d8eccSSepherosa Ziehau *m_head0 = m_head = m_new; 34836c8d8eccSSepherosa Ziehau } 348466deb1c1SSepherosa Ziehau if ((m_head->m_pkthdr.csum_flags & CSUM_TSO) == 0 && 3485aad4de2bSSepherosa Ziehau (txr->bnx_tx_flags & BNX_TX_FLAG_FORCE_DEFRAG) && 3486aad4de2bSSepherosa Ziehau m_head->m_next != NULL) { 34876c8d8eccSSepherosa Ziehau /* 34886c8d8eccSSepherosa Ziehau * Forcefully defragment mbuf chain to overcome hardware 34896c8d8eccSSepherosa Ziehau * limitation which only support a single outstanding 34906c8d8eccSSepherosa Ziehau * DMA read operation. If it fails, keep moving on using 34916c8d8eccSSepherosa Ziehau * the original mbuf chain. 34926c8d8eccSSepherosa Ziehau */ 34936c8d8eccSSepherosa Ziehau m_new = m_defrag(m_head, MB_DONTWAIT); 34946c8d8eccSSepherosa Ziehau if (m_new != NULL) 34956c8d8eccSSepherosa Ziehau *m_head0 = m_head = m_new; 34966c8d8eccSSepherosa Ziehau } 34976c8d8eccSSepherosa Ziehau 349833a04907SSepherosa Ziehau error = bus_dmamap_load_mbuf_defrag(txr->bnx_tx_mtag, map, 34996c8d8eccSSepherosa Ziehau m_head0, segs, maxsegs, &nsegs, BUS_DMA_NOWAIT); 35006c8d8eccSSepherosa Ziehau if (error) 35016c8d8eccSSepherosa Ziehau goto back; 3502c9b7f592SSepherosa Ziehau *segs_used += nsegs; 35036c8d8eccSSepherosa Ziehau 35046c8d8eccSSepherosa Ziehau m_head = *m_head0; 350533a04907SSepherosa Ziehau bus_dmamap_sync(txr->bnx_tx_mtag, map, BUS_DMASYNC_PREWRITE); 35066c8d8eccSSepherosa Ziehau 35076c8d8eccSSepherosa Ziehau for (i = 0; ; i++) { 350833a04907SSepherosa Ziehau d = &txr->bnx_tx_ring[idx]; 35096c8d8eccSSepherosa Ziehau 35106c8d8eccSSepherosa Ziehau d->bge_addr.bge_addr_lo = BGE_ADDR_LO(segs[i].ds_addr); 35116c8d8eccSSepherosa Ziehau d->bge_addr.bge_addr_hi = BGE_ADDR_HI(segs[i].ds_addr); 35126c8d8eccSSepherosa Ziehau d->bge_len = segs[i].ds_len; 35136c8d8eccSSepherosa Ziehau d->bge_flags = csum_flags; 351466deb1c1SSepherosa Ziehau d->bge_vlan_tag = vlan_tag; 351566deb1c1SSepherosa Ziehau d->bge_mss = mss; 35166c8d8eccSSepherosa Ziehau 35176c8d8eccSSepherosa Ziehau if (i == nsegs - 1) 35186c8d8eccSSepherosa Ziehau break; 35196c8d8eccSSepherosa Ziehau BNX_INC(idx, BGE_TX_RING_CNT); 35206c8d8eccSSepherosa Ziehau } 35216c8d8eccSSepherosa Ziehau /* Mark the last segment as end of packet... */ 35226c8d8eccSSepherosa Ziehau d->bge_flags |= BGE_TXBDFLAG_END; 35236c8d8eccSSepherosa Ziehau 35246c8d8eccSSepherosa Ziehau /* 35256c8d8eccSSepherosa Ziehau * Insure that the map for this transmission is placed at 35266c8d8eccSSepherosa Ziehau * the array index of the last descriptor in this chain. 35276c8d8eccSSepherosa Ziehau */ 3528fa4b1067SSepherosa Ziehau txr->bnx_tx_buf[*txidx].bnx_tx_dmamap = txr->bnx_tx_buf[idx].bnx_tx_dmamap; 3529fa4b1067SSepherosa Ziehau txr->bnx_tx_buf[idx].bnx_tx_dmamap = map; 3530fa4b1067SSepherosa Ziehau txr->bnx_tx_buf[idx].bnx_tx_mbuf = m_head; 3531fa639b88SSepherosa Ziehau txr->bnx_tx_cnt += nsegs; 35326c8d8eccSSepherosa Ziehau 35336c8d8eccSSepherosa Ziehau BNX_INC(idx, BGE_TX_RING_CNT); 35346c8d8eccSSepherosa Ziehau *txidx = idx; 35356c8d8eccSSepherosa Ziehau back: 35366c8d8eccSSepherosa Ziehau if (error) { 35376c8d8eccSSepherosa Ziehau m_freem(*m_head0); 35386c8d8eccSSepherosa Ziehau *m_head0 = NULL; 35396c8d8eccSSepherosa Ziehau } 35406c8d8eccSSepherosa Ziehau return error; 35416c8d8eccSSepherosa Ziehau } 35426c8d8eccSSepherosa Ziehau 35436c8d8eccSSepherosa Ziehau /* 35446c8d8eccSSepherosa Ziehau * Main transmit routine. To avoid having to do mbuf copies, we put pointers 35456c8d8eccSSepherosa Ziehau * to the mbuf data regions directly in the transmit descriptors. 35466c8d8eccSSepherosa Ziehau */ 35476c8d8eccSSepherosa Ziehau static void 3548f0a26983SSepherosa Ziehau bnx_start(struct ifnet *ifp, struct ifaltq_subque *ifsq) 35496c8d8eccSSepherosa Ziehau { 35503397dea6SSepherosa Ziehau struct bnx_tx_ring *txr = ifsq_get_priv(ifsq); 35516c8d8eccSSepherosa Ziehau struct mbuf *m_head = NULL; 35526c8d8eccSSepherosa Ziehau uint32_t prodidx; 3553c9b7f592SSepherosa Ziehau int nsegs = 0; 35546c8d8eccSSepherosa Ziehau 35553397dea6SSepherosa Ziehau KKASSERT(txr->bnx_ifsq == ifsq); 3556329f9016SSepherosa Ziehau ASSERT_SERIALIZED(&txr->bnx_tx_serialize); 3557f0a26983SSepherosa Ziehau 35583397dea6SSepherosa Ziehau if ((ifp->if_flags & IFF_RUNNING) == 0 || ifsq_is_oactive(ifsq)) 35596c8d8eccSSepherosa Ziehau return; 35606c8d8eccSSepherosa Ziehau 356133a04907SSepherosa Ziehau prodidx = txr->bnx_tx_prodidx; 35626c8d8eccSSepherosa Ziehau 3563fa4b1067SSepherosa Ziehau while (txr->bnx_tx_buf[prodidx].bnx_tx_mbuf == NULL) { 35646c8d8eccSSepherosa Ziehau /* 35656c8d8eccSSepherosa Ziehau * Sanity check: avoid coming within BGE_NSEG_RSVD 35666c8d8eccSSepherosa Ziehau * descriptors of the end of the ring. Also make 35676c8d8eccSSepherosa Ziehau * sure there are BGE_NSEG_SPARE descriptors for 3568a1bd58c9SSepherosa Ziehau * jumbo buffers' or TSO segments' defragmentation. 35696c8d8eccSSepherosa Ziehau */ 3570fa639b88SSepherosa Ziehau if ((BGE_TX_RING_CNT - txr->bnx_tx_cnt) < 35716c8d8eccSSepherosa Ziehau (BNX_NSEG_RSVD + BNX_NSEG_SPARE)) { 35723397dea6SSepherosa Ziehau ifsq_set_oactive(ifsq); 35736c8d8eccSSepherosa Ziehau break; 35746c8d8eccSSepherosa Ziehau } 35756c8d8eccSSepherosa Ziehau 3576ac9843a1SSepherosa Ziehau m_head = ifsq_dequeue(ifsq); 3577a1bd58c9SSepherosa Ziehau if (m_head == NULL) 3578a1bd58c9SSepherosa Ziehau break; 3579a1bd58c9SSepherosa Ziehau 35806c8d8eccSSepherosa Ziehau /* 35816c8d8eccSSepherosa Ziehau * Pack the data into the transmit ring. If we 35826c8d8eccSSepherosa Ziehau * don't have room, set the OACTIVE flag and wait 35836c8d8eccSSepherosa Ziehau * for the NIC to drain the ring. 35846c8d8eccSSepherosa Ziehau */ 358533a04907SSepherosa Ziehau if (bnx_encap(txr, &m_head, &prodidx, &nsegs)) { 35863397dea6SSepherosa Ziehau ifsq_set_oactive(ifsq); 3587d40991efSSepherosa Ziehau IFNET_STAT_INC(ifp, oerrors, 1); 35886c8d8eccSSepherosa Ziehau break; 35896c8d8eccSSepherosa Ziehau } 35906c8d8eccSSepherosa Ziehau 359133a04907SSepherosa Ziehau if (nsegs >= txr->bnx_tx_wreg) { 35926c8d8eccSSepherosa Ziehau /* Transmit */ 35938bd43d5dSSepherosa Ziehau bnx_writembx(txr->bnx_sc, txr->bnx_tx_mbx, prodidx); 3594c9b7f592SSepherosa Ziehau nsegs = 0; 3595c9b7f592SSepherosa Ziehau } 35966c8d8eccSSepherosa Ziehau 3597c9b7f592SSepherosa Ziehau ETHER_BPF_MTAP(ifp, m_head); 35986c8d8eccSSepherosa Ziehau 35996c8d8eccSSepherosa Ziehau /* 36006c8d8eccSSepherosa Ziehau * Set a timeout in case the chip goes out to lunch. 36016c8d8eccSSepherosa Ziehau */ 36023397dea6SSepherosa Ziehau txr->bnx_tx_watchdog.wd_timer = 5; 36036c8d8eccSSepherosa Ziehau } 36046c8d8eccSSepherosa Ziehau 3605c9b7f592SSepherosa Ziehau if (nsegs > 0) { 3606c9b7f592SSepherosa Ziehau /* Transmit */ 36078bd43d5dSSepherosa Ziehau bnx_writembx(txr->bnx_sc, txr->bnx_tx_mbx, prodidx); 3608c9b7f592SSepherosa Ziehau } 360933a04907SSepherosa Ziehau txr->bnx_tx_prodidx = prodidx; 3610c9b7f592SSepherosa Ziehau } 3611c9b7f592SSepherosa Ziehau 36126c8d8eccSSepherosa Ziehau static void 36136c8d8eccSSepherosa Ziehau bnx_init(void *xsc) 36146c8d8eccSSepherosa Ziehau { 36156c8d8eccSSepherosa Ziehau struct bnx_softc *sc = xsc; 36166c8d8eccSSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if; 36176c8d8eccSSepherosa Ziehau uint16_t *m; 36186c8d8eccSSepherosa Ziehau uint32_t mode; 361933a04907SSepherosa Ziehau int i; 36207dbaa833SSepherosa Ziehau boolean_t polling; 36216c8d8eccSSepherosa Ziehau 3622329f9016SSepherosa Ziehau ASSERT_IFNET_SERIALIZED_ALL(ifp); 36236c8d8eccSSepherosa Ziehau 36246c8d8eccSSepherosa Ziehau /* Cancel pending I/O and flush buffers. */ 36256c8d8eccSSepherosa Ziehau bnx_stop(sc); 36264aa71e73SSepherosa Ziehau 36274aa71e73SSepherosa Ziehau bnx_sig_pre_reset(sc, BNX_RESET_START); 36286c8d8eccSSepherosa Ziehau bnx_reset(sc); 36294aa71e73SSepherosa Ziehau bnx_sig_post_reset(sc, BNX_RESET_START); 36304aa71e73SSepherosa Ziehau 36316c8d8eccSSepherosa Ziehau bnx_chipinit(sc); 36326c8d8eccSSepherosa Ziehau 36336c8d8eccSSepherosa Ziehau /* 36346c8d8eccSSepherosa Ziehau * Init the various state machines, ring 36356c8d8eccSSepherosa Ziehau * control blocks and firmware. 36366c8d8eccSSepherosa Ziehau */ 36376c8d8eccSSepherosa Ziehau if (bnx_blockinit(sc)) { 36386c8d8eccSSepherosa Ziehau if_printf(ifp, "initialization failure\n"); 36396c8d8eccSSepherosa Ziehau bnx_stop(sc); 36406c8d8eccSSepherosa Ziehau return; 36416c8d8eccSSepherosa Ziehau } 36426c8d8eccSSepherosa Ziehau 36436c8d8eccSSepherosa Ziehau /* Specify MTU. */ 36446c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_RX_MTU, ifp->if_mtu + 36456c8d8eccSSepherosa Ziehau ETHER_HDR_LEN + ETHER_CRC_LEN + EVL_ENCAPLEN); 36466c8d8eccSSepherosa Ziehau 36476c8d8eccSSepherosa Ziehau /* Load our MAC address. */ 36486c8d8eccSSepherosa Ziehau m = (uint16_t *)&sc->arpcom.ac_enaddr[0]; 36496c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_MAC_ADDR1_LO, htons(m[0])); 36506c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_MAC_ADDR1_HI, (htons(m[1]) << 16) | htons(m[2])); 36516c8d8eccSSepherosa Ziehau 36526c8d8eccSSepherosa Ziehau /* Enable or disable promiscuous mode as needed. */ 36536c8d8eccSSepherosa Ziehau bnx_setpromisc(sc); 36546c8d8eccSSepherosa Ziehau 36556c8d8eccSSepherosa Ziehau /* Program multicast filter. */ 36566c8d8eccSSepherosa Ziehau bnx_setmulti(sc); 36576c8d8eccSSepherosa Ziehau 36586c8d8eccSSepherosa Ziehau /* Init RX ring. */ 3659beedf5beSSepherosa Ziehau if (bnx_init_rx_ring_std(&sc->bnx_rx_std_ring)) { 36606c8d8eccSSepherosa Ziehau if_printf(ifp, "RX ring initialization failed\n"); 36616c8d8eccSSepherosa Ziehau bnx_stop(sc); 36626c8d8eccSSepherosa Ziehau return; 36636c8d8eccSSepherosa Ziehau } 36646c8d8eccSSepherosa Ziehau 36656c8d8eccSSepherosa Ziehau /* Init jumbo RX ring. */ 36666c8d8eccSSepherosa Ziehau if (ifp->if_mtu > (ETHERMTU + ETHER_HDR_LEN + ETHER_CRC_LEN)) { 36676c8d8eccSSepherosa Ziehau if (bnx_init_rx_ring_jumbo(sc)) { 36686c8d8eccSSepherosa Ziehau if_printf(ifp, "Jumbo RX ring initialization failed\n"); 36696c8d8eccSSepherosa Ziehau bnx_stop(sc); 36706c8d8eccSSepherosa Ziehau return; 36716c8d8eccSSepherosa Ziehau } 36726c8d8eccSSepherosa Ziehau } 36736c8d8eccSSepherosa Ziehau 36746c8d8eccSSepherosa Ziehau /* Init our RX return ring index */ 3675841cdf08SSepherosa Ziehau for (i = 0; i < sc->bnx_rx_retcnt; ++i) { 3676841cdf08SSepherosa Ziehau struct bnx_rx_ret_ring *ret = &sc->bnx_rx_ret_ring[i]; 3677841cdf08SSepherosa Ziehau 3678841cdf08SSepherosa Ziehau ret->bnx_rx_saved_considx = 0; 3679841cdf08SSepherosa Ziehau ret->bnx_rx_cnt = 0; 3680841cdf08SSepherosa Ziehau } 36816c8d8eccSSepherosa Ziehau 36826c8d8eccSSepherosa Ziehau /* Init TX ring. */ 368333a04907SSepherosa Ziehau for (i = 0; i < sc->bnx_tx_ringcnt; ++i) 368433a04907SSepherosa Ziehau bnx_init_tx_ring(&sc->bnx_tx_ring[i]); 36856c8d8eccSSepherosa Ziehau 36866c8d8eccSSepherosa Ziehau /* Enable TX MAC state machine lockup fix. */ 36876c8d8eccSSepherosa Ziehau mode = CSR_READ_4(sc, BGE_TX_MODE); 36886c8d8eccSSepherosa Ziehau mode |= BGE_TXMODE_MBUF_LOCKUP_FIX; 3689b96cbbb6SSepherosa Ziehau if (sc->bnx_asicrev == BGE_ASICREV_BCM5720 || 3690b96cbbb6SSepherosa Ziehau sc->bnx_asicrev == BGE_ASICREV_BCM5762) { 36916c8d8eccSSepherosa Ziehau mode &= ~(BGE_TXMODE_JMB_FRM_LEN | BGE_TXMODE_CNT_DN_MODE); 36926c8d8eccSSepherosa Ziehau mode |= CSR_READ_4(sc, BGE_TX_MODE) & 36936c8d8eccSSepherosa Ziehau (BGE_TXMODE_JMB_FRM_LEN | BGE_TXMODE_CNT_DN_MODE); 36946c8d8eccSSepherosa Ziehau } 36956c8d8eccSSepherosa Ziehau /* Turn on transmitter */ 36966c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_TX_MODE, mode | BGE_TXMODE_ENABLE); 36974aa71e73SSepherosa Ziehau DELAY(100); 36986c8d8eccSSepherosa Ziehau 3699695a8586SSepherosa Ziehau /* Initialize RSS */ 37009f5082d5SSepherosa Ziehau mode = BGE_RXMODE_ENABLE | BGE_RXMODE_IPV6_ENABLE; 3701695a8586SSepherosa Ziehau if (BNX_RSS_ENABLED(sc)) { 3702695a8586SSepherosa Ziehau bnx_init_rss(sc); 3703695a8586SSepherosa Ziehau mode |= BGE_RXMODE_RSS_ENABLE | 3704695a8586SSepherosa Ziehau BGE_RXMODE_RSS_HASH_MASK_BITS | 3705695a8586SSepherosa Ziehau BGE_RXMODE_RSS_IPV4_HASH | 3706695a8586SSepherosa Ziehau BGE_RXMODE_RSS_TCP_IPV4_HASH; 3707695a8586SSepherosa Ziehau } 37086c8d8eccSSepherosa Ziehau /* Turn on receiver */ 3709695a8586SSepherosa Ziehau BNX_SETBIT(sc, BGE_RX_MODE, mode); 37104aa71e73SSepherosa Ziehau DELAY(10); 37116c8d8eccSSepherosa Ziehau 37126c8d8eccSSepherosa Ziehau /* 37136c8d8eccSSepherosa Ziehau * Set the number of good frames to receive after RX MBUF 37146c8d8eccSSepherosa Ziehau * Low Watermark has been reached. After the RX MAC receives 37156c8d8eccSSepherosa Ziehau * this number of frames, it will drop subsequent incoming 37166c8d8eccSSepherosa Ziehau * frames until the MBUF High Watermark is reached. 37176c8d8eccSSepherosa Ziehau */ 3718bcb29629SSepherosa Ziehau if (BNX_IS_57765_FAMILY(sc)) 37196c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_MAX_RX_FRAME_LOWAT, 1); 37206c8d8eccSSepherosa Ziehau else 37216c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_MAX_RX_FRAME_LOWAT, 2); 37226c8d8eccSSepherosa Ziehau 3723695a8586SSepherosa Ziehau if (sc->bnx_intr_type == PCI_INTR_TYPE_MSI || 3724695a8586SSepherosa Ziehau sc->bnx_intr_type == PCI_INTR_TYPE_MSIX) { 37256c8d8eccSSepherosa Ziehau if (bootverbose) { 37266c8d8eccSSepherosa Ziehau if_printf(ifp, "MSI_MODE: %#x\n", 37276c8d8eccSSepherosa Ziehau CSR_READ_4(sc, BGE_MSI_MODE)); 37286c8d8eccSSepherosa Ziehau } 37296c8d8eccSSepherosa Ziehau } 37306c8d8eccSSepherosa Ziehau 37316c8d8eccSSepherosa Ziehau /* Tell firmware we're alive. */ 37326c8d8eccSSepherosa Ziehau BNX_SETBIT(sc, BGE_MODE_CTL, BGE_MODECTL_STACKUP); 37336c8d8eccSSepherosa Ziehau 37346c8d8eccSSepherosa Ziehau /* Enable host interrupts if polling(4) is not enabled. */ 37356c8d8eccSSepherosa Ziehau PCI_SETBIT(sc->bnx_dev, BGE_PCI_MISC_CTL, BGE_PCIMISCCTL_CLEAR_INTA, 4); 37367dbaa833SSepherosa Ziehau 37377dbaa833SSepherosa Ziehau polling = FALSE; 373839a8d43aSSepherosa Ziehau #ifdef IFPOLL_ENABLE 373939a8d43aSSepherosa Ziehau if (ifp->if_flags & IFF_NPOLLING) 37407dbaa833SSepherosa Ziehau polling = TRUE; 37417dbaa833SSepherosa Ziehau #endif 37427dbaa833SSepherosa Ziehau if (polling) 37436c8d8eccSSepherosa Ziehau bnx_disable_intr(sc); 37446c8d8eccSSepherosa Ziehau else 37456c8d8eccSSepherosa Ziehau bnx_enable_intr(sc); 37467dbaa833SSepherosa Ziehau bnx_set_tick_cpuid(sc, polling); 37476c8d8eccSSepherosa Ziehau 37486c8d8eccSSepherosa Ziehau ifp->if_flags |= IFF_RUNNING; 37493397dea6SSepherosa Ziehau for (i = 0; i < sc->bnx_tx_ringcnt; ++i) { 37503397dea6SSepherosa Ziehau struct bnx_tx_ring *txr = &sc->bnx_tx_ring[i]; 37513397dea6SSepherosa Ziehau 37523397dea6SSepherosa Ziehau ifsq_clr_oactive(txr->bnx_ifsq); 37533397dea6SSepherosa Ziehau ifsq_watchdog_start(&txr->bnx_tx_watchdog); 37543397dea6SSepherosa Ziehau } 37556c8d8eccSSepherosa Ziehau 37564aa71e73SSepherosa Ziehau bnx_ifmedia_upd(ifp); 37574aa71e73SSepherosa Ziehau 37587dbaa833SSepherosa Ziehau callout_reset_bycpu(&sc->bnx_tick_timer, hz, bnx_tick, sc, 37597dbaa833SSepherosa Ziehau sc->bnx_tick_cpuid); 37606c8d8eccSSepherosa Ziehau } 37616c8d8eccSSepherosa Ziehau 37626c8d8eccSSepherosa Ziehau /* 37636c8d8eccSSepherosa Ziehau * Set media options. 37646c8d8eccSSepherosa Ziehau */ 37656c8d8eccSSepherosa Ziehau static int 37666c8d8eccSSepherosa Ziehau bnx_ifmedia_upd(struct ifnet *ifp) 37676c8d8eccSSepherosa Ziehau { 37686c8d8eccSSepherosa Ziehau struct bnx_softc *sc = ifp->if_softc; 37696c8d8eccSSepherosa Ziehau 37706c8d8eccSSepherosa Ziehau /* If this is a 1000baseX NIC, enable the TBI port. */ 37716c8d8eccSSepherosa Ziehau if (sc->bnx_flags & BNX_FLAG_TBI) { 37726c8d8eccSSepherosa Ziehau struct ifmedia *ifm = &sc->bnx_ifmedia; 37736c8d8eccSSepherosa Ziehau 37746c8d8eccSSepherosa Ziehau if (IFM_TYPE(ifm->ifm_media) != IFM_ETHER) 37756c8d8eccSSepherosa Ziehau return(EINVAL); 37766c8d8eccSSepherosa Ziehau 37776c8d8eccSSepherosa Ziehau switch(IFM_SUBTYPE(ifm->ifm_media)) { 37786c8d8eccSSepherosa Ziehau case IFM_AUTO: 37796c8d8eccSSepherosa Ziehau break; 37806c8d8eccSSepherosa Ziehau 37816c8d8eccSSepherosa Ziehau case IFM_1000_SX: 37826c8d8eccSSepherosa Ziehau if ((ifm->ifm_media & IFM_GMASK) == IFM_FDX) { 37836c8d8eccSSepherosa Ziehau BNX_CLRBIT(sc, BGE_MAC_MODE, 37846c8d8eccSSepherosa Ziehau BGE_MACMODE_HALF_DUPLEX); 37856c8d8eccSSepherosa Ziehau } else { 37866c8d8eccSSepherosa Ziehau BNX_SETBIT(sc, BGE_MAC_MODE, 37876c8d8eccSSepherosa Ziehau BGE_MACMODE_HALF_DUPLEX); 37886c8d8eccSSepherosa Ziehau } 37894aa71e73SSepherosa Ziehau DELAY(40); 37906c8d8eccSSepherosa Ziehau break; 37916c8d8eccSSepherosa Ziehau default: 37926c8d8eccSSepherosa Ziehau return(EINVAL); 37936c8d8eccSSepherosa Ziehau } 37946c8d8eccSSepherosa Ziehau } else { 37956c8d8eccSSepherosa Ziehau struct mii_data *mii = device_get_softc(sc->bnx_miibus); 37966c8d8eccSSepherosa Ziehau 37976c8d8eccSSepherosa Ziehau sc->bnx_link_evt++; 37986c8d8eccSSepherosa Ziehau sc->bnx_link = 0; 37996c8d8eccSSepherosa Ziehau if (mii->mii_instance) { 38006c8d8eccSSepherosa Ziehau struct mii_softc *miisc; 38016c8d8eccSSepherosa Ziehau 38026c8d8eccSSepherosa Ziehau LIST_FOREACH(miisc, &mii->mii_phys, mii_list) 38036c8d8eccSSepherosa Ziehau mii_phy_reset(miisc); 38046c8d8eccSSepherosa Ziehau } 38056c8d8eccSSepherosa Ziehau mii_mediachg(mii); 38066c8d8eccSSepherosa Ziehau 38076c8d8eccSSepherosa Ziehau /* 38086c8d8eccSSepherosa Ziehau * Force an interrupt so that we will call bnx_link_upd 38096c8d8eccSSepherosa Ziehau * if needed and clear any pending link state attention. 38106c8d8eccSSepherosa Ziehau * Without this we are not getting any further interrupts 38116c8d8eccSSepherosa Ziehau * for link state changes and thus will not UP the link and 38126c8d8eccSSepherosa Ziehau * not be able to send in bnx_start. The only way to get 38136c8d8eccSSepherosa Ziehau * things working was to receive a packet and get an RX 38146c8d8eccSSepherosa Ziehau * intr. 38156c8d8eccSSepherosa Ziehau * 38166c8d8eccSSepherosa Ziehau * bnx_tick should help for fiber cards and we might not 38176c8d8eccSSepherosa Ziehau * need to do this here if BNX_FLAG_TBI is set but as 38186c8d8eccSSepherosa Ziehau * we poll for fiber anyway it should not harm. 38196c8d8eccSSepherosa Ziehau */ 38206c8d8eccSSepherosa Ziehau BNX_SETBIT(sc, BGE_HCC_MODE, BGE_HCCMODE_COAL_NOW); 38216c8d8eccSSepherosa Ziehau } 38226c8d8eccSSepherosa Ziehau return(0); 38236c8d8eccSSepherosa Ziehau } 38246c8d8eccSSepherosa Ziehau 38256c8d8eccSSepherosa Ziehau /* 38266c8d8eccSSepherosa Ziehau * Report current media status. 38276c8d8eccSSepherosa Ziehau */ 38286c8d8eccSSepherosa Ziehau static void 38296c8d8eccSSepherosa Ziehau bnx_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr) 38306c8d8eccSSepherosa Ziehau { 38316c8d8eccSSepherosa Ziehau struct bnx_softc *sc = ifp->if_softc; 38326c8d8eccSSepherosa Ziehau 38334aa71e73SSepherosa Ziehau if ((ifp->if_flags & IFF_RUNNING) == 0) 38344aa71e73SSepherosa Ziehau return; 38354aa71e73SSepherosa Ziehau 38366c8d8eccSSepherosa Ziehau if (sc->bnx_flags & BNX_FLAG_TBI) { 38376c8d8eccSSepherosa Ziehau ifmr->ifm_status = IFM_AVALID; 38386c8d8eccSSepherosa Ziehau ifmr->ifm_active = IFM_ETHER; 38396c8d8eccSSepherosa Ziehau if (CSR_READ_4(sc, BGE_MAC_STS) & 38406c8d8eccSSepherosa Ziehau BGE_MACSTAT_TBI_PCS_SYNCHED) { 38416c8d8eccSSepherosa Ziehau ifmr->ifm_status |= IFM_ACTIVE; 38426c8d8eccSSepherosa Ziehau } else { 38436c8d8eccSSepherosa Ziehau ifmr->ifm_active |= IFM_NONE; 38446c8d8eccSSepherosa Ziehau return; 38456c8d8eccSSepherosa Ziehau } 38466c8d8eccSSepherosa Ziehau 38476c8d8eccSSepherosa Ziehau ifmr->ifm_active |= IFM_1000_SX; 38486c8d8eccSSepherosa Ziehau if (CSR_READ_4(sc, BGE_MAC_MODE) & BGE_MACMODE_HALF_DUPLEX) 38496c8d8eccSSepherosa Ziehau ifmr->ifm_active |= IFM_HDX; 38506c8d8eccSSepherosa Ziehau else 38516c8d8eccSSepherosa Ziehau ifmr->ifm_active |= IFM_FDX; 38526c8d8eccSSepherosa Ziehau } else { 38536c8d8eccSSepherosa Ziehau struct mii_data *mii = device_get_softc(sc->bnx_miibus); 38546c8d8eccSSepherosa Ziehau 38556c8d8eccSSepherosa Ziehau mii_pollstat(mii); 38566c8d8eccSSepherosa Ziehau ifmr->ifm_active = mii->mii_media_active; 38576c8d8eccSSepherosa Ziehau ifmr->ifm_status = mii->mii_media_status; 38586c8d8eccSSepherosa Ziehau } 38596c8d8eccSSepherosa Ziehau } 38606c8d8eccSSepherosa Ziehau 38616c8d8eccSSepherosa Ziehau static int 38626c8d8eccSSepherosa Ziehau bnx_ioctl(struct ifnet *ifp, u_long command, caddr_t data, struct ucred *cr) 38636c8d8eccSSepherosa Ziehau { 38646c8d8eccSSepherosa Ziehau struct bnx_softc *sc = ifp->if_softc; 38656c8d8eccSSepherosa Ziehau struct ifreq *ifr = (struct ifreq *)data; 38666c8d8eccSSepherosa Ziehau int mask, error = 0; 38676c8d8eccSSepherosa Ziehau 3868329f9016SSepherosa Ziehau ASSERT_IFNET_SERIALIZED_ALL(ifp); 38696c8d8eccSSepherosa Ziehau 38706c8d8eccSSepherosa Ziehau switch (command) { 38716c8d8eccSSepherosa Ziehau case SIOCSIFMTU: 38726c8d8eccSSepherosa Ziehau if ((!BNX_IS_JUMBO_CAPABLE(sc) && ifr->ifr_mtu > ETHERMTU) || 38736c8d8eccSSepherosa Ziehau (BNX_IS_JUMBO_CAPABLE(sc) && 38746c8d8eccSSepherosa Ziehau ifr->ifr_mtu > BNX_JUMBO_MTU)) { 38756c8d8eccSSepherosa Ziehau error = EINVAL; 38766c8d8eccSSepherosa Ziehau } else if (ifp->if_mtu != ifr->ifr_mtu) { 38776c8d8eccSSepherosa Ziehau ifp->if_mtu = ifr->ifr_mtu; 38786c8d8eccSSepherosa Ziehau if (ifp->if_flags & IFF_RUNNING) 38796c8d8eccSSepherosa Ziehau bnx_init(sc); 38806c8d8eccSSepherosa Ziehau } 38816c8d8eccSSepherosa Ziehau break; 38826c8d8eccSSepherosa Ziehau case SIOCSIFFLAGS: 38836c8d8eccSSepherosa Ziehau if (ifp->if_flags & IFF_UP) { 38846c8d8eccSSepherosa Ziehau if (ifp->if_flags & IFF_RUNNING) { 38856c8d8eccSSepherosa Ziehau mask = ifp->if_flags ^ sc->bnx_if_flags; 38866c8d8eccSSepherosa Ziehau 38876c8d8eccSSepherosa Ziehau /* 38886c8d8eccSSepherosa Ziehau * If only the state of the PROMISC flag 38896c8d8eccSSepherosa Ziehau * changed, then just use the 'set promisc 38906c8d8eccSSepherosa Ziehau * mode' command instead of reinitializing 38916c8d8eccSSepherosa Ziehau * the entire NIC. Doing a full re-init 38926c8d8eccSSepherosa Ziehau * means reloading the firmware and waiting 38936c8d8eccSSepherosa Ziehau * for it to start up, which may take a 38946c8d8eccSSepherosa Ziehau * second or two. Similarly for ALLMULTI. 38956c8d8eccSSepherosa Ziehau */ 38966c8d8eccSSepherosa Ziehau if (mask & IFF_PROMISC) 38976c8d8eccSSepherosa Ziehau bnx_setpromisc(sc); 38986c8d8eccSSepherosa Ziehau if (mask & IFF_ALLMULTI) 38996c8d8eccSSepherosa Ziehau bnx_setmulti(sc); 39006c8d8eccSSepherosa Ziehau } else { 39016c8d8eccSSepherosa Ziehau bnx_init(sc); 39026c8d8eccSSepherosa Ziehau } 39036c8d8eccSSepherosa Ziehau } else if (ifp->if_flags & IFF_RUNNING) { 39046c8d8eccSSepherosa Ziehau bnx_stop(sc); 39056c8d8eccSSepherosa Ziehau } 39066c8d8eccSSepherosa Ziehau sc->bnx_if_flags = ifp->if_flags; 39076c8d8eccSSepherosa Ziehau break; 39086c8d8eccSSepherosa Ziehau case SIOCADDMULTI: 39096c8d8eccSSepherosa Ziehau case SIOCDELMULTI: 39106c8d8eccSSepherosa Ziehau if (ifp->if_flags & IFF_RUNNING) 39116c8d8eccSSepherosa Ziehau bnx_setmulti(sc); 39126c8d8eccSSepherosa Ziehau break; 39136c8d8eccSSepherosa Ziehau case SIOCSIFMEDIA: 39146c8d8eccSSepherosa Ziehau case SIOCGIFMEDIA: 39156c8d8eccSSepherosa Ziehau if (sc->bnx_flags & BNX_FLAG_TBI) { 39166c8d8eccSSepherosa Ziehau error = ifmedia_ioctl(ifp, ifr, 39176c8d8eccSSepherosa Ziehau &sc->bnx_ifmedia, command); 39186c8d8eccSSepherosa Ziehau } else { 39196c8d8eccSSepherosa Ziehau struct mii_data *mii; 39206c8d8eccSSepherosa Ziehau 39216c8d8eccSSepherosa Ziehau mii = device_get_softc(sc->bnx_miibus); 39226c8d8eccSSepherosa Ziehau error = ifmedia_ioctl(ifp, ifr, 39236c8d8eccSSepherosa Ziehau &mii->mii_media, command); 39246c8d8eccSSepherosa Ziehau } 39256c8d8eccSSepherosa Ziehau break; 39266c8d8eccSSepherosa Ziehau case SIOCSIFCAP: 39276c8d8eccSSepherosa Ziehau mask = ifr->ifr_reqcap ^ ifp->if_capenable; 39286c8d8eccSSepherosa Ziehau if (mask & IFCAP_HWCSUM) { 39296c8d8eccSSepherosa Ziehau ifp->if_capenable ^= (mask & IFCAP_HWCSUM); 393066deb1c1SSepherosa Ziehau if (ifp->if_capenable & IFCAP_TXCSUM) 393166deb1c1SSepherosa Ziehau ifp->if_hwassist |= BNX_CSUM_FEATURES; 39326c8d8eccSSepherosa Ziehau else 393366deb1c1SSepherosa Ziehau ifp->if_hwassist &= ~BNX_CSUM_FEATURES; 393466deb1c1SSepherosa Ziehau } 393566deb1c1SSepherosa Ziehau if (mask & IFCAP_TSO) { 393666deb1c1SSepherosa Ziehau ifp->if_capenable ^= (mask & IFCAP_TSO); 393766deb1c1SSepherosa Ziehau if (ifp->if_capenable & IFCAP_TSO) 393866deb1c1SSepherosa Ziehau ifp->if_hwassist |= CSUM_TSO; 393966deb1c1SSepherosa Ziehau else 394066deb1c1SSepherosa Ziehau ifp->if_hwassist &= ~CSUM_TSO; 39416c8d8eccSSepherosa Ziehau } 3942b19ddf7eSSepherosa Ziehau if (mask & IFCAP_RSS) 3943b19ddf7eSSepherosa Ziehau ifp->if_capenable ^= IFCAP_RSS; 39446c8d8eccSSepherosa Ziehau break; 39456c8d8eccSSepherosa Ziehau default: 39466c8d8eccSSepherosa Ziehau error = ether_ioctl(ifp, command, data); 39476c8d8eccSSepherosa Ziehau break; 39486c8d8eccSSepherosa Ziehau } 39496c8d8eccSSepherosa Ziehau return error; 39506c8d8eccSSepherosa Ziehau } 39516c8d8eccSSepherosa Ziehau 39526c8d8eccSSepherosa Ziehau static void 39533397dea6SSepherosa Ziehau bnx_watchdog(struct ifaltq_subque *ifsq) 39546c8d8eccSSepherosa Ziehau { 39553397dea6SSepherosa Ziehau struct ifnet *ifp = ifsq_get_ifp(ifsq); 39566c8d8eccSSepherosa Ziehau struct bnx_softc *sc = ifp->if_softc; 39573397dea6SSepherosa Ziehau int i; 39583397dea6SSepherosa Ziehau 39593397dea6SSepherosa Ziehau ASSERT_IFNET_SERIALIZED_ALL(ifp); 39606c8d8eccSSepherosa Ziehau 39616c8d8eccSSepherosa Ziehau if_printf(ifp, "watchdog timeout -- resetting\n"); 39626c8d8eccSSepherosa Ziehau 39636c8d8eccSSepherosa Ziehau bnx_init(sc); 39646c8d8eccSSepherosa Ziehau 3965d40991efSSepherosa Ziehau IFNET_STAT_INC(ifp, oerrors, 1); 39666c8d8eccSSepherosa Ziehau 39673397dea6SSepherosa Ziehau for (i = 0; i < sc->bnx_tx_ringcnt; ++i) 39683397dea6SSepherosa Ziehau ifsq_devstart_sched(sc->bnx_tx_ring[i].bnx_ifsq); 39696c8d8eccSSepherosa Ziehau } 39706c8d8eccSSepherosa Ziehau 39716c8d8eccSSepherosa Ziehau /* 39726c8d8eccSSepherosa Ziehau * Stop the adapter and free any mbufs allocated to the 39736c8d8eccSSepherosa Ziehau * RX and TX lists. 39746c8d8eccSSepherosa Ziehau */ 39756c8d8eccSSepherosa Ziehau static void 39766c8d8eccSSepherosa Ziehau bnx_stop(struct bnx_softc *sc) 39776c8d8eccSSepherosa Ziehau { 39786c8d8eccSSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if; 397933a04907SSepherosa Ziehau int i; 39806c8d8eccSSepherosa Ziehau 3981329f9016SSepherosa Ziehau ASSERT_IFNET_SERIALIZED_ALL(ifp); 39826c8d8eccSSepherosa Ziehau 39837dbaa833SSepherosa Ziehau callout_stop(&sc->bnx_tick_timer); 39846c8d8eccSSepherosa Ziehau 39854aa71e73SSepherosa Ziehau /* Disable host interrupts. */ 39864aa71e73SSepherosa Ziehau bnx_disable_intr(sc); 39874aa71e73SSepherosa Ziehau 39884aa71e73SSepherosa Ziehau /* 39894aa71e73SSepherosa Ziehau * Tell firmware we're shutting down. 39904aa71e73SSepherosa Ziehau */ 39914aa71e73SSepherosa Ziehau bnx_sig_pre_reset(sc, BNX_RESET_SHUTDOWN); 39924aa71e73SSepherosa Ziehau 39936c8d8eccSSepherosa Ziehau /* 39946c8d8eccSSepherosa Ziehau * Disable all of the receiver blocks 39956c8d8eccSSepherosa Ziehau */ 39966c8d8eccSSepherosa Ziehau bnx_stop_block(sc, BGE_RX_MODE, BGE_RXMODE_ENABLE); 39976c8d8eccSSepherosa Ziehau bnx_stop_block(sc, BGE_RBDI_MODE, BGE_RBDIMODE_ENABLE); 39986c8d8eccSSepherosa Ziehau bnx_stop_block(sc, BGE_RXLP_MODE, BGE_RXLPMODE_ENABLE); 39996c8d8eccSSepherosa Ziehau bnx_stop_block(sc, BGE_RDBDI_MODE, BGE_RBDIMODE_ENABLE); 40006c8d8eccSSepherosa Ziehau bnx_stop_block(sc, BGE_RDC_MODE, BGE_RDCMODE_ENABLE); 40016c8d8eccSSepherosa Ziehau bnx_stop_block(sc, BGE_RBDC_MODE, BGE_RBDCMODE_ENABLE); 40026c8d8eccSSepherosa Ziehau 40036c8d8eccSSepherosa Ziehau /* 40046c8d8eccSSepherosa Ziehau * Disable all of the transmit blocks 40056c8d8eccSSepherosa Ziehau */ 40066c8d8eccSSepherosa Ziehau bnx_stop_block(sc, BGE_SRS_MODE, BGE_SRSMODE_ENABLE); 40076c8d8eccSSepherosa Ziehau bnx_stop_block(sc, BGE_SBDI_MODE, BGE_SBDIMODE_ENABLE); 40086c8d8eccSSepherosa Ziehau bnx_stop_block(sc, BGE_SDI_MODE, BGE_SDIMODE_ENABLE); 40096c8d8eccSSepherosa Ziehau bnx_stop_block(sc, BGE_RDMA_MODE, BGE_RDMAMODE_ENABLE); 40106c8d8eccSSepherosa Ziehau bnx_stop_block(sc, BGE_SDC_MODE, BGE_SDCMODE_ENABLE); 40116c8d8eccSSepherosa Ziehau bnx_stop_block(sc, BGE_SBDC_MODE, BGE_SBDCMODE_ENABLE); 40126c8d8eccSSepherosa Ziehau 40136c8d8eccSSepherosa Ziehau /* 40146c8d8eccSSepherosa Ziehau * Shut down all of the memory managers and related 40156c8d8eccSSepherosa Ziehau * state machines. 40166c8d8eccSSepherosa Ziehau */ 40176c8d8eccSSepherosa Ziehau bnx_stop_block(sc, BGE_HCC_MODE, BGE_HCCMODE_ENABLE); 40186c8d8eccSSepherosa Ziehau bnx_stop_block(sc, BGE_WDMA_MODE, BGE_WDMAMODE_ENABLE); 40196c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_FTQ_RESET, 0xFFFFFFFF); 40206c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_FTQ_RESET, 0); 40216c8d8eccSSepherosa Ziehau 40224aa71e73SSepherosa Ziehau bnx_reset(sc); 40234aa71e73SSepherosa Ziehau bnx_sig_post_reset(sc, BNX_RESET_SHUTDOWN); 40246c8d8eccSSepherosa Ziehau 40256c8d8eccSSepherosa Ziehau /* 40266c8d8eccSSepherosa Ziehau * Tell firmware we're shutting down. 40276c8d8eccSSepherosa Ziehau */ 40286c8d8eccSSepherosa Ziehau BNX_CLRBIT(sc, BGE_MODE_CTL, BGE_MODECTL_STACKUP); 40296c8d8eccSSepherosa Ziehau 40306c8d8eccSSepherosa Ziehau /* Free the RX lists. */ 4031beedf5beSSepherosa Ziehau bnx_free_rx_ring_std(&sc->bnx_rx_std_ring); 40326c8d8eccSSepherosa Ziehau 40336c8d8eccSSepherosa Ziehau /* Free jumbo RX list. */ 40346c8d8eccSSepherosa Ziehau if (BNX_IS_JUMBO_CAPABLE(sc)) 40356c8d8eccSSepherosa Ziehau bnx_free_rx_ring_jumbo(sc); 40366c8d8eccSSepherosa Ziehau 40376c8d8eccSSepherosa Ziehau /* Free TX buffers. */ 40384fa38985SSepherosa Ziehau for (i = 0; i < sc->bnx_tx_ringcnt; ++i) { 40394fa38985SSepherosa Ziehau struct bnx_tx_ring *txr = &sc->bnx_tx_ring[i]; 40406c8d8eccSSepherosa Ziehau 40414fa38985SSepherosa Ziehau txr->bnx_saved_status_tag = 0; 40424fa38985SSepherosa Ziehau bnx_free_tx_ring(txr); 40434fa38985SSepherosa Ziehau } 40444fa38985SSepherosa Ziehau 40454fa38985SSepherosa Ziehau /* Clear saved status tag */ 40464fa38985SSepherosa Ziehau for (i = 0; i < sc->bnx_rx_retcnt; ++i) 40474fa38985SSepherosa Ziehau sc->bnx_rx_ret_ring[i].bnx_saved_status_tag = 0; 40484fa38985SSepherosa Ziehau 40496c8d8eccSSepherosa Ziehau sc->bnx_link = 0; 40506c8d8eccSSepherosa Ziehau sc->bnx_coal_chg = 0; 40516c8d8eccSSepherosa Ziehau 40529ed293e0SSepherosa Ziehau ifp->if_flags &= ~IFF_RUNNING; 40533397dea6SSepherosa Ziehau for (i = 0; i < sc->bnx_tx_ringcnt; ++i) { 40543397dea6SSepherosa Ziehau struct bnx_tx_ring *txr = &sc->bnx_tx_ring[i]; 40553397dea6SSepherosa Ziehau 40563397dea6SSepherosa Ziehau ifsq_clr_oactive(txr->bnx_ifsq); 40573397dea6SSepherosa Ziehau ifsq_watchdog_stop(&txr->bnx_tx_watchdog); 40583397dea6SSepherosa Ziehau } 40596c8d8eccSSepherosa Ziehau } 40606c8d8eccSSepherosa Ziehau 40616c8d8eccSSepherosa Ziehau /* 40626c8d8eccSSepherosa Ziehau * Stop all chip I/O so that the kernel's probe routines don't 40636c8d8eccSSepherosa Ziehau * get confused by errant DMAs when rebooting. 40646c8d8eccSSepherosa Ziehau */ 40656c8d8eccSSepherosa Ziehau static void 40666c8d8eccSSepherosa Ziehau bnx_shutdown(device_t dev) 40676c8d8eccSSepherosa Ziehau { 40686c8d8eccSSepherosa Ziehau struct bnx_softc *sc = device_get_softc(dev); 40696c8d8eccSSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if; 40706c8d8eccSSepherosa Ziehau 4071329f9016SSepherosa Ziehau ifnet_serialize_all(ifp); 40726c8d8eccSSepherosa Ziehau bnx_stop(sc); 4073329f9016SSepherosa Ziehau ifnet_deserialize_all(ifp); 40746c8d8eccSSepherosa Ziehau } 40756c8d8eccSSepherosa Ziehau 40766c8d8eccSSepherosa Ziehau static int 40776c8d8eccSSepherosa Ziehau bnx_suspend(device_t dev) 40786c8d8eccSSepherosa Ziehau { 40796c8d8eccSSepherosa Ziehau struct bnx_softc *sc = device_get_softc(dev); 40806c8d8eccSSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if; 40816c8d8eccSSepherosa Ziehau 4082329f9016SSepherosa Ziehau ifnet_serialize_all(ifp); 40836c8d8eccSSepherosa Ziehau bnx_stop(sc); 4084329f9016SSepherosa Ziehau ifnet_deserialize_all(ifp); 40856c8d8eccSSepherosa Ziehau 40866c8d8eccSSepherosa Ziehau return 0; 40876c8d8eccSSepherosa Ziehau } 40886c8d8eccSSepherosa Ziehau 40896c8d8eccSSepherosa Ziehau static int 40906c8d8eccSSepherosa Ziehau bnx_resume(device_t dev) 40916c8d8eccSSepherosa Ziehau { 40926c8d8eccSSepherosa Ziehau struct bnx_softc *sc = device_get_softc(dev); 40936c8d8eccSSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if; 40946c8d8eccSSepherosa Ziehau 4095329f9016SSepherosa Ziehau ifnet_serialize_all(ifp); 40966c8d8eccSSepherosa Ziehau 40976c8d8eccSSepherosa Ziehau if (ifp->if_flags & IFF_UP) { 40983397dea6SSepherosa Ziehau int i; 40996c8d8eccSSepherosa Ziehau 41003397dea6SSepherosa Ziehau bnx_init(sc); 41013397dea6SSepherosa Ziehau for (i = 0; i < sc->bnx_tx_ringcnt; ++i) 41023397dea6SSepherosa Ziehau ifsq_devstart_sched(sc->bnx_tx_ring[i].bnx_ifsq); 41036c8d8eccSSepherosa Ziehau } 41046c8d8eccSSepherosa Ziehau 4105329f9016SSepherosa Ziehau ifnet_deserialize_all(ifp); 41066c8d8eccSSepherosa Ziehau 41076c8d8eccSSepherosa Ziehau return 0; 41086c8d8eccSSepherosa Ziehau } 41096c8d8eccSSepherosa Ziehau 41106c8d8eccSSepherosa Ziehau static void 41116c8d8eccSSepherosa Ziehau bnx_setpromisc(struct bnx_softc *sc) 41126c8d8eccSSepherosa Ziehau { 41136c8d8eccSSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if; 41146c8d8eccSSepherosa Ziehau 41156c8d8eccSSepherosa Ziehau if (ifp->if_flags & IFF_PROMISC) 41166c8d8eccSSepherosa Ziehau BNX_SETBIT(sc, BGE_RX_MODE, BGE_RXMODE_RX_PROMISC); 41176c8d8eccSSepherosa Ziehau else 41186c8d8eccSSepherosa Ziehau BNX_CLRBIT(sc, BGE_RX_MODE, BGE_RXMODE_RX_PROMISC); 41196c8d8eccSSepherosa Ziehau } 41206c8d8eccSSepherosa Ziehau 41216c8d8eccSSepherosa Ziehau static void 41226c8d8eccSSepherosa Ziehau bnx_dma_free(struct bnx_softc *sc) 41236c8d8eccSSepherosa Ziehau { 4124beedf5beSSepherosa Ziehau struct bnx_rx_std_ring *std = &sc->bnx_rx_std_ring; 41256c8d8eccSSepherosa Ziehau int i; 41266c8d8eccSSepherosa Ziehau 4127beedf5beSSepherosa Ziehau /* Destroy RX return rings */ 4128beedf5beSSepherosa Ziehau if (sc->bnx_rx_ret_ring != NULL) { 4129beedf5beSSepherosa Ziehau for (i = 0; i < sc->bnx_rx_retcnt; ++i) 4130beedf5beSSepherosa Ziehau bnx_destroy_rx_ret_ring(&sc->bnx_rx_ret_ring[i]); 4131beedf5beSSepherosa Ziehau kfree(sc->bnx_rx_ret_ring, M_DEVBUF); 4132beedf5beSSepherosa Ziehau } 4133beedf5beSSepherosa Ziehau 41346c8d8eccSSepherosa Ziehau /* Destroy RX mbuf DMA stuffs. */ 4135beedf5beSSepherosa Ziehau if (std->bnx_rx_mtag != NULL) { 41366c8d8eccSSepherosa Ziehau for (i = 0; i < BGE_STD_RX_RING_CNT; i++) { 4137beedf5beSSepherosa Ziehau KKASSERT(std->bnx_rx_std_buf[i].bnx_rx_mbuf == NULL); 4138beedf5beSSepherosa Ziehau bus_dmamap_destroy(std->bnx_rx_mtag, 4139beedf5beSSepherosa Ziehau std->bnx_rx_std_buf[i].bnx_rx_dmamap); 41406c8d8eccSSepherosa Ziehau } 4141beedf5beSSepherosa Ziehau bus_dma_tag_destroy(std->bnx_rx_mtag); 41426c8d8eccSSepherosa Ziehau } 41436c8d8eccSSepherosa Ziehau 4144beedf5beSSepherosa Ziehau /* Destroy standard RX ring */ 4145beedf5beSSepherosa Ziehau bnx_dma_block_free(std->bnx_rx_std_ring_tag, 4146beedf5beSSepherosa Ziehau std->bnx_rx_std_ring_map, std->bnx_rx_std_ring); 4147beedf5beSSepherosa Ziehau 414833a04907SSepherosa Ziehau /* Destroy TX rings */ 414933a04907SSepherosa Ziehau if (sc->bnx_tx_ring != NULL) { 415033a04907SSepherosa Ziehau for (i = 0; i < sc->bnx_tx_ringcnt; ++i) 415133a04907SSepherosa Ziehau bnx_destroy_tx_ring(&sc->bnx_tx_ring[i]); 415233a04907SSepherosa Ziehau kfree(sc->bnx_tx_ring, M_DEVBUF); 41536c8d8eccSSepherosa Ziehau } 41546c8d8eccSSepherosa Ziehau 41556c8d8eccSSepherosa Ziehau if (BNX_IS_JUMBO_CAPABLE(sc)) 41566c8d8eccSSepherosa Ziehau bnx_free_jumbo_mem(sc); 41576c8d8eccSSepherosa Ziehau 41580a806e3aSSepherosa Ziehau /* Destroy status blocks */ 41590a806e3aSSepherosa Ziehau for (i = 0; i < sc->bnx_intr_cnt; ++i) { 41600a806e3aSSepherosa Ziehau struct bnx_intr_data *intr = &sc->bnx_intr_data[i]; 41610a806e3aSSepherosa Ziehau 41620a806e3aSSepherosa Ziehau bnx_dma_block_free(intr->bnx_status_tag, 41630a806e3aSSepherosa Ziehau intr->bnx_status_map, intr->bnx_status_block); 41640a806e3aSSepherosa Ziehau } 41656c8d8eccSSepherosa Ziehau 41666c8d8eccSSepherosa Ziehau /* Destroy the parent tag */ 41676c8d8eccSSepherosa Ziehau if (sc->bnx_cdata.bnx_parent_tag != NULL) 41686c8d8eccSSepherosa Ziehau bus_dma_tag_destroy(sc->bnx_cdata.bnx_parent_tag); 41696c8d8eccSSepherosa Ziehau } 41706c8d8eccSSepherosa Ziehau 41716c8d8eccSSepherosa Ziehau static int 4172beedf5beSSepherosa Ziehau bnx_dma_alloc(device_t dev) 41736c8d8eccSSepherosa Ziehau { 4174beedf5beSSepherosa Ziehau struct bnx_softc *sc = device_get_softc(dev); 4175beedf5beSSepherosa Ziehau struct bnx_rx_std_ring *std = &sc->bnx_rx_std_ring; 4176ac2936fdSSepherosa Ziehau int i, error, mbx; 41776c8d8eccSSepherosa Ziehau 41786c8d8eccSSepherosa Ziehau /* 41796c8d8eccSSepherosa Ziehau * Allocate the parent bus DMA tag appropriate for PCI. 41806c8d8eccSSepherosa Ziehau * 41816c8d8eccSSepherosa Ziehau * All of the NetExtreme/NetLink controllers have 4GB boundary 41826c8d8eccSSepherosa Ziehau * DMA bug. 41836c8d8eccSSepherosa Ziehau * Whenever an address crosses a multiple of the 4GB boundary 41846c8d8eccSSepherosa Ziehau * (including 4GB, 8Gb, 12Gb, etc.) and makes the transition 41856c8d8eccSSepherosa Ziehau * from 0xX_FFFF_FFFF to 0x(X+1)_0000_0000 an internal DMA 41866c8d8eccSSepherosa Ziehau * state machine will lockup and cause the device to hang. 41876c8d8eccSSepherosa Ziehau */ 41886c8d8eccSSepherosa Ziehau error = bus_dma_tag_create(NULL, 1, BGE_DMA_BOUNDARY_4G, 4189beedf5beSSepherosa Ziehau BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL, NULL, 4190beedf5beSSepherosa Ziehau BUS_SPACE_MAXSIZE_32BIT, 0, BUS_SPACE_MAXSIZE_32BIT, 41916c8d8eccSSepherosa Ziehau 0, &sc->bnx_cdata.bnx_parent_tag); 41926c8d8eccSSepherosa Ziehau if (error) { 4193beedf5beSSepherosa Ziehau device_printf(dev, "could not create parent DMA tag\n"); 41946c8d8eccSSepherosa Ziehau return error; 41956c8d8eccSSepherosa Ziehau } 41966c8d8eccSSepherosa Ziehau 41976c8d8eccSSepherosa Ziehau /* 41980a806e3aSSepherosa Ziehau * Create DMA stuffs for status blocks. 41996c8d8eccSSepherosa Ziehau */ 42000a806e3aSSepherosa Ziehau for (i = 0; i < sc->bnx_intr_cnt; ++i) { 42010a806e3aSSepherosa Ziehau struct bnx_intr_data *intr = &sc->bnx_intr_data[i]; 42020a806e3aSSepherosa Ziehau 4203695a8586SSepherosa Ziehau error = bnx_dma_block_alloc(sc, 4204695a8586SSepherosa Ziehau __VM_CACHELINE_ALIGN(BGE_STATUS_BLK_SZ), 42050a806e3aSSepherosa Ziehau &intr->bnx_status_tag, &intr->bnx_status_map, 42060a806e3aSSepherosa Ziehau (void *)&intr->bnx_status_block, 42070a806e3aSSepherosa Ziehau &intr->bnx_status_block_paddr); 42086c8d8eccSSepherosa Ziehau if (error) { 42090a806e3aSSepherosa Ziehau device_printf(dev, 42100a806e3aSSepherosa Ziehau "could not create %dth status block\n", i); 42116c8d8eccSSepherosa Ziehau return error; 42126c8d8eccSSepherosa Ziehau } 42130a806e3aSSepherosa Ziehau } 4214695a8586SSepherosa Ziehau sc->bnx_hw_status = &sc->bnx_intr_data[0].bnx_status_block->bge_status; 4215695a8586SSepherosa Ziehau if (sc->bnx_flags & BNX_FLAG_STATUS_HASTAG) { 4216695a8586SSepherosa Ziehau sc->bnx_hw_status_tag = 4217695a8586SSepherosa Ziehau &sc->bnx_intr_data[0].bnx_status_block->bge_status_tag; 4218695a8586SSepherosa Ziehau } 42196c8d8eccSSepherosa Ziehau 4220beedf5beSSepherosa Ziehau /* 4221beedf5beSSepherosa Ziehau * Create DMA tag and maps for RX mbufs. 4222beedf5beSSepherosa Ziehau */ 4223beedf5beSSepherosa Ziehau std->bnx_sc = sc; 4224329f9016SSepherosa Ziehau lwkt_serialize_init(&std->bnx_rx_std_serialize); 4225beedf5beSSepherosa Ziehau error = bus_dma_tag_create(sc->bnx_cdata.bnx_parent_tag, 1, 0, 4226beedf5beSSepherosa Ziehau BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, 4227beedf5beSSepherosa Ziehau NULL, NULL, MCLBYTES, 1, MCLBYTES, 4228beedf5beSSepherosa Ziehau BUS_DMA_ALLOCNOW | BUS_DMA_WAITOK, &std->bnx_rx_mtag); 4229beedf5beSSepherosa Ziehau if (error) { 4230beedf5beSSepherosa Ziehau device_printf(dev, "could not create RX mbuf DMA tag\n"); 4231beedf5beSSepherosa Ziehau return error; 4232beedf5beSSepherosa Ziehau } 4233beedf5beSSepherosa Ziehau 4234beedf5beSSepherosa Ziehau for (i = 0; i < BGE_STD_RX_RING_CNT; ++i) { 4235beedf5beSSepherosa Ziehau error = bus_dmamap_create(std->bnx_rx_mtag, BUS_DMA_WAITOK, 4236beedf5beSSepherosa Ziehau &std->bnx_rx_std_buf[i].bnx_rx_dmamap); 4237beedf5beSSepherosa Ziehau if (error) { 4238beedf5beSSepherosa Ziehau int j; 4239beedf5beSSepherosa Ziehau 4240beedf5beSSepherosa Ziehau for (j = 0; j < i; ++j) { 4241beedf5beSSepherosa Ziehau bus_dmamap_destroy(std->bnx_rx_mtag, 4242beedf5beSSepherosa Ziehau std->bnx_rx_std_buf[j].bnx_rx_dmamap); 4243beedf5beSSepherosa Ziehau } 4244beedf5beSSepherosa Ziehau bus_dma_tag_destroy(std->bnx_rx_mtag); 4245beedf5beSSepherosa Ziehau std->bnx_rx_mtag = NULL; 4246beedf5beSSepherosa Ziehau 4247beedf5beSSepherosa Ziehau device_printf(dev, 4248beedf5beSSepherosa Ziehau "could not create %dth RX mbuf DMA map\n", i); 4249beedf5beSSepherosa Ziehau return error; 4250beedf5beSSepherosa Ziehau } 4251beedf5beSSepherosa Ziehau } 4252beedf5beSSepherosa Ziehau 4253beedf5beSSepherosa Ziehau /* 4254beedf5beSSepherosa Ziehau * Create DMA stuffs for standard RX ring. 4255beedf5beSSepherosa Ziehau */ 4256beedf5beSSepherosa Ziehau error = bnx_dma_block_alloc(sc, BGE_STD_RX_RING_SZ, 4257beedf5beSSepherosa Ziehau &std->bnx_rx_std_ring_tag, 4258beedf5beSSepherosa Ziehau &std->bnx_rx_std_ring_map, 4259beedf5beSSepherosa Ziehau (void *)&std->bnx_rx_std_ring, 4260beedf5beSSepherosa Ziehau &std->bnx_rx_std_ring_paddr); 4261beedf5beSSepherosa Ziehau if (error) { 4262beedf5beSSepherosa Ziehau device_printf(dev, "could not create std RX ring\n"); 4263beedf5beSSepherosa Ziehau return error; 4264beedf5beSSepherosa Ziehau } 4265beedf5beSSepherosa Ziehau 4266beedf5beSSepherosa Ziehau /* 4267beedf5beSSepherosa Ziehau * Create RX return rings 4268beedf5beSSepherosa Ziehau */ 4269ac2936fdSSepherosa Ziehau mbx = BGE_MBX_RX_CONS0_LO; 4270beedf5beSSepherosa Ziehau sc->bnx_rx_ret_ring = kmalloc_cachealign( 4271beedf5beSSepherosa Ziehau sizeof(struct bnx_rx_ret_ring) * sc->bnx_rx_retcnt, M_DEVBUF, 4272beedf5beSSepherosa Ziehau M_WAITOK | M_ZERO); 4273beedf5beSSepherosa Ziehau for (i = 0; i < sc->bnx_rx_retcnt; ++i) { 4274beedf5beSSepherosa Ziehau struct bnx_rx_ret_ring *ret = &sc->bnx_rx_ret_ring[i]; 42750a806e3aSSepherosa Ziehau struct bnx_intr_data *intr; 4276beedf5beSSepherosa Ziehau 4277beedf5beSSepherosa Ziehau ret->bnx_sc = sc; 4278beedf5beSSepherosa Ziehau ret->bnx_std = std; 4279ac2936fdSSepherosa Ziehau ret->bnx_rx_mbx = mbx; 4280841cdf08SSepherosa Ziehau ret->bnx_rx_cntmax = (BGE_STD_RX_RING_CNT / 4) / 4281841cdf08SSepherosa Ziehau sc->bnx_rx_retcnt; 4282841cdf08SSepherosa Ziehau ret->bnx_rx_mask = 1 << i; 42833a16b7b8SSepherosa Ziehau 4284695a8586SSepherosa Ziehau if (!BNX_RSS_ENABLED(sc)) { 42850a806e3aSSepherosa Ziehau intr = &sc->bnx_intr_data[0]; 42860a806e3aSSepherosa Ziehau } else { 42870a806e3aSSepherosa Ziehau KKASSERT(i + 1 < sc->bnx_intr_cnt); 42880a806e3aSSepherosa Ziehau intr = &sc->bnx_intr_data[i + 1]; 42890a806e3aSSepherosa Ziehau } 42900a806e3aSSepherosa Ziehau 4291695a8586SSepherosa Ziehau if (i == 0) { 42923a16b7b8SSepherosa Ziehau ret->bnx_rx_considx = 42930a806e3aSSepherosa Ziehau &intr->bnx_status_block->bge_idx[0].bge_rx_prod_idx; 4294695a8586SSepherosa Ziehau } else if (i == 1) { 4295695a8586SSepherosa Ziehau ret->bnx_rx_considx = 4296695a8586SSepherosa Ziehau &intr->bnx_status_block->bge_rx_jumbo_cons_idx; 4297695a8586SSepherosa Ziehau } else if (i == 2) { 4298695a8586SSepherosa Ziehau ret->bnx_rx_considx = 4299695a8586SSepherosa Ziehau &intr->bnx_status_block->bge_rsvd1; 4300695a8586SSepherosa Ziehau } else if (i == 3) { 4301695a8586SSepherosa Ziehau ret->bnx_rx_considx = 4302695a8586SSepherosa Ziehau &intr->bnx_status_block->bge_rx_mini_cons_idx; 4303695a8586SSepherosa Ziehau } else { 4304695a8586SSepherosa Ziehau panic("unknown RX return ring %d\n", i); 4305695a8586SSepherosa Ziehau } 43064fa38985SSepherosa Ziehau ret->bnx_hw_status_tag = 43070a806e3aSSepherosa Ziehau &intr->bnx_status_block->bge_status_tag; 43083a16b7b8SSepherosa Ziehau 4309beedf5beSSepherosa Ziehau error = bnx_create_rx_ret_ring(ret); 4310beedf5beSSepherosa Ziehau if (error) { 4311beedf5beSSepherosa Ziehau device_printf(dev, 4312beedf5beSSepherosa Ziehau "could not create %dth RX ret ring\n", i); 4313beedf5beSSepherosa Ziehau return error; 4314beedf5beSSepherosa Ziehau } 4315ac2936fdSSepherosa Ziehau mbx += 8; 4316beedf5beSSepherosa Ziehau } 4317beedf5beSSepherosa Ziehau 4318beedf5beSSepherosa Ziehau /* 4319beedf5beSSepherosa Ziehau * Create TX rings 4320beedf5beSSepherosa Ziehau */ 432133a04907SSepherosa Ziehau sc->bnx_tx_ring = kmalloc_cachealign( 432233a04907SSepherosa Ziehau sizeof(struct bnx_tx_ring) * sc->bnx_tx_ringcnt, M_DEVBUF, 432333a04907SSepherosa Ziehau M_WAITOK | M_ZERO); 432433a04907SSepherosa Ziehau for (i = 0; i < sc->bnx_tx_ringcnt; ++i) { 432533a04907SSepherosa Ziehau struct bnx_tx_ring *txr = &sc->bnx_tx_ring[i]; 43260a806e3aSSepherosa Ziehau struct bnx_intr_data *intr; 432733a04907SSepherosa Ziehau 432833a04907SSepherosa Ziehau txr->bnx_sc = sc; 43291c9d03f6SSepherosa Ziehau txr->bnx_tx_mbx = bnx_tx_mailbox[i]; 43308bd43d5dSSepherosa Ziehau 43310a806e3aSSepherosa Ziehau if (sc->bnx_tx_ringcnt == 1) { 43320a806e3aSSepherosa Ziehau intr = &sc->bnx_intr_data[0]; 43330a806e3aSSepherosa Ziehau } else { 43340a806e3aSSepherosa Ziehau KKASSERT(i + 1 < sc->bnx_intr_cnt); 43350a806e3aSSepherosa Ziehau intr = &sc->bnx_intr_data[i + 1]; 43360a806e3aSSepherosa Ziehau } 43370a806e3aSSepherosa Ziehau 4338695a8586SSepherosa Ziehau if ((sc->bnx_flags & BNX_FLAG_RXTX_BUNDLE) == 0) { 4339695a8586SSepherosa Ziehau txr->bnx_hw_status_tag = 4340695a8586SSepherosa Ziehau &intr->bnx_status_block->bge_status_tag; 4341695a8586SSepherosa Ziehau } 43423a16b7b8SSepherosa Ziehau txr->bnx_tx_considx = 43430a806e3aSSepherosa Ziehau &intr->bnx_status_block->bge_idx[0].bge_tx_cons_idx; 43443a16b7b8SSepherosa Ziehau 434533a04907SSepherosa Ziehau error = bnx_create_tx_ring(txr); 434633a04907SSepherosa Ziehau if (error) { 4347beedf5beSSepherosa Ziehau device_printf(dev, 4348beedf5beSSepherosa Ziehau "could not create %dth TX ring\n", i); 4349beedf5beSSepherosa Ziehau return error; 4350beedf5beSSepherosa Ziehau } 4351beedf5beSSepherosa Ziehau } 4352beedf5beSSepherosa Ziehau 4353beedf5beSSepherosa Ziehau /* 4354beedf5beSSepherosa Ziehau * Create jumbo buffer pool. 4355beedf5beSSepherosa Ziehau */ 4356beedf5beSSepherosa Ziehau if (BNX_IS_JUMBO_CAPABLE(sc)) { 4357beedf5beSSepherosa Ziehau error = bnx_alloc_jumbo_mem(sc); 4358beedf5beSSepherosa Ziehau if (error) { 4359beedf5beSSepherosa Ziehau device_printf(dev, 4360beedf5beSSepherosa Ziehau "could not create jumbo buffer pool\n"); 436133a04907SSepherosa Ziehau return error; 436233a04907SSepherosa Ziehau } 436333a04907SSepherosa Ziehau } 436433a04907SSepherosa Ziehau 43656c8d8eccSSepherosa Ziehau return 0; 43666c8d8eccSSepherosa Ziehau } 43676c8d8eccSSepherosa Ziehau 43686c8d8eccSSepherosa Ziehau static int 43696c8d8eccSSepherosa Ziehau bnx_dma_block_alloc(struct bnx_softc *sc, bus_size_t size, bus_dma_tag_t *tag, 43706c8d8eccSSepherosa Ziehau bus_dmamap_t *map, void **addr, bus_addr_t *paddr) 43716c8d8eccSSepherosa Ziehau { 43726c8d8eccSSepherosa Ziehau bus_dmamem_t dmem; 43736c8d8eccSSepherosa Ziehau int error; 43746c8d8eccSSepherosa Ziehau 43756c8d8eccSSepherosa Ziehau error = bus_dmamem_coherent(sc->bnx_cdata.bnx_parent_tag, PAGE_SIZE, 0, 43766c8d8eccSSepherosa Ziehau BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, 43776c8d8eccSSepherosa Ziehau size, BUS_DMA_WAITOK | BUS_DMA_ZERO, &dmem); 43786c8d8eccSSepherosa Ziehau if (error) 43796c8d8eccSSepherosa Ziehau return error; 43806c8d8eccSSepherosa Ziehau 43816c8d8eccSSepherosa Ziehau *tag = dmem.dmem_tag; 43826c8d8eccSSepherosa Ziehau *map = dmem.dmem_map; 43836c8d8eccSSepherosa Ziehau *addr = dmem.dmem_addr; 43846c8d8eccSSepherosa Ziehau *paddr = dmem.dmem_busaddr; 43856c8d8eccSSepherosa Ziehau 43866c8d8eccSSepherosa Ziehau return 0; 43876c8d8eccSSepherosa Ziehau } 43886c8d8eccSSepherosa Ziehau 43896c8d8eccSSepherosa Ziehau static void 43906c8d8eccSSepherosa Ziehau bnx_dma_block_free(bus_dma_tag_t tag, bus_dmamap_t map, void *addr) 43916c8d8eccSSepherosa Ziehau { 43926c8d8eccSSepherosa Ziehau if (tag != NULL) { 43936c8d8eccSSepherosa Ziehau bus_dmamap_unload(tag, map); 43946c8d8eccSSepherosa Ziehau bus_dmamem_free(tag, addr, map); 43956c8d8eccSSepherosa Ziehau bus_dma_tag_destroy(tag); 43966c8d8eccSSepherosa Ziehau } 43976c8d8eccSSepherosa Ziehau } 43986c8d8eccSSepherosa Ziehau 43996c8d8eccSSepherosa Ziehau static void 44006c8d8eccSSepherosa Ziehau bnx_tbi_link_upd(struct bnx_softc *sc, uint32_t status) 44016c8d8eccSSepherosa Ziehau { 44026c8d8eccSSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if; 44036c8d8eccSSepherosa Ziehau 44046c8d8eccSSepherosa Ziehau #define PCS_ENCODE_ERR (BGE_MACSTAT_PORT_DECODE_ERROR|BGE_MACSTAT_MI_COMPLETE) 44056c8d8eccSSepherosa Ziehau 44066c8d8eccSSepherosa Ziehau /* 44076c8d8eccSSepherosa Ziehau * Sometimes PCS encoding errors are detected in 44086c8d8eccSSepherosa Ziehau * TBI mode (on fiber NICs), and for some reason 44096c8d8eccSSepherosa Ziehau * the chip will signal them as link changes. 44106c8d8eccSSepherosa Ziehau * If we get a link change event, but the 'PCS 44116c8d8eccSSepherosa Ziehau * encoding error' bit in the MAC status register 44126c8d8eccSSepherosa Ziehau * is set, don't bother doing a link check. 44136c8d8eccSSepherosa Ziehau * This avoids spurious "gigabit link up" messages 44146c8d8eccSSepherosa Ziehau * that sometimes appear on fiber NICs during 44156c8d8eccSSepherosa Ziehau * periods of heavy traffic. 44166c8d8eccSSepherosa Ziehau */ 44176c8d8eccSSepherosa Ziehau if (status & BGE_MACSTAT_TBI_PCS_SYNCHED) { 44186c8d8eccSSepherosa Ziehau if (!sc->bnx_link) { 44196c8d8eccSSepherosa Ziehau sc->bnx_link++; 44206c8d8eccSSepherosa Ziehau if (sc->bnx_asicrev == BGE_ASICREV_BCM5704) { 44216c8d8eccSSepherosa Ziehau BNX_CLRBIT(sc, BGE_MAC_MODE, 44226c8d8eccSSepherosa Ziehau BGE_MACMODE_TBI_SEND_CFGS); 44234aa71e73SSepherosa Ziehau DELAY(40); 44246c8d8eccSSepherosa Ziehau } 44256c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_MAC_STS, 0xFFFFFFFF); 44266c8d8eccSSepherosa Ziehau 44276c8d8eccSSepherosa Ziehau if (bootverbose) 44286c8d8eccSSepherosa Ziehau if_printf(ifp, "link UP\n"); 44296c8d8eccSSepherosa Ziehau 44306c8d8eccSSepherosa Ziehau ifp->if_link_state = LINK_STATE_UP; 44316c8d8eccSSepherosa Ziehau if_link_state_change(ifp); 44326c8d8eccSSepherosa Ziehau } 44336c8d8eccSSepherosa Ziehau } else if ((status & PCS_ENCODE_ERR) != PCS_ENCODE_ERR) { 44346c8d8eccSSepherosa Ziehau if (sc->bnx_link) { 44356c8d8eccSSepherosa Ziehau sc->bnx_link = 0; 44366c8d8eccSSepherosa Ziehau 44376c8d8eccSSepherosa Ziehau if (bootverbose) 44386c8d8eccSSepherosa Ziehau if_printf(ifp, "link DOWN\n"); 44396c8d8eccSSepherosa Ziehau 44406c8d8eccSSepherosa Ziehau ifp->if_link_state = LINK_STATE_DOWN; 44416c8d8eccSSepherosa Ziehau if_link_state_change(ifp); 44426c8d8eccSSepherosa Ziehau } 44436c8d8eccSSepherosa Ziehau } 44446c8d8eccSSepherosa Ziehau 44456c8d8eccSSepherosa Ziehau #undef PCS_ENCODE_ERR 44466c8d8eccSSepherosa Ziehau 44476c8d8eccSSepherosa Ziehau /* Clear the attention. */ 44486c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_MAC_STS, BGE_MACSTAT_SYNC_CHANGED | 44496c8d8eccSSepherosa Ziehau BGE_MACSTAT_CFG_CHANGED | BGE_MACSTAT_MI_COMPLETE | 44506c8d8eccSSepherosa Ziehau BGE_MACSTAT_LINK_CHANGED); 44516c8d8eccSSepherosa Ziehau } 44526c8d8eccSSepherosa Ziehau 44536c8d8eccSSepherosa Ziehau static void 44546c8d8eccSSepherosa Ziehau bnx_copper_link_upd(struct bnx_softc *sc, uint32_t status __unused) 44556c8d8eccSSepherosa Ziehau { 44566c8d8eccSSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if; 44576c8d8eccSSepherosa Ziehau struct mii_data *mii = device_get_softc(sc->bnx_miibus); 44586c8d8eccSSepherosa Ziehau 44596c8d8eccSSepherosa Ziehau mii_pollstat(mii); 44606c8d8eccSSepherosa Ziehau bnx_miibus_statchg(sc->bnx_dev); 44616c8d8eccSSepherosa Ziehau 44626c8d8eccSSepherosa Ziehau if (bootverbose) { 44636c8d8eccSSepherosa Ziehau if (sc->bnx_link) 44646c8d8eccSSepherosa Ziehau if_printf(ifp, "link UP\n"); 44656c8d8eccSSepherosa Ziehau else 44666c8d8eccSSepherosa Ziehau if_printf(ifp, "link DOWN\n"); 44676c8d8eccSSepherosa Ziehau } 44686c8d8eccSSepherosa Ziehau 44696c8d8eccSSepherosa Ziehau /* Clear the attention. */ 44706c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_MAC_STS, BGE_MACSTAT_SYNC_CHANGED | 44716c8d8eccSSepherosa Ziehau BGE_MACSTAT_CFG_CHANGED | BGE_MACSTAT_MI_COMPLETE | 44726c8d8eccSSepherosa Ziehau BGE_MACSTAT_LINK_CHANGED); 44736c8d8eccSSepherosa Ziehau } 44746c8d8eccSSepherosa Ziehau 44756c8d8eccSSepherosa Ziehau static void 44766c8d8eccSSepherosa Ziehau bnx_autopoll_link_upd(struct bnx_softc *sc, uint32_t status __unused) 44776c8d8eccSSepherosa Ziehau { 44786c8d8eccSSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if; 44796c8d8eccSSepherosa Ziehau struct mii_data *mii = device_get_softc(sc->bnx_miibus); 44806c8d8eccSSepherosa Ziehau 44816c8d8eccSSepherosa Ziehau mii_pollstat(mii); 44826c8d8eccSSepherosa Ziehau 44836c8d8eccSSepherosa Ziehau if (!sc->bnx_link && 44846c8d8eccSSepherosa Ziehau (mii->mii_media_status & IFM_ACTIVE) && 44856c8d8eccSSepherosa Ziehau IFM_SUBTYPE(mii->mii_media_active) != IFM_NONE) { 44866c8d8eccSSepherosa Ziehau sc->bnx_link++; 44876c8d8eccSSepherosa Ziehau if (bootverbose) 44886c8d8eccSSepherosa Ziehau if_printf(ifp, "link UP\n"); 44896c8d8eccSSepherosa Ziehau } else if (sc->bnx_link && 44906c8d8eccSSepherosa Ziehau (!(mii->mii_media_status & IFM_ACTIVE) || 44916c8d8eccSSepherosa Ziehau IFM_SUBTYPE(mii->mii_media_active) == IFM_NONE)) { 44926c8d8eccSSepherosa Ziehau sc->bnx_link = 0; 44936c8d8eccSSepherosa Ziehau if (bootverbose) 44946c8d8eccSSepherosa Ziehau if_printf(ifp, "link DOWN\n"); 44956c8d8eccSSepherosa Ziehau } 44966c8d8eccSSepherosa Ziehau 44976c8d8eccSSepherosa Ziehau /* Clear the attention. */ 44986c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_MAC_STS, BGE_MACSTAT_SYNC_CHANGED | 44996c8d8eccSSepherosa Ziehau BGE_MACSTAT_CFG_CHANGED | BGE_MACSTAT_MI_COMPLETE | 45006c8d8eccSSepherosa Ziehau BGE_MACSTAT_LINK_CHANGED); 45016c8d8eccSSepherosa Ziehau } 45026c8d8eccSSepherosa Ziehau 45036c8d8eccSSepherosa Ziehau static int 45046c8d8eccSSepherosa Ziehau bnx_sysctl_rx_coal_ticks(SYSCTL_HANDLER_ARGS) 45056c8d8eccSSepherosa Ziehau { 45066c8d8eccSSepherosa Ziehau struct bnx_softc *sc = arg1; 45076c8d8eccSSepherosa Ziehau 45086c8d8eccSSepherosa Ziehau return bnx_sysctl_coal_chg(oidp, arg1, arg2, req, 45096c8d8eccSSepherosa Ziehau &sc->bnx_rx_coal_ticks, 45106c8d8eccSSepherosa Ziehau BNX_RX_COAL_TICKS_MIN, BNX_RX_COAL_TICKS_MAX, 45116c8d8eccSSepherosa Ziehau BNX_RX_COAL_TICKS_CHG); 45126c8d8eccSSepherosa Ziehau } 45136c8d8eccSSepherosa Ziehau 45146c8d8eccSSepherosa Ziehau static int 45156c8d8eccSSepherosa Ziehau bnx_sysctl_tx_coal_ticks(SYSCTL_HANDLER_ARGS) 45166c8d8eccSSepherosa Ziehau { 45176c8d8eccSSepherosa Ziehau struct bnx_softc *sc = arg1; 45186c8d8eccSSepherosa Ziehau 45196c8d8eccSSepherosa Ziehau return bnx_sysctl_coal_chg(oidp, arg1, arg2, req, 45206c8d8eccSSepherosa Ziehau &sc->bnx_tx_coal_ticks, 45216c8d8eccSSepherosa Ziehau BNX_TX_COAL_TICKS_MIN, BNX_TX_COAL_TICKS_MAX, 45226c8d8eccSSepherosa Ziehau BNX_TX_COAL_TICKS_CHG); 45236c8d8eccSSepherosa Ziehau } 45246c8d8eccSSepherosa Ziehau 45256c8d8eccSSepherosa Ziehau static int 45266c8d8eccSSepherosa Ziehau bnx_sysctl_rx_coal_bds(SYSCTL_HANDLER_ARGS) 45276c8d8eccSSepherosa Ziehau { 45286c8d8eccSSepherosa Ziehau struct bnx_softc *sc = arg1; 45296c8d8eccSSepherosa Ziehau 45306c8d8eccSSepherosa Ziehau return bnx_sysctl_coal_chg(oidp, arg1, arg2, req, 45316c8d8eccSSepherosa Ziehau &sc->bnx_rx_coal_bds, 45326c8d8eccSSepherosa Ziehau BNX_RX_COAL_BDS_MIN, BNX_RX_COAL_BDS_MAX, 45336c8d8eccSSepherosa Ziehau BNX_RX_COAL_BDS_CHG); 45346c8d8eccSSepherosa Ziehau } 45356c8d8eccSSepherosa Ziehau 45366c8d8eccSSepherosa Ziehau static int 4537a86cc105SSepherosa Ziehau bnx_sysctl_rx_coal_bds_poll(SYSCTL_HANDLER_ARGS) 4538a86cc105SSepherosa Ziehau { 4539a86cc105SSepherosa Ziehau struct bnx_softc *sc = arg1; 4540a86cc105SSepherosa Ziehau 4541a86cc105SSepherosa Ziehau return bnx_sysctl_coal_chg(oidp, arg1, arg2, req, 4542a86cc105SSepherosa Ziehau &sc->bnx_rx_coal_bds_poll, 4543a86cc105SSepherosa Ziehau BNX_RX_COAL_BDS_MIN, BNX_RX_COAL_BDS_MAX, 4544a86cc105SSepherosa Ziehau BNX_RX_COAL_BDS_CHG); 4545a86cc105SSepherosa Ziehau } 4546a86cc105SSepherosa Ziehau 4547a86cc105SSepherosa Ziehau static int 45486c8d8eccSSepherosa Ziehau bnx_sysctl_tx_coal_bds(SYSCTL_HANDLER_ARGS) 45496c8d8eccSSepherosa Ziehau { 45506c8d8eccSSepherosa Ziehau struct bnx_softc *sc = arg1; 45516c8d8eccSSepherosa Ziehau 45526c8d8eccSSepherosa Ziehau return bnx_sysctl_coal_chg(oidp, arg1, arg2, req, 45536c8d8eccSSepherosa Ziehau &sc->bnx_tx_coal_bds, 45546c8d8eccSSepherosa Ziehau BNX_TX_COAL_BDS_MIN, BNX_TX_COAL_BDS_MAX, 45556c8d8eccSSepherosa Ziehau BNX_TX_COAL_BDS_CHG); 45566c8d8eccSSepherosa Ziehau } 45576c8d8eccSSepherosa Ziehau 45586c8d8eccSSepherosa Ziehau static int 455927357d84SSepherosa Ziehau bnx_sysctl_tx_coal_bds_poll(SYSCTL_HANDLER_ARGS) 456027357d84SSepherosa Ziehau { 456127357d84SSepherosa Ziehau struct bnx_softc *sc = arg1; 456227357d84SSepherosa Ziehau 456327357d84SSepherosa Ziehau return bnx_sysctl_coal_chg(oidp, arg1, arg2, req, 456427357d84SSepherosa Ziehau &sc->bnx_tx_coal_bds_poll, 456527357d84SSepherosa Ziehau BNX_TX_COAL_BDS_MIN, BNX_TX_COAL_BDS_MAX, 456627357d84SSepherosa Ziehau BNX_TX_COAL_BDS_CHG); 456727357d84SSepherosa Ziehau } 456827357d84SSepherosa Ziehau 456927357d84SSepherosa Ziehau static int 45706c8d8eccSSepherosa Ziehau bnx_sysctl_rx_coal_bds_int(SYSCTL_HANDLER_ARGS) 45716c8d8eccSSepherosa Ziehau { 45726c8d8eccSSepherosa Ziehau struct bnx_softc *sc = arg1; 45736c8d8eccSSepherosa Ziehau 45746c8d8eccSSepherosa Ziehau return bnx_sysctl_coal_chg(oidp, arg1, arg2, req, 45756c8d8eccSSepherosa Ziehau &sc->bnx_rx_coal_bds_int, 45766c8d8eccSSepherosa Ziehau BNX_RX_COAL_BDS_MIN, BNX_RX_COAL_BDS_MAX, 45776c8d8eccSSepherosa Ziehau BNX_RX_COAL_BDS_INT_CHG); 45786c8d8eccSSepherosa Ziehau } 45796c8d8eccSSepherosa Ziehau 45806c8d8eccSSepherosa Ziehau static int 45816c8d8eccSSepherosa Ziehau bnx_sysctl_tx_coal_bds_int(SYSCTL_HANDLER_ARGS) 45826c8d8eccSSepherosa Ziehau { 45836c8d8eccSSepherosa Ziehau struct bnx_softc *sc = arg1; 45846c8d8eccSSepherosa Ziehau 45856c8d8eccSSepherosa Ziehau return bnx_sysctl_coal_chg(oidp, arg1, arg2, req, 45866c8d8eccSSepherosa Ziehau &sc->bnx_tx_coal_bds_int, 45876c8d8eccSSepherosa Ziehau BNX_TX_COAL_BDS_MIN, BNX_TX_COAL_BDS_MAX, 45886c8d8eccSSepherosa Ziehau BNX_TX_COAL_BDS_INT_CHG); 45896c8d8eccSSepherosa Ziehau } 45906c8d8eccSSepherosa Ziehau 45916c8d8eccSSepherosa Ziehau static int 45926c8d8eccSSepherosa Ziehau bnx_sysctl_coal_chg(SYSCTL_HANDLER_ARGS, uint32_t *coal, 45936c8d8eccSSepherosa Ziehau int coal_min, int coal_max, uint32_t coal_chg_mask) 45946c8d8eccSSepherosa Ziehau { 45956c8d8eccSSepherosa Ziehau struct bnx_softc *sc = arg1; 45966c8d8eccSSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if; 45976c8d8eccSSepherosa Ziehau int error = 0, v; 45986c8d8eccSSepherosa Ziehau 4599329f9016SSepherosa Ziehau ifnet_serialize_all(ifp); 46006c8d8eccSSepherosa Ziehau 46016c8d8eccSSepherosa Ziehau v = *coal; 46026c8d8eccSSepherosa Ziehau error = sysctl_handle_int(oidp, &v, 0, req); 46036c8d8eccSSepherosa Ziehau if (!error && req->newptr != NULL) { 46046c8d8eccSSepherosa Ziehau if (v < coal_min || v > coal_max) { 46056c8d8eccSSepherosa Ziehau error = EINVAL; 46066c8d8eccSSepherosa Ziehau } else { 46076c8d8eccSSepherosa Ziehau *coal = v; 46086c8d8eccSSepherosa Ziehau sc->bnx_coal_chg |= coal_chg_mask; 4609f5014362SSepherosa Ziehau 4610f5014362SSepherosa Ziehau /* Commit changes */ 4611f5014362SSepherosa Ziehau bnx_coal_change(sc); 46126c8d8eccSSepherosa Ziehau } 46136c8d8eccSSepherosa Ziehau } 46146c8d8eccSSepherosa Ziehau 4615329f9016SSepherosa Ziehau ifnet_deserialize_all(ifp); 46166c8d8eccSSepherosa Ziehau return error; 46176c8d8eccSSepherosa Ziehau } 46186c8d8eccSSepherosa Ziehau 46196c8d8eccSSepherosa Ziehau static void 46206c8d8eccSSepherosa Ziehau bnx_coal_change(struct bnx_softc *sc) 46216c8d8eccSSepherosa Ziehau { 46226c8d8eccSSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if; 4623695a8586SSepherosa Ziehau int i; 46246c8d8eccSSepherosa Ziehau 4625329f9016SSepherosa Ziehau ASSERT_IFNET_SERIALIZED_ALL(ifp); 46266c8d8eccSSepherosa Ziehau 46276c8d8eccSSepherosa Ziehau if (sc->bnx_coal_chg & BNX_RX_COAL_TICKS_CHG) { 4628695a8586SSepherosa Ziehau if (sc->bnx_rx_retcnt == 1) { 46296c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_HCC_RX_COAL_TICKS, 46306c8d8eccSSepherosa Ziehau sc->bnx_rx_coal_ticks); 4631695a8586SSepherosa Ziehau i = 0; 4632695a8586SSepherosa Ziehau } else { 4633695a8586SSepherosa Ziehau CSR_WRITE_4(sc, BGE_HCC_RX_COAL_TICKS, 0); 4634695a8586SSepherosa Ziehau for (i = 0; i < sc->bnx_rx_retcnt; ++i) { 4635695a8586SSepherosa Ziehau CSR_WRITE_4(sc, BGE_VEC1_RX_COAL_TICKS + 4636695a8586SSepherosa Ziehau (i * BGE_VEC_COALSET_SIZE), 4637695a8586SSepherosa Ziehau sc->bnx_rx_coal_ticks); 4638695a8586SSepherosa Ziehau } 4639695a8586SSepherosa Ziehau } 4640695a8586SSepherosa Ziehau for (; i < BNX_INTR_MAX - 1; ++i) { 4641695a8586SSepherosa Ziehau CSR_WRITE_4(sc, BGE_VEC1_RX_COAL_TICKS + 4642695a8586SSepherosa Ziehau (i * BGE_VEC_COALSET_SIZE), 0); 4643695a8586SSepherosa Ziehau } 46446c8d8eccSSepherosa Ziehau if (bootverbose) { 46456c8d8eccSSepherosa Ziehau if_printf(ifp, "rx_coal_ticks -> %u\n", 46466c8d8eccSSepherosa Ziehau sc->bnx_rx_coal_ticks); 46476c8d8eccSSepherosa Ziehau } 46486c8d8eccSSepherosa Ziehau } 46496c8d8eccSSepherosa Ziehau 46506c8d8eccSSepherosa Ziehau if (sc->bnx_coal_chg & BNX_TX_COAL_TICKS_CHG) { 4651695a8586SSepherosa Ziehau if (sc->bnx_tx_ringcnt == 1) { 46526c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_HCC_TX_COAL_TICKS, 46536c8d8eccSSepherosa Ziehau sc->bnx_tx_coal_ticks); 4654695a8586SSepherosa Ziehau i = 0; 4655695a8586SSepherosa Ziehau } else { 4656695a8586SSepherosa Ziehau CSR_WRITE_4(sc, BGE_HCC_TX_COAL_TICKS, 0); 4657695a8586SSepherosa Ziehau for (i = 0; i < sc->bnx_tx_ringcnt; ++i) { 4658695a8586SSepherosa Ziehau CSR_WRITE_4(sc, BGE_VEC1_TX_COAL_TICKS + 4659695a8586SSepherosa Ziehau (i * BGE_VEC_COALSET_SIZE), 4660695a8586SSepherosa Ziehau sc->bnx_tx_coal_ticks); 4661695a8586SSepherosa Ziehau } 4662695a8586SSepherosa Ziehau } 4663695a8586SSepherosa Ziehau for (; i < BNX_INTR_MAX - 1; ++i) { 4664695a8586SSepherosa Ziehau CSR_WRITE_4(sc, BGE_VEC1_TX_COAL_TICKS + 4665695a8586SSepherosa Ziehau (i * BGE_VEC_COALSET_SIZE), 0); 4666695a8586SSepherosa Ziehau } 46676c8d8eccSSepherosa Ziehau if (bootverbose) { 46686c8d8eccSSepherosa Ziehau if_printf(ifp, "tx_coal_ticks -> %u\n", 46696c8d8eccSSepherosa Ziehau sc->bnx_tx_coal_ticks); 46706c8d8eccSSepherosa Ziehau } 46716c8d8eccSSepherosa Ziehau } 46726c8d8eccSSepherosa Ziehau 46736c8d8eccSSepherosa Ziehau if (sc->bnx_coal_chg & BNX_RX_COAL_BDS_CHG) { 4674a86cc105SSepherosa Ziehau uint32_t rx_coal_bds; 4675a86cc105SSepherosa Ziehau 4676a86cc105SSepherosa Ziehau if (ifp->if_flags & IFF_NPOLLING) 4677a86cc105SSepherosa Ziehau rx_coal_bds = sc->bnx_rx_coal_bds_poll; 4678a86cc105SSepherosa Ziehau else 4679a86cc105SSepherosa Ziehau rx_coal_bds = sc->bnx_rx_coal_bds; 4680a86cc105SSepherosa Ziehau 4681695a8586SSepherosa Ziehau if (sc->bnx_rx_retcnt == 1) { 4682a86cc105SSepherosa Ziehau CSR_WRITE_4(sc, BGE_HCC_RX_MAX_COAL_BDS, rx_coal_bds); 4683695a8586SSepherosa Ziehau i = 0; 4684695a8586SSepherosa Ziehau } else { 4685695a8586SSepherosa Ziehau CSR_WRITE_4(sc, BGE_HCC_RX_MAX_COAL_BDS, 0); 4686695a8586SSepherosa Ziehau for (i = 0; i < sc->bnx_rx_retcnt; ++i) { 4687695a8586SSepherosa Ziehau CSR_WRITE_4(sc, BGE_VEC1_RX_MAX_COAL_BDS + 4688a86cc105SSepherosa Ziehau (i * BGE_VEC_COALSET_SIZE), rx_coal_bds); 4689695a8586SSepherosa Ziehau } 4690695a8586SSepherosa Ziehau } 4691695a8586SSepherosa Ziehau for (; i < BNX_INTR_MAX - 1; ++i) { 4692695a8586SSepherosa Ziehau CSR_WRITE_4(sc, BGE_VEC1_RX_MAX_COAL_BDS + 4693695a8586SSepherosa Ziehau (i * BGE_VEC_COALSET_SIZE), 0); 4694695a8586SSepherosa Ziehau } 46956c8d8eccSSepherosa Ziehau if (bootverbose) { 4696a86cc105SSepherosa Ziehau if_printf(ifp, "%srx_coal_bds -> %u\n", 4697a86cc105SSepherosa Ziehau (ifp->if_flags & IFF_NPOLLING) ? "polling " : "", 4698a86cc105SSepherosa Ziehau rx_coal_bds); 46996c8d8eccSSepherosa Ziehau } 47006c8d8eccSSepherosa Ziehau } 47016c8d8eccSSepherosa Ziehau 47026c8d8eccSSepherosa Ziehau if (sc->bnx_coal_chg & BNX_TX_COAL_BDS_CHG) { 470327357d84SSepherosa Ziehau uint32_t tx_coal_bds; 470427357d84SSepherosa Ziehau 470527357d84SSepherosa Ziehau if (ifp->if_flags & IFF_NPOLLING) 470627357d84SSepherosa Ziehau tx_coal_bds = sc->bnx_tx_coal_bds_poll; 470727357d84SSepherosa Ziehau else 470827357d84SSepherosa Ziehau tx_coal_bds = sc->bnx_tx_coal_bds; 470927357d84SSepherosa Ziehau 4710695a8586SSepherosa Ziehau if (sc->bnx_tx_ringcnt == 1) { 471127357d84SSepherosa Ziehau CSR_WRITE_4(sc, BGE_HCC_TX_MAX_COAL_BDS, tx_coal_bds); 4712695a8586SSepherosa Ziehau i = 0; 4713695a8586SSepherosa Ziehau } else { 4714695a8586SSepherosa Ziehau CSR_WRITE_4(sc, BGE_HCC_TX_MAX_COAL_BDS, 0); 4715695a8586SSepherosa Ziehau for (i = 0; i < sc->bnx_tx_ringcnt; ++i) { 4716695a8586SSepherosa Ziehau CSR_WRITE_4(sc, BGE_VEC1_TX_MAX_COAL_BDS + 471727357d84SSepherosa Ziehau (i * BGE_VEC_COALSET_SIZE), tx_coal_bds); 4718695a8586SSepherosa Ziehau } 4719695a8586SSepherosa Ziehau } 4720695a8586SSepherosa Ziehau for (; i < BNX_INTR_MAX - 1; ++i) { 4721695a8586SSepherosa Ziehau CSR_WRITE_4(sc, BGE_VEC1_TX_MAX_COAL_BDS + 4722695a8586SSepherosa Ziehau (i * BGE_VEC_COALSET_SIZE), 0); 4723695a8586SSepherosa Ziehau } 47246c8d8eccSSepherosa Ziehau if (bootverbose) { 472527357d84SSepherosa Ziehau if_printf(ifp, "%stx_coal_bds -> %u\n", 472627357d84SSepherosa Ziehau (ifp->if_flags & IFF_NPOLLING) ? "polling " : "", 472727357d84SSepherosa Ziehau tx_coal_bds); 47286c8d8eccSSepherosa Ziehau } 47296c8d8eccSSepherosa Ziehau } 47306c8d8eccSSepherosa Ziehau 47316c8d8eccSSepherosa Ziehau if (sc->bnx_coal_chg & BNX_RX_COAL_BDS_INT_CHG) { 4732695a8586SSepherosa Ziehau if (sc->bnx_rx_retcnt == 1) { 47336c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_HCC_RX_MAX_COAL_BDS_INT, 47346c8d8eccSSepherosa Ziehau sc->bnx_rx_coal_bds_int); 4735695a8586SSepherosa Ziehau i = 0; 4736695a8586SSepherosa Ziehau } else { 4737695a8586SSepherosa Ziehau CSR_WRITE_4(sc, BGE_HCC_RX_MAX_COAL_BDS_INT, 0); 4738695a8586SSepherosa Ziehau for (i = 0; i < sc->bnx_rx_retcnt; ++i) { 4739695a8586SSepherosa Ziehau CSR_WRITE_4(sc, BGE_VEC1_RX_MAX_COAL_BDS_INT + 4740695a8586SSepherosa Ziehau (i * BGE_VEC_COALSET_SIZE), 4741695a8586SSepherosa Ziehau sc->bnx_rx_coal_bds_int); 4742695a8586SSepherosa Ziehau } 4743695a8586SSepherosa Ziehau } 4744695a8586SSepherosa Ziehau for (; i < BNX_INTR_MAX - 1; ++i) { 4745695a8586SSepherosa Ziehau CSR_WRITE_4(sc, BGE_VEC1_RX_MAX_COAL_BDS_INT + 4746695a8586SSepherosa Ziehau (i * BGE_VEC_COALSET_SIZE), 0); 4747695a8586SSepherosa Ziehau } 47486c8d8eccSSepherosa Ziehau if (bootverbose) { 47496c8d8eccSSepherosa Ziehau if_printf(ifp, "rx_coal_bds_int -> %u\n", 47506c8d8eccSSepherosa Ziehau sc->bnx_rx_coal_bds_int); 47516c8d8eccSSepherosa Ziehau } 47526c8d8eccSSepherosa Ziehau } 47536c8d8eccSSepherosa Ziehau 47546c8d8eccSSepherosa Ziehau if (sc->bnx_coal_chg & BNX_TX_COAL_BDS_INT_CHG) { 4755695a8586SSepherosa Ziehau if (sc->bnx_tx_ringcnt == 1) { 47566c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_HCC_TX_MAX_COAL_BDS_INT, 47576c8d8eccSSepherosa Ziehau sc->bnx_tx_coal_bds_int); 4758695a8586SSepherosa Ziehau i = 0; 4759695a8586SSepherosa Ziehau } else { 4760695a8586SSepherosa Ziehau CSR_WRITE_4(sc, BGE_HCC_TX_MAX_COAL_BDS_INT, 0); 4761695a8586SSepherosa Ziehau for (i = 0; i < sc->bnx_tx_ringcnt; ++i) { 4762695a8586SSepherosa Ziehau CSR_WRITE_4(sc, BGE_VEC1_TX_MAX_COAL_BDS_INT + 4763695a8586SSepherosa Ziehau (i * BGE_VEC_COALSET_SIZE), 4764695a8586SSepherosa Ziehau sc->bnx_tx_coal_bds_int); 4765695a8586SSepherosa Ziehau } 4766695a8586SSepherosa Ziehau } 4767695a8586SSepherosa Ziehau for (; i < BNX_INTR_MAX - 1; ++i) { 4768695a8586SSepherosa Ziehau CSR_WRITE_4(sc, BGE_VEC1_TX_MAX_COAL_BDS_INT + 4769695a8586SSepherosa Ziehau (i * BGE_VEC_COALSET_SIZE), 0); 4770695a8586SSepherosa Ziehau } 47716c8d8eccSSepherosa Ziehau if (bootverbose) { 47726c8d8eccSSepherosa Ziehau if_printf(ifp, "tx_coal_bds_int -> %u\n", 47736c8d8eccSSepherosa Ziehau sc->bnx_tx_coal_bds_int); 47746c8d8eccSSepherosa Ziehau } 47756c8d8eccSSepherosa Ziehau } 47766c8d8eccSSepherosa Ziehau 47776c8d8eccSSepherosa Ziehau sc->bnx_coal_chg = 0; 47786c8d8eccSSepherosa Ziehau } 47796c8d8eccSSepherosa Ziehau 47806c8d8eccSSepherosa Ziehau static void 4781695a8586SSepherosa Ziehau bnx_check_intr_rxtx(void *xintr) 4782df9ccc98SSepherosa Ziehau { 4783f33ac8a4SSepherosa Ziehau struct bnx_intr_data *intr = xintr; 4784f33ac8a4SSepherosa Ziehau struct bnx_rx_ret_ring *ret; 4785f33ac8a4SSepherosa Ziehau struct bnx_tx_ring *txr; 4786f33ac8a4SSepherosa Ziehau struct ifnet *ifp; 4787df9ccc98SSepherosa Ziehau 4788f33ac8a4SSepherosa Ziehau lwkt_serialize_enter(intr->bnx_intr_serialize); 4789df9ccc98SSepherosa Ziehau 4790f33ac8a4SSepherosa Ziehau KKASSERT(mycpuid == intr->bnx_intr_cpuid); 4791df9ccc98SSepherosa Ziehau 4792f33ac8a4SSepherosa Ziehau ifp = &intr->bnx_sc->arpcom.ac_if; 479339a8d43aSSepherosa Ziehau if ((ifp->if_flags & (IFF_RUNNING | IFF_NPOLLING)) != IFF_RUNNING) { 4794f33ac8a4SSepherosa Ziehau lwkt_serialize_exit(intr->bnx_intr_serialize); 4795df9ccc98SSepherosa Ziehau return; 4796df9ccc98SSepherosa Ziehau } 4797df9ccc98SSepherosa Ziehau 4798f33ac8a4SSepherosa Ziehau txr = intr->bnx_txr; 4799f33ac8a4SSepherosa Ziehau ret = intr->bnx_ret; 4800f33ac8a4SSepherosa Ziehau 48013a16b7b8SSepherosa Ziehau if (*ret->bnx_rx_considx != ret->bnx_rx_saved_considx || 48023a16b7b8SSepherosa Ziehau *txr->bnx_tx_considx != txr->bnx_tx_saved_considx) { 4803f33ac8a4SSepherosa Ziehau if (intr->bnx_rx_check_considx == ret->bnx_rx_saved_considx && 4804f33ac8a4SSepherosa Ziehau intr->bnx_tx_check_considx == txr->bnx_tx_saved_considx) { 4805f33ac8a4SSepherosa Ziehau if (!intr->bnx_intr_maylose) { 4806f33ac8a4SSepherosa Ziehau intr->bnx_intr_maylose = TRUE; 4807df9ccc98SSepherosa Ziehau goto done; 4808df9ccc98SSepherosa Ziehau } 4809df9ccc98SSepherosa Ziehau if (bootverbose) 4810df9ccc98SSepherosa Ziehau if_printf(ifp, "lost interrupt\n"); 4811f33ac8a4SSepherosa Ziehau intr->bnx_intr_func(intr->bnx_intr_arg); 4812df9ccc98SSepherosa Ziehau } 4813df9ccc98SSepherosa Ziehau } 4814f33ac8a4SSepherosa Ziehau intr->bnx_intr_maylose = FALSE; 4815f33ac8a4SSepherosa Ziehau intr->bnx_rx_check_considx = ret->bnx_rx_saved_considx; 4816f33ac8a4SSepherosa Ziehau intr->bnx_tx_check_considx = txr->bnx_tx_saved_considx; 4817df9ccc98SSepherosa Ziehau 4818df9ccc98SSepherosa Ziehau done: 4819f33ac8a4SSepherosa Ziehau callout_reset(&intr->bnx_intr_timer, BNX_INTR_CKINTVL, 4820f33ac8a4SSepherosa Ziehau intr->bnx_intr_check, intr); 4821f33ac8a4SSepherosa Ziehau lwkt_serialize_exit(intr->bnx_intr_serialize); 4822df9ccc98SSepherosa Ziehau } 4823df9ccc98SSepherosa Ziehau 4824df9ccc98SSepherosa Ziehau static void 4825695a8586SSepherosa Ziehau bnx_check_intr_tx(void *xintr) 4826695a8586SSepherosa Ziehau { 4827695a8586SSepherosa Ziehau struct bnx_intr_data *intr = xintr; 4828695a8586SSepherosa Ziehau struct bnx_tx_ring *txr; 4829695a8586SSepherosa Ziehau struct ifnet *ifp; 4830695a8586SSepherosa Ziehau 4831695a8586SSepherosa Ziehau lwkt_serialize_enter(intr->bnx_intr_serialize); 4832695a8586SSepherosa Ziehau 4833695a8586SSepherosa Ziehau KKASSERT(mycpuid == intr->bnx_intr_cpuid); 4834695a8586SSepherosa Ziehau 4835695a8586SSepherosa Ziehau ifp = &intr->bnx_sc->arpcom.ac_if; 4836695a8586SSepherosa Ziehau if ((ifp->if_flags & (IFF_RUNNING | IFF_NPOLLING)) != IFF_RUNNING) { 4837695a8586SSepherosa Ziehau lwkt_serialize_exit(intr->bnx_intr_serialize); 4838695a8586SSepherosa Ziehau return; 4839695a8586SSepherosa Ziehau } 4840695a8586SSepherosa Ziehau 4841695a8586SSepherosa Ziehau txr = intr->bnx_txr; 4842695a8586SSepherosa Ziehau 4843695a8586SSepherosa Ziehau if (*txr->bnx_tx_considx != txr->bnx_tx_saved_considx) { 4844695a8586SSepherosa Ziehau if (intr->bnx_tx_check_considx == txr->bnx_tx_saved_considx) { 4845695a8586SSepherosa Ziehau if (!intr->bnx_intr_maylose) { 4846695a8586SSepherosa Ziehau intr->bnx_intr_maylose = TRUE; 4847695a8586SSepherosa Ziehau goto done; 4848695a8586SSepherosa Ziehau } 4849695a8586SSepherosa Ziehau if (bootverbose) 4850695a8586SSepherosa Ziehau if_printf(ifp, "lost interrupt\n"); 4851695a8586SSepherosa Ziehau intr->bnx_intr_func(intr->bnx_intr_arg); 4852695a8586SSepherosa Ziehau } 4853695a8586SSepherosa Ziehau } 4854695a8586SSepherosa Ziehau intr->bnx_intr_maylose = FALSE; 4855695a8586SSepherosa Ziehau intr->bnx_tx_check_considx = txr->bnx_tx_saved_considx; 4856695a8586SSepherosa Ziehau 4857695a8586SSepherosa Ziehau done: 4858695a8586SSepherosa Ziehau callout_reset(&intr->bnx_intr_timer, BNX_INTR_CKINTVL, 4859695a8586SSepherosa Ziehau intr->bnx_intr_check, intr); 4860695a8586SSepherosa Ziehau lwkt_serialize_exit(intr->bnx_intr_serialize); 4861695a8586SSepherosa Ziehau } 4862695a8586SSepherosa Ziehau 4863695a8586SSepherosa Ziehau static void 4864695a8586SSepherosa Ziehau bnx_check_intr_rx(void *xintr) 4865695a8586SSepherosa Ziehau { 4866695a8586SSepherosa Ziehau struct bnx_intr_data *intr = xintr; 4867695a8586SSepherosa Ziehau struct bnx_rx_ret_ring *ret; 4868695a8586SSepherosa Ziehau struct ifnet *ifp; 4869695a8586SSepherosa Ziehau 4870695a8586SSepherosa Ziehau lwkt_serialize_enter(intr->bnx_intr_serialize); 4871695a8586SSepherosa Ziehau 4872695a8586SSepherosa Ziehau KKASSERT(mycpuid == intr->bnx_intr_cpuid); 4873695a8586SSepherosa Ziehau 4874695a8586SSepherosa Ziehau ifp = &intr->bnx_sc->arpcom.ac_if; 4875695a8586SSepherosa Ziehau if ((ifp->if_flags & (IFF_RUNNING | IFF_NPOLLING)) != IFF_RUNNING) { 4876695a8586SSepherosa Ziehau lwkt_serialize_exit(intr->bnx_intr_serialize); 4877695a8586SSepherosa Ziehau return; 4878695a8586SSepherosa Ziehau } 4879695a8586SSepherosa Ziehau 4880695a8586SSepherosa Ziehau ret = intr->bnx_ret; 4881695a8586SSepherosa Ziehau 4882695a8586SSepherosa Ziehau if (*ret->bnx_rx_considx != ret->bnx_rx_saved_considx) { 4883695a8586SSepherosa Ziehau if (intr->bnx_rx_check_considx == ret->bnx_rx_saved_considx) { 4884695a8586SSepherosa Ziehau if (!intr->bnx_intr_maylose) { 4885695a8586SSepherosa Ziehau intr->bnx_intr_maylose = TRUE; 4886695a8586SSepherosa Ziehau goto done; 4887695a8586SSepherosa Ziehau } 4888695a8586SSepherosa Ziehau if (bootverbose) 4889695a8586SSepherosa Ziehau if_printf(ifp, "lost interrupt\n"); 4890695a8586SSepherosa Ziehau intr->bnx_intr_func(intr->bnx_intr_arg); 4891695a8586SSepherosa Ziehau } 4892695a8586SSepherosa Ziehau } 4893695a8586SSepherosa Ziehau intr->bnx_intr_maylose = FALSE; 4894695a8586SSepherosa Ziehau intr->bnx_rx_check_considx = ret->bnx_rx_saved_considx; 4895695a8586SSepherosa Ziehau 4896695a8586SSepherosa Ziehau done: 4897695a8586SSepherosa Ziehau callout_reset(&intr->bnx_intr_timer, BNX_INTR_CKINTVL, 4898695a8586SSepherosa Ziehau intr->bnx_intr_check, intr); 4899695a8586SSepherosa Ziehau lwkt_serialize_exit(intr->bnx_intr_serialize); 4900695a8586SSepherosa Ziehau } 4901695a8586SSepherosa Ziehau 4902695a8586SSepherosa Ziehau static void 49036c8d8eccSSepherosa Ziehau bnx_enable_intr(struct bnx_softc *sc) 49046c8d8eccSSepherosa Ziehau { 49056c8d8eccSSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if; 4906f33ac8a4SSepherosa Ziehau int i; 49076c8d8eccSSepherosa Ziehau 4908f33ac8a4SSepherosa Ziehau for (i = 0; i < sc->bnx_intr_cnt; ++i) { 4909f33ac8a4SSepherosa Ziehau lwkt_serialize_handler_enable( 4910f33ac8a4SSepherosa Ziehau sc->bnx_intr_data[i].bnx_intr_serialize); 4911f33ac8a4SSepherosa Ziehau } 49126c8d8eccSSepherosa Ziehau 49136c8d8eccSSepherosa Ziehau /* 49146c8d8eccSSepherosa Ziehau * Enable interrupt. 49156c8d8eccSSepherosa Ziehau */ 491697ba8fc5SSepherosa Ziehau for (i = 0; i < sc->bnx_intr_cnt; ++i) { 491797ba8fc5SSepherosa Ziehau struct bnx_intr_data *intr = &sc->bnx_intr_data[i]; 491897ba8fc5SSepherosa Ziehau 491997ba8fc5SSepherosa Ziehau bnx_writembx(sc, intr->bnx_intr_mbx, 492097ba8fc5SSepherosa Ziehau (*intr->bnx_saved_status_tag) << 24); 49216c8d8eccSSepherosa Ziehau /* XXX Linux driver */ 492297ba8fc5SSepherosa Ziehau bnx_writembx(sc, intr->bnx_intr_mbx, 492397ba8fc5SSepherosa Ziehau (*intr->bnx_saved_status_tag) << 24); 492497ba8fc5SSepherosa Ziehau } 49256c8d8eccSSepherosa Ziehau 49266c8d8eccSSepherosa Ziehau /* 49276c8d8eccSSepherosa Ziehau * Unmask the interrupt when we stop polling. 49286c8d8eccSSepherosa Ziehau */ 49296c8d8eccSSepherosa Ziehau PCI_CLRBIT(sc->bnx_dev, BGE_PCI_MISC_CTL, 49306c8d8eccSSepherosa Ziehau BGE_PCIMISCCTL_MASK_PCI_INTR, 4); 49316c8d8eccSSepherosa Ziehau 49326c8d8eccSSepherosa Ziehau /* 49336c8d8eccSSepherosa Ziehau * Trigger another interrupt, since above writing 49346c8d8eccSSepherosa Ziehau * to interrupt mailbox0 may acknowledge pending 49356c8d8eccSSepherosa Ziehau * interrupt. 49366c8d8eccSSepherosa Ziehau */ 49376c8d8eccSSepherosa Ziehau BNX_SETBIT(sc, BGE_MISC_LOCAL_CTL, BGE_MLC_INTR_SET); 4938df9ccc98SSepherosa Ziehau 4939df9ccc98SSepherosa Ziehau if (sc->bnx_flags & BNX_FLAG_STATUSTAG_BUG) { 4940df9ccc98SSepherosa Ziehau if (bootverbose) 4941df9ccc98SSepherosa Ziehau if_printf(ifp, "status tag bug workaround\n"); 4942df9ccc98SSepherosa Ziehau 4943f33ac8a4SSepherosa Ziehau for (i = 0; i < sc->bnx_intr_cnt; ++i) { 494497ba8fc5SSepherosa Ziehau struct bnx_intr_data *intr = &sc->bnx_intr_data[i]; 494597ba8fc5SSepherosa Ziehau 4946695a8586SSepherosa Ziehau if (intr->bnx_intr_check == NULL) 4947695a8586SSepherosa Ziehau continue; 4948f33ac8a4SSepherosa Ziehau intr->bnx_intr_maylose = FALSE; 4949f33ac8a4SSepherosa Ziehau intr->bnx_rx_check_considx = 0; 4950f33ac8a4SSepherosa Ziehau intr->bnx_tx_check_considx = 0; 4951f33ac8a4SSepherosa Ziehau callout_reset_bycpu(&intr->bnx_intr_timer, 4952f33ac8a4SSepherosa Ziehau BNX_INTR_CKINTVL, intr->bnx_intr_check, intr, 4953f33ac8a4SSepherosa Ziehau intr->bnx_intr_cpuid); 4954f33ac8a4SSepherosa Ziehau } 4955df9ccc98SSepherosa Ziehau } 49566c8d8eccSSepherosa Ziehau } 49576c8d8eccSSepherosa Ziehau 49586c8d8eccSSepherosa Ziehau static void 49596c8d8eccSSepherosa Ziehau bnx_disable_intr(struct bnx_softc *sc) 49606c8d8eccSSepherosa Ziehau { 4961f33ac8a4SSepherosa Ziehau int i; 4962f33ac8a4SSepherosa Ziehau 4963f33ac8a4SSepherosa Ziehau for (i = 0; i < sc->bnx_intr_cnt; ++i) { 4964f33ac8a4SSepherosa Ziehau struct bnx_intr_data *intr = &sc->bnx_intr_data[i]; 4965f33ac8a4SSepherosa Ziehau 4966f33ac8a4SSepherosa Ziehau callout_stop(&intr->bnx_intr_timer); 4967f33ac8a4SSepherosa Ziehau intr->bnx_intr_maylose = FALSE; 4968f33ac8a4SSepherosa Ziehau intr->bnx_rx_check_considx = 0; 4969f33ac8a4SSepherosa Ziehau intr->bnx_tx_check_considx = 0; 4970f33ac8a4SSepherosa Ziehau } 49716c8d8eccSSepherosa Ziehau 49726c8d8eccSSepherosa Ziehau /* 49736c8d8eccSSepherosa Ziehau * Mask the interrupt when we start polling. 49746c8d8eccSSepherosa Ziehau */ 49756c8d8eccSSepherosa Ziehau PCI_SETBIT(sc->bnx_dev, BGE_PCI_MISC_CTL, 49766c8d8eccSSepherosa Ziehau BGE_PCIMISCCTL_MASK_PCI_INTR, 4); 49776c8d8eccSSepherosa Ziehau 49786c8d8eccSSepherosa Ziehau /* 49796c8d8eccSSepherosa Ziehau * Acknowledge possible asserted interrupt. 49806c8d8eccSSepherosa Ziehau */ 4981695a8586SSepherosa Ziehau for (i = 0; i < BNX_INTR_MAX; ++i) 498297ba8fc5SSepherosa Ziehau bnx_writembx(sc, sc->bnx_intr_data[i].bnx_intr_mbx, 1); 49836c8d8eccSSepherosa Ziehau 4984f33ac8a4SSepherosa Ziehau for (i = 0; i < sc->bnx_intr_cnt; ++i) { 4985f33ac8a4SSepherosa Ziehau lwkt_serialize_handler_disable( 4986f33ac8a4SSepherosa Ziehau sc->bnx_intr_data[i].bnx_intr_serialize); 4987f33ac8a4SSepherosa Ziehau } 49886c8d8eccSSepherosa Ziehau } 49896c8d8eccSSepherosa Ziehau 49906c8d8eccSSepherosa Ziehau static int 49916c8d8eccSSepherosa Ziehau bnx_get_eaddr_mem(struct bnx_softc *sc, uint8_t ether_addr[]) 49926c8d8eccSSepherosa Ziehau { 49936c8d8eccSSepherosa Ziehau uint32_t mac_addr; 49946c8d8eccSSepherosa Ziehau int ret = 1; 49956c8d8eccSSepherosa Ziehau 49966c8d8eccSSepherosa Ziehau mac_addr = bnx_readmem_ind(sc, 0x0c14); 49976c8d8eccSSepherosa Ziehau if ((mac_addr >> 16) == 0x484b) { 49986c8d8eccSSepherosa Ziehau ether_addr[0] = (uint8_t)(mac_addr >> 8); 49996c8d8eccSSepherosa Ziehau ether_addr[1] = (uint8_t)mac_addr; 50006c8d8eccSSepherosa Ziehau mac_addr = bnx_readmem_ind(sc, 0x0c18); 50016c8d8eccSSepherosa Ziehau ether_addr[2] = (uint8_t)(mac_addr >> 24); 50026c8d8eccSSepherosa Ziehau ether_addr[3] = (uint8_t)(mac_addr >> 16); 50036c8d8eccSSepherosa Ziehau ether_addr[4] = (uint8_t)(mac_addr >> 8); 50046c8d8eccSSepherosa Ziehau ether_addr[5] = (uint8_t)mac_addr; 50056c8d8eccSSepherosa Ziehau ret = 0; 50066c8d8eccSSepherosa Ziehau } 50076c8d8eccSSepherosa Ziehau return ret; 50086c8d8eccSSepherosa Ziehau } 50096c8d8eccSSepherosa Ziehau 50106c8d8eccSSepherosa Ziehau static int 50116c8d8eccSSepherosa Ziehau bnx_get_eaddr_nvram(struct bnx_softc *sc, uint8_t ether_addr[]) 50126c8d8eccSSepherosa Ziehau { 50136c8d8eccSSepherosa Ziehau int mac_offset = BGE_EE_MAC_OFFSET; 50146c8d8eccSSepherosa Ziehau 501580969639SSepherosa Ziehau if (BNX_IS_5717_PLUS(sc)) { 501680969639SSepherosa Ziehau int f; 501780969639SSepherosa Ziehau 501880969639SSepherosa Ziehau f = pci_get_function(sc->bnx_dev); 501980969639SSepherosa Ziehau if (f & 1) 502080969639SSepherosa Ziehau mac_offset = BGE_EE_MAC_OFFSET_5717; 502180969639SSepherosa Ziehau if (f > 1) 502280969639SSepherosa Ziehau mac_offset += BGE_EE_MAC_OFFSET_5717_OFF; 502380969639SSepherosa Ziehau } 50246c8d8eccSSepherosa Ziehau 50256c8d8eccSSepherosa Ziehau return bnx_read_nvram(sc, ether_addr, mac_offset + 2, ETHER_ADDR_LEN); 50266c8d8eccSSepherosa Ziehau } 50276c8d8eccSSepherosa Ziehau 50286c8d8eccSSepherosa Ziehau static int 50296c8d8eccSSepherosa Ziehau bnx_get_eaddr_eeprom(struct bnx_softc *sc, uint8_t ether_addr[]) 50306c8d8eccSSepherosa Ziehau { 50316c8d8eccSSepherosa Ziehau if (sc->bnx_flags & BNX_FLAG_NO_EEPROM) 50326c8d8eccSSepherosa Ziehau return 1; 50336c8d8eccSSepherosa Ziehau 50346c8d8eccSSepherosa Ziehau return bnx_read_eeprom(sc, ether_addr, BGE_EE_MAC_OFFSET + 2, 50356c8d8eccSSepherosa Ziehau ETHER_ADDR_LEN); 50366c8d8eccSSepherosa Ziehau } 50376c8d8eccSSepherosa Ziehau 50386c8d8eccSSepherosa Ziehau static int 50396c8d8eccSSepherosa Ziehau bnx_get_eaddr(struct bnx_softc *sc, uint8_t eaddr[]) 50406c8d8eccSSepherosa Ziehau { 50416c8d8eccSSepherosa Ziehau static const bnx_eaddr_fcn_t bnx_eaddr_funcs[] = { 50426c8d8eccSSepherosa Ziehau /* NOTE: Order is critical */ 50436c8d8eccSSepherosa Ziehau bnx_get_eaddr_mem, 50446c8d8eccSSepherosa Ziehau bnx_get_eaddr_nvram, 50456c8d8eccSSepherosa Ziehau bnx_get_eaddr_eeprom, 50466c8d8eccSSepherosa Ziehau NULL 50476c8d8eccSSepherosa Ziehau }; 50486c8d8eccSSepherosa Ziehau const bnx_eaddr_fcn_t *func; 50496c8d8eccSSepherosa Ziehau 50506c8d8eccSSepherosa Ziehau for (func = bnx_eaddr_funcs; *func != NULL; ++func) { 50516c8d8eccSSepherosa Ziehau if ((*func)(sc, eaddr) == 0) 50526c8d8eccSSepherosa Ziehau break; 50536c8d8eccSSepherosa Ziehau } 50546c8d8eccSSepherosa Ziehau return (*func == NULL ? ENXIO : 0); 50556c8d8eccSSepherosa Ziehau } 50566c8d8eccSSepherosa Ziehau 50576c8d8eccSSepherosa Ziehau /* 50586c8d8eccSSepherosa Ziehau * NOTE: 'm' is not freed upon failure 50596c8d8eccSSepherosa Ziehau */ 50606c8d8eccSSepherosa Ziehau struct mbuf * 50616c8d8eccSSepherosa Ziehau bnx_defrag_shortdma(struct mbuf *m) 50626c8d8eccSSepherosa Ziehau { 50636c8d8eccSSepherosa Ziehau struct mbuf *n; 50646c8d8eccSSepherosa Ziehau int found; 50656c8d8eccSSepherosa Ziehau 50666c8d8eccSSepherosa Ziehau /* 50676c8d8eccSSepherosa Ziehau * If device receive two back-to-back send BDs with less than 50686c8d8eccSSepherosa Ziehau * or equal to 8 total bytes then the device may hang. The two 50696c8d8eccSSepherosa Ziehau * back-to-back send BDs must in the same frame for this failure 50706c8d8eccSSepherosa Ziehau * to occur. Scan mbuf chains and see whether two back-to-back 50716c8d8eccSSepherosa Ziehau * send BDs are there. If this is the case, allocate new mbuf 50726c8d8eccSSepherosa Ziehau * and copy the frame to workaround the silicon bug. 50736c8d8eccSSepherosa Ziehau */ 50746c8d8eccSSepherosa Ziehau for (n = m, found = 0; n != NULL; n = n->m_next) { 50756c8d8eccSSepherosa Ziehau if (n->m_len < 8) { 50766c8d8eccSSepherosa Ziehau found++; 50776c8d8eccSSepherosa Ziehau if (found > 1) 50786c8d8eccSSepherosa Ziehau break; 50796c8d8eccSSepherosa Ziehau continue; 50806c8d8eccSSepherosa Ziehau } 50816c8d8eccSSepherosa Ziehau found = 0; 50826c8d8eccSSepherosa Ziehau } 50836c8d8eccSSepherosa Ziehau 50846c8d8eccSSepherosa Ziehau if (found > 1) 50856c8d8eccSSepherosa Ziehau n = m_defrag(m, MB_DONTWAIT); 50866c8d8eccSSepherosa Ziehau else 50876c8d8eccSSepherosa Ziehau n = m; 50886c8d8eccSSepherosa Ziehau return n; 50896c8d8eccSSepherosa Ziehau } 50906c8d8eccSSepherosa Ziehau 50916c8d8eccSSepherosa Ziehau static void 50926c8d8eccSSepherosa Ziehau bnx_stop_block(struct bnx_softc *sc, bus_size_t reg, uint32_t bit) 50936c8d8eccSSepherosa Ziehau { 50946c8d8eccSSepherosa Ziehau int i; 50956c8d8eccSSepherosa Ziehau 50966c8d8eccSSepherosa Ziehau BNX_CLRBIT(sc, reg, bit); 50976c8d8eccSSepherosa Ziehau for (i = 0; i < BNX_TIMEOUT; i++) { 50986c8d8eccSSepherosa Ziehau if ((CSR_READ_4(sc, reg) & bit) == 0) 50996c8d8eccSSepherosa Ziehau return; 51006c8d8eccSSepherosa Ziehau DELAY(100); 51016c8d8eccSSepherosa Ziehau } 51026c8d8eccSSepherosa Ziehau } 51036c8d8eccSSepherosa Ziehau 51046c8d8eccSSepherosa Ziehau static void 51056c8d8eccSSepherosa Ziehau bnx_link_poll(struct bnx_softc *sc) 51066c8d8eccSSepherosa Ziehau { 51076c8d8eccSSepherosa Ziehau uint32_t status; 51086c8d8eccSSepherosa Ziehau 51096c8d8eccSSepherosa Ziehau status = CSR_READ_4(sc, BGE_MAC_STS); 51106c8d8eccSSepherosa Ziehau if ((status & sc->bnx_link_chg) || sc->bnx_link_evt) { 51116c8d8eccSSepherosa Ziehau sc->bnx_link_evt = 0; 51126c8d8eccSSepherosa Ziehau sc->bnx_link_upd(sc, status); 51136c8d8eccSSepherosa Ziehau } 51146c8d8eccSSepherosa Ziehau } 51156c8d8eccSSepherosa Ziehau 51166c8d8eccSSepherosa Ziehau static void 5117695a8586SSepherosa Ziehau bnx_enable_msi(struct bnx_softc *sc, boolean_t is_msix) 51186c8d8eccSSepherosa Ziehau { 51196c8d8eccSSepherosa Ziehau uint32_t msi_mode; 51206c8d8eccSSepherosa Ziehau 51216c8d8eccSSepherosa Ziehau msi_mode = CSR_READ_4(sc, BGE_MSI_MODE); 51226c8d8eccSSepherosa Ziehau msi_mode |= BGE_MSIMODE_ENABLE; 51236c8d8eccSSepherosa Ziehau /* 51246c8d8eccSSepherosa Ziehau * NOTE: 51250b4feeacSSepherosa Ziehau * 5718-PG105-R says that "one shot" mode does not work 51260b4feeacSSepherosa Ziehau * if MSI is used, however, it obviously works. 51276c8d8eccSSepherosa Ziehau */ 51286c8d8eccSSepherosa Ziehau msi_mode &= ~BGE_MSIMODE_ONESHOT_DISABLE; 5129695a8586SSepherosa Ziehau if (is_msix) 5130695a8586SSepherosa Ziehau msi_mode |= BGE_MSIMODE_MSIX_MULTIMODE; 5131695a8586SSepherosa Ziehau else 5132695a8586SSepherosa Ziehau msi_mode &= ~BGE_MSIMODE_MSIX_MULTIMODE; 51336c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_MSI_MODE, msi_mode); 51346c8d8eccSSepherosa Ziehau } 51356c8d8eccSSepherosa Ziehau 51366c8d8eccSSepherosa Ziehau static uint32_t 51376c8d8eccSSepherosa Ziehau bnx_dma_swap_options(struct bnx_softc *sc) 51386c8d8eccSSepherosa Ziehau { 51396c8d8eccSSepherosa Ziehau uint32_t dma_options; 51406c8d8eccSSepherosa Ziehau 51416c8d8eccSSepherosa Ziehau dma_options = BGE_MODECTL_WORDSWAP_NONFRAME | 51426c8d8eccSSepherosa Ziehau BGE_MODECTL_BYTESWAP_DATA | BGE_MODECTL_WORDSWAP_DATA; 51436c8d8eccSSepherosa Ziehau #if BYTE_ORDER == BIG_ENDIAN 51446c8d8eccSSepherosa Ziehau dma_options |= BGE_MODECTL_BYTESWAP_NONFRAME; 51456c8d8eccSSepherosa Ziehau #endif 51466c8d8eccSSepherosa Ziehau return dma_options; 51476c8d8eccSSepherosa Ziehau } 514866deb1c1SSepherosa Ziehau 514966deb1c1SSepherosa Ziehau static int 515033a04907SSepherosa Ziehau bnx_setup_tso(struct bnx_tx_ring *txr, struct mbuf **mp, 515166deb1c1SSepherosa Ziehau uint16_t *mss0, uint16_t *flags0) 515266deb1c1SSepherosa Ziehau { 515366deb1c1SSepherosa Ziehau struct mbuf *m; 515466deb1c1SSepherosa Ziehau struct ip *ip; 515566deb1c1SSepherosa Ziehau struct tcphdr *th; 515666deb1c1SSepherosa Ziehau int thoff, iphlen, hoff, hlen; 515766deb1c1SSepherosa Ziehau uint16_t flags, mss; 515866deb1c1SSepherosa Ziehau 5159f7a2269aSSepherosa Ziehau m = *mp; 5160f7a2269aSSepherosa Ziehau KASSERT(M_WRITABLE(m), ("TSO mbuf not writable")); 5161f7a2269aSSepherosa Ziehau 5162f7a2269aSSepherosa Ziehau hoff = m->m_pkthdr.csum_lhlen; 5163f7a2269aSSepherosa Ziehau iphlen = m->m_pkthdr.csum_iphlen; 5164f7a2269aSSepherosa Ziehau thoff = m->m_pkthdr.csum_thlen; 5165f7a2269aSSepherosa Ziehau 5166f7a2269aSSepherosa Ziehau KASSERT(hoff > 0, ("invalid ether header len")); 5167f7a2269aSSepherosa Ziehau KASSERT(iphlen > 0, ("invalid ip header len")); 5168f7a2269aSSepherosa Ziehau KASSERT(thoff > 0, ("invalid tcp header len")); 5169f7a2269aSSepherosa Ziehau 5170f7a2269aSSepherosa Ziehau if (__predict_false(m->m_len < hoff + iphlen + thoff)) { 5171f7a2269aSSepherosa Ziehau m = m_pullup(m, hoff + iphlen + thoff); 5172f7a2269aSSepherosa Ziehau if (m == NULL) { 5173f7a2269aSSepherosa Ziehau *mp = NULL; 5174f7a2269aSSepherosa Ziehau return ENOBUFS; 5175f7a2269aSSepherosa Ziehau } 5176f7a2269aSSepherosa Ziehau *mp = m; 5177f7a2269aSSepherosa Ziehau } 5178f7a2269aSSepherosa Ziehau ip = mtodoff(m, struct ip *, hoff); 5179f7a2269aSSepherosa Ziehau th = mtodoff(m, struct tcphdr *, hoff + iphlen); 5180f7a2269aSSepherosa Ziehau 5181f0336d39SSepherosa Ziehau mss = m->m_pkthdr.tso_segsz; 518266deb1c1SSepherosa Ziehau flags = BGE_TXBDFLAG_CPU_PRE_DMA | BGE_TXBDFLAG_CPU_POST_DMA; 518366deb1c1SSepherosa Ziehau 518466deb1c1SSepherosa Ziehau ip->ip_len = htons(mss + iphlen + thoff); 518566deb1c1SSepherosa Ziehau th->th_sum = 0; 518666deb1c1SSepherosa Ziehau 518766deb1c1SSepherosa Ziehau hlen = (iphlen + thoff) >> 2; 518866deb1c1SSepherosa Ziehau mss |= ((hlen & 0x3) << 14); 518966deb1c1SSepherosa Ziehau flags |= ((hlen & 0xf8) << 7) | ((hlen & 0x4) << 2); 519066deb1c1SSepherosa Ziehau 519166deb1c1SSepherosa Ziehau *mss0 = mss; 519266deb1c1SSepherosa Ziehau *flags0 = flags; 519366deb1c1SSepherosa Ziehau 519466deb1c1SSepherosa Ziehau return 0; 519566deb1c1SSepherosa Ziehau } 519633a04907SSepherosa Ziehau 519733a04907SSepherosa Ziehau static int 519833a04907SSepherosa Ziehau bnx_create_tx_ring(struct bnx_tx_ring *txr) 519933a04907SSepherosa Ziehau { 520033a04907SSepherosa Ziehau bus_size_t txmaxsz, txmaxsegsz; 520133a04907SSepherosa Ziehau int i, error; 520233a04907SSepherosa Ziehau 5203329f9016SSepherosa Ziehau lwkt_serialize_init(&txr->bnx_tx_serialize); 5204329f9016SSepherosa Ziehau 520533a04907SSepherosa Ziehau /* 520633a04907SSepherosa Ziehau * Create DMA tag and maps for TX mbufs. 520733a04907SSepherosa Ziehau */ 520833a04907SSepherosa Ziehau if (txr->bnx_sc->bnx_flags & BNX_FLAG_TSO) 520933a04907SSepherosa Ziehau txmaxsz = IP_MAXPACKET + sizeof(struct ether_vlan_header); 521033a04907SSepherosa Ziehau else 521133a04907SSepherosa Ziehau txmaxsz = BNX_JUMBO_FRAMELEN; 521233a04907SSepherosa Ziehau if (txr->bnx_sc->bnx_asicrev == BGE_ASICREV_BCM57766) 521333a04907SSepherosa Ziehau txmaxsegsz = MCLBYTES; 521433a04907SSepherosa Ziehau else 521533a04907SSepherosa Ziehau txmaxsegsz = PAGE_SIZE; 521633a04907SSepherosa Ziehau error = bus_dma_tag_create(txr->bnx_sc->bnx_cdata.bnx_parent_tag, 521733a04907SSepherosa Ziehau 1, 0, BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL, NULL, 521833a04907SSepherosa Ziehau txmaxsz, BNX_NSEG_NEW, txmaxsegsz, 521933a04907SSepherosa Ziehau BUS_DMA_ALLOCNOW | BUS_DMA_WAITOK | BUS_DMA_ONEBPAGE, 522033a04907SSepherosa Ziehau &txr->bnx_tx_mtag); 522133a04907SSepherosa Ziehau if (error) { 522233a04907SSepherosa Ziehau device_printf(txr->bnx_sc->bnx_dev, 5223beedf5beSSepherosa Ziehau "could not create TX mbuf DMA tag\n"); 522433a04907SSepherosa Ziehau return error; 522533a04907SSepherosa Ziehau } 522633a04907SSepherosa Ziehau 522733a04907SSepherosa Ziehau for (i = 0; i < BGE_TX_RING_CNT; i++) { 522833a04907SSepherosa Ziehau error = bus_dmamap_create(txr->bnx_tx_mtag, 522933a04907SSepherosa Ziehau BUS_DMA_WAITOK | BUS_DMA_ONEBPAGE, 5230fa4b1067SSepherosa Ziehau &txr->bnx_tx_buf[i].bnx_tx_dmamap); 523133a04907SSepherosa Ziehau if (error) { 523233a04907SSepherosa Ziehau int j; 523333a04907SSepherosa Ziehau 523433a04907SSepherosa Ziehau for (j = 0; j < i; ++j) { 523533a04907SSepherosa Ziehau bus_dmamap_destroy(txr->bnx_tx_mtag, 5236fa4b1067SSepherosa Ziehau txr->bnx_tx_buf[j].bnx_tx_dmamap); 523733a04907SSepherosa Ziehau } 523833a04907SSepherosa Ziehau bus_dma_tag_destroy(txr->bnx_tx_mtag); 523933a04907SSepherosa Ziehau txr->bnx_tx_mtag = NULL; 524033a04907SSepherosa Ziehau 524133a04907SSepherosa Ziehau device_printf(txr->bnx_sc->bnx_dev, 5242beedf5beSSepherosa Ziehau "could not create TX mbuf DMA map\n"); 524333a04907SSepherosa Ziehau return error; 524433a04907SSepherosa Ziehau } 524533a04907SSepherosa Ziehau } 524633a04907SSepherosa Ziehau 524733a04907SSepherosa Ziehau /* 524833a04907SSepherosa Ziehau * Create DMA stuffs for TX ring. 524933a04907SSepherosa Ziehau */ 525033a04907SSepherosa Ziehau error = bnx_dma_block_alloc(txr->bnx_sc, BGE_TX_RING_SZ, 5251beedf5beSSepherosa Ziehau &txr->bnx_tx_ring_tag, 5252beedf5beSSepherosa Ziehau &txr->bnx_tx_ring_map, 5253beedf5beSSepherosa Ziehau (void *)&txr->bnx_tx_ring, 5254beedf5beSSepherosa Ziehau &txr->bnx_tx_ring_paddr); 525533a04907SSepherosa Ziehau if (error) { 525633a04907SSepherosa Ziehau device_printf(txr->bnx_sc->bnx_dev, 525733a04907SSepherosa Ziehau "could not create TX ring\n"); 525833a04907SSepherosa Ziehau return error; 525933a04907SSepherosa Ziehau } 526033a04907SSepherosa Ziehau 526179a64343SSepherosa Ziehau txr->bnx_tx_flags |= BNX_TX_FLAG_SHORTDMA; 526233a04907SSepherosa Ziehau txr->bnx_tx_wreg = BNX_TX_WREG_NSEGS; 526333a04907SSepherosa Ziehau 526433a04907SSepherosa Ziehau return 0; 526533a04907SSepherosa Ziehau } 526633a04907SSepherosa Ziehau 526733a04907SSepherosa Ziehau static void 526833a04907SSepherosa Ziehau bnx_destroy_tx_ring(struct bnx_tx_ring *txr) 526933a04907SSepherosa Ziehau { 527033a04907SSepherosa Ziehau /* Destroy TX mbuf DMA stuffs. */ 527133a04907SSepherosa Ziehau if (txr->bnx_tx_mtag != NULL) { 527233a04907SSepherosa Ziehau int i; 527333a04907SSepherosa Ziehau 527433a04907SSepherosa Ziehau for (i = 0; i < BGE_TX_RING_CNT; i++) { 5275fa4b1067SSepherosa Ziehau KKASSERT(txr->bnx_tx_buf[i].bnx_tx_mbuf == NULL); 527633a04907SSepherosa Ziehau bus_dmamap_destroy(txr->bnx_tx_mtag, 5277fa4b1067SSepherosa Ziehau txr->bnx_tx_buf[i].bnx_tx_dmamap); 527833a04907SSepherosa Ziehau } 527933a04907SSepherosa Ziehau bus_dma_tag_destroy(txr->bnx_tx_mtag); 528033a04907SSepherosa Ziehau } 528133a04907SSepherosa Ziehau 528233a04907SSepherosa Ziehau /* Destroy TX ring */ 528333a04907SSepherosa Ziehau bnx_dma_block_free(txr->bnx_tx_ring_tag, 528433a04907SSepherosa Ziehau txr->bnx_tx_ring_map, txr->bnx_tx_ring); 528533a04907SSepherosa Ziehau } 5286aad4de2bSSepherosa Ziehau 5287aad4de2bSSepherosa Ziehau static int 5288aad4de2bSSepherosa Ziehau bnx_sysctl_force_defrag(SYSCTL_HANDLER_ARGS) 5289aad4de2bSSepherosa Ziehau { 5290aad4de2bSSepherosa Ziehau struct bnx_softc *sc = (void *)arg1; 5291aad4de2bSSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if; 5292aad4de2bSSepherosa Ziehau struct bnx_tx_ring *txr = &sc->bnx_tx_ring[0]; 5293aad4de2bSSepherosa Ziehau int error, defrag, i; 5294aad4de2bSSepherosa Ziehau 5295aad4de2bSSepherosa Ziehau if (txr->bnx_tx_flags & BNX_TX_FLAG_FORCE_DEFRAG) 5296aad4de2bSSepherosa Ziehau defrag = 1; 5297aad4de2bSSepherosa Ziehau else 5298aad4de2bSSepherosa Ziehau defrag = 0; 5299aad4de2bSSepherosa Ziehau 5300aad4de2bSSepherosa Ziehau error = sysctl_handle_int(oidp, &defrag, 0, req); 5301aad4de2bSSepherosa Ziehau if (error || req->newptr == NULL) 5302aad4de2bSSepherosa Ziehau return error; 5303aad4de2bSSepherosa Ziehau 5304329f9016SSepherosa Ziehau ifnet_serialize_all(ifp); 5305aad4de2bSSepherosa Ziehau for (i = 0; i < sc->bnx_tx_ringcnt; ++i) { 5306aad4de2bSSepherosa Ziehau txr = &sc->bnx_tx_ring[i]; 5307aad4de2bSSepherosa Ziehau if (defrag) 5308aad4de2bSSepherosa Ziehau txr->bnx_tx_flags |= BNX_TX_FLAG_FORCE_DEFRAG; 5309aad4de2bSSepherosa Ziehau else 5310aad4de2bSSepherosa Ziehau txr->bnx_tx_flags &= ~BNX_TX_FLAG_FORCE_DEFRAG; 5311aad4de2bSSepherosa Ziehau } 5312329f9016SSepherosa Ziehau ifnet_deserialize_all(ifp); 5313aad4de2bSSepherosa Ziehau 5314aad4de2bSSepherosa Ziehau return 0; 5315aad4de2bSSepherosa Ziehau } 5316472c99c8SSepherosa Ziehau 5317472c99c8SSepherosa Ziehau static int 5318472c99c8SSepherosa Ziehau bnx_sysctl_tx_wreg(SYSCTL_HANDLER_ARGS) 5319472c99c8SSepherosa Ziehau { 5320472c99c8SSepherosa Ziehau struct bnx_softc *sc = (void *)arg1; 5321472c99c8SSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if; 5322472c99c8SSepherosa Ziehau struct bnx_tx_ring *txr = &sc->bnx_tx_ring[0]; 5323472c99c8SSepherosa Ziehau int error, tx_wreg, i; 5324472c99c8SSepherosa Ziehau 5325472c99c8SSepherosa Ziehau tx_wreg = txr->bnx_tx_wreg; 5326472c99c8SSepherosa Ziehau error = sysctl_handle_int(oidp, &tx_wreg, 0, req); 5327472c99c8SSepherosa Ziehau if (error || req->newptr == NULL) 5328472c99c8SSepherosa Ziehau return error; 5329472c99c8SSepherosa Ziehau 5330329f9016SSepherosa Ziehau ifnet_serialize_all(ifp); 5331472c99c8SSepherosa Ziehau for (i = 0; i < sc->bnx_tx_ringcnt; ++i) 5332472c99c8SSepherosa Ziehau sc->bnx_tx_ring[i].bnx_tx_wreg = tx_wreg; 5333329f9016SSepherosa Ziehau ifnet_deserialize_all(ifp); 5334472c99c8SSepherosa Ziehau 5335472c99c8SSepherosa Ziehau return 0; 5336472c99c8SSepherosa Ziehau } 5337beedf5beSSepherosa Ziehau 5338beedf5beSSepherosa Ziehau static int 5339beedf5beSSepherosa Ziehau bnx_create_rx_ret_ring(struct bnx_rx_ret_ring *ret) 5340beedf5beSSepherosa Ziehau { 5341beedf5beSSepherosa Ziehau int error; 5342beedf5beSSepherosa Ziehau 5343329f9016SSepherosa Ziehau lwkt_serialize_init(&ret->bnx_rx_ret_serialize); 5344329f9016SSepherosa Ziehau 5345beedf5beSSepherosa Ziehau /* 5346beedf5beSSepherosa Ziehau * Create DMA stuffs for RX return ring. 5347beedf5beSSepherosa Ziehau */ 5348beedf5beSSepherosa Ziehau error = bnx_dma_block_alloc(ret->bnx_sc, 5349beedf5beSSepherosa Ziehau BGE_RX_RTN_RING_SZ(BNX_RETURN_RING_CNT), 5350beedf5beSSepherosa Ziehau &ret->bnx_rx_ret_ring_tag, 5351beedf5beSSepherosa Ziehau &ret->bnx_rx_ret_ring_map, 5352beedf5beSSepherosa Ziehau (void *)&ret->bnx_rx_ret_ring, 5353beedf5beSSepherosa Ziehau &ret->bnx_rx_ret_ring_paddr); 5354beedf5beSSepherosa Ziehau if (error) { 5355beedf5beSSepherosa Ziehau device_printf(ret->bnx_sc->bnx_dev, 5356beedf5beSSepherosa Ziehau "could not create RX ret ring\n"); 5357beedf5beSSepherosa Ziehau return error; 5358beedf5beSSepherosa Ziehau } 5359beedf5beSSepherosa Ziehau 5360beedf5beSSepherosa Ziehau /* Shadow standard ring's RX mbuf DMA tag */ 5361beedf5beSSepherosa Ziehau ret->bnx_rx_mtag = ret->bnx_std->bnx_rx_mtag; 5362beedf5beSSepherosa Ziehau 5363beedf5beSSepherosa Ziehau /* 5364beedf5beSSepherosa Ziehau * Create tmp DMA map for RX mbufs. 5365beedf5beSSepherosa Ziehau */ 5366beedf5beSSepherosa Ziehau error = bus_dmamap_create(ret->bnx_rx_mtag, BUS_DMA_WAITOK, 5367beedf5beSSepherosa Ziehau &ret->bnx_rx_tmpmap); 5368beedf5beSSepherosa Ziehau if (error) { 5369beedf5beSSepherosa Ziehau device_printf(ret->bnx_sc->bnx_dev, 5370beedf5beSSepherosa Ziehau "could not create tmp RX mbuf DMA map\n"); 5371beedf5beSSepherosa Ziehau ret->bnx_rx_mtag = NULL; 5372beedf5beSSepherosa Ziehau return error; 5373beedf5beSSepherosa Ziehau } 5374beedf5beSSepherosa Ziehau return 0; 5375beedf5beSSepherosa Ziehau } 5376beedf5beSSepherosa Ziehau 5377beedf5beSSepherosa Ziehau static void 5378beedf5beSSepherosa Ziehau bnx_destroy_rx_ret_ring(struct bnx_rx_ret_ring *ret) 5379beedf5beSSepherosa Ziehau { 5380beedf5beSSepherosa Ziehau /* Destroy tmp RX mbuf DMA map */ 5381beedf5beSSepherosa Ziehau if (ret->bnx_rx_mtag != NULL) 5382beedf5beSSepherosa Ziehau bus_dmamap_destroy(ret->bnx_rx_mtag, ret->bnx_rx_tmpmap); 5383beedf5beSSepherosa Ziehau 5384beedf5beSSepherosa Ziehau /* Destroy RX return ring */ 5385beedf5beSSepherosa Ziehau bnx_dma_block_free(ret->bnx_rx_ret_ring_tag, 5386beedf5beSSepherosa Ziehau ret->bnx_rx_ret_ring_map, ret->bnx_rx_ret_ring); 5387beedf5beSSepherosa Ziehau } 53880c7da01dSSepherosa Ziehau 53890c7da01dSSepherosa Ziehau static int 53900c7da01dSSepherosa Ziehau bnx_alloc_intr(struct bnx_softc *sc) 53910c7da01dSSepherosa Ziehau { 5392f33ac8a4SSepherosa Ziehau struct bnx_intr_data *intr; 53930c7da01dSSepherosa Ziehau u_int intr_flags; 5394695a8586SSepherosa Ziehau int error; 5395695a8586SSepherosa Ziehau 5396695a8586SSepherosa Ziehau if (sc->bnx_intr_cnt > 1) { 5397695a8586SSepherosa Ziehau error = bnx_alloc_msix(sc); 5398695a8586SSepherosa Ziehau if (error) 5399695a8586SSepherosa Ziehau return error; 5400695a8586SSepherosa Ziehau KKASSERT(sc->bnx_intr_type == PCI_INTR_TYPE_MSIX); 5401695a8586SSepherosa Ziehau return 0; 5402695a8586SSepherosa Ziehau } 54030c7da01dSSepherosa Ziehau 54040a806e3aSSepherosa Ziehau KKASSERT(sc->bnx_intr_cnt == 1); 54050c7da01dSSepherosa Ziehau 5406f33ac8a4SSepherosa Ziehau intr = &sc->bnx_intr_data[0]; 5407f33ac8a4SSepherosa Ziehau intr->bnx_ret = &sc->bnx_rx_ret_ring[0]; 5408f33ac8a4SSepherosa Ziehau intr->bnx_txr = &sc->bnx_tx_ring[0]; 5409f33ac8a4SSepherosa Ziehau intr->bnx_intr_serialize = &sc->bnx_main_serialize; 5410695a8586SSepherosa Ziehau intr->bnx_intr_check = bnx_check_intr_rxtx; 54114fa38985SSepherosa Ziehau intr->bnx_saved_status_tag = &intr->bnx_ret->bnx_saved_status_tag; 5412f33ac8a4SSepherosa Ziehau 5413f33ac8a4SSepherosa Ziehau sc->bnx_intr_type = pci_alloc_1intr(sc->bnx_dev, bnx_msi_enable, 5414f33ac8a4SSepherosa Ziehau &intr->bnx_intr_rid, &intr_flags); 5415f33ac8a4SSepherosa Ziehau 5416f33ac8a4SSepherosa Ziehau intr->bnx_intr_res = bus_alloc_resource_any(sc->bnx_dev, SYS_RES_IRQ, 5417f33ac8a4SSepherosa Ziehau &intr->bnx_intr_rid, intr_flags); 5418f33ac8a4SSepherosa Ziehau if (intr->bnx_intr_res == NULL) { 54190c7da01dSSepherosa Ziehau device_printf(sc->bnx_dev, "could not alloc interrupt\n"); 54200c7da01dSSepherosa Ziehau return ENXIO; 54210c7da01dSSepherosa Ziehau } 54220c7da01dSSepherosa Ziehau 5423f33ac8a4SSepherosa Ziehau if (sc->bnx_intr_type == PCI_INTR_TYPE_MSI) { 5424695a8586SSepherosa Ziehau bnx_enable_msi(sc, FALSE); 542503cc99fdSSepherosa Ziehau intr->bnx_intr_func = bnx_msi; 5426f33ac8a4SSepherosa Ziehau if (bootverbose) 5427f33ac8a4SSepherosa Ziehau device_printf(sc->bnx_dev, "oneshot MSI\n"); 5428f33ac8a4SSepherosa Ziehau } else { 5429f33ac8a4SSepherosa Ziehau intr->bnx_intr_func = bnx_intr_legacy; 5430f33ac8a4SSepherosa Ziehau } 5431f33ac8a4SSepherosa Ziehau intr->bnx_intr_arg = sc; 5432f33ac8a4SSepherosa Ziehau intr->bnx_intr_cpuid = rman_get_cpuid(intr->bnx_intr_res); 5433f33ac8a4SSepherosa Ziehau 5434f33ac8a4SSepherosa Ziehau intr->bnx_txr->bnx_tx_cpuid = intr->bnx_intr_cpuid; 5435f33ac8a4SSepherosa Ziehau 54360c7da01dSSepherosa Ziehau return 0; 54370c7da01dSSepherosa Ziehau } 54380c7da01dSSepherosa Ziehau 54390c7da01dSSepherosa Ziehau static int 54400c7da01dSSepherosa Ziehau bnx_setup_intr(struct bnx_softc *sc) 54410c7da01dSSepherosa Ziehau { 5442f33ac8a4SSepherosa Ziehau int error, i; 54430c7da01dSSepherosa Ziehau 5444f33ac8a4SSepherosa Ziehau for (i = 0; i < sc->bnx_intr_cnt; ++i) { 5445f33ac8a4SSepherosa Ziehau struct bnx_intr_data *intr = &sc->bnx_intr_data[i]; 5446f33ac8a4SSepherosa Ziehau 5447f33ac8a4SSepherosa Ziehau error = bus_setup_intr_descr(sc->bnx_dev, intr->bnx_intr_res, 5448f33ac8a4SSepherosa Ziehau INTR_MPSAFE, intr->bnx_intr_func, intr->bnx_intr_arg, 5449f33ac8a4SSepherosa Ziehau &intr->bnx_intr_hand, intr->bnx_intr_serialize, 5450f33ac8a4SSepherosa Ziehau intr->bnx_intr_desc); 54510c7da01dSSepherosa Ziehau if (error) { 5452f33ac8a4SSepherosa Ziehau device_printf(sc->bnx_dev, 5453f33ac8a4SSepherosa Ziehau "could not set up %dth intr\n", i); 5454f33ac8a4SSepherosa Ziehau bnx_teardown_intr(sc, i); 54550c7da01dSSepherosa Ziehau return error; 54560c7da01dSSepherosa Ziehau } 5457f33ac8a4SSepherosa Ziehau } 54580c7da01dSSepherosa Ziehau return 0; 54590c7da01dSSepherosa Ziehau } 54600c7da01dSSepherosa Ziehau 54610c7da01dSSepherosa Ziehau static void 5462f33ac8a4SSepherosa Ziehau bnx_teardown_intr(struct bnx_softc *sc, int cnt) 5463f33ac8a4SSepherosa Ziehau { 5464f33ac8a4SSepherosa Ziehau int i; 5465f33ac8a4SSepherosa Ziehau 5466f33ac8a4SSepherosa Ziehau for (i = 0; i < cnt; ++i) { 5467f33ac8a4SSepherosa Ziehau struct bnx_intr_data *intr = &sc->bnx_intr_data[i]; 5468f33ac8a4SSepherosa Ziehau 5469f33ac8a4SSepherosa Ziehau bus_teardown_intr(sc->bnx_dev, intr->bnx_intr_res, 5470f33ac8a4SSepherosa Ziehau intr->bnx_intr_hand); 5471f33ac8a4SSepherosa Ziehau } 5472f33ac8a4SSepherosa Ziehau } 5473f33ac8a4SSepherosa Ziehau 5474f33ac8a4SSepherosa Ziehau static void 54750c7da01dSSepherosa Ziehau bnx_free_intr(struct bnx_softc *sc) 54760c7da01dSSepherosa Ziehau { 5477695a8586SSepherosa Ziehau if (sc->bnx_intr_type != PCI_INTR_TYPE_MSIX) { 5478f33ac8a4SSepherosa Ziehau struct bnx_intr_data *intr; 5479f33ac8a4SSepherosa Ziehau 5480f33ac8a4SSepherosa Ziehau KKASSERT(sc->bnx_intr_cnt <= 1); 5481f33ac8a4SSepherosa Ziehau intr = &sc->bnx_intr_data[0]; 5482f33ac8a4SSepherosa Ziehau 5483f33ac8a4SSepherosa Ziehau if (intr->bnx_intr_res != NULL) { 54840c7da01dSSepherosa Ziehau bus_release_resource(sc->bnx_dev, SYS_RES_IRQ, 5485f33ac8a4SSepherosa Ziehau intr->bnx_intr_rid, intr->bnx_intr_res); 54860c7da01dSSepherosa Ziehau } 5487f33ac8a4SSepherosa Ziehau if (sc->bnx_intr_type == PCI_INTR_TYPE_MSI) 54880c7da01dSSepherosa Ziehau pci_release_msi(sc->bnx_dev); 5489695a8586SSepherosa Ziehau } else { 5490695a8586SSepherosa Ziehau bnx_free_msix(sc, TRUE); 5491695a8586SSepherosa Ziehau } 54920c7da01dSSepherosa Ziehau } 5493329f9016SSepherosa Ziehau 5494329f9016SSepherosa Ziehau static void 5495329f9016SSepherosa Ziehau bnx_setup_serialize(struct bnx_softc *sc) 5496329f9016SSepherosa Ziehau { 5497329f9016SSepherosa Ziehau int i, j; 5498329f9016SSepherosa Ziehau 5499329f9016SSepherosa Ziehau /* 5500329f9016SSepherosa Ziehau * Allocate serializer array 5501329f9016SSepherosa Ziehau */ 5502329f9016SSepherosa Ziehau 5503329f9016SSepherosa Ziehau /* Main + RX STD + TX + RX RET */ 5504329f9016SSepherosa Ziehau sc->bnx_serialize_cnt = 1 + 1 + sc->bnx_tx_ringcnt + sc->bnx_rx_retcnt; 5505329f9016SSepherosa Ziehau 5506329f9016SSepherosa Ziehau sc->bnx_serialize = 5507329f9016SSepherosa Ziehau kmalloc(sc->bnx_serialize_cnt * sizeof(struct lwkt_serialize *), 5508329f9016SSepherosa Ziehau M_DEVBUF, M_WAITOK | M_ZERO); 5509329f9016SSepherosa Ziehau 5510329f9016SSepherosa Ziehau /* 5511329f9016SSepherosa Ziehau * Setup serializers 5512329f9016SSepherosa Ziehau * 5513329f9016SSepherosa Ziehau * NOTE: Order is critical 5514329f9016SSepherosa Ziehau */ 5515329f9016SSepherosa Ziehau 5516329f9016SSepherosa Ziehau i = 0; 5517329f9016SSepherosa Ziehau 5518329f9016SSepherosa Ziehau KKASSERT(i < sc->bnx_serialize_cnt); 5519329f9016SSepherosa Ziehau sc->bnx_serialize[i++] = &sc->bnx_main_serialize; 5520329f9016SSepherosa Ziehau 5521329f9016SSepherosa Ziehau KKASSERT(i < sc->bnx_serialize_cnt); 5522329f9016SSepherosa Ziehau sc->bnx_serialize[i++] = &sc->bnx_rx_std_ring.bnx_rx_std_serialize; 5523329f9016SSepherosa Ziehau 5524329f9016SSepherosa Ziehau for (j = 0; j < sc->bnx_rx_retcnt; ++j) { 5525329f9016SSepherosa Ziehau KKASSERT(i < sc->bnx_serialize_cnt); 5526329f9016SSepherosa Ziehau sc->bnx_serialize[i++] = 5527329f9016SSepherosa Ziehau &sc->bnx_rx_ret_ring[j].bnx_rx_ret_serialize; 5528329f9016SSepherosa Ziehau } 5529329f9016SSepherosa Ziehau 5530329f9016SSepherosa Ziehau for (j = 0; j < sc->bnx_tx_ringcnt; ++j) { 5531329f9016SSepherosa Ziehau KKASSERT(i < sc->bnx_serialize_cnt); 5532329f9016SSepherosa Ziehau sc->bnx_serialize[i++] = 5533329f9016SSepherosa Ziehau &sc->bnx_tx_ring[j].bnx_tx_serialize; 5534329f9016SSepherosa Ziehau } 5535329f9016SSepherosa Ziehau 5536329f9016SSepherosa Ziehau KKASSERT(i == sc->bnx_serialize_cnt); 5537329f9016SSepherosa Ziehau } 5538329f9016SSepherosa Ziehau 5539329f9016SSepherosa Ziehau static void 5540329f9016SSepherosa Ziehau bnx_serialize(struct ifnet *ifp, enum ifnet_serialize slz) 5541329f9016SSepherosa Ziehau { 5542329f9016SSepherosa Ziehau struct bnx_softc *sc = ifp->if_softc; 5543329f9016SSepherosa Ziehau 5544329f9016SSepherosa Ziehau ifnet_serialize_array_enter(sc->bnx_serialize, 5545329f9016SSepherosa Ziehau sc->bnx_serialize_cnt, slz); 5546329f9016SSepherosa Ziehau } 5547329f9016SSepherosa Ziehau 5548329f9016SSepherosa Ziehau static void 5549329f9016SSepherosa Ziehau bnx_deserialize(struct ifnet *ifp, enum ifnet_serialize slz) 5550329f9016SSepherosa Ziehau { 5551329f9016SSepherosa Ziehau struct bnx_softc *sc = ifp->if_softc; 5552329f9016SSepherosa Ziehau 5553329f9016SSepherosa Ziehau ifnet_serialize_array_exit(sc->bnx_serialize, 5554329f9016SSepherosa Ziehau sc->bnx_serialize_cnt, slz); 5555329f9016SSepherosa Ziehau } 5556329f9016SSepherosa Ziehau 5557329f9016SSepherosa Ziehau static int 5558329f9016SSepherosa Ziehau bnx_tryserialize(struct ifnet *ifp, enum ifnet_serialize slz) 5559329f9016SSepherosa Ziehau { 5560329f9016SSepherosa Ziehau struct bnx_softc *sc = ifp->if_softc; 5561329f9016SSepherosa Ziehau 5562329f9016SSepherosa Ziehau return ifnet_serialize_array_try(sc->bnx_serialize, 5563329f9016SSepherosa Ziehau sc->bnx_serialize_cnt, slz); 5564329f9016SSepherosa Ziehau } 5565329f9016SSepherosa Ziehau 5566329f9016SSepherosa Ziehau #ifdef INVARIANTS 5567329f9016SSepherosa Ziehau 5568329f9016SSepherosa Ziehau static void 5569329f9016SSepherosa Ziehau bnx_serialize_assert(struct ifnet *ifp, enum ifnet_serialize slz, 5570329f9016SSepherosa Ziehau boolean_t serialized) 5571329f9016SSepherosa Ziehau { 5572329f9016SSepherosa Ziehau struct bnx_softc *sc = ifp->if_softc; 5573329f9016SSepherosa Ziehau 5574329f9016SSepherosa Ziehau ifnet_serialize_array_assert(sc->bnx_serialize, sc->bnx_serialize_cnt, 5575329f9016SSepherosa Ziehau slz, serialized); 5576329f9016SSepherosa Ziehau } 5577329f9016SSepherosa Ziehau 5578329f9016SSepherosa Ziehau #endif /* INVARIANTS */ 55794fa38985SSepherosa Ziehau 55804fa38985SSepherosa Ziehau #ifdef IFPOLL_ENABLE 55814fa38985SSepherosa Ziehau 55824fa38985SSepherosa Ziehau static int 55834fa38985SSepherosa Ziehau bnx_sysctl_npoll_offset(SYSCTL_HANDLER_ARGS) 55844fa38985SSepherosa Ziehau { 55854fa38985SSepherosa Ziehau struct bnx_softc *sc = (void *)arg1; 55864fa38985SSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if; 55874fa38985SSepherosa Ziehau int error, off; 55884fa38985SSepherosa Ziehau 55894fa38985SSepherosa Ziehau off = sc->bnx_npoll_rxoff; 55904fa38985SSepherosa Ziehau error = sysctl_handle_int(oidp, &off, 0, req); 55914fa38985SSepherosa Ziehau if (error || req->newptr == NULL) 55924fa38985SSepherosa Ziehau return error; 55934fa38985SSepherosa Ziehau if (off < 0) 55944fa38985SSepherosa Ziehau return EINVAL; 55954fa38985SSepherosa Ziehau 55964fa38985SSepherosa Ziehau ifnet_serialize_all(ifp); 55974fa38985SSepherosa Ziehau if (off >= ncpus2 || off % sc->bnx_rx_retcnt != 0) { 55984fa38985SSepherosa Ziehau error = EINVAL; 55994fa38985SSepherosa Ziehau } else { 56004fa38985SSepherosa Ziehau error = 0; 56014fa38985SSepherosa Ziehau sc->bnx_npoll_txoff = off; 56024fa38985SSepherosa Ziehau sc->bnx_npoll_rxoff = off; 56034fa38985SSepherosa Ziehau } 56044fa38985SSepherosa Ziehau ifnet_deserialize_all(ifp); 56054fa38985SSepherosa Ziehau 56064fa38985SSepherosa Ziehau return error; 56074fa38985SSepherosa Ziehau } 56084fa38985SSepherosa Ziehau 56094fa38985SSepherosa Ziehau static int 56104fa38985SSepherosa Ziehau bnx_sysctl_npoll_rxoff(SYSCTL_HANDLER_ARGS) 56114fa38985SSepherosa Ziehau { 56124fa38985SSepherosa Ziehau struct bnx_softc *sc = (void *)arg1; 56134fa38985SSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if; 56144fa38985SSepherosa Ziehau int error, off; 56154fa38985SSepherosa Ziehau 56164fa38985SSepherosa Ziehau off = sc->bnx_npoll_rxoff; 56174fa38985SSepherosa Ziehau error = sysctl_handle_int(oidp, &off, 0, req); 56184fa38985SSepherosa Ziehau if (error || req->newptr == NULL) 56194fa38985SSepherosa Ziehau return error; 56204fa38985SSepherosa Ziehau if (off < 0) 56214fa38985SSepherosa Ziehau return EINVAL; 56224fa38985SSepherosa Ziehau 56234fa38985SSepherosa Ziehau ifnet_serialize_all(ifp); 56244fa38985SSepherosa Ziehau if (off >= ncpus2 || off % sc->bnx_rx_retcnt != 0) { 56254fa38985SSepherosa Ziehau error = EINVAL; 56264fa38985SSepherosa Ziehau } else { 56274fa38985SSepherosa Ziehau error = 0; 56284fa38985SSepherosa Ziehau sc->bnx_npoll_rxoff = off; 56294fa38985SSepherosa Ziehau } 56304fa38985SSepherosa Ziehau ifnet_deserialize_all(ifp); 56314fa38985SSepherosa Ziehau 56324fa38985SSepherosa Ziehau return error; 56334fa38985SSepherosa Ziehau } 56344fa38985SSepherosa Ziehau 56354fa38985SSepherosa Ziehau static int 56364fa38985SSepherosa Ziehau bnx_sysctl_npoll_txoff(SYSCTL_HANDLER_ARGS) 56374fa38985SSepherosa Ziehau { 56384fa38985SSepherosa Ziehau struct bnx_softc *sc = (void *)arg1; 56394fa38985SSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if; 56404fa38985SSepherosa Ziehau int error, off; 56414fa38985SSepherosa Ziehau 56424fa38985SSepherosa Ziehau off = sc->bnx_npoll_txoff; 56434fa38985SSepherosa Ziehau error = sysctl_handle_int(oidp, &off, 0, req); 56444fa38985SSepherosa Ziehau if (error || req->newptr == NULL) 56454fa38985SSepherosa Ziehau return error; 56464fa38985SSepherosa Ziehau if (off < 0) 56474fa38985SSepherosa Ziehau return EINVAL; 56484fa38985SSepherosa Ziehau 56494fa38985SSepherosa Ziehau ifnet_serialize_all(ifp); 56504fa38985SSepherosa Ziehau if (off >= ncpus2) { 56514fa38985SSepherosa Ziehau error = EINVAL; 56524fa38985SSepherosa Ziehau } else { 56534fa38985SSepherosa Ziehau error = 0; 56544fa38985SSepherosa Ziehau sc->bnx_npoll_txoff = off; 56554fa38985SSepherosa Ziehau } 56564fa38985SSepherosa Ziehau ifnet_deserialize_all(ifp); 56574fa38985SSepherosa Ziehau 56584fa38985SSepherosa Ziehau return error; 56594fa38985SSepherosa Ziehau } 56604fa38985SSepherosa Ziehau 56614fa38985SSepherosa Ziehau #endif /* IFPOLL_ENABLE */ 56627dbaa833SSepherosa Ziehau 56637dbaa833SSepherosa Ziehau static void 56647dbaa833SSepherosa Ziehau bnx_set_tick_cpuid(struct bnx_softc *sc, boolean_t polling) 56657dbaa833SSepherosa Ziehau { 56667dbaa833SSepherosa Ziehau if (polling) 56677dbaa833SSepherosa Ziehau sc->bnx_tick_cpuid = 0; /* XXX */ 56687dbaa833SSepherosa Ziehau else 56697dbaa833SSepherosa Ziehau sc->bnx_tick_cpuid = sc->bnx_intr_data[0].bnx_intr_cpuid; 56707dbaa833SSepherosa Ziehau } 5671841cdf08SSepherosa Ziehau 5672841cdf08SSepherosa Ziehau static void 5673841cdf08SSepherosa Ziehau bnx_rx_std_refill_ithread(void *xstd) 5674841cdf08SSepherosa Ziehau { 5675841cdf08SSepherosa Ziehau struct bnx_rx_std_ring *std = xstd; 5676841cdf08SSepherosa Ziehau struct globaldata *gd = mycpu; 5677841cdf08SSepherosa Ziehau 5678841cdf08SSepherosa Ziehau crit_enter_gd(gd); 5679841cdf08SSepherosa Ziehau 5680841cdf08SSepherosa Ziehau while (!std->bnx_rx_std_stop) { 5681841cdf08SSepherosa Ziehau if (std->bnx_rx_std_refill) { 5682841cdf08SSepherosa Ziehau lwkt_serialize_handler_call( 5683841cdf08SSepherosa Ziehau &std->bnx_rx_std_serialize, 5684841cdf08SSepherosa Ziehau bnx_rx_std_refill, std, NULL); 5685841cdf08SSepherosa Ziehau } 5686841cdf08SSepherosa Ziehau 5687841cdf08SSepherosa Ziehau crit_exit_gd(gd); 5688841cdf08SSepherosa Ziehau crit_enter_gd(gd); 5689841cdf08SSepherosa Ziehau 5690695a8586SSepherosa Ziehau atomic_poll_release_int(&std->bnx_rx_std_running); 5691695a8586SSepherosa Ziehau cpu_mfence(); 5692695a8586SSepherosa Ziehau 5693841cdf08SSepherosa Ziehau if (!std->bnx_rx_std_refill && !std->bnx_rx_std_stop) { 5694841cdf08SSepherosa Ziehau lwkt_deschedule_self(gd->gd_curthread); 5695841cdf08SSepherosa Ziehau lwkt_switch(); 5696841cdf08SSepherosa Ziehau } 5697841cdf08SSepherosa Ziehau } 5698841cdf08SSepherosa Ziehau 5699841cdf08SSepherosa Ziehau crit_exit_gd(gd); 5700841cdf08SSepherosa Ziehau 5701841cdf08SSepherosa Ziehau wakeup(std); 5702841cdf08SSepherosa Ziehau 5703841cdf08SSepherosa Ziehau lwkt_exit(); 5704841cdf08SSepherosa Ziehau } 5705841cdf08SSepherosa Ziehau 5706841cdf08SSepherosa Ziehau static void 5707841cdf08SSepherosa Ziehau bnx_rx_std_refill(void *xstd, void *frame __unused) 5708841cdf08SSepherosa Ziehau { 5709841cdf08SSepherosa Ziehau struct bnx_rx_std_ring *std = xstd; 5710695a8586SSepherosa Ziehau int cnt, refill_mask; 5711841cdf08SSepherosa Ziehau 5712841cdf08SSepherosa Ziehau again: 5713841cdf08SSepherosa Ziehau cnt = 0; 5714841cdf08SSepherosa Ziehau 5715841cdf08SSepherosa Ziehau cpu_lfence(); 5716695a8586SSepherosa Ziehau refill_mask = std->bnx_rx_std_refill; 5717695a8586SSepherosa Ziehau atomic_clear_int(&std->bnx_rx_std_refill, refill_mask); 5718841cdf08SSepherosa Ziehau 5719695a8586SSepherosa Ziehau while (refill_mask) { 5720695a8586SSepherosa Ziehau uint16_t check_idx = std->bnx_rx_std; 5721695a8586SSepherosa Ziehau int ret_idx; 5722695a8586SSepherosa Ziehau 5723695a8586SSepherosa Ziehau ret_idx = bsfl(refill_mask); 5724841cdf08SSepherosa Ziehau for (;;) { 5725841cdf08SSepherosa Ziehau struct bnx_rx_buf *rb; 5726695a8586SSepherosa Ziehau int refilled; 5727841cdf08SSepherosa Ziehau 5728841cdf08SSepherosa Ziehau BNX_INC(check_idx, BGE_STD_RX_RING_CNT); 5729841cdf08SSepherosa Ziehau rb = &std->bnx_rx_std_buf[check_idx]; 5730695a8586SSepherosa Ziehau refilled = rb->bnx_rx_refilled; 5731841cdf08SSepherosa Ziehau cpu_lfence(); 5732695a8586SSepherosa Ziehau if (refilled) { 5733841cdf08SSepherosa Ziehau bnx_setup_rxdesc_std(std, check_idx); 5734841cdf08SSepherosa Ziehau std->bnx_rx_std = check_idx; 5735841cdf08SSepherosa Ziehau ++cnt; 5736695a8586SSepherosa Ziehau if (cnt >= 8) { 5737625c3ba3SSepherosa Ziehau atomic_subtract_int( 5738625c3ba3SSepherosa Ziehau &std->bnx_rx_std_used, cnt); 5739695a8586SSepherosa Ziehau bnx_writembx(std->bnx_sc, 5740695a8586SSepherosa Ziehau BGE_MBX_RX_STD_PROD_LO, 5741695a8586SSepherosa Ziehau std->bnx_rx_std); 5742695a8586SSepherosa Ziehau cnt = 0; 5743695a8586SSepherosa Ziehau } 5744841cdf08SSepherosa Ziehau } else { 5745841cdf08SSepherosa Ziehau break; 5746841cdf08SSepherosa Ziehau } 5747841cdf08SSepherosa Ziehau } 5748695a8586SSepherosa Ziehau refill_mask &= ~(1 << ret_idx); 5749695a8586SSepherosa Ziehau } 5750841cdf08SSepherosa Ziehau 5751841cdf08SSepherosa Ziehau if (cnt) { 5752625c3ba3SSepherosa Ziehau atomic_subtract_int(&std->bnx_rx_std_used, cnt); 5753841cdf08SSepherosa Ziehau bnx_writembx(std->bnx_sc, BGE_MBX_RX_STD_PROD_LO, 5754841cdf08SSepherosa Ziehau std->bnx_rx_std); 5755841cdf08SSepherosa Ziehau } 5756841cdf08SSepherosa Ziehau 5757841cdf08SSepherosa Ziehau if (std->bnx_rx_std_refill) 5758841cdf08SSepherosa Ziehau goto again; 5759841cdf08SSepherosa Ziehau 5760841cdf08SSepherosa Ziehau atomic_poll_release_int(&std->bnx_rx_std_running); 5761841cdf08SSepherosa Ziehau cpu_mfence(); 5762841cdf08SSepherosa Ziehau 5763841cdf08SSepherosa Ziehau if (std->bnx_rx_std_refill) 5764841cdf08SSepherosa Ziehau goto again; 5765841cdf08SSepherosa Ziehau } 5766841cdf08SSepherosa Ziehau 5767841cdf08SSepherosa Ziehau static int 5768841cdf08SSepherosa Ziehau bnx_sysctl_std_refill(SYSCTL_HANDLER_ARGS) 5769841cdf08SSepherosa Ziehau { 5770841cdf08SSepherosa Ziehau struct bnx_softc *sc = (void *)arg1; 5771841cdf08SSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if; 5772841cdf08SSepherosa Ziehau struct bnx_rx_ret_ring *ret = &sc->bnx_rx_ret_ring[0]; 5773841cdf08SSepherosa Ziehau int error, cntmax, i; 5774841cdf08SSepherosa Ziehau 5775841cdf08SSepherosa Ziehau cntmax = ret->bnx_rx_cntmax; 5776841cdf08SSepherosa Ziehau error = sysctl_handle_int(oidp, &cntmax, 0, req); 5777841cdf08SSepherosa Ziehau if (error || req->newptr == NULL) 5778841cdf08SSepherosa Ziehau return error; 5779841cdf08SSepherosa Ziehau 5780841cdf08SSepherosa Ziehau ifnet_serialize_all(ifp); 5781841cdf08SSepherosa Ziehau 5782625c3ba3SSepherosa Ziehau if ((cntmax * sc->bnx_rx_retcnt) >= BGE_STD_RX_RING_CNT / 2) { 5783841cdf08SSepherosa Ziehau error = EINVAL; 5784841cdf08SSepherosa Ziehau goto back; 5785841cdf08SSepherosa Ziehau } 5786841cdf08SSepherosa Ziehau 5787841cdf08SSepherosa Ziehau for (i = 0; i < sc->bnx_tx_ringcnt; ++i) 5788841cdf08SSepherosa Ziehau sc->bnx_rx_ret_ring[i].bnx_rx_cntmax = cntmax; 5789841cdf08SSepherosa Ziehau error = 0; 5790841cdf08SSepherosa Ziehau 5791841cdf08SSepherosa Ziehau back: 5792841cdf08SSepherosa Ziehau ifnet_deserialize_all(ifp); 5793841cdf08SSepherosa Ziehau 5794841cdf08SSepherosa Ziehau return error; 5795841cdf08SSepherosa Ziehau } 5796695a8586SSepherosa Ziehau 5797695a8586SSepherosa Ziehau static void 5798695a8586SSepherosa Ziehau bnx_init_rss(struct bnx_softc *sc) 5799695a8586SSepherosa Ziehau { 5800695a8586SSepherosa Ziehau uint8_t key[BGE_RSS_KEYREG_CNT * BGE_RSS_KEYREG_SIZE]; 5801695a8586SSepherosa Ziehau int i, j, r; 5802695a8586SSepherosa Ziehau 5803695a8586SSepherosa Ziehau KKASSERT(BNX_RSS_ENABLED(sc)); 5804695a8586SSepherosa Ziehau 58050f02bb87SSepherosa Ziehau /* 58060f02bb87SSepherosa Ziehau * Configure RSS redirect table in following fashion: 58070f02bb87SSepherosa Ziehau * (hash & ring_cnt_mask) == rdr_table[(hash & rdr_table_mask)] 58080f02bb87SSepherosa Ziehau */ 5809695a8586SSepherosa Ziehau r = 0; 5810695a8586SSepherosa Ziehau for (j = 0; j < BGE_RSS_INDIR_TBL_CNT; ++j) { 5811695a8586SSepherosa Ziehau uint32_t tbl = 0; 5812695a8586SSepherosa Ziehau 5813695a8586SSepherosa Ziehau for (i = 0; i < BGE_RSS_INDIR_TBLENT_CNT; ++i) { 5814695a8586SSepherosa Ziehau uint32_t q; 5815695a8586SSepherosa Ziehau 5816695a8586SSepherosa Ziehau q = r % sc->bnx_rx_retcnt; 5817695a8586SSepherosa Ziehau tbl |= q << (BGE_RSS_INDIR_TBLENT_SHIFT * 5818695a8586SSepherosa Ziehau (BGE_RSS_INDIR_TBLENT_CNT - i - 1)); 5819695a8586SSepherosa Ziehau ++r; 5820695a8586SSepherosa Ziehau } 5821695a8586SSepherosa Ziehau 5822695a8586SSepherosa Ziehau BNX_RSS_DPRINTF(sc, 1, "tbl%d %08x\n", j, tbl); 5823695a8586SSepherosa Ziehau CSR_WRITE_4(sc, BGE_RSS_INDIR_TBL(j), tbl); 5824695a8586SSepherosa Ziehau } 5825695a8586SSepherosa Ziehau 5826695a8586SSepherosa Ziehau toeplitz_get_key(key, sizeof(key)); 5827695a8586SSepherosa Ziehau for (i = 0; i < BGE_RSS_KEYREG_CNT; ++i) { 5828695a8586SSepherosa Ziehau uint32_t keyreg; 5829695a8586SSepherosa Ziehau 5830695a8586SSepherosa Ziehau keyreg = BGE_RSS_KEYREG_VAL(key, i); 5831695a8586SSepherosa Ziehau 5832695a8586SSepherosa Ziehau BNX_RSS_DPRINTF(sc, 1, "key%d %08x\n", i, keyreg); 5833695a8586SSepherosa Ziehau CSR_WRITE_4(sc, BGE_RSS_KEYREG(i), keyreg); 5834695a8586SSepherosa Ziehau } 5835695a8586SSepherosa Ziehau } 5836695a8586SSepherosa Ziehau 5837695a8586SSepherosa Ziehau static void 5838695a8586SSepherosa Ziehau bnx_setup_ring_cnt(struct bnx_softc *sc) 5839695a8586SSepherosa Ziehau { 5840695a8586SSepherosa Ziehau int msix_enable, i, msix_cnt, msix_cnt2, ring_max; 5841695a8586SSepherosa Ziehau 5842695a8586SSepherosa Ziehau sc->bnx_tx_ringcnt = 1; 5843695a8586SSepherosa Ziehau sc->bnx_rx_retcnt = 1; 5844695a8586SSepherosa Ziehau sc->bnx_intr_cnt = 1; 5845695a8586SSepherosa Ziehau 5846695a8586SSepherosa Ziehau msix_enable = device_getenv_int(sc->bnx_dev, "msix.enable", 5847695a8586SSepherosa Ziehau bnx_msix_enable); 5848695a8586SSepherosa Ziehau if (!msix_enable) 5849695a8586SSepherosa Ziehau return; 5850695a8586SSepherosa Ziehau 5851695a8586SSepherosa Ziehau if (ncpus2 == 1) 5852695a8586SSepherosa Ziehau return; 5853695a8586SSepherosa Ziehau 5854695a8586SSepherosa Ziehau msix_cnt = pci_msix_count(sc->bnx_dev); 5855695a8586SSepherosa Ziehau if (msix_cnt <= 1) 5856695a8586SSepherosa Ziehau return; 5857695a8586SSepherosa Ziehau 5858695a8586SSepherosa Ziehau i = 0; 5859695a8586SSepherosa Ziehau while ((1 << (i + 1)) <= msix_cnt) 5860695a8586SSepherosa Ziehau ++i; 5861695a8586SSepherosa Ziehau msix_cnt2 = 1 << i; 5862695a8586SSepherosa Ziehau 5863695a8586SSepherosa Ziehau /* 5864695a8586SSepherosa Ziehau * One MSI-X vector is dedicated to status or single TX queue, 5865695a8586SSepherosa Ziehau * so make sure that there are enough MSI-X vectors. 5866695a8586SSepherosa Ziehau */ 5867695a8586SSepherosa Ziehau if (msix_cnt == msix_cnt2) { 5868695a8586SSepherosa Ziehau /* 5869695a8586SSepherosa Ziehau * XXX 5870695a8586SSepherosa Ziehau * This probably will not happen; 57785/5718 families 5871695a8586SSepherosa Ziehau * come with at least 5 MSI-X vectors. 5872695a8586SSepherosa Ziehau */ 5873695a8586SSepherosa Ziehau msix_cnt2 >>= 1; 5874695a8586SSepherosa Ziehau if (msix_cnt2 <= 1) { 5875695a8586SSepherosa Ziehau device_printf(sc->bnx_dev, 5876695a8586SSepherosa Ziehau "MSI-X count %d could not be used\n", msix_cnt); 5877695a8586SSepherosa Ziehau return; 5878695a8586SSepherosa Ziehau } 5879695a8586SSepherosa Ziehau device_printf(sc->bnx_dev, "MSI-X count %d is power of 2\n", 5880695a8586SSepherosa Ziehau msix_cnt); 5881695a8586SSepherosa Ziehau } 5882695a8586SSepherosa Ziehau 5883695a8586SSepherosa Ziehau /* 5884695a8586SSepherosa Ziehau * Setup RX ring count 5885695a8586SSepherosa Ziehau */ 5886695a8586SSepherosa Ziehau ring_max = BNX_RX_RING_MAX; 5887695a8586SSepherosa Ziehau if (ring_max > msix_cnt2) 5888695a8586SSepherosa Ziehau ring_max = msix_cnt2; 5889695a8586SSepherosa Ziehau sc->bnx_rx_retcnt = device_getenv_int(sc->bnx_dev, "rx_rings", 5890695a8586SSepherosa Ziehau bnx_rx_rings); 5891695a8586SSepherosa Ziehau sc->bnx_rx_retcnt = if_ring_count2(sc->bnx_rx_retcnt, ring_max); 5892695a8586SSepherosa Ziehau 5893695a8586SSepherosa Ziehau if (sc->bnx_rx_retcnt == 1) 5894695a8586SSepherosa Ziehau return; 5895695a8586SSepherosa Ziehau 5896695a8586SSepherosa Ziehau /* 5897695a8586SSepherosa Ziehau * We need one extra MSI-X vector for link status or 5898695a8586SSepherosa Ziehau * TX ring (if only one TX ring is enabled). 5899695a8586SSepherosa Ziehau */ 5900695a8586SSepherosa Ziehau sc->bnx_intr_cnt = sc->bnx_rx_retcnt + 1; 5901695a8586SSepherosa Ziehau 5902695a8586SSepherosa Ziehau /* 5903695a8586SSepherosa Ziehau * Setup TX ring count 5904695a8586SSepherosa Ziehau * 5905695a8586SSepherosa Ziehau * Currently only BCM5719 and BCM5720 support multiple TX rings 5906695a8586SSepherosa Ziehau * and the TX ring count must be less than the RX ring count. 5907695a8586SSepherosa Ziehau */ 5908695a8586SSepherosa Ziehau if (sc->bnx_asicrev == BGE_ASICREV_BCM5719 || 5909695a8586SSepherosa Ziehau sc->bnx_asicrev == BGE_ASICREV_BCM5720) { 5910695a8586SSepherosa Ziehau ring_max = BNX_TX_RING_MAX; 5911695a8586SSepherosa Ziehau if (ring_max > msix_cnt2) 5912695a8586SSepherosa Ziehau ring_max = msix_cnt2; 5913695a8586SSepherosa Ziehau if (ring_max > sc->bnx_rx_retcnt) 5914695a8586SSepherosa Ziehau ring_max = sc->bnx_rx_retcnt; 5915695a8586SSepherosa Ziehau sc->bnx_tx_ringcnt = device_getenv_int(sc->bnx_dev, "tx_rings", 5916695a8586SSepherosa Ziehau bnx_tx_rings); 5917695a8586SSepherosa Ziehau sc->bnx_tx_ringcnt = if_ring_count2(sc->bnx_tx_ringcnt, 5918695a8586SSepherosa Ziehau ring_max); 5919695a8586SSepherosa Ziehau } 5920695a8586SSepherosa Ziehau } 5921695a8586SSepherosa Ziehau 5922695a8586SSepherosa Ziehau static int 5923695a8586SSepherosa Ziehau bnx_alloc_msix(struct bnx_softc *sc) 5924695a8586SSepherosa Ziehau { 5925695a8586SSepherosa Ziehau struct bnx_intr_data *intr; 5926695a8586SSepherosa Ziehau boolean_t setup = FALSE; 5927695a8586SSepherosa Ziehau int error, i, offset, offset_def; 5928695a8586SSepherosa Ziehau 5929695a8586SSepherosa Ziehau KKASSERT(sc->bnx_intr_cnt > 1); 5930695a8586SSepherosa Ziehau KKASSERT(sc->bnx_intr_cnt == sc->bnx_rx_retcnt + 1); 5931695a8586SSepherosa Ziehau 5932695a8586SSepherosa Ziehau if (sc->bnx_flags & BNX_FLAG_RXTX_BUNDLE) { 5933695a8586SSepherosa Ziehau /* 5934695a8586SSepherosa Ziehau * Link status 5935695a8586SSepherosa Ziehau */ 5936695a8586SSepherosa Ziehau intr = &sc->bnx_intr_data[0]; 5937695a8586SSepherosa Ziehau 5938695a8586SSepherosa Ziehau intr->bnx_intr_serialize = &sc->bnx_main_serialize; 5939695a8586SSepherosa Ziehau intr->bnx_saved_status_tag = &sc->bnx_saved_status_tag; 5940695a8586SSepherosa Ziehau 5941695a8586SSepherosa Ziehau intr->bnx_intr_func = bnx_msix_status; 5942695a8586SSepherosa Ziehau intr->bnx_intr_arg = sc; 5943695a8586SSepherosa Ziehau intr->bnx_intr_cpuid = 0; /* XXX */ 5944695a8586SSepherosa Ziehau 5945695a8586SSepherosa Ziehau ksnprintf(intr->bnx_intr_desc0, sizeof(intr->bnx_intr_desc0), 5946695a8586SSepherosa Ziehau "%s sts", device_get_nameunit(sc->bnx_dev)); 5947695a8586SSepherosa Ziehau intr->bnx_intr_desc = intr->bnx_intr_desc0; 5948695a8586SSepherosa Ziehau 5949695a8586SSepherosa Ziehau /* 5950695a8586SSepherosa Ziehau * RX/TX rings 5951695a8586SSepherosa Ziehau */ 5952695a8586SSepherosa Ziehau if (sc->bnx_rx_retcnt == ncpus2) { 5953695a8586SSepherosa Ziehau offset = 0; 5954695a8586SSepherosa Ziehau } else { 5955695a8586SSepherosa Ziehau offset_def = (sc->bnx_rx_retcnt * 5956695a8586SSepherosa Ziehau device_get_unit(sc->bnx_dev)) % ncpus2; 5957695a8586SSepherosa Ziehau 5958695a8586SSepherosa Ziehau offset = device_getenv_int(sc->bnx_dev, 5959695a8586SSepherosa Ziehau "msix.offset", offset_def); 5960695a8586SSepherosa Ziehau if (offset >= ncpus2 || 5961695a8586SSepherosa Ziehau offset % sc->bnx_rx_retcnt != 0) { 5962695a8586SSepherosa Ziehau device_printf(sc->bnx_dev, 5963695a8586SSepherosa Ziehau "invalid msix.offset %d, use %d\n", 5964695a8586SSepherosa Ziehau offset, offset_def); 5965695a8586SSepherosa Ziehau offset = offset_def; 5966695a8586SSepherosa Ziehau } 5967695a8586SSepherosa Ziehau } 5968695a8586SSepherosa Ziehau 5969695a8586SSepherosa Ziehau for (i = 1; i < sc->bnx_intr_cnt; ++i) { 5970695a8586SSepherosa Ziehau int idx = i - 1; 5971695a8586SSepherosa Ziehau 5972695a8586SSepherosa Ziehau intr = &sc->bnx_intr_data[i]; 5973695a8586SSepherosa Ziehau 5974695a8586SSepherosa Ziehau KKASSERT(idx < sc->bnx_rx_retcnt); 5975695a8586SSepherosa Ziehau intr->bnx_ret = &sc->bnx_rx_ret_ring[idx]; 5976695a8586SSepherosa Ziehau if (idx < sc->bnx_tx_ringcnt) { 5977695a8586SSepherosa Ziehau intr->bnx_txr = &sc->bnx_tx_ring[idx]; 5978695a8586SSepherosa Ziehau intr->bnx_ret->bnx_txr = intr->bnx_txr; 5979695a8586SSepherosa Ziehau } 5980695a8586SSepherosa Ziehau 5981695a8586SSepherosa Ziehau intr->bnx_intr_serialize = 5982695a8586SSepherosa Ziehau &intr->bnx_ret->bnx_rx_ret_serialize; 5983695a8586SSepherosa Ziehau intr->bnx_saved_status_tag = 5984695a8586SSepherosa Ziehau &intr->bnx_ret->bnx_saved_status_tag; 5985695a8586SSepherosa Ziehau 5986695a8586SSepherosa Ziehau intr->bnx_intr_arg = intr->bnx_ret; 5987695a8586SSepherosa Ziehau KKASSERT(idx + offset < ncpus2); 5988695a8586SSepherosa Ziehau intr->bnx_intr_cpuid = idx + offset; 5989695a8586SSepherosa Ziehau 5990695a8586SSepherosa Ziehau if (intr->bnx_txr == NULL) { 5991695a8586SSepherosa Ziehau intr->bnx_intr_check = bnx_check_intr_rx; 5992695a8586SSepherosa Ziehau intr->bnx_intr_func = bnx_msix_rx; 5993695a8586SSepherosa Ziehau ksnprintf(intr->bnx_intr_desc0, 5994695a8586SSepherosa Ziehau sizeof(intr->bnx_intr_desc0), "%s rx%d", 5995695a8586SSepherosa Ziehau device_get_nameunit(sc->bnx_dev), idx); 5996695a8586SSepherosa Ziehau } else { 5997695a8586SSepherosa Ziehau intr->bnx_intr_check = bnx_check_intr_rxtx; 5998695a8586SSepherosa Ziehau intr->bnx_intr_func = bnx_msix_rxtx; 5999695a8586SSepherosa Ziehau ksnprintf(intr->bnx_intr_desc0, 6000695a8586SSepherosa Ziehau sizeof(intr->bnx_intr_desc0), "%s rxtx%d", 6001695a8586SSepherosa Ziehau device_get_nameunit(sc->bnx_dev), idx); 6002695a8586SSepherosa Ziehau 6003695a8586SSepherosa Ziehau intr->bnx_txr->bnx_tx_cpuid = 6004695a8586SSepherosa Ziehau intr->bnx_intr_cpuid; 6005695a8586SSepherosa Ziehau } 6006695a8586SSepherosa Ziehau intr->bnx_intr_desc = intr->bnx_intr_desc0; 6007695a8586SSepherosa Ziehau 6008695a8586SSepherosa Ziehau intr->bnx_ret->bnx_msix_mbx = intr->bnx_intr_mbx; 6009695a8586SSepherosa Ziehau } 6010695a8586SSepherosa Ziehau } else { 6011695a8586SSepherosa Ziehau /* 6012695a8586SSepherosa Ziehau * TX ring and link status 6013695a8586SSepherosa Ziehau */ 6014695a8586SSepherosa Ziehau offset_def = device_get_unit(sc->bnx_dev) % ncpus2; 6015695a8586SSepherosa Ziehau offset = device_getenv_int(sc->bnx_dev, "msix.txoff", 6016695a8586SSepherosa Ziehau offset_def); 6017695a8586SSepherosa Ziehau if (offset >= ncpus2) { 6018695a8586SSepherosa Ziehau device_printf(sc->bnx_dev, 6019695a8586SSepherosa Ziehau "invalid msix.txoff %d, use %d\n", 6020695a8586SSepherosa Ziehau offset, offset_def); 6021695a8586SSepherosa Ziehau offset = offset_def; 6022695a8586SSepherosa Ziehau } 6023695a8586SSepherosa Ziehau 6024695a8586SSepherosa Ziehau intr = &sc->bnx_intr_data[0]; 6025695a8586SSepherosa Ziehau 6026695a8586SSepherosa Ziehau intr->bnx_txr = &sc->bnx_tx_ring[0]; 6027695a8586SSepherosa Ziehau intr->bnx_intr_serialize = &sc->bnx_main_serialize; 6028695a8586SSepherosa Ziehau intr->bnx_intr_check = bnx_check_intr_tx; 6029695a8586SSepherosa Ziehau intr->bnx_saved_status_tag = 6030695a8586SSepherosa Ziehau &intr->bnx_txr->bnx_saved_status_tag; 6031695a8586SSepherosa Ziehau 6032695a8586SSepherosa Ziehau intr->bnx_intr_func = bnx_msix_tx_status; 6033695a8586SSepherosa Ziehau intr->bnx_intr_arg = intr->bnx_txr; 6034695a8586SSepherosa Ziehau intr->bnx_intr_cpuid = offset; 6035695a8586SSepherosa Ziehau 6036695a8586SSepherosa Ziehau ksnprintf(intr->bnx_intr_desc0, sizeof(intr->bnx_intr_desc0), 6037695a8586SSepherosa Ziehau "%s ststx", device_get_nameunit(sc->bnx_dev)); 6038695a8586SSepherosa Ziehau intr->bnx_intr_desc = intr->bnx_intr_desc0; 6039695a8586SSepherosa Ziehau 6040695a8586SSepherosa Ziehau intr->bnx_txr->bnx_tx_cpuid = intr->bnx_intr_cpuid; 6041695a8586SSepherosa Ziehau 6042695a8586SSepherosa Ziehau /* 6043695a8586SSepherosa Ziehau * RX rings 6044695a8586SSepherosa Ziehau */ 6045695a8586SSepherosa Ziehau if (sc->bnx_rx_retcnt == ncpus2) { 6046695a8586SSepherosa Ziehau offset = 0; 6047695a8586SSepherosa Ziehau } else { 6048695a8586SSepherosa Ziehau offset_def = (sc->bnx_rx_retcnt * 6049695a8586SSepherosa Ziehau device_get_unit(sc->bnx_dev)) % ncpus2; 6050695a8586SSepherosa Ziehau 6051695a8586SSepherosa Ziehau offset = device_getenv_int(sc->bnx_dev, 6052695a8586SSepherosa Ziehau "msix.rxoff", offset_def); 6053695a8586SSepherosa Ziehau if (offset >= ncpus2 || 6054695a8586SSepherosa Ziehau offset % sc->bnx_rx_retcnt != 0) { 6055695a8586SSepherosa Ziehau device_printf(sc->bnx_dev, 6056695a8586SSepherosa Ziehau "invalid msix.rxoff %d, use %d\n", 6057695a8586SSepherosa Ziehau offset, offset_def); 6058695a8586SSepherosa Ziehau offset = offset_def; 6059695a8586SSepherosa Ziehau } 6060695a8586SSepherosa Ziehau } 6061695a8586SSepherosa Ziehau 6062695a8586SSepherosa Ziehau for (i = 1; i < sc->bnx_intr_cnt; ++i) { 6063695a8586SSepherosa Ziehau int idx = i - 1; 6064695a8586SSepherosa Ziehau 6065695a8586SSepherosa Ziehau intr = &sc->bnx_intr_data[i]; 6066695a8586SSepherosa Ziehau 6067695a8586SSepherosa Ziehau KKASSERT(idx < sc->bnx_rx_retcnt); 6068695a8586SSepherosa Ziehau intr->bnx_ret = &sc->bnx_rx_ret_ring[idx]; 6069695a8586SSepherosa Ziehau intr->bnx_intr_serialize = 6070695a8586SSepherosa Ziehau &intr->bnx_ret->bnx_rx_ret_serialize; 6071695a8586SSepherosa Ziehau intr->bnx_intr_check = bnx_check_intr_rx; 6072695a8586SSepherosa Ziehau intr->bnx_saved_status_tag = 6073695a8586SSepherosa Ziehau &intr->bnx_ret->bnx_saved_status_tag; 6074695a8586SSepherosa Ziehau 6075695a8586SSepherosa Ziehau intr->bnx_intr_func = bnx_msix_rx; 6076695a8586SSepherosa Ziehau intr->bnx_intr_arg = intr->bnx_ret; 6077695a8586SSepherosa Ziehau KKASSERT(idx + offset < ncpus2); 6078695a8586SSepherosa Ziehau intr->bnx_intr_cpuid = idx + offset; 6079695a8586SSepherosa Ziehau 6080695a8586SSepherosa Ziehau ksnprintf(intr->bnx_intr_desc0, 6081695a8586SSepherosa Ziehau sizeof(intr->bnx_intr_desc0), "%s rx%d", 6082695a8586SSepherosa Ziehau device_get_nameunit(sc->bnx_dev), idx); 6083695a8586SSepherosa Ziehau intr->bnx_intr_desc = intr->bnx_intr_desc0; 6084695a8586SSepherosa Ziehau 6085695a8586SSepherosa Ziehau intr->bnx_ret->bnx_msix_mbx = intr->bnx_intr_mbx; 6086695a8586SSepherosa Ziehau } 6087695a8586SSepherosa Ziehau } 6088695a8586SSepherosa Ziehau 60899f5082d5SSepherosa Ziehau if (BNX_IS_5717_PLUS(sc)) { 6090695a8586SSepherosa Ziehau sc->bnx_msix_mem_rid = PCIR_BAR(4); 60919f5082d5SSepherosa Ziehau } else { 60929f5082d5SSepherosa Ziehau if (sc->bnx_res2 == NULL) 6093715109c2SSepherosa Ziehau sc->bnx_msix_mem_rid = PCIR_BAR(2); 60949f5082d5SSepherosa Ziehau } 60959f5082d5SSepherosa Ziehau if (sc->bnx_msix_mem_rid != 0) { 6096695a8586SSepherosa Ziehau sc->bnx_msix_mem_res = bus_alloc_resource_any(sc->bnx_dev, 6097695a8586SSepherosa Ziehau SYS_RES_MEMORY, &sc->bnx_msix_mem_rid, RF_ACTIVE); 6098695a8586SSepherosa Ziehau if (sc->bnx_msix_mem_res == NULL) { 60999f5082d5SSepherosa Ziehau device_printf(sc->bnx_dev, 61009f5082d5SSepherosa Ziehau "could not alloc MSI-X table\n"); 6101695a8586SSepherosa Ziehau return ENXIO; 6102695a8586SSepherosa Ziehau } 61039f5082d5SSepherosa Ziehau } 6104695a8586SSepherosa Ziehau 6105695a8586SSepherosa Ziehau bnx_enable_msi(sc, TRUE); 6106695a8586SSepherosa Ziehau 6107695a8586SSepherosa Ziehau error = pci_setup_msix(sc->bnx_dev); 6108695a8586SSepherosa Ziehau if (error) { 6109695a8586SSepherosa Ziehau device_printf(sc->bnx_dev, "could not setup MSI-X\n"); 6110695a8586SSepherosa Ziehau goto back; 6111695a8586SSepherosa Ziehau } 6112695a8586SSepherosa Ziehau setup = TRUE; 6113695a8586SSepherosa Ziehau 6114695a8586SSepherosa Ziehau for (i = 0; i < sc->bnx_intr_cnt; ++i) { 6115695a8586SSepherosa Ziehau intr = &sc->bnx_intr_data[i]; 6116695a8586SSepherosa Ziehau 6117695a8586SSepherosa Ziehau error = pci_alloc_msix_vector(sc->bnx_dev, i, 6118695a8586SSepherosa Ziehau &intr->bnx_intr_rid, intr->bnx_intr_cpuid); 6119695a8586SSepherosa Ziehau if (error) { 6120695a8586SSepherosa Ziehau device_printf(sc->bnx_dev, 6121695a8586SSepherosa Ziehau "could not alloc MSI-X %d on cpu%d\n", 6122695a8586SSepherosa Ziehau i, intr->bnx_intr_cpuid); 6123695a8586SSepherosa Ziehau goto back; 6124695a8586SSepherosa Ziehau } 6125695a8586SSepherosa Ziehau 6126695a8586SSepherosa Ziehau intr->bnx_intr_res = bus_alloc_resource_any(sc->bnx_dev, 6127695a8586SSepherosa Ziehau SYS_RES_IRQ, &intr->bnx_intr_rid, RF_ACTIVE); 6128695a8586SSepherosa Ziehau if (intr->bnx_intr_res == NULL) { 6129695a8586SSepherosa Ziehau device_printf(sc->bnx_dev, 6130695a8586SSepherosa Ziehau "could not alloc MSI-X %d resource\n", i); 6131695a8586SSepherosa Ziehau error = ENXIO; 6132695a8586SSepherosa Ziehau goto back; 6133695a8586SSepherosa Ziehau } 6134695a8586SSepherosa Ziehau } 6135695a8586SSepherosa Ziehau 6136695a8586SSepherosa Ziehau pci_enable_msix(sc->bnx_dev); 6137695a8586SSepherosa Ziehau sc->bnx_intr_type = PCI_INTR_TYPE_MSIX; 6138695a8586SSepherosa Ziehau back: 6139695a8586SSepherosa Ziehau if (error) 6140695a8586SSepherosa Ziehau bnx_free_msix(sc, setup); 6141695a8586SSepherosa Ziehau return error; 6142695a8586SSepherosa Ziehau } 6143695a8586SSepherosa Ziehau 6144695a8586SSepherosa Ziehau static void 6145695a8586SSepherosa Ziehau bnx_free_msix(struct bnx_softc *sc, boolean_t setup) 6146695a8586SSepherosa Ziehau { 6147695a8586SSepherosa Ziehau int i; 6148695a8586SSepherosa Ziehau 6149695a8586SSepherosa Ziehau KKASSERT(sc->bnx_intr_cnt > 1); 6150695a8586SSepherosa Ziehau 6151695a8586SSepherosa Ziehau for (i = 0; i < sc->bnx_intr_cnt; ++i) { 6152695a8586SSepherosa Ziehau struct bnx_intr_data *intr = &sc->bnx_intr_data[i]; 6153695a8586SSepherosa Ziehau 6154695a8586SSepherosa Ziehau if (intr->bnx_intr_res != NULL) { 6155695a8586SSepherosa Ziehau bus_release_resource(sc->bnx_dev, SYS_RES_IRQ, 6156695a8586SSepherosa Ziehau intr->bnx_intr_rid, intr->bnx_intr_res); 6157695a8586SSepherosa Ziehau } 6158695a8586SSepherosa Ziehau if (intr->bnx_intr_rid >= 0) { 6159695a8586SSepherosa Ziehau pci_release_msix_vector(sc->bnx_dev, 6160695a8586SSepherosa Ziehau intr->bnx_intr_rid); 6161695a8586SSepherosa Ziehau } 6162695a8586SSepherosa Ziehau } 6163695a8586SSepherosa Ziehau if (setup) 6164695a8586SSepherosa Ziehau pci_teardown_msix(sc->bnx_dev); 6165695a8586SSepherosa Ziehau } 6166695a8586SSepherosa Ziehau 6167695a8586SSepherosa Ziehau static void 6168695a8586SSepherosa Ziehau bnx_rx_std_refill_sched_ipi(void *xret) 6169695a8586SSepherosa Ziehau { 6170695a8586SSepherosa Ziehau struct bnx_rx_ret_ring *ret = xret; 6171695a8586SSepherosa Ziehau struct bnx_rx_std_ring *std = ret->bnx_std; 6172695a8586SSepherosa Ziehau struct globaldata *gd = mycpu; 6173695a8586SSepherosa Ziehau 6174695a8586SSepherosa Ziehau crit_enter_gd(gd); 6175695a8586SSepherosa Ziehau 6176695a8586SSepherosa Ziehau atomic_set_int(&std->bnx_rx_std_refill, ret->bnx_rx_mask); 6177695a8586SSepherosa Ziehau cpu_sfence(); 6178695a8586SSepherosa Ziehau 6179695a8586SSepherosa Ziehau KKASSERT(std->bnx_rx_std_ithread.td_gd == gd); 6180695a8586SSepherosa Ziehau lwkt_schedule(&std->bnx_rx_std_ithread); 6181695a8586SSepherosa Ziehau 6182695a8586SSepherosa Ziehau crit_exit_gd(gd); 6183695a8586SSepherosa Ziehau } 6184695a8586SSepherosa Ziehau 6185695a8586SSepherosa Ziehau static void 6186695a8586SSepherosa Ziehau bnx_rx_std_refill_stop(void *xstd) 6187695a8586SSepherosa Ziehau { 6188695a8586SSepherosa Ziehau struct bnx_rx_std_ring *std = xstd; 6189695a8586SSepherosa Ziehau struct globaldata *gd = mycpu; 6190695a8586SSepherosa Ziehau 6191695a8586SSepherosa Ziehau crit_enter_gd(gd); 6192695a8586SSepherosa Ziehau 6193695a8586SSepherosa Ziehau std->bnx_rx_std_stop = 1; 6194695a8586SSepherosa Ziehau cpu_sfence(); 6195695a8586SSepherosa Ziehau 6196695a8586SSepherosa Ziehau KKASSERT(std->bnx_rx_std_ithread.td_gd == gd); 6197695a8586SSepherosa Ziehau lwkt_schedule(&std->bnx_rx_std_ithread); 6198695a8586SSepherosa Ziehau 6199695a8586SSepherosa Ziehau crit_exit_gd(gd); 6200695a8586SSepherosa Ziehau } 6201695a8586SSepherosa Ziehau 6202695a8586SSepherosa Ziehau static void 6203695a8586SSepherosa Ziehau bnx_serialize_skipmain(struct bnx_softc *sc) 6204695a8586SSepherosa Ziehau { 6205695a8586SSepherosa Ziehau lwkt_serialize_array_enter(sc->bnx_serialize, 6206695a8586SSepherosa Ziehau sc->bnx_serialize_cnt, 1); 6207695a8586SSepherosa Ziehau } 6208695a8586SSepherosa Ziehau 6209695a8586SSepherosa Ziehau static void 6210695a8586SSepherosa Ziehau bnx_deserialize_skipmain(struct bnx_softc *sc) 6211695a8586SSepherosa Ziehau { 6212695a8586SSepherosa Ziehau lwkt_serialize_array_exit(sc->bnx_serialize, 6213695a8586SSepherosa Ziehau sc->bnx_serialize_cnt, 1); 6214695a8586SSepherosa Ziehau } 6215695a8586SSepherosa Ziehau 6216695a8586SSepherosa Ziehau static void 6217695a8586SSepherosa Ziehau bnx_rx_std_refill_sched(struct bnx_rx_ret_ring *ret, 6218695a8586SSepherosa Ziehau struct bnx_rx_std_ring *std) 6219695a8586SSepherosa Ziehau { 6220695a8586SSepherosa Ziehau struct globaldata *gd = mycpu; 6221695a8586SSepherosa Ziehau 6222695a8586SSepherosa Ziehau ret->bnx_rx_cnt = 0; 6223695a8586SSepherosa Ziehau cpu_sfence(); 6224695a8586SSepherosa Ziehau 6225695a8586SSepherosa Ziehau crit_enter_gd(gd); 6226695a8586SSepherosa Ziehau 6227695a8586SSepherosa Ziehau atomic_set_int(&std->bnx_rx_std_refill, ret->bnx_rx_mask); 6228695a8586SSepherosa Ziehau cpu_sfence(); 6229695a8586SSepherosa Ziehau if (atomic_poll_acquire_int(&std->bnx_rx_std_running)) { 6230695a8586SSepherosa Ziehau if (std->bnx_rx_std_ithread.td_gd == gd) { 6231695a8586SSepherosa Ziehau lwkt_schedule(&std->bnx_rx_std_ithread); 6232695a8586SSepherosa Ziehau } else { 6233695a8586SSepherosa Ziehau lwkt_send_ipiq( 6234695a8586SSepherosa Ziehau std->bnx_rx_std_ithread.td_gd, 6235695a8586SSepherosa Ziehau bnx_rx_std_refill_sched_ipi, ret); 6236695a8586SSepherosa Ziehau } 6237695a8586SSepherosa Ziehau } 6238695a8586SSepherosa Ziehau 6239695a8586SSepherosa Ziehau crit_exit_gd(gd); 6240695a8586SSepherosa Ziehau } 6241b19ddf7eSSepherosa Ziehau 6242b19ddf7eSSepherosa Ziehau static struct pktinfo * 6243b19ddf7eSSepherosa Ziehau bnx_rss_info(struct pktinfo *pi, const struct bge_rx_bd *cur_rx) 6244b19ddf7eSSepherosa Ziehau { 6245b19ddf7eSSepherosa Ziehau /* Don't pick up IPv6 packet */ 6246b19ddf7eSSepherosa Ziehau if (cur_rx->bge_flags & BGE_RXBDFLAG_IPV6) 6247b19ddf7eSSepherosa Ziehau return NULL; 6248b19ddf7eSSepherosa Ziehau 6249b19ddf7eSSepherosa Ziehau /* Don't pick up IP packet w/o IP checksum */ 6250b19ddf7eSSepherosa Ziehau if ((cur_rx->bge_flags & BGE_RXBDFLAG_IP_CSUM) == 0 || 6251b19ddf7eSSepherosa Ziehau (cur_rx->bge_error_flag & BGE_RXERRFLAG_IP_CSUM_NOK)) 6252b19ddf7eSSepherosa Ziehau return NULL; 6253b19ddf7eSSepherosa Ziehau 6254b19ddf7eSSepherosa Ziehau /* Don't pick up IP packet w/o TCP/UDP checksum */ 6255b19ddf7eSSepherosa Ziehau if ((cur_rx->bge_flags & BGE_RXBDFLAG_TCP_UDP_CSUM) == 0) 6256b19ddf7eSSepherosa Ziehau return NULL; 6257b19ddf7eSSepherosa Ziehau 6258b19ddf7eSSepherosa Ziehau /* May be IP fragment */ 6259b19ddf7eSSepherosa Ziehau if (cur_rx->bge_tcp_udp_csum != 0xffff) 6260b19ddf7eSSepherosa Ziehau return NULL; 6261b19ddf7eSSepherosa Ziehau 6262b19ddf7eSSepherosa Ziehau if (cur_rx->bge_flags & BGE_RXBDFLAG_TCP_UDP_IS_TCP) 6263b19ddf7eSSepherosa Ziehau pi->pi_l3proto = IPPROTO_TCP; 6264b19ddf7eSSepherosa Ziehau else 6265b19ddf7eSSepherosa Ziehau pi->pi_l3proto = IPPROTO_UDP; 6266b19ddf7eSSepherosa Ziehau pi->pi_netisr = NETISR_IP; 6267b19ddf7eSSepherosa Ziehau pi->pi_flags = 0; 6268b19ddf7eSSepherosa Ziehau 6269b19ddf7eSSepherosa Ziehau return pi; 6270b19ddf7eSSepherosa Ziehau } 62714aa71e73SSepherosa Ziehau 62724aa71e73SSepherosa Ziehau static void 62734aa71e73SSepherosa Ziehau bnx_sig_pre_reset(struct bnx_softc *sc, int type) 62744aa71e73SSepherosa Ziehau { 62754aa71e73SSepherosa Ziehau if (type == BNX_RESET_START || type == BNX_RESET_SUSPEND) 62764aa71e73SSepherosa Ziehau bnx_ape_driver_state_change(sc, type); 62774aa71e73SSepherosa Ziehau } 62784aa71e73SSepherosa Ziehau 62794aa71e73SSepherosa Ziehau static void 62804aa71e73SSepherosa Ziehau bnx_sig_post_reset(struct bnx_softc *sc, int type) 62814aa71e73SSepherosa Ziehau { 62824aa71e73SSepherosa Ziehau if (type == BNX_RESET_SHUTDOWN) 62834aa71e73SSepherosa Ziehau bnx_ape_driver_state_change(sc, type); 62849f5082d5SSepherosa Ziehau } 62859f5082d5SSepherosa Ziehau 62869f5082d5SSepherosa Ziehau /* 62879f5082d5SSepherosa Ziehau * Clear all stale locks and select the lock for this driver instance. 62889f5082d5SSepherosa Ziehau */ 62899f5082d5SSepherosa Ziehau static void 62909f5082d5SSepherosa Ziehau bnx_ape_lock_init(struct bnx_softc *sc) 62919f5082d5SSepherosa Ziehau { 62929f5082d5SSepherosa Ziehau uint32_t bit, regbase; 62939f5082d5SSepherosa Ziehau int i; 62949f5082d5SSepherosa Ziehau 62959f5082d5SSepherosa Ziehau regbase = BGE_APE_PER_LOCK_GRANT; 62969f5082d5SSepherosa Ziehau 62979f5082d5SSepherosa Ziehau /* Clear any stale locks. */ 62989f5082d5SSepherosa Ziehau for (i = BGE_APE_LOCK_PHY0; i <= BGE_APE_LOCK_GPIO; i++) { 62999f5082d5SSepherosa Ziehau switch (i) { 63009f5082d5SSepherosa Ziehau case BGE_APE_LOCK_PHY0: 63019f5082d5SSepherosa Ziehau case BGE_APE_LOCK_PHY1: 63029f5082d5SSepherosa Ziehau case BGE_APE_LOCK_PHY2: 63039f5082d5SSepherosa Ziehau case BGE_APE_LOCK_PHY3: 63049f5082d5SSepherosa Ziehau bit = BGE_APE_LOCK_GRANT_DRIVER0; 63059f5082d5SSepherosa Ziehau break; 63069f5082d5SSepherosa Ziehau 63079f5082d5SSepherosa Ziehau default: 63089f5082d5SSepherosa Ziehau if (sc->bnx_func_addr == 0) 63099f5082d5SSepherosa Ziehau bit = BGE_APE_LOCK_GRANT_DRIVER0; 63109f5082d5SSepherosa Ziehau else 63119f5082d5SSepherosa Ziehau bit = 1 << sc->bnx_func_addr; 63129f5082d5SSepherosa Ziehau break; 63139f5082d5SSepherosa Ziehau } 63149f5082d5SSepherosa Ziehau APE_WRITE_4(sc, regbase + 4 * i, bit); 63159f5082d5SSepherosa Ziehau } 63169f5082d5SSepherosa Ziehau 63179f5082d5SSepherosa Ziehau /* Select the PHY lock based on the device's function number. */ 63189f5082d5SSepherosa Ziehau switch (sc->bnx_func_addr) { 63199f5082d5SSepherosa Ziehau case 0: 63209f5082d5SSepherosa Ziehau sc->bnx_phy_ape_lock = BGE_APE_LOCK_PHY0; 63219f5082d5SSepherosa Ziehau break; 63229f5082d5SSepherosa Ziehau 63239f5082d5SSepherosa Ziehau case 1: 63249f5082d5SSepherosa Ziehau sc->bnx_phy_ape_lock = BGE_APE_LOCK_PHY1; 63259f5082d5SSepherosa Ziehau break; 63269f5082d5SSepherosa Ziehau 63279f5082d5SSepherosa Ziehau case 2: 63289f5082d5SSepherosa Ziehau sc->bnx_phy_ape_lock = BGE_APE_LOCK_PHY2; 63299f5082d5SSepherosa Ziehau break; 63309f5082d5SSepherosa Ziehau 63319f5082d5SSepherosa Ziehau case 3: 63329f5082d5SSepherosa Ziehau sc->bnx_phy_ape_lock = BGE_APE_LOCK_PHY3; 63339f5082d5SSepherosa Ziehau break; 63349f5082d5SSepherosa Ziehau 63359f5082d5SSepherosa Ziehau default: 63369f5082d5SSepherosa Ziehau device_printf(sc->bnx_dev, 63379f5082d5SSepherosa Ziehau "PHY lock not supported on this function\n"); 63389f5082d5SSepherosa Ziehau break; 63399f5082d5SSepherosa Ziehau } 63409f5082d5SSepherosa Ziehau } 63419f5082d5SSepherosa Ziehau 63429f5082d5SSepherosa Ziehau /* 63439f5082d5SSepherosa Ziehau * Check for APE firmware, set flags, and print version info. 63449f5082d5SSepherosa Ziehau */ 63459f5082d5SSepherosa Ziehau static void 63469f5082d5SSepherosa Ziehau bnx_ape_read_fw_ver(struct bnx_softc *sc) 63479f5082d5SSepherosa Ziehau { 63489f5082d5SSepherosa Ziehau const char *fwtype; 63499f5082d5SSepherosa Ziehau uint32_t apedata, features; 63509f5082d5SSepherosa Ziehau 63519f5082d5SSepherosa Ziehau /* Check for a valid APE signature in shared memory. */ 63529f5082d5SSepherosa Ziehau apedata = APE_READ_4(sc, BGE_APE_SEG_SIG); 63539f5082d5SSepherosa Ziehau if (apedata != BGE_APE_SEG_SIG_MAGIC) { 63549f5082d5SSepherosa Ziehau device_printf(sc->bnx_dev, "no APE signature\n"); 63559f5082d5SSepherosa Ziehau sc->bnx_mfw_flags &= ~BNX_MFW_ON_APE; 63569f5082d5SSepherosa Ziehau return; 63579f5082d5SSepherosa Ziehau } 63589f5082d5SSepherosa Ziehau 63599f5082d5SSepherosa Ziehau /* Check if APE firmware is running. */ 63609f5082d5SSepherosa Ziehau apedata = APE_READ_4(sc, BGE_APE_FW_STATUS); 63619f5082d5SSepherosa Ziehau if ((apedata & BGE_APE_FW_STATUS_READY) == 0) { 63629f5082d5SSepherosa Ziehau device_printf(sc->bnx_dev, "APE signature found " 63639f5082d5SSepherosa Ziehau "but FW status not ready! 0x%08x\n", apedata); 63649f5082d5SSepherosa Ziehau return; 63659f5082d5SSepherosa Ziehau } 63669f5082d5SSepherosa Ziehau 63679f5082d5SSepherosa Ziehau sc->bnx_mfw_flags |= BNX_MFW_ON_APE; 63689f5082d5SSepherosa Ziehau 63699f5082d5SSepherosa Ziehau /* Fetch the APE firwmare type and version. */ 63709f5082d5SSepherosa Ziehau apedata = APE_READ_4(sc, BGE_APE_FW_VERSION); 63719f5082d5SSepherosa Ziehau features = APE_READ_4(sc, BGE_APE_FW_FEATURES); 63729f5082d5SSepherosa Ziehau if (features & BGE_APE_FW_FEATURE_NCSI) { 63739f5082d5SSepherosa Ziehau sc->bnx_mfw_flags |= BNX_MFW_TYPE_NCSI; 63749f5082d5SSepherosa Ziehau fwtype = "NCSI"; 63759f5082d5SSepherosa Ziehau } else if (features & BGE_APE_FW_FEATURE_DASH) { 63769f5082d5SSepherosa Ziehau sc->bnx_mfw_flags |= BNX_MFW_TYPE_DASH; 63779f5082d5SSepherosa Ziehau fwtype = "DASH"; 63789f5082d5SSepherosa Ziehau } else { 63799f5082d5SSepherosa Ziehau fwtype = "UNKN"; 63809f5082d5SSepherosa Ziehau } 63819f5082d5SSepherosa Ziehau 63829f5082d5SSepherosa Ziehau /* Print the APE firmware version. */ 63839f5082d5SSepherosa Ziehau device_printf(sc->bnx_dev, "APE FW version: %s v%d.%d.%d.%d\n", 63849f5082d5SSepherosa Ziehau fwtype, 63859f5082d5SSepherosa Ziehau (apedata & BGE_APE_FW_VERSION_MAJMSK) >> BGE_APE_FW_VERSION_MAJSFT, 63869f5082d5SSepherosa Ziehau (apedata & BGE_APE_FW_VERSION_MINMSK) >> BGE_APE_FW_VERSION_MINSFT, 63879f5082d5SSepherosa Ziehau (apedata & BGE_APE_FW_VERSION_REVMSK) >> BGE_APE_FW_VERSION_REVSFT, 63889f5082d5SSepherosa Ziehau (apedata & BGE_APE_FW_VERSION_BLDMSK)); 63899f5082d5SSepherosa Ziehau } 63909f5082d5SSepherosa Ziehau 63919f5082d5SSepherosa Ziehau static int 63929f5082d5SSepherosa Ziehau bnx_ape_lock(struct bnx_softc *sc, int locknum) 63939f5082d5SSepherosa Ziehau { 63949f5082d5SSepherosa Ziehau uint32_t bit, gnt, req, status; 63959f5082d5SSepherosa Ziehau int i, off; 63969f5082d5SSepherosa Ziehau 63979f5082d5SSepherosa Ziehau if ((sc->bnx_mfw_flags & BNX_MFW_ON_APE) == 0) 63989f5082d5SSepherosa Ziehau return 0; 63999f5082d5SSepherosa Ziehau 64009f5082d5SSepherosa Ziehau /* Lock request/grant registers have different bases. */ 64019f5082d5SSepherosa Ziehau req = BGE_APE_PER_LOCK_REQ; 64029f5082d5SSepherosa Ziehau gnt = BGE_APE_PER_LOCK_GRANT; 64039f5082d5SSepherosa Ziehau 64049f5082d5SSepherosa Ziehau off = 4 * locknum; 64059f5082d5SSepherosa Ziehau 64069f5082d5SSepherosa Ziehau switch (locknum) { 64079f5082d5SSepherosa Ziehau case BGE_APE_LOCK_GPIO: 64089f5082d5SSepherosa Ziehau /* Lock required when using GPIO. */ 64099f5082d5SSepherosa Ziehau if (sc->bnx_func_addr == 0) 64109f5082d5SSepherosa Ziehau bit = BGE_APE_LOCK_REQ_DRIVER0; 64119f5082d5SSepherosa Ziehau else 64129f5082d5SSepherosa Ziehau bit = 1 << sc->bnx_func_addr; 64139f5082d5SSepherosa Ziehau break; 64149f5082d5SSepherosa Ziehau 64159f5082d5SSepherosa Ziehau case BGE_APE_LOCK_GRC: 64169f5082d5SSepherosa Ziehau /* Lock required to reset the device. */ 64179f5082d5SSepherosa Ziehau if (sc->bnx_func_addr == 0) 64189f5082d5SSepherosa Ziehau bit = BGE_APE_LOCK_REQ_DRIVER0; 64199f5082d5SSepherosa Ziehau else 64209f5082d5SSepherosa Ziehau bit = 1 << sc->bnx_func_addr; 64219f5082d5SSepherosa Ziehau break; 64229f5082d5SSepherosa Ziehau 64239f5082d5SSepherosa Ziehau case BGE_APE_LOCK_MEM: 64249f5082d5SSepherosa Ziehau /* Lock required when accessing certain APE memory. */ 64259f5082d5SSepherosa Ziehau if (sc->bnx_func_addr == 0) 64269f5082d5SSepherosa Ziehau bit = BGE_APE_LOCK_REQ_DRIVER0; 64279f5082d5SSepherosa Ziehau else 64289f5082d5SSepherosa Ziehau bit = 1 << sc->bnx_func_addr; 64299f5082d5SSepherosa Ziehau break; 64309f5082d5SSepherosa Ziehau 64319f5082d5SSepherosa Ziehau case BGE_APE_LOCK_PHY0: 64329f5082d5SSepherosa Ziehau case BGE_APE_LOCK_PHY1: 64339f5082d5SSepherosa Ziehau case BGE_APE_LOCK_PHY2: 64349f5082d5SSepherosa Ziehau case BGE_APE_LOCK_PHY3: 64359f5082d5SSepherosa Ziehau /* Lock required when accessing PHYs. */ 64369f5082d5SSepherosa Ziehau bit = BGE_APE_LOCK_REQ_DRIVER0; 64379f5082d5SSepherosa Ziehau break; 64389f5082d5SSepherosa Ziehau 64399f5082d5SSepherosa Ziehau default: 64409f5082d5SSepherosa Ziehau return EINVAL; 64419f5082d5SSepherosa Ziehau } 64429f5082d5SSepherosa Ziehau 64439f5082d5SSepherosa Ziehau /* Request a lock. */ 64449f5082d5SSepherosa Ziehau APE_WRITE_4(sc, req + off, bit); 64459f5082d5SSepherosa Ziehau 64469f5082d5SSepherosa Ziehau /* Wait up to 1 second to acquire lock. */ 64479f5082d5SSepherosa Ziehau for (i = 0; i < 20000; i++) { 64489f5082d5SSepherosa Ziehau status = APE_READ_4(sc, gnt + off); 64499f5082d5SSepherosa Ziehau if (status == bit) 64509f5082d5SSepherosa Ziehau break; 64519f5082d5SSepherosa Ziehau DELAY(50); 64529f5082d5SSepherosa Ziehau } 64539f5082d5SSepherosa Ziehau 64549f5082d5SSepherosa Ziehau /* Handle any errors. */ 64559f5082d5SSepherosa Ziehau if (status != bit) { 64569f5082d5SSepherosa Ziehau if_printf(&sc->arpcom.ac_if, "APE lock %d request failed! " 64579f5082d5SSepherosa Ziehau "request = 0x%04x[0x%04x], status = 0x%04x[0x%04x]\n", 64589f5082d5SSepherosa Ziehau locknum, req + off, bit & 0xFFFF, gnt + off, 64599f5082d5SSepherosa Ziehau status & 0xFFFF); 64609f5082d5SSepherosa Ziehau /* Revoke the lock request. */ 64619f5082d5SSepherosa Ziehau APE_WRITE_4(sc, gnt + off, bit); 64629f5082d5SSepherosa Ziehau return EBUSY; 64639f5082d5SSepherosa Ziehau } 64649f5082d5SSepherosa Ziehau 64659f5082d5SSepherosa Ziehau return 0; 64669f5082d5SSepherosa Ziehau } 64679f5082d5SSepherosa Ziehau 64689f5082d5SSepherosa Ziehau static void 64699f5082d5SSepherosa Ziehau bnx_ape_unlock(struct bnx_softc *sc, int locknum) 64709f5082d5SSepherosa Ziehau { 64719f5082d5SSepherosa Ziehau uint32_t bit, gnt; 64729f5082d5SSepherosa Ziehau int off; 64739f5082d5SSepherosa Ziehau 64749f5082d5SSepherosa Ziehau if ((sc->bnx_mfw_flags & BNX_MFW_ON_APE) == 0) 64759f5082d5SSepherosa Ziehau return; 64769f5082d5SSepherosa Ziehau 64779f5082d5SSepherosa Ziehau gnt = BGE_APE_PER_LOCK_GRANT; 64789f5082d5SSepherosa Ziehau 64799f5082d5SSepherosa Ziehau off = 4 * locknum; 64809f5082d5SSepherosa Ziehau 64819f5082d5SSepherosa Ziehau switch (locknum) { 64829f5082d5SSepherosa Ziehau case BGE_APE_LOCK_GPIO: 64839f5082d5SSepherosa Ziehau if (sc->bnx_func_addr == 0) 64849f5082d5SSepherosa Ziehau bit = BGE_APE_LOCK_GRANT_DRIVER0; 64859f5082d5SSepherosa Ziehau else 64869f5082d5SSepherosa Ziehau bit = 1 << sc->bnx_func_addr; 64879f5082d5SSepherosa Ziehau break; 64889f5082d5SSepherosa Ziehau 64899f5082d5SSepherosa Ziehau case BGE_APE_LOCK_GRC: 64909f5082d5SSepherosa Ziehau if (sc->bnx_func_addr == 0) 64919f5082d5SSepherosa Ziehau bit = BGE_APE_LOCK_GRANT_DRIVER0; 64929f5082d5SSepherosa Ziehau else 64939f5082d5SSepherosa Ziehau bit = 1 << sc->bnx_func_addr; 64949f5082d5SSepherosa Ziehau break; 64959f5082d5SSepherosa Ziehau 64969f5082d5SSepherosa Ziehau case BGE_APE_LOCK_MEM: 64979f5082d5SSepherosa Ziehau if (sc->bnx_func_addr == 0) 64989f5082d5SSepherosa Ziehau bit = BGE_APE_LOCK_GRANT_DRIVER0; 64999f5082d5SSepherosa Ziehau else 65009f5082d5SSepherosa Ziehau bit = 1 << sc->bnx_func_addr; 65019f5082d5SSepherosa Ziehau break; 65029f5082d5SSepherosa Ziehau 65039f5082d5SSepherosa Ziehau case BGE_APE_LOCK_PHY0: 65049f5082d5SSepherosa Ziehau case BGE_APE_LOCK_PHY1: 65059f5082d5SSepherosa Ziehau case BGE_APE_LOCK_PHY2: 65069f5082d5SSepherosa Ziehau case BGE_APE_LOCK_PHY3: 65079f5082d5SSepherosa Ziehau bit = BGE_APE_LOCK_GRANT_DRIVER0; 65089f5082d5SSepherosa Ziehau break; 65099f5082d5SSepherosa Ziehau 65109f5082d5SSepherosa Ziehau default: 65119f5082d5SSepherosa Ziehau return; 65129f5082d5SSepherosa Ziehau } 65139f5082d5SSepherosa Ziehau 65149f5082d5SSepherosa Ziehau APE_WRITE_4(sc, gnt + off, bit); 65159f5082d5SSepherosa Ziehau } 65169f5082d5SSepherosa Ziehau 65179f5082d5SSepherosa Ziehau /* 65189f5082d5SSepherosa Ziehau * Send an event to the APE firmware. 65199f5082d5SSepherosa Ziehau */ 65209f5082d5SSepherosa Ziehau static void 65219f5082d5SSepherosa Ziehau bnx_ape_send_event(struct bnx_softc *sc, uint32_t event) 65229f5082d5SSepherosa Ziehau { 65239f5082d5SSepherosa Ziehau uint32_t apedata; 65249f5082d5SSepherosa Ziehau int i; 65259f5082d5SSepherosa Ziehau 65269f5082d5SSepherosa Ziehau /* NCSI does not support APE events. */ 65279f5082d5SSepherosa Ziehau if ((sc->bnx_mfw_flags & BNX_MFW_ON_APE) == 0) 65289f5082d5SSepherosa Ziehau return; 65299f5082d5SSepherosa Ziehau 65309f5082d5SSepherosa Ziehau /* Wait up to 1ms for APE to service previous event. */ 65319f5082d5SSepherosa Ziehau for (i = 10; i > 0; i--) { 65329f5082d5SSepherosa Ziehau if (bnx_ape_lock(sc, BGE_APE_LOCK_MEM) != 0) 65339f5082d5SSepherosa Ziehau break; 65349f5082d5SSepherosa Ziehau apedata = APE_READ_4(sc, BGE_APE_EVENT_STATUS); 65359f5082d5SSepherosa Ziehau if ((apedata & BGE_APE_EVENT_STATUS_EVENT_PENDING) == 0) { 65369f5082d5SSepherosa Ziehau APE_WRITE_4(sc, BGE_APE_EVENT_STATUS, event | 65379f5082d5SSepherosa Ziehau BGE_APE_EVENT_STATUS_EVENT_PENDING); 65389f5082d5SSepherosa Ziehau bnx_ape_unlock(sc, BGE_APE_LOCK_MEM); 65399f5082d5SSepherosa Ziehau APE_WRITE_4(sc, BGE_APE_EVENT, BGE_APE_EVENT_1); 65409f5082d5SSepherosa Ziehau break; 65419f5082d5SSepherosa Ziehau } 65429f5082d5SSepherosa Ziehau bnx_ape_unlock(sc, BGE_APE_LOCK_MEM); 65439f5082d5SSepherosa Ziehau DELAY(100); 65449f5082d5SSepherosa Ziehau } 65459f5082d5SSepherosa Ziehau if (i == 0) { 65469f5082d5SSepherosa Ziehau if_printf(&sc->arpcom.ac_if, 65479f5082d5SSepherosa Ziehau "APE event 0x%08x send timed out\n", event); 65489f5082d5SSepherosa Ziehau } 65499f5082d5SSepherosa Ziehau } 65509f5082d5SSepherosa Ziehau 65519f5082d5SSepherosa Ziehau static void 65529f5082d5SSepherosa Ziehau bnx_ape_driver_state_change(struct bnx_softc *sc, int kind) 65539f5082d5SSepherosa Ziehau { 65549f5082d5SSepherosa Ziehau uint32_t apedata, event; 65559f5082d5SSepherosa Ziehau 65569f5082d5SSepherosa Ziehau if ((sc->bnx_mfw_flags & BNX_MFW_ON_APE) == 0) 65579f5082d5SSepherosa Ziehau return; 65589f5082d5SSepherosa Ziehau 65599f5082d5SSepherosa Ziehau switch (kind) { 65609f5082d5SSepherosa Ziehau case BNX_RESET_START: 65619f5082d5SSepherosa Ziehau /* If this is the first load, clear the load counter. */ 65629f5082d5SSepherosa Ziehau apedata = APE_READ_4(sc, BGE_APE_HOST_SEG_SIG); 65639f5082d5SSepherosa Ziehau if (apedata != BGE_APE_HOST_SEG_SIG_MAGIC) { 65649f5082d5SSepherosa Ziehau APE_WRITE_4(sc, BGE_APE_HOST_INIT_COUNT, 0); 65659f5082d5SSepherosa Ziehau } else { 65669f5082d5SSepherosa Ziehau apedata = APE_READ_4(sc, BGE_APE_HOST_INIT_COUNT); 65679f5082d5SSepherosa Ziehau APE_WRITE_4(sc, BGE_APE_HOST_INIT_COUNT, ++apedata); 65689f5082d5SSepherosa Ziehau } 65699f5082d5SSepherosa Ziehau APE_WRITE_4(sc, BGE_APE_HOST_SEG_SIG, 65709f5082d5SSepherosa Ziehau BGE_APE_HOST_SEG_SIG_MAGIC); 65719f5082d5SSepherosa Ziehau APE_WRITE_4(sc, BGE_APE_HOST_SEG_LEN, 65729f5082d5SSepherosa Ziehau BGE_APE_HOST_SEG_LEN_MAGIC); 65739f5082d5SSepherosa Ziehau 65749f5082d5SSepherosa Ziehau /* Add some version info if bnx(4) supports it. */ 65759f5082d5SSepherosa Ziehau APE_WRITE_4(sc, BGE_APE_HOST_DRIVER_ID, 65769f5082d5SSepherosa Ziehau BGE_APE_HOST_DRIVER_ID_MAGIC(1, 0)); 65779f5082d5SSepherosa Ziehau APE_WRITE_4(sc, BGE_APE_HOST_BEHAVIOR, 65789f5082d5SSepherosa Ziehau BGE_APE_HOST_BEHAV_NO_PHYLOCK); 65799f5082d5SSepherosa Ziehau APE_WRITE_4(sc, BGE_APE_HOST_HEARTBEAT_INT_MS, 65809f5082d5SSepherosa Ziehau BGE_APE_HOST_HEARTBEAT_INT_DISABLE); 65819f5082d5SSepherosa Ziehau APE_WRITE_4(sc, BGE_APE_HOST_DRVR_STATE, 65829f5082d5SSepherosa Ziehau BGE_APE_HOST_DRVR_STATE_START); 65839f5082d5SSepherosa Ziehau event = BGE_APE_EVENT_STATUS_STATE_START; 65849f5082d5SSepherosa Ziehau break; 65859f5082d5SSepherosa Ziehau 65869f5082d5SSepherosa Ziehau case BNX_RESET_SHUTDOWN: 65879f5082d5SSepherosa Ziehau APE_WRITE_4(sc, BGE_APE_HOST_DRVR_STATE, 65889f5082d5SSepherosa Ziehau BGE_APE_HOST_DRVR_STATE_UNLOAD); 65899f5082d5SSepherosa Ziehau event = BGE_APE_EVENT_STATUS_STATE_UNLOAD; 65909f5082d5SSepherosa Ziehau break; 65919f5082d5SSepherosa Ziehau 65929f5082d5SSepherosa Ziehau case BNX_RESET_SUSPEND: 65939f5082d5SSepherosa Ziehau event = BGE_APE_EVENT_STATUS_STATE_SUSPEND; 65949f5082d5SSepherosa Ziehau break; 65959f5082d5SSepherosa Ziehau 65969f5082d5SSepherosa Ziehau default: 65979f5082d5SSepherosa Ziehau return; 65989f5082d5SSepherosa Ziehau } 65999f5082d5SSepherosa Ziehau 66009f5082d5SSepherosa Ziehau bnx_ape_send_event(sc, event | BGE_APE_EVENT_STATUS_DRIVER_EVNT | 66019f5082d5SSepherosa Ziehau BGE_APE_EVENT_STATUS_STATE_CHNGE); 66024aa71e73SSepherosa Ziehau } 6603