KVM: x86: update KVM_SAVE_MSRS_BEGIN to correct value
[cascardo/linux.git] / drivers / staging / tidspbridge / core / io_sm.c
1 /*
2  * io_sm.c
3  *
4  * DSP-BIOS Bridge driver support functions for TI OMAP processors.
5  *
6  * IO dispatcher for a shared memory channel driver.
7  *
8  * Copyright (C) 2005-2006 Texas Instruments, Inc.
9  *
10  * This package is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License version 2 as
12  * published by the Free Software Foundation.
13  *
14  * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
15  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
16  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
17  */
18
19 /*
20  * Channel Invariant:
21  * There is an important invariant condition which must be maintained per
22  * channel outside of bridge_chnl_get_ioc() and IO_Dispatch(), violation of
23  * which may cause timeouts and/or failure of the sync_wait_on_event
24  * function.
25  */
26 #include <linux/types.h>
27 #include <linux/list.h>
28
29 /* Host OS */
30 #include <dspbridge/host_os.h>
31 #include <linux/workqueue.h>
32
33 /*  ----------------------------------- DSP/BIOS Bridge */
34 #include <dspbridge/dbdefs.h>
35
36 /* Services Layer */
37 #include <dspbridge/ntfy.h>
38 #include <dspbridge/sync.h>
39
40 /* Hardware Abstraction Layer */
41 #include <hw_defs.h>
42 #include <hw_mmu.h>
43
44 /* Bridge Driver */
45 #include <dspbridge/dspdeh.h>
46 #include <dspbridge/dspio.h>
47 #include <dspbridge/dspioctl.h>
48 #include <dspbridge/wdt.h>
49 #include <_tiomap.h>
50 #include <tiomap_io.h>
51 #include <_tiomap_pwr.h>
52
53 /* Platform Manager */
54 #include <dspbridge/cod.h>
55 #include <dspbridge/node.h>
56 #include <dspbridge/dev.h>
57
58 /* Others */
59 #include <dspbridge/rms_sh.h>
60 #include <dspbridge/mgr.h>
61 #include <dspbridge/drv.h>
62 #include "_cmm.h"
63 #include "module_list.h"
64
65 /* This */
66 #include <dspbridge/io_sm.h>
67 #include "_msg_sm.h"
68
69 /* Defines, Data Structures, Typedefs */
70 #define OUTPUTNOTREADY  0xffff
71 #define NOTENABLED      0xffff  /* Channel(s) not enabled */
72
73 #define EXTEND      "_EXT_END"
74
75 #define SWAP_WORD(x)     (x)
76 #define UL_PAGE_ALIGN_SIZE 0x10000      /* Page Align Size */
77
78 #define MAX_PM_REQS 32
79
80 #define MMU_FAULT_HEAD1 0xa5a5a5a5
81 #define MMU_FAULT_HEAD2 0x96969696
82 #define POLL_MAX 1000
83 #define MAX_MMU_DBGBUFF 10240
84
85 /* IO Manager: only one created per board */
86 struct io_mgr {
87         /* These four fields must be the first fields in a io_mgr_ struct */
88         /* Bridge device context */
89         struct bridge_dev_context *bridge_context;
90         /* Function interface to Bridge driver */
91         struct bridge_drv_interface *intf_fxns;
92         struct dev_object *dev_obj;     /* Device this board represents */
93
94         /* These fields initialized in bridge_io_create() */
95         struct chnl_mgr *chnl_mgr;
96         struct shm *shared_mem; /* Shared Memory control */
97         u8 *input;              /* Address of input channel */
98         u8 *output;             /* Address of output channel */
99         struct msg_mgr *msg_mgr;        /* Message manager */
100         /* Msg control for from DSP messages */
101         struct msg_ctrl *msg_input_ctrl;
102         /* Msg control for to DSP messages */
103         struct msg_ctrl *msg_output_ctrl;
104         u8 *msg_input;          /* Address of input messages */
105         u8 *msg_output;         /* Address of output messages */
106         u32 sm_buf_size;        /* Size of a shared memory I/O channel */
107         bool shared_irq;        /* Is this IRQ shared? */
108         u32 word_size;          /* Size in bytes of DSP word */
109         u16 intr_val;           /* Interrupt value */
110         /* Private extnd proc info; mmu setup */
111         struct mgr_processorextinfo ext_proc_info;
112         struct cmm_object *cmm_mgr;     /* Shared Mem Mngr */
113         struct work_struct io_workq;    /* workqueue */
114 #if defined(CONFIG_TIDSPBRIDGE_BACKTRACE)
115         u32 trace_buffer_begin; /* Trace message start address */
116         u32 trace_buffer_end;   /* Trace message end address */
117         u32 trace_buffer_current;       /* Trace message current address */
118         u32 gpp_read_pointer;           /* GPP Read pointer to Trace buffer */
119         u8 *msg;
120         u32 gpp_va;
121         u32 dsp_va;
122 #endif
123         /* IO Dpc */
124         u32 dpc_req;            /* Number of requested DPC's. */
125         u32 dpc_sched;          /* Number of executed DPC's. */
126         struct tasklet_struct dpc_tasklet;
127         spinlock_t dpc_lock;
128
129 };
130
131 /* Function Prototypes */
132 static void io_dispatch_pm(struct io_mgr *pio_mgr);
133 static void notify_chnl_complete(struct chnl_object *pchnl,
134                                  struct chnl_irp *chnl_packet_obj);
135 static void input_chnl(struct io_mgr *pio_mgr, struct chnl_object *pchnl,
136                         u8 io_mode);
137 static void output_chnl(struct io_mgr *pio_mgr, struct chnl_object *pchnl,
138                         u8 io_mode);
139 static void input_msg(struct io_mgr *pio_mgr, struct msg_mgr *hmsg_mgr);
140 static void output_msg(struct io_mgr *pio_mgr, struct msg_mgr *hmsg_mgr);
141 static u32 find_ready_output(struct chnl_mgr *chnl_mgr_obj,
142                              struct chnl_object *pchnl, u32 mask);
143
144 /* Bus Addr (cached kernel) */
145 static int register_shm_segs(struct io_mgr *hio_mgr,
146                                     struct cod_manager *cod_man,
147                                     u32 dw_gpp_base_pa);
148
149 static inline void set_chnl_free(struct shm *sm, u32 chnl)
150 {
151         sm->host_free_mask &= ~(1 << chnl);
152 }
153
154 static inline void set_chnl_busy(struct shm *sm, u32 chnl)
155 {
156         sm->host_free_mask |= 1 << chnl;
157 }
158
159
160 /*
161  *  ======== bridge_io_create ========
162  *      Create an IO manager object.
163  */
164 int bridge_io_create(struct io_mgr **io_man,
165                             struct dev_object *hdev_obj,
166                             const struct io_attrs *mgr_attrts)
167 {
168         struct io_mgr *pio_mgr = NULL;
169         struct bridge_dev_context *hbridge_context = NULL;
170         struct cfg_devnode *dev_node_obj;
171         struct chnl_mgr *hchnl_mgr;
172         u8 dev_type;
173
174         /* Check requirements */
175         if (!io_man || !mgr_attrts || mgr_attrts->word_size == 0)
176                 return -EFAULT;
177
178         *io_man = NULL;
179
180         dev_get_chnl_mgr(hdev_obj, &hchnl_mgr);
181         if (!hchnl_mgr || hchnl_mgr->iomgr)
182                 return -EFAULT;
183
184         /*
185          * Message manager will be created when a file is loaded, since
186          * size of message buffer in shared memory is configurable in
187          * the base image.
188          */
189         dev_get_bridge_context(hdev_obj, &hbridge_context);
190         if (!hbridge_context)
191                 return -EFAULT;
192
193         dev_get_dev_type(hdev_obj, &dev_type);
194
195         /* Allocate IO manager object */
196         pio_mgr = kzalloc(sizeof(struct io_mgr), GFP_KERNEL);
197         if (!pio_mgr)
198                 return -ENOMEM;
199
200         /* Initialize chnl_mgr object */
201         pio_mgr->chnl_mgr = hchnl_mgr;
202         pio_mgr->word_size = mgr_attrts->word_size;
203
204         if (dev_type == DSP_UNIT) {
205                 /* Create an IO DPC */
206                 tasklet_init(&pio_mgr->dpc_tasklet, io_dpc, (u32) pio_mgr);
207
208                 /* Initialize DPC counters */
209                 pio_mgr->dpc_req = 0;
210                 pio_mgr->dpc_sched = 0;
211
212                 spin_lock_init(&pio_mgr->dpc_lock);
213
214                 if (dev_get_dev_node(hdev_obj, &dev_node_obj)) {
215                         bridge_io_destroy(pio_mgr);
216                         return -EIO;
217                 }
218         }
219
220         pio_mgr->bridge_context = hbridge_context;
221         pio_mgr->shared_irq = mgr_attrts->irq_shared;
222         if (dsp_wdt_init()) {
223                 bridge_io_destroy(pio_mgr);
224                 return -EPERM;
225         }
226
227         /* Return IO manager object to caller... */
228         hchnl_mgr->iomgr = pio_mgr;
229         *io_man = pio_mgr;
230
231         return 0;
232 }
233
234 /*
235  *  ======== bridge_io_destroy ========
236  *  Purpose:
237  *      Disable interrupts, destroy the IO manager.
238  */
239 int bridge_io_destroy(struct io_mgr *hio_mgr)
240 {
241         int status = 0;
242         if (hio_mgr) {
243                 /* Free IO DPC object */
244                 tasklet_kill(&hio_mgr->dpc_tasklet);
245
246 #if defined(CONFIG_TIDSPBRIDGE_BACKTRACE)
247                 kfree(hio_mgr->msg);
248 #endif
249                 dsp_wdt_exit();
250                 /* Free this IO manager object */
251                 kfree(hio_mgr);
252         } else {
253                 status = -EFAULT;
254         }
255
256         return status;
257 }
258
259 /*
260  *  ======== bridge_io_on_loaded ========
261  *  Purpose:
262  *      Called when a new program is loaded to get shared memory buffer
263  *      parameters from COFF file. ulSharedBufferBase and ulSharedBufferLimit
264  *      are in DSP address units.
265  */
266 int bridge_io_on_loaded(struct io_mgr *hio_mgr)
267 {
268         struct cod_manager *cod_man;
269         struct chnl_mgr *hchnl_mgr;
270         struct msg_mgr *hmsg_mgr;
271         u32 ul_shm_base;
272         u32 ul_shm_base_offset;
273         u32 ul_shm_limit;
274         u32 ul_shm_length = -1;
275         u32 ul_mem_length = -1;
276         u32 ul_msg_base;
277         u32 ul_msg_limit;
278         u32 ul_msg_length = -1;
279         u32 ul_ext_end;
280         u32 ul_gpp_pa = 0;
281         u32 ul_gpp_va = 0;
282         u32 ul_dsp_va = 0;
283         u32 ul_seg_size = 0;
284         u32 ul_pad_size = 0;
285         u32 i;
286         int status = 0;
287         u8 num_procs = 0;
288         s32 ndx = 0;
289         /* DSP MMU setup table */
290         struct bridge_ioctl_extproc ae_proc[BRDIOCTL_NUMOFMMUTLB];
291         struct cfg_hostres *host_res;
292         struct bridge_dev_context *pbridge_context;
293         u32 map_attrs;
294         u32 shm0_end;
295         u32 ul_dyn_ext_base;
296         u32 ul_seg1_size = 0;
297         u32 pa_curr = 0;
298         u32 va_curr = 0;
299         u32 gpp_va_curr = 0;
300         u32 num_bytes = 0;
301         u32 all_bits = 0;
302         u32 page_size[] = { HW_PAGE_SIZE16MB, HW_PAGE_SIZE1MB,
303                 HW_PAGE_SIZE64KB, HW_PAGE_SIZE4KB
304         };
305
306         status = dev_get_bridge_context(hio_mgr->dev_obj, &pbridge_context);
307         if (!pbridge_context) {
308                 status = -EFAULT;
309                 goto func_end;
310         }
311
312         host_res = pbridge_context->resources;
313         if (!host_res) {
314                 status = -EFAULT;
315                 goto func_end;
316         }
317         status = dev_get_cod_mgr(hio_mgr->dev_obj, &cod_man);
318         if (!cod_man) {
319                 status = -EFAULT;
320                 goto func_end;
321         }
322         hchnl_mgr = hio_mgr->chnl_mgr;
323         /* The message manager is destroyed when the board is stopped. */
324         dev_get_msg_mgr(hio_mgr->dev_obj, &hio_mgr->msg_mgr);
325         hmsg_mgr = hio_mgr->msg_mgr;
326         if (!hchnl_mgr || !hmsg_mgr) {
327                 status = -EFAULT;
328                 goto func_end;
329         }
330         if (hio_mgr->shared_mem)
331                 hio_mgr->shared_mem = NULL;
332
333         /* Get start and length of channel part of shared memory */
334         status = cod_get_sym_value(cod_man, CHNL_SHARED_BUFFER_BASE_SYM,
335                                    &ul_shm_base);
336         if (status) {
337                 status = -EFAULT;
338                 goto func_end;
339         }
340         status = cod_get_sym_value(cod_man, CHNL_SHARED_BUFFER_LIMIT_SYM,
341                                    &ul_shm_limit);
342         if (status) {
343                 status = -EFAULT;
344                 goto func_end;
345         }
346         if (ul_shm_limit <= ul_shm_base) {
347                 status = -EINVAL;
348                 goto func_end;
349         }
350         /* Get total length in bytes */
351         ul_shm_length = (ul_shm_limit - ul_shm_base + 1) * hio_mgr->word_size;
352         /* Calculate size of a PROCCOPY shared memory region */
353         dev_dbg(bridge, "%s: (proc)proccopy shmmem size: 0x%x bytes\n",
354                 __func__, (ul_shm_length - sizeof(struct shm)));
355
356         /* Get start and length of message part of shared memory */
357         status = cod_get_sym_value(cod_man, MSG_SHARED_BUFFER_BASE_SYM,
358                                            &ul_msg_base);
359         if (!status) {
360                 status = cod_get_sym_value(cod_man, MSG_SHARED_BUFFER_LIMIT_SYM,
361                                            &ul_msg_limit);
362                 if (!status) {
363                         if (ul_msg_limit <= ul_msg_base) {
364                                 status = -EINVAL;
365                         } else {
366                                 /*
367                                  * Length (bytes) of messaging part of shared
368                                  * memory.
369                                  */
370                                 ul_msg_length =
371                                     (ul_msg_limit - ul_msg_base +
372                                      1) * hio_mgr->word_size;
373                                 /*
374                                  * Total length (bytes) of shared memory:
375                                  * chnl + msg.
376                                  */
377                                 ul_mem_length = ul_shm_length + ul_msg_length;
378                         }
379                 } else {
380                         status = -EFAULT;
381                 }
382         } else {
383                 status = -EFAULT;
384         }
385         if (!status) {
386 #if defined(CONFIG_TIDSPBRIDGE_BACKTRACE)
387                 status =
388                     cod_get_sym_value(cod_man, DSP_TRACESEC_END, &shm0_end);
389 #else
390                 status = cod_get_sym_value(cod_man, SHM0_SHARED_END_SYM,
391                                            &shm0_end);
392 #endif
393                 if (status)
394                         status = -EFAULT;
395         }
396         if (!status) {
397                 status =
398                     cod_get_sym_value(cod_man, DYNEXTBASE, &ul_dyn_ext_base);
399                 if (status)
400                         status = -EFAULT;
401         }
402         if (!status) {
403                 status = cod_get_sym_value(cod_man, EXTEND, &ul_ext_end);
404                 if (status)
405                         status = -EFAULT;
406         }
407         if (!status) {
408                 /* Get memory reserved in host resources */
409                 (void)mgr_enum_processor_info(0, (struct dsp_processorinfo *)
410                                               &hio_mgr->ext_proc_info,
411                                               sizeof(struct
412                                                      mgr_processorextinfo),
413                                               &num_procs);
414
415                 /* The first MMU TLB entry(TLB_0) in DCD is ShmBase. */
416                 ndx = 0;
417                 ul_gpp_pa = host_res->mem_phys[1];
418                 ul_gpp_va = host_res->mem_base[1];
419                 /* This is the virtual uncached ioremapped address!!! */
420                 /* Why can't we directly take the DSPVA from the symbols? */
421                 ul_dsp_va = hio_mgr->ext_proc_info.ty_tlb[0].dsp_virt;
422                 ul_seg_size = (shm0_end - ul_dsp_va) * hio_mgr->word_size;
423                 ul_seg1_size =
424                     (ul_ext_end - ul_dyn_ext_base) * hio_mgr->word_size;
425                 /* 4K align */
426                 ul_seg1_size = (ul_seg1_size + 0xFFF) & (~0xFFFUL);
427                 /* 64K align */
428                 ul_seg_size = (ul_seg_size + 0xFFFF) & (~0xFFFFUL);
429                 ul_pad_size = UL_PAGE_ALIGN_SIZE - ((ul_gpp_pa + ul_seg1_size) %
430                                                     UL_PAGE_ALIGN_SIZE);
431                 if (ul_pad_size == UL_PAGE_ALIGN_SIZE)
432                         ul_pad_size = 0x0;
433
434                 dev_dbg(bridge, "%s: ul_gpp_pa %x, ul_gpp_va %x, ul_dsp_va %x, "
435                         "shm0_end %x, ul_dyn_ext_base %x, ul_ext_end %x, "
436                         "ul_seg_size %x ul_seg1_size %x \n", __func__,
437                         ul_gpp_pa, ul_gpp_va, ul_dsp_va, shm0_end,
438                         ul_dyn_ext_base, ul_ext_end, ul_seg_size, ul_seg1_size);
439
440                 if ((ul_seg_size + ul_seg1_size + ul_pad_size) >
441                     host_res->mem_length[1]) {
442                         pr_err("%s: shm Error, reserved 0x%x required 0x%x\n",
443                                __func__, host_res->mem_length[1],
444                                ul_seg_size + ul_seg1_size + ul_pad_size);
445                         status = -ENOMEM;
446                 }
447         }
448         if (status)
449                 goto func_end;
450
451         pa_curr = ul_gpp_pa;
452         va_curr = ul_dyn_ext_base * hio_mgr->word_size;
453         gpp_va_curr = ul_gpp_va;
454         num_bytes = ul_seg1_size;
455
456         /*
457          * Try to fit into TLB entries. If not possible, push them to page
458          * tables. It is quite possible that if sections are not on
459          * bigger page boundary, we may end up making several small pages.
460          * So, push them onto page tables, if that is the case.
461          */
462         map_attrs = 0x00000000;
463         map_attrs = DSP_MAPLITTLEENDIAN;
464         map_attrs |= DSP_MAPPHYSICALADDR;
465         map_attrs |= DSP_MAPELEMSIZE32;
466         map_attrs |= DSP_MAPDONOTLOCK;
467
468         while (num_bytes) {
469                 /*
470                  * To find the max. page size with which both PA & VA are
471                  * aligned.
472                  */
473                 all_bits = pa_curr | va_curr;
474                 dev_dbg(bridge, "all_bits %x, pa_curr %x, va_curr %x, "
475                         "num_bytes %x\n", all_bits, pa_curr, va_curr,
476                         num_bytes);
477                 for (i = 0; i < 4; i++) {
478                         if ((num_bytes >= page_size[i]) && ((all_bits &
479                                                              (page_size[i] -
480                                                               1)) == 0)) {
481                                 status =
482                                     hio_mgr->intf_fxns->
483                                     brd_mem_map(hio_mgr->bridge_context,
484                                                     pa_curr, va_curr,
485                                                     page_size[i], map_attrs,
486                                                     NULL);
487                                 if (status)
488                                         goto func_end;
489                                 pa_curr += page_size[i];
490                                 va_curr += page_size[i];
491                                 gpp_va_curr += page_size[i];
492                                 num_bytes -= page_size[i];
493                                 /*
494                                  * Don't try smaller sizes. Hopefully we have
495                                  * reached an address aligned to a bigger page
496                                  * size.
497                                  */
498                                 break;
499                         }
500                 }
501         }
502         pa_curr += ul_pad_size;
503         va_curr += ul_pad_size;
504         gpp_va_curr += ul_pad_size;
505
506         /* Configure the TLB entries for the next cacheable segment */
507         num_bytes = ul_seg_size;
508         va_curr = ul_dsp_va * hio_mgr->word_size;
509         while (num_bytes) {
510                 /*
511                  * To find the max. page size with which both PA & VA are
512                  * aligned.
513                  */
514                 all_bits = pa_curr | va_curr;
515                 dev_dbg(bridge, "all_bits for Seg1 %x, pa_curr %x, "
516                         "va_curr %x, num_bytes %x\n", all_bits, pa_curr,
517                         va_curr, num_bytes);
518                 for (i = 0; i < 4; i++) {
519                         if (!(num_bytes >= page_size[i]) ||
520                             !((all_bits & (page_size[i] - 1)) == 0))
521                                 continue;
522                         if (ndx < MAX_LOCK_TLB_ENTRIES) {
523                                 /*
524                                  * This is the physical address written to
525                                  * DSP MMU.
526                                  */
527                                 ae_proc[ndx].gpp_pa = pa_curr;
528                                 /*
529                                  * This is the virtual uncached ioremapped
530                                  * address!!!
531                                  */
532                                 ae_proc[ndx].gpp_va = gpp_va_curr;
533                                 ae_proc[ndx].dsp_va =
534                                     va_curr / hio_mgr->word_size;
535                                 ae_proc[ndx].size = page_size[i];
536                                 ae_proc[ndx].endianism = HW_LITTLE_ENDIAN;
537                                 ae_proc[ndx].elem_size = HW_ELEM_SIZE16BIT;
538                                 ae_proc[ndx].mixed_mode = HW_MMU_CPUES;
539                                 dev_dbg(bridge, "shm MMU TLB entry PA %x"
540                                         " VA %x DSP_VA %x Size %x\n",
541                                         ae_proc[ndx].gpp_pa,
542                                         ae_proc[ndx].gpp_va,
543                                         ae_proc[ndx].dsp_va *
544                                         hio_mgr->word_size, page_size[i]);
545                                 ndx++;
546                         } else {
547                                 status =
548                                     hio_mgr->intf_fxns->
549                                     brd_mem_map(hio_mgr->bridge_context,
550                                                     pa_curr, va_curr,
551                                                     page_size[i], map_attrs,
552                                                     NULL);
553                                 dev_dbg(bridge,
554                                         "shm MMU PTE entry PA %x"
555                                         " VA %x DSP_VA %x Size %x\n",
556                                         ae_proc[ndx].gpp_pa,
557                                         ae_proc[ndx].gpp_va,
558                                         ae_proc[ndx].dsp_va *
559                                         hio_mgr->word_size, page_size[i]);
560                                 if (status)
561                                         goto func_end;
562                         }
563                         pa_curr += page_size[i];
564                         va_curr += page_size[i];
565                         gpp_va_curr += page_size[i];
566                         num_bytes -= page_size[i];
567                         /*
568                          * Don't try smaller sizes. Hopefully we have reached
569                          * an address aligned to a bigger page size.
570                          */
571                         break;
572                 }
573         }
574
575         /*
576          * Copy remaining entries from CDB. All entries are 1 MB and
577          * should not conflict with shm entries on MPU or DSP side.
578          */
579         for (i = 3; i < 7 && ndx < BRDIOCTL_NUMOFMMUTLB; i++) {
580                 if (hio_mgr->ext_proc_info.ty_tlb[i].gpp_phys == 0)
581                         continue;
582
583                 if ((hio_mgr->ext_proc_info.ty_tlb[i].gpp_phys >
584                      ul_gpp_pa - 0x100000
585                      && hio_mgr->ext_proc_info.ty_tlb[i].gpp_phys <=
586                      ul_gpp_pa + ul_seg_size)
587                     || (hio_mgr->ext_proc_info.ty_tlb[i].dsp_virt >
588                         ul_dsp_va - 0x100000 / hio_mgr->word_size
589                         && hio_mgr->ext_proc_info.ty_tlb[i].dsp_virt <=
590                         ul_dsp_va + ul_seg_size / hio_mgr->word_size)) {
591                         dev_dbg(bridge,
592                                 "CDB MMU entry %d conflicts with "
593                                 "shm.\n\tCDB: GppPa %x, DspVa %x.\n\tSHM: "
594                                 "GppPa %x, DspVa %x, Bytes %x.\n", i,
595                                 hio_mgr->ext_proc_info.ty_tlb[i].gpp_phys,
596                                 hio_mgr->ext_proc_info.ty_tlb[i].dsp_virt,
597                                 ul_gpp_pa, ul_dsp_va, ul_seg_size);
598                         status = -EPERM;
599                 } else {
600                         if (ndx < MAX_LOCK_TLB_ENTRIES) {
601                                 ae_proc[ndx].dsp_va =
602                                     hio_mgr->ext_proc_info.ty_tlb[i].
603                                     dsp_virt;
604                                 ae_proc[ndx].gpp_pa =
605                                     hio_mgr->ext_proc_info.ty_tlb[i].
606                                     gpp_phys;
607                                 ae_proc[ndx].gpp_va = 0;
608                                 /* 1 MB */
609                                 ae_proc[ndx].size = 0x100000;
610                                 dev_dbg(bridge, "shm MMU entry PA %x "
611                                         "DSP_VA 0x%x\n", ae_proc[ndx].gpp_pa,
612                                         ae_proc[ndx].dsp_va);
613                                 ndx++;
614                         } else {
615                                 status = hio_mgr->intf_fxns->brd_mem_map
616                                     (hio_mgr->bridge_context,
617                                      hio_mgr->ext_proc_info.ty_tlb[i].
618                                      gpp_phys,
619                                      hio_mgr->ext_proc_info.ty_tlb[i].
620                                      dsp_virt, 0x100000, map_attrs,
621                                      NULL);
622                         }
623                 }
624                 if (status)
625                         goto func_end;
626         }
627
628         map_attrs = 0x00000000;
629         map_attrs = DSP_MAPLITTLEENDIAN;
630         map_attrs |= DSP_MAPPHYSICALADDR;
631         map_attrs |= DSP_MAPELEMSIZE32;
632         map_attrs |= DSP_MAPDONOTLOCK;
633
634         /* Map the L4 peripherals */
635         i = 0;
636         while (l4_peripheral_table[i].phys_addr) {
637                 status = hio_mgr->intf_fxns->brd_mem_map
638                     (hio_mgr->bridge_context, l4_peripheral_table[i].phys_addr,
639                      l4_peripheral_table[i].dsp_virt_addr, HW_PAGE_SIZE4KB,
640                      map_attrs, NULL);
641                 if (status)
642                         goto func_end;
643                 i++;
644         }
645
646         for (i = ndx; i < BRDIOCTL_NUMOFMMUTLB; i++) {
647                 ae_proc[i].dsp_va = 0;
648                 ae_proc[i].gpp_pa = 0;
649                 ae_proc[i].gpp_va = 0;
650                 ae_proc[i].size = 0;
651         }
652         /*
653          * Set the shm physical address entry (grayed out in CDB file)
654          * to the virtual uncached ioremapped address of shm reserved
655          * on MPU.
656          */
657         hio_mgr->ext_proc_info.ty_tlb[0].gpp_phys =
658             (ul_gpp_va + ul_seg1_size + ul_pad_size);
659
660         /*
661          * Need shm Phys addr. IO supports only one DSP for now:
662          * num_procs = 1.
663          */
664         if (!hio_mgr->ext_proc_info.ty_tlb[0].gpp_phys || num_procs != 1) {
665                 status = -EFAULT;
666                 goto func_end;
667         } else {
668                 if (ae_proc[0].dsp_va > ul_shm_base) {
669                         status = -EPERM;
670                         goto func_end;
671                 }
672                 /* ul_shm_base may not be at ul_dsp_va address */
673                 ul_shm_base_offset = (ul_shm_base - ae_proc[0].dsp_va) *
674                     hio_mgr->word_size;
675                 /*
676                  * bridge_dev_ctrl() will set dev context dsp-mmu info. In
677                  * bridge_brd_start() the MMU will be re-programed with MMU
678                  * DSPVa-GPPPa pair info while DSP is in a known
679                  * (reset) state.
680                  */
681
682                 status =
683                     hio_mgr->intf_fxns->dev_cntrl(hio_mgr->bridge_context,
684                                                       BRDIOCTL_SETMMUCONFIG,
685                                                       ae_proc);
686                 if (status)
687                         goto func_end;
688                 ul_shm_base = hio_mgr->ext_proc_info.ty_tlb[0].gpp_phys;
689                 ul_shm_base += ul_shm_base_offset;
690                 ul_shm_base = (u32) MEM_LINEAR_ADDRESS((void *)ul_shm_base,
691                                                        ul_mem_length);
692                 if (ul_shm_base == 0) {
693                         status = -EFAULT;
694                         goto func_end;
695                 }
696                 /* Register SM */
697                 status =
698                     register_shm_segs(hio_mgr, cod_man, ae_proc[0].gpp_pa);
699         }
700
701         hio_mgr->shared_mem = (struct shm *)ul_shm_base;
702         hio_mgr->input = (u8 *) hio_mgr->shared_mem + sizeof(struct shm);
703         hio_mgr->output = hio_mgr->input + (ul_shm_length -
704                                             sizeof(struct shm)) / 2;
705         hio_mgr->sm_buf_size = hio_mgr->output - hio_mgr->input;
706
707         /*  Set up Shared memory addresses for messaging. */
708         hio_mgr->msg_input_ctrl = (struct msg_ctrl *)((u8 *) hio_mgr->shared_mem
709                                                       + ul_shm_length);
710         hio_mgr->msg_input =
711             (u8 *) hio_mgr->msg_input_ctrl + sizeof(struct msg_ctrl);
712         hio_mgr->msg_output_ctrl =
713             (struct msg_ctrl *)((u8 *) hio_mgr->msg_input_ctrl +
714                                 ul_msg_length / 2);
715         hio_mgr->msg_output =
716             (u8 *) hio_mgr->msg_output_ctrl + sizeof(struct msg_ctrl);
717         hmsg_mgr->max_msgs =
718             ((u8 *) hio_mgr->msg_output_ctrl - hio_mgr->msg_input)
719             / sizeof(struct msg_dspmsg);
720         dev_dbg(bridge, "IO MGR shm details: shared_mem %p, input %p, "
721                 "output %p, msg_input_ctrl %p, msg_input %p, "
722                 "msg_output_ctrl %p, msg_output %p\n",
723                 (u8 *) hio_mgr->shared_mem, hio_mgr->input,
724                 hio_mgr->output, (u8 *) hio_mgr->msg_input_ctrl,
725                 hio_mgr->msg_input, (u8 *) hio_mgr->msg_output_ctrl,
726                 hio_mgr->msg_output);
727         dev_dbg(bridge, "(proc) Mas msgs in shared memory: 0x%x\n",
728                 hmsg_mgr->max_msgs);
729         memset((void *)hio_mgr->shared_mem, 0, sizeof(struct shm));
730
731 #if defined(CONFIG_TIDSPBRIDGE_BACKTRACE)
732         /* Get the start address of trace buffer */
733         status = cod_get_sym_value(cod_man, SYS_PUTCBEG,
734                                    &hio_mgr->trace_buffer_begin);
735         if (status) {
736                 status = -EFAULT;
737                 goto func_end;
738         }
739
740         hio_mgr->gpp_read_pointer = hio_mgr->trace_buffer_begin =
741             (ul_gpp_va + ul_seg1_size + ul_pad_size) +
742             (hio_mgr->trace_buffer_begin - ul_dsp_va);
743         /* Get the end address of trace buffer */
744         status = cod_get_sym_value(cod_man, SYS_PUTCEND,
745                                    &hio_mgr->trace_buffer_end);
746         if (status) {
747                 status = -EFAULT;
748                 goto func_end;
749         }
750         hio_mgr->trace_buffer_end =
751             (ul_gpp_va + ul_seg1_size + ul_pad_size) +
752             (hio_mgr->trace_buffer_end - ul_dsp_va);
753         /* Get the current address of DSP write pointer */
754         status = cod_get_sym_value(cod_man, BRIDGE_SYS_PUTC_CURRENT,
755                                    &hio_mgr->trace_buffer_current);
756         if (status) {
757                 status = -EFAULT;
758                 goto func_end;
759         }
760         hio_mgr->trace_buffer_current =
761             (ul_gpp_va + ul_seg1_size + ul_pad_size) +
762             (hio_mgr->trace_buffer_current - ul_dsp_va);
763         /* Calculate the size of trace buffer */
764         kfree(hio_mgr->msg);
765         hio_mgr->msg = kmalloc(((hio_mgr->trace_buffer_end -
766                                 hio_mgr->trace_buffer_begin) *
767                                 hio_mgr->word_size) + 2, GFP_KERNEL);
768         if (!hio_mgr->msg)
769                 status = -ENOMEM;
770
771         hio_mgr->dsp_va = ul_dsp_va;
772         hio_mgr->gpp_va = (ul_gpp_va + ul_seg1_size + ul_pad_size);
773
774 #endif
775 func_end:
776         return status;
777 }
778
779 /*
780  *  ======== io_buf_size ========
781  *      Size of shared memory I/O channel.
782  */
783 u32 io_buf_size(struct io_mgr *hio_mgr)
784 {
785         if (hio_mgr)
786                 return hio_mgr->sm_buf_size;
787         else
788                 return 0;
789 }
790
791 /*
792  *  ======== io_cancel_chnl ========
793  *      Cancel IO on a given PCPY channel.
794  */
795 void io_cancel_chnl(struct io_mgr *hio_mgr, u32 chnl)
796 {
797         struct io_mgr *pio_mgr = (struct io_mgr *)hio_mgr;
798         struct shm *sm;
799
800         if (!hio_mgr)
801                 goto func_end;
802         sm = hio_mgr->shared_mem;
803
804         /* Inform DSP that we have no more buffers on this channel */
805         set_chnl_free(sm, chnl);
806
807         sm_interrupt_dsp(pio_mgr->bridge_context, MBX_PCPY_CLASS);
808 func_end:
809         return;
810 }
811
812
813 /*
814  *  ======== io_dispatch_pm ========
815  *      Performs I/O dispatch on PM related messages from DSP
816  */
817 static void io_dispatch_pm(struct io_mgr *pio_mgr)
818 {
819         int status;
820         u32 parg[2];
821
822         /* Perform Power message processing here */
823         parg[0] = pio_mgr->intr_val;
824
825         /* Send the command to the Bridge clk/pwr manager to handle */
826         if (parg[0] == MBX_PM_HIBERNATE_EN) {
827                 dev_dbg(bridge, "PM: Hibernate command\n");
828                 status = pio_mgr->intf_fxns->
829                                 dev_cntrl(pio_mgr->bridge_context,
830                                               BRDIOCTL_PWR_HIBERNATE, parg);
831                 if (status)
832                         pr_err("%s: hibernate cmd failed 0x%x\n",
833                                        __func__, status);
834         } else if (parg[0] == MBX_PM_OPP_REQ) {
835                 parg[1] = pio_mgr->shared_mem->opp_request.rqst_opp_pt;
836                 dev_dbg(bridge, "PM: Requested OPP = 0x%x\n", parg[1]);
837                 status = pio_mgr->intf_fxns->
838                                 dev_cntrl(pio_mgr->bridge_context,
839                                         BRDIOCTL_CONSTRAINT_REQUEST, parg);
840                 if (status)
841                         dev_dbg(bridge, "PM: Failed to set constraint "
842                                 "= 0x%x\n", parg[1]);
843         } else {
844                 dev_dbg(bridge, "PM: clk control value of msg = 0x%x\n",
845                         parg[0]);
846                 status = pio_mgr->intf_fxns->
847                                 dev_cntrl(pio_mgr->bridge_context,
848                                               BRDIOCTL_CLK_CTRL, parg);
849                 if (status)
850                         dev_dbg(bridge, "PM: Failed to ctrl the DSP clk"
851                                 "= 0x%x\n", *parg);
852         }
853 }
854
855 /*
856  *  ======== io_dpc ========
857  *      Deferred procedure call for shared memory channel driver ISR.  Carries
858  *      out the dispatch of I/O as a non-preemptible event.It can only be
859  *      pre-empted      by an ISR.
860  */
861 void io_dpc(unsigned long ref_data)
862 {
863         struct io_mgr *pio_mgr = (struct io_mgr *)ref_data;
864         struct chnl_mgr *chnl_mgr_obj;
865         struct msg_mgr *msg_mgr_obj;
866         struct deh_mgr *hdeh_mgr;
867         u32 requested;
868         u32 serviced;
869
870         if (!pio_mgr)
871                 goto func_end;
872         chnl_mgr_obj = pio_mgr->chnl_mgr;
873         dev_get_msg_mgr(pio_mgr->dev_obj, &msg_mgr_obj);
874         dev_get_deh_mgr(pio_mgr->dev_obj, &hdeh_mgr);
875         if (!chnl_mgr_obj)
876                 goto func_end;
877
878         requested = pio_mgr->dpc_req;
879         serviced = pio_mgr->dpc_sched;
880
881         if (serviced == requested)
882                 goto func_end;
883
884         /* Process pending DPC's */
885         do {
886                 /* Check value of interrupt reg to ensure it's a valid error */
887                 if ((pio_mgr->intr_val > DEH_BASE) &&
888                     (pio_mgr->intr_val < DEH_LIMIT)) {
889                         /* Notify DSP/BIOS exception */
890                         if (hdeh_mgr) {
891 #ifdef CONFIG_TIDSPBRIDGE_BACKTRACE
892                                 print_dsp_debug_trace(pio_mgr);
893 #endif
894                                 bridge_deh_notify(hdeh_mgr, DSP_SYSERROR,
895                                                   pio_mgr->intr_val);
896                         }
897                 }
898                 /* Proc-copy chanel dispatch */
899                 input_chnl(pio_mgr, NULL, IO_SERVICE);
900                 output_chnl(pio_mgr, NULL, IO_SERVICE);
901
902 #ifdef CHNL_MESSAGES
903                 if (msg_mgr_obj) {
904                         /* Perform I/O dispatch on message queues */
905                         input_msg(pio_mgr, msg_mgr_obj);
906                         output_msg(pio_mgr, msg_mgr_obj);
907                 }
908
909 #endif
910 #ifdef CONFIG_TIDSPBRIDGE_BACKTRACE
911                 if (pio_mgr->intr_val & MBX_DBG_SYSPRINTF) {
912                         /* Notify DSP Trace message */
913                         print_dsp_debug_trace(pio_mgr);
914                 }
915 #endif
916                 serviced++;
917         } while (serviced != requested);
918         pio_mgr->dpc_sched = requested;
919 func_end:
920         return;
921 }
922
923 /*
924  *  ======== io_mbox_msg ========
925  *      Main interrupt handler for the shared memory IO manager.
926  *      Calls the Bridge's CHNL_ISR to determine if this interrupt is ours, then
927  *      schedules a DPC to dispatch I/O.
928  */
929 int io_mbox_msg(struct notifier_block *self, unsigned long len, void *msg)
930 {
931         struct io_mgr *pio_mgr;
932         struct dev_object *dev_obj;
933         unsigned long flags;
934
935         dev_obj = dev_get_first();
936         dev_get_io_mgr(dev_obj, &pio_mgr);
937
938         if (!pio_mgr)
939                 return NOTIFY_BAD;
940
941         pio_mgr->intr_val = (u16)((u32)msg);
942         if (pio_mgr->intr_val & MBX_PM_CLASS)
943                 io_dispatch_pm(pio_mgr);
944
945         if (pio_mgr->intr_val == MBX_DEH_RESET) {
946                 pio_mgr->intr_val = 0;
947         } else {
948                 spin_lock_irqsave(&pio_mgr->dpc_lock, flags);
949                 pio_mgr->dpc_req++;
950                 spin_unlock_irqrestore(&pio_mgr->dpc_lock, flags);
951                 tasklet_schedule(&pio_mgr->dpc_tasklet);
952         }
953         return NOTIFY_OK;
954 }
955
956 /*
957  *  ======== io_request_chnl ========
958  *  Purpose:
959  *      Request chanenel I/O from the DSP. Sets flags in shared memory, then
960  *      interrupts the DSP.
961  */
962 void io_request_chnl(struct io_mgr *io_manager, struct chnl_object *pchnl,
963                         u8 io_mode, u16 *mbx_val)
964 {
965         struct chnl_mgr *chnl_mgr_obj;
966         struct shm *sm;
967
968         if (!pchnl || !mbx_val)
969                 goto func_end;
970         chnl_mgr_obj = io_manager->chnl_mgr;
971         sm = io_manager->shared_mem;
972         if (io_mode == IO_INPUT) {
973                 /* Indicate to the DSP we have a buffer available for input */
974                 set_chnl_busy(sm, pchnl->chnl_id);
975                 *mbx_val = MBX_PCPY_CLASS;
976         } else if (io_mode == IO_OUTPUT) {
977                 /*
978                  * Record the fact that we have a buffer available for
979                  * output.
980                  */
981                 chnl_mgr_obj->output_mask |= (1 << pchnl->chnl_id);
982         } else {
983         }
984 func_end:
985         return;
986 }
987
988 /*
989  *  ======== iosm_schedule ========
990  *      Schedule DPC for IO.
991  */
992 void iosm_schedule(struct io_mgr *io_manager)
993 {
994         unsigned long flags;
995
996         if (!io_manager)
997                 return;
998
999         /* Increment count of DPC's pending. */
1000         spin_lock_irqsave(&io_manager->dpc_lock, flags);
1001         io_manager->dpc_req++;
1002         spin_unlock_irqrestore(&io_manager->dpc_lock, flags);
1003
1004         /* Schedule DPC */
1005         tasklet_schedule(&io_manager->dpc_tasklet);
1006 }
1007
1008 /*
1009  *  ======== find_ready_output ========
1010  *      Search for a host output channel which is ready to send.  If this is
1011  *      called as a result of servicing the DPC, then implement a round
1012  *      robin search; otherwise, this was called by a client thread (via
1013  *      IO_Dispatch()), so just start searching from the current channel id.
1014  */
1015 static u32 find_ready_output(struct chnl_mgr *chnl_mgr_obj,
1016                              struct chnl_object *pchnl, u32 mask)
1017 {
1018         u32 ret = OUTPUTNOTREADY;
1019         u32 id, start_id;
1020         u32 shift;
1021
1022         id = (pchnl !=
1023               NULL ? pchnl->chnl_id : (chnl_mgr_obj->last_output + 1));
1024         id = ((id == CHNL_MAXCHANNELS) ? 0 : id);
1025         if (id >= CHNL_MAXCHANNELS)
1026                 goto func_end;
1027         if (mask) {
1028                 shift = (1 << id);
1029                 start_id = id;
1030                 do {
1031                         if (mask & shift) {
1032                                 ret = id;
1033                                 if (pchnl == NULL)
1034                                         chnl_mgr_obj->last_output = id;
1035                                 break;
1036                         }
1037                         id = id + 1;
1038                         id = ((id == CHNL_MAXCHANNELS) ? 0 : id);
1039                         shift = (1 << id);
1040                 } while (id != start_id);
1041         }
1042 func_end:
1043         return ret;
1044 }
1045
1046 /*
1047  *  ======== input_chnl ========
1048  *      Dispatch a buffer on an input channel.
1049  */
1050 static void input_chnl(struct io_mgr *pio_mgr, struct chnl_object *pchnl,
1051                         u8 io_mode)
1052 {
1053         struct chnl_mgr *chnl_mgr_obj;
1054         struct shm *sm;
1055         u32 chnl_id;
1056         u32 bytes;
1057         struct chnl_irp *chnl_packet_obj = NULL;
1058         u32 dw_arg;
1059         bool clear_chnl = false;
1060         bool notify_client = false;
1061
1062         sm = pio_mgr->shared_mem;
1063         chnl_mgr_obj = pio_mgr->chnl_mgr;
1064
1065         /* Attempt to perform input */
1066         if (!sm->input_full)
1067                 goto func_end;
1068
1069         bytes = sm->input_size * chnl_mgr_obj->word_size;
1070         chnl_id = sm->input_id;
1071         dw_arg = sm->arg;
1072         if (chnl_id >= CHNL_MAXCHANNELS) {
1073                 /* Shouldn't be here: would indicate corrupted shm. */
1074                 goto func_end;
1075         }
1076         pchnl = chnl_mgr_obj->channels[chnl_id];
1077         if ((pchnl != NULL) && CHNL_IS_INPUT(pchnl->chnl_mode)) {
1078                 if ((pchnl->state & ~CHNL_STATEEOS) == CHNL_STATEREADY) {
1079                         /* Get the I/O request, and attempt a transfer */
1080                         if (!list_empty(&pchnl->io_requests)) {
1081                                 if (!pchnl->cio_reqs)
1082                                         goto func_end;
1083
1084                                 chnl_packet_obj = list_first_entry(
1085                                                 &pchnl->io_requests,
1086                                                 struct chnl_irp, link);
1087                                 list_del(&chnl_packet_obj->link);
1088                                 pchnl->cio_reqs--;
1089
1090                                 /*
1091                                  * Ensure we don't overflow the client's
1092                                  * buffer.
1093                                  */
1094                                 bytes = min(bytes, chnl_packet_obj->byte_size);
1095                                 memcpy(chnl_packet_obj->host_sys_buf,
1096                                                 pio_mgr->input, bytes);
1097                                 pchnl->bytes_moved += bytes;
1098                                 chnl_packet_obj->byte_size = bytes;
1099                                 chnl_packet_obj->arg = dw_arg;
1100                                 chnl_packet_obj->status = CHNL_IOCSTATCOMPLETE;
1101
1102                                 if (bytes == 0) {
1103                                         /*
1104                                          * This assertion fails if the DSP
1105                                          * sends EOS more than once on this
1106                                          * channel.
1107                                          */
1108                                         if (pchnl->state & CHNL_STATEEOS)
1109                                                 goto func_end;
1110                                         /*
1111                                          * Zero bytes indicates EOS. Update
1112                                          * IOC status for this chirp, and also
1113                                          * the channel state.
1114                                          */
1115                                         chnl_packet_obj->status |=
1116                                                 CHNL_IOCSTATEOS;
1117                                         pchnl->state |= CHNL_STATEEOS;
1118                                         /*
1119                                          * Notify that end of stream has
1120                                          * occurred.
1121                                          */
1122                                         ntfy_notify(pchnl->ntfy_obj,
1123                                                         DSP_STREAMDONE);
1124                                 }
1125                                 /* Tell DSP if no more I/O buffers available */
1126                                 if (list_empty(&pchnl->io_requests))
1127                                         set_chnl_free(sm, pchnl->chnl_id);
1128                                 clear_chnl = true;
1129                                 notify_client = true;
1130                         } else {
1131                                 /*
1132                                  * Input full for this channel, but we have no
1133                                  * buffers available.  The channel must be
1134                                  * "idling". Clear out the physical input
1135                                  * channel.
1136                                  */
1137                                 clear_chnl = true;
1138                         }
1139                 } else {
1140                         /* Input channel cancelled: clear input channel */
1141                         clear_chnl = true;
1142                 }
1143         } else {
1144                 /* DPC fired after host closed channel: clear input channel */
1145                 clear_chnl = true;
1146         }
1147         if (clear_chnl) {
1148                 /* Indicate to the DSP we have read the input */
1149                 sm->input_full = 0;
1150                 sm_interrupt_dsp(pio_mgr->bridge_context, MBX_PCPY_CLASS);
1151         }
1152         if (notify_client) {
1153                 /* Notify client with IO completion record */
1154                 notify_chnl_complete(pchnl, chnl_packet_obj);
1155         }
1156 func_end:
1157         return;
1158 }
1159
1160 /*
1161  *  ======== input_msg ========
1162  *      Copies messages from shared memory to the message queues.
1163  */
1164 static void input_msg(struct io_mgr *pio_mgr, struct msg_mgr *hmsg_mgr)
1165 {
1166         u32 num_msgs;
1167         u32 i;
1168         u8 *msg_input;
1169         struct msg_queue *msg_queue_obj;
1170         struct msg_frame *pmsg;
1171         struct msg_dspmsg msg;
1172         struct msg_ctrl *msg_ctr_obj;
1173         u32 input_empty;
1174         u32 addr;
1175
1176         msg_ctr_obj = pio_mgr->msg_input_ctrl;
1177         /* Get the number of input messages to be read */
1178         input_empty = msg_ctr_obj->buf_empty;
1179         num_msgs = msg_ctr_obj->size;
1180         if (input_empty)
1181                 return;
1182
1183         msg_input = pio_mgr->msg_input;
1184         for (i = 0; i < num_msgs; i++) {
1185                 /* Read the next message */
1186                 addr = (u32) &(((struct msg_dspmsg *)msg_input)->msg.cmd);
1187                 msg.msg.cmd =
1188                         read_ext32_bit_dsp_data(pio_mgr->bridge_context, addr);
1189                 addr = (u32) &(((struct msg_dspmsg *)msg_input)->msg.arg1);
1190                 msg.msg.arg1 =
1191                         read_ext32_bit_dsp_data(pio_mgr->bridge_context, addr);
1192                 addr = (u32) &(((struct msg_dspmsg *)msg_input)->msg.arg2);
1193                 msg.msg.arg2 =
1194                         read_ext32_bit_dsp_data(pio_mgr->bridge_context, addr);
1195                 addr = (u32) &(((struct msg_dspmsg *)msg_input)->msgq_id);
1196                 msg.msgq_id =
1197                         read_ext32_bit_dsp_data(pio_mgr->bridge_context, addr);
1198                 msg_input += sizeof(struct msg_dspmsg);
1199
1200                 /* Determine which queue to put the message in */
1201                 dev_dbg(bridge, "input msg: cmd=0x%x arg1=0x%x "
1202                                 "arg2=0x%x msgq_id=0x%x\n", msg.msg.cmd,
1203                                 msg.msg.arg1, msg.msg.arg2, msg.msgq_id);
1204                 /*
1205                  * Interrupt may occur before shared memory and message
1206                  * input locations have been set up. If all nodes were
1207                  * cleaned up, hmsg_mgr->max_msgs should be 0.
1208                  */
1209                 list_for_each_entry(msg_queue_obj, &hmsg_mgr->queue_list,
1210                                 list_elem) {
1211                         if (msg.msgq_id != msg_queue_obj->msgq_id)
1212                                 continue;
1213                         /* Found it */
1214                         if (msg.msg.cmd == RMS_EXITACK) {
1215                                 /*
1216                                  * Call the node exit notification.
1217                                  * The exit message does not get
1218                                  * queued.
1219                                  */
1220                                 (*hmsg_mgr->on_exit)(msg_queue_obj->arg,
1221                                                 msg.msg.arg1);
1222                                 break;
1223                         }
1224                         /*
1225                          * Not an exit acknowledgement, queue
1226                          * the message.
1227                          */
1228                         if (list_empty(&msg_queue_obj->msg_free_list)) {
1229                                 /*
1230                                  * No free frame to copy the
1231                                  * message into.
1232                                  */
1233                                 pr_err("%s: no free msg frames,"
1234                                                 " discarding msg\n",
1235                                                 __func__);
1236                                 break;
1237                         }
1238
1239                         pmsg = list_first_entry(&msg_queue_obj->msg_free_list,
1240                                         struct msg_frame, list_elem);
1241                         list_del(&pmsg->list_elem);
1242                         pmsg->msg_data = msg;
1243                         list_add_tail(&pmsg->list_elem,
1244                                         &msg_queue_obj->msg_used_list);
1245                         ntfy_notify(msg_queue_obj->ntfy_obj,
1246                                         DSP_NODEMESSAGEREADY);
1247                         sync_set_event(msg_queue_obj->sync_event);
1248                 }
1249         }
1250         /* Set the post SWI flag */
1251         if (num_msgs > 0) {
1252                 /* Tell the DSP we've read the messages */
1253                 msg_ctr_obj->buf_empty = true;
1254                 msg_ctr_obj->post_swi = true;
1255                 sm_interrupt_dsp(pio_mgr->bridge_context, MBX_PCPY_CLASS);
1256         }
1257 }
1258
1259 /*
1260  *  ======== notify_chnl_complete ========
1261  *  Purpose:
1262  *      Signal the channel event, notifying the client that I/O has completed.
1263  */
1264 static void notify_chnl_complete(struct chnl_object *pchnl,
1265                                  struct chnl_irp *chnl_packet_obj)
1266 {
1267         bool signal_event;
1268
1269         if (!pchnl || !pchnl->sync_event || !chnl_packet_obj)
1270                 goto func_end;
1271
1272         /*
1273          * Note: we signal the channel event only if the queue of IO
1274          * completions is empty.  If it is not empty, the event is sure to be
1275          * signalled by the only IO completion list consumer:
1276          * bridge_chnl_get_ioc().
1277          */
1278         signal_event = list_empty(&pchnl->io_completions);
1279         /* Enqueue the IO completion info for the client */
1280         list_add_tail(&chnl_packet_obj->link, &pchnl->io_completions);
1281         pchnl->cio_cs++;
1282
1283         if (pchnl->cio_cs > pchnl->chnl_packets)
1284                 goto func_end;
1285         /* Signal the channel event (if not already set) that IO is complete */
1286         if (signal_event)
1287                 sync_set_event(pchnl->sync_event);
1288
1289         /* Notify that IO is complete */
1290         ntfy_notify(pchnl->ntfy_obj, DSP_STREAMIOCOMPLETION);
1291 func_end:
1292         return;
1293 }
1294
1295 /*
1296  *  ======== output_chnl ========
1297  *  Purpose:
1298  *      Dispatch a buffer on an output channel.
1299  */
1300 static void output_chnl(struct io_mgr *pio_mgr, struct chnl_object *pchnl,
1301                         u8 io_mode)
1302 {
1303         struct chnl_mgr *chnl_mgr_obj;
1304         struct shm *sm;
1305         u32 chnl_id;
1306         struct chnl_irp *chnl_packet_obj;
1307         u32 dw_dsp_f_mask;
1308
1309         chnl_mgr_obj = pio_mgr->chnl_mgr;
1310         sm = pio_mgr->shared_mem;
1311         /* Attempt to perform output */
1312         if (sm->output_full)
1313                 goto func_end;
1314
1315         if (pchnl && !((pchnl->state & ~CHNL_STATEEOS) == CHNL_STATEREADY))
1316                 goto func_end;
1317
1318         /* Look to see if both a PC and DSP output channel are ready */
1319         dw_dsp_f_mask = sm->dsp_free_mask;
1320         chnl_id =
1321             find_ready_output(chnl_mgr_obj, pchnl,
1322                               (chnl_mgr_obj->output_mask & dw_dsp_f_mask));
1323         if (chnl_id == OUTPUTNOTREADY)
1324                 goto func_end;
1325
1326         pchnl = chnl_mgr_obj->channels[chnl_id];
1327         if (!pchnl || list_empty(&pchnl->io_requests)) {
1328                 /* Shouldn't get here */
1329                 goto func_end;
1330         }
1331
1332         if (!pchnl->cio_reqs)
1333                 goto func_end;
1334
1335         /* Get the I/O request, and attempt a transfer */
1336         chnl_packet_obj = list_first_entry(&pchnl->io_requests,
1337                         struct chnl_irp, link);
1338         list_del(&chnl_packet_obj->link);
1339
1340         pchnl->cio_reqs--;
1341
1342         /* Record fact that no more I/O buffers available */
1343         if (list_empty(&pchnl->io_requests))
1344                 chnl_mgr_obj->output_mask &= ~(1 << chnl_id);
1345
1346         /* Transfer buffer to DSP side */
1347         chnl_packet_obj->byte_size = min(pio_mgr->sm_buf_size,
1348                                         chnl_packet_obj->byte_size);
1349         memcpy(pio_mgr->output, chnl_packet_obj->host_sys_buf,
1350                                         chnl_packet_obj->byte_size);
1351         pchnl->bytes_moved += chnl_packet_obj->byte_size;
1352         /* Write all 32 bits of arg */
1353         sm->arg = chnl_packet_obj->arg;
1354 #if _CHNL_WORDSIZE == 2
1355         /* Access can be different SM access word size (e.g. 16/32 bit words) */
1356         sm->output_id = (u16) chnl_id;
1357         sm->output_size = (u16) (chnl_packet_obj->byte_size +
1358                                 chnl_mgr_obj->word_size - 1) /
1359                                 (u16) chnl_mgr_obj->word_size;
1360 #else
1361         sm->output_id = chnl_id;
1362         sm->output_size = (chnl_packet_obj->byte_size +
1363                         chnl_mgr_obj->word_size - 1) / chnl_mgr_obj->word_size;
1364 #endif
1365         sm->output_full =  1;
1366         /* Indicate to the DSP we have written the output */
1367         sm_interrupt_dsp(pio_mgr->bridge_context, MBX_PCPY_CLASS);
1368         /* Notify client with IO completion record (keep EOS) */
1369         chnl_packet_obj->status &= CHNL_IOCSTATEOS;
1370         notify_chnl_complete(pchnl, chnl_packet_obj);
1371         /* Notify if stream is done. */
1372         if (chnl_packet_obj->status & CHNL_IOCSTATEOS)
1373                 ntfy_notify(pchnl->ntfy_obj, DSP_STREAMDONE);
1374
1375 func_end:
1376         return;
1377 }
1378
1379 /*
1380  *  ======== output_msg ========
1381  *      Copies messages from the message queues to the shared memory.
1382  */
1383 static void output_msg(struct io_mgr *pio_mgr, struct msg_mgr *hmsg_mgr)
1384 {
1385         u32 num_msgs = 0;
1386         u32 i;
1387         struct msg_dspmsg *msg_output;
1388         struct msg_frame *pmsg;
1389         struct msg_ctrl *msg_ctr_obj;
1390         u32 val;
1391         u32 addr;
1392
1393         msg_ctr_obj = pio_mgr->msg_output_ctrl;
1394
1395         /* Check if output has been cleared */
1396         if (!msg_ctr_obj->buf_empty)
1397                 return;
1398
1399         num_msgs = (hmsg_mgr->msgs_pending > hmsg_mgr->max_msgs) ?
1400                 hmsg_mgr->max_msgs : hmsg_mgr->msgs_pending;
1401         msg_output = (struct msg_dspmsg *) pio_mgr->msg_output;
1402
1403         /* Copy num_msgs messages into shared memory */
1404         for (i = 0; i < num_msgs; i++) {
1405                 if (list_empty(&hmsg_mgr->msg_used_list))
1406                         continue;
1407
1408                 pmsg = list_first_entry(&hmsg_mgr->msg_used_list,
1409                                 struct msg_frame, list_elem);
1410                 list_del(&pmsg->list_elem);
1411
1412                 val = (pmsg->msg_data).msgq_id;
1413                 addr = (u32) &msg_output->msgq_id;
1414                 write_ext32_bit_dsp_data(pio_mgr->bridge_context, addr, val);
1415
1416                 val = (pmsg->msg_data).msg.cmd;
1417                 addr = (u32) &msg_output->msg.cmd;
1418                 write_ext32_bit_dsp_data(pio_mgr->bridge_context, addr, val);
1419
1420                 val = (pmsg->msg_data).msg.arg1;
1421                 addr = (u32) &msg_output->msg.arg1;
1422                 write_ext32_bit_dsp_data(pio_mgr->bridge_context, addr, val);
1423
1424                 val = (pmsg->msg_data).msg.arg2;
1425                 addr = (u32) &msg_output->msg.arg2;
1426                 write_ext32_bit_dsp_data(pio_mgr->bridge_context, addr, val);
1427
1428                 msg_output++;
1429                 list_add_tail(&pmsg->list_elem, &hmsg_mgr->msg_free_list);
1430                 sync_set_event(hmsg_mgr->sync_event);
1431         }
1432
1433         if (num_msgs > 0) {
1434                 hmsg_mgr->msgs_pending -= num_msgs;
1435 #if _CHNL_WORDSIZE == 2
1436                 /*
1437                  * Access can be different SM access word size
1438                  * (e.g. 16/32 bit words)
1439                  */
1440                 msg_ctr_obj->size = (u16) num_msgs;
1441 #else
1442                 msg_ctr_obj->size = num_msgs;
1443 #endif
1444                 msg_ctr_obj->buf_empty = false;
1445                 /* Set the post SWI flag */
1446                 msg_ctr_obj->post_swi = true;
1447                 /* Tell the DSP we have written the output. */
1448                 sm_interrupt_dsp(pio_mgr->bridge_context, MBX_PCPY_CLASS);
1449         }
1450 }
1451
1452 /*
1453  *  ======== register_shm_segs ========
1454  *  purpose:
1455  *      Registers GPP SM segment with CMM.
1456  */
1457 static int register_shm_segs(struct io_mgr *hio_mgr,
1458                                     struct cod_manager *cod_man,
1459                                     u32 dw_gpp_base_pa)
1460 {
1461         int status = 0;
1462         u32 ul_shm0_base = 0;
1463         u32 shm0_end = 0;
1464         u32 ul_shm0_rsrvd_start = 0;
1465         u32 ul_rsrvd_size = 0;
1466         u32 ul_gpp_phys;
1467         u32 ul_dsp_virt;
1468         u32 ul_shm_seg_id0 = 0;
1469         u32 dw_offset, dw_gpp_base_va, ul_dsp_size;
1470
1471         /*
1472          * Read address and size info for first SM region.
1473          * Get start of 1st SM Heap region.
1474          */
1475         status =
1476             cod_get_sym_value(cod_man, SHM0_SHARED_BASE_SYM, &ul_shm0_base);
1477         if (ul_shm0_base == 0) {
1478                 status = -EPERM;
1479                 goto func_end;
1480         }
1481         /* Get end of 1st SM Heap region */
1482         if (!status) {
1483                 /* Get start and length of message part of shared memory */
1484                 status = cod_get_sym_value(cod_man, SHM0_SHARED_END_SYM,
1485                                            &shm0_end);
1486                 if (shm0_end == 0) {
1487                         status = -EPERM;
1488                         goto func_end;
1489                 }
1490         }
1491         /* Start of Gpp reserved region */
1492         if (!status) {
1493                 /* Get start and length of message part of shared memory */
1494                 status =
1495                     cod_get_sym_value(cod_man, SHM0_SHARED_RESERVED_BASE_SYM,
1496                                       &ul_shm0_rsrvd_start);
1497                 if (ul_shm0_rsrvd_start == 0) {
1498                         status = -EPERM;
1499                         goto func_end;
1500                 }
1501         }
1502         /* Register with CMM */
1503         if (!status) {
1504                 status = dev_get_cmm_mgr(hio_mgr->dev_obj, &hio_mgr->cmm_mgr);
1505                 if (!status) {
1506                         status = cmm_un_register_gppsm_seg(hio_mgr->cmm_mgr,
1507                                                            CMM_ALLSEGMENTS);
1508                 }
1509         }
1510         /* Register new SM region(s) */
1511         if (!status && (shm0_end - ul_shm0_base) > 0) {
1512                 /* Calc size (bytes) of SM the GPP can alloc from */
1513                 ul_rsrvd_size =
1514                     (shm0_end - ul_shm0_rsrvd_start + 1) * hio_mgr->word_size;
1515                 if (ul_rsrvd_size <= 0) {
1516                         status = -EPERM;
1517                         goto func_end;
1518                 }
1519                 /* Calc size of SM DSP can alloc from */
1520                 ul_dsp_size =
1521                     (ul_shm0_rsrvd_start - ul_shm0_base) * hio_mgr->word_size;
1522                 if (ul_dsp_size <= 0) {
1523                         status = -EPERM;
1524                         goto func_end;
1525                 }
1526                 /* First TLB entry reserved for Bridge SM use. */
1527                 ul_gpp_phys = hio_mgr->ext_proc_info.ty_tlb[0].gpp_phys;
1528                 /* Get size in bytes */
1529                 ul_dsp_virt =
1530                     hio_mgr->ext_proc_info.ty_tlb[0].dsp_virt *
1531                     hio_mgr->word_size;
1532                 /*
1533                  * Calc byte offset used to convert GPP phys <-> DSP byte
1534                  * address.
1535                  */
1536                 if (dw_gpp_base_pa > ul_dsp_virt)
1537                         dw_offset = dw_gpp_base_pa - ul_dsp_virt;
1538                 else
1539                         dw_offset = ul_dsp_virt - dw_gpp_base_pa;
1540
1541                 if (ul_shm0_rsrvd_start * hio_mgr->word_size < ul_dsp_virt) {
1542                         status = -EPERM;
1543                         goto func_end;
1544                 }
1545                 /*
1546                  * Calc Gpp phys base of SM region.
1547                  * This is actually uncached kernel virtual address.
1548                  */
1549                 dw_gpp_base_va =
1550                     ul_gpp_phys + ul_shm0_rsrvd_start * hio_mgr->word_size -
1551                     ul_dsp_virt;
1552                 /*
1553                  * Calc Gpp phys base of SM region.
1554                  * This is the physical address.
1555                  */
1556                 dw_gpp_base_pa =
1557                     dw_gpp_base_pa + ul_shm0_rsrvd_start * hio_mgr->word_size -
1558                     ul_dsp_virt;
1559                 /* Register SM Segment 0. */
1560                 status =
1561                     cmm_register_gppsm_seg(hio_mgr->cmm_mgr, dw_gpp_base_pa,
1562                                            ul_rsrvd_size, dw_offset,
1563                                            (dw_gpp_base_pa >
1564                                             ul_dsp_virt) ? CMM_ADDTODSPPA :
1565                                            CMM_SUBFROMDSPPA,
1566                                            (u32) (ul_shm0_base *
1567                                                   hio_mgr->word_size),
1568                                            ul_dsp_size, &ul_shm_seg_id0,
1569                                            dw_gpp_base_va);
1570                 /* First SM region is seg_id = 1 */
1571                 if (ul_shm_seg_id0 != 1)
1572                         status = -EPERM;
1573         }
1574 func_end:
1575         return status;
1576 }
1577
1578 /* ZCPY IO routines. */
1579 /*
1580  *  ======== IO_SHMcontrol ========
1581  *      Sets the requested shm setting.
1582  */
1583 int io_sh_msetting(struct io_mgr *hio_mgr, u8 desc, void *pargs)
1584 {
1585 #ifdef CONFIG_TIDSPBRIDGE_DVFS
1586         u32 i;
1587         struct dspbridge_platform_data *pdata =
1588             omap_dspbridge_dev->dev.platform_data;
1589
1590         switch (desc) {
1591         case SHM_CURROPP:
1592                 /* Update the shared memory with requested OPP information */
1593                 if (pargs != NULL)
1594                         hio_mgr->shared_mem->opp_table_struct.curr_opp_pt =
1595                             *(u32 *) pargs;
1596                 else
1597                         return -EPERM;
1598                 break;
1599         case SHM_OPPINFO:
1600                 /*
1601                  * Update the shared memory with the voltage, frequency,
1602                  * min and max frequency values for an OPP.
1603                  */
1604                 for (i = 0; i <= dsp_max_opps; i++) {
1605                         hio_mgr->shared_mem->opp_table_struct.opp_point[i].
1606                             voltage = vdd1_dsp_freq[i][0];
1607                         dev_dbg(bridge, "OPP-shm: voltage: %d\n",
1608                                 vdd1_dsp_freq[i][0]);
1609                         hio_mgr->shared_mem->opp_table_struct.
1610                             opp_point[i].frequency = vdd1_dsp_freq[i][1];
1611                         dev_dbg(bridge, "OPP-shm: frequency: %d\n",
1612                                 vdd1_dsp_freq[i][1]);
1613                         hio_mgr->shared_mem->opp_table_struct.opp_point[i].
1614                             min_freq = vdd1_dsp_freq[i][2];
1615                         dev_dbg(bridge, "OPP-shm: min freq: %d\n",
1616                                 vdd1_dsp_freq[i][2]);
1617                         hio_mgr->shared_mem->opp_table_struct.opp_point[i].
1618                             max_freq = vdd1_dsp_freq[i][3];
1619                         dev_dbg(bridge, "OPP-shm: max freq: %d\n",
1620                                 vdd1_dsp_freq[i][3]);
1621                 }
1622                 hio_mgr->shared_mem->opp_table_struct.num_opp_pts =
1623                     dsp_max_opps;
1624                 dev_dbg(bridge, "OPP-shm: max OPP number: %d\n", dsp_max_opps);
1625                 /* Update the current OPP number */
1626                 if (pdata->dsp_get_opp)
1627                         i = (*pdata->dsp_get_opp) ();
1628                 hio_mgr->shared_mem->opp_table_struct.curr_opp_pt = i;
1629                 dev_dbg(bridge, "OPP-shm: value programmed = %d\n", i);
1630                 break;
1631         case SHM_GETOPP:
1632                 /* Get the OPP that DSP has requested */
1633                 *(u32 *) pargs = hio_mgr->shared_mem->opp_request.rqst_opp_pt;
1634                 break;
1635         default:
1636                 break;
1637         }
1638 #endif
1639         return 0;
1640 }
1641
1642 /*
1643  *  ======== bridge_io_get_proc_load ========
1644  *      Gets the Processor's Load information
1645  */
1646 int bridge_io_get_proc_load(struct io_mgr *hio_mgr,
1647                                 struct dsp_procloadstat *proc_lstat)
1648 {
1649         if (!hio_mgr->shared_mem)
1650                 return -EFAULT;
1651
1652         proc_lstat->curr_load =
1653                         hio_mgr->shared_mem->load_mon_info.curr_dsp_load;
1654         proc_lstat->predicted_load =
1655             hio_mgr->shared_mem->load_mon_info.pred_dsp_load;
1656         proc_lstat->curr_dsp_freq =
1657             hio_mgr->shared_mem->load_mon_info.curr_dsp_freq;
1658         proc_lstat->predicted_freq =
1659             hio_mgr->shared_mem->load_mon_info.pred_dsp_freq;
1660
1661         dev_dbg(bridge, "Curr Load = %d, Pred Load = %d, Curr Freq = %d, "
1662                 "Pred Freq = %d\n", proc_lstat->curr_load,
1663                 proc_lstat->predicted_load, proc_lstat->curr_dsp_freq,
1664                 proc_lstat->predicted_freq);
1665         return 0;
1666 }
1667
1668
1669 #if defined(CONFIG_TIDSPBRIDGE_BACKTRACE)
1670 void print_dsp_debug_trace(struct io_mgr *hio_mgr)
1671 {
1672         u32 ul_new_message_length = 0, ul_gpp_cur_pointer;
1673
1674         while (true) {
1675                 /* Get the DSP current pointer */
1676                 ul_gpp_cur_pointer =
1677                     *(u32 *) (hio_mgr->trace_buffer_current);
1678                 ul_gpp_cur_pointer =
1679                     hio_mgr->gpp_va + (ul_gpp_cur_pointer -
1680                                           hio_mgr->dsp_va);
1681
1682                 /* No new debug messages available yet */
1683                 if (ul_gpp_cur_pointer == hio_mgr->gpp_read_pointer) {
1684                         break;
1685                 } else if (ul_gpp_cur_pointer > hio_mgr->gpp_read_pointer) {
1686                         /* Continuous data */
1687                         ul_new_message_length =
1688                             ul_gpp_cur_pointer - hio_mgr->gpp_read_pointer;
1689
1690                         memcpy(hio_mgr->msg,
1691                                (char *)hio_mgr->gpp_read_pointer,
1692                                ul_new_message_length);
1693                         hio_mgr->msg[ul_new_message_length] = '\0';
1694                         /*
1695                          * Advance the GPP trace pointer to DSP current
1696                          * pointer.
1697                          */
1698                         hio_mgr->gpp_read_pointer += ul_new_message_length;
1699                         /* Print the trace messages */
1700                         pr_info("DSPTrace: %s\n", hio_mgr->msg);
1701                 } else if (ul_gpp_cur_pointer < hio_mgr->gpp_read_pointer) {
1702                         /* Handle trace buffer wraparound */
1703                         memcpy(hio_mgr->msg,
1704                                (char *)hio_mgr->gpp_read_pointer,
1705                                hio_mgr->trace_buffer_end -
1706                                hio_mgr->gpp_read_pointer);
1707                         ul_new_message_length =
1708                             ul_gpp_cur_pointer - hio_mgr->trace_buffer_begin;
1709                         memcpy(&hio_mgr->msg[hio_mgr->trace_buffer_end -
1710                                               hio_mgr->gpp_read_pointer],
1711                                (char *)hio_mgr->trace_buffer_begin,
1712                                ul_new_message_length);
1713                         hio_mgr->msg[hio_mgr->trace_buffer_end -
1714                                       hio_mgr->gpp_read_pointer +
1715                                       ul_new_message_length] = '\0';
1716                         /*
1717                          * Advance the GPP trace pointer to DSP current
1718                          * pointer.
1719                          */
1720                         hio_mgr->gpp_read_pointer =
1721                             hio_mgr->trace_buffer_begin +
1722                             ul_new_message_length;
1723                         /* Print the trace messages */
1724                         pr_info("DSPTrace: %s\n", hio_mgr->msg);
1725                 }
1726         }
1727 }
1728 #endif
1729
1730 #ifdef CONFIG_TIDSPBRIDGE_BACKTRACE
1731 /*
1732  *  ======== print_dsp_trace_buffer ========
1733  *      Prints the trace buffer returned from the DSP (if DBG_Trace is enabled).
1734  *  Parameters:
1735  *    hdeh_mgr:          Handle to DEH manager object
1736  *                      number of extra carriage returns to generate.
1737  *  Returns:
1738  *      0:        Success.
1739  *      -ENOMEM:    Unable to allocate memory.
1740  *  Requires:
1741  *      hdeh_mgr muse be valid. Checked in bridge_deh_notify.
1742  */
1743 int print_dsp_trace_buffer(struct bridge_dev_context *hbridge_context)
1744 {
1745         int status = 0;
1746         struct cod_manager *cod_mgr;
1747         u32 ul_trace_end;
1748         u32 ul_trace_begin;
1749         u32 trace_cur_pos;
1750         u32 ul_num_bytes = 0;
1751         u32 ul_num_words = 0;
1752         u32 ul_word_size = 2;
1753         char *psz_buf;
1754         char *str_beg;
1755         char *trace_end;
1756         char *buf_end;
1757         char *new_line;
1758
1759         struct bridge_dev_context *pbridge_context = hbridge_context;
1760         struct bridge_drv_interface *intf_fxns;
1761         struct dev_object *dev_obj = (struct dev_object *)
1762             pbridge_context->dev_obj;
1763
1764         status = dev_get_cod_mgr(dev_obj, &cod_mgr);
1765
1766         if (cod_mgr) {
1767                 /* Look for SYS_PUTCBEG/SYS_PUTCEND */
1768                 status =
1769                     cod_get_sym_value(cod_mgr, COD_TRACEBEG, &ul_trace_begin);
1770         } else {
1771                 status = -EFAULT;
1772         }
1773         if (!status)
1774                 status =
1775                     cod_get_sym_value(cod_mgr, COD_TRACEEND, &ul_trace_end);
1776
1777         if (!status)
1778                 /* trace_cur_pos will hold the address of a DSP pointer */
1779                 status = cod_get_sym_value(cod_mgr, COD_TRACECURPOS,
1780                                                         &trace_cur_pos);
1781
1782         if (status)
1783                 goto func_end;
1784
1785         ul_num_bytes = (ul_trace_end - ul_trace_begin);
1786
1787         ul_num_words = ul_num_bytes * ul_word_size;
1788         status = dev_get_intf_fxns(dev_obj, &intf_fxns);
1789
1790         if (status)
1791                 goto func_end;
1792
1793         psz_buf = kzalloc(ul_num_bytes + 2, GFP_ATOMIC);
1794         if (psz_buf != NULL) {
1795                 /* Read trace buffer data */
1796                 status = (*intf_fxns->brd_read)(pbridge_context,
1797                         (u8 *)psz_buf, (u32)ul_trace_begin,
1798                         ul_num_bytes, 0);
1799
1800                 if (status)
1801                         goto func_end;
1802
1803                 /* Pack and do newline conversion */
1804                 pr_debug("PrintDspTraceBuffer: "
1805                         "before pack and unpack.\n");
1806                 pr_debug("%s: DSP Trace Buffer Begin:\n"
1807                         "=======================\n%s\n",
1808                         __func__, psz_buf);
1809
1810                 /* Read the value at the DSP address in trace_cur_pos. */
1811                 status = (*intf_fxns->brd_read)(pbridge_context,
1812                                 (u8 *)&trace_cur_pos, (u32)trace_cur_pos,
1813                                 4, 0);
1814                 if (status)
1815                         goto func_end;
1816                 /* Pack and do newline conversion */
1817                 pr_info("DSP Trace Buffer Begin:\n"
1818                         "=======================\n%s\n",
1819                         psz_buf);
1820
1821
1822                 /* convert to offset */
1823                 trace_cur_pos = trace_cur_pos - ul_trace_begin;
1824
1825                 if (ul_num_bytes) {
1826                         /*
1827                          * The buffer is not full, find the end of the
1828                          * data -- buf_end will be >= pszBuf after
1829                          * while.
1830                          */
1831                         buf_end = &psz_buf[ul_num_bytes+1];
1832                         /* DSP print position */
1833                         trace_end = &psz_buf[trace_cur_pos];
1834
1835                         /*
1836                          * Search buffer for a new_line and replace it
1837                          * with '\0', then print as string.
1838                          * Continue until end of buffer is reached.
1839                          */
1840                         str_beg = trace_end;
1841                         ul_num_bytes = buf_end - str_beg;
1842
1843                         while (str_beg < buf_end) {
1844                                 new_line = strnchr(str_beg, ul_num_bytes,
1845                                                                 '\n');
1846                                 if (new_line && new_line < buf_end) {
1847                                         *new_line = 0;
1848                                         pr_debug("%s\n", str_beg);
1849                                         str_beg = ++new_line;
1850                                         ul_num_bytes = buf_end - str_beg;
1851                                 } else {
1852                                         /*
1853                                          * Assume buffer empty if it contains
1854                                          * a zero
1855                                          */
1856                                         if (*str_beg != '\0') {
1857                                                 str_beg[ul_num_bytes] = 0;
1858                                                 pr_debug("%s\n", str_beg);
1859                                         }
1860                                         str_beg = buf_end;
1861                                         ul_num_bytes = 0;
1862                                 }
1863                         }
1864                         /*
1865                          * Search buffer for a nNewLine and replace it
1866                          * with '\0', then print as string.
1867                          * Continue until buffer is exhausted.
1868                          */
1869                         str_beg = psz_buf;
1870                         ul_num_bytes = trace_end - str_beg;
1871
1872                         while (str_beg < trace_end) {
1873                                 new_line = strnchr(str_beg, ul_num_bytes, '\n');
1874                                 if (new_line != NULL && new_line < trace_end) {
1875                                         *new_line = 0;
1876                                         pr_debug("%s\n", str_beg);
1877                                         str_beg = ++new_line;
1878                                         ul_num_bytes = trace_end - str_beg;
1879                                 } else {
1880                                         /*
1881                                          * Assume buffer empty if it contains
1882                                          * a zero
1883                                          */
1884                                         if (*str_beg != '\0') {
1885                                                 str_beg[ul_num_bytes] = 0;
1886                                                 pr_debug("%s\n", str_beg);
1887                                         }
1888                                         str_beg = trace_end;
1889                                         ul_num_bytes = 0;
1890                                 }
1891                         }
1892                 }
1893                 pr_info("\n=======================\n"
1894                         "DSP Trace Buffer End:\n");
1895                 kfree(psz_buf);
1896         } else {
1897                 status = -ENOMEM;
1898         }
1899 func_end:
1900         if (status)
1901                 dev_dbg(bridge, "%s Failed, status 0x%x\n", __func__, status);
1902         return status;
1903 }
1904
1905 /**
1906  * dump_dsp_stack() - This function dumps the data on the DSP stack.
1907  * @bridge_context:     Bridge driver's device context pointer.
1908  *
1909  */
1910 int dump_dsp_stack(struct bridge_dev_context *bridge_context)
1911 {
1912         int status = 0;
1913         struct cod_manager *code_mgr;
1914         struct node_mgr *node_mgr;
1915         u32 trace_begin;
1916         char name[256];
1917         struct {
1918                 u32 head[2];
1919                 u32 size;
1920         } mmu_fault_dbg_info;
1921         u32 *buffer;
1922         u32 *buffer_beg;
1923         u32 *buffer_end;
1924         u32 exc_type;
1925         u32 dyn_ext_base;
1926         u32 i;
1927         u32 offset_output;
1928         u32 total_size;
1929         u32 poll_cnt;
1930         const char *dsp_regs[] = {"EFR", "IERR", "ITSR", "NTSR",
1931                                 "IRP", "NRP", "AMR", "SSR",
1932                                 "ILC", "RILC", "IER", "CSR"};
1933         const char *exec_ctxt[] = {"Task", "SWI", "HWI", "Unknown"};
1934         struct bridge_drv_interface *intf_fxns;
1935         struct dev_object *dev_object = bridge_context->dev_obj;
1936
1937         status = dev_get_cod_mgr(dev_object, &code_mgr);
1938         if (!code_mgr) {
1939                 pr_debug("%s: Failed on dev_get_cod_mgr.\n", __func__);
1940                 status = -EFAULT;
1941         }
1942
1943         if (!status) {
1944                 status = dev_get_node_manager(dev_object, &node_mgr);
1945                 if (!node_mgr) {
1946                         pr_debug("%s: Failed on dev_get_node_manager.\n",
1947                                                                 __func__);
1948                         status = -EFAULT;
1949                 }
1950         }
1951
1952         if (!status) {
1953                 /* Look for SYS_PUTCBEG/SYS_PUTCEND: */
1954                 status =
1955                         cod_get_sym_value(code_mgr, COD_TRACEBEG, &trace_begin);
1956                 pr_debug("%s: trace_begin Value 0x%x\n",
1957                         __func__, trace_begin);
1958                 if (status)
1959                         pr_debug("%s: Failed on cod_get_sym_value.\n",
1960                                                                 __func__);
1961         }
1962         if (!status)
1963                 status = dev_get_intf_fxns(dev_object, &intf_fxns);
1964         /*
1965          * Check for the "magic number" in the trace buffer.  If it has
1966          * yet to appear then poll the trace buffer to wait for it.  Its
1967          * appearance signals that the DSP has finished dumping its state.
1968          */
1969         mmu_fault_dbg_info.head[0] = 0;
1970         mmu_fault_dbg_info.head[1] = 0;
1971         if (!status) {
1972                 poll_cnt = 0;
1973                 while ((mmu_fault_dbg_info.head[0] != MMU_FAULT_HEAD1 ||
1974                         mmu_fault_dbg_info.head[1] != MMU_FAULT_HEAD2) &&
1975                         poll_cnt < POLL_MAX) {
1976
1977                         /* Read DSP dump size from the DSP trace buffer... */
1978                         status = (*intf_fxns->brd_read)(bridge_context,
1979                                 (u8 *)&mmu_fault_dbg_info, (u32)trace_begin,
1980                                 sizeof(mmu_fault_dbg_info), 0);
1981
1982                         if (status)
1983                                 break;
1984
1985                         poll_cnt++;
1986                 }
1987
1988                 if (mmu_fault_dbg_info.head[0] != MMU_FAULT_HEAD1 &&
1989                         mmu_fault_dbg_info.head[1] != MMU_FAULT_HEAD2) {
1990                         status = -ETIME;
1991                         pr_err("%s:No DSP MMU-Fault information available.\n",
1992                                                         __func__);
1993                 }
1994         }
1995
1996         if (!status) {
1997                 total_size = mmu_fault_dbg_info.size;
1998                 /* Limit the size in case DSP went crazy */
1999                 if (total_size > MAX_MMU_DBGBUFF)
2000                         total_size = MAX_MMU_DBGBUFF;
2001
2002                 buffer = kzalloc(total_size, GFP_ATOMIC);
2003                 if (!buffer) {
2004                         status = -ENOMEM;
2005                         pr_debug("%s: Failed to "
2006                                 "allocate stack dump buffer.\n", __func__);
2007                         goto func_end;
2008                 }
2009
2010                 buffer_beg = buffer;
2011                 buffer_end =  buffer + total_size / 4;
2012
2013                 /* Read bytes from the DSP trace buffer... */
2014                 status = (*intf_fxns->brd_read)(bridge_context,
2015                                 (u8 *)buffer, (u32)trace_begin,
2016                                 total_size, 0);
2017                 if (status) {
2018                         pr_debug("%s: Failed to Read Trace Buffer.\n",
2019                                                                 __func__);
2020                         goto func_end;
2021                 }
2022
2023                 pr_err("\nAproximate Crash Position:\n"
2024                         "--------------------------\n");
2025
2026                 exc_type = buffer[3];
2027                 if (!exc_type)
2028                         i = buffer[79];         /* IRP */
2029                 else
2030                         i = buffer[80];         /* NRP */
2031
2032                 status =
2033                     cod_get_sym_value(code_mgr, DYNEXTBASE, &dyn_ext_base);
2034                 if (status) {
2035                         status = -EFAULT;
2036                         goto func_end;
2037                 }
2038
2039                 if ((i > dyn_ext_base) && (node_find_addr(node_mgr, i,
2040                         0x1000, &offset_output, name) == 0))
2041                         pr_err("0x%-8x [\"%s\" + 0x%x]\n", i, name,
2042                                                         i - offset_output);
2043                 else
2044                         pr_err("0x%-8x [Unable to match to a symbol.]\n", i);
2045
2046                 buffer += 4;
2047
2048                 pr_err("\nExecution Info:\n"
2049                         "---------------\n");
2050
2051                 if (*buffer < ARRAY_SIZE(exec_ctxt)) {
2052                         pr_err("Execution context \t%s\n",
2053                                 exec_ctxt[*buffer++]);
2054                 } else {
2055                         pr_err("Execution context corrupt\n");
2056                         kfree(buffer_beg);
2057                         return -EFAULT;
2058                 }
2059                 pr_err("Task Handle\t\t0x%x\n", *buffer++);
2060                 pr_err("Stack Pointer\t\t0x%x\n", *buffer++);
2061                 pr_err("Stack Top\t\t0x%x\n", *buffer++);
2062                 pr_err("Stack Bottom\t\t0x%x\n", *buffer++);
2063                 pr_err("Stack Size\t\t0x%x\n", *buffer++);
2064                 pr_err("Stack Size In Use\t0x%x\n", *buffer++);
2065
2066                 pr_err("\nCPU Registers\n"
2067                         "---------------\n");
2068
2069                 for (i = 0; i < 32; i++) {
2070                         if (i == 4 || i == 6 || i == 8)
2071                                 pr_err("A%d 0x%-8x [Function Argument %d]\n",
2072                                                         i, *buffer++, i-3);
2073                         else if (i == 15)
2074                                 pr_err("A15 0x%-8x [Frame Pointer]\n",
2075                                                                 *buffer++);
2076                         else
2077                                 pr_err("A%d 0x%x\n", i, *buffer++);
2078                 }
2079
2080                 pr_err("\nB0 0x%x\n", *buffer++);
2081                 pr_err("B1 0x%x\n", *buffer++);
2082                 pr_err("B2 0x%x\n", *buffer++);
2083
2084                 if ((*buffer > dyn_ext_base) && (node_find_addr(node_mgr,
2085                         *buffer, 0x1000, &offset_output, name) == 0))
2086
2087                         pr_err("B3 0x%-8x [Function Return Pointer:"
2088                                 " \"%s\" + 0x%x]\n", *buffer, name,
2089                                 *buffer - offset_output);
2090                 else
2091                         pr_err("B3 0x%-8x [Function Return Pointer:"
2092                                 "Unable to match to a symbol.]\n", *buffer);
2093
2094                 buffer++;
2095
2096                 for (i = 4; i < 32; i++) {
2097                         if (i == 4 || i == 6 || i == 8)
2098                                 pr_err("B%d 0x%-8x [Function Argument %d]\n",
2099                                                         i, *buffer++, i-2);
2100                         else if (i == 14)
2101                                 pr_err("B14 0x%-8x [Data Page Pointer]\n",
2102                                                                 *buffer++);
2103                         else
2104                                 pr_err("B%d 0x%x\n", i, *buffer++);
2105                 }
2106
2107                 pr_err("\n");
2108
2109                 for (i = 0; i < ARRAY_SIZE(dsp_regs); i++)
2110                         pr_err("%s 0x%x\n", dsp_regs[i], *buffer++);
2111
2112                 pr_err("\nStack:\n"
2113                         "------\n");
2114
2115                 for (i = 0; buffer < buffer_end; i++, buffer++) {
2116                         if ((*buffer > dyn_ext_base) && (
2117                                 node_find_addr(node_mgr, *buffer , 0x600,
2118                                 &offset_output, name) == 0))
2119                                 pr_err("[%d] 0x%-8x [\"%s\" + 0x%x]\n",
2120                                         i, *buffer, name,
2121                                         *buffer - offset_output);
2122                         else
2123                                 pr_err("[%d] 0x%x\n", i, *buffer);
2124                 }
2125                 kfree(buffer_beg);
2126         }
2127 func_end:
2128         return status;
2129 }
2130
2131 /**
2132  * dump_dl_modules() - This functions dumps the _DLModules loaded in DSP side
2133  * @bridge_context:             Bridge driver's device context pointer.
2134  *
2135  */
2136 void dump_dl_modules(struct bridge_dev_context *bridge_context)
2137 {
2138         struct cod_manager *code_mgr;
2139         struct bridge_drv_interface *intf_fxns;
2140         struct bridge_dev_context *bridge_ctxt = bridge_context;
2141         struct dev_object *dev_object = bridge_ctxt->dev_obj;
2142         struct modules_header modules_hdr;
2143         struct dll_module *module_struct = NULL;
2144         u32 module_dsp_addr;
2145         u32 module_size;
2146         u32 module_struct_size = 0;
2147         u32 sect_ndx;
2148         char *sect_str ;
2149         int status = 0;
2150
2151         status = dev_get_intf_fxns(dev_object, &intf_fxns);
2152         if (status) {
2153                 pr_debug("%s: Failed on dev_get_intf_fxns.\n", __func__);
2154                 goto func_end;
2155         }
2156
2157         status = dev_get_cod_mgr(dev_object, &code_mgr);
2158         if (!code_mgr) {
2159                 pr_debug("%s: Failed on dev_get_cod_mgr.\n", __func__);
2160                 status = -EFAULT;
2161                 goto func_end;
2162         }
2163
2164         /* Lookup  the address of the modules_header structure */
2165         status = cod_get_sym_value(code_mgr, "_DLModules", &module_dsp_addr);
2166         if (status) {
2167                 pr_debug("%s: Failed on cod_get_sym_value for _DLModules.\n",
2168                         __func__);
2169                 goto func_end;
2170         }
2171
2172         pr_debug("%s: _DLModules at 0x%x\n", __func__, module_dsp_addr);
2173
2174         /* Copy the modules_header structure from DSP memory. */
2175         status = (*intf_fxns->brd_read)(bridge_context, (u8 *) &modules_hdr,
2176                                 (u32) module_dsp_addr, sizeof(modules_hdr), 0);
2177
2178         if (status) {
2179                 pr_debug("%s: Failed failed to read modules header.\n",
2180                                                                 __func__);
2181                 goto func_end;
2182         }
2183
2184         module_dsp_addr = modules_hdr.first_module;
2185         module_size = modules_hdr.first_module_size;
2186
2187         pr_debug("%s: dll_module_header 0x%x %d\n", __func__, module_dsp_addr,
2188                                                                 module_size);
2189
2190         pr_err("\nDynamically Loaded Modules:\n"
2191                 "---------------------------\n");
2192
2193         /* For each dll_module structure in the list... */
2194         while (module_size) {
2195                 /*
2196                  * Allocate/re-allocate memory to hold the dll_module
2197                  * structure. The memory is re-allocated only if the existing
2198                  * allocation is too small.
2199                  */
2200                 if (module_size > module_struct_size) {
2201                         kfree(module_struct);
2202                         module_struct = kzalloc(module_size+128, GFP_ATOMIC);
2203                         module_struct_size = module_size+128;
2204                         pr_debug("%s: allocated module struct %p %d\n",
2205                                 __func__, module_struct, module_struct_size);
2206                         if (!module_struct)
2207                                 goto func_end;
2208                 }
2209                 /* Copy the dll_module structure from DSP memory */
2210                 status = (*intf_fxns->brd_read)(bridge_context,
2211                         (u8 *)module_struct, module_dsp_addr, module_size, 0);
2212
2213                 if (status) {
2214                         pr_debug(
2215                         "%s: Failed to read dll_module struct for 0x%x.\n",
2216                         __func__, module_dsp_addr);
2217                         break;
2218                 }
2219
2220                 /* Update info regarding the _next_ module in the list. */
2221                 module_dsp_addr = module_struct->next_module;
2222                 module_size = module_struct->next_module_size;
2223
2224                 pr_debug("%s: next module 0x%x %d, this module num sects %d\n",
2225                         __func__, module_dsp_addr, module_size,
2226                         module_struct->num_sects);
2227
2228                 /*
2229                  * The section name strings start immedialty following
2230                  * the array of dll_sect structures.
2231                  */
2232                 sect_str = (char *) &module_struct->
2233                                         sects[module_struct->num_sects];
2234                 pr_err("%s\n", sect_str);
2235
2236                 /*
2237                  * Advance to the first section name string.
2238                  * Each string follows the one before.
2239                  */
2240                 sect_str += strlen(sect_str) + 1;
2241
2242                 /* Access each dll_sect structure and its name string. */
2243                 for (sect_ndx = 0;
2244                         sect_ndx < module_struct->num_sects; sect_ndx++) {
2245                         pr_err("    Section: 0x%x ",
2246                                 module_struct->sects[sect_ndx].sect_load_adr);
2247
2248                         if (((u32) sect_str - (u32) module_struct) <
2249                                 module_struct_size) {
2250                                 pr_err("%s\n", sect_str);
2251                                 /* Each string follows the one before. */
2252                                 sect_str += strlen(sect_str)+1;
2253                         } else {
2254                                 pr_err("<string error>\n");
2255                                 pr_debug("%s: section name sting address "
2256                                         "is invalid %p\n", __func__, sect_str);
2257                         }
2258                 }
2259         }
2260 func_end:
2261         kfree(module_struct);
2262 }
2263 #endif