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  */
mgr_create(struct mgr_object ** mgr_obj,struct cfg_devnode * dev_node_obj)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  */
mgr_destroy(struct mgr_object * hmgr_obj)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  */
mgr_enum_node_info(u32 node_id,struct dsp_ndbprops * pndb_props,u32 undb_props_size,u32 * pu_num_nodes)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  */
mgr_enum_processor_info(u32 processor_id,struct dsp_processorinfo * processor_info,u32 processor_info_size,u8 * pu_num_procs)171 int mgr_enum_processor_info(u32 processor_id,
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++,
228 					       DSP_DCDPROCESSORTYPE,
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 ==
258 				    DSPPROCTYPE_C64)
259 					proc_detect = true;
260 			} else if (dev_type == IVA_UNIT) {
261 				if (processor_info->processor_type ==
262 				    IVAPROCTYPE_ARM7)
263 					proc_detect = true;
264 			}
265 			/* User applciatiuons aonly check for chip type, so
266 			 * this 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  */
mgr_exit(void)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  */
mgr_get_dcd_handle(struct mgr_object * mgr_handle,u32 * dcd_handle)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  */
mgr_init(void)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  */
mgr_wait_for_bridge_events(struct dsp_notification ** anotifications,u32 count,u32 * pu_index,u32 utimeout)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 }
353