Эх сурвалжийг харах

Merge "msm: ipa: Add new IOCTLs to get and set MTU"

qctecmdr 4 жил өмнө
parent
commit
ef2c61e385

+ 1 - 0
drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c

@@ -83,6 +83,7 @@ const char *ipa3_event_name[IPA_EVENT_MAX_NUM] = {
 	__stringify(IPA_GSB_DISCONNECT),
 	__stringify(IPA_COALESCE_ENABLE),
 	__stringify(IPA_COALESCE_DISABLE),
+	__stringify(IPA_SET_MTU),
 	__stringify_1(WIGIG_CLIENT_CONNECT),
 	__stringify_1(WIGIG_FST_SWITCH),
 	__stringify(IPA_PDN_DEFAULT_MODE_CONFIG),

+ 6 - 1
drivers/platform/msm/ipa/ipa_v3/ipa_qmi_service.h

@@ -1,6 +1,6 @@
 /* SPDX-License-Identifier: GPL-2.0-only */
 /*
- * Copyright (c) 2013-2020, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2021, The Linux Foundation. All rights reserved.
  */
 
 #ifndef IPA_QMI_SERVICE_H
@@ -121,6 +121,8 @@ struct ipa3_rmnet_mux_val {
 	bool ul_flt_reg;
 	bool mux_hdr_set;
 	uint32_t  hdr_hdl;
+	uint16_t mtu_v4;
+	uint16_t mtu_v6;
 };
 
 extern struct qmi_elem_info
@@ -305,6 +307,9 @@ int rmnet_ipa3_enable_per_client_stats(bool *data);
 int rmnet_ipa3_query_per_client_stats(
 	struct wan_ioctl_query_per_client_stats *data);
 
+int rmnet_ipa3_get_wan_mtu(
+	struct ipa_mtu_info *data);
+
 int rmnet_ipa3_query_per_client_stats_v2(
 	struct wan_ioctl_query_per_client_stats *data);
 

+ 216 - 0
drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c

@@ -93,6 +93,10 @@ static DECLARE_DELAYED_WORK(ipa_tether_stats_poll_wakequeue_work,
 static int rmnet_ipa_send_coalesce_notification(uint8_t qmap_id, bool enable,
 					bool tcp, bool udp);
 
+static int rmnet_ipa_send_set_mtu_notification(char *if_name,
+					uint16_t mtu_v4, uint16_t mtu_v6, enum ipa_ip_type ip);
+
+
 enum ipa3_wwan_device_status {
 	WWAN_DEVICE_INACTIVE = 0,
 	WWAN_DEVICE_ACTIVE   = 1
@@ -2348,6 +2352,8 @@ static int ipa3_wwan_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 	struct mutex *mux_mutex_ptr;
 	int wan_ep;
 	bool tcp_en = false, udp_en = false;
+	bool mtu_v4_set = false, mtu_v6_set = false;
+	enum ipa_ip_type iptype;
 
 	IPAWANDBG("rmnet_ipa got ioctl number 0x%08x", cmd);
 	switch (cmd) {
@@ -2678,6 +2684,66 @@ static int ipa3_wwan_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 			}
 			mutex_unlock(&rmnet_ipa3_ctx->clock_vote.mutex);
 			break;
+		/* Get MTU */
+		case RMNET_IOCTL_GET_MTU:
+			mux_channel = rmnet_ipa3_ctx->mux_channel;
+			rmnet_index =
+				find_vchannel_name_index(ext_ioctl_data.u.mtu_params.if_name);
+
+			if (rmnet_index == MAX_NUM_OF_MUX_CHANNEL) {
+				IPAWANERR("%s is an invalid iface name\n",
+					ext_ioctl_data.u.mtu_params.if_name);
+				return -ENODEV;
+			}
+
+			IPAWANDBG("getting v4 MTU = %d\n", mux_channel[rmnet_index].mtu_v4);
+			ext_ioctl_data.u.mtu_params.mtu_v4 =
+				mux_channel[rmnet_index].mtu_v4;
+
+			IPAWANDBG("getting v6 MTU = %d\n", mux_channel[rmnet_index].mtu_v6);
+			ext_ioctl_data.u.mtu_params.mtu_v6 =
+				mux_channel[rmnet_index].mtu_v6;
+			break;
+		/* Set MTU */
+		case RMNET_IOCTL_SET_MTU:
+			mux_channel = rmnet_ipa3_ctx->mux_channel;
+			rmnet_index =
+				find_vchannel_name_index(ext_ioctl_data.u.mtu_params.if_name);
+
+			if (rmnet_index == MAX_NUM_OF_MUX_CHANNEL) {
+				IPAWANERR("%s is an invalid iface name\n",
+					ext_ioctl_data.u.mtu_params.if_name);
+				return -ENODEV;
+			}
+
+			/* V4 case */
+			if (ext_ioctl_data.u.mtu_params.mtu_v4 > 0) {
+				mux_channel[rmnet_index].mtu_v4 =
+					ext_ioctl_data.u.mtu_params.mtu_v4;
+				mtu_v4_set = true;
+				IPAWANDBG("Set v4 MTU = %d\n", mux_channel[rmnet_index].mtu_v4);
+				iptype = IPA_IP_v4;
+			}
+			/* V6 case */
+			if (ext_ioctl_data.u.mtu_params.mtu_v6 > 0) {
+				mux_channel[rmnet_index].mtu_v6 =
+					ext_ioctl_data.u.mtu_params.mtu_v6;
+				mtu_v6_set = true;
+				IPAWANDBG("Set v6 MTU = %d\n", mux_channel[rmnet_index].mtu_v6);
+				iptype = IPA_IP_v6;
+			}
+
+			if (mtu_v4_set && mtu_v6_set)
+				iptype = IPA_IP_MAX;
+
+			if (mtu_v4_set || mtu_v6_set)
+				rc = rmnet_ipa_send_set_mtu_notification(
+						ext_ioctl_data.u.mtu_params.if_name,
+						mux_channel[rmnet_index].mtu_v4,
+						mux_channel[rmnet_index].mtu_v6,
+						iptype);
+
+			break;
 		default:
 			IPAWANERR("[%s] unsupported extended cmd[%d]",
 				dev->name,
@@ -2808,6 +2874,37 @@ static int rmnet_ipa_send_coalesce_notification(uint8_t qmap_id,
 	return 0;
 }
 
+static int rmnet_ipa_send_set_mtu_notification(char *if_name,
+		uint16_t mtu_v4, uint16_t mtu_v6, enum ipa_ip_type ip)
+{
+	struct ipa_msg_meta msg_meta;
+	struct ipa_mtu_info *mtu_info;
+	int rc;
+
+	memset(&msg_meta, 0, sizeof(struct ipa_msg_meta));
+	mtu_info = kzalloc(sizeof(*mtu_info), GFP_KERNEL);
+	if (!mtu_info)
+		return -ENOMEM;
+
+	strlcpy(mtu_info->if_name, if_name, IPA_RESOURCE_NAME_MAX);
+	mtu_info->mtu_v4 = mtu_v4;
+	mtu_info->mtu_v6 = mtu_v6;
+	mtu_info->ip_type = ip;
+	msg_meta.msg_type = IPA_SET_MTU;
+	msg_meta.msg_len = sizeof(struct ipa_mtu_info);
+
+	rc = ipa_send_msg(&msg_meta, mtu_info, ipa3_wwan_msg_free_cb);
+	if (rc) {
+		IPAWANERR("ipa_send_msg failed: %d\n", rc);
+		return -EFAULT;
+	}
+	IPAWANDBG(
+		"sent new mtu_v4(%d)/mtu_v6(%d) with iptype(%d) for iface(%s) to IPACM",
+		mtu_v4, mtu_v6, ip, if_name);
+
+	return 0;
+}
+
 int ipa3_wwan_set_modem_state(struct wan_ioctl_notify_wan_state *state)
 {
 	uint32_t bw_mbps = 0;
@@ -5536,11 +5633,116 @@ int rmnet_ipa3_query_per_client_stats(
 	return 0;
 }
 
+/* rmnet_ipa3_get_wan_mtu() -
+ * @data - IOCTL data
+ *
+ * This function handles WAN_IOC_GET_WAN_MTU.
+ * It is used to send WAN MTU information to IPACM.
+ *
+ * Return codes:
+ * 0: Success
+ * -EINVAL: Invalid args provided
+ */
+int rmnet_ipa3_get_wan_mtu(
+	struct ipa_mtu_info *data)
+{
+	struct ipa3_rmnet_mux_val *mux_channel;
+	int rmnet_index;
+
+	mux_channel = rmnet_ipa3_ctx->mux_channel;
+	rmnet_index =
+		find_vchannel_name_index(data->if_name);
+
+	if (rmnet_index == MAX_NUM_OF_MUX_CHANNEL) {
+		IPAWANERR("%s is an invalid iface name\n",
+			data->if_name);
+		return -ENODEV;
+	}
+
+	IPAWANDBG("getting v4 MTU = %d\n", mux_channel[rmnet_index].mtu_v4);
+	data->mtu_v4 =
+		mux_channel[rmnet_index].mtu_v4;
+
+	IPAWANDBG("getting v6 MTU = %d\n", mux_channel[rmnet_index].mtu_v6);
+	data->mtu_v6 =
+		mux_channel[rmnet_index].mtu_v6;
+
+	return 0;
+}
 #ifdef CONFIG_DEBUG_FS
+static char dbg_buff[4096];
+
+static ssize_t rmnet_ipa_set_mtu(struct file *file,
+		const char __user *buf, size_t count, loff_t *ppos)
+{
+	__s8    if_name[IFNAMSIZ];
+	uint16_t mtu_v4 = 0, mtu_v6 = 0;
+	unsigned long missing;
+	char *sptr, *token;
+
+	if (count >= sizeof(dbg_buff))
+		return -EFAULT;
+
+	missing = copy_from_user(dbg_buff, buf, count);
+	if (missing)
+		return -EFAULT;
+
+	dbg_buff[count] = '\0';
+
+	sptr = dbg_buff;
+
+	memset(if_name, 0, IFNAMSIZ);
+	token = strsep(&sptr, " ");
+	if (!token)
+		return -EINVAL;
+	strlcpy(if_name, token, IFNAMSIZ);
+
+	token = strsep(&sptr, " ");
+	if (!token)
+		return -EINVAL;
+	if (kstrtou16(token, 0, &mtu_v4))
+		return -EINVAL;
+
+	token = strsep(&sptr, " ");
+	if (!token)
+		return -EINVAL;
+	if (kstrtou16(token, 0, &mtu_v6))
+		return -EINVAL;
+
+	rmnet_ipa_send_set_mtu_notification(
+		if_name,
+		mtu_v4,
+		mtu_v6, IPA_IP_MAX);
+
+	return count;
+}
+
+
+#define RMNET_IPA_WRITE_ONLY_MODE 0220
+
+struct rmnet_ipa_debugfs_file {
+	const char *name;
+	umode_t mode;
+	void *data;
+	const struct file_operations fops;
+};
+
+static const struct rmnet_ipa_debugfs_file debugfs_files[] = {
+	{
+		"mtu", RMNET_IPA_WRITE_ONLY_MODE, NULL, {
+			.write = rmnet_ipa_set_mtu,
+		}
+	},
+};
+
 static void rmnet_ipa_debugfs_init(void)
 {
 	const mode_t read_write_mode = 0664;
+	int i = 0;
+	struct dentry *file;
 	struct rmnet_ipa_debugfs *dbgfs = &rmnet_ipa3_ctx->dbgfs;
+	const size_t debugfs_files_num =
+		sizeof(debugfs_files) / sizeof(struct rmnet_ipa_debugfs_file);
 
 
 	dbgfs->dent = debugfs_create_dir("rmnet_ipa", 0);
@@ -5549,6 +5751,20 @@ static void rmnet_ipa_debugfs_init(void)
 		return;
 	}
 
+	for (i = 0; i < debugfs_files_num; ++i) {
+		const struct rmnet_ipa_debugfs_file *curr = &debugfs_files[i];
+
+		file = debugfs_create_file(curr->name, curr->mode, dbgfs->dent,
+			curr->data, &curr->fops);
+		if (!file || IS_ERR(file)) {
+			IPAERR("fail to create file for debug_fs %s\n",
+				curr->name);
+			debugfs_remove_recursive(dbgfs->dent);
+			memset(dbgfs, 0, sizeof(struct rmnet_ipa_debugfs));
+			return;
+		}
+	}
+
 	debugfs_create_u32("outstanding_high",
 		read_write_mode, dbgfs->dent,
 		&rmnet_ipa3_ctx->outstanding_high);

+ 23 - 1
drivers/platform/msm/ipa/ipa_v3/rmnet_ipa_fd_ioctl.c

@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
- * Copyright (c) 2013-2019, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2021, The Linux Foundation. All rights reserved.
  */
 
 #include <linux/init.h>
@@ -478,6 +478,28 @@ static long ipa3_wan_ioctl(struct file *filp,
 		}
 		break;
 
+	case WAN_IOC_GET_WAN_MTU:
+		IPAWANDBG_LOW("got WAN_IOC_GET_WAN_MTU :>>>\n");
+		pyld_sz = sizeof(struct ipa_mtu_info);
+		param = memdup_user((const void __user *)arg, pyld_sz);
+		if (IS_ERR(param)) {
+			retval = PTR_ERR(param);
+			break;
+		}
+		if (rmnet_ipa3_get_wan_mtu(
+			(struct ipa_mtu_info *)
+			param)) {
+			IPAWANERR("WAN_IOC_GET_WAN_MTU failed\n");
+			retval = -EFAULT;
+			break;
+		}
+
+		if (copy_to_user((void __user *)arg, param, pyld_sz)) {
+			retval = -EFAULT;
+			break;
+		}
+		break;
+
 	default:
 		retval = -ENOTTY;
 	}