Changeset View
Changeset View
Standalone View
Standalone View
sys/dev/ixl/ixl_pf_iov.c
Show First 20 Lines • Show All 83 Lines • ▼ Show 20 Lines | |||||
ixl_initialize_sriov(struct ixl_pf *pf) | ixl_initialize_sriov(struct ixl_pf *pf) | ||||
{ | { | ||||
device_t dev = pf->dev; | device_t dev = pf->dev; | ||||
struct i40e_hw *hw = &pf->hw; | struct i40e_hw *hw = &pf->hw; | ||||
nvlist_t *pf_schema, *vf_schema; | nvlist_t *pf_schema, *vf_schema; | ||||
int iov_error; | int iov_error; | ||||
/* SR-IOV is only supported when MSI-X is in use. */ | /* SR-IOV is only supported when MSI-X is in use. */ | ||||
// TODO: Make iflib stop using VSI as its softc | |||||
#if 0 | |||||
if (pf->msix <= 1) | if (pf->msix <= 1) | ||||
return; | return; | ||||
#endif | |||||
pf_schema = pci_iov_schema_alloc_node(); | pf_schema = pci_iov_schema_alloc_node(); | ||||
vf_schema = pci_iov_schema_alloc_node(); | vf_schema = pci_iov_schema_alloc_node(); | ||||
pci_iov_schema_add_unicast_mac(vf_schema, "mac-addr", 0, NULL); | pci_iov_schema_add_unicast_mac(vf_schema, "mac-addr", 0, NULL); | ||||
pci_iov_schema_add_bool(vf_schema, "mac-anti-spoof", | pci_iov_schema_add_bool(vf_schema, "mac-anti-spoof", | ||||
IOV_SCHEMA_HASDEFAULT, TRUE); | IOV_SCHEMA_HASDEFAULT, TRUE); | ||||
pci_iov_schema_add_bool(vf_schema, "allow-set-mac", | pci_iov_schema_add_bool(vf_schema, "allow-set-mac", | ||||
IOV_SCHEMA_HASDEFAULT, FALSE); | IOV_SCHEMA_HASDEFAULT, FALSE); | ||||
▲ Show 20 Lines • Show All 50 Lines • ▼ Show 20 Lines | ixl_vf_alloc_vsi(struct ixl_pf *pf, struct ixl_vf *vf) | ||||
vsi_ctx.info.valid_sections |= htole16(I40E_AQ_VSI_PROP_VLAN_VALID); | vsi_ctx.info.valid_sections |= htole16(I40E_AQ_VSI_PROP_VLAN_VALID); | ||||
vsi_ctx.info.port_vlan_flags = I40E_AQ_VSI_PVLAN_MODE_ALL | | vsi_ctx.info.port_vlan_flags = I40E_AQ_VSI_PVLAN_MODE_ALL | | ||||
I40E_AQ_VSI_PVLAN_EMOD_NOTHING; | I40E_AQ_VSI_PVLAN_EMOD_NOTHING; | ||||
vsi_ctx.info.valid_sections |= | vsi_ctx.info.valid_sections |= | ||||
htole16(I40E_AQ_VSI_PROP_QUEUE_MAP_VALID); | htole16(I40E_AQ_VSI_PROP_QUEUE_MAP_VALID); | ||||
vsi_ctx.info.mapping_flags = htole16(I40E_AQ_VSI_QUE_MAP_NONCONTIG); | vsi_ctx.info.mapping_flags = htole16(I40E_AQ_VSI_QUE_MAP_NONCONTIG); | ||||
/* ERJ: Only scattered allocation is supported for VFs right now */ | /* XXX: Only scattered allocation is supported for VFs right now */ | ||||
for (i = 0; i < vf->qtag.num_active; i++) | for (i = 0; i < vf->qtag.num_active; i++) | ||||
vsi_ctx.info.queue_mapping[i] = vf->qtag.qidx[i]; | vsi_ctx.info.queue_mapping[i] = vf->qtag.qidx[i]; | ||||
for (; i < nitems(vsi_ctx.info.queue_mapping); i++) | for (; i < nitems(vsi_ctx.info.queue_mapping); i++) | ||||
vsi_ctx.info.queue_mapping[i] = htole16(I40E_AQ_VSI_QUEUE_MASK); | vsi_ctx.info.queue_mapping[i] = htole16(I40E_AQ_VSI_QUEUE_MASK); | ||||
vsi_ctx.info.tc_mapping[0] = htole16( | vsi_ctx.info.tc_mapping[0] = htole16( | ||||
(0 << I40E_AQ_VSI_TC_QUE_OFFSET_SHIFT) | | (0 << I40E_AQ_VSI_TC_QUE_OFFSET_SHIFT) | | ||||
(bsrl(vf->qtag.num_allocated) << I40E_AQ_VSI_TC_QUE_NUMBER_SHIFT)); | (bsrl(vf->qtag.num_allocated) << I40E_AQ_VSI_TC_QUE_NUMBER_SHIFT)); | ||||
code = i40e_aq_add_vsi(hw, &vsi_ctx, NULL); | code = i40e_aq_add_vsi(hw, &vsi_ctx, NULL); | ||||
if (code != I40E_SUCCESS) | if (code != I40E_SUCCESS) | ||||
return (ixl_adminq_err_to_errno(hw->aq.asq_last_status)); | return (ixl_adminq_err_to_errno(hw->aq.asq_last_status)); | ||||
vf->vsi.seid = vsi_ctx.seid; | vf->vsi.seid = vsi_ctx.seid; | ||||
vf->vsi.vsi_num = vsi_ctx.vsi_number; | vf->vsi.vsi_num = vsi_ctx.vsi_number; | ||||
// vf->vsi.first_queue = vf->qtag.qidx[0]; | // TODO: How to deal with num tx queues / num rx queues split? | ||||
vf->vsi.num_queues = vf->qtag.num_active; | // I don't think just assigning this variable is going to work | ||||
vf->vsi.num_rx_queues = vf->qtag.num_active; | |||||
vf->vsi.num_tx_queues = vf->qtag.num_active; | |||||
code = i40e_aq_get_vsi_params(hw, &vsi_ctx, NULL); | code = i40e_aq_get_vsi_params(hw, &vsi_ctx, NULL); | ||||
if (code != I40E_SUCCESS) | if (code != I40E_SUCCESS) | ||||
return (ixl_adminq_err_to_errno(hw->aq.asq_last_status)); | return (ixl_adminq_err_to_errno(hw->aq.asq_last_status)); | ||||
code = i40e_aq_config_vsi_bw_limit(hw, vf->vsi.seid, 0, 0, NULL); | code = i40e_aq_config_vsi_bw_limit(hw, vf->vsi.seid, 0, 0, NULL); | ||||
if (code != I40E_SUCCESS) { | if (code != I40E_SUCCESS) { | ||||
device_printf(dev, "Failed to disable BW limit: %d\n", | device_printf(dev, "Failed to disable BW limit: %d\n", | ||||
Show All 14 Lines | ixl_vf_setup_vsi(struct ixl_pf *pf, struct ixl_vf *vf) | ||||
hw = &pf->hw; | hw = &pf->hw; | ||||
error = ixl_vf_alloc_vsi(pf, vf); | error = ixl_vf_alloc_vsi(pf, vf); | ||||
if (error != 0) | if (error != 0) | ||||
return (error); | return (error); | ||||
vf->vsi.hw_filters_add = 0; | vf->vsi.hw_filters_add = 0; | ||||
vf->vsi.hw_filters_del = 0; | vf->vsi.hw_filters_del = 0; | ||||
ixl_add_filter(&vf->vsi, ixl_bcast_addr, IXL_VLAN_ANY); | // ixl_add_filter(&vf->vsi, ixl_bcast_addr, IXL_VLAN_ANY); | ||||
ixl_reconfigure_filters(&vf->vsi); | ixl_reconfigure_filters(&vf->vsi); | ||||
return (0); | return (0); | ||||
} | } | ||||
static void | static void | ||||
ixl_vf_map_vsi_queue(struct i40e_hw *hw, struct ixl_vf *vf, int qnum, | ixl_vf_map_vsi_queue(struct i40e_hw *hw, struct ixl_vf *vf, int qnum, | ||||
uint32_t val) | uint32_t val) | ||||
Show All 32 Lines | i40e_write_rx_ctl(hw, I40E_VSILAN_QBASE(vf->vsi.vsi_num), | ||||
I40E_VSILAN_QBASE_VSIQTABLE_ENA_MASK); | I40E_VSILAN_QBASE_VSIQTABLE_ENA_MASK); | ||||
/* Enable LAN traffic on this VF */ | /* Enable LAN traffic on this VF */ | ||||
wr32(hw, I40E_VPLAN_MAPENA(vf->vf_num), | wr32(hw, I40E_VPLAN_MAPENA(vf->vf_num), | ||||
I40E_VPLAN_MAPENA_TXRX_ENA_MASK); | I40E_VPLAN_MAPENA_TXRX_ENA_MASK); | ||||
/* Program index of each VF queue into PF queue space | /* Program index of each VF queue into PF queue space | ||||
* (This is only needed if QTABLE is enabled) */ | * (This is only needed if QTABLE is enabled) */ | ||||
for (i = 0; i < vf->vsi.num_queues; i++) { | for (i = 0; i < vf->vsi.num_tx_queues; i++) { | ||||
qtable = ixl_pf_qidx_from_vsi_qidx(&vf->qtag, i) << | qtable = ixl_pf_qidx_from_vsi_qidx(&vf->qtag, i) << | ||||
I40E_VPLAN_QTABLE_QINDEX_SHIFT; | I40E_VPLAN_QTABLE_QINDEX_SHIFT; | ||||
wr32(hw, I40E_VPLAN_QTABLE(i, vf->vf_num), qtable); | wr32(hw, I40E_VPLAN_QTABLE(i, vf->vf_num), qtable); | ||||
} | } | ||||
for (; i < IXL_MAX_VSI_QUEUES; i++) | for (; i < IXL_MAX_VSI_QUEUES; i++) | ||||
wr32(hw, I40E_VPLAN_QTABLE(i, vf->vf_num), | wr32(hw, I40E_VPLAN_QTABLE(i, vf->vf_num), | ||||
I40E_VPLAN_QTABLE_QINDEX_MASK); | I40E_VPLAN_QTABLE_QINDEX_MASK); | ||||
/* Map queues allocated to VF to its VSI; | /* Map queues allocated to VF to its VSI; | ||||
* This mapping matches the VF-wide mapping since the VF | * This mapping matches the VF-wide mapping since the VF | ||||
* is only given a single VSI */ | * is only given a single VSI */ | ||||
for (i = 0; i < vf->vsi.num_queues; i++) | for (i = 0; i < vf->vsi.num_tx_queues; i++) | ||||
ixl_vf_map_vsi_queue(hw, vf, i, | ixl_vf_map_vsi_queue(hw, vf, i, | ||||
ixl_pf_qidx_from_vsi_qidx(&vf->qtag, i)); | ixl_pf_qidx_from_vsi_qidx(&vf->qtag, i)); | ||||
/* Set rest of VSI queues as unused. */ | /* Set rest of VSI queues as unused. */ | ||||
for (; i < IXL_MAX_VSI_QUEUES; i++) | for (; i < IXL_MAX_VSI_QUEUES; i++) | ||||
ixl_vf_map_vsi_queue(hw, vf, i, | ixl_vf_map_vsi_queue(hw, vf, i, | ||||
I40E_VSILAN_QTABLE_QINDEX_0_MASK); | I40E_VSILAN_QTABLE_QINDEX_0_MASK); | ||||
▲ Show 20 Lines • Show All 52 Lines • ▼ Show 20 Lines | ixl_vf_release_resources(struct ixl_pf *pf, struct ixl_vf *vf) | ||||
/* Index 0 has a special register. */ | /* Index 0 has a special register. */ | ||||
ixl_vf_unregister_intr(hw, I40E_VPINT_LNKLST0(vf->vf_num)); | ixl_vf_unregister_intr(hw, I40E_VPINT_LNKLST0(vf->vf_num)); | ||||
for (i = 1; i < hw->func_caps.num_msix_vectors_vf; i++) { | for (i = 1; i < hw->func_caps.num_msix_vectors_vf; i++) { | ||||
vpint_reg = IXL_VPINT_LNKLSTN_REG(hw, i, vf->vf_num); | vpint_reg = IXL_VPINT_LNKLSTN_REG(hw, i, vf->vf_num); | ||||
ixl_vf_unregister_intr(hw, vpint_reg); | ixl_vf_unregister_intr(hw, vpint_reg); | ||||
} | } | ||||
vf->vsi.num_queues = 0; | vf->vsi.num_tx_queues = 0; | ||||
vf->vsi.num_rx_queues = 0; | |||||
} | } | ||||
static int | static int | ||||
ixl_flush_pcie(struct ixl_pf *pf, struct ixl_vf *vf) | ixl_flush_pcie(struct ixl_pf *pf, struct ixl_vf *vf) | ||||
{ | { | ||||
struct i40e_hw *hw; | struct i40e_hw *hw; | ||||
int i; | int i; | ||||
uint16_t global_vf_num; | uint16_t global_vf_num; | ||||
▲ Show 20 Lines • Show All 181 Lines • ▼ Show 20 Lines | ixl_vf_get_resources_msg(struct ixl_pf *pf, struct ixl_vf *vf, void *msg, | ||||
else | else | ||||
/* Force VF RSS setup by PF in 1.1+ VFs */ | /* Force VF RSS setup by PF in 1.1+ VFs */ | ||||
reply.vf_offload_flags = *(u32 *)msg & ( | reply.vf_offload_flags = *(u32 *)msg & ( | ||||
I40E_VIRTCHNL_VF_OFFLOAD_L2 | | I40E_VIRTCHNL_VF_OFFLOAD_L2 | | ||||
I40E_VIRTCHNL_VF_OFFLOAD_RSS_PF | | I40E_VIRTCHNL_VF_OFFLOAD_RSS_PF | | ||||
I40E_VIRTCHNL_VF_OFFLOAD_VLAN); | I40E_VIRTCHNL_VF_OFFLOAD_VLAN); | ||||
reply.num_vsis = 1; | reply.num_vsis = 1; | ||||
reply.num_queue_pairs = vf->vsi.num_queues; | reply.num_queue_pairs = vf->vsi.num_tx_queues; | ||||
reply.max_vectors = pf->hw.func_caps.num_msix_vectors_vf; | reply.max_vectors = pf->hw.func_caps.num_msix_vectors_vf; | ||||
reply.rss_key_size = 52; | reply.rss_key_size = 52; | ||||
reply.rss_lut_size = 64; | reply.rss_lut_size = 64; | ||||
reply.vsi_res[0].vsi_id = vf->vsi.vsi_num; | reply.vsi_res[0].vsi_id = vf->vsi.vsi_num; | ||||
reply.vsi_res[0].vsi_type = I40E_VSI_SRIOV; | reply.vsi_res[0].vsi_type = I40E_VSI_SRIOV; | ||||
reply.vsi_res[0].num_queue_pairs = vf->vsi.num_queues; | reply.vsi_res[0].num_queue_pairs = vf->vsi.num_tx_queues; | ||||
memcpy(reply.vsi_res[0].default_mac_addr, vf->mac, ETHER_ADDR_LEN); | memcpy(reply.vsi_res[0].default_mac_addr, vf->mac, ETHER_ADDR_LEN); | ||||
ixl_send_vf_msg(pf, vf, I40E_VIRTCHNL_OP_GET_VF_RESOURCES, | ixl_send_vf_msg(pf, vf, I40E_VIRTCHNL_OP_GET_VF_RESOURCES, | ||||
I40E_SUCCESS, &reply, sizeof(reply)); | I40E_SUCCESS, &reply, sizeof(reply)); | ||||
} | } | ||||
static int | static int | ||||
ixl_vf_config_tx_queue(struct ixl_pf *pf, struct ixl_vf *vf, | ixl_vf_config_tx_queue(struct ixl_pf *pf, struct ixl_vf *vf, | ||||
▲ Show 20 Lines • Show All 118 Lines • ▼ Show 20 Lines | ixl_vf_config_vsi_msg(struct ixl_pf *pf, struct ixl_vf *vf, void *msg, | ||||
if (msg_size < sizeof(*info)) { | if (msg_size < sizeof(*info)) { | ||||
i40e_send_vf_nack(pf, vf, I40E_VIRTCHNL_OP_CONFIG_VSI_QUEUES, | i40e_send_vf_nack(pf, vf, I40E_VIRTCHNL_OP_CONFIG_VSI_QUEUES, | ||||
I40E_ERR_PARAM); | I40E_ERR_PARAM); | ||||
return; | return; | ||||
} | } | ||||
info = msg; | info = msg; | ||||
if (info->num_queue_pairs == 0 || info->num_queue_pairs > vf->vsi.num_queues) { | if (info->num_queue_pairs == 0 || info->num_queue_pairs > vf->vsi.num_tx_queues) { | ||||
device_printf(pf->dev, "VF %d: invalid # of qpairs (msg has %d, VSI has %d)\n", | device_printf(pf->dev, "VF %d: invalid # of qpairs (msg has %d, VSI has %d)\n", | ||||
vf->vf_num, info->num_queue_pairs, vf->vsi.num_queues); | vf->vf_num, info->num_queue_pairs, vf->vsi.num_tx_queues); | ||||
i40e_send_vf_nack(pf, vf, I40E_VIRTCHNL_OP_CONFIG_VSI_QUEUES, | i40e_send_vf_nack(pf, vf, I40E_VIRTCHNL_OP_CONFIG_VSI_QUEUES, | ||||
I40E_ERR_PARAM); | I40E_ERR_PARAM); | ||||
return; | return; | ||||
} | } | ||||
expected_msg_size = sizeof(*info) + info->num_queue_pairs * sizeof(*pair); | expected_msg_size = sizeof(*info) + info->num_queue_pairs * sizeof(*pair); | ||||
if (msg_size != expected_msg_size) { | if (msg_size != expected_msg_size) { | ||||
device_printf(pf->dev, "VF %d: size of recvd message (%d) does not match expected size (%d)\n", | device_printf(pf->dev, "VF %d: size of recvd message (%d) does not match expected size (%d)\n", | ||||
Show All 12 Lines | ixl_vf_config_vsi_msg(struct ixl_pf *pf, struct ixl_vf *vf, void *msg, | ||||
} | } | ||||
for (i = 0; i < info->num_queue_pairs; i++) { | for (i = 0; i < info->num_queue_pairs; i++) { | ||||
pair = &info->qpair[i]; | pair = &info->qpair[i]; | ||||
if (pair->txq.vsi_id != vf->vsi.vsi_num || | if (pair->txq.vsi_id != vf->vsi.vsi_num || | ||||
pair->rxq.vsi_id != vf->vsi.vsi_num || | pair->rxq.vsi_id != vf->vsi.vsi_num || | ||||
pair->txq.queue_id != pair->rxq.queue_id || | pair->txq.queue_id != pair->rxq.queue_id || | ||||
pair->txq.queue_id >= vf->vsi.num_queues) { | pair->txq.queue_id >= vf->vsi.num_tx_queues) { | ||||
i40e_send_vf_nack(pf, vf, | i40e_send_vf_nack(pf, vf, | ||||
I40E_VIRTCHNL_OP_CONFIG_VSI_QUEUES, I40E_ERR_PARAM); | I40E_VIRTCHNL_OP_CONFIG_VSI_QUEUES, I40E_ERR_PARAM); | ||||
return; | return; | ||||
} | } | ||||
if (ixl_vf_config_tx_queue(pf, vf, &pair->txq) != 0) { | if (ixl_vf_config_tx_queue(pf, vf, &pair->txq) != 0) { | ||||
i40e_send_vf_nack(pf, vf, | i40e_send_vf_nack(pf, vf, | ||||
▲ Show 20 Lines • Show All 132 Lines • ▼ Show 20 Lines | if ((vector->vector_id >= hw->func_caps.num_msix_vectors_vf) || | ||||
vector->vsi_id != vf->vsi.vsi_num) { | vector->vsi_id != vf->vsi.vsi_num) { | ||||
i40e_send_vf_nack(pf, vf, | i40e_send_vf_nack(pf, vf, | ||||
I40E_VIRTCHNL_OP_CONFIG_IRQ_MAP, I40E_ERR_PARAM); | I40E_VIRTCHNL_OP_CONFIG_IRQ_MAP, I40E_ERR_PARAM); | ||||
return; | return; | ||||
} | } | ||||
if (vector->rxq_map != 0) { | if (vector->rxq_map != 0) { | ||||
largest_rxq = fls(vector->rxq_map) - 1; | largest_rxq = fls(vector->rxq_map) - 1; | ||||
if (largest_rxq >= vf->vsi.num_queues) { | if (largest_rxq >= vf->vsi.num_rx_queues) { | ||||
i40e_send_vf_nack(pf, vf, | i40e_send_vf_nack(pf, vf, | ||||
I40E_VIRTCHNL_OP_CONFIG_IRQ_MAP, | I40E_VIRTCHNL_OP_CONFIG_IRQ_MAP, | ||||
I40E_ERR_PARAM); | I40E_ERR_PARAM); | ||||
return; | return; | ||||
} | } | ||||
} | } | ||||
if (vector->txq_map != 0) { | if (vector->txq_map != 0) { | ||||
largest_txq = fls(vector->txq_map) - 1; | largest_txq = fls(vector->txq_map) - 1; | ||||
if (largest_txq >= vf->vsi.num_queues) { | if (largest_txq >= vf->vsi.num_tx_queues) { | ||||
i40e_send_vf_nack(pf, vf, | i40e_send_vf_nack(pf, vf, | ||||
I40E_VIRTCHNL_OP_CONFIG_IRQ_MAP, | I40E_VIRTCHNL_OP_CONFIG_IRQ_MAP, | ||||
I40E_ERR_PARAM); | I40E_ERR_PARAM); | ||||
return; | return; | ||||
} | } | ||||
} | } | ||||
if (vector->rxitr_idx > IXL_MAX_ITR_IDX || | if (vector->rxitr_idx > IXL_MAX_ITR_IDX || | ||||
Show All 30 Lines | i40e_send_vf_nack(pf, vf, I40E_VIRTCHNL_OP_ENABLE_QUEUES, | ||||
I40E_ERR_PARAM); | I40E_ERR_PARAM); | ||||
return; | return; | ||||
} | } | ||||
/* Enable TX rings selected by the VF */ | /* Enable TX rings selected by the VF */ | ||||
for (int i = 0; i < 32; i++) { | for (int i = 0; i < 32; i++) { | ||||
if ((1 << i) & select->tx_queues) { | if ((1 << i) & select->tx_queues) { | ||||
/* Warn if queue is out of VF allocation range */ | /* Warn if queue is out of VF allocation range */ | ||||
if (i >= vf->vsi.num_queues) { | if (i >= vf->vsi.num_tx_queues) { | ||||
device_printf(pf->dev, "VF %d: TX ring %d is outside of VF VSI allocation!\n", | device_printf(pf->dev, "VF %d: TX ring %d is outside of VF VSI allocation!\n", | ||||
vf->vf_num, i); | vf->vf_num, i); | ||||
break; | break; | ||||
} | } | ||||
/* Skip this queue if it hasn't been configured */ | /* Skip this queue if it hasn't been configured */ | ||||
if (!ixl_pf_qmgr_is_queue_configured(&vf->qtag, i, true)) | if (!ixl_pf_qmgr_is_queue_configured(&vf->qtag, i, true)) | ||||
continue; | continue; | ||||
/* Warn if this queue is already marked as enabled */ | /* Warn if this queue is already marked as enabled */ | ||||
if (ixl_pf_qmgr_is_queue_enabled(&vf->qtag, i, true)) | if (ixl_pf_qmgr_is_queue_enabled(&vf->qtag, i, true)) | ||||
device_printf(pf->dev, "VF %d: TX ring %d is already enabled!\n", | device_printf(pf->dev, "VF %d: TX ring %d is already enabled!\n", | ||||
vf->vf_num, i); | vf->vf_num, i); | ||||
error = ixl_enable_tx_ring(pf, &vf->qtag, i); | error = ixl_enable_tx_ring(pf, &vf->qtag, i); | ||||
if (error) | if (error) | ||||
break; | break; | ||||
else | else | ||||
ixl_pf_qmgr_mark_queue_enabled(&vf->qtag, i, true); | ixl_pf_qmgr_mark_queue_enabled(&vf->qtag, i, true); | ||||
} | } | ||||
} | } | ||||
/* Enable RX rings selected by the VF */ | /* Enable RX rings selected by the VF */ | ||||
for (int i = 0; i < 32; i++) { | for (int i = 0; i < 32; i++) { | ||||
if ((1 << i) & select->rx_queues) { | if ((1 << i) & select->rx_queues) { | ||||
/* Warn if queue is out of VF allocation range */ | /* Warn if queue is out of VF allocation range */ | ||||
if (i >= vf->vsi.num_queues) { | if (i >= vf->vsi.num_rx_queues) { | ||||
device_printf(pf->dev, "VF %d: RX ring %d is outside of VF VSI allocation!\n", | device_printf(pf->dev, "VF %d: RX ring %d is outside of VF VSI allocation!\n", | ||||
vf->vf_num, i); | vf->vf_num, i); | ||||
break; | break; | ||||
} | } | ||||
/* Skip this queue if it hasn't been configured */ | /* Skip this queue if it hasn't been configured */ | ||||
if (!ixl_pf_qmgr_is_queue_configured(&vf->qtag, i, false)) | if (!ixl_pf_qmgr_is_queue_configured(&vf->qtag, i, false)) | ||||
continue; | continue; | ||||
/* Warn if this queue is already marked as enabled */ | /* Warn if this queue is already marked as enabled */ | ||||
Show All 37 Lines | i40e_send_vf_nack(pf, vf, I40E_VIRTCHNL_OP_DISABLE_QUEUES, | ||||
I40E_ERR_PARAM); | I40E_ERR_PARAM); | ||||
return; | return; | ||||
} | } | ||||
/* Disable TX rings selected by the VF */ | /* Disable TX rings selected by the VF */ | ||||
for (int i = 0; i < 32; i++) { | for (int i = 0; i < 32; i++) { | ||||
if ((1 << i) & select->tx_queues) { | if ((1 << i) & select->tx_queues) { | ||||
/* Warn if queue is out of VF allocation range */ | /* Warn if queue is out of VF allocation range */ | ||||
if (i >= vf->vsi.num_queues) { | if (i >= vf->vsi.num_tx_queues) { | ||||
device_printf(pf->dev, "VF %d: TX ring %d is outside of VF VSI allocation!\n", | device_printf(pf->dev, "VF %d: TX ring %d is outside of VF VSI allocation!\n", | ||||
vf->vf_num, i); | vf->vf_num, i); | ||||
break; | break; | ||||
} | } | ||||
/* Skip this queue if it hasn't been configured */ | /* Skip this queue if it hasn't been configured */ | ||||
if (!ixl_pf_qmgr_is_queue_configured(&vf->qtag, i, true)) | if (!ixl_pf_qmgr_is_queue_configured(&vf->qtag, i, true)) | ||||
continue; | continue; | ||||
/* Warn if this queue is already marked as disabled */ | /* Warn if this queue is already marked as disabled */ | ||||
Show All 9 Lines | if ((1 << i) & select->tx_queues) { | ||||
ixl_pf_qmgr_mark_queue_disabled(&vf->qtag, i, true); | ixl_pf_qmgr_mark_queue_disabled(&vf->qtag, i, true); | ||||
} | } | ||||
} | } | ||||
/* Enable RX rings selected by the VF */ | /* Enable RX rings selected by the VF */ | ||||
for (int i = 0; i < 32; i++) { | for (int i = 0; i < 32; i++) { | ||||
if ((1 << i) & select->rx_queues) { | if ((1 << i) & select->rx_queues) { | ||||
/* Warn if queue is out of VF allocation range */ | /* Warn if queue is out of VF allocation range */ | ||||
if (i >= vf->vsi.num_queues) { | if (i >= vf->vsi.num_rx_queues) { | ||||
device_printf(pf->dev, "VF %d: RX ring %d is outside of VF VSI allocation!\n", | device_printf(pf->dev, "VF %d: RX ring %d is outside of VF VSI allocation!\n", | ||||
vf->vf_num, i); | vf->vf_num, i); | ||||
break; | break; | ||||
} | } | ||||
/* Skip this queue if it hasn't been configured */ | /* Skip this queue if it hasn't been configured */ | ||||
if (!ixl_pf_qmgr_is_queue_configured(&vf->qtag, i, false)) | if (!ixl_pf_qmgr_is_queue_configured(&vf->qtag, i, false)) | ||||
continue; | continue; | ||||
/* Warn if this queue is already marked as disabled */ | /* Warn if this queue is already marked as disabled */ | ||||
Show All 25 Lines | ixl_zero_mac(const uint8_t *addr) | ||||
uint8_t zero[ETHER_ADDR_LEN] = {0, 0, 0, 0, 0, 0}; | uint8_t zero[ETHER_ADDR_LEN] = {0, 0, 0, 0, 0, 0}; | ||||
return (cmp_etheraddr(addr, zero)); | return (cmp_etheraddr(addr, zero)); | ||||
} | } | ||||
static bool | static bool | ||||
ixl_bcast_mac(const uint8_t *addr) | ixl_bcast_mac(const uint8_t *addr) | ||||
{ | { | ||||
static uint8_t ixl_bcast_addr[ETHER_ADDR_LEN] = | |||||
{0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; | |||||
return (cmp_etheraddr(addr, ixl_bcast_addr)); | return (cmp_etheraddr(addr, ixl_bcast_addr)); | ||||
} | } | ||||
static int | static int | ||||
ixl_vf_mac_valid(struct ixl_vf *vf, const uint8_t *addr) | ixl_vf_mac_valid(struct ixl_vf *vf, const uint8_t *addr) | ||||
{ | { | ||||
▲ Show 20 Lines • Show All 526 Lines • ▼ Show 20 Lines | ixl_handle_vflr(void *arg, int pending) | ||||
struct i40e_hw *hw; | struct i40e_hw *hw; | ||||
uint16_t global_vf_num; | uint16_t global_vf_num; | ||||
uint32_t vflrstat_index, vflrstat_mask, vflrstat, icr0; | uint32_t vflrstat_index, vflrstat_mask, vflrstat, icr0; | ||||
int i; | int i; | ||||
pf = arg; | pf = arg; | ||||
hw = &pf->hw; | hw = &pf->hw; | ||||
IXL_PF_LOCK(pf); | /* TODO: May need to lock this */ | ||||
for (i = 0; i < pf->num_vfs; i++) { | for (i = 0; i < pf->num_vfs; i++) { | ||||
global_vf_num = hw->func_caps.vf_base_id + i; | global_vf_num = hw->func_caps.vf_base_id + i; | ||||
vf = &pf->vfs[i]; | vf = &pf->vfs[i]; | ||||
if (!(vf->vf_flags & VF_FLAG_ENABLED)) | if (!(vf->vf_flags & VF_FLAG_ENABLED)) | ||||
continue; | continue; | ||||
vflrstat_index = IXL_GLGEN_VFLRSTAT_INDEX(global_vf_num); | vflrstat_index = IXL_GLGEN_VFLRSTAT_INDEX(global_vf_num); | ||||
vflrstat_mask = IXL_GLGEN_VFLRSTAT_MASK(global_vf_num); | vflrstat_mask = IXL_GLGEN_VFLRSTAT_MASK(global_vf_num); | ||||
vflrstat = rd32(hw, I40E_GLGEN_VFLRSTAT(vflrstat_index)); | vflrstat = rd32(hw, I40E_GLGEN_VFLRSTAT(vflrstat_index)); | ||||
if (vflrstat & vflrstat_mask) { | if (vflrstat & vflrstat_mask) { | ||||
wr32(hw, I40E_GLGEN_VFLRSTAT(vflrstat_index), | wr32(hw, I40E_GLGEN_VFLRSTAT(vflrstat_index), | ||||
vflrstat_mask); | vflrstat_mask); | ||||
ixl_reinit_vf(pf, vf); | ixl_reinit_vf(pf, vf); | ||||
} | } | ||||
} | } | ||||
atomic_clear_32(&pf->state, IXL_PF_STATE_VF_RESET_REQ); | |||||
icr0 = rd32(hw, I40E_PFINT_ICR0_ENA); | icr0 = rd32(hw, I40E_PFINT_ICR0_ENA); | ||||
icr0 |= I40E_PFINT_ICR0_ENA_VFLR_MASK; | icr0 |= I40E_PFINT_ICR0_ENA_VFLR_MASK; | ||||
wr32(hw, I40E_PFINT_ICR0_ENA, icr0); | wr32(hw, I40E_PFINT_ICR0_ENA, icr0); | ||||
ixl_flush(hw); | ixl_flush(hw); | ||||
IXL_PF_UNLOCK(pf); | // TODO: IXL_PF_UNLOCK() was here | ||||
} | } | ||||
static int | static int | ||||
ixl_adminq_err_to_errno(enum i40e_admin_queue_err err) | ixl_adminq_err_to_errno(enum i40e_admin_queue_err err) | ||||
{ | { | ||||
switch (err) { | switch (err) { | ||||
case I40E_AQ_RC_EPERM: | case I40E_AQ_RC_EPERM: | ||||
▲ Show 20 Lines • Show All 53 Lines • ▼ Show 20 Lines | ixl_iov_init(device_t dev, uint16_t num_vfs, const nvlist_t *params) | ||||
struct ixl_vsi *pf_vsi; | struct ixl_vsi *pf_vsi; | ||||
enum i40e_status_code ret; | enum i40e_status_code ret; | ||||
int i, error; | int i, error; | ||||
pf = device_get_softc(dev); | pf = device_get_softc(dev); | ||||
hw = &pf->hw; | hw = &pf->hw; | ||||
pf_vsi = &pf->vsi; | pf_vsi = &pf->vsi; | ||||
IXL_PF_LOCK(pf); | // TODO: IXL_PF_LOCK() was here | ||||
pf->vfs = malloc(sizeof(struct ixl_vf) * num_vfs, M_IXL, M_NOWAIT | | pf->vfs = malloc(sizeof(struct ixl_vf) * num_vfs, M_IXL, M_NOWAIT | | ||||
M_ZERO); | M_ZERO); | ||||
if (pf->vfs == NULL) { | if (pf->vfs == NULL) { | ||||
error = ENOMEM; | error = ENOMEM; | ||||
goto fail; | goto fail; | ||||
} | } | ||||
for (i = 0; i < num_vfs; i++) | for (i = 0; i < num_vfs; i++) | ||||
sysctl_ctx_init(&pf->vfs[i].ctx); | sysctl_ctx_init(&pf->vfs[i].ctx); | ||||
ret = i40e_aq_add_veb(hw, pf_vsi->uplink_seid, pf_vsi->seid, | ret = i40e_aq_add_veb(hw, pf_vsi->uplink_seid, pf_vsi->seid, | ||||
1, FALSE, &pf->veb_seid, FALSE, NULL); | 1, FALSE, &pf->veb_seid, FALSE, NULL); | ||||
if (ret != I40E_SUCCESS) { | if (ret != I40E_SUCCESS) { | ||||
error = ixl_adminq_err_to_errno(hw->aq.asq_last_status); | error = ixl_adminq_err_to_errno(hw->aq.asq_last_status); | ||||
device_printf(dev, "add_veb failed; code=%d error=%d", ret, | device_printf(dev, "add_veb failed; code=%d error=%d", ret, | ||||
error); | error); | ||||
goto fail; | goto fail; | ||||
} | } | ||||
pf->num_vfs = num_vfs; | pf->num_vfs = num_vfs; | ||||
IXL_PF_UNLOCK(pf); | // TODO: IXL_PF_UNLOCK() was here | ||||
return (0); | return (0); | ||||
fail: | fail: | ||||
free(pf->vfs, M_IXL); | free(pf->vfs, M_IXL); | ||||
pf->vfs = NULL; | pf->vfs = NULL; | ||||
IXL_PF_UNLOCK(pf); | // TODO: IXL_PF_UNLOCK() was here | ||||
return (error); | return (error); | ||||
} | } | ||||
void | void | ||||
ixl_iov_uninit(device_t dev) | ixl_iov_uninit(device_t dev) | ||||
{ | { | ||||
struct ixl_pf *pf; | struct ixl_pf *pf; | ||||
struct i40e_hw *hw; | struct i40e_hw *hw; | ||||
struct ixl_vsi *vsi; | struct ixl_vsi *vsi; | ||||
struct ifnet *ifp; | struct ifnet *ifp; | ||||
struct ixl_vf *vfs; | struct ixl_vf *vfs; | ||||
int i, num_vfs; | int i, num_vfs; | ||||
pf = device_get_softc(dev); | pf = device_get_softc(dev); | ||||
hw = &pf->hw; | hw = &pf->hw; | ||||
vsi = &pf->vsi; | vsi = &pf->vsi; | ||||
ifp = vsi->ifp; | ifp = vsi->ifp; | ||||
IXL_PF_LOCK(pf); | // TODO: IXL_PF_LOCK() was here | ||||
for (i = 0; i < pf->num_vfs; i++) { | for (i = 0; i < pf->num_vfs; i++) { | ||||
if (pf->vfs[i].vsi.seid != 0) | if (pf->vfs[i].vsi.seid != 0) | ||||
i40e_aq_delete_element(hw, pf->vfs[i].vsi.seid, NULL); | i40e_aq_delete_element(hw, pf->vfs[i].vsi.seid, NULL); | ||||
ixl_pf_qmgr_release(&pf->qmgr, &pf->vfs[i].qtag); | ixl_pf_qmgr_release(&pf->qmgr, &pf->vfs[i].qtag); | ||||
DDPRINTF(dev, "VF %d: %d released\n", | DDPRINTF(dev, "VF %d: %d released\n", | ||||
i, pf->vfs[i].qtag.num_allocated); | i, pf->vfs[i].qtag.num_allocated); | ||||
DDPRINTF(dev, "Unallocated total: %d\n", ixl_pf_qmgr_get_num_free(&pf->qmgr)); | DDPRINTF(dev, "Unallocated total: %d\n", ixl_pf_qmgr_get_num_free(&pf->qmgr)); | ||||
} | } | ||||
if (pf->veb_seid != 0) { | if (pf->veb_seid != 0) { | ||||
i40e_aq_delete_element(hw, pf->veb_seid, NULL); | i40e_aq_delete_element(hw, pf->veb_seid, NULL); | ||||
pf->veb_seid = 0; | pf->veb_seid = 0; | ||||
} | } | ||||
vfs = pf->vfs; | vfs = pf->vfs; | ||||
num_vfs = pf->num_vfs; | num_vfs = pf->num_vfs; | ||||
pf->vfs = NULL; | pf->vfs = NULL; | ||||
pf->num_vfs = 0; | pf->num_vfs = 0; | ||||
IXL_PF_UNLOCK(pf); | // TODO: IXL_PF_UNLOCK() was here | ||||
/* Do this after the unlock as sysctl_ctx_free might sleep. */ | /* Do this after the unlock as sysctl_ctx_free might sleep. */ | ||||
for (i = 0; i < num_vfs; i++) | for (i = 0; i < num_vfs; i++) | ||||
sysctl_ctx_free(&vfs[i].ctx); | sysctl_ctx_free(&vfs[i].ctx); | ||||
free(vfs, M_IXL); | free(vfs, M_IXL); | ||||
} | } | ||||
static int | static int | ||||
Show All 36 Lines | ixl_add_vf(device_t dev, uint16_t vfnum, const nvlist_t *params) | ||||
const void *mac; | const void *mac; | ||||
size_t size; | size_t size; | ||||
int error; | int error; | ||||
int vf_num_queues; | int vf_num_queues; | ||||
pf = device_get_softc(dev); | pf = device_get_softc(dev); | ||||
vf = &pf->vfs[vfnum]; | vf = &pf->vfs[vfnum]; | ||||
IXL_PF_LOCK(pf); | // TODO: IXL_PF_LOCK() was here | ||||
vf->vf_num = vfnum; | vf->vf_num = vfnum; | ||||
vf->vsi.back = pf; | vf->vsi.back = pf; | ||||
vf->vf_flags = VF_FLAG_ENABLED; | vf->vf_flags = VF_FLAG_ENABLED; | ||||
SLIST_INIT(&vf->vsi.ftl); | SLIST_INIT(&vf->vsi.ftl); | ||||
/* Reserve queue allocation from PF */ | /* Reserve queue allocation from PF */ | ||||
vf_num_queues = nvlist_get_number(params, "num-queues"); | vf_num_queues = nvlist_get_number(params, "num-queues"); | ||||
Show All 23 Lines | ixl_add_vf(device_t dev, uint16_t vfnum, const nvlist_t *params) | ||||
if (nvlist_get_bool(params, "allow-promisc")) | if (nvlist_get_bool(params, "allow-promisc")) | ||||
vf->vf_flags |= VF_FLAG_PROMISC_CAP; | vf->vf_flags |= VF_FLAG_PROMISC_CAP; | ||||
vf->vf_flags |= VF_FLAG_VLAN_CAP; | vf->vf_flags |= VF_FLAG_VLAN_CAP; | ||||
ixl_reset_vf(pf, vf); | ixl_reset_vf(pf, vf); | ||||
out: | out: | ||||
IXL_PF_UNLOCK(pf); | // TODO: IXL_PF_UNLOCK() was here | ||||
if (error == 0) { | if (error == 0) { | ||||
snprintf(sysctl_name, sizeof(sysctl_name), "vf%d", vfnum); | snprintf(sysctl_name, sizeof(sysctl_name), "vf%d", vfnum); | ||||
ixl_add_vsi_sysctls(pf, &vf->vsi, &vf->ctx, sysctl_name); | ixl_add_vsi_sysctls(pf, &vf->vsi, &vf->ctx, sysctl_name); | ||||
} | } | ||||
return (error); | return (error); | ||||
} | } | ||||