* [dpdk-dev] [PATCH v2 0/2] i40evf: support interrupt based pf reset request @ 2016-01-27 1:46 Jingjing Wu 2016-01-27 1:46 ` [dpdk-dev] [PATCH v2 1/2] i40evf: allocate virtchnl cmd buffer for each vf Jingjing Wu 2016-01-27 1:46 ` [dpdk-dev] [PATCH v2 2/2] i40evf: support interrupt based pf reset request Jingjing Wu 0 siblings, 2 replies; 7+ messages in thread From: Jingjing Wu @ 2016-01-27 1:46 UTC (permalink / raw) To: dev v2 changes: remove the change on vf reset status checking add pf event report support in release note If DPDK is used on VF while the host is using Linux Kernel driver as PF driver on FVL NIC, some setting on PF will trigger VF reset. DPDK VF need to know the event. This patch set makes the interrupt based request of PF reset from PF supported by enabling the adminq event process in VF driver. Users can register a callback for this interrupt event to get informed, when a PF reset request detected like: rte_eth_dev_callback_register(portid, RTE_ETH_EVENT_INTR_RESET, reset_event_callback, arg); Jingjing Wu (2): i40evf: allocate virtchnl cmd buffer for each vf i40evf: support interrupt based pf reset request doc/guides/rel_notes/release_2_3.rst | 1 + drivers/net/i40e/i40e_ethdev.h | 2 + drivers/net/i40e/i40e_ethdev_vf.c | 423 +++++++++++++++++++++++++---------- lib/librte_ether/rte_ethdev.h | 1 + 4 files changed, 304 insertions(+), 123 deletions(-) -- 2.4.0 ^ permalink raw reply [flat|nested] 7+ messages in thread
* [dpdk-dev] [PATCH v2 1/2] i40evf: allocate virtchnl cmd buffer for each vf 2016-01-27 1:46 [dpdk-dev] [PATCH v2 0/2] i40evf: support interrupt based pf reset request Jingjing Wu @ 2016-01-27 1:46 ` Jingjing Wu 2016-01-27 1:46 ` [dpdk-dev] [PATCH v2 2/2] i40evf: support interrupt based pf reset request Jingjing Wu 1 sibling, 0 replies; 7+ messages in thread From: Jingjing Wu @ 2016-01-27 1:46 UTC (permalink / raw) To: dev Currently, i40evf PMD uses a global static buffer to send virtchnl command to host driver. It is shared by multi VFs. This patch changed to allocate virtchnl cmd buffer for each VF. Signed-off-by: Jingjing Wu <jingjing.wu@intel.com> --- drivers/net/i40e/i40e_ethdev.h | 2 + drivers/net/i40e/i40e_ethdev_vf.c | 181 +++++++++++++++----------------------- 2 files changed, 74 insertions(+), 109 deletions(-) diff --git a/drivers/net/i40e/i40e_ethdev.h b/drivers/net/i40e/i40e_ethdev.h index 1f9792b..93122ad 100644 --- a/drivers/net/i40e/i40e_ethdev.h +++ b/drivers/net/i40e/i40e_ethdev.h @@ -494,7 +494,9 @@ struct i40e_vf { bool link_up; bool vf_reset; volatile uint32_t pend_cmd; /* pending command not finished yet */ + uint32_t cmd_retval; /* return value of the cmd response from PF */ u16 pend_msg; /* flags indicates events from pf not handled yet */ + uint8_t *aq_resp; /* buffer to store the adminq response from PF */ /* VSI info */ struct i40e_virtchnl_vf_resource *vf_res; /* All VSIs */ diff --git a/drivers/net/i40e/i40e_ethdev_vf.c b/drivers/net/i40e/i40e_ethdev_vf.c index 14d2a50..64e6957 100644 --- a/drivers/net/i40e/i40e_ethdev_vf.c +++ b/drivers/net/i40e/i40e_ethdev_vf.c @@ -103,9 +103,6 @@ enum i40evf_aq_result { I40EVF_MSG_CMD, /* Read async command result */ }; -/* A share buffer to store the command result from PF driver */ -static uint8_t cmd_result_buffer[I40E_AQ_BUF_SZ]; - static int i40evf_dev_configure(struct rte_eth_dev *dev); static int i40evf_dev_start(struct rte_eth_dev *dev); static void i40evf_dev_stop(struct rte_eth_dev *dev); @@ -237,31 +234,39 @@ i40evf_set_mac_type(struct i40e_hw *hw) } /* - * Parse admin queue message. - * - * return value: - * < 0: meet error - * 0: read sys msg - * > 0: read cmd result + * Read data in admin queue to get msg from pf driver */ static enum i40evf_aq_result -i40evf_parse_pfmsg(struct i40e_vf *vf, - struct i40e_arq_event_info *event, - struct i40evf_arq_msg_info *data) +i40evf_read_pfmsg(struct rte_eth_dev *dev, struct i40evf_arq_msg_info *data) { - enum i40e_virtchnl_ops opcode = (enum i40e_virtchnl_ops)\ - rte_le_to_cpu_32(event->desc.cookie_high); - enum i40e_status_code retval = (enum i40e_status_code)\ - rte_le_to_cpu_32(event->desc.cookie_low); - enum i40evf_aq_result ret = I40EVF_MSG_CMD; + struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private); + struct i40e_vf *vf = I40EVF_DEV_PRIVATE_TO_VF(dev->data->dev_private); + struct i40e_arq_event_info event; + enum i40e_virtchnl_ops opcode; + enum i40e_status_code retval; + int ret; + enum i40evf_aq_result result = I40EVF_MSG_NON; + event.buf_len = data->buf_len; + event.msg_buf = data->msg; + ret = i40e_clean_arq_element(hw, &event, NULL); + /* Can't read any msg from adminQ */ + if (ret) { + if (ret == I40E_ERR_ADMIN_QUEUE_NO_WORK) + result = I40EVF_MSG_NON; + else + result = I40EVF_MSG_ERR; + return result; + } + + opcode = (enum i40e_virtchnl_ops)rte_le_to_cpu_32(event.desc.cookie_high); + retval = (enum i40e_status_code)rte_le_to_cpu_32(event.desc.cookie_low); /* pf sys event */ if (opcode == I40E_VIRTCHNL_OP_EVENT) { struct i40e_virtchnl_pf_event *vpe = - (struct i40e_virtchnl_pf_event *)event->msg_buf; + (struct i40e_virtchnl_pf_event *)event.msg_buf; - /* Initialize ret to sys event */ - ret = I40EVF_MSG_SYS; + result = I40EVF_MSG_SYS; switch (vpe->event) { case I40E_VIRTCHNL_EVENT_LINK_CHANGE: vf->link_up = @@ -286,74 +291,17 @@ i40evf_parse_pfmsg(struct i40e_vf *vf, } } else { /* async reply msg on command issued by vf previously */ - ret = I40EVF_MSG_CMD; + result = I40EVF_MSG_CMD; /* Actual data length read from PF */ - data->msg_len = event->msg_len; + data->msg_len = event.msg_len; } - /* fill the ops and result to notify VF */ + data->result = retval; data->ops = opcode; - return ret; -} - -/* - * Read data in admin queue to get msg from pf driver - */ -static enum i40evf_aq_result -i40evf_read_pfmsg(struct rte_eth_dev *dev, struct i40evf_arq_msg_info *data) -{ - struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private); - struct i40e_vf *vf = I40EVF_DEV_PRIVATE_TO_VF(dev->data->dev_private); - struct i40e_arq_event_info event; - int ret; - enum i40evf_aq_result result = I40EVF_MSG_NON; - - event.buf_len = data->buf_len; - event.msg_buf = data->msg; - ret = i40e_clean_arq_element(hw, &event, NULL); - /* Can't read any msg from adminQ */ - if (ret) { - if (ret == I40E_ERR_ADMIN_QUEUE_NO_WORK) - result = I40EVF_MSG_NON; - else - result = I40EVF_MSG_ERR; - return result; - } - - /* Parse the event */ - result = i40evf_parse_pfmsg(vf, &event, data); - return result; } -/* - * Polling read until command result return from pf driver or meet error. - */ -static int -i40evf_wait_cmd_done(struct rte_eth_dev *dev, - struct i40evf_arq_msg_info *data) -{ - int i = 0; - enum i40evf_aq_result ret; - -#define MAX_TRY_TIMES 20 -#define ASQ_DELAY_MS 100 - do { - /* Delay some time first */ - rte_delay_ms(ASQ_DELAY_MS); - ret = i40evf_read_pfmsg(dev, data); - if (ret == I40EVF_MSG_CMD) - return 0; - else if (ret == I40EVF_MSG_ERR) - return -1; - - /* If don't read msg or read sys event, continue */ - } while(i++ < MAX_TRY_TIMES); - - return -1; -} - /** * clear current command. Only call in case execute * _atomic_set_cmd successfully. @@ -380,13 +328,18 @@ _atomic_set_cmd(struct i40e_vf *vf, enum i40e_virtchnl_ops ops) return !ret; } +#define MAX_TRY_TIMES 20 +#define ASQ_DELAY_MS 100 + static int i40evf_execute_vf_cmd(struct rte_eth_dev *dev, struct vf_cmd_info *args) { struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private); struct i40e_vf *vf = I40EVF_DEV_PRIVATE_TO_VF(dev->data->dev_private); - int err = -1; struct i40evf_arq_msg_info info; + enum i40evf_aq_result ret; + int err = -1; + int i = 0; if (_atomic_set_cmd(vf, args->ops)) return -1; @@ -404,19 +357,22 @@ i40evf_execute_vf_cmd(struct rte_eth_dev *dev, struct vf_cmd_info *args) return err; } - err = i40evf_wait_cmd_done(dev, &info); - /* read message and it's expected one */ - if (!err && args->ops == info.ops) - _clear_cmd(vf); - else if (err) { - PMD_DRV_LOG(ERR, "Failed to read message from AdminQ"); - _clear_cmd(vf); - } - else if (args->ops != info.ops) - PMD_DRV_LOG(ERR, "command mismatch, expect %u, get %u", - args->ops, info.ops); + do { + /* Delay some time first */ + rte_delay_ms(ASQ_DELAY_MS); + ret = i40evf_read_pfmsg(dev, &info); + if (ret == I40EVF_MSG_CMD) { + err = 0; + break; + } else if (ret == I40EVF_MSG_ERR) { + err = -1; + break; + } + /* If don't read msg or read sys event, continue */ + } while (i++ < MAX_TRY_TIMES); + _clear_cmd(vf); - return (err | info.result); + return (err | vf->cmd_retval); } /* @@ -436,7 +392,7 @@ i40evf_check_api_version(struct rte_eth_dev *dev) args.ops = I40E_VIRTCHNL_OP_VERSION; args.in_args = (uint8_t *)&version; args.in_args_size = sizeof(version); - args.out_buffer = cmd_result_buffer; + args.out_buffer = vf->aq_resp; args.out_size = I40E_AQ_BUF_SZ; err = i40evf_execute_vf_cmd(dev, &args); @@ -474,7 +430,7 @@ i40evf_get_vf_resource(struct rte_eth_dev *dev) uint32_t caps, len; args.ops = I40E_VIRTCHNL_OP_GET_VF_RESOURCES; - args.out_buffer = cmd_result_buffer; + args.out_buffer = vf->aq_resp; args.out_size = I40E_AQ_BUF_SZ; if (PF_IS_V11(vf)) { caps = I40E_VIRTCHNL_VF_OFFLOAD_L2 | @@ -527,7 +483,7 @@ i40evf_config_promisc(struct rte_eth_dev *dev, args.ops = I40E_VIRTCHNL_OP_CONFIG_PROMISCUOUS_MODE; args.in_args = (uint8_t *)&promisc; args.in_args_size = sizeof(promisc); - args.out_buffer = cmd_result_buffer; + args.out_buffer = vf->aq_resp; args.out_size = I40E_AQ_BUF_SZ; err = i40evf_execute_vf_cmd(dev, &args); @@ -554,7 +510,7 @@ i40evf_config_vlan_offload(struct rte_eth_dev *dev, args.ops = (enum i40e_virtchnl_ops)I40E_VIRTCHNL_OP_CFG_VLAN_OFFLOAD; args.in_args = (uint8_t *)&offload; args.in_args_size = sizeof(offload); - args.out_buffer = cmd_result_buffer; + args.out_buffer = vf->aq_resp; args.out_size = I40E_AQ_BUF_SZ; err = i40evf_execute_vf_cmd(dev, &args); @@ -585,7 +541,7 @@ i40evf_config_vlan_pvid(struct rte_eth_dev *dev, args.ops = (enum i40e_virtchnl_ops)I40E_VIRTCHNL_OP_CFG_VLAN_PVID; args.in_args = (uint8_t *)&tpid_info; args.in_args_size = sizeof(tpid_info); - args.out_buffer = cmd_result_buffer; + args.out_buffer = vf->aq_resp; args.out_size = I40E_AQ_BUF_SZ; err = i40evf_execute_vf_cmd(dev, &args); @@ -664,7 +620,7 @@ i40evf_configure_vsi_queues(struct rte_eth_dev *dev) args.ops = I40E_VIRTCHNL_OP_CONFIG_VSI_QUEUES; args.in_args = (uint8_t *)vc_vqci; args.in_args_size = size; - args.out_buffer = cmd_result_buffer; + args.out_buffer = vf->aq_resp; args.out_size = I40E_AQ_BUF_SZ; ret = i40evf_execute_vf_cmd(dev, &args); if (ret) @@ -717,7 +673,7 @@ i40evf_configure_vsi_queues_ext(struct rte_eth_dev *dev) (enum i40e_virtchnl_ops)I40E_VIRTCHNL_OP_CONFIG_VSI_QUEUES_EXT; args.in_args = (uint8_t *)vc_vqcei; args.in_args_size = size; - args.out_buffer = cmd_result_buffer; + args.out_buffer = vf->aq_resp; args.out_size = I40E_AQ_BUF_SZ; ret = i40evf_execute_vf_cmd(dev, &args); if (ret) @@ -779,7 +735,7 @@ i40evf_config_irq_map(struct rte_eth_dev *dev) args.ops = I40E_VIRTCHNL_OP_CONFIG_IRQ_MAP; args.in_args = (u8 *)cmd_buffer; args.in_args_size = sizeof(cmd_buffer); - args.out_buffer = cmd_result_buffer; + args.out_buffer = vf->aq_resp; args.out_size = I40E_AQ_BUF_SZ; err = i40evf_execute_vf_cmd(dev, &args); if (err) @@ -810,7 +766,7 @@ i40evf_switch_queue(struct rte_eth_dev *dev, bool isrx, uint16_t qid, args.ops = I40E_VIRTCHNL_OP_DISABLE_QUEUES; args.in_args = (u8 *)&queue_select; args.in_args_size = sizeof(queue_select); - args.out_buffer = cmd_result_buffer; + args.out_buffer = vf->aq_resp; args.out_size = I40E_AQ_BUF_SZ; err = i40evf_execute_vf_cmd(dev, &args); if (err) @@ -902,7 +858,7 @@ i40evf_add_mac_addr(struct rte_eth_dev *dev, struct ether_addr *addr) args.ops = I40E_VIRTCHNL_OP_ADD_ETHER_ADDRESS; args.in_args = cmd_buffer; args.in_args_size = sizeof(cmd_buffer); - args.out_buffer = cmd_result_buffer; + args.out_buffer = vf->aq_resp; args.out_size = I40E_AQ_BUF_SZ; err = i40evf_execute_vf_cmd(dev, &args); if (err) @@ -939,7 +895,7 @@ i40evf_del_mac_addr(struct rte_eth_dev *dev, struct ether_addr *addr) args.ops = I40E_VIRTCHNL_OP_DEL_ETHER_ADDRESS; args.in_args = cmd_buffer; args.in_args_size = sizeof(cmd_buffer); - args.out_buffer = cmd_result_buffer; + args.out_buffer = vf->aq_resp; args.out_size = I40E_AQ_BUF_SZ; err = i40evf_execute_vf_cmd(dev, &args); if (err) @@ -962,7 +918,7 @@ i40evf_update_stats(struct rte_eth_dev *dev, struct i40e_eth_stats **pstats) args.ops = I40E_VIRTCHNL_OP_GET_STATS; args.in_args = (u8 *)&q_stats; args.in_args_size = sizeof(q_stats); - args.out_buffer = cmd_result_buffer; + args.out_buffer = vf->aq_resp; args.out_size = I40E_AQ_BUF_SZ; err = i40evf_execute_vf_cmd(dev, &args); @@ -1056,7 +1012,7 @@ i40evf_add_vlan(struct rte_eth_dev *dev, uint16_t vlanid) args.ops = I40E_VIRTCHNL_OP_ADD_VLAN; args.in_args = (u8 *)&cmd_buffer; args.in_args_size = sizeof(cmd_buffer); - args.out_buffer = cmd_result_buffer; + args.out_buffer = vf->aq_resp; args.out_size = I40E_AQ_BUF_SZ; err = i40evf_execute_vf_cmd(dev, &args); if (err) @@ -1083,7 +1039,7 @@ i40evf_del_vlan(struct rte_eth_dev *dev, uint16_t vlanid) args.ops = I40E_VIRTCHNL_OP_DEL_VLAN; args.in_args = (u8 *)&cmd_buffer; args.in_args_size = sizeof(cmd_buffer); - args.out_buffer = cmd_result_buffer; + args.out_buffer = vf->aq_resp; args.out_size = I40E_AQ_BUF_SZ; err = i40evf_execute_vf_cmd(dev, &args); if (err) @@ -1095,6 +1051,7 @@ i40evf_del_vlan(struct rte_eth_dev *dev, uint16_t vlanid) static int i40evf_get_link_status(struct rte_eth_dev *dev, struct rte_eth_link *link) { + struct i40e_vf *vf = I40EVF_DEV_PRIVATE_TO_VF(dev->data->dev_private); int err; struct vf_cmd_info args; struct rte_eth_link *new_link; @@ -1102,7 +1059,7 @@ i40evf_get_link_status(struct rte_eth_dev *dev, struct rte_eth_link *link) args.ops = (enum i40e_virtchnl_ops)I40E_VIRTCHNL_OP_GET_LINK_STAT; args.in_args = NULL; args.in_args_size = 0; - args.out_buffer = cmd_result_buffer; + args.out_buffer = vf->aq_resp; args.out_size = I40E_AQ_BUF_SZ; err = i40evf_execute_vf_cmd(dev, &args); if (err) { @@ -1196,7 +1153,6 @@ i40evf_init_vf(struct rte_eth_dev *dev) goto err; } - /* Reset VF and wait until it's complete */ if (i40evf_reset_vf(hw)) { PMD_INIT_LOG(ERR, "reset NIC failed"); @@ -1214,6 +1170,11 @@ i40evf_init_vf(struct rte_eth_dev *dev) PMD_INIT_LOG(ERR, "init_adminq failed"); return -1; } + vf->aq_resp = rte_zmalloc("vf_aq_resp", I40E_AQ_BUF_SZ, 0); + if (!vf->aq_resp) { + PMD_INIT_LOG(ERR, "unable to allocate vf_aq_resp memory"); + goto err_aq; + } if (i40evf_check_api_version(dev) != 0) { PMD_INIT_LOG(ERR, "check_api version failed"); goto err_aq; @@ -1279,6 +1240,8 @@ i40evf_uninit_vf(struct rte_eth_dev *dev) i40evf_dev_close(dev); rte_free(vf->vf_res); vf->vf_res = NULL; + rte_free(vf->aq_resp); + vf->aq_resp = NULL; return 0; } -- 2.4.0 ^ permalink raw reply [flat|nested] 7+ messages in thread
* [dpdk-dev] [PATCH v2 2/2] i40evf: support interrupt based pf reset request 2016-01-27 1:46 [dpdk-dev] [PATCH v2 0/2] i40evf: support interrupt based pf reset request Jingjing Wu 2016-01-27 1:46 ` [dpdk-dev] [PATCH v2 1/2] i40evf: allocate virtchnl cmd buffer for each vf Jingjing Wu @ 2016-01-27 1:46 ` Jingjing Wu 1 sibling, 0 replies; 7+ messages in thread From: Jingjing Wu @ 2016-01-27 1:46 UTC (permalink / raw) To: dev Interrupt based request of PF reset from PF is supported by enabling the adminq event process in VF driver. Users can register a callback for this interrupt event to get informed, when a PF reset request detected like: rte_eth_dev_callback_register(portid, RTE_ETH_EVENT_INTR_RESET, reset_event_callback, arg); Signed-off-by: Jingjing Wu <jingjing.wu@intel.com> --- doc/guides/rel_notes/release_2_3.rst | 1 + drivers/net/i40e/i40e_ethdev_vf.c | 274 +++++++++++++++++++++++++++++++---- lib/librte_ether/rte_ethdev.h | 1 + 3 files changed, 246 insertions(+), 30 deletions(-) diff --git a/doc/guides/rel_notes/release_2_3.rst b/doc/guides/rel_notes/release_2_3.rst index 99de186..73d5f76 100644 --- a/doc/guides/rel_notes/release_2_3.rst +++ b/doc/guides/rel_notes/release_2_3.rst @@ -4,6 +4,7 @@ DPDK Release 2.3 New Features ------------ +* **Added pf reset event reported in i40e vf PMD driver. Resolved Issues --------------- diff --git a/drivers/net/i40e/i40e_ethdev_vf.c b/drivers/net/i40e/i40e_ethdev_vf.c index 64e6957..1ffe64e 100644 --- a/drivers/net/i40e/i40e_ethdev_vf.c +++ b/drivers/net/i40e/i40e_ethdev_vf.c @@ -74,8 +74,6 @@ #define I40EVF_BUSY_WAIT_DELAY 10 #define I40EVF_BUSY_WAIT_COUNT 50 #define MAX_RESET_WAIT_CNT 20 -/*ITR index for NOITR*/ -#define I40E_QINT_RQCTL_MSIX_INDX_NOITR 3 struct i40evf_arq_msg_info { enum i40e_virtchnl_ops ops; @@ -151,6 +149,9 @@ static int i40evf_dev_rx_queue_intr_enable(struct rte_eth_dev *dev, uint16_t queue_id); static int i40evf_dev_rx_queue_intr_disable(struct rte_eth_dev *dev, uint16_t queue_id); +static void i40evf_handle_pf_event(__rte_unused struct rte_eth_dev *dev, + uint8_t *msg, + uint16_t msglen); /* Default hash key buffer for RSS */ static uint32_t rss_key_default[I40E_VFQF_HKEY_MAX_INDEX + 1]; @@ -357,20 +358,42 @@ i40evf_execute_vf_cmd(struct rte_eth_dev *dev, struct vf_cmd_info *args) return err; } - do { - /* Delay some time first */ - rte_delay_ms(ASQ_DELAY_MS); - ret = i40evf_read_pfmsg(dev, &info); - if (ret == I40EVF_MSG_CMD) { - err = 0; - break; - } else if (ret == I40EVF_MSG_ERR) { - err = -1; - break; - } - /* If don't read msg or read sys event, continue */ - } while (i++ < MAX_TRY_TIMES); - _clear_cmd(vf); + switch (args->ops) { + case I40E_VIRTCHNL_OP_RESET_VF: + /*no need to process in this function */ + break; + case I40E_VIRTCHNL_OP_VERSION: + case I40E_VIRTCHNL_OP_GET_VF_RESOURCES: + /* for init adminq commands, need to poll the response */ + do { + /* Delay some time first */ + rte_delay_ms(ASQ_DELAY_MS); + ret = i40evf_read_pfmsg(dev, &info); + if (ret == I40EVF_MSG_CMD) { + err = 0; + break; + } else if (ret == I40EVF_MSG_ERR) { + err = -1; + break; + } + /* If don't read msg or read sys event, continue */ + } while (i++ < MAX_TRY_TIMES); + _clear_cmd(vf); + break; + + default: + /* for other adminq in running time, waiting the cmd done flag */ + do { + /* Delay some time first */ + rte_delay_ms(ASQ_DELAY_MS); + if (vf->pend_cmd == I40E_VIRTCHNL_OP_UNKNOWN) { + err = 0; + break; + } + /* If don't read msg or read sys event, continue */ + } while (i++ < MAX_TRY_TIMES); + break; + } return (err | vf->cmd_retval); } @@ -719,7 +742,7 @@ i40evf_config_irq_map(struct rte_eth_dev *dev) map_info = (struct i40e_virtchnl_irq_map_info *)cmd_buffer; map_info->num_vectors = 1; - map_info->vecmap[0].rxitr_idx = I40E_QINT_RQCTL_MSIX_INDX_NOITR; + map_info->vecmap[0].rxitr_idx = I40E_ITR_INDEX_DEFAULT; map_info->vecmap[0].vsi_id = vf->vsi_res->vsi_id; /* Alway use default dynamic MSIX interrupt */ map_info->vecmap[0].vector_id = vector_id; @@ -1093,6 +1116,38 @@ i40evf_dev_atomic_write_link_status(struct rte_eth_dev *dev, return 0; } +/* Disable IRQ0 */ +static inline void +i40evf_disable_irq0(struct i40e_hw *hw) +{ + /* Disable all interrupt types */ + I40E_WRITE_REG(hw, I40E_VFINT_ICR0_ENA1, 0); + I40E_WRITE_REG(hw, I40E_VFINT_DYN_CTL01, + I40E_VFINT_DYN_CTL01_ITR_INDX_MASK); + I40EVF_WRITE_FLUSH(hw); +} + +/* Enable IRQ0 */ +static inline void +i40evf_enable_irq0(struct i40e_hw *hw) +{ + /* Enable admin queue interrupt trigger */ + uint32_t val; + + i40evf_disable_irq0(hw); + val = I40E_READ_REG(hw, I40E_VFINT_ICR0_ENA1); + val |= I40E_VFINT_ICR0_ENA1_ADMINQ_MASK | + I40E_VFINT_ICR0_ENA1_LINK_STAT_CHANGE_MASK; + I40E_WRITE_REG(hw, I40E_VFINT_ICR0_ENA1, val); + + I40E_WRITE_REG(hw, I40E_VFINT_DYN_CTL01, + I40E_VFINT_DYN_CTL01_INTENA_MASK | + I40E_VFINT_DYN_CTL01_CLEARPBA_MASK | + I40E_VFINT_DYN_CTL01_ITR_INDX_MASK); + + I40EVF_WRITE_FLUSH(hw); +} + static int i40evf_reset_vf(struct i40e_hw *hw) { @@ -1137,6 +1192,8 @@ i40evf_init_vf(struct rte_eth_dev *dev) int i, err, bufsz; struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private); struct i40e_vf *vf = I40EVF_DEV_PRIVATE_TO_VF(dev->data->dev_private); + uint16_t interval = + i40e_calc_itr_interval(I40E_QUEUE_ITR_INTERVAL_MAX); vf->adapter = I40E_DEV_PRIVATE_TO_ADAPTER(dev->data->dev_private); vf->dev_data = dev->data; @@ -1218,6 +1275,15 @@ i40evf_init_vf(struct rte_eth_dev *dev) ether_addr_copy((struct ether_addr *)vf->vsi_res->default_mac_addr, (struct ether_addr *)hw->mac.addr); + /* If the PF host is not DPDK, set the interval of ITR0 to max*/ + if (vf->version_major != I40E_DPDK_VERSION_MAJOR) { + I40E_WRITE_REG(hw, I40E_VFINT_DYN_CTL01, + (I40E_ITR_INDEX_DEFAULT << + I40E_VFINT_DYN_CTL0_ITR_INDX_SHIFT) | + (interval << + I40E_VFINT_DYN_CTL0_INTERVAL_SHIFT)); + } + return 0; err_alloc: @@ -1246,11 +1312,142 @@ i40evf_uninit_vf(struct rte_eth_dev *dev) return 0; } +static void +i40evf_handle_pf_event(__rte_unused struct rte_eth_dev *dev, + uint8_t *msg, + __rte_unused uint16_t msglen) +{ + struct i40e_virtchnl_pf_event *pf_msg = + (struct i40e_virtchnl_pf_event *)msg; + + switch (pf_msg->event) { + case I40E_VIRTCHNL_EVENT_RESET_IMPENDING: + PMD_DRV_LOG(DEBUG, "VIRTCHNL_EVENT_RESET_IMPENDING event\n"); + _rte_eth_dev_callback_process(dev, RTE_ETH_EVENT_INTR_RESET); + break; + case I40E_VIRTCHNL_EVENT_LINK_CHANGE: + PMD_DRV_LOG(DEBUG, "VIRTCHNL_EVENT_LINK_CHANGE event\n"); + break; + case I40E_VIRTCHNL_EVENT_PF_DRIVER_CLOSE: + PMD_DRV_LOG(DEBUG, "VIRTCHNL_EVENT_PF_DRIVER_CLOSE event\n"); + break; + default: + PMD_DRV_LOG(ERR, " unknown event received %u", pf_msg->event); + break; + } +} + +static void +i40evf_handle_aq_msg(struct rte_eth_dev *dev) +{ + struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private); + struct i40e_vf *vf = I40EVF_DEV_PRIVATE_TO_VF(dev->data->dev_private); + struct i40e_arq_event_info info; + struct i40e_virtchnl_msg *v_msg; + uint16_t pending, opcode; + int ret; + + info.buf_len = I40E_AQ_BUF_SZ; + if (!vf->aq_resp) { + PMD_DRV_LOG(ERR, "Buffer for adminq resp should not be NULL"); + return; + } + info.msg_buf = vf->aq_resp; + v_msg = (struct i40e_virtchnl_msg *)&info.desc; + + pending = 1; + while (pending) { + ret = i40e_clean_arq_element(hw, &info, &pending); + + if (ret != I40E_SUCCESS) { + PMD_DRV_LOG(INFO, "Failed to read msg from AdminQ," + "ret: %d", ret); + break; + } + opcode = rte_le_to_cpu_16(info.desc.opcode); + + switch (opcode) { + case i40e_aqc_opc_send_msg_to_vf: + if (v_msg->v_opcode == I40E_VIRTCHNL_OP_EVENT) + /* process event*/ + i40evf_handle_pf_event(dev, info.msg_buf, + info.msg_len); + else { + /* read message and it's expected one */ + if (v_msg->v_opcode == vf->pend_cmd) { + vf->cmd_retval = v_msg->v_retval; + /* prevent compiler reordering */ + rte_compiler_barrier(); + _clear_cmd(vf); + } else + PMD_DRV_LOG(ERR, "command mismatch," + "expect %u, get %u", + vf->pend_cmd, v_msg->v_opcode); + PMD_DRV_LOG(DEBUG, "adminq response is received," + " opcode = %d\n", v_msg->v_opcode); + } + break; + default: + PMD_DRV_LOG(ERR, "Request %u is not supported yet", + opcode); + break; + } + } +} + +/** + * Interrupt handler triggered by NIC for handling + * specific interrupt. Only adminq interrupt is processed in VF. + * + * @param handle + * Pointer to interrupt handle. + * @param param + * The address of parameter (struct rte_eth_dev *) regsitered before. + * + * @return + * void + */ +static void +i40evf_dev_interrupt_handler(__rte_unused struct rte_intr_handle *handle, + void *param) +{ + struct rte_eth_dev *dev = (struct rte_eth_dev *)param; + struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private); + uint32_t icr0; + + i40evf_disable_irq0(hw); + + /* read out interrupt causes */ + icr0 = I40E_READ_REG(hw, I40E_VFINT_ICR01); + + /* No interrupt event indicated */ + if (!(icr0 & I40E_VFINT_ICR01_INTEVENT_MASK)) { + PMD_DRV_LOG(DEBUG, "No interrupt event, nothing to do\n"); + goto done; + } + + if (icr0 & I40E_VFINT_ICR01_ADMINQ_MASK) { + PMD_DRV_LOG(DEBUG, "ICR01_ADMINQ is reported\n"); + i40evf_handle_aq_msg(dev); + } + + /* Link Status Change interrupt */ + if (icr0 & I40E_VFINT_ICR01_LINK_STAT_CHANGE_MASK) + PMD_DRV_LOG(DEBUG, "LINK_STAT_CHANGE is reported," + " do nothing\n"); + +done: + i40evf_enable_irq0(hw); + rte_intr_enable(&(dev->pci_dev->intr_handle)); +} + + static int i40evf_dev_init(struct rte_eth_dev *eth_dev) { struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(\ eth_dev->data->dev_private); + struct rte_pci_device *pci_dev = eth_dev->pci_dev; PMD_INIT_FUNC_TRACE(); @@ -1285,6 +1482,16 @@ i40evf_dev_init(struct rte_eth_dev *eth_dev) return -1; } + /* register callback func to eal lib */ + rte_intr_callback_register(&(pci_dev->intr_handle), + i40evf_dev_interrupt_handler, (void *)eth_dev); + + /* configure and enable device interrupt */ + i40evf_enable_irq0(hw); + /* intr is enabled in i40evf_enable_queues_intr when dev_start */ + + /* enable uio intr after callback register */ + rte_intr_enable(&(pci_dev->intr_handle)); /* copy mac addr */ eth_dev->data->mac_addrs = rte_zmalloc("i40evf_mac", ETHER_ADDR_LEN, 0); @@ -1662,7 +1869,8 @@ i40evf_enable_queues_intr(struct rte_eth_dev *dev) I40E_WRITE_REG(hw, I40E_VFINT_DYN_CTL01, I40E_VFINT_DYN_CTL01_INTENA_MASK | - I40E_VFINT_DYN_CTL01_CLEARPBA_MASK); + I40E_VFINT_DYN_CTL01_CLEARPBA_MASK | + I40E_VFINT_DYN_CTL01_ITR_INDX_MASK); I40EVF_WRITE_FLUSH(hw); return; } @@ -1673,11 +1881,10 @@ i40evf_enable_queues_intr(struct rte_eth_dev *dev) I40E_VFINT_DYN_CTLN1(I40EVF_VSI_DEFAULT_MSIX_INTR - 1), I40E_VFINT_DYN_CTLN1_INTENA_MASK | I40E_VFINT_DYN_CTLN_CLEARPBA_MASK); - else - /* To support Linux PF host */ - I40E_WRITE_REG(hw, I40E_VFINT_DYN_CTL01, - I40E_VFINT_DYN_CTL01_INTENA_MASK | - I40E_VFINT_DYN_CTL01_CLEARPBA_MASK); + /* If host driver is kernel driver, do nothing. + * Interrupt 0 is used for rx packets, but don't set I40E_VFINT_DYN_CTL01, + * because it is already done in i40evf_enable_irq0. + */ I40EVF_WRITE_FLUSH(hw); } @@ -1690,7 +1897,8 @@ i40evf_disable_queues_intr(struct rte_eth_dev *dev) struct rte_intr_handle *intr_handle = &dev->pci_dev->intr_handle; if (!rte_intr_allow_others(intr_handle)) { - I40E_WRITE_REG(hw, I40E_VFINT_DYN_CTL01, 0); + I40E_WRITE_REG(hw, I40E_VFINT_DYN_CTL01, + I40E_VFINT_DYN_CTL01_ITR_INDX_MASK); I40EVF_WRITE_FLUSH(hw); return; } @@ -1700,8 +1908,10 @@ i40evf_disable_queues_intr(struct rte_eth_dev *dev) I40E_VFINT_DYN_CTLN1(I40EVF_VSI_DEFAULT_MSIX_INTR - 1), 0); - else - I40E_WRITE_REG(hw, I40E_VFINT_DYN_CTL01, 0); + /* If host driver is kernel driver, do nothing. + * Interrupt 0 is used for rx packets, but don't zero I40E_VFINT_DYN_CTL01, + * because interrupt 0 is also used for adminq processing. + */ I40EVF_WRITE_FLUSH(hw); } @@ -1825,10 +2035,6 @@ i40evf_dev_start(struct rte_eth_dev *dev) goto err_mac; } - /* vf don't allow intr except for rxq intr */ - if (dev->data->dev_conf.intr_conf.rxq != 0) - rte_intr_enable(intr_handle); - i40evf_enable_queues_intr(dev); return 0; @@ -2020,12 +2226,20 @@ static void i40evf_dev_close(struct rte_eth_dev *dev) { struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private); + struct rte_pci_device *pci_dev = dev->pci_dev; i40evf_dev_stop(dev); hw->adapter_stopped = 1; i40e_dev_free_queues(dev); i40evf_reset_vf(hw); i40e_shutdown_adminq(hw); + /* disable uio intr before callback unregister */ + rte_intr_disable(&(pci_dev->intr_handle)); + + /* unregister callback func from eal lib */ + rte_intr_callback_unregister(&(pci_dev->intr_handle), + i40evf_dev_interrupt_handler, (void *)dev); + i40evf_disable_irq0(hw); } static int diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h index bada8ad..1be1783 100644 --- a/lib/librte_ether/rte_ethdev.h +++ b/lib/librte_ether/rte_ethdev.h @@ -2666,6 +2666,7 @@ rte_eth_tx_burst(uint8_t port_id, uint16_t queue_id, enum rte_eth_event_type { RTE_ETH_EVENT_UNKNOWN, /**< unknown event type */ RTE_ETH_EVENT_INTR_LSC, /**< lsc interrupt event */ + RTE_ETH_EVENT_INTR_RESET, /**< reset interrupt event */ RTE_ETH_EVENT_MAX /**< max value of this enum */ }; -- 2.4.0 ^ permalink raw reply [flat|nested] 7+ messages in thread
* [dpdk-dev] [PATCH 0/2] i40evf: support interrupt based pf reset request @ 2016-01-13 12:31 Jingjing Wu 2016-01-27 1:49 ` [dpdk-dev] [PATCH v2 " Jingjing Wu 0 siblings, 1 reply; 7+ messages in thread From: Jingjing Wu @ 2016-01-13 12:31 UTC (permalink / raw) To: dev If DPDK is used on VF while the host is using Linux Kernel driver as PF driver on FVL NIC, some setting on PF will trigger VF reset. DPDK VF need to know the event. This patch set makes the interrupt based request of PF reset from PF supported by enabling the adminq event process in VF driver. Users can register a callback for this interrupt event to get informed, when a PF reset request detected like: rte_eth_dev_callback_register(portid, RTE_ETH_EVENT_INTR_RESET, reset_event_callback, arg); Jingjing Wu (2): i40evf: allocate virtchnl cmd buffer for each vf i40evf: support interrupt based pf reset request drivers/net/i40e/i40e_ethdev.h | 2 + drivers/net/i40e/i40e_ethdev_vf.c | 425 +++++++++++++++++++++++++++----------- lib/librte_ether/rte_ethdev.h | 1 + 3 files changed, 304 insertions(+), 124 deletions(-) -- 2.4.0 ^ permalink raw reply [flat|nested] 7+ messages in thread
* [dpdk-dev] [PATCH v2 0/2] i40evf: support interrupt based pf reset request 2016-01-13 12:31 [dpdk-dev] [PATCH 0/2] " Jingjing Wu @ 2016-01-27 1:49 ` Jingjing Wu 2016-01-27 1:49 ` [dpdk-dev] [PATCH v2 1/2] i40evf: allocate virtchnl cmd buffer for each vf Jingjing Wu 0 siblings, 1 reply; 7+ messages in thread From: Jingjing Wu @ 2016-01-27 1:49 UTC (permalink / raw) To: dev v2 changes: remove the change on vf reset status checking add pf event report support in release note If DPDK is used on VF while the host is using Linux Kernel driver as PF driver on FVL NIC, some setting on PF will trigger VF reset. DPDK VF need to know the event. This patch set makes the interrupt based request of PF reset from PF supported by enabling the adminq event process in VF driver. Users can register a callback for this interrupt event to get informed, when a PF reset request detected like: rte_eth_dev_callback_register(portid, RTE_ETH_EVENT_INTR_RESET, reset_event_callback, arg); Jingjing Wu (2): i40evf: allocate virtchnl cmd buffer for each vf i40evf: support interrupt based pf reset request doc/guides/rel_notes/release_2_3.rst | 1 + drivers/net/i40e/i40e_ethdev.h | 2 + drivers/net/i40e/i40e_ethdev_vf.c | 423 +++++++++++++++++++++++++---------- lib/librte_ether/rte_ethdev.h | 1 + 4 files changed, 304 insertions(+), 123 deletions(-) -- 2.4.0 ^ permalink raw reply [flat|nested] 7+ messages in thread
* [dpdk-dev] [PATCH v2 1/2] i40evf: allocate virtchnl cmd buffer for each vf 2016-01-27 1:49 ` [dpdk-dev] [PATCH v2 " Jingjing Wu @ 2016-01-27 1:49 ` Jingjing Wu 2016-01-29 7:28 ` Tao, Zhe 2016-02-22 7:26 ` Zhang, Helin 0 siblings, 2 replies; 7+ messages in thread From: Jingjing Wu @ 2016-01-27 1:49 UTC (permalink / raw) To: dev Currently, i40evf PMD uses a global static buffer to send virtchnl command to host driver. It is shared by multi VFs. This patch changed to allocate virtchnl cmd buffer for each VF. Signed-off-by: Jingjing Wu <jingjing.wu@intel.com> --- drivers/net/i40e/i40e_ethdev.h | 2 + drivers/net/i40e/i40e_ethdev_vf.c | 181 +++++++++++++++----------------------- 2 files changed, 74 insertions(+), 109 deletions(-) diff --git a/drivers/net/i40e/i40e_ethdev.h b/drivers/net/i40e/i40e_ethdev.h index 1f9792b..93122ad 100644 --- a/drivers/net/i40e/i40e_ethdev.h +++ b/drivers/net/i40e/i40e_ethdev.h @@ -494,7 +494,9 @@ struct i40e_vf { bool link_up; bool vf_reset; volatile uint32_t pend_cmd; /* pending command not finished yet */ + uint32_t cmd_retval; /* return value of the cmd response from PF */ u16 pend_msg; /* flags indicates events from pf not handled yet */ + uint8_t *aq_resp; /* buffer to store the adminq response from PF */ /* VSI info */ struct i40e_virtchnl_vf_resource *vf_res; /* All VSIs */ diff --git a/drivers/net/i40e/i40e_ethdev_vf.c b/drivers/net/i40e/i40e_ethdev_vf.c index 14d2a50..64e6957 100644 --- a/drivers/net/i40e/i40e_ethdev_vf.c +++ b/drivers/net/i40e/i40e_ethdev_vf.c @@ -103,9 +103,6 @@ enum i40evf_aq_result { I40EVF_MSG_CMD, /* Read async command result */ }; -/* A share buffer to store the command result from PF driver */ -static uint8_t cmd_result_buffer[I40E_AQ_BUF_SZ]; - static int i40evf_dev_configure(struct rte_eth_dev *dev); static int i40evf_dev_start(struct rte_eth_dev *dev); static void i40evf_dev_stop(struct rte_eth_dev *dev); @@ -237,31 +234,39 @@ i40evf_set_mac_type(struct i40e_hw *hw) } /* - * Parse admin queue message. - * - * return value: - * < 0: meet error - * 0: read sys msg - * > 0: read cmd result + * Read data in admin queue to get msg from pf driver */ static enum i40evf_aq_result -i40evf_parse_pfmsg(struct i40e_vf *vf, - struct i40e_arq_event_info *event, - struct i40evf_arq_msg_info *data) +i40evf_read_pfmsg(struct rte_eth_dev *dev, struct i40evf_arq_msg_info *data) { - enum i40e_virtchnl_ops opcode = (enum i40e_virtchnl_ops)\ - rte_le_to_cpu_32(event->desc.cookie_high); - enum i40e_status_code retval = (enum i40e_status_code)\ - rte_le_to_cpu_32(event->desc.cookie_low); - enum i40evf_aq_result ret = I40EVF_MSG_CMD; + struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private); + struct i40e_vf *vf = I40EVF_DEV_PRIVATE_TO_VF(dev->data->dev_private); + struct i40e_arq_event_info event; + enum i40e_virtchnl_ops opcode; + enum i40e_status_code retval; + int ret; + enum i40evf_aq_result result = I40EVF_MSG_NON; + event.buf_len = data->buf_len; + event.msg_buf = data->msg; + ret = i40e_clean_arq_element(hw, &event, NULL); + /* Can't read any msg from adminQ */ + if (ret) { + if (ret == I40E_ERR_ADMIN_QUEUE_NO_WORK) + result = I40EVF_MSG_NON; + else + result = I40EVF_MSG_ERR; + return result; + } + + opcode = (enum i40e_virtchnl_ops)rte_le_to_cpu_32(event.desc.cookie_high); + retval = (enum i40e_status_code)rte_le_to_cpu_32(event.desc.cookie_low); /* pf sys event */ if (opcode == I40E_VIRTCHNL_OP_EVENT) { struct i40e_virtchnl_pf_event *vpe = - (struct i40e_virtchnl_pf_event *)event->msg_buf; + (struct i40e_virtchnl_pf_event *)event.msg_buf; - /* Initialize ret to sys event */ - ret = I40EVF_MSG_SYS; + result = I40EVF_MSG_SYS; switch (vpe->event) { case I40E_VIRTCHNL_EVENT_LINK_CHANGE: vf->link_up = @@ -286,74 +291,17 @@ i40evf_parse_pfmsg(struct i40e_vf *vf, } } else { /* async reply msg on command issued by vf previously */ - ret = I40EVF_MSG_CMD; + result = I40EVF_MSG_CMD; /* Actual data length read from PF */ - data->msg_len = event->msg_len; + data->msg_len = event.msg_len; } - /* fill the ops and result to notify VF */ + data->result = retval; data->ops = opcode; - return ret; -} - -/* - * Read data in admin queue to get msg from pf driver - */ -static enum i40evf_aq_result -i40evf_read_pfmsg(struct rte_eth_dev *dev, struct i40evf_arq_msg_info *data) -{ - struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private); - struct i40e_vf *vf = I40EVF_DEV_PRIVATE_TO_VF(dev->data->dev_private); - struct i40e_arq_event_info event; - int ret; - enum i40evf_aq_result result = I40EVF_MSG_NON; - - event.buf_len = data->buf_len; - event.msg_buf = data->msg; - ret = i40e_clean_arq_element(hw, &event, NULL); - /* Can't read any msg from adminQ */ - if (ret) { - if (ret == I40E_ERR_ADMIN_QUEUE_NO_WORK) - result = I40EVF_MSG_NON; - else - result = I40EVF_MSG_ERR; - return result; - } - - /* Parse the event */ - result = i40evf_parse_pfmsg(vf, &event, data); - return result; } -/* - * Polling read until command result return from pf driver or meet error. - */ -static int -i40evf_wait_cmd_done(struct rte_eth_dev *dev, - struct i40evf_arq_msg_info *data) -{ - int i = 0; - enum i40evf_aq_result ret; - -#define MAX_TRY_TIMES 20 -#define ASQ_DELAY_MS 100 - do { - /* Delay some time first */ - rte_delay_ms(ASQ_DELAY_MS); - ret = i40evf_read_pfmsg(dev, data); - if (ret == I40EVF_MSG_CMD) - return 0; - else if (ret == I40EVF_MSG_ERR) - return -1; - - /* If don't read msg or read sys event, continue */ - } while(i++ < MAX_TRY_TIMES); - - return -1; -} - /** * clear current command. Only call in case execute * _atomic_set_cmd successfully. @@ -380,13 +328,18 @@ _atomic_set_cmd(struct i40e_vf *vf, enum i40e_virtchnl_ops ops) return !ret; } +#define MAX_TRY_TIMES 20 +#define ASQ_DELAY_MS 100 + static int i40evf_execute_vf_cmd(struct rte_eth_dev *dev, struct vf_cmd_info *args) { struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private); struct i40e_vf *vf = I40EVF_DEV_PRIVATE_TO_VF(dev->data->dev_private); - int err = -1; struct i40evf_arq_msg_info info; + enum i40evf_aq_result ret; + int err = -1; + int i = 0; if (_atomic_set_cmd(vf, args->ops)) return -1; @@ -404,19 +357,22 @@ i40evf_execute_vf_cmd(struct rte_eth_dev *dev, struct vf_cmd_info *args) return err; } - err = i40evf_wait_cmd_done(dev, &info); - /* read message and it's expected one */ - if (!err && args->ops == info.ops) - _clear_cmd(vf); - else if (err) { - PMD_DRV_LOG(ERR, "Failed to read message from AdminQ"); - _clear_cmd(vf); - } - else if (args->ops != info.ops) - PMD_DRV_LOG(ERR, "command mismatch, expect %u, get %u", - args->ops, info.ops); + do { + /* Delay some time first */ + rte_delay_ms(ASQ_DELAY_MS); + ret = i40evf_read_pfmsg(dev, &info); + if (ret == I40EVF_MSG_CMD) { + err = 0; + break; + } else if (ret == I40EVF_MSG_ERR) { + err = -1; + break; + } + /* If don't read msg or read sys event, continue */ + } while (i++ < MAX_TRY_TIMES); + _clear_cmd(vf); - return (err | info.result); + return (err | vf->cmd_retval); } /* @@ -436,7 +392,7 @@ i40evf_check_api_version(struct rte_eth_dev *dev) args.ops = I40E_VIRTCHNL_OP_VERSION; args.in_args = (uint8_t *)&version; args.in_args_size = sizeof(version); - args.out_buffer = cmd_result_buffer; + args.out_buffer = vf->aq_resp; args.out_size = I40E_AQ_BUF_SZ; err = i40evf_execute_vf_cmd(dev, &args); @@ -474,7 +430,7 @@ i40evf_get_vf_resource(struct rte_eth_dev *dev) uint32_t caps, len; args.ops = I40E_VIRTCHNL_OP_GET_VF_RESOURCES; - args.out_buffer = cmd_result_buffer; + args.out_buffer = vf->aq_resp; args.out_size = I40E_AQ_BUF_SZ; if (PF_IS_V11(vf)) { caps = I40E_VIRTCHNL_VF_OFFLOAD_L2 | @@ -527,7 +483,7 @@ i40evf_config_promisc(struct rte_eth_dev *dev, args.ops = I40E_VIRTCHNL_OP_CONFIG_PROMISCUOUS_MODE; args.in_args = (uint8_t *)&promisc; args.in_args_size = sizeof(promisc); - args.out_buffer = cmd_result_buffer; + args.out_buffer = vf->aq_resp; args.out_size = I40E_AQ_BUF_SZ; err = i40evf_execute_vf_cmd(dev, &args); @@ -554,7 +510,7 @@ i40evf_config_vlan_offload(struct rte_eth_dev *dev, args.ops = (enum i40e_virtchnl_ops)I40E_VIRTCHNL_OP_CFG_VLAN_OFFLOAD; args.in_args = (uint8_t *)&offload; args.in_args_size = sizeof(offload); - args.out_buffer = cmd_result_buffer; + args.out_buffer = vf->aq_resp; args.out_size = I40E_AQ_BUF_SZ; err = i40evf_execute_vf_cmd(dev, &args); @@ -585,7 +541,7 @@ i40evf_config_vlan_pvid(struct rte_eth_dev *dev, args.ops = (enum i40e_virtchnl_ops)I40E_VIRTCHNL_OP_CFG_VLAN_PVID; args.in_args = (uint8_t *)&tpid_info; args.in_args_size = sizeof(tpid_info); - args.out_buffer = cmd_result_buffer; + args.out_buffer = vf->aq_resp; args.out_size = I40E_AQ_BUF_SZ; err = i40evf_execute_vf_cmd(dev, &args); @@ -664,7 +620,7 @@ i40evf_configure_vsi_queues(struct rte_eth_dev *dev) args.ops = I40E_VIRTCHNL_OP_CONFIG_VSI_QUEUES; args.in_args = (uint8_t *)vc_vqci; args.in_args_size = size; - args.out_buffer = cmd_result_buffer; + args.out_buffer = vf->aq_resp; args.out_size = I40E_AQ_BUF_SZ; ret = i40evf_execute_vf_cmd(dev, &args); if (ret) @@ -717,7 +673,7 @@ i40evf_configure_vsi_queues_ext(struct rte_eth_dev *dev) (enum i40e_virtchnl_ops)I40E_VIRTCHNL_OP_CONFIG_VSI_QUEUES_EXT; args.in_args = (uint8_t *)vc_vqcei; args.in_args_size = size; - args.out_buffer = cmd_result_buffer; + args.out_buffer = vf->aq_resp; args.out_size = I40E_AQ_BUF_SZ; ret = i40evf_execute_vf_cmd(dev, &args); if (ret) @@ -779,7 +735,7 @@ i40evf_config_irq_map(struct rte_eth_dev *dev) args.ops = I40E_VIRTCHNL_OP_CONFIG_IRQ_MAP; args.in_args = (u8 *)cmd_buffer; args.in_args_size = sizeof(cmd_buffer); - args.out_buffer = cmd_result_buffer; + args.out_buffer = vf->aq_resp; args.out_size = I40E_AQ_BUF_SZ; err = i40evf_execute_vf_cmd(dev, &args); if (err) @@ -810,7 +766,7 @@ i40evf_switch_queue(struct rte_eth_dev *dev, bool isrx, uint16_t qid, args.ops = I40E_VIRTCHNL_OP_DISABLE_QUEUES; args.in_args = (u8 *)&queue_select; args.in_args_size = sizeof(queue_select); - args.out_buffer = cmd_result_buffer; + args.out_buffer = vf->aq_resp; args.out_size = I40E_AQ_BUF_SZ; err = i40evf_execute_vf_cmd(dev, &args); if (err) @@ -902,7 +858,7 @@ i40evf_add_mac_addr(struct rte_eth_dev *dev, struct ether_addr *addr) args.ops = I40E_VIRTCHNL_OP_ADD_ETHER_ADDRESS; args.in_args = cmd_buffer; args.in_args_size = sizeof(cmd_buffer); - args.out_buffer = cmd_result_buffer; + args.out_buffer = vf->aq_resp; args.out_size = I40E_AQ_BUF_SZ; err = i40evf_execute_vf_cmd(dev, &args); if (err) @@ -939,7 +895,7 @@ i40evf_del_mac_addr(struct rte_eth_dev *dev, struct ether_addr *addr) args.ops = I40E_VIRTCHNL_OP_DEL_ETHER_ADDRESS; args.in_args = cmd_buffer; args.in_args_size = sizeof(cmd_buffer); - args.out_buffer = cmd_result_buffer; + args.out_buffer = vf->aq_resp; args.out_size = I40E_AQ_BUF_SZ; err = i40evf_execute_vf_cmd(dev, &args); if (err) @@ -962,7 +918,7 @@ i40evf_update_stats(struct rte_eth_dev *dev, struct i40e_eth_stats **pstats) args.ops = I40E_VIRTCHNL_OP_GET_STATS; args.in_args = (u8 *)&q_stats; args.in_args_size = sizeof(q_stats); - args.out_buffer = cmd_result_buffer; + args.out_buffer = vf->aq_resp; args.out_size = I40E_AQ_BUF_SZ; err = i40evf_execute_vf_cmd(dev, &args); @@ -1056,7 +1012,7 @@ i40evf_add_vlan(struct rte_eth_dev *dev, uint16_t vlanid) args.ops = I40E_VIRTCHNL_OP_ADD_VLAN; args.in_args = (u8 *)&cmd_buffer; args.in_args_size = sizeof(cmd_buffer); - args.out_buffer = cmd_result_buffer; + args.out_buffer = vf->aq_resp; args.out_size = I40E_AQ_BUF_SZ; err = i40evf_execute_vf_cmd(dev, &args); if (err) @@ -1083,7 +1039,7 @@ i40evf_del_vlan(struct rte_eth_dev *dev, uint16_t vlanid) args.ops = I40E_VIRTCHNL_OP_DEL_VLAN; args.in_args = (u8 *)&cmd_buffer; args.in_args_size = sizeof(cmd_buffer); - args.out_buffer = cmd_result_buffer; + args.out_buffer = vf->aq_resp; args.out_size = I40E_AQ_BUF_SZ; err = i40evf_execute_vf_cmd(dev, &args); if (err) @@ -1095,6 +1051,7 @@ i40evf_del_vlan(struct rte_eth_dev *dev, uint16_t vlanid) static int i40evf_get_link_status(struct rte_eth_dev *dev, struct rte_eth_link *link) { + struct i40e_vf *vf = I40EVF_DEV_PRIVATE_TO_VF(dev->data->dev_private); int err; struct vf_cmd_info args; struct rte_eth_link *new_link; @@ -1102,7 +1059,7 @@ i40evf_get_link_status(struct rte_eth_dev *dev, struct rte_eth_link *link) args.ops = (enum i40e_virtchnl_ops)I40E_VIRTCHNL_OP_GET_LINK_STAT; args.in_args = NULL; args.in_args_size = 0; - args.out_buffer = cmd_result_buffer; + args.out_buffer = vf->aq_resp; args.out_size = I40E_AQ_BUF_SZ; err = i40evf_execute_vf_cmd(dev, &args); if (err) { @@ -1196,7 +1153,6 @@ i40evf_init_vf(struct rte_eth_dev *dev) goto err; } - /* Reset VF and wait until it's complete */ if (i40evf_reset_vf(hw)) { PMD_INIT_LOG(ERR, "reset NIC failed"); @@ -1214,6 +1170,11 @@ i40evf_init_vf(struct rte_eth_dev *dev) PMD_INIT_LOG(ERR, "init_adminq failed"); return -1; } + vf->aq_resp = rte_zmalloc("vf_aq_resp", I40E_AQ_BUF_SZ, 0); + if (!vf->aq_resp) { + PMD_INIT_LOG(ERR, "unable to allocate vf_aq_resp memory"); + goto err_aq; + } if (i40evf_check_api_version(dev) != 0) { PMD_INIT_LOG(ERR, "check_api version failed"); goto err_aq; @@ -1279,6 +1240,8 @@ i40evf_uninit_vf(struct rte_eth_dev *dev) i40evf_dev_close(dev); rte_free(vf->vf_res); vf->vf_res = NULL; + rte_free(vf->aq_resp); + vf->aq_resp = NULL; return 0; } -- 2.4.0 ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [dpdk-dev] [PATCH v2 1/2] i40evf: allocate virtchnl cmd buffer for each vf 2016-01-27 1:49 ` [dpdk-dev] [PATCH v2 1/2] i40evf: allocate virtchnl cmd buffer for each vf Jingjing Wu @ 2016-01-29 7:28 ` Tao, Zhe 2016-02-14 2:22 ` Wu, Jingjing 2016-02-22 7:26 ` Zhang, Helin 1 sibling, 1 reply; 7+ messages in thread From: Tao, Zhe @ 2016-01-29 7:28 UTC (permalink / raw) To: Wu, Jingjing, dev > -----Original Message----- > From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Jingjing Wu > Sent: Wednesday, January 27, 2016 9:50 AM > To: dev@dpdk.org > Subject: [dpdk-dev] [PATCH v2 1/2] i40evf: allocate virtchnl cmd buffer for > each vf > > Currently, i40evf PMD uses a global static buffer to send virtchnl command to > host driver. It is shared by multi VFs. > This patch changed to allocate virtchnl cmd buffer for each VF. > > Signed-off-by: Jingjing Wu <jingjing.wu@intel.com> > --- > drivers/net/i40e/i40e_ethdev.h | 2 + > drivers/net/i40e/i40e_ethdev_vf.c | 181 +++++++++++++++------------------- > ---- > 2 files changed, 74 insertions(+), 109 deletions(-) > > diff --git a/drivers/net/i40e/i40e_ethdev.h > b/drivers/net/i40e/i40e_ethdev.h index 1f9792b..93122ad 100644 > --- a/drivers/net/i40e/i40e_ethdev.h > +++ b/drivers/net/i40e/i40e_ethdev.h > @@ -494,7 +494,9 @@ struct i40e_vf { > bool link_up; > bool vf_reset; > volatile uint32_t pend_cmd; /* pending command not finished yet */ > + uint32_t cmd_retval; /* return value of the cmd response from PF */ > u16 pend_msg; /* flags indicates events from pf not handled yet */ > + uint8_t *aq_resp; /* buffer to store the adminq response from PF */ > > /* VSI info */ > struct i40e_virtchnl_vf_resource *vf_res; /* All VSIs */ diff --git > a/drivers/net/i40e/i40e_ethdev_vf.c b/drivers/net/i40e/i40e_ethdev_vf.c > index 14d2a50..64e6957 100644 > --- a/drivers/net/i40e/i40e_ethdev_vf.c > +++ b/drivers/net/i40e/i40e_ethdev_vf.c > @@ -103,9 +103,6 @@ enum i40evf_aq_result { > I40EVF_MSG_CMD, /* Read async command result */ > }; > > -/* A share buffer to store the command result from PF driver */ -static > uint8_t cmd_result_buffer[I40E_AQ_BUF_SZ]; > - > static int i40evf_dev_configure(struct rte_eth_dev *dev); static int > i40evf_dev_start(struct rte_eth_dev *dev); static void > i40evf_dev_stop(struct rte_eth_dev *dev); @@ -237,31 +234,39 @@ > i40evf_set_mac_type(struct i40e_hw *hw) } > > /* > - * Parse admin queue message. > - * > - * return value: > - * < 0: meet error > - * 0: read sys msg > - * > 0: read cmd result > + * Read data in admin queue to get msg from pf driver > */ > static enum i40evf_aq_result > -i40evf_parse_pfmsg(struct i40e_vf *vf, > - struct i40e_arq_event_info *event, > - struct i40evf_arq_msg_info *data) > +i40evf_read_pfmsg(struct rte_eth_dev *dev, struct i40evf_arq_msg_info > +*data) > { > - enum i40e_virtchnl_ops opcode = (enum i40e_virtchnl_ops)\ > - rte_le_to_cpu_32(event->desc.cookie_high); > - enum i40e_status_code retval = (enum i40e_status_code)\ > - rte_le_to_cpu_32(event->desc.cookie_low); > - enum i40evf_aq_result ret = I40EVF_MSG_CMD; > + struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data- > >dev_private); > + struct i40e_vf *vf = I40EVF_DEV_PRIVATE_TO_VF(dev->data- > >dev_private); > + struct i40e_arq_event_info event; > + enum i40e_virtchnl_ops opcode; > + enum i40e_status_code retval; > + int ret; > + enum i40evf_aq_result result = I40EVF_MSG_NON; > > + event.buf_len = data->buf_len; > + event.msg_buf = data->msg; > + ret = i40e_clean_arq_element(hw, &event, NULL); > + /* Can't read any msg from adminQ */ > + if (ret) { > + if (ret == I40E_ERR_ADMIN_QUEUE_NO_WORK) > + result = I40EVF_MSG_NON; > + else > + result = I40EVF_MSG_ERR; > + return result; > + } > + > + opcode = (enum > i40e_virtchnl_ops)rte_le_to_cpu_32(event.desc.cookie_high); > + retval = (enum > +i40e_status_code)rte_le_to_cpu_32(event.desc.cookie_low); > /* pf sys event */ > if (opcode == I40E_VIRTCHNL_OP_EVENT) { > struct i40e_virtchnl_pf_event *vpe = > - (struct i40e_virtchnl_pf_event *)event->msg_buf; > + (struct i40e_virtchnl_pf_event *)event.msg_buf; > > - /* Initialize ret to sys event */ > - ret = I40EVF_MSG_SYS; > + result = I40EVF_MSG_SYS; > switch (vpe->event) { > case I40E_VIRTCHNL_EVENT_LINK_CHANGE: > vf->link_up = > @@ -286,74 +291,17 @@ i40evf_parse_pfmsg(struct i40e_vf *vf, > } > } else { > /* async reply msg on command issued by vf previously */ > - ret = I40EVF_MSG_CMD; > + result = I40EVF_MSG_CMD; > /* Actual data length read from PF */ > - data->msg_len = event->msg_len; > + data->msg_len = event.msg_len; > } > - /* fill the ops and result to notify VF */ > + > data->result = retval; > data->ops = opcode; > > - return ret; > -} > - > -/* > - * Read data in admin queue to get msg from pf driver > - */ > -static enum i40evf_aq_result > -i40evf_read_pfmsg(struct rte_eth_dev *dev, struct i40evf_arq_msg_info > *data) -{ > - struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data- > >dev_private); > - struct i40e_vf *vf = I40EVF_DEV_PRIVATE_TO_VF(dev->data- > >dev_private); > - struct i40e_arq_event_info event; > - int ret; > - enum i40evf_aq_result result = I40EVF_MSG_NON; > - > - event.buf_len = data->buf_len; > - event.msg_buf = data->msg; > - ret = i40e_clean_arq_element(hw, &event, NULL); > - /* Can't read any msg from adminQ */ > - if (ret) { > - if (ret == I40E_ERR_ADMIN_QUEUE_NO_WORK) > - result = I40EVF_MSG_NON; > - else > - result = I40EVF_MSG_ERR; > - return result; > - } > - > - /* Parse the event */ > - result = i40evf_parse_pfmsg(vf, &event, data); > - > return result; > } > > -/* > - * Polling read until command result return from pf driver or meet error. > - */ > -static int > -i40evf_wait_cmd_done(struct rte_eth_dev *dev, > - struct i40evf_arq_msg_info *data) > -{ > - int i = 0; > - enum i40evf_aq_result ret; > - > -#define MAX_TRY_TIMES 20 > -#define ASQ_DELAY_MS 100 > - do { > - /* Delay some time first */ > - rte_delay_ms(ASQ_DELAY_MS); > - ret = i40evf_read_pfmsg(dev, data); > - if (ret == I40EVF_MSG_CMD) > - return 0; > - else if (ret == I40EVF_MSG_ERR) > - return -1; > - > - /* If don't read msg or read sys event, continue */ > - } while(i++ < MAX_TRY_TIMES); > - > - return -1; > -} > - > /** > * clear current command. Only call in case execute > * _atomic_set_cmd successfully. > @@ -380,13 +328,18 @@ _atomic_set_cmd(struct i40e_vf *vf, enum > i40e_virtchnl_ops ops) > return !ret; > } > > +#define MAX_TRY_TIMES 20 > +#define ASQ_DELAY_MS 100 > + > static int > i40evf_execute_vf_cmd(struct rte_eth_dev *dev, struct vf_cmd_info *args) > { > struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data- > >dev_private); > struct i40e_vf *vf = I40EVF_DEV_PRIVATE_TO_VF(dev->data- > >dev_private); > - int err = -1; > struct i40evf_arq_msg_info info; > + enum i40evf_aq_result ret; > + int err = -1; > + int i = 0; > > if (_atomic_set_cmd(vf, args->ops)) > return -1; > @@ -404,19 +357,22 @@ i40evf_execute_vf_cmd(struct rte_eth_dev *dev, > struct vf_cmd_info *args) > return err; > } > > - err = i40evf_wait_cmd_done(dev, &info); > - /* read message and it's expected one */ > - if (!err && args->ops == info.ops) > - _clear_cmd(vf); > - else if (err) { > - PMD_DRV_LOG(ERR, "Failed to read message from > AdminQ"); > - _clear_cmd(vf); > - } > - else if (args->ops != info.ops) > - PMD_DRV_LOG(ERR, "command mismatch, expect %u, > get %u", > - args->ops, info.ops); > + do { > + /* Delay some time first */ > + rte_delay_ms(ASQ_DELAY_MS); > + ret = i40evf_read_pfmsg(dev, &info); > + if (ret == I40EVF_MSG_CMD) { > + err = 0; > + break; > + } else if (ret == I40EVF_MSG_ERR) { > + err = -1; > + break; > + } > + /* If don't read msg or read sys event, continue */ > + } while (i++ < MAX_TRY_TIMES); > + _clear_cmd(vf); > > - return (err | info.result); > + return (err | vf->cmd_retval); > } > Why combine the i40evf_parse_pfmsg and i40evf_read_pfmsg into one function i40evf_read_pfmsg? ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [dpdk-dev] [PATCH v2 1/2] i40evf: allocate virtchnl cmd buffer for each vf 2016-01-29 7:28 ` Tao, Zhe @ 2016-02-14 2:22 ` Wu, Jingjing 0 siblings, 0 replies; 7+ messages in thread From: Wu, Jingjing @ 2016-02-14 2:22 UTC (permalink / raw) To: Tao, Zhe, dev > -----Original Message----- > From: Tao, Zhe > Sent: Friday, January 29, 2016 3:28 PM > To: Wu, Jingjing; dev@dpdk.org > Subject: RE: [dpdk-dev] [PATCH v2 1/2] i40evf: allocate virtchnl cmd buffer > for each vf > > > > > -----Original Message----- > > From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Jingjing Wu > > Sent: Wednesday, January 27, 2016 9:50 AM > > To: dev@dpdk.org > > Subject: [dpdk-dev] [PATCH v2 1/2] i40evf: allocate virtchnl cmd > > buffer for each vf > > > > Currently, i40evf PMD uses a global static buffer to send virtchnl > > command to host driver. It is shared by multi VFs. > > This patch changed to allocate virtchnl cmd buffer for each VF. > > > > Signed-off-by: Jingjing Wu <jingjing.wu@intel.com> > > --- > > drivers/net/i40e/i40e_ethdev.h | 2 + > > drivers/net/i40e/i40e_ethdev_vf.c | 181 > > +++++++++++++++------------------- > > ---- > > 2 files changed, 74 insertions(+), 109 deletions(-) > > > > diff --git a/drivers/net/i40e/i40e_ethdev.h > > b/drivers/net/i40e/i40e_ethdev.h index 1f9792b..93122ad 100644 > > --- a/drivers/net/i40e/i40e_ethdev.h > > +++ b/drivers/net/i40e/i40e_ethdev.h > > @@ -494,7 +494,9 @@ struct i40e_vf { > > bool link_up; > > bool vf_reset; > > volatile uint32_t pend_cmd; /* pending command not finished yet */ > > + uint32_t cmd_retval; /* return value of the cmd response from PF */ > > u16 pend_msg; /* flags indicates events from pf not handled yet */ > > + uint8_t *aq_resp; /* buffer to store the adminq response from PF */ > > > > /* VSI info */ > > struct i40e_virtchnl_vf_resource *vf_res; /* All VSIs */ diff --git > > a/drivers/net/i40e/i40e_ethdev_vf.c > > b/drivers/net/i40e/i40e_ethdev_vf.c > > index 14d2a50..64e6957 100644 > > --- a/drivers/net/i40e/i40e_ethdev_vf.c > > +++ b/drivers/net/i40e/i40e_ethdev_vf.c > > @@ -103,9 +103,6 @@ enum i40evf_aq_result { > > I40EVF_MSG_CMD, /* Read async command result */ > > }; > > > > -/* A share buffer to store the command result from PF driver */ > > -static uint8_t cmd_result_buffer[I40E_AQ_BUF_SZ]; > > - > > static int i40evf_dev_configure(struct rte_eth_dev *dev); static int > > i40evf_dev_start(struct rte_eth_dev *dev); static void > > i40evf_dev_stop(struct rte_eth_dev *dev); @@ -237,31 +234,39 @@ > > i40evf_set_mac_type(struct i40e_hw *hw) } > > > > /* > > - * Parse admin queue message. > > - * > > - * return value: > > - * < 0: meet error > > - * 0: read sys msg > > - * > 0: read cmd result > > + * Read data in admin queue to get msg from pf driver > > */ > > static enum i40evf_aq_result > > -i40evf_parse_pfmsg(struct i40e_vf *vf, > > - struct i40e_arq_event_info *event, > > - struct i40evf_arq_msg_info *data) > > +i40evf_read_pfmsg(struct rte_eth_dev *dev, struct i40evf_arq_msg_info > > +*data) > > { > > - enum i40e_virtchnl_ops opcode = (enum i40e_virtchnl_ops)\ > > - rte_le_to_cpu_32(event->desc.cookie_high); > > - enum i40e_status_code retval = (enum i40e_status_code)\ > > - rte_le_to_cpu_32(event->desc.cookie_low); > > - enum i40evf_aq_result ret = I40EVF_MSG_CMD; > > + struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data- > > >dev_private); > > + struct i40e_vf *vf = I40EVF_DEV_PRIVATE_TO_VF(dev->data- > > >dev_private); > > + struct i40e_arq_event_info event; > > + enum i40e_virtchnl_ops opcode; > > + enum i40e_status_code retval; > > + int ret; > > + enum i40evf_aq_result result = I40EVF_MSG_NON; > > > > + event.buf_len = data->buf_len; > > + event.msg_buf = data->msg; > > + ret = i40e_clean_arq_element(hw, &event, NULL); > > + /* Can't read any msg from adminQ */ > > + if (ret) { > > + if (ret == I40E_ERR_ADMIN_QUEUE_NO_WORK) > > + result = I40EVF_MSG_NON; > > + else > > + result = I40EVF_MSG_ERR; > > + return result; > > + } > > + > > + opcode = (enum > > i40e_virtchnl_ops)rte_le_to_cpu_32(event.desc.cookie_high); > > + retval = (enum > > +i40e_status_code)rte_le_to_cpu_32(event.desc.cookie_low); > > /* pf sys event */ > > if (opcode == I40E_VIRTCHNL_OP_EVENT) { > > struct i40e_virtchnl_pf_event *vpe = > > - (struct i40e_virtchnl_pf_event *)event->msg_buf; > > + (struct i40e_virtchnl_pf_event *)event.msg_buf; > > > > - /* Initialize ret to sys event */ > > - ret = I40EVF_MSG_SYS; > > + result = I40EVF_MSG_SYS; > > switch (vpe->event) { > > case I40E_VIRTCHNL_EVENT_LINK_CHANGE: > > vf->link_up = > > @@ -286,74 +291,17 @@ i40evf_parse_pfmsg(struct i40e_vf *vf, > > } > > } else { > > /* async reply msg on command issued by vf previously */ > > - ret = I40EVF_MSG_CMD; > > + result = I40EVF_MSG_CMD; > > /* Actual data length read from PF */ > > - data->msg_len = event->msg_len; > > + data->msg_len = event.msg_len; > > } > > - /* fill the ops and result to notify VF */ > > + > > data->result = retval; > > data->ops = opcode; > > > > - return ret; > > -} > > - > > -/* > > - * Read data in admin queue to get msg from pf driver > > - */ > > -static enum i40evf_aq_result > > -i40evf_read_pfmsg(struct rte_eth_dev *dev, struct i40evf_arq_msg_info > > *data) -{ > > - struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data- > > >dev_private); > > - struct i40e_vf *vf = I40EVF_DEV_PRIVATE_TO_VF(dev->data- > > >dev_private); > > - struct i40e_arq_event_info event; > > - int ret; > > - enum i40evf_aq_result result = I40EVF_MSG_NON; > > - > > - event.buf_len = data->buf_len; > > - event.msg_buf = data->msg; > > - ret = i40e_clean_arq_element(hw, &event, NULL); > > - /* Can't read any msg from adminQ */ > > - if (ret) { > > - if (ret == I40E_ERR_ADMIN_QUEUE_NO_WORK) > > - result = I40EVF_MSG_NON; > > - else > > - result = I40EVF_MSG_ERR; > > - return result; > > - } > > - > > - /* Parse the event */ > > - result = i40evf_parse_pfmsg(vf, &event, data); > > - > > return result; > > } > > > > -/* > > - * Polling read until command result return from pf driver or meet error. > > - */ > > -static int > > -i40evf_wait_cmd_done(struct rte_eth_dev *dev, > > - struct i40evf_arq_msg_info *data) > > -{ > > - int i = 0; > > - enum i40evf_aq_result ret; > > - > > -#define MAX_TRY_TIMES 20 > > -#define ASQ_DELAY_MS 100 > > - do { > > - /* Delay some time first */ > > - rte_delay_ms(ASQ_DELAY_MS); > > - ret = i40evf_read_pfmsg(dev, data); > > - if (ret == I40EVF_MSG_CMD) > > - return 0; > > - else if (ret == I40EVF_MSG_ERR) > > - return -1; > > - > > - /* If don't read msg or read sys event, continue */ > > - } while(i++ < MAX_TRY_TIMES); > > - > > - return -1; > > -} > > - > > /** > > * clear current command. Only call in case execute > > * _atomic_set_cmd successfully. > > @@ -380,13 +328,18 @@ _atomic_set_cmd(struct i40e_vf *vf, enum > > i40e_virtchnl_ops ops) > > return !ret; > > } > > > > +#define MAX_TRY_TIMES 20 > > +#define ASQ_DELAY_MS 100 > > + > > static int > > i40evf_execute_vf_cmd(struct rte_eth_dev *dev, struct vf_cmd_info > > *args) { > > struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data- > > >dev_private); > > struct i40e_vf *vf = I40EVF_DEV_PRIVATE_TO_VF(dev->data- > > >dev_private); > > - int err = -1; > > struct i40evf_arq_msg_info info; > > + enum i40evf_aq_result ret; > > + int err = -1; > > + int i = 0; > > > > if (_atomic_set_cmd(vf, args->ops)) > > return -1; > > @@ -404,19 +357,22 @@ i40evf_execute_vf_cmd(struct rte_eth_dev *dev, > > struct vf_cmd_info *args) > > return err; > > } > > > > - err = i40evf_wait_cmd_done(dev, &info); > > - /* read message and it's expected one */ > > - if (!err && args->ops == info.ops) > > - _clear_cmd(vf); > > - else if (err) { > > - PMD_DRV_LOG(ERR, "Failed to read message from > > AdminQ"); > > - _clear_cmd(vf); > > - } > > - else if (args->ops != info.ops) > > - PMD_DRV_LOG(ERR, "command mismatch, expect %u, > > get %u", > > - args->ops, info.ops); > > + do { > > + /* Delay some time first */ > > + rte_delay_ms(ASQ_DELAY_MS); > > + ret = i40evf_read_pfmsg(dev, &info); > > + if (ret == I40EVF_MSG_CMD) { > > + err = 0; > > + break; > > + } else if (ret == I40EVF_MSG_ERR) { > > + err = -1; > > + break; > > + } > > + /* If don't read msg or read sys event, continue */ > > + } while (i++ < MAX_TRY_TIMES); > > + _clear_cmd(vf); > > > > - return (err | info.result); > > + return (err | vf->cmd_retval); > > } > > > Why combine the i40evf_parse_pfmsg and i40evf_read_pfmsg into one > function i40evf_read_pfmsg? Because what the i40evf_parse_pfmsg did is processing the pf event message, and it is meaningless for checking whether the vf request message is done. And the pf event message will be processed in i40evf_handle_pf_event which defined in the next patch of the same patch set. Thanks Jingjing ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [dpdk-dev] [PATCH v2 1/2] i40evf: allocate virtchnl cmd buffer for each vf 2016-01-27 1:49 ` [dpdk-dev] [PATCH v2 1/2] i40evf: allocate virtchnl cmd buffer for each vf Jingjing Wu 2016-01-29 7:28 ` Tao, Zhe @ 2016-02-22 7:26 ` Zhang, Helin 1 sibling, 0 replies; 7+ messages in thread From: Zhang, Helin @ 2016-02-22 7:26 UTC (permalink / raw) To: Wu, Jingjing, dev > -----Original Message----- > From: Wu, Jingjing > Sent: Wednesday, January 27, 2016 9:50 AM > To: dev@dpdk.org > Cc: Wu, Jingjing; Zhang, Helin; Lu, Wenzhuo; Pei, Yulong > Subject: [PATCH v2 1/2] i40evf: allocate virtchnl cmd buffer for each vf > > Currently, i40evf PMD uses a global static buffer to send virtchnl command to > host driver. It is shared by multi VFs. > This patch changed to allocate virtchnl cmd buffer for each VF. > > Signed-off-by: Jingjing Wu <jingjing.wu@intel.com> > --- > drivers/net/i40e/i40e_ethdev.h | 2 + > drivers/net/i40e/i40e_ethdev_vf.c | 181 +++++++++++++++------------------- > ---- > 2 files changed, 74 insertions(+), 109 deletions(-) > > diff --git a/drivers/net/i40e/i40e_ethdev.h > b/drivers/net/i40e/i40e_ethdev.h index 1f9792b..93122ad 100644 > --- a/drivers/net/i40e/i40e_ethdev.h > +++ b/drivers/net/i40e/i40e_ethdev.h > @@ -494,7 +494,9 @@ struct i40e_vf { > bool link_up; > bool vf_reset; > volatile uint32_t pend_cmd; /* pending command not finished yet */ > + uint32_t cmd_retval; /* return value of the cmd response from PF */ > u16 pend_msg; /* flags indicates events from pf not handled yet */ > + uint8_t *aq_resp; /* buffer to store the adminq response from PF */ > > /* VSI info */ > struct i40e_virtchnl_vf_resource *vf_res; /* All VSIs */ diff --git > a/drivers/net/i40e/i40e_ethdev_vf.c b/drivers/net/i40e/i40e_ethdev_vf.c > index 14d2a50..64e6957 100644 > --- a/drivers/net/i40e/i40e_ethdev_vf.c > +++ b/drivers/net/i40e/i40e_ethdev_vf.c > @@ -103,9 +103,6 @@ enum i40evf_aq_result { > I40EVF_MSG_CMD, /* Read async command result */ > }; > > -/* A share buffer to store the command result from PF driver */ -static > uint8_t cmd_result_buffer[I40E_AQ_BUF_SZ]; > - > static int i40evf_dev_configure(struct rte_eth_dev *dev); static int > i40evf_dev_start(struct rte_eth_dev *dev); static void > i40evf_dev_stop(struct rte_eth_dev *dev); @@ -237,31 +234,39 @@ > i40evf_set_mac_type(struct i40e_hw *hw) } > > /* > - * Parse admin queue message. > - * > - * return value: > - * < 0: meet error > - * 0: read sys msg > - * > 0: read cmd result > + * Read data in admin queue to get msg from pf driver > */ > static enum i40evf_aq_result > -i40evf_parse_pfmsg(struct i40e_vf *vf, > - struct i40e_arq_event_info *event, > - struct i40evf_arq_msg_info *data) > +i40evf_read_pfmsg(struct rte_eth_dev *dev, struct i40evf_arq_msg_info > +*data) > { > - enum i40e_virtchnl_ops opcode = (enum i40e_virtchnl_ops)\ > - rte_le_to_cpu_32(event->desc.cookie_high); > - enum i40e_status_code retval = (enum i40e_status_code)\ > - rte_le_to_cpu_32(event->desc.cookie_low); > - enum i40evf_aq_result ret = I40EVF_MSG_CMD; > + struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data- > >dev_private); > + struct i40e_vf *vf = I40EVF_DEV_PRIVATE_TO_VF(dev->data- > >dev_private); > + struct i40e_arq_event_info event; > + enum i40e_virtchnl_ops opcode; > + enum i40e_status_code retval; > + int ret; > + enum i40evf_aq_result result = I40EVF_MSG_NON; > > + event.buf_len = data->buf_len; > + event.msg_buf = data->msg; > + ret = i40e_clean_arq_element(hw, &event, NULL); > + /* Can't read any msg from adminQ */ > + if (ret) { > + if (ret == I40E_ERR_ADMIN_QUEUE_NO_WORK) > + result = I40EVF_MSG_NON; No need to assign I40EVF_MSG_NON, as it was initialized at first. > + else > + result = I40EVF_MSG_ERR; > + return result; > + } > + > + opcode = (enum > i40e_virtchnl_ops)rte_le_to_cpu_32(event.desc.cookie_high); > + retval = (enum > +i40e_status_code)rte_le_to_cpu_32(event.desc.cookie_low); > /* pf sys event */ > if (opcode == I40E_VIRTCHNL_OP_EVENT) { > struct i40e_virtchnl_pf_event *vpe = > - (struct i40e_virtchnl_pf_event *)event->msg_buf; > + (struct i40e_virtchnl_pf_event *)event.msg_buf; > > - /* Initialize ret to sys event */ > - ret = I40EVF_MSG_SYS; > + result = I40EVF_MSG_SYS; > switch (vpe->event) { > case I40E_VIRTCHNL_EVENT_LINK_CHANGE: > vf->link_up = > @@ -286,74 +291,17 @@ i40evf_parse_pfmsg(struct i40e_vf *vf, > } > } else { > /* async reply msg on command issued by vf previously */ > - ret = I40EVF_MSG_CMD; > + result = I40EVF_MSG_CMD; > /* Actual data length read from PF */ > - data->msg_len = event->msg_len; > + data->msg_len = event.msg_len; > } > - /* fill the ops and result to notify VF */ > + > data->result = retval; > data->ops = opcode; > > - return ret; > -} > - > -/* > - * Read data in admin queue to get msg from pf driver > - */ > -static enum i40evf_aq_result > -i40evf_read_pfmsg(struct rte_eth_dev *dev, struct i40evf_arq_msg_info > *data) -{ > - struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data- > >dev_private); > - struct i40e_vf *vf = I40EVF_DEV_PRIVATE_TO_VF(dev->data- > >dev_private); > - struct i40e_arq_event_info event; > - int ret; > - enum i40evf_aq_result result = I40EVF_MSG_NON; > - > - event.buf_len = data->buf_len; > - event.msg_buf = data->msg; > - ret = i40e_clean_arq_element(hw, &event, NULL); > - /* Can't read any msg from adminQ */ > - if (ret) { > - if (ret == I40E_ERR_ADMIN_QUEUE_NO_WORK) > - result = I40EVF_MSG_NON; > - else > - result = I40EVF_MSG_ERR; > - return result; > - } > - > - /* Parse the event */ > - result = i40evf_parse_pfmsg(vf, &event, data); > - > return result; > } > > -/* > - * Polling read until command result return from pf driver or meet error. > - */ > -static int > -i40evf_wait_cmd_done(struct rte_eth_dev *dev, > - struct i40evf_arq_msg_info *data) > -{ > - int i = 0; > - enum i40evf_aq_result ret; > - > -#define MAX_TRY_TIMES 20 > -#define ASQ_DELAY_MS 100 > - do { > - /* Delay some time first */ > - rte_delay_ms(ASQ_DELAY_MS); > - ret = i40evf_read_pfmsg(dev, data); > - if (ret == I40EVF_MSG_CMD) > - return 0; > - else if (ret == I40EVF_MSG_ERR) > - return -1; > - > - /* If don't read msg or read sys event, continue */ > - } while(i++ < MAX_TRY_TIMES); > - > - return -1; > -} > - > /** > * clear current command. Only call in case execute > * _atomic_set_cmd successfully. > @@ -380,13 +328,18 @@ _atomic_set_cmd(struct i40e_vf *vf, enum > i40e_virtchnl_ops ops) > return !ret; > } > > +#define MAX_TRY_TIMES 20 > +#define ASQ_DELAY_MS 100 > + > static int > i40evf_execute_vf_cmd(struct rte_eth_dev *dev, struct vf_cmd_info *args) > { > struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data- > >dev_private); > struct i40e_vf *vf = I40EVF_DEV_PRIVATE_TO_VF(dev->data- > >dev_private); > - int err = -1; > struct i40evf_arq_msg_info info; > + enum i40evf_aq_result ret; > + int err = -1; > + int i = 0; > > if (_atomic_set_cmd(vf, args->ops)) > return -1; > @@ -404,19 +357,22 @@ i40evf_execute_vf_cmd(struct rte_eth_dev *dev, > struct vf_cmd_info *args) > return err; > } > > - err = i40evf_wait_cmd_done(dev, &info); > - /* read message and it's expected one */ > - if (!err && args->ops == info.ops) > - _clear_cmd(vf); > - else if (err) { > - PMD_DRV_LOG(ERR, "Failed to read message from > AdminQ"); > - _clear_cmd(vf); > - } > - else if (args->ops != info.ops) > - PMD_DRV_LOG(ERR, "command mismatch, expect %u, > get %u", > - args->ops, info.ops); > + do { > + /* Delay some time first */ > + rte_delay_ms(ASQ_DELAY_MS); It would be better to read first, but not delay first. In addition, the value of ASG_DELAY_MS shouldn't be 100ms. It is a bit too long, try 5ms or 10ms, or even shorter, and see if it is good. I remember that there is a complaint here for the interval. Note that if ASG_DELAY_MS changed, MAX_TRY_TIMES should also be modified. > + ret = i40evf_read_pfmsg(dev, &info); > + if (ret == I40EVF_MSG_CMD) { > + err = 0; > + break; > + } else if (ret == I40EVF_MSG_ERR) { > + err = -1; > + break; > + } > + /* If don't read msg or read sys event, continue */ > + } while (i++ < MAX_TRY_TIMES); > + _clear_cmd(vf); > > - return (err | info.result); > + return (err | vf->cmd_retval); > } > > /* ^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2016-02-22 7:26 UTC | newest] Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2016-01-27 1:46 [dpdk-dev] [PATCH v2 0/2] i40evf: support interrupt based pf reset request Jingjing Wu 2016-01-27 1:46 ` [dpdk-dev] [PATCH v2 1/2] i40evf: allocate virtchnl cmd buffer for each vf Jingjing Wu 2016-01-27 1:46 ` [dpdk-dev] [PATCH v2 2/2] i40evf: support interrupt based pf reset request Jingjing Wu -- strict thread matches above, loose matches on Subject: below -- 2016-01-13 12:31 [dpdk-dev] [PATCH 0/2] " Jingjing Wu 2016-01-27 1:49 ` [dpdk-dev] [PATCH v2 " Jingjing Wu 2016-01-27 1:49 ` [dpdk-dev] [PATCH v2 1/2] i40evf: allocate virtchnl cmd buffer for each vf Jingjing Wu 2016-01-29 7:28 ` Tao, Zhe 2016-02-14 2:22 ` Wu, Jingjing 2016-02-22 7:26 ` Zhang, Helin
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).