mirror of
				git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
				synced 2025-10-31 08:44:41 +00:00 
			
		
		
		
	wifi: iwlwifi: pnvm: handle memory descriptor tlv
When PNVM is obtained from UEFI, there's an additional memory descriptor TLV that has to be handled. It is the same TLV that holds data in the reduced power tables. Also, in this TLV, the actual data is located after address and size, so add the corresponding offset. Signed-off-by: Gregory Greenman <gregory.greenman@intel.com> Link: https://lore.kernel.org/r/20230606103519.8c5f5ee8e30b.Id1893c9dec140b5ba4abe8a121c2e1a1d121d2d7@changeid Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
		
							parent
							
								
									8ae3e23195
								
							
						
					
					
						commit
						372a714808
					
				
					 3 changed files with 59 additions and 17 deletions
				
			
		|  | @ -127,6 +127,11 @@ static int iwl_pnvm_handle_section(struct iwl_trans *trans, const u8 *data, | |||
| 
 | ||||
| 			break; | ||||
| 		} | ||||
| 		case IWL_UCODE_TLV_MEM_DESC: | ||||
| 			if (iwl_uefi_handle_tlv_mem_desc(trans, data, tlv_len, | ||||
| 							 pnvm_data)) | ||||
| 				return -EINVAL; | ||||
| 			break; | ||||
| 		case IWL_UCODE_TLV_PNVM_SKU: | ||||
| 			IWL_DEBUG_FW(trans, | ||||
| 				     "New PNVM section started, stop parsing.\n"); | ||||
|  |  | |||
|  | @ -17,6 +17,12 @@ | |||
| 				  0xb2, 0xec, 0xf5, 0xa3,	\ | ||||
| 				  0x59, 0x4f, 0x4a, 0xea) | ||||
| 
 | ||||
| struct iwl_uefi_pnvm_mem_desc { | ||||
| 	__le32 addr; | ||||
| 	__le32 size; | ||||
| 	const u8 data[]; | ||||
| } __packed; | ||||
| 
 | ||||
| static void *iwl_uefi_get_variable(efi_char16_t *name, efi_guid_t *guid, | ||||
| 				   unsigned long *data_size) | ||||
| { | ||||
|  | @ -70,6 +76,42 @@ void *iwl_uefi_get_pnvm(struct iwl_trans *trans, size_t *len) | |||
| 	return data; | ||||
| } | ||||
| 
 | ||||
| int iwl_uefi_handle_tlv_mem_desc(struct iwl_trans *trans, const u8 *data, | ||||
| 				 u32 tlv_len, struct iwl_pnvm_image *pnvm_data) | ||||
| { | ||||
| 	const struct iwl_uefi_pnvm_mem_desc *desc = (const void *)data; | ||||
| 	u32 data_len; | ||||
| 
 | ||||
| 	if (tlv_len < sizeof(*desc)) { | ||||
| 		IWL_DEBUG_FW(trans, "TLV len (%d) is too small\n", tlv_len); | ||||
| 		return -EINVAL; | ||||
| 	} | ||||
| 
 | ||||
| 	data_len = tlv_len - sizeof(*desc); | ||||
| 
 | ||||
| 	IWL_DEBUG_FW(trans, | ||||
| 		     "Handle IWL_UCODE_TLV_MEM_DESC, len %d data_len %d\n", | ||||
| 		     tlv_len, data_len); | ||||
| 
 | ||||
| 	if (le32_to_cpu(desc->size) != data_len) { | ||||
| 		IWL_DEBUG_FW(trans, "invalid mem desc size %d\n", desc->size); | ||||
| 		return -EINVAL; | ||||
| 	} | ||||
| 
 | ||||
| 	if (pnvm_data->n_chunks == IPC_DRAM_MAP_ENTRY_NUM_MAX) { | ||||
| 		IWL_DEBUG_FW(trans, "too many payloads to allocate in DRAM.\n"); | ||||
| 		return -EINVAL; | ||||
| 	} | ||||
| 
 | ||||
| 	IWL_DEBUG_FW(trans, "Adding data (size %d)\n", data_len); | ||||
| 
 | ||||
| 	pnvm_data->chunks[pnvm_data->n_chunks].data = desc->data; | ||||
| 	pnvm_data->chunks[pnvm_data->n_chunks].len = data_len; | ||||
| 	pnvm_data->n_chunks++; | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int iwl_uefi_reduce_power_section(struct iwl_trans *trans, | ||||
| 					 const u8 *data, size_t len, | ||||
| 					 struct iwl_pnvm_image *pnvm_data) | ||||
|  | @ -97,25 +139,11 @@ static int iwl_uefi_reduce_power_section(struct iwl_trans *trans, | |||
| 		data += sizeof(*tlv); | ||||
| 
 | ||||
| 		switch (tlv_type) { | ||||
| 		case IWL_UCODE_TLV_MEM_DESC: { | ||||
| 			IWL_DEBUG_FW(trans, | ||||
| 				     "Got IWL_UCODE_TLV_MEM_DESC len %d\n", | ||||
| 				     tlv_len); | ||||
| 
 | ||||
| 			if (pnvm_data->n_chunks == IPC_DRAM_MAP_ENTRY_NUM_MAX) { | ||||
| 				IWL_DEBUG_FW(trans, | ||||
| 				"too many payloads to allocate in DRAM.\n"); | ||||
| 		case IWL_UCODE_TLV_MEM_DESC: | ||||
| 			if (iwl_uefi_handle_tlv_mem_desc(trans, data, tlv_len, | ||||
| 							 pnvm_data)) | ||||
| 				return -EINVAL; | ||||
| 			} | ||||
| 
 | ||||
| 			IWL_DEBUG_FW(trans, "Adding data (size %d)\n", tlv_len); | ||||
| 
 | ||||
| 			pnvm_data->chunks[pnvm_data->n_chunks].data = data; | ||||
| 			pnvm_data->chunks[pnvm_data->n_chunks].len = tlv_len; | ||||
| 			pnvm_data->n_chunks++; | ||||
| 
 | ||||
| 			break; | ||||
| 		} | ||||
| 		case IWL_UCODE_TLV_PNVM_SKU: | ||||
| 			IWL_DEBUG_FW(trans, | ||||
| 				     "New REDUCE_POWER section started, stop parsing.\n"); | ||||
|  |  | |||
|  | @ -46,6 +46,8 @@ int iwl_uefi_reduce_power_parse(struct iwl_trans *trans, | |||
| 				const u8 *data, size_t len, | ||||
| 				struct iwl_pnvm_image *pnvm_data); | ||||
| void iwl_uefi_get_step_table(struct iwl_trans *trans); | ||||
| int iwl_uefi_handle_tlv_mem_desc(struct iwl_trans *trans, const u8 *data, | ||||
| 				 u32 tlv_len, struct iwl_pnvm_image *pnvm_data); | ||||
| #else /* CONFIG_EFI */ | ||||
| static inline void *iwl_uefi_get_pnvm(struct iwl_trans *trans, size_t *len) | ||||
| { | ||||
|  | @ -69,6 +71,13 @@ iwl_uefi_get_reduced_power(struct iwl_trans *trans, size_t *len) | |||
| static inline void iwl_uefi_get_step_table(struct iwl_trans *trans) | ||||
| { | ||||
| } | ||||
| 
 | ||||
| static inline int | ||||
| iwl_uefi_handle_tlv_mem_desc(struct iwl_trans *trans, const u8 *data, | ||||
| 			     u32 tlv_len, struct iwl_pnvm_image *pnvm_data) | ||||
| { | ||||
| 	return 0; | ||||
| } | ||||
| #endif /* CONFIG_EFI */ | ||||
| 
 | ||||
| #if defined(CONFIG_EFI) && defined(CONFIG_ACPI) | ||||
|  |  | |||
		Loading…
	
	Add table
		
		Reference in a new issue
	
	 Gregory Greenman
						Gregory Greenman