From 18912806bbf8bd6e2b5cb12317679790eb0e0ce4 Mon Sep 17 00:00:00 2001 From: Andy Gross Date: Tue, 11 Aug 2015 23:48:15 -0500 Subject: soc: qcom: smem: Fix errant private access This patch corrects private partition item access. Instead of falling back to global for instances where we have an actual host and remote partition existing, return the results of the private lookup. Signed-off-by: Andy Gross --- drivers/soc/qcom/smem.c | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) (limited to 'drivers/soc') diff --git a/drivers/soc/qcom/smem.c b/drivers/soc/qcom/smem.c index 7c2c324c..5236518 100644 --- a/drivers/soc/qcom/smem.c +++ b/drivers/soc/qcom/smem.c @@ -258,10 +258,6 @@ static int qcom_smem_alloc_private(struct qcom_smem *smem, size_t alloc_size; void *p; - /* We're not going to find it if there's no matching partition */ - if (host >= SMEM_HOST_COUNT || !smem->partitions[host]) - return -ENOENT; - phdr = smem->partitions[host]; p = (void *)phdr + sizeof(*phdr); @@ -371,8 +367,9 @@ int qcom_smem_alloc(unsigned host, unsigned item, size_t size) if (ret) return ret; - ret = qcom_smem_alloc_private(__smem, host, item, size); - if (ret == -ENOENT) + if (host < SMEM_HOST_COUNT && __smem->partitions[host]) + ret = qcom_smem_alloc_private(__smem, host, item, size); + else ret = qcom_smem_alloc_global(__smem, item, size); hwspin_unlock_irqrestore(__smem->hwlock, &flags); @@ -428,10 +425,6 @@ static int qcom_smem_get_private(struct qcom_smem *smem, struct smem_private_entry *hdr; void *p; - /* We're not going to find it if there's no matching partition */ - if (host >= SMEM_HOST_COUNT || !smem->partitions[host]) - return -ENOENT; - phdr = smem->partitions[host]; p = (void *)phdr + sizeof(*phdr); @@ -484,8 +477,9 @@ int qcom_smem_get(unsigned host, unsigned item, void **ptr, size_t *size) if (ret) return ret; - ret = qcom_smem_get_private(__smem, host, item, ptr, size); - if (ret == -ENOENT) + if (host < SMEM_HOST_COUNT && __smem->partitions[host]) + ret = qcom_smem_get_private(__smem, host, item, ptr, size); + else ret = qcom_smem_get_global(__smem, item, ptr, size); hwspin_unlock_irqrestore(__smem->hwlock, &flags); -- cgit v1.1 From 93dbed9121cc8e0fcc93edd9fca901322bdfbd1a Mon Sep 17 00:00:00 2001 From: Andy Gross Date: Wed, 26 Aug 2015 14:42:45 -0500 Subject: soc: qcom: smd: Use correct remote processor ID This patch fixes SMEM addressing issues when remote processors need to use secure SMEM partitions. Signed-off-by: Andy Gross Reviewed-by: Bjorn Andersson --- drivers/soc/qcom/smd.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) (limited to 'drivers/soc') diff --git a/drivers/soc/qcom/smd.c b/drivers/soc/qcom/smd.c index 327adcf..edd9d9a 100644 --- a/drivers/soc/qcom/smd.c +++ b/drivers/soc/qcom/smd.c @@ -96,6 +96,7 @@ static const struct { * @smd: handle to qcom_smd * @of_node: of_node handle for information related to this edge * @edge_id: identifier of this edge + * @remote_pid: identifier of remote processor * @irq: interrupt for signals on this edge * @ipc_regmap: regmap handle holding the outgoing ipc register * @ipc_offset: offset within @ipc_regmap of the register for ipc @@ -111,6 +112,7 @@ struct qcom_smd_edge { struct qcom_smd *smd; struct device_node *of_node; unsigned edge_id; + unsigned remote_pid; int irq; @@ -572,7 +574,7 @@ static irqreturn_t qcom_smd_edge_intr(int irq, void *data) * have to scan if the amount of available space in smem have changed * since last scan. */ - available = qcom_smem_get_free_space(edge->edge_id); + available = qcom_smem_get_free_space(edge->remote_pid); if (available != edge->smem_available) { edge->smem_available = available; edge->need_rescan = true; @@ -976,7 +978,8 @@ static struct qcom_smd_channel *qcom_smd_create_channel(struct qcom_smd_edge *ed spin_lock_init(&channel->recv_lock); init_waitqueue_head(&channel->fblockread_event); - ret = qcom_smem_get(edge->edge_id, smem_info_item, (void **)&info, &info_size); + ret = qcom_smem_get(edge->remote_pid, smem_info_item, (void **)&info, + &info_size); if (ret) goto free_name_and_channel; @@ -997,7 +1000,8 @@ static struct qcom_smd_channel *qcom_smd_create_channel(struct qcom_smd_edge *ed goto free_name_and_channel; } - ret = qcom_smem_get(edge->edge_id, smem_fifo_item, &fifo_base, &fifo_size); + ret = qcom_smem_get(edge->remote_pid, smem_fifo_item, &fifo_base, + &fifo_size); if (ret) goto free_name_and_channel; @@ -1041,7 +1045,7 @@ static void qcom_discover_channels(struct qcom_smd_edge *edge) int i; for (tbl = 0; tbl < SMD_ALLOC_TBL_COUNT; tbl++) { - ret = qcom_smem_get(edge->edge_id, + ret = qcom_smem_get(edge->remote_pid, smem_items[tbl].alloc_tbl_id, (void **)&alloc_tbl, NULL); @@ -1184,6 +1188,10 @@ static int qcom_smd_parse_edge(struct device *dev, return -EINVAL; } + edge->remote_pid = QCOM_SMEM_HOST_ANY; + key = "qcom,remote-pid"; + of_property_read_u32(node, key, &edge->remote_pid); + syscon_np = of_parse_phandle(node, "qcom,ipc", 0); if (!syscon_np) { dev_err(dev, "no qcom,ipc node\n"); -- cgit v1.1 From 208487a8f69084992f76ef87ddd3e00e5eaf6587 Mon Sep 17 00:00:00 2001 From: Bjorn Andersson Date: Mon, 24 Aug 2015 13:38:46 -0700 Subject: soc: qcom: smd: Correct fBLOCKREADINTR handling fBLOCKREADINTR is masking the notification from the remote and should hence be cleared while we're waiting the tx fifo to drain. Also change the reset state to mask the notification, as send is the only use case where we're interested in it. Signed-off-by: Bjorn Andersson Signed-off-by: Andy Gross --- drivers/soc/qcom/smd.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/soc') diff --git a/drivers/soc/qcom/smd.c b/drivers/soc/qcom/smd.c index edd9d9a..a6155c9 100644 --- a/drivers/soc/qcom/smd.c +++ b/drivers/soc/qcom/smd.c @@ -312,7 +312,7 @@ static void qcom_smd_channel_reset(struct qcom_smd_channel *channel) SET_TX_CHANNEL_INFO(channel, fHEAD, 0); SET_TX_CHANNEL_INFO(channel, fTAIL, 0); SET_TX_CHANNEL_INFO(channel, fSTATE, 1); - SET_TX_CHANNEL_INFO(channel, fBLOCKREADINTR, 0); + SET_TX_CHANNEL_INFO(channel, fBLOCKREADINTR, 1); SET_TX_CHANNEL_INFO(channel, head, 0); SET_TX_CHANNEL_INFO(channel, tail, 0); @@ -683,7 +683,7 @@ int qcom_smd_send(struct qcom_smd_channel *channel, const void *data, int len) goto out; } - SET_TX_CHANNEL_INFO(channel, fBLOCKREADINTR, 1); + SET_TX_CHANNEL_INFO(channel, fBLOCKREADINTR, 0); ret = wait_event_interruptible(channel->fblockread_event, qcom_smd_get_tx_avail(channel) >= tlen || @@ -691,7 +691,7 @@ int qcom_smd_send(struct qcom_smd_channel *channel, const void *data, int len) if (ret) goto out; - SET_TX_CHANNEL_INFO(channel, fBLOCKREADINTR, 0); + SET_TX_CHANNEL_INFO(channel, fBLOCKREADINTR, 1); } SET_TX_CHANNEL_INFO(channel, fTAIL, 0); -- cgit v1.1