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

Commit eeb49449 authored by Sean Tranchetti's avatar Sean Tranchetti
Browse files

core: rmnet: Fastforward to 4.19 tip



This brings the RmNet and DFC modules up to date with the 4.19 tip as of
commit 9b38611ea527 ("rmnet: Reduce synchronize_rcu calls").

As part of this, the rmnet_ctl driver was also incorporated, using commit
4ceee3aafb7d ("rmnet_ctl: Add IPC logging and optimizations")

Change-Id: Ic45d46074c7401dfed408c769cfb6462dac0d4ee
Signed-off-by: default avatarSean Tranchetti <stranche@codeaurora.org>
parent 08d4972b
Loading
Loading
Loading
Loading
+12 −1
Original line number Diff line number Diff line
@@ -12,7 +12,18 @@ LOCAL_CLANG :=true
LOCAL_MODULE_PATH := $(KERNEL_MODULES_OUT)
LOCAL_MODULE := rmnet_core.ko

LOCAL_SRC_FILES := rmnet_config.c rmnet_descriptor.c rmnet_handlers.c rmnet_map_command.c rmnet_map_data.c rmnet_vnd.c dfc_qmi.c qmi_rmnet.c wda_qmi.c
LOCAL_SRC_FILES := \
	rmnet_config.c \
	rmnet_descriptor.c \
	rmnet_genl.c \
	rmnet_handlers.c \
	rmnet_map_command.c \
	rmnet_map_data.c \
	rmnet_vnd.c \
	dfc_qmap.c \
	dfc_qmi.c \
	qmi_rmnet.c \
	wda_qmi.c

RMNET_BLD_DIR := ../../vendor/qcom/opensource/datarmnet/core
DLKM_DIR := $(TOP)/device/qcom/common/dlkm
+3 −2
Original line number Diff line number Diff line
obj-m += rmnet_core.o
rmnet_core-y := rmnet_config.o rmnet_handlers.o rmnet_descriptor.o rmnet_map_command.o rmnet_map_data.o rmnet_vnd.o rmnet_descriptor.o\
	qmi_rmnet.o wda_qmi.o dfc_qmi.o	
rmnet_core-y := rmnet_config.o rmnet_handlers.o rmnet_descriptor.o \
	rmnet_genl.o rmnet_map_command.o rmnet_map_data.o rmnet_vnd.o\
	qmi_rmnet.o wda_qmi.o dfc_qmi.o dfc_qmap.o

+41 −27
Original line number Diff line number Diff line
/* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
/* Copyright (c) 2018-2020, 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
@@ -23,35 +23,25 @@

TRACE_EVENT(dfc_qmi_tc,

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

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

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

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

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

@@ -93,14 +83,16 @@ TRACE_EVENT(dfc_flow_ind,

TRACE_EVENT(dfc_flow_check,

	TP_PROTO(const char *name, u8 bearer_id, unsigned int len, u32 grant),
	TP_PROTO(const char *name, u8 bearer_id, unsigned int len,
		 u32 mark, u32 grant),

	TP_ARGS(name, bearer_id, len, grant),
	TP_ARGS(name, bearer_id, len, mark, grant),

	TP_STRUCT__entry(
		__string(dev_name, name)
		__field(u8, bearer_id)
		__field(unsigned int, len)
		__field(u32, mark)
		__field(u32, grant)
	),

@@ -108,12 +100,13 @@ TRACE_EVENT(dfc_flow_check,
		__assign_str(dev_name, name)
		__entry->bearer_id = bearer_id;
		__entry->len = len;
		__entry->mark = mark;
		__entry->grant = grant;
	),

	TP_printk("dev=%s bearer_id=%u skb_len=%u current_grant=%u",
		__get_str(dev_name),
		__entry->bearer_id, __entry->len, __entry->grant)
	TP_printk("dev=%s bearer_id=%u skb_len=%u mark=%u current_grant=%u",
		__get_str(dev_name), __entry->bearer_id,
		__entry->len, __entry->mark, __entry->grant)
);

TRACE_EVENT(dfc_flow_info,
@@ -141,7 +134,7 @@ TRACE_EVENT(dfc_flow_info,
		__entry->action = add;
	),

	TP_printk("%s: dev=%s bearer_id=%u flow_id=%u ip_type=%d q=%d",
	TP_printk("%s: dev=%s bearer_id=%u flow_id=%u ip_type=%d txq=%d",
		__entry->action ? "add flow" : "delete flow",
		__get_str(dev_name),
		__entry->bid, __entry->fid, __entry->ip, __entry->handle)
@@ -167,8 +160,7 @@ TRACE_EVENT(dfc_client_state_up,
		__entry->iface = iface;
	),

	TP_printk("Client[%d]: Connection established with DFC Service "
		  "instance=%u ep_type=%u iface_id=%u",
	TP_printk("DFC Client[%d] connect: instance=%u ep_type=%u iface_id=%u",
		__entry->idx, __entry->instance,
		__entry->ep_type, __entry->iface)
);
@@ -189,8 +181,7 @@ TRACE_EVENT(dfc_client_state_down,
		__entry->from_cb = from_cb;
	),

	TP_printk("Client[%d]: Connection with DFC service lost. "
		  "Exit by callback %d",
	TP_printk("DFC Client[%d] exit: callback %d",
		  __entry->idx, __entry->from_cb)
);

@@ -248,6 +239,29 @@ TRACE_EVENT(dfc_tx_link_status_ind,
		__entry->mid, __entry->bid)
);

TRACE_EVENT(dfc_qmap,

	TP_PROTO(const void *data, size_t len, bool in),

	TP_ARGS(data, len, in),

	TP_STRUCT__entry(
		__field(bool, in)
		__field(size_t, len)
		__dynamic_array(u8, data, len)
	),

	TP_fast_assign(
		__entry->in = in;
		__entry->len = len;
		memcpy(__get_dynamic_array(data), data, len);
	),

	TP_printk("%s [%s]",
		__entry->in ? "<--" : "-->",
		__print_hex(__get_dynamic_array(data), __entry->len))
);

#endif /* _TRACE_DFC_H */

/* This part must be outside protection */
+7 −5
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>
#include <soc/qcom/rmnet_qmi.h>
#include <soc/qcom/qmi_rmnet.h>
#include <trace/events/dfc.h>
#include <soc/qcom/rmnet_ctl.h>
#include "rmnet_ctl.h"
#include "dfc_defs.h"
#include "rmnet_qmi.h"
#include "qmi_rmnet.h"
#include "dfc.h"

#define QMAP_DFC_VER		1

@@ -148,6 +148,7 @@ static void dfc_qmap_send_inband_ack(struct dfc_qmi_data *dfc,
	skb->protocol = htons(ETH_P_MAP);
	skb->dev = rmnet_get_real_dev(dfc->rmnet_port);

	rmnet_ctl_log_debug("TXI", skb->data, skb->len);
	trace_dfc_qmap(skb->data, skb->len, false);
	dev_queue_xmit(skb);
}
@@ -433,6 +434,7 @@ static void dfc_qmap_send_end_marker_cnf(struct qos_info *qos,
	skb->dev = qos->real_dev;

	/* This cmd needs to be sent in-band */
	rmnet_ctl_log_info("TXI", skb->data, skb->len);
	trace_dfc_qmap(skb->data, skb->len, false);
	rmnet_map_tx_qmap_cmd(skb);
}
+67 −157
Original line number Diff line number Diff line
/*
 * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
 * Copyright (c) 2018-2020, 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
@@ -11,27 +11,14 @@
 * GNU General Public License for more details.
 */

#include <linux/rtnetlink.h>
#include <net/pkt_sched.h>
#include <linux/soc/qcom/qmi.h>
#include "rmnet_qmi.h"
#include "qmi_rmnet.h"
#include "dfc_defs.h"

#include "qmi_rmnet_i.h"
#define CREATE_TRACE_POINTS
#include "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

#define DFC_ACK_TYPE_DISABLE 1
#define DFC_ACK_TYPE_THRESHOLD 2

struct dfc_qmap_header {
	u8  pad_len:6;
	u8  reserved_bit:1;
@@ -56,20 +43,6 @@ struct dfc_ack_cmd {
	u8  bearer_id;
} __aligned(1);

struct dfc_qmi_data {
	void *rmnet_port;
	struct workqueue_struct *dfc_wq;
	struct work_struct svc_arrive;
	struct qmi_handle handle;
	struct sockaddr_qrtr ssctl;
	struct svc_info svc;
	struct work_struct qmi_ind_work;
	struct list_head qmi_ind_q;
	spinlock_t qmi_ind_lock;
	int index;
	int restart_state;
};

static void dfc_svc_init(struct work_struct *work);

/* **************************************************** */
@@ -115,28 +88,6 @@ struct dfc_indication_register_resp_msg_v01 {
	struct qmi_response_type_v01 resp;
};

enum dfc_ip_type_enum_v01 {
	DFC_IP_TYPE_ENUM_MIN_ENUM_VAL_V01 = -2147483647,
	DFC_IPV4_TYPE_V01 = 0x4,
	DFC_IPV6_TYPE_V01 = 0x6,
	DFC_IP_TYPE_ENUM_MAX_ENUM_VAL_V01 = 2147483647
};

struct dfc_qos_id_type_v01 {
	u32 qos_id;
	enum dfc_ip_type_enum_v01 ip_type;
};

struct dfc_flow_status_info_type_v01 {
	u8 subs_id;
	u8 mux_id;
	u8 bearer_id;
	u32 num_bytes;
	u16 seq_num;
	u8 qos_ids_len;
	struct dfc_qos_id_type_v01 qos_ids[DFC_MAX_QOS_ID_V01];
};

static struct qmi_elem_info dfc_qos_id_type_v01_ei[] = {
	{
		.data_type	= QMI_UNSIGNED_4_BYTE,
@@ -250,13 +201,6 @@ static struct qmi_elem_info dfc_flow_status_info_type_v01_ei[] = {
	},
};

struct dfc_ancillary_info_type_v01 {
	u8 subs_id;
	u8 mux_id;
	u8 bearer_id;
	u32 reserved;
};

static struct qmi_elem_info dfc_ancillary_info_type_v01_ei[] = {
	{
		.data_type	= QMI_UNSIGNED_1_BYTE,
@@ -309,31 +253,6 @@ static struct qmi_elem_info dfc_ancillary_info_type_v01_ei[] = {
	},
};

struct dfc_flow_status_ind_msg_v01 {
	u8 flow_status_valid;
	u8 flow_status_len;
	struct dfc_flow_status_info_type_v01 flow_status[DFC_MAX_BEARERS_V01];
	u8 eod_ack_reqd_valid;
	u8 eod_ack_reqd;
	u8 ancillary_info_valid;
	u8 ancillary_info_len;
	struct dfc_ancillary_info_type_v01 ancillary_info[DFC_MAX_BEARERS_V01];
};

struct dfc_bearer_info_type_v01 {
	u8 subs_id;
	u8 mux_id;
	u8 bearer_id;
	enum dfc_ip_type_enum_v01 ip_type;
};

struct dfc_tx_link_status_ind_msg_v01 {
	u8 tx_status;
	u8 bearer_info_valid;
	u8 bearer_info_len;
	struct dfc_bearer_info_type_v01 bearer_info[DFC_MAX_BEARERS_V01];
};

struct dfc_get_flow_status_req_msg_v01 {
	u8 bearer_id_list_valid;
	u8 bearer_id_list_len;
@@ -963,6 +882,11 @@ dfc_send_ack(struct net_device *dev, u8 bearer_id, u16 seq, u8 mux_id, u8 type)
	if (!qos)
		return;

	if (dfc_qmap) {
		dfc_qmap_send_ack(qos, bearer_id, seq, type);
		return;
	}

	skb = alloc_skb(data_size, GFP_ATOMIC);
	if (!skb)
		return;
@@ -995,75 +919,45 @@ int dfc_bearer_flow_ctl(struct net_device *dev,
			struct rmnet_bearer_map *bearer,
			struct qos_info *qos)
{
	struct rmnet_flow_map *itm;
	int rc = 0, qlen;
	int enable;
	bool enable;

	enable = bearer->grant_size ? 1 : 0;
	enable = bearer->grant_size ? true : false;

	list_for_each_entry(itm, &qos->flow_head, list) {
		if (itm->bearer_id == bearer->bearer_id) {
			/*
			 * Do not flow disable ancillary q if ancillary is true
			 */
			if (bearer->tcp_bidir && enable == 0 &&
					DFC_IS_ANCILLARY(itm->ip_type))
				continue;
	qmi_rmnet_flow_control(dev, bearer->mq_idx, enable);

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

	if (enable == 0 && bearer->ack_req)
	if (!enable && bearer->ack_req)
		dfc_send_ack(dev, bearer->bearer_id,
			     bearer->seq, qos->mux_id,
			     DFC_ACK_TYPE_DISABLE);

	return rc;
	return 0;
}

static int dfc_all_bearer_flow_ctl(struct net_device *dev,
				struct qos_info *qos, u8 ack_req, u32 ancillary,
				struct dfc_flow_status_info_type_v01 *fc_info)
{
	struct rmnet_bearer_map *bearer_itm;
	struct rmnet_flow_map *flow_itm;
	int rc = 0, qlen;
	bool enable;
	struct rmnet_bearer_map *bearer;

	enable = fc_info->num_bytes > 0 ? 1 : 0;

	list_for_each_entry(bearer_itm, &qos->bearer_head, list) {
		bearer_itm->grant_size = fc_info->num_bytes;
		bearer_itm->grant_thresh =
			qmi_rmnet_grant_per(bearer_itm->grant_size);
		bearer_itm->seq = fc_info->seq_num;
		bearer_itm->ack_req = ack_req;
		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(bearer, &qos->bearer_head, list) {
		bearer->grant_size = fc_info->num_bytes;
		bearer->grant_thresh =
			qmi_rmnet_grant_per(bearer->grant_size);
		bearer->seq = fc_info->seq_num;
		bearer->ack_req = ack_req;
		bearer->tcp_bidir = DFC_IS_TCP_BIDIR(ancillary);
		bearer->last_grant = fc_info->num_bytes;
		bearer->last_seq = fc_info->seq_num;

	list_for_each_entry(flow_itm, &qos->flow_head, list) {
		qlen = qmi_rmnet_flow_control(dev, flow_itm->tcm_handle,
					      enable);
		trace_dfc_qmi_tc(dev->name, flow_itm->bearer_id,
				 flow_itm->flow_id, fc_info->num_bytes,
				 qlen, flow_itm->tcm_handle, enable);
		rc++;
		dfc_bearer_flow_ctl(dev, bearer, qos);
	}

	if (enable == 0 && ack_req)
		dfc_send_ack(dev, fc_info->bearer_id,
			     fc_info->seq_num, fc_info->mux_id,
			     DFC_ACK_TYPE_DISABLE);

	return rc;
	return 0;
}

static int dfc_update_fc_map(struct net_device *dev, struct qos_info *qos,
@@ -1075,6 +969,9 @@ static int dfc_update_fc_map(struct net_device *dev, struct qos_info *qos,
	bool action = false;

	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) {
		/* The RAT switch flag indicates the start and end of
		 * the switch. Ignore indications in between.
@@ -1093,6 +990,11 @@ static int dfc_update_fc_map(struct net_device *dev, struct qos_info *qos,
		    (itm->grant_size > 0 && fc_info->num_bytes == 0))
			action = true;

		/* This is needed by qmap */
		if (dfc_qmap && itm->ack_req && !ack_req && itm->grant_size)
			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->seq = fc_info->seq_num;
@@ -1103,17 +1005,14 @@ static int dfc_update_fc_map(struct net_device *dev, struct qos_info *qos,

		if (action)
			rc = dfc_bearer_flow_ctl(dev, itm, qos);
	} else {
		pr_debug("grant %u before flow activate", fc_info->num_bytes);
		qos->default_grant = fc_info->num_bytes;
	}

	return rc;
}

static void dfc_do_burst_flow_control(struct dfc_qmi_data *dfc,
				      struct dfc_svc_ind *svc_ind)
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 = &svc_ind->d.dfc_info;
	struct net_device *dev;
	struct qos_info *qos;
	struct dfc_flow_status_info_type_v01 *flow_status;
@@ -1187,13 +1086,17 @@ static void dfc_update_tx_link_status(struct net_device *dev,
	if (!itm)
		return;

	/* If no change in tx status, ignore */
	if (itm->tx_off == !tx_status)
		return;

	if (itm->grant_size && !tx_status) {
		itm->grant_size = 0;
		itm->tcp_bidir = false;
		dfc_bearer_flow_ctl(dev, itm, qos);
	} else if (itm->grant_size == 0 && tx_status && !itm->rat_switch) {
		itm->grant_size = DEFAULT_GRANT;
		itm->grant_thresh = DEFAULT_GRANT;
		itm->grant_thresh = qmi_rmnet_grant_per(DEFAULT_GRANT);
		itm->seq = 0;
		itm->ack_req = 0;
		dfc_bearer_flow_ctl(dev, itm, qos);
@@ -1202,10 +1105,9 @@ static void dfc_update_tx_link_status(struct net_device *dev,
	itm->tx_off = !tx_status;
}

static void dfc_handle_tx_link_status_ind(struct dfc_qmi_data *dfc,
					  struct dfc_svc_ind *svc_ind)
void dfc_handle_tx_link_status_ind(struct dfc_qmi_data *dfc,
				   struct dfc_tx_link_status_ind_msg_v01 *ind)
{
	struct dfc_tx_link_status_ind_msg_v01 *ind = &svc_ind->d.tx_status;
	struct net_device *dev;
	struct qos_info *qos;
	struct dfc_bearer_info_type_v01 *bearer_info;
@@ -1267,10 +1169,12 @@ 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);
				dfc_do_burst_flow_control(
						dfc, &svc_ind->d.dfc_info);
			else if (svc_ind->msg_id ==
					QMI_DFC_TX_LINK_STATUS_IND_V01)
				dfc_handle_tx_link_status_ind(dfc, svc_ind);
				dfc_handle_tx_link_status_ind(
						dfc, &svc_ind->d.tx_status);
		}
		kfree(svc_ind);
	} while (1);
@@ -1518,22 +1422,28 @@ void dfc_qmi_client_exit(void *dfc_data)
void dfc_qmi_burst_check(struct net_device *dev, struct qos_info *qos,
			 int ip_type, u32 mark, unsigned int len)
{
	struct rmnet_bearer_map *bearer;
	struct rmnet_bearer_map *bearer = NULL;
	struct rmnet_flow_map *itm;
	u32 start_grant;

	spin_lock_bh(&qos->qos_lock);

	if (dfc_mode == DFC_MODE_MQ_NUM) {
		/* Mark is mq num */
		if (likely(mark < MAX_MQ_NUM))
			bearer = qos->mq[mark].bearer;
	} else {
		/* Mark is flow_id */
		itm = qmi_rmnet_get_flow_map(qos, mark, ip_type);
	if (unlikely(!itm))
		goto out;
		if (likely(itm))
			bearer = itm->bearer;
	}

	bearer = qmi_rmnet_get_bearer_map(qos, itm->bearer_id);
	if (unlikely(!bearer))
		goto out;

	trace_dfc_flow_check(dev->name, bearer->bearer_id,
			     len, bearer->grant_size);
			     len, mark, bearer->grant_size);

	if (!bearer->grant_size)
		goto out;
@@ -1588,7 +1498,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);
	dfc_do_burst_flow_control(data, &svc_ind->d.dfc_info);

done:
	kfree(svc_ind);
Loading