179251f5eSSepherosa Ziehau /*
26150453fSSepherosa Ziehau * Copyright (c) 2001-2017, Intel Corporation
379251f5eSSepherosa Ziehau * All rights reserved.
479251f5eSSepherosa Ziehau *
579251f5eSSepherosa Ziehau * Redistribution and use in source and binary forms, with or without
679251f5eSSepherosa Ziehau * modification, are permitted provided that the following conditions are met:
779251f5eSSepherosa Ziehau *
879251f5eSSepherosa Ziehau * 1. Redistributions of source code must retain the above copyright notice,
979251f5eSSepherosa Ziehau * this list of conditions and the following disclaimer.
1079251f5eSSepherosa Ziehau *
1179251f5eSSepherosa Ziehau * 2. Redistributions in binary form must reproduce the above copyright
1279251f5eSSepherosa Ziehau * notice, this list of conditions and the following disclaimer in the
1379251f5eSSepherosa Ziehau * documentation and/or other materials provided with the distribution.
1479251f5eSSepherosa Ziehau *
1579251f5eSSepherosa Ziehau * 3. Neither the name of the Intel Corporation nor the names of its
1679251f5eSSepherosa Ziehau * contributors may be used to endorse or promote products derived from
1779251f5eSSepherosa Ziehau * this software without specific prior written permission.
1879251f5eSSepherosa Ziehau *
1979251f5eSSepherosa Ziehau * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
2079251f5eSSepherosa Ziehau * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2179251f5eSSepherosa Ziehau * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2279251f5eSSepherosa Ziehau * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
2379251f5eSSepherosa Ziehau * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
2479251f5eSSepherosa Ziehau * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2579251f5eSSepherosa Ziehau * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2679251f5eSSepherosa Ziehau * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
2779251f5eSSepherosa Ziehau * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
2879251f5eSSepherosa Ziehau * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
2979251f5eSSepherosa Ziehau * POSSIBILITY OF SUCH DAMAGE.
3079251f5eSSepherosa Ziehau */
3179251f5eSSepherosa Ziehau
324a648aefSSepherosa Ziehau #include "opt_ifpoll.h"
3379251f5eSSepherosa Ziehau #include "opt_ix.h"
3479251f5eSSepherosa Ziehau
3579251f5eSSepherosa Ziehau #include <sys/param.h>
3679251f5eSSepherosa Ziehau #include <sys/bus.h>
3779251f5eSSepherosa Ziehau #include <sys/endian.h>
3879251f5eSSepherosa Ziehau #include <sys/interrupt.h>
3979251f5eSSepherosa Ziehau #include <sys/kernel.h>
4079251f5eSSepherosa Ziehau #include <sys/malloc.h>
4179251f5eSSepherosa Ziehau #include <sys/mbuf.h>
4279251f5eSSepherosa Ziehau #include <sys/proc.h>
4379251f5eSSepherosa Ziehau #include <sys/rman.h>
4479251f5eSSepherosa Ziehau #include <sys/serialize.h>
4579251f5eSSepherosa Ziehau #include <sys/serialize2.h>
4679251f5eSSepherosa Ziehau #include <sys/socket.h>
4779251f5eSSepherosa Ziehau #include <sys/sockio.h>
4879251f5eSSepherosa Ziehau #include <sys/sysctl.h>
4979251f5eSSepherosa Ziehau #include <sys/systm.h>
508d0afa86SSepherosa Ziehau #include <sys/taskqueue.h>
5179251f5eSSepherosa Ziehau
5279251f5eSSepherosa Ziehau #include <net/bpf.h>
5379251f5eSSepherosa Ziehau #include <net/ethernet.h>
5479251f5eSSepherosa Ziehau #include <net/if.h>
5579251f5eSSepherosa Ziehau #include <net/if_arp.h>
5679251f5eSSepherosa Ziehau #include <net/if_dl.h>
5779251f5eSSepherosa Ziehau #include <net/if_media.h>
5879251f5eSSepherosa Ziehau #include <net/ifq_var.h>
59afc5d5f3SSepherosa Ziehau #include <net/if_ringmap.h>
6079251f5eSSepherosa Ziehau #include <net/toeplitz.h>
6179251f5eSSepherosa Ziehau #include <net/toeplitz2.h>
6279251f5eSSepherosa Ziehau #include <net/vlan/if_vlan_var.h>
6379251f5eSSepherosa Ziehau #include <net/vlan/if_vlan_ether.h>
6479251f5eSSepherosa Ziehau #include <net/if_poll.h>
6579251f5eSSepherosa Ziehau
6679251f5eSSepherosa Ziehau #include <netinet/in_systm.h>
6779251f5eSSepherosa Ziehau #include <netinet/in.h>
6879251f5eSSepherosa Ziehau #include <netinet/ip.h>
6979251f5eSSepherosa Ziehau
7079251f5eSSepherosa Ziehau #include <bus/pci/pcivar.h>
7179251f5eSSepherosa Ziehau #include <bus/pci/pcireg.h>
7279251f5eSSepherosa Ziehau
736150453fSSepherosa Ziehau #include <dev/netif/ix/ixgbe_common.h>
7479251f5eSSepherosa Ziehau #include <dev/netif/ix/ixgbe_api.h>
7579251f5eSSepherosa Ziehau #include <dev/netif/ix/if_ix.h>
7679251f5eSSepherosa Ziehau
7763d483cdSSepherosa Ziehau #define IX_IFM_DEFAULT (IFM_ETHER | IFM_AUTO)
7863d483cdSSepherosa Ziehau
7979251f5eSSepherosa Ziehau #ifdef IX_RSS_DEBUG
8079251f5eSSepherosa Ziehau #define IX_RSS_DPRINTF(sc, lvl, fmt, ...) \
8179251f5eSSepherosa Ziehau do { \
8279251f5eSSepherosa Ziehau if (sc->rss_debug >= lvl) \
8379251f5eSSepherosa Ziehau if_printf(&sc->arpcom.ac_if, fmt, __VA_ARGS__); \
8479251f5eSSepherosa Ziehau } while (0)
8579251f5eSSepherosa Ziehau #else /* !IX_RSS_DEBUG */
8679251f5eSSepherosa Ziehau #define IX_RSS_DPRINTF(sc, lvl, fmt, ...) ((void)0)
8779251f5eSSepherosa Ziehau #endif /* IX_RSS_DEBUG */
8879251f5eSSepherosa Ziehau
8979251f5eSSepherosa Ziehau #define IX_NAME "Intel(R) PRO/10GbE "
9079251f5eSSepherosa Ziehau #define IX_DEVICE(id) \
9163d483cdSSepherosa Ziehau { IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_##id, IX_NAME #id }
9279251f5eSSepherosa Ziehau #define IX_DEVICE_NULL { 0, 0, NULL }
9379251f5eSSepherosa Ziehau
9479251f5eSSepherosa Ziehau static struct ix_device {
9579251f5eSSepherosa Ziehau uint16_t vid;
9679251f5eSSepherosa Ziehau uint16_t did;
9779251f5eSSepherosa Ziehau const char *desc;
9879251f5eSSepherosa Ziehau } ix_devices[] = {
9979251f5eSSepherosa Ziehau IX_DEVICE(82598AF_DUAL_PORT),
10079251f5eSSepherosa Ziehau IX_DEVICE(82598AF_SINGLE_PORT),
10179251f5eSSepherosa Ziehau IX_DEVICE(82598EB_CX4),
10279251f5eSSepherosa Ziehau IX_DEVICE(82598AT),
10379251f5eSSepherosa Ziehau IX_DEVICE(82598AT2),
10479251f5eSSepherosa Ziehau IX_DEVICE(82598),
10579251f5eSSepherosa Ziehau IX_DEVICE(82598_DA_DUAL_PORT),
10679251f5eSSepherosa Ziehau IX_DEVICE(82598_CX4_DUAL_PORT),
10779251f5eSSepherosa Ziehau IX_DEVICE(82598EB_XF_LR),
10879251f5eSSepherosa Ziehau IX_DEVICE(82598_SR_DUAL_PORT_EM),
10979251f5eSSepherosa Ziehau IX_DEVICE(82598EB_SFP_LOM),
11079251f5eSSepherosa Ziehau IX_DEVICE(82599_KX4),
11179251f5eSSepherosa Ziehau IX_DEVICE(82599_KX4_MEZZ),
11279251f5eSSepherosa Ziehau IX_DEVICE(82599_SFP),
11379251f5eSSepherosa Ziehau IX_DEVICE(82599_XAUI_LOM),
11479251f5eSSepherosa Ziehau IX_DEVICE(82599_CX4),
11579251f5eSSepherosa Ziehau IX_DEVICE(82599_T3_LOM),
11679251f5eSSepherosa Ziehau IX_DEVICE(82599_COMBO_BACKPLANE),
11779251f5eSSepherosa Ziehau IX_DEVICE(82599_BACKPLANE_FCOE),
11879251f5eSSepherosa Ziehau IX_DEVICE(82599_SFP_SF2),
11979251f5eSSepherosa Ziehau IX_DEVICE(82599_SFP_FCOE),
12079251f5eSSepherosa Ziehau IX_DEVICE(82599EN_SFP),
12179251f5eSSepherosa Ziehau IX_DEVICE(82599_SFP_SF_QP),
12263d483cdSSepherosa Ziehau IX_DEVICE(82599_QSFP_SF_QP),
12379251f5eSSepherosa Ziehau IX_DEVICE(X540T),
12463d483cdSSepherosa Ziehau IX_DEVICE(X540T1),
12563d483cdSSepherosa Ziehau IX_DEVICE(X550T),
1266150453fSSepherosa Ziehau IX_DEVICE(X550T1),
12763d483cdSSepherosa Ziehau IX_DEVICE(X550EM_X_KR),
12863d483cdSSepherosa Ziehau IX_DEVICE(X550EM_X_KX4),
12963d483cdSSepherosa Ziehau IX_DEVICE(X550EM_X_10G_T),
1306150453fSSepherosa Ziehau IX_DEVICE(X550EM_X_1G_T),
1316150453fSSepherosa Ziehau IX_DEVICE(X550EM_X_SFP),
1326150453fSSepherosa Ziehau IX_DEVICE(X550EM_A_KR),
1336150453fSSepherosa Ziehau IX_DEVICE(X550EM_A_KR_L),
1346150453fSSepherosa Ziehau IX_DEVICE(X550EM_A_SFP),
1356150453fSSepherosa Ziehau IX_DEVICE(X550EM_A_SFP_N),
1366150453fSSepherosa Ziehau IX_DEVICE(X550EM_A_SGMII),
1376150453fSSepherosa Ziehau IX_DEVICE(X550EM_A_SGMII_L),
1386150453fSSepherosa Ziehau IX_DEVICE(X550EM_A_10G_T),
1396150453fSSepherosa Ziehau IX_DEVICE(X550EM_A_1G_T),
1406150453fSSepherosa Ziehau IX_DEVICE(X550EM_A_1G_T_L),
1416150453fSSepherosa Ziehau #if 0
1426150453fSSepherosa Ziehau IX_DEVICE(X540_BYPASS),
1436150453fSSepherosa Ziehau IX_DEVICE(82599_BYPASS),
1446150453fSSepherosa Ziehau #endif
14579251f5eSSepherosa Ziehau
14679251f5eSSepherosa Ziehau /* required last entry */
14779251f5eSSepherosa Ziehau IX_DEVICE_NULL
14879251f5eSSepherosa Ziehau };
14979251f5eSSepherosa Ziehau
15079251f5eSSepherosa Ziehau static int ix_probe(device_t);
15179251f5eSSepherosa Ziehau static int ix_attach(device_t);
15279251f5eSSepherosa Ziehau static int ix_detach(device_t);
15379251f5eSSepherosa Ziehau static int ix_shutdown(device_t);
15479251f5eSSepherosa Ziehau
15579251f5eSSepherosa Ziehau static void ix_serialize(struct ifnet *, enum ifnet_serialize);
15679251f5eSSepherosa Ziehau static void ix_deserialize(struct ifnet *, enum ifnet_serialize);
15779251f5eSSepherosa Ziehau static int ix_tryserialize(struct ifnet *, enum ifnet_serialize);
15879251f5eSSepherosa Ziehau #ifdef INVARIANTS
15979251f5eSSepherosa Ziehau static void ix_serialize_assert(struct ifnet *, enum ifnet_serialize,
16079251f5eSSepherosa Ziehau boolean_t);
16179251f5eSSepherosa Ziehau #endif
16279251f5eSSepherosa Ziehau static void ix_start(struct ifnet *, struct ifaltq_subque *);
16379251f5eSSepherosa Ziehau static void ix_watchdog(struct ifaltq_subque *);
16479251f5eSSepherosa Ziehau static int ix_ioctl(struct ifnet *, u_long, caddr_t, struct ucred *);
16579251f5eSSepherosa Ziehau static void ix_init(void *);
16679251f5eSSepherosa Ziehau static void ix_stop(struct ix_softc *);
16779251f5eSSepherosa Ziehau static void ix_media_status(struct ifnet *, struct ifmediareq *);
16879251f5eSSepherosa Ziehau static int ix_media_change(struct ifnet *);
16979251f5eSSepherosa Ziehau static void ix_timer(void *);
170dd5ce676SSepherosa Ziehau static void ix_fw_timer(void *);
1714a648aefSSepherosa Ziehau #ifdef IFPOLL_ENABLE
1724a648aefSSepherosa Ziehau static void ix_npoll(struct ifnet *, struct ifpoll_info *);
1734a648aefSSepherosa Ziehau static void ix_npoll_rx(struct ifnet *, void *, int);
1748d0afa86SSepherosa Ziehau static void ix_npoll_rx_direct(struct ifnet *, void *, int);
1754a648aefSSepherosa Ziehau static void ix_npoll_tx(struct ifnet *, void *, int);
1764a648aefSSepherosa Ziehau static void ix_npoll_status(struct ifnet *);
1774a648aefSSepherosa Ziehau #endif
17879251f5eSSepherosa Ziehau
17979251f5eSSepherosa Ziehau static void ix_add_sysctl(struct ix_softc *);
180189a0ff3SSepherosa Ziehau static void ix_add_intr_rate_sysctl(struct ix_softc *, int,
181189a0ff3SSepherosa Ziehau const char *, int (*)(SYSCTL_HANDLER_ARGS), const char *);
18279251f5eSSepherosa Ziehau static int ix_sysctl_tx_wreg_nsegs(SYSCTL_HANDLER_ARGS);
18382db96e9SSepherosa Ziehau static int ix_sysctl_tx_nmbuf(SYSCTL_HANDLER_ARGS);
18479251f5eSSepherosa Ziehau static int ix_sysctl_rx_wreg_nsegs(SYSCTL_HANDLER_ARGS);
18579251f5eSSepherosa Ziehau static int ix_sysctl_txd(SYSCTL_HANDLER_ARGS);
18679251f5eSSepherosa Ziehau static int ix_sysctl_rxd(SYSCTL_HANDLER_ARGS);
18779251f5eSSepherosa Ziehau static int ix_sysctl_tx_intr_nsegs(SYSCTL_HANDLER_ARGS);
188189a0ff3SSepherosa Ziehau static int ix_sysctl_intr_rate(SYSCTL_HANDLER_ARGS, int);
189189a0ff3SSepherosa Ziehau static int ix_sysctl_rxtx_intr_rate(SYSCTL_HANDLER_ARGS);
190189a0ff3SSepherosa Ziehau static int ix_sysctl_rx_intr_rate(SYSCTL_HANDLER_ARGS);
191189a0ff3SSepherosa Ziehau static int ix_sysctl_tx_intr_rate(SYSCTL_HANDLER_ARGS);
192189a0ff3SSepherosa Ziehau static int ix_sysctl_sts_intr_rate(SYSCTL_HANDLER_ARGS);
19379251f5eSSepherosa Ziehau #if 0
19479251f5eSSepherosa Ziehau static void ix_add_hw_stats(struct ix_softc *);
19579251f5eSSepherosa Ziehau #endif
19679251f5eSSepherosa Ziehau
1978d0afa86SSepherosa Ziehau static void ix_watchdog_reset(struct ix_softc *);
1988d0afa86SSepherosa Ziehau static void ix_watchdog_task(void *, int);
1998d0afa86SSepherosa Ziehau static void ix_sync_netisr(struct ix_softc *, int);
20079251f5eSSepherosa Ziehau static void ix_slot_info(struct ix_softc *);
20179251f5eSSepherosa Ziehau static int ix_alloc_rings(struct ix_softc *);
20279251f5eSSepherosa Ziehau static void ix_free_rings(struct ix_softc *);
20379251f5eSSepherosa Ziehau static void ix_setup_ifp(struct ix_softc *);
20479251f5eSSepherosa Ziehau static void ix_setup_serialize(struct ix_softc *);
2056150453fSSepherosa Ziehau static void ix_setup_caps(struct ix_softc *);
20679251f5eSSepherosa Ziehau static void ix_set_ring_inuse(struct ix_softc *, boolean_t);
207dd5ce676SSepherosa Ziehau static int ix_get_timer_cpuid(const struct ix_softc *, boolean_t);
20879251f5eSSepherosa Ziehau static void ix_update_stats(struct ix_softc *);
2096150453fSSepherosa Ziehau static void ix_detect_fanfail(struct ix_softc *, uint32_t, boolean_t);
21079251f5eSSepherosa Ziehau
21179251f5eSSepherosa Ziehau static void ix_set_promisc(struct ix_softc *);
21279251f5eSSepherosa Ziehau static void ix_set_multi(struct ix_softc *);
21379251f5eSSepherosa Ziehau static void ix_set_vlan(struct ix_softc *);
21479251f5eSSepherosa Ziehau static uint8_t *ix_mc_array_itr(struct ixgbe_hw *, uint8_t **, uint32_t *);
215060fa21cSSepherosa Ziehau static enum ixgbe_fc_mode ix_ifmedia2fc(int);
216060fa21cSSepherosa Ziehau static const char *ix_ifmedia2str(int);
217060fa21cSSepherosa Ziehau static const char *ix_fc2str(enum ixgbe_fc_mode);
21879251f5eSSepherosa Ziehau
2193c37d13bSSepherosa Ziehau static void ix_get_txring_cnt(const struct ix_softc *, int *, int *);
22079251f5eSSepherosa Ziehau static int ix_get_txring_inuse(const struct ix_softc *, boolean_t);
22179251f5eSSepherosa Ziehau static void ix_init_tx_ring(struct ix_tx_ring *);
22279251f5eSSepherosa Ziehau static void ix_free_tx_ring(struct ix_tx_ring *);
22379251f5eSSepherosa Ziehau static int ix_create_tx_ring(struct ix_tx_ring *);
22479251f5eSSepherosa Ziehau static void ix_destroy_tx_ring(struct ix_tx_ring *, int);
22579251f5eSSepherosa Ziehau static void ix_init_tx_unit(struct ix_softc *);
22679251f5eSSepherosa Ziehau static int ix_encap(struct ix_tx_ring *, struct mbuf **,
22779251f5eSSepherosa Ziehau uint16_t *, int *);
22879251f5eSSepherosa Ziehau static int ix_tx_ctx_setup(struct ix_tx_ring *,
22979251f5eSSepherosa Ziehau const struct mbuf *, uint32_t *, uint32_t *);
23079251f5eSSepherosa Ziehau static int ix_tso_ctx_setup(struct ix_tx_ring *,
23179251f5eSSepherosa Ziehau const struct mbuf *, uint32_t *, uint32_t *);
232189a0ff3SSepherosa Ziehau static void ix_txeof(struct ix_tx_ring *, int);
23382db96e9SSepherosa Ziehau static void ix_txgc(struct ix_tx_ring *);
23482db96e9SSepherosa Ziehau static void ix_txgc_timer(void *);
23579251f5eSSepherosa Ziehau
2363c37d13bSSepherosa Ziehau static void ix_get_rxring_cnt(const struct ix_softc *, int *, int *);
23779251f5eSSepherosa Ziehau static int ix_get_rxring_inuse(const struct ix_softc *, boolean_t);
23879251f5eSSepherosa Ziehau static int ix_init_rx_ring(struct ix_rx_ring *);
23979251f5eSSepherosa Ziehau static void ix_free_rx_ring(struct ix_rx_ring *);
24079251f5eSSepherosa Ziehau static int ix_create_rx_ring(struct ix_rx_ring *);
24179251f5eSSepherosa Ziehau static void ix_destroy_rx_ring(struct ix_rx_ring *, int);
2423c37d13bSSepherosa Ziehau static void ix_init_rx_unit(struct ix_softc *, boolean_t);
24379251f5eSSepherosa Ziehau #if 0
24479251f5eSSepherosa Ziehau static void ix_setup_hw_rsc(struct ix_rx_ring *);
24579251f5eSSepherosa Ziehau #endif
24679251f5eSSepherosa Ziehau static int ix_newbuf(struct ix_rx_ring *, int, boolean_t);
2474a648aefSSepherosa Ziehau static void ix_rxeof(struct ix_rx_ring *, int);
24879251f5eSSepherosa Ziehau static void ix_rx_discard(struct ix_rx_ring *, int, boolean_t);
24979251f5eSSepherosa Ziehau static void ix_enable_rx_drop(struct ix_softc *);
25079251f5eSSepherosa Ziehau static void ix_disable_rx_drop(struct ix_softc *);
25179251f5eSSepherosa Ziehau
2526150453fSSepherosa Ziehau static void ix_config_gpie(struct ix_softc *);
253189a0ff3SSepherosa Ziehau static void ix_alloc_msix(struct ix_softc *);
254189a0ff3SSepherosa Ziehau static void ix_free_msix(struct ix_softc *, boolean_t);
255189a0ff3SSepherosa Ziehau static void ix_setup_msix_eims(const struct ix_softc *, int,
256189a0ff3SSepherosa Ziehau uint32_t *, uint32_t *);
25779251f5eSSepherosa Ziehau static int ix_alloc_intr(struct ix_softc *);
25879251f5eSSepherosa Ziehau static void ix_free_intr(struct ix_softc *);
25979251f5eSSepherosa Ziehau static int ix_setup_intr(struct ix_softc *);
26079251f5eSSepherosa Ziehau static void ix_teardown_intr(struct ix_softc *, int);
26179251f5eSSepherosa Ziehau static void ix_enable_intr(struct ix_softc *);
26279251f5eSSepherosa Ziehau static void ix_disable_intr(struct ix_softc *);
26379251f5eSSepherosa Ziehau static void ix_set_ivar(struct ix_softc *, uint8_t, uint8_t, int8_t);
26479251f5eSSepherosa Ziehau static void ix_set_eitr(struct ix_softc *, int, int);
265189a0ff3SSepherosa Ziehau static void ix_intr_status(struct ix_softc *, uint32_t);
2666150453fSSepherosa Ziehau static void ix_intr_82598(void *);
26779251f5eSSepherosa Ziehau static void ix_intr(void *);
268189a0ff3SSepherosa Ziehau static void ix_msix_rxtx(void *);
269189a0ff3SSepherosa Ziehau static void ix_msix_rx(void *);
270189a0ff3SSepherosa Ziehau static void ix_msix_tx(void *);
271189a0ff3SSepherosa Ziehau static void ix_msix_status(void *);
27279251f5eSSepherosa Ziehau
27379251f5eSSepherosa Ziehau static void ix_config_link(struct ix_softc *);
27479251f5eSSepherosa Ziehau static boolean_t ix_sfp_probe(struct ix_softc *);
2756150453fSSepherosa Ziehau static boolean_t ix_is_sfp(struct ixgbe_hw *);
27679251f5eSSepherosa Ziehau static void ix_update_link_status(struct ix_softc *);
27779251f5eSSepherosa Ziehau static void ix_handle_link(struct ix_softc *);
27879251f5eSSepherosa Ziehau static void ix_handle_mod(struct ix_softc *);
27979251f5eSSepherosa Ziehau static void ix_handle_msf(struct ix_softc *);
28063d483cdSSepherosa Ziehau static void ix_handle_phy(struct ix_softc *);
28163d483cdSSepherosa Ziehau static int ix_powerdown(struct ix_softc *);
28263d483cdSSepherosa Ziehau static void ix_config_flowctrl(struct ix_softc *);
28363d483cdSSepherosa Ziehau static void ix_config_dmac(struct ix_softc *);
28463d483cdSSepherosa Ziehau static void ix_init_media(struct ix_softc *);
28579251f5eSSepherosa Ziehau
286dd5ce676SSepherosa Ziehau static void ix_serialize_skipmain(struct ix_softc *);
287dd5ce676SSepherosa Ziehau static void ix_deserialize_skipmain(struct ix_softc *);
288dd5ce676SSepherosa Ziehau
28979251f5eSSepherosa Ziehau static device_method_t ix_methods[] = {
29079251f5eSSepherosa Ziehau /* Device interface */
29179251f5eSSepherosa Ziehau DEVMETHOD(device_probe, ix_probe),
29279251f5eSSepherosa Ziehau DEVMETHOD(device_attach, ix_attach),
29379251f5eSSepherosa Ziehau DEVMETHOD(device_detach, ix_detach),
29479251f5eSSepherosa Ziehau DEVMETHOD(device_shutdown, ix_shutdown),
29579251f5eSSepherosa Ziehau DEVMETHOD_END
29679251f5eSSepherosa Ziehau };
29779251f5eSSepherosa Ziehau
29879251f5eSSepherosa Ziehau static driver_t ix_driver = {
29979251f5eSSepherosa Ziehau "ix",
30079251f5eSSepherosa Ziehau ix_methods,
30179251f5eSSepherosa Ziehau sizeof(struct ix_softc)
30279251f5eSSepherosa Ziehau };
30379251f5eSSepherosa Ziehau
30479251f5eSSepherosa Ziehau static devclass_t ix_devclass;
30579251f5eSSepherosa Ziehau
30679251f5eSSepherosa Ziehau DECLARE_DUMMY_MODULE(if_ix);
30779251f5eSSepherosa Ziehau DRIVER_MODULE(if_ix, pci, ix_driver, ix_devclass, NULL, NULL);
30879251f5eSSepherosa Ziehau
30979251f5eSSepherosa Ziehau static int ix_msi_enable = 1;
310189a0ff3SSepherosa Ziehau static int ix_msix_enable = 1;
31179251f5eSSepherosa Ziehau static int ix_rxr = 0;
312189a0ff3SSepherosa Ziehau static int ix_txr = 0;
31379251f5eSSepherosa Ziehau static int ix_txd = IX_PERF_TXD;
31479251f5eSSepherosa Ziehau static int ix_rxd = IX_PERF_RXD;
31579251f5eSSepherosa Ziehau static int ix_unsupported_sfp = 0;
3168d0afa86SSepherosa Ziehau static int ix_direct_input = 1;
31779251f5eSSepherosa Ziehau
318c2c5f4f3SSepherosa Ziehau static char ix_flowctrl[IFM_ETH_FC_STRLEN] = IFM_ETH_FC_NONE;
319060fa21cSSepherosa Ziehau
32079251f5eSSepherosa Ziehau TUNABLE_INT("hw.ix.msi.enable", &ix_msi_enable);
321189a0ff3SSepherosa Ziehau TUNABLE_INT("hw.ix.msix.enable", &ix_msix_enable);
32279251f5eSSepherosa Ziehau TUNABLE_INT("hw.ix.rxr", &ix_rxr);
323189a0ff3SSepherosa Ziehau TUNABLE_INT("hw.ix.txr", &ix_txr);
32479251f5eSSepherosa Ziehau TUNABLE_INT("hw.ix.txd", &ix_txd);
32579251f5eSSepherosa Ziehau TUNABLE_INT("hw.ix.rxd", &ix_rxd);
32679251f5eSSepherosa Ziehau TUNABLE_INT("hw.ix.unsupported_sfp", &ix_unsupported_sfp);
327060fa21cSSepherosa Ziehau TUNABLE_STR("hw.ix.flow_ctrl", ix_flowctrl, sizeof(ix_flowctrl));
3288d0afa86SSepherosa Ziehau TUNABLE_INT("hw.ix.direct_input", &ix_direct_input);
32979251f5eSSepherosa Ziehau
33079251f5eSSepherosa Ziehau /*
33179251f5eSSepherosa Ziehau * Smart speed setting, default to on. This only works
33279251f5eSSepherosa Ziehau * as a compile option right now as its during attach,
33379251f5eSSepherosa Ziehau * set this to 'ixgbe_smart_speed_off' to disable.
33479251f5eSSepherosa Ziehau */
33579251f5eSSepherosa Ziehau static const enum ixgbe_smart_speed ix_smart_speed =
33679251f5eSSepherosa Ziehau ixgbe_smart_speed_on;
33779251f5eSSepherosa Ziehau
33882db96e9SSepherosa Ziehau static __inline void
ix_try_txgc(struct ix_tx_ring * txr,int8_t dec)33982db96e9SSepherosa Ziehau ix_try_txgc(struct ix_tx_ring *txr, int8_t dec)
34082db96e9SSepherosa Ziehau {
34182db96e9SSepherosa Ziehau
34282db96e9SSepherosa Ziehau if (txr->tx_running > 0) {
34382db96e9SSepherosa Ziehau txr->tx_running -= dec;
34482db96e9SSepherosa Ziehau if (txr->tx_running <= 0 && txr->tx_nmbuf &&
34582db96e9SSepherosa Ziehau txr->tx_avail < txr->tx_ndesc &&
34682db96e9SSepherosa Ziehau txr->tx_avail + txr->tx_intr_nsegs > txr->tx_ndesc)
34782db96e9SSepherosa Ziehau ix_txgc(txr);
34882db96e9SSepherosa Ziehau }
34982db96e9SSepherosa Ziehau }
35082db96e9SSepherosa Ziehau
35182db96e9SSepherosa Ziehau static void
ix_txgc_timer(void * xtxr)35282db96e9SSepherosa Ziehau ix_txgc_timer(void *xtxr)
35382db96e9SSepherosa Ziehau {
35482db96e9SSepherosa Ziehau struct ix_tx_ring *txr = xtxr;
35582db96e9SSepherosa Ziehau struct ifnet *ifp = &txr->tx_sc->arpcom.ac_if;
35682db96e9SSepherosa Ziehau
35782db96e9SSepherosa Ziehau if ((ifp->if_flags & (IFF_RUNNING | IFF_UP | IFF_NPOLLING)) !=
35882db96e9SSepherosa Ziehau (IFF_RUNNING | IFF_UP))
35982db96e9SSepherosa Ziehau return;
36082db96e9SSepherosa Ziehau
36182db96e9SSepherosa Ziehau if (!lwkt_serialize_try(&txr->tx_serialize))
36282db96e9SSepherosa Ziehau goto done;
36382db96e9SSepherosa Ziehau
36482db96e9SSepherosa Ziehau if ((ifp->if_flags & (IFF_RUNNING | IFF_UP | IFF_NPOLLING)) !=
36582db96e9SSepherosa Ziehau (IFF_RUNNING | IFF_UP)) {
36682db96e9SSepherosa Ziehau lwkt_serialize_exit(&txr->tx_serialize);
36782db96e9SSepherosa Ziehau return;
36882db96e9SSepherosa Ziehau }
36982db96e9SSepherosa Ziehau ix_try_txgc(txr, IX_TX_RUNNING_DEC);
37082db96e9SSepherosa Ziehau
37182db96e9SSepherosa Ziehau lwkt_serialize_exit(&txr->tx_serialize);
37282db96e9SSepherosa Ziehau done:
37382db96e9SSepherosa Ziehau callout_reset(&txr->tx_gc_timer, 1, ix_txgc_timer, txr);
37482db96e9SSepherosa Ziehau }
37582db96e9SSepherosa Ziehau
37682db96e9SSepherosa Ziehau static __inline void
ix_tx_intr(struct ix_tx_ring * txr,int hdr)37782db96e9SSepherosa Ziehau ix_tx_intr(struct ix_tx_ring *txr, int hdr)
37882db96e9SSepherosa Ziehau {
37982db96e9SSepherosa Ziehau
38082db96e9SSepherosa Ziehau ix_txeof(txr, hdr);
38182db96e9SSepherosa Ziehau if (!ifsq_is_empty(txr->tx_ifsq))
38282db96e9SSepherosa Ziehau ifsq_devstart(txr->tx_ifsq);
38382db96e9SSepherosa Ziehau }
38482db96e9SSepherosa Ziehau
38582db96e9SSepherosa Ziehau static __inline void
ix_free_txbuf(struct ix_tx_ring * txr,struct ix_tx_buf * txbuf)38682db96e9SSepherosa Ziehau ix_free_txbuf(struct ix_tx_ring *txr, struct ix_tx_buf *txbuf)
38782db96e9SSepherosa Ziehau {
38882db96e9SSepherosa Ziehau
38982db96e9SSepherosa Ziehau KKASSERT(txbuf->m_head != NULL);
39082db96e9SSepherosa Ziehau KKASSERT(txr->tx_nmbuf > 0);
39182db96e9SSepherosa Ziehau txr->tx_nmbuf--;
39282db96e9SSepherosa Ziehau
39382db96e9SSepherosa Ziehau bus_dmamap_unload(txr->tx_tag, txbuf->map);
39482db96e9SSepherosa Ziehau m_freem(txbuf->m_head);
39582db96e9SSepherosa Ziehau txbuf->m_head = NULL;
39682db96e9SSepherosa Ziehau }
39782db96e9SSepherosa Ziehau
39879251f5eSSepherosa Ziehau static int
ix_probe(device_t dev)39979251f5eSSepherosa Ziehau ix_probe(device_t dev)
40079251f5eSSepherosa Ziehau {
40179251f5eSSepherosa Ziehau const struct ix_device *d;
40279251f5eSSepherosa Ziehau uint16_t vid, did;
40379251f5eSSepherosa Ziehau
40479251f5eSSepherosa Ziehau vid = pci_get_vendor(dev);
40579251f5eSSepherosa Ziehau did = pci_get_device(dev);
40679251f5eSSepherosa Ziehau
40779251f5eSSepherosa Ziehau for (d = ix_devices; d->desc != NULL; ++d) {
40879251f5eSSepherosa Ziehau if (vid == d->vid && did == d->did) {
40979251f5eSSepherosa Ziehau device_set_desc(dev, d->desc);
41079251f5eSSepherosa Ziehau return 0;
41179251f5eSSepherosa Ziehau }
41279251f5eSSepherosa Ziehau }
41379251f5eSSepherosa Ziehau return ENXIO;
41479251f5eSSepherosa Ziehau }
41579251f5eSSepherosa Ziehau
4163c37d13bSSepherosa Ziehau static void
ix_get_rxring_cnt(const struct ix_softc * sc,int * ring_cnt,int * ring_cntmax)4173c37d13bSSepherosa Ziehau ix_get_rxring_cnt(const struct ix_softc *sc, int *ring_cnt, int *ring_cntmax)
4183c37d13bSSepherosa Ziehau {
4193c37d13bSSepherosa Ziehau
4203c37d13bSSepherosa Ziehau switch (sc->hw.mac.type) {
4213c37d13bSSepherosa Ziehau case ixgbe_mac_X550:
4223c37d13bSSepherosa Ziehau case ixgbe_mac_X550EM_x:
4233c37d13bSSepherosa Ziehau case ixgbe_mac_X550EM_a:
4243c37d13bSSepherosa Ziehau *ring_cntmax = IX_MAX_RXRING_X550;
4253c37d13bSSepherosa Ziehau break;
4263c37d13bSSepherosa Ziehau
4273c37d13bSSepherosa Ziehau default:
4283c37d13bSSepherosa Ziehau *ring_cntmax = IX_MAX_RXRING;
4293c37d13bSSepherosa Ziehau break;
4303c37d13bSSepherosa Ziehau }
4313c37d13bSSepherosa Ziehau *ring_cnt = device_getenv_int(sc->dev, "rxr", ix_rxr);
4323c37d13bSSepherosa Ziehau }
4333c37d13bSSepherosa Ziehau
4343c37d13bSSepherosa Ziehau static void
ix_get_txring_cnt(const struct ix_softc * sc,int * ring_cnt,int * ring_cntmax)4353c37d13bSSepherosa Ziehau ix_get_txring_cnt(const struct ix_softc *sc, int *ring_cnt, int *ring_cntmax)
4363c37d13bSSepherosa Ziehau {
4373c37d13bSSepherosa Ziehau
4383c37d13bSSepherosa Ziehau switch (sc->hw.mac.type) {
4393c37d13bSSepherosa Ziehau case ixgbe_mac_82598EB:
4403c37d13bSSepherosa Ziehau *ring_cntmax = IX_MAX_TXRING_82598;
4413c37d13bSSepherosa Ziehau break;
4423c37d13bSSepherosa Ziehau
4433c37d13bSSepherosa Ziehau case ixgbe_mac_82599EB:
4443c37d13bSSepherosa Ziehau *ring_cntmax = IX_MAX_TXRING_82599;
4453c37d13bSSepherosa Ziehau break;
4463c37d13bSSepherosa Ziehau
4473c37d13bSSepherosa Ziehau case ixgbe_mac_X540:
4483c37d13bSSepherosa Ziehau *ring_cntmax = IX_MAX_TXRING_X540;
4493c37d13bSSepherosa Ziehau break;
4503c37d13bSSepherosa Ziehau
4513c37d13bSSepherosa Ziehau case ixgbe_mac_X550:
4523c37d13bSSepherosa Ziehau case ixgbe_mac_X550EM_x:
4533c37d13bSSepherosa Ziehau case ixgbe_mac_X550EM_a:
4543c37d13bSSepherosa Ziehau *ring_cntmax = IX_MAX_TXRING_X550;
4553c37d13bSSepherosa Ziehau break;
4563c37d13bSSepherosa Ziehau
4573c37d13bSSepherosa Ziehau default:
4583c37d13bSSepherosa Ziehau *ring_cntmax = IX_MAX_TXRING;
4593c37d13bSSepherosa Ziehau break;
4603c37d13bSSepherosa Ziehau }
4613c37d13bSSepherosa Ziehau *ring_cnt = device_getenv_int(sc->dev, "txr", ix_txr);
4623c37d13bSSepherosa Ziehau }
4633c37d13bSSepherosa Ziehau
46479251f5eSSepherosa Ziehau static int
ix_attach(device_t dev)46579251f5eSSepherosa Ziehau ix_attach(device_t dev)
46679251f5eSSepherosa Ziehau {
46779251f5eSSepherosa Ziehau struct ix_softc *sc = device_get_softc(dev);
46879251f5eSSepherosa Ziehau struct ixgbe_hw *hw;
4693c37d13bSSepherosa Ziehau int error, ring_cnt, ring_cntmax;
47079251f5eSSepherosa Ziehau uint32_t ctrl_ext;
471060fa21cSSepherosa Ziehau char flowctrl[IFM_ETH_FC_STRLEN];
47279251f5eSSepherosa Ziehau
4736150453fSSepherosa Ziehau sc->dev = dev;
47479251f5eSSepherosa Ziehau hw = &sc->hw;
4756150453fSSepherosa Ziehau hw->back = sc;
47679251f5eSSepherosa Ziehau
47779251f5eSSepherosa Ziehau if_initname(&sc->arpcom.ac_if, device_get_name(dev),
47879251f5eSSepherosa Ziehau device_get_unit(dev));
479060fa21cSSepherosa Ziehau ifmedia_init(&sc->media, IFM_IMASK | IFM_ETH_FCMASK,
48079251f5eSSepherosa Ziehau ix_media_change, ix_media_status);
48179251f5eSSepherosa Ziehau
48279251f5eSSepherosa Ziehau /* Save frame size */
48379251f5eSSepherosa Ziehau sc->max_frame_size = ETHERMTU + ETHER_HDR_LEN + ETHER_CRC_LEN;
48479251f5eSSepherosa Ziehau
4858d0afa86SSepherosa Ziehau sc->direct_input = ix_direct_input;
4868d0afa86SSepherosa Ziehau TASK_INIT(&sc->wdog_task, 0, ix_watchdog_task, sc);
4878d0afa86SSepherosa Ziehau
488dd5ce676SSepherosa Ziehau callout_init_mp(&sc->fw_timer);
48979251f5eSSepherosa Ziehau callout_init_mp(&sc->timer);
49079251f5eSSepherosa Ziehau lwkt_serialize_init(&sc->main_serialize);
49179251f5eSSepherosa Ziehau
49279251f5eSSepherosa Ziehau /*
49379251f5eSSepherosa Ziehau * Save off the information about this board
49479251f5eSSepherosa Ziehau */
49579251f5eSSepherosa Ziehau hw->vendor_id = pci_get_vendor(dev);
49679251f5eSSepherosa Ziehau hw->device_id = pci_get_device(dev);
49779251f5eSSepherosa Ziehau hw->revision_id = pci_read_config(dev, PCIR_REVID, 1);
49879251f5eSSepherosa Ziehau hw->subsystem_vendor_id = pci_read_config(dev, PCIR_SUBVEND_0, 2);
49979251f5eSSepherosa Ziehau hw->subsystem_device_id = pci_read_config(dev, PCIR_SUBDEV_0, 2);
50079251f5eSSepherosa Ziehau
50179251f5eSSepherosa Ziehau /* Enable bus mastering */
50279251f5eSSepherosa Ziehau pci_enable_busmaster(dev);
50379251f5eSSepherosa Ziehau
50479251f5eSSepherosa Ziehau /*
50579251f5eSSepherosa Ziehau * Allocate IO memory
50679251f5eSSepherosa Ziehau */
50779251f5eSSepherosa Ziehau sc->mem_rid = PCIR_BAR(0);
50879251f5eSSepherosa Ziehau sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
50979251f5eSSepherosa Ziehau &sc->mem_rid, RF_ACTIVE);
51079251f5eSSepherosa Ziehau if (sc->mem_res == NULL) {
51179251f5eSSepherosa Ziehau device_printf(dev, "Unable to allocate bus resource: memory\n");
51279251f5eSSepherosa Ziehau error = ENXIO;
51379251f5eSSepherosa Ziehau goto failed;
51479251f5eSSepherosa Ziehau }
51579251f5eSSepherosa Ziehau
51679251f5eSSepherosa Ziehau sc->osdep.mem_bus_space_tag = rman_get_bustag(sc->mem_res);
51779251f5eSSepherosa Ziehau sc->osdep.mem_bus_space_handle = rman_get_bushandle(sc->mem_res);
51879251f5eSSepherosa Ziehau
51979251f5eSSepherosa Ziehau sc->hw.hw_addr = (uint8_t *)&sc->osdep.mem_bus_space_handle;
5206150453fSSepherosa Ziehau
5216150453fSSepherosa Ziehau /* Let hardware know driver is loaded */
5226150453fSSepherosa Ziehau ctrl_ext = IXGBE_READ_REG(hw, IXGBE_CTRL_EXT);
5236150453fSSepherosa Ziehau ctrl_ext |= IXGBE_CTRL_EXT_DRV_LOAD;
5246150453fSSepherosa Ziehau IXGBE_WRITE_REG(hw, IXGBE_CTRL_EXT, ctrl_ext);
5256150453fSSepherosa Ziehau
5266150453fSSepherosa Ziehau /*
5276150453fSSepherosa Ziehau * Initialize the shared code
5286150453fSSepherosa Ziehau */
5296150453fSSepherosa Ziehau if (ixgbe_init_shared_code(hw)) {
5306150453fSSepherosa Ziehau device_printf(dev, "Unable to initialize the shared code\n");
5316150453fSSepherosa Ziehau error = ENXIO;
5326150453fSSepherosa Ziehau goto failed;
5336150453fSSepherosa Ziehau }
5346150453fSSepherosa Ziehau
5356150453fSSepherosa Ziehau if (hw->mbx.ops.init_params)
5366150453fSSepherosa Ziehau hw->mbx.ops.init_params(hw);
5376150453fSSepherosa Ziehau
5386150453fSSepherosa Ziehau hw->allow_unsupported_sfp = ix_unsupported_sfp;
5396150453fSSepherosa Ziehau
5406150453fSSepherosa Ziehau /* Pick up the 82599 settings */
5416150453fSSepherosa Ziehau if (hw->mac.type != ixgbe_mac_82598EB)
5426150453fSSepherosa Ziehau hw->phy.smart_speed = ix_smart_speed;
5436150453fSSepherosa Ziehau
5446150453fSSepherosa Ziehau /* Setup hardware capabilities */
5456150453fSSepherosa Ziehau ix_setup_caps(sc);
5466150453fSSepherosa Ziehau
5476150453fSSepherosa Ziehau /* Allocate multicast array memory. */
5486150453fSSepherosa Ziehau sc->mta = kmalloc(sizeof(*sc->mta) * IX_MAX_MCASTADDR,
5496150453fSSepherosa Ziehau M_DEVBUF, M_WAITOK);
5506150453fSSepherosa Ziehau
5516150453fSSepherosa Ziehau /* Save initial wake up filter configuration; WOL is disabled. */
5526150453fSSepherosa Ziehau sc->wufc = IXGBE_READ_REG(hw, IXGBE_WUFC);
5536150453fSSepherosa Ziehau
5546150453fSSepherosa Ziehau /* Verify adapter fan is still functional (if applicable) */
5556150453fSSepherosa Ziehau if (sc->caps & IX_CAP_DETECT_FANFAIL)
5566150453fSSepherosa Ziehau ix_detect_fanfail(sc, IXGBE_READ_REG(hw, IXGBE_ESDP), FALSE);
5576150453fSSepherosa Ziehau
5586150453fSSepherosa Ziehau /* Ensure SW/FW semaphore is free */
5596150453fSSepherosa Ziehau ixgbe_init_swfw_semaphore(hw);
5606150453fSSepherosa Ziehau
5616150453fSSepherosa Ziehau #ifdef notyet
5626150453fSSepherosa Ziehau /* Enable EEE power saving */
5636150453fSSepherosa Ziehau if (sc->caps & IX_CAP_EEE)
5646150453fSSepherosa Ziehau hw->mac.ops.setup_eee(hw, true);
5656150453fSSepherosa Ziehau #endif
56679251f5eSSepherosa Ziehau
56779251f5eSSepherosa Ziehau /*
56879251f5eSSepherosa Ziehau * Configure total supported RX/TX ring count
56979251f5eSSepherosa Ziehau */
5703c37d13bSSepherosa Ziehau ix_get_rxring_cnt(sc, &ring_cnt, &ring_cntmax);
5713c37d13bSSepherosa Ziehau sc->rx_rmap = if_ringmap_alloc(dev, ring_cnt, ring_cntmax);
5723c37d13bSSepherosa Ziehau ix_get_txring_cnt(sc, &ring_cnt, &ring_cntmax);
5733c37d13bSSepherosa Ziehau sc->tx_rmap = if_ringmap_alloc(dev, ring_cnt, ring_cntmax);
5743c37d13bSSepherosa Ziehau if_ringmap_match(dev, sc->rx_rmap, sc->tx_rmap);
575737c1c7cSSepherosa Ziehau
5763c37d13bSSepherosa Ziehau sc->rx_ring_cnt = if_ringmap_count(sc->rx_rmap);
57779251f5eSSepherosa Ziehau sc->rx_ring_inuse = sc->rx_ring_cnt;
5783c37d13bSSepherosa Ziehau sc->tx_ring_cnt = if_ringmap_count(sc->tx_rmap);
57979251f5eSSepherosa Ziehau sc->tx_ring_inuse = sc->tx_ring_cnt;
58079251f5eSSepherosa Ziehau
58179251f5eSSepherosa Ziehau /* Allocate TX/RX rings */
58279251f5eSSepherosa Ziehau error = ix_alloc_rings(sc);
58379251f5eSSepherosa Ziehau if (error)
58479251f5eSSepherosa Ziehau goto failed;
58579251f5eSSepherosa Ziehau
58679251f5eSSepherosa Ziehau /* Allocate interrupt */
58779251f5eSSepherosa Ziehau error = ix_alloc_intr(sc);
58879251f5eSSepherosa Ziehau if (error)
58979251f5eSSepherosa Ziehau goto failed;
59079251f5eSSepherosa Ziehau
59179251f5eSSepherosa Ziehau /* Setup serializes */
59279251f5eSSepherosa Ziehau ix_setup_serialize(sc);
59379251f5eSSepherosa Ziehau
5946150453fSSepherosa Ziehau hw->phy.reset_if_overtemp = TRUE;
5956150453fSSepherosa Ziehau error = ixgbe_reset_hw(hw);
5966150453fSSepherosa Ziehau hw->phy.reset_if_overtemp = FALSE;
59779251f5eSSepherosa Ziehau if (error == IXGBE_ERR_SFP_NOT_PRESENT) {
59879251f5eSSepherosa Ziehau /*
59979251f5eSSepherosa Ziehau * No optics in this port; ask timer routine
60079251f5eSSepherosa Ziehau * to probe for later insertion.
60179251f5eSSepherosa Ziehau */
60279251f5eSSepherosa Ziehau sc->sfp_probe = TRUE;
60379251f5eSSepherosa Ziehau error = 0;
60479251f5eSSepherosa Ziehau } else if (error == IXGBE_ERR_SFP_NOT_SUPPORTED) {
60579251f5eSSepherosa Ziehau device_printf(dev, "Unsupported SFP+ module detected!\n");
60679251f5eSSepherosa Ziehau error = EIO;
60779251f5eSSepherosa Ziehau goto failed;
60879251f5eSSepherosa Ziehau } else if (error) {
6096150453fSSepherosa Ziehau device_printf(dev, "Hardware initialization failed\n");
61079251f5eSSepherosa Ziehau error = EIO;
61179251f5eSSepherosa Ziehau goto failed;
61279251f5eSSepherosa Ziehau }
61379251f5eSSepherosa Ziehau
61479251f5eSSepherosa Ziehau /* Make sure we have a good EEPROM before we read from it */
6156150453fSSepherosa Ziehau if (ixgbe_validate_eeprom_checksum(&sc->hw, NULL) < 0) {
61679251f5eSSepherosa Ziehau device_printf(dev, "The EEPROM Checksum Is Not Valid\n");
61779251f5eSSepherosa Ziehau error = EIO;
61879251f5eSSepherosa Ziehau goto failed;
61979251f5eSSepherosa Ziehau }
62079251f5eSSepherosa Ziehau
6216150453fSSepherosa Ziehau error = ixgbe_start_hw(hw);
62279251f5eSSepherosa Ziehau if (error == IXGBE_ERR_EEPROM_VERSION) {
62379251f5eSSepherosa Ziehau device_printf(dev, "Pre-production device detected\n");
62479251f5eSSepherosa Ziehau } else if (error == IXGBE_ERR_SFP_NOT_SUPPORTED) {
62579251f5eSSepherosa Ziehau device_printf(dev, "Unsupported SFP+ Module\n");
62679251f5eSSepherosa Ziehau error = EIO;
62779251f5eSSepherosa Ziehau goto failed;
62879251f5eSSepherosa Ziehau } else if (error == IXGBE_ERR_SFP_NOT_PRESENT) {
62979251f5eSSepherosa Ziehau device_printf(dev, "No SFP+ Module found\n");
63079251f5eSSepherosa Ziehau }
63179251f5eSSepherosa Ziehau
6326150453fSSepherosa Ziehau /* Enable the optics for 82599 SFP+ fiber */
6336150453fSSepherosa Ziehau ixgbe_enable_tx_laser(hw);
6346150453fSSepherosa Ziehau
6356150453fSSepherosa Ziehau /* Enable power to the phy. */
6366150453fSSepherosa Ziehau ixgbe_set_phy_power(hw, TRUE);
6376150453fSSepherosa Ziehau
63863d483cdSSepherosa Ziehau sc->ifm_media = IX_IFM_DEFAULT;
639060fa21cSSepherosa Ziehau /* Get default flow control settings */
640060fa21cSSepherosa Ziehau device_getenv_string(dev, "flow_ctrl", flowctrl, sizeof(flowctrl),
641060fa21cSSepherosa Ziehau ix_flowctrl);
64263d483cdSSepherosa Ziehau sc->ifm_media |= ifmedia_str2ethfc(flowctrl);
64363d483cdSSepherosa Ziehau sc->advspeed = IXGBE_LINK_SPEED_UNKNOWN;
644060fa21cSSepherosa Ziehau
64579251f5eSSepherosa Ziehau /* Setup OS specific network interface */
64679251f5eSSepherosa Ziehau ix_setup_ifp(sc);
64779251f5eSSepherosa Ziehau
64879251f5eSSepherosa Ziehau /* Add sysctl tree */
64979251f5eSSepherosa Ziehau ix_add_sysctl(sc);
65079251f5eSSepherosa Ziehau
65179251f5eSSepherosa Ziehau error = ix_setup_intr(sc);
65279251f5eSSepherosa Ziehau if (error) {
65379251f5eSSepherosa Ziehau ether_ifdetach(&sc->arpcom.ac_if);
65479251f5eSSepherosa Ziehau goto failed;
65579251f5eSSepherosa Ziehau }
65679251f5eSSepherosa Ziehau
65779251f5eSSepherosa Ziehau /* Initialize statistics */
65879251f5eSSepherosa Ziehau ix_update_stats(sc);
65979251f5eSSepherosa Ziehau
66063d483cdSSepherosa Ziehau /* Check PCIE slot type/speed/width */
66179251f5eSSepherosa Ziehau ix_slot_info(sc);
66279251f5eSSepherosa Ziehau
663dd5ce676SSepherosa Ziehau if (sc->caps & IX_CAP_FW_RECOVERY) {
664dd5ce676SSepherosa Ziehau device_printf(dev, "start fw timer\n");
665dd5ce676SSepherosa Ziehau callout_reset_bycpu(&sc->fw_timer, hz,
666dd5ce676SSepherosa Ziehau ix_fw_timer, sc, ix_get_timer_cpuid(sc, FALSE));
667dd5ce676SSepherosa Ziehau }
668dd5ce676SSepherosa Ziehau
66979251f5eSSepherosa Ziehau return 0;
67079251f5eSSepherosa Ziehau failed:
67179251f5eSSepherosa Ziehau ix_detach(dev);
67279251f5eSSepherosa Ziehau return error;
67379251f5eSSepherosa Ziehau }
67479251f5eSSepherosa Ziehau
67579251f5eSSepherosa Ziehau static int
ix_detach(device_t dev)67679251f5eSSepherosa Ziehau ix_detach(device_t dev)
67779251f5eSSepherosa Ziehau {
67879251f5eSSepherosa Ziehau struct ix_softc *sc = device_get_softc(dev);
67979251f5eSSepherosa Ziehau
68079251f5eSSepherosa Ziehau if (device_is_attached(dev)) {
68179251f5eSSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if;
68279251f5eSSepherosa Ziehau
6838d0afa86SSepherosa Ziehau ix_sync_netisr(sc, IFF_UP);
6848d0afa86SSepherosa Ziehau taskqueue_drain(taskqueue_thread[0], &sc->wdog_task);
6858d0afa86SSepherosa Ziehau
68679251f5eSSepherosa Ziehau ifnet_serialize_all(ifp);
68779251f5eSSepherosa Ziehau
68863d483cdSSepherosa Ziehau ix_powerdown(sc);
68979251f5eSSepherosa Ziehau ix_teardown_intr(sc, sc->intr_cnt);
69079251f5eSSepherosa Ziehau
69179251f5eSSepherosa Ziehau ifnet_deserialize_all(ifp);
69279251f5eSSepherosa Ziehau
69379251f5eSSepherosa Ziehau callout_terminate(&sc->timer);
69479251f5eSSepherosa Ziehau ether_ifdetach(ifp);
6956150453fSSepherosa Ziehau }
696dd5ce676SSepherosa Ziehau callout_terminate(&sc->fw_timer);
6976150453fSSepherosa Ziehau
6986150453fSSepherosa Ziehau if (sc->mem_res != NULL) {
6996150453fSSepherosa Ziehau uint32_t ctrl_ext;
70079251f5eSSepherosa Ziehau
70179251f5eSSepherosa Ziehau /* Let hardware know driver is unloading */
70279251f5eSSepherosa Ziehau ctrl_ext = IXGBE_READ_REG(&sc->hw, IXGBE_CTRL_EXT);
70379251f5eSSepherosa Ziehau ctrl_ext &= ~IXGBE_CTRL_EXT_DRV_LOAD;
70479251f5eSSepherosa Ziehau IXGBE_WRITE_REG(&sc->hw, IXGBE_CTRL_EXT, ctrl_ext);
70579251f5eSSepherosa Ziehau }
70679251f5eSSepherosa Ziehau
70779251f5eSSepherosa Ziehau ifmedia_removeall(&sc->media);
70879251f5eSSepherosa Ziehau bus_generic_detach(dev);
70979251f5eSSepherosa Ziehau
71079251f5eSSepherosa Ziehau ix_free_intr(sc);
71179251f5eSSepherosa Ziehau
712189a0ff3SSepherosa Ziehau if (sc->msix_mem_res != NULL) {
713189a0ff3SSepherosa Ziehau bus_release_resource(dev, SYS_RES_MEMORY, sc->msix_mem_rid,
714189a0ff3SSepherosa Ziehau sc->msix_mem_res);
715189a0ff3SSepherosa Ziehau }
71679251f5eSSepherosa Ziehau if (sc->mem_res != NULL) {
71779251f5eSSepherosa Ziehau bus_release_resource(dev, SYS_RES_MEMORY, sc->mem_rid,
71879251f5eSSepherosa Ziehau sc->mem_res);
71979251f5eSSepherosa Ziehau }
72079251f5eSSepherosa Ziehau
72179251f5eSSepherosa Ziehau ix_free_rings(sc);
72279251f5eSSepherosa Ziehau
72379251f5eSSepherosa Ziehau if (sc->mta != NULL)
72479251f5eSSepherosa Ziehau kfree(sc->mta, M_DEVBUF);
72579251f5eSSepherosa Ziehau if (sc->serializes != NULL)
72679251f5eSSepherosa Ziehau kfree(sc->serializes, M_DEVBUF);
72779251f5eSSepherosa Ziehau
7283c37d13bSSepherosa Ziehau if (sc->rx_rmap != NULL)
7293c37d13bSSepherosa Ziehau if_ringmap_free(sc->rx_rmap);
7303c37d13bSSepherosa Ziehau if (sc->rx_rmap_intr != NULL)
7313c37d13bSSepherosa Ziehau if_ringmap_free(sc->rx_rmap_intr);
7323c37d13bSSepherosa Ziehau if (sc->tx_rmap != NULL)
7333c37d13bSSepherosa Ziehau if_ringmap_free(sc->tx_rmap);
7343c37d13bSSepherosa Ziehau if (sc->tx_rmap_intr != NULL)
7353c37d13bSSepherosa Ziehau if_ringmap_free(sc->tx_rmap_intr);
7363c37d13bSSepherosa Ziehau
73779251f5eSSepherosa Ziehau return 0;
73879251f5eSSepherosa Ziehau }
73979251f5eSSepherosa Ziehau
74079251f5eSSepherosa Ziehau static int
ix_shutdown(device_t dev)74179251f5eSSepherosa Ziehau ix_shutdown(device_t dev)
74279251f5eSSepherosa Ziehau {
74379251f5eSSepherosa Ziehau struct ix_softc *sc = device_get_softc(dev);
74479251f5eSSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if;
74579251f5eSSepherosa Ziehau
7468d0afa86SSepherosa Ziehau ix_sync_netisr(sc, IFF_UP);
7478d0afa86SSepherosa Ziehau taskqueue_drain(taskqueue_thread[0], &sc->wdog_task);
7488d0afa86SSepherosa Ziehau
74979251f5eSSepherosa Ziehau ifnet_serialize_all(ifp);
75063d483cdSSepherosa Ziehau ix_powerdown(sc);
75179251f5eSSepherosa Ziehau ifnet_deserialize_all(ifp);
75279251f5eSSepherosa Ziehau
75379251f5eSSepherosa Ziehau return 0;
75479251f5eSSepherosa Ziehau }
75579251f5eSSepherosa Ziehau
75679251f5eSSepherosa Ziehau static void
ix_start(struct ifnet * ifp,struct ifaltq_subque * ifsq)75779251f5eSSepherosa Ziehau ix_start(struct ifnet *ifp, struct ifaltq_subque *ifsq)
75879251f5eSSepherosa Ziehau {
75979251f5eSSepherosa Ziehau struct ix_softc *sc = ifp->if_softc;
76079251f5eSSepherosa Ziehau struct ix_tx_ring *txr = ifsq_get_priv(ifsq);
76179251f5eSSepherosa Ziehau int idx = -1;
76279251f5eSSepherosa Ziehau uint16_t nsegs;
76379251f5eSSepherosa Ziehau
76479251f5eSSepherosa Ziehau KKASSERT(txr->tx_ifsq == ifsq);
76579251f5eSSepherosa Ziehau ASSERT_SERIALIZED(&txr->tx_serialize);
76679251f5eSSepherosa Ziehau
76779251f5eSSepherosa Ziehau if ((ifp->if_flags & IFF_RUNNING) == 0 || ifsq_is_oactive(ifsq))
76879251f5eSSepherosa Ziehau return;
76979251f5eSSepherosa Ziehau
7704a648aefSSepherosa Ziehau if (!sc->link_active || (txr->tx_flags & IX_TXFLAG_ENABLED) == 0) {
77179251f5eSSepherosa Ziehau ifsq_purge(ifsq);
77279251f5eSSepherosa Ziehau return;
77379251f5eSSepherosa Ziehau }
77479251f5eSSepherosa Ziehau
77579251f5eSSepherosa Ziehau while (!ifsq_is_empty(ifsq)) {
77679251f5eSSepherosa Ziehau struct mbuf *m_head;
77779251f5eSSepherosa Ziehau
77879251f5eSSepherosa Ziehau if (txr->tx_avail <= IX_MAX_SCATTER + IX_TX_RESERVED) {
77979251f5eSSepherosa Ziehau ifsq_set_oactive(ifsq);
780e2292763SMatthew Dillon ifsq_watchdog_set_count(&txr->tx_watchdog, 5);
78179251f5eSSepherosa Ziehau break;
78279251f5eSSepherosa Ziehau }
78379251f5eSSepherosa Ziehau
78479251f5eSSepherosa Ziehau m_head = ifsq_dequeue(ifsq);
78579251f5eSSepherosa Ziehau if (m_head == NULL)
78679251f5eSSepherosa Ziehau break;
78779251f5eSSepherosa Ziehau
78879251f5eSSepherosa Ziehau if (ix_encap(txr, &m_head, &nsegs, &idx)) {
78979251f5eSSepherosa Ziehau IFNET_STAT_INC(ifp, oerrors, 1);
79079251f5eSSepherosa Ziehau continue;
79179251f5eSSepherosa Ziehau }
79279251f5eSSepherosa Ziehau
793608dda76SSepherosa Ziehau /*
794608dda76SSepherosa Ziehau * TX interrupt are aggressively aggregated, so increasing
795608dda76SSepherosa Ziehau * opackets at TX interrupt time will make the opackets
796608dda76SSepherosa Ziehau * statistics vastly inaccurate; we do the opackets increment
797608dda76SSepherosa Ziehau * now.
798608dda76SSepherosa Ziehau */
799608dda76SSepherosa Ziehau IFNET_STAT_INC(ifp, opackets, 1);
800608dda76SSepherosa Ziehau
80179251f5eSSepherosa Ziehau if (nsegs >= txr->tx_wreg_nsegs) {
80279251f5eSSepherosa Ziehau IXGBE_WRITE_REG(&sc->hw, IXGBE_TDT(txr->tx_idx), idx);
80379251f5eSSepherosa Ziehau nsegs = 0;
80479251f5eSSepherosa Ziehau idx = -1;
80579251f5eSSepherosa Ziehau }
80679251f5eSSepherosa Ziehau
80779251f5eSSepherosa Ziehau ETHER_BPF_MTAP(ifp, m_head);
80879251f5eSSepherosa Ziehau }
80979251f5eSSepherosa Ziehau if (idx >= 0)
81079251f5eSSepherosa Ziehau IXGBE_WRITE_REG(&sc->hw, IXGBE_TDT(txr->tx_idx), idx);
81182db96e9SSepherosa Ziehau txr->tx_running = IX_TX_RUNNING;
81279251f5eSSepherosa Ziehau }
81379251f5eSSepherosa Ziehau
81479251f5eSSepherosa Ziehau static int
ix_ioctl(struct ifnet * ifp,u_long command,caddr_t data,struct ucred * cr)81579251f5eSSepherosa Ziehau ix_ioctl(struct ifnet *ifp, u_long command, caddr_t data, struct ucred *cr)
81679251f5eSSepherosa Ziehau {
81779251f5eSSepherosa Ziehau struct ix_softc *sc = ifp->if_softc;
81879251f5eSSepherosa Ziehau struct ifreq *ifr = (struct ifreq *) data;
81979251f5eSSepherosa Ziehau int error = 0, mask, reinit;
82079251f5eSSepherosa Ziehau
82179251f5eSSepherosa Ziehau ASSERT_IFNET_SERIALIZED_ALL(ifp);
82279251f5eSSepherosa Ziehau
82379251f5eSSepherosa Ziehau switch (command) {
82479251f5eSSepherosa Ziehau case SIOCSIFMTU:
82563d483cdSSepherosa Ziehau if (ifr->ifr_mtu > IX_MAX_MTU) {
82679251f5eSSepherosa Ziehau error = EINVAL;
82779251f5eSSepherosa Ziehau } else {
82879251f5eSSepherosa Ziehau ifp->if_mtu = ifr->ifr_mtu;
82963d483cdSSepherosa Ziehau sc->max_frame_size = ifp->if_mtu + IX_MTU_HDR;
83079251f5eSSepherosa Ziehau ix_init(sc);
83179251f5eSSepherosa Ziehau }
83279251f5eSSepherosa Ziehau break;
83379251f5eSSepherosa Ziehau
83479251f5eSSepherosa Ziehau case SIOCSIFFLAGS:
83579251f5eSSepherosa Ziehau if (ifp->if_flags & IFF_UP) {
83679251f5eSSepherosa Ziehau if (ifp->if_flags & IFF_RUNNING) {
83779251f5eSSepherosa Ziehau if ((ifp->if_flags ^ sc->if_flags) &
83879251f5eSSepherosa Ziehau (IFF_PROMISC | IFF_ALLMULTI))
83979251f5eSSepherosa Ziehau ix_set_promisc(sc);
84079251f5eSSepherosa Ziehau } else {
84179251f5eSSepherosa Ziehau ix_init(sc);
84279251f5eSSepherosa Ziehau }
84379251f5eSSepherosa Ziehau } else if (ifp->if_flags & IFF_RUNNING) {
84479251f5eSSepherosa Ziehau ix_stop(sc);
84579251f5eSSepherosa Ziehau }
84679251f5eSSepherosa Ziehau sc->if_flags = ifp->if_flags;
84779251f5eSSepherosa Ziehau break;
84879251f5eSSepherosa Ziehau
84979251f5eSSepherosa Ziehau case SIOCADDMULTI:
85079251f5eSSepherosa Ziehau case SIOCDELMULTI:
85179251f5eSSepherosa Ziehau if (ifp->if_flags & IFF_RUNNING) {
85279251f5eSSepherosa Ziehau ix_disable_intr(sc);
85379251f5eSSepherosa Ziehau ix_set_multi(sc);
8544a648aefSSepherosa Ziehau #ifdef IFPOLL_ENABLE
8554a648aefSSepherosa Ziehau if ((ifp->if_flags & IFF_NPOLLING) == 0)
8564a648aefSSepherosa Ziehau #endif
85779251f5eSSepherosa Ziehau ix_enable_intr(sc);
85879251f5eSSepherosa Ziehau }
85979251f5eSSepherosa Ziehau break;
86079251f5eSSepherosa Ziehau
86179251f5eSSepherosa Ziehau case SIOCSIFMEDIA:
86279251f5eSSepherosa Ziehau case SIOCGIFMEDIA:
86379251f5eSSepherosa Ziehau error = ifmedia_ioctl(ifp, ifr, &sc->media, command);
86479251f5eSSepherosa Ziehau break;
86579251f5eSSepherosa Ziehau
86679251f5eSSepherosa Ziehau case SIOCSIFCAP:
86779251f5eSSepherosa Ziehau reinit = 0;
86879251f5eSSepherosa Ziehau mask = ifr->ifr_reqcap ^ ifp->if_capenable;
86979251f5eSSepherosa Ziehau if (mask & IFCAP_RXCSUM) {
87079251f5eSSepherosa Ziehau ifp->if_capenable ^= IFCAP_RXCSUM;
87179251f5eSSepherosa Ziehau reinit = 1;
87279251f5eSSepherosa Ziehau }
87379251f5eSSepherosa Ziehau if (mask & IFCAP_VLAN_HWTAGGING) {
87479251f5eSSepherosa Ziehau ifp->if_capenable ^= IFCAP_VLAN_HWTAGGING;
87579251f5eSSepherosa Ziehau reinit = 1;
87679251f5eSSepherosa Ziehau }
87779251f5eSSepherosa Ziehau if (mask & IFCAP_TXCSUM) {
87879251f5eSSepherosa Ziehau ifp->if_capenable ^= IFCAP_TXCSUM;
87979251f5eSSepherosa Ziehau if (ifp->if_capenable & IFCAP_TXCSUM)
88079251f5eSSepherosa Ziehau ifp->if_hwassist |= CSUM_OFFLOAD;
88179251f5eSSepherosa Ziehau else
88279251f5eSSepherosa Ziehau ifp->if_hwassist &= ~CSUM_OFFLOAD;
88379251f5eSSepherosa Ziehau }
88479251f5eSSepherosa Ziehau if (mask & IFCAP_TSO) {
88579251f5eSSepherosa Ziehau ifp->if_capenable ^= IFCAP_TSO;
88679251f5eSSepherosa Ziehau if (ifp->if_capenable & IFCAP_TSO)
88779251f5eSSepherosa Ziehau ifp->if_hwassist |= CSUM_TSO;
88879251f5eSSepherosa Ziehau else
88979251f5eSSepherosa Ziehau ifp->if_hwassist &= ~CSUM_TSO;
89079251f5eSSepherosa Ziehau }
89179251f5eSSepherosa Ziehau if (mask & IFCAP_RSS)
89279251f5eSSepherosa Ziehau ifp->if_capenable ^= IFCAP_RSS;
89379251f5eSSepherosa Ziehau if (reinit && (ifp->if_flags & IFF_RUNNING))
89479251f5eSSepherosa Ziehau ix_init(sc);
89579251f5eSSepherosa Ziehau break;
89679251f5eSSepherosa Ziehau
89779251f5eSSepherosa Ziehau #if 0
89879251f5eSSepherosa Ziehau case SIOCGI2C:
89979251f5eSSepherosa Ziehau {
90079251f5eSSepherosa Ziehau struct ixgbe_i2c_req i2c;
90179251f5eSSepherosa Ziehau error = copyin(ifr->ifr_data, &i2c, sizeof(i2c));
90279251f5eSSepherosa Ziehau if (error)
90379251f5eSSepherosa Ziehau break;
90479251f5eSSepherosa Ziehau if ((i2c.dev_addr != 0xA0) || (i2c.dev_addr != 0xA2)){
90579251f5eSSepherosa Ziehau error = EINVAL;
90679251f5eSSepherosa Ziehau break;
90779251f5eSSepherosa Ziehau }
90879251f5eSSepherosa Ziehau hw->phy.ops.read_i2c_byte(hw, i2c.offset,
90979251f5eSSepherosa Ziehau i2c.dev_addr, i2c.data);
91079251f5eSSepherosa Ziehau error = copyout(&i2c, ifr->ifr_data, sizeof(i2c));
91179251f5eSSepherosa Ziehau break;
91279251f5eSSepherosa Ziehau }
91379251f5eSSepherosa Ziehau #endif
91479251f5eSSepherosa Ziehau
91579251f5eSSepherosa Ziehau default:
91679251f5eSSepherosa Ziehau error = ether_ioctl(ifp, command, data);
91779251f5eSSepherosa Ziehau break;
91879251f5eSSepherosa Ziehau }
91979251f5eSSepherosa Ziehau return error;
92079251f5eSSepherosa Ziehau }
92179251f5eSSepherosa Ziehau
92279251f5eSSepherosa Ziehau #define IXGBE_MHADD_MFS_SHIFT 16
92379251f5eSSepherosa Ziehau
92479251f5eSSepherosa Ziehau static void
ix_init(void * xsc)92579251f5eSSepherosa Ziehau ix_init(void *xsc)
92679251f5eSSepherosa Ziehau {
92779251f5eSSepherosa Ziehau struct ix_softc *sc = xsc;
92879251f5eSSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if;
92979251f5eSSepherosa Ziehau struct ixgbe_hw *hw = &sc->hw;
9306150453fSSepherosa Ziehau uint32_t rxctrl;
93179251f5eSSepherosa Ziehau int i, error;
9324a648aefSSepherosa Ziehau boolean_t polling;
93379251f5eSSepherosa Ziehau
93479251f5eSSepherosa Ziehau ASSERT_IFNET_SERIALIZED_ALL(ifp);
93579251f5eSSepherosa Ziehau
93679251f5eSSepherosa Ziehau ix_stop(sc);
93779251f5eSSepherosa Ziehau
938dd5ce676SSepherosa Ziehau if (sc->flags & IX_FLAG_FW_RECOVERY)
939dd5ce676SSepherosa Ziehau return;
940dd5ce676SSepherosa Ziehau
9414a648aefSSepherosa Ziehau polling = FALSE;
9424a648aefSSepherosa Ziehau #ifdef IFPOLL_ENABLE
9434a648aefSSepherosa Ziehau if (ifp->if_flags & IFF_NPOLLING)
9444a648aefSSepherosa Ziehau polling = TRUE;
9454a648aefSSepherosa Ziehau #endif
9464a648aefSSepherosa Ziehau
94779251f5eSSepherosa Ziehau /* Configure # of used RX/TX rings */
9484a648aefSSepherosa Ziehau ix_set_ring_inuse(sc, polling);
9493c37d13bSSepherosa Ziehau ifq_set_subq_divisor(&ifp->if_snd, sc->tx_ring_inuse);
95079251f5eSSepherosa Ziehau
95179251f5eSSepherosa Ziehau /* Get the latest mac address, User can use a LAA */
95279251f5eSSepherosa Ziehau bcopy(IF_LLADDR(ifp), hw->mac.addr, IXGBE_ETH_LENGTH_OF_ADDRESS);
95379251f5eSSepherosa Ziehau ixgbe_set_rar(hw, 0, hw->mac.addr, 0, 1);
95479251f5eSSepherosa Ziehau hw->addr_ctrl.rar_used_count = 1;
95579251f5eSSepherosa Ziehau
95679251f5eSSepherosa Ziehau /* Prepare transmit descriptors and buffers */
95779251f5eSSepherosa Ziehau for (i = 0; i < sc->tx_ring_inuse; ++i)
95879251f5eSSepherosa Ziehau ix_init_tx_ring(&sc->tx_rings[i]);
95979251f5eSSepherosa Ziehau
96079251f5eSSepherosa Ziehau ixgbe_init_hw(hw);
96179251f5eSSepherosa Ziehau ix_init_tx_unit(sc);
96279251f5eSSepherosa Ziehau
96379251f5eSSepherosa Ziehau /* Setup Multicast table */
96479251f5eSSepherosa Ziehau ix_set_multi(sc);
96579251f5eSSepherosa Ziehau
96679251f5eSSepherosa Ziehau /* Prepare receive descriptors and buffers */
96779251f5eSSepherosa Ziehau for (i = 0; i < sc->rx_ring_inuse; ++i) {
96879251f5eSSepherosa Ziehau error = ix_init_rx_ring(&sc->rx_rings[i]);
96979251f5eSSepherosa Ziehau if (error) {
97079251f5eSSepherosa Ziehau if_printf(ifp, "Could not initialize RX ring%d\n", i);
97179251f5eSSepherosa Ziehau ix_stop(sc);
97279251f5eSSepherosa Ziehau return;
97379251f5eSSepherosa Ziehau }
97479251f5eSSepherosa Ziehau }
97579251f5eSSepherosa Ziehau
97679251f5eSSepherosa Ziehau /* Configure RX settings */
9773c37d13bSSepherosa Ziehau ix_init_rx_unit(sc, polling);
97879251f5eSSepherosa Ziehau
9796150453fSSepherosa Ziehau /* Enable SDP & MSI-X interrupts based on adapter */
9806150453fSSepherosa Ziehau ix_config_gpie(sc);
98179251f5eSSepherosa Ziehau
98279251f5eSSepherosa Ziehau /* Set MTU size */
98379251f5eSSepherosa Ziehau if (ifp->if_mtu > ETHERMTU) {
98479251f5eSSepherosa Ziehau uint32_t mhadd;
98579251f5eSSepherosa Ziehau
98663d483cdSSepherosa Ziehau /* aka IXGBE_MAXFRS on 82599 and newer */
98779251f5eSSepherosa Ziehau mhadd = IXGBE_READ_REG(hw, IXGBE_MHADD);
98879251f5eSSepherosa Ziehau mhadd &= ~IXGBE_MHADD_MFS_MASK;
98979251f5eSSepherosa Ziehau mhadd |= sc->max_frame_size << IXGBE_MHADD_MFS_SHIFT;
99079251f5eSSepherosa Ziehau IXGBE_WRITE_REG(hw, IXGBE_MHADD, mhadd);
99179251f5eSSepherosa Ziehau }
99279251f5eSSepherosa Ziehau
99379251f5eSSepherosa Ziehau /*
99479251f5eSSepherosa Ziehau * Enable TX rings
99579251f5eSSepherosa Ziehau */
99679251f5eSSepherosa Ziehau for (i = 0; i < sc->tx_ring_inuse; ++i) {
99779251f5eSSepherosa Ziehau uint32_t txdctl;
99879251f5eSSepherosa Ziehau
99979251f5eSSepherosa Ziehau txdctl = IXGBE_READ_REG(hw, IXGBE_TXDCTL(i));
100079251f5eSSepherosa Ziehau txdctl |= IXGBE_TXDCTL_ENABLE;
100179251f5eSSepherosa Ziehau
100279251f5eSSepherosa Ziehau /*
100379251f5eSSepherosa Ziehau * Set WTHRESH to 0, since TX head write-back is used
100479251f5eSSepherosa Ziehau */
100579251f5eSSepherosa Ziehau txdctl &= ~(0x7f << 16);
100679251f5eSSepherosa Ziehau
100779251f5eSSepherosa Ziehau /*
100879251f5eSSepherosa Ziehau * When the internal queue falls below PTHRESH (32),
100979251f5eSSepherosa Ziehau * start prefetching as long as there are at least
101079251f5eSSepherosa Ziehau * HTHRESH (1) buffers ready. The values are taken
101179251f5eSSepherosa Ziehau * from the Intel linux driver 3.8.21.
101279251f5eSSepherosa Ziehau * Prefetching enables tx line rate even with 1 queue.
101379251f5eSSepherosa Ziehau */
101479251f5eSSepherosa Ziehau txdctl |= (32 << 0) | (1 << 8);
101579251f5eSSepherosa Ziehau IXGBE_WRITE_REG(hw, IXGBE_TXDCTL(i), txdctl);
101679251f5eSSepherosa Ziehau }
101779251f5eSSepherosa Ziehau
101879251f5eSSepherosa Ziehau /*
101979251f5eSSepherosa Ziehau * Enable RX rings
102079251f5eSSepherosa Ziehau */
102179251f5eSSepherosa Ziehau for (i = 0; i < sc->rx_ring_inuse; ++i) {
102279251f5eSSepherosa Ziehau uint32_t rxdctl;
102379251f5eSSepherosa Ziehau int k;
102479251f5eSSepherosa Ziehau
102579251f5eSSepherosa Ziehau rxdctl = IXGBE_READ_REG(hw, IXGBE_RXDCTL(i));
102679251f5eSSepherosa Ziehau if (hw->mac.type == ixgbe_mac_82598EB) {
102779251f5eSSepherosa Ziehau /*
102879251f5eSSepherosa Ziehau * PTHRESH = 21
102979251f5eSSepherosa Ziehau * HTHRESH = 4
103079251f5eSSepherosa Ziehau * WTHRESH = 8
103179251f5eSSepherosa Ziehau */
103279251f5eSSepherosa Ziehau rxdctl &= ~0x3FFFFF;
103379251f5eSSepherosa Ziehau rxdctl |= 0x080420;
103479251f5eSSepherosa Ziehau }
103579251f5eSSepherosa Ziehau rxdctl |= IXGBE_RXDCTL_ENABLE;
103679251f5eSSepherosa Ziehau IXGBE_WRITE_REG(hw, IXGBE_RXDCTL(i), rxdctl);
103779251f5eSSepherosa Ziehau for (k = 0; k < 10; ++k) {
103879251f5eSSepherosa Ziehau if (IXGBE_READ_REG(hw, IXGBE_RXDCTL(i)) &
103979251f5eSSepherosa Ziehau IXGBE_RXDCTL_ENABLE)
104079251f5eSSepherosa Ziehau break;
104179251f5eSSepherosa Ziehau else
104279251f5eSSepherosa Ziehau msec_delay(1);
104379251f5eSSepherosa Ziehau }
104479251f5eSSepherosa Ziehau wmb();
104579251f5eSSepherosa Ziehau IXGBE_WRITE_REG(hw, IXGBE_RDT(i),
104679251f5eSSepherosa Ziehau sc->rx_rings[0].rx_ndesc - 1);
104779251f5eSSepherosa Ziehau }
104879251f5eSSepherosa Ziehau
104979251f5eSSepherosa Ziehau /* Enable Receive engine */
105079251f5eSSepherosa Ziehau rxctrl = IXGBE_READ_REG(hw, IXGBE_RXCTRL);
105179251f5eSSepherosa Ziehau if (hw->mac.type == ixgbe_mac_82598EB)
105279251f5eSSepherosa Ziehau rxctrl |= IXGBE_RXCTRL_DMBYPS;
105379251f5eSSepherosa Ziehau rxctrl |= IXGBE_RXCTRL_RXEN;
105479251f5eSSepherosa Ziehau ixgbe_enable_rx_dma(hw, rxctrl);
105579251f5eSSepherosa Ziehau
1056189a0ff3SSepherosa Ziehau for (i = 0; i < sc->tx_ring_inuse; ++i) {
1057189a0ff3SSepherosa Ziehau const struct ix_tx_ring *txr = &sc->tx_rings[i];
1058189a0ff3SSepherosa Ziehau
1059189a0ff3SSepherosa Ziehau if (txr->tx_intr_vec >= 0) {
1060189a0ff3SSepherosa Ziehau ix_set_ivar(sc, i, txr->tx_intr_vec, 1);
10613c37d13bSSepherosa Ziehau } else if (!polling) {
1062189a0ff3SSepherosa Ziehau /*
1063189a0ff3SSepherosa Ziehau * Unconfigured TX interrupt vector could only
1064189a0ff3SSepherosa Ziehau * happen for MSI-X.
1065189a0ff3SSepherosa Ziehau */
1066189a0ff3SSepherosa Ziehau KASSERT(sc->intr_type == PCI_INTR_TYPE_MSIX,
1067189a0ff3SSepherosa Ziehau ("TX intr vector is not set"));
1068189a0ff3SSepherosa Ziehau if (bootverbose)
1069189a0ff3SSepherosa Ziehau if_printf(ifp, "IVAR skips TX ring %d\n", i);
1070189a0ff3SSepherosa Ziehau }
1071189a0ff3SSepherosa Ziehau }
1072189a0ff3SSepherosa Ziehau for (i = 0; i < sc->rx_ring_inuse; ++i) {
1073189a0ff3SSepherosa Ziehau const struct ix_rx_ring *rxr = &sc->rx_rings[i];
1074189a0ff3SSepherosa Ziehau
10753c37d13bSSepherosa Ziehau if (polling && rxr->rx_intr_vec < 0)
10763c37d13bSSepherosa Ziehau continue;
10773c37d13bSSepherosa Ziehau
1078189a0ff3SSepherosa Ziehau KKASSERT(rxr->rx_intr_vec >= 0);
1079189a0ff3SSepherosa Ziehau ix_set_ivar(sc, i, rxr->rx_intr_vec, 0);
1080189a0ff3SSepherosa Ziehau if (rxr->rx_txr != NULL) {
1081189a0ff3SSepherosa Ziehau /*
1082189a0ff3SSepherosa Ziehau * Piggyback the TX ring interrupt onto the RX
1083189a0ff3SSepherosa Ziehau * ring interrupt vector.
1084189a0ff3SSepherosa Ziehau */
1085189a0ff3SSepherosa Ziehau KASSERT(rxr->rx_txr->tx_intr_vec < 0,
1086189a0ff3SSepherosa Ziehau ("piggybacked TX ring configured intr vector"));
10873c37d13bSSepherosa Ziehau ix_set_ivar(sc, rxr->rx_txr->tx_idx,
10883c37d13bSSepherosa Ziehau rxr->rx_intr_vec, 1);
1089189a0ff3SSepherosa Ziehau if (bootverbose) {
1090189a0ff3SSepherosa Ziehau if_printf(ifp, "IVAR RX ring %d piggybacks "
1091189a0ff3SSepherosa Ziehau "TX ring %u\n", i, rxr->rx_txr->tx_idx);
1092189a0ff3SSepherosa Ziehau }
1093189a0ff3SSepherosa Ziehau }
1094189a0ff3SSepherosa Ziehau }
109579251f5eSSepherosa Ziehau if (sc->intr_type == PCI_INTR_TYPE_MSIX) {
1096189a0ff3SSepherosa Ziehau /* Set up status MSI-X vector; it is using fixed entry 1 */
1097189a0ff3SSepherosa Ziehau ix_set_ivar(sc, 1, sc->sts_msix_vec, -1);
1098189a0ff3SSepherosa Ziehau
1099189a0ff3SSepherosa Ziehau /* Set up auto-mask for TX and RX rings */
1100189a0ff3SSepherosa Ziehau if (hw->mac.type == ixgbe_mac_82598EB) {
1101189a0ff3SSepherosa Ziehau IXGBE_WRITE_REG(hw, IXGBE_EIAM, IXGBE_EIMS_RTX_QUEUE);
1102189a0ff3SSepherosa Ziehau } else {
110379251f5eSSepherosa Ziehau IXGBE_WRITE_REG(hw, IXGBE_EIAM_EX(0), 0xFFFFFFFF);
110479251f5eSSepherosa Ziehau IXGBE_WRITE_REG(hw, IXGBE_EIAM_EX(1), 0xFFFFFFFF);
110579251f5eSSepherosa Ziehau }
110679251f5eSSepherosa Ziehau } else {
1107189a0ff3SSepherosa Ziehau IXGBE_WRITE_REG(hw, IXGBE_EIAM, IXGBE_EIMS_RTX_QUEUE);
110879251f5eSSepherosa Ziehau }
1109189a0ff3SSepherosa Ziehau for (i = 0; i < sc->intr_cnt; ++i)
1110189a0ff3SSepherosa Ziehau ix_set_eitr(sc, i, sc->intr_data[i].intr_rate);
111179251f5eSSepherosa Ziehau
111279251f5eSSepherosa Ziehau /*
111379251f5eSSepherosa Ziehau * Check on any SFP devices that need to be kick-started
111479251f5eSSepherosa Ziehau */
111579251f5eSSepherosa Ziehau if (hw->phy.type == ixgbe_phy_none) {
111679251f5eSSepherosa Ziehau error = hw->phy.ops.identify(hw);
111779251f5eSSepherosa Ziehau if (error == IXGBE_ERR_SFP_NOT_SUPPORTED) {
111879251f5eSSepherosa Ziehau if_printf(ifp,
111979251f5eSSepherosa Ziehau "Unsupported SFP+ module type was detected.\n");
112079251f5eSSepherosa Ziehau /* XXX stop */
112179251f5eSSepherosa Ziehau return;
112279251f5eSSepherosa Ziehau }
112379251f5eSSepherosa Ziehau }
112479251f5eSSepherosa Ziehau
112579251f5eSSepherosa Ziehau /* Config/Enable Link */
112679251f5eSSepherosa Ziehau ix_config_link(sc);
112779251f5eSSepherosa Ziehau
112863d483cdSSepherosa Ziehau /* Hardware Packet Buffer & Flow Control setup */
112963d483cdSSepherosa Ziehau ix_config_flowctrl(sc);
113079251f5eSSepherosa Ziehau
113179251f5eSSepherosa Ziehau /* Initialize the FC settings */
113279251f5eSSepherosa Ziehau ixgbe_start_hw(hw);
113379251f5eSSepherosa Ziehau
113463d483cdSSepherosa Ziehau /* Set up VLAN support and filter */
113563d483cdSSepherosa Ziehau ix_set_vlan(sc);
113663d483cdSSepherosa Ziehau
113763d483cdSSepherosa Ziehau /* Setup DMA Coalescing */
113863d483cdSSepherosa Ziehau ix_config_dmac(sc);
113963d483cdSSepherosa Ziehau
11404a648aefSSepherosa Ziehau /*
11414a648aefSSepherosa Ziehau * Only enable interrupts if we are not polling, make sure
11424a648aefSSepherosa Ziehau * they are off otherwise.
11434a648aefSSepherosa Ziehau */
11444a648aefSSepherosa Ziehau if (polling)
11454a648aefSSepherosa Ziehau ix_disable_intr(sc);
11464a648aefSSepherosa Ziehau else
114779251f5eSSepherosa Ziehau ix_enable_intr(sc);
114879251f5eSSepherosa Ziehau
114979251f5eSSepherosa Ziehau ifp->if_flags |= IFF_RUNNING;
115079251f5eSSepherosa Ziehau for (i = 0; i < sc->tx_ring_inuse; ++i) {
115182db96e9SSepherosa Ziehau struct ix_tx_ring *txr = &sc->tx_rings[i];
115282db96e9SSepherosa Ziehau
115382db96e9SSepherosa Ziehau ifsq_clr_oactive(txr->tx_ifsq);
115482db96e9SSepherosa Ziehau ifsq_watchdog_start(&txr->tx_watchdog);
115582db96e9SSepherosa Ziehau
115682db96e9SSepherosa Ziehau if (!polling) {
115782db96e9SSepherosa Ziehau callout_reset_bycpu(&txr->tx_gc_timer, 1,
115882db96e9SSepherosa Ziehau ix_txgc_timer, txr, txr->tx_intr_cpuid);
115982db96e9SSepherosa Ziehau }
116079251f5eSSepherosa Ziehau }
116179251f5eSSepherosa Ziehau
1162dd5ce676SSepherosa Ziehau sc->timer_cpuid = ix_get_timer_cpuid(sc, polling);
116379251f5eSSepherosa Ziehau callout_reset_bycpu(&sc->timer, hz, ix_timer, sc, sc->timer_cpuid);
116479251f5eSSepherosa Ziehau }
116579251f5eSSepherosa Ziehau
116679251f5eSSepherosa Ziehau static void
ix_intr(void * xsc)116779251f5eSSepherosa Ziehau ix_intr(void *xsc)
116879251f5eSSepherosa Ziehau {
116979251f5eSSepherosa Ziehau struct ix_softc *sc = xsc;
117079251f5eSSepherosa Ziehau struct ixgbe_hw *hw = &sc->hw;
117179251f5eSSepherosa Ziehau uint32_t eicr;
117279251f5eSSepherosa Ziehau
117379251f5eSSepherosa Ziehau ASSERT_SERIALIZED(&sc->main_serialize);
117479251f5eSSepherosa Ziehau
117579251f5eSSepherosa Ziehau eicr = IXGBE_READ_REG(hw, IXGBE_EICR);
117679251f5eSSepherosa Ziehau if (eicr == 0) {
117779251f5eSSepherosa Ziehau IXGBE_WRITE_REG(hw, IXGBE_EIMS, sc->intr_mask);
117879251f5eSSepherosa Ziehau return;
117979251f5eSSepherosa Ziehau }
118079251f5eSSepherosa Ziehau
118179251f5eSSepherosa Ziehau if (eicr & IX_RX0_INTR_MASK) {
118279251f5eSSepherosa Ziehau struct ix_rx_ring *rxr = &sc->rx_rings[0];
118379251f5eSSepherosa Ziehau
118479251f5eSSepherosa Ziehau lwkt_serialize_enter(&rxr->rx_serialize);
11854a648aefSSepherosa Ziehau ix_rxeof(rxr, -1);
118679251f5eSSepherosa Ziehau lwkt_serialize_exit(&rxr->rx_serialize);
118779251f5eSSepherosa Ziehau }
118879251f5eSSepherosa Ziehau if (eicr & IX_RX1_INTR_MASK) {
118979251f5eSSepherosa Ziehau struct ix_rx_ring *rxr;
119079251f5eSSepherosa Ziehau
119179251f5eSSepherosa Ziehau KKASSERT(sc->rx_ring_inuse == IX_MIN_RXRING_RSS);
119279251f5eSSepherosa Ziehau rxr = &sc->rx_rings[1];
119379251f5eSSepherosa Ziehau
119479251f5eSSepherosa Ziehau lwkt_serialize_enter(&rxr->rx_serialize);
11954a648aefSSepherosa Ziehau ix_rxeof(rxr, -1);
119679251f5eSSepherosa Ziehau lwkt_serialize_exit(&rxr->rx_serialize);
119779251f5eSSepherosa Ziehau }
119879251f5eSSepherosa Ziehau
119979251f5eSSepherosa Ziehau if (eicr & IX_TX_INTR_MASK) {
120079251f5eSSepherosa Ziehau struct ix_tx_ring *txr = &sc->tx_rings[0];
120179251f5eSSepherosa Ziehau
120279251f5eSSepherosa Ziehau lwkt_serialize_enter(&txr->tx_serialize);
120382db96e9SSepherosa Ziehau ix_tx_intr(txr, *(txr->tx_hdr));
120479251f5eSSepherosa Ziehau lwkt_serialize_exit(&txr->tx_serialize);
120579251f5eSSepherosa Ziehau }
120679251f5eSSepherosa Ziehau
1207189a0ff3SSepherosa Ziehau if (__predict_false(eicr & IX_EICR_STATUS))
1208189a0ff3SSepherosa Ziehau ix_intr_status(sc, eicr);
120979251f5eSSepherosa Ziehau
121079251f5eSSepherosa Ziehau IXGBE_WRITE_REG(hw, IXGBE_EIMS, sc->intr_mask);
121179251f5eSSepherosa Ziehau }
121279251f5eSSepherosa Ziehau
121379251f5eSSepherosa Ziehau static void
ix_intr_82598(void * xsc)12146150453fSSepherosa Ziehau ix_intr_82598(void *xsc)
12156150453fSSepherosa Ziehau {
12166150453fSSepherosa Ziehau struct ix_softc *sc = xsc;
12176150453fSSepherosa Ziehau
12186150453fSSepherosa Ziehau ASSERT_SERIALIZED(&sc->main_serialize);
12196150453fSSepherosa Ziehau
12206150453fSSepherosa Ziehau /* Software workaround for 82598 errata #26 */
12216150453fSSepherosa Ziehau IXGBE_WRITE_REG(&sc->hw, IXGBE_EIMC, IXGBE_IRQ_CLEAR_MASK);
12226150453fSSepherosa Ziehau
12236150453fSSepherosa Ziehau ix_intr(sc);
12246150453fSSepherosa Ziehau }
12256150453fSSepherosa Ziehau
12266150453fSSepherosa Ziehau static void
ix_media_status(struct ifnet * ifp,struct ifmediareq * ifmr)122779251f5eSSepherosa Ziehau ix_media_status(struct ifnet *ifp, struct ifmediareq *ifmr)
122879251f5eSSepherosa Ziehau {
122979251f5eSSepherosa Ziehau struct ix_softc *sc = ifp->if_softc;
123063d483cdSSepherosa Ziehau struct ifmedia *ifm = &sc->media;
123163d483cdSSepherosa Ziehau int layer;
1232dd5ce676SSepherosa Ziehau boolean_t link_active;
123379251f5eSSepherosa Ziehau
1234dd5ce676SSepherosa Ziehau if (sc->flags & IX_FLAG_FW_RECOVERY) {
1235dd5ce676SSepherosa Ziehau link_active = FALSE;
1236dd5ce676SSepherosa Ziehau } else {
123779251f5eSSepherosa Ziehau ix_update_link_status(sc);
1238dd5ce676SSepherosa Ziehau link_active = sc->link_active;
1239dd5ce676SSepherosa Ziehau }
124079251f5eSSepherosa Ziehau
124179251f5eSSepherosa Ziehau ifmr->ifm_status = IFM_AVALID;
124279251f5eSSepherosa Ziehau ifmr->ifm_active = IFM_ETHER;
124379251f5eSSepherosa Ziehau
1244dd5ce676SSepherosa Ziehau if (!link_active) {
124563d483cdSSepherosa Ziehau if (IFM_SUBTYPE(ifm->ifm_media) != IFM_AUTO)
124663d483cdSSepherosa Ziehau ifmr->ifm_active |= ifm->ifm_media;
124763d483cdSSepherosa Ziehau else
12480d60c5c8SSepherosa Ziehau ifmr->ifm_active |= IFM_NONE;
124979251f5eSSepherosa Ziehau return;
12500d60c5c8SSepherosa Ziehau }
125179251f5eSSepherosa Ziehau ifmr->ifm_status |= IFM_ACTIVE;
125279251f5eSSepherosa Ziehau
12536150453fSSepherosa Ziehau layer = sc->phy_layer;
125463d483cdSSepherosa Ziehau
125563d483cdSSepherosa Ziehau if ((layer & IXGBE_PHYSICAL_LAYER_10GBASE_T) ||
125663d483cdSSepherosa Ziehau (layer & IXGBE_PHYSICAL_LAYER_1000BASE_T) ||
12576150453fSSepherosa Ziehau (layer & IXGBE_PHYSICAL_LAYER_100BASE_TX) ||
12586150453fSSepherosa Ziehau (layer & IXGBE_PHYSICAL_LAYER_10BASE_T)) {
125979251f5eSSepherosa Ziehau switch (sc->link_speed) {
126063d483cdSSepherosa Ziehau case IXGBE_LINK_SPEED_10GB_FULL:
126163d483cdSSepherosa Ziehau ifmr->ifm_active |= IFM_10G_T | IFM_FDX;
126263d483cdSSepherosa Ziehau break;
126363d483cdSSepherosa Ziehau case IXGBE_LINK_SPEED_1GB_FULL:
126463d483cdSSepherosa Ziehau ifmr->ifm_active |= IFM_1000_T | IFM_FDX;
126563d483cdSSepherosa Ziehau break;
126679251f5eSSepherosa Ziehau case IXGBE_LINK_SPEED_100_FULL:
126779251f5eSSepherosa Ziehau ifmr->ifm_active |= IFM_100_TX | IFM_FDX;
126879251f5eSSepherosa Ziehau break;
12696150453fSSepherosa Ziehau case IXGBE_LINK_SPEED_10_FULL:
12706150453fSSepherosa Ziehau ifmr->ifm_active |= IFM_10_T | IFM_FDX;
12716150453fSSepherosa Ziehau break;
127263d483cdSSepherosa Ziehau }
127363d483cdSSepherosa Ziehau } else if ((layer & IXGBE_PHYSICAL_LAYER_SFP_PLUS_CU) ||
127463d483cdSSepherosa Ziehau (layer & IXGBE_PHYSICAL_LAYER_SFP_ACTIVE_DA)) {
127563d483cdSSepherosa Ziehau switch (sc->link_speed) {
127663d483cdSSepherosa Ziehau case IXGBE_LINK_SPEED_10GB_FULL:
127763d483cdSSepherosa Ziehau ifmr->ifm_active |= IFM_10G_TWINAX | IFM_FDX;
127863d483cdSSepherosa Ziehau break;
127963d483cdSSepherosa Ziehau }
128063d483cdSSepherosa Ziehau } else if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_LR) {
128163d483cdSSepherosa Ziehau switch (sc->link_speed) {
128263d483cdSSepherosa Ziehau case IXGBE_LINK_SPEED_10GB_FULL:
128363d483cdSSepherosa Ziehau ifmr->ifm_active |= IFM_10G_LR | IFM_FDX;
128463d483cdSSepherosa Ziehau break;
128563d483cdSSepherosa Ziehau case IXGBE_LINK_SPEED_1GB_FULL:
128663d483cdSSepherosa Ziehau ifmr->ifm_active |= IFM_1000_LX | IFM_FDX;
128763d483cdSSepherosa Ziehau break;
128863d483cdSSepherosa Ziehau }
128963d483cdSSepherosa Ziehau } else if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_LRM) {
129063d483cdSSepherosa Ziehau switch (sc->link_speed) {
129163d483cdSSepherosa Ziehau case IXGBE_LINK_SPEED_10GB_FULL:
129263d483cdSSepherosa Ziehau ifmr->ifm_active |= IFM_10G_LRM | IFM_FDX;
129363d483cdSSepherosa Ziehau break;
129463d483cdSSepherosa Ziehau case IXGBE_LINK_SPEED_1GB_FULL:
129563d483cdSSepherosa Ziehau ifmr->ifm_active |= IFM_1000_LX | IFM_FDX;
129663d483cdSSepherosa Ziehau break;
129763d483cdSSepherosa Ziehau }
129863d483cdSSepherosa Ziehau } else if ((layer & IXGBE_PHYSICAL_LAYER_10GBASE_SR) ||
129963d483cdSSepherosa Ziehau (layer & IXGBE_PHYSICAL_LAYER_1000BASE_SX)) {
130063d483cdSSepherosa Ziehau switch (sc->link_speed) {
130163d483cdSSepherosa Ziehau case IXGBE_LINK_SPEED_10GB_FULL:
130263d483cdSSepherosa Ziehau ifmr->ifm_active |= IFM_10G_SR | IFM_FDX;
130363d483cdSSepherosa Ziehau break;
130479251f5eSSepherosa Ziehau case IXGBE_LINK_SPEED_1GB_FULL:
130579251f5eSSepherosa Ziehau ifmr->ifm_active |= IFM_1000_SX | IFM_FDX;
130679251f5eSSepherosa Ziehau break;
130763d483cdSSepherosa Ziehau }
130863d483cdSSepherosa Ziehau } else if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_CX4) {
130963d483cdSSepherosa Ziehau switch (sc->link_speed) {
131079251f5eSSepherosa Ziehau case IXGBE_LINK_SPEED_10GB_FULL:
131163d483cdSSepherosa Ziehau ifmr->ifm_active |= IFM_10G_CX4 | IFM_FDX;
131279251f5eSSepherosa Ziehau break;
131363d483cdSSepherosa Ziehau }
131463d483cdSSepherosa Ziehau } else if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_KR) {
131563d483cdSSepherosa Ziehau /*
131663d483cdSSepherosa Ziehau * XXX: These need to use the proper media types once
131763d483cdSSepherosa Ziehau * they're added.
131863d483cdSSepherosa Ziehau */
131963d483cdSSepherosa Ziehau switch (sc->link_speed) {
132063d483cdSSepherosa Ziehau case IXGBE_LINK_SPEED_10GB_FULL:
132163d483cdSSepherosa Ziehau ifmr->ifm_active |= IFM_10G_SR | IFM_FDX;
132263d483cdSSepherosa Ziehau break;
132363d483cdSSepherosa Ziehau case IXGBE_LINK_SPEED_2_5GB_FULL:
132463d483cdSSepherosa Ziehau ifmr->ifm_active |= IFM_2500_SX | IFM_FDX;
132563d483cdSSepherosa Ziehau break;
132663d483cdSSepherosa Ziehau case IXGBE_LINK_SPEED_1GB_FULL:
132763d483cdSSepherosa Ziehau ifmr->ifm_active |= IFM_1000_CX | IFM_FDX;
132863d483cdSSepherosa Ziehau break;
132963d483cdSSepherosa Ziehau }
133063d483cdSSepherosa Ziehau } else if ((layer & IXGBE_PHYSICAL_LAYER_10GBASE_KX4) ||
13316150453fSSepherosa Ziehau (layer & IXGBE_PHYSICAL_LAYER_2500BASE_KX) ||
133263d483cdSSepherosa Ziehau (layer & IXGBE_PHYSICAL_LAYER_1000BASE_KX)) {
133363d483cdSSepherosa Ziehau /*
133463d483cdSSepherosa Ziehau * XXX: These need to use the proper media types once
133563d483cdSSepherosa Ziehau * they're added.
133663d483cdSSepherosa Ziehau */
133763d483cdSSepherosa Ziehau switch (sc->link_speed) {
133863d483cdSSepherosa Ziehau case IXGBE_LINK_SPEED_10GB_FULL:
133963d483cdSSepherosa Ziehau ifmr->ifm_active |= IFM_10G_CX4 | IFM_FDX;
134063d483cdSSepherosa Ziehau break;
134163d483cdSSepherosa Ziehau case IXGBE_LINK_SPEED_2_5GB_FULL:
134263d483cdSSepherosa Ziehau ifmr->ifm_active |= IFM_2500_SX | IFM_FDX;
134363d483cdSSepherosa Ziehau break;
134463d483cdSSepherosa Ziehau case IXGBE_LINK_SPEED_1GB_FULL:
134563d483cdSSepherosa Ziehau ifmr->ifm_active |= IFM_1000_CX | IFM_FDX;
134663d483cdSSepherosa Ziehau break;
134763d483cdSSepherosa Ziehau }
1348060fa21cSSepherosa Ziehau }
1349060fa21cSSepherosa Ziehau
135063d483cdSSepherosa Ziehau /* If nothing is recognized... */
135163d483cdSSepherosa Ziehau if (IFM_SUBTYPE(ifmr->ifm_active) == 0)
135263d483cdSSepherosa Ziehau ifmr->ifm_active |= IFM_NONE;
135363d483cdSSepherosa Ziehau
135463d483cdSSepherosa Ziehau if (sc->ifm_media & IFM_ETH_FORCEPAUSE)
135563d483cdSSepherosa Ziehau ifmr->ifm_active |= (sc->ifm_media & IFM_ETH_FCMASK);
1356060fa21cSSepherosa Ziehau
1357060fa21cSSepherosa Ziehau switch (sc->hw.fc.current_mode) {
1358060fa21cSSepherosa Ziehau case ixgbe_fc_full:
1359060fa21cSSepherosa Ziehau ifmr->ifm_active |= IFM_ETH_RXPAUSE | IFM_ETH_TXPAUSE;
1360060fa21cSSepherosa Ziehau break;
1361060fa21cSSepherosa Ziehau case ixgbe_fc_rx_pause:
1362060fa21cSSepherosa Ziehau ifmr->ifm_active |= IFM_ETH_RXPAUSE;
1363060fa21cSSepherosa Ziehau break;
1364060fa21cSSepherosa Ziehau case ixgbe_fc_tx_pause:
1365060fa21cSSepherosa Ziehau ifmr->ifm_active |= IFM_ETH_TXPAUSE;
1366060fa21cSSepherosa Ziehau break;
1367060fa21cSSepherosa Ziehau default:
13680d60c5c8SSepherosa Ziehau break;
136979251f5eSSepherosa Ziehau }
137079251f5eSSepherosa Ziehau }
137179251f5eSSepherosa Ziehau
137279251f5eSSepherosa Ziehau static int
ix_media_change(struct ifnet * ifp)137379251f5eSSepherosa Ziehau ix_media_change(struct ifnet *ifp)
137479251f5eSSepherosa Ziehau {
137579251f5eSSepherosa Ziehau struct ix_softc *sc = ifp->if_softc;
137679251f5eSSepherosa Ziehau struct ifmedia *ifm = &sc->media;
137763d483cdSSepherosa Ziehau struct ixgbe_hw *hw = &sc->hw;
137879251f5eSSepherosa Ziehau
137979251f5eSSepherosa Ziehau if (IFM_TYPE(ifm->ifm_media) != IFM_ETHER)
138063d483cdSSepherosa Ziehau return (EINVAL);
138163d483cdSSepherosa Ziehau
138263d483cdSSepherosa Ziehau if (hw->phy.media_type == ixgbe_media_type_backplane ||
138363d483cdSSepherosa Ziehau hw->mac.ops.setup_link == NULL) {
138463d483cdSSepherosa Ziehau if ((ifm->ifm_media ^ sc->ifm_media) & IFM_ETH_FCMASK) {
138563d483cdSSepherosa Ziehau /* Only flow control setting changes are allowed */
138663d483cdSSepherosa Ziehau return (EOPNOTSUPP);
138763d483cdSSepherosa Ziehau }
138863d483cdSSepherosa Ziehau }
138979251f5eSSepherosa Ziehau
139079251f5eSSepherosa Ziehau switch (IFM_SUBTYPE(ifm->ifm_media)) {
139179251f5eSSepherosa Ziehau case IFM_AUTO:
139263d483cdSSepherosa Ziehau sc->advspeed = IXGBE_LINK_SPEED_UNKNOWN;
139379251f5eSSepherosa Ziehau break;
139463d483cdSSepherosa Ziehau
139563d483cdSSepherosa Ziehau case IFM_10G_T:
139663d483cdSSepherosa Ziehau case IFM_10G_LRM:
139763d483cdSSepherosa Ziehau case IFM_10G_SR: /* XXX also KR */
139863d483cdSSepherosa Ziehau case IFM_10G_LR:
139963d483cdSSepherosa Ziehau case IFM_10G_CX4: /* XXX also KX4 */
140063d483cdSSepherosa Ziehau case IFM_10G_TWINAX:
140163d483cdSSepherosa Ziehau sc->advspeed = IXGBE_LINK_SPEED_10GB_FULL;
140263d483cdSSepherosa Ziehau break;
140363d483cdSSepherosa Ziehau
140463d483cdSSepherosa Ziehau case IFM_1000_T:
140563d483cdSSepherosa Ziehau case IFM_1000_LX:
140663d483cdSSepherosa Ziehau case IFM_1000_SX:
140763d483cdSSepherosa Ziehau case IFM_1000_CX: /* XXX is KX */
140863d483cdSSepherosa Ziehau sc->advspeed = IXGBE_LINK_SPEED_1GB_FULL;
140963d483cdSSepherosa Ziehau break;
141063d483cdSSepherosa Ziehau
141163d483cdSSepherosa Ziehau case IFM_100_TX:
141263d483cdSSepherosa Ziehau sc->advspeed = IXGBE_LINK_SPEED_100_FULL;
141363d483cdSSepherosa Ziehau break;
141463d483cdSSepherosa Ziehau
141579251f5eSSepherosa Ziehau default:
141663d483cdSSepherosa Ziehau if (bootverbose) {
141763d483cdSSepherosa Ziehau if_printf(ifp, "Invalid media type %d!\n",
141863d483cdSSepherosa Ziehau ifm->ifm_media);
141963d483cdSSepherosa Ziehau }
142079251f5eSSepherosa Ziehau return EINVAL;
142179251f5eSSepherosa Ziehau }
142263d483cdSSepherosa Ziehau sc->ifm_media = ifm->ifm_media;
1423060fa21cSSepherosa Ziehau
142463d483cdSSepherosa Ziehau #if 0
142563d483cdSSepherosa Ziehau if (hw->mac.ops.setup_link != NULL) {
142663d483cdSSepherosa Ziehau hw->mac.autotry_restart = TRUE;
142763d483cdSSepherosa Ziehau hw->mac.ops.setup_link(hw, sc->advspeed, TRUE);
142863d483cdSSepherosa Ziehau }
142963d483cdSSepherosa Ziehau #else
1430060fa21cSSepherosa Ziehau if (ifp->if_flags & IFF_RUNNING)
1431060fa21cSSepherosa Ziehau ix_init(sc);
143263d483cdSSepherosa Ziehau #endif
143379251f5eSSepherosa Ziehau return 0;
143479251f5eSSepherosa Ziehau }
143579251f5eSSepherosa Ziehau
143679251f5eSSepherosa Ziehau static __inline int
ix_tso_pullup(struct mbuf ** mp)143779251f5eSSepherosa Ziehau ix_tso_pullup(struct mbuf **mp)
143879251f5eSSepherosa Ziehau {
143979251f5eSSepherosa Ziehau int hoff, iphlen, thoff;
144079251f5eSSepherosa Ziehau struct mbuf *m;
144179251f5eSSepherosa Ziehau
144279251f5eSSepherosa Ziehau m = *mp;
144379251f5eSSepherosa Ziehau KASSERT(M_WRITABLE(m), ("TSO mbuf not writable"));
144479251f5eSSepherosa Ziehau
144579251f5eSSepherosa Ziehau iphlen = m->m_pkthdr.csum_iphlen;
144679251f5eSSepherosa Ziehau thoff = m->m_pkthdr.csum_thlen;
144779251f5eSSepherosa Ziehau hoff = m->m_pkthdr.csum_lhlen;
144879251f5eSSepherosa Ziehau
144979251f5eSSepherosa Ziehau KASSERT(iphlen > 0, ("invalid ip hlen"));
145079251f5eSSepherosa Ziehau KASSERT(thoff > 0, ("invalid tcp hlen"));
145179251f5eSSepherosa Ziehau KASSERT(hoff > 0, ("invalid ether hlen"));
145279251f5eSSepherosa Ziehau
145379251f5eSSepherosa Ziehau if (__predict_false(m->m_len < hoff + iphlen + thoff)) {
145479251f5eSSepherosa Ziehau m = m_pullup(m, hoff + iphlen + thoff);
145579251f5eSSepherosa Ziehau if (m == NULL) {
145679251f5eSSepherosa Ziehau *mp = NULL;
145779251f5eSSepherosa Ziehau return ENOBUFS;
145879251f5eSSepherosa Ziehau }
145979251f5eSSepherosa Ziehau *mp = m;
146079251f5eSSepherosa Ziehau }
146179251f5eSSepherosa Ziehau return 0;
146279251f5eSSepherosa Ziehau }
146379251f5eSSepherosa Ziehau
146479251f5eSSepherosa Ziehau static int
ix_encap(struct ix_tx_ring * txr,struct mbuf ** m_headp,uint16_t * segs_used,int * idx)146579251f5eSSepherosa Ziehau ix_encap(struct ix_tx_ring *txr, struct mbuf **m_headp,
146679251f5eSSepherosa Ziehau uint16_t *segs_used, int *idx)
146779251f5eSSepherosa Ziehau {
146879251f5eSSepherosa Ziehau uint32_t olinfo_status = 0, cmd_type_len, cmd_rs = 0;
146979251f5eSSepherosa Ziehau int i, j, error, nsegs, first, maxsegs;
147079251f5eSSepherosa Ziehau struct mbuf *m_head = *m_headp;
147179251f5eSSepherosa Ziehau bus_dma_segment_t segs[IX_MAX_SCATTER];
147279251f5eSSepherosa Ziehau bus_dmamap_t map;
147379251f5eSSepherosa Ziehau struct ix_tx_buf *txbuf;
147479251f5eSSepherosa Ziehau union ixgbe_adv_tx_desc *txd = NULL;
147579251f5eSSepherosa Ziehau
147679251f5eSSepherosa Ziehau if (m_head->m_pkthdr.csum_flags & CSUM_TSO) {
147779251f5eSSepherosa Ziehau error = ix_tso_pullup(m_headp);
147879251f5eSSepherosa Ziehau if (__predict_false(error))
147979251f5eSSepherosa Ziehau return error;
148079251f5eSSepherosa Ziehau m_head = *m_headp;
148179251f5eSSepherosa Ziehau }
148279251f5eSSepherosa Ziehau
148379251f5eSSepherosa Ziehau /* Basic descriptor defines */
148479251f5eSSepherosa Ziehau cmd_type_len = (IXGBE_ADVTXD_DTYP_DATA |
148579251f5eSSepherosa Ziehau IXGBE_ADVTXD_DCMD_IFCS | IXGBE_ADVTXD_DCMD_DEXT);
148679251f5eSSepherosa Ziehau
148779251f5eSSepherosa Ziehau if (m_head->m_flags & M_VLANTAG)
148879251f5eSSepherosa Ziehau cmd_type_len |= IXGBE_ADVTXD_DCMD_VLE;
148979251f5eSSepherosa Ziehau
149079251f5eSSepherosa Ziehau /*
149179251f5eSSepherosa Ziehau * Important to capture the first descriptor
149279251f5eSSepherosa Ziehau * used because it will contain the index of
149379251f5eSSepherosa Ziehau * the one we tell the hardware to report back
149479251f5eSSepherosa Ziehau */
149579251f5eSSepherosa Ziehau first = txr->tx_next_avail;
149679251f5eSSepherosa Ziehau txbuf = &txr->tx_buf[first];
149779251f5eSSepherosa Ziehau map = txbuf->map;
149879251f5eSSepherosa Ziehau
149979251f5eSSepherosa Ziehau /*
150079251f5eSSepherosa Ziehau * Map the packet for DMA.
150179251f5eSSepherosa Ziehau */
150279251f5eSSepherosa Ziehau maxsegs = txr->tx_avail - IX_TX_RESERVED;
150379251f5eSSepherosa Ziehau if (maxsegs > IX_MAX_SCATTER)
150479251f5eSSepherosa Ziehau maxsegs = IX_MAX_SCATTER;
150579251f5eSSepherosa Ziehau
150679251f5eSSepherosa Ziehau error = bus_dmamap_load_mbuf_defrag(txr->tx_tag, map, m_headp,
150779251f5eSSepherosa Ziehau segs, maxsegs, &nsegs, BUS_DMA_NOWAIT);
150879251f5eSSepherosa Ziehau if (__predict_false(error)) {
150979251f5eSSepherosa Ziehau m_freem(*m_headp);
151079251f5eSSepherosa Ziehau *m_headp = NULL;
151179251f5eSSepherosa Ziehau return error;
151279251f5eSSepherosa Ziehau }
151379251f5eSSepherosa Ziehau bus_dmamap_sync(txr->tx_tag, map, BUS_DMASYNC_PREWRITE);
151479251f5eSSepherosa Ziehau
151579251f5eSSepherosa Ziehau m_head = *m_headp;
151679251f5eSSepherosa Ziehau
151779251f5eSSepherosa Ziehau /*
151879251f5eSSepherosa Ziehau * Set up the appropriate offload context if requested,
151979251f5eSSepherosa Ziehau * this may consume one TX descriptor.
152079251f5eSSepherosa Ziehau */
152179251f5eSSepherosa Ziehau if (ix_tx_ctx_setup(txr, m_head, &cmd_type_len, &olinfo_status)) {
152279251f5eSSepherosa Ziehau (*segs_used)++;
152379251f5eSSepherosa Ziehau txr->tx_nsegs++;
152479251f5eSSepherosa Ziehau }
152579251f5eSSepherosa Ziehau
152679251f5eSSepherosa Ziehau *segs_used += nsegs;
152779251f5eSSepherosa Ziehau txr->tx_nsegs += nsegs;
152879251f5eSSepherosa Ziehau if (txr->tx_nsegs >= txr->tx_intr_nsegs) {
152979251f5eSSepherosa Ziehau /*
153079251f5eSSepherosa Ziehau * Report Status (RS) is turned on every intr_nsegs
153179251f5eSSepherosa Ziehau * descriptors (roughly).
153279251f5eSSepherosa Ziehau */
153379251f5eSSepherosa Ziehau txr->tx_nsegs = 0;
153479251f5eSSepherosa Ziehau cmd_rs = IXGBE_TXD_CMD_RS;
153579251f5eSSepherosa Ziehau }
153679251f5eSSepherosa Ziehau
153779251f5eSSepherosa Ziehau i = txr->tx_next_avail;
153879251f5eSSepherosa Ziehau for (j = 0; j < nsegs; j++) {
153979251f5eSSepherosa Ziehau bus_size_t seglen;
154079251f5eSSepherosa Ziehau bus_addr_t segaddr;
154179251f5eSSepherosa Ziehau
154279251f5eSSepherosa Ziehau txbuf = &txr->tx_buf[i];
154379251f5eSSepherosa Ziehau txd = &txr->tx_base[i];
154479251f5eSSepherosa Ziehau seglen = segs[j].ds_len;
154579251f5eSSepherosa Ziehau segaddr = htole64(segs[j].ds_addr);
154679251f5eSSepherosa Ziehau
154779251f5eSSepherosa Ziehau txd->read.buffer_addr = segaddr;
154879251f5eSSepherosa Ziehau txd->read.cmd_type_len = htole32(IXGBE_TXD_CMD_IFCS |
154979251f5eSSepherosa Ziehau cmd_type_len |seglen);
155079251f5eSSepherosa Ziehau txd->read.olinfo_status = htole32(olinfo_status);
155179251f5eSSepherosa Ziehau
155279251f5eSSepherosa Ziehau if (++i == txr->tx_ndesc)
155379251f5eSSepherosa Ziehau i = 0;
155479251f5eSSepherosa Ziehau }
155579251f5eSSepherosa Ziehau txd->read.cmd_type_len |= htole32(IXGBE_TXD_CMD_EOP | cmd_rs);
155679251f5eSSepherosa Ziehau
155779251f5eSSepherosa Ziehau txr->tx_avail -= nsegs;
155879251f5eSSepherosa Ziehau txr->tx_next_avail = i;
155982db96e9SSepherosa Ziehau txr->tx_nmbuf++;
156079251f5eSSepherosa Ziehau
156179251f5eSSepherosa Ziehau txbuf->m_head = m_head;
156279251f5eSSepherosa Ziehau txr->tx_buf[first].map = txbuf->map;
156379251f5eSSepherosa Ziehau txbuf->map = map;
156479251f5eSSepherosa Ziehau
156579251f5eSSepherosa Ziehau /*
156679251f5eSSepherosa Ziehau * Defer TDT updating, until enough descrptors are setup
156779251f5eSSepherosa Ziehau */
156879251f5eSSepherosa Ziehau *idx = i;
156979251f5eSSepherosa Ziehau
157079251f5eSSepherosa Ziehau return 0;
157179251f5eSSepherosa Ziehau }
157279251f5eSSepherosa Ziehau
157379251f5eSSepherosa Ziehau static void
ix_set_promisc(struct ix_softc * sc)157479251f5eSSepherosa Ziehau ix_set_promisc(struct ix_softc *sc)
157579251f5eSSepherosa Ziehau {
157679251f5eSSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if;
157779251f5eSSepherosa Ziehau uint32_t reg_rctl;
157879251f5eSSepherosa Ziehau int mcnt = 0;
157979251f5eSSepherosa Ziehau
158079251f5eSSepherosa Ziehau reg_rctl = IXGBE_READ_REG(&sc->hw, IXGBE_FCTRL);
158179251f5eSSepherosa Ziehau reg_rctl &= ~IXGBE_FCTRL_UPE;
158279251f5eSSepherosa Ziehau if (ifp->if_flags & IFF_ALLMULTI) {
158379251f5eSSepherosa Ziehau mcnt = IX_MAX_MCASTADDR;
158479251f5eSSepherosa Ziehau } else {
158579251f5eSSepherosa Ziehau struct ifmultiaddr *ifma;
158679251f5eSSepherosa Ziehau
158779251f5eSSepherosa Ziehau TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
158879251f5eSSepherosa Ziehau if (ifma->ifma_addr->sa_family != AF_LINK)
158979251f5eSSepherosa Ziehau continue;
159079251f5eSSepherosa Ziehau if (mcnt == IX_MAX_MCASTADDR)
159179251f5eSSepherosa Ziehau break;
159279251f5eSSepherosa Ziehau mcnt++;
159379251f5eSSepherosa Ziehau }
159479251f5eSSepherosa Ziehau }
159579251f5eSSepherosa Ziehau if (mcnt < IX_MAX_MCASTADDR)
159679251f5eSSepherosa Ziehau reg_rctl &= ~IXGBE_FCTRL_MPE;
159779251f5eSSepherosa Ziehau IXGBE_WRITE_REG(&sc->hw, IXGBE_FCTRL, reg_rctl);
159879251f5eSSepherosa Ziehau
159979251f5eSSepherosa Ziehau if (ifp->if_flags & IFF_PROMISC) {
160079251f5eSSepherosa Ziehau reg_rctl |= IXGBE_FCTRL_UPE | IXGBE_FCTRL_MPE;
160179251f5eSSepherosa Ziehau IXGBE_WRITE_REG(&sc->hw, IXGBE_FCTRL, reg_rctl);
160279251f5eSSepherosa Ziehau } else if (ifp->if_flags & IFF_ALLMULTI) {
160379251f5eSSepherosa Ziehau reg_rctl |= IXGBE_FCTRL_MPE;
160479251f5eSSepherosa Ziehau reg_rctl &= ~IXGBE_FCTRL_UPE;
160579251f5eSSepherosa Ziehau IXGBE_WRITE_REG(&sc->hw, IXGBE_FCTRL, reg_rctl);
160679251f5eSSepherosa Ziehau }
160779251f5eSSepherosa Ziehau }
160879251f5eSSepherosa Ziehau
160979251f5eSSepherosa Ziehau static void
ix_set_multi(struct ix_softc * sc)161079251f5eSSepherosa Ziehau ix_set_multi(struct ix_softc *sc)
161179251f5eSSepherosa Ziehau {
161279251f5eSSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if;
161379251f5eSSepherosa Ziehau struct ifmultiaddr *ifma;
161479251f5eSSepherosa Ziehau uint32_t fctrl;
16156150453fSSepherosa Ziehau struct ix_mc_addr *mta;
161679251f5eSSepherosa Ziehau int mcnt = 0;
161779251f5eSSepherosa Ziehau
161879251f5eSSepherosa Ziehau mta = sc->mta;
16196150453fSSepherosa Ziehau bzero(mta, sizeof(*mta) * IX_MAX_MCASTADDR);
162079251f5eSSepherosa Ziehau
162179251f5eSSepherosa Ziehau TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
162279251f5eSSepherosa Ziehau if (ifma->ifma_addr->sa_family != AF_LINK)
162379251f5eSSepherosa Ziehau continue;
162479251f5eSSepherosa Ziehau if (mcnt == IX_MAX_MCASTADDR)
162579251f5eSSepherosa Ziehau break;
162679251f5eSSepherosa Ziehau bcopy(LLADDR((struct sockaddr_dl *)ifma->ifma_addr),
16276150453fSSepherosa Ziehau mta[mcnt].addr, IXGBE_ETH_LENGTH_OF_ADDRESS);
162879251f5eSSepherosa Ziehau mcnt++;
162979251f5eSSepherosa Ziehau }
163079251f5eSSepherosa Ziehau
163179251f5eSSepherosa Ziehau fctrl = IXGBE_READ_REG(&sc->hw, IXGBE_FCTRL);
163279251f5eSSepherosa Ziehau fctrl |= (IXGBE_FCTRL_UPE | IXGBE_FCTRL_MPE);
163379251f5eSSepherosa Ziehau if (ifp->if_flags & IFF_PROMISC) {
163479251f5eSSepherosa Ziehau fctrl |= IXGBE_FCTRL_UPE | IXGBE_FCTRL_MPE;
163579251f5eSSepherosa Ziehau } else if (mcnt >= IX_MAX_MCASTADDR || (ifp->if_flags & IFF_ALLMULTI)) {
163679251f5eSSepherosa Ziehau fctrl |= IXGBE_FCTRL_MPE;
163779251f5eSSepherosa Ziehau fctrl &= ~IXGBE_FCTRL_UPE;
163879251f5eSSepherosa Ziehau } else {
163979251f5eSSepherosa Ziehau fctrl &= ~(IXGBE_FCTRL_UPE | IXGBE_FCTRL_MPE);
164079251f5eSSepherosa Ziehau }
164179251f5eSSepherosa Ziehau IXGBE_WRITE_REG(&sc->hw, IXGBE_FCTRL, fctrl);
164279251f5eSSepherosa Ziehau
164379251f5eSSepherosa Ziehau if (mcnt < IX_MAX_MCASTADDR) {
164479251f5eSSepherosa Ziehau ixgbe_update_mc_addr_list(&sc->hw,
16456150453fSSepherosa Ziehau (uint8_t *)mta, mcnt, ix_mc_array_itr, TRUE);
164679251f5eSSepherosa Ziehau }
164779251f5eSSepherosa Ziehau }
164879251f5eSSepherosa Ziehau
164979251f5eSSepherosa Ziehau /*
165079251f5eSSepherosa Ziehau * This is an iterator function now needed by the multicast
165179251f5eSSepherosa Ziehau * shared code. It simply feeds the shared code routine the
165279251f5eSSepherosa Ziehau * addresses in the array of ix_set_multi() one by one.
165379251f5eSSepherosa Ziehau */
165479251f5eSSepherosa Ziehau static uint8_t *
ix_mc_array_itr(struct ixgbe_hw * hw,uint8_t ** update_ptr,uint32_t * vmdq)165579251f5eSSepherosa Ziehau ix_mc_array_itr(struct ixgbe_hw *hw, uint8_t **update_ptr, uint32_t *vmdq)
165679251f5eSSepherosa Ziehau {
16576150453fSSepherosa Ziehau struct ix_mc_addr *mta = (struct ix_mc_addr *)*update_ptr;
165879251f5eSSepherosa Ziehau
16596150453fSSepherosa Ziehau *vmdq = mta->vmdq;
16606150453fSSepherosa Ziehau *update_ptr = (uint8_t *)(mta + 1);
16616150453fSSepherosa Ziehau
16626150453fSSepherosa Ziehau return (mta->addr);
166379251f5eSSepherosa Ziehau }
166479251f5eSSepherosa Ziehau
166579251f5eSSepherosa Ziehau static void
ix_timer(void * arg)166679251f5eSSepherosa Ziehau ix_timer(void *arg)
166779251f5eSSepherosa Ziehau {
166879251f5eSSepherosa Ziehau struct ix_softc *sc = arg;
166979251f5eSSepherosa Ziehau
167079251f5eSSepherosa Ziehau lwkt_serialize_enter(&sc->main_serialize);
167179251f5eSSepherosa Ziehau
167279251f5eSSepherosa Ziehau if ((sc->arpcom.ac_if.if_flags & IFF_RUNNING) == 0) {
167379251f5eSSepherosa Ziehau lwkt_serialize_exit(&sc->main_serialize);
167479251f5eSSepherosa Ziehau return;
167579251f5eSSepherosa Ziehau }
167679251f5eSSepherosa Ziehau
167779251f5eSSepherosa Ziehau /* Check for pluggable optics */
167879251f5eSSepherosa Ziehau if (sc->sfp_probe) {
167979251f5eSSepherosa Ziehau if (!ix_sfp_probe(sc))
168079251f5eSSepherosa Ziehau goto done; /* Nothing to do */
168179251f5eSSepherosa Ziehau }
168279251f5eSSepherosa Ziehau
168379251f5eSSepherosa Ziehau ix_update_link_status(sc);
168479251f5eSSepherosa Ziehau ix_update_stats(sc);
168579251f5eSSepherosa Ziehau
168679251f5eSSepherosa Ziehau done:
168779251f5eSSepherosa Ziehau callout_reset_bycpu(&sc->timer, hz, ix_timer, sc, sc->timer_cpuid);
168879251f5eSSepherosa Ziehau lwkt_serialize_exit(&sc->main_serialize);
168979251f5eSSepherosa Ziehau }
169079251f5eSSepherosa Ziehau
169179251f5eSSepherosa Ziehau static void
ix_update_link_status(struct ix_softc * sc)169279251f5eSSepherosa Ziehau ix_update_link_status(struct ix_softc *sc)
169379251f5eSSepherosa Ziehau {
169479251f5eSSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if;
169579251f5eSSepherosa Ziehau
169679251f5eSSepherosa Ziehau if (sc->link_up) {
169779251f5eSSepherosa Ziehau if (sc->link_active == FALSE) {
169879251f5eSSepherosa Ziehau if (bootverbose) {
169979251f5eSSepherosa Ziehau if_printf(ifp, "Link is up %d Gbps %s\n",
170079251f5eSSepherosa Ziehau sc->link_speed == 128 ? 10 : 1,
170179251f5eSSepherosa Ziehau "Full Duplex");
170279251f5eSSepherosa Ziehau }
170379251f5eSSepherosa Ziehau
1704060fa21cSSepherosa Ziehau /*
1705060fa21cSSepherosa Ziehau * Update any Flow Control changes
1706060fa21cSSepherosa Ziehau */
170779251f5eSSepherosa Ziehau ixgbe_fc_enable(&sc->hw);
1708060fa21cSSepherosa Ziehau /* MUST after ixgbe_fc_enable() */
1709060fa21cSSepherosa Ziehau if (sc->rx_ring_inuse > 1) {
1710060fa21cSSepherosa Ziehau switch (sc->hw.fc.current_mode) {
1711060fa21cSSepherosa Ziehau case ixgbe_fc_rx_pause:
1712060fa21cSSepherosa Ziehau case ixgbe_fc_tx_pause:
1713060fa21cSSepherosa Ziehau case ixgbe_fc_full:
1714060fa21cSSepherosa Ziehau ix_disable_rx_drop(sc);
1715060fa21cSSepherosa Ziehau break;
1716060fa21cSSepherosa Ziehau
1717060fa21cSSepherosa Ziehau case ixgbe_fc_none:
1718060fa21cSSepherosa Ziehau ix_enable_rx_drop(sc);
1719060fa21cSSepherosa Ziehau break;
1720060fa21cSSepherosa Ziehau
1721060fa21cSSepherosa Ziehau default:
1722060fa21cSSepherosa Ziehau break;
1723060fa21cSSepherosa Ziehau }
1724060fa21cSSepherosa Ziehau }
1725060fa21cSSepherosa Ziehau
172663d483cdSSepherosa Ziehau /* Update DMA coalescing config */
172763d483cdSSepherosa Ziehau ix_config_dmac(sc);
172863d483cdSSepherosa Ziehau
1729060fa21cSSepherosa Ziehau sc->link_active = TRUE;
173079251f5eSSepherosa Ziehau
173179251f5eSSepherosa Ziehau ifp->if_link_state = LINK_STATE_UP;
173279251f5eSSepherosa Ziehau if_link_state_change(ifp);
173379251f5eSSepherosa Ziehau }
173479251f5eSSepherosa Ziehau } else { /* Link down */
173579251f5eSSepherosa Ziehau if (sc->link_active == TRUE) {
173679251f5eSSepherosa Ziehau if (bootverbose)
173779251f5eSSepherosa Ziehau if_printf(ifp, "Link is Down\n");
173879251f5eSSepherosa Ziehau ifp->if_link_state = LINK_STATE_DOWN;
173979251f5eSSepherosa Ziehau if_link_state_change(ifp);
174079251f5eSSepherosa Ziehau
174179251f5eSSepherosa Ziehau sc->link_active = FALSE;
174279251f5eSSepherosa Ziehau }
174379251f5eSSepherosa Ziehau }
174479251f5eSSepherosa Ziehau }
174579251f5eSSepherosa Ziehau
174679251f5eSSepherosa Ziehau static void
ix_stop(struct ix_softc * sc)174779251f5eSSepherosa Ziehau ix_stop(struct ix_softc *sc)
174879251f5eSSepherosa Ziehau {
174979251f5eSSepherosa Ziehau struct ixgbe_hw *hw = &sc->hw;
175079251f5eSSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if;
175179251f5eSSepherosa Ziehau int i;
175279251f5eSSepherosa Ziehau
175379251f5eSSepherosa Ziehau ASSERT_IFNET_SERIALIZED_ALL(ifp);
175479251f5eSSepherosa Ziehau
175579251f5eSSepherosa Ziehau ix_disable_intr(sc);
175679251f5eSSepherosa Ziehau callout_stop(&sc->timer);
175779251f5eSSepherosa Ziehau
175879251f5eSSepherosa Ziehau ifp->if_flags &= ~IFF_RUNNING;
175979251f5eSSepherosa Ziehau for (i = 0; i < sc->tx_ring_cnt; ++i) {
17604a648aefSSepherosa Ziehau struct ix_tx_ring *txr = &sc->tx_rings[i];
17614a648aefSSepherosa Ziehau
17624a648aefSSepherosa Ziehau ifsq_clr_oactive(txr->tx_ifsq);
17634a648aefSSepherosa Ziehau ifsq_watchdog_stop(&txr->tx_watchdog);
17644a648aefSSepherosa Ziehau txr->tx_flags &= ~IX_TXFLAG_ENABLED;
176582db96e9SSepherosa Ziehau
176682db96e9SSepherosa Ziehau txr->tx_running = 0;
176782db96e9SSepherosa Ziehau callout_stop(&txr->tx_gc_timer);
176879251f5eSSepherosa Ziehau }
176979251f5eSSepherosa Ziehau
177079251f5eSSepherosa Ziehau ixgbe_reset_hw(hw);
177179251f5eSSepherosa Ziehau hw->adapter_stopped = FALSE;
177279251f5eSSepherosa Ziehau ixgbe_stop_adapter(hw);
177379251f5eSSepherosa Ziehau if (hw->mac.type == ixgbe_mac_82599EB)
177479251f5eSSepherosa Ziehau ixgbe_stop_mac_link_on_d3_82599(hw);
177579251f5eSSepherosa Ziehau /* Turn off the laser - noop with no optics */
177679251f5eSSepherosa Ziehau ixgbe_disable_tx_laser(hw);
177779251f5eSSepherosa Ziehau
177879251f5eSSepherosa Ziehau /* Update the stack */
177979251f5eSSepherosa Ziehau sc->link_up = FALSE;
178079251f5eSSepherosa Ziehau ix_update_link_status(sc);
178179251f5eSSepherosa Ziehau
178279251f5eSSepherosa Ziehau /* Reprogram the RAR[0] in case user changed it. */
178379251f5eSSepherosa Ziehau ixgbe_set_rar(hw, 0, hw->mac.addr, 0, IXGBE_RAH_AV);
178479251f5eSSepherosa Ziehau
178579251f5eSSepherosa Ziehau for (i = 0; i < sc->tx_ring_cnt; ++i)
178679251f5eSSepherosa Ziehau ix_free_tx_ring(&sc->tx_rings[i]);
178779251f5eSSepherosa Ziehau
178879251f5eSSepherosa Ziehau for (i = 0; i < sc->rx_ring_cnt; ++i)
178979251f5eSSepherosa Ziehau ix_free_rx_ring(&sc->rx_rings[i]);
179079251f5eSSepherosa Ziehau }
179179251f5eSSepherosa Ziehau
179279251f5eSSepherosa Ziehau static void
ix_setup_ifp(struct ix_softc * sc)179379251f5eSSepherosa Ziehau ix_setup_ifp(struct ix_softc *sc)
179479251f5eSSepherosa Ziehau {
179579251f5eSSepherosa Ziehau struct ixgbe_hw *hw = &sc->hw;
179679251f5eSSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if;
179779251f5eSSepherosa Ziehau int i;
179879251f5eSSepherosa Ziehau
179979251f5eSSepherosa Ziehau ifp->if_baudrate = IF_Gbps(10UL);
180079251f5eSSepherosa Ziehau
180179251f5eSSepherosa Ziehau ifp->if_softc = sc;
180279251f5eSSepherosa Ziehau ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
180379251f5eSSepherosa Ziehau ifp->if_init = ix_init;
180479251f5eSSepherosa Ziehau ifp->if_ioctl = ix_ioctl;
180579251f5eSSepherosa Ziehau ifp->if_start = ix_start;
180679251f5eSSepherosa Ziehau ifp->if_serialize = ix_serialize;
180779251f5eSSepherosa Ziehau ifp->if_deserialize = ix_deserialize;
180879251f5eSSepherosa Ziehau ifp->if_tryserialize = ix_tryserialize;
180979251f5eSSepherosa Ziehau #ifdef INVARIANTS
181079251f5eSSepherosa Ziehau ifp->if_serialize_assert = ix_serialize_assert;
181179251f5eSSepherosa Ziehau #endif
18124a648aefSSepherosa Ziehau #ifdef IFPOLL_ENABLE
18134a648aefSSepherosa Ziehau ifp->if_npoll = ix_npoll;
18144a648aefSSepherosa Ziehau #endif
181579251f5eSSepherosa Ziehau
1816189a0ff3SSepherosa Ziehau /* Increase TSO burst length */
1817189a0ff3SSepherosa Ziehau ifp->if_tsolen = (8 * ETHERMTU);
1818189a0ff3SSepherosa Ziehau
181914929979SSepherosa Ziehau ifp->if_nmbclusters = sc->rx_ring_cnt * sc->rx_rings[0].rx_ndesc;
182014929979SSepherosa Ziehau ifp->if_nmbjclusters = ifp->if_nmbclusters;
182114929979SSepherosa Ziehau
182279251f5eSSepherosa Ziehau ifq_set_maxlen(&ifp->if_snd, sc->tx_rings[0].tx_ndesc - 2);
182379251f5eSSepherosa Ziehau ifq_set_ready(&ifp->if_snd);
182479251f5eSSepherosa Ziehau ifq_set_subq_cnt(&ifp->if_snd, sc->tx_ring_cnt);
182579251f5eSSepherosa Ziehau
18263c37d13bSSepherosa Ziehau ifp->if_mapsubq = ifq_mapsubq_modulo;
18273c37d13bSSepherosa Ziehau ifq_set_subq_divisor(&ifp->if_snd, 1);
182879251f5eSSepherosa Ziehau
182979251f5eSSepherosa Ziehau ether_ifattach(ifp, hw->mac.addr, NULL);
183079251f5eSSepherosa Ziehau
183179251f5eSSepherosa Ziehau ifp->if_capabilities =
183279251f5eSSepherosa Ziehau IFCAP_HWCSUM | IFCAP_TSO | IFCAP_VLAN_HWTAGGING | IFCAP_VLAN_MTU;
183379251f5eSSepherosa Ziehau if (IX_ENABLE_HWRSS(sc))
183479251f5eSSepherosa Ziehau ifp->if_capabilities |= IFCAP_RSS;
183579251f5eSSepherosa Ziehau ifp->if_capenable = ifp->if_capabilities;
183679251f5eSSepherosa Ziehau ifp->if_hwassist = CSUM_OFFLOAD | CSUM_TSO;
183779251f5eSSepherosa Ziehau
183879251f5eSSepherosa Ziehau /*
183979251f5eSSepherosa Ziehau * Tell the upper layer(s) we support long frames.
184079251f5eSSepherosa Ziehau */
184179251f5eSSepherosa Ziehau ifp->if_data.ifi_hdrlen = sizeof(struct ether_vlan_header);
184279251f5eSSepherosa Ziehau
184379251f5eSSepherosa Ziehau /* Setup TX rings and subqueues */
184479251f5eSSepherosa Ziehau for (i = 0; i < sc->tx_ring_cnt; ++i) {
184579251f5eSSepherosa Ziehau struct ifaltq_subque *ifsq = ifq_get_subq(&ifp->if_snd, i);
184679251f5eSSepherosa Ziehau struct ix_tx_ring *txr = &sc->tx_rings[i];
184779251f5eSSepherosa Ziehau
184879251f5eSSepherosa Ziehau ifsq_set_cpuid(ifsq, txr->tx_intr_cpuid);
184979251f5eSSepherosa Ziehau ifsq_set_priv(ifsq, txr);
185079251f5eSSepherosa Ziehau ifsq_set_hw_serialize(ifsq, &txr->tx_serialize);
185179251f5eSSepherosa Ziehau txr->tx_ifsq = ifsq;
185279251f5eSSepherosa Ziehau
1853e2292763SMatthew Dillon ifsq_watchdog_init(&txr->tx_watchdog, ifsq, ix_watchdog, 0);
185479251f5eSSepherosa Ziehau }
185579251f5eSSepherosa Ziehau
185663d483cdSSepherosa Ziehau /* Specify the media types supported by this adapter */
18576150453fSSepherosa Ziehau sc->phy_layer = ixgbe_get_supported_physical_layer(hw);
185863d483cdSSepherosa Ziehau ix_init_media(sc);
185979251f5eSSepherosa Ziehau }
186079251f5eSSepherosa Ziehau
186179251f5eSSepherosa Ziehau static boolean_t
ix_is_sfp(struct ixgbe_hw * hw)18626150453fSSepherosa Ziehau ix_is_sfp(struct ixgbe_hw *hw)
186379251f5eSSepherosa Ziehau {
18646150453fSSepherosa Ziehau switch (hw->mac.type) {
18656150453fSSepherosa Ziehau case ixgbe_mac_82598EB:
18666150453fSSepherosa Ziehau if (hw->phy.type == ixgbe_phy_nl)
186779251f5eSSepherosa Ziehau return TRUE;
18686150453fSSepherosa Ziehau return FALSE;
18696150453fSSepherosa Ziehau
18706150453fSSepherosa Ziehau case ixgbe_mac_82599EB:
18716150453fSSepherosa Ziehau switch (hw->mac.ops.get_media_type(hw)) {
18726150453fSSepherosa Ziehau case ixgbe_media_type_fiber:
18736150453fSSepherosa Ziehau case ixgbe_media_type_fiber_qsfp:
18746150453fSSepherosa Ziehau return TRUE;
18756150453fSSepherosa Ziehau default:
18766150453fSSepherosa Ziehau return FALSE;
18776150453fSSepherosa Ziehau }
18786150453fSSepherosa Ziehau
18796150453fSSepherosa Ziehau case ixgbe_mac_X550EM_x:
18806150453fSSepherosa Ziehau case ixgbe_mac_X550EM_a:
18816150453fSSepherosa Ziehau if (hw->mac.ops.get_media_type(hw) == ixgbe_media_type_fiber)
18826150453fSSepherosa Ziehau return TRUE;
18836150453fSSepherosa Ziehau return FALSE;
18846150453fSSepherosa Ziehau
188579251f5eSSepherosa Ziehau default:
188679251f5eSSepherosa Ziehau return FALSE;
188779251f5eSSepherosa Ziehau }
188879251f5eSSepherosa Ziehau }
188979251f5eSSepherosa Ziehau
189079251f5eSSepherosa Ziehau static void
ix_config_link(struct ix_softc * sc)189179251f5eSSepherosa Ziehau ix_config_link(struct ix_softc *sc)
189279251f5eSSepherosa Ziehau {
189379251f5eSSepherosa Ziehau struct ixgbe_hw *hw = &sc->hw;
189479251f5eSSepherosa Ziehau boolean_t sfp;
189579251f5eSSepherosa Ziehau
189679251f5eSSepherosa Ziehau sfp = ix_is_sfp(hw);
189779251f5eSSepherosa Ziehau if (sfp) {
18986150453fSSepherosa Ziehau if (hw->phy.multispeed_fiber)
189979251f5eSSepherosa Ziehau ixgbe_enable_tx_laser(hw);
190079251f5eSSepherosa Ziehau ix_handle_mod(sc);
190179251f5eSSepherosa Ziehau } else {
190279251f5eSSepherosa Ziehau uint32_t autoneg, err = 0;
190379251f5eSSepherosa Ziehau
190479251f5eSSepherosa Ziehau if (hw->mac.ops.check_link != NULL) {
190579251f5eSSepherosa Ziehau err = ixgbe_check_link(hw, &sc->link_speed,
190679251f5eSSepherosa Ziehau &sc->link_up, FALSE);
190779251f5eSSepherosa Ziehau if (err)
190879251f5eSSepherosa Ziehau return;
190979251f5eSSepherosa Ziehau }
191079251f5eSSepherosa Ziehau
191163d483cdSSepherosa Ziehau if (sc->advspeed != IXGBE_LINK_SPEED_UNKNOWN)
191263d483cdSSepherosa Ziehau autoneg = sc->advspeed;
191363d483cdSSepherosa Ziehau else
191479251f5eSSepherosa Ziehau autoneg = hw->phy.autoneg_advertised;
191579251f5eSSepherosa Ziehau if (!autoneg && hw->mac.ops.get_link_capabilities != NULL) {
191679251f5eSSepherosa Ziehau bool negotiate;
191779251f5eSSepherosa Ziehau
191879251f5eSSepherosa Ziehau err = hw->mac.ops.get_link_capabilities(hw,
191979251f5eSSepherosa Ziehau &autoneg, &negotiate);
192079251f5eSSepherosa Ziehau if (err)
192179251f5eSSepherosa Ziehau return;
192279251f5eSSepherosa Ziehau }
192379251f5eSSepherosa Ziehau
192479251f5eSSepherosa Ziehau if (hw->mac.ops.setup_link != NULL) {
192579251f5eSSepherosa Ziehau err = hw->mac.ops.setup_link(hw,
192679251f5eSSepherosa Ziehau autoneg, sc->link_up);
192779251f5eSSepherosa Ziehau if (err)
192879251f5eSSepherosa Ziehau return;
192979251f5eSSepherosa Ziehau }
193079251f5eSSepherosa Ziehau }
193179251f5eSSepherosa Ziehau }
193279251f5eSSepherosa Ziehau
193379251f5eSSepherosa Ziehau static int
ix_alloc_rings(struct ix_softc * sc)193479251f5eSSepherosa Ziehau ix_alloc_rings(struct ix_softc *sc)
193579251f5eSSepherosa Ziehau {
193679251f5eSSepherosa Ziehau int error, i;
193779251f5eSSepherosa Ziehau
193879251f5eSSepherosa Ziehau /*
193979251f5eSSepherosa Ziehau * Create top level busdma tag
194079251f5eSSepherosa Ziehau */
194179251f5eSSepherosa Ziehau error = bus_dma_tag_create(NULL, 1, 0,
1942*030b0c8cSMichael Neumann BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR,
194379251f5eSSepherosa Ziehau BUS_SPACE_MAXSIZE_32BIT, 0, BUS_SPACE_MAXSIZE_32BIT, 0,
194479251f5eSSepherosa Ziehau &sc->parent_tag);
194579251f5eSSepherosa Ziehau if (error) {
194679251f5eSSepherosa Ziehau device_printf(sc->dev, "could not create top level DMA tag\n");
194779251f5eSSepherosa Ziehau return error;
194879251f5eSSepherosa Ziehau }
194979251f5eSSepherosa Ziehau
195079251f5eSSepherosa Ziehau /*
195179251f5eSSepherosa Ziehau * Allocate TX descriptor rings and buffers
195279251f5eSSepherosa Ziehau */
195362938642SMatthew Dillon sc->tx_rings = kmalloc(sizeof(struct ix_tx_ring) * sc->tx_ring_cnt,
195462938642SMatthew Dillon M_DEVBUF,
195562938642SMatthew Dillon M_WAITOK | M_ZERO | M_CACHEALIGN);
195679251f5eSSepherosa Ziehau for (i = 0; i < sc->tx_ring_cnt; ++i) {
195779251f5eSSepherosa Ziehau struct ix_tx_ring *txr = &sc->tx_rings[i];
195879251f5eSSepherosa Ziehau
195979251f5eSSepherosa Ziehau txr->tx_sc = sc;
196079251f5eSSepherosa Ziehau txr->tx_idx = i;
1961189a0ff3SSepherosa Ziehau txr->tx_intr_vec = -1;
19623c37d13bSSepherosa Ziehau txr->tx_intr_cpuid = -1;
196379251f5eSSepherosa Ziehau lwkt_serialize_init(&txr->tx_serialize);
196482db96e9SSepherosa Ziehau callout_init_mp(&txr->tx_gc_timer);
196579251f5eSSepherosa Ziehau
196679251f5eSSepherosa Ziehau error = ix_create_tx_ring(txr);
196779251f5eSSepherosa Ziehau if (error)
196879251f5eSSepherosa Ziehau return error;
196979251f5eSSepherosa Ziehau }
197079251f5eSSepherosa Ziehau
197179251f5eSSepherosa Ziehau /*
197279251f5eSSepherosa Ziehau * Allocate RX descriptor rings and buffers
197379251f5eSSepherosa Ziehau */
197462938642SMatthew Dillon sc->rx_rings = kmalloc(sizeof(struct ix_rx_ring) * sc->rx_ring_cnt,
197562938642SMatthew Dillon M_DEVBUF,
197662938642SMatthew Dillon M_WAITOK | M_ZERO | M_CACHEALIGN);
197779251f5eSSepherosa Ziehau for (i = 0; i < sc->rx_ring_cnt; ++i) {
197879251f5eSSepherosa Ziehau struct ix_rx_ring *rxr = &sc->rx_rings[i];
197979251f5eSSepherosa Ziehau
198079251f5eSSepherosa Ziehau rxr->rx_sc = sc;
198179251f5eSSepherosa Ziehau rxr->rx_idx = i;
1982189a0ff3SSepherosa Ziehau rxr->rx_intr_vec = -1;
198379251f5eSSepherosa Ziehau lwkt_serialize_init(&rxr->rx_serialize);
198479251f5eSSepherosa Ziehau
198579251f5eSSepherosa Ziehau error = ix_create_rx_ring(rxr);
198679251f5eSSepherosa Ziehau if (error)
198779251f5eSSepherosa Ziehau return error;
198879251f5eSSepherosa Ziehau }
198979251f5eSSepherosa Ziehau
199079251f5eSSepherosa Ziehau return 0;
199179251f5eSSepherosa Ziehau }
199279251f5eSSepherosa Ziehau
199379251f5eSSepherosa Ziehau static int
ix_create_tx_ring(struct ix_tx_ring * txr)199479251f5eSSepherosa Ziehau ix_create_tx_ring(struct ix_tx_ring *txr)
199579251f5eSSepherosa Ziehau {
199679251f5eSSepherosa Ziehau int error, i, tsize, ntxd;
199779251f5eSSepherosa Ziehau
199879251f5eSSepherosa Ziehau /*
199979251f5eSSepherosa Ziehau * Validate number of transmit descriptors. It must not exceed
200079251f5eSSepherosa Ziehau * hardware maximum, and must be multiple of IX_DBA_ALIGN.
200179251f5eSSepherosa Ziehau */
200279251f5eSSepherosa Ziehau ntxd = device_getenv_int(txr->tx_sc->dev, "txd", ix_txd);
200379251f5eSSepherosa Ziehau if (((ntxd * sizeof(union ixgbe_adv_tx_desc)) % IX_DBA_ALIGN) != 0 ||
200479251f5eSSepherosa Ziehau ntxd < IX_MIN_TXD || ntxd > IX_MAX_TXD) {
200579251f5eSSepherosa Ziehau device_printf(txr->tx_sc->dev,
200679251f5eSSepherosa Ziehau "Using %d TX descriptors instead of %d!\n",
200779251f5eSSepherosa Ziehau IX_DEF_TXD, ntxd);
200879251f5eSSepherosa Ziehau txr->tx_ndesc = IX_DEF_TXD;
200979251f5eSSepherosa Ziehau } else {
201079251f5eSSepherosa Ziehau txr->tx_ndesc = ntxd;
201179251f5eSSepherosa Ziehau }
201279251f5eSSepherosa Ziehau
201379251f5eSSepherosa Ziehau /*
201479251f5eSSepherosa Ziehau * Allocate TX head write-back buffer
201579251f5eSSepherosa Ziehau */
201679251f5eSSepherosa Ziehau txr->tx_hdr = bus_dmamem_coherent_any(txr->tx_sc->parent_tag,
201779251f5eSSepherosa Ziehau __VM_CACHELINE_SIZE, __VM_CACHELINE_SIZE, BUS_DMA_WAITOK,
201879251f5eSSepherosa Ziehau &txr->tx_hdr_dtag, &txr->tx_hdr_map, &txr->tx_hdr_paddr);
201979251f5eSSepherosa Ziehau if (txr->tx_hdr == NULL) {
202079251f5eSSepherosa Ziehau device_printf(txr->tx_sc->dev,
202179251f5eSSepherosa Ziehau "Unable to allocate TX head write-back buffer\n");
202279251f5eSSepherosa Ziehau return ENOMEM;
202379251f5eSSepherosa Ziehau }
202479251f5eSSepherosa Ziehau
202579251f5eSSepherosa Ziehau /*
202679251f5eSSepherosa Ziehau * Allocate TX descriptor ring
202779251f5eSSepherosa Ziehau */
202879251f5eSSepherosa Ziehau tsize = roundup2(txr->tx_ndesc * sizeof(union ixgbe_adv_tx_desc),
202979251f5eSSepherosa Ziehau IX_DBA_ALIGN);
203079251f5eSSepherosa Ziehau txr->tx_base = bus_dmamem_coherent_any(txr->tx_sc->parent_tag,
203179251f5eSSepherosa Ziehau IX_DBA_ALIGN, tsize, BUS_DMA_WAITOK | BUS_DMA_ZERO,
203279251f5eSSepherosa Ziehau &txr->tx_base_dtag, &txr->tx_base_map, &txr->tx_base_paddr);
203379251f5eSSepherosa Ziehau if (txr->tx_base == NULL) {
203479251f5eSSepherosa Ziehau device_printf(txr->tx_sc->dev,
203579251f5eSSepherosa Ziehau "Unable to allocate TX Descriptor memory\n");
203679251f5eSSepherosa Ziehau return ENOMEM;
203779251f5eSSepherosa Ziehau }
203879251f5eSSepherosa Ziehau
203979251f5eSSepherosa Ziehau tsize = __VM_CACHELINE_ALIGN(sizeof(struct ix_tx_buf) * txr->tx_ndesc);
204062938642SMatthew Dillon txr->tx_buf = kmalloc(tsize, M_DEVBUF,
204162938642SMatthew Dillon M_WAITOK | M_ZERO | M_CACHEALIGN);
204279251f5eSSepherosa Ziehau
204379251f5eSSepherosa Ziehau /*
204479251f5eSSepherosa Ziehau * Create DMA tag for TX buffers
204579251f5eSSepherosa Ziehau */
204679251f5eSSepherosa Ziehau error = bus_dma_tag_create(txr->tx_sc->parent_tag,
204779251f5eSSepherosa Ziehau 1, 0, /* alignment, bounds */
204879251f5eSSepherosa Ziehau BUS_SPACE_MAXADDR, /* lowaddr */
204979251f5eSSepherosa Ziehau BUS_SPACE_MAXADDR, /* highaddr */
205079251f5eSSepherosa Ziehau IX_TSO_SIZE, /* maxsize */
205179251f5eSSepherosa Ziehau IX_MAX_SCATTER, /* nsegments */
205279251f5eSSepherosa Ziehau PAGE_SIZE, /* maxsegsize */
205379251f5eSSepherosa Ziehau BUS_DMA_WAITOK | BUS_DMA_ALLOCNOW |
205479251f5eSSepherosa Ziehau BUS_DMA_ONEBPAGE, /* flags */
205579251f5eSSepherosa Ziehau &txr->tx_tag);
205679251f5eSSepherosa Ziehau if (error) {
205779251f5eSSepherosa Ziehau device_printf(txr->tx_sc->dev,
205879251f5eSSepherosa Ziehau "Unable to allocate TX DMA tag\n");
205979251f5eSSepherosa Ziehau kfree(txr->tx_buf, M_DEVBUF);
206079251f5eSSepherosa Ziehau txr->tx_buf = NULL;
206179251f5eSSepherosa Ziehau return error;
206279251f5eSSepherosa Ziehau }
206379251f5eSSepherosa Ziehau
206479251f5eSSepherosa Ziehau /*
206579251f5eSSepherosa Ziehau * Create DMA maps for TX buffers
206679251f5eSSepherosa Ziehau */
206779251f5eSSepherosa Ziehau for (i = 0; i < txr->tx_ndesc; ++i) {
206879251f5eSSepherosa Ziehau struct ix_tx_buf *txbuf = &txr->tx_buf[i];
206979251f5eSSepherosa Ziehau
207079251f5eSSepherosa Ziehau error = bus_dmamap_create(txr->tx_tag,
207179251f5eSSepherosa Ziehau BUS_DMA_WAITOK | BUS_DMA_ONEBPAGE, &txbuf->map);
207279251f5eSSepherosa Ziehau if (error) {
207379251f5eSSepherosa Ziehau device_printf(txr->tx_sc->dev,
207479251f5eSSepherosa Ziehau "Unable to create TX DMA map\n");
207579251f5eSSepherosa Ziehau ix_destroy_tx_ring(txr, i);
207679251f5eSSepherosa Ziehau return error;
207779251f5eSSepherosa Ziehau }
207879251f5eSSepherosa Ziehau }
207979251f5eSSepherosa Ziehau
208079251f5eSSepherosa Ziehau /*
208179251f5eSSepherosa Ziehau * Initialize various watermark
208279251f5eSSepherosa Ziehau */
208379251f5eSSepherosa Ziehau txr->tx_wreg_nsegs = IX_DEF_TXWREG_NSEGS;
208479251f5eSSepherosa Ziehau txr->tx_intr_nsegs = txr->tx_ndesc / 16;
208579251f5eSSepherosa Ziehau
208679251f5eSSepherosa Ziehau return 0;
208779251f5eSSepherosa Ziehau }
208879251f5eSSepherosa Ziehau
208979251f5eSSepherosa Ziehau static void
ix_destroy_tx_ring(struct ix_tx_ring * txr,int ndesc)209079251f5eSSepherosa Ziehau ix_destroy_tx_ring(struct ix_tx_ring *txr, int ndesc)
209179251f5eSSepherosa Ziehau {
209279251f5eSSepherosa Ziehau int i;
209379251f5eSSepherosa Ziehau
209479251f5eSSepherosa Ziehau if (txr->tx_hdr != NULL) {
209579251f5eSSepherosa Ziehau bus_dmamap_unload(txr->tx_hdr_dtag, txr->tx_hdr_map);
209679251f5eSSepherosa Ziehau bus_dmamem_free(txr->tx_hdr_dtag,
209779251f5eSSepherosa Ziehau __DEVOLATILE(void *, txr->tx_hdr), txr->tx_hdr_map);
209879251f5eSSepherosa Ziehau bus_dma_tag_destroy(txr->tx_hdr_dtag);
209979251f5eSSepherosa Ziehau txr->tx_hdr = NULL;
210079251f5eSSepherosa Ziehau }
210179251f5eSSepherosa Ziehau
210279251f5eSSepherosa Ziehau if (txr->tx_base != NULL) {
210379251f5eSSepherosa Ziehau bus_dmamap_unload(txr->tx_base_dtag, txr->tx_base_map);
210479251f5eSSepherosa Ziehau bus_dmamem_free(txr->tx_base_dtag, txr->tx_base,
210579251f5eSSepherosa Ziehau txr->tx_base_map);
210679251f5eSSepherosa Ziehau bus_dma_tag_destroy(txr->tx_base_dtag);
210779251f5eSSepherosa Ziehau txr->tx_base = NULL;
210879251f5eSSepherosa Ziehau }
210979251f5eSSepherosa Ziehau
211079251f5eSSepherosa Ziehau if (txr->tx_buf == NULL)
211179251f5eSSepherosa Ziehau return;
211279251f5eSSepherosa Ziehau
211379251f5eSSepherosa Ziehau for (i = 0; i < ndesc; ++i) {
211479251f5eSSepherosa Ziehau struct ix_tx_buf *txbuf = &txr->tx_buf[i];
211579251f5eSSepherosa Ziehau
211679251f5eSSepherosa Ziehau KKASSERT(txbuf->m_head == NULL);
211779251f5eSSepherosa Ziehau bus_dmamap_destroy(txr->tx_tag, txbuf->map);
211879251f5eSSepherosa Ziehau }
211979251f5eSSepherosa Ziehau bus_dma_tag_destroy(txr->tx_tag);
212079251f5eSSepherosa Ziehau
212179251f5eSSepherosa Ziehau kfree(txr->tx_buf, M_DEVBUF);
212279251f5eSSepherosa Ziehau txr->tx_buf = NULL;
212379251f5eSSepherosa Ziehau }
212479251f5eSSepherosa Ziehau
212579251f5eSSepherosa Ziehau static void
ix_init_tx_ring(struct ix_tx_ring * txr)212679251f5eSSepherosa Ziehau ix_init_tx_ring(struct ix_tx_ring *txr)
212779251f5eSSepherosa Ziehau {
212879251f5eSSepherosa Ziehau /* Clear the old ring contents */
212979251f5eSSepherosa Ziehau bzero(txr->tx_base, sizeof(union ixgbe_adv_tx_desc) * txr->tx_ndesc);
213079251f5eSSepherosa Ziehau
213179251f5eSSepherosa Ziehau /* Clear TX head write-back buffer */
213279251f5eSSepherosa Ziehau *(txr->tx_hdr) = 0;
213379251f5eSSepherosa Ziehau
213479251f5eSSepherosa Ziehau /* Reset indices */
213579251f5eSSepherosa Ziehau txr->tx_next_avail = 0;
213679251f5eSSepherosa Ziehau txr->tx_next_clean = 0;
213779251f5eSSepherosa Ziehau txr->tx_nsegs = 0;
213882db96e9SSepherosa Ziehau txr->tx_nmbuf = 0;
213982db96e9SSepherosa Ziehau txr->tx_running = 0;
214079251f5eSSepherosa Ziehau
214179251f5eSSepherosa Ziehau /* Set number of descriptors available */
214279251f5eSSepherosa Ziehau txr->tx_avail = txr->tx_ndesc;
21434a648aefSSepherosa Ziehau
21444a648aefSSepherosa Ziehau /* Enable this TX ring */
21454a648aefSSepherosa Ziehau txr->tx_flags |= IX_TXFLAG_ENABLED;
214679251f5eSSepherosa Ziehau }
214779251f5eSSepherosa Ziehau
214879251f5eSSepherosa Ziehau static void
ix_init_tx_unit(struct ix_softc * sc)214979251f5eSSepherosa Ziehau ix_init_tx_unit(struct ix_softc *sc)
215079251f5eSSepherosa Ziehau {
215179251f5eSSepherosa Ziehau struct ixgbe_hw *hw = &sc->hw;
215279251f5eSSepherosa Ziehau int i;
215379251f5eSSepherosa Ziehau
215479251f5eSSepherosa Ziehau /*
215579251f5eSSepherosa Ziehau * Setup the Base and Length of the Tx Descriptor Ring
215679251f5eSSepherosa Ziehau */
215779251f5eSSepherosa Ziehau for (i = 0; i < sc->tx_ring_inuse; ++i) {
215879251f5eSSepherosa Ziehau struct ix_tx_ring *txr = &sc->tx_rings[i];
215979251f5eSSepherosa Ziehau uint64_t tdba = txr->tx_base_paddr;
216079251f5eSSepherosa Ziehau uint64_t hdr_paddr = txr->tx_hdr_paddr;
216179251f5eSSepherosa Ziehau uint32_t txctrl;
216279251f5eSSepherosa Ziehau
216379251f5eSSepherosa Ziehau IXGBE_WRITE_REG(hw, IXGBE_TDBAL(i), (uint32_t)tdba);
216479251f5eSSepherosa Ziehau IXGBE_WRITE_REG(hw, IXGBE_TDBAH(i), (uint32_t)(tdba >> 32));
216579251f5eSSepherosa Ziehau IXGBE_WRITE_REG(hw, IXGBE_TDLEN(i),
216679251f5eSSepherosa Ziehau txr->tx_ndesc * sizeof(union ixgbe_adv_tx_desc));
216779251f5eSSepherosa Ziehau
216879251f5eSSepherosa Ziehau /* Setup the HW Tx Head and Tail descriptor pointers */
216979251f5eSSepherosa Ziehau IXGBE_WRITE_REG(hw, IXGBE_TDH(i), 0);
217079251f5eSSepherosa Ziehau IXGBE_WRITE_REG(hw, IXGBE_TDT(i), 0);
217179251f5eSSepherosa Ziehau
217279251f5eSSepherosa Ziehau /* Disable TX head write-back relax ordering */
217379251f5eSSepherosa Ziehau switch (hw->mac.type) {
217479251f5eSSepherosa Ziehau case ixgbe_mac_82598EB:
217579251f5eSSepherosa Ziehau txctrl = IXGBE_READ_REG(hw, IXGBE_DCA_TXCTRL(i));
217679251f5eSSepherosa Ziehau break;
217779251f5eSSepherosa Ziehau default:
217879251f5eSSepherosa Ziehau txctrl = IXGBE_READ_REG(hw, IXGBE_DCA_TXCTRL_82599(i));
217979251f5eSSepherosa Ziehau break;
218079251f5eSSepherosa Ziehau }
218179251f5eSSepherosa Ziehau txctrl &= ~IXGBE_DCA_TXCTRL_DESC_WRO_EN;
218279251f5eSSepherosa Ziehau switch (hw->mac.type) {
218379251f5eSSepherosa Ziehau case ixgbe_mac_82598EB:
218479251f5eSSepherosa Ziehau IXGBE_WRITE_REG(hw, IXGBE_DCA_TXCTRL(i), txctrl);
218579251f5eSSepherosa Ziehau break;
218679251f5eSSepherosa Ziehau default:
218779251f5eSSepherosa Ziehau IXGBE_WRITE_REG(hw, IXGBE_DCA_TXCTRL_82599(i), txctrl);
218879251f5eSSepherosa Ziehau break;
218979251f5eSSepherosa Ziehau }
219079251f5eSSepherosa Ziehau
219179251f5eSSepherosa Ziehau /* Enable TX head write-back */
219279251f5eSSepherosa Ziehau IXGBE_WRITE_REG(hw, IXGBE_TDWBAH(i),
219379251f5eSSepherosa Ziehau (uint32_t)(hdr_paddr >> 32));
219479251f5eSSepherosa Ziehau IXGBE_WRITE_REG(hw, IXGBE_TDWBAL(i),
219579251f5eSSepherosa Ziehau ((uint32_t)hdr_paddr) | IXGBE_TDWBAL_HEAD_WB_ENABLE);
219679251f5eSSepherosa Ziehau }
219779251f5eSSepherosa Ziehau
219879251f5eSSepherosa Ziehau if (hw->mac.type != ixgbe_mac_82598EB) {
219979251f5eSSepherosa Ziehau uint32_t dmatxctl, rttdcs;
220079251f5eSSepherosa Ziehau
220179251f5eSSepherosa Ziehau dmatxctl = IXGBE_READ_REG(hw, IXGBE_DMATXCTL);
220279251f5eSSepherosa Ziehau dmatxctl |= IXGBE_DMATXCTL_TE;
220379251f5eSSepherosa Ziehau IXGBE_WRITE_REG(hw, IXGBE_DMATXCTL, dmatxctl);
220479251f5eSSepherosa Ziehau
220579251f5eSSepherosa Ziehau /* Disable arbiter to set MTQC */
220679251f5eSSepherosa Ziehau rttdcs = IXGBE_READ_REG(hw, IXGBE_RTTDCS);
220779251f5eSSepherosa Ziehau rttdcs |= IXGBE_RTTDCS_ARBDIS;
220879251f5eSSepherosa Ziehau IXGBE_WRITE_REG(hw, IXGBE_RTTDCS, rttdcs);
220979251f5eSSepherosa Ziehau
221079251f5eSSepherosa Ziehau IXGBE_WRITE_REG(hw, IXGBE_MTQC, IXGBE_MTQC_64Q_1PB);
221179251f5eSSepherosa Ziehau
221279251f5eSSepherosa Ziehau /* Reenable aribter */
221379251f5eSSepherosa Ziehau rttdcs &= ~IXGBE_RTTDCS_ARBDIS;
221479251f5eSSepherosa Ziehau IXGBE_WRITE_REG(hw, IXGBE_RTTDCS, rttdcs);
221579251f5eSSepherosa Ziehau }
221679251f5eSSepherosa Ziehau }
221779251f5eSSepherosa Ziehau
221879251f5eSSepherosa Ziehau static int
ix_tx_ctx_setup(struct ix_tx_ring * txr,const struct mbuf * mp,uint32_t * cmd_type_len,uint32_t * olinfo_status)221979251f5eSSepherosa Ziehau ix_tx_ctx_setup(struct ix_tx_ring *txr, const struct mbuf *mp,
222079251f5eSSepherosa Ziehau uint32_t *cmd_type_len, uint32_t *olinfo_status)
222179251f5eSSepherosa Ziehau {
222279251f5eSSepherosa Ziehau struct ixgbe_adv_tx_context_desc *TXD;
222379251f5eSSepherosa Ziehau uint32_t vlan_macip_lens = 0, type_tucmd_mlhl = 0;
222479251f5eSSepherosa Ziehau int ehdrlen, ip_hlen = 0, ctxd;
222579251f5eSSepherosa Ziehau boolean_t offload = TRUE;
222679251f5eSSepherosa Ziehau
222779251f5eSSepherosa Ziehau /* First check if TSO is to be used */
222879251f5eSSepherosa Ziehau if (mp->m_pkthdr.csum_flags & CSUM_TSO) {
222979251f5eSSepherosa Ziehau return ix_tso_ctx_setup(txr, mp,
223079251f5eSSepherosa Ziehau cmd_type_len, olinfo_status);
223179251f5eSSepherosa Ziehau }
223279251f5eSSepherosa Ziehau
223379251f5eSSepherosa Ziehau if ((mp->m_pkthdr.csum_flags & CSUM_OFFLOAD) == 0)
223479251f5eSSepherosa Ziehau offload = FALSE;
223579251f5eSSepherosa Ziehau
223679251f5eSSepherosa Ziehau /* Indicate the whole packet as payload when not doing TSO */
223779251f5eSSepherosa Ziehau *olinfo_status |= mp->m_pkthdr.len << IXGBE_ADVTXD_PAYLEN_SHIFT;
223879251f5eSSepherosa Ziehau
223979251f5eSSepherosa Ziehau /*
224079251f5eSSepherosa Ziehau * In advanced descriptors the vlan tag must be placed into the
224179251f5eSSepherosa Ziehau * context descriptor. Hence we need to make one even if not
224279251f5eSSepherosa Ziehau * doing checksum offloads.
224379251f5eSSepherosa Ziehau */
224479251f5eSSepherosa Ziehau if (mp->m_flags & M_VLANTAG) {
224579251f5eSSepherosa Ziehau vlan_macip_lens |= htole16(mp->m_pkthdr.ether_vlantag) <<
224679251f5eSSepherosa Ziehau IXGBE_ADVTXD_VLAN_SHIFT;
224779251f5eSSepherosa Ziehau } else if (!offload) {
224879251f5eSSepherosa Ziehau /* No TX descriptor is consumed */
224979251f5eSSepherosa Ziehau return 0;
225079251f5eSSepherosa Ziehau }
225179251f5eSSepherosa Ziehau
225279251f5eSSepherosa Ziehau /* Set the ether header length */
225379251f5eSSepherosa Ziehau ehdrlen = mp->m_pkthdr.csum_lhlen;
225479251f5eSSepherosa Ziehau KASSERT(ehdrlen > 0, ("invalid ether hlen"));
225579251f5eSSepherosa Ziehau vlan_macip_lens |= ehdrlen << IXGBE_ADVTXD_MACLEN_SHIFT;
225679251f5eSSepherosa Ziehau
225779251f5eSSepherosa Ziehau if (mp->m_pkthdr.csum_flags & CSUM_IP) {
225879251f5eSSepherosa Ziehau *olinfo_status |= IXGBE_TXD_POPTS_IXSM << 8;
225979251f5eSSepherosa Ziehau type_tucmd_mlhl |= IXGBE_ADVTXD_TUCMD_IPV4;
226079251f5eSSepherosa Ziehau ip_hlen = mp->m_pkthdr.csum_iphlen;
226179251f5eSSepherosa Ziehau KASSERT(ip_hlen > 0, ("invalid ip hlen"));
226279251f5eSSepherosa Ziehau }
226379251f5eSSepherosa Ziehau vlan_macip_lens |= ip_hlen;
226479251f5eSSepherosa Ziehau
226579251f5eSSepherosa Ziehau type_tucmd_mlhl |= IXGBE_ADVTXD_DCMD_DEXT | IXGBE_ADVTXD_DTYP_CTXT;
226679251f5eSSepherosa Ziehau if (mp->m_pkthdr.csum_flags & CSUM_TCP)
226779251f5eSSepherosa Ziehau type_tucmd_mlhl |= IXGBE_ADVTXD_TUCMD_L4T_TCP;
226879251f5eSSepherosa Ziehau else if (mp->m_pkthdr.csum_flags & CSUM_UDP)
226979251f5eSSepherosa Ziehau type_tucmd_mlhl |= IXGBE_ADVTXD_TUCMD_L4T_UDP;
227079251f5eSSepherosa Ziehau
227179251f5eSSepherosa Ziehau if (mp->m_pkthdr.csum_flags & (CSUM_TCP | CSUM_UDP))
227279251f5eSSepherosa Ziehau *olinfo_status |= IXGBE_TXD_POPTS_TXSM << 8;
227379251f5eSSepherosa Ziehau
227479251f5eSSepherosa Ziehau /* Now ready a context descriptor */
227579251f5eSSepherosa Ziehau ctxd = txr->tx_next_avail;
227679251f5eSSepherosa Ziehau TXD = (struct ixgbe_adv_tx_context_desc *)&txr->tx_base[ctxd];
227779251f5eSSepherosa Ziehau
227879251f5eSSepherosa Ziehau /* Now copy bits into descriptor */
227979251f5eSSepherosa Ziehau TXD->vlan_macip_lens = htole32(vlan_macip_lens);
228079251f5eSSepherosa Ziehau TXD->type_tucmd_mlhl = htole32(type_tucmd_mlhl);
228179251f5eSSepherosa Ziehau TXD->seqnum_seed = htole32(0);
228279251f5eSSepherosa Ziehau TXD->mss_l4len_idx = htole32(0);
228379251f5eSSepherosa Ziehau
228479251f5eSSepherosa Ziehau /* We've consumed the first desc, adjust counters */
228579251f5eSSepherosa Ziehau if (++ctxd == txr->tx_ndesc)
228679251f5eSSepherosa Ziehau ctxd = 0;
228779251f5eSSepherosa Ziehau txr->tx_next_avail = ctxd;
228879251f5eSSepherosa Ziehau --txr->tx_avail;
228979251f5eSSepherosa Ziehau
229079251f5eSSepherosa Ziehau /* One TX descriptor is consumed */
229179251f5eSSepherosa Ziehau return 1;
229279251f5eSSepherosa Ziehau }
229379251f5eSSepherosa Ziehau
229479251f5eSSepherosa Ziehau static int
ix_tso_ctx_setup(struct ix_tx_ring * txr,const struct mbuf * mp,uint32_t * cmd_type_len,uint32_t * olinfo_status)229579251f5eSSepherosa Ziehau ix_tso_ctx_setup(struct ix_tx_ring *txr, const struct mbuf *mp,
229679251f5eSSepherosa Ziehau uint32_t *cmd_type_len, uint32_t *olinfo_status)
229779251f5eSSepherosa Ziehau {
229879251f5eSSepherosa Ziehau struct ixgbe_adv_tx_context_desc *TXD;
229979251f5eSSepherosa Ziehau uint32_t vlan_macip_lens = 0, type_tucmd_mlhl = 0;
230079251f5eSSepherosa Ziehau uint32_t mss_l4len_idx = 0, paylen;
230179251f5eSSepherosa Ziehau int ctxd, ehdrlen, ip_hlen, tcp_hlen;
230279251f5eSSepherosa Ziehau
230379251f5eSSepherosa Ziehau ehdrlen = mp->m_pkthdr.csum_lhlen;
230479251f5eSSepherosa Ziehau KASSERT(ehdrlen > 0, ("invalid ether hlen"));
230579251f5eSSepherosa Ziehau
230679251f5eSSepherosa Ziehau ip_hlen = mp->m_pkthdr.csum_iphlen;
230779251f5eSSepherosa Ziehau KASSERT(ip_hlen > 0, ("invalid ip hlen"));
230879251f5eSSepherosa Ziehau
230979251f5eSSepherosa Ziehau tcp_hlen = mp->m_pkthdr.csum_thlen;
231079251f5eSSepherosa Ziehau KASSERT(tcp_hlen > 0, ("invalid tcp hlen"));
231179251f5eSSepherosa Ziehau
231279251f5eSSepherosa Ziehau ctxd = txr->tx_next_avail;
231379251f5eSSepherosa Ziehau TXD = (struct ixgbe_adv_tx_context_desc *) &txr->tx_base[ctxd];
231479251f5eSSepherosa Ziehau
231579251f5eSSepherosa Ziehau if (mp->m_flags & M_VLANTAG) {
231679251f5eSSepherosa Ziehau vlan_macip_lens |= htole16(mp->m_pkthdr.ether_vlantag) <<
231779251f5eSSepherosa Ziehau IXGBE_ADVTXD_VLAN_SHIFT;
231879251f5eSSepherosa Ziehau }
231979251f5eSSepherosa Ziehau vlan_macip_lens |= ehdrlen << IXGBE_ADVTXD_MACLEN_SHIFT;
232079251f5eSSepherosa Ziehau vlan_macip_lens |= ip_hlen;
232179251f5eSSepherosa Ziehau TXD->vlan_macip_lens = htole32(vlan_macip_lens);
232279251f5eSSepherosa Ziehau
232379251f5eSSepherosa Ziehau /* ADV DTYPE TUCMD */
232479251f5eSSepherosa Ziehau type_tucmd_mlhl |= IXGBE_ADVTXD_TUCMD_IPV4;
232579251f5eSSepherosa Ziehau type_tucmd_mlhl |= IXGBE_ADVTXD_DCMD_DEXT | IXGBE_ADVTXD_DTYP_CTXT;
232679251f5eSSepherosa Ziehau type_tucmd_mlhl |= IXGBE_ADVTXD_TUCMD_L4T_TCP;
232779251f5eSSepherosa Ziehau TXD->type_tucmd_mlhl = htole32(type_tucmd_mlhl);
232879251f5eSSepherosa Ziehau
232979251f5eSSepherosa Ziehau /* MSS L4LEN IDX */
233079251f5eSSepherosa Ziehau mss_l4len_idx |= (mp->m_pkthdr.tso_segsz << IXGBE_ADVTXD_MSS_SHIFT);
233179251f5eSSepherosa Ziehau mss_l4len_idx |= (tcp_hlen << IXGBE_ADVTXD_L4LEN_SHIFT);
233279251f5eSSepherosa Ziehau TXD->mss_l4len_idx = htole32(mss_l4len_idx);
233379251f5eSSepherosa Ziehau
233479251f5eSSepherosa Ziehau TXD->seqnum_seed = htole32(0);
233579251f5eSSepherosa Ziehau
233679251f5eSSepherosa Ziehau if (++ctxd == txr->tx_ndesc)
233779251f5eSSepherosa Ziehau ctxd = 0;
233879251f5eSSepherosa Ziehau
233979251f5eSSepherosa Ziehau txr->tx_avail--;
234079251f5eSSepherosa Ziehau txr->tx_next_avail = ctxd;
234179251f5eSSepherosa Ziehau
234279251f5eSSepherosa Ziehau *cmd_type_len |= IXGBE_ADVTXD_DCMD_TSE;
234379251f5eSSepherosa Ziehau
234479251f5eSSepherosa Ziehau /* This is used in the transmit desc in encap */
234579251f5eSSepherosa Ziehau paylen = mp->m_pkthdr.len - ehdrlen - ip_hlen - tcp_hlen;
234679251f5eSSepherosa Ziehau
234779251f5eSSepherosa Ziehau *olinfo_status |= IXGBE_TXD_POPTS_IXSM << 8;
234879251f5eSSepherosa Ziehau *olinfo_status |= IXGBE_TXD_POPTS_TXSM << 8;
234979251f5eSSepherosa Ziehau *olinfo_status |= paylen << IXGBE_ADVTXD_PAYLEN_SHIFT;
235079251f5eSSepherosa Ziehau
235179251f5eSSepherosa Ziehau /* One TX descriptor is consumed */
235279251f5eSSepherosa Ziehau return 1;
235379251f5eSSepherosa Ziehau }
235479251f5eSSepherosa Ziehau
235579251f5eSSepherosa Ziehau static void
ix_txeof(struct ix_tx_ring * txr,int hdr)2356189a0ff3SSepherosa Ziehau ix_txeof(struct ix_tx_ring *txr, int hdr)
235779251f5eSSepherosa Ziehau {
2358189a0ff3SSepherosa Ziehau int first, avail;
235979251f5eSSepherosa Ziehau
236079251f5eSSepherosa Ziehau if (txr->tx_avail == txr->tx_ndesc)
236179251f5eSSepherosa Ziehau return;
236279251f5eSSepherosa Ziehau
236379251f5eSSepherosa Ziehau first = txr->tx_next_clean;
236479251f5eSSepherosa Ziehau if (first == hdr)
236579251f5eSSepherosa Ziehau return;
236679251f5eSSepherosa Ziehau
236779251f5eSSepherosa Ziehau avail = txr->tx_avail;
236879251f5eSSepherosa Ziehau while (first != hdr) {
236979251f5eSSepherosa Ziehau struct ix_tx_buf *txbuf = &txr->tx_buf[first];
237079251f5eSSepherosa Ziehau
237182db96e9SSepherosa Ziehau KKASSERT(avail < txr->tx_ndesc);
237279251f5eSSepherosa Ziehau ++avail;
237382db96e9SSepherosa Ziehau
237482db96e9SSepherosa Ziehau if (txbuf->m_head != NULL)
237582db96e9SSepherosa Ziehau ix_free_txbuf(txr, txbuf);
237679251f5eSSepherosa Ziehau if (++first == txr->tx_ndesc)
237779251f5eSSepherosa Ziehau first = 0;
237879251f5eSSepherosa Ziehau }
237979251f5eSSepherosa Ziehau txr->tx_next_clean = first;
238079251f5eSSepherosa Ziehau txr->tx_avail = avail;
238179251f5eSSepherosa Ziehau
238279251f5eSSepherosa Ziehau if (txr->tx_avail > IX_MAX_SCATTER + IX_TX_RESERVED) {
238379251f5eSSepherosa Ziehau ifsq_clr_oactive(txr->tx_ifsq);
2384e2292763SMatthew Dillon ifsq_watchdog_set_count(&txr->tx_watchdog, 0);
238579251f5eSSepherosa Ziehau }
238682db96e9SSepherosa Ziehau txr->tx_running = IX_TX_RUNNING;
238782db96e9SSepherosa Ziehau }
238882db96e9SSepherosa Ziehau
238982db96e9SSepherosa Ziehau static void
ix_txgc(struct ix_tx_ring * txr)239082db96e9SSepherosa Ziehau ix_txgc(struct ix_tx_ring *txr)
239182db96e9SSepherosa Ziehau {
239282db96e9SSepherosa Ziehau int first, hdr;
239382db96e9SSepherosa Ziehau #ifdef INVARIANTS
239482db96e9SSepherosa Ziehau int avail;
239582db96e9SSepherosa Ziehau #endif
239682db96e9SSepherosa Ziehau
239782db96e9SSepherosa Ziehau if (txr->tx_avail == txr->tx_ndesc)
239882db96e9SSepherosa Ziehau return;
239982db96e9SSepherosa Ziehau
240082db96e9SSepherosa Ziehau hdr = IXGBE_READ_REG(&txr->tx_sc->hw, IXGBE_TDH(txr->tx_idx));
240182db96e9SSepherosa Ziehau first = txr->tx_next_clean;
240282db96e9SSepherosa Ziehau if (first == hdr)
24035ae4b2e8SSepherosa Ziehau goto done;
240482db96e9SSepherosa Ziehau txr->tx_gc++;
240582db96e9SSepherosa Ziehau
240682db96e9SSepherosa Ziehau #ifdef INVARIANTS
240782db96e9SSepherosa Ziehau avail = txr->tx_avail;
240882db96e9SSepherosa Ziehau #endif
240982db96e9SSepherosa Ziehau while (first != hdr) {
241082db96e9SSepherosa Ziehau struct ix_tx_buf *txbuf = &txr->tx_buf[first];
241182db96e9SSepherosa Ziehau
241282db96e9SSepherosa Ziehau #ifdef INVARIANTS
241382db96e9SSepherosa Ziehau KKASSERT(avail < txr->tx_ndesc);
241482db96e9SSepherosa Ziehau ++avail;
241582db96e9SSepherosa Ziehau #endif
241682db96e9SSepherosa Ziehau if (txbuf->m_head != NULL)
241782db96e9SSepherosa Ziehau ix_free_txbuf(txr, txbuf);
241882db96e9SSepherosa Ziehau if (++first == txr->tx_ndesc)
241982db96e9SSepherosa Ziehau first = 0;
242082db96e9SSepherosa Ziehau }
24215ae4b2e8SSepherosa Ziehau done:
242282db96e9SSepherosa Ziehau if (txr->tx_nmbuf)
242382db96e9SSepherosa Ziehau txr->tx_running = IX_TX_RUNNING;
242479251f5eSSepherosa Ziehau }
242579251f5eSSepherosa Ziehau
242679251f5eSSepherosa Ziehau static int
ix_create_rx_ring(struct ix_rx_ring * rxr)242779251f5eSSepherosa Ziehau ix_create_rx_ring(struct ix_rx_ring *rxr)
242879251f5eSSepherosa Ziehau {
242979251f5eSSepherosa Ziehau int i, rsize, error, nrxd;
243079251f5eSSepherosa Ziehau
243179251f5eSSepherosa Ziehau /*
243279251f5eSSepherosa Ziehau * Validate number of receive descriptors. It must not exceed
243379251f5eSSepherosa Ziehau * hardware maximum, and must be multiple of IX_DBA_ALIGN.
243479251f5eSSepherosa Ziehau */
243579251f5eSSepherosa Ziehau nrxd = device_getenv_int(rxr->rx_sc->dev, "rxd", ix_rxd);
243679251f5eSSepherosa Ziehau if (((nrxd * sizeof(union ixgbe_adv_rx_desc)) % IX_DBA_ALIGN) != 0 ||
243779251f5eSSepherosa Ziehau nrxd < IX_MIN_RXD || nrxd > IX_MAX_RXD) {
243879251f5eSSepherosa Ziehau device_printf(rxr->rx_sc->dev,
243979251f5eSSepherosa Ziehau "Using %d RX descriptors instead of %d!\n",
244079251f5eSSepherosa Ziehau IX_DEF_RXD, nrxd);
244179251f5eSSepherosa Ziehau rxr->rx_ndesc = IX_DEF_RXD;
244279251f5eSSepherosa Ziehau } else {
244379251f5eSSepherosa Ziehau rxr->rx_ndesc = nrxd;
244479251f5eSSepherosa Ziehau }
244579251f5eSSepherosa Ziehau
244679251f5eSSepherosa Ziehau /*
244779251f5eSSepherosa Ziehau * Allocate RX descriptor ring
244879251f5eSSepherosa Ziehau */
244979251f5eSSepherosa Ziehau rsize = roundup2(rxr->rx_ndesc * sizeof(union ixgbe_adv_rx_desc),
245079251f5eSSepherosa Ziehau IX_DBA_ALIGN);
245179251f5eSSepherosa Ziehau rxr->rx_base = bus_dmamem_coherent_any(rxr->rx_sc->parent_tag,
245279251f5eSSepherosa Ziehau IX_DBA_ALIGN, rsize, BUS_DMA_WAITOK | BUS_DMA_ZERO,
245379251f5eSSepherosa Ziehau &rxr->rx_base_dtag, &rxr->rx_base_map, &rxr->rx_base_paddr);
245479251f5eSSepherosa Ziehau if (rxr->rx_base == NULL) {
245579251f5eSSepherosa Ziehau device_printf(rxr->rx_sc->dev,
245679251f5eSSepherosa Ziehau "Unable to allocate TX Descriptor memory\n");
245779251f5eSSepherosa Ziehau return ENOMEM;
245879251f5eSSepherosa Ziehau }
245979251f5eSSepherosa Ziehau
246079251f5eSSepherosa Ziehau rsize = __VM_CACHELINE_ALIGN(sizeof(struct ix_rx_buf) * rxr->rx_ndesc);
246162938642SMatthew Dillon rxr->rx_buf = kmalloc(rsize, M_DEVBUF,
246262938642SMatthew Dillon M_WAITOK | M_ZERO | M_CACHEALIGN);
246379251f5eSSepherosa Ziehau
246479251f5eSSepherosa Ziehau /*
246579251f5eSSepherosa Ziehau * Create DMA tag for RX buffers
246679251f5eSSepherosa Ziehau */
246779251f5eSSepherosa Ziehau error = bus_dma_tag_create(rxr->rx_sc->parent_tag,
246879251f5eSSepherosa Ziehau 1, 0, /* alignment, bounds */
246979251f5eSSepherosa Ziehau BUS_SPACE_MAXADDR, /* lowaddr */
247079251f5eSSepherosa Ziehau BUS_SPACE_MAXADDR, /* highaddr */
247179251f5eSSepherosa Ziehau PAGE_SIZE, /* maxsize */
247279251f5eSSepherosa Ziehau 1, /* nsegments */
247379251f5eSSepherosa Ziehau PAGE_SIZE, /* maxsegsize */
247479251f5eSSepherosa Ziehau BUS_DMA_WAITOK | BUS_DMA_ALLOCNOW, /* flags */
247579251f5eSSepherosa Ziehau &rxr->rx_tag);
247679251f5eSSepherosa Ziehau if (error) {
247779251f5eSSepherosa Ziehau device_printf(rxr->rx_sc->dev,
247879251f5eSSepherosa Ziehau "Unable to create RX DMA tag\n");
247979251f5eSSepherosa Ziehau kfree(rxr->rx_buf, M_DEVBUF);
248079251f5eSSepherosa Ziehau rxr->rx_buf = NULL;
248179251f5eSSepherosa Ziehau return error;
248279251f5eSSepherosa Ziehau }
248379251f5eSSepherosa Ziehau
248479251f5eSSepherosa Ziehau /*
248579251f5eSSepherosa Ziehau * Create spare DMA map for RX buffers
248679251f5eSSepherosa Ziehau */
248779251f5eSSepherosa Ziehau error = bus_dmamap_create(rxr->rx_tag, BUS_DMA_WAITOK,
248879251f5eSSepherosa Ziehau &rxr->rx_sparemap);
248979251f5eSSepherosa Ziehau if (error) {
249079251f5eSSepherosa Ziehau device_printf(rxr->rx_sc->dev,
249179251f5eSSepherosa Ziehau "Unable to create spare RX DMA map\n");
249279251f5eSSepherosa Ziehau bus_dma_tag_destroy(rxr->rx_tag);
249379251f5eSSepherosa Ziehau kfree(rxr->rx_buf, M_DEVBUF);
249479251f5eSSepherosa Ziehau rxr->rx_buf = NULL;
249579251f5eSSepherosa Ziehau return error;
249679251f5eSSepherosa Ziehau }
249779251f5eSSepherosa Ziehau
249879251f5eSSepherosa Ziehau /*
249979251f5eSSepherosa Ziehau * Create DMA maps for RX buffers
250079251f5eSSepherosa Ziehau */
250179251f5eSSepherosa Ziehau for (i = 0; i < rxr->rx_ndesc; ++i) {
250279251f5eSSepherosa Ziehau struct ix_rx_buf *rxbuf = &rxr->rx_buf[i];
250379251f5eSSepherosa Ziehau
250479251f5eSSepherosa Ziehau error = bus_dmamap_create(rxr->rx_tag,
250579251f5eSSepherosa Ziehau BUS_DMA_WAITOK, &rxbuf->map);
250679251f5eSSepherosa Ziehau if (error) {
250779251f5eSSepherosa Ziehau device_printf(rxr->rx_sc->dev,
250879251f5eSSepherosa Ziehau "Unable to create RX dma map\n");
250979251f5eSSepherosa Ziehau ix_destroy_rx_ring(rxr, i);
251079251f5eSSepherosa Ziehau return error;
251179251f5eSSepherosa Ziehau }
251279251f5eSSepherosa Ziehau }
251379251f5eSSepherosa Ziehau
251479251f5eSSepherosa Ziehau /*
251579251f5eSSepherosa Ziehau * Initialize various watermark
251679251f5eSSepherosa Ziehau */
251779251f5eSSepherosa Ziehau rxr->rx_wreg_nsegs = IX_DEF_RXWREG_NSEGS;
251879251f5eSSepherosa Ziehau
251979251f5eSSepherosa Ziehau return 0;
252079251f5eSSepherosa Ziehau }
252179251f5eSSepherosa Ziehau
252279251f5eSSepherosa Ziehau static void
ix_destroy_rx_ring(struct ix_rx_ring * rxr,int ndesc)252379251f5eSSepherosa Ziehau ix_destroy_rx_ring(struct ix_rx_ring *rxr, int ndesc)
252479251f5eSSepherosa Ziehau {
252579251f5eSSepherosa Ziehau int i;
252679251f5eSSepherosa Ziehau
252779251f5eSSepherosa Ziehau if (rxr->rx_base != NULL) {
252879251f5eSSepherosa Ziehau bus_dmamap_unload(rxr->rx_base_dtag, rxr->rx_base_map);
252979251f5eSSepherosa Ziehau bus_dmamem_free(rxr->rx_base_dtag, rxr->rx_base,
253079251f5eSSepherosa Ziehau rxr->rx_base_map);
253179251f5eSSepherosa Ziehau bus_dma_tag_destroy(rxr->rx_base_dtag);
253279251f5eSSepherosa Ziehau rxr->rx_base = NULL;
253379251f5eSSepherosa Ziehau }
253479251f5eSSepherosa Ziehau
253579251f5eSSepherosa Ziehau if (rxr->rx_buf == NULL)
253679251f5eSSepherosa Ziehau return;
253779251f5eSSepherosa Ziehau
253879251f5eSSepherosa Ziehau for (i = 0; i < ndesc; ++i) {
253979251f5eSSepherosa Ziehau struct ix_rx_buf *rxbuf = &rxr->rx_buf[i];
254079251f5eSSepherosa Ziehau
254179251f5eSSepherosa Ziehau KKASSERT(rxbuf->m_head == NULL);
254279251f5eSSepherosa Ziehau bus_dmamap_destroy(rxr->rx_tag, rxbuf->map);
254379251f5eSSepherosa Ziehau }
254479251f5eSSepherosa Ziehau bus_dmamap_destroy(rxr->rx_tag, rxr->rx_sparemap);
254579251f5eSSepherosa Ziehau bus_dma_tag_destroy(rxr->rx_tag);
254679251f5eSSepherosa Ziehau
254779251f5eSSepherosa Ziehau kfree(rxr->rx_buf, M_DEVBUF);
254879251f5eSSepherosa Ziehau rxr->rx_buf = NULL;
254979251f5eSSepherosa Ziehau }
255079251f5eSSepherosa Ziehau
255179251f5eSSepherosa Ziehau /*
255279251f5eSSepherosa Ziehau ** Used to detect a descriptor that has
255379251f5eSSepherosa Ziehau ** been merged by Hardware RSC.
255479251f5eSSepherosa Ziehau */
255579251f5eSSepherosa Ziehau static __inline uint32_t
ix_rsc_count(union ixgbe_adv_rx_desc * rx)255679251f5eSSepherosa Ziehau ix_rsc_count(union ixgbe_adv_rx_desc *rx)
255779251f5eSSepherosa Ziehau {
255879251f5eSSepherosa Ziehau return (le32toh(rx->wb.lower.lo_dword.data) &
255979251f5eSSepherosa Ziehau IXGBE_RXDADV_RSCCNT_MASK) >> IXGBE_RXDADV_RSCCNT_SHIFT;
256079251f5eSSepherosa Ziehau }
256179251f5eSSepherosa Ziehau
256279251f5eSSepherosa Ziehau #if 0
256379251f5eSSepherosa Ziehau /*********************************************************************
256479251f5eSSepherosa Ziehau *
256579251f5eSSepherosa Ziehau * Initialize Hardware RSC (LRO) feature on 82599
256679251f5eSSepherosa Ziehau * for an RX ring, this is toggled by the LRO capability
256779251f5eSSepherosa Ziehau * even though it is transparent to the stack.
256879251f5eSSepherosa Ziehau *
256979251f5eSSepherosa Ziehau * NOTE: since this HW feature only works with IPV4 and
257079251f5eSSepherosa Ziehau * our testing has shown soft LRO to be as effective
257179251f5eSSepherosa Ziehau * I have decided to disable this by default.
257279251f5eSSepherosa Ziehau *
257379251f5eSSepherosa Ziehau **********************************************************************/
257479251f5eSSepherosa Ziehau static void
257579251f5eSSepherosa Ziehau ix_setup_hw_rsc(struct ix_rx_ring *rxr)
257679251f5eSSepherosa Ziehau {
257779251f5eSSepherosa Ziehau struct ix_softc *sc = rxr->rx_sc;
257879251f5eSSepherosa Ziehau struct ixgbe_hw *hw = &sc->hw;
257979251f5eSSepherosa Ziehau uint32_t rscctrl, rdrxctl;
258079251f5eSSepherosa Ziehau
258179251f5eSSepherosa Ziehau #if 0
258279251f5eSSepherosa Ziehau /* If turning LRO/RSC off we need to disable it */
258379251f5eSSepherosa Ziehau if ((sc->arpcom.ac_if.if_capenable & IFCAP_LRO) == 0) {
258479251f5eSSepherosa Ziehau rscctrl = IXGBE_READ_REG(hw, IXGBE_RSCCTL(rxr->me));
258579251f5eSSepherosa Ziehau rscctrl &= ~IXGBE_RSCCTL_RSCEN;
258679251f5eSSepherosa Ziehau return;
258779251f5eSSepherosa Ziehau }
258879251f5eSSepherosa Ziehau #endif
258979251f5eSSepherosa Ziehau
259079251f5eSSepherosa Ziehau rdrxctl = IXGBE_READ_REG(hw, IXGBE_RDRXCTL);
259179251f5eSSepherosa Ziehau rdrxctl &= ~IXGBE_RDRXCTL_RSCFRSTSIZE;
259279251f5eSSepherosa Ziehau rdrxctl |= IXGBE_RDRXCTL_CRCSTRIP;
259379251f5eSSepherosa Ziehau rdrxctl |= IXGBE_RDRXCTL_RSCACKC;
259479251f5eSSepherosa Ziehau IXGBE_WRITE_REG(hw, IXGBE_RDRXCTL, rdrxctl);
259579251f5eSSepherosa Ziehau
259679251f5eSSepherosa Ziehau rscctrl = IXGBE_READ_REG(hw, IXGBE_RSCCTL(rxr->me));
259779251f5eSSepherosa Ziehau rscctrl |= IXGBE_RSCCTL_RSCEN;
259879251f5eSSepherosa Ziehau /*
259979251f5eSSepherosa Ziehau ** Limit the total number of descriptors that
260079251f5eSSepherosa Ziehau ** can be combined, so it does not exceed 64K
260179251f5eSSepherosa Ziehau */
260279251f5eSSepherosa Ziehau if (rxr->mbuf_sz == MCLBYTES)
260379251f5eSSepherosa Ziehau rscctrl |= IXGBE_RSCCTL_MAXDESC_16;
260479251f5eSSepherosa Ziehau else if (rxr->mbuf_sz == MJUMPAGESIZE)
260579251f5eSSepherosa Ziehau rscctrl |= IXGBE_RSCCTL_MAXDESC_8;
260679251f5eSSepherosa Ziehau else if (rxr->mbuf_sz == MJUM9BYTES)
260779251f5eSSepherosa Ziehau rscctrl |= IXGBE_RSCCTL_MAXDESC_4;
260879251f5eSSepherosa Ziehau else /* Using 16K cluster */
260979251f5eSSepherosa Ziehau rscctrl |= IXGBE_RSCCTL_MAXDESC_1;
261079251f5eSSepherosa Ziehau
261179251f5eSSepherosa Ziehau IXGBE_WRITE_REG(hw, IXGBE_RSCCTL(rxr->me), rscctrl);
261279251f5eSSepherosa Ziehau
261379251f5eSSepherosa Ziehau /* Enable TCP header recognition */
261479251f5eSSepherosa Ziehau IXGBE_WRITE_REG(hw, IXGBE_PSRTYPE(0),
261579251f5eSSepherosa Ziehau (IXGBE_READ_REG(hw, IXGBE_PSRTYPE(0)) |
261679251f5eSSepherosa Ziehau IXGBE_PSRTYPE_TCPHDR));
261779251f5eSSepherosa Ziehau
261879251f5eSSepherosa Ziehau /* Disable RSC for ACK packets */
261979251f5eSSepherosa Ziehau IXGBE_WRITE_REG(hw, IXGBE_RSCDBU,
262079251f5eSSepherosa Ziehau (IXGBE_RSCDBU_RSCACKDIS | IXGBE_READ_REG(hw, IXGBE_RSCDBU)));
262179251f5eSSepherosa Ziehau
262279251f5eSSepherosa Ziehau rxr->hw_rsc = TRUE;
262379251f5eSSepherosa Ziehau }
262479251f5eSSepherosa Ziehau #endif
262579251f5eSSepherosa Ziehau
262679251f5eSSepherosa Ziehau static int
ix_init_rx_ring(struct ix_rx_ring * rxr)262779251f5eSSepherosa Ziehau ix_init_rx_ring(struct ix_rx_ring *rxr)
262879251f5eSSepherosa Ziehau {
262979251f5eSSepherosa Ziehau int i;
263079251f5eSSepherosa Ziehau
263179251f5eSSepherosa Ziehau /* Clear the ring contents */
263279251f5eSSepherosa Ziehau bzero(rxr->rx_base, rxr->rx_ndesc * sizeof(union ixgbe_adv_rx_desc));
263379251f5eSSepherosa Ziehau
263479251f5eSSepherosa Ziehau /* XXX we need JUMPAGESIZE for RSC too */
263579251f5eSSepherosa Ziehau if (rxr->rx_sc->max_frame_size <= MCLBYTES)
263679251f5eSSepherosa Ziehau rxr->rx_mbuf_sz = MCLBYTES;
263779251f5eSSepherosa Ziehau else
263879251f5eSSepherosa Ziehau rxr->rx_mbuf_sz = MJUMPAGESIZE;
263979251f5eSSepherosa Ziehau
264079251f5eSSepherosa Ziehau /* Now replenish the mbufs */
264179251f5eSSepherosa Ziehau for (i = 0; i < rxr->rx_ndesc; ++i) {
264279251f5eSSepherosa Ziehau int error;
264379251f5eSSepherosa Ziehau
264479251f5eSSepherosa Ziehau error = ix_newbuf(rxr, i, TRUE);
264579251f5eSSepherosa Ziehau if (error)
264679251f5eSSepherosa Ziehau return error;
264779251f5eSSepherosa Ziehau }
264879251f5eSSepherosa Ziehau
264979251f5eSSepherosa Ziehau /* Setup our descriptor indices */
265079251f5eSSepherosa Ziehau rxr->rx_next_check = 0;
265179251f5eSSepherosa Ziehau rxr->rx_flags &= ~IX_RXRING_FLAG_DISC;
265279251f5eSSepherosa Ziehau
265379251f5eSSepherosa Ziehau #if 0
265479251f5eSSepherosa Ziehau /*
265579251f5eSSepherosa Ziehau ** Now set up the LRO interface:
265679251f5eSSepherosa Ziehau */
265779251f5eSSepherosa Ziehau if (ixgbe_rsc_enable)
265879251f5eSSepherosa Ziehau ix_setup_hw_rsc(rxr);
265979251f5eSSepherosa Ziehau #endif
266079251f5eSSepherosa Ziehau
266179251f5eSSepherosa Ziehau return 0;
266279251f5eSSepherosa Ziehau }
266379251f5eSSepherosa Ziehau
266479251f5eSSepherosa Ziehau #define IXGBE_SRRCTL_BSIZEHDRSIZE_SHIFT 2
266579251f5eSSepherosa Ziehau
266679251f5eSSepherosa Ziehau #define BSIZEPKT_ROUNDUP ((1<<IXGBE_SRRCTL_BSIZEPKT_SHIFT)-1)
266779251f5eSSepherosa Ziehau
266879251f5eSSepherosa Ziehau static void
ix_init_rx_unit(struct ix_softc * sc,boolean_t polling)26693c37d13bSSepherosa Ziehau ix_init_rx_unit(struct ix_softc *sc, boolean_t polling)
267079251f5eSSepherosa Ziehau {
267179251f5eSSepherosa Ziehau struct ixgbe_hw *hw = &sc->hw;
267279251f5eSSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if;
267363d483cdSSepherosa Ziehau uint32_t bufsz, fctrl, rxcsum, hlreg;
267479251f5eSSepherosa Ziehau int i;
267579251f5eSSepherosa Ziehau
267679251f5eSSepherosa Ziehau /*
267779251f5eSSepherosa Ziehau * Make sure receives are disabled while setting up the descriptor ring
267879251f5eSSepherosa Ziehau */
267963d483cdSSepherosa Ziehau ixgbe_disable_rx(hw);
268079251f5eSSepherosa Ziehau
268179251f5eSSepherosa Ziehau /* Enable broadcasts */
268279251f5eSSepherosa Ziehau fctrl = IXGBE_READ_REG(hw, IXGBE_FCTRL);
268379251f5eSSepherosa Ziehau fctrl |= IXGBE_FCTRL_BAM;
268463d483cdSSepherosa Ziehau if (hw->mac.type == ixgbe_mac_82598EB) {
268579251f5eSSepherosa Ziehau fctrl |= IXGBE_FCTRL_DPF;
268679251f5eSSepherosa Ziehau fctrl |= IXGBE_FCTRL_PMCF;
268763d483cdSSepherosa Ziehau }
268879251f5eSSepherosa Ziehau IXGBE_WRITE_REG(hw, IXGBE_FCTRL, fctrl);
268979251f5eSSepherosa Ziehau
269079251f5eSSepherosa Ziehau /* Set for Jumbo Frames? */
269179251f5eSSepherosa Ziehau hlreg = IXGBE_READ_REG(hw, IXGBE_HLREG0);
269279251f5eSSepherosa Ziehau if (ifp->if_mtu > ETHERMTU)
269379251f5eSSepherosa Ziehau hlreg |= IXGBE_HLREG0_JUMBOEN;
269479251f5eSSepherosa Ziehau else
269579251f5eSSepherosa Ziehau hlreg &= ~IXGBE_HLREG0_JUMBOEN;
269679251f5eSSepherosa Ziehau IXGBE_WRITE_REG(hw, IXGBE_HLREG0, hlreg);
269779251f5eSSepherosa Ziehau
269879251f5eSSepherosa Ziehau KKASSERT(sc->rx_rings[0].rx_mbuf_sz >= MCLBYTES);
269979251f5eSSepherosa Ziehau bufsz = (sc->rx_rings[0].rx_mbuf_sz + BSIZEPKT_ROUNDUP) >>
270079251f5eSSepherosa Ziehau IXGBE_SRRCTL_BSIZEPKT_SHIFT;
270179251f5eSSepherosa Ziehau
270279251f5eSSepherosa Ziehau for (i = 0; i < sc->rx_ring_inuse; ++i) {
270379251f5eSSepherosa Ziehau struct ix_rx_ring *rxr = &sc->rx_rings[i];
270479251f5eSSepherosa Ziehau uint64_t rdba = rxr->rx_base_paddr;
270579251f5eSSepherosa Ziehau uint32_t srrctl;
270679251f5eSSepherosa Ziehau
270779251f5eSSepherosa Ziehau /* Setup the Base and Length of the Rx Descriptor Ring */
270879251f5eSSepherosa Ziehau IXGBE_WRITE_REG(hw, IXGBE_RDBAL(i), (uint32_t)rdba);
270979251f5eSSepherosa Ziehau IXGBE_WRITE_REG(hw, IXGBE_RDBAH(i), (uint32_t)(rdba >> 32));
271079251f5eSSepherosa Ziehau IXGBE_WRITE_REG(hw, IXGBE_RDLEN(i),
271179251f5eSSepherosa Ziehau rxr->rx_ndesc * sizeof(union ixgbe_adv_rx_desc));
271279251f5eSSepherosa Ziehau
271379251f5eSSepherosa Ziehau /*
271479251f5eSSepherosa Ziehau * Set up the SRRCTL register
271579251f5eSSepherosa Ziehau */
271679251f5eSSepherosa Ziehau srrctl = IXGBE_READ_REG(hw, IXGBE_SRRCTL(i));
271779251f5eSSepherosa Ziehau
271879251f5eSSepherosa Ziehau srrctl &= ~IXGBE_SRRCTL_BSIZEHDR_MASK;
271979251f5eSSepherosa Ziehau srrctl &= ~IXGBE_SRRCTL_BSIZEPKT_MASK;
272079251f5eSSepherosa Ziehau srrctl |= bufsz;
272179251f5eSSepherosa Ziehau srrctl |= IXGBE_SRRCTL_DESCTYPE_ADV_ONEBUF;
272279251f5eSSepherosa Ziehau if (sc->rx_ring_inuse > 1) {
272379251f5eSSepherosa Ziehau /* See the commend near ix_enable_rx_drop() */
272463d483cdSSepherosa Ziehau if (sc->ifm_media &
2725060fa21cSSepherosa Ziehau (IFM_ETH_RXPAUSE | IFM_ETH_TXPAUSE)) {
272679251f5eSSepherosa Ziehau srrctl &= ~IXGBE_SRRCTL_DROP_EN;
272779251f5eSSepherosa Ziehau if (i == 0 && bootverbose) {
2728060fa21cSSepherosa Ziehau if_printf(ifp, "flow control %s, "
2729060fa21cSSepherosa Ziehau "disable RX drop\n",
273063d483cdSSepherosa Ziehau ix_ifmedia2str(sc->ifm_media));
273179251f5eSSepherosa Ziehau }
2732060fa21cSSepherosa Ziehau } else {
273379251f5eSSepherosa Ziehau srrctl |= IXGBE_SRRCTL_DROP_EN;
273479251f5eSSepherosa Ziehau if (i == 0 && bootverbose) {
2735060fa21cSSepherosa Ziehau if_printf(ifp, "flow control %s, "
2736060fa21cSSepherosa Ziehau "enable RX drop\n",
273763d483cdSSepherosa Ziehau ix_ifmedia2str(sc->ifm_media));
273879251f5eSSepherosa Ziehau }
273979251f5eSSepherosa Ziehau }
274079251f5eSSepherosa Ziehau }
274179251f5eSSepherosa Ziehau IXGBE_WRITE_REG(hw, IXGBE_SRRCTL(i), srrctl);
274279251f5eSSepherosa Ziehau
274379251f5eSSepherosa Ziehau /* Setup the HW Rx Head and Tail Descriptor Pointers */
274479251f5eSSepherosa Ziehau IXGBE_WRITE_REG(hw, IXGBE_RDH(i), 0);
274579251f5eSSepherosa Ziehau IXGBE_WRITE_REG(hw, IXGBE_RDT(i), 0);
274679251f5eSSepherosa Ziehau }
274779251f5eSSepherosa Ziehau
274879251f5eSSepherosa Ziehau if (sc->hw.mac.type != ixgbe_mac_82598EB)
274979251f5eSSepherosa Ziehau IXGBE_WRITE_REG(hw, IXGBE_PSRTYPE(0), 0);
275079251f5eSSepherosa Ziehau
275179251f5eSSepherosa Ziehau rxcsum = IXGBE_READ_REG(hw, IXGBE_RXCSUM);
275279251f5eSSepherosa Ziehau
275379251f5eSSepherosa Ziehau /*
275479251f5eSSepherosa Ziehau * Setup RSS
275579251f5eSSepherosa Ziehau */
27563c37d13bSSepherosa Ziehau if (sc->rx_ring_inuse > 1) {
275779251f5eSSepherosa Ziehau uint8_t key[IX_NRSSRK * IX_RSSRK_SIZE];
27583c37d13bSSepherosa Ziehau const struct if_ringmap *rm;
27593c37d13bSSepherosa Ziehau int j, r, nreta, table_nent;
276079251f5eSSepherosa Ziehau
276179251f5eSSepherosa Ziehau /*
276279251f5eSSepherosa Ziehau * NOTE:
276379251f5eSSepherosa Ziehau * When we reach here, RSS has already been disabled
276479251f5eSSepherosa Ziehau * in ix_stop(), so we could safely configure RSS key
276579251f5eSSepherosa Ziehau * and redirect table.
276679251f5eSSepherosa Ziehau */
276779251f5eSSepherosa Ziehau
276879251f5eSSepherosa Ziehau /*
276979251f5eSSepherosa Ziehau * Configure RSS key
277079251f5eSSepherosa Ziehau */
277179251f5eSSepherosa Ziehau toeplitz_get_key(key, sizeof(key));
277279251f5eSSepherosa Ziehau for (i = 0; i < IX_NRSSRK; ++i) {
277379251f5eSSepherosa Ziehau uint32_t rssrk;
277479251f5eSSepherosa Ziehau
277579251f5eSSepherosa Ziehau rssrk = IX_RSSRK_VAL(key, i);
277679251f5eSSepherosa Ziehau IX_RSS_DPRINTF(sc, 1, "rssrk%d 0x%08x\n",
277779251f5eSSepherosa Ziehau i, rssrk);
277879251f5eSSepherosa Ziehau
277979251f5eSSepherosa Ziehau IXGBE_WRITE_REG(hw, IXGBE_RSSRK(i), rssrk);
278079251f5eSSepherosa Ziehau }
278179251f5eSSepherosa Ziehau
27823c37d13bSSepherosa Ziehau /*
27833c37d13bSSepherosa Ziehau * Configure RSS redirect table.
27843c37d13bSSepherosa Ziehau */
27853c37d13bSSepherosa Ziehau
278663d483cdSSepherosa Ziehau /* Table size will differ based on MAC */
278763d483cdSSepherosa Ziehau switch (hw->mac.type) {
278863d483cdSSepherosa Ziehau case ixgbe_mac_X550:
278963d483cdSSepherosa Ziehau case ixgbe_mac_X550EM_x:
279063d483cdSSepherosa Ziehau case ixgbe_mac_X550EM_a:
279163d483cdSSepherosa Ziehau nreta = IX_NRETA_X550;
279263d483cdSSepherosa Ziehau break;
279363d483cdSSepherosa Ziehau default:
279463d483cdSSepherosa Ziehau nreta = IX_NRETA;
279563d483cdSSepherosa Ziehau break;
279663d483cdSSepherosa Ziehau }
279763d483cdSSepherosa Ziehau
27983c37d13bSSepherosa Ziehau table_nent = nreta * IX_RETA_SIZE;
27993c37d13bSSepherosa Ziehau KASSERT(table_nent <= IX_RDRTABLE_SIZE,
28003c37d13bSSepherosa Ziehau ("invalid RETA count %d", nreta));
28013c37d13bSSepherosa Ziehau if (polling)
28023c37d13bSSepherosa Ziehau rm = sc->rx_rmap;
28033c37d13bSSepherosa Ziehau else
28043c37d13bSSepherosa Ziehau rm = sc->rx_rmap_intr;
28053c37d13bSSepherosa Ziehau if_ringmap_rdrtable(rm, sc->rdr_table, table_nent);
28063c37d13bSSepherosa Ziehau
280779251f5eSSepherosa Ziehau r = 0;
280863d483cdSSepherosa Ziehau for (j = 0; j < nreta; ++j) {
280979251f5eSSepherosa Ziehau uint32_t reta = 0;
281079251f5eSSepherosa Ziehau
281179251f5eSSepherosa Ziehau for (i = 0; i < IX_RETA_SIZE; ++i) {
281279251f5eSSepherosa Ziehau uint32_t q;
281379251f5eSSepherosa Ziehau
28143c37d13bSSepherosa Ziehau q = sc->rdr_table[r];
28153c37d13bSSepherosa Ziehau KASSERT(q < sc->rx_ring_inuse,
28163c37d13bSSepherosa Ziehau ("invalid RX ring index %d", q));
281779251f5eSSepherosa Ziehau reta |= q << (8 * i);
281879251f5eSSepherosa Ziehau ++r;
281979251f5eSSepherosa Ziehau }
282079251f5eSSepherosa Ziehau IX_RSS_DPRINTF(sc, 1, "reta 0x%08x\n", reta);
282163d483cdSSepherosa Ziehau if (j < IX_NRETA) {
282279251f5eSSepherosa Ziehau IXGBE_WRITE_REG(hw, IXGBE_RETA(j), reta);
282363d483cdSSepherosa Ziehau } else {
282463d483cdSSepherosa Ziehau IXGBE_WRITE_REG(hw, IXGBE_ERETA(j - IX_NRETA),
282563d483cdSSepherosa Ziehau reta);
282663d483cdSSepherosa Ziehau }
282779251f5eSSepherosa Ziehau }
282879251f5eSSepherosa Ziehau
282979251f5eSSepherosa Ziehau /*
283079251f5eSSepherosa Ziehau * Enable multiple receive queues.
283179251f5eSSepherosa Ziehau * Enable IPv4 RSS standard hash functions.
283279251f5eSSepherosa Ziehau */
283379251f5eSSepherosa Ziehau IXGBE_WRITE_REG(hw, IXGBE_MRQC,
283479251f5eSSepherosa Ziehau IXGBE_MRQC_RSSEN |
283579251f5eSSepherosa Ziehau IXGBE_MRQC_RSS_FIELD_IPV4 |
283679251f5eSSepherosa Ziehau IXGBE_MRQC_RSS_FIELD_IPV4_TCP);
283779251f5eSSepherosa Ziehau
283879251f5eSSepherosa Ziehau /*
283979251f5eSSepherosa Ziehau * NOTE:
284079251f5eSSepherosa Ziehau * PCSD must be enabled to enable multiple
284179251f5eSSepherosa Ziehau * receive queues.
284279251f5eSSepherosa Ziehau */
284379251f5eSSepherosa Ziehau rxcsum |= IXGBE_RXCSUM_PCSD;
284479251f5eSSepherosa Ziehau }
284579251f5eSSepherosa Ziehau
284679251f5eSSepherosa Ziehau if (ifp->if_capenable & IFCAP_RXCSUM)
284779251f5eSSepherosa Ziehau rxcsum |= IXGBE_RXCSUM_PCSD;
284879251f5eSSepherosa Ziehau
284979251f5eSSepherosa Ziehau IXGBE_WRITE_REG(hw, IXGBE_RXCSUM, rxcsum);
285079251f5eSSepherosa Ziehau }
285179251f5eSSepherosa Ziehau
285279251f5eSSepherosa Ziehau static __inline void
ix_rx_refresh(struct ix_rx_ring * rxr,int i)285379251f5eSSepherosa Ziehau ix_rx_refresh(struct ix_rx_ring *rxr, int i)
285479251f5eSSepherosa Ziehau {
285579251f5eSSepherosa Ziehau if (--i < 0)
285679251f5eSSepherosa Ziehau i = rxr->rx_ndesc - 1;
285779251f5eSSepherosa Ziehau IXGBE_WRITE_REG(&rxr->rx_sc->hw, IXGBE_RDT(rxr->rx_idx), i);
285879251f5eSSepherosa Ziehau }
285979251f5eSSepherosa Ziehau
286079251f5eSSepherosa Ziehau static __inline void
ix_rxcsum(uint32_t staterr,struct mbuf * mp,uint32_t ptype)286179251f5eSSepherosa Ziehau ix_rxcsum(uint32_t staterr, struct mbuf *mp, uint32_t ptype)
286279251f5eSSepherosa Ziehau {
286379251f5eSSepherosa Ziehau if ((ptype &
286479251f5eSSepherosa Ziehau (IXGBE_RXDADV_PKTTYPE_IPV4 | IXGBE_RXDADV_PKTTYPE_IPV4_EX)) == 0) {
286579251f5eSSepherosa Ziehau /* Not IPv4 */
286679251f5eSSepherosa Ziehau return;
286779251f5eSSepherosa Ziehau }
286879251f5eSSepherosa Ziehau
286979251f5eSSepherosa Ziehau if ((staterr & (IXGBE_RXD_STAT_IPCS | IXGBE_RXDADV_ERR_IPE)) ==
287079251f5eSSepherosa Ziehau IXGBE_RXD_STAT_IPCS)
287179251f5eSSepherosa Ziehau mp->m_pkthdr.csum_flags |= CSUM_IP_CHECKED | CSUM_IP_VALID;
287279251f5eSSepherosa Ziehau
287379251f5eSSepherosa Ziehau if ((ptype &
287479251f5eSSepherosa Ziehau (IXGBE_RXDADV_PKTTYPE_TCP | IXGBE_RXDADV_PKTTYPE_UDP)) == 0) {
287579251f5eSSepherosa Ziehau /*
287679251f5eSSepherosa Ziehau * - Neither TCP nor UDP
287779251f5eSSepherosa Ziehau * - IPv4 fragment
287879251f5eSSepherosa Ziehau */
287979251f5eSSepherosa Ziehau return;
288079251f5eSSepherosa Ziehau }
288179251f5eSSepherosa Ziehau
288279251f5eSSepherosa Ziehau if ((staterr & (IXGBE_RXD_STAT_L4CS | IXGBE_RXDADV_ERR_TCPE)) ==
288379251f5eSSepherosa Ziehau IXGBE_RXD_STAT_L4CS) {
288479251f5eSSepherosa Ziehau mp->m_pkthdr.csum_flags |= CSUM_DATA_VALID | CSUM_PSEUDO_HDR |
288579251f5eSSepherosa Ziehau CSUM_FRAG_NOT_CHECKED;
288679251f5eSSepherosa Ziehau mp->m_pkthdr.csum_data = htons(0xffff);
288779251f5eSSepherosa Ziehau }
288879251f5eSSepherosa Ziehau }
288979251f5eSSepherosa Ziehau
289079251f5eSSepherosa Ziehau static __inline struct pktinfo *
ix_rssinfo(struct mbuf * m,struct pktinfo * pi,uint32_t hash,uint32_t hashtype,uint32_t ptype)289179251f5eSSepherosa Ziehau ix_rssinfo(struct mbuf *m, struct pktinfo *pi,
289279251f5eSSepherosa Ziehau uint32_t hash, uint32_t hashtype, uint32_t ptype)
289379251f5eSSepherosa Ziehau {
289479251f5eSSepherosa Ziehau switch (hashtype) {
289579251f5eSSepherosa Ziehau case IXGBE_RXDADV_RSSTYPE_IPV4_TCP:
289679251f5eSSepherosa Ziehau pi->pi_netisr = NETISR_IP;
289779251f5eSSepherosa Ziehau pi->pi_flags = 0;
289879251f5eSSepherosa Ziehau pi->pi_l3proto = IPPROTO_TCP;
289979251f5eSSepherosa Ziehau break;
290079251f5eSSepherosa Ziehau
290179251f5eSSepherosa Ziehau case IXGBE_RXDADV_RSSTYPE_IPV4:
290279251f5eSSepherosa Ziehau if ((ptype & IXGBE_RXDADV_PKTTYPE_UDP) == 0) {
290379251f5eSSepherosa Ziehau /* Not UDP or is fragment */
290479251f5eSSepherosa Ziehau return NULL;
290579251f5eSSepherosa Ziehau }
290679251f5eSSepherosa Ziehau pi->pi_netisr = NETISR_IP;
290779251f5eSSepherosa Ziehau pi->pi_flags = 0;
290879251f5eSSepherosa Ziehau pi->pi_l3proto = IPPROTO_UDP;
290979251f5eSSepherosa Ziehau break;
291079251f5eSSepherosa Ziehau
291179251f5eSSepherosa Ziehau default:
291279251f5eSSepherosa Ziehau return NULL;
291379251f5eSSepherosa Ziehau }
291479251f5eSSepherosa Ziehau
29157558541bSSepherosa Ziehau m_sethash(m, toeplitz_hash(hash));
291679251f5eSSepherosa Ziehau return pi;
291779251f5eSSepherosa Ziehau }
291879251f5eSSepherosa Ziehau
291979251f5eSSepherosa Ziehau static __inline void
ix_setup_rxdesc(union ixgbe_adv_rx_desc * rxd,const struct ix_rx_buf * rxbuf)292079251f5eSSepherosa Ziehau ix_setup_rxdesc(union ixgbe_adv_rx_desc *rxd, const struct ix_rx_buf *rxbuf)
292179251f5eSSepherosa Ziehau {
292279251f5eSSepherosa Ziehau rxd->read.pkt_addr = htole64(rxbuf->paddr);
292379251f5eSSepherosa Ziehau rxd->wb.upper.status_error = 0;
292479251f5eSSepherosa Ziehau }
292579251f5eSSepherosa Ziehau
292679251f5eSSepherosa Ziehau static void
ix_rx_discard(struct ix_rx_ring * rxr,int i,boolean_t eop)292779251f5eSSepherosa Ziehau ix_rx_discard(struct ix_rx_ring *rxr, int i, boolean_t eop)
292879251f5eSSepherosa Ziehau {
292979251f5eSSepherosa Ziehau struct ix_rx_buf *rxbuf = &rxr->rx_buf[i];
293079251f5eSSepherosa Ziehau
293179251f5eSSepherosa Ziehau /*
293279251f5eSSepherosa Ziehau * XXX discard may not be correct
293379251f5eSSepherosa Ziehau */
293479251f5eSSepherosa Ziehau if (eop) {
293579251f5eSSepherosa Ziehau IFNET_STAT_INC(&rxr->rx_sc->arpcom.ac_if, ierrors, 1);
293679251f5eSSepherosa Ziehau rxr->rx_flags &= ~IX_RXRING_FLAG_DISC;
293779251f5eSSepherosa Ziehau } else {
293879251f5eSSepherosa Ziehau rxr->rx_flags |= IX_RXRING_FLAG_DISC;
293979251f5eSSepherosa Ziehau }
294079251f5eSSepherosa Ziehau if (rxbuf->fmp != NULL) {
294179251f5eSSepherosa Ziehau m_freem(rxbuf->fmp);
294279251f5eSSepherosa Ziehau rxbuf->fmp = NULL;
294379251f5eSSepherosa Ziehau rxbuf->lmp = NULL;
294479251f5eSSepherosa Ziehau }
294579251f5eSSepherosa Ziehau ix_setup_rxdesc(&rxr->rx_base[i], rxbuf);
294679251f5eSSepherosa Ziehau }
294779251f5eSSepherosa Ziehau
294879251f5eSSepherosa Ziehau static void
ix_rxeof(struct ix_rx_ring * rxr,int count)29494a648aefSSepherosa Ziehau ix_rxeof(struct ix_rx_ring *rxr, int count)
295079251f5eSSepherosa Ziehau {
295179251f5eSSepherosa Ziehau struct ifnet *ifp = &rxr->rx_sc->arpcom.ac_if;
2952ff37a356SSepherosa Ziehau int i, nsegs = 0, cpuid = mycpuid;
295379251f5eSSepherosa Ziehau
295479251f5eSSepherosa Ziehau i = rxr->rx_next_check;
29554a648aefSSepherosa Ziehau while (count != 0) {
295679251f5eSSepherosa Ziehau struct ix_rx_buf *rxbuf, *nbuf = NULL;
295779251f5eSSepherosa Ziehau union ixgbe_adv_rx_desc *cur;
295879251f5eSSepherosa Ziehau struct mbuf *sendmp = NULL, *mp;
295979251f5eSSepherosa Ziehau struct pktinfo *pi = NULL, pi0;
296079251f5eSSepherosa Ziehau uint32_t rsc = 0, ptype, staterr, hash, hashtype;
296179251f5eSSepherosa Ziehau uint16_t len;
296279251f5eSSepherosa Ziehau boolean_t eop;
296379251f5eSSepherosa Ziehau
296479251f5eSSepherosa Ziehau cur = &rxr->rx_base[i];
296579251f5eSSepherosa Ziehau staterr = le32toh(cur->wb.upper.status_error);
296679251f5eSSepherosa Ziehau
296779251f5eSSepherosa Ziehau if ((staterr & IXGBE_RXD_STAT_DD) == 0)
296879251f5eSSepherosa Ziehau break;
296979251f5eSSepherosa Ziehau ++nsegs;
297079251f5eSSepherosa Ziehau
297179251f5eSSepherosa Ziehau rxbuf = &rxr->rx_buf[i];
297279251f5eSSepherosa Ziehau mp = rxbuf->m_head;
297379251f5eSSepherosa Ziehau
297479251f5eSSepherosa Ziehau len = le16toh(cur->wb.upper.length);
297579251f5eSSepherosa Ziehau ptype = le32toh(cur->wb.lower.lo_dword.data) &
297679251f5eSSepherosa Ziehau IXGBE_RXDADV_PKTTYPE_MASK;
297779251f5eSSepherosa Ziehau hash = le32toh(cur->wb.lower.hi_dword.rss);
297879251f5eSSepherosa Ziehau hashtype = le32toh(cur->wb.lower.lo_dword.data) &
297979251f5eSSepherosa Ziehau IXGBE_RXDADV_RSSTYPE_MASK;
29804a648aefSSepherosa Ziehau
298179251f5eSSepherosa Ziehau eop = ((staterr & IXGBE_RXD_STAT_EOP) != 0);
29824a648aefSSepherosa Ziehau if (eop)
29834a648aefSSepherosa Ziehau --count;
298479251f5eSSepherosa Ziehau
298579251f5eSSepherosa Ziehau /*
298679251f5eSSepherosa Ziehau * Make sure bad packets are discarded
298779251f5eSSepherosa Ziehau */
298879251f5eSSepherosa Ziehau if ((staterr & IXGBE_RXDADV_ERR_FRAME_ERR_MASK) ||
298979251f5eSSepherosa Ziehau (rxr->rx_flags & IX_RXRING_FLAG_DISC)) {
299079251f5eSSepherosa Ziehau ix_rx_discard(rxr, i, eop);
299179251f5eSSepherosa Ziehau goto next_desc;
299279251f5eSSepherosa Ziehau }
299379251f5eSSepherosa Ziehau
299479251f5eSSepherosa Ziehau bus_dmamap_sync(rxr->rx_tag, rxbuf->map, BUS_DMASYNC_POSTREAD);
299579251f5eSSepherosa Ziehau if (ix_newbuf(rxr, i, FALSE) != 0) {
299679251f5eSSepherosa Ziehau ix_rx_discard(rxr, i, eop);
299779251f5eSSepherosa Ziehau goto next_desc;
299879251f5eSSepherosa Ziehau }
299979251f5eSSepherosa Ziehau
300079251f5eSSepherosa Ziehau /*
300179251f5eSSepherosa Ziehau * On 82599 which supports a hardware LRO, packets
300279251f5eSSepherosa Ziehau * need not be fragmented across sequential descriptors,
300379251f5eSSepherosa Ziehau * rather the next descriptor is indicated in bits
300479251f5eSSepherosa Ziehau * of the descriptor. This also means that we might
300579251f5eSSepherosa Ziehau * proceses more than one packet at a time, something
300679251f5eSSepherosa Ziehau * that has never been true before, it required
300779251f5eSSepherosa Ziehau * eliminating global chain pointers in favor of what
300879251f5eSSepherosa Ziehau * we are doing here.
300979251f5eSSepherosa Ziehau */
301079251f5eSSepherosa Ziehau if (!eop) {
301179251f5eSSepherosa Ziehau int nextp;
301279251f5eSSepherosa Ziehau
301379251f5eSSepherosa Ziehau /*
301479251f5eSSepherosa Ziehau * Figure out the next descriptor
301579251f5eSSepherosa Ziehau * of this frame.
301679251f5eSSepherosa Ziehau */
301779251f5eSSepherosa Ziehau if (rxr->rx_flags & IX_RXRING_FLAG_LRO)
301879251f5eSSepherosa Ziehau rsc = ix_rsc_count(cur);
301979251f5eSSepherosa Ziehau if (rsc) { /* Get hardware index */
302079251f5eSSepherosa Ziehau nextp = ((staterr &
302179251f5eSSepherosa Ziehau IXGBE_RXDADV_NEXTP_MASK) >>
302279251f5eSSepherosa Ziehau IXGBE_RXDADV_NEXTP_SHIFT);
302379251f5eSSepherosa Ziehau } else { /* Just sequential */
302479251f5eSSepherosa Ziehau nextp = i + 1;
302579251f5eSSepherosa Ziehau if (nextp == rxr->rx_ndesc)
302679251f5eSSepherosa Ziehau nextp = 0;
302779251f5eSSepherosa Ziehau }
302879251f5eSSepherosa Ziehau nbuf = &rxr->rx_buf[nextp];
302979251f5eSSepherosa Ziehau prefetch(nbuf);
303079251f5eSSepherosa Ziehau }
303179251f5eSSepherosa Ziehau mp->m_len = len;
303279251f5eSSepherosa Ziehau
303379251f5eSSepherosa Ziehau /*
303479251f5eSSepherosa Ziehau * Rather than using the fmp/lmp global pointers
303579251f5eSSepherosa Ziehau * we now keep the head of a packet chain in the
303679251f5eSSepherosa Ziehau * buffer struct and pass this along from one
303779251f5eSSepherosa Ziehau * descriptor to the next, until we get EOP.
303879251f5eSSepherosa Ziehau */
303979251f5eSSepherosa Ziehau if (rxbuf->fmp == NULL) {
304079251f5eSSepherosa Ziehau mp->m_pkthdr.len = len;
304179251f5eSSepherosa Ziehau rxbuf->fmp = mp;
304279251f5eSSepherosa Ziehau rxbuf->lmp = mp;
304379251f5eSSepherosa Ziehau } else {
304479251f5eSSepherosa Ziehau rxbuf->fmp->m_pkthdr.len += len;
304579251f5eSSepherosa Ziehau rxbuf->lmp->m_next = mp;
304679251f5eSSepherosa Ziehau rxbuf->lmp = mp;
304779251f5eSSepherosa Ziehau }
304879251f5eSSepherosa Ziehau
304979251f5eSSepherosa Ziehau if (nbuf != NULL) {
305079251f5eSSepherosa Ziehau /*
305179251f5eSSepherosa Ziehau * Not the last fragment of this frame,
305279251f5eSSepherosa Ziehau * pass this fragment list on
305379251f5eSSepherosa Ziehau */
305479251f5eSSepherosa Ziehau nbuf->fmp = rxbuf->fmp;
305579251f5eSSepherosa Ziehau nbuf->lmp = rxbuf->lmp;
305679251f5eSSepherosa Ziehau } else {
305779251f5eSSepherosa Ziehau /*
305879251f5eSSepherosa Ziehau * Send this frame
305979251f5eSSepherosa Ziehau */
306079251f5eSSepherosa Ziehau sendmp = rxbuf->fmp;
306179251f5eSSepherosa Ziehau
306279251f5eSSepherosa Ziehau sendmp->m_pkthdr.rcvif = ifp;
306379251f5eSSepherosa Ziehau IFNET_STAT_INC(ifp, ipackets, 1);
306479251f5eSSepherosa Ziehau #ifdef IX_RSS_DEBUG
306579251f5eSSepherosa Ziehau rxr->rx_pkts++;
306679251f5eSSepherosa Ziehau #endif
306779251f5eSSepherosa Ziehau
306879251f5eSSepherosa Ziehau /* Process vlan info */
306979251f5eSSepherosa Ziehau if (staterr & IXGBE_RXD_STAT_VP) {
307079251f5eSSepherosa Ziehau sendmp->m_pkthdr.ether_vlantag =
307179251f5eSSepherosa Ziehau le16toh(cur->wb.upper.vlan);
307279251f5eSSepherosa Ziehau sendmp->m_flags |= M_VLANTAG;
307379251f5eSSepherosa Ziehau }
307479251f5eSSepherosa Ziehau if (ifp->if_capenable & IFCAP_RXCSUM)
307579251f5eSSepherosa Ziehau ix_rxcsum(staterr, sendmp, ptype);
307679251f5eSSepherosa Ziehau if (ifp->if_capenable & IFCAP_RSS) {
307779251f5eSSepherosa Ziehau pi = ix_rssinfo(sendmp, &pi0,
307879251f5eSSepherosa Ziehau hash, hashtype, ptype);
307979251f5eSSepherosa Ziehau }
308079251f5eSSepherosa Ziehau }
308179251f5eSSepherosa Ziehau rxbuf->fmp = NULL;
308279251f5eSSepherosa Ziehau rxbuf->lmp = NULL;
308379251f5eSSepherosa Ziehau next_desc:
308479251f5eSSepherosa Ziehau /* Advance our pointers to the next descriptor. */
308579251f5eSSepherosa Ziehau if (++i == rxr->rx_ndesc)
308679251f5eSSepherosa Ziehau i = 0;
308779251f5eSSepherosa Ziehau
308879251f5eSSepherosa Ziehau if (sendmp != NULL)
3089be4134c6SFranco Fichtner ifp->if_input(ifp, sendmp, pi, cpuid);
309079251f5eSSepherosa Ziehau
309179251f5eSSepherosa Ziehau if (nsegs >= rxr->rx_wreg_nsegs) {
309279251f5eSSepherosa Ziehau ix_rx_refresh(rxr, i);
309379251f5eSSepherosa Ziehau nsegs = 0;
309479251f5eSSepherosa Ziehau }
309579251f5eSSepherosa Ziehau }
309679251f5eSSepherosa Ziehau rxr->rx_next_check = i;
309779251f5eSSepherosa Ziehau
309879251f5eSSepherosa Ziehau if (nsegs > 0)
309979251f5eSSepherosa Ziehau ix_rx_refresh(rxr, i);
310079251f5eSSepherosa Ziehau }
310179251f5eSSepherosa Ziehau
310279251f5eSSepherosa Ziehau static void
ix_set_vlan(struct ix_softc * sc)310379251f5eSSepherosa Ziehau ix_set_vlan(struct ix_softc *sc)
310479251f5eSSepherosa Ziehau {
310579251f5eSSepherosa Ziehau struct ixgbe_hw *hw = &sc->hw;
310679251f5eSSepherosa Ziehau uint32_t ctrl;
310779251f5eSSepherosa Ziehau
3108dd5ce676SSepherosa Ziehau if ((sc->arpcom.ac_if.if_capenable & IFCAP_VLAN_HWTAGGING) == 0)
3109dd5ce676SSepherosa Ziehau return;
3110dd5ce676SSepherosa Ziehau
311179251f5eSSepherosa Ziehau if (hw->mac.type == ixgbe_mac_82598EB) {
311279251f5eSSepherosa Ziehau ctrl = IXGBE_READ_REG(hw, IXGBE_VLNCTRL);
311379251f5eSSepherosa Ziehau ctrl |= IXGBE_VLNCTRL_VME;
311479251f5eSSepherosa Ziehau IXGBE_WRITE_REG(hw, IXGBE_VLNCTRL, ctrl);
311579251f5eSSepherosa Ziehau } else {
311679251f5eSSepherosa Ziehau int i;
311779251f5eSSepherosa Ziehau
311879251f5eSSepherosa Ziehau /*
311979251f5eSSepherosa Ziehau * On 82599 and later chips the VLAN enable is
312079251f5eSSepherosa Ziehau * per queue in RXDCTL
312179251f5eSSepherosa Ziehau */
312279251f5eSSepherosa Ziehau for (i = 0; i < sc->rx_ring_inuse; ++i) {
312379251f5eSSepherosa Ziehau ctrl = IXGBE_READ_REG(hw, IXGBE_RXDCTL(i));
312479251f5eSSepherosa Ziehau ctrl |= IXGBE_RXDCTL_VME;
312579251f5eSSepherosa Ziehau IXGBE_WRITE_REG(hw, IXGBE_RXDCTL(i), ctrl);
312679251f5eSSepherosa Ziehau }
312779251f5eSSepherosa Ziehau }
312879251f5eSSepherosa Ziehau }
312979251f5eSSepherosa Ziehau
313079251f5eSSepherosa Ziehau static void
ix_enable_intr(struct ix_softc * sc)313179251f5eSSepherosa Ziehau ix_enable_intr(struct ix_softc *sc)
313279251f5eSSepherosa Ziehau {
313379251f5eSSepherosa Ziehau struct ixgbe_hw *hw = &sc->hw;
3134189a0ff3SSepherosa Ziehau uint32_t fwsm;
313579251f5eSSepherosa Ziehau int i;
313679251f5eSSepherosa Ziehau
313779251f5eSSepherosa Ziehau for (i = 0; i < sc->intr_cnt; ++i)
313879251f5eSSepherosa Ziehau lwkt_serialize_handler_enable(sc->intr_data[i].intr_serialize);
313979251f5eSSepherosa Ziehau
3140189a0ff3SSepherosa Ziehau sc->intr_mask = (IXGBE_EIMS_ENABLE_MASK & ~IXGBE_EIMS_RTX_QUEUE);
314179251f5eSSepherosa Ziehau
314263d483cdSSepherosa Ziehau switch (hw->mac.type) {
314379251f5eSSepherosa Ziehau case ixgbe_mac_82599EB:
3144189a0ff3SSepherosa Ziehau sc->intr_mask |= IXGBE_EIMS_ECC;
314563d483cdSSepherosa Ziehau /* Temperature sensor on some adapters */
3146189a0ff3SSepherosa Ziehau sc->intr_mask |= IXGBE_EIMS_GPI_SDP0;
314763d483cdSSepherosa Ziehau /* SFP+ (RX_LOS_N & MOD_ABS_N) */
3148189a0ff3SSepherosa Ziehau sc->intr_mask |= IXGBE_EIMS_GPI_SDP1;
3149189a0ff3SSepherosa Ziehau sc->intr_mask |= IXGBE_EIMS_GPI_SDP2;
315079251f5eSSepherosa Ziehau break;
3151189a0ff3SSepherosa Ziehau
315279251f5eSSepherosa Ziehau case ixgbe_mac_X540:
3153189a0ff3SSepherosa Ziehau sc->intr_mask |= IXGBE_EIMS_ECC;
315479251f5eSSepherosa Ziehau /* Detect if Thermal Sensor is enabled */
315579251f5eSSepherosa Ziehau fwsm = IXGBE_READ_REG(hw, IXGBE_FWSM);
315679251f5eSSepherosa Ziehau if (fwsm & IXGBE_FWSM_TS_ENABLED)
3157189a0ff3SSepherosa Ziehau sc->intr_mask |= IXGBE_EIMS_TS;
315863d483cdSSepherosa Ziehau break;
315963d483cdSSepherosa Ziehau
316063d483cdSSepherosa Ziehau case ixgbe_mac_X550:
316163d483cdSSepherosa Ziehau sc->intr_mask |= IXGBE_EIMS_ECC;
316263d483cdSSepherosa Ziehau /* MAC thermal sensor is automatically enabled */
316363d483cdSSepherosa Ziehau sc->intr_mask |= IXGBE_EIMS_TS;
31646150453fSSepherosa Ziehau break;
31656150453fSSepherosa Ziehau
31666150453fSSepherosa Ziehau case ixgbe_mac_X550EM_a:
31676150453fSSepherosa Ziehau case ixgbe_mac_X550EM_x:
31686150453fSSepherosa Ziehau sc->intr_mask |= IXGBE_EIMS_ECC;
316963d483cdSSepherosa Ziehau /* Some devices use SDP0 for important information */
317063d483cdSSepherosa Ziehau if (hw->device_id == IXGBE_DEV_ID_X550EM_X_SFP ||
31716150453fSSepherosa Ziehau hw->device_id == IXGBE_DEV_ID_X550EM_A_SFP ||
31726150453fSSepherosa Ziehau hw->device_id == IXGBE_DEV_ID_X550EM_A_SFP_N ||
317363d483cdSSepherosa Ziehau hw->device_id == IXGBE_DEV_ID_X550EM_X_10G_T)
317463d483cdSSepherosa Ziehau sc->intr_mask |= IXGBE_EIMS_GPI_SDP0_BY_MAC(hw);
31756150453fSSepherosa Ziehau if (hw->phy.type == ixgbe_phy_x550em_ext_t)
31766150453fSSepherosa Ziehau sc->intr_mask |= IXGBE_EICR_GPI_SDP0_X540;
31776150453fSSepherosa Ziehau break;
31786150453fSSepherosa Ziehau
317979251f5eSSepherosa Ziehau default:
318079251f5eSSepherosa Ziehau break;
318179251f5eSSepherosa Ziehau }
318279251f5eSSepherosa Ziehau
31836150453fSSepherosa Ziehau /* Enable Fan Failure detection */
31846150453fSSepherosa Ziehau if (sc->caps & IX_CAP_DETECT_FANFAIL)
31856150453fSSepherosa Ziehau sc->intr_mask |= IXGBE_EIMS_GPI_SDP1;
31866150453fSSepherosa Ziehau
3187189a0ff3SSepherosa Ziehau /* With MSI-X we use auto clear for RX and TX rings */
318879251f5eSSepherosa Ziehau if (sc->intr_type == PCI_INTR_TYPE_MSIX) {
3189189a0ff3SSepherosa Ziehau /*
3190189a0ff3SSepherosa Ziehau * There are no EIAC1/EIAC2 for newer chips; the related
3191189a0ff3SSepherosa Ziehau * bits for TX and RX rings > 16 are always auto clear.
3192189a0ff3SSepherosa Ziehau *
3193189a0ff3SSepherosa Ziehau * XXX which bits? There are _no_ documented EICR1 and
3194189a0ff3SSepherosa Ziehau * EICR2 at all; only EICR.
3195189a0ff3SSepherosa Ziehau */
3196189a0ff3SSepherosa Ziehau IXGBE_WRITE_REG(hw, IXGBE_EIAC, IXGBE_EIMS_RTX_QUEUE);
319779251f5eSSepherosa Ziehau } else {
3198189a0ff3SSepherosa Ziehau sc->intr_mask |= IX_TX_INTR_MASK | IX_RX0_INTR_MASK;
319979251f5eSSepherosa Ziehau
320079251f5eSSepherosa Ziehau KKASSERT(sc->rx_ring_inuse <= IX_MIN_RXRING_RSS);
320179251f5eSSepherosa Ziehau if (sc->rx_ring_inuse == IX_MIN_RXRING_RSS)
320279251f5eSSepherosa Ziehau sc->intr_mask |= IX_RX1_INTR_MASK;
320379251f5eSSepherosa Ziehau }
320479251f5eSSepherosa Ziehau
320579251f5eSSepherosa Ziehau IXGBE_WRITE_REG(hw, IXGBE_EIMS, sc->intr_mask);
3206189a0ff3SSepherosa Ziehau
3207189a0ff3SSepherosa Ziehau /*
3208189a0ff3SSepherosa Ziehau * Enable RX and TX rings for MSI-X
3209189a0ff3SSepherosa Ziehau */
3210189a0ff3SSepherosa Ziehau if (sc->intr_type == PCI_INTR_TYPE_MSIX) {
3211189a0ff3SSepherosa Ziehau for (i = 0; i < sc->tx_ring_inuse; ++i) {
3212189a0ff3SSepherosa Ziehau const struct ix_tx_ring *txr = &sc->tx_rings[i];
3213189a0ff3SSepherosa Ziehau
3214189a0ff3SSepherosa Ziehau if (txr->tx_intr_vec >= 0) {
3215189a0ff3SSepherosa Ziehau IXGBE_WRITE_REG(hw, txr->tx_eims,
3216189a0ff3SSepherosa Ziehau txr->tx_eims_val);
3217189a0ff3SSepherosa Ziehau }
3218189a0ff3SSepherosa Ziehau }
3219189a0ff3SSepherosa Ziehau for (i = 0; i < sc->rx_ring_inuse; ++i) {
3220189a0ff3SSepherosa Ziehau const struct ix_rx_ring *rxr = &sc->rx_rings[i];
3221189a0ff3SSepherosa Ziehau
3222189a0ff3SSepherosa Ziehau KKASSERT(rxr->rx_intr_vec >= 0);
3223189a0ff3SSepherosa Ziehau IXGBE_WRITE_REG(hw, rxr->rx_eims, rxr->rx_eims_val);
3224189a0ff3SSepherosa Ziehau }
3225189a0ff3SSepherosa Ziehau }
322679251f5eSSepherosa Ziehau
322779251f5eSSepherosa Ziehau IXGBE_WRITE_FLUSH(hw);
322879251f5eSSepherosa Ziehau }
322979251f5eSSepherosa Ziehau
323079251f5eSSepherosa Ziehau static void
ix_disable_intr(struct ix_softc * sc)323179251f5eSSepherosa Ziehau ix_disable_intr(struct ix_softc *sc)
323279251f5eSSepherosa Ziehau {
323379251f5eSSepherosa Ziehau int i;
323479251f5eSSepherosa Ziehau
3235189a0ff3SSepherosa Ziehau if (sc->intr_type == PCI_INTR_TYPE_MSIX)
323679251f5eSSepherosa Ziehau IXGBE_WRITE_REG(&sc->hw, IXGBE_EIAC, 0);
3237189a0ff3SSepherosa Ziehau
323879251f5eSSepherosa Ziehau if (sc->hw.mac.type == ixgbe_mac_82598EB) {
323979251f5eSSepherosa Ziehau IXGBE_WRITE_REG(&sc->hw, IXGBE_EIMC, ~0);
324079251f5eSSepherosa Ziehau } else {
324179251f5eSSepherosa Ziehau IXGBE_WRITE_REG(&sc->hw, IXGBE_EIMC, 0xFFFF0000);
324279251f5eSSepherosa Ziehau IXGBE_WRITE_REG(&sc->hw, IXGBE_EIMC_EX(0), ~0);
324379251f5eSSepherosa Ziehau IXGBE_WRITE_REG(&sc->hw, IXGBE_EIMC_EX(1), ~0);
324479251f5eSSepherosa Ziehau }
324579251f5eSSepherosa Ziehau IXGBE_WRITE_FLUSH(&sc->hw);
324679251f5eSSepherosa Ziehau
324779251f5eSSepherosa Ziehau for (i = 0; i < sc->intr_cnt; ++i)
324879251f5eSSepherosa Ziehau lwkt_serialize_handler_disable(sc->intr_data[i].intr_serialize);
324979251f5eSSepherosa Ziehau }
325079251f5eSSepherosa Ziehau
325179251f5eSSepherosa Ziehau static void
ix_slot_info(struct ix_softc * sc)325279251f5eSSepherosa Ziehau ix_slot_info(struct ix_softc *sc)
325379251f5eSSepherosa Ziehau {
325479251f5eSSepherosa Ziehau device_t dev = sc->dev;
32556150453fSSepherosa Ziehau struct ixgbe_hw *hw = &sc->hw;
325679251f5eSSepherosa Ziehau uint32_t offset;
32576150453fSSepherosa Ziehau uint16_t link;
32586150453fSSepherosa Ziehau boolean_t bus_info_valid = TRUE;
325979251f5eSSepherosa Ziehau
32606150453fSSepherosa Ziehau /* Some devices are behind an internal bridge */
32616150453fSSepherosa Ziehau switch (hw->device_id) {
32626150453fSSepherosa Ziehau case IXGBE_DEV_ID_82599_SFP_SF_QP:
32636150453fSSepherosa Ziehau case IXGBE_DEV_ID_82599_QSFP_SF_QP:
32646150453fSSepherosa Ziehau goto get_parent_info;
32656150453fSSepherosa Ziehau default:
32666150453fSSepherosa Ziehau break;
32676150453fSSepherosa Ziehau }
32686150453fSSepherosa Ziehau
326979251f5eSSepherosa Ziehau ixgbe_get_bus_info(hw);
32706150453fSSepherosa Ziehau
32716150453fSSepherosa Ziehau /*
32726150453fSSepherosa Ziehau * Some devices don't use PCI-E, but there is no need
32736150453fSSepherosa Ziehau * to display "Unknown" for bus speed and width.
32746150453fSSepherosa Ziehau */
32756150453fSSepherosa Ziehau switch (hw->mac.type) {
32766150453fSSepherosa Ziehau case ixgbe_mac_X550EM_x:
32776150453fSSepherosa Ziehau case ixgbe_mac_X550EM_a:
327863d483cdSSepherosa Ziehau return;
32796150453fSSepherosa Ziehau default:
328079251f5eSSepherosa Ziehau goto display;
328179251f5eSSepherosa Ziehau }
328279251f5eSSepherosa Ziehau
32836150453fSSepherosa Ziehau get_parent_info:
328479251f5eSSepherosa Ziehau /*
32856150453fSSepherosa Ziehau * For the Quad port adapter we need to parse back up
32866150453fSSepherosa Ziehau * the PCI tree to find the speed of the expansion slot
32876150453fSSepherosa Ziehau * into which this adapter is plugged. A bit more work.
328879251f5eSSepherosa Ziehau */
328979251f5eSSepherosa Ziehau dev = device_get_parent(device_get_parent(dev));
329079251f5eSSepherosa Ziehau #ifdef IXGBE_DEBUG
32916150453fSSepherosa Ziehau device_printf(dev, "parent pcib = %x,%x,%x\n", pci_get_bus(dev),
32926150453fSSepherosa Ziehau pci_get_slot(dev), pci_get_function(dev));
329379251f5eSSepherosa Ziehau #endif
329479251f5eSSepherosa Ziehau dev = device_get_parent(device_get_parent(dev));
329579251f5eSSepherosa Ziehau #ifdef IXGBE_DEBUG
32966150453fSSepherosa Ziehau device_printf(dev, "slot pcib = %x,%x,%x\n", pci_get_bus(dev),
32976150453fSSepherosa Ziehau pci_get_slot(dev), pci_get_function(dev));
329879251f5eSSepherosa Ziehau #endif
329979251f5eSSepherosa Ziehau /* Now get the PCI Express Capabilities offset */
330079251f5eSSepherosa Ziehau offset = pci_get_pciecap_ptr(dev);
33016150453fSSepherosa Ziehau if (offset == 0) {
33026150453fSSepherosa Ziehau /*
33036150453fSSepherosa Ziehau * Hmm...can't get PCI-Express capabilities.
33046150453fSSepherosa Ziehau * Falling back to default method.
33056150453fSSepherosa Ziehau */
33066150453fSSepherosa Ziehau bus_info_valid = FALSE;
33076150453fSSepherosa Ziehau ixgbe_get_bus_info(hw);
33086150453fSSepherosa Ziehau goto display;
33096150453fSSepherosa Ziehau }
331079251f5eSSepherosa Ziehau /* ...and read the Link Status Register */
331179251f5eSSepherosa Ziehau link = pci_read_config(dev, offset + PCIER_LINKSTAT, 2);
33126150453fSSepherosa Ziehau ixgbe_set_pci_config_data_generic(hw, link);
331379251f5eSSepherosa Ziehau
331479251f5eSSepherosa Ziehau display:
331579251f5eSSepherosa Ziehau device_printf(dev, "PCI Express Bus: Speed %s %s\n",
331679251f5eSSepherosa Ziehau hw->bus.speed == ixgbe_bus_speed_8000 ? "8.0GT/s" :
331779251f5eSSepherosa Ziehau hw->bus.speed == ixgbe_bus_speed_5000 ? "5.0GT/s" :
331879251f5eSSepherosa Ziehau hw->bus.speed == ixgbe_bus_speed_2500 ? "2.5GT/s" : "Unknown",
331979251f5eSSepherosa Ziehau hw->bus.width == ixgbe_bus_width_pcie_x8 ? "Width x8" :
332079251f5eSSepherosa Ziehau hw->bus.width == ixgbe_bus_width_pcie_x4 ? "Width x4" :
332179251f5eSSepherosa Ziehau hw->bus.width == ixgbe_bus_width_pcie_x1 ? "Width x1" : "Unknown");
332279251f5eSSepherosa Ziehau
33236150453fSSepherosa Ziehau if (bus_info_valid) {
332479251f5eSSepherosa Ziehau if (hw->device_id != IXGBE_DEV_ID_82599_SFP_SF_QP &&
332579251f5eSSepherosa Ziehau hw->bus.width <= ixgbe_bus_width_pcie_x4 &&
332679251f5eSSepherosa Ziehau hw->bus.speed == ixgbe_bus_speed_2500) {
33276150453fSSepherosa Ziehau device_printf(dev, "PCI-Express bandwidth available "
33286150453fSSepherosa Ziehau "for this card is not sufficient for optimal "
33296150453fSSepherosa Ziehau "performance.\n");
33306150453fSSepherosa Ziehau device_printf(dev, "For optimal performance a "
33316150453fSSepherosa Ziehau "x8 PCIE, or x4 PCIE Gen2 slot is required.\n");
33326150453fSSepherosa Ziehau }
33336150453fSSepherosa Ziehau if (hw->device_id == IXGBE_DEV_ID_82599_SFP_SF_QP &&
333479251f5eSSepherosa Ziehau hw->bus.width <= ixgbe_bus_width_pcie_x8 &&
333579251f5eSSepherosa Ziehau hw->bus.speed < ixgbe_bus_speed_8000) {
33366150453fSSepherosa Ziehau device_printf(dev, "PCI-Express bandwidth available "
33376150453fSSepherosa Ziehau "for this card is not sufficient for optimal "
33386150453fSSepherosa Ziehau "performance.\n");
33396150453fSSepherosa Ziehau device_printf(dev, "For optimal performance a "
33406150453fSSepherosa Ziehau "x8 PCIE Gen3 slot is required.\n");
33416150453fSSepherosa Ziehau }
33426150453fSSepherosa Ziehau } else {
33436150453fSSepherosa Ziehau device_printf(dev, "Unable to determine slot speed/width. "
33446150453fSSepherosa Ziehau "The speed/width reported are that of the internal "
33456150453fSSepherosa Ziehau "switch.\n");
334679251f5eSSepherosa Ziehau }
334779251f5eSSepherosa Ziehau }
334879251f5eSSepherosa Ziehau
334979251f5eSSepherosa Ziehau /*
335079251f5eSSepherosa Ziehau * TODO comment is incorrect
335179251f5eSSepherosa Ziehau *
335279251f5eSSepherosa Ziehau * Setup the correct IVAR register for a particular MSIX interrupt
335379251f5eSSepherosa Ziehau * - entry is the register array entry
335479251f5eSSepherosa Ziehau * - vector is the MSIX vector for this queue
335579251f5eSSepherosa Ziehau * - type is RX/TX/MISC
335679251f5eSSepherosa Ziehau */
335779251f5eSSepherosa Ziehau static void
ix_set_ivar(struct ix_softc * sc,uint8_t entry,uint8_t vector,int8_t type)335879251f5eSSepherosa Ziehau ix_set_ivar(struct ix_softc *sc, uint8_t entry, uint8_t vector,
335979251f5eSSepherosa Ziehau int8_t type)
336079251f5eSSepherosa Ziehau {
336179251f5eSSepherosa Ziehau struct ixgbe_hw *hw = &sc->hw;
336279251f5eSSepherosa Ziehau uint32_t ivar, index;
336379251f5eSSepherosa Ziehau
336479251f5eSSepherosa Ziehau vector |= IXGBE_IVAR_ALLOC_VAL;
336579251f5eSSepherosa Ziehau
336679251f5eSSepherosa Ziehau switch (hw->mac.type) {
336779251f5eSSepherosa Ziehau case ixgbe_mac_82598EB:
336879251f5eSSepherosa Ziehau if (type == -1)
336979251f5eSSepherosa Ziehau entry = IXGBE_IVAR_OTHER_CAUSES_INDEX;
337079251f5eSSepherosa Ziehau else
337179251f5eSSepherosa Ziehau entry += (type * 64);
337279251f5eSSepherosa Ziehau index = (entry >> 2) & 0x1F;
337379251f5eSSepherosa Ziehau ivar = IXGBE_READ_REG(hw, IXGBE_IVAR(index));
337479251f5eSSepherosa Ziehau ivar &= ~(0xFF << (8 * (entry & 0x3)));
337579251f5eSSepherosa Ziehau ivar |= (vector << (8 * (entry & 0x3)));
337679251f5eSSepherosa Ziehau IXGBE_WRITE_REG(hw, IXGBE_IVAR(index), ivar);
337779251f5eSSepherosa Ziehau break;
337879251f5eSSepherosa Ziehau
337979251f5eSSepherosa Ziehau case ixgbe_mac_82599EB:
338079251f5eSSepherosa Ziehau case ixgbe_mac_X540:
338163d483cdSSepherosa Ziehau case ixgbe_mac_X550:
338263d483cdSSepherosa Ziehau case ixgbe_mac_X550EM_a:
338363d483cdSSepherosa Ziehau case ixgbe_mac_X550EM_x:
338479251f5eSSepherosa Ziehau if (type == -1) { /* MISC IVAR */
338579251f5eSSepherosa Ziehau index = (entry & 1) * 8;
338679251f5eSSepherosa Ziehau ivar = IXGBE_READ_REG(hw, IXGBE_IVAR_MISC);
338779251f5eSSepherosa Ziehau ivar &= ~(0xFF << index);
338879251f5eSSepherosa Ziehau ivar |= (vector << index);
338979251f5eSSepherosa Ziehau IXGBE_WRITE_REG(hw, IXGBE_IVAR_MISC, ivar);
339079251f5eSSepherosa Ziehau } else { /* RX/TX IVARS */
339179251f5eSSepherosa Ziehau index = (16 * (entry & 1)) + (8 * type);
339279251f5eSSepherosa Ziehau ivar = IXGBE_READ_REG(hw, IXGBE_IVAR(entry >> 1));
339379251f5eSSepherosa Ziehau ivar &= ~(0xFF << index);
339479251f5eSSepherosa Ziehau ivar |= (vector << index);
339579251f5eSSepherosa Ziehau IXGBE_WRITE_REG(hw, IXGBE_IVAR(entry >> 1), ivar);
339679251f5eSSepherosa Ziehau }
339763d483cdSSepherosa Ziehau /* FALL THROUGH */
339879251f5eSSepherosa Ziehau default:
339979251f5eSSepherosa Ziehau break;
340079251f5eSSepherosa Ziehau }
340179251f5eSSepherosa Ziehau }
340279251f5eSSepherosa Ziehau
340379251f5eSSepherosa Ziehau static boolean_t
ix_sfp_probe(struct ix_softc * sc)340479251f5eSSepherosa Ziehau ix_sfp_probe(struct ix_softc *sc)
340579251f5eSSepherosa Ziehau {
340679251f5eSSepherosa Ziehau struct ixgbe_hw *hw = &sc->hw;
340779251f5eSSepherosa Ziehau
340879251f5eSSepherosa Ziehau if (hw->phy.type == ixgbe_phy_nl &&
340979251f5eSSepherosa Ziehau hw->phy.sfp_type == ixgbe_sfp_type_not_present) {
341079251f5eSSepherosa Ziehau int32_t ret;
341179251f5eSSepherosa Ziehau
341279251f5eSSepherosa Ziehau ret = hw->phy.ops.identify_sfp(hw);
341379251f5eSSepherosa Ziehau if (ret)
341479251f5eSSepherosa Ziehau return FALSE;
341579251f5eSSepherosa Ziehau
341679251f5eSSepherosa Ziehau ret = hw->phy.ops.reset(hw);
34176150453fSSepherosa Ziehau sc->sfp_probe = FALSE;
341879251f5eSSepherosa Ziehau if (ret == IXGBE_ERR_SFP_NOT_SUPPORTED) {
341979251f5eSSepherosa Ziehau if_printf(&sc->arpcom.ac_if,
342079251f5eSSepherosa Ziehau "Unsupported SFP+ module detected! "
342179251f5eSSepherosa Ziehau "Reload driver with supported module.\n");
342279251f5eSSepherosa Ziehau return FALSE;
342379251f5eSSepherosa Ziehau }
342479251f5eSSepherosa Ziehau if_printf(&sc->arpcom.ac_if, "SFP+ module detected!\n");
342579251f5eSSepherosa Ziehau
342679251f5eSSepherosa Ziehau /* We now have supported optics */
342779251f5eSSepherosa Ziehau return TRUE;
342879251f5eSSepherosa Ziehau }
342979251f5eSSepherosa Ziehau return FALSE;
343079251f5eSSepherosa Ziehau }
343179251f5eSSepherosa Ziehau
343279251f5eSSepherosa Ziehau static void
ix_handle_link(struct ix_softc * sc)343379251f5eSSepherosa Ziehau ix_handle_link(struct ix_softc *sc)
343479251f5eSSepherosa Ziehau {
343579251f5eSSepherosa Ziehau ixgbe_check_link(&sc->hw, &sc->link_speed, &sc->link_up, 0);
343679251f5eSSepherosa Ziehau ix_update_link_status(sc);
343779251f5eSSepherosa Ziehau }
343879251f5eSSepherosa Ziehau
343979251f5eSSepherosa Ziehau /*
344079251f5eSSepherosa Ziehau * Handling SFP module
344179251f5eSSepherosa Ziehau */
344279251f5eSSepherosa Ziehau static void
ix_handle_mod(struct ix_softc * sc)344379251f5eSSepherosa Ziehau ix_handle_mod(struct ix_softc *sc)
344479251f5eSSepherosa Ziehau {
344579251f5eSSepherosa Ziehau struct ixgbe_hw *hw = &sc->hw;
344679251f5eSSepherosa Ziehau uint32_t err;
344779251f5eSSepherosa Ziehau
34486150453fSSepherosa Ziehau if (sc->hw.need_crosstalk_fix) {
34496150453fSSepherosa Ziehau uint32_t cage_full = 0;
34506150453fSSepherosa Ziehau
34516150453fSSepherosa Ziehau switch (hw->mac.type) {
34526150453fSSepherosa Ziehau case ixgbe_mac_82599EB:
34536150453fSSepherosa Ziehau cage_full = IXGBE_READ_REG(hw, IXGBE_ESDP) &
34546150453fSSepherosa Ziehau IXGBE_ESDP_SDP2;
34556150453fSSepherosa Ziehau break;
34566150453fSSepherosa Ziehau
34576150453fSSepherosa Ziehau case ixgbe_mac_X550EM_x:
34586150453fSSepherosa Ziehau case ixgbe_mac_X550EM_a:
34596150453fSSepherosa Ziehau cage_full = IXGBE_READ_REG(hw, IXGBE_ESDP) &
34606150453fSSepherosa Ziehau IXGBE_ESDP_SDP0;
34616150453fSSepherosa Ziehau break;
34626150453fSSepherosa Ziehau
34636150453fSSepherosa Ziehau default:
34646150453fSSepherosa Ziehau break;
34656150453fSSepherosa Ziehau }
34666150453fSSepherosa Ziehau
34676150453fSSepherosa Ziehau if (!cage_full)
34686150453fSSepherosa Ziehau return;
34696150453fSSepherosa Ziehau }
34706150453fSSepherosa Ziehau
347179251f5eSSepherosa Ziehau err = hw->phy.ops.identify_sfp(hw);
347279251f5eSSepherosa Ziehau if (err == IXGBE_ERR_SFP_NOT_SUPPORTED) {
347379251f5eSSepherosa Ziehau if_printf(&sc->arpcom.ac_if,
347479251f5eSSepherosa Ziehau "Unsupported SFP+ module type was detected.\n");
347579251f5eSSepherosa Ziehau return;
347679251f5eSSepherosa Ziehau }
34776150453fSSepherosa Ziehau
34786150453fSSepherosa Ziehau if (hw->mac.type == ixgbe_mac_82598EB)
34796150453fSSepherosa Ziehau err = hw->phy.ops.reset(hw);
34806150453fSSepherosa Ziehau else
348179251f5eSSepherosa Ziehau err = hw->mac.ops.setup_sfp(hw);
348279251f5eSSepherosa Ziehau if (err == IXGBE_ERR_SFP_NOT_SUPPORTED) {
348379251f5eSSepherosa Ziehau if_printf(&sc->arpcom.ac_if,
348479251f5eSSepherosa Ziehau "Setup failure - unsupported SFP+ module type.\n");
348579251f5eSSepherosa Ziehau return;
348679251f5eSSepherosa Ziehau }
348779251f5eSSepherosa Ziehau ix_handle_msf(sc);
348879251f5eSSepherosa Ziehau }
348979251f5eSSepherosa Ziehau
349079251f5eSSepherosa Ziehau /*
349179251f5eSSepherosa Ziehau * Handling MSF (multispeed fiber)
349279251f5eSSepherosa Ziehau */
349379251f5eSSepherosa Ziehau static void
ix_handle_msf(struct ix_softc * sc)349479251f5eSSepherosa Ziehau ix_handle_msf(struct ix_softc *sc)
349579251f5eSSepherosa Ziehau {
349679251f5eSSepherosa Ziehau struct ixgbe_hw *hw = &sc->hw;
349779251f5eSSepherosa Ziehau uint32_t autoneg;
349879251f5eSSepherosa Ziehau
34996150453fSSepherosa Ziehau sc->phy_layer = ixgbe_get_supported_physical_layer(hw);
350063d483cdSSepherosa Ziehau ix_init_media(sc);
350163d483cdSSepherosa Ziehau
350263d483cdSSepherosa Ziehau if (sc->advspeed != IXGBE_LINK_SPEED_UNKNOWN)
350363d483cdSSepherosa Ziehau autoneg = sc->advspeed;
350463d483cdSSepherosa Ziehau else
350579251f5eSSepherosa Ziehau autoneg = hw->phy.autoneg_advertised;
350679251f5eSSepherosa Ziehau if (!autoneg && hw->mac.ops.get_link_capabilities != NULL) {
350779251f5eSSepherosa Ziehau bool negotiate;
350879251f5eSSepherosa Ziehau
350979251f5eSSepherosa Ziehau hw->mac.ops.get_link_capabilities(hw, &autoneg, &negotiate);
351079251f5eSSepherosa Ziehau }
351179251f5eSSepherosa Ziehau if (hw->mac.ops.setup_link != NULL)
351279251f5eSSepherosa Ziehau hw->mac.ops.setup_link(hw, autoneg, TRUE);
351379251f5eSSepherosa Ziehau }
351479251f5eSSepherosa Ziehau
351579251f5eSSepherosa Ziehau static void
ix_handle_phy(struct ix_softc * sc)351663d483cdSSepherosa Ziehau ix_handle_phy(struct ix_softc *sc)
351763d483cdSSepherosa Ziehau {
351863d483cdSSepherosa Ziehau struct ixgbe_hw *hw = &sc->hw;
351963d483cdSSepherosa Ziehau int error;
352063d483cdSSepherosa Ziehau
352163d483cdSSepherosa Ziehau error = hw->phy.ops.handle_lasi(hw);
352263d483cdSSepherosa Ziehau if (error == IXGBE_ERR_OVERTEMP) {
352363d483cdSSepherosa Ziehau if_printf(&sc->arpcom.ac_if,
352463d483cdSSepherosa Ziehau "CRITICAL: EXTERNAL PHY OVER TEMP!! "
352563d483cdSSepherosa Ziehau "PHY will downshift to lower power state!\n");
352663d483cdSSepherosa Ziehau } else if (error) {
352763d483cdSSepherosa Ziehau if_printf(&sc->arpcom.ac_if,
352863d483cdSSepherosa Ziehau "Error handling LASI interrupt: %d\n", error);
352963d483cdSSepherosa Ziehau }
353063d483cdSSepherosa Ziehau }
353163d483cdSSepherosa Ziehau
353263d483cdSSepherosa Ziehau static void
ix_update_stats(struct ix_softc * sc)353379251f5eSSepherosa Ziehau ix_update_stats(struct ix_softc *sc)
353479251f5eSSepherosa Ziehau {
353579251f5eSSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if;
353679251f5eSSepherosa Ziehau struct ixgbe_hw *hw = &sc->hw;
35376150453fSSepherosa Ziehau struct ixgbe_hw_stats *stats = &sc->stats;
353879251f5eSSepherosa Ziehau uint32_t missed_rx = 0, bprc, lxon, lxoff, total;
353979251f5eSSepherosa Ziehau uint64_t total_missed_rx = 0;
354079251f5eSSepherosa Ziehau int i;
354179251f5eSSepherosa Ziehau
35426150453fSSepherosa Ziehau stats->crcerrs += IXGBE_READ_REG(hw, IXGBE_CRCERRS);
35436150453fSSepherosa Ziehau stats->illerrc += IXGBE_READ_REG(hw, IXGBE_ILLERRC);
35446150453fSSepherosa Ziehau stats->errbc += IXGBE_READ_REG(hw, IXGBE_ERRBC);
35456150453fSSepherosa Ziehau stats->mspdc += IXGBE_READ_REG(hw, IXGBE_MSPDC);
35466150453fSSepherosa Ziehau stats->mpc[0] += IXGBE_READ_REG(hw, IXGBE_MPC(0));
354779251f5eSSepherosa Ziehau
354879251f5eSSepherosa Ziehau for (i = 0; i < 16; i++) {
35496150453fSSepherosa Ziehau stats->qprc[i] += IXGBE_READ_REG(hw, IXGBE_QPRC(i));
35506150453fSSepherosa Ziehau stats->qptc[i] += IXGBE_READ_REG(hw, IXGBE_QPTC(i));
35516150453fSSepherosa Ziehau stats->qprdc[i] += IXGBE_READ_REG(hw, IXGBE_QPRDC(i));
355279251f5eSSepherosa Ziehau }
35536150453fSSepherosa Ziehau stats->mlfc += IXGBE_READ_REG(hw, IXGBE_MLFC);
35546150453fSSepherosa Ziehau stats->mrfc += IXGBE_READ_REG(hw, IXGBE_MRFC);
35556150453fSSepherosa Ziehau stats->rlec += IXGBE_READ_REG(hw, IXGBE_RLEC);
355679251f5eSSepherosa Ziehau
355779251f5eSSepherosa Ziehau /* Hardware workaround, gprc counts missed packets */
35586150453fSSepherosa Ziehau stats->gprc += IXGBE_READ_REG(hw, IXGBE_GPRC);
35596150453fSSepherosa Ziehau stats->gprc -= missed_rx;
356079251f5eSSepherosa Ziehau
356179251f5eSSepherosa Ziehau if (hw->mac.type != ixgbe_mac_82598EB) {
35626150453fSSepherosa Ziehau stats->gorc += IXGBE_READ_REG(hw, IXGBE_GORCL) +
356379251f5eSSepherosa Ziehau ((uint64_t)IXGBE_READ_REG(hw, IXGBE_GORCH) << 32);
35646150453fSSepherosa Ziehau stats->gotc += IXGBE_READ_REG(hw, IXGBE_GOTCL) +
356579251f5eSSepherosa Ziehau ((uint64_t)IXGBE_READ_REG(hw, IXGBE_GOTCH) << 32);
35666150453fSSepherosa Ziehau stats->tor += IXGBE_READ_REG(hw, IXGBE_TORL) +
356779251f5eSSepherosa Ziehau ((uint64_t)IXGBE_READ_REG(hw, IXGBE_TORH) << 32);
35686150453fSSepherosa Ziehau stats->lxonrxc += IXGBE_READ_REG(hw, IXGBE_LXONRXCNT);
35696150453fSSepherosa Ziehau stats->lxoffrxc += IXGBE_READ_REG(hw, IXGBE_LXOFFRXCNT);
357079251f5eSSepherosa Ziehau } else {
35716150453fSSepherosa Ziehau stats->lxonrxc += IXGBE_READ_REG(hw, IXGBE_LXONRXC);
35726150453fSSepherosa Ziehau stats->lxoffrxc += IXGBE_READ_REG(hw, IXGBE_LXOFFRXC);
357379251f5eSSepherosa Ziehau /* 82598 only has a counter in the high register */
35746150453fSSepherosa Ziehau stats->gorc += IXGBE_READ_REG(hw, IXGBE_GORCH);
35756150453fSSepherosa Ziehau stats->gotc += IXGBE_READ_REG(hw, IXGBE_GOTCH);
35766150453fSSepherosa Ziehau stats->tor += IXGBE_READ_REG(hw, IXGBE_TORH);
357779251f5eSSepherosa Ziehau }
357879251f5eSSepherosa Ziehau
357979251f5eSSepherosa Ziehau /*
358079251f5eSSepherosa Ziehau * Workaround: mprc hardware is incorrectly counting
358179251f5eSSepherosa Ziehau * broadcasts, so for now we subtract those.
358279251f5eSSepherosa Ziehau */
358379251f5eSSepherosa Ziehau bprc = IXGBE_READ_REG(hw, IXGBE_BPRC);
35846150453fSSepherosa Ziehau stats->bprc += bprc;
35856150453fSSepherosa Ziehau stats->mprc += IXGBE_READ_REG(hw, IXGBE_MPRC);
358679251f5eSSepherosa Ziehau if (hw->mac.type == ixgbe_mac_82598EB)
35876150453fSSepherosa Ziehau stats->mprc -= bprc;
358879251f5eSSepherosa Ziehau
35896150453fSSepherosa Ziehau stats->prc64 += IXGBE_READ_REG(hw, IXGBE_PRC64);
35906150453fSSepherosa Ziehau stats->prc127 += IXGBE_READ_REG(hw, IXGBE_PRC127);
35916150453fSSepherosa Ziehau stats->prc255 += IXGBE_READ_REG(hw, IXGBE_PRC255);
35926150453fSSepherosa Ziehau stats->prc511 += IXGBE_READ_REG(hw, IXGBE_PRC511);
35936150453fSSepherosa Ziehau stats->prc1023 += IXGBE_READ_REG(hw, IXGBE_PRC1023);
35946150453fSSepherosa Ziehau stats->prc1522 += IXGBE_READ_REG(hw, IXGBE_PRC1522);
359579251f5eSSepherosa Ziehau
359679251f5eSSepherosa Ziehau lxon = IXGBE_READ_REG(hw, IXGBE_LXONTXC);
35976150453fSSepherosa Ziehau stats->lxontxc += lxon;
359879251f5eSSepherosa Ziehau lxoff = IXGBE_READ_REG(hw, IXGBE_LXOFFTXC);
35996150453fSSepherosa Ziehau stats->lxofftxc += lxoff;
360079251f5eSSepherosa Ziehau total = lxon + lxoff;
360179251f5eSSepherosa Ziehau
36026150453fSSepherosa Ziehau stats->gptc += IXGBE_READ_REG(hw, IXGBE_GPTC);
36036150453fSSepherosa Ziehau stats->mptc += IXGBE_READ_REG(hw, IXGBE_MPTC);
36046150453fSSepherosa Ziehau stats->ptc64 += IXGBE_READ_REG(hw, IXGBE_PTC64);
36056150453fSSepherosa Ziehau stats->gptc -= total;
36066150453fSSepherosa Ziehau stats->mptc -= total;
36076150453fSSepherosa Ziehau stats->ptc64 -= total;
36086150453fSSepherosa Ziehau stats->gotc -= total * ETHER_MIN_LEN;
360979251f5eSSepherosa Ziehau
36106150453fSSepherosa Ziehau stats->ruc += IXGBE_READ_REG(hw, IXGBE_RUC);
36116150453fSSepherosa Ziehau stats->rfc += IXGBE_READ_REG(hw, IXGBE_RFC);
36126150453fSSepherosa Ziehau stats->roc += IXGBE_READ_REG(hw, IXGBE_ROC);
36136150453fSSepherosa Ziehau stats->rjc += IXGBE_READ_REG(hw, IXGBE_RJC);
36146150453fSSepherosa Ziehau stats->mngprc += IXGBE_READ_REG(hw, IXGBE_MNGPRC);
36156150453fSSepherosa Ziehau stats->mngpdc += IXGBE_READ_REG(hw, IXGBE_MNGPDC);
36166150453fSSepherosa Ziehau stats->mngptc += IXGBE_READ_REG(hw, IXGBE_MNGPTC);
36176150453fSSepherosa Ziehau stats->tpr += IXGBE_READ_REG(hw, IXGBE_TPR);
36186150453fSSepherosa Ziehau stats->tpt += IXGBE_READ_REG(hw, IXGBE_TPT);
36196150453fSSepherosa Ziehau stats->ptc127 += IXGBE_READ_REG(hw, IXGBE_PTC127);
36206150453fSSepherosa Ziehau stats->ptc255 += IXGBE_READ_REG(hw, IXGBE_PTC255);
36216150453fSSepherosa Ziehau stats->ptc511 += IXGBE_READ_REG(hw, IXGBE_PTC511);
36226150453fSSepherosa Ziehau stats->ptc1023 += IXGBE_READ_REG(hw, IXGBE_PTC1023);
36236150453fSSepherosa Ziehau stats->ptc1522 += IXGBE_READ_REG(hw, IXGBE_PTC1522);
36246150453fSSepherosa Ziehau stats->bptc += IXGBE_READ_REG(hw, IXGBE_BPTC);
36256150453fSSepherosa Ziehau stats->xec += IXGBE_READ_REG(hw, IXGBE_XEC);
36266150453fSSepherosa Ziehau stats->fccrc += IXGBE_READ_REG(hw, IXGBE_FCCRC);
36276150453fSSepherosa Ziehau stats->fclast += IXGBE_READ_REG(hw, IXGBE_FCLAST);
362879251f5eSSepherosa Ziehau /* Only read FCOE on 82599 */
362979251f5eSSepherosa Ziehau if (hw->mac.type != ixgbe_mac_82598EB) {
36306150453fSSepherosa Ziehau stats->fcoerpdc += IXGBE_READ_REG(hw, IXGBE_FCOERPDC);
36316150453fSSepherosa Ziehau stats->fcoeprc += IXGBE_READ_REG(hw, IXGBE_FCOEPRC);
36326150453fSSepherosa Ziehau stats->fcoeptc += IXGBE_READ_REG(hw, IXGBE_FCOEPTC);
36336150453fSSepherosa Ziehau stats->fcoedwrc += IXGBE_READ_REG(hw, IXGBE_FCOEDWRC);
36346150453fSSepherosa Ziehau stats->fcoedwtc += IXGBE_READ_REG(hw, IXGBE_FCOEDWTC);
363579251f5eSSepherosa Ziehau }
363679251f5eSSepherosa Ziehau
363779251f5eSSepherosa Ziehau /* Rx Errors */
363879251f5eSSepherosa Ziehau IFNET_STAT_SET(ifp, iqdrops, total_missed_rx);
363979251f5eSSepherosa Ziehau IFNET_STAT_SET(ifp, ierrors, sc->stats.crcerrs + sc->stats.rlec);
364079251f5eSSepherosa Ziehau }
364179251f5eSSepherosa Ziehau
364279251f5eSSepherosa Ziehau #if 0
364379251f5eSSepherosa Ziehau /*
364479251f5eSSepherosa Ziehau * Add sysctl variables, one per statistic, to the system.
364579251f5eSSepherosa Ziehau */
364679251f5eSSepherosa Ziehau static void
364779251f5eSSepherosa Ziehau ix_add_hw_stats(struct ix_softc *sc)
364879251f5eSSepherosa Ziehau {
364979251f5eSSepherosa Ziehau
365079251f5eSSepherosa Ziehau device_t dev = sc->dev;
365179251f5eSSepherosa Ziehau
365279251f5eSSepherosa Ziehau struct ix_tx_ring *txr = sc->tx_rings;
365379251f5eSSepherosa Ziehau struct ix_rx_ring *rxr = sc->rx_rings;
365479251f5eSSepherosa Ziehau
365579251f5eSSepherosa Ziehau struct sysctl_ctx_list *ctx = device_get_sysctl_ctx(dev);
365679251f5eSSepherosa Ziehau struct sysctl_oid *tree = device_get_sysctl_tree(dev);
365779251f5eSSepherosa Ziehau struct sysctl_oid_list *child = SYSCTL_CHILDREN(tree);
365879251f5eSSepherosa Ziehau struct ixgbe_hw_stats *stats = &sc->stats;
365979251f5eSSepherosa Ziehau
366079251f5eSSepherosa Ziehau struct sysctl_oid *stat_node, *queue_node;
366179251f5eSSepherosa Ziehau struct sysctl_oid_list *stat_list, *queue_list;
366279251f5eSSepherosa Ziehau
366379251f5eSSepherosa Ziehau #define QUEUE_NAME_LEN 32
366479251f5eSSepherosa Ziehau char namebuf[QUEUE_NAME_LEN];
366579251f5eSSepherosa Ziehau
366679251f5eSSepherosa Ziehau /* MAC stats get the own sub node */
366779251f5eSSepherosa Ziehau
366879251f5eSSepherosa Ziehau stat_node = SYSCTL_ADD_NODE(ctx, child, OID_AUTO, "mac_stats",
366979251f5eSSepherosa Ziehau CTLFLAG_RD, NULL, "MAC Statistics");
367079251f5eSSepherosa Ziehau stat_list = SYSCTL_CHILDREN(stat_node);
367179251f5eSSepherosa Ziehau
367279251f5eSSepherosa Ziehau SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "crc_errs",
367379251f5eSSepherosa Ziehau CTLFLAG_RD, &stats->crcerrs,
367479251f5eSSepherosa Ziehau "CRC Errors");
367579251f5eSSepherosa Ziehau SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "ill_errs",
367679251f5eSSepherosa Ziehau CTLFLAG_RD, &stats->illerrc,
367779251f5eSSepherosa Ziehau "Illegal Byte Errors");
367879251f5eSSepherosa Ziehau SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "byte_errs",
367979251f5eSSepherosa Ziehau CTLFLAG_RD, &stats->errbc,
368079251f5eSSepherosa Ziehau "Byte Errors");
368179251f5eSSepherosa Ziehau SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "short_discards",
368279251f5eSSepherosa Ziehau CTLFLAG_RD, &stats->mspdc,
368379251f5eSSepherosa Ziehau "MAC Short Packets Discarded");
368479251f5eSSepherosa Ziehau SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "local_faults",
368579251f5eSSepherosa Ziehau CTLFLAG_RD, &stats->mlfc,
368679251f5eSSepherosa Ziehau "MAC Local Faults");
368779251f5eSSepherosa Ziehau SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "remote_faults",
368879251f5eSSepherosa Ziehau CTLFLAG_RD, &stats->mrfc,
368979251f5eSSepherosa Ziehau "MAC Remote Faults");
369079251f5eSSepherosa Ziehau SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rec_len_errs",
369179251f5eSSepherosa Ziehau CTLFLAG_RD, &stats->rlec,
369279251f5eSSepherosa Ziehau "Receive Length Errors");
369379251f5eSSepherosa Ziehau
369479251f5eSSepherosa Ziehau /* Flow Control stats */
369579251f5eSSepherosa Ziehau SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "xon_txd",
369679251f5eSSepherosa Ziehau CTLFLAG_RD, &stats->lxontxc,
369779251f5eSSepherosa Ziehau "Link XON Transmitted");
369879251f5eSSepherosa Ziehau SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "xon_recvd",
369979251f5eSSepherosa Ziehau CTLFLAG_RD, &stats->lxonrxc,
370079251f5eSSepherosa Ziehau "Link XON Received");
370179251f5eSSepherosa Ziehau SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "xoff_txd",
370279251f5eSSepherosa Ziehau CTLFLAG_RD, &stats->lxofftxc,
370379251f5eSSepherosa Ziehau "Link XOFF Transmitted");
370479251f5eSSepherosa Ziehau SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "xoff_recvd",
370579251f5eSSepherosa Ziehau CTLFLAG_RD, &stats->lxoffrxc,
370679251f5eSSepherosa Ziehau "Link XOFF Received");
370779251f5eSSepherosa Ziehau
370879251f5eSSepherosa Ziehau /* Packet Reception Stats */
370979251f5eSSepherosa Ziehau SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "total_octets_rcvd",
371079251f5eSSepherosa Ziehau CTLFLAG_RD, &stats->tor,
371179251f5eSSepherosa Ziehau "Total Octets Received");
371279251f5eSSepherosa Ziehau SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "good_octets_rcvd",
371379251f5eSSepherosa Ziehau CTLFLAG_RD, &stats->gorc,
371479251f5eSSepherosa Ziehau "Good Octets Received");
371579251f5eSSepherosa Ziehau SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "total_pkts_rcvd",
371679251f5eSSepherosa Ziehau CTLFLAG_RD, &stats->tpr,
371779251f5eSSepherosa Ziehau "Total Packets Received");
371879251f5eSSepherosa Ziehau SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "good_pkts_rcvd",
371979251f5eSSepherosa Ziehau CTLFLAG_RD, &stats->gprc,
372079251f5eSSepherosa Ziehau "Good Packets Received");
372179251f5eSSepherosa Ziehau SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "mcast_pkts_rcvd",
372279251f5eSSepherosa Ziehau CTLFLAG_RD, &stats->mprc,
372379251f5eSSepherosa Ziehau "Multicast Packets Received");
372479251f5eSSepherosa Ziehau SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "bcast_pkts_rcvd",
372579251f5eSSepherosa Ziehau CTLFLAG_RD, &stats->bprc,
372679251f5eSSepherosa Ziehau "Broadcast Packets Received");
372779251f5eSSepherosa Ziehau SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_frames_64",
372879251f5eSSepherosa Ziehau CTLFLAG_RD, &stats->prc64,
372979251f5eSSepherosa Ziehau "64 byte frames received ");
373079251f5eSSepherosa Ziehau SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_frames_65_127",
373179251f5eSSepherosa Ziehau CTLFLAG_RD, &stats->prc127,
373279251f5eSSepherosa Ziehau "65-127 byte frames received");
373379251f5eSSepherosa Ziehau SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_frames_128_255",
373479251f5eSSepherosa Ziehau CTLFLAG_RD, &stats->prc255,
373579251f5eSSepherosa Ziehau "128-255 byte frames received");
373679251f5eSSepherosa Ziehau SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_frames_256_511",
373779251f5eSSepherosa Ziehau CTLFLAG_RD, &stats->prc511,
373879251f5eSSepherosa Ziehau "256-511 byte frames received");
373979251f5eSSepherosa Ziehau SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_frames_512_1023",
374079251f5eSSepherosa Ziehau CTLFLAG_RD, &stats->prc1023,
374179251f5eSSepherosa Ziehau "512-1023 byte frames received");
374279251f5eSSepherosa Ziehau SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_frames_1024_1522",
374379251f5eSSepherosa Ziehau CTLFLAG_RD, &stats->prc1522,
374479251f5eSSepherosa Ziehau "1023-1522 byte frames received");
374579251f5eSSepherosa Ziehau SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "recv_undersized",
374679251f5eSSepherosa Ziehau CTLFLAG_RD, &stats->ruc,
374779251f5eSSepherosa Ziehau "Receive Undersized");
374879251f5eSSepherosa Ziehau SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "recv_fragmented",
374979251f5eSSepherosa Ziehau CTLFLAG_RD, &stats->rfc,
375079251f5eSSepherosa Ziehau "Fragmented Packets Received ");
375179251f5eSSepherosa Ziehau SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "recv_oversized",
375279251f5eSSepherosa Ziehau CTLFLAG_RD, &stats->roc,
375379251f5eSSepherosa Ziehau "Oversized Packets Received");
375479251f5eSSepherosa Ziehau SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "recv_jabberd",
375579251f5eSSepherosa Ziehau CTLFLAG_RD, &stats->rjc,
375679251f5eSSepherosa Ziehau "Received Jabber");
375779251f5eSSepherosa Ziehau SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "management_pkts_rcvd",
375879251f5eSSepherosa Ziehau CTLFLAG_RD, &stats->mngprc,
375979251f5eSSepherosa Ziehau "Management Packets Received");
376079251f5eSSepherosa Ziehau SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "management_pkts_drpd",
376179251f5eSSepherosa Ziehau CTLFLAG_RD, &stats->mngptc,
376279251f5eSSepherosa Ziehau "Management Packets Dropped");
376379251f5eSSepherosa Ziehau SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "checksum_errs",
376479251f5eSSepherosa Ziehau CTLFLAG_RD, &stats->xec,
376579251f5eSSepherosa Ziehau "Checksum Errors");
376679251f5eSSepherosa Ziehau
376779251f5eSSepherosa Ziehau /* Packet Transmission Stats */
376879251f5eSSepherosa Ziehau SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "good_octets_txd",
376979251f5eSSepherosa Ziehau CTLFLAG_RD, &stats->gotc,
377079251f5eSSepherosa Ziehau "Good Octets Transmitted");
377179251f5eSSepherosa Ziehau SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "total_pkts_txd",
377279251f5eSSepherosa Ziehau CTLFLAG_RD, &stats->tpt,
377379251f5eSSepherosa Ziehau "Total Packets Transmitted");
377479251f5eSSepherosa Ziehau SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "good_pkts_txd",
377579251f5eSSepherosa Ziehau CTLFLAG_RD, &stats->gptc,
377679251f5eSSepherosa Ziehau "Good Packets Transmitted");
377779251f5eSSepherosa Ziehau SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "bcast_pkts_txd",
377879251f5eSSepherosa Ziehau CTLFLAG_RD, &stats->bptc,
377979251f5eSSepherosa Ziehau "Broadcast Packets Transmitted");
378079251f5eSSepherosa Ziehau SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "mcast_pkts_txd",
378179251f5eSSepherosa Ziehau CTLFLAG_RD, &stats->mptc,
378279251f5eSSepherosa Ziehau "Multicast Packets Transmitted");
378379251f5eSSepherosa Ziehau SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "management_pkts_txd",
378479251f5eSSepherosa Ziehau CTLFLAG_RD, &stats->mngptc,
378579251f5eSSepherosa Ziehau "Management Packets Transmitted");
378679251f5eSSepherosa Ziehau SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "tx_frames_64",
378779251f5eSSepherosa Ziehau CTLFLAG_RD, &stats->ptc64,
378879251f5eSSepherosa Ziehau "64 byte frames transmitted ");
378979251f5eSSepherosa Ziehau SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "tx_frames_65_127",
379079251f5eSSepherosa Ziehau CTLFLAG_RD, &stats->ptc127,
379179251f5eSSepherosa Ziehau "65-127 byte frames transmitted");
379279251f5eSSepherosa Ziehau SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "tx_frames_128_255",
379379251f5eSSepherosa Ziehau CTLFLAG_RD, &stats->ptc255,
379479251f5eSSepherosa Ziehau "128-255 byte frames transmitted");
379579251f5eSSepherosa Ziehau SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "tx_frames_256_511",
379679251f5eSSepherosa Ziehau CTLFLAG_RD, &stats->ptc511,
379779251f5eSSepherosa Ziehau "256-511 byte frames transmitted");
379879251f5eSSepherosa Ziehau SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "tx_frames_512_1023",
379979251f5eSSepherosa Ziehau CTLFLAG_RD, &stats->ptc1023,
380079251f5eSSepherosa Ziehau "512-1023 byte frames transmitted");
380179251f5eSSepherosa Ziehau SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "tx_frames_1024_1522",
380279251f5eSSepherosa Ziehau CTLFLAG_RD, &stats->ptc1522,
380379251f5eSSepherosa Ziehau "1024-1522 byte frames transmitted");
380479251f5eSSepherosa Ziehau }
380579251f5eSSepherosa Ziehau #endif
380679251f5eSSepherosa Ziehau
380779251f5eSSepherosa Ziehau /*
380879251f5eSSepherosa Ziehau * Enable the hardware to drop packets when the buffer is full.
380979251f5eSSepherosa Ziehau * This is useful when multiple RX rings are used, so that no
381079251f5eSSepherosa Ziehau * single RX ring being full stalls the entire RX engine. We
381179251f5eSSepherosa Ziehau * only enable this when multiple RX rings are used and when
381279251f5eSSepherosa Ziehau * flow control is disabled.
381379251f5eSSepherosa Ziehau */
381479251f5eSSepherosa Ziehau static void
ix_enable_rx_drop(struct ix_softc * sc)381579251f5eSSepherosa Ziehau ix_enable_rx_drop(struct ix_softc *sc)
381679251f5eSSepherosa Ziehau {
381779251f5eSSepherosa Ziehau struct ixgbe_hw *hw = &sc->hw;
381879251f5eSSepherosa Ziehau int i;
381979251f5eSSepherosa Ziehau
382079251f5eSSepherosa Ziehau if (bootverbose) {
382179251f5eSSepherosa Ziehau if_printf(&sc->arpcom.ac_if,
3822060fa21cSSepherosa Ziehau "flow control %s, enable RX drop\n",
3823060fa21cSSepherosa Ziehau ix_fc2str(sc->hw.fc.current_mode));
382479251f5eSSepherosa Ziehau }
382579251f5eSSepherosa Ziehau
382679251f5eSSepherosa Ziehau for (i = 0; i < sc->rx_ring_inuse; ++i) {
382779251f5eSSepherosa Ziehau uint32_t srrctl = IXGBE_READ_REG(hw, IXGBE_SRRCTL(i));
382879251f5eSSepherosa Ziehau
382979251f5eSSepherosa Ziehau srrctl |= IXGBE_SRRCTL_DROP_EN;
383079251f5eSSepherosa Ziehau IXGBE_WRITE_REG(hw, IXGBE_SRRCTL(i), srrctl);
383179251f5eSSepherosa Ziehau }
383279251f5eSSepherosa Ziehau }
383379251f5eSSepherosa Ziehau
383479251f5eSSepherosa Ziehau static void
ix_disable_rx_drop(struct ix_softc * sc)383579251f5eSSepherosa Ziehau ix_disable_rx_drop(struct ix_softc *sc)
383679251f5eSSepherosa Ziehau {
383779251f5eSSepherosa Ziehau struct ixgbe_hw *hw = &sc->hw;
383879251f5eSSepherosa Ziehau int i;
383979251f5eSSepherosa Ziehau
384079251f5eSSepherosa Ziehau if (bootverbose) {
384179251f5eSSepherosa Ziehau if_printf(&sc->arpcom.ac_if,
3842060fa21cSSepherosa Ziehau "flow control %s, disable RX drop\n",
3843060fa21cSSepherosa Ziehau ix_fc2str(sc->hw.fc.current_mode));
384479251f5eSSepherosa Ziehau }
384579251f5eSSepherosa Ziehau
384679251f5eSSepherosa Ziehau for (i = 0; i < sc->rx_ring_inuse; ++i) {
384779251f5eSSepherosa Ziehau uint32_t srrctl = IXGBE_READ_REG(hw, IXGBE_SRRCTL(i));
384879251f5eSSepherosa Ziehau
384979251f5eSSepherosa Ziehau srrctl &= ~IXGBE_SRRCTL_DROP_EN;
385079251f5eSSepherosa Ziehau IXGBE_WRITE_REG(hw, IXGBE_SRRCTL(i), srrctl);
385179251f5eSSepherosa Ziehau }
385279251f5eSSepherosa Ziehau }
385379251f5eSSepherosa Ziehau
385479251f5eSSepherosa Ziehau static void
ix_setup_serialize(struct ix_softc * sc)385579251f5eSSepherosa Ziehau ix_setup_serialize(struct ix_softc *sc)
385679251f5eSSepherosa Ziehau {
385779251f5eSSepherosa Ziehau int i = 0, j;
385879251f5eSSepherosa Ziehau
385979251f5eSSepherosa Ziehau /* Main + RX + TX */
386079251f5eSSepherosa Ziehau sc->nserialize = 1 + sc->rx_ring_cnt + sc->tx_ring_cnt;
386179251f5eSSepherosa Ziehau sc->serializes =
386279251f5eSSepherosa Ziehau kmalloc(sc->nserialize * sizeof(struct lwkt_serialize *),
386379251f5eSSepherosa Ziehau M_DEVBUF, M_WAITOK | M_ZERO);
386479251f5eSSepherosa Ziehau
386579251f5eSSepherosa Ziehau /*
386679251f5eSSepherosa Ziehau * Setup serializes
386779251f5eSSepherosa Ziehau *
386879251f5eSSepherosa Ziehau * NOTE: Order is critical
386979251f5eSSepherosa Ziehau */
387079251f5eSSepherosa Ziehau
387179251f5eSSepherosa Ziehau KKASSERT(i < sc->nserialize);
387279251f5eSSepherosa Ziehau sc->serializes[i++] = &sc->main_serialize;
387379251f5eSSepherosa Ziehau
387479251f5eSSepherosa Ziehau for (j = 0; j < sc->rx_ring_cnt; ++j) {
387579251f5eSSepherosa Ziehau KKASSERT(i < sc->nserialize);
387679251f5eSSepherosa Ziehau sc->serializes[i++] = &sc->rx_rings[j].rx_serialize;
387779251f5eSSepherosa Ziehau }
387879251f5eSSepherosa Ziehau
387979251f5eSSepherosa Ziehau for (j = 0; j < sc->tx_ring_cnt; ++j) {
388079251f5eSSepherosa Ziehau KKASSERT(i < sc->nserialize);
388179251f5eSSepherosa Ziehau sc->serializes[i++] = &sc->tx_rings[j].tx_serialize;
388279251f5eSSepherosa Ziehau }
388379251f5eSSepherosa Ziehau
388479251f5eSSepherosa Ziehau KKASSERT(i == sc->nserialize);
388579251f5eSSepherosa Ziehau }
388679251f5eSSepherosa Ziehau
388779251f5eSSepherosa Ziehau static int
ix_alloc_intr(struct ix_softc * sc)388879251f5eSSepherosa Ziehau ix_alloc_intr(struct ix_softc *sc)
388979251f5eSSepherosa Ziehau {
389079251f5eSSepherosa Ziehau struct ix_intr_data *intr;
38913c37d13bSSepherosa Ziehau struct ix_tx_ring *txr;
389279251f5eSSepherosa Ziehau u_int intr_flags;
38933c37d13bSSepherosa Ziehau int i;
3894189a0ff3SSepherosa Ziehau
3895189a0ff3SSepherosa Ziehau ix_alloc_msix(sc);
3896189a0ff3SSepherosa Ziehau if (sc->intr_type == PCI_INTR_TYPE_MSIX) {
3897189a0ff3SSepherosa Ziehau ix_set_ring_inuse(sc, FALSE);
38983c37d13bSSepherosa Ziehau goto done;
3899189a0ff3SSepherosa Ziehau }
390079251f5eSSepherosa Ziehau
39013c37d13bSSepherosa Ziehau /*
39023c37d13bSSepherosa Ziehau * Reset some settings changed by ix_alloc_msix().
39033c37d13bSSepherosa Ziehau */
39043c37d13bSSepherosa Ziehau if (sc->rx_rmap_intr != NULL) {
39053c37d13bSSepherosa Ziehau if_ringmap_free(sc->rx_rmap_intr);
39063c37d13bSSepherosa Ziehau sc->rx_rmap_intr = NULL;
39073c37d13bSSepherosa Ziehau }
39083c37d13bSSepherosa Ziehau if (sc->tx_rmap_intr != NULL) {
39093c37d13bSSepherosa Ziehau if_ringmap_free(sc->tx_rmap_intr);
39103c37d13bSSepherosa Ziehau sc->tx_rmap_intr = NULL;
39113c37d13bSSepherosa Ziehau }
39123c37d13bSSepherosa Ziehau if (sc->intr_data != NULL) {
391379251f5eSSepherosa Ziehau kfree(sc->intr_data, M_DEVBUF);
39143c37d13bSSepherosa Ziehau sc->intr_data = NULL;
39153c37d13bSSepherosa Ziehau }
39163c37d13bSSepherosa Ziehau for (i = 0; i < sc->tx_ring_cnt; ++i) {
39173c37d13bSSepherosa Ziehau txr = &sc->tx_rings[i];
39183c37d13bSSepherosa Ziehau txr->tx_intr_vec = -1;
39193c37d13bSSepherosa Ziehau txr->tx_intr_cpuid = -1;
39203c37d13bSSepherosa Ziehau }
39213c37d13bSSepherosa Ziehau for (i = 0; i < sc->rx_ring_cnt; ++i) {
39223c37d13bSSepherosa Ziehau struct ix_rx_ring *rxr = &sc->rx_rings[i];
39233c37d13bSSepherosa Ziehau
39243c37d13bSSepherosa Ziehau rxr->rx_intr_vec = -1;
39253c37d13bSSepherosa Ziehau rxr->rx_txr = NULL;
39263c37d13bSSepherosa Ziehau }
392779251f5eSSepherosa Ziehau
392879251f5eSSepherosa Ziehau sc->intr_cnt = 1;
392979251f5eSSepherosa Ziehau sc->intr_data = kmalloc(sizeof(struct ix_intr_data), M_DEVBUF,
393079251f5eSSepherosa Ziehau M_WAITOK | M_ZERO);
393179251f5eSSepherosa Ziehau intr = &sc->intr_data[0];
393279251f5eSSepherosa Ziehau
393379251f5eSSepherosa Ziehau /*
393479251f5eSSepherosa Ziehau * Allocate MSI/legacy interrupt resource
393579251f5eSSepherosa Ziehau */
39366150453fSSepherosa Ziehau if (sc->caps & IX_CAP_LEGACY_INTR) {
393779251f5eSSepherosa Ziehau sc->intr_type = pci_alloc_1intr(sc->dev, ix_msi_enable,
393879251f5eSSepherosa Ziehau &intr->intr_rid, &intr_flags);
39396150453fSSepherosa Ziehau } else {
39406150453fSSepherosa Ziehau int cpu;
39416150453fSSepherosa Ziehau
39426150453fSSepherosa Ziehau /*
39436150453fSSepherosa Ziehau * Only MSI is supported.
39446150453fSSepherosa Ziehau */
39456150453fSSepherosa Ziehau cpu = device_getenv_int(sc->dev, "msi.cpu", -1);
39466150453fSSepherosa Ziehau if (cpu >= ncpus)
39476150453fSSepherosa Ziehau cpu = ncpus - 1;
39486150453fSSepherosa Ziehau
39496150453fSSepherosa Ziehau if (pci_alloc_msi(sc->dev, &intr->intr_rid, 1, cpu) == 0) {
39506150453fSSepherosa Ziehau sc->intr_type = PCI_INTR_TYPE_MSI;
39516150453fSSepherosa Ziehau intr_flags = RF_ACTIVE;
39526150453fSSepherosa Ziehau } else {
39536150453fSSepherosa Ziehau sc->intr_type = PCI_INTR_TYPE_LEGACY;
39546150453fSSepherosa Ziehau device_printf(sc->dev, "Unable to allocate MSI\n");
39556150453fSSepherosa Ziehau return ENXIO;
39566150453fSSepherosa Ziehau }
39576150453fSSepherosa Ziehau }
395879251f5eSSepherosa Ziehau
395979251f5eSSepherosa Ziehau intr->intr_res = bus_alloc_resource_any(sc->dev, SYS_RES_IRQ,
396079251f5eSSepherosa Ziehau &intr->intr_rid, intr_flags);
396179251f5eSSepherosa Ziehau if (intr->intr_res == NULL) {
396279251f5eSSepherosa Ziehau device_printf(sc->dev, "Unable to allocate bus resource: "
396379251f5eSSepherosa Ziehau "interrupt\n");
396479251f5eSSepherosa Ziehau return ENXIO;
396579251f5eSSepherosa Ziehau }
396679251f5eSSepherosa Ziehau
396779251f5eSSepherosa Ziehau intr->intr_serialize = &sc->main_serialize;
396879251f5eSSepherosa Ziehau intr->intr_cpuid = rman_get_cpuid(intr->intr_res);
39696150453fSSepherosa Ziehau if (sc->hw.mac.type == ixgbe_mac_82598EB)
39706150453fSSepherosa Ziehau intr->intr_func = ix_intr_82598;
39716150453fSSepherosa Ziehau else
397279251f5eSSepherosa Ziehau intr->intr_func = ix_intr;
397379251f5eSSepherosa Ziehau intr->intr_funcarg = sc;
397479251f5eSSepherosa Ziehau intr->intr_rate = IX_INTR_RATE;
397579251f5eSSepherosa Ziehau intr->intr_use = IX_INTR_USE_RXTX;
397679251f5eSSepherosa Ziehau
3977189a0ff3SSepherosa Ziehau sc->tx_rings[0].tx_intr_vec = IX_TX_INTR_VEC;
39783c37d13bSSepherosa Ziehau sc->tx_rings[0].tx_intr_cpuid = intr->intr_cpuid;
397979251f5eSSepherosa Ziehau
3980189a0ff3SSepherosa Ziehau sc->rx_rings[0].rx_intr_vec = IX_RX0_INTR_VEC;
398179251f5eSSepherosa Ziehau
398279251f5eSSepherosa Ziehau ix_set_ring_inuse(sc, FALSE);
398379251f5eSSepherosa Ziehau
398479251f5eSSepherosa Ziehau KKASSERT(sc->rx_ring_inuse <= IX_MIN_RXRING_RSS);
39853c37d13bSSepherosa Ziehau if (sc->rx_ring_inuse == IX_MIN_RXRING_RSS) {
398679251f5eSSepherosa Ziehau sc->rx_rings[1].rx_intr_vec = IX_RX1_INTR_VEC;
398779251f5eSSepherosa Ziehau
39883c37d13bSSepherosa Ziehau /*
39893c37d13bSSepherosa Ziehau * Allocate RX ring map for RSS setup.
39903c37d13bSSepherosa Ziehau */
39913c37d13bSSepherosa Ziehau sc->rx_rmap_intr = if_ringmap_alloc(sc->dev,
39923c37d13bSSepherosa Ziehau IX_MIN_RXRING_RSS, IX_MIN_RXRING_RSS);
39933c37d13bSSepherosa Ziehau KASSERT(if_ringmap_count(sc->rx_rmap_intr) ==
39943c37d13bSSepherosa Ziehau sc->rx_ring_inuse, ("RX ring inuse mismatch"));
39953c37d13bSSepherosa Ziehau }
39963c37d13bSSepherosa Ziehau done:
39973c37d13bSSepherosa Ziehau for (i = 0; i < sc->tx_ring_cnt; ++i) {
39983c37d13bSSepherosa Ziehau txr = &sc->tx_rings[i];
39993c37d13bSSepherosa Ziehau if (txr->tx_intr_cpuid < 0)
40003c37d13bSSepherosa Ziehau txr->tx_intr_cpuid = 0;
40013c37d13bSSepherosa Ziehau }
400279251f5eSSepherosa Ziehau return 0;
400379251f5eSSepherosa Ziehau }
400479251f5eSSepherosa Ziehau
400579251f5eSSepherosa Ziehau static void
ix_free_intr(struct ix_softc * sc)400679251f5eSSepherosa Ziehau ix_free_intr(struct ix_softc *sc)
400779251f5eSSepherosa Ziehau {
400879251f5eSSepherosa Ziehau if (sc->intr_data == NULL)
400979251f5eSSepherosa Ziehau return;
401079251f5eSSepherosa Ziehau
401179251f5eSSepherosa Ziehau if (sc->intr_type != PCI_INTR_TYPE_MSIX) {
401279251f5eSSepherosa Ziehau struct ix_intr_data *intr = &sc->intr_data[0];
401379251f5eSSepherosa Ziehau
401479251f5eSSepherosa Ziehau KKASSERT(sc->intr_cnt == 1);
401579251f5eSSepherosa Ziehau if (intr->intr_res != NULL) {
401679251f5eSSepherosa Ziehau bus_release_resource(sc->dev, SYS_RES_IRQ,
401779251f5eSSepherosa Ziehau intr->intr_rid, intr->intr_res);
401879251f5eSSepherosa Ziehau }
401979251f5eSSepherosa Ziehau if (sc->intr_type == PCI_INTR_TYPE_MSI)
402079251f5eSSepherosa Ziehau pci_release_msi(sc->dev);
4021189a0ff3SSepherosa Ziehau
402279251f5eSSepherosa Ziehau kfree(sc->intr_data, M_DEVBUF);
4023189a0ff3SSepherosa Ziehau } else {
4024189a0ff3SSepherosa Ziehau ix_free_msix(sc, TRUE);
4025189a0ff3SSepherosa Ziehau }
402679251f5eSSepherosa Ziehau }
402779251f5eSSepherosa Ziehau
402879251f5eSSepherosa Ziehau static void
ix_set_ring_inuse(struct ix_softc * sc,boolean_t polling)402979251f5eSSepherosa Ziehau ix_set_ring_inuse(struct ix_softc *sc, boolean_t polling)
403079251f5eSSepherosa Ziehau {
403179251f5eSSepherosa Ziehau sc->rx_ring_inuse = ix_get_rxring_inuse(sc, polling);
403279251f5eSSepherosa Ziehau sc->tx_ring_inuse = ix_get_txring_inuse(sc, polling);
403379251f5eSSepherosa Ziehau if (bootverbose) {
403479251f5eSSepherosa Ziehau if_printf(&sc->arpcom.ac_if,
403579251f5eSSepherosa Ziehau "RX rings %d/%d, TX rings %d/%d\n",
403679251f5eSSepherosa Ziehau sc->rx_ring_inuse, sc->rx_ring_cnt,
403779251f5eSSepherosa Ziehau sc->tx_ring_inuse, sc->tx_ring_cnt);
403879251f5eSSepherosa Ziehau }
403979251f5eSSepherosa Ziehau }
404079251f5eSSepherosa Ziehau
404179251f5eSSepherosa Ziehau static int
ix_get_rxring_inuse(const struct ix_softc * sc,boolean_t polling)404279251f5eSSepherosa Ziehau ix_get_rxring_inuse(const struct ix_softc *sc, boolean_t polling)
404379251f5eSSepherosa Ziehau {
404479251f5eSSepherosa Ziehau if (!IX_ENABLE_HWRSS(sc))
404579251f5eSSepherosa Ziehau return 1;
404679251f5eSSepherosa Ziehau
404779251f5eSSepherosa Ziehau if (polling)
404879251f5eSSepherosa Ziehau return sc->rx_ring_cnt;
404979251f5eSSepherosa Ziehau else if (sc->intr_type != PCI_INTR_TYPE_MSIX)
405079251f5eSSepherosa Ziehau return IX_MIN_RXRING_RSS;
405179251f5eSSepherosa Ziehau else
4052189a0ff3SSepherosa Ziehau return sc->rx_ring_msix;
405379251f5eSSepherosa Ziehau }
405479251f5eSSepherosa Ziehau
405579251f5eSSepherosa Ziehau static int
ix_get_txring_inuse(const struct ix_softc * sc,boolean_t polling)405679251f5eSSepherosa Ziehau ix_get_txring_inuse(const struct ix_softc *sc, boolean_t polling)
405779251f5eSSepherosa Ziehau {
405879251f5eSSepherosa Ziehau if (!IX_ENABLE_HWTSS(sc))
405979251f5eSSepherosa Ziehau return 1;
406079251f5eSSepherosa Ziehau
406179251f5eSSepherosa Ziehau if (polling)
406279251f5eSSepherosa Ziehau return sc->tx_ring_cnt;
406379251f5eSSepherosa Ziehau else if (sc->intr_type != PCI_INTR_TYPE_MSIX)
406479251f5eSSepherosa Ziehau return 1;
406579251f5eSSepherosa Ziehau else
4066189a0ff3SSepherosa Ziehau return sc->tx_ring_msix;
406779251f5eSSepherosa Ziehau }
406879251f5eSSepherosa Ziehau
406979251f5eSSepherosa Ziehau static int
ix_setup_intr(struct ix_softc * sc)407079251f5eSSepherosa Ziehau ix_setup_intr(struct ix_softc *sc)
407179251f5eSSepherosa Ziehau {
407279251f5eSSepherosa Ziehau int i;
407379251f5eSSepherosa Ziehau
407479251f5eSSepherosa Ziehau for (i = 0; i < sc->intr_cnt; ++i) {
407579251f5eSSepherosa Ziehau struct ix_intr_data *intr = &sc->intr_data[i];
407679251f5eSSepherosa Ziehau int error;
407779251f5eSSepherosa Ziehau
407879251f5eSSepherosa Ziehau error = bus_setup_intr_descr(sc->dev, intr->intr_res,
407979251f5eSSepherosa Ziehau INTR_MPSAFE, intr->intr_func, intr->intr_funcarg,
408079251f5eSSepherosa Ziehau &intr->intr_hand, intr->intr_serialize, intr->intr_desc);
408179251f5eSSepherosa Ziehau if (error) {
408279251f5eSSepherosa Ziehau device_printf(sc->dev, "can't setup %dth intr\n", i);
408379251f5eSSepherosa Ziehau ix_teardown_intr(sc, i);
408479251f5eSSepherosa Ziehau return error;
408579251f5eSSepherosa Ziehau }
408679251f5eSSepherosa Ziehau }
408779251f5eSSepherosa Ziehau return 0;
408879251f5eSSepherosa Ziehau }
408979251f5eSSepherosa Ziehau
409079251f5eSSepherosa Ziehau static void
ix_teardown_intr(struct ix_softc * sc,int intr_cnt)409179251f5eSSepherosa Ziehau ix_teardown_intr(struct ix_softc *sc, int intr_cnt)
409279251f5eSSepherosa Ziehau {
409379251f5eSSepherosa Ziehau int i;
409479251f5eSSepherosa Ziehau
409579251f5eSSepherosa Ziehau if (sc->intr_data == NULL)
409679251f5eSSepherosa Ziehau return;
409779251f5eSSepherosa Ziehau
409879251f5eSSepherosa Ziehau for (i = 0; i < intr_cnt; ++i) {
409979251f5eSSepherosa Ziehau struct ix_intr_data *intr = &sc->intr_data[i];
410079251f5eSSepherosa Ziehau
410179251f5eSSepherosa Ziehau bus_teardown_intr(sc->dev, intr->intr_res, intr->intr_hand);
410279251f5eSSepherosa Ziehau }
410379251f5eSSepherosa Ziehau }
410479251f5eSSepherosa Ziehau
410579251f5eSSepherosa Ziehau static void
ix_serialize(struct ifnet * ifp,enum ifnet_serialize slz)410679251f5eSSepherosa Ziehau ix_serialize(struct ifnet *ifp, enum ifnet_serialize slz)
410779251f5eSSepherosa Ziehau {
410879251f5eSSepherosa Ziehau struct ix_softc *sc = ifp->if_softc;
410979251f5eSSepherosa Ziehau
411079251f5eSSepherosa Ziehau ifnet_serialize_array_enter(sc->serializes, sc->nserialize, slz);
411179251f5eSSepherosa Ziehau }
411279251f5eSSepherosa Ziehau
411379251f5eSSepherosa Ziehau static void
ix_deserialize(struct ifnet * ifp,enum ifnet_serialize slz)411479251f5eSSepherosa Ziehau ix_deserialize(struct ifnet *ifp, enum ifnet_serialize slz)
411579251f5eSSepherosa Ziehau {
411679251f5eSSepherosa Ziehau struct ix_softc *sc = ifp->if_softc;
411779251f5eSSepherosa Ziehau
411879251f5eSSepherosa Ziehau ifnet_serialize_array_exit(sc->serializes, sc->nserialize, slz);
411979251f5eSSepherosa Ziehau }
412079251f5eSSepherosa Ziehau
412179251f5eSSepherosa Ziehau static int
ix_tryserialize(struct ifnet * ifp,enum ifnet_serialize slz)412279251f5eSSepherosa Ziehau ix_tryserialize(struct ifnet *ifp, enum ifnet_serialize slz)
412379251f5eSSepherosa Ziehau {
412479251f5eSSepherosa Ziehau struct ix_softc *sc = ifp->if_softc;
412579251f5eSSepherosa Ziehau
412679251f5eSSepherosa Ziehau return ifnet_serialize_array_try(sc->serializes, sc->nserialize, slz);
412779251f5eSSepherosa Ziehau }
412879251f5eSSepherosa Ziehau
4129dd5ce676SSepherosa Ziehau static void
ix_serialize_skipmain(struct ix_softc * sc)4130dd5ce676SSepherosa Ziehau ix_serialize_skipmain(struct ix_softc *sc)
4131dd5ce676SSepherosa Ziehau {
4132dd5ce676SSepherosa Ziehau lwkt_serialize_array_enter(sc->serializes, sc->nserialize, 1);
4133dd5ce676SSepherosa Ziehau }
4134dd5ce676SSepherosa Ziehau
4135dd5ce676SSepherosa Ziehau static void
ix_deserialize_skipmain(struct ix_softc * sc)4136dd5ce676SSepherosa Ziehau ix_deserialize_skipmain(struct ix_softc *sc)
4137dd5ce676SSepherosa Ziehau {
4138dd5ce676SSepherosa Ziehau lwkt_serialize_array_exit(sc->serializes, sc->nserialize, 1);
4139dd5ce676SSepherosa Ziehau }
4140dd5ce676SSepherosa Ziehau
414179251f5eSSepherosa Ziehau #ifdef INVARIANTS
414279251f5eSSepherosa Ziehau
414379251f5eSSepherosa Ziehau static void
ix_serialize_assert(struct ifnet * ifp,enum ifnet_serialize slz,boolean_t serialized)414479251f5eSSepherosa Ziehau ix_serialize_assert(struct ifnet *ifp, enum ifnet_serialize slz,
414579251f5eSSepherosa Ziehau boolean_t serialized)
414679251f5eSSepherosa Ziehau {
414779251f5eSSepherosa Ziehau struct ix_softc *sc = ifp->if_softc;
414879251f5eSSepherosa Ziehau
414979251f5eSSepherosa Ziehau ifnet_serialize_array_assert(sc->serializes, sc->nserialize, slz,
415079251f5eSSepherosa Ziehau serialized);
415179251f5eSSepherosa Ziehau }
415279251f5eSSepherosa Ziehau
415379251f5eSSepherosa Ziehau #endif /* INVARIANTS */
415479251f5eSSepherosa Ziehau
415579251f5eSSepherosa Ziehau static void
ix_free_rings(struct ix_softc * sc)415679251f5eSSepherosa Ziehau ix_free_rings(struct ix_softc *sc)
415779251f5eSSepherosa Ziehau {
415879251f5eSSepherosa Ziehau int i;
415979251f5eSSepherosa Ziehau
416079251f5eSSepherosa Ziehau if (sc->tx_rings != NULL) {
416179251f5eSSepherosa Ziehau for (i = 0; i < sc->tx_ring_cnt; ++i) {
416279251f5eSSepherosa Ziehau struct ix_tx_ring *txr = &sc->tx_rings[i];
416379251f5eSSepherosa Ziehau
416479251f5eSSepherosa Ziehau ix_destroy_tx_ring(txr, txr->tx_ndesc);
416579251f5eSSepherosa Ziehau }
416679251f5eSSepherosa Ziehau kfree(sc->tx_rings, M_DEVBUF);
416779251f5eSSepherosa Ziehau }
416879251f5eSSepherosa Ziehau
416979251f5eSSepherosa Ziehau if (sc->rx_rings != NULL) {
417079251f5eSSepherosa Ziehau for (i =0; i < sc->rx_ring_cnt; ++i) {
417179251f5eSSepherosa Ziehau struct ix_rx_ring *rxr = &sc->rx_rings[i];
417279251f5eSSepherosa Ziehau
417379251f5eSSepherosa Ziehau ix_destroy_rx_ring(rxr, rxr->rx_ndesc);
417479251f5eSSepherosa Ziehau }
417579251f5eSSepherosa Ziehau kfree(sc->rx_rings, M_DEVBUF);
417679251f5eSSepherosa Ziehau }
417779251f5eSSepherosa Ziehau
417879251f5eSSepherosa Ziehau if (sc->parent_tag != NULL)
417979251f5eSSepherosa Ziehau bus_dma_tag_destroy(sc->parent_tag);
418079251f5eSSepherosa Ziehau }
418179251f5eSSepherosa Ziehau
418279251f5eSSepherosa Ziehau static void
ix_watchdog_reset(struct ix_softc * sc)41838d0afa86SSepherosa Ziehau ix_watchdog_reset(struct ix_softc *sc)
41848d0afa86SSepherosa Ziehau {
41858d0afa86SSepherosa Ziehau int i;
41868d0afa86SSepherosa Ziehau
41878d0afa86SSepherosa Ziehau ASSERT_IFNET_SERIALIZED_ALL(&sc->arpcom.ac_if);
41888d0afa86SSepherosa Ziehau ix_init(sc);
41898d0afa86SSepherosa Ziehau for (i = 0; i < sc->tx_ring_inuse; ++i)
41908d0afa86SSepherosa Ziehau ifsq_devstart_sched(sc->tx_rings[i].tx_ifsq);
41918d0afa86SSepherosa Ziehau }
41928d0afa86SSepherosa Ziehau
41938d0afa86SSepherosa Ziehau static void
ix_sync_netisr(struct ix_softc * sc,int flags)41948d0afa86SSepherosa Ziehau ix_sync_netisr(struct ix_softc *sc, int flags)
41958d0afa86SSepherosa Ziehau {
41968d0afa86SSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if;
41978d0afa86SSepherosa Ziehau
41988d0afa86SSepherosa Ziehau ifnet_serialize_all(ifp);
41998d0afa86SSepherosa Ziehau if (ifp->if_flags & IFF_RUNNING) {
42008d0afa86SSepherosa Ziehau ifp->if_flags &= ~(IFF_RUNNING | flags);
42018d0afa86SSepherosa Ziehau } else {
42028d0afa86SSepherosa Ziehau ifnet_deserialize_all(ifp);
42038d0afa86SSepherosa Ziehau return;
42048d0afa86SSepherosa Ziehau }
42058d0afa86SSepherosa Ziehau ifnet_deserialize_all(ifp);
42068d0afa86SSepherosa Ziehau
42078d0afa86SSepherosa Ziehau /* Make sure that polling stopped. */
42088d0afa86SSepherosa Ziehau netmsg_service_sync();
42098d0afa86SSepherosa Ziehau }
42108d0afa86SSepherosa Ziehau
42118d0afa86SSepherosa Ziehau static void
ix_watchdog_task(void * xsc,int pending __unused)42128d0afa86SSepherosa Ziehau ix_watchdog_task(void *xsc, int pending __unused)
42138d0afa86SSepherosa Ziehau {
42148d0afa86SSepherosa Ziehau struct ix_softc *sc = xsc;
42158d0afa86SSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if;
42168d0afa86SSepherosa Ziehau
42178d0afa86SSepherosa Ziehau ix_sync_netisr(sc, 0);
42188d0afa86SSepherosa Ziehau
42198d0afa86SSepherosa Ziehau ifnet_serialize_all(ifp);
42208d0afa86SSepherosa Ziehau if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) == IFF_UP)
42218d0afa86SSepherosa Ziehau ix_watchdog_reset(sc);
42228d0afa86SSepherosa Ziehau ifnet_deserialize_all(ifp);
42238d0afa86SSepherosa Ziehau }
42248d0afa86SSepherosa Ziehau
42258d0afa86SSepherosa Ziehau static void
ix_watchdog(struct ifaltq_subque * ifsq)422679251f5eSSepherosa Ziehau ix_watchdog(struct ifaltq_subque *ifsq)
422779251f5eSSepherosa Ziehau {
422879251f5eSSepherosa Ziehau struct ix_tx_ring *txr = ifsq_get_priv(ifsq);
422979251f5eSSepherosa Ziehau struct ifnet *ifp = ifsq_get_ifp(ifsq);
423079251f5eSSepherosa Ziehau struct ix_softc *sc = ifp->if_softc;
423179251f5eSSepherosa Ziehau
423279251f5eSSepherosa Ziehau KKASSERT(txr->tx_ifsq == ifsq);
423379251f5eSSepherosa Ziehau ASSERT_IFNET_SERIALIZED_ALL(ifp);
423479251f5eSSepherosa Ziehau
423579251f5eSSepherosa Ziehau /*
423679251f5eSSepherosa Ziehau * If the interface has been paused then don't do the watchdog check
423779251f5eSSepherosa Ziehau */
423879251f5eSSepherosa Ziehau if (IXGBE_READ_REG(&sc->hw, IXGBE_TFCS) & IXGBE_TFCS_TXOFF) {
4239e2292763SMatthew Dillon ifsq_watchdog_set_count(&txr->tx_watchdog, 5);
424079251f5eSSepherosa Ziehau return;
424179251f5eSSepherosa Ziehau }
424279251f5eSSepherosa Ziehau
424379251f5eSSepherosa Ziehau if_printf(ifp, "Watchdog timeout -- resetting\n");
424479251f5eSSepherosa Ziehau if_printf(ifp, "Queue(%d) tdh = %d, hw tdt = %d\n", txr->tx_idx,
424579251f5eSSepherosa Ziehau IXGBE_READ_REG(&sc->hw, IXGBE_TDH(txr->tx_idx)),
424679251f5eSSepherosa Ziehau IXGBE_READ_REG(&sc->hw, IXGBE_TDT(txr->tx_idx)));
424779251f5eSSepherosa Ziehau if_printf(ifp, "TX(%d) desc avail = %d, next TX to Clean = %d\n",
424879251f5eSSepherosa Ziehau txr->tx_idx, txr->tx_avail, txr->tx_next_clean);
424979251f5eSSepherosa Ziehau
42508d0afa86SSepherosa Ziehau if ((ifp->if_flags & (IFF_IDIRECT | IFF_NPOLLING | IFF_RUNNING)) ==
42518d0afa86SSepherosa Ziehau (IFF_IDIRECT | IFF_NPOLLING | IFF_RUNNING))
42528d0afa86SSepherosa Ziehau taskqueue_enqueue(taskqueue_thread[0], &sc->wdog_task);
42538d0afa86SSepherosa Ziehau else
42548d0afa86SSepherosa Ziehau ix_watchdog_reset(sc);
425579251f5eSSepherosa Ziehau }
425679251f5eSSepherosa Ziehau
425779251f5eSSepherosa Ziehau static void
ix_free_tx_ring(struct ix_tx_ring * txr)425879251f5eSSepherosa Ziehau ix_free_tx_ring(struct ix_tx_ring *txr)
425979251f5eSSepherosa Ziehau {
426079251f5eSSepherosa Ziehau int i;
426179251f5eSSepherosa Ziehau
426279251f5eSSepherosa Ziehau for (i = 0; i < txr->tx_ndesc; ++i) {
426379251f5eSSepherosa Ziehau struct ix_tx_buf *txbuf = &txr->tx_buf[i];
426479251f5eSSepherosa Ziehau
426582db96e9SSepherosa Ziehau if (txbuf->m_head != NULL)
426682db96e9SSepherosa Ziehau ix_free_txbuf(txr, txbuf);
426779251f5eSSepherosa Ziehau }
426879251f5eSSepherosa Ziehau }
426979251f5eSSepherosa Ziehau
427079251f5eSSepherosa Ziehau static void
ix_free_rx_ring(struct ix_rx_ring * rxr)427179251f5eSSepherosa Ziehau ix_free_rx_ring(struct ix_rx_ring *rxr)
427279251f5eSSepherosa Ziehau {
427379251f5eSSepherosa Ziehau int i;
427479251f5eSSepherosa Ziehau
427579251f5eSSepherosa Ziehau for (i = 0; i < rxr->rx_ndesc; ++i) {
427679251f5eSSepherosa Ziehau struct ix_rx_buf *rxbuf = &rxr->rx_buf[i];
427779251f5eSSepherosa Ziehau
427879251f5eSSepherosa Ziehau if (rxbuf->fmp != NULL) {
427979251f5eSSepherosa Ziehau m_freem(rxbuf->fmp);
428079251f5eSSepherosa Ziehau rxbuf->fmp = NULL;
428179251f5eSSepherosa Ziehau rxbuf->lmp = NULL;
428279251f5eSSepherosa Ziehau } else {
428379251f5eSSepherosa Ziehau KKASSERT(rxbuf->lmp == NULL);
428479251f5eSSepherosa Ziehau }
428579251f5eSSepherosa Ziehau if (rxbuf->m_head != NULL) {
428679251f5eSSepherosa Ziehau bus_dmamap_unload(rxr->rx_tag, rxbuf->map);
428779251f5eSSepherosa Ziehau m_freem(rxbuf->m_head);
428879251f5eSSepherosa Ziehau rxbuf->m_head = NULL;
428979251f5eSSepherosa Ziehau }
429079251f5eSSepherosa Ziehau }
429179251f5eSSepherosa Ziehau }
429279251f5eSSepherosa Ziehau
429379251f5eSSepherosa Ziehau static int
ix_newbuf(struct ix_rx_ring * rxr,int i,boolean_t wait)429479251f5eSSepherosa Ziehau ix_newbuf(struct ix_rx_ring *rxr, int i, boolean_t wait)
429579251f5eSSepherosa Ziehau {
429679251f5eSSepherosa Ziehau struct mbuf *m;
429779251f5eSSepherosa Ziehau bus_dma_segment_t seg;
429879251f5eSSepherosa Ziehau bus_dmamap_t map;
429979251f5eSSepherosa Ziehau struct ix_rx_buf *rxbuf;
430079251f5eSSepherosa Ziehau int flags, error, nseg;
430179251f5eSSepherosa Ziehau
4302b5523eacSSascha Wildner flags = M_NOWAIT;
430379251f5eSSepherosa Ziehau if (__predict_false(wait))
4304b5523eacSSascha Wildner flags = M_WAITOK;
430579251f5eSSepherosa Ziehau
430679251f5eSSepherosa Ziehau m = m_getjcl(flags, MT_DATA, M_PKTHDR, rxr->rx_mbuf_sz);
430779251f5eSSepherosa Ziehau if (m == NULL) {
430879251f5eSSepherosa Ziehau if (wait) {
430979251f5eSSepherosa Ziehau if_printf(&rxr->rx_sc->arpcom.ac_if,
431079251f5eSSepherosa Ziehau "Unable to allocate RX mbuf\n");
431179251f5eSSepherosa Ziehau }
431279251f5eSSepherosa Ziehau return ENOBUFS;
431379251f5eSSepherosa Ziehau }
431479251f5eSSepherosa Ziehau m->m_len = m->m_pkthdr.len = rxr->rx_mbuf_sz;
431579251f5eSSepherosa Ziehau
431679251f5eSSepherosa Ziehau error = bus_dmamap_load_mbuf_segment(rxr->rx_tag,
431779251f5eSSepherosa Ziehau rxr->rx_sparemap, m, &seg, 1, &nseg, BUS_DMA_NOWAIT);
431879251f5eSSepherosa Ziehau if (error) {
431979251f5eSSepherosa Ziehau m_freem(m);
432079251f5eSSepherosa Ziehau if (wait) {
432179251f5eSSepherosa Ziehau if_printf(&rxr->rx_sc->arpcom.ac_if,
432279251f5eSSepherosa Ziehau "Unable to load RX mbuf\n");
432379251f5eSSepherosa Ziehau }
432479251f5eSSepherosa Ziehau return error;
432579251f5eSSepherosa Ziehau }
432679251f5eSSepherosa Ziehau
432779251f5eSSepherosa Ziehau rxbuf = &rxr->rx_buf[i];
432879251f5eSSepherosa Ziehau if (rxbuf->m_head != NULL)
432979251f5eSSepherosa Ziehau bus_dmamap_unload(rxr->rx_tag, rxbuf->map);
433079251f5eSSepherosa Ziehau
433179251f5eSSepherosa Ziehau map = rxbuf->map;
433279251f5eSSepherosa Ziehau rxbuf->map = rxr->rx_sparemap;
433379251f5eSSepherosa Ziehau rxr->rx_sparemap = map;
433479251f5eSSepherosa Ziehau
433579251f5eSSepherosa Ziehau rxbuf->m_head = m;
433679251f5eSSepherosa Ziehau rxbuf->paddr = seg.ds_addr;
433779251f5eSSepherosa Ziehau
433879251f5eSSepherosa Ziehau ix_setup_rxdesc(&rxr->rx_base[i], rxbuf);
433979251f5eSSepherosa Ziehau return 0;
434079251f5eSSepherosa Ziehau }
434179251f5eSSepherosa Ziehau
434279251f5eSSepherosa Ziehau static void
ix_add_sysctl(struct ix_softc * sc)434379251f5eSSepherosa Ziehau ix_add_sysctl(struct ix_softc *sc)
434479251f5eSSepherosa Ziehau {
434526595b18SSascha Wildner struct sysctl_ctx_list *ctx = device_get_sysctl_ctx(sc->dev);
434626595b18SSascha Wildner struct sysctl_oid *tree = device_get_sysctl_tree(sc->dev);
434779251f5eSSepherosa Ziehau char node[32];
4348020afcaaSSascha Wildner int i;
434979251f5eSSepherosa Ziehau
435026595b18SSascha Wildner SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(tree),
435179251f5eSSepherosa Ziehau OID_AUTO, "rxr", CTLFLAG_RD, &sc->rx_ring_cnt, 0, "# of RX rings");
435226595b18SSascha Wildner SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(tree),
435379251f5eSSepherosa Ziehau OID_AUTO, "rxr_inuse", CTLFLAG_RD, &sc->rx_ring_inuse, 0,
435479251f5eSSepherosa Ziehau "# of RX rings used");
435526595b18SSascha Wildner SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(tree),
435679251f5eSSepherosa Ziehau OID_AUTO, "txr", CTLFLAG_RD, &sc->tx_ring_cnt, 0, "# of TX rings");
435726595b18SSascha Wildner SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(tree),
435879251f5eSSepherosa Ziehau OID_AUTO, "txr_inuse", CTLFLAG_RD, &sc->tx_ring_inuse, 0,
435979251f5eSSepherosa Ziehau "# of TX rings used");
436026595b18SSascha Wildner SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree),
436179251f5eSSepherosa Ziehau OID_AUTO, "rxd", CTLTYPE_INT | CTLFLAG_RD,
436279251f5eSSepherosa Ziehau sc, 0, ix_sysctl_rxd, "I",
436379251f5eSSepherosa Ziehau "# of RX descs");
436426595b18SSascha Wildner SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree),
436579251f5eSSepherosa Ziehau OID_AUTO, "txd", CTLTYPE_INT | CTLFLAG_RD,
436679251f5eSSepherosa Ziehau sc, 0, ix_sysctl_txd, "I",
436779251f5eSSepherosa Ziehau "# of TX descs");
436826595b18SSascha Wildner SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree),
436979251f5eSSepherosa Ziehau OID_AUTO, "tx_wreg_nsegs", CTLTYPE_INT | CTLFLAG_RW,
437079251f5eSSepherosa Ziehau sc, 0, ix_sysctl_tx_wreg_nsegs, "I",
437179251f5eSSepherosa Ziehau "# of segments sent before write to hardware register");
437226595b18SSascha Wildner SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree),
437379251f5eSSepherosa Ziehau OID_AUTO, "rx_wreg_nsegs", CTLTYPE_INT | CTLFLAG_RW,
437479251f5eSSepherosa Ziehau sc, 0, ix_sysctl_rx_wreg_nsegs, "I",
437579251f5eSSepherosa Ziehau "# of received segments sent before write to hardware register");
437626595b18SSascha Wildner SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree),
437779251f5eSSepherosa Ziehau OID_AUTO, "tx_intr_nsegs", CTLTYPE_INT | CTLFLAG_RW,
437879251f5eSSepherosa Ziehau sc, 0, ix_sysctl_tx_intr_nsegs, "I",
437979251f5eSSepherosa Ziehau "# of segments per TX interrupt");
43808d0afa86SSepherosa Ziehau SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(tree),
43818d0afa86SSepherosa Ziehau OID_AUTO, "direct_input", CTLFLAG_RW, &sc->direct_input, 0,
43828d0afa86SSepherosa Ziehau "Enable direct input");
43833c37d13bSSepherosa Ziehau if (sc->intr_type == PCI_INTR_TYPE_MSIX) {
43843c37d13bSSepherosa Ziehau SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree),
43853c37d13bSSepherosa Ziehau OID_AUTO, "tx_msix_cpumap", CTLTYPE_OPAQUE | CTLFLAG_RD,
43863c37d13bSSepherosa Ziehau sc->tx_rmap_intr, 0, if_ringmap_cpumap_sysctl, "I",
43873c37d13bSSepherosa Ziehau "TX MSI-X CPU map");
43883c37d13bSSepherosa Ziehau SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree),
43893c37d13bSSepherosa Ziehau OID_AUTO, "rx_msix_cpumap", CTLTYPE_OPAQUE | CTLFLAG_RD,
43903c37d13bSSepherosa Ziehau sc->rx_rmap_intr, 0, if_ringmap_cpumap_sysctl, "I",
43913c37d13bSSepherosa Ziehau "RX MSI-X CPU map");
43923c37d13bSSepherosa Ziehau }
43934a648aefSSepherosa Ziehau #ifdef IFPOLL_ENABLE
439426595b18SSascha Wildner SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree),
43953c37d13bSSepherosa Ziehau OID_AUTO, "tx_poll_cpumap", CTLTYPE_OPAQUE | CTLFLAG_RD,
43963c37d13bSSepherosa Ziehau sc->tx_rmap, 0, if_ringmap_cpumap_sysctl, "I",
43973c37d13bSSepherosa Ziehau "TX polling CPU map");
439826595b18SSascha Wildner SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree),
43993c37d13bSSepherosa Ziehau OID_AUTO, "rx_poll_cpumap", CTLTYPE_OPAQUE | CTLFLAG_RD,
44003c37d13bSSepherosa Ziehau sc->rx_rmap, 0, if_ringmap_cpumap_sysctl, "I",
44013c37d13bSSepherosa Ziehau "RX polling CPU map");
44024a648aefSSepherosa Ziehau #endif
44034a648aefSSepherosa Ziehau
4404189a0ff3SSepherosa Ziehau #define IX_ADD_INTR_RATE_SYSCTL(sc, use, name) \
4405189a0ff3SSepherosa Ziehau do { \
4406189a0ff3SSepherosa Ziehau ix_add_intr_rate_sysctl(sc, IX_INTR_USE_##use, #name, \
4407189a0ff3SSepherosa Ziehau ix_sysctl_##name, #use " interrupt rate"); \
4408189a0ff3SSepherosa Ziehau } while (0)
4409189a0ff3SSepherosa Ziehau
4410189a0ff3SSepherosa Ziehau IX_ADD_INTR_RATE_SYSCTL(sc, RXTX, rxtx_intr_rate);
4411189a0ff3SSepherosa Ziehau IX_ADD_INTR_RATE_SYSCTL(sc, RX, rx_intr_rate);
4412189a0ff3SSepherosa Ziehau IX_ADD_INTR_RATE_SYSCTL(sc, TX, tx_intr_rate);
4413189a0ff3SSepherosa Ziehau IX_ADD_INTR_RATE_SYSCTL(sc, STATUS, sts_intr_rate);
4414189a0ff3SSepherosa Ziehau
4415189a0ff3SSepherosa Ziehau #undef IX_ADD_INTR_RATE_SYSCTL
441679251f5eSSepherosa Ziehau
441779251f5eSSepherosa Ziehau #ifdef IX_RSS_DEBUG
441826595b18SSascha Wildner SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(tree),
441979251f5eSSepherosa Ziehau OID_AUTO, "rss_debug", CTLFLAG_RW, &sc->rss_debug, 0,
442079251f5eSSepherosa Ziehau "RSS debug level");
442179251f5eSSepherosa Ziehau for (i = 0; i < sc->rx_ring_cnt; ++i) {
442279251f5eSSepherosa Ziehau ksnprintf(node, sizeof(node), "rx%d_pkt", i);
442326595b18SSascha Wildner SYSCTL_ADD_ULONG(ctx,
442426595b18SSascha Wildner SYSCTL_CHILDREN(tree), OID_AUTO, node,
442579251f5eSSepherosa Ziehau CTLFLAG_RW, &sc->rx_rings[i].rx_pkts, "RXed packets");
442679251f5eSSepherosa Ziehau }
442779251f5eSSepherosa Ziehau #endif
442882db96e9SSepherosa Ziehau for (i = 0; i < sc->tx_ring_cnt; ++i) {
442982db96e9SSepherosa Ziehau struct ix_tx_ring *txr = &sc->tx_rings[i];
443082db96e9SSepherosa Ziehau
443182db96e9SSepherosa Ziehau ksnprintf(node, sizeof(node), "tx%d_nmbuf", i);
443282db96e9SSepherosa Ziehau SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, node,
443382db96e9SSepherosa Ziehau CTLTYPE_INT | CTLFLAG_RD, txr, 0, ix_sysctl_tx_nmbuf, "I",
443482db96e9SSepherosa Ziehau "# of pending TX mbufs");
443582db96e9SSepherosa Ziehau
443682db96e9SSepherosa Ziehau ksnprintf(node, sizeof(node), "tx%d_gc", i);
443782db96e9SSepherosa Ziehau SYSCTL_ADD_ULONG(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, node,
443882db96e9SSepherosa Ziehau CTLFLAG_RW, &txr->tx_gc, "# of TX desc GC");
443982db96e9SSepherosa Ziehau }
444079251f5eSSepherosa Ziehau
444179251f5eSSepherosa Ziehau #if 0
444279251f5eSSepherosa Ziehau ix_add_hw_stats(sc);
444379251f5eSSepherosa Ziehau #endif
444479251f5eSSepherosa Ziehau
444579251f5eSSepherosa Ziehau }
444679251f5eSSepherosa Ziehau
444779251f5eSSepherosa Ziehau static int
ix_sysctl_tx_nmbuf(SYSCTL_HANDLER_ARGS)444882db96e9SSepherosa Ziehau ix_sysctl_tx_nmbuf(SYSCTL_HANDLER_ARGS)
444982db96e9SSepherosa Ziehau {
445082db96e9SSepherosa Ziehau struct ix_tx_ring *txr = (void *)arg1;
445182db96e9SSepherosa Ziehau int nmbuf;
445282db96e9SSepherosa Ziehau
445382db96e9SSepherosa Ziehau nmbuf = txr->tx_nmbuf;
445482db96e9SSepherosa Ziehau return (sysctl_handle_int(oidp, &nmbuf, 0, req));
445582db96e9SSepherosa Ziehau }
445682db96e9SSepherosa Ziehau
445782db96e9SSepherosa Ziehau static int
ix_sysctl_tx_wreg_nsegs(SYSCTL_HANDLER_ARGS)445879251f5eSSepherosa Ziehau ix_sysctl_tx_wreg_nsegs(SYSCTL_HANDLER_ARGS)
445979251f5eSSepherosa Ziehau {
446079251f5eSSepherosa Ziehau struct ix_softc *sc = (void *)arg1;
446179251f5eSSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if;
446279251f5eSSepherosa Ziehau int error, nsegs, i;
446379251f5eSSepherosa Ziehau
446479251f5eSSepherosa Ziehau nsegs = sc->tx_rings[0].tx_wreg_nsegs;
446579251f5eSSepherosa Ziehau error = sysctl_handle_int(oidp, &nsegs, 0, req);
446679251f5eSSepherosa Ziehau if (error || req->newptr == NULL)
446779251f5eSSepherosa Ziehau return error;
446879251f5eSSepherosa Ziehau if (nsegs < 0)
446979251f5eSSepherosa Ziehau return EINVAL;
447079251f5eSSepherosa Ziehau
447179251f5eSSepherosa Ziehau ifnet_serialize_all(ifp);
447279251f5eSSepherosa Ziehau for (i = 0; i < sc->tx_ring_cnt; ++i)
447379251f5eSSepherosa Ziehau sc->tx_rings[i].tx_wreg_nsegs = nsegs;
447479251f5eSSepherosa Ziehau ifnet_deserialize_all(ifp);
447579251f5eSSepherosa Ziehau
447679251f5eSSepherosa Ziehau return 0;
447779251f5eSSepherosa Ziehau }
447879251f5eSSepherosa Ziehau
447979251f5eSSepherosa Ziehau static int
ix_sysctl_rx_wreg_nsegs(SYSCTL_HANDLER_ARGS)448079251f5eSSepherosa Ziehau ix_sysctl_rx_wreg_nsegs(SYSCTL_HANDLER_ARGS)
448179251f5eSSepherosa Ziehau {
448279251f5eSSepherosa Ziehau struct ix_softc *sc = (void *)arg1;
448379251f5eSSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if;
448479251f5eSSepherosa Ziehau int error, nsegs, i;
448579251f5eSSepherosa Ziehau
448679251f5eSSepherosa Ziehau nsegs = sc->rx_rings[0].rx_wreg_nsegs;
448779251f5eSSepherosa Ziehau error = sysctl_handle_int(oidp, &nsegs, 0, req);
448879251f5eSSepherosa Ziehau if (error || req->newptr == NULL)
448979251f5eSSepherosa Ziehau return error;
449079251f5eSSepherosa Ziehau if (nsegs < 0)
449179251f5eSSepherosa Ziehau return EINVAL;
449279251f5eSSepherosa Ziehau
449379251f5eSSepherosa Ziehau ifnet_serialize_all(ifp);
449479251f5eSSepherosa Ziehau for (i = 0; i < sc->rx_ring_cnt; ++i)
449579251f5eSSepherosa Ziehau sc->rx_rings[i].rx_wreg_nsegs =nsegs;
449679251f5eSSepherosa Ziehau ifnet_deserialize_all(ifp);
449779251f5eSSepherosa Ziehau
449879251f5eSSepherosa Ziehau return 0;
449979251f5eSSepherosa Ziehau }
450079251f5eSSepherosa Ziehau
450179251f5eSSepherosa Ziehau static int
ix_sysctl_txd(SYSCTL_HANDLER_ARGS)450279251f5eSSepherosa Ziehau ix_sysctl_txd(SYSCTL_HANDLER_ARGS)
450379251f5eSSepherosa Ziehau {
450479251f5eSSepherosa Ziehau struct ix_softc *sc = (void *)arg1;
450579251f5eSSepherosa Ziehau int txd;
450679251f5eSSepherosa Ziehau
450779251f5eSSepherosa Ziehau txd = sc->tx_rings[0].tx_ndesc;
450879251f5eSSepherosa Ziehau return sysctl_handle_int(oidp, &txd, 0, req);
450979251f5eSSepherosa Ziehau }
451079251f5eSSepherosa Ziehau
451179251f5eSSepherosa Ziehau static int
ix_sysctl_rxd(SYSCTL_HANDLER_ARGS)451279251f5eSSepherosa Ziehau ix_sysctl_rxd(SYSCTL_HANDLER_ARGS)
451379251f5eSSepherosa Ziehau {
451479251f5eSSepherosa Ziehau struct ix_softc *sc = (void *)arg1;
451579251f5eSSepherosa Ziehau int rxd;
451679251f5eSSepherosa Ziehau
451779251f5eSSepherosa Ziehau rxd = sc->rx_rings[0].rx_ndesc;
451879251f5eSSepherosa Ziehau return sysctl_handle_int(oidp, &rxd, 0, req);
451979251f5eSSepherosa Ziehau }
452079251f5eSSepherosa Ziehau
452179251f5eSSepherosa Ziehau static int
ix_sysctl_tx_intr_nsegs(SYSCTL_HANDLER_ARGS)452279251f5eSSepherosa Ziehau ix_sysctl_tx_intr_nsegs(SYSCTL_HANDLER_ARGS)
452379251f5eSSepherosa Ziehau {
452479251f5eSSepherosa Ziehau struct ix_softc *sc = (void *)arg1;
452579251f5eSSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if;
452679251f5eSSepherosa Ziehau struct ix_tx_ring *txr = &sc->tx_rings[0];
452779251f5eSSepherosa Ziehau int error, nsegs;
452879251f5eSSepherosa Ziehau
452979251f5eSSepherosa Ziehau nsegs = txr->tx_intr_nsegs;
453079251f5eSSepherosa Ziehau error = sysctl_handle_int(oidp, &nsegs, 0, req);
453179251f5eSSepherosa Ziehau if (error || req->newptr == NULL)
453279251f5eSSepherosa Ziehau return error;
453379251f5eSSepherosa Ziehau if (nsegs < 0)
453479251f5eSSepherosa Ziehau return EINVAL;
453579251f5eSSepherosa Ziehau
453679251f5eSSepherosa Ziehau ifnet_serialize_all(ifp);
453779251f5eSSepherosa Ziehau
453879251f5eSSepherosa Ziehau if (nsegs >= txr->tx_ndesc - IX_MAX_SCATTER - IX_TX_RESERVED) {
453979251f5eSSepherosa Ziehau error = EINVAL;
454079251f5eSSepherosa Ziehau } else {
454179251f5eSSepherosa Ziehau int i;
454279251f5eSSepherosa Ziehau
454379251f5eSSepherosa Ziehau error = 0;
454479251f5eSSepherosa Ziehau for (i = 0; i < sc->tx_ring_cnt; ++i)
454579251f5eSSepherosa Ziehau sc->tx_rings[i].tx_intr_nsegs = nsegs;
454679251f5eSSepherosa Ziehau }
454779251f5eSSepherosa Ziehau
454879251f5eSSepherosa Ziehau ifnet_deserialize_all(ifp);
454979251f5eSSepherosa Ziehau
455079251f5eSSepherosa Ziehau return error;
455179251f5eSSepherosa Ziehau }
455279251f5eSSepherosa Ziehau
455379251f5eSSepherosa Ziehau static void
ix_set_eitr(struct ix_softc * sc,int idx,int rate)455479251f5eSSepherosa Ziehau ix_set_eitr(struct ix_softc *sc, int idx, int rate)
455579251f5eSSepherosa Ziehau {
455679251f5eSSepherosa Ziehau uint32_t eitr, eitr_intvl;
455779251f5eSSepherosa Ziehau
455879251f5eSSepherosa Ziehau eitr = IXGBE_READ_REG(&sc->hw, IXGBE_EITR(idx));
455979251f5eSSepherosa Ziehau eitr_intvl = 1000000000 / 256 / rate;
456079251f5eSSepherosa Ziehau
456179251f5eSSepherosa Ziehau if (sc->hw.mac.type == ixgbe_mac_82598EB) {
456279251f5eSSepherosa Ziehau eitr &= ~IX_EITR_INTVL_MASK_82598;
456379251f5eSSepherosa Ziehau if (eitr_intvl == 0)
456479251f5eSSepherosa Ziehau eitr_intvl = 1;
456579251f5eSSepherosa Ziehau else if (eitr_intvl > IX_EITR_INTVL_MASK_82598)
456679251f5eSSepherosa Ziehau eitr_intvl = IX_EITR_INTVL_MASK_82598;
456779251f5eSSepherosa Ziehau } else {
456879251f5eSSepherosa Ziehau eitr &= ~IX_EITR_INTVL_MASK;
456979251f5eSSepherosa Ziehau
457079251f5eSSepherosa Ziehau eitr_intvl &= ~IX_EITR_INTVL_RSVD_MASK;
457179251f5eSSepherosa Ziehau if (eitr_intvl == 0)
457279251f5eSSepherosa Ziehau eitr_intvl = IX_EITR_INTVL_MIN;
457379251f5eSSepherosa Ziehau else if (eitr_intvl > IX_EITR_INTVL_MAX)
457479251f5eSSepherosa Ziehau eitr_intvl = IX_EITR_INTVL_MAX;
457579251f5eSSepherosa Ziehau }
457679251f5eSSepherosa Ziehau eitr |= eitr_intvl;
457779251f5eSSepherosa Ziehau
457879251f5eSSepherosa Ziehau IXGBE_WRITE_REG(&sc->hw, IXGBE_EITR(idx), eitr);
457979251f5eSSepherosa Ziehau }
458079251f5eSSepherosa Ziehau
458179251f5eSSepherosa Ziehau static int
ix_sysctl_rxtx_intr_rate(SYSCTL_HANDLER_ARGS)4582189a0ff3SSepherosa Ziehau ix_sysctl_rxtx_intr_rate(SYSCTL_HANDLER_ARGS)
4583189a0ff3SSepherosa Ziehau {
4584189a0ff3SSepherosa Ziehau return ix_sysctl_intr_rate(oidp, arg1, arg2, req, IX_INTR_USE_RXTX);
4585189a0ff3SSepherosa Ziehau }
4586189a0ff3SSepherosa Ziehau
4587189a0ff3SSepherosa Ziehau static int
ix_sysctl_rx_intr_rate(SYSCTL_HANDLER_ARGS)4588189a0ff3SSepherosa Ziehau ix_sysctl_rx_intr_rate(SYSCTL_HANDLER_ARGS)
4589189a0ff3SSepherosa Ziehau {
4590189a0ff3SSepherosa Ziehau return ix_sysctl_intr_rate(oidp, arg1, arg2, req, IX_INTR_USE_RX);
4591189a0ff3SSepherosa Ziehau }
4592189a0ff3SSepherosa Ziehau
4593189a0ff3SSepherosa Ziehau static int
ix_sysctl_tx_intr_rate(SYSCTL_HANDLER_ARGS)4594189a0ff3SSepherosa Ziehau ix_sysctl_tx_intr_rate(SYSCTL_HANDLER_ARGS)
4595189a0ff3SSepherosa Ziehau {
4596189a0ff3SSepherosa Ziehau return ix_sysctl_intr_rate(oidp, arg1, arg2, req, IX_INTR_USE_TX);
4597189a0ff3SSepherosa Ziehau }
4598189a0ff3SSepherosa Ziehau
4599189a0ff3SSepherosa Ziehau static int
ix_sysctl_sts_intr_rate(SYSCTL_HANDLER_ARGS)4600189a0ff3SSepherosa Ziehau ix_sysctl_sts_intr_rate(SYSCTL_HANDLER_ARGS)
4601189a0ff3SSepherosa Ziehau {
4602189a0ff3SSepherosa Ziehau return ix_sysctl_intr_rate(oidp, arg1, arg2, req, IX_INTR_USE_STATUS);
4603189a0ff3SSepherosa Ziehau }
4604189a0ff3SSepherosa Ziehau
4605189a0ff3SSepherosa Ziehau static int
ix_sysctl_intr_rate(SYSCTL_HANDLER_ARGS,int use)4606189a0ff3SSepherosa Ziehau ix_sysctl_intr_rate(SYSCTL_HANDLER_ARGS, int use)
460779251f5eSSepherosa Ziehau {
460879251f5eSSepherosa Ziehau struct ix_softc *sc = (void *)arg1;
460979251f5eSSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if;
461079251f5eSSepherosa Ziehau int error, rate, i;
461179251f5eSSepherosa Ziehau
461279251f5eSSepherosa Ziehau rate = 0;
461379251f5eSSepherosa Ziehau for (i = 0; i < sc->intr_cnt; ++i) {
4614189a0ff3SSepherosa Ziehau if (sc->intr_data[i].intr_use == use) {
461579251f5eSSepherosa Ziehau rate = sc->intr_data[i].intr_rate;
461679251f5eSSepherosa Ziehau break;
461779251f5eSSepherosa Ziehau }
461879251f5eSSepherosa Ziehau }
461979251f5eSSepherosa Ziehau
462079251f5eSSepherosa Ziehau error = sysctl_handle_int(oidp, &rate, 0, req);
462179251f5eSSepherosa Ziehau if (error || req->newptr == NULL)
462279251f5eSSepherosa Ziehau return error;
462379251f5eSSepherosa Ziehau if (rate <= 0)
462479251f5eSSepherosa Ziehau return EINVAL;
462579251f5eSSepherosa Ziehau
462679251f5eSSepherosa Ziehau ifnet_serialize_all(ifp);
462779251f5eSSepherosa Ziehau
462879251f5eSSepherosa Ziehau for (i = 0; i < sc->intr_cnt; ++i) {
4629189a0ff3SSepherosa Ziehau if (sc->intr_data[i].intr_use == use) {
463079251f5eSSepherosa Ziehau sc->intr_data[i].intr_rate = rate;
463179251f5eSSepherosa Ziehau if (ifp->if_flags & IFF_RUNNING)
463279251f5eSSepherosa Ziehau ix_set_eitr(sc, i, rate);
463379251f5eSSepherosa Ziehau }
463479251f5eSSepherosa Ziehau }
463579251f5eSSepherosa Ziehau
463679251f5eSSepherosa Ziehau ifnet_deserialize_all(ifp);
463779251f5eSSepherosa Ziehau
463879251f5eSSepherosa Ziehau return error;
463979251f5eSSepherosa Ziehau }
464079251f5eSSepherosa Ziehau
464179251f5eSSepherosa Ziehau static void
ix_add_intr_rate_sysctl(struct ix_softc * sc,int use,const char * name,int (* handler)(SYSCTL_HANDLER_ARGS),const char * desc)4642189a0ff3SSepherosa Ziehau ix_add_intr_rate_sysctl(struct ix_softc *sc, int use,
4643189a0ff3SSepherosa Ziehau const char *name, int (*handler)(SYSCTL_HANDLER_ARGS), const char *desc)
4644189a0ff3SSepherosa Ziehau {
4645189a0ff3SSepherosa Ziehau int i;
4646189a0ff3SSepherosa Ziehau
4647189a0ff3SSepherosa Ziehau for (i = 0; i < sc->intr_cnt; ++i) {
4648189a0ff3SSepherosa Ziehau if (sc->intr_data[i].intr_use == use) {
464926595b18SSascha Wildner SYSCTL_ADD_PROC(device_get_sysctl_ctx(sc->dev),
465026595b18SSascha Wildner SYSCTL_CHILDREN(device_get_sysctl_tree(sc->dev)),
4651189a0ff3SSepherosa Ziehau OID_AUTO, name, CTLTYPE_INT | CTLFLAG_RW,
4652189a0ff3SSepherosa Ziehau sc, 0, handler, "I", desc);
4653189a0ff3SSepherosa Ziehau break;
4654189a0ff3SSepherosa Ziehau }
4655189a0ff3SSepherosa Ziehau }
4656189a0ff3SSepherosa Ziehau }
4657189a0ff3SSepherosa Ziehau
4658dd5ce676SSepherosa Ziehau static int
ix_get_timer_cpuid(const struct ix_softc * sc,boolean_t polling)4659dd5ce676SSepherosa Ziehau ix_get_timer_cpuid(const struct ix_softc *sc, boolean_t polling)
466079251f5eSSepherosa Ziehau {
466179251f5eSSepherosa Ziehau if (polling || sc->intr_type == PCI_INTR_TYPE_MSIX)
4662dd5ce676SSepherosa Ziehau return 0; /* XXX fixed */
466379251f5eSSepherosa Ziehau else
4664dd5ce676SSepherosa Ziehau return rman_get_cpuid(sc->intr_data[0].intr_res);
466579251f5eSSepherosa Ziehau }
4666189a0ff3SSepherosa Ziehau
4667189a0ff3SSepherosa Ziehau static void
ix_alloc_msix(struct ix_softc * sc)4668189a0ff3SSepherosa Ziehau ix_alloc_msix(struct ix_softc *sc)
4669189a0ff3SSepherosa Ziehau {
46703c37d13bSSepherosa Ziehau int msix_enable, msix_cnt, msix_ring, alloc_cnt;
4671189a0ff3SSepherosa Ziehau struct ix_intr_data *intr;
4672189a0ff3SSepherosa Ziehau int i, x, error;
46733c37d13bSSepherosa Ziehau int ring_cnt, ring_cntmax;
46743c37d13bSSepherosa Ziehau boolean_t setup = FALSE;
4675189a0ff3SSepherosa Ziehau
4676189a0ff3SSepherosa Ziehau msix_enable = ix_msix_enable;
4677189a0ff3SSepherosa Ziehau /*
4678189a0ff3SSepherosa Ziehau * Don't enable MSI-X on 82598 by default, see:
4679189a0ff3SSepherosa Ziehau * 82598 specification update errata #38
4680189a0ff3SSepherosa Ziehau */
4681189a0ff3SSepherosa Ziehau if (sc->hw.mac.type == ixgbe_mac_82598EB)
4682189a0ff3SSepherosa Ziehau msix_enable = 0;
4683189a0ff3SSepherosa Ziehau msix_enable = device_getenv_int(sc->dev, "msix.enable", msix_enable);
4684189a0ff3SSepherosa Ziehau if (!msix_enable)
4685189a0ff3SSepherosa Ziehau return;
4686189a0ff3SSepherosa Ziehau
4687189a0ff3SSepherosa Ziehau msix_cnt = pci_msix_count(sc->dev);
4688189a0ff3SSepherosa Ziehau #ifdef IX_MSIX_DEBUG
4689189a0ff3SSepherosa Ziehau msix_cnt = device_getenv_int(sc->dev, "msix.count", msix_cnt);
4690189a0ff3SSepherosa Ziehau #endif
4691189a0ff3SSepherosa Ziehau if (msix_cnt <= 1) {
46923c37d13bSSepherosa Ziehau /* One MSI-X model does not make sense. */
4693189a0ff3SSepherosa Ziehau return;
4694189a0ff3SSepherosa Ziehau }
4695189a0ff3SSepherosa Ziehau
4696189a0ff3SSepherosa Ziehau /*
4697189a0ff3SSepherosa Ziehau * Make sure that we don't break interrupt related registers
4698189a0ff3SSepherosa Ziehau * (EIMS, etc) limitation.
4699189a0ff3SSepherosa Ziehau */
4700189a0ff3SSepherosa Ziehau if (sc->hw.mac.type == ixgbe_mac_82598EB) {
47013c37d13bSSepherosa Ziehau if (msix_cnt > IX_MAX_MSIX_82598)
47023c37d13bSSepherosa Ziehau msix_cnt = IX_MAX_MSIX_82598;
4703189a0ff3SSepherosa Ziehau } else {
47043c37d13bSSepherosa Ziehau if (msix_cnt > IX_MAX_MSIX)
47053c37d13bSSepherosa Ziehau msix_cnt = IX_MAX_MSIX;
4706189a0ff3SSepherosa Ziehau }
4707189a0ff3SSepherosa Ziehau if (bootverbose)
47083c37d13bSSepherosa Ziehau device_printf(sc->dev, "MSI-X count %d\n", msix_cnt);
47093c37d13bSSepherosa Ziehau msix_ring = msix_cnt - 1; /* -1 for status */
47103c37d13bSSepherosa Ziehau
47113c37d13bSSepherosa Ziehau /*
47123c37d13bSSepherosa Ziehau * Configure # of RX/TX rings usable by MSI-X.
47133c37d13bSSepherosa Ziehau */
47143c37d13bSSepherosa Ziehau ix_get_rxring_cnt(sc, &ring_cnt, &ring_cntmax);
47153c37d13bSSepherosa Ziehau if (ring_cntmax > msix_ring)
47163c37d13bSSepherosa Ziehau ring_cntmax = msix_ring;
47173c37d13bSSepherosa Ziehau sc->rx_rmap_intr = if_ringmap_alloc(sc->dev, ring_cnt, ring_cntmax);
47183c37d13bSSepherosa Ziehau
47193c37d13bSSepherosa Ziehau ix_get_txring_cnt(sc, &ring_cnt, &ring_cntmax);
47203c37d13bSSepherosa Ziehau if (ring_cntmax > msix_ring)
47213c37d13bSSepherosa Ziehau ring_cntmax = msix_ring;
47223c37d13bSSepherosa Ziehau sc->tx_rmap_intr = if_ringmap_alloc(sc->dev, ring_cnt, ring_cntmax);
47233c37d13bSSepherosa Ziehau
47243c37d13bSSepherosa Ziehau if_ringmap_match(sc->dev, sc->rx_rmap_intr, sc->tx_rmap_intr);
47253c37d13bSSepherosa Ziehau sc->rx_ring_msix = if_ringmap_count(sc->rx_rmap_intr);
47263c37d13bSSepherosa Ziehau KASSERT(sc->rx_ring_msix <= sc->rx_ring_cnt,
47273c37d13bSSepherosa Ziehau ("total RX ring count %d, MSI-X RX ring count %d",
47283c37d13bSSepherosa Ziehau sc->rx_ring_cnt, sc->rx_ring_msix));
47293c37d13bSSepherosa Ziehau sc->tx_ring_msix = if_ringmap_count(sc->tx_rmap_intr);
47303c37d13bSSepherosa Ziehau KASSERT(sc->tx_ring_msix <= sc->tx_ring_cnt,
47313c37d13bSSepherosa Ziehau ("total TX ring count %d, MSI-X TX ring count %d",
47323c37d13bSSepherosa Ziehau sc->tx_ring_cnt, sc->tx_ring_msix));
47333c37d13bSSepherosa Ziehau
4734189a0ff3SSepherosa Ziehau /*
4735189a0ff3SSepherosa Ziehau * Aggregate TX/RX MSI-X
4736189a0ff3SSepherosa Ziehau */
47373c37d13bSSepherosa Ziehau ring_cntmax = sc->rx_ring_msix;
47383c37d13bSSepherosa Ziehau if (ring_cntmax < sc->tx_ring_msix)
47393c37d13bSSepherosa Ziehau ring_cntmax = sc->tx_ring_msix;
47403c37d13bSSepherosa Ziehau KASSERT(ring_cntmax <= msix_ring,
47413c37d13bSSepherosa Ziehau ("invalid ring count max %d, MSI-X count for rings %d",
47423c37d13bSSepherosa Ziehau ring_cntmax, msix_ring));
4743189a0ff3SSepherosa Ziehau
47443c37d13bSSepherosa Ziehau alloc_cnt = ring_cntmax + 1; /* +1 for status */
4745189a0ff3SSepherosa Ziehau if (bootverbose) {
4746189a0ff3SSepherosa Ziehau device_printf(sc->dev, "MSI-X alloc %d, "
4747189a0ff3SSepherosa Ziehau "RX ring %d, TX ring %d\n", alloc_cnt,
4748189a0ff3SSepherosa Ziehau sc->rx_ring_msix, sc->tx_ring_msix);
4749189a0ff3SSepherosa Ziehau }
4750189a0ff3SSepherosa Ziehau
4751189a0ff3SSepherosa Ziehau sc->msix_mem_rid = PCIR_BAR(IX_MSIX_BAR_82598);
4752189a0ff3SSepherosa Ziehau sc->msix_mem_res = bus_alloc_resource_any(sc->dev, SYS_RES_MEMORY,
4753189a0ff3SSepherosa Ziehau &sc->msix_mem_rid, RF_ACTIVE);
4754189a0ff3SSepherosa Ziehau if (sc->msix_mem_res == NULL) {
4755189a0ff3SSepherosa Ziehau sc->msix_mem_rid = PCIR_BAR(IX_MSIX_BAR_82599);
4756189a0ff3SSepherosa Ziehau sc->msix_mem_res = bus_alloc_resource_any(sc->dev,
4757189a0ff3SSepherosa Ziehau SYS_RES_MEMORY, &sc->msix_mem_rid, RF_ACTIVE);
4758189a0ff3SSepherosa Ziehau if (sc->msix_mem_res == NULL) {
4759189a0ff3SSepherosa Ziehau device_printf(sc->dev, "Unable to map MSI-X table\n");
4760189a0ff3SSepherosa Ziehau return;
4761189a0ff3SSepherosa Ziehau }
4762189a0ff3SSepherosa Ziehau }
4763189a0ff3SSepherosa Ziehau
4764189a0ff3SSepherosa Ziehau sc->intr_cnt = alloc_cnt;
4765189a0ff3SSepherosa Ziehau sc->intr_data = kmalloc(sizeof(struct ix_intr_data) * sc->intr_cnt,
4766189a0ff3SSepherosa Ziehau M_DEVBUF, M_WAITOK | M_ZERO);
4767189a0ff3SSepherosa Ziehau for (x = 0; x < sc->intr_cnt; ++x) {
4768189a0ff3SSepherosa Ziehau intr = &sc->intr_data[x];
4769189a0ff3SSepherosa Ziehau intr->intr_rid = -1;
4770189a0ff3SSepherosa Ziehau intr->intr_rate = IX_INTR_RATE;
4771189a0ff3SSepherosa Ziehau }
4772189a0ff3SSepherosa Ziehau
4773189a0ff3SSepherosa Ziehau x = 0;
47743c37d13bSSepherosa Ziehau for (i = 0; i < sc->rx_ring_msix; ++i) {
4775189a0ff3SSepherosa Ziehau struct ix_rx_ring *rxr = &sc->rx_rings[i];
47763c37d13bSSepherosa Ziehau struct ix_tx_ring *txr = NULL;
47773c37d13bSSepherosa Ziehau int cpuid, j;
4778189a0ff3SSepherosa Ziehau
4779189a0ff3SSepherosa Ziehau KKASSERT(x < sc->intr_cnt);
4780189a0ff3SSepherosa Ziehau rxr->rx_intr_vec = x;
4781189a0ff3SSepherosa Ziehau ix_setup_msix_eims(sc, x,
4782189a0ff3SSepherosa Ziehau &rxr->rx_eims, &rxr->rx_eims_val);
47833c37d13bSSepherosa Ziehau
47843c37d13bSSepherosa Ziehau cpuid = if_ringmap_cpumap(sc->rx_rmap_intr, i);
47853c37d13bSSepherosa Ziehau
47863c37d13bSSepherosa Ziehau /*
47873c37d13bSSepherosa Ziehau * Try finding TX ring to piggyback.
47883c37d13bSSepherosa Ziehau */
47893c37d13bSSepherosa Ziehau for (j = 0; j < sc->tx_ring_msix; ++j) {
47903c37d13bSSepherosa Ziehau if (cpuid ==
47913c37d13bSSepherosa Ziehau if_ringmap_cpumap(sc->tx_rmap_intr, j)) {
47923c37d13bSSepherosa Ziehau txr = &sc->tx_rings[j];
47933c37d13bSSepherosa Ziehau KKASSERT(txr->tx_intr_cpuid < 0);
47943c37d13bSSepherosa Ziehau break;
47953c37d13bSSepherosa Ziehau }
47963c37d13bSSepherosa Ziehau }
4797189a0ff3SSepherosa Ziehau rxr->rx_txr = txr;
4798189a0ff3SSepherosa Ziehau
4799189a0ff3SSepherosa Ziehau intr = &sc->intr_data[x++];
4800189a0ff3SSepherosa Ziehau intr->intr_serialize = &rxr->rx_serialize;
48013c37d13bSSepherosa Ziehau if (txr != NULL) {
48023c37d13bSSepherosa Ziehau ksnprintf(intr->intr_desc0,
48033c37d13bSSepherosa Ziehau sizeof(intr->intr_desc0), "%s rx%dtx%d",
48043c37d13bSSepherosa Ziehau device_get_nameunit(sc->dev), i, txr->tx_idx);
4805189a0ff3SSepherosa Ziehau intr->intr_use = IX_INTR_USE_RXTX;
48063c37d13bSSepherosa Ziehau intr->intr_func = ix_msix_rxtx;
48073c37d13bSSepherosa Ziehau } else {
48083c37d13bSSepherosa Ziehau ksnprintf(intr->intr_desc0,
48093c37d13bSSepherosa Ziehau sizeof(intr->intr_desc0), "%s rx%d",
48103c37d13bSSepherosa Ziehau device_get_nameunit(sc->dev), i);
48113c37d13bSSepherosa Ziehau intr->intr_rate = IX_MSIX_RX_RATE;
48123c37d13bSSepherosa Ziehau intr->intr_use = IX_INTR_USE_RX;
48133c37d13bSSepherosa Ziehau intr->intr_func = ix_msix_rx;
48143c37d13bSSepherosa Ziehau }
48153c37d13bSSepherosa Ziehau intr->intr_funcarg = rxr;
48163c37d13bSSepherosa Ziehau intr->intr_cpuid = cpuid;
48173c37d13bSSepherosa Ziehau KKASSERT(intr->intr_cpuid < netisr_ncpus);
4818189a0ff3SSepherosa Ziehau intr->intr_desc = intr->intr_desc0;
48193c37d13bSSepherosa Ziehau
48203c37d13bSSepherosa Ziehau if (txr != NULL) {
48213c37d13bSSepherosa Ziehau txr->tx_intr_cpuid = intr->intr_cpuid;
48223c37d13bSSepherosa Ziehau /* NOTE: Leave TX ring's intr_vec negative. */
48233c37d13bSSepherosa Ziehau }
4824189a0ff3SSepherosa Ziehau }
4825189a0ff3SSepherosa Ziehau
48263c37d13bSSepherosa Ziehau for (i = 0; i < sc->tx_ring_msix; ++i) {
48273c37d13bSSepherosa Ziehau struct ix_tx_ring *txr = &sc->tx_rings[i];
48283c37d13bSSepherosa Ziehau
48293c37d13bSSepherosa Ziehau if (txr->tx_intr_cpuid >= 0) {
48303c37d13bSSepherosa Ziehau /* Piggybacked by RX ring. */
48313c37d13bSSepherosa Ziehau continue;
4832189a0ff3SSepherosa Ziehau }
48333c37d13bSSepherosa Ziehau
48343c37d13bSSepherosa Ziehau KKASSERT(x < sc->intr_cnt);
48353c37d13bSSepherosa Ziehau txr->tx_intr_vec = x;
48363c37d13bSSepherosa Ziehau ix_setup_msix_eims(sc, x, &txr->tx_eims, &txr->tx_eims_val);
48373c37d13bSSepherosa Ziehau
48383c37d13bSSepherosa Ziehau intr = &sc->intr_data[x++];
48393c37d13bSSepherosa Ziehau intr->intr_serialize = &txr->tx_serialize;
48403c37d13bSSepherosa Ziehau intr->intr_rate = IX_MSIX_TX_RATE;
48413c37d13bSSepherosa Ziehau intr->intr_use = IX_INTR_USE_TX;
48423c37d13bSSepherosa Ziehau intr->intr_func = ix_msix_tx;
48433c37d13bSSepherosa Ziehau intr->intr_funcarg = txr;
48443c37d13bSSepherosa Ziehau intr->intr_cpuid = if_ringmap_cpumap(sc->tx_rmap_intr, i);
48453c37d13bSSepherosa Ziehau KKASSERT(intr->intr_cpuid < netisr_ncpus);
48463c37d13bSSepherosa Ziehau ksnprintf(intr->intr_desc0, sizeof(intr->intr_desc0), "%s tx%d",
48473c37d13bSSepherosa Ziehau device_get_nameunit(sc->dev), i);
48483c37d13bSSepherosa Ziehau intr->intr_desc = intr->intr_desc0;
48493c37d13bSSepherosa Ziehau
48503c37d13bSSepherosa Ziehau txr->tx_intr_cpuid = intr->intr_cpuid;
4851189a0ff3SSepherosa Ziehau }
4852189a0ff3SSepherosa Ziehau
4853189a0ff3SSepherosa Ziehau /*
4854189a0ff3SSepherosa Ziehau * Status MSI-X
4855189a0ff3SSepherosa Ziehau */
4856189a0ff3SSepherosa Ziehau KKASSERT(x < sc->intr_cnt);
4857189a0ff3SSepherosa Ziehau sc->sts_msix_vec = x;
4858189a0ff3SSepherosa Ziehau
4859189a0ff3SSepherosa Ziehau intr = &sc->intr_data[x++];
4860189a0ff3SSepherosa Ziehau
4861189a0ff3SSepherosa Ziehau intr->intr_serialize = &sc->main_serialize;
4862189a0ff3SSepherosa Ziehau intr->intr_func = ix_msix_status;
4863189a0ff3SSepherosa Ziehau intr->intr_funcarg = sc;
4864189a0ff3SSepherosa Ziehau intr->intr_cpuid = 0;
4865189a0ff3SSepherosa Ziehau intr->intr_use = IX_INTR_USE_STATUS;
4866189a0ff3SSepherosa Ziehau
4867189a0ff3SSepherosa Ziehau ksnprintf(intr->intr_desc0, sizeof(intr->intr_desc0), "%s sts",
4868189a0ff3SSepherosa Ziehau device_get_nameunit(sc->dev));
4869189a0ff3SSepherosa Ziehau intr->intr_desc = intr->intr_desc0;
4870189a0ff3SSepherosa Ziehau
4871189a0ff3SSepherosa Ziehau KKASSERT(x == sc->intr_cnt);
4872189a0ff3SSepherosa Ziehau
4873189a0ff3SSepherosa Ziehau error = pci_setup_msix(sc->dev);
4874189a0ff3SSepherosa Ziehau if (error) {
4875189a0ff3SSepherosa Ziehau device_printf(sc->dev, "Setup MSI-X failed\n");
4876189a0ff3SSepherosa Ziehau goto back;
4877189a0ff3SSepherosa Ziehau }
4878189a0ff3SSepherosa Ziehau setup = TRUE;
4879189a0ff3SSepherosa Ziehau
4880189a0ff3SSepherosa Ziehau for (i = 0; i < sc->intr_cnt; ++i) {
4881189a0ff3SSepherosa Ziehau intr = &sc->intr_data[i];
4882189a0ff3SSepherosa Ziehau
4883189a0ff3SSepherosa Ziehau error = pci_alloc_msix_vector(sc->dev, i, &intr->intr_rid,
4884189a0ff3SSepherosa Ziehau intr->intr_cpuid);
4885189a0ff3SSepherosa Ziehau if (error) {
4886189a0ff3SSepherosa Ziehau device_printf(sc->dev,
4887189a0ff3SSepherosa Ziehau "Unable to allocate MSI-X %d on cpu%d\n", i,
4888189a0ff3SSepherosa Ziehau intr->intr_cpuid);
4889189a0ff3SSepherosa Ziehau goto back;
4890189a0ff3SSepherosa Ziehau }
4891189a0ff3SSepherosa Ziehau
4892189a0ff3SSepherosa Ziehau intr->intr_res = bus_alloc_resource_any(sc->dev, SYS_RES_IRQ,
4893189a0ff3SSepherosa Ziehau &intr->intr_rid, RF_ACTIVE);
4894189a0ff3SSepherosa Ziehau if (intr->intr_res == NULL) {
4895189a0ff3SSepherosa Ziehau device_printf(sc->dev,
4896189a0ff3SSepherosa Ziehau "Unable to allocate MSI-X %d resource\n", i);
4897189a0ff3SSepherosa Ziehau error = ENOMEM;
4898189a0ff3SSepherosa Ziehau goto back;
4899189a0ff3SSepherosa Ziehau }
4900189a0ff3SSepherosa Ziehau }
4901189a0ff3SSepherosa Ziehau
4902189a0ff3SSepherosa Ziehau pci_enable_msix(sc->dev);
4903189a0ff3SSepherosa Ziehau sc->intr_type = PCI_INTR_TYPE_MSIX;
4904189a0ff3SSepherosa Ziehau back:
4905189a0ff3SSepherosa Ziehau if (error)
4906189a0ff3SSepherosa Ziehau ix_free_msix(sc, setup);
4907189a0ff3SSepherosa Ziehau }
4908189a0ff3SSepherosa Ziehau
4909189a0ff3SSepherosa Ziehau static void
ix_free_msix(struct ix_softc * sc,boolean_t setup)4910189a0ff3SSepherosa Ziehau ix_free_msix(struct ix_softc *sc, boolean_t setup)
4911189a0ff3SSepherosa Ziehau {
4912189a0ff3SSepherosa Ziehau int i;
4913189a0ff3SSepherosa Ziehau
4914189a0ff3SSepherosa Ziehau KKASSERT(sc->intr_cnt > 1);
4915189a0ff3SSepherosa Ziehau
4916189a0ff3SSepherosa Ziehau for (i = 0; i < sc->intr_cnt; ++i) {
4917189a0ff3SSepherosa Ziehau struct ix_intr_data *intr = &sc->intr_data[i];
4918189a0ff3SSepherosa Ziehau
4919189a0ff3SSepherosa Ziehau if (intr->intr_res != NULL) {
4920189a0ff3SSepherosa Ziehau bus_release_resource(sc->dev, SYS_RES_IRQ,
4921189a0ff3SSepherosa Ziehau intr->intr_rid, intr->intr_res);
4922189a0ff3SSepherosa Ziehau }
4923189a0ff3SSepherosa Ziehau if (intr->intr_rid >= 0)
4924189a0ff3SSepherosa Ziehau pci_release_msix_vector(sc->dev, intr->intr_rid);
4925189a0ff3SSepherosa Ziehau }
4926189a0ff3SSepherosa Ziehau if (setup)
4927189a0ff3SSepherosa Ziehau pci_teardown_msix(sc->dev);
4928189a0ff3SSepherosa Ziehau
4929189a0ff3SSepherosa Ziehau sc->intr_cnt = 0;
4930189a0ff3SSepherosa Ziehau kfree(sc->intr_data, M_DEVBUF);
4931189a0ff3SSepherosa Ziehau sc->intr_data = NULL;
4932189a0ff3SSepherosa Ziehau }
4933189a0ff3SSepherosa Ziehau
4934189a0ff3SSepherosa Ziehau static void
ix_msix_rx(void * xrxr)4935189a0ff3SSepherosa Ziehau ix_msix_rx(void *xrxr)
4936189a0ff3SSepherosa Ziehau {
4937189a0ff3SSepherosa Ziehau struct ix_rx_ring *rxr = xrxr;
4938189a0ff3SSepherosa Ziehau
4939189a0ff3SSepherosa Ziehau ASSERT_SERIALIZED(&rxr->rx_serialize);
4940189a0ff3SSepherosa Ziehau
49414a648aefSSepherosa Ziehau ix_rxeof(rxr, -1);
4942189a0ff3SSepherosa Ziehau IXGBE_WRITE_REG(&rxr->rx_sc->hw, rxr->rx_eims, rxr->rx_eims_val);
4943189a0ff3SSepherosa Ziehau }
4944189a0ff3SSepherosa Ziehau
4945189a0ff3SSepherosa Ziehau static void
ix_msix_tx(void * xtxr)4946189a0ff3SSepherosa Ziehau ix_msix_tx(void *xtxr)
4947189a0ff3SSepherosa Ziehau {
4948189a0ff3SSepherosa Ziehau struct ix_tx_ring *txr = xtxr;
4949189a0ff3SSepherosa Ziehau
4950189a0ff3SSepherosa Ziehau ASSERT_SERIALIZED(&txr->tx_serialize);
4951189a0ff3SSepherosa Ziehau
495282db96e9SSepherosa Ziehau ix_tx_intr(txr, *(txr->tx_hdr));
4953189a0ff3SSepherosa Ziehau IXGBE_WRITE_REG(&txr->tx_sc->hw, txr->tx_eims, txr->tx_eims_val);
4954189a0ff3SSepherosa Ziehau }
4955189a0ff3SSepherosa Ziehau
4956189a0ff3SSepherosa Ziehau static void
ix_msix_rxtx(void * xrxr)4957189a0ff3SSepherosa Ziehau ix_msix_rxtx(void *xrxr)
4958189a0ff3SSepherosa Ziehau {
4959189a0ff3SSepherosa Ziehau struct ix_rx_ring *rxr = xrxr;
4960189a0ff3SSepherosa Ziehau struct ix_tx_ring *txr;
4961189a0ff3SSepherosa Ziehau int hdr;
4962189a0ff3SSepherosa Ziehau
4963189a0ff3SSepherosa Ziehau ASSERT_SERIALIZED(&rxr->rx_serialize);
4964189a0ff3SSepherosa Ziehau
49654a648aefSSepherosa Ziehau ix_rxeof(rxr, -1);
4966189a0ff3SSepherosa Ziehau
4967189a0ff3SSepherosa Ziehau /*
4968189a0ff3SSepherosa Ziehau * NOTE:
4969189a0ff3SSepherosa Ziehau * Since tx_next_clean is only changed by ix_txeof(),
4970189a0ff3SSepherosa Ziehau * which is called only in interrupt handler, the
4971189a0ff3SSepherosa Ziehau * check w/o holding tx serializer is MPSAFE.
4972189a0ff3SSepherosa Ziehau */
4973189a0ff3SSepherosa Ziehau txr = rxr->rx_txr;
4974189a0ff3SSepherosa Ziehau hdr = *(txr->tx_hdr);
4975189a0ff3SSepherosa Ziehau if (hdr != txr->tx_next_clean) {
4976189a0ff3SSepherosa Ziehau lwkt_serialize_enter(&txr->tx_serialize);
497782db96e9SSepherosa Ziehau ix_tx_intr(txr, hdr);
4978189a0ff3SSepherosa Ziehau lwkt_serialize_exit(&txr->tx_serialize);
4979189a0ff3SSepherosa Ziehau }
4980189a0ff3SSepherosa Ziehau
4981189a0ff3SSepherosa Ziehau IXGBE_WRITE_REG(&rxr->rx_sc->hw, rxr->rx_eims, rxr->rx_eims_val);
4982189a0ff3SSepherosa Ziehau }
4983189a0ff3SSepherosa Ziehau
4984189a0ff3SSepherosa Ziehau static void
ix_intr_status(struct ix_softc * sc,uint32_t eicr)4985189a0ff3SSepherosa Ziehau ix_intr_status(struct ix_softc *sc, uint32_t eicr)
4986189a0ff3SSepherosa Ziehau {
4987189a0ff3SSepherosa Ziehau struct ixgbe_hw *hw = &sc->hw;
4988189a0ff3SSepherosa Ziehau
4989189a0ff3SSepherosa Ziehau /* Link status change */
4990189a0ff3SSepherosa Ziehau if (eicr & IXGBE_EICR_LSC)
4991189a0ff3SSepherosa Ziehau ix_handle_link(sc);
4992189a0ff3SSepherosa Ziehau
4993189a0ff3SSepherosa Ziehau if (hw->mac.type != ixgbe_mac_82598EB) {
4994189a0ff3SSepherosa Ziehau if (eicr & IXGBE_EICR_ECC)
49956150453fSSepherosa Ziehau if_printf(&sc->arpcom.ac_if, "ECC ERROR!! REBOOT!!\n");
499663d483cdSSepherosa Ziehau
499763d483cdSSepherosa Ziehau /* Check for over temp condition */
49986150453fSSepherosa Ziehau if (sc->caps & IX_CAP_TEMP_SENSOR) {
49996150453fSSepherosa Ziehau int32_t retval;
50006150453fSSepherosa Ziehau
50016150453fSSepherosa Ziehau switch (sc->hw.mac.type) {
50026150453fSSepherosa Ziehau case ixgbe_mac_X550EM_a:
50036150453fSSepherosa Ziehau if ((eicr & IXGBE_EICR_GPI_SDP0_X550EM_a) == 0)
50046150453fSSepherosa Ziehau break;
50056150453fSSepherosa Ziehau retval = hw->phy.ops.check_overtemp(hw);
50066150453fSSepherosa Ziehau if (retval != IXGBE_ERR_OVERTEMP)
50076150453fSSepherosa Ziehau break;
50086150453fSSepherosa Ziehau
50096150453fSSepherosa Ziehau /* Disable more temp sensor interrupts. */
50106150453fSSepherosa Ziehau IXGBE_WRITE_REG(hw, IXGBE_EIMC,
50116150453fSSepherosa Ziehau IXGBE_EICR_GPI_SDP0_X550EM_a);
50126150453fSSepherosa Ziehau if_printf(&sc->arpcom.ac_if, "CRITICAL: "
50136150453fSSepherosa Ziehau "OVER TEMP!! PHY IS SHUT DOWN!! "
50146150453fSSepherosa Ziehau "SHUTDOWN!!\n");
50156150453fSSepherosa Ziehau break;
50166150453fSSepherosa Ziehau
50176150453fSSepherosa Ziehau default:
50186150453fSSepherosa Ziehau if ((eicr & IXGBE_EICR_TS) == 0)
50196150453fSSepherosa Ziehau break;
50206150453fSSepherosa Ziehau retval = hw->phy.ops.check_overtemp(hw);
50216150453fSSepherosa Ziehau if (retval != IXGBE_ERR_OVERTEMP)
50226150453fSSepherosa Ziehau break;
50236150453fSSepherosa Ziehau
50246150453fSSepherosa Ziehau /* Disable more temp sensor interrupts. */
50256150453fSSepherosa Ziehau IXGBE_WRITE_REG(hw, IXGBE_EIMC, IXGBE_EICR_TS);
50266150453fSSepherosa Ziehau if_printf(&sc->arpcom.ac_if, "CRITICAL: "
50276150453fSSepherosa Ziehau "OVER TEMP!! PHY IS SHUT DOWN!! "
50286150453fSSepherosa Ziehau "SHUTDOWN!!\n");
50296150453fSSepherosa Ziehau break;
50306150453fSSepherosa Ziehau }
503163d483cdSSepherosa Ziehau }
503263d483cdSSepherosa Ziehau }
503363d483cdSSepherosa Ziehau
503463d483cdSSepherosa Ziehau if (ix_is_sfp(hw)) {
50356150453fSSepherosa Ziehau uint32_t eicr_mask;
503663d483cdSSepherosa Ziehau
503763d483cdSSepherosa Ziehau /* Pluggable optics-related interrupt */
50386150453fSSepherosa Ziehau if (hw->mac.type >= ixgbe_mac_X540)
50396150453fSSepherosa Ziehau eicr_mask = IXGBE_EICR_GPI_SDP0_X540;
504063d483cdSSepherosa Ziehau else
50416150453fSSepherosa Ziehau eicr_mask = IXGBE_EICR_GPI_SDP2_BY_MAC(hw);
50426150453fSSepherosa Ziehau
50436150453fSSepherosa Ziehau if (eicr & eicr_mask)
5044189a0ff3SSepherosa Ziehau ix_handle_mod(sc);
50456150453fSSepherosa Ziehau
50466150453fSSepherosa Ziehau if (hw->mac.type == ixgbe_mac_82599EB &&
50476150453fSSepherosa Ziehau (eicr & IXGBE_EICR_GPI_SDP1_BY_MAC(hw)))
50486150453fSSepherosa Ziehau ix_handle_msf(sc);
5049189a0ff3SSepherosa Ziehau }
5050189a0ff3SSepherosa Ziehau
5051189a0ff3SSepherosa Ziehau /* Check for fan failure */
50526150453fSSepherosa Ziehau if (sc->caps & IX_CAP_DETECT_FANFAIL)
50536150453fSSepherosa Ziehau ix_detect_fanfail(sc, eicr, TRUE);
5054189a0ff3SSepherosa Ziehau
505563d483cdSSepherosa Ziehau /* External PHY interrupt */
50566150453fSSepherosa Ziehau if (hw->phy.type == ixgbe_phy_x550em_ext_t &&
505763d483cdSSepherosa Ziehau (eicr & IXGBE_EICR_GPI_SDP0_X540))
505863d483cdSSepherosa Ziehau ix_handle_phy(sc);
5059189a0ff3SSepherosa Ziehau }
5060189a0ff3SSepherosa Ziehau
5061189a0ff3SSepherosa Ziehau static void
ix_msix_status(void * xsc)5062189a0ff3SSepherosa Ziehau ix_msix_status(void *xsc)
5063189a0ff3SSepherosa Ziehau {
5064189a0ff3SSepherosa Ziehau struct ix_softc *sc = xsc;
5065189a0ff3SSepherosa Ziehau uint32_t eicr;
5066189a0ff3SSepherosa Ziehau
5067189a0ff3SSepherosa Ziehau ASSERT_SERIALIZED(&sc->main_serialize);
5068189a0ff3SSepherosa Ziehau
5069189a0ff3SSepherosa Ziehau eicr = IXGBE_READ_REG(&sc->hw, IXGBE_EICR);
5070189a0ff3SSepherosa Ziehau ix_intr_status(sc, eicr);
5071189a0ff3SSepherosa Ziehau
5072189a0ff3SSepherosa Ziehau IXGBE_WRITE_REG(&sc->hw, IXGBE_EIMS, sc->intr_mask);
5073189a0ff3SSepherosa Ziehau }
5074189a0ff3SSepherosa Ziehau
5075189a0ff3SSepherosa Ziehau static void
ix_setup_msix_eims(const struct ix_softc * sc,int x,uint32_t * eims,uint32_t * eims_val)5076189a0ff3SSepherosa Ziehau ix_setup_msix_eims(const struct ix_softc *sc, int x,
5077189a0ff3SSepherosa Ziehau uint32_t *eims, uint32_t *eims_val)
5078189a0ff3SSepherosa Ziehau {
5079189a0ff3SSepherosa Ziehau if (x < 32) {
5080189a0ff3SSepherosa Ziehau if (sc->hw.mac.type == ixgbe_mac_82598EB) {
5081189a0ff3SSepherosa Ziehau KASSERT(x < IX_MAX_MSIX_82598,
5082189a0ff3SSepherosa Ziehau ("%s: invalid vector %d for 82598",
5083189a0ff3SSepherosa Ziehau device_get_nameunit(sc->dev), x));
5084189a0ff3SSepherosa Ziehau *eims = IXGBE_EIMS;
5085189a0ff3SSepherosa Ziehau } else {
5086189a0ff3SSepherosa Ziehau *eims = IXGBE_EIMS_EX(0);
5087189a0ff3SSepherosa Ziehau }
5088189a0ff3SSepherosa Ziehau *eims_val = 1 << x;
5089189a0ff3SSepherosa Ziehau } else {
5090189a0ff3SSepherosa Ziehau KASSERT(x < IX_MAX_MSIX, ("%s: invalid vector %d",
5091189a0ff3SSepherosa Ziehau device_get_nameunit(sc->dev), x));
5092189a0ff3SSepherosa Ziehau KASSERT(sc->hw.mac.type != ixgbe_mac_82598EB,
5093189a0ff3SSepherosa Ziehau ("%s: invalid vector %d for 82598",
5094189a0ff3SSepherosa Ziehau device_get_nameunit(sc->dev), x));
5095189a0ff3SSepherosa Ziehau *eims = IXGBE_EIMS_EX(1);
5096189a0ff3SSepherosa Ziehau *eims_val = 1 << (x - 32);
5097189a0ff3SSepherosa Ziehau }
5098189a0ff3SSepherosa Ziehau }
50994a648aefSSepherosa Ziehau
51004a648aefSSepherosa Ziehau #ifdef IFPOLL_ENABLE
51014a648aefSSepherosa Ziehau
51024a648aefSSepherosa Ziehau static void
ix_npoll_status(struct ifnet * ifp)51034a648aefSSepherosa Ziehau ix_npoll_status(struct ifnet *ifp)
51044a648aefSSepherosa Ziehau {
51054a648aefSSepherosa Ziehau struct ix_softc *sc = ifp->if_softc;
51064a648aefSSepherosa Ziehau uint32_t eicr;
51074a648aefSSepherosa Ziehau
51084a648aefSSepherosa Ziehau ASSERT_SERIALIZED(&sc->main_serialize);
51094a648aefSSepherosa Ziehau
51104a648aefSSepherosa Ziehau eicr = IXGBE_READ_REG(&sc->hw, IXGBE_EICR);
51114a648aefSSepherosa Ziehau ix_intr_status(sc, eicr);
51124a648aefSSepherosa Ziehau }
51134a648aefSSepherosa Ziehau
51144a648aefSSepherosa Ziehau static void
ix_npoll_tx(struct ifnet * ifp,void * arg,int cycle __unused)51154a648aefSSepherosa Ziehau ix_npoll_tx(struct ifnet *ifp, void *arg, int cycle __unused)
51164a648aefSSepherosa Ziehau {
51174a648aefSSepherosa Ziehau struct ix_tx_ring *txr = arg;
51184a648aefSSepherosa Ziehau
51194a648aefSSepherosa Ziehau ASSERT_SERIALIZED(&txr->tx_serialize);
51204a648aefSSepherosa Ziehau
512182db96e9SSepherosa Ziehau ix_tx_intr(txr, *(txr->tx_hdr));
512282db96e9SSepherosa Ziehau ix_try_txgc(txr, 1);
51234a648aefSSepherosa Ziehau }
51244a648aefSSepherosa Ziehau
51254a648aefSSepherosa Ziehau static void
ix_npoll_rx(struct ifnet * ifp __unused,void * arg,int cycle)51264a648aefSSepherosa Ziehau ix_npoll_rx(struct ifnet *ifp __unused, void *arg, int cycle)
51274a648aefSSepherosa Ziehau {
51284a648aefSSepherosa Ziehau struct ix_rx_ring *rxr = arg;
51294a648aefSSepherosa Ziehau
51304a648aefSSepherosa Ziehau ASSERT_SERIALIZED(&rxr->rx_serialize);
51318d0afa86SSepherosa Ziehau ix_rxeof(rxr, cycle);
51328d0afa86SSepherosa Ziehau }
51334a648aefSSepherosa Ziehau
51348d0afa86SSepherosa Ziehau static void
ix_npoll_rx_direct(struct ifnet * ifp __unused,void * arg,int cycle)51358d0afa86SSepherosa Ziehau ix_npoll_rx_direct(struct ifnet *ifp __unused, void *arg, int cycle)
51368d0afa86SSepherosa Ziehau {
51378d0afa86SSepherosa Ziehau struct ix_rx_ring *rxr = arg;
51388d0afa86SSepherosa Ziehau
51398d0afa86SSepherosa Ziehau ASSERT_NOT_SERIALIZED(&rxr->rx_serialize);
51404a648aefSSepherosa Ziehau ix_rxeof(rxr, cycle);
51414a648aefSSepherosa Ziehau }
51424a648aefSSepherosa Ziehau
51434a648aefSSepherosa Ziehau static void
ix_npoll(struct ifnet * ifp,struct ifpoll_info * info)51444a648aefSSepherosa Ziehau ix_npoll(struct ifnet *ifp, struct ifpoll_info *info)
51454a648aefSSepherosa Ziehau {
51464a648aefSSepherosa Ziehau struct ix_softc *sc = ifp->if_softc;
51478d0afa86SSepherosa Ziehau int i, txr_cnt, rxr_cnt, idirect;
51484a648aefSSepherosa Ziehau
51494a648aefSSepherosa Ziehau ASSERT_IFNET_SERIALIZED_ALL(ifp);
51504a648aefSSepherosa Ziehau
51518d0afa86SSepherosa Ziehau idirect = sc->direct_input;
51528d0afa86SSepherosa Ziehau cpu_ccfence();
51538d0afa86SSepherosa Ziehau
51544a648aefSSepherosa Ziehau if (info) {
51553c37d13bSSepherosa Ziehau int cpu;
51564a648aefSSepherosa Ziehau
51574a648aefSSepherosa Ziehau info->ifpi_status.status_func = ix_npoll_status;
51584a648aefSSepherosa Ziehau info->ifpi_status.serializer = &sc->main_serialize;
51594a648aefSSepherosa Ziehau
51604a648aefSSepherosa Ziehau txr_cnt = ix_get_txring_inuse(sc, TRUE);
51614a648aefSSepherosa Ziehau for (i = 0; i < txr_cnt; ++i) {
51624a648aefSSepherosa Ziehau struct ix_tx_ring *txr = &sc->tx_rings[i];
51634a648aefSSepherosa Ziehau
51643c37d13bSSepherosa Ziehau cpu = if_ringmap_cpumap(sc->tx_rmap, i);
51653c37d13bSSepherosa Ziehau KKASSERT(cpu < netisr_ncpus);
51663c37d13bSSepherosa Ziehau info->ifpi_tx[cpu].poll_func = ix_npoll_tx;
51673c37d13bSSepherosa Ziehau info->ifpi_tx[cpu].arg = txr;
51683c37d13bSSepherosa Ziehau info->ifpi_tx[cpu].serializer = &txr->tx_serialize;
51693c37d13bSSepherosa Ziehau ifsq_set_cpuid(txr->tx_ifsq, cpu);
51704a648aefSSepherosa Ziehau }
51714a648aefSSepherosa Ziehau
51724a648aefSSepherosa Ziehau rxr_cnt = ix_get_rxring_inuse(sc, TRUE);
51734a648aefSSepherosa Ziehau for (i = 0; i < rxr_cnt; ++i) {
51744a648aefSSepherosa Ziehau struct ix_rx_ring *rxr = &sc->rx_rings[i];
51754a648aefSSepherosa Ziehau
51763c37d13bSSepherosa Ziehau cpu = if_ringmap_cpumap(sc->rx_rmap, i);
51773c37d13bSSepherosa Ziehau KKASSERT(cpu < netisr_ncpus);
51783c37d13bSSepherosa Ziehau info->ifpi_rx[cpu].arg = rxr;
51798d0afa86SSepherosa Ziehau if (idirect) {
51808d0afa86SSepherosa Ziehau info->ifpi_rx[cpu].poll_func =
51818d0afa86SSepherosa Ziehau ix_npoll_rx_direct;
51828d0afa86SSepherosa Ziehau info->ifpi_rx[cpu].serializer = NULL;
51834a648aefSSepherosa Ziehau } else {
51848d0afa86SSepherosa Ziehau info->ifpi_rx[cpu].poll_func = ix_npoll_rx;
51858d0afa86SSepherosa Ziehau info->ifpi_rx[cpu].serializer =
51868d0afa86SSepherosa Ziehau &rxr->rx_serialize;
51878d0afa86SSepherosa Ziehau }
51888d0afa86SSepherosa Ziehau }
51898d0afa86SSepherosa Ziehau if (idirect)
51908d0afa86SSepherosa Ziehau ifp->if_flags |= IFF_IDIRECT;
51918d0afa86SSepherosa Ziehau } else {
51928d0afa86SSepherosa Ziehau ifp->if_flags &= ~IFF_IDIRECT;
51934a648aefSSepherosa Ziehau for (i = 0; i < sc->tx_ring_cnt; ++i) {
51944a648aefSSepherosa Ziehau struct ix_tx_ring *txr = &sc->tx_rings[i];
51954a648aefSSepherosa Ziehau
51964a648aefSSepherosa Ziehau ifsq_set_cpuid(txr->tx_ifsq, txr->tx_intr_cpuid);
51974a648aefSSepherosa Ziehau }
51983c37d13bSSepherosa Ziehau }
51993c37d13bSSepherosa Ziehau if (ifp->if_flags & IFF_RUNNING)
52004a648aefSSepherosa Ziehau ix_init(sc);
52014a648aefSSepherosa Ziehau }
52024a648aefSSepherosa Ziehau
52034a648aefSSepherosa Ziehau #endif /* IFPOLL_ENABLE */
5204060fa21cSSepherosa Ziehau
5205060fa21cSSepherosa Ziehau static enum ixgbe_fc_mode
ix_ifmedia2fc(int ifm)5206060fa21cSSepherosa Ziehau ix_ifmedia2fc(int ifm)
5207060fa21cSSepherosa Ziehau {
5208060fa21cSSepherosa Ziehau int fc_opt = ifm & (IFM_ETH_RXPAUSE | IFM_ETH_TXPAUSE);
5209060fa21cSSepherosa Ziehau
5210060fa21cSSepherosa Ziehau switch (fc_opt) {
5211060fa21cSSepherosa Ziehau case (IFM_ETH_RXPAUSE | IFM_ETH_TXPAUSE):
5212060fa21cSSepherosa Ziehau return ixgbe_fc_full;
5213060fa21cSSepherosa Ziehau
5214060fa21cSSepherosa Ziehau case IFM_ETH_RXPAUSE:
5215060fa21cSSepherosa Ziehau return ixgbe_fc_rx_pause;
5216060fa21cSSepherosa Ziehau
5217060fa21cSSepherosa Ziehau case IFM_ETH_TXPAUSE:
5218060fa21cSSepherosa Ziehau return ixgbe_fc_tx_pause;
5219060fa21cSSepherosa Ziehau
5220060fa21cSSepherosa Ziehau default:
5221060fa21cSSepherosa Ziehau return ixgbe_fc_none;
5222060fa21cSSepherosa Ziehau }
5223060fa21cSSepherosa Ziehau }
5224060fa21cSSepherosa Ziehau
5225060fa21cSSepherosa Ziehau static const char *
ix_ifmedia2str(int ifm)5226060fa21cSSepherosa Ziehau ix_ifmedia2str(int ifm)
5227060fa21cSSepherosa Ziehau {
5228060fa21cSSepherosa Ziehau int fc_opt = ifm & (IFM_ETH_RXPAUSE | IFM_ETH_TXPAUSE);
5229060fa21cSSepherosa Ziehau
5230060fa21cSSepherosa Ziehau switch (fc_opt) {
5231060fa21cSSepherosa Ziehau case (IFM_ETH_RXPAUSE | IFM_ETH_TXPAUSE):
5232060fa21cSSepherosa Ziehau return IFM_ETH_FC_FULL;
5233060fa21cSSepherosa Ziehau
5234060fa21cSSepherosa Ziehau case IFM_ETH_RXPAUSE:
5235060fa21cSSepherosa Ziehau return IFM_ETH_FC_RXPAUSE;
5236060fa21cSSepherosa Ziehau
5237060fa21cSSepherosa Ziehau case IFM_ETH_TXPAUSE:
5238060fa21cSSepherosa Ziehau return IFM_ETH_FC_TXPAUSE;
5239060fa21cSSepherosa Ziehau
5240060fa21cSSepherosa Ziehau default:
5241060fa21cSSepherosa Ziehau return IFM_ETH_FC_NONE;
5242060fa21cSSepherosa Ziehau }
5243060fa21cSSepherosa Ziehau }
5244060fa21cSSepherosa Ziehau
5245060fa21cSSepherosa Ziehau static const char *
ix_fc2str(enum ixgbe_fc_mode fc)5246060fa21cSSepherosa Ziehau ix_fc2str(enum ixgbe_fc_mode fc)
5247060fa21cSSepherosa Ziehau {
5248060fa21cSSepherosa Ziehau switch (fc) {
5249060fa21cSSepherosa Ziehau case ixgbe_fc_full:
5250060fa21cSSepherosa Ziehau return IFM_ETH_FC_FULL;
5251060fa21cSSepherosa Ziehau
5252060fa21cSSepherosa Ziehau case ixgbe_fc_rx_pause:
5253060fa21cSSepherosa Ziehau return IFM_ETH_FC_RXPAUSE;
5254060fa21cSSepherosa Ziehau
5255060fa21cSSepherosa Ziehau case ixgbe_fc_tx_pause:
5256060fa21cSSepherosa Ziehau return IFM_ETH_FC_TXPAUSE;
5257060fa21cSSepherosa Ziehau
5258060fa21cSSepherosa Ziehau default:
5259060fa21cSSepherosa Ziehau return IFM_ETH_FC_NONE;
5260060fa21cSSepherosa Ziehau }
5261060fa21cSSepherosa Ziehau }
526263d483cdSSepherosa Ziehau
526363d483cdSSepherosa Ziehau static int
ix_powerdown(struct ix_softc * sc)526463d483cdSSepherosa Ziehau ix_powerdown(struct ix_softc *sc)
526563d483cdSSepherosa Ziehau {
526663d483cdSSepherosa Ziehau struct ixgbe_hw *hw = &sc->hw;
526763d483cdSSepherosa Ziehau int error = 0;
526863d483cdSSepherosa Ziehau
52696150453fSSepherosa Ziehau /* Limit power management flow to X550EM baseT */
527063d483cdSSepherosa Ziehau if (hw->device_id == IXGBE_DEV_ID_X550EM_X_10G_T &&
527163d483cdSSepherosa Ziehau hw->phy.ops.enter_lplu) {
527263d483cdSSepherosa Ziehau /* Turn off support for APM wakeup. (Using ACPI instead) */
527363d483cdSSepherosa Ziehau IXGBE_WRITE_REG(hw, IXGBE_GRC,
527463d483cdSSepherosa Ziehau IXGBE_READ_REG(hw, IXGBE_GRC) & ~(uint32_t)2);
527563d483cdSSepherosa Ziehau
527663d483cdSSepherosa Ziehau /*
527763d483cdSSepherosa Ziehau * Clear Wake Up Status register to prevent any previous wakeup
527863d483cdSSepherosa Ziehau * events from waking us up immediately after we suspend.
527963d483cdSSepherosa Ziehau */
528063d483cdSSepherosa Ziehau IXGBE_WRITE_REG(hw, IXGBE_WUS, 0xffffffff);
528163d483cdSSepherosa Ziehau
528263d483cdSSepherosa Ziehau /*
528363d483cdSSepherosa Ziehau * Program the Wakeup Filter Control register with user filter
528463d483cdSSepherosa Ziehau * settings
528563d483cdSSepherosa Ziehau */
528663d483cdSSepherosa Ziehau IXGBE_WRITE_REG(hw, IXGBE_WUFC, sc->wufc);
528763d483cdSSepherosa Ziehau
528863d483cdSSepherosa Ziehau /* Enable wakeups and power management in Wakeup Control */
528963d483cdSSepherosa Ziehau IXGBE_WRITE_REG(hw, IXGBE_WUC,
529063d483cdSSepherosa Ziehau IXGBE_WUC_WKEN | IXGBE_WUC_PME_EN);
529163d483cdSSepherosa Ziehau
529263d483cdSSepherosa Ziehau /* X550EM baseT adapters need a special LPLU flow */
529363d483cdSSepherosa Ziehau hw->phy.reset_disable = true;
529463d483cdSSepherosa Ziehau ix_stop(sc);
529563d483cdSSepherosa Ziehau error = hw->phy.ops.enter_lplu(hw);
529663d483cdSSepherosa Ziehau if (error) {
529763d483cdSSepherosa Ziehau if_printf(&sc->arpcom.ac_if,
529863d483cdSSepherosa Ziehau "Error entering LPLU: %d\n", error);
529963d483cdSSepherosa Ziehau }
530063d483cdSSepherosa Ziehau hw->phy.reset_disable = false;
530163d483cdSSepherosa Ziehau } else {
530263d483cdSSepherosa Ziehau /* Just stop for other adapters */
530363d483cdSSepherosa Ziehau ix_stop(sc);
530463d483cdSSepherosa Ziehau }
530563d483cdSSepherosa Ziehau return error;
530663d483cdSSepherosa Ziehau }
530763d483cdSSepherosa Ziehau
530863d483cdSSepherosa Ziehau static void
ix_config_flowctrl(struct ix_softc * sc)530963d483cdSSepherosa Ziehau ix_config_flowctrl(struct ix_softc *sc)
531063d483cdSSepherosa Ziehau {
531163d483cdSSepherosa Ziehau struct ixgbe_hw *hw = &sc->hw;
531263d483cdSSepherosa Ziehau uint32_t rxpb, frame, size, tmp;
531363d483cdSSepherosa Ziehau
531463d483cdSSepherosa Ziehau frame = sc->max_frame_size;
531563d483cdSSepherosa Ziehau
531663d483cdSSepherosa Ziehau /* Calculate High Water */
531763d483cdSSepherosa Ziehau switch (hw->mac.type) {
531863d483cdSSepherosa Ziehau case ixgbe_mac_X540:
531963d483cdSSepherosa Ziehau case ixgbe_mac_X550:
532063d483cdSSepherosa Ziehau case ixgbe_mac_X550EM_a:
532163d483cdSSepherosa Ziehau case ixgbe_mac_X550EM_x:
532263d483cdSSepherosa Ziehau tmp = IXGBE_DV_X540(frame, frame);
532363d483cdSSepherosa Ziehau break;
532463d483cdSSepherosa Ziehau default:
532563d483cdSSepherosa Ziehau tmp = IXGBE_DV(frame, frame);
532663d483cdSSepherosa Ziehau break;
532763d483cdSSepherosa Ziehau }
532863d483cdSSepherosa Ziehau size = IXGBE_BT2KB(tmp);
532963d483cdSSepherosa Ziehau rxpb = IXGBE_READ_REG(hw, IXGBE_RXPBSIZE(0)) >> 10;
533063d483cdSSepherosa Ziehau hw->fc.high_water[0] = rxpb - size;
533163d483cdSSepherosa Ziehau
533263d483cdSSepherosa Ziehau /* Now calculate Low Water */
533363d483cdSSepherosa Ziehau switch (hw->mac.type) {
533463d483cdSSepherosa Ziehau case ixgbe_mac_X540:
533563d483cdSSepherosa Ziehau case ixgbe_mac_X550:
533663d483cdSSepherosa Ziehau case ixgbe_mac_X550EM_a:
533763d483cdSSepherosa Ziehau case ixgbe_mac_X550EM_x:
533863d483cdSSepherosa Ziehau tmp = IXGBE_LOW_DV_X540(frame);
533963d483cdSSepherosa Ziehau break;
534063d483cdSSepherosa Ziehau default:
534163d483cdSSepherosa Ziehau tmp = IXGBE_LOW_DV(frame);
534263d483cdSSepherosa Ziehau break;
534363d483cdSSepherosa Ziehau }
534463d483cdSSepherosa Ziehau hw->fc.low_water[0] = IXGBE_BT2KB(tmp);
534563d483cdSSepherosa Ziehau
534663d483cdSSepherosa Ziehau hw->fc.requested_mode = ix_ifmedia2fc(sc->ifm_media);
534763d483cdSSepherosa Ziehau if (sc->ifm_media & IFM_ETH_FORCEPAUSE)
534863d483cdSSepherosa Ziehau hw->fc.disable_fc_autoneg = TRUE;
534963d483cdSSepherosa Ziehau else
535063d483cdSSepherosa Ziehau hw->fc.disable_fc_autoneg = FALSE;
535163d483cdSSepherosa Ziehau hw->fc.pause_time = IX_FC_PAUSE;
535263d483cdSSepherosa Ziehau hw->fc.send_xon = TRUE;
535363d483cdSSepherosa Ziehau }
535463d483cdSSepherosa Ziehau
535563d483cdSSepherosa Ziehau static void
ix_config_dmac(struct ix_softc * sc)535663d483cdSSepherosa Ziehau ix_config_dmac(struct ix_softc *sc)
535763d483cdSSepherosa Ziehau {
535863d483cdSSepherosa Ziehau struct ixgbe_hw *hw = &sc->hw;
535963d483cdSSepherosa Ziehau struct ixgbe_dmac_config *dcfg = &hw->mac.dmac_config;
536063d483cdSSepherosa Ziehau
536163d483cdSSepherosa Ziehau if (hw->mac.type < ixgbe_mac_X550 || !hw->mac.ops.dmac_config)
536263d483cdSSepherosa Ziehau return;
536363d483cdSSepherosa Ziehau
536463d483cdSSepherosa Ziehau if ((dcfg->watchdog_timer ^ sc->dmac) ||
536563d483cdSSepherosa Ziehau (dcfg->link_speed ^ sc->link_speed)) {
536663d483cdSSepherosa Ziehau dcfg->watchdog_timer = sc->dmac;
536763d483cdSSepherosa Ziehau dcfg->fcoe_en = false;
536863d483cdSSepherosa Ziehau dcfg->link_speed = sc->link_speed;
536963d483cdSSepherosa Ziehau dcfg->num_tcs = 1;
537063d483cdSSepherosa Ziehau
537163d483cdSSepherosa Ziehau if (bootverbose) {
537263d483cdSSepherosa Ziehau if_printf(&sc->arpcom.ac_if, "dmac settings: "
537363d483cdSSepherosa Ziehau "watchdog %d, link speed %d\n",
537463d483cdSSepherosa Ziehau dcfg->watchdog_timer, dcfg->link_speed);
537563d483cdSSepherosa Ziehau }
537663d483cdSSepherosa Ziehau
537763d483cdSSepherosa Ziehau hw->mac.ops.dmac_config(hw);
537863d483cdSSepherosa Ziehau }
537963d483cdSSepherosa Ziehau }
538063d483cdSSepherosa Ziehau
538163d483cdSSepherosa Ziehau static void
ix_init_media(struct ix_softc * sc)538263d483cdSSepherosa Ziehau ix_init_media(struct ix_softc *sc)
538363d483cdSSepherosa Ziehau {
538463d483cdSSepherosa Ziehau struct ixgbe_hw *hw = &sc->hw;
53856150453fSSepherosa Ziehau uint32_t layer;
538663d483cdSSepherosa Ziehau
538763d483cdSSepherosa Ziehau ifmedia_removeall(&sc->media);
538863d483cdSSepherosa Ziehau
53896150453fSSepherosa Ziehau layer = sc->phy_layer;
539063d483cdSSepherosa Ziehau
539163d483cdSSepherosa Ziehau /*
539263d483cdSSepherosa Ziehau * Media types with matching DragonFlyBSD media defines
539363d483cdSSepherosa Ziehau */
539463d483cdSSepherosa Ziehau if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_T) {
539563d483cdSSepherosa Ziehau ifmedia_add_nodup(&sc->media, IFM_ETHER | IFM_10G_T | IFM_FDX,
539663d483cdSSepherosa Ziehau 0, NULL);
539763d483cdSSepherosa Ziehau }
539863d483cdSSepherosa Ziehau if (layer & IXGBE_PHYSICAL_LAYER_1000BASE_T) {
539963d483cdSSepherosa Ziehau ifmedia_add_nodup(&sc->media, IFM_ETHER | IFM_1000_T | IFM_FDX,
540063d483cdSSepherosa Ziehau 0, NULL);
540163d483cdSSepherosa Ziehau }
540263d483cdSSepherosa Ziehau if (layer & IXGBE_PHYSICAL_LAYER_100BASE_TX) {
540363d483cdSSepherosa Ziehau ifmedia_add_nodup(&sc->media, IFM_ETHER | IFM_100_TX | IFM_FDX,
540463d483cdSSepherosa Ziehau 0, NULL);
540563d483cdSSepherosa Ziehau /* No half-duplex support */
540663d483cdSSepherosa Ziehau }
54076150453fSSepherosa Ziehau if (layer & IXGBE_PHYSICAL_LAYER_10BASE_T) {
54086150453fSSepherosa Ziehau ifmedia_add_nodup(&sc->media, IFM_ETHER | IFM_10_T | IFM_FDX,
540963d483cdSSepherosa Ziehau 0, NULL);
54106150453fSSepherosa Ziehau /* No half-duplex support */
541163d483cdSSepherosa Ziehau }
541263d483cdSSepherosa Ziehau
541363d483cdSSepherosa Ziehau if ((layer & IXGBE_PHYSICAL_LAYER_SFP_PLUS_CU) ||
541463d483cdSSepherosa Ziehau (layer & IXGBE_PHYSICAL_LAYER_SFP_ACTIVE_DA)) {
541563d483cdSSepherosa Ziehau ifmedia_add_nodup(&sc->media,
541663d483cdSSepherosa Ziehau IFM_ETHER | IFM_10G_TWINAX | IFM_FDX, 0, NULL);
541763d483cdSSepherosa Ziehau }
54186150453fSSepherosa Ziehau
54196150453fSSepherosa Ziehau if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_LR) {
54206150453fSSepherosa Ziehau ifmedia_add_nodup(&sc->media, IFM_ETHER | IFM_10G_LR | IFM_FDX,
54216150453fSSepherosa Ziehau 0, NULL);
54226150453fSSepherosa Ziehau if (hw->phy.multispeed_fiber) {
54236150453fSSepherosa Ziehau ifmedia_add_nodup(&sc->media,
54246150453fSSepherosa Ziehau IFM_ETHER | IFM_1000_LX | IFM_FDX, 0, NULL);
54256150453fSSepherosa Ziehau }
54266150453fSSepherosa Ziehau }
54276150453fSSepherosa Ziehau if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_LRM) {
54286150453fSSepherosa Ziehau ifmedia_add_nodup(&sc->media, IFM_ETHER | IFM_10G_LRM | IFM_FDX,
54296150453fSSepherosa Ziehau 0, NULL);
54306150453fSSepherosa Ziehau if (hw->phy.multispeed_fiber) {
54316150453fSSepherosa Ziehau ifmedia_add_nodup(&sc->media,
54326150453fSSepherosa Ziehau IFM_ETHER | IFM_1000_LX | IFM_FDX, 0, NULL);
54336150453fSSepherosa Ziehau }
54346150453fSSepherosa Ziehau }
54356150453fSSepherosa Ziehau
54366150453fSSepherosa Ziehau if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_SR) {
54376150453fSSepherosa Ziehau ifmedia_add_nodup(&sc->media, IFM_ETHER | IFM_10G_SR | IFM_FDX,
54386150453fSSepherosa Ziehau 0, NULL);
54396150453fSSepherosa Ziehau if (hw->phy.multispeed_fiber) {
54406150453fSSepherosa Ziehau ifmedia_add_nodup(&sc->media,
54416150453fSSepherosa Ziehau IFM_ETHER | IFM_1000_SX | IFM_FDX, 0, NULL);
54426150453fSSepherosa Ziehau }
54436150453fSSepherosa Ziehau } else if (layer & IXGBE_PHYSICAL_LAYER_1000BASE_SX) {
54446150453fSSepherosa Ziehau ifmedia_add_nodup(&sc->media, IFM_ETHER | IFM_1000_SX | IFM_FDX,
544563d483cdSSepherosa Ziehau 0, NULL);
544663d483cdSSepherosa Ziehau }
54476150453fSSepherosa Ziehau
54486150453fSSepherosa Ziehau if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_CX4) {
54496150453fSSepherosa Ziehau ifmedia_add_nodup(&sc->media, IFM_ETHER | IFM_10G_CX4 | IFM_FDX,
545063d483cdSSepherosa Ziehau 0, NULL);
545163d483cdSSepherosa Ziehau }
545263d483cdSSepherosa Ziehau
545363d483cdSSepherosa Ziehau /*
545463d483cdSSepherosa Ziehau * XXX Other (no matching DragonFlyBSD media type):
545563d483cdSSepherosa Ziehau * To workaround this, we'll assign these completely
545663d483cdSSepherosa Ziehau * inappropriate media types.
545763d483cdSSepherosa Ziehau */
545863d483cdSSepherosa Ziehau if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_KR) {
545963d483cdSSepherosa Ziehau if_printf(&sc->arpcom.ac_if, "Media supported: 10GbaseKR\n");
546063d483cdSSepherosa Ziehau if_printf(&sc->arpcom.ac_if, "10GbaseKR mapped to 10GbaseSR\n");
546163d483cdSSepherosa Ziehau ifmedia_add_nodup(&sc->media, IFM_ETHER | IFM_10G_SR | IFM_FDX,
546263d483cdSSepherosa Ziehau 0, NULL);
546363d483cdSSepherosa Ziehau }
546463d483cdSSepherosa Ziehau if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_KX4) {
546563d483cdSSepherosa Ziehau if_printf(&sc->arpcom.ac_if, "Media supported: 10GbaseKX4\n");
546663d483cdSSepherosa Ziehau if_printf(&sc->arpcom.ac_if,
546763d483cdSSepherosa Ziehau "10GbaseKX4 mapped to 10GbaseCX4\n");
546863d483cdSSepherosa Ziehau ifmedia_add_nodup(&sc->media, IFM_ETHER | IFM_10G_CX4 | IFM_FDX,
546963d483cdSSepherosa Ziehau 0, NULL);
547063d483cdSSepherosa Ziehau }
547163d483cdSSepherosa Ziehau if (layer & IXGBE_PHYSICAL_LAYER_1000BASE_KX) {
547263d483cdSSepherosa Ziehau if_printf(&sc->arpcom.ac_if, "Media supported: 1000baseKX\n");
547363d483cdSSepherosa Ziehau if_printf(&sc->arpcom.ac_if,
547463d483cdSSepherosa Ziehau "1000baseKX mapped to 1000baseCX\n");
547563d483cdSSepherosa Ziehau ifmedia_add_nodup(&sc->media, IFM_ETHER | IFM_1000_CX | IFM_FDX,
547663d483cdSSepherosa Ziehau 0, NULL);
547763d483cdSSepherosa Ziehau }
54786150453fSSepherosa Ziehau if (layer & IXGBE_PHYSICAL_LAYER_2500BASE_KX) {
54796150453fSSepherosa Ziehau if_printf(&sc->arpcom.ac_if, "Media supported: 2500baseKX\n");
54806150453fSSepherosa Ziehau if_printf(&sc->arpcom.ac_if,
54816150453fSSepherosa Ziehau "2500baseKX mapped to 2500baseSX\n");
54826150453fSSepherosa Ziehau ifmedia_add_nodup(&sc->media, IFM_ETHER | IFM_2500_SX | IFM_FDX,
54836150453fSSepherosa Ziehau 0, NULL);
54846150453fSSepherosa Ziehau }
548563d483cdSSepherosa Ziehau if (layer & IXGBE_PHYSICAL_LAYER_1000BASE_BX) {
548663d483cdSSepherosa Ziehau if_printf(&sc->arpcom.ac_if,
548763d483cdSSepherosa Ziehau "Media supported: 1000baseBX, ignored\n");
548863d483cdSSepherosa Ziehau }
548963d483cdSSepherosa Ziehau
549063d483cdSSepherosa Ziehau /* XXX we probably don't need this */
549163d483cdSSepherosa Ziehau if (hw->device_id == IXGBE_DEV_ID_82598AT) {
549263d483cdSSepherosa Ziehau ifmedia_add_nodup(&sc->media,
549363d483cdSSepherosa Ziehau IFM_ETHER | IFM_1000_T | IFM_FDX, 0, NULL);
549463d483cdSSepherosa Ziehau }
549563d483cdSSepherosa Ziehau
549663d483cdSSepherosa Ziehau ifmedia_add_nodup(&sc->media, IFM_ETHER | IFM_AUTO, 0, NULL);
549763d483cdSSepherosa Ziehau
549863d483cdSSepherosa Ziehau if (ifmedia_tryset(&sc->media, sc->ifm_media)) {
549963d483cdSSepherosa Ziehau int flowctrl = (sc->ifm_media & IFM_ETH_FCMASK);
550063d483cdSSepherosa Ziehau
550163d483cdSSepherosa Ziehau sc->advspeed = IXGBE_LINK_SPEED_UNKNOWN;
550263d483cdSSepherosa Ziehau sc->ifm_media = IX_IFM_DEFAULT | flowctrl;
550363d483cdSSepherosa Ziehau ifmedia_set(&sc->media, sc->ifm_media);
550463d483cdSSepherosa Ziehau }
550563d483cdSSepherosa Ziehau }
55066150453fSSepherosa Ziehau
55076150453fSSepherosa Ziehau static void
ix_setup_caps(struct ix_softc * sc)55086150453fSSepherosa Ziehau ix_setup_caps(struct ix_softc *sc)
55096150453fSSepherosa Ziehau {
55106150453fSSepherosa Ziehau
55116150453fSSepherosa Ziehau sc->caps |= IX_CAP_LEGACY_INTR;
55126150453fSSepherosa Ziehau
55136150453fSSepherosa Ziehau switch (sc->hw.mac.type) {
55146150453fSSepherosa Ziehau case ixgbe_mac_82598EB:
55156150453fSSepherosa Ziehau if (sc->hw.device_id == IXGBE_DEV_ID_82598AT)
55166150453fSSepherosa Ziehau sc->caps |= IX_CAP_DETECT_FANFAIL;
55176150453fSSepherosa Ziehau break;
55186150453fSSepherosa Ziehau
55196150453fSSepherosa Ziehau case ixgbe_mac_X550:
5520dd5ce676SSepherosa Ziehau sc->caps |= IX_CAP_TEMP_SENSOR | IX_CAP_FW_RECOVERY;
55216150453fSSepherosa Ziehau break;
55226150453fSSepherosa Ziehau
55236150453fSSepherosa Ziehau case ixgbe_mac_X550EM_x:
55246150453fSSepherosa Ziehau if (sc->hw.device_id == IXGBE_DEV_ID_X550EM_X_KR)
55256150453fSSepherosa Ziehau sc->caps |= IX_CAP_EEE;
5526dd5ce676SSepherosa Ziehau sc->caps |= IX_CAP_FW_RECOVERY;
55276150453fSSepherosa Ziehau break;
55286150453fSSepherosa Ziehau
55296150453fSSepherosa Ziehau case ixgbe_mac_X550EM_a:
55306150453fSSepherosa Ziehau sc->caps &= ~IX_CAP_LEGACY_INTR;
55316150453fSSepherosa Ziehau if (sc->hw.device_id == IXGBE_DEV_ID_X550EM_A_1G_T ||
55326150453fSSepherosa Ziehau sc->hw.device_id == IXGBE_DEV_ID_X550EM_A_1G_T_L)
55336150453fSSepherosa Ziehau sc->caps |= IX_CAP_TEMP_SENSOR | IX_CAP_EEE;
5534dd5ce676SSepherosa Ziehau sc->caps |= IX_CAP_FW_RECOVERY;
55356150453fSSepherosa Ziehau break;
55366150453fSSepherosa Ziehau
55376150453fSSepherosa Ziehau case ixgbe_mac_82599EB:
55386150453fSSepherosa Ziehau if (sc->hw.device_id == IXGBE_DEV_ID_82599_QSFP_SF_QP)
55396150453fSSepherosa Ziehau sc->caps &= ~IX_CAP_LEGACY_INTR;
55406150453fSSepherosa Ziehau break;
55416150453fSSepherosa Ziehau
55426150453fSSepherosa Ziehau default:
55436150453fSSepherosa Ziehau break;
55446150453fSSepherosa Ziehau }
55456150453fSSepherosa Ziehau }
55466150453fSSepherosa Ziehau
55476150453fSSepherosa Ziehau static void
ix_detect_fanfail(struct ix_softc * sc,uint32_t reg,boolean_t intr)55486150453fSSepherosa Ziehau ix_detect_fanfail(struct ix_softc *sc, uint32_t reg, boolean_t intr)
55496150453fSSepherosa Ziehau {
55506150453fSSepherosa Ziehau uint32_t mask;
55516150453fSSepherosa Ziehau
55526150453fSSepherosa Ziehau mask = intr ? IXGBE_EICR_GPI_SDP1_BY_MAC(&sc->hw) : IXGBE_ESDP_SDP1;
55536150453fSSepherosa Ziehau if (reg & mask) {
55546150453fSSepherosa Ziehau if_printf(&sc->arpcom.ac_if,
55556150453fSSepherosa Ziehau "CRITICAL: FAN FAILURE!! REPLACE IMMEDIATELY!!\n");
55566150453fSSepherosa Ziehau }
55576150453fSSepherosa Ziehau }
55586150453fSSepherosa Ziehau
55596150453fSSepherosa Ziehau static void
ix_config_gpie(struct ix_softc * sc)55606150453fSSepherosa Ziehau ix_config_gpie(struct ix_softc *sc)
55616150453fSSepherosa Ziehau {
55626150453fSSepherosa Ziehau struct ixgbe_hw *hw = &sc->hw;
55636150453fSSepherosa Ziehau uint32_t gpie;
55646150453fSSepherosa Ziehau
55656150453fSSepherosa Ziehau gpie = IXGBE_READ_REG(hw, IXGBE_GPIE);
55666150453fSSepherosa Ziehau
55676150453fSSepherosa Ziehau if (sc->intr_type == PCI_INTR_TYPE_MSIX) {
55686150453fSSepherosa Ziehau /* Enable Enhanced MSI-X mode */
55696150453fSSepherosa Ziehau gpie |= IXGBE_GPIE_MSIX_MODE |
55706150453fSSepherosa Ziehau IXGBE_GPIE_EIAME |
55716150453fSSepherosa Ziehau IXGBE_GPIE_PBA_SUPPORT |
55726150453fSSepherosa Ziehau IXGBE_GPIE_OCD;
55736150453fSSepherosa Ziehau }
55746150453fSSepherosa Ziehau
55756150453fSSepherosa Ziehau /* Fan Failure Interrupt */
55766150453fSSepherosa Ziehau if (sc->caps & IX_CAP_DETECT_FANFAIL)
55776150453fSSepherosa Ziehau gpie |= IXGBE_SDP1_GPIEN;
55786150453fSSepherosa Ziehau
55796150453fSSepherosa Ziehau /* Thermal Sensor Interrupt */
55806150453fSSepherosa Ziehau if (sc->caps & IX_CAP_TEMP_SENSOR)
55816150453fSSepherosa Ziehau gpie |= IXGBE_SDP0_GPIEN_X540;
55826150453fSSepherosa Ziehau
55836150453fSSepherosa Ziehau /* Link detection */
55846150453fSSepherosa Ziehau switch (hw->mac.type) {
55856150453fSSepherosa Ziehau case ixgbe_mac_82599EB:
55866150453fSSepherosa Ziehau gpie |= IXGBE_SDP1_GPIEN | IXGBE_SDP2_GPIEN;
55876150453fSSepherosa Ziehau break;
55886150453fSSepherosa Ziehau
55896150453fSSepherosa Ziehau case ixgbe_mac_X550EM_x:
55906150453fSSepherosa Ziehau case ixgbe_mac_X550EM_a:
55916150453fSSepherosa Ziehau gpie |= IXGBE_SDP0_GPIEN_X540;
55926150453fSSepherosa Ziehau break;
55936150453fSSepherosa Ziehau
55946150453fSSepherosa Ziehau default:
55956150453fSSepherosa Ziehau break;
55966150453fSSepherosa Ziehau }
55976150453fSSepherosa Ziehau
55986150453fSSepherosa Ziehau IXGBE_WRITE_REG(hw, IXGBE_GPIE, gpie);
55996150453fSSepherosa Ziehau }
5600dd5ce676SSepherosa Ziehau
5601dd5ce676SSepherosa Ziehau static void
ix_fw_timer(void * xsc)5602dd5ce676SSepherosa Ziehau ix_fw_timer(void *xsc)
5603dd5ce676SSepherosa Ziehau {
5604dd5ce676SSepherosa Ziehau struct ix_softc *sc = xsc;
5605dd5ce676SSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if;
5606dd5ce676SSepherosa Ziehau
5607dd5ce676SSepherosa Ziehau lwkt_serialize_enter(&sc->main_serialize);
5608dd5ce676SSepherosa Ziehau
5609dd5ce676SSepherosa Ziehau if (ixgbe_fw_recovery_mode(&sc->hw)) {
5610dd5ce676SSepherosa Ziehau if ((sc->flags & IX_FLAG_FW_RECOVERY) == 0) {
5611dd5ce676SSepherosa Ziehau sc->flags |= IX_FLAG_FW_RECOVERY;
5612dd5ce676SSepherosa Ziehau if (ifp->if_flags & IFF_RUNNING) {
5613dd5ce676SSepherosa Ziehau if_printf(ifp,
5614dd5ce676SSepherosa Ziehau "fw recovery mode entered, stop\n");
5615dd5ce676SSepherosa Ziehau ix_serialize_skipmain(sc);
5616dd5ce676SSepherosa Ziehau ix_stop(sc);
5617dd5ce676SSepherosa Ziehau ix_deserialize_skipmain(sc);
5618dd5ce676SSepherosa Ziehau } else {
5619dd5ce676SSepherosa Ziehau if_printf(ifp, "fw recovery mode entered\n");
5620dd5ce676SSepherosa Ziehau }
5621dd5ce676SSepherosa Ziehau }
5622dd5ce676SSepherosa Ziehau } else {
5623dd5ce676SSepherosa Ziehau if (sc->flags & IX_FLAG_FW_RECOVERY) {
5624dd5ce676SSepherosa Ziehau sc->flags &= ~IX_FLAG_FW_RECOVERY;
5625dd5ce676SSepherosa Ziehau if (ifp->if_flags & IFF_UP) {
5626dd5ce676SSepherosa Ziehau if_printf(ifp,
5627dd5ce676SSepherosa Ziehau "fw recovery mode exited, reinit\n");
5628dd5ce676SSepherosa Ziehau ix_serialize_skipmain(sc);
5629dd5ce676SSepherosa Ziehau ix_init(sc);
5630dd5ce676SSepherosa Ziehau ix_deserialize_skipmain(sc);
5631dd5ce676SSepherosa Ziehau } else {
5632dd5ce676SSepherosa Ziehau if_printf(ifp, "fw recovery mode exited\n");
5633dd5ce676SSepherosa Ziehau }
5634dd5ce676SSepherosa Ziehau }
5635dd5ce676SSepherosa Ziehau }
5636dd5ce676SSepherosa Ziehau
5637dd5ce676SSepherosa Ziehau callout_reset_bycpu(&sc->fw_timer, hz, ix_fw_timer, sc,
5638dd5ce676SSepherosa Ziehau ix_get_timer_cpuid(sc,
5639dd5ce676SSepherosa Ziehau (ifp->if_flags & IFF_NPOLLING) ? TRUE : FALSE));
5640dd5ce676SSepherosa Ziehau
5641dd5ce676SSepherosa Ziehau lwkt_serialize_exit(&sc->main_serialize);
5642dd5ce676SSepherosa Ziehau }
5643