diff options
Diffstat (limited to 'sys/dev/igc')
-rw-r--r-- | sys/dev/igc/if_igc.c | 1857 | ||||
-rw-r--r-- | sys/dev/igc/if_igc.h | 118 | ||||
-rw-r--r-- | sys/dev/igc/igc_api.c | 2 | ||||
-rw-r--r-- | sys/dev/igc/igc_defines.h | 29 | ||||
-rw-r--r-- | sys/dev/igc/igc_nvm.c | 81 | ||||
-rw-r--r-- | sys/dev/igc/igc_nvm.h | 18 | ||||
-rw-r--r-- | sys/dev/igc/igc_regs.h | 7 | ||||
-rw-r--r-- | sys/dev/igc/igc_txrx.c | 113 |
8 files changed, 1356 insertions, 869 deletions
diff --git a/sys/dev/igc/if_igc.c b/sys/dev/igc/if_igc.c index bfa33c82f7ba..a1ae35c7aa43 100644 --- a/sys/dev/igc/if_igc.c +++ b/sys/dev/igc/if_igc.c @@ -1,9 +1,9 @@ /*- * SPDX-License-Identifier: BSD-2-Clause * + * Copyright (c) 2001-2024, Intel Corporation * Copyright (c) 2016 Nicole Graziano <nicole@nextbsd.org> - * All rights reserved. - * Copyright (c) 2021 Rubicon Communications, LLC (Netgate) + * Copyright (c) 2021-2024 Rubicon Communications, LLC (Netgate) * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -49,22 +49,38 @@ static const pci_vendor_info_t igc_vendor_info_array[] = { /* Intel(R) PRO/1000 Network Connection - igc */ - PVID(0x8086, IGC_DEV_ID_I225_LM, "Intel(R) Ethernet Controller I225-LM"), - PVID(0x8086, IGC_DEV_ID_I225_V, "Intel(R) Ethernet Controller I225-V"), - PVID(0x8086, IGC_DEV_ID_I225_K, "Intel(R) Ethernet Controller I225-K"), - PVID(0x8086, IGC_DEV_ID_I225_I, "Intel(R) Ethernet Controller I225-I"), - PVID(0x8086, IGC_DEV_ID_I220_V, "Intel(R) Ethernet Controller I220-V"), - PVID(0x8086, IGC_DEV_ID_I225_K2, "Intel(R) Ethernet Controller I225-K(2)"), - PVID(0x8086, IGC_DEV_ID_I225_LMVP, "Intel(R) Ethernet Controller I225-LMvP(2)"), - PVID(0x8086, IGC_DEV_ID_I226_K, "Intel(R) Ethernet Controller I226-K"), - PVID(0x8086, IGC_DEV_ID_I226_LMVP, "Intel(R) Ethernet Controller I226-LMvP"), - PVID(0x8086, IGC_DEV_ID_I225_IT, "Intel(R) Ethernet Controller I225-IT(2)"), - PVID(0x8086, IGC_DEV_ID_I226_LM, "Intel(R) Ethernet Controller I226-LM"), - PVID(0x8086, IGC_DEV_ID_I226_V, "Intel(R) Ethernet Controller I226-V"), - PVID(0x8086, IGC_DEV_ID_I226_IT, "Intel(R) Ethernet Controller I226-IT"), - PVID(0x8086, IGC_DEV_ID_I221_V, "Intel(R) Ethernet Controller I221-V"), - PVID(0x8086, IGC_DEV_ID_I226_BLANK_NVM, "Intel(R) Ethernet Controller I226(blankNVM)"), - PVID(0x8086, IGC_DEV_ID_I225_BLANK_NVM, "Intel(R) Ethernet Controller I225(blankNVM)"), + PVID(0x8086, IGC_DEV_ID_I225_LM, + "Intel(R) Ethernet Controller I225-LM"), + PVID(0x8086, IGC_DEV_ID_I225_V, + "Intel(R) Ethernet Controller I225-V"), + PVID(0x8086, IGC_DEV_ID_I225_K, + "Intel(R) Ethernet Controller I225-K"), + PVID(0x8086, IGC_DEV_ID_I225_I, + "Intel(R) Ethernet Controller I225-IT"), + PVID(0x8086, IGC_DEV_ID_I220_V, + "Intel(R) Ethernet Controller I220-V"), + PVID(0x8086, IGC_DEV_ID_I225_K2, + "Intel(R) Ethernet Controller I225-K(2)"), + PVID(0x8086, IGC_DEV_ID_I225_LMVP, + "Intel(R) Ethernet Controller I225-LMvP(2)"), + PVID(0x8086, IGC_DEV_ID_I226_K, + "Intel(R) Ethernet Controller I226-K"), + PVID(0x8086, IGC_DEV_ID_I226_LMVP, + "Intel(R) Ethernet Controller I226-LMvP"), + PVID(0x8086, IGC_DEV_ID_I225_IT, + "Intel(R) Ethernet Controller I225-IT(2)"), + PVID(0x8086, IGC_DEV_ID_I226_LM, + "Intel(R) Ethernet Controller I226-LM"), + PVID(0x8086, IGC_DEV_ID_I226_V, + "Intel(R) Ethernet Controller I226-V"), + PVID(0x8086, IGC_DEV_ID_I226_IT, + "Intel(R) Ethernet Controller I226-IT"), + PVID(0x8086, IGC_DEV_ID_I221_V, + "Intel(R) Ethernet Controller I221-V"), + PVID(0x8086, IGC_DEV_ID_I226_BLANK_NVM, + "Intel(R) Ethernet Controller I226(blankNVM)"), + PVID(0x8086, IGC_DEV_ID_I225_BLANK_NVM, + "Intel(R) Ethernet Controller I225(blankNVM)"), /* required last entry */ PVID_END }; @@ -72,65 +88,71 @@ static const pci_vendor_info_t igc_vendor_info_array[] = /********************************************************************* * Function prototypes *********************************************************************/ -static void *igc_register(device_t dev); -static int igc_if_attach_pre(if_ctx_t ctx); -static int igc_if_attach_post(if_ctx_t ctx); -static int igc_if_detach(if_ctx_t ctx); -static int igc_if_shutdown(if_ctx_t ctx); -static int igc_if_suspend(if_ctx_t ctx); -static int igc_if_resume(if_ctx_t ctx); - -static int igc_if_tx_queues_alloc(if_ctx_t ctx, caddr_t *vaddrs, uint64_t *paddrs, int ntxqs, int ntxqsets); -static int igc_if_rx_queues_alloc(if_ctx_t ctx, caddr_t *vaddrs, uint64_t *paddrs, int nrxqs, int nrxqsets); -static void igc_if_queues_free(if_ctx_t ctx); +static void *igc_register(device_t); +static int igc_if_attach_pre(if_ctx_t); +static int igc_if_attach_post(if_ctx_t); +static int igc_if_detach(if_ctx_t); +static int igc_if_shutdown(if_ctx_t); +static int igc_if_suspend(if_ctx_t); +static int igc_if_resume(if_ctx_t); + +static int igc_if_tx_queues_alloc(if_ctx_t, caddr_t *, uint64_t *, int, + int); +static int igc_if_rx_queues_alloc(if_ctx_t, caddr_t *, uint64_t *, int, + int); +static void igc_if_queues_free(if_ctx_t); static uint64_t igc_if_get_counter(if_ctx_t, ift_counter); -static void igc_if_init(if_ctx_t ctx); -static void igc_if_stop(if_ctx_t ctx); +static void igc_if_init(if_ctx_t); +static void igc_if_stop(if_ctx_t); static void igc_if_media_status(if_ctx_t, struct ifmediareq *); -static int igc_if_media_change(if_ctx_t ctx); -static int igc_if_mtu_set(if_ctx_t ctx, uint32_t mtu); -static void igc_if_timer(if_ctx_t ctx, uint16_t qid); -static void igc_if_watchdog_reset(if_ctx_t ctx); -static bool igc_if_needs_restart(if_ctx_t ctx, enum iflib_restart_event event); - -static void igc_identify_hardware(if_ctx_t ctx); -static int igc_allocate_pci_resources(if_ctx_t ctx); -static void igc_free_pci_resources(if_ctx_t ctx); -static void igc_reset(if_ctx_t ctx); -static int igc_setup_interface(if_ctx_t ctx); -static int igc_setup_msix(if_ctx_t ctx); - -static void igc_initialize_transmit_unit(if_ctx_t ctx); -static void igc_initialize_receive_unit(if_ctx_t ctx); - -static void igc_if_intr_enable(if_ctx_t ctx); -static void igc_if_intr_disable(if_ctx_t ctx); -static int igc_if_rx_queue_intr_enable(if_ctx_t ctx, uint16_t rxqid); -static int igc_if_tx_queue_intr_enable(if_ctx_t ctx, uint16_t txqid); -static void igc_if_multi_set(if_ctx_t ctx); -static void igc_if_update_admin_status(if_ctx_t ctx); -static void igc_if_debug(if_ctx_t ctx); -static void igc_update_stats_counters(struct igc_adapter *); -static void igc_add_hw_stats(struct igc_adapter *adapter); -static int igc_if_set_promisc(if_ctx_t ctx, int flags); -static void igc_setup_vlan_hw_support(if_ctx_t ctx); +static int igc_if_media_change(if_ctx_t); +static int igc_if_mtu_set(if_ctx_t, uint32_t); +static void igc_if_timer(if_ctx_t, uint16_t); +static void igc_if_watchdog_reset(if_ctx_t); +static bool igc_if_needs_restart(if_ctx_t, enum iflib_restart_event); + +static void igc_identify_hardware(if_ctx_t); +static int igc_allocate_pci_resources(if_ctx_t); +static void igc_free_pci_resources(if_ctx_t); +static void igc_reset(if_ctx_t); +static int igc_setup_interface(if_ctx_t); +static int igc_setup_msix(if_ctx_t); + +static void igc_initialize_transmit_unit(if_ctx_t); +static void igc_initialize_receive_unit(if_ctx_t); + +static void igc_if_intr_enable(if_ctx_t); +static void igc_if_intr_disable(if_ctx_t); +static int igc_if_rx_queue_intr_enable(if_ctx_t, uint16_t); +static int igc_if_tx_queue_intr_enable(if_ctx_t, uint16_t); +static void igc_if_multi_set(if_ctx_t); +static void igc_if_update_admin_status(if_ctx_t); +static void igc_if_debug(if_ctx_t); +static void igc_update_stats_counters(struct igc_softc *); +static void igc_add_hw_stats(struct igc_softc *); +static int igc_if_set_promisc(if_ctx_t, int); +static void igc_setup_vlan_hw_support(if_ctx_t); +static void igc_fw_version(struct igc_softc *); +static void igc_sbuf_fw_version(struct igc_fw_version *, struct sbuf *); +static void igc_print_fw_version(struct igc_softc *); +static int igc_sysctl_print_fw_version(SYSCTL_HANDLER_ARGS); static int igc_sysctl_nvm_info(SYSCTL_HANDLER_ARGS); -static void igc_print_nvm_info(struct igc_adapter *); +static void igc_print_nvm_info(struct igc_softc *); static int igc_sysctl_debug_info(SYSCTL_HANDLER_ARGS); static int igc_get_rs(SYSCTL_HANDLER_ARGS); -static void igc_print_debug_info(struct igc_adapter *); +static void igc_print_debug_info(struct igc_softc *); static int igc_is_valid_ether_addr(u8 *); -static int igc_sysctl_int_delay(SYSCTL_HANDLER_ARGS); -static void igc_add_int_delay_sysctl(struct igc_adapter *, const char *, - const char *, struct igc_int_delay_info *, int, int); +static void igc_neweitr(struct igc_softc *, struct igc_rx_queue *, + struct tx_ring *, struct rx_ring *); +static int igc_sysctl_tso_tcp_flags_mask(SYSCTL_HANDLER_ARGS); /* Management and WOL Support */ -static void igc_get_hw_control(struct igc_adapter *); -static void igc_release_hw_control(struct igc_adapter *); -static void igc_get_wakeup(if_ctx_t ctx); -static void igc_enable_wakeup(if_ctx_t ctx); +static void igc_get_hw_control(struct igc_softc *); +static void igc_release_hw_control(struct igc_softc *); +static void igc_get_wakeup(if_ctx_t); +static void igc_enable_wakeup(if_ctx_t); -int igc_intr(void *arg); +int igc_intr(void *); /* MSI-X handlers */ static int igc_if_msix_intr_assign(if_ctx_t, int); @@ -138,11 +160,12 @@ static int igc_msix_link(void *); static void igc_handle_link(void *context); static int igc_set_flowcntl(SYSCTL_HANDLER_ARGS); +static int igc_sysctl_dmac(SYSCTL_HANDLER_ARGS); static int igc_sysctl_eee(SYSCTL_HANDLER_ARGS); static int igc_get_regs(SYSCTL_HANDLER_ARGS); -static void igc_configure_queues(struct igc_adapter *adapter); +static void igc_configure_queues(struct igc_softc *); /********************************************************************* @@ -161,7 +184,7 @@ static device_method_t igc_methods[] = { }; static driver_t igc_driver = { - "igc", igc_methods, sizeof(struct igc_adapter), + "igc", igc_methods, sizeof(struct igc_softc), }; DRIVER_MODULE(igc, pci, igc_driver, 0, 0); @@ -204,19 +227,13 @@ static device_method_t igc_if_methods[] = { }; static driver_t igc_if_driver = { - "igc_if", igc_if_methods, sizeof(struct igc_adapter) + "igc_if", igc_if_methods, sizeof(struct igc_softc) }; /********************************************************************* * Tunable default values. *********************************************************************/ -#define IGC_TICKS_TO_USECS(ticks) ((1024 * (ticks) + 500) / 1000) -#define IGC_USECS_TO_TICKS(usecs) ((1000 * (usecs) + 512) / 1024) - -#define MAX_INTS_PER_SEC 8000 -#define DEFAULT_ITR (1000000000/(MAX_INTS_PER_SEC * 256)) - /* Allow common code without TSO */ #ifndef CSUM_TSO #define CSUM_TSO 0 @@ -229,28 +246,13 @@ static int igc_disable_crc_stripping = 0; SYSCTL_INT(_hw_igc, OID_AUTO, disable_crc_stripping, CTLFLAG_RDTUN, &igc_disable_crc_stripping, 0, "Disable CRC Stripping"); -static int igc_tx_int_delay_dflt = IGC_TICKS_TO_USECS(IGC_TIDV_VAL); -static int igc_rx_int_delay_dflt = IGC_TICKS_TO_USECS(IGC_RDTR_VAL); -SYSCTL_INT(_hw_igc, OID_AUTO, tx_int_delay, CTLFLAG_RDTUN, &igc_tx_int_delay_dflt, - 0, "Default transmit interrupt delay in usecs"); -SYSCTL_INT(_hw_igc, OID_AUTO, rx_int_delay, CTLFLAG_RDTUN, &igc_rx_int_delay_dflt, - 0, "Default receive interrupt delay in usecs"); - -static int igc_tx_abs_int_delay_dflt = IGC_TICKS_TO_USECS(IGC_TADV_VAL); -static int igc_rx_abs_int_delay_dflt = IGC_TICKS_TO_USECS(IGC_RADV_VAL); -SYSCTL_INT(_hw_igc, OID_AUTO, tx_abs_int_delay, CTLFLAG_RDTUN, - &igc_tx_abs_int_delay_dflt, 0, - "Default transmit interrupt delay limit in usecs"); -SYSCTL_INT(_hw_igc, OID_AUTO, rx_abs_int_delay, CTLFLAG_RDTUN, - &igc_rx_abs_int_delay_dflt, 0, - "Default receive interrupt delay limit in usecs"); - static int igc_smart_pwr_down = false; -SYSCTL_INT(_hw_igc, OID_AUTO, smart_pwr_down, CTLFLAG_RDTUN, &igc_smart_pwr_down, +SYSCTL_INT(_hw_igc, OID_AUTO, smart_pwr_down, CTLFLAG_RDTUN, + &igc_smart_pwr_down, 0, "Set to true to leave smart power down enabled on newer adapters"); /* Controls whether promiscuous also shows bad packets */ -static int igc_debug_sbp = true; +static int igc_debug_sbp = false; SYSCTL_INT(_hw_igc, OID_AUTO, sbp, CTLFLAG_RDTUN, &igc_debug_sbp, 0, "Show bad packets in promiscuous mode"); @@ -260,9 +262,18 @@ SYSCTL_INT(_hw_igc, OID_AUTO, eee_setting, CTLFLAG_RDTUN, &igc_eee_setting, 0, "Enable Energy Efficient Ethernet"); /* + * AIM: Adaptive Interrupt Moderation + * which means that the interrupt rate is varied over time based on the + * traffic for that interrupt vector + */ +static int igc_enable_aim = 1; +SYSCTL_INT(_hw_igc, OID_AUTO, enable_aim, CTLFLAG_RWTUN, &igc_enable_aim, + 0, "Enable adaptive interrupt moderation (1=normal, 2=lowlatency)"); + +/* ** Tuneable Interrupt rate */ -static int igc_max_interrupt_rate = 20000; +static int igc_max_interrupt_rate = IGC_INTS_DEFAULT; SYSCTL_INT(_hw_igc, OID_AUTO, max_interrupt_rate, CTLFLAG_RDTUN, &igc_max_interrupt_rate, 0, "Maximum interrupts per second"); @@ -285,7 +296,8 @@ static struct if_shared_ctx igc_sctx_init = { .isc_vendor_info = igc_vendor_info_array, .isc_driver_version = "1", .isc_driver = &igc_if_driver, - .isc_flags = IFLIB_NEED_SCRATCH | IFLIB_TSO_INIT_IP | IFLIB_NEED_ZERO_CSUM, + .isc_flags = + IFLIB_NEED_SCRATCH | IFLIB_TSO_INIT_IP | IFLIB_NEED_ZERO_CSUM, .isc_nrxd_min = {IGC_MIN_RXD}, .isc_ntxd_min = {IGC_MIN_TXD}, @@ -304,8 +316,8 @@ static struct if_shared_ctx igc_sctx_init = { static int igc_get_regs(SYSCTL_HANDLER_ARGS) { - struct igc_adapter *adapter = (struct igc_adapter *)arg1; - struct igc_hw *hw = &adapter->hw; + struct igc_softc *sc = (struct igc_softc *)arg1; + struct igc_hw *hw = &sc->hw; struct sbuf *sb; u32 *regs_buff; int rc; @@ -381,7 +393,7 @@ static int igc_get_regs(SYSCTL_HANDLER_ARGS) #ifdef DUMP_DESCS { - if_softc_ctx_t scctx = adapter->shared; + if_softc_ctx_t scctx = sc->shared; struct rx_ring *rxr = &rx_que->rxr; struct tx_ring *txr = &tx_que->txr; int ntxd = scctx->isc_ntxd[0]; @@ -391,15 +403,20 @@ static int igc_get_regs(SYSCTL_HANDLER_ARGS) for (j = 0; j < nrxd; j++) { u32 staterr = le32toh(rxr->rx_base[j].wb.upper.status_error); u32 length = le32toh(rxr->rx_base[j].wb.upper.length); - sbuf_printf(sb, "\tReceive Descriptor Address %d: %08" PRIx64 " Error:%d Length:%d\n", j, rxr->rx_base[j].read.buffer_addr, staterr, length); + sbuf_printf(sb, "\tReceive Descriptor Address %d: %08" + PRIx64 " Error:%d Length:%d\n", + j, rxr->rx_base[j].read.buffer_addr, staterr, length); } for (j = 0; j < min(ntxd, 256); j++) { unsigned int *ptr = (unsigned int *)&txr->tx_base[j]; - sbuf_printf(sb, "\tTXD[%03d] [0]: %08x [1]: %08x [2]: %08x [3]: %08x eop: %d DD=%d\n", - j, ptr[0], ptr[1], ptr[2], ptr[3], buf->eop, - buf->eop != -1 ? txr->tx_base[buf->eop].upper.fields.status & IGC_TXD_STAT_DD : 0); + sbuf_printf(sb, "\tTXD[%03d] [0]: %08x [1]: %08x [2]: %08x" + "[3]: %08x eop: %d DD=%d\n", + j, ptr[0], ptr[1], ptr[2], ptr[3], buf->eop, + buf->eop != -1 ? + txr->tx_base[buf->eop].upper.fields.status & + IGC_TXD_STAT_DD : 0); } } @@ -443,7 +460,7 @@ igc_set_num_queues(if_ctx_t ctx) static int igc_if_attach_pre(if_ctx_t ctx) { - struct igc_adapter *adapter; + struct igc_softc *sc; if_softc_ctx_t scctx; device_t dev; struct igc_hw *hw; @@ -451,53 +468,96 @@ igc_if_attach_pre(if_ctx_t ctx) INIT_DEBUGOUT("igc_if_attach_pre: begin"); dev = iflib_get_dev(ctx); - adapter = iflib_get_softc(ctx); + sc = iflib_get_softc(ctx); - adapter->ctx = adapter->osdep.ctx = ctx; - adapter->dev = adapter->osdep.dev = dev; - scctx = adapter->shared = iflib_get_softc_ctx(ctx); - adapter->media = iflib_get_media(ctx); - hw = &adapter->hw; + sc->ctx = sc->osdep.ctx = ctx; + sc->dev = sc->osdep.dev = dev; + scctx = sc->shared = iflib_get_softc_ctx(ctx); + sc->media = iflib_get_media(ctx); + hw = &sc->hw; /* SYSCTL stuff */ SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev), SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO, "nvm", CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NEEDGIANT, - adapter, 0, igc_sysctl_nvm_info, "I", "NVM Information"); + sc, 0, igc_sysctl_nvm_info, "I", "NVM Information"); + + sc->enable_aim = igc_enable_aim; + SYSCTL_ADD_INT(device_get_sysctl_ctx(dev), + SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), + OID_AUTO, "enable_aim", CTLFLAG_RW, + &sc->enable_aim, 0, + "Interrupt Moderation (1=normal, 2=lowlatency)"); + + SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev), + SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), + OID_AUTO, "fw_version", CTLTYPE_STRING | CTLFLAG_RD, + sc, 0, igc_sysctl_print_fw_version, "A", + "Prints FW/NVM Versions"); SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev), SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO, "debug", CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NEEDGIANT, - adapter, 0, igc_sysctl_debug_info, "I", "Debug Information"); + sc, 0, igc_sysctl_debug_info, "I", "Debug Information"); SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev), SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO, "fc", CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NEEDGIANT, - adapter, 0, igc_set_flowcntl, "I", "Flow Control"); + sc, 0, igc_set_flowcntl, "I", "Flow Control"); SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev), SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO, "reg_dump", - CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_NEEDGIANT, adapter, 0, + CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_NEEDGIANT, sc, 0, igc_get_regs, "A", "Dump Registers"); SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev), SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO, "rs_dump", - CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NEEDGIANT, adapter, 0, + CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NEEDGIANT, sc, 0, igc_get_rs, "I", "Dump RS indexes"); + SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev), + SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), + OID_AUTO, "dmac", + CTLTYPE_INT | CTLFLAG_RW, sc, 0, + igc_sysctl_dmac, "I", "DMA Coalesce"); + + SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev), + SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), + OID_AUTO, "tso_tcp_flags_mask_first_segment", + CTLTYPE_UINT | CTLFLAG_RW | CTLFLAG_NEEDGIANT, + sc, 0, igc_sysctl_tso_tcp_flags_mask, "IU", + "TSO TCP flags mask for first segment"); + + SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev), + SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), + OID_AUTO, "tso_tcp_flags_mask_middle_segment", + CTLTYPE_UINT | CTLFLAG_RW | CTLFLAG_NEEDGIANT, + sc, 1, igc_sysctl_tso_tcp_flags_mask, "IU", + "TSO TCP flags mask for middle segment"); + + SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev), + SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), + OID_AUTO, "tso_tcp_flags_mask_last_segment", + CTLTYPE_UINT | CTLFLAG_RW | CTLFLAG_NEEDGIANT, + sc, 2, igc_sysctl_tso_tcp_flags_mask, "IU", + "TSO TCP flags mask for last segment"); + /* Determine hardware and mac info */ igc_identify_hardware(ctx); scctx->isc_tx_nsegments = IGC_MAX_SCATTER; - scctx->isc_nrxqsets_max = scctx->isc_ntxqsets_max = igc_set_num_queues(ctx); + scctx->isc_nrxqsets_max = + scctx->isc_ntxqsets_max = igc_set_num_queues(ctx); if (bootverbose) device_printf(dev, "attach_pre capping queues at %d\n", scctx->isc_ntxqsets_max); - scctx->isc_txqsizes[0] = roundup2(scctx->isc_ntxd[0] * sizeof(union igc_adv_tx_desc), IGC_DBA_ALIGN); - scctx->isc_rxqsizes[0] = roundup2(scctx->isc_nrxd[0] * sizeof(union igc_adv_rx_desc), IGC_DBA_ALIGN); + scctx->isc_txqsizes[0] = roundup2(scctx->isc_ntxd[0] * + sizeof(union igc_adv_tx_desc), IGC_DBA_ALIGN); + scctx->isc_rxqsizes[0] = roundup2(scctx->isc_nrxd[0] * + sizeof(union igc_adv_rx_desc), IGC_DBA_ALIGN); scctx->isc_txd_size[0] = sizeof(union igc_adv_tx_desc); scctx->isc_rxd_size[0] = sizeof(union igc_adv_rx_desc); scctx->isc_txrx = &igc_txrx; @@ -536,29 +596,6 @@ igc_if_attach_pre(if_ctx_t ctx) igc_setup_msix(ctx); igc_get_bus_info(hw); - /* Set up some sysctls for the tunable interrupt delays */ - igc_add_int_delay_sysctl(adapter, "rx_int_delay", - "receive interrupt delay in usecs", &adapter->rx_int_delay, - IGC_REGISTER(hw, IGC_RDTR), igc_rx_int_delay_dflt); - igc_add_int_delay_sysctl(adapter, "tx_int_delay", - "transmit interrupt delay in usecs", &adapter->tx_int_delay, - IGC_REGISTER(hw, IGC_TIDV), igc_tx_int_delay_dflt); - igc_add_int_delay_sysctl(adapter, "rx_abs_int_delay", - "receive interrupt delay limit in usecs", - &adapter->rx_abs_int_delay, - IGC_REGISTER(hw, IGC_RADV), - igc_rx_abs_int_delay_dflt); - igc_add_int_delay_sysctl(adapter, "tx_abs_int_delay", - "transmit interrupt delay limit in usecs", - &adapter->tx_abs_int_delay, - IGC_REGISTER(hw, IGC_TADV), - igc_tx_abs_int_delay_dflt); - igc_add_int_delay_sysctl(adapter, "itr", - "interrupt delay limit in usecs/4", - &adapter->tx_itr, - IGC_REGISTER(hw, IGC_ITR), - DEFAULT_ITR); - hw->mac.autoneg = DO_AUTO_NEG; hw->phy.autoneg_wait_to_complete = false; hw->phy.autoneg_advertised = AUTONEG_ADV_DEFAULT; @@ -572,14 +609,15 @@ igc_if_attach_pre(if_ctx_t ctx) * Set the frame limits assuming * standard ethernet sized frames. */ - scctx->isc_max_frame_size = adapter->hw.mac.max_frame_size = + scctx->isc_max_frame_size = sc->hw.mac.max_frame_size = ETHERMTU + ETHER_HDR_LEN + ETHERNET_FCS_SIZE; /* Allocate multicast array memory. */ - adapter->mta = malloc(sizeof(u8) * ETHER_ADDR_LEN * + sc->mta = malloc(sizeof(u8) * ETHER_ADDR_LEN * MAX_NUM_MULTICAST_ADDRESSES, M_DEVBUF, M_NOWAIT); - if (adapter->mta == NULL) { - device_printf(dev, "Can not allocate multicast setup array\n"); + if (sc->mta == NULL) { + device_printf(dev, + "Can not allocate multicast setup array\n"); error = ENOMEM; goto err_late; } @@ -590,12 +628,12 @@ igc_if_attach_pre(if_ctx_t ctx) " due to SOL/IDER session.\n"); /* Sysctl for setting Energy Efficient Ethernet */ - adapter->hw.dev_spec._i225.eee_disable = igc_eee_setting; + sc->hw.dev_spec._i225.eee_disable = igc_eee_setting; SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev), SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO, "eee_control", CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NEEDGIANT, - adapter, 0, igc_sysctl_eee, "I", + sc, 0, igc_sysctl_eee, "I", "Disable Energy Efficient Ethernet"); /* @@ -623,7 +661,7 @@ igc_if_attach_pre(if_ctx_t ctx) /* Copy the permanent MAC address out of the EEPROM */ if (igc_read_mac_addr(hw) < 0) { device_printf(dev, "EEPROM read error while reading MAC" - " address\n"); + " address\n"); error = EIO; goto err_late; } @@ -634,6 +672,11 @@ igc_if_attach_pre(if_ctx_t ctx) goto err_late; } + /* Save the EEPROM/NVM versions */ + igc_fw_version(sc); + + igc_print_fw_version(sc); + /* * Get Wake-on-Lan and Management info for later use */ @@ -641,7 +684,7 @@ igc_if_attach_pre(if_ctx_t ctx) /* Enable only WOL MAGIC by default */ scctx->isc_capenable &= ~IFCAP_WOL; - if (adapter->wol != 0) + if (sc->wol != 0) scctx->isc_capenable |= IFCAP_WOL_MAGIC; iflib_set_mac(ctx, hw->mac.addr); @@ -649,10 +692,10 @@ igc_if_attach_pre(if_ctx_t ctx) return (0); err_late: - igc_release_hw_control(adapter); + igc_release_hw_control(sc); err_pci: igc_free_pci_resources(ctx); - free(adapter->mta, M_DEVBUF); + free(sc->mta, M_DEVBUF); return (error); } @@ -660,8 +703,8 @@ err_pci: static int igc_if_attach_post(if_ctx_t ctx) { - struct igc_adapter *adapter = iflib_get_softc(ctx); - struct igc_hw *hw = &adapter->hw; + struct igc_softc *sc = iflib_get_softc(ctx); + struct igc_hw *hw = &sc->hw; int error = 0; /* Setup OS specific network interface */ @@ -673,23 +716,23 @@ igc_if_attach_post(if_ctx_t ctx) igc_reset(ctx); /* Initialize statistics */ - igc_update_stats_counters(adapter); + igc_update_stats_counters(sc); hw->mac.get_link_status = true; igc_if_update_admin_status(ctx); - igc_add_hw_stats(adapter); + igc_add_hw_stats(sc); /* the driver can now take control from firmware */ - igc_get_hw_control(adapter); + igc_get_hw_control(sc); INIT_DEBUGOUT("igc_if_attach_post: end"); return (error); err_late: - igc_release_hw_control(adapter); + igc_release_hw_control(sc); igc_free_pci_resources(ctx); igc_if_queues_free(ctx); - free(adapter->mta, M_DEVBUF); + free(sc->mta, M_DEVBUF); return (error); } @@ -706,13 +749,13 @@ err_late: static int igc_if_detach(if_ctx_t ctx) { - struct igc_adapter *adapter = iflib_get_softc(ctx); + struct igc_softc *sc = iflib_get_softc(ctx); INIT_DEBUGOUT("igc_if_detach: begin"); - igc_phy_hw_reset(&adapter->hw); + igc_phy_hw_reset(&sc->hw); - igc_release_hw_control(adapter); + igc_release_hw_control(sc); igc_free_pci_resources(ctx); return (0); @@ -736,9 +779,9 @@ igc_if_shutdown(if_ctx_t ctx) static int igc_if_suspend(if_ctx_t ctx) { - struct igc_adapter *adapter = iflib_get_softc(ctx); + struct igc_softc *sc = iflib_get_softc(ctx); - igc_release_hw_control(adapter); + igc_release_hw_control(sc); igc_enable_wakeup(ctx); return (0); } @@ -755,10 +798,10 @@ static int igc_if_mtu_set(if_ctx_t ctx, uint32_t mtu) { int max_frame_size; - struct igc_adapter *adapter = iflib_get_softc(ctx); + struct igc_softc *sc = iflib_get_softc(ctx); if_softc_ctx_t scctx = iflib_get_softc_ctx(ctx); - IOCTL_DEBUGOUT("ioctl rcv'd: SIOCSIFMTU (Set Interface MTU)"); + IOCTL_DEBUGOUT("ioctl rcv'd: SIOCSIFMTU (Set Interface MTU)"); /* 9K Jumbo Frame size */ max_frame_size = 9234; @@ -767,7 +810,7 @@ igc_if_mtu_set(if_ctx_t ctx, uint32_t mtu) return (EINVAL); } - scctx->isc_max_frame_size = adapter->hw.mac.max_frame_size = + scctx->isc_max_frame_size = sc->hw.mac.max_frame_size = mtu + ETHER_HDR_LEN + ETHER_CRC_LEN; return (0); } @@ -784,8 +827,8 @@ igc_if_mtu_set(if_ctx_t ctx, uint32_t mtu) static void igc_if_init(if_ctx_t ctx) { - struct igc_adapter *adapter = iflib_get_softc(ctx); - if_softc_ctx_t scctx = adapter->shared; + struct igc_softc *sc = iflib_get_softc(ctx); + if_softc_ctx_t scctx = sc->shared; if_t ifp = iflib_get_ifp(ctx); struct igc_tx_queue *tx_que; int i; @@ -793,17 +836,18 @@ igc_if_init(if_ctx_t ctx) INIT_DEBUGOUT("igc_if_init: begin"); /* Get the latest mac address, User can use a LAA */ - bcopy(if_getlladdr(ifp), adapter->hw.mac.addr, + bcopy(if_getlladdr(ifp), sc->hw.mac.addr, ETHER_ADDR_LEN); /* Put the address into the Receive Address Array */ - igc_rar_set(&adapter->hw, adapter->hw.mac.addr, 0); + igc_rar_set(&sc->hw, sc->hw.mac.addr, 0); /* Initialize the hardware */ igc_reset(ctx); igc_if_update_admin_status(ctx); - for (i = 0, tx_que = adapter->tx_queues; i < adapter->tx_num_queues; i++, tx_que++) { + for (i = 0, tx_que = sc->tx_queues; i < sc->tx_num_queues; + i++, tx_que++) { struct tx_ring *txr = &tx_que->txr; txr->tx_rs_cidx = txr->tx_rs_pidx; @@ -817,7 +861,7 @@ igc_if_init(if_ctx_t ctx) } /* Setup VLAN support, basic and offload if available */ - IGC_WRITE_REG(&adapter->hw, IGC_VET, ETHERTYPE_VLAN); + IGC_WRITE_REG(&sc->hw, IGC_VET, ETHERTYPE_VLAN); /* Prepare transmit descriptors and buffers */ igc_initialize_transmit_unit(ctx); @@ -825,7 +869,7 @@ igc_if_init(if_ctx_t ctx) /* Setup Multicast table */ igc_if_multi_set(ctx); - adapter->rx_mbuf_sz = iflib_get_rx_mbuf_sz(ctx); + sc->rx_mbuf_sz = iflib_get_rx_mbuf_sz(ctx); igc_initialize_receive_unit(ctx); /* Set up VLAN support */ @@ -833,20 +877,164 @@ igc_if_init(if_ctx_t ctx) /* Don't lose promiscuous settings */ igc_if_set_promisc(ctx, if_getflags(ifp)); - igc_clear_hw_cntrs_base_generic(&adapter->hw); + igc_clear_hw_cntrs_base_generic(&sc->hw); - if (adapter->intr_type == IFLIB_INTR_MSIX) /* Set up queue routing */ - igc_configure_queues(adapter); + if (sc->intr_type == IFLIB_INTR_MSIX) /* Set up queue routing */ + igc_configure_queues(sc); /* this clears any pending interrupts */ - IGC_READ_REG(&adapter->hw, IGC_ICR); - IGC_WRITE_REG(&adapter->hw, IGC_ICS, IGC_ICS_LSC); + IGC_READ_REG(&sc->hw, IGC_ICR); + IGC_WRITE_REG(&sc->hw, IGC_ICS, IGC_ICS_LSC); /* the driver can now take control from firmware */ - igc_get_hw_control(adapter); + igc_get_hw_control(sc); /* Set Energy Efficient Ethernet */ - igc_set_eee_i225(&adapter->hw, true, true, true); + igc_set_eee_i225(&sc->hw, true, true, true); +} + +enum eitr_latency_target { + eitr_latency_disabled = 0, + eitr_latency_lowest = 1, + eitr_latency_low = 2, + eitr_latency_bulk = 3 +}; +/********************************************************************* + * + * Helper to calculate next EITR value for AIM + * + *********************************************************************/ +static void +igc_neweitr(struct igc_softc *sc, struct igc_rx_queue *que, + struct tx_ring *txr, struct rx_ring *rxr) +{ + struct igc_hw *hw = &sc->hw; + unsigned long bytes, bytes_per_packet, packets; + unsigned long rxbytes, rxpackets, txbytes, txpackets; + u32 neweitr; + u8 nextlatency; + + rxbytes = atomic_load_long(&rxr->rx_bytes); + txbytes = atomic_load_long(&txr->tx_bytes); + + /* Idle, do nothing */ + if (txbytes == 0 && rxbytes == 0) + return; + + neweitr = 0; + + if (sc->enable_aim) { + nextlatency = rxr->rx_nextlatency; + + /* Use half default (4K) ITR if sub-gig */ + if (sc->link_speed < 1000) { + neweitr = IGC_INTS_4K; + goto igc_set_next_eitr; + } + /* Want at least enough packet buffer for two frames to AIM */ + if (sc->shared->isc_max_frame_size * 2 > (sc->pba << 10)) { + neweitr = igc_max_interrupt_rate; + sc->enable_aim = 0; + goto igc_set_next_eitr; + } + + bytes = bytes_per_packet = 0; + /* Get largest values from the associated tx and rx ring */ + txpackets = atomic_load_long(&txr->tx_packets); + if (txpackets != 0) { + bytes = txbytes; + bytes_per_packet = txbytes / txpackets; + packets = txpackets; + } + rxpackets = atomic_load_long(&rxr->rx_packets); + if (rxpackets != 0) { + bytes = lmax(bytes, rxbytes); + bytes_per_packet = + lmax(bytes_per_packet, rxbytes / rxpackets); + packets = lmax(packets, rxpackets); + } + + /* Latency state machine */ + switch (nextlatency) { + case eitr_latency_disabled: /* Bootstrapping */ + nextlatency = eitr_latency_low; + break; + case eitr_latency_lowest: /* 70k ints/s */ + /* TSO and jumbo frames */ + if (bytes_per_packet > 8000) + nextlatency = eitr_latency_bulk; + else if ((packets < 5) && (bytes > 512)) + nextlatency = eitr_latency_low; + break; + case eitr_latency_low: /* 20k ints/s */ + if (bytes > 10000) { + /* Handle TSO */ + if (bytes_per_packet > 8000) + nextlatency = eitr_latency_bulk; + else if ((packets < 10) || + (bytes_per_packet > 1200)) + nextlatency = eitr_latency_bulk; + else if (packets > 35) + nextlatency = eitr_latency_lowest; + } else if (bytes_per_packet > 2000) { + nextlatency = eitr_latency_bulk; + } else if (packets < 3 && bytes < 512) { + nextlatency = eitr_latency_lowest; + } + break; + case eitr_latency_bulk: /* 4k ints/s */ + if (bytes > 25000) { + if (packets > 35) + nextlatency = eitr_latency_low; + } else if (bytes < 1500) + nextlatency = eitr_latency_low; + break; + default: + nextlatency = eitr_latency_low; + device_printf(sc->dev, + "Unexpected neweitr transition %d\n", + nextlatency); + break; + } + + /* Trim itr_latency_lowest for default AIM setting */ + if (sc->enable_aim == 1 && nextlatency == eitr_latency_lowest) + nextlatency = eitr_latency_low; + + /* Request new latency */ + rxr->rx_nextlatency = nextlatency; + } else { + /* We may have toggled to AIM disabled */ + nextlatency = eitr_latency_disabled; + rxr->rx_nextlatency = nextlatency; + } + + /* ITR state machine */ + switch(nextlatency) { + case eitr_latency_lowest: + neweitr = IGC_INTS_70K; + break; + case eitr_latency_low: + neweitr = IGC_INTS_20K; + break; + case eitr_latency_bulk: + neweitr = IGC_INTS_4K; + break; + case eitr_latency_disabled: + default: + neweitr = igc_max_interrupt_rate; + break; + } + +igc_set_next_eitr: + neweitr = IGC_INTS_TO_EITR(neweitr); + + neweitr |= IGC_EITR_CNT_IGNR; + + if (neweitr != que->eitr_setting) { + que->eitr_setting = neweitr; + IGC_WRITE_REG(hw, IGC_EITR(que->msix), que->eitr_setting); + } } /********************************************************************* @@ -857,11 +1045,15 @@ igc_if_init(if_ctx_t ctx) int igc_intr(void *arg) { - struct igc_adapter *adapter = arg; - if_ctx_t ctx = adapter->ctx; + struct igc_softc *sc = arg; + struct igc_hw *hw = &sc->hw; + struct igc_rx_queue *que = &sc->rx_queues[0]; + struct tx_ring *txr = &sc->tx_queues[0].txr; + struct rx_ring *rxr = &que->rxr; + if_ctx_t ctx = sc->ctx; u32 reg_icr; - reg_icr = IGC_READ_REG(&adapter->hw, IGC_ICR); + reg_icr = IGC_READ_REG(hw, IGC_ICR); /* Hot eject? */ if (reg_icr == 0xffffffff) @@ -887,7 +1079,15 @@ igc_intr(void *arg) igc_handle_link(ctx); if (reg_icr & IGC_ICR_RXO) - adapter->rx_overruns++; + sc->rx_overruns++; + + igc_neweitr(sc, que, txr, rxr); + + /* Reset state */ + txr->tx_bytes = 0; + txr->tx_packets = 0; + rxr->rx_bytes = 0; + rxr->rx_packets = 0; return (FILTER_SCHEDULE_THREAD); } @@ -895,20 +1095,20 @@ igc_intr(void *arg) static int igc_if_rx_queue_intr_enable(if_ctx_t ctx, uint16_t rxqid) { - struct igc_adapter *adapter = iflib_get_softc(ctx); - struct igc_rx_queue *rxq = &adapter->rx_queues[rxqid]; + struct igc_softc *sc = iflib_get_softc(ctx); + struct igc_rx_queue *rxq = &sc->rx_queues[rxqid]; - IGC_WRITE_REG(&adapter->hw, IGC_EIMS, rxq->eims); + IGC_WRITE_REG(&sc->hw, IGC_EIMS, rxq->eims); return (0); } static int igc_if_tx_queue_intr_enable(if_ctx_t ctx, uint16_t txqid) { - struct igc_adapter *adapter = iflib_get_softc(ctx); - struct igc_tx_queue *txq = &adapter->tx_queues[txqid]; + struct igc_softc *sc = iflib_get_softc(ctx); + struct igc_tx_queue *txq = &sc->tx_queues[txqid]; - IGC_WRITE_REG(&adapter->hw, IGC_EIMS, txq->eims); + IGC_WRITE_REG(&sc->hw, IGC_EIMS, txq->eims); return (0); } @@ -921,9 +1121,20 @@ static int igc_msix_que(void *arg) { struct igc_rx_queue *que = arg; + struct igc_softc *sc = que->sc; + struct tx_ring *txr = &sc->tx_queues[que->msix].txr; + struct rx_ring *rxr = &que->rxr; ++que->irqs; + igc_neweitr(sc, que, txr, rxr); + + /* Reset state */ + txr->tx_bytes = 0; + txr->tx_packets = 0; + rxr->rx_bytes = 0; + rxr->rx_packets = 0; + return (FILTER_SCHEDULE_THREAD); } @@ -935,22 +1146,22 @@ igc_msix_que(void *arg) static int igc_msix_link(void *arg) { - struct igc_adapter *adapter = arg; + struct igc_softc *sc = arg; u32 reg_icr; - ++adapter->link_irq; - MPASS(adapter->hw.back != NULL); - reg_icr = IGC_READ_REG(&adapter->hw, IGC_ICR); + ++sc->link_irq; + MPASS(sc->hw.back != NULL); + reg_icr = IGC_READ_REG(&sc->hw, IGC_ICR); if (reg_icr & IGC_ICR_RXO) - adapter->rx_overruns++; + sc->rx_overruns++; if (reg_icr & (IGC_ICR_RXSEQ | IGC_ICR_LSC)) { - igc_handle_link(adapter->ctx); + igc_handle_link(sc->ctx); } - IGC_WRITE_REG(&adapter->hw, IGC_IMS, IGC_IMS_LSC); - IGC_WRITE_REG(&adapter->hw, IGC_EIMS, adapter->link_mask); + IGC_WRITE_REG(&sc->hw, IGC_IMS, IGC_IMS_LSC); + IGC_WRITE_REG(&sc->hw, IGC_EIMS, sc->link_mask); return (FILTER_HANDLED); } @@ -959,9 +1170,9 @@ static void igc_handle_link(void *context) { if_ctx_t ctx = context; - struct igc_adapter *adapter = iflib_get_softc(ctx); + struct igc_softc *sc = iflib_get_softc(ctx); - adapter->hw.mac.get_link_status = true; + sc->hw.mac.get_link_status = true; iflib_admin_intr_deferred(ctx); } @@ -976,7 +1187,7 @@ igc_handle_link(void *context) static void igc_if_media_status(if_ctx_t ctx, struct ifmediareq *ifmr) { - struct igc_adapter *adapter = iflib_get_softc(ctx); + struct igc_softc *sc = iflib_get_softc(ctx); INIT_DEBUGOUT("igc_if_media_status: begin"); @@ -985,28 +1196,28 @@ igc_if_media_status(if_ctx_t ctx, struct ifmediareq *ifmr) ifmr->ifm_status = IFM_AVALID; ifmr->ifm_active = IFM_ETHER; - if (!adapter->link_active) { + if (!sc->link_active) { return; } ifmr->ifm_status |= IFM_ACTIVE; - switch (adapter->link_speed) { + switch (sc->link_speed) { case 10: ifmr->ifm_active |= IFM_10_T; break; case 100: ifmr->ifm_active |= IFM_100_TX; - break; + break; case 1000: ifmr->ifm_active |= IFM_1000_T; break; case 2500: - ifmr->ifm_active |= IFM_2500_T; - break; + ifmr->ifm_active |= IFM_2500_T; + break; } - if (adapter->link_duplex == FULL_DUPLEX) + if (sc->link_duplex == FULL_DUPLEX) ifmr->ifm_active |= IFM_FDX; else ifmr->ifm_active |= IFM_HDX; @@ -1023,7 +1234,7 @@ igc_if_media_status(if_ctx_t ctx, struct ifmediareq *ifmr) static int igc_if_media_change(if_ctx_t ctx) { - struct igc_adapter *adapter = iflib_get_softc(ctx); + struct igc_softc *sc = iflib_get_softc(ctx); struct ifmedia *ifm = iflib_get_media(ctx); INIT_DEBUGOUT("igc_if_media_change: begin"); @@ -1031,32 +1242,32 @@ igc_if_media_change(if_ctx_t ctx) if (IFM_TYPE(ifm->ifm_media) != IFM_ETHER) return (EINVAL); - adapter->hw.mac.autoneg = DO_AUTO_NEG; + sc->hw.mac.autoneg = DO_AUTO_NEG; switch (IFM_SUBTYPE(ifm->ifm_media)) { case IFM_AUTO: - adapter->hw.phy.autoneg_advertised = AUTONEG_ADV_DEFAULT; + sc->hw.phy.autoneg_advertised = AUTONEG_ADV_DEFAULT; + break; + case IFM_2500_T: + sc->hw.phy.autoneg_advertised = ADVERTISE_2500_FULL; break; - case IFM_2500_T: - adapter->hw.phy.autoneg_advertised = ADVERTISE_2500_FULL; - break; case IFM_1000_T: - adapter->hw.phy.autoneg_advertised = ADVERTISE_1000_FULL; + sc->hw.phy.autoneg_advertised = ADVERTISE_1000_FULL; break; case IFM_100_TX: if ((ifm->ifm_media & IFM_GMASK) == IFM_FDX) - adapter->hw.phy.autoneg_advertised = ADVERTISE_100_FULL; + sc->hw.phy.autoneg_advertised = ADVERTISE_100_FULL; else - adapter->hw.phy.autoneg_advertised = ADVERTISE_100_HALF; + sc->hw.phy.autoneg_advertised = ADVERTISE_100_HALF; break; case IFM_10_T: if ((ifm->ifm_media & IFM_GMASK) == IFM_FDX) - adapter->hw.phy.autoneg_advertised = ADVERTISE_10_FULL; + sc->hw.phy.autoneg_advertised = ADVERTISE_10_FULL; else - adapter->hw.phy.autoneg_advertised = ADVERTISE_10_HALF; + sc->hw.phy.autoneg_advertised = ADVERTISE_10_HALF; break; default: - device_printf(adapter->dev, "Unsupported media type\n"); + device_printf(sc->dev, "Unsupported media type\n"); } igc_if_init(ctx); @@ -1067,12 +1278,12 @@ igc_if_media_change(if_ctx_t ctx) static int igc_if_set_promisc(if_ctx_t ctx, int flags) { - struct igc_adapter *adapter = iflib_get_softc(ctx); + struct igc_softc *sc = iflib_get_softc(ctx); if_t ifp = iflib_get_ifp(ctx); u32 reg_rctl; int mcnt = 0; - reg_rctl = IGC_READ_REG(&adapter->hw, IGC_RCTL); + reg_rctl = IGC_READ_REG(&sc->hw, IGC_RCTL); reg_rctl &= ~(IGC_RCTL_SBP | IGC_RCTL_UPE); if (flags & IFF_ALLMULTI) mcnt = MAX_NUM_MULTICAST_ADDRESSES; @@ -1082,18 +1293,18 @@ igc_if_set_promisc(if_ctx_t ctx, int flags) /* Don't disable if in MAX groups */ if (mcnt < MAX_NUM_MULTICAST_ADDRESSES) reg_rctl &= (~IGC_RCTL_MPE); - IGC_WRITE_REG(&adapter->hw, IGC_RCTL, reg_rctl); + IGC_WRITE_REG(&sc->hw, IGC_RCTL, reg_rctl); if (flags & IFF_PROMISC) { reg_rctl |= (IGC_RCTL_UPE | IGC_RCTL_MPE); /* Turn this on if you want to see bad packets */ if (igc_debug_sbp) reg_rctl |= IGC_RCTL_SBP; - IGC_WRITE_REG(&adapter->hw, IGC_RCTL, reg_rctl); + IGC_WRITE_REG(&sc->hw, IGC_RCTL, reg_rctl); } else if (flags & IFF_ALLMULTI) { reg_rctl |= IGC_RCTL_MPE; reg_rctl &= ~IGC_RCTL_UPE; - IGC_WRITE_REG(&adapter->hw, IGC_RCTL, reg_rctl); + IGC_WRITE_REG(&sc->hw, IGC_RCTL, reg_rctl); } return (0); } @@ -1121,20 +1332,20 @@ igc_copy_maddr(void *arg, struct sockaddr_dl *sdl, u_int idx) static void igc_if_multi_set(if_ctx_t ctx) { - struct igc_adapter *adapter = iflib_get_softc(ctx); + struct igc_softc *sc = iflib_get_softc(ctx); if_t ifp = iflib_get_ifp(ctx); - u8 *mta; /* Multicast array memory */ + u8 *mta; /* Multicast array memory */ u32 reg_rctl = 0; int mcnt = 0; IOCTL_DEBUGOUT("igc_set_multi: begin"); - mta = adapter->mta; + mta = sc->mta; bzero(mta, sizeof(u8) * ETHER_ADDR_LEN * MAX_NUM_MULTICAST_ADDRESSES); mcnt = if_foreach_llmaddr(ifp, igc_copy_maddr, mta); - reg_rctl = IGC_READ_REG(&adapter->hw, IGC_RCTL); + reg_rctl = IGC_READ_REG(&sc->hw, IGC_RCTL); if (if_getflags(ifp) & IFF_PROMISC) { reg_rctl |= (IGC_RCTL_UPE | IGC_RCTL_MPE); @@ -1142,16 +1353,16 @@ igc_if_multi_set(if_ctx_t ctx) if (igc_debug_sbp) reg_rctl |= IGC_RCTL_SBP; } else if (mcnt >= MAX_NUM_MULTICAST_ADDRESSES || - if_getflags(ifp) & IFF_ALLMULTI) { - reg_rctl |= IGC_RCTL_MPE; + if_getflags(ifp) & IFF_ALLMULTI) { + reg_rctl |= IGC_RCTL_MPE; reg_rctl &= ~IGC_RCTL_UPE; - } else + } else reg_rctl &= ~(IGC_RCTL_UPE | IGC_RCTL_MPE); if (mcnt < MAX_NUM_MULTICAST_ADDRESSES) - igc_update_mc_addr_list(&adapter->hw, mta, mcnt); + igc_update_mc_addr_list(&sc->hw, mta, mcnt); - IGC_WRITE_REG(&adapter->hw, IGC_RCTL, reg_rctl); + IGC_WRITE_REG(&sc->hw, IGC_RCTL, reg_rctl); } /********************************************************************* @@ -1175,8 +1386,8 @@ igc_if_timer(if_ctx_t ctx, uint16_t qid) static void igc_if_update_admin_status(if_ctx_t ctx) { - struct igc_adapter *adapter = iflib_get_softc(ctx); - struct igc_hw *hw = &adapter->hw; + struct igc_softc *sc = iflib_get_softc(ctx); + struct igc_hw *hw = &sc->hw; device_t dev = iflib_get_dev(ctx); u32 link_check, thstat, ctrl; @@ -1200,36 +1411,36 @@ igc_if_update_admin_status(if_ctx_t ctx) } /* Now check for a transition */ - if (link_check && (adapter->link_active == 0)) { - igc_get_speed_and_duplex(hw, &adapter->link_speed, - &adapter->link_duplex); + if (link_check && (sc->link_active == 0)) { + igc_get_speed_and_duplex(hw, &sc->link_speed, + &sc->link_duplex); if (bootverbose) device_printf(dev, "Link is up %d Mbps %s\n", - adapter->link_speed, - ((adapter->link_duplex == FULL_DUPLEX) ? + sc->link_speed, + ((sc->link_duplex == FULL_DUPLEX) ? "Full Duplex" : "Half Duplex")); - adapter->link_active = 1; + sc->link_active = 1; iflib_link_state_change(ctx, LINK_STATE_UP, - IF_Mbps(adapter->link_speed)); - } else if (!link_check && (adapter->link_active == 1)) { - adapter->link_speed = 0; - adapter->link_duplex = 0; - adapter->link_active = 0; + IF_Mbps(sc->link_speed)); + } else if (!link_check && (sc->link_active == 1)) { + sc->link_speed = 0; + sc->link_duplex = 0; + sc->link_active = 0; iflib_link_state_change(ctx, LINK_STATE_DOWN, 0); } - igc_update_stats_counters(adapter); + igc_update_stats_counters(sc); } static void igc_if_watchdog_reset(if_ctx_t ctx) { - struct igc_adapter *adapter = iflib_get_softc(ctx); + struct igc_softc *sc = iflib_get_softc(ctx); /* * Just count the event; iflib(4) will already trigger a * sufficient reset of the controller. */ - adapter->watchdog_events++; + sc->watchdog_events++; } /********************************************************************* @@ -1241,12 +1452,12 @@ igc_if_watchdog_reset(if_ctx_t ctx) static void igc_if_stop(if_ctx_t ctx) { - struct igc_adapter *adapter = iflib_get_softc(ctx); + struct igc_softc *sc = iflib_get_softc(ctx); INIT_DEBUGOUT("igc_if_stop: begin"); - igc_reset_hw(&adapter->hw); - IGC_WRITE_REG(&adapter->hw, IGC_WUC, 0); + igc_reset_hw(&sc->hw); + IGC_WRITE_REG(&sc->hw, IGC_WUC, 0); } /********************************************************************* @@ -1258,22 +1469,22 @@ static void igc_identify_hardware(if_ctx_t ctx) { device_t dev = iflib_get_dev(ctx); - struct igc_adapter *adapter = iflib_get_softc(ctx); + struct igc_softc *sc = iflib_get_softc(ctx); /* Make sure our PCI config space has the necessary stuff set */ - adapter->hw.bus.pci_cmd_word = pci_read_config(dev, PCIR_COMMAND, 2); + sc->hw.bus.pci_cmd_word = pci_read_config(dev, PCIR_COMMAND, 2); /* Save off the information about this board */ - adapter->hw.vendor_id = pci_get_vendor(dev); - adapter->hw.device_id = pci_get_device(dev); - adapter->hw.revision_id = pci_read_config(dev, PCIR_REVID, 1); - adapter->hw.subsystem_vendor_id = + sc->hw.vendor_id = pci_get_vendor(dev); + sc->hw.device_id = pci_get_device(dev); + sc->hw.revision_id = pci_read_config(dev, PCIR_REVID, 1); + sc->hw.subsystem_vendor_id = pci_read_config(dev, PCIR_SUBVEND_0, 2); - adapter->hw.subsystem_device_id = + sc->hw.subsystem_device_id = pci_read_config(dev, PCIR_SUBDEV_0, 2); /* Do Shared Code Init and Setup */ - if (igc_set_mac_type(&adapter->hw)) { + if (igc_set_mac_type(&sc->hw)) { device_printf(dev, "Setup init failure\n"); return; } @@ -1282,23 +1493,24 @@ igc_identify_hardware(if_ctx_t ctx) static int igc_allocate_pci_resources(if_ctx_t ctx) { - struct igc_adapter *adapter = iflib_get_softc(ctx); + struct igc_softc *sc = iflib_get_softc(ctx); device_t dev = iflib_get_dev(ctx); int rid; rid = PCIR_BAR(0); - adapter->memory = bus_alloc_resource_any(dev, SYS_RES_MEMORY, + sc->memory = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE); - if (adapter->memory == NULL) { - device_printf(dev, "Unable to allocate bus resource: memory\n"); + if (sc->memory == NULL) { + device_printf(dev, + "Unable to allocate bus resource: memory\n"); return (ENXIO); } - adapter->osdep.mem_bus_space_tag = rman_get_bustag(adapter->memory); - adapter->osdep.mem_bus_space_handle = - rman_get_bushandle(adapter->memory); - adapter->hw.hw_addr = (u8 *)&adapter->osdep.mem_bus_space_handle; + sc->osdep.mem_bus_space_tag = rman_get_bustag(sc->memory); + sc->osdep.mem_bus_space_handle = + rman_get_bushandle(sc->memory); + sc->hw.hw_addr = (u8 *)&sc->osdep.mem_bus_space_handle; - adapter->hw.back = &adapter->osdep; + sc->hw.back = &sc->osdep; return (0); } @@ -1311,20 +1523,23 @@ igc_allocate_pci_resources(if_ctx_t ctx) static int igc_if_msix_intr_assign(if_ctx_t ctx, int msix) { - struct igc_adapter *adapter = iflib_get_softc(ctx); - struct igc_rx_queue *rx_que = adapter->rx_queues; - struct igc_tx_queue *tx_que = adapter->tx_queues; + struct igc_softc *sc = iflib_get_softc(ctx); + struct igc_rx_queue *rx_que = sc->rx_queues; + struct igc_tx_queue *tx_que = sc->tx_queues; int error, rid, i, vector = 0, rx_vectors; char buf[16]; /* First set up ring resources */ - for (i = 0; i < adapter->rx_num_queues; i++, rx_que++, vector++) { + for (i = 0; i < sc->rx_num_queues; i++, rx_que++, vector++) { rid = vector + 1; snprintf(buf, sizeof(buf), "rxq%d", i); - error = iflib_irq_alloc_generic(ctx, &rx_que->que_irq, rid, IFLIB_INTR_RXTX, igc_msix_que, rx_que, rx_que->me, buf); + error = iflib_irq_alloc_generic(ctx, &rx_que->que_irq, rid, + IFLIB_INTR_RXTX, igc_msix_que, rx_que, rx_que->me, buf); if (error) { - device_printf(iflib_get_dev(ctx), "Failed to allocate que int %d err: %d", i, error); - adapter->rx_num_queues = i + 1; + device_printf(iflib_get_dev(ctx), + "Failed to allocate que int %d err: %d", + i, error); + sc->rx_num_queues = i + 1; goto fail; } @@ -1341,14 +1556,14 @@ igc_if_msix_intr_assign(if_ctx_t ctx, int msix) rx_vectors = vector; vector = 0; - for (i = 0; i < adapter->tx_num_queues; i++, tx_que++, vector++) { + for (i = 0; i < sc->tx_num_queues; i++, tx_que++, vector++) { snprintf(buf, sizeof(buf), "txq%d", i); - tx_que = &adapter->tx_queues[i]; + tx_que = &sc->tx_queues[i]; iflib_softirq_alloc_generic(ctx, - &adapter->rx_queues[i % adapter->rx_num_queues].que_irq, + &sc->rx_queues[i % sc->rx_num_queues].que_irq, IFLIB_INTR_TX, tx_que, tx_que->me, buf); - tx_que->msix = (vector % adapter->rx_num_queues); + tx_que->msix = (vector % sc->rx_num_queues); /* * Set the bit to enable interrupt @@ -1361,26 +1576,28 @@ igc_if_msix_intr_assign(if_ctx_t ctx, int msix) /* Link interrupt */ rid = rx_vectors + 1; - error = iflib_irq_alloc_generic(ctx, &adapter->irq, rid, IFLIB_INTR_ADMIN, igc_msix_link, adapter, 0, "aq"); + error = iflib_irq_alloc_generic(ctx, &sc->irq, rid, IFLIB_INTR_ADMIN, + igc_msix_link, sc, 0, "aq"); if (error) { - device_printf(iflib_get_dev(ctx), "Failed to register admin handler"); + device_printf(iflib_get_dev(ctx), + "Failed to register admin handler"); goto fail; } - adapter->linkvec = rx_vectors; + sc->linkvec = rx_vectors; return (0); fail: - iflib_irq_free(ctx, &adapter->irq); - rx_que = adapter->rx_queues; - for (int i = 0; i < adapter->rx_num_queues; i++, rx_que++) + iflib_irq_free(ctx, &sc->irq); + rx_que = sc->rx_queues; + for (int i = 0; i < sc->rx_num_queues; i++, rx_que++) iflib_irq_free(ctx, &rx_que->que_irq); return (error); } static void -igc_configure_queues(struct igc_adapter *adapter) +igc_configure_queues(struct igc_softc *sc) { - struct igc_hw *hw = &adapter->hw; + struct igc_hw *hw = &sc->hw; struct igc_rx_queue *rx_que; struct igc_tx_queue *tx_que; u32 ivar = 0, newitr = 0; @@ -1392,10 +1609,10 @@ igc_configure_queues(struct igc_adapter *adapter) /* Turn on MSI-X */ /* RX entries */ - for (int i = 0; i < adapter->rx_num_queues; i++) { + for (int i = 0; i < sc->rx_num_queues; i++) { u32 index = i >> 1; ivar = IGC_READ_REG_ARRAY(hw, IGC_IVAR0, index); - rx_que = &adapter->rx_queues[i]; + rx_que = &sc->rx_queues[i]; if (i & 1) { ivar &= 0xFF00FFFF; ivar |= (rx_que->msix | IGC_IVAR_VALID) << 16; @@ -1406,10 +1623,10 @@ igc_configure_queues(struct igc_adapter *adapter) IGC_WRITE_REG_ARRAY(hw, IGC_IVAR0, index, ivar); } /* TX entries */ - for (int i = 0; i < adapter->tx_num_queues; i++) { + for (int i = 0; i < sc->tx_num_queues; i++) { u32 index = i >> 1; ivar = IGC_READ_REG_ARRAY(hw, IGC_IVAR0, index); - tx_que = &adapter->tx_queues[i]; + tx_que = &sc->tx_queues[i]; if (i & 1) { ivar &= 0x00FFFFFF; ivar |= (tx_que->msix | IGC_IVAR_VALID) << 24; @@ -1418,22 +1635,22 @@ igc_configure_queues(struct igc_adapter *adapter) ivar |= (tx_que->msix | IGC_IVAR_VALID) << 8; } IGC_WRITE_REG_ARRAY(hw, IGC_IVAR0, index, ivar); - adapter->que_mask |= tx_que->eims; + sc->que_mask |= tx_que->eims; } /* And for the link interrupt */ - ivar = (adapter->linkvec | IGC_IVAR_VALID) << 8; - adapter->link_mask = 1 << adapter->linkvec; + ivar = (sc->linkvec | IGC_IVAR_VALID) << 8; + sc->link_mask = 1 << sc->linkvec; IGC_WRITE_REG(hw, IGC_IVAR_MISC, ivar); /* Set the starting interrupt rate */ if (igc_max_interrupt_rate > 0) - newitr = (4000000 / igc_max_interrupt_rate) & 0x7FFC; + newitr = IGC_INTS_TO_EITR(igc_max_interrupt_rate); newitr |= IGC_EITR_CNT_IGNR; - for (int i = 0; i < adapter->rx_num_queues; i++) { - rx_que = &adapter->rx_queues[i]; + for (int i = 0; i < sc->rx_num_queues; i++) { + rx_que = &sc->rx_queues[i]; IGC_WRITE_REG(hw, IGC_EITR(rx_que->msix), newitr); } @@ -1443,34 +1660,34 @@ igc_configure_queues(struct igc_adapter *adapter) static void igc_free_pci_resources(if_ctx_t ctx) { - struct igc_adapter *adapter = iflib_get_softc(ctx); - struct igc_rx_queue *que = adapter->rx_queues; + struct igc_softc *sc = iflib_get_softc(ctx); + struct igc_rx_queue *que = sc->rx_queues; device_t dev = iflib_get_dev(ctx); /* Release all MSI-X queue resources */ - if (adapter->intr_type == IFLIB_INTR_MSIX) - iflib_irq_free(ctx, &adapter->irq); + if (sc->intr_type == IFLIB_INTR_MSIX) + iflib_irq_free(ctx, &sc->irq); - for (int i = 0; i < adapter->rx_num_queues; i++, que++) { + for (int i = 0; i < sc->rx_num_queues; i++, que++) { iflib_irq_free(ctx, &que->que_irq); } - if (adapter->memory != NULL) { + if (sc->memory != NULL) { bus_release_resource(dev, SYS_RES_MEMORY, - rman_get_rid(adapter->memory), adapter->memory); - adapter->memory = NULL; + rman_get_rid(sc->memory), sc->memory); + sc->memory = NULL; } - if (adapter->flash != NULL) { + if (sc->flash != NULL) { bus_release_resource(dev, SYS_RES_MEMORY, - rman_get_rid(adapter->flash), adapter->flash); - adapter->flash = NULL; + rman_get_rid(sc->flash), sc->flash); + sc->flash = NULL; } - if (adapter->ioport != NULL) { + if (sc->ioport != NULL) { bus_release_resource(dev, SYS_RES_IOPORT, - rman_get_rid(adapter->ioport), adapter->ioport); - adapter->ioport = NULL; + rman_get_rid(sc->ioport), sc->ioport); + sc->ioport = NULL; } } @@ -1487,18 +1704,18 @@ igc_setup_msix(if_ctx_t ctx) * **********************************************************************/ static void -igc_init_dmac(struct igc_adapter *adapter, u32 pba) +igc_init_dmac(struct igc_softc *sc, u32 pba) { - device_t dev = adapter->dev; - struct igc_hw *hw = &adapter->hw; - u32 dmac, reg = ~IGC_DMACR_DMAC_EN; - u16 hwm; - u16 max_frame_size; - int status; + device_t dev = sc->dev; + struct igc_hw *hw = &sc->hw; + u32 dmac, reg = ~IGC_DMACR_DMAC_EN; + u16 hwm; + u16 max_frame_size; + int status; - max_frame_size = adapter->shared->isc_max_frame_size; + max_frame_size = sc->shared->isc_max_frame_size; - if (adapter->dmac == 0) { /* Disabling it */ + if (sc->dmac == 0) { /* Disabling it */ IGC_WRITE_REG(hw, IGC_DMACR, reg); return; } else @@ -1536,9 +1753,9 @@ igc_init_dmac(struct igc_adapter *adapter, u32 pba) status = IGC_READ_REG(hw, IGC_STATUS); if ((status & IGC_STATUS_2P5_SKU) && (!(status & IGC_STATUS_2P5_SKU_OVER))) - reg |= ((adapter->dmac * 5) >> 6); + reg |= ((sc->dmac * 5) >> 6); else - reg |= (adapter->dmac >> 5); + reg |= (sc->dmac >> 5); IGC_WRITE_REG(hw, IGC_DMACR, reg); @@ -1574,21 +1791,21 @@ igc_init_dmac(struct igc_adapter *adapter, u32 pba) /********************************************************************* * * Initialize the hardware to a configuration as specified by the - * adapter structure. + * softc structure. * **********************************************************************/ static void igc_reset(if_ctx_t ctx) { device_t dev = iflib_get_dev(ctx); - struct igc_adapter *adapter = iflib_get_softc(ctx); - struct igc_hw *hw = &adapter->hw; + struct igc_softc *sc = iflib_get_softc(ctx); + struct igc_hw *hw = &sc->hw; u32 rx_buffer_size; u32 pba; INIT_DEBUGOUT("igc_reset: begin"); /* Let the firmware know the OS is in control */ - igc_get_hw_control(adapter); + igc_get_hw_control(sc); /* * Packet Buffer Allocation (PBA) @@ -1604,7 +1821,8 @@ igc_reset(if_ctx_t ctx) * response (Rx) to Ethernet PAUSE frames. * - High water mark should allow for at least two frames to be * received after sending an XOFF. - * - Low water mark works best when it is very near the high water mark. + * - Low water mark works best when it is very near the high water + * mark. * This allows the receiver to restart by sending XON when it has * drained a bit. Here we use an arbitrary value of 1500 which will * restart after one full frame is pulled from the buffer. There @@ -1615,12 +1833,12 @@ igc_reset(if_ctx_t ctx) */ rx_buffer_size = (pba & 0xffff) << 10; hw->fc.high_water = rx_buffer_size - - roundup2(adapter->hw.mac.max_frame_size, 1024); + roundup2(sc->hw.mac.max_frame_size, 1024); /* 16-byte granularity */ hw->fc.low_water = hw->fc.high_water - 16; - if (adapter->fc) /* locally set flow control value? */ - hw->fc.requested_mode = adapter->fc; + if (sc->fc) /* locally set flow control value? */ + hw->fc.requested_mode = sc->fc; else hw->fc.requested_mode = igc_fc_full; @@ -1639,7 +1857,10 @@ igc_reset(if_ctx_t ctx) } /* Setup DMA Coalescing */ - igc_init_dmac(adapter, pba); + igc_init_dmac(sc, pba); + + /* Save the final PBA off if it needs to be used elsewhere i.e. AIM */ + sc->pba = pba; IGC_WRITE_REG(hw, IGC_VET, ETHERTYPE_VLAN); igc_get_phy_info(hw); @@ -1653,9 +1874,9 @@ igc_reset(if_ctx_t ctx) #define RSSKEYLEN 10 static void -igc_initialize_rss_mapping(struct igc_adapter *adapter) +igc_initialize_rss_mapping(struct igc_softc *sc) { - struct igc_hw *hw = &adapter->hw; + struct igc_hw *hw = &sc->hw; int i; int queue_id; u32 reta; @@ -1692,9 +1913,9 @@ igc_initialize_rss_mapping(struct igc_adapter *adapter) * the case so we don't go out of bounds * indexing arrays and such. */ - queue_id = queue_id % adapter->rx_num_queues; + queue_id = queue_id % sc->rx_num_queues; #else - queue_id = (i % adapter->rx_num_queues); + queue_id = (i % sc->rx_num_queues); #endif /* Adjust if required */ queue_id = queue_id << shift; @@ -1752,13 +1973,13 @@ static int igc_setup_interface(if_ctx_t ctx) { if_t ifp = iflib_get_ifp(ctx); - struct igc_adapter *adapter = iflib_get_softc(ctx); - if_softc_ctx_t scctx = adapter->shared; + struct igc_softc *sc = iflib_get_softc(ctx); + if_softc_ctx_t scctx = sc->shared; INIT_DEBUGOUT("igc_setup_interface: begin"); /* Single Queue */ - if (adapter->tx_num_queues == 1) { + if (sc->tx_num_queues == 1) { if_setsendqlen(ifp, scctx->isc_ntxd[0] - 1); if_setsendqready(ifp); } @@ -1767,62 +1988,66 @@ igc_setup_interface(if_ctx_t ctx) * Specify the media types supported by this adapter and register * callbacks to update media and link information */ - ifmedia_add(adapter->media, IFM_ETHER | IFM_10_T, 0, NULL); - ifmedia_add(adapter->media, IFM_ETHER | IFM_10_T | IFM_FDX, 0, NULL); - ifmedia_add(adapter->media, IFM_ETHER | IFM_100_TX, 0, NULL); - ifmedia_add(adapter->media, IFM_ETHER | IFM_100_TX | IFM_FDX, 0, NULL); - ifmedia_add(adapter->media, IFM_ETHER | IFM_1000_T | IFM_FDX, 0, NULL); - ifmedia_add(adapter->media, IFM_ETHER | IFM_1000_T, 0, NULL); - ifmedia_add(adapter->media, IFM_ETHER | IFM_2500_T, 0, NULL); - - ifmedia_add(adapter->media, IFM_ETHER | IFM_AUTO, 0, NULL); - ifmedia_set(adapter->media, IFM_ETHER | IFM_AUTO); + ifmedia_add(sc->media, IFM_ETHER | IFM_10_T, 0, NULL); + ifmedia_add(sc->media, IFM_ETHER | IFM_10_T | IFM_FDX, 0, NULL); + ifmedia_add(sc->media, IFM_ETHER | IFM_100_TX, 0, NULL); + ifmedia_add(sc->media, IFM_ETHER | IFM_100_TX | IFM_FDX, 0, NULL); + ifmedia_add(sc->media, IFM_ETHER | IFM_1000_T | IFM_FDX, 0, NULL); + ifmedia_add(sc->media, IFM_ETHER | IFM_1000_T, 0, NULL); + ifmedia_add(sc->media, IFM_ETHER | IFM_2500_T, 0, NULL); + + ifmedia_add(sc->media, IFM_ETHER | IFM_AUTO, 0, NULL); + ifmedia_set(sc->media, IFM_ETHER | IFM_AUTO); return (0); } static int -igc_if_tx_queues_alloc(if_ctx_t ctx, caddr_t *vaddrs, uint64_t *paddrs, int ntxqs, int ntxqsets) +igc_if_tx_queues_alloc(if_ctx_t ctx, caddr_t *vaddrs, uint64_t *paddrs, + int ntxqs, int ntxqsets) { - struct igc_adapter *adapter = iflib_get_softc(ctx); - if_softc_ctx_t scctx = adapter->shared; + struct igc_softc *sc = iflib_get_softc(ctx); + if_softc_ctx_t scctx = sc->shared; int error = IGC_SUCCESS; struct igc_tx_queue *que; int i, j; - MPASS(adapter->tx_num_queues > 0); - MPASS(adapter->tx_num_queues == ntxqsets); + MPASS(sc->tx_num_queues > 0); + MPASS(sc->tx_num_queues == ntxqsets); /* First allocate the top level queue structs */ - if (!(adapter->tx_queues = + if (!(sc->tx_queues = (struct igc_tx_queue *) malloc(sizeof(struct igc_tx_queue) * - adapter->tx_num_queues, M_DEVBUF, M_NOWAIT | M_ZERO))) { - device_printf(iflib_get_dev(ctx), "Unable to allocate queue memory\n"); + sc->tx_num_queues, M_DEVBUF, M_NOWAIT | M_ZERO))) { + device_printf(iflib_get_dev(ctx), + "Unable to allocate queue memory\n"); return(ENOMEM); } - for (i = 0, que = adapter->tx_queues; i < adapter->tx_num_queues; i++, que++) { + for (i = 0, que = sc->tx_queues; i < sc->tx_num_queues; i++, que++) { /* Set up some basics */ struct tx_ring *txr = &que->txr; - txr->adapter = que->adapter = adapter; + txr->sc = que->sc = sc; que->me = txr->me = i; /* Allocate report status array */ - if (!(txr->tx_rsq = (qidx_t *) malloc(sizeof(qidx_t) * scctx->isc_ntxd[0], M_DEVBUF, M_NOWAIT | M_ZERO))) { - device_printf(iflib_get_dev(ctx), "failed to allocate rs_idxs memory\n"); + if (!(txr->tx_rsq = (qidx_t *) malloc(sizeof(qidx_t) * + scctx->isc_ntxd[0], M_DEVBUF, M_NOWAIT | M_ZERO))) { + device_printf(iflib_get_dev(ctx), + "failed to allocate rs_idxs memory\n"); error = ENOMEM; goto fail; } for (j = 0; j < scctx->isc_ntxd[0]; j++) txr->tx_rsq[j] = QIDX_INVALID; - /* get the virtual and physical address of the hardware queues */ + /* get virtual and physical address of the hardware queues */ txr->tx_base = (struct igc_tx_desc *)vaddrs[i*ntxqs]; txr->tx_paddr = paddrs[i*ntxqs]; } if (bootverbose) device_printf(iflib_get_dev(ctx), - "allocated for %d tx_queues\n", adapter->tx_num_queues); + "allocated for %d tx_queues\n", sc->tx_num_queues); return (0); fail: igc_if_queues_free(ctx); @@ -1830,40 +2055,42 @@ fail: } static int -igc_if_rx_queues_alloc(if_ctx_t ctx, caddr_t *vaddrs, uint64_t *paddrs, int nrxqs, int nrxqsets) +igc_if_rx_queues_alloc(if_ctx_t ctx, caddr_t *vaddrs, uint64_t *paddrs, + int nrxqs, int nrxqsets) { - struct igc_adapter *adapter = iflib_get_softc(ctx); + struct igc_softc *sc = iflib_get_softc(ctx); int error = IGC_SUCCESS; struct igc_rx_queue *que; int i; - MPASS(adapter->rx_num_queues > 0); - MPASS(adapter->rx_num_queues == nrxqsets); + MPASS(sc->rx_num_queues > 0); + MPASS(sc->rx_num_queues == nrxqsets); /* First allocate the top level queue structs */ - if (!(adapter->rx_queues = + if (!(sc->rx_queues = (struct igc_rx_queue *) malloc(sizeof(struct igc_rx_queue) * - adapter->rx_num_queues, M_DEVBUF, M_NOWAIT | M_ZERO))) { - device_printf(iflib_get_dev(ctx), "Unable to allocate queue memory\n"); + sc->rx_num_queues, M_DEVBUF, M_NOWAIT | M_ZERO))) { + device_printf(iflib_get_dev(ctx), + "Unable to allocate queue memory\n"); error = ENOMEM; goto fail; } - for (i = 0, que = adapter->rx_queues; i < nrxqsets; i++, que++) { + for (i = 0, que = sc->rx_queues; i < nrxqsets; i++, que++) { /* Set up some basics */ struct rx_ring *rxr = &que->rxr; - rxr->adapter = que->adapter = adapter; + rxr->sc = que->sc = sc; rxr->que = que; que->me = rxr->me = i; - /* get the virtual and physical address of the hardware queues */ + /* get virtual and physical address of the hardware queues */ rxr->rx_base = (union igc_rx_desc_extended *)vaddrs[i*nrxqs]; rxr->rx_paddr = paddrs[i*nrxqs]; } if (bootverbose) device_printf(iflib_get_dev(ctx), - "allocated for %d rx_queues\n", adapter->rx_num_queues); + "allocated for %d rx_queues\n", sc->rx_num_queues); return (0); fail: @@ -1874,12 +2101,12 @@ fail: static void igc_if_queues_free(if_ctx_t ctx) { - struct igc_adapter *adapter = iflib_get_softc(ctx); - struct igc_tx_queue *tx_que = adapter->tx_queues; - struct igc_rx_queue *rx_que = adapter->rx_queues; + struct igc_softc *sc = iflib_get_softc(ctx); + struct igc_tx_queue *tx_que = sc->tx_queues; + struct igc_rx_queue *rx_que = sc->rx_queues; if (tx_que != NULL) { - for (int i = 0; i < adapter->tx_num_queues; i++, tx_que++) { + for (int i = 0; i < sc->tx_num_queues; i++, tx_que++) { struct tx_ring *txr = &tx_que->txr; if (txr->tx_rsq == NULL) break; @@ -1887,19 +2114,17 @@ igc_if_queues_free(if_ctx_t ctx) free(txr->tx_rsq, M_DEVBUF); txr->tx_rsq = NULL; } - free(adapter->tx_queues, M_DEVBUF); - adapter->tx_queues = NULL; + free(sc->tx_queues, M_DEVBUF); + sc->tx_queues = NULL; } if (rx_que != NULL) { - free(adapter->rx_queues, M_DEVBUF); - adapter->rx_queues = NULL; + free(sc->rx_queues, M_DEVBUF); + sc->rx_queues = NULL; } - igc_release_hw_control(adapter); - - if (adapter->mta != NULL) { - free(adapter->mta, M_DEVBUF); + if (sc->mta != NULL) { + free(sc->mta, M_DEVBUF); } } @@ -1911,20 +2136,20 @@ igc_if_queues_free(if_ctx_t ctx) static void igc_initialize_transmit_unit(if_ctx_t ctx) { - struct igc_adapter *adapter = iflib_get_softc(ctx); - if_softc_ctx_t scctx = adapter->shared; + struct igc_softc *sc = iflib_get_softc(ctx); + if_softc_ctx_t scctx = sc->shared; struct igc_tx_queue *que; struct tx_ring *txr; - struct igc_hw *hw = &adapter->hw; + struct igc_hw *hw = &sc->hw; u32 tctl, txdctl = 0; INIT_DEBUGOUT("igc_initialize_transmit_unit: begin"); - for (int i = 0; i < adapter->tx_num_queues; i++, txr++) { + for (int i = 0; i < sc->tx_num_queues; i++, txr++) { u64 bus_addr; caddr_t offp, endp; - que = &adapter->tx_queues[i]; + que = &sc->tx_queues[i]; txr = &que->txr; bus_addr = txr->tx_paddr; @@ -1945,8 +2170,8 @@ igc_initialize_transmit_unit(if_ctx_t ctx) IGC_WRITE_REG(hw, IGC_TDH(i), 0); HW_DEBUGOUT2("Base = %x, Length = %x\n", - IGC_READ_REG(&adapter->hw, IGC_TDBAL(i)), - IGC_READ_REG(&adapter->hw, IGC_TDLEN(i))); + IGC_READ_REG(&sc->hw, IGC_TDBAL(i)), + IGC_READ_REG(&sc->hw, IGC_TDLEN(i))); txdctl = 0; /* clear txdctl */ txdctl |= 0x1f; /* PTHRESH */ @@ -1960,13 +2185,13 @@ igc_initialize_transmit_unit(if_ctx_t ctx) } /* Program the Transmit Control Register */ - tctl = IGC_READ_REG(&adapter->hw, IGC_TCTL); + tctl = IGC_READ_REG(&sc->hw, IGC_TCTL); tctl &= ~IGC_TCTL_CT; tctl |= (IGC_TCTL_PSP | IGC_TCTL_RTLC | IGC_TCTL_EN | - (IGC_COLLISION_THRESHOLD << IGC_CT_SHIFT)); + (IGC_COLLISION_THRESHOLD << IGC_CT_SHIFT)); /* This write will effectively turn on the transmit unit. */ - IGC_WRITE_REG(&adapter->hw, IGC_TCTL, tctl); + IGC_WRITE_REG(&sc->hw, IGC_TCTL, tctl); } /********************************************************************* @@ -1979,10 +2204,10 @@ igc_initialize_transmit_unit(if_ctx_t ctx) static void igc_initialize_receive_unit(if_ctx_t ctx) { - struct igc_adapter *adapter = iflib_get_softc(ctx); - if_softc_ctx_t scctx = adapter->shared; + struct igc_softc *sc = iflib_get_softc(ctx); + if_softc_ctx_t scctx = sc->shared; if_t ifp = iflib_get_ifp(ctx); - struct igc_hw *hw = &adapter->hw; + struct igc_hw *hw = &sc->hw; struct igc_rx_queue *que; int i; u32 psize, rctl, rxcsum, srrctl = 0; @@ -2015,40 +2240,34 @@ igc_initialize_receive_unit(if_ctx_t ctx) if (!igc_disable_crc_stripping) rctl |= IGC_RCTL_SECRC; - /* - * Set the interrupt throttling rate. Value is calculated - * as DEFAULT_ITR = 1/(MAX_INTS_PER_SEC * 256ns) - */ - IGC_WRITE_REG(hw, IGC_ITR, DEFAULT_ITR); - rxcsum = IGC_READ_REG(hw, IGC_RXCSUM); if (if_getcapenable(ifp) & IFCAP_RXCSUM) { rxcsum |= IGC_RXCSUM_CRCOFL; - if (adapter->tx_num_queues > 1) + if (sc->tx_num_queues > 1) rxcsum |= IGC_RXCSUM_PCSD; else rxcsum |= IGC_RXCSUM_IPPCSE; } else { - if (adapter->tx_num_queues > 1) + if (sc->tx_num_queues > 1) rxcsum |= IGC_RXCSUM_PCSD; else rxcsum &= ~IGC_RXCSUM_TUOFL; } IGC_WRITE_REG(hw, IGC_RXCSUM, rxcsum); - if (adapter->rx_num_queues > 1) - igc_initialize_rss_mapping(adapter); + if (sc->rx_num_queues > 1) + igc_initialize_rss_mapping(sc); if (if_getmtu(ifp) > ETHERMTU) { psize = scctx->isc_max_frame_size; /* are we on a vlan? */ if (if_vlantrunkinuse(ifp)) psize += VLAN_TAG_SIZE; - IGC_WRITE_REG(&adapter->hw, IGC_RLPML, psize); + IGC_WRITE_REG(&sc->hw, IGC_RLPML, psize); } /* Set maximum packet buffer len */ - srrctl |= (adapter->rx_mbuf_sz + BSIZEPKT_ROUNDUP) >> + srrctl |= (sc->rx_mbuf_sz + BSIZEPKT_ROUNDUP) >> IGC_SRRCTL_BSIZEPKT_SHIFT; /* srrctl above overrides this but set the register to a sane value */ rctl |= IGC_RCTL_SZ_2048; @@ -2059,14 +2278,14 @@ igc_initialize_receive_unit(if_ctx_t ctx) * * This drops frames rather than hanging the RX MAC for all queues. */ - if ((adapter->rx_num_queues > 1) && - (adapter->fc == igc_fc_none || - adapter->fc == igc_fc_rx_pause)) { + if ((sc->rx_num_queues > 1) && + (sc->fc == igc_fc_none || + sc->fc == igc_fc_rx_pause)) { srrctl |= IGC_SRRCTL_DROP_EN; } /* Setup the Base and Length of the Rx Descriptor Rings */ - for (i = 0, que = adapter->rx_queues; i < adapter->rx_num_queues; i++, que++) { + for (i = 0, que = sc->rx_queues; i < sc->rx_num_queues; i++, que++) { struct rx_ring *rxr = &que->rxr; u64 bus_addr = rxr->rx_paddr; u32 rxdctl; @@ -2079,11 +2298,9 @@ igc_initialize_receive_unit(if_ctx_t ctx) #endif IGC_WRITE_REG(hw, IGC_RDLEN(i), - scctx->isc_nrxd[0] * sizeof(struct igc_rx_desc)); - IGC_WRITE_REG(hw, IGC_RDBAH(i), - (uint32_t)(bus_addr >> 32)); - IGC_WRITE_REG(hw, IGC_RDBAL(i), - (uint32_t)bus_addr); + scctx->isc_nrxd[0] * sizeof(struct igc_rx_desc)); + IGC_WRITE_REG(hw, IGC_RDBAH(i), (uint32_t)(bus_addr >> 32)); + IGC_WRITE_REG(hw, IGC_RDBAL(i), (uint32_t)bus_addr); IGC_WRITE_REG(hw, IGC_SRRCTL(i), srrctl); /* Setup the Head and Tail Descriptor Pointers */ IGC_WRITE_REG(hw, IGC_RDH(i), 0); @@ -2110,8 +2327,8 @@ igc_initialize_receive_unit(if_ctx_t ctx) static void igc_setup_vlan_hw_support(if_ctx_t ctx) { - struct igc_adapter *adapter = iflib_get_softc(ctx); - struct igc_hw *hw = &adapter->hw; + struct igc_softc *sc = iflib_get_softc(ctx); + struct igc_hw *hw = &sc->hw; struct ifnet *ifp = iflib_get_ifp(ctx); u32 reg; @@ -2132,12 +2349,12 @@ igc_setup_vlan_hw_support(if_ctx_t ctx) static void igc_if_intr_enable(if_ctx_t ctx) { - struct igc_adapter *adapter = iflib_get_softc(ctx); - struct igc_hw *hw = &adapter->hw; + struct igc_softc *sc = iflib_get_softc(ctx); + struct igc_hw *hw = &sc->hw; u32 mask; - if (__predict_true(adapter->intr_type == IFLIB_INTR_MSIX)) { - mask = (adapter->que_mask | adapter->link_mask); + if (__predict_true(sc->intr_type == IFLIB_INTR_MSIX)) { + mask = (sc->que_mask | sc->link_mask); IGC_WRITE_REG(hw, IGC_EIAC, mask); IGC_WRITE_REG(hw, IGC_EIAM, mask); IGC_WRITE_REG(hw, IGC_EIMS, mask); @@ -2150,10 +2367,10 @@ igc_if_intr_enable(if_ctx_t ctx) static void igc_if_intr_disable(if_ctx_t ctx) { - struct igc_adapter *adapter = iflib_get_softc(ctx); - struct igc_hw *hw = &adapter->hw; + struct igc_softc *sc = iflib_get_softc(ctx); + struct igc_hw *hw = &sc->hw; - if (__predict_true(adapter->intr_type == IFLIB_INTR_MSIX)) { + if (__predict_true(sc->intr_type == IFLIB_INTR_MSIX)) { IGC_WRITE_REG(hw, IGC_EIMC, 0xffffffff); IGC_WRITE_REG(hw, IGC_EIAC, 0); } @@ -2168,15 +2385,15 @@ igc_if_intr_disable(if_ctx_t ctx) * this means that the network i/f is open. */ static void -igc_get_hw_control(struct igc_adapter *adapter) +igc_get_hw_control(struct igc_softc *sc) { u32 ctrl_ext; - if (adapter->vf_ifp) + if (sc->vf_ifp) return; - ctrl_ext = IGC_READ_REG(&adapter->hw, IGC_CTRL_EXT); - IGC_WRITE_REG(&adapter->hw, IGC_CTRL_EXT, + ctrl_ext = IGC_READ_REG(&sc->hw, IGC_CTRL_EXT); + IGC_WRITE_REG(&sc->hw, IGC_CTRL_EXT, ctrl_ext | IGC_CTRL_EXT_DRV_LOAD); } @@ -2187,12 +2404,12 @@ igc_get_hw_control(struct igc_adapter *adapter) * f/w this means that the network i/f is closed. */ static void -igc_release_hw_control(struct igc_adapter *adapter) +igc_release_hw_control(struct igc_softc *sc) { u32 ctrl_ext; - ctrl_ext = IGC_READ_REG(&adapter->hw, IGC_CTRL_EXT); - IGC_WRITE_REG(&adapter->hw, IGC_CTRL_EXT, + ctrl_ext = IGC_READ_REG(&sc->hw, IGC_CTRL_EXT); + IGC_WRITE_REG(&sc->hw, IGC_CTRL_EXT, ctrl_ext & ~IGC_CTRL_EXT_DRV_LOAD); return; } @@ -2217,14 +2434,14 @@ igc_is_valid_ether_addr(u8 *addr) static void igc_get_wakeup(if_ctx_t ctx) { - struct igc_adapter *adapter = iflib_get_softc(ctx); + struct igc_softc *sc = iflib_get_softc(ctx); u16 eeprom_data = 0, apme_mask; apme_mask = IGC_WUC_APME; - eeprom_data = IGC_READ_REG(&adapter->hw, IGC_WUC); + eeprom_data = IGC_READ_REG(&sc->hw, IGC_WUC); if (eeprom_data & apme_mask) - adapter->wol = IGC_WUFC_LNKC; + sc->wol = IGC_WUFC_LNKC; } @@ -2234,14 +2451,13 @@ igc_get_wakeup(if_ctx_t ctx) static void igc_enable_wakeup(if_ctx_t ctx) { - struct igc_adapter *adapter = iflib_get_softc(ctx); + struct igc_softc *sc = iflib_get_softc(ctx); device_t dev = iflib_get_dev(ctx); if_t ifp = iflib_get_ifp(ctx); int error = 0; - u32 pmc, ctrl, rctl; - u16 status; + u32 ctrl, rctl; - if (pci_find_cap(dev, PCIY_PMG, &pmc) != 0) + if (!pci_has_pm(dev)) return; /* @@ -2249,37 +2465,34 @@ igc_enable_wakeup(if_ctx_t ctx) * is set with all bits on by default. */ if ((if_getcapenable(ifp) & IFCAP_WOL_MAGIC) == 0) - adapter->wol &= ~IGC_WUFC_MAG; + sc->wol &= ~IGC_WUFC_MAG; if ((if_getcapenable(ifp) & IFCAP_WOL_UCAST) == 0) - adapter->wol &= ~IGC_WUFC_EX; + sc->wol &= ~IGC_WUFC_EX; if ((if_getcapenable(ifp) & IFCAP_WOL_MCAST) == 0) - adapter->wol &= ~IGC_WUFC_MC; + sc->wol &= ~IGC_WUFC_MC; else { - rctl = IGC_READ_REG(&adapter->hw, IGC_RCTL); + rctl = IGC_READ_REG(&sc->hw, IGC_RCTL); rctl |= IGC_RCTL_MPE; - IGC_WRITE_REG(&adapter->hw, IGC_RCTL, rctl); + IGC_WRITE_REG(&sc->hw, IGC_RCTL, rctl); } - if (!(adapter->wol & (IGC_WUFC_EX | IGC_WUFC_MAG | IGC_WUFC_MC))) + if (!(sc->wol & (IGC_WUFC_EX | IGC_WUFC_MAG | IGC_WUFC_MC))) goto pme; /* Advertise the wakeup capability */ - ctrl = IGC_READ_REG(&adapter->hw, IGC_CTRL); + ctrl = IGC_READ_REG(&sc->hw, IGC_CTRL); ctrl |= IGC_CTRL_ADVD3WUC; - IGC_WRITE_REG(&adapter->hw, IGC_CTRL, ctrl); + IGC_WRITE_REG(&sc->hw, IGC_CTRL, ctrl); /* Enable wakeup by the MAC */ - IGC_WRITE_REG(&adapter->hw, IGC_WUC, IGC_WUC_PME_EN); - IGC_WRITE_REG(&adapter->hw, IGC_WUFC, adapter->wol); + IGC_WRITE_REG(&sc->hw, IGC_WUC, IGC_WUC_PME_EN); + IGC_WRITE_REG(&sc->hw, IGC_WUFC, sc->wol); pme: - status = pci_read_config(dev, pmc + PCIR_POWER_STATUS, 2); - status &= ~(PCIM_PSTAT_PME | PCIM_PSTAT_PMEENABLE); if (!error && (if_getcapenable(ifp) & IFCAP_WOL)) - status |= PCIM_PSTAT_PME | PCIM_PSTAT_PMEENABLE; - pci_write_config(dev, pmc + PCIR_POWER_STATUS, status, 2); + pci_enable_pme(dev); return; } @@ -2290,100 +2503,104 @@ pme: * **********************************************************************/ static void -igc_update_stats_counters(struct igc_adapter *adapter) -{ - u64 prev_xoffrxc = adapter->stats.xoffrxc; - - adapter->stats.crcerrs += IGC_READ_REG(&adapter->hw, IGC_CRCERRS); - adapter->stats.mpc += IGC_READ_REG(&adapter->hw, IGC_MPC); - adapter->stats.scc += IGC_READ_REG(&adapter->hw, IGC_SCC); - adapter->stats.ecol += IGC_READ_REG(&adapter->hw, IGC_ECOL); - - adapter->stats.mcc += IGC_READ_REG(&adapter->hw, IGC_MCC); - adapter->stats.latecol += IGC_READ_REG(&adapter->hw, IGC_LATECOL); - adapter->stats.colc += IGC_READ_REG(&adapter->hw, IGC_COLC); - adapter->stats.colc += IGC_READ_REG(&adapter->hw, IGC_RERC); - adapter->stats.dc += IGC_READ_REG(&adapter->hw, IGC_DC); - adapter->stats.rlec += IGC_READ_REG(&adapter->hw, IGC_RLEC); - adapter->stats.xonrxc += IGC_READ_REG(&adapter->hw, IGC_XONRXC); - adapter->stats.xontxc += IGC_READ_REG(&adapter->hw, IGC_XONTXC); - adapter->stats.xoffrxc += IGC_READ_REG(&adapter->hw, IGC_XOFFRXC); +igc_update_stats_counters(struct igc_softc *sc) +{ + u64 prev_xoffrxc = sc->stats.xoffrxc; + + sc->stats.crcerrs += IGC_READ_REG(&sc->hw, IGC_CRCERRS); + sc->stats.mpc += IGC_READ_REG(&sc->hw, IGC_MPC); + sc->stats.scc += IGC_READ_REG(&sc->hw, IGC_SCC); + sc->stats.ecol += IGC_READ_REG(&sc->hw, IGC_ECOL); + + sc->stats.mcc += IGC_READ_REG(&sc->hw, IGC_MCC); + sc->stats.latecol += IGC_READ_REG(&sc->hw, IGC_LATECOL); + sc->stats.colc += IGC_READ_REG(&sc->hw, IGC_COLC); + sc->stats.colc += IGC_READ_REG(&sc->hw, IGC_RERC); + sc->stats.dc += IGC_READ_REG(&sc->hw, IGC_DC); + sc->stats.rlec += IGC_READ_REG(&sc->hw, IGC_RLEC); + sc->stats.xonrxc += IGC_READ_REG(&sc->hw, IGC_XONRXC); + sc->stats.xontxc += IGC_READ_REG(&sc->hw, IGC_XONTXC); + sc->stats.xoffrxc += IGC_READ_REG(&sc->hw, IGC_XOFFRXC); /* * For watchdog management we need to know if we have been * paused during the last interval, so capture that here. */ - if (adapter->stats.xoffrxc != prev_xoffrxc) - adapter->shared->isc_pause_frames = 1; - adapter->stats.xofftxc += IGC_READ_REG(&adapter->hw, IGC_XOFFTXC); - adapter->stats.fcruc += IGC_READ_REG(&adapter->hw, IGC_FCRUC); - adapter->stats.prc64 += IGC_READ_REG(&adapter->hw, IGC_PRC64); - adapter->stats.prc127 += IGC_READ_REG(&adapter->hw, IGC_PRC127); - adapter->stats.prc255 += IGC_READ_REG(&adapter->hw, IGC_PRC255); - adapter->stats.prc511 += IGC_READ_REG(&adapter->hw, IGC_PRC511); - adapter->stats.prc1023 += IGC_READ_REG(&adapter->hw, IGC_PRC1023); - adapter->stats.prc1522 += IGC_READ_REG(&adapter->hw, IGC_PRC1522); - adapter->stats.tlpic += IGC_READ_REG(&adapter->hw, IGC_TLPIC); - adapter->stats.rlpic += IGC_READ_REG(&adapter->hw, IGC_RLPIC); - adapter->stats.gprc += IGC_READ_REG(&adapter->hw, IGC_GPRC); - adapter->stats.bprc += IGC_READ_REG(&adapter->hw, IGC_BPRC); - adapter->stats.mprc += IGC_READ_REG(&adapter->hw, IGC_MPRC); - adapter->stats.gptc += IGC_READ_REG(&adapter->hw, IGC_GPTC); + if (sc->stats.xoffrxc != prev_xoffrxc) + sc->shared->isc_pause_frames = 1; + sc->stats.xofftxc += IGC_READ_REG(&sc->hw, IGC_XOFFTXC); + sc->stats.fcruc += IGC_READ_REG(&sc->hw, IGC_FCRUC); + sc->stats.prc64 += IGC_READ_REG(&sc->hw, IGC_PRC64); + sc->stats.prc127 += IGC_READ_REG(&sc->hw, IGC_PRC127); + sc->stats.prc255 += IGC_READ_REG(&sc->hw, IGC_PRC255); + sc->stats.prc511 += IGC_READ_REG(&sc->hw, IGC_PRC511); + sc->stats.prc1023 += IGC_READ_REG(&sc->hw, IGC_PRC1023); + sc->stats.prc1522 += IGC_READ_REG(&sc->hw, IGC_PRC1522); + sc->stats.tlpic += IGC_READ_REG(&sc->hw, IGC_TLPIC); + sc->stats.rlpic += IGC_READ_REG(&sc->hw, IGC_RLPIC); + sc->stats.gprc += IGC_READ_REG(&sc->hw, IGC_GPRC); + sc->stats.bprc += IGC_READ_REG(&sc->hw, IGC_BPRC); + sc->stats.mprc += IGC_READ_REG(&sc->hw, IGC_MPRC); + sc->stats.gptc += IGC_READ_REG(&sc->hw, IGC_GPTC); /* For the 64-bit byte counters the low dword must be read first. */ /* Both registers clear on the read of the high dword */ - adapter->stats.gorc += IGC_READ_REG(&adapter->hw, IGC_GORCL) + - ((u64)IGC_READ_REG(&adapter->hw, IGC_GORCH) << 32); - adapter->stats.gotc += IGC_READ_REG(&adapter->hw, IGC_GOTCL) + - ((u64)IGC_READ_REG(&adapter->hw, IGC_GOTCH) << 32); - - adapter->stats.rnbc += IGC_READ_REG(&adapter->hw, IGC_RNBC); - adapter->stats.ruc += IGC_READ_REG(&adapter->hw, IGC_RUC); - adapter->stats.rfc += IGC_READ_REG(&adapter->hw, IGC_RFC); - adapter->stats.roc += IGC_READ_REG(&adapter->hw, IGC_ROC); - adapter->stats.rjc += IGC_READ_REG(&adapter->hw, IGC_RJC); - - adapter->stats.tor += IGC_READ_REG(&adapter->hw, IGC_TORH); - adapter->stats.tot += IGC_READ_REG(&adapter->hw, IGC_TOTH); - - adapter->stats.tpr += IGC_READ_REG(&adapter->hw, IGC_TPR); - adapter->stats.tpt += IGC_READ_REG(&adapter->hw, IGC_TPT); - adapter->stats.ptc64 += IGC_READ_REG(&adapter->hw, IGC_PTC64); - adapter->stats.ptc127 += IGC_READ_REG(&adapter->hw, IGC_PTC127); - adapter->stats.ptc255 += IGC_READ_REG(&adapter->hw, IGC_PTC255); - adapter->stats.ptc511 += IGC_READ_REG(&adapter->hw, IGC_PTC511); - adapter->stats.ptc1023 += IGC_READ_REG(&adapter->hw, IGC_PTC1023); - adapter->stats.ptc1522 += IGC_READ_REG(&adapter->hw, IGC_PTC1522); - adapter->stats.mptc += IGC_READ_REG(&adapter->hw, IGC_MPTC); - adapter->stats.bptc += IGC_READ_REG(&adapter->hw, IGC_BPTC); + sc->stats.gorc += IGC_READ_REG(&sc->hw, IGC_GORCL) + + ((u64)IGC_READ_REG(&sc->hw, IGC_GORCH) << 32); + sc->stats.gotc += IGC_READ_REG(&sc->hw, IGC_GOTCL) + + ((u64)IGC_READ_REG(&sc->hw, IGC_GOTCH) << 32); + + sc->stats.rnbc += IGC_READ_REG(&sc->hw, IGC_RNBC); + sc->stats.ruc += IGC_READ_REG(&sc->hw, IGC_RUC); + sc->stats.rfc += IGC_READ_REG(&sc->hw, IGC_RFC); + sc->stats.roc += IGC_READ_REG(&sc->hw, IGC_ROC); + sc->stats.rjc += IGC_READ_REG(&sc->hw, IGC_RJC); + + sc->stats.mgprc += IGC_READ_REG(&sc->hw, IGC_MGTPRC); + sc->stats.mgpdc += IGC_READ_REG(&sc->hw, IGC_MGTPDC); + sc->stats.mgptc += IGC_READ_REG(&sc->hw, IGC_MGTPTC); + + sc->stats.tor += IGC_READ_REG(&sc->hw, IGC_TORH); + sc->stats.tot += IGC_READ_REG(&sc->hw, IGC_TOTH); + + sc->stats.tpr += IGC_READ_REG(&sc->hw, IGC_TPR); + sc->stats.tpt += IGC_READ_REG(&sc->hw, IGC_TPT); + sc->stats.ptc64 += IGC_READ_REG(&sc->hw, IGC_PTC64); + sc->stats.ptc127 += IGC_READ_REG(&sc->hw, IGC_PTC127); + sc->stats.ptc255 += IGC_READ_REG(&sc->hw, IGC_PTC255); + sc->stats.ptc511 += IGC_READ_REG(&sc->hw, IGC_PTC511); + sc->stats.ptc1023 += IGC_READ_REG(&sc->hw, IGC_PTC1023); + sc->stats.ptc1522 += IGC_READ_REG(&sc->hw, IGC_PTC1522); + sc->stats.mptc += IGC_READ_REG(&sc->hw, IGC_MPTC); + sc->stats.bptc += IGC_READ_REG(&sc->hw, IGC_BPTC); /* Interrupt Counts */ - adapter->stats.iac += IGC_READ_REG(&adapter->hw, IGC_IAC); - adapter->stats.rxdmtc += IGC_READ_REG(&adapter->hw, IGC_RXDMTC); + sc->stats.iac += IGC_READ_REG(&sc->hw, IGC_IAC); + sc->stats.rxdmtc += IGC_READ_REG(&sc->hw, IGC_RXDMTC); - adapter->stats.algnerrc += IGC_READ_REG(&adapter->hw, IGC_ALGNERRC); - adapter->stats.tncrs += IGC_READ_REG(&adapter->hw, IGC_TNCRS); - adapter->stats.htdpmc += IGC_READ_REG(&adapter->hw, IGC_HTDPMC); - adapter->stats.tsctc += IGC_READ_REG(&adapter->hw, IGC_TSCTC); + sc->stats.algnerrc += IGC_READ_REG(&sc->hw, IGC_ALGNERRC); + sc->stats.tncrs += IGC_READ_REG(&sc->hw, IGC_TNCRS); + sc->stats.htdpmc += IGC_READ_REG(&sc->hw, IGC_HTDPMC); + sc->stats.tsctc += IGC_READ_REG(&sc->hw, IGC_TSCTC); } static uint64_t igc_if_get_counter(if_ctx_t ctx, ift_counter cnt) { - struct igc_adapter *adapter = iflib_get_softc(ctx); + struct igc_softc *sc = iflib_get_softc(ctx); if_t ifp = iflib_get_ifp(ctx); switch (cnt) { case IFCOUNTER_COLLISIONS: - return (adapter->stats.colc); + return (sc->stats.colc); case IFCOUNTER_IERRORS: - return (adapter->dropped_pkts + adapter->stats.rxerrc + - adapter->stats.crcerrs + adapter->stats.algnerrc + - adapter->stats.ruc + adapter->stats.roc + - adapter->stats.mpc + adapter->stats.htdpmc); + return (sc->dropped_pkts + sc->stats.rxerrc + + sc->stats.crcerrs + sc->stats.algnerrc + + sc->stats.ruc + sc->stats.roc + + sc->stats.mpc + sc->stats.htdpmc); case IFCOUNTER_OERRORS: - return (adapter->stats.ecol + adapter->stats.latecol + - adapter->watchdog_events); + return (sc->stats.ecol + sc->stats.latecol + + sc->watchdog_events); default: return (if_get_counter_default(ifp, cnt)); } @@ -2411,28 +2628,62 @@ igc_if_needs_restart(if_ctx_t ctx __unused, enum iflib_restart_event event) static int igc_sysctl_reg_handler(SYSCTL_HANDLER_ARGS) { - struct igc_adapter *adapter; + struct igc_softc *sc; u_int val; - adapter = oidp->oid_arg1; - val = IGC_READ_REG(&adapter->hw, oidp->oid_arg2); + sc = oidp->oid_arg1; + val = IGC_READ_REG(&sc->hw, oidp->oid_arg2); return (sysctl_handle_int(oidp, &val, 0, req)); } +/* Per queue holdoff interrupt rate handler */ +static int +igc_sysctl_interrupt_rate_handler(SYSCTL_HANDLER_ARGS) +{ + struct igc_rx_queue *rque; + struct igc_tx_queue *tque; + struct igc_hw *hw; + int error; + u32 reg, usec, rate; + + bool tx = oidp->oid_arg2; + + if (tx) { + tque = oidp->oid_arg1; + hw = &tque->sc->hw; + reg = IGC_READ_REG(hw, IGC_EITR(tque->me)); + } else { + rque = oidp->oid_arg1; + hw = &rque->sc->hw; + reg = IGC_READ_REG(hw, IGC_EITR(rque->msix)); + } + + usec = (reg & IGC_QVECTOR_MASK); + if (usec > 0) + rate = IGC_INTS_TO_EITR(usec); + else + rate = 0; + + error = sysctl_handle_int(oidp, &rate, 0, req); + if (error || !req->newptr) + return error; + return 0; +} + /* * Add sysctl variables, one per statistic, to the system. */ static void -igc_add_hw_stats(struct igc_adapter *adapter) +igc_add_hw_stats(struct igc_softc *sc) { - device_t dev = iflib_get_dev(adapter->ctx); - struct igc_tx_queue *tx_que = adapter->tx_queues; - struct igc_rx_queue *rx_que = adapter->rx_queues; + device_t dev = iflib_get_dev(sc->ctx); + struct igc_tx_queue *tx_que = sc->tx_queues; + struct igc_rx_queue *rx_que = sc->rx_queues; struct sysctl_ctx_list *ctx = device_get_sysctl_ctx(dev); struct sysctl_oid *tree = device_get_sysctl_tree(dev); struct sysctl_oid_list *child = SYSCTL_CHILDREN(tree); - struct igc_hw_stats *stats = &adapter->stats; + struct igc_hw_stats *stats = &sc->stats; struct sysctl_oid *stat_node, *queue_node, *int_node; struct sysctl_oid_list *stat_list, *queue_list, *int_list; @@ -2442,228 +2693,339 @@ igc_add_hw_stats(struct igc_adapter *adapter) /* Driver Statistics */ SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "dropped", - CTLFLAG_RD, &adapter->dropped_pkts, - "Driver dropped packets"); + CTLFLAG_RD, &sc->dropped_pkts, + "Driver dropped packets"); SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "link_irq", - CTLFLAG_RD, &adapter->link_irq, - "Link MSI-X IRQ Handled"); + CTLFLAG_RD, &sc->link_irq, + "Link MSI-X IRQ Handled"); SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "rx_overruns", - CTLFLAG_RD, &adapter->rx_overruns, - "RX overruns"); + CTLFLAG_RD, &sc->rx_overruns, + "RX overruns"); SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "watchdog_timeouts", - CTLFLAG_RD, &adapter->watchdog_events, - "Watchdog timeouts"); + CTLFLAG_RD, &sc->watchdog_events, + "Watchdog timeouts"); SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "device_control", CTLTYPE_UINT | CTLFLAG_RD | CTLFLAG_NEEDGIANT, - adapter, IGC_CTRL, igc_sysctl_reg_handler, "IU", + sc, IGC_CTRL, igc_sysctl_reg_handler, "IU", "Device Control Register"); SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "rx_control", CTLTYPE_UINT | CTLFLAG_RD | CTLFLAG_NEEDGIANT, - adapter, IGC_RCTL, igc_sysctl_reg_handler, "IU", + sc, IGC_RCTL, igc_sysctl_reg_handler, "IU", "Receiver Control Register"); SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "fc_high_water", - CTLFLAG_RD, &adapter->hw.fc.high_water, 0, - "Flow Control High Watermark"); + CTLFLAG_RD, &sc->hw.fc.high_water, 0, + "Flow Control High Watermark"); SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "fc_low_water", - CTLFLAG_RD, &adapter->hw.fc.low_water, 0, - "Flow Control Low Watermark"); + CTLFLAG_RD, &sc->hw.fc.low_water, 0, + "Flow Control Low Watermark"); - for (int i = 0; i < adapter->tx_num_queues; i++, tx_que++) { + for (int i = 0; i < sc->tx_num_queues; i++, tx_que++) { struct tx_ring *txr = &tx_que->txr; snprintf(namebuf, QUEUE_NAME_LEN, "queue_tx_%d", i); queue_node = SYSCTL_ADD_NODE(ctx, child, OID_AUTO, namebuf, CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, "TX Queue Name"); queue_list = SYSCTL_CHILDREN(queue_node); + SYSCTL_ADD_PROC(ctx, queue_list, OID_AUTO, "interrupt_rate", + CTLTYPE_UINT | CTLFLAG_RD, tx_que, + true, igc_sysctl_interrupt_rate_handler, "IU", + "Interrupt Rate"); SYSCTL_ADD_PROC(ctx, queue_list, OID_AUTO, "txd_head", - CTLTYPE_UINT | CTLFLAG_RD | CTLFLAG_NEEDGIANT, adapter, + CTLTYPE_UINT | CTLFLAG_RD | CTLFLAG_NEEDGIANT, sc, IGC_TDH(txr->me), igc_sysctl_reg_handler, "IU", "Transmit Descriptor Head"); SYSCTL_ADD_PROC(ctx, queue_list, OID_AUTO, "txd_tail", - CTLTYPE_UINT | CTLFLAG_RD | CTLFLAG_NEEDGIANT, adapter, + CTLTYPE_UINT | CTLFLAG_RD | CTLFLAG_NEEDGIANT, sc, IGC_TDT(txr->me), igc_sysctl_reg_handler, "IU", "Transmit Descriptor Tail"); SYSCTL_ADD_ULONG(ctx, queue_list, OID_AUTO, "tx_irq", - CTLFLAG_RD, &txr->tx_irq, - "Queue MSI-X Transmit Interrupts"); + CTLFLAG_RD, &txr->tx_irq, + "Queue MSI-X Transmit Interrupts"); } - for (int j = 0; j < adapter->rx_num_queues; j++, rx_que++) { + for (int j = 0; j < sc->rx_num_queues; j++, rx_que++) { struct rx_ring *rxr = &rx_que->rxr; snprintf(namebuf, QUEUE_NAME_LEN, "queue_rx_%d", j); queue_node = SYSCTL_ADD_NODE(ctx, child, OID_AUTO, namebuf, CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, "RX Queue Name"); queue_list = SYSCTL_CHILDREN(queue_node); + SYSCTL_ADD_PROC(ctx, queue_list, OID_AUTO, "interrupt_rate", + CTLTYPE_UINT | CTLFLAG_RD, rx_que, + false, igc_sysctl_interrupt_rate_handler, "IU", + "Interrupt Rate"); SYSCTL_ADD_PROC(ctx, queue_list, OID_AUTO, "rxd_head", - CTLTYPE_UINT | CTLFLAG_RD | CTLFLAG_NEEDGIANT, adapter, + CTLTYPE_UINT | CTLFLAG_RD | CTLFLAG_NEEDGIANT, sc, IGC_RDH(rxr->me), igc_sysctl_reg_handler, "IU", "Receive Descriptor Head"); SYSCTL_ADD_PROC(ctx, queue_list, OID_AUTO, "rxd_tail", - CTLTYPE_UINT | CTLFLAG_RD | CTLFLAG_NEEDGIANT, adapter, + CTLTYPE_UINT | CTLFLAG_RD | CTLFLAG_NEEDGIANT, sc, IGC_RDT(rxr->me), igc_sysctl_reg_handler, "IU", "Receive Descriptor Tail"); SYSCTL_ADD_ULONG(ctx, queue_list, OID_AUTO, "rx_irq", - CTLFLAG_RD, &rxr->rx_irq, - "Queue MSI-X Receive Interrupts"); + CTLFLAG_RD, &rxr->rx_irq, + "Queue MSI-X Receive Interrupts"); } /* MAC stats get their own sub node */ - stat_node = SYSCTL_ADD_NODE(ctx, child, OID_AUTO, "mac_stats", CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, "Statistics"); stat_list = SYSCTL_CHILDREN(stat_node); SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "excess_coll", - CTLFLAG_RD, &stats->ecol, - "Excessive collisions"); + CTLFLAG_RD, &stats->ecol, + "Excessive collisions"); SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "single_coll", - CTLFLAG_RD, &stats->scc, - "Single collisions"); + CTLFLAG_RD, &stats->scc, + "Single collisions"); SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "multiple_coll", - CTLFLAG_RD, &stats->mcc, - "Multiple collisions"); + CTLFLAG_RD, &stats->mcc, + "Multiple collisions"); SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "late_coll", - CTLFLAG_RD, &stats->latecol, - "Late collisions"); + CTLFLAG_RD, &stats->latecol, + "Late collisions"); SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "collision_count", - CTLFLAG_RD, &stats->colc, - "Collision Count"); + CTLFLAG_RD, &stats->colc, + "Collision Count"); SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "symbol_errors", - CTLFLAG_RD, &adapter->stats.symerrs, - "Symbol Errors"); + CTLFLAG_RD, &sc->stats.symerrs, + "Symbol Errors"); SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "sequence_errors", - CTLFLAG_RD, &adapter->stats.sec, - "Sequence Errors"); + CTLFLAG_RD, &sc->stats.sec, + "Sequence Errors"); SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "defer_count", - CTLFLAG_RD, &adapter->stats.dc, - "Defer Count"); + CTLFLAG_RD, &sc->stats.dc, + "Defer Count"); SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "missed_packets", - CTLFLAG_RD, &adapter->stats.mpc, - "Missed Packets"); + CTLFLAG_RD, &sc->stats.mpc, + "Missed Packets"); + SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "recv_length_errors", + CTLFLAG_RD, &sc->stats.rlec, + "Receive Length Errors"); SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "recv_no_buff", - CTLFLAG_RD, &adapter->stats.rnbc, - "Receive No Buffers"); + CTLFLAG_RD, &sc->stats.rnbc, + "Receive No Buffers"); SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "recv_undersize", - CTLFLAG_RD, &adapter->stats.ruc, - "Receive Undersize"); + CTLFLAG_RD, &sc->stats.ruc, + "Receive Undersize"); SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "recv_fragmented", - CTLFLAG_RD, &adapter->stats.rfc, - "Fragmented Packets Received "); + CTLFLAG_RD, &sc->stats.rfc, + "Fragmented Packets Received "); SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "recv_oversize", - CTLFLAG_RD, &adapter->stats.roc, - "Oversized Packets Received"); + CTLFLAG_RD, &sc->stats.roc, + "Oversized Packets Received"); SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "recv_jabber", - CTLFLAG_RD, &adapter->stats.rjc, - "Recevied Jabber"); + CTLFLAG_RD, &sc->stats.rjc, + "Recevied Jabber"); SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "recv_errs", - CTLFLAG_RD, &adapter->stats.rxerrc, - "Receive Errors"); + CTLFLAG_RD, &sc->stats.rxerrc, + "Receive Errors"); SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "crc_errs", - CTLFLAG_RD, &adapter->stats.crcerrs, - "CRC errors"); + CTLFLAG_RD, &sc->stats.crcerrs, + "CRC errors"); SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "alignment_errs", - CTLFLAG_RD, &adapter->stats.algnerrc, - "Alignment Errors"); + CTLFLAG_RD, &sc->stats.algnerrc, + "Alignment Errors"); SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "xon_recvd", - CTLFLAG_RD, &adapter->stats.xonrxc, - "XON Received"); + CTLFLAG_RD, &sc->stats.xonrxc, + "XON Received"); SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "xon_txd", - CTLFLAG_RD, &adapter->stats.xontxc, - "XON Transmitted"); + CTLFLAG_RD, &sc->stats.xontxc, + "XON Transmitted"); SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "xoff_recvd", - CTLFLAG_RD, &adapter->stats.xoffrxc, - "XOFF Received"); + CTLFLAG_RD, &sc->stats.xoffrxc, + "XOFF Received"); SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "xoff_txd", - CTLFLAG_RD, &adapter->stats.xofftxc, - "XOFF Transmitted"); + CTLFLAG_RD, &sc->stats.xofftxc, + "XOFF Transmitted"); + SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "unsupported_fc_recvd", + CTLFLAG_RD, &sc->stats.fcruc, + "Unsupported Flow Control Received"); + SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "mgmt_pkts_recvd", + CTLFLAG_RD, &sc->stats.mgprc, + "Management Packets Received"); + SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "mgmt_pkts_drop", + CTLFLAG_RD, &sc->stats.mgpdc, + "Management Packets Dropped"); + SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "mgmt_pkts_txd", + CTLFLAG_RD, &sc->stats.mgptc, + "Management Packets Transmitted"); /* Packet Reception Stats */ SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "total_pkts_recvd", - CTLFLAG_RD, &adapter->stats.tpr, - "Total Packets Received "); + CTLFLAG_RD, &sc->stats.tpr, + "Total Packets Received "); SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "good_pkts_recvd", - CTLFLAG_RD, &adapter->stats.gprc, - "Good Packets Received"); + CTLFLAG_RD, &sc->stats.gprc, + "Good Packets Received"); SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "bcast_pkts_recvd", - CTLFLAG_RD, &adapter->stats.bprc, - "Broadcast Packets Received"); + CTLFLAG_RD, &sc->stats.bprc, + "Broadcast Packets Received"); SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "mcast_pkts_recvd", - CTLFLAG_RD, &adapter->stats.mprc, - "Multicast Packets Received"); + CTLFLAG_RD, &sc->stats.mprc, + "Multicast Packets Received"); SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_frames_64", - CTLFLAG_RD, &adapter->stats.prc64, - "64 byte frames received "); + CTLFLAG_RD, &sc->stats.prc64, + "64 byte frames received "); SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_frames_65_127", - CTLFLAG_RD, &adapter->stats.prc127, - "65-127 byte frames received"); + CTLFLAG_RD, &sc->stats.prc127, + "65-127 byte frames received"); SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_frames_128_255", - CTLFLAG_RD, &adapter->stats.prc255, - "128-255 byte frames received"); + CTLFLAG_RD, &sc->stats.prc255, + "128-255 byte frames received"); SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_frames_256_511", - CTLFLAG_RD, &adapter->stats.prc511, - "256-511 byte frames received"); + CTLFLAG_RD, &sc->stats.prc511, + "256-511 byte frames received"); SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_frames_512_1023", - CTLFLAG_RD, &adapter->stats.prc1023, - "512-1023 byte frames received"); + CTLFLAG_RD, &sc->stats.prc1023, + "512-1023 byte frames received"); SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_frames_1024_1522", - CTLFLAG_RD, &adapter->stats.prc1522, - "1023-1522 byte frames received"); + CTLFLAG_RD, &sc->stats.prc1522, + "1023-1522 byte frames received"); SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "good_octets_recvd", - CTLFLAG_RD, &adapter->stats.gorc, - "Good Octets Received"); + CTLFLAG_RD, &sc->stats.gorc, + "Good Octets Received"); /* Packet Transmission Stats */ SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "good_octets_txd", - CTLFLAG_RD, &adapter->stats.gotc, - "Good Octets Transmitted"); + CTLFLAG_RD, &sc->stats.gotc, + "Good Octets Transmitted"); SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "total_pkts_txd", - CTLFLAG_RD, &adapter->stats.tpt, - "Total Packets Transmitted"); + CTLFLAG_RD, &sc->stats.tpt, + "Total Packets Transmitted"); SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "good_pkts_txd", - CTLFLAG_RD, &adapter->stats.gptc, - "Good Packets Transmitted"); + CTLFLAG_RD, &sc->stats.gptc, + "Good Packets Transmitted"); SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "bcast_pkts_txd", - CTLFLAG_RD, &adapter->stats.bptc, - "Broadcast Packets Transmitted"); + CTLFLAG_RD, &sc->stats.bptc, + "Broadcast Packets Transmitted"); SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "mcast_pkts_txd", - CTLFLAG_RD, &adapter->stats.mptc, - "Multicast Packets Transmitted"); + CTLFLAG_RD, &sc->stats.mptc, + "Multicast Packets Transmitted"); SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "tx_frames_64", - CTLFLAG_RD, &adapter->stats.ptc64, - "64 byte frames transmitted "); + CTLFLAG_RD, &sc->stats.ptc64, + "64 byte frames transmitted "); SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "tx_frames_65_127", - CTLFLAG_RD, &adapter->stats.ptc127, - "65-127 byte frames transmitted"); + CTLFLAG_RD, &sc->stats.ptc127, + "65-127 byte frames transmitted"); SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "tx_frames_128_255", - CTLFLAG_RD, &adapter->stats.ptc255, - "128-255 byte frames transmitted"); + CTLFLAG_RD, &sc->stats.ptc255, + "128-255 byte frames transmitted"); SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "tx_frames_256_511", - CTLFLAG_RD, &adapter->stats.ptc511, - "256-511 byte frames transmitted"); + CTLFLAG_RD, &sc->stats.ptc511, + "256-511 byte frames transmitted"); SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "tx_frames_512_1023", - CTLFLAG_RD, &adapter->stats.ptc1023, - "512-1023 byte frames transmitted"); + CTLFLAG_RD, &sc->stats.ptc1023, + "512-1023 byte frames transmitted"); SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "tx_frames_1024_1522", - CTLFLAG_RD, &adapter->stats.ptc1522, - "1024-1522 byte frames transmitted"); + CTLFLAG_RD, &sc->stats.ptc1522, + "1024-1522 byte frames transmitted"); SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "tso_txd", - CTLFLAG_RD, &adapter->stats.tsctc, - "TSO Contexts Transmitted"); + CTLFLAG_RD, &sc->stats.tsctc, + "TSO Contexts Transmitted"); /* Interrupt Stats */ - int_node = SYSCTL_ADD_NODE(ctx, child, OID_AUTO, "interrupts", CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, "Interrupt Statistics"); int_list = SYSCTL_CHILDREN(int_node); SYSCTL_ADD_UQUAD(ctx, int_list, OID_AUTO, "asserts", - CTLFLAG_RD, &adapter->stats.iac, - "Interrupt Assertion Count"); + CTLFLAG_RD, &sc->stats.iac, + "Interrupt Assertion Count"); SYSCTL_ADD_UQUAD(ctx, int_list, OID_AUTO, "rx_desc_min_thresh", - CTLFLAG_RD, &adapter->stats.rxdmtc, - "Rx Desc Min Thresh Count"); + CTLFLAG_RD, &sc->stats.rxdmtc, + "Rx Desc Min Thresh Count"); +} + +static void +igc_fw_version(struct igc_softc *sc) +{ + struct igc_hw *hw = &sc->hw; + struct igc_fw_version *fw_ver = &sc->fw_ver; + + *fw_ver = (struct igc_fw_version){0}; + + igc_get_fw_version(hw, fw_ver); +} + +static void +igc_sbuf_fw_version(struct igc_fw_version *fw_ver, struct sbuf *buf) +{ + const char *space = ""; + + if (fw_ver->eep_major || fw_ver->eep_minor || fw_ver->eep_build) { + sbuf_printf(buf, "EEPROM V%d.%d-%d", fw_ver->eep_major, + fw_ver->eep_minor, fw_ver->eep_build); + space = " "; + } + + if (fw_ver->invm_major || fw_ver->invm_minor || + fw_ver->invm_img_type) { + sbuf_printf(buf, "%sNVM V%d.%d imgtype%d", + space, fw_ver->invm_major, fw_ver->invm_minor, + fw_ver->invm_img_type); + space = " "; + } + + if (fw_ver->or_valid) { + sbuf_printf(buf, "%sOption ROM V%d-b%d-p%d", + space, fw_ver->or_major, fw_ver->or_build, + fw_ver->or_patch); + space = " "; + } + + if (fw_ver->etrack_id) + sbuf_printf(buf, "%seTrack 0x%08x", space, fw_ver->etrack_id); +} + +static void +igc_print_fw_version(struct igc_softc *sc ) +{ + device_t dev = sc->dev; + struct sbuf *buf; + int error = 0; + + buf = sbuf_new_auto(); + if (!buf) { + device_printf(dev, "Could not allocate sbuf for output.\n"); + return; + } + + igc_sbuf_fw_version(&sc->fw_ver, buf); + + error = sbuf_finish(buf); + if (error) + device_printf(dev, "Error finishing sbuf: %d\n", error); + else if (sbuf_len(buf)) + device_printf(dev, "%s\n", sbuf_data(buf)); + + sbuf_delete(buf); +} + +static int +igc_sysctl_print_fw_version(SYSCTL_HANDLER_ARGS) +{ + struct igc_softc *sc = (struct igc_softc *)arg1; + device_t dev = sc->dev; + struct sbuf *buf; + int error = 0; + + buf = sbuf_new_for_sysctl(NULL, NULL, 128, req); + if (!buf) { + device_printf(dev, "Could not allocate sbuf for output.\n"); + return (ENOMEM); + } + + igc_sbuf_fw_version(&sc->fw_ver, buf); + + error = sbuf_finish(buf); + if (error) + device_printf(dev, "Error finishing sbuf: %d\n", error); + + sbuf_delete(buf); + + return (0); } /********************************************************************** @@ -2676,7 +3038,7 @@ igc_add_hw_stats(struct igc_adapter *adapter) static int igc_sysctl_nvm_info(SYSCTL_HANDLER_ARGS) { - struct igc_adapter *adapter = (struct igc_adapter *)arg1; + struct igc_softc *sc = (struct igc_softc *)arg1; int error; int result; @@ -2692,13 +3054,13 @@ igc_sysctl_nvm_info(SYSCTL_HANDLER_ARGS) * the screen. */ if (result == 1) - igc_print_nvm_info(adapter); + igc_print_nvm_info(sc); return (error); } static void -igc_print_nvm_info(struct igc_adapter *adapter) +igc_print_nvm_info(struct igc_softc *sc) { u16 eeprom_data; int i, j, row = 0; @@ -2711,67 +3073,49 @@ igc_print_nvm_info(struct igc_adapter *adapter) j = 0; ++row; printf("\n0x00%x0 ",row); } - igc_read_nvm(&adapter->hw, i, 1, &eeprom_data); + igc_read_nvm(&sc->hw, i, 1, &eeprom_data); printf("%04x ", eeprom_data); } printf("\n"); } static int -igc_sysctl_int_delay(SYSCTL_HANDLER_ARGS) +igc_sysctl_tso_tcp_flags_mask(SYSCTL_HANDLER_ARGS) { - struct igc_int_delay_info *info; - struct igc_adapter *adapter; - u32 regval; - int error, usecs, ticks; + struct igc_softc *sc; + u32 reg, val, shift; + int error, mask; - info = (struct igc_int_delay_info *) arg1; - usecs = info->value; - error = sysctl_handle_int(oidp, &usecs, 0, req); - if (error != 0 || req->newptr == NULL) - return (error); - if (usecs < 0 || usecs > IGC_TICKS_TO_USECS(65535)) - return (EINVAL); - info->value = usecs; - ticks = IGC_USECS_TO_TICKS(usecs); - if (info->offset == IGC_ITR) /* units are 256ns here */ - ticks *= 4; - - adapter = info->adapter; - - regval = IGC_READ_OFFSET(&adapter->hw, info->offset); - regval = (regval & ~0xffff) | (ticks & 0xffff); - /* Handle a few special cases. */ - switch (info->offset) { - case IGC_RDTR: + sc = oidp->oid_arg1; + switch (oidp->oid_arg2) { + case 0: + reg = IGC_DTXTCPFLGL; + shift = 0; break; - case IGC_TIDV: - if (ticks == 0) { - adapter->txd_cmd &= ~IGC_TXD_CMD_IDE; - /* Don't write 0 into the TIDV register. */ - regval++; - } else - adapter->txd_cmd |= IGC_TXD_CMD_IDE; + case 1: + reg = IGC_DTXTCPFLGL; + shift = 16; + break; + case 2: + reg = IGC_DTXTCPFLGH; + shift = 0; + break; + default: + return (EINVAL); break; } - IGC_WRITE_OFFSET(&adapter->hw, info->offset, regval); + val = IGC_READ_REG(&sc->hw, reg); + mask = (val >> shift) & 0xfff; + error = sysctl_handle_int(oidp, &mask, 0, req); + if (error != 0 || req->newptr == NULL) + return (error); + if (mask < 0 || mask > 0xfff) + return (EINVAL); + val = (val & ~(0xfff << shift)) | (mask << shift); + IGC_WRITE_REG(&sc->hw, reg, val); return (0); } -static void -igc_add_int_delay_sysctl(struct igc_adapter *adapter, const char *name, - const char *description, struct igc_int_delay_info *info, - int offset, int value) -{ - info->adapter = adapter; - info->offset = offset; - info->value = value; - SYSCTL_ADD_PROC(device_get_sysctl_ctx(adapter->dev), - SYSCTL_CHILDREN(device_get_sysctl_tree(adapter->dev)), - OID_AUTO, name, CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NEEDGIANT, - info, 0, igc_sysctl_int_delay, "I", description); -} - /* * Set flow control using sysctl: * Flow control values: @@ -2785,14 +3129,14 @@ igc_set_flowcntl(SYSCTL_HANDLER_ARGS) { int error; static int input = 3; /* default is full */ - struct igc_adapter *adapter = (struct igc_adapter *) arg1; + struct igc_softc *sc = (struct igc_softc *) arg1; error = sysctl_handle_int(oidp, &input, 0, req); if ((error) || (req->newptr == NULL)) return (error); - if (input == adapter->fc) /* no change? */ + if (input == sc->fc) /* no change? */ return (error); switch (input) { @@ -2800,16 +3144,65 @@ igc_set_flowcntl(SYSCTL_HANDLER_ARGS) case igc_fc_tx_pause: case igc_fc_full: case igc_fc_none: - adapter->hw.fc.requested_mode = input; - adapter->fc = input; + sc->hw.fc.requested_mode = input; + sc->fc = input; break; default: /* Do nothing */ return (error); } - adapter->hw.fc.current_mode = adapter->hw.fc.requested_mode; - igc_force_mac_fc(&adapter->hw); + sc->hw.fc.current_mode = sc->hw.fc.requested_mode; + igc_force_mac_fc(&sc->hw); + return (error); +} + +/* + * Manage DMA Coalesce: + * Control values: + * 0/1 - off/on + * Legal timer values are: + * 250,500,1000-10000 in thousands + */ +static int +igc_sysctl_dmac(SYSCTL_HANDLER_ARGS) +{ + struct igc_softc *sc = (struct igc_softc *) arg1; + int error; + + error = sysctl_handle_int(oidp, &sc->dmac, 0, req); + + if ((error) || (req->newptr == NULL)) + return (error); + + switch (sc->dmac) { + case 0: + /* Disabling */ + break; + case 1: /* Just enable and use default */ + sc->dmac = 1000; + break; + case 250: + case 500: + case 1000: + case 2000: + case 3000: + case 4000: + case 5000: + case 6000: + case 7000: + case 8000: + case 9000: + case 10000: + /* Legal values - allow */ + break; + default: + /* Do nothing, illegal value */ + sc->dmac = 0; + return (EINVAL); + } + /* Reinit the interface */ + igc_if_init(sc->ctx); return (error); } @@ -2821,16 +3214,16 @@ igc_set_flowcntl(SYSCTL_HANDLER_ARGS) static int igc_sysctl_eee(SYSCTL_HANDLER_ARGS) { - struct igc_adapter *adapter = (struct igc_adapter *) arg1; + struct igc_softc *sc = (struct igc_softc *) arg1; int error, value; - value = adapter->hw.dev_spec._i225.eee_disable; + value = sc->hw.dev_spec._i225.eee_disable; error = sysctl_handle_int(oidp, &value, 0, req); if (error || req->newptr == NULL) return (error); - adapter->hw.dev_spec._i225.eee_disable = (value != 0); - igc_if_init(adapter->ctx); + sc->hw.dev_spec._i225.eee_disable = (value != 0); + igc_if_init(sc->ctx); return (0); } @@ -2838,7 +3231,7 @@ igc_sysctl_eee(SYSCTL_HANDLER_ARGS) static int igc_sysctl_debug_info(SYSCTL_HANDLER_ARGS) { - struct igc_adapter *adapter; + struct igc_softc *sc; int error; int result; @@ -2849,8 +3242,8 @@ igc_sysctl_debug_info(SYSCTL_HANDLER_ARGS) return (error); if (result == 1) { - adapter = (struct igc_adapter *) arg1; - igc_print_debug_info(adapter); + sc = (struct igc_softc *) arg1; + igc_print_debug_info(sc); } return (error); @@ -2859,7 +3252,7 @@ igc_sysctl_debug_info(SYSCTL_HANDLER_ARGS) static int igc_get_rs(SYSCTL_HANDLER_ARGS) { - struct igc_adapter *adapter = (struct igc_adapter *) arg1; + struct igc_softc *sc = (struct igc_softc *) arg1; int error; int result; @@ -2868,7 +3261,7 @@ igc_get_rs(SYSCTL_HANDLER_ARGS) if (error || !req->newptr || result != 1) return (error); - igc_dump_rs(adapter); + igc_dump_rs(sc); return (error); } @@ -2884,12 +3277,12 @@ igc_if_debug(if_ctx_t ctx) * needed for debugging a problem. -jfv */ static void -igc_print_debug_info(struct igc_adapter *adapter) +igc_print_debug_info(struct igc_softc *sc) { - device_t dev = iflib_get_dev(adapter->ctx); - if_t ifp = iflib_get_ifp(adapter->ctx); - struct tx_ring *txr = &adapter->tx_queues->txr; - struct rx_ring *rxr = &adapter->rx_queues->rxr; + device_t dev = iflib_get_dev(sc->ctx); + if_t ifp = iflib_get_ifp(sc->ctx); + struct tx_ring *txr = &sc->tx_queues->txr; + struct rx_ring *rxr = &sc->rx_queues->rxr; if (if_getdrvflags(ifp) & IFF_DRV_RUNNING) printf("Interface is RUNNING "); @@ -2901,17 +3294,17 @@ igc_print_debug_info(struct igc_adapter *adapter) else printf("and ACTIVE\n"); - for (int i = 0; i < adapter->tx_num_queues; i++, txr++) { + for (int i = 0; i < sc->tx_num_queues; i++, txr++) { device_printf(dev, "TX Queue %d ------\n", i); device_printf(dev, "hw tdh = %d, hw tdt = %d\n", - IGC_READ_REG(&adapter->hw, IGC_TDH(i)), - IGC_READ_REG(&adapter->hw, IGC_TDT(i))); + IGC_READ_REG(&sc->hw, IGC_TDH(i)), + IGC_READ_REG(&sc->hw, IGC_TDT(i))); } - for (int j=0; j < adapter->rx_num_queues; j++, rxr++) { + for (int j=0; j < sc->rx_num_queues; j++, rxr++) { device_printf(dev, "RX Queue %d ------\n", j); device_printf(dev, "hw rdh = %d, hw rdt = %d\n", - IGC_READ_REG(&adapter->hw, IGC_RDH(j)), - IGC_READ_REG(&adapter->hw, IGC_RDT(j))); + IGC_READ_REG(&sc->hw, IGC_RDH(j)), + IGC_READ_REG(&sc->hw, IGC_RDT(j))); } } diff --git a/sys/dev/igc/if_igc.h b/sys/dev/igc/if_igc.h index 0c22ce9f76f4..236a16c4add3 100644 --- a/sys/dev/igc/if_igc.h +++ b/sys/dev/igc/if_igc.h @@ -1,9 +1,9 @@ /*- * SPDX-License-Identifier: BSD-2-Clause * + * Copyright (c) 2001-2024, Intel Corporation * Copyright (c) 2016 Nicole Graziano <nicole@nextbsd.org> - * All rights reserved. - * Copyright (c) 2021 Rubicon Communications, LLC (Netgate) + * Copyright (c) 2021-2024 Rubicon Communications, LLC (Netgate) * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -132,65 +132,6 @@ #define IGC_MAX_RXD 4096 /* - * IGC_TIDV_VAL - Transmit Interrupt Delay Value - * Valid Range: 0-65535 (0=off) - * Default Value: 64 - * This value delays the generation of transmit interrupts in units of - * 1.024 microseconds. Transmit interrupt reduction can improve CPU - * efficiency if properly tuned for specific network traffic. If the - * system is reporting dropped transmits, this value may be set too high - * causing the driver to run out of available transmit descriptors. - */ -#define IGC_TIDV_VAL 64 - -/* - * IGC_TADV_VAL - Transmit Absolute Interrupt Delay Value - * Valid Range: 0-65535 (0=off) - * Default Value: 64 - * This value, in units of 1.024 microseconds, limits the delay in which a - * transmit interrupt is generated. Useful only if IGC_TIDV is non-zero, - * this value ensures that an interrupt is generated after the initial - * packet is sent on the wire within the set amount of time. Proper tuning, - * along with IGC_TIDV_VAL, may improve traffic throughput in specific - * network conditions. - */ -#define IGC_TADV_VAL 64 - -/* - * IGC_RDTR_VAL - Receive Interrupt Delay Timer (Packet Timer) - * Valid Range: 0-65535 (0=off) - * Default Value: 0 - * This value delays the generation of receive interrupts in units of 1.024 - * microseconds. Receive interrupt reduction can improve CPU efficiency if - * properly tuned for specific network traffic. Increasing this value adds - * extra latency to frame reception and can end up decreasing the throughput - * of TCP traffic. If the system is reporting dropped receives, this value - * may be set too high, causing the driver to run out of available receive - * descriptors. - * - * CAUTION: When setting IGC_RDTR to a value other than 0, adapters - * may hang (stop transmitting) under certain network conditions. - * If this occurs a WATCHDOG message is logged in the system - * event log. In addition, the controller is automatically reset, - * restoring the network connection. To eliminate the potential - * for the hang ensure that IGC_RDTR is set to 0. - */ -#define IGC_RDTR_VAL 0 - -/* - * Receive Interrupt Absolute Delay Timer - * Valid Range: 0-65535 (0=off) - * Default Value: 64 - * This value, in units of 1.024 microseconds, limits the delay in which a - * receive interrupt is generated. Useful only if IGC_RDTR is non-zero, - * this value ensures that an interrupt is generated after the initial - * packet is received within the set amount of time. Proper tuning, - * along with IGC_RDTR, may improve traffic throughput in specific network - * conditions. - */ -#define IGC_RADV_VAL 64 - -/* * This parameter controls whether or not autonegotation is enabled. * 0 - Disable autonegotiation * 1 - Enable autonegotiation @@ -222,6 +163,17 @@ #define IGC_TX_PTHRESH 8 #define IGC_TX_HTHRESH 1 +/* Define the interrupt rates and EITR helpers */ +#define IGC_INTS_4K 4000 +#define IGC_INTS_20K 20000 +#define IGC_INTS_70K 70000 +#define IGC_INTS_DEFAULT 8000 +#define IGC_EITR_DIVIDEND 1000000 +#define IGC_EITR_SHIFT 2 +#define IGC_QVECTOR_MASK 0x7FFC +#define IGC_INTS_TO_EITR(i) (((IGC_EITR_DIVIDEND/i) & IGC_QVECTOR_MASK) << \ + IGC_EITR_SHIFT) + /* * TDBA/RDBA should be aligned on 16 byte boundary. But TDLEN/RDLEN should be * multiple of 128 bytes. So we align TDBA/RDBA on 128 byte boundary. This will @@ -254,10 +206,10 @@ CSUM_IP_SCTP | CSUM_IP6_UDP | CSUM_IP6_TCP | \ CSUM_IP6_SCTP) /* Offload bits in mbuf flag */ -struct igc_adapter; +struct igc_softc; struct igc_int_delay_info { - struct igc_adapter *adapter; /* Back-pointer to the adapter struct */ + struct igc_softc *sc; /* Back-pointer to the softc struct */ int offset; /* Register offset to read/write */ int value; /* Current value in usecs */ }; @@ -266,9 +218,9 @@ struct igc_int_delay_info { * The transmit ring, one per tx queue */ struct tx_ring { - struct igc_adapter *adapter; + struct igc_softc *sc; struct igc_tx_desc *tx_base; - uint64_t tx_paddr; + uint64_t tx_paddr; qidx_t *tx_rsq; uint8_t me; qidx_t tx_rs_cidx; @@ -277,7 +229,12 @@ struct tx_ring { /* Interrupt resources */ void *tag; struct resource *res; - unsigned long tx_irq; + + /* Soft stats */ + unsigned long tx_irq; + unsigned long tx_packets; + unsigned long tx_bytes; + /* Saved csum offloading context information */ int csum_flags; @@ -296,7 +253,7 @@ struct tx_ring { * The Receive ring, one per rx queue */ struct rx_ring { - struct igc_adapter *adapter; + struct igc_softc *sc; struct igc_rx_queue *que; u32 me; u32 payload; @@ -312,28 +269,32 @@ struct rx_ring { unsigned long rx_discarded; unsigned long rx_packets; unsigned long rx_bytes; + + /* Next requested EITR latency */ + u8 rx_nextlatency; }; struct igc_tx_queue { - struct igc_adapter *adapter; - u32 msix; - u32 eims; /* This queue's EIMS bit */ - u32 me; - struct tx_ring txr; + struct igc_softc *sc; + u32 msix; + u32 eims; /* This queue's EIMS bit */ + u32 me; + struct tx_ring txr; }; struct igc_rx_queue { - struct igc_adapter *adapter; + struct igc_softc *sc; u32 me; u32 msix; u32 eims; + u32 eitr_setting; struct rx_ring rxr; u64 irqs; struct if_irq que_irq; }; -/* Our adapter structure */ -struct igc_adapter { +/* Our softc structure */ +struct igc_softc { if_t ifp; struct igc_hw hw; @@ -374,6 +335,8 @@ struct igc_adapter { u32 rx_mbuf_sz; + int enable_aim; + /* Management and WOL features */ u32 wol; @@ -387,10 +350,13 @@ struct igc_adapter { u16 link_duplex; u32 smartspeed; u32 dmac; + u32 pba; int link_mask; u64 que_mask; + struct igc_fw_version fw_ver; + struct igc_int_delay_info tx_int_delay; struct igc_int_delay_info tx_abs_int_delay; struct igc_int_delay_info rx_int_delay; @@ -407,7 +373,7 @@ struct igc_adapter { u16 vf_ifp; }; -void igc_dump_rs(struct igc_adapter *); +void igc_dump_rs(struct igc_softc *); #define IGC_RSSRK_SIZE 4 #define IGC_RSSRK_VAL(key, i) (key[(i) * IGC_RSSRK_SIZE] | \ diff --git a/sys/dev/igc/igc_api.c b/sys/dev/igc/igc_api.c index 9e91e7a4c73f..da499274fca4 100644 --- a/sys/dev/igc/igc_api.c +++ b/sys/dev/igc/igc_api.c @@ -109,6 +109,8 @@ s32 igc_set_mac_type(struct igc_hw *hw) case IGC_DEV_ID_I220_V: case IGC_DEV_ID_I225_K2: case IGC_DEV_ID_I225_LMVP: + case IGC_DEV_ID_I226_K: + case IGC_DEV_ID_I226_LMVP: case IGC_DEV_ID_I225_IT: case IGC_DEV_ID_I226_LM: case IGC_DEV_ID_I226_V: diff --git a/sys/dev/igc/igc_defines.h b/sys/dev/igc/igc_defines.h index 1701918c3a9c..09f75fe2787e 100644 --- a/sys/dev/igc/igc_defines.h +++ b/sys/dev/igc/igc_defines.h @@ -96,7 +96,6 @@ #define IGC_RXD_ERR_TCPE 0x20 /* TCP/UDP Checksum Error */ #define IGC_RXD_ERR_IPE 0x40 /* IP Checksum Error */ #define IGC_RXD_ERR_RXE 0x80 /* Rx Data Error */ -#define IGC_RXD_SPC_VLAN_MASK 0x0FFF /* VLAN ID is in lower 12 bits */ #define IGC_RXDEXT_STATERR_TST 0x00000100 /* Time Stamp taken */ #define IGC_RXDEXT_STATERR_LB 0x00040000 @@ -967,11 +966,31 @@ #define IGC_FLASH_UPDATES 2000 /* NVM Word Offsets */ -#define NVM_COMPAT 0x0003 -#define NVM_ID_LED_SETTINGS 0x0004 -#define NVM_FUTURE_INIT_WORD1 0x0019 -#define NVM_COMPAT_VALID_CSUM 0x0001 +#define NVM_COMPAT 0x0003 +#define NVM_ID_LED_SETTINGS 0x0004 +#define NVM_VERSION 0x0005 +#define NVM_FUTURE_INIT_WORD1 0x0019 +#define NVM_COMPAT_VALID_CSUM 0x0001 #define NVM_FUTURE_INIT_WORD1_VALID_CSUM 0x0040 +#define NVM_ETRACK_WORD 0x0042 +#define NVM_ETRACK_HIWORD 0x0043 +#define NVM_COMB_VER_OFF 0x0083 +#define NVM_COMB_VER_PTR 0x003d + +/* NVM version defines */ +#define NVM_MAJOR_MASK 0xF000 +#define NVM_MINOR_MASK 0x0FF0 +#define NVM_IMAGE_ID_MASK 0x000F +#define NVM_COMB_VER_MASK 0x00FF +#define NVM_MAJOR_SHIFT 12 +#define NVM_MINOR_SHIFT 4 +#define NVM_COMB_VER_SHFT 8 +#define NVM_VER_INVALID 0xFFFF +#define NVM_ETRACK_SHIFT 16 +#define NVM_ETRACK_VALID 0x8000 +#define NVM_NEW_DEC_MASK 0x0F00 +#define NVM_HEX_CONV 16 +#define NVM_HEX_TENS 10 #define NVM_INIT_CONTROL2_REG 0x000F #define NVM_INIT_CONTROL3_PORT_B 0x0014 diff --git a/sys/dev/igc/igc_nvm.c b/sys/dev/igc/igc_nvm.c index d86e04ffa0dc..b476a5fdbeac 100644 --- a/sys/dev/igc/igc_nvm.c +++ b/sys/dev/igc/igc_nvm.c @@ -716,4 +716,85 @@ static void igc_reload_nvm_generic(struct igc_hw *hw) IGC_WRITE_FLUSH(hw); } +/** + * igc_get_fw_version - Get firmware version information + * @hw: pointer to the HW structure + * @fw_vers: pointer to output version structure + * + * unsupported/not present features return 0 in version structure + **/ +void igc_get_fw_version(struct igc_hw *hw, struct igc_fw_version *fw_vers) +{ + u16 eeprom_verh, eeprom_verl, etrack_test, fw_version; + u8 q, hval, rem, result; + u16 comb_verh, comb_verl, comb_offset; + + memset(fw_vers, 0, sizeof(struct igc_fw_version)); + /* + * basic eeprom version numbers, bits used vary by part and by tool + * used to create the nvm images. Check which data format we have. + */ + switch (hw->mac.type) { + case igc_i225: + hw->nvm.ops.read(hw, NVM_ETRACK_HIWORD, 1, &etrack_test); + /* find combo image version */ + hw->nvm.ops.read(hw, NVM_COMB_VER_PTR, 1, &comb_offset); + if (comb_offset && comb_offset != NVM_VER_INVALID) { + hw->nvm.ops.read(hw, NVM_COMB_VER_OFF + comb_offset + 1, + 1, &comb_verh); + hw->nvm.ops.read(hw, NVM_COMB_VER_OFF + comb_offset, + 1, &comb_verl); + + /* get Option Rom version if it exists and is valid */ + if (comb_verh && comb_verl && + comb_verh != NVM_VER_INVALID && + comb_verl != NVM_VER_INVALID) { + fw_vers->or_valid = true; + fw_vers->or_major = comb_verl >> + NVM_COMB_VER_SHFT; + fw_vers->or_build = (comb_verl << + NVM_COMB_VER_SHFT) | + (comb_verh >> + NVM_COMB_VER_SHFT); + fw_vers->or_patch = comb_verh & + NVM_COMB_VER_MASK; + } + } + break; + default: + hw->nvm.ops.read(hw, NVM_ETRACK_HIWORD, 1, &etrack_test); + return; + } + hw->nvm.ops.read(hw, NVM_VERSION, 1, &fw_version); + fw_vers->eep_major = (fw_version & NVM_MAJOR_MASK) + >> NVM_MAJOR_SHIFT; + + /* check for old style version format in newer images*/ + if ((fw_version & NVM_NEW_DEC_MASK) == 0x0) { + eeprom_verl = (fw_version & NVM_COMB_VER_MASK); + } else { + eeprom_verl = (fw_version & NVM_MINOR_MASK) + >> NVM_MINOR_SHIFT; + } + /* Convert minor value to hex before assigning to output struct + * Val to be converted will not be higher than 99, per tool output + */ + q = eeprom_verl / NVM_HEX_CONV; + hval = q * NVM_HEX_TENS; + rem = eeprom_verl % NVM_HEX_CONV; + result = hval + rem; + fw_vers->eep_minor = result; + + if ((etrack_test & NVM_MAJOR_MASK) == NVM_ETRACK_VALID) { + hw->nvm.ops.read(hw, NVM_ETRACK_WORD, 1, &eeprom_verl); + hw->nvm.ops.read(hw, (NVM_ETRACK_WORD + 1), 1, &eeprom_verh); + fw_vers->etrack_id = (eeprom_verh << NVM_ETRACK_SHIFT) + | eeprom_verl; + } else if ((etrack_test & NVM_ETRACK_VALID) == 0) { + hw->nvm.ops.read(hw, NVM_ETRACK_WORD, 1, &eeprom_verh); + hw->nvm.ops.read(hw, (NVM_ETRACK_WORD + 1), 1, &eeprom_verl); + fw_vers->etrack_id = (eeprom_verh << NVM_ETRACK_SHIFT) | + eeprom_verl; + } +} diff --git a/sys/dev/igc/igc_nvm.h b/sys/dev/igc/igc_nvm.h index eae0db4b484b..b4b602af6595 100644 --- a/sys/dev/igc/igc_nvm.h +++ b/sys/dev/igc/igc_nvm.h @@ -7,6 +7,22 @@ #ifndef _IGC_NVM_H_ #define _IGC_NVM_H_ +struct igc_fw_version { + u32 etrack_id; + u16 eep_major; + u16 eep_minor; + u16 eep_build; + + u8 invm_major; + u8 invm_minor; + u8 invm_img_type; + + bool or_valid; + u16 or_major; + u16 or_build; + u16 or_patch; +}; + void igc_init_nvm_ops_generic(struct igc_hw *hw); s32 igc_null_read_nvm(struct igc_hw *hw, u16 a, u16 b, u16 *c); void igc_null_nvm_generic(struct igc_hw *hw); @@ -26,5 +42,7 @@ s32 igc_write_nvm_spi(struct igc_hw *hw, u16 offset, u16 words, u16 *data); s32 igc_update_nvm_checksum_generic(struct igc_hw *hw); void igc_release_nvm_generic(struct igc_hw *hw); +void igc_get_fw_version(struct igc_hw *hw, + struct igc_fw_version *fw_vers); #endif diff --git a/sys/dev/igc/igc_regs.h b/sys/dev/igc/igc_regs.h index f4ded07ce6ab..17fa89e492e8 100644 --- a/sys/dev/igc/igc_regs.h +++ b/sys/dev/igc/igc_regs.h @@ -27,7 +27,6 @@ #define IGC_CONNSW 0x00034 /* Copper/Fiber switch control - RW */ #define IGC_VET 0x00038 /* VLAN Ether Type - RW */ #define IGC_ICR 0x01500 /* Intr Cause Read - RC/W1C */ -#define IGC_ITR 0x000C4 /* Interrupt Throttling Rate - RW */ #define IGC_ICS 0x01504 /* Intr Cause Set - WO */ #define IGC_IMS 0x01508 /* Intr Mask Set/Read - RW */ #define IGC_IMC 0x0150C /* Intr Mask Clear - WO */ @@ -78,8 +77,6 @@ #define IGC_FCRTV 0x02460 /* Flow Control Refresh Timer Value - RW */ /* Split and Replication Rx Control - RW */ #define IGC_RXPBS 0x02404 /* Rx Packet Buffer Size - RW */ -#define IGC_RDTR 0x02820 /* Rx Delay Timer - RW */ -#define IGC_RADV 0x0282C /* Rx Interrupt Absolute Delay Timer - RW */ /* Shadow Ram Write Register - RW */ #define IGC_SRWR 0x12018 #define IGC_EEC_REG 0x12010 @@ -148,8 +145,8 @@ #define IGC_FFVT_REG(_i) (0x09800 + ((_i) * 8)) #define IGC_FFLT_REG(_i) (0x05F00 + ((_i) * 8)) #define IGC_TXPBS 0x03404 /* Tx Packet Buffer Size - RW */ -#define IGC_TIDV 0x03820 /* Tx Interrupt Delay Value - RW */ -#define IGC_TADV 0x0382C /* Tx Interrupt Absolute Delay Val - RW */ +#define IGC_DTXTCPFLGL 0x0359C /* DMA Tx Control flag low - RW */ +#define IGC_DTXTCPFLGH 0x035A0 /* DMA Tx Control flag high - RW */ /* Statistics Register Descriptions */ #define IGC_CRCERRS 0x04000 /* CRC Error Count - R/clr */ #define IGC_ALGNERRC 0x04004 /* Alignment Error Count - R/clr */ diff --git a/sys/dev/igc/igc_txrx.c b/sys/dev/igc/igc_txrx.c index 7601513a709e..92ba81c79c58 100644 --- a/sys/dev/igc/igc_txrx.c +++ b/sys/dev/igc/igc_txrx.c @@ -44,29 +44,27 @@ /********************************************************************* * Local Function prototypes *********************************************************************/ -static int igc_isc_txd_encap(void *arg, if_pkt_info_t pi); -static void igc_isc_txd_flush(void *arg, uint16_t txqid, qidx_t pidx); -static int igc_isc_txd_credits_update(void *arg, uint16_t txqid, bool clear); +static int igc_isc_txd_encap(void *, if_pkt_info_t); +static void igc_isc_txd_flush(void *, uint16_t, qidx_t); +static int igc_isc_txd_credits_update(void *, uint16_t, bool); -static void igc_isc_rxd_refill(void *arg, if_rxd_update_t iru); +static void igc_isc_rxd_refill(void *, if_rxd_update_t); -static void igc_isc_rxd_flush(void *arg, uint16_t rxqid, uint8_t flid __unused, - qidx_t pidx); -static int igc_isc_rxd_available(void *arg, uint16_t rxqid, qidx_t idx, - qidx_t budget); +static void igc_isc_rxd_flush(void *, uint16_t, uint8_t, qidx_t); +static int igc_isc_rxd_available(void *, uint16_t, qidx_t, qidx_t); -static int igc_isc_rxd_pkt_get(void *arg, if_rxd_info_t ri); +static int igc_isc_rxd_pkt_get(void *, if_rxd_info_t); -static int igc_tx_ctx_setup(struct tx_ring *txr, if_pkt_info_t pi, - uint32_t *cmd_type_len, uint32_t *olinfo_status); -static int igc_tso_setup(struct tx_ring *txr, if_pkt_info_t pi, - uint32_t *cmd_type_len, uint32_t *olinfo_status); +static int igc_tx_ctx_setup(struct tx_ring *, if_pkt_info_t, uint32_t *, + uint32_t *); +static int igc_tso_setup(struct tx_ring *, if_pkt_info_t, uint32_t *, + uint32_t *); -static void igc_rx_checksum(uint32_t staterr, if_rxd_info_t ri, uint32_t ptype); -static int igc_determine_rsstype(uint16_t pkt_info); +static void igc_rx_checksum(uint32_t, if_rxd_info_t, uint32_t); +static int igc_determine_rsstype(uint16_t); -extern void igc_if_enable_intr(if_ctx_t ctx); -extern int igc_intr(void *arg); +extern void igc_if_enable_intr(if_ctx_t); +extern int igc_intr(void *); struct if_txrx igc_txrx = { .ift_txd_encap = igc_isc_txd_encap, @@ -80,9 +78,9 @@ struct if_txrx igc_txrx = { }; void -igc_dump_rs(struct igc_adapter *adapter) +igc_dump_rs(struct igc_softc *sc) { - if_softc_ctx_t scctx = adapter->shared; + if_softc_ctx_t scctx = sc->shared; struct igc_tx_queue *que; struct tx_ring *txr; qidx_t i, ntxd, qid, cur; @@ -91,23 +89,27 @@ igc_dump_rs(struct igc_adapter *adapter) printf("\n"); ntxd = scctx->isc_ntxd[0]; - for (qid = 0; qid < adapter->tx_num_queues; qid++) { - que = &adapter->tx_queues[qid]; + for (qid = 0; qid < sc->tx_num_queues; qid++) { + que = &sc->tx_queues[qid]; txr = &que->txr; rs_cidx = txr->tx_rs_cidx; if (rs_cidx != txr->tx_rs_pidx) { cur = txr->tx_rsq[rs_cidx]; status = txr->tx_base[cur].upper.fields.status; if (!(status & IGC_TXD_STAT_DD)) - printf("qid[%d]->tx_rsq[%d]: %d clear ", qid, rs_cidx, cur); + printf("qid[%d]->tx_rsq[%d]: %d clear ", + qid, rs_cidx, cur); } else { rs_cidx = (rs_cidx-1)&(ntxd-1); cur = txr->tx_rsq[rs_cidx]; - printf("qid[%d]->tx_rsq[rs_cidx-1=%d]: %d ", qid, rs_cidx, cur); + printf("qid[%d]->tx_rsq[rs_cidx-1=%d]: %d ", + qid, rs_cidx, cur); } - printf("cidx_prev=%d rs_pidx=%d ",txr->tx_cidx_processed, txr->tx_rs_pidx); + printf("cidx_prev=%d rs_pidx=%d ",txr->tx_cidx_processed, + txr->tx_rs_pidx); for (i = 0; i < ntxd; i++) { - if (txr->tx_base[i].upper.fields.status & IGC_TXD_STAT_DD) + if (txr->tx_base[i].upper.fields.status & + IGC_TXD_STAT_DD) printf("%d set ", i); } printf("\n"); @@ -140,14 +142,15 @@ igc_tso_setup(struct tx_ring *txr, if_pkt_info_t pi, uint32_t *cmd_type_len, break; default: panic("%s: CSUM_TSO but no supported IP version (0x%04x)", - __func__, ntohs(pi->ipi_etype)); + __func__, ntohs(pi->ipi_etype)); break; } TXD = (struct igc_adv_tx_context_desc *) &txr->tx_base[pi->ipi_pidx]; /* This is used in the transmit desc in encap */ - paylen = pi->ipi_len - pi->ipi_ehdrlen - pi->ipi_ip_hlen - pi->ipi_tcp_hlen; + paylen = pi->ipi_len - pi->ipi_ehdrlen - pi->ipi_ip_hlen - + pi->ipi_tcp_hlen; /* VLAN MACLEN IPLEN */ if (pi->ipi_mflags & M_VLANTAG) { @@ -182,8 +185,8 @@ igc_tso_setup(struct tx_ring *txr, if_pkt_info_t pi, uint32_t *cmd_type_len, * **********************************************************************/ static int -igc_tx_ctx_setup(struct tx_ring *txr, if_pkt_info_t pi, uint32_t *cmd_type_len, - uint32_t *olinfo_status) +igc_tx_ctx_setup(struct tx_ring *txr, if_pkt_info_t pi, + uint32_t *cmd_type_len, uint32_t *olinfo_status) { struct igc_adv_tx_context_desc *TXD; uint32_t vlan_macip_lens, type_tucmd_mlhl; @@ -263,7 +266,7 @@ igc_tx_ctx_setup(struct tx_ring *txr, if_pkt_info_t pi, uint32_t *cmd_type_len, static int igc_isc_txd_encap(void *arg, if_pkt_info_t pi) { - struct igc_adapter *sc = arg; + struct igc_softc *sc = arg; if_softc_ctx_t scctx = sc->shared; struct igc_tx_queue *que = &sc->tx_queues[pi->ipi_qsidx]; struct tx_ring *txr = &que->txr; @@ -277,7 +280,7 @@ igc_isc_txd_encap(void *arg, if_pkt_info_t pi) pidx_last = olinfo_status = 0; /* Basic descriptor defines */ cmd_type_len = (IGC_ADVTXD_DTYP_DATA | - IGC_ADVTXD_DCMD_IFCS | IGC_ADVTXD_DCMD_DEXT); + IGC_ADVTXD_DCMD_IFCS | IGC_ADVTXD_DCMD_DEXT); if (pi->ipi_mflags & M_VLANTAG) cmd_type_len |= IGC_ADVTXD_DCMD_VLE; @@ -316,25 +319,29 @@ igc_isc_txd_encap(void *arg, if_pkt_info_t pi) txd->read.cmd_type_len |= htole32(IGC_ADVTXD_DCMD_EOP | txd_flags); pi->ipi_new_pidx = i; + /* Sent data accounting for AIM */ + txr->tx_bytes += pi->ipi_len; + ++txr->tx_packets; + return (0); } static void igc_isc_txd_flush(void *arg, uint16_t txqid, qidx_t pidx) { - struct igc_adapter *adapter = arg; - struct igc_tx_queue *que = &adapter->tx_queues[txqid]; - struct tx_ring *txr = &que->txr; + struct igc_softc *sc = arg; + struct igc_tx_queue *que = &sc->tx_queues[txqid]; + struct tx_ring *txr = &que->txr; - IGC_WRITE_REG(&adapter->hw, IGC_TDT(txr->me), pidx); + IGC_WRITE_REG(&sc->hw, IGC_TDT(txr->me), pidx); } static int igc_isc_txd_credits_update(void *arg, uint16_t txqid, bool clear) { - struct igc_adapter *adapter = arg; - if_softc_ctx_t scctx = adapter->shared; - struct igc_tx_queue *que = &adapter->tx_queues[txqid]; + struct igc_softc *sc = arg; + if_softc_ctx_t scctx = sc->shared; + struct igc_tx_queue *que = &sc->tx_queues[txqid]; struct tx_ring *txr = &que->txr; qidx_t processed = 0; @@ -368,12 +375,13 @@ igc_isc_txd_credits_update(void *arg, uint16_t txqid, bool clear) MPASS(delta > 0); processed += delta; - prev = cur; + prev = cur; rs_cidx = (rs_cidx + 1) & (ntxd-1); - if (rs_cidx == txr->tx_rs_pidx) + if (rs_cidx == txr->tx_rs_pidx) break; cur = txr->tx_rsq[rs_cidx]; - status = ((union igc_adv_tx_desc *)&txr->tx_base[cur])->wb.status; + status = + ((union igc_adv_tx_desc *)&txr->tx_base[cur])->wb.status; } while ((status & IGC_TXD_STAT_DD)); txr->tx_rs_cidx = rs_cidx; @@ -384,7 +392,7 @@ igc_isc_txd_credits_update(void *arg, uint16_t txqid, bool clear) static void igc_isc_rxd_refill(void *arg, if_rxd_update_t iru) { - struct igc_adapter *sc = arg; + struct igc_softc *sc = arg; if_softc_ctx_t scctx = sc->shared; uint16_t rxqid = iru->iru_qsidx; struct igc_rx_queue *que = &sc->rx_queues[rxqid]; @@ -409,9 +417,10 @@ igc_isc_rxd_refill(void *arg, if_rxd_update_t iru) } static void -igc_isc_rxd_flush(void *arg, uint16_t rxqid, uint8_t flid __unused, qidx_t pidx) +igc_isc_rxd_flush(void *arg, uint16_t rxqid, uint8_t flid __unused, + qidx_t pidx) { - struct igc_adapter *sc = arg; + struct igc_softc *sc = arg; struct igc_rx_queue *que = &sc->rx_queues[rxqid]; struct rx_ring *rxr = &que->rxr; @@ -421,7 +430,7 @@ igc_isc_rxd_flush(void *arg, uint16_t rxqid, uint8_t flid __unused, qidx_t pidx) static int igc_isc_rxd_available(void *arg, uint16_t rxqid, qidx_t idx, qidx_t budget) { - struct igc_adapter *sc = arg; + struct igc_softc *sc = arg; if_softc_ctx_t scctx = sc->shared; struct igc_rx_queue *que = &sc->rx_queues[rxqid]; struct rx_ring *rxr = &que->rxr; @@ -453,9 +462,9 @@ igc_isc_rxd_available(void *arg, uint16_t rxqid, qidx_t idx, qidx_t budget) static int igc_isc_rxd_pkt_get(void *arg, if_rxd_info_t ri) { - struct igc_adapter *adapter = arg; - if_softc_ctx_t scctx = adapter->shared; - struct igc_rx_queue *que = &adapter->rx_queues[ri->iri_qsidx]; + struct igc_softc *sc = arg; + if_softc_ctx_t scctx = sc->shared; + struct igc_rx_queue *que = &sc->rx_queues[ri->iri_qsidx]; struct rx_ring *rxr = &que->rxr; union igc_adv_rx_desc *rxd; @@ -475,7 +484,8 @@ igc_isc_rxd_pkt_get(void *arg, if_rxd_info_t ri) MPASS ((staterr & IGC_RXD_STAT_DD) != 0); len = le16toh(rxd->wb.upper.length); - ptype = le32toh(rxd->wb.lower.lo_dword.data) & IGC_PKTTYPE_MASK; + ptype = + le32toh(rxd->wb.lower.lo_dword.data) & IGC_PKTTYPE_MASK; ri->iri_len += len; rxr->rx_bytes += ri->iri_len; @@ -485,7 +495,7 @@ igc_isc_rxd_pkt_get(void *arg, if_rxd_info_t ri) /* Make sure bad packets are discarded */ if (eop && ((staterr & IGC_RXDEXT_STATERR_RXE) != 0)) { - adapter->dropped_pkts++; + sc->dropped_pkts++; ++rxr->rx_discarded; return (EBADMSG); } @@ -556,7 +566,8 @@ igc_rx_checksum(uint32_t staterr, if_rxd_info_t ri, uint32_t ptype) (ptype & IGC_RXDADV_PKTTYPE_SCTP) != 0)) { ri->iri_csum_flags |= CSUM_SCTP_VALID; } else { - ri->iri_csum_flags |= CSUM_DATA_VALID | CSUM_PSEUDO_HDR; + ri->iri_csum_flags |= + CSUM_DATA_VALID | CSUM_PSEUDO_HDR; ri->iri_csum_data = htons(0xffff); } } |