diff options
Diffstat (limited to 'drivers/soc/qcom/smd.c')
-rw-r--r-- | drivers/soc/qcom/smd.c | 146 |
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) { |