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

Commit 8548f47a authored by Skylar Chang's avatar Skylar Chang
Browse files

msm: ipa4: add unit test for statistics



Add a unit test for IPA hardware statistics.

Change-Id: Ibd35feca0034070e2596ee93650b73acd711339b
CRs-Fixed: 2069977
Acked-by: default avatarAdy Abraham <adya@qti.qualcomm.com>
Signed-off-by: default avatarSkylar Chang <chiaweic@codeaurora.org>
parent 6f6e3076
Loading
Loading
Loading
Loading
+1 −1
Original line number Original line Diff line number Diff line
obj-$(CONFIG_IPA_UT) += ipa_ut_mod.o
obj-$(CONFIG_IPA_UT) += ipa_ut_mod.o
ipa_ut_mod-y := ipa_ut_framework.o ipa_test_example.o ipa_test_mhi.o ipa_test_dma.o
ipa_ut_mod-y := ipa_ut_framework.o ipa_test_example.o ipa_test_mhi.o ipa_test_dma.o ipa_test_hw_stats.o
+330 −0
Original line number Original line Diff line number Diff line
/* Copyright (c) 2017, 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
 * only version 2 as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 */

#include "ipa_ut_framework.h"
#include <linux/netdevice.h>

struct ipa_test_hw_stats_ctx {
	u32 odu_prod_hdl;
	u32 odu_cons_hdl;
	u32 rt4_usb;
	u32 rt6_usb;
	u32 rt4_odu_cons;
	u32 rt6_odu_cons;
	atomic_t odu_pending;
};

static struct ipa_test_hw_stats_ctx *ctx;

static int ipa_test_hw_stats_suite_setup(void **ppriv)
{
	IPA_UT_DBG("Start Setup\n");

	if (!ctx)
		ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);

	return 0;
}

static int ipa_test_hw_stats_suite_teardown(void *priv)
{
	IPA_UT_DBG("Start Teardown\n");

	return 0;
}

static void odu_prod_notify(void *priv, enum ipa_dp_evt_type evt,
	unsigned long data)
{
	struct sk_buff *skb = (struct sk_buff *)data;

	switch (evt) {
	case IPA_RECEIVE:
		dev_kfree_skb_any(skb);
		break;
	case IPA_WRITE_DONE:
		atomic_dec(&ctx->odu_pending);
		dev_kfree_skb_any(skb);
		break;
	default:
		IPA_UT_ERR("unexpected evt %d\n", evt);
	}
}
static void odu_cons_notify(void *priv, enum ipa_dp_evt_type evt,
	unsigned long data)
{
	struct sk_buff *skb = (struct sk_buff *)data;
	int ret;

	switch (evt) {
	case IPA_RECEIVE:
		if (atomic_read(&ctx->odu_pending) >= 64)
			msleep(20);
		atomic_inc(&ctx->odu_pending);
		skb_put(skb, 100);
		ret = ipa_tx_dp(IPA_CLIENT_ODU_PROD, skb, NULL);
		while (ret) {
			msleep(100);
			ret = ipa_tx_dp(IPA_CLIENT_ODU_PROD, skb, NULL);
		}
		break;
	case IPA_WRITE_DONE:
		dev_kfree_skb_any(skb);
		break;
	default:
		IPA_UT_ERR("unexpected evt %d\n", evt);
	}
}

static int ipa_test_hw_stats_configure(void *priv)
{
	struct ipa_sys_connect_params odu_prod_params;
	struct ipa_sys_connect_params odu_emb_cons_params;
	int res;

	/* first connect all additional pipe */
	memset(&odu_prod_params, 0, sizeof(odu_prod_params));
	memset(&odu_emb_cons_params, 0, sizeof(odu_emb_cons_params));

	odu_prod_params.client = IPA_CLIENT_ODU_PROD;
	odu_prod_params.desc_fifo_sz = 0x1000;
	odu_prod_params.priv = NULL;
	odu_prod_params.notify = odu_prod_notify;
	res = ipa_setup_sys_pipe(&odu_prod_params,
		&ctx->odu_prod_hdl);
	if (res) {
		IPA_UT_ERR("fail to setup sys pipe ODU_PROD %d\n", res);
		return res;
	}

	odu_emb_cons_params.client = IPA_CLIENT_ODU_EMB_CONS;
	odu_emb_cons_params.desc_fifo_sz = 0x1000;
	odu_emb_cons_params.priv = NULL;
	odu_emb_cons_params.notify = odu_cons_notify;
	res = ipa_setup_sys_pipe(&odu_emb_cons_params,
		&ctx->odu_cons_hdl);
	if (res) {
		IPA_UT_ERR("fail to setup sys pipe ODU_EMB_CONS %d\n", res);
		ipa_teardown_sys_pipe(ctx->odu_prod_hdl);
		return res;
	}

	IPA_UT_INFO("Configured. Please connect USB RNDIS now\n");

	return 0;
}

static int ipa_test_hw_stats_add_FnR(void *priv)
{
	struct ipa_ioc_add_rt_rule *rt_rule;
	struct ipa_ioc_add_flt_rule *flt_rule;
	struct ipa_ioc_get_rt_tbl rt_lookup;
	int ret;

	rt_rule = kzalloc(sizeof(*rt_rule) + 1 * sizeof(struct ipa_rt_rule_add),
		GFP_KERNEL);
	if (!rt_rule) {
		IPA_UT_DBG("no mem\n");
		return -ENOMEM;
	}

	flt_rule = kzalloc(sizeof(*flt_rule) +
		1 * sizeof(struct ipa_flt_rule_add), GFP_KERNEL);
	if (!flt_rule) {
		IPA_UT_DBG("no mem\n");
		ret = -ENOMEM;
		goto free_rt;
	}

	rt_rule->commit = 1;
	rt_rule->ip = IPA_IP_v4;
	rt_lookup.ip = rt_rule->ip;
	strlcpy(rt_rule->rt_tbl_name, "V4_RT_TO_USB_CONS",
		IPA_RESOURCE_NAME_MAX);
	strlcpy(rt_lookup.name, rt_rule->rt_tbl_name, IPA_RESOURCE_NAME_MAX);
	rt_rule->num_rules = 1;
	rt_rule->rules[0].rule.dst = IPA_CLIENT_USB_CONS;
	rt_rule->rules[0].rule.attrib.attrib_mask = IPA_FLT_DST_PORT;
	rt_rule->rules[0].rule.attrib.dst_port = 5002;
	rt_rule->rules[0].rule.hashable = true;
	if (ipa_add_rt_rule(rt_rule) || rt_rule->rules[0].status) {
		IPA_UT_ERR("failed to install V4 rules\n");
		ret = -EFAULT;
		goto free_flt;
	}
	if (ipa_get_rt_tbl(&rt_lookup)) {
		IPA_UT_ERR("failed to query V4 rules\n");
		ret = -EFAULT;
		goto free_flt;
	}
	ctx->rt4_usb = rt_lookup.hdl;

	memset(rt_rule, 0, sizeof(*rt_rule));
	rt_rule->commit = 1;
	rt_rule->ip = IPA_IP_v6;
	rt_lookup.ip = rt_rule->ip;
	strlcpy(rt_rule->rt_tbl_name, "V6_RT_TO_USB_CONS",
		IPA_RESOURCE_NAME_MAX);
	strlcpy(rt_lookup.name, rt_rule->rt_tbl_name, IPA_RESOURCE_NAME_MAX);
	rt_rule->num_rules = 1;
	rt_rule->rules[0].rule.dst = IPA_CLIENT_USB_CONS;
	rt_rule->rules[0].rule.attrib.attrib_mask = IPA_FLT_DST_PORT;
	rt_rule->rules[0].rule.attrib.dst_port = 5002;
	rt_rule->rules[0].rule.hashable = true;
	if (ipa_add_rt_rule(rt_rule) || rt_rule->rules[0].status) {
		IPA_UT_ERR("failed to install V4 rules\n");
		ret = -EFAULT;
		goto free_flt;
	}
	if (ipa_get_rt_tbl(&rt_lookup)) {
		IPA_UT_ERR("failed to query V4 rules\n");
		ret = -EFAULT;
		goto free_flt;
	}
	ctx->rt6_usb = rt_lookup.hdl;

	memset(rt_rule, 0, sizeof(*rt_rule));
	rt_rule->commit = 1;
	rt_rule->ip = IPA_IP_v4;
	rt_lookup.ip = rt_rule->ip;
	strlcpy(rt_rule->rt_tbl_name, "V4_RT_TO_ODU_CONS",
		IPA_RESOURCE_NAME_MAX);
	strlcpy(rt_lookup.name, rt_rule->rt_tbl_name, IPA_RESOURCE_NAME_MAX);
	rt_rule->num_rules = 1;
	rt_rule->rules[0].rule.dst = IPA_CLIENT_ODU_EMB_CONS;
	rt_rule->rules[0].rule.attrib.attrib_mask = IPA_FLT_DST_PORT;
	rt_rule->rules[0].rule.attrib.dst_port = 5002;
	rt_rule->rules[0].rule.hashable = true;
	if (ipa_add_rt_rule(rt_rule) || rt_rule->rules[0].status) {
		IPA_UT_ERR("failed to install V4 rules\n");
		ret = -EFAULT;
		goto free_flt;
	}
	if (ipa_get_rt_tbl(&rt_lookup)) {
		IPA_UT_ERR("failed to query V4 rules\n");
		return -EFAULT;
	}
	ctx->rt4_odu_cons = rt_lookup.hdl;

	memset(rt_rule, 0, sizeof(*rt_rule));
	rt_rule->commit = 1;
	rt_rule->ip = IPA_IP_v6;
	rt_lookup.ip = rt_rule->ip;
	strlcpy(rt_rule->rt_tbl_name, "V6_RT_TO_ODU_CONS",
		IPA_RESOURCE_NAME_MAX);
	strlcpy(rt_lookup.name, rt_rule->rt_tbl_name, IPA_RESOURCE_NAME_MAX);
	rt_rule->num_rules = 1;
	rt_rule->rules[0].rule.dst = IPA_CLIENT_ODU_EMB_CONS;
	rt_rule->rules[0].rule.attrib.attrib_mask = IPA_FLT_DST_PORT;
	rt_rule->rules[0].rule.attrib.dst_port = 5002;
	rt_rule->rules[0].rule.hashable = true;
	if (ipa_add_rt_rule(rt_rule) || rt_rule->rules[0].status) {
		IPA_UT_ERR("failed to install V4 rules\n");
		ret = -EFAULT;
		goto free_flt;
	}
	if (ipa_get_rt_tbl(&rt_lookup)) {
		IPA_UT_ERR("failed to query V4 rules\n");
		ret = -EFAULT;
		goto free_flt;
	}
	ctx->rt6_odu_cons = rt_lookup.hdl;

	flt_rule->commit = 1;
	flt_rule->ip = IPA_IP_v4;
	flt_rule->ep = IPA_CLIENT_USB_PROD;
	flt_rule->num_rules = 1;
	flt_rule->rules[0].at_rear = 1;
	flt_rule->rules[0].rule.action = IPA_PASS_TO_ROUTING;
	flt_rule->rules[0].rule.attrib.attrib_mask = IPA_FLT_DST_PORT;
	flt_rule->rules[0].rule.attrib.dst_port = 5002;
	flt_rule->rules[0].rule.rt_tbl_hdl = ctx->rt4_odu_cons;
	flt_rule->rules[0].rule.hashable = 1;
	if (ipa_add_flt_rule(flt_rule) || flt_rule->rules[0].status) {
		IPA_UT_ERR("failed to install V4 rules\n");
		ret = -EFAULT;
		goto free_flt;
	}

	memset(flt_rule, 0, sizeof(*flt_rule));
	flt_rule->commit = 1;
	flt_rule->ip = IPA_IP_v6;
	flt_rule->ep = IPA_CLIENT_USB_PROD;
	flt_rule->num_rules = 1;
	flt_rule->rules[0].at_rear = 1;
	flt_rule->rules[0].rule.action = IPA_PASS_TO_ROUTING;
	flt_rule->rules[0].rule.attrib.attrib_mask = IPA_FLT_DST_PORT;
	flt_rule->rules[0].rule.attrib.dst_port = 5002;
	flt_rule->rules[0].rule.rt_tbl_hdl = ctx->rt6_odu_cons;
	flt_rule->rules[0].rule.hashable = 1;
	if (ipa_add_flt_rule(flt_rule) || flt_rule->rules[0].status) {
		IPA_UT_ERR("failed to install V6 rules\n");
		ret = -EFAULT;
		goto free_flt;
	}

	memset(flt_rule, 0, sizeof(*flt_rule));
	flt_rule->commit = 1;
	flt_rule->ip = IPA_IP_v4;
	flt_rule->ep = IPA_CLIENT_ODU_PROD;
	flt_rule->num_rules = 1;
	flt_rule->rules[0].at_rear = 1;
	flt_rule->rules[0].rule.action = IPA_PASS_TO_ROUTING;
	flt_rule->rules[0].rule.attrib.attrib_mask = IPA_FLT_DST_PORT;
	flt_rule->rules[0].rule.attrib.dst_port = 5002;
	flt_rule->rules[0].rule.rt_tbl_hdl = ctx->rt4_usb;
	flt_rule->rules[0].rule.hashable = 1;
	if (ipa_add_flt_rule(flt_rule) || flt_rule->rules[0].status) {
		IPA_UT_ERR("failed to install V4 rules\n");
		ret = -EFAULT;
		goto free_flt;
	}

	memset(flt_rule, 0, sizeof(*flt_rule));
	flt_rule->commit = 1;
	flt_rule->ip = IPA_IP_v6;
	flt_rule->ep = IPA_CLIENT_ODU_PROD;
	flt_rule->num_rules = 1;
	flt_rule->rules[0].at_rear = 1;
	flt_rule->rules[0].rule.action = IPA_PASS_TO_ROUTING;
	flt_rule->rules[0].rule.attrib.attrib_mask = IPA_FLT_DST_PORT;
	flt_rule->rules[0].rule.attrib.dst_port = 5002;
	flt_rule->rules[0].rule.rt_tbl_hdl = ctx->rt6_usb;
	flt_rule->rules[0].rule.hashable = 1;
	if (ipa_add_flt_rule(flt_rule) || flt_rule->rules[0].status) {
		IPA_UT_ERR("failed to install V6 rules\n");
		ret = -EFAULT;
		goto free_flt;
	}

	IPA_UT_INFO(
		"Rules added. Please start data transfer on ports 5001/5002\n");
	ret = 0;
free_flt:
	kfree(flt_rule);
free_rt:
	kfree(rt_rule);
	return ret;

}

/* Suite definition block */
IPA_UT_DEFINE_SUITE_START(hw_stats, "HW stats test",
	ipa_test_hw_stats_suite_setup, ipa_test_hw_stats_suite_teardown)
{
	IPA_UT_ADD_TEST(configure, "Configure the setup",
		ipa_test_hw_stats_configure, false, IPA_HW_v4_0, IPA_HW_MAX),

	IPA_UT_ADD_TEST(add_rules, "Add FLT and RT rules",
		ipa_test_hw_stats_add_FnR, false, IPA_HW_v4_0, IPA_HW_MAX),

} IPA_UT_DEFINE_SUITE_END(hw_stats);
+2 −0
Original line number Original line Diff line number Diff line
@@ -23,6 +23,7 @@
IPA_UT_DECLARE_SUITE(mhi);
IPA_UT_DECLARE_SUITE(mhi);
IPA_UT_DECLARE_SUITE(dma);
IPA_UT_DECLARE_SUITE(dma);
IPA_UT_DECLARE_SUITE(example);
IPA_UT_DECLARE_SUITE(example);
IPA_UT_DECLARE_SUITE(hw_stats);




/**
/**
@@ -34,6 +35,7 @@ IPA_UT_DEFINE_ALL_SUITES_START
	IPA_UT_REGISTER_SUITE(mhi),
	IPA_UT_REGISTER_SUITE(mhi),
	IPA_UT_REGISTER_SUITE(dma),
	IPA_UT_REGISTER_SUITE(dma),
	IPA_UT_REGISTER_SUITE(example),
	IPA_UT_REGISTER_SUITE(example),
	IPA_UT_REGISTER_SUITE(hw_stats),
} IPA_UT_DEFINE_ALL_SUITES_END;
} IPA_UT_DEFINE_ALL_SUITES_END;


#endif /* _IPA_UT_SUITE_LIST_H_ */
#endif /* _IPA_UT_SUITE_LIST_H_ */