162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-only */
262306a36Sopenharmony_ci/* Copyright 2012 Cisco Systems, Inc.  All rights reserved. */
362306a36Sopenharmony_ci
462306a36Sopenharmony_ci#ifndef __FNIC_TRACE_H__
562306a36Sopenharmony_ci#define __FNIC_TRACE_H__
662306a36Sopenharmony_ci
762306a36Sopenharmony_ci#define FNIC_ENTRY_SIZE_BYTES 64
862306a36Sopenharmony_ci#define FC_TRC_SIZE_BYTES 256
962306a36Sopenharmony_ci#define FC_TRC_HEADER_SIZE sizeof(struct fc_trace_hdr)
1062306a36Sopenharmony_ci
1162306a36Sopenharmony_ci/*
1262306a36Sopenharmony_ci * Fisrt bit of FNIC_FC_RECV and FNIC_FC_SEND is used to represent the type
1362306a36Sopenharmony_ci * of frame 1 => Eth frame, 0=> FC frame
1462306a36Sopenharmony_ci */
1562306a36Sopenharmony_ci
1662306a36Sopenharmony_ci#define FNIC_FC_RECV 0x52 /* Character R */
1762306a36Sopenharmony_ci#define FNIC_FC_SEND 0x54 /* Character T */
1862306a36Sopenharmony_ci#define FNIC_FC_LE 0x4C /* Character L */
1962306a36Sopenharmony_ci
2062306a36Sopenharmony_ciextern ssize_t simple_read_from_buffer(void __user *to,
2162306a36Sopenharmony_ci					  size_t count,
2262306a36Sopenharmony_ci					  loff_t *ppos,
2362306a36Sopenharmony_ci					  const void *from,
2462306a36Sopenharmony_ci					  size_t available);
2562306a36Sopenharmony_ci
2662306a36Sopenharmony_ciextern unsigned int fnic_trace_max_pages;
2762306a36Sopenharmony_ciextern int fnic_tracing_enabled;
2862306a36Sopenharmony_ciextern unsigned int trace_max_pages;
2962306a36Sopenharmony_ci
3062306a36Sopenharmony_ciextern unsigned int fnic_fc_trace_max_pages;
3162306a36Sopenharmony_ciextern int fnic_fc_tracing_enabled;
3262306a36Sopenharmony_ciextern int fnic_fc_trace_cleared;
3362306a36Sopenharmony_ci
3462306a36Sopenharmony_citypedef struct fnic_trace_dbg {
3562306a36Sopenharmony_ci	int wr_idx;
3662306a36Sopenharmony_ci	int rd_idx;
3762306a36Sopenharmony_ci	unsigned long *page_offset;
3862306a36Sopenharmony_ci} fnic_trace_dbg_t;
3962306a36Sopenharmony_ci
4062306a36Sopenharmony_citypedef struct fnic_dbgfs {
4162306a36Sopenharmony_ci	int buffer_len;
4262306a36Sopenharmony_ci	char *buffer;
4362306a36Sopenharmony_ci} fnic_dbgfs_t;
4462306a36Sopenharmony_ci
4562306a36Sopenharmony_cistruct fnic_trace_data {
4662306a36Sopenharmony_ci	union {
4762306a36Sopenharmony_ci		struct {
4862306a36Sopenharmony_ci			u32 low;
4962306a36Sopenharmony_ci			u32 high;
5062306a36Sopenharmony_ci		};
5162306a36Sopenharmony_ci		u64 val;
5262306a36Sopenharmony_ci	} timestamp, fnaddr;
5362306a36Sopenharmony_ci	u32 host_no;
5462306a36Sopenharmony_ci	u32 tag;
5562306a36Sopenharmony_ci	u64 data[5];
5662306a36Sopenharmony_ci} __attribute__((__packed__));
5762306a36Sopenharmony_ci
5862306a36Sopenharmony_citypedef struct fnic_trace_data fnic_trace_data_t;
5962306a36Sopenharmony_ci
6062306a36Sopenharmony_cistruct fc_trace_hdr {
6162306a36Sopenharmony_ci	struct timespec64 time_stamp;
6262306a36Sopenharmony_ci	u32 host_no;
6362306a36Sopenharmony_ci	u8 frame_type;
6462306a36Sopenharmony_ci	u8 frame_len;
6562306a36Sopenharmony_ci} __attribute__((__packed__));
6662306a36Sopenharmony_ci
6762306a36Sopenharmony_ci#define FC_TRACE_ADDRESS(a) \
6862306a36Sopenharmony_ci	((unsigned long)(a) + sizeof(struct fc_trace_hdr))
6962306a36Sopenharmony_ci
7062306a36Sopenharmony_ci#define FNIC_TRACE_ENTRY_SIZE \
7162306a36Sopenharmony_ci		  (FNIC_ENTRY_SIZE_BYTES - sizeof(fnic_trace_data_t))
7262306a36Sopenharmony_ci
7362306a36Sopenharmony_ci#define FNIC_TRACE(_fn, _hn, _t, _a, _b, _c, _d, _e)           \
7462306a36Sopenharmony_ci	if (unlikely(fnic_tracing_enabled)) {                   \
7562306a36Sopenharmony_ci		fnic_trace_data_t *trace_buf = fnic_trace_get_buf(); \
7662306a36Sopenharmony_ci		if (trace_buf) { \
7762306a36Sopenharmony_ci			if (sizeof(unsigned long) < 8) { \
7862306a36Sopenharmony_ci				trace_buf->timestamp.low = jiffies; \
7962306a36Sopenharmony_ci				trace_buf->fnaddr.low = (u32)(unsigned long)_fn; \
8062306a36Sopenharmony_ci			} else { \
8162306a36Sopenharmony_ci				trace_buf->timestamp.val = jiffies; \
8262306a36Sopenharmony_ci				trace_buf->fnaddr.val = (u64)(unsigned long)_fn; \
8362306a36Sopenharmony_ci			} \
8462306a36Sopenharmony_ci			trace_buf->host_no = _hn; \
8562306a36Sopenharmony_ci			trace_buf->tag = _t; \
8662306a36Sopenharmony_ci			trace_buf->data[0] = (u64)(unsigned long)_a; \
8762306a36Sopenharmony_ci			trace_buf->data[1] = (u64)(unsigned long)_b; \
8862306a36Sopenharmony_ci			trace_buf->data[2] = (u64)(unsigned long)_c; \
8962306a36Sopenharmony_ci			trace_buf->data[3] = (u64)(unsigned long)_d; \
9062306a36Sopenharmony_ci			trace_buf->data[4] = (u64)(unsigned long)_e; \
9162306a36Sopenharmony_ci		} \
9262306a36Sopenharmony_ci	}
9362306a36Sopenharmony_ci
9462306a36Sopenharmony_cifnic_trace_data_t *fnic_trace_get_buf(void);
9562306a36Sopenharmony_ciint fnic_get_trace_data(fnic_dbgfs_t *);
9662306a36Sopenharmony_ciint fnic_trace_buf_init(void);
9762306a36Sopenharmony_civoid fnic_trace_free(void);
9862306a36Sopenharmony_ciint fnic_debugfs_init(void);
9962306a36Sopenharmony_civoid fnic_debugfs_terminate(void);
10062306a36Sopenharmony_civoid fnic_trace_debugfs_init(void);
10162306a36Sopenharmony_civoid fnic_trace_debugfs_terminate(void);
10262306a36Sopenharmony_ci
10362306a36Sopenharmony_ci/* Fnic FC CTLR Trace releated function */
10462306a36Sopenharmony_ciint fnic_fc_trace_init(void);
10562306a36Sopenharmony_civoid fnic_fc_trace_free(void);
10662306a36Sopenharmony_ciint fnic_fc_trace_set_data(u32 host_no, u8 frame_type,
10762306a36Sopenharmony_ci				char *frame, u32 fc_frame_len);
10862306a36Sopenharmony_ciint fnic_fc_trace_get_data(fnic_dbgfs_t *fnic_dbgfs_prt, u8 rdata_flag);
10962306a36Sopenharmony_civoid copy_and_format_trace_data(struct fc_trace_hdr *tdata,
11062306a36Sopenharmony_ci				fnic_dbgfs_t *fnic_dbgfs_prt,
11162306a36Sopenharmony_ci				int *len, u8 rdata_flag);
11262306a36Sopenharmony_civoid fnic_fc_trace_debugfs_init(void);
11362306a36Sopenharmony_civoid fnic_fc_trace_debugfs_terminate(void);
11462306a36Sopenharmony_ci
11562306a36Sopenharmony_ci#endif
116