aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-msm/smd.c
diff options
context:
space:
mode:
authorBrian Swetland <swetland@google.com>2009-04-26 21:38:49 -0400
committerDaniel Walker <dwalker@codeaurora.org>2010-05-12 12:15:01 -0400
commit5b0f5a3f6084397194a8b556cdca572ad8e14f05 (patch)
tree1835a38df270d648ab55af164885389ec9579581 /arch/arm/mach-msm/smd.c
parent4d4fb2660ddd2d8131ebc3314e4c648fc0f4b8dd (diff)
msm: smd: initial support for smd v2
- support both v2 and v1 style smd channels - support both v2 and v1 smsm shared state - update smsm state defines and smem item enum - prep work for dealing with smd to qdsp6 - simplify some smem access to minimize use of smem_alloc() at runtime Signed-off-by: Brian Swetland <swetland@google.com> Signed-off-by: Daniel Walker <dwalker@codeaurora.org>
Diffstat (limited to 'arch/arm/mach-msm/smd.c')
-rw-r--r--arch/arm/mach-msm/smd.c426
1 files changed, 258 insertions, 168 deletions
diff --git a/arch/arm/mach-msm/smd.c b/arch/arm/mach-msm/smd.c
index 78031c0a6db3..f731ddeaa25c 100644
--- a/arch/arm/mach-msm/smd.c
+++ b/arch/arm/mach-msm/smd.c
@@ -46,10 +46,26 @@ enum {
46 46
47static int msm_smd_debug_mask; 47static int msm_smd_debug_mask;
48 48
49struct shared_info
50{
51 int ready;
52 unsigned state_apps;
53 unsigned state_modem;
54};
55
56static unsigned dummy_state_apps;
57static unsigned dummy_state_modem;
58
59static struct shared_info smd_info = {
60 .state_apps = (unsigned) &dummy_state_apps,
61 .state_modem = (unsigned) &dummy_state_modem,
62};
63
49module_param_named(debug_mask, msm_smd_debug_mask, 64module_param_named(debug_mask, msm_smd_debug_mask,
50 int, S_IRUGO | S_IWUSR | S_IWGRP); 65 int, S_IRUGO | S_IWUSR | S_IWGRP);
51 66
52void *smem_find(unsigned id, unsigned size); 67void *smem_find(unsigned id, unsigned size);
68static void *smem_item(unsigned id, unsigned *size);
53static void smd_diag(void); 69static void smd_diag(void);
54 70
55static unsigned last_heap_free = 0xffffffff; 71static unsigned last_heap_free = 0xffffffff;
@@ -61,11 +77,16 @@ static inline void notify_other_smsm(void)
61 writel(1, MSM_A2M_INT(5)); 77 writel(1, MSM_A2M_INT(5));
62} 78}
63 79
64static inline void notify_other_smd(void) 80static inline void notify_modem_smd(void)
65{ 81{
66 writel(1, MSM_A2M_INT(0)); 82 writel(1, MSM_A2M_INT(0));
67} 83}
68 84
85static inline void notify_dsp_smd(void)
86{
87 writel(1, MSM_A2M_INT(8));
88}
89
69static void smd_diag(void) 90static void smd_diag(void)
70{ 91{
71 char *x; 92 char *x;
@@ -96,34 +117,25 @@ extern int (*msm_check_for_modem_crash)(void);
96 117
97static int check_for_modem_crash(void) 118static int check_for_modem_crash(void)
98{ 119{
99 struct smsm_shared *smsm; 120 if (readl(smd_info.state_modem) & SMSM_RESET) {
100
101 smsm = smem_find(ID_SHARED_STATE, 2 * sizeof(struct smsm_shared));
102
103 /* if the modem's not ready yet, we have to hope for the best */
104 if (!smsm)
105 return 0;
106
107 if (smsm[1].state & SMSM_RESET) {
108 handle_modem_crash(); 121 handle_modem_crash();
109 return -1; 122 return -1;
110 } else {
111 return 0;
112 } 123 }
124 return 0;
113} 125}
114 126
115#define SMD_SS_CLOSED 0x00000000 127#define SMD_SS_CLOSED 0x00000000
116#define SMD_SS_OPENING 0x00000001 128#define SMD_SS_OPENING 0x00000001
117#define SMD_SS_OPENED 0x00000002 129#define SMD_SS_OPENED 0x00000002
118#define SMD_SS_FLUSHING 0x00000003 130#define SMD_SS_FLUSHING 0x00000003
119#define SMD_SS_CLOSING 0x00000004 131#define SMD_SS_CLOSING 0x00000004
120#define SMD_SS_RESET 0x00000005 132#define SMD_SS_RESET 0x00000005
121#define SMD_SS_RESET_OPENING 0x00000006 133#define SMD_SS_RESET_OPENING 0x00000006
122 134
123#define SMD_BUF_SIZE 8192 135#define SMD_BUF_SIZE 8192
124#define SMD_CHANNELS 64 136#define SMD_CHANNELS 64
125 137
126#define SMD_HEADER_SIZE 20 138#define SMD_HEADER_SIZE 20
127 139
128 140
129/* the spinlock is used to synchronize between the 141/* the spinlock is used to synchronize between the
@@ -160,21 +172,33 @@ struct smd_half_channel {
160 unsigned char fUNUSED; 172 unsigned char fUNUSED;
161 unsigned tail; 173 unsigned tail;
162 unsigned head; 174 unsigned head;
163 unsigned char data[SMD_BUF_SIZE]; 175} __attribute__((packed));
164};
165 176
166struct smd_shared { 177struct smd_shared_v1 {
167 struct smd_half_channel ch0; 178 struct smd_half_channel ch0;
179 unsigned char data0[SMD_BUF_SIZE];
168 struct smd_half_channel ch1; 180 struct smd_half_channel ch1;
181 unsigned char data1[SMD_BUF_SIZE];
169}; 182};
170 183
184struct smd_shared_v2 {
185 struct smd_half_channel ch0;
186 struct smd_half_channel ch1;
187};
188
171struct smd_channel { 189struct smd_channel {
172 volatile struct smd_half_channel *send; 190 volatile struct smd_half_channel *send;
173 volatile struct smd_half_channel *recv; 191 volatile struct smd_half_channel *recv;
174 struct list_head ch_list; 192 unsigned char *send_data;
193 unsigned char *recv_data;
175 194
195 unsigned fifo_mask;
196 unsigned fifo_size;
176 unsigned current_packet; 197 unsigned current_packet;
177 unsigned n; 198 unsigned n;
199
200 struct list_head ch_list;
201
178 void *priv; 202 void *priv;
179 void (*notify)(void *priv, unsigned flags); 203 void (*notify)(void *priv, unsigned flags);
180 204
@@ -185,22 +209,35 @@ struct smd_channel {
185 209
186 void (*update_state)(smd_channel_t *ch); 210 void (*update_state)(smd_channel_t *ch);
187 unsigned last_state; 211 unsigned last_state;
212 void (*notify_other_cpu)(void);
213 unsigned type;
188 214
189 char name[32]; 215 char name[32];
190 struct platform_device pdev; 216 struct platform_device pdev;
191}; 217};
192 218
193static LIST_HEAD(smd_ch_closed_list); 219static LIST_HEAD(smd_ch_closed_list);
194static LIST_HEAD(smd_ch_list); 220static LIST_HEAD(smd_ch_list); /* todo: per-target lists */
195 221
196static unsigned char smd_ch_allocated[64]; 222static unsigned char smd_ch_allocated[64];
197static struct work_struct probe_work; 223static struct work_struct probe_work;
198 224
225#define SMD_TYPE_MASK 0x0FF
226#define SMD_TYPE_APPS_MODEM 0x000
227#define SMD_TYPE_APPS_DSP 0x001
228#define SMD_TYPE_MODEM_DSP 0x002
229
230#define SMD_KIND_MASK 0xF00
231#define SMD_KIND_UNKNOWN 0x000
232#define SMD_KIND_STREAM 0x100
233#define SMD_KIND_PACKET 0x200
234
199static void smd_alloc_channel(const char *name, uint32_t cid, uint32_t type); 235static void smd_alloc_channel(const char *name, uint32_t cid, uint32_t type);
200 236
201static void smd_channel_probe_worker(struct work_struct *work) 237static void smd_channel_probe_worker(struct work_struct *work)
202{ 238{
203 struct smd_alloc_elm *shared; 239 struct smd_alloc_elm *shared;
240 unsigned type;
204 unsigned n; 241 unsigned n;
205 242
206 shared = smem_find(ID_CH_ALLOC_TBL, sizeof(*shared) * 64); 243 shared = smem_find(ID_CH_ALLOC_TBL, sizeof(*shared) * 64);
@@ -215,9 +252,12 @@ static void smd_channel_probe_worker(struct work_struct *work)
215 continue; 252 continue;
216 if (!shared[n].name[0]) 253 if (!shared[n].name[0])
217 continue; 254 continue;
218 smd_alloc_channel(shared[n].name, 255 type = shared[n].ctype & SMD_TYPE_MASK;
219 shared[n].cid, 256 if ((type == SMD_TYPE_APPS_MODEM) ||
220 shared[n].ctype); 257 (type == SMD_TYPE_APPS_DSP))
258 smd_alloc_channel(shared[n].name,
259 shared[n].cid,
260 shared[n].ctype);
221 smd_ch_allocated[n] = 1; 261 smd_ch_allocated[n] = 1;
222 } 262 }
223} 263}
@@ -247,14 +287,14 @@ static char *chstate(unsigned n)
247/* how many bytes are available for reading */ 287/* how many bytes are available for reading */
248static int smd_stream_read_avail(struct smd_channel *ch) 288static int smd_stream_read_avail(struct smd_channel *ch)
249{ 289{
250 return (ch->recv->head - ch->recv->tail) & (SMD_BUF_SIZE - 1); 290 return (ch->recv->head - ch->recv->tail) & ch->fifo_mask;
251} 291}
252 292
253/* how many bytes we are free to write */ 293/* how many bytes we are free to write */
254static int smd_stream_write_avail(struct smd_channel *ch) 294static int smd_stream_write_avail(struct smd_channel *ch)
255{ 295{
256 return (SMD_BUF_SIZE - 1) - 296 return ch->fifo_mask -
257 ((ch->send->head - ch->send->tail) & (SMD_BUF_SIZE - 1)); 297 ((ch->send->head - ch->send->tail) & ch->fifo_mask);
258} 298}
259 299
260static int smd_packet_read_avail(struct smd_channel *ch) 300static int smd_packet_read_avail(struct smd_channel *ch)
@@ -286,19 +326,19 @@ static unsigned ch_read_buffer(struct smd_channel *ch, void **ptr)
286{ 326{
287 unsigned head = ch->recv->head; 327 unsigned head = ch->recv->head;
288 unsigned tail = ch->recv->tail; 328 unsigned tail = ch->recv->tail;
289 *ptr = (void *) (ch->recv->data + tail); 329 *ptr = (void *) (ch->recv_data + tail);
290 330
291 if (tail <= head) 331 if (tail <= head)
292 return head - tail; 332 return head - tail;
293 else 333 else
294 return SMD_BUF_SIZE - tail; 334 return ch->fifo_size - tail;
295} 335}
296 336
297/* advance the fifo read pointer after data from ch_read_buffer is consumed */ 337/* advance the fifo read pointer after data from ch_read_buffer is consumed */
298static void ch_read_done(struct smd_channel *ch, unsigned count) 338static void ch_read_done(struct smd_channel *ch, unsigned count)
299{ 339{
300 BUG_ON(count > smd_stream_read_avail(ch)); 340 BUG_ON(count > smd_stream_read_avail(ch));
301 ch->recv->tail = (ch->recv->tail + count) & (SMD_BUF_SIZE - 1); 341 ch->recv->tail = (ch->recv->tail + count) & ch->fifo_mask;
302 ch->recv->fTAIL = 1; 342 ch->recv->fTAIL = 1;
303} 343}
304 344
@@ -360,15 +400,15 @@ static unsigned ch_write_buffer(struct smd_channel *ch, void **ptr)
360{ 400{
361 unsigned head = ch->send->head; 401 unsigned head = ch->send->head;
362 unsigned tail = ch->send->tail; 402 unsigned tail = ch->send->tail;
363 *ptr = (void *) (ch->send->data + head); 403 *ptr = (void *) (ch->send_data + head);
364 404
365 if (head < tail) { 405 if (head < tail) {
366 return tail - head - 1; 406 return tail - head - 1;
367 } else { 407 } else {
368 if (tail == 0) 408 if (tail == 0)
369 return SMD_BUF_SIZE - head - 1; 409 return ch->fifo_size - head - 1;
370 else 410 else
371 return SMD_BUF_SIZE - head; 411 return ch->fifo_size - head;
372 } 412 }
373} 413}
374 414
@@ -378,24 +418,24 @@ static unsigned ch_write_buffer(struct smd_channel *ch, void **ptr)
378static void ch_write_done(struct smd_channel *ch, unsigned count) 418static void ch_write_done(struct smd_channel *ch, unsigned count)
379{ 419{
380 BUG_ON(count > smd_stream_write_avail(ch)); 420 BUG_ON(count > smd_stream_write_avail(ch));
381 ch->send->head = (ch->send->head + count) & (SMD_BUF_SIZE - 1); 421 ch->send->head = (ch->send->head + count) & ch->fifo_mask;
382 ch->send->fHEAD = 1; 422 ch->send->fHEAD = 1;
383} 423}
384 424
385static void hc_set_state(volatile struct smd_half_channel *hc, unsigned n) 425static void ch_set_state(struct smd_channel *ch, unsigned n)
386{ 426{
387 if (n == SMD_SS_OPENED) { 427 if (n == SMD_SS_OPENED) {
388 hc->fDSR = 1; 428 ch->send->fDSR = 1;
389 hc->fCTS = 1; 429 ch->send->fCTS = 1;
390 hc->fCD = 1; 430 ch->send->fCD = 1;
391 } else { 431 } else {
392 hc->fDSR = 0; 432 ch->send->fDSR = 0;
393 hc->fCTS = 0; 433 ch->send->fCTS = 0;
394 hc->fCD = 0; 434 ch->send->fCD = 0;
395 } 435 }
396 hc->state = n; 436 ch->send->state = n;
397 hc->fSTATE = 1; 437 ch->send->fSTATE = 1;
398 notify_other_smd(); 438 ch->notify_other_cpu();
399} 439}
400 440
401static void do_smd_probe(void) 441static void do_smd_probe(void)
@@ -420,7 +460,7 @@ static void smd_state_change(struct smd_channel *ch,
420 ch->recv->tail = 0; 460 ch->recv->tail = 0;
421 case SMD_SS_OPENED: 461 case SMD_SS_OPENED:
422 if (ch->send->state != SMD_SS_OPENED) 462 if (ch->send->state != SMD_SS_OPENED)
423 hc_set_state(ch->send, SMD_SS_OPENED); 463 ch_set_state(ch, SMD_SS_OPENED);
424 ch->notify(ch->priv, SMD_EVENT_OPEN); 464 ch->notify(ch->priv, SMD_EVENT_OPEN);
425 break; 465 break;
426 case SMD_SS_FLUSHING: 466 case SMD_SS_FLUSHING:
@@ -431,7 +471,7 @@ static void smd_state_change(struct smd_channel *ch,
431 } 471 }
432} 472}
433 473
434static irqreturn_t smd_irq_handler(int irq, void *data) 474static void handle_smd_irq(struct list_head *list, void (*notify)(void))
435{ 475{
436 unsigned long flags; 476 unsigned long flags;
437 struct smd_channel *ch; 477 struct smd_channel *ch;
@@ -440,7 +480,7 @@ static irqreturn_t smd_irq_handler(int irq, void *data)
440 unsigned tmp; 480 unsigned tmp;
441 481
442 spin_lock_irqsave(&smd_lock, flags); 482 spin_lock_irqsave(&smd_lock, flags);
443 list_for_each_entry(ch, &smd_ch_list, ch_list) { 483 list_for_each_entry(ch, list, ch_list) {
444 ch_flags = 0; 484 ch_flags = 0;
445 if (ch_is_open(ch)) { 485 if (ch_is_open(ch)) {
446 if (ch->recv->fHEAD) { 486 if (ch->recv->fHEAD) {
@@ -468,9 +508,14 @@ static irqreturn_t smd_irq_handler(int irq, void *data)
468 } 508 }
469 } 509 }
470 if (do_notify) 510 if (do_notify)
471 notify_other_smd(); 511 notify();
472 spin_unlock_irqrestore(&smd_lock, flags); 512 spin_unlock_irqrestore(&smd_lock, flags);
473 do_smd_probe(); 513 do_smd_probe();
514}
515
516static irqreturn_t smd_irq_handler(int irq, void *data)
517{
518 handle_smd_irq(&smd_ch_list, notify_modem_smd);
474 return IRQ_HANDLED; 519 return IRQ_HANDLED;
475} 520}
476 521
@@ -553,12 +598,19 @@ void smd_kick(smd_channel_t *ch)
553 ch->notify(ch->priv, SMD_EVENT_CLOSE); 598 ch->notify(ch->priv, SMD_EVENT_CLOSE);
554 } 599 }
555 ch->notify(ch->priv, SMD_EVENT_DATA); 600 ch->notify(ch->priv, SMD_EVENT_DATA);
556 notify_other_smd(); 601 ch->notify_other_cpu();
557 spin_unlock_irqrestore(&smd_lock, flags); 602 spin_unlock_irqrestore(&smd_lock, flags);
558} 603}
559 604
560static int smd_is_packet(int chn) 605static int smd_is_packet(int chn, unsigned type)
561{ 606{
607 type &= SMD_KIND_MASK;
608 if (type == SMD_KIND_PACKET)
609 return 1;
610 if (type == SMD_KIND_STREAM)
611 return 0;
612
613 /* older AMSS reports SMD_KIND_UNKNOWN always */
562 if ((chn > 4) || (chn == 1)) 614 if ((chn > 4) || (chn == 1))
563 return 1; 615 return 1;
564 else 616 else
@@ -588,7 +640,7 @@ static int smd_stream_write(smd_channel_t *ch, const void *_data, int len)
588 break; 640 break;
589 } 641 }
590 642
591 notify_other_smd(); 643 ch->notify_other_cpu();
592 644
593 return orig_len - len; 645 return orig_len - len;
594} 646}
@@ -621,7 +673,7 @@ static int smd_stream_read(smd_channel_t *ch, void *data, int len)
621 673
622 r = ch_read(ch, data, len); 674 r = ch_read(ch, data, len);
623 if (r > 0) 675 if (r > 0)
624 notify_other_smd(); 676 ch->notify_other_cpu();
625 677
626 return r; 678 return r;
627} 679}
@@ -639,7 +691,7 @@ static int smd_packet_read(smd_channel_t *ch, void *data, int len)
639 691
640 r = ch_read(ch, data, len); 692 r = ch_read(ch, data, len);
641 if (r > 0) 693 if (r > 0)
642 notify_other_smd(); 694 ch->notify_other_cpu();
643 695
644 spin_lock_irqsave(&smd_lock, flags); 696 spin_lock_irqsave(&smd_lock, flags);
645 ch->current_packet -= r; 697 ch->current_packet -= r;
@@ -649,28 +701,73 @@ static int smd_packet_read(smd_channel_t *ch, void *data, int len)
649 return r; 701 return r;
650} 702}
651 703
652static void smd_alloc_channel(const char *name, uint32_t cid, uint32_t type) 704static int smd_alloc_v2(struct smd_channel *ch)
653{ 705{
654 struct smd_channel *ch; 706 struct smd_shared_v2 *shared2;
655 struct smd_shared *shared; 707 void *buffer;
708 unsigned buffer_sz;
656 709
657 shared = smem_alloc(ID_SMD_CHANNELS + cid, sizeof(*shared)); 710 shared2 = smem_alloc(SMEM_SMD_BASE_ID + ch->n, sizeof(*shared2));
658 if (!shared) { 711 buffer = smem_item(SMEM_SMD_FIFO_BASE_ID + ch->n, &buffer_sz);
659 pr_err("smd_alloc_channel() cid %d does not exist\n", cid); 712
660 return; 713 if (!buffer)
714 return -1;
715
716 /* buffer must be a power-of-two size */
717 if (buffer_sz & (buffer_sz - 1))
718 return -1;
719
720 buffer_sz /= 2;
721 ch->send = &shared2->ch0;
722 ch->recv = &shared2->ch1;
723 ch->send_data = buffer;
724 ch->recv_data = buffer + buffer_sz;
725 ch->fifo_size = buffer_sz;
726 return 0;
727}
728
729static int smd_alloc_v1(struct smd_channel *ch)
730{
731 struct smd_shared_v1 *shared1;
732 shared1 = smem_alloc(ID_SMD_CHANNELS + ch->n, sizeof(*shared1));
733 if (!shared1) {
734 pr_err("smd_alloc_channel() cid %d does not exist\n", ch->n);
735 return -1;
661 } 736 }
737 ch->send = &shared1->ch0;
738 ch->recv = &shared1->ch1;
739 ch->send_data = shared1->data0;
740 ch->recv_data = shared1->data1;
741 ch->fifo_size = SMD_BUF_SIZE;
742 return 0;
743}
744
745
746static void smd_alloc_channel(const char *name, uint32_t cid, uint32_t type)
747{
748 struct smd_channel *ch;
662 749
663 ch = kzalloc(sizeof(struct smd_channel), GFP_KERNEL); 750 ch = kzalloc(sizeof(struct smd_channel), GFP_KERNEL);
664 if (ch == 0) { 751 if (ch == 0) {
665 pr_err("smd_alloc_channel() out of memory\n"); 752 pr_err("smd_alloc_channel() out of memory\n");
666 return; 753 return;
667 } 754 }
668
669 ch->send = &shared->ch0;
670 ch->recv = &shared->ch1;
671 ch->n = cid; 755 ch->n = cid;
672 756
673 if (smd_is_packet(cid)) { 757 if (smd_alloc_v2(ch) && smd_alloc_v1(ch)) {
758 kfree(ch);
759 return;
760 }
761
762 ch->fifo_mask = ch->fifo_size - 1;
763 ch->type = type;
764
765 if ((type & SMD_TYPE_MASK) == SMD_TYPE_APPS_MODEM)
766 ch->notify_other_cpu = notify_modem_smd;
767 else
768 ch->notify_other_cpu = notify_dsp_smd;
769
770 if (smd_is_packet(cid, type)) {
674 ch->read = smd_packet_read; 771 ch->read = smd_packet_read;
675 ch->write = smd_packet_write; 772 ch->write = smd_packet_write;
676 ch->read_avail = smd_packet_read_avail; 773 ch->read_avail = smd_packet_read_avail;
@@ -684,14 +781,17 @@ static void smd_alloc_channel(const char *name, uint32_t cid, uint32_t type)
684 ch->update_state = update_stream_state; 781 ch->update_state = update_stream_state;
685 } 782 }
686 783
687 memcpy(ch->name, "SMD_", 4); 784 if ((type & 0xff) == 0)
785 memcpy(ch->name, "SMD_", 4);
786 else
787 memcpy(ch->name, "DSP_", 4);
688 memcpy(ch->name + 4, name, 20); 788 memcpy(ch->name + 4, name, 20);
689 ch->name[23] = 0; 789 ch->name[23] = 0;
690 ch->pdev.name = ch->name; 790 ch->pdev.name = ch->name;
691 ch->pdev.id = -1; 791 ch->pdev.id = -1;
692 792
693 pr_info("smd_alloc_channel() '%s' cid=%d, shared=%p\n", 793 pr_info("smd_alloc_channel() cid=%02d size=%05d '%s'\n",
694 ch->name, ch->n, shared); 794 ch->n, ch->fifo_size, ch->name);
695 795
696 mutex_lock(&smd_creation_mutex); 796 mutex_lock(&smd_creation_mutex);
697 list_add(&ch->ch_list, &smd_ch_closed_list); 797 list_add(&ch->ch_list, &smd_ch_closed_list);
@@ -759,9 +859,9 @@ int smd_open(const char *name, smd_channel_t **_ch,
759 */ 859 */
760 if (ch->recv->state == SMD_SS_CLOSING) { 860 if (ch->recv->state == SMD_SS_CLOSING) {
761 ch->send->head = 0; 861 ch->send->head = 0;
762 hc_set_state(ch->send, SMD_SS_OPENING); 862 ch_set_state(ch, SMD_SS_OPENING);
763 } else { 863 } else {
764 hc_set_state(ch->send, SMD_SS_OPENED); 864 ch_set_state(ch, SMD_SS_OPENED);
765 } 865 }
766 spin_unlock_irqrestore(&smd_lock, flags); 866 spin_unlock_irqrestore(&smd_lock, flags);
767 smd_kick(ch); 867 smd_kick(ch);
@@ -781,7 +881,7 @@ int smd_close(smd_channel_t *ch)
781 spin_lock_irqsave(&smd_lock, flags); 881 spin_lock_irqsave(&smd_lock, flags);
782 ch->notify = do_nothing_notify; 882 ch->notify = do_nothing_notify;
783 list_del(&ch->ch_list); 883 list_del(&ch->ch_list);
784 hc_set_state(ch->send, SMD_SS_CLOSED); 884 ch_set_state(ch, SMD_SS_CLOSED);
785 spin_unlock_irqrestore(&smd_lock, flags); 885 spin_unlock_irqrestore(&smd_lock, flags);
786 886
787 mutex_lock(&smd_creation_mutex); 887 mutex_lock(&smd_creation_mutex);
@@ -834,7 +934,7 @@ void *smem_alloc(unsigned id, unsigned size)
834 return smem_find(id, size); 934 return smem_find(id, size);
835} 935}
836 936
837static void *_smem_find(unsigned id, unsigned *size) 937static void *smem_item(unsigned id, unsigned *size)
838{ 938{
839 struct smem_shared *shared = (void *) MSM_SHARED_RAM_BASE; 939 struct smem_shared *shared = (void *) MSM_SHARED_RAM_BASE;
840 struct smem_heap_entry *toc = shared->heap_toc; 940 struct smem_heap_entry *toc = shared->heap_toc;
@@ -845,6 +945,8 @@ static void *_smem_find(unsigned id, unsigned *size)
845 if (toc[id].allocated) { 945 if (toc[id].allocated) {
846 *size = toc[id].size; 946 *size = toc[id].size;
847 return (void *) (MSM_SHARED_RAM_BASE + toc[id].offset); 947 return (void *) (MSM_SHARED_RAM_BASE + toc[id].offset);
948 } else {
949 *size = 0;
848 } 950 }
849 951
850 return 0; 952 return 0;
@@ -855,7 +957,7 @@ void *smem_find(unsigned id, unsigned size_in)
855 unsigned size; 957 unsigned size;
856 void *ptr; 958 void *ptr;
857 959
858 ptr = _smem_find(id, &size); 960 ptr = smem_item(id, &size);
859 if (!ptr) 961 if (!ptr)
860 return 0; 962 return 0;
861 963
@@ -872,38 +974,20 @@ void *smem_find(unsigned id, unsigned size_in)
872static irqreturn_t smsm_irq_handler(int irq, void *data) 974static irqreturn_t smsm_irq_handler(int irq, void *data)
873{ 975{
874 unsigned long flags; 976 unsigned long flags;
875 struct smsm_shared *smsm; 977 unsigned apps, modm;
876 978
877 spin_lock_irqsave(&smem_lock, flags); 979 spin_lock_irqsave(&smem_lock, flags);
878 smsm = smem_alloc(ID_SHARED_STATE,
879 2 * sizeof(struct smsm_shared));
880 980
881 if (smsm == 0) { 981 apps = readl(smd_info.state_apps);
882 pr_info("<SM NO STATE>\n"); 982 modm = readl(smd_info.state_modem);
883 } else {
884 unsigned apps = smsm[0].state;
885 unsigned modm = smsm[1].state;
886
887 if (msm_smd_debug_mask & MSM_SMSM_DEBUG)
888 pr_info("<SM %08x %08x>\n", apps, modm);
889 if (modm & SMSM_RESET) {
890 handle_modem_crash();
891 } else {
892 apps |= SMSM_INIT;
893 if (modm & SMSM_SMDINIT)
894 apps |= SMSM_SMDINIT;
895 if (modm & SMSM_RPCINIT)
896 apps |= SMSM_RPCINIT;
897 }
898 983
899 if (smsm[0].state != apps) { 984 if (msm_smd_debug_mask & MSM_SMSM_DEBUG)
900 if (msm_smd_debug_mask & MSM_SMSM_DEBUG) 985 pr_info("<SM %08x %08x>\n", apps, modm);
901 pr_info("<SM %08x NOTIFY>\n", apps); 986 if (modm & SMSM_RESET) {
902 smsm[0].state = apps; 987 handle_modem_crash();
903 do_smd_probe();
904 notify_other_smsm();
905 }
906 } 988 }
989 do_smd_probe();
990
907 spin_unlock_irqrestore(&smem_lock, flags); 991 spin_unlock_irqrestore(&smem_lock, flags);
908 return IRQ_HANDLED; 992 return IRQ_HANDLED;
909} 993}
@@ -911,55 +995,42 @@ static irqreturn_t smsm_irq_handler(int irq, void *data)
911int smsm_change_state(uint32_t clear_mask, uint32_t set_mask) 995int smsm_change_state(uint32_t clear_mask, uint32_t set_mask)
912{ 996{
913 unsigned long flags; 997 unsigned long flags;
914 struct smsm_shared *smsm; 998 unsigned state;
999
1000 if (!smd_info.ready)
1001 return -EIO;
915 1002
916 spin_lock_irqsave(&smem_lock, flags); 1003 spin_lock_irqsave(&smem_lock, flags);
917 1004
918 smsm = smem_alloc(ID_SHARED_STATE, 1005 if (readl(smd_info.state_modem) & SMSM_RESET)
919 2 * sizeof(struct smsm_shared)); 1006 handle_modem_crash();
920 1007
921 if (smsm) { 1008 state = (readl(smd_info.state_apps) & ~clear_mask) | set_mask;
922 if (smsm[1].state & SMSM_RESET) 1009 writel(state, smd_info.state_apps);
923 handle_modem_crash(); 1010
924 smsm[0].state = (smsm[0].state & ~clear_mask) | set_mask; 1011 if (msm_smd_debug_mask & MSM_SMSM_DEBUG)
925 if (msm_smd_debug_mask & MSM_SMSM_DEBUG) 1012 pr_info("smsm_change_state %x\n", state);
926 pr_info("smsm_change_state %x\n", 1013 notify_other_smsm();
927 smsm[0].state);
928 notify_other_smsm();
929 }
930 1014
931 spin_unlock_irqrestore(&smem_lock, flags); 1015 spin_unlock_irqrestore(&smem_lock, flags);
932 1016
933 if (smsm == NULL) {
934 pr_err("smsm_change_state <SM NO STATE>\n");
935 return -EIO;
936 }
937 return 0; 1017 return 0;
938} 1018}
939 1019
940uint32_t smsm_get_state(void) 1020uint32_t smsm_get_state(void)
941{ 1021{
942 unsigned long flags; 1022 unsigned long flags;
943 struct smsm_shared *smsm;
944 uint32_t rv; 1023 uint32_t rv;
945 1024
946 spin_lock_irqsave(&smem_lock, flags); 1025 spin_lock_irqsave(&smem_lock, flags);
947 1026
948 smsm = smem_alloc(ID_SHARED_STATE, 1027 rv = readl(smd_info.state_modem);
949 2 * sizeof(struct smsm_shared));
950
951 if (smsm)
952 rv = smsm[1].state;
953 else
954 rv = 0;
955 1028
956 if (rv & SMSM_RESET) 1029 if (rv & SMSM_RESET)
957 handle_modem_crash(); 1030 handle_modem_crash();
958 1031
959 spin_unlock_irqrestore(&smem_lock, flags); 1032 spin_unlock_irqrestore(&smem_lock, flags);
960 1033
961 if (smsm == NULL)
962 pr_err("smsm_get_state <SM NO STATE>\n");
963 return rv; 1034 return rv;
964} 1035}
965 1036
@@ -1069,6 +1140,25 @@ int smd_core_init(void)
1069 int r; 1140 int r;
1070 pr_info("smd_core_init()\n"); 1141 pr_info("smd_core_init()\n");
1071 1142
1143 /* wait for essential items to be initialized */
1144 for (;;) {
1145 unsigned size;
1146 void *state;
1147 state = smem_item(SMEM_SMSM_SHARED_STATE, &size);
1148 if (size == SMSM_V1_SIZE) {
1149 smd_info.state_apps = state + SMSM_V1_STATE_APPS;
1150 smd_info.state_modem = state + SMSM_V1_STATE_MODEM;
1151 break;
1152 }
1153 if (size == SMSM_V2_SIZE) {
1154 smd_info.state_apps = state + SMSM_V2_STATE_APPS;
1155 smd_info.state_modem = state + SMSM_V2_STATE_MODEM;
1156 break;
1157 }
1158 }
1159
1160 smd_info.ready = 1;
1161
1072 r = request_irq(INT_A9_M2A_0, smd_irq_handler, 1162 r = request_irq(INT_A9_M2A_0, smd_irq_handler,
1073 IRQF_TRIGGER_RISING, "smd_dev", 0); 1163 IRQF_TRIGGER_RISING, "smd_dev", 0);
1074 if (r < 0) 1164 if (r < 0)
@@ -1087,11 +1177,12 @@ int smd_core_init(void)
1087 if (r < 0) 1177 if (r < 0)
1088 pr_err("smd_core_init: enable_irq_wake failed for A9_M2A_5\n"); 1178 pr_err("smd_core_init: enable_irq_wake failed for A9_M2A_5\n");
1089 1179
1090 /* we may have missed a signal while booting -- fake 1180 /* check for any SMD channels that may already exist */
1091 * an interrupt to make sure we process any existing 1181 do_smd_probe();
1092 * state 1182
1093 */ 1183 /* indicate that we're up and running */
1094 smsm_irq_handler(0, 0); 1184 writel(SMSM_INIT | SMSM_SMDINIT | SMSM_RPCINIT, smd_info.state_apps);
1185 notify_other_smsm();
1095 1186
1096 pr_info("smd_core_init() done\n"); 1187 pr_info("smd_core_init() done\n");
1097 1188
@@ -1100,15 +1191,16 @@ int smd_core_init(void)
1100 1191
1101#if defined(CONFIG_DEBUG_FS) 1192#if defined(CONFIG_DEBUG_FS)
1102 1193
1103static int dump_ch(char *buf, int max, int n, 1194static int dump_ch(char *buf, int max, struct smd_channel *ch)
1104 struct smd_half_channel *s,
1105 struct smd_half_channel *r)
1106{ 1195{
1196 volatile struct smd_half_channel *s = ch->send;
1197 volatile struct smd_half_channel *r = ch->recv;
1198
1107 return scnprintf( 1199 return scnprintf(
1108 buf, max, 1200 buf, max,
1109 "ch%02d:" 1201 "ch%02d:"
1110 " %8s(%04d/%04d) %c%c%c%c%c%c%c <->" 1202 " %8s(%05d/%05d) %c%c%c%c%c%c%c <->"
1111 " %8s(%04d/%04d) %c%c%c%c%c%c%c\n", n, 1203 " %8s(%05d/%05d) %c%c%c%c%c%c%c\n", ch->n,
1112 chstate(s->state), s->tail, s->head, 1204 chstate(s->state), s->tail, s->head,
1113 s->fDSR ? 'D' : 'd', 1205 s->fDSR ? 'D' : 'd',
1114 s->fCTS ? 'C' : 'c', 1206 s->fCTS ? 'C' : 'c',
@@ -1130,24 +1222,19 @@ static int dump_ch(char *buf, int max, int n,
1130 1222
1131static int debug_read_stat(char *buf, int max) 1223static int debug_read_stat(char *buf, int max)
1132{ 1224{
1133 struct smsm_shared *smsm;
1134 char *msg; 1225 char *msg;
1135 int i = 0; 1226 int i = 0;
1136 1227
1137 smsm = smem_find(ID_SHARED_STATE,
1138 2 * sizeof(struct smsm_shared));
1139
1140 msg = smem_find(ID_DIAG_ERR_MSG, SZ_DIAG_ERR_MSG); 1228 msg = smem_find(ID_DIAG_ERR_MSG, SZ_DIAG_ERR_MSG);
1141 1229
1142 if (smsm) { 1230 if (readl(smd_info.state_modem) & SMSM_RESET)
1143 if (smsm[1].state & SMSM_RESET) 1231 i += scnprintf(buf + i, max - i,
1144 i += scnprintf(buf + i, max - i, 1232 "smsm: ARM9 HAS CRASHED\n");
1145 "smsm: ARM9 HAS CRASHED\n"); 1233
1146 i += scnprintf(buf + i, max - i, "smsm: a9: %08x a11: %08x\n", 1234 i += scnprintf(buf + i, max - i, "smsm: a9: %08x a11: %08x\n",
1147 smsm[0].state, smsm[1].state); 1235 readl(smd_info.state_modem),
1148 } else { 1236 readl(smd_info.state_apps));
1149 i += scnprintf(buf + i, max - i, "smsm: cannot find\n"); 1237
1150 }
1151 if (msg) { 1238 if (msg) {
1152 msg[SZ_DIAG_ERR_MSG - 1] = 0; 1239 msg[SZ_DIAG_ERR_MSG - 1] = 0;
1153 i += scnprintf(buf + i, max - i, "diag: '%s'\n", msg); 1240 i += scnprintf(buf + i, max - i, "diag: '%s'\n", msg);
@@ -1172,7 +1259,7 @@ static int debug_read_mem(char *buf, int max)
1172 if (toc[n].allocated == 0) 1259 if (toc[n].allocated == 0)
1173 continue; 1260 continue;
1174 i += scnprintf(buf + i, max - i, 1261 i += scnprintf(buf + i, max - i,
1175 "%04d: offsed %08x size %08x\n", 1262 "%04d: offset %08x size %08x\n",
1176 n, toc[n].offset, toc[n].size); 1263 n, toc[n].offset, toc[n].size);
1177 } 1264 }
1178 return i; 1265 return i;
@@ -1180,16 +1267,16 @@ static int debug_read_mem(char *buf, int max)
1180 1267
1181static int debug_read_ch(char *buf, int max) 1268static int debug_read_ch(char *buf, int max)
1182{ 1269{
1183 struct smd_shared *shared; 1270 struct smd_channel *ch;
1184 int n, i = 0; 1271 unsigned long flags;
1272 int i = 0;
1185 1273
1186 for (n = 0; n < SMD_CHANNELS; n++) { 1274 spin_lock_irqsave(&smd_lock, flags);
1187 shared = smem_find(ID_SMD_CHANNELS + n, 1275 list_for_each_entry(ch, &smd_ch_list, ch_list)
1188 sizeof(struct smd_shared)); 1276 i += dump_ch(buf + i, max - i, ch);
1189 if (shared == 0) 1277 list_for_each_entry(ch, &smd_ch_closed_list, ch_list)
1190 continue; 1278 i += dump_ch(buf + i, max - i, ch);
1191 i += dump_ch(buf + i, max - i, n, &shared->ch0, &shared->ch1); 1279 spin_unlock_irqrestore(&smd_lock, flags);
1192 }
1193 1280
1194 return i; 1281 return i;
1195} 1282}
@@ -1206,7 +1293,7 @@ static int debug_read_build_id(char *buf, int max)
1206 unsigned size; 1293 unsigned size;
1207 void *data; 1294 void *data;
1208 1295
1209 data = _smem_find(SMEM_HW_SW_BUILD_ID, &size); 1296 data = smem_item(SMEM_HW_SW_BUILD_ID, &size);
1210 if (!data) 1297 if (!data)
1211 return 0; 1298 return 0;
1212 1299
@@ -1228,9 +1315,12 @@ static int debug_read_alloc_tbl(char *buf, int max)
1228 if (shared[n].ref_count == 0) 1315 if (shared[n].ref_count == 0)
1229 continue; 1316 continue;
1230 i += scnprintf(buf + i, max - i, 1317 i += scnprintf(buf + i, max - i,
1231 "%03d: %20s cid=%02d ctype=%d ref_count=%d\n", 1318 "%03d: %-20s cid=%02d type=%03d "
1319 "kind=%02d ref_count=%d\n",
1232 n, shared[n].name, shared[n].cid, 1320 n, shared[n].name, shared[n].cid,
1233 shared[n].ctype, shared[n].ref_count); 1321 shared[n].ctype & 0xff,
1322 (shared[n].ctype >> 8) & 0xf,
1323 shared[n].ref_count);
1234 } 1324 }
1235 1325
1236 return i; 1326 return i;