/** * _create_endpoint * * This function creates rpmsg endpoint. * * @param rdev - pointer to remote device * @param cb - Rx completion call back * @param priv - private data * @param addr - endpoint src address * * @return - pointer to endpoint control block * */ struct rpmsg_endpoint *_create_endpoint(struct remote_device *rdev, rpmsg_rx_cb_t cb, void *priv, unsigned long addr) { struct rpmsg_endpoint *rp_ept; struct llist *node; int status = RPMSG_SUCCESS; rp_ept = env_allocate_memory(sizeof(struct rpmsg_endpoint)); if (!rp_ept) { return RPMSG_NULL ; } env_memset(rp_ept, 0x00, sizeof(struct rpmsg_endpoint)); node = env_allocate_memory(sizeof(struct llist)); if (!node) { env_free_memory(rp_ept); return RPMSG_NULL; } env_lock_mutex(rdev->lock); if (addr != RPMSG_ADDR_ANY) { /* * Application has requested a particular src address for endpoint, * first check if address is available. */ if (!rpmsg_is_address_set(rdev->bitmap, RPMSG_ADDR_BMP_SIZE, addr)) { /* Mark the address as used in the address bitmap. */ rpmsg_set_address(rdev->bitmap, RPMSG_ADDR_BMP_SIZE, addr); } else { status = RPMSG_ERR_DEV_ADDR; } } else { addr = rpmsg_get_address(rdev->bitmap, RPMSG_ADDR_BMP_SIZE); if (addr < 0) { status = RPMSG_ERR_DEV_ADDR; } } /* Do cleanup in case of error and return */ if (status) { env_free_memory(node); env_free_memory(rp_ept); env_unlock_mutex(rdev->lock); return RPMSG_NULL; } rp_ept->addr = addr; rp_ept->cb = cb; rp_ept->priv = priv; node->data = rp_ept; add_to_list(&rdev->rp_endpoints, node); env_unlock_mutex(rdev->lock); return rp_ept; }
int rpmsg_retarget_deinit(struct rpmsg_channel *rp_chnl) { env_free_memory(rpc_data->rpc); env_free_memory(rpc_data->rpc_response); env_delete_mutex(rpc_data->rpc_lock); env_delete_sync_lock(rpc_data->sync_lock); rpmsg_destroy_ept(rpc_data->rp_ept); env_free_memory(rpc_data); return 0; }
/** * rpmsg_destroy_ept * * This function deletes rpmsg endpoint and performs cleanup. * * @param rdev - pointer to remote device * @param rp_ept - pointer to endpoint to destroy * */ void _destroy_endpoint(struct remote_device *rdev, struct rpmsg_endpoint *rp_ept) { struct llist *node; node = rpmsg_rdev_get_endpoint_from_addr(rdev, rp_ept->addr); if (node) { env_lock_mutex(rdev->lock); rpmsg_release_address(rdev->bitmap, RPMSG_ADDR_BMP_SIZE, rp_ept->addr); remove_from_list(&rdev->rp_endpoints, node); env_unlock_mutex(rdev->lock); env_free_memory(node); } env_free_memory(rp_ept); }
/** * _rpmsg_delete_channel * * Deletes given rpmsg channel. * * @param rp_chnl - pointer to rpmsg channel to delete * * return - none */ void _rpmsg_delete_channel(struct rpmsg_channel * rp_chnl) { struct llist *node; if (rp_chnl) { node = rpmsg_rdev_get_chnl_node_from_id(rp_chnl->rdev, rp_chnl->name); if (node) { env_lock_mutex(rp_chnl->rdev->lock); remove_from_list(&rp_chnl->rdev->rp_channels, node); env_unlock_mutex(rp_chnl->rdev->lock); env_free_memory(node); } env_free_memory(rp_chnl); } }
/** * _rpmsg_create_channel * * Creates new rpmsg channel with the given parameters. * * @param rdev - pointer to remote device which contains the channel * @param name - name of the device * @param src - source address for the rpmsg channel * @param dst - destination address for the rpmsg channel * * @return - pointer to new rpmsg channel * */ struct rpmsg_channel *_rpmsg_create_channel(struct remote_device *rdev, char *name, unsigned long src, unsigned long dst) { struct rpmsg_channel *rp_chnl; struct llist *node; rp_chnl = env_allocate_memory(sizeof(struct rpmsg_channel)); if (rp_chnl) { env_memset(rp_chnl, 0x00, sizeof(struct rpmsg_channel)); env_strncpy(rp_chnl->name, name, sizeof(rp_chnl->name)); rp_chnl->src = src; rp_chnl->dst = dst; rp_chnl->rdev = rdev; /* Place channel on channels list */ node = env_allocate_memory(sizeof(struct llist)); if (!node) { env_free_memory(rp_chnl); return RPMSG_NULL ; } node->data = rp_chnl; env_lock_mutex(rdev->lock); add_to_list(&rdev->rp_channels , node); env_unlock_mutex(rdev->lock); } return rp_chnl; }
int remoteproc_resource_deinit(struct remote_proc *rproc) { int i = 0; struct proc_vring *vring_hw = 0; if (rproc) { if (rproc->rdev) { /* disable IPC interrupts */ if (rproc->proc->ops->reg_ipi_after_deinit) { for(i = 0; i < 2; i++) { vring_hw = &rproc->proc->vdev.vring_info[i]; rproc->proc->ops->reg_ipi_after_deinit(vring_hw); } } rpmsg_deinit(rproc->rdev); } if (rproc->proc) { hil_delete_proc(rproc->proc); } env_free_memory(rproc); } env_deinit(); /* Disable the caches - This is required if master boots firmwares * multiple times without hard reset on same core. If caches are * not invalidated at this point in time then subsequent firmware * boots on the same core may experience cache inconsistencies. * */ env_disable_cache(); return RPROC_SUCCESS; }
/** * hil_create_proc * * This function creates a HIL proc instance for given CPU id and populates * it with platform info. * * @param cpu_id - cpu id * * @return - pointer to proc instance * */ struct hil_proc *hil_create_proc(int cpu_id) { struct hil_proc *proc = NULL; struct llist *node = NULL; struct llist *proc_hd = procs.proc_list; int status; /* If proc already exists then return it */ while (proc_hd != NULL) { proc = (struct hil_proc *)proc_hd->data; if (proc->cpu_id == (unsigned int)cpu_id) { return proc; } proc_hd = proc_hd->next; } /* Allocate memory for proc instance */ proc = env_allocate_memory(sizeof(struct hil_proc)); if (!proc) { return NULL; } /* Get HW specfic info */ status = platform_get_processor_info(proc, cpu_id); if (status) { env_free_memory(proc); return NULL; } /* Enable mapping for the shared memory region */ env_map_memory((unsigned int)proc->sh_buff.start_addr, (unsigned int)proc->sh_buff.start_addr, proc->sh_buff.size, (SHARED_MEM | UNCACHED)); /* Put the new proc in the procs list */ node = env_allocate_memory(sizeof(struct llist)); if (!node) { env_free_memory(proc); return NULL; } node->data = proc; add_to_list(&procs.proc_list, node); return proc; }
/** * rpmsg_rdev_deinit * * This function un-initializes the remote device. * * @param rdev - pointer to remote device to deinit. * * @return - none * */ void rpmsg_rdev_deinit(struct remote_device *rdev) { struct llist *rp_chnl_head, *rp_chnl_temp, *node; struct rpmsg_channel *rp_chnl; rp_chnl_head = rdev->rp_channels; while (rp_chnl_head != RPMSG_NULL) { rp_chnl_temp = rp_chnl_head->next; rp_chnl = (struct rpmsg_channel *)rp_chnl_head->data; if (rdev->channel_destroyed) { rdev->channel_destroyed(rp_chnl); } if ((rdev->support_ns) && (rdev->role == RPMSG_MASTER)) { rpmsg_send_ns_message(rdev, rp_chnl, RPMSG_NS_DESTROY); } /* Delete default endpoint for channel */ if (rp_chnl->rp_ept) { rpmsg_destroy_ept(rp_chnl->rp_ept); } _rpmsg_delete_channel(rp_chnl); rp_chnl_head = rp_chnl_temp; } /* Delete name service endpoint */ node = rpmsg_rdev_get_endpoint_from_addr(rdev, RPMSG_NS_EPT_ADDR); if (node) { _destroy_endpoint(rdev, (struct rpmsg_endpoint *)node->data); } if (rdev->rvq) { virtqueue_free(rdev->rvq); } if (rdev->tvq) { virtqueue_free(rdev->tvq); } if (rdev->mem_pool) { sh_mem_delete_pool(rdev->mem_pool); } if (rdev->lock) { env_delete_mutex(rdev->lock); } if (rdev->proc) { hil_delete_proc(rdev->proc); rdev->proc = 0; } env_free_memory(rdev); }
/** * hil_delete_proc * * This function deletes the given proc instance and frees the * associated resources. * * @param proc - pointer to hil remote_proc instance * */ void hil_delete_proc(struct hil_proc *proc) { struct llist *proc_hd = NULL; if (!proc) return; proc_hd = procs.proc_list; while (proc_hd != NULL) { if (proc_hd->data == proc) { remove_from_list(&procs.proc_list, proc_hd); env_free_memory(proc_hd); env_free_memory(proc); break; } proc_hd = proc_hd->next; } }
/** * remoteproc_deinit * * Uninitializes resources for remoteproc "master" configuration. * * @param rproc - pointer to remote proc instance * * @param returns - status of function execution * */ int remoteproc_deinit(struct remote_proc *rproc) { if (rproc) { if (rproc->loader) { (void) remoteproc_loader_delete(rproc->loader); rproc->loader = RPROC_NULL; } if (rproc->proc) { hil_delete_proc(rproc->proc); rproc->proc = RPROC_NULL; } env_free_memory(rproc); } env_deinit(); return RPROC_SUCCESS; }
/** * virtqueue_free - Frees VirtIO queue resources * * @param vq - Pointer to VirtIO queue control block * */ void virtqueue_free(struct virtqueue *vq) { if (vq != VQ_NULL) { if (vq->vq_free_cnt != vq->vq_nentries) { env_print ("\r\nWARNING %s: freeing non-empty virtqueue\r\n", vq->vq_name); } //TODO : Need to free indirect buffers here if (vq->vq_ring_mem != VQ_NULL) { vq->vq_ring_size = 0; vq->vq_ring_mem = VQ_NULL; } env_free_memory(vq); } }
/** * remoteproc_loader_delete * * Deletes the remoteproc loader. * * @param loader - pointer to remoteproc loader * * @return - 0 if success, error otherwise */ int remoteproc_loader_delete(struct remoteproc_loader *loader) { int status = 0; if (!loader) { return RPROC_ERR_PARAM; } /* Check if a firmware is attached. */ if (loader->remote_firmware) { /* Detach firmware first. */ status = loader->detach_firmware(loader); } /* Recover the allocated memory. */ env_free_memory(loader); return status; }
/** * remoteproc_loader_init * * Initializes the remoteproc loader. * * @param type - loader type * * @return - remoteproc_loader */ struct remoteproc_loader *remoteproc_loader_init(enum loader_type type) { struct remoteproc_loader *loader; /* Check for valid loader type. */ if (type >= LAST_LOADER) { return RPROC_NULL; } /* Allocate a loader handle. */ loader = env_allocate_memory(sizeof(struct remoteproc_loader)); if (!loader) { return RPROC_NULL; } /* Clear loader handle. */ env_memset(loader, 0, sizeof(struct remoteproc_loader)); /* Save loader type. */ loader->type = type; switch (type) { case ELF_LOADER: elf_loader_init(loader); break; default: /* Loader not supported. */ env_free_memory(loader); loader = RPROC_NULL; break; } return loader; }