Hi Bjorn,
On Tue, Sep 25, 2018 at 01:06:07AM -0700, Bjorn Andersson wrote:
rmtfs_mem provides access to physical storage and is crucial for the
operation of the Qualcomm modem subsystem.
The rmtfs_mem implementation must be available before the modem
subsystem is booted and a solution where the modem remoteproc will
verify that the rmtfs_mem is available has been discussed in the past.
But this would not handle the case where the rmtfs_mem provider is
restarted, which would cause fatal loss of access to the storage device
for the modem.
The suggestion is therefor to link the rmtfs_mem to its associated
remote processor instance and control it based on the availability of
the rmtfs_mem implementation.
But what does "availability" mean? If I'm reading your rmtfs daemon
properly, "availability" should mean that the daemon is up and has
registered a RMTFS_QMI_SERVICE. But in this patch, you're keying off of
the open() call, which sounds like you're introducing a race condition
-- we might have open()ed the RMTFS memory but we're not actually
completely ready to service requests.
So rather than looking for open(), I think somebody needs to be looking
for the appearance and disappearance of the RMTFS_QMI_SERVICE. (Looking
for disappearance would resolve the daemon restart issue, no?) That
"somebody" could be the remoteproc driver I suppose (qmi_add_lookup()?),
or...couldn't it just be the modem itself? Do you actually need to
restart the entire modem when the RMTFS service goes away, or do you
just need to pause storage activity?
Signed-off-by: Bjorn Andersson <bjorn.andersson@xxxxxxxxxx>...
---
The currently implemented workaround in the Linaro QCOMLT releases is to
blacklist the qcom_q6v5_pil kernel module and load this explicitly after rmtfs
has been started.
With this patch the modem module can be loaded automatically by the
platform_bus and will only be booted as the rmtfs becomes available. Performing
actions such as upgrading (and restarting) the rmtfs service will cause the
modem to automatically restart and hence continue to function after the
upgrade.
.../reserved-memory/qcom,rmtfs-mem.txt | 7 ++++++
drivers/remoteproc/qcom_q6v5_pil.c | 1 +
drivers/soc/qcom/Kconfig | 1 +
drivers/soc/qcom/rmtfs_mem.c | 23 ++++++++++++++++++-
4 files changed, 31 insertions(+), 1 deletion(-)
diff --git a/drivers/soc/qcom/rmtfs_mem.c b/drivers/soc/qcom/rmtfs_mem.c
index 8a3678c2e83c..8b08be310397 100644
--- a/drivers/soc/qcom/rmtfs_mem.c
+++ b/drivers/soc/qcom/rmtfs_mem.c
@@ -18,6 +18,7 @@
#include <linux/platform_device.h>
#include <linux/of.h>
#include <linux/of_reserved_mem.h>
+#include <linux/remoteproc.h>
#include <linux/dma-mapping.h>
#include <linux/slab.h>
#include <linux/uaccess.h>
@@ -39,6 +40,8 @@ struct qcom_rmtfs_mem {
unsigned int client_id;
unsigned int perms;
+
+ struct rproc *rproc;
};
static ssize_t qcom_rmtfs_mem_show(struct device *dev,
@@ -80,11 +83,18 @@ static int qcom_rmtfs_mem_open(struct inode *inode, struct file *filp)
struct qcom_rmtfs_mem *rmtfs_mem = container_of(inode->i_cdev,
struct qcom_rmtfs_mem,
cdev);
+ int ret = 0;
get_device(&rmtfs_mem->dev);
filp->private_data = rmtfs_mem;
- return 0;
+ if (rmtfs_mem->rproc) {
+ ret = rproc_boot(rmtfs_mem->rproc);
+ if (ret)
+ put_device(&rmtfs_mem->dev);
+ }
+
+ return ret;
}
static ssize_t qcom_rmtfs_mem_read(struct file *filp,
char __user *buf, size_t count, loff_t *f_pos)
@@ -127,6 +137,9 @@ static int qcom_rmtfs_mem_release(struct inode *inode, struct file *filp)
{
struct qcom_rmtfs_mem *rmtfs_mem = filp->private_data;
+ if (rmtfs_mem->rproc)
+ rproc_shutdown(rmtfs_mem->rproc);
+
put_device(&rmtfs_mem->dev);
return 0;
@@ -156,6 +169,7 @@ static int qcom_rmtfs_mem_probe(struct platform_device *pdev)
struct qcom_scm_vmperm perms[2];
struct reserved_mem *rmem;
struct qcom_rmtfs_mem *rmtfs_mem;
+ phandle rproc_phandle;
u32 client_id;
u32 vmid;
int ret;
@@ -181,6 +195,13 @@ static int qcom_rmtfs_mem_probe(struct platform_device *pdev)
rmtfs_mem->client_id = client_id;
rmtfs_mem->size = rmem->size;
+ ret = of_property_read_u32(node, "rproc", &rproc_phandle);
+ if (!ret) {
+ rmtfs_mem->rproc = rproc_get_by_phandle(rproc_phandle);
You're doing an rproc_get(), so you need to do a rproc_put() in
remove().
Brian
+ if (!rmtfs_mem->rproc)
+ return -EPROBE_DEFER;
+ }
+
device_initialize(&rmtfs_mem->dev);
rmtfs_mem->dev.parent = &pdev->dev;
rmtfs_mem->dev.groups = qcom_rmtfs_mem_groups;