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

Commit 05112982 authored by Vamsi Krishna's avatar Vamsi Krishna
Browse files

u_ether: Boost the cpu when rmnet/rndis ifc is up



During peak throughput testing when threads migrate from cpus
running in peak frequency to cpu running at low frequency there
could be throughput drop. Also, if for some unknown reason
upcoming cpu setttles at lower frequency it could lead throughput
drop. Avoid this by boosting the cpus to 1Ghz whenever usb tethered
call is established. There is no power impact as USB cable is
connected and phone can be charged from phone.

Change-Id: I5d54565752527dbdbed7280fea852fc7bd3e09dd
Signed-off-by: default avatarVamsi Krishna <vskrishn@codeaurora.org>
parent d062ba1f
Loading
Loading
Loading
Loading
+82 −0
Original line number Diff line number Diff line
@@ -25,6 +25,8 @@
#include <linux/msm_rmnet.h>
#include <linux/debugfs.h>
#include <linux/seq_file.h>
#include <linux/notifier.h>
#include <linux/cpufreq.h>
#include "u_ether.h"


@@ -68,6 +70,13 @@ MODULE_PARM_DESC(tx_stop_threshold,
 * which includes headers/data packets
 */
#define DL_MAX_PKTS_PER_XFER	20

enum ifc_state {
	ETH_UNDEFINED,
	ETH_STOP,
	ETH_START,
};

struct eth_dev {
	/* lock is held while accessing port_usb
	 */
@@ -117,6 +126,10 @@ struct eth_dev {
	unsigned int		loop_brk_cnt;
	struct dentry		*uether_dent;
	struct dentry		*uether_dfile;

	enum ifc_state		state;
	struct notifier_block	cpufreq_notifier;
	struct work_struct	cpu_policy_w;
};

/* when sg is enabled, sg_ctx is used to track skb each usb request will
@@ -1173,6 +1186,7 @@ static int eth_open(struct net_device *net)
	struct eth_dev	*dev = netdev_priv(net);
	struct gether	*link;
	bool wait_for_rx_trigger;
	int i;

	DBG(dev, "%s\n", __func__);

@@ -1186,6 +1200,10 @@ static int eth_open(struct net_device *net)
	if (netif_carrier_ok(dev->net) && !wait_for_rx_trigger)
		eth_start(dev, GFP_KERNEL);

	dev->state = ETH_START;
	for_each_online_cpu(i)
		cpufreq_update_policy(i);

	spin_lock_irq(&dev->lock);
	if (link && link->open)
		link->open(link);
@@ -1198,8 +1216,11 @@ static int eth_stop(struct net_device *net)
{
	struct eth_dev	*dev = netdev_priv(net);
	unsigned long	flags;
	int i;
	enum ifc_state prev_state;

	VDBG(dev, "%s\n", __func__);

	netif_stop_queue(net);

	DBG(dev, "stop stats: rx/tx %ld/%ld, errs %ld/%ld\n",
@@ -1248,6 +1269,14 @@ static int eth_stop(struct net_device *net)
	}
	spin_unlock_irqrestore(&dev->lock, flags);

	prev_state = dev->state;
	dev->state = ETH_STOP;

	/* if previous state is eth_start, update cpufreq policy to normal */
	if (prev_state == ETH_START)
		for_each_online_cpu(i)
			cpufreq_update_policy(i);

	return 0;
}

@@ -1445,6 +1474,39 @@ static struct device_type gadget_type = {
	.name	= "gadget",
};

static int gether_cpufreq_notifier_cb(struct notifier_block *nfb,
		unsigned long event, void *data)
{
	struct cpufreq_policy *policy = data;
	unsigned int cpu = policy->cpu;
	struct eth_dev	*dev = container_of(nfb, struct eth_dev,
					cpufreq_notifier);

	switch (event) {
	case CPUFREQ_ADJUST:
		pr_debug("%s: cpu:%u\n", __func__, cpu);

		if (dev->state == ETH_START)
			cpufreq_verify_within_limits(policy,
					1000000, UINT_MAX);
		else
			cpufreq_verify_within_limits(policy,
					policy->min, UINT_MAX);

		break;
	}

	return NOTIFY_OK;
}

static void update_cpu_policy_w(struct work_struct *work)
{
	int i;

	for_each_online_cpu(i)
		cpufreq_update_policy(i);
}

/**
 * gether_setup_name - initialize one ethernet-over-usb link
 * @g: gadget to associated with these links
@@ -1478,6 +1540,7 @@ struct eth_dev *gether_setup_name(struct usb_gadget *g, u8 ethaddr[ETH_ALEN],
	INIT_WORK(&dev->tx_work, process_tx_w);
	INIT_LIST_HEAD(&dev->tx_reqs);
	INIT_LIST_HEAD(&dev->rx_reqs);
	INIT_WORK(&dev->cpu_policy_w, update_cpu_policy_w);

	skb_queue_head_init(&dev->rx_frames);
	skb_queue_head_init(&dev->tx_skb_q);
@@ -1522,6 +1585,11 @@ struct eth_dev *gether_setup_name(struct usb_gadget *g, u8 ethaddr[ETH_ALEN],
		 */
		netif_carrier_off(net);
		uether_debugfs_init(dev, netname);

		dev->cpufreq_notifier.notifier_call =
					gether_cpufreq_notifier_cb;
		cpufreq_register_notifier(&dev->cpufreq_notifier,
				CPUFREQ_POLICY_NOTIFIER);
	}

	return dev;
@@ -1535,9 +1603,20 @@ struct eth_dev *gether_setup_name(struct usb_gadget *g, u8 ethaddr[ETH_ALEN],
 */
void gether_cleanup(struct eth_dev *dev)
{
	int i;

	if (!dev)
		return;

	/* make sure cpu boost is set to normal again */
	dev->state = ETH_UNDEFINED;
	cancel_work_sync(&dev->cpu_policy_w);
	for_each_online_cpu(i)
		cpufreq_update_policy(i);

	cpufreq_unregister_notifier(&dev->cpufreq_notifier,
				CPUFREQ_POLICY_NOTIFIER);

	uether_debugfs_exit(dev);
	unregister_netdev(dev->net);
	flush_work(&dev->work);
@@ -1700,6 +1779,9 @@ void gether_disconnect(struct gether *link)

	DBG(dev, "%s\n", __func__);

	dev->state = ETH_UNDEFINED;
	queue_work(uether_wq, &dev->cpu_policy_w);

	netif_stop_queue(dev->net);
	netif_carrier_off(dev->net);