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> 656c8d8eccSSepherosa Ziehau #include <net/vlan/if_vlan_var.h> 666c8d8eccSSepherosa Ziehau #include <net/vlan/if_vlan_ether.h> 676c8d8eccSSepherosa Ziehau 686c8d8eccSSepherosa Ziehau #include <dev/netif/mii_layer/mii.h> 696c8d8eccSSepherosa Ziehau #include <dev/netif/mii_layer/miivar.h> 706c8d8eccSSepherosa Ziehau #include <dev/netif/mii_layer/brgphyreg.h> 716c8d8eccSSepherosa Ziehau 726c8d8eccSSepherosa Ziehau #include <bus/pci/pcidevs.h> 736c8d8eccSSepherosa Ziehau #include <bus/pci/pcireg.h> 746c8d8eccSSepherosa Ziehau #include <bus/pci/pcivar.h> 756c8d8eccSSepherosa Ziehau 766c8d8eccSSepherosa Ziehau #include <dev/netif/bge/if_bgereg.h> 776c8d8eccSSepherosa Ziehau #include <dev/netif/bnx/if_bnxvar.h> 786c8d8eccSSepherosa Ziehau 796c8d8eccSSepherosa Ziehau /* "device miibus" required. See GENERIC if you get errors here. */ 806c8d8eccSSepherosa Ziehau #include "miibus_if.h" 816c8d8eccSSepherosa Ziehau 823b18363fSSepherosa Ziehau #define BNX_CSUM_FEATURES (CSUM_IP | CSUM_TCP | CSUM_UDP) 836c8d8eccSSepherosa Ziehau 84df9ccc98SSepherosa Ziehau #define BNX_INTR_CKINTVL ((10 * hz) / 1000) /* 10ms */ 85df9ccc98SSepherosa Ziehau 866c8d8eccSSepherosa Ziehau static const struct bnx_type { 876c8d8eccSSepherosa Ziehau uint16_t bnx_vid; 886c8d8eccSSepherosa Ziehau uint16_t bnx_did; 896c8d8eccSSepherosa Ziehau char *bnx_name; 906c8d8eccSSepherosa Ziehau } bnx_devs[] = { 916c8d8eccSSepherosa Ziehau { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM5717, 926c8d8eccSSepherosa Ziehau "Broadcom BCM5717 Gigabit Ethernet" }, 93d79f5d8fSSepherosa Ziehau { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM5717C, 94d79f5d8fSSepherosa Ziehau "Broadcom BCM5717C Gigabit Ethernet" }, 956c8d8eccSSepherosa Ziehau { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM5718, 966c8d8eccSSepherosa Ziehau "Broadcom BCM5718 Gigabit Ethernet" }, 976c8d8eccSSepherosa Ziehau { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM5719, 986c8d8eccSSepherosa Ziehau "Broadcom BCM5719 Gigabit Ethernet" }, 996c8d8eccSSepherosa Ziehau { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM5720_ALT, 1006c8d8eccSSepherosa Ziehau "Broadcom BCM5720 Gigabit Ethernet" }, 1016c8d8eccSSepherosa Ziehau 102b96cbbb6SSepherosa Ziehau { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM5725, 103b96cbbb6SSepherosa Ziehau "Broadcom BCM5725 Gigabit Ethernet" }, 104b96cbbb6SSepherosa Ziehau { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM5727, 105b96cbbb6SSepherosa Ziehau "Broadcom BCM5727 Gigabit Ethernet" }, 106b96cbbb6SSepherosa Ziehau { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM5762, 107b96cbbb6SSepherosa Ziehau "Broadcom BCM5762 Gigabit Ethernet" }, 108b96cbbb6SSepherosa Ziehau 1096c8d8eccSSepherosa Ziehau { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM57761, 1106c8d8eccSSepherosa Ziehau "Broadcom BCM57761 Gigabit Ethernet" }, 11132ff3c80SSepherosa Ziehau { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM57762, 11232ff3c80SSepherosa Ziehau "Broadcom BCM57762 Gigabit Ethernet" }, 1136c8d8eccSSepherosa Ziehau { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM57765, 1146c8d8eccSSepherosa Ziehau "Broadcom BCM57765 Gigabit Ethernet" }, 11532ff3c80SSepherosa Ziehau { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM57766, 11632ff3c80SSepherosa Ziehau "Broadcom BCM57766 Gigabit Ethernet" }, 11732ff3c80SSepherosa Ziehau { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM57781, 11832ff3c80SSepherosa Ziehau "Broadcom BCM57781 Gigabit Ethernet" }, 11932ff3c80SSepherosa Ziehau { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM57782, 12032ff3c80SSepherosa Ziehau "Broadcom BCM57782 Gigabit Ethernet" }, 1216c8d8eccSSepherosa Ziehau { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM57785, 1226c8d8eccSSepherosa Ziehau "Broadcom BCM57785 Gigabit Ethernet" }, 12332ff3c80SSepherosa Ziehau { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM57786, 12432ff3c80SSepherosa Ziehau "Broadcom BCM57786 Gigabit Ethernet" }, 12532ff3c80SSepherosa Ziehau { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM57791, 12632ff3c80SSepherosa Ziehau "Broadcom BCM57791 Fast Ethernet" }, 1276c8d8eccSSepherosa Ziehau { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM57795, 1286c8d8eccSSepherosa Ziehau "Broadcom BCM57795 Fast Ethernet" }, 1296c8d8eccSSepherosa Ziehau 1306c8d8eccSSepherosa Ziehau { 0, 0, NULL } 1316c8d8eccSSepherosa Ziehau }; 1326c8d8eccSSepherosa Ziehau 1331c9d03f6SSepherosa Ziehau static const int bnx_tx_mailbox[BNX_TX_RING_MAX] = { 1341c9d03f6SSepherosa Ziehau BGE_MBX_TX_HOST_PROD0_LO, 1351c9d03f6SSepherosa Ziehau BGE_MBX_TX_HOST_PROD0_HI, 1361c9d03f6SSepherosa Ziehau BGE_MBX_TX_HOST_PROD1_LO, 1371c9d03f6SSepherosa Ziehau BGE_MBX_TX_HOST_PROD1_HI 1381c9d03f6SSepherosa Ziehau }; 1391c9d03f6SSepherosa Ziehau 1406c8d8eccSSepherosa Ziehau #define BNX_IS_JUMBO_CAPABLE(sc) ((sc)->bnx_flags & BNX_FLAG_JUMBO) 1416c8d8eccSSepherosa Ziehau #define BNX_IS_5717_PLUS(sc) ((sc)->bnx_flags & BNX_FLAG_5717_PLUS) 142f368d0d9SSepherosa Ziehau #define BNX_IS_57765_PLUS(sc) ((sc)->bnx_flags & BNX_FLAG_57765_PLUS) 143f368d0d9SSepherosa Ziehau #define BNX_IS_57765_FAMILY(sc) \ 144f368d0d9SSepherosa Ziehau ((sc)->bnx_flags & BNX_FLAG_57765_FAMILY) 1456c8d8eccSSepherosa Ziehau 1466c8d8eccSSepherosa Ziehau typedef int (*bnx_eaddr_fcn_t)(struct bnx_softc *, uint8_t[]); 1476c8d8eccSSepherosa Ziehau 1486c8d8eccSSepherosa Ziehau static int bnx_probe(device_t); 1496c8d8eccSSepherosa Ziehau static int bnx_attach(device_t); 1506c8d8eccSSepherosa Ziehau static int bnx_detach(device_t); 1516c8d8eccSSepherosa Ziehau static void bnx_shutdown(device_t); 1526c8d8eccSSepherosa Ziehau static int bnx_suspend(device_t); 1536c8d8eccSSepherosa Ziehau static int bnx_resume(device_t); 1546c8d8eccSSepherosa Ziehau static int bnx_miibus_readreg(device_t, int, int); 1556c8d8eccSSepherosa Ziehau static int bnx_miibus_writereg(device_t, int, int, int); 1566c8d8eccSSepherosa Ziehau static void bnx_miibus_statchg(device_t); 1576c8d8eccSSepherosa Ziehau 15839a8d43aSSepherosa Ziehau #ifdef IFPOLL_ENABLE 15939a8d43aSSepherosa Ziehau static void bnx_npoll(struct ifnet *, struct ifpoll_info *); 1604fa38985SSepherosa Ziehau static void bnx_npoll_rx(struct ifnet *, void *, int); 1614fa38985SSepherosa Ziehau static void bnx_npoll_tx(struct ifnet *, void *, int); 1624fa38985SSepherosa Ziehau static void bnx_npoll_status(struct ifnet *); 1636c8d8eccSSepherosa Ziehau #endif 1646c8d8eccSSepherosa Ziehau static void bnx_intr_legacy(void *); 1656c8d8eccSSepherosa Ziehau static void bnx_msi(void *); 1666c8d8eccSSepherosa Ziehau static void bnx_msi_oneshot(void *); 1676c8d8eccSSepherosa Ziehau static void bnx_intr(struct bnx_softc *); 1686c8d8eccSSepherosa Ziehau static void bnx_enable_intr(struct bnx_softc *); 1696c8d8eccSSepherosa Ziehau static void bnx_disable_intr(struct bnx_softc *); 17033a04907SSepherosa Ziehau static void bnx_txeof(struct bnx_tx_ring *, uint16_t); 171beedf5beSSepherosa Ziehau static void bnx_rxeof(struct bnx_rx_ret_ring *, uint16_t, int); 1720c7da01dSSepherosa Ziehau static int bnx_alloc_intr(struct bnx_softc *); 1730c7da01dSSepherosa Ziehau static int bnx_setup_intr(struct bnx_softc *); 1740c7da01dSSepherosa Ziehau static void bnx_free_intr(struct bnx_softc *); 175f33ac8a4SSepherosa Ziehau static void bnx_teardown_intr(struct bnx_softc *, int); 176f33ac8a4SSepherosa Ziehau static void bnx_check_intr(void *); 177841cdf08SSepherosa Ziehau static void bnx_rx_std_refill_ithread(void *); 178841cdf08SSepherosa Ziehau static void bnx_rx_std_refill(void *, void *); 1796c8d8eccSSepherosa Ziehau 180f0a26983SSepherosa Ziehau static void bnx_start(struct ifnet *, struct ifaltq_subque *); 1816c8d8eccSSepherosa Ziehau static int bnx_ioctl(struct ifnet *, u_long, caddr_t, struct ucred *); 1826c8d8eccSSepherosa Ziehau static void bnx_init(void *); 1836c8d8eccSSepherosa Ziehau static void bnx_stop(struct bnx_softc *); 1843397dea6SSepherosa Ziehau static void bnx_watchdog(struct ifaltq_subque *); 1856c8d8eccSSepherosa Ziehau static int bnx_ifmedia_upd(struct ifnet *); 1866c8d8eccSSepherosa Ziehau static void bnx_ifmedia_sts(struct ifnet *, struct ifmediareq *); 1876c8d8eccSSepherosa Ziehau static void bnx_tick(void *); 188329f9016SSepherosa Ziehau static void bnx_serialize(struct ifnet *, enum ifnet_serialize); 189329f9016SSepherosa Ziehau static void bnx_deserialize(struct ifnet *, enum ifnet_serialize); 190329f9016SSepherosa Ziehau static int bnx_tryserialize(struct ifnet *, enum ifnet_serialize); 191329f9016SSepherosa Ziehau #ifdef INVARIANTS 192329f9016SSepherosa Ziehau static void bnx_serialize_assert(struct ifnet *, enum ifnet_serialize, 193329f9016SSepherosa Ziehau boolean_t); 194329f9016SSepherosa Ziehau #endif 1956c8d8eccSSepherosa Ziehau 1966c8d8eccSSepherosa Ziehau static int bnx_alloc_jumbo_mem(struct bnx_softc *); 1976c8d8eccSSepherosa Ziehau static void bnx_free_jumbo_mem(struct bnx_softc *); 1986c8d8eccSSepherosa Ziehau static struct bnx_jslot 1996c8d8eccSSepherosa Ziehau *bnx_jalloc(struct bnx_softc *); 2006c8d8eccSSepherosa Ziehau static void bnx_jfree(void *); 2016c8d8eccSSepherosa Ziehau static void bnx_jref(void *); 202beedf5beSSepherosa Ziehau static int bnx_newbuf_std(struct bnx_rx_ret_ring *, int, int); 2036c8d8eccSSepherosa Ziehau static int bnx_newbuf_jumbo(struct bnx_softc *, int, int); 204beedf5beSSepherosa Ziehau static void bnx_setup_rxdesc_std(struct bnx_rx_std_ring *, int); 2056c8d8eccSSepherosa Ziehau static void bnx_setup_rxdesc_jumbo(struct bnx_softc *, int); 206beedf5beSSepherosa Ziehau static int bnx_init_rx_ring_std(struct bnx_rx_std_ring *); 207beedf5beSSepherosa Ziehau static void bnx_free_rx_ring_std(struct bnx_rx_std_ring *); 2086c8d8eccSSepherosa Ziehau static int bnx_init_rx_ring_jumbo(struct bnx_softc *); 2096c8d8eccSSepherosa Ziehau static void bnx_free_rx_ring_jumbo(struct bnx_softc *); 21033a04907SSepherosa Ziehau static void bnx_free_tx_ring(struct bnx_tx_ring *); 21133a04907SSepherosa Ziehau static int bnx_init_tx_ring(struct bnx_tx_ring *); 21233a04907SSepherosa Ziehau static int bnx_create_tx_ring(struct bnx_tx_ring *); 21333a04907SSepherosa Ziehau static void bnx_destroy_tx_ring(struct bnx_tx_ring *); 214beedf5beSSepherosa Ziehau static int bnx_create_rx_ret_ring(struct bnx_rx_ret_ring *); 215beedf5beSSepherosa Ziehau static void bnx_destroy_rx_ret_ring(struct bnx_rx_ret_ring *); 216beedf5beSSepherosa Ziehau static int bnx_dma_alloc(device_t); 2176c8d8eccSSepherosa Ziehau static void bnx_dma_free(struct bnx_softc *); 2186c8d8eccSSepherosa Ziehau static int bnx_dma_block_alloc(struct bnx_softc *, bus_size_t, 2196c8d8eccSSepherosa Ziehau bus_dma_tag_t *, bus_dmamap_t *, void **, bus_addr_t *); 2206c8d8eccSSepherosa Ziehau static void bnx_dma_block_free(bus_dma_tag_t, bus_dmamap_t, void *); 2216c8d8eccSSepherosa Ziehau static struct mbuf * 2226c8d8eccSSepherosa Ziehau bnx_defrag_shortdma(struct mbuf *); 22333a04907SSepherosa Ziehau static int bnx_encap(struct bnx_tx_ring *, struct mbuf **, 224c9b7f592SSepherosa Ziehau uint32_t *, int *); 22533a04907SSepherosa Ziehau static int bnx_setup_tso(struct bnx_tx_ring *, struct mbuf **, 22666deb1c1SSepherosa Ziehau uint16_t *, uint16_t *); 227329f9016SSepherosa Ziehau static void bnx_setup_serialize(struct bnx_softc *); 2287dbaa833SSepherosa Ziehau static void bnx_set_tick_cpuid(struct bnx_softc *, boolean_t); 2296c8d8eccSSepherosa Ziehau 2306c8d8eccSSepherosa Ziehau static void bnx_reset(struct bnx_softc *); 2316c8d8eccSSepherosa Ziehau static int bnx_chipinit(struct bnx_softc *); 2326c8d8eccSSepherosa Ziehau static int bnx_blockinit(struct bnx_softc *); 2336c8d8eccSSepherosa Ziehau static void bnx_stop_block(struct bnx_softc *, bus_size_t, uint32_t); 2346c8d8eccSSepherosa Ziehau static void bnx_enable_msi(struct bnx_softc *sc); 2356c8d8eccSSepherosa Ziehau static void bnx_setmulti(struct bnx_softc *); 2366c8d8eccSSepherosa Ziehau static void bnx_setpromisc(struct bnx_softc *); 2376c8d8eccSSepherosa Ziehau static void bnx_stats_update_regs(struct bnx_softc *); 2386c8d8eccSSepherosa Ziehau static uint32_t bnx_dma_swap_options(struct bnx_softc *); 2396c8d8eccSSepherosa Ziehau 2406c8d8eccSSepherosa Ziehau static uint32_t bnx_readmem_ind(struct bnx_softc *, uint32_t); 2416c8d8eccSSepherosa Ziehau static void bnx_writemem_ind(struct bnx_softc *, uint32_t, uint32_t); 2426c8d8eccSSepherosa Ziehau #ifdef notdef 2436c8d8eccSSepherosa Ziehau static uint32_t bnx_readreg_ind(struct bnx_softc *, uint32_t); 2446c8d8eccSSepherosa Ziehau #endif 2456c8d8eccSSepherosa Ziehau static void bnx_writemem_direct(struct bnx_softc *, uint32_t, uint32_t); 2466c8d8eccSSepherosa Ziehau static void bnx_writembx(struct bnx_softc *, int, int); 2476c8d8eccSSepherosa Ziehau static int bnx_read_nvram(struct bnx_softc *, caddr_t, int, int); 2486c8d8eccSSepherosa Ziehau static uint8_t bnx_eeprom_getbyte(struct bnx_softc *, uint32_t, uint8_t *); 2496c8d8eccSSepherosa Ziehau static int bnx_read_eeprom(struct bnx_softc *, caddr_t, uint32_t, size_t); 2506c8d8eccSSepherosa Ziehau 2516c8d8eccSSepherosa Ziehau static void bnx_tbi_link_upd(struct bnx_softc *, uint32_t); 2526c8d8eccSSepherosa Ziehau static void bnx_copper_link_upd(struct bnx_softc *, uint32_t); 2536c8d8eccSSepherosa Ziehau static void bnx_autopoll_link_upd(struct bnx_softc *, uint32_t); 2546c8d8eccSSepherosa Ziehau static void bnx_link_poll(struct bnx_softc *); 2556c8d8eccSSepherosa Ziehau 2566c8d8eccSSepherosa Ziehau static int bnx_get_eaddr_mem(struct bnx_softc *, uint8_t[]); 2576c8d8eccSSepherosa Ziehau static int bnx_get_eaddr_nvram(struct bnx_softc *, uint8_t[]); 2586c8d8eccSSepherosa Ziehau static int bnx_get_eaddr_eeprom(struct bnx_softc *, uint8_t[]); 2596c8d8eccSSepherosa Ziehau static int bnx_get_eaddr(struct bnx_softc *, uint8_t[]); 2606c8d8eccSSepherosa Ziehau 2616c8d8eccSSepherosa Ziehau static void bnx_coal_change(struct bnx_softc *); 262aad4de2bSSepherosa Ziehau static int bnx_sysctl_force_defrag(SYSCTL_HANDLER_ARGS); 263472c99c8SSepherosa Ziehau static int bnx_sysctl_tx_wreg(SYSCTL_HANDLER_ARGS); 2646c8d8eccSSepherosa Ziehau static int bnx_sysctl_rx_coal_ticks(SYSCTL_HANDLER_ARGS); 2656c8d8eccSSepherosa Ziehau static int bnx_sysctl_tx_coal_ticks(SYSCTL_HANDLER_ARGS); 2666c8d8eccSSepherosa Ziehau static int bnx_sysctl_rx_coal_bds(SYSCTL_HANDLER_ARGS); 2676c8d8eccSSepherosa Ziehau static int bnx_sysctl_tx_coal_bds(SYSCTL_HANDLER_ARGS); 2686c8d8eccSSepherosa Ziehau static int bnx_sysctl_rx_coal_bds_int(SYSCTL_HANDLER_ARGS); 2696c8d8eccSSepherosa Ziehau static int bnx_sysctl_tx_coal_bds_int(SYSCTL_HANDLER_ARGS); 2706c8d8eccSSepherosa Ziehau static int bnx_sysctl_coal_chg(SYSCTL_HANDLER_ARGS, uint32_t *, 2716c8d8eccSSepherosa Ziehau int, int, uint32_t); 2724fa38985SSepherosa Ziehau #ifdef IFPOLL_ENABLE 2734fa38985SSepherosa Ziehau static int bnx_sysctl_npoll_offset(SYSCTL_HANDLER_ARGS); 2744fa38985SSepherosa Ziehau static int bnx_sysctl_npoll_rxoff(SYSCTL_HANDLER_ARGS); 2754fa38985SSepherosa Ziehau static int bnx_sysctl_npoll_txoff(SYSCTL_HANDLER_ARGS); 2764fa38985SSepherosa Ziehau #endif 277841cdf08SSepherosa Ziehau static int bnx_sysctl_std_refill(SYSCTL_HANDLER_ARGS); 2786c8d8eccSSepherosa Ziehau 2796c8d8eccSSepherosa Ziehau static int bnx_msi_enable = 1; 2806c8d8eccSSepherosa Ziehau TUNABLE_INT("hw.bnx.msi.enable", &bnx_msi_enable); 2816c8d8eccSSepherosa Ziehau 2826c8d8eccSSepherosa Ziehau static device_method_t bnx_methods[] = { 2836c8d8eccSSepherosa Ziehau /* Device interface */ 2846c8d8eccSSepherosa Ziehau DEVMETHOD(device_probe, bnx_probe), 2856c8d8eccSSepherosa Ziehau DEVMETHOD(device_attach, bnx_attach), 2866c8d8eccSSepherosa Ziehau DEVMETHOD(device_detach, bnx_detach), 2876c8d8eccSSepherosa Ziehau DEVMETHOD(device_shutdown, bnx_shutdown), 2886c8d8eccSSepherosa Ziehau DEVMETHOD(device_suspend, bnx_suspend), 2896c8d8eccSSepherosa Ziehau DEVMETHOD(device_resume, bnx_resume), 2906c8d8eccSSepherosa Ziehau 2916c8d8eccSSepherosa Ziehau /* bus interface */ 2926c8d8eccSSepherosa Ziehau DEVMETHOD(bus_print_child, bus_generic_print_child), 2936c8d8eccSSepherosa Ziehau DEVMETHOD(bus_driver_added, bus_generic_driver_added), 2946c8d8eccSSepherosa Ziehau 2956c8d8eccSSepherosa Ziehau /* MII interface */ 2966c8d8eccSSepherosa Ziehau DEVMETHOD(miibus_readreg, bnx_miibus_readreg), 2976c8d8eccSSepherosa Ziehau DEVMETHOD(miibus_writereg, bnx_miibus_writereg), 2986c8d8eccSSepherosa Ziehau DEVMETHOD(miibus_statchg, bnx_miibus_statchg), 2996c8d8eccSSepherosa Ziehau 300d3c9c58eSSascha Wildner DEVMETHOD_END 3016c8d8eccSSepherosa Ziehau }; 3026c8d8eccSSepherosa Ziehau 3036c8d8eccSSepherosa Ziehau static DEFINE_CLASS_0(bnx, bnx_driver, bnx_methods, sizeof(struct bnx_softc)); 3046c8d8eccSSepherosa Ziehau static devclass_t bnx_devclass; 3056c8d8eccSSepherosa Ziehau 3066c8d8eccSSepherosa Ziehau DECLARE_DUMMY_MODULE(if_bnx); 3076c8d8eccSSepherosa Ziehau DRIVER_MODULE(if_bnx, pci, bnx_driver, bnx_devclass, NULL, NULL); 3086c8d8eccSSepherosa Ziehau DRIVER_MODULE(miibus, bnx, miibus_driver, miibus_devclass, NULL, NULL); 3096c8d8eccSSepherosa Ziehau 3106c8d8eccSSepherosa Ziehau static uint32_t 3116c8d8eccSSepherosa Ziehau bnx_readmem_ind(struct bnx_softc *sc, uint32_t off) 3126c8d8eccSSepherosa Ziehau { 3136c8d8eccSSepherosa Ziehau device_t dev = sc->bnx_dev; 3146c8d8eccSSepherosa Ziehau uint32_t val; 3156c8d8eccSSepherosa Ziehau 3166c8d8eccSSepherosa Ziehau pci_write_config(dev, BGE_PCI_MEMWIN_BASEADDR, off, 4); 3176c8d8eccSSepherosa Ziehau val = pci_read_config(dev, BGE_PCI_MEMWIN_DATA, 4); 3186c8d8eccSSepherosa Ziehau pci_write_config(dev, BGE_PCI_MEMWIN_BASEADDR, 0, 4); 3196c8d8eccSSepherosa Ziehau return (val); 3206c8d8eccSSepherosa Ziehau } 3216c8d8eccSSepherosa Ziehau 3226c8d8eccSSepherosa Ziehau static void 3236c8d8eccSSepherosa Ziehau bnx_writemem_ind(struct bnx_softc *sc, uint32_t off, uint32_t val) 3246c8d8eccSSepherosa Ziehau { 3256c8d8eccSSepherosa Ziehau device_t dev = sc->bnx_dev; 3266c8d8eccSSepherosa Ziehau 3276c8d8eccSSepherosa Ziehau pci_write_config(dev, BGE_PCI_MEMWIN_BASEADDR, off, 4); 3286c8d8eccSSepherosa Ziehau pci_write_config(dev, BGE_PCI_MEMWIN_DATA, val, 4); 3296c8d8eccSSepherosa Ziehau pci_write_config(dev, BGE_PCI_MEMWIN_BASEADDR, 0, 4); 3306c8d8eccSSepherosa Ziehau } 3316c8d8eccSSepherosa Ziehau 3326c8d8eccSSepherosa Ziehau static void 3336c8d8eccSSepherosa Ziehau bnx_writemem_direct(struct bnx_softc *sc, uint32_t off, uint32_t val) 3346c8d8eccSSepherosa Ziehau { 3356c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, off, val); 3366c8d8eccSSepherosa Ziehau } 3376c8d8eccSSepherosa Ziehau 3386c8d8eccSSepherosa Ziehau static void 3396c8d8eccSSepherosa Ziehau bnx_writembx(struct bnx_softc *sc, int off, int val) 3406c8d8eccSSepherosa Ziehau { 3416c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, off, val); 3426c8d8eccSSepherosa Ziehau } 3436c8d8eccSSepherosa Ziehau 3446c8d8eccSSepherosa Ziehau /* 3456c8d8eccSSepherosa Ziehau * Read a sequence of bytes from NVRAM. 3466c8d8eccSSepherosa Ziehau */ 3476c8d8eccSSepherosa Ziehau static int 3486c8d8eccSSepherosa Ziehau bnx_read_nvram(struct bnx_softc *sc, caddr_t dest, int off, int cnt) 3496c8d8eccSSepherosa Ziehau { 3506c8d8eccSSepherosa Ziehau return (1); 3516c8d8eccSSepherosa Ziehau } 3526c8d8eccSSepherosa Ziehau 3536c8d8eccSSepherosa Ziehau /* 3546c8d8eccSSepherosa Ziehau * Read a byte of data stored in the EEPROM at address 'addr.' The 3556c8d8eccSSepherosa Ziehau * BCM570x supports both the traditional bitbang interface and an 3566c8d8eccSSepherosa Ziehau * auto access interface for reading the EEPROM. We use the auto 3576c8d8eccSSepherosa Ziehau * access method. 3586c8d8eccSSepherosa Ziehau */ 3596c8d8eccSSepherosa Ziehau static uint8_t 3606c8d8eccSSepherosa Ziehau bnx_eeprom_getbyte(struct bnx_softc *sc, uint32_t addr, uint8_t *dest) 3616c8d8eccSSepherosa Ziehau { 3626c8d8eccSSepherosa Ziehau int i; 3636c8d8eccSSepherosa Ziehau uint32_t byte = 0; 3646c8d8eccSSepherosa Ziehau 3656c8d8eccSSepherosa Ziehau /* 3666c8d8eccSSepherosa Ziehau * Enable use of auto EEPROM access so we can avoid 3676c8d8eccSSepherosa Ziehau * having to use the bitbang method. 3686c8d8eccSSepherosa Ziehau */ 3696c8d8eccSSepherosa Ziehau BNX_SETBIT(sc, BGE_MISC_LOCAL_CTL, BGE_MLC_AUTO_EEPROM); 3706c8d8eccSSepherosa Ziehau 3716c8d8eccSSepherosa Ziehau /* Reset the EEPROM, load the clock period. */ 3726c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_EE_ADDR, 3736c8d8eccSSepherosa Ziehau BGE_EEADDR_RESET|BGE_EEHALFCLK(BGE_HALFCLK_384SCL)); 3746c8d8eccSSepherosa Ziehau DELAY(20); 3756c8d8eccSSepherosa Ziehau 3766c8d8eccSSepherosa Ziehau /* Issue the read EEPROM command. */ 3776c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_EE_ADDR, BGE_EE_READCMD | addr); 3786c8d8eccSSepherosa Ziehau 3796c8d8eccSSepherosa Ziehau /* Wait for completion */ 3806c8d8eccSSepherosa Ziehau for(i = 0; i < BNX_TIMEOUT * 10; i++) { 3816c8d8eccSSepherosa Ziehau DELAY(10); 3826c8d8eccSSepherosa Ziehau if (CSR_READ_4(sc, BGE_EE_ADDR) & BGE_EEADDR_DONE) 3836c8d8eccSSepherosa Ziehau break; 3846c8d8eccSSepherosa Ziehau } 3856c8d8eccSSepherosa Ziehau 3866c8d8eccSSepherosa Ziehau if (i == BNX_TIMEOUT) { 3876c8d8eccSSepherosa Ziehau if_printf(&sc->arpcom.ac_if, "eeprom read timed out\n"); 3886c8d8eccSSepherosa Ziehau return(1); 3896c8d8eccSSepherosa Ziehau } 3906c8d8eccSSepherosa Ziehau 3916c8d8eccSSepherosa Ziehau /* Get result. */ 3926c8d8eccSSepherosa Ziehau byte = CSR_READ_4(sc, BGE_EE_DATA); 3936c8d8eccSSepherosa Ziehau 3946c8d8eccSSepherosa Ziehau *dest = (byte >> ((addr % 4) * 8)) & 0xFF; 3956c8d8eccSSepherosa Ziehau 3966c8d8eccSSepherosa Ziehau return(0); 3976c8d8eccSSepherosa Ziehau } 3986c8d8eccSSepherosa Ziehau 3996c8d8eccSSepherosa Ziehau /* 4006c8d8eccSSepherosa Ziehau * Read a sequence of bytes from the EEPROM. 4016c8d8eccSSepherosa Ziehau */ 4026c8d8eccSSepherosa Ziehau static int 4036c8d8eccSSepherosa Ziehau bnx_read_eeprom(struct bnx_softc *sc, caddr_t dest, uint32_t off, size_t len) 4046c8d8eccSSepherosa Ziehau { 4056c8d8eccSSepherosa Ziehau size_t i; 4066c8d8eccSSepherosa Ziehau int err; 4076c8d8eccSSepherosa Ziehau uint8_t byte; 4086c8d8eccSSepherosa Ziehau 4096c8d8eccSSepherosa Ziehau for (byte = 0, err = 0, i = 0; i < len; i++) { 4106c8d8eccSSepherosa Ziehau err = bnx_eeprom_getbyte(sc, off + i, &byte); 4116c8d8eccSSepherosa Ziehau if (err) 4126c8d8eccSSepherosa Ziehau break; 4136c8d8eccSSepherosa Ziehau *(dest + i) = byte; 4146c8d8eccSSepherosa Ziehau } 4156c8d8eccSSepherosa Ziehau 4166c8d8eccSSepherosa Ziehau return(err ? 1 : 0); 4176c8d8eccSSepherosa Ziehau } 4186c8d8eccSSepherosa Ziehau 4196c8d8eccSSepherosa Ziehau static int 4206c8d8eccSSepherosa Ziehau bnx_miibus_readreg(device_t dev, int phy, int reg) 4216c8d8eccSSepherosa Ziehau { 4226c8d8eccSSepherosa Ziehau struct bnx_softc *sc = device_get_softc(dev); 4236c8d8eccSSepherosa Ziehau uint32_t val; 4246c8d8eccSSepherosa Ziehau int i; 4256c8d8eccSSepherosa Ziehau 4266c8d8eccSSepherosa Ziehau KASSERT(phy == sc->bnx_phyno, 4276c8d8eccSSepherosa Ziehau ("invalid phyno %d, should be %d", phy, sc->bnx_phyno)); 4286c8d8eccSSepherosa Ziehau 4296c8d8eccSSepherosa Ziehau /* Clear the autopoll bit if set, otherwise may trigger PCI errors. */ 4306c8d8eccSSepherosa Ziehau if (sc->bnx_mi_mode & BGE_MIMODE_AUTOPOLL) { 4316c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_MI_MODE, 4326c8d8eccSSepherosa Ziehau sc->bnx_mi_mode & ~BGE_MIMODE_AUTOPOLL); 4336c8d8eccSSepherosa Ziehau DELAY(80); 4346c8d8eccSSepherosa Ziehau } 4356c8d8eccSSepherosa Ziehau 4366c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_MI_COMM, BGE_MICMD_READ | BGE_MICOMM_BUSY | 4376c8d8eccSSepherosa Ziehau BGE_MIPHY(phy) | BGE_MIREG(reg)); 4386c8d8eccSSepherosa Ziehau 4396c8d8eccSSepherosa Ziehau /* Poll for the PHY register access to complete. */ 4406c8d8eccSSepherosa Ziehau for (i = 0; i < BNX_TIMEOUT; i++) { 4416c8d8eccSSepherosa Ziehau DELAY(10); 4426c8d8eccSSepherosa Ziehau val = CSR_READ_4(sc, BGE_MI_COMM); 4436c8d8eccSSepherosa Ziehau if ((val & BGE_MICOMM_BUSY) == 0) { 4446c8d8eccSSepherosa Ziehau DELAY(5); 4456c8d8eccSSepherosa Ziehau val = CSR_READ_4(sc, BGE_MI_COMM); 4466c8d8eccSSepherosa Ziehau break; 4476c8d8eccSSepherosa Ziehau } 4486c8d8eccSSepherosa Ziehau } 4496c8d8eccSSepherosa Ziehau if (i == BNX_TIMEOUT) { 4506c8d8eccSSepherosa Ziehau if_printf(&sc->arpcom.ac_if, "PHY read timed out " 4516c8d8eccSSepherosa Ziehau "(phy %d, reg %d, val 0x%08x)\n", phy, reg, val); 4526c8d8eccSSepherosa Ziehau val = 0; 4536c8d8eccSSepherosa Ziehau } 4546c8d8eccSSepherosa Ziehau 4556c8d8eccSSepherosa Ziehau /* Restore the autopoll bit if necessary. */ 4566c8d8eccSSepherosa Ziehau if (sc->bnx_mi_mode & BGE_MIMODE_AUTOPOLL) { 4576c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_MI_MODE, sc->bnx_mi_mode); 4586c8d8eccSSepherosa Ziehau DELAY(80); 4596c8d8eccSSepherosa Ziehau } 4606c8d8eccSSepherosa Ziehau 4616c8d8eccSSepherosa Ziehau if (val & BGE_MICOMM_READFAIL) 4626c8d8eccSSepherosa Ziehau return 0; 4636c8d8eccSSepherosa Ziehau 4646c8d8eccSSepherosa Ziehau return (val & 0xFFFF); 4656c8d8eccSSepherosa Ziehau } 4666c8d8eccSSepherosa Ziehau 4676c8d8eccSSepherosa Ziehau static int 4686c8d8eccSSepherosa Ziehau bnx_miibus_writereg(device_t dev, int phy, int reg, int val) 4696c8d8eccSSepherosa Ziehau { 4706c8d8eccSSepherosa Ziehau struct bnx_softc *sc = device_get_softc(dev); 4716c8d8eccSSepherosa Ziehau int i; 4726c8d8eccSSepherosa Ziehau 4736c8d8eccSSepherosa Ziehau KASSERT(phy == sc->bnx_phyno, 4746c8d8eccSSepherosa Ziehau ("invalid phyno %d, should be %d", phy, sc->bnx_phyno)); 4756c8d8eccSSepherosa Ziehau 4766c8d8eccSSepherosa Ziehau /* Clear the autopoll bit if set, otherwise may trigger PCI errors. */ 4776c8d8eccSSepherosa Ziehau if (sc->bnx_mi_mode & BGE_MIMODE_AUTOPOLL) { 4786c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_MI_MODE, 4796c8d8eccSSepherosa Ziehau sc->bnx_mi_mode & ~BGE_MIMODE_AUTOPOLL); 4806c8d8eccSSepherosa Ziehau DELAY(80); 4816c8d8eccSSepherosa Ziehau } 4826c8d8eccSSepherosa Ziehau 4836c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_MI_COMM, BGE_MICMD_WRITE | BGE_MICOMM_BUSY | 4846c8d8eccSSepherosa Ziehau BGE_MIPHY(phy) | BGE_MIREG(reg) | val); 4856c8d8eccSSepherosa Ziehau 4866c8d8eccSSepherosa Ziehau for (i = 0; i < BNX_TIMEOUT; i++) { 4876c8d8eccSSepherosa Ziehau DELAY(10); 4886c8d8eccSSepherosa Ziehau if (!(CSR_READ_4(sc, BGE_MI_COMM) & BGE_MICOMM_BUSY)) { 4896c8d8eccSSepherosa Ziehau DELAY(5); 4906c8d8eccSSepherosa Ziehau CSR_READ_4(sc, BGE_MI_COMM); /* dummy read */ 4916c8d8eccSSepherosa Ziehau break; 4926c8d8eccSSepherosa Ziehau } 4936c8d8eccSSepherosa Ziehau } 4946c8d8eccSSepherosa Ziehau if (i == BNX_TIMEOUT) { 4956c8d8eccSSepherosa Ziehau if_printf(&sc->arpcom.ac_if, "PHY write timed out " 4966c8d8eccSSepherosa Ziehau "(phy %d, reg %d, val %d)\n", phy, reg, val); 4976c8d8eccSSepherosa Ziehau } 4986c8d8eccSSepherosa Ziehau 4996c8d8eccSSepherosa Ziehau /* Restore the autopoll bit if necessary. */ 5006c8d8eccSSepherosa Ziehau if (sc->bnx_mi_mode & BGE_MIMODE_AUTOPOLL) { 5016c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_MI_MODE, sc->bnx_mi_mode); 5026c8d8eccSSepherosa Ziehau DELAY(80); 5036c8d8eccSSepherosa Ziehau } 5046c8d8eccSSepherosa Ziehau 5056c8d8eccSSepherosa Ziehau return 0; 5066c8d8eccSSepherosa Ziehau } 5076c8d8eccSSepherosa Ziehau 5086c8d8eccSSepherosa Ziehau static void 5096c8d8eccSSepherosa Ziehau bnx_miibus_statchg(device_t dev) 5106c8d8eccSSepherosa Ziehau { 5116c8d8eccSSepherosa Ziehau struct bnx_softc *sc; 5126c8d8eccSSepherosa Ziehau struct mii_data *mii; 5136c8d8eccSSepherosa Ziehau 5146c8d8eccSSepherosa Ziehau sc = device_get_softc(dev); 5156c8d8eccSSepherosa Ziehau mii = device_get_softc(sc->bnx_miibus); 5166c8d8eccSSepherosa Ziehau 5176c8d8eccSSepherosa Ziehau if ((mii->mii_media_status & (IFM_ACTIVE | IFM_AVALID)) == 5186c8d8eccSSepherosa Ziehau (IFM_ACTIVE | IFM_AVALID)) { 5196c8d8eccSSepherosa Ziehau switch (IFM_SUBTYPE(mii->mii_media_active)) { 5206c8d8eccSSepherosa Ziehau case IFM_10_T: 5216c8d8eccSSepherosa Ziehau case IFM_100_TX: 5226c8d8eccSSepherosa Ziehau sc->bnx_link = 1; 5236c8d8eccSSepherosa Ziehau break; 5246c8d8eccSSepherosa Ziehau case IFM_1000_T: 5256c8d8eccSSepherosa Ziehau case IFM_1000_SX: 5266c8d8eccSSepherosa Ziehau case IFM_2500_SX: 5276c8d8eccSSepherosa Ziehau sc->bnx_link = 1; 5286c8d8eccSSepherosa Ziehau break; 5296c8d8eccSSepherosa Ziehau default: 5306c8d8eccSSepherosa Ziehau sc->bnx_link = 0; 5316c8d8eccSSepherosa Ziehau break; 5326c8d8eccSSepherosa Ziehau } 5336c8d8eccSSepherosa Ziehau } else { 5346c8d8eccSSepherosa Ziehau sc->bnx_link = 0; 5356c8d8eccSSepherosa Ziehau } 5366c8d8eccSSepherosa Ziehau if (sc->bnx_link == 0) 5376c8d8eccSSepherosa Ziehau return; 5386c8d8eccSSepherosa Ziehau 5396c8d8eccSSepherosa Ziehau BNX_CLRBIT(sc, BGE_MAC_MODE, BGE_MACMODE_PORTMODE); 5406c8d8eccSSepherosa Ziehau if (IFM_SUBTYPE(mii->mii_media_active) == IFM_1000_T || 5416c8d8eccSSepherosa Ziehau IFM_SUBTYPE(mii->mii_media_active) == IFM_1000_SX) { 5426c8d8eccSSepherosa Ziehau BNX_SETBIT(sc, BGE_MAC_MODE, BGE_PORTMODE_GMII); 5436c8d8eccSSepherosa Ziehau } else { 5446c8d8eccSSepherosa Ziehau BNX_SETBIT(sc, BGE_MAC_MODE, BGE_PORTMODE_MII); 5456c8d8eccSSepherosa Ziehau } 5466c8d8eccSSepherosa Ziehau 5476c8d8eccSSepherosa Ziehau if ((mii->mii_media_active & IFM_GMASK) == IFM_FDX) { 5486c8d8eccSSepherosa Ziehau BNX_CLRBIT(sc, BGE_MAC_MODE, BGE_MACMODE_HALF_DUPLEX); 5496c8d8eccSSepherosa Ziehau } else { 5506c8d8eccSSepherosa Ziehau BNX_SETBIT(sc, BGE_MAC_MODE, BGE_MACMODE_HALF_DUPLEX); 5516c8d8eccSSepherosa Ziehau } 5526c8d8eccSSepherosa Ziehau } 5536c8d8eccSSepherosa Ziehau 5546c8d8eccSSepherosa Ziehau /* 5556c8d8eccSSepherosa Ziehau * Memory management for jumbo frames. 5566c8d8eccSSepherosa Ziehau */ 5576c8d8eccSSepherosa Ziehau static int 5586c8d8eccSSepherosa Ziehau bnx_alloc_jumbo_mem(struct bnx_softc *sc) 5596c8d8eccSSepherosa Ziehau { 5606c8d8eccSSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if; 5616c8d8eccSSepherosa Ziehau struct bnx_jslot *entry; 5626c8d8eccSSepherosa Ziehau uint8_t *ptr; 5636c8d8eccSSepherosa Ziehau bus_addr_t paddr; 5646c8d8eccSSepherosa Ziehau int i, error; 5656c8d8eccSSepherosa Ziehau 5666c8d8eccSSepherosa Ziehau /* 5676c8d8eccSSepherosa Ziehau * Create tag for jumbo mbufs. 5686c8d8eccSSepherosa Ziehau * This is really a bit of a kludge. We allocate a special 5696c8d8eccSSepherosa Ziehau * jumbo buffer pool which (thanks to the way our DMA 5706c8d8eccSSepherosa Ziehau * memory allocation works) will consist of contiguous 5716c8d8eccSSepherosa Ziehau * pages. This means that even though a jumbo buffer might 5726c8d8eccSSepherosa Ziehau * be larger than a page size, we don't really need to 5736c8d8eccSSepherosa Ziehau * map it into more than one DMA segment. However, the 5746c8d8eccSSepherosa Ziehau * default mbuf tag will result in multi-segment mappings, 5756c8d8eccSSepherosa Ziehau * so we have to create a special jumbo mbuf tag that 5766c8d8eccSSepherosa Ziehau * lets us get away with mapping the jumbo buffers as 5776c8d8eccSSepherosa Ziehau * a single segment. I think eventually the driver should 5786c8d8eccSSepherosa Ziehau * be changed so that it uses ordinary mbufs and cluster 5796c8d8eccSSepherosa Ziehau * buffers, i.e. jumbo frames can span multiple DMA 5806c8d8eccSSepherosa Ziehau * descriptors. But that's a project for another day. 5816c8d8eccSSepherosa Ziehau */ 5826c8d8eccSSepherosa Ziehau 5836c8d8eccSSepherosa Ziehau /* 5846c8d8eccSSepherosa Ziehau * Create DMA stuffs for jumbo RX ring. 5856c8d8eccSSepherosa Ziehau */ 5866c8d8eccSSepherosa Ziehau error = bnx_dma_block_alloc(sc, BGE_JUMBO_RX_RING_SZ, 5876c8d8eccSSepherosa Ziehau &sc->bnx_cdata.bnx_rx_jumbo_ring_tag, 5886c8d8eccSSepherosa Ziehau &sc->bnx_cdata.bnx_rx_jumbo_ring_map, 5896c8d8eccSSepherosa Ziehau (void *)&sc->bnx_ldata.bnx_rx_jumbo_ring, 5906c8d8eccSSepherosa Ziehau &sc->bnx_ldata.bnx_rx_jumbo_ring_paddr); 5916c8d8eccSSepherosa Ziehau if (error) { 5926c8d8eccSSepherosa Ziehau if_printf(ifp, "could not create jumbo RX ring\n"); 5936c8d8eccSSepherosa Ziehau return error; 5946c8d8eccSSepherosa Ziehau } 5956c8d8eccSSepherosa Ziehau 5966c8d8eccSSepherosa Ziehau /* 5976c8d8eccSSepherosa Ziehau * Create DMA stuffs for jumbo buffer block. 5986c8d8eccSSepherosa Ziehau */ 5996c8d8eccSSepherosa Ziehau error = bnx_dma_block_alloc(sc, BNX_JMEM, 6006c8d8eccSSepherosa Ziehau &sc->bnx_cdata.bnx_jumbo_tag, 6016c8d8eccSSepherosa Ziehau &sc->bnx_cdata.bnx_jumbo_map, 6026c8d8eccSSepherosa Ziehau (void **)&sc->bnx_ldata.bnx_jumbo_buf, 6036c8d8eccSSepherosa Ziehau &paddr); 6046c8d8eccSSepherosa Ziehau if (error) { 6056c8d8eccSSepherosa Ziehau if_printf(ifp, "could not create jumbo buffer\n"); 6066c8d8eccSSepherosa Ziehau return error; 6076c8d8eccSSepherosa Ziehau } 6086c8d8eccSSepherosa Ziehau 6096c8d8eccSSepherosa Ziehau SLIST_INIT(&sc->bnx_jfree_listhead); 6106c8d8eccSSepherosa Ziehau 6116c8d8eccSSepherosa Ziehau /* 6126c8d8eccSSepherosa Ziehau * Now divide it up into 9K pieces and save the addresses 6136c8d8eccSSepherosa Ziehau * in an array. Note that we play an evil trick here by using 6146c8d8eccSSepherosa Ziehau * the first few bytes in the buffer to hold the the address 6156c8d8eccSSepherosa Ziehau * of the softc structure for this interface. This is because 6166c8d8eccSSepherosa Ziehau * bnx_jfree() needs it, but it is called by the mbuf management 6176c8d8eccSSepherosa Ziehau * code which will not pass it to us explicitly. 6186c8d8eccSSepherosa Ziehau */ 6196c8d8eccSSepherosa Ziehau for (i = 0, ptr = sc->bnx_ldata.bnx_jumbo_buf; i < BNX_JSLOTS; i++) { 6206c8d8eccSSepherosa Ziehau entry = &sc->bnx_cdata.bnx_jslots[i]; 6216c8d8eccSSepherosa Ziehau entry->bnx_sc = sc; 6226c8d8eccSSepherosa Ziehau entry->bnx_buf = ptr; 6236c8d8eccSSepherosa Ziehau entry->bnx_paddr = paddr; 6246c8d8eccSSepherosa Ziehau entry->bnx_inuse = 0; 6256c8d8eccSSepherosa Ziehau entry->bnx_slot = i; 6266c8d8eccSSepherosa Ziehau SLIST_INSERT_HEAD(&sc->bnx_jfree_listhead, entry, jslot_link); 6276c8d8eccSSepherosa Ziehau 6286c8d8eccSSepherosa Ziehau ptr += BNX_JLEN; 6296c8d8eccSSepherosa Ziehau paddr += BNX_JLEN; 6306c8d8eccSSepherosa Ziehau } 6316c8d8eccSSepherosa Ziehau return 0; 6326c8d8eccSSepherosa Ziehau } 6336c8d8eccSSepherosa Ziehau 6346c8d8eccSSepherosa Ziehau static void 6356c8d8eccSSepherosa Ziehau bnx_free_jumbo_mem(struct bnx_softc *sc) 6366c8d8eccSSepherosa Ziehau { 6376c8d8eccSSepherosa Ziehau /* Destroy jumbo RX ring. */ 6386c8d8eccSSepherosa Ziehau bnx_dma_block_free(sc->bnx_cdata.bnx_rx_jumbo_ring_tag, 6396c8d8eccSSepherosa Ziehau sc->bnx_cdata.bnx_rx_jumbo_ring_map, 6406c8d8eccSSepherosa Ziehau sc->bnx_ldata.bnx_rx_jumbo_ring); 6416c8d8eccSSepherosa Ziehau 6426c8d8eccSSepherosa Ziehau /* Destroy jumbo buffer block. */ 6436c8d8eccSSepherosa Ziehau bnx_dma_block_free(sc->bnx_cdata.bnx_jumbo_tag, 6446c8d8eccSSepherosa Ziehau sc->bnx_cdata.bnx_jumbo_map, 6456c8d8eccSSepherosa Ziehau sc->bnx_ldata.bnx_jumbo_buf); 6466c8d8eccSSepherosa Ziehau } 6476c8d8eccSSepherosa Ziehau 6486c8d8eccSSepherosa Ziehau /* 6496c8d8eccSSepherosa Ziehau * Allocate a jumbo buffer. 6506c8d8eccSSepherosa Ziehau */ 6516c8d8eccSSepherosa Ziehau static struct bnx_jslot * 6526c8d8eccSSepherosa Ziehau bnx_jalloc(struct bnx_softc *sc) 6536c8d8eccSSepherosa Ziehau { 6546c8d8eccSSepherosa Ziehau struct bnx_jslot *entry; 6556c8d8eccSSepherosa Ziehau 6566c8d8eccSSepherosa Ziehau lwkt_serialize_enter(&sc->bnx_jslot_serializer); 6576c8d8eccSSepherosa Ziehau entry = SLIST_FIRST(&sc->bnx_jfree_listhead); 6586c8d8eccSSepherosa Ziehau if (entry) { 6596c8d8eccSSepherosa Ziehau SLIST_REMOVE_HEAD(&sc->bnx_jfree_listhead, jslot_link); 6606c8d8eccSSepherosa Ziehau entry->bnx_inuse = 1; 6616c8d8eccSSepherosa Ziehau } else { 6626c8d8eccSSepherosa Ziehau if_printf(&sc->arpcom.ac_if, "no free jumbo buffers\n"); 6636c8d8eccSSepherosa Ziehau } 6646c8d8eccSSepherosa Ziehau lwkt_serialize_exit(&sc->bnx_jslot_serializer); 6656c8d8eccSSepherosa Ziehau return(entry); 6666c8d8eccSSepherosa Ziehau } 6676c8d8eccSSepherosa Ziehau 6686c8d8eccSSepherosa Ziehau /* 6696c8d8eccSSepherosa Ziehau * Adjust usage count on a jumbo buffer. 6706c8d8eccSSepherosa Ziehau */ 6716c8d8eccSSepherosa Ziehau static void 6726c8d8eccSSepherosa Ziehau bnx_jref(void *arg) 6736c8d8eccSSepherosa Ziehau { 6746c8d8eccSSepherosa Ziehau struct bnx_jslot *entry = (struct bnx_jslot *)arg; 6756c8d8eccSSepherosa Ziehau struct bnx_softc *sc = entry->bnx_sc; 6766c8d8eccSSepherosa Ziehau 6776c8d8eccSSepherosa Ziehau if (sc == NULL) 6786c8d8eccSSepherosa Ziehau panic("bnx_jref: can't find softc pointer!"); 6796c8d8eccSSepherosa Ziehau 6806c8d8eccSSepherosa Ziehau if (&sc->bnx_cdata.bnx_jslots[entry->bnx_slot] != entry) { 6816c8d8eccSSepherosa Ziehau panic("bnx_jref: asked to reference buffer " 6826c8d8eccSSepherosa Ziehau "that we don't manage!"); 6836c8d8eccSSepherosa Ziehau } else if (entry->bnx_inuse == 0) { 6846c8d8eccSSepherosa Ziehau panic("bnx_jref: buffer already free!"); 6856c8d8eccSSepherosa Ziehau } else { 6866c8d8eccSSepherosa Ziehau atomic_add_int(&entry->bnx_inuse, 1); 6876c8d8eccSSepherosa Ziehau } 6886c8d8eccSSepherosa Ziehau } 6896c8d8eccSSepherosa Ziehau 6906c8d8eccSSepherosa Ziehau /* 6916c8d8eccSSepherosa Ziehau * Release a jumbo buffer. 6926c8d8eccSSepherosa Ziehau */ 6936c8d8eccSSepherosa Ziehau static void 6946c8d8eccSSepherosa Ziehau bnx_jfree(void *arg) 6956c8d8eccSSepherosa Ziehau { 6966c8d8eccSSepherosa Ziehau struct bnx_jslot *entry = (struct bnx_jslot *)arg; 6976c8d8eccSSepherosa Ziehau struct bnx_softc *sc = entry->bnx_sc; 6986c8d8eccSSepherosa Ziehau 6996c8d8eccSSepherosa Ziehau if (sc == NULL) 7006c8d8eccSSepherosa Ziehau panic("bnx_jfree: can't find softc pointer!"); 7016c8d8eccSSepherosa Ziehau 7026c8d8eccSSepherosa Ziehau if (&sc->bnx_cdata.bnx_jslots[entry->bnx_slot] != entry) { 7036c8d8eccSSepherosa Ziehau panic("bnx_jfree: asked to free buffer that we don't manage!"); 7046c8d8eccSSepherosa Ziehau } else if (entry->bnx_inuse == 0) { 7056c8d8eccSSepherosa Ziehau panic("bnx_jfree: buffer already free!"); 7066c8d8eccSSepherosa Ziehau } else { 7076c8d8eccSSepherosa Ziehau /* 7086c8d8eccSSepherosa Ziehau * Possible MP race to 0, use the serializer. The atomic insn 7096c8d8eccSSepherosa Ziehau * is still needed for races against bnx_jref(). 7106c8d8eccSSepherosa Ziehau */ 7116c8d8eccSSepherosa Ziehau lwkt_serialize_enter(&sc->bnx_jslot_serializer); 7126c8d8eccSSepherosa Ziehau atomic_subtract_int(&entry->bnx_inuse, 1); 7136c8d8eccSSepherosa Ziehau if (entry->bnx_inuse == 0) { 7146c8d8eccSSepherosa Ziehau SLIST_INSERT_HEAD(&sc->bnx_jfree_listhead, 7156c8d8eccSSepherosa Ziehau entry, jslot_link); 7166c8d8eccSSepherosa Ziehau } 7176c8d8eccSSepherosa Ziehau lwkt_serialize_exit(&sc->bnx_jslot_serializer); 7186c8d8eccSSepherosa Ziehau } 7196c8d8eccSSepherosa Ziehau } 7206c8d8eccSSepherosa Ziehau 7216c8d8eccSSepherosa Ziehau 7226c8d8eccSSepherosa Ziehau /* 7236c8d8eccSSepherosa Ziehau * Intialize a standard receive ring descriptor. 7246c8d8eccSSepherosa Ziehau */ 7256c8d8eccSSepherosa Ziehau static int 726beedf5beSSepherosa Ziehau bnx_newbuf_std(struct bnx_rx_ret_ring *ret, int i, int init) 7276c8d8eccSSepherosa Ziehau { 7286c8d8eccSSepherosa Ziehau struct mbuf *m_new = NULL; 7296c8d8eccSSepherosa Ziehau bus_dma_segment_t seg; 7306c8d8eccSSepherosa Ziehau bus_dmamap_t map; 7316c8d8eccSSepherosa Ziehau int error, nsegs; 732beedf5beSSepherosa Ziehau struct bnx_rx_buf *rb; 7336c8d8eccSSepherosa Ziehau 734841cdf08SSepherosa Ziehau rb = &ret->bnx_std->bnx_rx_std_buf[i]; 735841cdf08SSepherosa Ziehau KASSERT(!rb->bnx_rx_refilled, ("RX buf %dth has been refilled", i)); 736841cdf08SSepherosa Ziehau 7376c8d8eccSSepherosa Ziehau m_new = m_getcl(init ? MB_WAIT : MB_DONTWAIT, MT_DATA, M_PKTHDR); 738841cdf08SSepherosa Ziehau if (m_new == NULL) { 739841cdf08SSepherosa Ziehau error = ENOBUFS; 740841cdf08SSepherosa Ziehau goto back; 741841cdf08SSepherosa Ziehau } 7426c8d8eccSSepherosa Ziehau m_new->m_len = m_new->m_pkthdr.len = MCLBYTES; 7436c8d8eccSSepherosa Ziehau m_adj(m_new, ETHER_ALIGN); 7446c8d8eccSSepherosa Ziehau 745beedf5beSSepherosa Ziehau error = bus_dmamap_load_mbuf_segment(ret->bnx_rx_mtag, 746beedf5beSSepherosa Ziehau ret->bnx_rx_tmpmap, m_new, &seg, 1, &nsegs, BUS_DMA_NOWAIT); 7476c8d8eccSSepherosa Ziehau if (error) { 7486c8d8eccSSepherosa Ziehau m_freem(m_new); 749841cdf08SSepherosa Ziehau goto back; 7506c8d8eccSSepherosa Ziehau } 7516c8d8eccSSepherosa Ziehau 7526c8d8eccSSepherosa Ziehau if (!init) { 753beedf5beSSepherosa Ziehau bus_dmamap_sync(ret->bnx_rx_mtag, rb->bnx_rx_dmamap, 7546c8d8eccSSepherosa Ziehau BUS_DMASYNC_POSTREAD); 755beedf5beSSepherosa Ziehau bus_dmamap_unload(ret->bnx_rx_mtag, rb->bnx_rx_dmamap); 7566c8d8eccSSepherosa Ziehau } 7576c8d8eccSSepherosa Ziehau 758beedf5beSSepherosa Ziehau map = ret->bnx_rx_tmpmap; 759beedf5beSSepherosa Ziehau ret->bnx_rx_tmpmap = rb->bnx_rx_dmamap; 7606c8d8eccSSepherosa Ziehau 761841cdf08SSepherosa Ziehau rb->bnx_rx_dmamap = map; 762beedf5beSSepherosa Ziehau rb->bnx_rx_mbuf = m_new; 763beedf5beSSepherosa Ziehau rb->bnx_rx_paddr = seg.ds_addr; 764841cdf08SSepherosa Ziehau back: 765841cdf08SSepherosa Ziehau cpu_sfence(); 766841cdf08SSepherosa Ziehau rb->bnx_rx_refilled = 1; 767841cdf08SSepherosa Ziehau return error; 7686c8d8eccSSepherosa Ziehau } 7696c8d8eccSSepherosa Ziehau 7706c8d8eccSSepherosa Ziehau static void 771beedf5beSSepherosa Ziehau bnx_setup_rxdesc_std(struct bnx_rx_std_ring *std, int i) 7726c8d8eccSSepherosa Ziehau { 773841cdf08SSepherosa Ziehau struct bnx_rx_buf *rb; 7746c8d8eccSSepherosa Ziehau struct bge_rx_bd *r; 7756c8d8eccSSepherosa Ziehau 776beedf5beSSepherosa Ziehau rb = &std->bnx_rx_std_buf[i]; 777841cdf08SSepherosa Ziehau KASSERT(rb->bnx_rx_refilled, ("RX buf %dth is not refilled", i)); 778841cdf08SSepherosa Ziehau rb->bnx_rx_refilled = 0; 7796c8d8eccSSepherosa Ziehau 780841cdf08SSepherosa Ziehau r = &std->bnx_rx_std_ring[i]; 781beedf5beSSepherosa Ziehau r->bge_addr.bge_addr_lo = BGE_ADDR_LO(rb->bnx_rx_paddr); 782beedf5beSSepherosa Ziehau r->bge_addr.bge_addr_hi = BGE_ADDR_HI(rb->bnx_rx_paddr); 783beedf5beSSepherosa Ziehau r->bge_len = rb->bnx_rx_mbuf->m_len; 7846c8d8eccSSepherosa Ziehau r->bge_idx = i; 7856c8d8eccSSepherosa Ziehau r->bge_flags = BGE_RXBDFLAG_END; 7866c8d8eccSSepherosa Ziehau } 7876c8d8eccSSepherosa Ziehau 7886c8d8eccSSepherosa Ziehau /* 7896c8d8eccSSepherosa Ziehau * Initialize a jumbo receive ring descriptor. This allocates 7906c8d8eccSSepherosa Ziehau * a jumbo buffer from the pool managed internally by the driver. 7916c8d8eccSSepherosa Ziehau */ 7926c8d8eccSSepherosa Ziehau static int 7936c8d8eccSSepherosa Ziehau bnx_newbuf_jumbo(struct bnx_softc *sc, int i, int init) 7946c8d8eccSSepherosa Ziehau { 7956c8d8eccSSepherosa Ziehau struct mbuf *m_new = NULL; 7966c8d8eccSSepherosa Ziehau struct bnx_jslot *buf; 7976c8d8eccSSepherosa Ziehau bus_addr_t paddr; 7986c8d8eccSSepherosa Ziehau 7996c8d8eccSSepherosa Ziehau /* Allocate the mbuf. */ 8006c8d8eccSSepherosa Ziehau MGETHDR(m_new, init ? MB_WAIT : MB_DONTWAIT, MT_DATA); 8016c8d8eccSSepherosa Ziehau if (m_new == NULL) 8026c8d8eccSSepherosa Ziehau return ENOBUFS; 8036c8d8eccSSepherosa Ziehau 8046c8d8eccSSepherosa Ziehau /* Allocate the jumbo buffer */ 8056c8d8eccSSepherosa Ziehau buf = bnx_jalloc(sc); 8066c8d8eccSSepherosa Ziehau if (buf == NULL) { 8076c8d8eccSSepherosa Ziehau m_freem(m_new); 8086c8d8eccSSepherosa Ziehau return ENOBUFS; 8096c8d8eccSSepherosa Ziehau } 8106c8d8eccSSepherosa Ziehau 8116c8d8eccSSepherosa Ziehau /* Attach the buffer to the mbuf. */ 8126c8d8eccSSepherosa Ziehau m_new->m_ext.ext_arg = buf; 8136c8d8eccSSepherosa Ziehau m_new->m_ext.ext_buf = buf->bnx_buf; 8146c8d8eccSSepherosa Ziehau m_new->m_ext.ext_free = bnx_jfree; 8156c8d8eccSSepherosa Ziehau m_new->m_ext.ext_ref = bnx_jref; 8166c8d8eccSSepherosa Ziehau m_new->m_ext.ext_size = BNX_JUMBO_FRAMELEN; 8176c8d8eccSSepherosa Ziehau 8186c8d8eccSSepherosa Ziehau m_new->m_flags |= M_EXT; 8196c8d8eccSSepherosa Ziehau 8206c8d8eccSSepherosa Ziehau m_new->m_data = m_new->m_ext.ext_buf; 8216c8d8eccSSepherosa Ziehau m_new->m_len = m_new->m_pkthdr.len = m_new->m_ext.ext_size; 8226c8d8eccSSepherosa Ziehau 8236c8d8eccSSepherosa Ziehau paddr = buf->bnx_paddr; 8246c8d8eccSSepherosa Ziehau m_adj(m_new, ETHER_ALIGN); 8256c8d8eccSSepherosa Ziehau paddr += ETHER_ALIGN; 8266c8d8eccSSepherosa Ziehau 8276c8d8eccSSepherosa Ziehau /* Save necessary information */ 828beedf5beSSepherosa Ziehau sc->bnx_cdata.bnx_rx_jumbo_chain[i].bnx_rx_mbuf = m_new; 829beedf5beSSepherosa Ziehau sc->bnx_cdata.bnx_rx_jumbo_chain[i].bnx_rx_paddr = paddr; 8306c8d8eccSSepherosa Ziehau 8316c8d8eccSSepherosa Ziehau /* Set up the descriptor. */ 8326c8d8eccSSepherosa Ziehau bnx_setup_rxdesc_jumbo(sc, i); 8336c8d8eccSSepherosa Ziehau return 0; 8346c8d8eccSSepherosa Ziehau } 8356c8d8eccSSepherosa Ziehau 8366c8d8eccSSepherosa Ziehau static void 8376c8d8eccSSepherosa Ziehau bnx_setup_rxdesc_jumbo(struct bnx_softc *sc, int i) 8386c8d8eccSSepherosa Ziehau { 8396c8d8eccSSepherosa Ziehau struct bge_rx_bd *r; 840beedf5beSSepherosa Ziehau struct bnx_rx_buf *rc; 8416c8d8eccSSepherosa Ziehau 8426c8d8eccSSepherosa Ziehau r = &sc->bnx_ldata.bnx_rx_jumbo_ring[i]; 8436c8d8eccSSepherosa Ziehau rc = &sc->bnx_cdata.bnx_rx_jumbo_chain[i]; 8446c8d8eccSSepherosa Ziehau 845beedf5beSSepherosa Ziehau r->bge_addr.bge_addr_lo = BGE_ADDR_LO(rc->bnx_rx_paddr); 846beedf5beSSepherosa Ziehau r->bge_addr.bge_addr_hi = BGE_ADDR_HI(rc->bnx_rx_paddr); 847beedf5beSSepherosa Ziehau r->bge_len = rc->bnx_rx_mbuf->m_len; 8486c8d8eccSSepherosa Ziehau r->bge_idx = i; 8496c8d8eccSSepherosa Ziehau r->bge_flags = BGE_RXBDFLAG_END|BGE_RXBDFLAG_JUMBO_RING; 8506c8d8eccSSepherosa Ziehau } 8516c8d8eccSSepherosa Ziehau 8526c8d8eccSSepherosa Ziehau static int 853beedf5beSSepherosa Ziehau bnx_init_rx_ring_std(struct bnx_rx_std_ring *std) 8546c8d8eccSSepherosa Ziehau { 8556c8d8eccSSepherosa Ziehau int i, error; 8566c8d8eccSSepherosa Ziehau 8576c8d8eccSSepherosa Ziehau for (i = 0; i < BGE_STD_RX_RING_CNT; i++) { 858beedf5beSSepherosa Ziehau /* Use the first RX return ring's tmp RX mbuf DMA map */ 859beedf5beSSepherosa Ziehau error = bnx_newbuf_std(&std->bnx_sc->bnx_rx_ret_ring[0], i, 1); 8606c8d8eccSSepherosa Ziehau if (error) 8616c8d8eccSSepherosa Ziehau return error; 862841cdf08SSepherosa Ziehau bnx_setup_rxdesc_std(std, i); 86387c7a7cfSSascha Wildner } 8646c8d8eccSSepherosa Ziehau 865841cdf08SSepherosa Ziehau std->bnx_rx_std_refill = 0; 866841cdf08SSepherosa Ziehau std->bnx_rx_std_running = 0; 867841cdf08SSepherosa Ziehau cpu_sfence(); 868841cdf08SSepherosa Ziehau lwkt_serialize_handler_enable(&std->bnx_rx_std_serialize); 869841cdf08SSepherosa Ziehau 870beedf5beSSepherosa Ziehau std->bnx_rx_std = BGE_STD_RX_RING_CNT - 1; 871beedf5beSSepherosa Ziehau bnx_writembx(std->bnx_sc, BGE_MBX_RX_STD_PROD_LO, std->bnx_rx_std); 8726c8d8eccSSepherosa Ziehau 8736c8d8eccSSepherosa Ziehau return(0); 8746c8d8eccSSepherosa Ziehau } 8756c8d8eccSSepherosa Ziehau 8766c8d8eccSSepherosa Ziehau static void 877beedf5beSSepherosa Ziehau bnx_free_rx_ring_std(struct bnx_rx_std_ring *std) 8786c8d8eccSSepherosa Ziehau { 8796c8d8eccSSepherosa Ziehau int i; 8806c8d8eccSSepherosa Ziehau 881841cdf08SSepherosa Ziehau lwkt_serialize_handler_disable(&std->bnx_rx_std_serialize); 882841cdf08SSepherosa Ziehau 8836c8d8eccSSepherosa Ziehau for (i = 0; i < BGE_STD_RX_RING_CNT; i++) { 884beedf5beSSepherosa Ziehau struct bnx_rx_buf *rb = &std->bnx_rx_std_buf[i]; 8856c8d8eccSSepherosa Ziehau 886841cdf08SSepherosa Ziehau rb->bnx_rx_refilled = 0; 887beedf5beSSepherosa Ziehau if (rb->bnx_rx_mbuf != NULL) { 888beedf5beSSepherosa Ziehau bus_dmamap_unload(std->bnx_rx_mtag, rb->bnx_rx_dmamap); 889beedf5beSSepherosa Ziehau m_freem(rb->bnx_rx_mbuf); 890beedf5beSSepherosa Ziehau rb->bnx_rx_mbuf = NULL; 8916c8d8eccSSepherosa Ziehau } 892beedf5beSSepherosa Ziehau bzero(&std->bnx_rx_std_ring[i], sizeof(struct bge_rx_bd)); 8936c8d8eccSSepherosa Ziehau } 8946c8d8eccSSepherosa Ziehau } 8956c8d8eccSSepherosa Ziehau 8966c8d8eccSSepherosa Ziehau static int 8976c8d8eccSSepherosa Ziehau bnx_init_rx_ring_jumbo(struct bnx_softc *sc) 8986c8d8eccSSepherosa Ziehau { 8996c8d8eccSSepherosa Ziehau struct bge_rcb *rcb; 9006c8d8eccSSepherosa Ziehau int i, error; 9016c8d8eccSSepherosa Ziehau 9026c8d8eccSSepherosa Ziehau for (i = 0; i < BGE_JUMBO_RX_RING_CNT; i++) { 9036c8d8eccSSepherosa Ziehau error = bnx_newbuf_jumbo(sc, i, 1); 9046c8d8eccSSepherosa Ziehau if (error) 9056c8d8eccSSepherosa Ziehau return error; 90687c7a7cfSSascha Wildner } 9076c8d8eccSSepherosa Ziehau 9086c8d8eccSSepherosa Ziehau sc->bnx_jumbo = BGE_JUMBO_RX_RING_CNT - 1; 9096c8d8eccSSepherosa Ziehau 9106c8d8eccSSepherosa Ziehau rcb = &sc->bnx_ldata.bnx_info.bnx_jumbo_rx_rcb; 9116c8d8eccSSepherosa Ziehau rcb->bge_maxlen_flags = BGE_RCB_MAXLEN_FLAGS(0, 0); 9126c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_RX_JUMBO_RCB_MAXLEN_FLAGS, rcb->bge_maxlen_flags); 9136c8d8eccSSepherosa Ziehau 9146c8d8eccSSepherosa Ziehau bnx_writembx(sc, BGE_MBX_RX_JUMBO_PROD_LO, sc->bnx_jumbo); 9156c8d8eccSSepherosa Ziehau 9166c8d8eccSSepherosa Ziehau return(0); 9176c8d8eccSSepherosa Ziehau } 9186c8d8eccSSepherosa Ziehau 9196c8d8eccSSepherosa Ziehau static void 9206c8d8eccSSepherosa Ziehau bnx_free_rx_ring_jumbo(struct bnx_softc *sc) 9216c8d8eccSSepherosa Ziehau { 9226c8d8eccSSepherosa Ziehau int i; 9236c8d8eccSSepherosa Ziehau 9246c8d8eccSSepherosa Ziehau for (i = 0; i < BGE_JUMBO_RX_RING_CNT; i++) { 925beedf5beSSepherosa Ziehau struct bnx_rx_buf *rc = &sc->bnx_cdata.bnx_rx_jumbo_chain[i]; 9266c8d8eccSSepherosa Ziehau 927beedf5beSSepherosa Ziehau if (rc->bnx_rx_mbuf != NULL) { 928beedf5beSSepherosa Ziehau m_freem(rc->bnx_rx_mbuf); 929beedf5beSSepherosa Ziehau rc->bnx_rx_mbuf = NULL; 9306c8d8eccSSepherosa Ziehau } 9316c8d8eccSSepherosa Ziehau bzero(&sc->bnx_ldata.bnx_rx_jumbo_ring[i], 9326c8d8eccSSepherosa Ziehau sizeof(struct bge_rx_bd)); 9336c8d8eccSSepherosa Ziehau } 9346c8d8eccSSepherosa Ziehau } 9356c8d8eccSSepherosa Ziehau 9366c8d8eccSSepherosa Ziehau static void 93733a04907SSepherosa Ziehau bnx_free_tx_ring(struct bnx_tx_ring *txr) 9386c8d8eccSSepherosa Ziehau { 9396c8d8eccSSepherosa Ziehau int i; 9406c8d8eccSSepherosa Ziehau 9416c8d8eccSSepherosa Ziehau for (i = 0; i < BGE_TX_RING_CNT; i++) { 942fa4b1067SSepherosa Ziehau struct bnx_tx_buf *buf = &txr->bnx_tx_buf[i]; 943fa4b1067SSepherosa Ziehau 944fa4b1067SSepherosa Ziehau if (buf->bnx_tx_mbuf != NULL) { 94533a04907SSepherosa Ziehau bus_dmamap_unload(txr->bnx_tx_mtag, 946fa4b1067SSepherosa Ziehau buf->bnx_tx_dmamap); 947fa4b1067SSepherosa Ziehau m_freem(buf->bnx_tx_mbuf); 948fa4b1067SSepherosa Ziehau buf->bnx_tx_mbuf = NULL; 9496c8d8eccSSepherosa Ziehau } 95033a04907SSepherosa Ziehau bzero(&txr->bnx_tx_ring[i], sizeof(struct bge_tx_bd)); 9516c8d8eccSSepherosa Ziehau } 95233a04907SSepherosa Ziehau txr->bnx_tx_saved_considx = BNX_TXCONS_UNSET; 9536c8d8eccSSepherosa Ziehau } 9546c8d8eccSSepherosa Ziehau 9556c8d8eccSSepherosa Ziehau static int 95633a04907SSepherosa Ziehau bnx_init_tx_ring(struct bnx_tx_ring *txr) 9576c8d8eccSSepherosa Ziehau { 958fa639b88SSepherosa Ziehau txr->bnx_tx_cnt = 0; 95933a04907SSepherosa Ziehau txr->bnx_tx_saved_considx = 0; 96033a04907SSepherosa Ziehau txr->bnx_tx_prodidx = 0; 9616c8d8eccSSepherosa Ziehau 9626c8d8eccSSepherosa Ziehau /* Initialize transmit producer index for host-memory send ring. */ 9638bd43d5dSSepherosa Ziehau bnx_writembx(txr->bnx_sc, txr->bnx_tx_mbx, txr->bnx_tx_prodidx); 9646c8d8eccSSepherosa Ziehau 9656c8d8eccSSepherosa Ziehau return(0); 9666c8d8eccSSepherosa Ziehau } 9676c8d8eccSSepherosa Ziehau 9686c8d8eccSSepherosa Ziehau static void 9696c8d8eccSSepherosa Ziehau bnx_setmulti(struct bnx_softc *sc) 9706c8d8eccSSepherosa Ziehau { 9716c8d8eccSSepherosa Ziehau struct ifnet *ifp; 9726c8d8eccSSepherosa Ziehau struct ifmultiaddr *ifma; 9736c8d8eccSSepherosa Ziehau uint32_t hashes[4] = { 0, 0, 0, 0 }; 9746c8d8eccSSepherosa Ziehau int h, i; 9756c8d8eccSSepherosa Ziehau 9766c8d8eccSSepherosa Ziehau ifp = &sc->arpcom.ac_if; 9776c8d8eccSSepherosa Ziehau 9786c8d8eccSSepherosa Ziehau if (ifp->if_flags & IFF_ALLMULTI || ifp->if_flags & IFF_PROMISC) { 9796c8d8eccSSepherosa Ziehau for (i = 0; i < 4; i++) 9806c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_MAR0 + (i * 4), 0xFFFFFFFF); 9816c8d8eccSSepherosa Ziehau return; 9826c8d8eccSSepherosa Ziehau } 9836c8d8eccSSepherosa Ziehau 9846c8d8eccSSepherosa Ziehau /* First, zot all the existing filters. */ 9856c8d8eccSSepherosa Ziehau for (i = 0; i < 4; i++) 9866c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_MAR0 + (i * 4), 0); 9876c8d8eccSSepherosa Ziehau 9886c8d8eccSSepherosa Ziehau /* Now program new ones. */ 9896c8d8eccSSepherosa Ziehau TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { 9906c8d8eccSSepherosa Ziehau if (ifma->ifma_addr->sa_family != AF_LINK) 9916c8d8eccSSepherosa Ziehau continue; 9926c8d8eccSSepherosa Ziehau h = ether_crc32_le( 9936c8d8eccSSepherosa Ziehau LLADDR((struct sockaddr_dl *)ifma->ifma_addr), 9946c8d8eccSSepherosa Ziehau ETHER_ADDR_LEN) & 0x7f; 9956c8d8eccSSepherosa Ziehau hashes[(h & 0x60) >> 5] |= 1 << (h & 0x1F); 9966c8d8eccSSepherosa Ziehau } 9976c8d8eccSSepherosa Ziehau 9986c8d8eccSSepherosa Ziehau for (i = 0; i < 4; i++) 9996c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_MAR0 + (i * 4), hashes[i]); 10006c8d8eccSSepherosa Ziehau } 10016c8d8eccSSepherosa Ziehau 10026c8d8eccSSepherosa Ziehau /* 10036c8d8eccSSepherosa Ziehau * Do endian, PCI and DMA initialization. Also check the on-board ROM 10046c8d8eccSSepherosa Ziehau * self-test results. 10056c8d8eccSSepherosa Ziehau */ 10066c8d8eccSSepherosa Ziehau static int 10076c8d8eccSSepherosa Ziehau bnx_chipinit(struct bnx_softc *sc) 10086c8d8eccSSepherosa Ziehau { 10096c8d8eccSSepherosa Ziehau uint32_t dma_rw_ctl, mode_ctl; 10106c8d8eccSSepherosa Ziehau int i; 10116c8d8eccSSepherosa Ziehau 10126c8d8eccSSepherosa Ziehau /* Set endian type before we access any non-PCI registers. */ 10136c8d8eccSSepherosa Ziehau pci_write_config(sc->bnx_dev, BGE_PCI_MISC_CTL, 10146c8d8eccSSepherosa Ziehau BGE_INIT | BGE_PCIMISCCTL_TAGGED_STATUS, 4); 10156c8d8eccSSepherosa Ziehau 10166c8d8eccSSepherosa Ziehau /* Clear the MAC control register */ 10176c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_MAC_MODE, 0); 10186c8d8eccSSepherosa Ziehau 10196c8d8eccSSepherosa Ziehau /* 10206c8d8eccSSepherosa Ziehau * Clear the MAC statistics block in the NIC's 10216c8d8eccSSepherosa Ziehau * internal memory. 10226c8d8eccSSepherosa Ziehau */ 10236c8d8eccSSepherosa Ziehau for (i = BGE_STATS_BLOCK; 10246c8d8eccSSepherosa Ziehau i < BGE_STATS_BLOCK_END + 1; i += sizeof(uint32_t)) 10256c8d8eccSSepherosa Ziehau BNX_MEMWIN_WRITE(sc, i, 0); 10266c8d8eccSSepherosa Ziehau 10276c8d8eccSSepherosa Ziehau for (i = BGE_STATUS_BLOCK; 10286c8d8eccSSepherosa Ziehau i < BGE_STATUS_BLOCK_END + 1; i += sizeof(uint32_t)) 10296c8d8eccSSepherosa Ziehau BNX_MEMWIN_WRITE(sc, i, 0); 10306c8d8eccSSepherosa Ziehau 1031d7872545SSepherosa Ziehau if (BNX_IS_57765_FAMILY(sc)) { 1032d7872545SSepherosa Ziehau uint32_t val; 1033d7872545SSepherosa Ziehau 1034d7872545SSepherosa Ziehau if (sc->bnx_chipid == BGE_CHIPID_BCM57765_A0) { 1035d7872545SSepherosa Ziehau mode_ctl = CSR_READ_4(sc, BGE_MODE_CTL); 1036d7872545SSepherosa Ziehau val = mode_ctl & ~BGE_MODECTL_PCIE_PORTS; 1037d7872545SSepherosa Ziehau 1038d7872545SSepherosa Ziehau /* Access the lower 1K of PL PCI-E block registers. */ 1039d7872545SSepherosa Ziehau CSR_WRITE_4(sc, BGE_MODE_CTL, 1040d7872545SSepherosa Ziehau val | BGE_MODECTL_PCIE_PL_SEL); 1041d7872545SSepherosa Ziehau 1042d7872545SSepherosa Ziehau val = CSR_READ_4(sc, BGE_PCIE_PL_LO_PHYCTL5); 1043d7872545SSepherosa Ziehau val |= BGE_PCIE_PL_LO_PHYCTL5_DIS_L2CLKREQ; 1044d7872545SSepherosa Ziehau CSR_WRITE_4(sc, BGE_PCIE_PL_LO_PHYCTL5, val); 1045d7872545SSepherosa Ziehau 1046d7872545SSepherosa Ziehau CSR_WRITE_4(sc, BGE_MODE_CTL, mode_ctl); 1047d7872545SSepherosa Ziehau } 1048d7872545SSepherosa Ziehau if (sc->bnx_chiprev != BGE_CHIPREV_57765_AX) { 10491749651bSSepherosa Ziehau /* Fix transmit hangs */ 10501749651bSSepherosa Ziehau val = CSR_READ_4(sc, BGE_CPMU_PADRNG_CTL); 10511749651bSSepherosa Ziehau val |= BGE_CPMU_PADRNG_CTL_RDIV2; 10521749651bSSepherosa Ziehau CSR_WRITE_4(sc, BGE_CPMU_PADRNG_CTL, val); 10531749651bSSepherosa Ziehau 1054d7872545SSepherosa Ziehau mode_ctl = CSR_READ_4(sc, BGE_MODE_CTL); 1055d7872545SSepherosa Ziehau val = mode_ctl & ~BGE_MODECTL_PCIE_PORTS; 1056d7872545SSepherosa Ziehau 1057d7872545SSepherosa Ziehau /* Access the lower 1K of DL PCI-E block registers. */ 1058d7872545SSepherosa Ziehau CSR_WRITE_4(sc, BGE_MODE_CTL, 1059d7872545SSepherosa Ziehau val | BGE_MODECTL_PCIE_DL_SEL); 1060d7872545SSepherosa Ziehau 1061d7872545SSepherosa Ziehau val = CSR_READ_4(sc, BGE_PCIE_DL_LO_FTSMAX); 1062d7872545SSepherosa Ziehau val &= ~BGE_PCIE_DL_LO_FTSMAX_MASK; 1063d7872545SSepherosa Ziehau val |= BGE_PCIE_DL_LO_FTSMAX_VAL; 1064d7872545SSepherosa Ziehau CSR_WRITE_4(sc, BGE_PCIE_DL_LO_FTSMAX, val); 1065d7872545SSepherosa Ziehau 1066d7872545SSepherosa Ziehau CSR_WRITE_4(sc, BGE_MODE_CTL, mode_ctl); 1067d7872545SSepherosa Ziehau } 1068d7872545SSepherosa Ziehau 1069d7872545SSepherosa Ziehau val = CSR_READ_4(sc, BGE_CPMU_LSPD_10MB_CLK); 1070d7872545SSepherosa Ziehau val &= ~BGE_CPMU_LSPD_10MB_MACCLK_MASK; 1071d7872545SSepherosa Ziehau val |= BGE_CPMU_LSPD_10MB_MACCLK_6_25; 1072d7872545SSepherosa Ziehau CSR_WRITE_4(sc, BGE_CPMU_LSPD_10MB_CLK, val); 1073d7872545SSepherosa Ziehau } 1074d7872545SSepherosa Ziehau 10752890cca3SSepherosa Ziehau /* 10762890cca3SSepherosa Ziehau * Set up the PCI DMA control register. 10772890cca3SSepherosa Ziehau */ 10782890cca3SSepherosa Ziehau dma_rw_ctl = pci_read_config(sc->bnx_dev, BGE_PCI_DMA_RW_CTL, 4); 10792890cca3SSepherosa Ziehau /* 10802890cca3SSepherosa Ziehau * Disable 32bytes cache alignment for DMA write to host memory 10812890cca3SSepherosa Ziehau * 10822890cca3SSepherosa Ziehau * NOTE: 10832890cca3SSepherosa Ziehau * 64bytes cache alignment for DMA write to host memory is still 10842890cca3SSepherosa Ziehau * enabled. 10852890cca3SSepherosa Ziehau */ 10862890cca3SSepherosa Ziehau dma_rw_ctl |= BGE_PCIDMARWCTL_DIS_CACHE_ALIGNMENT; 10876c8d8eccSSepherosa Ziehau if (sc->bnx_chipid == BGE_CHIPID_BCM57765_A0) 10886c8d8eccSSepherosa Ziehau dma_rw_ctl &= ~BGE_PCIDMARWCTL_CRDRDR_RDMA_MRRS_MSK; 10896c8d8eccSSepherosa Ziehau /* 10906c8d8eccSSepherosa Ziehau * Enable HW workaround for controllers that misinterpret 10916c8d8eccSSepherosa Ziehau * a status tag update and leave interrupts permanently 10926c8d8eccSSepherosa Ziehau * disabled. 10936c8d8eccSSepherosa Ziehau */ 10946c8d8eccSSepherosa Ziehau if (sc->bnx_asicrev != BGE_ASICREV_BCM5717 && 1095b96cbbb6SSepherosa Ziehau sc->bnx_asicrev != BGE_ASICREV_BCM5762 && 10962890cca3SSepherosa Ziehau !BNX_IS_57765_FAMILY(sc)) 10976c8d8eccSSepherosa Ziehau dma_rw_ctl |= BGE_PCIDMARWCTL_TAGGED_STATUS_WA; 10982890cca3SSepherosa Ziehau if (bootverbose) { 10992890cca3SSepherosa Ziehau if_printf(&sc->arpcom.ac_if, "DMA read/write %#x\n", 11002890cca3SSepherosa Ziehau dma_rw_ctl); 11016c8d8eccSSepherosa Ziehau } 11026c8d8eccSSepherosa Ziehau pci_write_config(sc->bnx_dev, BGE_PCI_DMA_RW_CTL, dma_rw_ctl, 4); 11036c8d8eccSSepherosa Ziehau 11046c8d8eccSSepherosa Ziehau /* 11056c8d8eccSSepherosa Ziehau * Set up general mode register. 11066c8d8eccSSepherosa Ziehau */ 11076c8d8eccSSepherosa Ziehau mode_ctl = bnx_dma_swap_options(sc) | BGE_MODECTL_MAC_ATTN_INTR | 11086c8d8eccSSepherosa Ziehau BGE_MODECTL_HOST_SEND_BDS | BGE_MODECTL_TX_NO_PHDR_CSUM; 11096c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_MODE_CTL, mode_ctl); 11106c8d8eccSSepherosa Ziehau 11116c8d8eccSSepherosa Ziehau /* 11126c8d8eccSSepherosa Ziehau * Disable memory write invalidate. Apparently it is not supported 11136c8d8eccSSepherosa Ziehau * properly by these devices. Also ensure that INTx isn't disabled, 11146c8d8eccSSepherosa Ziehau * as these chips need it even when using MSI. 11156c8d8eccSSepherosa Ziehau */ 11166c8d8eccSSepherosa Ziehau PCI_CLRBIT(sc->bnx_dev, BGE_PCI_CMD, 11176c8d8eccSSepherosa Ziehau (PCIM_CMD_MWRICEN | PCIM_CMD_INTxDIS), 4); 11186c8d8eccSSepherosa Ziehau 11196c8d8eccSSepherosa Ziehau /* Set the timer prescaler (always 66Mhz) */ 11206c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_MISC_CFG, 65 << 1/*BGE_32BITTIME_66MHZ*/); 11216c8d8eccSSepherosa Ziehau 11226c8d8eccSSepherosa Ziehau return(0); 11236c8d8eccSSepherosa Ziehau } 11246c8d8eccSSepherosa Ziehau 11256c8d8eccSSepherosa Ziehau static int 11266c8d8eccSSepherosa Ziehau bnx_blockinit(struct bnx_softc *sc) 11276c8d8eccSSepherosa Ziehau { 112833a04907SSepherosa Ziehau struct bnx_tx_ring *txr = &sc->bnx_tx_ring[0]; 1129beedf5beSSepherosa Ziehau struct bnx_rx_ret_ring *ret = &sc->bnx_rx_ret_ring[0]; 1130*0a806e3aSSepherosa Ziehau struct bnx_intr_data *intr = &sc->bnx_intr_data[0]; 11316c8d8eccSSepherosa Ziehau struct bge_rcb *rcb; 11326c8d8eccSSepherosa Ziehau bus_size_t vrcb; 11336c8d8eccSSepherosa Ziehau bge_hostaddr taddr; 11346c8d8eccSSepherosa Ziehau uint32_t val; 11356c8d8eccSSepherosa Ziehau int i, limit; 11366c8d8eccSSepherosa Ziehau 11376c8d8eccSSepherosa Ziehau /* 11386c8d8eccSSepherosa Ziehau * Initialize the memory window pointer register so that 11396c8d8eccSSepherosa Ziehau * we can access the first 32K of internal NIC RAM. This will 11406c8d8eccSSepherosa Ziehau * allow us to set up the TX send ring RCBs and the RX return 11416c8d8eccSSepherosa Ziehau * ring RCBs, plus other things which live in NIC memory. 11426c8d8eccSSepherosa Ziehau */ 11436c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_PCI_MEMWIN_BASEADDR, 0); 11446c8d8eccSSepherosa Ziehau 11456c8d8eccSSepherosa Ziehau /* Configure mbuf pool watermarks */ 1146f368d0d9SSepherosa Ziehau if (BNX_IS_57765_PLUS(sc)) { 11476c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_BMAN_MBUFPOOL_READDMA_LOWAT, 0x0); 11486c8d8eccSSepherosa Ziehau if (sc->arpcom.ac_if.if_mtu > ETHERMTU) { 11496c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_BMAN_MBUFPOOL_MACRX_LOWAT, 0x7e); 11506c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_BMAN_MBUFPOOL_HIWAT, 0xea); 11516c8d8eccSSepherosa Ziehau } else { 11526c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_BMAN_MBUFPOOL_MACRX_LOWAT, 0x2a); 11536c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_BMAN_MBUFPOOL_HIWAT, 0xa0); 11546c8d8eccSSepherosa Ziehau } 11556c8d8eccSSepherosa Ziehau } else { 11566c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_BMAN_MBUFPOOL_READDMA_LOWAT, 0x0); 11576c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_BMAN_MBUFPOOL_MACRX_LOWAT, 0x10); 11586c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_BMAN_MBUFPOOL_HIWAT, 0x60); 11596c8d8eccSSepherosa Ziehau } 11606c8d8eccSSepherosa Ziehau 11616c8d8eccSSepherosa Ziehau /* Configure DMA resource watermarks */ 11626c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_BMAN_DMA_DESCPOOL_LOWAT, 5); 11636c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_BMAN_DMA_DESCPOOL_HIWAT, 10); 11646c8d8eccSSepherosa Ziehau 11656c8d8eccSSepherosa Ziehau /* Enable buffer manager */ 11666c8d8eccSSepherosa Ziehau val = BGE_BMANMODE_ENABLE | BGE_BMANMODE_LOMBUF_ATTN; 11676c8d8eccSSepherosa Ziehau /* 11686c8d8eccSSepherosa Ziehau * Change the arbitration algorithm of TXMBUF read request to 11696c8d8eccSSepherosa Ziehau * round-robin instead of priority based for BCM5719. When 11706c8d8eccSSepherosa Ziehau * TXFIFO is almost empty, RDMA will hold its request until 11716c8d8eccSSepherosa Ziehau * TXFIFO is not almost empty. 11726c8d8eccSSepherosa Ziehau */ 11736c8d8eccSSepherosa Ziehau if (sc->bnx_asicrev == BGE_ASICREV_BCM5719) 11746c8d8eccSSepherosa Ziehau val |= BGE_BMANMODE_NO_TX_UNDERRUN; 1175e5eebe34SSepherosa Ziehau if (sc->bnx_asicrev == BGE_ASICREV_BCM5717 || 1176e5eebe34SSepherosa Ziehau sc->bnx_chipid == BGE_CHIPID_BCM5719_A0 || 1177e5eebe34SSepherosa Ziehau sc->bnx_chipid == BGE_CHIPID_BCM5720_A0) 1178e5eebe34SSepherosa Ziehau val |= BGE_BMANMODE_LOMBUF_ATTN; 11796c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_BMAN_MODE, val); 11806c8d8eccSSepherosa Ziehau 11816c8d8eccSSepherosa Ziehau /* Poll for buffer manager start indication */ 11826c8d8eccSSepherosa Ziehau for (i = 0; i < BNX_TIMEOUT; i++) { 11836c8d8eccSSepherosa Ziehau if (CSR_READ_4(sc, BGE_BMAN_MODE) & BGE_BMANMODE_ENABLE) 11846c8d8eccSSepherosa Ziehau break; 11856c8d8eccSSepherosa Ziehau DELAY(10); 11866c8d8eccSSepherosa Ziehau } 11876c8d8eccSSepherosa Ziehau 11886c8d8eccSSepherosa Ziehau if (i == BNX_TIMEOUT) { 11896c8d8eccSSepherosa Ziehau if_printf(&sc->arpcom.ac_if, 11906c8d8eccSSepherosa Ziehau "buffer manager failed to start\n"); 11916c8d8eccSSepherosa Ziehau return(ENXIO); 11926c8d8eccSSepherosa Ziehau } 11936c8d8eccSSepherosa Ziehau 11946c8d8eccSSepherosa Ziehau /* Enable flow-through queues */ 11956c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_FTQ_RESET, 0xFFFFFFFF); 11966c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_FTQ_RESET, 0); 11976c8d8eccSSepherosa Ziehau 11986c8d8eccSSepherosa Ziehau /* Wait until queue initialization is complete */ 11996c8d8eccSSepherosa Ziehau for (i = 0; i < BNX_TIMEOUT; i++) { 12006c8d8eccSSepherosa Ziehau if (CSR_READ_4(sc, BGE_FTQ_RESET) == 0) 12016c8d8eccSSepherosa Ziehau break; 12026c8d8eccSSepherosa Ziehau DELAY(10); 12036c8d8eccSSepherosa Ziehau } 12046c8d8eccSSepherosa Ziehau 12056c8d8eccSSepherosa Ziehau if (i == BNX_TIMEOUT) { 12066c8d8eccSSepherosa Ziehau if_printf(&sc->arpcom.ac_if, 12076c8d8eccSSepherosa Ziehau "flow-through queue init failed\n"); 12086c8d8eccSSepherosa Ziehau return(ENXIO); 12096c8d8eccSSepherosa Ziehau } 12106c8d8eccSSepherosa Ziehau 12116c8d8eccSSepherosa Ziehau /* 12126c8d8eccSSepherosa Ziehau * Summary of rings supported by the controller: 12136c8d8eccSSepherosa Ziehau * 12146c8d8eccSSepherosa Ziehau * Standard Receive Producer Ring 12156c8d8eccSSepherosa Ziehau * - This ring is used to feed receive buffers for "standard" 12166c8d8eccSSepherosa Ziehau * sized frames (typically 1536 bytes) to the controller. 12176c8d8eccSSepherosa Ziehau * 12186c8d8eccSSepherosa Ziehau * Jumbo Receive Producer Ring 12196c8d8eccSSepherosa Ziehau * - This ring is used to feed receive buffers for jumbo sized 12206c8d8eccSSepherosa Ziehau * frames (i.e. anything bigger than the "standard" frames) 12216c8d8eccSSepherosa Ziehau * to the controller. 12226c8d8eccSSepherosa Ziehau * 12236c8d8eccSSepherosa Ziehau * Mini Receive Producer Ring 12246c8d8eccSSepherosa Ziehau * - This ring is used to feed receive buffers for "mini" 12256c8d8eccSSepherosa Ziehau * sized frames to the controller. 12266c8d8eccSSepherosa Ziehau * - This feature required external memory for the controller 12276c8d8eccSSepherosa Ziehau * but was never used in a production system. Should always 12286c8d8eccSSepherosa Ziehau * be disabled. 12296c8d8eccSSepherosa Ziehau * 12306c8d8eccSSepherosa Ziehau * Receive Return Ring 12316c8d8eccSSepherosa Ziehau * - After the controller has placed an incoming frame into a 12326c8d8eccSSepherosa Ziehau * receive buffer that buffer is moved into a receive return 12336c8d8eccSSepherosa Ziehau * ring. The driver is then responsible to passing the 12346c8d8eccSSepherosa Ziehau * buffer up to the stack. Many versions of the controller 12356c8d8eccSSepherosa Ziehau * support multiple RR rings. 12366c8d8eccSSepherosa Ziehau * 12376c8d8eccSSepherosa Ziehau * Send Ring 12386c8d8eccSSepherosa Ziehau * - This ring is used for outgoing frames. Many versions of 12396c8d8eccSSepherosa Ziehau * the controller support multiple send rings. 12406c8d8eccSSepherosa Ziehau */ 12416c8d8eccSSepherosa Ziehau 12426c8d8eccSSepherosa Ziehau /* Initialize the standard receive producer ring control block. */ 12436c8d8eccSSepherosa Ziehau rcb = &sc->bnx_ldata.bnx_info.bnx_std_rx_rcb; 12446c8d8eccSSepherosa Ziehau rcb->bge_hostaddr.bge_addr_lo = 1245beedf5beSSepherosa Ziehau BGE_ADDR_LO(sc->bnx_rx_std_ring.bnx_rx_std_ring_paddr); 12466c8d8eccSSepherosa Ziehau rcb->bge_hostaddr.bge_addr_hi = 1247beedf5beSSepherosa Ziehau BGE_ADDR_HI(sc->bnx_rx_std_ring.bnx_rx_std_ring_paddr); 1248f368d0d9SSepherosa Ziehau if (BNX_IS_57765_PLUS(sc)) { 12496c8d8eccSSepherosa Ziehau /* 12506c8d8eccSSepherosa Ziehau * Bits 31-16: Programmable ring size (2048, 1024, 512, .., 32) 12516c8d8eccSSepherosa Ziehau * Bits 15-2 : Maximum RX frame size 12526c8d8eccSSepherosa Ziehau * Bit 1 : 1 = Ring Disabled, 0 = Ring ENabled 12536c8d8eccSSepherosa Ziehau * Bit 0 : Reserved 12546c8d8eccSSepherosa Ziehau */ 12556c8d8eccSSepherosa Ziehau rcb->bge_maxlen_flags = 12566c8d8eccSSepherosa Ziehau BGE_RCB_MAXLEN_FLAGS(512, BNX_MAX_FRAMELEN << 2); 12576c8d8eccSSepherosa Ziehau } else { 12586c8d8eccSSepherosa Ziehau /* 12596c8d8eccSSepherosa Ziehau * Bits 31-16: Programmable ring size (512, 256, 128, 64, 32) 12606c8d8eccSSepherosa Ziehau * Bits 15-2 : Reserved (should be 0) 12616c8d8eccSSepherosa Ziehau * Bit 1 : 1 = Ring Disabled, 0 = Ring Enabled 12626c8d8eccSSepherosa Ziehau * Bit 0 : Reserved 12636c8d8eccSSepherosa Ziehau */ 12646c8d8eccSSepherosa Ziehau rcb->bge_maxlen_flags = BGE_RCB_MAXLEN_FLAGS(512, 0); 12656c8d8eccSSepherosa Ziehau } 1266303fdc72SSepherosa Ziehau if (BNX_IS_5717_PLUS(sc)) 12676c8d8eccSSepherosa Ziehau rcb->bge_nicaddr = BGE_STD_RX_RINGS_5717; 12686c8d8eccSSepherosa Ziehau else 12696c8d8eccSSepherosa Ziehau rcb->bge_nicaddr = BGE_STD_RX_RINGS; 12706c8d8eccSSepherosa Ziehau /* Write the standard receive producer ring control block. */ 12716c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_RX_STD_RCB_HADDR_HI, rcb->bge_hostaddr.bge_addr_hi); 12726c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_RX_STD_RCB_HADDR_LO, rcb->bge_hostaddr.bge_addr_lo); 12736c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_RX_STD_RCB_MAXLEN_FLAGS, rcb->bge_maxlen_flags); 12746c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_RX_STD_RCB_NICADDR, rcb->bge_nicaddr); 12756c8d8eccSSepherosa Ziehau /* Reset the standard receive producer ring producer index. */ 12766c8d8eccSSepherosa Ziehau bnx_writembx(sc, BGE_MBX_RX_STD_PROD_LO, 0); 12776c8d8eccSSepherosa Ziehau 12786c8d8eccSSepherosa Ziehau /* 12796c8d8eccSSepherosa Ziehau * Initialize the jumbo RX producer ring control 12806c8d8eccSSepherosa Ziehau * block. We set the 'ring disabled' bit in the 12816c8d8eccSSepherosa Ziehau * flags field until we're actually ready to start 12826c8d8eccSSepherosa Ziehau * using this ring (i.e. once we set the MTU 12836c8d8eccSSepherosa Ziehau * high enough to require it). 12846c8d8eccSSepherosa Ziehau */ 12856c8d8eccSSepherosa Ziehau if (BNX_IS_JUMBO_CAPABLE(sc)) { 12866c8d8eccSSepherosa Ziehau rcb = &sc->bnx_ldata.bnx_info.bnx_jumbo_rx_rcb; 12876c8d8eccSSepherosa Ziehau /* Get the jumbo receive producer ring RCB parameters. */ 12886c8d8eccSSepherosa Ziehau rcb->bge_hostaddr.bge_addr_lo = 12896c8d8eccSSepherosa Ziehau BGE_ADDR_LO(sc->bnx_ldata.bnx_rx_jumbo_ring_paddr); 12906c8d8eccSSepherosa Ziehau rcb->bge_hostaddr.bge_addr_hi = 12916c8d8eccSSepherosa Ziehau BGE_ADDR_HI(sc->bnx_ldata.bnx_rx_jumbo_ring_paddr); 12926c8d8eccSSepherosa Ziehau rcb->bge_maxlen_flags = 12936c8d8eccSSepherosa Ziehau BGE_RCB_MAXLEN_FLAGS(BNX_MAX_FRAMELEN, 12946c8d8eccSSepherosa Ziehau BGE_RCB_FLAG_RING_DISABLED); 1295303fdc72SSepherosa Ziehau if (BNX_IS_5717_PLUS(sc)) 12966c8d8eccSSepherosa Ziehau rcb->bge_nicaddr = BGE_JUMBO_RX_RINGS_5717; 12976c8d8eccSSepherosa Ziehau else 12986c8d8eccSSepherosa Ziehau rcb->bge_nicaddr = BGE_JUMBO_RX_RINGS; 12996c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_RX_JUMBO_RCB_HADDR_HI, 13006c8d8eccSSepherosa Ziehau rcb->bge_hostaddr.bge_addr_hi); 13016c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_RX_JUMBO_RCB_HADDR_LO, 13026c8d8eccSSepherosa Ziehau rcb->bge_hostaddr.bge_addr_lo); 13036c8d8eccSSepherosa Ziehau /* Program the jumbo receive producer ring RCB parameters. */ 13046c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_RX_JUMBO_RCB_MAXLEN_FLAGS, 13056c8d8eccSSepherosa Ziehau rcb->bge_maxlen_flags); 13066c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_RX_JUMBO_RCB_NICADDR, rcb->bge_nicaddr); 13076c8d8eccSSepherosa Ziehau /* Reset the jumbo receive producer ring producer index. */ 13086c8d8eccSSepherosa Ziehau bnx_writembx(sc, BGE_MBX_RX_JUMBO_PROD_LO, 0); 13096c8d8eccSSepherosa Ziehau } 13106c8d8eccSSepherosa Ziehau 13116c8d8eccSSepherosa Ziehau /* 13126c8d8eccSSepherosa Ziehau * The BD ring replenish thresholds control how often the 13136c8d8eccSSepherosa Ziehau * hardware fetches new BD's from the producer rings in host 13146c8d8eccSSepherosa Ziehau * memory. Setting the value too low on a busy system can 13156c8d8eccSSepherosa Ziehau * starve the hardware and recue the throughpout. 13166c8d8eccSSepherosa Ziehau * 13176c8d8eccSSepherosa Ziehau * Set the BD ring replentish thresholds. The recommended 13186c8d8eccSSepherosa Ziehau * values are 1/8th the number of descriptors allocated to 13196c8d8eccSSepherosa Ziehau * each ring. 13206c8d8eccSSepherosa Ziehau */ 13216c8d8eccSSepherosa Ziehau val = 8; 13226c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_RBDI_STD_REPL_THRESH, val); 13236c8d8eccSSepherosa Ziehau if (BNX_IS_JUMBO_CAPABLE(sc)) { 13246c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_RBDI_JUMBO_REPL_THRESH, 13256c8d8eccSSepherosa Ziehau BGE_JUMBO_RX_RING_CNT/8); 13266c8d8eccSSepherosa Ziehau } 1327f368d0d9SSepherosa Ziehau if (BNX_IS_57765_PLUS(sc)) { 13286c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_STD_REPLENISH_LWM, 32); 13296c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_JMB_REPLENISH_LWM, 16); 13306c8d8eccSSepherosa Ziehau } 13316c8d8eccSSepherosa Ziehau 13326c8d8eccSSepherosa Ziehau /* 13336c8d8eccSSepherosa Ziehau * Disable all send rings by setting the 'ring disabled' bit 13346c8d8eccSSepherosa Ziehau * in the flags field of all the TX send ring control blocks, 13356c8d8eccSSepherosa Ziehau * located in NIC memory. 13366c8d8eccSSepherosa Ziehau */ 133780969639SSepherosa Ziehau if (BNX_IS_5717_PLUS(sc)) 133880969639SSepherosa Ziehau limit = 4; 1339b96cbbb6SSepherosa Ziehau else if (BNX_IS_57765_FAMILY(sc) || 1340b96cbbb6SSepherosa Ziehau sc->bnx_asicrev == BGE_ASICREV_BCM5762) 13414f23029eSSepherosa Ziehau limit = 2; 134280969639SSepherosa Ziehau else 13436c8d8eccSSepherosa Ziehau limit = 1; 13446c8d8eccSSepherosa Ziehau vrcb = BGE_MEMWIN_START + BGE_SEND_RING_RCB; 13456c8d8eccSSepherosa Ziehau for (i = 0; i < limit; i++) { 13466c8d8eccSSepherosa Ziehau RCB_WRITE_4(sc, vrcb, bge_maxlen_flags, 13476c8d8eccSSepherosa Ziehau BGE_RCB_MAXLEN_FLAGS(0, BGE_RCB_FLAG_RING_DISABLED)); 13486c8d8eccSSepherosa Ziehau RCB_WRITE_4(sc, vrcb, bge_nicaddr, 0); 13496c8d8eccSSepherosa Ziehau vrcb += sizeof(struct bge_rcb); 13506c8d8eccSSepherosa Ziehau } 13516c8d8eccSSepherosa Ziehau 13526c8d8eccSSepherosa Ziehau /* Configure send ring RCB 0 (we use only the first ring) */ 13536c8d8eccSSepherosa Ziehau vrcb = BGE_MEMWIN_START + BGE_SEND_RING_RCB; 135433a04907SSepherosa Ziehau BGE_HOSTADDR(taddr, txr->bnx_tx_ring_paddr); 13556c8d8eccSSepherosa Ziehau RCB_WRITE_4(sc, vrcb, bge_hostaddr.bge_addr_hi, taddr.bge_addr_hi); 13566c8d8eccSSepherosa Ziehau RCB_WRITE_4(sc, vrcb, bge_hostaddr.bge_addr_lo, taddr.bge_addr_lo); 1357303fdc72SSepherosa Ziehau if (BNX_IS_5717_PLUS(sc)) { 13586c8d8eccSSepherosa Ziehau RCB_WRITE_4(sc, vrcb, bge_nicaddr, BGE_SEND_RING_5717); 13596c8d8eccSSepherosa Ziehau } else { 13606c8d8eccSSepherosa Ziehau RCB_WRITE_4(sc, vrcb, bge_nicaddr, 13616c8d8eccSSepherosa Ziehau BGE_NIC_TXRING_ADDR(0, BGE_TX_RING_CNT)); 13626c8d8eccSSepherosa Ziehau } 13636c8d8eccSSepherosa Ziehau RCB_WRITE_4(sc, vrcb, bge_maxlen_flags, 13646c8d8eccSSepherosa Ziehau BGE_RCB_MAXLEN_FLAGS(BGE_TX_RING_CNT, 0)); 13656c8d8eccSSepherosa Ziehau 13666c8d8eccSSepherosa Ziehau /* 13676c8d8eccSSepherosa Ziehau * Disable all receive return rings by setting the 13686c8d8eccSSepherosa Ziehau * 'ring disabled' bit in the flags field of all the receive 13696c8d8eccSSepherosa Ziehau * return ring control blocks, located in NIC memory. 13706c8d8eccSSepherosa Ziehau */ 137180969639SSepherosa Ziehau if (BNX_IS_5717_PLUS(sc)) { 13726c8d8eccSSepherosa Ziehau /* Should be 17, use 16 until we get an SRAM map. */ 13736c8d8eccSSepherosa Ziehau limit = 16; 1374b96cbbb6SSepherosa Ziehau } else if (BNX_IS_57765_FAMILY(sc) || 1375b96cbbb6SSepherosa Ziehau sc->bnx_asicrev == BGE_ASICREV_BCM5762) { 13766c8d8eccSSepherosa Ziehau limit = 4; 13776c8d8eccSSepherosa Ziehau } else { 13786c8d8eccSSepherosa Ziehau limit = 1; 13796c8d8eccSSepherosa Ziehau } 13806c8d8eccSSepherosa Ziehau /* Disable all receive return rings. */ 13816c8d8eccSSepherosa Ziehau vrcb = BGE_MEMWIN_START + BGE_RX_RETURN_RING_RCB; 13826c8d8eccSSepherosa Ziehau for (i = 0; i < limit; i++) { 13836c8d8eccSSepherosa Ziehau RCB_WRITE_4(sc, vrcb, bge_hostaddr.bge_addr_hi, 0); 13846c8d8eccSSepherosa Ziehau RCB_WRITE_4(sc, vrcb, bge_hostaddr.bge_addr_lo, 0); 13856c8d8eccSSepherosa Ziehau RCB_WRITE_4(sc, vrcb, bge_maxlen_flags, 13866c8d8eccSSepherosa Ziehau BGE_RCB_FLAG_RING_DISABLED); 13876c8d8eccSSepherosa Ziehau RCB_WRITE_4(sc, vrcb, bge_nicaddr, 0); 13886c8d8eccSSepherosa Ziehau bnx_writembx(sc, BGE_MBX_RX_CONS0_LO + 13896c8d8eccSSepherosa Ziehau (i * (sizeof(uint64_t))), 0); 13906c8d8eccSSepherosa Ziehau vrcb += sizeof(struct bge_rcb); 13916c8d8eccSSepherosa Ziehau } 13926c8d8eccSSepherosa Ziehau 13936c8d8eccSSepherosa Ziehau /* 13946c8d8eccSSepherosa Ziehau * Set up receive return ring 0. Note that the NIC address 13956c8d8eccSSepherosa Ziehau * for RX return rings is 0x0. The return rings live entirely 13966c8d8eccSSepherosa Ziehau * within the host, so the nicaddr field in the RCB isn't used. 13976c8d8eccSSepherosa Ziehau */ 13986c8d8eccSSepherosa Ziehau vrcb = BGE_MEMWIN_START + BGE_RX_RETURN_RING_RCB; 1399beedf5beSSepherosa Ziehau BGE_HOSTADDR(taddr, ret->bnx_rx_ret_ring_paddr); 14006c8d8eccSSepherosa Ziehau RCB_WRITE_4(sc, vrcb, bge_hostaddr.bge_addr_hi, taddr.bge_addr_hi); 14016c8d8eccSSepherosa Ziehau RCB_WRITE_4(sc, vrcb, bge_hostaddr.bge_addr_lo, taddr.bge_addr_lo); 14026c8d8eccSSepherosa Ziehau RCB_WRITE_4(sc, vrcb, bge_nicaddr, 0); 14036c8d8eccSSepherosa Ziehau RCB_WRITE_4(sc, vrcb, bge_maxlen_flags, 1404e0f74fc8SSepherosa Ziehau BGE_RCB_MAXLEN_FLAGS(BNX_RETURN_RING_CNT, 0)); 14056c8d8eccSSepherosa Ziehau 14066c8d8eccSSepherosa Ziehau /* Set random backoff seed for TX */ 14076c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_TX_RANDOM_BACKOFF, 14086c8d8eccSSepherosa Ziehau sc->arpcom.ac_enaddr[0] + sc->arpcom.ac_enaddr[1] + 14096c8d8eccSSepherosa Ziehau sc->arpcom.ac_enaddr[2] + sc->arpcom.ac_enaddr[3] + 14106c8d8eccSSepherosa Ziehau sc->arpcom.ac_enaddr[4] + sc->arpcom.ac_enaddr[5] + 14116c8d8eccSSepherosa Ziehau BGE_TX_BACKOFF_SEED_MASK); 14126c8d8eccSSepherosa Ziehau 14136c8d8eccSSepherosa Ziehau /* Set inter-packet gap */ 14146c8d8eccSSepherosa Ziehau val = 0x2620; 1415b96cbbb6SSepherosa Ziehau if (sc->bnx_asicrev == BGE_ASICREV_BCM5720 || 1416b96cbbb6SSepherosa Ziehau sc->bnx_asicrev == BGE_ASICREV_BCM5762) { 14176c8d8eccSSepherosa Ziehau val |= CSR_READ_4(sc, BGE_TX_LENGTHS) & 14186c8d8eccSSepherosa Ziehau (BGE_TXLEN_JMB_FRM_LEN_MSK | BGE_TXLEN_CNT_DN_VAL_MSK); 14196c8d8eccSSepherosa Ziehau } 14206c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_TX_LENGTHS, val); 14216c8d8eccSSepherosa Ziehau 14226c8d8eccSSepherosa Ziehau /* 14236c8d8eccSSepherosa Ziehau * Specify which ring to use for packets that don't match 14246c8d8eccSSepherosa Ziehau * any RX rules. 14256c8d8eccSSepherosa Ziehau */ 14266c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_RX_RULES_CFG, 0x08); 14276c8d8eccSSepherosa Ziehau 14286c8d8eccSSepherosa Ziehau /* 14296c8d8eccSSepherosa Ziehau * Configure number of RX lists. One interrupt distribution 14306c8d8eccSSepherosa Ziehau * list, sixteen active lists, one bad frames class. 14316c8d8eccSSepherosa Ziehau */ 14326c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_RXLP_CFG, 0x181); 14336c8d8eccSSepherosa Ziehau 14346c8d8eccSSepherosa Ziehau /* Inialize RX list placement stats mask. */ 14356c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_RXLP_STATS_ENABLE_MASK, 0x007FFFFF); 14366c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_RXLP_STATS_CTL, 0x1); 14376c8d8eccSSepherosa Ziehau 14386c8d8eccSSepherosa Ziehau /* Disable host coalescing until we get it set up */ 14396c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_HCC_MODE, 0x00000000); 14406c8d8eccSSepherosa Ziehau 14416c8d8eccSSepherosa Ziehau /* Poll to make sure it's shut down. */ 14426c8d8eccSSepherosa Ziehau for (i = 0; i < BNX_TIMEOUT; i++) { 14436c8d8eccSSepherosa Ziehau if (!(CSR_READ_4(sc, BGE_HCC_MODE) & BGE_HCCMODE_ENABLE)) 14446c8d8eccSSepherosa Ziehau break; 14456c8d8eccSSepherosa Ziehau DELAY(10); 14466c8d8eccSSepherosa Ziehau } 14476c8d8eccSSepherosa Ziehau 14486c8d8eccSSepherosa Ziehau if (i == BNX_TIMEOUT) { 14496c8d8eccSSepherosa Ziehau if_printf(&sc->arpcom.ac_if, 14506c8d8eccSSepherosa Ziehau "host coalescing engine failed to idle\n"); 14516c8d8eccSSepherosa Ziehau return(ENXIO); 14526c8d8eccSSepherosa Ziehau } 14536c8d8eccSSepherosa Ziehau 14546c8d8eccSSepherosa Ziehau /* Set up host coalescing defaults */ 14556c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_HCC_RX_COAL_TICKS, sc->bnx_rx_coal_ticks); 14566c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_HCC_TX_COAL_TICKS, sc->bnx_tx_coal_ticks); 14576c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_HCC_RX_MAX_COAL_BDS, sc->bnx_rx_coal_bds); 14586c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_HCC_TX_MAX_COAL_BDS, sc->bnx_tx_coal_bds); 14596c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_HCC_RX_MAX_COAL_BDS_INT, sc->bnx_rx_coal_bds_int); 14606c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_HCC_TX_MAX_COAL_BDS_INT, sc->bnx_tx_coal_bds_int); 14616c8d8eccSSepherosa Ziehau 14626c8d8eccSSepherosa Ziehau /* Set up address of status block */ 1463*0a806e3aSSepherosa Ziehau bzero(intr->bnx_status_block, BGE_STATUS_BLK_SZ); 14646c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_HCC_STATUSBLK_ADDR_HI, 1465*0a806e3aSSepherosa Ziehau BGE_ADDR_HI(intr->bnx_status_block_paddr)); 14666c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_HCC_STATUSBLK_ADDR_LO, 1467*0a806e3aSSepherosa Ziehau BGE_ADDR_LO(intr->bnx_status_block_paddr)); 14686c8d8eccSSepherosa Ziehau 14696c8d8eccSSepherosa Ziehau /* Set up status block partail update size. */ 14706c8d8eccSSepherosa Ziehau val = BGE_STATBLKSZ_32BYTE; 14716c8d8eccSSepherosa Ziehau #if 0 14726c8d8eccSSepherosa Ziehau /* 14736c8d8eccSSepherosa Ziehau * Does not seem to have visible effect in both 14746c8d8eccSSepherosa Ziehau * bulk data (1472B UDP datagram) and tiny data 14756c8d8eccSSepherosa Ziehau * (18B UDP datagram) TX tests. 14766c8d8eccSSepherosa Ziehau */ 14776c8d8eccSSepherosa Ziehau val |= BGE_HCCMODE_CLRTICK_TX; 14786c8d8eccSSepherosa Ziehau #endif 14796c8d8eccSSepherosa Ziehau /* Turn on host coalescing state machine */ 14806c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_HCC_MODE, val | BGE_HCCMODE_ENABLE); 14816c8d8eccSSepherosa Ziehau 14826c8d8eccSSepherosa Ziehau /* Turn on RX BD completion state machine and enable attentions */ 14836c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_RBDC_MODE, 14846c8d8eccSSepherosa Ziehau BGE_RBDCMODE_ENABLE|BGE_RBDCMODE_ATTN); 14856c8d8eccSSepherosa Ziehau 14866c8d8eccSSepherosa Ziehau /* Turn on RX list placement state machine */ 14876c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_RXLP_MODE, BGE_RXLPMODE_ENABLE); 14886c8d8eccSSepherosa Ziehau 14896c8d8eccSSepherosa Ziehau val = BGE_MACMODE_TXDMA_ENB | BGE_MACMODE_RXDMA_ENB | 14906c8d8eccSSepherosa Ziehau BGE_MACMODE_RX_STATS_CLEAR | BGE_MACMODE_TX_STATS_CLEAR | 14916c8d8eccSSepherosa Ziehau BGE_MACMODE_RX_STATS_ENB | BGE_MACMODE_TX_STATS_ENB | 14926c8d8eccSSepherosa Ziehau BGE_MACMODE_FRMHDR_DMA_ENB; 14936c8d8eccSSepherosa Ziehau 14946c8d8eccSSepherosa Ziehau if (sc->bnx_flags & BNX_FLAG_TBI) 14956c8d8eccSSepherosa Ziehau val |= BGE_PORTMODE_TBI; 14966c8d8eccSSepherosa Ziehau else if (sc->bnx_flags & BNX_FLAG_MII_SERDES) 14976c8d8eccSSepherosa Ziehau val |= BGE_PORTMODE_GMII; 14986c8d8eccSSepherosa Ziehau else 14996c8d8eccSSepherosa Ziehau val |= BGE_PORTMODE_MII; 15006c8d8eccSSepherosa Ziehau 15016c8d8eccSSepherosa Ziehau /* Turn on DMA, clear stats */ 15026c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_MAC_MODE, val); 15036c8d8eccSSepherosa Ziehau 15046c8d8eccSSepherosa Ziehau /* Set misc. local control, enable interrupts on attentions */ 15056c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_MISC_LOCAL_CTL, BGE_MLC_INTR_ONATTN); 15066c8d8eccSSepherosa Ziehau 15076c8d8eccSSepherosa Ziehau #ifdef notdef 15086c8d8eccSSepherosa Ziehau /* Assert GPIO pins for PHY reset */ 15096c8d8eccSSepherosa Ziehau BNX_SETBIT(sc, BGE_MISC_LOCAL_CTL, BGE_MLC_MISCIO_OUT0| 15106c8d8eccSSepherosa Ziehau BGE_MLC_MISCIO_OUT1|BGE_MLC_MISCIO_OUT2); 15116c8d8eccSSepherosa Ziehau BNX_SETBIT(sc, BGE_MISC_LOCAL_CTL, BGE_MLC_MISCIO_OUTEN0| 15126c8d8eccSSepherosa Ziehau BGE_MLC_MISCIO_OUTEN1|BGE_MLC_MISCIO_OUTEN2); 15136c8d8eccSSepherosa Ziehau #endif 15146c8d8eccSSepherosa Ziehau 15156c8d8eccSSepherosa Ziehau /* Turn on write DMA state machine */ 15166c8d8eccSSepherosa Ziehau val = BGE_WDMAMODE_ENABLE|BGE_WDMAMODE_ALL_ATTNS; 15176c8d8eccSSepherosa Ziehau /* Enable host coalescing bug fix. */ 15186c8d8eccSSepherosa Ziehau val |= BGE_WDMAMODE_STATUS_TAG_FIX; 15196c8d8eccSSepherosa Ziehau if (sc->bnx_asicrev == BGE_ASICREV_BCM5785) { 15206c8d8eccSSepherosa Ziehau /* Request larger DMA burst size to get better performance. */ 15216c8d8eccSSepherosa Ziehau val |= BGE_WDMAMODE_BURST_ALL_DATA; 15226c8d8eccSSepherosa Ziehau } 15236c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_WDMA_MODE, val); 15246c8d8eccSSepherosa Ziehau DELAY(40); 15256c8d8eccSSepherosa Ziehau 15263730a14dSSepherosa Ziehau if (BNX_IS_57765_PLUS(sc)) { 1527b96cbbb6SSepherosa Ziehau uint32_t dmactl, dmactl_reg; 15286c8d8eccSSepherosa Ziehau 1529b96cbbb6SSepherosa Ziehau if (sc->bnx_asicrev == BGE_ASICREV_BCM5762) 1530b96cbbb6SSepherosa Ziehau dmactl_reg = BGE_RDMA_RSRVCTRL2; 1531b96cbbb6SSepherosa Ziehau else 1532b96cbbb6SSepherosa Ziehau dmactl_reg = BGE_RDMA_RSRVCTRL; 1533b96cbbb6SSepherosa Ziehau 1534b96cbbb6SSepherosa Ziehau dmactl = CSR_READ_4(sc, dmactl_reg); 15356c8d8eccSSepherosa Ziehau /* 15366c8d8eccSSepherosa Ziehau * Adjust tx margin to prevent TX data corruption and 15376c8d8eccSSepherosa Ziehau * fix internal FIFO overflow. 15386c8d8eccSSepherosa Ziehau */ 15396c8d8eccSSepherosa Ziehau if (sc->bnx_asicrev == BGE_ASICREV_BCM5719 || 1540b96cbbb6SSepherosa Ziehau sc->bnx_asicrev == BGE_ASICREV_BCM5720 || 1541b96cbbb6SSepherosa Ziehau sc->bnx_asicrev == BGE_ASICREV_BCM5762) { 15426c8d8eccSSepherosa Ziehau dmactl &= ~(BGE_RDMA_RSRVCTRL_FIFO_LWM_MASK | 15436c8d8eccSSepherosa Ziehau BGE_RDMA_RSRVCTRL_FIFO_HWM_MASK | 15446c8d8eccSSepherosa Ziehau BGE_RDMA_RSRVCTRL_TXMRGN_MASK); 15456c8d8eccSSepherosa Ziehau dmactl |= BGE_RDMA_RSRVCTRL_FIFO_LWM_1_5K | 15466c8d8eccSSepherosa Ziehau BGE_RDMA_RSRVCTRL_FIFO_HWM_1_5K | 15476c8d8eccSSepherosa Ziehau BGE_RDMA_RSRVCTRL_TXMRGN_320B; 15486c8d8eccSSepherosa Ziehau } 15496c8d8eccSSepherosa Ziehau /* 15506c8d8eccSSepherosa Ziehau * Enable fix for read DMA FIFO overruns. 15516c8d8eccSSepherosa Ziehau * The fix is to limit the number of RX BDs 15526c8d8eccSSepherosa Ziehau * the hardware would fetch at a fime. 15536c8d8eccSSepherosa Ziehau */ 1554b96cbbb6SSepherosa Ziehau CSR_WRITE_4(sc, dmactl_reg, 15556c8d8eccSSepherosa Ziehau dmactl | BGE_RDMA_RSRVCTRL_FIFO_OFLW_FIX); 15566c8d8eccSSepherosa Ziehau } 15576c8d8eccSSepherosa Ziehau 15586c8d8eccSSepherosa Ziehau if (sc->bnx_asicrev == BGE_ASICREV_BCM5719) { 15596c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_RDMA_LSO_CRPTEN_CTRL, 15606c8d8eccSSepherosa Ziehau CSR_READ_4(sc, BGE_RDMA_LSO_CRPTEN_CTRL) | 15616c8d8eccSSepherosa Ziehau BGE_RDMA_LSO_CRPTEN_CTRL_BLEN_BD_4K | 15626c8d8eccSSepherosa Ziehau BGE_RDMA_LSO_CRPTEN_CTRL_BLEN_LSO_4K); 1563b96cbbb6SSepherosa Ziehau } else if (sc->bnx_asicrev == BGE_ASICREV_BCM5720 || 1564b96cbbb6SSepherosa Ziehau sc->bnx_asicrev == BGE_ASICREV_BCM5762) { 1565b96cbbb6SSepherosa Ziehau uint32_t ctrl_reg; 1566b96cbbb6SSepherosa Ziehau 1567b96cbbb6SSepherosa Ziehau if (sc->bnx_asicrev == BGE_ASICREV_BCM5762) 1568b96cbbb6SSepherosa Ziehau ctrl_reg = BGE_RDMA_LSO_CRPTEN_CTRL2; 1569b96cbbb6SSepherosa Ziehau else 1570b96cbbb6SSepherosa Ziehau ctrl_reg = BGE_RDMA_LSO_CRPTEN_CTRL; 1571b96cbbb6SSepherosa Ziehau 15726c8d8eccSSepherosa Ziehau /* 15736c8d8eccSSepherosa Ziehau * Allow 4KB burst length reads for non-LSO frames. 15746c8d8eccSSepherosa Ziehau * Enable 512B burst length reads for buffer descriptors. 15756c8d8eccSSepherosa Ziehau */ 1576b96cbbb6SSepherosa Ziehau CSR_WRITE_4(sc, ctrl_reg, 1577b96cbbb6SSepherosa Ziehau CSR_READ_4(sc, ctrl_reg) | 15786c8d8eccSSepherosa Ziehau BGE_RDMA_LSO_CRPTEN_CTRL_BLEN_BD_512 | 15796c8d8eccSSepherosa Ziehau BGE_RDMA_LSO_CRPTEN_CTRL_BLEN_LSO_4K); 15806c8d8eccSSepherosa Ziehau } 15816c8d8eccSSepherosa Ziehau 15826c8d8eccSSepherosa Ziehau /* Turn on read DMA state machine */ 15836c8d8eccSSepherosa Ziehau val = BGE_RDMAMODE_ENABLE | BGE_RDMAMODE_ALL_ATTNS; 15846c8d8eccSSepherosa Ziehau if (sc->bnx_asicrev == BGE_ASICREV_BCM5717) 15856c8d8eccSSepherosa Ziehau val |= BGE_RDMAMODE_MULT_DMA_RD_DIS; 15866c8d8eccSSepherosa Ziehau if (sc->bnx_asicrev == BGE_ASICREV_BCM5784 || 15876c8d8eccSSepherosa Ziehau sc->bnx_asicrev == BGE_ASICREV_BCM5785 || 15886c8d8eccSSepherosa Ziehau sc->bnx_asicrev == BGE_ASICREV_BCM57780) { 15896c8d8eccSSepherosa Ziehau val |= BGE_RDMAMODE_BD_SBD_CRPT_ATTN | 15906c8d8eccSSepherosa Ziehau BGE_RDMAMODE_MBUF_RBD_CRPT_ATTN | 15916c8d8eccSSepherosa Ziehau BGE_RDMAMODE_MBUF_SBD_CRPT_ATTN; 15926c8d8eccSSepherosa Ziehau } 1593b96cbbb6SSepherosa Ziehau if (sc->bnx_asicrev == BGE_ASICREV_BCM5720 || 1594b96cbbb6SSepherosa Ziehau sc->bnx_asicrev == BGE_ASICREV_BCM5762) { 15956c8d8eccSSepherosa Ziehau val |= CSR_READ_4(sc, BGE_RDMA_MODE) & 15966c8d8eccSSepherosa Ziehau BGE_RDMAMODE_H2BNC_VLAN_DET; 15976c8d8eccSSepherosa Ziehau /* 15986c8d8eccSSepherosa Ziehau * Allow multiple outstanding read requests from 15996c8d8eccSSepherosa Ziehau * non-LSO read DMA engine. 16006c8d8eccSSepherosa Ziehau */ 16016c8d8eccSSepherosa Ziehau val &= ~BGE_RDMAMODE_MULT_DMA_RD_DIS; 16026c8d8eccSSepherosa Ziehau } 160360e67e3fSSepherosa Ziehau if (sc->bnx_asicrev == BGE_ASICREV_BCM57766) 160460e67e3fSSepherosa Ziehau val |= BGE_RDMAMODE_JMB_2K_MMRR; 160566deb1c1SSepherosa Ziehau if (sc->bnx_flags & BNX_FLAG_TSO) 160666deb1c1SSepherosa Ziehau val |= BGE_RDMAMODE_TSO4_ENABLE; 16076c8d8eccSSepherosa Ziehau val |= BGE_RDMAMODE_FIFO_LONG_BURST; 16086c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_RDMA_MODE, val); 16096c8d8eccSSepherosa Ziehau DELAY(40); 16106c8d8eccSSepherosa Ziehau 16116c8d8eccSSepherosa Ziehau /* Turn on RX data completion state machine */ 16126c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_RDC_MODE, BGE_RDCMODE_ENABLE); 16136c8d8eccSSepherosa Ziehau 16146c8d8eccSSepherosa Ziehau /* Turn on RX BD initiator state machine */ 16156c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_RBDI_MODE, BGE_RBDIMODE_ENABLE); 16166c8d8eccSSepherosa Ziehau 16176c8d8eccSSepherosa Ziehau /* Turn on RX data and RX BD initiator state machine */ 16186c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_RDBDI_MODE, BGE_RDBDIMODE_ENABLE); 16196c8d8eccSSepherosa Ziehau 16206c8d8eccSSepherosa Ziehau /* Turn on send BD completion state machine */ 16216c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_SBDC_MODE, BGE_SBDCMODE_ENABLE); 16226c8d8eccSSepherosa Ziehau 16236c8d8eccSSepherosa Ziehau /* Turn on send data completion state machine */ 16246c8d8eccSSepherosa Ziehau val = BGE_SDCMODE_ENABLE; 16256c8d8eccSSepherosa Ziehau if (sc->bnx_asicrev == BGE_ASICREV_BCM5761) 16266c8d8eccSSepherosa Ziehau val |= BGE_SDCMODE_CDELAY; 16276c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_SDC_MODE, val); 16286c8d8eccSSepherosa Ziehau 16296c8d8eccSSepherosa Ziehau /* Turn on send data initiator state machine */ 163066deb1c1SSepherosa Ziehau if (sc->bnx_flags & BNX_FLAG_TSO) { 163166deb1c1SSepherosa Ziehau CSR_WRITE_4(sc, BGE_SDI_MODE, BGE_SDIMODE_ENABLE | 163266deb1c1SSepherosa Ziehau BGE_SDIMODE_HW_LSO_PRE_DMA); 163366deb1c1SSepherosa Ziehau } else { 16346c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_SDI_MODE, BGE_SDIMODE_ENABLE); 163566deb1c1SSepherosa Ziehau } 16366c8d8eccSSepherosa Ziehau 16376c8d8eccSSepherosa Ziehau /* Turn on send BD initiator state machine */ 16386c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_SBDI_MODE, BGE_SBDIMODE_ENABLE); 16396c8d8eccSSepherosa Ziehau 16406c8d8eccSSepherosa Ziehau /* Turn on send BD selector state machine */ 16416c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_SRS_MODE, BGE_SRSMODE_ENABLE); 16426c8d8eccSSepherosa Ziehau 16436c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_SDI_STATS_ENABLE_MASK, 0x007FFFFF); 16446c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_SDI_STATS_CTL, 16456c8d8eccSSepherosa Ziehau BGE_SDISTATSCTL_ENABLE|BGE_SDISTATSCTL_FASTER); 16466c8d8eccSSepherosa Ziehau 16476c8d8eccSSepherosa Ziehau /* ack/clear link change events */ 16486c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_MAC_STS, BGE_MACSTAT_SYNC_CHANGED| 16496c8d8eccSSepherosa Ziehau BGE_MACSTAT_CFG_CHANGED|BGE_MACSTAT_MI_COMPLETE| 16506c8d8eccSSepherosa Ziehau BGE_MACSTAT_LINK_CHANGED); 16516c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_MI_STS, 0); 16526c8d8eccSSepherosa Ziehau 16536c8d8eccSSepherosa Ziehau /* 16546c8d8eccSSepherosa Ziehau * Enable attention when the link has changed state for 16556c8d8eccSSepherosa Ziehau * devices that use auto polling. 16566c8d8eccSSepherosa Ziehau */ 16576c8d8eccSSepherosa Ziehau if (sc->bnx_flags & BNX_FLAG_TBI) { 16586c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_MI_STS, BGE_MISTS_LINK); 16596c8d8eccSSepherosa Ziehau } else { 16606c8d8eccSSepherosa Ziehau if (sc->bnx_mi_mode & BGE_MIMODE_AUTOPOLL) { 16616c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_MI_MODE, sc->bnx_mi_mode); 16626c8d8eccSSepherosa Ziehau DELAY(80); 16636c8d8eccSSepherosa Ziehau } 16646c8d8eccSSepherosa Ziehau } 16656c8d8eccSSepherosa Ziehau 16666c8d8eccSSepherosa Ziehau /* 16676c8d8eccSSepherosa Ziehau * Clear any pending link state attention. 16686c8d8eccSSepherosa Ziehau * Otherwise some link state change events may be lost until attention 16696c8d8eccSSepherosa Ziehau * is cleared by bnx_intr() -> bnx_softc.bnx_link_upd() sequence. 16706c8d8eccSSepherosa Ziehau * It's not necessary on newer BCM chips - perhaps enabling link 16716c8d8eccSSepherosa Ziehau * state change attentions implies clearing pending attention. 16726c8d8eccSSepherosa Ziehau */ 16736c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_MAC_STS, BGE_MACSTAT_SYNC_CHANGED| 16746c8d8eccSSepherosa Ziehau BGE_MACSTAT_CFG_CHANGED|BGE_MACSTAT_MI_COMPLETE| 16756c8d8eccSSepherosa Ziehau BGE_MACSTAT_LINK_CHANGED); 16766c8d8eccSSepherosa Ziehau 16776c8d8eccSSepherosa Ziehau /* Enable link state change attentions. */ 16786c8d8eccSSepherosa Ziehau BNX_SETBIT(sc, BGE_MAC_EVT_ENB, BGE_EVTENB_LINK_CHANGED); 16796c8d8eccSSepherosa Ziehau 16806c8d8eccSSepherosa Ziehau return(0); 16816c8d8eccSSepherosa Ziehau } 16826c8d8eccSSepherosa Ziehau 16836c8d8eccSSepherosa Ziehau /* 16846c8d8eccSSepherosa Ziehau * Probe for a Broadcom chip. Check the PCI vendor and device IDs 16856c8d8eccSSepherosa Ziehau * against our list and return its name if we find a match. Note 16866c8d8eccSSepherosa Ziehau * that since the Broadcom controller contains VPD support, we 16876c8d8eccSSepherosa Ziehau * can get the device name string from the controller itself instead 16886c8d8eccSSepherosa Ziehau * of the compiled-in string. This is a little slow, but it guarantees 16896c8d8eccSSepherosa Ziehau * we'll always announce the right product name. 16906c8d8eccSSepherosa Ziehau */ 16916c8d8eccSSepherosa Ziehau static int 16926c8d8eccSSepherosa Ziehau bnx_probe(device_t dev) 16936c8d8eccSSepherosa Ziehau { 16946c8d8eccSSepherosa Ziehau const struct bnx_type *t; 16956c8d8eccSSepherosa Ziehau uint16_t product, vendor; 16966c8d8eccSSepherosa Ziehau 16976c8d8eccSSepherosa Ziehau if (!pci_is_pcie(dev)) 16986c8d8eccSSepherosa Ziehau return ENXIO; 16996c8d8eccSSepherosa Ziehau 17006c8d8eccSSepherosa Ziehau product = pci_get_device(dev); 17016c8d8eccSSepherosa Ziehau vendor = pci_get_vendor(dev); 17026c8d8eccSSepherosa Ziehau 17036c8d8eccSSepherosa Ziehau for (t = bnx_devs; t->bnx_name != NULL; t++) { 17046c8d8eccSSepherosa Ziehau if (vendor == t->bnx_vid && product == t->bnx_did) 17056c8d8eccSSepherosa Ziehau break; 17066c8d8eccSSepherosa Ziehau } 17076c8d8eccSSepherosa Ziehau if (t->bnx_name == NULL) 17086c8d8eccSSepherosa Ziehau return ENXIO; 17096c8d8eccSSepherosa Ziehau 17106c8d8eccSSepherosa Ziehau device_set_desc(dev, t->bnx_name); 17116c8d8eccSSepherosa Ziehau return 0; 17126c8d8eccSSepherosa Ziehau } 17136c8d8eccSSepherosa Ziehau 17146c8d8eccSSepherosa Ziehau static int 17156c8d8eccSSepherosa Ziehau bnx_attach(device_t dev) 17166c8d8eccSSepherosa Ziehau { 17176c8d8eccSSepherosa Ziehau struct ifnet *ifp; 17186c8d8eccSSepherosa Ziehau struct bnx_softc *sc; 1719841cdf08SSepherosa Ziehau struct bnx_rx_std_ring *std; 1720e594b5c4SSepherosa Ziehau uint32_t hwcfg = 0; 1721841cdf08SSepherosa Ziehau int error = 0, rid, capmask, i, std_cpuid, std_cpuid_def; 17226c8d8eccSSepherosa Ziehau uint8_t ether_addr[ETHER_ADDR_LEN]; 172307e9f7c0SSascha Wildner uint16_t product; 17246c8d8eccSSepherosa Ziehau uintptr_t mii_priv = 0; 172566deb1c1SSepherosa Ziehau #ifdef BNX_TSO_DEBUG 172666deb1c1SSepherosa Ziehau char desc[32]; 172766deb1c1SSepherosa Ziehau #endif 17284fa38985SSepherosa Ziehau #ifdef IFPOLL_ENABLE 17294fa38985SSepherosa Ziehau int offset, offset_def; 17304fa38985SSepherosa Ziehau #endif 17316c8d8eccSSepherosa Ziehau 17326c8d8eccSSepherosa Ziehau sc = device_get_softc(dev); 17336c8d8eccSSepherosa Ziehau sc->bnx_dev = dev; 17347dbaa833SSepherosa Ziehau callout_init_mp(&sc->bnx_tick_timer); 17356c8d8eccSSepherosa Ziehau lwkt_serialize_init(&sc->bnx_jslot_serializer); 1736f33ac8a4SSepherosa Ziehau lwkt_serialize_init(&sc->bnx_main_serialize); 17376c8d8eccSSepherosa Ziehau 17386c8d8eccSSepherosa Ziehau product = pci_get_device(dev); 17396c8d8eccSSepherosa Ziehau 17406c8d8eccSSepherosa Ziehau #ifndef BURN_BRIDGES 17416c8d8eccSSepherosa Ziehau if (pci_get_powerstate(dev) != PCI_POWERSTATE_D0) { 17426c8d8eccSSepherosa Ziehau uint32_t irq, mem; 17436c8d8eccSSepherosa Ziehau 17446c8d8eccSSepherosa Ziehau irq = pci_read_config(dev, PCIR_INTLINE, 4); 17456c8d8eccSSepherosa Ziehau mem = pci_read_config(dev, BGE_PCI_BAR0, 4); 17466c8d8eccSSepherosa Ziehau 17476c8d8eccSSepherosa Ziehau device_printf(dev, "chip is in D%d power mode " 17486c8d8eccSSepherosa Ziehau "-- setting to D0\n", pci_get_powerstate(dev)); 17496c8d8eccSSepherosa Ziehau 17506c8d8eccSSepherosa Ziehau pci_set_powerstate(dev, PCI_POWERSTATE_D0); 17516c8d8eccSSepherosa Ziehau 17526c8d8eccSSepherosa Ziehau pci_write_config(dev, PCIR_INTLINE, irq, 4); 17536c8d8eccSSepherosa Ziehau pci_write_config(dev, BGE_PCI_BAR0, mem, 4); 17546c8d8eccSSepherosa Ziehau } 17556c8d8eccSSepherosa Ziehau #endif /* !BURN_BRIDGE */ 17566c8d8eccSSepherosa Ziehau 17576c8d8eccSSepherosa Ziehau /* 17586c8d8eccSSepherosa Ziehau * Map control/status registers. 17596c8d8eccSSepherosa Ziehau */ 17606c8d8eccSSepherosa Ziehau pci_enable_busmaster(dev); 17616c8d8eccSSepherosa Ziehau 17626c8d8eccSSepherosa Ziehau rid = BGE_PCI_BAR0; 17636c8d8eccSSepherosa Ziehau sc->bnx_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, 17646c8d8eccSSepherosa Ziehau RF_ACTIVE); 17656c8d8eccSSepherosa Ziehau 17666c8d8eccSSepherosa Ziehau if (sc->bnx_res == NULL) { 17676c8d8eccSSepherosa Ziehau device_printf(dev, "couldn't map memory\n"); 17686c8d8eccSSepherosa Ziehau return ENXIO; 17696c8d8eccSSepherosa Ziehau } 17706c8d8eccSSepherosa Ziehau 17716c8d8eccSSepherosa Ziehau sc->bnx_btag = rman_get_bustag(sc->bnx_res); 17726c8d8eccSSepherosa Ziehau sc->bnx_bhandle = rman_get_bushandle(sc->bnx_res); 17736c8d8eccSSepherosa Ziehau 17746c8d8eccSSepherosa Ziehau /* Save various chip information */ 17756c8d8eccSSepherosa Ziehau sc->bnx_chipid = 17766c8d8eccSSepherosa Ziehau pci_read_config(dev, BGE_PCI_MISC_CTL, 4) >> 17776c8d8eccSSepherosa Ziehau BGE_PCIMISCCTL_ASICREV_SHIFT; 17786c8d8eccSSepherosa Ziehau if (BGE_ASICREV(sc->bnx_chipid) == BGE_ASICREV_USE_PRODID_REG) { 17796c8d8eccSSepherosa Ziehau /* All chips having dedicated ASICREV register have CPMU */ 17806c8d8eccSSepherosa Ziehau sc->bnx_flags |= BNX_FLAG_CPMU; 17816c8d8eccSSepherosa Ziehau 17826c8d8eccSSepherosa Ziehau switch (product) { 17836c8d8eccSSepherosa Ziehau case PCI_PRODUCT_BROADCOM_BCM5717: 1784d79f5d8fSSepherosa Ziehau case PCI_PRODUCT_BROADCOM_BCM5717C: 17856c8d8eccSSepherosa Ziehau case PCI_PRODUCT_BROADCOM_BCM5718: 17866c8d8eccSSepherosa Ziehau case PCI_PRODUCT_BROADCOM_BCM5719: 17876c8d8eccSSepherosa Ziehau case PCI_PRODUCT_BROADCOM_BCM5720_ALT: 1788b96cbbb6SSepherosa Ziehau case PCI_PRODUCT_BROADCOM_BCM5725: 1789b96cbbb6SSepherosa Ziehau case PCI_PRODUCT_BROADCOM_BCM5727: 1790b96cbbb6SSepherosa Ziehau case PCI_PRODUCT_BROADCOM_BCM5762: 17916c8d8eccSSepherosa Ziehau sc->bnx_chipid = pci_read_config(dev, 17926c8d8eccSSepherosa Ziehau BGE_PCI_GEN2_PRODID_ASICREV, 4); 17936c8d8eccSSepherosa Ziehau break; 17946c8d8eccSSepherosa Ziehau 17956c8d8eccSSepherosa Ziehau case PCI_PRODUCT_BROADCOM_BCM57761: 179632ff3c80SSepherosa Ziehau case PCI_PRODUCT_BROADCOM_BCM57762: 17976c8d8eccSSepherosa Ziehau case PCI_PRODUCT_BROADCOM_BCM57765: 179832ff3c80SSepherosa Ziehau case PCI_PRODUCT_BROADCOM_BCM57766: 17996c8d8eccSSepherosa Ziehau case PCI_PRODUCT_BROADCOM_BCM57781: 180032ff3c80SSepherosa Ziehau case PCI_PRODUCT_BROADCOM_BCM57782: 18016c8d8eccSSepherosa Ziehau case PCI_PRODUCT_BROADCOM_BCM57785: 180232ff3c80SSepherosa Ziehau case PCI_PRODUCT_BROADCOM_BCM57786: 18036c8d8eccSSepherosa Ziehau case PCI_PRODUCT_BROADCOM_BCM57791: 18046c8d8eccSSepherosa Ziehau case PCI_PRODUCT_BROADCOM_BCM57795: 18056c8d8eccSSepherosa Ziehau sc->bnx_chipid = pci_read_config(dev, 18066c8d8eccSSepherosa Ziehau BGE_PCI_GEN15_PRODID_ASICREV, 4); 18076c8d8eccSSepherosa Ziehau break; 18086c8d8eccSSepherosa Ziehau 18096c8d8eccSSepherosa Ziehau default: 18106c8d8eccSSepherosa Ziehau sc->bnx_chipid = pci_read_config(dev, 18116c8d8eccSSepherosa Ziehau BGE_PCI_PRODID_ASICREV, 4); 18126c8d8eccSSepherosa Ziehau break; 18136c8d8eccSSepherosa Ziehau } 18146c8d8eccSSepherosa Ziehau } 1815d79f5d8fSSepherosa Ziehau if (sc->bnx_chipid == BGE_CHIPID_BCM5717_C0) 1816d79f5d8fSSepherosa Ziehau sc->bnx_chipid = BGE_CHIPID_BCM5720_A0; 1817d79f5d8fSSepherosa Ziehau 18186c8d8eccSSepherosa Ziehau sc->bnx_asicrev = BGE_ASICREV(sc->bnx_chipid); 18196c8d8eccSSepherosa Ziehau sc->bnx_chiprev = BGE_CHIPREV(sc->bnx_chipid); 18206c8d8eccSSepherosa Ziehau 18216c8d8eccSSepherosa Ziehau switch (sc->bnx_asicrev) { 18226c8d8eccSSepherosa Ziehau case BGE_ASICREV_BCM5717: 18236c8d8eccSSepherosa Ziehau case BGE_ASICREV_BCM5719: 18246c8d8eccSSepherosa Ziehau case BGE_ASICREV_BCM5720: 1825f368d0d9SSepherosa Ziehau sc->bnx_flags |= BNX_FLAG_5717_PLUS | BNX_FLAG_57765_PLUS; 1826f368d0d9SSepherosa Ziehau break; 1827f368d0d9SSepherosa Ziehau 1828b96cbbb6SSepherosa Ziehau case BGE_ASICREV_BCM5762: 1829b96cbbb6SSepherosa Ziehau sc->bnx_flags |= BNX_FLAG_57765_PLUS; 1830b96cbbb6SSepherosa Ziehau break; 1831b96cbbb6SSepherosa Ziehau 18326c8d8eccSSepherosa Ziehau case BGE_ASICREV_BCM57765: 183332ff3c80SSepherosa Ziehau case BGE_ASICREV_BCM57766: 1834f368d0d9SSepherosa Ziehau sc->bnx_flags |= BNX_FLAG_57765_FAMILY | BNX_FLAG_57765_PLUS; 18356c8d8eccSSepherosa Ziehau break; 18366c8d8eccSSepherosa Ziehau } 18376c8d8eccSSepherosa Ziehau 183866deb1c1SSepherosa Ziehau sc->bnx_flags |= BNX_FLAG_TSO; 183966deb1c1SSepherosa Ziehau if (sc->bnx_asicrev == BGE_ASICREV_BCM5719 && 184066deb1c1SSepherosa Ziehau sc->bnx_chipid == BGE_CHIPID_BCM5719_A0) 184166deb1c1SSepherosa Ziehau sc->bnx_flags &= ~BNX_FLAG_TSO; 184266deb1c1SSepherosa Ziehau 1843df9ccc98SSepherosa Ziehau if (sc->bnx_asicrev == BGE_ASICREV_BCM5717 || 1844df9ccc98SSepherosa Ziehau BNX_IS_57765_FAMILY(sc)) { 1845df9ccc98SSepherosa Ziehau /* 1846df9ccc98SSepherosa Ziehau * All BCM57785 and BCM5718 families chips have a bug that 1847df9ccc98SSepherosa Ziehau * under certain situation interrupt will not be enabled 1848df9ccc98SSepherosa Ziehau * even if status tag is written to BGE_MBX_IRQ0_LO mailbox. 1849df9ccc98SSepherosa Ziehau * 1850df9ccc98SSepherosa Ziehau * While BCM5719 and BCM5720 have a hardware workaround 1851df9ccc98SSepherosa Ziehau * which could fix the above bug. 1852df9ccc98SSepherosa Ziehau * See the comment near BGE_PCIDMARWCTL_TAGGED_STATUS_WA in 1853df9ccc98SSepherosa Ziehau * bnx_chipinit(). 1854df9ccc98SSepherosa Ziehau * 1855df9ccc98SSepherosa Ziehau * For the rest of the chips in these two families, we will 1856df9ccc98SSepherosa Ziehau * have to poll the status block at high rate (10ms currently) 1857df9ccc98SSepherosa Ziehau * to check whether the interrupt is hosed or not. 1858f33ac8a4SSepherosa Ziehau * See bnx_check_intr() for details. 1859df9ccc98SSepherosa Ziehau */ 1860df9ccc98SSepherosa Ziehau sc->bnx_flags |= BNX_FLAG_STATUSTAG_BUG; 1861df9ccc98SSepherosa Ziehau } 1862df9ccc98SSepherosa Ziehau 18636c8d8eccSSepherosa Ziehau sc->bnx_pciecap = pci_get_pciecap_ptr(sc->bnx_dev); 18646c8d8eccSSepherosa Ziehau if (sc->bnx_asicrev == BGE_ASICREV_BCM5719 || 18656c8d8eccSSepherosa Ziehau sc->bnx_asicrev == BGE_ASICREV_BCM5720) 18666c8d8eccSSepherosa Ziehau pcie_set_max_readrq(dev, PCIEM_DEVCTL_MAX_READRQ_2048); 18676c8d8eccSSepherosa Ziehau else 18686c8d8eccSSepherosa Ziehau pcie_set_max_readrq(dev, PCIEM_DEVCTL_MAX_READRQ_4096); 18696c8d8eccSSepherosa Ziehau device_printf(dev, "CHIP ID 0x%08x; " 18706c8d8eccSSepherosa Ziehau "ASIC REV 0x%02x; CHIP REV 0x%02x\n", 18716c8d8eccSSepherosa Ziehau sc->bnx_chipid, sc->bnx_asicrev, sc->bnx_chiprev); 18726c8d8eccSSepherosa Ziehau 18736c8d8eccSSepherosa Ziehau /* 18746c8d8eccSSepherosa Ziehau * Set various PHY quirk flags. 18756c8d8eccSSepherosa Ziehau */ 18766c8d8eccSSepherosa Ziehau 18776c8d8eccSSepherosa Ziehau capmask = MII_CAPMASK_DEFAULT; 187846283a40SSepherosa Ziehau if (product == PCI_PRODUCT_BROADCOM_BCM57791 || 187946283a40SSepherosa Ziehau product == PCI_PRODUCT_BROADCOM_BCM57795) { 18806c8d8eccSSepherosa Ziehau /* 10/100 only */ 18816c8d8eccSSepherosa Ziehau capmask &= ~BMSR_EXTSTAT; 18826c8d8eccSSepherosa Ziehau } 18836c8d8eccSSepherosa Ziehau 18846c8d8eccSSepherosa Ziehau mii_priv |= BRGPHY_FLAG_WIRESPEED; 1885b96cbbb6SSepherosa Ziehau if (sc->bnx_chipid == BGE_CHIPID_BCM5762_A0) 1886b96cbbb6SSepherosa Ziehau mii_priv |= BRGPHY_FLAG_5762_A0; 18876c8d8eccSSepherosa Ziehau 18886c8d8eccSSepherosa Ziehau /* Initialize if_name earlier, so if_printf could be used */ 18896c8d8eccSSepherosa Ziehau ifp = &sc->arpcom.ac_if; 18906c8d8eccSSepherosa Ziehau if_initname(ifp, device_get_name(dev), device_get_unit(dev)); 18916c8d8eccSSepherosa Ziehau 18926c8d8eccSSepherosa Ziehau /* Try to reset the chip. */ 18936c8d8eccSSepherosa Ziehau bnx_reset(sc); 18946c8d8eccSSepherosa Ziehau 18956c8d8eccSSepherosa Ziehau if (bnx_chipinit(sc)) { 18966c8d8eccSSepherosa Ziehau device_printf(dev, "chip initialization failed\n"); 18976c8d8eccSSepherosa Ziehau error = ENXIO; 18986c8d8eccSSepherosa Ziehau goto fail; 18996c8d8eccSSepherosa Ziehau } 19006c8d8eccSSepherosa Ziehau 19016c8d8eccSSepherosa Ziehau /* 19026c8d8eccSSepherosa Ziehau * Get station address 19036c8d8eccSSepherosa Ziehau */ 19046c8d8eccSSepherosa Ziehau error = bnx_get_eaddr(sc, ether_addr); 19056c8d8eccSSepherosa Ziehau if (error) { 19066c8d8eccSSepherosa Ziehau device_printf(dev, "failed to read station address\n"); 19076c8d8eccSSepherosa Ziehau goto fail; 19086c8d8eccSSepherosa Ziehau } 19096c8d8eccSSepherosa Ziehau 191033a04907SSepherosa Ziehau /* XXX */ 191133a04907SSepherosa Ziehau sc->bnx_tx_ringcnt = 1; 1912beedf5beSSepherosa Ziehau sc->bnx_rx_retcnt = 1; 1913*0a806e3aSSepherosa Ziehau sc->bnx_intr_cnt = 1; 191433a04907SSepherosa Ziehau 19154fa38985SSepherosa Ziehau if ((sc->bnx_rx_retcnt == 1 && sc->bnx_tx_ringcnt == 1) || 19164fa38985SSepherosa Ziehau (sc->bnx_rx_retcnt > 1 && sc->bnx_tx_ringcnt > 1)) { 19174fa38985SSepherosa Ziehau /* 19184fa38985SSepherosa Ziehau * The RX ring and the corresponding TX ring processing 19194fa38985SSepherosa Ziehau * should be on the same CPU, since they share the same 19204fa38985SSepherosa Ziehau * status block. 19214fa38985SSepherosa Ziehau */ 19224fa38985SSepherosa Ziehau sc->bnx_flags |= BNX_FLAG_RXTX_BUNDLE; 19234fa38985SSepherosa Ziehau if (bootverbose) 19244fa38985SSepherosa Ziehau device_printf(dev, "RX/TX bundle\n"); 19254fa38985SSepherosa Ziehau } else { 19264fa38985SSepherosa Ziehau KKASSERT(sc->bnx_rx_retcnt > 1 && sc->bnx_tx_ringcnt == 1); 19274fa38985SSepherosa Ziehau } 19284fa38985SSepherosa Ziehau 1929beedf5beSSepherosa Ziehau error = bnx_dma_alloc(dev); 19306c8d8eccSSepherosa Ziehau if (error) 19316c8d8eccSSepherosa Ziehau goto fail; 19326c8d8eccSSepherosa Ziehau 19334fa38985SSepherosa Ziehau #ifdef IFPOLL_ENABLE 19344fa38985SSepherosa Ziehau if (sc->bnx_flags & BNX_FLAG_RXTX_BUNDLE) { 19354fa38985SSepherosa Ziehau /* 19364fa38985SSepherosa Ziehau * NPOLLING RX/TX CPU offset 19374fa38985SSepherosa Ziehau */ 19384fa38985SSepherosa Ziehau if (sc->bnx_rx_retcnt == ncpus2) { 19394fa38985SSepherosa Ziehau offset = 0; 19404fa38985SSepherosa Ziehau } else { 19414fa38985SSepherosa Ziehau offset_def = 19424fa38985SSepherosa Ziehau (sc->bnx_rx_retcnt * device_get_unit(dev)) % ncpus2; 19434fa38985SSepherosa Ziehau offset = device_getenv_int(dev, "npoll.offset", 19444fa38985SSepherosa Ziehau offset_def); 19454fa38985SSepherosa Ziehau if (offset >= ncpus2 || 19464fa38985SSepherosa Ziehau offset % sc->bnx_rx_retcnt != 0) { 19474fa38985SSepherosa Ziehau device_printf(dev, "invalid npoll.offset %d, " 19484fa38985SSepherosa Ziehau "use %d\n", offset, offset_def); 19494fa38985SSepherosa Ziehau offset = offset_def; 19504fa38985SSepherosa Ziehau } 19514fa38985SSepherosa Ziehau } 19524fa38985SSepherosa Ziehau sc->bnx_npoll_rxoff = offset; 19534fa38985SSepherosa Ziehau sc->bnx_npoll_txoff = offset; 19544fa38985SSepherosa Ziehau } else { 19554fa38985SSepherosa Ziehau /* 19564fa38985SSepherosa Ziehau * NPOLLING RX CPU offset 19574fa38985SSepherosa Ziehau */ 19584fa38985SSepherosa Ziehau if (sc->bnx_rx_retcnt == ncpus2) { 19594fa38985SSepherosa Ziehau offset = 0; 19604fa38985SSepherosa Ziehau } else { 19614fa38985SSepherosa Ziehau offset_def = 19624fa38985SSepherosa Ziehau (sc->bnx_rx_retcnt * device_get_unit(dev)) % ncpus2; 19634fa38985SSepherosa Ziehau offset = device_getenv_int(dev, "npoll.rxoff", 19644fa38985SSepherosa Ziehau offset_def); 19654fa38985SSepherosa Ziehau if (offset >= ncpus2 || 19664fa38985SSepherosa Ziehau offset % sc->bnx_rx_retcnt != 0) { 19674fa38985SSepherosa Ziehau device_printf(dev, "invalid npoll.rxoff %d, " 19684fa38985SSepherosa Ziehau "use %d\n", offset, offset_def); 19694fa38985SSepherosa Ziehau offset = offset_def; 19704fa38985SSepherosa Ziehau } 19714fa38985SSepherosa Ziehau } 19724fa38985SSepherosa Ziehau sc->bnx_npoll_rxoff = offset; 19734fa38985SSepherosa Ziehau 19744fa38985SSepherosa Ziehau /* 19754fa38985SSepherosa Ziehau * NPOLLING TX CPU offset 19764fa38985SSepherosa Ziehau */ 19774fa38985SSepherosa Ziehau offset_def = device_get_unit(dev) % ncpus2; 19784fa38985SSepherosa Ziehau offset = device_getenv_int(dev, "npoll.txoff", offset_def); 19794fa38985SSepherosa Ziehau if (offset >= ncpus2) { 19804fa38985SSepherosa Ziehau device_printf(dev, "invalid npoll.txoff %d, use %d\n", 19814fa38985SSepherosa Ziehau offset, offset_def); 19824fa38985SSepherosa Ziehau offset = offset_def; 19834fa38985SSepherosa Ziehau } 19844fa38985SSepherosa Ziehau sc->bnx_npoll_txoff = offset; 19854fa38985SSepherosa Ziehau } 19864fa38985SSepherosa Ziehau #endif /* IFPOLL_ENABLE */ 19874fa38985SSepherosa Ziehau 198816b32c4cSSepherosa Ziehau /* 198916b32c4cSSepherosa Ziehau * Allocate interrupt 199016b32c4cSSepherosa Ziehau */ 19910c7da01dSSepherosa Ziehau error = bnx_alloc_intr(sc); 19920c7da01dSSepherosa Ziehau if (error) 199316b32c4cSSepherosa Ziehau goto fail; 199416b32c4cSSepherosa Ziehau 1995329f9016SSepherosa Ziehau /* Setup serializers */ 1996329f9016SSepherosa Ziehau bnx_setup_serialize(sc); 1997329f9016SSepherosa Ziehau 19986c8d8eccSSepherosa Ziehau /* Set default tuneable values. */ 19996c8d8eccSSepherosa Ziehau sc->bnx_rx_coal_ticks = BNX_RX_COAL_TICKS_DEF; 20006c8d8eccSSepherosa Ziehau sc->bnx_tx_coal_ticks = BNX_TX_COAL_TICKS_DEF; 20016c8d8eccSSepherosa Ziehau sc->bnx_rx_coal_bds = BNX_RX_COAL_BDS_DEF; 20026c8d8eccSSepherosa Ziehau sc->bnx_tx_coal_bds = BNX_TX_COAL_BDS_DEF; 2003306e5498SSepherosa Ziehau sc->bnx_rx_coal_bds_int = BNX_RX_COAL_BDS_INT_DEF; 2004306e5498SSepherosa Ziehau sc->bnx_tx_coal_bds_int = BNX_TX_COAL_BDS_INT_DEF; 20056c8d8eccSSepherosa Ziehau 20066c8d8eccSSepherosa Ziehau /* Set up ifnet structure */ 20076c8d8eccSSepherosa Ziehau ifp->if_softc = sc; 20086c8d8eccSSepherosa Ziehau ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; 20096c8d8eccSSepherosa Ziehau ifp->if_ioctl = bnx_ioctl; 20106c8d8eccSSepherosa Ziehau ifp->if_start = bnx_start; 201139a8d43aSSepherosa Ziehau #ifdef IFPOLL_ENABLE 201239a8d43aSSepherosa Ziehau ifp->if_npoll = bnx_npoll; 20136c8d8eccSSepherosa Ziehau #endif 20146c8d8eccSSepherosa Ziehau ifp->if_init = bnx_init; 2015329f9016SSepherosa Ziehau ifp->if_serialize = bnx_serialize; 2016329f9016SSepherosa Ziehau ifp->if_deserialize = bnx_deserialize; 2017329f9016SSepherosa Ziehau ifp->if_tryserialize = bnx_tryserialize; 2018329f9016SSepherosa Ziehau #ifdef INVARIANTS 2019329f9016SSepherosa Ziehau ifp->if_serialize_assert = bnx_serialize_assert; 2020329f9016SSepherosa Ziehau #endif 20216c8d8eccSSepherosa Ziehau ifp->if_mtu = ETHERMTU; 20226c8d8eccSSepherosa Ziehau ifp->if_capabilities = IFCAP_VLAN_HWTAGGING | IFCAP_VLAN_MTU; 20236c8d8eccSSepherosa Ziehau 20246c8d8eccSSepherosa Ziehau ifp->if_capabilities |= IFCAP_HWCSUM; 20256c8d8eccSSepherosa Ziehau ifp->if_hwassist = BNX_CSUM_FEATURES; 202666deb1c1SSepherosa Ziehau if (sc->bnx_flags & BNX_FLAG_TSO) { 202766deb1c1SSepherosa Ziehau ifp->if_capabilities |= IFCAP_TSO; 202866deb1c1SSepherosa Ziehau ifp->if_hwassist |= CSUM_TSO; 202966deb1c1SSepherosa Ziehau } 20306c8d8eccSSepherosa Ziehau ifp->if_capenable = ifp->if_capabilities; 20316c8d8eccSSepherosa Ziehau 2032329f9016SSepherosa Ziehau ifq_set_maxlen(&ifp->if_snd, BGE_TX_RING_CNT - 1); 2033329f9016SSepherosa Ziehau ifq_set_ready(&ifp->if_snd); 2034329f9016SSepherosa Ziehau ifq_set_subq_cnt(&ifp->if_snd, sc->bnx_tx_ringcnt); 2035329f9016SSepherosa Ziehau 20366c8d8eccSSepherosa Ziehau /* 20376c8d8eccSSepherosa Ziehau * Figure out what sort of media we have by checking the 20386c8d8eccSSepherosa Ziehau * hardware config word in the first 32k of NIC internal memory, 20396c8d8eccSSepherosa Ziehau * or fall back to examining the EEPROM if necessary. 20406c8d8eccSSepherosa Ziehau * Note: on some BCM5700 cards, this value appears to be unset. 20416c8d8eccSSepherosa Ziehau * If that's the case, we have to rely on identifying the NIC 20426c8d8eccSSepherosa Ziehau * by its PCI subsystem ID, as we do below for the SysKonnect 20436c8d8eccSSepherosa Ziehau * SK-9D41. 20446c8d8eccSSepherosa Ziehau */ 20456c8d8eccSSepherosa Ziehau if (bnx_readmem_ind(sc, BGE_SOFTWARE_GENCOMM_SIG) == BGE_MAGIC_NUMBER) { 20466c8d8eccSSepherosa Ziehau hwcfg = bnx_readmem_ind(sc, BGE_SOFTWARE_GENCOMM_NICCFG); 20476c8d8eccSSepherosa Ziehau } else { 20486c8d8eccSSepherosa Ziehau if (bnx_read_eeprom(sc, (caddr_t)&hwcfg, BGE_EE_HWCFG_OFFSET, 20496c8d8eccSSepherosa Ziehau sizeof(hwcfg))) { 20506c8d8eccSSepherosa Ziehau device_printf(dev, "failed to read EEPROM\n"); 20516c8d8eccSSepherosa Ziehau error = ENXIO; 20526c8d8eccSSepherosa Ziehau goto fail; 20536c8d8eccSSepherosa Ziehau } 20546c8d8eccSSepherosa Ziehau hwcfg = ntohl(hwcfg); 20556c8d8eccSSepherosa Ziehau } 20566c8d8eccSSepherosa Ziehau 20576c8d8eccSSepherosa Ziehau /* The SysKonnect SK-9D41 is a 1000baseSX card. */ 20586c8d8eccSSepherosa Ziehau if (pci_get_subvendor(dev) == PCI_PRODUCT_SCHNEIDERKOCH_SK_9D41 || 20596c8d8eccSSepherosa Ziehau (hwcfg & BGE_HWCFG_MEDIA) == BGE_MEDIA_FIBER) 20606c8d8eccSSepherosa Ziehau sc->bnx_flags |= BNX_FLAG_TBI; 20616c8d8eccSSepherosa Ziehau 20626c8d8eccSSepherosa Ziehau /* Setup MI MODE */ 20636c8d8eccSSepherosa Ziehau if (sc->bnx_flags & BNX_FLAG_CPMU) 20646c8d8eccSSepherosa Ziehau sc->bnx_mi_mode = BGE_MIMODE_500KHZ_CONST; 20656c8d8eccSSepherosa Ziehau else 20666c8d8eccSSepherosa Ziehau sc->bnx_mi_mode = BGE_MIMODE_BASE; 20676c8d8eccSSepherosa Ziehau 20686c8d8eccSSepherosa Ziehau /* Setup link status update stuffs */ 20696c8d8eccSSepherosa Ziehau if (sc->bnx_flags & BNX_FLAG_TBI) { 20706c8d8eccSSepherosa Ziehau sc->bnx_link_upd = bnx_tbi_link_upd; 20716c8d8eccSSepherosa Ziehau sc->bnx_link_chg = BGE_MACSTAT_LINK_CHANGED; 20726c8d8eccSSepherosa Ziehau } else if (sc->bnx_mi_mode & BGE_MIMODE_AUTOPOLL) { 20736c8d8eccSSepherosa Ziehau sc->bnx_link_upd = bnx_autopoll_link_upd; 20746c8d8eccSSepherosa Ziehau sc->bnx_link_chg = BGE_MACSTAT_LINK_CHANGED; 20756c8d8eccSSepherosa Ziehau } else { 20766c8d8eccSSepherosa Ziehau sc->bnx_link_upd = bnx_copper_link_upd; 20776c8d8eccSSepherosa Ziehau sc->bnx_link_chg = BGE_MACSTAT_LINK_CHANGED; 20786c8d8eccSSepherosa Ziehau } 20796c8d8eccSSepherosa Ziehau 20806c8d8eccSSepherosa Ziehau /* Set default PHY address */ 20816c8d8eccSSepherosa Ziehau sc->bnx_phyno = 1; 20826c8d8eccSSepherosa Ziehau 20836c8d8eccSSepherosa Ziehau /* 20846c8d8eccSSepherosa Ziehau * PHY address mapping for various devices. 20856c8d8eccSSepherosa Ziehau * 20866c8d8eccSSepherosa Ziehau * | F0 Cu | F0 Sr | F1 Cu | F1 Sr | 20876c8d8eccSSepherosa Ziehau * ---------+-------+-------+-------+-------+ 20886c8d8eccSSepherosa Ziehau * BCM57XX | 1 | X | X | X | 20896c8d8eccSSepherosa Ziehau * BCM5704 | 1 | X | 1 | X | 20906c8d8eccSSepherosa Ziehau * BCM5717 | 1 | 8 | 2 | 9 | 20916c8d8eccSSepherosa Ziehau * BCM5719 | 1 | 8 | 2 | 9 | 20926c8d8eccSSepherosa Ziehau * BCM5720 | 1 | 8 | 2 | 9 | 20936c8d8eccSSepherosa Ziehau * 20946c8d8eccSSepherosa Ziehau * Other addresses may respond but they are not 20956c8d8eccSSepherosa Ziehau * IEEE compliant PHYs and should be ignored. 20966c8d8eccSSepherosa Ziehau */ 209780969639SSepherosa Ziehau if (BNX_IS_5717_PLUS(sc)) { 20986c8d8eccSSepherosa Ziehau int f; 20996c8d8eccSSepherosa Ziehau 21006c8d8eccSSepherosa Ziehau f = pci_get_function(dev); 21016c8d8eccSSepherosa Ziehau if (sc->bnx_chipid == BGE_CHIPID_BCM5717_A0) { 21026c8d8eccSSepherosa Ziehau if (CSR_READ_4(sc, BGE_SGDIG_STS) & 21036c8d8eccSSepherosa Ziehau BGE_SGDIGSTS_IS_SERDES) 21046c8d8eccSSepherosa Ziehau sc->bnx_phyno = f + 8; 21056c8d8eccSSepherosa Ziehau else 21066c8d8eccSSepherosa Ziehau sc->bnx_phyno = f + 1; 21076c8d8eccSSepherosa Ziehau } else { 21086c8d8eccSSepherosa Ziehau if (CSR_READ_4(sc, BGE_CPMU_PHY_STRAP) & 21096c8d8eccSSepherosa Ziehau BGE_CPMU_PHY_STRAP_IS_SERDES) 21106c8d8eccSSepherosa Ziehau sc->bnx_phyno = f + 8; 21116c8d8eccSSepherosa Ziehau else 21126c8d8eccSSepherosa Ziehau sc->bnx_phyno = f + 1; 21136c8d8eccSSepherosa Ziehau } 21146c8d8eccSSepherosa Ziehau } 21156c8d8eccSSepherosa Ziehau 21166c8d8eccSSepherosa Ziehau if (sc->bnx_flags & BNX_FLAG_TBI) { 21176c8d8eccSSepherosa Ziehau ifmedia_init(&sc->bnx_ifmedia, IFM_IMASK, 21186c8d8eccSSepherosa Ziehau bnx_ifmedia_upd, bnx_ifmedia_sts); 21196c8d8eccSSepherosa Ziehau ifmedia_add(&sc->bnx_ifmedia, IFM_ETHER|IFM_1000_SX, 0, NULL); 21206c8d8eccSSepherosa Ziehau ifmedia_add(&sc->bnx_ifmedia, 21216c8d8eccSSepherosa Ziehau IFM_ETHER|IFM_1000_SX|IFM_FDX, 0, NULL); 21226c8d8eccSSepherosa Ziehau ifmedia_add(&sc->bnx_ifmedia, IFM_ETHER|IFM_AUTO, 0, NULL); 21236c8d8eccSSepherosa Ziehau ifmedia_set(&sc->bnx_ifmedia, IFM_ETHER|IFM_AUTO); 21246c8d8eccSSepherosa Ziehau sc->bnx_ifmedia.ifm_media = sc->bnx_ifmedia.ifm_cur->ifm_media; 21256c8d8eccSSepherosa Ziehau } else { 21266c8d8eccSSepherosa Ziehau struct mii_probe_args mii_args; 21276c8d8eccSSepherosa Ziehau 21286c8d8eccSSepherosa Ziehau mii_probe_args_init(&mii_args, bnx_ifmedia_upd, bnx_ifmedia_sts); 21296c8d8eccSSepherosa Ziehau mii_args.mii_probemask = 1 << sc->bnx_phyno; 21306c8d8eccSSepherosa Ziehau mii_args.mii_capmask = capmask; 21316c8d8eccSSepherosa Ziehau mii_args.mii_privtag = MII_PRIVTAG_BRGPHY; 21326c8d8eccSSepherosa Ziehau mii_args.mii_priv = mii_priv; 21336c8d8eccSSepherosa Ziehau 21346c8d8eccSSepherosa Ziehau error = mii_probe(dev, &sc->bnx_miibus, &mii_args); 21356c8d8eccSSepherosa Ziehau if (error) { 21366c8d8eccSSepherosa Ziehau device_printf(dev, "MII without any PHY!\n"); 21376c8d8eccSSepherosa Ziehau goto fail; 21386c8d8eccSSepherosa Ziehau } 21396c8d8eccSSepherosa Ziehau } 21406c8d8eccSSepherosa Ziehau 21416c8d8eccSSepherosa Ziehau /* 21426c8d8eccSSepherosa Ziehau * Create sysctl nodes. 21436c8d8eccSSepherosa Ziehau */ 21446c8d8eccSSepherosa Ziehau sysctl_ctx_init(&sc->bnx_sysctl_ctx); 21456c8d8eccSSepherosa Ziehau sc->bnx_sysctl_tree = SYSCTL_ADD_NODE(&sc->bnx_sysctl_ctx, 21466c8d8eccSSepherosa Ziehau SYSCTL_STATIC_CHILDREN(_hw), 21476c8d8eccSSepherosa Ziehau OID_AUTO, 21486c8d8eccSSepherosa Ziehau device_get_nameunit(dev), 21496c8d8eccSSepherosa Ziehau CTLFLAG_RD, 0, ""); 21506c8d8eccSSepherosa Ziehau if (sc->bnx_sysctl_tree == NULL) { 21516c8d8eccSSepherosa Ziehau device_printf(dev, "can't add sysctl node\n"); 21526c8d8eccSSepherosa Ziehau error = ENXIO; 21536c8d8eccSSepherosa Ziehau goto fail; 21546c8d8eccSSepherosa Ziehau } 21556c8d8eccSSepherosa Ziehau 215693146551SSepherosa Ziehau SYSCTL_ADD_INT(&sc->bnx_sysctl_ctx, 215793146551SSepherosa Ziehau SYSCTL_CHILDREN(sc->bnx_sysctl_tree), OID_AUTO, 215893146551SSepherosa Ziehau "rx_rings", CTLFLAG_RD, &sc->bnx_rx_retcnt, 0, "# of RX rings"); 215993146551SSepherosa Ziehau SYSCTL_ADD_INT(&sc->bnx_sysctl_ctx, 216093146551SSepherosa Ziehau SYSCTL_CHILDREN(sc->bnx_sysctl_tree), OID_AUTO, 216193146551SSepherosa Ziehau "tx_rings", CTLFLAG_RD, &sc->bnx_tx_ringcnt, 0, "# of TX rings"); 216293146551SSepherosa Ziehau 21636c8d8eccSSepherosa Ziehau SYSCTL_ADD_PROC(&sc->bnx_sysctl_ctx, 21646c8d8eccSSepherosa Ziehau SYSCTL_CHILDREN(sc->bnx_sysctl_tree), 21656c8d8eccSSepherosa Ziehau OID_AUTO, "rx_coal_ticks", 21666c8d8eccSSepherosa Ziehau CTLTYPE_INT | CTLFLAG_RW, 21676c8d8eccSSepherosa Ziehau sc, 0, bnx_sysctl_rx_coal_ticks, "I", 21686c8d8eccSSepherosa Ziehau "Receive coalescing ticks (usec)."); 21696c8d8eccSSepherosa Ziehau SYSCTL_ADD_PROC(&sc->bnx_sysctl_ctx, 21706c8d8eccSSepherosa Ziehau SYSCTL_CHILDREN(sc->bnx_sysctl_tree), 21716c8d8eccSSepherosa Ziehau OID_AUTO, "tx_coal_ticks", 21726c8d8eccSSepherosa Ziehau CTLTYPE_INT | CTLFLAG_RW, 21736c8d8eccSSepherosa Ziehau sc, 0, bnx_sysctl_tx_coal_ticks, "I", 21746c8d8eccSSepherosa Ziehau "Transmit coalescing ticks (usec)."); 21756c8d8eccSSepherosa Ziehau SYSCTL_ADD_PROC(&sc->bnx_sysctl_ctx, 21766c8d8eccSSepherosa Ziehau SYSCTL_CHILDREN(sc->bnx_sysctl_tree), 21776c8d8eccSSepherosa Ziehau OID_AUTO, "rx_coal_bds", 21786c8d8eccSSepherosa Ziehau CTLTYPE_INT | CTLFLAG_RW, 21796c8d8eccSSepherosa Ziehau sc, 0, bnx_sysctl_rx_coal_bds, "I", 21806c8d8eccSSepherosa Ziehau "Receive max coalesced BD count."); 21816c8d8eccSSepherosa Ziehau SYSCTL_ADD_PROC(&sc->bnx_sysctl_ctx, 21826c8d8eccSSepherosa Ziehau SYSCTL_CHILDREN(sc->bnx_sysctl_tree), 21836c8d8eccSSepherosa Ziehau OID_AUTO, "tx_coal_bds", 21846c8d8eccSSepherosa Ziehau CTLTYPE_INT | CTLFLAG_RW, 21856c8d8eccSSepherosa Ziehau sc, 0, bnx_sysctl_tx_coal_bds, "I", 21866c8d8eccSSepherosa Ziehau "Transmit max coalesced BD count."); 21876c8d8eccSSepherosa Ziehau /* 21886c8d8eccSSepherosa Ziehau * A common design characteristic for many Broadcom 21896c8d8eccSSepherosa Ziehau * client controllers is that they only support a 21906c8d8eccSSepherosa Ziehau * single outstanding DMA read operation on the PCIe 21916c8d8eccSSepherosa Ziehau * bus. This means that it will take twice as long to 21926c8d8eccSSepherosa Ziehau * fetch a TX frame that is split into header and 21936c8d8eccSSepherosa Ziehau * payload buffers as it does to fetch a single, 21946c8d8eccSSepherosa Ziehau * contiguous TX frame (2 reads vs. 1 read). For these 21956c8d8eccSSepherosa Ziehau * controllers, coalescing buffers to reduce the number 21966c8d8eccSSepherosa Ziehau * of memory reads is effective way to get maximum 21976c8d8eccSSepherosa Ziehau * performance(about 940Mbps). Without collapsing TX 21986c8d8eccSSepherosa Ziehau * buffers the maximum TCP bulk transfer performance 21996c8d8eccSSepherosa Ziehau * is about 850Mbps. However forcing coalescing mbufs 22006c8d8eccSSepherosa Ziehau * consumes a lot of CPU cycles, so leave it off by 22016c8d8eccSSepherosa Ziehau * default. 22026c8d8eccSSepherosa Ziehau */ 2203aad4de2bSSepherosa Ziehau SYSCTL_ADD_PROC(&sc->bnx_sysctl_ctx, 22046c8d8eccSSepherosa Ziehau SYSCTL_CHILDREN(sc->bnx_sysctl_tree), OID_AUTO, 2205aad4de2bSSepherosa Ziehau "force_defrag", CTLTYPE_INT | CTLFLAG_RW, 2206aad4de2bSSepherosa Ziehau sc, 0, bnx_sysctl_force_defrag, "I", 22076c8d8eccSSepherosa Ziehau "Force defragment on TX path"); 22086c8d8eccSSepherosa Ziehau 2209472c99c8SSepherosa Ziehau SYSCTL_ADD_PROC(&sc->bnx_sysctl_ctx, 2210c9b7f592SSepherosa Ziehau SYSCTL_CHILDREN(sc->bnx_sysctl_tree), OID_AUTO, 2211472c99c8SSepherosa Ziehau "tx_wreg", CTLTYPE_INT | CTLFLAG_RW, 2212472c99c8SSepherosa Ziehau sc, 0, bnx_sysctl_tx_wreg, "I", 2213c9b7f592SSepherosa Ziehau "# of segments before writing to hardware register"); 2214c9b7f592SSepherosa Ziehau 22156c8d8eccSSepherosa Ziehau SYSCTL_ADD_PROC(&sc->bnx_sysctl_ctx, 22166c8d8eccSSepherosa Ziehau SYSCTL_CHILDREN(sc->bnx_sysctl_tree), OID_AUTO, 2217841cdf08SSepherosa Ziehau "std_refill", CTLTYPE_INT | CTLFLAG_RW, 2218841cdf08SSepherosa Ziehau sc, 0, bnx_sysctl_std_refill, "I", 2219841cdf08SSepherosa Ziehau "# of packets received before scheduling standard refilling"); 2220841cdf08SSepherosa Ziehau 2221841cdf08SSepherosa Ziehau SYSCTL_ADD_PROC(&sc->bnx_sysctl_ctx, 2222841cdf08SSepherosa Ziehau SYSCTL_CHILDREN(sc->bnx_sysctl_tree), OID_AUTO, 22236c8d8eccSSepherosa Ziehau "rx_coal_bds_int", CTLTYPE_INT | CTLFLAG_RW, 22246c8d8eccSSepherosa Ziehau sc, 0, bnx_sysctl_rx_coal_bds_int, "I", 22256c8d8eccSSepherosa Ziehau "Receive max coalesced BD count during interrupt."); 22266c8d8eccSSepherosa Ziehau SYSCTL_ADD_PROC(&sc->bnx_sysctl_ctx, 22276c8d8eccSSepherosa Ziehau SYSCTL_CHILDREN(sc->bnx_sysctl_tree), OID_AUTO, 22286c8d8eccSSepherosa Ziehau "tx_coal_bds_int", CTLTYPE_INT | CTLFLAG_RW, 22296c8d8eccSSepherosa Ziehau sc, 0, bnx_sysctl_tx_coal_bds_int, "I", 22306c8d8eccSSepherosa Ziehau "Transmit max coalesced BD count during interrupt."); 22316c8d8eccSSepherosa Ziehau 22324fa38985SSepherosa Ziehau #ifdef IFPOLL_ENABLE 22334fa38985SSepherosa Ziehau if (sc->bnx_flags & BNX_FLAG_RXTX_BUNDLE) { 22344fa38985SSepherosa Ziehau SYSCTL_ADD_PROC(&sc->bnx_sysctl_ctx, 22354fa38985SSepherosa Ziehau SYSCTL_CHILDREN(sc->bnx_sysctl_tree), OID_AUTO, 22364fa38985SSepherosa Ziehau "npoll_offset", CTLTYPE_INT | CTLFLAG_RW, 22374fa38985SSepherosa Ziehau sc, 0, bnx_sysctl_npoll_offset, "I", 22384fa38985SSepherosa Ziehau "NPOLLING cpu offset"); 22394fa38985SSepherosa Ziehau } else { 22404fa38985SSepherosa Ziehau SYSCTL_ADD_PROC(&sc->bnx_sysctl_ctx, 22414fa38985SSepherosa Ziehau SYSCTL_CHILDREN(sc->bnx_sysctl_tree), OID_AUTO, 22424fa38985SSepherosa Ziehau "npoll_rxoff", CTLTYPE_INT | CTLFLAG_RW, 22434fa38985SSepherosa Ziehau sc, 0, bnx_sysctl_npoll_rxoff, "I", 22444fa38985SSepherosa Ziehau "NPOLLING RX cpu offset"); 22454fa38985SSepherosa Ziehau SYSCTL_ADD_PROC(&sc->bnx_sysctl_ctx, 22464fa38985SSepherosa Ziehau SYSCTL_CHILDREN(sc->bnx_sysctl_tree), OID_AUTO, 22474fa38985SSepherosa Ziehau "npoll_txoff", CTLTYPE_INT | CTLFLAG_RW, 22484fa38985SSepherosa Ziehau sc, 0, bnx_sysctl_npoll_txoff, "I", 22494fa38985SSepherosa Ziehau "NPOLLING TX cpu offset"); 22504fa38985SSepherosa Ziehau } 22514fa38985SSepherosa Ziehau #endif 22524fa38985SSepherosa Ziehau 225366deb1c1SSepherosa Ziehau #ifdef BNX_TSO_DEBUG 225466deb1c1SSepherosa Ziehau for (i = 0; i < BNX_TSO_NSTATS; ++i) { 225566deb1c1SSepherosa Ziehau ksnprintf(desc, sizeof(desc), "tso%d", i + 1); 225666deb1c1SSepherosa Ziehau SYSCTL_ADD_ULONG(&sc->bnx_sysctl_ctx, 225766deb1c1SSepherosa Ziehau SYSCTL_CHILDREN(sc->bnx_sysctl_tree), OID_AUTO, 225866deb1c1SSepherosa Ziehau desc, CTLFLAG_RW, &sc->bnx_tsosegs[i], ""); 225966deb1c1SSepherosa Ziehau } 226066deb1c1SSepherosa Ziehau #endif 226166deb1c1SSepherosa Ziehau 22626c8d8eccSSepherosa Ziehau /* 22636c8d8eccSSepherosa Ziehau * Call MI attach routine. 22646c8d8eccSSepherosa Ziehau */ 2265329f9016SSepherosa Ziehau ether_ifattach(ifp, ether_addr, NULL); 22666c8d8eccSSepherosa Ziehau 2267329f9016SSepherosa Ziehau /* Setup TX rings and subqueues */ 2268329f9016SSepherosa Ziehau for (i = 0; i < sc->bnx_tx_ringcnt; ++i) { 2269329f9016SSepherosa Ziehau struct ifaltq_subque *ifsq = ifq_get_subq(&ifp->if_snd, i); 2270329f9016SSepherosa Ziehau struct bnx_tx_ring *txr = &sc->bnx_tx_ring[i]; 2271329f9016SSepherosa Ziehau 2272329f9016SSepherosa Ziehau ifsq_set_cpuid(ifsq, txr->bnx_tx_cpuid); 2273329f9016SSepherosa Ziehau ifsq_set_hw_serialize(ifsq, &txr->bnx_tx_serialize); 2274329f9016SSepherosa Ziehau ifsq_set_priv(ifsq, txr); 22753397dea6SSepherosa Ziehau txr->bnx_ifsq = ifsq; 2276329f9016SSepherosa Ziehau 22773397dea6SSepherosa Ziehau ifsq_watchdog_init(&txr->bnx_tx_watchdog, ifsq, bnx_watchdog); 2278329f9016SSepherosa Ziehau } 22794c77af2dSSepherosa Ziehau 22800c7da01dSSepherosa Ziehau error = bnx_setup_intr(sc); 22816c8d8eccSSepherosa Ziehau if (error) { 22826c8d8eccSSepherosa Ziehau ether_ifdetach(ifp); 22836c8d8eccSSepherosa Ziehau goto fail; 22846c8d8eccSSepherosa Ziehau } 22857dbaa833SSepherosa Ziehau bnx_set_tick_cpuid(sc, FALSE); 22868ca0f604SSepherosa Ziehau 2287841cdf08SSepherosa Ziehau /* 2288841cdf08SSepherosa Ziehau * Create RX standard ring refilling thread 2289841cdf08SSepherosa Ziehau */ 2290841cdf08SSepherosa Ziehau std_cpuid_def = device_get_unit(dev) % ncpus; 2291841cdf08SSepherosa Ziehau std_cpuid = device_getenv_int(dev, "std.cpuid", std_cpuid_def); 2292841cdf08SSepherosa Ziehau if (std_cpuid < 0 || std_cpuid >= ncpus) { 2293841cdf08SSepherosa Ziehau device_printf(dev, "invalid std.cpuid %d, use %d\n", 2294841cdf08SSepherosa Ziehau std_cpuid, std_cpuid_def); 2295841cdf08SSepherosa Ziehau std_cpuid = std_cpuid_def; 2296841cdf08SSepherosa Ziehau } 2297841cdf08SSepherosa Ziehau 2298841cdf08SSepherosa Ziehau std = &sc->bnx_rx_std_ring; 2299841cdf08SSepherosa Ziehau lwkt_create(bnx_rx_std_refill_ithread, std, NULL, 2300841cdf08SSepherosa Ziehau &std->bnx_rx_std_ithread, TDF_NOSTART | TDF_INTTHREAD, std_cpuid, 2301841cdf08SSepherosa Ziehau "%s std", device_get_nameunit(dev)); 2302841cdf08SSepherosa Ziehau lwkt_setpri(&std->bnx_rx_std_ithread, TDPRI_INT_MED); 2303841cdf08SSepherosa Ziehau std->bnx_rx_std_ithread.td_preemptable = lwkt_preempt; 2304841cdf08SSepherosa Ziehau sc->bnx_flags |= BNX_FLAG_STD_THREAD; 2305841cdf08SSepherosa Ziehau 23066c8d8eccSSepherosa Ziehau return(0); 23076c8d8eccSSepherosa Ziehau fail: 23086c8d8eccSSepherosa Ziehau bnx_detach(dev); 23096c8d8eccSSepherosa Ziehau return(error); 23106c8d8eccSSepherosa Ziehau } 23116c8d8eccSSepherosa Ziehau 23126c8d8eccSSepherosa Ziehau static int 23136c8d8eccSSepherosa Ziehau bnx_detach(device_t dev) 23146c8d8eccSSepherosa Ziehau { 23156c8d8eccSSepherosa Ziehau struct bnx_softc *sc = device_get_softc(dev); 23166c8d8eccSSepherosa Ziehau 23176c8d8eccSSepherosa Ziehau if (device_is_attached(dev)) { 23186c8d8eccSSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if; 23196c8d8eccSSepherosa Ziehau 2320329f9016SSepherosa Ziehau ifnet_serialize_all(ifp); 23216c8d8eccSSepherosa Ziehau bnx_stop(sc); 23226c8d8eccSSepherosa Ziehau bnx_reset(sc); 2323f33ac8a4SSepherosa Ziehau bnx_teardown_intr(sc, sc->bnx_intr_cnt); 2324329f9016SSepherosa Ziehau ifnet_deserialize_all(ifp); 23256c8d8eccSSepherosa Ziehau 23266c8d8eccSSepherosa Ziehau ether_ifdetach(ifp); 23276c8d8eccSSepherosa Ziehau } 23286c8d8eccSSepherosa Ziehau 2329841cdf08SSepherosa Ziehau if (sc->bnx_flags & BNX_FLAG_STD_THREAD) { 2330841cdf08SSepherosa Ziehau struct bnx_rx_std_ring *std = &sc->bnx_rx_std_ring; 2331841cdf08SSepherosa Ziehau 2332841cdf08SSepherosa Ziehau tsleep_interlock(std, 0); 2333841cdf08SSepherosa Ziehau std->bnx_rx_std_stop = 1; 2334841cdf08SSepherosa Ziehau cpu_sfence(); 2335841cdf08SSepherosa Ziehau lwkt_schedule(&std->bnx_rx_std_ithread); 2336841cdf08SSepherosa Ziehau tsleep(std, PINTERLOCKED, "bnx_detach", 0); 2337841cdf08SSepherosa Ziehau if (bootverbose) 2338841cdf08SSepherosa Ziehau device_printf(dev, "RX std ithread exited\n"); 2339841cdf08SSepherosa Ziehau } 2340841cdf08SSepherosa Ziehau 23416c8d8eccSSepherosa Ziehau if (sc->bnx_flags & BNX_FLAG_TBI) 23426c8d8eccSSepherosa Ziehau ifmedia_removeall(&sc->bnx_ifmedia); 23436c8d8eccSSepherosa Ziehau if (sc->bnx_miibus) 23446c8d8eccSSepherosa Ziehau device_delete_child(dev, sc->bnx_miibus); 23456c8d8eccSSepherosa Ziehau bus_generic_detach(dev); 23466c8d8eccSSepherosa Ziehau 23470c7da01dSSepherosa Ziehau bnx_free_intr(sc); 23486c8d8eccSSepherosa Ziehau 23496c8d8eccSSepherosa Ziehau if (sc->bnx_res != NULL) { 23506c8d8eccSSepherosa Ziehau bus_release_resource(dev, SYS_RES_MEMORY, 23516c8d8eccSSepherosa Ziehau BGE_PCI_BAR0, sc->bnx_res); 23526c8d8eccSSepherosa Ziehau } 23536c8d8eccSSepherosa Ziehau 23546c8d8eccSSepherosa Ziehau if (sc->bnx_sysctl_tree != NULL) 23556c8d8eccSSepherosa Ziehau sysctl_ctx_free(&sc->bnx_sysctl_ctx); 23566c8d8eccSSepherosa Ziehau 23576c8d8eccSSepherosa Ziehau bnx_dma_free(sc); 23586c8d8eccSSepherosa Ziehau 2359329f9016SSepherosa Ziehau if (sc->bnx_serialize != NULL) 2360329f9016SSepherosa Ziehau kfree(sc->bnx_serialize, M_DEVBUF); 2361329f9016SSepherosa Ziehau 23626c8d8eccSSepherosa Ziehau return 0; 23636c8d8eccSSepherosa Ziehau } 23646c8d8eccSSepherosa Ziehau 23656c8d8eccSSepherosa Ziehau static void 23666c8d8eccSSepherosa Ziehau bnx_reset(struct bnx_softc *sc) 23676c8d8eccSSepherosa Ziehau { 23686c8d8eccSSepherosa Ziehau device_t dev; 23696c8d8eccSSepherosa Ziehau uint32_t cachesize, command, pcistate, reset; 23706c8d8eccSSepherosa Ziehau void (*write_op)(struct bnx_softc *, uint32_t, uint32_t); 23716c8d8eccSSepherosa Ziehau int i, val = 0; 23726c8d8eccSSepherosa Ziehau uint16_t devctl; 23736c8d8eccSSepherosa Ziehau 23746c8d8eccSSepherosa Ziehau dev = sc->bnx_dev; 23756c8d8eccSSepherosa Ziehau 23766c8d8eccSSepherosa Ziehau write_op = bnx_writemem_direct; 23776c8d8eccSSepherosa Ziehau 23786c8d8eccSSepherosa Ziehau /* Save some important PCI state. */ 23796c8d8eccSSepherosa Ziehau cachesize = pci_read_config(dev, BGE_PCI_CACHESZ, 4); 23806c8d8eccSSepherosa Ziehau command = pci_read_config(dev, BGE_PCI_CMD, 4); 23816c8d8eccSSepherosa Ziehau pcistate = pci_read_config(dev, BGE_PCI_PCISTATE, 4); 23826c8d8eccSSepherosa Ziehau 23836c8d8eccSSepherosa Ziehau pci_write_config(dev, BGE_PCI_MISC_CTL, 23846c8d8eccSSepherosa Ziehau BGE_PCIMISCCTL_INDIRECT_ACCESS|BGE_PCIMISCCTL_MASK_PCI_INTR| 23856c8d8eccSSepherosa Ziehau BGE_HIF_SWAP_OPTIONS|BGE_PCIMISCCTL_PCISTATE_RW| 23866c8d8eccSSepherosa Ziehau BGE_PCIMISCCTL_TAGGED_STATUS, 4); 23876c8d8eccSSepherosa Ziehau 23886c8d8eccSSepherosa Ziehau /* Disable fastboot on controllers that support it. */ 23896c8d8eccSSepherosa Ziehau if (bootverbose) 23906c8d8eccSSepherosa Ziehau if_printf(&sc->arpcom.ac_if, "Disabling fastboot\n"); 23916c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_FASTBOOT_PC, 0x0); 23926c8d8eccSSepherosa Ziehau 23936c8d8eccSSepherosa Ziehau /* 23946c8d8eccSSepherosa Ziehau * Write the magic number to SRAM at offset 0xB50. 23956c8d8eccSSepherosa Ziehau * When firmware finishes its initialization it will 23966c8d8eccSSepherosa Ziehau * write ~BGE_MAGIC_NUMBER to the same location. 23976c8d8eccSSepherosa Ziehau */ 23986c8d8eccSSepherosa Ziehau bnx_writemem_ind(sc, BGE_SOFTWARE_GENCOMM, BGE_MAGIC_NUMBER); 23996c8d8eccSSepherosa Ziehau 24006c8d8eccSSepherosa Ziehau reset = BGE_MISCCFG_RESET_CORE_CLOCKS|(65<<1); 24016c8d8eccSSepherosa Ziehau 24026c8d8eccSSepherosa Ziehau /* XXX: Broadcom Linux driver. */ 24036c8d8eccSSepherosa Ziehau /* Force PCI-E 1.0a mode */ 24043730a14dSSepherosa Ziehau if (!BNX_IS_57765_PLUS(sc) && 24056c8d8eccSSepherosa Ziehau CSR_READ_4(sc, BGE_PCIE_PHY_TSTCTL) == 24066c8d8eccSSepherosa Ziehau (BGE_PCIE_PHY_TSTCTL_PSCRAM | 24076c8d8eccSSepherosa Ziehau BGE_PCIE_PHY_TSTCTL_PCIE10)) { 24086c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_PCIE_PHY_TSTCTL, 24096c8d8eccSSepherosa Ziehau BGE_PCIE_PHY_TSTCTL_PSCRAM); 24106c8d8eccSSepherosa Ziehau } 24116c8d8eccSSepherosa Ziehau if (sc->bnx_chipid != BGE_CHIPID_BCM5750_A0) { 24126c8d8eccSSepherosa Ziehau /* Prevent PCIE link training during global reset */ 24136c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_MISC_CFG, (1<<29)); 24146c8d8eccSSepherosa Ziehau reset |= (1<<29); 24156c8d8eccSSepherosa Ziehau } 24166c8d8eccSSepherosa Ziehau 24176c8d8eccSSepherosa Ziehau /* 24186c8d8eccSSepherosa Ziehau * Set GPHY Power Down Override to leave GPHY 24196c8d8eccSSepherosa Ziehau * powered up in D0 uninitialized. 24206c8d8eccSSepherosa Ziehau */ 24216c8d8eccSSepherosa Ziehau if ((sc->bnx_flags & BNX_FLAG_CPMU) == 0) 24226c8d8eccSSepherosa Ziehau reset |= BGE_MISCCFG_GPHY_PD_OVERRIDE; 24236c8d8eccSSepherosa Ziehau 24246c8d8eccSSepherosa Ziehau /* Issue global reset */ 24256c8d8eccSSepherosa Ziehau write_op(sc, BGE_MISC_CFG, reset); 24266c8d8eccSSepherosa Ziehau 24276c8d8eccSSepherosa Ziehau DELAY(1000); 24286c8d8eccSSepherosa Ziehau 24296c8d8eccSSepherosa Ziehau /* XXX: Broadcom Linux driver. */ 24306c8d8eccSSepherosa Ziehau if (sc->bnx_chipid == BGE_CHIPID_BCM5750_A0) { 24316c8d8eccSSepherosa Ziehau uint32_t v; 24326c8d8eccSSepherosa Ziehau 24336c8d8eccSSepherosa Ziehau DELAY(500000); /* wait for link training to complete */ 24346c8d8eccSSepherosa Ziehau v = pci_read_config(dev, 0xc4, 4); 24356c8d8eccSSepherosa Ziehau pci_write_config(dev, 0xc4, v | (1<<15), 4); 24366c8d8eccSSepherosa Ziehau } 24376c8d8eccSSepherosa Ziehau 24386c8d8eccSSepherosa Ziehau devctl = pci_read_config(dev, sc->bnx_pciecap + PCIER_DEVCTRL, 2); 24396c8d8eccSSepherosa Ziehau 24406c8d8eccSSepherosa Ziehau /* Disable no snoop and disable relaxed ordering. */ 24416c8d8eccSSepherosa Ziehau devctl &= ~(PCIEM_DEVCTL_RELAX_ORDER | PCIEM_DEVCTL_NOSNOOP); 24426c8d8eccSSepherosa Ziehau 24436c8d8eccSSepherosa Ziehau /* Old PCI-E chips only support 128 bytes Max PayLoad Size. */ 24446c8d8eccSSepherosa Ziehau if ((sc->bnx_flags & BNX_FLAG_CPMU) == 0) { 24456c8d8eccSSepherosa Ziehau devctl &= ~PCIEM_DEVCTL_MAX_PAYLOAD_MASK; 24466c8d8eccSSepherosa Ziehau devctl |= PCIEM_DEVCTL_MAX_PAYLOAD_128; 24476c8d8eccSSepherosa Ziehau } 24486c8d8eccSSepherosa Ziehau 24496c8d8eccSSepherosa Ziehau pci_write_config(dev, sc->bnx_pciecap + PCIER_DEVCTRL, 24506c8d8eccSSepherosa Ziehau devctl, 2); 24516c8d8eccSSepherosa Ziehau 24526c8d8eccSSepherosa Ziehau /* Clear error status. */ 24536c8d8eccSSepherosa Ziehau pci_write_config(dev, sc->bnx_pciecap + PCIER_DEVSTS, 24546c8d8eccSSepherosa Ziehau PCIEM_DEVSTS_CORR_ERR | 24556c8d8eccSSepherosa Ziehau PCIEM_DEVSTS_NFATAL_ERR | 24566c8d8eccSSepherosa Ziehau PCIEM_DEVSTS_FATAL_ERR | 24576c8d8eccSSepherosa Ziehau PCIEM_DEVSTS_UNSUPP_REQ, 2); 24586c8d8eccSSepherosa Ziehau 24596c8d8eccSSepherosa Ziehau /* Reset some of the PCI state that got zapped by reset */ 24606c8d8eccSSepherosa Ziehau pci_write_config(dev, BGE_PCI_MISC_CTL, 24616c8d8eccSSepherosa Ziehau BGE_PCIMISCCTL_INDIRECT_ACCESS|BGE_PCIMISCCTL_MASK_PCI_INTR| 24626c8d8eccSSepherosa Ziehau BGE_HIF_SWAP_OPTIONS|BGE_PCIMISCCTL_PCISTATE_RW| 24636c8d8eccSSepherosa Ziehau BGE_PCIMISCCTL_TAGGED_STATUS, 4); 24646c8d8eccSSepherosa Ziehau pci_write_config(dev, BGE_PCI_CACHESZ, cachesize, 4); 24656c8d8eccSSepherosa Ziehau pci_write_config(dev, BGE_PCI_CMD, command, 4); 24666c8d8eccSSepherosa Ziehau write_op(sc, BGE_MISC_CFG, (65 << 1)); 24676c8d8eccSSepherosa Ziehau 24686c8d8eccSSepherosa Ziehau /* Enable memory arbiter */ 24696c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_MARB_MODE, BGE_MARBMODE_ENABLE); 24706c8d8eccSSepherosa Ziehau 24716c8d8eccSSepherosa Ziehau /* 24726c8d8eccSSepherosa Ziehau * Poll until we see the 1's complement of the magic number. 2473ddd93a5cSSepherosa Ziehau * This indicates that the firmware initialization is complete. 24746c8d8eccSSepherosa Ziehau */ 24756c8d8eccSSepherosa Ziehau for (i = 0; i < BNX_FIRMWARE_TIMEOUT; i++) { 24766c8d8eccSSepherosa Ziehau val = bnx_readmem_ind(sc, BGE_SOFTWARE_GENCOMM); 24776c8d8eccSSepherosa Ziehau if (val == ~BGE_MAGIC_NUMBER) 24786c8d8eccSSepherosa Ziehau break; 24796c8d8eccSSepherosa Ziehau DELAY(10); 24806c8d8eccSSepherosa Ziehau } 24816c8d8eccSSepherosa Ziehau if (i == BNX_FIRMWARE_TIMEOUT) { 24826c8d8eccSSepherosa Ziehau if_printf(&sc->arpcom.ac_if, "firmware handshake " 24836c8d8eccSSepherosa Ziehau "timed out, found 0x%08x\n", val); 24846c8d8eccSSepherosa Ziehau } 24856c8d8eccSSepherosa Ziehau 24866c8d8eccSSepherosa Ziehau /* BCM57765 A0 needs additional time before accessing. */ 24876c8d8eccSSepherosa Ziehau if (sc->bnx_chipid == BGE_CHIPID_BCM57765_A0) 24886c8d8eccSSepherosa Ziehau DELAY(10 * 1000); 24896c8d8eccSSepherosa Ziehau 24906c8d8eccSSepherosa Ziehau /* 24916c8d8eccSSepherosa Ziehau * XXX Wait for the value of the PCISTATE register to 24926c8d8eccSSepherosa Ziehau * return to its original pre-reset state. This is a 24936c8d8eccSSepherosa Ziehau * fairly good indicator of reset completion. If we don't 24946c8d8eccSSepherosa Ziehau * wait for the reset to fully complete, trying to read 24956c8d8eccSSepherosa Ziehau * from the device's non-PCI registers may yield garbage 24966c8d8eccSSepherosa Ziehau * results. 24976c8d8eccSSepherosa Ziehau */ 24986c8d8eccSSepherosa Ziehau for (i = 0; i < BNX_TIMEOUT; i++) { 24996c8d8eccSSepherosa Ziehau if (pci_read_config(dev, BGE_PCI_PCISTATE, 4) == pcistate) 25006c8d8eccSSepherosa Ziehau break; 25016c8d8eccSSepherosa Ziehau DELAY(10); 25026c8d8eccSSepherosa Ziehau } 25036c8d8eccSSepherosa Ziehau 25046c8d8eccSSepherosa Ziehau /* Fix up byte swapping */ 25056c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_MODE_CTL, bnx_dma_swap_options(sc)); 25066c8d8eccSSepherosa Ziehau 25076c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_MAC_MODE, 0); 25086c8d8eccSSepherosa Ziehau 25096c8d8eccSSepherosa Ziehau /* 25106c8d8eccSSepherosa Ziehau * The 5704 in TBI mode apparently needs some special 25116c8d8eccSSepherosa Ziehau * adjustment to insure the SERDES drive level is set 25126c8d8eccSSepherosa Ziehau * to 1.2V. 25136c8d8eccSSepherosa Ziehau */ 25146c8d8eccSSepherosa Ziehau if (sc->bnx_asicrev == BGE_ASICREV_BCM5704 && 25156c8d8eccSSepherosa Ziehau (sc->bnx_flags & BNX_FLAG_TBI)) { 25166c8d8eccSSepherosa Ziehau uint32_t serdescfg; 25176c8d8eccSSepherosa Ziehau 25186c8d8eccSSepherosa Ziehau serdescfg = CSR_READ_4(sc, BGE_SERDES_CFG); 25196c8d8eccSSepherosa Ziehau serdescfg = (serdescfg & ~0xFFF) | 0x880; 25206c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_SERDES_CFG, serdescfg); 25216c8d8eccSSepherosa Ziehau } 25226c8d8eccSSepherosa Ziehau 25237892075dSSepherosa Ziehau CSR_WRITE_4(sc, BGE_MI_MODE, 25247892075dSSepherosa Ziehau sc->bnx_mi_mode & ~BGE_MIMODE_AUTOPOLL); 25257892075dSSepherosa Ziehau DELAY(80); 25267892075dSSepherosa Ziehau 25276c8d8eccSSepherosa Ziehau /* XXX: Broadcom Linux driver. */ 25283730a14dSSepherosa Ziehau if (!BNX_IS_57765_PLUS(sc)) { 25296c8d8eccSSepherosa Ziehau uint32_t v; 25306c8d8eccSSepherosa Ziehau 25316c8d8eccSSepherosa Ziehau /* Enable Data FIFO protection. */ 2532f1f34fc4SSepherosa Ziehau v = CSR_READ_4(sc, BGE_PCIE_TLDLPL_PORT); 2533f1f34fc4SSepherosa Ziehau CSR_WRITE_4(sc, BGE_PCIE_TLDLPL_PORT, v | (1 << 25)); 25346c8d8eccSSepherosa Ziehau } 25356c8d8eccSSepherosa Ziehau 25366c8d8eccSSepherosa Ziehau DELAY(10000); 25376c8d8eccSSepherosa Ziehau 25386c8d8eccSSepherosa Ziehau if (sc->bnx_asicrev == BGE_ASICREV_BCM5720) { 25396c8d8eccSSepherosa Ziehau BNX_CLRBIT(sc, BGE_CPMU_CLCK_ORIDE, 25406c8d8eccSSepherosa Ziehau CPMU_CLCK_ORIDE_MAC_ORIDE_EN); 25416c8d8eccSSepherosa Ziehau } 25426c8d8eccSSepherosa Ziehau } 25436c8d8eccSSepherosa Ziehau 25446c8d8eccSSepherosa Ziehau /* 25456c8d8eccSSepherosa Ziehau * Frame reception handling. This is called if there's a frame 25466c8d8eccSSepherosa Ziehau * on the receive return list. 25476c8d8eccSSepherosa Ziehau * 25486c8d8eccSSepherosa Ziehau * Note: we have to be able to handle two possibilities here: 25496c8d8eccSSepherosa Ziehau * 1) the frame is from the jumbo recieve ring 25506c8d8eccSSepherosa Ziehau * 2) the frame is from the standard receive ring 25516c8d8eccSSepherosa Ziehau */ 25526c8d8eccSSepherosa Ziehau 25536c8d8eccSSepherosa Ziehau static void 2554beedf5beSSepherosa Ziehau bnx_rxeof(struct bnx_rx_ret_ring *ret, uint16_t rx_prod, int count) 25556c8d8eccSSepherosa Ziehau { 2556beedf5beSSepherosa Ziehau struct bnx_softc *sc = ret->bnx_sc; 2557beedf5beSSepherosa Ziehau struct bnx_rx_std_ring *std = ret->bnx_std; 2558beedf5beSSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if; 25596c8d8eccSSepherosa Ziehau 2560beedf5beSSepherosa Ziehau while (ret->bnx_rx_saved_considx != rx_prod && count != 0) { 25616c8d8eccSSepherosa Ziehau struct bge_rx_bd *cur_rx; 2562841cdf08SSepherosa Ziehau struct bnx_rx_buf *rb; 25636c8d8eccSSepherosa Ziehau uint32_t rxidx; 25646c8d8eccSSepherosa Ziehau struct mbuf *m = NULL; 25656c8d8eccSSepherosa Ziehau uint16_t vlan_tag = 0; 25666c8d8eccSSepherosa Ziehau int have_tag = 0; 25676c8d8eccSSepherosa Ziehau 256897381780SSepherosa Ziehau --count; 256997381780SSepherosa Ziehau 2570beedf5beSSepherosa Ziehau cur_rx = &ret->bnx_rx_ret_ring[ret->bnx_rx_saved_considx]; 25716c8d8eccSSepherosa Ziehau 25726c8d8eccSSepherosa Ziehau rxidx = cur_rx->bge_idx; 2573beedf5beSSepherosa Ziehau BNX_INC(ret->bnx_rx_saved_considx, BNX_RETURN_RING_CNT); 25746c8d8eccSSepherosa Ziehau 25756c8d8eccSSepherosa Ziehau if (cur_rx->bge_flags & BGE_RXBDFLAG_VLAN_TAG) { 25766c8d8eccSSepherosa Ziehau have_tag = 1; 25776c8d8eccSSepherosa Ziehau vlan_tag = cur_rx->bge_vlan_tag; 25786c8d8eccSSepherosa Ziehau } 25796c8d8eccSSepherosa Ziehau 2580841cdf08SSepherosa Ziehau if (ret->bnx_rx_cnt >= ret->bnx_rx_cntmax) { 2581841cdf08SSepherosa Ziehau ret->bnx_rx_cnt = 0; 2582841cdf08SSepherosa Ziehau cpu_sfence(); 2583841cdf08SSepherosa Ziehau atomic_set_int(&std->bnx_rx_std_refill, 2584841cdf08SSepherosa Ziehau ret->bnx_rx_mask); 2585841cdf08SSepherosa Ziehau if (atomic_poll_acquire_int(&std->bnx_rx_std_running)) 2586841cdf08SSepherosa Ziehau lwkt_schedule(&std->bnx_rx_std_ithread); 25876c8d8eccSSepherosa Ziehau } 2588841cdf08SSepherosa Ziehau ret->bnx_rx_cnt++; 25896c8d8eccSSepherosa Ziehau 2590841cdf08SSepherosa Ziehau rb = &std->bnx_rx_std_buf[rxidx]; 2591841cdf08SSepherosa Ziehau m = rb->bnx_rx_mbuf; 25926c8d8eccSSepherosa Ziehau if (cur_rx->bge_flags & BGE_RXBDFLAG_ERROR) { 2593d40991efSSepherosa Ziehau IFNET_STAT_INC(ifp, ierrors, 1); 2594841cdf08SSepherosa Ziehau cpu_sfence(); 2595841cdf08SSepherosa Ziehau rb->bnx_rx_refilled = 1; 25966c8d8eccSSepherosa Ziehau continue; 25976c8d8eccSSepherosa Ziehau } 2598841cdf08SSepherosa Ziehau if (bnx_newbuf_std(ret, rxidx, 0)) { 2599d40991efSSepherosa Ziehau IFNET_STAT_INC(ifp, ierrors, 1); 26006c8d8eccSSepherosa Ziehau continue; 26016c8d8eccSSepherosa Ziehau } 26026c8d8eccSSepherosa Ziehau 2603d40991efSSepherosa Ziehau IFNET_STAT_INC(ifp, ipackets, 1); 26046c8d8eccSSepherosa Ziehau m->m_pkthdr.len = m->m_len = cur_rx->bge_len - ETHER_CRC_LEN; 26056c8d8eccSSepherosa Ziehau m->m_pkthdr.rcvif = ifp; 26066c8d8eccSSepherosa Ziehau 26076c8d8eccSSepherosa Ziehau if ((ifp->if_capenable & IFCAP_RXCSUM) && 26086c8d8eccSSepherosa Ziehau (cur_rx->bge_flags & BGE_RXBDFLAG_IPV6) == 0) { 26096c8d8eccSSepherosa Ziehau if (cur_rx->bge_flags & BGE_RXBDFLAG_IP_CSUM) { 26106c8d8eccSSepherosa Ziehau m->m_pkthdr.csum_flags |= CSUM_IP_CHECKED; 26116c8d8eccSSepherosa Ziehau if ((cur_rx->bge_error_flag & 26126c8d8eccSSepherosa Ziehau BGE_RXERRFLAG_IP_CSUM_NOK) == 0) 26136c8d8eccSSepherosa Ziehau m->m_pkthdr.csum_flags |= CSUM_IP_VALID; 26146c8d8eccSSepherosa Ziehau } 26156c8d8eccSSepherosa Ziehau if (cur_rx->bge_flags & BGE_RXBDFLAG_TCP_UDP_CSUM) { 26166c8d8eccSSepherosa Ziehau m->m_pkthdr.csum_data = 26176c8d8eccSSepherosa Ziehau cur_rx->bge_tcp_udp_csum; 26186c8d8eccSSepherosa Ziehau m->m_pkthdr.csum_flags |= CSUM_DATA_VALID | 26196c8d8eccSSepherosa Ziehau CSUM_PSEUDO_HDR; 26206c8d8eccSSepherosa Ziehau } 26216c8d8eccSSepherosa Ziehau } 26226c8d8eccSSepherosa Ziehau 26236c8d8eccSSepherosa Ziehau /* 26246c8d8eccSSepherosa Ziehau * If we received a packet with a vlan tag, pass it 26256c8d8eccSSepherosa Ziehau * to vlan_input() instead of ether_input(). 26266c8d8eccSSepherosa Ziehau */ 26276c8d8eccSSepherosa Ziehau if (have_tag) { 26286c8d8eccSSepherosa Ziehau m->m_flags |= M_VLANTAG; 26296c8d8eccSSepherosa Ziehau m->m_pkthdr.ether_vlantag = vlan_tag; 26306c8d8eccSSepherosa Ziehau } 26316c8d8eccSSepherosa Ziehau ifp->if_input(ifp, m); 26326c8d8eccSSepherosa Ziehau } 2633ac2936fdSSepherosa Ziehau bnx_writembx(sc, ret->bnx_rx_mbx, ret->bnx_rx_saved_considx); 26346c8d8eccSSepherosa Ziehau } 26356c8d8eccSSepherosa Ziehau 26366c8d8eccSSepherosa Ziehau static void 263733a04907SSepherosa Ziehau bnx_txeof(struct bnx_tx_ring *txr, uint16_t tx_cons) 26386c8d8eccSSepherosa Ziehau { 263933a04907SSepherosa Ziehau struct ifnet *ifp = &txr->bnx_sc->arpcom.ac_if; 26406c8d8eccSSepherosa Ziehau 26416c8d8eccSSepherosa Ziehau /* 26426c8d8eccSSepherosa Ziehau * Go through our tx ring and free mbufs for those 26436c8d8eccSSepherosa Ziehau * frames that have been sent. 26446c8d8eccSSepherosa Ziehau */ 264533a04907SSepherosa Ziehau while (txr->bnx_tx_saved_considx != tx_cons) { 2646fa4b1067SSepherosa Ziehau struct bnx_tx_buf *buf; 26476c8d8eccSSepherosa Ziehau uint32_t idx = 0; 26486c8d8eccSSepherosa Ziehau 264933a04907SSepherosa Ziehau idx = txr->bnx_tx_saved_considx; 2650fa4b1067SSepherosa Ziehau buf = &txr->bnx_tx_buf[idx]; 2651fa4b1067SSepherosa Ziehau if (buf->bnx_tx_mbuf != NULL) { 2652d40991efSSepherosa Ziehau IFNET_STAT_INC(ifp, opackets, 1); 265333a04907SSepherosa Ziehau bus_dmamap_unload(txr->bnx_tx_mtag, 2654fa4b1067SSepherosa Ziehau buf->bnx_tx_dmamap); 2655fa4b1067SSepherosa Ziehau m_freem(buf->bnx_tx_mbuf); 2656fa4b1067SSepherosa Ziehau buf->bnx_tx_mbuf = NULL; 26576c8d8eccSSepherosa Ziehau } 2658fa639b88SSepherosa Ziehau txr->bnx_tx_cnt--; 265933a04907SSepherosa Ziehau BNX_INC(txr->bnx_tx_saved_considx, BGE_TX_RING_CNT); 26606c8d8eccSSepherosa Ziehau } 26616c8d8eccSSepherosa Ziehau 2662fa639b88SSepherosa Ziehau if ((BGE_TX_RING_CNT - txr->bnx_tx_cnt) >= 26636c8d8eccSSepherosa Ziehau (BNX_NSEG_RSVD + BNX_NSEG_SPARE)) 26643397dea6SSepherosa Ziehau ifsq_clr_oactive(txr->bnx_ifsq); 26656c8d8eccSSepherosa Ziehau 2666fa639b88SSepherosa Ziehau if (txr->bnx_tx_cnt == 0) 26673397dea6SSepherosa Ziehau txr->bnx_tx_watchdog.wd_timer = 0; 26686c8d8eccSSepherosa Ziehau 26693397dea6SSepherosa Ziehau if (!ifsq_is_empty(txr->bnx_ifsq)) 26703397dea6SSepherosa Ziehau ifsq_devstart(txr->bnx_ifsq); 26716c8d8eccSSepherosa Ziehau } 26726c8d8eccSSepherosa Ziehau 267339a8d43aSSepherosa Ziehau #ifdef IFPOLL_ENABLE 26746c8d8eccSSepherosa Ziehau 26756c8d8eccSSepherosa Ziehau static void 26764fa38985SSepherosa Ziehau bnx_npoll_rx(struct ifnet *ifp __unused, void *xret, int cycle) 26774fa38985SSepherosa Ziehau { 26784fa38985SSepherosa Ziehau struct bnx_rx_ret_ring *ret = xret; 26794fa38985SSepherosa Ziehau uint16_t rx_prod; 26804fa38985SSepherosa Ziehau 26814fa38985SSepherosa Ziehau ASSERT_SERIALIZED(&ret->bnx_rx_ret_serialize); 26824fa38985SSepherosa Ziehau 26834fa38985SSepherosa Ziehau ret->bnx_saved_status_tag = *ret->bnx_hw_status_tag; 26844fa38985SSepherosa Ziehau cpu_lfence(); 26854fa38985SSepherosa Ziehau 26864fa38985SSepherosa Ziehau rx_prod = *ret->bnx_rx_considx; 26874fa38985SSepherosa Ziehau if (ret->bnx_rx_saved_considx != rx_prod) 26884fa38985SSepherosa Ziehau bnx_rxeof(ret, rx_prod, cycle); 26894fa38985SSepherosa Ziehau } 26904fa38985SSepherosa Ziehau 26914fa38985SSepherosa Ziehau static void 26924fa38985SSepherosa Ziehau bnx_npoll_tx(struct ifnet *ifp __unused, void *xtxr, int cycle __unused) 26934fa38985SSepherosa Ziehau { 26944fa38985SSepherosa Ziehau struct bnx_tx_ring *txr = xtxr; 26954fa38985SSepherosa Ziehau uint16_t tx_cons; 26964fa38985SSepherosa Ziehau 26974fa38985SSepherosa Ziehau ASSERT_SERIALIZED(&txr->bnx_tx_serialize); 26984fa38985SSepherosa Ziehau 26994fa38985SSepherosa Ziehau tx_cons = *txr->bnx_tx_considx; 27004fa38985SSepherosa Ziehau if (txr->bnx_tx_saved_considx != tx_cons) 27014fa38985SSepherosa Ziehau bnx_txeof(txr, tx_cons); 27024fa38985SSepherosa Ziehau } 27034fa38985SSepherosa Ziehau 27044fa38985SSepherosa Ziehau static void 27054fa38985SSepherosa Ziehau bnx_npoll_status(struct ifnet *ifp) 27064fa38985SSepherosa Ziehau { 27074fa38985SSepherosa Ziehau struct bnx_softc *sc = ifp->if_softc; 2708*0a806e3aSSepherosa Ziehau struct bge_status_block *sblk = sc->bnx_intr_data[0].bnx_status_block; 27094fa38985SSepherosa Ziehau 27104fa38985SSepherosa Ziehau ASSERT_SERIALIZED(&sc->bnx_main_serialize); 27114fa38985SSepherosa Ziehau 27124fa38985SSepherosa Ziehau if ((sblk->bge_status & BGE_STATFLAG_LINKSTATE_CHANGED) || 27134fa38985SSepherosa Ziehau sc->bnx_link_evt) 27144fa38985SSepherosa Ziehau bnx_link_poll(sc); 27154fa38985SSepherosa Ziehau } 27164fa38985SSepherosa Ziehau 27174fa38985SSepherosa Ziehau static void 271839a8d43aSSepherosa Ziehau bnx_npoll(struct ifnet *ifp, struct ifpoll_info *info) 271939a8d43aSSepherosa Ziehau { 272039a8d43aSSepherosa Ziehau struct bnx_softc *sc = ifp->if_softc; 27214fa38985SSepherosa Ziehau int i; 272239a8d43aSSepherosa Ziehau 2723329f9016SSepherosa Ziehau ASSERT_IFNET_SERIALIZED_ALL(ifp); 272439a8d43aSSepherosa Ziehau 272539a8d43aSSepherosa Ziehau if (info != NULL) { 27264fa38985SSepherosa Ziehau /* 27274fa38985SSepherosa Ziehau * TODO handle RXTX bundle and non-bundle 27284fa38985SSepherosa Ziehau */ 27294fa38985SSepherosa Ziehau info->ifpi_status.status_func = bnx_npoll_status; 27304fa38985SSepherosa Ziehau info->ifpi_status.serializer = &sc->bnx_main_serialize; 273139a8d43aSSepherosa Ziehau 27324fa38985SSepherosa Ziehau for (i = 0; i < sc->bnx_tx_ringcnt; ++i) { 27334fa38985SSepherosa Ziehau struct bnx_tx_ring *txr = &sc->bnx_tx_ring[i]; 27344fa38985SSepherosa Ziehau int idx = i + sc->bnx_npoll_txoff; 27354fa38985SSepherosa Ziehau 27364fa38985SSepherosa Ziehau KKASSERT(idx < ncpus2); 27374fa38985SSepherosa Ziehau info->ifpi_tx[idx].poll_func = bnx_npoll_tx; 27384fa38985SSepherosa Ziehau info->ifpi_tx[idx].arg = txr; 27394fa38985SSepherosa Ziehau info->ifpi_tx[idx].serializer = &txr->bnx_tx_serialize; 27404fa38985SSepherosa Ziehau ifsq_set_cpuid(txr->bnx_ifsq, idx); 27414fa38985SSepherosa Ziehau } 27424fa38985SSepherosa Ziehau 27434fa38985SSepherosa Ziehau for (i = 0; i < sc->bnx_rx_retcnt; ++i) { 27444fa38985SSepherosa Ziehau struct bnx_rx_ret_ring *ret = &sc->bnx_rx_ret_ring[i]; 27454fa38985SSepherosa Ziehau int idx = i + sc->bnx_npoll_rxoff; 27464fa38985SSepherosa Ziehau 27474fa38985SSepherosa Ziehau KKASSERT(idx < ncpus2); 27484fa38985SSepherosa Ziehau info->ifpi_rx[idx].poll_func = bnx_npoll_rx; 27494fa38985SSepherosa Ziehau info->ifpi_rx[idx].arg = ret; 27504fa38985SSepherosa Ziehau info->ifpi_rx[idx].serializer = 27514fa38985SSepherosa Ziehau &ret->bnx_rx_ret_serialize; 27524fa38985SSepherosa Ziehau } 275339a8d43aSSepherosa Ziehau 27547dbaa833SSepherosa Ziehau if (ifp->if_flags & IFF_RUNNING) { 275539a8d43aSSepherosa Ziehau bnx_disable_intr(sc); 27567dbaa833SSepherosa Ziehau bnx_set_tick_cpuid(sc, TRUE); 27577dbaa833SSepherosa Ziehau } 275839a8d43aSSepherosa Ziehau } else { 27594fa38985SSepherosa Ziehau for (i = 0; i < sc->bnx_tx_ringcnt; ++i) { 27604fa38985SSepherosa Ziehau ifsq_set_cpuid(sc->bnx_tx_ring[i].bnx_ifsq, 27614fa38985SSepherosa Ziehau sc->bnx_tx_ring[i].bnx_tx_cpuid); 27624fa38985SSepherosa Ziehau } 27637dbaa833SSepherosa Ziehau if (ifp->if_flags & IFF_RUNNING) { 276439a8d43aSSepherosa Ziehau bnx_enable_intr(sc); 27657dbaa833SSepherosa Ziehau bnx_set_tick_cpuid(sc, FALSE); 27667dbaa833SSepherosa Ziehau } 276739a8d43aSSepherosa Ziehau } 276839a8d43aSSepherosa Ziehau } 276939a8d43aSSepherosa Ziehau 277039a8d43aSSepherosa Ziehau #endif /* IFPOLL_ENABLE */ 27716c8d8eccSSepherosa Ziehau 27726c8d8eccSSepherosa Ziehau static void 27736c8d8eccSSepherosa Ziehau bnx_intr_legacy(void *xsc) 27746c8d8eccSSepherosa Ziehau { 27756c8d8eccSSepherosa Ziehau struct bnx_softc *sc = xsc; 27764fa38985SSepherosa Ziehau struct bnx_rx_ret_ring *ret = &sc->bnx_rx_ret_ring[0]; 27776c8d8eccSSepherosa Ziehau 27784fa38985SSepherosa Ziehau if (ret->bnx_saved_status_tag == *ret->bnx_hw_status_tag) { 27796c8d8eccSSepherosa Ziehau uint32_t val; 27806c8d8eccSSepherosa Ziehau 27816c8d8eccSSepherosa Ziehau val = pci_read_config(sc->bnx_dev, BGE_PCI_PCISTATE, 4); 27826c8d8eccSSepherosa Ziehau if (val & BGE_PCISTAT_INTR_NOTACT) 27836c8d8eccSSepherosa Ziehau return; 27846c8d8eccSSepherosa Ziehau } 27856c8d8eccSSepherosa Ziehau 27866c8d8eccSSepherosa Ziehau /* 27876c8d8eccSSepherosa Ziehau * NOTE: 27886c8d8eccSSepherosa Ziehau * Interrupt will have to be disabled if tagged status 27896c8d8eccSSepherosa Ziehau * is used, else interrupt will always be asserted on 27906c8d8eccSSepherosa Ziehau * certain chips (at least on BCM5750 AX/BX). 27916c8d8eccSSepherosa Ziehau */ 27926c8d8eccSSepherosa Ziehau bnx_writembx(sc, BGE_MBX_IRQ0_LO, 1); 27936c8d8eccSSepherosa Ziehau 27946c8d8eccSSepherosa Ziehau bnx_intr(sc); 27956c8d8eccSSepherosa Ziehau } 27966c8d8eccSSepherosa Ziehau 27976c8d8eccSSepherosa Ziehau static void 27986c8d8eccSSepherosa Ziehau bnx_msi(void *xsc) 27996c8d8eccSSepherosa Ziehau { 28006c8d8eccSSepherosa Ziehau struct bnx_softc *sc = xsc; 28016c8d8eccSSepherosa Ziehau 28026c8d8eccSSepherosa Ziehau /* Disable interrupt first */ 28036c8d8eccSSepherosa Ziehau bnx_writembx(sc, BGE_MBX_IRQ0_LO, 1); 28046c8d8eccSSepherosa Ziehau bnx_intr(sc); 28056c8d8eccSSepherosa Ziehau } 28066c8d8eccSSepherosa Ziehau 28076c8d8eccSSepherosa Ziehau static void 28086c8d8eccSSepherosa Ziehau bnx_msi_oneshot(void *xsc) 28096c8d8eccSSepherosa Ziehau { 28106c8d8eccSSepherosa Ziehau bnx_intr(xsc); 28116c8d8eccSSepherosa Ziehau } 28126c8d8eccSSepherosa Ziehau 28136c8d8eccSSepherosa Ziehau static void 28146c8d8eccSSepherosa Ziehau bnx_intr(struct bnx_softc *sc) 28156c8d8eccSSepherosa Ziehau { 28166c8d8eccSSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if; 28174fa38985SSepherosa Ziehau struct bnx_rx_ret_ring *ret = &sc->bnx_rx_ret_ring[0]; 2818*0a806e3aSSepherosa Ziehau struct bge_status_block *sblk = sc->bnx_intr_data[0].bnx_status_block; 28196c8d8eccSSepherosa Ziehau uint32_t status; 28206c8d8eccSSepherosa Ziehau 2821329f9016SSepherosa Ziehau ASSERT_SERIALIZED(&sc->bnx_main_serialize); 2822329f9016SSepherosa Ziehau 28234fa38985SSepherosa Ziehau ret->bnx_saved_status_tag = *ret->bnx_hw_status_tag; 28246c8d8eccSSepherosa Ziehau /* 28256c8d8eccSSepherosa Ziehau * Use a load fence to ensure that status_tag is saved 28266c8d8eccSSepherosa Ziehau * before rx_prod, tx_cons and status. 28276c8d8eccSSepherosa Ziehau */ 28286c8d8eccSSepherosa Ziehau cpu_lfence(); 28296c8d8eccSSepherosa Ziehau 28306c8d8eccSSepherosa Ziehau status = sblk->bge_status; 28316c8d8eccSSepherosa Ziehau 28326c8d8eccSSepherosa Ziehau if ((status & BGE_STATFLAG_LINKSTATE_CHANGED) || sc->bnx_link_evt) 28336c8d8eccSSepherosa Ziehau bnx_link_poll(sc); 28346c8d8eccSSepherosa Ziehau 28356c8d8eccSSepherosa Ziehau if (ifp->if_flags & IFF_RUNNING) { 28364fa38985SSepherosa Ziehau struct bnx_tx_ring *txr = &sc->bnx_tx_ring[0]; 28373a16b7b8SSepherosa Ziehau uint16_t rx_prod, tx_cons; 28383a16b7b8SSepherosa Ziehau 2839329f9016SSepherosa Ziehau lwkt_serialize_enter(&ret->bnx_rx_ret_serialize); 28403a16b7b8SSepherosa Ziehau rx_prod = *ret->bnx_rx_considx; 2841beedf5beSSepherosa Ziehau if (ret->bnx_rx_saved_considx != rx_prod) 2842beedf5beSSepherosa Ziehau bnx_rxeof(ret, rx_prod, -1); 2843329f9016SSepherosa Ziehau lwkt_serialize_exit(&ret->bnx_rx_ret_serialize); 28446c8d8eccSSepherosa Ziehau 2845329f9016SSepherosa Ziehau lwkt_serialize_enter(&txr->bnx_tx_serialize); 2846329f9016SSepherosa Ziehau tx_cons = *txr->bnx_tx_considx; 284733a04907SSepherosa Ziehau if (txr->bnx_tx_saved_considx != tx_cons) 284833a04907SSepherosa Ziehau bnx_txeof(txr, tx_cons); 2849329f9016SSepherosa Ziehau lwkt_serialize_exit(&txr->bnx_tx_serialize); 28506c8d8eccSSepherosa Ziehau } 28516c8d8eccSSepherosa Ziehau 28524fa38985SSepherosa Ziehau bnx_writembx(sc, BGE_MBX_IRQ0_LO, ret->bnx_saved_status_tag << 24); 28536c8d8eccSSepherosa Ziehau } 28546c8d8eccSSepherosa Ziehau 28556c8d8eccSSepherosa Ziehau static void 28566c8d8eccSSepherosa Ziehau bnx_tick(void *xsc) 28576c8d8eccSSepherosa Ziehau { 28586c8d8eccSSepherosa Ziehau struct bnx_softc *sc = xsc; 28596c8d8eccSSepherosa Ziehau 2860329f9016SSepherosa Ziehau lwkt_serialize_enter(&sc->bnx_main_serialize); 28616c8d8eccSSepherosa Ziehau 28626c8d8eccSSepherosa Ziehau bnx_stats_update_regs(sc); 28636c8d8eccSSepherosa Ziehau 28646c8d8eccSSepherosa Ziehau if (sc->bnx_flags & BNX_FLAG_TBI) { 28656c8d8eccSSepherosa Ziehau /* 28666c8d8eccSSepherosa Ziehau * Since in TBI mode auto-polling can't be used we should poll 28676c8d8eccSSepherosa Ziehau * link status manually. Here we register pending link event 28686c8d8eccSSepherosa Ziehau * and trigger interrupt. 28696c8d8eccSSepherosa Ziehau */ 28706c8d8eccSSepherosa Ziehau sc->bnx_link_evt++; 28716c8d8eccSSepherosa Ziehau BNX_SETBIT(sc, BGE_HCC_MODE, BGE_HCCMODE_COAL_NOW); 28726c8d8eccSSepherosa Ziehau } else if (!sc->bnx_link) { 28736c8d8eccSSepherosa Ziehau mii_tick(device_get_softc(sc->bnx_miibus)); 28746c8d8eccSSepherosa Ziehau } 28756c8d8eccSSepherosa Ziehau 28767dbaa833SSepherosa Ziehau callout_reset_bycpu(&sc->bnx_tick_timer, hz, bnx_tick, sc, 28777dbaa833SSepherosa Ziehau sc->bnx_tick_cpuid); 28786c8d8eccSSepherosa Ziehau 2879329f9016SSepherosa Ziehau lwkt_serialize_exit(&sc->bnx_main_serialize); 28806c8d8eccSSepherosa Ziehau } 28816c8d8eccSSepherosa Ziehau 28826c8d8eccSSepherosa Ziehau static void 28836c8d8eccSSepherosa Ziehau bnx_stats_update_regs(struct bnx_softc *sc) 28846c8d8eccSSepherosa Ziehau { 28856c8d8eccSSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if; 28866c8d8eccSSepherosa Ziehau struct bge_mac_stats_regs stats; 28876c8d8eccSSepherosa Ziehau uint32_t *s; 28886c8d8eccSSepherosa Ziehau int i; 28896c8d8eccSSepherosa Ziehau 28906c8d8eccSSepherosa Ziehau s = (uint32_t *)&stats; 28916c8d8eccSSepherosa Ziehau for (i = 0; i < sizeof(struct bge_mac_stats_regs); i += 4) { 28926c8d8eccSSepherosa Ziehau *s = CSR_READ_4(sc, BGE_RX_STATS + i); 28936c8d8eccSSepherosa Ziehau s++; 28946c8d8eccSSepherosa Ziehau } 28956c8d8eccSSepherosa Ziehau 2896d40991efSSepherosa Ziehau IFNET_STAT_SET(ifp, collisions, 28976c8d8eccSSepherosa Ziehau (stats.dot3StatsSingleCollisionFrames + 28986c8d8eccSSepherosa Ziehau stats.dot3StatsMultipleCollisionFrames + 28996c8d8eccSSepherosa Ziehau stats.dot3StatsExcessiveCollisions + 2900d40991efSSepherosa Ziehau stats.dot3StatsLateCollisions)); 29016c8d8eccSSepherosa Ziehau } 29026c8d8eccSSepherosa Ziehau 29036c8d8eccSSepherosa Ziehau /* 29046c8d8eccSSepherosa Ziehau * Encapsulate an mbuf chain in the tx ring by coupling the mbuf data 29056c8d8eccSSepherosa Ziehau * pointers to descriptors. 29066c8d8eccSSepherosa Ziehau */ 29076c8d8eccSSepherosa Ziehau static int 290833a04907SSepherosa Ziehau bnx_encap(struct bnx_tx_ring *txr, struct mbuf **m_head0, uint32_t *txidx, 2909c9b7f592SSepherosa Ziehau int *segs_used) 29106c8d8eccSSepherosa Ziehau { 29116c8d8eccSSepherosa Ziehau struct bge_tx_bd *d = NULL; 291266deb1c1SSepherosa Ziehau uint16_t csum_flags = 0, vlan_tag = 0, mss = 0; 29136c8d8eccSSepherosa Ziehau bus_dma_segment_t segs[BNX_NSEG_NEW]; 29146c8d8eccSSepherosa Ziehau bus_dmamap_t map; 29156c8d8eccSSepherosa Ziehau int error, maxsegs, nsegs, idx, i; 29166c8d8eccSSepherosa Ziehau struct mbuf *m_head = *m_head0, *m_new; 29176c8d8eccSSepherosa Ziehau 291866deb1c1SSepherosa Ziehau if (m_head->m_pkthdr.csum_flags & CSUM_TSO) { 291966deb1c1SSepherosa Ziehau #ifdef BNX_TSO_DEBUG 292066deb1c1SSepherosa Ziehau int tso_nsegs; 292166deb1c1SSepherosa Ziehau #endif 292266deb1c1SSepherosa Ziehau 292333a04907SSepherosa Ziehau error = bnx_setup_tso(txr, m_head0, &mss, &csum_flags); 292466deb1c1SSepherosa Ziehau if (error) 292566deb1c1SSepherosa Ziehau return error; 292666deb1c1SSepherosa Ziehau m_head = *m_head0; 292766deb1c1SSepherosa Ziehau 292866deb1c1SSepherosa Ziehau #ifdef BNX_TSO_DEBUG 2929f0336d39SSepherosa Ziehau tso_nsegs = (m_head->m_pkthdr.len / 2930f0336d39SSepherosa Ziehau m_head->m_pkthdr.tso_segsz) - 1; 293166deb1c1SSepherosa Ziehau if (tso_nsegs > (BNX_TSO_NSTATS - 1)) 293266deb1c1SSepherosa Ziehau tso_nsegs = BNX_TSO_NSTATS - 1; 293366deb1c1SSepherosa Ziehau else if (tso_nsegs < 0) 293466deb1c1SSepherosa Ziehau tso_nsegs = 0; 29355a0c3c3aSSascha Wildner txr->bnx_sc->bnx_tsosegs[tso_nsegs]++; 293666deb1c1SSepherosa Ziehau #endif 293766deb1c1SSepherosa Ziehau } else if (m_head->m_pkthdr.csum_flags & BNX_CSUM_FEATURES) { 29386c8d8eccSSepherosa Ziehau if (m_head->m_pkthdr.csum_flags & CSUM_IP) 29396c8d8eccSSepherosa Ziehau csum_flags |= BGE_TXBDFLAG_IP_CSUM; 29406c8d8eccSSepherosa Ziehau if (m_head->m_pkthdr.csum_flags & (CSUM_TCP | CSUM_UDP)) 29416c8d8eccSSepherosa Ziehau csum_flags |= BGE_TXBDFLAG_TCP_UDP_CSUM; 29426c8d8eccSSepherosa Ziehau if (m_head->m_flags & M_LASTFRAG) 29436c8d8eccSSepherosa Ziehau csum_flags |= BGE_TXBDFLAG_IP_FRAG_END; 29446c8d8eccSSepherosa Ziehau else if (m_head->m_flags & M_FRAG) 29456c8d8eccSSepherosa Ziehau csum_flags |= BGE_TXBDFLAG_IP_FRAG; 29466c8d8eccSSepherosa Ziehau } 294766deb1c1SSepherosa Ziehau if (m_head->m_flags & M_VLANTAG) { 294866deb1c1SSepherosa Ziehau csum_flags |= BGE_TXBDFLAG_VLAN_TAG; 294966deb1c1SSepherosa Ziehau vlan_tag = m_head->m_pkthdr.ether_vlantag; 295066deb1c1SSepherosa Ziehau } 29516c8d8eccSSepherosa Ziehau 29526c8d8eccSSepherosa Ziehau idx = *txidx; 2953fa4b1067SSepherosa Ziehau map = txr->bnx_tx_buf[idx].bnx_tx_dmamap; 29546c8d8eccSSepherosa Ziehau 2955fa639b88SSepherosa Ziehau maxsegs = (BGE_TX_RING_CNT - txr->bnx_tx_cnt) - BNX_NSEG_RSVD; 29566c8d8eccSSepherosa Ziehau KASSERT(maxsegs >= BNX_NSEG_SPARE, 29576c8d8eccSSepherosa Ziehau ("not enough segments %d", maxsegs)); 29586c8d8eccSSepherosa Ziehau 29596c8d8eccSSepherosa Ziehau if (maxsegs > BNX_NSEG_NEW) 29606c8d8eccSSepherosa Ziehau maxsegs = BNX_NSEG_NEW; 29616c8d8eccSSepherosa Ziehau 29626c8d8eccSSepherosa Ziehau /* 29636c8d8eccSSepherosa Ziehau * Pad outbound frame to BGE_MIN_FRAMELEN for an unusual reason. 29646c8d8eccSSepherosa Ziehau * The bge hardware will pad out Tx runts to BGE_MIN_FRAMELEN, 29656c8d8eccSSepherosa Ziehau * but when such padded frames employ the bge IP/TCP checksum 29666c8d8eccSSepherosa Ziehau * offload, the hardware checksum assist gives incorrect results 29676c8d8eccSSepherosa Ziehau * (possibly from incorporating its own padding into the UDP/TCP 29686c8d8eccSSepherosa Ziehau * checksum; who knows). If we pad such runts with zeros, the 29696c8d8eccSSepherosa Ziehau * onboard checksum comes out correct. 29706c8d8eccSSepherosa Ziehau */ 29716c8d8eccSSepherosa Ziehau if ((csum_flags & BGE_TXBDFLAG_TCP_UDP_CSUM) && 29726c8d8eccSSepherosa Ziehau m_head->m_pkthdr.len < BNX_MIN_FRAMELEN) { 29736c8d8eccSSepherosa Ziehau error = m_devpad(m_head, BNX_MIN_FRAMELEN); 29746c8d8eccSSepherosa Ziehau if (error) 29756c8d8eccSSepherosa Ziehau goto back; 29766c8d8eccSSepherosa Ziehau } 29776c8d8eccSSepherosa Ziehau 297879a64343SSepherosa Ziehau if ((txr->bnx_tx_flags & BNX_TX_FLAG_SHORTDMA) && 297933a04907SSepherosa Ziehau m_head->m_next != NULL) { 29806c8d8eccSSepherosa Ziehau m_new = bnx_defrag_shortdma(m_head); 29816c8d8eccSSepherosa Ziehau if (m_new == NULL) { 29826c8d8eccSSepherosa Ziehau error = ENOBUFS; 29836c8d8eccSSepherosa Ziehau goto back; 29846c8d8eccSSepherosa Ziehau } 29856c8d8eccSSepherosa Ziehau *m_head0 = m_head = m_new; 29866c8d8eccSSepherosa Ziehau } 298766deb1c1SSepherosa Ziehau if ((m_head->m_pkthdr.csum_flags & CSUM_TSO) == 0 && 2988aad4de2bSSepherosa Ziehau (txr->bnx_tx_flags & BNX_TX_FLAG_FORCE_DEFRAG) && 2989aad4de2bSSepherosa Ziehau m_head->m_next != NULL) { 29906c8d8eccSSepherosa Ziehau /* 29916c8d8eccSSepherosa Ziehau * Forcefully defragment mbuf chain to overcome hardware 29926c8d8eccSSepherosa Ziehau * limitation which only support a single outstanding 29936c8d8eccSSepherosa Ziehau * DMA read operation. If it fails, keep moving on using 29946c8d8eccSSepherosa Ziehau * the original mbuf chain. 29956c8d8eccSSepherosa Ziehau */ 29966c8d8eccSSepherosa Ziehau m_new = m_defrag(m_head, MB_DONTWAIT); 29976c8d8eccSSepherosa Ziehau if (m_new != NULL) 29986c8d8eccSSepherosa Ziehau *m_head0 = m_head = m_new; 29996c8d8eccSSepherosa Ziehau } 30006c8d8eccSSepherosa Ziehau 300133a04907SSepherosa Ziehau error = bus_dmamap_load_mbuf_defrag(txr->bnx_tx_mtag, map, 30026c8d8eccSSepherosa Ziehau m_head0, segs, maxsegs, &nsegs, BUS_DMA_NOWAIT); 30036c8d8eccSSepherosa Ziehau if (error) 30046c8d8eccSSepherosa Ziehau goto back; 3005c9b7f592SSepherosa Ziehau *segs_used += nsegs; 30066c8d8eccSSepherosa Ziehau 30076c8d8eccSSepherosa Ziehau m_head = *m_head0; 300833a04907SSepherosa Ziehau bus_dmamap_sync(txr->bnx_tx_mtag, map, BUS_DMASYNC_PREWRITE); 30096c8d8eccSSepherosa Ziehau 30106c8d8eccSSepherosa Ziehau for (i = 0; ; i++) { 301133a04907SSepherosa Ziehau d = &txr->bnx_tx_ring[idx]; 30126c8d8eccSSepherosa Ziehau 30136c8d8eccSSepherosa Ziehau d->bge_addr.bge_addr_lo = BGE_ADDR_LO(segs[i].ds_addr); 30146c8d8eccSSepherosa Ziehau d->bge_addr.bge_addr_hi = BGE_ADDR_HI(segs[i].ds_addr); 30156c8d8eccSSepherosa Ziehau d->bge_len = segs[i].ds_len; 30166c8d8eccSSepherosa Ziehau d->bge_flags = csum_flags; 301766deb1c1SSepherosa Ziehau d->bge_vlan_tag = vlan_tag; 301866deb1c1SSepherosa Ziehau d->bge_mss = mss; 30196c8d8eccSSepherosa Ziehau 30206c8d8eccSSepherosa Ziehau if (i == nsegs - 1) 30216c8d8eccSSepherosa Ziehau break; 30226c8d8eccSSepherosa Ziehau BNX_INC(idx, BGE_TX_RING_CNT); 30236c8d8eccSSepherosa Ziehau } 30246c8d8eccSSepherosa Ziehau /* Mark the last segment as end of packet... */ 30256c8d8eccSSepherosa Ziehau d->bge_flags |= BGE_TXBDFLAG_END; 30266c8d8eccSSepherosa Ziehau 30276c8d8eccSSepherosa Ziehau /* 30286c8d8eccSSepherosa Ziehau * Insure that the map for this transmission is placed at 30296c8d8eccSSepherosa Ziehau * the array index of the last descriptor in this chain. 30306c8d8eccSSepherosa Ziehau */ 3031fa4b1067SSepherosa Ziehau txr->bnx_tx_buf[*txidx].bnx_tx_dmamap = txr->bnx_tx_buf[idx].bnx_tx_dmamap; 3032fa4b1067SSepherosa Ziehau txr->bnx_tx_buf[idx].bnx_tx_dmamap = map; 3033fa4b1067SSepherosa Ziehau txr->bnx_tx_buf[idx].bnx_tx_mbuf = m_head; 3034fa639b88SSepherosa Ziehau txr->bnx_tx_cnt += nsegs; 30356c8d8eccSSepherosa Ziehau 30366c8d8eccSSepherosa Ziehau BNX_INC(idx, BGE_TX_RING_CNT); 30376c8d8eccSSepherosa Ziehau *txidx = idx; 30386c8d8eccSSepherosa Ziehau back: 30396c8d8eccSSepherosa Ziehau if (error) { 30406c8d8eccSSepherosa Ziehau m_freem(*m_head0); 30416c8d8eccSSepherosa Ziehau *m_head0 = NULL; 30426c8d8eccSSepherosa Ziehau } 30436c8d8eccSSepherosa Ziehau return error; 30446c8d8eccSSepherosa Ziehau } 30456c8d8eccSSepherosa Ziehau 30466c8d8eccSSepherosa Ziehau /* 30476c8d8eccSSepherosa Ziehau * Main transmit routine. To avoid having to do mbuf copies, we put pointers 30486c8d8eccSSepherosa Ziehau * to the mbuf data regions directly in the transmit descriptors. 30496c8d8eccSSepherosa Ziehau */ 30506c8d8eccSSepherosa Ziehau static void 3051f0a26983SSepherosa Ziehau bnx_start(struct ifnet *ifp, struct ifaltq_subque *ifsq) 30526c8d8eccSSepherosa Ziehau { 30533397dea6SSepherosa Ziehau struct bnx_tx_ring *txr = ifsq_get_priv(ifsq); 30546c8d8eccSSepherosa Ziehau struct mbuf *m_head = NULL; 30556c8d8eccSSepherosa Ziehau uint32_t prodidx; 3056c9b7f592SSepherosa Ziehau int nsegs = 0; 30576c8d8eccSSepherosa Ziehau 30583397dea6SSepherosa Ziehau KKASSERT(txr->bnx_ifsq == ifsq); 3059329f9016SSepherosa Ziehau ASSERT_SERIALIZED(&txr->bnx_tx_serialize); 3060f0a26983SSepherosa Ziehau 30613397dea6SSepherosa Ziehau if ((ifp->if_flags & IFF_RUNNING) == 0 || ifsq_is_oactive(ifsq)) 30626c8d8eccSSepherosa Ziehau return; 30636c8d8eccSSepherosa Ziehau 306433a04907SSepherosa Ziehau prodidx = txr->bnx_tx_prodidx; 30656c8d8eccSSepherosa Ziehau 3066fa4b1067SSepherosa Ziehau while (txr->bnx_tx_buf[prodidx].bnx_tx_mbuf == NULL) { 30676c8d8eccSSepherosa Ziehau /* 30686c8d8eccSSepherosa Ziehau * Sanity check: avoid coming within BGE_NSEG_RSVD 30696c8d8eccSSepherosa Ziehau * descriptors of the end of the ring. Also make 30706c8d8eccSSepherosa Ziehau * sure there are BGE_NSEG_SPARE descriptors for 3071a1bd58c9SSepherosa Ziehau * jumbo buffers' or TSO segments' defragmentation. 30726c8d8eccSSepherosa Ziehau */ 3073fa639b88SSepherosa Ziehau if ((BGE_TX_RING_CNT - txr->bnx_tx_cnt) < 30746c8d8eccSSepherosa Ziehau (BNX_NSEG_RSVD + BNX_NSEG_SPARE)) { 30753397dea6SSepherosa Ziehau ifsq_set_oactive(ifsq); 30766c8d8eccSSepherosa Ziehau break; 30776c8d8eccSSepherosa Ziehau } 30786c8d8eccSSepherosa Ziehau 30793397dea6SSepherosa Ziehau m_head = ifsq_dequeue(ifsq, NULL); 3080a1bd58c9SSepherosa Ziehau if (m_head == NULL) 3081a1bd58c9SSepherosa Ziehau break; 3082a1bd58c9SSepherosa Ziehau 30836c8d8eccSSepherosa Ziehau /* 30846c8d8eccSSepherosa Ziehau * Pack the data into the transmit ring. If we 30856c8d8eccSSepherosa Ziehau * don't have room, set the OACTIVE flag and wait 30866c8d8eccSSepherosa Ziehau * for the NIC to drain the ring. 30876c8d8eccSSepherosa Ziehau */ 308833a04907SSepherosa Ziehau if (bnx_encap(txr, &m_head, &prodidx, &nsegs)) { 30893397dea6SSepherosa Ziehau ifsq_set_oactive(ifsq); 3090d40991efSSepherosa Ziehau IFNET_STAT_INC(ifp, oerrors, 1); 30916c8d8eccSSepherosa Ziehau break; 30926c8d8eccSSepherosa Ziehau } 30936c8d8eccSSepherosa Ziehau 309433a04907SSepherosa Ziehau if (nsegs >= txr->bnx_tx_wreg) { 30956c8d8eccSSepherosa Ziehau /* Transmit */ 30968bd43d5dSSepherosa Ziehau bnx_writembx(txr->bnx_sc, txr->bnx_tx_mbx, prodidx); 3097c9b7f592SSepherosa Ziehau nsegs = 0; 3098c9b7f592SSepherosa Ziehau } 30996c8d8eccSSepherosa Ziehau 3100c9b7f592SSepherosa Ziehau ETHER_BPF_MTAP(ifp, m_head); 31016c8d8eccSSepherosa Ziehau 31026c8d8eccSSepherosa Ziehau /* 31036c8d8eccSSepherosa Ziehau * Set a timeout in case the chip goes out to lunch. 31046c8d8eccSSepherosa Ziehau */ 31053397dea6SSepherosa Ziehau txr->bnx_tx_watchdog.wd_timer = 5; 31066c8d8eccSSepherosa Ziehau } 31076c8d8eccSSepherosa Ziehau 3108c9b7f592SSepherosa Ziehau if (nsegs > 0) { 3109c9b7f592SSepherosa Ziehau /* Transmit */ 31108bd43d5dSSepherosa Ziehau bnx_writembx(txr->bnx_sc, txr->bnx_tx_mbx, prodidx); 3111c9b7f592SSepherosa Ziehau } 311233a04907SSepherosa Ziehau txr->bnx_tx_prodidx = prodidx; 3113c9b7f592SSepherosa Ziehau } 3114c9b7f592SSepherosa Ziehau 31156c8d8eccSSepherosa Ziehau static void 31166c8d8eccSSepherosa Ziehau bnx_init(void *xsc) 31176c8d8eccSSepherosa Ziehau { 31186c8d8eccSSepherosa Ziehau struct bnx_softc *sc = xsc; 31196c8d8eccSSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if; 31206c8d8eccSSepherosa Ziehau uint16_t *m; 31216c8d8eccSSepherosa Ziehau uint32_t mode; 312233a04907SSepherosa Ziehau int i; 31237dbaa833SSepherosa Ziehau boolean_t polling; 31246c8d8eccSSepherosa Ziehau 3125329f9016SSepherosa Ziehau ASSERT_IFNET_SERIALIZED_ALL(ifp); 31266c8d8eccSSepherosa Ziehau 31276c8d8eccSSepherosa Ziehau /* Cancel pending I/O and flush buffers. */ 31286c8d8eccSSepherosa Ziehau bnx_stop(sc); 31296c8d8eccSSepherosa Ziehau bnx_reset(sc); 31306c8d8eccSSepherosa Ziehau bnx_chipinit(sc); 31316c8d8eccSSepherosa Ziehau 31326c8d8eccSSepherosa Ziehau /* 31336c8d8eccSSepherosa Ziehau * Init the various state machines, ring 31346c8d8eccSSepherosa Ziehau * control blocks and firmware. 31356c8d8eccSSepherosa Ziehau */ 31366c8d8eccSSepherosa Ziehau if (bnx_blockinit(sc)) { 31376c8d8eccSSepherosa Ziehau if_printf(ifp, "initialization failure\n"); 31386c8d8eccSSepherosa Ziehau bnx_stop(sc); 31396c8d8eccSSepherosa Ziehau return; 31406c8d8eccSSepherosa Ziehau } 31416c8d8eccSSepherosa Ziehau 31426c8d8eccSSepherosa Ziehau /* Specify MTU. */ 31436c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_RX_MTU, ifp->if_mtu + 31446c8d8eccSSepherosa Ziehau ETHER_HDR_LEN + ETHER_CRC_LEN + EVL_ENCAPLEN); 31456c8d8eccSSepherosa Ziehau 31466c8d8eccSSepherosa Ziehau /* Load our MAC address. */ 31476c8d8eccSSepherosa Ziehau m = (uint16_t *)&sc->arpcom.ac_enaddr[0]; 31486c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_MAC_ADDR1_LO, htons(m[0])); 31496c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_MAC_ADDR1_HI, (htons(m[1]) << 16) | htons(m[2])); 31506c8d8eccSSepherosa Ziehau 31516c8d8eccSSepherosa Ziehau /* Enable or disable promiscuous mode as needed. */ 31526c8d8eccSSepherosa Ziehau bnx_setpromisc(sc); 31536c8d8eccSSepherosa Ziehau 31546c8d8eccSSepherosa Ziehau /* Program multicast filter. */ 31556c8d8eccSSepherosa Ziehau bnx_setmulti(sc); 31566c8d8eccSSepherosa Ziehau 31576c8d8eccSSepherosa Ziehau /* Init RX ring. */ 3158beedf5beSSepherosa Ziehau if (bnx_init_rx_ring_std(&sc->bnx_rx_std_ring)) { 31596c8d8eccSSepherosa Ziehau if_printf(ifp, "RX ring initialization failed\n"); 31606c8d8eccSSepherosa Ziehau bnx_stop(sc); 31616c8d8eccSSepherosa Ziehau return; 31626c8d8eccSSepherosa Ziehau } 31636c8d8eccSSepherosa Ziehau 31646c8d8eccSSepherosa Ziehau /* Init jumbo RX ring. */ 31656c8d8eccSSepherosa Ziehau if (ifp->if_mtu > (ETHERMTU + ETHER_HDR_LEN + ETHER_CRC_LEN)) { 31666c8d8eccSSepherosa Ziehau if (bnx_init_rx_ring_jumbo(sc)) { 31676c8d8eccSSepherosa Ziehau if_printf(ifp, "Jumbo RX ring initialization failed\n"); 31686c8d8eccSSepherosa Ziehau bnx_stop(sc); 31696c8d8eccSSepherosa Ziehau return; 31706c8d8eccSSepherosa Ziehau } 31716c8d8eccSSepherosa Ziehau } 31726c8d8eccSSepherosa Ziehau 31736c8d8eccSSepherosa Ziehau /* Init our RX return ring index */ 3174841cdf08SSepherosa Ziehau for (i = 0; i < sc->bnx_rx_retcnt; ++i) { 3175841cdf08SSepherosa Ziehau struct bnx_rx_ret_ring *ret = &sc->bnx_rx_ret_ring[i]; 3176841cdf08SSepherosa Ziehau 3177841cdf08SSepherosa Ziehau ret->bnx_rx_saved_considx = 0; 3178841cdf08SSepherosa Ziehau ret->bnx_rx_cnt = 0; 3179841cdf08SSepherosa Ziehau } 31806c8d8eccSSepherosa Ziehau 31816c8d8eccSSepherosa Ziehau /* Init TX ring. */ 318233a04907SSepherosa Ziehau for (i = 0; i < sc->bnx_tx_ringcnt; ++i) 318333a04907SSepherosa Ziehau bnx_init_tx_ring(&sc->bnx_tx_ring[i]); 31846c8d8eccSSepherosa Ziehau 31856c8d8eccSSepherosa Ziehau /* Enable TX MAC state machine lockup fix. */ 31866c8d8eccSSepherosa Ziehau mode = CSR_READ_4(sc, BGE_TX_MODE); 31876c8d8eccSSepherosa Ziehau mode |= BGE_TXMODE_MBUF_LOCKUP_FIX; 3188b96cbbb6SSepherosa Ziehau if (sc->bnx_asicrev == BGE_ASICREV_BCM5720 || 3189b96cbbb6SSepherosa Ziehau sc->bnx_asicrev == BGE_ASICREV_BCM5762) { 31906c8d8eccSSepherosa Ziehau mode &= ~(BGE_TXMODE_JMB_FRM_LEN | BGE_TXMODE_CNT_DN_MODE); 31916c8d8eccSSepherosa Ziehau mode |= CSR_READ_4(sc, BGE_TX_MODE) & 31926c8d8eccSSepherosa Ziehau (BGE_TXMODE_JMB_FRM_LEN | BGE_TXMODE_CNT_DN_MODE); 31936c8d8eccSSepherosa Ziehau } 31946c8d8eccSSepherosa Ziehau /* Turn on transmitter */ 31956c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_TX_MODE, mode | BGE_TXMODE_ENABLE); 31966c8d8eccSSepherosa Ziehau 31976c8d8eccSSepherosa Ziehau /* Turn on receiver */ 31986c8d8eccSSepherosa Ziehau BNX_SETBIT(sc, BGE_RX_MODE, BGE_RXMODE_ENABLE); 31996c8d8eccSSepherosa Ziehau 32006c8d8eccSSepherosa Ziehau /* 32016c8d8eccSSepherosa Ziehau * Set the number of good frames to receive after RX MBUF 32026c8d8eccSSepherosa Ziehau * Low Watermark has been reached. After the RX MAC receives 32036c8d8eccSSepherosa Ziehau * this number of frames, it will drop subsequent incoming 32046c8d8eccSSepherosa Ziehau * frames until the MBUF High Watermark is reached. 32056c8d8eccSSepherosa Ziehau */ 3206bcb29629SSepherosa Ziehau if (BNX_IS_57765_FAMILY(sc)) 32076c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_MAX_RX_FRAME_LOWAT, 1); 32086c8d8eccSSepherosa Ziehau else 32096c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_MAX_RX_FRAME_LOWAT, 2); 32106c8d8eccSSepherosa Ziehau 3211f33ac8a4SSepherosa Ziehau if (sc->bnx_intr_type == PCI_INTR_TYPE_MSI) { 32126c8d8eccSSepherosa Ziehau if (bootverbose) { 32136c8d8eccSSepherosa Ziehau if_printf(ifp, "MSI_MODE: %#x\n", 32146c8d8eccSSepherosa Ziehau CSR_READ_4(sc, BGE_MSI_MODE)); 32156c8d8eccSSepherosa Ziehau } 32166c8d8eccSSepherosa Ziehau } 32176c8d8eccSSepherosa Ziehau 32186c8d8eccSSepherosa Ziehau /* Tell firmware we're alive. */ 32196c8d8eccSSepherosa Ziehau BNX_SETBIT(sc, BGE_MODE_CTL, BGE_MODECTL_STACKUP); 32206c8d8eccSSepherosa Ziehau 32216c8d8eccSSepherosa Ziehau /* Enable host interrupts if polling(4) is not enabled. */ 32226c8d8eccSSepherosa Ziehau PCI_SETBIT(sc->bnx_dev, BGE_PCI_MISC_CTL, BGE_PCIMISCCTL_CLEAR_INTA, 4); 32237dbaa833SSepherosa Ziehau 32247dbaa833SSepherosa Ziehau polling = FALSE; 322539a8d43aSSepherosa Ziehau #ifdef IFPOLL_ENABLE 322639a8d43aSSepherosa Ziehau if (ifp->if_flags & IFF_NPOLLING) 32277dbaa833SSepherosa Ziehau polling = TRUE; 32287dbaa833SSepherosa Ziehau #endif 32297dbaa833SSepherosa Ziehau if (polling) 32306c8d8eccSSepherosa Ziehau bnx_disable_intr(sc); 32316c8d8eccSSepherosa Ziehau else 32326c8d8eccSSepherosa Ziehau bnx_enable_intr(sc); 32337dbaa833SSepherosa Ziehau bnx_set_tick_cpuid(sc, polling); 32346c8d8eccSSepherosa Ziehau 32356c8d8eccSSepherosa Ziehau bnx_ifmedia_upd(ifp); 32366c8d8eccSSepherosa Ziehau 32376c8d8eccSSepherosa Ziehau ifp->if_flags |= IFF_RUNNING; 32383397dea6SSepherosa Ziehau for (i = 0; i < sc->bnx_tx_ringcnt; ++i) { 32393397dea6SSepherosa Ziehau struct bnx_tx_ring *txr = &sc->bnx_tx_ring[i]; 32403397dea6SSepherosa Ziehau 32413397dea6SSepherosa Ziehau ifsq_clr_oactive(txr->bnx_ifsq); 32423397dea6SSepherosa Ziehau ifsq_watchdog_start(&txr->bnx_tx_watchdog); 32433397dea6SSepherosa Ziehau } 32446c8d8eccSSepherosa Ziehau 32457dbaa833SSepherosa Ziehau callout_reset_bycpu(&sc->bnx_tick_timer, hz, bnx_tick, sc, 32467dbaa833SSepherosa Ziehau sc->bnx_tick_cpuid); 32476c8d8eccSSepherosa Ziehau } 32486c8d8eccSSepherosa Ziehau 32496c8d8eccSSepherosa Ziehau /* 32506c8d8eccSSepherosa Ziehau * Set media options. 32516c8d8eccSSepherosa Ziehau */ 32526c8d8eccSSepherosa Ziehau static int 32536c8d8eccSSepherosa Ziehau bnx_ifmedia_upd(struct ifnet *ifp) 32546c8d8eccSSepherosa Ziehau { 32556c8d8eccSSepherosa Ziehau struct bnx_softc *sc = ifp->if_softc; 32566c8d8eccSSepherosa Ziehau 32576c8d8eccSSepherosa Ziehau /* If this is a 1000baseX NIC, enable the TBI port. */ 32586c8d8eccSSepherosa Ziehau if (sc->bnx_flags & BNX_FLAG_TBI) { 32596c8d8eccSSepherosa Ziehau struct ifmedia *ifm = &sc->bnx_ifmedia; 32606c8d8eccSSepherosa Ziehau 32616c8d8eccSSepherosa Ziehau if (IFM_TYPE(ifm->ifm_media) != IFM_ETHER) 32626c8d8eccSSepherosa Ziehau return(EINVAL); 32636c8d8eccSSepherosa Ziehau 32646c8d8eccSSepherosa Ziehau switch(IFM_SUBTYPE(ifm->ifm_media)) { 32656c8d8eccSSepherosa Ziehau case IFM_AUTO: 32666c8d8eccSSepherosa Ziehau break; 32676c8d8eccSSepherosa Ziehau 32686c8d8eccSSepherosa Ziehau case IFM_1000_SX: 32696c8d8eccSSepherosa Ziehau if ((ifm->ifm_media & IFM_GMASK) == IFM_FDX) { 32706c8d8eccSSepherosa Ziehau BNX_CLRBIT(sc, BGE_MAC_MODE, 32716c8d8eccSSepherosa Ziehau BGE_MACMODE_HALF_DUPLEX); 32726c8d8eccSSepherosa Ziehau } else { 32736c8d8eccSSepherosa Ziehau BNX_SETBIT(sc, BGE_MAC_MODE, 32746c8d8eccSSepherosa Ziehau BGE_MACMODE_HALF_DUPLEX); 32756c8d8eccSSepherosa Ziehau } 32766c8d8eccSSepherosa Ziehau break; 32776c8d8eccSSepherosa Ziehau default: 32786c8d8eccSSepherosa Ziehau return(EINVAL); 32796c8d8eccSSepherosa Ziehau } 32806c8d8eccSSepherosa Ziehau } else { 32816c8d8eccSSepherosa Ziehau struct mii_data *mii = device_get_softc(sc->bnx_miibus); 32826c8d8eccSSepherosa Ziehau 32836c8d8eccSSepherosa Ziehau sc->bnx_link_evt++; 32846c8d8eccSSepherosa Ziehau sc->bnx_link = 0; 32856c8d8eccSSepherosa Ziehau if (mii->mii_instance) { 32866c8d8eccSSepherosa Ziehau struct mii_softc *miisc; 32876c8d8eccSSepherosa Ziehau 32886c8d8eccSSepherosa Ziehau LIST_FOREACH(miisc, &mii->mii_phys, mii_list) 32896c8d8eccSSepherosa Ziehau mii_phy_reset(miisc); 32906c8d8eccSSepherosa Ziehau } 32916c8d8eccSSepherosa Ziehau mii_mediachg(mii); 32926c8d8eccSSepherosa Ziehau 32936c8d8eccSSepherosa Ziehau /* 32946c8d8eccSSepherosa Ziehau * Force an interrupt so that we will call bnx_link_upd 32956c8d8eccSSepherosa Ziehau * if needed and clear any pending link state attention. 32966c8d8eccSSepherosa Ziehau * Without this we are not getting any further interrupts 32976c8d8eccSSepherosa Ziehau * for link state changes and thus will not UP the link and 32986c8d8eccSSepherosa Ziehau * not be able to send in bnx_start. The only way to get 32996c8d8eccSSepherosa Ziehau * things working was to receive a packet and get an RX 33006c8d8eccSSepherosa Ziehau * intr. 33016c8d8eccSSepherosa Ziehau * 33026c8d8eccSSepherosa Ziehau * bnx_tick should help for fiber cards and we might not 33036c8d8eccSSepherosa Ziehau * need to do this here if BNX_FLAG_TBI is set but as 33046c8d8eccSSepherosa Ziehau * we poll for fiber anyway it should not harm. 33056c8d8eccSSepherosa Ziehau */ 33066c8d8eccSSepherosa Ziehau BNX_SETBIT(sc, BGE_HCC_MODE, BGE_HCCMODE_COAL_NOW); 33076c8d8eccSSepherosa Ziehau } 33086c8d8eccSSepherosa Ziehau return(0); 33096c8d8eccSSepherosa Ziehau } 33106c8d8eccSSepherosa Ziehau 33116c8d8eccSSepherosa Ziehau /* 33126c8d8eccSSepherosa Ziehau * Report current media status. 33136c8d8eccSSepherosa Ziehau */ 33146c8d8eccSSepherosa Ziehau static void 33156c8d8eccSSepherosa Ziehau bnx_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr) 33166c8d8eccSSepherosa Ziehau { 33176c8d8eccSSepherosa Ziehau struct bnx_softc *sc = ifp->if_softc; 33186c8d8eccSSepherosa Ziehau 33196c8d8eccSSepherosa Ziehau if (sc->bnx_flags & BNX_FLAG_TBI) { 33206c8d8eccSSepherosa Ziehau ifmr->ifm_status = IFM_AVALID; 33216c8d8eccSSepherosa Ziehau ifmr->ifm_active = IFM_ETHER; 33226c8d8eccSSepherosa Ziehau if (CSR_READ_4(sc, BGE_MAC_STS) & 33236c8d8eccSSepherosa Ziehau BGE_MACSTAT_TBI_PCS_SYNCHED) { 33246c8d8eccSSepherosa Ziehau ifmr->ifm_status |= IFM_ACTIVE; 33256c8d8eccSSepherosa Ziehau } else { 33266c8d8eccSSepherosa Ziehau ifmr->ifm_active |= IFM_NONE; 33276c8d8eccSSepherosa Ziehau return; 33286c8d8eccSSepherosa Ziehau } 33296c8d8eccSSepherosa Ziehau 33306c8d8eccSSepherosa Ziehau ifmr->ifm_active |= IFM_1000_SX; 33316c8d8eccSSepherosa Ziehau if (CSR_READ_4(sc, BGE_MAC_MODE) & BGE_MACMODE_HALF_DUPLEX) 33326c8d8eccSSepherosa Ziehau ifmr->ifm_active |= IFM_HDX; 33336c8d8eccSSepherosa Ziehau else 33346c8d8eccSSepherosa Ziehau ifmr->ifm_active |= IFM_FDX; 33356c8d8eccSSepherosa Ziehau } else { 33366c8d8eccSSepherosa Ziehau struct mii_data *mii = device_get_softc(sc->bnx_miibus); 33376c8d8eccSSepherosa Ziehau 33386c8d8eccSSepherosa Ziehau mii_pollstat(mii); 33396c8d8eccSSepherosa Ziehau ifmr->ifm_active = mii->mii_media_active; 33406c8d8eccSSepherosa Ziehau ifmr->ifm_status = mii->mii_media_status; 33416c8d8eccSSepherosa Ziehau } 33426c8d8eccSSepherosa Ziehau } 33436c8d8eccSSepherosa Ziehau 33446c8d8eccSSepherosa Ziehau static int 33456c8d8eccSSepherosa Ziehau bnx_ioctl(struct ifnet *ifp, u_long command, caddr_t data, struct ucred *cr) 33466c8d8eccSSepherosa Ziehau { 33476c8d8eccSSepherosa Ziehau struct bnx_softc *sc = ifp->if_softc; 33486c8d8eccSSepherosa Ziehau struct ifreq *ifr = (struct ifreq *)data; 33496c8d8eccSSepherosa Ziehau int mask, error = 0; 33506c8d8eccSSepherosa Ziehau 3351329f9016SSepherosa Ziehau ASSERT_IFNET_SERIALIZED_ALL(ifp); 33526c8d8eccSSepherosa Ziehau 33536c8d8eccSSepherosa Ziehau switch (command) { 33546c8d8eccSSepherosa Ziehau case SIOCSIFMTU: 33556c8d8eccSSepherosa Ziehau if ((!BNX_IS_JUMBO_CAPABLE(sc) && ifr->ifr_mtu > ETHERMTU) || 33566c8d8eccSSepherosa Ziehau (BNX_IS_JUMBO_CAPABLE(sc) && 33576c8d8eccSSepherosa Ziehau ifr->ifr_mtu > BNX_JUMBO_MTU)) { 33586c8d8eccSSepherosa Ziehau error = EINVAL; 33596c8d8eccSSepherosa Ziehau } else if (ifp->if_mtu != ifr->ifr_mtu) { 33606c8d8eccSSepherosa Ziehau ifp->if_mtu = ifr->ifr_mtu; 33616c8d8eccSSepherosa Ziehau if (ifp->if_flags & IFF_RUNNING) 33626c8d8eccSSepherosa Ziehau bnx_init(sc); 33636c8d8eccSSepherosa Ziehau } 33646c8d8eccSSepherosa Ziehau break; 33656c8d8eccSSepherosa Ziehau case SIOCSIFFLAGS: 33666c8d8eccSSepherosa Ziehau if (ifp->if_flags & IFF_UP) { 33676c8d8eccSSepherosa Ziehau if (ifp->if_flags & IFF_RUNNING) { 33686c8d8eccSSepherosa Ziehau mask = ifp->if_flags ^ sc->bnx_if_flags; 33696c8d8eccSSepherosa Ziehau 33706c8d8eccSSepherosa Ziehau /* 33716c8d8eccSSepherosa Ziehau * If only the state of the PROMISC flag 33726c8d8eccSSepherosa Ziehau * changed, then just use the 'set promisc 33736c8d8eccSSepherosa Ziehau * mode' command instead of reinitializing 33746c8d8eccSSepherosa Ziehau * the entire NIC. Doing a full re-init 33756c8d8eccSSepherosa Ziehau * means reloading the firmware and waiting 33766c8d8eccSSepherosa Ziehau * for it to start up, which may take a 33776c8d8eccSSepherosa Ziehau * second or two. Similarly for ALLMULTI. 33786c8d8eccSSepherosa Ziehau */ 33796c8d8eccSSepherosa Ziehau if (mask & IFF_PROMISC) 33806c8d8eccSSepherosa Ziehau bnx_setpromisc(sc); 33816c8d8eccSSepherosa Ziehau if (mask & IFF_ALLMULTI) 33826c8d8eccSSepherosa Ziehau bnx_setmulti(sc); 33836c8d8eccSSepherosa Ziehau } else { 33846c8d8eccSSepherosa Ziehau bnx_init(sc); 33856c8d8eccSSepherosa Ziehau } 33866c8d8eccSSepherosa Ziehau } else if (ifp->if_flags & IFF_RUNNING) { 33876c8d8eccSSepherosa Ziehau bnx_stop(sc); 33886c8d8eccSSepherosa Ziehau } 33896c8d8eccSSepherosa Ziehau sc->bnx_if_flags = ifp->if_flags; 33906c8d8eccSSepherosa Ziehau break; 33916c8d8eccSSepherosa Ziehau case SIOCADDMULTI: 33926c8d8eccSSepherosa Ziehau case SIOCDELMULTI: 33936c8d8eccSSepherosa Ziehau if (ifp->if_flags & IFF_RUNNING) 33946c8d8eccSSepherosa Ziehau bnx_setmulti(sc); 33956c8d8eccSSepherosa Ziehau break; 33966c8d8eccSSepherosa Ziehau case SIOCSIFMEDIA: 33976c8d8eccSSepherosa Ziehau case SIOCGIFMEDIA: 33986c8d8eccSSepherosa Ziehau if (sc->bnx_flags & BNX_FLAG_TBI) { 33996c8d8eccSSepherosa Ziehau error = ifmedia_ioctl(ifp, ifr, 34006c8d8eccSSepherosa Ziehau &sc->bnx_ifmedia, command); 34016c8d8eccSSepherosa Ziehau } else { 34026c8d8eccSSepherosa Ziehau struct mii_data *mii; 34036c8d8eccSSepherosa Ziehau 34046c8d8eccSSepherosa Ziehau mii = device_get_softc(sc->bnx_miibus); 34056c8d8eccSSepherosa Ziehau error = ifmedia_ioctl(ifp, ifr, 34066c8d8eccSSepherosa Ziehau &mii->mii_media, command); 34076c8d8eccSSepherosa Ziehau } 34086c8d8eccSSepherosa Ziehau break; 34096c8d8eccSSepherosa Ziehau case SIOCSIFCAP: 34106c8d8eccSSepherosa Ziehau mask = ifr->ifr_reqcap ^ ifp->if_capenable; 34116c8d8eccSSepherosa Ziehau if (mask & IFCAP_HWCSUM) { 34126c8d8eccSSepherosa Ziehau ifp->if_capenable ^= (mask & IFCAP_HWCSUM); 341366deb1c1SSepherosa Ziehau if (ifp->if_capenable & IFCAP_TXCSUM) 341466deb1c1SSepherosa Ziehau ifp->if_hwassist |= BNX_CSUM_FEATURES; 34156c8d8eccSSepherosa Ziehau else 341666deb1c1SSepherosa Ziehau ifp->if_hwassist &= ~BNX_CSUM_FEATURES; 341766deb1c1SSepherosa Ziehau } 341866deb1c1SSepherosa Ziehau if (mask & IFCAP_TSO) { 341966deb1c1SSepherosa Ziehau ifp->if_capenable ^= (mask & IFCAP_TSO); 342066deb1c1SSepherosa Ziehau if (ifp->if_capenable & IFCAP_TSO) 342166deb1c1SSepherosa Ziehau ifp->if_hwassist |= CSUM_TSO; 342266deb1c1SSepherosa Ziehau else 342366deb1c1SSepherosa Ziehau ifp->if_hwassist &= ~CSUM_TSO; 34246c8d8eccSSepherosa Ziehau } 34256c8d8eccSSepherosa Ziehau break; 34266c8d8eccSSepherosa Ziehau default: 34276c8d8eccSSepherosa Ziehau error = ether_ioctl(ifp, command, data); 34286c8d8eccSSepherosa Ziehau break; 34296c8d8eccSSepherosa Ziehau } 34306c8d8eccSSepherosa Ziehau return error; 34316c8d8eccSSepherosa Ziehau } 34326c8d8eccSSepherosa Ziehau 34336c8d8eccSSepherosa Ziehau static void 34343397dea6SSepherosa Ziehau bnx_watchdog(struct ifaltq_subque *ifsq) 34356c8d8eccSSepherosa Ziehau { 34363397dea6SSepherosa Ziehau struct ifnet *ifp = ifsq_get_ifp(ifsq); 34376c8d8eccSSepherosa Ziehau struct bnx_softc *sc = ifp->if_softc; 34383397dea6SSepherosa Ziehau int i; 34393397dea6SSepherosa Ziehau 34403397dea6SSepherosa Ziehau ASSERT_IFNET_SERIALIZED_ALL(ifp); 34416c8d8eccSSepherosa Ziehau 34426c8d8eccSSepherosa Ziehau if_printf(ifp, "watchdog timeout -- resetting\n"); 34436c8d8eccSSepherosa Ziehau 34446c8d8eccSSepherosa Ziehau bnx_init(sc); 34456c8d8eccSSepherosa Ziehau 3446d40991efSSepherosa Ziehau IFNET_STAT_INC(ifp, oerrors, 1); 34476c8d8eccSSepherosa Ziehau 34483397dea6SSepherosa Ziehau for (i = 0; i < sc->bnx_tx_ringcnt; ++i) 34493397dea6SSepherosa Ziehau ifsq_devstart_sched(sc->bnx_tx_ring[i].bnx_ifsq); 34506c8d8eccSSepherosa Ziehau } 34516c8d8eccSSepherosa Ziehau 34526c8d8eccSSepherosa Ziehau /* 34536c8d8eccSSepherosa Ziehau * Stop the adapter and free any mbufs allocated to the 34546c8d8eccSSepherosa Ziehau * RX and TX lists. 34556c8d8eccSSepherosa Ziehau */ 34566c8d8eccSSepherosa Ziehau static void 34576c8d8eccSSepherosa Ziehau bnx_stop(struct bnx_softc *sc) 34586c8d8eccSSepherosa Ziehau { 34596c8d8eccSSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if; 346033a04907SSepherosa Ziehau int i; 34616c8d8eccSSepherosa Ziehau 3462329f9016SSepherosa Ziehau ASSERT_IFNET_SERIALIZED_ALL(ifp); 34636c8d8eccSSepherosa Ziehau 34647dbaa833SSepherosa Ziehau callout_stop(&sc->bnx_tick_timer); 34656c8d8eccSSepherosa Ziehau 34666c8d8eccSSepherosa Ziehau /* 34676c8d8eccSSepherosa Ziehau * Disable all of the receiver blocks 34686c8d8eccSSepherosa Ziehau */ 34696c8d8eccSSepherosa Ziehau bnx_stop_block(sc, BGE_RX_MODE, BGE_RXMODE_ENABLE); 34706c8d8eccSSepherosa Ziehau bnx_stop_block(sc, BGE_RBDI_MODE, BGE_RBDIMODE_ENABLE); 34716c8d8eccSSepherosa Ziehau bnx_stop_block(sc, BGE_RXLP_MODE, BGE_RXLPMODE_ENABLE); 34726c8d8eccSSepherosa Ziehau bnx_stop_block(sc, BGE_RDBDI_MODE, BGE_RBDIMODE_ENABLE); 34736c8d8eccSSepherosa Ziehau bnx_stop_block(sc, BGE_RDC_MODE, BGE_RDCMODE_ENABLE); 34746c8d8eccSSepherosa Ziehau bnx_stop_block(sc, BGE_RBDC_MODE, BGE_RBDCMODE_ENABLE); 34756c8d8eccSSepherosa Ziehau 34766c8d8eccSSepherosa Ziehau /* 34776c8d8eccSSepherosa Ziehau * Disable all of the transmit blocks 34786c8d8eccSSepherosa Ziehau */ 34796c8d8eccSSepherosa Ziehau bnx_stop_block(sc, BGE_SRS_MODE, BGE_SRSMODE_ENABLE); 34806c8d8eccSSepherosa Ziehau bnx_stop_block(sc, BGE_SBDI_MODE, BGE_SBDIMODE_ENABLE); 34816c8d8eccSSepherosa Ziehau bnx_stop_block(sc, BGE_SDI_MODE, BGE_SDIMODE_ENABLE); 34826c8d8eccSSepherosa Ziehau bnx_stop_block(sc, BGE_RDMA_MODE, BGE_RDMAMODE_ENABLE); 34836c8d8eccSSepherosa Ziehau bnx_stop_block(sc, BGE_SDC_MODE, BGE_SDCMODE_ENABLE); 34846c8d8eccSSepherosa Ziehau bnx_stop_block(sc, BGE_SBDC_MODE, BGE_SBDCMODE_ENABLE); 34856c8d8eccSSepherosa Ziehau 34866c8d8eccSSepherosa Ziehau /* 34876c8d8eccSSepherosa Ziehau * Shut down all of the memory managers and related 34886c8d8eccSSepherosa Ziehau * state machines. 34896c8d8eccSSepherosa Ziehau */ 34906c8d8eccSSepherosa Ziehau bnx_stop_block(sc, BGE_HCC_MODE, BGE_HCCMODE_ENABLE); 34916c8d8eccSSepherosa Ziehau bnx_stop_block(sc, BGE_WDMA_MODE, BGE_WDMAMODE_ENABLE); 34926c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_FTQ_RESET, 0xFFFFFFFF); 34936c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_FTQ_RESET, 0); 34946c8d8eccSSepherosa Ziehau 34956c8d8eccSSepherosa Ziehau /* Disable host interrupts. */ 34966c8d8eccSSepherosa Ziehau bnx_disable_intr(sc); 34976c8d8eccSSepherosa Ziehau 34986c8d8eccSSepherosa Ziehau /* 34996c8d8eccSSepherosa Ziehau * Tell firmware we're shutting down. 35006c8d8eccSSepherosa Ziehau */ 35016c8d8eccSSepherosa Ziehau BNX_CLRBIT(sc, BGE_MODE_CTL, BGE_MODECTL_STACKUP); 35026c8d8eccSSepherosa Ziehau 35036c8d8eccSSepherosa Ziehau /* Free the RX lists. */ 3504beedf5beSSepherosa Ziehau bnx_free_rx_ring_std(&sc->bnx_rx_std_ring); 35056c8d8eccSSepherosa Ziehau 35066c8d8eccSSepherosa Ziehau /* Free jumbo RX list. */ 35076c8d8eccSSepherosa Ziehau if (BNX_IS_JUMBO_CAPABLE(sc)) 35086c8d8eccSSepherosa Ziehau bnx_free_rx_ring_jumbo(sc); 35096c8d8eccSSepherosa Ziehau 35106c8d8eccSSepherosa Ziehau /* Free TX buffers. */ 35114fa38985SSepherosa Ziehau for (i = 0; i < sc->bnx_tx_ringcnt; ++i) { 35124fa38985SSepherosa Ziehau struct bnx_tx_ring *txr = &sc->bnx_tx_ring[i]; 35136c8d8eccSSepherosa Ziehau 35144fa38985SSepherosa Ziehau txr->bnx_saved_status_tag = 0; 35154fa38985SSepherosa Ziehau bnx_free_tx_ring(txr); 35164fa38985SSepherosa Ziehau } 35174fa38985SSepherosa Ziehau 35184fa38985SSepherosa Ziehau /* Clear saved status tag */ 35194fa38985SSepherosa Ziehau for (i = 0; i < sc->bnx_rx_retcnt; ++i) 35204fa38985SSepherosa Ziehau sc->bnx_rx_ret_ring[i].bnx_saved_status_tag = 0; 35214fa38985SSepherosa Ziehau 35226c8d8eccSSepherosa Ziehau sc->bnx_link = 0; 35236c8d8eccSSepherosa Ziehau sc->bnx_coal_chg = 0; 35246c8d8eccSSepherosa Ziehau 35259ed293e0SSepherosa Ziehau ifp->if_flags &= ~IFF_RUNNING; 35263397dea6SSepherosa Ziehau for (i = 0; i < sc->bnx_tx_ringcnt; ++i) { 35273397dea6SSepherosa Ziehau struct bnx_tx_ring *txr = &sc->bnx_tx_ring[i]; 35283397dea6SSepherosa Ziehau 35293397dea6SSepherosa Ziehau ifsq_clr_oactive(txr->bnx_ifsq); 35303397dea6SSepherosa Ziehau ifsq_watchdog_stop(&txr->bnx_tx_watchdog); 35313397dea6SSepherosa Ziehau } 35326c8d8eccSSepherosa Ziehau } 35336c8d8eccSSepherosa Ziehau 35346c8d8eccSSepherosa Ziehau /* 35356c8d8eccSSepherosa Ziehau * Stop all chip I/O so that the kernel's probe routines don't 35366c8d8eccSSepherosa Ziehau * get confused by errant DMAs when rebooting. 35376c8d8eccSSepherosa Ziehau */ 35386c8d8eccSSepherosa Ziehau static void 35396c8d8eccSSepherosa Ziehau bnx_shutdown(device_t dev) 35406c8d8eccSSepherosa Ziehau { 35416c8d8eccSSepherosa Ziehau struct bnx_softc *sc = device_get_softc(dev); 35426c8d8eccSSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if; 35436c8d8eccSSepherosa Ziehau 3544329f9016SSepherosa Ziehau ifnet_serialize_all(ifp); 35456c8d8eccSSepherosa Ziehau bnx_stop(sc); 35466c8d8eccSSepherosa Ziehau bnx_reset(sc); 3547329f9016SSepherosa Ziehau ifnet_deserialize_all(ifp); 35486c8d8eccSSepherosa Ziehau } 35496c8d8eccSSepherosa Ziehau 35506c8d8eccSSepherosa Ziehau static int 35516c8d8eccSSepherosa Ziehau bnx_suspend(device_t dev) 35526c8d8eccSSepherosa Ziehau { 35536c8d8eccSSepherosa Ziehau struct bnx_softc *sc = device_get_softc(dev); 35546c8d8eccSSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if; 35556c8d8eccSSepherosa Ziehau 3556329f9016SSepherosa Ziehau ifnet_serialize_all(ifp); 35576c8d8eccSSepherosa Ziehau bnx_stop(sc); 3558329f9016SSepherosa Ziehau ifnet_deserialize_all(ifp); 35596c8d8eccSSepherosa Ziehau 35606c8d8eccSSepherosa Ziehau return 0; 35616c8d8eccSSepherosa Ziehau } 35626c8d8eccSSepherosa Ziehau 35636c8d8eccSSepherosa Ziehau static int 35646c8d8eccSSepherosa Ziehau bnx_resume(device_t dev) 35656c8d8eccSSepherosa Ziehau { 35666c8d8eccSSepherosa Ziehau struct bnx_softc *sc = device_get_softc(dev); 35676c8d8eccSSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if; 35686c8d8eccSSepherosa Ziehau 3569329f9016SSepherosa Ziehau ifnet_serialize_all(ifp); 35706c8d8eccSSepherosa Ziehau 35716c8d8eccSSepherosa Ziehau if (ifp->if_flags & IFF_UP) { 35723397dea6SSepherosa Ziehau int i; 35736c8d8eccSSepherosa Ziehau 35743397dea6SSepherosa Ziehau bnx_init(sc); 35753397dea6SSepherosa Ziehau for (i = 0; i < sc->bnx_tx_ringcnt; ++i) 35763397dea6SSepherosa Ziehau ifsq_devstart_sched(sc->bnx_tx_ring[i].bnx_ifsq); 35776c8d8eccSSepherosa Ziehau } 35786c8d8eccSSepherosa Ziehau 3579329f9016SSepherosa Ziehau ifnet_deserialize_all(ifp); 35806c8d8eccSSepherosa Ziehau 35816c8d8eccSSepherosa Ziehau return 0; 35826c8d8eccSSepherosa Ziehau } 35836c8d8eccSSepherosa Ziehau 35846c8d8eccSSepherosa Ziehau static void 35856c8d8eccSSepherosa Ziehau bnx_setpromisc(struct bnx_softc *sc) 35866c8d8eccSSepherosa Ziehau { 35876c8d8eccSSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if; 35886c8d8eccSSepherosa Ziehau 35896c8d8eccSSepherosa Ziehau if (ifp->if_flags & IFF_PROMISC) 35906c8d8eccSSepherosa Ziehau BNX_SETBIT(sc, BGE_RX_MODE, BGE_RXMODE_RX_PROMISC); 35916c8d8eccSSepherosa Ziehau else 35926c8d8eccSSepherosa Ziehau BNX_CLRBIT(sc, BGE_RX_MODE, BGE_RXMODE_RX_PROMISC); 35936c8d8eccSSepherosa Ziehau } 35946c8d8eccSSepherosa Ziehau 35956c8d8eccSSepherosa Ziehau static void 35966c8d8eccSSepherosa Ziehau bnx_dma_free(struct bnx_softc *sc) 35976c8d8eccSSepherosa Ziehau { 3598beedf5beSSepherosa Ziehau struct bnx_rx_std_ring *std = &sc->bnx_rx_std_ring; 35996c8d8eccSSepherosa Ziehau int i; 36006c8d8eccSSepherosa Ziehau 3601beedf5beSSepherosa Ziehau /* Destroy RX return rings */ 3602beedf5beSSepherosa Ziehau if (sc->bnx_rx_ret_ring != NULL) { 3603beedf5beSSepherosa Ziehau for (i = 0; i < sc->bnx_rx_retcnt; ++i) 3604beedf5beSSepherosa Ziehau bnx_destroy_rx_ret_ring(&sc->bnx_rx_ret_ring[i]); 3605beedf5beSSepherosa Ziehau kfree(sc->bnx_rx_ret_ring, M_DEVBUF); 3606beedf5beSSepherosa Ziehau } 3607beedf5beSSepherosa Ziehau 36086c8d8eccSSepherosa Ziehau /* Destroy RX mbuf DMA stuffs. */ 3609beedf5beSSepherosa Ziehau if (std->bnx_rx_mtag != NULL) { 36106c8d8eccSSepherosa Ziehau for (i = 0; i < BGE_STD_RX_RING_CNT; i++) { 3611beedf5beSSepherosa Ziehau KKASSERT(std->bnx_rx_std_buf[i].bnx_rx_mbuf == NULL); 3612beedf5beSSepherosa Ziehau bus_dmamap_destroy(std->bnx_rx_mtag, 3613beedf5beSSepherosa Ziehau std->bnx_rx_std_buf[i].bnx_rx_dmamap); 36146c8d8eccSSepherosa Ziehau } 3615beedf5beSSepherosa Ziehau bus_dma_tag_destroy(std->bnx_rx_mtag); 36166c8d8eccSSepherosa Ziehau } 36176c8d8eccSSepherosa Ziehau 3618beedf5beSSepherosa Ziehau /* Destroy standard RX ring */ 3619beedf5beSSepherosa Ziehau bnx_dma_block_free(std->bnx_rx_std_ring_tag, 3620beedf5beSSepherosa Ziehau std->bnx_rx_std_ring_map, std->bnx_rx_std_ring); 3621beedf5beSSepherosa Ziehau 362233a04907SSepherosa Ziehau /* Destroy TX rings */ 362333a04907SSepherosa Ziehau if (sc->bnx_tx_ring != NULL) { 362433a04907SSepherosa Ziehau for (i = 0; i < sc->bnx_tx_ringcnt; ++i) 362533a04907SSepherosa Ziehau bnx_destroy_tx_ring(&sc->bnx_tx_ring[i]); 362633a04907SSepherosa Ziehau kfree(sc->bnx_tx_ring, M_DEVBUF); 36276c8d8eccSSepherosa Ziehau } 36286c8d8eccSSepherosa Ziehau 36296c8d8eccSSepherosa Ziehau if (BNX_IS_JUMBO_CAPABLE(sc)) 36306c8d8eccSSepherosa Ziehau bnx_free_jumbo_mem(sc); 36316c8d8eccSSepherosa Ziehau 3632*0a806e3aSSepherosa Ziehau /* Destroy status blocks */ 3633*0a806e3aSSepherosa Ziehau for (i = 0; i < sc->bnx_intr_cnt; ++i) { 3634*0a806e3aSSepherosa Ziehau struct bnx_intr_data *intr = &sc->bnx_intr_data[i]; 3635*0a806e3aSSepherosa Ziehau 3636*0a806e3aSSepherosa Ziehau bnx_dma_block_free(intr->bnx_status_tag, 3637*0a806e3aSSepherosa Ziehau intr->bnx_status_map, intr->bnx_status_block); 3638*0a806e3aSSepherosa Ziehau } 36396c8d8eccSSepherosa Ziehau 36406c8d8eccSSepherosa Ziehau /* Destroy the parent tag */ 36416c8d8eccSSepherosa Ziehau if (sc->bnx_cdata.bnx_parent_tag != NULL) 36426c8d8eccSSepherosa Ziehau bus_dma_tag_destroy(sc->bnx_cdata.bnx_parent_tag); 36436c8d8eccSSepherosa Ziehau } 36446c8d8eccSSepherosa Ziehau 36456c8d8eccSSepherosa Ziehau static int 3646beedf5beSSepherosa Ziehau bnx_dma_alloc(device_t dev) 36476c8d8eccSSepherosa Ziehau { 3648beedf5beSSepherosa Ziehau struct bnx_softc *sc = device_get_softc(dev); 3649beedf5beSSepherosa Ziehau struct bnx_rx_std_ring *std = &sc->bnx_rx_std_ring; 3650ac2936fdSSepherosa Ziehau int i, error, mbx; 36516c8d8eccSSepherosa Ziehau 36526c8d8eccSSepherosa Ziehau /* 36536c8d8eccSSepherosa Ziehau * Allocate the parent bus DMA tag appropriate for PCI. 36546c8d8eccSSepherosa Ziehau * 36556c8d8eccSSepherosa Ziehau * All of the NetExtreme/NetLink controllers have 4GB boundary 36566c8d8eccSSepherosa Ziehau * DMA bug. 36576c8d8eccSSepherosa Ziehau * Whenever an address crosses a multiple of the 4GB boundary 36586c8d8eccSSepherosa Ziehau * (including 4GB, 8Gb, 12Gb, etc.) and makes the transition 36596c8d8eccSSepherosa Ziehau * from 0xX_FFFF_FFFF to 0x(X+1)_0000_0000 an internal DMA 36606c8d8eccSSepherosa Ziehau * state machine will lockup and cause the device to hang. 36616c8d8eccSSepherosa Ziehau */ 36626c8d8eccSSepherosa Ziehau error = bus_dma_tag_create(NULL, 1, BGE_DMA_BOUNDARY_4G, 3663beedf5beSSepherosa Ziehau BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL, NULL, 3664beedf5beSSepherosa Ziehau BUS_SPACE_MAXSIZE_32BIT, 0, BUS_SPACE_MAXSIZE_32BIT, 36656c8d8eccSSepherosa Ziehau 0, &sc->bnx_cdata.bnx_parent_tag); 36666c8d8eccSSepherosa Ziehau if (error) { 3667beedf5beSSepherosa Ziehau device_printf(dev, "could not create parent DMA tag\n"); 36686c8d8eccSSepherosa Ziehau return error; 36696c8d8eccSSepherosa Ziehau } 36706c8d8eccSSepherosa Ziehau 36716c8d8eccSSepherosa Ziehau /* 3672*0a806e3aSSepherosa Ziehau * Create DMA stuffs for status blocks. 36736c8d8eccSSepherosa Ziehau */ 3674*0a806e3aSSepherosa Ziehau for (i = 0; i < sc->bnx_intr_cnt; ++i) { 3675*0a806e3aSSepherosa Ziehau struct bnx_intr_data *intr = &sc->bnx_intr_data[i]; 3676*0a806e3aSSepherosa Ziehau 36776c8d8eccSSepherosa Ziehau error = bnx_dma_block_alloc(sc, BGE_STATUS_BLK_SZ, 3678*0a806e3aSSepherosa Ziehau &intr->bnx_status_tag, &intr->bnx_status_map, 3679*0a806e3aSSepherosa Ziehau (void *)&intr->bnx_status_block, 3680*0a806e3aSSepherosa Ziehau &intr->bnx_status_block_paddr); 36816c8d8eccSSepherosa Ziehau if (error) { 3682*0a806e3aSSepherosa Ziehau device_printf(dev, 3683*0a806e3aSSepherosa Ziehau "could not create %dth status block\n", i); 36846c8d8eccSSepherosa Ziehau return error; 36856c8d8eccSSepherosa Ziehau } 3686*0a806e3aSSepherosa Ziehau } 36876c8d8eccSSepherosa Ziehau 3688beedf5beSSepherosa Ziehau /* 3689beedf5beSSepherosa Ziehau * Create DMA tag and maps for RX mbufs. 3690beedf5beSSepherosa Ziehau */ 3691beedf5beSSepherosa Ziehau std->bnx_sc = sc; 3692329f9016SSepherosa Ziehau lwkt_serialize_init(&std->bnx_rx_std_serialize); 3693beedf5beSSepherosa Ziehau error = bus_dma_tag_create(sc->bnx_cdata.bnx_parent_tag, 1, 0, 3694beedf5beSSepherosa Ziehau BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, 3695beedf5beSSepherosa Ziehau NULL, NULL, MCLBYTES, 1, MCLBYTES, 3696beedf5beSSepherosa Ziehau BUS_DMA_ALLOCNOW | BUS_DMA_WAITOK, &std->bnx_rx_mtag); 3697beedf5beSSepherosa Ziehau if (error) { 3698beedf5beSSepherosa Ziehau device_printf(dev, "could not create RX mbuf DMA tag\n"); 3699beedf5beSSepherosa Ziehau return error; 3700beedf5beSSepherosa Ziehau } 3701beedf5beSSepherosa Ziehau 3702beedf5beSSepherosa Ziehau for (i = 0; i < BGE_STD_RX_RING_CNT; ++i) { 3703beedf5beSSepherosa Ziehau error = bus_dmamap_create(std->bnx_rx_mtag, BUS_DMA_WAITOK, 3704beedf5beSSepherosa Ziehau &std->bnx_rx_std_buf[i].bnx_rx_dmamap); 3705beedf5beSSepherosa Ziehau if (error) { 3706beedf5beSSepherosa Ziehau int j; 3707beedf5beSSepherosa Ziehau 3708beedf5beSSepherosa Ziehau for (j = 0; j < i; ++j) { 3709beedf5beSSepherosa Ziehau bus_dmamap_destroy(std->bnx_rx_mtag, 3710beedf5beSSepherosa Ziehau std->bnx_rx_std_buf[j].bnx_rx_dmamap); 3711beedf5beSSepherosa Ziehau } 3712beedf5beSSepherosa Ziehau bus_dma_tag_destroy(std->bnx_rx_mtag); 3713beedf5beSSepherosa Ziehau std->bnx_rx_mtag = NULL; 3714beedf5beSSepherosa Ziehau 3715beedf5beSSepherosa Ziehau device_printf(dev, 3716beedf5beSSepherosa Ziehau "could not create %dth RX mbuf DMA map\n", i); 3717beedf5beSSepherosa Ziehau return error; 3718beedf5beSSepherosa Ziehau } 3719beedf5beSSepherosa Ziehau } 3720beedf5beSSepherosa Ziehau 3721beedf5beSSepherosa Ziehau /* 3722beedf5beSSepherosa Ziehau * Create DMA stuffs for standard RX ring. 3723beedf5beSSepherosa Ziehau */ 3724beedf5beSSepherosa Ziehau error = bnx_dma_block_alloc(sc, BGE_STD_RX_RING_SZ, 3725beedf5beSSepherosa Ziehau &std->bnx_rx_std_ring_tag, 3726beedf5beSSepherosa Ziehau &std->bnx_rx_std_ring_map, 3727beedf5beSSepherosa Ziehau (void *)&std->bnx_rx_std_ring, 3728beedf5beSSepherosa Ziehau &std->bnx_rx_std_ring_paddr); 3729beedf5beSSepherosa Ziehau if (error) { 3730beedf5beSSepherosa Ziehau device_printf(dev, "could not create std RX ring\n"); 3731beedf5beSSepherosa Ziehau return error; 3732beedf5beSSepherosa Ziehau } 3733beedf5beSSepherosa Ziehau 3734beedf5beSSepherosa Ziehau /* 3735beedf5beSSepherosa Ziehau * Create RX return rings 3736beedf5beSSepherosa Ziehau */ 3737ac2936fdSSepherosa Ziehau mbx = BGE_MBX_RX_CONS0_LO; 3738beedf5beSSepherosa Ziehau sc->bnx_rx_ret_ring = kmalloc_cachealign( 3739beedf5beSSepherosa Ziehau sizeof(struct bnx_rx_ret_ring) * sc->bnx_rx_retcnt, M_DEVBUF, 3740beedf5beSSepherosa Ziehau M_WAITOK | M_ZERO); 3741beedf5beSSepherosa Ziehau for (i = 0; i < sc->bnx_rx_retcnt; ++i) { 3742beedf5beSSepherosa Ziehau struct bnx_rx_ret_ring *ret = &sc->bnx_rx_ret_ring[i]; 3743*0a806e3aSSepherosa Ziehau struct bnx_intr_data *intr; 3744beedf5beSSepherosa Ziehau 3745beedf5beSSepherosa Ziehau ret->bnx_sc = sc; 3746beedf5beSSepherosa Ziehau ret->bnx_std = std; 3747ac2936fdSSepherosa Ziehau ret->bnx_rx_mbx = mbx; 3748841cdf08SSepherosa Ziehau ret->bnx_rx_cntmax = (BGE_STD_RX_RING_CNT / 4) / 3749841cdf08SSepherosa Ziehau sc->bnx_rx_retcnt; 3750841cdf08SSepherosa Ziehau ret->bnx_rx_mask = 1 << i; 37513a16b7b8SSepherosa Ziehau 3752*0a806e3aSSepherosa Ziehau if (sc->bnx_rx_retcnt == 1) { 3753*0a806e3aSSepherosa Ziehau intr = &sc->bnx_intr_data[0]; 3754*0a806e3aSSepherosa Ziehau } else { 3755*0a806e3aSSepherosa Ziehau KKASSERT(i + 1 < sc->bnx_intr_cnt); 3756*0a806e3aSSepherosa Ziehau intr = &sc->bnx_intr_data[i + 1]; 3757*0a806e3aSSepherosa Ziehau } 3758*0a806e3aSSepherosa Ziehau 37593a16b7b8SSepherosa Ziehau ret->bnx_rx_considx = 3760*0a806e3aSSepherosa Ziehau &intr->bnx_status_block->bge_idx[0].bge_rx_prod_idx; 37614fa38985SSepherosa Ziehau ret->bnx_hw_status_tag = 3762*0a806e3aSSepherosa Ziehau &intr->bnx_status_block->bge_status_tag; 37633a16b7b8SSepherosa Ziehau 3764beedf5beSSepherosa Ziehau error = bnx_create_rx_ret_ring(ret); 3765beedf5beSSepherosa Ziehau if (error) { 3766beedf5beSSepherosa Ziehau device_printf(dev, 3767beedf5beSSepherosa Ziehau "could not create %dth RX ret ring\n", i); 3768beedf5beSSepherosa Ziehau return error; 3769beedf5beSSepherosa Ziehau } 3770ac2936fdSSepherosa Ziehau mbx += 8; 3771beedf5beSSepherosa Ziehau } 3772beedf5beSSepherosa Ziehau 3773beedf5beSSepherosa Ziehau /* 3774beedf5beSSepherosa Ziehau * Create TX rings 3775beedf5beSSepherosa Ziehau */ 377633a04907SSepherosa Ziehau sc->bnx_tx_ring = kmalloc_cachealign( 377733a04907SSepherosa Ziehau sizeof(struct bnx_tx_ring) * sc->bnx_tx_ringcnt, M_DEVBUF, 377833a04907SSepherosa Ziehau M_WAITOK | M_ZERO); 377933a04907SSepherosa Ziehau for (i = 0; i < sc->bnx_tx_ringcnt; ++i) { 378033a04907SSepherosa Ziehau struct bnx_tx_ring *txr = &sc->bnx_tx_ring[i]; 3781*0a806e3aSSepherosa Ziehau struct bnx_intr_data *intr; 378233a04907SSepherosa Ziehau 378333a04907SSepherosa Ziehau txr->bnx_sc = sc; 37841c9d03f6SSepherosa Ziehau txr->bnx_tx_mbx = bnx_tx_mailbox[i]; 37858bd43d5dSSepherosa Ziehau 3786*0a806e3aSSepherosa Ziehau if (sc->bnx_tx_ringcnt == 1) { 3787*0a806e3aSSepherosa Ziehau intr = &sc->bnx_intr_data[0]; 3788*0a806e3aSSepherosa Ziehau } else { 3789*0a806e3aSSepherosa Ziehau KKASSERT(i + 1 < sc->bnx_intr_cnt); 3790*0a806e3aSSepherosa Ziehau intr = &sc->bnx_intr_data[i + 1]; 3791*0a806e3aSSepherosa Ziehau } 3792*0a806e3aSSepherosa Ziehau 37933a16b7b8SSepherosa Ziehau txr->bnx_tx_considx = 3794*0a806e3aSSepherosa Ziehau &intr->bnx_status_block->bge_idx[0].bge_tx_cons_idx; 37953a16b7b8SSepherosa Ziehau 379633a04907SSepherosa Ziehau error = bnx_create_tx_ring(txr); 379733a04907SSepherosa Ziehau if (error) { 3798beedf5beSSepherosa Ziehau device_printf(dev, 3799beedf5beSSepherosa Ziehau "could not create %dth TX ring\n", i); 3800beedf5beSSepherosa Ziehau return error; 3801beedf5beSSepherosa Ziehau } 3802beedf5beSSepherosa Ziehau } 3803beedf5beSSepherosa Ziehau 3804beedf5beSSepherosa Ziehau /* 3805beedf5beSSepherosa Ziehau * Create jumbo buffer pool. 3806beedf5beSSepherosa Ziehau */ 3807beedf5beSSepherosa Ziehau if (BNX_IS_JUMBO_CAPABLE(sc)) { 3808beedf5beSSepherosa Ziehau error = bnx_alloc_jumbo_mem(sc); 3809beedf5beSSepherosa Ziehau if (error) { 3810beedf5beSSepherosa Ziehau device_printf(dev, 3811beedf5beSSepherosa Ziehau "could not create jumbo buffer pool\n"); 381233a04907SSepherosa Ziehau return error; 381333a04907SSepherosa Ziehau } 381433a04907SSepherosa Ziehau } 381533a04907SSepherosa Ziehau 38166c8d8eccSSepherosa Ziehau return 0; 38176c8d8eccSSepherosa Ziehau } 38186c8d8eccSSepherosa Ziehau 38196c8d8eccSSepherosa Ziehau static int 38206c8d8eccSSepherosa Ziehau bnx_dma_block_alloc(struct bnx_softc *sc, bus_size_t size, bus_dma_tag_t *tag, 38216c8d8eccSSepherosa Ziehau bus_dmamap_t *map, void **addr, bus_addr_t *paddr) 38226c8d8eccSSepherosa Ziehau { 38236c8d8eccSSepherosa Ziehau bus_dmamem_t dmem; 38246c8d8eccSSepherosa Ziehau int error; 38256c8d8eccSSepherosa Ziehau 38266c8d8eccSSepherosa Ziehau error = bus_dmamem_coherent(sc->bnx_cdata.bnx_parent_tag, PAGE_SIZE, 0, 38276c8d8eccSSepherosa Ziehau BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, 38286c8d8eccSSepherosa Ziehau size, BUS_DMA_WAITOK | BUS_DMA_ZERO, &dmem); 38296c8d8eccSSepherosa Ziehau if (error) 38306c8d8eccSSepherosa Ziehau return error; 38316c8d8eccSSepherosa Ziehau 38326c8d8eccSSepherosa Ziehau *tag = dmem.dmem_tag; 38336c8d8eccSSepherosa Ziehau *map = dmem.dmem_map; 38346c8d8eccSSepherosa Ziehau *addr = dmem.dmem_addr; 38356c8d8eccSSepherosa Ziehau *paddr = dmem.dmem_busaddr; 38366c8d8eccSSepherosa Ziehau 38376c8d8eccSSepherosa Ziehau return 0; 38386c8d8eccSSepherosa Ziehau } 38396c8d8eccSSepherosa Ziehau 38406c8d8eccSSepherosa Ziehau static void 38416c8d8eccSSepherosa Ziehau bnx_dma_block_free(bus_dma_tag_t tag, bus_dmamap_t map, void *addr) 38426c8d8eccSSepherosa Ziehau { 38436c8d8eccSSepherosa Ziehau if (tag != NULL) { 38446c8d8eccSSepherosa Ziehau bus_dmamap_unload(tag, map); 38456c8d8eccSSepherosa Ziehau bus_dmamem_free(tag, addr, map); 38466c8d8eccSSepherosa Ziehau bus_dma_tag_destroy(tag); 38476c8d8eccSSepherosa Ziehau } 38486c8d8eccSSepherosa Ziehau } 38496c8d8eccSSepherosa Ziehau 38506c8d8eccSSepherosa Ziehau static void 38516c8d8eccSSepherosa Ziehau bnx_tbi_link_upd(struct bnx_softc *sc, uint32_t status) 38526c8d8eccSSepherosa Ziehau { 38536c8d8eccSSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if; 38546c8d8eccSSepherosa Ziehau 38556c8d8eccSSepherosa Ziehau #define PCS_ENCODE_ERR (BGE_MACSTAT_PORT_DECODE_ERROR|BGE_MACSTAT_MI_COMPLETE) 38566c8d8eccSSepherosa Ziehau 38576c8d8eccSSepherosa Ziehau /* 38586c8d8eccSSepherosa Ziehau * Sometimes PCS encoding errors are detected in 38596c8d8eccSSepherosa Ziehau * TBI mode (on fiber NICs), and for some reason 38606c8d8eccSSepherosa Ziehau * the chip will signal them as link changes. 38616c8d8eccSSepherosa Ziehau * If we get a link change event, but the 'PCS 38626c8d8eccSSepherosa Ziehau * encoding error' bit in the MAC status register 38636c8d8eccSSepherosa Ziehau * is set, don't bother doing a link check. 38646c8d8eccSSepherosa Ziehau * This avoids spurious "gigabit link up" messages 38656c8d8eccSSepherosa Ziehau * that sometimes appear on fiber NICs during 38666c8d8eccSSepherosa Ziehau * periods of heavy traffic. 38676c8d8eccSSepherosa Ziehau */ 38686c8d8eccSSepherosa Ziehau if (status & BGE_MACSTAT_TBI_PCS_SYNCHED) { 38696c8d8eccSSepherosa Ziehau if (!sc->bnx_link) { 38706c8d8eccSSepherosa Ziehau sc->bnx_link++; 38716c8d8eccSSepherosa Ziehau if (sc->bnx_asicrev == BGE_ASICREV_BCM5704) { 38726c8d8eccSSepherosa Ziehau BNX_CLRBIT(sc, BGE_MAC_MODE, 38736c8d8eccSSepherosa Ziehau BGE_MACMODE_TBI_SEND_CFGS); 38746c8d8eccSSepherosa Ziehau } 38756c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_MAC_STS, 0xFFFFFFFF); 38766c8d8eccSSepherosa Ziehau 38776c8d8eccSSepherosa Ziehau if (bootverbose) 38786c8d8eccSSepherosa Ziehau if_printf(ifp, "link UP\n"); 38796c8d8eccSSepherosa Ziehau 38806c8d8eccSSepherosa Ziehau ifp->if_link_state = LINK_STATE_UP; 38816c8d8eccSSepherosa Ziehau if_link_state_change(ifp); 38826c8d8eccSSepherosa Ziehau } 38836c8d8eccSSepherosa Ziehau } else if ((status & PCS_ENCODE_ERR) != PCS_ENCODE_ERR) { 38846c8d8eccSSepherosa Ziehau if (sc->bnx_link) { 38856c8d8eccSSepherosa Ziehau sc->bnx_link = 0; 38866c8d8eccSSepherosa Ziehau 38876c8d8eccSSepherosa Ziehau if (bootverbose) 38886c8d8eccSSepherosa Ziehau if_printf(ifp, "link DOWN\n"); 38896c8d8eccSSepherosa Ziehau 38906c8d8eccSSepherosa Ziehau ifp->if_link_state = LINK_STATE_DOWN; 38916c8d8eccSSepherosa Ziehau if_link_state_change(ifp); 38926c8d8eccSSepherosa Ziehau } 38936c8d8eccSSepherosa Ziehau } 38946c8d8eccSSepherosa Ziehau 38956c8d8eccSSepherosa Ziehau #undef PCS_ENCODE_ERR 38966c8d8eccSSepherosa Ziehau 38976c8d8eccSSepherosa Ziehau /* Clear the attention. */ 38986c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_MAC_STS, BGE_MACSTAT_SYNC_CHANGED | 38996c8d8eccSSepherosa Ziehau BGE_MACSTAT_CFG_CHANGED | BGE_MACSTAT_MI_COMPLETE | 39006c8d8eccSSepherosa Ziehau BGE_MACSTAT_LINK_CHANGED); 39016c8d8eccSSepherosa Ziehau } 39026c8d8eccSSepherosa Ziehau 39036c8d8eccSSepherosa Ziehau static void 39046c8d8eccSSepherosa Ziehau bnx_copper_link_upd(struct bnx_softc *sc, uint32_t status __unused) 39056c8d8eccSSepherosa Ziehau { 39066c8d8eccSSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if; 39076c8d8eccSSepherosa Ziehau struct mii_data *mii = device_get_softc(sc->bnx_miibus); 39086c8d8eccSSepherosa Ziehau 39096c8d8eccSSepherosa Ziehau mii_pollstat(mii); 39106c8d8eccSSepherosa Ziehau bnx_miibus_statchg(sc->bnx_dev); 39116c8d8eccSSepherosa Ziehau 39126c8d8eccSSepherosa Ziehau if (bootverbose) { 39136c8d8eccSSepherosa Ziehau if (sc->bnx_link) 39146c8d8eccSSepherosa Ziehau if_printf(ifp, "link UP\n"); 39156c8d8eccSSepherosa Ziehau else 39166c8d8eccSSepherosa Ziehau if_printf(ifp, "link DOWN\n"); 39176c8d8eccSSepherosa Ziehau } 39186c8d8eccSSepherosa Ziehau 39196c8d8eccSSepherosa Ziehau /* Clear the attention. */ 39206c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_MAC_STS, BGE_MACSTAT_SYNC_CHANGED | 39216c8d8eccSSepherosa Ziehau BGE_MACSTAT_CFG_CHANGED | BGE_MACSTAT_MI_COMPLETE | 39226c8d8eccSSepherosa Ziehau BGE_MACSTAT_LINK_CHANGED); 39236c8d8eccSSepherosa Ziehau } 39246c8d8eccSSepherosa Ziehau 39256c8d8eccSSepherosa Ziehau static void 39266c8d8eccSSepherosa Ziehau bnx_autopoll_link_upd(struct bnx_softc *sc, uint32_t status __unused) 39276c8d8eccSSepherosa Ziehau { 39286c8d8eccSSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if; 39296c8d8eccSSepherosa Ziehau struct mii_data *mii = device_get_softc(sc->bnx_miibus); 39306c8d8eccSSepherosa Ziehau 39316c8d8eccSSepherosa Ziehau mii_pollstat(mii); 39326c8d8eccSSepherosa Ziehau 39336c8d8eccSSepherosa Ziehau if (!sc->bnx_link && 39346c8d8eccSSepherosa Ziehau (mii->mii_media_status & IFM_ACTIVE) && 39356c8d8eccSSepherosa Ziehau IFM_SUBTYPE(mii->mii_media_active) != IFM_NONE) { 39366c8d8eccSSepherosa Ziehau sc->bnx_link++; 39376c8d8eccSSepherosa Ziehau if (bootverbose) 39386c8d8eccSSepherosa Ziehau if_printf(ifp, "link UP\n"); 39396c8d8eccSSepherosa Ziehau } else if (sc->bnx_link && 39406c8d8eccSSepherosa Ziehau (!(mii->mii_media_status & IFM_ACTIVE) || 39416c8d8eccSSepherosa Ziehau IFM_SUBTYPE(mii->mii_media_active) == IFM_NONE)) { 39426c8d8eccSSepherosa Ziehau sc->bnx_link = 0; 39436c8d8eccSSepherosa Ziehau if (bootverbose) 39446c8d8eccSSepherosa Ziehau if_printf(ifp, "link DOWN\n"); 39456c8d8eccSSepherosa Ziehau } 39466c8d8eccSSepherosa Ziehau 39476c8d8eccSSepherosa Ziehau /* Clear the attention. */ 39486c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_MAC_STS, BGE_MACSTAT_SYNC_CHANGED | 39496c8d8eccSSepherosa Ziehau BGE_MACSTAT_CFG_CHANGED | BGE_MACSTAT_MI_COMPLETE | 39506c8d8eccSSepherosa Ziehau BGE_MACSTAT_LINK_CHANGED); 39516c8d8eccSSepherosa Ziehau } 39526c8d8eccSSepherosa Ziehau 39536c8d8eccSSepherosa Ziehau static int 39546c8d8eccSSepherosa Ziehau bnx_sysctl_rx_coal_ticks(SYSCTL_HANDLER_ARGS) 39556c8d8eccSSepherosa Ziehau { 39566c8d8eccSSepherosa Ziehau struct bnx_softc *sc = arg1; 39576c8d8eccSSepherosa Ziehau 39586c8d8eccSSepherosa Ziehau return bnx_sysctl_coal_chg(oidp, arg1, arg2, req, 39596c8d8eccSSepherosa Ziehau &sc->bnx_rx_coal_ticks, 39606c8d8eccSSepherosa Ziehau BNX_RX_COAL_TICKS_MIN, BNX_RX_COAL_TICKS_MAX, 39616c8d8eccSSepherosa Ziehau BNX_RX_COAL_TICKS_CHG); 39626c8d8eccSSepherosa Ziehau } 39636c8d8eccSSepherosa Ziehau 39646c8d8eccSSepherosa Ziehau static int 39656c8d8eccSSepherosa Ziehau bnx_sysctl_tx_coal_ticks(SYSCTL_HANDLER_ARGS) 39666c8d8eccSSepherosa Ziehau { 39676c8d8eccSSepherosa Ziehau struct bnx_softc *sc = arg1; 39686c8d8eccSSepherosa Ziehau 39696c8d8eccSSepherosa Ziehau return bnx_sysctl_coal_chg(oidp, arg1, arg2, req, 39706c8d8eccSSepherosa Ziehau &sc->bnx_tx_coal_ticks, 39716c8d8eccSSepherosa Ziehau BNX_TX_COAL_TICKS_MIN, BNX_TX_COAL_TICKS_MAX, 39726c8d8eccSSepherosa Ziehau BNX_TX_COAL_TICKS_CHG); 39736c8d8eccSSepherosa Ziehau } 39746c8d8eccSSepherosa Ziehau 39756c8d8eccSSepherosa Ziehau static int 39766c8d8eccSSepherosa Ziehau bnx_sysctl_rx_coal_bds(SYSCTL_HANDLER_ARGS) 39776c8d8eccSSepherosa Ziehau { 39786c8d8eccSSepherosa Ziehau struct bnx_softc *sc = arg1; 39796c8d8eccSSepherosa Ziehau 39806c8d8eccSSepherosa Ziehau return bnx_sysctl_coal_chg(oidp, arg1, arg2, req, 39816c8d8eccSSepherosa Ziehau &sc->bnx_rx_coal_bds, 39826c8d8eccSSepherosa Ziehau BNX_RX_COAL_BDS_MIN, BNX_RX_COAL_BDS_MAX, 39836c8d8eccSSepherosa Ziehau BNX_RX_COAL_BDS_CHG); 39846c8d8eccSSepherosa Ziehau } 39856c8d8eccSSepherosa Ziehau 39866c8d8eccSSepherosa Ziehau static int 39876c8d8eccSSepherosa Ziehau bnx_sysctl_tx_coal_bds(SYSCTL_HANDLER_ARGS) 39886c8d8eccSSepherosa Ziehau { 39896c8d8eccSSepherosa Ziehau struct bnx_softc *sc = arg1; 39906c8d8eccSSepherosa Ziehau 39916c8d8eccSSepherosa Ziehau return bnx_sysctl_coal_chg(oidp, arg1, arg2, req, 39926c8d8eccSSepherosa Ziehau &sc->bnx_tx_coal_bds, 39936c8d8eccSSepherosa Ziehau BNX_TX_COAL_BDS_MIN, BNX_TX_COAL_BDS_MAX, 39946c8d8eccSSepherosa Ziehau BNX_TX_COAL_BDS_CHG); 39956c8d8eccSSepherosa Ziehau } 39966c8d8eccSSepherosa Ziehau 39976c8d8eccSSepherosa Ziehau static int 39986c8d8eccSSepherosa Ziehau bnx_sysctl_rx_coal_bds_int(SYSCTL_HANDLER_ARGS) 39996c8d8eccSSepherosa Ziehau { 40006c8d8eccSSepherosa Ziehau struct bnx_softc *sc = arg1; 40016c8d8eccSSepherosa Ziehau 40026c8d8eccSSepherosa Ziehau return bnx_sysctl_coal_chg(oidp, arg1, arg2, req, 40036c8d8eccSSepherosa Ziehau &sc->bnx_rx_coal_bds_int, 40046c8d8eccSSepherosa Ziehau BNX_RX_COAL_BDS_MIN, BNX_RX_COAL_BDS_MAX, 40056c8d8eccSSepherosa Ziehau BNX_RX_COAL_BDS_INT_CHG); 40066c8d8eccSSepherosa Ziehau } 40076c8d8eccSSepherosa Ziehau 40086c8d8eccSSepherosa Ziehau static int 40096c8d8eccSSepherosa Ziehau bnx_sysctl_tx_coal_bds_int(SYSCTL_HANDLER_ARGS) 40106c8d8eccSSepherosa Ziehau { 40116c8d8eccSSepherosa Ziehau struct bnx_softc *sc = arg1; 40126c8d8eccSSepherosa Ziehau 40136c8d8eccSSepherosa Ziehau return bnx_sysctl_coal_chg(oidp, arg1, arg2, req, 40146c8d8eccSSepherosa Ziehau &sc->bnx_tx_coal_bds_int, 40156c8d8eccSSepherosa Ziehau BNX_TX_COAL_BDS_MIN, BNX_TX_COAL_BDS_MAX, 40166c8d8eccSSepherosa Ziehau BNX_TX_COAL_BDS_INT_CHG); 40176c8d8eccSSepherosa Ziehau } 40186c8d8eccSSepherosa Ziehau 40196c8d8eccSSepherosa Ziehau static int 40206c8d8eccSSepherosa Ziehau bnx_sysctl_coal_chg(SYSCTL_HANDLER_ARGS, uint32_t *coal, 40216c8d8eccSSepherosa Ziehau int coal_min, int coal_max, uint32_t coal_chg_mask) 40226c8d8eccSSepherosa Ziehau { 40236c8d8eccSSepherosa Ziehau struct bnx_softc *sc = arg1; 40246c8d8eccSSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if; 40256c8d8eccSSepherosa Ziehau int error = 0, v; 40266c8d8eccSSepherosa Ziehau 4027329f9016SSepherosa Ziehau ifnet_serialize_all(ifp); 40286c8d8eccSSepherosa Ziehau 40296c8d8eccSSepherosa Ziehau v = *coal; 40306c8d8eccSSepherosa Ziehau error = sysctl_handle_int(oidp, &v, 0, req); 40316c8d8eccSSepherosa Ziehau if (!error && req->newptr != NULL) { 40326c8d8eccSSepherosa Ziehau if (v < coal_min || v > coal_max) { 40336c8d8eccSSepherosa Ziehau error = EINVAL; 40346c8d8eccSSepherosa Ziehau } else { 40356c8d8eccSSepherosa Ziehau *coal = v; 40366c8d8eccSSepherosa Ziehau sc->bnx_coal_chg |= coal_chg_mask; 4037f5014362SSepherosa Ziehau 4038f5014362SSepherosa Ziehau /* Commit changes */ 4039f5014362SSepherosa Ziehau bnx_coal_change(sc); 40406c8d8eccSSepherosa Ziehau } 40416c8d8eccSSepherosa Ziehau } 40426c8d8eccSSepherosa Ziehau 4043329f9016SSepherosa Ziehau ifnet_deserialize_all(ifp); 40446c8d8eccSSepherosa Ziehau return error; 40456c8d8eccSSepherosa Ziehau } 40466c8d8eccSSepherosa Ziehau 40476c8d8eccSSepherosa Ziehau static void 40486c8d8eccSSepherosa Ziehau bnx_coal_change(struct bnx_softc *sc) 40496c8d8eccSSepherosa Ziehau { 40506c8d8eccSSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if; 40516c8d8eccSSepherosa Ziehau 4052329f9016SSepherosa Ziehau ASSERT_IFNET_SERIALIZED_ALL(ifp); 40536c8d8eccSSepherosa Ziehau 40546c8d8eccSSepherosa Ziehau if (sc->bnx_coal_chg & BNX_RX_COAL_TICKS_CHG) { 40556c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_HCC_RX_COAL_TICKS, 40566c8d8eccSSepherosa Ziehau sc->bnx_rx_coal_ticks); 40576c8d8eccSSepherosa Ziehau DELAY(10); 4058e594b5c4SSepherosa Ziehau CSR_READ_4(sc, BGE_HCC_RX_COAL_TICKS); 40596c8d8eccSSepherosa Ziehau 40606c8d8eccSSepherosa Ziehau if (bootverbose) { 40616c8d8eccSSepherosa Ziehau if_printf(ifp, "rx_coal_ticks -> %u\n", 40626c8d8eccSSepherosa Ziehau sc->bnx_rx_coal_ticks); 40636c8d8eccSSepherosa Ziehau } 40646c8d8eccSSepherosa Ziehau } 40656c8d8eccSSepherosa Ziehau 40666c8d8eccSSepherosa Ziehau if (sc->bnx_coal_chg & BNX_TX_COAL_TICKS_CHG) { 40676c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_HCC_TX_COAL_TICKS, 40686c8d8eccSSepherosa Ziehau sc->bnx_tx_coal_ticks); 40696c8d8eccSSepherosa Ziehau DELAY(10); 4070e594b5c4SSepherosa Ziehau CSR_READ_4(sc, BGE_HCC_TX_COAL_TICKS); 40716c8d8eccSSepherosa Ziehau 40726c8d8eccSSepherosa Ziehau if (bootverbose) { 40736c8d8eccSSepherosa Ziehau if_printf(ifp, "tx_coal_ticks -> %u\n", 40746c8d8eccSSepherosa Ziehau sc->bnx_tx_coal_ticks); 40756c8d8eccSSepherosa Ziehau } 40766c8d8eccSSepherosa Ziehau } 40776c8d8eccSSepherosa Ziehau 40786c8d8eccSSepherosa Ziehau if (sc->bnx_coal_chg & BNX_RX_COAL_BDS_CHG) { 40796c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_HCC_RX_MAX_COAL_BDS, 40806c8d8eccSSepherosa Ziehau sc->bnx_rx_coal_bds); 40816c8d8eccSSepherosa Ziehau DELAY(10); 4082e594b5c4SSepherosa Ziehau CSR_READ_4(sc, BGE_HCC_RX_MAX_COAL_BDS); 40836c8d8eccSSepherosa Ziehau 40846c8d8eccSSepherosa Ziehau if (bootverbose) { 40856c8d8eccSSepherosa Ziehau if_printf(ifp, "rx_coal_bds -> %u\n", 40866c8d8eccSSepherosa Ziehau sc->bnx_rx_coal_bds); 40876c8d8eccSSepherosa Ziehau } 40886c8d8eccSSepherosa Ziehau } 40896c8d8eccSSepherosa Ziehau 40906c8d8eccSSepherosa Ziehau if (sc->bnx_coal_chg & BNX_TX_COAL_BDS_CHG) { 40916c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_HCC_TX_MAX_COAL_BDS, 40926c8d8eccSSepherosa Ziehau sc->bnx_tx_coal_bds); 40936c8d8eccSSepherosa Ziehau DELAY(10); 4094e594b5c4SSepherosa Ziehau CSR_READ_4(sc, BGE_HCC_TX_MAX_COAL_BDS); 40956c8d8eccSSepherosa Ziehau 40966c8d8eccSSepherosa Ziehau if (bootverbose) { 4097cc98a7c2SSepherosa Ziehau if_printf(ifp, "tx_coal_bds -> %u\n", 40986c8d8eccSSepherosa Ziehau sc->bnx_tx_coal_bds); 40996c8d8eccSSepherosa Ziehau } 41006c8d8eccSSepherosa Ziehau } 41016c8d8eccSSepherosa Ziehau 41026c8d8eccSSepherosa Ziehau if (sc->bnx_coal_chg & BNX_RX_COAL_BDS_INT_CHG) { 41036c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_HCC_RX_MAX_COAL_BDS_INT, 41046c8d8eccSSepherosa Ziehau sc->bnx_rx_coal_bds_int); 41056c8d8eccSSepherosa Ziehau DELAY(10); 4106e594b5c4SSepherosa Ziehau CSR_READ_4(sc, BGE_HCC_RX_MAX_COAL_BDS_INT); 41076c8d8eccSSepherosa Ziehau 41086c8d8eccSSepherosa Ziehau if (bootverbose) { 41096c8d8eccSSepherosa Ziehau if_printf(ifp, "rx_coal_bds_int -> %u\n", 41106c8d8eccSSepherosa Ziehau sc->bnx_rx_coal_bds_int); 41116c8d8eccSSepherosa Ziehau } 41126c8d8eccSSepherosa Ziehau } 41136c8d8eccSSepherosa Ziehau 41146c8d8eccSSepherosa Ziehau if (sc->bnx_coal_chg & BNX_TX_COAL_BDS_INT_CHG) { 41156c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_HCC_TX_MAX_COAL_BDS_INT, 41166c8d8eccSSepherosa Ziehau sc->bnx_tx_coal_bds_int); 41176c8d8eccSSepherosa Ziehau DELAY(10); 4118e594b5c4SSepherosa Ziehau CSR_READ_4(sc, BGE_HCC_TX_MAX_COAL_BDS_INT); 41196c8d8eccSSepherosa Ziehau 41206c8d8eccSSepherosa Ziehau if (bootverbose) { 41216c8d8eccSSepherosa Ziehau if_printf(ifp, "tx_coal_bds_int -> %u\n", 41226c8d8eccSSepherosa Ziehau sc->bnx_tx_coal_bds_int); 41236c8d8eccSSepherosa Ziehau } 41246c8d8eccSSepherosa Ziehau } 41256c8d8eccSSepherosa Ziehau 41266c8d8eccSSepherosa Ziehau sc->bnx_coal_chg = 0; 41276c8d8eccSSepherosa Ziehau } 41286c8d8eccSSepherosa Ziehau 41296c8d8eccSSepherosa Ziehau static void 4130f33ac8a4SSepherosa Ziehau bnx_check_intr(void *xintr) 4131df9ccc98SSepherosa Ziehau { 4132f33ac8a4SSepherosa Ziehau struct bnx_intr_data *intr = xintr; 4133f33ac8a4SSepherosa Ziehau struct bnx_rx_ret_ring *ret; 4134f33ac8a4SSepherosa Ziehau struct bnx_tx_ring *txr; 4135f33ac8a4SSepherosa Ziehau struct ifnet *ifp; 4136df9ccc98SSepherosa Ziehau 4137f33ac8a4SSepherosa Ziehau lwkt_serialize_enter(intr->bnx_intr_serialize); 4138df9ccc98SSepherosa Ziehau 4139f33ac8a4SSepherosa Ziehau KKASSERT(mycpuid == intr->bnx_intr_cpuid); 4140df9ccc98SSepherosa Ziehau 4141f33ac8a4SSepherosa Ziehau ifp = &intr->bnx_sc->arpcom.ac_if; 414239a8d43aSSepherosa Ziehau if ((ifp->if_flags & (IFF_RUNNING | IFF_NPOLLING)) != IFF_RUNNING) { 4143f33ac8a4SSepherosa Ziehau lwkt_serialize_exit(intr->bnx_intr_serialize); 4144df9ccc98SSepherosa Ziehau return; 4145df9ccc98SSepherosa Ziehau } 4146df9ccc98SSepherosa Ziehau 4147f33ac8a4SSepherosa Ziehau txr = intr->bnx_txr; 4148f33ac8a4SSepherosa Ziehau ret = intr->bnx_ret; 4149f33ac8a4SSepherosa Ziehau 41503a16b7b8SSepherosa Ziehau if (*ret->bnx_rx_considx != ret->bnx_rx_saved_considx || 41513a16b7b8SSepherosa Ziehau *txr->bnx_tx_considx != txr->bnx_tx_saved_considx) { 4152f33ac8a4SSepherosa Ziehau if (intr->bnx_rx_check_considx == ret->bnx_rx_saved_considx && 4153f33ac8a4SSepherosa Ziehau intr->bnx_tx_check_considx == txr->bnx_tx_saved_considx) { 4154f33ac8a4SSepherosa Ziehau if (!intr->bnx_intr_maylose) { 4155f33ac8a4SSepherosa Ziehau intr->bnx_intr_maylose = TRUE; 4156df9ccc98SSepherosa Ziehau goto done; 4157df9ccc98SSepherosa Ziehau } 4158df9ccc98SSepherosa Ziehau if (bootverbose) 4159df9ccc98SSepherosa Ziehau if_printf(ifp, "lost interrupt\n"); 4160f33ac8a4SSepherosa Ziehau intr->bnx_intr_func(intr->bnx_intr_arg); 4161df9ccc98SSepherosa Ziehau } 4162df9ccc98SSepherosa Ziehau } 4163f33ac8a4SSepherosa Ziehau intr->bnx_intr_maylose = FALSE; 4164f33ac8a4SSepherosa Ziehau intr->bnx_rx_check_considx = ret->bnx_rx_saved_considx; 4165f33ac8a4SSepherosa Ziehau intr->bnx_tx_check_considx = txr->bnx_tx_saved_considx; 4166df9ccc98SSepherosa Ziehau 4167df9ccc98SSepherosa Ziehau done: 4168f33ac8a4SSepherosa Ziehau callout_reset(&intr->bnx_intr_timer, BNX_INTR_CKINTVL, 4169f33ac8a4SSepherosa Ziehau intr->bnx_intr_check, intr); 4170f33ac8a4SSepherosa Ziehau lwkt_serialize_exit(intr->bnx_intr_serialize); 4171df9ccc98SSepherosa Ziehau } 4172df9ccc98SSepherosa Ziehau 4173df9ccc98SSepherosa Ziehau static void 41746c8d8eccSSepherosa Ziehau bnx_enable_intr(struct bnx_softc *sc) 41756c8d8eccSSepherosa Ziehau { 41766c8d8eccSSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if; 41774fa38985SSepherosa Ziehau struct bnx_intr_data *intr; 4178f33ac8a4SSepherosa Ziehau int i; 41796c8d8eccSSepherosa Ziehau 4180f33ac8a4SSepherosa Ziehau for (i = 0; i < sc->bnx_intr_cnt; ++i) { 4181f33ac8a4SSepherosa Ziehau lwkt_serialize_handler_enable( 4182f33ac8a4SSepherosa Ziehau sc->bnx_intr_data[i].bnx_intr_serialize); 4183f33ac8a4SSepherosa Ziehau } 41846c8d8eccSSepherosa Ziehau 41856c8d8eccSSepherosa Ziehau /* 41866c8d8eccSSepherosa Ziehau * Enable interrupt. 41876c8d8eccSSepherosa Ziehau */ 41884fa38985SSepherosa Ziehau intr = &sc->bnx_intr_data[0]; /* XXX */ 41894fa38985SSepherosa Ziehau bnx_writembx(sc, BGE_MBX_IRQ0_LO, (*intr->bnx_saved_status_tag) << 24); 41906c8d8eccSSepherosa Ziehau if (sc->bnx_flags & BNX_FLAG_ONESHOT_MSI) { 41916c8d8eccSSepherosa Ziehau /* XXX Linux driver */ 41924fa38985SSepherosa Ziehau bnx_writembx(sc, BGE_MBX_IRQ0_LO, 41934fa38985SSepherosa Ziehau (*intr->bnx_saved_status_tag) << 24); 41946c8d8eccSSepherosa Ziehau } 41956c8d8eccSSepherosa Ziehau 41966c8d8eccSSepherosa Ziehau /* 41976c8d8eccSSepherosa Ziehau * Unmask the interrupt when we stop polling. 41986c8d8eccSSepherosa Ziehau */ 41996c8d8eccSSepherosa Ziehau PCI_CLRBIT(sc->bnx_dev, BGE_PCI_MISC_CTL, 42006c8d8eccSSepherosa Ziehau BGE_PCIMISCCTL_MASK_PCI_INTR, 4); 42016c8d8eccSSepherosa Ziehau 42026c8d8eccSSepherosa Ziehau /* 42036c8d8eccSSepherosa Ziehau * Trigger another interrupt, since above writing 42046c8d8eccSSepherosa Ziehau * to interrupt mailbox0 may acknowledge pending 42056c8d8eccSSepherosa Ziehau * interrupt. 42066c8d8eccSSepherosa Ziehau */ 42076c8d8eccSSepherosa Ziehau BNX_SETBIT(sc, BGE_MISC_LOCAL_CTL, BGE_MLC_INTR_SET); 4208df9ccc98SSepherosa Ziehau 4209df9ccc98SSepherosa Ziehau if (sc->bnx_flags & BNX_FLAG_STATUSTAG_BUG) { 4210df9ccc98SSepherosa Ziehau if (bootverbose) 4211df9ccc98SSepherosa Ziehau if_printf(ifp, "status tag bug workaround\n"); 4212df9ccc98SSepherosa Ziehau 4213f33ac8a4SSepherosa Ziehau for (i = 0; i < sc->bnx_intr_cnt; ++i) { 42144fa38985SSepherosa Ziehau intr = &sc->bnx_intr_data[i]; 4215f33ac8a4SSepherosa Ziehau intr->bnx_intr_maylose = FALSE; 4216f33ac8a4SSepherosa Ziehau intr->bnx_rx_check_considx = 0; 4217f33ac8a4SSepherosa Ziehau intr->bnx_tx_check_considx = 0; 4218f33ac8a4SSepherosa Ziehau callout_reset_bycpu(&intr->bnx_intr_timer, 4219f33ac8a4SSepherosa Ziehau BNX_INTR_CKINTVL, intr->bnx_intr_check, intr, 4220f33ac8a4SSepherosa Ziehau intr->bnx_intr_cpuid); 4221f33ac8a4SSepherosa Ziehau } 4222df9ccc98SSepherosa Ziehau } 42236c8d8eccSSepherosa Ziehau } 42246c8d8eccSSepherosa Ziehau 42256c8d8eccSSepherosa Ziehau static void 42266c8d8eccSSepherosa Ziehau bnx_disable_intr(struct bnx_softc *sc) 42276c8d8eccSSepherosa Ziehau { 4228f33ac8a4SSepherosa Ziehau int i; 4229f33ac8a4SSepherosa Ziehau 4230f33ac8a4SSepherosa Ziehau for (i = 0; i < sc->bnx_intr_cnt; ++i) { 4231f33ac8a4SSepherosa Ziehau struct bnx_intr_data *intr = &sc->bnx_intr_data[i]; 4232f33ac8a4SSepherosa Ziehau 4233f33ac8a4SSepherosa Ziehau callout_stop(&intr->bnx_intr_timer); 4234f33ac8a4SSepherosa Ziehau intr->bnx_intr_maylose = FALSE; 4235f33ac8a4SSepherosa Ziehau intr->bnx_rx_check_considx = 0; 4236f33ac8a4SSepherosa Ziehau intr->bnx_tx_check_considx = 0; 4237f33ac8a4SSepherosa Ziehau } 42386c8d8eccSSepherosa Ziehau 42396c8d8eccSSepherosa Ziehau /* 42406c8d8eccSSepherosa Ziehau * Mask the interrupt when we start polling. 42416c8d8eccSSepherosa Ziehau */ 42426c8d8eccSSepherosa Ziehau PCI_SETBIT(sc->bnx_dev, BGE_PCI_MISC_CTL, 42436c8d8eccSSepherosa Ziehau BGE_PCIMISCCTL_MASK_PCI_INTR, 4); 42446c8d8eccSSepherosa Ziehau 42456c8d8eccSSepherosa Ziehau /* 42466c8d8eccSSepherosa Ziehau * Acknowledge possible asserted interrupt. 42476c8d8eccSSepherosa Ziehau */ 42486c8d8eccSSepherosa Ziehau bnx_writembx(sc, BGE_MBX_IRQ0_LO, 1); 42496c8d8eccSSepherosa Ziehau 4250f33ac8a4SSepherosa Ziehau for (i = 0; i < sc->bnx_intr_cnt; ++i) { 4251f33ac8a4SSepherosa Ziehau lwkt_serialize_handler_disable( 4252f33ac8a4SSepherosa Ziehau sc->bnx_intr_data[i].bnx_intr_serialize); 4253f33ac8a4SSepherosa Ziehau } 42546c8d8eccSSepherosa Ziehau } 42556c8d8eccSSepherosa Ziehau 42566c8d8eccSSepherosa Ziehau static int 42576c8d8eccSSepherosa Ziehau bnx_get_eaddr_mem(struct bnx_softc *sc, uint8_t ether_addr[]) 42586c8d8eccSSepherosa Ziehau { 42596c8d8eccSSepherosa Ziehau uint32_t mac_addr; 42606c8d8eccSSepherosa Ziehau int ret = 1; 42616c8d8eccSSepherosa Ziehau 42626c8d8eccSSepherosa Ziehau mac_addr = bnx_readmem_ind(sc, 0x0c14); 42636c8d8eccSSepherosa Ziehau if ((mac_addr >> 16) == 0x484b) { 42646c8d8eccSSepherosa Ziehau ether_addr[0] = (uint8_t)(mac_addr >> 8); 42656c8d8eccSSepherosa Ziehau ether_addr[1] = (uint8_t)mac_addr; 42666c8d8eccSSepherosa Ziehau mac_addr = bnx_readmem_ind(sc, 0x0c18); 42676c8d8eccSSepherosa Ziehau ether_addr[2] = (uint8_t)(mac_addr >> 24); 42686c8d8eccSSepherosa Ziehau ether_addr[3] = (uint8_t)(mac_addr >> 16); 42696c8d8eccSSepherosa Ziehau ether_addr[4] = (uint8_t)(mac_addr >> 8); 42706c8d8eccSSepherosa Ziehau ether_addr[5] = (uint8_t)mac_addr; 42716c8d8eccSSepherosa Ziehau ret = 0; 42726c8d8eccSSepherosa Ziehau } 42736c8d8eccSSepherosa Ziehau return ret; 42746c8d8eccSSepherosa Ziehau } 42756c8d8eccSSepherosa Ziehau 42766c8d8eccSSepherosa Ziehau static int 42776c8d8eccSSepherosa Ziehau bnx_get_eaddr_nvram(struct bnx_softc *sc, uint8_t ether_addr[]) 42786c8d8eccSSepherosa Ziehau { 42796c8d8eccSSepherosa Ziehau int mac_offset = BGE_EE_MAC_OFFSET; 42806c8d8eccSSepherosa Ziehau 428180969639SSepherosa Ziehau if (BNX_IS_5717_PLUS(sc)) { 428280969639SSepherosa Ziehau int f; 428380969639SSepherosa Ziehau 428480969639SSepherosa Ziehau f = pci_get_function(sc->bnx_dev); 428580969639SSepherosa Ziehau if (f & 1) 428680969639SSepherosa Ziehau mac_offset = BGE_EE_MAC_OFFSET_5717; 428780969639SSepherosa Ziehau if (f > 1) 428880969639SSepherosa Ziehau mac_offset += BGE_EE_MAC_OFFSET_5717_OFF; 428980969639SSepherosa Ziehau } 42906c8d8eccSSepherosa Ziehau 42916c8d8eccSSepherosa Ziehau return bnx_read_nvram(sc, ether_addr, mac_offset + 2, ETHER_ADDR_LEN); 42926c8d8eccSSepherosa Ziehau } 42936c8d8eccSSepherosa Ziehau 42946c8d8eccSSepherosa Ziehau static int 42956c8d8eccSSepherosa Ziehau bnx_get_eaddr_eeprom(struct bnx_softc *sc, uint8_t ether_addr[]) 42966c8d8eccSSepherosa Ziehau { 42976c8d8eccSSepherosa Ziehau if (sc->bnx_flags & BNX_FLAG_NO_EEPROM) 42986c8d8eccSSepherosa Ziehau return 1; 42996c8d8eccSSepherosa Ziehau 43006c8d8eccSSepherosa Ziehau return bnx_read_eeprom(sc, ether_addr, BGE_EE_MAC_OFFSET + 2, 43016c8d8eccSSepherosa Ziehau ETHER_ADDR_LEN); 43026c8d8eccSSepherosa Ziehau } 43036c8d8eccSSepherosa Ziehau 43046c8d8eccSSepherosa Ziehau static int 43056c8d8eccSSepherosa Ziehau bnx_get_eaddr(struct bnx_softc *sc, uint8_t eaddr[]) 43066c8d8eccSSepherosa Ziehau { 43076c8d8eccSSepherosa Ziehau static const bnx_eaddr_fcn_t bnx_eaddr_funcs[] = { 43086c8d8eccSSepherosa Ziehau /* NOTE: Order is critical */ 43096c8d8eccSSepherosa Ziehau bnx_get_eaddr_mem, 43106c8d8eccSSepherosa Ziehau bnx_get_eaddr_nvram, 43116c8d8eccSSepherosa Ziehau bnx_get_eaddr_eeprom, 43126c8d8eccSSepherosa Ziehau NULL 43136c8d8eccSSepherosa Ziehau }; 43146c8d8eccSSepherosa Ziehau const bnx_eaddr_fcn_t *func; 43156c8d8eccSSepherosa Ziehau 43166c8d8eccSSepherosa Ziehau for (func = bnx_eaddr_funcs; *func != NULL; ++func) { 43176c8d8eccSSepherosa Ziehau if ((*func)(sc, eaddr) == 0) 43186c8d8eccSSepherosa Ziehau break; 43196c8d8eccSSepherosa Ziehau } 43206c8d8eccSSepherosa Ziehau return (*func == NULL ? ENXIO : 0); 43216c8d8eccSSepherosa Ziehau } 43226c8d8eccSSepherosa Ziehau 43236c8d8eccSSepherosa Ziehau /* 43246c8d8eccSSepherosa Ziehau * NOTE: 'm' is not freed upon failure 43256c8d8eccSSepherosa Ziehau */ 43266c8d8eccSSepherosa Ziehau struct mbuf * 43276c8d8eccSSepherosa Ziehau bnx_defrag_shortdma(struct mbuf *m) 43286c8d8eccSSepherosa Ziehau { 43296c8d8eccSSepherosa Ziehau struct mbuf *n; 43306c8d8eccSSepherosa Ziehau int found; 43316c8d8eccSSepherosa Ziehau 43326c8d8eccSSepherosa Ziehau /* 43336c8d8eccSSepherosa Ziehau * If device receive two back-to-back send BDs with less than 43346c8d8eccSSepherosa Ziehau * or equal to 8 total bytes then the device may hang. The two 43356c8d8eccSSepherosa Ziehau * back-to-back send BDs must in the same frame for this failure 43366c8d8eccSSepherosa Ziehau * to occur. Scan mbuf chains and see whether two back-to-back 43376c8d8eccSSepherosa Ziehau * send BDs are there. If this is the case, allocate new mbuf 43386c8d8eccSSepherosa Ziehau * and copy the frame to workaround the silicon bug. 43396c8d8eccSSepherosa Ziehau */ 43406c8d8eccSSepherosa Ziehau for (n = m, found = 0; n != NULL; n = n->m_next) { 43416c8d8eccSSepherosa Ziehau if (n->m_len < 8) { 43426c8d8eccSSepherosa Ziehau found++; 43436c8d8eccSSepherosa Ziehau if (found > 1) 43446c8d8eccSSepherosa Ziehau break; 43456c8d8eccSSepherosa Ziehau continue; 43466c8d8eccSSepherosa Ziehau } 43476c8d8eccSSepherosa Ziehau found = 0; 43486c8d8eccSSepherosa Ziehau } 43496c8d8eccSSepherosa Ziehau 43506c8d8eccSSepherosa Ziehau if (found > 1) 43516c8d8eccSSepherosa Ziehau n = m_defrag(m, MB_DONTWAIT); 43526c8d8eccSSepherosa Ziehau else 43536c8d8eccSSepherosa Ziehau n = m; 43546c8d8eccSSepherosa Ziehau return n; 43556c8d8eccSSepherosa Ziehau } 43566c8d8eccSSepherosa Ziehau 43576c8d8eccSSepherosa Ziehau static void 43586c8d8eccSSepherosa Ziehau bnx_stop_block(struct bnx_softc *sc, bus_size_t reg, uint32_t bit) 43596c8d8eccSSepherosa Ziehau { 43606c8d8eccSSepherosa Ziehau int i; 43616c8d8eccSSepherosa Ziehau 43626c8d8eccSSepherosa Ziehau BNX_CLRBIT(sc, reg, bit); 43636c8d8eccSSepherosa Ziehau for (i = 0; i < BNX_TIMEOUT; i++) { 43646c8d8eccSSepherosa Ziehau if ((CSR_READ_4(sc, reg) & bit) == 0) 43656c8d8eccSSepherosa Ziehau return; 43666c8d8eccSSepherosa Ziehau DELAY(100); 43676c8d8eccSSepherosa Ziehau } 43686c8d8eccSSepherosa Ziehau } 43696c8d8eccSSepherosa Ziehau 43706c8d8eccSSepherosa Ziehau static void 43716c8d8eccSSepherosa Ziehau bnx_link_poll(struct bnx_softc *sc) 43726c8d8eccSSepherosa Ziehau { 43736c8d8eccSSepherosa Ziehau uint32_t status; 43746c8d8eccSSepherosa Ziehau 43756c8d8eccSSepherosa Ziehau status = CSR_READ_4(sc, BGE_MAC_STS); 43766c8d8eccSSepherosa Ziehau if ((status & sc->bnx_link_chg) || sc->bnx_link_evt) { 43776c8d8eccSSepherosa Ziehau sc->bnx_link_evt = 0; 43786c8d8eccSSepherosa Ziehau sc->bnx_link_upd(sc, status); 43796c8d8eccSSepherosa Ziehau } 43806c8d8eccSSepherosa Ziehau } 43816c8d8eccSSepherosa Ziehau 43826c8d8eccSSepherosa Ziehau static void 43836c8d8eccSSepherosa Ziehau bnx_enable_msi(struct bnx_softc *sc) 43846c8d8eccSSepherosa Ziehau { 43856c8d8eccSSepherosa Ziehau uint32_t msi_mode; 43866c8d8eccSSepherosa Ziehau 43876c8d8eccSSepherosa Ziehau msi_mode = CSR_READ_4(sc, BGE_MSI_MODE); 43886c8d8eccSSepherosa Ziehau msi_mode |= BGE_MSIMODE_ENABLE; 43896c8d8eccSSepherosa Ziehau if (sc->bnx_flags & BNX_FLAG_ONESHOT_MSI) { 43906c8d8eccSSepherosa Ziehau /* 43916c8d8eccSSepherosa Ziehau * NOTE: 43926c8d8eccSSepherosa Ziehau * 5718-PG105-R says that "one shot" mode 43936c8d8eccSSepherosa Ziehau * does not work if MSI is used, however, 43946c8d8eccSSepherosa Ziehau * it obviously works. 43956c8d8eccSSepherosa Ziehau */ 43966c8d8eccSSepherosa Ziehau msi_mode &= ~BGE_MSIMODE_ONESHOT_DISABLE; 43976c8d8eccSSepherosa Ziehau } 43986c8d8eccSSepherosa Ziehau CSR_WRITE_4(sc, BGE_MSI_MODE, msi_mode); 43996c8d8eccSSepherosa Ziehau } 44006c8d8eccSSepherosa Ziehau 44016c8d8eccSSepherosa Ziehau static uint32_t 44026c8d8eccSSepherosa Ziehau bnx_dma_swap_options(struct bnx_softc *sc) 44036c8d8eccSSepherosa Ziehau { 44046c8d8eccSSepherosa Ziehau uint32_t dma_options; 44056c8d8eccSSepherosa Ziehau 44066c8d8eccSSepherosa Ziehau dma_options = BGE_MODECTL_WORDSWAP_NONFRAME | 44076c8d8eccSSepherosa Ziehau BGE_MODECTL_BYTESWAP_DATA | BGE_MODECTL_WORDSWAP_DATA; 44086c8d8eccSSepherosa Ziehau #if BYTE_ORDER == BIG_ENDIAN 44096c8d8eccSSepherosa Ziehau dma_options |= BGE_MODECTL_BYTESWAP_NONFRAME; 44106c8d8eccSSepherosa Ziehau #endif 4411b96cbbb6SSepherosa Ziehau if (sc->bnx_asicrev == BGE_ASICREV_BCM5720 || 4412b96cbbb6SSepherosa Ziehau sc->bnx_asicrev == BGE_ASICREV_BCM5762) { 44136c8d8eccSSepherosa Ziehau dma_options |= BGE_MODECTL_BYTESWAP_B2HRX_DATA | 44146c8d8eccSSepherosa Ziehau BGE_MODECTL_WORDSWAP_B2HRX_DATA | BGE_MODECTL_B2HRX_ENABLE | 44156c8d8eccSSepherosa Ziehau BGE_MODECTL_HTX2B_ENABLE; 44166c8d8eccSSepherosa Ziehau } 44176c8d8eccSSepherosa Ziehau return dma_options; 44186c8d8eccSSepherosa Ziehau } 441966deb1c1SSepherosa Ziehau 442066deb1c1SSepherosa Ziehau static int 442133a04907SSepherosa Ziehau bnx_setup_tso(struct bnx_tx_ring *txr, struct mbuf **mp, 442266deb1c1SSepherosa Ziehau uint16_t *mss0, uint16_t *flags0) 442366deb1c1SSepherosa Ziehau { 442466deb1c1SSepherosa Ziehau struct mbuf *m; 442566deb1c1SSepherosa Ziehau struct ip *ip; 442666deb1c1SSepherosa Ziehau struct tcphdr *th; 442766deb1c1SSepherosa Ziehau int thoff, iphlen, hoff, hlen; 442866deb1c1SSepherosa Ziehau uint16_t flags, mss; 442966deb1c1SSepherosa Ziehau 4430f7a2269aSSepherosa Ziehau m = *mp; 4431f7a2269aSSepherosa Ziehau KASSERT(M_WRITABLE(m), ("TSO mbuf not writable")); 4432f7a2269aSSepherosa Ziehau 4433f7a2269aSSepherosa Ziehau hoff = m->m_pkthdr.csum_lhlen; 4434f7a2269aSSepherosa Ziehau iphlen = m->m_pkthdr.csum_iphlen; 4435f7a2269aSSepherosa Ziehau thoff = m->m_pkthdr.csum_thlen; 4436f7a2269aSSepherosa Ziehau 4437f7a2269aSSepherosa Ziehau KASSERT(hoff > 0, ("invalid ether header len")); 4438f7a2269aSSepherosa Ziehau KASSERT(iphlen > 0, ("invalid ip header len")); 4439f7a2269aSSepherosa Ziehau KASSERT(thoff > 0, ("invalid tcp header len")); 4440f7a2269aSSepherosa Ziehau 4441f7a2269aSSepherosa Ziehau if (__predict_false(m->m_len < hoff + iphlen + thoff)) { 4442f7a2269aSSepherosa Ziehau m = m_pullup(m, hoff + iphlen + thoff); 4443f7a2269aSSepherosa Ziehau if (m == NULL) { 4444f7a2269aSSepherosa Ziehau *mp = NULL; 4445f7a2269aSSepherosa Ziehau return ENOBUFS; 4446f7a2269aSSepherosa Ziehau } 4447f7a2269aSSepherosa Ziehau *mp = m; 4448f7a2269aSSepherosa Ziehau } 4449f7a2269aSSepherosa Ziehau ip = mtodoff(m, struct ip *, hoff); 4450f7a2269aSSepherosa Ziehau th = mtodoff(m, struct tcphdr *, hoff + iphlen); 4451f7a2269aSSepherosa Ziehau 4452f0336d39SSepherosa Ziehau mss = m->m_pkthdr.tso_segsz; 445366deb1c1SSepherosa Ziehau flags = BGE_TXBDFLAG_CPU_PRE_DMA | BGE_TXBDFLAG_CPU_POST_DMA; 445466deb1c1SSepherosa Ziehau 445566deb1c1SSepherosa Ziehau ip->ip_len = htons(mss + iphlen + thoff); 445666deb1c1SSepherosa Ziehau th->th_sum = 0; 445766deb1c1SSepherosa Ziehau 445866deb1c1SSepherosa Ziehau hlen = (iphlen + thoff) >> 2; 445966deb1c1SSepherosa Ziehau mss |= ((hlen & 0x3) << 14); 446066deb1c1SSepherosa Ziehau flags |= ((hlen & 0xf8) << 7) | ((hlen & 0x4) << 2); 446166deb1c1SSepherosa Ziehau 446266deb1c1SSepherosa Ziehau *mss0 = mss; 446366deb1c1SSepherosa Ziehau *flags0 = flags; 446466deb1c1SSepherosa Ziehau 446566deb1c1SSepherosa Ziehau return 0; 446666deb1c1SSepherosa Ziehau } 446733a04907SSepherosa Ziehau 446833a04907SSepherosa Ziehau static int 446933a04907SSepherosa Ziehau bnx_create_tx_ring(struct bnx_tx_ring *txr) 447033a04907SSepherosa Ziehau { 447133a04907SSepherosa Ziehau bus_size_t txmaxsz, txmaxsegsz; 447233a04907SSepherosa Ziehau int i, error; 447333a04907SSepherosa Ziehau 4474329f9016SSepherosa Ziehau lwkt_serialize_init(&txr->bnx_tx_serialize); 4475329f9016SSepherosa Ziehau 447633a04907SSepherosa Ziehau /* 447733a04907SSepherosa Ziehau * Create DMA tag and maps for TX mbufs. 447833a04907SSepherosa Ziehau */ 447933a04907SSepherosa Ziehau if (txr->bnx_sc->bnx_flags & BNX_FLAG_TSO) 448033a04907SSepherosa Ziehau txmaxsz = IP_MAXPACKET + sizeof(struct ether_vlan_header); 448133a04907SSepherosa Ziehau else 448233a04907SSepherosa Ziehau txmaxsz = BNX_JUMBO_FRAMELEN; 448333a04907SSepherosa Ziehau if (txr->bnx_sc->bnx_asicrev == BGE_ASICREV_BCM57766) 448433a04907SSepherosa Ziehau txmaxsegsz = MCLBYTES; 448533a04907SSepherosa Ziehau else 448633a04907SSepherosa Ziehau txmaxsegsz = PAGE_SIZE; 448733a04907SSepherosa Ziehau error = bus_dma_tag_create(txr->bnx_sc->bnx_cdata.bnx_parent_tag, 448833a04907SSepherosa Ziehau 1, 0, BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL, NULL, 448933a04907SSepherosa Ziehau txmaxsz, BNX_NSEG_NEW, txmaxsegsz, 449033a04907SSepherosa Ziehau BUS_DMA_ALLOCNOW | BUS_DMA_WAITOK | BUS_DMA_ONEBPAGE, 449133a04907SSepherosa Ziehau &txr->bnx_tx_mtag); 449233a04907SSepherosa Ziehau if (error) { 449333a04907SSepherosa Ziehau device_printf(txr->bnx_sc->bnx_dev, 4494beedf5beSSepherosa Ziehau "could not create TX mbuf DMA tag\n"); 449533a04907SSepherosa Ziehau return error; 449633a04907SSepherosa Ziehau } 449733a04907SSepherosa Ziehau 449833a04907SSepherosa Ziehau for (i = 0; i < BGE_TX_RING_CNT; i++) { 449933a04907SSepherosa Ziehau error = bus_dmamap_create(txr->bnx_tx_mtag, 450033a04907SSepherosa Ziehau BUS_DMA_WAITOK | BUS_DMA_ONEBPAGE, 4501fa4b1067SSepherosa Ziehau &txr->bnx_tx_buf[i].bnx_tx_dmamap); 450233a04907SSepherosa Ziehau if (error) { 450333a04907SSepherosa Ziehau int j; 450433a04907SSepherosa Ziehau 450533a04907SSepherosa Ziehau for (j = 0; j < i; ++j) { 450633a04907SSepherosa Ziehau bus_dmamap_destroy(txr->bnx_tx_mtag, 4507fa4b1067SSepherosa Ziehau txr->bnx_tx_buf[j].bnx_tx_dmamap); 450833a04907SSepherosa Ziehau } 450933a04907SSepherosa Ziehau bus_dma_tag_destroy(txr->bnx_tx_mtag); 451033a04907SSepherosa Ziehau txr->bnx_tx_mtag = NULL; 451133a04907SSepherosa Ziehau 451233a04907SSepherosa Ziehau device_printf(txr->bnx_sc->bnx_dev, 4513beedf5beSSepherosa Ziehau "could not create TX mbuf DMA map\n"); 451433a04907SSepherosa Ziehau return error; 451533a04907SSepherosa Ziehau } 451633a04907SSepherosa Ziehau } 451733a04907SSepherosa Ziehau 451833a04907SSepherosa Ziehau /* 451933a04907SSepherosa Ziehau * Create DMA stuffs for TX ring. 452033a04907SSepherosa Ziehau */ 452133a04907SSepherosa Ziehau error = bnx_dma_block_alloc(txr->bnx_sc, BGE_TX_RING_SZ, 4522beedf5beSSepherosa Ziehau &txr->bnx_tx_ring_tag, 4523beedf5beSSepherosa Ziehau &txr->bnx_tx_ring_map, 4524beedf5beSSepherosa Ziehau (void *)&txr->bnx_tx_ring, 4525beedf5beSSepherosa Ziehau &txr->bnx_tx_ring_paddr); 452633a04907SSepherosa Ziehau if (error) { 452733a04907SSepherosa Ziehau device_printf(txr->bnx_sc->bnx_dev, 452833a04907SSepherosa Ziehau "could not create TX ring\n"); 452933a04907SSepherosa Ziehau return error; 453033a04907SSepherosa Ziehau } 453133a04907SSepherosa Ziehau 453279a64343SSepherosa Ziehau txr->bnx_tx_flags |= BNX_TX_FLAG_SHORTDMA; 453333a04907SSepherosa Ziehau txr->bnx_tx_wreg = BNX_TX_WREG_NSEGS; 453433a04907SSepherosa Ziehau 453533a04907SSepherosa Ziehau return 0; 453633a04907SSepherosa Ziehau } 453733a04907SSepherosa Ziehau 453833a04907SSepherosa Ziehau static void 453933a04907SSepherosa Ziehau bnx_destroy_tx_ring(struct bnx_tx_ring *txr) 454033a04907SSepherosa Ziehau { 454133a04907SSepherosa Ziehau /* Destroy TX mbuf DMA stuffs. */ 454233a04907SSepherosa Ziehau if (txr->bnx_tx_mtag != NULL) { 454333a04907SSepherosa Ziehau int i; 454433a04907SSepherosa Ziehau 454533a04907SSepherosa Ziehau for (i = 0; i < BGE_TX_RING_CNT; i++) { 4546fa4b1067SSepherosa Ziehau KKASSERT(txr->bnx_tx_buf[i].bnx_tx_mbuf == NULL); 454733a04907SSepherosa Ziehau bus_dmamap_destroy(txr->bnx_tx_mtag, 4548fa4b1067SSepherosa Ziehau txr->bnx_tx_buf[i].bnx_tx_dmamap); 454933a04907SSepherosa Ziehau } 455033a04907SSepherosa Ziehau bus_dma_tag_destroy(txr->bnx_tx_mtag); 455133a04907SSepherosa Ziehau } 455233a04907SSepherosa Ziehau 455333a04907SSepherosa Ziehau /* Destroy TX ring */ 455433a04907SSepherosa Ziehau bnx_dma_block_free(txr->bnx_tx_ring_tag, 455533a04907SSepherosa Ziehau txr->bnx_tx_ring_map, txr->bnx_tx_ring); 455633a04907SSepherosa Ziehau } 4557aad4de2bSSepherosa Ziehau 4558aad4de2bSSepherosa Ziehau static int 4559aad4de2bSSepherosa Ziehau bnx_sysctl_force_defrag(SYSCTL_HANDLER_ARGS) 4560aad4de2bSSepherosa Ziehau { 4561aad4de2bSSepherosa Ziehau struct bnx_softc *sc = (void *)arg1; 4562aad4de2bSSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if; 4563aad4de2bSSepherosa Ziehau struct bnx_tx_ring *txr = &sc->bnx_tx_ring[0]; 4564aad4de2bSSepherosa Ziehau int error, defrag, i; 4565aad4de2bSSepherosa Ziehau 4566aad4de2bSSepherosa Ziehau if (txr->bnx_tx_flags & BNX_TX_FLAG_FORCE_DEFRAG) 4567aad4de2bSSepherosa Ziehau defrag = 1; 4568aad4de2bSSepherosa Ziehau else 4569aad4de2bSSepherosa Ziehau defrag = 0; 4570aad4de2bSSepherosa Ziehau 4571aad4de2bSSepherosa Ziehau error = sysctl_handle_int(oidp, &defrag, 0, req); 4572aad4de2bSSepherosa Ziehau if (error || req->newptr == NULL) 4573aad4de2bSSepherosa Ziehau return error; 4574aad4de2bSSepherosa Ziehau 4575329f9016SSepherosa Ziehau ifnet_serialize_all(ifp); 4576aad4de2bSSepherosa Ziehau for (i = 0; i < sc->bnx_tx_ringcnt; ++i) { 4577aad4de2bSSepherosa Ziehau txr = &sc->bnx_tx_ring[i]; 4578aad4de2bSSepherosa Ziehau if (defrag) 4579aad4de2bSSepherosa Ziehau txr->bnx_tx_flags |= BNX_TX_FLAG_FORCE_DEFRAG; 4580aad4de2bSSepherosa Ziehau else 4581aad4de2bSSepherosa Ziehau txr->bnx_tx_flags &= ~BNX_TX_FLAG_FORCE_DEFRAG; 4582aad4de2bSSepherosa Ziehau } 4583329f9016SSepherosa Ziehau ifnet_deserialize_all(ifp); 4584aad4de2bSSepherosa Ziehau 4585aad4de2bSSepherosa Ziehau return 0; 4586aad4de2bSSepherosa Ziehau } 4587472c99c8SSepherosa Ziehau 4588472c99c8SSepherosa Ziehau static int 4589472c99c8SSepherosa Ziehau bnx_sysctl_tx_wreg(SYSCTL_HANDLER_ARGS) 4590472c99c8SSepherosa Ziehau { 4591472c99c8SSepherosa Ziehau struct bnx_softc *sc = (void *)arg1; 4592472c99c8SSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if; 4593472c99c8SSepherosa Ziehau struct bnx_tx_ring *txr = &sc->bnx_tx_ring[0]; 4594472c99c8SSepherosa Ziehau int error, tx_wreg, i; 4595472c99c8SSepherosa Ziehau 4596472c99c8SSepherosa Ziehau tx_wreg = txr->bnx_tx_wreg; 4597472c99c8SSepherosa Ziehau error = sysctl_handle_int(oidp, &tx_wreg, 0, req); 4598472c99c8SSepherosa Ziehau if (error || req->newptr == NULL) 4599472c99c8SSepherosa Ziehau return error; 4600472c99c8SSepherosa Ziehau 4601329f9016SSepherosa Ziehau ifnet_serialize_all(ifp); 4602472c99c8SSepherosa Ziehau for (i = 0; i < sc->bnx_tx_ringcnt; ++i) 4603472c99c8SSepherosa Ziehau sc->bnx_tx_ring[i].bnx_tx_wreg = tx_wreg; 4604329f9016SSepherosa Ziehau ifnet_deserialize_all(ifp); 4605472c99c8SSepherosa Ziehau 4606472c99c8SSepherosa Ziehau return 0; 4607472c99c8SSepherosa Ziehau } 4608beedf5beSSepherosa Ziehau 4609beedf5beSSepherosa Ziehau static int 4610beedf5beSSepherosa Ziehau bnx_create_rx_ret_ring(struct bnx_rx_ret_ring *ret) 4611beedf5beSSepherosa Ziehau { 4612beedf5beSSepherosa Ziehau int error; 4613beedf5beSSepherosa Ziehau 4614329f9016SSepherosa Ziehau lwkt_serialize_init(&ret->bnx_rx_ret_serialize); 4615329f9016SSepherosa Ziehau 4616beedf5beSSepherosa Ziehau /* 4617beedf5beSSepherosa Ziehau * Create DMA stuffs for RX return ring. 4618beedf5beSSepherosa Ziehau */ 4619beedf5beSSepherosa Ziehau error = bnx_dma_block_alloc(ret->bnx_sc, 4620beedf5beSSepherosa Ziehau BGE_RX_RTN_RING_SZ(BNX_RETURN_RING_CNT), 4621beedf5beSSepherosa Ziehau &ret->bnx_rx_ret_ring_tag, 4622beedf5beSSepherosa Ziehau &ret->bnx_rx_ret_ring_map, 4623beedf5beSSepherosa Ziehau (void *)&ret->bnx_rx_ret_ring, 4624beedf5beSSepherosa Ziehau &ret->bnx_rx_ret_ring_paddr); 4625beedf5beSSepherosa Ziehau if (error) { 4626beedf5beSSepherosa Ziehau device_printf(ret->bnx_sc->bnx_dev, 4627beedf5beSSepherosa Ziehau "could not create RX ret ring\n"); 4628beedf5beSSepherosa Ziehau return error; 4629beedf5beSSepherosa Ziehau } 4630beedf5beSSepherosa Ziehau 4631beedf5beSSepherosa Ziehau /* Shadow standard ring's RX mbuf DMA tag */ 4632beedf5beSSepherosa Ziehau ret->bnx_rx_mtag = ret->bnx_std->bnx_rx_mtag; 4633beedf5beSSepherosa Ziehau 4634beedf5beSSepherosa Ziehau /* 4635beedf5beSSepherosa Ziehau * Create tmp DMA map for RX mbufs. 4636beedf5beSSepherosa Ziehau */ 4637beedf5beSSepherosa Ziehau error = bus_dmamap_create(ret->bnx_rx_mtag, BUS_DMA_WAITOK, 4638beedf5beSSepherosa Ziehau &ret->bnx_rx_tmpmap); 4639beedf5beSSepherosa Ziehau if (error) { 4640beedf5beSSepherosa Ziehau device_printf(ret->bnx_sc->bnx_dev, 4641beedf5beSSepherosa Ziehau "could not create tmp RX mbuf DMA map\n"); 4642beedf5beSSepherosa Ziehau ret->bnx_rx_mtag = NULL; 4643beedf5beSSepherosa Ziehau return error; 4644beedf5beSSepherosa Ziehau } 4645beedf5beSSepherosa Ziehau return 0; 4646beedf5beSSepherosa Ziehau } 4647beedf5beSSepherosa Ziehau 4648beedf5beSSepherosa Ziehau static void 4649beedf5beSSepherosa Ziehau bnx_destroy_rx_ret_ring(struct bnx_rx_ret_ring *ret) 4650beedf5beSSepherosa Ziehau { 4651beedf5beSSepherosa Ziehau /* Destroy tmp RX mbuf DMA map */ 4652beedf5beSSepherosa Ziehau if (ret->bnx_rx_mtag != NULL) 4653beedf5beSSepherosa Ziehau bus_dmamap_destroy(ret->bnx_rx_mtag, ret->bnx_rx_tmpmap); 4654beedf5beSSepherosa Ziehau 4655beedf5beSSepherosa Ziehau /* Destroy RX return ring */ 4656beedf5beSSepherosa Ziehau bnx_dma_block_free(ret->bnx_rx_ret_ring_tag, 4657beedf5beSSepherosa Ziehau ret->bnx_rx_ret_ring_map, ret->bnx_rx_ret_ring); 4658beedf5beSSepherosa Ziehau } 46590c7da01dSSepherosa Ziehau 46600c7da01dSSepherosa Ziehau static int 46610c7da01dSSepherosa Ziehau bnx_alloc_intr(struct bnx_softc *sc) 46620c7da01dSSepherosa Ziehau { 4663f33ac8a4SSepherosa Ziehau struct bnx_intr_data *intr; 46640c7da01dSSepherosa Ziehau u_int intr_flags; 46650c7da01dSSepherosa Ziehau 4666*0a806e3aSSepherosa Ziehau KKASSERT(sc->bnx_intr_cnt == 1); 46670c7da01dSSepherosa Ziehau 4668f33ac8a4SSepherosa Ziehau intr = &sc->bnx_intr_data[0]; 4669f33ac8a4SSepherosa Ziehau intr->bnx_sc = sc; 4670f33ac8a4SSepherosa Ziehau intr->bnx_ret = &sc->bnx_rx_ret_ring[0]; 4671f33ac8a4SSepherosa Ziehau intr->bnx_txr = &sc->bnx_tx_ring[0]; 4672f33ac8a4SSepherosa Ziehau intr->bnx_intr_serialize = &sc->bnx_main_serialize; 4673f33ac8a4SSepherosa Ziehau callout_init_mp(&intr->bnx_intr_timer); 4674f33ac8a4SSepherosa Ziehau intr->bnx_intr_check = bnx_check_intr; 46754fa38985SSepherosa Ziehau intr->bnx_saved_status_tag = &intr->bnx_ret->bnx_saved_status_tag; 4676f33ac8a4SSepherosa Ziehau 4677f33ac8a4SSepherosa Ziehau sc->bnx_intr_type = pci_alloc_1intr(sc->bnx_dev, bnx_msi_enable, 4678f33ac8a4SSepherosa Ziehau &intr->bnx_intr_rid, &intr_flags); 4679f33ac8a4SSepherosa Ziehau 4680f33ac8a4SSepherosa Ziehau intr->bnx_intr_res = bus_alloc_resource_any(sc->bnx_dev, SYS_RES_IRQ, 4681f33ac8a4SSepherosa Ziehau &intr->bnx_intr_rid, intr_flags); 4682f33ac8a4SSepherosa Ziehau if (intr->bnx_intr_res == NULL) { 46830c7da01dSSepherosa Ziehau device_printf(sc->bnx_dev, "could not alloc interrupt\n"); 46840c7da01dSSepherosa Ziehau return ENXIO; 46850c7da01dSSepherosa Ziehau } 46860c7da01dSSepherosa Ziehau 4687f33ac8a4SSepherosa Ziehau if (sc->bnx_intr_type == PCI_INTR_TYPE_MSI) { 46880c7da01dSSepherosa Ziehau sc->bnx_flags |= BNX_FLAG_ONESHOT_MSI; 46890c7da01dSSepherosa Ziehau bnx_enable_msi(sc); 4690f33ac8a4SSepherosa Ziehau 4691f33ac8a4SSepherosa Ziehau if (sc->bnx_flags & BNX_FLAG_ONESHOT_MSI) { 4692f33ac8a4SSepherosa Ziehau intr->bnx_intr_func = bnx_msi_oneshot; 4693f33ac8a4SSepherosa Ziehau if (bootverbose) 4694f33ac8a4SSepherosa Ziehau device_printf(sc->bnx_dev, "oneshot MSI\n"); 4695f33ac8a4SSepherosa Ziehau } else { 4696f33ac8a4SSepherosa Ziehau intr->bnx_intr_func = bnx_msi; 46970c7da01dSSepherosa Ziehau } 4698f33ac8a4SSepherosa Ziehau } else { 4699f33ac8a4SSepherosa Ziehau intr->bnx_intr_func = bnx_intr_legacy; 4700f33ac8a4SSepherosa Ziehau } 4701f33ac8a4SSepherosa Ziehau intr->bnx_intr_arg = sc; 4702f33ac8a4SSepherosa Ziehau intr->bnx_intr_cpuid = rman_get_cpuid(intr->bnx_intr_res); 4703f33ac8a4SSepherosa Ziehau 4704f33ac8a4SSepherosa Ziehau intr->bnx_txr->bnx_tx_cpuid = intr->bnx_intr_cpuid; 4705f33ac8a4SSepherosa Ziehau 47060c7da01dSSepherosa Ziehau return 0; 47070c7da01dSSepherosa Ziehau } 47080c7da01dSSepherosa Ziehau 47090c7da01dSSepherosa Ziehau static int 47100c7da01dSSepherosa Ziehau bnx_setup_intr(struct bnx_softc *sc) 47110c7da01dSSepherosa Ziehau { 4712f33ac8a4SSepherosa Ziehau int error, i; 47130c7da01dSSepherosa Ziehau 4714f33ac8a4SSepherosa Ziehau for (i = 0; i < sc->bnx_intr_cnt; ++i) { 4715f33ac8a4SSepherosa Ziehau struct bnx_intr_data *intr = &sc->bnx_intr_data[i]; 4716f33ac8a4SSepherosa Ziehau 4717f33ac8a4SSepherosa Ziehau error = bus_setup_intr_descr(sc->bnx_dev, intr->bnx_intr_res, 4718f33ac8a4SSepherosa Ziehau INTR_MPSAFE, intr->bnx_intr_func, intr->bnx_intr_arg, 4719f33ac8a4SSepherosa Ziehau &intr->bnx_intr_hand, intr->bnx_intr_serialize, 4720f33ac8a4SSepherosa Ziehau intr->bnx_intr_desc); 47210c7da01dSSepherosa Ziehau if (error) { 4722f33ac8a4SSepherosa Ziehau device_printf(sc->bnx_dev, 4723f33ac8a4SSepherosa Ziehau "could not set up %dth intr\n", i); 4724f33ac8a4SSepherosa Ziehau bnx_teardown_intr(sc, i); 47250c7da01dSSepherosa Ziehau return error; 47260c7da01dSSepherosa Ziehau } 4727f33ac8a4SSepherosa Ziehau } 47280c7da01dSSepherosa Ziehau return 0; 47290c7da01dSSepherosa Ziehau } 47300c7da01dSSepherosa Ziehau 47310c7da01dSSepherosa Ziehau static void 4732f33ac8a4SSepherosa Ziehau bnx_teardown_intr(struct bnx_softc *sc, int cnt) 4733f33ac8a4SSepherosa Ziehau { 4734f33ac8a4SSepherosa Ziehau int i; 4735f33ac8a4SSepherosa Ziehau 4736f33ac8a4SSepherosa Ziehau for (i = 0; i < cnt; ++i) { 4737f33ac8a4SSepherosa Ziehau struct bnx_intr_data *intr = &sc->bnx_intr_data[i]; 4738f33ac8a4SSepherosa Ziehau 4739f33ac8a4SSepherosa Ziehau bus_teardown_intr(sc->bnx_dev, intr->bnx_intr_res, 4740f33ac8a4SSepherosa Ziehau intr->bnx_intr_hand); 4741f33ac8a4SSepherosa Ziehau } 4742f33ac8a4SSepherosa Ziehau } 4743f33ac8a4SSepherosa Ziehau 4744f33ac8a4SSepherosa Ziehau static void 47450c7da01dSSepherosa Ziehau bnx_free_intr(struct bnx_softc *sc) 47460c7da01dSSepherosa Ziehau { 4747f33ac8a4SSepherosa Ziehau struct bnx_intr_data *intr; 4748f33ac8a4SSepherosa Ziehau 4749f33ac8a4SSepherosa Ziehau KKASSERT(sc->bnx_intr_cnt <= 1); 4750f33ac8a4SSepherosa Ziehau intr = &sc->bnx_intr_data[0]; 4751f33ac8a4SSepherosa Ziehau 4752f33ac8a4SSepherosa Ziehau if (intr->bnx_intr_res != NULL) { 47530c7da01dSSepherosa Ziehau bus_release_resource(sc->bnx_dev, SYS_RES_IRQ, 4754f33ac8a4SSepherosa Ziehau intr->bnx_intr_rid, intr->bnx_intr_res); 47550c7da01dSSepherosa Ziehau } 4756f33ac8a4SSepherosa Ziehau if (sc->bnx_intr_type == PCI_INTR_TYPE_MSI) 47570c7da01dSSepherosa Ziehau pci_release_msi(sc->bnx_dev); 47580c7da01dSSepherosa Ziehau } 4759329f9016SSepherosa Ziehau 4760329f9016SSepherosa Ziehau static void 4761329f9016SSepherosa Ziehau bnx_setup_serialize(struct bnx_softc *sc) 4762329f9016SSepherosa Ziehau { 4763329f9016SSepherosa Ziehau int i, j; 4764329f9016SSepherosa Ziehau 4765329f9016SSepherosa Ziehau /* 4766329f9016SSepherosa Ziehau * Allocate serializer array 4767329f9016SSepherosa Ziehau */ 4768329f9016SSepherosa Ziehau 4769329f9016SSepherosa Ziehau /* Main + RX STD + TX + RX RET */ 4770329f9016SSepherosa Ziehau sc->bnx_serialize_cnt = 1 + 1 + sc->bnx_tx_ringcnt + sc->bnx_rx_retcnt; 4771329f9016SSepherosa Ziehau 4772329f9016SSepherosa Ziehau sc->bnx_serialize = 4773329f9016SSepherosa Ziehau kmalloc(sc->bnx_serialize_cnt * sizeof(struct lwkt_serialize *), 4774329f9016SSepherosa Ziehau M_DEVBUF, M_WAITOK | M_ZERO); 4775329f9016SSepherosa Ziehau 4776329f9016SSepherosa Ziehau /* 4777329f9016SSepherosa Ziehau * Setup serializers 4778329f9016SSepherosa Ziehau * 4779329f9016SSepherosa Ziehau * NOTE: Order is critical 4780329f9016SSepherosa Ziehau */ 4781329f9016SSepherosa Ziehau 4782329f9016SSepherosa Ziehau i = 0; 4783329f9016SSepherosa Ziehau 4784329f9016SSepherosa Ziehau KKASSERT(i < sc->bnx_serialize_cnt); 4785329f9016SSepherosa Ziehau sc->bnx_serialize[i++] = &sc->bnx_main_serialize; 4786329f9016SSepherosa Ziehau 4787329f9016SSepherosa Ziehau KKASSERT(i < sc->bnx_serialize_cnt); 4788329f9016SSepherosa Ziehau sc->bnx_serialize[i++] = &sc->bnx_rx_std_ring.bnx_rx_std_serialize; 4789329f9016SSepherosa Ziehau 4790329f9016SSepherosa Ziehau for (j = 0; j < sc->bnx_rx_retcnt; ++j) { 4791329f9016SSepherosa Ziehau KKASSERT(i < sc->bnx_serialize_cnt); 4792329f9016SSepherosa Ziehau sc->bnx_serialize[i++] = 4793329f9016SSepherosa Ziehau &sc->bnx_rx_ret_ring[j].bnx_rx_ret_serialize; 4794329f9016SSepherosa Ziehau } 4795329f9016SSepherosa Ziehau 4796329f9016SSepherosa Ziehau for (j = 0; j < sc->bnx_tx_ringcnt; ++j) { 4797329f9016SSepherosa Ziehau KKASSERT(i < sc->bnx_serialize_cnt); 4798329f9016SSepherosa Ziehau sc->bnx_serialize[i++] = 4799329f9016SSepherosa Ziehau &sc->bnx_tx_ring[j].bnx_tx_serialize; 4800329f9016SSepherosa Ziehau } 4801329f9016SSepherosa Ziehau 4802329f9016SSepherosa Ziehau KKASSERT(i == sc->bnx_serialize_cnt); 4803329f9016SSepherosa Ziehau } 4804329f9016SSepherosa Ziehau 4805329f9016SSepherosa Ziehau static void 4806329f9016SSepherosa Ziehau bnx_serialize(struct ifnet *ifp, enum ifnet_serialize slz) 4807329f9016SSepherosa Ziehau { 4808329f9016SSepherosa Ziehau struct bnx_softc *sc = ifp->if_softc; 4809329f9016SSepherosa Ziehau 4810329f9016SSepherosa Ziehau ifnet_serialize_array_enter(sc->bnx_serialize, 4811329f9016SSepherosa Ziehau sc->bnx_serialize_cnt, slz); 4812329f9016SSepherosa Ziehau } 4813329f9016SSepherosa Ziehau 4814329f9016SSepherosa Ziehau static void 4815329f9016SSepherosa Ziehau bnx_deserialize(struct ifnet *ifp, enum ifnet_serialize slz) 4816329f9016SSepherosa Ziehau { 4817329f9016SSepherosa Ziehau struct bnx_softc *sc = ifp->if_softc; 4818329f9016SSepherosa Ziehau 4819329f9016SSepherosa Ziehau ifnet_serialize_array_exit(sc->bnx_serialize, 4820329f9016SSepherosa Ziehau sc->bnx_serialize_cnt, slz); 4821329f9016SSepherosa Ziehau } 4822329f9016SSepherosa Ziehau 4823329f9016SSepherosa Ziehau static int 4824329f9016SSepherosa Ziehau bnx_tryserialize(struct ifnet *ifp, enum ifnet_serialize slz) 4825329f9016SSepherosa Ziehau { 4826329f9016SSepherosa Ziehau struct bnx_softc *sc = ifp->if_softc; 4827329f9016SSepherosa Ziehau 4828329f9016SSepherosa Ziehau return ifnet_serialize_array_try(sc->bnx_serialize, 4829329f9016SSepherosa Ziehau sc->bnx_serialize_cnt, slz); 4830329f9016SSepherosa Ziehau } 4831329f9016SSepherosa Ziehau 4832329f9016SSepherosa Ziehau #ifdef INVARIANTS 4833329f9016SSepherosa Ziehau 4834329f9016SSepherosa Ziehau static void 4835329f9016SSepherosa Ziehau bnx_serialize_assert(struct ifnet *ifp, enum ifnet_serialize slz, 4836329f9016SSepherosa Ziehau boolean_t serialized) 4837329f9016SSepherosa Ziehau { 4838329f9016SSepherosa Ziehau struct bnx_softc *sc = ifp->if_softc; 4839329f9016SSepherosa Ziehau 4840329f9016SSepherosa Ziehau ifnet_serialize_array_assert(sc->bnx_serialize, sc->bnx_serialize_cnt, 4841329f9016SSepherosa Ziehau slz, serialized); 4842329f9016SSepherosa Ziehau } 4843329f9016SSepherosa Ziehau 4844329f9016SSepherosa Ziehau #endif /* INVARIANTS */ 48454fa38985SSepherosa Ziehau 48464fa38985SSepherosa Ziehau #ifdef IFPOLL_ENABLE 48474fa38985SSepherosa Ziehau 48484fa38985SSepherosa Ziehau static int 48494fa38985SSepherosa Ziehau bnx_sysctl_npoll_offset(SYSCTL_HANDLER_ARGS) 48504fa38985SSepherosa Ziehau { 48514fa38985SSepherosa Ziehau struct bnx_softc *sc = (void *)arg1; 48524fa38985SSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if; 48534fa38985SSepherosa Ziehau int error, off; 48544fa38985SSepherosa Ziehau 48554fa38985SSepherosa Ziehau off = sc->bnx_npoll_rxoff; 48564fa38985SSepherosa Ziehau error = sysctl_handle_int(oidp, &off, 0, req); 48574fa38985SSepherosa Ziehau if (error || req->newptr == NULL) 48584fa38985SSepherosa Ziehau return error; 48594fa38985SSepherosa Ziehau if (off < 0) 48604fa38985SSepherosa Ziehau return EINVAL; 48614fa38985SSepherosa Ziehau 48624fa38985SSepherosa Ziehau ifnet_serialize_all(ifp); 48634fa38985SSepherosa Ziehau if (off >= ncpus2 || off % sc->bnx_rx_retcnt != 0) { 48644fa38985SSepherosa Ziehau error = EINVAL; 48654fa38985SSepherosa Ziehau } else { 48664fa38985SSepherosa Ziehau error = 0; 48674fa38985SSepherosa Ziehau sc->bnx_npoll_txoff = off; 48684fa38985SSepherosa Ziehau sc->bnx_npoll_rxoff = off; 48694fa38985SSepherosa Ziehau } 48704fa38985SSepherosa Ziehau ifnet_deserialize_all(ifp); 48714fa38985SSepherosa Ziehau 48724fa38985SSepherosa Ziehau return error; 48734fa38985SSepherosa Ziehau } 48744fa38985SSepherosa Ziehau 48754fa38985SSepherosa Ziehau static int 48764fa38985SSepherosa Ziehau bnx_sysctl_npoll_rxoff(SYSCTL_HANDLER_ARGS) 48774fa38985SSepherosa Ziehau { 48784fa38985SSepherosa Ziehau struct bnx_softc *sc = (void *)arg1; 48794fa38985SSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if; 48804fa38985SSepherosa Ziehau int error, off; 48814fa38985SSepherosa Ziehau 48824fa38985SSepherosa Ziehau off = sc->bnx_npoll_rxoff; 48834fa38985SSepherosa Ziehau error = sysctl_handle_int(oidp, &off, 0, req); 48844fa38985SSepherosa Ziehau if (error || req->newptr == NULL) 48854fa38985SSepherosa Ziehau return error; 48864fa38985SSepherosa Ziehau if (off < 0) 48874fa38985SSepherosa Ziehau return EINVAL; 48884fa38985SSepherosa Ziehau 48894fa38985SSepherosa Ziehau ifnet_serialize_all(ifp); 48904fa38985SSepherosa Ziehau if (off >= ncpus2 || off % sc->bnx_rx_retcnt != 0) { 48914fa38985SSepherosa Ziehau error = EINVAL; 48924fa38985SSepherosa Ziehau } else { 48934fa38985SSepherosa Ziehau error = 0; 48944fa38985SSepherosa Ziehau sc->bnx_npoll_rxoff = off; 48954fa38985SSepherosa Ziehau } 48964fa38985SSepherosa Ziehau ifnet_deserialize_all(ifp); 48974fa38985SSepherosa Ziehau 48984fa38985SSepherosa Ziehau return error; 48994fa38985SSepherosa Ziehau } 49004fa38985SSepherosa Ziehau 49014fa38985SSepherosa Ziehau static int 49024fa38985SSepherosa Ziehau bnx_sysctl_npoll_txoff(SYSCTL_HANDLER_ARGS) 49034fa38985SSepherosa Ziehau { 49044fa38985SSepherosa Ziehau struct bnx_softc *sc = (void *)arg1; 49054fa38985SSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if; 49064fa38985SSepherosa Ziehau int error, off; 49074fa38985SSepherosa Ziehau 49084fa38985SSepherosa Ziehau off = sc->bnx_npoll_txoff; 49094fa38985SSepherosa Ziehau error = sysctl_handle_int(oidp, &off, 0, req); 49104fa38985SSepherosa Ziehau if (error || req->newptr == NULL) 49114fa38985SSepherosa Ziehau return error; 49124fa38985SSepherosa Ziehau if (off < 0) 49134fa38985SSepherosa Ziehau return EINVAL; 49144fa38985SSepherosa Ziehau 49154fa38985SSepherosa Ziehau ifnet_serialize_all(ifp); 49164fa38985SSepherosa Ziehau if (off >= ncpus2) { 49174fa38985SSepherosa Ziehau error = EINVAL; 49184fa38985SSepherosa Ziehau } else { 49194fa38985SSepherosa Ziehau error = 0; 49204fa38985SSepherosa Ziehau sc->bnx_npoll_txoff = off; 49214fa38985SSepherosa Ziehau } 49224fa38985SSepherosa Ziehau ifnet_deserialize_all(ifp); 49234fa38985SSepherosa Ziehau 49244fa38985SSepherosa Ziehau return error; 49254fa38985SSepherosa Ziehau } 49264fa38985SSepherosa Ziehau 49274fa38985SSepherosa Ziehau #endif /* IFPOLL_ENABLE */ 49287dbaa833SSepherosa Ziehau 49297dbaa833SSepherosa Ziehau static void 49307dbaa833SSepherosa Ziehau bnx_set_tick_cpuid(struct bnx_softc *sc, boolean_t polling) 49317dbaa833SSepherosa Ziehau { 49327dbaa833SSepherosa Ziehau if (polling) 49337dbaa833SSepherosa Ziehau sc->bnx_tick_cpuid = 0; /* XXX */ 49347dbaa833SSepherosa Ziehau else 49357dbaa833SSepherosa Ziehau sc->bnx_tick_cpuid = sc->bnx_intr_data[0].bnx_intr_cpuid; 49367dbaa833SSepherosa Ziehau } 4937841cdf08SSepherosa Ziehau 4938841cdf08SSepherosa Ziehau static void 4939841cdf08SSepherosa Ziehau bnx_rx_std_refill_ithread(void *xstd) 4940841cdf08SSepherosa Ziehau { 4941841cdf08SSepherosa Ziehau struct bnx_rx_std_ring *std = xstd; 4942841cdf08SSepherosa Ziehau struct globaldata *gd = mycpu; 4943841cdf08SSepherosa Ziehau 4944841cdf08SSepherosa Ziehau crit_enter_gd(gd); 4945841cdf08SSepherosa Ziehau 4946841cdf08SSepherosa Ziehau while (!std->bnx_rx_std_stop) { 4947841cdf08SSepherosa Ziehau if (std->bnx_rx_std_refill) { 4948841cdf08SSepherosa Ziehau lwkt_serialize_handler_call( 4949841cdf08SSepherosa Ziehau &std->bnx_rx_std_serialize, 4950841cdf08SSepherosa Ziehau bnx_rx_std_refill, std, NULL); 4951841cdf08SSepherosa Ziehau } 4952841cdf08SSepherosa Ziehau 4953841cdf08SSepherosa Ziehau crit_exit_gd(gd); 4954841cdf08SSepherosa Ziehau crit_enter_gd(gd); 4955841cdf08SSepherosa Ziehau 4956841cdf08SSepherosa Ziehau if (!std->bnx_rx_std_refill && !std->bnx_rx_std_stop) { 4957841cdf08SSepherosa Ziehau lwkt_deschedule_self(gd->gd_curthread); 4958841cdf08SSepherosa Ziehau lwkt_switch(); 4959841cdf08SSepherosa Ziehau } 4960841cdf08SSepherosa Ziehau } 4961841cdf08SSepherosa Ziehau 4962841cdf08SSepherosa Ziehau crit_exit_gd(gd); 4963841cdf08SSepherosa Ziehau 4964841cdf08SSepherosa Ziehau wakeup(std); 4965841cdf08SSepherosa Ziehau 4966841cdf08SSepherosa Ziehau lwkt_exit(); 4967841cdf08SSepherosa Ziehau } 4968841cdf08SSepherosa Ziehau 4969841cdf08SSepherosa Ziehau static void 4970841cdf08SSepherosa Ziehau bnx_rx_std_refill(void *xstd, void *frame __unused) 4971841cdf08SSepherosa Ziehau { 4972841cdf08SSepherosa Ziehau struct bnx_rx_std_ring *std = xstd; 4973841cdf08SSepherosa Ziehau uint16_t check_idx; 4974841cdf08SSepherosa Ziehau int cnt, refill; 4975841cdf08SSepherosa Ziehau 4976841cdf08SSepherosa Ziehau again: 4977841cdf08SSepherosa Ziehau cnt = 0; 4978841cdf08SSepherosa Ziehau check_idx = std->bnx_rx_std; 4979841cdf08SSepherosa Ziehau 4980841cdf08SSepherosa Ziehau cpu_lfence(); 4981841cdf08SSepherosa Ziehau refill = std->bnx_rx_std_refill; 4982841cdf08SSepherosa Ziehau atomic_clear_int(&std->bnx_rx_std_refill, refill); 4983841cdf08SSepherosa Ziehau 4984841cdf08SSepherosa Ziehau for (;;) { 4985841cdf08SSepherosa Ziehau struct bnx_rx_buf *rb; 4986841cdf08SSepherosa Ziehau 4987841cdf08SSepherosa Ziehau BNX_INC(check_idx, BGE_STD_RX_RING_CNT); 4988841cdf08SSepherosa Ziehau rb = &std->bnx_rx_std_buf[check_idx]; 4989841cdf08SSepherosa Ziehau 4990841cdf08SSepherosa Ziehau if (rb->bnx_rx_refilled) { 4991841cdf08SSepherosa Ziehau cpu_lfence(); 4992841cdf08SSepherosa Ziehau bnx_setup_rxdesc_std(std, check_idx); 4993841cdf08SSepherosa Ziehau std->bnx_rx_std = check_idx; 4994841cdf08SSepherosa Ziehau ++cnt; 4995841cdf08SSepherosa Ziehau } else { 4996841cdf08SSepherosa Ziehau break; 4997841cdf08SSepherosa Ziehau } 4998841cdf08SSepherosa Ziehau } 4999841cdf08SSepherosa Ziehau 5000841cdf08SSepherosa Ziehau if (cnt) { 5001841cdf08SSepherosa Ziehau bnx_writembx(std->bnx_sc, BGE_MBX_RX_STD_PROD_LO, 5002841cdf08SSepherosa Ziehau std->bnx_rx_std); 5003841cdf08SSepherosa Ziehau } 5004841cdf08SSepherosa Ziehau 5005841cdf08SSepherosa Ziehau if (std->bnx_rx_std_refill) 5006841cdf08SSepherosa Ziehau goto again; 5007841cdf08SSepherosa Ziehau 5008841cdf08SSepherosa Ziehau atomic_poll_release_int(&std->bnx_rx_std_running); 5009841cdf08SSepherosa Ziehau cpu_mfence(); 5010841cdf08SSepherosa Ziehau 5011841cdf08SSepherosa Ziehau if (std->bnx_rx_std_refill) 5012841cdf08SSepherosa Ziehau goto again; 5013841cdf08SSepherosa Ziehau } 5014841cdf08SSepherosa Ziehau 5015841cdf08SSepherosa Ziehau static int 5016841cdf08SSepherosa Ziehau bnx_sysctl_std_refill(SYSCTL_HANDLER_ARGS) 5017841cdf08SSepherosa Ziehau { 5018841cdf08SSepherosa Ziehau struct bnx_softc *sc = (void *)arg1; 5019841cdf08SSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if; 5020841cdf08SSepherosa Ziehau struct bnx_rx_ret_ring *ret = &sc->bnx_rx_ret_ring[0]; 5021841cdf08SSepherosa Ziehau int error, cntmax, i; 5022841cdf08SSepherosa Ziehau 5023841cdf08SSepherosa Ziehau cntmax = ret->bnx_rx_cntmax; 5024841cdf08SSepherosa Ziehau error = sysctl_handle_int(oidp, &cntmax, 0, req); 5025841cdf08SSepherosa Ziehau if (error || req->newptr == NULL) 5026841cdf08SSepherosa Ziehau return error; 5027841cdf08SSepherosa Ziehau 5028841cdf08SSepherosa Ziehau ifnet_serialize_all(ifp); 5029841cdf08SSepherosa Ziehau 5030841cdf08SSepherosa Ziehau if ((cntmax * sc->bnx_rx_retcnt) > BGE_STD_RX_RING_CNT / 2) { 5031841cdf08SSepherosa Ziehau error = EINVAL; 5032841cdf08SSepherosa Ziehau goto back; 5033841cdf08SSepherosa Ziehau } 5034841cdf08SSepherosa Ziehau 5035841cdf08SSepherosa Ziehau for (i = 0; i < sc->bnx_tx_ringcnt; ++i) 5036841cdf08SSepherosa Ziehau sc->bnx_rx_ret_ring[i].bnx_rx_cntmax = cntmax; 5037841cdf08SSepherosa Ziehau error = 0; 5038841cdf08SSepherosa Ziehau 5039841cdf08SSepherosa Ziehau back: 5040841cdf08SSepherosa Ziehau ifnet_deserialize_all(ifp); 5041841cdf08SSepherosa Ziehau 5042841cdf08SSepherosa Ziehau return error; 5043841cdf08SSepherosa Ziehau } 5044