1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (c) 2005-2014 Brocade Communications Systems, Inc. 4 * Copyright (c) 2014- QLogic Corporation. 5 * All rights reserved 6 * www.qlogic.com 7 * 8 * Linux driver for QLogic BR-series Fibre Channel Host Bus Adapter. 9 */ 10 11 #include <linux/debugfs.h> 12 #include <linux/export.h> 13 14 #include "bfad_drv.h" 15 #include "bfad_im.h" 16 17 /* 18 * BFA debufs interface 19 * 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 23 * 24 * BFA Hierarchy: 25 * - bfa/pci_dev:<pci_name> 26 * where the pci_name corresponds to the one under /sys/bus/pci/drivers/bfa 27 * 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. 34 */ 35 36 struct bfad_debug_info { 37 char *debug_buffer; 38 void *i_private; 39 int buffer_len; 40 }; 41 42 static int 43 bfad_debugfs_open_drvtrc(struct inode *inode, struct file *file) 44 { 45 struct bfad_port_s *port = inode->i_private; 46 struct bfad_s *bfad = port->bfad; 47 struct bfad_debug_info *debug; 48 49 debug = kzalloc(sizeof(struct bfad_debug_info), GFP_KERNEL); 50 if (!debug) 51 return -ENOMEM; 52 53 debug->debug_buffer = (void *) bfad->trcmod; 54 debug->buffer_len = sizeof(struct bfa_trc_mod_s); 55 56 file->private_data = debug; 57 58 return 0; 59 } 60 61 static int 62 bfad_debugfs_open_fwtrc(struct inode *inode, struct file *file) 63 { 64 struct bfad_port_s *port = inode->i_private; 65 struct bfad_s *bfad = port->bfad; 66 struct bfad_debug_info *fw_debug; 67 unsigned long flags; 68 int rc; 69 70 fw_debug = kzalloc(sizeof(struct bfad_debug_info), GFP_KERNEL); 71 if (!fw_debug) 72 return -ENOMEM; 73 74 fw_debug->buffer_len = sizeof(struct bfa_trc_mod_s); 75 76 fw_debug->debug_buffer = vzalloc(fw_debug->buffer_len); 77 if (!fw_debug->debug_buffer) { 78 kfree(fw_debug); 79 printk(KERN_INFO "bfad[%d]: Failed to allocate fwtrc buffer\n", 80 bfad->inst_no); 81 return -ENOMEM; 82 } 83 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; 92 kfree(fw_debug); 93 printk(KERN_INFO "bfad[%d]: Failed to collect fwtrc\n", 94 bfad->inst_no); 95 return -ENOMEM; 96 } 97 98 file->private_data = fw_debug; 99 100 return 0; 101 } 102 103 static int 104 bfad_debugfs_open_fwsave(struct inode *inode, struct file *file) 105 { 106 struct bfad_port_s *port = inode->i_private; 107 struct bfad_s *bfad = port->bfad; 108 struct bfad_debug_info *fw_debug; 109 unsigned long flags; 110 int rc; 111 112 fw_debug = kzalloc(sizeof(struct bfad_debug_info), GFP_KERNEL); 113 if (!fw_debug) 114 return -ENOMEM; 115 116 fw_debug->buffer_len = sizeof(struct bfa_trc_mod_s); 117 118 fw_debug->debug_buffer = vzalloc(fw_debug->buffer_len); 119 if (!fw_debug->debug_buffer) { 120 kfree(fw_debug); 121 printk(KERN_INFO "bfad[%d]: Failed to allocate fwsave buffer\n", 122 bfad->inst_no); 123 return -ENOMEM; 124 } 125 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; 134 kfree(fw_debug); 135 printk(KERN_INFO "bfad[%d]: Failed to collect fwsave\n", 136 bfad->inst_no); 137 return -ENOMEM; 138 } 139 140 file->private_data = fw_debug; 141 142 return 0; 143 } 144 145 static int 146 bfad_debugfs_open_reg(struct inode *inode, struct file *file) 147 { 148 struct bfad_debug_info *reg_debug; 149 150 reg_debug = kzalloc(sizeof(struct bfad_debug_info), GFP_KERNEL); 151 if (!reg_debug) 152 return -ENOMEM; 153 154 reg_debug->i_private = inode->i_private; 155 156 file->private_data = reg_debug; 157 158 return 0; 159 } 160 161 /* Changes the current file position */ 162 static loff_t 163 bfad_debugfs_lseek(struct file *file, loff_t offset, int orig) 164 { 165 struct bfad_debug_info *debug = file->private_data; 166 return fixed_size_llseek(file, offset, orig, 167 debug->buffer_len); 168 } 169 170 static ssize_t 171 bfad_debugfs_read(struct file *file, char __user *buf, 172 size_t nbytes, loff_t *pos) 173 { 174 struct bfad_debug_info *debug = file->private_data; 175 176 if (!debug || !debug->debug_buffer) 177 return 0; 178 179 return simple_read_from_buffer(buf, nbytes, pos, 180 debug->debug_buffer, debug->buffer_len); 181 } 182 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) 189 190 static bfa_status_t 191 bfad_reg_offset_check(struct bfa_s *bfa, u32 offset, u32 len) 192 { 193 u8 area; 194 195 /* check [16:15] */ 196 area = (offset >> 15) & 0x7; 197 if (area == 0) { 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; 205 } else { 206 /* CB register space 64KB */ 207 if ((offset + (len<<2)) > BFA_REG_ADDRMSK(&bfa->ioc)) 208 return BFA_STATUS_EINVAL; 209 } 210 return BFA_STATUS_OK; 211 } 212 213 static ssize_t 214 bfad_debugfs_read_regrd(struct file *file, char __user *buf, 215 size_t nbytes, loff_t *pos) 216 { 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; 220 ssize_t rc; 221 222 if (!bfad->regdata) 223 return 0; 224 225 rc = simple_read_from_buffer(buf, nbytes, pos, 226 bfad->regdata, bfad->reglen); 227 228 if ((*pos + nbytes) >= bfad->reglen) { 229 kfree(bfad->regdata); 230 bfad->regdata = NULL; 231 bfad->reglen = 0; 232 } 233 234 return rc; 235 } 236 237 static ssize_t 238 bfad_debugfs_write_regrd(struct file *file, const char __user *buf, 239 size_t nbytes, loff_t *ppos) 240 { 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; 246 int addr, rc, i; 247 u32 len; 248 u32 *regbuf; 249 void __iomem *rb, *reg_addr; 250 unsigned long flags; 251 void *kern_buf; 252 253 kern_buf = memdup_user(buf, nbytes); 254 if (IS_ERR(kern_buf)) 255 return PTR_ERR(kern_buf); 256 257 rc = sscanf(kern_buf, "%x:%x", &addr, &len); 258 if (rc < 2 || len > (UINT_MAX >> 2)) { 259 printk(KERN_INFO 260 "bfad[%d]: %s failed to read user buf\n", 261 bfad->inst_no, __func__); 262 kfree(kern_buf); 263 return -EINVAL; 264 } 265 266 kfree(kern_buf); 267 kfree(bfad->regdata); 268 bfad->regdata = NULL; 269 bfad->reglen = 0; 270 271 bfad->regdata = kzalloc(len << 2, GFP_KERNEL); 272 if (!bfad->regdata) { 273 printk(KERN_INFO "bfad[%d]: Failed to allocate regrd buffer\n", 274 bfad->inst_no); 275 return -ENOMEM; 276 } 277 278 bfad->reglen = len << 2; 279 rb = bfa_ioc_bar0(ioc); 280 addr &= BFA_REG_ADDRMSK(ioc); 281 282 /* offset and len sanity check */ 283 rc = bfad_reg_offset_check(bfa, addr, len); 284 if (rc) { 285 printk(KERN_INFO "bfad[%d]: Failed reg offset check\n", 286 bfad->inst_no); 287 kfree(bfad->regdata); 288 bfad->regdata = NULL; 289 bfad->reglen = 0; 290 return -EINVAL; 291 } 292 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); 298 regbuf++; 299 reg_addr += sizeof(u32); 300 } 301 spin_unlock_irqrestore(&bfad->bfad_lock, flags); 302 303 return nbytes; 304 } 305 306 static ssize_t 307 bfad_debugfs_write_regwr(struct file *file, const char __user *buf, 308 size_t nbytes, loff_t *ppos) 309 { 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; 315 int addr, val, rc; 316 void __iomem *reg_addr; 317 unsigned long flags; 318 void *kern_buf; 319 320 kern_buf = memdup_user(buf, nbytes); 321 if (IS_ERR(kern_buf)) 322 return PTR_ERR(kern_buf); 323 324 rc = sscanf(kern_buf, "%x:%x", &addr, &val); 325 if (rc < 2) { 326 printk(KERN_INFO 327 "bfad[%d]: %s failed to read user buf\n", 328 bfad->inst_no, __func__); 329 kfree(kern_buf); 330 return -EINVAL; 331 } 332 kfree(kern_buf); 333 334 addr &= BFA_REG_ADDRMSK(ioc); /* offset only 17 bit and word align */ 335 336 /* offset and len sanity check */ 337 rc = bfad_reg_offset_check(bfa, addr, 1); 338 if (rc) { 339 printk(KERN_INFO 340 "bfad[%d]: Failed reg offset check\n", 341 bfad->inst_no); 342 return -EINVAL; 343 } 344 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); 349 350 return nbytes; 351 } 352 353 static int 354 bfad_debugfs_release(struct inode *inode, struct file *file) 355 { 356 struct bfad_debug_info *debug = file->private_data; 357 358 if (!debug) 359 return 0; 360 361 file->private_data = NULL; 362 kfree(debug); 363 return 0; 364 } 365 366 static int 367 bfad_debugfs_release_fwtrc(struct inode *inode, struct file *file) 368 { 369 struct bfad_debug_info *fw_debug = file->private_data; 370 371 if (!fw_debug) 372 return 0; 373 374 if (fw_debug->debug_buffer) 375 vfree(fw_debug->debug_buffer); 376 377 file->private_data = NULL; 378 kfree(fw_debug); 379 return 0; 380 } 381 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, 388 }; 389 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, 396 }; 397 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, 404 }; 405 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, 413 }; 414 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, 421 }; 422 423 struct bfad_debugfs_entry { 424 const char *name; 425 umode_t mode; 426 const struct file_operations *fops; 427 }; 428 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, }, 435 }; 436 437 static struct dentry *bfa_debugfs_root; 438 static atomic_t bfa_debugfs_port_count; 439 440 inline void 441 bfad_debugfs_init(struct bfad_port_s *port) 442 { 443 struct bfad_s *bfad = port->bfad; 444 const struct bfad_debugfs_entry *file; 445 char name[64]; 446 int i; 447 448 if (!bfa_debugfs_enable) 449 return; 450 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); 455 } 456 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); 462 463 atomic_inc(&bfa_debugfs_port_count); 464 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, 469 file->mode, 470 port->port_debugfs_root, 471 port, 472 file->fops); 473 } 474 } 475 476 return; 477 } 478 479 inline void 480 bfad_debugfs_exit(struct bfad_port_s *port) 481 { 482 struct bfad_s *bfad = port->bfad; 483 int i; 484 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; 489 } 490 } 491 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); 497 } 498 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; 503 } 504 } 505