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

Commit 490a42a7 authored by Chris Lew's avatar Chris Lew Committed by Gerrit - the friendly Code Review server
Browse files

soc: qcom: glink: Add support to set affinities



There is a need to pin the interrupts and rx worker thread to a
specific cpu set for power and performance. Add support to define
the cpu set in device tree. This change does not include any hotplug
support.

Change-Id: Ibe651e987e72f5119e9e8453d87fa8059219ec1f
Signed-off-by: default avatarChris Lew <clew@codeaurora.org>
parent 07609e0f
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -11,6 +11,7 @@ Required properties:
-label : the name of the subsystem this link connects to

Optional properties:
-cpu-affinity: Cores to pin the interrupt and receiving work thread to.
-qcom,qos-config: Reference to the qos configuration elements.It depends on
		ramp-time.
-qcom,ramp-time: Worst case time in microseconds to transition to this power
@@ -36,6 +37,7 @@ Example:
		qcom,irq-mask = <0x1000>;
		interrupts = <0 25 1>;
		label = "lpass";
		cpu-affinity = <1 2>;
		qcom,qos-config = <&glink_qos_adsp>;
		qcom,ramp-time = <0x10>,
				     <0x20>,
+1 −0
Original line number Diff line number Diff line
@@ -4070,6 +4070,7 @@ int glink_core_register_transport(struct glink_transport_if *if_ptr,
		kfree(xprt_ptr);
		return -ENOMEM;
	}
	cfg->tx_task = xprt_ptr->tx_task;
	ret = glink_core_init_xprt_qos_cfg(xprt_ptr, cfg);
	if (ret < 0) {
		kfree(xprt_ptr);
+4 −1
Original line number Diff line number Diff line
/* Copyright (c) 2014-2016, The Linux Foundation. All rights reserved.
/* Copyright (c) 2014-2017, 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
@@ -14,6 +14,7 @@

#include <linux/of.h>
#include <linux/types.h>
#include <linux/sched.h>
#include "glink_private.h"

/* Local Channel state */
@@ -105,6 +106,7 @@ struct glink_core_flow_info {
 * @versions_entries:	Number of entries in @versions.
 * @max_cid:		Maximum number of channel identifiers supported.
 * @max_iid:		Maximum number of intent identifiers supported.
 * @tx_task:		Task structure for tx thread.
 * @mtu:		MTU supported by this transport.
 * @num_flows:		Number of traffic flows/priority buckets.
 * @flow_info:		Information about each flow/priority.
@@ -117,6 +119,7 @@ struct glink_core_transport_cfg {
	size_t versions_entries;
	uint32_t max_cid;
	uint32_t max_iid;
	struct task_struct *tx_task;

	size_t mtu;
	uint32_t num_flows;
+39 −1
Original line number Diff line number Diff line
@@ -33,6 +33,7 @@
#include <linux/spinlock.h>
#include <linux/srcu.h>
#include <linux/wait.h>
#include <linux/cpumask.h>
#include <soc/qcom/smem.h>
#include <soc/qcom/tracer_pkt.h>
#include "glink_core_if.h"
@@ -2323,17 +2324,40 @@ static int subsys_name_to_id(const char *name)
	return -ENODEV;
}

static void glink_set_affinity(struct edge_info *einfo, u32 *arr, size_t size)
{
	struct cpumask cpumask;
	pid_t pid;
	int i;

	cpumask_clear(&cpumask);
	for (i = 0; i < size; i++) {
		if (arr[i] < num_possible_cpus())
			cpumask_set_cpu(arr[i], &cpumask);
	}
	if (irq_set_affinity(einfo->irq_line, &cpumask))
		pr_err("%s: Failed to set irq affinity\n", __func__);

	if (sched_setaffinity(einfo->task->pid, &cpumask))
		pr_err("%s: Failed to set rx cpu affinity\n", __func__);

	pid = einfo->xprt_cfg.tx_task->pid;
	if (sched_setaffinity(pid, &cpumask))
		pr_err("%s: Failed to set tx cpu affinity\n", __func__);
}

static int glink_smem_native_probe(struct platform_device *pdev)
{
	struct device_node *node;
	struct device_node *phandle_node;
	struct edge_info *einfo;
	int rc;
	int rc, cpu_size;
	char *key;
	const char *subsys_name;
	uint32_t irq_line;
	uint32_t irq_mask;
	struct resource *r;
	u32 *cpu_array;

	node = pdev->dev.of_node;

@@ -2480,6 +2504,20 @@ static int glink_smem_native_probe(struct platform_device *pdev)
		pr_err("%s: enable_irq_wake() failed on %d\n", __func__,
								irq_line);

	key = "cpu-affinity";
	cpu_size = of_property_count_u32_elems(node, key);
	if (cpu_size > 0) {
		cpu_array = kmalloc_array(cpu_size, sizeof(u32), GFP_KERNEL);
		if (!cpu_array) {
			rc = -ENOMEM;
			goto request_irq_fail;
		}
		rc = of_property_read_u32_array(node, key, cpu_array, cpu_size);
		if (!rc)
			glink_set_affinity(einfo, cpu_array, cpu_size);
		kfree(cpu_array);
	}

	register_debugfs_info(einfo);
	/* fake an interrupt on this edge to see if the remote side is up */
	irq_handler(0, einfo);