ice: implement snapshot for device capabilities
Add a new devlink region used for capturing a snapshot of the device capabilities buffer which is reported by the firmware over the AdminQ. This information can useful in debugging driver and firmware interactions. Signed-off-by: Jacob Keller <jacob.e.keller@intel.com> Tested-by: Andrew Bowers <andrewx.bowers@intel.com> Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
This commit is contained in:
		
							parent
							
								
									2b04a66156
								
							
						
					
					
						commit
						8d7aab3515
					
				| @ -373,6 +373,7 @@ struct ice_pf { | |||||||
| 	struct devlink_port devlink_port; | 	struct devlink_port devlink_port; | ||||||
| 
 | 
 | ||||||
| 	struct devlink_region *nvm_region; | 	struct devlink_region *nvm_region; | ||||||
|  | 	struct devlink_region *devcaps_region; | ||||||
| 
 | 
 | ||||||
| 	/* OS reserved IRQ details */ | 	/* OS reserved IRQ details */ | ||||||
| 	struct msix_entry *msix_entries; | 	struct msix_entry *msix_entries; | ||||||
|  | |||||||
| @ -1823,20 +1823,27 @@ ice_parse_caps(struct ice_hw *hw, void *buf, u32 cap_count, | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /**
 | /**
 | ||||||
|  * ice_aq_discover_caps - query function/device capabilities |  * ice_aq_list_caps - query function/device capabilities | ||||||
|  * @hw: pointer to the HW struct |  * @hw: pointer to the HW struct | ||||||
|  * @buf: a virtual buffer to hold the capabilities |  * @buf: a buffer to hold the capabilities | ||||||
|  * @buf_size: Size of the virtual buffer |  * @buf_size: size of the buffer | ||||||
|  * @cap_count: cap count needed if AQ err==ENOMEM |  * @cap_count: if not NULL, set to the number of capabilities reported | ||||||
|  * @opc: capabilities type to discover - pass in the command opcode |  * @opc: capabilities type to discover, device or function | ||||||
|  * @cd: pointer to command details structure or NULL |  * @cd: pointer to command details structure or NULL | ||||||
|  * |  * | ||||||
|  * Get the function(0x000a)/device(0x000b) capabilities description from |  * Get the function (0x000A) or device (0x000B) capabilities description from | ||||||
|  * the firmware. |  * firmware and store it in the buffer. | ||||||
|  |  * | ||||||
|  |  * If the cap_count pointer is not NULL, then it is set to the number of | ||||||
|  |  * capabilities firmware will report. Note that if the buffer size is too | ||||||
|  |  * small, it is possible the command will return ICE_AQ_ERR_ENOMEM. The | ||||||
|  |  * cap_count will still be updated in this case. It is recommended that the | ||||||
|  |  * buffer size be set to ICE_AQ_MAX_BUF_LEN (the largest possible buffer that | ||||||
|  |  * firmware could return) to avoid this. | ||||||
|  */ |  */ | ||||||
| static enum ice_status | enum ice_status | ||||||
| ice_aq_discover_caps(struct ice_hw *hw, void *buf, u16 buf_size, u32 *cap_count, | ice_aq_list_caps(struct ice_hw *hw, void *buf, u16 buf_size, u32 *cap_count, | ||||||
| 		     enum ice_adminq_opc opc, struct ice_sq_cd *cd) | 		 enum ice_adminq_opc opc, struct ice_sq_cd *cd) | ||||||
| { | { | ||||||
| 	struct ice_aqc_list_caps *cmd; | 	struct ice_aqc_list_caps *cmd; | ||||||
| 	struct ice_aq_desc desc; | 	struct ice_aq_desc desc; | ||||||
| @ -1849,12 +1856,43 @@ ice_aq_discover_caps(struct ice_hw *hw, void *buf, u16 buf_size, u32 *cap_count, | |||||||
| 		return ICE_ERR_PARAM; | 		return ICE_ERR_PARAM; | ||||||
| 
 | 
 | ||||||
| 	ice_fill_dflt_direct_cmd_desc(&desc, opc); | 	ice_fill_dflt_direct_cmd_desc(&desc, opc); | ||||||
| 
 |  | ||||||
| 	status = ice_aq_send_cmd(hw, &desc, buf, buf_size, cd); | 	status = ice_aq_send_cmd(hw, &desc, buf, buf_size, cd); | ||||||
| 	if (!status) | 
 | ||||||
| 		ice_parse_caps(hw, buf, le32_to_cpu(cmd->count), opc); | 	if (cap_count) | ||||||
| 	else if (hw->adminq.sq_last_status == ICE_AQ_RC_ENOMEM) |  | ||||||
| 		*cap_count = le32_to_cpu(cmd->count); | 		*cap_count = le32_to_cpu(cmd->count); | ||||||
|  | 
 | ||||||
|  | 	return status; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * ice_aq_discover_caps - query function/device capabilities | ||||||
|  |  * @hw: pointer to the HW struct | ||||||
|  |  * @buf: a virtual buffer to hold the capabilities | ||||||
|  |  * @buf_size: Size of the virtual buffer | ||||||
|  |  * @cap_count: cap count needed if AQ err==ENOMEM | ||||||
|  |  * @opc: capabilities type to discover - pass in the command opcode | ||||||
|  |  * @cd: pointer to command details structure or NULL | ||||||
|  |  * | ||||||
|  |  * Get the function(0x000a)/device(0x000b) capabilities description from | ||||||
|  |  * the firmware. | ||||||
|  |  * | ||||||
|  |  * NOTE: this function has the side effect of updating the hw->dev_caps or | ||||||
|  |  * hw->func_caps by way of calling ice_parse_caps. | ||||||
|  |  */ | ||||||
|  | static enum ice_status | ||||||
|  | ice_aq_discover_caps(struct ice_hw *hw, void *buf, u16 buf_size, u32 *cap_count, | ||||||
|  | 		     enum ice_adminq_opc opc, struct ice_sq_cd *cd) | ||||||
|  | { | ||||||
|  | 	u32 local_cap_count = 0; | ||||||
|  | 	enum ice_status status; | ||||||
|  | 
 | ||||||
|  | 	status = ice_aq_list_caps(hw, buf, buf_size, &local_cap_count, | ||||||
|  | 				  opc, cd); | ||||||
|  | 	if (!status) | ||||||
|  | 		ice_parse_caps(hw, buf, local_cap_count, opc); | ||||||
|  | 	else if (hw->adminq.sq_last_status == ICE_AQ_RC_ENOMEM) | ||||||
|  | 		*cap_count = local_cap_count; | ||||||
|  | 
 | ||||||
| 	return status; | 	return status; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -87,6 +87,9 @@ enum ice_status | |||||||
| ice_aq_get_phy_caps(struct ice_port_info *pi, bool qual_mods, u8 report_mode, | ice_aq_get_phy_caps(struct ice_port_info *pi, bool qual_mods, u8 report_mode, | ||||||
| 		    struct ice_aqc_get_phy_caps_data *caps, | 		    struct ice_aqc_get_phy_caps_data *caps, | ||||||
| 		    struct ice_sq_cd *cd); | 		    struct ice_sq_cd *cd); | ||||||
|  | enum ice_status | ||||||
|  | ice_aq_list_caps(struct ice_hw *hw, void *buf, u16 buf_size, u32 *cap_count, | ||||||
|  | 		 enum ice_adminq_opc opc, struct ice_sq_cd *cd); | ||||||
| void | void | ||||||
| ice_update_phy_type(u64 *phy_type_low, u64 *phy_type_high, | ice_update_phy_type(u64 *phy_type_low, u64 *phy_type_high, | ||||||
| 		    u16 link_speeds_bitmap); | 		    u16 link_speeds_bitmap); | ||||||
|  | |||||||
| @ -397,12 +397,60 @@ static int ice_devlink_nvm_snapshot(struct devlink *devlink, | |||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | /**
 | ||||||
|  |  * ice_devlink_devcaps_snapshot - Capture snapshot of device capabilities | ||||||
|  |  * @devlink: the devlink instance | ||||||
|  |  * @extack: extended ACK response structure | ||||||
|  |  * @data: on exit points to snapshot data buffer | ||||||
|  |  * | ||||||
|  |  * This function is called in response to the DEVLINK_CMD_REGION_TRIGGER for | ||||||
|  |  * the device-caps devlink region. It captures a snapshot of the device | ||||||
|  |  * capabilities reported by firmware. | ||||||
|  |  * | ||||||
|  |  * @returns zero on success, and updates the data pointer. Returns a non-zero | ||||||
|  |  * error code on failure. | ||||||
|  |  */ | ||||||
|  | static int | ||||||
|  | ice_devlink_devcaps_snapshot(struct devlink *devlink, | ||||||
|  | 			     struct netlink_ext_ack *extack, u8 **data) | ||||||
|  | { | ||||||
|  | 	struct ice_pf *pf = devlink_priv(devlink); | ||||||
|  | 	struct device *dev = ice_pf_to_dev(pf); | ||||||
|  | 	struct ice_hw *hw = &pf->hw; | ||||||
|  | 	enum ice_status status; | ||||||
|  | 	void *devcaps; | ||||||
|  | 
 | ||||||
|  | 	devcaps = vzalloc(ICE_AQ_MAX_BUF_LEN); | ||||||
|  | 	if (!devcaps) | ||||||
|  | 		return -ENOMEM; | ||||||
|  | 
 | ||||||
|  | 	status = ice_aq_list_caps(hw, devcaps, ICE_AQ_MAX_BUF_LEN, NULL, | ||||||
|  | 				  ice_aqc_opc_list_dev_caps, NULL); | ||||||
|  | 	if (status) { | ||||||
|  | 		dev_dbg(dev, "ice_aq_list_caps: failed to read device capabilities, err %d aq_err %d\n", | ||||||
|  | 			status, hw->adminq.sq_last_status); | ||||||
|  | 		NL_SET_ERR_MSG_MOD(extack, "Failed to read device capabilities"); | ||||||
|  | 		vfree(devcaps); | ||||||
|  | 		return -EIO; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	*data = (u8 *)devcaps; | ||||||
|  | 
 | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| static const struct devlink_region_ops ice_nvm_region_ops = { | static const struct devlink_region_ops ice_nvm_region_ops = { | ||||||
| 	.name = "nvm-flash", | 	.name = "nvm-flash", | ||||||
| 	.destructor = vfree, | 	.destructor = vfree, | ||||||
| 	.snapshot = ice_devlink_nvm_snapshot, | 	.snapshot = ice_devlink_nvm_snapshot, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | static const struct devlink_region_ops ice_devcaps_region_ops = { | ||||||
|  | 	.name = "device-caps", | ||||||
|  | 	.destructor = vfree, | ||||||
|  | 	.snapshot = ice_devlink_devcaps_snapshot, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| /**
 | /**
 | ||||||
|  * ice_devlink_init_regions - Initialize devlink regions |  * ice_devlink_init_regions - Initialize devlink regions | ||||||
|  * @pf: the PF device structure |  * @pf: the PF device structure | ||||||
| @ -424,6 +472,15 @@ void ice_devlink_init_regions(struct ice_pf *pf) | |||||||
| 			PTR_ERR(pf->nvm_region)); | 			PTR_ERR(pf->nvm_region)); | ||||||
| 		pf->nvm_region = NULL; | 		pf->nvm_region = NULL; | ||||||
| 	} | 	} | ||||||
|  | 
 | ||||||
|  | 	pf->devcaps_region = devlink_region_create(devlink, | ||||||
|  | 						   &ice_devcaps_region_ops, 10, | ||||||
|  | 						   ICE_AQ_MAX_BUF_LEN); | ||||||
|  | 	if (IS_ERR(pf->devcaps_region)) { | ||||||
|  | 		dev_err(dev, "failed to create device-caps devlink region, err %ld\n", | ||||||
|  | 			PTR_ERR(pf->devcaps_region)); | ||||||
|  | 		pf->devcaps_region = NULL; | ||||||
|  | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /**
 | /**
 | ||||||
| @ -436,4 +493,6 @@ void ice_devlink_destroy_regions(struct ice_pf *pf) | |||||||
| { | { | ||||||
| 	if (pf->nvm_region) | 	if (pf->nvm_region) | ||||||
| 		devlink_region_destroy(pf->nvm_region); | 		devlink_region_destroy(pf->nvm_region); | ||||||
|  | 	if (pf->devcaps_region) | ||||||
|  | 		devlink_region_destroy(pf->devcaps_region); | ||||||
| } | } | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user