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

Commit dcd19194 authored by Karthikeyan Ramasubramanian's avatar Karthikeyan Ramasubramanian
Browse files

net: ipc_router: Move redundant definition to IPC Router Core



The helper function to load the default peripheral is defined redundantly
in multiple IPC Router transports.

Move the redundant definition of loading the default peripheral to the
IPC Router Core. Add an optional default peripheral property to enable
IPC Router to load and communicate with that peripheral.

Change-Id: I78cfb7a94e7fc71f5a95938850ecc905323bb9d1
Signed-off-by: default avatarKarthikeyan Ramasubramanian <kramasub@codeaurora.org>
parent d3846f3c
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -4,8 +4,13 @@ Required properties:
-compatible:	should be "qcom,ipc_router"
-qcom,node-id:	unique ID to identify the node in network

Optional properties:
-qcom,default-peripheral: String property to indicate the default peripheral
			  to communicate

Example:
	qcom,ipc_router {
		compatible = "qcom,ipc_router";
		qcom,node-id = <1>;
		qcom,default-peripheral = "modem";
	};
+0 −129
Original line number Diff line number Diff line
@@ -135,12 +135,8 @@ struct ipc_router_glink_xprt_config {
static DEFINE_MUTEX(glink_xprt_list_lock_lha1);
static LIST_HEAD(glink_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 *glink_xprt_wq;

static bool is_pil_loading_disabled(char *edge);

static void glink_xprt_link_state_cb(struct glink_link_state_cb_info *cb_info,
				     void *priv);
static struct glink_link_info glink_xprt_link_info = {
@@ -388,33 +384,6 @@ static void glink_xprt_qrx_intent_worker(struct work_struct *work)
	kfree(qrx_intent_work);
}

/**
* is_pil_loading_disabled() - Check if pil loading a subsystem is disabled
* @pil_edge: Remote subsystem edge name understood by PIL.
*
* @return: true if disabled, false if enabled.
*/
static bool is_pil_loading_disabled(char *pil_edge)
{
	struct ipc_router_glink_xprt *glink_xprtp;

	mutex_lock(&glink_xprt_list_lock_lha1);
	list_for_each_entry(glink_xprtp, &glink_xprt_list, list) {
		if (!strcmp(glink_xprtp->pil_edge, pil_edge)) {
			mutex_unlock(&glink_xprt_list_lock_lha1);
			return glink_xprtp->disable_pil_loading;
		}
	}
	mutex_unlock(&glink_xprt_list_lock_lha1);
	return true;
}

struct pil_vote_info {
	void *pil_handle;
	struct work_struct load_work;
	struct work_struct unload_work;
};

static void msm_ipc_unload_subsystem(struct ipc_router_glink_xprt *glink_xprtp)
{
	if (glink_xprtp->pil) {
@@ -438,104 +407,6 @@ static void *msm_ipc_load_subsystem(struct ipc_router_glink_xprt *glink_xprtp)
	return pil;
}

/**
 * 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)
{
	char *peripheral;
	struct pil_vote_info *vote_info;
	bool loading_disabled;

	vote_info = container_of(work, struct pil_vote_info, load_work);
	peripheral = "modem";
	loading_disabled = is_pil_loading_disabled(peripheral);
	if (!loading_disabled) {
		vote_info->pil_handle = subsystem_get(peripheral);
		if (IS_ERR(vote_info->pil_handle)) {
			IPC_RTR_ERR("%s: Failed to load %s\n",
				__func__, peripheral);
			vote_info->pil_handle = NULL;
		}
	} else {
		vote_info->pil_handle = NULL;
	}
}

/**
 * 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(glink_xprt_wq, &vote_info->load_work);

	return vote_info;
}
EXPORT_SYMBOL(msm_ipc_load_default_node);

/**
 * 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)
{
	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(glink_xprt_wq, &vote_info->unload_work);
	}
}
EXPORT_SYMBOL(msm_ipc_unload_default_node);

static void glink_xprt_notify_rxv(void *handle, const void *priv,
	const void *pkt_priv, void *ptr, size_t size,
	void * (*vbuf_provider)(void *iovec, size_t offset, size_t *size),
+1 −117
Original line number Diff line number Diff line
/* Copyright (c) 2011-2014, The Linux Foundation. All rights reserved.
/* Copyright (c) 2011-2015, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -133,10 +133,6 @@ 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 bool is_pil_loading_disabled(uint32_t edge);

static int msm_ipc_router_smd_get_xprt_version(
@@ -572,112 +568,6 @@ static int msm_ipc_router_smd_remote_probe(struct platform_device *pdev)
	return 0;
}

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)
{
	const char *peripheral;
	struct pil_vote_info *vote_info;
	bool loading_disabled;

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

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

/**
 * 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);

/**
 * 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)
{
	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);

/**
 * msm_ipc_router_smd_driver_register() - register SMD XPRT drivers
 *
@@ -938,12 +828,6 @@ 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,
+0 −11
Original line number Diff line number Diff line
@@ -165,15 +165,4 @@ void release_pkt(struct rr_packet *pkt);
 */
int ipc_router_peek_pkt_size(char *data);

#if defined CONFIG_MSM_IPC_ROUTER_SMD_XPRT || CONFIG_MSM_IPC_ROUTER_GLINK_XPRT
extern void *msm_ipc_load_default_node(void);

extern void msm_ipc_unload_default_node(void *pil);
#else
static inline void *msm_ipc_load_default_node(void)
{ return NULL; }

static inline void msm_ipc_unload_default_node(void *pil) { }
#endif

#endif
+164 −0
Original line number Diff line number Diff line
@@ -32,6 +32,7 @@
#include <linux/ipc_router_xprt.h>
#include <linux/kref.h>
#include <soc/qcom/subsystem_notif.h>
#include <soc/qcom/subsystem_restart.h>

#include <asm/byteorder.h>

@@ -48,6 +49,7 @@ enum {
static int msm_ipc_router_debug_mask;
module_param_named(debug_mask, msm_ipc_router_debug_mask,
		   int, S_IRUGO | S_IWUSR | S_IWGRP);
#define MODULE_NAME "ipc_router"

#define IPC_RTR_INFO_PAGES 6

@@ -193,6 +195,15 @@ static int process_resume_tx_msg(union rr_control_msg *msg,
				 struct rr_packet *pkt);
static void ipc_router_reset_conn(struct msm_ipc_router_remote_port *rport_ptr);

struct pil_vote_info {
	void *pil_handle;
	struct work_struct load_work;
	struct work_struct unload_work;
};

#define PIL_SUBSYSTEM_NAME_LEN 32
static char default_peripheral[PIL_SUBSYSTEM_NAME_LEN];

enum {
	DOWN,
	UP,
@@ -3520,6 +3531,96 @@ int msm_ipc_router_close(void)
	return 0;
}

/**
 * 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)
{
	struct pil_vote_info *vote_info;

	vote_info = container_of(work, struct pil_vote_info, load_work);
	if (strlen(default_peripheral)) {
		vote_info->pil_handle = subsystem_get(default_peripheral);
		if (IS_ERR(vote_info->pil_handle)) {
			IPC_RTR_ERR("%s: Failed to load %s\n",
				    __func__, default_peripheral);
			vote_info->pil_handle = NULL;
		}
	} else {
		vote_info->pil_handle = NULL;
	}
}

/**
 * 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(*vote_info), GFP_KERNEL);
	if (!vote_info)
		return vote_info;

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

	return vote_info;
}

/**
 * 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)
{
	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(msm_ipc_router_workqueue, &vote_info->unload_work);
	}
}

#if defined(CONFIG_DEBUG_FS)
static void dump_routing_table(struct seq_file *s)
{
@@ -3933,6 +4034,63 @@ void msm_ipc_router_xprt_notify(struct msm_ipc_router_xprt *xprt,
	queue_work(xprt_info->workqueue, &xprt_info->read_data);
}

/**
 * parse_devicetree() - parse device tree binding
 *
 * @node: pointer to device tree node
 *
 * @return: 0 on success, -ENODEV on failure.
 */
static int parse_devicetree(struct device_node *node)
{
	char *key;
	const char *peripheral = NULL;

	key = "qcom,default-peripheral";
	peripheral = of_get_property(node, key, NULL);
	if (peripheral)
		strlcpy(default_peripheral, peripheral, PIL_SUBSYSTEM_NAME_LEN);

	return 0;
}

/**
 * ipc_router_probe() - Probe the IPC Router
 *
 * @pdev: Platform device corresponding to IPC Router.
 *
 * @return: 0 on success, standard Linux error codes on error.
 *
 * This function is called when the underlying device tree driver registers
 * a platform device, mapped to IPC Router.
 */
static int ipc_router_probe(struct platform_device *pdev)
{
	int ret = 0;

	if (pdev && pdev->dev.of_node) {
		ret = parse_devicetree(pdev->dev.of_node);
		if (ret)
			IPC_RTR_ERR("%s: Failed to parse device tree\n",
				    __func__);
	}
	return ret;
}

static struct of_device_id ipc_router_match_table[] = {
	{ .compatible = "qcom,ipc_router" },
	{},
};

static struct platform_driver ipc_router_driver = {
	.probe = ipc_router_probe,
	.driver = {
		.name = MODULE_NAME,
		.owner = THIS_MODULE,
		.of_match_table = ipc_router_match_table,
	 },
};

static int msm_ipc_router_init(void)
{
	int i, ret;
@@ -3978,6 +4136,12 @@ static int msm_ipc_router_init(void)
		return -ENOMEM;
	}
	is_ipc_router_inited = true;

	ret = platform_driver_register(&ipc_router_driver);
	if (ret)
		IPC_RTR_ERR(
		"%s: ipc_router_driver register failed %d\n", __func__, ret);

	ipc_router_log_ctx_init();
	mutex_unlock(&ipc_router_init_lock);
	return ret;
Loading