2 * Copyright (c) 2005-2014 Brocade Communications Systems, Inc.
3 * Copyright (c) 2014- QLogic Corporation.
7 * Linux driver for QLogic BR-series Fibre Channel Host Bus Adapter.
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License (GPL) Version 2 as
11 * published by the Free Software Foundation
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
19 #include <linux/debugfs.h>
20 #include <linux/export.h>
26 * BFA debufs interface
28 * To access the interface, debugfs file system should be mounted
29 * if not already mounted using:
30 * mount -t debugfs none /sys/kernel/debug
33 * - bfa/pci_dev:<pci_name>
34 * where the pci_name corresponds to the one under /sys/bus/pci/drivers/bfa
36 * Debugging service available per pci_dev:
37 * fwtrc: To collect current firmware trace.
38 * drvtrc: To collect current driver trace
39 * fwsave: To collect last saved fw trace as a result of firmware crash.
40 * regwr: To write one word to chip register
41 * regrd: To read one or more words from chip register.
44 struct bfad_debug_info
{
51 bfad_debugfs_open_drvtrc(struct inode
*inode
, struct file
*file
)
53 struct bfad_port_s
*port
= inode
->i_private
;
54 struct bfad_s
*bfad
= port
->bfad
;
55 struct bfad_debug_info
*debug
;
57 debug
= kzalloc(sizeof(struct bfad_debug_info
), GFP_KERNEL
);
61 debug
->debug_buffer
= (void *) bfad
->trcmod
;
62 debug
->buffer_len
= sizeof(struct bfa_trc_mod_s
);
64 file
->private_data
= debug
;
70 bfad_debugfs_open_fwtrc(struct inode
*inode
, struct file
*file
)
72 struct bfad_port_s
*port
= inode
->i_private
;
73 struct bfad_s
*bfad
= port
->bfad
;
74 struct bfad_debug_info
*fw_debug
;
78 fw_debug
= kzalloc(sizeof(struct bfad_debug_info
), GFP_KERNEL
);
82 fw_debug
->buffer_len
= sizeof(struct bfa_trc_mod_s
);
84 fw_debug
->debug_buffer
= vzalloc(fw_debug
->buffer_len
);
85 if (!fw_debug
->debug_buffer
) {
87 printk(KERN_INFO
"bfad[%d]: Failed to allocate fwtrc buffer\n",
92 spin_lock_irqsave(&bfad
->bfad_lock
, flags
);
93 rc
= bfa_ioc_debug_fwtrc(&bfad
->bfa
.ioc
,
94 fw_debug
->debug_buffer
,
95 &fw_debug
->buffer_len
);
96 spin_unlock_irqrestore(&bfad
->bfad_lock
, flags
);
97 if (rc
!= BFA_STATUS_OK
) {
98 vfree(fw_debug
->debug_buffer
);
99 fw_debug
->debug_buffer
= NULL
;
101 printk(KERN_INFO
"bfad[%d]: Failed to collect fwtrc\n",
106 file
->private_data
= fw_debug
;
112 bfad_debugfs_open_fwsave(struct inode
*inode
, struct file
*file
)
114 struct bfad_port_s
*port
= inode
->i_private
;
115 struct bfad_s
*bfad
= port
->bfad
;
116 struct bfad_debug_info
*fw_debug
;
120 fw_debug
= kzalloc(sizeof(struct bfad_debug_info
), GFP_KERNEL
);
124 fw_debug
->buffer_len
= sizeof(struct bfa_trc_mod_s
);
126 fw_debug
->debug_buffer
= vzalloc(fw_debug
->buffer_len
);
127 if (!fw_debug
->debug_buffer
) {
129 printk(KERN_INFO
"bfad[%d]: Failed to allocate fwsave buffer\n",
134 spin_lock_irqsave(&bfad
->bfad_lock
, flags
);
135 rc
= bfa_ioc_debug_fwsave(&bfad
->bfa
.ioc
,
136 fw_debug
->debug_buffer
,
137 &fw_debug
->buffer_len
);
138 spin_unlock_irqrestore(&bfad
->bfad_lock
, flags
);
139 if (rc
!= BFA_STATUS_OK
) {
140 vfree(fw_debug
->debug_buffer
);
141 fw_debug
->debug_buffer
= NULL
;
143 printk(KERN_INFO
"bfad[%d]: Failed to collect fwsave\n",
148 file
->private_data
= fw_debug
;
154 bfad_debugfs_open_reg(struct inode
*inode
, struct file
*file
)
156 struct bfad_debug_info
*reg_debug
;
158 reg_debug
= kzalloc(sizeof(struct bfad_debug_info
), GFP_KERNEL
);
162 reg_debug
->i_private
= inode
->i_private
;
164 file
->private_data
= reg_debug
;
169 /* Changes the current file position */
171 bfad_debugfs_lseek(struct file
*file
, loff_t offset
, int orig
)
173 struct bfad_debug_info
*debug
= file
->private_data
;
174 return fixed_size_llseek(file
, offset
, orig
,
179 bfad_debugfs_read(struct file
*file
, char __user
*buf
,
180 size_t nbytes
, loff_t
*pos
)
182 struct bfad_debug_info
*debug
= file
->private_data
;
184 if (!debug
|| !debug
->debug_buffer
)
187 return simple_read_from_buffer(buf
, nbytes
, pos
,
188 debug
->debug_buffer
, debug
->buffer_len
);
191 #define BFA_REG_CT_ADDRSZ (0x40000)
192 #define BFA_REG_CB_ADDRSZ (0x20000)
193 #define BFA_REG_ADDRSZ(__ioc) \
194 ((u32)(bfa_asic_id_ctc(bfa_ioc_devid(__ioc)) ? \
195 BFA_REG_CT_ADDRSZ : BFA_REG_CB_ADDRSZ))
196 #define BFA_REG_ADDRMSK(__ioc) (BFA_REG_ADDRSZ(__ioc) - 1)
199 bfad_reg_offset_check(struct bfa_s
*bfa
, u32 offset
, u32 len
)
204 area
= (offset
>> 15) & 0x7;
206 /* PCIe core register */
207 if ((offset
+ (len
<<2)) > 0x8000) /* 8k dwords or 32KB */
208 return BFA_STATUS_EINVAL
;
209 } else if (area
== 0x1) {
210 /* CB 32 KB memory page */
211 if ((offset
+ (len
<<2)) > 0x10000) /* 8k dwords or 32KB */
212 return BFA_STATUS_EINVAL
;
214 /* CB register space 64KB */
215 if ((offset
+ (len
<<2)) > BFA_REG_ADDRMSK(&bfa
->ioc
))
216 return BFA_STATUS_EINVAL
;
218 return BFA_STATUS_OK
;
222 bfad_debugfs_read_regrd(struct file
*file
, char __user
*buf
,
223 size_t nbytes
, loff_t
*pos
)
225 struct bfad_debug_info
*regrd_debug
= file
->private_data
;
226 struct bfad_port_s
*port
= (struct bfad_port_s
*)regrd_debug
->i_private
;
227 struct bfad_s
*bfad
= port
->bfad
;
233 rc
= simple_read_from_buffer(buf
, nbytes
, pos
,
234 bfad
->regdata
, bfad
->reglen
);
236 if ((*pos
+ nbytes
) >= bfad
->reglen
) {
237 kfree(bfad
->regdata
);
238 bfad
->regdata
= NULL
;
246 bfad_debugfs_write_regrd(struct file
*file
, const char __user
*buf
,
247 size_t nbytes
, loff_t
*ppos
)
249 struct bfad_debug_info
*regrd_debug
= file
->private_data
;
250 struct bfad_port_s
*port
= (struct bfad_port_s
*)regrd_debug
->i_private
;
251 struct bfad_s
*bfad
= port
->bfad
;
252 struct bfa_s
*bfa
= &bfad
->bfa
;
253 struct bfa_ioc_s
*ioc
= &bfa
->ioc
;
257 void __iomem
*rb
, *reg_addr
;
261 kern_buf
= memdup_user(buf
, nbytes
);
262 if (IS_ERR(kern_buf
))
263 return PTR_ERR(kern_buf
);
265 rc
= sscanf(kern_buf
, "%x:%x", &addr
, &len
);
266 if (rc
< 2 || len
> (UINT_MAX
>> 2)) {
268 "bfad[%d]: %s failed to read user buf\n",
269 bfad
->inst_no
, __func__
);
275 kfree(bfad
->regdata
);
276 bfad
->regdata
= NULL
;
279 bfad
->regdata
= kzalloc(len
<< 2, GFP_KERNEL
);
280 if (!bfad
->regdata
) {
281 printk(KERN_INFO
"bfad[%d]: Failed to allocate regrd buffer\n",
286 bfad
->reglen
= len
<< 2;
287 rb
= bfa_ioc_bar0(ioc
);
288 addr
&= BFA_REG_ADDRMSK(ioc
);
290 /* offset and len sanity check */
291 rc
= bfad_reg_offset_check(bfa
, addr
, len
);
293 printk(KERN_INFO
"bfad[%d]: Failed reg offset check\n",
295 kfree(bfad
->regdata
);
296 bfad
->regdata
= NULL
;
301 reg_addr
= rb
+ addr
;
302 regbuf
= (u32
*)bfad
->regdata
;
303 spin_lock_irqsave(&bfad
->bfad_lock
, flags
);
304 for (i
= 0; i
< len
; i
++) {
305 *regbuf
= readl(reg_addr
);
307 reg_addr
+= sizeof(u32
);
309 spin_unlock_irqrestore(&bfad
->bfad_lock
, flags
);
315 bfad_debugfs_write_regwr(struct file
*file
, const char __user
*buf
,
316 size_t nbytes
, loff_t
*ppos
)
318 struct bfad_debug_info
*debug
= file
->private_data
;
319 struct bfad_port_s
*port
= (struct bfad_port_s
*)debug
->i_private
;
320 struct bfad_s
*bfad
= port
->bfad
;
321 struct bfa_s
*bfa
= &bfad
->bfa
;
322 struct bfa_ioc_s
*ioc
= &bfa
->ioc
;
324 void __iomem
*reg_addr
;
328 kern_buf
= memdup_user(buf
, nbytes
);
329 if (IS_ERR(kern_buf
))
330 return PTR_ERR(kern_buf
);
332 rc
= sscanf(kern_buf
, "%x:%x", &addr
, &val
);
335 "bfad[%d]: %s failed to read user buf\n",
336 bfad
->inst_no
, __func__
);
342 addr
&= BFA_REG_ADDRMSK(ioc
); /* offset only 17 bit and word align */
344 /* offset and len sanity check */
345 rc
= bfad_reg_offset_check(bfa
, addr
, 1);
348 "bfad[%d]: Failed reg offset check\n",
353 reg_addr
= (bfa_ioc_bar0(ioc
)) + addr
;
354 spin_lock_irqsave(&bfad
->bfad_lock
, flags
);
355 writel(val
, reg_addr
);
356 spin_unlock_irqrestore(&bfad
->bfad_lock
, flags
);
362 bfad_debugfs_release(struct inode
*inode
, struct file
*file
)
364 struct bfad_debug_info
*debug
= file
->private_data
;
369 file
->private_data
= NULL
;
375 bfad_debugfs_release_fwtrc(struct inode
*inode
, struct file
*file
)
377 struct bfad_debug_info
*fw_debug
= file
->private_data
;
382 if (fw_debug
->debug_buffer
)
383 vfree(fw_debug
->debug_buffer
);
385 file
->private_data
= NULL
;
390 static const struct file_operations bfad_debugfs_op_drvtrc
= {
391 .owner
= THIS_MODULE
,
392 .open
= bfad_debugfs_open_drvtrc
,
393 .llseek
= bfad_debugfs_lseek
,
394 .read
= bfad_debugfs_read
,
395 .release
= bfad_debugfs_release
,
398 static const struct file_operations bfad_debugfs_op_fwtrc
= {
399 .owner
= THIS_MODULE
,
400 .open
= bfad_debugfs_open_fwtrc
,
401 .llseek
= bfad_debugfs_lseek
,
402 .read
= bfad_debugfs_read
,
403 .release
= bfad_debugfs_release_fwtrc
,
406 static const struct file_operations bfad_debugfs_op_fwsave
= {
407 .owner
= THIS_MODULE
,
408 .open
= bfad_debugfs_open_fwsave
,
409 .llseek
= bfad_debugfs_lseek
,
410 .read
= bfad_debugfs_read
,
411 .release
= bfad_debugfs_release_fwtrc
,
414 static const struct file_operations bfad_debugfs_op_regrd
= {
415 .owner
= THIS_MODULE
,
416 .open
= bfad_debugfs_open_reg
,
417 .llseek
= bfad_debugfs_lseek
,
418 .read
= bfad_debugfs_read_regrd
,
419 .write
= bfad_debugfs_write_regrd
,
420 .release
= bfad_debugfs_release
,
423 static const struct file_operations bfad_debugfs_op_regwr
= {
424 .owner
= THIS_MODULE
,
425 .open
= bfad_debugfs_open_reg
,
426 .llseek
= bfad_debugfs_lseek
,
427 .write
= bfad_debugfs_write_regwr
,
428 .release
= bfad_debugfs_release
,
431 struct bfad_debugfs_entry
{
434 const struct file_operations
*fops
;
437 static const struct bfad_debugfs_entry bfad_debugfs_files
[] = {
438 { "drvtrc", S_IFREG
|S_IRUGO
, &bfad_debugfs_op_drvtrc
, },
439 { "fwtrc", S_IFREG
|S_IRUGO
, &bfad_debugfs_op_fwtrc
, },
440 { "fwsave", S_IFREG
|S_IRUGO
, &bfad_debugfs_op_fwsave
, },
441 { "regrd", S_IFREG
|S_IRUGO
|S_IWUSR
, &bfad_debugfs_op_regrd
, },
442 { "regwr", S_IFREG
|S_IWUSR
, &bfad_debugfs_op_regwr
, },
445 static struct dentry
*bfa_debugfs_root
;
446 static atomic_t bfa_debugfs_port_count
;
449 bfad_debugfs_init(struct bfad_port_s
*port
)
451 struct bfad_s
*bfad
= port
->bfad
;
452 const struct bfad_debugfs_entry
*file
;
456 if (!bfa_debugfs_enable
)
459 /* Setup the BFA debugfs root directory*/
460 if (!bfa_debugfs_root
) {
461 bfa_debugfs_root
= debugfs_create_dir("bfa", NULL
);
462 atomic_set(&bfa_debugfs_port_count
, 0);
465 /* Setup the pci_dev debugfs directory for the port */
466 snprintf(name
, sizeof(name
), "pci_dev:%s", bfad
->pci_name
);
467 if (!port
->port_debugfs_root
) {
468 port
->port_debugfs_root
=
469 debugfs_create_dir(name
, bfa_debugfs_root
);
471 atomic_inc(&bfa_debugfs_port_count
);
473 for (i
= 0; i
< ARRAY_SIZE(bfad_debugfs_files
); i
++) {
474 file
= &bfad_debugfs_files
[i
];
475 bfad
->bfad_dentry_files
[i
] =
476 debugfs_create_file(file
->name
,
478 port
->port_debugfs_root
,
488 bfad_debugfs_exit(struct bfad_port_s
*port
)
490 struct bfad_s
*bfad
= port
->bfad
;
493 for (i
= 0; i
< ARRAY_SIZE(bfad_debugfs_files
); i
++) {
494 if (bfad
->bfad_dentry_files
[i
]) {
495 debugfs_remove(bfad
->bfad_dentry_files
[i
]);
496 bfad
->bfad_dentry_files
[i
] = NULL
;
500 /* Remove the pci_dev debugfs directory for the port */
501 if (port
->port_debugfs_root
) {
502 debugfs_remove(port
->port_debugfs_root
);
503 port
->port_debugfs_root
= NULL
;
504 atomic_dec(&bfa_debugfs_port_count
);
507 /* Remove the BFA debugfs root directory */
508 if (atomic_read(&bfa_debugfs_port_count
) == 0) {
509 debugfs_remove(bfa_debugfs_root
);
510 bfa_debugfs_root
= NULL
;