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 42struct bnad_debug_info { 43 char *debug_buffer; 44 void *i_private; 45 int buffer_len; 46}; 47 48static int 49bnad_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 89static int 90bnad_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 130static int 131bnad_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 146static int 147bnad_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; 187out: 188 return ret; 189} 190 191static int 192bnad_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 */ 231static loff_t 232bnad_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 242static ssize_t 243bnad_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 */ 265static int 266bna_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 288static ssize_t 289bnad_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 311static ssize_t 312bnad_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 /* Allocate memory to store the user space buf */ 325 kern_buf = kzalloc(nbytes, GFP_KERNEL); 326 if (!kern_buf) 327 return -ENOMEM; 328 329 if (copy_from_user(kern_buf, (void __user *)buf, nbytes)) { 330 kfree(kern_buf); 331 return -ENOMEM; 332 } 333 334 rc = sscanf(kern_buf, "%x:%x", &addr, &len); 335 if (rc < 2) { 336 pr_warn("bna %s: Failed to read user buffer\n", 337 pci_name(bnad->pcidev)); 338 kfree(kern_buf); 339 return -EINVAL; 340 } 341 342 kfree(kern_buf); 343 kfree(bnad->regdata); 344 bnad->regdata = NULL; 345 bnad->reglen = 0; 346 347 bnad->regdata = kzalloc(len << 2, GFP_KERNEL); 348 if (!bnad->regdata) 349 return -ENOMEM; 350 351 bnad->reglen = len << 2; 352 rb = bfa_ioc_bar0(ioc); 353 addr &= BFA_REG_ADDRMSK(ioc); 354 355 /* offset and len sanity check */ 356 rc = bna_reg_offset_check(ioc, addr, len); 357 if (rc) { 358 pr_warn("bna %s: Failed reg offset check\n", 359 pci_name(bnad->pcidev)); 360 kfree(bnad->regdata); 361 bnad->regdata = NULL; 362 bnad->reglen = 0; 363 return -EINVAL; 364 } 365 366 reg_addr = rb + addr; 367 regbuf = (u32 *)bnad->regdata; 368 spin_lock_irqsave(&bnad->bna_lock, flags); 369 for (i = 0; i < len; i++) { 370 *regbuf = readl(reg_addr); 371 regbuf++; 372 reg_addr += sizeof(u32); 373 } 374 spin_unlock_irqrestore(&bnad->bna_lock, flags); 375 376 return nbytes; 377} 378 379static ssize_t 380bnad_debugfs_write_regwr(struct file *file, const char __user *buf, 381 size_t nbytes, loff_t *ppos) 382{ 383 struct bnad_debug_info *debug = file->private_data; 384 struct bnad *bnad = (struct bnad *)debug->i_private; 385 struct bfa_ioc *ioc = &bnad->bna.ioceth.ioc; 386 int addr, val, rc; 387 void __iomem *reg_addr; 388 unsigned long flags; 389 void *kern_buf; 390 391 /* Allocate memory to store the user space buf */ 392 kern_buf = kzalloc(nbytes, GFP_KERNEL); 393 if (!kern_buf) 394 return -ENOMEM; 395 396 if (copy_from_user(kern_buf, (void __user *)buf, nbytes)) { 397 kfree(kern_buf); 398 return -ENOMEM; 399 } 400 401 rc = sscanf(kern_buf, "%x:%x", &addr, &val); 402 if (rc < 2) { 403 pr_warn("bna %s: Failed to read user buffer\n", 404 pci_name(bnad->pcidev)); 405 kfree(kern_buf); 406 return -EINVAL; 407 } 408 kfree(kern_buf); 409 410 addr &= BFA_REG_ADDRMSK(ioc); /* offset only 17 bit and word align */ 411 412 /* offset and len sanity check */ 413 rc = bna_reg_offset_check(ioc, addr, 1); 414 if (rc) { 415 pr_warn("bna %s: Failed reg offset check\n", 416 pci_name(bnad->pcidev)); 417 return -EINVAL; 418 } 419 420 reg_addr = (bfa_ioc_bar0(ioc)) + addr; 421 spin_lock_irqsave(&bnad->bna_lock, flags); 422 writel(val, reg_addr); 423 spin_unlock_irqrestore(&bnad->bna_lock, flags); 424 425 return nbytes; 426} 427 428static int 429bnad_debugfs_release(struct inode *inode, struct file *file) 430{ 431 struct bnad_debug_info *debug = file->private_data; 432 433 if (!debug) 434 return 0; 435 436 file->private_data = NULL; 437 kfree(debug); 438 return 0; 439} 440 441static int 442bnad_debugfs_buffer_release(struct inode *inode, struct file *file) 443{ 444 struct bnad_debug_info *debug = file->private_data; 445 446 if (!debug) 447 return 0; 448 449 kfree(debug->debug_buffer); 450 451 file->private_data = NULL; 452 kfree(debug); 453 debug = NULL; 454 return 0; 455} 456 457static const struct file_operations bnad_debugfs_op_fwtrc = { 458 .owner = THIS_MODULE, 459 .open = bnad_debugfs_open_fwtrc, 460 .llseek = bnad_debugfs_lseek, 461 .read = bnad_debugfs_read, 462 .release = bnad_debugfs_buffer_release, 463}; 464 465static const struct file_operations bnad_debugfs_op_fwsave = { 466 .owner = THIS_MODULE, 467 .open = bnad_debugfs_open_fwsave, 468 .llseek = bnad_debugfs_lseek, 469 .read = bnad_debugfs_read, 470 .release = bnad_debugfs_buffer_release, 471}; 472 473static const struct file_operations bnad_debugfs_op_regrd = { 474 .owner = THIS_MODULE, 475 .open = bnad_debugfs_open_reg, 476 .llseek = bnad_debugfs_lseek, 477 .read = bnad_debugfs_read_regrd, 478 .write = bnad_debugfs_write_regrd, 479 .release = bnad_debugfs_release, 480}; 481 482static const struct file_operations bnad_debugfs_op_regwr = { 483 .owner = THIS_MODULE, 484 .open = bnad_debugfs_open_reg, 485 .llseek = bnad_debugfs_lseek, 486 .write = bnad_debugfs_write_regwr, 487 .release = bnad_debugfs_release, 488}; 489 490static const struct file_operations bnad_debugfs_op_drvinfo = { 491 .owner = THIS_MODULE, 492 .open = bnad_debugfs_open_drvinfo, 493 .llseek = bnad_debugfs_lseek, 494 .read = bnad_debugfs_read, 495 .release = bnad_debugfs_buffer_release, 496}; 497 498struct bnad_debugfs_entry { 499 const char *name; 500 umode_t mode; 501 const struct file_operations *fops; 502}; 503 504static const struct bnad_debugfs_entry bnad_debugfs_files[] = { 505 { "fwtrc", S_IFREG|S_IRUGO, &bnad_debugfs_op_fwtrc, }, 506 { "fwsave", S_IFREG|S_IRUGO, &bnad_debugfs_op_fwsave, }, 507 { "regrd", S_IFREG|S_IRUGO|S_IWUSR, &bnad_debugfs_op_regrd, }, 508 { "regwr", S_IFREG|S_IWUSR, &bnad_debugfs_op_regwr, }, 509 { "drvinfo", S_IFREG|S_IRUGO, &bnad_debugfs_op_drvinfo, }, 510}; 511 512static struct dentry *bna_debugfs_root; 513static atomic_t bna_debugfs_port_count; 514 515/* Initialize debugfs interface for BNA */ 516void 517bnad_debugfs_init(struct bnad *bnad) 518{ 519 const struct bnad_debugfs_entry *file; 520 char name[64]; 521 int i; 522 523 /* Setup the BNA debugfs root directory*/ 524 if (!bna_debugfs_root) { 525 bna_debugfs_root = debugfs_create_dir("bna", NULL); 526 atomic_set(&bna_debugfs_port_count, 0); 527 if (!bna_debugfs_root) { 528 pr_warn("BNA: debugfs root dir creation failed\n"); 529 return; 530 } 531 } 532 533 /* Setup the pci_dev debugfs directory for the port */ 534 snprintf(name, sizeof(name), "pci_dev:%s", pci_name(bnad->pcidev)); 535 if (!bnad->port_debugfs_root) { 536 bnad->port_debugfs_root = 537 debugfs_create_dir(name, bna_debugfs_root); 538 if (!bnad->port_debugfs_root) { 539 pr_warn("bna pci_dev %s: root dir creation failed\n", 540 pci_name(bnad->pcidev)); 541 return; 542 } 543 544 atomic_inc(&bna_debugfs_port_count); 545 546 for (i = 0; i < ARRAY_SIZE(bnad_debugfs_files); i++) { 547 file = &bnad_debugfs_files[i]; 548 bnad->bnad_dentry_files[i] = 549 debugfs_create_file(file->name, 550 file->mode, 551 bnad->port_debugfs_root, 552 bnad, 553 file->fops); 554 if (!bnad->bnad_dentry_files[i]) { 555 pr_warn( 556 "BNA pci_dev:%s: create %s entry failed\n", 557 pci_name(bnad->pcidev), file->name); 558 return; 559 } 560 } 561 } 562} 563 564/* Uninitialize debugfs interface for BNA */ 565void 566bnad_debugfs_uninit(struct bnad *bnad) 567{ 568 int i; 569 570 for (i = 0; i < ARRAY_SIZE(bnad_debugfs_files); i++) { 571 if (bnad->bnad_dentry_files[i]) { 572 debugfs_remove(bnad->bnad_dentry_files[i]); 573 bnad->bnad_dentry_files[i] = NULL; 574 } 575 } 576 577 /* Remove the pci_dev debugfs directory for the port */ 578 if (bnad->port_debugfs_root) { 579 debugfs_remove(bnad->port_debugfs_root); 580 bnad->port_debugfs_root = NULL; 581 atomic_dec(&bna_debugfs_port_count); 582 } 583 584 /* Remove the BNA debugfs root directory */ 585 if (atomic_read(&bna_debugfs_port_count) == 0) { 586 debugfs_remove(bna_debugfs_root); 587 bna_debugfs_root = NULL; 588 } 589} 590