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