Currently, there is a certain amount of duplication and unnecessary branching in the virtchnl message handling function which makes it difficult to read and reason about.
Refactor the function to achieve the following: - clean and explicit distinction between synchronous and asynchronous ops - common looping and error handling logic - fewer and clearer special cases Signed-off-by: Anatoly Burakov <[email protected]> --- drivers/net/intel/iavf/iavf_vchnl.c | 151 +++++++++++++--------------- 1 file changed, 70 insertions(+), 81 deletions(-) diff --git a/drivers/net/intel/iavf/iavf_vchnl.c b/drivers/net/intel/iavf/iavf_vchnl.c index d240745f5c..3f6ce0dd89 100644 --- a/drivers/net/intel/iavf/iavf_vchnl.c +++ b/drivers/net/intel/iavf/iavf_vchnl.c @@ -361,16 +361,66 @@ iavf_get_cmd_resp_count(enum virtchnl_ops op) } } +static int +iavf_op_needs_poll(struct iavf_info *vf) +{ + /* Poll if interrupts disabled or we are in interrupt thread */ + return !vf->aq_intr_enabled || rte_thread_is_intr(); +} + +static int +iavf_wait_for_msg(struct iavf_adapter *adapter, struct iavf_cmd_info *args, + bool poll) +{ + struct iavf_info *vf = IAVF_DEV_PRIVATE_TO_VF(adapter); + int err = 0; + int i = 0; + + if (args->out_buffer == NULL) { + PMD_DRV_LOG(ERR, "Invalid buffer for cmd %d response", args->ops); + return -EINVAL; + } + + /* Wait for command completion */ + do { + if (poll) { + enum iavf_aq_result result; + result = iavf_read_msg_from_pf(adapter, args->out_size, + args->out_buffer); + if (result == IAVF_MSG_CMD) + break; + } else { + /* check if interrupt thread has erased pending cmd */ + if (vf->pend_cmd == VIRTCHNL_OP_UNKNOWN) + break; + } + iavf_msec_delay(ASQ_DELAY_MS); + } while (i++ < MAX_TRY_TIMES); + + if (i >= MAX_TRY_TIMES) { + PMD_DRV_LOG(ERR, "No response for cmd %d", args->ops); + err = -EIO; + } else if (vf->cmd_retval == VIRTCHNL_STATUS_ERR_NOT_SUPPORTED) { + PMD_DRV_LOG(ERR, "Cmd %d not supported", args->ops); + err = -ENOTSUP; + } else if (vf->cmd_retval != VIRTCHNL_STATUS_SUCCESS) { + PMD_DRV_LOG(ERR, "Return failure %d for cmd %d", + vf->cmd_retval, args->ops); + err = -EINVAL; + } + + return err; +} + static int iavf_execute_vf_cmd(struct iavf_adapter *adapter, struct iavf_cmd_info *args) { struct iavf_hw *hw = IAVF_DEV_PRIVATE_TO_HW(adapter); struct iavf_info *vf = IAVF_DEV_PRIVATE_TO_VF(adapter); - enum iavf_aq_result result; - enum iavf_status ret; + enum iavf_status status; uint32_t resp_count; - int err = 0; - int i = 0; + bool poll = iavf_op_needs_poll(vf); + int err; if (vf->vf_reset) return -EIO; @@ -385,89 +435,28 @@ iavf_execute_vf_cmd(struct iavf_adapter *adapter, struct iavf_cmd_info *args) if (iavf_set_pending_cmd(vf, args->ops, RTE_MAX(1U, resp_count))) return -1; - ret = iavf_aq_send_msg_to_pf(hw, args->ops, IAVF_SUCCESS, - args->in_args, args->in_args_size, NULL); - if (ret) { + status = iavf_aq_send_msg_to_pf(hw, args->ops, IAVF_SUCCESS, + args->in_args, args->in_args_size, NULL); + if (status != IAVF_SUCCESS) { PMD_DRV_LOG(ERR, "fail to send cmd %d", args->ops); - iavf_clear_pending_cmd(vf); - return err; + err = (int)status; + goto clear_cmd; + } else if (resp_count == 0) { + /* we're not waiting on responses */ + err = 0; + goto clear_cmd; } - if (resp_count == 0) { - /* reset pending commands, counter will be overwritten on reset */ - iavf_clear_pending_cmd(vf); - return 0; - } - - switch (args->ops) { - case VIRTCHNL_OP_VERSION: - case VIRTCHNL_OP_GET_VF_RESOURCES: - case VIRTCHNL_OP_GET_SUPPORTED_RXDIDS: - case VIRTCHNL_OP_GET_OFFLOAD_VLAN_V2_CAPS: - /* for init virtchnl ops, need to poll the response */ - do { - result = iavf_read_msg_from_pf(adapter, args->out_size, - args->out_buffer); - if (result == IAVF_MSG_CMD) - break; - iavf_msec_delay(ASQ_DELAY_MS); - } 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); - } - iavf_clear_pending_cmd(vf); - break; - default: - if (rte_thread_is_intr()) { - /* For virtchnl ops were executed in eal_intr_thread, - * need to poll the response. - */ - do { - result = iavf_read_msg_from_pf(adapter, args->out_size, - args->out_buffer); - if (result == IAVF_MSG_CMD) - break; - iavf_msec_delay(ASQ_DELAY_MS); - } 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); - } - iavf_clear_pending_cmd(vf); - } else { - /* For other virtchnl ops in running time, - * wait for the cmd done flag. - */ - do { - if (vf->pend_cmd == VIRTCHNL_OP_UNKNOWN) - break; - iavf_msec_delay(ASQ_DELAY_MS); - /* If don't read msg or read sys event, continue */ - } while (i++ < MAX_TRY_TIMES); + err = iavf_wait_for_msg(adapter, args, poll); - if (i >= MAX_TRY_TIMES) { - PMD_DRV_LOG(ERR, "No response for cmd %d", args->ops); - iavf_clear_pending_cmd(vf); - err = -EIO; - } else if (vf->cmd_retval == - VIRTCHNL_STATUS_ERR_NOT_SUPPORTED) { - PMD_DRV_LOG(ERR, "Cmd %d not supported", args->ops); - err = -ENOTSUP; - } else if (vf->cmd_retval != VIRTCHNL_STATUS_SUCCESS) { - PMD_DRV_LOG(ERR, "Return failure %d for cmd %d", - vf->cmd_retval, args->ops); - err = -EINVAL; - } - } - break; - } + /* in interrupt success case, pending cmd is cleared by intr thread */ + if (err != 0 || poll) + goto clear_cmd; return err; +clear_cmd: + iavf_clear_pending_cmd(vf); + return err; } static int -- 2.47.3

