1f931551bSRalph Campbell /* 2f931551bSRalph Campbell * Copyright (c) 2006, 2007, 2008, 2009 QLogic Corporation. All rights reserved. 3f931551bSRalph Campbell * Copyright (c) 2006 PathScale, Inc. All rights reserved. 4f931551bSRalph Campbell * 5f931551bSRalph Campbell * This software is available to you under a choice of one of two 6f931551bSRalph Campbell * licenses. You may choose to be licensed under the terms of the GNU 7f931551bSRalph Campbell * General Public License (GPL) Version 2, available from the file 8f931551bSRalph Campbell * COPYING in the main directory of this source tree, or the 9f931551bSRalph Campbell * OpenIB.org BSD license below: 10f931551bSRalph Campbell * 11f931551bSRalph Campbell * Redistribution and use in source and binary forms, with or 12f931551bSRalph Campbell * without modification, are permitted provided that the following 13f931551bSRalph Campbell * conditions are met: 14f931551bSRalph Campbell * 15f931551bSRalph Campbell * - Redistributions of source code must retain the above 16f931551bSRalph Campbell * copyright notice, this list of conditions and the following 17f931551bSRalph Campbell * disclaimer. 18f931551bSRalph Campbell * 19f931551bSRalph Campbell * - Redistributions in binary form must reproduce the above 20f931551bSRalph Campbell * copyright notice, this list of conditions and the following 21f931551bSRalph Campbell * disclaimer in the documentation and/or other materials 22f931551bSRalph Campbell * provided with the distribution. 23f931551bSRalph Campbell * 24f931551bSRalph Campbell * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 25f931551bSRalph Campbell * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 26f931551bSRalph Campbell * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 27f931551bSRalph Campbell * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 28f931551bSRalph Campbell * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 29f931551bSRalph Campbell * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 30f931551bSRalph Campbell * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 31f931551bSRalph Campbell * SOFTWARE. 32f931551bSRalph Campbell */ 33f931551bSRalph Campbell 34f931551bSRalph Campbell #include <linux/module.h> 35f931551bSRalph Campbell #include <linux/fs.h> 36f931551bSRalph Campbell #include <linux/mount.h> 37f931551bSRalph Campbell #include <linux/pagemap.h> 38f931551bSRalph Campbell #include <linux/init.h> 39f931551bSRalph Campbell #include <linux/namei.h> 40f931551bSRalph Campbell 41f931551bSRalph Campbell #include "qib.h" 42f931551bSRalph Campbell 43f931551bSRalph Campbell #define QIBFS_MAGIC 0x726a77 44f931551bSRalph Campbell 45f931551bSRalph Campbell static struct super_block *qib_super; 46f931551bSRalph Campbell 47f931551bSRalph Campbell #define private2dd(file) ((file)->f_dentry->d_inode->i_private) 48f931551bSRalph Campbell 49f931551bSRalph Campbell static int qibfs_mknod(struct inode *dir, struct dentry *dentry, 50f931551bSRalph Campbell int mode, const struct file_operations *fops, 51f931551bSRalph Campbell void *data) 52f931551bSRalph Campbell { 53f931551bSRalph Campbell int error; 54f931551bSRalph Campbell struct inode *inode = new_inode(dir->i_sb); 55f931551bSRalph Campbell 56f931551bSRalph Campbell if (!inode) { 57f931551bSRalph Campbell error = -EPERM; 58f931551bSRalph Campbell goto bail; 59f931551bSRalph Campbell } 60f931551bSRalph Campbell 61f931551bSRalph Campbell inode->i_mode = mode; 62f931551bSRalph Campbell inode->i_uid = 0; 63f931551bSRalph Campbell inode->i_gid = 0; 64f931551bSRalph Campbell inode->i_blocks = 0; 65f931551bSRalph Campbell inode->i_atime = CURRENT_TIME; 66f931551bSRalph Campbell inode->i_mtime = inode->i_atime; 67f931551bSRalph Campbell inode->i_ctime = inode->i_atime; 68f931551bSRalph Campbell inode->i_private = data; 69f931551bSRalph Campbell if ((mode & S_IFMT) == S_IFDIR) { 70f931551bSRalph Campbell inode->i_op = &simple_dir_inode_operations; 71f931551bSRalph Campbell inc_nlink(inode); 72f931551bSRalph Campbell inc_nlink(dir); 73f931551bSRalph Campbell } 74f931551bSRalph Campbell 75f931551bSRalph Campbell inode->i_fop = fops; 76f931551bSRalph Campbell 77f931551bSRalph Campbell d_instantiate(dentry, inode); 78f931551bSRalph Campbell error = 0; 79f931551bSRalph Campbell 80f931551bSRalph Campbell bail: 81f931551bSRalph Campbell return error; 82f931551bSRalph Campbell } 83f931551bSRalph Campbell 84f931551bSRalph Campbell static int create_file(const char *name, mode_t mode, 85f931551bSRalph Campbell struct dentry *parent, struct dentry **dentry, 86f931551bSRalph Campbell const struct file_operations *fops, void *data) 87f931551bSRalph Campbell { 88f931551bSRalph Campbell int error; 89f931551bSRalph Campbell 90f931551bSRalph Campbell *dentry = NULL; 91f931551bSRalph Campbell mutex_lock(&parent->d_inode->i_mutex); 92f931551bSRalph Campbell *dentry = lookup_one_len(name, parent, strlen(name)); 93f931551bSRalph Campbell if (!IS_ERR(*dentry)) 94f931551bSRalph Campbell error = qibfs_mknod(parent->d_inode, *dentry, 95f931551bSRalph Campbell mode, fops, data); 96f931551bSRalph Campbell else 97f931551bSRalph Campbell error = PTR_ERR(*dentry); 98f931551bSRalph Campbell mutex_unlock(&parent->d_inode->i_mutex); 99f931551bSRalph Campbell 100f931551bSRalph Campbell return error; 101f931551bSRalph Campbell } 102f931551bSRalph Campbell 103f931551bSRalph Campbell static ssize_t driver_stats_read(struct file *file, char __user *buf, 104f931551bSRalph Campbell size_t count, loff_t *ppos) 105f931551bSRalph Campbell { 106f931551bSRalph Campbell return simple_read_from_buffer(buf, count, ppos, &qib_stats, 107f931551bSRalph Campbell sizeof qib_stats); 108f931551bSRalph Campbell } 109f931551bSRalph Campbell 110f931551bSRalph Campbell /* 111f931551bSRalph Campbell * driver stats field names, one line per stat, single string. Used by 112f931551bSRalph Campbell * programs like ipathstats to print the stats in a way which works for 113f931551bSRalph Campbell * different versions of drivers, without changing program source. 114f931551bSRalph Campbell * if qlogic_ib_stats changes, this needs to change. Names need to be 115f931551bSRalph Campbell * 12 chars or less (w/o newline), for proper display by ipathstats utility. 116f931551bSRalph Campbell */ 117f931551bSRalph Campbell static const char qib_statnames[] = 118f931551bSRalph Campbell "KernIntr\n" 119f931551bSRalph Campbell "ErrorIntr\n" 120f931551bSRalph Campbell "Tx_Errs\n" 121f931551bSRalph Campbell "Rcv_Errs\n" 122f931551bSRalph Campbell "H/W_Errs\n" 123f931551bSRalph Campbell "NoPIOBufs\n" 124f931551bSRalph Campbell "CtxtsOpen\n" 125f931551bSRalph Campbell "RcvLen_Errs\n" 126f931551bSRalph Campbell "EgrBufFull\n" 127f931551bSRalph Campbell "EgrHdrFull\n" 128f931551bSRalph Campbell ; 129f931551bSRalph Campbell 130f931551bSRalph Campbell static ssize_t driver_names_read(struct file *file, char __user *buf, 131f931551bSRalph Campbell size_t count, loff_t *ppos) 132f931551bSRalph Campbell { 133f931551bSRalph Campbell return simple_read_from_buffer(buf, count, ppos, qib_statnames, 134f931551bSRalph Campbell sizeof qib_statnames - 1); /* no null */ 135f931551bSRalph Campbell } 136f931551bSRalph Campbell 137f931551bSRalph Campbell static const struct file_operations driver_ops[] = { 138f931551bSRalph Campbell { .read = driver_stats_read, }, 139f931551bSRalph Campbell { .read = driver_names_read, }, 140f931551bSRalph Campbell }; 141f931551bSRalph Campbell 142f931551bSRalph Campbell /* read the per-device counters */ 143f931551bSRalph Campbell static ssize_t dev_counters_read(struct file *file, char __user *buf, 144f931551bSRalph Campbell size_t count, loff_t *ppos) 145f931551bSRalph Campbell { 146f931551bSRalph Campbell u64 *counters; 147f931551bSRalph Campbell struct qib_devdata *dd = private2dd(file); 148f931551bSRalph Campbell 149f931551bSRalph Campbell return simple_read_from_buffer(buf, count, ppos, counters, 150f931551bSRalph Campbell dd->f_read_cntrs(dd, *ppos, NULL, &counters)); 151f931551bSRalph Campbell } 152f931551bSRalph Campbell 153f931551bSRalph Campbell /* read the per-device counters */ 154f931551bSRalph Campbell static ssize_t dev_names_read(struct file *file, char __user *buf, 155f931551bSRalph Campbell size_t count, loff_t *ppos) 156f931551bSRalph Campbell { 157f931551bSRalph Campbell char *names; 158f931551bSRalph Campbell struct qib_devdata *dd = private2dd(file); 159f931551bSRalph Campbell 160f931551bSRalph Campbell return simple_read_from_buffer(buf, count, ppos, names, 161f931551bSRalph Campbell dd->f_read_cntrs(dd, *ppos, &names, NULL)); 162f931551bSRalph Campbell } 163f931551bSRalph Campbell 164f931551bSRalph Campbell static const struct file_operations cntr_ops[] = { 165f931551bSRalph Campbell { .read = dev_counters_read, }, 166f931551bSRalph Campbell { .read = dev_names_read, }, 167f931551bSRalph Campbell }; 168f931551bSRalph Campbell 169f931551bSRalph Campbell /* 170f931551bSRalph Campbell * Could use file->f_dentry->d_inode->i_ino to figure out which file, 171f931551bSRalph Campbell * instead of separate routine for each, but for now, this works... 172f931551bSRalph Campbell */ 173f931551bSRalph Campbell 174f931551bSRalph Campbell /* read the per-port names (same for each port) */ 175f931551bSRalph Campbell static ssize_t portnames_read(struct file *file, char __user *buf, 176f931551bSRalph Campbell size_t count, loff_t *ppos) 177f931551bSRalph Campbell { 178f931551bSRalph Campbell char *names; 179f931551bSRalph Campbell struct qib_devdata *dd = private2dd(file); 180f931551bSRalph Campbell 181f931551bSRalph Campbell return simple_read_from_buffer(buf, count, ppos, names, 182f931551bSRalph Campbell dd->f_read_portcntrs(dd, *ppos, 0, &names, NULL)); 183f931551bSRalph Campbell } 184f931551bSRalph Campbell 185f931551bSRalph Campbell /* read the per-port counters for port 1 (pidx 0) */ 186f931551bSRalph Campbell static ssize_t portcntrs_1_read(struct file *file, char __user *buf, 187f931551bSRalph Campbell size_t count, loff_t *ppos) 188f931551bSRalph Campbell { 189f931551bSRalph Campbell u64 *counters; 190f931551bSRalph Campbell struct qib_devdata *dd = private2dd(file); 191f931551bSRalph Campbell 192f931551bSRalph Campbell return simple_read_from_buffer(buf, count, ppos, counters, 193f931551bSRalph Campbell dd->f_read_portcntrs(dd, *ppos, 0, NULL, &counters)); 194f931551bSRalph Campbell } 195f931551bSRalph Campbell 196f931551bSRalph Campbell /* read the per-port counters for port 2 (pidx 1) */ 197f931551bSRalph Campbell static ssize_t portcntrs_2_read(struct file *file, char __user *buf, 198f931551bSRalph Campbell size_t count, loff_t *ppos) 199f931551bSRalph Campbell { 200f931551bSRalph Campbell u64 *counters; 201f931551bSRalph Campbell struct qib_devdata *dd = private2dd(file); 202f931551bSRalph Campbell 203f931551bSRalph Campbell return simple_read_from_buffer(buf, count, ppos, counters, 204f931551bSRalph Campbell dd->f_read_portcntrs(dd, *ppos, 1, NULL, &counters)); 205f931551bSRalph Campbell } 206f931551bSRalph Campbell 207f931551bSRalph Campbell static const struct file_operations portcntr_ops[] = { 208f931551bSRalph Campbell { .read = portnames_read, }, 209f931551bSRalph Campbell { .read = portcntrs_1_read, }, 210f931551bSRalph Campbell { .read = portcntrs_2_read, }, 211f931551bSRalph Campbell }; 212f931551bSRalph Campbell 213f931551bSRalph Campbell /* 214f931551bSRalph Campbell * read the per-port QSFP data for port 1 (pidx 0) 215f931551bSRalph Campbell */ 216f931551bSRalph Campbell static ssize_t qsfp_1_read(struct file *file, char __user *buf, 217f931551bSRalph Campbell size_t count, loff_t *ppos) 218f931551bSRalph Campbell { 219f931551bSRalph Campbell struct qib_devdata *dd = private2dd(file); 220f931551bSRalph Campbell char *tmp; 221f931551bSRalph Campbell int ret; 222f931551bSRalph Campbell 223f931551bSRalph Campbell tmp = kmalloc(PAGE_SIZE, GFP_KERNEL); 224f931551bSRalph Campbell if (!tmp) 225f931551bSRalph Campbell return -ENOMEM; 226f931551bSRalph Campbell 227f931551bSRalph Campbell ret = qib_qsfp_dump(dd->pport, tmp, PAGE_SIZE); 228f931551bSRalph Campbell if (ret > 0) 229f931551bSRalph Campbell ret = simple_read_from_buffer(buf, count, ppos, tmp, ret); 230f931551bSRalph Campbell kfree(tmp); 231f931551bSRalph Campbell return ret; 232f931551bSRalph Campbell } 233f931551bSRalph Campbell 234f931551bSRalph Campbell /* 235f931551bSRalph Campbell * read the per-port QSFP data for port 2 (pidx 1) 236f931551bSRalph Campbell */ 237f931551bSRalph Campbell static ssize_t qsfp_2_read(struct file *file, char __user *buf, 238f931551bSRalph Campbell size_t count, loff_t *ppos) 239f931551bSRalph Campbell { 240f931551bSRalph Campbell struct qib_devdata *dd = private2dd(file); 241f931551bSRalph Campbell char *tmp; 242f931551bSRalph Campbell int ret; 243f931551bSRalph Campbell 244f931551bSRalph Campbell if (dd->num_pports < 2) 245f931551bSRalph Campbell return -ENODEV; 246f931551bSRalph Campbell 247f931551bSRalph Campbell tmp = kmalloc(PAGE_SIZE, GFP_KERNEL); 248f931551bSRalph Campbell if (!tmp) 249f931551bSRalph Campbell return -ENOMEM; 250f931551bSRalph Campbell 251f931551bSRalph Campbell ret = qib_qsfp_dump(dd->pport + 1, tmp, PAGE_SIZE); 252f931551bSRalph Campbell if (ret > 0) 253f931551bSRalph Campbell ret = simple_read_from_buffer(buf, count, ppos, tmp, ret); 254f931551bSRalph Campbell kfree(tmp); 255f931551bSRalph Campbell return ret; 256f931551bSRalph Campbell } 257f931551bSRalph Campbell 258f931551bSRalph Campbell static const struct file_operations qsfp_ops[] = { 259f931551bSRalph Campbell { .read = qsfp_1_read, }, 260f931551bSRalph Campbell { .read = qsfp_2_read, }, 261f931551bSRalph Campbell }; 262f931551bSRalph Campbell 263f931551bSRalph Campbell static ssize_t flash_read(struct file *file, char __user *buf, 264f931551bSRalph Campbell size_t count, loff_t *ppos) 265f931551bSRalph Campbell { 266f931551bSRalph Campbell struct qib_devdata *dd; 267f931551bSRalph Campbell ssize_t ret; 268f931551bSRalph Campbell loff_t pos; 269f931551bSRalph Campbell char *tmp; 270f931551bSRalph Campbell 271f931551bSRalph Campbell pos = *ppos; 272f931551bSRalph Campbell 273f931551bSRalph Campbell if (pos < 0) { 274f931551bSRalph Campbell ret = -EINVAL; 275f931551bSRalph Campbell goto bail; 276f931551bSRalph Campbell } 277f931551bSRalph Campbell 278f931551bSRalph Campbell if (pos >= sizeof(struct qib_flash)) { 279f931551bSRalph Campbell ret = 0; 280f931551bSRalph Campbell goto bail; 281f931551bSRalph Campbell } 282f931551bSRalph Campbell 283f931551bSRalph Campbell if (count > sizeof(struct qib_flash) - pos) 284f931551bSRalph Campbell count = sizeof(struct qib_flash) - pos; 285f931551bSRalph Campbell 286f931551bSRalph Campbell tmp = kmalloc(count, GFP_KERNEL); 287f931551bSRalph Campbell if (!tmp) { 288f931551bSRalph Campbell ret = -ENOMEM; 289f931551bSRalph Campbell goto bail; 290f931551bSRalph Campbell } 291f931551bSRalph Campbell 292f931551bSRalph Campbell dd = private2dd(file); 293f931551bSRalph Campbell if (qib_eeprom_read(dd, pos, tmp, count)) { 294f931551bSRalph Campbell qib_dev_err(dd, "failed to read from flash\n"); 295f931551bSRalph Campbell ret = -ENXIO; 296f931551bSRalph Campbell goto bail_tmp; 297f931551bSRalph Campbell } 298f931551bSRalph Campbell 299f931551bSRalph Campbell if (copy_to_user(buf, tmp, count)) { 300f931551bSRalph Campbell ret = -EFAULT; 301f931551bSRalph Campbell goto bail_tmp; 302f931551bSRalph Campbell } 303f931551bSRalph Campbell 304f931551bSRalph Campbell *ppos = pos + count; 305f931551bSRalph Campbell ret = count; 306f931551bSRalph Campbell 307f931551bSRalph Campbell bail_tmp: 308f931551bSRalph Campbell kfree(tmp); 309f931551bSRalph Campbell 310f931551bSRalph Campbell bail: 311f931551bSRalph Campbell return ret; 312f931551bSRalph Campbell } 313f931551bSRalph Campbell 314f931551bSRalph Campbell static ssize_t flash_write(struct file *file, const char __user *buf, 315f931551bSRalph Campbell size_t count, loff_t *ppos) 316f931551bSRalph Campbell { 317f931551bSRalph Campbell struct qib_devdata *dd; 318f931551bSRalph Campbell ssize_t ret; 319f931551bSRalph Campbell loff_t pos; 320f931551bSRalph Campbell char *tmp; 321f931551bSRalph Campbell 322f931551bSRalph Campbell pos = *ppos; 323f931551bSRalph Campbell 324f931551bSRalph Campbell if (pos != 0) { 325f931551bSRalph Campbell ret = -EINVAL; 326f931551bSRalph Campbell goto bail; 327f931551bSRalph Campbell } 328f931551bSRalph Campbell 329f931551bSRalph Campbell if (count != sizeof(struct qib_flash)) { 330f931551bSRalph Campbell ret = -EINVAL; 331f931551bSRalph Campbell goto bail; 332f931551bSRalph Campbell } 333f931551bSRalph Campbell 334f931551bSRalph Campbell tmp = kmalloc(count, GFP_KERNEL); 335f931551bSRalph Campbell if (!tmp) { 336f931551bSRalph Campbell ret = -ENOMEM; 337f931551bSRalph Campbell goto bail; 338f931551bSRalph Campbell } 339f931551bSRalph Campbell 340f931551bSRalph Campbell if (copy_from_user(tmp, buf, count)) { 341f931551bSRalph Campbell ret = -EFAULT; 342f931551bSRalph Campbell goto bail_tmp; 343f931551bSRalph Campbell } 344f931551bSRalph Campbell 345f931551bSRalph Campbell dd = private2dd(file); 346f931551bSRalph Campbell if (qib_eeprom_write(dd, pos, tmp, count)) { 347f931551bSRalph Campbell ret = -ENXIO; 348f931551bSRalph Campbell qib_dev_err(dd, "failed to write to flash\n"); 349f931551bSRalph Campbell goto bail_tmp; 350f931551bSRalph Campbell } 351f931551bSRalph Campbell 352f931551bSRalph Campbell *ppos = pos + count; 353f931551bSRalph Campbell ret = count; 354f931551bSRalph Campbell 355f931551bSRalph Campbell bail_tmp: 356f931551bSRalph Campbell kfree(tmp); 357f931551bSRalph Campbell 358f931551bSRalph Campbell bail: 359f931551bSRalph Campbell return ret; 360f931551bSRalph Campbell } 361f931551bSRalph Campbell 362f931551bSRalph Campbell static const struct file_operations flash_ops = { 363f931551bSRalph Campbell .read = flash_read, 364f931551bSRalph Campbell .write = flash_write, 365f931551bSRalph Campbell }; 366f931551bSRalph Campbell 367f931551bSRalph Campbell static int add_cntr_files(struct super_block *sb, struct qib_devdata *dd) 368f931551bSRalph Campbell { 369f931551bSRalph Campbell struct dentry *dir, *tmp; 370f931551bSRalph Campbell char unit[10]; 371f931551bSRalph Campbell int ret, i; 372f931551bSRalph Campbell 373f931551bSRalph Campbell /* create the per-unit directory */ 374f931551bSRalph Campbell snprintf(unit, sizeof unit, "%u", dd->unit); 375f931551bSRalph Campbell ret = create_file(unit, S_IFDIR|S_IRUGO|S_IXUGO, sb->s_root, &dir, 376f931551bSRalph Campbell &simple_dir_operations, dd); 377f931551bSRalph Campbell if (ret) { 378f931551bSRalph Campbell printk(KERN_ERR "create_file(%s) failed: %d\n", unit, ret); 379f931551bSRalph Campbell goto bail; 380f931551bSRalph Campbell } 381f931551bSRalph Campbell 382f931551bSRalph Campbell /* create the files in the new directory */ 383f931551bSRalph Campbell ret = create_file("counters", S_IFREG|S_IRUGO, dir, &tmp, 384f931551bSRalph Campbell &cntr_ops[0], dd); 385f931551bSRalph Campbell if (ret) { 386f931551bSRalph Campbell printk(KERN_ERR "create_file(%s/counters) failed: %d\n", 387f931551bSRalph Campbell unit, ret); 388f931551bSRalph Campbell goto bail; 389f931551bSRalph Campbell } 390f931551bSRalph Campbell ret = create_file("counter_names", S_IFREG|S_IRUGO, dir, &tmp, 391f931551bSRalph Campbell &cntr_ops[1], dd); 392f931551bSRalph Campbell if (ret) { 393f931551bSRalph Campbell printk(KERN_ERR "create_file(%s/counter_names) failed: %d\n", 394f931551bSRalph Campbell unit, ret); 395f931551bSRalph Campbell goto bail; 396f931551bSRalph Campbell } 397f931551bSRalph Campbell ret = create_file("portcounter_names", S_IFREG|S_IRUGO, dir, &tmp, 398f931551bSRalph Campbell &portcntr_ops[0], dd); 399f931551bSRalph Campbell if (ret) { 400f931551bSRalph Campbell printk(KERN_ERR "create_file(%s/%s) failed: %d\n", 401f931551bSRalph Campbell unit, "portcounter_names", ret); 402f931551bSRalph Campbell goto bail; 403f931551bSRalph Campbell } 404f931551bSRalph Campbell for (i = 1; i <= dd->num_pports; i++) { 405f931551bSRalph Campbell char fname[24]; 406f931551bSRalph Campbell 407f931551bSRalph Campbell sprintf(fname, "port%dcounters", i); 408f931551bSRalph Campbell /* create the files in the new directory */ 409f931551bSRalph Campbell ret = create_file(fname, S_IFREG|S_IRUGO, dir, &tmp, 410f931551bSRalph Campbell &portcntr_ops[i], dd); 411f931551bSRalph Campbell if (ret) { 412f931551bSRalph Campbell printk(KERN_ERR "create_file(%s/%s) failed: %d\n", 413f931551bSRalph Campbell unit, fname, ret); 414f931551bSRalph Campbell goto bail; 415f931551bSRalph Campbell } 416f931551bSRalph Campbell if (!(dd->flags & QIB_HAS_QSFP)) 417f931551bSRalph Campbell continue; 418f931551bSRalph Campbell sprintf(fname, "qsfp%d", i); 419f931551bSRalph Campbell ret = create_file(fname, S_IFREG|S_IRUGO, dir, &tmp, 420f931551bSRalph Campbell &qsfp_ops[i - 1], dd); 421f931551bSRalph Campbell if (ret) { 422f931551bSRalph Campbell printk(KERN_ERR "create_file(%s/%s) failed: %d\n", 423f931551bSRalph Campbell unit, fname, ret); 424f931551bSRalph Campbell goto bail; 425f931551bSRalph Campbell } 426f931551bSRalph Campbell } 427f931551bSRalph Campbell 428f931551bSRalph Campbell ret = create_file("flash", S_IFREG|S_IWUSR|S_IRUGO, dir, &tmp, 429f931551bSRalph Campbell &flash_ops, dd); 430f931551bSRalph Campbell if (ret) 431f931551bSRalph Campbell printk(KERN_ERR "create_file(%s/flash) failed: %d\n", 432f931551bSRalph Campbell unit, ret); 433f931551bSRalph Campbell bail: 434f931551bSRalph Campbell return ret; 435f931551bSRalph Campbell } 436f931551bSRalph Campbell 437f931551bSRalph Campbell static int remove_file(struct dentry *parent, char *name) 438f931551bSRalph Campbell { 439f931551bSRalph Campbell struct dentry *tmp; 440f931551bSRalph Campbell int ret; 441f931551bSRalph Campbell 442f931551bSRalph Campbell tmp = lookup_one_len(name, parent, strlen(name)); 443f931551bSRalph Campbell 444f931551bSRalph Campbell if (IS_ERR(tmp)) { 445f931551bSRalph Campbell ret = PTR_ERR(tmp); 446f931551bSRalph Campbell goto bail; 447f931551bSRalph Campbell } 448f931551bSRalph Campbell 449f931551bSRalph Campbell spin_lock(&dcache_lock); 450f931551bSRalph Campbell spin_lock(&tmp->d_lock); 451f931551bSRalph Campbell if (!(d_unhashed(tmp) && tmp->d_inode)) { 452f931551bSRalph Campbell dget_locked(tmp); 453f931551bSRalph Campbell __d_drop(tmp); 454f931551bSRalph Campbell spin_unlock(&tmp->d_lock); 455f931551bSRalph Campbell spin_unlock(&dcache_lock); 456f931551bSRalph Campbell simple_unlink(parent->d_inode, tmp); 457f931551bSRalph Campbell } else { 458f931551bSRalph Campbell spin_unlock(&tmp->d_lock); 459f931551bSRalph Campbell spin_unlock(&dcache_lock); 460f931551bSRalph Campbell } 461f931551bSRalph Campbell 462f931551bSRalph Campbell ret = 0; 463f931551bSRalph Campbell bail: 464f931551bSRalph Campbell /* 465f931551bSRalph Campbell * We don't expect clients to care about the return value, but 466f931551bSRalph Campbell * it's there if they need it. 467f931551bSRalph Campbell */ 468f931551bSRalph Campbell return ret; 469f931551bSRalph Campbell } 470f931551bSRalph Campbell 471f931551bSRalph Campbell static int remove_device_files(struct super_block *sb, 472f931551bSRalph Campbell struct qib_devdata *dd) 473f931551bSRalph Campbell { 474f931551bSRalph Campbell struct dentry *dir, *root; 475f931551bSRalph Campbell char unit[10]; 476f931551bSRalph Campbell int ret, i; 477f931551bSRalph Campbell 478f931551bSRalph Campbell root = dget(sb->s_root); 479f931551bSRalph Campbell mutex_lock(&root->d_inode->i_mutex); 480f931551bSRalph Campbell snprintf(unit, sizeof unit, "%u", dd->unit); 481f931551bSRalph Campbell dir = lookup_one_len(unit, root, strlen(unit)); 482f931551bSRalph Campbell 483f931551bSRalph Campbell if (IS_ERR(dir)) { 484f931551bSRalph Campbell ret = PTR_ERR(dir); 485f931551bSRalph Campbell printk(KERN_ERR "Lookup of %s failed\n", unit); 486f931551bSRalph Campbell goto bail; 487f931551bSRalph Campbell } 488f931551bSRalph Campbell 489f931551bSRalph Campbell remove_file(dir, "counters"); 490f931551bSRalph Campbell remove_file(dir, "counter_names"); 491f931551bSRalph Campbell remove_file(dir, "portcounter_names"); 492f931551bSRalph Campbell for (i = 0; i < dd->num_pports; i++) { 493f931551bSRalph Campbell char fname[24]; 494f931551bSRalph Campbell 495f931551bSRalph Campbell sprintf(fname, "port%dcounters", i + 1); 496f931551bSRalph Campbell remove_file(dir, fname); 497f931551bSRalph Campbell if (dd->flags & QIB_HAS_QSFP) { 498f931551bSRalph Campbell sprintf(fname, "qsfp%d", i + 1); 499f931551bSRalph Campbell remove_file(dir, fname); 500f931551bSRalph Campbell } 501f931551bSRalph Campbell } 502f931551bSRalph Campbell remove_file(dir, "flash"); 503f931551bSRalph Campbell d_delete(dir); 504f931551bSRalph Campbell ret = simple_rmdir(root->d_inode, dir); 505f931551bSRalph Campbell 506f931551bSRalph Campbell bail: 507f931551bSRalph Campbell mutex_unlock(&root->d_inode->i_mutex); 508f931551bSRalph Campbell dput(root); 509f931551bSRalph Campbell return ret; 510f931551bSRalph Campbell } 511f931551bSRalph Campbell 512f931551bSRalph Campbell /* 513f931551bSRalph Campbell * This fills everything in when the fs is mounted, to handle umount/mount 514f931551bSRalph Campbell * after device init. The direct add_cntr_files() call handles adding 515f931551bSRalph Campbell * them from the init code, when the fs is already mounted. 516f931551bSRalph Campbell */ 517f931551bSRalph Campbell static int qibfs_fill_super(struct super_block *sb, void *data, int silent) 518f931551bSRalph Campbell { 519f931551bSRalph Campbell struct qib_devdata *dd, *tmp; 520f931551bSRalph Campbell unsigned long flags; 521f931551bSRalph Campbell int ret; 522f931551bSRalph Campbell 523f931551bSRalph Campbell static struct tree_descr files[] = { 524f931551bSRalph Campbell [2] = {"driver_stats", &driver_ops[0], S_IRUGO}, 525f931551bSRalph Campbell [3] = {"driver_stats_names", &driver_ops[1], S_IRUGO}, 526f931551bSRalph Campbell {""}, 527f931551bSRalph Campbell }; 528f931551bSRalph Campbell 529f931551bSRalph Campbell ret = simple_fill_super(sb, QIBFS_MAGIC, files); 530f931551bSRalph Campbell if (ret) { 531f931551bSRalph Campbell printk(KERN_ERR "simple_fill_super failed: %d\n", ret); 532f931551bSRalph Campbell goto bail; 533f931551bSRalph Campbell } 534f931551bSRalph Campbell 535f931551bSRalph Campbell spin_lock_irqsave(&qib_devs_lock, flags); 536f931551bSRalph Campbell 537f931551bSRalph Campbell list_for_each_entry_safe(dd, tmp, &qib_dev_list, list) { 538f931551bSRalph Campbell spin_unlock_irqrestore(&qib_devs_lock, flags); 539f931551bSRalph Campbell ret = add_cntr_files(sb, dd); 540f931551bSRalph Campbell if (ret) { 541f931551bSRalph Campbell deactivate_super(sb); 542f931551bSRalph Campbell goto bail; 543f931551bSRalph Campbell } 544f931551bSRalph Campbell spin_lock_irqsave(&qib_devs_lock, flags); 545f931551bSRalph Campbell } 546f931551bSRalph Campbell 547f931551bSRalph Campbell spin_unlock_irqrestore(&qib_devs_lock, flags); 548f931551bSRalph Campbell 549f931551bSRalph Campbell bail: 550f931551bSRalph Campbell return ret; 551f931551bSRalph Campbell } 552f931551bSRalph Campbell 553f931551bSRalph Campbell static int qibfs_get_sb(struct file_system_type *fs_type, int flags, 554f931551bSRalph Campbell const char *dev_name, void *data, struct vfsmount *mnt) 555f931551bSRalph Campbell { 556f931551bSRalph Campbell int ret = get_sb_single(fs_type, flags, data, 557f931551bSRalph Campbell qibfs_fill_super, mnt); 558f931551bSRalph Campbell if (ret >= 0) 559f931551bSRalph Campbell qib_super = mnt->mnt_sb; 560f931551bSRalph Campbell return ret; 561f931551bSRalph Campbell } 562f931551bSRalph Campbell 563f931551bSRalph Campbell static void qibfs_kill_super(struct super_block *s) 564f931551bSRalph Campbell { 565f931551bSRalph Campbell kill_litter_super(s); 566f931551bSRalph Campbell qib_super = NULL; 567f931551bSRalph Campbell } 568f931551bSRalph Campbell 569f931551bSRalph Campbell int qibfs_add(struct qib_devdata *dd) 570f931551bSRalph Campbell { 571f931551bSRalph Campbell int ret; 572f931551bSRalph Campbell 573f931551bSRalph Campbell /* 574f931551bSRalph Campbell * On first unit initialized, qib_super will not yet exist 575f931551bSRalph Campbell * because nobody has yet tried to mount the filesystem, so 576f931551bSRalph Campbell * we can't consider that to be an error; if an error occurs 577f931551bSRalph Campbell * during the mount, that will get a complaint, so this is OK. 578f931551bSRalph Campbell * add_cntr_files() for all units is done at mount from 579f931551bSRalph Campbell * qibfs_fill_super(), so one way or another, everything works. 580f931551bSRalph Campbell */ 581f931551bSRalph Campbell if (qib_super == NULL) 582f931551bSRalph Campbell ret = 0; 583f931551bSRalph Campbell else 584f931551bSRalph Campbell ret = add_cntr_files(qib_super, dd); 585f931551bSRalph Campbell return ret; 586f931551bSRalph Campbell } 587f931551bSRalph Campbell 588f931551bSRalph Campbell int qibfs_remove(struct qib_devdata *dd) 589f931551bSRalph Campbell { 590f931551bSRalph Campbell int ret = 0; 591f931551bSRalph Campbell 592f931551bSRalph Campbell if (qib_super) 593f931551bSRalph Campbell ret = remove_device_files(qib_super, dd); 594f931551bSRalph Campbell 595f931551bSRalph Campbell return ret; 596f931551bSRalph Campbell } 597f931551bSRalph Campbell 598f931551bSRalph Campbell static struct file_system_type qibfs_fs_type = { 599f931551bSRalph Campbell .owner = THIS_MODULE, 600f931551bSRalph Campbell .name = "ipathfs", 601f931551bSRalph Campbell .get_sb = qibfs_get_sb, 602f931551bSRalph Campbell .kill_sb = qibfs_kill_super, 603f931551bSRalph Campbell }; 604f931551bSRalph Campbell 605f931551bSRalph Campbell int __init qib_init_qibfs(void) 606f931551bSRalph Campbell { 607f931551bSRalph Campbell return register_filesystem(&qibfs_fs_type); 608f931551bSRalph Campbell } 609f931551bSRalph Campbell 610f931551bSRalph Campbell int __exit qib_exit_qibfs(void) 611f931551bSRalph Campbell { 612f931551bSRalph Campbell return unregister_filesystem(&qibfs_fs_type); 613f931551bSRalph Campbell } 614