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

Commit af2c9a52 authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "msm: ipa: store IPA status for debug"

parents 91cab8ef e2b9daf5
Loading
Loading
Loading
Loading
+90 −0
Original line number Diff line number Diff line
@@ -22,6 +22,9 @@
#define IPA_DBG_CNTR_ON 127265
#define IPA_DBG_CNTR_OFF 127264

#define IPA_DUMP_STATUS_FIELD(f) \
	pr_err(#f "=0x%x\n", status->f)

const char *ipa_excp_name[] = {
	__stringify_1(IPA_A5_MUX_HDR_EXCP_RSVD0),
	__stringify_1(IPA_A5_MUX_HDR_EXCP_RSVD1),
@@ -102,6 +105,7 @@ static struct dentry *dfile_dbg_cnt;
static struct dentry *dfile_msg;
static struct dentry *dfile_ip4_nat;
static struct dentry *dfile_rm_stats;
static struct dentry *dfile_status_stats;
static char dbg_buff[IPA_MAX_MSG_LEN];
static s8 ep_reg_idx;

@@ -1468,6 +1472,81 @@ static ssize_t ipa_rm_read_stats(struct file *file, char __user *ubuf,
	return simple_read_from_buffer(ubuf, count, ppos, dbg_buff, cnt);
}

static void ipa_dump_status(struct ipa_hw_pkt_status *status)
{
	IPA_DUMP_STATUS_FIELD(status_opcode);
	IPA_DUMP_STATUS_FIELD(exception);
	IPA_DUMP_STATUS_FIELD(status_mask);
	IPA_DUMP_STATUS_FIELD(pkt_len);
	IPA_DUMP_STATUS_FIELD(endp_src_idx);
	IPA_DUMP_STATUS_FIELD(endp_dest_idx);
	IPA_DUMP_STATUS_FIELD(metadata);

	if (ipa_ctx->ipa_hw_type < IPA_HW_v2_5) {
		IPA_DUMP_STATUS_FIELD(ipa_hw_v2_0_pkt_status.filt_local);
		IPA_DUMP_STATUS_FIELD(ipa_hw_v2_0_pkt_status.filt_global);
		IPA_DUMP_STATUS_FIELD(ipa_hw_v2_0_pkt_status.filt_pipe_idx);
		IPA_DUMP_STATUS_FIELD(ipa_hw_v2_0_pkt_status.filt_match);
		IPA_DUMP_STATUS_FIELD(ipa_hw_v2_0_pkt_status.filt_rule_idx);
		IPA_DUMP_STATUS_FIELD(ipa_hw_v2_0_pkt_status.ret_hdr);
		IPA_DUMP_STATUS_FIELD(ipa_hw_v2_0_pkt_status.tag_f_1);
	} else {
		IPA_DUMP_STATUS_FIELD(ipa_hw_v2_5_pkt_status.filt_local);
		IPA_DUMP_STATUS_FIELD(ipa_hw_v2_5_pkt_status.filt_global);
		IPA_DUMP_STATUS_FIELD(ipa_hw_v2_5_pkt_status.filt_pipe_idx);
		IPA_DUMP_STATUS_FIELD(ipa_hw_v2_5_pkt_status.ret_hdr);
		IPA_DUMP_STATUS_FIELD(ipa_hw_v2_5_pkt_status.filt_rule_idx);
		IPA_DUMP_STATUS_FIELD(ipa_hw_v2_5_pkt_status.tag_f_1);
	}

	IPA_DUMP_STATUS_FIELD(tag_f_2);
	IPA_DUMP_STATUS_FIELD(time_day_ctr);
	IPA_DUMP_STATUS_FIELD(nat_hit);
	IPA_DUMP_STATUS_FIELD(nat_tbl_idx);
	IPA_DUMP_STATUS_FIELD(nat_type);
	IPA_DUMP_STATUS_FIELD(route_local);
	IPA_DUMP_STATUS_FIELD(route_tbl_idx);
	IPA_DUMP_STATUS_FIELD(route_match);
	IPA_DUMP_STATUS_FIELD(ucp);
	IPA_DUMP_STATUS_FIELD(route_rule_idx);
	IPA_DUMP_STATUS_FIELD(hdr_local);
	IPA_DUMP_STATUS_FIELD(hdr_offset);
	IPA_DUMP_STATUS_FIELD(frag_hit);
	IPA_DUMP_STATUS_FIELD(frag_rule);
}

static ssize_t ipa_status_stats_read(struct file *file, char __user *ubuf,
		size_t count, loff_t *ppos)
{
	struct ipa_status_stats *stats;
	int i, j;

	stats = kzalloc(sizeof(*stats), GFP_KERNEL);
	if (!stats)
		return -EFAULT;

	for (i = 0; i < ipa_ctx->ipa_num_pipes; i++) {
		if (!ipa_ctx->ep[i].sys || !ipa_ctx->ep[i].sys->status_stat)
			continue;

		memcpy(stats, ipa_ctx->ep[i].sys->status_stat, sizeof(*stats));
		stats->curr = (stats->curr + IPA_MAX_STATUS_STAT_NUM - 1)
			% IPA_MAX_STATUS_STAT_NUM;
		pr_err("Statuses for pipe %d\n", i);
		for (j = 0; j < IPA_MAX_STATUS_STAT_NUM; j++) {
			pr_err("curr=%d\n", stats->curr);
			ipa_dump_status(&stats->status[stats->curr]);
			pr_err("\n\n\n");
			stats->curr = (stats->curr + 1) %
				IPA_MAX_STATUS_STAT_NUM;
		}
	}

	kfree(stats);
	return 0;
}


const struct file_operations ipa_gen_reg_ops = {
	.read = ipa_read_gen_reg,
};
@@ -1533,6 +1612,10 @@ const struct file_operations ipa_rm_stats = {
	.read = ipa_rm_read_stats,
};

const struct file_operations ipa_status_stats_ops = {
	.read = ipa_status_stats_read,
};

void ipa_debugfs_init(void)
{
	const mode_t read_only_mode = S_IRUSR | S_IRGRP | S_IROTH;
@@ -1674,6 +1757,13 @@ void ipa_debugfs_init(void)
		goto fail;
	}

	dfile_status_stats = debugfs_create_file("status_stats",
			read_only_mode, dent, 0, &ipa_status_stats_ops);
	if (!dfile_status_stats || IS_ERR(dfile_status_stats)) {
		IPAERR("fail to create file for debug_fs status_stats\n");
		goto fail;
	}

	file = debugfs_create_u32("enable_clock_scaling", read_write_mode,
		dent, &ipa_ctx->enable_clock_scaling);
	if (!file) {
+26 −0
Original line number Diff line number Diff line
@@ -1064,6 +1064,16 @@ int ipa2_setup_sys_pipe(struct ipa_sys_connect_params *sys_in, u32 *clnt_hdl)
	atomic_set(&ep->avail_fifo_desc,
		((sys_in->desc_fifo_sz/sizeof(struct sps_iovec))-1));

	if (ep->status.status_en && IPA_CLIENT_IS_CONS(ep->client) &&
	    ep->sys->status_stat == NULL) {
		ep->sys->status_stat =
			kzalloc(sizeof(struct ipa_status_stats), GFP_KERNEL);
		if (!ep->sys->status_stat) {
			IPAERR("no memory\n");
			goto fail_gen2;
		}
	}

	result = ipa_enable_data_path(ipa_ep_idx);
	if (result) {
		IPAERR("enable data path failed res=%d clnt=%d.\n", result,
@@ -1992,6 +2002,13 @@ begin:
		IPADBG("STATUS opcode=%d src=%d dst=%d len=%d\n",
				status->status_opcode, status->endp_src_idx,
				status->endp_dest_idx, status->pkt_len);
		if (sys->status_stat) {
			sys->status_stat->status[sys->status_stat->curr] =
				*status;
			sys->status_stat->curr++;
			if (sys->status_stat->curr == IPA_MAX_STATUS_STAT_NUM)
				sys->status_stat->curr = 0;
		}

		if (status->status_opcode !=
			IPA_HW_STATUS_OPCODE_DROPPED_PACKET &&
@@ -2240,6 +2257,15 @@ static int ipa_wan_rx_pyld_hdlr(struct sk_buff *skb,
		IPADBG("STATUS opcode=%d src=%d dst=%d len=%d\n",
				status->status_opcode, status->endp_src_idx,
				status->endp_dest_idx, status->pkt_len);

		if (sys->status_stat) {
			sys->status_stat->status[sys->status_stat->curr] =
				*status;
			sys->status_stat->curr++;
			if (sys->status_stat->curr == IPA_MAX_STATUS_STAT_NUM)
				sys->status_stat->curr = 0;
		}

		if (status->status_opcode !=
			IPA_HW_STATUS_OPCODE_DROPPED_PACKET &&
			status->status_opcode !=
+8 −0
Original line number Diff line number Diff line
@@ -46,6 +46,8 @@
#define IPA_NUM_DESC_PER_SW_TX (2)
#define IPA_GENERIC_RX_POOL_SZ 192

#define IPA_MAX_STATUS_STAT_NUM 30

#define IPADBG(fmt, args...) \
	pr_debug(DRV_NAME " %s:%d " fmt, __func__, __LINE__, ## args)
#define IPAERR(fmt, args...) \
@@ -478,6 +480,11 @@ struct ipa_wlan_comm_memb {
	atomic_t active_clnt_cnt;
};

struct ipa_status_stats {
	struct ipa_hw_pkt_status status[IPA_MAX_STATUS_STAT_NUM];
	int curr;
};

/**
 * struct ipa_ep_context - IPA end point context
 * @valid: flag indicating id EP context is valid
@@ -592,6 +599,7 @@ struct ipa_sys_context {
	spinlock_t spinlock;
	struct workqueue_struct *wq;
	struct workqueue_struct *repl_wq;
	struct ipa_status_stats *status_stat;
	/* ordering is important - other immutable fields go below */
};

+78 −0
Original line number Diff line number Diff line
@@ -23,6 +23,9 @@
#define IPA_DBG_CNTR_OFF 127264
#define IPA_DBG_MAX_RULE_IN_TBL 128

#define IPA_DUMP_STATUS_FIELD(f) \
	pr_err(#f "=0x%x\n", status->f)

const char *ipa3_excp_name[] = {
	__stringify_1(IPA_A5_MUX_HDR_EXCP_RSVD0),
	__stringify_1(IPA_A5_MUX_HDR_EXCP_RSVD1),
@@ -107,6 +110,7 @@ static struct dentry *dfile_dbg_cnt;
static struct dentry *dfile_msg;
static struct dentry *dfile_ip4_nat;
static struct dentry *dfile_rm_stats;
static struct dentry *dfile_status_stats;
static char dbg_buff[IPA_MAX_MSG_LEN];
static s8 ep_reg_idx;

@@ -1519,6 +1523,69 @@ static ssize_t ipa3_rm_read_stats(struct file *file, char __user *ubuf,
	return simple_read_from_buffer(ubuf, count, ppos, dbg_buff, cnt);
}

static void ipa_dump_status(struct ipa3_hw_pkt_status *status)
{
	IPA_DUMP_STATUS_FIELD(status_opcode);
	IPA_DUMP_STATUS_FIELD(exception);
	IPA_DUMP_STATUS_FIELD(status_mask);
	IPA_DUMP_STATUS_FIELD(pkt_len);
	IPA_DUMP_STATUS_FIELD(endp_src_idx);
	IPA_DUMP_STATUS_FIELD(endp_dest_idx);
	IPA_DUMP_STATUS_FIELD(metadata);
	IPA_DUMP_STATUS_FIELD(filt_local);
	IPA_DUMP_STATUS_FIELD(filt_hash);
	IPA_DUMP_STATUS_FIELD(filt_global);
	IPA_DUMP_STATUS_FIELD(ret_hdr);
	IPA_DUMP_STATUS_FIELD(filt_rule_id);
	IPA_DUMP_STATUS_FIELD(route_local);
	IPA_DUMP_STATUS_FIELD(route_hash);
	IPA_DUMP_STATUS_FIELD(ucp);
	IPA_DUMP_STATUS_FIELD(route_tbl_idx);
	IPA_DUMP_STATUS_FIELD(route_rule_id);
	IPA_DUMP_STATUS_FIELD(nat_hit);
	IPA_DUMP_STATUS_FIELD(nat_tbl_idx);
	IPA_DUMP_STATUS_FIELD(nat_type);
	pr_err("tag = 0x%llx\n", (u64)status->tag & 0xFFFFFFFFFFFF);
	IPA_DUMP_STATUS_FIELD(seq_num);
	IPA_DUMP_STATUS_FIELD(time_day_ctr);
	IPA_DUMP_STATUS_FIELD(hdr_local);
	IPA_DUMP_STATUS_FIELD(hdr_offset);
	IPA_DUMP_STATUS_FIELD(frag_hit);
	IPA_DUMP_STATUS_FIELD(frag_rule);
}

static ssize_t ipa_status_stats_read(struct file *file, char __user *ubuf,
		size_t count, loff_t *ppos)
{
	struct ipa3_status_stats *stats;
	int i, j;

	stats = kzalloc(sizeof(*stats), GFP_KERNEL);
	if (!stats)
		return -EFAULT;

	for (i = 0; i < ipa3_ctx->ipa_num_pipes; i++) {
		if (!ipa3_ctx->ep[i].sys || !ipa3_ctx->ep[i].sys->status_stat)
			continue;

		memcpy(stats, ipa3_ctx->ep[i].sys->status_stat, sizeof(*stats));
		stats->curr = (stats->curr + IPA_MAX_STATUS_STAT_NUM - 1)
			% IPA_MAX_STATUS_STAT_NUM;
		pr_err("Statuses for pipe %d\n", i);
		for (j = 0; j < IPA_MAX_STATUS_STAT_NUM; j++) {
			pr_err("curr=%d\n", stats->curr);
			ipa_dump_status(&stats->status[stats->curr]);
			pr_err("\n\n\n");
			stats->curr = (stats->curr + 1) %
				IPA_MAX_STATUS_STAT_NUM;
		}
	}

	kfree(stats);
	return 0;
}


const struct file_operations ipa3_gen_reg_ops = {
	.read = ipa3_read_gen_reg,
};
@@ -1586,6 +1653,10 @@ const struct file_operations ipa3_dbg_cnt_ops = {
	.write = ipa3_write_dbg_cnt,
};

const struct file_operations ipa3_status_stats_ops = {
	.read = ipa_status_stats_read,
};

const struct file_operations ipa3_nat4_ops = {
	.read = ipa3_read_nat4,
};
@@ -1763,6 +1834,13 @@ void ipa3_debugfs_init(void)
		goto fail;
	}

	dfile_status_stats = debugfs_create_file("status_stats",
			read_only_mode, dent, 0, &ipa3_status_stats_ops);
	if (!dfile_status_stats || IS_ERR(dfile_status_stats)) {
		IPAERR("fail to create file for debug_fs status_stats\n");
		goto fail;
	}

	file = debugfs_create_u32("enable_clock_scaling", read_write_mode,
		dent, &ipa3_ctx->enable_clock_scaling);
	if (!file) {
+26 −0
Original line number Diff line number Diff line
@@ -1116,6 +1116,16 @@ int ipa3_setup_sys_pipe(struct ipa_sys_connect_params *sys_in, u32 *clnt_hdl)
	atomic_set(&ep->avail_fifo_desc,
		((sys_in->desc_fifo_sz/sizeof(struct sps_iovec))-1));

	if (ep->status.status_en && IPA_CLIENT_IS_CONS(ep->client) &&
	    ep->sys->status_stat == NULL) {
		ep->sys->status_stat =
			kzalloc(sizeof(struct ipa3_status_stats), GFP_KERNEL);
		if (!ep->sys->status_stat) {
			IPAERR("no memory\n");
			goto fail_gen2;
		}
	}

	result = ipa3_enable_data_path(ipa_ep_idx);
	if (result) {
		IPAERR("enable data path failed res=%d clnt=%d.\n", result,
@@ -2141,6 +2151,13 @@ begin:
		IPADBG("STATUS opcode=%d src=%d dst=%d len=%d\n",
				status->status_opcode, status->endp_src_idx,
				status->endp_dest_idx, status->pkt_len);
		if (sys->status_stat) {
			sys->status_stat->status[sys->status_stat->curr] =
				*status;
			sys->status_stat->curr++;
			if (sys->status_stat->curr == IPA_MAX_STATUS_STAT_NUM)
				sys->status_stat->curr = 0;
		}

		if ((status->status_opcode &
		    (IPA_HW_STATUS_OPCODE_DROPPED_PACKET |
@@ -2383,6 +2400,15 @@ static int ipa3_wan_rx_pyld_hdlr(struct sk_buff *skb,
		IPADBG("STATUS opcode=%d src=%d dst=%d len=%d\n",
				status->status_opcode, status->endp_src_idx,
				status->endp_dest_idx, status->pkt_len);

		if (sys->status_stat) {
			sys->status_stat->status[sys->status_stat->curr] =
				*status;
			sys->status_stat->curr++;
			if (sys->status_stat->curr == IPA_MAX_STATUS_STAT_NUM)
				sys->status_stat->curr = 0;
		}

		if ((status->status_opcode &
		    (IPA_HW_STATUS_OPCODE_DROPPED_PACKET |
		    IPA_HW_STATUS_OPCODE_PACKET |
Loading