Changeset View
Changeset View
Standalone View
Standalone View
sys/dev/ixl/if_ixl.c
Show First 20 Lines • Show All 106 Lines • ▼ Show 20 Lines | |||||
static void ixl_local_timer(void *); | static void ixl_local_timer(void *); | ||||
static int ixl_setup_interface(device_t, struct ixl_vsi *); | static int ixl_setup_interface(device_t, struct ixl_vsi *); | ||||
static bool ixl_config_link(struct i40e_hw *); | static bool ixl_config_link(struct i40e_hw *); | ||||
static void ixl_config_rss(struct ixl_vsi *); | static void ixl_config_rss(struct ixl_vsi *); | ||||
static void ixl_set_queue_rx_itr(struct ixl_queue *); | static void ixl_set_queue_rx_itr(struct ixl_queue *); | ||||
static void ixl_set_queue_tx_itr(struct ixl_queue *); | static void ixl_set_queue_tx_itr(struct ixl_queue *); | ||||
static int ixl_set_advertised_speeds(struct ixl_pf *, int); | static int ixl_set_advertised_speeds(struct ixl_pf *, int); | ||||
static void ixl_enable_rings(struct ixl_vsi *); | static int ixl_enable_rings(struct ixl_vsi *); | ||||
static void ixl_disable_rings(struct ixl_vsi *); | static int ixl_disable_rings(struct ixl_vsi *); | ||||
static void ixl_enable_intr(struct ixl_vsi *); | static void ixl_enable_intr(struct ixl_vsi *); | ||||
static void ixl_disable_intr(struct ixl_vsi *); | static void ixl_disable_intr(struct ixl_vsi *); | ||||
static void ixl_enable_adminq(struct i40e_hw *); | static void ixl_enable_adminq(struct i40e_hw *); | ||||
static void ixl_disable_adminq(struct i40e_hw *); | static void ixl_disable_adminq(struct i40e_hw *); | ||||
static void ixl_enable_queue(struct i40e_hw *, int); | static void ixl_enable_queue(struct i40e_hw *, int); | ||||
static void ixl_disable_queue(struct i40e_hw *, int); | static void ixl_disable_queue(struct i40e_hw *, int); | ||||
static void ixl_enable_legacy(struct i40e_hw *); | static void ixl_enable_legacy(struct i40e_hw *); | ||||
static void ixl_disable_legacy(struct i40e_hw *); | static void ixl_disable_legacy(struct i40e_hw *); | ||||
static void ixl_set_promisc(struct ixl_vsi *); | static void ixl_set_promisc(struct ixl_vsi *); | ||||
static void ixl_add_multi(struct ixl_vsi *); | static void ixl_add_multi(struct ixl_vsi *); | ||||
static void ixl_del_multi(struct ixl_vsi *); | static void ixl_del_multi(struct ixl_vsi *); | ||||
static void ixl_register_vlan(void *, struct ifnet *, u16); | static void ixl_register_vlan(void *, struct ifnet *, u16); | ||||
static void ixl_unregister_vlan(void *, struct ifnet *, u16); | static void ixl_unregister_vlan(void *, struct ifnet *, u16); | ||||
static void ixl_setup_vlan_filters(struct ixl_vsi *); | static void ixl_setup_vlan_filters(struct ixl_vsi *); | ||||
static void ixl_init_filters(struct ixl_vsi *); | static void ixl_init_filters(struct ixl_vsi *); | ||||
static void ixl_add_filter(struct ixl_vsi *, u8 *, s16 vlan); | static void ixl_add_filter(struct ixl_vsi *, u8 *, s16 vlan); | ||||
static void ixl_del_filter(struct ixl_vsi *, u8 *, s16 vlan); | static void ixl_del_filter(struct ixl_vsi *, u8 *, s16 vlan); | ||||
static void ixl_add_hw_filters(struct ixl_vsi *, int, int); | static void ixl_add_hw_filters(struct ixl_vsi *, int, int); | ||||
static void ixl_del_hw_filters(struct ixl_vsi *, int); | static void ixl_del_hw_filters(struct ixl_vsi *, int); | ||||
static struct ixl_mac_filter * | static struct ixl_mac_filter * | ||||
ixl_find_filter(struct ixl_vsi *, u8 *, s16); | ixl_find_filter(struct ixl_vsi *, u8 *, s16); | ||||
static void ixl_add_mc_filter(struct ixl_vsi *, u8 *); | static void ixl_add_mc_filter(struct ixl_vsi *, u8 *); | ||||
static void ixl_free_mac_filters(struct ixl_vsi *vsi); | |||||
/* Sysctl debug interface */ | /* Sysctl debug interface */ | ||||
static int ixl_debug_info(SYSCTL_HANDLER_ARGS); | static int ixl_debug_info(SYSCTL_HANDLER_ARGS); | ||||
static void ixl_print_debug_info(struct ixl_pf *); | static void ixl_print_debug_info(struct ixl_pf *); | ||||
/* The MSI/X Interrupt handlers */ | /* The MSI/X Interrupt handlers */ | ||||
static void ixl_intr(void *); | static void ixl_intr(void *); | ||||
static void ixl_msix_que(void *); | static void ixl_msix_que(void *); | ||||
static void ixl_msix_adminq(void *); | static void ixl_msix_adminq(void *); | ||||
Show All 12 Lines | |||||
static void ixl_add_hw_stats(struct ixl_pf *); | static void ixl_add_hw_stats(struct ixl_pf *); | ||||
static void ixl_add_sysctls_mac_stats(struct sysctl_ctx_list *, | static void ixl_add_sysctls_mac_stats(struct sysctl_ctx_list *, | ||||
struct sysctl_oid_list *, struct i40e_hw_port_stats *); | struct sysctl_oid_list *, struct i40e_hw_port_stats *); | ||||
static void ixl_add_sysctls_eth_stats(struct sysctl_ctx_list *, | static void ixl_add_sysctls_eth_stats(struct sysctl_ctx_list *, | ||||
struct sysctl_oid_list *, | struct sysctl_oid_list *, | ||||
struct i40e_eth_stats *); | struct i40e_eth_stats *); | ||||
static void ixl_update_stats_counters(struct ixl_pf *); | static void ixl_update_stats_counters(struct ixl_pf *); | ||||
static void ixl_update_eth_stats(struct ixl_vsi *); | static void ixl_update_eth_stats(struct ixl_vsi *); | ||||
static void ixl_update_vsi_stats(struct ixl_vsi *); | |||||
static void ixl_pf_reset_stats(struct ixl_pf *); | static void ixl_pf_reset_stats(struct ixl_pf *); | ||||
static void ixl_vsi_reset_stats(struct ixl_vsi *); | static void ixl_vsi_reset_stats(struct ixl_vsi *); | ||||
static void ixl_stat_update48(struct i40e_hw *, u32, u32, bool, | static void ixl_stat_update48(struct i40e_hw *, u32, u32, bool, | ||||
u64 *, u64 *); | u64 *, u64 *); | ||||
static void ixl_stat_update32(struct i40e_hw *, u32, bool, | static void ixl_stat_update32(struct i40e_hw *, u32, bool, | ||||
u64 *, u64 *); | u64 *, u64 *); | ||||
#ifdef IXL_DEBUG_SYSCTL | #ifdef IXL_DEBUG_SYSCTL | ||||
▲ Show 20 Lines • Show All 97 Lines • ▼ Show 20 Lines | |||||
static int ixl_enable_fdir = 1; | static int ixl_enable_fdir = 1; | ||||
TUNABLE_INT("hw.ixl.enable_fdir", &ixl_enable_fdir); | TUNABLE_INT("hw.ixl.enable_fdir", &ixl_enable_fdir); | ||||
/* Rate at which we sample */ | /* Rate at which we sample */ | ||||
int ixl_atr_rate = 20; | int ixl_atr_rate = 20; | ||||
TUNABLE_INT("hw.ixl.atr_rate", &ixl_atr_rate); | TUNABLE_INT("hw.ixl.atr_rate", &ixl_atr_rate); | ||||
#endif | #endif | ||||
static uint8_t ixl_bcast_addr[ETHER_ADDR_LEN] = | |||||
{0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; | |||||
static char *ixl_fc_string[6] = { | static char *ixl_fc_string[6] = { | ||||
"None", | "None", | ||||
"Rx", | "Rx", | ||||
"Tx", | "Tx", | ||||
"Full", | "Full", | ||||
"Priority", | "Priority", | ||||
"Default" | "Default" | ||||
}; | }; | ||||
▲ Show 20 Lines • Show All 624 Lines • ▼ Show 20 Lines | |||||
* | * | ||||
* return 0 on success, positive on failure | * return 0 on success, positive on failure | ||||
**********************************************************************/ | **********************************************************************/ | ||||
static int | static int | ||||
ixl_ioctl(struct ifnet * ifp, u_long command, caddr_t data) | ixl_ioctl(struct ifnet * ifp, u_long command, caddr_t data) | ||||
{ | { | ||||
struct ixl_vsi *vsi = ifp->if_softc; | struct ixl_vsi *vsi = ifp->if_softc; | ||||
struct ixl_pf *pf = (struct ixl_pf *)vsi->back; | struct ixl_pf *pf = vsi->back; | ||||
struct ifreq *ifr = (struct ifreq *) data; | struct ifreq *ifr = (struct ifreq *) data; | ||||
#if defined(INET) || defined(INET6) | #if defined(INET) || defined(INET6) | ||||
struct ifaddr *ifa = (struct ifaddr *)data; | struct ifaddr *ifa = (struct ifaddr *)data; | ||||
bool avoid_reset = FALSE; | bool avoid_reset = FALSE; | ||||
#endif | #endif | ||||
int error = 0; | int error = 0; | ||||
switch (command) { | switch (command) { | ||||
▲ Show 20 Lines • Show All 181 Lines • ▼ Show 20 Lines | |||||
#endif | #endif | ||||
if (i40e_set_filter_control(hw, &filter)) | if (i40e_set_filter_control(hw, &filter)) | ||||
device_printf(dev, "set_filter_control() failed\n"); | device_printf(dev, "set_filter_control() failed\n"); | ||||
/* Set up RSS */ | /* Set up RSS */ | ||||
ixl_config_rss(vsi); | ixl_config_rss(vsi); | ||||
/* Setup the VSI */ | /* Setup the VSI */ | ||||
ixl_setup_vsi(vsi); | if (ixl_setup_vsi(vsi)) { | ||||
device_printf(dev,"ixl_setup_vsi() failed!\n"); | |||||
return; | |||||
} | |||||
/* | /* | ||||
** Prepare the rings, hmc contexts, etc... | ** Prepare the rings, hmc contexts, etc... | ||||
*/ | */ | ||||
if (ixl_initialize_vsi(vsi)) { | if (ixl_initialize_vsi(vsi)) { | ||||
device_printf(dev, "initialize vsi failed!!\n"); | device_printf(dev, "initialize vsi failed!!\n"); | ||||
return; | return; | ||||
} | } | ||||
Show All 13 Lines | if (ixl_enable_msix) { | ||||
ixl_configure_itr(pf); | ixl_configure_itr(pf); | ||||
} else | } else | ||||
ixl_configure_legacy(pf); | ixl_configure_legacy(pf); | ||||
ixl_enable_rings(vsi); | ixl_enable_rings(vsi); | ||||
i40e_aq_set_default_vsi(hw, vsi->seid, NULL); | i40e_aq_set_default_vsi(hw, vsi->seid, NULL); | ||||
/* Set MTU in hardware*/ | /* Set MTU in hardware*/ | ||||
int aq_error = i40e_aq_set_mac_config(hw, vsi->max_frame_size, | int aq_error = i40e_aq_set_mac_config(hw, vsi->max_frame_size, | ||||
TRUE, 0, NULL); | TRUE, 0, NULL); | ||||
if (aq_error) | if (aq_error) | ||||
device_printf(vsi->dev, | device_printf(vsi->dev, | ||||
"aq_set_mac_config in init error, code %d\n", | "aq_set_mac_config in init error, code %d\n", | ||||
aq_error); | aq_error); | ||||
▲ Show 20 Lines • Show All 204 Lines • ▼ Show 20 Lines | |||||
* This routine is called whenever the user queries the status of | * This routine is called whenever the user queries the status of | ||||
* the interface using ifconfig. | * the interface using ifconfig. | ||||
* | * | ||||
**********************************************************************/ | **********************************************************************/ | ||||
static void | static void | ||||
ixl_media_status(struct ifnet * ifp, struct ifmediareq * ifmr) | ixl_media_status(struct ifnet * ifp, struct ifmediareq * ifmr) | ||||
{ | { | ||||
struct ixl_vsi *vsi = ifp->if_softc; | struct ixl_vsi *vsi = ifp->if_softc; | ||||
struct ixl_pf *pf = (struct ixl_pf *)vsi->back; | struct ixl_pf *pf = vsi->back; | ||||
struct i40e_hw *hw = &pf->hw; | struct i40e_hw *hw = &pf->hw; | ||||
INIT_DEBUGOUT("ixl_media_status: begin"); | INIT_DEBUGOUT("ixl_media_status: begin"); | ||||
IXL_PF_LOCK(pf); | IXL_PF_LOCK(pf); | ||||
ixl_update_link_status(pf); | ixl_update_link_status(pf); | ||||
ifmr->ifm_status = IFM_AVALID; | ifmr->ifm_status = IFM_AVALID; | ||||
▲ Show 20 Lines • Show All 378 Lines • ▼ Show 20 Lines | |||||
{ | { | ||||
struct ixl_vsi *vsi = &pf->vsi; | struct ixl_vsi *vsi = &pf->vsi; | ||||
struct i40e_hw *hw = &pf->hw; | struct i40e_hw *hw = &pf->hw; | ||||
struct ifnet *ifp = vsi->ifp; | struct ifnet *ifp = vsi->ifp; | ||||
device_t dev = pf->dev; | device_t dev = pf->dev; | ||||
enum i40e_fc_mode fc; | enum i40e_fc_mode fc; | ||||
if (vsi->link_up){ | if (vsi->link_up){ | ||||
if (vsi->link_active == FALSE) { | if (vsi->link_active == FALSE) { | ||||
i40e_aq_get_link_info(hw, TRUE, NULL, NULL); | i40e_aq_get_link_info(hw, TRUE, NULL, NULL); | ||||
if (bootverbose) { | if (bootverbose) { | ||||
fc = hw->fc.current_mode; | fc = hw->fc.current_mode; | ||||
device_printf(dev,"Link is up %d Gbps %s," | device_printf(dev,"Link is up %d Gbps %s," | ||||
" Flow Control: %s\n", | " Flow Control: %s\n", | ||||
((vsi->link_speed == I40E_LINK_SPEED_40GB)? 40:10), | ((vsi->link_speed == I40E_LINK_SPEED_40GB)? 40:10), | ||||
"Full Duplex", ixl_fc_string[fc]); | "Full Duplex", ixl_fc_string[fc]); | ||||
▲ Show 20 Lines • Show All 835 Lines • ▼ Show 20 Lines | txctl |= ((hw->pf_id << I40E_QTX_CTL_PF_INDX_SHIFT) & | ||||
I40E_QTX_CTL_PF_INDX_MASK); | I40E_QTX_CTL_PF_INDX_MASK); | ||||
wr32(hw, I40E_QTX_CTL(i), txctl); | wr32(hw, I40E_QTX_CTL(i), txctl); | ||||
ixl_flush(hw); | ixl_flush(hw); | ||||
/* Do ring (re)init */ | /* Do ring (re)init */ | ||||
ixl_init_tx_ring(que); | ixl_init_tx_ring(que); | ||||
/* Next setup the HMC RX Context */ | /* Next setup the HMC RX Context */ | ||||
if (vsi->max_frame_size <= 2048) | if (vsi->max_frame_size <= MCLBYTES) | ||||
rxr->mbuf_sz = MCLBYTES; | rxr->mbuf_sz = MCLBYTES; | ||||
else | else | ||||
rxr->mbuf_sz = MJUMPAGESIZE; | rxr->mbuf_sz = MJUMPAGESIZE; | ||||
u16 max_rxmax = rxr->mbuf_sz * hw->func_caps.rx_buf_chain_len; | u16 max_rxmax = rxr->mbuf_sz * hw->func_caps.rx_buf_chain_len; | ||||
/* Set up an RX context for the HMC */ | /* Set up an RX context for the HMC */ | ||||
memset(&rctx, 0, sizeof(struct i40e_hmc_obj_rxq)); | memset(&rctx, 0, sizeof(struct i40e_hmc_obj_rxq)); | ||||
▲ Show 20 Lines • Show All 46 Lines • ▼ Show 20 Lines | |||||
* Free all VSI structs. | * Free all VSI structs. | ||||
* | * | ||||
**********************************************************************/ | **********************************************************************/ | ||||
void | void | ||||
ixl_free_vsi(struct ixl_vsi *vsi) | ixl_free_vsi(struct ixl_vsi *vsi) | ||||
{ | { | ||||
struct ixl_pf *pf = (struct ixl_pf *)vsi->back; | struct ixl_pf *pf = (struct ixl_pf *)vsi->back; | ||||
struct ixl_queue *que = vsi->queues; | struct ixl_queue *que = vsi->queues; | ||||
struct ixl_mac_filter *f; | |||||
/* Free station queues */ | /* Free station queues */ | ||||
for (int i = 0; i < vsi->num_queues; i++, que++) { | for (int i = 0; i < vsi->num_queues; i++, que++) { | ||||
struct tx_ring *txr = &que->txr; | struct tx_ring *txr = &que->txr; | ||||
struct rx_ring *rxr = &que->rxr; | struct rx_ring *rxr = &que->rxr; | ||||
if (!mtx_initialized(&txr->mtx)) /* uninitialized */ | if (!mtx_initialized(&txr->mtx)) /* uninitialized */ | ||||
continue; | continue; | ||||
Show All 12 Lines | if (rxr->base) | ||||
i40e_free_dma_mem(&pf->hw, &rxr->dma); | i40e_free_dma_mem(&pf->hw, &rxr->dma); | ||||
IXL_RX_UNLOCK(rxr); | IXL_RX_UNLOCK(rxr); | ||||
IXL_RX_LOCK_DESTROY(rxr); | IXL_RX_LOCK_DESTROY(rxr); | ||||
} | } | ||||
free(vsi->queues, M_DEVBUF); | free(vsi->queues, M_DEVBUF); | ||||
/* Free VSI filter list */ | /* Free VSI filter list */ | ||||
ixl_free_mac_filters(vsi); | |||||
} | |||||
static void | |||||
ixl_free_mac_filters(struct ixl_vsi *vsi) | |||||
{ | |||||
struct ixl_mac_filter *f; | |||||
while (!SLIST_EMPTY(&vsi->ftl)) { | while (!SLIST_EMPTY(&vsi->ftl)) { | ||||
f = SLIST_FIRST(&vsi->ftl); | f = SLIST_FIRST(&vsi->ftl); | ||||
SLIST_REMOVE_HEAD(&vsi->ftl, next); | SLIST_REMOVE_HEAD(&vsi->ftl, next); | ||||
free(f, M_DEVBUF); | free(f, M_DEVBUF); | ||||
} | } | ||||
} | } | ||||
Show All 15 Lines | ixl_setup_stations(struct ixl_pf *pf) | ||||
int rsize, tsize; | int rsize, tsize; | ||||
int error = I40E_SUCCESS; | int error = I40E_SUCCESS; | ||||
vsi = &pf->vsi; | vsi = &pf->vsi; | ||||
vsi->back = (void *)pf; | vsi->back = (void *)pf; | ||||
vsi->hw = &pf->hw; | vsi->hw = &pf->hw; | ||||
vsi->id = 0; | vsi->id = 0; | ||||
vsi->num_vlans = 0; | vsi->num_vlans = 0; | ||||
vsi->back = pf; | |||||
/* Get memory for the station queues */ | /* Get memory for the station queues */ | ||||
if (!(vsi->queues = | if (!(vsi->queues = | ||||
(struct ixl_queue *) malloc(sizeof(struct ixl_queue) * | (struct ixl_queue *) malloc(sizeof(struct ixl_queue) * | ||||
vsi->num_queues, M_DEVBUF, M_NOWAIT | M_ZERO))) { | vsi->num_queues, M_DEVBUF, M_NOWAIT | M_ZERO))) { | ||||
device_printf(dev, "Unable to allocate queue memory\n"); | device_printf(dev, "Unable to allocate queue memory\n"); | ||||
error = ENOMEM; | error = ENOMEM; | ||||
goto early; | goto early; | ||||
▲ Show 20 Lines • Show All 236 Lines • ▼ Show 20 Lines | if (txr->itr != vsi->tx_itr_setting) { | ||||
que->me), txr->itr); | que->me), txr->itr); | ||||
} | } | ||||
} | } | ||||
txr->bytes = 0; | txr->bytes = 0; | ||||
txr->packets = 0; | txr->packets = 0; | ||||
return; | return; | ||||
} | } | ||||
#define QUEUE_NAME_LEN 32 | |||||
static void | static void | ||||
ixl_add_vsi_sysctls(struct ixl_pf *pf, struct ixl_vsi *vsi, | |||||
struct sysctl_ctx_list *ctx) | |||||
{ | |||||
struct sysctl_oid *tree; | |||||
struct sysctl_oid_list *child; | |||||
struct sysctl_oid_list *vsi_list; | |||||
char vsi_namebuf[QUEUE_NAME_LEN]; | |||||
tree = device_get_sysctl_tree(pf->dev); | |||||
child = SYSCTL_CHILDREN(tree); | |||||
snprintf(vsi_namebuf, QUEUE_NAME_LEN, "vsi%d", | |||||
vsi->info.stat_counter_idx); | |||||
vsi->vsi_node = SYSCTL_ADD_NODE(ctx, child, OID_AUTO, vsi_namebuf, | |||||
CTLFLAG_RD, NULL, "VSI Number"); | |||||
vsi_list = SYSCTL_CHILDREN(vsi->vsi_node); | |||||
ixl_add_sysctls_eth_stats(ctx, vsi_list, &vsi->eth_stats); | |||||
} | |||||
static void | |||||
ixl_add_hw_stats(struct ixl_pf *pf) | ixl_add_hw_stats(struct ixl_pf *pf) | ||||
{ | { | ||||
device_t dev = pf->dev; | device_t dev = pf->dev; | ||||
struct ixl_vsi *vsi = &pf->vsi; | struct ixl_vsi *vsi = &pf->vsi; | ||||
struct ixl_queue *queues = vsi->queues; | struct ixl_queue *queues = vsi->queues; | ||||
struct i40e_eth_stats *vsi_stats = &vsi->eth_stats; | |||||
struct i40e_hw_port_stats *pf_stats = &pf->stats; | struct i40e_hw_port_stats *pf_stats = &pf->stats; | ||||
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 sysctl_oid_list *vsi_list; | |||||
struct sysctl_oid *vsi_node, *queue_node; | struct sysctl_oid *queue_node; | ||||
struct sysctl_oid_list *vsi_list, *queue_list; | struct sysctl_oid_list *queue_list; | ||||
struct tx_ring *txr; | struct tx_ring *txr; | ||||
struct rx_ring *rxr; | struct rx_ring *rxr; | ||||
char queue_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, &pf->watchdog_events, | CTLFLAG_RD, &pf->watchdog_events, | ||||
"Watchdog timeouts"); | "Watchdog timeouts"); | ||||
SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "admin_irq", | SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "admin_irq", | ||||
CTLFLAG_RD, &pf->admin_irq, | CTLFLAG_RD, &pf->admin_irq, | ||||
"Admin Queue IRQ Handled"); | "Admin Queue IRQ Handled"); | ||||
/* VSI statistics */ | |||||
#define QUEUE_NAME_LEN 32 | |||||
char queue_namebuf[QUEUE_NAME_LEN]; | |||||
// ERJ: Only one vsi now, re-do when >1 VSI enabled | ixl_add_vsi_sysctls(pf, &pf->vsi, ctx); | ||||
// snprintf(vsi_namebuf, QUEUE_NAME_LEN, "vsi%d", vsi->info.stat_counter_idx); | vsi_list = SYSCTL_CHILDREN(pf->vsi.vsi_node); | ||||
vsi_node = SYSCTL_ADD_NODE(ctx, child, OID_AUTO, "vsi", | |||||
CTLFLAG_RD, NULL, "VSI-specific stats"); | |||||
vsi_list = SYSCTL_CHILDREN(vsi_node); | |||||
ixl_add_sysctls_eth_stats(ctx, vsi_list, vsi_stats); | |||||
/* Queue statistics */ | /* Queue statistics */ | ||||
for (int q = 0; q < vsi->num_queues; q++) { | for (int q = 0; q < vsi->num_queues; q++) { | ||||
snprintf(queue_namebuf, QUEUE_NAME_LEN, "que%d", q); | snprintf(queue_namebuf, QUEUE_NAME_LEN, "que%d", q); | ||||
queue_node = SYSCTL_ADD_NODE(ctx, vsi_list, OID_AUTO, queue_namebuf, | queue_node = SYSCTL_ADD_NODE(ctx, vsi_list, OID_AUTO, queue_namebuf, | ||||
CTLFLAG_RD, NULL, "Queue #"); | CTLFLAG_RD, NULL, "Queue #"); | ||||
queue_list = SYSCTL_CHILDREN(queue_node); | queue_list = SYSCTL_CHILDREN(queue_node); | ||||
txr = &(queues[q].txr); | txr = &(queues[q].txr); | ||||
▲ Show 20 Lines • Show All 310 Lines • ▼ Show 20 Lines | |||||
/* | /* | ||||
** Initialize filter list and add filters that the hardware | ** Initialize filter list and add filters that the hardware | ||||
** needs to know about. | ** needs to know about. | ||||
*/ | */ | ||||
static void | static void | ||||
ixl_init_filters(struct ixl_vsi *vsi) | ixl_init_filters(struct ixl_vsi *vsi) | ||||
{ | { | ||||
/* Add broadcast address */ | /* Add broadcast address */ | ||||
u8 bc[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; | ixl_add_filter(vsi, ixl_bcast_addr, IXL_VLAN_ANY); | ||||
ixl_add_filter(vsi, bc, IXL_VLAN_ANY); | |||||
} | } | ||||
/* | /* | ||||
** This routine adds mulicast filters | ** This routine adds mulicast filters | ||||
*/ | */ | ||||
static void | static void | ||||
ixl_add_mc_filter(struct ixl_vsi *vsi, u8 *macaddr) | ixl_add_mc_filter(struct ixl_vsi *vsi, u8 *macaddr) | ||||
{ | { | ||||
Show All 19 Lines | |||||
/* | /* | ||||
** This routine adds macvlan filters | ** This routine adds macvlan filters | ||||
*/ | */ | ||||
static void | static void | ||||
ixl_add_filter(struct ixl_vsi *vsi, u8 *macaddr, s16 vlan) | ixl_add_filter(struct ixl_vsi *vsi, u8 *macaddr, s16 vlan) | ||||
{ | { | ||||
struct ixl_mac_filter *f, *tmp; | struct ixl_mac_filter *f, *tmp; | ||||
device_t dev = vsi->dev; | struct ixl_pf *pf; | ||||
device_t dev; | |||||
DEBUGOUT("ixl_add_filter: begin"); | DEBUGOUT("ixl_add_filter: begin"); | ||||
pf = vsi->back; | |||||
dev = pf->dev; | |||||
/* Does one already exist */ | /* Does one already exist */ | ||||
f = ixl_find_filter(vsi, macaddr, vlan); | f = ixl_find_filter(vsi, macaddr, vlan); | ||||
if (f != NULL) | if (f != NULL) | ||||
return; | return; | ||||
/* | /* | ||||
** Is this the first vlan being registered, if so we | ** Is this the first vlan being registered, if so we | ||||
** need to remove the ANY filter that indicates we are | ** need to remove the ANY filter that indicates we are | ||||
** not in a vlan, and replace that with a 0 filter. | ** not in a vlan, and replace that with a 0 filter. | ||||
▲ Show 20 Lines • Show All 70 Lines • ▼ Show 20 Lines | |||||
** table and creates an Admin Queue call to create | ** table and creates an Admin Queue call to create | ||||
** the filters in the hardware. | ** the filters in the hardware. | ||||
*/ | */ | ||||
static void | static void | ||||
ixl_add_hw_filters(struct ixl_vsi *vsi, int flags, int cnt) | ixl_add_hw_filters(struct ixl_vsi *vsi, int flags, int cnt) | ||||
{ | { | ||||
struct i40e_aqc_add_macvlan_element_data *a, *b; | struct i40e_aqc_add_macvlan_element_data *a, *b; | ||||
struct ixl_mac_filter *f; | struct ixl_mac_filter *f; | ||||
struct i40e_hw *hw = vsi->hw; | struct ixl_pf *pf; | ||||
device_t dev = vsi->dev; | struct i40e_hw *hw; | ||||
device_t dev; | |||||
int err, j = 0; | int err, j = 0; | ||||
pf = vsi->back; | |||||
dev = pf->dev; | |||||
hw = &pf->hw; | |||||
IXL_PF_LOCK_ASSERT(pf); | |||||
a = malloc(sizeof(struct i40e_aqc_add_macvlan_element_data) * cnt, | a = malloc(sizeof(struct i40e_aqc_add_macvlan_element_data) * cnt, | ||||
M_DEVBUF, M_NOWAIT | M_ZERO); | M_DEVBUF, M_NOWAIT | M_ZERO); | ||||
if (a == NULL) { | if (a == NULL) { | ||||
device_printf(dev, "add_hw_filters failed to get memory\n"); | device_printf(dev, "add_hw_filters failed to get memory\n"); | ||||
return; | return; | ||||
} | } | ||||
/* | /* | ||||
Show All 30 Lines | |||||
** This routine takes removals in the vsi filter | ** This routine takes removals in the vsi filter | ||||
** table and creates an Admin Queue call to delete | ** table and creates an Admin Queue call to delete | ||||
** the filters in the hardware. | ** the filters in the hardware. | ||||
*/ | */ | ||||
static void | static void | ||||
ixl_del_hw_filters(struct ixl_vsi *vsi, int cnt) | ixl_del_hw_filters(struct ixl_vsi *vsi, int cnt) | ||||
{ | { | ||||
struct i40e_aqc_remove_macvlan_element_data *d, *e; | struct i40e_aqc_remove_macvlan_element_data *d, *e; | ||||
struct i40e_hw *hw = vsi->hw; | struct ixl_pf *pf; | ||||
device_t dev = vsi->dev; | struct i40e_hw *hw; | ||||
device_t dev; | |||||
struct ixl_mac_filter *f, *f_temp; | struct ixl_mac_filter *f, *f_temp; | ||||
int err, j = 0; | int err, j = 0; | ||||
DEBUGOUT("ixl_del_hw_filters: begin\n"); | DEBUGOUT("ixl_del_hw_filters: begin\n"); | ||||
pf = vsi->back; | |||||
hw = &pf->hw; | |||||
dev = pf->dev; | |||||
d = malloc(sizeof(struct i40e_aqc_remove_macvlan_element_data) * cnt, | d = malloc(sizeof(struct i40e_aqc_remove_macvlan_element_data) * cnt, | ||||
M_DEVBUF, M_NOWAIT | M_ZERO); | M_DEVBUF, M_NOWAIT | M_ZERO); | ||||
if (d == NULL) { | if (d == NULL) { | ||||
printf("del hw filter failed to get memory\n"); | printf("del hw filter failed to get memory\n"); | ||||
return; | return; | ||||
} | } | ||||
SLIST_FOREACH_SAFE(f, &vsi->ftl, next, f_temp) { | SLIST_FOREACH_SAFE(f, &vsi->ftl, next, f_temp) { | ||||
Show All 27 Lines | if (err && hw->aq.asq_last_status != I40E_AQ_RC_ENOENT) { | ||||
vsi->hw_filters_del += j; | vsi->hw_filters_del += j; | ||||
} | } | ||||
free(d, M_DEVBUF); | free(d, M_DEVBUF); | ||||
DEBUGOUT("ixl_del_hw_filters: end\n"); | DEBUGOUT("ixl_del_hw_filters: end\n"); | ||||
return; | return; | ||||
} | } | ||||
static int | |||||
static void | |||||
ixl_enable_rings(struct ixl_vsi *vsi) | ixl_enable_rings(struct ixl_vsi *vsi) | ||||
{ | { | ||||
struct i40e_hw *hw = vsi->hw; | struct ixl_pf *pf = vsi->back; | ||||
struct i40e_hw *hw = &pf->hw; | |||||
int index, error; | |||||
u32 reg; | u32 reg; | ||||
error = 0; | |||||
for (int i = 0; i < vsi->num_queues; i++) { | for (int i = 0; i < vsi->num_queues; i++) { | ||||
i40e_pre_tx_queue_cfg(hw, i, TRUE); | index = vsi->first_queue + i; | ||||
i40e_pre_tx_queue_cfg(hw, index, TRUE); | |||||
reg = rd32(hw, I40E_QTX_ENA(i)); | reg = rd32(hw, I40E_QTX_ENA(index)); | ||||
reg |= I40E_QTX_ENA_QENA_REQ_MASK | | reg |= I40E_QTX_ENA_QENA_REQ_MASK | | ||||
I40E_QTX_ENA_QENA_STAT_MASK; | I40E_QTX_ENA_QENA_STAT_MASK; | ||||
wr32(hw, I40E_QTX_ENA(i), reg); | wr32(hw, I40E_QTX_ENA(index), reg); | ||||
/* Verify the enable took */ | /* Verify the enable took */ | ||||
for (int j = 0; j < 10; j++) { | for (int j = 0; j < 10; j++) { | ||||
reg = rd32(hw, I40E_QTX_ENA(i)); | reg = rd32(hw, I40E_QTX_ENA(index)); | ||||
if (reg & I40E_QTX_ENA_QENA_STAT_MASK) | if (reg & I40E_QTX_ENA_QENA_STAT_MASK) | ||||
break; | break; | ||||
i40e_msec_delay(10); | i40e_msec_delay(10); | ||||
} | } | ||||
if ((reg & I40E_QTX_ENA_QENA_STAT_MASK) == 0) | if ((reg & I40E_QTX_ENA_QENA_STAT_MASK) == 0) { | ||||
printf("TX queue %d disabled!\n", i); | device_printf(pf->dev, "TX queue %d disabled!\n", | ||||
index); | |||||
error = ETIMEDOUT; | |||||
} | |||||
reg = rd32(hw, I40E_QRX_ENA(i)); | reg = rd32(hw, I40E_QRX_ENA(index)); | ||||
reg |= I40E_QRX_ENA_QENA_REQ_MASK | | reg |= I40E_QRX_ENA_QENA_REQ_MASK | | ||||
I40E_QRX_ENA_QENA_STAT_MASK; | I40E_QRX_ENA_QENA_STAT_MASK; | ||||
wr32(hw, I40E_QRX_ENA(i), reg); | wr32(hw, I40E_QRX_ENA(index), reg); | ||||
/* Verify the enable took */ | /* Verify the enable took */ | ||||
for (int j = 0; j < 10; j++) { | for (int j = 0; j < 10; j++) { | ||||
reg = rd32(hw, I40E_QRX_ENA(i)); | reg = rd32(hw, I40E_QRX_ENA(index)); | ||||
if (reg & I40E_QRX_ENA_QENA_STAT_MASK) | if (reg & I40E_QRX_ENA_QENA_STAT_MASK) | ||||
break; | break; | ||||
i40e_msec_delay(10); | i40e_msec_delay(10); | ||||
} | } | ||||
if ((reg & I40E_QRX_ENA_QENA_STAT_MASK) == 0) | if ((reg & I40E_QRX_ENA_QENA_STAT_MASK) == 0) { | ||||
printf("RX queue %d disabled!\n", i); | device_printf(pf->dev, "RX queue %d disabled!\n", | ||||
index); | |||||
error = ETIMEDOUT; | |||||
} | } | ||||
} | } | ||||
static void | return (error); | ||||
} | |||||
static int | |||||
ixl_disable_rings(struct ixl_vsi *vsi) | ixl_disable_rings(struct ixl_vsi *vsi) | ||||
{ | { | ||||
struct i40e_hw *hw = vsi->hw; | struct ixl_pf *pf = vsi->back; | ||||
struct i40e_hw *hw = &pf->hw; | |||||
int index, error; | |||||
u32 reg; | u32 reg; | ||||
error = 0; | |||||
for (int i = 0; i < vsi->num_queues; i++) { | for (int i = 0; i < vsi->num_queues; i++) { | ||||
i40e_pre_tx_queue_cfg(hw, i, FALSE); | index = vsi->first_queue + i; | ||||
i40e_pre_tx_queue_cfg(hw, index, FALSE); | |||||
i40e_usec_delay(500); | i40e_usec_delay(500); | ||||
reg = rd32(hw, I40E_QTX_ENA(i)); | reg = rd32(hw, I40E_QTX_ENA(index)); | ||||
reg &= ~I40E_QTX_ENA_QENA_REQ_MASK; | reg &= ~I40E_QTX_ENA_QENA_REQ_MASK; | ||||
wr32(hw, I40E_QTX_ENA(i), reg); | wr32(hw, I40E_QTX_ENA(index), reg); | ||||
/* Verify the disable took */ | /* Verify the disable took */ | ||||
for (int j = 0; j < 10; j++) { | for (int j = 0; j < 10; j++) { | ||||
reg = rd32(hw, I40E_QTX_ENA(i)); | reg = rd32(hw, I40E_QTX_ENA(index)); | ||||
if (!(reg & I40E_QTX_ENA_QENA_STAT_MASK)) | if (!(reg & I40E_QTX_ENA_QENA_STAT_MASK)) | ||||
break; | break; | ||||
i40e_msec_delay(10); | i40e_msec_delay(10); | ||||
} | } | ||||
if (reg & I40E_QTX_ENA_QENA_STAT_MASK) | if (reg & I40E_QTX_ENA_QENA_STAT_MASK) { | ||||
printf("TX queue %d still enabled!\n", i); | device_printf(pf->dev, "TX queue %d still enabled!\n", | ||||
index); | |||||
error = ETIMEDOUT; | |||||
} | |||||
reg = rd32(hw, I40E_QRX_ENA(i)); | reg = rd32(hw, I40E_QRX_ENA(index)); | ||||
reg &= ~I40E_QRX_ENA_QENA_REQ_MASK; | reg &= ~I40E_QRX_ENA_QENA_REQ_MASK; | ||||
wr32(hw, I40E_QRX_ENA(i), reg); | wr32(hw, I40E_QRX_ENA(index), reg); | ||||
/* Verify the disable took */ | /* Verify the disable took */ | ||||
for (int j = 0; j < 10; j++) { | for (int j = 0; j < 10; j++) { | ||||
reg = rd32(hw, I40E_QRX_ENA(i)); | reg = rd32(hw, I40E_QRX_ENA(index)); | ||||
if (!(reg & I40E_QRX_ENA_QENA_STAT_MASK)) | if (!(reg & I40E_QRX_ENA_QENA_STAT_MASK)) | ||||
break; | break; | ||||
i40e_msec_delay(10); | i40e_msec_delay(10); | ||||
} | } | ||||
if (reg & I40E_QRX_ENA_QENA_STAT_MASK) | if (reg & I40E_QRX_ENA_QENA_STAT_MASK) { | ||||
printf("RX queue %d still enabled!\n", i); | device_printf(pf->dev, "RX queue %d still enabled!\n", | ||||
index); | |||||
error = ETIMEDOUT; | |||||
} | } | ||||
} | } | ||||
return (error); | |||||
} | |||||
/** | /** | ||||
* ixl_handle_mdd_event | * ixl_handle_mdd_event | ||||
* | * | ||||
* Called from interrupt handler to identify possibly malicious vfs | * Called from interrupt handler to identify possibly malicious vfs | ||||
* (But also detects events from the PF, as well) | * (But also detects events from the PF, as well) | ||||
**/ | **/ | ||||
static void ixl_handle_mdd_event(struct ixl_pf *pf) | static void ixl_handle_mdd_event(struct ixl_pf *pf) | ||||
{ | { | ||||
▲ Show 20 Lines • Show All 317 Lines • ▼ Show 20 Lines | ixl_stat_update32(hw, I40E_GLPRT_ROC(hw->port), | ||||
&osd->rx_oversize, &nsd->rx_oversize); | &osd->rx_oversize, &nsd->rx_oversize); | ||||
ixl_stat_update32(hw, I40E_GLPRT_RJC(hw->port), | ixl_stat_update32(hw, I40E_GLPRT_RJC(hw->port), | ||||
pf->stat_offsets_loaded, | pf->stat_offsets_loaded, | ||||
&osd->rx_jabber, &nsd->rx_jabber); | &osd->rx_jabber, &nsd->rx_jabber); | ||||
pf->stat_offsets_loaded = true; | pf->stat_offsets_loaded = true; | ||||
/* End hw stats */ | /* End hw stats */ | ||||
/* Update vsi stats */ | /* Update vsi stats */ | ||||
ixl_update_eth_stats(vsi); | ixl_update_vsi_stats(vsi); | ||||
/* OS statistics */ | /* OS statistics */ | ||||
// ERJ - these are per-port, update all vsis? | // ERJ - these are per-port, update all vsis? | ||||
IXL_SET_IERRORS(vsi, nsd->crc_errors + nsd->illegal_bytes); | IXL_SET_IERRORS(vsi, nsd->crc_errors + nsd->illegal_bytes); | ||||
} | } | ||||
/* | /* | ||||
** Tasklet handler for MSIX Adminq interrupts | ** Tasklet handler for MSIX Adminq interrupts | ||||
▲ Show 20 Lines • Show All 123 Lines • ▼ Show 20 Lines | |||||
* Update VSI-specific ethernet statistics counters. | * Update VSI-specific ethernet statistics counters. | ||||
**/ | **/ | ||||
void ixl_update_eth_stats(struct ixl_vsi *vsi) | void ixl_update_eth_stats(struct ixl_vsi *vsi) | ||||
{ | { | ||||
struct ixl_pf *pf = (struct ixl_pf *)vsi->back; | struct ixl_pf *pf = (struct ixl_pf *)vsi->back; | ||||
struct i40e_hw *hw = &pf->hw; | struct i40e_hw *hw = &pf->hw; | ||||
struct i40e_eth_stats *es; | struct i40e_eth_stats *es; | ||||
struct i40e_eth_stats *oes; | struct i40e_eth_stats *oes; | ||||
int i; | |||||
uint64_t tx_discards; | |||||
struct i40e_hw_port_stats *nsd; | struct i40e_hw_port_stats *nsd; | ||||
u16 stat_idx = vsi->info.stat_counter_idx; | u16 stat_idx = vsi->info.stat_counter_idx; | ||||
es = &vsi->eth_stats; | es = &vsi->eth_stats; | ||||
oes = &vsi->eth_stats_offsets; | oes = &vsi->eth_stats_offsets; | ||||
nsd = &pf->stats; | nsd = &pf->stats; | ||||
/* Gather up the stats that the hw collects */ | /* Gather up the stats that the hw collects */ | ||||
Show All 33 Lines | ixl_stat_update48(hw, I40E_GLV_MPTCH(stat_idx), | ||||
I40E_GLV_MPTCL(stat_idx), | I40E_GLV_MPTCL(stat_idx), | ||||
vsi->stat_offsets_loaded, | vsi->stat_offsets_loaded, | ||||
&oes->tx_multicast, &es->tx_multicast); | &oes->tx_multicast, &es->tx_multicast); | ||||
ixl_stat_update48(hw, I40E_GLV_BPTCH(stat_idx), | ixl_stat_update48(hw, I40E_GLV_BPTCH(stat_idx), | ||||
I40E_GLV_BPTCL(stat_idx), | I40E_GLV_BPTCL(stat_idx), | ||||
vsi->stat_offsets_loaded, | vsi->stat_offsets_loaded, | ||||
&oes->tx_broadcast, &es->tx_broadcast); | &oes->tx_broadcast, &es->tx_broadcast); | ||||
vsi->stat_offsets_loaded = true; | vsi->stat_offsets_loaded = true; | ||||
} | |||||
static void | |||||
ixl_update_vsi_stats(struct ixl_vsi *vsi) | |||||
{ | |||||
struct ixl_pf *pf; | |||||
struct ifnet *ifp; | |||||
struct i40e_eth_stats *es; | |||||
struct i40e_hw_port_stats *nsd; | |||||
uint64_t tx_discards; | |||||
int i; | |||||
pf = vsi->back; | |||||
ifp = vsi->ifp; | |||||
es = &vsi->eth_stats; | |||||
nsd = &pf->stats; | |||||
ixl_update_eth_stats(vsi); | |||||
tx_discards = es->tx_discards + nsd->tx_dropped_link_down; | tx_discards = es->tx_discards + nsd->tx_dropped_link_down; | ||||
for (i = 0; i < vsi->num_queues; i++) | for (i = 0; i < vsi->num_queues; i++) | ||||
tx_discards += vsi->queues[i].txr.br->br_drops; | tx_discards += vsi->queues[i].txr.br->br_drops; | ||||
/* Update ifnet stats */ | /* Update ifnet stats */ | ||||
IXL_SET_IPACKETS(vsi, es->rx_unicast + | IXL_SET_IPACKETS(vsi, es->rx_unicast + | ||||
es->rx_multicast + | es->rx_multicast + | ||||
es->rx_broadcast); | es->rx_broadcast); | ||||
▲ Show 20 Lines • Show All 733 Lines • ▼ Show 20 Lines | ixl_sysctl_dump_txd(SYSCTL_HANDLER_ARGS) | ||||
// Don't use this sysctl yet | // Don't use this sysctl yet | ||||
if (TRUE) | if (TRUE) | ||||
return (ENODEV); | return (ENODEV); | ||||
sbuf_cat(buf, "\n"); | sbuf_cat(buf, "\n"); | ||||
// set to queue 1? | // set to queue 1? | ||||
struct ixl_queue *que = pf->vsi.queues; | struct ixl_queue *que = pf->queues; | ||||
struct tx_ring *txr = &(que[1].txr); | struct tx_ring *txr = &(que[1].txr); | ||||
struct i40e_tx_desc *txd = &txr->base[desc_idx]; | struct i40e_tx_desc *txd = &txr->base[desc_idx]; | ||||
sbuf_printf(buf, "Que: %d, Desc: %d\n", que->me, desc_idx); | sbuf_printf(buf, "Que: %d, Desc: %d\n", que->me, desc_idx); | ||||
sbuf_printf(buf, "Addr: %#18lx\n", txd->buffer_addr); | sbuf_printf(buf, "Addr: %#18lx\n", txd->buffer_addr); | ||||
sbuf_printf(buf, "Opts: %#18lx\n", txd->cmd_type_offset_bsz); | sbuf_printf(buf, "Opts: %#18lx\n", txd->cmd_type_offset_bsz); | ||||
error = sbuf_finish(buf); | error = sbuf_finish(buf); | ||||
Show All 14 Lines |