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

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

Merge "msm: ipa: IPA driver changes for H/w fnr stats"

parents 465a26f8 1bb8ba82
Loading
Loading
Loading
Loading
+4 −1
Original line number Diff line number Diff line
/* Copyright (c) 2013-2018, The Linux Foundation. All rights reserved.
/* Copyright (c) 2013-2019, 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
@@ -283,6 +283,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_query_per_client_stats_v2(
	struct wan_ioctl_query_per_client_stats *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);

+207 −0
Original line number Diff line number Diff line
@@ -83,6 +83,8 @@ MODULE_PARM_DESC(outstanding_low, "Outstanding low");

#define IPA_WWAN_CONS_DESC_FIFO_SZ 256

#define LAN_STATS_FOR_ALL_CLIENTS 0xFFFFFFFF

static void rmnet_ipa_free_msg(void *buff, u32 len, u32 type);
static void rmnet_ipa_get_stats_and_update(void);

@@ -4025,6 +4027,54 @@ static inline int rmnet_ipa3_delete_lan_client_info
	return 0;
}

/* Query must be free-d by the caller */
static int rmnet_ipa_get_hw_fnr_stats_v2(
	struct ipa_lan_client_cntr_index *client,
	struct wan_ioctl_query_per_client_stats *data,
	struct ipa_ioc_flt_rt_query *query)
{
	int num_counters;

	query->start_id = client->ul_cnt_idx;
	query->end_id = client->dl_cnt_idx;

	query->reset = data->reset_stats;
	num_counters = query->end_id - query->start_id + 1;

	if (num_counters != 2) {
		IPAWANERR("Dont support more than 2 counter\n");
		return -EINVAL;
	}

	IPAWANDBG(" Start/End %u/%u, num counters = %d\n",
		query->start_id, query->end_id, num_counters);

	query->stats = (uint64_t)kcalloc(
			num_counters,
			sizeof(struct ipa_flt_rt_stats),
			GFP_KERNEL);
	if (!query->stats) {
		IPAERR("Failed to allocate memory for query stats\n");
		return -ENOMEM;
	}

	if (ipa_get_flt_rt_stats(query)) {
		IPAERR("Failed to request stats from h/w\n");
		return -EINVAL;
	}

	IPAWANDBG("ul: bytes = %llu, pkts = %u, pkts_hash = %u\n",
	  ((struct ipa_flt_rt_stats *)query->stats)[0].num_bytes,
	  ((struct ipa_flt_rt_stats *)query->stats)[0].num_pkts,
	  ((struct ipa_flt_rt_stats *)query->stats)[0].num_pkts_hash);
	IPAWANDBG("dl: bytes = %llu, pkts = %u, pkts_hash = %u\n",
	  ((struct ipa_flt_rt_stats *)query->stats)[1].num_bytes,
	  ((struct ipa_flt_rt_stats *)query->stats)[1].num_pkts,
	  ((struct ipa_flt_rt_stats *)query->stats)[1].num_pkts_hash);

	return 0;
}

/* rmnet_ipa3_set_lan_client_info() -
 * @data - IOCTL data
 *
@@ -4040,6 +4090,8 @@ int rmnet_ipa3_set_lan_client_info(
	struct wan_ioctl_lan_client_info *data)
{
	struct ipa_lan_client *lan_client = NULL;
	struct ipa_lan_client_cntr_index
		*client_index = NULL;
	struct ipa_tether_device_info *teth_ptr = NULL;


@@ -4061,6 +4113,14 @@ int rmnet_ipa3_set_lan_client_info(
		return -EINVAL;
	}

	/* This should be done when allocation of hw fnr counters happens */
	if (!(data->ul_cnt_idx > 0 &&
		data->dl_cnt_idx == (data->ul_cnt_idx + 1))) {
		IPAWANERR("Invalid counter indices %u, %u\n",
				data->ul_cnt_idx, data->dl_cnt_idx);
		return -EINVAL;
	}

	mutex_lock(&rmnet_ipa3_ctx->per_client_stats_guard);
	if (data->client_init) {
		/* check if the client is already inited. */
@@ -4075,6 +4135,7 @@ int rmnet_ipa3_set_lan_client_info(

	teth_ptr = &rmnet_ipa3_ctx->tether_device[data->device_type];
	lan_client = &teth_ptr->lan_client[data->client_idx];
	client_index = &teth_ptr->lan_client_indices[data->client_idx];

	memcpy(lan_client->mac, data->mac, IPA_MAC_ADDR_SIZE);

@@ -4088,6 +4149,13 @@ int rmnet_ipa3_set_lan_client_info(
	if (!rmnet_ipa3_ctx->tether_device[data->device_type].hdr_len)
		rmnet_ipa3_ctx->tether_device[data->device_type].hdr_len =
			data->hdr_len;
	client_index->ul_cnt_idx = data->ul_cnt_idx;
	client_index->dl_cnt_idx = data->dl_cnt_idx;

	IPAWANDBG("Device type %d, ul/dl = %d/%d\n",
			data->device_type,
			data->ul_cnt_idx,
			data->dl_cnt_idx);

	lan_client->inited = true;

@@ -4455,6 +4523,145 @@ int rmnet_ipa3_query_per_client_stats(
	return 0;
}

int rmnet_ipa3_query_per_client_stats_v2(
		struct wan_ioctl_query_per_client_stats *data)
{
	int lan_clnt_idx, i, j;
	struct ipa_lan_client *lan_client = NULL;
	struct ipa_lan_client_cntr_index
		*lan_client_index = NULL;
	struct ipa_tether_device_info *teth_ptr = NULL;
	struct ipa_ioc_flt_rt_query query_f;
	struct ipa_ioc_flt_rt_query *query = &query_f;
	struct ipa_flt_rt_stats *fnr_stats = NULL;
	int ret = 1;

	/* Check if Device type is valid. */
	if (data->device_type >= IPACM_MAX_CLIENT_DEVICE_TYPES ||
			data->device_type < 0) {
		IPAWANERR("Invalid Device type: %d\n", data->device_type);
		return -EINVAL;
	}

	/* Check if num_clients is valid. */
	if (data->num_clients != IPA_MAX_NUM_HW_PATH_CLIENTS &&
			data->num_clients != 1) {
		IPAWANERR("Invalid number of clients: %d\n", data->num_clients);
		return -EINVAL;
	}

	mutex_lock(&rmnet_ipa3_ctx->per_client_stats_guard);

	/* Check if Source pipe is valid. */
	if (rmnet_ipa3_ctx->tether_device
			[data->device_type].ul_src_pipe == -1) {
		IPAWANERR("Device not initialized: %d\n", data->device_type);
		mutex_unlock(&rmnet_ipa3_ctx->per_client_stats_guard);
		return -EINVAL;
	}

	/* Check if we have clients connected. */
	if (rmnet_ipa3_ctx->tether_device[data->device_type].num_clients == 0) {
		IPAWANERR("No clients connected: %d\n", data->device_type);
		mutex_unlock(&rmnet_ipa3_ctx->per_client_stats_guard);
		return -EINVAL;
	}

	if (data->num_clients == 1) {
		/* Check if the client info is valid.*/
		lan_clnt_idx = rmnet_ipa3_get_lan_client_info(
				data->device_type,
				data->client_info[0].mac);
		if (lan_clnt_idx < 0) {
			IPAWANERR("Client info not available return.\n");
			mutex_unlock(&rmnet_ipa3_ctx->per_client_stats_guard);
			return -EINVAL;
		}
	} else {
		/* Max number of clients. */
		/* Check if disconnect flag is set and
		 * see if all the clients info are cleared.
		 */
		if (data->disconnect_clnt &&
			rmnet_ipa3_check_any_client_inited(data->device_type)) {
			IPAWANERR("CLient not inited. Try again.\n");
			mutex_unlock(&rmnet_ipa3_ctx->per_client_stats_guard);
			return -EAGAIN;
		}
		lan_clnt_idx = LAN_STATS_FOR_ALL_CLIENTS;
	}

	IPAWANDBG("Query stats for client index (0x%x)\n",
		lan_clnt_idx);

	teth_ptr = &rmnet_ipa3_ctx->tether_device[data->device_type];
	lan_client = teth_ptr->lan_client;
	lan_client_index = teth_ptr->lan_client_indices;

	if (lan_clnt_idx == LAN_STATS_FOR_ALL_CLIENTS) {
		i = 0;
		j = IPA_MAX_NUM_HW_PATH_CLIENTS;
	} else {
		i = lan_clnt_idx;
		j = i + 1;
	}

	for (; i < j; i++) {
		if (!lan_client[i].inited && !data->disconnect_clnt)
			continue;

		IPAWANDBG("Client MAC %02x:%02x:%02x:%02x:%02x:%02x\n",
				lan_client[i].mac[0],
				lan_client[i].mac[1],
				lan_client[i].mac[2],
				lan_client[i].mac[3],
				lan_client[i].mac[4],
				lan_client[i].mac[5]);
		IPAWANDBG("Lan client %d inited\n", i);
		IPAWANDBG("Query stats ul/dl indices = %u/%u\n",
				lan_client_index[i].ul_cnt_idx,
				lan_client_index[i].dl_cnt_idx);
		memset(query, 0, sizeof(query_f));
		ret = rmnet_ipa_get_hw_fnr_stats_v2(&lan_client_index[i],
				data, query);
		if (ret) {
			IPAWANERR("Failed: Client type %d, idx %d\n",
					data->device_type, i);
			kfree((void *)query->stats);
			continue;
		}
		fnr_stats = &((struct ipa_flt_rt_stats *)
				query->stats)[0];
		data->client_info[i].ipv4_tx_bytes =
			fnr_stats->num_bytes;
		fnr_stats = &((struct ipa_flt_rt_stats *)
				query->stats)[1];
		data->client_info[i].ipv4_rx_bytes =
			fnr_stats->num_bytes;
		memcpy(data->client_info[i].mac,
				lan_client[i].mac,
				IPA_MAC_ADDR_SIZE);

		IPAWANDBG("Client ipv4_tx_bytes = %lu, ipv4_rx_bytes = %lu\n",
				data->client_info[i].ipv4_tx_bytes,
				data->client_info[i].ipv4_rx_bytes);

		kfree((void *)query->stats);
	}

	/* Legacy per-client stats */
	IPAWANDBG("Disconnect clnt: %s",
			data->disconnect_clnt?"Yes":"No");

	if (data->disconnect_clnt) {
		rmnet_ipa3_delete_lan_client_info(data->device_type,
				lan_clnt_idx);
	}

	mutex_unlock(&rmnet_ipa3_ctx->per_client_stats_guard);
	return ret;
}

static int __init ipa3_wwan_init(void)
{
	int i, j;
+6 −3
Original line number Diff line number Diff line
@@ -426,7 +426,10 @@ static long ipa3_wan_ioctl(struct file *filp,
			retval = -EFAULT;
			break;
		}

		if (ipa3_ctx->ipa_hw_type >= IPA_HW_v4_5)
			retval = rmnet_ipa3_query_per_client_stats_v2(
			  (struct wan_ioctl_query_per_client_stats *)param);
		else
			retval = rmnet_ipa3_query_per_client_stats(
			  (struct wan_ioctl_query_per_client_stats *)param);
		if (retval) {
+14 −0
Original line number Diff line number Diff line
@@ -170,6 +170,8 @@
#define IPA_FLT_RT_HW_COUNTER (120)
#define IPA_FLT_RT_SW_COUNTER \
	(IPA_MAX_FLT_RT_CNT_INDEX - IPA_FLT_RT_HW_COUNTER)
#define IPA_MAX_FLT_RT_CLIENTS 60


/**
 * the attributes of the rule (routing or filtering)
@@ -2412,6 +2414,16 @@ struct ipa_lan_client {
	uint8_t inited;
};

/**
 * struct ipa_lan_client_cntr_index
 * @ul_cnt_idx: H/w counter index for uplink stats
 * @dl_cnt_idx: H/w counter index for downlink stats
 */
struct ipa_lan_client_cntr_index {
	uint8_t ul_cnt_idx;
	uint8_t dl_cnt_idx;
};

/**
 * struct ipa_tether_device_info - tether device info indicated from IPACM
 * @ul_src_pipe: Source pipe of the lan client.
@@ -2423,6 +2435,8 @@ struct ipa_tether_device_info {
	uint8_t hdr_len;
	uint32_t num_clients;
	struct ipa_lan_client lan_client[IPA_MAX_NUM_HW_PATH_CLIENTS];
	struct ipa_lan_client_cntr_index
		lan_client_indices[IPA_MAX_NUM_HW_PATH_CLIENTS];
};

/**
+5 −1
Original line number Diff line number Diff line
/* Copyright (c) 2013-2018, The Linux Foundation. All rights reserved.
/* Copyright (c) 2013-2019, 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
@@ -158,6 +158,10 @@ struct wan_ioctl_lan_client_info {
	uint8_t hdr_len;
	/* Source pipe of the lan client. */
	enum ipa_client_type ul_src_pipe;
	/* Counter indices for h/w fnr stats */
#define IPA_HW_FNR_STATS
	uint8_t ul_cnt_idx;
	uint8_t dl_cnt_idx;
};

struct wan_ioctl_per_client_info {