Esempio n. 1
0
/**
 * rpmsg_rdev_init_channels
 *
 * This function is only applicable to RPMSG remote. It obtains channel IDs
 * from the HIL and creates RPMSG channels corresponding to each ID.
 *
 * @param rdev - pointer to remote device
 *
 * @return  - status of function execution
 *
 */
int rpmsg_rdev_init_channels(struct remote_device *rdev)
{
	struct rpmsg_channel *rp_chnl;
	struct proc_chnl *chnl_info;
	int num_chnls, idx;

	if (rdev->role == RPMSG_MASTER) {

		chnl_info = hil_get_chnl_info(rdev->proc, &num_chnls);
		for (idx = 0; idx < num_chnls; idx++) {

			rp_chnl =
			    _rpmsg_create_channel(rdev, chnl_info[idx].name,
						  0x00, RPMSG_NS_EPT_ADDR);
			if (!rp_chnl) {
				return RPMSG_ERR_NO_MEM;
			}

			rp_chnl->rp_ept =
			    rpmsg_create_ept(rp_chnl, rdev->default_cb, rdev,
					     RPMSG_ADDR_ANY);

			if (!rp_chnl->rp_ept) {
				return RPMSG_ERR_NO_MEM;
			}

			rp_chnl->src = rp_chnl->rp_ept->addr;
		}
	}

	return RPMSG_SUCCESS;
}
int alloc_rpmsg_instance(struct rpmsg_channel *rpdev,
				struct rpmsg_instance **pInstance)
{
	int ret = 0;
	struct rpmsg_instance *instance;

	dev_info(&rpdev->dev, "Allocating rpmsg_instance\n");

	instance = kzalloc(sizeof(*instance), GFP_KERNEL);
	if (!instance) {
		ret = -ENOMEM;
		dev_err(&rpdev->dev, "kzalloc rpmsg_instance failed\n");
		goto alloc_out;
	}

	instance->rpdev = rpdev;

	instance->tx_msg = kzalloc(sizeof(struct tx_ipc_msg), GFP_KERNEL);
	if (!instance->tx_msg) {
		ret = -ENOMEM;
		dev_err(&rpdev->dev, "kzalloc instance tx_msg failed\n");
		goto error_tx_msg_create;
	}

	instance->rx_msg = kzalloc(sizeof(struct rx_ipc_msg), GFP_KERNEL);
	if (!instance->rx_msg) {
		ret = -ENOMEM;
		dev_err(&rpdev->dev, "kzalloc instance rx_msg failed\n");
		goto error_rx_msg_create;
	}

	instance->endpoint = rpmsg_create_ept(rpdev, rpmsg_recv_cb,
							instance,
							RPMSG_ADDR_ANY);
	if (!instance->endpoint) {
		dev_err(&rpdev->dev, "create instance endpoint failed\n");
		ret = -ENOMEM;
		goto error_endpoint_create;
	}

	goto alloc_out;

error_endpoint_create:
	kfree(instance->rx_msg);
	instance->rx_msg = NULL;
error_rx_msg_create:
	kfree(instance->tx_msg);
	instance->tx_msg = NULL;
error_tx_msg_create:
	kfree(instance);
	instance = NULL;
alloc_out:
	*pInstance = instance;
	return ret;

}
Esempio n. 3
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);
                }
            }
        }
    }
}
Esempio n. 4
0
static int init_neo_proxy(struct _rpmsg_params *local, struct rpmsg_channel *rpmsg_chnl)
{
    int status =0;

    /* Initialize mutex */
    mutex_init(&local->sync_lock);

    /* Initialize wait queue head that provides blocking rx for userspace */
    init_waitqueue_head(&local->usr_wait_q);

    /* Allocate kfifo for rpmsg */
    status = kfifo_alloc(&local->rpmsg_kfifo, RPMSG_KFIFO_SIZE, GFP_KERNEL);
    kfifo_reset(&local->rpmsg_kfifo);

    if (status)
    {
        pr_err("ERROR: %s %d Failed to run kfifo_alloc. rc=%d\n", __FUNCTION__, __LINE__,status);
        goto error0;
    }

    local->rpmsg_chnl = rpmsg_chnl;
    local->block_flag = 0;

    local->ept = rpmsg_create_ept(local->rpmsg_chnl,
                                  rpmsg_proxy_dev_ept_cb,
                                  local,
                                  local->endpt);
    if (!local->ept)
    {
        pr_err("ERROR: %s %d Failed to create endpoint.\n",  __FUNCTION__, __LINE__);
        goto error1;
    }
    goto out;

//TCM        rpmsg_destroy_ept(local->ept);
error1:
    kfifo_free(&local->rpmsg_kfifo);
error0:

    pr_err("ERROR: %s %d\n",  __FUNCTION__, __LINE__);
    return -ENODEV;
out:
    pr_info("%s %d\n",  __FUNCTION__, __LINE__);
    return 0;
}
Esempio n. 5
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;
}
Esempio n. 6
0
/**
 * rpmsg_create_channel
 *
 * This function provides facility to create channel dynamically. It sends
 * Name Service announcement to remote device to let it know about the channel
 * creation. There must be an active communication among the cores (or atleast
 * one rpmsg channel must already exist) before using this API to create new
 * channels.
 *
 * @param rdev - pointer to remote device
 * @param name - channel name
 *
 * @return - pointer to new rpmsg channel
 *
 */
struct rpmsg_channel *rpmsg_create_channel(struct remote_device *rdev,
                char *name) {

    struct rpmsg_channel *rp_chnl;
    struct rpmsg_endpoint *rp_ept;

    if (!rdev || !name) {
        return RPMSG_NULL ;
    }

    /* Create channel instance */
    rp_chnl = _rpmsg_create_channel(rdev, name, RPMSG_NS_EPT_ADDR,
                    RPMSG_NS_EPT_ADDR);
    if (!rp_chnl) {
        return RPMSG_NULL ;
    }

    /* Create default endpoint for the channel */
    rp_ept = rpmsg_create_ept(rp_chnl , rdev->default_cb, rdev,
                    RPMSG_ADDR_ANY);

    if (!rp_ept) {
        _rpmsg_delete_channel(rp_chnl);
        return RPMSG_NULL;
    }

    rp_chnl->rp_ept = rp_ept;
    rp_chnl->src = rp_ept->addr;
    rp_chnl->state = RPMSG_CHNL_STATE_NS;

    /* Notify the application of channel creation event */
    if (rdev->channel_created) {
        rdev->channel_created(rp_chnl);
    }

    /* Send NS announcement to remote processor */
    rpmsg_send_ns_message(rdev, rp_chnl, RPMSG_NS_CREATE);

    return rp_chnl;
}
Esempio n. 7
0
int rpmsg_retarget_init(struct rpmsg_channel *rp_chnl, rpc_shutdown_cb cb) {
	int status;

	/* Allocate memory for rpc control block */
	rpc_data = (struct _rpc_data*) env_allocate_memory(
				sizeof(struct _rpc_data));

	/* Create a mutex for synchronization */
	status = env_create_mutex(&rpc_data->rpc_lock, 1);

	/* Create a mutex for synchronization */
	status = env_create_sync_lock(&rpc_data->sync_lock, LOCKED);

	/* Create a endpoint to handle rpc response from master */
	rpc_data->rpmsg_chnl = rp_chnl;
	rpc_data->rp_ept = rpmsg_create_ept(rpc_data->rpmsg_chnl, rpc_cb,
						RPMSG_NULL, PROXY_ENDPOINT);
	rpc_data->rpc = env_allocate_memory(RPC_BUFF_SIZE);
	rpc_data->rpc_response = env_allocate_memory(RPC_BUFF_SIZE);
	rpc_data->shutdown_cb = cb;

	return status;
}
Esempio n. 8
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;
}
Esempio n. 9
0
static void rpmsg_channel_created(struct rpmsg_channel *rp_chnl)
{
	app_rp_chnl = rp_chnl;
	rp_ept = rpmsg_create_ept(rp_chnl, rpmsg_read_cb, RPMSG_NULL,
				RPMSG_ADDR_ANY);
}
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;
}
Esempio n. 11
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;

}
Esempio n. 12
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;
}
Esempio n. 13
0
int rpmsg_neo_ethernet(struct rpmsg_channel *rpmsg_chnl,
                       rpmsg_neo_remove_t *remove_func  )
{

    int result, ret = -ENOMEM;
    struct _rpmsg_dev_params *priv;
    
    pr_info("INFO:%s %d\n", __FUNCTION__, __LINE__);
    
    *remove_func = rpmsg_neo_ethernet_remove;

    rpmsg_netdev = alloc_etherdev(sizeof(struct _rpmsg_dev_params));
    if (rpmsg_netdev ==NULL) {
        pr_err("ERROR: %s %s %d\n", __FILE__, __FUNCTION__, __LINE__);
        return ret;
    }
    
    rpmsg_netdev->ethtool_ops    = &rpmsg_ethtool_ops;
    rpmsg_netdev->netdev_ops = &rpmsg_netdev_ops;
    rpmsg_netdev->mtu            = ETHERNET_MTU_SIZE;

    priv = netdev_priv(rpmsg_netdev);
    memset(priv, 0, sizeof(*priv));

    pr_info("INFO: %s %s %d\n", __FILE__, __FUNCTION__, __LINE__);

    priv->dev = rpmsg_netdev;

    rpmsg_read_mac_addr(rpmsg_netdev);

  // call 
    priv->rpmsg_chnl = rpmsg_chnl;
    priv->endpt = ETHERNET_ENDPOINT;
    
   spin_lock_init(&priv->lock);

    
    priv->ept = rpmsg_create_ept(priv->rpmsg_chnl,
                                 rpmsg_ethernet_dev_ept_cb,
                                  priv,
                                  priv->endpt);


    if (!priv->ept)
    {
      pr_err("ERROR: %s %d Failed to create endpoint.\n",  __FUNCTION__, __LINE__);
        goto out;
    }

    result = register_netdev(rpmsg_netdev);
    if (result) {
        pr_err("ERROR: %s %s %d\n", __FILE__, __FUNCTION__, __LINE__);

    } else {
           
        ret = 0;
        pr_info("INFO: %s %s %d\n", __FILE__, __FUNCTION__, __LINE__);
    }

    return 0;

out:
    if(rpmsg_netdev) {
        pr_err("ERROR: %s %s %d\n", __FILE__, __FUNCTION__, __LINE__);
        return -1;
    }

    return ret;
}