Changeset View
Changeset View
Standalone View
Standalone View
sys/dev/ixgbe/if_ixv.c
Show First 20 Lines • Show All 65 Lines • ▼ Show 20 Lines | static pci_vendor_info_t ixv_vendor_info_array[] = | ||||
PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_A_VF, "Intel(R) X553 Virtual Function"), | PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_A_VF, "Intel(R) X553 Virtual Function"), | ||||
/* required last entry */ | /* required last entry */ | ||||
PVID_END | PVID_END | ||||
}; | }; | ||||
/************************************************************************ | /************************************************************************ | ||||
* Function prototypes | * Function prototypes | ||||
************************************************************************/ | ************************************************************************/ | ||||
static void *ixv_register(device_t dev); | static void *ixv_register(device_t); | ||||
static int ixv_if_attach_pre(if_ctx_t ctx); | static int ixv_if_attach_pre(if_ctx_t); | ||||
static int ixv_if_attach_post(if_ctx_t ctx); | static int ixv_if_attach_post(if_ctx_t); | ||||
static int ixv_if_detach(if_ctx_t ctx); | static int ixv_if_detach(if_ctx_t); | ||||
static int ixv_if_rx_queue_intr_enable(if_ctx_t ctx, uint16_t qid); | static int ixv_if_rx_queue_intr_enable(if_ctx_t, uint16_t); | ||||
static int ixv_if_tx_queues_alloc(if_ctx_t ctx, caddr_t *vaddrs, uint64_t *paddrs, int nqs, int nqsets); | static int ixv_if_tx_queues_alloc(if_ctx_t, caddr_t *, uint64_t *, int, int); | ||||
static int ixv_if_rx_queues_alloc(if_ctx_t ctx, caddr_t *vaddrs, uint64_t *paddrs, int nqs, int nqsets); | static int ixv_if_rx_queues_alloc(if_ctx_t, caddr_t *, uint64_t *, int, int); | ||||
static void ixv_if_queues_free(if_ctx_t ctx); | static void ixv_if_queues_free(if_ctx_t); | ||||
static void ixv_identify_hardware(if_ctx_t ctx); | static void ixv_identify_hardware(if_ctx_t); | ||||
static void ixv_init_device_features(struct adapter *); | static void ixv_init_device_features(struct ixgbe_softc *); | ||||
static int ixv_allocate_pci_resources(if_ctx_t ctx); | static int ixv_allocate_pci_resources(if_ctx_t); | ||||
static void ixv_free_pci_resources(if_ctx_t ctx); | static void ixv_free_pci_resources(if_ctx_t); | ||||
static int ixv_setup_interface(if_ctx_t ctx); | static int ixv_setup_interface(if_ctx_t); | ||||
static void ixv_if_media_status(if_ctx_t , struct ifmediareq *); | static void ixv_if_media_status(if_ctx_t, struct ifmediareq *); | ||||
static int ixv_if_media_change(if_ctx_t ctx); | static int ixv_if_media_change(if_ctx_t); | ||||
static void ixv_if_update_admin_status(if_ctx_t ctx); | static void ixv_if_update_admin_status(if_ctx_t); | ||||
static int ixv_if_msix_intr_assign(if_ctx_t ctx, int msix); | static int ixv_if_msix_intr_assign(if_ctx_t, int); | ||||
static int ixv_if_mtu_set(if_ctx_t ctx, uint32_t mtu); | static int ixv_if_mtu_set(if_ctx_t, uint32_t); | ||||
static void ixv_if_init(if_ctx_t ctx); | static void ixv_if_init(if_ctx_t); | ||||
static void ixv_if_local_timer(if_ctx_t ctx, uint16_t qid); | static void ixv_if_local_timer(if_ctx_t, uint16_t); | ||||
static void ixv_if_stop(if_ctx_t ctx); | static void ixv_if_stop(if_ctx_t); | ||||
static int ixv_negotiate_api(struct adapter *); | static int ixv_negotiate_api(struct ixgbe_softc *); | ||||
static void ixv_initialize_transmit_units(if_ctx_t ctx); | static void ixv_initialize_transmit_units(if_ctx_t); | ||||
static void ixv_initialize_receive_units(if_ctx_t ctx); | static void ixv_initialize_receive_units(if_ctx_t); | ||||
static void ixv_initialize_rss_mapping(struct adapter *); | static void ixv_initialize_rss_mapping(struct ixgbe_softc *); | ||||
static void ixv_setup_vlan_support(if_ctx_t ctx); | static void ixv_setup_vlan_support(if_ctx_t); | ||||
static void ixv_configure_ivars(struct adapter *); | static void ixv_configure_ivars(struct ixgbe_softc *); | ||||
static void ixv_if_enable_intr(if_ctx_t ctx); | static void ixv_if_enable_intr(if_ctx_t); | ||||
static void ixv_if_disable_intr(if_ctx_t ctx); | static void ixv_if_disable_intr(if_ctx_t); | ||||
static void ixv_if_multi_set(if_ctx_t ctx); | static void ixv_if_multi_set(if_ctx_t); | ||||
static void ixv_if_register_vlan(if_ctx_t, u16); | static void ixv_if_register_vlan(if_ctx_t, u16); | ||||
static void ixv_if_unregister_vlan(if_ctx_t, u16); | static void ixv_if_unregister_vlan(if_ctx_t, u16); | ||||
static uint64_t ixv_if_get_counter(if_ctx_t, ift_counter); | static uint64_t ixv_if_get_counter(if_ctx_t, ift_counter); | ||||
static bool ixv_if_needs_restart(if_ctx_t, enum iflib_restart_event); | static bool ixv_if_needs_restart(if_ctx_t, enum iflib_restart_event); | ||||
static void ixv_save_stats(struct adapter *); | static void ixv_save_stats(struct ixgbe_softc *); | ||||
static void ixv_init_stats(struct adapter *); | static void ixv_init_stats(struct ixgbe_softc *); | ||||
static void ixv_update_stats(struct adapter *); | static void ixv_update_stats(struct ixgbe_softc *); | ||||
static void ixv_add_stats_sysctls(struct adapter *adapter); | static void ixv_add_stats_sysctls(struct ixgbe_softc *); | ||||
static int ixv_sysctl_debug(SYSCTL_HANDLER_ARGS); | static int ixv_sysctl_debug(SYSCTL_HANDLER_ARGS); | ||||
static void ixv_set_ivar(struct adapter *, u8, u8, s8); | static void ixv_set_ivar(struct ixgbe_softc *, u8, u8, s8); | ||||
static u8 *ixv_mc_array_itr(struct ixgbe_hw *, u8 **, u32 *); | static u8 *ixv_mc_array_itr(struct ixgbe_hw *, u8 **, u32 *); | ||||
/* The MSI-X Interrupt handlers */ | /* The MSI-X Interrupt handlers */ | ||||
static int ixv_msix_que(void *); | static int ixv_msix_que(void *); | ||||
static int ixv_msix_mbx(void *); | static int ixv_msix_mbx(void *); | ||||
/************************************************************************ | /************************************************************************ | ||||
* FreeBSD Device Interface Entry Points | * FreeBSD Device Interface Entry Points | ||||
************************************************************************/ | ************************************************************************/ | ||||
static device_method_t ixv_methods[] = { | static device_method_t ixv_methods[] = { | ||||
/* Device interface */ | /* Device interface */ | ||||
DEVMETHOD(device_register, ixv_register), | DEVMETHOD(device_register, ixv_register), | ||||
DEVMETHOD(device_probe, iflib_device_probe), | DEVMETHOD(device_probe, iflib_device_probe), | ||||
DEVMETHOD(device_attach, iflib_device_attach), | DEVMETHOD(device_attach, iflib_device_attach), | ||||
DEVMETHOD(device_detach, iflib_device_detach), | DEVMETHOD(device_detach, iflib_device_detach), | ||||
DEVMETHOD(device_shutdown, iflib_device_shutdown), | DEVMETHOD(device_shutdown, iflib_device_shutdown), | ||||
DEVMETHOD_END | DEVMETHOD_END | ||||
}; | }; | ||||
static driver_t ixv_driver = { | static driver_t ixv_driver = { | ||||
"ixv", ixv_methods, sizeof(struct adapter), | "ixv", ixv_methods, sizeof(struct ixgbe_softc), | ||||
}; | }; | ||||
devclass_t ixv_devclass; | devclass_t ixv_devclass; | ||||
DRIVER_MODULE(ixv, pci, ixv_driver, ixv_devclass, 0, 0); | DRIVER_MODULE(ixv, pci, ixv_driver, ixv_devclass, 0, 0); | ||||
IFLIB_PNP_INFO(pci, ixv_driver, ixv_vendor_info_array); | IFLIB_PNP_INFO(pci, ixv_driver, ixv_vendor_info_array); | ||||
MODULE_DEPEND(ixv, iflib, 1, 1, 1); | MODULE_DEPEND(ixv, iflib, 1, 1, 1); | ||||
MODULE_DEPEND(ixv, pci, 1, 1, 1); | MODULE_DEPEND(ixv, pci, 1, 1, 1); | ||||
MODULE_DEPEND(ixv, ether, 1, 1, 1); | MODULE_DEPEND(ixv, ether, 1, 1, 1); | ||||
Show All 21 Lines | static device_method_t ixv_if_methods[] = { | ||||
DEVMETHOD(ifdi_vlan_register, ixv_if_register_vlan), | DEVMETHOD(ifdi_vlan_register, ixv_if_register_vlan), | ||||
DEVMETHOD(ifdi_vlan_unregister, ixv_if_unregister_vlan), | DEVMETHOD(ifdi_vlan_unregister, ixv_if_unregister_vlan), | ||||
DEVMETHOD(ifdi_get_counter, ixv_if_get_counter), | DEVMETHOD(ifdi_get_counter, ixv_if_get_counter), | ||||
DEVMETHOD(ifdi_needs_restart, ixv_if_needs_restart), | DEVMETHOD(ifdi_needs_restart, ixv_if_needs_restart), | ||||
DEVMETHOD_END | DEVMETHOD_END | ||||
}; | }; | ||||
static driver_t ixv_if_driver = { | static driver_t ixv_if_driver = { | ||||
"ixv_if", ixv_if_methods, sizeof(struct adapter) | "ixv_if", ixv_if_methods, sizeof(struct ixgbe_softc) | ||||
}; | }; | ||||
/* | /* | ||||
* TUNEABLE PARAMETERS: | * TUNEABLE PARAMETERS: | ||||
*/ | */ | ||||
/* Flow control setting, default to full */ | /* Flow control setting, default to full */ | ||||
static int ixv_flow_control = ixgbe_fc_full; | static int ixv_flow_control = ixgbe_fc_full; | ||||
▲ Show 20 Lines • Show All 51 Lines • ▼ Show 20 Lines | |||||
/************************************************************************ | /************************************************************************ | ||||
* ixv_if_tx_queues_alloc | * ixv_if_tx_queues_alloc | ||||
************************************************************************/ | ************************************************************************/ | ||||
static int | static int | ||||
ixv_if_tx_queues_alloc(if_ctx_t ctx, caddr_t *vaddrs, uint64_t *paddrs, | ixv_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 == 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_DEVBUF, M_NOWAIT | M_ZERO); | M_DEVBUF, 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; | ||||
txr->me = i; | txr->me = i; | ||||
txr->adapter = que->adapter = adapter; | txr->sc = que->sc = sc; | ||||
/* Allocate report status array */ | /* Allocate report status array */ | ||||
if (!(txr->tx_rsq = (qidx_t *)malloc(sizeof(qidx_t) * scctx->isc_ntxd[0], M_DEVBUF, M_NOWAIT | M_ZERO))) { | if (!(txr->tx_rsq = (qidx_t *)malloc(sizeof(qidx_t) * scctx->isc_ntxd[0], M_DEVBUF, M_NOWAIT | M_ZERO))) { | ||||
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_VFTDT(txr->me); | txr->tail = IXGBE_VFTDT(txr->me); | ||||
txr->tx_base = (union ixgbe_adv_tx_desc *)vaddrs[i*ntxqs]; | txr->tx_base = (union ixgbe_adv_tx_desc *)vaddrs[i*ntxqs]; | ||||
txr->tx_paddr = paddrs[i*ntxqs]; | txr->tx_paddr = paddrs[i*ntxqs]; | ||||
txr->bytes = 0; | txr->bytes = 0; | ||||
txr->total_packets = 0; | txr->total_packets = 0; | ||||
} | } | ||||
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: | ||||
ixv_if_queues_free(ctx); | ixv_if_queues_free(ctx); | ||||
return (error); | return (error); | ||||
} /* ixv_if_tx_queues_alloc */ | } /* ixv_if_tx_queues_alloc */ | ||||
/************************************************************************ | /************************************************************************ | ||||
* ixv_if_rx_queues_alloc | * ixv_if_rx_queues_alloc | ||||
************************************************************************/ | ************************************************************************/ | ||||
static int | static int | ||||
ixv_if_rx_queues_alloc(if_ctx_t ctx, caddr_t *vaddrs, uint64_t *paddrs, | ixv_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, error; | int i, error; | ||||
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_DEVBUF, M_NOWAIT | M_ZERO); | M_DEVBUF, 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"); | ||||
error = ENOMEM; | error = ENOMEM; | ||||
goto fail; | goto fail; | ||||
} | } | ||||
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; | ||||
rxr->me = i; | rxr->me = 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_VFRDT(rxr->me); | rxr->tail = IXGBE_VFRDT(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*nrxqs]; | rxr->rx_paddr = paddrs[i*nrxqs]; | ||||
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); | ||||
fail: | fail: | ||||
ixv_if_queues_free(ctx); | ixv_if_queues_free(ctx); | ||||
return (error); | return (error); | ||||
} /* ixv_if_rx_queues_alloc */ | } /* ixv_if_rx_queues_alloc */ | ||||
/************************************************************************ | /************************************************************************ | ||||
* ixv_if_queues_free | * ixv_if_queues_free | ||||
************************************************************************/ | ************************************************************************/ | ||||
static void | static void | ||||
ixv_if_queues_free(if_ctx_t ctx) | ixv_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 *que = adapter->tx_queues; | struct ix_tx_queue *que = sc->tx_queues; | ||||
int i; | int i; | ||||
if (que == NULL) | if (que == NULL) | ||||
goto free; | goto free; | ||||
for (i = 0; i < adapter->num_tx_queues; i++, que++) { | for (i = 0; i < sc->num_tx_queues; i++, que++) { | ||||
struct tx_ring *txr = &que->txr; | struct tx_ring *txr = &que->txr; | ||||
if (txr->tx_rsq == NULL) | if (txr->tx_rsq == NULL) | ||||
break; | break; | ||||
free(txr->tx_rsq, M_DEVBUF); | free(txr->tx_rsq, M_DEVBUF); | ||||
txr->tx_rsq = NULL; | txr->tx_rsq = NULL; | ||||
} | } | ||||
if (adapter->tx_queues != NULL) | if (sc->tx_queues != NULL) | ||||
free(adapter->tx_queues, M_DEVBUF); | free(sc->tx_queues, M_DEVBUF); | ||||
free: | free: | ||||
if (adapter->rx_queues != NULL) | if (sc->rx_queues != NULL) | ||||
free(adapter->rx_queues, M_DEVBUF); | free(sc->rx_queues, M_DEVBUF); | ||||
adapter->tx_queues = NULL; | sc->tx_queues = NULL; | ||||
adapter->rx_queues = NULL; | sc->rx_queues = NULL; | ||||
} /* ixv_if_queues_free */ | } /* ixv_if_queues_free */ | ||||
/************************************************************************ | /************************************************************************ | ||||
* ixv_if_attach_pre - Device initialization routine | * ixv_if_attach_pre - Device initialization routine | ||||
* | * | ||||
* Called when the driver is being loaded. | * Called when the driver is being loaded. | ||||
* Identifies the type of hardware, allocates all resources | * Identifies the type of hardware, allocates all resources | ||||
* and initializes the hardware. | * and initializes the hardware. | ||||
* | * | ||||
* return 0 on success, positive on failure | * return 0 on success, positive on failure | ||||
************************************************************************/ | ************************************************************************/ | ||||
static int | static int | ||||
ixv_if_attach_pre(if_ctx_t ctx) | ixv_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; | ||||
INIT_DEBUGOUT("ixv_attach: begin"); | INIT_DEBUGOUT("ixv_attach: begin"); | ||||
/* Allocate, clear, and link in our adapter structure */ | /* Allocate, clear, and link in our sc structure */ | ||||
dev = iflib_get_dev(ctx); | dev = iflib_get_dev(ctx); | ||||
adapter = iflib_get_softc(ctx); | sc = iflib_get_softc(ctx); | ||||
adapter->dev = dev; | sc->dev = dev; | ||||
adapter->ctx = ctx; | sc->ctx = ctx; | ||||
adapter->hw.back = adapter; | sc->hw.back = sc; | ||||
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; | ||||
/* Do base PCI setup - map BAR0 */ | /* Do base PCI setup - map BAR0 */ | ||||
if (ixv_allocate_pci_resources(ctx)) { | if (ixv_allocate_pci_resources(ctx)) { | ||||
device_printf(dev, "ixv_allocate_pci_resources() failed!\n"); | device_printf(dev, "ixv_allocate_pci_resources() failed!\n"); | ||||
error = ENXIO; | error = ENXIO; | ||||
goto err_out; | goto err_out; | ||||
} | } | ||||
/* SYSCTL APIs */ | /* SYSCTL APIs */ | ||||
SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev), | SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev), | ||||
SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO, "debug", | SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO, "debug", | ||||
CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NEEDGIANT, | CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NEEDGIANT, | ||||
adapter, 0, ixv_sysctl_debug, "I", "Debug Info"); | sc, 0, ixv_sysctl_debug, "I", "Debug Info"); | ||||
/* Determine hardware revision */ | /* Determine hardware revision */ | ||||
ixv_identify_hardware(ctx); | ixv_identify_hardware(ctx); | ||||
ixv_init_device_features(adapter); | ixv_init_device_features(sc); | ||||
/* Initialize the shared code */ | /* Initialize the shared code */ | ||||
error = ixgbe_init_ops_vf(hw); | error = ixgbe_init_ops_vf(hw); | ||||
if (error) { | if (error) { | ||||
device_printf(dev, "ixgbe_init_ops_vf() failed!\n"); | device_printf(dev, "ixgbe_init_ops_vf() failed!\n"); | ||||
error = EIO; | error = EIO; | ||||
goto err_out; | goto err_out; | ||||
} | } | ||||
Show All 16 Lines | ixv_if_attach_pre(if_ctx_t ctx) | ||||
if (error) { | if (error) { | ||||
device_printf(dev, "...init_hw() failed with error %d\n", | device_printf(dev, "...init_hw() failed with error %d\n", | ||||
error); | error); | ||||
error = EIO; | error = EIO; | ||||
goto err_out; | goto err_out; | ||||
} | } | ||||
/* Negotiate mailbox API version */ | /* Negotiate mailbox API version */ | ||||
error = ixv_negotiate_api(adapter); | error = ixv_negotiate_api(sc); | ||||
if (error) { | if (error) { | ||||
device_printf(dev, | device_printf(dev, | ||||
"Mailbox API negotiation failed during attach!\n"); | "Mailbox API negotiation failed during attach!\n"); | ||||
goto err_out; | goto err_out; | ||||
} | } | ||||
/* If no mac address was assigned, make a random one */ | /* If no mac address was assigned, make a random one */ | ||||
if (!ixv_check_ether_addr(hw->mac.addr)) { | if (!ixv_check_ether_addr(hw->mac.addr)) { | ||||
ether_gen_addr(iflib_get_ifp(ctx), | ether_gen_addr(iflib_get_ifp(ctx), | ||||
(struct ether_addr *)hw->mac.addr); | (struct ether_addr *)hw->mac.addr); | ||||
bcopy(hw->mac.addr, hw->mac.perm_addr, | bcopy(hw->mac.addr, hw->mac.perm_addr, | ||||
sizeof(hw->mac.perm_addr)); | sizeof(hw->mac.perm_addr)); | ||||
} | } | ||||
/* 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_vf: | case ixgbe_mac_X550_vf: | ||||
case ixgbe_mac_X550EM_x_vf: | case ixgbe_mac_X550EM_x_vf: | ||||
case ixgbe_mac_X550EM_a_vf: | case ixgbe_mac_X550EM_a_vf: | ||||
scctx->isc_ntxqsets_max = scctx->isc_nrxqsets_max = 2; | scctx->isc_ntxqsets_max = scctx->isc_nrxqsets_max = 2; | ||||
break; | break; | ||||
default: | default: | ||||
scctx->isc_ntxqsets_max = scctx->isc_nrxqsets_max = 1; | scctx->isc_ntxqsets_max = scctx->isc_nrxqsets_max = 1; | ||||
} | } | ||||
Show All 31 Lines | err_out: | ||||
ixv_free_pci_resources(ctx); | ixv_free_pci_resources(ctx); | ||||
return (error); | return (error); | ||||
} /* ixv_if_attach_pre */ | } /* ixv_if_attach_pre */ | ||||
static int | static int | ||||
ixv_if_attach_post(if_ctx_t ctx) | ixv_if_attach_post(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 error = 0; | int error = 0; | ||||
/* Setup OS specific network interface */ | /* Setup OS specific network interface */ | ||||
error = ixv_setup_interface(ctx); | error = ixv_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 end; | goto end; | ||||
} | } | ||||
/* Do the stats setup */ | /* Do the stats setup */ | ||||
ixv_save_stats(adapter); | ixv_save_stats(sc); | ||||
ixv_init_stats(adapter); | ixv_init_stats(sc); | ||||
ixv_add_stats_sysctls(adapter); | ixv_add_stats_sysctls(sc); | ||||
end: | end: | ||||
return error; | return error; | ||||
} /* ixv_if_attach_post */ | } /* ixv_if_attach_post */ | ||||
/************************************************************************ | /************************************************************************ | ||||
* ixv_detach - Device removal routine | * ixv_detach - Device removal routine | ||||
* | * | ||||
Show All 14 Lines | |||||
} /* ixv_if_detach */ | } /* ixv_if_detach */ | ||||
/************************************************************************ | /************************************************************************ | ||||
* ixv_if_mtu_set | * ixv_if_mtu_set | ||||
************************************************************************/ | ************************************************************************/ | ||||
static int | static int | ||||
ixv_if_mtu_set(if_ctx_t ctx, uint32_t mtu) | ixv_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); | ||||
struct ifnet *ifp = iflib_get_ifp(ctx); | struct ifnet *ifp = iflib_get_ifp(ctx); | ||||
int error = 0; | int error = 0; | ||||
IOCTL_DEBUGOUT("ioctl: SIOCSIFMTU (Set Interface MTU)"); | IOCTL_DEBUGOUT("ioctl: SIOCSIFMTU (Set Interface MTU)"); | ||||
if (mtu > IXGBE_MAX_FRAME_SIZE - IXGBE_MTU_HDR) { | if (mtu > IXGBE_MAX_FRAME_SIZE - IXGBE_MTU_HDR) { | ||||
error = EINVAL; | error = EINVAL; | ||||
} else { | } else { | ||||
ifp->if_mtu = mtu; | ifp->if_mtu = mtu; | ||||
adapter->max_frame_size = ifp->if_mtu + IXGBE_MTU_HDR; | sc->max_frame_size = ifp->if_mtu + IXGBE_MTU_HDR; | ||||
} | } | ||||
return error; | return error; | ||||
} /* ixv_if_mtu_set */ | } /* ixv_if_mtu_set */ | ||||
/************************************************************************ | /************************************************************************ | ||||
* ixv_if_init - Init entry point | * ixv_if_init - Init entry point | ||||
* | * | ||||
* Used in two ways: It is used by the stack as an init entry | * Used in two ways: It is used by the stack as an init entry | ||||
* point in network interface structure. It is also used | * point in network interface structure. It is also used | ||||
* by the driver as a hw/sw initialization routine to get | * by the driver as a hw/sw initialization routine to get | ||||
* to a consistent state. | * to a consistent state. | ||||
* | * | ||||
* return 0 on success, positive on failure | * return 0 on success, positive on failure | ||||
************************************************************************/ | ************************************************************************/ | ||||
static void | static void | ||||
ixv_if_init(if_ctx_t ctx) | ixv_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; | ||||
int error = 0; | int error = 0; | ||||
INIT_DEBUGOUT("ixv_if_init: begin"); | INIT_DEBUGOUT("ixv_if_init: begin"); | ||||
hw->adapter_stopped = false; | hw->adapter_stopped = false; | ||||
hw->mac.ops.stop_adapter(hw); | hw->mac.ops.stop_adapter(hw); | ||||
/* reprogram the RAR[0] in case user changed it. */ | /* reprogram the RAR[0] in case user changed it. */ | ||||
hw->mac.ops.set_rar(hw, 0, hw->mac.addr, 0, IXGBE_RAH_AV); | hw->mac.ops.set_rar(hw, 0, hw->mac.addr, 0, 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); | ||||
hw->mac.ops.set_rar(hw, 0, hw->mac.addr, 0, 1); | hw->mac.ops.set_rar(hw, 0, hw->mac.addr, 0, 1); | ||||
/* Reset VF and renegotiate mailbox API version */ | /* Reset VF and renegotiate mailbox API version */ | ||||
hw->mac.ops.reset_hw(hw); | hw->mac.ops.reset_hw(hw); | ||||
hw->mac.ops.start_hw(hw); | hw->mac.ops.start_hw(hw); | ||||
error = ixv_negotiate_api(adapter); | error = ixv_negotiate_api(sc); | ||||
if (error) { | if (error) { | ||||
device_printf(dev, | device_printf(dev, | ||||
"Mailbox API negotiation failed in if_init!\n"); | "Mailbox API negotiation failed in if_init!\n"); | ||||
return; | return; | ||||
} | } | ||||
ixv_initialize_transmit_units(ctx); | ixv_initialize_transmit_units(ctx); | ||||
/* Setup Multicast table */ | /* Setup Multicast table */ | ||||
ixv_if_multi_set(ctx); | ixv_if_multi_set(ctx); | ||||
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 */ | ||||
ixv_initialize_receive_units(ctx); | ixv_initialize_receive_units(ctx); | ||||
/* Set up VLAN offload and filter */ | /* Set up VLAN offload and filter */ | ||||
ixv_setup_vlan_support(ctx); | ixv_setup_vlan_support(ctx); | ||||
/* Set up MSI-X routing */ | /* Set up MSI-X routing */ | ||||
ixv_configure_ivars(adapter); | ixv_configure_ivars(sc); | ||||
/* Set up auto-mask */ | /* Set up auto-mask */ | ||||
IXGBE_WRITE_REG(hw, IXGBE_VTEIAM, IXGBE_EICS_RTX_QUEUE); | IXGBE_WRITE_REG(hw, IXGBE_VTEIAM, IXGBE_EICS_RTX_QUEUE); | ||||
/* Set moderation on the Link interrupt */ | /* Set moderation on the Link interrupt */ | ||||
IXGBE_WRITE_REG(hw, IXGBE_VTEITR(adapter->vector), IXGBE_LINK_ITR); | IXGBE_WRITE_REG(hw, IXGBE_VTEITR(sc->vector), IXGBE_LINK_ITR); | ||||
/* Stats init */ | /* Stats init */ | ||||
ixv_init_stats(adapter); | ixv_init_stats(sc); | ||||
/* Config/Enable Link */ | /* Config/Enable Link */ | ||||
hw->mac.ops.check_link(hw, &adapter->link_speed, &adapter->link_up, | hw->mac.ops.check_link(hw, &sc->link_speed, &sc->link_up, | ||||
false); | false); | ||||
/* And now turn on interrupts */ | /* And now turn on interrupts */ | ||||
ixv_if_enable_intr(ctx); | ixv_if_enable_intr(ctx); | ||||
return; | return; | ||||
} /* ixv_if_init */ | } /* ixv_if_init */ | ||||
/************************************************************************ | /************************************************************************ | ||||
* ixv_enable_queue | * ixv_enable_queue | ||||
************************************************************************/ | ************************************************************************/ | ||||
static inline void | static inline void | ||||
ixv_enable_queue(struct adapter *adapter, u32 vector) | ixv_enable_queue(struct ixgbe_softc *sc, u32 vector) | ||||
{ | { | ||||
struct ixgbe_hw *hw = &adapter->hw; | struct ixgbe_hw *hw = &sc->hw; | ||||
u32 queue = 1 << vector; | u32 queue = 1 << vector; | ||||
u32 mask; | u32 mask; | ||||
mask = (IXGBE_EIMS_RTX_QUEUE & queue); | mask = (IXGBE_EIMS_RTX_QUEUE & queue); | ||||
IXGBE_WRITE_REG(hw, IXGBE_VTEIMS, mask); | IXGBE_WRITE_REG(hw, IXGBE_VTEIMS, mask); | ||||
} /* ixv_enable_queue */ | } /* ixv_enable_queue */ | ||||
/************************************************************************ | /************************************************************************ | ||||
* ixv_disable_queue | * ixv_disable_queue | ||||
************************************************************************/ | ************************************************************************/ | ||||
static inline void | static inline void | ||||
ixv_disable_queue(struct adapter *adapter, u32 vector) | ixv_disable_queue(struct ixgbe_softc *sc, u32 vector) | ||||
{ | { | ||||
struct ixgbe_hw *hw = &adapter->hw; | struct ixgbe_hw *hw = &sc->hw; | ||||
u64 queue = (u64)(1 << vector); | u64 queue = (u64)(1 << vector); | ||||
u32 mask; | u32 mask; | ||||
mask = (IXGBE_EIMS_RTX_QUEUE & queue); | mask = (IXGBE_EIMS_RTX_QUEUE & queue); | ||||
IXGBE_WRITE_REG(hw, IXGBE_VTEIMC, mask); | IXGBE_WRITE_REG(hw, IXGBE_VTEIMC, mask); | ||||
} /* ixv_disable_queue */ | } /* ixv_disable_queue */ | ||||
/************************************************************************ | /************************************************************************ | ||||
* ixv_msix_que - MSI-X Queue Interrupt Service routine | * ixv_msix_que - MSI-X Queue Interrupt Service routine | ||||
************************************************************************/ | ************************************************************************/ | ||||
static int | static int | ||||
ixv_msix_que(void *arg) | ixv_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; | ||||
ixv_disable_queue(adapter, que->msix); | ixv_disable_queue(sc, que->msix); | ||||
++que->irqs; | ++que->irqs; | ||||
return (FILTER_SCHEDULE_THREAD); | return (FILTER_SCHEDULE_THREAD); | ||||
} /* ixv_msix_que */ | } /* ixv_msix_que */ | ||||
/************************************************************************ | /************************************************************************ | ||||
* ixv_msix_mbx | * ixv_msix_mbx | ||||
************************************************************************/ | ************************************************************************/ | ||||
static int | static int | ||||
ixv_msix_mbx(void *arg) | ixv_msix_mbx(void *arg) | ||||
{ | { | ||||
struct adapter *adapter = arg; | struct ixgbe_softc *sc = arg; | ||||
struct ixgbe_hw *hw = &adapter->hw; | struct ixgbe_hw *hw = &sc->hw; | ||||
u32 reg; | u32 reg; | ||||
++adapter->link_irq; | ++sc->link_irq; | ||||
/* First get the cause */ | /* First get the cause */ | ||||
reg = IXGBE_READ_REG(hw, IXGBE_VTEICS); | reg = IXGBE_READ_REG(hw, IXGBE_VTEICS); | ||||
/* Clear interrupt with write */ | /* Clear interrupt with write */ | ||||
IXGBE_WRITE_REG(hw, IXGBE_VTEICR, reg); | IXGBE_WRITE_REG(hw, IXGBE_VTEICR, reg); | ||||
/* Link status change */ | /* Link status change */ | ||||
if (reg & IXGBE_EICR_LSC) | if (reg & IXGBE_EICR_LSC) | ||||
iflib_admin_intr_deferred(adapter->ctx); | iflib_admin_intr_deferred(sc->ctx); | ||||
IXGBE_WRITE_REG(hw, IXGBE_VTEIMS, IXGBE_EIMS_OTHER); | IXGBE_WRITE_REG(hw, IXGBE_VTEIMS, IXGBE_EIMS_OTHER); | ||||
return (FILTER_HANDLED); | return (FILTER_HANDLED); | ||||
} /* ixv_msix_mbx */ | } /* ixv_msix_mbx */ | ||||
/************************************************************************ | /************************************************************************ | ||||
* ixv_media_status - Media Ioctl callback | * ixv_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 | ||||
ixv_if_media_status(if_ctx_t ctx, struct ifmediareq * ifmr) | ixv_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); | ||||
INIT_DEBUGOUT("ixv_media_status: begin"); | INIT_DEBUGOUT("ixv_media_status: begin"); | ||||
iflib_admin_intr_deferred(ctx); | iflib_admin_intr_deferred(ctx); | ||||
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; | ||||
switch (adapter->link_speed) { | switch (sc->link_speed) { | ||||
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_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_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; | ||||
} | } | ||||
} /* ixv_if_media_status */ | } /* ixv_if_media_status */ | ||||
/************************************************************************ | /************************************************************************ | ||||
* ixv_if_media_change - Media Ioctl callback | * ixv_if_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 | ||||
ixv_if_media_change(if_ctx_t ctx) | ixv_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); | ||||
INIT_DEBUGOUT("ixv_media_change: begin"); | INIT_DEBUGOUT("ixv_media_change: begin"); | ||||
if (IFM_TYPE(ifm->ifm_media) != IFM_ETHER) | if (IFM_TYPE(ifm->ifm_media) != IFM_ETHER) | ||||
return (EINVAL); | return (EINVAL); | ||||
switch (IFM_SUBTYPE(ifm->ifm_media)) { | switch (IFM_SUBTYPE(ifm->ifm_media)) { | ||||
case IFM_AUTO: | case IFM_AUTO: | ||||
break; | break; | ||||
default: | default: | ||||
device_printf(adapter->dev, "Only auto media type\n"); | device_printf(sc->dev, "Only auto media type\n"); | ||||
return (EINVAL); | return (EINVAL); | ||||
} | } | ||||
return (0); | return (0); | ||||
} /* ixv_if_media_change */ | } /* ixv_if_media_change */ | ||||
/************************************************************************ | /************************************************************************ | ||||
* ixv_negotiate_api | * ixv_negotiate_api | ||||
* | * | ||||
* Negotiate the Mailbox API with the PF; | * Negotiate the Mailbox API with the PF; | ||||
* start with the most featured API first. | * start with the most featured API first. | ||||
************************************************************************/ | ************************************************************************/ | ||||
static int | static int | ||||
ixv_negotiate_api(struct adapter *adapter) | ixv_negotiate_api(struct ixgbe_softc *sc) | ||||
{ | { | ||||
struct ixgbe_hw *hw = &adapter->hw; | struct ixgbe_hw *hw = &sc->hw; | ||||
int mbx_api[] = { ixgbe_mbox_api_11, | int mbx_api[] = { ixgbe_mbox_api_11, | ||||
ixgbe_mbox_api_10, | ixgbe_mbox_api_10, | ||||
ixgbe_mbox_api_unknown }; | ixgbe_mbox_api_unknown }; | ||||
int i = 0; | int i = 0; | ||||
while (mbx_api[i] != ixgbe_mbox_api_unknown) { | while (mbx_api[i] != ixgbe_mbox_api_unknown) { | ||||
if (ixgbevf_negotiate_api_version(hw, mbx_api[i]) == 0) | if (ixgbevf_negotiate_api_version(hw, mbx_api[i]) == 0) | ||||
return (0); | return (0); | ||||
i++; | i++; | ||||
} | } | ||||
return (EINVAL); | return (EINVAL); | ||||
} /* ixv_negotiate_api */ | } /* ixv_negotiate_api */ | ||||
/************************************************************************ | /************************************************************************ | ||||
* ixv_if_multi_set - Multicast Update | * ixv_if_multi_set - Multicast Update | ||||
* | * | ||||
* Called whenever multicast address list is updated. | * Called whenever multicast address list is updated. | ||||
************************************************************************/ | ************************************************************************/ | ||||
static void | static void | ||||
ixv_if_multi_set(if_ctx_t ctx) | ixv_if_multi_set(if_ctx_t ctx) | ||||
{ | { | ||||
u8 mta[MAX_NUM_MULTICAST_ADDRESSES * IXGBE_ETH_LENGTH_OF_ADDRESS]; | u8 mta[MAX_NUM_MULTICAST_ADDRESSES * IXGBE_ETH_LENGTH_OF_ADDRESS]; | ||||
struct adapter *adapter = iflib_get_softc(ctx); | struct ixgbe_softc *sc = iflib_get_softc(ctx); | ||||
u8 *update_ptr; | u8 *update_ptr; | ||||
struct ifmultiaddr *ifma; | struct ifmultiaddr *ifma; | ||||
if_t ifp = iflib_get_ifp(ctx); | if_t ifp = iflib_get_ifp(ctx); | ||||
int mcnt = 0; | int mcnt = 0; | ||||
IOCTL_DEBUGOUT("ixv_if_multi_set: begin"); | IOCTL_DEBUGOUT("ixv_if_multi_set: begin"); | ||||
CK_STAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { | CK_STAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { | ||||
if (ifma->ifma_addr->sa_family != AF_LINK) | if (ifma->ifma_addr->sa_family != AF_LINK) | ||||
continue; | continue; | ||||
bcopy(LLADDR((struct sockaddr_dl *)ifma->ifma_addr), | bcopy(LLADDR((struct sockaddr_dl *)ifma->ifma_addr), | ||||
&mta[mcnt * IXGBE_ETH_LENGTH_OF_ADDRESS], | &mta[mcnt * IXGBE_ETH_LENGTH_OF_ADDRESS], | ||||
IXGBE_ETH_LENGTH_OF_ADDRESS); | IXGBE_ETH_LENGTH_OF_ADDRESS); | ||||
mcnt++; | mcnt++; | ||||
} | } | ||||
update_ptr = mta; | update_ptr = mta; | ||||
adapter->hw.mac.ops.update_mc_addr_list(&adapter->hw, update_ptr, mcnt, | sc->hw.mac.ops.update_mc_addr_list(&sc->hw, update_ptr, mcnt, | ||||
ixv_mc_array_itr, true); | ixv_mc_array_itr, true); | ||||
} /* ixv_if_multi_set */ | } /* ixv_if_multi_set */ | ||||
/************************************************************************ | /************************************************************************ | ||||
* ixv_mc_array_itr | * ixv_mc_array_itr | ||||
* | * | ||||
* An iterator function needed by the multicast shared code. | * An iterator function needed by the multicast shared code. | ||||
* It feeds the shared code routine the addresses in the | * It feeds the shared code routine the addresses in the | ||||
Show All 34 Lines | |||||
* | * | ||||
* 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 | ||||
ixv_if_update_admin_status(if_ctx_t ctx) | ixv_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); | ||||
s32 status; | s32 status; | ||||
adapter->hw.mac.get_link_status = true; | sc->hw.mac.get_link_status = true; | ||||
status = ixgbe_check_link(&adapter->hw, &adapter->link_speed, | status = ixgbe_check_link(&sc->hw, &sc->link_speed, | ||||
&adapter->link_up, false); | &sc->link_up, false); | ||||
if (status != IXGBE_SUCCESS && adapter->hw.adapter_stopped == false) { | if (status != IXGBE_SUCCESS && sc->hw.adapter_stopped == false) { | ||||
/* Mailbox's Clear To Send status is lost or timeout occurred. | /* Mailbox's Clear To Send status is lost or timeout occurred. | ||||
* We need reinitialization. */ | * We need reinitialization. */ | ||||
iflib_get_ifp(ctx)->if_init(ctx); | iflib_get_ifp(ctx)->if_init(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; | ||||
iflib_link_state_change(ctx, LINK_STATE_UP, | iflib_link_state_change(ctx, LINK_STATE_UP, | ||||
IF_Gbps(10)); | IF_Gbps(10)); | ||||
} | } | ||||
} 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; | ||||
} | } | ||||
} | } | ||||
/* Stats Update */ | /* Stats Update */ | ||||
ixv_update_stats(adapter); | ixv_update_stats(sc); | ||||
} /* ixv_if_update_admin_status */ | } /* ixv_if_update_admin_status */ | ||||
/************************************************************************ | /************************************************************************ | ||||
* ixv_if_stop - Stop the hardware | * ixv_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 | ||||
ixv_if_stop(if_ctx_t ctx) | ixv_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("ixv_stop: begin\n"); | INIT_DEBUGOUT("ixv_stop: begin\n"); | ||||
ixv_if_disable_intr(ctx); | ixv_if_disable_intr(ctx); | ||||
hw->mac.ops.reset_hw(hw); | hw->mac.ops.reset_hw(hw); | ||||
adapter->hw.adapter_stopped = false; | sc->hw.adapter_stopped = false; | ||||
hw->mac.ops.stop_adapter(hw); | hw->mac.ops.stop_adapter(hw); | ||||
/* Update the stack */ | /* Update the stack */ | ||||
adapter->link_up = false; | sc->link_up = false; | ||||
ixv_if_update_admin_status(ctx); | ixv_if_update_admin_status(ctx); | ||||
/* reprogram the RAR[0] in case user changed it. */ | /* reprogram the RAR[0] in case user changed it. */ | ||||
hw->mac.ops.set_rar(hw, 0, hw->mac.addr, 0, IXGBE_RAH_AV); | hw->mac.ops.set_rar(hw, 0, hw->mac.addr, 0, IXGBE_RAH_AV); | ||||
} /* ixv_if_stop */ | } /* ixv_if_stop */ | ||||
/************************************************************************ | /************************************************************************ | ||||
* ixv_identify_hardware - Determine hardware revision. | * ixv_identify_hardware - Determine hardware revision. | ||||
************************************************************************/ | ************************************************************************/ | ||||
static void | static void | ||||
ixv_identify_hardware(if_ctx_t ctx) | ixv_identify_hardware(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; | ||||
/* Save off the information about this board */ | /* Save off the information about this board */ | ||||
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 22 Lines | |||||
} /* ixv_identify_hardware */ | } /* ixv_identify_hardware */ | ||||
/************************************************************************ | /************************************************************************ | ||||
* ixv_if_msix_intr_assign - Setup MSI-X Interrupt resources and handlers | * ixv_if_msix_intr_assign - Setup MSI-X Interrupt resources and handlers | ||||
************************************************************************/ | ************************************************************************/ | ||||
static int | static int | ||||
ixv_if_msix_intr_assign(if_ctx_t ctx, int msix) | ixv_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); | ||||
device_t dev = iflib_get_dev(ctx); | device_t dev = iflib_get_dev(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; | ||||
char buf[16]; | char buf[16]; | ||||
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, ixv_msix_que, rx_que, rx_que->rxr.me, buf); | IFLIB_INTR_RXTX, ixv_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; | ||||
} | } | ||||
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, ixv_msix_mbx, adapter, 0, "aq"); | IFLIB_INTR_ADMIN, ixv_msix_mbx, 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; | ||||
/* | /* | ||||
* Due to a broken design QEMU will fail to properly | * Due to a broken design QEMU will fail to properly | ||||
* enable the guest for MSIX unless the vectors in | * enable the guest for MSIX unless the vectors in | ||||
* the table are all set up, so we must rewrite the | * the table are all set up, so we must rewrite the | ||||
* ENABLE in the MSIX control register again at this | * ENABLE in the MSIX control register again at this | ||||
* point to cause it to successfully initialize us. | * point to cause it to successfully initialize us. | ||||
*/ | */ | ||||
if (adapter->hw.mac.type == ixgbe_mac_82599_vf) { | if (sc->hw.mac.type == ixgbe_mac_82599_vf) { | ||||
int msix_ctrl; | int msix_ctrl; | ||||
pci_find_cap(dev, PCIY_MSIX, &rid); | pci_find_cap(dev, PCIY_MSIX, &rid); | ||||
rid += PCIR_MSIX_CTRL; | rid += PCIR_MSIX_CTRL; | ||||
msix_ctrl = pci_read_config(dev, rid, 2); | msix_ctrl = pci_read_config(dev, rid, 2); | ||||
msix_ctrl |= PCIM_MSIXCTRL_MSIX_ENABLE; | msix_ctrl |= PCIM_MSIXCTRL_MSIX_ENABLE; | ||||
pci_write_config(dev, rid, msix_ctrl, 2); | pci_write_config(dev, rid, msix_ctrl, 2); | ||||
} | } | ||||
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); | ||||
} /* ixv_if_msix_intr_assign */ | } /* ixv_if_msix_intr_assign */ | ||||
/************************************************************************ | /************************************************************************ | ||||
* ixv_allocate_pci_resources | * ixv_allocate_pci_resources | ||||
************************************************************************/ | ************************************************************************/ | ||||
static int | static int | ||||
ixv_allocate_pci_resources(if_ctx_t ctx) | ixv_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); | ||||
} | } | ||||
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); | ||||
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); | ||||
} /* ixv_allocate_pci_resources */ | } /* ixv_allocate_pci_resources */ | ||||
/************************************************************************ | /************************************************************************ | ||||
* ixv_free_pci_resources | * ixv_free_pci_resources | ||||
************************************************************************/ | ************************************************************************/ | ||||
static void | static void | ||||
ixv_free_pci_resources(if_ctx_t ctx) | ixv_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); | ||||
} /* ixv_free_pci_resources */ | } /* ixv_free_pci_resources */ | ||||
/************************************************************************ | /************************************************************************ | ||||
* ixv_setup_interface | * ixv_setup_interface | ||||
* | * | ||||
* Setup networking device structure and register an interface. | * Setup networking device structure and register an interface. | ||||
************************************************************************/ | ************************************************************************/ | ||||
static int | static int | ||||
ixv_setup_interface(if_ctx_t ctx) | ixv_setup_interface(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 ifnet *ifp = iflib_get_ifp(ctx); | struct ifnet *ifp = iflib_get_ifp(ctx); | ||||
INIT_DEBUGOUT("ixv_setup_interface: begin"); | INIT_DEBUGOUT("ixv_setup_interface: begin"); | ||||
if_setbaudrate(ifp, IF_Gbps(10)); | if_setbaudrate(ifp, IF_Gbps(10)); | ||||
ifp->if_snd.ifq_maxlen = scctx->isc_ntxd[0] - 2; | ifp->if_snd.ifq_maxlen = scctx->isc_ntxd[0] - 2; | ||||
adapter->max_frame_size = ifp->if_mtu + IXGBE_MTU_HDR; | sc->max_frame_size = ifp->if_mtu + IXGBE_MTU_HDR; | ||||
ifmedia_add(adapter->media, IFM_ETHER | IFM_AUTO, 0, NULL); | ifmedia_add(sc->media, IFM_ETHER | IFM_AUTO, 0, NULL); | ||||
ifmedia_set(adapter->media, IFM_ETHER | IFM_AUTO); | ifmedia_set(sc->media, IFM_ETHER | IFM_AUTO); | ||||
return 0; | return 0; | ||||
} /* ixv_setup_interface */ | } /* ixv_setup_interface */ | ||||
/************************************************************************ | /************************************************************************ | ||||
* ixv_if_get_counter | * ixv_if_get_counter | ||||
************************************************************************/ | ************************************************************************/ | ||||
static uint64_t | static uint64_t | ||||
ixv_if_get_counter(if_ctx_t ctx, ift_counter cnt) | ixv_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); | ||||
default: | default: | ||||
return (if_get_counter_default(ifp, cnt)); | return (if_get_counter_default(ifp, cnt)); | ||||
} | } | ||||
} /* ixv_if_get_counter */ | } /* ixv_if_get_counter */ | ||||
/* ixv_if_needs_restart - Tell iflib when the driver needs to be reinitialized | /* ixv_if_needs_restart - Tell iflib when the driver needs to be reinitialized | ||||
* @ctx: iflib context | * @ctx: iflib context | ||||
* @event: event code to check | * @event: event code to check | ||||
Show All 14 Lines | |||||
} | } | ||||
/************************************************************************ | /************************************************************************ | ||||
* ixv_initialize_transmit_units - Enable transmit unit. | * ixv_initialize_transmit_units - Enable transmit unit. | ||||
************************************************************************/ | ************************************************************************/ | ||||
static void | static void | ||||
ixv_initialize_transmit_units(if_ctx_t ctx) | ixv_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 = adapter->tx_queues; | struct ix_tx_queue *que = sc->tx_queues; | ||||
int i; | int i; | ||||
for (i = 0; i < adapter->num_tx_queues; i++, que++) { | for (i = 0; i < sc->num_tx_queues; 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, txdctl; | u32 txctrl, txdctl; | ||||
int j = txr->me; | int j = txr->me; | ||||
/* Set WTHRESH to 8, burst writeback */ | /* Set WTHRESH to 8, burst writeback */ | ||||
txdctl = IXGBE_READ_REG(hw, IXGBE_VFTXDCTL(j)); | txdctl = IXGBE_READ_REG(hw, IXGBE_VFTXDCTL(j)); | ||||
txdctl |= (8 << 16); | txdctl |= (8 << 16); | ||||
IXGBE_WRITE_REG(hw, IXGBE_VFTXDCTL(j), txdctl); | IXGBE_WRITE_REG(hw, IXGBE_VFTXDCTL(j), txdctl); | ||||
/* Set the HW Tx Head and Tail indices */ | /* Set the HW Tx Head and Tail indices */ | ||||
IXGBE_WRITE_REG(&adapter->hw, IXGBE_VFTDH(j), 0); | IXGBE_WRITE_REG(&sc->hw, IXGBE_VFTDH(j), 0); | ||||
IXGBE_WRITE_REG(&adapter->hw, IXGBE_VFTDT(j), 0); | IXGBE_WRITE_REG(&sc->hw, IXGBE_VFTDT(j), 0); | ||||
/* Set Tx Tail register */ | /* Set Tx Tail register */ | ||||
txr->tail = IXGBE_VFTDT(j); | txr->tail = IXGBE_VFTDT(j); | ||||
txr->tx_rs_cidx = txr->tx_rs_pidx; | txr->tx_rs_cidx = txr->tx_rs_pidx; | ||||
/* Initialize the last processed descriptor to be the end of | /* Initialize the last processed descriptor to be the end of | ||||
* the ring, rather than the start, so that we avoid an | * the ring, rather than the start, so that we avoid an | ||||
* off-by-one error when calculating how many descriptors are | * off-by-one error when calculating how many descriptors are | ||||
Show All 21 Lines | ixv_initialize_transmit_units(if_ctx_t ctx) | ||||
return; | return; | ||||
} /* ixv_initialize_transmit_units */ | } /* ixv_initialize_transmit_units */ | ||||
/************************************************************************ | /************************************************************************ | ||||
* ixv_initialize_rss_mapping | * ixv_initialize_rss_mapping | ||||
************************************************************************/ | ************************************************************************/ | ||||
static void | static void | ||||
ixv_initialize_rss_mapping(struct adapter *adapter) | ixv_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; | int queue_id; | ||||
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); | ||||
} | } | ||||
/* Now fill out hash function seeds */ | /* Now fill out hash function seeds */ | ||||
for (i = 0; i < 10; i++) | for (i = 0; i < 10; i++) | ||||
IXGBE_WRITE_REG(hw, IXGBE_VFRSSRK(i), rss_key[i]); | IXGBE_WRITE_REG(hw, IXGBE_VFRSSRK(i), rss_key[i]); | ||||
/* Set up the redirection table */ | /* Set up the redirection table */ | ||||
for (i = 0, j = 0; i < 64; i++, j++) { | for (i = 0, j = 0; i < 64; 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; | queue_id = j; | ||||
/* | /* | ||||
* 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 >>= 8; | reta >>= 8; | ||||
reta |= ((uint32_t)queue_id) << 24; | reta |= ((uint32_t)queue_id) << 24; | ||||
if ((i & 3) == 3) { | if ((i & 3) == 3) { | ||||
IXGBE_WRITE_REG(hw, IXGBE_VFRETA(i >> 2), reta); | IXGBE_WRITE_REG(hw, IXGBE_VFRETA(i >> 2), reta); | ||||
reta = 0; | reta = 0; | ||||
} | } | ||||
} | } | ||||
/* 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 | ||||
| RSS_HASHTYPE_RSS_TCP_IPV4 | | RSS_HASHTYPE_RSS_TCP_IPV4 | ||||
| RSS_HASHTYPE_RSS_IPV6 | | RSS_HASHTYPE_RSS_IPV6 | ||||
| RSS_HASHTYPE_RSS_TCP_IPV6; | | RSS_HASHTYPE_RSS_TCP_IPV6; | ||||
} | } | ||||
mrqc = IXGBE_MRQC_RSSEN; | mrqc = IXGBE_MRQC_RSSEN; | ||||
if (rss_hash_config & RSS_HASHTYPE_RSS_IPV4) | if (rss_hash_config & RSS_HASHTYPE_RSS_IPV4) | ||||
mrqc |= IXGBE_MRQC_RSS_FIELD_IPV4; | mrqc |= IXGBE_MRQC_RSS_FIELD_IPV4; | ||||
if (rss_hash_config & RSS_HASHTYPE_RSS_TCP_IPV4) | if (rss_hash_config & RSS_HASHTYPE_RSS_TCP_IPV4) | ||||
mrqc |= IXGBE_MRQC_RSS_FIELD_IPV4_TCP; | mrqc |= IXGBE_MRQC_RSS_FIELD_IPV4_TCP; | ||||
if (rss_hash_config & RSS_HASHTYPE_RSS_IPV6) | if (rss_hash_config & RSS_HASHTYPE_RSS_IPV6) | ||||
mrqc |= IXGBE_MRQC_RSS_FIELD_IPV6; | mrqc |= IXGBE_MRQC_RSS_FIELD_IPV6; | ||||
if (rss_hash_config & RSS_HASHTYPE_RSS_TCP_IPV6) | if (rss_hash_config & RSS_HASHTYPE_RSS_TCP_IPV6) | ||||
mrqc |= IXGBE_MRQC_RSS_FIELD_IPV6_TCP; | mrqc |= IXGBE_MRQC_RSS_FIELD_IPV6_TCP; | ||||
if (rss_hash_config & RSS_HASHTYPE_RSS_IPV6_EX) | if (rss_hash_config & RSS_HASHTYPE_RSS_IPV6_EX) | ||||
device_printf(adapter->dev, "%s: RSS_HASHTYPE_RSS_IPV6_EX defined, but not supported\n", | device_printf(sc->dev, "%s: RSS_HASHTYPE_RSS_IPV6_EX defined, but not supported\n", | ||||
__func__); | __func__); | ||||
if (rss_hash_config & RSS_HASHTYPE_RSS_TCP_IPV6_EX) | if (rss_hash_config & RSS_HASHTYPE_RSS_TCP_IPV6_EX) | ||||
device_printf(adapter->dev, "%s: RSS_HASHTYPE_RSS_TCP_IPV6_EX defined, but not supported\n", | device_printf(sc->dev, "%s: RSS_HASHTYPE_RSS_TCP_IPV6_EX defined, but not supported\n", | ||||
__func__); | __func__); | ||||
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) | ||||
device_printf(adapter->dev, "%s: RSS_HASHTYPE_RSS_UDP_IPV6_EX defined, but not supported\n", | device_printf(sc->dev, "%s: RSS_HASHTYPE_RSS_UDP_IPV6_EX defined, but not supported\n", | ||||
__func__); | __func__); | ||||
IXGBE_WRITE_REG(hw, IXGBE_VFMRQC, mrqc); | IXGBE_WRITE_REG(hw, IXGBE_VFMRQC, mrqc); | ||||
} /* ixv_initialize_rss_mapping */ | } /* ixv_initialize_rss_mapping */ | ||||
/************************************************************************ | /************************************************************************ | ||||
* ixv_initialize_receive_units - Setup receive registers and features. | * ixv_initialize_receive_units - Setup receive registers and features. | ||||
************************************************************************/ | ************************************************************************/ | ||||
static void | static void | ||||
ixv_initialize_receive_units(if_ctx_t ctx) | ixv_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; | if_softc_ctx_t scctx; | ||||
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 = adapter->rx_queues; | struct ix_rx_queue *que = sc->rx_queues; | ||||
u32 bufsz, psrtype; | u32 bufsz, psrtype; | ||||
if (ifp->if_mtu > ETHERMTU) | if (ifp->if_mtu > ETHERMTU) | ||||
bufsz = 4096 >> IXGBE_SRRCTL_BSIZEPKT_SHIFT; | bufsz = 4096 >> IXGBE_SRRCTL_BSIZEPKT_SHIFT; | ||||
else | else | ||||
bufsz = 2048 >> IXGBE_SRRCTL_BSIZEPKT_SHIFT; | bufsz = 2048 >> IXGBE_SRRCTL_BSIZEPKT_SHIFT; | ||||
psrtype = IXGBE_PSRTYPE_TCPHDR | psrtype = IXGBE_PSRTYPE_TCPHDR | ||||
| IXGBE_PSRTYPE_UDPHDR | | IXGBE_PSRTYPE_UDPHDR | ||||
| IXGBE_PSRTYPE_IPV4HDR | | IXGBE_PSRTYPE_IPV4HDR | ||||
| IXGBE_PSRTYPE_IPV6HDR | | IXGBE_PSRTYPE_IPV6HDR | ||||
| IXGBE_PSRTYPE_L2HDR; | | IXGBE_PSRTYPE_L2HDR; | ||||
if (adapter->num_rx_queues > 1) | if (sc->num_rx_queues > 1) | ||||
psrtype |= 1 << 29; | psrtype |= 1 << 29; | ||||
IXGBE_WRITE_REG(hw, IXGBE_VFPSRTYPE, psrtype); | IXGBE_WRITE_REG(hw, IXGBE_VFPSRTYPE, psrtype); | ||||
/* Tell PF our max_frame size */ | /* Tell PF our max_frame size */ | ||||
if (ixgbevf_rlpml_set_vf(hw, adapter->max_frame_size) != 0) { | if (ixgbevf_rlpml_set_vf(hw, sc->max_frame_size) != 0) { | ||||
device_printf(adapter->dev, "There is a problem with the PF setup. It is likely the receive unit for this VF will not function correctly.\n"); | device_printf(sc->dev, "There is a problem with the PF setup. It is likely the receive unit for this VF will not function correctly.\n"); | ||||
} | } | ||||
scctx = adapter->shared; | scctx = sc->shared; | ||||
for (int i = 0; i < adapter->num_rx_queues; i++, que++) { | for (int i = 0; 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; | ||||
u32 reg, rxdctl; | u32 reg, rxdctl; | ||||
int j = rxr->me; | int j = rxr->me; | ||||
/* Disable the queue */ | /* Disable the queue */ | ||||
rxdctl = IXGBE_READ_REG(hw, IXGBE_VFRXDCTL(j)); | rxdctl = IXGBE_READ_REG(hw, IXGBE_VFRXDCTL(j)); | ||||
rxdctl &= ~IXGBE_RXDCTL_ENABLE; | rxdctl &= ~IXGBE_RXDCTL_ENABLE; | ||||
▲ Show 20 Lines • Show All 68 Lines • ▼ Show 20 Lines | #endif /* DEV_NETMAP */ | ||||
IXGBE_WRITE_REG(hw, IXGBE_VFRDT(rxr->me), | IXGBE_WRITE_REG(hw, IXGBE_VFRDT(rxr->me), | ||||
scctx->isc_nrxd[0] - 1); | scctx->isc_nrxd[0] - 1); | ||||
} | } | ||||
/* | /* | ||||
* Do not touch RSS and RETA settings for older hardware | * Do not touch RSS and RETA settings for older hardware | ||||
* as those are shared among PF and all VF. | * as those are shared among PF and all VF. | ||||
*/ | */ | ||||
if (adapter->hw.mac.type >= ixgbe_mac_X550_vf) | if (sc->hw.mac.type >= ixgbe_mac_X550_vf) | ||||
ixv_initialize_rss_mapping(adapter); | ixv_initialize_rss_mapping(sc); | ||||
} /* ixv_initialize_receive_units */ | } /* ixv_initialize_receive_units */ | ||||
/************************************************************************ | /************************************************************************ | ||||
* ixv_setup_vlan_support | * ixv_setup_vlan_support | ||||
************************************************************************/ | ************************************************************************/ | ||||
static void | static void | ||||
ixv_setup_vlan_support(if_ctx_t ctx) | ixv_setup_vlan_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; | ||||
u32 ctrl, vid, vfta, retry; | u32 ctrl, vid, vfta, retry; | ||||
/* | /* | ||||
* We get here thru if_init, meaning | * We get here thru if_init, 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; | ||||
if (ifp->if_capenable & IFCAP_VLAN_HWTAGGING) { | if (ifp->if_capenable & IFCAP_VLAN_HWTAGGING) { | ||||
/* Enable the queues */ | /* Enable the queues */ | ||||
for (int i = 0; i < adapter->num_rx_queues; i++) { | for (int i = 0; i < sc->num_rx_queues; i++) { | ||||
ctrl = IXGBE_READ_REG(hw, IXGBE_VFRXDCTL(i)); | ctrl = IXGBE_READ_REG(hw, IXGBE_VFRXDCTL(i)); | ||||
ctrl |= IXGBE_RXDCTL_VME; | ctrl |= IXGBE_RXDCTL_VME; | ||||
IXGBE_WRITE_REG(hw, IXGBE_VFRXDCTL(i), ctrl); | IXGBE_WRITE_REG(hw, IXGBE_VFRXDCTL(i), ctrl); | ||||
/* | /* | ||||
* Let Rx path know that it needs to store VLAN tag | * Let Rx path know that it needs to store VLAN tag | ||||
* as part of extra mbuf info. | * as part of extra mbuf info. | ||||
*/ | */ | ||||
adapter->rx_queues[i].rxr.vtag_strip = true; | sc->rx_queues[i].rxr.vtag_strip = true; | ||||
} | } | ||||
} | } | ||||
/* | /* | ||||
* If filtering VLAN tags is disabled, | * If filtering VLAN tags is disabled, | ||||
* there is no need to fill VLAN Filter Table Array (VFTA). | * there is no need to fill VLAN Filter Table Array (VFTA). | ||||
*/ | */ | ||||
if ((ifp->if_capenable & IFCAP_VLAN_HWFILTER) == 0) | if ((ifp->if_capenable & IFCAP_VLAN_HWFILTER) == 0) | ||||
Show All 32 Lines | |||||
* Run via a vlan config EVENT, it enables us to use the | * Run via a vlan config EVENT, it enables us to use the | ||||
* HW Filter table since we can get the vlan id. This just | * HW Filter table since we can get the vlan id. This just | ||||
* creates the entry in the soft version of the VFTA, init | * creates the entry in the soft version of the VFTA, init | ||||
* will repopulate the real table. | * will repopulate the real table. | ||||
************************************************************************/ | ************************************************************************/ | ||||
static void | static void | ||||
ixv_if_register_vlan(if_ctx_t ctx, u16 vtag) | ixv_if_register_vlan(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; | ||||
ixv_shadow_vfta[index] |= (1 << bit); | ixv_shadow_vfta[index] |= (1 << bit); | ||||
++adapter->num_vlans; | ++sc->num_vlans; | ||||
} /* ixv_if_register_vlan */ | } /* ixv_if_register_vlan */ | ||||
/************************************************************************ | /************************************************************************ | ||||
* ixv_if_unregister_vlan | * ixv_if_unregister_vlan | ||||
* | * | ||||
* Run via a vlan unconfig EVENT, remove our entry | * Run via a vlan unconfig EVENT, remove our entry | ||||
* in the soft vfta. | * in the soft vfta. | ||||
************************************************************************/ | ************************************************************************/ | ||||
static void | static void | ||||
ixv_if_unregister_vlan(if_ctx_t ctx, u16 vtag) | ixv_if_unregister_vlan(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; | ||||
ixv_shadow_vfta[index] &= ~(1 << bit); | ixv_shadow_vfta[index] &= ~(1 << bit); | ||||
--adapter->num_vlans; | --sc->num_vlans; | ||||
} /* ixv_if_unregister_vlan */ | } /* ixv_if_unregister_vlan */ | ||||
/************************************************************************ | /************************************************************************ | ||||
* ixv_if_enable_intr | * ixv_if_enable_intr | ||||
************************************************************************/ | ************************************************************************/ | ||||
static void | static void | ||||
ixv_if_enable_intr(if_ctx_t ctx) | ixv_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 = (IXGBE_EIMS_ENABLE_MASK & ~IXGBE_EIMS_RTX_QUEUE); | u32 mask = (IXGBE_EIMS_ENABLE_MASK & ~IXGBE_EIMS_RTX_QUEUE); | ||||
IXGBE_WRITE_REG(hw, IXGBE_VTEIMS, mask); | IXGBE_WRITE_REG(hw, IXGBE_VTEIMS, mask); | ||||
mask = IXGBE_EIMS_ENABLE_MASK; | mask = IXGBE_EIMS_ENABLE_MASK; | ||||
mask &= ~(IXGBE_EIMS_OTHER | IXGBE_EIMS_LSC); | mask &= ~(IXGBE_EIMS_OTHER | IXGBE_EIMS_LSC); | ||||
IXGBE_WRITE_REG(hw, IXGBE_VTEIAC, mask); | IXGBE_WRITE_REG(hw, IXGBE_VTEIAC, mask); | ||||
for (int i = 0; i < adapter->num_rx_queues; i++, que++) | for (int i = 0; i < sc->num_rx_queues; i++, que++) | ||||
ixv_enable_queue(adapter, que->msix); | ixv_enable_queue(sc, que->msix); | ||||
IXGBE_WRITE_FLUSH(hw); | IXGBE_WRITE_FLUSH(hw); | ||||
} /* ixv_if_enable_intr */ | } /* ixv_if_enable_intr */ | ||||
/************************************************************************ | /************************************************************************ | ||||
* ixv_if_disable_intr | * ixv_if_disable_intr | ||||
************************************************************************/ | ************************************************************************/ | ||||
static void | static void | ||||
ixv_if_disable_intr(if_ctx_t ctx) | ixv_if_disable_intr(if_ctx_t ctx) | ||||
{ | { | ||||
struct adapter *adapter = iflib_get_softc(ctx); | struct ixgbe_softc *sc = iflib_get_softc(ctx); | ||||
IXGBE_WRITE_REG(&adapter->hw, IXGBE_VTEIAC, 0); | IXGBE_WRITE_REG(&sc->hw, IXGBE_VTEIAC, 0); | ||||
IXGBE_WRITE_REG(&adapter->hw, IXGBE_VTEIMC, ~0); | IXGBE_WRITE_REG(&sc->hw, IXGBE_VTEIMC, ~0); | ||||
IXGBE_WRITE_FLUSH(&adapter->hw); | IXGBE_WRITE_FLUSH(&sc->hw); | ||||
} /* ixv_if_disable_intr */ | } /* ixv_if_disable_intr */ | ||||
/************************************************************************ | /************************************************************************ | ||||
* ixv_if_rx_queue_intr_enable | * ixv_if_rx_queue_intr_enable | ||||
************************************************************************/ | ************************************************************************/ | ||||
static int | static int | ||||
ixv_if_rx_queue_intr_enable(if_ctx_t ctx, uint16_t rxqid) | ixv_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]; | ||||
ixv_enable_queue(adapter, que->rxr.me); | ixv_enable_queue(sc, que->rxr.me); | ||||
return (0); | return (0); | ||||
} /* ixv_if_rx_queue_intr_enable */ | } /* ixv_if_rx_queue_intr_enable */ | ||||
/************************************************************************ | /************************************************************************ | ||||
* ixv_set_ivar | * ixv_set_ivar | ||||
* | * | ||||
* Setup the correct IVAR register for a particular MSI-X interrupt | * Setup the correct IVAR register for a particular MSI-X interrupt | ||||
* - 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 | ||||
ixv_set_ivar(struct adapter *adapter, u8 entry, u8 vector, s8 type) | ixv_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; | ||||
if (type == -1) { /* MISC IVAR */ | if (type == -1) { /* MISC IVAR */ | ||||
ivar = IXGBE_READ_REG(hw, IXGBE_VTIVAR_MISC); | ivar = IXGBE_READ_REG(hw, IXGBE_VTIVAR_MISC); | ||||
ivar &= ~0xFF; | ivar &= ~0xFF; | ||||
ivar |= vector; | ivar |= vector; | ||||
IXGBE_WRITE_REG(hw, IXGBE_VTIVAR_MISC, ivar); | IXGBE_WRITE_REG(hw, IXGBE_VTIVAR_MISC, ivar); | ||||
} else { /* RX/TX IVARS */ | } else { /* RX/TX IVARS */ | ||||
index = (16 * (entry & 1)) + (8 * type); | index = (16 * (entry & 1)) + (8 * type); | ||||
ivar = IXGBE_READ_REG(hw, IXGBE_VTIVAR(entry >> 1)); | ivar = IXGBE_READ_REG(hw, IXGBE_VTIVAR(entry >> 1)); | ||||
ivar &= ~(0xFF << index); | ivar &= ~(0xFF << index); | ||||
ivar |= (vector << index); | ivar |= (vector << index); | ||||
IXGBE_WRITE_REG(hw, IXGBE_VTIVAR(entry >> 1), ivar); | IXGBE_WRITE_REG(hw, IXGBE_VTIVAR(entry >> 1), ivar); | ||||
} | } | ||||
} /* ixv_set_ivar */ | } /* ixv_set_ivar */ | ||||
/************************************************************************ | /************************************************************************ | ||||
* ixv_configure_ivars | * ixv_configure_ivars | ||||
************************************************************************/ | ************************************************************************/ | ||||
static void | static void | ||||
ixv_configure_ivars(struct adapter *adapter) | ixv_configure_ivars(struct ixgbe_softc *sc) | ||||
{ | { | ||||
struct ix_rx_queue *que = adapter->rx_queues; | struct ix_rx_queue *que = sc->rx_queues; | ||||
MPASS(adapter->num_rx_queues == adapter->num_tx_queues); | MPASS(sc->num_rx_queues == sc->num_tx_queues); | ||||
for (int i = 0; i < adapter->num_rx_queues; i++, que++) { | for (int i = 0; i < sc->num_rx_queues; i++, que++) { | ||||
/* First the RX queue entry */ | /* First the RX queue entry */ | ||||
ixv_set_ivar(adapter, i, que->msix, 0); | ixv_set_ivar(sc, i, que->msix, 0); | ||||
/* ... and the TX */ | /* ... and the TX */ | ||||
ixv_set_ivar(adapter, i, que->msix, 1); | ixv_set_ivar(sc, i, que->msix, 1); | ||||
/* Set an initial value in EITR */ | /* Set an initial value in EITR */ | ||||
IXGBE_WRITE_REG(&adapter->hw, IXGBE_VTEITR(que->msix), | IXGBE_WRITE_REG(&sc->hw, IXGBE_VTEITR(que->msix), | ||||
IXGBE_EITR_DEFAULT); | IXGBE_EITR_DEFAULT); | ||||
} | } | ||||
/* For the mailbox interrupt */ | /* For the mailbox interrupt */ | ||||
ixv_set_ivar(adapter, 1, adapter->vector, -1); | ixv_set_ivar(sc, 1, sc->vector, -1); | ||||
} /* ixv_configure_ivars */ | } /* ixv_configure_ivars */ | ||||
/************************************************************************ | /************************************************************************ | ||||
* ixv_save_stats | * ixv_save_stats | ||||
* | * | ||||
* The VF stats registers never have a truly virgin | * The VF stats registers never have a truly virgin | ||||
* starting point, so this routine tries to make an | * starting point, so this routine tries to make an | ||||
* artificial one, marking ground zero on attach as | * artificial one, marking ground zero on attach as | ||||
* it were. | * it were. | ||||
************************************************************************/ | ************************************************************************/ | ||||
static void | static void | ||||
ixv_save_stats(struct adapter *adapter) | ixv_save_stats(struct ixgbe_softc *sc) | ||||
{ | { | ||||
if (adapter->stats.vf.vfgprc || adapter->stats.vf.vfgptc) { | if (sc->stats.vf.vfgprc || sc->stats.vf.vfgptc) { | ||||
adapter->stats.vf.saved_reset_vfgprc += | sc->stats.vf.saved_reset_vfgprc += | ||||
adapter->stats.vf.vfgprc - adapter->stats.vf.base_vfgprc; | sc->stats.vf.vfgprc - sc->stats.vf.base_vfgprc; | ||||
adapter->stats.vf.saved_reset_vfgptc += | sc->stats.vf.saved_reset_vfgptc += | ||||
adapter->stats.vf.vfgptc - adapter->stats.vf.base_vfgptc; | sc->stats.vf.vfgptc - sc->stats.vf.base_vfgptc; | ||||
adapter->stats.vf.saved_reset_vfgorc += | sc->stats.vf.saved_reset_vfgorc += | ||||
adapter->stats.vf.vfgorc - adapter->stats.vf.base_vfgorc; | sc->stats.vf.vfgorc - sc->stats.vf.base_vfgorc; | ||||
adapter->stats.vf.saved_reset_vfgotc += | sc->stats.vf.saved_reset_vfgotc += | ||||
adapter->stats.vf.vfgotc - adapter->stats.vf.base_vfgotc; | sc->stats.vf.vfgotc - sc->stats.vf.base_vfgotc; | ||||
adapter->stats.vf.saved_reset_vfmprc += | sc->stats.vf.saved_reset_vfmprc += | ||||
adapter->stats.vf.vfmprc - adapter->stats.vf.base_vfmprc; | sc->stats.vf.vfmprc - sc->stats.vf.base_vfmprc; | ||||
} | } | ||||
} /* ixv_save_stats */ | } /* ixv_save_stats */ | ||||
/************************************************************************ | /************************************************************************ | ||||
* ixv_init_stats | * ixv_init_stats | ||||
************************************************************************/ | ************************************************************************/ | ||||
static void | static void | ||||
ixv_init_stats(struct adapter *adapter) | ixv_init_stats(struct ixgbe_softc *sc) | ||||
{ | { | ||||
struct ixgbe_hw *hw = &adapter->hw; | struct ixgbe_hw *hw = &sc->hw; | ||||
adapter->stats.vf.last_vfgprc = IXGBE_READ_REG(hw, IXGBE_VFGPRC); | sc->stats.vf.last_vfgprc = IXGBE_READ_REG(hw, IXGBE_VFGPRC); | ||||
adapter->stats.vf.last_vfgorc = IXGBE_READ_REG(hw, IXGBE_VFGORC_LSB); | sc->stats.vf.last_vfgorc = IXGBE_READ_REG(hw, IXGBE_VFGORC_LSB); | ||||
adapter->stats.vf.last_vfgorc |= | sc->stats.vf.last_vfgorc |= | ||||
(((u64)(IXGBE_READ_REG(hw, IXGBE_VFGORC_MSB))) << 32); | (((u64)(IXGBE_READ_REG(hw, IXGBE_VFGORC_MSB))) << 32); | ||||
adapter->stats.vf.last_vfgptc = IXGBE_READ_REG(hw, IXGBE_VFGPTC); | sc->stats.vf.last_vfgptc = IXGBE_READ_REG(hw, IXGBE_VFGPTC); | ||||
adapter->stats.vf.last_vfgotc = IXGBE_READ_REG(hw, IXGBE_VFGOTC_LSB); | sc->stats.vf.last_vfgotc = IXGBE_READ_REG(hw, IXGBE_VFGOTC_LSB); | ||||
adapter->stats.vf.last_vfgotc |= | sc->stats.vf.last_vfgotc |= | ||||
(((u64)(IXGBE_READ_REG(hw, IXGBE_VFGOTC_MSB))) << 32); | (((u64)(IXGBE_READ_REG(hw, IXGBE_VFGOTC_MSB))) << 32); | ||||
adapter->stats.vf.last_vfmprc = IXGBE_READ_REG(hw, IXGBE_VFMPRC); | sc->stats.vf.last_vfmprc = IXGBE_READ_REG(hw, IXGBE_VFMPRC); | ||||
adapter->stats.vf.base_vfgprc = adapter->stats.vf.last_vfgprc; | sc->stats.vf.base_vfgprc = sc->stats.vf.last_vfgprc; | ||||
adapter->stats.vf.base_vfgorc = adapter->stats.vf.last_vfgorc; | sc->stats.vf.base_vfgorc = sc->stats.vf.last_vfgorc; | ||||
adapter->stats.vf.base_vfgptc = adapter->stats.vf.last_vfgptc; | sc->stats.vf.base_vfgptc = sc->stats.vf.last_vfgptc; | ||||
adapter->stats.vf.base_vfgotc = adapter->stats.vf.last_vfgotc; | sc->stats.vf.base_vfgotc = sc->stats.vf.last_vfgotc; | ||||
adapter->stats.vf.base_vfmprc = adapter->stats.vf.last_vfmprc; | sc->stats.vf.base_vfmprc = sc->stats.vf.last_vfmprc; | ||||
} /* ixv_init_stats */ | } /* ixv_init_stats */ | ||||
#define UPDATE_STAT_32(reg, last, count) \ | #define UPDATE_STAT_32(reg, last, count) \ | ||||
{ \ | { \ | ||||
u32 current = IXGBE_READ_REG(hw, reg); \ | u32 current = IXGBE_READ_REG(hw, reg); \ | ||||
if (current < last) \ | if (current < last) \ | ||||
count += 0x100000000LL; \ | count += 0x100000000LL; \ | ||||
last = current; \ | last = current; \ | ||||
Show All 12 Lines | #define UPDATE_STAT_36(lsb, msb, last, count) \ | ||||
count &= 0xFFFFFFF000000000LL; \ | count &= 0xFFFFFFF000000000LL; \ | ||||
count |= current; \ | count |= current; \ | ||||
} | } | ||||
/************************************************************************ | /************************************************************************ | ||||
* ixv_update_stats - Update the board statistics counters. | * ixv_update_stats - Update the board statistics counters. | ||||
************************************************************************/ | ************************************************************************/ | ||||
void | void | ||||
ixv_update_stats(struct adapter *adapter) | ixv_update_stats(struct ixgbe_softc *sc) | ||||
{ | { | ||||
struct ixgbe_hw *hw = &adapter->hw; | struct ixgbe_hw *hw = &sc->hw; | ||||
struct ixgbevf_hw_stats *stats = &adapter->stats.vf; | struct ixgbevf_hw_stats *stats = &sc->stats.vf; | ||||
UPDATE_STAT_32(IXGBE_VFGPRC, adapter->stats.vf.last_vfgprc, | UPDATE_STAT_32(IXGBE_VFGPRC, sc->stats.vf.last_vfgprc, | ||||
adapter->stats.vf.vfgprc); | sc->stats.vf.vfgprc); | ||||
UPDATE_STAT_32(IXGBE_VFGPTC, adapter->stats.vf.last_vfgptc, | UPDATE_STAT_32(IXGBE_VFGPTC, sc->stats.vf.last_vfgptc, | ||||
adapter->stats.vf.vfgptc); | sc->stats.vf.vfgptc); | ||||
UPDATE_STAT_36(IXGBE_VFGORC_LSB, IXGBE_VFGORC_MSB, | UPDATE_STAT_36(IXGBE_VFGORC_LSB, IXGBE_VFGORC_MSB, | ||||
adapter->stats.vf.last_vfgorc, adapter->stats.vf.vfgorc); | sc->stats.vf.last_vfgorc, sc->stats.vf.vfgorc); | ||||
UPDATE_STAT_36(IXGBE_VFGOTC_LSB, IXGBE_VFGOTC_MSB, | UPDATE_STAT_36(IXGBE_VFGOTC_LSB, IXGBE_VFGOTC_MSB, | ||||
adapter->stats.vf.last_vfgotc, adapter->stats.vf.vfgotc); | sc->stats.vf.last_vfgotc, sc->stats.vf.vfgotc); | ||||
UPDATE_STAT_32(IXGBE_VFMPRC, adapter->stats.vf.last_vfmprc, | UPDATE_STAT_32(IXGBE_VFMPRC, sc->stats.vf.last_vfmprc, | ||||
adapter->stats.vf.vfmprc); | sc->stats.vf.vfmprc); | ||||
/* Fill out the OS statistics structure */ | /* Fill out the OS statistics structure */ | ||||
IXGBE_SET_IPACKETS(adapter, stats->vfgprc); | IXGBE_SET_IPACKETS(sc, stats->vfgprc); | ||||
IXGBE_SET_OPACKETS(adapter, stats->vfgptc); | IXGBE_SET_OPACKETS(sc, stats->vfgptc); | ||||
IXGBE_SET_IBYTES(adapter, stats->vfgorc); | IXGBE_SET_IBYTES(sc, stats->vfgorc); | ||||
IXGBE_SET_OBYTES(adapter, stats->vfgotc); | IXGBE_SET_OBYTES(sc, stats->vfgotc); | ||||
IXGBE_SET_IMCASTS(adapter, stats->vfmprc); | IXGBE_SET_IMCASTS(sc, stats->vfmprc); | ||||
} /* ixv_update_stats */ | } /* ixv_update_stats */ | ||||
/************************************************************************ | /************************************************************************ | ||||
* ixv_add_stats_sysctls - Add statistic sysctls for the VF. | * ixv_add_stats_sysctls - Add statistic sysctls for the VF. | ||||
************************************************************************/ | ************************************************************************/ | ||||
static void | static void | ||||
ixv_add_stats_sysctls(struct adapter *adapter) | ixv_add_stats_sysctls(struct ixgbe_softc *sc) | ||||
{ | { | ||||
device_t dev = adapter->dev; | device_t dev = sc->dev; | ||||
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; | ||||
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 ixgbevf_hw_stats *stats = &adapter->stats.vf; | struct ixgbevf_hw_stats *stats = &sc->stats.vf; | ||||
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; | ||||
#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, "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 (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; | ||||
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_UQUAD(ctx, queue_list, OID_AUTO, "tso_tx", | SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "tso_tx", | ||||
CTLFLAG_RD, &(txr->tso_tx), "TSO Packets"); | CTLFLAG_RD, &(txr->tso_tx), "TSO Packets"); | ||||
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), "TX Packets"); | CTLFLAG_RD, &(txr->total_packets), "TX Packets"); | ||||
} | } | ||||
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; | ||||
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_UQUAD(ctx, queue_list, OID_AUTO, "irqs", | SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "irqs", | ||||
CTLFLAG_RD, &(rx_que->irqs), "IRQs on queue"); | CTLFLAG_RD, &(rx_que->irqs), "IRQs on queue"); | ||||
Show All 25 Lines | |||||
/************************************************************************ | /************************************************************************ | ||||
* ixv_print_debug_info | * ixv_print_debug_info | ||||
* | * | ||||
* Called only when em_display_debug_stats is enabled. | * Called only when em_display_debug_stats is enabled. | ||||
* Provides a way to take a look at important statistics | * Provides a way to take a look at important statistics | ||||
* maintained by the driver and hardware. | * maintained by the driver and hardware. | ||||
************************************************************************/ | ************************************************************************/ | ||||
static void | static void | ||||
ixv_print_debug_info(struct adapter *adapter) | ixv_print_debug_info(struct ixgbe_softc *sc) | ||||
{ | { | ||||
device_t dev = adapter->dev; | device_t dev = sc->dev; | ||||
struct ixgbe_hw *hw = &adapter->hw; | struct ixgbe_hw *hw = &sc->hw; | ||||
device_printf(dev, "Error Byte Count = %u \n", | device_printf(dev, "Error Byte Count = %u \n", | ||||
IXGBE_READ_REG(hw, IXGBE_ERRBC)); | IXGBE_READ_REG(hw, IXGBE_ERRBC)); | ||||
device_printf(dev, "MBX IRQ Handled: %lu\n", (long)adapter->link_irq); | device_printf(dev, "MBX IRQ Handled: %lu\n", (long)sc->link_irq); | ||||
} /* ixv_print_debug_info */ | } /* ixv_print_debug_info */ | ||||
/************************************************************************ | /************************************************************************ | ||||
* ixv_sysctl_debug | * ixv_sysctl_debug | ||||
************************************************************************/ | ************************************************************************/ | ||||
static int | static int | ||||
ixv_sysctl_debug(SYSCTL_HANDLER_ARGS) | ixv_sysctl_debug(SYSCTL_HANDLER_ARGS) | ||||
{ | { | ||||
struct adapter *adapter; | struct ixgbe_softc *sc; | ||||
int error, result; | int error, result; | ||||
result = -1; | result = -1; | ||||
error = sysctl_handle_int(oidp, &result, 0, req); | error = sysctl_handle_int(oidp, &result, 0, req); | ||||
if (error || !req->newptr) | if (error || !req->newptr) | ||||
return (error); | return (error); | ||||
if (result == 1) { | if (result == 1) { | ||||
adapter = (struct adapter *)arg1; | sc = (struct ixgbe_softc *)arg1; | ||||
ixv_print_debug_info(adapter); | ixv_print_debug_info(sc); | ||||
} | } | ||||
return error; | return error; | ||||
} /* ixv_sysctl_debug */ | } /* ixv_sysctl_debug */ | ||||
/************************************************************************ | /************************************************************************ | ||||
* ixv_init_device_features | * ixv_init_device_features | ||||
************************************************************************/ | ************************************************************************/ | ||||
static void | static void | ||||
ixv_init_device_features(struct adapter *adapter) | ixv_init_device_features(struct ixgbe_softc *sc) | ||||
{ | { | ||||
adapter->feat_cap = IXGBE_FEATURE_NETMAP | sc->feat_cap = IXGBE_FEATURE_NETMAP | ||||
| IXGBE_FEATURE_VF | | IXGBE_FEATURE_VF | ||||
| IXGBE_FEATURE_LEGACY_TX; | | IXGBE_FEATURE_LEGACY_TX; | ||||
/* A tad short on feature flags for VFs, atm. */ | /* A tad short on feature flags for VFs, atm. */ | ||||
switch (adapter->hw.mac.type) { | switch (sc->hw.mac.type) { | ||||
case ixgbe_mac_82599_vf: | case ixgbe_mac_82599_vf: | ||||
break; | break; | ||||
case ixgbe_mac_X540_vf: | case ixgbe_mac_X540_vf: | ||||
break; | break; | ||||
case ixgbe_mac_X550_vf: | case ixgbe_mac_X550_vf: | ||||
case ixgbe_mac_X550EM_x_vf: | case ixgbe_mac_X550EM_x_vf: | ||||
case ixgbe_mac_X550EM_a_vf: | case |