aboutsummaryrefslogtreecommitdiff
path: root/drivers/soc/qcom/smem.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/soc/qcom/smem.c')
-rw-r--r--drivers/soc/qcom/smem.c51
1 files changed, 43 insertions, 8 deletions
diff --git a/drivers/soc/qcom/smem.c b/drivers/soc/qcom/smem.c
index 077421ef971..9e59252bd5f 100644
--- a/drivers/soc/qcom/smem.c
+++ b/drivers/soc/qcom/smem.c
@@ -23,11 +23,11 @@
#include <linux/printk.h>
#include <linux/slab.h>
#include <linux/stat.h>
+#include <soc/qcom/subsystem_notif.h>
+#include <soc/qcom/ramdump.h>
#include <soc/qcom/smem.h>
-#include <mach/ramdump.h>
-#include <mach/subsystem_notif.h>
#include "smem_private.h"
@@ -92,6 +92,7 @@ static DEFINE_SPINLOCK(smem_init_check_lock);
static int smem_module_inited;
static RAW_NOTIFIER_HEAD(smem_module_init_notifier_list);
static DEFINE_MUTEX(smem_module_init_notifier_lock);
+static bool probe_done;
/* smem security feature components */
#define SMEM_TOC_IDENTIFIER 0x434f5424 /* "$TOC" */
@@ -181,6 +182,19 @@ static struct restart_notifier_block restart_notifiers[] = {
static int init_smem_remote_spinlock(void);
/**
+ * is_probe_done() - Did the probe function successfully complete
+ *
+ * @return - true if probe successfully completed, false if otherwise
+ *
+ * Helper function for EPROBE_DEFER support. If this function returns false,
+ * the calling function should immediately return -EPROBE_DEFER.
+ */
+static bool is_probe_done(void)
+{
+ return probe_done;
+}
+
+/**
* smem_phys_to_virt() - Convert a physical base and offset to virtual address
*
* @base: physical base address to check
@@ -255,7 +269,10 @@ static void *smem_phys_to_virt(phys_addr_t base, unsigned offset)
* @returns: Physical address (or NULL if there is a failure)
*
* This function should only be used if an SMEM item needs to be handed
- * off to a DMA engine.
+ * off to a DMA engine. This function will not return a version of EPROBE_DEFER
+ * if the driver is not ready since the caller should obtain @smem_address from
+ * one of the other public APIs and get EPROBE_DEFER at that time, if
+ * applicable.
*/
phys_addr_t smem_virt_to_phys(void *smem_address)
{
@@ -485,7 +502,8 @@ static void *__smem_find(unsigned id, unsigned size_in, bool skip_init_check)
* @size_in: Size of the SMEM item
* @to_proc: SMEM host that shares the item with apps
* @flags: Item attribute flags
- * @returns: Pointer to SMEM item or NULL if it doesn't exist
+ * @returns: Pointer to SMEM item, NULL if it doesn't exist, or -EPROBE_DEFER
+ * if the driver is not ready
*/
void *smem_find(unsigned id, unsigned size_in, unsigned to_proc, unsigned flags)
{
@@ -495,6 +513,9 @@ void *smem_find(unsigned id, unsigned size_in, unsigned to_proc, unsigned flags)
SMEM_DBG("%s(%u, %u, %u, %u)\n", __func__, id, size_in, to_proc,
flags);
+ if (!is_probe_done())
+ return ERR_PTR(-EPROBE_DEFER);
+
ptr = smem_get_entry(id, &size, to_proc, flags);
if (!ptr)
return 0;
@@ -668,7 +689,8 @@ static void *alloc_item_secure(unsigned id, unsigned size_in, unsigned to_proc,
* @size_in: Size of the SMEM item
* @to_proc: SMEM host that shares the item with apps
* @flags: Item attribute flags
- * @returns: Pointer to SMEM item or NULL if it couldn't be found/allocated
+ * @returns: Pointer to SMEM item, NULL if it couldn't be found/allocated,
+ * or -EPROBE_DEFER if the driver is not ready
*/
void *smem_alloc(unsigned id, unsigned size_in, unsigned to_proc,
unsigned flags)
@@ -682,6 +704,9 @@ void *smem_alloc(unsigned id, unsigned size_in, unsigned to_proc,
SMEM_DBG("%s(%u, %u, %u, %u)\n", __func__, id, size_in, to_proc,
flags);
+ if (!is_probe_done())
+ return ERR_PTR(-EPROBE_DEFER);
+
if (!smem_initialized_check())
return NULL;
@@ -748,13 +773,17 @@ EXPORT_SYMBOL(smem_alloc);
* @size: Pointer to size variable for storing the result
* @to_proc: SMEM host that shares the item with apps
* @flags: Item attribute flags
- * @returns: Pointer to SMEM item or NULL if it doesn't exist
+ * @returns: Pointer to SMEM item, NULL if it doesn't exist, or -EPROBE_DEFER
+ * if the driver isn't ready
*/
void *smem_get_entry(unsigned id, unsigned *size, unsigned to_proc,
unsigned flags)
{
SMEM_DBG("%s(%u, %u, %u, %u)\n", __func__, id, *size, to_proc, flags);
+ if (!is_probe_done())
+ return ERR_PTR(-EPROBE_DEFER);
+
return __smem_get_entry_secure(id, size, to_proc, flags, false, true);
}
EXPORT_SYMBOL(smem_get_entry);
@@ -766,7 +795,8 @@ EXPORT_SYMBOL(smem_get_entry);
* @size_out: Pointer to size variable for storing the result
* @to_proc: SMEM host that shares the item with apps
* @flags: Item attribute flags
- * @returns: Pointer to SMEM item or NULL if it doesn't exist
+ * @returns: Pointer to SMEM item, NULL if it doesn't exist, or -EPROBE_DEFER
+ * if the driver isn't ready
*
* This function does not lock the remote spinlock and should only be used in
* failure-recover cases such as retrieving the subsystem failure reason during
@@ -775,6 +805,9 @@ EXPORT_SYMBOL(smem_get_entry);
void *smem_get_entry_no_rlock(unsigned id, unsigned *size_out, unsigned to_proc,
unsigned flags)
{
+ if (!is_probe_done())
+ return ERR_PTR(-EPROBE_DEFER);
+
return __smem_get_entry_secure(id, size_out, to_proc, flags, false,
false);
}
@@ -1384,6 +1417,8 @@ smem_targ_info_done:
smem_init_security();
}
+ probe_done = true;
+
ret = of_platform_populate(pdev->dev.of_node, NULL, NULL, &pdev->dev);
if (ret)
LOG_ERR("%s: of_platform_populate failed %d\n", __func__, ret);
@@ -1442,4 +1477,4 @@ int __init msm_smem_init(void)
return 0;
}
-module_init(msm_smem_init);
+arch_initcall(msm_smem_init);