1 /* 2 * Linux network driver for QLogic BR-series Converged Network Adapter. 3 * 4 * This program is free software; you can redistribute it and/or modify it 5 * under the terms of the GNU General Public License (GPL) Version 2 as 6 * published by the Free Software Foundation 7 * 8 * This program is distributed in the hope that it will be useful, but 9 * WITHOUT ANY WARRANTY; without even the implied warranty of 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 11 * General Public License for more details. 12 */ 13 /* 14 * Copyright (c) 2005-2014 Brocade Communications Systems, Inc. 15 * Copyright (c) 2014-2015 QLogic Corporation 16 * All rights reserved 17 * www.qlogic.com 18 */ 19 20 #include <linux/debugfs.h> 21 #include <linux/module.h> 22 #include "bnad.h" 23 24 /* 25 * BNA debufs interface 26 * 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 30 * 31 * BNA Hierarchy: 32 * - bna/pci_dev:<pci_name> 33 * where the pci_name corresponds to the one under /sys/bus/pci/drivers/bna 34 * 35 * Debugging service available per pci_dev: 36 * fwtrc: To collect current firmware trace. 37 * fwsave: To collect last saved fw trace as a result of firmware crash. 38 * regwr: To write one word to chip register 39 * regrd: To read one or more words from chip register. 40 */ 41 42 struct bnad_debug_info { 43 char *debug_buffer; 44 void *i_private; 45 int buffer_len; 46 }; 47 48 static int 49 bnad_debugfs_open_fwtrc(struct inode *inode, struct file *file) 50 { 51 struct bnad *bnad = inode->i_private; 52 struct bnad_debug_info *fw_debug; 53 unsigned long flags; 54 int rc; 55 56 fw_debug = kzalloc(sizeof(struct bnad_debug_info), GFP_KERNEL); 57 if (!fw_debug) 58 return -ENOMEM; 59 60 fw_debug->buffer_len = BNA_DBG_FWTRC_LEN; 61 62 fw_debug->debug_buffer = kzalloc(fw_debug->buffer_len, GFP_KERNEL); 63 if (!fw_debug->debug_buffer) { 64 kfree(fw_debug); 65 fw_debug = NULL; 66 return -ENOMEM; 67 } 68 69 spin_lock_irqsave(&bnad->bna_lock, flags); 70 rc = bfa_nw_ioc_debug_fwtrc(&bnad->bna.ioceth.ioc, 71 fw_debug->debug_buffer, 72 &fw_debug->buffer_len); 73 spin_unlock_irqrestore(&bnad->bna_lock, flags); 74 if (rc != BFA_STATUS_OK) { 75 kfree(fw_debug->debug_buffer); 76 fw_debug->debug_buffer = NULL; 77 kfree(fw_debug); 78 fw_debug = NULL; 79 pr_warn("bnad %s: Failed to collect fwtrc\n", 80 pci_name(bnad->pcidev)); 81 return -ENOMEM; 82 } 83 84 file->private_data = fw_debug; 85 86 return 0; 87 } 88 89 static int 90 bnad_debugfs_open_fwsave(struct inode *inode, struct file *file) 91 { 92 struct bnad *bnad = inode->i_private; 93 struct bnad_debug_info *fw_debug; 94 unsigned long flags; 95 int rc; 96 97 fw_debug = kzalloc(sizeof(struct bnad_debug_info), GFP_KERNEL); 98 if (!fw_debug) 99 return -ENOMEM; 100 101 fw_debug->buffer_len = BNA_DBG_FWTRC_LEN; 102 103 fw_debug->debug_buffer = kzalloc(fw_debug->buffer_len, GFP_KERNEL); 104 if (!fw_debug->debug_buffer) { 105 kfree(fw_debug); 106 fw_debug = NULL; 107 return -ENOMEM; 108 } 109 110 spin_lock_irqsave(&bnad->bna_lock, flags); 111 rc = bfa_nw_ioc_debug_fwsave(&bnad->bna.ioceth.ioc, 112 fw_debug->debug_buffer, 113 &fw_debug->buffer_len); 114 spin_unlock_irqrestore(&bnad->bna_lock, flags); 115 if (rc != BFA_STATUS_OK && rc != BFA_STATUS_ENOFSAVE) { 116 kfree(fw_debug->debug_buffer); 117 fw_debug->debug_buffer = NULL; 118 kfree(fw_debug); 119 fw_debug = NULL; 120 pr_warn("bna %s: Failed to collect fwsave\n", 121 pci_name(bnad->pcidev)); 122 return -ENOMEM; 123 } 124 125 file->private_data = fw_debug; 126 127 return 0; 128 } 129 130 static int 131 bnad_debugfs_open_reg(struct inode *inode, struct file *file) 132 { 133 struct bnad_debug_info *reg_debug; 134 135 reg_debug = kzalloc(sizeof(struct bnad_debug_info), GFP_KERNEL); 136 if (!reg_debug) 137 return -ENOMEM; 138 139 reg_debug->i_private = inode->i_private; 140 141 file->private_data = reg_debug; 142 143 return 0; 144 } 145 146 static int 147 bnad_get_debug_drvinfo(struct bnad *bnad, void *buffer, u32 len) 148 { 149 struct bnad_drvinfo *drvinfo = (struct bnad_drvinfo *) buffer; 150 struct bnad_iocmd_comp fcomp; 151 unsigned long flags = 0; 152 int ret = BFA_STATUS_FAILED; 153 154 /* Get IOC info */ 155 spin_lock_irqsave(&bnad->bna_lock, flags); 156 bfa_nw_ioc_get_attr(&bnad->bna.ioceth.ioc, &drvinfo->ioc_attr); 157 spin_unlock_irqrestore(&bnad->bna_lock, flags); 158 159 /* Retrieve CEE related info */ 160 fcomp.bnad = bnad; 161 fcomp.comp_status = 0; 162 init_completion(&fcomp.comp); 163 spin_lock_irqsave(&bnad->bna_lock, flags); 164 ret = bfa_nw_cee_get_attr(&bnad->bna.cee, &drvinfo->cee_attr, 165 bnad_cb_completion, &fcomp); 166 if (ret != BFA_STATUS_OK) { 167 spin_unlock_irqrestore(&bnad->bna_lock, flags); 168 goto out; 169 } 170 spin_unlock_irqrestore(&bnad->bna_lock, flags); 171 wait_for_completion(&fcomp.comp); 172 drvinfo->cee_status = fcomp.comp_status; 173 174 /* Retrieve flash partition info */ 175 fcomp.comp_status = 0; 176 reinit_completion(&fcomp.comp); 177 spin_lock_irqsave(&bnad->bna_lock, flags); 178 ret = bfa_nw_flash_get_attr(&bnad->bna.flash, &drvinfo->flash_attr, 179 bnad_cb_completion, &fcomp); 180 if (ret != BFA_STATUS_OK) { 181 spin_unlock_irqrestore(&bnad->bna_lock, flags); 182 goto out; 183 } 184 spin_unlock_irqrestore(&bnad->bna_lock, flags); 185 wait_for_completion(&fcomp.comp); 186 drvinfo->flash_status = fcomp.comp_status; 187 out: 188 return ret; 189 } 190 191 static int 192 bnad_debugfs_open_drvinfo(struct inode *inode, struct file *file) 193 { 194 struct bnad *bnad = inode->i_private; 195 struct bnad_debug_info *drv_info; 196 int rc; 197 198 drv_info = kzalloc(sizeof(struct bnad_debug_info), GFP_KERNEL); 199 if (!drv_info) 200 return -ENOMEM; 201 202 drv_info->buffer_len = sizeof(struct bnad_drvinfo); 203 204 drv_info->debug_buffer = kzalloc(drv_info->buffer_len, GFP_KERNEL); 205 if (!drv_info->debug_buffer) { 206 kfree(drv_info); 207 drv_info = NULL; 208 return -ENOMEM; 209 } 210 211 mutex_lock(&bnad->conf_mutex); 212 rc = bnad_get_debug_drvinfo(bnad, drv_info->debug_buffer, 213 drv_info->buffer_len); 214 mutex_unlock(&bnad->conf_mutex); 215 if (rc != BFA_STATUS_OK) { 216 kfree(drv_info->debug_buffer); 217 drv_info->debug_buffer = NULL; 218 kfree(drv_info); 219 drv_info = NULL; 220 pr_warn("bna %s: Failed to collect drvinfo\n", 221 pci_name(bnad->pcidev)); 222 return -ENOMEM; 223 } 224 225 file->private_data = drv_info; 226 227 return 0; 228 } 229 230 /* Changes the current file position */ 231 static loff_t 232 bnad_debugfs_lseek(struct file *file, loff_t offset, int orig) 233 { 234 struct bnad_debug_info *debug = file->private_data; 235 236 if (!debug) 237 return -EINVAL; 238 239 return fixed_size_llseek(file, offset, orig, debug->buffer_len); 240 } 241 242 static ssize_t 243 bnad_debugfs_read(struct file *file, char __user *buf, 244 size_t nbytes, loff_t *pos) 245 { 246 struct bnad_debug_info *debug = file->private_data; 247 248 if (!debug || !debug->debug_buffer) 249 return 0; 250 251 return simple_read_from_buffer(buf, nbytes, pos, 252 debug->debug_buffer, debug->buffer_len); 253 } 254 255 #define BFA_REG_CT_ADDRSZ (0x40000) 256 #define BFA_REG_CB_ADDRSZ (0x20000) 257 #define BFA_REG_ADDRSZ(__ioc) \ 258 ((u32)(bfa_asic_id_ctc(bfa_ioc_devid(__ioc)) ? \ 259 BFA_REG_CT_ADDRSZ : BFA_REG_CB_ADDRSZ)) 260 #define BFA_REG_ADDRMSK(__ioc) (BFA_REG_ADDRSZ(__ioc) - 1) 261 262 /* 263 * Function to check if the register offset passed is valid. 264 */ 265 static int 266 bna_reg_offset_check(struct bfa_ioc *ioc, u32 offset, u32 len) 267 { 268 u8 area; 269 270 /* check [16:15] */ 271 area = (offset >> 15) & 0x7; 272 if (area == 0) { 273 /* PCIe core register */ 274 if ((offset + (len<<2)) > 0x8000) /* 8k dwords or 32KB */ 275 return BFA_STATUS_EINVAL; 276 } else if (area == 0x1) { 277 /* CB 32 KB memory page */ 278 if ((offset + (len<<2)) > 0x10000) /* 8k dwords or 32KB */ 279 return BFA_STATUS_EINVAL; 280 } else { 281 /* CB register space 64KB */ 282 if ((offset + (len<<2)) > BFA_REG_ADDRMSK(ioc)) 283 return BFA_STATUS_EINVAL; 284 } 285 return BFA_STATUS_OK; 286 } 287 288 static ssize_t 289 bnad_debugfs_read_regrd(struct file *file, char __user *buf, 290 size_t nbytes, loff_t *pos) 291 { 292 struct bnad_debug_info *regrd_debug = file->private_data; 293 struct bnad *bnad = (struct bnad *)regrd_debug->i_private; 294 ssize_t rc; 295 296 if (!bnad->regdata) 297 return 0; 298 299 rc = simple_read_from_buffer(buf, nbytes, pos, 300 bnad->regdata, bnad->reglen); 301 302 if ((*pos + nbytes) >= bnad->reglen) { 303 kfree(bnad->regdata); 304 bnad->regdata = NULL; 305 bnad->reglen = 0; 306 } 307 308 return rc; 309 } 310 311 static ssize_t 312 bnad_debugfs_write_regrd(struct file *file, const char __user *buf, 313 size_t nbytes, loff_t *ppos) 314 { 315 struct bnad_debug_info *regrd_debug = file->private_data; 316 struct bnad *bnad = (struct bnad *)regrd_debug->i_private; 317 struct bfa_ioc *ioc = &bnad->bna.ioceth.ioc; 318 int addr, len, rc, i; 319 u32 *regbuf; 320 void __iomem *rb, *reg_addr; 321 unsigned long flags; 322 void *kern_buf; 323 324 /* Copy the user space buf */ 325 kern_buf = memdup_user(buf, nbytes); 326 if (IS_ERR(kern_buf)) 327 return PTR_ERR(kern_buf); 328 329 rc = sscanf(kern_buf, "%x:%x", &addr, &len); 330 if (rc < 2) { 331 pr_warn("bna %s: Failed to read user buffer\n", 332 pci_name(bnad->pcidev)); 333 kfree(kern_buf); 334 return -EINVAL; 335 } 336 337 kfree(kern_buf); 338 kfree(bnad->regdata); 339 bnad->reglen = 0; 340 341 bnad->regdata = kzalloc(len << 2, GFP_KERNEL); 342 if (!bnad->regdata) 343 return -ENOMEM; 344 345 bnad->reglen = len << 2; 346 rb = bfa_ioc_bar0(ioc); 347 addr &= BFA_REG_ADDRMSK(ioc); 348 349 /* offset and len sanity check */ 350 rc = bna_reg_offset_check(ioc, addr, len); 351 if (rc) { 352 pr_warn("bna %s: Failed reg offset check\n", 353 pci_name(bnad->pcidev)); 354 kfree(bnad->regdata); 355 bnad->regdata = NULL; 356 bnad->reglen = 0; 357 return -EINVAL; 358 } 359 360 reg_addr = rb + addr; 361 regbuf = (u32 *)bnad->regdata; 362 spin_lock_irqsave(&bnad->bna_lock, flags); 363 for (i = 0; i < len; i++) { 364 *regbuf = readl(reg_addr); 365 regbuf++; 366 reg_addr += sizeof(u32); 367 } 368 spin_unlock_irqrestore(&bnad->bna_lock, flags); 369 370 return nbytes; 371 } 372 373 static ssize_t 374 bnad_debugfs_write_regwr(struct file *file, const char __user *buf, 375 size_t nbytes, loff_t *ppos) 376 { 377 struct bnad_debug_info *debug = file->private_data; 378 struct bnad *bnad = (struct bnad *)debug->i_private; 379 struct bfa_ioc *ioc = &bnad->bna.ioceth.ioc; 380 int addr, val, rc; 381 void __iomem *reg_addr; 382 unsigned long flags; 383 void *kern_buf; 384 385 /* Copy the user space buf */ 386 kern_buf = memdup_user(buf, nbytes); 387 if (IS_ERR(kern_buf)) 388 return PTR_ERR(kern_buf); 389 390 rc = sscanf(kern_buf, "%x:%x", &addr, &val); 391 if (rc < 2) { 392 pr_warn("bna %s: Failed to read user buffer\n", 393 pci_name(bnad->pcidev)); 394 kfree(kern_buf); 395 return -EINVAL; 396 } 397 kfree(kern_buf); 398 399 addr &= BFA_REG_ADDRMSK(ioc); /* offset only 17 bit and word align */ 400 401 /* offset and len sanity check */ 402 rc = bna_reg_offset_check(ioc, addr, 1); 403 if (rc) { 404 pr_warn("bna %s: Failed reg offset check\n", 405 pci_name(bnad->pcidev)); 406 return -EINVAL; 407 } 408 409 reg_addr = (bfa_ioc_bar0(ioc)) + addr; 410 spin_lock_irqsave(&bnad->bna_lock, flags); 411 writel(val, reg_addr); 412 spin_unlock_irqrestore(&bnad->bna_lock, flags); 413 414 return nbytes; 415 } 416 417 static int 418 bnad_debugfs_release(struct inode *inode, struct file *file) 419 { 420 struct bnad_debug_info *debug = file->private_data; 421 422 if (!debug) 423 return 0; 424 425 file->private_data = NULL; 426 kfree(debug); 427 return 0; 428 } 429 430 static int 431 bnad_debugfs_buffer_release(struct inode *inode, struct file *file) 432 { 433 struct bnad_debug_info *debug = file->private_data; 434 435 if (!debug) 436 return 0; 437 438 kfree(debug->debug_buffer); 439 440 file->private_data = NULL; 441 kfree(debug); 442 debug = NULL; 443 return 0; 444 } 445 446 static const struct file_operations bnad_debugfs_op_fwtrc = { 447 .owner = THIS_MODULE, 448 .open = bnad_debugfs_open_fwtrc, 449 .llseek = bnad_debugfs_lseek, 450 .read = bnad_debugfs_read, 451 .release = bnad_debugfs_buffer_release, 452 }; 453 454 static const struct file_operations bnad_debugfs_op_fwsave = { 455 .owner = THIS_MODULE, 456 .open = bnad_debugfs_open_fwsave, 457 .llseek = bnad_debugfs_lseek, 458 .read = bnad_debugfs_read, 459 .release = bnad_debugfs_buffer_release, 460 }; 461 462 static const struct file_operations bnad_debugfs_op_regrd = { 463 .owner = THIS_MODULE, 464 .open = bnad_debugfs_open_reg, 465 .llseek = bnad_debugfs_lseek, 466 .read = bnad_debugfs_read_regrd, 467 .write = bnad_debugfs_write_regrd, 468 .release = bnad_debugfs_release, 469 }; 470 471 static const struct file_operations bnad_debugfs_op_regwr = { 472 .owner = THIS_MODULE, 473 .open = bnad_debugfs_open_reg, 474 .llseek = bnad_debugfs_lseek, 475 .write = bnad_debugfs_write_regwr, 476 .release = bnad_debugfs_release, 477 }; 478 479 static const struct file_operations bnad_debugfs_op_drvinfo = { 480 .owner = THIS_MODULE, 481 .open = bnad_debugfs_open_drvinfo, 482 .llseek = bnad_debugfs_lseek, 483 .read = bnad_debugfs_read, 484 .release = bnad_debugfs_buffer_release, 485 }; 486 487 struct bnad_debugfs_entry { 488 const char *name; 489 umode_t mode; 490 const struct file_operations *fops; 491 }; 492 493 static const struct bnad_debugfs_entry bnad_debugfs_files[] = { 494 { "fwtrc", S_IFREG|S_IRUGO, &bnad_debugfs_op_fwtrc, }, 495 { "fwsave", S_IFREG|S_IRUGO, &bnad_debugfs_op_fwsave, }, 496 { "regrd", S_IFREG|S_IRUGO|S_IWUSR, &bnad_debugfs_op_regrd, }, 497 { "regwr", S_IFREG|S_IWUSR, &bnad_debugfs_op_regwr, }, 498 { "drvinfo", S_IFREG|S_IRUGO, &bnad_debugfs_op_drvinfo, }, 499 }; 500 501 static struct dentry *bna_debugfs_root; 502 static atomic_t bna_debugfs_port_count; 503 504 /* Initialize debugfs interface for BNA */ 505 void 506 bnad_debugfs_init(struct bnad *bnad) 507 { 508 const struct bnad_debugfs_entry *file; 509 char name[64]; 510 int i; 511 512 /* Setup the BNA debugfs root directory*/ 513 if (!bna_debugfs_root) { 514 bna_debugfs_root = debugfs_create_dir("bna", NULL); 515 atomic_set(&bna_debugfs_port_count, 0); 516 if (!bna_debugfs_root) { 517 pr_warn("BNA: debugfs root dir creation failed\n"); 518 return; 519 } 520 } 521 522 /* Setup the pci_dev debugfs directory for the port */ 523 snprintf(name, sizeof(name), "pci_dev:%s", pci_name(bnad->pcidev)); 524 if (!bnad->port_debugfs_root) { 525 bnad->port_debugfs_root = 526 debugfs_create_dir(name, bna_debugfs_root); 527 if (!bnad->port_debugfs_root) { 528 pr_warn("bna pci_dev %s: root dir creation failed\n", 529 pci_name(bnad->pcidev)); 530 return; 531 } 532 533 atomic_inc(&bna_debugfs_port_count); 534 535 for (i = 0; i < ARRAY_SIZE(bnad_debugfs_files); i++) { 536 file = &bnad_debugfs_files[i]; 537 bnad->bnad_dentry_files[i] = 538 debugfs_create_file(file->name, 539 file->mode, 540 bnad->port_debugfs_root, 541 bnad, 542 file->fops); 543 if (!bnad->bnad_dentry_files[i]) { 544 pr_warn( 545 "BNA pci_dev:%s: create %s entry failed\n", 546 pci_name(bnad->pcidev), file->name); 547 return; 548 } 549 } 550 } 551 } 552 553 /* Uninitialize debugfs interface for BNA */ 554 void 555 bnad_debugfs_uninit(struct bnad *bnad) 556 { 557 int i; 558 559 for (i = 0; i < ARRAY_SIZE(bnad_debugfs_files); i++) { 560 if (bnad->bnad_dentry_files[i]) { 561 debugfs_remove(bnad->bnad_dentry_files[i]); 562 bnad->bnad_dentry_files[i] = NULL; 563 } 564 } 565 566 /* Remove the pci_dev debugfs directory for the port */ 567 if (bnad->port_debugfs_root) { 568 debugfs_remove(bnad->port_debugfs_root); 569 bnad->port_debugfs_root = NULL; 570 atomic_dec(&bna_debugfs_port_count); 571 } 572 573 /* Remove the BNA debugfs root directory */ 574 if (atomic_read(&bna_debugfs_port_count) == 0) { 575 debugfs_remove(bna_debugfs_root); 576 bna_debugfs_root = NULL; 577 } 578 } 579