0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012 #include <linux/debugfs.h>
0013 #include <linux/module.h>
0014 #include "bnad.h"
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034 struct bnad_debug_info {
0035 char *debug_buffer;
0036 void *i_private;
0037 int buffer_len;
0038 };
0039
0040 static int
0041 bnad_debugfs_open_fwtrc(struct inode *inode, struct file *file)
0042 {
0043 struct bnad *bnad = inode->i_private;
0044 struct bnad_debug_info *fw_debug;
0045 unsigned long flags;
0046 int rc;
0047
0048 fw_debug = kzalloc(sizeof(struct bnad_debug_info), GFP_KERNEL);
0049 if (!fw_debug)
0050 return -ENOMEM;
0051
0052 fw_debug->buffer_len = BNA_DBG_FWTRC_LEN;
0053
0054 fw_debug->debug_buffer = kzalloc(fw_debug->buffer_len, GFP_KERNEL);
0055 if (!fw_debug->debug_buffer) {
0056 kfree(fw_debug);
0057 fw_debug = NULL;
0058 return -ENOMEM;
0059 }
0060
0061 spin_lock_irqsave(&bnad->bna_lock, flags);
0062 rc = bfa_nw_ioc_debug_fwtrc(&bnad->bna.ioceth.ioc,
0063 fw_debug->debug_buffer,
0064 &fw_debug->buffer_len);
0065 spin_unlock_irqrestore(&bnad->bna_lock, flags);
0066 if (rc != BFA_STATUS_OK) {
0067 kfree(fw_debug->debug_buffer);
0068 fw_debug->debug_buffer = NULL;
0069 kfree(fw_debug);
0070 fw_debug = NULL;
0071 netdev_warn(bnad->netdev, "failed to collect fwtrc\n");
0072 return -ENOMEM;
0073 }
0074
0075 file->private_data = fw_debug;
0076
0077 return 0;
0078 }
0079
0080 static int
0081 bnad_debugfs_open_fwsave(struct inode *inode, struct file *file)
0082 {
0083 struct bnad *bnad = inode->i_private;
0084 struct bnad_debug_info *fw_debug;
0085 unsigned long flags;
0086 int rc;
0087
0088 fw_debug = kzalloc(sizeof(struct bnad_debug_info), GFP_KERNEL);
0089 if (!fw_debug)
0090 return -ENOMEM;
0091
0092 fw_debug->buffer_len = BNA_DBG_FWTRC_LEN;
0093
0094 fw_debug->debug_buffer = kzalloc(fw_debug->buffer_len, GFP_KERNEL);
0095 if (!fw_debug->debug_buffer) {
0096 kfree(fw_debug);
0097 fw_debug = NULL;
0098 return -ENOMEM;
0099 }
0100
0101 spin_lock_irqsave(&bnad->bna_lock, flags);
0102 rc = bfa_nw_ioc_debug_fwsave(&bnad->bna.ioceth.ioc,
0103 fw_debug->debug_buffer,
0104 &fw_debug->buffer_len);
0105 spin_unlock_irqrestore(&bnad->bna_lock, flags);
0106 if (rc != BFA_STATUS_OK && rc != BFA_STATUS_ENOFSAVE) {
0107 kfree(fw_debug->debug_buffer);
0108 fw_debug->debug_buffer = NULL;
0109 kfree(fw_debug);
0110 fw_debug = NULL;
0111 netdev_warn(bnad->netdev, "failed to collect fwsave\n");
0112 return -ENOMEM;
0113 }
0114
0115 file->private_data = fw_debug;
0116
0117 return 0;
0118 }
0119
0120 static int
0121 bnad_debugfs_open_reg(struct inode *inode, struct file *file)
0122 {
0123 struct bnad_debug_info *reg_debug;
0124
0125 reg_debug = kzalloc(sizeof(struct bnad_debug_info), GFP_KERNEL);
0126 if (!reg_debug)
0127 return -ENOMEM;
0128
0129 reg_debug->i_private = inode->i_private;
0130
0131 file->private_data = reg_debug;
0132
0133 return 0;
0134 }
0135
0136 static int
0137 bnad_get_debug_drvinfo(struct bnad *bnad, void *buffer, u32 len)
0138 {
0139 struct bnad_drvinfo *drvinfo = (struct bnad_drvinfo *) buffer;
0140 struct bnad_iocmd_comp fcomp;
0141 unsigned long flags = 0;
0142 int ret = BFA_STATUS_FAILED;
0143
0144
0145 spin_lock_irqsave(&bnad->bna_lock, flags);
0146 bfa_nw_ioc_get_attr(&bnad->bna.ioceth.ioc, &drvinfo->ioc_attr);
0147 spin_unlock_irqrestore(&bnad->bna_lock, flags);
0148
0149
0150 fcomp.bnad = bnad;
0151 fcomp.comp_status = 0;
0152 init_completion(&fcomp.comp);
0153 spin_lock_irqsave(&bnad->bna_lock, flags);
0154 ret = bfa_nw_cee_get_attr(&bnad->bna.cee, &drvinfo->cee_attr,
0155 bnad_cb_completion, &fcomp);
0156 if (ret != BFA_STATUS_OK) {
0157 spin_unlock_irqrestore(&bnad->bna_lock, flags);
0158 goto out;
0159 }
0160 spin_unlock_irqrestore(&bnad->bna_lock, flags);
0161 wait_for_completion(&fcomp.comp);
0162 drvinfo->cee_status = fcomp.comp_status;
0163
0164
0165 fcomp.comp_status = 0;
0166 reinit_completion(&fcomp.comp);
0167 spin_lock_irqsave(&bnad->bna_lock, flags);
0168 ret = bfa_nw_flash_get_attr(&bnad->bna.flash, &drvinfo->flash_attr,
0169 bnad_cb_completion, &fcomp);
0170 if (ret != BFA_STATUS_OK) {
0171 spin_unlock_irqrestore(&bnad->bna_lock, flags);
0172 goto out;
0173 }
0174 spin_unlock_irqrestore(&bnad->bna_lock, flags);
0175 wait_for_completion(&fcomp.comp);
0176 drvinfo->flash_status = fcomp.comp_status;
0177 out:
0178 return ret;
0179 }
0180
0181 static int
0182 bnad_debugfs_open_drvinfo(struct inode *inode, struct file *file)
0183 {
0184 struct bnad *bnad = inode->i_private;
0185 struct bnad_debug_info *drv_info;
0186 int rc;
0187
0188 drv_info = kzalloc(sizeof(struct bnad_debug_info), GFP_KERNEL);
0189 if (!drv_info)
0190 return -ENOMEM;
0191
0192 drv_info->buffer_len = sizeof(struct bnad_drvinfo);
0193
0194 drv_info->debug_buffer = kzalloc(drv_info->buffer_len, GFP_KERNEL);
0195 if (!drv_info->debug_buffer) {
0196 kfree(drv_info);
0197 drv_info = NULL;
0198 return -ENOMEM;
0199 }
0200
0201 mutex_lock(&bnad->conf_mutex);
0202 rc = bnad_get_debug_drvinfo(bnad, drv_info->debug_buffer,
0203 drv_info->buffer_len);
0204 mutex_unlock(&bnad->conf_mutex);
0205 if (rc != BFA_STATUS_OK) {
0206 kfree(drv_info->debug_buffer);
0207 drv_info->debug_buffer = NULL;
0208 kfree(drv_info);
0209 drv_info = NULL;
0210 netdev_warn(bnad->netdev, "failed to collect drvinfo\n");
0211 return -ENOMEM;
0212 }
0213
0214 file->private_data = drv_info;
0215
0216 return 0;
0217 }
0218
0219
0220 static loff_t
0221 bnad_debugfs_lseek(struct file *file, loff_t offset, int orig)
0222 {
0223 struct bnad_debug_info *debug = file->private_data;
0224
0225 if (!debug)
0226 return -EINVAL;
0227
0228 return fixed_size_llseek(file, offset, orig, debug->buffer_len);
0229 }
0230
0231 static ssize_t
0232 bnad_debugfs_read(struct file *file, char __user *buf,
0233 size_t nbytes, loff_t *pos)
0234 {
0235 struct bnad_debug_info *debug = file->private_data;
0236
0237 if (!debug || !debug->debug_buffer)
0238 return 0;
0239
0240 return simple_read_from_buffer(buf, nbytes, pos,
0241 debug->debug_buffer, debug->buffer_len);
0242 }
0243
0244 #define BFA_REG_CT_ADDRSZ (0x40000)
0245 #define BFA_REG_CB_ADDRSZ (0x20000)
0246 #define BFA_REG_ADDRSZ(__ioc) \
0247 ((u32)(bfa_asic_id_ctc(bfa_ioc_devid(__ioc)) ? \
0248 BFA_REG_CT_ADDRSZ : BFA_REG_CB_ADDRSZ))
0249 #define BFA_REG_ADDRMSK(__ioc) (BFA_REG_ADDRSZ(__ioc) - 1)
0250
0251
0252
0253
0254 static int
0255 bna_reg_offset_check(struct bfa_ioc *ioc, u32 offset, u32 len)
0256 {
0257 u8 area;
0258
0259
0260 area = (offset >> 15) & 0x7;
0261 if (area == 0) {
0262
0263 if (offset + (len << 2) > 0x8000)
0264 return BFA_STATUS_EINVAL;
0265 } else if (area == 0x1) {
0266
0267 if (offset + (len << 2) > 0x10000)
0268 return BFA_STATUS_EINVAL;
0269 } else {
0270
0271 if (offset + (len << 2) > BFA_REG_ADDRMSK(ioc))
0272 return BFA_STATUS_EINVAL;
0273 }
0274 return BFA_STATUS_OK;
0275 }
0276
0277 static ssize_t
0278 bnad_debugfs_read_regrd(struct file *file, char __user *buf,
0279 size_t nbytes, loff_t *pos)
0280 {
0281 struct bnad_debug_info *regrd_debug = file->private_data;
0282 struct bnad *bnad = (struct bnad *)regrd_debug->i_private;
0283 ssize_t rc;
0284
0285 if (!bnad->regdata)
0286 return 0;
0287
0288 rc = simple_read_from_buffer(buf, nbytes, pos,
0289 bnad->regdata, bnad->reglen);
0290
0291 if ((*pos + nbytes) >= bnad->reglen) {
0292 kfree(bnad->regdata);
0293 bnad->regdata = NULL;
0294 bnad->reglen = 0;
0295 }
0296
0297 return rc;
0298 }
0299
0300 static ssize_t
0301 bnad_debugfs_write_regrd(struct file *file, const char __user *buf,
0302 size_t nbytes, loff_t *ppos)
0303 {
0304 struct bnad_debug_info *regrd_debug = file->private_data;
0305 struct bnad *bnad = (struct bnad *)regrd_debug->i_private;
0306 struct bfa_ioc *ioc = &bnad->bna.ioceth.ioc;
0307 int rc, i;
0308 u32 addr, len;
0309 u32 *regbuf;
0310 void __iomem *rb, *reg_addr;
0311 unsigned long flags;
0312 void *kern_buf;
0313
0314
0315 kern_buf = memdup_user(buf, nbytes);
0316 if (IS_ERR(kern_buf))
0317 return PTR_ERR(kern_buf);
0318
0319 rc = sscanf(kern_buf, "%x:%x", &addr, &len);
0320 if (rc < 2 || len > UINT_MAX >> 2) {
0321 netdev_warn(bnad->netdev, "failed to read user buffer\n");
0322 kfree(kern_buf);
0323 return -EINVAL;
0324 }
0325
0326 kfree(kern_buf);
0327 kfree(bnad->regdata);
0328 bnad->reglen = 0;
0329
0330 bnad->regdata = kzalloc(len << 2, GFP_KERNEL);
0331 if (!bnad->regdata)
0332 return -ENOMEM;
0333
0334 bnad->reglen = len << 2;
0335 rb = bfa_ioc_bar0(ioc);
0336 addr &= BFA_REG_ADDRMSK(ioc);
0337
0338
0339 rc = bna_reg_offset_check(ioc, addr, len);
0340 if (rc) {
0341 netdev_warn(bnad->netdev, "failed reg offset check\n");
0342 kfree(bnad->regdata);
0343 bnad->regdata = NULL;
0344 bnad->reglen = 0;
0345 return -EINVAL;
0346 }
0347
0348 reg_addr = rb + addr;
0349 regbuf = (u32 *)bnad->regdata;
0350 spin_lock_irqsave(&bnad->bna_lock, flags);
0351 for (i = 0; i < len; i++) {
0352 *regbuf = readl(reg_addr);
0353 regbuf++;
0354 reg_addr += sizeof(u32);
0355 }
0356 spin_unlock_irqrestore(&bnad->bna_lock, flags);
0357
0358 return nbytes;
0359 }
0360
0361 static ssize_t
0362 bnad_debugfs_write_regwr(struct file *file, const char __user *buf,
0363 size_t nbytes, loff_t *ppos)
0364 {
0365 struct bnad_debug_info *debug = file->private_data;
0366 struct bnad *bnad = (struct bnad *)debug->i_private;
0367 struct bfa_ioc *ioc = &bnad->bna.ioceth.ioc;
0368 int rc;
0369 u32 addr, val;
0370 void __iomem *reg_addr;
0371 unsigned long flags;
0372 void *kern_buf;
0373
0374
0375 kern_buf = memdup_user(buf, nbytes);
0376 if (IS_ERR(kern_buf))
0377 return PTR_ERR(kern_buf);
0378
0379 rc = sscanf(kern_buf, "%x:%x", &addr, &val);
0380 if (rc < 2) {
0381 netdev_warn(bnad->netdev, "failed to read user buffer\n");
0382 kfree(kern_buf);
0383 return -EINVAL;
0384 }
0385 kfree(kern_buf);
0386
0387 addr &= BFA_REG_ADDRMSK(ioc);
0388
0389
0390 rc = bna_reg_offset_check(ioc, addr, 1);
0391 if (rc) {
0392 netdev_warn(bnad->netdev, "failed reg offset check\n");
0393 return -EINVAL;
0394 }
0395
0396 reg_addr = (bfa_ioc_bar0(ioc)) + addr;
0397 spin_lock_irqsave(&bnad->bna_lock, flags);
0398 writel(val, reg_addr);
0399 spin_unlock_irqrestore(&bnad->bna_lock, flags);
0400
0401 return nbytes;
0402 }
0403
0404 static int
0405 bnad_debugfs_release(struct inode *inode, struct file *file)
0406 {
0407 struct bnad_debug_info *debug = file->private_data;
0408
0409 if (!debug)
0410 return 0;
0411
0412 file->private_data = NULL;
0413 kfree(debug);
0414 return 0;
0415 }
0416
0417 static int
0418 bnad_debugfs_buffer_release(struct inode *inode, struct file *file)
0419 {
0420 struct bnad_debug_info *debug = file->private_data;
0421
0422 if (!debug)
0423 return 0;
0424
0425 kfree(debug->debug_buffer);
0426
0427 file->private_data = NULL;
0428 kfree(debug);
0429 debug = NULL;
0430 return 0;
0431 }
0432
0433 static const struct file_operations bnad_debugfs_op_fwtrc = {
0434 .owner = THIS_MODULE,
0435 .open = bnad_debugfs_open_fwtrc,
0436 .llseek = bnad_debugfs_lseek,
0437 .read = bnad_debugfs_read,
0438 .release = bnad_debugfs_buffer_release,
0439 };
0440
0441 static const struct file_operations bnad_debugfs_op_fwsave = {
0442 .owner = THIS_MODULE,
0443 .open = bnad_debugfs_open_fwsave,
0444 .llseek = bnad_debugfs_lseek,
0445 .read = bnad_debugfs_read,
0446 .release = bnad_debugfs_buffer_release,
0447 };
0448
0449 static const struct file_operations bnad_debugfs_op_regrd = {
0450 .owner = THIS_MODULE,
0451 .open = bnad_debugfs_open_reg,
0452 .llseek = bnad_debugfs_lseek,
0453 .read = bnad_debugfs_read_regrd,
0454 .write = bnad_debugfs_write_regrd,
0455 .release = bnad_debugfs_release,
0456 };
0457
0458 static const struct file_operations bnad_debugfs_op_regwr = {
0459 .owner = THIS_MODULE,
0460 .open = bnad_debugfs_open_reg,
0461 .llseek = bnad_debugfs_lseek,
0462 .write = bnad_debugfs_write_regwr,
0463 .release = bnad_debugfs_release,
0464 };
0465
0466 static const struct file_operations bnad_debugfs_op_drvinfo = {
0467 .owner = THIS_MODULE,
0468 .open = bnad_debugfs_open_drvinfo,
0469 .llseek = bnad_debugfs_lseek,
0470 .read = bnad_debugfs_read,
0471 .release = bnad_debugfs_buffer_release,
0472 };
0473
0474 struct bnad_debugfs_entry {
0475 const char *name;
0476 umode_t mode;
0477 const struct file_operations *fops;
0478 };
0479
0480 static const struct bnad_debugfs_entry bnad_debugfs_files[] = {
0481 { "fwtrc", S_IFREG | 0444, &bnad_debugfs_op_fwtrc, },
0482 { "fwsave", S_IFREG | 0444, &bnad_debugfs_op_fwsave, },
0483 { "regrd", S_IFREG | 0644, &bnad_debugfs_op_regrd, },
0484 { "regwr", S_IFREG | 0200, &bnad_debugfs_op_regwr, },
0485 { "drvinfo", S_IFREG | 0444, &bnad_debugfs_op_drvinfo, },
0486 };
0487
0488 static struct dentry *bna_debugfs_root;
0489 static atomic_t bna_debugfs_port_count;
0490
0491
0492 void
0493 bnad_debugfs_init(struct bnad *bnad)
0494 {
0495 const struct bnad_debugfs_entry *file;
0496 char name[64];
0497 int i;
0498
0499
0500 if (!bna_debugfs_root) {
0501 bna_debugfs_root = debugfs_create_dir("bna", NULL);
0502 atomic_set(&bna_debugfs_port_count, 0);
0503 if (!bna_debugfs_root) {
0504 netdev_warn(bnad->netdev,
0505 "debugfs root dir creation failed\n");
0506 return;
0507 }
0508 }
0509
0510
0511 snprintf(name, sizeof(name), "pci_dev:%s", pci_name(bnad->pcidev));
0512 if (!bnad->port_debugfs_root) {
0513 bnad->port_debugfs_root =
0514 debugfs_create_dir(name, bna_debugfs_root);
0515 if (!bnad->port_debugfs_root) {
0516 netdev_warn(bnad->netdev,
0517 "debugfs root dir creation failed\n");
0518 return;
0519 }
0520
0521 atomic_inc(&bna_debugfs_port_count);
0522
0523 for (i = 0; i < ARRAY_SIZE(bnad_debugfs_files); i++) {
0524 file = &bnad_debugfs_files[i];
0525 bnad->bnad_dentry_files[i] =
0526 debugfs_create_file(file->name,
0527 file->mode,
0528 bnad->port_debugfs_root,
0529 bnad,
0530 file->fops);
0531 if (!bnad->bnad_dentry_files[i]) {
0532 netdev_warn(bnad->netdev,
0533 "create %s entry failed\n",
0534 file->name);
0535 return;
0536 }
0537 }
0538 }
0539 }
0540
0541
0542 void
0543 bnad_debugfs_uninit(struct bnad *bnad)
0544 {
0545 int i;
0546
0547 for (i = 0; i < ARRAY_SIZE(bnad_debugfs_files); i++) {
0548 if (bnad->bnad_dentry_files[i]) {
0549 debugfs_remove(bnad->bnad_dentry_files[i]);
0550 bnad->bnad_dentry_files[i] = NULL;
0551 }
0552 }
0553
0554
0555 if (bnad->port_debugfs_root) {
0556 debugfs_remove(bnad->port_debugfs_root);
0557 bnad->port_debugfs_root = NULL;
0558 atomic_dec(&bna_debugfs_port_count);
0559 }
0560
0561
0562 if (atomic_read(&bna_debugfs_port_count) == 0) {
0563 debugfs_remove(bna_debugfs_root);
0564 bna_debugfs_root = NULL;
0565 }
0566 }