Skip to content

Commit

Permalink
net/iavf: fix abnormal disable HW interrupt
Browse files Browse the repository at this point in the history
[ upstream commit 675a104e2e940ec476e8b469725e8465d01c0098 ]

For command VIRTCHNL_OP_REQUEST_QUEUES, polling access to the admin
queue has the issue of access overruns after disabling interrupt. That
results in FW disabling HW interrupt for protection purposes.

The updates/changes in this patch:
1. Remove the polling admin queue processing and use the generic interrupt
processing instead.
2. Release redundant queue resource before stopping processing interrupt
events.

Fixes: 22b123a ("net/avf: initialize PMD")
Fixes: ef80792 ("net/iavf: support requesting additional queues from PF")
Fixes: 8410842 ("net/iavf: support asynchronous virtual channel message")

Signed-off-by: Mingjin Ye <mingjinx.ye@intel.com>
Acked-by: Qi Zhang <qi.z.zhang@intel.com>
  • Loading branch information
yemj-odc authored and kevintraynor committed Jul 12, 2023
1 parent 3a61738 commit 8fcb633
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 50 deletions.
25 changes: 13 additions & 12 deletions drivers/net/iavf/iavf_ethdev.c
Original file line number Diff line number Diff line change
Expand Up @@ -2644,6 +2644,19 @@ iavf_dev_close(struct rte_eth_dev *dev)
}

ret = iavf_dev_stop(dev);

/*
* Release redundant queue resource when close the dev
* so that other vfs can re-use the queues.
*/
if (vf->lv_enabled) {
ret = iavf_request_queues(dev, IAVF_MAX_NUM_QUEUES_DFLT);
if (ret)
PMD_DRV_LOG(ERR, "Reset the num of queues failed");

vf->max_rss_qregion = IAVF_MAX_NUM_QUEUES_DFLT;
}

adapter->closed = true;

/* free iAVF security device context all related resources */
Expand All @@ -2660,18 +2673,6 @@ iavf_dev_close(struct rte_eth_dev *dev)
if (vf->promisc_unicast_enabled || vf->promisc_multicast_enabled)
iavf_config_promisc(adapter, false, false);

/*
* Release redundant queue resource when close the dev
* so that other vfs can re-use the queues.
*/
if (vf->lv_enabled) {
ret = iavf_request_queues(dev, IAVF_MAX_NUM_QUEUES_DFLT);
if (ret)
PMD_DRV_LOG(ERR, "Reset the num of queues failed");

vf->max_rss_qregion = IAVF_MAX_NUM_QUEUES_DFLT;
}

iavf_shutdown_adminq(hw);
if (vf->vf_res->vf_cap_flags & VIRTCHNL_VF_OFFLOAD_WB_ON_ITR) {
/* disable uio intr before callback unregister */
Expand Down
48 changes: 10 additions & 38 deletions drivers/net/iavf/iavf_vchnl.c
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,7 @@ iavf_execute_vf_cmd(struct iavf_adapter *adapter, struct iavf_cmd_info *args,

switch (args->ops) {
case VIRTCHNL_OP_RESET_VF:
case VIRTCHNL_OP_REQUEST_QUEUES:
/*no need to wait for response */
_clear_cmd(vf);
break;
Expand All @@ -198,33 +199,6 @@ iavf_execute_vf_cmd(struct iavf_adapter *adapter, struct iavf_cmd_info *args,
}
_clear_cmd(vf);
break;
case VIRTCHNL_OP_REQUEST_QUEUES:
/*
* ignore async reply, only wait for system message,
* vf_reset = true if get VIRTCHNL_EVENT_RESET_IMPENDING,
* if not, means request queues failed.
*/
do {
result = iavf_read_msg_from_pf(adapter, args->out_size,
args->out_buffer);
if (result == IAVF_MSG_SYS && vf->vf_reset) {
break;
} else if (result == IAVF_MSG_CMD ||
result == IAVF_MSG_ERR) {
err = -1;
break;
}
iavf_msec_delay(ASQ_DELAY_MS);
/* If don't read msg or read sys event, continue */
} while (i++ < MAX_TRY_TIMES);
if (i >= MAX_TRY_TIMES ||
vf->cmd_retval != VIRTCHNL_STATUS_SUCCESS) {
err = -1;
PMD_DRV_LOG(ERR, "No response or return failure (%d)"
" for cmd %d", vf->cmd_retval, args->ops);
}
_clear_cmd(vf);
break;
default:
/* For other virtchnl ops in running time,
* wait for the cmd done flag.
Expand Down Expand Up @@ -1722,11 +1696,11 @@ iavf_request_queues(struct rte_eth_dev *dev, uint16_t num)
struct iavf_adapter *adapter =
IAVF_DEV_PRIVATE_TO_ADAPTER(dev->data->dev_private);
struct iavf_info *vf = IAVF_DEV_PRIVATE_TO_VF(adapter);
struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev);
struct virtchnl_vf_res_request vfres;
struct iavf_cmd_info args;
uint16_t num_queue_pairs;
int err;
int i = 0;

if (!(vf->vf_res->vf_cap_flags &
VIRTCHNL_VF_OFFLOAD_REQ_QUEUES)) {
Expand All @@ -1747,16 +1721,7 @@ iavf_request_queues(struct rte_eth_dev *dev, uint16_t num)
args.out_size = IAVF_AQ_BUF_SZ;

if (vf->vf_res->vf_cap_flags & VIRTCHNL_VF_OFFLOAD_WB_ON_ITR) {
/* disable interrupt to avoid the admin queue message to be read
* before iavf_read_msg_from_pf.
*
* don't disable interrupt handler until ready to execute vf cmd.
*/
rte_spinlock_lock(&vf->aq_lock);
rte_intr_disable(pci_dev->intr_handle);
err = iavf_execute_vf_cmd(adapter, &args, 0);
rte_intr_enable(pci_dev->intr_handle);
rte_spinlock_unlock(&vf->aq_lock);
err = iavf_execute_vf_cmd_safe(adapter, &args, 0);
} else {
rte_eal_alarm_cancel(iavf_dev_alarm_handler, dev);
err = iavf_execute_vf_cmd_safe(adapter, &args, 0);
Expand All @@ -1769,6 +1734,13 @@ iavf_request_queues(struct rte_eth_dev *dev, uint16_t num)
return err;
}

/* wait for interrupt notification vf is resetting */
while (i++ < MAX_TRY_TIMES) {
if (vf->vf_reset)
break;
iavf_msec_delay(ASQ_DELAY_MS);
}

/* request queues succeeded, vf is resetting */
if (vf->vf_reset) {
PMD_DRV_LOG(INFO, "vf is resetting");
Expand Down

0 comments on commit 8fcb633

Please sign in to comment.