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