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

Commit 9fcd60f7 authored by Subash Abhinov Kasiviswanathan's avatar Subash Abhinov Kasiviswanathan
Browse files

dfc: Adjust QMAP query grants



The grants sent by DS in the query response is based on the current
watermark levels. Due to UL accumulation, the grants may not reflex
the real data capacity. This could cause AP to send more data than
expected especially after multiple queries and lead to DNE packet
drops.

Adjust grants from QMAP query response based on the new field in the
resposne indicating the amount of data that already received to more
accurately assess how much data can be sent.

Change-Id: I9da42a9d2425b491cdef375492dbf4d7f7552dff
Acked-by: default avatarWeiyi Chen <weiyic@qti.qualcomm.com>
Signed-off-by: default avatarSubash Abhinov Kasiviswanathan <subashab@codeaurora.org>
parent b9fa92c7
Loading
Loading
Loading
Loading
+5 −2
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0-only */
/*
 * Copyright (c) 2019, The Linux Foundation. All rights reserved.
 * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved.
 */

#ifndef _DFC_DEFS_H
@@ -53,6 +53,8 @@ struct dfc_flow_status_info_type_v01 {
	u16 seq_num;
	u8 qos_ids_len;
	struct dfc_qos_id_type_v01 qos_ids[DFC_MAX_QOS_ID_V01];
	u8 rx_bytes_valid;
	u32 rx_bytes;
};

struct dfc_ancillary_info_type_v01 {
@@ -88,7 +90,8 @@ struct dfc_tx_link_status_ind_msg_v01 {
};

void dfc_do_burst_flow_control(struct dfc_qmi_data *dfc,
			       struct dfc_flow_status_ind_msg_v01 *ind);
			       struct dfc_flow_status_ind_msg_v01 *ind,
			       bool is_query);

void dfc_handle_tx_link_status_ind(struct dfc_qmi_data *dfc,
				   struct dfc_tx_link_status_ind_msg_v01 *ind);
+19 −7
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0-only
/*
 * Copyright (c) 2019, The Linux Foundation. All rights reserved.
 * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved.
 */

#include <net/pkt_sched.h>
@@ -65,13 +65,14 @@ struct qmap_dfc_ind {
	u8			reserved2;
	u8			tx_info_valid:1;
	u8			tx_info:1;
	u8			reserved3:6;
	u8			rx_bytes_valid:1;
	u8			reserved3:5;
	u8			bearer_id;
	u8			tcp_bidir:1;
	u8			bearer_status:3;
	u8			reserved4:4;
	__be32			grant;
	u32			reserved5;
	__be32			rx_bytes;
	u32			reserved6;
} __aligned(1);

@@ -89,11 +90,12 @@ struct qmap_dfc_query_resp {
	u8			cmd_ver;
	u8			bearer_id;
	u8			tcp_bidir:1;
	u8			reserved:7;
	u8			rx_bytes_valid:1;
	u8			reserved:6;
	u8			invalid:1;
	u8			reserved2:7;
	__be32			grant;
	u32			reserved3;
	__be32			rx_bytes;
	u32			reserved4;
} __aligned(1);

@@ -185,6 +187,11 @@ static int dfc_qmap_handle_ind(struct dfc_qmi_data *dfc,
	qmap_flow_ind.flow_status[0].num_bytes = ntohl(cmd->grant);
	qmap_flow_ind.flow_status[0].seq_num = ntohs(cmd->seq_num);

	if (cmd->rx_bytes_valid) {
		qmap_flow_ind.flow_status[0].rx_bytes_valid = 1;
		qmap_flow_ind.flow_status[0].rx_bytes = ntohl(cmd->rx_bytes);
	}

	if (cmd->tcp_bidir) {
		qmap_flow_ind.ancillary_info_valid = 1;
		qmap_flow_ind.ancillary_info_len = 1;
@@ -193,7 +200,7 @@ static int dfc_qmap_handle_ind(struct dfc_qmi_data *dfc,
		qmap_flow_ind.ancillary_info[0].reserved = DFC_MASK_TCP_BIDIR;
	}

	dfc_do_burst_flow_control(dfc, &qmap_flow_ind);
	dfc_do_burst_flow_control(dfc, &qmap_flow_ind, false);

done:
	return QMAP_CMD_ACK;
@@ -221,6 +228,11 @@ static int dfc_qmap_handle_query_resp(struct dfc_qmi_data *dfc,
	qmap_flow_ind.flow_status[0].num_bytes = ntohl(cmd->grant);
	qmap_flow_ind.flow_status[0].seq_num = 0xFFFF;

	if (cmd->rx_bytes_valid) {
		qmap_flow_ind.flow_status[0].rx_bytes_valid = 1;
		qmap_flow_ind.flow_status[0].rx_bytes = ntohl(cmd->rx_bytes);
	}

	if (cmd->tcp_bidir) {
		qmap_flow_ind.ancillary_info_valid = 1;
		qmap_flow_ind.ancillary_info_len = 1;
@@ -229,7 +241,7 @@ static int dfc_qmap_handle_query_resp(struct dfc_qmi_data *dfc,
		qmap_flow_ind.ancillary_info[0].reserved = DFC_MASK_TCP_BIDIR;
	}

	dfc_do_burst_flow_control(dfc, &qmap_flow_ind);
	dfc_do_burst_flow_control(dfc, &qmap_flow_ind, true);

	return QMAP_CMD_DONE;
}
+63 −10
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0-only
/*
 * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
 * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved.
 */

#include <net/pkt_sched.h>
@@ -945,6 +945,7 @@ static int dfc_all_bearer_flow_ctl(struct net_device *dev,
		bearer->tcp_bidir = DFC_IS_TCP_BIDIR(ancillary);
		bearer->last_grant = fc_info->num_bytes;
		bearer->last_seq = fc_info->seq_num;
		bearer->last_adjusted_grant = fc_info->num_bytes;

		dfc_bearer_flow_ctl(dev, bearer, qos);
	}
@@ -952,13 +953,40 @@ static int dfc_all_bearer_flow_ctl(struct net_device *dev,
	return 0;
}

static u32 dfc_adjust_grant(struct rmnet_bearer_map *bearer,
			    struct dfc_flow_status_info_type_v01 *fc_info)
{
	u32 grant;

	if (!fc_info->rx_bytes_valid)
		return fc_info->num_bytes;

	if (bearer->bytes_in_flight > fc_info->rx_bytes)
		bearer->bytes_in_flight -= fc_info->rx_bytes;
	else
		bearer->bytes_in_flight = 0;

	/* Adjusted grant = grant - bytes_in_flight */
	if (fc_info->num_bytes > bearer->bytes_in_flight)
		grant = fc_info->num_bytes - bearer->bytes_in_flight;
	else
		grant = 0;

	trace_dfc_adjust_grant(fc_info->mux_id, fc_info->bearer_id,
			       fc_info->num_bytes, fc_info->rx_bytes,
			       bearer->bytes_in_flight, grant);
	return grant;
}

static int dfc_update_fc_map(struct net_device *dev, struct qos_info *qos,
			     u8 ack_req, u32 ancillary,
			     struct dfc_flow_status_info_type_v01 *fc_info)
			     struct dfc_flow_status_info_type_v01 *fc_info,
			     bool is_query)
{
	struct rmnet_bearer_map *itm = NULL;
	int rc = 0;
	bool action = false;
	u32 adjusted_grant;

	itm = qmi_rmnet_get_bearer_map(qos, fc_info->bearer_id);
	if (!itm)
@@ -978,8 +1006,16 @@ static int dfc_update_fc_map(struct net_device *dev, struct qos_info *qos,
		if (itm->tx_off  && fc_info->num_bytes > 0)
			return 0;

		if ((itm->grant_size == 0 && fc_info->num_bytes > 0) ||
		    (itm->grant_size > 0 && fc_info->num_bytes == 0))
		/* Adjuste grant for query */
		if (dfc_qmap && is_query) {
			adjusted_grant = dfc_adjust_grant(itm, fc_info);
		} else {
			adjusted_grant = fc_info->num_bytes;
			itm->bytes_in_flight = 0;
		}

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

		/* This is needed by qmap */
@@ -987,13 +1023,24 @@ static int dfc_update_fc_map(struct net_device *dev, struct qos_info *qos,
			dfc_qmap_send_ack(qos, itm->bearer_id,
					  itm->seq, DFC_ACK_TYPE_DISABLE);

		itm->grant_size = fc_info->num_bytes;
		itm->grant_thresh = qmi_rmnet_grant_per(itm->grant_size);
		itm->grant_size = adjusted_grant;

		/* No further query if the adjusted grant is less
		 * than 20% of the original grant
		 */
		if (dfc_qmap && is_query &&
		    itm->grant_size < (fc_info->num_bytes / 5))
			itm->grant_thresh = itm->grant_size;
		else
			itm->grant_thresh =
				qmi_rmnet_grant_per(itm->grant_size);

		itm->seq = fc_info->seq_num;
		itm->ack_req = ack_req;
		itm->tcp_bidir = DFC_IS_TCP_BIDIR(ancillary);
		itm->last_grant = fc_info->num_bytes;
		itm->last_seq = fc_info->seq_num;
		itm->last_adjusted_grant = adjusted_grant;

		if (action)
			rc = dfc_bearer_flow_ctl(dev, itm, qos);
@@ -1003,7 +1050,8 @@ static int dfc_update_fc_map(struct net_device *dev, struct qos_info *qos,
}

void dfc_do_burst_flow_control(struct dfc_qmi_data *dfc,
			       struct dfc_flow_status_ind_msg_v01 *ind)
			       struct dfc_flow_status_ind_msg_v01 *ind,
			       bool is_query)
{
	struct net_device *dev;
	struct qos_info *qos;
@@ -1059,7 +1107,8 @@ void dfc_do_burst_flow_control(struct dfc_qmi_data *dfc,
				dev, qos, ack_req, ancillary, flow_status);
		else
			dfc_update_fc_map(
				dev, qos, ack_req, ancillary, flow_status);
				dev, qos, ack_req, ancillary, flow_status,
				is_query);

		spin_unlock_bh(&qos->qos_lock);
	}
@@ -1085,6 +1134,7 @@ static void dfc_update_tx_link_status(struct net_device *dev,
	if (itm->grant_size && !tx_status) {
		itm->grant_size = 0;
		itm->tcp_bidir = false;
		itm->bytes_in_flight = 0;
		dfc_bearer_flow_ctl(dev, itm, qos);
	} else if (itm->grant_size == 0 && tx_status && !itm->rat_switch) {
		itm->grant_size = DEFAULT_GRANT;
@@ -1162,7 +1212,8 @@ static void dfc_qmi_ind_work(struct work_struct *work)
		if (!dfc->restart_state) {
			if (svc_ind->msg_id == QMI_DFC_FLOW_STATUS_IND_V01)
				dfc_do_burst_flow_control(
						dfc, &svc_ind->d.dfc_info);
						dfc, &svc_ind->d.dfc_info,
						false);
			else if (svc_ind->msg_id ==
					QMI_DFC_TX_LINK_STATUS_IND_V01)
				dfc_handle_tx_link_status_ind(
@@ -1437,6 +1488,8 @@ void dfc_qmi_burst_check(struct net_device *dev, struct qos_info *qos,
	trace_dfc_flow_check(dev->name, bearer->bearer_id,
			     len, mark, bearer->grant_size);

	bearer->bytes_in_flight += len;

	if (!bearer->grant_size)
		goto out;

@@ -1490,7 +1543,7 @@ void dfc_qmi_query_flow(void *dfc_data)
	svc_ind->d.dfc_info.flow_status_len = resp->flow_status_len;
	memcpy(&svc_ind->d.dfc_info.flow_status, resp->flow_status,
		sizeof(resp->flow_status[0]) * resp->flow_status_len);
	dfc_do_burst_flow_control(data, &svc_ind->d.dfc_info);
	dfc_do_burst_flow_control(data, &svc_ind->d.dfc_info, true);

done:
	kfree(svc_ind);
+2 −1
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0-only
/*
 * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
 * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved.
 */

#include <soc/qcom/qmi_rmnet.h>
@@ -722,6 +722,7 @@ void qmi_rmnet_enable_all_flows(struct net_device *dev)
		bearer->grant_thresh = qmi_rmnet_grant_per(DEFAULT_GRANT);
		bearer->seq = 0;
		bearer->ack_req = 0;
		bearer->bytes_in_flight = 0;
		bearer->tcp_bidir = false;
		bearer->rat_switch = false;

+3 −1
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0-only */
/*
 * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
 * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved.
 */

#ifndef _RMNET_QMI_I_H
@@ -36,6 +36,8 @@ struct rmnet_bearer_map {
	u8  ack_req;
	u32 last_grant;
	u16 last_seq;
	u32 bytes_in_flight;
	u32 last_adjusted_grant;
	bool tcp_bidir;
	bool rat_switch;
	bool tx_off;
Loading