1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright (c) 2005-2014 Brocade Communications Systems, Inc.
4 * Copyright (c) 2014- QLogic Corporation.
8 * Linux driver for QLogic BR-series Fibre Channel Host Bus Adapter.
11 #include <linux/debugfs.h>
12 #include <linux/export.h>
18 * BFA debufs interface
20 * To access the interface, debugfs file system should be mounted
21 * if not already mounted using:
22 * mount -t debugfs none /sys/kernel/debug
25 * - bfa/pci_dev:<pci_name>
26 * where the pci_name corresponds to the one under /sys/bus/pci/drivers/bfa
28 * Debugging service available per pci_dev:
29 * fwtrc: To collect current firmware trace.
30 * drvtrc: To collect current driver trace
31 * fwsave: To collect last saved fw trace as a result of firmware crash.
32 * regwr: To write one word to chip register
33 * regrd: To read one or more words from chip register.
36 struct bfad_debug_info
{
43 bfad_debugfs_open_drvtrc(struct inode
*inode
, struct file
*file
)
45 struct bfad_port_s
*port
= inode
->i_private
;
46 struct bfad_s
*bfad
= port
->bfad
;
47 struct bfad_debug_info
*debug
;
49 debug
= kzalloc(sizeof(struct bfad_debug_info
), GFP_KERNEL
);
53 debug
->debug_buffer
= (void *) bfad
->trcmod
;
54 debug
->buffer_len
= sizeof(struct bfa_trc_mod_s
);
56 file
->private_data
= debug
;
62 bfad_debugfs_open_fwtrc(struct inode
*inode
, struct file
*file
)
64 struct bfad_port_s
*port
= inode
->i_private
;
65 struct bfad_s
*bfad
= port
->bfad
;
66 struct bfad_debug_info
*fw_debug
;
70 fw_debug
= kzalloc(sizeof(struct bfad_debug_info
), GFP_KERNEL
);
74 fw_debug
->buffer_len
= sizeof(struct bfa_trc_mod_s
);
76 fw_debug
->debug_buffer
= vzalloc(fw_debug
->buffer_len
);
77 if (!fw_debug
->debug_buffer
) {
79 printk(KERN_INFO
"bfad[%d]: Failed to allocate fwtrc buffer\n",
84 spin_lock_irqsave(&bfad
->bfad_lock
, flags
);
85 rc
= bfa_ioc_debug_fwtrc(&bfad
->bfa
.ioc
,
86 fw_debug
->debug_buffer
,
87 &fw_debug
->buffer_len
);
88 spin_unlock_irqrestore(&bfad
->bfad_lock
, flags
);
89 if (rc
!= BFA_STATUS_OK
) {
90 vfree(fw_debug
->debug_buffer
);
91 fw_debug
->debug_buffer
= NULL
;
93 printk(KERN_INFO
"bfad[%d]: Failed to collect fwtrc\n",
98 file
->private_data
= fw_debug
;
104 bfad_debugfs_open_fwsave(struct inode
*inode
, struct file
*file
)
106 struct bfad_port_s
*port
= inode
->i_private
;
107 struct bfad_s
*bfad
= port
->bfad
;
108 struct bfad_debug_info
*fw_debug
;
112 fw_debug
= kzalloc(sizeof(struct bfad_debug_info
), GFP_KERNEL
);
116 fw_debug
->buffer_len
= sizeof(struct bfa_trc_mod_s
);
118 fw_debug
->debug_buffer
= vzalloc(fw_debug
->buffer_len
);
119 if (!fw_debug
->debug_buffer
) {
121 printk(KERN_INFO
"bfad[%d]: Failed to allocate fwsave buffer\n",
126 spin_lock_irqsave(&bfad
->bfad_lock
, flags
);
127 rc
= bfa_ioc_debug_fwsave(&bfad
->bfa
.ioc
,
128 fw_debug
->debug_buffer
,
129 &fw_debug
->buffer_len
);
130 spin_unlock_irqrestore(&bfad
->bfad_lock
, flags
);
131 if (rc
!= BFA_STATUS_OK
) {
132 vfree(fw_debug
->debug_buffer
);
133 fw_debug
->debug_buffer
= NULL
;
135 printk(KERN_INFO
"bfad[%d]: Failed to collect fwsave\n",
140 file
->private_data
= fw_debug
;
146 bfad_debugfs_open_reg(struct inode
*inode
, struct file
*file
)
148 struct bfad_debug_info
*reg_debug
;
150 reg_debug
= kzalloc(sizeof(struct bfad_debug_info
), GFP_KERNEL
);
154 reg_debug
->i_private
= inode
->i_private
;
156 file
->private_data
= reg_debug
;
161 /* Changes the current file position */
163 bfad_debugfs_lseek(struct file
*file
, loff_t offset
, int orig
)
165 struct bfad_debug_info
*debug
= file
->private_data
;
166 return fixed_size_llseek(file
, offset
, orig
,
171 bfad_debugfs_read(struct file
*file
, char __user
*buf
,
172 size_t nbytes
, loff_t
*pos
)
174 struct bfad_debug_info
*debug
= file
->private_data
;
176 if (!debug
|| !debug
->debug_buffer
)
179 return simple_read_from_buffer(buf
, nbytes
, pos
,
180 debug
->debug_buffer
, debug
->buffer_len
);
183 #define BFA_REG_CT_ADDRSZ (0x40000)
184 #define BFA_REG_CB_ADDRSZ (0x20000)
185 #define BFA_REG_ADDRSZ(__ioc) \
186 ((u32)(bfa_asic_id_ctc(bfa_ioc_devid(__ioc)) ? \
187 BFA_REG_CT_ADDRSZ : BFA_REG_CB_ADDRSZ))
188 #define BFA_REG_ADDRMSK(__ioc) (BFA_REG_ADDRSZ(__ioc) - 1)
191 bfad_reg_offset_check(struct bfa_s
*bfa
, u32 offset
, u32 len
)
196 area
= (offset
>> 15) & 0x7;
198 /* PCIe core register */
199 if ((offset
+ (len
<<2)) > 0x8000) /* 8k dwords or 32KB */
200 return BFA_STATUS_EINVAL
;
201 } else if (area
== 0x1) {
202 /* CB 32 KB memory page */
203 if ((offset
+ (len
<<2)) > 0x10000) /* 8k dwords or 32KB */
204 return BFA_STATUS_EINVAL
;
206 /* CB register space 64KB */
207 if ((offset
+ (len
<<2)) > BFA_REG_ADDRMSK(&bfa
->ioc
))
208 return BFA_STATUS_EINVAL
;
210 return BFA_STATUS_OK
;
214 bfad_debugfs_read_regrd(struct file
*file
, char __user
*buf
,
215 size_t nbytes
, loff_t
*pos
)
217 struct bfad_debug_info
*regrd_debug
= file
->private_data
;
218 struct bfad_port_s
*port
= (struct bfad_port_s
*)regrd_debug
->i_private
;
219 struct bfad_s
*bfad
= port
->bfad
;
225 rc
= simple_read_from_buffer(buf
, nbytes
, pos
,
226 bfad
->regdata
, bfad
->reglen
);
228 if ((*pos
+ nbytes
) >= bfad
->reglen
) {
229 kfree(bfad
->regdata
);
230 bfad
->regdata
= NULL
;
238 bfad_debugfs_write_regrd(struct file
*file
, const char __user
*buf
,
239 size_t nbytes
, loff_t
*ppos
)
241 struct bfad_debug_info
*regrd_debug
= file
->private_data
;
242 struct bfad_port_s
*port
= (struct bfad_port_s
*)regrd_debug
->i_private
;
243 struct bfad_s
*bfad
= port
->bfad
;
244 struct bfa_s
*bfa
= &bfad
->bfa
;
245 struct bfa_ioc_s
*ioc
= &bfa
->ioc
;
249 void __iomem
*rb
, *reg_addr
;
253 kern_buf
= memdup_user(buf
, nbytes
);
254 if (IS_ERR(kern_buf
))
255 return PTR_ERR(kern_buf
);
257 rc
= sscanf(kern_buf
, "%x:%x", &addr
, &len
);
258 if (rc
< 2 || len
> (UINT_MAX
>> 2)) {
260 "bfad[%d]: %s failed to read user buf\n",
261 bfad
->inst_no
, __func__
);
267 kfree(bfad
->regdata
);
268 bfad
->regdata
= NULL
;
271 bfad
->regdata
= kzalloc(len
<< 2, GFP_KERNEL
);
272 if (!bfad
->regdata
) {
273 printk(KERN_INFO
"bfad[%d]: Failed to allocate regrd buffer\n",
278 bfad
->reglen
= len
<< 2;
279 rb
= bfa_ioc_bar0(ioc
);
280 addr
&= BFA_REG_ADDRMSK(ioc
);
282 /* offset and len sanity check */
283 rc
= bfad_reg_offset_check(bfa
, addr
, len
);
285 printk(KERN_INFO
"bfad[%d]: Failed reg offset check\n",
287 kfree(bfad
->regdata
);
288 bfad
->regdata
= NULL
;
293 reg_addr
= rb
+ addr
;
294 regbuf
= (u32
*)bfad
->regdata
;
295 spin_lock_irqsave(&bfad
->bfad_lock
, flags
);
296 for (i
= 0; i
< len
; i
++) {
297 *regbuf
= readl(reg_addr
);
299 reg_addr
+= sizeof(u32
);
301 spin_unlock_irqrestore(&bfad
->bfad_lock
, flags
);
307 bfad_debugfs_write_regwr(struct file
*file
, const char __user
*buf
,
308 size_t nbytes
, loff_t
*ppos
)
310 struct bfad_debug_info
*debug
= file
->private_data
;
311 struct bfad_port_s
*port
= (struct bfad_port_s
*)debug
->i_private
;
312 struct bfad_s
*bfad
= port
->bfad
;
313 struct bfa_s
*bfa
= &bfad
->bfa
;
314 struct bfa_ioc_s
*ioc
= &bfa
->ioc
;
316 void __iomem
*reg_addr
;
320 kern_buf
= memdup_user(buf
, nbytes
);
321 if (IS_ERR(kern_buf
))
322 return PTR_ERR(kern_buf
);
324 rc
= sscanf(kern_buf
, "%x:%x", &addr
, &val
);
327 "bfad[%d]: %s failed to read user buf\n",
328 bfad
->inst_no
, __func__
);
334 addr
&= BFA_REG_ADDRMSK(ioc
); /* offset only 17 bit and word align */
336 /* offset and len sanity check */
337 rc
= bfad_reg_offset_check(bfa
, addr
, 1);
340 "bfad[%d]: Failed reg offset check\n",
345 reg_addr
= (bfa_ioc_bar0(ioc
)) + addr
;
346 spin_lock_irqsave(&bfad
->bfad_lock
, flags
);
347 writel(val
, reg_addr
);
348 spin_unlock_irqrestore(&bfad
->bfad_lock
, flags
);
354 bfad_debugfs_release(struct inode
*inode
, struct file
*file
)
356 struct bfad_debug_info
*debug
= file
->private_data
;
361 file
->private_data
= NULL
;
367 bfad_debugfs_release_fwtrc(struct inode
*inode
, struct file
*file
)
369 struct bfad_debug_info
*fw_debug
= file
->private_data
;
374 if (fw_debug
->debug_buffer
)
375 vfree(fw_debug
->debug_buffer
);
377 file
->private_data
= NULL
;
382 static const struct file_operations bfad_debugfs_op_drvtrc
= {
383 .owner
= THIS_MODULE
,
384 .open
= bfad_debugfs_open_drvtrc
,
385 .llseek
= bfad_debugfs_lseek
,
386 .read
= bfad_debugfs_read
,
387 .release
= bfad_debugfs_release
,
390 static const struct file_operations bfad_debugfs_op_fwtrc
= {
391 .owner
= THIS_MODULE
,
392 .open
= bfad_debugfs_open_fwtrc
,
393 .llseek
= bfad_debugfs_lseek
,
394 .read
= bfad_debugfs_read
,
395 .release
= bfad_debugfs_release_fwtrc
,
398 static const struct file_operations bfad_debugfs_op_fwsave
= {
399 .owner
= THIS_MODULE
,
400 .open
= bfad_debugfs_open_fwsave
,
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_regrd
= {
407 .owner
= THIS_MODULE
,
408 .open
= bfad_debugfs_open_reg
,
409 .llseek
= bfad_debugfs_lseek
,
410 .read
= bfad_debugfs_read_regrd
,
411 .write
= bfad_debugfs_write_regrd
,
412 .release
= bfad_debugfs_release
,
415 static const struct file_operations bfad_debugfs_op_regwr
= {
416 .owner
= THIS_MODULE
,
417 .open
= bfad_debugfs_open_reg
,
418 .llseek
= bfad_debugfs_lseek
,
419 .write
= bfad_debugfs_write_regwr
,
420 .release
= bfad_debugfs_release
,
423 struct bfad_debugfs_entry
{
426 const struct file_operations
*fops
;
429 static const struct bfad_debugfs_entry bfad_debugfs_files
[] = {
430 { "drvtrc", S_IFREG
|S_IRUGO
, &bfad_debugfs_op_drvtrc
, },
431 { "fwtrc", S_IFREG
|S_IRUGO
, &bfad_debugfs_op_fwtrc
, },
432 { "fwsave", S_IFREG
|S_IRUGO
, &bfad_debugfs_op_fwsave
, },
433 { "regrd", S_IFREG
|S_IRUGO
|S_IWUSR
, &bfad_debugfs_op_regrd
, },
434 { "regwr", S_IFREG
|S_IWUSR
, &bfad_debugfs_op_regwr
, },
437 static struct dentry
*bfa_debugfs_root
;
438 static atomic_t bfa_debugfs_port_count
;
441 bfad_debugfs_init(struct bfad_port_s
*port
)
443 struct bfad_s
*bfad
= port
->bfad
;
444 const struct bfad_debugfs_entry
*file
;
448 if (!bfa_debugfs_enable
)
451 /* Setup the BFA debugfs root directory*/
452 if (!bfa_debugfs_root
) {
453 bfa_debugfs_root
= debugfs_create_dir("bfa", NULL
);
454 atomic_set(&bfa_debugfs_port_count
, 0);
457 /* Setup the pci_dev debugfs directory for the port */
458 snprintf(name
, sizeof(name
), "pci_dev:%s", bfad
->pci_name
);
459 if (!port
->port_debugfs_root
) {
460 port
->port_debugfs_root
=
461 debugfs_create_dir(name
, bfa_debugfs_root
);
463 atomic_inc(&bfa_debugfs_port_count
);
465 for (i
= 0; i
< ARRAY_SIZE(bfad_debugfs_files
); i
++) {
466 file
= &bfad_debugfs_files
[i
];
467 bfad
->bfad_dentry_files
[i
] =
468 debugfs_create_file(file
->name
,
470 port
->port_debugfs_root
,
480 bfad_debugfs_exit(struct bfad_port_s
*port
)
482 struct bfad_s
*bfad
= port
->bfad
;
485 for (i
= 0; i
< ARRAY_SIZE(bfad_debugfs_files
); i
++) {
486 if (bfad
->bfad_dentry_files
[i
]) {
487 debugfs_remove(bfad
->bfad_dentry_files
[i
]);
488 bfad
->bfad_dentry_files
[i
] = NULL
;
492 /* Remove the pci_dev debugfs directory for the port */
493 if (port
->port_debugfs_root
) {
494 debugfs_remove(port
->port_debugfs_root
);
495 port
->port_debugfs_root
= NULL
;
496 atomic_dec(&bfa_debugfs_port_count
);
499 /* Remove the BFA debugfs root directory */
500 if (atomic_read(&bfa_debugfs_port_count
) == 0) {
501 debugfs_remove(bfa_debugfs_root
);
502 bfa_debugfs_root
= NULL
;