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