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