Changeset View
Changeset View
Standalone View
Standalone View
sys/dev/ixl/ixlvc.c
Show First 20 Lines • Show All 63 Lines • ▼ Show 20 Lines | static int ixl_vc_validate_vf_msg(struct ixlv_sc *sc, u32 v_opcode, | ||||
int valid_len; | int valid_len; | ||||
/* Validate message length. */ | /* Validate message length. */ | ||||
switch (v_opcode) { | switch (v_opcode) { | ||||
case I40E_VIRTCHNL_OP_VERSION: | case I40E_VIRTCHNL_OP_VERSION: | ||||
valid_len = sizeof(struct i40e_virtchnl_version_info); | valid_len = sizeof(struct i40e_virtchnl_version_info); | ||||
break; | break; | ||||
case I40E_VIRTCHNL_OP_RESET_VF: | case I40E_VIRTCHNL_OP_RESET_VF: | ||||
valid_len = 0; | |||||
break; | |||||
case I40E_VIRTCHNL_OP_GET_VF_RESOURCES: | case I40E_VIRTCHNL_OP_GET_VF_RESOURCES: | ||||
// TODO: valid length in api v1.0 is 0, v1.1 is 4 | /* Valid length in api v1.0 is 0, v1.1 is 4 */ | ||||
valid_len = 4; | valid_len = 4; | ||||
break; | break; | ||||
case I40E_VIRTCHNL_OP_CONFIG_TX_QUEUE: | case I40E_VIRTCHNL_OP_CONFIG_TX_QUEUE: | ||||
valid_len = sizeof(struct i40e_virtchnl_txq_info); | valid_len = sizeof(struct i40e_virtchnl_txq_info); | ||||
break; | break; | ||||
case I40E_VIRTCHNL_OP_CONFIG_RX_QUEUE: | case I40E_VIRTCHNL_OP_CONFIG_RX_QUEUE: | ||||
valid_len = sizeof(struct i40e_virtchnl_rxq_info); | valid_len = sizeof(struct i40e_virtchnl_rxq_info); | ||||
break; | break; | ||||
▲ Show 20 Lines • Show All 131 Lines • ▼ Show 20 Lines | |||||
{ | { | ||||
struct i40e_virtchnl_version_info *pf_vvi; | struct i40e_virtchnl_version_info *pf_vvi; | ||||
struct i40e_hw *hw = &sc->hw; | struct i40e_hw *hw = &sc->hw; | ||||
struct i40e_arq_event_info event; | struct i40e_arq_event_info event; | ||||
device_t dev = sc->dev; | device_t dev = sc->dev; | ||||
i40e_status err; | i40e_status err; | ||||
int retries = 0; | int retries = 0; | ||||
event.buf_len = IXL_AQ_BUFSZ; | event.buf_len = IXL_AQ_BUF_SZ; | ||||
event.msg_buf = malloc(event.buf_len, M_DEVBUF, M_NOWAIT); | event.msg_buf = malloc(event.buf_len, M_DEVBUF, M_NOWAIT); | ||||
if (!event.msg_buf) { | if (!event.msg_buf) { | ||||
err = ENOMEM; | err = ENOMEM; | ||||
goto out; | goto out; | ||||
} | } | ||||
for (;;) { | for (;;) { | ||||
if (++retries > IXLV_AQ_MAX_ERR) | if (++retries > IXLV_AQ_MAX_ERR) | ||||
goto out_alloc; | goto out_alloc; | ||||
/* Initial delay here is necessary */ | /* Initial delay here is necessary */ | ||||
i40e_msec_delay(100); | i40e_msec_pause(100); | ||||
err = i40e_clean_arq_element(hw, &event, NULL); | err = i40e_clean_arq_element(hw, &event, NULL); | ||||
if (err == I40E_ERR_ADMIN_QUEUE_NO_WORK) | if (err == I40E_ERR_ADMIN_QUEUE_NO_WORK) | ||||
continue; | continue; | ||||
else if (err) { | else if (err) { | ||||
err = EIO; | err = EIO; | ||||
goto out_alloc; | goto out_alloc; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 41 Lines • ▼ Show 20 Lines | |||||
** successfully sent, or one of the I40E_ADMIN_QUEUE_ERROR_ statuses if not. | ** successfully sent, or one of the I40E_ADMIN_QUEUE_ERROR_ statuses if not. | ||||
*/ | */ | ||||
int | int | ||||
ixlv_send_vf_config_msg(struct ixlv_sc *sc) | ixlv_send_vf_config_msg(struct ixlv_sc *sc) | ||||
{ | { | ||||
u32 caps; | u32 caps; | ||||
caps = I40E_VIRTCHNL_VF_OFFLOAD_L2 | | caps = I40E_VIRTCHNL_VF_OFFLOAD_L2 | | ||||
I40E_VIRTCHNL_VF_OFFLOAD_RSS_REG | | I40E_VIRTCHNL_VF_OFFLOAD_RSS_PF | | ||||
I40E_VIRTCHNL_VF_OFFLOAD_VLAN; | I40E_VIRTCHNL_VF_OFFLOAD_VLAN; | ||||
if (sc->pf_version == I40E_VIRTCHNL_VERSION_MINOR_NO_VF_CAPS) | if (sc->pf_version == I40E_VIRTCHNL_VERSION_MINOR_NO_VF_CAPS) | ||||
return ixlv_send_pf_msg(sc, I40E_VIRTCHNL_OP_GET_VF_RESOURCES, | return ixlv_send_pf_msg(sc, I40E_VIRTCHNL_OP_GET_VF_RESOURCES, | ||||
NULL, 0); | NULL, 0); | ||||
else | else | ||||
return ixlv_send_pf_msg(sc, I40E_VIRTCHNL_OP_GET_VF_RESOURCES, | return ixlv_send_pf_msg(sc, I40E_VIRTCHNL_OP_GET_VF_RESOURCES, | ||||
(u8 *)&caps, sizeof(caps)); | (u8 *)&caps, sizeof(caps)); | ||||
Show All 26 Lines | if (!event.msg_buf) { | ||||
err = ENOMEM; | err = ENOMEM; | ||||
goto out; | goto out; | ||||
} | } | ||||
for (;;) { | for (;;) { | ||||
err = i40e_clean_arq_element(hw, &event, NULL); | err = i40e_clean_arq_element(hw, &event, NULL); | ||||
if (err == I40E_ERR_ADMIN_QUEUE_NO_WORK) { | if (err == I40E_ERR_ADMIN_QUEUE_NO_WORK) { | ||||
if (++retries <= IXLV_AQ_MAX_ERR) | if (++retries <= IXLV_AQ_MAX_ERR) | ||||
i40e_msec_delay(10); | i40e_msec_pause(10); | ||||
} else if ((enum i40e_virtchnl_ops)le32toh(event.desc.cookie_high) != | } else if ((enum i40e_virtchnl_ops)le32toh(event.desc.cookie_high) != | ||||
I40E_VIRTCHNL_OP_GET_VF_RESOURCES) { | I40E_VIRTCHNL_OP_GET_VF_RESOURCES) { | ||||
DDPRINTF(dev, "Received a response from PF," | DDPRINTF(dev, "Received a response from PF," | ||||
" opcode %d, error %d", | " opcode %d, error %d", | ||||
le32toh(event.desc.cookie_high), | le32toh(event.desc.cookie_high), | ||||
le32toh(event.desc.cookie_low)); | le32toh(event.desc.cookie_low)); | ||||
retries++; | retries++; | ||||
continue; | continue; | ||||
▲ Show 20 Lines • Show All 150 Lines • ▼ Show 20 Lines | ixlv_map_queues(struct ixlv_sc *sc) | ||||
vm->num_vectors = sc->msix; | vm->num_vectors = sc->msix; | ||||
/* Queue vectors first */ | /* Queue vectors first */ | ||||
for (i = 0; i < q; i++, que++) { | for (i = 0; i < q; i++, que++) { | ||||
vm->vecmap[i].vsi_id = sc->vsi_res->vsi_id; | vm->vecmap[i].vsi_id = sc->vsi_res->vsi_id; | ||||
vm->vecmap[i].vector_id = i + 1; /* first is adminq */ | vm->vecmap[i].vector_id = i + 1; /* first is adminq */ | ||||
vm->vecmap[i].txq_map = (1 << que->me); | vm->vecmap[i].txq_map = (1 << que->me); | ||||
vm->vecmap[i].rxq_map = (1 << que->me); | vm->vecmap[i].rxq_map = (1 << que->me); | ||||
vm->vecmap[i].rxitr_idx = 0; | vm->vecmap[i].rxitr_idx = 0; | ||||
vm->vecmap[i].txitr_idx = 0; | vm->vecmap[i].txitr_idx = 1; | ||||
} | } | ||||
/* Misc vector last - this is only for AdminQ messages */ | /* Misc vector last - this is only for AdminQ messages */ | ||||
vm->vecmap[i].vsi_id = sc->vsi_res->vsi_id; | vm->vecmap[i].vsi_id = sc->vsi_res->vsi_id; | ||||
vm->vecmap[i].vector_id = 0; | vm->vecmap[i].vector_id = 0; | ||||
vm->vecmap[i].txq_map = 0; | vm->vecmap[i].txq_map = 0; | ||||
vm->vecmap[i].rxq_map = 0; | vm->vecmap[i].rxq_map = 0; | ||||
vm->vecmap[i].rxitr_idx = 0; | vm->vecmap[i].rxitr_idx = 0; | ||||
▲ Show 20 Lines • Show All 55 Lines • ▼ Show 20 Lines | SLIST_FOREACH_SAFE(f, sc->vlan_filters, next, ftmp) { | ||||
if (f->flags & IXL_FILTER_ADD) { | if (f->flags & IXL_FILTER_ADD) { | ||||
bcopy(&f->vlan, &v->vlan_id[i], sizeof(u16)); | bcopy(&f->vlan, &v->vlan_id[i], sizeof(u16)); | ||||
f->flags = IXL_FILTER_USED; | f->flags = IXL_FILTER_USED; | ||||
i++; | i++; | ||||
} | } | ||||
if (i == cnt) | if (i == cnt) | ||||
break; | break; | ||||
} | } | ||||
// ERJ: Should this be taken out? | |||||
if (i == 0) { /* Should not happen... */ | |||||
device_printf(dev, "%s: i == 0?\n", __func__); | |||||
ixl_vc_process_resp(&sc->vc_mgr, IXLV_FLAG_AQ_ADD_VLAN_FILTER, | |||||
I40E_SUCCESS); | |||||
return; | |||||
} | |||||
ixlv_send_pf_msg(sc, I40E_VIRTCHNL_OP_ADD_VLAN, (u8 *)v, len); | ixlv_send_pf_msg(sc, I40E_VIRTCHNL_OP_ADD_VLAN, (u8 *)v, len); | ||||
free(v, M_DEVBUF); | free(v, M_DEVBUF); | ||||
/* add stats? */ | /* add stats? */ | ||||
} | } | ||||
/* | /* | ||||
** Scan the Filter Table looking for vlans that need | ** Scan the Filter Table looking for vlans that need | ||||
▲ Show 20 Lines • Show All 47 Lines • ▼ Show 20 Lines | SLIST_FOREACH_SAFE(f, sc->vlan_filters, next, ftmp) { | ||||
bcopy(&f->vlan, &v->vlan_id[i], sizeof(u16)); | bcopy(&f->vlan, &v->vlan_id[i], sizeof(u16)); | ||||
i++; | i++; | ||||
SLIST_REMOVE(sc->vlan_filters, f, ixlv_vlan_filter, next); | SLIST_REMOVE(sc->vlan_filters, f, ixlv_vlan_filter, next); | ||||
free(f, M_DEVBUF); | free(f, M_DEVBUF); | ||||
} | } | ||||
if (i == cnt) | if (i == cnt) | ||||
break; | break; | ||||
} | } | ||||
// ERJ: Take this out? | |||||
if (i == 0) { /* Should not happen... */ | |||||
device_printf(dev, "%s: i == 0?\n", __func__); | |||||
ixl_vc_process_resp(&sc->vc_mgr, IXLV_FLAG_AQ_DEL_VLAN_FILTER, | |||||
I40E_SUCCESS); | |||||
return; | |||||
} | |||||
ixlv_send_pf_msg(sc, I40E_VIRTCHNL_OP_DEL_VLAN, (u8 *)v, len); | ixlv_send_pf_msg(sc, I40E_VIRTCHNL_OP_DEL_VLAN, (u8 *)v, len); | ||||
free(v, M_DEVBUF); | free(v, M_DEVBUF); | ||||
/* add stats? */ | /* add stats? */ | ||||
} | } | ||||
/* | /* | ||||
▲ Show 20 Lines • Show All 179 Lines • ▼ Show 20 Lines | ixlv_update_stats_counters(struct ixlv_sc *sc, struct i40e_eth_stats *es) | ||||
IXL_SET_IQDROPS(vsi, es->rx_discards); | IXL_SET_IQDROPS(vsi, es->rx_discards); | ||||
IXL_SET_OQDROPS(vsi, tx_discards); | IXL_SET_OQDROPS(vsi, tx_discards); | ||||
IXL_SET_NOPROTO(vsi, es->rx_unknown_protocol); | IXL_SET_NOPROTO(vsi, es->rx_unknown_protocol); | ||||
IXL_SET_COLLISIONS(vsi, 0); | IXL_SET_COLLISIONS(vsi, 0); | ||||
vsi->eth_stats = *es; | vsi->eth_stats = *es; | ||||
} | } | ||||
void | |||||
ixlv_config_rss_key(struct ixlv_sc *sc) | |||||
{ | |||||
struct i40e_virtchnl_rss_key *rss_key_msg; | |||||
int msg_len, key_length; | |||||
u8 rss_seed[IXL_RSS_KEY_SIZE]; | |||||
#ifdef RSS | |||||
u32 rss_hash_config; | |||||
#endif | |||||
#ifdef RSS | |||||
/* Fetch the configured RSS key */ | |||||
rss_getkey(&rss_seed); | |||||
#else | |||||
ixl_get_default_rss_key((u32 *)rss_seed); | |||||
#endif | |||||
/* Send the fetched key */ | |||||
key_length = IXL_RSS_KEY_SIZE; | |||||
msg_len = sizeof(struct i40e_virtchnl_rss_key) + (sizeof(u8) * key_length) - 1; | |||||
rss_key_msg = malloc(msg_len, M_DEVBUF, M_NOWAIT | M_ZERO); | |||||
if (rss_key_msg == NULL) { | |||||
device_printf(sc->dev, "Unable to allocate msg memory for RSS key msg.\n"); | |||||
return; | |||||
} | |||||
rss_key_msg->vsi_id = sc->vsi_res->vsi_id; | |||||
rss_key_msg->key_len = key_length; | |||||
bcopy(rss_seed, &rss_key_msg->key[0], key_length); | |||||
DDPRINTF(sc->dev, "config_rss: vsi_id %d, key_len %d", | |||||
rss_key_msg->vsi_id, rss_key_msg->key_len); | |||||
ixlv_send_pf_msg(sc, I40E_VIRTCHNL_OP_CONFIG_RSS_KEY, | |||||
(u8 *)rss_key_msg, msg_len); | |||||
free(rss_key_msg, M_DEVBUF); | |||||
} | |||||
void | |||||
ixlv_set_rss_hena(struct ixlv_sc *sc) | |||||
{ | |||||
struct i40e_virtchnl_rss_hena hena; | |||||
hena.hena = IXL_DEFAULT_RSS_HENA; | |||||
ixlv_send_pf_msg(sc, I40E_VIRTCHNL_OP_SET_RSS_HENA, | |||||
(u8 *)&hena, sizeof(hena)); | |||||
} | |||||
void | |||||
ixlv_config_rss_lut(struct ixlv_sc *sc) | |||||
{ | |||||
struct i40e_virtchnl_rss_lut *rss_lut_msg; | |||||
int msg_len; | |||||
u16 lut_length; | |||||
u32 lut; | |||||
int i, que_id; | |||||
lut_length = IXL_RSS_VSI_LUT_SIZE; | |||||
msg_len = sizeof(struct i40e_virtchnl_rss_lut) + (lut_length * sizeof(u8)) - 1; | |||||
rss_lut_msg = malloc(msg_len, M_DEVBUF, M_NOWAIT | M_ZERO); | |||||
if (rss_lut_msg == NULL) { | |||||
device_printf(sc->dev, "Unable to allocate msg memory for RSS lut msg.\n"); | |||||
return; | |||||
} | |||||
rss_lut_msg->vsi_id = sc->vsi_res->vsi_id; | |||||
/* Each LUT entry is a max of 1 byte, so this is easy */ | |||||
rss_lut_msg->lut_entries = lut_length; | |||||
/* Populate the LUT with max no. of queues in round robin fashion */ | |||||
for (i = 0; i < lut_length; i++) { | |||||
#ifdef RSS | |||||
/* | /* | ||||
* Fetch the RSS bucket id for the given indirection entry. | |||||
* Cap it at the number of configured buckets (which is | |||||
* num_queues.) | |||||
*/ | |||||
que_id = rss_get_indirection_to_bucket(i); | |||||
que_id = que_id % sc->vsi.num_queues; | |||||
#else | |||||
que_id = i % sc->vsi.num_queues; | |||||
#endif | |||||
lut = que_id & IXL_RSS_VSI_LUT_ENTRY_MASK; | |||||
rss_lut_msg->lut[i] = lut; | |||||
} | |||||
ixlv_send_pf_msg(sc, I40E_VIRTCHNL_OP_CONFIG_RSS_LUT, | |||||
(u8 *)rss_lut_msg, msg_len); | |||||
free(rss_lut_msg, M_DEVBUF); | |||||
} | |||||
/* | |||||
** ixlv_vc_completion | ** ixlv_vc_completion | ||||
** | ** | ||||
** Asynchronous completion function for admin queue messages. Rather than busy | ** Asynchronous completion function for admin queue messages. Rather than busy | ||||
** wait, we fire off our requests and assume that no errors will be returned. | ** wait, we fire off our requests and assume that no errors will be returned. | ||||
** This function handles the reply messages. | ** This function handles the reply messages. | ||||
*/ | */ | ||||
void | void | ||||
ixlv_vc_completion(struct ixlv_sc *sc, | ixlv_vc_completion(struct ixlv_sc *sc, | ||||
▲ Show 20 Lines • Show All 81 Lines • ▼ Show 20 Lines | ixl_vc_process_resp(&sc->vc_mgr, IXLV_FLAG_AQ_ENABLE_QUEUES, | ||||
v_retval); | v_retval); | ||||
if (v_retval == 0) { | if (v_retval == 0) { | ||||
/* Update link status */ | /* Update link status */ | ||||
ixlv_update_link_status(sc); | ixlv_update_link_status(sc); | ||||
/* Turn on all interrupts */ | /* Turn on all interrupts */ | ||||
ixlv_enable_intr(vsi); | ixlv_enable_intr(vsi); | ||||
/* And inform the stack we're ready */ | /* And inform the stack we're ready */ | ||||
vsi->ifp->if_drv_flags |= IFF_DRV_RUNNING; | vsi->ifp->if_drv_flags |= IFF_DRV_RUNNING; | ||||
vsi->ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; | /* TODO: Clear a state flag, so we know we're ready to run init again */ | ||||
} | } | ||||
break; | break; | ||||
case I40E_VIRTCHNL_OP_DISABLE_QUEUES: | case I40E_VIRTCHNL_OP_DISABLE_QUEUES: | ||||
ixl_vc_process_resp(&sc->vc_mgr, IXLV_FLAG_AQ_DISABLE_QUEUES, | ixl_vc_process_resp(&sc->vc_mgr, IXLV_FLAG_AQ_DISABLE_QUEUES, | ||||
v_retval); | v_retval); | ||||
if (v_retval == 0) { | if (v_retval == 0) { | ||||
/* Turn off all interrupts */ | /* Turn off all interrupts */ | ||||
ixlv_disable_intr(vsi); | ixlv_disable_intr(vsi); | ||||
/* Tell the stack that the interface is no longer active */ | /* Tell the stack that the interface is no longer active */ | ||||
vsi->ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); | vsi->ifp->if_drv_flags &= ~(IFF_DRV_RUNNING); | ||||
} | } | ||||
break; | break; | ||||
case I40E_VIRTCHNL_OP_CONFIG_VSI_QUEUES: | case I40E_VIRTCHNL_OP_CONFIG_VSI_QUEUES: | ||||
ixl_vc_process_resp(&sc->vc_mgr, IXLV_FLAG_AQ_CONFIGURE_QUEUES, | ixl_vc_process_resp(&sc->vc_mgr, IXLV_FLAG_AQ_CONFIGURE_QUEUES, | ||||
v_retval); | v_retval); | ||||
break; | break; | ||||
case I40E_VIRTCHNL_OP_CONFIG_IRQ_MAP: | case I40E_VIRTCHNL_OP_CONFIG_IRQ_MAP: | ||||
ixl_vc_process_resp(&sc->vc_mgr, IXLV_FLAG_AQ_MAP_VECTORS, | ixl_vc_process_resp(&sc->vc_mgr, IXLV_FLAG_AQ_MAP_VECTORS, | ||||
v_retval); | v_retval); | ||||
break; | break; | ||||
case I40E_VIRTCHNL_OP_CONFIG_RSS_KEY: | |||||
ixl_vc_process_resp(&sc->vc_mgr, IXLV_FLAG_AQ_CONFIG_RSS_KEY, | |||||
v_retval); | |||||
break; | |||||
case I40E_VIRTCHNL_OP_SET_RSS_HENA: | |||||
ixl_vc_process_resp(&sc->vc_mgr, IXLV_FLAG_AQ_SET_RSS_HENA, | |||||
v_retval); | |||||
break; | |||||
case I40E_VIRTCHNL_OP_CONFIG_RSS_LUT: | |||||
ixl_vc_process_resp(&sc->vc_mgr, IXLV_FLAG_AQ_CONFIG_RSS_LUT, | |||||
v_retval); | |||||
break; | |||||
default: | default: | ||||
#ifdef IXL_DEBUG | #ifdef IXL_DEBUG | ||||
device_printf(dev, | device_printf(dev, | ||||
"%s: Received unexpected message %d from PF.\n", | "%s: Received unexpected message %d from PF.\n", | ||||
__func__, v_opcode); | __func__, v_opcode); | ||||
#endif | #endif | ||||
break; | break; | ||||
} | } | ||||
Show All 30 Lines | case IXLV_FLAG_AQ_CONFIGURE_QUEUES: | ||||
break; | break; | ||||
case IXLV_FLAG_AQ_DISABLE_QUEUES: | case IXLV_FLAG_AQ_DISABLE_QUEUES: | ||||
ixlv_disable_queues(sc); | ixlv_disable_queues(sc); | ||||
break; | break; | ||||
case IXLV_FLAG_AQ_ENABLE_QUEUES: | case IXLV_FLAG_AQ_ENABLE_QUEUES: | ||||
ixlv_enable_queues(sc); | ixlv_enable_queues(sc); | ||||
break; | |||||
case IXLV_FLAG_AQ_CONFIG_RSS_KEY: | |||||
ixlv_config_rss_key(sc); | |||||
break; | |||||
case IXLV_FLAG_AQ_SET_RSS_HENA: | |||||
ixlv_set_rss_hena(sc); | |||||
break; | |||||
case IXLV_FLAG_AQ_CONFIG_RSS_LUT: | |||||
ixlv_config_rss_lut(sc); | |||||
break; | break; | ||||
} | } | ||||
} | } | ||||
void | void | ||||
ixl_vc_init_mgr(struct ixlv_sc *sc, struct ixl_vc_mgr *mgr) | ixl_vc_init_mgr(struct ixlv_sc *sc, struct ixl_vc_mgr *mgr) | ||||
{ | { | ||||
mgr->sc = sc; | mgr->sc = sc; | ||||
▲ Show 20 Lines • Show All 132 Lines • Show Last 20 Lines |