Changeset View
Changeset View
Standalone View
Standalone View
sys/dev/ixgbe/if_ix.c
Show First 20 Lines • Show All 103 Lines • ▼ Show 20 Lines | static pci_vendor_info_t ixgbe_vendor_info_array[] = | ||||
PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_A_1G_T, "Intel(R) X553 (1GbE)"), | PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_A_1G_T, "Intel(R) X553 (1GbE)"), | ||||
PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_A_1G_T_L, "Intel(R) X553 L (1GbE)"), | PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_A_1G_T_L, "Intel(R) X553 L (1GbE)"), | ||||
PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X540_BYPASS, "Intel(R) X540-T2 (Bypass)"), | PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X540_BYPASS, "Intel(R) X540-T2 (Bypass)"), | ||||
PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_BYPASS, "Intel(R) X520 82599 (Bypass)"), | PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_BYPASS, "Intel(R) X520 82599 (Bypass)"), | ||||
/* required last entry */ | /* required last entry */ | ||||
PVID_END | PVID_END | ||||
}; | }; | ||||
static void *ixgbe_register(device_t dev); | static void *ixgbe_register(device_t); | ||||
static int ixgbe_if_attach_pre(if_ctx_t ctx); | static int ixgbe_if_attach_pre(if_ctx_t); | ||||
static int ixgbe_if_attach_post(if_ctx_t ctx); | static int ixgbe_if_attach_post(if_ctx_t); | ||||
static int ixgbe_if_detach(if_ctx_t ctx); | static int ixgbe_if_detach(if_ctx_t); | ||||
static int ixgbe_if_shutdown(if_ctx_t ctx); | static int ixgbe_if_shutdown(if_ctx_t); | ||||
static int ixgbe_if_suspend(if_ctx_t ctx); | static int ixgbe_if_suspend(if_ctx_t); | ||||
static int ixgbe_if_resume(if_ctx_t ctx); | static int ixgbe_if_resume(if_ctx_t); | ||||
static void ixgbe_if_stop(if_ctx_t ctx); | static void ixgbe_if_stop(if_ctx_t); | ||||
void ixgbe_if_enable_intr(if_ctx_t ctx); | void ixgbe_if_enable_intr(if_ctx_t); | ||||
static void ixgbe_if_disable_intr(if_ctx_t ctx); | static void ixgbe_if_disable_intr(if_ctx_t); | ||||
static void ixgbe_link_intr_enable(if_ctx_t ctx); | static void ixgbe_link_intr_enable(if_ctx_t); | ||||
static int ixgbe_if_rx_queue_intr_enable(if_ctx_t ctx, uint16_t qid); | static int ixgbe_if_rx_queue_intr_enable(if_ctx_t, uint16_t); | ||||
static void ixgbe_if_media_status(if_ctx_t ctx, struct ifmediareq * ifmr); | static void ixgbe_if_media_status(if_ctx_t, struct ifmediareq *); | ||||
static int ixgbe_if_media_change(if_ctx_t ctx); | static int ixgbe_if_media_change(if_ctx_t); | ||||
static int ixgbe_if_msix_intr_assign(if_ctx_t, int); | static int ixgbe_if_msix_intr_assign(if_ctx_t, int); | ||||
static int ixgbe_if_mtu_set(if_ctx_t ctx, uint32_t mtu); | static int ixgbe_if_mtu_set(if_ctx_t, uint32_t); | ||||
static void ixgbe_if_crcstrip_set(if_ctx_t ctx, int onoff, int strip); | static void ixgbe_if_crcstrip_set(if_ctx_t, int, int); | ||||
static void ixgbe_if_multi_set(if_ctx_t ctx); | static void ixgbe_if_multi_set(if_ctx_t); | ||||
static int ixgbe_if_promisc_set(if_ctx_t ctx, int flags); | static int ixgbe_if_promisc_set(if_ctx_t, int); | ||||
static int ixgbe_if_tx_queues_alloc(if_ctx_t ctx, caddr_t *vaddrs, | static int ixgbe_if_tx_queues_alloc(if_ctx_t, caddr_t *, uint64_t *, int, int); | ||||
uint64_t *paddrs, int nrxqs, int nrxqsets); | static int ixgbe_if_rx_queues_alloc(if_ctx_t, caddr_t *, uint64_t *, int, int); | ||||
static int ixgbe_if_rx_queues_alloc(if_ctx_t ctx, caddr_t *vaddrs, | static void ixgbe_if_queues_free(if_ctx_t); | ||||
uint64_t *paddrs, int nrxqs, int nrxqsets); | static void ixgbe_if_timer(if_ctx_t, uint16_t); | ||||
static void ixgbe_if_queues_free(if_ctx_t ctx); | static void ixgbe_if_update_admin_status(if_ctx_t); | ||||
static void ixgbe_if_timer(if_ctx_t ctx, uint16_t); | static void ixgbe_if_vlan_register(if_ctx_t, u16); | ||||
static void ixgbe_if_update_admin_status(if_ctx_t ctx); | static void ixgbe_if_vlan_unregister(if_ctx_t, u16); | ||||
static void ixgbe_if_vlan_register(if_ctx_t ctx, u16 vtag); | static int ixgbe_if_i2c_req(if_ctx_t, struct ifi2creq *); | ||||
static void ixgbe_if_vlan_unregister(if_ctx_t ctx, u16 vtag); | static bool ixgbe_if_needs_restart(if_ctx_t, enum iflib_restart_event); | ||||
static int ixgbe_if_i2c_req(if_ctx_t ctx, struct ifi2creq *req); | int ixgbe_intr(void *); | ||||
static bool ixgbe_if_needs_restart(if_ctx_t ctx, enum iflib_restart_event event); | |||||
int ixgbe_intr(void *arg); | |||||
/************************************************************************ | /************************************************************************ | ||||
* Function prototypes | * Function prototypes | ||||
************************************************************************/ | ************************************************************************/ | ||||
#if __FreeBSD_version >= 1100036 | |||||
static uint64_t ixgbe_if_get_counter(if_ctx_t, ift_counter); | static uint64_t ixgbe_if_get_counter(if_ctx_t, ift_counter); | ||||
#endif | |||||
static void ixgbe_enable_queue(struct adapter *adapter, u32 vector); | static void ixgbe_enable_queue(struct ixgbe_softc *, u32); | ||||
static void ixgbe_disable_queue(struct adapter *adapter, u32 vector); | static void ixgbe_disable_queue(struct ixgbe_softc *, u32); | ||||
static void ixgbe_add_device_sysctls(if_ctx_t ctx); | static void ixgbe_add_device_sysctls(if_ctx_t); | ||||
static int ixgbe_allocate_pci_resources(if_ctx_t ctx); | static int ixgbe_allocate_pci_resources(if_ctx_t); | ||||
static int ixgbe_setup_low_power_mode(if_ctx_t ctx); | static int ixgbe_setup_low_power_mode(if_ctx_t); | ||||
static void ixgbe_config_dmac(struct adapter *adapter); | static void ixgbe_config_dmac(struct ixgbe_softc *); | ||||
static void ixgbe_configure_ivars(struct adapter *adapter); | static void ixgbe_configure_ivars(struct ixgbe_softc *); | ||||
static void ixgbe_set_ivar(struct adapter *adapter, u8 entry, u8 vector, | static void ixgbe_set_ivar(struct ixgbe_softc *, u8, u8, s8); | ||||
s8 type); | |||||
static u8 *ixgbe_mc_array_itr(struct ixgbe_hw *, u8 **, u32 *); | static u8 *ixgbe_mc_array_itr(struct ixgbe_hw *, u8 **, u32 *); | ||||
static bool ixgbe_sfp_probe(if_ctx_t ctx); | static bool ixgbe_sfp_probe(if_ctx_t); | ||||
static void ixgbe_free_pci_resources(if_ctx_t ctx); | static void ixgbe_free_pci_resources(if_ctx_t); | ||||
static int ixgbe_msix_link(void *arg); | static int ixgbe_msix_link(void *); | ||||
static int ixgbe_msix_que(void *arg); | static int ixgbe_msix_que(void *); | ||||
static void ixgbe_initialize_rss_mapping(struct adapter *adapter); | static void ixgbe_initialize_rss_mapping(struct ixgbe_softc *); | ||||
static void ixgbe_initialize_receive_units(if_ctx_t ctx); | static void ixgbe_initialize_receive_units(if_ctx_t); | ||||
static void ixgbe_initialize_transmit_units(if_ctx_t ctx); | static void ixgbe_initialize_transmit_units(if_ctx_t); | ||||
static int ixgbe_setup_interface(if_ctx_t ctx); | static int ixgbe_setup_interface(if_ctx_t); | ||||
static void ixgbe_init_device_features(struct adapter *adapter); | static void ixgbe_init_device_features(struct ixgbe_softc *); | ||||
static void ixgbe_check_fan_failure(struct adapter *, u32, bool); | static void ixgbe_check_fan_failure(struct ixgbe_softc *, u32, bool); | ||||
static void ixgbe_sbuf_fw_version(struct ixgbe_hw *, struct sbuf *); | static void ixgbe_sbuf_fw_version(struct ixgbe_hw *, struct sbuf *); | ||||
static void ixgbe_print_fw_version(if_ctx_t ctx); | static void ixgbe_print_fw_version(if_ctx_t); | ||||
static void ixgbe_add_media_types(if_ctx_t ctx); | static void ixgbe_add_media_types(if_ctx_t); | ||||
static void ixgbe_update_stats_counters(struct adapter *adapter); | static void ixgbe_update_stats_counters(struct ixgbe_softc *); | ||||
static void ixgbe_config_link(if_ctx_t ctx); | static void ixgbe_config_link(if_ctx_t); | ||||
static void ixgbe_get_slot_info(struct adapter *); | static void ixgbe_get_slot_info(struct ixgbe_softc *); | ||||
static void ixgbe_check_wol_support(struct adapter *adapter); | static void ixgbe_check_wol_support(struct ixgbe_softc *); | ||||
static void ixgbe_enable_rx_drop(struct adapter *); | static void ixgbe_enable_rx_drop(struct ixgbe_softc *); | ||||
static void ixgbe_disable_rx_drop(struct adapter *); | static void ixgbe_disable_rx_drop(struct ixgbe_softc *); | ||||
static void ixgbe_add_hw_stats(struct adapter *adapter); | static void ixgbe_add_hw_stats(struct ixgbe_softc *); | ||||
static int ixgbe_set_flowcntl(struct adapter *, int); | static int ixgbe_set_flowcntl(struct ixgbe_softc *, int); | ||||
static int ixgbe_set_advertise(struct adapter *, int); | static int ixgbe_set_advertise(struct ixgbe_softc *, int); | ||||
static int ixgbe_get_advertise(struct adapter *); | static int ixgbe_get_advertise(struct ixgbe_softc *); | ||||
static void ixgbe_setup_vlan_hw_support(if_ctx_t ctx); | static void ixgbe_setup_vlan_hw_support(if_ctx_t); | ||||
static void ixgbe_config_gpie(struct adapter *adapter); | static void ixgbe_config_gpie(struct ixgbe_softc *); | ||||
static void ixgbe_config_delay_values(struct adapter *adapter); | static void ixgbe_config_delay_values(struct ixgbe_softc *); | ||||
/* Sysctl handlers */ | /* Sysctl handlers */ | ||||
static int ixgbe_sysctl_flowcntl(SYSCTL_HANDLER_ARGS); | static int ixgbe_sysctl_flowcntl(SYSCTL_HANDLER_ARGS); | ||||
static int ixgbe_sysctl_advertise(SYSCTL_HANDLER_ARGS); | static int ixgbe_sysctl_advertise(SYSCTL_HANDLER_ARGS); | ||||
static int ixgbe_sysctl_interrupt_rate_handler(SYSCTL_HANDLER_ARGS); | static int ixgbe_sysctl_interrupt_rate_handler(SYSCTL_HANDLER_ARGS); | ||||
static int ixgbe_sysctl_dmac(SYSCTL_HANDLER_ARGS); | static int ixgbe_sysctl_dmac(SYSCTL_HANDLER_ARGS); | ||||
static int ixgbe_sysctl_phy_temp(SYSCTL_HANDLER_ARGS); | static int ixgbe_sysctl_phy_temp(SYSCTL_HANDLER_ARGS); | ||||
static int ixgbe_sysctl_phy_overtemp_occurred(SYSCTL_HANDLER_ARGS); | static int ixgbe_sysctl_phy_overtemp_occurred(SYSCTL_HANDLER_ARGS); | ||||
Show All 31 Lines | #ifdef PCI_IOV | ||||
DEVMETHOD(pci_iov_init, iflib_device_iov_init), | DEVMETHOD(pci_iov_init, iflib_device_iov_init), | ||||
DEVMETHOD(pci_iov_uninit, iflib_device_iov_uninit), | DEVMETHOD(pci_iov_uninit, iflib_device_iov_uninit), | ||||
DEVMETHOD(pci_iov_add_vf, iflib_device_iov_add_vf), | DEVMETHOD(pci_iov_add_vf, iflib_device_iov_add_vf), | ||||
#endif /* PCI_IOV */ | #endif /* PCI_IOV */ | ||||
DEVMETHOD_END | DEVMETHOD_END | ||||
}; | }; | ||||
static driver_t ix_driver = { | static driver_t ix_driver = { | ||||
"ix", ix_methods, sizeof(struct adapter), | "ix", ix_methods, sizeof(struct ixgbe_softc), | ||||
}; | }; | ||||
devclass_t ix_devclass; | devclass_t ix_devclass; | ||||
DRIVER_MODULE(ix, pci, ix_driver, ix_devclass, 0, 0); | DRIVER_MODULE(ix, pci, ix_driver, ix_devclass, 0, 0); | ||||
IFLIB_PNP_INFO(pci, ix_driver, ixgbe_vendor_info_array); | IFLIB_PNP_INFO(pci, ix_driver, ixgbe_vendor_info_array); | ||||
MODULE_DEPEND(ix, pci, 1, 1, 1); | MODULE_DEPEND(ix, pci, 1, 1, 1); | ||||
MODULE_DEPEND(ix, ether, 1, 1, 1); | MODULE_DEPEND(ix, ether, 1, 1, 1); | ||||
MODULE_DEPEND(ix, iflib, 1, 1, 1); | MODULE_DEPEND(ix, iflib, 1, 1, 1); | ||||
Show All 39 Lines | |||||
/* | /* | ||||
* TUNEABLE PARAMETERS: | * TUNEABLE PARAMETERS: | ||||
*/ | */ | ||||
static SYSCTL_NODE(_hw, OID_AUTO, ix, CTLFLAG_RD | CTLFLAG_MPSAFE, 0, | static SYSCTL_NODE(_hw, OID_AUTO, ix, CTLFLAG_RD | CTLFLAG_MPSAFE, 0, | ||||
"IXGBE driver parameters"); | "IXGBE driver parameters"); | ||||
static driver_t ixgbe_if_driver = { | static driver_t ixgbe_if_driver = { | ||||
"ixgbe_if", ixgbe_if_methods, sizeof(struct adapter) | "ixgbe_if", ixgbe_if_methods, sizeof(struct ixgbe_softc) | ||||
}; | }; | ||||
static int ixgbe_max_interrupt_rate = (4000000 / IXGBE_LOW_LATENCY); | static int ixgbe_max_interrupt_rate = (4000000 / IXGBE_LOW_LATENCY); | ||||
SYSCTL_INT(_hw_ix, OID_AUTO, max_interrupt_rate, CTLFLAG_RDTUN, | SYSCTL_INT(_hw_ix, OID_AUTO, max_interrupt_rate, CTLFLAG_RDTUN, | ||||
&ixgbe_max_interrupt_rate, 0, "Maximum interrupts per second"); | &ixgbe_max_interrupt_rate, 0, "Maximum interrupts per second"); | ||||
/* Flow control setting, default to full */ | /* Flow control setting, default to full */ | ||||
static int ixgbe_flow_control = ixgbe_fc_full; | static int ixgbe_flow_control = ixgbe_fc_full; | ||||
▲ Show 20 Lines • Show All 102 Lines • ▼ Show 20 Lines | |||||
/************************************************************************ | /************************************************************************ | ||||
* ixgbe_if_tx_queues_alloc | * ixgbe_if_tx_queues_alloc | ||||
************************************************************************/ | ************************************************************************/ | ||||
static int | static int | ||||
ixgbe_if_tx_queues_alloc(if_ctx_t ctx, caddr_t *vaddrs, uint64_t *paddrs, | ixgbe_if_tx_queues_alloc(if_ctx_t ctx, caddr_t *vaddrs, uint64_t *paddrs, | ||||
int ntxqs, int ntxqsets) | int ntxqs, int ntxqsets) | ||||
{ | { | ||||
struct adapter *adapter = iflib_get_softc(ctx); | struct ixgbe_softc *sc = iflib_get_softc(ctx); | ||||
if_softc_ctx_t scctx = adapter->shared; | if_softc_ctx_t scctx = sc->shared; | ||||
struct ix_tx_queue *que; | struct ix_tx_queue *que; | ||||
int i, j, error; | int i, j, error; | ||||
MPASS(adapter->num_tx_queues > 0); | MPASS(sc->num_tx_queues > 0); | ||||
MPASS(adapter->num_tx_queues == ntxqsets); | MPASS(sc->num_tx_queues == ntxqsets); | ||||
MPASS(ntxqs == 1); | MPASS(ntxqs == 1); | ||||
/* Allocate queue structure memory */ | /* Allocate queue structure memory */ | ||||
adapter->tx_queues = | sc->tx_queues = | ||||
(struct ix_tx_queue *)malloc(sizeof(struct ix_tx_queue) * ntxqsets, | (struct ix_tx_queue *)malloc(sizeof(struct ix_tx_queue) * ntxqsets, | ||||
M_IXGBE, M_NOWAIT | M_ZERO); | M_IXGBE, M_NOWAIT | M_ZERO); | ||||
if (!adapter->tx_queues) { | if (!sc->tx_queues) { | ||||
device_printf(iflib_get_dev(ctx), | device_printf(iflib_get_dev(ctx), | ||||
"Unable to allocate TX ring memory\n"); | "Unable to allocate TX ring memory\n"); | ||||
return (ENOMEM); | return (ENOMEM); | ||||
} | } | ||||
for (i = 0, que = adapter->tx_queues; i < ntxqsets; i++, que++) { | for (i = 0, que = sc->tx_queues; i < ntxqsets; i++, que++) { | ||||
struct tx_ring *txr = &que->txr; | struct tx_ring *txr = &que->txr; | ||||
/* In case SR-IOV is enabled, align the index properly */ | /* In case SR-IOV is enabled, align the index properly */ | ||||
txr->me = ixgbe_vf_que_index(adapter->iov_mode, adapter->pool, | txr->me = ixgbe_vf_que_index(sc->iov_mode, sc->pool, | ||||
i); | i); | ||||
txr->adapter = que->adapter = adapter; | txr->sc = que->sc = sc; | ||||
/* Allocate report status array */ | /* Allocate report status array */ | ||||
txr->tx_rsq = (qidx_t *)malloc(sizeof(qidx_t) * scctx->isc_ntxd[0], M_IXGBE, M_NOWAIT | M_ZERO); | txr->tx_rsq = (qidx_t *)malloc(sizeof(qidx_t) * scctx->isc_ntxd[0], M_IXGBE, M_NOWAIT | M_ZERO); | ||||
if (txr->tx_rsq == NULL) { | if (txr->tx_rsq == NULL) { | ||||
error = ENOMEM; | error = ENOMEM; | ||||
goto fail; | goto fail; | ||||
} | } | ||||
for (j = 0; j < scctx->isc_ntxd[0]; j++) | for (j = 0; j < scctx->isc_ntxd[0]; j++) | ||||
txr->tx_rsq[j] = QIDX_INVALID; | txr->tx_rsq[j] = QIDX_INVALID; | ||||
/* get the virtual and physical address of the hardware queues */ | /* get the virtual and physical address of the hardware queues */ | ||||
txr->tail = IXGBE_TDT(txr->me); | txr->tail = IXGBE_TDT(txr->me); | ||||
txr->tx_base = (union ixgbe_adv_tx_desc *)vaddrs[i]; | txr->tx_base = (union ixgbe_adv_tx_desc *)vaddrs[i]; | ||||
txr->tx_paddr = paddrs[i]; | txr->tx_paddr = paddrs[i]; | ||||
txr->bytes = 0; | txr->bytes = 0; | ||||
txr->total_packets = 0; | txr->total_packets = 0; | ||||
/* Set the rate at which we sample packets */ | /* Set the rate at which we sample packets */ | ||||
if (adapter->feat_en & IXGBE_FEATURE_FDIR) | if (sc->feat_en & IXGBE_FEATURE_FDIR) | ||||
txr->atr_sample = atr_sample_rate; | txr->atr_sample = atr_sample_rate; | ||||
} | } | ||||
device_printf(iflib_get_dev(ctx), "allocated for %d queues\n", | device_printf(iflib_get_dev(ctx), "allocated for %d queues\n", | ||||
adapter->num_tx_queues); | sc->num_tx_queues); | ||||
return (0); | return (0); | ||||
fail: | fail: | ||||
ixgbe_if_queues_free(ctx); | ixgbe_if_queues_free(ctx); | ||||
return (error); | return (error); | ||||
} /* ixgbe_if_tx_queues_alloc */ | } /* ixgbe_if_tx_queues_alloc */ | ||||
/************************************************************************ | /************************************************************************ | ||||
* ixgbe_if_rx_queues_alloc | * ixgbe_if_rx_queues_alloc | ||||
************************************************************************/ | ************************************************************************/ | ||||
static int | static int | ||||
ixgbe_if_rx_queues_alloc(if_ctx_t ctx, caddr_t *vaddrs, uint64_t *paddrs, | ixgbe_if_rx_queues_alloc(if_ctx_t ctx, caddr_t *vaddrs, uint64_t *paddrs, | ||||
int nrxqs, int nrxqsets) | int nrxqs, int nrxqsets) | ||||
{ | { | ||||
struct adapter *adapter = iflib_get_softc(ctx); | struct ixgbe_softc *sc = iflib_get_softc(ctx); | ||||
struct ix_rx_queue *que; | struct ix_rx_queue *que; | ||||
int i; | int i; | ||||
MPASS(adapter->num_rx_queues > 0); | MPASS(sc->num_rx_queues > 0); | ||||
MPASS(adapter->num_rx_queues == nrxqsets); | MPASS(sc->num_rx_queues == nrxqsets); | ||||
MPASS(nrxqs == 1); | MPASS(nrxqs == 1); | ||||
/* Allocate queue structure memory */ | /* Allocate queue structure memory */ | ||||
adapter->rx_queues = | sc->rx_queues = | ||||
(struct ix_rx_queue *)malloc(sizeof(struct ix_rx_queue)*nrxqsets, | (struct ix_rx_queue *)malloc(sizeof(struct ix_rx_queue)*nrxqsets, | ||||
M_IXGBE, M_NOWAIT | M_ZERO); | M_IXGBE, M_NOWAIT | M_ZERO); | ||||
if (!adapter->rx_queues) { | if (!sc->rx_queues) { | ||||
device_printf(iflib_get_dev(ctx), | device_printf(iflib_get_dev(ctx), | ||||
"Unable to allocate TX ring memory\n"); | "Unable to allocate TX ring memory\n"); | ||||
return (ENOMEM); | return (ENOMEM); | ||||
} | } | ||||
for (i = 0, que = adapter->rx_queues; i < nrxqsets; i++, que++) { | for (i = 0, que = sc->rx_queues; i < nrxqsets; i++, que++) { | ||||
struct rx_ring *rxr = &que->rxr; | struct rx_ring *rxr = &que->rxr; | ||||
/* In case SR-IOV is enabled, align the index properly */ | /* In case SR-IOV is enabled, align the index properly */ | ||||
rxr->me = ixgbe_vf_que_index(adapter->iov_mode, adapter->pool, | rxr->me = ixgbe_vf_que_index(sc->iov_mode, sc->pool, | ||||
i); | i); | ||||
rxr->adapter = que->adapter = adapter; | rxr->sc = que->sc = sc; | ||||
/* get the virtual and physical address of the hw queues */ | /* get the virtual and physical address of the hw queues */ | ||||
rxr->tail = IXGBE_RDT(rxr->me); | rxr->tail = IXGBE_RDT(rxr->me); | ||||
rxr->rx_base = (union ixgbe_adv_rx_desc *)vaddrs[i]; | rxr->rx_base = (union ixgbe_adv_rx_desc *)vaddrs[i]; | ||||
rxr->rx_paddr = paddrs[i]; | rxr->rx_paddr = paddrs[i]; | ||||
rxr->bytes = 0; | rxr->bytes = 0; | ||||
rxr->que = que; | rxr->que = que; | ||||
} | } | ||||
device_printf(iflib_get_dev(ctx), "allocated for %d rx queues\n", | device_printf(iflib_get_dev(ctx), "allocated for %d rx queues\n", | ||||
adapter->num_rx_queues); | sc->num_rx_queues); | ||||
return (0); | return (0); | ||||
} /* ixgbe_if_rx_queues_alloc */ | } /* ixgbe_if_rx_queues_alloc */ | ||||
/************************************************************************ | /************************************************************************ | ||||
* ixgbe_if_queues_free | * ixgbe_if_queues_free | ||||
************************************************************************/ | ************************************************************************/ | ||||
static void | static void | ||||
ixgbe_if_queues_free(if_ctx_t ctx) | ixgbe_if_queues_free(if_ctx_t ctx) | ||||
{ | { | ||||
struct adapter *adapter = iflib_get_softc(ctx); | struct ixgbe_softc *sc = iflib_get_softc(ctx); | ||||
struct ix_tx_queue *tx_que = adapter->tx_queues; | struct ix_tx_queue *tx_que = sc->tx_queues; | ||||
struct ix_rx_queue *rx_que = adapter->rx_queues; | struct ix_rx_queue *rx_que = sc->rx_queues; | ||||
int i; | int i; | ||||
if (tx_que != NULL) { | if (tx_que != NULL) { | ||||
for (i = 0; i < adapter->num_tx_queues; i++, tx_que++) { | for (i = 0; i < sc->num_tx_queues; i++, tx_que++) { | ||||
struct tx_ring *txr = &tx_que->txr; | struct tx_ring *txr = &tx_que->txr; | ||||
if (txr->tx_rsq == NULL) | if (txr->tx_rsq == NULL) | ||||
break; | break; | ||||
free(txr->tx_rsq, M_IXGBE); | free(txr->tx_rsq, M_IXGBE); | ||||
txr->tx_rsq = NULL; | txr->tx_rsq = NULL; | ||||
} | } | ||||
free(adapter->tx_queues, M_IXGBE); | free(sc->tx_queues, M_IXGBE); | ||||
adapter->tx_queues = NULL; | sc->tx_queues = NULL; | ||||
} | } | ||||
if (rx_que != NULL) { | if (rx_que != NULL) { | ||||
free(adapter->rx_queues, M_IXGBE); | free(sc->rx_queues, M_IXGBE); | ||||
adapter->rx_queues = NULL; | sc->rx_queues = NULL; | ||||
} | } | ||||
} /* ixgbe_if_queues_free */ | } /* ixgbe_if_queues_free */ | ||||
/************************************************************************ | /************************************************************************ | ||||
* ixgbe_initialize_rss_mapping | * ixgbe_initialize_rss_mapping | ||||
************************************************************************/ | ************************************************************************/ | ||||
static void | static void | ||||
ixgbe_initialize_rss_mapping(struct adapter *adapter) | ixgbe_initialize_rss_mapping(struct ixgbe_softc *sc) | ||||
{ | { | ||||
struct ixgbe_hw *hw = &adapter->hw; | struct ixgbe_hw *hw = &sc->hw; | ||||
u32 reta = 0, mrqc, rss_key[10]; | u32 reta = 0, mrqc, rss_key[10]; | ||||
int queue_id, table_size, index_mult; | int queue_id, table_size, index_mult; | ||||
int i, j; | int i, j; | ||||
u32 rss_hash_config; | u32 rss_hash_config; | ||||
if (adapter->feat_en & IXGBE_FEATURE_RSS) { | if (sc->feat_en & IXGBE_FEATURE_RSS) { | ||||
/* Fetch the configured RSS key */ | /* Fetch the configured RSS key */ | ||||
rss_getkey((uint8_t *)&rss_key); | rss_getkey((uint8_t *)&rss_key); | ||||
} else { | } else { | ||||
/* set up random bits */ | /* set up random bits */ | ||||
arc4rand(&rss_key, sizeof(rss_key), 0); | arc4rand(&rss_key, sizeof(rss_key), 0); | ||||
} | } | ||||
/* Set multiplier for RETA setup and table size based on MAC */ | /* Set multiplier for RETA setup and table size based on MAC */ | ||||
index_mult = 0x1; | index_mult = 0x1; | ||||
table_size = 128; | table_size = 128; | ||||
switch (adapter->hw.mac.type) { | switch (sc->hw.mac.type) { | ||||
case ixgbe_mac_82598EB: | case ixgbe_mac_82598EB: | ||||
index_mult = 0x11; | index_mult = 0x11; | ||||
break; | break; | ||||
case ixgbe_mac_X550: | case ixgbe_mac_X550: | ||||
case ixgbe_mac_X550EM_x: | case ixgbe_mac_X550EM_x: | ||||
case ixgbe_mac_X550EM_a: | case ixgbe_mac_X550EM_a: | ||||
table_size = 512; | table_size = 512; | ||||
break; | break; | ||||
default: | default: | ||||
break; | break; | ||||
} | } | ||||
/* Set up the redirection table */ | /* Set up the redirection table */ | ||||
for (i = 0, j = 0; i < table_size; i++, j++) { | for (i = 0, j = 0; i < table_size; i++, j++) { | ||||
if (j == adapter->num_rx_queues) | if (j == sc->num_rx_queues) | ||||
j = 0; | j = 0; | ||||
if (adapter->feat_en & IXGBE_FEATURE_RSS) { | if (sc->feat_en & IXGBE_FEATURE_RSS) { | ||||
/* | /* | ||||
* Fetch the RSS bucket id for the given indirection | * Fetch the RSS bucket id for the given indirection | ||||
* entry. Cap it at the number of configured buckets | * entry. Cap it at the number of configured buckets | ||||
* (which is num_rx_queues.) | * (which is num_rx_queues.) | ||||
*/ | */ | ||||
queue_id = rss_get_indirection_to_bucket(i); | queue_id = rss_get_indirection_to_bucket(i); | ||||
queue_id = queue_id % adapter->num_rx_queues; | queue_id = queue_id % sc->num_rx_queues; | ||||
} else | } else | ||||
queue_id = (j * index_mult); | queue_id = (j * index_mult); | ||||
/* | /* | ||||
* The low 8 bits are for hash value (n+0); | * The low 8 bits are for hash value (n+0); | ||||
* The next 8 bits are for hash value (n+1), etc. | * The next 8 bits are for hash value (n+1), etc. | ||||
*/ | */ | ||||
reta = reta >> 8; | reta = reta >> 8; | ||||
reta = reta | (((uint32_t)queue_id) << 24); | reta = reta | (((uint32_t)queue_id) << 24); | ||||
if ((i & 3) == 3) { | if ((i & 3) == 3) { | ||||
if (i < 128) | if (i < 128) | ||||
IXGBE_WRITE_REG(hw, IXGBE_RETA(i >> 2), reta); | IXGBE_WRITE_REG(hw, IXGBE_RETA(i >> 2), reta); | ||||
else | else | ||||
IXGBE_WRITE_REG(hw, IXGBE_ERETA((i >> 2) - 32), | IXGBE_WRITE_REG(hw, IXGBE_ERETA((i >> 2) - 32), | ||||
reta); | reta); | ||||
reta = 0; | reta = 0; | ||||
} | } | ||||
} | } | ||||
/* Now fill our hash function seeds */ | /* Now fill our hash function seeds */ | ||||
for (i = 0; i < 10; i++) | for (i = 0; i < 10; i++) | ||||
IXGBE_WRITE_REG(hw, IXGBE_RSSRK(i), rss_key[i]); | IXGBE_WRITE_REG(hw, IXGBE_RSSRK(i), rss_key[i]); | ||||
/* Perform hash on these packet types */ | /* Perform hash on these packet types */ | ||||
if (adapter->feat_en & IXGBE_FEATURE_RSS) | if (sc->feat_en & IXGBE_FEATURE_RSS) | ||||
rss_hash_config = rss_gethashconfig(); | rss_hash_config = rss_gethashconfig(); | ||||
else { | else { | ||||
/* | /* | ||||
* Disable UDP - IP fragments aren't currently being handled | * Disable UDP - IP fragments aren't currently being handled | ||||
* and so we end up with a mix of 2-tuple and 4-tuple | * and so we end up with a mix of 2-tuple and 4-tuple | ||||
* traffic. | * traffic. | ||||
*/ | */ | ||||
rss_hash_config = RSS_HASHTYPE_RSS_IPV4 | rss_hash_config = RSS_HASHTYPE_RSS_IPV4 | ||||
Show All 18 Lines | ixgbe_initialize_rss_mapping(struct ixgbe_softc *sc) | ||||
if (rss_hash_config & RSS_HASHTYPE_RSS_TCP_IPV6_EX) | if (rss_hash_config & RSS_HASHTYPE_RSS_TCP_IPV6_EX) | ||||
mrqc |= IXGBE_MRQC_RSS_FIELD_IPV6_EX_TCP; | mrqc |= IXGBE_MRQC_RSS_FIELD_IPV6_EX_TCP; | ||||
if (rss_hash_config & RSS_HASHTYPE_RSS_UDP_IPV4) | if (rss_hash_config & RSS_HASHTYPE_RSS_UDP_IPV4) | ||||
mrqc |= IXGBE_MRQC_RSS_FIELD_IPV4_UDP; | mrqc |= IXGBE_MRQC_RSS_FIELD_IPV4_UDP; | ||||
if (rss_hash_config & RSS_HASHTYPE_RSS_UDP_IPV6) | if (rss_hash_config & RSS_HASHTYPE_RSS_UDP_IPV6) | ||||
mrqc |= IXGBE_MRQC_RSS_FIELD_IPV6_UDP; | mrqc |= IXGBE_MRQC_RSS_FIELD_IPV6_UDP; | ||||
if (rss_hash_config & RSS_HASHTYPE_RSS_UDP_IPV6_EX) | if (rss_hash_config & RSS_HASHTYPE_RSS_UDP_IPV6_EX) | ||||
mrqc |= IXGBE_MRQC_RSS_FIELD_IPV6_EX_UDP; | mrqc |= IXGBE_MRQC_RSS_FIELD_IPV6_EX_UDP; | ||||
mrqc |= ixgbe_get_mrqc(adapter->iov_mode); | mrqc |= ixgbe_get_mrqc(sc->iov_mode); | ||||
IXGBE_WRITE_REG(hw, IXGBE_MRQC, mrqc); | IXGBE_WRITE_REG(hw, IXGBE_MRQC, mrqc); | ||||
} /* ixgbe_initialize_rss_mapping */ | } /* ixgbe_initialize_rss_mapping */ | ||||
/************************************************************************ | /************************************************************************ | ||||
* ixgbe_initialize_receive_units - Setup receive registers and features. | * ixgbe_initialize_receive_units - Setup receive registers and features. | ||||
************************************************************************/ | ************************************************************************/ | ||||
#define BSIZEPKT_ROUNDUP ((1<<IXGBE_SRRCTL_BSIZEPKT_SHIFT)-1) | #define BSIZEPKT_ROUNDUP ((1<<IXGBE_SRRCTL_BSIZEPKT_SHIFT)-1) | ||||
static void | static void | ||||
ixgbe_initialize_receive_units(if_ctx_t ctx) | ixgbe_initialize_receive_units(if_ctx_t ctx) | ||||
{ | { | ||||
struct adapter *adapter = iflib_get_softc(ctx); | struct ixgbe_softc *sc = iflib_get_softc(ctx); | ||||
if_softc_ctx_t scctx = adapter->shared; | if_softc_ctx_t scctx = sc->shared; | ||||
struct ixgbe_hw *hw = &adapter->hw; | struct ixgbe_hw *hw = &sc->hw; | ||||
struct ifnet *ifp = iflib_get_ifp(ctx); | struct ifnet *ifp = iflib_get_ifp(ctx); | ||||
struct ix_rx_queue *que; | struct ix_rx_queue *que; | ||||
int i, j; | int i, j; | ||||
u32 bufsz, fctrl, srrctl, rxcsum; | u32 bufsz, fctrl, srrctl, rxcsum; | ||||
u32 hlreg; | u32 hlreg; | ||||
/* | /* | ||||
* Make sure receives are disabled while | * Make sure receives are disabled while | ||||
* setting up the descriptor ring | * setting up the descriptor ring | ||||
*/ | */ | ||||
ixgbe_disable_rx(hw); | ixgbe_disable_rx(hw); | ||||
/* Enable broadcasts */ | /* Enable broadcasts */ | ||||
fctrl = IXGBE_READ_REG(hw, IXGBE_FCTRL); | fctrl = IXGBE_READ_REG(hw, IXGBE_FCTRL); | ||||
fctrl |= IXGBE_FCTRL_BAM; | fctrl |= IXGBE_FCTRL_BAM; | ||||
if (adapter->hw.mac.type == ixgbe_mac_82598EB) { | if (sc->hw.mac.type == ixgbe_mac_82598EB) { | ||||
fctrl |= IXGBE_FCTRL_DPF; | fctrl |= IXGBE_FCTRL_DPF; | ||||
fctrl |= IXGBE_FCTRL_PMCF; | fctrl |= IXGBE_FCTRL_PMCF; | ||||
} | } | ||||
IXGBE_WRITE_REG(hw, IXGBE_FCTRL, fctrl); | IXGBE_WRITE_REG(hw, IXGBE_FCTRL, fctrl); | ||||
/* Set for Jumbo Frames? */ | /* Set for Jumbo Frames? */ | ||||
hlreg = IXGBE_READ_REG(hw, IXGBE_HLREG0); | hlreg = IXGBE_READ_REG(hw, IXGBE_HLREG0); | ||||
if (ifp->if_mtu > ETHERMTU) | if (ifp->if_mtu > ETHERMTU) | ||||
hlreg |= IXGBE_HLREG0_JUMBOEN; | hlreg |= IXGBE_HLREG0_JUMBOEN; | ||||
else | else | ||||
hlreg &= ~IXGBE_HLREG0_JUMBOEN; | hlreg &= ~IXGBE_HLREG0_JUMBOEN; | ||||
IXGBE_WRITE_REG(hw, IXGBE_HLREG0, hlreg); | IXGBE_WRITE_REG(hw, IXGBE_HLREG0, hlreg); | ||||
bufsz = (adapter->rx_mbuf_sz + BSIZEPKT_ROUNDUP) >> | bufsz = (sc->rx_mbuf_sz + BSIZEPKT_ROUNDUP) >> | ||||
IXGBE_SRRCTL_BSIZEPKT_SHIFT; | IXGBE_SRRCTL_BSIZEPKT_SHIFT; | ||||
/* Setup the Base and Length of the Rx Descriptor Ring */ | /* Setup the Base and Length of the Rx Descriptor Ring */ | ||||
for (i = 0, que = adapter->rx_queues; i < adapter->num_rx_queues; i++, que++) { | for (i = 0, que = sc->rx_queues; i < sc->num_rx_queues; i++, que++) { | ||||
struct rx_ring *rxr = &que->rxr; | struct rx_ring *rxr = &que->rxr; | ||||
u64 rdba = rxr->rx_paddr; | u64 rdba = rxr->rx_paddr; | ||||
j = rxr->me; | j = rxr->me; | ||||
/* Setup the Base and Length of the Rx Descriptor Ring */ | /* Setup the Base and Length of the Rx Descriptor Ring */ | ||||
IXGBE_WRITE_REG(hw, IXGBE_RDBAL(j), | IXGBE_WRITE_REG(hw, IXGBE_RDBAL(j), | ||||
(rdba & 0x00000000ffffffffULL)); | (rdba & 0x00000000ffffffffULL)); | ||||
Show All 9 Lines | for (i = 0, que = sc->rx_queues; i < sc->num_rx_queues; i++, que++) { | ||||
srrctl |= IXGBE_SRRCTL_DESCTYPE_ADV_ONEBUF; | srrctl |= IXGBE_SRRCTL_DESCTYPE_ADV_ONEBUF; | ||||
/* | /* | ||||
* Set DROP_EN iff we have no flow control and >1 queue. | * Set DROP_EN iff we have no flow control and >1 queue. | ||||
* Note that srrctl was cleared shortly before during reset, | * Note that srrctl was cleared shortly before during reset, | ||||
* so we do not need to clear the bit, but do it just in case | * so we do not need to clear the bit, but do it just in case | ||||
* this code is moved elsewhere. | * this code is moved elsewhere. | ||||
*/ | */ | ||||
if (adapter->num_rx_queues > 1 && | if (sc->num_rx_queues > 1 && | ||||
adapter->hw.fc.requested_mode == ixgbe_fc_none) { | sc->hw.fc.requested_mode == ixgbe_fc_none) { | ||||
srrctl |= IXGBE_SRRCTL_DROP_EN; | srrctl |= IXGBE_SRRCTL_DROP_EN; | ||||
} else { | } else { | ||||
srrctl &= ~IXGBE_SRRCTL_DROP_EN; | srrctl &= ~IXGBE_SRRCTL_DROP_EN; | ||||
} | } | ||||
IXGBE_WRITE_REG(hw, IXGBE_SRRCTL(j), srrctl); | IXGBE_WRITE_REG(hw, IXGBE_SRRCTL(j), srrctl); | ||||
/* Setup the HW Rx Head and Tail Descriptor Pointers */ | /* Setup the HW Rx Head and Tail Descriptor Pointers */ | ||||
IXGBE_WRITE_REG(hw, IXGBE_RDH(j), 0); | IXGBE_WRITE_REG(hw, IXGBE_RDH(j), 0); | ||||
IXGBE_WRITE_REG(hw, IXGBE_RDT(j), 0); | IXGBE_WRITE_REG(hw, IXGBE_RDT(j), 0); | ||||
/* Set the driver rx tail address */ | /* Set the driver rx tail address */ | ||||
rxr->tail = IXGBE_RDT(rxr->me); | rxr->tail = IXGBE_RDT(rxr->me); | ||||
} | } | ||||
if (adapter->hw.mac.type != ixgbe_mac_82598EB) { | if (sc->hw.mac.type != ixgbe_mac_82598EB) { | ||||
u32 psrtype = IXGBE_PSRTYPE_TCPHDR | u32 psrtype = IXGBE_PSRTYPE_TCPHDR | ||||
| IXGBE_PSRTYPE_UDPHDR | | IXGBE_PSRTYPE_UDPHDR | ||||
| IXGBE_PSRTYPE_IPV4HDR | | IXGBE_PSRTYPE_IPV4HDR | ||||
| IXGBE_PSRTYPE_IPV6HDR; | | IXGBE_PSRTYPE_IPV6HDR; | ||||
IXGBE_WRITE_REG(hw, IXGBE_PSRTYPE(0), psrtype); | IXGBE_WRITE_REG(hw, IXGBE_PSRTYPE(0), psrtype); | ||||
} | } | ||||
rxcsum = IXGBE_READ_REG(hw, IXGBE_RXCSUM); | rxcsum = IXGBE_READ_REG(hw, IXGBE_RXCSUM); | ||||
ixgbe_initialize_rss_mapping(adapter); | ixgbe_initialize_rss_mapping(sc); | ||||
if (adapter->num_rx_queues > 1) { | if (sc->num_rx_queues > 1) { | ||||
/* RSS and RX IPP Checksum are mutually exclusive */ | /* RSS and RX IPP Checksum are mutually exclusive */ | ||||
rxcsum |= IXGBE_RXCSUM_PCSD; | rxcsum |= IXGBE_RXCSUM_PCSD; | ||||
} | } | ||||
if (ifp->if_capenable & IFCAP_RXCSUM) | if (ifp->if_capenable & IFCAP_RXCSUM) | ||||
rxcsum |= IXGBE_RXCSUM_PCSD; | rxcsum |= IXGBE_RXCSUM_PCSD; | ||||
/* This is useful for calculating UDP/IP fragment checksums */ | /* This is useful for calculating UDP/IP fragment checksums */ | ||||
if (!(rxcsum & IXGBE_RXCSUM_PCSD)) | if (!(rxcsum & IXGBE_RXCSUM_PCSD)) | ||||
rxcsum |= IXGBE_RXCSUM_IPPCSE; | rxcsum |= IXGBE_RXCSUM_IPPCSE; | ||||
IXGBE_WRITE_REG(hw, IXGBE_RXCSUM, rxcsum); | IXGBE_WRITE_REG(hw, IXGBE_RXCSUM, rxcsum); | ||||
} /* ixgbe_initialize_receive_units */ | } /* ixgbe_initialize_receive_units */ | ||||
/************************************************************************ | /************************************************************************ | ||||
* ixgbe_initialize_transmit_units - Enable transmit units. | * ixgbe_initialize_transmit_units - Enable transmit units. | ||||
************************************************************************/ | ************************************************************************/ | ||||
static void | static void | ||||
ixgbe_initialize_transmit_units(if_ctx_t ctx) | ixgbe_initialize_transmit_units(if_ctx_t ctx) | ||||
{ | { | ||||
struct adapter *adapter = iflib_get_softc(ctx); | struct ixgbe_softc *sc = iflib_get_softc(ctx); | ||||
struct ixgbe_hw *hw = &adapter->hw; | struct ixgbe_hw *hw = &sc->hw; | ||||
if_softc_ctx_t scctx = adapter->shared; | if_softc_ctx_t scctx = sc->shared; | ||||
struct ix_tx_queue *que; | struct ix_tx_queue *que; | ||||
int i; | int i; | ||||
/* Setup the Base and Length of the Tx Descriptor Ring */ | /* Setup the Base and Length of the Tx Descriptor Ring */ | ||||
for (i = 0, que = adapter->tx_queues; i < adapter->num_tx_queues; | for (i = 0, que = sc->tx_queues; i < sc->num_tx_queues; | ||||
i++, que++) { | i++, que++) { | ||||
struct tx_ring *txr = &que->txr; | struct tx_ring *txr = &que->txr; | ||||
u64 tdba = txr->tx_paddr; | u64 tdba = txr->tx_paddr; | ||||
u32 txctrl = 0; | u32 txctrl = 0; | ||||
int j = txr->me; | int j = txr->me; | ||||
IXGBE_WRITE_REG(hw, IXGBE_TDBAL(j), | IXGBE_WRITE_REG(hw, IXGBE_TDBAL(j), | ||||
(tdba & 0x00000000ffffffffULL)); | (tdba & 0x00000000ffffffffULL)); | ||||
▲ Show 20 Lines • Show All 45 Lines • ▼ Show 20 Lines | if (hw->mac.type != ixgbe_mac_82598EB) { | ||||
dmatxctl = IXGBE_READ_REG(hw, IXGBE_DMATXCTL); | dmatxctl = IXGBE_READ_REG(hw, IXGBE_DMATXCTL); | ||||
dmatxctl |= IXGBE_DMATXCTL_TE; | dmatxctl |= IXGBE_DMATXCTL_TE; | ||||
IXGBE_WRITE_REG(hw, IXGBE_DMATXCTL, dmatxctl); | IXGBE_WRITE_REG(hw, IXGBE_DMATXCTL, dmatxctl); | ||||
/* Disable arbiter to set MTQC */ | /* Disable arbiter to set MTQC */ | ||||
rttdcs = IXGBE_READ_REG(hw, IXGBE_RTTDCS); | rttdcs = IXGBE_READ_REG(hw, IXGBE_RTTDCS); | ||||
rttdcs |= IXGBE_RTTDCS_ARBDIS; | rttdcs |= IXGBE_RTTDCS_ARBDIS; | ||||
IXGBE_WRITE_REG(hw, IXGBE_RTTDCS, rttdcs); | IXGBE_WRITE_REG(hw, IXGBE_RTTDCS, rttdcs); | ||||
IXGBE_WRITE_REG(hw, IXGBE_MTQC, | IXGBE_WRITE_REG(hw, IXGBE_MTQC, | ||||
ixgbe_get_mtqc(adapter->iov_mode)); | ixgbe_get_mtqc(sc->iov_mode)); | ||||
rttdcs &= ~IXGBE_RTTDCS_ARBDIS; | rttdcs &= ~IXGBE_RTTDCS_ARBDIS; | ||||
IXGBE_WRITE_REG(hw, IXGBE_RTTDCS, rttdcs); | IXGBE_WRITE_REG(hw, IXGBE_RTTDCS, rttdcs); | ||||
} | } | ||||
} /* ixgbe_initialize_transmit_units */ | } /* ixgbe_initialize_transmit_units */ | ||||
/************************************************************************ | /************************************************************************ | ||||
* ixgbe_register | * ixgbe_register | ||||
Show All 11 Lines | |||||
* Identifies the type of hardware, initializes the hardware, | * Identifies the type of hardware, initializes the hardware, | ||||
* and initializes iflib structures. | * and initializes iflib structures. | ||||
* | * | ||||
* return 0 on success, positive on failure | * return 0 on success, positive on failure | ||||
************************************************************************/ | ************************************************************************/ | ||||
static int | static int | ||||
ixgbe_if_attach_pre(if_ctx_t ctx) | ixgbe_if_attach_pre(if_ctx_t ctx) | ||||
{ | { | ||||
struct adapter *adapter; | struct ixgbe_softc *sc; | ||||
device_t dev; | device_t dev; | ||||
if_softc_ctx_t scctx; | if_softc_ctx_t scctx; | ||||
struct ixgbe_hw *hw; | struct ixgbe_hw *hw; | ||||
int error = 0; | int error = 0; | ||||
u32 ctrl_ext; | u32 ctrl_ext; | ||||
INIT_DEBUGOUT("ixgbe_attach: begin"); | INIT_DEBUGOUT("ixgbe_attach: begin"); | ||||
/* Allocate, clear, and link in our adapter structure */ | /* Allocate, clear, and link in our adapter structure */ | ||||
dev = iflib_get_dev(ctx); | dev = iflib_get_dev(ctx); | ||||
adapter = iflib_get_softc(ctx); | sc = iflib_get_softc(ctx); | ||||
adapter->hw.back = adapter; | sc->hw.back = sc; | ||||
adapter->ctx = ctx; | sc->ctx = ctx; | ||||
adapter->dev = dev; | sc->dev = dev; | ||||
scctx = adapter->shared = iflib_get_softc_ctx(ctx); | scctx = sc->shared = iflib_get_softc_ctx(ctx); | ||||
adapter->media = iflib_get_media(ctx); | sc->media = iflib_get_media(ctx); | ||||
hw = &adapter->hw; | hw = &sc->hw; | ||||
/* Determine hardware revision */ | /* Determine hardware revision */ | ||||
hw->vendor_id = pci_get_vendor(dev); | hw->vendor_id = pci_get_vendor(dev); | ||||
hw->device_id = pci_get_device(dev); | hw->device_id = pci_get_device(dev); | ||||
hw->revision_id = pci_get_revid(dev); | hw->revision_id = pci_get_revid(dev); | ||||
hw->subsystem_vendor_id = pci_get_subvendor(dev); | hw->subsystem_vendor_id = pci_get_subvendor(dev); | ||||
hw->subsystem_device_id = pci_get_subdevice(dev); | hw->subsystem_device_id = pci_get_subdevice(dev); | ||||
Show All 20 Lines | ixgbe_if_attach_pre(if_ctx_t ctx) | ||||
if (hw->mbx.ops.init_params) | if (hw->mbx.ops.init_params) | ||||
hw->mbx.ops.init_params(hw); | hw->mbx.ops.init_params(hw); | ||||
hw->allow_unsupported_sfp = allow_unsupported_sfp; | hw->allow_unsupported_sfp = allow_unsupported_sfp; | ||||
if (hw->mac.type != ixgbe_mac_82598EB) | if (hw->mac.type != ixgbe_mac_82598EB) | ||||
hw->phy.smart_speed = ixgbe_smart_speed; | hw->phy.smart_speed = ixgbe_smart_speed; | ||||
ixgbe_init_device_features(adapter); | ixgbe_init_device_features(sc); | ||||
/* Enable WoL (if supported) */ | /* Enable WoL (if supported) */ | ||||
ixgbe_check_wol_support(adapter); | ixgbe_check_wol_support(sc); | ||||
/* Verify adapter fan is still functional (if applicable) */ | /* Verify adapter fan is still functional (if applicable) */ | ||||
if (adapter->feat_en & IXGBE_FEATURE_FAN_FAIL) { | if (sc->feat_en & IXGBE_FEATURE_FAN_FAIL) { | ||||
u32 esdp = IXGBE_READ_REG(hw, IXGBE_ESDP); | u32 esdp = IXGBE_READ_REG(hw, IXGBE_ESDP); | ||||
ixgbe_check_fan_failure(adapter, esdp, false); | ixgbe_check_fan_failure(sc, esdp, false); | ||||
} | } | ||||
/* Ensure SW/FW semaphore is free */ | /* Ensure SW/FW semaphore is free */ | ||||
ixgbe_init_swfw_semaphore(hw); | ixgbe_init_swfw_semaphore(hw); | ||||
/* Set an initial default flow control value */ | /* Set an initial default flow control value */ | ||||
hw->fc.requested_mode = ixgbe_flow_control; | hw->fc.requested_mode = ixgbe_flow_control; | ||||
hw->phy.reset_if_overtemp = true; | hw->phy.reset_if_overtemp = true; | ||||
error = ixgbe_reset_hw(hw); | error = ixgbe_reset_hw(hw); | ||||
hw->phy.reset_if_overtemp = false; | hw->phy.reset_if_overtemp = false; | ||||
if (error == IXGBE_ERR_SFP_NOT_PRESENT) { | if (error == IXGBE_ERR_SFP_NOT_PRESENT) { | ||||
/* | /* | ||||
* No optics in this port, set up | * No optics in this port, set up | ||||
* so the timer routine will probe | * so the timer routine will probe | ||||
* for later insertion. | * for later insertion. | ||||
*/ | */ | ||||
adapter->sfp_probe = true; | sc->sfp_probe = true; | ||||
error = 0; | error = 0; | ||||
} else if (error == IXGBE_ERR_SFP_NOT_SUPPORTED) { | } else if (error == IXGBE_ERR_SFP_NOT_SUPPORTED) { | ||||
device_printf(dev, "Unsupported SFP+ module detected!\n"); | device_printf(dev, "Unsupported SFP+ module detected!\n"); | ||||
error = EIO; | error = EIO; | ||||
goto err_pci; | goto err_pci; | ||||
} else if (error) { | } else if (error) { | ||||
device_printf(dev, "Hardware initialization failed\n"); | device_printf(dev, "Hardware initialization failed\n"); | ||||
error = EIO; | error = EIO; | ||||
goto err_pci; | goto err_pci; | ||||
} | } | ||||
/* Make sure we have a good EEPROM before we read from it */ | /* Make sure we have a good EEPROM before we read from it */ | ||||
if (ixgbe_validate_eeprom_checksum(&adapter->hw, NULL) < 0) { | if (ixgbe_validate_eeprom_checksum(&sc->hw, NULL) < 0) { | ||||
device_printf(dev, "The EEPROM Checksum Is Not Valid\n"); | device_printf(dev, "The EEPROM Checksum Is Not Valid\n"); | ||||
error = EIO; | error = EIO; | ||||
goto err_pci; | goto err_pci; | ||||
} | } | ||||
error = ixgbe_start_hw(hw); | error = ixgbe_start_hw(hw); | ||||
switch (error) { | switch (error) { | ||||
case IXGBE_ERR_EEPROM_VERSION: | case IXGBE_ERR_EEPROM_VERSION: | ||||
device_printf(dev, "This device is a pre-production adapter/LOM. Please be aware there may be issues associated with your hardware.\nIf you are experiencing problems please contact your Intel or hardware representative who provided you with this hardware.\n"); | device_printf(dev, "This device is a pre-production adapter/LOM. Please be aware there may be issues associated with your hardware.\nIf you are experiencing problems please contact your Intel or hardware representative who provided you with this hardware.\n"); | ||||
break; | break; | ||||
case IXGBE_ERR_SFP_NOT_SUPPORTED: | case IXGBE_ERR_SFP_NOT_SUPPORTED: | ||||
device_printf(dev, "Unsupported SFP+ Module\n"); | device_printf(dev, "Unsupported SFP+ Module\n"); | ||||
error = EIO; | error = EIO; | ||||
goto err_pci; | goto err_pci; | ||||
case IXGBE_ERR_SFP_NOT_PRESENT: | case IXGBE_ERR_SFP_NOT_PRESENT: | ||||
device_printf(dev, "No SFP+ Module found\n"); | device_printf(dev, "No SFP+ Module found\n"); | ||||
/* falls thru */ | /* falls thru */ | ||||
default: | default: | ||||
break; | break; | ||||
} | } | ||||
/* Most of the iflib initialization... */ | /* Most of the iflib initialization... */ | ||||
iflib_set_mac(ctx, hw->mac.addr); | iflib_set_mac(ctx, hw->mac.addr); | ||||
switch (adapter->hw.mac.type) { | switch (sc->hw.mac.type) { | ||||
case ixgbe_mac_X550: | case ixgbe_mac_X550: | ||||
case ixgbe_mac_X550EM_x: | case ixgbe_mac_X550EM_x: | ||||
case ixgbe_mac_X550EM_a: | case ixgbe_mac_X550EM_a: | ||||
scctx->isc_rss_table_size = 512; | scctx->isc_rss_table_size = 512; | ||||
scctx->isc_ntxqsets_max = scctx->isc_nrxqsets_max = 64; | scctx->isc_ntxqsets_max = scctx->isc_nrxqsets_max = 64; | ||||
break; | break; | ||||
default: | default: | ||||
scctx->isc_rss_table_size = 128; | scctx->isc_rss_table_size = 128; | ||||
scctx->isc_ntxqsets_max = scctx->isc_nrxqsets_max = 16; | scctx->isc_ntxqsets_max = scctx->isc_nrxqsets_max = 16; | ||||
} | } | ||||
/* Allow legacy interrupts */ | /* Allow legacy interrupts */ | ||||
ixgbe_txrx.ift_legacy_intr = ixgbe_intr; | ixgbe_txrx.ift_legacy_intr = ixgbe_intr; | ||||
scctx->isc_txqsizes[0] = | scctx->isc_txqsizes[0] = | ||||
roundup2(scctx->isc_ntxd[0] * sizeof(union ixgbe_adv_tx_desc) + | roundup2(scctx->isc_ntxd[0] * sizeof(union ixgbe_adv_tx_desc) + | ||||
sizeof(u32), DBA_ALIGN), | sizeof(u32), DBA_ALIGN), | ||||
scctx->isc_rxqsizes[0] = | scctx->isc_rxqsizes[0] = | ||||
roundup2(scctx->isc_nrxd[0] * sizeof(union ixgbe_adv_rx_desc), | roundup2(scctx->isc_nrxd[0] * sizeof(union ixgbe_adv_rx_desc), | ||||
DBA_ALIGN); | DBA_ALIGN); | ||||
/* XXX */ | /* XXX */ | ||||
scctx->isc_tx_csum_flags = CSUM_IP | CSUM_TCP | CSUM_UDP | CSUM_TSO | | scctx->isc_tx_csum_flags = CSUM_IP | CSUM_TCP | CSUM_UDP | CSUM_TSO | | ||||
CSUM_IP6_TCP | CSUM_IP6_UDP | CSUM_IP6_TSO; | CSUM_IP6_TCP | CSUM_IP6_UDP | CSUM_IP6_TSO; | ||||
if (adapter->hw.mac.type == ixgbe_mac_82598EB) { | if (sc->hw.mac.type == ixgbe_mac_82598EB) { | ||||
scctx->isc_tx_nsegments = IXGBE_82598_SCATTER; | scctx->isc_tx_nsegments = IXGBE_82598_SCATTER; | ||||
} else { | } else { | ||||
scctx->isc_tx_csum_flags |= CSUM_SCTP |CSUM_IP6_SCTP; | scctx->isc_tx_csum_flags |= CSUM_SCTP |CSUM_IP6_SCTP; | ||||
scctx->isc_tx_nsegments = IXGBE_82599_SCATTER; | scctx->isc_tx_nsegments = IXGBE_82599_SCATTER; | ||||
} | } | ||||
scctx->isc_msix_bar = pci_msix_table_bar(dev); | scctx->isc_msix_bar = pci_msix_table_bar(dev); | ||||
scctx->isc_tx_tso_segments_max = scctx->isc_tx_nsegments; | scctx->isc_tx_tso_segments_max = scctx->isc_tx_nsegments; | ||||
scctx->isc_tx_tso_size_max = IXGBE_TSO_SIZE; | scctx->isc_tx_tso_size_max = IXGBE_TSO_SIZE; | ||||
scctx->isc_tx_tso_segsize_max = PAGE_SIZE; | scctx->isc_tx_tso_segsize_max = PAGE_SIZE; | ||||
scctx->isc_txrx = &ixgbe_txrx; | scctx->isc_txrx = &ixgbe_txrx; | ||||
scctx->isc_capabilities = scctx->isc_capenable = IXGBE_CAPS; | scctx->isc_capabilities = scctx->isc_capenable = IXGBE_CAPS; | ||||
return (0); | return (0); | ||||
err_pci: | err_pci: | ||||
ctrl_ext = IXGBE_READ_REG(&adapter->hw, IXGBE_CTRL_EXT); | ctrl_ext = IXGBE_READ_REG(&sc->hw, IXGBE_CTRL_EXT); | ||||
ctrl_ext &= ~IXGBE_CTRL_EXT_DRV_LOAD; | ctrl_ext &= ~IXGBE_CTRL_EXT_DRV_LOAD; | ||||
IXGBE_WRITE_REG(&adapter->hw, IXGBE_CTRL_EXT, ctrl_ext); | IXGBE_WRITE_REG(&sc->hw, IXGBE_CTRL_EXT, ctrl_ext); | ||||
ixgbe_free_pci_resources(ctx); | ixgbe_free_pci_resources(ctx); | ||||
return (error); | return (error); | ||||
} /* ixgbe_if_attach_pre */ | } /* ixgbe_if_attach_pre */ | ||||
/********************************************************************* | /********************************************************************* | ||||
* ixgbe_if_attach_post - Device initialization routine, part 2 | * ixgbe_if_attach_post - Device initialization routine, part 2 | ||||
* | * | ||||
* Called during driver load, but after interrupts and | * Called during driver load, but after interrupts and | ||||
* resources have been allocated and configured. | * resources have been allocated and configured. | ||||
* Sets up some data structures not relevant to iflib. | * Sets up some data structures not relevant to iflib. | ||||
* | * | ||||
* return 0 on success, positive on failure | * return 0 on success, positive on failure | ||||
*********************************************************************/ | *********************************************************************/ | ||||
static int | static int | ||||
ixgbe_if_attach_post(if_ctx_t ctx) | ixgbe_if_attach_post(if_ctx_t ctx) | ||||
{ | { | ||||
device_t dev; | device_t dev; | ||||
struct adapter *adapter; | struct ixgbe_softc *sc; | ||||
struct ixgbe_hw *hw; | struct ixgbe_hw *hw; | ||||
int error = 0; | int error = 0; | ||||
dev = iflib_get_dev(ctx); | dev = iflib_get_dev(ctx); | ||||
adapter = iflib_get_softc(ctx); | sc = iflib_get_softc(ctx); | ||||
hw = &adapter->hw; | hw = &sc->hw; | ||||
if (adapter->intr_type == IFLIB_INTR_LEGACY && | if (sc->intr_type == IFLIB_INTR_LEGACY && | ||||
(adapter->feat_cap & IXGBE_FEATURE_LEGACY_IRQ) == 0) { | (sc->feat_cap & IXGBE_FEATURE_LEGACY_IRQ) == 0) { | ||||
device_printf(dev, "Device does not support legacy interrupts"); | device_printf(dev, "Device does not support legacy interrupts"); | ||||
error = ENXIO; | error = ENXIO; | ||||
goto err; | goto err; | ||||
} | } | ||||
/* Allocate multicast array memory. */ | /* Allocate multicast array memory. */ | ||||
adapter->mta = malloc(sizeof(*adapter->mta) * | sc->mta = malloc(sizeof(*sc->mta) * | ||||
MAX_NUM_MULTICAST_ADDRESSES, M_IXGBE, M_NOWAIT); | MAX_NUM_MULTICAST_ADDRESSES, M_IXGBE, M_NOWAIT); | ||||
if (adapter->mta == NULL) { | if (sc->mta == NULL) { | ||||
device_printf(dev, "Can not allocate multicast setup array\n"); | device_printf(dev, "Can not allocate multicast setup array\n"); | ||||
error = ENOMEM; | error = ENOMEM; | ||||
goto err; | goto err; | ||||
} | } | ||||
/* hw.ix defaults init */ | /* hw.ix defaults init */ | ||||
ixgbe_set_advertise(adapter, ixgbe_advertise_speed); | ixgbe_set_advertise(sc, ixgbe_advertise_speed); | ||||
/* Enable the optics for 82599 SFP+ fiber */ | /* Enable the optics for 82599 SFP+ fiber */ | ||||
ixgbe_enable_tx_laser(hw); | ixgbe_enable_tx_laser(hw); | ||||
/* Enable power to the phy. */ | /* Enable power to the phy. */ | ||||
ixgbe_set_phy_power(hw, true); | ixgbe_set_phy_power(hw, true); | ||||
ixgbe_initialize_iov(adapter); | ixgbe_initialize_iov(sc); | ||||
error = ixgbe_setup_interface(ctx); | error = ixgbe_setup_interface(ctx); | ||||
if (error) { | if (error) { | ||||
device_printf(dev, "Interface setup failed: %d\n", error); | device_printf(dev, "Interface setup failed: %d\n", error); | ||||
goto err; | goto err; | ||||
} | } | ||||
ixgbe_if_update_admin_status(ctx); | ixgbe_if_update_admin_status(ctx); | ||||
/* Initialize statistics */ | /* Initialize statistics */ | ||||
ixgbe_update_stats_counters(adapter); | ixgbe_update_stats_counters(sc); | ||||
ixgbe_add_hw_stats(adapter); | ixgbe_add_hw_stats(sc); | ||||
/* Check PCIE slot type/speed/width */ | /* Check PCIE slot type/speed/width */ | ||||
ixgbe_get_slot_info(adapter); | ixgbe_get_slot_info(sc); | ||||
/* | /* | ||||
* Do time init and sysctl init here, but | * Do time init and sysctl init here, but | ||||
* only on the first port of a bypass adapter. | * only on the first port of a bypass sc. | ||||
*/ | */ | ||||
ixgbe_bypass_init(adapter); | ixgbe_bypass_init(sc); | ||||
/* Display NVM and Option ROM versions */ | /* Display NVM and Option ROM versions */ | ||||
ixgbe_print_fw_version(ctx); | ixgbe_print_fw_version(ctx); | ||||
/* Set an initial dmac value */ | /* Set an initial dmac value */ | ||||
adapter->dmac = 0; | sc->dmac = 0; | ||||
/* Set initial advertised speeds (if applicable) */ | /* Set initial advertised speeds (if applicable) */ | ||||
adapter->advertise = ixgbe_get_advertise(adapter); | sc->advertise = ixgbe_get_advertise(sc); | ||||
if (adapter->feat_cap & IXGBE_FEATURE_SRIOV) | if (sc->feat_cap & IXGBE_FEATURE_SRIOV) | ||||
ixgbe_define_iov_schemas(dev, &error); | ixgbe_define_iov_schemas(dev, &error); | ||||
/* Add sysctls */ | /* Add sysctls */ | ||||
ixgbe_add_device_sysctls(ctx); | ixgbe_add_device_sysctls(ctx); | ||||
return (0); | return (0); | ||||
err: | err: | ||||
return (error); | return (error); | ||||
} /* ixgbe_if_attach_post */ | } /* ixgbe_if_attach_post */ | ||||
/************************************************************************ | /************************************************************************ | ||||
* ixgbe_check_wol_support | * ixgbe_check_wol_support | ||||
* | * | ||||
* Checks whether the adapter's ports are capable of | * Checks whether the adapter's ports are capable of | ||||
* Wake On LAN by reading the adapter's NVM. | * Wake On LAN by reading the adapter's NVM. | ||||
* | * | ||||
* Sets each port's hw->wol_enabled value depending | * Sets each port's hw->wol_enabled value depending | ||||
* on the value read here. | * on the value read here. | ||||
************************************************************************/ | ************************************************************************/ | ||||
static void | static void | ||||
ixgbe_check_wol_support(struct adapter *adapter) | ixgbe_check_wol_support(struct ixgbe_softc *sc) | ||||
{ | { | ||||
struct ixgbe_hw *hw = &adapter->hw; | struct ixgbe_hw *hw = &sc->hw; | ||||
u16 dev_caps = 0; | u16 dev_caps = 0; | ||||
/* Find out WoL support for port */ | /* Find out WoL support for port */ | ||||
adapter->wol_support = hw->wol_enabled = 0; | sc->wol_support = hw->wol_enabled = 0; | ||||
ixgbe_get_device_caps(hw, &dev_caps); | ixgbe_get_device_caps(hw, &dev_caps); | ||||
if ((dev_caps & IXGBE_DEVICE_CAPS_WOL_PORT0_1) || | if ((dev_caps & IXGBE_DEVICE_CAPS_WOL_PORT0_1) || | ||||
((dev_caps & IXGBE_DEVICE_CAPS_WOL_PORT0) && | ((dev_caps & IXGBE_DEVICE_CAPS_WOL_PORT0) && | ||||
hw->bus.func == 0)) | hw->bus.func == 0)) | ||||
adapter->wol_support = hw->wol_enabled = 1; | sc->wol_support = hw->wol_enabled = 1; | ||||
/* Save initial wake up filter configuration */ | /* Save initial wake up filter configuration */ | ||||
adapter->wufc = IXGBE_READ_REG(hw, IXGBE_WUFC); | sc->wufc = IXGBE_READ_REG(hw, IXGBE_WUFC); | ||||
return; | return; | ||||
} /* ixgbe_check_wol_support */ | } /* ixgbe_check_wol_support */ | ||||
/************************************************************************ | /************************************************************************ | ||||
* ixgbe_setup_interface | * ixgbe_setup_interface | ||||
* | * | ||||
* Setup networking device structure and register an interface. | * Setup networking device structure and register an interface. | ||||
************************************************************************/ | ************************************************************************/ | ||||
static int | static int | ||||
ixgbe_setup_interface(if_ctx_t ctx) | ixgbe_setup_interface(if_ctx_t ctx) | ||||
{ | { | ||||
struct ifnet *ifp = iflib_get_ifp(ctx); | struct ifnet *ifp = iflib_get_ifp(ctx); | ||||
struct adapter *adapter = iflib_get_softc(ctx); | struct ixgbe_softc *sc = iflib_get_softc(ctx); | ||||
INIT_DEBUGOUT("ixgbe_setup_interface: begin"); | INIT_DEBUGOUT("ixgbe_setup_interface: begin"); | ||||
if_setbaudrate(ifp, IF_Gbps(10)); | if_setbaudrate(ifp, IF_Gbps(10)); | ||||
adapter->max_frame_size = ifp->if_mtu + ETHER_HDR_LEN + ETHER_CRC_LEN; | sc->max_frame_size = ifp->if_mtu + ETHER_HDR_LEN + ETHER_CRC_LEN; | ||||
adapter->phy_layer = ixgbe_get_supported_physical_layer(&adapter->hw); | sc->phy_layer = ixgbe_get_supported_physical_layer(&sc->hw); | ||||
ixgbe_add_media_types(ctx); | ixgbe_add_media_types(ctx); | ||||
/* Autoselect media by default */ | /* Autoselect media by default */ | ||||
ifmedia_set(adapter->media, IFM_ETHER | IFM_AUTO); | ifmedia_set(sc->media, IFM_ETHER | IFM_AUTO); | ||||
return (0); | return (0); | ||||
} /* ixgbe_setup_interface */ | } /* ixgbe_setup_interface */ | ||||
/************************************************************************ | /************************************************************************ | ||||
* ixgbe_if_get_counter | * ixgbe_if_get_counter | ||||
************************************************************************/ | ************************************************************************/ | ||||
static uint64_t | static uint64_t | ||||
ixgbe_if_get_counter(if_ctx_t ctx, ift_counter cnt) | ixgbe_if_get_counter(if_ctx_t ctx, ift_counter cnt) | ||||
{ | { | ||||
struct adapter *adapter = iflib_get_softc(ctx); | struct ixgbe_softc *sc = iflib_get_softc(ctx); | ||||
if_t ifp = iflib_get_ifp(ctx); | if_t ifp = iflib_get_ifp(ctx); | ||||
switch (cnt) { | switch (cnt) { | ||||
case IFCOUNTER_IPACKETS: | case IFCOUNTER_IPACKETS: | ||||
return (adapter->ipackets); | return (sc->ipackets); | ||||
case IFCOUNTER_OPACKETS: | case IFCOUNTER_OPACKETS: | ||||
return (adapter->opackets); | return (sc->opackets); | ||||
case IFCOUNTER_IBYTES: | case IFCOUNTER_IBYTES: | ||||
return (adapter->ibytes); | return (sc->ibytes); | ||||
case IFCOUNTER_OBYTES: | case IFCOUNTER_OBYTES: | ||||
return (adapter->obytes); | return (sc->obytes); | ||||
case IFCOUNTER_IMCASTS: | case IFCOUNTER_IMCASTS: | ||||
return (adapter->imcasts); | return (sc->imcasts); | ||||
case IFCOUNTER_OMCASTS: | case IFCOUNTER_OMCASTS: | ||||
return (adapter->omcasts); | return (sc->omcasts); | ||||
case IFCOUNTER_COLLISIONS: | case IFCOUNTER_COLLISIONS: | ||||
return (0); | return (0); | ||||
case IFCOUNTER_IQDROPS: | case IFCOUNTER_IQDROPS: | ||||
return (adapter->iqdrops); | return (sc->iqdrops); | ||||
case IFCOUNTER_OQDROPS: | case IFCOUNTER_OQDROPS: | ||||
return (0); | return (0); | ||||
case IFCOUNTER_IERRORS: | case IFCOUNTER_IERRORS: | ||||
return (adapter->ierrors); | return (sc->ierrors); | ||||
default: | default: | ||||
return (if_get_counter_default(ifp, cnt)); | return (if_get_counter_default(ifp, cnt)); | ||||
} | } | ||||
} /* ixgbe_if_get_counter */ | } /* ixgbe_if_get_counter */ | ||||
/************************************************************************ | /************************************************************************ | ||||
* ixgbe_if_i2c_req | * ixgbe_if_i2c_req | ||||
************************************************************************/ | ************************************************************************/ | ||||
static int | static int | ||||
ixgbe_if_i2c_req(if_ctx_t ctx, struct ifi2creq *req) | ixgbe_if_i2c_req(if_ctx_t ctx, struct ifi2creq *req) | ||||
{ | { | ||||
struct adapter *adapter = iflib_get_softc(ctx); | struct ixgbe_softc *sc = iflib_get_softc(ctx); | ||||
struct ixgbe_hw *hw = &adapter->hw; | struct ixgbe_hw *hw = &sc->hw; | ||||
int i; | int i; | ||||
if (hw->phy.ops.read_i2c_byte == NULL) | if (hw->phy.ops.read_i2c_byte == NULL) | ||||
return (ENXIO); | return (ENXIO); | ||||
for (i = 0; i < req->len; i++) | for (i = 0; i < req->len; i++) | ||||
hw->phy.ops.read_i2c_byte(hw, req->offset + i, | hw->phy.ops.read_i2c_byte(hw, req->offset + i, | ||||
req->dev_addr, &req->data[i]); | req->dev_addr, &req->data[i]); | ||||
Show All 20 Lines | |||||
} | } | ||||
/************************************************************************ | /************************************************************************ | ||||
* ixgbe_add_media_types | * ixgbe_add_media_types | ||||
************************************************************************/ | ************************************************************************/ | ||||
static void | static void | ||||
ixgbe_add_media_types(if_ctx_t ctx) | ixgbe_add_media_types(if_ctx_t ctx) | ||||
{ | { | ||||
struct adapter *adapter = iflib_get_softc(ctx); | struct ixgbe_softc *sc = iflib_get_softc(ctx); | ||||
struct ixgbe_hw *hw = &adapter->hw; | struct ixgbe_hw *hw = &sc->hw; | ||||
device_t dev = iflib_get_dev(ctx); | device_t dev = iflib_get_dev(ctx); | ||||
u64 layer; | u64 layer; | ||||
layer = adapter->phy_layer = ixgbe_get_supported_physical_layer(hw); | layer = sc->phy_layer = ixgbe_get_supported_physical_layer(hw); | ||||
/* Media types with matching FreeBSD media defines */ | /* Media types with matching FreeBSD media defines */ | ||||
if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_T) | if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_T) | ||||
ifmedia_add(adapter->media, IFM_ETHER | IFM_10G_T, 0, NULL); | ifmedia_add(sc->media, IFM_ETHER | IFM_10G_T, 0, NULL); | ||||
if (layer & IXGBE_PHYSICAL_LAYER_1000BASE_T) | if (layer & IXGBE_PHYSICAL_LAYER_1000BASE_T) | ||||
ifmedia_add(adapter->media, IFM_ETHER | IFM_1000_T, 0, NULL); | ifmedia_add(sc->media, IFM_ETHER | IFM_1000_T, 0, NULL); | ||||
if (layer & IXGBE_PHYSICAL_LAYER_100BASE_TX) | if (layer & IXGBE_PHYSICAL_LAYER_100BASE_TX) | ||||
ifmedia_add(adapter->media, IFM_ETHER | IFM_100_TX, 0, NULL); | ifmedia_add(sc->media, IFM_ETHER | IFM_100_TX, 0, NULL); | ||||
if (layer & IXGBE_PHYSICAL_LAYER_10BASE_T) | if (layer & IXGBE_PHYSICAL_LAYER_10BASE_T) | ||||
ifmedia_add(adapter->media, IFM_ETHER | IFM_10_T, 0, NULL); | ifmedia_add(sc->media, IFM_ETHER | IFM_10_T, 0, NULL); | ||||
if (layer & IXGBE_PHYSICAL_LAYER_SFP_PLUS_CU || | if (layer & IXGBE_PHYSICAL_LAYER_SFP_PLUS_CU || | ||||
layer & IXGBE_PHYSICAL_LAYER_SFP_ACTIVE_DA) | layer & IXGBE_PHYSICAL_LAYER_SFP_ACTIVE_DA) | ||||
ifmedia_add(adapter->media, IFM_ETHER | IFM_10G_TWINAX, 0, | ifmedia_add(sc->media, IFM_ETHER | IFM_10G_TWINAX, 0, | ||||
NULL); | NULL); | ||||
if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_LR) { | if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_LR) { | ||||
ifmedia_add(adapter->media, IFM_ETHER | IFM_10G_LR, 0, NULL); | ifmedia_add(sc->media, IFM_ETHER | IFM_10G_LR, 0, NULL); | ||||
if (hw->phy.multispeed_fiber) | if (hw->phy.multispeed_fiber) | ||||
ifmedia_add(adapter->media, IFM_ETHER | IFM_1000_LX, 0, | ifmedia_add(sc->media, IFM_ETHER | IFM_1000_LX, 0, | ||||
NULL); | NULL); | ||||
} | } | ||||
if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_SR) { | if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_SR) { | ||||
ifmedia_add(adapter->media, IFM_ETHER | IFM_10G_SR, 0, NULL); | ifmedia_add(sc->media, IFM_ETHER | IFM_10G_SR, 0, NULL); | ||||
if (hw->phy.multispeed_fiber) | if (hw->phy.multispeed_fiber) | ||||
ifmedia_add(adapter->media, IFM_ETHER | IFM_1000_SX, 0, | ifmedia_add(sc->media, IFM_ETHER | IFM_1000_SX, 0, | ||||
NULL); | NULL); | ||||
} else if (layer & IXGBE_PHYSICAL_LAYER_1000BASE_SX) | } else if (layer & IXGBE_PHYSICAL_LAYER_1000BASE_SX) | ||||
ifmedia_add(adapter->media, IFM_ETHER | IFM_1000_SX, 0, NULL); | ifmedia_add(sc->media, IFM_ETHER | IFM_1000_SX, 0, NULL); | ||||
if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_CX4) | if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_CX4) | ||||
ifmedia_add(adapter->media, IFM_ETHER | IFM_10G_CX4, 0, NULL); | ifmedia_add(sc->media, IFM_ETHER | IFM_10G_CX4, 0, NULL); | ||||
#ifdef IFM_ETH_XTYPE | #ifdef IFM_ETH_XTYPE | ||||
if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_KR) | if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_KR) | ||||
ifmedia_add(adapter->media, IFM_ETHER | IFM_10G_KR, 0, NULL); | ifmedia_add(sc->media, IFM_ETHER | IFM_10G_KR, 0, NULL); | ||||
if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_KX4) | if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_KX4) | ||||
ifmedia_add( adapter->media, IFM_ETHER | IFM_10G_KX4, 0, NULL); | ifmedia_add( sc->media, IFM_ETHER | IFM_10G_KX4, 0, NULL); | ||||
if (layer & IXGBE_PHYSICAL_LAYER_1000BASE_KX) | if (layer & IXGBE_PHYSICAL_LAYER_1000BASE_KX) | ||||
ifmedia_add(adapter->media, IFM_ETHER | IFM_1000_KX, 0, NULL); | ifmedia_add(sc->media, IFM_ETHER | IFM_1000_KX, 0, NULL); | ||||
if (layer & IXGBE_PHYSICAL_LAYER_2500BASE_KX) | if (layer & IXGBE_PHYSICAL_LAYER_2500BASE_KX) | ||||
ifmedia_add(adapter->media, IFM_ETHER | IFM_2500_KX, 0, NULL); | ifmedia_add(sc->media, IFM_ETHER | IFM_2500_KX, 0, NULL); | ||||
#else | #else | ||||
if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_KR) { | if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_KR) { | ||||
device_printf(dev, "Media supported: 10GbaseKR\n"); | device_printf(dev, "Media supported: 10GbaseKR\n"); | ||||
device_printf(dev, "10GbaseKR mapped to 10GbaseSR\n"); | device_printf(dev, "10GbaseKR mapped to 10GbaseSR\n"); | ||||
ifmedia_add(adapter->media, IFM_ETHER | IFM_10G_SR, 0, NULL); | ifmedia_add(sc->media, IFM_ETHER | IFM_10G_SR, 0, NULL); | ||||
} | } | ||||
if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_KX4) { | if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_KX4) { | ||||
device_printf(dev, "Media supported: 10GbaseKX4\n"); | device_printf(dev, "Media supported: 10GbaseKX4\n"); | ||||
device_printf(dev, "10GbaseKX4 mapped to 10GbaseCX4\n"); | device_printf(dev, "10GbaseKX4 mapped to 10GbaseCX4\n"); | ||||
ifmedia_add(adapter->media, IFM_ETHER | IFM_10G_CX4, 0, NULL); | ifmedia_add(sc->media, IFM_ETHER | IFM_10G_CX4, 0, NULL); | ||||
} | } | ||||
if (layer & IXGBE_PHYSICAL_LAYER_1000BASE_KX) { | if (layer & IXGBE_PHYSICAL_LAYER_1000BASE_KX) { | ||||
device_printf(dev, "Media supported: 1000baseKX\n"); | device_printf(dev, "Media supported: 1000baseKX\n"); | ||||
device_printf(dev, "1000baseKX mapped to 1000baseCX\n"); | device_printf(dev, "1000baseKX mapped to 1000baseCX\n"); | ||||
ifmedia_add(adapter->media, IFM_ETHER | IFM_1000_CX, 0, NULL); | ifmedia_add(sc->media, IFM_ETHER | IFM_1000_CX, 0, NULL); | ||||
} | } | ||||
if (layer & IXGBE_PHYSICAL_LAYER_2500BASE_KX) { | if (layer & IXGBE_PHYSICAL_LAYER_2500BASE_KX) { | ||||
device_printf(dev, "Media supported: 2500baseKX\n"); | device_printf(dev, "Media supported: 2500baseKX\n"); | ||||
device_printf(dev, "2500baseKX mapped to 2500baseSX\n"); | device_printf(dev, "2500baseKX mapped to 2500baseSX\n"); | ||||
ifmedia_add(adapter->media, IFM_ETHER | IFM_2500_SX, 0, NULL); | ifmedia_add(sc->media, IFM_ETHER | IFM_2500_SX, 0, NULL); | ||||
} | } | ||||
#endif | #endif | ||||
if (layer & IXGBE_PHYSICAL_LAYER_1000BASE_BX) | if (layer & IXGBE_PHYSICAL_LAYER_1000BASE_BX) | ||||
device_printf(dev, "Media supported: 1000baseBX\n"); | device_printf(dev, "Media supported: 1000baseBX\n"); | ||||
if (hw->device_id == IXGBE_DEV_ID_82598AT) { | if (hw->device_id == IXGBE_DEV_ID_82598AT) { | ||||
ifmedia_add(adapter->media, IFM_ETHER | IFM_1000_T | IFM_FDX, | ifmedia_add(sc->media, IFM_ETHER | IFM_1000_T | IFM_FDX, | ||||
0, NULL); | 0, NULL); | ||||
ifmedia_add(adapter->media, IFM_ETHER | IFM_1000_T, 0, NULL); | ifmedia_add(sc->media, IFM_ETHER | IFM_1000_T, 0, NULL); | ||||
} | } | ||||
ifmedia_add(adapter->media, IFM_ETHER | IFM_AUTO, 0, NULL); | ifmedia_add(sc->media, IFM_ETHER | IFM_AUTO, 0, NULL); | ||||
} /* ixgbe_add_media_types */ | } /* ixgbe_add_media_types */ | ||||
/************************************************************************ | /************************************************************************ | ||||
* ixgbe_is_sfp | * ixgbe_is_sfp | ||||
************************************************************************/ | ************************************************************************/ | ||||
static inline bool | static inline bool | ||||
ixgbe_is_sfp(struct ixgbe_hw *hw) | ixgbe_is_sfp(struct ixgbe_hw *hw) | ||||
{ | { | ||||
Show All 21 Lines | |||||
} /* ixgbe_is_sfp */ | } /* ixgbe_is_sfp */ | ||||
/************************************************************************ | /************************************************************************ | ||||
* ixgbe_config_link | * ixgbe_config_link | ||||
************************************************************************/ | ************************************************************************/ | ||||
static void | static void | ||||
ixgbe_config_link(if_ctx_t ctx) | ixgbe_config_link(if_ctx_t ctx) | ||||
{ | { | ||||
struct adapter *adapter = iflib_get_softc(ctx); | struct ixgbe_softc *sc = iflib_get_softc(ctx); | ||||
struct ixgbe_hw *hw = &adapter->hw; | struct ixgbe_hw *hw = &sc->hw; | ||||
u32 autoneg, err = 0; | u32 autoneg, err = 0; | ||||
bool sfp, negotiate; | bool sfp, negotiate; | ||||
sfp = ixgbe_is_sfp(hw); | sfp = ixgbe_is_sfp(hw); | ||||
if (sfp) { | if (sfp) { | ||||
adapter->task_requests |= IXGBE_REQUEST_TASK_MOD; | sc->task_requests |= IXGBE_REQUEST_TASK_MOD; | ||||
iflib_admin_intr_deferred(ctx); | iflib_admin_intr_deferred(ctx); | ||||
} else { | } else { | ||||
if (hw->mac.ops.check_link) | if (hw->mac.ops.check_link) | ||||
err = ixgbe_check_link(hw, &adapter->link_speed, | err = ixgbe_check_link(hw, &sc->link_speed, | ||||
&adapter->link_up, false); | &sc->link_up, false); | ||||
if (err) | if (err) | ||||
return; | return; | ||||
autoneg = hw->phy.autoneg_advertised; | autoneg = hw->phy.autoneg_advertised; | ||||
if ((!autoneg) && (hw->mac.ops.get_link_capabilities)) | if ((!autoneg) && (hw->mac.ops.get_link_capabilities)) | ||||
err = hw->mac.ops.get_link_capabilities(hw, &autoneg, | err = hw->mac.ops.get_link_capabilities(hw, &autoneg, | ||||
&negotiate); | &negotiate); | ||||
if (err) | if (err) | ||||
return; | return; | ||||
if (hw->mac.ops.setup_link) | if (hw->mac.ops.setup_link) | ||||
err = hw->mac.ops.setup_link(hw, autoneg, | err = hw->mac.ops.setup_link(hw, autoneg, | ||||
adapter->link_up); | sc->link_up); | ||||
} | } | ||||
} /* ixgbe_config_link */ | } /* ixgbe_config_link */ | ||||
/************************************************************************ | /************************************************************************ | ||||
* ixgbe_update_stats_counters - Update board statistics counters. | * ixgbe_update_stats_counters - Update board statistics counters. | ||||
************************************************************************/ | ************************************************************************/ | ||||
static void | static void | ||||
ixgbe_update_stats_counters(struct adapter *adapter) | ixgbe_update_stats_counters(struct ixgbe_softc *sc) | ||||
{ | { | ||||
struct ixgbe_hw *hw = &adapter->hw; | struct ixgbe_hw *hw = &sc->hw; | ||||
struct ixgbe_hw_stats *stats = &adapter->stats.pf; | struct ixgbe_hw_stats *stats = &sc->stats.pf; | ||||
u32 missed_rx = 0, bprc, lxon, lxoff, total; | u32 missed_rx = 0, bprc, lxon, lxoff, total; | ||||
u32 lxoffrxc; | u32 lxoffrxc; | ||||
u64 total_missed_rx = 0; | u64 total_missed_rx = 0; | ||||
stats->crcerrs += IXGBE_READ_REG(hw, IXGBE_CRCERRS); | stats->crcerrs += IXGBE_READ_REG(hw, IXGBE_CRCERRS); | ||||
stats->illerrc += IXGBE_READ_REG(hw, IXGBE_ILLERRC); | stats->illerrc += IXGBE_READ_REG(hw, IXGBE_ILLERRC); | ||||
stats->errbc += IXGBE_READ_REG(hw, IXGBE_ERRBC); | stats->errbc += IXGBE_READ_REG(hw, IXGBE_ERRBC); | ||||
stats->mspdc += IXGBE_READ_REG(hw, IXGBE_MSPDC); | stats->mspdc += IXGBE_READ_REG(hw, IXGBE_MSPDC); | ||||
Show All 32 Lines | if (hw->mac.type != ixgbe_mac_82598EB) { | ||||
stats->tor += IXGBE_READ_REG(hw, IXGBE_TORH); | stats->tor += IXGBE_READ_REG(hw, IXGBE_TORH); | ||||
} | } | ||||
/* | /* | ||||
* For watchdog management we need to know if we have been paused | * For watchdog management we need to know if we have been paused | ||||
* during the last interval, so capture that here. | * during the last interval, so capture that here. | ||||
*/ | */ | ||||
if (lxoffrxc) | if (lxoffrxc) | ||||
adapter->shared->isc_pause_frames = 1; | sc->shared->isc_pause_frames = 1; | ||||
/* | /* | ||||
* Workaround: mprc hardware is incorrectly counting | * Workaround: mprc hardware is incorrectly counting | ||||
* broadcasts, so for now we subtract those. | * broadcasts, so for now we subtract those. | ||||
*/ | */ | ||||
bprc = IXGBE_READ_REG(hw, IXGBE_BPRC); | bprc = IXGBE_READ_REG(hw, IXGBE_BPRC); | ||||
stats->bprc += bprc; | stats->bprc += bprc; | ||||
stats->mprc += IXGBE_READ_REG(hw, IXGBE_MPRC); | stats->mprc += IXGBE_READ_REG(hw, IXGBE_MPRC); | ||||
▲ Show 20 Lines • Show All 44 Lines • ▼ Show 20 Lines | if (hw->mac.type != ixgbe_mac_82598EB) { | ||||
stats->fcoerpdc += IXGBE_READ_REG(hw, IXGBE_FCOERPDC); | stats->fcoerpdc += IXGBE_READ_REG(hw, IXGBE_FCOERPDC); | ||||
stats->fcoeprc += IXGBE_READ_REG(hw, IXGBE_FCOEPRC); | stats->fcoeprc += IXGBE_READ_REG(hw, IXGBE_FCOEPRC); | ||||
stats->fcoeptc += IXGBE_READ_REG(hw, IXGBE_FCOEPTC); | stats->fcoeptc += IXGBE_READ_REG(hw, IXGBE_FCOEPTC); | ||||
stats->fcoedwrc += IXGBE_READ_REG(hw, IXGBE_FCOEDWRC); | stats->fcoedwrc += IXGBE_READ_REG(hw, IXGBE_FCOEDWRC); | ||||
stats->fcoedwtc += IXGBE_READ_REG(hw, IXGBE_FCOEDWTC); | stats->fcoedwtc += IXGBE_READ_REG(hw, IXGBE_FCOEDWTC); | ||||
} | } | ||||
/* Fill out the OS statistics structure */ | /* Fill out the OS statistics structure */ | ||||
IXGBE_SET_IPACKETS(adapter, stats->gprc); | IXGBE_SET_IPACKETS(sc, stats->gprc); | ||||
IXGBE_SET_OPACKETS(adapter, stats->gptc); | IXGBE_SET_OPACKETS(sc, stats->gptc); | ||||
IXGBE_SET_IBYTES(adapter, stats->gorc); | IXGBE_SET_IBYTES(sc, stats->gorc); | ||||
IXGBE_SET_OBYTES(adapter, stats->gotc); | IXGBE_SET_OBYTES(sc, stats->gotc); | ||||
IXGBE_SET_IMCASTS(adapter, stats->mprc); | IXGBE_SET_IMCASTS(sc, stats->mprc); | ||||
IXGBE_SET_OMCASTS(adapter, stats->mptc); | IXGBE_SET_OMCASTS(sc, stats->mptc); | ||||
IXGBE_SET_COLLISIONS(adapter, 0); | IXGBE_SET_COLLISIONS(sc, 0); | ||||
IXGBE_SET_IQDROPS(adapter, total_missed_rx); | IXGBE_SET_IQDROPS(sc, total_missed_rx); | ||||
/* | /* | ||||
* Aggregate following types of errors as RX errors: | * Aggregate following types of errors as RX errors: | ||||
* - CRC error count, | * - CRC error count, | ||||
* - illegal byte error count, | * - illegal byte error count, | ||||
* - checksum error count, | * - checksum error count, | ||||
* - missed packets count, | * - missed packets count, | ||||
* - length error count, | * - length error count, | ||||
* - undersized packets count, | * - undersized packets count, | ||||
* - fragmented packets count, | * - fragmented packets count, | ||||
* - oversized packets count, | * - oversized packets count, | ||||
* - jabber count. | * - jabber count. | ||||
*/ | */ | ||||
IXGBE_SET_IERRORS(adapter, stats->crcerrs + stats->illerrc + stats->xec + | IXGBE_SET_IERRORS(sc, stats->crcerrs + stats->illerrc + stats->xec + | ||||
stats->mpc[0] + stats->rlec + stats->ruc + stats->rfc + stats->roc + | stats->mpc[0] + stats->rlec + stats->ruc + stats->rfc + stats->roc + | ||||
stats->rjc); | stats->rjc); | ||||
} /* ixgbe_update_stats_counters */ | } /* ixgbe_update_stats_counters */ | ||||
/************************************************************************ | /************************************************************************ | ||||
* ixgbe_add_hw_stats | * ixgbe_add_hw_stats | ||||
* | * | ||||
* Add sysctl variables, one per statistic, to the system. | * Add sysctl variables, one per statistic, to the system. | ||||
************************************************************************/ | ************************************************************************/ | ||||
static void | static void | ||||
ixgbe_add_hw_stats(struct adapter *adapter) | ixgbe_add_hw_stats(struct ixgbe_softc *sc) | ||||
{ | { | ||||
device_t dev = iflib_get_dev(adapter->ctx); | device_t dev = iflib_get_dev(sc->ctx); | ||||
struct ix_rx_queue *rx_que; | struct ix_rx_queue *rx_que; | ||||
struct ix_tx_queue *tx_que; | struct ix_tx_queue *tx_que; | ||||
struct sysctl_ctx_list *ctx = device_get_sysctl_ctx(dev); | struct sysctl_ctx_list *ctx = device_get_sysctl_ctx(dev); | ||||
struct sysctl_oid *tree = device_get_sysctl_tree(dev); | struct sysctl_oid *tree = device_get_sysctl_tree(dev); | ||||
struct sysctl_oid_list *child = SYSCTL_CHILDREN(tree); | struct sysctl_oid_list *child = SYSCTL_CHILDREN(tree); | ||||
struct ixgbe_hw_stats *stats = &adapter->stats.pf; | struct ixgbe_hw_stats *stats = &sc->stats.pf; | ||||
struct sysctl_oid *stat_node, *queue_node; | struct sysctl_oid *stat_node, *queue_node; | ||||
struct sysctl_oid_list *stat_list, *queue_list; | struct sysctl_oid_list *stat_list, *queue_list; | ||||
int i; | int i; | ||||
#define QUEUE_NAME_LEN 32 | #define QUEUE_NAME_LEN 32 | ||||
char namebuf[QUEUE_NAME_LEN]; | char namebuf[QUEUE_NAME_LEN]; | ||||
/* Driver Statistics */ | /* Driver Statistics */ | ||||
SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "dropped", | 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, "watchdog_events", | SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "watchdog_events", | ||||
CTLFLAG_RD, &adapter->watchdog_events, "Watchdog timeouts"); | CTLFLAG_RD, &sc->watchdog_events, "Watchdog timeouts"); | ||||
SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "link_irq", | 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"); | ||||
for (i = 0, tx_que = adapter->tx_queues; i < adapter->num_tx_queues; i++, tx_que++) { | for (i = 0, tx_que = sc->tx_queues; i < sc->num_tx_queues; i++, tx_que++) { | ||||
struct tx_ring *txr = &tx_que->txr; | struct tx_ring *txr = &tx_que->txr; | ||||
snprintf(namebuf, QUEUE_NAME_LEN, "queue%d", i); | snprintf(namebuf, QUEUE_NAME_LEN, "queue%d", i); | ||||
queue_node = SYSCTL_ADD_NODE(ctx, child, OID_AUTO, namebuf, | queue_node = SYSCTL_ADD_NODE(ctx, child, OID_AUTO, namebuf, | ||||
CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, "Queue Name"); | CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, "Queue Name"); | ||||
queue_list = SYSCTL_CHILDREN(queue_node); | queue_list = SYSCTL_CHILDREN(queue_node); | ||||
SYSCTL_ADD_PROC(ctx, queue_list, OID_AUTO, "txd_head", | SYSCTL_ADD_PROC(ctx, queue_list, OID_AUTO, "txd_head", | ||||
CTLTYPE_UINT | CTLFLAG_RD | CTLFLAG_NEEDGIANT, txr, 0, | CTLTYPE_UINT | CTLFLAG_RD | CTLFLAG_NEEDGIANT, txr, 0, | ||||
ixgbe_sysctl_tdh_handler, "IU", "Transmit Descriptor Head"); | ixgbe_sysctl_tdh_handler, "IU", "Transmit Descriptor Head"); | ||||
SYSCTL_ADD_PROC(ctx, queue_list, OID_AUTO, "txd_tail", | SYSCTL_ADD_PROC(ctx, queue_list, OID_AUTO, "txd_tail", | ||||
CTLTYPE_UINT | CTLFLAG_RD | CTLFLAG_NEEDGIANT, txr, 0, | CTLTYPE_UINT | CTLFLAG_RD | CTLFLAG_NEEDGIANT, txr, 0, | ||||
ixgbe_sysctl_tdt_handler, "IU", "Transmit Descriptor Tail"); | ixgbe_sysctl_tdt_handler, "IU", "Transmit Descriptor Tail"); | ||||
SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "tso_tx", | SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "tso_tx", | ||||
CTLFLAG_RD, &txr->tso_tx, "TSO"); | CTLFLAG_RD, &txr->tso_tx, "TSO"); | ||||
SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "tx_packets", | SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "tx_packets", | ||||
CTLFLAG_RD, &txr->total_packets, | CTLFLAG_RD, &txr->total_packets, | ||||
"Queue Packets Transmitted"); | "Queue Packets Transmitted"); | ||||
} | } | ||||
for (i = 0, rx_que = adapter->rx_queues; i < adapter->num_rx_queues; i++, rx_que++) { | for (i = 0, rx_que = sc->rx_queues; i < sc->num_rx_queues; i++, rx_que++) { | ||||
struct rx_ring *rxr = &rx_que->rxr; | struct rx_ring *rxr = &rx_que->rxr; | ||||
snprintf(namebuf, QUEUE_NAME_LEN, "queue%d", i); | snprintf(namebuf, QUEUE_NAME_LEN, "queue%d", i); | ||||
queue_node = SYSCTL_ADD_NODE(ctx, child, OID_AUTO, namebuf, | queue_node = SYSCTL_ADD_NODE(ctx, child, OID_AUTO, namebuf, | ||||
CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, "Queue Name"); | CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, "Queue Name"); | ||||
queue_list = SYSCTL_CHILDREN(queue_node); | queue_list = SYSCTL_CHILDREN(queue_node); | ||||
SYSCTL_ADD_PROC(ctx, queue_list, OID_AUTO, "interrupt_rate", | SYSCTL_ADD_PROC(ctx, queue_list, OID_AUTO, "interrupt_rate", | ||||
CTLTYPE_UINT | CTLFLAG_RW | CTLFLAG_NEEDGIANT, | CTLTYPE_UINT | CTLFLAG_RW | CTLFLAG_NEEDGIANT, | ||||
&adapter->rx_queues[i], 0, | &sc->rx_queues[i], 0, | ||||
ixgbe_sysctl_interrupt_rate_handler, "IU", | ixgbe_sysctl_interrupt_rate_handler, "IU", | ||||
"Interrupt Rate"); | "Interrupt Rate"); | ||||
SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "irqs", | SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "irqs", | ||||
CTLFLAG_RD, &(adapter->rx_queues[i].irqs), | CTLFLAG_RD, &(sc->rx_queues[i].irqs), | ||||
"irqs on this queue"); | "irqs on this queue"); | ||||
SYSCTL_ADD_PROC(ctx, queue_list, OID_AUTO, "rxd_head", | SYSCTL_ADD_PROC(ctx, queue_list, OID_AUTO, "rxd_head", | ||||
CTLTYPE_UINT | CTLFLAG_RD | CTLFLAG_NEEDGIANT, rxr, 0, | CTLTYPE_UINT | CTLFLAG_RD | CTLFLAG_NEEDGIANT, rxr, 0, | ||||
ixgbe_sysctl_rdh_handler, "IU", "Receive Descriptor Head"); | ixgbe_sysctl_rdh_handler, "IU", "Receive Descriptor Head"); | ||||
SYSCTL_ADD_PROC(ctx, queue_list, OID_AUTO, "rxd_tail", | SYSCTL_ADD_PROC(ctx, queue_list, OID_AUTO, "rxd_tail", | ||||
CTLTYPE_UINT | CTLFLAG_RD | CTLFLAG_NEEDGIANT, rxr, 0, | CTLTYPE_UINT | CTLFLAG_RD | CTLFLAG_NEEDGIANT, rxr, 0, | ||||
ixgbe_sysctl_rdt_handler, "IU", "Receive Descriptor Tail"); | ixgbe_sysctl_rdt_handler, "IU", "Receive Descriptor Tail"); | ||||
SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "rx_packets", | SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "rx_packets", | ||||
CTLFLAG_RD, &rxr->rx_packets, "Queue Packets Received"); | CTLFLAG_RD, &rxr->rx_packets, "Queue Packets Received"); | ||||
SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "rx_bytes", | SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "rx_bytes", | ||||
CTLFLAG_RD, &rxr->rx_bytes, "Queue Bytes Received"); | CTLFLAG_RD, &rxr->rx_bytes, "Queue Bytes Received"); | ||||
SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "rx_copies", | SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "rx_copies", | ||||
CTLFLAG_RD, &rxr->rx_copies, "Copied RX Frames"); | CTLFLAG_RD, &rxr->rx_copies, "Copied RX Frames"); | ||||
SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "rx_discarded", | SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "rx_discarded", | ||||
CTLFLAG_RD, &rxr->rx_discarded, "Discarded RX packets"); | CTLFLAG_RD, &rxr->rx_discarded, "Discarded RX packets"); | ||||
} | } | ||||
/* MAC stats get their own sub node */ | /* MAC stats get their own sub node */ | ||||
stat_node = SYSCTL_ADD_NODE(ctx, child, OID_AUTO, "mac_stats", | stat_node = SYSCTL_ADD_NODE(ctx, child, OID_AUTO, "mac_stats", | ||||
CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, "MAC Statistics"); | CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, "MAC Statistics"); | ||||
stat_list = SYSCTL_CHILDREN(stat_node); | stat_list = SYSCTL_CHILDREN(stat_node); | ||||
SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_errs", | SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_errs", | ||||
CTLFLAG_RD, &adapter->ierrors, IXGBE_SYSCTL_DESC_RX_ERRS); | CTLFLAG_RD, &sc->ierrors, IXGBE_SYSCTL_DESC_RX_ERRS); | ||||
SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "crc_errs", | SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "crc_errs", | ||||
CTLFLAG_RD, &stats->crcerrs, "CRC Errors"); | CTLFLAG_RD, &stats->crcerrs, "CRC Errors"); | ||||
SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "ill_errs", | SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "ill_errs", | ||||
CTLFLAG_RD, &stats->illerrc, "Illegal Byte Errors"); | CTLFLAG_RD, &stats->illerrc, "Illegal Byte Errors"); | ||||
SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "byte_errs", | SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "byte_errs", | ||||
CTLFLAG_RD, &stats->errbc, "Byte Errors"); | CTLFLAG_RD, &stats->errbc, "Byte Errors"); | ||||
SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "short_discards", | SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "short_discards", | ||||
CTLFLAG_RD, &stats->mspdc, "MAC Short Packets Discarded"); | CTLFLAG_RD, &stats->mspdc, "MAC Short Packets Discarded"); | ||||
▲ Show 20 Lines • Show All 93 Lines • ▼ Show 20 Lines | |||||
{ | { | ||||
struct tx_ring *txr = ((struct tx_ring *)oidp->oid_arg1); | struct tx_ring *txr = ((struct tx_ring *)oidp->oid_arg1); | ||||
int error; | int error; | ||||
unsigned int val; | unsigned int val; | ||||
if (!txr) | if (!txr) | ||||
return (0); | return (0); | ||||
val = IXGBE_READ_REG(&txr->adapter->hw, IXGBE_TDH(txr->me)); | val = IXGBE_READ_REG(&txr->sc->hw, IXGBE_TDH(txr->me)); | ||||
error = sysctl_handle_int(oidp, &val, 0, req); | error = sysctl_handle_int(oidp, &val, 0, req); | ||||
if (error || !req->newptr) | if (error || !req->newptr) | ||||
return error; | return error; | ||||
return (0); | return (0); | ||||
} /* ixgbe_sysctl_tdh_handler */ | } /* ixgbe_sysctl_tdh_handler */ | ||||
/************************************************************************ | /************************************************************************ | ||||
* ixgbe_sysctl_tdt_handler - Transmit Descriptor Tail handler function | * ixgbe_sysctl_tdt_handler - Transmit Descriptor Tail handler function | ||||
* | * | ||||
* Retrieves the TDT value from the hardware | * Retrieves the TDT value from the hardware | ||||
************************************************************************/ | ************************************************************************/ | ||||
static int | static int | ||||
ixgbe_sysctl_tdt_handler(SYSCTL_HANDLER_ARGS) | ixgbe_sysctl_tdt_handler(SYSCTL_HANDLER_ARGS) | ||||
{ | { | ||||
struct tx_ring *txr = ((struct tx_ring *)oidp->oid_arg1); | struct tx_ring *txr = ((struct tx_ring *)oidp->oid_arg1); | ||||
int error; | int error; | ||||
unsigned int val; | unsigned int val; | ||||
if (!txr) | if (!txr) | ||||
return (0); | return (0); | ||||
val = IXGBE_READ_REG(&txr->adapter->hw, IXGBE_TDT(txr->me)); | val = IXGBE_READ_REG(&txr->sc->hw, IXGBE_TDT(txr->me)); | ||||
error = sysctl_handle_int(oidp, &val, 0, req); | error = sysctl_handle_int(oidp, &val, 0, req); | ||||
if (error || !req->newptr) | if (error || !req->newptr) | ||||
return error; | return error; | ||||
return (0); | return (0); | ||||
} /* ixgbe_sysctl_tdt_handler */ | } /* ixgbe_sysctl_tdt_handler */ | ||||
/************************************************************************ | /************************************************************************ | ||||
* ixgbe_sysctl_rdh_handler - Receive Descriptor Head handler function | * ixgbe_sysctl_rdh_handler - Receive Descriptor Head handler function | ||||
* | * | ||||
* Retrieves the RDH value from the hardware | * Retrieves the RDH value from the hardware | ||||
************************************************************************/ | ************************************************************************/ | ||||
static int | static int | ||||
ixgbe_sysctl_rdh_handler(SYSCTL_HANDLER_ARGS) | ixgbe_sysctl_rdh_handler(SYSCTL_HANDLER_ARGS) | ||||
{ | { | ||||
struct rx_ring *rxr = ((struct rx_ring *)oidp->oid_arg1); | struct rx_ring *rxr = ((struct rx_ring *)oidp->oid_arg1); | ||||
int error; | int error; | ||||
unsigned int val; | unsigned int val; | ||||
if (!rxr) | if (!rxr) | ||||
return (0); | return (0); | ||||
val = IXGBE_READ_REG(&rxr->adapter->hw, IXGBE_RDH(rxr->me)); | val = IXGBE_READ_REG(&rxr->sc->hw, IXGBE_RDH(rxr->me)); | ||||
error = sysctl_handle_int(oidp, &val, 0, req); | error = sysctl_handle_int(oidp, &val, 0, req); | ||||
if (error || !req->newptr) | if (error || !req->newptr) | ||||
return error; | return error; | ||||
return (0); | return (0); | ||||
} /* ixgbe_sysctl_rdh_handler */ | } /* ixgbe_sysctl_rdh_handler */ | ||||
/************************************************************************ | /************************************************************************ | ||||
* ixgbe_sysctl_rdt_handler - Receive Descriptor Tail handler function | * ixgbe_sysctl_rdt_handler - Receive Descriptor Tail handler function | ||||
* | * | ||||
* Retrieves the RDT value from the hardware | * Retrieves the RDT value from the hardware | ||||
************************************************************************/ | ************************************************************************/ | ||||
static int | static int | ||||
ixgbe_sysctl_rdt_handler(SYSCTL_HANDLER_ARGS) | ixgbe_sysctl_rdt_handler(SYSCTL_HANDLER_ARGS) | ||||
{ | { | ||||
struct rx_ring *rxr = ((struct rx_ring *)oidp->oid_arg1); | struct rx_ring *rxr = ((struct rx_ring *)oidp->oid_arg1); | ||||
int error; | int error; | ||||
unsigned int val; | unsigned int val; | ||||
if (!rxr) | if (!rxr) | ||||
return (0); | return (0); | ||||
val = IXGBE_READ_REG(&rxr->adapter->hw, IXGBE_RDT(rxr->me)); | val = IXGBE_READ_REG(&rxr->sc->hw, IXGBE_RDT(rxr->me)); | ||||
error = sysctl_handle_int(oidp, &val, 0, req); | error = sysctl_handle_int(oidp, &val, 0, req); | ||||
if (error || !req->newptr) | if (error || !req->newptr) | ||||
return error; | return error; | ||||
return (0); | return (0); | ||||
} /* ixgbe_sysctl_rdt_handler */ | } /* ixgbe_sysctl_rdt_handler */ | ||||
/************************************************************************ | /************************************************************************ | ||||
* ixgbe_if_vlan_register | * ixgbe_if_vlan_register | ||||
* | * | ||||
* Run via vlan config EVENT, it enables us to use the | * Run via vlan config EVENT, it enables us to use the | ||||
* HW Filter table since we can get the vlan id. This | * HW Filter table since we can get the vlan id. This | ||||
* just creates the entry in the soft version of the | * just creates the entry in the soft version of the | ||||
* VFTA, init will repopulate the real table. | * VFTA, init will repopulate the real table. | ||||
************************************************************************/ | ************************************************************************/ | ||||
static void | static void | ||||
ixgbe_if_vlan_register(if_ctx_t ctx, u16 vtag) | ixgbe_if_vlan_register(if_ctx_t ctx, u16 vtag) | ||||
{ | { | ||||
struct adapter *adapter = iflib_get_softc(ctx); | struct ixgbe_softc *sc = iflib_get_softc(ctx); | ||||
u16 index, bit; | u16 index, bit; | ||||
index = (vtag >> 5) & 0x7F; | index = (vtag >> 5) & 0x7F; | ||||
bit = vtag & 0x1F; | bit = vtag & 0x1F; | ||||
adapter->shadow_vfta[index] |= (1 << bit); | sc->shadow_vfta[index] |= (1 << bit); | ||||
++adapter->num_vlans; | ++sc->num_vlans; | ||||
ixgbe_setup_vlan_hw_support(ctx); | ixgbe_setup_vlan_hw_support(ctx); | ||||
} /* ixgbe_if_vlan_register */ | } /* ixgbe_if_vlan_register */ | ||||
/************************************************************************ | /************************************************************************ | ||||
* ixgbe_if_vlan_unregister | * ixgbe_if_vlan_unregister | ||||
* | * | ||||
* Run via vlan unconfig EVENT, remove our entry in the soft vfta. | * Run via vlan unconfig EVENT, remove our entry in the soft vfta. | ||||
************************************************************************/ | ************************************************************************/ | ||||
static void | static void | ||||
ixgbe_if_vlan_unregister(if_ctx_t ctx, u16 vtag) | ixgbe_if_vlan_unregister(if_ctx_t ctx, u16 vtag) | ||||
{ | { | ||||
struct adapter *adapter = iflib_get_softc(ctx); | struct ixgbe_softc *sc = iflib_get_softc(ctx); | ||||
u16 index, bit; | u16 index, bit; | ||||
index = (vtag >> 5) & 0x7F; | index = (vtag >> 5) & 0x7F; | ||||
bit = vtag & 0x1F; | bit = vtag & 0x1F; | ||||
adapter->shadow_vfta[index] &= ~(1 << bit); | sc->shadow_vfta[index] &= ~(1 << bit); | ||||
--adapter->num_vlans; | --sc->num_vlans; | ||||
/* Re-init to load the changes */ | /* Re-init to load the changes */ | ||||
ixgbe_setup_vlan_hw_support(ctx); | ixgbe_setup_vlan_hw_support(ctx); | ||||
} /* ixgbe_if_vlan_unregister */ | } /* ixgbe_if_vlan_unregister */ | ||||
/************************************************************************ | /************************************************************************ | ||||
* ixgbe_setup_vlan_hw_support | * ixgbe_setup_vlan_hw_support | ||||
************************************************************************/ | ************************************************************************/ | ||||
static void | static void | ||||
ixgbe_setup_vlan_hw_support(if_ctx_t ctx) | ixgbe_setup_vlan_hw_support(if_ctx_t ctx) | ||||
{ | { | ||||
struct ifnet *ifp = iflib_get_ifp(ctx); | struct ifnet *ifp = iflib_get_ifp(ctx); | ||||
struct adapter *adapter = iflib_get_softc(ctx); | struct ixgbe_softc *sc = iflib_get_softc(ctx); | ||||
struct ixgbe_hw *hw = &adapter->hw; | struct ixgbe_hw *hw = &sc->hw; | ||||
struct rx_ring *rxr; | struct rx_ring *rxr; | ||||
int i; | int i; | ||||
u32 ctrl; | u32 ctrl; | ||||
/* | /* | ||||
* We get here thru init_locked, meaning | * We get here thru init_locked, meaning | ||||
* a soft reset, this has already cleared | * a soft reset, this has already cleared | ||||
* the VFTA and other state, so if there | * the VFTA and other state, so if there | ||||
* have been no vlan's registered do nothing. | * have been no vlan's registered do nothing. | ||||
*/ | */ | ||||
if (adapter->num_vlans == 0) | if (sc->num_vlans == 0) | ||||
return; | return; | ||||
/* Setup the queues for vlans */ | /* Setup the queues for vlans */ | ||||
if (ifp->if_capenable & IFCAP_VLAN_HWTAGGING) { | if (ifp->if_capenable & IFCAP_VLAN_HWTAGGING) { | ||||
for (i = 0; i < adapter->num_rx_queues; i++) { | for (i = 0; i < sc->num_rx_queues; i++) { | ||||
rxr = &adapter->rx_queues[i].rxr; | rxr = &sc->rx_queues[i].rxr; | ||||
/* On 82599 the VLAN enable is per/queue in RXDCTL */ | /* On 82599 the VLAN enable is per/queue in RXDCTL */ | ||||
if (hw->mac.type != ixgbe_mac_82598EB) { | if (hw->mac.type != ixgbe_mac_82598EB) { | ||||
ctrl = IXGBE_READ_REG(hw, IXGBE_RXDCTL(rxr->me)); | ctrl = IXGBE_READ_REG(hw, IXGBE_RXDCTL(rxr->me)); | ||||
ctrl |= IXGBE_RXDCTL_VME; | ctrl |= IXGBE_RXDCTL_VME; | ||||
IXGBE_WRITE_REG(hw, IXGBE_RXDCTL(rxr->me), ctrl); | IXGBE_WRITE_REG(hw, IXGBE_RXDCTL(rxr->me), ctrl); | ||||
} | } | ||||
rxr->vtag_strip = true; | rxr->vtag_strip = true; | ||||
} | } | ||||
} | } | ||||
if ((ifp->if_capenable & IFCAP_VLAN_HWFILTER) == 0) | if ((ifp->if_capenable & IFCAP_VLAN_HWFILTER) == 0) | ||||
return; | return; | ||||
/* | /* | ||||
* A soft reset zero's out the VFTA, so | * A soft reset zero's out the VFTA, so | ||||
* we need to repopulate it now. | * we need to repopulate it now. | ||||
*/ | */ | ||||
for (i = 0; i < IXGBE_VFTA_SIZE; i++) | for (i = 0; i < IXGBE_VFTA_SIZE; i++) | ||||
if (adapter->shadow_vfta[i] != 0) | if (sc->shadow_vfta[i] != 0) | ||||
IXGBE_WRITE_REG(hw, IXGBE_VFTA(i), | IXGBE_WRITE_REG(hw, IXGBE_VFTA(i), | ||||
adapter->shadow_vfta[i]); | sc->shadow_vfta[i]); | ||||
ctrl = IXGBE_READ_REG(hw, IXGBE_VLNCTRL); | ctrl = IXGBE_READ_REG(hw, IXGBE_VLNCTRL); | ||||
/* Enable the Filter Table if enabled */ | /* Enable the Filter Table if enabled */ | ||||
if (ifp->if_capenable & IFCAP_VLAN_HWFILTER) { | if (ifp->if_capenable & IFCAP_VLAN_HWFILTER) { | ||||
ctrl &= ~IXGBE_VLNCTRL_CFIEN; | ctrl &= ~IXGBE_VLNCTRL_CFIEN; | ||||
ctrl |= IXGBE_VLNCTRL_VFE; | ctrl |= IXGBE_VLNCTRL_VFE; | ||||
} | } | ||||
if (hw->mac.type == ixgbe_mac_82598EB) | if (hw->mac.type == ixgbe_mac_82598EB) | ||||
ctrl |= IXGBE_VLNCTRL_VME; | ctrl |= IXGBE_VLNCTRL_VME; | ||||
IXGBE_WRITE_REG(hw, IXGBE_VLNCTRL, ctrl); | IXGBE_WRITE_REG(hw, IXGBE_VLNCTRL, ctrl); | ||||
} /* ixgbe_setup_vlan_hw_support */ | } /* ixgbe_setup_vlan_hw_support */ | ||||
/************************************************************************ | /************************************************************************ | ||||
* ixgbe_get_slot_info | * ixgbe_get_slot_info | ||||
* | * | ||||
* Get the width and transaction speed of | * Get the width and transaction speed of | ||||
* the slot this adapter is plugged into. | * the slot this adapter is plugged into. | ||||
************************************************************************/ | ************************************************************************/ | ||||
static void | static void | ||||
ixgbe_get_slot_info(struct adapter *adapter) | ixgbe_get_slot_info(struct ixgbe_softc *sc) | ||||
{ | { | ||||
device_t dev = iflib_get_dev(adapter->ctx); | device_t dev = iflib_get_dev(sc->ctx); | ||||
struct ixgbe_hw *hw = &adapter->hw; | struct ixgbe_hw *hw = &sc->hw; | ||||
int bus_info_valid = true; | int bus_info_valid = true; | ||||
u32 offset; | u32 offset; | ||||
u16 link; | u16 link; | ||||
/* Some devices are behind an internal bridge */ | /* Some devices are behind an internal bridge */ | ||||
switch (hw->device_id) { | switch (hw->device_id) { | ||||
case IXGBE_DEV_ID_82599_SFP_SF_QP: | case IXGBE_DEV_ID_82599_SFP_SF_QP: | ||||
case IXGBE_DEV_ID_82599_QSFP_SF_QP: | case IXGBE_DEV_ID_82599_QSFP_SF_QP: | ||||
▲ Show 20 Lines • Show All 79 Lines • ▼ Show 20 Lines | |||||
/************************************************************************ | /************************************************************************ | ||||
* ixgbe_if_msix_intr_assign | * ixgbe_if_msix_intr_assign | ||||
* | * | ||||
* Setup MSI-X Interrupt resources and handlers | * Setup MSI-X Interrupt resources and handlers | ||||
************************************************************************/ | ************************************************************************/ | ||||
static int | static int | ||||
ixgbe_if_msix_intr_assign(if_ctx_t ctx, int msix) | ixgbe_if_msix_intr_assign(if_ctx_t ctx, int msix) | ||||
{ | { | ||||
struct adapter *adapter = iflib_get_softc(ctx); | struct ixgbe_softc *sc = iflib_get_softc(ctx); | ||||
struct ix_rx_queue *rx_que = adapter->rx_queues; | struct ix_rx_queue *rx_que = sc->rx_queues; | ||||
struct ix_tx_queue *tx_que; | struct ix_tx_queue *tx_que; | ||||
int error, rid, vector = 0; | int error, rid, vector = 0; | ||||
int cpu_id = 0; | int cpu_id = 0; | ||||
char buf[16]; | char buf[16]; | ||||
/* Admin Que is vector 0*/ | /* Admin Que is vector 0*/ | ||||
rid = vector + 1; | rid = vector + 1; | ||||
for (int i = 0; i < adapter->num_rx_queues; i++, vector++, rx_que++) { | for (int i = 0; i < sc->num_rx_queues; i++, vector++, rx_que++) { | ||||
rid = vector + 1; | rid = vector + 1; | ||||
snprintf(buf, sizeof(buf), "rxq%d", i); | snprintf(buf, sizeof(buf), "rxq%d", i); | ||||
error = iflib_irq_alloc_generic(ctx, &rx_que->que_irq, rid, | error = iflib_irq_alloc_generic(ctx, &rx_que->que_irq, rid, | ||||
IFLIB_INTR_RXTX, ixgbe_msix_que, rx_que, rx_que->rxr.me, buf); | IFLIB_INTR_RXTX, ixgbe_msix_que, rx_que, rx_que->rxr.me, buf); | ||||
if (error) { | if (error) { | ||||
device_printf(iflib_get_dev(ctx), | device_printf(iflib_get_dev(ctx), | ||||
"Failed to allocate que int %d err: %d", i, error); | "Failed to allocate que int %d err: %d", i, error); | ||||
adapter->num_rx_queues = i + 1; | sc->num_rx_queues = i + 1; | ||||
goto fail; | goto fail; | ||||
} | } | ||||
rx_que->msix = vector; | rx_que->msix = vector; | ||||
if (adapter->feat_en & IXGBE_FEATURE_RSS) { | if (sc->feat_en & IXGBE_FEATURE_RSS) { | ||||
/* | /* | ||||
* The queue ID is used as the RSS layer bucket ID. | * The queue ID is used as the RSS layer bucket ID. | ||||
* We look up the queue ID -> RSS CPU ID and select | * We look up the queue ID -> RSS CPU ID and select | ||||
* that. | * that. | ||||
*/ | */ | ||||
cpu_id = rss_getcpu(i % rss_getnumbuckets()); | cpu_id = rss_getcpu(i % rss_getnumbuckets()); | ||||
} else { | } else { | ||||
/* | /* | ||||
* Bind the MSI-X vector, and thus the | * Bind the MSI-X vector, and thus the | ||||
* rings to the corresponding cpu. | * rings to the corresponding cpu. | ||||
* | * | ||||
* This just happens to match the default RSS | * This just happens to match the default RSS | ||||
* round-robin bucket -> queue -> CPU allocation. | * round-robin bucket -> queue -> CPU allocation. | ||||
*/ | */ | ||||
if (adapter->num_rx_queues > 1) | if (sc->num_rx_queues > 1) | ||||
cpu_id = i; | cpu_id = i; | ||||
} | } | ||||
} | } | ||||
for (int i = 0; i < adapter->num_tx_queues; i++) { | for (int i = 0; i < sc->num_tx_queues; i++) { | ||||
snprintf(buf, sizeof(buf), "txq%d", i); | snprintf(buf, sizeof(buf), "txq%d", i); | ||||
tx_que = &adapter->tx_queues[i]; | tx_que = &sc->tx_queues[i]; | ||||
tx_que->msix = i % adapter->num_rx_queues; | tx_que->msix = i % sc->num_rx_queues; | ||||
iflib_softirq_alloc_generic(ctx, | iflib_softirq_alloc_generic(ctx, | ||||
&adapter->rx_queues[tx_que->msix].que_irq, | &sc->rx_queues[tx_que->msix].que_irq, | ||||
IFLIB_INTR_TX, tx_que, tx_que->txr.me, buf); | IFLIB_INTR_TX, tx_que, tx_que->txr.me, buf); | ||||
} | } | ||||
rid = vector + 1; | rid = vector + 1; | ||||
error = iflib_irq_alloc_generic(ctx, &adapter->irq, rid, | error = iflib_irq_alloc_generic(ctx, &sc->irq, rid, | ||||
IFLIB_INTR_ADMIN, ixgbe_msix_link, adapter, 0, "aq"); | IFLIB_INTR_ADMIN, ixgbe_msix_link, sc, 0, "aq"); | ||||
if (error) { | if (error) { | ||||
device_printf(iflib_get_dev(ctx), | device_printf(iflib_get_dev(ctx), | ||||
"Failed to register admin handler"); | "Failed to register admin handler"); | ||||
return (error); | return (error); | ||||
} | } | ||||
adapter->vector = vector; | sc->vector = vector; | ||||
return (0); | return (0); | ||||
fail: | fail: | ||||
iflib_irq_free(ctx, &adapter->irq); | iflib_irq_free(ctx, &sc->irq); | ||||
rx_que = adapter->rx_queues; | rx_que = sc->rx_queues; | ||||
for (int i = 0; i < adapter->num_rx_queues; i++, rx_que++) | for (int i = 0; i < sc->num_rx_queues; i++, rx_que++) | ||||
iflib_irq_free(ctx, &rx_que->que_irq); | iflib_irq_free(ctx, &rx_que->que_irq); | ||||
return (error); | return (error); | ||||
} /* ixgbe_if_msix_intr_assign */ | } /* ixgbe_if_msix_intr_assign */ | ||||
static inline void | static inline void | ||||
ixgbe_perform_aim(struct adapter *adapter, struct ix_rx_queue *que) | ixgbe_perform_aim(struct ixgbe_softc *sc, struct ix_rx_queue *que) | ||||
{ | { | ||||
uint32_t newitr = 0; | uint32_t newitr = 0; | ||||
struct rx_ring *rxr = &que->rxr; | struct rx_ring *rxr = &que->rxr; | ||||
/* | /* | ||||
* Do Adaptive Interrupt Moderation: | * Do Adaptive Interrupt Moderation: | ||||
* - Write out last calculated setting | * - Write out last calculated setting | ||||
* - Calculate based on average size over | * - Calculate based on average size over | ||||
* the last interval. | * the last interval. | ||||
*/ | */ | ||||
if (que->eitr_setting) { | if (que->eitr_setting) { | ||||
IXGBE_WRITE_REG(&adapter->hw, IXGBE_EITR(que->msix), | IXGBE_WRITE_REG(&sc->hw, IXGBE_EITR(que->msix), | ||||
que->eitr_setting); | que->eitr_setting); | ||||
} | } | ||||
que->eitr_setting = 0; | que->eitr_setting = 0; | ||||
/* Idle, do nothing */ | /* Idle, do nothing */ | ||||
if (rxr->bytes == 0) { | if (rxr->bytes == 0) { | ||||
return; | return; | ||||
} | } | ||||
if ((rxr->bytes) && (rxr->packets)) { | if ((rxr->bytes) && (rxr->packets)) { | ||||
newitr = (rxr->bytes / rxr->packets); | newitr = (rxr->bytes / rxr->packets); | ||||
} | } | ||||
newitr += 24; /* account for hardware frame, crc */ | newitr += 24; /* account for hardware frame, crc */ | ||||
/* set an upper boundary */ | /* set an upper boundary */ | ||||
newitr = min(newitr, 3000); | newitr = min(newitr, 3000); | ||||
/* Be nice to the mid range */ | /* Be nice to the mid range */ | ||||
if ((newitr > 300) && (newitr < 1200)) { | if ((newitr > 300) && (newitr < 1200)) { | ||||
newitr = (newitr / 3); | newitr = (newitr / 3); | ||||
} else { | } else { | ||||
newitr = (newitr / 2); | newitr = (newitr / 2); | ||||
} | } | ||||
if (adapter->hw.mac.type == ixgbe_mac_82598EB) { | if (sc->hw.mac.type == ixgbe_mac_82598EB) { | ||||
newitr |= newitr << 16; | newitr |= newitr << 16; | ||||
} else { | } else { | ||||
newitr |= IXGBE_EITR_CNT_WDIS; | newitr |= IXGBE_EITR_CNT_WDIS; | ||||
} | } | ||||
/* save for next interrupt */ | /* save for next interrupt */ | ||||
que->eitr_setting = newitr; | que->eitr_setting = newitr; | ||||
/* Reset state */ | /* Reset state */ | ||||
rxr->bytes = 0; | rxr->bytes = 0; | ||||
rxr->packets = 0; | rxr->packets = 0; | ||||
return; | return; | ||||
} | } | ||||
/********************************************************************* | /********************************************************************* | ||||
* ixgbe_msix_que - MSI-X Queue Interrupt Service routine | * ixgbe_msix_que - MSI-X Queue Interrupt Service routine | ||||
**********************************************************************/ | **********************************************************************/ | ||||
static int | static int | ||||
ixgbe_msix_que(void *arg) | ixgbe_msix_que(void *arg) | ||||
{ | { | ||||
struct ix_rx_queue *que = arg; | struct ix_rx_queue *que = arg; | ||||
struct adapter *adapter = que->adapter; | struct ixgbe_softc *sc = que->sc; | ||||
struct ifnet *ifp = iflib_get_ifp(que->adapter->ctx); | struct ifnet *ifp = iflib_get_ifp(que->sc->ctx); | ||||
/* Protect against spurious interrupts */ | /* Protect against spurious interrupts */ | ||||
if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) | if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) | ||||
return (FILTER_HANDLED); | return (FILTER_HANDLED); | ||||
ixgbe_disable_queue(adapter, que->msix); | ixgbe_disable_queue(sc, que->msix); | ||||
++que->irqs; | ++que->irqs; | ||||
/* Check for AIM */ | /* Check for AIM */ | ||||
if (adapter->enable_aim) { | if (sc->enable_aim) { | ||||
ixgbe_perform_aim(adapter, que); | ixgbe_perform_aim(sc, que); | ||||
} | } | ||||
return (FILTER_SCHEDULE_THREAD); | return (FILTER_SCHEDULE_THREAD); | ||||
} /* ixgbe_msix_que */ | } /* ixgbe_msix_que */ | ||||
/************************************************************************ | /************************************************************************ | ||||
* ixgbe_media_status - Media Ioctl callback | * ixgbe_media_status - Media Ioctl callback | ||||
* | * | ||||
* Called whenever the user queries the status of | * Called whenever the user queries the status of | ||||
* the interface using ifconfig. | * the interface using ifconfig. | ||||
************************************************************************/ | ************************************************************************/ | ||||
static void | static void | ||||
ixgbe_if_media_status(if_ctx_t ctx, struct ifmediareq * ifmr) | ixgbe_if_media_status(if_ctx_t ctx, struct ifmediareq * ifmr) | ||||
{ | { | ||||
struct adapter *adapter = iflib_get_softc(ctx); | struct ixgbe_softc *sc = iflib_get_softc(ctx); | ||||
struct ixgbe_hw *hw = &adapter->hw; | struct ixgbe_hw *hw = &sc->hw; | ||||
int layer; | int layer; | ||||
INIT_DEBUGOUT("ixgbe_if_media_status: begin"); | INIT_DEBUGOUT("ixgbe_if_media_status: begin"); | ||||
ifmr->ifm_status = IFM_AVALID; | ifmr->ifm_status = IFM_AVALID; | ||||
ifmr->ifm_active = IFM_ETHER; | ifmr->ifm_active = IFM_ETHER; | ||||
if (!adapter->link_active) | if (!sc->link_active) | ||||
return; | return; | ||||
ifmr->ifm_status |= IFM_ACTIVE; | ifmr->ifm_status |= IFM_ACTIVE; | ||||
layer = adapter->phy_layer; | layer = sc->phy_layer; | ||||
if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_T || | if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_T || | ||||
layer & IXGBE_PHYSICAL_LAYER_1000BASE_T || | layer & IXGBE_PHYSICAL_LAYER_1000BASE_T || | ||||
layer & IXGBE_PHYSICAL_LAYER_100BASE_TX || | layer & IXGBE_PHYSICAL_LAYER_100BASE_TX || | ||||
layer & IXGBE_PHYSICAL_LAYER_10BASE_T) | layer & IXGBE_PHYSICAL_LAYER_10BASE_T) | ||||
switch (adapter->link_speed) { | switch (sc->link_speed) { | ||||
case IXGBE_LINK_SPEED_10GB_FULL: | case IXGBE_LINK_SPEED_10GB_FULL: | ||||
ifmr->ifm_active |= IFM_10G_T | IFM_FDX; | ifmr->ifm_active |= IFM_10G_T | IFM_FDX; | ||||
break; | break; | ||||
case IXGBE_LINK_SPEED_1GB_FULL: | case IXGBE_LINK_SPEED_1GB_FULL: | ||||
ifmr->ifm_active |= IFM_1000_T | IFM_FDX; | ifmr->ifm_active |= IFM_1000_T | IFM_FDX; | ||||
break; | break; | ||||
case IXGBE_LINK_SPEED_100_FULL: | case IXGBE_LINK_SPEED_100_FULL: | ||||
ifmr->ifm_active |= IFM_100_TX | IFM_FDX; | ifmr->ifm_active |= IFM_100_TX | IFM_FDX; | ||||
break; | break; | ||||
case IXGBE_LINK_SPEED_10_FULL: | case IXGBE_LINK_SPEED_10_FULL: | ||||
ifmr->ifm_active |= IFM_10_T | IFM_FDX; | ifmr->ifm_active |= IFM_10_T | IFM_FDX; | ||||
break; | break; | ||||
} | } | ||||
if (layer & IXGBE_PHYSICAL_LAYER_SFP_PLUS_CU || | if (layer & IXGBE_PHYSICAL_LAYER_SFP_PLUS_CU || | ||||
layer & IXGBE_PHYSICAL_LAYER_SFP_ACTIVE_DA) | layer & IXGBE_PHYSICAL_LAYER_SFP_ACTIVE_DA) | ||||
switch (adapter->link_speed) { | switch (sc->link_speed) { | ||||
case IXGBE_LINK_SPEED_10GB_FULL: | case IXGBE_LINK_SPEED_10GB_FULL: | ||||
ifmr->ifm_active |= IFM_10G_TWINAX | IFM_FDX; | ifmr->ifm_active |= IFM_10G_TWINAX | IFM_FDX; | ||||
break; | break; | ||||
} | } | ||||
if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_LR) | if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_LR) | ||||
switch (adapter->link_speed) { | switch (sc->link_speed) { | ||||
case IXGBE_LINK_SPEED_10GB_FULL: | case IXGBE_LINK_SPEED_10GB_FULL: | ||||
ifmr->ifm_active |= IFM_10G_LR | IFM_FDX; | ifmr->ifm_active |= IFM_10G_LR | IFM_FDX; | ||||
break; | break; | ||||
case IXGBE_LINK_SPEED_1GB_FULL: | case IXGBE_LINK_SPEED_1GB_FULL: | ||||
ifmr->ifm_active |= IFM_1000_LX | IFM_FDX; | ifmr->ifm_active |= IFM_1000_LX | IFM_FDX; | ||||
break; | break; | ||||
} | } | ||||
if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_LRM) | if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_LRM) | ||||
switch (adapter->link_speed) { | switch (sc->link_speed) { | ||||
case IXGBE_LINK_SPEED_10GB_FULL: | case IXGBE_LINK_SPEED_10GB_FULL: | ||||
ifmr->ifm_active |= IFM_10G_LRM | IFM_FDX; | ifmr->ifm_active |= IFM_10G_LRM | IFM_FDX; | ||||
break; | break; | ||||
case IXGBE_LINK_SPEED_1GB_FULL: | case IXGBE_LINK_SPEED_1GB_FULL: | ||||
ifmr->ifm_active |= IFM_1000_LX | IFM_FDX; | ifmr->ifm_active |= IFM_1000_LX | IFM_FDX; | ||||
break; | break; | ||||
} | } | ||||
if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_SR || | if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_SR || | ||||
layer & IXGBE_PHYSICAL_LAYER_1000BASE_SX) | layer & IXGBE_PHYSICAL_LAYER_1000BASE_SX) | ||||
switch (adapter->link_speed) { | switch (sc->link_speed) { | ||||
case IXGBE_LINK_SPEED_10GB_FULL: | case IXGBE_LINK_SPEED_10GB_FULL: | ||||
ifmr->ifm_active |= IFM_10G_SR | IFM_FDX; | ifmr->ifm_active |= IFM_10G_SR | IFM_FDX; | ||||
break; | break; | ||||
case IXGBE_LINK_SPEED_1GB_FULL: | case IXGBE_LINK_SPEED_1GB_FULL: | ||||
ifmr->ifm_active |= IFM_1000_SX | IFM_FDX; | ifmr->ifm_active |= IFM_1000_SX | IFM_FDX; | ||||
break; | break; | ||||
} | } | ||||
if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_CX4) | if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_CX4) | ||||
switch (adapter->link_speed) { | switch (sc->link_speed) { | ||||
case IXGBE_LINK_SPEED_10GB_FULL: | case IXGBE_LINK_SPEED_10GB_FULL: | ||||
ifmr->ifm_active |= IFM_10G_CX4 | IFM_FDX; | ifmr->ifm_active |= IFM_10G_CX4 | IFM_FDX; | ||||
break; | break; | ||||
} | } | ||||
/* | /* | ||||
* XXX: These need to use the proper media types once | * XXX: These need to use the proper media types once | ||||
* they're added. | * they're added. | ||||
*/ | */ | ||||
#ifndef IFM_ETH_XTYPE | #ifndef IFM_ETH_XTYPE | ||||
if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_KR) | if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_KR) | ||||
switch (adapter->link_speed) { | switch (sc->link_speed) { | ||||
case IXGBE_LINK_SPEED_10GB_FULL: | case IXGBE_LINK_SPEED_10GB_FULL: | ||||
ifmr->ifm_active |= IFM_10G_SR | IFM_FDX; | ifmr->ifm_active |= IFM_10G_SR | IFM_FDX; | ||||
break; | break; | ||||
case IXGBE_LINK_SPEED_2_5GB_FULL: | case IXGBE_LINK_SPEED_2_5GB_FULL: | ||||
ifmr->ifm_active |= IFM_2500_SX | IFM_FDX; | ifmr->ifm_active |= IFM_2500_SX | IFM_FDX; | ||||
break; | break; | ||||
case IXGBE_LINK_SPEED_1GB_FULL: | case IXGBE_LINK_SPEED_1GB_FULL: | ||||
ifmr->ifm_active |= IFM_1000_CX | IFM_FDX; | ifmr->ifm_active |= IFM_1000_CX | IFM_FDX; | ||||
break; | break; | ||||
} | } | ||||
else if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_KX4 || | else if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_KX4 || | ||||
layer & IXGBE_PHYSICAL_LAYER_2500BASE_KX || | layer & IXGBE_PHYSICAL_LAYER_2500BASE_KX || | ||||
layer & IXGBE_PHYSICAL_LAYER_1000BASE_KX) | layer & IXGBE_PHYSICAL_LAYER_1000BASE_KX) | ||||
switch (adapter->link_speed) { | switch (sc->link_speed) { | ||||
case IXGBE_LINK_SPEED_10GB_FULL: | case IXGBE_LINK_SPEED_10GB_FULL: | ||||
ifmr->ifm_active |= IFM_10G_CX4 | IFM_FDX; | ifmr->ifm_active |= IFM_10G_CX4 | IFM_FDX; | ||||
break; | break; | ||||
case IXGBE_LINK_SPEED_2_5GB_FULL: | case IXGBE_LINK_SPEED_2_5GB_FULL: | ||||
ifmr->ifm_active |= IFM_2500_SX | IFM_FDX; | ifmr->ifm_active |= IFM_2500_SX | IFM_FDX; | ||||
break; | break; | ||||
case IXGBE_LINK_SPEED_1GB_FULL: | case IXGBE_LINK_SPEED_1GB_FULL: | ||||
ifmr->ifm_active |= IFM_1000_CX | IFM_FDX; | ifmr->ifm_active |= IFM_1000_CX | IFM_FDX; | ||||
break; | break; | ||||
} | } | ||||
#else | #else | ||||
if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_KR) | if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_KR) | ||||
switch (adapter->link_speed) { | switch (sc->link_speed) { | ||||
case IXGBE_LINK_SPEED_10GB_FULL: | case IXGBE_LINK_SPEED_10GB_FULL: | ||||
ifmr->ifm_active |= IFM_10G_KR | IFM_FDX; | ifmr->ifm_active |= IFM_10G_KR | IFM_FDX; | ||||
break; | break; | ||||
case IXGBE_LINK_SPEED_2_5GB_FULL: | case IXGBE_LINK_SPEED_2_5GB_FULL: | ||||
ifmr->ifm_active |= IFM_2500_KX | IFM_FDX; | ifmr->ifm_active |= IFM_2500_KX | IFM_FDX; | ||||
break; | break; | ||||
case IXGBE_LINK_SPEED_1GB_FULL: | case IXGBE_LINK_SPEED_1GB_FULL: | ||||
ifmr->ifm_active |= IFM_1000_KX | IFM_FDX; | ifmr->ifm_active |= IFM_1000_KX | IFM_FDX; | ||||
break; | break; | ||||
} | } | ||||
else if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_KX4 || | else if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_KX4 || | ||||
layer & IXGBE_PHYSICAL_LAYER_2500BASE_KX || | layer & IXGBE_PHYSICAL_LAYER_2500BASE_KX || | ||||
layer & IXGBE_PHYSICAL_LAYER_1000BASE_KX) | layer & IXGBE_PHYSICAL_LAYER_1000BASE_KX) | ||||
switch (adapter->link_speed) { | switch (sc->link_speed) { | ||||
case IXGBE_LINK_SPEED_10GB_FULL: | case IXGBE_LINK_SPEED_10GB_FULL: | ||||
ifmr->ifm_active |= IFM_10G_KX4 | IFM_FDX; | ifmr->ifm_active |= IFM_10G_KX4 | IFM_FDX; | ||||
break; | break; | ||||
case IXGBE_LINK_SPEED_2_5GB_FULL: | case IXGBE_LINK_SPEED_2_5GB_FULL: | ||||
ifmr->ifm_active |= IFM_2500_KX | IFM_FDX; | ifmr->ifm_active |= IFM_2500_KX | IFM_FDX; | ||||
break; | break; | ||||
case IXGBE_LINK_SPEED_1GB_FULL: | case IXGBE_LINK_SPEED_1GB_FULL: | ||||
ifmr->ifm_active |= IFM_1000_KX | IFM_FDX; | ifmr->ifm_active |= IFM_1000_KX | IFM_FDX; | ||||
Show All 18 Lines | |||||
* ixgbe_media_change - Media Ioctl callback | * ixgbe_media_change - Media Ioctl callback | ||||
* | * | ||||
* Called when the user changes speed/duplex using | * Called when the user changes speed/duplex using | ||||
* media/mediopt option with ifconfig. | * media/mediopt option with ifconfig. | ||||
************************************************************************/ | ************************************************************************/ | ||||
static int | static int | ||||
ixgbe_if_media_change(if_ctx_t ctx) | ixgbe_if_media_change(if_ctx_t ctx) | ||||
{ | { | ||||
struct adapter *adapter = iflib_get_softc(ctx); | struct ixgbe_softc *sc = iflib_get_softc(ctx); | ||||
struct ifmedia *ifm = iflib_get_media(ctx); | struct ifmedia *ifm = iflib_get_media(ctx); | ||||
struct ixgbe_hw *hw = &adapter->hw; | struct ixgbe_hw *hw = &sc->hw; | ||||
ixgbe_link_speed speed = 0; | ixgbe_link_speed speed = 0; | ||||
INIT_DEBUGOUT("ixgbe_if_media_change: begin"); | INIT_DEBUGOUT("ixgbe_if_media_change: begin"); | ||||
if (IFM_TYPE(ifm->ifm_media) != IFM_ETHER) | if (IFM_TYPE(ifm->ifm_media) != IFM_ETHER) | ||||
return (EINVAL); | return (EINVAL); | ||||
if (hw->phy.media_type == ixgbe_media_type_backplane) | if (hw->phy.media_type == ixgbe_media_type_backplane) | ||||
▲ Show 20 Lines • Show All 46 Lines • ▼ Show 20 Lines | case IFM_10_T: | ||||
speed |= IXGBE_LINK_SPEED_10_FULL; | speed |= IXGBE_LINK_SPEED_10_FULL; | ||||
break; | break; | ||||
default: | default: | ||||
goto invalid; | goto invalid; | ||||
} | } | ||||
hw->mac.autotry_restart = true; | hw->mac.autotry_restart = true; | ||||
hw->mac.ops.setup_link(hw, speed, true); | hw->mac.ops.setup_link(hw, speed, true); | ||||
adapter->advertise = | sc->advertise = | ||||
((speed & IXGBE_LINK_SPEED_10GB_FULL) ? 4 : 0) | | ((speed & IXGBE_LINK_SPEED_10GB_FULL) ? 4 : 0) | | ||||
((speed & IXGBE_LINK_SPEED_1GB_FULL) ? 2 : 0) | | ((speed & IXGBE_LINK_SPEED_1GB_FULL) ? 2 : 0) | | ||||
((speed & IXGBE_LINK_SPEED_100_FULL) ? 1 : 0) | | ((speed & IXGBE_LINK_SPEED_100_FULL) ? 1 : 0) | | ||||
((speed & IXGBE_LINK_SPEED_10_FULL) ? 8 : 0); | ((speed & IXGBE_LINK_SPEED_10_FULL) ? 8 : 0); | ||||
return (0); | return (0); | ||||
invalid: | invalid: | ||||
device_printf(iflib_get_dev(ctx), "Invalid media type!\n"); | device_printf(iflib_get_dev(ctx), "Invalid media type!\n"); | ||||
return (EINVAL); | return (EINVAL); | ||||
} /* ixgbe_if_media_change */ | } /* ixgbe_if_media_change */ | ||||
/************************************************************************ | /************************************************************************ | ||||
* ixgbe_set_promisc | * ixgbe_set_promisc | ||||
************************************************************************/ | ************************************************************************/ | ||||
static int | static int | ||||
ixgbe_if_promisc_set(if_ctx_t ctx, int flags) | ixgbe_if_promisc_set(if_ctx_t ctx, int flags) | ||||
{ | { | ||||
struct adapter *adapter = iflib_get_softc(ctx); | struct ixgbe_softc *sc = iflib_get_softc(ctx); | ||||
struct ifnet *ifp = iflib_get_ifp(ctx); | struct ifnet *ifp = iflib_get_ifp(ctx); | ||||
u32 rctl; | u32 rctl; | ||||
int mcnt = 0; | int mcnt = 0; | ||||
rctl = IXGBE_READ_REG(&adapter->hw, IXGBE_FCTRL); | rctl = IXGBE_READ_REG(&sc->hw, IXGBE_FCTRL); | ||||
rctl &= (~IXGBE_FCTRL_UPE); | rctl &= (~IXGBE_FCTRL_UPE); | ||||
if (ifp->if_flags & IFF_ALLMULTI) | if (ifp->if_flags & IFF_ALLMULTI) | ||||
mcnt = MAX_NUM_MULTICAST_ADDRESSES; | mcnt = MAX_NUM_MULTICAST_ADDRESSES; | ||||
else { | else { | ||||
mcnt = min(if_llmaddr_count(ifp), MAX_NUM_MULTICAST_ADDRESSES); | mcnt = min(if_llmaddr_count(ifp), MAX_NUM_MULTICAST_ADDRESSES); | ||||
} | } | ||||
if (mcnt < MAX_NUM_MULTICAST_ADDRESSES) | if (mcnt < MAX_NUM_MULTICAST_ADDRESSES) | ||||
rctl &= (~IXGBE_FCTRL_MPE); | rctl &= (~IXGBE_FCTRL_MPE); | ||||
IXGBE_WRITE_REG(&adapter->hw, IXGBE_FCTRL, rctl); | IXGBE_WRITE_REG(&sc->hw, IXGBE_FCTRL, rctl); | ||||
if (ifp->if_flags & IFF_PROMISC) { | if (ifp->if_flags & IFF_PROMISC) { | ||||
rctl |= (IXGBE_FCTRL_UPE | IXGBE_FCTRL_MPE); | rctl |= (IXGBE_FCTRL_UPE | IXGBE_FCTRL_MPE); | ||||
IXGBE_WRITE_REG(&adapter->hw, IXGBE_FCTRL, rctl); | IXGBE_WRITE_REG(&sc->hw, IXGBE_FCTRL, rctl); | ||||
} else if (ifp->if_flags & IFF_ALLMULTI) { | } else if (ifp->if_flags & IFF_ALLMULTI) { | ||||
rctl |= IXGBE_FCTRL_MPE; | rctl |= IXGBE_FCTRL_MPE; | ||||
rctl &= ~IXGBE_FCTRL_UPE; | rctl &= ~IXGBE_FCTRL_UPE; | ||||
IXGBE_WRITE_REG(&adapter->hw, IXGBE_FCTRL, rctl); | IXGBE_WRITE_REG(&sc->hw, IXGBE_FCTRL, rctl); | ||||
} | } | ||||
return (0); | return (0); | ||||
} /* ixgbe_if_promisc_set */ | } /* ixgbe_if_promisc_set */ | ||||
/************************************************************************ | /************************************************************************ | ||||
* ixgbe_msix_link - Link status change ISR (MSI/MSI-X) | * ixgbe_msix_link - Link status change ISR (MSI/MSI-X) | ||||
************************************************************************/ | ************************************************************************/ | ||||
static int | static int | ||||
ixgbe_msix_link(void *arg) | ixgbe_msix_link(void *arg) | ||||
{ | { | ||||
struct adapter *adapter = arg; | struct ixgbe_softc *sc = arg; | ||||
struct ixgbe_hw *hw = &adapter->hw; | struct ixgbe_hw *hw = &sc->hw; | ||||
u32 eicr, eicr_mask; | u32 eicr, eicr_mask; | ||||
s32 retval; | s32 retval; | ||||
++adapter->link_irq; | ++sc->link_irq; | ||||
/* Pause other interrupts */ | /* Pause other interrupts */ | ||||
IXGBE_WRITE_REG(hw, IXGBE_EIMC, IXGBE_EIMC_OTHER); | IXGBE_WRITE_REG(hw, IXGBE_EIMC, IXGBE_EIMC_OTHER); | ||||
/* First get the cause */ | /* First get the cause */ | ||||
eicr = IXGBE_READ_REG(hw, IXGBE_EICS); | eicr = IXGBE_READ_REG(hw, IXGBE_EICS); | ||||
/* Be sure the queue bits are not cleared */ | /* Be sure the queue bits are not cleared */ | ||||
eicr &= ~IXGBE_EICR_RTX_QUEUE; | eicr &= ~IXGBE_EICR_RTX_QUEUE; | ||||
/* Clear interrupt with write */ | /* Clear interrupt with write */ | ||||
IXGBE_WRITE_REG(hw, IXGBE_EICR, eicr); | IXGBE_WRITE_REG(hw, IXGBE_EICR, eicr); | ||||
/* Link status change */ | /* Link status change */ | ||||
if (eicr & IXGBE_EICR_LSC) { | if (eicr & IXGBE_EICR_LSC) { | ||||
IXGBE_WRITE_REG(hw, IXGBE_EIMC, IXGBE_EIMC_LSC); | IXGBE_WRITE_REG(hw, IXGBE_EIMC, IXGBE_EIMC_LSC); | ||||
adapter->task_requests |= IXGBE_REQUEST_TASK_LSC; | sc->task_requests |= IXGBE_REQUEST_TASK_LSC; | ||||
} | } | ||||
if (adapter->hw.mac.type != ixgbe_mac_82598EB) { | if (sc->hw.mac.type != ixgbe_mac_82598EB) { | ||||
if ((adapter->feat_en & IXGBE_FEATURE_FDIR) && | if ((sc->feat_en & IXGBE_FEATURE_FDIR) && | ||||
(eicr & IXGBE_EICR_FLOW_DIR)) { | (eicr & IXGBE_EICR_FLOW_DIR)) { | ||||
/* This is probably overkill :) */ | /* This is probably overkill :) */ | ||||
if (!atomic_cmpset_int(&adapter->fdir_reinit, 0, 1)) | if (!atomic_cmpset_int(&sc->fdir_reinit, 0, 1)) | ||||
return (FILTER_HANDLED); | return (FILTER_HANDLED); | ||||
/* Disable the interrupt */ | /* Disable the interrupt */ | ||||
IXGBE_WRITE_REG(hw, IXGBE_EIMC, IXGBE_EICR_FLOW_DIR); | IXGBE_WRITE_REG(hw, IXGBE_EIMC, IXGBE_EICR_FLOW_DIR); | ||||
adapter->task_requests |= IXGBE_REQUEST_TASK_FDIR; | sc->task_requests |= IXGBE_REQUEST_TASK_FDIR; | ||||
} else | } else | ||||
if (eicr & IXGBE_EICR_ECC) { | if (eicr & IXGBE_EICR_ECC) { | ||||
device_printf(iflib_get_dev(adapter->ctx), | device_printf(iflib_get_dev(sc->ctx), | ||||
"\nCRITICAL: ECC ERROR!! Please Reboot!!\n"); | "\nCRITICAL: ECC ERROR!! Please Reboot!!\n"); | ||||
IXGBE_WRITE_REG(hw, IXGBE_EICR, IXGBE_EICR_ECC); | IXGBE_WRITE_REG(hw, IXGBE_EICR, IXGBE_EICR_ECC); | ||||
} | } | ||||
/* Check for over temp condition */ | /* Check for over temp condition */ | ||||
if (adapter->feat_en & IXGBE_FEATURE_TEMP_SENSOR) { | if (sc->feat_en & IXGBE_FEATURE_TEMP_SENSOR) { | ||||
switch (adapter->hw.mac.type) { | switch (sc->hw.mac.type) { | ||||
case ixgbe_mac_X550EM_a: | case ixgbe_mac_X550EM_a: | ||||
if (!(eicr & IXGBE_EICR_GPI_SDP0_X550EM_a)) | if (!(eicr & IXGBE_EICR_GPI_SDP0_X550EM_a)) | ||||
break; | break; | ||||
IXGBE_WRITE_REG(hw, IXGBE_EIMC, | IXGBE_WRITE_REG(hw, IXGBE_EIMC, | ||||
IXGBE_EICR_GPI_SDP0_X550EM_a); | IXGBE_EICR_GPI_SDP0_X550EM_a); | ||||
IXGBE_WRITE_REG(hw, IXGBE_EICR, | IXGBE_WRITE_REG(hw, IXGBE_EICR, | ||||
IXGBE_EICR_GPI_SDP0_X550EM_a); | IXGBE_EICR_GPI_SDP0_X550EM_a); | ||||
retval = hw->phy.ops.check_overtemp(hw); | retval = hw->phy.ops.check_overtemp(hw); | ||||
if (retval != IXGBE_ERR_OVERTEMP) | if (retval != IXGBE_ERR_OVERTEMP) | ||||
break; | break; | ||||
device_printf(iflib_get_dev(adapter->ctx), | device_printf(iflib_get_dev(sc->ctx), | ||||
"\nCRITICAL: OVER TEMP!! PHY IS SHUT DOWN!!\n"); | "\nCRITICAL: OVER TEMP!! PHY IS SHUT DOWN!!\n"); | ||||
device_printf(iflib_get_dev(adapter->ctx), | device_printf(iflib_get_dev(sc->ctx), | ||||
"System shutdown required!\n"); | "System shutdown required!\n"); | ||||
break; | break; | ||||
default: | default: | ||||
if (!(eicr & IXGBE_EICR_TS)) | if (!(eicr & IXGBE_EICR_TS)) | ||||
break; | break; | ||||
retval = hw->phy.ops.check_overtemp(hw); | retval = hw->phy.ops.check_overtemp(hw); | ||||
if (retval != IXGBE_ERR_OVERTEMP) | if (retval != IXGBE_ERR_OVERTEMP) | ||||
break; | break; | ||||
device_printf(iflib_get_dev(adapter->ctx), | device_printf(iflib_get_dev(sc->ctx), | ||||
"\nCRITICAL: OVER TEMP!! PHY IS SHUT DOWN!!\n"); | "\nCRITICAL: OVER TEMP!! PHY IS SHUT DOWN!!\n"); | ||||
device_printf(iflib_get_dev(adapter->ctx), | device_printf(iflib_get_dev(sc->ctx), | ||||
"System shutdown required!\n"); | "System shutdown required!\n"); | ||||
IXGBE_WRITE_REG(hw, IXGBE_EICR, IXGBE_EICR_TS); | IXGBE_WRITE_REG(hw, IXGBE_EICR, IXGBE_EICR_TS); | ||||
break; | break; | ||||
} | } | ||||
} | } | ||||
/* Check for VF message */ | /* Check for VF message */ | ||||
if ((adapter->feat_en & IXGBE_FEATURE_SRIOV) && | if ((sc->feat_en & IXGBE_FEATURE_SRIOV) && | ||||
(eicr & IXGBE_EICR_MAILBOX)) | (eicr & IXGBE_EICR_MAILBOX)) | ||||
adapter->task_requests |= IXGBE_REQUEST_TASK_MBX; | sc->task_requests |= IXGBE_REQUEST_TASK_MBX; | ||||
} | } | ||||
if (ixgbe_is_sfp(hw)) { | if (ixgbe_is_sfp(hw)) { | ||||
/* Pluggable optics-related interrupt */ | /* Pluggable optics-related interrupt */ | ||||
if (hw->mac.type >= ixgbe_mac_X540) | if (hw->mac.type >= ixgbe_mac_X540) | ||||
eicr_mask = IXGBE_EICR_GPI_SDP0_X540; | eicr_mask = IXGBE_EICR_GPI_SDP0_X540; | ||||
else | else | ||||
eicr_mask = IXGBE_EICR_GPI_SDP2_BY_MAC(hw); | eicr_mask = IXGBE_EICR_GPI_SDP2_BY_MAC(hw); | ||||
if (eicr & eicr_mask) { | if (eicr & eicr_mask) { | ||||
IXGBE_WRITE_REG(hw, IXGBE_EICR, eicr_mask); | IXGBE_WRITE_REG(hw, IXGBE_EICR, eicr_mask); | ||||
adapter->task_requests |= IXGBE_REQUEST_TASK_MOD; | sc->task_requests |= IXGBE_REQUEST_TASK_MOD; | ||||
} | } | ||||
if ((hw->mac.type == ixgbe_mac_82599EB) && | if ((hw->mac.type == ixgbe_mac_82599EB) && | ||||
(eicr & IXGBE_EICR_GPI_SDP1_BY_MAC(hw))) { | (eicr & IXGBE_EICR_GPI_SDP1_BY_MAC(hw))) { | ||||
IXGBE_WRITE_REG(hw, IXGBE_EICR, | IXGBE_WRITE_REG(hw, IXGBE_EICR, | ||||
IXGBE_EICR_GPI_SDP1_BY_MAC(hw)); | IXGBE_EICR_GPI_SDP1_BY_MAC(hw)); | ||||
adapter->task_requests |= IXGBE_REQUEST_TASK_MSF; | sc->task_requests |= IXGBE_REQUEST_TASK_MSF; | ||||
} | } | ||||
} | } | ||||
/* Check for fan failure */ | /* Check for fan failure */ | ||||
if (adapter->feat_en & IXGBE_FEATURE_FAN_FAIL) { | if (sc->feat_en & IXGBE_FEATURE_FAN_FAIL) { | ||||
ixgbe_check_fan_failure(adapter, eicr, true); | ixgbe_check_fan_failure(sc, eicr, true); | ||||
IXGBE_WRITE_REG(hw, IXGBE_EICR, IXGBE_EICR_GPI_SDP1_BY_MAC(hw)); | IXGBE_WRITE_REG(hw, IXGBE_EICR, IXGBE_EICR_GPI_SDP1_BY_MAC(hw)); | ||||
} | } | ||||
/* External PHY interrupt */ | /* External PHY interrupt */ | ||||
if ((hw->phy.type == ixgbe_phy_x550em_ext_t) && | if ((hw->phy.type == ixgbe_phy_x550em_ext_t) && | ||||
(eicr & IXGBE_EICR_GPI_SDP0_X540)) { | (eicr & IXGBE_EICR_GPI_SDP0_X540)) { | ||||
IXGBE_WRITE_REG(hw, IXGBE_EICR, IXGBE_EICR_GPI_SDP0_X540); | IXGBE_WRITE_REG(hw, IXGBE_EICR, IXGBE_EICR_GPI_SDP0_X540); | ||||
adapter->task_requests |= IXGBE_REQUEST_TASK_PHY; | sc->task_requests |= IXGBE_REQUEST_TASK_PHY; | ||||
} | } | ||||
return (adapter->task_requests != 0) ? FILTER_SCHEDULE_THREAD : FILTER_HANDLED; | return (sc->task_requests != 0) ? FILTER_SCHEDULE_THREAD : FILTER_HANDLED; | ||||
} /* ixgbe_msix_link */ | } /* ixgbe_msix_link */ | ||||
/************************************************************************ | /************************************************************************ | ||||
* ixgbe_sysctl_interrupt_rate_handler | * ixgbe_sysctl_interrupt_rate_handler | ||||
************************************************************************/ | ************************************************************************/ | ||||
static int | static int | ||||
ixgbe_sysctl_interrupt_rate_handler(SYSCTL_HANDLER_ARGS) | ixgbe_sysctl_interrupt_rate_handler(SYSCTL_HANDLER_ARGS) | ||||
{ | { | ||||
struct ix_rx_queue *que = ((struct ix_rx_queue *)oidp->oid_arg1); | struct ix_rx_queue *que = ((struct ix_rx_queue *)oidp->oid_arg1); | ||||
int error; | int error; | ||||
unsigned int reg, usec, rate; | unsigned int reg, usec, rate; | ||||
reg = IXGBE_READ_REG(&que->adapter->hw, IXGBE_EITR(que->msix)); | reg = IXGBE_READ_REG(&que->sc->hw, IXGBE_EITR(que->msix)); | ||||
usec = ((reg & 0x0FF8) >> 3); | usec = ((reg & 0x0FF8) >> 3); | ||||
if (usec > 0) | if (usec > 0) | ||||
rate = 500000 / usec; | rate = 500000 / usec; | ||||
else | else | ||||
rate = 0; | rate = 0; | ||||
error = sysctl_handle_int(oidp, &rate, 0, req); | error = sysctl_handle_int(oidp, &rate, 0, req); | ||||
if (error || !req->newptr) | if (error || !req->newptr) | ||||
return error; | return error; | ||||
reg &= ~0xfff; /* default, no limitation */ | reg &= ~0xfff; /* default, no limitation */ | ||||
ixgbe_max_interrupt_rate = 0; | ixgbe_max_interrupt_rate = 0; | ||||
if (rate > 0 && rate < 500000) { | if (rate > 0 && rate < 500000) { | ||||
if (rate < 1000) | if (rate < 1000) | ||||
rate = 1000; | rate = 1000; | ||||
ixgbe_max_interrupt_rate = rate; | ixgbe_max_interrupt_rate = rate; | ||||
reg |= ((4000000/rate) & 0xff8); | reg |= ((4000000/rate) & 0xff8); | ||||
} | } | ||||
IXGBE_WRITE_REG(&que->adapter->hw, IXGBE_EITR(que->msix), reg); | IXGBE_WRITE_REG(&que->sc->hw, IXGBE_EITR(que->msix), reg); | ||||
return (0); | return (0); | ||||
} /* ixgbe_sysctl_interrupt_rate_handler */ | } /* ixgbe_sysctl_interrupt_rate_handler */ | ||||
/************************************************************************ | /************************************************************************ | ||||
* ixgbe_add_device_sysctls | * ixgbe_add_device_sysctls | ||||
************************************************************************/ | ************************************************************************/ | ||||
static void | static void | ||||
ixgbe_add_device_sysctls(if_ctx_t ctx) | ixgbe_add_device_sysctls(if_ctx_t ctx) | ||||
{ | { | ||||
struct adapter *adapter = iflib_get_softc(ctx); | struct ixgbe_softc *sc = iflib_get_softc(ctx); | ||||
device_t dev = iflib_get_dev(ctx); | device_t dev = iflib_get_dev(ctx); | ||||
struct ixgbe_hw *hw = &adapter->hw; | struct ixgbe_hw *hw = &sc->hw; | ||||
struct sysctl_oid_list *child; | struct sysctl_oid_list *child; | ||||
struct sysctl_ctx_list *ctx_list; | struct sysctl_ctx_list *ctx_list; | ||||
ctx_list = device_get_sysctl_ctx(dev); | ctx_list = device_get_sysctl_ctx(dev); | ||||
child = SYSCTL_CHILDREN(device_get_sysctl_tree(dev)); | child = SYSCTL_CHILDREN(device_get_sysctl_tree(dev)); | ||||
/* Sysctls for all devices */ | /* Sysctls for all devices */ | ||||
SYSCTL_ADD_PROC(ctx_list, child, OID_AUTO, "fc", | SYSCTL_ADD_PROC(ctx_list, child, OID_AUTO, "fc", | ||||
CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NEEDGIANT, | CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NEEDGIANT, | ||||
adapter, 0, ixgbe_sysctl_flowcntl, "I", | sc, 0, ixgbe_sysctl_flowcntl, "I", | ||||
IXGBE_SYSCTL_DESC_SET_FC); | IXGBE_SYSCTL_DESC_SET_FC); | ||||
SYSCTL_ADD_PROC(ctx_list, child, OID_AUTO, "advertise_speed", | SYSCTL_ADD_PROC(ctx_list, child, OID_AUTO, "advertise_speed", | ||||
CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NEEDGIANT, | CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NEEDGIANT, | ||||
adapter, 0, ixgbe_sysctl_advertise, "I", | sc, 0, ixgbe_sysctl_advertise, "I", | ||||
IXGBE_SYSCTL_DESC_ADV_SPEED); | IXGBE_SYSCTL_DESC_ADV_SPEED); | ||||
adapter->enable_aim = ixgbe_enable_aim; | sc->enable_aim = ixgbe_enable_aim; | ||||
SYSCTL_ADD_INT(ctx_list, child, OID_AUTO, "enable_aim", CTLFLAG_RW, | SYSCTL_ADD_INT(ctx_list, child, OID_AUTO, "enable_aim", CTLFLAG_RW, | ||||
&adapter->enable_aim, 0, "Interrupt Moderation"); | &sc->enable_aim, 0, "Interrupt Moderation"); | ||||
SYSCTL_ADD_PROC(ctx_list, child, OID_AUTO, "fw_version", | SYSCTL_ADD_PROC(ctx_list, child, OID_AUTO, "fw_version", | ||||
CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_NEEDGIANT, adapter, 0, | CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_NEEDGIANT, sc, 0, | ||||
ixgbe_sysctl_print_fw_version, "A", "Prints FW/NVM Versions"); | ixgbe_sysctl_print_fw_version, "A", "Prints FW/NVM Versions"); | ||||
#ifdef IXGBE_DEBUG | #ifdef IXGBE_DEBUG | ||||
/* testing sysctls (for all devices) */ | /* testing sysctls (for all devices) */ | ||||
SYSCTL_ADD_PROC(ctx_list, child, OID_AUTO, "power_state", | SYSCTL_ADD_PROC(ctx_list, child, OID_AUTO, "power_state", | ||||
CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NEEDGIANT, | CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NEEDGIANT, | ||||
adapter, 0, ixgbe_sysctl_power_state, | sc, 0, ixgbe_sysctl_power_state, | ||||
"I", "PCI Power State"); | "I", "PCI Power State"); | ||||
SYSCTL_ADD_PROC(ctx_list, child, OID_AUTO, "print_rss_config", | SYSCTL_ADD_PROC(ctx_list, child, OID_AUTO, "print_rss_config", | ||||
CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_NEEDGIANT, adapter, 0, | CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_NEEDGIANT, sc, 0, | ||||
ixgbe_sysctl_print_rss_config, "A", "Prints RSS Configuration"); | ixgbe_sysctl_print_rss_config, "A", "Prints RSS Configuration"); | ||||
#endif | #endif | ||||
/* for X550 series devices */ | /* for X550 series devices */ | ||||
if (hw->mac.type >= ixgbe_mac_X550) | if (hw->mac.type >= ixgbe_mac_X550) | ||||
SYSCTL_ADD_PROC(ctx_list, child, OID_AUTO, "dmac", | SYSCTL_ADD_PROC(ctx_list, child, OID_AUTO, "dmac", | ||||
CTLTYPE_U16 | CTLFLAG_RW | CTLFLAG_NEEDGIANT, | CTLTYPE_U16 | CTLFLAG_RW | CTLFLAG_NEEDGIANT, | ||||
adapter, 0, ixgbe_sysctl_dmac, | sc, 0, ixgbe_sysctl_dmac, | ||||
"I", "DMA Coalesce"); | "I", "DMA Coalesce"); | ||||
/* for WoL-capable devices */ | /* for WoL-capable devices */ | ||||
if (hw->device_id == IXGBE_DEV_ID_X550EM_X_10G_T) { | if (hw->device_id == IXGBE_DEV_ID_X550EM_X_10G_T) { | ||||
SYSCTL_ADD_PROC(ctx_list, child, OID_AUTO, "wol_enable", | SYSCTL_ADD_PROC(ctx_list, child, OID_AUTO, "wol_enable", | ||||
CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NEEDGIANT, adapter, 0, | CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NEEDGIANT, sc, 0, | ||||
ixgbe_sysctl_wol_enable, "I", "Enable/Disable Wake on LAN"); | ixgbe_sysctl_wol_enable, "I", "Enable/Disable Wake on LAN"); | ||||
SYSCTL_ADD_PROC(ctx_list, child, OID_AUTO, "wufc", | SYSCTL_ADD_PROC(ctx_list, child, OID_AUTO, "wufc", | ||||
CTLTYPE_U32 | CTLFLAG_RW | CTLFLAG_NEEDGIANT, | CTLTYPE_U32 | CTLFLAG_RW | CTLFLAG_NEEDGIANT, | ||||
adapter, 0, ixgbe_sysctl_wufc, | sc, 0, ixgbe_sysctl_wufc, | ||||
"I", "Enable/Disable Wake Up Filters"); | "I", "Enable/Disable Wake Up Filters"); | ||||
} | } | ||||
/* for X552/X557-AT devices */ | /* for X552/X557-AT devices */ | ||||
if (hw->device_id == IXGBE_DEV_ID_X550EM_X_10G_T) { | if (hw->device_id == IXGBE_DEV_ID_X550EM_X_10G_T) { | ||||
struct sysctl_oid *phy_node; | struct sysctl_oid *phy_node; | ||||
struct sysctl_oid_list *phy_list; | struct sysctl_oid_list *phy_list; | ||||
phy_node = SYSCTL_ADD_NODE(ctx_list, child, OID_AUTO, "phy", | phy_node = SYSCTL_ADD_NODE(ctx_list, child, OID_AUTO, "phy", | ||||
CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, "External PHY sysctls"); | CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, "External PHY sysctls"); | ||||
phy_list = SYSCTL_CHILDREN(phy_node); | phy_list = SYSCTL_CHILDREN(phy_node); | ||||
SYSCTL_ADD_PROC(ctx_list, phy_list, OID_AUTO, "temp", | SYSCTL_ADD_PROC(ctx_list, phy_list, OID_AUTO, "temp", | ||||
CTLTYPE_U16 | CTLFLAG_RD | CTLFLAG_NEEDGIANT, | CTLTYPE_U16 | CTLFLAG_RD | CTLFLAG_NEEDGIANT, | ||||
adapter, 0, ixgbe_sysctl_phy_temp, | sc, 0, ixgbe_sysctl_phy_temp, | ||||
"I", "Current External PHY Temperature (Celsius)"); | "I", "Current External PHY Temperature (Celsius)"); | ||||
SYSCTL_ADD_PROC(ctx_list, phy_list, OID_AUTO, | SYSCTL_ADD_PROC(ctx_list, phy_list, OID_AUTO, | ||||
"overtemp_occurred", | "overtemp_occurred", | ||||
CTLTYPE_U16 | CTLFLAG_RD | CTLFLAG_NEEDGIANT, adapter, 0, | CTLTYPE_U16 | CTLFLAG_RD | CTLFLAG_NEEDGIANT, sc, 0, | ||||
ixgbe_sysctl_phy_overtemp_occurred, "I", | ixgbe_sysctl_phy_overtemp_occurred, "I", | ||||
"External PHY High Temperature Event Occurred"); | "External PHY High Temperature Event Occurred"); | ||||
} | } | ||||
if (adapter->feat_cap & IXGBE_FEATURE_EEE) { | if (sc->feat_cap & IXGBE_FEATURE_EEE) { | ||||
SYSCTL_ADD_PROC(ctx_list, child, OID_AUTO, "eee_state", | SYSCTL_ADD_PROC(ctx_list, child, OID_AUTO, "eee_state", | ||||
CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NEEDGIANT, adapter, 0, | CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NEEDGIANT, sc, 0, | ||||
ixgbe_sysctl_eee_state, "I", "EEE Power Save State"); | ixgbe_sysctl_eee_state, "I", "EEE Power Save State"); | ||||
} | } | ||||
} /* ixgbe_add_device_sysctls */ | } /* ixgbe_add_device_sysctls */ | ||||
/************************************************************************ | /************************************************************************ | ||||
* ixgbe_allocate_pci_resources | * ixgbe_allocate_pci_resources | ||||
************************************************************************/ | ************************************************************************/ | ||||
static int | static int | ||||
ixgbe_allocate_pci_resources(if_ctx_t ctx) | ixgbe_allocate_pci_resources(if_ctx_t ctx) | ||||
{ | { | ||||
struct adapter *adapter = iflib_get_softc(ctx); | struct ixgbe_softc *sc = iflib_get_softc(ctx); | ||||
device_t dev = iflib_get_dev(ctx); | device_t dev = iflib_get_dev(ctx); | ||||
int rid; | int rid; | ||||
rid = PCIR_BAR(0); | rid = PCIR_BAR(0); | ||||
adapter->pci_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, | sc->pci_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, | ||||
RF_ACTIVE); | RF_ACTIVE); | ||||
if (!(adapter->pci_mem)) { | if (!(sc->pci_mem)) { | ||||
device_printf(dev, "Unable to allocate bus resource: memory\n"); | device_printf(dev, "Unable to allocate bus resource: memory\n"); | ||||
return (ENXIO); | return (ENXIO); | ||||
} | } | ||||
/* Save bus_space values for READ/WRITE_REG macros */ | /* Save bus_space values for READ/WRITE_REG macros */ | ||||
adapter->osdep.mem_bus_space_tag = rman_get_bustag(adapter->pci_mem); | sc->osdep.mem_bus_space_tag = rman_get_bustag(sc->pci_mem); | ||||
adapter->osdep.mem_bus_space_handle = | sc->osdep.mem_bus_space_handle = | ||||
rman_get_bushandle(adapter->pci_mem); | rman_get_bushandle(sc->pci_mem); | ||||
/* Set hw values for shared code */ | /* Set hw values for shared code */ | ||||
adapter->hw.hw_addr = (u8 *)&adapter->osdep.mem_bus_space_handle; | sc->hw.hw_addr = (u8 *)&sc->osdep.mem_bus_space_handle; | ||||
return (0); | return (0); | ||||
} /* ixgbe_allocate_pci_resources */ | } /* ixgbe_allocate_pci_resources */ | ||||
/************************************************************************ | /************************************************************************ | ||||
* ixgbe_detach - Device removal routine | * ixgbe_detach - Device removal routine | ||||
* | * | ||||
* Called when the driver is being removed. | * Called when the driver is being removed. | ||||
* Stops the adapter and deallocates all the resources | * Stops the adapter and deallocates all the resources | ||||
* that were allocated for driver operation. | * that were allocated for driver operation. | ||||
* | * | ||||
* return 0 on success, positive on failure | * return 0 on success, positive on failure | ||||
************************************************************************/ | ************************************************************************/ | ||||
static int | static int | ||||
ixgbe_if_detach(if_ctx_t ctx) | ixgbe_if_detach(if_ctx_t ctx) | ||||
{ | { | ||||
struct adapter *adapter = iflib_get_softc(ctx); | struct ixgbe_softc *sc = iflib_get_softc(ctx); | ||||
device_t dev = iflib_get_dev(ctx); | device_t dev = iflib_get_dev(ctx); | ||||
u32 ctrl_ext; | u32 ctrl_ext; | ||||
INIT_DEBUGOUT("ixgbe_detach: begin"); | INIT_DEBUGOUT("ixgbe_detach: begin"); | ||||
if (ixgbe_pci_iov_detach(dev) != 0) { | if (ixgbe_pci_iov_detach(dev) != 0) { | ||||
device_printf(dev, "SR-IOV in use; detach first.\n"); | device_printf(dev, "SR-IOV in use; detach first.\n"); | ||||
return (EBUSY); | return (EBUSY); | ||||
} | } | ||||
ixgbe_setup_low_power_mode(ctx); | ixgbe_setup_low_power_mode(ctx); | ||||
/* let hardware know driver is unloading */ | /* let hardware know driver is unloading */ | ||||
ctrl_ext = IXGBE_READ_REG(&adapter->hw, IXGBE_CTRL_EXT); | ctrl_ext = IXGBE_READ_REG(&sc->hw, IXGBE_CTRL_EXT); | ||||
ctrl_ext &= ~IXGBE_CTRL_EXT_DRV_LOAD; | ctrl_ext &= ~IXGBE_CTRL_EXT_DRV_LOAD; | ||||
IXGBE_WRITE_REG(&adapter->hw, IXGBE_CTRL_EXT, ctrl_ext); | IXGBE_WRITE_REG(&sc->hw, IXGBE_CTRL_EXT, ctrl_ext); | ||||
ixgbe_free_pci_resources(ctx); | ixgbe_free_pci_resources(ctx); | ||||
free(adapter->mta, M_IXGBE); | free(sc->mta, M_IXGBE); | ||||
return (0); | return (0); | ||||
} /* ixgbe_if_detach */ | } /* ixgbe_if_detach */ | ||||
/************************************************************************ | /************************************************************************ | ||||
* ixgbe_setup_low_power_mode - LPLU/WoL preparation | * ixgbe_setup_low_power_mode - LPLU/WoL preparation | ||||
* | * | ||||
* Prepare the adapter/port for LPLU and/or WoL | * Prepare the adapter/port for LPLU and/or WoL | ||||
************************************************************************/ | ************************************************************************/ | ||||
static int | static int | ||||
ixgbe_setup_low_power_mode(if_ctx_t ctx) | ixgbe_setup_low_power_mode(if_ctx_t ctx) | ||||
{ | { | ||||
struct adapter *adapter = iflib_get_softc(ctx); | struct ixgbe_softc *sc = iflib_get_softc(ctx); | ||||
struct ixgbe_hw *hw = &adapter->hw; | struct ixgbe_hw *hw = &sc->hw; | ||||
device_t dev = iflib_get_dev(ctx); | device_t dev = iflib_get_dev(ctx); | ||||
s32 error = 0; | s32 error = 0; | ||||
if (!hw->wol_enabled) | if (!hw->wol_enabled) | ||||
ixgbe_set_phy_power(hw, false); | ixgbe_set_phy_power(hw, false); | ||||
/* Limit power management flow to X550EM baseT */ | /* Limit power management flow to X550EM baseT */ | ||||
if (hw->device_id == IXGBE_DEV_ID_X550EM_X_10G_T && | if (hw->device_id == IXGBE_DEV_ID_X550EM_X_10G_T && | ||||
hw->phy.ops.enter_lplu) { | hw->phy.ops.enter_lplu) { | ||||
/* Turn off support for APM wakeup. (Using ACPI instead) */ | /* Turn off support for APM wakeup. (Using ACPI instead) */ | ||||
IXGBE_WRITE_REG(hw, IXGBE_GRC, | IXGBE_WRITE_REG(hw, IXGBE_GRC, | ||||
IXGBE_READ_REG(hw, IXGBE_GRC) & ~(u32)2); | IXGBE_READ_REG(hw, IXGBE_GRC) & ~(u32)2); | ||||
/* | /* | ||||
* Clear Wake Up Status register to prevent any previous wakeup | * Clear Wake Up Status register to prevent any previous wakeup | ||||
* events from waking us up immediately after we suspend. | * events from waking us up immediately after we suspend. | ||||
*/ | */ | ||||
IXGBE_WRITE_REG(hw, IXGBE_WUS, 0xffffffff); | IXGBE_WRITE_REG(hw, IXGBE_WUS, 0xffffffff); | ||||
/* | /* | ||||
* Program the Wakeup Filter Control register with user filter | * Program the Wakeup Filter Control register with user filter | ||||
* settings | * settings | ||||
*/ | */ | ||||
IXGBE_WRITE_REG(hw, IXGBE_WUFC, adapter->wufc); | IXGBE_WRITE_REG(hw, IXGBE_WUFC, sc->wufc); | ||||
/* Enable wakeups and power management in Wakeup Control */ | /* Enable wakeups and power management in Wakeup Control */ | ||||
IXGBE_WRITE_REG(hw, IXGBE_WUC, | IXGBE_WRITE_REG(hw, IXGBE_WUC, | ||||
IXGBE_WUC_WKEN | IXGBE_WUC_PME_EN); | IXGBE_WUC_WKEN | IXGBE_WUC_PME_EN); | ||||
/* X550EM baseT adapters need a special LPLU flow */ | /* X550EM baseT adapters need a special LPLU flow */ | ||||
hw->phy.reset_disable = true; | hw->phy.reset_disable = true; | ||||
ixgbe_if_stop(ctx); | ixgbe_if_stop(ctx); | ||||
▲ Show 20 Lines • Show All 44 Lines • ▼ Show 20 Lines | |||||
/************************************************************************ | /************************************************************************ | ||||
* ixgbe_resume | * ixgbe_resume | ||||
* | * | ||||
* From D3 to D0 | * From D3 to D0 | ||||
************************************************************************/ | ************************************************************************/ | ||||
static int | static int | ||||
ixgbe_if_resume(if_ctx_t ctx) | ixgbe_if_resume(if_ctx_t ctx) | ||||
{ | { | ||||
struct adapter *adapter = iflib_get_softc(ctx); | struct ixgbe_softc *sc = iflib_get_softc(ctx); | ||||
device_t dev = iflib_get_dev(ctx); | device_t dev = iflib_get_dev(ctx); | ||||
struct ifnet *ifp = iflib_get_ifp(ctx); | struct ifnet *ifp = iflib_get_ifp(ctx); | ||||
struct ixgbe_hw *hw = &adapter->hw; | struct ixgbe_hw *hw = &sc->hw; | ||||
u32 wus; | u32 wus; | ||||
INIT_DEBUGOUT("ixgbe_resume: begin"); | INIT_DEBUGOUT("ixgbe_resume: begin"); | ||||
/* Read & clear WUS register */ | /* Read & clear WUS register */ | ||||
wus = IXGBE_READ_REG(hw, IXGBE_WUS); | wus = IXGBE_READ_REG(hw, IXGBE_WUS); | ||||
if (wus) | if (wus) | ||||
device_printf(dev, "Woken up by (WUS): %#010x\n", | device_printf(dev, "Woken up by (WUS): %#010x\n", | ||||
Show All 15 Lines | |||||
/************************************************************************ | /************************************************************************ | ||||
* ixgbe_if_mtu_set - Ioctl mtu entry point | * ixgbe_if_mtu_set - Ioctl mtu entry point | ||||
* | * | ||||
* Return 0 on success, EINVAL on failure | * Return 0 on success, EINVAL on failure | ||||
************************************************************************/ | ************************************************************************/ | ||||
static int | static int | ||||
ixgbe_if_mtu_set(if_ctx_t ctx, uint32_t mtu) | ixgbe_if_mtu_set(if_ctx_t ctx, uint32_t mtu) | ||||
{ | { | ||||
struct adapter *adapter = iflib_get_softc(ctx); | struct ixgbe_softc *sc = iflib_get_softc(ctx); | ||||
int error = 0; | int error = 0; | ||||
IOCTL_DEBUGOUT("ioctl: SIOCIFMTU (Set Interface MTU)"); | IOCTL_DEBUGOUT("ioctl: SIOCIFMTU (Set Interface MTU)"); | ||||
if (mtu > IXGBE_MAX_MTU) { | if (mtu > IXGBE_MAX_MTU) { | ||||
error = EINVAL; | error = EINVAL; | ||||
} else { | } else { | ||||
adapter->max_frame_size = mtu + IXGBE_MTU_HDR; | sc->max_frame_size = mtu + IXGBE_MTU_HDR; | ||||
} | } | ||||
return error; | return error; | ||||
} /* ixgbe_if_mtu_set */ | } /* ixgbe_if_mtu_set */ | ||||
/************************************************************************ | /************************************************************************ | ||||
* ixgbe_if_crcstrip_set | * ixgbe_if_crcstrip_set | ||||
************************************************************************/ | ************************************************************************/ | ||||
static void | static void | ||||
ixgbe_if_crcstrip_set(if_ctx_t ctx, int onoff, int crcstrip) | ixgbe_if_crcstrip_set(if_ctx_t ctx, int onoff, int crcstrip) | ||||
{ | { | ||||
struct adapter *sc = iflib_get_softc(ctx); | struct ixgbe_softc *sc = iflib_get_softc(ctx); | ||||
struct ixgbe_hw *hw = &sc->hw; | struct ixgbe_hw *hw = &sc->hw; | ||||
/* crc stripping is set in two places: | /* crc stripping is set in two places: | ||||
* IXGBE_HLREG0 (modified on init_locked and hw reset) | * IXGBE_HLREG0 (modified on init_locked and hw reset) | ||||
* IXGBE_RDRXCTL (set by the original driver in | * IXGBE_RDRXCTL (set by the original driver in | ||||
* ixgbe_setup_hw_rsc() called in init_locked. | * ixgbe_setup_hw_rsc() called in init_locked. | ||||
* We disable the setting when netmap is compiled in). | * We disable the setting when netmap is compiled in). | ||||
* We update the values here, but also in ixgbe.c because | * We update the values here, but also in ixgbe.c because | ||||
* init_locked sometimes is called outside our control. | * init_locked sometimes is called outside our control. | ||||
Show All 36 Lines | |||||
* used by the driver as a hw/sw initialization routine to | * used by the driver as a hw/sw initialization routine to | ||||
* get to a consistent state. | * get to a consistent state. | ||||
* | * | ||||
* Return 0 on success, positive on failure | * Return 0 on success, positive on failure | ||||
**********************************************************************/ | **********************************************************************/ | ||||
void | void | ||||
ixgbe_if_init(if_ctx_t ctx) | ixgbe_if_init(if_ctx_t ctx) | ||||
{ | { | ||||
struct adapter *adapter = iflib_get_softc(ctx); | struct ixgbe_softc *sc = iflib_get_softc(ctx); | ||||
struct ifnet *ifp = iflib_get_ifp(ctx); | struct ifnet *ifp = iflib_get_ifp(ctx); | ||||
device_t dev = iflib_get_dev(ctx); | device_t dev = iflib_get_dev(ctx); | ||||
struct ixgbe_hw *hw = &adapter->hw; | struct ixgbe_hw *hw = &sc->hw; | ||||
struct ix_rx_queue *rx_que; | struct ix_rx_queue *rx_que; | ||||
struct ix_tx_queue *tx_que; | struct ix_tx_queue *tx_que; | ||||
u32 txdctl, mhadd; | u32 txdctl, mhadd; | ||||
u32 rxdctl, rxctrl; | u32 rxdctl, rxctrl; | ||||
u32 ctrl_ext; | u32 ctrl_ext; | ||||
int i, j, err; | int i, j, err; | ||||
INIT_DEBUGOUT("ixgbe_if_init: begin"); | INIT_DEBUGOUT("ixgbe_if_init: begin"); | ||||
/* Queue indices may change with IOV mode */ | /* Queue indices may change with IOV mode */ | ||||
ixgbe_align_all_queue_indices(adapter); | ixgbe_align_all_queue_indices(sc); | ||||
/* reprogram the RAR[0] in case user changed it. */ | /* reprogram the RAR[0] in case user changed it. */ | ||||
ixgbe_set_rar(hw, 0, hw->mac.addr, adapter->pool, IXGBE_RAH_AV); | ixgbe_set_rar(hw, 0, hw->mac.addr, sc->pool, IXGBE_RAH_AV); | ||||
/* Get the latest mac address, User can use a LAA */ | /* Get the latest mac address, User can use a LAA */ | ||||
bcopy(IF_LLADDR(ifp), hw->mac.addr, IXGBE_ETH_LENGTH_OF_ADDRESS); | bcopy(IF_LLADDR(ifp), hw->mac.addr, IXGBE_ETH_LENGTH_OF_ADDRESS); | ||||
ixgbe_set_rar(hw, 0, hw->mac.addr, adapter->pool, 1); | ixgbe_set_rar(hw, 0, hw->mac.addr, sc->pool, 1); | ||||
hw->addr_ctrl.rar_used_count = 1; | hw->addr_ctrl.rar_used_count = 1; | ||||
ixgbe_init_hw(hw); | ixgbe_init_hw(hw); | ||||
ixgbe_initialize_iov(adapter); | ixgbe_initialize_iov(sc); | ||||
ixgbe_initialize_transmit_units(ctx); | ixgbe_initialize_transmit_units(ctx); | ||||
/* Setup Multicast table */ | /* Setup Multicast table */ | ||||
ixgbe_if_multi_set(ctx); | ixgbe_if_multi_set(ctx); | ||||
/* Determine the correct mbuf pool, based on frame size */ | /* Determine the correct mbuf pool, based on frame size */ | ||||
adapter->rx_mbuf_sz = iflib_get_rx_mbuf_sz(ctx); | sc->rx_mbuf_sz = iflib_get_rx_mbuf_sz(ctx); | ||||
/* Configure RX settings */ | /* Configure RX settings */ | ||||
ixgbe_initialize_receive_units(ctx); | ixgbe_initialize_receive_units(ctx); | ||||
/* | /* | ||||
* Initialize variable holding task enqueue requests | * Initialize variable holding task enqueue requests | ||||
* from MSI-X interrupts | * from MSI-X interrupts | ||||
*/ | */ | ||||
adapter->task_requests = 0; | sc->task_requests = 0; | ||||
/* Enable SDP & MSI-X interrupts based on adapter */ | /* Enable SDP & MSI-X interrupts based on adapter */ | ||||
ixgbe_config_gpie(adapter); | ixgbe_config_gpie(sc); | ||||
/* Set MTU size */ | /* Set MTU size */ | ||||
if (ifp->if_mtu > ETHERMTU) { | if (ifp->if_mtu > ETHERMTU) { | ||||
/* aka IXGBE_MAXFRS on 82599 and newer */ | /* aka IXGBE_MAXFRS on 82599 and newer */ | ||||
mhadd = IXGBE_READ_REG(hw, IXGBE_MHADD); | mhadd = IXGBE_READ_REG(hw, IXGBE_MHADD); | ||||
mhadd &= ~IXGBE_MHADD_MFS_MASK; | mhadd &= ~IXGBE_MHADD_MFS_MASK; | ||||
mhadd |= adapter->max_frame_size << IXGBE_MHADD_MFS_SHIFT; | mhadd |= sc->max_frame_size << IXGBE_MHADD_MFS_SHIFT; | ||||
IXGBE_WRITE_REG(hw, IXGBE_MHADD, mhadd); | IXGBE_WRITE_REG(hw, IXGBE_MHADD, mhadd); | ||||
} | } | ||||
/* Now enable all the queues */ | /* Now enable all the queues */ | ||||
for (i = 0, tx_que = adapter->tx_queues; i < adapter->num_tx_queues; i++, tx_que++) { | for (i = 0, tx_que = sc->tx_queues; i < sc->num_tx_queues; i++, tx_que++) { | ||||
struct tx_ring *txr = &tx_que->txr; | struct tx_ring *txr = &tx_que->txr; | ||||
txdctl = IXGBE_READ_REG(hw, IXGBE_TXDCTL(txr->me)); | txdctl = IXGBE_READ_REG(hw, IXGBE_TXDCTL(txr->me)); | ||||
txdctl |= IXGBE_TXDCTL_ENABLE; | txdctl |= IXGBE_TXDCTL_ENABLE; | ||||
/* Set WTHRESH to 8, burst writeback */ | /* Set WTHRESH to 8, burst writeback */ | ||||
txdctl |= (8 << 16); | txdctl |= (8 << 16); | ||||
/* | /* | ||||
* When the internal queue falls below PTHRESH (32), | * When the internal queue falls below PTHRESH (32), | ||||
* start prefetching as long as there are at least | * start prefetching as long as there are at least | ||||
* HTHRESH (1) buffers ready. The values are taken | * HTHRESH (1) buffers ready. The values are taken | ||||
* from the Intel linux driver 3.8.21. | * from the Intel linux driver 3.8.21. | ||||
* Prefetching enables tx line rate even with 1 queue. | * Prefetching enables tx line rate even with 1 queue. | ||||
*/ | */ | ||||
txdctl |= (32 << 0) | (1 << 8); | txdctl |= (32 << 0) | (1 << 8); | ||||
IXGBE_WRITE_REG(hw, IXGBE_TXDCTL(txr->me), txdctl); | IXGBE_WRITE_REG(hw, IXGBE_TXDCTL(txr->me), txdctl); | ||||
} | } | ||||
for (i = 0, rx_que = adapter->rx_queues; i < adapter->num_rx_queues; i++, rx_que++) { | for (i = 0, rx_que = sc->rx_queues; i < sc->num_rx_queues; i++, rx_que++) { | ||||
struct rx_ring *rxr = &rx_que->rxr; | struct rx_ring *rxr = &rx_que->rxr; | ||||
rxdctl = IXGBE_READ_REG(hw, IXGBE_RXDCTL(rxr->me)); | rxdctl = IXGBE_READ_REG(hw, IXGBE_RXDCTL(rxr->me)); | ||||
if (hw->mac.type == ixgbe_mac_82598EB) { | if (hw->mac.type == ixgbe_mac_82598EB) { | ||||
/* | /* | ||||
* PTHRESH = 21 | * PTHRESH = 21 | ||||
* HTHRESH = 4 | * HTHRESH = 4 | ||||
* WTHRESH = 8 | * WTHRESH = 8 | ||||
Show All 17 Lines | ixgbe_if_init(if_ctx_t ctx) | ||||
rxctrl = IXGBE_READ_REG(hw, IXGBE_RXCTRL); | rxctrl = IXGBE_READ_REG(hw, IXGBE_RXCTRL); | ||||
if (hw->mac.type == ixgbe_mac_82598EB) | if (hw->mac.type == ixgbe_mac_82598EB) | ||||
rxctrl |= IXGBE_RXCTRL_DMBYPS; | rxctrl |= IXGBE_RXCTRL_DMBYPS; | ||||
rxctrl |= IXGBE_RXCTRL_RXEN; | rxctrl |= IXGBE_RXCTRL_RXEN; | ||||
ixgbe_enable_rx_dma(hw, rxctrl); | ixgbe_enable_rx_dma(hw, rxctrl); | ||||
/* Set up MSI/MSI-X routing */ | /* Set up MSI/MSI-X routing */ | ||||
if (ixgbe_enable_msix) { | if (ixgbe_enable_msix) { | ||||
ixgbe_configure_ivars(adapter); | ixgbe_configure_ivars(sc); | ||||
/* Set up auto-mask */ | /* Set up auto-mask */ | ||||
if (hw->mac.type == ixgbe_mac_82598EB) | if (hw->mac.type == ixgbe_mac_82598EB) | ||||
IXGBE_WRITE_REG(hw, IXGBE_EIAM, IXGBE_EICS_RTX_QUEUE); | IXGBE_WRITE_REG(hw, IXGBE_EIAM, IXGBE_EICS_RTX_QUEUE); | ||||
else { | else { | ||||
IXGBE_WRITE_REG(hw, IXGBE_EIAM_EX(0), 0xFFFFFFFF); | IXGBE_WRITE_REG(hw, IXGBE_EIAM_EX(0), 0xFFFFFFFF); | ||||
IXGBE_WRITE_REG(hw, IXGBE_EIAM_EX(1), 0xFFFFFFFF); | IXGBE_WRITE_REG(hw, IXGBE_EIAM_EX(1), 0xFFFFFFFF); | ||||
} | } | ||||
} else { /* Simple settings for Legacy/MSI */ | } else { /* Simple settings for Legacy/MSI */ | ||||
ixgbe_set_ivar(adapter, 0, 0, 0); | ixgbe_set_ivar(sc, 0, 0, 0); | ||||
ixgbe_set_ivar(adapter, 0, 0, 1); | ixgbe_set_ivar(sc, 0, 0, 1); | ||||
IXGBE_WRITE_REG(hw, IXGBE_EIAM, IXGBE_EICS_RTX_QUEUE); | IXGBE_WRITE_REG(hw, IXGBE_EIAM, IXGBE_EICS_RTX_QUEUE); | ||||
} | } | ||||
ixgbe_init_fdir(adapter); | ixgbe_init_fdir(sc); | ||||
/* | /* | ||||
* Check on any SFP devices that | * Check on any SFP devices that | ||||
* need to be kick-started | * need to be kick-started | ||||
*/ | */ | ||||
if (hw->phy.type == ixgbe_phy_none) { | if (hw->phy.type == ixgbe_phy_none) { | ||||
err = hw->phy.ops.identify(hw); | err = hw->phy.ops.identify(hw); | ||||
if (err == IXGBE_ERR_SFP_NOT_SUPPORTED) { | if (err == IXGBE_ERR_SFP_NOT_SUPPORTED) { | ||||
device_printf(dev, | device_printf(dev, | ||||
"Unsupported SFP+ module type was detected.\n"); | "Unsupported SFP+ module type was detected.\n"); | ||||
return; | return; | ||||
} | } | ||||
} | } | ||||
/* Set moderation on the Link interrupt */ | /* Set moderation on the Link interrupt */ | ||||
IXGBE_WRITE_REG(hw, IXGBE_EITR(adapter->vector), IXGBE_LINK_ITR); | IXGBE_WRITE_REG(hw, IXGBE_EITR(sc->vector), IXGBE_LINK_ITR); | ||||
/* Enable power to the phy. */ | /* Enable power to the phy. */ | ||||
ixgbe_set_phy_power(hw, true); | ixgbe_set_phy_power(hw, true); | ||||
/* Config/Enable Link */ | /* Config/Enable Link */ | ||||
ixgbe_config_link(ctx); | ixgbe_config_link(ctx); | ||||
/* Hardware Packet Buffer & Flow Control setup */ | /* Hardware Packet Buffer & Flow Control setup */ | ||||
ixgbe_config_delay_values(adapter); | ixgbe_config_delay_values(sc); | ||||
/* Initialize the FC settings */ | /* Initialize the FC settings */ | ||||
ixgbe_start_hw(hw); | ixgbe_start_hw(hw); | ||||
/* Set up VLAN support and filter */ | /* Set up VLAN support and filter */ | ||||
ixgbe_setup_vlan_hw_support(ctx); | ixgbe_setup_vlan_hw_support(ctx); | ||||
/* Setup DMA Coalescing */ | /* Setup DMA Coalescing */ | ||||
ixgbe_config_dmac(adapter); | ixgbe_config_dmac(sc); | ||||
/* And now turn on interrupts */ | /* And now turn on interrupts */ | ||||
ixgbe_if_enable_intr(ctx); | ixgbe_if_enable_intr(ctx); | ||||
/* Enable the use of the MBX by the VF's */ | /* Enable the use of the MBX by the VF's */ | ||||
if (adapter->feat_en & IXGBE_FEATURE_SRIOV) { | if (sc->feat_en & IXGBE_FEATURE_SRIOV) { | ||||
ctrl_ext = IXGBE_READ_REG(hw, IXGBE_CTRL_EXT); | ctrl_ext = IXGBE_READ_REG(hw, IXGBE_CTRL_EXT); | ||||
ctrl_ext |= IXGBE_CTRL_EXT_PFRSTD; | ctrl_ext |= IXGBE_CTRL_EXT_PFRSTD; | ||||
IXGBE_WRITE_REG(hw, IXGBE_CTRL_EXT, ctrl_ext); | IXGBE_WRITE_REG(hw, IXGBE_CTRL_EXT, ctrl_ext); | ||||
} | } | ||||
} /* ixgbe_init_locked */ | } /* ixgbe_init_locked */ | ||||
/************************************************************************ | /************************************************************************ | ||||
* ixgbe_set_ivar | * ixgbe_set_ivar | ||||
* | * | ||||
* Setup the correct IVAR register for a particular MSI-X interrupt | * Setup the correct IVAR register for a particular MSI-X interrupt | ||||
* (yes this is all very magic and confusing :) | * (yes this is all very magic and confusing :) | ||||
* - entry is the register array entry | * - entry is the register array entry | ||||
* - vector is the MSI-X vector for this queue | * - vector is the MSI-X vector for this queue | ||||
* - type is RX/TX/MISC | * - type is RX/TX/MISC | ||||
************************************************************************/ | ************************************************************************/ | ||||
static void | static void | ||||
ixgbe_set_ivar(struct adapter *adapter, u8 entry, u8 vector, s8 type) | ixgbe_set_ivar(struct ixgbe_softc *sc, u8 entry, u8 vector, s8 type) | ||||
{ | { | ||||
struct ixgbe_hw *hw = &adapter->hw; | struct ixgbe_hw *hw = &sc->hw; | ||||
u32 ivar, index; | u32 ivar, index; | ||||
vector |= IXGBE_IVAR_ALLOC_VAL; | vector |= IXGBE_IVAR_ALLOC_VAL; | ||||
switch (hw->mac.type) { | switch (hw->mac.type) { | ||||
case ixgbe_mac_82598EB: | case ixgbe_mac_82598EB: | ||||
if (type == -1) | if (type == -1) | ||||
entry = IXGBE_IVAR_OTHER_CAUSES_INDEX; | entry = IXGBE_IVAR_OTHER_CAUSES_INDEX; | ||||
else | else | ||||
entry += (type * 64); | entry += (type * 64); | ||||
index = (entry >> 2) & 0x1F; | index = (entry >> 2) & 0x1F; | ||||
ivar = IXGBE_READ_REG(hw, IXGBE_IVAR(index)); | ivar = IXGBE_READ_REG(hw, IXGBE_IVAR(index)); | ||||
ivar &= ~(0xFF << (8 * (entry & 0x3))); | ivar &= ~(0xFF << (8 * (entry & 0x3))); | ||||
ivar |= (vector << (8 * (entry & 0x3))); | ivar |= (vector << (8 * (entry & 0x3))); | ||||
IXGBE_WRITE_REG(&adapter->hw, IXGBE_IVAR(index), ivar); | IXGBE_WRITE_REG(&sc->hw, IXGBE_IVAR(index), ivar); | ||||
break; | break; | ||||
case ixgbe_mac_82599EB: | case ixgbe_mac_82599EB: | ||||
case ixgbe_mac_X540: | case ixgbe_mac_X540: | ||||
case ixgbe_mac_X550: | case ixgbe_mac_X550: | ||||
case ixgbe_mac_X550EM_x: | case ixgbe_mac_X550EM_x: | ||||
case ixgbe_mac_X550EM_a: | case ixgbe_mac_X550EM_a: | ||||
if (type == -1) { /* MISC IVAR */ | if (type == -1) { /* MISC IVAR */ | ||||
index = (entry & 1) * 8; | index = (entry & 1) * 8; | ||||
Show All 12 Lines | default: | ||||
break; | break; | ||||
} | } | ||||
} /* ixgbe_set_ivar */ | } /* ixgbe_set_ivar */ | ||||
/************************************************************************ | /************************************************************************ | ||||
* ixgbe_configure_ivars | * ixgbe_configure_ivars | ||||
************************************************************************/ | ************************************************************************/ | ||||
static void | static void | ||||
ixgbe_configure_ivars(struct adapter *adapter) | ixgbe_configure_ivars(struct ixgbe_softc *sc) | ||||
{ | { | ||||
struct ix_rx_queue *rx_que = adapter->rx_queues; | struct ix_rx_queue *rx_que = sc->rx_queues; | ||||
struct ix_tx_queue *tx_que = adapter->tx_queues; | struct ix_tx_queue *tx_que = sc->tx_queues; | ||||
u32 newitr; | u32 newitr; | ||||
if (ixgbe_max_interrupt_rate > 0) | if (ixgbe_max_interrupt_rate > 0) | ||||
newitr = (4000000 / ixgbe_max_interrupt_rate) & 0x0FF8; | newitr = (4000000 / ixgbe_max_interrupt_rate) & 0x0FF8; | ||||
else { | else { | ||||
/* | /* | ||||
* Disable DMA coalescing if interrupt moderation is | * Disable DMA coalescing if interrupt moderation is | ||||
* disabled. | * disabled. | ||||
*/ | */ | ||||
adapter->dmac = 0; | sc->dmac = 0; | ||||
newitr = 0; | newitr = 0; | ||||
} | } | ||||
for (int i = 0; i < adapter->num_rx_queues; i++, rx_que++) { | for (int i = 0; i < sc->num_rx_queues; i++, rx_que++) { | ||||
struct rx_ring *rxr = &rx_que->rxr; | struct rx_ring *rxr = &rx_que->rxr; | ||||
/* First the RX queue entry */ | /* First the RX queue entry */ | ||||
ixgbe_set_ivar(adapter, rxr->me, rx_que->msix, 0); | ixgbe_set_ivar(sc, rxr->me, rx_que->msix, 0); | ||||
/* Set an Initial EITR value */ | /* Set an Initial EITR value */ | ||||
IXGBE_WRITE_REG(&adapter->hw, IXGBE_EITR(rx_que->msix), newitr); | IXGBE_WRITE_REG(&sc->hw, IXGBE_EITR(rx_que->msix), newitr); | ||||
} | } | ||||
for (int i = 0; i < adapter->num_tx_queues; i++, tx_que++) { | for (int i = 0; i < sc->num_tx_queues; i++, tx_que++) { | ||||
struct tx_ring *txr = &tx_que->txr; | struct tx_ring *txr = &tx_que->txr; | ||||
/* ... and the TX */ | /* ... and the TX */ | ||||
ixgbe_set_ivar(adapter, txr->me, tx_que->msix, 1); | ixgbe_set_ivar(sc, txr->me, tx_que->msix, 1); | ||||
} | } | ||||
/* For the Link interrupt */ | /* For the Link interrupt */ | ||||
ixgbe_set_ivar(adapter, 1, adapter->vector, -1); | ixgbe_set_ivar(sc, 1, sc->vector, -1); | ||||
} /* ixgbe_configure_ivars */ | } /* ixgbe_configure_ivars */ | ||||
/************************************************************************ | /************************************************************************ | ||||
* ixgbe_config_gpie | * ixgbe_config_gpie | ||||
************************************************************************/ | ************************************************************************/ | ||||
static void | static void | ||||
ixgbe_config_gpie(struct adapter *adapter) | ixgbe_config_gpie(struct ixgbe_softc *sc) | ||||
{ | { | ||||
struct ixgbe_hw *hw = &adapter->hw; | struct ixgbe_hw *hw = &sc->hw; | ||||
u32 gpie; | u32 gpie; | ||||
gpie = IXGBE_READ_REG(hw, IXGBE_GPIE); | gpie = IXGBE_READ_REG(hw, IXGBE_GPIE); | ||||
if (adapter->intr_type == IFLIB_INTR_MSIX) { | if (sc->intr_type == IFLIB_INTR_MSIX) { | ||||
/* Enable Enhanced MSI-X mode */ | /* Enable Enhanced MSI-X mode */ | ||||
gpie |= IXGBE_GPIE_MSIX_MODE | gpie |= IXGBE_GPIE_MSIX_MODE | ||||
| IXGBE_GPIE_EIAME | | IXGBE_GPIE_EIAME | ||||
| IXGBE_GPIE_PBA_SUPPORT | | IXGBE_GPIE_PBA_SUPPORT | ||||
| IXGBE_GPIE_OCD; | | IXGBE_GPIE_OCD; | ||||
} | } | ||||
/* Fan Failure Interrupt */ | /* Fan Failure Interrupt */ | ||||
if (adapter->feat_en & IXGBE_FEATURE_FAN_FAIL) | if (sc->feat_en & IXGBE_FEATURE_FAN_FAIL) | ||||
gpie |= IXGBE_SDP1_GPIEN; | gpie |= IXGBE_SDP1_GPIEN; | ||||
/* Thermal Sensor Interrupt */ | /* Thermal Sensor Interrupt */ | ||||
if (adapter->feat_en & IXGBE_FEATURE_TEMP_SENSOR) | if (sc->feat_en & IXGBE_FEATURE_TEMP_SENSOR) | ||||
gpie |= IXGBE_SDP0_GPIEN_X540; | gpie |= IXGBE_SDP0_GPIEN_X540; | ||||
/* Link detection */ | /* Link detection */ | ||||
switch (hw->mac.type) { | switch (hw->mac.type) { | ||||
case ixgbe_mac_82599EB: | case ixgbe_mac_82599EB: | ||||
gpie |= IXGBE_SDP1_GPIEN | IXGBE_SDP2_GPIEN; | gpie |= IXGBE_SDP1_GPIEN | IXGBE_SDP2_GPIEN; | ||||
break; | break; | ||||
case ixgbe_mac_X550EM_x: | case ixgbe_mac_X550EM_x: | ||||
case ixgbe_mac_X550EM_a: | case ixgbe_mac_X550EM_a: | ||||
gpie |= IXGBE_SDP0_GPIEN_X540; | gpie |= IXGBE_SDP0_GPIEN_X540; | ||||
break; | break; | ||||
default: | default: | ||||
break; | break; | ||||
} | } | ||||
IXGBE_WRITE_REG(hw, IXGBE_GPIE, gpie); | IXGBE_WRITE_REG(hw, IXGBE_GPIE, gpie); | ||||
} /* ixgbe_config_gpie */ | } /* ixgbe_config_gpie */ | ||||
/************************************************************************ | /************************************************************************ | ||||
* ixgbe_config_delay_values | * ixgbe_config_delay_values | ||||
* | * | ||||
* Requires adapter->max_frame_size to be set. | * Requires sc->max_frame_size to be set. | ||||
************************************************************************/ | ************************************************************************/ | ||||
static void | static void | ||||
ixgbe_config_delay_values(struct adapter *adapter) | ixgbe_config_delay_values(struct ixgbe_softc *sc) | ||||
{ | { | ||||
struct ixgbe_hw *hw = &adapter->hw; | struct ixgbe_hw *hw = &sc->hw; | ||||
u32 rxpb, frame, size, tmp; | u32 rxpb, frame, size, tmp; | ||||
frame = adapter->max_frame_size; | frame = sc->max_frame_size; | ||||
/* Calculate High Water */ | /* Calculate High Water */ | ||||
switch (hw->mac.type) { | switch (hw->mac.type) { | ||||
case ixgbe_mac_X540: | case ixgbe_mac_X540: | ||||
case ixgbe_mac_X550: | case ixgbe_mac_X550: | ||||
case ixgbe_mac_X550EM_x: | case ixgbe_mac_X550EM_x: | ||||
case ixgbe_mac_X550EM_a: | case ixgbe_mac_X550EM_a: | ||||
tmp = IXGBE_DV_X540(frame, frame); | tmp = IXGBE_DV_X540(frame, frame); | ||||
Show All 27 Lines | |||||
/************************************************************************ | /************************************************************************ | ||||
* ixgbe_set_multi - Multicast Update | * ixgbe_set_multi - Multicast Update | ||||
* | * | ||||
* Called whenever multicast address list is updated. | * Called whenever multicast address list is updated. | ||||
************************************************************************/ | ************************************************************************/ | ||||
static u_int | static u_int | ||||
ixgbe_mc_filter_apply(void *arg, struct sockaddr_dl *sdl, u_int idx) | ixgbe_mc_filter_apply(void *arg, struct sockaddr_dl *sdl, u_int idx) | ||||
{ | { | ||||
struct adapter *adapter = arg; | struct ixgbe_softc *sc = arg; | ||||
struct ixgbe_mc_addr *mta = adapter->mta; | struct ixgbe_mc_addr *mta = sc->mta; | ||||
if (idx == MAX_NUM_MULTICAST_ADDRESSES) | if (idx == MAX_NUM_MULTICAST_ADDRESSES) | ||||
return (0); | return (0); | ||||
bcopy(LLADDR(sdl), mta[idx].addr, IXGBE_ETH_LENGTH_OF_ADDRESS); | bcopy(LLADDR(sdl), mta[idx].addr, IXGBE_ETH_LENGTH_OF_ADDRESS); | ||||
mta[idx].vmdq = adapter->pool; | mta[idx].vmdq = sc->pool; | ||||
return (1); | return (1); | ||||
} /* ixgbe_mc_filter_apply */ | } /* ixgbe_mc_filter_apply */ | ||||
static void | static void | ||||
ixgbe_if_multi_set(if_ctx_t ctx) | ixgbe_if_multi_set(if_ctx_t ctx) | ||||
{ | { | ||||
struct adapter *adapter = iflib_get_softc(ctx); | struct ixgbe_softc *sc = iflib_get_softc(ctx); | ||||
struct ixgbe_mc_addr *mta; | struct ixgbe_mc_addr *mta; | ||||
struct ifnet *ifp = iflib_get_ifp(ctx); | struct ifnet *ifp = iflib_get_ifp(ctx); | ||||
u8 *update_ptr; | u8 *update_ptr; | ||||
u32 fctrl; | u32 fctrl; | ||||
u_int mcnt; | u_int mcnt; | ||||
IOCTL_DEBUGOUT("ixgbe_if_multi_set: begin"); | IOCTL_DEBUGOUT("ixgbe_if_multi_set: begin"); | ||||
mta = adapter->mta; | mta = sc->mta; | ||||
bzero(mta, sizeof(*mta) * MAX_NUM_MULTICAST_ADDRESSES); | bzero(mta, sizeof(*mta) * MAX_NUM_MULTICAST_ADDRESSES); | ||||
mcnt = if_foreach_llmaddr(iflib_get_ifp(ctx), ixgbe_mc_filter_apply, | mcnt = if_foreach_llmaddr(iflib_get_ifp(ctx), ixgbe_mc_filter_apply, sc); | ||||
adapter); | |||||
fctrl = IXGBE_READ_REG(&adapter->hw, IXGBE_FCTRL); | fctrl = IXGBE_READ_REG(&sc->hw, IXGBE_FCTRL); | ||||
if (ifp->if_flags & IFF_PROMISC) | if (ifp->if_flags & IFF_PROMISC) | ||||
fctrl |= (IXGBE_FCTRL_UPE | IXGBE_FCTRL_MPE); | fctrl |= (IXGBE_FCTRL_UPE | IXGBE_FCTRL_MPE); | ||||
else if (mcnt >= MAX_NUM_MULTICAST_ADDRESSES || | else if (mcnt >= MAX_NUM_MULTICAST_ADDRESSES || | ||||
ifp->if_flags & IFF_ALLMULTI) { | ifp->if_flags & IFF_ALLMULTI) { | ||||
fctrl |= IXGBE_FCTRL_MPE; | fctrl |= IXGBE_FCTRL_MPE; | ||||
fctrl &= ~IXGBE_FCTRL_UPE; | fctrl &= ~IXGBE_FCTRL_UPE; | ||||
} else | } else | ||||
fctrl &= ~(IXGBE_FCTRL_UPE | IXGBE_FCTRL_MPE); | fctrl &= ~(IXGBE_FCTRL_UPE | IXGBE_FCTRL_MPE); | ||||
IXGBE_WRITE_REG(&adapter->hw, IXGBE_FCTRL, fctrl); | IXGBE_WRITE_REG(&sc->hw, IXGBE_FCTRL, fctrl); | ||||
if (mcnt < MAX_NUM_MULTICAST_ADDRESSES) { | if (mcnt < MAX_NUM_MULTICAST_ADDRESSES) { | ||||
update_ptr = (u8 *)mta; | update_ptr = (u8 *)mta; | ||||
ixgbe_update_mc_addr_list(&adapter->hw, update_ptr, mcnt, | ixgbe_update_mc_addr_list(&sc->hw, update_ptr, mcnt, | ||||
ixgbe_mc_array_itr, true); | ixgbe_mc_array_itr, true); | ||||
} | } | ||||
} /* ixgbe_if_multi_set */ | } /* ixgbe_if_multi_set */ | ||||
/************************************************************************ | /************************************************************************ | ||||
* ixgbe_mc_array_itr | * ixgbe_mc_array_itr | ||||
* | * | ||||
Show All 18 Lines | |||||
* ixgbe_local_timer - Timer routine | * ixgbe_local_timer - Timer routine | ||||
* | * | ||||
* Checks for link status, updates statistics, | * Checks for link status, updates statistics, | ||||
* and runs the watchdog check. | * and runs the watchdog check. | ||||
************************************************************************/ | ************************************************************************/ | ||||
static void | static void | ||||
ixgbe_if_timer(if_ctx_t ctx, uint16_t qid) | ixgbe_if_timer(if_ctx_t ctx, uint16_t qid) | ||||
{ | { | ||||
struct adapter *adapter = iflib_get_softc(ctx); | struct ixgbe_softc *sc = iflib_get_softc(ctx); | ||||
if (qid != 0) | if (qid != 0) | ||||
return; | return; | ||||
/* Check for pluggable optics */ | /* Check for pluggable optics */ | ||||
if (adapter->sfp_probe) | if (sc->sfp_probe) | ||||
if (!ixgbe_sfp_probe(ctx)) | if (!ixgbe_sfp_probe(ctx)) | ||||
return; /* Nothing to do */ | return; /* Nothing to do */ | ||||
ixgbe_check_link(&adapter->hw, &adapter->link_speed, | ixgbe_check_link(&sc->hw, &sc->link_speed, &sc->link_up, 0); | ||||
&adapter->link_up, 0); | |||||
/* Fire off the adminq task */ | /* Fire off the adminq task */ | ||||
iflib_admin_intr_deferred(ctx); | iflib_admin_intr_deferred(ctx); | ||||
} /* ixgbe_if_timer */ | } /* ixgbe_if_timer */ | ||||
/************************************************************************ | /************************************************************************ | ||||
* ixgbe_sfp_probe | * ixgbe_sfp_probe | ||||
* | * | ||||
* Determine if a port had optics inserted. | * Determine if a port had optics inserted. | ||||
************************************************************************/ | ************************************************************************/ | ||||
static bool | static bool | ||||
ixgbe_sfp_probe(if_ctx_t ctx) | ixgbe_sfp_probe(if_ctx_t ctx) | ||||
{ | { | ||||
struct adapter *adapter = iflib_get_softc(ctx); | struct ixgbe_softc *sc = iflib_get_softc(ctx); | ||||
struct ixgbe_hw *hw = &adapter->hw; | struct ixgbe_hw *hw = &sc->hw; | ||||
device_t dev = iflib_get_dev(ctx); | device_t dev = iflib_get_dev(ctx); | ||||
bool result = false; | bool result = false; | ||||
if ((hw->phy.type == ixgbe_phy_nl) && | if ((hw->phy.type == ixgbe_phy_nl) && | ||||
(hw->phy.sfp_type == ixgbe_sfp_type_not_present)) { | (hw->phy.sfp_type == ixgbe_sfp_type_not_present)) { | ||||
s32 ret = hw->phy.ops.identify_sfp(hw); | s32 ret = hw->phy.ops.identify_sfp(hw); | ||||
if (ret) | if (ret) | ||||
goto out; | goto out; | ||||
ret = hw->phy.ops.reset(hw); | ret = hw->phy.ops.reset(hw); | ||||
adapter->sfp_probe = false; | sc->sfp_probe = false; | ||||
if (ret == IXGBE_ERR_SFP_NOT_SUPPORTED) { | if (ret == IXGBE_ERR_SFP_NOT_SUPPORTED) { | ||||
device_printf(dev, "Unsupported SFP+ module detected!"); | device_printf(dev, "Unsupported SFP+ module detected!"); | ||||
device_printf(dev, | device_printf(dev, | ||||
"Reload driver with supported module.\n"); | "Reload driver with supported module.\n"); | ||||
goto out; | goto out; | ||||
} else | } else | ||||
device_printf(dev, "SFP+ module detected!\n"); | device_printf(dev, "SFP+ module detected!\n"); | ||||
/* We now have supported optics */ | /* We now have supported optics */ | ||||
result = true; | result = true; | ||||
} | } | ||||
out: | out: | ||||
return (result); | return (result); | ||||
} /* ixgbe_sfp_probe */ | } /* ixgbe_sfp_probe */ | ||||
/************************************************************************ | /************************************************************************ | ||||
* ixgbe_handle_mod - Tasklet for SFP module interrupts | * ixgbe_handle_mod - Tasklet for SFP module interrupts | ||||
************************************************************************/ | ************************************************************************/ | ||||
static void | static void | ||||
ixgbe_handle_mod(void *context) | ixgbe_handle_mod(void *context) | ||||
{ | { | ||||
if_ctx_t ctx = context; | if_ctx_t ctx = context; | ||||
struct adapter *adapter = iflib_get_softc(ctx); | struct ixgbe_softc *sc = iflib_get_softc(ctx); | ||||
struct ixgbe_hw *hw = &adapter->hw; | struct ixgbe_hw *hw = &sc->hw; | ||||
device_t dev = iflib_get_dev(ctx); | device_t dev = iflib_get_dev(ctx); | ||||
u32 err, cage_full = 0; | u32 err, cage_full = 0; | ||||
if (adapter->hw.need_crosstalk_fix) { | if (sc->hw.need_crosstalk_fix) { | ||||
switch (hw->mac.type) { | switch (hw->mac.type) { | ||||
case ixgbe_mac_82599EB: | case ixgbe_mac_82599EB: | ||||
cage_full = IXGBE_READ_REG(hw, IXGBE_ESDP) & | cage_full = IXGBE_READ_REG(hw, IXGBE_ESDP) & | ||||
IXGBE_ESDP_SDP2; | IXGBE_ESDP_SDP2; | ||||
break; | break; | ||||
case ixgbe_mac_X550EM_x: | case ixgbe_mac_X550EM_x: | ||||
case ixgbe_mac_X550EM_a: | case ixgbe_mac_X550EM_a: | ||||
cage_full = IXGBE_READ_REG(hw, IXGBE_ESDP) & | cage_full = IXGBE_READ_REG(hw, IXGBE_ESDP) & | ||||
Show All 19 Lines | ixgbe_handle_mod(void *context) | ||||
else | else | ||||
err = hw->mac.ops.setup_sfp(hw); | err = hw->mac.ops.setup_sfp(hw); | ||||
if (err == IXGBE_ERR_SFP_NOT_SUPPORTED) { | if (err == IXGBE_ERR_SFP_NOT_SUPPORTED) { | ||||
device_printf(dev, | device_printf(dev, | ||||
"Setup failure - unsupported SFP+ module type.\n"); | "Setup failure - unsupported SFP+ module type.\n"); | ||||
goto handle_mod_out; | goto handle_mod_out; | ||||
} | } | ||||
adapter->task_requests |= IXGBE_REQUEST_TASK_MSF; | sc->task_requests |= IXGBE_REQUEST_TASK_MSF; | ||||
return; | return; | ||||
handle_mod_out: | handle_mod_out: | ||||
adapter->task_requests &= ~(IXGBE_REQUEST_TASK_MSF); | sc->task_requests &= ~(IXGBE_REQUEST_TASK_MSF); | ||||
} /* ixgbe_handle_mod */ | } /* ixgbe_handle_mod */ | ||||
/************************************************************************ | /************************************************************************ | ||||
* ixgbe_handle_msf - Tasklet for MSF (multispeed fiber) interrupts | * ixgbe_handle_msf - Tasklet for MSF (multispeed fiber) interrupts | ||||
************************************************************************/ | ************************************************************************/ | ||||
static void | static void | ||||
ixgbe_handle_msf(void *context) | ixgbe_handle_msf(void *context) | ||||
{ | { | ||||
if_ctx_t ctx = context; | if_ctx_t ctx = context; | ||||
struct adapter *adapter = iflib_get_softc(ctx); | struct ixgbe_softc *sc = iflib_get_softc(ctx); | ||||
struct ixgbe_hw *hw = &adapter->hw; | struct ixgbe_hw *hw = &sc->hw; | ||||
u32 autoneg; | u32 autoneg; | ||||
bool negotiate; | bool negotiate; | ||||
/* get_supported_phy_layer will call hw->phy.ops.identify_sfp() */ | /* get_supported_phy_layer will call hw->phy.ops.identify_sfp() */ | ||||
adapter->phy_layer = ixgbe_get_supported_physical_layer(hw); | sc->phy_layer = ixgbe_get_supported_physical_layer(hw); | ||||
autoneg = hw->phy.autoneg_advertised; | autoneg = hw->phy.autoneg_advertised; | ||||
if ((!autoneg) && (hw->mac.ops.get_link_capabilities)) | if ((!autoneg) && (hw->mac.ops.get_link_capabilities)) | ||||
hw->mac.ops.get_link_capabilities(hw, &autoneg, &negotiate); | hw->mac.ops.get_link_capabilities(hw, &autoneg, &negotiate); | ||||
if (hw->mac.ops.setup_link) | if (hw->mac.ops.setup_link) | ||||
hw->mac.ops.setup_link(hw, autoneg, true); | hw->mac.ops.setup_link(hw, autoneg, true); | ||||
/* Adjust media types shown in ifconfig */ | /* Adjust media types shown in ifconfig */ | ||||
ifmedia_removeall(adapter->media); | ifmedia_removeall(sc->media); | ||||
ixgbe_add_media_types(adapter->ctx); | ixgbe_add_media_types(sc->ctx); | ||||
ifmedia_set(adapter->media, IFM_ETHER | IFM_AUTO); | ifmedia_set(sc->media, IFM_ETHER | IFM_AUTO); | ||||
} /* ixgbe_handle_msf */ | } /* ixgbe_handle_msf */ | ||||
/************************************************************************ | /************************************************************************ | ||||
* ixgbe_handle_phy - Tasklet for external PHY interrupts | * ixgbe_handle_phy - Tasklet for external PHY interrupts | ||||
************************************************************************/ | ************************************************************************/ | ||||
static void | static void | ||||
ixgbe_handle_phy(void *context) | ixgbe_handle_phy(void *context) | ||||
{ | { | ||||
if_ctx_t ctx = context; | if_ctx_t ctx = context; | ||||
struct adapter *adapter = iflib_get_softc(ctx); | struct ixgbe_softc *sc = iflib_get_softc(ctx); | ||||
struct ixgbe_hw *hw = &adapter->hw; | struct ixgbe_hw *hw = &sc->hw; | ||||
int error; | int error; | ||||
error = hw->phy.ops.handle_lasi(hw); | error = hw->phy.ops.handle_lasi(hw); | ||||
if (error == IXGBE_ERR_OVERTEMP) | if (error == IXGBE_ERR_OVERTEMP) | ||||
device_printf(adapter->dev, "CRITICAL: EXTERNAL PHY OVER TEMP!! PHY will downshift to lower power state!\n"); | device_printf(sc->dev, "CRITICAL: EXTERNAL PHY OVER TEMP!! PHY will downshift to lower power state!\n"); | ||||
else if (error) | else if (error) | ||||
device_printf(adapter->dev, | device_printf(sc->dev, | ||||
"Error handling LASI interrupt: %d\n", error); | "Error handling LASI interrupt: %d\n", error); | ||||
} /* ixgbe_handle_phy */ | } /* ixgbe_handle_phy */ | ||||
/************************************************************************ | /************************************************************************ | ||||
* ixgbe_if_stop - Stop the hardware | * ixgbe_if_stop - Stop the hardware | ||||
* | * | ||||
* Disables all traffic on the adapter by issuing a | * Disables all traffic on the adapter by issuing a | ||||
* global reset on the MAC and deallocates TX/RX buffers. | * global reset on the MAC and deallocates TX/RX buffers. | ||||
************************************************************************/ | ************************************************************************/ | ||||
static void | static void | ||||
ixgbe_if_stop(if_ctx_t ctx) | ixgbe_if_stop(if_ctx_t ctx) | ||||
{ | { | ||||
struct adapter *adapter = iflib_get_softc(ctx); | struct ixgbe_softc *sc = iflib_get_softc(ctx); | ||||
struct ixgbe_hw *hw = &adapter->hw; | struct ixgbe_hw *hw = &sc->hw; | ||||
INIT_DEBUGOUT("ixgbe_if_stop: begin\n"); | INIT_DEBUGOUT("ixgbe_if_stop: begin\n"); | ||||
ixgbe_reset_hw(hw); | ixgbe_reset_hw(hw); | ||||
hw->adapter_stopped = false; | hw->adapter_stopped = false; | ||||
ixgbe_stop_adapter(hw); | ixgbe_stop_adapter(hw); | ||||
if (hw->mac.type == ixgbe_mac_82599EB) | if (hw->mac.type == ixgbe_mac_82599EB) | ||||
ixgbe_stop_mac_link_on_d3_82599(hw); | ixgbe_stop_mac_link_on_d3_82599(hw); | ||||
/* Turn off the laser - noop with no optics */ | /* Turn off the laser - noop with no optics */ | ||||
ixgbe_disable_tx_laser(hw); | ixgbe_disable_tx_laser(hw); | ||||
/* Update the stack */ | /* Update the stack */ | ||||
adapter->link_up = false; | sc->link_up = false; | ||||
ixgbe_if_update_admin_status(ctx); | ixgbe_if_update_admin_status(ctx); | ||||
/* reprogram the RAR[0] in case user changed it. */ | /* reprogram the RAR[0] in case user changed it. */ | ||||
ixgbe_set_rar(&adapter->hw, 0, adapter->hw.mac.addr, 0, IXGBE_RAH_AV); | ixgbe_set_rar(&sc->hw, 0, sc->hw.mac.addr, 0, IXGBE_RAH_AV); | ||||
return; | return; | ||||
} /* ixgbe_if_stop */ | } /* ixgbe_if_stop */ | ||||
/************************************************************************ | /************************************************************************ | ||||
* ixgbe_update_link_status - Update OS on link state | * ixgbe_update_link_status - Update OS on link state | ||||
* | * | ||||
* Note: Only updates the OS on the cached link state. | * Note: Only updates the OS on the cached link state. | ||||
* The real check of the hardware only happens with | * The real check of the hardware only happens with | ||||
* a link interrupt. | * a link interrupt. | ||||
************************************************************************/ | ************************************************************************/ | ||||
static void | static void | ||||
ixgbe_if_update_admin_status(if_ctx_t ctx) | ixgbe_if_update_admin_status(if_ctx_t ctx) | ||||
{ | { | ||||
struct adapter *adapter = iflib_get_softc(ctx); | struct ixgbe_softc *sc = iflib_get_softc(ctx); | ||||
device_t dev = iflib_get_dev(ctx); | device_t dev = iflib_get_dev(ctx); | ||||
if (adapter->link_up) { | if (sc->link_up) { | ||||
if (adapter->link_active == false) { | if (sc->link_active == false) { | ||||
if (bootverbose) | if (bootverbose) | ||||
device_printf(dev, "Link is up %d Gbps %s \n", | device_printf(dev, "Link is up %d Gbps %s \n", | ||||
((adapter->link_speed == 128) ? 10 : 1), | ((sc->link_speed == 128) ? 10 : 1), | ||||
"Full Duplex"); | "Full Duplex"); | ||||
adapter->link_active = true; | sc->link_active = true; | ||||
/* Update any Flow Control changes */ | /* Update any Flow Control changes */ | ||||
ixgbe_fc_enable(&adapter->hw); | ixgbe_fc_enable(&sc->hw); | ||||
/* Update DMA coalescing config */ | /* Update DMA coalescing config */ | ||||
ixgbe_config_dmac(adapter); | ixgbe_config_dmac(sc); | ||||
/* should actually be negotiated value */ | /* should actually be negotiated value */ | ||||
iflib_link_state_change(ctx, LINK_STATE_UP, IF_Gbps(10)); | iflib_link_state_change(ctx, LINK_STATE_UP, IF_Gbps(10)); | ||||
if (adapter->feat_en & IXGBE_FEATURE_SRIOV) | if (sc->feat_en & IXGBE_FEATURE_SRIOV) | ||||
ixgbe_ping_all_vfs(adapter); | ixgbe_ping_all_vfs(sc); | ||||
} | } | ||||
} else { /* Link down */ | } else { /* Link down */ | ||||
if (adapter->link_active == true) { | if (sc->link_active == true) { | ||||
if (bootverbose) | if (bootverbose) | ||||
device_printf(dev, "Link is Down\n"); | device_printf(dev, "Link is Down\n"); | ||||
iflib_link_state_change(ctx, LINK_STATE_DOWN, 0); | iflib_link_state_change(ctx, LINK_STATE_DOWN, 0); | ||||
adapter->link_active = false; | sc->link_active = false; | ||||
if (adapter->feat_en & IXGBE_FEATURE_SRIOV) | if (sc->feat_en & IXGBE_FEATURE_SRIOV) | ||||
ixgbe_ping_all_vfs(adapter); | ixgbe_ping_all_vfs(sc); | ||||
} | } | ||||
} | } | ||||
/* Handle task requests from msix_link() */ | /* Handle task requests from msix_link() */ | ||||
if (adapter->task_requests & IXGBE_REQUEST_TASK_MOD) | if (sc->task_requests & IXGBE_REQUEST_TASK_MOD) | ||||
ixgbe_handle_mod(ctx); | ixgbe_handle_mod(ctx); | ||||
if (adapter->task_requests & IXGBE_REQUEST_TASK_MSF) | if (sc->task_requests & IXGBE_REQUEST_TASK_MSF) | ||||
ixgbe_handle_msf(ctx); | ixgbe_handle_msf(ctx); | ||||
if (adapter->task_requests & IXGBE_REQUEST_TASK_MBX) | if (sc->task_requests & IXGBE_REQUEST_TASK_MBX) | ||||
ixgbe_handle_mbx(ctx); | ixgbe_handle_mbx(ctx); | ||||
if (adapter->task_requests & IXGBE_REQUEST_TASK_FDIR) | if (sc->task_requests & IXGBE_REQUEST_TASK_FDIR) | ||||
ixgbe_reinit_fdir(ctx); | ixgbe_reinit_fdir(ctx); | ||||
if (adapter->task_requests & IXGBE_REQUEST_TASK_PHY) | if (sc->task_requests & IXGBE_REQUEST_TASK_PHY) | ||||
ixgbe_handle_phy(ctx); | ixgbe_handle_phy(ctx); | ||||
adapter->task_requests = 0; | sc->task_requests = 0; | ||||
ixgbe_update_stats_counters(adapter); | ixgbe_update_stats_counters(sc); | ||||
} /* ixgbe_if_update_admin_status */ | } /* ixgbe_if_update_admin_status */ | ||||
/************************************************************************ | /************************************************************************ | ||||
* ixgbe_config_dmac - Configure DMA Coalescing | * ixgbe_config_dmac - Configure DMA Coalescing | ||||
************************************************************************/ | ************************************************************************/ | ||||
static void | static void | ||||
ixgbe_config_dmac(struct adapter *adapter) | ixgbe_config_dmac(struct ixgbe_softc *sc) | ||||
{ | { | ||||
struct ixgbe_hw *hw = &adapter->hw; | struct ixgbe_hw *hw = &sc->hw; | ||||
struct ixgbe_dmac_config *dcfg = &hw->mac.dmac_config; | struct ixgbe_dmac_config *dcfg = &hw->mac.dmac_config; | ||||
if (hw->mac.type < ixgbe_mac_X550 || !hw->mac.ops.dmac_config) | if (hw->mac.type < ixgbe_mac_X550 || !hw->mac.ops.dmac_config) | ||||
return; | return; | ||||
if (dcfg->watchdog_timer ^ adapter->dmac || | if (dcfg->watchdog_timer ^ sc->dmac || | ||||
dcfg->link_speed ^ adapter->link_speed) { | dcfg->link_speed ^ sc->link_speed) { | ||||
dcfg->watchdog_timer = adapter->dmac; | dcfg->watchdog_timer = sc->dmac; | ||||
dcfg->fcoe_en = false; | dcfg->fcoe_en = false; | ||||
dcfg->link_speed = adapter->link_speed; | dcfg->link_speed = sc->link_speed; | ||||
dcfg->num_tcs = 1; | dcfg->num_tcs = 1; | ||||
INIT_DEBUGOUT2("dmac settings: watchdog %d, link speed %d\n", | INIT_DEBUGOUT2("dmac settings: watchdog %d, link speed %d\n", | ||||
dcfg->watchdog_timer, dcfg->link_speed); | dcfg->watchdog_timer, dcfg->link_speed); | ||||
hw->mac.ops.dmac_config(hw); | hw->mac.ops.dmac_config(hw); | ||||
} | } | ||||
} /* ixgbe_config_dmac */ | } /* ixgbe_config_dmac */ | ||||
/************************************************************************ | /************************************************************************ | ||||
* ixgbe_if_enable_intr | * ixgbe_if_enable_intr | ||||
************************************************************************/ | ************************************************************************/ | ||||
void | void | ||||
ixgbe_if_enable_intr(if_ctx_t ctx) | ixgbe_if_enable_intr(if_ctx_t ctx) | ||||
{ | { | ||||
struct adapter *adapter = iflib_get_softc(ctx); | struct ixgbe_softc *sc = iflib_get_softc(ctx); | ||||
struct ixgbe_hw *hw = &adapter->hw; | struct ixgbe_hw *hw = &sc->hw; | ||||
struct ix_rx_queue *que = adapter->rx_queues; | struct ix_rx_queue *que = sc->rx_queues; | ||||
u32 mask, fwsm; | u32 mask, fwsm; | ||||
mask = (IXGBE_EIMS_ENABLE_MASK & ~IXGBE_EIMS_RTX_QUEUE); | mask = (IXGBE_EIMS_ENABLE_MASK & ~IXGBE_EIMS_RTX_QUEUE); | ||||
switch (adapter->hw.mac.type) { | switch (sc->hw.mac.type) { | ||||
case ixgbe_mac_82599EB: | case ixgbe_mac_82599EB: | ||||
mask |= IXGBE_EIMS_ECC; | mask |= IXGBE_EIMS_ECC; | ||||
/* Temperature sensor on some adapters */ | /* Temperature sensor on some scs */ | ||||
mask |= IXGBE_EIMS_GPI_SDP0; | mask |= IXGBE_EIMS_GPI_SDP0; | ||||
/* SFP+ (RX_LOS_N & MOD_ABS_N) */ | /* SFP+ (RX_LOS_N & MOD_ABS_N) */ | ||||
mask |= IXGBE_EIMS_GPI_SDP1; | mask |= IXGBE_EIMS_GPI_SDP1; | ||||
mask |= IXGBE_EIMS_GPI_SDP2; | mask |= IXGBE_EIMS_GPI_SDP2; | ||||
break; | break; | ||||
case ixgbe_mac_X540: | case ixgbe_mac_X540: | ||||
/* Detect if Thermal Sensor is enabled */ | /* Detect if Thermal Sensor is enabled */ | ||||
fwsm = IXGBE_READ_REG(hw, IXGBE_FWSM); | fwsm = IXGBE_READ_REG(hw, IXGBE_FWSM); | ||||
Show All 18 Lines | if (hw->phy.type == ixgbe_phy_x550em_ext_t) | ||||
mask |= IXGBE_EICR_GPI_SDP0_X540; | mask |= IXGBE_EICR_GPI_SDP0_X540; | ||||
mask |= IXGBE_EIMS_ECC; | mask |= IXGBE_EIMS_ECC; | ||||
break; | break; | ||||
default: | default: | ||||
break; | break; | ||||
} | } | ||||
/* Enable Fan Failure detection */ | /* Enable Fan Failure detection */ | ||||
if (adapter->feat_en & IXGBE_FEATURE_FAN_FAIL) | if (sc->feat_en & IXGBE_FEATURE_FAN_FAIL) | ||||
mask |= IXGBE_EIMS_GPI_SDP1; | mask |= IXGBE_EIMS_GPI_SDP1; | ||||
/* Enable SR-IOV */ | /* Enable SR-IOV */ | ||||
if (adapter->feat_en & IXGBE_FEATURE_SRIOV) | if (sc->feat_en & IXGBE_FEATURE_SRIOV) | ||||
mask |= IXGBE_EIMS_MAILBOX; | mask |= IXGBE_EIMS_MAILBOX; | ||||
/* Enable Flow Director */ | /* Enable Flow Director */ | ||||
if (adapter->feat_en & IXGBE_FEATURE_FDIR) | if (sc->feat_en & IXGBE_FEATURE_FDIR) | ||||
mask |= IXGBE_EIMS_FLOW_DIR; | mask |= IXGBE_EIMS_FLOW_DIR; | ||||
IXGBE_WRITE_REG(hw, IXGBE_EIMS, mask); | IXGBE_WRITE_REG(hw, IXGBE_EIMS, mask); | ||||
/* With MSI-X we use auto clear */ | /* With MSI-X we use auto clear */ | ||||
if (adapter->intr_type == IFLIB_INTR_MSIX) { | if (sc->intr_type == IFLIB_INTR_MSIX) { | ||||
mask = IXGBE_EIMS_ENABLE_MASK; | mask = IXGBE_EIMS_ENABLE_MASK; | ||||
/* Don't autoclear Link */ | /* Don't autoclear Link */ | ||||
mask &= ~IXGBE_EIMS_OTHER; | mask &= ~IXGBE_EIMS_OTHER; | ||||
mask &= ~IXGBE_EIMS_LSC; | mask &= ~IXGBE_EIMS_LSC; | ||||
if (adapter->feat_cap & IXGBE_FEATURE_SRIOV) | if (sc->feat_cap & IXGBE_FEATURE_SRIOV) | ||||
mask &= ~IXGBE_EIMS_MAILBOX; | mask &= ~IXGBE_EIMS_MAILBOX; | ||||
IXGBE_WRITE_REG(hw, IXGBE_EIAC, mask); | IXGBE_WRITE_REG(hw, IXGBE_EIAC, mask); | ||||
} | } | ||||
/* | /* | ||||
* Now enable all queues, this is done separately to | * Now enable all queues, this is done separately to | ||||
* allow for handling the extended (beyond 32) MSI-X | * allow for handling the extended (beyond 32) MSI-X | ||||
* vectors that can be used by 82599 | * vectors that can be used by 82599 | ||||
*/ | */ | ||||
for (int i = 0; i < adapter->num_rx_queues; i++, que++) | for (int i = 0; i < sc->num_rx_queues; i++, que++) | ||||
ixgbe_enable_queue(adapter, que->msix); | ixgbe_enable_queue(sc, que->msix); | ||||
IXGBE_WRITE_FLUSH(hw); | IXGBE_WRITE_FLUSH(hw); | ||||
} /* ixgbe_if_enable_intr */ | } /* ixgbe_if_enable_intr */ | ||||
/************************************************************************ | /************************************************************************ | ||||
* ixgbe_disable_intr | * ixgbe_disable_intr | ||||
************************************************************************/ | ************************************************************************/ | ||||
static void | static void | ||||
ixgbe_if_disable_intr(if_ctx_t ctx) | ixgbe_if_disable_intr(if_ctx_t ctx) | ||||
{ | { | ||||
struct adapter *adapter = iflib_get_softc(ctx); | struct ixgbe_softc *sc = iflib_get_softc(ctx); | ||||
if (adapter->intr_type == IFLIB_INTR_MSIX) | if (sc->intr_type == IFLIB_INTR_MSIX) | ||||
IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIAC, 0); | IXGBE_WRITE_REG(&sc->hw, IXGBE_EIAC, 0); | ||||
if (adapter->hw.mac.type == ixgbe_mac_82598EB) { | if (sc->hw.mac.type == ixgbe_mac_82598EB) { | ||||
IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC, ~0); | IXGBE_WRITE_REG(&sc->hw, IXGBE_EIMC, ~0); | ||||
} else { | } else { | ||||
IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC, 0xFFFF0000); | IXGBE_WRITE_REG(&sc->hw, IXGBE_EIMC, 0xFFFF0000); | ||||
IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC_EX(0), ~0); | IXGBE_WRITE_REG(&sc->hw, IXGBE_EIMC_EX(0), ~0); | ||||
IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC_EX(1), ~0); | IXGBE_WRITE_REG(&sc->hw, IXGBE_EIMC_EX(1), ~0); | ||||
} | } | ||||
IXGBE_WRITE_FLUSH(&adapter->hw); | IXGBE_WRITE_FLUSH(&sc->hw); | ||||
} /* ixgbe_if_disable_intr */ | } /* ixgbe_if_disable_intr */ | ||||
/************************************************************************ | /************************************************************************ | ||||
* ixgbe_link_intr_enable | * ixgbe_link_intr_enable | ||||
************************************************************************/ | ************************************************************************/ | ||||
static void | static void | ||||
ixgbe_link_intr_enable(if_ctx_t ctx) | ixgbe_link_intr_enable(if_ctx_t ctx) | ||||
{ | { | ||||
struct ixgbe_hw *hw = &((struct adapter *)iflib_get_softc(ctx))->hw; | struct ixgbe_hw *hw = &((struct ixgbe_softc *)iflib_get_softc(ctx))->hw; | ||||
/* Re-enable other interrupts */ | /* Re-enable other interrupts */ | ||||
IXGBE_WRITE_REG(hw, IXGBE_EIMS, IXGBE_EIMS_OTHER | IXGBE_EIMS_LSC); | IXGBE_WRITE_REG(hw, IXGBE_EIMS, IXGBE_EIMS_OTHER | IXGBE_EIMS_LSC); | ||||
} /* ixgbe_link_intr_enable */ | } /* ixgbe_link_intr_enable */ | ||||
/************************************************************************ | /************************************************************************ | ||||
* ixgbe_if_rx_queue_intr_enable | * ixgbe_if_rx_queue_intr_enable | ||||
************************************************************************/ | ************************************************************************/ | ||||
static int | static int | ||||
ixgbe_if_rx_queue_intr_enable(if_ctx_t ctx, uint16_t rxqid) | ixgbe_if_rx_queue_intr_enable(if_ctx_t ctx, uint16_t rxqid) | ||||
{ | { | ||||
struct adapter *adapter = iflib_get_softc(ctx); | struct ixgbe_softc *sc = iflib_get_softc(ctx); | ||||
struct ix_rx_queue *que = &adapter->rx_queues[rxqid]; | struct ix_rx_queue *que = &sc->rx_queues[rxqid]; | ||||
ixgbe_enable_queue(adapter, que->msix); | ixgbe_enable_queue(sc, que->msix); | ||||
return (0); | return (0); | ||||
} /* ixgbe_if_rx_queue_intr_enable */ | } /* ixgbe_if_rx_queue_intr_enable */ | ||||
/************************************************************************ | /************************************************************************ | ||||
* ixgbe_enable_queue | * ixgbe_enable_queue | ||||
************************************************************************/ | ************************************************************************/ | ||||
static void | static void | ||||
ixgbe_enable_queue(struct adapter *adapter, u32 vector) | ixgbe_enable_queue(struct ixgbe_softc *sc, u32 vector) | ||||
{ | { | ||||
struct ixgbe_hw *hw = &adapter->hw; | struct ixgbe_hw *hw = &sc->hw; | ||||
u64 queue = 1ULL << vector; | u64 queue = 1ULL << vector; | ||||
u32 mask; | u32 mask; | ||||
if (hw->mac.type == ixgbe_mac_82598EB) { | if (hw->mac.type == ixgbe_mac_82598EB) { | ||||
mask = (IXGBE_EIMS_RTX_QUEUE & queue); | mask = (IXGBE_EIMS_RTX_QUEUE & queue); | ||||
IXGBE_WRITE_REG(hw, IXGBE_EIMS, mask); | IXGBE_WRITE_REG(hw, IXGBE_EIMS, mask); | ||||
} else { | } else { | ||||
mask = (queue & 0xFFFFFFFF); | mask = (queue & 0xFFFFFFFF); | ||||
if (mask) | if (mask) | ||||
IXGBE_WRITE_REG(hw, IXGBE_EIMS_EX(0), mask); | IXGBE_WRITE_REG(hw, IXGBE_EIMS_EX(0), mask); | ||||
mask = (queue >> 32); | mask = (queue >> 32); | ||||
if (mask) | if (mask) | ||||
IXGBE_WRITE_REG(hw, IXGBE_EIMS_EX(1), mask); | IXGBE_WRITE_REG(hw, IXGBE_EIMS_EX(1), mask); | ||||
} | } | ||||
} /* ixgbe_enable_queue */ | } /* ixgbe_enable_queue */ | ||||
/************************************************************************ | /************************************************************************ | ||||
* ixgbe_disable_queue | * ixgbe_disable_queue | ||||
************************************************************************/ | ************************************************************************/ | ||||
static void | static void | ||||
ixgbe_disable_queue(struct adapter *adapter, u32 vector) | ixgbe_disable_queue(struct ixgbe_softc *sc, u32 vector) | ||||
{ | { | ||||
struct ixgbe_hw *hw = &adapter->hw; | struct ixgbe_hw *hw = &sc->hw; | ||||
u64 queue = 1ULL << vector; | u64 queue = 1ULL << vector; | ||||
u32 mask; | u32 mask; | ||||
if (hw->mac.type == ixgbe_mac_82598EB) { | if (hw->mac.type == ixgbe_mac_82598EB) { | ||||
mask = (IXGBE_EIMS_RTX_QUEUE & queue); | mask = (IXGBE_EIMS_RTX_QUEUE & queue); | ||||
IXGBE_WRITE_REG(hw, IXGBE_EIMC, mask); | IXGBE_WRITE_REG(hw, IXGBE_EIMC, mask); | ||||
} else { | } else { | ||||
mask = (queue & 0xFFFFFFFF); | mask = (queue & 0xFFFFFFFF); | ||||
if (mask) | if (mask) | ||||
IXGBE_WRITE_REG(hw, IXGBE_EIMC_EX(0), mask); | IXGBE_WRITE_REG(hw, IXGBE_EIMC_EX(0), mask); | ||||
mask = (queue >> 32); | mask = (queue >> 32); | ||||
if (mask) | if (mask) | ||||
IXGBE_WRITE_REG(hw, IXGBE_EIMC_EX(1), mask); | IXGBE_WRITE_REG(hw, IXGBE_EIMC_EX(1), mask); | ||||
} | } | ||||
} /* ixgbe_disable_queue */ | } /* ixgbe_disable_queue */ | ||||
/************************************************************************ | /************************************************************************ | ||||
* ixgbe_intr - Legacy Interrupt Service Routine | * ixgbe_intr - Legacy Interrupt Service Routine | ||||
************************************************************************/ | ************************************************************************/ | ||||
int | int | ||||
ixgbe_intr(void *arg) | ixgbe_intr(void *arg) | ||||
{ | { | ||||
struct adapter *adapter = arg; | struct ixgbe_softc *sc = arg; | ||||
struct ix_rx_queue *que = adapter->rx_queues; | struct ix_rx_queue *que = sc->rx_queues; | ||||
struct ixgbe_hw *hw = &adapter->hw; | struct ixgbe_hw *hw = &sc->hw; | ||||
if_ctx_t ctx = adapter->ctx; | if_ctx_t ctx = sc->ctx; | ||||
u32 eicr, eicr_mask; | u32 eicr, eicr_mask; | ||||
eicr = IXGBE_READ_REG(hw, IXGBE_EICR); | eicr = IXGBE_READ_REG(hw, IXGBE_EICR); | ||||
++que->irqs; | ++que->irqs; | ||||
if (eicr == 0) { | if (eicr == 0) { | ||||
ixgbe_if_enable_intr(ctx); | ixgbe_if_enable_intr(ctx); | ||||
return (FILTER_HANDLED); | return (FILTER_HANDLED); | ||||
} | } | ||||
/* Check for fan failure */ | /* Check for fan failure */ | ||||
if ((hw->device_id == IXGBE_DEV_ID_82598AT) && | if ((hw->device_id == IXGBE_DEV_ID_82598AT) && | ||||
(eicr & IXGBE_EICR_GPI_SDP1)) { | (eicr & IXGBE_EICR_GPI_SDP1)) { | ||||
device_printf(adapter->dev, | device_printf(sc->dev, | ||||
"\nCRITICAL: FAN FAILURE!! REPLACE IMMEDIATELY!!\n"); | "\nCRITICAL: FAN FAILURE!! REPLACE IMMEDIATELY!!\n"); | ||||
IXGBE_WRITE_REG(hw, IXGBE_EIMS, IXGBE_EICR_GPI_SDP1_BY_MAC(hw)); | IXGBE_WRITE_REG(hw, IXGBE_EIMS, IXGBE_EICR_GPI_SDP1_BY_MAC(hw)); | ||||
} | } | ||||
/* Link status change */ | /* Link status change */ | ||||
if (eicr & IXGBE_EICR_LSC) { | if (eicr & IXGBE_EICR_LSC) { | ||||
IXGBE_WRITE_REG(hw, IXGBE_EIMC, IXGBE_EIMC_LSC); | IXGBE_WRITE_REG(hw, IXGBE_EIMC, IXGBE_EIMC_LSC); | ||||
iflib_admin_intr_deferred(ctx); | iflib_admin_intr_deferred(ctx); | ||||
} | } | ||||
if (ixgbe_is_sfp(hw)) { | if (ixgbe_is_sfp(hw)) { | ||||
/* Pluggable optics-related interrupt */ | /* Pluggable optics-related interrupt */ | ||||
if (hw->mac.type >= ixgbe_mac_X540) | if (hw->mac.type >= ixgbe_mac_X540) | ||||
eicr_mask = IXGBE_EICR_GPI_SDP0_X540; | eicr_mask = IXGBE_EICR_GPI_SDP0_X540; | ||||
else | else | ||||
eicr_mask = IXGBE_EICR_GPI_SDP2_BY_MAC(hw); | eicr_mask = IXGBE_EICR_GPI_SDP2_BY_MAC(hw); | ||||
if (eicr & eicr_mask) { | if (eicr & eicr_mask) { | ||||
IXGBE_WRITE_REG(hw, IXGBE_EICR, eicr_mask); | IXGBE_WRITE_REG(hw, IXGBE_EICR, eicr_mask); | ||||
adapter->task_requests |= IXGBE_REQUEST_TASK_MOD; | sc->task_requests |= IXGBE_REQUEST_TASK_MOD; | ||||
} | } | ||||
if ((hw->mac.type == ixgbe_mac_82599EB) && | if ((hw->mac.type == ixgbe_mac_82599EB) && | ||||
(eicr & IXGBE_EICR_GPI_SDP1_BY_MAC(hw))) { | (eicr & IXGBE_EICR_GPI_SDP1_BY_MAC(hw))) { | ||||
IXGBE_WRITE_REG(hw, IXGBE_EICR, | IXGBE_WRITE_REG(hw, IXGBE_EICR, | ||||
IXGBE_EICR_GPI_SDP1_BY_MAC(hw)); | IXGBE_EICR_GPI_SDP1_BY_MAC(hw)); | ||||
adapter->task_requests |= IXGBE_REQUEST_TASK_MSF; | sc->task_requests |= IXGBE_REQUEST_TASK_MSF; | ||||
} | } | ||||
} | } | ||||
/* External PHY interrupt */ | /* External PHY interrupt */ | ||||
if ((hw->phy.type == ixgbe_phy_x550em_ext_t) && | if ((hw->phy.type == ixgbe_phy_x550em_ext_t) && | ||||
(eicr & IXGBE_EICR_GPI_SDP0_X540)) | (eicr & IXGBE_EICR_GPI_SDP0_X540)) | ||||
adapter->task_requests |= IXGBE_REQUEST_TASK_PHY; | sc->task_requests |= IXGBE_REQUEST_TASK_PHY; | ||||
return (FILTER_SCHEDULE_THREAD); | return (FILTER_SCHEDULE_THREAD); | ||||
} /* ixgbe_intr */ | } /* ixgbe_intr */ | ||||
/************************************************************************ | /************************************************************************ | ||||
* ixgbe_free_pci_resources | * ixgbe_free_pci_resources | ||||
************************************************************************/ | ************************************************************************/ | ||||
static void | static void | ||||
ixgbe_free_pci_resources(if_ctx_t ctx) | ixgbe_free_pci_resources(if_ctx_t ctx) | ||||
{ | { | ||||
struct adapter *adapter = iflib_get_softc(ctx); | struct ixgbe_softc *sc = iflib_get_softc(ctx); | ||||
struct ix_rx_queue *que = adapter->rx_queues; | struct ix_rx_queue *que = sc->rx_queues; | ||||
device_t dev = iflib_get_dev(ctx); | device_t dev = iflib_get_dev(ctx); | ||||
/* Release all MSI-X queue resources */ | /* Release all MSI-X queue resources */ | ||||
if (adapter->intr_type == IFLIB_INTR_MSIX) | if (sc->intr_type == IFLIB_INTR_MSIX) | ||||
iflib_irq_free(ctx, &adapter->irq); | iflib_irq_free(ctx, &sc->irq); | ||||
if (que != NULL) { | if (que != NULL) { | ||||
for (int i = 0; i < adapter->num_rx_queues; i++, que++) { | for (int i = 0; i < sc->num_rx_queues; i++, que++) { | ||||
iflib_irq_free(ctx, &que->que_irq); | iflib_irq_free(ctx, &que->que_irq); | ||||
} | } | ||||
} | } | ||||
if (adapter->pci_mem != NULL) | if (sc->pci_mem != NULL) | ||||
bus_release_resource(dev, SYS_RES_MEMORY, | bus_release_resource(dev, SYS_RES_MEMORY, | ||||
rman_get_rid(adapter->pci_mem), adapter->pci_mem); | rman_get_rid(sc->pci_mem), sc->pci_mem); | ||||
} /* ixgbe_free_pci_resources */ | } /* ixgbe_free_pci_resources */ | ||||
/************************************************************************ | /************************************************************************ | ||||
* ixgbe_sysctl_flowcntl | * ixgbe_sysctl_flowcntl | ||||
* | * | ||||
* SYSCTL wrapper around setting Flow Control | * SYSCTL wrapper around setting Flow Control | ||||
************************************************************************/ | ************************************************************************/ | ||||
static int | static int | ||||
ixgbe_sysctl_flowcntl(SYSCTL_HANDLER_ARGS) | ixgbe_sysctl_flowcntl(SYSCTL_HANDLER_ARGS) | ||||
{ | { | ||||
struct adapter *adapter; | struct ixgbe_softc *sc; | ||||
int error, fc; | int error, fc; | ||||
adapter = (struct adapter *)arg1; | sc = (struct ixgbe_softc *)arg1; | ||||
fc = adapter->hw.fc.current_mode; | fc = sc->hw.fc.current_mode; | ||||
error = sysctl_handle_int(oidp, &fc, 0, req); | error = sysctl_handle_int(oidp, &fc, 0, req); | ||||
if ((error) || (req->newptr == NULL)) | if ((error) || (req->newptr == NULL)) | ||||
return (error); | return (error); | ||||
/* Don't bother if it's not changed */ | /* Don't bother if it's not changed */ | ||||
if (fc == adapter->hw.fc.current_mode) | if (fc == sc->hw.fc.current_mode) | ||||
return (0); | return (0); | ||||
return ixgbe_set_flowcntl(adapter, fc); | return ixgbe_set_flowcntl(sc, fc); | ||||
} /* ixgbe_sysctl_flowcntl */ | } /* ixgbe_sysctl_flowcntl */ | ||||
/************************************************************************ | /************************************************************************ | ||||
* ixgbe_set_flowcntl - Set flow control | * ixgbe_set_flowcntl - Set flow control | ||||
* | * | ||||
* Flow control values: | * Flow control values: | ||||
* 0 - off | * 0 - off | ||||
* 1 - rx pause | * 1 - rx pause | ||||
* 2 - tx pause | * 2 - tx pause | ||||
* 3 - full | * 3 - full | ||||
************************************************************************/ | ************************************************************************/ | ||||
static int | static int | ||||
ixgbe_set_flowcntl(struct adapter *adapter, int fc) | ixgbe_set_flowcntl(struct ixgbe_softc *sc, int fc) | ||||
{ | { | ||||
switch (fc) { | switch (fc) { | ||||
case ixgbe_fc_rx_pause: | case ixgbe_fc_rx_pause: | ||||
case ixgbe_fc_tx_pause: | case ixgbe_fc_tx_pause: | ||||
case ixgbe_fc_full: | case ixgbe_fc_full: | ||||
adapter->hw.fc.requested_mode = fc; | sc->hw.fc.requested_mode = fc; | ||||
if (adapter->num_rx_queues > 1) | if (sc->num_rx_queues > 1) | ||||
ixgbe_disable_rx_drop(adapter); | ixgbe_disable_rx_drop(sc); | ||||
break; | break; | ||||
case ixgbe_fc_none: | case ixgbe_fc_none: | ||||
adapter->hw.fc.requested_mode = ixgbe_fc_none; | sc->hw.fc.requested_mode = ixgbe_fc_none; | ||||
if (adapter->num_rx_queues > 1) | if (sc->num_rx_queues > 1) | ||||
ixgbe_enable_rx_drop(adapter); | ixgbe_enable_rx_drop(sc); | ||||
break; | break; | ||||
default: | default: | ||||
return (EINVAL); | return (EINVAL); | ||||
} | } | ||||
/* Don't autoneg if forcing a value */ | /* Don't autoneg if forcing a value */ | ||||
adapter->hw.fc.disable_fc_autoneg = true; | sc->hw.fc.disable_fc_autoneg = true; | ||||
ixgbe_fc_enable(&adapter->hw); | ixgbe_fc_enable(&sc->hw); | ||||
return (0); | return (0); | ||||
} /* ixgbe_set_flowcntl */ | } /* ixgbe_set_flowcntl */ | ||||
/************************************************************************ | /************************************************************************ | ||||
* ixgbe_enable_rx_drop | * ixgbe_enable_rx_drop | ||||
* | * | ||||
* Enable the hardware to drop packets when the buffer is | * Enable the hardware to drop packets when the buffer is | ||||
* full. This is useful with multiqueue, so that no single | * full. This is useful with multiqueue, so that no single | ||||
* queue being full stalls the entire RX engine. We only | * queue being full stalls the entire RX engine. We only | ||||
* enable this when Multiqueue is enabled AND Flow Control | * enable this when Multiqueue is enabled AND Flow Control | ||||
* is disabled. | * is disabled. | ||||
************************************************************************/ | ************************************************************************/ | ||||
static void | static void | ||||
ixgbe_enable_rx_drop(struct adapter *adapter) | ixgbe_enable_rx_drop(struct ixgbe_softc *sc) | ||||
{ | { | ||||
struct ixgbe_hw *hw = &adapter->hw; | struct ixgbe_hw *hw = &sc->hw; | ||||
struct rx_ring *rxr; | struct rx_ring *rxr; | ||||
u32 srrctl; | u32 srrctl; | ||||
for (int i = 0; i < adapter->num_rx_queues; i++) { | for (int i = 0; i < sc->num_rx_queues; i++) { | ||||
rxr = &adapter->rx_queues[i].rxr; | rxr = &sc->rx_queues[i].rxr; | ||||
srrctl = IXGBE_READ_REG(hw, IXGBE_SRRCTL(rxr->me)); | srrctl = IXGBE_READ_REG(hw, IXGBE_SRRCTL(rxr->me)); | ||||
srrctl |= IXGBE_SRRCTL_DROP_EN; | srrctl |= IXGBE_SRRCTL_DROP_EN; | ||||
IXGBE_WRITE_REG(hw, IXGBE_SRRCTL(rxr->me), srrctl); | IXGBE_WRITE_REG(hw, IXGBE_SRRCTL(rxr->me), srrctl); | ||||
} | } | ||||
/* enable drop for each vf */ | /* enable drop for each vf */ | ||||
for (int i = 0; i < adapter->num_vfs; i++) { | for (int i = 0; i < sc->num_vfs; i++) { | ||||
IXGBE_WRITE_REG(hw, IXGBE_QDE, | IXGBE_WRITE_REG(hw, IXGBE_QDE, | ||||
(IXGBE_QDE_WRITE | (i << IXGBE_QDE_IDX_SHIFT) | | (IXGBE_QDE_WRITE | (i << IXGBE_QDE_IDX_SHIFT) | | ||||
IXGBE_QDE_ENABLE)); | IXGBE_QDE_ENABLE)); | ||||
} | } | ||||
} /* ixgbe_enable_rx_drop */ | } /* ixgbe_enable_rx_drop */ | ||||
/************************************************************************ | /************************************************************************ | ||||
* ixgbe_disable_rx_drop | * ixgbe_disable_rx_drop | ||||
************************************************************************/ | ************************************************************************/ | ||||
static void | static void | ||||
ixgbe_disable_rx_drop(struct adapter *adapter) | ixgbe_disable_rx_drop(struct ixgbe_softc *sc) | ||||
{ | { | ||||
struct ixgbe_hw *hw = &adapter->hw; | struct ixgbe_hw *hw = &sc->hw; | ||||
struct rx_ring *rxr; | struct rx_ring *rxr; | ||||
u32 srrctl; | u32 srrctl; | ||||
for (int i = 0; i < adapter->num_rx_queues; i++) { | for (int i = 0; i < sc->num_rx_queues; i++) { | ||||
rxr = &adapter->rx_queues[i].rxr; | rxr = &sc->rx_queues[i].rxr; | ||||
srrctl = IXGBE_READ_REG(hw, IXGBE_SRRCTL(rxr->me)); | srrctl = IXGBE_READ_REG(hw, IXGBE_SRRCTL(rxr->me)); | ||||
srrctl &= ~IXGBE_SRRCTL_DROP_EN; | srrctl &= ~IXGBE_SRRCTL_DROP_EN; | ||||
IXGBE_WRITE_REG(hw, IXGBE_SRRCTL(rxr->me), srrctl); | IXGBE_WRITE_REG(hw, IXGBE_SRRCTL(rxr->me), srrctl); | ||||
} | } | ||||
/* disable drop for each vf */ | /* disable drop for each vf */ | ||||
for (int i = 0; i < adapter->num_vfs; i++) { | for (int i = 0; i < sc->num_vfs; i++) { | ||||
IXGBE_WRITE_REG(hw, IXGBE_QDE, | IXGBE_WRITE_REG(hw, IXGBE_QDE, | ||||
(IXGBE_QDE_WRITE | (i << IXGBE_QDE_IDX_SHIFT))); | (IXGBE_QDE_WRITE | (i << IXGBE_QDE_IDX_SHIFT))); | ||||
} | } | ||||
} /* ixgbe_disable_rx_drop */ | } /* ixgbe_disable_rx_drop */ | ||||
/************************************************************************ | /************************************************************************ | ||||
* ixgbe_sysctl_advertise | * ixgbe_sysctl_advertise | ||||
* | * | ||||
* SYSCTL wrapper around setting advertised speed | * SYSCTL wrapper around setting advertised speed | ||||
************************************************************************/ | ************************************************************************/ | ||||
static int | static int | ||||
ixgbe_sysctl_advertise(SYSCTL_HANDLER_ARGS) | ixgbe_sysctl_advertise(SYSCTL_HANDLER_ARGS) | ||||
{ | { | ||||
struct adapter *adapter; | struct ixgbe_softc *sc; | ||||
int error, advertise; | int error, advertise; | ||||
adapter = (struct adapter *)arg1; | sc = (struct ixgbe_softc *)arg1; | ||||
advertise = adapter->advertise; | advertise = sc->advertise; | ||||
error = sysctl_handle_int(oidp, &advertise, 0, req); | error = sysctl_handle_int(oidp, &advertise, 0, req); | ||||
if ((error) || (req->newptr == NULL)) | if ((error) || (req->newptr == NULL)) | ||||
return (error); | return (error); | ||||
return ixgbe_set_advertise(adapter, advertise); | return ixgbe_set_advertise(sc, advertise); | ||||
} /* ixgbe_sysctl_advertise */ | } /* ixgbe_sysctl_advertise */ | ||||
/************************************************************************ | /************************************************************************ | ||||
* ixgbe_set_advertise - Control advertised link speed | * ixgbe_set_advertise - Control advertised link speed | ||||
* | * | ||||
* Flags: | * Flags: | ||||
* 0x1 - advertise 100 Mb | * 0x1 - advertise 100 Mb | ||||
* 0x2 - advertise 1G | * 0x2 - advertise 1G | ||||
* 0x4 - advertise 10G | * 0x4 - advertise 10G | ||||
* 0x8 - advertise 10 Mb (yes, Mb) | * 0x8 - advertise 10 Mb (yes, Mb) | ||||
************************************************************************/ | ************************************************************************/ | ||||
static int | static int | ||||
ixgbe_set_advertise(struct adapter *adapter, int advertise) | ixgbe_set_advertise(struct ixgbe_softc *sc, int advertise) | ||||
{ | { | ||||
device_t dev = iflib_get_dev(adapter->ctx); | device_t dev = iflib_get_dev(sc->ctx); | ||||
struct ixgbe_hw *hw; | struct ixgbe_hw *hw; | ||||
ixgbe_link_speed speed = 0; | ixgbe_link_speed speed = 0; | ||||
ixgbe_link_speed link_caps = 0; | ixgbe_link_speed link_caps = 0; | ||||
s32 err = IXGBE_NOT_IMPLEMENTED; | s32 err = IXGBE_NOT_IMPLEMENTED; | ||||
bool negotiate = false; | bool negotiate = false; | ||||
/* Checks to validate new value */ | /* Checks to validate new value */ | ||||
if (adapter->advertise == advertise) /* no change */ | if (sc->advertise == advertise) /* no change */ | ||||
return (0); | return (0); | ||||
hw = &adapter->hw; | hw = &sc->hw; | ||||
/* No speed changes for backplane media */ | /* No speed changes for backplane media */ | ||||
if (hw->phy.media_type == ixgbe_media_type_backplane) | if (hw->phy.media_type == ixgbe_media_type_backplane) | ||||
return (ENODEV); | return (ENODEV); | ||||
if (!((hw->phy.media_type == ixgbe_media_type_copper) || | if (!((hw->phy.media_type == ixgbe_media_type_copper) || | ||||
(hw->phy.multispeed_fiber))) { | (hw->phy.multispeed_fiber))) { | ||||
device_printf(dev, "Advertised speed can only be set on copper or multispeed fiber media types.\n"); | device_printf(dev, "Advertised speed can only be set on copper or multispeed fiber media types.\n"); | ||||
▲ Show 20 Lines • Show All 41 Lines • ▼ Show 20 Lines | if (!(link_caps & IXGBE_LINK_SPEED_10_FULL)) { | ||||
device_printf(dev, "Interface does not support 10Mb advertised speed\n"); | device_printf(dev, "Interface does not support 10Mb advertised speed\n"); | ||||
return (EINVAL); | return (EINVAL); | ||||
} | } | ||||
speed |= IXGBE_LINK_SPEED_10_FULL; | speed |= IXGBE_LINK_SPEED_10_FULL; | ||||
} | } | ||||
hw->mac.autotry_restart = true; | hw->mac.autotry_restart = true; | ||||
hw->mac.ops.setup_link(hw, speed, true); | hw->mac.ops.setup_link(hw, speed, true); | ||||
adapter->advertise = advertise; | sc->advertise = advertise; | ||||
return (0); | return (0); | ||||
} /* ixgbe_set_advertise */ | } /* ixgbe_set_advertise */ | ||||
/************************************************************************ | /************************************************************************ | ||||
* ixgbe_get_advertise - Get current advertised speed settings | * ixgbe_get_advertise - Get current advertised speed settings | ||||
* | * | ||||
* Formatted for sysctl usage. | * Formatted for sysctl usage. | ||||
* Flags: | * Flags: | ||||
* 0x1 - advertise 100 Mb | * 0x1 - advertise 100 Mb | ||||
* 0x2 - advertise 1G | * 0x2 - advertise 1G | ||||
* 0x4 - advertise 10G | * 0x4 - advertise 10G | ||||
* 0x8 - advertise 10 Mb (yes, Mb) | * 0x8 - advertise 10 Mb (yes, Mb) | ||||
************************************************************************/ | ************************************************************************/ | ||||
static int | static int | ||||
ixgbe_get_advertise(struct adapter *adapter) | ixgbe_get_advertise(struct ixgbe_softc *sc) | ||||
{ | { | ||||
struct ixgbe_hw *hw = &adapter->hw; | struct ixgbe_hw *hw = &sc->hw; | ||||
int speed; | int speed; | ||||
ixgbe_link_speed link_caps = 0; | ixgbe_link_speed link_caps = 0; | ||||
s32 err; | s32 err; | ||||
bool negotiate = false; | bool negotiate = false; | ||||
/* | /* | ||||
* Advertised speed means nothing unless it's copper or | * Advertised speed means nothing unless it's copper or | ||||
* multi-speed fiber | * multi-speed fiber | ||||
Show All 24 Lines | |||||
* Legal timer values are: | * Legal timer values are: | ||||
* 50,100,250,500,1000,2000,5000,10000 | * 50,100,250,500,1000,2000,5000,10000 | ||||
* | * | ||||
* Turning off interrupt moderation will also turn this off. | * Turning off interrupt moderation will also turn this off. | ||||
************************************************************************/ | ************************************************************************/ | ||||
static int | static int | ||||
ixgbe_sysctl_dmac(SYSCTL_HANDLER_ARGS) | ixgbe_sysctl_dmac(SYSCTL_HANDLER_ARGS) | ||||
{ | { | ||||
struct adapter *adapter = (struct adapter *)arg1; | struct ixgbe_softc *sc = (struct ixgbe_softc *)arg1; | ||||
struct ifnet *ifp = iflib_get_ifp(adapter->ctx); | struct ifnet *ifp = iflib_get_ifp(sc->ctx); | ||||
int error; | int error; | ||||
u16 newval; | u16 newval; | ||||
newval = adapter->dmac; | newval = sc->dmac; | ||||
error = sysctl_handle_16(oidp, &newval, 0, req); | error = sysctl_handle_16(oidp, &newval, 0, req); | ||||
if ((error) || (req->newptr == NULL)) | if ((error) || (req->newptr == NULL)) | ||||
return (error); | return (error); | ||||
switch (newval) { | switch (newval) { | ||||
case 0: | case 0: | ||||
/* Disabled */ | /* Disabled */ | ||||
adapter->dmac = 0; | sc->dmac = 0; | ||||
break; | break; | ||||
case 1: | case 1: | ||||
/* Enable and use default */ | /* Enable and use default */ | ||||
adapter->dmac = 1000; | sc->dmac = 1000; | ||||
break; | break; | ||||
case 50: | case 50: | ||||
case 100: | case 100: | ||||
case 250: | case 250: | ||||
case 500: | case 500: | ||||
case 1000: | case 1000: | ||||
case 2000: | case 2000: | ||||
case 5000: | case 5000: | ||||
case 10000: | case 10000: | ||||
/* Legal values - allow */ | /* Legal values - allow */ | ||||
adapter->dmac = newval; | sc->dmac = newval; | ||||
break; | break; | ||||
default: | default: | ||||
/* Do nothing, illegal value */ | /* Do nothing, illegal value */ | ||||
return (EINVAL); | return (EINVAL); | ||||
} | } | ||||
/* Re-initialize hardware if it's already running */ | /* Re-initialize hardware if it's already running */ | ||||
if (ifp->if_drv_flags & IFF_DRV_RUNNING) | if (ifp->if_drv_flags & IFF_DRV_RUNNING) | ||||
Show All 10 Lines | |||||
* Values: | * Values: | ||||
* 0 - set device to D0 | * 0 - set device to D0 | ||||
* 3 - set device to D3 | * 3 - set device to D3 | ||||
* (none) - get current device power state | * (none) - get current device power state | ||||
************************************************************************/ | ************************************************************************/ | ||||
static int | static int | ||||
ixgbe_sysctl_power_state(SYSCTL_HANDLER_ARGS) | ixgbe_sysctl_power_state(SYSCTL_HANDLER_ARGS) | ||||
{ | { | ||||
struct adapter *adapter = (struct adapter *)arg1; | struct ixgbe_softc *sc = (struct ixgbe_softc *)arg1; | ||||
device_t dev = adapter->dev; | device_t dev = sc->dev; | ||||
int curr_ps, new_ps, error = 0; | int curr_ps, new_ps, error = 0; | ||||
curr_ps = new_ps = pci_get_powerstate(dev); | curr_ps = new_ps = pci_get_powerstate(dev); | ||||
error = sysctl_handle_int(oidp, &new_ps, 0, req); | error = sysctl_handle_int(oidp, &new_ps, 0, req); | ||||
if ((error) || (req->newptr == NULL)) | if ((error) || (req->newptr == NULL)) | ||||
return (error); | return (error); | ||||
Show All 21 Lines | |||||
* | * | ||||
* Values: | * Values: | ||||
* 0 - disabled | * 0 - disabled | ||||
* 1 - enabled | * 1 - enabled | ||||
************************************************************************/ | ************************************************************************/ | ||||
static int | static int | ||||
ixgbe_sysctl_wol_enable(SYSCTL_HANDLER_ARGS) | ixgbe_sysctl_wol_enable(SYSCTL_HANDLER_ARGS) | ||||
{ | { | ||||
struct adapter *adapter = (struct adapter *)arg1; | struct ixgbe_softc *sc = (struct ixgbe_softc *)arg1; | ||||
struct ixgbe_hw *hw = &adapter->hw; | struct ixgbe_hw *hw = &sc->hw; | ||||
int new_wol_enabled; | int new_wol_enabled; | ||||
int error = 0; | int error = 0; | ||||
new_wol_enabled = hw->wol_enabled; | new_wol_enabled = hw->wol_enabled; | ||||
error = sysctl_handle_int(oidp, &new_wol_enabled, 0, req); | error = sysctl_handle_int(oidp, &new_wol_enabled, 0, req); | ||||
if ((error) || (req->newptr == NULL)) | if ((error) || (req->newptr == NULL)) | ||||
return (error); | return (error); | ||||
new_wol_enabled = !!(new_wol_enabled); | new_wol_enabled = !!(new_wol_enabled); | ||||
if (new_wol_enabled == hw->wol_enabled) | if (new_wol_enabled == hw->wol_enabled) | ||||
return (0); | return (0); | ||||
if (new_wol_enabled > 0 && !adapter->wol_support) | if (new_wol_enabled > 0 && !sc->wol_support) | ||||
return (ENODEV); | return (ENODEV); | ||||
else | else | ||||
hw->wol_enabled = new_wol_enabled; | hw->wol_enabled = new_wol_enabled; | ||||
return (0); | return (0); | ||||
} /* ixgbe_sysctl_wol_enable */ | } /* ixgbe_sysctl_wol_enable */ | ||||
/************************************************************************ | /************************************************************************ | ||||
Show All 11 Lines | |||||
* 0x40 - Direct IPv4 Packet | * 0x40 - Direct IPv4 Packet | ||||
* 0x80 - Direct IPv6 Packet | * 0x80 - Direct IPv6 Packet | ||||
* | * | ||||
* Settings not listed above will cause the sysctl to return an error. | * Settings not listed above will cause the sysctl to return an error. | ||||
************************************************************************/ | ************************************************************************/ | ||||
static int | static int | ||||
ixgbe_sysctl_wufc(SYSCTL_HANDLER_ARGS) | ixgbe_sysctl_wufc(SYSCTL_HANDLER_ARGS) | ||||
{ | { | ||||
struct adapter *adapter = (struct adapter *)arg1; | struct ixgbe_softc *sc = (struct ixgbe_softc *)arg1; | ||||
int error = 0; | int error = 0; | ||||
u32 new_wufc; | u32 new_wufc; | ||||
new_wufc = adapter->wufc; | new_wufc = sc->wufc; | ||||
error = sysctl_handle_32(oidp, &new_wufc, 0, req); | error = sysctl_handle_32(oidp, &new_wufc, 0, req); | ||||
if ((error) || (req->newptr == NULL)) | if ((error) || (req->newptr == NULL)) | ||||
return (error); | return (error); | ||||
if (new_wufc == adapter->wufc) | if (new_wufc == sc->wufc) | ||||
return (0); | return (0); | ||||
if (new_wufc & 0xffffff00) | if (new_wufc & 0xffffff00) | ||||
return (EINVAL); | return (EINVAL); | ||||
new_wufc &= 0xff; | new_wufc &= 0xff; | ||||
new_wufc |= (0xffffff & adapter->wufc); | new_wufc |= (0xffffff & sc->wufc); | ||||
adapter->wufc = new_wufc; | sc->wufc = new_wufc; | ||||
return (0); | return (0); | ||||
} /* ixgbe_sysctl_wufc */ | } /* ixgbe_sysctl_wufc */ | ||||
#ifdef IXGBE_DEBUG | #ifdef IXGBE_DEBUG | ||||
/************************************************************************ | /************************************************************************ | ||||
* ixgbe_sysctl_print_rss_config | * ixgbe_sysctl_print_rss_config | ||||
************************************************************************/ | ************************************************************************/ | ||||
static int | static int | ||||
ixgbe_sysctl_print_rss_config(SYSCTL_HANDLER_ARGS) | ixgbe_sysctl_print_rss_config(SYSCTL_HANDLER_ARGS) | ||||
{ | { | ||||
struct adapter *adapter = (struct adapter *)arg1; | struct ixgbe_softc *sc = (struct ixgbe_softc *)arg1; | ||||
struct ixgbe_hw *hw = &adapter->hw; | struct ixgbe_hw *hw = &sc->hw; | ||||
device_t dev = adapter->dev; | device_t dev = sc->dev; | ||||
struct sbuf *buf; | struct sbuf *buf; | ||||
int error = 0, reta_size; | int error = 0, reta_size; | ||||
u32 reg; | u32 reg; | ||||
buf = sbuf_new_for_sysctl(NULL, NULL, 128, req); | buf = sbuf_new_for_sysctl(NULL, NULL, 128, req); | ||||
if (!buf) { | if (!buf) { | ||||
device_printf(dev, "Could not allocate sbuf for output.\n"); | device_printf(dev, "Could not allocate sbuf for output.\n"); | ||||
return (ENOMEM); | return (ENOMEM); | ||||
} | } | ||||
// TODO: use sbufs to make a string to print out | // TODO: use sbufs to make a string to print out | ||||
/* Set multiplier for RETA setup and table size based on MAC */ | /* Set multiplier for RETA setup and table size based on MAC */ | ||||
switch (adapter->hw.mac.type) { | switch (sc->hw.mac.type) { | ||||
case ixgbe_mac_X550: | case ixgbe_mac_X550: | ||||
case ixgbe_mac_X550EM_x: | case ixgbe_mac_X550EM_x: | ||||
case ixgbe_mac_X550EM_a: | case ixgbe_mac_X550EM_a: | ||||
reta_size = 128; | reta_size = 128; | ||||
break; | break; | ||||
default: | default: | ||||
reta_size = 32; | reta_size = 32; | ||||
break; | break; | ||||
Show All 26 Lines | |||||
/************************************************************************ | /************************************************************************ | ||||
* ixgbe_sysctl_phy_temp - Retrieve temperature of PHY | * ixgbe_sysctl_phy_temp - Retrieve temperature of PHY | ||||
* | * | ||||
* For X552/X557-AT devices using an external PHY | * For X552/X557-AT devices using an external PHY | ||||
************************************************************************/ | ************************************************************************/ | ||||
static int | static int | ||||
ixgbe_sysctl_phy_temp(SYSCTL_HANDLER_ARGS) | ixgbe_sysctl_phy_temp(SYSCTL_HANDLER_ARGS) | ||||
{ | { | ||||
struct adapter *adapter = (struct adapter *)arg1; | struct ixgbe_softc *sc = (struct ixgbe_softc *)arg1; | ||||
struct ixgbe_hw *hw = &adapter->hw; | struct ixgbe_hw *hw = &sc->hw; | ||||
u16 reg; | u16 reg; | ||||
if (hw->device_id != IXGBE_DEV_ID_X550EM_X_10G_T) { | if (hw->device_id != IXGBE_DEV_ID_X550EM_X_10G_T) { | ||||
device_printf(iflib_get_dev(adapter->ctx), | device_printf(iflib_get_dev(sc->ctx), | ||||
"Device has no supported external thermal sensor.\n"); | "Device has no supported external thermal sensor.\n"); | ||||
return (ENODEV); | return (ENODEV); | ||||
} | } | ||||
if (hw->phy.ops.read_reg(hw, IXGBE_PHY_CURRENT_TEMP, | if (hw->phy.ops.read_reg(hw, IXGBE_PHY_CURRENT_TEMP, | ||||
IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, ®)) { | IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, ®)) { | ||||
device_printf(iflib_get_dev(adapter->ctx), | device_printf(iflib_get_dev(sc->ctx), | ||||
"Error reading from PHY's current temperature register\n"); | "Error reading from PHY's current temperature register\n"); | ||||
return (EAGAIN); | return (EAGAIN); | ||||
} | } | ||||
/* Shift temp for output */ | /* Shift temp for output */ | ||||
reg = reg >> 8; | reg = reg >> 8; | ||||
return (sysctl_handle_16(oidp, NULL, reg, req)); | return (sysctl_handle_16(oidp, NULL, reg, req)); | ||||
} /* ixgbe_sysctl_phy_temp */ | } /* ixgbe_sysctl_phy_temp */ | ||||
/************************************************************************ | /************************************************************************ | ||||
* ixgbe_sysctl_phy_overtemp_occurred | * ixgbe_sysctl_phy_overtemp_occurred | ||||
* | * | ||||
* Reports (directly from the PHY) whether the current PHY | * Reports (directly from the PHY) whether the current PHY | ||||
* temperature is over the overtemp threshold. | * temperature is over the overtemp threshold. | ||||
************************************************************************/ | ************************************************************************/ | ||||
static int | static int | ||||
ixgbe_sysctl_phy_overtemp_occurred(SYSCTL_HANDLER_ARGS) | ixgbe_sysctl_phy_overtemp_occurred(SYSCTL_HANDLER_ARGS) | ||||
{ | { | ||||
struct adapter *adapter = (struct adapter *)arg1; | struct ixgbe_softc *sc = (struct ixgbe_softc *)arg1; | ||||
struct ixgbe_hw *hw = &adapter->hw; | struct ixgbe_hw *hw = &sc->hw; | ||||
u16 reg; | u16 reg; | ||||
if (hw->device_id != IXGBE_DEV_ID_X550EM_X_10G_T) { | if (hw->device_id != IXGBE_DEV_ID_X550EM_X_10G_T) { | ||||
device_printf(iflib_get_dev(adapter->ctx), | device_printf(iflib_get_dev(sc->ctx), | ||||
"Device has no supported external thermal sensor.\n"); | "Device has no supported external thermal sensor.\n"); | ||||
return (ENODEV); | return (ENODEV); | ||||
} | } | ||||
if (hw->phy.ops.read_reg(hw, IXGBE_PHY_OVERTEMP_STATUS, | if (hw->phy.ops.read_reg(hw, IXGBE_PHY_OVERTEMP_STATUS, | ||||
IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, ®)) { | IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, ®)) { | ||||
device_printf(iflib_get_dev(adapter->ctx), | device_printf(iflib_get_dev(sc->ctx), | ||||
"Error reading from PHY's temperature status register\n"); | "Error reading from PHY's temperature status register\n"); | ||||
return (EAGAIN); | return (EAGAIN); | ||||
} | } | ||||
/* Get occurrence bit */ | /* Get occurrence bit */ | ||||
reg = !!(reg & 0x4000); | reg = !!(reg & 0x4000); | ||||
return (sysctl_handle_16(oidp, 0, reg, req)); | return (sysctl_handle_16(oidp, 0, reg, req)); | ||||
} /* ixgbe_sysctl_phy_overtemp_occurred */ | } /* ixgbe_sysctl_phy_overtemp_occurred */ | ||||
/************************************************************************ | /************************************************************************ | ||||
* ixgbe_sysctl_eee_state | * ixgbe_sysctl_eee_state | ||||
* | * | ||||
* Sysctl to set EEE power saving feature | * Sysctl to set EEE power saving feature | ||||
* Values: | * Values: | ||||
* 0 - disable EEE | * 0 - disable EEE | ||||
* 1 - enable EEE | * 1 - enable EEE | ||||
* (none) - get current device EEE state | * (none) - get current device EEE state | ||||
************************************************************************/ | ************************************************************************/ | ||||
static int | static int | ||||
ixgbe_sysctl_eee_state(SYSCTL_HANDLER_ARGS) | ixgbe_sysctl_eee_state(SYSCTL_HANDLER_ARGS) | ||||
{ | { | ||||
struct adapter *adapter = (struct adapter *)arg1; | struct ixgbe_softc *sc = (struct ixgbe_softc *)arg1; | ||||
device_t dev = adapter->dev; | device_t dev = sc->dev; | ||||
struct ifnet *ifp = iflib_get_ifp(adapter->ctx); | struct ifnet *ifp = iflib_get_ifp(sc->ctx); | ||||
int curr_eee, new_eee, error = 0; | int curr_eee, new_eee, error = 0; | ||||
s32 retval; | s32 retval; | ||||
curr_eee = new_eee = !!(adapter->feat_en & IXGBE_FEATURE_EEE); | curr_eee = new_eee = !!(sc->feat_en & IXGBE_FEATURE_EEE); | ||||
error = sysctl_handle_int(oidp, &new_eee, 0, req); | error = sysctl_handle_int(oidp, &new_eee, 0, req); | ||||
if ((error) || (req->newptr == NULL)) | if ((error) || (req->newptr == NULL)) | ||||
return (error); | return (error); | ||||
/* Nothing to do */ | /* Nothing to do */ | ||||
if (new_eee == curr_eee) | if (new_eee == curr_eee) | ||||
return (0); | return (0); | ||||
/* Not supported */ | /* Not supported */ | ||||
if (!(adapter->feat_cap & IXGBE_FEATURE_EEE)) | if (!(sc->feat_cap & IXGBE_FEATURE_EEE)) | ||||
return (EINVAL); | return (EINVAL); | ||||
/* Bounds checking */ | /* Bounds checking */ | ||||
if ((new_eee < 0) || (new_eee > 1)) | if ((new_eee < 0) || (new_eee > 1)) | ||||
return (EINVAL); | return (EINVAL); | ||||
retval = ixgbe_setup_eee(&adapter->hw, new_eee); | retval = ixgbe_setup_eee(&sc->hw, new_eee); | ||||
if (retval) { | if (retval) { | ||||
device_printf(dev, "Error in EEE setup: 0x%08X\n", retval); | device_printf(dev, "Error in EEE setup: 0x%08X\n", retval); | ||||
return (EINVAL); | return (EINVAL); | ||||
} | } | ||||
/* Restart auto-neg */ | /* Restart auto-neg */ | ||||
ifp->if_init(ifp); | ifp->if_init(ifp); | ||||
device_printf(dev, "New EEE state: %d\n", new_eee); | device_printf(dev, "New EEE state: %d\n", new_eee); | ||||
/* Cache new value */ | /* Cache new value */ | ||||
if (new_eee) | if (new_eee) | ||||
adapter->feat_en |= IXGBE_FEATURE_EEE; | sc->feat_en |= IXGBE_FEATURE_EEE; | ||||
else | else | ||||
adapter->feat_en &= ~IXGBE_FEATURE_EEE; | sc->feat_en &= ~IXGBE_FEATURE_EEE; | ||||
return (error); | return (error); | ||||
} /* ixgbe_sysctl_eee_state */ | } /* ixgbe_sysctl_eee_state */ | ||||
/************************************************************************ | /************************************************************************ | ||||
* ixgbe_init_device_features | * ixgbe_init_device_features | ||||
************************************************************************/ | ************************************************************************/ | ||||
static void | static void | ||||
ixgbe_init_device_features(struct adapter *adapter) | ixgbe_init_device_features(struct ixgbe_softc *sc) | ||||
{ | { | ||||
adapter->feat_cap = IXGBE_FEATURE_NETMAP | sc->feat_cap = IXGBE_FEATURE_NETMAP | ||||
| IXGBE_FEATURE_RSS | | IXGBE_FEATURE_RSS | ||||
| IXGBE_FEATURE_MSI | | IXGBE_FEATURE_MSI | ||||
| IXGBE_FEATURE_MSIX | | IXGBE_FEATURE_MSIX | ||||
| IXGBE_FEATURE_LEGACY_IRQ; | | IXGBE_FEATURE_LEGACY_IRQ; | ||||
/* Set capabilities first... */ | /* Set capabilities first... */ | ||||
switch (adapter->hw.mac.type) { | switch (sc->hw.mac.type) { | ||||
case ixgbe_mac_82598EB: | case ixgbe_mac_82598EB: | ||||
if (adapter->hw.device_id == IXGBE_DEV_ID_82598AT) | if (sc->hw.device_id == IXGBE_DEV_ID_82598AT) | ||||
adapter->feat_cap |= IXGBE_FEATURE_FAN_FAIL; | sc->feat_cap |= IXGBE_FEATURE_FAN_FAIL; | ||||
break; | break; | ||||
case ixgbe_mac_X540: | case ixgbe_mac_X540: | ||||
adapter->feat_cap |= IXGBE_FEATURE_SRIOV; | sc->feat_cap |= IXGBE_FEATURE_SRIOV; | ||||
adapter->feat_cap |= IXGBE_FEATURE_FDIR; | sc->feat_cap |= IXGBE_FEATURE_FDIR; | ||||
if ((adapter->hw.device_id == IXGBE_DEV_ID_X540_BYPASS) && | if ((sc->hw.device_id == IXGBE_DEV_ID_X540_BYPASS) && | ||||
(adapter->hw.bus.func == 0)) | (sc->hw.bus.func == 0)) | ||||
adapter->feat_cap |= IXGBE_FEATURE_BYPASS; | sc->feat_cap |= IXGBE_FEATURE_BYPASS; | ||||
break; | break; | ||||
case ixgbe_mac_X550: | case ixgbe_mac_X550: | ||||
adapter->feat_cap |= IXGBE_FEATURE_TEMP_SENSOR; | sc->feat_cap |= IXGBE_FEATURE_TEMP_SENSOR; | ||||
adapter->feat_cap |= IXGBE_FEATURE_SRIOV; | sc->feat_cap |= IXGBE_FEATURE_SRIOV; | ||||
adapter->feat_cap |= IXGBE_FEATURE_FDIR; | sc->feat_cap |= IXGBE_FEATURE_FDIR; | ||||
break; | break; | ||||
case ixgbe_mac_X550EM_x: | case ixgbe_mac_X550EM_x: | ||||
adapter->feat_cap |= IXGBE_FEATURE_SRIOV; | sc->feat_cap |= IXGBE_FEATURE_SRIOV; | ||||
adapter->feat_cap |= IXGBE_FEATURE_FDIR; | sc->feat_cap |= IXGBE_FEATURE_FDIR; | ||||
break; | break; | ||||
case ixgbe_mac_X550EM_a: | case ixgbe_mac_X550EM_a: | ||||
adapter->feat_cap |= IXGBE_FEATURE_SRIOV; | sc->feat_cap |= IXGBE_FEATURE_SRIOV; | ||||
adapter->feat_cap |= IXGBE_FEATURE_FDIR; | sc->feat_cap |= IXGBE_FEATURE_FDIR; | ||||
adapter->feat_cap &= ~IXGBE_FEATURE_LEGACY_IRQ; | sc->feat_cap &= ~IXGBE_FEATURE_LEGACY_IRQ; | ||||
if ((adapter->hw.device_id == IXGBE_DEV_ID_X550EM_A_1G_T) || | if ((sc->hw.device_id == IXGBE_DEV_ID_X550EM_A_1G_T) || | ||||
(adapter->hw.device_id == IXGBE_DEV_ID_X550EM_A_1G_T_L)) { | (sc->hw.device_id == IXGBE_DEV_ID_X550EM_A_1G_T_L)) { | ||||
adapter->feat_cap |= IXGBE_FEATURE_TEMP_SENSOR; | sc->feat_cap |= IXGBE_FEATURE_TEMP_SENSOR; | ||||
adapter->feat_cap |= IXGBE_FEATURE_EEE; | sc->feat_cap |= IXGBE_FEATURE_EEE; | ||||
} | } | ||||
break; | break; | ||||
case ixgbe_mac_82599EB: | case ixgbe_mac_82599EB: | ||||
adapter->feat_cap |= IXGBE_FEATURE_SRIOV; | sc->feat_cap |= IXGBE_FEATURE_SRIOV; | ||||
adapter->feat_cap |= IXGBE_FEATURE_FDIR; | sc->feat_cap |= IXGBE_FEATURE_FDIR; | ||||
if ((adapter->hw.device_id == IXGBE_DEV_ID_82599_BYPASS) && | if ((sc->hw.device_id == IXGBE_DEV_ID_82599_BYPASS) && | ||||
(adapter->hw.bus.func == 0)) | (sc->hw.bus.func == 0)) | ||||
adapter->feat_cap |= IXGBE_FEATURE_BYPASS; | sc->feat_cap |= IXGBE_FEATURE_BYPASS; | ||||
if (adapter->hw.device_id == IXGBE_DEV_ID_82599_QSFP_SF_QP) | if (sc->hw.device_id == IXGBE_DEV_ID_82599_QSFP_SF_QP) | ||||
adapter->feat_cap &= ~IXGBE_FEATURE_LEGACY_IRQ; | sc->feat_cap &= ~IXGBE_FEATURE_LEGACY_IRQ; | ||||
break; | break; | ||||
default: | default: | ||||
break; | break; | ||||
} | } | ||||
/* Enabled by default... */ | /* Enabled by default... */ | ||||
/* Fan failure detection */ | /* Fan failure detection */ | ||||
if (adapter->feat_cap & IXGBE_FEATURE_FAN_FAIL) | if (sc->feat_cap & IXGBE_FEATURE_FAN_FAIL) | ||||
adapter->feat_en |= IXGBE_FEATURE_FAN_FAIL; | sc->feat_en |= IXGBE_FEATURE_FAN_FAIL; | ||||
/* Netmap */ | /* Netmap */ | ||||
if (adapter->feat_cap & IXGBE_FEATURE_NETMAP) | if (sc->feat_cap & IXGBE_FEATURE_NETMAP) | ||||
adapter->feat_en |= IXGBE_FEATURE_NETMAP; | sc->feat_en |= IXGBE_FEATURE_NETMAP; | ||||
/* EEE */ | /* EEE */ | ||||
if (adapter->feat_cap & IXGBE_FEATURE_EEE) | if (sc->feat_cap & IXGBE_FEATURE_EEE) | ||||
adapter->feat_en |= IXGBE_FEATURE_EEE; | sc->feat_en |= IXGBE_FEATURE_EEE; | ||||
/* Thermal Sensor */ | /* Thermal Sensor */ | ||||
if (adapter->feat_cap & IXGBE_FEATURE_TEMP_SENSOR) | if (sc->feat_cap & IXGBE_FEATURE_TEMP_SENSOR) | ||||
adapter->feat_en |= IXGBE_FEATURE_TEMP_SENSOR; | sc->feat_en |= IXGBE_FEATURE_TEMP_SENSOR; | ||||
/* Enabled via global sysctl... */ | /* Enabled via global sysctl... */ | ||||
/* Flow Director */ | /* Flow Director */ | ||||
if (ixgbe_enable_fdir) { | if (ixgbe_enable_fdir) { | ||||
if (adapter->feat_cap & IXGBE_FEATURE_FDIR) | if (sc->feat_cap & IXGBE_FEATURE_FDIR) | ||||
adapter->feat_en |= IXGBE_FEATURE_FDIR; | sc->feat_en |= IXGBE_FEATURE_FDIR; | ||||
else | else | ||||
device_printf(adapter->dev, "Device does not support Flow Director. Leaving disabled."); | device_printf(sc->dev, "Device does not support Flow Director. Leaving disabled."); | ||||
} | } | ||||
/* | /* | ||||
* Message Signal Interrupts - Extended (MSI-X) | * Message Signal Interrupts - Extended (MSI-X) | ||||
* Normal MSI is only enabled if MSI-X calls fail. | * Normal MSI is only enabled if MSI-X calls fail. | ||||
*/ | */ | ||||
if (!ixgbe_enable_msix) | if (!ixgbe_enable_msix) | ||||
adapter->feat_cap &= ~IXGBE_FEATURE_MSIX; | sc->feat_cap &= ~IXGBE_FEATURE_MSIX; | ||||
/* Receive-Side Scaling (RSS) */ | /* Receive-Side Scaling (RSS) */ | ||||
if ((adapter->feat_cap & IXGBE_FEATURE_RSS) && ixgbe_enable_rss) | if ((sc->feat_cap & IXGBE_FEATURE_RSS) && ixgbe_enable_rss) | ||||
adapter->feat_en |= IXGBE_FEATURE_RSS; | sc->feat_en |= IXGBE_FEATURE_RSS; | ||||
/* Disable features with unmet dependencies... */ | /* Disable features with unmet dependencies... */ | ||||
/* No MSI-X */ | /* No MSI-X */ | ||||
if (!(adapter->feat_cap & IXGBE_FEATURE_MSIX)) { | if (!(sc->feat_cap & IXGBE_FEATURE_MSIX)) { | ||||
adapter->feat_cap &= ~IXGBE_FEATURE_RSS; | sc->feat_cap &= ~IXGBE_FEATURE_RSS; | ||||
adapter->feat_cap &= ~IXGBE_FEATURE_SRIOV; | sc->feat_cap &= ~IXGBE_FEATURE_SRIOV; | ||||
adapter->feat_en &= ~IXGBE_FEATURE_RSS; | sc->feat_en &= ~IXGBE_FEATURE_RSS; | ||||
adapter->feat_en &= ~IXGBE_FEATURE_SRIOV; | sc->feat_en &= ~IXGBE_FEATURE_SRIOV; | ||||
} | } | ||||
} /* ixgbe_init_device_features */ | } /* ixgbe_init_device_features */ | ||||
/************************************************************************ | /************************************************************************ | ||||
* ixgbe_check_fan_failure | * ixgbe_check_fan_failure | ||||
************************************************************************/ | ************************************************************************/ | ||||
static void | static void | ||||
ixgbe_check_fan_failure(struct adapter *adapter, u32 reg, bool in_interrupt) | ixgbe_check_fan_failure(struct ixgbe_softc *sc, u32 reg, bool in_interrupt) | ||||
{ | { | ||||
u32 mask; | u32 mask; | ||||
mask = (in_interrupt) ? IXGBE_EICR_GPI_SDP1_BY_MAC(&adapter->hw) : | mask = (in_interrupt) ? IXGBE_EICR_GPI_SDP1_BY_MAC(&sc->hw) : | ||||
IXGBE_ESDP_SDP1; | IXGBE_ESDP_SDP1; | ||||
if (reg & mask) | if (reg & mask) | ||||
device_printf(adapter->dev, "\nCRITICAL: FAN FAILURE!! REPLACE IMMEDIATELY!!\n"); | device_printf(sc->dev, "\nCRITICAL: FAN FAILURE!! REPLACE IMMEDIATELY!!\n"); | ||||
} /* ixgbe_check_fan_failure */ | } /* ixgbe_check_fan_failure */ | ||||
/************************************************************************ | /************************************************************************ | ||||
* ixgbe_sbuf_fw_version | * ixgbe_sbuf_fw_version | ||||
************************************************************************/ | ************************************************************************/ | ||||
static void | static void | ||||
ixgbe_sbuf_fw_version(struct ixgbe_hw *hw, struct sbuf *buf) | ixgbe_sbuf_fw_version(struct ixgbe_hw *hw, struct sbuf *buf) | ||||
{ | { | ||||
Show All 30 Lines | |||||
} /* ixgbe_sbuf_fw_version */ | } /* ixgbe_sbuf_fw_version */ | ||||
/************************************************************************ | /************************************************************************ | ||||
* ixgbe_print_fw_version | * ixgbe_print_fw_version | ||||
************************************************************************/ | ************************************************************************/ | ||||
static void | static void | ||||
ixgbe_print_fw_version(if_ctx_t ctx) | ixgbe_print_fw_version(if_ctx_t ctx) | ||||
{ | { | ||||
struct adapter *adapter = iflib_get_softc(ctx); | struct ixgbe_softc *sc = iflib_get_softc(ctx); | ||||
struct ixgbe_hw *hw = &adapter->hw; | struct ixgbe_hw *hw = &sc->hw; | ||||
device_t dev = adapter->dev; | device_t dev = sc->dev; | ||||
struct sbuf *buf; | struct sbuf *buf; | ||||
int error = 0; | int error = 0; | ||||
buf = sbuf_new_auto(); | buf = sbuf_new_auto(); | ||||
if (!buf) { | if (!buf) { | ||||
device_printf(dev, "Could not allocate sbuf for output.\n"); | device_printf(dev, "Could not allocate sbuf for output.\n"); | ||||
return; | return; | ||||
} | } | ||||
Show All 10 Lines | |||||
} /* ixgbe_print_fw_version */ | } /* ixgbe_print_fw_version */ | ||||
/************************************************************************ | /************************************************************************ | ||||
* ixgbe_sysctl_print_fw_version | * ixgbe_sysctl_print_fw_version | ||||
************************************************************************/ | ************************************************************************/ | ||||
static int | static int | ||||
ixgbe_sysctl_print_fw_version(SYSCTL_HANDLER_ARGS) | ixgbe_sysctl_print_fw_version(SYSCTL_HANDLER_ARGS) | ||||
{ | { | ||||
struct adapter *adapter = (struct adapter *)arg1; | struct ixgbe_softc *sc = (struct ixgbe_softc *)arg1; | ||||
struct ixgbe_hw *hw = &adapter->hw; | struct ixgbe_hw *hw = &sc->hw; | ||||
device_t dev = adapter->dev; | device_t dev = sc->dev; | ||||
struct sbuf *buf; | struct sbuf *buf; | ||||
int error = 0; | int error = 0; | ||||
buf = sbuf_new_for_sysctl(NULL, NULL, 128, req); | buf = sbuf_new_for_sysctl(NULL, NULL, 128, req); | ||||
if (!buf) { | if (!buf) { | ||||
device_printf(dev, "Could not allocate sbuf for output.\n"); | device_printf(dev, "Could not allocate sbuf for output.\n"); | ||||
return (ENOMEM); | return (ENOMEM); | ||||
} | } | ||||
Show All 11 Lines |