Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

soc: qcom: mdt_loader: Extract PAS operations

Rather than passing a boolean to indicate if the PAS operations should
be performed from within __mdt_load(), extract them to their own helper
function.

This will allow clients to invoke this directly, with some
qcom_scm_pas_metadata context that they later needs to release, without
further having to complicate the prototype of qcom_mdt_load().

Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
Link: https://lore.kernel.org/r/20220128025513.97188-9-bjorn.andersson@linaro.org

+85 -36
+74 -36
drivers/soc/qcom/mdt_loader.c
··· 188 188 } 189 189 EXPORT_SYMBOL_GPL(qcom_mdt_read_metadata); 190 190 191 + /** 192 + * qcom_mdt_pas_init() - initialize PAS region for firmware loading 193 + * @dev: device handle to associate resources with 194 + * @fw: firmware object for the mdt file 195 + * @firmware: name of the firmware, for construction of segment file names 196 + * @pas_id: PAS identifier 197 + * @mem_phys: physical address of allocated memory region 198 + * @ctx: PAS metadata context, to be released by caller 199 + * 200 + * Returns 0 on success, negative errno otherwise. 201 + */ 202 + int qcom_mdt_pas_init(struct device *dev, const struct firmware *fw, 203 + const char *fw_name, int pas_id, phys_addr_t mem_phys, 204 + struct qcom_scm_pas_metadata *ctx) 205 + { 206 + const struct elf32_phdr *phdrs; 207 + const struct elf32_phdr *phdr; 208 + const struct elf32_hdr *ehdr; 209 + phys_addr_t min_addr = PHYS_ADDR_MAX; 210 + phys_addr_t max_addr = 0; 211 + size_t metadata_len; 212 + void *metadata; 213 + int ret; 214 + int i; 215 + 216 + ehdr = (struct elf32_hdr *)fw->data; 217 + phdrs = (struct elf32_phdr *)(ehdr + 1); 218 + 219 + for (i = 0; i < ehdr->e_phnum; i++) { 220 + phdr = &phdrs[i]; 221 + 222 + if (!mdt_phdr_valid(phdr)) 223 + continue; 224 + 225 + if (phdr->p_paddr < min_addr) 226 + min_addr = phdr->p_paddr; 227 + 228 + if (phdr->p_paddr + phdr->p_memsz > max_addr) 229 + max_addr = ALIGN(phdr->p_paddr + phdr->p_memsz, SZ_4K); 230 + } 231 + 232 + metadata = qcom_mdt_read_metadata(fw, &metadata_len, fw_name, dev); 233 + if (IS_ERR(metadata)) { 234 + ret = PTR_ERR(metadata); 235 + dev_err(dev, "error %d reading firmware %s metadata\n", ret, fw_name); 236 + goto out; 237 + } 238 + 239 + ret = qcom_scm_pas_init_image(pas_id, metadata, metadata_len, ctx); 240 + kfree(metadata); 241 + if (ret) { 242 + /* Invalid firmware metadata */ 243 + dev_err(dev, "error %d initializing firmware %s\n", ret, fw_name); 244 + goto out; 245 + } 246 + 247 + ret = qcom_scm_pas_mem_setup(pas_id, mem_phys, max_addr - min_addr); 248 + if (ret) { 249 + /* Unable to set up relocation */ 250 + dev_err(dev, "error %d setting up firmware %s\n", ret, fw_name); 251 + goto out; 252 + } 253 + 254 + out: 255 + return ret; 256 + } 257 + EXPORT_SYMBOL_GPL(qcom_mdt_pas_init); 258 + 191 259 static int __qcom_mdt_load(struct device *dev, const struct firmware *fw, 192 260 const char *fw_name, int pas_id, void *mem_region, 193 261 phys_addr_t mem_phys, size_t mem_size, ··· 266 198 const struct elf32_hdr *ehdr; 267 199 phys_addr_t mem_reloc; 268 200 phys_addr_t min_addr = PHYS_ADDR_MAX; 269 - phys_addr_t max_addr = 0; 270 - size_t metadata_len; 271 201 ssize_t offset; 272 - void *metadata; 273 202 bool relocate = false; 274 203 void *ptr; 275 204 int ret = 0; ··· 289 224 290 225 if (phdr->p_paddr < min_addr) 291 226 min_addr = phdr->p_paddr; 292 - 293 - if (phdr->p_paddr + phdr->p_memsz > max_addr) 294 - max_addr = ALIGN(phdr->p_paddr + phdr->p_memsz, SZ_4K); 295 - } 296 - 297 - if (pas_init) { 298 - metadata = qcom_mdt_read_metadata(fw, &metadata_len, fw_name, dev); 299 - if (IS_ERR(metadata)) { 300 - ret = PTR_ERR(metadata); 301 - dev_err(dev, "error %d reading firmware %s metadata\n", 302 - ret, fw_name); 303 - goto out; 304 - } 305 - 306 - ret = qcom_scm_pas_init_image(pas_id, metadata, metadata_len, NULL); 307 - 308 - kfree(metadata); 309 - if (ret) { 310 - /* Invalid firmware metadata */ 311 - dev_err(dev, "error %d initializing firmware %s\n", 312 - ret, fw_name); 313 - goto out; 314 - } 315 - 316 - ret = qcom_scm_pas_mem_setup(pas_id, mem_phys, max_addr - min_addr); 317 - if (ret) { 318 - /* Unable to set up relocation */ 319 - dev_err(dev, "error %d setting up firmware %s\n", 320 - ret, fw_name); 321 - goto out; 322 - } 323 227 } 324 228 325 229 if (relocate) { ··· 353 319 if (reloc_base) 354 320 *reloc_base = mem_reloc; 355 321 356 - out: 357 - 358 322 return ret; 359 323 } 360 324 ··· 374 342 phys_addr_t mem_phys, size_t mem_size, 375 343 phys_addr_t *reloc_base) 376 344 { 345 + int ret; 346 + 347 + ret = qcom_mdt_pas_init(dev, fw, firmware, pas_id, mem_phys, NULL); 348 + if (ret) 349 + return ret; 350 + 377 351 return __qcom_mdt_load(dev, fw, firmware, pas_id, mem_region, mem_phys, 378 352 mem_size, reloc_base, true); 379 353 }
+11
include/linux/soc/qcom/mdt_loader.h
··· 10 10 11 11 struct device; 12 12 struct firmware; 13 + struct qcom_scm_pas_metadata; 13 14 14 15 #if IS_ENABLED(CONFIG_QCOM_MDT_LOADER) 15 16 16 17 ssize_t qcom_mdt_get_size(const struct firmware *fw); 18 + int qcom_mdt_pas_init(struct device *dev, const struct firmware *fw, 19 + const char *fw_name, int pas_id, phys_addr_t mem_phys, 20 + struct qcom_scm_pas_metadata *pas_metadata_ctx); 17 21 int qcom_mdt_load(struct device *dev, const struct firmware *fw, 18 22 const char *fw_name, int pas_id, void *mem_region, 19 23 phys_addr_t mem_phys, size_t mem_size, ··· 33 29 #else /* !IS_ENABLED(CONFIG_QCOM_MDT_LOADER) */ 34 30 35 31 static inline ssize_t qcom_mdt_get_size(const struct firmware *fw) 32 + { 33 + return -ENODEV; 34 + } 35 + 36 + static inline int qcom_mdt_pas_init(struct device *dev, const struct firmware *fw, 37 + const char *fw_name, int pas_id, phys_addr_t mem_phys, 38 + struct qcom_scm_pas_metadata *pas_metadata_ctx) 36 39 { 37 40 return -ENODEV; 38 41 }