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