2 * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
6 * Linux driver for Brocade Fibre Channel Host Bus Adapter.
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License (GPL) Version 2 as
10 * published by the Free Software Foundation
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
18 #include <linux/debugfs.h>
19 #include <linux/export.h>
25 * BFA debufs interface
27 * To access the interface, debugfs file system should be mounted
28 * if not already mounted using:
29 * mount -t debugfs none /sys/kernel/debug
32 * - bfa/pci_dev:<pci_name>
33 * where the pci_name corresponds to the one under /sys/bus/pci/drivers/bfa
35 * Debugging service available per pci_dev:
36 * fwtrc: To collect current firmware trace.
37 * drvtrc: To collect current driver trace
38 * fwsave: To collect last saved fw trace as a result of firmware crash.
39 * regwr: To write one word to chip register
40 * regrd: To read one or more words from chip register.
43 struct bfad_debug_info
{
50 bfad_debugfs_open_drvtrc(struct inode
*inode
, struct file
*file
)
52 struct bfad_port_s
*port
= inode
->i_private
;
53 struct bfad_s
*bfad
= port
->bfad
;
54 struct bfad_debug_info
*debug
;
56 debug
= kzalloc(sizeof(struct bfad_debug_info
), GFP_KERNEL
);
60 debug
->debug_buffer
= (void *) bfad
->trcmod
;
61 debug
->buffer_len
= sizeof(struct bfa_trc_mod_s
);
63 file
->private_data
= debug
;
69 bfad_debugfs_open_fwtrc(struct inode
*inode
, struct file
*file
)
71 struct bfad_port_s
*port
= inode
->i_private
;
72 struct bfad_s
*bfad
= port
->bfad
;
73 struct bfad_debug_info
*fw_debug
;
77 fw_debug
= kzalloc(sizeof(struct bfad_debug_info
), GFP_KERNEL
);
81 fw_debug
->buffer_len
= sizeof(struct bfa_trc_mod_s
);
83 fw_debug
->debug_buffer
= vmalloc(fw_debug
->buffer_len
);
84 if (!fw_debug
->debug_buffer
) {
86 printk(KERN_INFO
"bfad[%d]: Failed to allocate fwtrc buffer\n",
91 memset(fw_debug
->debug_buffer
, 0, fw_debug
->buffer_len
);
93 spin_lock_irqsave(&bfad
->bfad_lock
, flags
);
94 rc
= bfa_ioc_debug_fwtrc(&bfad
->bfa
.ioc
,
95 fw_debug
->debug_buffer
,
96 &fw_debug
->buffer_len
);
97 spin_unlock_irqrestore(&bfad
->bfad_lock
, flags
);
98 if (rc
!= BFA_STATUS_OK
) {
99 vfree(fw_debug
->debug_buffer
);
100 fw_debug
->debug_buffer
= NULL
;
102 printk(KERN_INFO
"bfad[%d]: Failed to collect fwtrc\n",
107 file
->private_data
= fw_debug
;
113 bfad_debugfs_open_fwsave(struct inode
*inode
, struct file
*file
)
115 struct bfad_port_s
*port
= inode
->i_private
;
116 struct bfad_s
*bfad
= port
->bfad
;
117 struct bfad_debug_info
*fw_debug
;
121 fw_debug
= kzalloc(sizeof(struct bfad_debug_info
), GFP_KERNEL
);
125 fw_debug
->buffer_len
= sizeof(struct bfa_trc_mod_s
);
127 fw_debug
->debug_buffer
= vmalloc(fw_debug
->buffer_len
);
128 if (!fw_debug
->debug_buffer
) {
130 printk(KERN_INFO
"bfad[%d]: Failed to allocate fwsave buffer\n",
135 memset(fw_debug
->debug_buffer
, 0, fw_debug
->buffer_len
);
137 spin_lock_irqsave(&bfad
->bfad_lock
, flags
);
138 rc
= bfa_ioc_debug_fwsave(&bfad
->bfa
.ioc
,
139 fw_debug
->debug_buffer
,
140 &fw_debug
->buffer_len
);
141 spin_unlock_irqrestore(&bfad
->bfad_lock
, flags
);
142 if (rc
!= BFA_STATUS_OK
) {
143 vfree(fw_debug
->debug_buffer
);
144 fw_debug
->debug_buffer
= NULL
;
146 printk(KERN_INFO
"bfad[%d]: Failed to collect fwsave\n",
151 file
->private_data
= fw_debug
;
157 bfad_debugfs_open_reg(struct inode
*inode
, struct file
*file
)
159 struct bfad_debug_info
*reg_debug
;
161 reg_debug
= kzalloc(sizeof(struct bfad_debug_info
), GFP_KERNEL
);
165 reg_debug
->i_private
= inode
->i_private
;
167 file
->private_data
= reg_debug
;
172 /* Changes the current file position */
174 bfad_debugfs_lseek(struct file
*file
, loff_t offset
, int orig
)
176 struct bfad_debug_info
*debug
;
177 loff_t pos
= file
->f_pos
;
179 debug
= file
->private_data
;
183 file
->f_pos
= offset
;
186 file
->f_pos
+= offset
;
189 file
->f_pos
= debug
->buffer_len
- offset
;
195 if (file
->f_pos
< 0 || file
->f_pos
> debug
->buffer_len
) {
204 bfad_debugfs_read(struct file
*file
, char __user
*buf
,
205 size_t nbytes
, loff_t
*pos
)
207 struct bfad_debug_info
*debug
= file
->private_data
;
209 if (!debug
|| !debug
->debug_buffer
)
212 return simple_read_from_buffer(buf
, nbytes
, pos
,
213 debug
->debug_buffer
, debug
->buffer_len
);
216 #define BFA_REG_CT_ADDRSZ (0x40000)
217 #define BFA_REG_CB_ADDRSZ (0x20000)
218 #define BFA_REG_ADDRSZ(__ioc) \
219 ((u32)(bfa_asic_id_ctc(bfa_ioc_devid(__ioc)) ? \
220 BFA_REG_CT_ADDRSZ : BFA_REG_CB_ADDRSZ))
221 #define BFA_REG_ADDRMSK(__ioc) (BFA_REG_ADDRSZ(__ioc) - 1)
224 bfad_reg_offset_check(struct bfa_s
*bfa
, u32 offset
, u32 len
)
229 area
= (offset
>> 15) & 0x7;
231 /* PCIe core register */
232 if ((offset
+ (len
<<2)) > 0x8000) /* 8k dwords or 32KB */
233 return BFA_STATUS_EINVAL
;
234 } else if (area
== 0x1) {
235 /* CB 32 KB memory page */
236 if ((offset
+ (len
<<2)) > 0x10000) /* 8k dwords or 32KB */
237 return BFA_STATUS_EINVAL
;
239 /* CB register space 64KB */
240 if ((offset
+ (len
<<2)) > BFA_REG_ADDRMSK(&bfa
->ioc
))
241 return BFA_STATUS_EINVAL
;
243 return BFA_STATUS_OK
;
247 bfad_debugfs_read_regrd(struct file
*file
, char __user
*buf
,
248 size_t nbytes
, loff_t
*pos
)
250 struct bfad_debug_info
*regrd_debug
= file
->private_data
;
251 struct bfad_port_s
*port
= (struct bfad_port_s
*)regrd_debug
->i_private
;
252 struct bfad_s
*bfad
= port
->bfad
;
258 rc
= simple_read_from_buffer(buf
, nbytes
, pos
,
259 bfad
->regdata
, bfad
->reglen
);
261 if ((*pos
+ nbytes
) >= bfad
->reglen
) {
262 kfree(bfad
->regdata
);
263 bfad
->regdata
= NULL
;
271 bfad_debugfs_write_regrd(struct file
*file
, const char __user
*buf
,
272 size_t nbytes
, loff_t
*ppos
)
274 struct bfad_debug_info
*regrd_debug
= file
->private_data
;
275 struct bfad_port_s
*port
= (struct bfad_port_s
*)regrd_debug
->i_private
;
276 struct bfad_s
*bfad
= port
->bfad
;
277 struct bfa_s
*bfa
= &bfad
->bfa
;
278 struct bfa_ioc_s
*ioc
= &bfa
->ioc
;
279 int addr
, len
, rc
, i
;
281 void __iomem
*rb
, *reg_addr
;
285 kern_buf
= kzalloc(nbytes
, GFP_KERNEL
);
288 printk(KERN_INFO
"bfad[%d]: Failed to allocate buffer\n",
293 if (copy_from_user(kern_buf
, (void __user
*)buf
, nbytes
)) {
298 rc
= sscanf(kern_buf
, "%x:%x", &addr
, &len
);
301 "bfad[%d]: %s failed to read user buf\n",
302 bfad
->inst_no
, __func__
);
308 kfree(bfad
->regdata
);
309 bfad
->regdata
= NULL
;
312 bfad
->regdata
= kzalloc(len
<< 2, GFP_KERNEL
);
313 if (!bfad
->regdata
) {
314 printk(KERN_INFO
"bfad[%d]: Failed to allocate regrd buffer\n",
319 bfad
->reglen
= len
<< 2;
320 rb
= bfa_ioc_bar0(ioc
);
321 addr
&= BFA_REG_ADDRMSK(ioc
);
323 /* offset and len sanity check */
324 rc
= bfad_reg_offset_check(bfa
, addr
, len
);
326 printk(KERN_INFO
"bfad[%d]: Failed reg offset check\n",
328 kfree(bfad
->regdata
);
329 bfad
->regdata
= NULL
;
334 reg_addr
= rb
+ addr
;
335 regbuf
= (u32
*)bfad
->regdata
;
336 spin_lock_irqsave(&bfad
->bfad_lock
, flags
);
337 for (i
= 0; i
< len
; i
++) {
338 *regbuf
= readl(reg_addr
);
340 reg_addr
+= sizeof(u32
);
342 spin_unlock_irqrestore(&bfad
->bfad_lock
, flags
);
348 bfad_debugfs_write_regwr(struct file
*file
, const char __user
*buf
,
349 size_t nbytes
, loff_t
*ppos
)
351 struct bfad_debug_info
*debug
= file
->private_data
;
352 struct bfad_port_s
*port
= (struct bfad_port_s
*)debug
->i_private
;
353 struct bfad_s
*bfad
= port
->bfad
;
354 struct bfa_s
*bfa
= &bfad
->bfa
;
355 struct bfa_ioc_s
*ioc
= &bfa
->ioc
;
357 void __iomem
*reg_addr
;
361 kern_buf
= kzalloc(nbytes
, GFP_KERNEL
);
364 printk(KERN_INFO
"bfad[%d]: Failed to allocate buffer\n",
369 if (copy_from_user(kern_buf
, (void __user
*)buf
, nbytes
)) {
374 rc
= sscanf(kern_buf
, "%x:%x", &addr
, &val
);
377 "bfad[%d]: %s failed to read user buf\n",
378 bfad
->inst_no
, __func__
);
384 addr
&= BFA_REG_ADDRMSK(ioc
); /* offset only 17 bit and word align */
386 /* offset and len sanity check */
387 rc
= bfad_reg_offset_check(bfa
, addr
, 1);
390 "bfad[%d]: Failed reg offset check\n",
395 reg_addr
= (bfa_ioc_bar0(ioc
)) + addr
;
396 spin_lock_irqsave(&bfad
->bfad_lock
, flags
);
397 writel(val
, reg_addr
);
398 spin_unlock_irqrestore(&bfad
->bfad_lock
, flags
);
404 bfad_debugfs_release(struct inode
*inode
, struct file
*file
)
406 struct bfad_debug_info
*debug
= file
->private_data
;
411 file
->private_data
= NULL
;
417 bfad_debugfs_release_fwtrc(struct inode
*inode
, struct file
*file
)
419 struct bfad_debug_info
*fw_debug
= file
->private_data
;
424 if (fw_debug
->debug_buffer
)
425 vfree(fw_debug
->debug_buffer
);
427 file
->private_data
= NULL
;
432 static const struct file_operations bfad_debugfs_op_drvtrc
= {
433 .owner
= THIS_MODULE
,
434 .open
= bfad_debugfs_open_drvtrc
,
435 .llseek
= bfad_debugfs_lseek
,
436 .read
= bfad_debugfs_read
,
437 .release
= bfad_debugfs_release
,
440 static const struct file_operations bfad_debugfs_op_fwtrc
= {
441 .owner
= THIS_MODULE
,
442 .open
= bfad_debugfs_open_fwtrc
,
443 .llseek
= bfad_debugfs_lseek
,
444 .read
= bfad_debugfs_read
,
445 .release
= bfad_debugfs_release_fwtrc
,
448 static const struct file_operations bfad_debugfs_op_fwsave
= {
449 .owner
= THIS_MODULE
,
450 .open
= bfad_debugfs_open_fwsave
,
451 .llseek
= bfad_debugfs_lseek
,
452 .read
= bfad_debugfs_read
,
453 .release
= bfad_debugfs_release_fwtrc
,
456 static const struct file_operations bfad_debugfs_op_regrd
= {
457 .owner
= THIS_MODULE
,
458 .open
= bfad_debugfs_open_reg
,
459 .llseek
= bfad_debugfs_lseek
,
460 .read
= bfad_debugfs_read_regrd
,
461 .write
= bfad_debugfs_write_regrd
,
462 .release
= bfad_debugfs_release
,
465 static const struct file_operations bfad_debugfs_op_regwr
= {
466 .owner
= THIS_MODULE
,
467 .open
= bfad_debugfs_open_reg
,
468 .llseek
= bfad_debugfs_lseek
,
469 .write
= bfad_debugfs_write_regwr
,
470 .release
= bfad_debugfs_release
,
473 struct bfad_debugfs_entry
{
476 const struct file_operations
*fops
;
479 static const struct bfad_debugfs_entry bfad_debugfs_files
[] = {
480 { "drvtrc", S_IFREG
|S_IRUGO
, &bfad_debugfs_op_drvtrc
, },
481 { "fwtrc", S_IFREG
|S_IRUGO
, &bfad_debugfs_op_fwtrc
, },
482 { "fwsave", S_IFREG
|S_IRUGO
, &bfad_debugfs_op_fwsave
, },
483 { "regrd", S_IFREG
|S_IRUGO
|S_IWUSR
, &bfad_debugfs_op_regrd
, },
484 { "regwr", S_IFREG
|S_IWUSR
, &bfad_debugfs_op_regwr
, },
487 static struct dentry
*bfa_debugfs_root
;
488 static atomic_t bfa_debugfs_port_count
;
491 bfad_debugfs_init(struct bfad_port_s
*port
)
493 struct bfad_s
*bfad
= port
->bfad
;
494 const struct bfad_debugfs_entry
*file
;
498 if (!bfa_debugfs_enable
)
501 /* Setup the BFA debugfs root directory*/
502 if (!bfa_debugfs_root
) {
503 bfa_debugfs_root
= debugfs_create_dir("bfa", NULL
);
504 atomic_set(&bfa_debugfs_port_count
, 0);
505 if (!bfa_debugfs_root
) {
507 "BFA debugfs root dir creation failed\n");
512 /* Setup the pci_dev debugfs directory for the port */
513 snprintf(name
, sizeof(name
), "pci_dev:%s", bfad
->pci_name
);
514 if (!port
->port_debugfs_root
) {
515 port
->port_debugfs_root
=
516 debugfs_create_dir(name
, bfa_debugfs_root
);
517 if (!port
->port_debugfs_root
) {
519 "bfa %s: debugfs root creation failed\n",
524 atomic_inc(&bfa_debugfs_port_count
);
526 for (i
= 0; i
< ARRAY_SIZE(bfad_debugfs_files
); i
++) {
527 file
= &bfad_debugfs_files
[i
];
528 bfad
->bfad_dentry_files
[i
] =
529 debugfs_create_file(file
->name
,
531 port
->port_debugfs_root
,
534 if (!bfad
->bfad_dentry_files
[i
]) {
536 "bfa %s: debugfs %s creation failed\n",
537 bfad
->pci_name
, file
->name
);
548 bfad_debugfs_exit(struct bfad_port_s
*port
)
550 struct bfad_s
*bfad
= port
->bfad
;
553 for (i
= 0; i
< ARRAY_SIZE(bfad_debugfs_files
); i
++) {
554 if (bfad
->bfad_dentry_files
[i
]) {
555 debugfs_remove(bfad
->bfad_dentry_files
[i
]);
556 bfad
->bfad_dentry_files
[i
] = NULL
;
560 /* Remove the pci_dev debugfs directory for the port */
561 if (port
->port_debugfs_root
) {
562 debugfs_remove(port
->port_debugfs_root
);
563 port
->port_debugfs_root
= NULL
;
564 atomic_dec(&bfa_debugfs_port_count
);
567 /* Remove the BFA debugfs root directory */
568 if (atomic_read(&bfa_debugfs_port_count
) == 0) {
569 debugfs_remove(bfa_debugfs_root
);
570 bfa_debugfs_root
= NULL
;