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

Commit f5a1f29b authored by Subash Abhinov Kasiviswanathan's avatar Subash Abhinov Kasiviswanathan
Browse files

dfc: Cache grants before flow is added



If a grant indication is received before the corresponding flow
is added, the grant information needs to be cached for use later
instead of ignored which could lead to data stall.

This change also adjust flow control ftrace prints.

Change-Id: I78ab6a6f0a046e92eac3d477cab6ec33b1109171
Acked-by: default avatarWeiyi Chen <weiyic@qti.qualcomm.com>
Signed-off-by: default avatarSubash Abhinov Kasiviswanathan <subashab@codeaurora.org>
parent f74668f9
Loading
Loading
Loading
Loading
+4 −8
Original line number Original line Diff line number Diff line
@@ -916,18 +916,11 @@ int dfc_bearer_flow_ctl(struct net_device *dev,
	enable = bearer->grant_size ? true : false;
	enable = bearer->grant_size ? true : false;


	qmi_rmnet_flow_control(dev, bearer->mq_idx, enable);
	qmi_rmnet_flow_control(dev, bearer->mq_idx, enable);
	trace_dfc_qmi_tc(dev->name, bearer->bearer_id,
			 bearer->grant_size,
			 0, bearer->mq_idx, enable);


	/* Do not flow disable tcp ack q in tcp bidir */
	/* Do not flow disable tcp ack q in tcp bidir */
	if (bearer->ack_mq_idx != INVALID_MQ &&
	if (bearer->ack_mq_idx != INVALID_MQ &&
	    (enable || !bearer->tcp_bidir)) {
	    (enable || !bearer->tcp_bidir))
		qmi_rmnet_flow_control(dev, bearer->ack_mq_idx, enable);
		qmi_rmnet_flow_control(dev, bearer->ack_mq_idx, enable);
		trace_dfc_qmi_tc(dev->name, bearer->bearer_id,
				 bearer->grant_size,
				 0, bearer->ack_mq_idx, enable);
	}


	if (!enable && bearer->ack_req)
	if (!enable && bearer->ack_req)
		dfc_send_ack(dev, bearer->bearer_id,
		dfc_send_ack(dev, bearer->bearer_id,
@@ -968,6 +961,9 @@ static int dfc_update_fc_map(struct net_device *dev, struct qos_info *qos,
	bool action = false;
	bool action = false;


	itm = qmi_rmnet_get_bearer_map(qos, fc_info->bearer_id);
	itm = qmi_rmnet_get_bearer_map(qos, fc_info->bearer_id);
	if (!itm)
		itm = qmi_rmnet_get_bearer_noref(qos, fc_info->bearer_id);

	if (itm) {
	if (itm) {
		/* The RAT switch flag indicates the start and end of
		/* The RAT switch flag indicates the start and end of
		 * the switch. Ignore indications in between.
		 * the switch. Ignore indications in between.
+19 −15
Original line number Original line Diff line number Diff line
@@ -205,6 +205,8 @@ int qmi_rmnet_flow_control(struct net_device *dev, u32 mq_idx, int enable)
	else
	else
		netif_tx_stop_queue(q);
		netif_tx_stop_queue(q);


	trace_dfc_qmi_tc(dev->name, mq_idx, enable);

	return 0;
	return 0;
}
}


@@ -266,15 +268,11 @@ static void __qmi_rmnet_bearer_put(struct net_device *dev,
			if (reset) {
			if (reset) {
				qmi_rmnet_reset_txq(dev, i);
				qmi_rmnet_reset_txq(dev, i);
				qmi_rmnet_flow_control(dev, i, 1);
				qmi_rmnet_flow_control(dev, i, 1);
				trace_dfc_qmi_tc(dev->name,
					bearer->bearer_id, 0, 0, i, 1);


				if (dfc_mode == DFC_MODE_SA) {
				if (dfc_mode == DFC_MODE_SA) {
					j = i + ACK_MQ_OFFSET;
					j = i + ACK_MQ_OFFSET;
					qmi_rmnet_reset_txq(dev, j);
					qmi_rmnet_reset_txq(dev, j);
					qmi_rmnet_flow_control(dev, j, 1);
					qmi_rmnet_flow_control(dev, j, 1);
					trace_dfc_qmi_tc(dev->name,
						bearer->bearer_id, 0, 0, j, 1);
				}
				}
			}
			}
		}
		}
@@ -312,18 +310,10 @@ static void __qmi_rmnet_update_mq(struct net_device *dev,


		qmi_rmnet_flow_control(dev, itm->mq_idx,
		qmi_rmnet_flow_control(dev, itm->mq_idx,
				       bearer->grant_size > 0 ? 1 : 0);
				       bearer->grant_size > 0 ? 1 : 0);
		trace_dfc_qmi_tc(dev->name, itm->bearer_id,
				 bearer->grant_size, 0, itm->mq_idx,
				 bearer->grant_size > 0 ? 1 : 0);


		if (dfc_mode == DFC_MODE_SA) {
		if (dfc_mode == DFC_MODE_SA)
			qmi_rmnet_flow_control(dev, bearer->ack_mq_idx,
			qmi_rmnet_flow_control(dev, bearer->ack_mq_idx,
					bearer->grant_size > 0 ? 1 : 0);
					bearer->grant_size > 0 ? 1 : 0);
			trace_dfc_qmi_tc(dev->name, itm->bearer_id,
					bearer->grant_size, 0,
					bearer->ack_mq_idx,
					bearer->grant_size > 0 ? 1 : 0);
		}
	}
	}
}
}


@@ -476,6 +466,18 @@ static void qmi_rmnet_query_flows(struct qmi_info *qmi)
	}
	}
}
}


struct rmnet_bearer_map *qmi_rmnet_get_bearer_noref(struct qos_info *qos_info,
						    u8 bearer_id)
{
	struct rmnet_bearer_map *bearer;

	bearer = __qmi_rmnet_bearer_get(qos_info, bearer_id);
	if (bearer)
		bearer->flow_ref--;

	return bearer;
}

#else
#else
static inline void qmi_rmnet_clean_flow_list(struct qos_info *qos)
static inline void qmi_rmnet_clean_flow_list(struct qos_info *qos)
{
{
@@ -780,7 +782,8 @@ static bool qmi_rmnet_is_tcp_ack(struct sk_buff *skb)
		if ((ip_hdr(skb)->protocol == IPPROTO_TCP) &&
		if ((ip_hdr(skb)->protocol == IPPROTO_TCP) &&
		    (ip_hdr(skb)->ihl == 5) &&
		    (ip_hdr(skb)->ihl == 5) &&
		    (len == 40 || len == 52) &&
		    (len == 40 || len == 52) &&
		    ((tcp_flag_word(tcp_hdr(skb)) & 0xFF00) == TCP_FLAG_ACK))
		    ((tcp_flag_word(tcp_hdr(skb)) &
		      cpu_to_be32(0x00FF0000)) == TCP_FLAG_ACK))
			return true;
			return true;
		break;
		break;


@@ -788,7 +791,8 @@ static bool qmi_rmnet_is_tcp_ack(struct sk_buff *skb)
	case htons(ETH_P_IPV6):
	case htons(ETH_P_IPV6):
		if ((ipv6_hdr(skb)->nexthdr == IPPROTO_TCP) &&
		if ((ipv6_hdr(skb)->nexthdr == IPPROTO_TCP) &&
		    (len == 60 || len == 72) &&
		    (len == 60 || len == 72) &&
		    ((tcp_flag_word(tcp_hdr(skb)) & 0xFF00) == TCP_FLAG_ACK))
		    ((tcp_flag_word(tcp_hdr(skb)) &
		      cpu_to_be32(0x00FF0000)) == TCP_FLAG_ACK))
			return true;
			return true;
		break;
		break;
	}
	}
+3 −0
Original line number Original line Diff line number Diff line
@@ -137,6 +137,9 @@ int dfc_qmap_client_init(void *port, int index, struct svc_info *psvc,
void dfc_qmap_client_exit(void *dfc_data);
void dfc_qmap_client_exit(void *dfc_data);


void dfc_qmap_send_ack(struct qos_info *qos, u8 bearer_id, u16 seq, u8 type);
void dfc_qmap_send_ack(struct qos_info *qos, u8 bearer_id, u16 seq, u8 type);

struct rmnet_bearer_map *qmi_rmnet_get_bearer_noref(struct qos_info *qos_info,
						    u8 bearer_id);
#else
#else
static inline struct rmnet_flow_map *
static inline struct rmnet_flow_map *
qmi_rmnet_get_flow_map(struct qos_info *qos_info,
qmi_rmnet_get_flow_map(struct qos_info *qos_info,
+7 −15
Original line number Original line Diff line number Diff line
@@ -12,33 +12,25 @@


TRACE_EVENT(dfc_qmi_tc,
TRACE_EVENT(dfc_qmi_tc,


	TP_PROTO(const char *name, u8 bearer_id, u32 grant,
	TP_PROTO(const char *name, u32 txq, int enable),
		 int qlen, u32 tcm_handle, int enable),


	TP_ARGS(name, bearer_id, grant, qlen, tcm_handle, enable),
	TP_ARGS(name, txq, enable),


	TP_STRUCT__entry(
	TP_STRUCT__entry(
		__string(dev_name, name)
		__string(dev_name, name)
		__field(u8, bid)
		__field(u32, txq)
		__field(u32, grant)
		__field(int, qlen)
		__field(u32, tcm_handle)
		__field(int, enable)
		__field(int, enable)
	),
	),


	TP_fast_assign(
	TP_fast_assign(
		__assign_str(dev_name, name);
		__assign_str(dev_name, name);
		__entry->bid = bearer_id;
		__entry->txq = txq;
		__entry->grant = grant;
		__entry->qlen = qlen;
		__entry->tcm_handle = tcm_handle;
		__entry->enable = enable;
		__entry->enable = enable;
	),
	),


	TP_printk("dev=%s bearer_id=%u grant=%u len=%d mq=%u %s",
	TP_printk("dev=%s txq=%u %s",
		__get_str(dev_name),
		__get_str(dev_name),
		__entry->bid, __entry->grant, __entry->qlen,
		__entry->txq,
		__entry->tcm_handle,
		__entry->enable ? "enable" : "disable")
		__entry->enable ? "enable" : "disable")
);
);


@@ -131,7 +123,7 @@ TRACE_EVENT(dfc_flow_info,
		__entry->action = add;
		__entry->action = add;
	),
	),


	TP_printk("%s: dev=%s bearer_id=%u flow_id=%u ip_type=%d mq=%d",
	TP_printk("%s: dev=%s bearer_id=%u flow_id=%u ip_type=%d txq=%d",
		__entry->action ? "add flow" : "delete flow",
		__entry->action ? "add flow" : "delete flow",
		__get_str(dev_name),
		__get_str(dev_name),
		__entry->bid, __entry->fid, __entry->ip, __entry->handle)
		__entry->bid, __entry->fid, __entry->ip, __entry->handle)