]> Pileus Git - ~andy/linux/blob - drivers/staging/tidspbridge/rmgr/drv.c
staging: ti dspbridge: make variables in prototypes match within functions definitions
[~andy/linux] / drivers / staging / tidspbridge / rmgr / drv.c
1 /*
2  * drv.c
3  *
4  * DSP-BIOS Bridge driver support functions for TI OMAP processors.
5  *
6  * DSP/BIOS Bridge resource allocation module.
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 /*  ----------------------------------- Host OS */
20 #include <dspbridge/host_os.h>
21
22 /*  ----------------------------------- DSP/BIOS Bridge */
23 #include <dspbridge/std.h>
24 #include <dspbridge/dbdefs.h>
25
26 /*  ----------------------------------- Trace & Debug */
27 #include <dspbridge/dbc.h>
28
29 /*  ----------------------------------- OS Adaptation Layer */
30 #include <dspbridge/cfg.h>
31 #include <dspbridge/list.h>
32
33 /*  ----------------------------------- This */
34 #include <dspbridge/drv.h>
35 #include <dspbridge/dev.h>
36
37 #include <dspbridge/node.h>
38 #include <dspbridge/proc.h>
39 #include <dspbridge/strm.h>
40 #include <dspbridge/nodepriv.h>
41 #include <dspbridge/dspchnl.h>
42 #include <dspbridge/resourcecleanup.h>
43
44 /*  ----------------------------------- Defines, Data Structures, Typedefs */
45 struct drv_object {
46         struct lst_list *dev_list;
47         struct lst_list *dev_node_string;
48 };
49
50 /*
51  *  This is the Device Extension. Named with the Prefix
52  *  DRV_ since it is living in this module
53  */
54 struct drv_ext {
55         struct list_head link;
56         char sz_string[MAXREGPATHLENGTH];
57 };
58
59 /*  ----------------------------------- Globals */
60 static s32 refs;
61 static bool ext_phys_mem_pool_enabled;
62 struct ext_phys_mem_pool {
63         u32 phys_mem_base;
64         u32 phys_mem_size;
65         u32 virt_mem_base;
66         u32 next_phys_alloc_ptr;
67 };
68 static struct ext_phys_mem_pool ext_mem_pool;
69
70 /*  ----------------------------------- Function Prototypes */
71 static int request_bridge_resources(struct cfg_hostres *res);
72
73
74 /* GPP PROCESS CLEANUP CODE */
75
76 static int drv_proc_free_node_res(void *process_ctxt);
77
78 /* Allocate and add a node resource element
79 * This function is called from .Node_Allocate. */
80 int drv_insert_node_res_element(void *hnode, void *node_resource,
81                                        void *process_ctxt)
82 {
83         struct node_res_object **node_res_obj =
84             (struct node_res_object **)node_resource;
85         struct process_context *ctxt = (struct process_context *)process_ctxt;
86         int status = 0;
87         struct node_res_object *temp_node_res = NULL;
88
89         *node_res_obj = kzalloc(sizeof(struct node_res_object), GFP_KERNEL);
90         if (*node_res_obj == NULL)
91                 status = -EFAULT;
92
93         if (DSP_SUCCEEDED(status)) {
94                 if (mutex_lock_interruptible(&ctxt->node_mutex)) {
95                         kfree(*node_res_obj);
96                         return -EPERM;
97                 }
98                 (*node_res_obj)->hnode = hnode;
99                 if (ctxt->node_list != NULL) {
100                         temp_node_res = ctxt->node_list;
101                         while (temp_node_res->next != NULL)
102                                 temp_node_res = temp_node_res->next;
103
104                         temp_node_res->next = *node_res_obj;
105                 } else {
106                         ctxt->node_list = *node_res_obj;
107                 }
108                 mutex_unlock(&ctxt->node_mutex);
109         }
110
111         return status;
112 }
113
114 /* Release all Node resources and its context
115 * This is called from .Node_Delete. */
116 int drv_remove_node_res_element(void *node_resource, void *process_ctxt)
117 {
118         struct node_res_object *node_res_obj =
119             (struct node_res_object *)node_resource;
120         struct process_context *ctxt = (struct process_context *)process_ctxt;
121         struct node_res_object *temp_node;
122         int status = 0;
123
124         if (mutex_lock_interruptible(&ctxt->node_mutex))
125                 return -EPERM;
126         temp_node = ctxt->node_list;
127         if (temp_node == node_res_obj) {
128                 ctxt->node_list = node_res_obj->next;
129         } else {
130                 while (temp_node && temp_node->next != node_res_obj)
131                         temp_node = temp_node->next;
132                 if (!temp_node)
133                         status = -ENOENT;
134                 else
135                         temp_node->next = node_res_obj->next;
136         }
137         mutex_unlock(&ctxt->node_mutex);
138         kfree(node_res_obj);
139         return status;
140 }
141
142 /* Actual Node De-Allocation */
143 static int drv_proc_free_node_res(void *process_ctxt)
144 {
145         struct process_context *ctxt = (struct process_context *)process_ctxt;
146         int status = 0;
147         struct node_res_object *node_list = NULL;
148         struct node_res_object *node_res_obj = NULL;
149         u32 node_state;
150
151         node_list = ctxt->node_list;
152         while (node_list != NULL) {
153                 node_res_obj = node_list;
154                 node_list = node_list->next;
155                 if (node_res_obj->node_allocated) {
156                         node_state = node_get_state(node_res_obj->hnode);
157                         if (node_state <= NODE_DELETING) {
158                                 if ((node_state == NODE_RUNNING) ||
159                                     (node_state == NODE_PAUSED) ||
160                                     (node_state == NODE_TERMINATING))
161                                         status = node_terminate
162                                             (node_res_obj->hnode, &status);
163
164                                 status = node_delete(node_res_obj->hnode, ctxt);
165                         }
166                 }
167         }
168         return status;
169 }
170
171 /* Release all Mapped and Reserved DMM resources */
172 int drv_remove_all_dmm_res_elements(void *process_ctxt)
173 {
174         struct process_context *ctxt = (struct process_context *)process_ctxt;
175         int status = 0;
176         struct dmm_map_object *temp_map, *map_obj;
177         struct dmm_rsv_object *temp_rsv, *rsv_obj;
178
179         /* Free DMM mapped memory resources */
180         list_for_each_entry_safe(map_obj, temp_map, &ctxt->dmm_map_list, link) {
181                 status = proc_un_map(ctxt->hprocessor,
182                                      (void *)map_obj->dsp_addr, ctxt);
183                 if (DSP_FAILED(status))
184                         pr_err("%s: proc_un_map failed!"
185                                " status = 0x%xn", __func__, status);
186         }
187
188         /* Free DMM reserved memory resources */
189         list_for_each_entry_safe(rsv_obj, temp_rsv, &ctxt->dmm_rsv_list, link) {
190                 status = proc_un_reserve_memory(ctxt->hprocessor, (void *)
191                                                 rsv_obj->dsp_reserved_addr,
192                                                 ctxt);
193                 if (DSP_FAILED(status))
194                         pr_err("%s: proc_un_reserve_memory failed!"
195                                " status = 0x%xn", __func__, status);
196         }
197         return status;
198 }
199
200 /* Update Node allocation status */
201 void drv_proc_node_update_status(void *node_resource, s32 status)
202 {
203         struct node_res_object *node_res_obj =
204             (struct node_res_object *)node_resource;
205         DBC_ASSERT(node_resource != NULL);
206         node_res_obj->node_allocated = status;
207 }
208
209 /* Update Node Heap status */
210 void drv_proc_node_update_heap_status(void *node_resource, s32 status)
211 {
212         struct node_res_object *node_res_obj =
213             (struct node_res_object *)node_resource;
214         DBC_ASSERT(node_resource != NULL);
215         node_res_obj->heap_allocated = status;
216 }
217
218 /* Release all Node resources and its context
219 * This is called from .bridge_release.
220  */
221 int drv_remove_all_node_res_elements(void *process_ctxt)
222 {
223         struct process_context *ctxt = (struct process_context *)process_ctxt;
224         int status = 0;
225         struct node_res_object *temp_node2 = NULL;
226         struct node_res_object *temp_node = NULL;
227
228         drv_proc_free_node_res(ctxt);
229         temp_node = ctxt->node_list;
230         while (temp_node != NULL) {
231                 temp_node2 = temp_node;
232                 temp_node = temp_node->next;
233                 kfree(temp_node2);
234         }
235         ctxt->node_list = NULL;
236         return status;
237 }
238
239 /* Getting the node resource element */
240 int drv_get_node_res_element(void *hnode, void *node_resource,
241                                     void *process_ctxt)
242 {
243         struct node_res_object **node_res =
244                                      (struct node_res_object **)node_resource;
245         struct process_context *ctxt = (struct process_context *)process_ctxt;
246         int status = 0;
247         struct node_res_object *temp_node2 = NULL;
248         struct node_res_object *temp_node = NULL;
249
250         if (mutex_lock_interruptible(&ctxt->node_mutex))
251                 return -EPERM;
252
253         temp_node = ctxt->node_list;
254         while ((temp_node != NULL) && (temp_node->hnode != hnode)) {
255                 temp_node2 = temp_node;
256                 temp_node = temp_node->next;
257         }
258
259         mutex_unlock(&ctxt->node_mutex);
260
261         if (temp_node != NULL)
262                 *node_res = temp_node;
263         else
264                 status = -ENOENT;
265
266         return status;
267 }
268
269 /* Allocate the STRM resource element
270 * This is called after the actual resource is allocated
271  */
272 int drv_proc_insert_strm_res_element(void *stream_obj,
273                                             void *strm_res, void *process_ctxt)
274 {
275         struct strm_res_object **pstrm_res =
276             (struct strm_res_object **)strm_res;
277         struct process_context *ctxt = (struct process_context *)process_ctxt;
278         int status = 0;
279         struct strm_res_object *temp_strm_res = NULL;
280
281         *pstrm_res = kzalloc(sizeof(struct strm_res_object), GFP_KERNEL);
282         if (*pstrm_res == NULL)
283                 status = -EFAULT;
284
285         if (DSP_SUCCEEDED(status)) {
286                 if (mutex_lock_interruptible(&ctxt->strm_mutex)) {
287                         kfree(*pstrm_res);
288                         return -EPERM;
289                 }
290                 (*pstrm_res)->hstream = stream_obj;
291                 if (ctxt->pstrm_list != NULL) {
292                         temp_strm_res = ctxt->pstrm_list;
293                         while (temp_strm_res->next != NULL)
294                                 temp_strm_res = temp_strm_res->next;
295
296                         temp_strm_res->next = *pstrm_res;
297                 } else {
298                         ctxt->pstrm_list = *pstrm_res;
299                 }
300                 mutex_unlock(&ctxt->strm_mutex);
301         }
302         return status;
303 }
304
305 /* Release Stream resource element context
306 * This function called after the actual resource is freed
307  */
308 int drv_proc_remove_strm_res_element(void *strm_res, void *process_ctxt)
309 {
310         struct strm_res_object *pstrm_res = (struct strm_res_object *)strm_res;
311         struct process_context *ctxt = (struct process_context *)process_ctxt;
312         struct strm_res_object *temp_strm_res;
313         int status = 0;
314
315         if (mutex_lock_interruptible(&ctxt->strm_mutex))
316                 return -EPERM;
317         temp_strm_res = ctxt->pstrm_list;
318
319         if (ctxt->pstrm_list == pstrm_res) {
320                 ctxt->pstrm_list = pstrm_res->next;
321         } else {
322                 while (temp_strm_res && temp_strm_res->next != pstrm_res)
323                         temp_strm_res = temp_strm_res->next;
324                 if (temp_strm_res == NULL)
325                         status = -ENOENT;
326                 else
327                         temp_strm_res->next = pstrm_res->next;
328         }
329         mutex_unlock(&ctxt->strm_mutex);
330         kfree(pstrm_res);
331         return status;
332 }
333
334 /* Release all Stream resources and its context
335 * This is called from .bridge_release.
336  */
337 int drv_remove_all_strm_res_elements(void *process_ctxt)
338 {
339         struct process_context *ctxt = (struct process_context *)process_ctxt;
340         int status = 0;
341         struct strm_res_object *strm_res = NULL;
342         struct strm_res_object *strm_tmp = NULL;
343         struct stream_info strm_info;
344         struct dsp_streaminfo user;
345         u8 **ap_buffer = NULL;
346         u8 *buf_ptr;
347         u32 ul_bytes;
348         u32 dw_arg;
349         s32 ul_buf_size;
350
351         strm_tmp = ctxt->pstrm_list;
352         while (strm_tmp) {
353                 strm_res = strm_tmp;
354                 strm_tmp = strm_tmp->next;
355                 if (strm_res->num_bufs) {
356                         ap_buffer = kmalloc((strm_res->num_bufs *
357                                         sizeof(u8 *)), GFP_KERNEL);
358                         if (ap_buffer) {
359                                 status = strm_free_buffer(strm_res->hstream,
360                                                           ap_buffer,
361                                                           strm_res->num_bufs,
362                                                           ctxt);
363                                 kfree(ap_buffer);
364                         }
365                 }
366                 strm_info.user_strm = &user;
367                 user.number_bufs_in_stream = 0;
368                 strm_get_info(strm_res->hstream, &strm_info, sizeof(strm_info));
369                 while (user.number_bufs_in_stream--)
370                         strm_reclaim(strm_res->hstream, &buf_ptr, &ul_bytes,
371                                      (u32 *) &ul_buf_size, &dw_arg);
372                 status = strm_close(strm_res->hstream, ctxt);
373         }
374         return status;
375 }
376
377 /* Getting the stream resource element */
378 int drv_get_strm_res_element(void *stream_obj, void *strm_resources,
379                                     void *process_ctxt)
380 {
381         struct strm_res_object **strm_res =
382             (struct strm_res_object **)strm_resources;
383         struct process_context *ctxt = (struct process_context *)process_ctxt;
384         int status = 0;
385         struct strm_res_object *temp_strm2 = NULL;
386         struct strm_res_object *temp_strm;
387
388         if (mutex_lock_interruptible(&ctxt->strm_mutex))
389                 return -EPERM;
390
391         temp_strm = ctxt->pstrm_list;
392         while ((temp_strm != NULL) && (temp_strm->hstream != stream_obj)) {
393                 temp_strm2 = temp_strm;
394                 temp_strm = temp_strm->next;
395         }
396
397         mutex_unlock(&ctxt->strm_mutex);
398
399         if (temp_strm != NULL)
400                 *strm_res = temp_strm;
401         else
402                 status = -ENOENT;
403
404         return status;
405 }
406
407 /* Updating the stream resource element */
408 int drv_proc_update_strm_res(u32 num_bufs, void *strm_resources)
409 {
410         int status = 0;
411         struct strm_res_object **strm_res =
412             (struct strm_res_object **)strm_resources;
413
414         (*strm_res)->num_bufs = num_bufs;
415         return status;
416 }
417
418 /* GPP PROCESS CLEANUP CODE END */
419
420 /*
421  *  ======== = drv_create ======== =
422  *  Purpose:
423  *      DRV Object gets created only once during Driver Loading.
424  */
425 int drv_create(OUT struct drv_object **drv_obj)
426 {
427         int status = 0;
428         struct drv_object *pdrv_object = NULL;
429
430         DBC_REQUIRE(drv_obj != NULL);
431         DBC_REQUIRE(refs > 0);
432
433         pdrv_object = kzalloc(sizeof(struct drv_object), GFP_KERNEL);
434         if (pdrv_object) {
435                 /* Create and Initialize List of device objects */
436                 pdrv_object->dev_list = kzalloc(sizeof(struct lst_list),
437                                                         GFP_KERNEL);
438                 if (pdrv_object->dev_list) {
439                         /* Create and Initialize List of device Extension */
440                         pdrv_object->dev_node_string =
441                                 kzalloc(sizeof(struct lst_list), GFP_KERNEL);
442                         if (!(pdrv_object->dev_node_string)) {
443                                 status = -EPERM;
444                         } else {
445                                 INIT_LIST_HEAD(&pdrv_object->
446                                                dev_node_string->head);
447                                 INIT_LIST_HEAD(&pdrv_object->dev_list->head);
448                         }
449                 } else {
450                         status = -ENOMEM;
451                 }
452         } else {
453                 status = -ENOMEM;
454         }
455         /* Store the DRV Object in the Registry */
456         if (DSP_SUCCEEDED(status))
457                 status = cfg_set_object((u32) pdrv_object, REG_DRV_OBJECT);
458         if (DSP_SUCCEEDED(status)) {
459                 *drv_obj = pdrv_object;
460         } else {
461                 kfree(pdrv_object->dev_list);
462                 kfree(pdrv_object->dev_node_string);
463                 /* Free the DRV Object */
464                 kfree(pdrv_object);
465         }
466
467         DBC_ENSURE(DSP_FAILED(status) || pdrv_object);
468         return status;
469 }
470
471 /*
472  *  ======== drv_exit ========
473  *  Purpose:
474  *      Discontinue usage of the DRV module.
475  */
476 void drv_exit(void)
477 {
478         DBC_REQUIRE(refs > 0);
479
480         refs--;
481
482         DBC_ENSURE(refs >= 0);
483 }
484
485 /*
486  *  ======== = drv_destroy ======== =
487  *  purpose:
488  *      Invoked during bridge de-initialization
489  */
490 int drv_destroy(struct drv_object *driver_obj)
491 {
492         int status = 0;
493         struct drv_object *pdrv_object = (struct drv_object *)driver_obj;
494
495         DBC_REQUIRE(refs > 0);
496         DBC_REQUIRE(pdrv_object);
497
498         /*
499          *  Delete the List if it exists.Should not come here
500          *  as the drv_remove_dev_object and the Last drv_request_resources
501          *  removes the list if the lists are empty.
502          */
503         kfree(pdrv_object->dev_list);
504         kfree(pdrv_object->dev_node_string);
505         kfree(pdrv_object);
506         /* Update the DRV Object in Registry to be 0 */
507         (void)cfg_set_object(0, REG_DRV_OBJECT);
508
509         return status;
510 }
511
512 /*
513  *  ======== drv_get_dev_object ========
514  *  Purpose:
515  *      Given a index, returns a handle to DevObject from the list.
516  */
517 int drv_get_dev_object(u32 index, struct drv_object *hdrv_obj,
518                               struct dev_object **device_obj)
519 {
520         int status = 0;
521 #ifdef CONFIG_TIDSPBRIDGE_DEBUG
522         /* used only for Assertions and debug messages */
523         struct drv_object *pdrv_obj = (struct drv_object *)hdrv_obj;
524 #endif
525         struct dev_object *dev_obj;
526         u32 i;
527         DBC_REQUIRE(pdrv_obj);
528         DBC_REQUIRE(device_obj != NULL);
529         DBC_REQUIRE(index >= 0);
530         DBC_REQUIRE(refs > 0);
531         DBC_ASSERT(!(LST_IS_EMPTY(pdrv_obj->dev_list)));
532
533         dev_obj = (struct dev_object *)drv_get_first_dev_object();
534         for (i = 0; i < index; i++) {
535                 dev_obj =
536                     (struct dev_object *)drv_get_next_dev_object((u32) dev_obj);
537         }
538         if (dev_obj) {
539                 *device_obj = (struct dev_object *)dev_obj;
540         } else {
541                 *device_obj = NULL;
542                 status = -EPERM;
543         }
544
545         return status;
546 }
547
548 /*
549  *  ======== drv_get_first_dev_object ========
550  *  Purpose:
551  *      Retrieve the first Device Object handle from an internal linked list of
552  *      of DEV_OBJECTs maintained by DRV.
553  */
554 u32 drv_get_first_dev_object(void)
555 {
556         u32 dw_dev_object = 0;
557         struct drv_object *pdrv_obj;
558
559         if (DSP_SUCCEEDED(cfg_get_object((u32 *) &pdrv_obj, REG_DRV_OBJECT))) {
560                 if ((pdrv_obj->dev_list != NULL) &&
561                     !LST_IS_EMPTY(pdrv_obj->dev_list))
562                         dw_dev_object = (u32) lst_first(pdrv_obj->dev_list);
563         }
564
565         return dw_dev_object;
566 }
567
568 /*
569  *  ======== DRV_GetFirstDevNodeString ========
570  *  Purpose:
571  *      Retrieve the first Device Extension from an internal linked list of
572  *      of Pointer to dev_node Strings maintained by DRV.
573  */
574 u32 drv_get_first_dev_extension(void)
575 {
576         u32 dw_dev_extension = 0;
577         struct drv_object *pdrv_obj;
578
579         if (DSP_SUCCEEDED(cfg_get_object((u32 *) &pdrv_obj, REG_DRV_OBJECT))) {
580
581                 if ((pdrv_obj->dev_node_string != NULL) &&
582                     !LST_IS_EMPTY(pdrv_obj->dev_node_string)) {
583                         dw_dev_extension =
584                             (u32) lst_first(pdrv_obj->dev_node_string);
585                 }
586         }
587
588         return dw_dev_extension;
589 }
590
591 /*
592  *  ======== drv_get_next_dev_object ========
593  *  Purpose:
594  *      Retrieve the next Device Object handle from an internal linked list of
595  *      of DEV_OBJECTs maintained by DRV, after having previously called
596  *      drv_get_first_dev_object() and zero or more DRV_GetNext.
597  */
598 u32 drv_get_next_dev_object(u32 hdev_obj)
599 {
600         u32 dw_next_dev_object = 0;
601         struct drv_object *pdrv_obj;
602
603         DBC_REQUIRE(hdev_obj != 0);
604
605         if (DSP_SUCCEEDED(cfg_get_object((u32 *) &pdrv_obj, REG_DRV_OBJECT))) {
606
607                 if ((pdrv_obj->dev_list != NULL) &&
608                     !LST_IS_EMPTY(pdrv_obj->dev_list)) {
609                         dw_next_dev_object = (u32) lst_next(pdrv_obj->dev_list,
610                                                             (struct list_head *)
611                                                             hdev_obj);
612                 }
613         }
614         return dw_next_dev_object;
615 }
616
617 /*
618  *  ======== drv_get_next_dev_extension ========
619  *  Purpose:
620  *      Retrieve the next Device Extension from an internal linked list of
621  *      of pointer to DevNodeString maintained by DRV, after having previously
622  *      called drv_get_first_dev_extension() and zero or more
623  *      drv_get_next_dev_extension().
624  */
625 u32 drv_get_next_dev_extension(u32 dev_extension)
626 {
627         u32 dw_dev_extension = 0;
628         struct drv_object *pdrv_obj;
629
630         DBC_REQUIRE(dev_extension != 0);
631
632         if (DSP_SUCCEEDED(cfg_get_object((u32 *) &pdrv_obj, REG_DRV_OBJECT))) {
633                 if ((pdrv_obj->dev_node_string != NULL) &&
634                     !LST_IS_EMPTY(pdrv_obj->dev_node_string)) {
635                         dw_dev_extension =
636                             (u32) lst_next(pdrv_obj->dev_node_string,
637                                            (struct list_head *)dev_extension);
638                 }
639         }
640
641         return dw_dev_extension;
642 }
643
644 /*
645  *  ======== drv_init ========
646  *  Purpose:
647  *      Initialize DRV module private state.
648  */
649 int drv_init(void)
650 {
651         s32 ret = 1;            /* function return value */
652
653         DBC_REQUIRE(refs >= 0);
654
655         if (ret)
656                 refs++;
657
658         DBC_ENSURE((ret && (refs > 0)) || (!ret && (refs >= 0)));
659
660         return ret;
661 }
662
663 /*
664  *  ======== drv_insert_dev_object ========
665  *  Purpose:
666  *      Insert a DevObject into the list of Manager object.
667  */
668 int drv_insert_dev_object(struct drv_object *driver_obj,
669                                  struct dev_object *hdev_obj)
670 {
671         int status = 0;
672         struct drv_object *pdrv_object = (struct drv_object *)driver_obj;
673
674         DBC_REQUIRE(refs > 0);
675         DBC_REQUIRE(hdev_obj != NULL);
676         DBC_REQUIRE(pdrv_object);
677         DBC_ASSERT(pdrv_object->dev_list);
678
679         lst_put_tail(pdrv_object->dev_list, (struct list_head *)hdev_obj);
680
681         DBC_ENSURE(DSP_SUCCEEDED(status)
682                    && !LST_IS_EMPTY(pdrv_object->dev_list));
683
684         return status;
685 }
686
687 /*
688  *  ======== drv_remove_dev_object ========
689  *  Purpose:
690  *      Search for and remove a DeviceObject from the given list of DRV
691  *      objects.
692  */
693 int drv_remove_dev_object(struct drv_object *driver_obj,
694                                  struct dev_object *hdev_obj)
695 {
696         int status = -EPERM;
697         struct drv_object *pdrv_object = (struct drv_object *)driver_obj;
698         struct list_head *cur_elem;
699
700         DBC_REQUIRE(refs > 0);
701         DBC_REQUIRE(pdrv_object);
702         DBC_REQUIRE(hdev_obj != NULL);
703
704         DBC_REQUIRE(pdrv_object->dev_list != NULL);
705         DBC_REQUIRE(!LST_IS_EMPTY(pdrv_object->dev_list));
706
707         /* Search list for p_proc_object: */
708         for (cur_elem = lst_first(pdrv_object->dev_list); cur_elem != NULL;
709              cur_elem = lst_next(pdrv_object->dev_list, cur_elem)) {
710                 /* If found, remove it. */
711                 if ((struct dev_object *)cur_elem == hdev_obj) {
712                         lst_remove_elem(pdrv_object->dev_list, cur_elem);
713                         status = 0;
714                         break;
715                 }
716         }
717         /* Remove list if empty. */
718         if (LST_IS_EMPTY(pdrv_object->dev_list)) {
719                 kfree(pdrv_object->dev_list);
720                 pdrv_object->dev_list = NULL;
721         }
722         DBC_ENSURE((pdrv_object->dev_list == NULL) ||
723                    !LST_IS_EMPTY(pdrv_object->dev_list));
724
725         return status;
726 }
727
728 /*
729  *  ======== drv_request_resources ========
730  *  Purpose:
731  *      Requests  resources from the OS.
732  */
733 int drv_request_resources(u32 dw_context, u32 *dev_node_strg)
734 {
735         int status = 0;
736         struct drv_object *pdrv_object;
737         struct drv_ext *pszdev_node;
738
739         DBC_REQUIRE(dw_context != 0);
740         DBC_REQUIRE(dev_node_strg != NULL);
741
742         /*
743          *  Allocate memory to hold the string. This will live untill
744          *  it is freed in the Release resources. Update the driver object
745          *  list.
746          */
747
748         status = cfg_get_object((u32 *) &pdrv_object, REG_DRV_OBJECT);
749         if (DSP_SUCCEEDED(status)) {
750                 pszdev_node = kzalloc(sizeof(struct drv_ext), GFP_KERNEL);
751                 if (pszdev_node) {
752                         lst_init_elem(&pszdev_node->link);
753                         strncpy(pszdev_node->sz_string,
754                                 (char *)dw_context, MAXREGPATHLENGTH - 1);
755                         pszdev_node->sz_string[MAXREGPATHLENGTH - 1] = '\0';
756                         /* Update the Driver Object List */
757                         *dev_node_strg = (u32) pszdev_node->sz_string;
758                         lst_put_tail(pdrv_object->dev_node_string,
759                                      (struct list_head *)pszdev_node);
760                 } else {
761                         status = -ENOMEM;
762                         *dev_node_strg = 0;
763                 }
764         } else {
765                 dev_dbg(bridge, "%s: Failed to get Driver Object from Registry",
766                         __func__);
767                 *dev_node_strg = 0;
768         }
769
770         DBC_ENSURE((DSP_SUCCEEDED(status) && dev_node_strg != NULL &&
771                     !LST_IS_EMPTY(pdrv_object->dev_node_string)) ||
772                    (DSP_FAILED(status) && *dev_node_strg == 0));
773
774         return status;
775 }
776
777 /*
778  *  ======== drv_release_resources ========
779  *  Purpose:
780  *      Releases  resources from the OS.
781  */
782 int drv_release_resources(u32 dw_context, struct drv_object *hdrv_obj)
783 {
784         int status = 0;
785         struct drv_object *pdrv_object = (struct drv_object *)hdrv_obj;
786         struct drv_ext *pszdev_node;
787
788         /*
789          *  Irrespective of the status go ahead and clean it
790          *  The following will over write the status.
791          */
792         for (pszdev_node = (struct drv_ext *)drv_get_first_dev_extension();
793              pszdev_node != NULL; pszdev_node = (struct drv_ext *)
794              drv_get_next_dev_extension((u32) pszdev_node)) {
795                 if (!pdrv_object->dev_node_string) {
796                         /* When this could happen? */
797                         continue;
798                 }
799                 if ((u32) pszdev_node == dw_context) {
800                         /* Found it */
801                         /* Delete from the Driver object list */
802                         lst_remove_elem(pdrv_object->dev_node_string,
803                                         (struct list_head *)pszdev_node);
804                         kfree((void *)pszdev_node);
805                         break;
806                 }
807                 /* Delete the List if it is empty */
808                 if (LST_IS_EMPTY(pdrv_object->dev_node_string)) {
809                         kfree(pdrv_object->dev_node_string);
810                         pdrv_object->dev_node_string = NULL;
811                 }
812         }
813         return status;
814 }
815
816 /*
817  *  ======== request_bridge_resources ========
818  *  Purpose:
819  *      Reserves shared memory for bridge.
820  */
821 static int request_bridge_resources(struct cfg_hostres *res)
822 {
823         int status = 0;
824         struct cfg_hostres *host_res = res;
825
826         /* num_mem_windows must not be more than CFG_MAXMEMREGISTERS */
827         host_res->num_mem_windows = 2;
828
829         /* First window is for DSP internal memory */
830         host_res->dw_sys_ctrl_base = ioremap(OMAP_SYSC_BASE, OMAP_SYSC_SIZE);
831         dev_dbg(bridge, "dw_mem_base[0] 0x%x\n", host_res->dw_mem_base[0]);
832         dev_dbg(bridge, "dw_mem_base[3] 0x%x\n", host_res->dw_mem_base[3]);
833         dev_dbg(bridge, "dw_dmmu_base %p\n", host_res->dw_dmmu_base);
834
835         /* for 24xx base port is not mapping the mamory for DSP
836          * internal memory TODO Do a ioremap here */
837         /* Second window is for DSP external memory shared with MPU */
838
839         /* These are hard-coded values */
840         host_res->birq_registers = 0;
841         host_res->birq_attrib = 0;
842         host_res->dw_offset_for_monitor = 0;
843         host_res->dw_chnl_offset = 0;
844         /* CHNL_MAXCHANNELS */
845         host_res->dw_num_chnls = CHNL_MAXCHANNELS;
846         host_res->dw_chnl_buf_size = 0x400;
847
848         return status;
849 }
850
851 /*
852  *  ======== drv_request_bridge_res_dsp ========
853  *  Purpose:
854  *      Reserves shared memory for bridge.
855  */
856 int drv_request_bridge_res_dsp(void **phost_resources)
857 {
858         int status = 0;
859         struct cfg_hostres *host_res;
860         u32 dw_buff_size;
861         u32 dma_addr;
862         u32 shm_size;
863         struct drv_data *drv_datap = dev_get_drvdata(bridge);
864
865         dw_buff_size = sizeof(struct cfg_hostres);
866
867         host_res = kzalloc(dw_buff_size, GFP_KERNEL);
868
869         if (host_res != NULL) {
870                 request_bridge_resources(host_res);
871                 /* num_mem_windows must not be more than CFG_MAXMEMREGISTERS */
872                 host_res->num_mem_windows = 4;
873
874                 host_res->dw_mem_base[0] = 0;
875                 host_res->dw_mem_base[2] = (u32) ioremap(OMAP_DSP_MEM1_BASE,
876                                                          OMAP_DSP_MEM1_SIZE);
877                 host_res->dw_mem_base[3] = (u32) ioremap(OMAP_DSP_MEM2_BASE,
878                                                          OMAP_DSP_MEM2_SIZE);
879                 host_res->dw_mem_base[4] = (u32) ioremap(OMAP_DSP_MEM3_BASE,
880                                                          OMAP_DSP_MEM3_SIZE);
881                 host_res->dw_per_base = ioremap(OMAP_PER_CM_BASE,
882                                                 OMAP_PER_CM_SIZE);
883                 host_res->dw_per_pm_base = (u32) ioremap(OMAP_PER_PRM_BASE,
884                                                          OMAP_PER_PRM_SIZE);
885                 host_res->dw_core_pm_base = (u32) ioremap(OMAP_CORE_PRM_BASE,
886                                                           OMAP_CORE_PRM_SIZE);
887                 host_res->dw_dmmu_base = ioremap(OMAP_DMMU_BASE,
888                                                  OMAP_DMMU_SIZE);
889
890                 dev_dbg(bridge, "dw_mem_base[0] 0x%x\n",
891                         host_res->dw_mem_base[0]);
892                 dev_dbg(bridge, "dw_mem_base[1] 0x%x\n",
893                         host_res->dw_mem_base[1]);
894                 dev_dbg(bridge, "dw_mem_base[2] 0x%x\n",
895                         host_res->dw_mem_base[2]);
896                 dev_dbg(bridge, "dw_mem_base[3] 0x%x\n",
897                         host_res->dw_mem_base[3]);
898                 dev_dbg(bridge, "dw_mem_base[4] 0x%x\n",
899                         host_res->dw_mem_base[4]);
900                 dev_dbg(bridge, "dw_dmmu_base %p\n", host_res->dw_dmmu_base);
901
902                 shm_size = drv_datap->shm_size;
903                 if (shm_size >= 0x10000) {
904                         /* Allocate Physically contiguous,
905                          * non-cacheable  memory */
906                         host_res->dw_mem_base[1] =
907                             (u32) mem_alloc_phys_mem(shm_size, 0x100000,
908                                                      &dma_addr);
909                         if (host_res->dw_mem_base[1] == 0) {
910                                 status = -ENOMEM;
911                                 pr_err("shm reservation Failed\n");
912                         } else {
913                                 host_res->dw_mem_length[1] = shm_size;
914                                 host_res->dw_mem_phys[1] = dma_addr;
915
916                                 dev_dbg(bridge, "%s: Bridge shm address 0x%x "
917                                         "dma_addr %x size %x\n", __func__,
918                                         host_res->dw_mem_base[1],
919                                         dma_addr, shm_size);
920                         }
921                 }
922                 if (DSP_SUCCEEDED(status)) {
923                         /* These are hard-coded values */
924                         host_res->birq_registers = 0;
925                         host_res->birq_attrib = 0;
926                         host_res->dw_offset_for_monitor = 0;
927                         host_res->dw_chnl_offset = 0;
928                         /* CHNL_MAXCHANNELS */
929                         host_res->dw_num_chnls = CHNL_MAXCHANNELS;
930                         host_res->dw_chnl_buf_size = 0x400;
931                         dw_buff_size = sizeof(struct cfg_hostres);
932                 }
933                 *phost_resources = host_res;
934         }
935         /* End Mem alloc */
936         return status;
937 }
938
939 void mem_ext_phys_pool_init(u32 pool_phys_base, u32 pool_size)
940 {
941         u32 pool_virt_base;
942
943         /* get the virtual address for the physical memory pool passed */
944         pool_virt_base = (u32) ioremap(pool_phys_base, pool_size);
945
946         if ((void **)pool_virt_base == NULL) {
947                 pr_err("%s: external physical memory map failed\n", __func__);
948                 ext_phys_mem_pool_enabled = false;
949         } else {
950                 ext_mem_pool.phys_mem_base = pool_phys_base;
951                 ext_mem_pool.phys_mem_size = pool_size;
952                 ext_mem_pool.virt_mem_base = pool_virt_base;
953                 ext_mem_pool.next_phys_alloc_ptr = pool_phys_base;
954                 ext_phys_mem_pool_enabled = true;
955         }
956 }
957
958 void mem_ext_phys_pool_release(void)
959 {
960         if (ext_phys_mem_pool_enabled) {
961                 iounmap((void *)(ext_mem_pool.virt_mem_base));
962                 ext_phys_mem_pool_enabled = false;
963         }
964 }
965
966 /*
967  *  ======== mem_ext_phys_mem_alloc ========
968  *  Purpose:
969  *     Allocate physically contiguous, uncached memory from external memory pool
970  */
971
972 static void *mem_ext_phys_mem_alloc(u32 bytes, u32 align, OUT u32 * phys_addr)
973 {
974         u32 new_alloc_ptr;
975         u32 offset;
976         u32 virt_addr;
977
978         if (align == 0)
979                 align = 1;
980
981         if (bytes > ((ext_mem_pool.phys_mem_base + ext_mem_pool.phys_mem_size)
982                      - ext_mem_pool.next_phys_alloc_ptr)) {
983                 phys_addr = NULL;
984                 return NULL;
985         } else {
986                 offset = (ext_mem_pool.next_phys_alloc_ptr & (align - 1));
987                 if (offset == 0)
988                         new_alloc_ptr = ext_mem_pool.next_phys_alloc_ptr;
989                 else
990                         new_alloc_ptr = (ext_mem_pool.next_phys_alloc_ptr) +
991                             (align - offset);
992                 if ((new_alloc_ptr + bytes) <=
993                     (ext_mem_pool.phys_mem_base + ext_mem_pool.phys_mem_size)) {
994                         /* we can allocate */
995                         *phys_addr = new_alloc_ptr;
996                         ext_mem_pool.next_phys_alloc_ptr =
997                             new_alloc_ptr + bytes;
998                         virt_addr =
999                             ext_mem_pool.virt_mem_base + (new_alloc_ptr -
1000                                                           ext_mem_pool.
1001                                                           phys_mem_base);
1002                         return (void *)virt_addr;
1003                 } else {
1004                         *phys_addr = 0;
1005                         return NULL;
1006                 }
1007         }
1008 }
1009
1010 /*
1011  *  ======== mem_alloc_phys_mem ========
1012  *  Purpose:
1013  *      Allocate physically contiguous, uncached memory
1014  */
1015 void *mem_alloc_phys_mem(u32 byte_size, u32 align_mask,
1016                                 OUT u32 *physical_address)
1017 {
1018         void *va_mem = NULL;
1019         dma_addr_t pa_mem;
1020
1021         if (byte_size > 0) {
1022                 if (ext_phys_mem_pool_enabled) {
1023                         va_mem = mem_ext_phys_mem_alloc(byte_size, align_mask,
1024                                                         (u32 *) &pa_mem);
1025                 } else
1026                         va_mem = dma_alloc_coherent(NULL, byte_size, &pa_mem,
1027                                                                 GFP_KERNEL);
1028                 if (va_mem == NULL)
1029                         *physical_address = 0;
1030                 else
1031                         *physical_address = pa_mem;
1032         }
1033         return va_mem;
1034 }
1035
1036 /*
1037  *  ======== mem_free_phys_mem ========
1038  *  Purpose:
1039  *      Free the given block of physically contiguous memory.
1040  */
1041 void mem_free_phys_mem(void *virtual_address, u32 physical_address,
1042                        u32 byte_size)
1043 {
1044         DBC_REQUIRE(virtual_address != NULL);
1045
1046         if (!ext_phys_mem_pool_enabled)
1047                 dma_free_coherent(NULL, byte_size, virtual_address,
1048                                   physical_address);
1049 }