Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
mgr.c
Go to the documentation of this file.
1 /*
2  * mgr.c
3  *
4  * DSP-BIOS Bridge driver support functions for TI OMAP processors.
5  *
6  * Implementation of Manager interface to the device object at the
7  * driver level. This queries the NDB data base and retrieves the
8  * data about Node and Processor.
9  *
10  * Copyright (C) 2005-2006 Texas Instruments, Inc.
11  *
12  * This package is free software; you can redistribute it and/or modify
13  * it under the terms of the GNU General Public License version 2 as
14  * published by the Free Software Foundation.
15  *
16  * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
17  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
18  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
19  */
20 
21 #include <linux/types.h>
22 
23 /* ----------------------------------- Host OS */
24 #include <dspbridge/host_os.h>
25 
26 /* ----------------------------------- DSP/BIOS Bridge */
27 #include <dspbridge/dbdefs.h>
28 
29 /* ----------------------------------- OS Adaptation Layer */
30 #include <dspbridge/sync.h>
31 
32 /* ----------------------------------- Others */
33 #include <dspbridge/dbdcd.h>
34 #include <dspbridge/drv.h>
35 #include <dspbridge/dev.h>
36 
37 /* ----------------------------------- This */
38 #include <dspbridge/mgr.h>
39 
40 /* ----------------------------------- Defines, Data Structures, Typedefs */
41 #define ZLDLLNAME ""
42 
43 struct mgr_object {
44  struct dcd_manager *dcd_mgr; /* Proc/Node data manager */
45 };
46 
47 /* ----------------------------------- Globals */
48 static u32 refs;
49 
50 /*
51  * ========= mgr_create =========
52  * Purpose:
53  * MGR Object gets created only once during driver Loading.
54  */
55 int mgr_create(struct mgr_object **mgr_obj,
56  struct cfg_devnode *dev_node_obj)
57 {
58  int status = 0;
59  struct mgr_object *pmgr_obj = NULL;
60  struct drv_data *drv_datap = dev_get_drvdata(bridge);
61 
62  pmgr_obj = kzalloc(sizeof(struct mgr_object), GFP_KERNEL);
63  if (pmgr_obj) {
64  status = dcd_create_manager(ZLDLLNAME, &pmgr_obj->dcd_mgr);
65  if (!status) {
66  /* If succeeded store the handle in the MGR Object */
67  if (drv_datap) {
68  drv_datap->mgr_object = (void *)pmgr_obj;
69  } else {
70  status = -EPERM;
71  pr_err("%s: Failed to store MGR object\n",
72  __func__);
73  }
74 
75  if (!status) {
76  *mgr_obj = pmgr_obj;
77  } else {
78  dcd_destroy_manager(pmgr_obj->dcd_mgr);
79  kfree(pmgr_obj);
80  }
81  } else {
82  /* failed to Create DCD Manager */
83  kfree(pmgr_obj);
84  }
85  } else {
86  status = -ENOMEM;
87  }
88 
89  return status;
90 }
91 
92 /*
93  * ========= mgr_destroy =========
94  * This function is invoked during bridge driver unloading.Frees MGR object.
95  */
96 int mgr_destroy(struct mgr_object *hmgr_obj)
97 {
98  int status = 0;
99  struct mgr_object *pmgr_obj = (struct mgr_object *)hmgr_obj;
100  struct drv_data *drv_datap = dev_get_drvdata(bridge);
101 
102  /* Free resources */
103  if (hmgr_obj->dcd_mgr)
104  dcd_destroy_manager(hmgr_obj->dcd_mgr);
105 
106  kfree(pmgr_obj);
107  /* Update the driver data with NULL for MGR Object */
108  if (drv_datap) {
109  drv_datap->mgr_object = NULL;
110  } else {
111  status = -EPERM;
112  pr_err("%s: Failed to store MGR object\n", __func__);
113  }
114 
115  return status;
116 }
117 
118 /*
119  * ======== mgr_enum_node_info ========
120  * Enumerate and get configuration information about nodes configured
121  * in the node database.
122  */
123 int mgr_enum_node_info(u32 node_id, struct dsp_ndbprops *pndb_props,
124  u32 undb_props_size, u32 *pu_num_nodes)
125 {
126  int status = 0;
127  struct dsp_uuid node_uuid;
128  u32 node_index = 0;
129  struct dcd_genericobj gen_obj;
130  struct mgr_object *pmgr_obj = NULL;
131  struct drv_data *drv_datap = dev_get_drvdata(bridge);
132 
133  *pu_num_nodes = 0;
134  /* Get the Manager Object from the driver data */
135  if (!drv_datap || !drv_datap->mgr_object) {
136  pr_err("%s: Failed to retrieve the object handle\n", __func__);
137  return -ENODATA;
138  }
139  pmgr_obj = drv_datap->mgr_object;
140 
141  /* Forever loop till we hit failed or no more items in the
142  * Enumeration. We will exit the loop other than 0; */
143  while (!status) {
144  status = dcd_enumerate_object(node_index++, DSP_DCDNODETYPE,
145  &node_uuid);
146  if (status)
147  break;
148  *pu_num_nodes = node_index;
149  if (node_id == (node_index - 1)) {
150  status = dcd_get_object_def(pmgr_obj->dcd_mgr,
151  &node_uuid, DSP_DCDNODETYPE, &gen_obj);
152  if (status)
153  break;
154  /* Get the Obj def */
155  *pndb_props = gen_obj.obj_data.node_obj.ndb_props;
156  }
157  }
158 
159  /* the last status is not 0, but neither an error */
160  if (status > 0)
161  status = 0;
162 
163  return status;
164 }
165 
166 /*
167  * ======== mgr_enum_processor_info ========
168  * Enumerate and get configuration information about available
169  * DSP processors.
170  */
172  struct dsp_processorinfo *
173  processor_info, u32 processor_info_size,
174  u8 *pu_num_procs)
175 {
176  int status = 0;
177  int status1 = 0;
178  int status2 = 0;
179  struct dsp_uuid temp_uuid;
180  u32 temp_index = 0;
181  u32 proc_index = 0;
182  struct dcd_genericobj gen_obj;
183  struct mgr_object *pmgr_obj = NULL;
184  struct mgr_processorextinfo *ext_info;
185  struct dev_object *hdev_obj;
186  struct drv_object *hdrv_obj;
187  u8 dev_type;
188  struct cfg_devnode *dev_node;
189  struct drv_data *drv_datap = dev_get_drvdata(bridge);
190  bool proc_detect = false;
191 
192  *pu_num_procs = 0;
193 
194  /* Retrieve the Object handle from the driver data */
195  if (!drv_datap || !drv_datap->drv_object) {
196  status = -ENODATA;
197  pr_err("%s: Failed to retrieve the object handle\n", __func__);
198  } else {
199  hdrv_obj = drv_datap->drv_object;
200  }
201 
202  if (!status) {
203  status = drv_get_dev_object(processor_id, hdrv_obj, &hdev_obj);
204  if (!status) {
205  status = dev_get_dev_type(hdev_obj, (u8 *) &dev_type);
206  status = dev_get_dev_node(hdev_obj, &dev_node);
207  if (dev_type != DSP_UNIT)
208  status = -EPERM;
209 
210  if (!status)
211  processor_info->processor_type = DSPTYPE64;
212  }
213  }
214  if (status)
215  goto func_end;
216 
217  /* Get The Manager Object from the driver data */
218  if (drv_datap && drv_datap->mgr_object) {
219  pmgr_obj = drv_datap->mgr_object;
220  } else {
221  dev_dbg(bridge, "%s: Failed to get MGR Object\n", __func__);
222  goto func_end;
223  }
224  /* Forever loop till we hit no more items in the
225  * Enumeration. We will exit the loop other than 0; */
226  while (status1 == 0) {
227  status1 = dcd_enumerate_object(temp_index++,
229  &temp_uuid);
230  if (status1 != 0)
231  break;
232 
233  proc_index++;
234  /* Get the Object properties to find the Device/Processor
235  * Type */
236  if (proc_detect != false)
237  continue;
238 
239  status2 = dcd_get_object_def(pmgr_obj->dcd_mgr,
240  (struct dsp_uuid *)&temp_uuid,
241  DSP_DCDPROCESSORTYPE, &gen_obj);
242  if (!status2) {
243  /* Get the Obj def */
244  if (processor_info_size <
245  sizeof(struct mgr_processorextinfo)) {
246  *processor_info = gen_obj.obj_data.proc_info;
247  } else {
248  /* extended info */
249  ext_info = (struct mgr_processorextinfo *)
250  processor_info;
251  *ext_info = gen_obj.obj_data.ext_proc_obj;
252  }
253  dev_dbg(bridge, "%s: Got proctype from DCD %x\n",
254  __func__, processor_info->processor_type);
255  /* See if we got the needed processor */
256  if (dev_type == DSP_UNIT) {
257  if (processor_info->processor_type ==
259  proc_detect = true;
260  } else if (dev_type == IVA_UNIT) {
261  if (processor_info->processor_type ==
263  proc_detect = true;
264  }
265  /* User applications only check for chip type, so
266  * this is a clumsy overwrite */
267  processor_info->processor_type = DSPTYPE64;
268  } else {
269  dev_dbg(bridge, "%s: Failed to get DCD processor info "
270  "%x\n", __func__, status2);
271  status = -EPERM;
272  }
273  }
274  *pu_num_procs = proc_index;
275  if (proc_detect == false) {
276  dev_dbg(bridge, "%s: Failed to get proc info from DCD, so use "
277  "CFG registry\n", __func__);
278  processor_info->processor_type = DSPTYPE64;
279  }
280 func_end:
281  return status;
282 }
283 
284 /*
285  * ======== mgr_exit ========
286  * Decrement reference count, and free resources when reference count is
287  * 0.
288  */
289 void mgr_exit(void)
290 {
291  refs--;
292  if (refs == 0)
293  dcd_exit();
294 }
295 
296 /*
297  * ======== mgr_get_dcd_handle ========
298  * Retrieves the MGR handle. Accessor Function.
299  */
300 int mgr_get_dcd_handle(struct mgr_object *mgr_handle,
301  u32 *dcd_handle)
302 {
303  int status = -EPERM;
304  struct mgr_object *pmgr_obj = (struct mgr_object *)mgr_handle;
305 
306  *dcd_handle = (u32) NULL;
307  if (pmgr_obj) {
308  *dcd_handle = (u32) pmgr_obj->dcd_mgr;
309  status = 0;
310  }
311 
312  return status;
313 }
314 
315 /*
316  * ======== mgr_init ========
317  * Initialize MGR's private state, keeping a reference count on each call.
318  */
319 bool mgr_init(void)
320 {
321  bool ret = true;
322 
323  if (refs == 0)
324  ret = dcd_init(); /* DCD Module */
325 
326  if (ret)
327  refs++;
328 
329  return ret;
330 }
331 
332 /*
333  * ======== mgr_wait_for_bridge_events ========
334  * Block on any Bridge event(s)
335  */
336 int mgr_wait_for_bridge_events(struct dsp_notification **anotifications,
337  u32 count, u32 *pu_index,
338  u32 utimeout)
339 {
340  int status;
341  struct sync_object *sync_events[MAX_EVENTS];
342  u32 i;
343 
344  for (i = 0; i < count; i++)
345  sync_events[i] = anotifications[i]->handle;
346 
347  status = sync_wait_on_multiple_events(sync_events, count, utimeout,
348  pu_index);
349 
350  return status;
351 
352 }