]> Pileus Git - ~andy/linux/blob - drivers/staging/tidspbridge/rmgr/proc.c
Merge tag 'stable/for-linus-3.7-arm-tag' of git://git.kernel.org/pub/scm/linux/kernel...
[~andy/linux] / drivers / staging / tidspbridge / rmgr / proc.c
1 /*
2  * proc.c
3  *
4  * DSP-BIOS Bridge driver support functions for TI OMAP processors.
5  *
6  * Processor interface at the driver level.
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 #include <linux/types.h>
20 /* ------------------------------------ Host OS */
21 #include <linux/dma-mapping.h>
22 #include <linux/scatterlist.h>
23 #include <dspbridge/host_os.h>
24
25 /*  ----------------------------------- DSP/BIOS Bridge */
26 #include <dspbridge/dbdefs.h>
27
28 /*  ----------------------------------- OS Adaptation Layer */
29 #include <dspbridge/ntfy.h>
30 #include <dspbridge/sync.h>
31 /*  ----------------------------------- Bridge Driver */
32 #include <dspbridge/dspdefs.h>
33 #include <dspbridge/dspdeh.h>
34 /*  ----------------------------------- Platform Manager */
35 #include <dspbridge/cod.h>
36 #include <dspbridge/dev.h>
37 #include <dspbridge/procpriv.h>
38 #include <dspbridge/dmm.h>
39
40 /*  ----------------------------------- Resource Manager */
41 #include <dspbridge/mgr.h>
42 #include <dspbridge/node.h>
43 #include <dspbridge/nldr.h>
44 #include <dspbridge/rmm.h>
45
46 /*  ----------------------------------- Others */
47 #include <dspbridge/dbdcd.h>
48 #include <dspbridge/msg.h>
49 #include <dspbridge/dspioctl.h>
50 #include <dspbridge/drv.h>
51
52 /*  ----------------------------------- This */
53 #include <dspbridge/proc.h>
54 #include <dspbridge/pwr.h>
55
56 #include <dspbridge/resourcecleanup.h>
57 /*  ----------------------------------- Defines, Data Structures, Typedefs */
58 #define MAXCMDLINELEN       255
59 #define PROC_ENVPROCID      "PROC_ID=%d"
60 #define MAXPROCIDLEN    (8 + 5)
61 #define PROC_DFLT_TIMEOUT   10000       /* Time out in milliseconds */
62 #define PWR_TIMEOUT      500    /* Sleep/wake timout in msec */
63 #define EXTEND        "_EXT_END"        /* Extmem end addr in DSP binary */
64
65 #define DSP_CACHE_LINE 128
66
67 #define BUFMODE_MASK    (3 << 14)
68
69 /* Buffer modes from DSP perspective */
70 #define RBUF            0x4000          /* Input buffer */
71 #define WBUF            0x8000          /* Output Buffer */
72
73 extern struct device *bridge;
74
75 /*  ----------------------------------- Globals */
76
77 /* The proc_object structure. */
78 struct proc_object {
79         struct list_head link;  /* Link to next proc_object */
80         struct dev_object *dev_obj;     /* Device this PROC represents */
81         u32 process;            /* Process owning this Processor */
82         struct mgr_object *mgr_obj;     /* Manager Object Handle */
83         u32 attach_count;       /* Processor attach count */
84         u32 processor_id;       /* Processor number */
85         u32 timeout;            /* Time out count */
86         enum dsp_procstate proc_state;  /* Processor state */
87         u32 unit;               /* DDSP unit number */
88         bool is_already_attached;       /*
89                                          * True if the Device below has
90                                          * GPP Client attached
91                                          */
92         struct ntfy_object *ntfy_obj;   /* Manages  notifications */
93         /* Bridge Context Handle */
94         struct bridge_dev_context *bridge_context;
95         /* Function interface to Bridge driver */
96         struct bridge_drv_interface *intf_fxns;
97         char *last_coff;
98         struct list_head proc_list;
99 };
100
101 DEFINE_MUTEX(proc_lock);        /* For critical sections */
102
103 /*  ----------------------------------- Function Prototypes */
104 static int proc_monitor(struct proc_object *proc_obj);
105 static s32 get_envp_count(char **envp);
106 static char **prepend_envp(char **new_envp, char **envp, s32 envp_elems,
107                            s32 cnew_envp, char *sz_var);
108
109 /* remember mapping information */
110 static struct dmm_map_object *add_mapping_info(struct process_context *pr_ctxt,
111                                 u32 mpu_addr, u32 dsp_addr, u32 size)
112 {
113         struct dmm_map_object *map_obj;
114
115         u32 num_usr_pgs = size / PG_SIZE4K;
116
117         pr_debug("%s: adding map info: mpu_addr 0x%x virt 0x%x size 0x%x\n",
118                                                 __func__, mpu_addr,
119                                                 dsp_addr, size);
120
121         map_obj = kzalloc(sizeof(struct dmm_map_object), GFP_KERNEL);
122         if (!map_obj) {
123                 pr_err("%s: kzalloc failed\n", __func__);
124                 return NULL;
125         }
126         INIT_LIST_HEAD(&map_obj->link);
127
128         map_obj->pages = kcalloc(num_usr_pgs, sizeof(struct page *),
129                                                         GFP_KERNEL);
130         if (!map_obj->pages) {
131                 pr_err("%s: kzalloc failed\n", __func__);
132                 kfree(map_obj);
133                 return NULL;
134         }
135
136         map_obj->mpu_addr = mpu_addr;
137         map_obj->dsp_addr = dsp_addr;
138         map_obj->size = size;
139         map_obj->num_usr_pgs = num_usr_pgs;
140
141         spin_lock(&pr_ctxt->dmm_map_lock);
142         list_add(&map_obj->link, &pr_ctxt->dmm_map_list);
143         spin_unlock(&pr_ctxt->dmm_map_lock);
144
145         return map_obj;
146 }
147
148 static int match_exact_map_obj(struct dmm_map_object *map_obj,
149                                         u32 dsp_addr, u32 size)
150 {
151         if (map_obj->dsp_addr == dsp_addr && map_obj->size != size)
152                 pr_err("%s: addr match (0x%x), size don't (0x%x != 0x%x)\n",
153                                 __func__, dsp_addr, map_obj->size, size);
154
155         return map_obj->dsp_addr == dsp_addr &&
156                 map_obj->size == size;
157 }
158
159 static void remove_mapping_information(struct process_context *pr_ctxt,
160                                                 u32 dsp_addr, u32 size)
161 {
162         struct dmm_map_object *map_obj;
163
164         pr_debug("%s: looking for virt 0x%x size 0x%x\n", __func__,
165                                                         dsp_addr, size);
166
167         spin_lock(&pr_ctxt->dmm_map_lock);
168         list_for_each_entry(map_obj, &pr_ctxt->dmm_map_list, link) {
169                 pr_debug("%s: candidate: mpu_addr 0x%x virt 0x%x size 0x%x\n",
170                                                         __func__,
171                                                         map_obj->mpu_addr,
172                                                         map_obj->dsp_addr,
173                                                         map_obj->size);
174
175                 if (match_exact_map_obj(map_obj, dsp_addr, size)) {
176                         pr_debug("%s: match, deleting map info\n", __func__);
177                         list_del(&map_obj->link);
178                         kfree(map_obj->dma_info.sg);
179                         kfree(map_obj->pages);
180                         kfree(map_obj);
181                         goto out;
182                 }
183                 pr_debug("%s: candidate didn't match\n", __func__);
184         }
185
186         pr_err("%s: failed to find given map info\n", __func__);
187 out:
188         spin_unlock(&pr_ctxt->dmm_map_lock);
189 }
190
191 static int match_containing_map_obj(struct dmm_map_object *map_obj,
192                                         u32 mpu_addr, u32 size)
193 {
194         u32 map_obj_end = map_obj->mpu_addr + map_obj->size;
195
196         return mpu_addr >= map_obj->mpu_addr &&
197                 mpu_addr + size <= map_obj_end;
198 }
199
200 static struct dmm_map_object *find_containing_mapping(
201                                 struct process_context *pr_ctxt,
202                                 u32 mpu_addr, u32 size)
203 {
204         struct dmm_map_object *map_obj;
205         pr_debug("%s: looking for mpu_addr 0x%x size 0x%x\n", __func__,
206                                                 mpu_addr, size);
207
208         spin_lock(&pr_ctxt->dmm_map_lock);
209         list_for_each_entry(map_obj, &pr_ctxt->dmm_map_list, link) {
210                 pr_debug("%s: candidate: mpu_addr 0x%x virt 0x%x size 0x%x\n",
211                                                 __func__,
212                                                 map_obj->mpu_addr,
213                                                 map_obj->dsp_addr,
214                                                 map_obj->size);
215                 if (match_containing_map_obj(map_obj, mpu_addr, size)) {
216                         pr_debug("%s: match!\n", __func__);
217                         goto out;
218                 }
219
220                 pr_debug("%s: no match!\n", __func__);
221         }
222
223         map_obj = NULL;
224 out:
225         spin_unlock(&pr_ctxt->dmm_map_lock);
226         return map_obj;
227 }
228
229 static int find_first_page_in_cache(struct dmm_map_object *map_obj,
230                                         unsigned long mpu_addr)
231 {
232         u32 mapped_base_page = map_obj->mpu_addr >> PAGE_SHIFT;
233         u32 requested_base_page = mpu_addr >> PAGE_SHIFT;
234         int pg_index = requested_base_page - mapped_base_page;
235
236         if (pg_index < 0 || pg_index >= map_obj->num_usr_pgs) {
237                 pr_err("%s: failed (got %d)\n", __func__, pg_index);
238                 return -1;
239         }
240
241         pr_debug("%s: first page is %d\n", __func__, pg_index);
242         return pg_index;
243 }
244
245 static inline struct page *get_mapping_page(struct dmm_map_object *map_obj,
246                                                                 int pg_i)
247 {
248         pr_debug("%s: looking for pg_i %d, num_usr_pgs: %d\n", __func__,
249                                         pg_i, map_obj->num_usr_pgs);
250
251         if (pg_i < 0 || pg_i >= map_obj->num_usr_pgs) {
252                 pr_err("%s: requested pg_i %d is out of mapped range\n",
253                                 __func__, pg_i);
254                 return NULL;
255         }
256
257         return map_obj->pages[pg_i];
258 }
259
260 /*
261  *  ======== proc_attach ========
262  *  Purpose:
263  *      Prepare for communication with a particular DSP processor, and return
264  *      a handle to the processor object.
265  */
266 int
267 proc_attach(u32 processor_id,
268             const struct dsp_processorattrin *attr_in,
269             void **ph_processor, struct process_context *pr_ctxt)
270 {
271         int status = 0;
272         struct dev_object *hdev_obj;
273         struct proc_object *p_proc_object = NULL;
274         struct mgr_object *hmgr_obj = NULL;
275         struct drv_object *hdrv_obj = NULL;
276         struct drv_data *drv_datap = dev_get_drvdata(bridge);
277         u8 dev_type;
278
279         if (pr_ctxt->processor) {
280                 *ph_processor = pr_ctxt->processor;
281                 return status;
282         }
283
284         /* Get the Driver and Manager Object Handles */
285         if (!drv_datap || !drv_datap->drv_object || !drv_datap->mgr_object) {
286                 status = -ENODATA;
287                 pr_err("%s: Failed to get object handles\n", __func__);
288         } else {
289                 hdrv_obj = drv_datap->drv_object;
290                 hmgr_obj = drv_datap->mgr_object;
291         }
292
293         if (!status) {
294                 /* Get the Device Object */
295                 status = drv_get_dev_object(processor_id, hdrv_obj, &hdev_obj);
296         }
297         if (!status)
298                 status = dev_get_dev_type(hdev_obj, &dev_type);
299
300         if (status)
301                 goto func_end;
302
303         /* If we made it this far, create the Processor object: */
304         p_proc_object = kzalloc(sizeof(struct proc_object), GFP_KERNEL);
305         /* Fill out the Processor Object: */
306         if (p_proc_object == NULL) {
307                 status = -ENOMEM;
308                 goto func_end;
309         }
310         p_proc_object->dev_obj = hdev_obj;
311         p_proc_object->mgr_obj = hmgr_obj;
312         p_proc_object->processor_id = dev_type;
313         /* Store TGID instead of process handle */
314         p_proc_object->process = current->tgid;
315
316         INIT_LIST_HEAD(&p_proc_object->proc_list);
317
318         if (attr_in)
319                 p_proc_object->timeout = attr_in->timeout;
320         else
321                 p_proc_object->timeout = PROC_DFLT_TIMEOUT;
322
323         status = dev_get_intf_fxns(hdev_obj, &p_proc_object->intf_fxns);
324         if (!status) {
325                 status = dev_get_bridge_context(hdev_obj,
326                                              &p_proc_object->bridge_context);
327                 if (status)
328                         kfree(p_proc_object);
329         } else
330                 kfree(p_proc_object);
331
332         if (status)
333                 goto func_end;
334
335         /* Create the Notification Object */
336         /* This is created with no event mask, no notify mask
337          * and no valid handle to the notification. They all get
338          * filled up when proc_register_notify is called */
339         p_proc_object->ntfy_obj = kmalloc(sizeof(struct ntfy_object),
340                                                         GFP_KERNEL);
341         if (p_proc_object->ntfy_obj)
342                 ntfy_init(p_proc_object->ntfy_obj);
343         else
344                 status = -ENOMEM;
345
346         if (!status) {
347                 /* Insert the Processor Object into the DEV List.
348                  * Return handle to this Processor Object:
349                  * Find out if the Device is already attached to a
350                  * Processor. If so, return AlreadyAttached status */
351                 status = dev_insert_proc_object(p_proc_object->dev_obj,
352                                                 (u32) p_proc_object,
353                                                 &p_proc_object->
354                                                 is_already_attached);
355                 if (!status) {
356                         if (p_proc_object->is_already_attached)
357                                 status = 0;
358                 } else {
359                         if (p_proc_object->ntfy_obj) {
360                                 ntfy_delete(p_proc_object->ntfy_obj);
361                                 kfree(p_proc_object->ntfy_obj);
362                         }
363
364                         kfree(p_proc_object);
365                 }
366                 if (!status) {
367                         *ph_processor = (void *)p_proc_object;
368                         pr_ctxt->processor = *ph_processor;
369                         (void)proc_notify_clients(p_proc_object,
370                                                   DSP_PROCESSORATTACH);
371                 }
372         } else {
373                 /* Don't leak memory if status is failed */
374                 kfree(p_proc_object);
375         }
376 func_end:
377         return status;
378 }
379
380 static int get_exec_file(struct cfg_devnode *dev_node_obj,
381                                 struct dev_object *hdev_obj,
382                                 u32 size, char *exec_file)
383 {
384         u8 dev_type;
385         s32 len;
386         struct drv_data *drv_datap = dev_get_drvdata(bridge);
387
388         dev_get_dev_type(hdev_obj, (u8 *) &dev_type);
389
390         if (!exec_file)
391                 return -EFAULT;
392
393         if (dev_type == DSP_UNIT) {
394                 if (!drv_datap || !drv_datap->base_img)
395                         return -EFAULT;
396
397                 if (strlen(drv_datap->base_img) > size)
398                         return -EINVAL;
399
400                 strcpy(exec_file, drv_datap->base_img);
401         } else if (dev_type == IVA_UNIT && iva_img) {
402                 len = strlen(iva_img);
403                 strncpy(exec_file, iva_img, len + 1);
404         } else {
405                 return -ENOENT;
406         }
407
408         return 0;
409 }
410
411 /*
412  *  ======== proc_auto_start ======== =
413  *  Purpose:
414  *      A Particular device gets loaded with the default image
415  *      if the AutoStart flag is set.
416  *  Parameters:
417  *      hdev_obj:     Handle to the Device
418  *  Returns:
419  *      0:   On Successful Loading
420  *      -EPERM  General Failure
421  *  Requires:
422  *      hdev_obj != NULL
423  *  Ensures:
424  */
425 int proc_auto_start(struct cfg_devnode *dev_node_obj,
426                            struct dev_object *hdev_obj)
427 {
428         int status = -EPERM;
429         struct proc_object *p_proc_object;
430         char sz_exec_file[MAXCMDLINELEN];
431         char *argv[2];
432         struct mgr_object *hmgr_obj = NULL;
433         struct drv_data *drv_datap = dev_get_drvdata(bridge);
434         u8 dev_type;
435
436         /* Create a Dummy PROC Object */
437         if (!drv_datap || !drv_datap->mgr_object) {
438                 status = -ENODATA;
439                 pr_err("%s: Failed to retrieve the object handle\n", __func__);
440                 goto func_end;
441         } else {
442                 hmgr_obj = drv_datap->mgr_object;
443         }
444
445         p_proc_object = kzalloc(sizeof(struct proc_object), GFP_KERNEL);
446         if (p_proc_object == NULL) {
447                 status = -ENOMEM;
448                 goto func_end;
449         }
450         p_proc_object->dev_obj = hdev_obj;
451         p_proc_object->mgr_obj = hmgr_obj;
452         status = dev_get_intf_fxns(hdev_obj, &p_proc_object->intf_fxns);
453         if (!status)
454                 status = dev_get_bridge_context(hdev_obj,
455                                              &p_proc_object->bridge_context);
456         if (status)
457                 goto func_cont;
458
459         /* Stop the Device, put it into standby mode */
460         status = proc_stop(p_proc_object);
461
462         if (status)
463                 goto func_cont;
464
465         /* Get the default executable for this board... */
466         dev_get_dev_type(hdev_obj, (u8 *) &dev_type);
467         p_proc_object->processor_id = dev_type;
468         status = get_exec_file(dev_node_obj, hdev_obj, sizeof(sz_exec_file),
469                                sz_exec_file);
470         if (!status) {
471                 argv[0] = sz_exec_file;
472                 argv[1] = NULL;
473                 /* ...and try to load it: */
474                 status = proc_load(p_proc_object, 1, (const char **)argv, NULL);
475                 if (!status)
476                         status = proc_start(p_proc_object);
477         }
478         kfree(p_proc_object->last_coff);
479         p_proc_object->last_coff = NULL;
480 func_cont:
481         kfree(p_proc_object);
482 func_end:
483         return status;
484 }
485
486 /*
487  *  ======== proc_ctrl ========
488  *  Purpose:
489  *      Pass control information to the GPP device driver managing the
490  *      DSP processor.
491  *
492  *      This will be an OEM-only function, and not part of the DSP/BIOS Bridge
493  *      application developer's API.
494  *      Call the bridge_dev_ctrl fxn with the Argument. This is a Synchronous
495  *      Operation. arg can be null.
496  */
497 int proc_ctrl(void *hprocessor, u32 dw_cmd, struct dsp_cbdata * arg)
498 {
499         int status = 0;
500         struct proc_object *p_proc_object = hprocessor;
501         u32 timeout = 0;
502
503         if (p_proc_object) {
504                 /* intercept PWR deep sleep command */
505                 if (dw_cmd == BRDIOCTL_DEEPSLEEP) {
506                         timeout = arg->cb_data;
507                         status = pwr_sleep_dsp(PWR_DEEPSLEEP, timeout);
508                 }
509                 /* intercept PWR emergency sleep command */
510                 else if (dw_cmd == BRDIOCTL_EMERGENCYSLEEP) {
511                         timeout = arg->cb_data;
512                         status = pwr_sleep_dsp(PWR_EMERGENCYDEEPSLEEP, timeout);
513                 } else if (dw_cmd == PWR_DEEPSLEEP) {
514                         /* timeout = arg->cb_data; */
515                         status = pwr_sleep_dsp(PWR_DEEPSLEEP, timeout);
516                 }
517                 /* intercept PWR wake commands */
518                 else if (dw_cmd == BRDIOCTL_WAKEUP) {
519                         timeout = arg->cb_data;
520                         status = pwr_wake_dsp(timeout);
521                 } else if (dw_cmd == PWR_WAKEUP) {
522                         /* timeout = arg->cb_data; */
523                         status = pwr_wake_dsp(timeout);
524                 } else
525                     if (!((*p_proc_object->intf_fxns->dev_cntrl)
526                                       (p_proc_object->bridge_context, dw_cmd,
527                                        arg))) {
528                         status = 0;
529                 } else {
530                         status = -EPERM;
531                 }
532         } else {
533                 status = -EFAULT;
534         }
535
536         return status;
537 }
538
539 /*
540  *  ======== proc_detach ========
541  *  Purpose:
542  *      Destroys the  Processor Object. Removes the notification from the Dev
543  *      List.
544  */
545 int proc_detach(struct process_context *pr_ctxt)
546 {
547         int status = 0;
548         struct proc_object *p_proc_object = NULL;
549
550         p_proc_object = (struct proc_object *)pr_ctxt->processor;
551
552         if (p_proc_object) {
553                 /* Notify the Client */
554                 ntfy_notify(p_proc_object->ntfy_obj, DSP_PROCESSORDETACH);
555                 /* Remove the notification memory */
556                 if (p_proc_object->ntfy_obj) {
557                         ntfy_delete(p_proc_object->ntfy_obj);
558                         kfree(p_proc_object->ntfy_obj);
559                 }
560
561                 kfree(p_proc_object->last_coff);
562                 p_proc_object->last_coff = NULL;
563                 /* Remove the Proc from the DEV List */
564                 (void)dev_remove_proc_object(p_proc_object->dev_obj,
565                                              (u32) p_proc_object);
566                 /* Free the Processor Object */
567                 kfree(p_proc_object);
568                 pr_ctxt->processor = NULL;
569         } else {
570                 status = -EFAULT;
571         }
572
573         return status;
574 }
575
576 /*
577  *  ======== proc_enum_nodes ========
578  *  Purpose:
579  *      Enumerate and get configuration information about nodes allocated
580  *      on a DSP processor.
581  */
582 int proc_enum_nodes(void *hprocessor, void **node_tab,
583                            u32 node_tab_size, u32 *pu_num_nodes,
584                            u32 *pu_allocated)
585 {
586         int status = -EPERM;
587         struct proc_object *p_proc_object = (struct proc_object *)hprocessor;
588         struct node_mgr *hnode_mgr = NULL;
589
590         if (p_proc_object) {
591                 if (!(dev_get_node_manager(p_proc_object->dev_obj,
592                                                        &hnode_mgr))) {
593                         if (hnode_mgr) {
594                                 status = node_enum_nodes(hnode_mgr, node_tab,
595                                                          node_tab_size,
596                                                          pu_num_nodes,
597                                                          pu_allocated);
598                         }
599                 }
600         } else {
601                 status = -EFAULT;
602         }
603
604         return status;
605 }
606
607 /* Cache operation against kernel address instead of users */
608 static int build_dma_sg(struct dmm_map_object *map_obj, unsigned long start,
609                                                 ssize_t len, int pg_i)
610 {
611         struct page *page;
612         unsigned long offset;
613         ssize_t rest;
614         int ret = 0, i = 0;
615         struct scatterlist *sg = map_obj->dma_info.sg;
616
617         while (len) {
618                 page = get_mapping_page(map_obj, pg_i);
619                 if (!page) {
620                         pr_err("%s: no page for %08lx\n", __func__, start);
621                         ret = -EINVAL;
622                         goto out;
623                 } else if (IS_ERR(page)) {
624                         pr_err("%s: err page for %08lx(%lu)\n", __func__, start,
625                                PTR_ERR(page));
626                         ret = PTR_ERR(page);
627                         goto out;
628                 }
629
630                 offset = start & ~PAGE_MASK;
631                 rest = min_t(ssize_t, PAGE_SIZE - offset, len);
632
633                 sg_set_page(&sg[i], page, rest, offset);
634
635                 len -= rest;
636                 start += rest;
637                 pg_i++, i++;
638         }
639
640         if (i != map_obj->dma_info.num_pages) {
641                 pr_err("%s: bad number of sg iterations\n", __func__);
642                 ret = -EFAULT;
643                 goto out;
644         }
645
646 out:
647         return ret;
648 }
649
650 static int memory_regain_ownership(struct dmm_map_object *map_obj,
651                 unsigned long start, ssize_t len, enum dma_data_direction dir)
652 {
653         int ret = 0;
654         unsigned long first_data_page = start >> PAGE_SHIFT;
655         unsigned long last_data_page = ((u32)(start + len - 1) >> PAGE_SHIFT);
656         /* calculating the number of pages this area spans */
657         unsigned long num_pages = last_data_page - first_data_page + 1;
658         struct bridge_dma_map_info *dma_info = &map_obj->dma_info;
659
660         if (!dma_info->sg)
661                 goto out;
662
663         if (dma_info->dir != dir || dma_info->num_pages != num_pages) {
664                 pr_err("%s: dma info doesn't match given params\n", __func__);
665                 return -EINVAL;
666         }
667
668         dma_unmap_sg(bridge, dma_info->sg, num_pages, dma_info->dir);
669
670         pr_debug("%s: dma_map_sg unmapped\n", __func__);
671
672         kfree(dma_info->sg);
673
674         map_obj->dma_info.sg = NULL;
675
676 out:
677         return ret;
678 }
679
680 /* Cache operation against kernel address instead of users */
681 static int memory_give_ownership(struct dmm_map_object *map_obj,
682                 unsigned long start, ssize_t len, enum dma_data_direction dir)
683 {
684         int pg_i, ret, sg_num;
685         struct scatterlist *sg;
686         unsigned long first_data_page = start >> PAGE_SHIFT;
687         unsigned long last_data_page = ((u32)(start + len - 1) >> PAGE_SHIFT);
688         /* calculating the number of pages this area spans */
689         unsigned long num_pages = last_data_page - first_data_page + 1;
690
691         pg_i = find_first_page_in_cache(map_obj, start);
692         if (pg_i < 0) {
693                 pr_err("%s: failed to find first page in cache\n", __func__);
694                 ret = -EINVAL;
695                 goto out;
696         }
697
698         sg = kcalloc(num_pages, sizeof(*sg), GFP_KERNEL);
699         if (!sg) {
700                 pr_err("%s: kcalloc failed\n", __func__);
701                 ret = -ENOMEM;
702                 goto out;
703         }
704
705         sg_init_table(sg, num_pages);
706
707         /* cleanup a previous sg allocation */
708         /* this may happen if application doesn't signal for e/o DMA */
709         kfree(map_obj->dma_info.sg);
710
711         map_obj->dma_info.sg = sg;
712         map_obj->dma_info.dir = dir;
713         map_obj->dma_info.num_pages = num_pages;
714
715         ret = build_dma_sg(map_obj, start, len, pg_i);
716         if (ret)
717                 goto kfree_sg;
718
719         sg_num = dma_map_sg(bridge, sg, num_pages, dir);
720         if (sg_num < 1) {
721                 pr_err("%s: dma_map_sg failed: %d\n", __func__, sg_num);
722                 ret = -EFAULT;
723                 goto kfree_sg;
724         }
725
726         pr_debug("%s: dma_map_sg mapped %d elements\n", __func__, sg_num);
727         map_obj->dma_info.sg_num = sg_num;
728
729         return 0;
730
731 kfree_sg:
732         kfree(sg);
733         map_obj->dma_info.sg = NULL;
734 out:
735         return ret;
736 }
737
738 int proc_begin_dma(void *hprocessor, void *pmpu_addr, u32 ul_size,
739                                 enum dma_data_direction dir)
740 {
741         /* Keep STATUS here for future additions to this function */
742         int status = 0;
743         struct process_context *pr_ctxt = (struct process_context *) hprocessor;
744         struct dmm_map_object *map_obj;
745
746         if (!pr_ctxt) {
747                 status = -EFAULT;
748                 goto err_out;
749         }
750
751         pr_debug("%s: addr 0x%x, size 0x%x, type %d\n", __func__,
752                                                         (u32)pmpu_addr,
753                                                         ul_size, dir);
754
755         mutex_lock(&proc_lock);
756
757         /* find requested memory are in cached mapping information */
758         map_obj = find_containing_mapping(pr_ctxt, (u32) pmpu_addr, ul_size);
759         if (!map_obj) {
760                 pr_err("%s: find_containing_mapping failed\n", __func__);
761                 status = -EFAULT;
762                 goto no_map;
763         }
764
765         if (memory_give_ownership(map_obj, (u32) pmpu_addr, ul_size, dir)) {
766                 pr_err("%s: InValid address parameters %p %x\n",
767                                __func__, pmpu_addr, ul_size);
768                 status = -EFAULT;
769         }
770
771 no_map:
772         mutex_unlock(&proc_lock);
773 err_out:
774
775         return status;
776 }
777
778 int proc_end_dma(void *hprocessor, void *pmpu_addr, u32 ul_size,
779                         enum dma_data_direction dir)
780 {
781         /* Keep STATUS here for future additions to this function */
782         int status = 0;
783         struct process_context *pr_ctxt = (struct process_context *) hprocessor;
784         struct dmm_map_object *map_obj;
785
786         if (!pr_ctxt) {
787                 status = -EFAULT;
788                 goto err_out;
789         }
790
791         pr_debug("%s: addr 0x%x, size 0x%x, type %d\n", __func__,
792                                                         (u32)pmpu_addr,
793                                                         ul_size, dir);
794
795         mutex_lock(&proc_lock);
796
797         /* find requested memory are in cached mapping information */
798         map_obj = find_containing_mapping(pr_ctxt, (u32) pmpu_addr, ul_size);
799         if (!map_obj) {
800                 pr_err("%s: find_containing_mapping failed\n", __func__);
801                 status = -EFAULT;
802                 goto no_map;
803         }
804
805         if (memory_regain_ownership(map_obj, (u32) pmpu_addr, ul_size, dir)) {
806                 pr_err("%s: InValid address parameters %p %x\n",
807                        __func__, pmpu_addr, ul_size);
808                 status = -EFAULT;
809         }
810
811 no_map:
812         mutex_unlock(&proc_lock);
813 err_out:
814         return status;
815 }
816
817 /*
818  *  ======== proc_flush_memory ========
819  *  Purpose:
820  *     Flush cache
821  */
822 int proc_flush_memory(void *hprocessor, void *pmpu_addr,
823                              u32 ul_size, u32 ul_flags)
824 {
825         enum dma_data_direction dir = DMA_BIDIRECTIONAL;
826
827         return proc_begin_dma(hprocessor, pmpu_addr, ul_size, dir);
828 }
829
830 /*
831  *  ======== proc_invalidate_memory ========
832  *  Purpose:
833  *     Invalidates the memory specified
834  */
835 int proc_invalidate_memory(void *hprocessor, void *pmpu_addr, u32 size)
836 {
837         enum dma_data_direction dir = DMA_FROM_DEVICE;
838
839         return proc_begin_dma(hprocessor, pmpu_addr, size, dir);
840 }
841
842 /*
843  *  ======== proc_get_resource_info ========
844  *  Purpose:
845  *      Enumerate the resources currently available on a processor.
846  */
847 int proc_get_resource_info(void *hprocessor, u32 resource_type,
848                                   struct dsp_resourceinfo *resource_info,
849                                   u32 resource_info_size)
850 {
851         int status = -EPERM;
852         struct proc_object *p_proc_object = (struct proc_object *)hprocessor;
853         struct node_mgr *hnode_mgr = NULL;
854         struct nldr_object *nldr_obj = NULL;
855         struct rmm_target_obj *rmm = NULL;
856         struct io_mgr *hio_mgr = NULL;  /* IO manager handle */
857
858         if (!p_proc_object) {
859                 status = -EFAULT;
860                 goto func_end;
861         }
862         switch (resource_type) {
863         case DSP_RESOURCE_DYNDARAM:
864         case DSP_RESOURCE_DYNSARAM:
865         case DSP_RESOURCE_DYNEXTERNAL:
866         case DSP_RESOURCE_DYNSRAM:
867                 status = dev_get_node_manager(p_proc_object->dev_obj,
868                                               &hnode_mgr);
869                 if (!hnode_mgr) {
870                         status = -EFAULT;
871                         goto func_end;
872                 }
873
874                 status = node_get_nldr_obj(hnode_mgr, &nldr_obj);
875                 if (!status) {
876                         status = nldr_get_rmm_manager(nldr_obj, &rmm);
877                         if (rmm) {
878                                 if (!rmm_stat(rmm,
879                                               (enum dsp_memtype)resource_type,
880                                               (struct dsp_memstat *)
881                                               &(resource_info->result.
882                                                 mem_stat)))
883                                         status = -EINVAL;
884                         } else {
885                                 status = -EFAULT;
886                         }
887                 }
888                 break;
889         case DSP_RESOURCE_PROCLOAD:
890                 status = dev_get_io_mgr(p_proc_object->dev_obj, &hio_mgr);
891                 if (hio_mgr)
892                         status =
893                             p_proc_object->intf_fxns->
894                             io_get_proc_load(hio_mgr,
895                                                  (struct dsp_procloadstat *)
896                                                  &(resource_info->result.
897                                                    proc_load_stat));
898                 else
899                         status = -EFAULT;
900                 break;
901         default:
902                 status = -EPERM;
903                 break;
904         }
905 func_end:
906         return status;
907 }
908
909 /*
910  *  ======== proc_get_dev_object ========
911  *  Purpose:
912  *      Return the Dev Object handle for a given Processor.
913  *
914  */
915 int proc_get_dev_object(void *hprocessor,
916                                struct dev_object **device_obj)
917 {
918         int status = -EPERM;
919         struct proc_object *p_proc_object = (struct proc_object *)hprocessor;
920
921         if (p_proc_object) {
922                 *device_obj = p_proc_object->dev_obj;
923                 status = 0;
924         } else {
925                 *device_obj = NULL;
926                 status = -EFAULT;
927         }
928
929         return status;
930 }
931
932 /*
933  *  ======== proc_get_state ========
934  *  Purpose:
935  *      Report the state of the specified DSP processor.
936  */
937 int proc_get_state(void *hprocessor,
938                           struct dsp_processorstate *proc_state_obj,
939                           u32 state_info_size)
940 {
941         int status = 0;
942         struct proc_object *p_proc_object = (struct proc_object *)hprocessor;
943         int brd_status;
944
945         if (p_proc_object) {
946                 /* First, retrieve BRD state information */
947                 status = (*p_proc_object->intf_fxns->brd_status)
948                     (p_proc_object->bridge_context, &brd_status);
949                 if (!status) {
950                         switch (brd_status) {
951                         case BRD_STOPPED:
952                                 proc_state_obj->proc_state = PROC_STOPPED;
953                                 break;
954                         case BRD_SLEEP_TRANSITION:
955                         case BRD_DSP_HIBERNATION:
956                                 /* Fall through */
957                         case BRD_RUNNING:
958                                 proc_state_obj->proc_state = PROC_RUNNING;
959                                 break;
960                         case BRD_LOADED:
961                                 proc_state_obj->proc_state = PROC_LOADED;
962                                 break;
963                         case BRD_ERROR:
964                                 proc_state_obj->proc_state = PROC_ERROR;
965                                 break;
966                         default:
967                                 proc_state_obj->proc_state = 0xFF;
968                                 status = -EPERM;
969                                 break;
970                         }
971                 }
972         } else {
973                 status = -EFAULT;
974         }
975         dev_dbg(bridge, "%s, results: status: 0x%x proc_state_obj: 0x%x\n",
976                 __func__, status, proc_state_obj->proc_state);
977         return status;
978 }
979
980 /*
981  *  ======== proc_get_trace ========
982  *  Purpose:
983  *      Retrieve the current contents of the trace buffer, located on the
984  *      Processor.  Predefined symbols for the trace buffer must have been
985  *      configured into the DSP executable.
986  *  Details:
987  *      We support using the symbols SYS_PUTCBEG and SYS_PUTCEND to define a
988  *      trace buffer, only.  Treat it as an undocumented feature.
989  *      This call is destructive, meaning the processor is placed in the monitor
990  *      state as a result of this function.
991  */
992 int proc_get_trace(void *hprocessor, u8 * pbuf, u32 max_size)
993 {
994         int status;
995         status = -ENOSYS;
996         return status;
997 }
998
999 /*
1000  *  ======== proc_load ========
1001  *  Purpose:
1002  *      Reset a processor and load a new base program image.
1003  *      This will be an OEM-only function, and not part of the DSP/BIOS Bridge
1004  *      application developer's API.
1005  */
1006 int proc_load(void *hprocessor, const s32 argc_index,
1007                      const char **user_args, const char **user_envp)
1008 {
1009         int status = 0;
1010         struct proc_object *p_proc_object = (struct proc_object *)hprocessor;
1011         struct io_mgr *hio_mgr; /* IO manager handle */
1012         struct msg_mgr *hmsg_mgr;
1013         struct cod_manager *cod_mgr;    /* Code manager handle */
1014         char *pargv0;           /* temp argv[0] ptr */
1015         char **new_envp;        /* Updated envp[] array. */
1016         char sz_proc_id[MAXPROCIDLEN];  /* Size of "PROC_ID=<n>" */
1017         s32 envp_elems;         /* Num elements in envp[]. */
1018         s32 cnew_envp;          /* "  " in new_envp[] */
1019         s32 nproc_id = 0;       /* Anticipate MP version. */
1020         struct dcd_manager *hdcd_handle;
1021         struct dmm_object *dmm_mgr;
1022         u32 dw_ext_end;
1023         u32 proc_id;
1024         int brd_state;
1025         struct drv_data *drv_datap = dev_get_drvdata(bridge);
1026
1027 #ifdef OPT_LOAD_TIME_INSTRUMENTATION
1028         struct timeval tv1;
1029         struct timeval tv2;
1030 #endif
1031
1032 #if defined(CONFIG_TIDSPBRIDGE_DVFS) && !defined(CONFIG_CPU_FREQ)
1033         struct dspbridge_platform_data *pdata =
1034             omap_dspbridge_dev->dev.platform_data;
1035 #endif
1036
1037 #ifdef OPT_LOAD_TIME_INSTRUMENTATION
1038         do_gettimeofday(&tv1);
1039 #endif
1040         if (!p_proc_object) {
1041                 status = -EFAULT;
1042                 goto func_end;
1043         }
1044         dev_get_cod_mgr(p_proc_object->dev_obj, &cod_mgr);
1045         if (!cod_mgr) {
1046                 status = -EPERM;
1047                 goto func_end;
1048         }
1049         status = proc_stop(hprocessor);
1050         if (status)
1051                 goto func_end;
1052
1053         /* Place the board in the monitor state. */
1054         status = proc_monitor(hprocessor);
1055         if (status)
1056                 goto func_end;
1057
1058         /* Save ptr to  original argv[0]. */
1059         pargv0 = (char *)user_args[0];
1060         /*Prepend "PROC_ID=<nproc_id>"to envp array for target. */
1061         envp_elems = get_envp_count((char **)user_envp);
1062         cnew_envp = (envp_elems ? (envp_elems + 1) : (envp_elems + 2));
1063         new_envp = kzalloc(cnew_envp * sizeof(char **), GFP_KERNEL);
1064         if (new_envp) {
1065                 status = snprintf(sz_proc_id, MAXPROCIDLEN, PROC_ENVPROCID,
1066                                   nproc_id);
1067                 if (status == -1) {
1068                         dev_dbg(bridge, "%s: Proc ID string overflow\n",
1069                                 __func__);
1070                         status = -EPERM;
1071                 } else {
1072                         new_envp =
1073                             prepend_envp(new_envp, (char **)user_envp,
1074                                          envp_elems, cnew_envp, sz_proc_id);
1075                         /* Get the DCD Handle */
1076                         status = mgr_get_dcd_handle(p_proc_object->mgr_obj,
1077                                                     (u32 *) &hdcd_handle);
1078                         if (!status) {
1079                                 /*  Before proceeding with new load,
1080                                  *  check if a previously registered COFF
1081                                  *  exists.
1082                                  *  If yes, unregister nodes in previously
1083                                  *  registered COFF.  If any error occurred,
1084                                  *  set previously registered COFF to NULL. */
1085                                 if (p_proc_object->last_coff != NULL) {
1086                                         status =
1087                                             dcd_auto_unregister(hdcd_handle,
1088                                                                 p_proc_object->
1089                                                                 last_coff);
1090                                         /* Regardless of auto unregister status,
1091                                          *  free previously allocated
1092                                          *  memory. */
1093                                         kfree(p_proc_object->last_coff);
1094                                         p_proc_object->last_coff = NULL;
1095                                 }
1096                         }
1097                         /* On success, do cod_open_base() */
1098                         status = cod_open_base(cod_mgr, (char *)user_args[0],
1099                                                COD_SYMB);
1100                 }
1101         } else {
1102                 status = -ENOMEM;
1103         }
1104         if (!status) {
1105                 /* Auto-register data base */
1106                 /* Get the DCD Handle */
1107                 status = mgr_get_dcd_handle(p_proc_object->mgr_obj,
1108                                             (u32 *) &hdcd_handle);
1109                 if (!status) {
1110                         /*  Auto register nodes in specified COFF
1111                          *  file.  If registration did not fail,
1112                          *  (status = 0 or -EACCES)
1113                          *  save the name of the COFF file for
1114                          *  de-registration in the future. */
1115                         status =
1116                             dcd_auto_register(hdcd_handle,
1117                                               (char *)user_args[0]);
1118                         if (status == -EACCES)
1119                                 status = 0;
1120
1121                         if (status) {
1122                                 status = -EPERM;
1123                         } else {
1124                                 /* Allocate memory for pszLastCoff */
1125                                 p_proc_object->last_coff =
1126                                                 kzalloc((strlen(user_args[0]) +
1127                                                 1), GFP_KERNEL);
1128                                 /* If memory allocated, save COFF file name */
1129                                 if (p_proc_object->last_coff) {
1130                                         strncpy(p_proc_object->last_coff,
1131                                                 (char *)user_args[0],
1132                                                 (strlen((char *)user_args[0]) +
1133                                                  1));
1134                                 }
1135                         }
1136                 }
1137         }
1138         /* Update shared memory address and size */
1139         if (!status) {
1140                 /*  Create the message manager. This must be done
1141                  *  before calling the IOOnLoaded function. */
1142                 dev_get_msg_mgr(p_proc_object->dev_obj, &hmsg_mgr);
1143                 if (!hmsg_mgr) {
1144                         status = msg_create(&hmsg_mgr, p_proc_object->dev_obj,
1145                                             (msg_onexit) node_on_exit);
1146                         dev_set_msg_mgr(p_proc_object->dev_obj, hmsg_mgr);
1147                 }
1148         }
1149         if (!status) {
1150                 /* Set the Device object's message manager */
1151                 status = dev_get_io_mgr(p_proc_object->dev_obj, &hio_mgr);
1152                 if (hio_mgr)
1153                         status = (*p_proc_object->intf_fxns->io_on_loaded)
1154                                                                 (hio_mgr);
1155                 else
1156                         status = -EFAULT;
1157         }
1158         if (!status) {
1159                 /* Now, attempt to load an exec: */
1160
1161                 /* Boost the OPP level to Maximum level supported by baseport */
1162 #if defined(CONFIG_TIDSPBRIDGE_DVFS) && !defined(CONFIG_CPU_FREQ)
1163                 if (pdata->cpu_set_freq)
1164                         (*pdata->cpu_set_freq) (pdata->mpu_speed[VDD1_OPP5]);
1165 #endif
1166                 status = cod_load_base(cod_mgr, argc_index, (char **)user_args,
1167                                        dev_brd_write_fxn,
1168                                        p_proc_object->dev_obj, NULL);
1169                 if (status) {
1170                         if (status == -EBADF) {
1171                                 dev_dbg(bridge, "%s: Failure to Load the EXE\n",
1172                                         __func__);
1173                         }
1174                         if (status == -ESPIPE) {
1175                                 pr_err("%s: Couldn't parse the file\n",
1176                                        __func__);
1177                         }
1178                 }
1179                 /* Requesting the lowest opp supported */
1180 #if defined(CONFIG_TIDSPBRIDGE_DVFS) && !defined(CONFIG_CPU_FREQ)
1181                 if (pdata->cpu_set_freq)
1182                         (*pdata->cpu_set_freq) (pdata->mpu_speed[VDD1_OPP1]);
1183 #endif
1184
1185         }
1186         if (!status) {
1187                 /* Update the Processor status to loaded */
1188                 status = (*p_proc_object->intf_fxns->brd_set_state)
1189                     (p_proc_object->bridge_context, BRD_LOADED);
1190                 if (!status) {
1191                         p_proc_object->proc_state = PROC_LOADED;
1192                         if (p_proc_object->ntfy_obj)
1193                                 proc_notify_clients(p_proc_object,
1194                                                     DSP_PROCESSORSTATECHANGE);
1195                 }
1196         }
1197         if (!status) {
1198                 status = proc_get_processor_id(hprocessor, &proc_id);
1199                 if (proc_id == DSP_UNIT) {
1200                         /* Use all available DSP address space after EXTMEM
1201                          * for DMM */
1202                         if (!status)
1203                                 status = cod_get_sym_value(cod_mgr, EXTEND,
1204                                                            &dw_ext_end);
1205
1206                         /* Reset DMM structs and add an initial free chunk */
1207                         if (!status) {
1208                                 status =
1209                                     dev_get_dmm_mgr(p_proc_object->dev_obj,
1210                                                     &dmm_mgr);
1211                                 if (dmm_mgr) {
1212                                         /* Set dw_ext_end to DMM START u8
1213                                          * address */
1214                                         dw_ext_end =
1215                                             (dw_ext_end + 1) * DSPWORDSIZE;
1216                                         /* DMM memory is from EXT_END */
1217                                         status = dmm_create_tables(dmm_mgr,
1218                                                                    dw_ext_end,
1219                                                                    DMMPOOLSIZE);
1220                                 } else {
1221                                         status = -EFAULT;
1222                                 }
1223                         }
1224                 }
1225         }
1226         /* Restore the original argv[0] */
1227         kfree(new_envp);
1228         user_args[0] = pargv0;
1229         if (!status) {
1230                 if (!((*p_proc_object->intf_fxns->brd_status)
1231                                 (p_proc_object->bridge_context, &brd_state))) {
1232                         pr_info("%s: Processor Loaded %s\n", __func__, pargv0);
1233                         kfree(drv_datap->base_img);
1234                         drv_datap->base_img = kmalloc(strlen(pargv0) + 1,
1235                                                                 GFP_KERNEL);
1236                         if (drv_datap->base_img)
1237                                 strncpy(drv_datap->base_img, pargv0,
1238                                                         strlen(pargv0) + 1);
1239                         else
1240                                 status = -ENOMEM;
1241                 }
1242         }
1243
1244 func_end:
1245         if (status) {
1246                 pr_err("%s: Processor failed to load\n", __func__);
1247                 proc_stop(p_proc_object);
1248         }
1249 #ifdef OPT_LOAD_TIME_INSTRUMENTATION
1250         do_gettimeofday(&tv2);
1251         if (tv2.tv_usec < tv1.tv_usec) {
1252                 tv2.tv_usec += 1000000;
1253                 tv2.tv_sec--;
1254         }
1255         dev_dbg(bridge, "%s: time to load %d sec and %d usec\n", __func__,
1256                 tv2.tv_sec - tv1.tv_sec, tv2.tv_usec - tv1.tv_usec);
1257 #endif
1258         return status;
1259 }
1260
1261 /*
1262  *  ======== proc_map ========
1263  *  Purpose:
1264  *      Maps a MPU buffer to DSP address space.
1265  */
1266 int proc_map(void *hprocessor, void *pmpu_addr, u32 ul_size,
1267                     void *req_addr, void **pp_map_addr, u32 ul_map_attr,
1268                     struct process_context *pr_ctxt)
1269 {
1270         u32 va_align;
1271         u32 pa_align;
1272         struct dmm_object *dmm_mgr;
1273         u32 size_align;
1274         int status = 0;
1275         struct proc_object *p_proc_object = (struct proc_object *)hprocessor;
1276         struct dmm_map_object *map_obj;
1277         u32 tmp_addr = 0;
1278
1279 #ifdef CONFIG_TIDSPBRIDGE_CACHE_LINE_CHECK
1280         if ((ul_map_attr & BUFMODE_MASK) != RBUF) {
1281                 if (!IS_ALIGNED((u32)pmpu_addr, DSP_CACHE_LINE) ||
1282                     !IS_ALIGNED(ul_size, DSP_CACHE_LINE)) {
1283                         pr_err("%s: not aligned: 0x%x (%d)\n", __func__,
1284                                                 (u32)pmpu_addr, ul_size);
1285                         return -EFAULT;
1286                 }
1287         }
1288 #endif
1289
1290         /* Calculate the page-aligned PA, VA and size */
1291         va_align = PG_ALIGN_LOW((u32) req_addr, PG_SIZE4K);
1292         pa_align = PG_ALIGN_LOW((u32) pmpu_addr, PG_SIZE4K);
1293         size_align = PG_ALIGN_HIGH(ul_size + (u32) pmpu_addr - pa_align,
1294                                    PG_SIZE4K);
1295
1296         if (!p_proc_object) {
1297                 status = -EFAULT;
1298                 goto func_end;
1299         }
1300         /* Critical section */
1301         mutex_lock(&proc_lock);
1302         dmm_get_handle(p_proc_object, &dmm_mgr);
1303         if (dmm_mgr)
1304                 status = dmm_map_memory(dmm_mgr, va_align, size_align);
1305         else
1306                 status = -EFAULT;
1307
1308         /* Add mapping to the page tables. */
1309         if (!status) {
1310
1311                 /* Mapped address = MSB of VA | LSB of PA */
1312                 tmp_addr = (va_align | ((u32) pmpu_addr & (PG_SIZE4K - 1)));
1313                 /* mapped memory resource tracking */
1314                 map_obj = add_mapping_info(pr_ctxt, pa_align, tmp_addr,
1315                                                 size_align);
1316                 if (!map_obj)
1317                         status = -ENOMEM;
1318                 else
1319                         status = (*p_proc_object->intf_fxns->brd_mem_map)
1320                             (p_proc_object->bridge_context, pa_align, va_align,
1321                              size_align, ul_map_attr, map_obj->pages);
1322         }
1323         if (!status) {
1324                 /* Mapped address = MSB of VA | LSB of PA */
1325                 *pp_map_addr = (void *) tmp_addr;
1326         } else {
1327                 remove_mapping_information(pr_ctxt, tmp_addr, size_align);
1328                 dmm_un_map_memory(dmm_mgr, va_align, &size_align);
1329         }
1330         mutex_unlock(&proc_lock);
1331
1332         if (status)
1333                 goto func_end;
1334
1335 func_end:
1336         dev_dbg(bridge, "%s: hprocessor %p, pmpu_addr %p, ul_size %x, "
1337                 "req_addr %p, ul_map_attr %x, pp_map_addr %p, va_align %x, "
1338                 "pa_align %x, size_align %x status 0x%x\n", __func__,
1339                 hprocessor, pmpu_addr, ul_size, req_addr, ul_map_attr,
1340                 pp_map_addr, va_align, pa_align, size_align, status);
1341
1342         return status;
1343 }
1344
1345 /*
1346  *  ======== proc_register_notify ========
1347  *  Purpose:
1348  *      Register to be notified of specific processor events.
1349  */
1350 int proc_register_notify(void *hprocessor, u32 event_mask,
1351                                 u32 notify_type, struct dsp_notification
1352                                 * hnotification)
1353 {
1354         int status = 0;
1355         struct proc_object *p_proc_object = (struct proc_object *)hprocessor;
1356         struct deh_mgr *hdeh_mgr;
1357
1358         /* Check processor handle */
1359         if (!p_proc_object) {
1360                 status = -EFAULT;
1361                 goto func_end;
1362         }
1363         /* Check if event mask is a valid processor related event */
1364         if (event_mask & ~(DSP_PROCESSORSTATECHANGE | DSP_PROCESSORATTACH |
1365                         DSP_PROCESSORDETACH | DSP_PROCESSORRESTART |
1366                         DSP_MMUFAULT | DSP_SYSERROR | DSP_PWRERROR |
1367                         DSP_WDTOVERFLOW))
1368                 status = -EINVAL;
1369
1370         /* Check if notify type is valid */
1371         if (notify_type != DSP_SIGNALEVENT)
1372                 status = -EINVAL;
1373
1374         if (!status) {
1375                 /* If event mask is not DSP_SYSERROR, DSP_MMUFAULT,
1376                  * or DSP_PWRERROR then register event immediately. */
1377                 if (event_mask &
1378                     ~(DSP_SYSERROR | DSP_MMUFAULT | DSP_PWRERROR |
1379                                 DSP_WDTOVERFLOW)) {
1380                         status = ntfy_register(p_proc_object->ntfy_obj,
1381                                                hnotification, event_mask,
1382                                                notify_type);
1383                         /* Special case alert, special case alert!
1384                          * If we're trying to *deregister* (i.e. event_mask
1385                          * is 0), a DSP_SYSERROR or DSP_MMUFAULT notification,
1386                          * we have to deregister with the DEH manager.
1387                          * There's no way to know, based on event_mask which
1388                          * manager the notification event was registered with,
1389                          * so if we're trying to deregister and ntfy_register
1390                          * failed, we'll give the deh manager a shot.
1391                          */
1392                         if ((event_mask == 0) && status) {
1393                                 status =
1394                                     dev_get_deh_mgr(p_proc_object->dev_obj,
1395                                                     &hdeh_mgr);
1396                                 status =
1397                                         bridge_deh_register_notify(hdeh_mgr,
1398                                                         event_mask,
1399                                                         notify_type,
1400                                                         hnotification);
1401                         }
1402                 } else {
1403                         status = dev_get_deh_mgr(p_proc_object->dev_obj,
1404                                                  &hdeh_mgr);
1405                         status =
1406                             bridge_deh_register_notify(hdeh_mgr,
1407                                             event_mask,
1408                                             notify_type,
1409                                             hnotification);
1410
1411                 }
1412         }
1413 func_end:
1414         return status;
1415 }
1416
1417 /*
1418  *  ======== proc_reserve_memory ========
1419  *  Purpose:
1420  *      Reserve a virtually contiguous region of DSP address space.
1421  */
1422 int proc_reserve_memory(void *hprocessor, u32 ul_size,
1423                                void **pp_rsv_addr,
1424                                struct process_context *pr_ctxt)
1425 {
1426         struct dmm_object *dmm_mgr;
1427         int status = 0;
1428         struct proc_object *p_proc_object = (struct proc_object *)hprocessor;
1429         struct dmm_rsv_object *rsv_obj;
1430
1431         if (!p_proc_object) {
1432                 status = -EFAULT;
1433                 goto func_end;
1434         }
1435
1436         status = dmm_get_handle(p_proc_object, &dmm_mgr);
1437         if (!dmm_mgr) {
1438                 status = -EFAULT;
1439                 goto func_end;
1440         }
1441
1442         status = dmm_reserve_memory(dmm_mgr, ul_size, (u32 *) pp_rsv_addr);
1443         if (status != 0)
1444                 goto func_end;
1445
1446         /*
1447          * A successful reserve should be followed by insertion of rsv_obj
1448          * into dmm_rsv_list, so that reserved memory resource tracking
1449          * remains uptodate
1450          */
1451         rsv_obj = kmalloc(sizeof(struct dmm_rsv_object), GFP_KERNEL);
1452         if (rsv_obj) {
1453                 rsv_obj->dsp_reserved_addr = (u32) *pp_rsv_addr;
1454                 spin_lock(&pr_ctxt->dmm_rsv_lock);
1455                 list_add(&rsv_obj->link, &pr_ctxt->dmm_rsv_list);
1456                 spin_unlock(&pr_ctxt->dmm_rsv_lock);
1457         }
1458
1459 func_end:
1460         dev_dbg(bridge, "%s: hprocessor: 0x%p ul_size: 0x%x pp_rsv_addr: 0x%p "
1461                 "status 0x%x\n", __func__, hprocessor,
1462                 ul_size, pp_rsv_addr, status);
1463         return status;
1464 }
1465
1466 /*
1467  *  ======== proc_start ========
1468  *  Purpose:
1469  *      Start a processor running.
1470  */
1471 int proc_start(void *hprocessor)
1472 {
1473         int status = 0;
1474         struct proc_object *p_proc_object = (struct proc_object *)hprocessor;
1475         struct cod_manager *cod_mgr;    /* Code manager handle */
1476         u32 dw_dsp_addr;        /* Loaded code's entry point. */
1477         int brd_state;
1478
1479         if (!p_proc_object) {
1480                 status = -EFAULT;
1481                 goto func_end;
1482         }
1483         /* Call the bridge_brd_start */
1484         if (p_proc_object->proc_state != PROC_LOADED) {
1485                 status = -EBADR;
1486                 goto func_end;
1487         }
1488         status = dev_get_cod_mgr(p_proc_object->dev_obj, &cod_mgr);
1489         if (!cod_mgr) {
1490                 status = -EFAULT;
1491                 goto func_cont;
1492         }
1493
1494         status = cod_get_entry(cod_mgr, &dw_dsp_addr);
1495         if (status)
1496                 goto func_cont;
1497
1498         status = (*p_proc_object->intf_fxns->brd_start)
1499             (p_proc_object->bridge_context, dw_dsp_addr);
1500         if (status)
1501                 goto func_cont;
1502
1503         /* Call dev_create2 */
1504         status = dev_create2(p_proc_object->dev_obj);
1505         if (!status) {
1506                 p_proc_object->proc_state = PROC_RUNNING;
1507                 /* Deep sleep switces off the peripheral clocks.
1508                  * we just put the DSP CPU in idle in the idle loop.
1509                  * so there is no need to send a command to DSP */
1510
1511                 if (p_proc_object->ntfy_obj) {
1512                         proc_notify_clients(p_proc_object,
1513                                             DSP_PROCESSORSTATECHANGE);
1514                 }
1515         } else {
1516                 /* Failed to Create Node Manager and DISP Object
1517                  * Stop the Processor from running. Put it in STOPPED State */
1518                 (void)(*p_proc_object->intf_fxns->
1519                        brd_stop) (p_proc_object->bridge_context);
1520                 p_proc_object->proc_state = PROC_STOPPED;
1521         }
1522 func_cont:
1523         if (!status) {
1524                 if (!((*p_proc_object->intf_fxns->brd_status)
1525                                 (p_proc_object->bridge_context, &brd_state))) {
1526                         pr_info("%s: dsp in running state\n", __func__);
1527                 }
1528         } else {
1529                 pr_err("%s: Failed to start the dsp\n", __func__);
1530                 proc_stop(p_proc_object);
1531         }
1532
1533 func_end:
1534         return status;
1535 }
1536
1537 /*
1538  *  ======== proc_stop ========
1539  *  Purpose:
1540  *      Stop a processor running.
1541  */
1542 int proc_stop(void *hprocessor)
1543 {
1544         int status = 0;
1545         struct proc_object *p_proc_object = (struct proc_object *)hprocessor;
1546         struct msg_mgr *hmsg_mgr;
1547         struct node_mgr *hnode_mgr;
1548         void *hnode;
1549         u32 node_tab_size = 1;
1550         u32 num_nodes = 0;
1551         u32 nodes_allocated = 0;
1552
1553         if (!p_proc_object) {
1554                 status = -EFAULT;
1555                 goto func_end;
1556         }
1557         /* check if there are any running nodes */
1558         status = dev_get_node_manager(p_proc_object->dev_obj, &hnode_mgr);
1559         if (!status && hnode_mgr) {
1560                 status = node_enum_nodes(hnode_mgr, &hnode, node_tab_size,
1561                                          &num_nodes, &nodes_allocated);
1562                 if ((status == -EINVAL) || (nodes_allocated > 0)) {
1563                         pr_err("%s: Can't stop device, active nodes = %d \n",
1564                                __func__, nodes_allocated);
1565                         return -EBADR;
1566                 }
1567         }
1568         /* Call the bridge_brd_stop */
1569         /* It is OK to stop a device that does n't have nodes OR not started */
1570         status =
1571             (*p_proc_object->intf_fxns->
1572              brd_stop) (p_proc_object->bridge_context);
1573         if (!status) {
1574                 dev_dbg(bridge, "%s: processor in standby mode\n", __func__);
1575                 p_proc_object->proc_state = PROC_STOPPED;
1576                 /* Destroy the Node Manager, msg_ctrl Manager */
1577                 if (!(dev_destroy2(p_proc_object->dev_obj))) {
1578                         /* Destroy the msg_ctrl by calling msg_delete */
1579                         dev_get_msg_mgr(p_proc_object->dev_obj, &hmsg_mgr);
1580                         if (hmsg_mgr) {
1581                                 msg_delete(hmsg_mgr);
1582                                 dev_set_msg_mgr(p_proc_object->dev_obj, NULL);
1583                         }
1584                 }
1585         } else {
1586                 pr_err("%s: Failed to stop the processor\n", __func__);
1587         }
1588 func_end:
1589
1590         return status;
1591 }
1592
1593 /*
1594  *  ======== proc_un_map ========
1595  *  Purpose:
1596  *      Removes a MPU buffer mapping from the DSP address space.
1597  */
1598 int proc_un_map(void *hprocessor, void *map_addr,
1599                        struct process_context *pr_ctxt)
1600 {
1601         int status = 0;
1602         struct proc_object *p_proc_object = (struct proc_object *)hprocessor;
1603         struct dmm_object *dmm_mgr;
1604         u32 va_align;
1605         u32 size_align;
1606
1607         va_align = PG_ALIGN_LOW((u32) map_addr, PG_SIZE4K);
1608         if (!p_proc_object) {
1609                 status = -EFAULT;
1610                 goto func_end;
1611         }
1612
1613         status = dmm_get_handle(hprocessor, &dmm_mgr);
1614         if (!dmm_mgr) {
1615                 status = -EFAULT;
1616                 goto func_end;
1617         }
1618
1619         /* Critical section */
1620         mutex_lock(&proc_lock);
1621         /*
1622          * Update DMM structures. Get the size to unmap.
1623          * This function returns error if the VA is not mapped
1624          */
1625         status = dmm_un_map_memory(dmm_mgr, (u32) va_align, &size_align);
1626         /* Remove mapping from the page tables. */
1627         if (!status) {
1628                 status = (*p_proc_object->intf_fxns->brd_mem_un_map)
1629                     (p_proc_object->bridge_context, va_align, size_align);
1630         }
1631
1632         if (status)
1633                 goto unmap_failed;
1634
1635         /*
1636          * A successful unmap should be followed by removal of map_obj
1637          * from dmm_map_list, so that mapped memory resource tracking
1638          * remains uptodate
1639          */
1640         remove_mapping_information(pr_ctxt, (u32) map_addr, size_align);
1641
1642 unmap_failed:
1643         mutex_unlock(&proc_lock);
1644
1645 func_end:
1646         dev_dbg(bridge, "%s: hprocessor: 0x%p map_addr: 0x%p status: 0x%x\n",
1647                 __func__, hprocessor, map_addr, status);
1648         return status;
1649 }
1650
1651 /*
1652  *  ======== proc_un_reserve_memory ========
1653  *  Purpose:
1654  *      Frees a previously reserved region of DSP address space.
1655  */
1656 int proc_un_reserve_memory(void *hprocessor, void *prsv_addr,
1657                                   struct process_context *pr_ctxt)
1658 {
1659         struct dmm_object *dmm_mgr;
1660         int status = 0;
1661         struct proc_object *p_proc_object = (struct proc_object *)hprocessor;
1662         struct dmm_rsv_object *rsv_obj;
1663
1664         if (!p_proc_object) {
1665                 status = -EFAULT;
1666                 goto func_end;
1667         }
1668
1669         status = dmm_get_handle(p_proc_object, &dmm_mgr);
1670         if (!dmm_mgr) {
1671                 status = -EFAULT;
1672                 goto func_end;
1673         }
1674
1675         status = dmm_un_reserve_memory(dmm_mgr, (u32) prsv_addr);
1676         if (status != 0)
1677                 goto func_end;
1678
1679         /*
1680          * A successful unreserve should be followed by removal of rsv_obj
1681          * from dmm_rsv_list, so that reserved memory resource tracking
1682          * remains uptodate
1683          */
1684         spin_lock(&pr_ctxt->dmm_rsv_lock);
1685         list_for_each_entry(rsv_obj, &pr_ctxt->dmm_rsv_list, link) {
1686                 if (rsv_obj->dsp_reserved_addr == (u32) prsv_addr) {
1687                         list_del(&rsv_obj->link);
1688                         kfree(rsv_obj);
1689                         break;
1690                 }
1691         }
1692         spin_unlock(&pr_ctxt->dmm_rsv_lock);
1693
1694 func_end:
1695         dev_dbg(bridge, "%s: hprocessor: 0x%p prsv_addr: 0x%p status: 0x%x\n",
1696                 __func__, hprocessor, prsv_addr, status);
1697         return status;
1698 }
1699
1700 /*
1701  *  ======== = proc_monitor ======== ==
1702  *  Purpose:
1703  *      Place the Processor in Monitor State. This is an internal
1704  *      function and a requirement before Processor is loaded.
1705  *      This does a bridge_brd_stop, dev_destroy2 and bridge_brd_monitor.
1706  *      In dev_destroy2 we delete the node manager.
1707  *  Parameters:
1708  *      p_proc_object:    Pointer to Processor Object
1709  *  Returns:
1710  *      0:      Processor placed in monitor mode.
1711  *      !0:       Failed to place processor in monitor mode.
1712  *  Requires:
1713  *      Valid Processor Handle
1714  *  Ensures:
1715  *      Success:        ProcObject state is PROC_IDLE
1716  */
1717 static int proc_monitor(struct proc_object *proc_obj)
1718 {
1719         int status = -EPERM;
1720         struct msg_mgr *hmsg_mgr;
1721
1722         /* This is needed only when Device is loaded when it is
1723          * already 'ACTIVE' */
1724         /* Destroy the Node Manager, msg_ctrl Manager */
1725         if (!dev_destroy2(proc_obj->dev_obj)) {
1726                 /* Destroy the msg_ctrl by calling msg_delete */
1727                 dev_get_msg_mgr(proc_obj->dev_obj, &hmsg_mgr);
1728                 if (hmsg_mgr) {
1729                         msg_delete(hmsg_mgr);
1730                         dev_set_msg_mgr(proc_obj->dev_obj, NULL);
1731                 }
1732         }
1733         /* Place the Board in the Monitor State */
1734         if (!((*proc_obj->intf_fxns->brd_monitor)
1735                           (proc_obj->bridge_context))) {
1736                 status = 0;
1737         }
1738
1739         return status;
1740 }
1741
1742 /*
1743  *  ======== get_envp_count ========
1744  *  Purpose:
1745  *      Return the number of elements in the envp array, including the
1746  *      terminating NULL element.
1747  */
1748 static s32 get_envp_count(char **envp)
1749 {
1750         s32 ret = 0;
1751         if (envp) {
1752                 while (*envp++)
1753                         ret++;
1754
1755                 ret += 1;       /* Include the terminating NULL in the count. */
1756         }
1757
1758         return ret;
1759 }
1760
1761 /*
1762  *  ======== prepend_envp ========
1763  *  Purpose:
1764  *      Prepend an environment variable=value pair to the new envp array, and
1765  *      copy in the existing var=value pairs in the old envp array.
1766  */
1767 static char **prepend_envp(char **new_envp, char **envp, s32 envp_elems,
1768                            s32 cnew_envp, char *sz_var)
1769 {
1770         char **pp_envp = new_envp;
1771
1772         /* Prepend new environ var=value string */
1773         *new_envp++ = sz_var;
1774
1775         /* Copy user's environment into our own. */
1776         while (envp_elems--)
1777                 *new_envp++ = *envp++;
1778
1779         /* Ensure NULL terminates the new environment strings array. */
1780         if (envp_elems == 0)
1781                 *new_envp = NULL;
1782
1783         return pp_envp;
1784 }
1785
1786 /*
1787  *  ======== proc_notify_clients ========
1788  *  Purpose:
1789  *      Notify the processor the events.
1790  */
1791 int proc_notify_clients(void *proc, u32 events)
1792 {
1793         int status = 0;
1794         struct proc_object *p_proc_object = (struct proc_object *)proc;
1795
1796         if (!p_proc_object) {
1797                 status = -EFAULT;
1798                 goto func_end;
1799         }
1800
1801         ntfy_notify(p_proc_object->ntfy_obj, events);
1802 func_end:
1803         return status;
1804 }
1805
1806 /*
1807  *  ======== proc_notify_all_clients ========
1808  *  Purpose:
1809  *      Notify the processor the events. This includes notifying all clients
1810  *      attached to a particulat DSP.
1811  */
1812 int proc_notify_all_clients(void *proc, u32 events)
1813 {
1814         int status = 0;
1815         struct proc_object *p_proc_object = (struct proc_object *)proc;
1816
1817         if (!p_proc_object) {
1818                 status = -EFAULT;
1819                 goto func_end;
1820         }
1821
1822         dev_notify_clients(p_proc_object->dev_obj, events);
1823
1824 func_end:
1825         return status;
1826 }
1827
1828 /*
1829  *  ======== proc_get_processor_id ========
1830  *  Purpose:
1831  *      Retrieves the processor ID.
1832  */
1833 int proc_get_processor_id(void *proc, u32 * proc_id)
1834 {
1835         int status = 0;
1836         struct proc_object *p_proc_object = (struct proc_object *)proc;
1837
1838         if (p_proc_object)
1839                 *proc_id = p_proc_object->processor_id;
1840         else
1841                 status = -EFAULT;
1842
1843         return status;
1844 }