From mboxrd@z Thu Jan 1 00:00:00 1970 From: Beilei Xing Subject: [PATCH] ppp implemantation Date: Fri, 3 Mar 2017 15:26:10 +0800 Message-ID: <1488525977-15321-6-git-send-email-beilei.xing@intel.com> References: <1488525977-15321-1-git-send-email-beilei.xing@intel.com> Cc: helin.zhang@intel.com, dev@dpdk.org To: jingjing.wu@intel.com Return-path: Received: from mga03.intel.com (mga03.intel.com [134.134.136.65]) by dpdk.org (Postfix) with ESMTP id 337BA37AA for ; Fri, 3 Mar 2017 08:27:30 +0100 (CET) In-Reply-To: <1488525977-15321-1-git-send-email-beilei.xing@intel.com> List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" Signed-off-by: Beilei Xing --- app/test-pmd/cmdline.c | 57 ++++++++++++ app/test-pmd/config.c | 62 +++++++++++++ app/test-pmd/testpmd.h | 3 + drivers/net/i40e/base/i40e_adminq_cmd.h | 33 +++++++ drivers/net/i40e/base/i40e_common.c | 160 +++++++++++++++++++++++++++++++- drivers/net/i40e/base/i40e_prototype.h | 12 +++ drivers/net/i40e/base/i40e_type.h | 69 ++++++++++++++ drivers/net/i40e/i40e_ethdev.c | 55 +++++++++++ drivers/net/i40e/rte_pmd_i40e.h | 1 + 9 files changed, 451 insertions(+), 1 deletion(-) diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c index 43fc636..0d62a07 100644 --- a/app/test-pmd/cmdline.c +++ b/app/test-pmd/cmdline.c @@ -12395,6 +12395,62 @@ cmdline_parse_inst_t cmd_set_vf_vlan_tag = { }, }; +/* Write Pipeline Personalization Profile */ +struct cmd_write_ppp_result { + cmdline_fixed_string_t write; + cmdline_fixed_string_t ppp; + uint8_t port_id; + char filename[]; +}; + +cmdline_parse_token_string_t cmd_write_ppp_write = + TOKEN_STRING_INITIALIZER(struct cmd_write_ppp_result, write, "write"); +cmdline_parse_token_string_t cmd_write_ppp_ppp = + TOKEN_STRING_INITIALIZER(struct cmd_write_ppp_result, ppp, "ppp"); +cmdline_parse_token_num_t cmd_write_ppp_port_id = + TOKEN_NUM_INITIALIZER(struct cmd_write_ppp_result, port_id, UINT8); +cmdline_parse_token_string_t cmd_write_ppp_filename = + TOKEN_STRING_INITIALIZER(struct cmd_write_ppp_result, filename, NULL); + +static void +cmd_write_ppp_parsed( + void *parsed_result, + __attribute__((unused)) struct cmdline *cl, + __attribute__((unused)) void *data) +{ + struct cmd_write_ppp_result *res = parsed_result; + uint8_t *buff; + int ret = -ENOTSUP; + + if (res->port_id > nb_ports) { + printf("Invalid port, range is [0, %d]\n", nb_ports - 1); + return; + } + + buff = open_package_file(res->filename); + if (!buff) + return; + + ret = i40e_process_package(res->port_id, buff); + if (ret < 0) + printf("Failed to write profile.\n"); + + close_package_file(buff); +} + +cmdline_parse_inst_t cmd_write_ppp = { + .f = cmd_write_ppp_parsed, + .data = NULL, + .help_str = "write ppp ", + .tokens = { + (void *)&cmd_write_ppp_write, + (void *)&cmd_write_ppp_ppp, + (void *)&cmd_write_ppp_port_id, + (void *)&cmd_write_ppp_filename, + NULL, + }, +}; + /* ******************************************************************************** */ /* list of instructions */ @@ -12570,6 +12626,7 @@ cmdline_parse_ctx_t main_ctx[] = { (cmdline_parse_inst_t *)&cmd_set_vf_allmulti, (cmdline_parse_inst_t *)&cmd_set_vf_broadcast, (cmdline_parse_inst_t *)&cmd_set_vf_vlan_tag, + (cmdline_parse_inst_t *)&cmd_write_ppp, NULL, }; diff --git a/app/test-pmd/config.c b/app/test-pmd/config.c index 80491fc..aa26da1 100644 --- a/app/test-pmd/config.c +++ b/app/test-pmd/config.c @@ -3245,3 +3245,65 @@ port_dcb_info_display(uint8_t port_id) printf("\t%4d", dcb_info.tc_queue.tc_txq[0][i].nb_queue); printf("\n"); } + +uint8_t * +open_package_file(const char *file_path) +{ + FILE *fh = fopen(file_path, "rb"); + uint32_t pkg_size; + uint8_t *buf = NULL; + int ret = 0; + + if (fh == NULL) { + printf("%s: Failed to open %s\n", __func__, file_path); + return buf; + } + + ret = fseek(fh, 0, SEEK_END); + if (ret < 0) { + fclose(fh); + printf("%s: File operations failed\n", __func__); + return buf; + } + + pkg_size = ftell(fh); + + buf = (uint8_t *)malloc(pkg_size); + if (!buf) { + fclose(fh); + printf("%s: Failed to malloc memory\n", __func__); + return buf; + } + + ret = fseek(fh, 0, SEEK_SET); + if (ret < 0) { + fclose(fh); + printf("%s: File operations failed\n", __func__); + close_package_file(buf); + return NULL; + } + fread(buf, 1, pkg_size, fh); + + for(uint32_t i = 0; i < pkg_size; i++) { + if (!(i % 16)) + printf(" "); + printf(" 0x%02X,", buf[i]); + if (!((i + 1) % 16)) + printf("\n"); + } + + fclose(fh); + + return buf; +} + +int +close_package_file(uint8_t *buf) +{ + if (buf) { + free((void *)buf); + return 0; + } + + return -1; +} diff --git a/app/test-pmd/testpmd.h b/app/test-pmd/testpmd.h index 8cf2860..2a7f683 100644 --- a/app/test-pmd/testpmd.h +++ b/app/test-pmd/testpmd.h @@ -622,6 +622,9 @@ void mcast_addr_add(uint8_t port_id, struct ether_addr *mc_addr); void mcast_addr_remove(uint8_t port_id, struct ether_addr *mc_addr); void port_dcb_info_display(uint8_t port_id); +uint8_t *open_package_file(const char *file_path); +int close_package_file(uint8_t *buf); + enum print_warning { ENABLED_WARN = 0, DISABLED_WARN diff --git a/drivers/net/i40e/base/i40e_adminq_cmd.h b/drivers/net/i40e/base/i40e_adminq_cmd.h index 67cef7c..593394a 100644 --- a/drivers/net/i40e/base/i40e_adminq_cmd.h +++ b/drivers/net/i40e/base/i40e_adminq_cmd.h @@ -198,6 +198,10 @@ enum i40e_admin_queue_opc { i40e_aqc_opc_add_mirror_rule = 0x0260, i40e_aqc_opc_delete_mirror_rule = 0x0261, + /* Support Pipeline Personalization Profile */ + i40e_aqc_opc_write_personalization_profile = 0x0270, + i40e_aqc_opc_read_personalization_profile_list = 0x0271, + /* DCB commands */ i40e_aqc_opc_dcb_ignore_pfc = 0x0301, i40e_aqc_opc_dcb_updated = 0x0302, @@ -1441,6 +1445,35 @@ struct i40e_aqc_add_delete_mirror_rule_completion { I40E_CHECK_CMD_LENGTH(i40e_aqc_add_delete_mirror_rule_completion); +/* Pipeline Personalization Profile */ +struct i40e_aqc_write_ppp { + u8 flags; +#define I40E_AQ_WR_PPP_ADD_TRACK_ID 0x01 +#define I40E_AQ_WR_PPP_REMOVE_TRACK_ID 0x02 + u8 reserved[3]; + __le32 profile_track_id; + __le32 addr_high; + __le32 addr_low; +}; + +I40E_CHECK_CMD_LENGTH(i40e_aqc_write_ppp); + +struct i40e_aqc_write_ppp_resp { + __le32 error_offset; + __le32 error_info; + __le32 addr_high; + __le32 addr_low; +}; + +struct i40e_aqc_read_ppp { + u8 flags; + u8 reserved[7]; + __le32 addr_high; + __le32 addr_low; +}; + +I40E_CHECK_CMD_LENGTH(i40e_aqc_read_ppp); + /* DCB 0x03xx*/ /* PFC Ignore (direct 0x0301) diff --git a/drivers/net/i40e/base/i40e_common.c b/drivers/net/i40e/base/i40e_common.c index b8d8165..4fb419c 100644 --- a/drivers/net/i40e/base/i40e_common.c +++ b/drivers/net/i40e/base/i40e_common.c @@ -6997,4 +6997,162 @@ enum i40e_status_code i40e_aq_clear_all_wol_filters(struct i40e_hw *hw, status = i40e_asq_send_command(hw, &desc, NULL, 0, cmd_details); return status; -} \ No newline at end of file +} + +/** + * i40e_aq_write_ppp - Write pipeline personalization profile (ppp) + * @hw: pointer to the hw struct + * @buff: command buffer (size in bytes = buff_size) + * @buff_size: buffer size in bytes + * @track_id: package tracking id + * @cmd_details: pointer to command details structure or NULL + **/ +enum +i40e_status_code i40e_aq_write_ppp(struct i40e_hw *hw, void *buff, + u16 buff_size, u32 track_id, + struct i40e_asq_cmd_details *cmd_details) +{ + struct i40e_aq_desc desc; + struct i40e_aqc_write_ppp *cmd = + (struct i40e_aqc_write_ppp *)&desc.params.raw; + struct i40e_aqc_write_ppp_resp *resp; + enum i40e_status_code status; + + i40e_fill_default_direct_cmd_desc(&desc, + i40e_aqc_opc_write_personalization_profile); + + desc.flags |= CPU_TO_LE16(I40E_AQ_FLAG_BUF | I40E_AQ_FLAG_RD); + if (buff_size > I40E_AQ_LARGE_BUF) + desc.flags |= CPU_TO_LE16((u16)I40E_AQ_FLAG_LB); + + desc.datalen = CPU_TO_LE16(buff_size); + + cmd->profile_track_id = CPU_TO_LE32(track_id); + + status = i40e_asq_send_command(hw, &desc, buff, buff_size, cmd_details); + + return status; +} + +/** + * i40e_aq_read_ppp - Read pipeline personalization profile (ppp) + * @hw: pointer to the hw struct + * @buff: command buffer (size in bytes = buff_size) + * @buff_size: buffer size in bytes + * @cmd_details: pointer to command details structure or NULL + **/ +enum +i40e_status_code i40e_aq_read_ppp(struct i40e_hw *hw, + void *buff, u16 buff_size, + struct i40e_asq_cmd_details *cmd_details) +{ + struct i40e_aq_desc desc; + struct i40e_aqc_read_ppp *cmd = + (struct i40e_aqc_read_ppp *)&desc.params.raw; + enum i40e_status_code status; + + i40e_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_read_personalization_profile_list); + + if (buff_size > I40E_AQ_LARGE_BUF) + desc.flags |= CPU_TO_LE16((u16)I40E_AQ_FLAG_LB); + desc.datalen = CPU_TO_LE16(buff_size); + + status = i40e_asq_send_command(hw, &desc, buff, buff_size, cmd_details); + + return status; +} + +/** + * i40e_find_segment_in_package + * @segment_type: the segment type to search for (i.e., SEGMENT_TYPE_I40E) + * @pkg_hdr: pointer to the package header to be searched + * + * This function searches a package file for a particular segment type. On + * success it returns a pointer to the segment header, otherwise it will + * return NULL. + */ +struct i40e_generic_seg_header * +i40e_find_segment_in_package(u32 segment_type, + struct i40e_package_header *pkg_hdr) +{ + struct i40e_generic_seg_header *segment; + u32 i; + + PMD_DRV_LOG(INFO, "i40e_find_segment_in_package"); + PMD_DRV_LOG(INFO, "Package version: %d.%d.%d.%d", + pkg_hdr->version.major, + pkg_hdr->version.minor, + pkg_hdr->version.update, + pkg_hdr->version.draft); + + /* Search all package segments for the requested segment type */ + for (i = 0; i < pkg_hdr->segment_count; i++) { + segment = + (struct i40e_generic_seg_header *)((u8 *)pkg_hdr + + pkg_hdr->segment_offset[i]); + + if (segment->type == segment_type) + return segment; + } + + return NULL; +} + +/** + * i40e_write_profile + * @hw: pointer to the hardware structure + * @profile: pointer to the profile segment of the package to be downloaded + * @track_id: package tracking id + * + * Handles the download of a complete package. + */ +enum i40e_status_code +i40e_write_profile(struct i40e_hw *hw, struct i40e_profile_segment *profile, + u32 track_id) +{ + enum i40e_status_code status = I40E_SUCCESS; + struct i40e_section_table *sec_tbl; + struct i40e_profile_section_header *sec = NULL; + u32 dev_cnt; + u32 *nvm; + u32 section_size = 0; + u32 i; + + PMD_DRV_LOG(INFO, "i40e_write_profile"); + PMD_DRV_LOG(INFO, "Segment version: %d.%d.%d.%d", + profile->header.version.major, + profile->header.version.minor, + profile->header.version.update, + profile->header.version.draft); + PMD_DRV_LOG(INFO, "Seg: type 0x%X, size %d, name %s", + LE32_TO_CPU(profile->header.type), + LE32_TO_CPU(profile->header.size), + profile->header.name); + + dev_cnt = profile->device_table_count; + nvm = (u32 *)&profile->device_table[dev_cnt]; + sec_tbl = (struct i40e_section_table *)&nvm[nvm[0] + 1]; + + for (i = 0; i < sec_tbl->section_count; i++) { + sec = (struct i40e_profile_section_header *)((char *)profile + + sec_tbl->section_offset[i]); + + /* Skip 'AQ', 'note' and 'name' sections */ + if (sec->section.type != SECTION_TYPE_MMIO) + continue; + + section_size = sec->section.size + + sizeof(struct i40e_profile_section_header); + break; + } + + /* Write profile */ + status = i40e_aq_write_ppp(hw, (void *)sec, section_size, + track_id, NULL); + if (status) { + PMD_DRV_LOG(ERR, "Failed to write profile!"); + return status; + } + + return status; +} diff --git a/drivers/net/i40e/base/i40e_prototype.h b/drivers/net/i40e/base/i40e_prototype.h index 109d3c5..4f7b63f 100644 --- a/drivers/net/i40e/base/i40e_prototype.h +++ b/drivers/net/i40e/base/i40e_prototype.h @@ -555,4 +555,16 @@ enum i40e_status_code i40e_write_phy_register(struct i40e_hw *hw, u8 i40e_get_phy_address(struct i40e_hw *hw, u8 dev_num); enum i40e_status_code i40e_blink_phy_link_led(struct i40e_hw *hw, u32 time, u32 interval); +enum i40e_status_code i40e_aq_write_ppp(struct i40e_hw *hw, void *buff, + u16 buff_size, u32 track_id, + struct i40e_asq_cmd_details *cmd_details); +enum i40e_status_code i40e_aq_read_ppp(struct i40e_hw *hw, + void *buff, u16 buff_size, + struct i40e_asq_cmd_details *cmd_details); +struct i40e_generic_seg_header * +i40e_find_segment_in_package(u32 segment_type, + struct i40e_package_header *pkg_header); +enum i40e_status_code +i40e_write_profile(struct i40e_hw *hw, struct i40e_profile_segment *i40e_seg, + u32 track_id); #endif /* _I40E_PROTOTYPE_H_ */ diff --git a/drivers/net/i40e/base/i40e_type.h b/drivers/net/i40e/base/i40e_type.h index 590d97c..dafb8d9 100644 --- a/drivers/net/i40e/base/i40e_type.h +++ b/drivers/net/i40e/base/i40e_type.h @@ -1878,4 +1878,73 @@ struct i40e_lldp_variables { #define I40E_FLEX_56_MASK (0x1ULL << I40E_FLEX_56_SHIFT) #define I40E_FLEX_57_SHIFT 6 #define I40E_FLEX_57_MASK (0x1ULL << I40E_FLEX_57_SHIFT) + +/* Version format for PPP */ +struct i40e_ppp_version { + u8 major; + u8 minor; + u8 update; + u8 draft; +}; + +#define I40E_PPP_NAME_SIZE 32 + +/* Package header */ +struct i40e_package_header { + struct i40e_ppp_version version; + u32 segment_count; + u32 segment_offset[1]; +}; + +/* Generic segment header */ +struct i40e_generic_seg_header { + #define SEGMENT_TYPE_METADATA 0x00000001 + #define SEGMENT_TYPE_NOTES 0x00000002 + #define SEGMENT_TYPE_I40E 0x00000011 + #define SEGMENT_TYPE_X722 0x00000012 + u32 type; + struct i40e_ppp_version version; + u32 size; + char name[I40E_PPP_NAME_SIZE]; +}; + +struct i40e_metadata_segment { + struct i40e_generic_seg_header header; + struct i40e_ppp_version version; + uint32_t track_id; + char name[I40E_PPP_NAME_SIZE]; +}; + +struct i40e_device_id_entry { + u32 device_id; + u32 sub_device_id; +}; + +struct i40e_profile_segment { + struct i40e_generic_seg_header header; + struct i40e_ppp_version version; + char name[I40E_PPP_NAME_SIZE]; + u32 device_table_count; + struct i40e_device_id_entry device_table[1]; +}; + +struct i40e_section_table { + u32 section_count; + u32 section_offset[1]; +}; + +struct i40e_profile_section_header { + u16 tbl_size; + u16 data_end; + struct { + #define SECTION_TYPE_INFO 0x0000010 + #define SECTION_TYPE_MMIO 0x0000800 + #define SECTION_TYPE_AQ 0x0000801 + #define SECTION_TYPE_NOTE 0x8000000 + #define SECTION_TYPE_NAME 0x8000001 + u32 type; + u32 offset; + u32 size; + } section; +}; #endif /* _I40E_TYPE_H_ */ diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c index 303027b..a467711 100644 --- a/drivers/net/i40e/i40e_ethdev.c +++ b/drivers/net/i40e/i40e_ethdev.c @@ -39,6 +39,10 @@ #include #include #include +#include +#include +#include +#include #include #include @@ -11212,3 +11216,54 @@ rte_pmd_i40e_reset_vf_stats(uint8_t port, return 0; } + +/** + * i40e_process_package - Load package + * @port: port id + * @filename: file name of the package + **/ +int +i40e_process_package(uint8_t port, uint8_t *buff) +{ + struct rte_eth_dev *dev = &rte_eth_devices[port]; + struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private); + struct i40e_package_header *pkg_hdr; + struct i40e_generic_seg_header *profile_seg_hdr; + struct i40e_generic_seg_header *metadata_seg_hdr; + uint32_t track_id; + enum i40e_status_code status; + + pkg_hdr = (struct i40e_package_header *)buff; + + if (!pkg_hdr) { + PMD_DRV_LOG(ERR, "Failed to fill the package structure"); + return -EINVAL; + } + + /* Find metadata segment */ + metadata_seg_hdr = i40e_find_segment_in_package(SEGMENT_TYPE_METADATA, + pkg_hdr); + if (!metadata_seg_hdr) { + PMD_DRV_LOG(ERR, "Failed to find metadata segment header"); + return -EINVAL; + } + track_id = ((struct i40e_metadata_segment *)metadata_seg_hdr)->track_id; + + /* Find profile segment */ + profile_seg_hdr = i40e_find_segment_in_package(SEGMENT_TYPE_I40E, + pkg_hdr); + if (!profile_seg_hdr) { + PMD_DRV_LOG(ERR, "Failed to find profile segment header"); + return -EINVAL; + } + + /* Write profile to HW */ + status = i40e_write_profile(hw, + (struct i40e_profile_segment *)profile_seg_hdr, + track_id); + + if (!status) + printf("Write profile successfully.\n"); + + return status; +} diff --git a/drivers/net/i40e/rte_pmd_i40e.h b/drivers/net/i40e/rte_pmd_i40e.h index a0ad88c..755a279 100644 --- a/drivers/net/i40e/rte_pmd_i40e.h +++ b/drivers/net/i40e/rte_pmd_i40e.h @@ -332,4 +332,5 @@ int rte_pmd_i40e_get_vf_stats(uint8_t port, int rte_pmd_i40e_reset_vf_stats(uint8_t port, uint16_t vf_id); +int i40e_process_package(uint8_t port, uint8_t *buff); #endif /* _PMD_I40E_H_ */ -- 2.5.5