Changeset View
Changeset View
Standalone View
Standalone View
sys/dev/ixl/ixl_pf_iov.c
Show All 33 Lines | |||||
#include "ixl_pf_iov.h" | #include "ixl_pf_iov.h" | ||||
/* Private functions */ | /* Private functions */ | ||||
static void ixl_vf_map_vsi_queue(struct i40e_hw *hw, struct ixl_vf *vf, int qnum, uint32_t val); | static void ixl_vf_map_vsi_queue(struct i40e_hw *hw, struct ixl_vf *vf, int qnum, uint32_t val); | ||||
static void ixl_vf_disable_queue_intr(struct i40e_hw *hw, uint32_t vfint_reg); | static void ixl_vf_disable_queue_intr(struct i40e_hw *hw, uint32_t vfint_reg); | ||||
static void ixl_vf_unregister_intr(struct i40e_hw *hw, uint32_t vpint_reg); | static void ixl_vf_unregister_intr(struct i40e_hw *hw, uint32_t vpint_reg); | ||||
static bool ixl_zero_mac(const uint8_t *addr); | |||||
static bool ixl_bcast_mac(const uint8_t *addr); | |||||
static int ixl_vc_opcode_level(uint16_t opcode); | static int ixl_vc_opcode_level(uint16_t opcode); | ||||
static int ixl_vf_mac_valid(struct ixl_vf *vf, const uint8_t *addr); | static int ixl_vf_mac_valid(struct ixl_vf *vf, const uint8_t *addr); | ||||
static int ixl_vf_alloc_vsi(struct ixl_pf *pf, struct ixl_vf *vf); | static int ixl_vf_alloc_vsi(struct ixl_pf *pf, struct ixl_vf *vf); | ||||
static int ixl_vf_setup_vsi(struct ixl_pf *pf, struct ixl_vf *vf); | static int ixl_vf_setup_vsi(struct ixl_pf *pf, struct ixl_vf *vf); | ||||
static void ixl_vf_map_queues(struct ixl_pf *pf, struct ixl_vf *vf); | static void ixl_vf_map_queues(struct ixl_pf *pf, struct ixl_vf *vf); | ||||
static void ixl_vf_vsi_release(struct ixl_pf *pf, struct ixl_vsi *vsi); | static void ixl_vf_vsi_release(struct ixl_pf *pf, struct ixl_vsi *vsi); | ||||
▲ Show 20 Lines • Show All 59 Lines • ▼ Show 20 Lines | ixl_initialize_sriov(struct ixl_pf *pf) | ||||
iov_error = pci_iov_attach(dev, pf_schema, vf_schema); | iov_error = pci_iov_attach(dev, pf_schema, vf_schema); | ||||
if (iov_error != 0) { | if (iov_error != 0) { | ||||
device_printf(dev, | device_printf(dev, | ||||
"Failed to initialize SR-IOV (error=%d)\n", | "Failed to initialize SR-IOV (error=%d)\n", | ||||
iov_error); | iov_error); | ||||
} else | } else | ||||
device_printf(dev, "SR-IOV ready\n"); | device_printf(dev, "SR-IOV ready\n"); | ||||
pf->vc_debug_lvl = 1; | |||||
} | } | ||||
/* | /* | ||||
* Allocate the VSI for a VF. | * Allocate the VSI for a VF. | ||||
*/ | */ | ||||
static int | static int | ||||
ixl_vf_alloc_vsi(struct ixl_pf *pf, struct ixl_vf *vf) | ixl_vf_alloc_vsi(struct ixl_pf *pf, struct ixl_vf *vf) | ||||
{ | { | ||||
device_t dev; | device_t dev; | ||||
struct i40e_hw *hw; | struct i40e_hw *hw; | ||||
▲ Show 20 Lines • Show All 67 Lines • ▼ Show 20 Lines | |||||
static int | static int | ||||
ixl_vf_setup_vsi(struct ixl_pf *pf, struct ixl_vf *vf) | ixl_vf_setup_vsi(struct ixl_pf *pf, struct ixl_vf *vf) | ||||
{ | { | ||||
struct i40e_hw *hw; | struct i40e_hw *hw; | ||||
int error; | int error; | ||||
hw = &pf->hw; | hw = &pf->hw; | ||||
vf->vsi.flags |= IXL_FLAGS_IS_VF; | |||||
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.dev = pf->dev; | |||||
ixl_init_filters(&vf->vsi); | |||||
/* Let VF receive broadcast Ethernet frames */ | /* Let VF receive broadcast Ethernet frames */ | ||||
error = i40e_aq_set_vsi_broadcast(hw, vf->vsi.seid, TRUE, NULL); | error = i40e_aq_set_vsi_broadcast(hw, vf->vsi.seid, TRUE, NULL); | ||||
if (error) | if (error) | ||||
device_printf(pf->dev, "Error configuring VF VSI for broadcast promiscuous\n"); | device_printf(pf->dev, "Error configuring VF VSI for broadcast promiscuous\n"); | ||||
/* Re-add VF's MAC/VLAN filters to its VSI */ | /* Re-add VF's MAC/VLAN filters to its VSI */ | ||||
ixl_reconfigure_filters(&vf->vsi); | ixl_reconfigure_filters(&vf->vsi); | ||||
/* Reset stats? */ | |||||
vf->vsi.hw_filters_add = 0; | |||||
vf->vsi.hw_filters_del = 0; | |||||
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 20 Lines • Show All 255 Lines • ▼ Show 20 Lines | I40E_VC_DEBUG(pf, 1, | ||||
status, vf->vf_num, file, line); | status, vf->vf_num, file, line); | ||||
ixl_send_vf_msg(pf, vf, op, status, NULL, 0); | ixl_send_vf_msg(pf, vf, op, status, NULL, 0); | ||||
} | } | ||||
static void | static void | ||||
ixl_vf_version_msg(struct ixl_pf *pf, struct ixl_vf *vf, void *msg, | ixl_vf_version_msg(struct ixl_pf *pf, struct ixl_vf *vf, void *msg, | ||||
uint16_t msg_size) | uint16_t msg_size) | ||||
{ | { | ||||
struct virtchnl_version_info reply; | struct virtchnl_version_info *recv_vf_version; | ||||
device_t dev = pf->dev; | |||||
if (msg_size != sizeof(struct virtchnl_version_info)) { | recv_vf_version = (struct virtchnl_version_info *)msg; | ||||
i40e_send_vf_nack(pf, vf, VIRTCHNL_OP_VERSION, | |||||
I40E_ERR_PARAM); | |||||
return; | |||||
} | |||||
vf->version = ((struct virtchnl_version_info *)msg)->minor; | /* VFs running the 1.0 API expect to get 1.0 back */ | ||||
if (VF_IS_V10(recv_vf_version)) { | |||||
vf->version.major = 1; | |||||
vf->version.minor = VIRTCHNL_VERSION_MINOR_NO_VF_CAPS; | |||||
} else { | |||||
vf->version.major = VIRTCHNL_VERSION_MAJOR; | |||||
vf->version.minor = VIRTCHNL_VERSION_MINOR; | |||||
reply.major = VIRTCHNL_VERSION_MAJOR; | if ((recv_vf_version->major != VIRTCHNL_VERSION_MAJOR) || | ||||
reply.minor = VIRTCHNL_VERSION_MINOR; | (recv_vf_version->minor != VIRTCHNL_VERSION_MINOR)) | ||||
ixl_send_vf_msg(pf, vf, VIRTCHNL_OP_VERSION, I40E_SUCCESS, &reply, | device_printf(dev, | ||||
sizeof(reply)); | "%s: VF-%d requested version (%d.%d) differs from PF version (%d.%d)\n", | ||||
__func__, vf->vf_num, | |||||
recv_vf_version->major, recv_vf_version->minor, | |||||
VIRTCHNL_VERSION_MAJOR, VIRTCHNL_VERSION_MINOR); | |||||
} | } | ||||
ixl_send_vf_msg(pf, vf, VIRTCHNL_OP_VERSION, I40E_SUCCESS, | |||||
&vf->version, sizeof(vf->version)); | |||||
} | |||||
static void | static void | ||||
ixl_vf_reset_msg(struct ixl_pf *pf, struct ixl_vf *vf, void *msg, | ixl_vf_reset_msg(struct ixl_pf *pf, struct ixl_vf *vf, void *msg, | ||||
uint16_t msg_size) | uint16_t msg_size) | ||||
{ | { | ||||
if (msg_size != 0) { | |||||
i40e_send_vf_nack(pf, vf, VIRTCHNL_OP_RESET_VF, | |||||
I40E_ERR_PARAM); | |||||
return; | |||||
} | |||||
ixl_reset_vf(pf, vf); | ixl_reset_vf(pf, vf); | ||||
/* No response to a reset message. */ | /* No response to a reset message. */ | ||||
} | } | ||||
static void | static void | ||||
ixl_vf_get_resources_msg(struct ixl_pf *pf, struct ixl_vf *vf, void *msg, | ixl_vf_get_resources_msg(struct ixl_pf *pf, struct ixl_vf *vf, void *msg, | ||||
uint16_t msg_size) | uint16_t msg_size) | ||||
{ | { | ||||
struct virtchnl_vf_resource reply; | struct virtchnl_vf_resource reply; | ||||
if ((vf->version == 0 && msg_size != 0) || | |||||
(vf->version == 1 && msg_size != 4)) { | |||||
device_printf(pf->dev, "Invalid GET_VF_RESOURCES message size," | |||||
" for VF version %d.%d\n", VIRTCHNL_VERSION_MAJOR, | |||||
vf->version); | |||||
i40e_send_vf_nack(pf, vf, VIRTCHNL_OP_GET_VF_RESOURCES, | |||||
I40E_ERR_PARAM); | |||||
return; | |||||
} | |||||
bzero(&reply, sizeof(reply)); | bzero(&reply, sizeof(reply)); | ||||
if (vf->version == VIRTCHNL_VERSION_MINOR_NO_VF_CAPS) | if (vf->version.minor == VIRTCHNL_VERSION_MINOR_NO_VF_CAPS) | ||||
reply.vf_cap_flags = VIRTCHNL_VF_OFFLOAD_L2 | | reply.vf_cap_flags = VIRTCHNL_VF_OFFLOAD_L2 | | ||||
VIRTCHNL_VF_OFFLOAD_RSS_REG | | VIRTCHNL_VF_OFFLOAD_RSS_REG | | ||||
VIRTCHNL_VF_OFFLOAD_VLAN; | VIRTCHNL_VF_OFFLOAD_VLAN; | ||||
else | else | ||||
/* Force VF RSS setup by PF in 1.1+ VFs */ | /* Force VF RSS setup by PF in 1.1+ VFs */ | ||||
reply.vf_cap_flags = *(u32 *)msg & ( | reply.vf_cap_flags = *(u32 *)msg & ( | ||||
VIRTCHNL_VF_OFFLOAD_L2 | | VIRTCHNL_VF_OFFLOAD_L2 | | ||||
VIRTCHNL_VF_OFFLOAD_RSS_PF | | VIRTCHNL_VF_OFFLOAD_RSS_PF | | ||||
▲ Show 20 Lines • Show All 126 Lines • ▼ Show 20 Lines | |||||
} | } | ||||
static void | static void | ||||
ixl_vf_config_vsi_msg(struct ixl_pf *pf, struct ixl_vf *vf, void *msg, | ixl_vf_config_vsi_msg(struct ixl_pf *pf, struct ixl_vf *vf, void *msg, | ||||
uint16_t msg_size) | uint16_t msg_size) | ||||
{ | { | ||||
struct virtchnl_vsi_queue_config_info *info; | struct virtchnl_vsi_queue_config_info *info; | ||||
struct virtchnl_queue_pair_info *pair; | struct virtchnl_queue_pair_info *pair; | ||||
uint16_t expected_msg_size; | |||||
int i; | int i; | ||||
if (msg_size < sizeof(*info)) { | |||||
i40e_send_vf_nack(pf, vf, VIRTCHNL_OP_CONFIG_VSI_QUEUES, | |||||
I40E_ERR_PARAM); | |||||
return; | |||||
} | |||||
info = msg; | info = msg; | ||||
if (info->num_queue_pairs == 0 || info->num_queue_pairs > vf->vsi.num_tx_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_tx_queues); | vf->vf_num, info->num_queue_pairs, vf->vsi.num_tx_queues); | ||||
i40e_send_vf_nack(pf, vf, VIRTCHNL_OP_CONFIG_VSI_QUEUES, | i40e_send_vf_nack(pf, vf, VIRTCHNL_OP_CONFIG_VSI_QUEUES, | ||||
I40E_ERR_PARAM); | I40E_ERR_PARAM); | ||||
return; | return; | ||||
} | } | ||||
expected_msg_size = sizeof(*info) + info->num_queue_pairs * sizeof(*pair); | |||||
if (msg_size != expected_msg_size) { | |||||
device_printf(pf->dev, "VF %d: size of recvd message (%d) does not match expected size (%d)\n", | |||||
vf->vf_num, msg_size, expected_msg_size); | |||||
i40e_send_vf_nack(pf, vf, VIRTCHNL_OP_CONFIG_VSI_QUEUES, | |||||
I40E_ERR_PARAM); | |||||
return; | |||||
} | |||||
if (info->vsi_id != vf->vsi.vsi_num) { | if (info->vsi_id != vf->vsi.vsi_num) { | ||||
device_printf(pf->dev, "VF %d: VSI id in recvd message (%d) does not match expected id (%d)\n", | device_printf(pf->dev, "VF %d: VSI id in recvd message (%d) does not match expected id (%d)\n", | ||||
vf->vf_num, info->vsi_id, vf->vsi.vsi_num); | vf->vf_num, info->vsi_id, vf->vsi.vsi_num); | ||||
i40e_send_vf_nack(pf, vf, VIRTCHNL_OP_CONFIG_VSI_QUEUES, | i40e_send_vf_nack(pf, vf, VIRTCHNL_OP_CONFIG_VSI_QUEUES, | ||||
I40E_ERR_PARAM); | I40E_ERR_PARAM); | ||||
return; | return; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 115 Lines • ▼ Show 20 Lines | ixl_vf_config_irq_msg(struct ixl_pf *pf, struct ixl_vf *vf, void *msg, | ||||
uint16_t msg_size) | uint16_t msg_size) | ||||
{ | { | ||||
struct virtchnl_irq_map_info *map; | struct virtchnl_irq_map_info *map; | ||||
struct virtchnl_vector_map *vector; | struct virtchnl_vector_map *vector; | ||||
struct i40e_hw *hw; | struct i40e_hw *hw; | ||||
int i, largest_txq, largest_rxq; | int i, largest_txq, largest_rxq; | ||||
hw = &pf->hw; | hw = &pf->hw; | ||||
if (msg_size < sizeof(*map)) { | |||||
i40e_send_vf_nack(pf, vf, VIRTCHNL_OP_CONFIG_IRQ_MAP, | |||||
I40E_ERR_PARAM); | |||||
return; | |||||
} | |||||
map = msg; | map = msg; | ||||
if (map->num_vectors == 0) { | |||||
i40e_send_vf_nack(pf, vf, VIRTCHNL_OP_CONFIG_IRQ_MAP, | |||||
I40E_ERR_PARAM); | |||||
return; | |||||
} | |||||
if (msg_size != sizeof(*map) + map->num_vectors * sizeof(*vector)) { | |||||
i40e_send_vf_nack(pf, vf, VIRTCHNL_OP_CONFIG_IRQ_MAP, | |||||
I40E_ERR_PARAM); | |||||
return; | |||||
} | |||||
for (i = 0; i < map->num_vectors; i++) { | for (i = 0; i < map->num_vectors; i++) { | ||||
vector = &map->vecmap[i]; | vector = &map->vecmap[i]; | ||||
if ((vector->vector_id >= hw->func_caps.num_msix_vectors_vf) || | 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, | ||||
VIRTCHNL_OP_CONFIG_IRQ_MAP, I40E_ERR_PARAM); | VIRTCHNL_OP_CONFIG_IRQ_MAP, I40E_ERR_PARAM); | ||||
return; | return; | ||||
Show All 35 Lines | |||||
static void | static void | ||||
ixl_vf_enable_queues_msg(struct ixl_pf *pf, struct ixl_vf *vf, void *msg, | ixl_vf_enable_queues_msg(struct ixl_pf *pf, struct ixl_vf *vf, void *msg, | ||||
uint16_t msg_size) | uint16_t msg_size) | ||||
{ | { | ||||
struct virtchnl_queue_select *select; | struct virtchnl_queue_select *select; | ||||
int error = 0; | int error = 0; | ||||
if (msg_size != sizeof(*select)) { | |||||
i40e_send_vf_nack(pf, vf, VIRTCHNL_OP_ENABLE_QUEUES, | |||||
I40E_ERR_PARAM); | |||||
return; | |||||
} | |||||
select = msg; | select = msg; | ||||
if (select->vsi_id != vf->vsi.vsi_num || | if (select->vsi_id != vf->vsi.vsi_num || | ||||
select->rx_queues == 0 || select->tx_queues == 0) { | select->rx_queues == 0 || select->tx_queues == 0) { | ||||
i40e_send_vf_nack(pf, vf, VIRTCHNL_OP_ENABLE_QUEUES, | i40e_send_vf_nack(pf, vf, 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 */ | ||||
▲ Show 20 Lines • Show All 56 Lines • ▼ Show 20 Lines | |||||
static void | static void | ||||
ixl_vf_disable_queues_msg(struct ixl_pf *pf, struct ixl_vf *vf, | ixl_vf_disable_queues_msg(struct ixl_pf *pf, struct ixl_vf *vf, | ||||
void *msg, uint16_t msg_size) | void *msg, uint16_t msg_size) | ||||
{ | { | ||||
struct virtchnl_queue_select *select; | struct virtchnl_queue_select *select; | ||||
int error = 0; | int error = 0; | ||||
if (msg_size != sizeof(*select)) { | |||||
i40e_send_vf_nack(pf, vf, VIRTCHNL_OP_DISABLE_QUEUES, | |||||
I40E_ERR_PARAM); | |||||
return; | |||||
} | |||||
select = msg; | select = msg; | ||||
if (select->vsi_id != vf->vsi.vsi_num || | if (select->vsi_id != vf->vsi.vsi_num || | ||||
select->rx_queues == 0 || select->tx_queues == 0) { | select->rx_queues == 0 || select->tx_queues == 0) { | ||||
i40e_send_vf_nack(pf, vf, VIRTCHNL_OP_DISABLE_QUEUES, | i40e_send_vf_nack(pf, vf, 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 */ | ||||
▲ Show 20 Lines • Show All 52 Lines • ▼ Show 20 Lines | if (error) { | ||||
i40e_send_vf_nack(pf, vf, VIRTCHNL_OP_DISABLE_QUEUES, | i40e_send_vf_nack(pf, vf, VIRTCHNL_OP_DISABLE_QUEUES, | ||||
I40E_ERR_TIMEOUT); | I40E_ERR_TIMEOUT); | ||||
return; | return; | ||||
} | } | ||||
ixl_send_vf_ack(pf, vf, VIRTCHNL_OP_DISABLE_QUEUES); | ixl_send_vf_ack(pf, vf, VIRTCHNL_OP_DISABLE_QUEUES); | ||||
} | } | ||||
static bool | |||||
ixl_zero_mac(const uint8_t *addr) | |||||
{ | |||||
uint8_t zero[ETHER_ADDR_LEN] = {0, 0, 0, 0, 0, 0}; | |||||
return (cmp_etheraddr(addr, zero)); | |||||
} | |||||
static bool | |||||
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)); | |||||
} | |||||
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) | ||||
{ | { | ||||
if (ixl_zero_mac(addr) || ixl_bcast_mac(addr)) | if (ETHER_IS_ZERO(addr) || ETHER_IS_BROADCAST(addr)) | ||||
return (EINVAL); | return (EINVAL); | ||||
/* | /* | ||||
* If the VF is not allowed to change its MAC address, don't let it | * If the VF is not allowed to change its MAC address, don't let it | ||||
* set a MAC filter for an address that is not a multicast address and | * set a MAC filter for an address that is not a multicast address and | ||||
* is not its assigned MAC. | * is not its assigned MAC. | ||||
*/ | */ | ||||
if (!(vf->vf_flags & VF_FLAG_SET_MAC_CAP) && | if (!(vf->vf_flags & VF_FLAG_SET_MAC_CAP) && | ||||
!(ETHER_IS_MULTICAST(addr) || cmp_etheraddr(addr, vf->mac))) | !(ETHER_IS_MULTICAST(addr) || cmp_etheraddr(addr, vf->mac))) | ||||
return (EPERM); | return (EPERM); | ||||
return (0); | return (0); | ||||
} | } | ||||
static void | static void | ||||
ixl_vf_add_mac_msg(struct ixl_pf *pf, struct ixl_vf *vf, void *msg, | ixl_vf_add_mac_msg(struct ixl_pf *pf, struct ixl_vf *vf, void *msg, | ||||
uint16_t msg_size) | uint16_t msg_size) | ||||
{ | { | ||||
struct virtchnl_ether_addr_list *addr_list; | struct virtchnl_ether_addr_list *addr_list; | ||||
struct virtchnl_ether_addr *addr; | struct virtchnl_ether_addr *addr; | ||||
struct ixl_vsi *vsi; | struct ixl_vsi *vsi; | ||||
int i; | int i; | ||||
size_t expected_size; | |||||
vsi = &vf->vsi; | vsi = &vf->vsi; | ||||
if (msg_size < sizeof(*addr_list)) { | |||||
i40e_send_vf_nack(pf, vf, VIRTCHNL_OP_ADD_ETH_ADDR, | |||||
I40E_ERR_PARAM); | |||||
return; | |||||
} | |||||
addr_list = msg; | addr_list = msg; | ||||
expected_size = sizeof(*addr_list) + | |||||
addr_list->num_elements * sizeof(*addr); | |||||
if (addr_list->num_elements == 0 || | if (addr_list->vsi_id != vsi->vsi_num) { | ||||
addr_list->vsi_id != vsi->vsi_num || | |||||
msg_size != expected_size) { | |||||
i40e_send_vf_nack(pf, vf, VIRTCHNL_OP_ADD_ETH_ADDR, | i40e_send_vf_nack(pf, vf, VIRTCHNL_OP_ADD_ETH_ADDR, | ||||
I40E_ERR_PARAM); | I40E_ERR_PARAM); | ||||
return; | return; | ||||
} | } | ||||
for (i = 0; i < addr_list->num_elements; i++) { | for (i = 0; i < addr_list->num_elements; i++) { | ||||
if (ixl_vf_mac_valid(vf, addr_list->list[i].addr) != 0) { | if (ixl_vf_mac_valid(vf, addr_list->list[i].addr) != 0) { | ||||
i40e_send_vf_nack(pf, vf, | i40e_send_vf_nack(pf, vf, | ||||
Show All 11 Lines | |||||
} | } | ||||
static void | static void | ||||
ixl_vf_del_mac_msg(struct ixl_pf *pf, struct ixl_vf *vf, void *msg, | ixl_vf_del_mac_msg(struct ixl_pf *pf, struct ixl_vf *vf, void *msg, | ||||
uint16_t msg_size) | uint16_t msg_size) | ||||
{ | { | ||||
struct virtchnl_ether_addr_list *addr_list; | struct virtchnl_ether_addr_list *addr_list; | ||||
struct virtchnl_ether_addr *addr; | struct virtchnl_ether_addr *addr; | ||||
size_t expected_size; | struct ixl_vsi *vsi; | ||||
int i; | int i; | ||||
if (msg_size < sizeof(*addr_list)) { | vsi = &vf->vsi; | ||||
i40e_send_vf_nack(pf, vf, VIRTCHNL_OP_ADD_ETH_ADDR, | |||||
I40E_ERR_PARAM); | |||||
return; | |||||
} | |||||
addr_list = msg; | addr_list = msg; | ||||
expected_size = sizeof(*addr_list) + | |||||
addr_list->num_elements * sizeof(*addr); | |||||
if (addr_list->num_elements == 0 || | if (addr_list->vsi_id != vsi->vsi_num) { | ||||
addr_list->vsi_id != vf->vsi.vsi_num || | i40e_send_vf_nack(pf, vf, VIRTCHNL_OP_DEL_ETH_ADDR, | ||||
msg_size != expected_size) { | |||||
i40e_send_vf_nack(pf, vf, VIRTCHNL_OP_ADD_ETH_ADDR, | |||||
I40E_ERR_PARAM); | I40E_ERR_PARAM); | ||||
return; | return; | ||||
} | } | ||||
for (i = 0; i < addr_list->num_elements; i++) { | for (i = 0; i < addr_list->num_elements; i++) { | ||||
addr = &addr_list->list[i]; | addr = &addr_list->list[i]; | ||||
if (ixl_zero_mac(addr->addr) || ixl_bcast_mac(addr->addr)) { | if (ETHER_IS_ZERO(addr->addr) || ETHER_IS_BROADCAST(addr->addr)) { | ||||
i40e_send_vf_nack(pf, vf, | i40e_send_vf_nack(pf, vf, | ||||
VIRTCHNL_OP_ADD_ETH_ADDR, I40E_ERR_PARAM); | VIRTCHNL_OP_DEL_ETH_ADDR, I40E_ERR_PARAM); | ||||
return; | return; | ||||
} | } | ||||
} | } | ||||
for (i = 0; i < addr_list->num_elements; i++) { | for (i = 0; i < addr_list->num_elements; i++) { | ||||
addr = &addr_list->list[i]; | addr = &addr_list->list[i]; | ||||
ixl_del_filter(&vf->vsi, addr->addr, IXL_VLAN_ANY); | ixl_del_filter(&vf->vsi, addr->addr, IXL_VLAN_ANY); | ||||
} | } | ||||
Show All 16 Lines | |||||
} | } | ||||
static void | static void | ||||
ixl_vf_add_vlan_msg(struct ixl_pf *pf, struct ixl_vf *vf, void *msg, | ixl_vf_add_vlan_msg(struct ixl_pf *pf, struct ixl_vf *vf, void *msg, | ||||
uint16_t msg_size) | uint16_t msg_size) | ||||
{ | { | ||||
struct virtchnl_vlan_filter_list *filter_list; | struct virtchnl_vlan_filter_list *filter_list; | ||||
enum i40e_status_code code; | enum i40e_status_code code; | ||||
size_t expected_size; | |||||
int i; | int i; | ||||
if (msg_size < sizeof(*filter_list)) { | |||||
i40e_send_vf_nack(pf, vf, VIRTCHNL_OP_ADD_VLAN, | |||||
I40E_ERR_PARAM); | |||||
return; | |||||
} | |||||
filter_list = msg; | filter_list = msg; | ||||
expected_size = sizeof(*filter_list) + | |||||
filter_list->num_elements * sizeof(uint16_t); | if (filter_list->vsi_id != vf->vsi.vsi_num) { | ||||
if (filter_list->num_elements == 0 || | |||||
filter_list->vsi_id != vf->vsi.vsi_num || | |||||
msg_size != expected_size) { | |||||
i40e_send_vf_nack(pf, vf, VIRTCHNL_OP_ADD_VLAN, | i40e_send_vf_nack(pf, vf, VIRTCHNL_OP_ADD_VLAN, | ||||
I40E_ERR_PARAM); | I40E_ERR_PARAM); | ||||
return; | return; | ||||
} | } | ||||
if (!(vf->vf_flags & VF_FLAG_VLAN_CAP)) { | if (!(vf->vf_flags & VF_FLAG_VLAN_CAP)) { | ||||
i40e_send_vf_nack(pf, vf, VIRTCHNL_OP_ADD_VLAN, | i40e_send_vf_nack(pf, vf, VIRTCHNL_OP_ADD_VLAN, | ||||
I40E_ERR_PARAM); | I40E_ERR_PARAM); | ||||
Show All 21 Lines | |||||
} | } | ||||
static void | static void | ||||
ixl_vf_del_vlan_msg(struct ixl_pf *pf, struct ixl_vf *vf, void *msg, | ixl_vf_del_vlan_msg(struct ixl_pf *pf, struct ixl_vf *vf, void *msg, | ||||
uint16_t msg_size) | uint16_t msg_size) | ||||
{ | { | ||||
struct virtchnl_vlan_filter_list *filter_list; | struct virtchnl_vlan_filter_list *filter_list; | ||||
int i; | int i; | ||||
size_t expected_size; | |||||
if (msg_size < sizeof(*filter_list)) { | |||||
i40e_send_vf_nack(pf, vf, VIRTCHNL_OP_DEL_VLAN, | |||||
I40E_ERR_PARAM); | |||||
return; | |||||
} | |||||
filter_list = msg; | filter_list = msg; | ||||
expected_size = sizeof(*filter_list) + | |||||
filter_list->num_elements * sizeof(uint16_t); | if (filter_list->vsi_id != vf->vsi.vsi_num) { | ||||
if (filter_list->num_elements == 0 || | |||||
filter_list->vsi_id != vf->vsi.vsi_num || | |||||
msg_size != expected_size) { | |||||
i40e_send_vf_nack(pf, vf, VIRTCHNL_OP_DEL_VLAN, | i40e_send_vf_nack(pf, vf, VIRTCHNL_OP_DEL_VLAN, | ||||
I40E_ERR_PARAM); | I40E_ERR_PARAM); | ||||
return; | return; | ||||
} | } | ||||
for (i = 0; i < filter_list->num_elements; i++) { | for (i = 0; i < filter_list->num_elements; i++) { | ||||
if (filter_list->vlan_id[i] > EVL_VLID_MASK) { | if (filter_list->vlan_id[i] > EVL_VLID_MASK) { | ||||
i40e_send_vf_nack(pf, vf, VIRTCHNL_OP_ADD_VLAN, | i40e_send_vf_nack(pf, vf, VIRTCHNL_OP_ADD_VLAN, | ||||
Show All 17 Lines | |||||
static void | static void | ||||
ixl_vf_config_promisc_msg(struct ixl_pf *pf, struct ixl_vf *vf, | ixl_vf_config_promisc_msg(struct ixl_pf *pf, struct ixl_vf *vf, | ||||
void *msg, uint16_t msg_size) | void *msg, uint16_t msg_size) | ||||
{ | { | ||||
struct virtchnl_promisc_info *info; | struct virtchnl_promisc_info *info; | ||||
struct i40e_hw *hw = &pf->hw; | struct i40e_hw *hw = &pf->hw; | ||||
enum i40e_status_code code; | enum i40e_status_code code; | ||||
if (msg_size != sizeof(*info)) { | |||||
i40e_send_vf_nack(pf, vf, | |||||
VIRTCHNL_OP_CONFIG_PROMISCUOUS_MODE, I40E_ERR_PARAM); | |||||
return; | |||||
} | |||||
if (!(vf->vf_flags & VF_FLAG_PROMISC_CAP)) { | if (!(vf->vf_flags & VF_FLAG_PROMISC_CAP)) { | ||||
/* | /* | ||||
* Do the same thing as the Linux PF driver -- lie to the VF | * Do the same thing as the Linux PF driver -- lie to the VF | ||||
*/ | */ | ||||
ixl_send_vf_ack(pf, vf, | ixl_send_vf_ack(pf, vf, | ||||
VIRTCHNL_OP_CONFIG_PROMISCUOUS_MODE); | VIRTCHNL_OP_CONFIG_PROMISCUOUS_MODE); | ||||
return; | return; | ||||
} | } | ||||
Show All 31 Lines | |||||
} | } | ||||
static void | static void | ||||
ixl_vf_get_stats_msg(struct ixl_pf *pf, struct ixl_vf *vf, void *msg, | ixl_vf_get_stats_msg(struct ixl_pf *pf, struct ixl_vf *vf, void *msg, | ||||
uint16_t msg_size) | uint16_t msg_size) | ||||
{ | { | ||||
struct virtchnl_queue_select *queue; | struct virtchnl_queue_select *queue; | ||||
if (msg_size != sizeof(*queue)) { | |||||
i40e_send_vf_nack(pf, vf, VIRTCHNL_OP_GET_STATS, | |||||
I40E_ERR_PARAM); | |||||
return; | |||||
} | |||||
queue = msg; | queue = msg; | ||||
if (queue->vsi_id != vf->vsi.vsi_num) { | if (queue->vsi_id != vf->vsi.vsi_num) { | ||||
i40e_send_vf_nack(pf, vf, VIRTCHNL_OP_GET_STATS, | i40e_send_vf_nack(pf, vf, VIRTCHNL_OP_GET_STATS, | ||||
I40E_ERR_PARAM); | I40E_ERR_PARAM); | ||||
return; | return; | ||||
} | } | ||||
ixl_update_eth_stats(&vf->vsi); | ixl_update_eth_stats(&vf->vsi); | ||||
ixl_send_vf_msg(pf, vf, VIRTCHNL_OP_GET_STATS, | ixl_send_vf_msg(pf, vf, VIRTCHNL_OP_GET_STATS, | ||||
I40E_SUCCESS, &vf->vsi.eth_stats, sizeof(vf->vsi.eth_stats)); | I40E_SUCCESS, &vf->vsi.eth_stats, sizeof(vf->vsi.eth_stats)); | ||||
} | } | ||||
static void | static void | ||||
ixl_vf_config_rss_key_msg(struct ixl_pf *pf, struct ixl_vf *vf, void *msg, | ixl_vf_config_rss_key_msg(struct ixl_pf *pf, struct ixl_vf *vf, void *msg, | ||||
uint16_t msg_size) | uint16_t msg_size) | ||||
{ | { | ||||
struct i40e_hw *hw; | struct i40e_hw *hw; | ||||
struct virtchnl_rss_key *key; | struct virtchnl_rss_key *key; | ||||
struct i40e_aqc_get_set_rss_key_data key_data; | struct i40e_aqc_get_set_rss_key_data key_data; | ||||
enum i40e_status_code status; | enum i40e_status_code status; | ||||
hw = &pf->hw; | hw = &pf->hw; | ||||
if (msg_size < sizeof(*key)) { | |||||
i40e_send_vf_nack(pf, vf, VIRTCHNL_OP_CONFIG_RSS_KEY, | |||||
I40E_ERR_PARAM); | |||||
return; | |||||
} | |||||
key = msg; | key = msg; | ||||
if (key->key_len > 52) { | if (key->key_len > 52) { | ||||
device_printf(pf->dev, "VF %d: Key size in msg (%d) is greater than max key size (%d)\n", | device_printf(pf->dev, "VF %d: Key size in msg (%d) is greater than max key size (%d)\n", | ||||
vf->vf_num, key->key_len, 52); | vf->vf_num, key->key_len, 52); | ||||
i40e_send_vf_nack(pf, vf, VIRTCHNL_OP_CONFIG_RSS_KEY, | i40e_send_vf_nack(pf, vf, VIRTCHNL_OP_CONFIG_RSS_KEY, | ||||
I40E_ERR_PARAM); | I40E_ERR_PARAM); | ||||
return; | return; | ||||
Show All 40 Lines | ixl_vf_config_rss_lut_msg(struct ixl_pf *pf, struct ixl_vf *vf, void *msg, | ||||
uint16_t msg_size) | uint16_t msg_size) | ||||
{ | { | ||||
struct i40e_hw *hw; | struct i40e_hw *hw; | ||||
struct virtchnl_rss_lut *lut; | struct virtchnl_rss_lut *lut; | ||||
enum i40e_status_code status; | enum i40e_status_code status; | ||||
hw = &pf->hw; | hw = &pf->hw; | ||||
if (msg_size < sizeof(*lut)) { | |||||
i40e_send_vf_nack(pf, vf, VIRTCHNL_OP_CONFIG_RSS_LUT, | |||||
I40E_ERR_PARAM); | |||||
return; | |||||
} | |||||
lut = msg; | lut = msg; | ||||
if (lut->lut_entries > 64) { | if (lut->lut_entries > 64) { | ||||
device_printf(pf->dev, "VF %d: # of LUT entries in msg (%d) is greater than max (%d)\n", | device_printf(pf->dev, "VF %d: # of LUT entries in msg (%d) is greater than max (%d)\n", | ||||
vf->vf_num, lut->lut_entries, 64); | vf->vf_num, lut->lut_entries, 64); | ||||
i40e_send_vf_nack(pf, vf, VIRTCHNL_OP_CONFIG_RSS_LUT, | i40e_send_vf_nack(pf, vf, VIRTCHNL_OP_CONFIG_RSS_LUT, | ||||
I40E_ERR_PARAM); | I40E_ERR_PARAM); | ||||
return; | return; | ||||
Show All 31 Lines | |||||
static void | static void | ||||
ixl_vf_set_rss_hena_msg(struct ixl_pf *pf, struct ixl_vf *vf, void *msg, | ixl_vf_set_rss_hena_msg(struct ixl_pf *pf, struct ixl_vf *vf, void *msg, | ||||
uint16_t msg_size) | uint16_t msg_size) | ||||
{ | { | ||||
struct i40e_hw *hw; | struct i40e_hw *hw; | ||||
struct virtchnl_rss_hena *hena; | struct virtchnl_rss_hena *hena; | ||||
hw = &pf->hw; | hw = &pf->hw; | ||||
if (msg_size < sizeof(*hena)) { | |||||
i40e_send_vf_nack(pf, vf, VIRTCHNL_OP_SET_RSS_HENA, | |||||
I40E_ERR_PARAM); | |||||
return; | |||||
} | |||||
hena = msg; | hena = msg; | ||||
/* Set HENA */ | /* Set HENA */ | ||||
i40e_write_rx_ctl(hw, I40E_VFQF_HENA1(0, vf->vf_num), (u32)hena->hena); | i40e_write_rx_ctl(hw, I40E_VFQF_HENA1(0, vf->vf_num), (u32)hena->hena); | ||||
i40e_write_rx_ctl(hw, I40E_VFQF_HENA1(1, vf->vf_num), (u32)(hena->hena >> 32)); | i40e_write_rx_ctl(hw, I40E_VFQF_HENA1(1, vf->vf_num), (u32)(hena->hena >> 32)); | ||||
DDPRINTF(pf->dev, "VF %d: Programmed HENA with 0x%016lx", | DDPRINTF(pf->dev, "VF %d: Programmed HENA with 0x%016lx", | ||||
vf->vf_num, hena->hena); | vf->vf_num, hena->hena); | ||||
ixl_send_vf_ack(pf, vf, VIRTCHNL_OP_SET_RSS_HENA); | ixl_send_vf_ack(pf, vf, VIRTCHNL_OP_SET_RSS_HENA); | ||||
} | } | ||||
static void | static void | ||||
ixl_notify_vf_link_state(struct ixl_pf *pf, struct ixl_vf *vf) | ixl_notify_vf_link_state(struct ixl_pf *pf, struct ixl_vf *vf) | ||||
{ | { | ||||
struct virtchnl_pf_event event; | struct virtchnl_pf_event event; | ||||
struct i40e_hw *hw; | struct i40e_hw *hw; | ||||
hw = &pf->hw; | hw = &pf->hw; | ||||
event.event = VIRTCHNL_EVENT_LINK_CHANGE; | event.event = VIRTCHNL_EVENT_LINK_CHANGE; | ||||
event.severity = PF_EVENT_SEVERITY_INFO; | event.severity = PF_EVENT_SEVERITY_INFO; | ||||
event.event_data.link_event.link_status = pf->vsi.link_active; | event.event_data.link_event.link_status = pf->vsi.link_active; | ||||
event.event_data.link_event.link_speed = | event.event_data.link_event.link_speed = | ||||
(enum virtchnl_link_speed)hw->phy.link_info.link_speed; | i40e_virtchnl_link_speed(hw->phy.link_info.link_speed); | ||||
ixl_send_vf_msg(pf, vf, VIRTCHNL_OP_EVENT, I40E_SUCCESS, &event, | ixl_send_vf_msg(pf, vf, VIRTCHNL_OP_EVENT, I40E_SUCCESS, &event, | ||||
sizeof(event)); | sizeof(event)); | ||||
} | } | ||||
void | void | ||||
ixl_broadcast_link_state(struct ixl_pf *pf) | ixl_broadcast_link_state(struct ixl_pf *pf) | ||||
{ | { | ||||
int i; | int i; | ||||
for (i = 0; i < pf->num_vfs; i++) | for (i = 0; i < pf->num_vfs; i++) | ||||
ixl_notify_vf_link_state(pf, &pf->vfs[i]); | ixl_notify_vf_link_state(pf, &pf->vfs[i]); | ||||
} | } | ||||
void | void | ||||
ixl_handle_vf_msg(struct ixl_pf *pf, struct i40e_arq_event_info *event) | ixl_handle_vf_msg(struct ixl_pf *pf, struct i40e_arq_event_info *event) | ||||
{ | { | ||||
device_t dev = pf->dev; | |||||
struct ixl_vf *vf; | struct ixl_vf *vf; | ||||
void *msg; | |||||
uint16_t vf_num, msg_size; | uint16_t vf_num, msg_size; | ||||
uint32_t opcode; | uint32_t opcode; | ||||
void *msg; | |||||
int err; | |||||
vf_num = le16toh(event->desc.retval) - pf->hw.func_caps.vf_base_id; | vf_num = le16toh(event->desc.retval) - pf->hw.func_caps.vf_base_id; | ||||
opcode = le32toh(event->desc.cookie_high); | opcode = le32toh(event->desc.cookie_high); | ||||
if (vf_num >= pf->num_vfs) { | if (vf_num >= pf->num_vfs) { | ||||
device_printf(pf->dev, "Got msg from illegal VF: %d\n", vf_num); | device_printf(pf->dev, "Got msg from illegal VF: %d\n", vf_num); | ||||
return; | return; | ||||
} | } | ||||
vf = &pf->vfs[vf_num]; | vf = &pf->vfs[vf_num]; | ||||
msg = event->msg_buf; | msg = event->msg_buf; | ||||
msg_size = event->msg_len; | msg_size = event->msg_len; | ||||
I40E_VC_DEBUG(pf, ixl_vc_opcode_level(opcode), | I40E_VC_DEBUG(pf, ixl_vc_opcode_level(opcode), | ||||
"Got msg %s(%d) from%sVF-%d of size %d\n", | "Got msg %s(%d) from%sVF-%d of size %d\n", | ||||
ixl_vc_opcode_str(opcode), opcode, | ixl_vc_opcode_str(opcode), opcode, | ||||
(vf->vf_flags & VF_FLAG_ENABLED) ? " " : " disabled ", | (vf->vf_flags & VF_FLAG_ENABLED) ? " " : " disabled ", | ||||
vf_num, msg_size); | vf_num, msg_size); | ||||
/* Perform basic checks on the msg */ | |||||
err = virtchnl_vc_validate_vf_msg(&vf->version, opcode, msg, msg_size); | |||||
if (err) { | |||||
device_printf(dev, "%s: Received invalid msg from VF-%d: opcode %d, len %d, error %d\n", | |||||
__func__, vf->vf_num, opcode, msg_size, err); | |||||
i40e_send_vf_nack(pf, vf, opcode, I40E_ERR_PARAM); | |||||
return; | |||||
} | |||||
/* This must be a stray msg from a previously destroyed VF. */ | /* This must be a stray msg from a previously destroyed VF. */ | ||||
if (!(vf->vf_flags & VF_FLAG_ENABLED)) | if (!(vf->vf_flags & VF_FLAG_ENABLED)) | ||||
return; | return; | ||||
switch (opcode) { | switch (opcode) { | ||||
case VIRTCHNL_OP_VERSION: | case VIRTCHNL_OP_VERSION: | ||||
ixl_vf_version_msg(pf, vf, msg, msg_size); | ixl_vf_version_msg(pf, vf, msg, msg_size); | ||||
break; | break; | ||||
▲ Show 20 Lines • Show All 191 Lines • ▼ Show 20 Lines | |||||
int | int | ||||
ixl_if_iov_init(if_ctx_t ctx, uint16_t num_vfs, const nvlist_t *params) | ixl_if_iov_init(if_ctx_t ctx, uint16_t num_vfs, const nvlist_t *params) | ||||
{ | { | ||||
struct ixl_pf *pf = iflib_get_softc(ctx); | struct ixl_pf *pf = iflib_get_softc(ctx); | ||||
device_t dev = iflib_get_dev(ctx); | device_t dev = iflib_get_dev(ctx); | ||||
struct i40e_hw *hw; | struct i40e_hw *hw; | ||||
struct ixl_vsi *pf_vsi; | struct ixl_vsi *pf_vsi; | ||||
enum i40e_status_code ret; | enum i40e_status_code ret; | ||||
int i, error; | int error; | ||||
hw = &pf->hw; | hw = &pf->hw; | ||||
pf_vsi = &pf->vsi; | pf_vsi = &pf->vsi; | ||||
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++) | |||||
sysctl_ctx_init(&pf->vfs[i].ctx); | |||||
/* | /* | ||||
* Add the VEB and ... | * Add the VEB and ... | ||||
* - do nothing: VEPA mode | * - do nothing: VEPA mode | ||||
* - enable loopback mode on connected VSIs: VEB mode | * - enable loopback mode on connected VSIs: VEB mode | ||||
*/ | */ | ||||
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) { | ||||
▲ Show 20 Lines • Show All 56 Lines • ▼ Show 20 Lines | ixl_if_iov_uninit(if_ctx_t ctx) | ||||
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; | ||||
/* sysctl_ctx_free might sleep, but this func is called w/ an sx lock */ | /* sysctl_ctx_free might sleep, but this func is called w/ an sx lock */ | ||||
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].vsi.sysctl_ctx); | ||||
free(vfs, M_IXL); | free(vfs, M_IXL); | ||||
} | } | ||||
static int | static int | ||||
ixl_vf_reserve_queues(struct ixl_pf *pf, struct ixl_vf *vf, int num_queues) | ixl_vf_reserve_queues(struct ixl_pf *pf, struct ixl_vf *vf, int num_queues) | ||||
{ | { | ||||
device_t dev = pf->dev; | device_t dev = pf->dev; | ||||
int error; | int error; | ||||
Show All 22 Lines | ixl_vf_reserve_queues(struct ixl_pf *pf, struct ixl_vf *vf, int num_queues) | ||||
return (0); | return (0); | ||||
} | } | ||||
int | int | ||||
ixl_if_iov_vf_add(if_ctx_t ctx, uint16_t vfnum, const nvlist_t *params) | ixl_if_iov_vf_add(if_ctx_t ctx, uint16_t vfnum, const nvlist_t *params) | ||||
{ | { | ||||
struct ixl_pf *pf = iflib_get_softc(ctx); | struct ixl_pf *pf = iflib_get_softc(ctx); | ||||
device_t dev = pf->dev; | char sysctl_name[IXL_QUEUE_NAME_LEN]; | ||||
char sysctl_name[QUEUE_NAME_LEN]; | |||||
struct ixl_vf *vf; | struct ixl_vf *vf; | ||||
const void *mac; | const void *mac; | ||||
size_t size; | size_t size; | ||||
int error; | int error; | ||||
int vf_num_queues; | int vf_num_queues; | ||||
vf = &pf->vfs[vfnum]; | vf = &pf->vfs[vfnum]; | ||||
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); | |||||
/* 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"); | ||||
error = ixl_vf_reserve_queues(pf, vf, vf_num_queues); | error = ixl_vf_reserve_queues(pf, vf, vf_num_queues); | ||||
if (error != 0) | if (error != 0) | ||||
goto out; | goto out; | ||||
error = ixl_vf_setup_vsi(pf, vf); | error = ixl_vf_setup_vsi(pf, vf); | ||||
Show All 21 Lines | ixl_if_iov_vf_add(if_ctx_t ctx, uint16_t vfnum, const nvlist_t *params) | ||||
vf->vf_flags |= VF_FLAG_VLAN_CAP; | vf->vf_flags |= VF_FLAG_VLAN_CAP; | ||||
/* VF needs to be reset before it can be used */ | /* VF needs to be reset before it can be used */ | ||||
ixl_reset_vf(pf, vf); | ixl_reset_vf(pf, vf); | ||||
out: | out: | ||||
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(dev, &vf->vsi, &vf->ctx, sysctl_name); | ixl_vsi_add_sysctls(&vf->vsi, sysctl_name, false); | ||||
} | } | ||||
return (error); | return (error); | ||||
} | } | ||||