Beispiel #1
0
/*
 *  ======== cod_create ========
 *  Purpose:
 *      Create an object to manage code on a DSP system.
 *      This object can be used to load an initial program image with
 *      arguments that can later be expanded with
 *      dynamically loaded object files.
 *
 */
int cod_create(struct cod_manager **mgr, char *str_zl_file,
		      const struct cod_attrs *attrs)
{
	struct cod_manager *mgr_new;
	struct dbll_attrs zl_attrs;
	int status = 0;

	DBC_REQUIRE(refs > 0);
	DBC_REQUIRE(mgr != NULL);

	/* assume failure */
	*mgr = NULL;

	/* we don't support non-default attrs yet */
	if (attrs != NULL)
		return -ENOSYS;

	mgr_new = kzalloc(sizeof(struct cod_manager), GFP_KERNEL);
	if (mgr_new == NULL)
		return -ENOMEM;

	/* Set up loader functions */
	mgr_new->fxns = ldr_fxns;

	/* initialize the ZL module */
	mgr_new->fxns.init_fxn();

	zl_attrs.alloc = (dbll_alloc_fxn) no_op;
	zl_attrs.free = (dbll_free_fxn) no_op;
	zl_attrs.fread = (dbll_read_fxn) cod_f_read;
	zl_attrs.fseek = (dbll_seek_fxn) cod_f_seek;
	zl_attrs.ftell = (dbll_tell_fxn) cod_f_tell;
	zl_attrs.fclose = (dbll_f_close_fxn) cod_f_close;
	zl_attrs.fopen = (dbll_f_open_fxn) cod_f_open;
	zl_attrs.sym_lookup = NULL;
	zl_attrs.base_image = true;
	zl_attrs.log_write = NULL;
	zl_attrs.log_write_handle = NULL;
	zl_attrs.write = NULL;
	zl_attrs.rmm_handle = NULL;
	zl_attrs.input_params = NULL;
	zl_attrs.sym_handle = NULL;
	zl_attrs.sym_arg = NULL;

	mgr_new->attrs = zl_attrs;

	status = mgr_new->fxns.create_fxn(&mgr_new->target, &zl_attrs);

	if (status) {
		cod_delete(mgr_new);
		return -ESPIPE;
	}

	/* return the new manager */
	*mgr = mgr_new;

	return 0;
}
Beispiel #2
0
int cod_create(struct cod_manager **mgr, char *str_zl_file)
{
	struct cod_manager *mgr_new;
	struct dbll_attrs zl_attrs;
	int status = 0;

	/*                */
	*mgr = NULL;

	mgr_new = kzalloc(sizeof(struct cod_manager), GFP_KERNEL);
	if (mgr_new == NULL)
		return -ENOMEM;

	/*                         */
	mgr_new->fxns = ldr_fxns;

	/*                          */
	mgr_new->fxns.init_fxn();

	zl_attrs.alloc = (dbll_alloc_fxn) no_op;
	zl_attrs.free = (dbll_free_fxn) no_op;
	zl_attrs.fread = (dbll_read_fxn) cod_f_read;
	zl_attrs.fseek = (dbll_seek_fxn) cod_f_seek;
	zl_attrs.ftell = (dbll_tell_fxn) cod_f_tell;
	zl_attrs.fclose = (dbll_f_close_fxn) cod_f_close;
	zl_attrs.fopen = (dbll_f_open_fxn) cod_f_open;
	zl_attrs.sym_lookup = NULL;
	zl_attrs.base_image = true;
	zl_attrs.log_write = NULL;
	zl_attrs.log_write_handle = NULL;
	zl_attrs.write = NULL;
	zl_attrs.rmm_handle = NULL;
	zl_attrs.input_params = NULL;
	zl_attrs.sym_handle = NULL;
	zl_attrs.sym_arg = NULL;

	mgr_new->attrs = zl_attrs;

	status = mgr_new->fxns.create_fxn(&mgr_new->target, &zl_attrs);

	if (status) {
		cod_delete(mgr_new);
		return -ESPIPE;
	}

	/*                        */
	*mgr = mgr_new;

	return 0;
}
Beispiel #3
0
/*
 *  ======== dev_destroy_device ========
 *  Purpose:
 *      Destroys the channel manager for this device, if any, calls
 *      bridge_dev_destroy(), and then attempts to unload the Bridge module.
 */
int dev_destroy_device(struct dev_object *hdev_obj)
{
	int status = 0;
	struct dev_object *dev_obj = hdev_obj;

	DBC_REQUIRE(refs > 0);

	if (hdev_obj) {
		if (dev_obj->cod_mgr) {
			cod_delete(dev_obj->cod_mgr);
			dev_obj->cod_mgr = NULL;
		}

		if (dev_obj->hnode_mgr) {
			node_delete_mgr(dev_obj->hnode_mgr);
			dev_obj->hnode_mgr = NULL;
		}

		/* Free the io, channel, and message managers for this board: */
		if (dev_obj->hio_mgr) {
			io_destroy(dev_obj->hio_mgr);
			dev_obj->hio_mgr = NULL;
		}
		if (dev_obj->hchnl_mgr) {
			chnl_destroy(dev_obj->hchnl_mgr);
			dev_obj->hchnl_mgr = NULL;
		}
		if (dev_obj->hmsg_mgr) {
			msg_delete(dev_obj->hmsg_mgr);
			dev_obj->hmsg_mgr = NULL;
		}

		if (dev_obj->hdeh_mgr) {
			/* Uninitialize DEH module. */
			bridge_deh_destroy(dev_obj->hdeh_mgr);
			dev_obj->hdeh_mgr = NULL;
		}
		if (dev_obj->hcmm_mgr) {
			cmm_destroy(dev_obj->hcmm_mgr, true);
			dev_obj->hcmm_mgr = NULL;
		}

		if (dev_obj->dmm_mgr) {
			dmm_destroy(dev_obj->dmm_mgr);
			dev_obj->dmm_mgr = NULL;
		}

		/* Call the driver's bridge_dev_destroy() function: */
		/* Require of DevDestroy */
		if (dev_obj->hbridge_context) {
			status = (*dev_obj->bridge_interface.pfn_dev_destroy)
			    (dev_obj->hbridge_context);
			dev_obj->hbridge_context = NULL;
		} else
			status = -EPERM;
		if (!status) {
			kfree(dev_obj->proc_list);
			dev_obj->proc_list = NULL;

			/* Remove this DEV_Object from the global list: */
			drv_remove_dev_object(dev_obj->hdrv_obj, dev_obj);
			/* Free The library * LDR_FreeModule
			 * (dev_obj->module_obj); */
			/* Free this dev object: */
			kfree(dev_obj);
			dev_obj = NULL;
		}
	} else {
		status = -EFAULT;
	}

	return status;
}
Beispiel #4
0
/*
 *  ======== dev_create_device ========
 *  Purpose:
 *      Called by the operating system to load the PM Bridge Driver for a
 *      PM board (device).
 */
int dev_create_device(struct dev_object **device_obj,
			     const char *driver_file_name,
			     struct cfg_devnode *dev_node_obj)
{
	struct cfg_hostres *host_res;
	struct ldr_module *module_obj = NULL;
	struct bridge_drv_interface *drv_fxns = NULL;
	struct dev_object *dev_obj = NULL;
	struct chnl_mgrattrs mgr_attrs;
	struct io_attrs io_mgr_attrs;
	u32 num_windows;
	struct drv_object *hdrv_obj = NULL;
	struct drv_data *drv_datap = dev_get_drvdata(bridge);
	int status = 0;
	DBC_REQUIRE(refs > 0);
	DBC_REQUIRE(device_obj != NULL);
	DBC_REQUIRE(driver_file_name != NULL);

	status = drv_request_bridge_res_dsp((void *)&host_res);

	if (status) {
		dev_dbg(bridge, "%s: Failed to reserve bridge resources\n",
			__func__);
		goto leave;
	}

	/*  Get the Bridge driver interface functions */
	bridge_drv_entry(&drv_fxns, driver_file_name);

	/* Retrieve the Object handle from the driver data */
	if (drv_datap && drv_datap->drv_object) {
		hdrv_obj = drv_datap->drv_object;
	} else {
		status = -EPERM;
		pr_err("%s: Failed to retrieve the object handle\n", __func__);
	}

	/* Create the device object, and pass a handle to the Bridge driver for
	 * storage. */
	if (!status) {
		DBC_ASSERT(drv_fxns);
		dev_obj = kzalloc(sizeof(struct dev_object), GFP_KERNEL);
		if (dev_obj) {
			/* Fill out the rest of the Dev Object structure: */
			dev_obj->dev_node_obj = dev_node_obj;
			dev_obj->module_obj = module_obj;
			dev_obj->cod_mgr = NULL;
			dev_obj->hchnl_mgr = NULL;
			dev_obj->hdeh_mgr = NULL;
			dev_obj->lock_owner = NULL;
			dev_obj->word_size = DSPWORDSIZE;
			dev_obj->hdrv_obj = hdrv_obj;
			dev_obj->dev_type = DSP_UNIT;
			/* Store this Bridge's interface functions, based on its
			 * version. */
			store_interface_fxns(drv_fxns,
						&dev_obj->bridge_interface);

			/* Call fxn_dev_create() to get the Bridge's device
			 * context handle. */
			status = (dev_obj->bridge_interface.pfn_dev_create)
			    (&dev_obj->hbridge_context, dev_obj,
			     host_res);
			/* Assert bridge_dev_create()'s ensure clause: */
			DBC_ASSERT(status
				   || (dev_obj->hbridge_context != NULL));
		} else {
			status = -ENOMEM;
		}
	}
	/* Attempt to create the COD manager for this device: */
	if (!status)
		status = init_cod_mgr(dev_obj);

	/* Attempt to create the channel manager for this device: */
	if (!status) {
		mgr_attrs.max_channels = CHNL_MAXCHANNELS;
		io_mgr_attrs.birq = host_res->birq_registers;
		io_mgr_attrs.irq_shared =
		    (host_res->birq_attrib & CFG_IRQSHARED);
		io_mgr_attrs.word_size = DSPWORDSIZE;
		mgr_attrs.word_size = DSPWORDSIZE;
		num_windows = host_res->num_mem_windows;
		if (num_windows) {
			/* Assume last memory window is for CHNL */
			io_mgr_attrs.shm_base = host_res->dw_mem_base[1] +
			    host_res->dw_offset_for_monitor;
			io_mgr_attrs.usm_length =
			    host_res->dw_mem_length[1] -
			    host_res->dw_offset_for_monitor;
		} else {
			io_mgr_attrs.shm_base = 0;
			io_mgr_attrs.usm_length = 0;
			pr_err("%s: No memory reserved for shared structures\n",
			       __func__);
		}
		status = chnl_create(&dev_obj->hchnl_mgr, dev_obj, &mgr_attrs);
		if (status == -ENOSYS) {
			/* It's OK for a device not to have a channel
			 * manager: */
			status = 0;
		}
		/* Create CMM mgr even if Msg Mgr not impl. */
		status = cmm_create(&dev_obj->hcmm_mgr,
				    (struct dev_object *)dev_obj, NULL);
		/* Only create IO manager if we have a channel manager */
		if (!status && dev_obj->hchnl_mgr) {
			status = io_create(&dev_obj->hio_mgr, dev_obj,
					   &io_mgr_attrs);
		}
		/* Only create DEH manager if we have an IO manager */
		if (!status) {
			/* Instantiate the DEH module */
			status = bridge_deh_create(&dev_obj->hdeh_mgr, dev_obj);
		}
		/* Create DMM mgr . */
		status = dmm_create(&dev_obj->dmm_mgr,
				    (struct dev_object *)dev_obj, NULL);
	}
	/* Add the new DEV_Object to the global list: */
	if (!status) {
		lst_init_elem(&dev_obj->link);
		status = drv_insert_dev_object(hdrv_obj, dev_obj);
	}
	/* Create the Processor List */
	if (!status) {
		dev_obj->proc_list = kzalloc(sizeof(struct lst_list),
							GFP_KERNEL);
		if (!(dev_obj->proc_list))
			status = -EPERM;
		else
			INIT_LIST_HEAD(&dev_obj->proc_list->head);
	}
leave:
	/*  If all went well, return a handle to the dev object;
	 *  else, cleanup and return NULL in the OUT parameter. */
	if (!status) {
		*device_obj = dev_obj;
	} else {
		if (dev_obj) {
			kfree(dev_obj->proc_list);
			if (dev_obj->cod_mgr)
				cod_delete(dev_obj->cod_mgr);
			if (dev_obj->dmm_mgr)
				dmm_destroy(dev_obj->dmm_mgr);
			kfree(dev_obj);
		}

		*device_obj = NULL;
	}

	DBC_ENSURE((!status && *device_obj) || (status && !*device_obj));
	return status;
}