Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e68ad298 authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "msm: ipc: Add single-threaded workqueue for PIL voting"

parents 85221f0d 79354076
Loading
Loading
Loading
Loading
+95 −9
Original line number Diff line number Diff line
@@ -129,6 +129,10 @@ static struct delayed_work ipc_router_smd_xprt_probe_work;
static DEFINE_MUTEX(smd_remote_xprt_list_lock_lha1);
static LIST_HEAD(smd_remote_xprt_list);

static void pil_vote_load_worker(struct work_struct *work);
static void pil_vote_unload_worker(struct work_struct *work);
static struct workqueue_struct *pil_vote_wq;

static int msm_ipc_router_smd_get_xprt_version(
	struct msm_ipc_router_xprt *xprt)
{
@@ -545,28 +549,104 @@ static int msm_ipc_router_smd_remote_probe(struct platform_device *pdev)
	return 0;
}

void *msm_ipc_load_default_node(void)
struct pil_vote_info {
	void *pil_handle;
	struct work_struct load_work;
	struct work_struct unload_work;
};

/**
 * pil_vote_load_worker() - Process vote to load the modem
 *
 * @work: Work item to process
 *
 * This function is called to process votes to load the modem that have been
 * queued by msm_ipc_load_default_node().
 */
static void pil_vote_load_worker(struct work_struct *work)
{
	void *pil = NULL;
	const char *peripheral;
	struct pil_vote_info *vote_info;

	vote_info = container_of(work, struct pil_vote_info, load_work);
	peripheral = smd_edge_to_pil_str(SMD_APPS_MODEM);

	if (!IS_ERR_OR_NULL(peripheral) && !strcmp(peripheral, "modem")) {
		pil = subsystem_get(peripheral);
		if (IS_ERR(pil)) {
		vote_info->pil_handle = subsystem_get(peripheral);
		if (IS_ERR(vote_info->pil_handle)) {
			pr_err("%s: Failed to load %s\n",
				__func__, peripheral);
			pil = NULL;
			vote_info->pil_handle = NULL;
		}
	}
	return pil;
}

/**
 * pil_vote_unload_worker() - Process vote to unload the modem
 *
 * @work: Work item to process
 *
 * This function is called to process votes to unload the modem that have been
 * queued by msm_ipc_unload_default_node().
 */
static void pil_vote_unload_worker(struct work_struct *work)
{
	struct pil_vote_info *vote_info;

	vote_info = container_of(work, struct pil_vote_info, unload_work);

	if (vote_info->pil_handle) {
		subsystem_put(vote_info->pil_handle);
		vote_info->pil_handle = NULL;
	}
	kfree(vote_info);
}

/**
 * msm_ipc_load_default_node() - Queue a vote to load the modem.
 *
 * @return: PIL vote info structure on success, NULL on failure.
 *
 * This function places a work item that loads the modem on the
 * single-threaded workqueue used for processing PIL votes to load
 * or unload the modem.
 */
void *msm_ipc_load_default_node(void)
{
	struct pil_vote_info *vote_info;

	vote_info = kmalloc(sizeof(struct pil_vote_info), GFP_KERNEL);
	if (vote_info == NULL) {
		pr_err("%s: mem alloc for pil_vote_info failed\n", __func__);
		return NULL;
	}

	INIT_WORK(&vote_info->load_work, pil_vote_load_worker);
	queue_work(pil_vote_wq, &vote_info->load_work);

	return vote_info;
}
EXPORT_SYMBOL(msm_ipc_load_default_node);

void msm_ipc_unload_default_node(void *pil)
/**
 * msm_ipc_unload_default_node() - Queue a vote to unload the modem.
 *
 * @pil_vote: PIL vote info structure, containing the PIL handle
 * and work structure.
 *
 * This function places a work item that unloads the modem on the
 * single-threaded workqueue used for processing PIL votes to load
 * or unload the modem.
 */
void msm_ipc_unload_default_node(void *pil_vote)
{
	if (pil)
		subsystem_put(pil);
	struct pil_vote_info *vote_info;

	if (pil_vote) {
		vote_info = (struct pil_vote_info *) pil_vote;
		INIT_WORK(&vote_info->unload_work, pil_vote_unload_worker);
		queue_work(pil_vote_wq, &vote_info->unload_work);
	}
}
EXPORT_SYMBOL(msm_ipc_unload_default_node);

@@ -823,6 +903,12 @@ static int __init msm_ipc_router_smd_xprt_init(void)
		return rc;
	}

	pil_vote_wq = create_singlethread_workqueue("pil_vote_wq");
	if (IS_ERR_OR_NULL(pil_vote_wq)) {
		pr_err("%s: create_singlethread_workqueue failed\n", __func__);
		return -EFAULT;
	}

	INIT_DELAYED_WORK(&ipc_router_smd_xprt_probe_work,
					ipc_router_smd_xprt_probe_worker);
	schedule_delayed_work(&ipc_router_smd_xprt_probe_work,
+1 −1
Original line number Diff line number Diff line
@@ -67,7 +67,7 @@ enum {
struct msm_ipc_sock {
	struct sock sk;
	struct msm_ipc_port *port;
	void *default_pil;
	void *default_node_vote_info;
};

/**
+8 −9
Original line number Diff line number Diff line
@@ -303,7 +303,6 @@ int msm_ipc_router_bind(struct socket *sock, struct sockaddr *uaddr,
	struct sock *sk = sock->sk;
	struct msm_ipc_port *port_ptr;
	int ret;
	void *pil;

	if (!sk)
		return -EINVAL;
@@ -333,8 +332,9 @@ int msm_ipc_router_bind(struct socket *sock, struct sockaddr *uaddr,
	if (!port_ptr)
		return -ENODEV;

	pil = msm_ipc_load_default_node();
	msm_ipc_sk(sk)->default_pil = pil;
	if (!msm_ipc_sk(sk)->default_node_vote_info)
		msm_ipc_sk(sk)->default_node_vote_info =
			msm_ipc_load_default_node();
	lock_sock(sk);

	ret = msm_ipc_router_register_server(port_ptr, &addr->address);
@@ -445,7 +445,6 @@ static int msm_ipc_router_ioctl(struct socket *sock,
	unsigned int n;
	size_t srv_info_sz = 0;
	int ret;
	void *pil;

	if (!sk)
		return -EINVAL;
@@ -473,8 +472,10 @@ static int msm_ipc_router_ioctl(struct socket *sock,
		break;

	case IPC_ROUTER_IOCTL_LOOKUP_SERVER:
		pil = msm_ipc_load_default_node();
		msm_ipc_sk(sk)->default_pil = pil;
		if (!msm_ipc_sk(sk)->default_node_vote_info)
			msm_ipc_sk(sk)->default_node_vote_info =
				msm_ipc_load_default_node();

		ret = copy_from_user(&server_arg, (void *)arg,
				     sizeof(server_arg));
		if (ret) {
@@ -568,13 +569,11 @@ static int msm_ipc_router_close(struct socket *sock)
{
	struct sock *sk = sock->sk;
	struct msm_ipc_port *port_ptr = msm_ipc_sk_port(sk);
	void *pil = msm_ipc_sk(sk)->default_pil;
	int ret;

	lock_sock(sk);
	ret = msm_ipc_router_close_port(port_ptr);
	if (pil)
		msm_ipc_unload_default_node(pil);
	msm_ipc_unload_default_node(msm_ipc_sk(sk)->default_node_vote_info);
	release_sock(sk);
	sock_put(sk);
	sock->sk = NULL;