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

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

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

parents 0d30ec33 7abd8fd0
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -75,6 +75,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),
};
+5 −0
Original line number Diff line number Diff line
@@ -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 ipa3_qmi_get_data_stats(struct ipa_get_data_stats_req_msg_v01 *req,
	struct ipa_get_data_stats_resp_msg_v01 *resp);

+213 −0
Original line number Diff line number Diff line
@@ -90,6 +90,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
@@ -1756,6 +1760,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) {
@@ -2086,6 +2092,65 @@ 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;

			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,
@@ -2179,6 +2244,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;
@@ -4785,13 +4881,118 @@ 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);
@@ -4800,6 +5001,18 @@ 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);
			goto fail;
		}
	}

	dbgfs->dfile_outstanding_high = debugfs_create_u32("outstanding_high",
		read_write_mode, dbgfs->dent,
		&rmnet_ipa3_ctx->outstanding_high);
+22 −0
Original line number Diff line number Diff line
@@ -475,6 +475,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;
	}