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