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