aboutsummaryrefslogtreecommitdiff
path: root/drivers/soc/qcom/smd.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/soc/qcom/smd.c')
-rw-r--r--drivers/soc/qcom/smd.c146
1 files changed, 45 insertions, 101 deletions
diff --git a/drivers/soc/qcom/smd.c b/drivers/soc/qcom/smd.c
index a6155c917d52..576c89fd8965 100644
--- a/drivers/soc/qcom/smd.c
+++ b/drivers/soc/qcom/smd.c
@@ -131,18 +131,6 @@ struct qcom_smd_edge {
struct work_struct work;
};
-/*
- * SMD channel states.
- */
-enum smd_channel_state {
- SMD_CHANNEL_CLOSED,
- SMD_CHANNEL_OPENING,
- SMD_CHANNEL_OPENED,
- SMD_CHANNEL_FLUSHING,
- SMD_CHANNEL_CLOSING,
- SMD_CHANNEL_RESET,
- SMD_CHANNEL_RESET_OPENING
-};
/**
* struct qcom_smd_channel - smd channel struct
@@ -166,38 +154,6 @@ enum smd_channel_state {
* @pkt_size: size of the currently handled packet
* @list: lite entry for @channels in qcom_smd_edge
*/
-struct qcom_smd_channel {
- struct qcom_smd_edge *edge;
-
- struct qcom_smd_device *qsdev;
-
- char *name;
- enum smd_channel_state state;
- enum smd_channel_state remote_state;
-
- struct smd_channel_info *tx_info;
- struct smd_channel_info *rx_info;
-
- struct smd_channel_info_word *tx_info_word;
- struct smd_channel_info_word *rx_info_word;
-
- struct mutex tx_lock;
- wait_queue_head_t fblockread_event;
-
- void *tx_fifo;
- void *rx_fifo;
- int fifo_size;
-
- void *bounce_buffer;
- int (*cb)(struct qcom_smd_device *, const void *, size_t);
-
- spinlock_t recv_lock;
-
- int pkt_size;
-
- struct list_head list;
-};
-
/**
* struct qcom_smd - smd struct
* @dev: device struct
@@ -362,43 +318,37 @@ static void qcom_smd_channel_set_state(struct qcom_smd_channel *channel,
}
/*
- * Copy count bytes of data using 32bit accesses, if that's required.
+ * Copy count bytes of data from memory to device memory using 32bit accesses
*/
-static void smd_copy_to_fifo(void __iomem *_dst,
- const void *_src,
- size_t count,
- bool word_aligned)
+static void smd_copy_to_fifo(void __iomem *_dst, const void *_src, size_t count, bool word_aligned)
{
- u32 *dst = (u32 *)_dst;
- u32 *src = (u32 *)_src;
-
- if (word_aligned) {
- count /= sizeof(u32);
- while (count--)
- writel_relaxed(*src++, dst++);
- } else {
- memcpy_toio(_dst, _src, count);
- }
+ u32 *dst = (u32 *)_dst;
+ u32 *src = (u32 *)_src;
+
+ if (word_aligned) {
+ count /= sizeof(u32);
+ while (count--)
+ writel_relaxed(*src++, dst++);
+ } else {
+ memcpy_toio(_dst, _src, count);
+ }
}
/*
- * Copy count bytes of data using 32bit accesses, if that is required.
+ * Copy count bytes of data from device memory to memory using 32bit accesses
*/
-static void smd_copy_from_fifo(void *_dst,
- const void __iomem *_src,
- size_t count,
- bool word_aligned)
+static void smd_copy_from_fifo(void *_dst, const void __iomem *_src, size_t count, bool word_aligned)
{
- u32 *dst = (u32 *)_dst;
- u32 *src = (u32 *)_src;
-
- if (word_aligned) {
- count /= sizeof(u32);
- while (count--)
- *dst++ = readl_relaxed(src++);
- } else {
- memcpy_fromio(_dst, _src, count);
- }
+ u32 *dst = (u32 *)_dst;
+ u32 *src = (u32 *)_src;
+
+ if (word_aligned) {
+ count /= sizeof(u32);
+ while (count--)
+ *dst++ = readl_relaxed(src++);
+ } else {
+ memcpy_fromio(_dst, _src, count);
+ }
}
/*
@@ -416,19 +366,11 @@ static size_t qcom_smd_channel_peek(struct qcom_smd_channel *channel,
tail = GET_RX_CHANNEL_INFO(channel, tail);
len = min_t(size_t, count, channel->fifo_size - tail);
- if (len) {
- smd_copy_from_fifo(buf,
- channel->rx_fifo + tail,
- len,
- word_aligned);
- }
+ if (len)
+ smd_copy_from_fifo(buf, channel->rx_fifo + tail, len, word_aligned);
- if (len != count) {
- smd_copy_from_fifo(buf + len,
- channel->rx_fifo,
- count - len,
- word_aligned);
- }
+ if (len != count)
+ smd_copy_from_fifo(buf + len, channel->rx_fifo, count - len, word_aligned);
return count;
}
@@ -631,19 +573,11 @@ static int qcom_smd_write_fifo(struct qcom_smd_channel *channel,
head = GET_TX_CHANNEL_INFO(channel, head);
len = min_t(size_t, count, channel->fifo_size - head);
- if (len) {
- smd_copy_to_fifo(channel->tx_fifo + head,
- data,
- len,
- word_aligned);
- }
+ if (len)
+ smd_copy_to_fifo(channel->tx_fifo + head, data, len, word_aligned);
- if (len != count) {
- smd_copy_to_fifo(channel->tx_fifo,
- data + len,
- count - len,
- word_aligned);
- }
+ if (len != count)
+ smd_copy_to_fifo(channel->tx_fifo, data + len, count - len, word_aligned);
head += count;
head &= (channel->fifo_size - 1);
@@ -667,16 +601,19 @@ int qcom_smd_send(struct qcom_smd_channel *channel, const void *data, int len)
{
u32 hdr[5] = {len,};
int tlen = sizeof(hdr) + len;
- int ret;
+ int ret, length;
/* Word aligned channels only accept word size aligned data */
if (channel->rx_info_word != NULL && len % 4)
return -EINVAL;
+ length = qcom_smd_get_tx_avail(channel);
+
ret = mutex_lock_interruptible(&channel->tx_lock);
if (ret)
return ret;
+ length = qcom_smd_get_tx_avail(channel);
while (qcom_smd_get_tx_avail(channel) < tlen) {
if (channel->state != SMD_CHANNEL_OPENED) {
ret = -EPIPE;
@@ -696,9 +633,12 @@ int qcom_smd_send(struct qcom_smd_channel *channel, const void *data, int len)
SET_TX_CHANNEL_INFO(channel, fTAIL, 0);
+ length = qcom_smd_get_tx_avail(channel);
qcom_smd_write_fifo(channel, hdr, sizeof(hdr));
qcom_smd_write_fifo(channel, data, len);
+ length = qcom_smd_get_tx_avail(channel);
+
SET_TX_CHANNEL_INFO(channel, fHEAD, 1);
/* Ensure ordering of channel info updates */
@@ -1008,7 +948,7 @@ static struct qcom_smd_channel *qcom_smd_create_channel(struct qcom_smd_edge *ed
/* The channel consist of a rx and tx fifo of equal size */
fifo_size /= 2;
- dev_dbg(smd->dev, "new channel '%s' info-size: %zu fifo-size: %zu\n",
+ dev_err(smd->dev, "new channel '%s' info-size: %zu fifo-size: %zu\n",
name, info_size, fifo_size);
channel->tx_fifo = fifo_base;
@@ -1190,7 +1130,11 @@ static int qcom_smd_parse_edge(struct device *dev,
edge->remote_pid = QCOM_SMEM_HOST_ANY;
key = "qcom,remote-pid";
- of_property_read_u32(node, key, &edge->remote_pid);
+ ret = of_property_read_u32(node, key, &edge->remote_pid);
+ if (ret) {
+ dev_err(dev, "edge missing %s property\n", key);
+ return -EINVAL;
+ }
syscon_np = of_parse_phandle(node, "qcom,ipc", 0);
if (!syscon_np) {