// SPDX-License-Identifier: GPL-2.0 /* Copyright (c) 2022, Intel Corporation. */ #include "ice_common.h" #include "ice.h" #include "ice_ddp.h" #include "ice_sched.h" /* For supporting double VLAN mode, it is necessary to enable or disable certain * boost tcam entries. The metadata labels names that match the following * prefixes will be saved to allow enabling double VLAN mode. */ #define ICE_DVM_PRE … #define ICE_SVM_PRE … /* To support tunneling entries by PF, the package will append the PF number to * the label; for example TNL_VXLAN_PF0, TNL_VXLAN_PF1, TNL_VXLAN_PF2, etc. */ #define ICE_TNL_PRE … static const struct ice_tunnel_type_scan tnls[] = …; /** * ice_verify_pkg - verify package * @pkg: pointer to the package buffer * @len: size of the package buffer * * Verifies various attributes of the package file, including length, format * version, and the requirement of at least one segment. */ static enum ice_ddp_state ice_verify_pkg(const struct ice_pkg_hdr *pkg, u32 len) { … } /** * ice_free_seg - free package segment pointer * @hw: pointer to the hardware structure * * Frees the package segment pointer in the proper manner, depending on if the * segment was allocated or just the passed in pointer was stored. */ void ice_free_seg(struct ice_hw *hw) { … } /** * ice_chk_pkg_version - check package version for compatibility with driver * @pkg_ver: pointer to a version structure to check * * Check to make sure that the package about to be downloaded is compatible with * the driver. To be compatible, the major and minor components of the package * version must match our ICE_PKG_SUPP_VER_MAJ and ICE_PKG_SUPP_VER_MNR * definitions. */ static enum ice_ddp_state ice_chk_pkg_version(struct ice_pkg_ver *pkg_ver) { … } /** * ice_pkg_val_buf * @buf: pointer to the ice buffer * * This helper function validates a buffer's header. */ static const struct ice_buf_hdr *ice_pkg_val_buf(const struct ice_buf *buf) { … } /** * ice_find_buf_table * @ice_seg: pointer to the ice segment * * Returns the address of the buffer table within the ice segment. */ static struct ice_buf_table *ice_find_buf_table(struct ice_seg *ice_seg) { … } /** * ice_pkg_enum_buf * @ice_seg: pointer to the ice segment (or NULL on subsequent calls) * @state: pointer to the enum state * * This function will enumerate all the buffers in the ice segment. The first * call is made with the ice_seg parameter non-NULL; on subsequent calls, * ice_seg is set to NULL which continues the enumeration. When the function * returns a NULL pointer, then the end of the buffers has been reached, or an * unexpected value has been detected (for example an invalid section count or * an invalid buffer end value). */ static const struct ice_buf_hdr *ice_pkg_enum_buf(struct ice_seg *ice_seg, struct ice_pkg_enum *state) { … } /** * ice_pkg_advance_sect * @ice_seg: pointer to the ice segment (or NULL on subsequent calls) * @state: pointer to the enum state * * This helper function will advance the section within the ice segment, * also advancing the buffer if needed. */ static bool ice_pkg_advance_sect(struct ice_seg *ice_seg, struct ice_pkg_enum *state) { … } /** * ice_pkg_enum_section * @ice_seg: pointer to the ice segment (or NULL on subsequent calls) * @state: pointer to the enum state * @sect_type: section type to enumerate * * This function will enumerate all the sections of a particular type in the * ice segment. The first call is made with the ice_seg parameter non-NULL; * on subsequent calls, ice_seg is set to NULL which continues the enumeration. * When the function returns a NULL pointer, then the end of the matching * sections has been reached. */ void *ice_pkg_enum_section(struct ice_seg *ice_seg, struct ice_pkg_enum *state, u32 sect_type) { … } /** * ice_pkg_enum_entry * @ice_seg: pointer to the ice segment (or NULL on subsequent calls) * @state: pointer to the enum state * @sect_type: section type to enumerate * @offset: pointer to variable that receives the offset in the table (optional) * @handler: function that handles access to the entries into the section type * * This function will enumerate all the entries in particular section type in * the ice segment. The first call is made with the ice_seg parameter non-NULL; * on subsequent calls, ice_seg is set to NULL which continues the enumeration. * When the function returns a NULL pointer, then the end of the entries has * been reached. * * Since each section may have a different header and entry size, the handler * function is needed to determine the number and location entries in each * section. * * The offset parameter is optional, but should be used for sections that * contain an offset for each section table. For such cases, the section handler * function must return the appropriate offset + index to give the absolution * offset for each entry. For example, if the base for a section's header * indicates a base offset of 10, and the index for the entry is 2, then * section handler function should set the offset to 10 + 2 = 12. */ void *ice_pkg_enum_entry(struct ice_seg *ice_seg, struct ice_pkg_enum *state, u32 sect_type, u32 *offset, void *(*handler)(u32 sect_type, void *section, u32 index, u32 *offset)) { … } /** * ice_sw_fv_handler * @sect_type: section type * @section: pointer to section * @index: index of the field vector entry to be returned * @offset: ptr to variable that receives the offset in the field vector table * * This is a callback function that can be passed to ice_pkg_enum_entry. * This function treats the given section as of type ice_sw_fv_section and * enumerates offset field. "offset" is an index into the field vector table. */ static void *ice_sw_fv_handler(u32 sect_type, void *section, u32 index, u32 *offset) { … } /** * ice_get_prof_index_max - get the max profile index for used profile * @hw: pointer to the HW struct * * Calling this function will get the max profile index for used profile * and store the index number in struct ice_switch_info *switch_info * in HW for following use. */ static int ice_get_prof_index_max(struct ice_hw *hw) { … } /** * ice_get_ddp_pkg_state - get DDP pkg state after download * @hw: pointer to the HW struct * @already_loaded: indicates if pkg was already loaded onto the device */ static enum ice_ddp_state ice_get_ddp_pkg_state(struct ice_hw *hw, bool already_loaded) { … } /** * ice_init_pkg_regs - initialize additional package registers * @hw: pointer to the hardware structure */ static void ice_init_pkg_regs(struct ice_hw *hw) { … } /** * ice_marker_ptype_tcam_handler * @sect_type: section type * @section: pointer to section * @index: index of the Marker PType TCAM entry to be returned * @offset: pointer to receive absolute offset, always 0 for ptype TCAM sections * * This is a callback function that can be passed to ice_pkg_enum_entry. * Handles enumeration of individual Marker PType TCAM entries. */ static void *ice_marker_ptype_tcam_handler(u32 sect_type, void *section, u32 index, u32 *offset) { … } /** * ice_add_dvm_hint * @hw: pointer to the HW structure * @val: value of the boost entry * @enable: true if entry needs to be enabled, or false if needs to be disabled */ static void ice_add_dvm_hint(struct ice_hw *hw, u16 val, bool enable) { … } /** * ice_add_tunnel_hint * @hw: pointer to the HW structure * @label_name: label text * @val: value of the tunnel port boost entry */ static void ice_add_tunnel_hint(struct ice_hw *hw, char *label_name, u16 val) { … } /** * ice_label_enum_handler * @sect_type: section type * @section: pointer to section * @index: index of the label entry to be returned * @offset: pointer to receive absolute offset, always zero for label sections * * This is a callback function that can be passed to ice_pkg_enum_entry. * Handles enumeration of individual label entries. */ static void *ice_label_enum_handler(u32 __always_unused sect_type, void *section, u32 index, u32 *offset) { … } /** * ice_enum_labels * @ice_seg: pointer to the ice segment (NULL on subsequent calls) * @type: the section type that will contain the label (0 on subsequent calls) * @state: ice_pkg_enum structure that will hold the state of the enumeration * @value: pointer to a value that will return the label's value if found * * Enumerates a list of labels in the package. The caller will call * ice_enum_labels(ice_seg, type, ...) to start the enumeration, then call * ice_enum_labels(NULL, 0, ...) to continue. When the function returns a NULL * the end of the list has been reached. */ static char *ice_enum_labels(struct ice_seg *ice_seg, u32 type, struct ice_pkg_enum *state, u16 *value) { … } /** * ice_boost_tcam_handler * @sect_type: section type * @section: pointer to section * @index: index of the boost TCAM entry to be returned * @offset: pointer to receive absolute offset, always 0 for boost TCAM sections * * This is a callback function that can be passed to ice_pkg_enum_entry. * Handles enumeration of individual boost TCAM entries. */ static void *ice_boost_tcam_handler(u32 sect_type, void *section, u32 index, u32 *offset) { … } /** * ice_find_boost_entry * @ice_seg: pointer to the ice segment (non-NULL) * @addr: Boost TCAM address of entry to search for * @entry: returns pointer to the entry * * Finds a particular Boost TCAM entry and returns a pointer to that entry * if it is found. The ice_seg parameter must not be NULL since the first call * to ice_pkg_enum_entry requires a pointer to an actual ice_segment structure. */ static int ice_find_boost_entry(struct ice_seg *ice_seg, u16 addr, struct ice_boost_tcam_entry **entry) { … } /** * ice_is_init_pkg_successful - check if DDP init was successful * @state: state of the DDP pkg after download */ bool ice_is_init_pkg_successful(enum ice_ddp_state state) { … } /** * ice_pkg_buf_alloc * @hw: pointer to the HW structure * * Allocates a package buffer and returns a pointer to the buffer header. * Note: all package contents must be in Little Endian form. */ struct ice_buf_build *ice_pkg_buf_alloc(struct ice_hw *hw) { … } static bool ice_is_gtp_u_profile(u16 prof_idx) { … } static bool ice_is_gtp_c_profile(u16 prof_idx) { … } static bool ice_is_pfcp_profile(u16 prof_idx) { … } /** * ice_get_sw_prof_type - determine switch profile type * @hw: pointer to the HW structure * @fv: pointer to the switch field vector * @prof_idx: profile index to check */ static enum ice_prof_type ice_get_sw_prof_type(struct ice_hw *hw, struct ice_fv *fv, u32 prof_idx) { … } /** * ice_get_sw_fv_bitmap - Get switch field vector bitmap based on profile type * @hw: pointer to hardware structure * @req_profs: type of profiles requested * @bm: pointer to memory for returning the bitmap of field vectors */ void ice_get_sw_fv_bitmap(struct ice_hw *hw, enum ice_prof_type req_profs, unsigned long *bm) { … } /** * ice_get_sw_fv_list * @hw: pointer to the HW structure * @lkups: list of protocol types * @bm: bitmap of field vectors to consider * @fv_list: Head of a list * * Finds all the field vector entries from switch block that contain * a given protocol ID and offset and returns a list of structures of type * "ice_sw_fv_list_entry". Every structure in the list has a field vector * definition and profile ID information * NOTE: The caller of the function is responsible for freeing the memory * allocated for every list entry. */ int ice_get_sw_fv_list(struct ice_hw *hw, struct ice_prot_lkup_ext *lkups, unsigned long *bm, struct list_head *fv_list) { … } /** * ice_init_prof_result_bm - Initialize the profile result index bitmap * @hw: pointer to hardware structure */ void ice_init_prof_result_bm(struct ice_hw *hw) { … } /** * ice_pkg_buf_free * @hw: pointer to the HW structure * @bld: pointer to pkg build (allocated by ice_pkg_buf_alloc()) * * Frees a package buffer */ void ice_pkg_buf_free(struct ice_hw *hw, struct ice_buf_build *bld) { … } /** * ice_pkg_buf_reserve_section * @bld: pointer to pkg build (allocated by ice_pkg_buf_alloc()) * @count: the number of sections to reserve * * Reserves one or more section table entries in a package buffer. This routine * can be called multiple times as long as they are made before calling * ice_pkg_buf_alloc_section(). Once ice_pkg_buf_alloc_section() * is called once, the number of sections that can be allocated will not be able * to be increased; not using all reserved sections is fine, but this will * result in some wasted space in the buffer. * Note: all package contents must be in Little Endian form. */ int ice_pkg_buf_reserve_section(struct ice_buf_build *bld, u16 count) { … } /** * ice_pkg_buf_alloc_section * @bld: pointer to pkg build (allocated by ice_pkg_buf_alloc()) * @type: the section type value * @size: the size of the section to reserve (in bytes) * * Reserves memory in the buffer for a section's content and updates the * buffers' status accordingly. This routine returns a pointer to the first * byte of the section start within the buffer, which is used to fill in the * section contents. * Note: all package contents must be in Little Endian form. */ void *ice_pkg_buf_alloc_section(struct ice_buf_build *bld, u32 type, u16 size) { … } /** * ice_pkg_buf_alloc_single_section * @hw: pointer to the HW structure * @type: the section type value * @size: the size of the section to reserve (in bytes) * @section: returns pointer to the section * * Allocates a package buffer with a single section. * Note: all package contents must be in Little Endian form. */ struct ice_buf_build *ice_pkg_buf_alloc_single_section(struct ice_hw *hw, u32 type, u16 size, void **section) { … } /** * ice_pkg_buf_get_active_sections * @bld: pointer to pkg build (allocated by ice_pkg_buf_alloc()) * * Returns the number of active sections. Before using the package buffer * in an update package command, the caller should make sure that there is at * least one active section - otherwise, the buffer is not legal and should * not be used. * Note: all package contents must be in Little Endian form. */ u16 ice_pkg_buf_get_active_sections(struct ice_buf_build *bld) { … } /** * ice_pkg_buf * @bld: pointer to pkg build (allocated by ice_pkg_buf_alloc()) * * Return a pointer to the buffer's header */ struct ice_buf *ice_pkg_buf(struct ice_buf_build *bld) { … } static enum ice_ddp_state ice_map_aq_err_to_ddp_state(enum ice_aq_err aq_err) { … } /** * ice_acquire_global_cfg_lock * @hw: pointer to the HW structure * @access: access type (read or write) * * This function will request ownership of the global config lock for reading * or writing of the package. When attempting to obtain write access, the * caller must check for the following two return values: * * 0 - Means the caller has acquired the global config lock * and can perform writing of the package. * -EALREADY - Indicates another driver has already written the * package or has found that no update was necessary; in * this case, the caller can just skip performing any * update of the package. */ static int ice_acquire_global_cfg_lock(struct ice_hw *hw, enum ice_aq_res_access_type access) { … } /** * ice_release_global_cfg_lock * @hw: pointer to the HW structure * * This function will release the global config lock. */ static void ice_release_global_cfg_lock(struct ice_hw *hw) { … } /** * ice_aq_download_pkg * @hw: pointer to the hardware structure * @pkg_buf: the package buffer to transfer * @buf_size: the size of the package buffer * @last_buf: last buffer indicator * @error_offset: returns error offset * @error_info: returns error information * @cd: pointer to command details structure or NULL * * Download Package (0x0C40) */ static int ice_aq_download_pkg(struct ice_hw *hw, struct ice_buf_hdr *pkg_buf, u16 buf_size, bool last_buf, u32 *error_offset, u32 *error_info, struct ice_sq_cd *cd) { … } /** * ice_get_pkg_seg_by_idx * @pkg_hdr: pointer to the package header to be searched * @idx: index of segment */ static struct ice_generic_seg_hdr * ice_get_pkg_seg_by_idx(struct ice_pkg_hdr *pkg_hdr, u32 idx) { … } /** * ice_is_signing_seg_at_idx - determine if segment is a signing segment * @pkg_hdr: pointer to package header * @idx: segment index */ static bool ice_is_signing_seg_at_idx(struct ice_pkg_hdr *pkg_hdr, u32 idx) { … } /** * ice_is_signing_seg_type_at_idx * @pkg_hdr: pointer to package header * @idx: segment index * @seg_id: segment id that is expected * @sign_type: signing type * * Determine if a segment is a signing segment of the correct type */ static bool ice_is_signing_seg_type_at_idx(struct ice_pkg_hdr *pkg_hdr, u32 idx, u32 seg_id, u32 sign_type) { … } /** * ice_is_buffer_metadata - determine if package buffer is a metadata buffer * @buf: pointer to buffer header */ static bool ice_is_buffer_metadata(struct ice_buf_hdr *buf) { … } /** * ice_is_last_download_buffer * @buf: pointer to current buffer header * @idx: index of the buffer in the current sequence * @count: the buffer count in the current sequence * * Note: this routine should only be called if the buffer is not the last buffer */ static bool ice_is_last_download_buffer(struct ice_buf_hdr *buf, u32 idx, u32 count) { … } /** * ice_dwnld_cfg_bufs_no_lock * @hw: pointer to the hardware structure * @bufs: pointer to an array of buffers * @start: buffer index of first buffer to download * @count: the number of buffers to download * @indicate_last: if true, then set last buffer flag on last buffer download * * Downloads package configuration buffers to the firmware. Metadata buffers * are skipped, and the first metadata buffer found indicates that the rest * of the buffers are all metadata buffers. */ static enum ice_ddp_state ice_dwnld_cfg_bufs_no_lock(struct ice_hw *hw, struct ice_buf *bufs, u32 start, u32 count, bool indicate_last) { … } /** * ice_download_pkg_sig_seg - download a signature segment * @hw: pointer to the hardware structure * @seg: pointer to signature segment */ static enum ice_ddp_state ice_download_pkg_sig_seg(struct ice_hw *hw, struct ice_sign_seg *seg) { … } /** * ice_download_pkg_config_seg - download a config segment * @hw: pointer to the hardware structure * @pkg_hdr: pointer to package header * @idx: segment index * @start: starting buffer * @count: buffer count * * Note: idx must reference a ICE segment */ static enum ice_ddp_state ice_download_pkg_config_seg(struct ice_hw *hw, struct ice_pkg_hdr *pkg_hdr, u32 idx, u32 start, u32 count) { … } /** * ice_dwnld_sign_and_cfg_segs - download a signing segment and config segment * @hw: pointer to the hardware structure * @pkg_hdr: pointer to package header * @idx: segment index (must be a signature segment) * * Note: idx must reference a signature segment */ static enum ice_ddp_state ice_dwnld_sign_and_cfg_segs(struct ice_hw *hw, struct ice_pkg_hdr *pkg_hdr, u32 idx) { … } /** * ice_match_signing_seg - determine if a matching signing segment exists * @pkg_hdr: pointer to package header * @seg_id: segment id that is expected * @sign_type: signing type */ static bool ice_match_signing_seg(struct ice_pkg_hdr *pkg_hdr, u32 seg_id, u32 sign_type) { … } /** * ice_post_dwnld_pkg_actions - perform post download package actions * @hw: pointer to the hardware structure */ static enum ice_ddp_state ice_post_dwnld_pkg_actions(struct ice_hw *hw) { … } /** * ice_download_pkg_with_sig_seg * @hw: pointer to the hardware structure * @pkg_hdr: pointer to package header * * Handles the download of a complete package. */ static enum ice_ddp_state ice_download_pkg_with_sig_seg(struct ice_hw *hw, struct ice_pkg_hdr *pkg_hdr) { … } /** * ice_dwnld_cfg_bufs * @hw: pointer to the hardware structure * @bufs: pointer to an array of buffers * @count: the number of buffers in the array * * Obtains global config lock and downloads the package configuration buffers * to the firmware. */ static enum ice_ddp_state ice_dwnld_cfg_bufs(struct ice_hw *hw, struct ice_buf *bufs, u32 count) { … } /** * ice_download_pkg_without_sig_seg * @hw: pointer to the hardware structure * @ice_seg: pointer to the segment of the package to be downloaded * * Handles the download of a complete package without signature segment. */ static enum ice_ddp_state ice_download_pkg_without_sig_seg(struct ice_hw *hw, struct ice_seg *ice_seg) { … } /** * ice_download_pkg * @hw: pointer to the hardware structure * @pkg_hdr: pointer to package header * @ice_seg: pointer to the segment of the package to be downloaded * * Handles the download of a complete package. */ static enum ice_ddp_state ice_download_pkg(struct ice_hw *hw, struct ice_pkg_hdr *pkg_hdr, struct ice_seg *ice_seg) { … } /** * ice_aq_get_pkg_info_list * @hw: pointer to the hardware structure * @pkg_info: the buffer which will receive the information list * @buf_size: the size of the pkg_info information buffer * @cd: pointer to command details structure or NULL * * Get Package Info List (0x0C43) */ static int ice_aq_get_pkg_info_list(struct ice_hw *hw, struct ice_aqc_get_pkg_info_resp *pkg_info, u16 buf_size, struct ice_sq_cd *cd) { … } /** * ice_aq_update_pkg * @hw: pointer to the hardware structure * @pkg_buf: the package cmd buffer * @buf_size: the size of the package cmd buffer * @last_buf: last buffer indicator * @error_offset: returns error offset * @error_info: returns error information * @cd: pointer to command details structure or NULL * * Update Package (0x0C42) */ static int ice_aq_update_pkg(struct ice_hw *hw, struct ice_buf_hdr *pkg_buf, u16 buf_size, bool last_buf, u32 *error_offset, u32 *error_info, struct ice_sq_cd *cd) { … } /** * ice_aq_upload_section * @hw: pointer to the hardware structure * @pkg_buf: the package buffer which will receive the section * @buf_size: the size of the package buffer * @cd: pointer to command details structure or NULL * * Upload Section (0x0C41) */ int ice_aq_upload_section(struct ice_hw *hw, struct ice_buf_hdr *pkg_buf, u16 buf_size, struct ice_sq_cd *cd) { … } /** * ice_update_pkg_no_lock * @hw: pointer to the hardware structure * @bufs: pointer to an array of buffers * @count: the number of buffers in the array */ int ice_update_pkg_no_lock(struct ice_hw *hw, struct ice_buf *bufs, u32 count) { … } /** * ice_update_pkg * @hw: pointer to the hardware structure * @bufs: pointer to an array of buffers * @count: the number of buffers in the array * * Obtains change lock and updates package. */ int ice_update_pkg(struct ice_hw *hw, struct ice_buf *bufs, u32 count) { … } /** * ice_find_seg_in_pkg * @hw: pointer to the hardware structure * @seg_type: the segment type to search for (i.e., SEGMENT_TYPE_CPK) * @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. */ static const struct ice_generic_seg_hdr * ice_find_seg_in_pkg(struct ice_hw *hw, u32 seg_type, const struct ice_pkg_hdr *pkg_hdr) { … } /** * ice_has_signing_seg - determine if package has a signing segment * @hw: pointer to the hardware structure * @pkg_hdr: pointer to the driver's package hdr */ static bool ice_has_signing_seg(struct ice_hw *hw, struct ice_pkg_hdr *pkg_hdr) { … } /** * ice_get_pkg_segment_id - get correct package segment id, based on device * @mac_type: MAC type of the device */ static u32 ice_get_pkg_segment_id(enum ice_mac_type mac_type) { … } /** * ice_get_pkg_sign_type - get package segment sign type, based on device * @mac_type: MAC type of the device */ static u32 ice_get_pkg_sign_type(enum ice_mac_type mac_type) { … } /** * ice_get_signing_req - get correct package requirements, based on device * @hw: pointer to the hardware structure */ static void ice_get_signing_req(struct ice_hw *hw) { … } /** * ice_init_pkg_info * @hw: pointer to the hardware structure * @pkg_hdr: pointer to the driver's package hdr * * Saves off the package details into the HW structure. */ static enum ice_ddp_state ice_init_pkg_info(struct ice_hw *hw, struct ice_pkg_hdr *pkg_hdr) { … } /** * ice_get_pkg_info * @hw: pointer to the hardware structure * * Store details of the package currently loaded in HW into the HW structure. */ static enum ice_ddp_state ice_get_pkg_info(struct ice_hw *hw) { … } /** * ice_chk_pkg_compat * @hw: pointer to the hardware structure * @ospkg: pointer to the package hdr * @seg: pointer to the package segment hdr * * This function checks the package version compatibility with driver and NVM */ static enum ice_ddp_state ice_chk_pkg_compat(struct ice_hw *hw, struct ice_pkg_hdr *ospkg, struct ice_seg **seg) { … } /** * ice_init_pkg_hints * @hw: pointer to the HW structure * @ice_seg: pointer to the segment of the package scan (non-NULL) * * This function will scan the package and save off relevant information * (hints or metadata) for driver use. The ice_seg parameter must not be NULL * since the first call to ice_enum_labels requires a pointer to an actual * ice_seg structure. */ static void ice_init_pkg_hints(struct ice_hw *hw, struct ice_seg *ice_seg) { … } /** * ice_fill_hw_ptype - fill the enabled PTYPE bit information * @hw: pointer to the HW structure */ static void ice_fill_hw_ptype(struct ice_hw *hw) { … } /** * ice_init_pkg - initialize/download package * @hw: pointer to the hardware structure * @buf: pointer to the package buffer * @len: size of the package buffer * * This function initializes a package. The package contains HW tables * required to do packet processing. First, the function extracts package * information such as version. Then it finds the ice configuration segment * within the package; this function then saves a copy of the segment pointer * within the supplied package buffer. Next, the function will cache any hints * from the package, followed by downloading the package itself. Note, that if * a previous PF driver has already downloaded the package successfully, then * the current driver will not have to download the package again. * * The local package contents will be used to query default behavior and to * update specific sections of the HW's version of the package (e.g. to update * the parse graph to understand new protocols). * * This function stores a pointer to the package buffer memory, and it is * expected that the supplied buffer will not be freed immediately. If the * package buffer needs to be freed, such as when read from a file, use * ice_copy_and_init_pkg() instead of directly calling ice_init_pkg() in this * case. */ enum ice_ddp_state ice_init_pkg(struct ice_hw *hw, u8 *buf, u32 len) { … } /** * ice_copy_and_init_pkg - initialize/download a copy of the package * @hw: pointer to the hardware structure * @buf: pointer to the package buffer * @len: size of the package buffer * * This function copies the package buffer, and then calls ice_init_pkg() to * initialize the copied package contents. * * The copying is necessary if the package buffer supplied is constant, or if * the memory may disappear shortly after calling this function. * * If the package buffer resides in the data segment and can be modified, the * caller is free to use ice_init_pkg() instead of ice_copy_and_init_pkg(). * * However, if the package buffer needs to be copied first, such as when being * read from a file, the caller should use ice_copy_and_init_pkg(). * * This function will first copy the package buffer, before calling * ice_init_pkg(). The caller is free to immediately destroy the original * package buffer, as the new copy will be managed by this function and * related routines. */ enum ice_ddp_state ice_copy_and_init_pkg(struct ice_hw *hw, const u8 *buf, u32 len) { … } /** * ice_get_set_tx_topo - get or set Tx topology * @hw: pointer to the HW struct * @buf: pointer to Tx topology buffer * @buf_size: buffer size * @cd: pointer to command details structure or NULL * @flags: pointer to descriptor flags * @set: 0-get, 1-set topology * * The function will get or set Tx topology * * Return: zero when set was successful, negative values otherwise. */ static int ice_get_set_tx_topo(struct ice_hw *hw, u8 *buf, u16 buf_size, struct ice_sq_cd *cd, u8 *flags, bool set) { … } /** * ice_cfg_tx_topo - Initialize new Tx topology if available * @hw: pointer to the HW struct * @buf: pointer to Tx topology buffer * @len: buffer size * * The function will apply the new Tx topology from the package buffer * if available. * * Return: zero when update was successful, negative values otherwise. */ int ice_cfg_tx_topo(struct ice_hw *hw, const void *buf, u32 len) { … }