コード例 #1
0
ファイル: rpmsg_core.c プロジェクト: manelkammoun/embeddedsw
/**
 * _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;
}
コード例 #2
0
ファイル: virtqueue.c プロジェクト: BadrElh/open-amp
/**
 * virtqueue_create - Creates new VirtIO queue
 *
 * @param device    - Pointer to VirtIO device
 * @param id        - VirtIO queue ID , must be unique
 * @param name      - Name of VirtIO queue
 * @param ring      - Pointer to vring_alloc_info control block
 * @param callback  - Pointer to callback function, invoked
 *                    when message is available on VirtIO queue
 * @param notify    - Pointer to notify function, used to notify
 *                    other side that there is job available for it
 * @param v_queue   - Created VirtIO queue.
 *
 * @return          - Function status
 */
int virtqueue_create(struct virtio_device *virt_dev, unsigned short id,
		     char *name, struct vring_alloc_info *ring,
		     void (*callback) (struct virtqueue * vq),
		     void (*notify) (struct virtqueue * vq),
		     struct virtqueue **v_queue)
{

	struct virtqueue *vq = VQ_NULL;
	int status = VQUEUE_SUCCESS;
	uint32_t vq_size = 0;

	VQ_PARAM_CHK(ring == VQ_NULL, status, ERROR_VQUEUE_INVLD_PARAM);
	VQ_PARAM_CHK(ring->num_descs == 0, status, ERROR_VQUEUE_INVLD_PARAM);
	VQ_PARAM_CHK(ring->num_descs & (ring->num_descs - 1), status,
		     ERROR_VRING_ALIGN);

	//TODO : Error check for indirect buffer addition

	if (status == VQUEUE_SUCCESS) {

		vq_size = sizeof(struct virtqueue)
		    + (ring->num_descs) * sizeof(struct vq_desc_extra);
		vq = (struct virtqueue *)env_allocate_memory(vq_size);

		if (vq == VQ_NULL) {
			return (ERROR_NO_MEM);
		}

		env_memset(vq, 0x00, vq_size);

		vq->vq_dev = virt_dev;
		env_strncpy(vq->vq_name, name, VIRTQUEUE_MAX_NAME_SZ);
		vq->vq_queue_index = id;
		vq->vq_alignment = ring->align;
		vq->vq_nentries = ring->num_descs;
		vq->vq_free_cnt = vq->vq_nentries;
		vq->callback = callback;
		vq->notify = notify;

		//TODO : Whether we want to support indirect addition or not.
		vq->vq_ring_size = vring_size(ring->num_descs, ring->align);
		vq->vq_ring_mem = (void *)ring->phy_addr;

		/* Initialize vring control block in virtqueue. */
		vq_ring_init(vq);

		/* Disable callbacks - will be enabled by the application
		 * once initialization is completed.
		 */
		virtqueue_disable_cb(vq);

		*v_queue = vq;

		//TODO : Need to add cleanup in case of error used with the indirect buffer addition
		//TODO: do we need to save the new queue in db based on its id
	}

	return (status);
}
コード例 #3
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;
}
コード例 #4
0
/*-----------------------------------------------------------------------------*
 *  Application specific
 *-----------------------------------------------------------------------------*/
static void Matrix_Multiply(const matrix *m, const matrix *n, matrix *r) {
	int i, j, k;

	env_memset(r, 0x0, sizeof(matrix));
	r->size = m->size;

	for (i = 0; i < m->size; ++i) {
		for (j = 0; j < n->size; ++j) {
			for (k = 0; k < r->size; ++k) {
				r->elements[i][j] += m->elements[i][k] * n->elements[k][j];
			}
		}
	}
}
コード例 #5
0
ファイル: remoteproc.c プロジェクト: PetrLukas/open-amp
/**
 * remoteproc_resource_init
 *
 * Initializes resources for remoteproc remote configuration. Only
 * remoteproc remote applications are allowed to call this function.
 *
 * @param rsc_info          - pointer to resource table info control
 * 							  block
 * @param channel_created   - callback function for channel creation
 * @param channel_destroyed - callback function for channel deletion
 * @param default_cb        - default callback for channel I/O
 * @param rproc_handle      - pointer to new remoteproc instance
 *
 * @param returns - status of function execution
 *
 */
int remoteproc_resource_init(struct rsc_table_info *rsc_info,
                rpmsg_chnl_cb_t channel_created, rpmsg_chnl_cb_t channel_destroyed,
                rpmsg_rx_cb_t default_cb, struct remote_proc** rproc_handle) {

    struct remote_proc *rproc;
    int status;

    if(!rsc_info) {
        return RPROC_ERR_PARAM;
    }

    /* Initialize environment component */
    status = env_init();
    if (status != RPROC_SUCCESS) {
        return status;
    }

    rproc = env_allocate_memory(sizeof(struct remote_proc));
    if (rproc) {
        env_memset(rproc, 0x00, sizeof(struct remote_proc));
        /* There can be only one master for remote configuration so use the
         * rsvd cpu id for creating hil proc */
        rproc->proc = hil_create_proc(HIL_RSVD_CPU_ID);
        if (rproc->proc) {
            /* Parse resource table */
            status = handle_rsc_table(rproc, rsc_info->rsc_tab, rsc_info->size);
            if (status == RPROC_SUCCESS) {
                /* Initialize RPMSG "messaging" component */
                *rproc_handle = rproc;
                status = rpmsg_init(rproc->proc->cpu_id, &rproc->rdev,
                                channel_created, channel_destroyed, default_cb,
                                RPMSG_MASTER);
            } else {
                status = RPROC_ERR_NO_RSC_TABLE;
            }
        } else {
            status = RPROC_ERR_CPU_ID;
        }
    } else {
        status = RPROC_ERR_NO_MEM;
    }

    /* Cleanup in case of error */
    if (status != RPROC_SUCCESS) {
         *rproc_handle = 0;
        (void) remoteproc_resource_deinit(rproc);
        return status;
    }
    return status;
}
コード例 #6
0
ファイル: remoteproc_loader.c プロジェクト: BadrElh/open-amp
/**
 * 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;
}
コード例 #7
0
ファイル: remoteproc.c プロジェクト: PetrLukas/open-amp
/**
 * remoteproc_init
 *
 * Initializes resources for remoteproc master configuration. Only
 * remoteproc master applications are allowed to call this function.
 *
 * @param fw_name           - name of frimware
 * @param channel_created   - callback function for channel creation
 * @param channel_destroyed - callback function for channel deletion
 * @param default_cb        - default callback for channel I/O
 * @param rproc_handle      - pointer to new remoteproc instance
 *
 * @param returns - status of function execution
 *
 */
int remoteproc_init(char *fw_name, rpmsg_chnl_cb_t channel_created,
                rpmsg_chnl_cb_t channel_destroyed, rpmsg_rx_cb_t default_cb,
                struct remote_proc** rproc_handle) {

    struct remote_proc *rproc;
    struct resource_table *rsc_table;
    unsigned int fw_addr, fw_size, rsc_size;
    int status, cpu_id;

    if (!fw_name) {
        return RPROC_ERR_PARAM;
    }

    /* Initialize environment component */
    status = env_init();
    if (status != RPROC_SUCCESS) {
        return status;
    }

    rproc = env_allocate_memory(sizeof(struct remote_proc));
    if (rproc) {
        env_memset((void *) rproc, 0x00, sizeof(struct remote_proc));
        /* Get CPU ID for the given firmware name */
        cpu_id = hil_get_cpuforfw(fw_name);
        if (cpu_id >= 0) {
            /* Create proc instance */
            rproc->proc = hil_create_proc(cpu_id);
            if (rproc->proc) {
                /* Retrieve firmware attributes */
                status = hil_get_firmware(fw_name, &fw_addr, &fw_size);
                if (!status) {
                    /* Initialize ELF loader - currently only ELF format is supported */
                    rproc->loader = remoteproc_loader_init(ELF_LOADER);
                    if (rproc->loader) {
                        /* Attach the given firmware with the ELF parser/loader */
                        status = remoteproc_loader_attach_firmware(
                                        rproc->loader, (void *) fw_addr);
                    } else {
                        status = RPROC_ERR_LOADER;
                    }
                }
            } else {
                status = RPROC_ERR_NO_MEM;
            }
        } else {
            status = RPROC_ERR_INVLD_FW;
        }
    } else {
        status = RPROC_ERR_NO_MEM;
    }

    if (!status) {
        rproc->role = RPROC_MASTER;

        /* Get resource table from firmware */
        rsc_table = remoteproc_loader_retrieve_resource_section(rproc->loader,
                        &rsc_size);
        if (rsc_table) {
            /* Parse resource table */
            status = handle_rsc_table(rproc, rsc_table, rsc_size);
        } else {
            status = RPROC_ERR_NO_RSC_TABLE;
        }
    }

    /* Cleanup in case of error */
    if (status != RPROC_SUCCESS) {
        (void) remoteproc_deinit(rproc);
        return status;
    }

    rproc->channel_created = channel_created;
    rproc->channel_destroyed = channel_destroyed;
    rproc->default_cb = default_cb;

    *rproc_handle = rproc;

    return status;
}
コード例 #8
0
ファイル: remote_device.c プロジェクト: BadrElh/open-amp
/**
 * rpmsg_rdev_init
 *
 * This function creates and initializes the remote device. The remote device
 * encapsulates virtio device.
 *
 * @param rdev              - pointer to newly created remote device
 * @param dev-id            - ID of device to create , remote cpu id
 * @param role              - role of the other device, Master or Remote
 * @param channel_created   - callback function for channel creation
 * @param channel_destroyed - callback function for channel deletion
 * @param default_cb        - default callback for channel
 *
 * @return - status of function execution
 *
 */
int rpmsg_rdev_init(struct remote_device **rdev, int dev_id, int role,
		    rpmsg_chnl_cb_t channel_created,
		    rpmsg_chnl_cb_t channel_destroyed, rpmsg_rx_cb_t default_cb)
{

	struct remote_device *rdev_loc;
	struct virtio_device *virt_dev;
	struct hil_proc *proc;
	struct proc_shm *shm;
	int status;

	/* Initialize HIL data structures for given device */
	proc = hil_create_proc(dev_id);

	if (!proc) {
		return RPMSG_ERR_DEV_ID;
	}

	/* Create software representation of remote processor. */
	rdev_loc =
	    (struct remote_device *)
	    env_allocate_memory(sizeof(struct remote_device));

	if (!rdev_loc) {
		return RPMSG_ERR_NO_MEM;
	}

	env_memset(rdev_loc, 0x00, sizeof(struct remote_device));
	status = env_create_mutex(&rdev_loc->lock, 1);

	if (status != RPMSG_SUCCESS) {

		/* Cleanup required in case of error is performed by caller */
		return status;
	}

	rdev_loc->proc = proc;
	rdev_loc->role = role;
	rdev_loc->channel_created = channel_created;
	rdev_loc->channel_destroyed = channel_destroyed;
	rdev_loc->default_cb = default_cb;

	/* Restrict the ept address - zero address can't be assigned */
	rdev_loc->bitmap[0] = 1;

	/* Initialize the virtio device */
	virt_dev = &rdev_loc->virt_dev;
	virt_dev->device = proc;
	virt_dev->func = &rpmsg_rdev_config_ops;
	if (virt_dev->func->set_features != RPMSG_NULL) {
		virt_dev->func->set_features(virt_dev, proc->vdev.dfeatures);
	}

	if (rdev_loc->role == RPMSG_REMOTE) {
		/*
		 * Since device is RPMSG Remote so we need to manage the
		 * shared buffers. Create shared memory pool to handle buffers.
		 */
		shm = hil_get_shm_info(proc);
		rdev_loc->mem_pool =
		    sh_mem_create_pool(shm->start_addr, shm->size,
				       RPMSG_BUFFER_SIZE);

		if (!rdev_loc->mem_pool) {
			return RPMSG_ERR_NO_MEM;
		}
	}

	/* Initialize channels for RPMSG Remote */
	status = rpmsg_rdev_init_channels(rdev_loc);

	if (status != RPMSG_SUCCESS) {
		return status;
	}

	*rdev = rdev_loc;

	return RPMSG_SUCCESS;
}
コード例 #9
0
ファイル: remote_device.c プロジェクト: BadrElh/open-amp
/**
 *------------------------------------------------------------------------
 * The rest of the file implements the virtio device interface as defined
 * by the virtio.h file.
 *------------------------------------------------------------------------
 */
int rpmsg_rdev_create_virtqueues(struct virtio_device *dev, int flags, int nvqs,
				 const char *names[], vq_callback * callbacks[],
				 struct virtqueue *vqs_[])
{
	struct remote_device *rdev;
	struct vring_alloc_info ring_info;
	struct virtqueue *vqs[RPMSG_MAX_VQ_PER_RDEV];
	struct proc_vring *vring_table;
	void *buffer;
	struct llist node;
	int idx, num_vrings, status;

	(void)flags;
	(void)vqs_;

	rdev = (struct remote_device *)dev;

	/* Get the vring HW info for the given virtio device */
	vring_table = hil_get_vring_info(&rdev->proc->vdev, &num_vrings);

	if (num_vrings > nvqs) {
		return RPMSG_ERR_MAX_VQ;
	}

	/* Create virtqueue for each vring. */
	for (idx = 0; idx < num_vrings; idx++) {

		INIT_VRING_ALLOC_INFO(ring_info, vring_table[idx]);

		if (rdev->role == RPMSG_REMOTE) {
			env_memset((void *)ring_info.phy_addr, 0x00,
				   vring_size(vring_table[idx].num_descs,
					      vring_table[idx].align));
		}

		status =
		    virtqueue_create(dev, idx, (char *)names[idx], &ring_info,
				     callbacks[idx], hil_vring_notify,
				     &vqs[idx]);

		if (status != RPMSG_SUCCESS) {
			return status;
		}
	}

	//FIXME - a better way to handle this , tx for master is rx for remote and vice versa.
	if (rdev->role == RPMSG_MASTER) {
		rdev->tvq = vqs[0];
		rdev->rvq = vqs[1];
	} else {
		rdev->tvq = vqs[1];
		rdev->rvq = vqs[0];
	}

	if (rdev->role == RPMSG_REMOTE) {
		for (idx = 0; ((idx < rdev->rvq->vq_nentries)
			       && (idx < rdev->mem_pool->total_buffs / 2));
		     idx++) {

			/* Initialize TX virtqueue buffers for remote device */
			buffer = sh_mem_get_buffer(rdev->mem_pool);

			if (!buffer) {
				return RPMSG_ERR_NO_BUFF;
			}

			node.data = buffer;
			node.attr = RPMSG_BUFFER_SIZE;
			node.next = RPMSG_NULL;

			env_memset(buffer, 0x00, RPMSG_BUFFER_SIZE);
			status =
			    virtqueue_add_buffer(rdev->rvq, &node, 0, 1,
						 buffer);

			if (status != RPMSG_SUCCESS) {
				return status;
			}
		}
	}

	return RPMSG_SUCCESS;
}