Exemplo n.º 1
0
/**
 * rpmsg_delete_channel
 *
 * Deletes the given RPMSG channel. The channel must first be created with the
 * rpmsg_create_channel API.
 *
 * @param rp_chnl - pointer to rpmsg channel to delete
 *
 */
void rpmsg_delete_channel(struct rpmsg_channel *rp_chnl) {

    struct remote_device *rdev;

    if (!rp_chnl) {
        return;
    }

    rdev = rp_chnl->rdev;

    if (rp_chnl->state > RPMSG_CHNL_STATE_IDLE) {
        /* Notify the other processor that channel no longer exists */
        rpmsg_send_ns_message(rdev, rp_chnl, RPMSG_NS_DESTROY);
    }

    /* Notify channel deletion to application */
    if (rdev->channel_destroyed) {
        rdev->channel_destroyed(rp_chnl);
    }

    rpmsg_destroy_ept(rp_chnl->rp_ept);
    _rpmsg_delete_channel(rp_chnl);

    return;
}
Exemplo n.º 2
0
static int rpmsg_dev_remove(struct device *dev)
{
	struct rpmsg_channel *rpdev = to_rpmsg_channel(dev);
	struct rpmsg_driver *rpdrv = to_rpmsg_driver(rpdev->dev.driver);
	struct virtproc_info *vrp = rpdev->vrp;
	int err = 0;

	/* tell remote processor's name service we're removing this channel */
	if (rpdev->announce &&
			virtio_has_feature(vrp->vdev, VIRTIO_RPMSG_F_NS)) {
		struct rpmsg_ns_msg nsm;

		strncpy(nsm.name, rpdev->id.name, RPMSG_NAME_SIZE);
		nsm.addr = rpdev->src;
		nsm.flags = RPMSG_NS_DESTROY;

		err = rpmsg_sendto(rpdev, &nsm, sizeof(nsm), RPMSG_NS_ADDR);
		if (err)
			dev_err(dev, "failed to announce service %d\n", err);
	}

	rpdrv->remove(rpdev);

	rpmsg_destroy_ept(rpdev->ept);

	return err;
}
Exemplo n.º 3
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;
}
Exemplo n.º 4
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);
}
Exemplo n.º 5
0
/**
 * rpmsg_ns_callback
 *
 * This callback handles name service announcement from the remote device
 * and creates/deletes rpmsg channels.
 *
 * @param server_chnl - pointer to server channel control block.
 * @param data        - pointer to received messages
 * @param len         - length of received data
 * @param priv        - any private data
 * @param src         - source address
 *
 * @return void
 */
void rpmsg_ns_callback(struct rpmsg_channel *server_chnl, void *data, int len,
                void *priv, unsigned long src) {
    struct remote_device *rdev;
    struct rpmsg_channel *rp_chnl;
    struct rpmsg_ns_msg *ns_msg;
    struct llist *node;

    rdev = (struct remote_device *) priv;

    //FIXME: This assumes same name string size for channel name both on master
    //and remote. If this is not the case then we will have to parse the
    //message contents.

    ns_msg = (struct rpmsg_ns_msg *) data;
    ns_msg->name[len - 1] = '\0';

    if (ns_msg->flags & RPMSG_NS_DESTROY) {
        node = rpmsg_rdev_get_chnl_node_from_id(rdev, ns_msg->name);
        if (node) {
            rp_chnl = (struct rpmsg_channel *) node->data;
            if (rdev->channel_destroyed) {
                rdev->channel_destroyed(rp_chnl);
            }

            rpmsg_destroy_ept(rp_chnl->rp_ept);
            _rpmsg_delete_channel(rp_chnl);
        }
    } else {
        rp_chnl = _rpmsg_create_channel(rdev, ns_msg->name, 0x00, ns_msg->addr);
        if (rp_chnl) {
            rp_chnl->state = RPMSG_CHNL_STATE_ACTIVE;
            /* Create default endpoint for channel */
            rp_chnl->rp_ept = rpmsg_create_ept(rp_chnl, rdev->default_cb, rdev,
                            RPMSG_ADDR_ANY);
            
            if (rp_chnl->rp_ept) {
                rp_chnl->src = rp_chnl->rp_ept->addr;
                /*
                 * Echo back the NS message to remote in order to
                 * complete the connection stage. Remote will know the endpoint
                 * address from this point onward which will enable it to send
                 * message without waiting for any application level message from
                 * master.
                 */
                rpmsg_send(rp_chnl,data,len);
                if (rdev->channel_created) {
                    rdev->channel_created(rp_chnl);
                }
            }
        }
    }
}
Exemplo n.º 6
0
static int rpmsg_dev_remove(struct device *dev)
{
	struct rpmsg_device *rpdev = to_rpmsg_device(dev);
	struct rpmsg_driver *rpdrv = to_rpmsg_driver(rpdev->dev.driver);
	int err = 0;

	if (rpdev->ops->announce_destroy)
		err = rpdev->ops->announce_destroy(rpdev);

	rpdrv->remove(rpdev);

	if (rpdev->ept)
		rpmsg_destroy_ept(rpdev->ept);

	return err;
}
void free_rpmsg_instance(struct rpmsg_channel *rpdev,
				struct rpmsg_instance **pInstance)
{
	struct rpmsg_instance *instance = *pInstance;

	mutex_lock(&instance->instance_lock);
	rpmsg_destroy_ept(instance->endpoint);
	kfree(instance->tx_msg);
	instance->tx_msg = NULL;
	kfree(instance->rx_msg);
	instance->rx_msg = NULL;
	mutex_unlock(&instance->instance_lock);
	kfree(instance);
	*pInstance = NULL;
	dev_info(&rpdev->dev, "Freeing rpmsg device\n");
}
Exemplo n.º 8
0
void rpmsg_deinit_vdev(struct rpmsg_virtio_device *rvdev)
{
	struct metal_list *node;
	struct rpmsg_device *rdev;
	struct rpmsg_endpoint *ept;

	rdev = &rvdev->rdev;
	while (!metal_list_is_empty(&rdev->endpoints)) {
		node = rdev->endpoints.next;
		ept = metal_container_of(node, struct rpmsg_endpoint, node);
		rpmsg_destroy_ept(ept);
	}

	rvdev->rvq = 0;
	rvdev->svq = 0;

	metal_mutex_deinit(&rdev->lock);
}
Exemplo n.º 9
0
static int rpmsg_dev_probe(struct device *dev)
{
	struct rpmsg_channel *rpdev = to_rpmsg_channel(dev);
	struct rpmsg_driver *rpdrv = to_rpmsg_driver(rpdev->dev.driver);
	struct virtproc_info *vrp = rpdev->vrp;
	struct rpmsg_endpoint *ept;
	int err;

	ept = rpmsg_create_ept(rpdev, rpdrv->callback, NULL, rpdev->src);
	if (!ept) {
		dev_err(dev, "failed to create endpoint\n");
		err = -ENOMEM;
		goto out;
	}

	rpdev->ept = ept;
	rpdev->src = ept->addr;

	err = rpdrv->probe(rpdev);
	if (err) {
		dev_err(dev, "%s: failed: %d\n", __func__, err);
		rpmsg_destroy_ept(ept);
		goto out;
	}

	/* need to tell remote processor's name service about this channel ? */
	if (rpdev->announce &&
			virtio_has_feature(vrp->vdev, VIRTIO_RPMSG_F_NS)) {
		struct rpmsg_ns_msg nsm;

		strncpy(nsm.name, rpdev->id.name, RPMSG_NAME_SIZE);
		nsm.addr = rpdev->src;
		nsm.flags = RPMSG_NS_CREATE;

		err = rpmsg_sendto(rpdev, &nsm, sizeof(nsm), RPMSG_NS_ADDR);
		if (err)
			dev_err(dev, "failed to announce service %d\n", err);
	}

out:
	return err;
}
Exemplo n.º 10
0
/*
 * when an rpmsg driver is probed with a channel, we seamlessly create
 * it an endpoint, binding its rx callback to a unique local rpmsg
 * address.
 *
 * if we need to, we also announce about this channel to the remote
 * processor (needed in case the driver is exposing an rpmsg service).
 */
static int rpmsg_dev_probe(struct device *dev)
{
	struct rpmsg_device *rpdev = to_rpmsg_device(dev);
	struct rpmsg_driver *rpdrv = to_rpmsg_driver(rpdev->dev.driver);
	struct rpmsg_channel_info chinfo = {};
	struct rpmsg_endpoint *ept = NULL;
	int err;

	if (rpdrv->callback) {
		strncpy(chinfo.name, rpdev->id.name, RPMSG_NAME_SIZE);
		chinfo.src = rpdev->src;
		chinfo.dst = RPMSG_ADDR_ANY;

		ept = rpmsg_create_ept(rpdev, rpdrv->callback, NULL, chinfo);
		if (!ept) {
			dev_err(dev, "failed to create endpoint\n");
			err = -ENOMEM;
			goto out;
		}

		rpdev->ept = ept;
		rpdev->src = ept->addr;
	}

	err = rpdrv->probe(rpdev);
	if (err) {
		dev_err(dev, "%s: failed: %d\n", __func__, err);
		if (ept)
			rpmsg_destroy_ept(ept);
		goto out;
	}

	if (ept && rpdev->ops->announce_create)
		err = rpdev->ops->announce_create(rpdev);
out:
	return err;
}
Exemplo n.º 11
0
static void rpmsg_channel_deleted(struct rpmsg_channel *rp_chnl)
{
	rpmsg_destroy_ept(rp_ept);
}
Exemplo n.º 12
0
static void rpmsg_func_test_kern_app_remove(struct rpmsg_channel *rpdev)
{
	rpmsg_destroy_ept(ept);
}
Exemplo n.º 13
0
static int rpmsg_func_test_kern_app_probe(struct rpmsg_channel *rpdev)
{
	int	err;
	int   uninit = 0;
	struct ept_cmd_data *ept_data;
	struct command *cmd;

	pr_err("\r\nFunc Test Suite Start! \r\n");

	/* Create endpoint for remote channel and register rx callabck */
	ept = rpmsg_create_ept(rpdev, rpmsg_func_test_default_rx_cb, 0,
				RPMSG_ADDR_ANY);

	if (!ept) {
		pr_err(" Endpoint creation for failed!\r\n");
		return -ENOMEM;
	}

	/* Send init message to complete the connection loop */
	err = rpmsg_send_offchannel(rpdev, ept->addr, rpdev->dst,
				init_msg, sizeof(init_msg));

	if (err) {
		pr_err(" Init message send failed!\r\n");
		return err;
	}

	/* Send a message to start tests */
	err = rpmsg_send_offchannel(rpdev, ept->addr, rpdev->dst,
				start_test, sizeof(start_test));

	if (err) {
		pr_err("Test start command failed!\r\n");
		return err;
	}


	while (1) {
		/* Wait till the data is echoed back. */
		wait_event_interruptible(wait_queue, flag != 0);
		flag = 0;

		cmd = (struct command *)r_buffer;

		if (cmd->comm_start == CMD_START) {
			unsigned int cm_code = cmd->comm_code;
			void *data = cmd->data;

			switch (cm_code) {
			case CREATE_EPT:
				ept_data = (struct ept_cmd_data *)data;
				rp_ept = rpmsg_create_ept(rpdev,
						rpmsg_func_test_ept_rx_cb,
						0, ept_data->dst);
				if (rp_ept)
					/* Send data back to ack. */
					rpmsg_send_offchannel(rpdev,
							ept->addr, rpdev->dst,
							r_buffer, data_length);
				break;
			case DELETE_EPT:
				rpmsg_destroy_ept(rp_ept);
				rpmsg_send_offchannel(rpdev, ept->addr,
							rpdev->dst,
							r_buffer, data_length);
				break;
			case CREATE_CHNL:
				break;
			case DELETE_CHNL:
				rpmsg_send_offchannel(rpdev, ept->addr,
							rpdev->dst,
							r_buffer, data_length);
				uninit = 1;
				break;
			case QUERY_FW_NAME:
				rpmsg_send_offchannel(rpdev, ept->addr,
						rpdev->dst,
						&firmware_name[0],
						strlen(firmware_name)+1);
				break;
			case PRINT_RESULT:
				pr_err("%s", data);
				rpmsg_send_offchannel(rpdev, ept->addr,
							rpdev->dst,
							r_buffer, data_length);
				break;
			default:
				rpmsg_send_offchannel(rpdev, ept->addr,
							rpdev->dst,
							r_buffer, data_length);
				break;
			}
		} else
			rpmsg_send_offchannel(rpdev, ept->addr, rpdev->dst,
						r_buffer, data_length);

		if (uninit)
			break;
	}

	call_usermodehelper(shutdown_argv[0], shutdown_argv, NULL, UMH_NO_WAIT);

	return 0;
}
Exemplo n.º 14
0
int rpmsg_neo_tty(struct rpmsg_channel *rpmsg_chnl,rpmsg_neo_remove_t *remove_func )
{
    int err = 0;
    struct rpmsgtty_port *cport = &rpmsg_tty_port;

    *remove_func =  rpmsg_neo_tty_remove;

    memset(cport, 0, sizeof(rpmsg_tty_port));

    cport->rpmsg_chnl = rpmsg_chnl;
    cport->endpt = RPMSG_TTY_ENPT;

    cport->ept = rpmsg_create_ept(cport->rpmsg_chnl,
                                  rpmsg_tty_cb,
                                  cport,
                                  cport->endpt);
    if (!cport->ept)
    {
        pr_err("ERROR: %s %s %d Failed to create proxy service endpoint.\n", __FILE__, __FUNCTION__, __LINE__);
        err = -1;
        goto error0;
    }
    
    rpmsgtty_driver = tty_alloc_driver(1, TTY_DRIVER_RESET_TERMIOS |
			TTY_DRIVER_REAL_RAW |
			TTY_DRIVER_UNNUMBERED_NODE);
    if (IS_ERR(rpmsgtty_driver))
    {
        pr_err("ERROR:%s %d Failed to alloc tty\n", __FUNCTION__, __LINE__);
        rpmsg_destroy_ept(cport->ept);
        return PTR_ERR(rpmsgtty_driver);
    }
         
    spin_lock_init(&cport->rx_lock);
    cport->port.low_latency = cport->port.flags | ASYNC_LOW_LATENCY;
    
    tty_port_init(&cport->port);
    cport->port.ops = &rpmsgtty_port_ops;
    
    rpmsgtty_driver->driver_name = "ttyrpmsg";
    rpmsgtty_driver->name = "ttyrpmsg";
    rpmsgtty_driver->major = TTYAUX_MAJOR;
    rpmsgtty_driver->minor_start = 4;
    rpmsgtty_driver->type = TTY_DRIVER_TYPE_CONSOLE;
    rpmsgtty_driver->init_termios = tty_std_termios;
  //  rpmsgtty_driver->init_termios.c_oflag = OPOST | OCRNL | ONOCR | ONLRET;
rpmsgtty_driver->init_termios.c_cflag |= CLOCAL;

    tty_set_operations(rpmsgtty_driver, &imxrpmsgtty_ops);
    tty_port_link_device(&cport->port, rpmsgtty_driver, 0);
        
    err = tty_register_driver(rpmsgtty_driver);
    if (err < 0)
    {
        pr_err("Couldn't install rpmsg tty driver: err %d\n", err);
        goto error;
    }
    else
    {
        pr_info("Install rpmsg tty driver!\n");
    }

    return 0;

error:
    put_tty_driver(rpmsgtty_driver);
    tty_port_destroy(&cport->port);
    rpmsgtty_driver = NULL;
    rpmsg_destroy_ept(cport->ept);


error0:
    return err;

}
Exemplo n.º 15
0
int main()
{
	struct remote_proc *proc;
	int uninit = 0;
	struct ept_cmd_data *ept_data;

#ifdef ZYNQ7_BAREMETAL
	/* Switch to System Mode */
	SWITCH_TO_SYS_MODE();
#endif

	/* Initialize HW system components */
	init_system();

	rsc_info.rsc_tab = (struct resource_table *)&resources;
	rsc_info.size = sizeof(resources);

	/* This API creates the virtio devices for this remote node and initializes
	   other relevant resources defined in the resource table */
	remoteproc_resource_init(&rsc_info, rpmsg_channel_created,
				 rpmsg_channel_deleted, rpmsg_read_default_cb,
				 &proc);

	for (;;) {

		if (intr_flag) {
			struct command *cmd = (struct command *)r_buffer;
			if (cmd->comm_start == CMD_START) {
				unsigned int cm_code = cmd->comm_code;
				void *data = cmd->data;

				switch (cm_code) {
				case CREATE_EPT:
					ept_data = (struct ept_cmd_data *)data;
					rp_ept =
					    rpmsg_create_ept(app_rp_chnl,
							     rpmsg_read_ept_cb,
							     RPMSG_NULL,
							     ept_data->dst);
					if (rp_ept) {
						/* Send data back to ack. */
						rpmsg_sendto(app_rp_chnl,
							     r_buffer, Len,
							     Src);
					}
					break;
				case DELETE_EPT:
					rpmsg_destroy_ept(rp_ept);
					rpmsg_sendto(app_rp_chnl, r_buffer, Len,
						     Src);

					break;
				case CREATE_CHNL:
					break;
				case DELETE_CHNL:
					rpmsg_sendto(app_rp_chnl, r_buffer, Len,
						     Src);
					remoteproc_resource_deinit(proc);
					uninit = 1;
					break;
				case QUERY_FW_NAME:
					rpmsg_send(app_rp_chnl,
						   &firmware_name[0],
						   strlen(firmware_name) + 1);
					break;
				default:
					rpmsg_sendto(app_rp_chnl, r_buffer, Len,
						     Src);
					break;
				}
			} else {
				rpmsg_sendto(app_rp_chnl, r_buffer, Len, Src);
			}
			intr_flag = 0;
			if (uninit)
				break;
		}

		sleep();
	}

	return 0;
}