Commit 24f60e37 authored by Stephen Boyd's avatar Stephen Boyd Committed by Andy Gross

soc: qcom: smd: Handle big endian CPUs

The smd structures are always in little endian, but the smd
driver is not capable of being used on big endian CPUs. Annotate
the little endian data members and update the code to do the
proper byte swapping.

Cc: Bjorn Andersson <bjorn.andersson@sonymobile.com>
Signed-off-by: default avatarStephen Boyd <sboyd@codeaurora.org>
Signed-off-by: default avatarAndy Gross <agross@codeaurora.org>
parent 30b7ea5e
...@@ -212,7 +212,7 @@ struct qcom_smd { ...@@ -212,7 +212,7 @@ struct qcom_smd {
* Format of the smd_info smem items, for byte aligned channels. * Format of the smd_info smem items, for byte aligned channels.
*/ */
struct smd_channel_info { struct smd_channel_info {
u32 state; __le32 state;
u8 fDSR; u8 fDSR;
u8 fCTS; u8 fCTS;
u8 fCD; u8 fCD;
...@@ -221,8 +221,8 @@ struct smd_channel_info { ...@@ -221,8 +221,8 @@ struct smd_channel_info {
u8 fTAIL; u8 fTAIL;
u8 fSTATE; u8 fSTATE;
u8 fBLOCKREADINTR; u8 fBLOCKREADINTR;
u32 tail; __le32 tail;
u32 head; __le32 head;
}; };
struct smd_channel_info_pair { struct smd_channel_info_pair {
...@@ -234,17 +234,17 @@ struct smd_channel_info_pair { ...@@ -234,17 +234,17 @@ struct smd_channel_info_pair {
* Format of the smd_info smem items, for word aligned channels. * Format of the smd_info smem items, for word aligned channels.
*/ */
struct smd_channel_info_word { struct smd_channel_info_word {
u32 state; __le32 state;
u32 fDSR; __le32 fDSR;
u32 fCTS; __le32 fCTS;
u32 fCD; __le32 fCD;
u32 fRI; __le32 fRI;
u32 fHEAD; __le32 fHEAD;
u32 fTAIL; __le32 fTAIL;
u32 fSTATE; __le32 fSTATE;
u32 fBLOCKREADINTR; __le32 fBLOCKREADINTR;
u32 tail; __le32 tail;
u32 head; __le32 head;
}; };
struct smd_channel_info_word_pair { struct smd_channel_info_word_pair {
...@@ -252,25 +252,73 @@ struct smd_channel_info_word_pair { ...@@ -252,25 +252,73 @@ struct smd_channel_info_word_pair {
struct smd_channel_info_word rx; struct smd_channel_info_word rx;
}; };
#define GET_RX_CHANNEL_FLAG(channel, param) \
({ \
BUILD_BUG_ON(sizeof(channel->info->rx.param) != sizeof(u8)); \
channel->info_word ? \
le32_to_cpu(channel->info_word->rx.param) : \
channel->info->rx.param; \
})
#define GET_RX_CHANNEL_INFO(channel, param) \ #define GET_RX_CHANNEL_INFO(channel, param) \
(channel->info_word ? \ ({ \
BUILD_BUG_ON(sizeof(channel->info->rx.param) != sizeof(u32)); \
le32_to_cpu(channel->info_word ? \
channel->info_word->rx.param : \ channel->info_word->rx.param : \
channel->info->rx.param) channel->info->rx.param); \
})
#define SET_RX_CHANNEL_FLAG(channel, param, value) \
({ \
BUILD_BUG_ON(sizeof(channel->info->rx.param) != sizeof(u8)); \
if (channel->info_word) \
channel->info_word->rx.param = cpu_to_le32(value); \
else \
channel->info->rx.param = value; \
})
#define SET_RX_CHANNEL_INFO(channel, param, value) \ #define SET_RX_CHANNEL_INFO(channel, param, value) \
(channel->info_word ? \ ({ \
(channel->info_word->rx.param = value) : \ BUILD_BUG_ON(sizeof(channel->info->rx.param) != sizeof(u32)); \
(channel->info->rx.param = value)) if (channel->info_word) \
channel->info_word->rx.param = cpu_to_le32(value); \
else \
channel->info->rx.param = cpu_to_le32(value); \
})
#define GET_TX_CHANNEL_FLAG(channel, param) \
({ \
BUILD_BUG_ON(sizeof(channel->info->tx.param) != sizeof(u8)); \
channel->info_word ? \
le32_to_cpu(channel->info_word->tx.param) : \
channel->info->tx.param; \
})
#define GET_TX_CHANNEL_INFO(channel, param) \ #define GET_TX_CHANNEL_INFO(channel, param) \
(channel->info_word ? \ ({ \
BUILD_BUG_ON(sizeof(channel->info->tx.param) != sizeof(u32)); \
le32_to_cpu(channel->info_word ? \
channel->info_word->tx.param : \ channel->info_word->tx.param : \
channel->info->tx.param) channel->info->tx.param); \
})
#define SET_TX_CHANNEL_FLAG(channel, param, value) \
({ \
BUILD_BUG_ON(sizeof(channel->info->tx.param) != sizeof(u8)); \
if (channel->info_word) \
channel->info_word->tx.param = cpu_to_le32(value); \
else \
channel->info->tx.param = value; \
})
#define SET_TX_CHANNEL_INFO(channel, param, value) \ #define SET_TX_CHANNEL_INFO(channel, param, value) \
(channel->info_word ? \ ({ \
(channel->info_word->tx.param = value) : \ BUILD_BUG_ON(sizeof(channel->info->tx.param) != sizeof(u32)); \
(channel->info->tx.param = value)) if (channel->info_word) \
channel->info_word->tx.param = cpu_to_le32(value); \
else \
channel->info->tx.param = cpu_to_le32(value); \
})
/** /**
* struct qcom_smd_alloc_entry - channel allocation entry * struct qcom_smd_alloc_entry - channel allocation entry
...@@ -281,9 +329,9 @@ struct smd_channel_info_word_pair { ...@@ -281,9 +329,9 @@ struct smd_channel_info_word_pair {
*/ */
struct qcom_smd_alloc_entry { struct qcom_smd_alloc_entry {
u8 name[20]; u8 name[20];
u32 cid; __le32 cid;
u32 flags; __le32 flags;
u32 ref_count; __le32 ref_count;
} __packed; } __packed;
#define SMD_CHANNEL_FLAGS_EDGE_MASK 0xff #define SMD_CHANNEL_FLAGS_EDGE_MASK 0xff
...@@ -312,14 +360,14 @@ static void qcom_smd_signal_channel(struct qcom_smd_channel *channel) ...@@ -312,14 +360,14 @@ static void qcom_smd_signal_channel(struct qcom_smd_channel *channel)
static void qcom_smd_channel_reset(struct qcom_smd_channel *channel) static void qcom_smd_channel_reset(struct qcom_smd_channel *channel)
{ {
SET_TX_CHANNEL_INFO(channel, state, SMD_CHANNEL_CLOSED); SET_TX_CHANNEL_INFO(channel, state, SMD_CHANNEL_CLOSED);
SET_TX_CHANNEL_INFO(channel, fDSR, 0); SET_TX_CHANNEL_FLAG(channel, fDSR, 0);
SET_TX_CHANNEL_INFO(channel, fCTS, 0); SET_TX_CHANNEL_FLAG(channel, fCTS, 0);
SET_TX_CHANNEL_INFO(channel, fCD, 0); SET_TX_CHANNEL_FLAG(channel, fCD, 0);
SET_TX_CHANNEL_INFO(channel, fRI, 0); SET_TX_CHANNEL_FLAG(channel, fRI, 0);
SET_TX_CHANNEL_INFO(channel, fHEAD, 0); SET_TX_CHANNEL_FLAG(channel, fHEAD, 0);
SET_TX_CHANNEL_INFO(channel, fTAIL, 0); SET_TX_CHANNEL_FLAG(channel, fTAIL, 0);
SET_TX_CHANNEL_INFO(channel, fSTATE, 1); SET_TX_CHANNEL_FLAG(channel, fSTATE, 1);
SET_TX_CHANNEL_INFO(channel, fBLOCKREADINTR, 1); SET_TX_CHANNEL_FLAG(channel, fBLOCKREADINTR, 1);
SET_TX_CHANNEL_INFO(channel, head, 0); SET_TX_CHANNEL_INFO(channel, head, 0);
SET_TX_CHANNEL_INFO(channel, tail, 0); SET_TX_CHANNEL_INFO(channel, tail, 0);
...@@ -357,12 +405,12 @@ static void qcom_smd_channel_set_state(struct qcom_smd_channel *channel, ...@@ -357,12 +405,12 @@ static void qcom_smd_channel_set_state(struct qcom_smd_channel *channel,
dev_dbg(edge->smd->dev, "set_state(%s, %d)\n", channel->name, state); dev_dbg(edge->smd->dev, "set_state(%s, %d)\n", channel->name, state);
SET_TX_CHANNEL_INFO(channel, fDSR, is_open); SET_TX_CHANNEL_FLAG(channel, fDSR, is_open);
SET_TX_CHANNEL_INFO(channel, fCTS, is_open); SET_TX_CHANNEL_FLAG(channel, fCTS, is_open);
SET_TX_CHANNEL_INFO(channel, fCD, is_open); SET_TX_CHANNEL_FLAG(channel, fCD, is_open);
SET_TX_CHANNEL_INFO(channel, state, state); SET_TX_CHANNEL_INFO(channel, state, state);
SET_TX_CHANNEL_INFO(channel, fSTATE, 1); SET_TX_CHANNEL_FLAG(channel, fSTATE, 1);
channel->state = state; channel->state = state;
qcom_smd_signal_channel(channel); qcom_smd_signal_channel(channel);
...@@ -397,7 +445,7 @@ static void smd_copy_from_fifo(void *_dst, ...@@ -397,7 +445,7 @@ static void smd_copy_from_fifo(void *_dst,
if (word_aligned) { if (word_aligned) {
count /= sizeof(u32); count /= sizeof(u32);
while (count--) while (count--)
*dst++ = readl_relaxed(src++); *dst++ = __raw_readl(src++);
} else { } else {
memcpy_fromio(_dst, _src, count); memcpy_fromio(_dst, _src, count);
} }
...@@ -493,7 +541,7 @@ static bool qcom_smd_channel_intr(struct qcom_smd_channel *channel) ...@@ -493,7 +541,7 @@ static bool qcom_smd_channel_intr(struct qcom_smd_channel *channel)
{ {
bool need_state_scan = false; bool need_state_scan = false;
int remote_state; int remote_state;
u32 pktlen; __le32 pktlen;
int avail; int avail;
int ret; int ret;
...@@ -504,10 +552,10 @@ static bool qcom_smd_channel_intr(struct qcom_smd_channel *channel) ...@@ -504,10 +552,10 @@ static bool qcom_smd_channel_intr(struct qcom_smd_channel *channel)
need_state_scan = true; need_state_scan = true;
} }
/* Indicate that we have seen any state change */ /* Indicate that we have seen any state change */
SET_RX_CHANNEL_INFO(channel, fSTATE, 0); SET_RX_CHANNEL_FLAG(channel, fSTATE, 0);
/* Signal waiting qcom_smd_send() about the interrupt */ /* Signal waiting qcom_smd_send() about the interrupt */
if (!GET_TX_CHANNEL_INFO(channel, fBLOCKREADINTR)) if (!GET_TX_CHANNEL_FLAG(channel, fBLOCKREADINTR))
wake_up_interruptible(&channel->fblockread_event); wake_up_interruptible(&channel->fblockread_event);
/* Don't consume any data until we've opened the channel */ /* Don't consume any data until we've opened the channel */
...@@ -515,7 +563,7 @@ static bool qcom_smd_channel_intr(struct qcom_smd_channel *channel) ...@@ -515,7 +563,7 @@ static bool qcom_smd_channel_intr(struct qcom_smd_channel *channel)
goto out; goto out;
/* Indicate that we've seen the new data */ /* Indicate that we've seen the new data */
SET_RX_CHANNEL_INFO(channel, fHEAD, 0); SET_RX_CHANNEL_FLAG(channel, fHEAD, 0);
/* Consume data */ /* Consume data */
for (;;) { for (;;) {
...@@ -524,7 +572,7 @@ static bool qcom_smd_channel_intr(struct qcom_smd_channel *channel) ...@@ -524,7 +572,7 @@ static bool qcom_smd_channel_intr(struct qcom_smd_channel *channel)
if (!channel->pkt_size && avail >= SMD_PACKET_HEADER_LEN) { if (!channel->pkt_size && avail >= SMD_PACKET_HEADER_LEN) {
qcom_smd_channel_peek(channel, &pktlen, sizeof(pktlen)); qcom_smd_channel_peek(channel, &pktlen, sizeof(pktlen));
qcom_smd_channel_advance(channel, SMD_PACKET_HEADER_LEN); qcom_smd_channel_advance(channel, SMD_PACKET_HEADER_LEN);
channel->pkt_size = pktlen; channel->pkt_size = le32_to_cpu(pktlen);
} else if (channel->pkt_size && avail >= channel->pkt_size) { } else if (channel->pkt_size && avail >= channel->pkt_size) {
ret = qcom_smd_channel_recv_single(channel); ret = qcom_smd_channel_recv_single(channel);
if (ret) if (ret)
...@@ -535,10 +583,10 @@ static bool qcom_smd_channel_intr(struct qcom_smd_channel *channel) ...@@ -535,10 +583,10 @@ static bool qcom_smd_channel_intr(struct qcom_smd_channel *channel)
} }
/* Indicate that we have seen and updated tail */ /* Indicate that we have seen and updated tail */
SET_RX_CHANNEL_INFO(channel, fTAIL, 1); SET_RX_CHANNEL_FLAG(channel, fTAIL, 1);
/* Signal the remote that we've consumed the data (if requested) */ /* Signal the remote that we've consumed the data (if requested) */
if (!GET_RX_CHANNEL_INFO(channel, fBLOCKREADINTR)) { if (!GET_RX_CHANNEL_FLAG(channel, fBLOCKREADINTR)) {
/* Ensure ordering of channel info updates */ /* Ensure ordering of channel info updates */
wmb(); wmb();
...@@ -667,7 +715,7 @@ static int qcom_smd_write_fifo(struct qcom_smd_channel *channel, ...@@ -667,7 +715,7 @@ static int qcom_smd_write_fifo(struct qcom_smd_channel *channel,
*/ */
int qcom_smd_send(struct qcom_smd_channel *channel, const void *data, int len) int qcom_smd_send(struct qcom_smd_channel *channel, const void *data, int len)
{ {
u32 hdr[5] = {len,}; __le32 hdr[5] = { cpu_to_le32(len), };
int tlen = sizeof(hdr) + len; int tlen = sizeof(hdr) + len;
int ret; int ret;
...@@ -685,7 +733,7 @@ int qcom_smd_send(struct qcom_smd_channel *channel, const void *data, int len) ...@@ -685,7 +733,7 @@ int qcom_smd_send(struct qcom_smd_channel *channel, const void *data, int len)
goto out; goto out;
} }
SET_TX_CHANNEL_INFO(channel, fBLOCKREADINTR, 0); SET_TX_CHANNEL_FLAG(channel, fBLOCKREADINTR, 0);
ret = wait_event_interruptible(channel->fblockread_event, ret = wait_event_interruptible(channel->fblockread_event,
qcom_smd_get_tx_avail(channel) >= tlen || qcom_smd_get_tx_avail(channel) >= tlen ||
...@@ -693,15 +741,15 @@ int qcom_smd_send(struct qcom_smd_channel *channel, const void *data, int len) ...@@ -693,15 +741,15 @@ int qcom_smd_send(struct qcom_smd_channel *channel, const void *data, int len)
if (ret) if (ret)
goto out; goto out;
SET_TX_CHANNEL_INFO(channel, fBLOCKREADINTR, 1); SET_TX_CHANNEL_FLAG(channel, fBLOCKREADINTR, 1);
} }
SET_TX_CHANNEL_INFO(channel, fTAIL, 0); SET_TX_CHANNEL_FLAG(channel, fTAIL, 0);
qcom_smd_write_fifo(channel, hdr, sizeof(hdr)); qcom_smd_write_fifo(channel, hdr, sizeof(hdr));
qcom_smd_write_fifo(channel, data, len); qcom_smd_write_fifo(channel, data, len);
SET_TX_CHANNEL_INFO(channel, fHEAD, 1); SET_TX_CHANNEL_FLAG(channel, fHEAD, 1);
/* Ensure ordering of channel info updates */ /* Ensure ordering of channel info updates */
wmb(); wmb();
...@@ -1055,6 +1103,7 @@ static void qcom_discover_channels(struct qcom_smd_edge *edge) ...@@ -1055,6 +1103,7 @@ static void qcom_discover_channels(struct qcom_smd_edge *edge)
unsigned info_id; unsigned info_id;
int tbl; int tbl;
int i; int i;
u32 eflags, cid;
for (tbl = 0; tbl < SMD_ALLOC_TBL_COUNT; tbl++) { for (tbl = 0; tbl < SMD_ALLOC_TBL_COUNT; tbl++) {
alloc_tbl = qcom_smem_get(edge->remote_pid, alloc_tbl = qcom_smem_get(edge->remote_pid,
...@@ -1064,6 +1113,7 @@ static void qcom_discover_channels(struct qcom_smd_edge *edge) ...@@ -1064,6 +1113,7 @@ static void qcom_discover_channels(struct qcom_smd_edge *edge)
for (i = 0; i < SMD_ALLOC_TBL_SIZE; i++) { for (i = 0; i < SMD_ALLOC_TBL_SIZE; i++) {
entry = &alloc_tbl[i]; entry = &alloc_tbl[i];
eflags = le32_to_cpu(entry->flags);
if (test_bit(i, edge->allocated[tbl])) if (test_bit(i, edge->allocated[tbl]))
continue; continue;
...@@ -1073,14 +1123,15 @@ static void qcom_discover_channels(struct qcom_smd_edge *edge) ...@@ -1073,14 +1123,15 @@ static void qcom_discover_channels(struct qcom_smd_edge *edge)
if (!entry->name[0]) if (!entry->name[0])
continue; continue;
if (!(entry->flags & SMD_CHANNEL_FLAGS_PACKET)) if (!(eflags & SMD_CHANNEL_FLAGS_PACKET))
continue; continue;
if ((entry->flags & SMD_CHANNEL_FLAGS_EDGE_MASK) != edge->edge_id) if ((eflags & SMD_CHANNEL_FLAGS_EDGE_MASK) != edge->edge_id)
continue; continue;
info_id = smem_items[tbl].info_base_id + entry->cid; cid = le32_to_cpu(entry->cid);
fifo_id = smem_items[tbl].fifo_base_id + entry->cid; info_id = smem_items[tbl].info_base_id + cid;
fifo_id = smem_items[tbl].fifo_base_id + cid;
channel = qcom_smd_create_channel(edge, info_id, fifo_id, entry->name); channel = qcom_smd_create_channel(edge, info_id, fifo_id, entry->name);
if (IS_ERR(channel)) if (IS_ERR(channel))
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment