Esempio n. 1
0
/**
 * _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;
}
Esempio n. 2
0
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;
}
Esempio n. 3
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);
}
Esempio n. 4
0
/**
 * _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);
    }
}
Esempio n. 5
0
/**
 * _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;
}
Esempio n. 6
0
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;
}
Esempio n. 7
0
/**
 * 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;
}
Esempio n. 8
0
/**
 * 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);
}
Esempio n. 9
0
/**
 * 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;
	}

}
Esempio n. 10
0
/**
 * 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;
}
Esempio n. 11
0
/**
 * 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);
	}
}
Esempio n. 12
0
/**
 * 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;
}
Esempio n. 13
0
/**
 * 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;
}