Skip to content

Commit df613b9

Browse files
avasquez01James Bottomley
authored and
James Bottomley
committed
[SCSI] qla2xxx: Add Fibre Channel Event (FCE) tracing support.
FCE support enables the firmware to record FC extended link services and basic link services frames which have been transmitted and received by the ISP. This allows for a limited view of the FC traffic through the ISP without using a FC analyzer. This can be useful in situations where a physical connection to the FC bus is not possible. The driver exports this information in two ways -- first, via a debugfs node exported for all supported ISPs under: <debugfs_mount_point>/qla2xxx/qla2xxx_<host_no>/fce where a read of the 'fce' file will provide a snapshot of the firmware's FCE buffer; and finally, the FCE buffer will be extracted during a firmware-dump scenario. Signed-off-by: Andrew Vasquez <[email protected]> Signed-off-by: James Bottomley <[email protected]>
1 parent 00b6bd2 commit df613b9

File tree

10 files changed

+405
-14
lines changed

10 files changed

+405
-14
lines changed

drivers/scsi/qla2xxx/Makefile

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
qla2xxx-y := qla_os.o qla_init.o qla_mbx.o qla_iocb.o qla_isr.o qla_gs.o \
2-
qla_dbg.o qla_sup.o qla_attr.o qla_mid.o
2+
qla_dbg.o qla_sup.o qla_attr.o qla_mid.o qla_dfs.o
33

44
obj-$(CONFIG_SCSI_QLA_FC) += qla2xxx.o

drivers/scsi/qla2xxx/qla_dbg.c

+22
Original file line numberDiff line numberDiff line change
@@ -1051,6 +1051,7 @@ qla25xx_fw_dump(scsi_qla_host_t *ha, int hardware_locked)
10511051
struct qla25xx_fw_dump *fw;
10521052
uint32_t ext_mem_cnt;
10531053
void *nxt;
1054+
struct qla2xxx_fce_chain *fcec;
10541055

10551056
risc_address = ext_mem_cnt = 0;
10561057
flags = 0;
@@ -1321,10 +1322,31 @@ qla25xx_fw_dump(scsi_qla_host_t *ha, int hardware_locked)
13211322
if (rval != QLA_SUCCESS)
13221323
goto qla25xx_fw_dump_failed_0;
13231324

1325+
/* Fibre Channel Trace Buffer. */
13241326
nxt = qla2xxx_copy_queues(ha, nxt);
13251327
if (ha->eft)
13261328
memcpy(nxt, ha->eft, ntohl(ha->fw_dump->eft_size));
13271329

1330+
/* Fibre Channel Event Buffer. */
1331+
if (!ha->fce)
1332+
goto qla25xx_fw_dump_failed_0;
1333+
1334+
ha->fw_dump->version |= __constant_htonl(DUMP_CHAIN_VARIANT);
1335+
1336+
fcec = nxt + ntohl(ha->fw_dump->eft_size);
1337+
fcec->type = __constant_htonl(DUMP_CHAIN_FCE | DUMP_CHAIN_LAST);
1338+
fcec->chain_size = htonl(sizeof(struct qla2xxx_fce_chain) +
1339+
fce_calc_size(ha->fce_bufs));
1340+
fcec->size = htonl(fce_calc_size(ha->fce_bufs));
1341+
fcec->addr_l = htonl(LSD(ha->fce_dma));
1342+
fcec->addr_h = htonl(MSD(ha->fce_dma));
1343+
1344+
iter_reg = fcec->eregs;
1345+
for (cnt = 0; cnt < 8; cnt++)
1346+
*iter_reg++ = htonl(ha->fce_mb[cnt]);
1347+
1348+
memcpy(iter_reg, ha->fce, ntohl(fcec->size));
1349+
13281350
qla25xx_fw_dump_failed_0:
13291351
if (rval != QLA_SUCCESS) {
13301352
qla_printk(KERN_WARNING, ha,

drivers/scsi/qla2xxx/qla_dbg.h

+19
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,25 @@ struct qla25xx_fw_dump {
256256
#define EFT_BYTES_PER_BUFFER 0x4000
257257
#define EFT_SIZE ((EFT_BYTES_PER_BUFFER) * (EFT_NUM_BUFFERS))
258258

259+
#define FCE_NUM_BUFFERS 64
260+
#define FCE_BYTES_PER_BUFFER 0x400
261+
#define FCE_SIZE ((FCE_BYTES_PER_BUFFER) * (FCE_NUM_BUFFERS))
262+
#define fce_calc_size(b) ((FCE_BYTES_PER_BUFFER) * (b))
263+
264+
struct qla2xxx_fce_chain {
265+
uint32_t type;
266+
uint32_t chain_size;
267+
268+
uint32_t size;
269+
uint32_t addr_l;
270+
uint32_t addr_h;
271+
uint32_t eregs[8];
272+
};
273+
274+
#define DUMP_CHAIN_VARIANT 0x80000000
275+
#define DUMP_CHAIN_FCE 0x7FFFFAF0
276+
#define DUMP_CHAIN_LAST 0x80000000
277+
259278
struct qla2xxx_fw_dump {
260279
uint8_t signature[4];
261280
uint32_t version;

drivers/scsi/qla2xxx/qla_def.h

+10
Original file line numberDiff line numberDiff line change
@@ -2156,6 +2156,7 @@ typedef struct scsi_qla_host {
21562156
uint32_t gpsc_supported :1;
21572157
uint32_t vsan_enabled :1;
21582158
uint32_t npiv_supported :1;
2159+
uint32_t fce_enabled :1;
21592160
} flags;
21602161

21612162
atomic_t loop_state;
@@ -2449,6 +2450,15 @@ typedef struct scsi_qla_host {
24492450
dma_addr_t eft_dma;
24502451
void *eft;
24512452

2453+
struct dentry *dfs_dir;
2454+
struct dentry *dfs_fce;
2455+
dma_addr_t fce_dma;
2456+
void *fce;
2457+
uint32_t fce_bufs;
2458+
uint16_t fce_mb[8];
2459+
uint64_t fce_wr, fce_rd;
2460+
struct mutex fce_mutex;
2461+
24522462
uint8_t host_str[16];
24532463
uint32_t pci_attr;
24542464
uint16_t chip_revision;

drivers/scsi/qla2xxx/qla_dfs.c

+175
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
/*
2+
* QLogic Fibre Channel HBA Driver
3+
* Copyright (c) 2003-2005 QLogic Corporation
4+
*
5+
* See LICENSE.qla2xxx for copyright and licensing details.
6+
*/
7+
#include "qla_def.h"
8+
9+
#include <linux/debugfs.h>
10+
#include <linux/seq_file.h>
11+
12+
static struct dentry *qla2x00_dfs_root;
13+
static atomic_t qla2x00_dfs_root_count;
14+
15+
static int
16+
qla2x00_dfs_fce_show(struct seq_file *s, void *unused)
17+
{
18+
scsi_qla_host_t *ha = s->private;
19+
uint32_t cnt;
20+
uint32_t *fce;
21+
uint64_t fce_start;
22+
23+
mutex_lock(&ha->fce_mutex);
24+
25+
seq_printf(s, "FCE Trace Buffer\n");
26+
seq_printf(s, "In Pointer = %llx\n\n", ha->fce_wr);
27+
seq_printf(s, "Base = %llx\n\n", (unsigned long long) ha->fce_dma);
28+
seq_printf(s, "FCE Enable Registers\n");
29+
seq_printf(s, "%08x %08x %08x %08x %08x %08x\n",
30+
ha->fce_mb[0], ha->fce_mb[2], ha->fce_mb[3], ha->fce_mb[4],
31+
ha->fce_mb[5], ha->fce_mb[6]);
32+
33+
fce = (uint32_t *) ha->fce;
34+
fce_start = (unsigned long long) ha->fce_dma;
35+
for (cnt = 0; cnt < fce_calc_size(ha->fce_bufs) / 4; cnt++) {
36+
if (cnt % 8 == 0)
37+
seq_printf(s, "\n%llx: ",
38+
(unsigned long long)((cnt * 4) + fce_start));
39+
else
40+
seq_printf(s, " ");
41+
seq_printf(s, "%08x", *fce++);
42+
}
43+
44+
seq_printf(s, "\nEnd\n");
45+
46+
mutex_unlock(&ha->fce_mutex);
47+
48+
return 0;
49+
}
50+
51+
static int
52+
qla2x00_dfs_fce_open(struct inode *inode, struct file *file)
53+
{
54+
scsi_qla_host_t *ha = inode->i_private;
55+
int rval;
56+
57+
if (!ha->flags.fce_enabled)
58+
goto out;
59+
60+
mutex_lock(&ha->fce_mutex);
61+
62+
/* Pause tracing to flush FCE buffers. */
63+
rval = qla2x00_disable_fce_trace(ha, &ha->fce_wr, &ha->fce_rd);
64+
if (rval)
65+
qla_printk(KERN_WARNING, ha,
66+
"DebugFS: Unable to disable FCE (%d).\n", rval);
67+
68+
ha->flags.fce_enabled = 0;
69+
70+
mutex_unlock(&ha->fce_mutex);
71+
out:
72+
return single_open(file, qla2x00_dfs_fce_show, ha);
73+
}
74+
75+
static int
76+
qla2x00_dfs_fce_release(struct inode *inode, struct file *file)
77+
{
78+
scsi_qla_host_t *ha = inode->i_private;
79+
int rval;
80+
81+
if (ha->flags.fce_enabled)
82+
goto out;
83+
84+
mutex_lock(&ha->fce_mutex);
85+
86+
/* Re-enable FCE tracing. */
87+
ha->flags.fce_enabled = 1;
88+
memset(ha->fce, 0, fce_calc_size(ha->fce_bufs));
89+
rval = qla2x00_enable_fce_trace(ha, ha->fce_dma, ha->fce_bufs,
90+
ha->fce_mb, &ha->fce_bufs);
91+
if (rval) {
92+
qla_printk(KERN_WARNING, ha,
93+
"DebugFS: Unable to reinitialize FCE (%d).\n", rval);
94+
ha->flags.fce_enabled = 0;
95+
}
96+
97+
mutex_unlock(&ha->fce_mutex);
98+
out:
99+
return single_release(inode, file);
100+
}
101+
102+
static const struct file_operations dfs_fce_ops = {
103+
.open = qla2x00_dfs_fce_open,
104+
.read = seq_read,
105+
.llseek = seq_lseek,
106+
.release = qla2x00_dfs_fce_release,
107+
};
108+
109+
int
110+
qla2x00_dfs_setup(scsi_qla_host_t *ha)
111+
{
112+
if (!IS_QLA25XX(ha))
113+
goto out;
114+
if (!ha->fce)
115+
goto out;
116+
117+
if (qla2x00_dfs_root)
118+
goto create_dir;
119+
120+
atomic_set(&qla2x00_dfs_root_count, 0);
121+
qla2x00_dfs_root = debugfs_create_dir(QLA2XXX_DRIVER_NAME, NULL);
122+
if (!qla2x00_dfs_root) {
123+
qla_printk(KERN_NOTICE, ha,
124+
"DebugFS: Unable to create root directory.\n");
125+
goto out;
126+
}
127+
128+
create_dir:
129+
if (ha->dfs_dir)
130+
goto create_nodes;
131+
132+
mutex_init(&ha->fce_mutex);
133+
ha->dfs_dir = debugfs_create_dir(ha->host_str, qla2x00_dfs_root);
134+
if (!ha->dfs_dir) {
135+
qla_printk(KERN_NOTICE, ha,
136+
"DebugFS: Unable to create ha directory.\n");
137+
goto out;
138+
}
139+
140+
atomic_inc(&qla2x00_dfs_root_count);
141+
142+
create_nodes:
143+
ha->dfs_fce = debugfs_create_file("fce", S_IRUSR, ha->dfs_dir, ha,
144+
&dfs_fce_ops);
145+
if (!ha->dfs_fce) {
146+
qla_printk(KERN_NOTICE, ha,
147+
"DebugFS: Unable to fce node.\n");
148+
goto out;
149+
}
150+
out:
151+
return 0;
152+
}
153+
154+
int
155+
qla2x00_dfs_remove(scsi_qla_host_t *ha)
156+
{
157+
if (ha->dfs_fce) {
158+
debugfs_remove(ha->dfs_fce);
159+
ha->dfs_fce = NULL;
160+
}
161+
162+
if (ha->dfs_dir) {
163+
debugfs_remove(ha->dfs_dir);
164+
ha->dfs_dir = NULL;
165+
atomic_dec(&qla2x00_dfs_root_count);
166+
}
167+
168+
if (atomic_read(&qla2x00_dfs_root_count) == 0 &&
169+
qla2x00_dfs_root) {
170+
debugfs_remove(qla2x00_dfs_root);
171+
qla2x00_dfs_root = NULL;
172+
}
173+
174+
return 0;
175+
}

drivers/scsi/qla2xxx/qla_fw.h

+7
Original file line numberDiff line numberDiff line change
@@ -959,6 +959,13 @@ struct device_reg_24xx {
959959
#define TC_EFT_ENABLE 4
960960
#define TC_EFT_DISABLE 5
961961

962+
#define TC_FCE_ENABLE 8
963+
#define TC_FCE_OPTIONS 0
964+
#define TC_FCE_DEFAULT_RX_SIZE 2112
965+
#define TC_FCE_DEFAULT_TX_SIZE 2112
966+
#define TC_FCE_DISABLE 9
967+
#define TC_FCE_DISABLE_TRACE BIT_0
968+
962969
/* MID Support ***************************************************************/
963970

964971
#define MIN_MULTI_ID_FABRIC 64 /* Must be power-of-2. */

drivers/scsi/qla2xxx/qla_gbl.h

+13
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,13 @@ qla2x00_enable_eft_trace(scsi_qla_host_t *, dma_addr_t, uint16_t);
232232
extern int
233233
qla2x00_disable_eft_trace(scsi_qla_host_t *);
234234

235+
extern int
236+
qla2x00_enable_fce_trace(scsi_qla_host_t *, dma_addr_t, uint16_t , uint16_t *,
237+
uint32_t *);
238+
239+
extern int
240+
qla2x00_disable_fce_trace(scsi_qla_host_t *, uint64_t *, uint64_t *);
241+
235242
extern int
236243
qla2x00_read_sfp(scsi_qla_host_t *, dma_addr_t, uint16_t, uint16_t, uint16_t);
237244

@@ -334,4 +341,10 @@ extern void qla2x00_free_sysfs_attr(scsi_qla_host_t *);
334341
extern void qla2x00_init_host_attr(scsi_qla_host_t *);
335342
extern void qla2x00_alloc_sysfs_attr(scsi_qla_host_t *);
336343
extern void qla2x00_free_sysfs_attr(scsi_qla_host_t *);
344+
345+
/*
346+
* Global Function Prototypes in qla_dfs.c source file.
347+
*/
348+
extern int qla2x00_dfs_setup(scsi_qla_host_t *);
349+
extern int qla2x00_dfs_remove(scsi_qla_host_t *);
337350
#endif /* _QLA_GBL_H */

0 commit comments

Comments
 (0)