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

Configure Feed

Select the types of activity you want to include in your feed.

soc: qcom: smem: better track SMEM uninitialized state

There is currently a problem where, in the specific case of SMEM not
initialized by SBL, any SMEM API wrongly returns PROBE_DEFER
communicating wrong info to any user of this API.

A better way to handle this would be to track the SMEM state and return
a different kind of error than PROBE_DEFER.

Rework the __smem handle to always init it to the error pointer
-EPROBE_DEFER following what is already done by the SMEM API.
If we detect that the SBL didn't initialized SMEM, set the __smem handle
to the error pointer -ENODEV.
Also rework the SMEM API to handle the __smem handle to be an error
pointer and return it appropriately.

This way user of the API can react and return a proper error or use
fallback way for the failing API.

While at it, change the return error when SMEM is not initialized by SBL
also to -ENODEV to make it consistent with the __smem handle and use
dev_err_probe() helper to return the message.

Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
Link: https://lore.kernel.org/r/20251031130835.7953-3-ansuelsmth@gmail.com
Signed-off-by: Bjorn Andersson <andersson@kernel.org>

authored by

Christian Marangi and committed by
Bjorn Andersson
7a94d5f3 652a86b2

+15 -11
+15 -11
drivers/soc/qcom/smem.c
··· 353 353 return p - le32_to_cpu(e->size); 354 354 } 355 355 356 - /* Pointer to the one and only smem handle */ 357 - static struct qcom_smem *__smem; 356 + /* 357 + * Pointer to the one and only smem handle. 358 + * Init to -EPROBE_DEFER to signal SMEM still has to be probed. 359 + * Can be set to -ENODEV if SMEM is not initialized by SBL. 360 + */ 361 + static struct qcom_smem *__smem = INIT_ERR_PTR(-EPROBE_DEFER); 358 362 359 363 /* Timeout (ms) for the trylock of remote spinlocks */ 360 364 #define HWSPINLOCK_TIMEOUT 1000 ··· 512 508 unsigned long flags; 513 509 int ret; 514 510 515 - if (!__smem) 516 - return -EPROBE_DEFER; 511 + if (IS_ERR(__smem)) 512 + return PTR_ERR(__smem); 517 513 518 514 if (item < SMEM_ITEM_LAST_FIXED) { 519 515 dev_err(__smem->dev, ··· 689 685 void *qcom_smem_get(unsigned host, unsigned item, size_t *size) 690 686 { 691 687 struct smem_partition *part; 692 - void *ptr = ERR_PTR(-EPROBE_DEFER); 688 + void *ptr; 693 689 694 - if (!__smem) 695 - return ptr; 690 + if (IS_ERR(__smem)) 691 + return __smem; 696 692 697 693 if (WARN_ON(item >= __smem->item_count)) 698 694 return ERR_PTR(-EINVAL); ··· 727 723 struct smem_header *header; 728 724 unsigned ret; 729 725 730 - if (!__smem) 731 - return -EPROBE_DEFER; 726 + if (IS_ERR(__smem)) 727 + return PTR_ERR(__smem); 732 728 733 729 if (host < SMEM_HOST_COUNT && __smem->partitions[host].virt_base) { 734 730 part = &__smem->partitions[host]; ··· 1185 1181 header = smem->regions[0].virt_base; 1186 1182 if (le32_to_cpu(header->initialized) != 1 || 1187 1183 le32_to_cpu(header->reserved)) { 1188 - dev_err(&pdev->dev, "SMEM is not initialized by SBL\n"); 1189 - return -EINVAL; 1184 + __smem = ERR_PTR(-ENODEV); 1185 + return dev_err_probe(&pdev->dev, PTR_ERR(__smem), "SMEM is not initialized by SBL\n"); 1190 1186 } 1191 1187 1192 1188 hwlock_id = of_hwspin_lock_get_id(pdev->dev.of_node, 0);