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

Commit 97381e73 authored by qctecmdr Service's avatar qctecmdr Service Committed by Gerrit - the friendly Code Review server
Browse files

Merge "soc: qcom: dfc: ignore indications during RAT switch"

parents a1dba62f e7ba4463
Loading
Loading
Loading
Loading
+24 −0
Original line number Diff line number Diff line
@@ -610,6 +610,30 @@ void rmnet_enable_all_flows(void *port)
}
EXPORT_SYMBOL(rmnet_enable_all_flows);

bool rmnet_all_flows_enabled(void *port)
{
	struct rmnet_endpoint *ep;
	unsigned long bkt;
	bool ret = true;

	if (unlikely(!port))
		return true;

	rcu_read_lock();
	hash_for_each_rcu(((struct rmnet_port *)port)->muxed_ep,
			  bkt, ep, hlnode) {
		if (!qmi_rmnet_all_flows_enabled(ep->egress_dev)) {
			ret = false;
			goto out;
		}
	}
out:
	rcu_read_unlock();

	return ret;
}
EXPORT_SYMBOL(rmnet_all_flows_enabled);

int rmnet_get_powersave_notif(void *port)
{
	if (!port)
+1 −3
Original line number Diff line number Diff line
@@ -219,6 +219,7 @@ __rmnet_map_ingress_handler(struct sk_buff *skb,

	qmap = (struct rmnet_map_header *)rmnet_map_data_ptr(skb);
	if (qmap->cd_bit) {
		qmi_rmnet_set_dl_msg_active(port);
		if (port->data_format & RMNET_INGRESS_FORMAT_DL_MARKER) {
			if (!rmnet_map_flow_command(skb, port, false))
				return;
@@ -349,9 +350,6 @@ static int rmnet_map_egress_handler(struct sk_buff *skb,
			return -ENOMEM;
	}

	if (port->data_format & RMNET_INGRESS_FORMAT_PS)
		qmi_rmnet_work_maybe_restart(port);

	if (csum_type)
		rmnet_map_checksum_uplink_packet(skb, orig_dev, csum_type);

+2 −0
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@
#include "rmnet_vnd.h"

#include <soc/qcom/qmi_rmnet.h>
#include <soc/qcom/rmnet_qmi.h>
#define CREATE_TRACE_POINTS
#include <trace/events/rmnet.h>

@@ -75,6 +76,7 @@ static netdev_tx_t rmnet_vnd_start_xmit(struct sk_buff *skb,
		trace_rmnet_xmit_skb(skb);
		rmnet_egress_handler(skb);
		qmi_rmnet_burst_fc_check(dev, ip_type, mark, len);
		qmi_rmnet_work_maybe_restart(rmnet_get_rmnet_port(dev));
	} else {
		this_cpu_inc(priv->pcpu_stats->stats.tx_drops);
		kfree_skb(skb);
+29 −9
Original line number Diff line number Diff line
@@ -15,11 +15,17 @@
#include <net/pkt_sched.h>
#include <linux/soc/qcom/qmi.h>
#include <soc/qcom/rmnet_qmi.h>
#include <soc/qcom/qmi_rmnet.h>

#include "qmi_rmnet_i.h"
#define CREATE_TRACE_POINTS
#include <trace/events/dfc.h>

#define DFC_MASK_TCP_BIDIR 0x1
#define DFC_MASK_RAT_SWITCH 0x2
#define DFC_IS_TCP_BIDIR(r) (bool)((r) & DFC_MASK_TCP_BIDIR)
#define DFC_IS_RAT_SWITCH(r) (bool)((r) & DFC_MASK_RAT_SWITCH)

#define DFC_IS_ANCILLARY(type) ((type) != AF_INET && (type) != AF_INET6)

#define DFC_MAX_QOS_ID_V01 2
@@ -851,7 +857,7 @@ static int dfc_bearer_flow_ctl(struct net_device *dev,
			/*
			 * Do not flow disable ancillary q if ancillary is true
			 */
			if (bearer->ancillary && enable == 0 &&
			if (bearer->tcp_bidir && enable == 0 &&
					DFC_IS_ANCILLARY(itm->ip_type))
				continue;

@@ -889,7 +895,9 @@ static int dfc_all_bearer_flow_ctl(struct net_device *dev,
			qmi_rmnet_grant_per(bearer_itm->grant_size);
		bearer_itm->seq = fc_info->seq_num;
		bearer_itm->ack_req = ack_req;
		bearer_itm->ancillary = ancillary;
		bearer_itm->tcp_bidir = DFC_IS_TCP_BIDIR(ancillary);
		bearer_itm->last_grant = fc_info->num_bytes;
		bearer_itm->last_seq = fc_info->seq_num;
	}

	list_for_each_entry(flow_itm, &qos->flow_head, list) {
@@ -915,22 +923,32 @@ static int dfc_update_fc_map(struct net_device *dev, struct qos_info *qos,
{
	struct rmnet_bearer_map *itm = NULL;
	int rc = 0;
	int action = -1;
	bool action = false;

	itm = qmi_rmnet_get_bearer_map(qos, fc_info->bearer_id);
	if (itm) {
		if (itm->grant_size == 0 && fc_info->num_bytes > 0)
			action = 1;
		else if (itm->grant_size > 0 && fc_info->num_bytes == 0)
			action = 0;
		/* The RAT switch flag indicates the start and end of
		 * the switch. Ignore indications in between.
		 */
		if (DFC_IS_RAT_SWITCH(ancillary))
			itm->rat_switch = !fc_info->num_bytes;
		else
			if (itm->rat_switch)
				return 0;

		if ((itm->grant_size == 0 && fc_info->num_bytes > 0) ||
		    (itm->grant_size > 0 && fc_info->num_bytes == 0))
			action = true;

		itm->grant_size = fc_info->num_bytes;
		itm->grant_thresh = qmi_rmnet_grant_per(itm->grant_size);
		itm->seq = fc_info->seq_num;
		itm->ack_req = ack_req;
		itm->ancillary = ancillary;
		itm->tcp_bidir = DFC_IS_TCP_BIDIR(ancillary);
		itm->last_grant = fc_info->num_bytes;
		itm->last_seq = fc_info->seq_num;

		if (action != -1)
		if (action)
			rc = dfc_bearer_flow_ctl(dev, itm, qos);
	} else {
		pr_debug("grant %u before flow activate", fc_info->num_bytes);
@@ -1029,6 +1047,8 @@ static void dfc_qmi_ind_work(struct work_struct *work)
	} while (svc_ind != NULL);

	local_bh_enable();

	qmi_rmnet_set_dl_msg_active(dfc->rmnet_port);
}

static void dfc_clnt_ind_cb(struct qmi_handle *qmi, struct sockaddr_qrtr *sq,
+62 −16
Original line number Diff line number Diff line
@@ -575,7 +575,7 @@ void qmi_rmnet_enable_all_flows(struct net_device *dev)
{
	struct qos_info *qos;
	struct rmnet_bearer_map *bearer;
	int do_wake = 0;
	bool do_wake = false;

	qos = (struct qos_info *)rmnet_get_qos_pt(dev);
	if (!qos)
@@ -584,14 +584,14 @@ void qmi_rmnet_enable_all_flows(struct net_device *dev)
	spin_lock_bh(&qos->qos_lock);

	list_for_each_entry(bearer, &qos->bearer_head, list) {
		bearer->grant_before_ps = bearer->grant_size;
		bearer->seq_before_ps = bearer->seq;
		if (!bearer->grant_size)
			do_wake = true;
		bearer->grant_size = DEFAULT_GRANT;
		bearer->grant_thresh = DEFAULT_GRANT;
		bearer->seq = 0;
		bearer->ack_req = 0;
		bearer->ancillary = 0;
		do_wake = 1;
		bearer->tcp_bidir = false;
		bearer->rat_switch = false;
	}

	if (do_wake) {
@@ -603,6 +603,31 @@ void qmi_rmnet_enable_all_flows(struct net_device *dev)
}
EXPORT_SYMBOL(qmi_rmnet_enable_all_flows);

bool qmi_rmnet_all_flows_enabled(struct net_device *dev)
{
	struct qos_info *qos;
	struct rmnet_bearer_map *bearer;
	bool ret = true;

	qos = (struct qos_info *)rmnet_get_qos_pt(dev);
	if (!qos)
		return true;

	spin_lock_bh(&qos->qos_lock);

	list_for_each_entry(bearer, &qos->bearer_head, list) {
		if (!bearer->grant_size) {
			ret = false;
			break;
		}
	}

	spin_unlock_bh(&qos->qos_lock);

	return ret;
}
EXPORT_SYMBOL(qmi_rmnet_all_flows_enabled);

#ifdef CONFIG_QCOM_QMI_DFC
void qmi_rmnet_burst_fc_check(struct net_device *dev,
			      int ip_type, u32 mark, unsigned int len)
@@ -798,13 +823,12 @@ int qmi_rmnet_set_powersave_mode(void *port, uint8_t enable)
}
EXPORT_SYMBOL(qmi_rmnet_set_powersave_mode);

void qmi_rmnet_work_restart(void *port)
static void qmi_rmnet_work_restart(void *port)
{
	if (!rmnet_ps_wq || !rmnet_work)
		return;
	queue_delayed_work(rmnet_ps_wq, &rmnet_work->work, NO_DELAY);
}
EXPORT_SYMBOL(qmi_rmnet_work_restart);

static void qmi_rmnet_check_stats(struct work_struct *work)
{
@@ -812,6 +836,7 @@ static void qmi_rmnet_check_stats(struct work_struct *work)
	struct qmi_info *qmi;
	u64 rxd, txd;
	u64 rx, tx;
	bool dl_msg_active;

	real_work = container_of(to_delayed_work(work),
				 struct rmnet_powersave_work, work);
@@ -824,17 +849,15 @@ static void qmi_rmnet_check_stats(struct work_struct *work)
		return;

	if (qmi->ps_enabled) {
		/* Retry after small delay if qmi error
		 * This resumes UL grants by disabling
		 * powersave mode if successful.
		 */
		/* Register to get QMI DFC and DL marker */
		if (qmi_rmnet_set_powersave_mode(real_work->port, 0) < 0) {
			/* If this failed need to retry quickly */
			queue_delayed_work(rmnet_ps_wq,
					   &real_work->work, HZ / 50);
			return;

		}
		qmi->ps_enabled = 0;
		qmi->ps_enabled = false;

		if (rmnet_get_powersave_notif(real_work->port))
			qmi_rmnet_ps_off_notify(real_work->port);
@@ -849,18 +872,29 @@ static void qmi_rmnet_check_stats(struct work_struct *work)
	real_work->old_rx_pkts = rx;
	real_work->old_tx_pkts = tx;

	dl_msg_active = qmi->dl_msg_active;
	qmi->dl_msg_active = false;

	if (!rxd && !txd) {
		/* If no DL msg received and there is a flow disabled,
		 * (likely in RLF), no need to enter powersave
		 */
		if (!dl_msg_active &&
		    !rmnet_all_flows_enabled(real_work->port))
			goto end;

		/* Deregister to suppress QMI DFC and DL marker */
		if (qmi_rmnet_set_powersave_mode(real_work->port, 1) < 0) {
			queue_delayed_work(rmnet_ps_wq,
					   &real_work->work, PS_INTERVAL);
			return;
		}
		qmi->ps_enabled = 1;
		clear_bit(PS_WORK_ACTIVE_BIT, &qmi->ps_work_active);
		qmi->ps_enabled = true;

		/* Enable flow after clear the bit so a new
		 * work can be triggered.
		/* Clear the bit before enabling flow so pending packets
		 * can trigger the work again
		 */
		clear_bit(PS_WORK_ACTIVE_BIT, &qmi->ps_work_active);
		rmnet_enable_all_flows(real_work->port);

		if (rmnet_get_powersave_notif(real_work->port))
@@ -936,4 +970,16 @@ void qmi_rmnet_work_exit(void *port)
	rmnet_work = NULL;
}
EXPORT_SYMBOL(qmi_rmnet_work_exit);

void qmi_rmnet_set_dl_msg_active(void *port)
{
	struct qmi_info *qmi;

	qmi = (struct qmi_info *)rmnet_get_qmi_pt(port);
	if (unlikely(!qmi))
		return;

	qmi->dl_msg_active = true;
}
EXPORT_SYMBOL(qmi_rmnet_set_dl_msg_active);
#endif
Loading