aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/soc
diff options
context:
space:
mode:
authorStephen Boyd <sboyd@codeaurora.org>2015-09-17 17:50:53 -0400
committerAndy Gross <agross@codeaurora.org>2015-10-14 15:51:21 -0400
commit24f60e3776e340136f8d822aff75fe06b78a315f (patch)
treee4e3f75bf279f14211095d9b9d2589cf9de1c7ca /drivers/soc
parent30b7ea5eda0afb13164b2d7049a56645cfc1d47b (diff)
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: Stephen Boyd <sboyd@codeaurora.org> Signed-off-by: Andy Gross <agross@codeaurora.org>
Diffstat (limited to 'drivers/soc')
-rw-r--r--drivers/soc/qcom/smd.c181
1 files changed, 116 insertions, 65 deletions
diff --git a/drivers/soc/qcom/smd.c b/drivers/soc/qcom/smd.c
index f9768bff8051..18964f154383 100644
--- a/drivers/soc/qcom/smd.c
+++ b/drivers/soc/qcom/smd.c
@@ -212,7 +212,7 @@ struct qcom_smd {
212 * Format of the smd_info smem items, for byte aligned channels. 212 * Format of the smd_info smem items, for byte aligned channels.
213 */ 213 */
214struct smd_channel_info { 214struct smd_channel_info {
215 u32 state; 215 __le32 state;
216 u8 fDSR; 216 u8 fDSR;
217 u8 fCTS; 217 u8 fCTS;
218 u8 fCD; 218 u8 fCD;
@@ -221,8 +221,8 @@ struct smd_channel_info {
221 u8 fTAIL; 221 u8 fTAIL;
222 u8 fSTATE; 222 u8 fSTATE;
223 u8 fBLOCKREADINTR; 223 u8 fBLOCKREADINTR;
224 u32 tail; 224 __le32 tail;
225 u32 head; 225 __le32 head;
226}; 226};
227 227
228struct smd_channel_info_pair { 228struct smd_channel_info_pair {
@@ -234,17 +234,17 @@ struct smd_channel_info_pair {
234 * Format of the smd_info smem items, for word aligned channels. 234 * Format of the smd_info smem items, for word aligned channels.
235 */ 235 */
236struct smd_channel_info_word { 236struct smd_channel_info_word {
237 u32 state; 237 __le32 state;
238 u32 fDSR; 238 __le32 fDSR;
239 u32 fCTS; 239 __le32 fCTS;
240 u32 fCD; 240 __le32 fCD;
241 u32 fRI; 241 __le32 fRI;
242 u32 fHEAD; 242 __le32 fHEAD;
243 u32 fTAIL; 243 __le32 fTAIL;
244 u32 fSTATE; 244 __le32 fSTATE;
245 u32 fBLOCKREADINTR; 245 __le32 fBLOCKREADINTR;
246 u32 tail; 246 __le32 tail;
247 u32 head; 247 __le32 head;
248}; 248};
249 249
250struct smd_channel_info_word_pair { 250struct smd_channel_info_word_pair {
@@ -252,25 +252,73 @@ struct smd_channel_info_word_pair {
252 struct smd_channel_info_word rx; 252 struct smd_channel_info_word rx;
253}; 253};
254 254
255#define GET_RX_CHANNEL_INFO(channel, param) \ 255#define GET_RX_CHANNEL_FLAG(channel, param) \
256 (channel->info_word ? \ 256 ({ \
257 channel->info_word->rx.param : \ 257 BUILD_BUG_ON(sizeof(channel->info->rx.param) != sizeof(u8)); \
258 channel->info->rx.param) 258 channel->info_word ? \
259 259 le32_to_cpu(channel->info_word->rx.param) : \
260#define SET_RX_CHANNEL_INFO(channel, param, value) \ 260 channel->info->rx.param; \
261 (channel->info_word ? \ 261 })
262 (channel->info_word->rx.param = value) : \ 262
263 (channel->info->rx.param = value)) 263#define GET_RX_CHANNEL_INFO(channel, param) \
264 264 ({ \
265#define GET_TX_CHANNEL_INFO(channel, param) \ 265 BUILD_BUG_ON(sizeof(channel->info->rx.param) != sizeof(u32)); \
266 (channel->info_word ? \ 266 le32_to_cpu(channel->info_word ? \
267 channel->info_word->tx.param : \ 267 channel->info_word->rx.param : \
268 channel->info->tx.param) 268 channel->info->rx.param); \
269 269 })
270#define SET_TX_CHANNEL_INFO(channel, param, value) \ 270
271 (channel->info_word ? \ 271#define SET_RX_CHANNEL_FLAG(channel, param, value) \
272 (channel->info_word->tx.param = value) : \ 272 ({ \
273 (channel->info->tx.param = value)) 273 BUILD_BUG_ON(sizeof(channel->info->rx.param) != sizeof(u8)); \
274 if (channel->info_word) \
275 channel->info_word->rx.param = cpu_to_le32(value); \
276 else \
277 channel->info->rx.param = value; \
278 })
279
280#define SET_RX_CHANNEL_INFO(channel, param, value) \
281 ({ \
282 BUILD_BUG_ON(sizeof(channel->info->rx.param) != sizeof(u32)); \
283 if (channel->info_word) \
284 channel->info_word->rx.param = cpu_to_le32(value); \
285 else \
286 channel->info->rx.param = cpu_to_le32(value); \
287 })
288
289#define GET_TX_CHANNEL_FLAG(channel, param) \
290 ({ \
291 BUILD_BUG_ON(sizeof(channel->info->tx.param) != sizeof(u8)); \
292 channel->info_word ? \
293 le32_to_cpu(channel->info_word->tx.param) : \
294 channel->info->tx.param; \
295 })
296
297#define GET_TX_CHANNEL_INFO(channel, param) \
298 ({ \
299 BUILD_BUG_ON(sizeof(channel->info->tx.param) != sizeof(u32)); \
300 le32_to_cpu(channel->info_word ? \
301 channel->info_word->tx.param : \
302 channel->info->tx.param); \
303 })
304
305#define SET_TX_CHANNEL_FLAG(channel, param, value) \
306 ({ \
307 BUILD_BUG_ON(sizeof(channel->info->tx.param) != sizeof(u8)); \
308 if (channel->info_word) \
309 channel->info_word->tx.param = cpu_to_le32(value); \
310 else \
311 channel->info->tx.param = value; \
312 })
313
314#define SET_TX_CHANNEL_INFO(channel, param, value) \
315 ({ \
316 BUILD_BUG_ON(sizeof(channel->info->tx.param) != sizeof(u32)); \
317 if (channel->info_word) \
318 channel->info_word->tx.param = cpu_to_le32(value); \
319 else \
320 channel->info->tx.param = cpu_to_le32(value); \
321 })
274 322
275/** 323/**
276 * struct qcom_smd_alloc_entry - channel allocation entry 324 * struct qcom_smd_alloc_entry - channel allocation entry
@@ -281,9 +329,9 @@ struct smd_channel_info_word_pair {
281 */ 329 */
282struct qcom_smd_alloc_entry { 330struct qcom_smd_alloc_entry {
283 u8 name[20]; 331 u8 name[20];
284 u32 cid; 332 __le32 cid;
285 u32 flags; 333 __le32 flags;
286 u32 ref_count; 334 __le32 ref_count;
287} __packed; 335} __packed;
288 336
289#define SMD_CHANNEL_FLAGS_EDGE_MASK 0xff 337#define SMD_CHANNEL_FLAGS_EDGE_MASK 0xff
@@ -312,14 +360,14 @@ static void qcom_smd_signal_channel(struct qcom_smd_channel *channel)
312static void qcom_smd_channel_reset(struct qcom_smd_channel *channel) 360static void qcom_smd_channel_reset(struct qcom_smd_channel *channel)
313{ 361{
314 SET_TX_CHANNEL_INFO(channel, state, SMD_CHANNEL_CLOSED); 362 SET_TX_CHANNEL_INFO(channel, state, SMD_CHANNEL_CLOSED);
315 SET_TX_CHANNEL_INFO(channel, fDSR, 0); 363 SET_TX_CHANNEL_FLAG(channel, fDSR, 0);
316 SET_TX_CHANNEL_INFO(channel, fCTS, 0); 364 SET_TX_CHANNEL_FLAG(channel, fCTS, 0);
317 SET_TX_CHANNEL_INFO(channel, fCD, 0); 365 SET_TX_CHANNEL_FLAG(channel, fCD, 0);
318 SET_TX_CHANNEL_INFO(channel, fRI, 0); 366 SET_TX_CHANNEL_FLAG(channel, fRI, 0);
319 SET_TX_CHANNEL_INFO(channel, fHEAD, 0); 367 SET_TX_CHANNEL_FLAG(channel, fHEAD, 0);
320 SET_TX_CHANNEL_INFO(channel, fTAIL, 0); 368 SET_TX_CHANNEL_FLAG(channel, fTAIL, 0);
321 SET_TX_CHANNEL_INFO(channel, fSTATE, 1); 369 SET_TX_CHANNEL_FLAG(channel, fSTATE, 1);
322 SET_TX_CHANNEL_INFO(channel, fBLOCKREADINTR, 1); 370 SET_TX_CHANNEL_FLAG(channel, fBLOCKREADINTR, 1);
323 SET_TX_CHANNEL_INFO(channel, head, 0); 371 SET_TX_CHANNEL_INFO(channel, head, 0);
324 SET_TX_CHANNEL_INFO(channel, tail, 0); 372 SET_TX_CHANNEL_INFO(channel, tail, 0);
325 373
@@ -357,12 +405,12 @@ static void qcom_smd_channel_set_state(struct qcom_smd_channel *channel,
357 405
358 dev_dbg(edge->smd->dev, "set_state(%s, %d)\n", channel->name, state); 406 dev_dbg(edge->smd->dev, "set_state(%s, %d)\n", channel->name, state);
359 407
360 SET_TX_CHANNEL_INFO(channel, fDSR, is_open); 408 SET_TX_CHANNEL_FLAG(channel, fDSR, is_open);
361 SET_TX_CHANNEL_INFO(channel, fCTS, is_open); 409 SET_TX_CHANNEL_FLAG(channel, fCTS, is_open);
362 SET_TX_CHANNEL_INFO(channel, fCD, is_open); 410 SET_TX_CHANNEL_FLAG(channel, fCD, is_open);
363 411
364 SET_TX_CHANNEL_INFO(channel, state, state); 412 SET_TX_CHANNEL_INFO(channel, state, state);
365 SET_TX_CHANNEL_INFO(channel, fSTATE, 1); 413 SET_TX_CHANNEL_FLAG(channel, fSTATE, 1);
366 414
367 channel->state = state; 415 channel->state = state;
368 qcom_smd_signal_channel(channel); 416 qcom_smd_signal_channel(channel);
@@ -397,7 +445,7 @@ static void smd_copy_from_fifo(void *_dst,
397 if (word_aligned) { 445 if (word_aligned) {
398 count /= sizeof(u32); 446 count /= sizeof(u32);
399 while (count--) 447 while (count--)
400 *dst++ = readl_relaxed(src++); 448 *dst++ = __raw_readl(src++);
401 } else { 449 } else {
402 memcpy_fromio(_dst, _src, count); 450 memcpy_fromio(_dst, _src, count);
403 } 451 }
@@ -493,7 +541,7 @@ static bool qcom_smd_channel_intr(struct qcom_smd_channel *channel)
493{ 541{
494 bool need_state_scan = false; 542 bool need_state_scan = false;
495 int remote_state; 543 int remote_state;
496 u32 pktlen; 544 __le32 pktlen;
497 int avail; 545 int avail;
498 int ret; 546 int ret;
499 547
@@ -504,10 +552,10 @@ static bool qcom_smd_channel_intr(struct qcom_smd_channel *channel)
504 need_state_scan = true; 552 need_state_scan = true;
505 } 553 }
506 /* Indicate that we have seen any state change */ 554 /* Indicate that we have seen any state change */
507 SET_RX_CHANNEL_INFO(channel, fSTATE, 0); 555 SET_RX_CHANNEL_FLAG(channel, fSTATE, 0);
508 556
509 /* Signal waiting qcom_smd_send() about the interrupt */ 557 /* Signal waiting qcom_smd_send() about the interrupt */
510 if (!GET_TX_CHANNEL_INFO(channel, fBLOCKREADINTR)) 558 if (!GET_TX_CHANNEL_FLAG(channel, fBLOCKREADINTR))
511 wake_up_interruptible(&channel->fblockread_event); 559 wake_up_interruptible(&channel->fblockread_event);
512 560
513 /* Don't consume any data until we've opened the channel */ 561 /* 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 goto out; 563 goto out;
516 564
517 /* Indicate that we've seen the new data */ 565 /* Indicate that we've seen the new data */
518 SET_RX_CHANNEL_INFO(channel, fHEAD, 0); 566 SET_RX_CHANNEL_FLAG(channel, fHEAD, 0);
519 567
520 /* Consume data */ 568 /* Consume data */
521 for (;;) { 569 for (;;) {
@@ -524,7 +572,7 @@ static bool qcom_smd_channel_intr(struct qcom_smd_channel *channel)
524 if (!channel->pkt_size && avail >= SMD_PACKET_HEADER_LEN) { 572 if (!channel->pkt_size && avail >= SMD_PACKET_HEADER_LEN) {
525 qcom_smd_channel_peek(channel, &pktlen, sizeof(pktlen)); 573 qcom_smd_channel_peek(channel, &pktlen, sizeof(pktlen));
526 qcom_smd_channel_advance(channel, SMD_PACKET_HEADER_LEN); 574 qcom_smd_channel_advance(channel, SMD_PACKET_HEADER_LEN);
527 channel->pkt_size = pktlen; 575 channel->pkt_size = le32_to_cpu(pktlen);
528 } else if (channel->pkt_size && avail >= channel->pkt_size) { 576 } else if (channel->pkt_size && avail >= channel->pkt_size) {
529 ret = qcom_smd_channel_recv_single(channel); 577 ret = qcom_smd_channel_recv_single(channel);
530 if (ret) 578 if (ret)
@@ -535,10 +583,10 @@ static bool qcom_smd_channel_intr(struct qcom_smd_channel *channel)
535 } 583 }
536 584
537 /* Indicate that we have seen and updated tail */ 585 /* Indicate that we have seen and updated tail */
538 SET_RX_CHANNEL_INFO(channel, fTAIL, 1); 586 SET_RX_CHANNEL_FLAG(channel, fTAIL, 1);
539 587
540 /* Signal the remote that we've consumed the data (if requested) */ 588 /* Signal the remote that we've consumed the data (if requested) */
541 if (!GET_RX_CHANNEL_INFO(channel, fBLOCKREADINTR)) { 589 if (!GET_RX_CHANNEL_FLAG(channel, fBLOCKREADINTR)) {
542 /* Ensure ordering of channel info updates */ 590 /* Ensure ordering of channel info updates */
543 wmb(); 591 wmb();
544 592
@@ -667,7 +715,7 @@ static int qcom_smd_write_fifo(struct qcom_smd_channel *channel,
667 */ 715 */
668int qcom_smd_send(struct qcom_smd_channel *channel, const void *data, int len) 716int qcom_smd_send(struct qcom_smd_channel *channel, const void *data, int len)
669{ 717{
670 u32 hdr[5] = {len,}; 718 __le32 hdr[5] = { cpu_to_le32(len), };
671 int tlen = sizeof(hdr) + len; 719 int tlen = sizeof(hdr) + len;
672 int ret; 720 int ret;
673 721
@@ -685,7 +733,7 @@ int qcom_smd_send(struct qcom_smd_channel *channel, const void *data, int len)
685 goto out; 733 goto out;
686 } 734 }
687 735
688 SET_TX_CHANNEL_INFO(channel, fBLOCKREADINTR, 0); 736 SET_TX_CHANNEL_FLAG(channel, fBLOCKREADINTR, 0);
689 737
690 ret = wait_event_interruptible(channel->fblockread_event, 738 ret = wait_event_interruptible(channel->fblockread_event,
691 qcom_smd_get_tx_avail(channel) >= tlen || 739 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 if (ret) 741 if (ret)
694 goto out; 742 goto out;
695 743
696 SET_TX_CHANNEL_INFO(channel, fBLOCKREADINTR, 1); 744 SET_TX_CHANNEL_FLAG(channel, fBLOCKREADINTR, 1);
697 } 745 }
698 746
699 SET_TX_CHANNEL_INFO(channel, fTAIL, 0); 747 SET_TX_CHANNEL_FLAG(channel, fTAIL, 0);
700 748
701 qcom_smd_write_fifo(channel, hdr, sizeof(hdr)); 749 qcom_smd_write_fifo(channel, hdr, sizeof(hdr));
702 qcom_smd_write_fifo(channel, data, len); 750 qcom_smd_write_fifo(channel, data, len);
703 751
704 SET_TX_CHANNEL_INFO(channel, fHEAD, 1); 752 SET_TX_CHANNEL_FLAG(channel, fHEAD, 1);
705 753
706 /* Ensure ordering of channel info updates */ 754 /* Ensure ordering of channel info updates */
707 wmb(); 755 wmb();
@@ -1055,6 +1103,7 @@ static void qcom_discover_channels(struct qcom_smd_edge *edge)
1055 unsigned info_id; 1103 unsigned info_id;
1056 int tbl; 1104 int tbl;
1057 int i; 1105 int i;
1106 u32 eflags, cid;
1058 1107
1059 for (tbl = 0; tbl < SMD_ALLOC_TBL_COUNT; tbl++) { 1108 for (tbl = 0; tbl < SMD_ALLOC_TBL_COUNT; tbl++) {
1060 alloc_tbl = qcom_smem_get(edge->remote_pid, 1109 alloc_tbl = qcom_smem_get(edge->remote_pid,
@@ -1064,6 +1113,7 @@ static void qcom_discover_channels(struct qcom_smd_edge *edge)
1064 1113
1065 for (i = 0; i < SMD_ALLOC_TBL_SIZE; i++) { 1114 for (i = 0; i < SMD_ALLOC_TBL_SIZE; i++) {
1066 entry = &alloc_tbl[i]; 1115 entry = &alloc_tbl[i];
1116 eflags = le32_to_cpu(entry->flags);
1067 if (test_bit(i, edge->allocated[tbl])) 1117 if (test_bit(i, edge->allocated[tbl]))
1068 continue; 1118 continue;
1069 1119
@@ -1073,14 +1123,15 @@ static void qcom_discover_channels(struct qcom_smd_edge *edge)
1073 if (!entry->name[0]) 1123 if (!entry->name[0])
1074 continue; 1124 continue;
1075 1125
1076 if (!(entry->flags & SMD_CHANNEL_FLAGS_PACKET)) 1126 if (!(eflags & SMD_CHANNEL_FLAGS_PACKET))
1077 continue; 1127 continue;
1078 1128
1079 if ((entry->flags & SMD_CHANNEL_FLAGS_EDGE_MASK) != edge->edge_id) 1129 if ((eflags & SMD_CHANNEL_FLAGS_EDGE_MASK) != edge->edge_id)
1080 continue; 1130 continue;
1081 1131
1082 info_id = smem_items[tbl].info_base_id + entry->cid; 1132 cid = le32_to_cpu(entry->cid);
1083 fifo_id = smem_items[tbl].fifo_base_id + entry->cid; 1133 info_id = smem_items[tbl].info_base_id + cid;
1134 fifo_id = smem_items[tbl].fifo_base_id + cid;
1084 1135
1085 channel = qcom_smd_create_channel(edge, info_id, fifo_id, entry->name); 1136 channel = qcom_smd_create_channel(edge, info_id, fifo_id, entry->name);
1086 if (IS_ERR(channel)) 1137 if (IS_ERR(channel))