ipath_fs.c revision 7dae5bff2e8e4699744e782a6e7605ad18d1240e
13e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan/* 2759d57686dab8169ca68bbf938ce8e965d1e107aBryan O'Sullivan * Copyright (c) 2006 QLogic, Inc. All rights reserved. 33e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan * Copyright (c) 2006 PathScale, Inc. All rights reserved. 43e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan * 53e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan * This software is available to you under a choice of one of two 63e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan * licenses. You may choose to be licensed under the terms of the GNU 73e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan * General Public License (GPL) Version 2, available from the file 83e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan * COPYING in the main directory of this source tree, or the 93e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan * OpenIB.org BSD license below: 103e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan * 113e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan * Redistribution and use in source and binary forms, with or 123e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan * without modification, are permitted provided that the following 133e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan * conditions are met: 143e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan * 153e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan * - Redistributions of source code must retain the above 163e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan * copyright notice, this list of conditions and the following 173e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan * disclaimer. 183e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan * 193e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan * - Redistributions in binary form must reproduce the above 203e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan * copyright notice, this list of conditions and the following 213e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan * disclaimer in the documentation and/or other materials 223e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan * provided with the distribution. 233e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan * 243e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 253e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 263e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 273e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 283e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 293e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 303e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 313e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan * SOFTWARE. 323e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan */ 333e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan 343e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan#include <linux/version.h> 353e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan#include <linux/module.h> 363e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan#include <linux/fs.h> 373e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan#include <linux/mount.h> 383e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan#include <linux/pagemap.h> 393e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan#include <linux/init.h> 403e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan#include <linux/namei.h> 413e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan#include <linux/pci.h> 423e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan 433e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan#include "ipath_kernel.h" 443e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan 453e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan#define IPATHFS_MAGIC 0x726a77 463e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan 473e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivanstatic struct super_block *ipath_super; 483e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan 493e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivanstatic int ipathfs_mknod(struct inode *dir, struct dentry *dentry, 503e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan int mode, struct file_operations *fops, 513e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan void *data) 523e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan{ 533e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan int error; 543e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan struct inode *inode = new_inode(dir->i_sb); 553e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan 563e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan if (!inode) { 573e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan error = -EPERM; 583e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan goto bail; 593e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan } 603e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan 613e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan inode->i_mode = mode; 623e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan inode->i_uid = 0; 633e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan inode->i_gid = 0; 643e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan inode->i_blocks = 0; 653e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; 668e18e2941c53416aa219708e7dcad21fb4bd6794Theodore Ts'o inode->i_private = data; 673e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan if ((mode & S_IFMT) == S_IFDIR) { 683e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan inode->i_op = &simple_dir_inode_operations; 693e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan inode->i_nlink++; 703e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan dir->i_nlink++; 713e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan } 723e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan 733e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan inode->i_fop = fops; 743e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan 753e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan d_instantiate(dentry, inode); 763e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan error = 0; 773e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan 783e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivanbail: 793e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan return error; 803e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan} 813e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan 823e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivanstatic int create_file(const char *name, mode_t mode, 833e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan struct dentry *parent, struct dentry **dentry, 843e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan struct file_operations *fops, void *data) 853e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan{ 863e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan int error; 873e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan 883e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan *dentry = NULL; 893e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan mutex_lock(&parent->d_inode->i_mutex); 903e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan *dentry = lookup_one_len(name, parent, strlen(name)); 913e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan if (!IS_ERR(dentry)) 923e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan error = ipathfs_mknod(parent->d_inode, *dentry, 933e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan mode, fops, data); 943e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan else 953e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan error = PTR_ERR(dentry); 963e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan mutex_unlock(&parent->d_inode->i_mutex); 973e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan 983e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan return error; 993e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan} 1003e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan 1013e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivanstatic ssize_t atomic_stats_read(struct file *file, char __user *buf, 1023e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan size_t count, loff_t *ppos) 1033e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan{ 1043e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan return simple_read_from_buffer(buf, count, ppos, &ipath_stats, 1053e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan sizeof ipath_stats); 1063e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan} 1073e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan 1083e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivanstatic struct file_operations atomic_stats_ops = { 1093e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan .read = atomic_stats_read, 1103e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan}; 1113e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan 1123e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan#define NUM_COUNTERS sizeof(struct infinipath_counters) / sizeof(u64) 1133e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan 1143e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivanstatic ssize_t atomic_counters_read(struct file *file, char __user *buf, 1153e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan size_t count, loff_t *ppos) 1163e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan{ 1173e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan u64 counters[NUM_COUNTERS]; 1183e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan u16 i; 1193e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan struct ipath_devdata *dd; 1203e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan 1218e18e2941c53416aa219708e7dcad21fb4bd6794Theodore Ts'o dd = file->f_dentry->d_inode->i_private; 1223e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan 1233e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan for (i = 0; i < NUM_COUNTERS; i++) 1243e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan counters[i] = ipath_snap_cntr(dd, i); 1253e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan 1263e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan return simple_read_from_buffer(buf, count, ppos, counters, 1273e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan sizeof counters); 1283e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan} 1293e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan 1303e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivanstatic struct file_operations atomic_counters_ops = { 1313e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan .read = atomic_counters_read, 1323e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan}; 1333e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan 1343e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivanstatic ssize_t atomic_node_info_read(struct file *file, char __user *buf, 1353e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan size_t count, loff_t *ppos) 1363e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan{ 1373e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan u32 nodeinfo[10]; 1383e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan struct ipath_devdata *dd; 1393e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan u64 guid; 1403e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan 1418e18e2941c53416aa219708e7dcad21fb4bd6794Theodore Ts'o dd = file->f_dentry->d_inode->i_private; 1423e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan 1433e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan guid = be64_to_cpu(dd->ipath_guid); 1443e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan 1453e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan nodeinfo[0] = /* BaseVersion is SMA */ 1463e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan /* ClassVersion is SMA */ 1473e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan (1 << 8) /* NodeType */ 1483e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan | (1 << 0); /* NumPorts */ 1493e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan nodeinfo[1] = (u32) (guid >> 32); 1503e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan nodeinfo[2] = (u32) (guid & 0xffffffff); 1513e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan /* PortGUID == SystemImageGUID for us */ 1523e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan nodeinfo[3] = nodeinfo[1]; 1533e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan /* PortGUID == SystemImageGUID for us */ 1543e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan nodeinfo[4] = nodeinfo[2]; 1553e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan /* PortGUID == NodeGUID for us */ 1563e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan nodeinfo[5] = nodeinfo[3]; 1573e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan /* PortGUID == NodeGUID for us */ 1583e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan nodeinfo[6] = nodeinfo[4]; 1593e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan nodeinfo[7] = (4 << 16) /* we support 4 pkeys */ 1603e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan | (dd->ipath_deviceid << 0); 1613e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan /* our chip version as 16 bits major, 16 bits minor */ 1623e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan nodeinfo[8] = dd->ipath_minrev | (dd->ipath_majrev << 16); 1633e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan nodeinfo[9] = (dd->ipath_unit << 24) | (dd->ipath_vendorid << 0); 1643e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan 1653e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan return simple_read_from_buffer(buf, count, ppos, nodeinfo, 1663e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan sizeof nodeinfo); 1673e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan} 1683e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan 1693e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivanstatic struct file_operations atomic_node_info_ops = { 1703e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan .read = atomic_node_info_read, 1713e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan}; 1723e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan 1733e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivanstatic ssize_t atomic_port_info_read(struct file *file, char __user *buf, 1743e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan size_t count, loff_t *ppos) 1753e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan{ 1763e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan u32 portinfo[13]; 1773e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan u32 tmp, tmp2; 1783e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan struct ipath_devdata *dd; 1793e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan 1808e18e2941c53416aa219708e7dcad21fb4bd6794Theodore Ts'o dd = file->f_dentry->d_inode->i_private; 1813e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan 1823e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan /* so we only initialize non-zero fields. */ 1833e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan memset(portinfo, 0, sizeof portinfo); 1843e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan 1853e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan /* 1863e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan * Notimpl yet M_Key (64) 1873e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan * Notimpl yet GID (64) 1883e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan */ 1893e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan 1903e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan portinfo[4] = (dd->ipath_lid << 16); 1913e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan 1923e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan /* 1930fd41363e0785247b7c19127318abc8b5eacc86bBryan O'Sullivan * Notimpl yet SMLID. 1940fd41363e0785247b7c19127318abc8b5eacc86bBryan O'Sullivan * CapabilityMask is 0, we don't support any of these 1953e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan * DiagCode is 0; we don't store any diag info for now Notimpl yet 1963e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan * M_KeyLeasePeriod (we don't support M_Key) 1973e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan */ 1983e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan 1993e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan /* LocalPortNum is whichever port number they ask for */ 2003e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan portinfo[7] = (dd->ipath_unit << 24) 2013e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan /* LinkWidthEnabled */ 2023e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan | (2 << 16) 2033e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan /* LinkWidthSupported (really 2, but not IB valid) */ 2043e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan | (3 << 8) 2053e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan /* LinkWidthActive */ 2063e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan | (2 << 0); 2073e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan tmp = dd->ipath_lastibcstat & IPATH_IBSTATE_MASK; 2083e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan tmp2 = 5; 2093e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan if (tmp == IPATH_IBSTATE_INIT) 2103e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan tmp = 2; 2113e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan else if (tmp == IPATH_IBSTATE_ARM) 2123e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan tmp = 3; 2133e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan else if (tmp == IPATH_IBSTATE_ACTIVE) 2143e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan tmp = 4; 2153e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan else { 2163e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan tmp = 0; /* down */ 2173e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan tmp2 = tmp & 0xf; 2183e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan } 2193e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan 2203e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan portinfo[8] = (1 << 28) /* LinkSpeedSupported */ 2213e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan | (tmp << 24) /* PortState */ 2223e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan | (tmp2 << 20) /* PortPhysicalState */ 2233e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan | (2 << 16) 2243e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan 2253e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan /* LinkDownDefaultState */ 2263e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan /* M_KeyProtectBits == 0 */ 2273e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan /* NotImpl yet LMC == 0 (we can support all values) */ 2283e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan | (1 << 4) /* LinkSpeedActive */ 2293e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan | (1 << 0); /* LinkSpeedEnabled */ 2303e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan switch (dd->ipath_ibmtu) { 2313e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan case 4096: 2323e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan tmp = 5; 2333e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan break; 2343e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan case 2048: 2353e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan tmp = 4; 2363e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan break; 2373e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan case 1024: 2383e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan tmp = 3; 2393e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan break; 2403e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan case 512: 2413e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan tmp = 2; 2423e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan break; 2433e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan case 256: 2443e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan tmp = 1; 2453e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan break; 2463e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan default: /* oops, something is wrong */ 2473e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan ipath_dbg("Problem, ipath_ibmtu 0x%x not a valid IB MTU, " 2483e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan "treat as 2048\n", dd->ipath_ibmtu); 2493e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan tmp = 4; 2503e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan break; 2513e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan } 2523e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan portinfo[9] = (tmp << 28) 2533e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan /* NeighborMTU */ 2543e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan /* Notimpl MasterSMSL */ 2553e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan | (1 << 20) 2563e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan 2573e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan /* VLCap */ 2583e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan /* Notimpl InitType (actually, an SMA decision) */ 2593e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan /* VLHighLimit is 0 (only one VL) */ 2603e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan ; /* VLArbitrationHighCap is 0 (only one VL) */ 2613e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan portinfo[10] = /* VLArbitrationLowCap is 0 (only one VL) */ 2623e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan /* InitTypeReply is SMA decision */ 2633e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan (5 << 16) /* MTUCap 4096 */ 2643e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan | (7 << 13) /* VLStallCount */ 2653e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan | (0x1f << 8) /* HOQLife */ 2663e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan | (1 << 4) 2673e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan 2683e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan /* OperationalVLs 0 */ 2693e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan /* PartitionEnforcementInbound */ 2703e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan /* PartitionEnforcementOutbound not enforced */ 2713e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan /* FilterRawinbound not enforced */ 2723e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan ; /* FilterRawOutbound not enforced */ 2733e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan /* M_KeyViolations are not counted by hardware, SMA can count */ 2743e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan tmp = ipath_read_creg32(dd, dd->ipath_cregs->cr_errpkey); 2753e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan /* P_KeyViolations are counted by hardware. */ 2763e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan portinfo[11] = ((tmp & 0xffff) << 0); 2773e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan portinfo[12] = 2783e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan /* Q_KeyViolations are not counted by hardware */ 2793e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan (1 << 8) 2803e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan 2813e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan /* GUIDCap */ 2823e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan /* SubnetTimeOut handled by SMA */ 2833e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan /* RespTimeValue handled by SMA */ 2843e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan ; 2853e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan /* LocalPhyErrors are programmed to max */ 2863e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan portinfo[12] |= (0xf << 20) 2873e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan | (0xf << 16) /* OverRunErrors are programmed to max */ 2883e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan ; 2893e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan 2903e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan return simple_read_from_buffer(buf, count, ppos, portinfo, 2913e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan sizeof portinfo); 2923e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan} 2933e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan 2943e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivanstatic struct file_operations atomic_port_info_ops = { 2953e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan .read = atomic_port_info_read, 2963e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan}; 2973e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan 2983e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivanstatic ssize_t flash_read(struct file *file, char __user *buf, 2993e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan size_t count, loff_t *ppos) 3003e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan{ 3013e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan struct ipath_devdata *dd; 3023e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan ssize_t ret; 3033e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan loff_t pos; 3043e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan char *tmp; 3053e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan 3063e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan pos = *ppos; 3073e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan 3083e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan if ( pos < 0) { 3093e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan ret = -EINVAL; 3103e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan goto bail; 3113e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan } 3123e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan 3133e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan if (pos >= sizeof(struct ipath_flash)) { 3143e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan ret = 0; 3153e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan goto bail; 3163e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan } 3173e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan 3183e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan if (count > sizeof(struct ipath_flash) - pos) 3193e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan count = sizeof(struct ipath_flash) - pos; 3203e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan 3213e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan tmp = kmalloc(count, GFP_KERNEL); 3223e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan if (!tmp) { 3233e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan ret = -ENOMEM; 3243e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan goto bail; 3253e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan } 3263e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan 3278e18e2941c53416aa219708e7dcad21fb4bd6794Theodore Ts'o dd = file->f_dentry->d_inode->i_private; 3283e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan if (ipath_eeprom_read(dd, pos, tmp, count)) { 3293e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan ipath_dev_err(dd, "failed to read from flash\n"); 3303e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan ret = -ENXIO; 3313e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan goto bail_tmp; 3323e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan } 3333e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan 3343e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan if (copy_to_user(buf, tmp, count)) { 3353e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan ret = -EFAULT; 3363e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan goto bail_tmp; 3373e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan } 3383e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan 3393e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan *ppos = pos + count; 3403e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan ret = count; 3413e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan 3423e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivanbail_tmp: 3433e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan kfree(tmp); 3443e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan 3453e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivanbail: 3463e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan return ret; 3473e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan} 3483e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan 3493e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivanstatic ssize_t flash_write(struct file *file, const char __user *buf, 3503e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan size_t count, loff_t *ppos) 3513e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan{ 3523e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan struct ipath_devdata *dd; 3533e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan ssize_t ret; 3543e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan loff_t pos; 3553e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan char *tmp; 3563e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan 3573e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan pos = *ppos; 3583e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan 3597dae5bff2e8e4699744e782a6e7605ad18d1240eBryan O'Sullivan if (pos != 0) { 3603e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan ret = -EINVAL; 3613e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan goto bail; 3623e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan } 3633e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan 3647dae5bff2e8e4699744e782a6e7605ad18d1240eBryan O'Sullivan if (count != sizeof(struct ipath_flash)) { 3657dae5bff2e8e4699744e782a6e7605ad18d1240eBryan O'Sullivan ret = -EINVAL; 3663e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan goto bail; 3673e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan } 3683e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan 3693e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan tmp = kmalloc(count, GFP_KERNEL); 3703e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan if (!tmp) { 3713e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan ret = -ENOMEM; 3723e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan goto bail; 3733e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan } 3743e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan 3753e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan if (copy_from_user(tmp, buf, count)) { 3763e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan ret = -EFAULT; 3773e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan goto bail_tmp; 3783e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan } 3793e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan 3808e18e2941c53416aa219708e7dcad21fb4bd6794Theodore Ts'o dd = file->f_dentry->d_inode->i_private; 3813e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan if (ipath_eeprom_write(dd, pos, tmp, count)) { 3823e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan ret = -ENXIO; 3833e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan ipath_dev_err(dd, "failed to write to flash\n"); 3843e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan goto bail_tmp; 3853e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan } 3863e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan 3873e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan *ppos = pos + count; 3883e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan ret = count; 3893e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan 3903e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivanbail_tmp: 3913e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan kfree(tmp); 3923e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan 3933e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivanbail: 3943e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan return ret; 3953e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan} 3963e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan 3973e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivanstatic struct file_operations flash_ops = { 3983e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan .read = flash_read, 3993e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan .write = flash_write, 4003e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan}; 4013e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan 4023e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivanstatic int create_device_files(struct super_block *sb, 4033e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan struct ipath_devdata *dd) 4043e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan{ 4053e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan struct dentry *dir, *tmp; 4063e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan char unit[10]; 4073e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan int ret; 4083e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan 4093e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan snprintf(unit, sizeof unit, "%02d", dd->ipath_unit); 4103e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan ret = create_file(unit, S_IFDIR|S_IRUGO|S_IXUGO, sb->s_root, &dir, 4113e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan (struct file_operations *) &simple_dir_operations, 4123e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan dd); 4133e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan if (ret) { 4143e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan printk(KERN_ERR "create_file(%s) failed: %d\n", unit, ret); 4153e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan goto bail; 4163e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan } 4173e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan 4183e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan ret = create_file("atomic_counters", S_IFREG|S_IRUGO, dir, &tmp, 4193e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan &atomic_counters_ops, dd); 4203e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan if (ret) { 4213e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan printk(KERN_ERR "create_file(%s/atomic_counters) " 4223e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan "failed: %d\n", unit, ret); 4233e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan goto bail; 4243e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan } 4253e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan 4263e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan ret = create_file("node_info", S_IFREG|S_IRUGO, dir, &tmp, 4273e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan &atomic_node_info_ops, dd); 4283e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan if (ret) { 4293e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan printk(KERN_ERR "create_file(%s/node_info) " 4303e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan "failed: %d\n", unit, ret); 4313e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan goto bail; 4323e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan } 4333e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan 4343e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan ret = create_file("port_info", S_IFREG|S_IRUGO, dir, &tmp, 4353e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan &atomic_port_info_ops, dd); 4363e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan if (ret) { 4373e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan printk(KERN_ERR "create_file(%s/port_info) " 4383e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan "failed: %d\n", unit, ret); 4393e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan goto bail; 4403e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan } 4413e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan 4423e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan ret = create_file("flash", S_IFREG|S_IWUSR|S_IRUGO, dir, &tmp, 4433e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan &flash_ops, dd); 4443e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan if (ret) { 4453e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan printk(KERN_ERR "create_file(%s/flash) " 4463e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan "failed: %d\n", unit, ret); 4473e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan goto bail; 4483e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan } 4493e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan 4503e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivanbail: 4513e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan return ret; 4523e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan} 4533e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan 4543e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivanstatic void remove_file(struct dentry *parent, char *name) 4553e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan{ 4563e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan struct dentry *tmp; 4573e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan 4583e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan tmp = lookup_one_len(name, parent, strlen(name)); 4593e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan 4603e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan spin_lock(&dcache_lock); 4613e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan spin_lock(&tmp->d_lock); 4623e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan if (!(d_unhashed(tmp) && tmp->d_inode)) { 4633e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan dget_locked(tmp); 4643e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan __d_drop(tmp); 4653e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan spin_unlock(&tmp->d_lock); 4663e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan spin_unlock(&dcache_lock); 4673e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan simple_unlink(parent->d_inode, tmp); 4683e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan } else { 4693e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan spin_unlock(&tmp->d_lock); 4703e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan spin_unlock(&dcache_lock); 4713e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan } 4723e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan} 4733e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan 4743e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivanstatic int remove_device_files(struct super_block *sb, 4753e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan struct ipath_devdata *dd) 4763e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan{ 4773e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan struct dentry *dir, *root; 4783e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan char unit[10]; 4793e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan int ret; 4803e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan 4813e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan root = dget(sb->s_root); 4823e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan mutex_lock(&root->d_inode->i_mutex); 4833e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan snprintf(unit, sizeof unit, "%02d", dd->ipath_unit); 4843e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan dir = lookup_one_len(unit, root, strlen(unit)); 4853e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan 4863e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan if (IS_ERR(dir)) { 4873e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan ret = PTR_ERR(dir); 4883e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan printk(KERN_ERR "Lookup of %s failed\n", unit); 4893e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan goto bail; 4903e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan } 4913e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan 4923e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan remove_file(dir, "flash"); 4933e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan remove_file(dir, "port_info"); 4943e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan remove_file(dir, "node_info"); 4953e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan remove_file(dir, "atomic_counters"); 4963e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan d_delete(dir); 4973e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan ret = simple_rmdir(root->d_inode, dir); 4983e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan 4993e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivanbail: 5003e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan mutex_unlock(&root->d_inode->i_mutex); 5013e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan dput(root); 5023e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan return ret; 5033e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan} 5043e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan 5053e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivanstatic int ipathfs_fill_super(struct super_block *sb, void *data, 5063e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan int silent) 5073e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan{ 5083e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan struct ipath_devdata *dd, *tmp; 5093e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan unsigned long flags; 5103e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan int ret; 5113e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan 5123e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan static struct tree_descr files[] = { 5133e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan [1] = {"atomic_stats", &atomic_stats_ops, S_IRUGO}, 5143e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan {""}, 5153e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan }; 5163e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan 5173e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan ret = simple_fill_super(sb, IPATHFS_MAGIC, files); 5183e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan if (ret) { 5193e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan printk(KERN_ERR "simple_fill_super failed: %d\n", ret); 5203e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan goto bail; 5213e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan } 5223e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan 5233e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan spin_lock_irqsave(&ipath_devs_lock, flags); 5243e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan 5253e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan list_for_each_entry_safe(dd, tmp, &ipath_dev_list, ipath_list) { 5263e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan spin_unlock_irqrestore(&ipath_devs_lock, flags); 5273e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan ret = create_device_files(sb, dd); 5283e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan if (ret) { 5293e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan deactivate_super(sb); 5303e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan goto bail; 5313e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan } 5323e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan spin_lock_irqsave(&ipath_devs_lock, flags); 5333e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan } 5343e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan 5353e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan spin_unlock_irqrestore(&ipath_devs_lock, flags); 5363e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan 5373e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivanbail: 5383e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan return ret; 5393e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan} 5403e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan 541454e2398be9b9fa30433fccc548db34d19aa9958David Howellsstatic int ipathfs_get_sb(struct file_system_type *fs_type, int flags, 542454e2398be9b9fa30433fccc548db34d19aa9958David Howells const char *dev_name, void *data, struct vfsmount *mnt) 5433e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan{ 544454e2398be9b9fa30433fccc548db34d19aa9958David Howells int ret = get_sb_single(fs_type, flags, data, 545454e2398be9b9fa30433fccc548db34d19aa9958David Howells ipathfs_fill_super, mnt); 546454e2398be9b9fa30433fccc548db34d19aa9958David Howells if (ret >= 0) 547454e2398be9b9fa30433fccc548db34d19aa9958David Howells ipath_super = mnt->mnt_sb; 548454e2398be9b9fa30433fccc548db34d19aa9958David Howells return ret; 5493e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan} 5503e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan 5513e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivanstatic void ipathfs_kill_super(struct super_block *s) 5523e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan{ 5533e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan kill_litter_super(s); 5543e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan ipath_super = NULL; 5553e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan} 5563e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan 5573e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivanint ipathfs_add_device(struct ipath_devdata *dd) 5583e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan{ 5593e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan int ret; 5603e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan 5613e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan if (ipath_super == NULL) { 5623e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan ret = 0; 5633e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan goto bail; 5643e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan } 5653e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan 5663e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan ret = create_device_files(ipath_super, dd); 5673e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan 5683e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivanbail: 5693e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan return ret; 5703e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan} 5713e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan 5723e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivanint ipathfs_remove_device(struct ipath_devdata *dd) 5733e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan{ 5743e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan int ret; 5753e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan 5763e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan if (ipath_super == NULL) { 5773e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan ret = 0; 5783e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan goto bail; 5793e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan } 5803e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan 5813e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan ret = remove_device_files(ipath_super, dd); 5823e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan 5833e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivanbail: 5843e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan return ret; 5853e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan} 5863e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan 5873e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivanstatic struct file_system_type ipathfs_fs_type = { 5883e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan .owner = THIS_MODULE, 5893e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan .name = "ipathfs", 5903e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan .get_sb = ipathfs_get_sb, 5913e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan .kill_sb = ipathfs_kill_super, 5923e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan}; 5933e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan 5943e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivanint __init ipath_init_ipathfs(void) 5953e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan{ 5963e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan return register_filesystem(&ipathfs_fs_type); 5973e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan} 5983e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan 5993e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivanvoid __exit ipath_exit_ipathfs(void) 6003e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan{ 6013e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan unregister_filesystem(&ipathfs_fs_type); 6023e9b4a5eb4ae4936feeea256c0105e078c7702cdBryan O'Sullivan} 603