Re: [PATCH] Replace pcihpfs with sysfs.

From: Stanley Wang (stanley.wang@linux.co.intel.com)
Date: Thu Jan 23 2003 - 21:12:38 EST


Hi, Greg
Following is the whole patch generated by bksend.

Thanks,
-Stan

You can import this changeset into BK by piping this whole message to:
'| bk receive [path to repository]' or apply the patch as usual.

===================================================================

ChangeSet@1.957, 2003-01-24 10:03:36+08:00, stanley@manticore.sh.intel.com
  Replace pcihpfs with sysfs

ChangeSet@1.956, 2003-01-16 18:20:34-08:00, torvalds@penguin.transmeta.com
  Linux v2.5.59
  TAG: v2.5.59

 pci_hotplug.h | 9
 pci_hotplug_core.c | 1024 +++++++----------------------------------------------
 2 files changed, 160 insertions(+), 873 deletions(-)

diff -Nru a/drivers/hotplug/pci_hotplug.h b/drivers/hotplug/pci_hotplug.h
--- a/drivers/hotplug/pci_hotplug.h Fri Jan 24 10:04:58 2003
+++ b/drivers/hotplug/pci_hotplug.h Fri Jan 24 10:04:58 2003
@@ -46,8 +46,11 @@
 };
 
 struct hotplug_slot;
-struct hotplug_slot_core;
-
+struct hotplug_slot_attribute {
+ struct attribute attr;
+ ssize_t (*show)(struct hotplug_slot *, char *);
+ ssize_t (*store)(struct hotplug_slot *, const char *, size_t);
+};
 /**
  * struct hotplug_slot_ops -the callbacks that the hotplug pci core can use
  * @owner: The module owner of this structure
@@ -131,7 +134,7 @@
 
         /* Variables below this are for use only by the hotplug pci core. */
         struct list_head slot_list;
- struct hotplug_slot_core *core_priv;
+ struct kobject kobj;
 };
 
 extern int pci_hp_register (struct hotplug_slot *slot);
diff -Nru a/drivers/hotplug/pci_hotplug_core.c b/drivers/hotplug/pci_hotplug_core.c
--- a/drivers/hotplug/pci_hotplug_core.c Fri Jan 24 10:04:58 2003
+++ b/drivers/hotplug/pci_hotplug_core.c Fri Jan 24 10:04:58 2003
@@ -42,6 +42,8 @@
 #include <linux/dnotify.h>
 #include <linux/proc_fs.h>
 #include <asm/uaccess.h>
+#include <linux/kobject.h>
+#include <linux/sysfs.h>
 #include "pci_hotplug.h"
 
 
@@ -67,29 +69,43 @@
 
 //////////////////////////////////////////////////////////////////
 
-/* Random magic number */
-#define PCIHPFS_MAGIC 0x52454541
+static spinlock_t list_lock;
+
+static LIST_HEAD(pci_hotplug_slot_list);
+
+static struct subsystem hotplug_slots_subsys;
+
+static ssize_t hotplug_slot_attr_show(struct kobject *kobj,
+ struct attribute *attr, char *buf)
+{
+ struct hotplug_slot *slot=container_of(kobj,
+ struct hotplug_slot,kobj);
+ struct hotplug_slot_attribute *attribute =
+ container_of(attr, struct hotplug_slot_attribute, attr);
+ return attribute->show ? attribute->show(slot, buf) : 0;
+}
+
+static ssize_t hotplug_slot_attr_store(struct kobject *kobj,
+ struct attribute *attr, const char *buf, size_t len)
+{
+ struct hotplug_slot *slot=container_of(kobj,
+ struct hotplug_slot,kobj);
+ struct hotplug_slot_attribute *attribute =
+ container_of(attr, struct hotplug_slot_attribute, attr);
+ return attribute->store ? attribute->store(slot, buf, len) : 0;
+}
 
-struct hotplug_slot_core {
- struct dentry *dir_dentry;
- struct dentry *power_dentry;
- struct dentry *attention_dentry;
- struct dentry *latch_dentry;
- struct dentry *adapter_dentry;
- struct dentry *test_dentry;
- struct dentry *max_bus_speed_dentry;
- struct dentry *cur_bus_speed_dentry;
+static struct sysfs_ops hotplug_slot_sysfs_ops = {
+ .show = hotplug_slot_attr_show,
+ .store = hotplug_slot_attr_store,
 };
 
-static struct super_operations pcihpfs_ops;
-static struct file_operations default_file_operations;
-static struct inode_operations pcihpfs_dir_inode_operations;
-static struct vfsmount *pcihpfs_mount; /* one of the mounts of our fs for reference counting */
-static int pcihpfs_mount_count; /* times we have mounted our fs */
-static spinlock_t mount_lock; /* protects our mount_count */
-static spinlock_t list_lock;
+static struct kobj_type hotplug_slot_ktype = {
+ .sysfs_ops = &hotplug_slot_sysfs_ops
+};
+
+static decl_subsys(hotplug_slots, &hotplug_slot_ktype);
 
-static LIST_HEAD(pci_hotplug_slot_list);
 
 /* these strings match up with the values in pci_bus_speed */
 static char *pci_bus_speed_strings[] = {
@@ -129,438 +145,6 @@
 static inline void cpci_hotplug_exit(void) { }
 #endif
 
-static struct inode *pcihpfs_get_inode (struct super_block *sb, int mode, dev_t dev)
-{
- struct inode *inode = new_inode(sb);
-
- if (inode) {
- inode->i_mode = mode;
- inode->i_uid = current->fsuid;
- inode->i_gid = current->fsgid;
- inode->i_blksize = PAGE_CACHE_SIZE;
- inode->i_blocks = 0;
- inode->i_rdev = NODEV;
- inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
- switch (mode & S_IFMT) {
- default:
- init_special_inode(inode, mode, dev);
- break;
- case S_IFREG:
- inode->i_fop = &default_file_operations;
- break;
- case S_IFDIR:
- inode->i_op = &pcihpfs_dir_inode_operations;
- inode->i_fop = &simple_dir_operations;
-
- /* directory inodes start off with i_nlink == 2 (for "." entry) */
- inode->i_nlink++;
- break;
- }
- }
- return inode;
-}
-
-/* SMP-safe */
-static int pcihpfs_mknod (struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
-{
- struct inode *inode = pcihpfs_get_inode(dir->i_sb, mode, dev);
- int error = -ENOSPC;
-
- if (inode) {
- d_instantiate(dentry, inode);
- dget(dentry);
- error = 0;
- }
- return error;
-}
-
-static int pcihpfs_mkdir (struct inode *dir, struct dentry *dentry, int mode)
-{
- return pcihpfs_mknod (dir, dentry, mode | S_IFDIR, 0);
-}
-
-static int pcihpfs_create (struct inode *dir, struct dentry *dentry, int mode)
-{
- return pcihpfs_mknod (dir, dentry, mode | S_IFREG, 0);
-}
-
-static inline int pcihpfs_positive (struct dentry *dentry)
-{
- return dentry->d_inode && !d_unhashed(dentry);
-}
-
-static int pcihpfs_empty (struct dentry *dentry)
-{
- struct list_head *list;
-
- spin_lock(&dcache_lock);
-
- list_for_each(list, &dentry->d_subdirs) {
- struct dentry *de = list_entry(list, struct dentry, d_child);
- if (pcihpfs_positive(de)) {
- spin_unlock(&dcache_lock);
- return 0;
- }
- }
-
- spin_unlock(&dcache_lock);
- return 1;
-}
-
-static int pcihpfs_unlink (struct inode *dir, struct dentry *dentry)
-{
- int error = -ENOTEMPTY;
-
- if (pcihpfs_empty(dentry)) {
- struct inode *inode = dentry->d_inode;
-
- lock_kernel();
- inode->i_nlink--;
- unlock_kernel();
- dput(dentry);
- error = 0;
- }
- return error;
-}
-
-#define pcihpfs_rmdir pcihpfs_unlink
-
-/* default file operations */
-static ssize_t default_read_file (struct file *file, char *buf, size_t count, loff_t *ppos)
-{
- dbg ("\n");
- return 0;
-}
-
-static ssize_t default_write_file (struct file *file, const char *buf, size_t count, loff_t *ppos)
-{
- dbg ("\n");
- return count;
-}
-
-static loff_t default_file_lseek (struct file *file, loff_t offset, int orig)
-{
- loff_t retval = -EINVAL;
-
- lock_kernel();
- switch(orig) {
- case 0:
- if (offset > 0) {
- file->f_pos = offset;
- retval = file->f_pos;
- }
- break;
- case 1:
- if ((offset + file->f_pos) > 0) {
- file->f_pos += offset;
- retval = file->f_pos;
- }
- break;
- default:
- break;
- }
- unlock_kernel();
- return retval;
-}
-
-static int default_open (struct inode *inode, struct file *filp)
-{
- if (inode->u.generic_ip)
- filp->private_data = inode->u.generic_ip;
-
- return 0;
-}
-
-static struct file_operations default_file_operations = {
- .read = default_read_file,
- .write = default_write_file,
- .open = default_open,
- .llseek = default_file_lseek,
-};
-
-/* file ops for the "power" files */
-static ssize_t power_read_file (struct file *file, char *buf, size_t count, loff_t *offset);
-static ssize_t power_write_file (struct file *file, const char *buf, size_t count, loff_t *ppos);
-static struct file_operations power_file_operations = {
- .read = power_read_file,
- .write = power_write_file,
- .open = default_open,
- .llseek = default_file_lseek,
-};
-
-/* file ops for the "attention" files */
-static ssize_t attention_read_file (struct file *file, char *buf, size_t count, loff_t *offset);
-static ssize_t attention_write_file (struct file *file, const char *buf, size_t count, loff_t *ppos);
-static struct file_operations attention_file_operations = {
- .read = attention_read_file,
- .write = attention_write_file,
- .open = default_open,
- .llseek = default_file_lseek,
-};
-
-/* file ops for the "latch" files */
-static ssize_t latch_read_file (struct file *file, char *buf, size_t count, loff_t *offset);
-static struct file_operations latch_file_operations = {
- .read = latch_read_file,
- .write = default_write_file,
- .open = default_open,
- .llseek = default_file_lseek,
-};
-
-/* file ops for the "presence" files */
-static ssize_t presence_read_file (struct file *file, char *buf, size_t count, loff_t *offset);
-static struct file_operations presence_file_operations = {
- .read = presence_read_file,
- .write = default_write_file,
- .open = default_open,
- .llseek = default_file_lseek,
-};
-
-/* file ops for the "max bus speed" files */
-static ssize_t max_bus_speed_read_file (struct file *file, char *buf, size_t count, loff_t *offset);
-static struct file_operations max_bus_speed_file_operations = {
- .read = max_bus_speed_read_file,
- .write = default_write_file,
- .open = default_open,
- .llseek = default_file_lseek,
-};
-
-/* file ops for the "current bus speed" files */
-static ssize_t cur_bus_speed_read_file (struct file *file, char *buf, size_t count, loff_t *offset);
-static struct file_operations cur_bus_speed_file_operations = {
- .read = cur_bus_speed_read_file,
- .write = default_write_file,
- .open = default_open,
- .llseek = default_file_lseek,
-};
-
-/* file ops for the "test" files */
-static ssize_t test_write_file (struct file *file, const char *buf, size_t count, loff_t *ppos);
-static struct file_operations test_file_operations = {
- .read = default_read_file,
- .write = test_write_file,
- .open = default_open,
- .llseek = default_file_lseek,
-};
-
-static struct inode_operations pcihpfs_dir_inode_operations = {
- .create = pcihpfs_create,
- .lookup = simple_lookup,
- .unlink = pcihpfs_unlink,
- .mkdir = pcihpfs_mkdir,
- .rmdir = pcihpfs_rmdir,
- .mknod = pcihpfs_mknod,
-};
-
-static struct super_operations pcihpfs_ops = {
- .statfs = simple_statfs,
- .drop_inode = generic_delete_inode,
-};
-
-static int pcihpfs_fill_super(struct super_block *sb, void *data, int silent)
-{
- struct inode *inode;
- struct dentry *root;
-
- sb->s_blocksize = PAGE_CACHE_SIZE;
- sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
- sb->s_magic = PCIHPFS_MAGIC;
- sb->s_op = &pcihpfs_ops;
- inode = pcihpfs_get_inode(sb, S_IFDIR | 0755, 0);
-
- if (!inode) {
- dbg("%s: could not get inode!\n",__FUNCTION__);
- return -ENOMEM;
- }
-
- root = d_alloc_root(inode);
- if (!root) {
- dbg("%s: could not get root dentry!\n",__FUNCTION__);
- iput(inode);
- return -ENOMEM;
- }
- sb->s_root = root;
- return 0;
-}
-
-static struct super_block *pcihpfs_get_sb(struct file_system_type *fs_type,
- int flags, char *dev_name, void *data)
-{
- return get_sb_single(fs_type, flags, data, pcihpfs_fill_super);
-}
-
-static struct file_system_type pcihpfs_type = {
- .owner = THIS_MODULE,
- .name = "pcihpfs",
- .get_sb = pcihpfs_get_sb,
- .kill_sb = kill_litter_super,
-};
-
-static int get_mount (void)
-{
- struct vfsmount *mnt;
-
- spin_lock (&mount_lock);
- if (pcihpfs_mount) {
- mntget(pcihpfs_mount);
- ++pcihpfs_mount_count;
- spin_unlock (&mount_lock);
- goto go_ahead;
- }
-
- spin_unlock (&mount_lock);
- mnt = kern_mount (&pcihpfs_type);
- if (IS_ERR(mnt)) {
- err ("could not mount the fs...erroring out!\n");
- return -ENODEV;
- }
- spin_lock (&mount_lock);
- if (!pcihpfs_mount) {
- pcihpfs_mount = mnt;
- ++pcihpfs_mount_count;
- spin_unlock (&mount_lock);
- goto go_ahead;
- }
- mntget(pcihpfs_mount);
- ++pcihpfs_mount_count;
- spin_unlock (&mount_lock);
- mntput(mnt);
-
-go_ahead:
- dbg("pcihpfs_mount_count = %d\n", pcihpfs_mount_count);
- return 0;
-}
-
-static void remove_mount (void)
-{
- struct vfsmount *mnt;
-
- spin_lock (&mount_lock);
- mnt = pcihpfs_mount;
- --pcihpfs_mount_count;
- if (!pcihpfs_mount_count)
- pcihpfs_mount = NULL;
-
- spin_unlock (&mount_lock);
- mntput(mnt);
- dbg("pcihpfs_mount_count = %d\n", pcihpfs_mount_count);
-}
-
-
-/**
- * pcihpfs_create_by_name - create a file, given a name
- * @name: name of file
- * @mode: type of file
- * @parent: dentry of directory to create it in
- * @dentry: resulting dentry of file
- *
- * There is a bit of overhead in creating a file - basically, we
- * have to hash the name of the file, then look it up. This will
- * prevent files of the same name.
- * We then call the proper vfs_ function to take care of all the
- * file creation details.
- * This function handles both regular files and directories.
- */
-static int pcihpfs_create_by_name (const char *name, mode_t mode,
- struct dentry *parent, struct dentry **dentry)
-{
- struct dentry *d = NULL;
- struct qstr qstr;
- int error;
-
- /* If the parent is not specified, we create it in the root.
- * We need the root dentry to do this, which is in the super
- * block. A pointer to that is in the struct vfsmount that we
- * have around.
- */
- if (!parent ) {
- if (pcihpfs_mount && pcihpfs_mount->mnt_sb) {
- parent = pcihpfs_mount->mnt_sb->s_root;
- }
- }
-
- if (!parent) {
- dbg("Ah! can not find a parent!\n");
- return -EINVAL;
- }
-
- *dentry = NULL;
- qstr.name = name;
- qstr.len = strlen(name);
- qstr.hash = full_name_hash(name,qstr.len);
-
- parent = dget(parent);
-
- down(&parent->d_inode->i_sem);
-
- d = lookup_hash(&qstr,parent);
-
- error = PTR_ERR(d);
- if (!IS_ERR(d)) {
- switch(mode & S_IFMT) {
- case 0:
- case S_IFREG:
- error = vfs_create(parent->d_inode,d,mode);
- break;
- case S_IFDIR:
- error = vfs_mkdir(parent->d_inode,d,mode);
- break;
- default:
- err("cannot create special files\n");
- }
- *dentry = d;
- }
- up(&parent->d_inode->i_sem);
-
- dput(parent);
- return error;
-}
-
-static struct dentry *fs_create_file (const char *name, mode_t mode,
- struct dentry *parent, void *data,
- struct file_operations *fops)
-{
- struct dentry *dentry;
- int error;
-
- dbg("creating file '%s'\n",name);
-
- error = pcihpfs_create_by_name(name,mode,parent,&dentry);
- if (error) {
- dentry = NULL;
- } else {
- if (dentry->d_inode) {
- if (data)
- dentry->d_inode->u.generic_ip = data;
- if (fops)
- dentry->d_inode->i_fop = fops;
- }
- }
-
- return dentry;
-}
-
-static void fs_remove_file (struct dentry *dentry)
-{
- struct dentry *parent = dentry->d_parent;
-
- if (!parent || !parent->d_inode)
- return;
-
- down(&parent->d_inode->i_sem);
- if (pcihpfs_positive(dentry)) {
- if (dentry->d_inode) {
- if (S_ISDIR(dentry->d_inode->i_mode))
- vfs_rmdir(parent->d_inode,dentry);
- else
- vfs_unlink(parent->d_inode,dentry);
- }
-
- dput(dentry);
- }
- up(&parent->d_inode->i_sem);
-}
-
 /* Weee, fun with macros... */
 #define GET_STATUS(name,type) \
 static int get_##name (struct hotplug_slot *slot, type *value) \
@@ -584,80 +168,27 @@
 GET_STATUS(max_bus_speed, enum pci_bus_speed)
 GET_STATUS(cur_bus_speed, enum pci_bus_speed)
 
-static ssize_t power_read_file (struct file *file, char *buf, size_t count, loff_t *offset)
+static ssize_t power_read_file (struct hotplug_slot *slot, char *buf)
 {
- struct hotplug_slot *slot = file->private_data;
- unsigned char *page;
         int retval;
- int len;
         u8 value;
 
- dbg(" count = %d, offset = %lld\n", count, *offset);
-
- if (*offset < 0)
- return -EINVAL;
- if (count == 0 || count > 16384)
- return 0;
- if (*offset != 0)
- return 0;
-
- if (slot == NULL) {
- dbg("slot == NULL???\n");
- return -ENODEV;
- }
-
- page = (unsigned char *)__get_free_page(GFP_KERNEL);
- if (!page)
- return -ENOMEM;
-
         retval = get_power_status (slot, &value);
         if (retval)
                 goto exit;
- len = sprintf (page, "%d\n", value);
-
- if (copy_to_user (buf, page, len)) {
- retval = -EFAULT;
- goto exit;
- }
- *offset += len;
- retval = len;
-
+ retval = sprintf (buf, "%d\n", value);
 exit:
- free_page((unsigned long)page);
         return retval;
 }
 
-static ssize_t power_write_file (struct file *file, const char *ubuff, size_t count, loff_t *offset)
+static ssize_t power_write_file (struct hotplug_slot *slot, const char *buf,
+ size_t count)
 {
- struct hotplug_slot *slot = file->private_data;
- char *buff;
         unsigned long lpower;
         u8 power;
         int retval = 0;
 
- if (*offset < 0)
- return -EINVAL;
- if (count == 0 || count > 16384)
- return 0;
- if (*offset != 0)
- return 0;
-
- if (slot == NULL) {
- dbg("slot == NULL???\n");
- return -ENODEV;
- }
-
- buff = kmalloc (count + 1, GFP_KERNEL);
- if (!buff)
- return -ENOMEM;
- memset (buff, 0x00, count + 1);
-
- if (copy_from_user ((void *)buff, (void *)ubuff, count)) {
- retval = -EFAULT;
- goto exit;
- }
-
- lpower = simple_strtoul (buff, NULL, 10);
+ lpower = simple_strtoul (buf, NULL, 10);
         power = (u8)(lpower & 0xff);
         dbg ("power = %d\n", power);
 
@@ -683,87 +214,39 @@
         module_put(slot->ops->owner);
 
 exit:
- kfree (buff);
-
         if (retval)
                 return retval;
         return count;
 }
 
-static ssize_t attention_read_file (struct file *file, char *buf, size_t count, loff_t *offset)
+static struct hotplug_slot_attribute hotplug_slot_attr_power = {
+ .attr = {.name = "power", .mode = S_IFREG | S_IRUGO | S_IWUSR},
+ .show = power_read_file,
+ .store = power_write_file
+};
+
+static ssize_t attention_read_file (struct hotplug_slot *slot, char *buf)
 {
- struct hotplug_slot *slot = file->private_data;
- unsigned char *page;
         int retval;
- int len;
         u8 value;
 
- dbg("count = %d, offset = %lld\n", count, *offset);
-
- if (*offset < 0)
- return -EINVAL;
- if (count <= 0)
- return 0;
- if (*offset != 0)
- return 0;
-
- if (slot == NULL) {
- dbg("slot == NULL???\n");
- return -ENODEV;
- }
-
- page = (unsigned char *)__get_free_page(GFP_KERNEL);
- if (!page)
- return -ENOMEM;
-
         retval = get_attention_status (slot, &value);
         if (retval)
                 goto exit;
- len = sprintf (page, "%d\n", value);
-
- if (copy_to_user (buf, page, len)) {
- retval = -EFAULT;
- goto exit;
- }
- *offset += len;
- retval = len;
+ retval = sprintf (buf, "%d\n", value);
 
 exit:
- free_page((unsigned long)page);
         return retval;
 }
 
-static ssize_t attention_write_file (struct file *file, const char *ubuff, size_t count, loff_t *offset)
+static ssize_t attention_write_file (struct hotplug_slot *slot, const char *buf,
+ size_t count)
 {
- struct hotplug_slot *slot = file->private_data;
- char *buff;
         unsigned long lattention;
         u8 attention;
         int retval = 0;
 
- if (*offset < 0)
- return -EINVAL;
- if (count == 0 || count > 16384)
- return 0;
- if (*offset != 0)
- return 0;
-
- if (slot == NULL) {
- dbg("slot == NULL???\n");
- return -ENODEV;
- }
-
- buff = kmalloc (count + 1, GFP_KERNEL);
- if (!buff)
- return -ENOMEM;
- memset (buff, 0x00, count + 1);
-
- if (copy_from_user ((void *)buff, (void *)ubuff, count)) {
- retval = -EFAULT;
- goto exit;
- }
-
- lattention = simple_strtoul (buff, NULL, 10);
+ lattention = simple_strtoul (buf, NULL, 10);
         attention = (u8)(lattention & 0xff);
         dbg (" - attention = %d\n", attention);
 
@@ -776,128 +259,63 @@
         module_put(slot->ops->owner);
 
 exit:
- kfree (buff);
-
         if (retval)
                 return retval;
         return count;
 }
 
-static ssize_t latch_read_file (struct file *file, char *buf, size_t count, loff_t *offset)
+static struct hotplug_slot_attribute hotplug_slot_attr_attention = {
+ .attr = {.name = "attention", .mode = S_IFREG | S_IRUGO | S_IWUSR},
+ .show = attention_read_file,
+ .store = attention_write_file
+};
+
+static ssize_t latch_read_file (struct hotplug_slot *slot, char *buf)
 {
- struct hotplug_slot *slot = file->private_data;
- unsigned char *page;
         int retval;
- int len;
         u8 value;
 
- dbg("count = %d, offset = %lld\n", count, *offset);
-
- if (*offset < 0)
- return -EINVAL;
- if (count <= 0)
- return 0;
- if (*offset != 0)
- return 0;
-
- if (slot == NULL) {
- dbg("slot == NULL???\n");
- return -ENODEV;
- }
-
- page = (unsigned char *)__get_free_page(GFP_KERNEL);
- if (!page)
- return -ENOMEM;
-
         retval = get_latch_status (slot, &value);
         if (retval)
                 goto exit;
- len = sprintf (page, "%d\n", value);
-
- if (copy_to_user (buf, page, len)) {
- retval = -EFAULT;
- goto exit;
- }
- *offset += len;
- retval = len;
+ retval = sprintf (buf, "%d\n", value);
 
 exit:
- free_page((unsigned long)page);
         return retval;
 }
 
-static ssize_t presence_read_file (struct file *file, char *buf, size_t count, loff_t *offset)
+static struct hotplug_slot_attribute hotplug_slot_attr_latch = {
+ .attr = {.name = "latch", .mode = S_IFREG | S_IRUGO | S_IWUSR},
+ .show = latch_read_file,
+};
+
+static ssize_t presence_read_file (struct hotplug_slot *slot, char *buf)
 {
- struct hotplug_slot *slot = file->private_data;
- unsigned char *page;
         int retval;
- int len;
         u8 value;
 
- dbg("count = %d, offset = %lld\n", count, *offset);
-
- if (*offset < 0)
- return -EINVAL;
- if (count <= 0)
- return 0;
- if (*offset != 0)
- return 0;
-
- if (slot == NULL) {
- dbg("slot == NULL???\n");
- return -ENODEV;
- }
-
- page = (unsigned char *)__get_free_page(GFP_KERNEL);
- if (!page)
- return -ENOMEM;
-
         retval = get_adapter_status (slot, &value);
         if (retval)
                 goto exit;
- len = sprintf (page, "%d\n", value);
-
- if (copy_to_user (buf, page, len)) {
- retval = -EFAULT;
- goto exit;
- }
- *offset += len;
- retval = len;
+ retval = sprintf (buf, "%d\n", value);
 
 exit:
- free_page((unsigned long)page);
         return retval;
 }
 
+static struct hotplug_slot_attribute hotplug_slot_attr_presence = {
+ .attr = {.name = "adapter", .mode = S_IFREG | S_IRUGO | S_IWUSR},
+ .show = presence_read_file,
+};
+
 static char *unknown_speed = "Unknown bus speed";
 
-static ssize_t max_bus_speed_read_file (struct file *file, char *buf, size_t count, loff_t *offset)
+static ssize_t max_bus_speed_read_file (struct hotplug_slot *slot, char *buf)
 {
- struct hotplug_slot *slot = file->private_data;
- unsigned char *page;
         char *speed_string;
         int retval;
- int len = 0;
         enum pci_bus_speed value;
         
- dbg ("count = %d, offset = %lld\n", count, *offset);
-
- if (*offset < 0)
- return -EINVAL;
- if (count <= 0)
- return 0;
- if (*offset != 0)
- return 0;
-
- if (slot == NULL) {
- dbg("slot == NULL???\n");
- return -ENODEV;
- }
-
- page = (unsigned char *)__get_free_page(GFP_KERNEL);
- if (!page)
- return -ENOMEM;
-
         retval = get_max_bus_speed (slot, &value);
         if (retval)
                 goto exit;
@@ -907,47 +325,23 @@
         else
                 speed_string = pci_bus_speed_strings[value];
         
- len = sprintf (page, "%s\n", speed_string);
-
- if (copy_to_user (buf, page, len)) {
- retval = -EFAULT;
- goto exit;
- }
- *offset += len;
- retval = len;
+ retval = sprintf (buf, "%s\n", speed_string);
 
 exit:
- free_page((unsigned long)page);
         return retval;
 }
 
-static ssize_t cur_bus_speed_read_file (struct file *file, char *buf, size_t count, loff_t *offset)
+static struct hotplug_slot_attribute hotplug_slot_attr_max_bus_speed = {
+ .attr = {.name = "max_bus_speed", .mode = S_IFREG | S_IRUGO | S_IWUSR},
+ .show = max_bus_speed_read_file,
+};
+
+static ssize_t cur_bus_speed_read_file (struct hotplug_slot *slot, char *buf)
 {
- struct hotplug_slot *slot = file->private_data;
- unsigned char *page;
         char *speed_string;
         int retval;
- int len = 0;
         enum pci_bus_speed value;
 
- dbg ("count = %d, offset = %lld\n", count, *offset);
-
- if (*offset < 0)
- return -EINVAL;
- if (count <= 0)
- return 0;
- if (*offset != 0)
- return 0;
-
- if (slot == NULL) {
- dbg("slot == NULL???\n");
- return -ENODEV;
- }
-
- page = (unsigned char *)__get_free_page(GFP_KERNEL);
- if (!page)
- return -ENOMEM;
-
         retval = get_cur_bus_speed (slot, &value);
         if (retval)
                 goto exit;
@@ -957,51 +351,25 @@
         else
                 speed_string = pci_bus_speed_strings[value];
         
- len = sprintf (page, "%s\n", speed_string);
-
- if (copy_to_user (buf, page, len)) {
- retval = -EFAULT;
- goto exit;
- }
- *offset += len;
- retval = len;
+ retval = sprintf (buf, "%s\n", speed_string);
 
 exit:
- free_page((unsigned long)page);
         return retval;
 }
 
-static ssize_t test_write_file (struct file *file, const char *ubuff, size_t count, loff_t *offset)
+static struct hotplug_slot_attribute hotplug_slot_attr_cur_bus_speed = {
+ .attr = {.name = "cur_bus_speed", .mode = S_IFREG | S_IRUGO | S_IWUSR},
+ .show = cur_bus_speed_read_file,
+};
+
+static ssize_t test_write_file (struct hotplug_slot *slot, const char *buf,
+ size_t count)
 {
- struct hotplug_slot *slot = file->private_data;
- char *buff;
         unsigned long ltest;
         u32 test;
         int retval = 0;
 
- if (*offset < 0)
- return -EINVAL;
- if (count == 0 || count > 16384)
- return 0;
- if (*offset != 0)
- return 0;
-
- if (slot == NULL) {
- dbg("slot == NULL???\n");
- return -ENODEV;
- }
-
- buff = kmalloc (count + 1, GFP_KERNEL);
- if (!buff)
- return -ENOMEM;
- memset (buff, 0x00, count + 1);
-
- if (copy_from_user ((void *)buff, (void *)ubuff, count)) {
- retval = -EFAULT;
- goto exit;
- }
-
- ltest = simple_strtoul (buff, NULL, 10);
+ ltest = simple_strtoul (buf, NULL, 10);
         test = (u32)(ltest & 0xffffffff);
         dbg ("test = %d\n", test);
 
@@ -1014,104 +382,69 @@
         module_put(slot->ops->owner);
 
 exit:
- kfree (buff);
-
         if (retval)
                 return retval;
         return count;
 }
 
+static struct hotplug_slot_attribute hotplug_slot_attr_test = {
+ .attr = {.name = "test", .mode = S_IFREG | S_IRUGO | S_IWUSR},
+ .store = test_write_file
+};
+
 static int fs_add_slot (struct hotplug_slot *slot)
 {
- struct hotplug_slot_core *core = slot->core_priv;
- int result;
+ if ((slot->ops->enable_slot) ||
+ (slot->ops->disable_slot) ||
+ (slot->ops->get_power_status))
+ sysfs_create_file(&slot->kobj, &hotplug_slot_attr_power.attr);
+
+ if ((slot->ops->set_attention_status) ||
+ (slot->ops->get_attention_status))
+ sysfs_create_file(&slot->kobj, &hotplug_slot_attr_attention.attr);
+
+ if (slot->ops->get_latch_status)
+ sysfs_create_file(&slot->kobj, &hotplug_slot_attr_latch.attr);
 
- result = get_mount();
- if (result)
- return result;
-
- core->dir_dentry = fs_create_file (slot->name,
- S_IFDIR | S_IXUGO | S_IRUGO,
- NULL, NULL, NULL);
- if (core->dir_dentry != NULL) {
- if ((slot->ops->enable_slot) ||
- (slot->ops->disable_slot) ||
- (slot->ops->get_power_status))
- core->power_dentry =
- fs_create_file ("power",
- S_IFREG | S_IRUGO | S_IWUSR,
- core->dir_dentry, slot,
- &power_file_operations);
-
- if ((slot->ops->set_attention_status) ||
- (slot->ops->get_attention_status))
- core->attention_dentry =
- fs_create_file ("attention",
- S_IFREG | S_IRUGO | S_IWUSR,
- core->dir_dentry, slot,
- &attention_file_operations);
-
- if (slot->ops->get_latch_status)
- core->latch_dentry =
- fs_create_file ("latch",
- S_IFREG | S_IRUGO,
- core->dir_dentry, slot,
- &latch_file_operations);
-
- if (slot->ops->get_adapter_status)
- core->adapter_dentry =
- fs_create_file ("adapter",
- S_IFREG | S_IRUGO,
- core->dir_dentry, slot,
- &presence_file_operations);
-
- if (slot->ops->get_max_bus_speed)
- core->max_bus_speed_dentry =
- fs_create_file ("max_bus_speed",
- S_IFREG | S_IRUGO,
- core->dir_dentry, slot,
- &max_bus_speed_file_operations);
-
- if (slot->ops->get_cur_bus_speed)
- core->cur_bus_speed_dentry =
- fs_create_file ("cur_bus_speed",
- S_IFREG | S_IRUGO,
- core->dir_dentry, slot,
- &cur_bus_speed_file_operations);
-
- if (slot->ops->hardware_test)
- core->test_dentry =
- fs_create_file ("test",
- S_IFREG | S_IRUGO | S_IWUSR,
- core->dir_dentry, slot,
- &test_file_operations);
- }
+ if (slot->ops->get_adapter_status)
+ sysfs_create_file(&slot->kobj, &hotplug_slot_attr_presence.attr);
+
+ if (slot->ops->get_max_bus_speed)
+ sysfs_create_file(&slot->kobj, &hotplug_slot_attr_max_bus_speed.attr);
+
+ if (slot->ops->get_cur_bus_speed)
+ sysfs_create_file(&slot->kobj, &hotplug_slot_attr_cur_bus_speed.attr);
+
+ if (slot->ops->hardware_test)
+ sysfs_create_file(&slot->kobj, &hotplug_slot_attr_test.attr);
         return 0;
 }
 
 static void fs_remove_slot (struct hotplug_slot *slot)
 {
- struct hotplug_slot_core *core = slot->core_priv;
+ if ((slot->ops->enable_slot) ||
+ (slot->ops->disable_slot) ||
+ (slot->ops->get_power_status))
+ sysfs_remove_file(&slot->kobj, &hotplug_slot_attr_power.attr);
+
+ if ((slot->ops->set_attention_status) ||
+ (slot->ops->get_attention_status))
+ sysfs_remove_file(&slot->kobj, &hotplug_slot_attr_attention.attr);
+
+ if (slot->ops->get_latch_status)
+ sysfs_remove_file(&slot->kobj, &hotplug_slot_attr_latch.attr);
 
- if (core->dir_dentry) {
- if (core->power_dentry)
- fs_remove_file (core->power_dentry);
- if (core->attention_dentry)
- fs_remove_file (core->attention_dentry);
- if (core->latch_dentry)
- fs_remove_file (core->latch_dentry);
- if (core->adapter_dentry)
- fs_remove_file (core->adapter_dentry);
- if (core->max_bus_speed_dentry)
- fs_remove_file (core->max_bus_speed_dentry);
- if (core->cur_bus_speed_dentry)
- fs_remove_file (core->cur_bus_speed_dentry);
- if (core->test_dentry)
- fs_remove_file (core->test_dentry);
- fs_remove_file (core->dir_dentry);
- }
+ if (slot->ops->get_adapter_status)
+ sysfs_remove_file(&slot->kobj, &hotplug_slot_attr_presence.attr);
+
+ if (slot->ops->get_max_bus_speed)
+ sysfs_remove_file(&slot->kobj, &hotplug_slot_attr_max_bus_speed.attr);
 
- remove_mount();
+ if (slot->ops->get_cur_bus_speed)
+ sysfs_remove_file(&slot->kobj, &hotplug_slot_attr_cur_bus_speed.attr);
+
+ if (slot->ops->hardware_test)
+ sysfs_remove_file(&slot->kobj, &hotplug_slot_attr_test.attr);
 }
 
 static struct hotplug_slot *get_slot_from_name (const char *name)
@@ -1138,7 +471,6 @@
  */
 int pci_hp_register (struct hotplug_slot *slot)
 {
- struct hotplug_slot_core *core;
         int result;
 
         if (slot == NULL)
@@ -1146,21 +478,21 @@
         if ((slot->info == NULL) || (slot->ops == NULL))
                 return -EINVAL;
 
- core = kmalloc (sizeof (struct hotplug_slot_core), GFP_KERNEL);
- if (!core)
- return -ENOMEM;
-
         /* make sure we have not already registered this slot */
         spin_lock (&list_lock);
         if (get_slot_from_name (slot->name) != NULL) {
                 spin_unlock (&list_lock);
- kfree (core);
                 return -EINVAL;
         }
 
- memset (core, 0, sizeof (struct hotplug_slot_core));
- slot->core_priv = core;
+ strncpy(slot->kobj.name, slot->name, KOBJ_NAME_LEN);
+ kobj_set_kset_s(slot, hotplug_slots_subsys);
 
+ if (kobject_register(&slot->kobj)) {
+ err("Unable to register kobject");
+ return -EINVAL;
+ }
+
         list_add (&slot->slot_list, &pci_hotplug_slot_list);
         spin_unlock (&list_lock);
 
@@ -1197,20 +529,11 @@
         spin_unlock (&list_lock);
 
         fs_remove_slot (slot);
- kfree(slot->core_priv);
         dbg ("Removed slot %s from the list\n", slot->name);
+ kobject_unregister(&slot->kobj);
         return 0;
 }
 
-static inline void update_dentry_inode_time (struct dentry *dentry)
-{
- struct inode *inode = dentry->d_inode;
- if (inode) {
- inode->i_mtime = CURRENT_TIME;
- dnotify_parent(dentry, DN_MODIFY);
- }
-}
-
 /**
  * pci_hp_change_slot_info - changes the slot's information structure in the core
  * @name: the name of the slot whose info has changed
@@ -1220,45 +543,10 @@
  * hotplug subsystem previously with a call to pci_hp_register().
  *
  * Returns 0 if successful, anything else for an error.
+ * Not supported by sysfs now.
  */
 int pci_hp_change_slot_info (const char *name, struct hotplug_slot_info *info)
 {
- struct hotplug_slot *temp;
- struct hotplug_slot_core *core;
-
- if (info == NULL)
- return -ENODEV;
-
- spin_lock (&list_lock);
- temp = get_slot_from_name (name);
- if (temp == NULL) {
- spin_unlock (&list_lock);
- return -ENODEV;
- }
-
- /*
- * check all fields in the info structure, and update timestamps
- * for the files referring to the fields that have now changed.
- */
- core = temp->core_priv;
- if ((core->power_dentry) &&
- (temp->info->power_status != info->power_status))
- update_dentry_inode_time (core->power_dentry);
- if ((core->attention_dentry) &&
- (temp->info->attention_status != info->attention_status))
- update_dentry_inode_time (core->attention_dentry);
- if ((core->latch_dentry) &&
- (temp->info->latch_status != info->latch_status))
- update_dentry_inode_time (core->latch_dentry);
- if ((core->adapter_dentry) &&
- (temp->info->adapter_status != info->adapter_status))
- update_dentry_inode_time (core->adapter_dentry);
- if ((core->cur_bus_speed_dentry) &&
- (temp->info->cur_bus_speed != info->cur_bus_speed))
- update_dentry_inode_time (core->cur_bus_speed_dentry);
-
- memcpy (temp->info, info, sizeof (struct hotplug_slot_info));
- spin_unlock (&list_lock);
         return 0;
 }
 
@@ -1266,20 +554,18 @@
 {
         int result;
 
- spin_lock_init(&mount_lock);
         spin_lock_init(&list_lock);
 
- dbg("registering filesystem.\n");
- result = register_filesystem(&pcihpfs_type);
+ kset_set_kset_s(&hotplug_slots_subsys, pci_bus_type.subsys);
+ result = subsystem_register(&hotplug_slots_subsys);
         if (result) {
- err("register_filesystem failed with %d\n", result);
+ err("Register subsys with error %d\n", result);
                 goto exit;
         }
-
         result = cpci_hotplug_init(debug);
         if (result) {
                 err ("cpci_hotplug_init with error %d\n", result);
- goto error_fs;
+ goto err_subsys;
         }
 
 #ifdef CONFIG_PROC_FS
@@ -1290,22 +576,21 @@
         info (DRIVER_DESC " version: " DRIVER_VERSION "\n");
         goto exit;
         
-error_fs:
- unregister_filesystem(&pcihpfs_type);
+err_subsys:
+ subsystem_unregister(&hotplug_slots_subsys);
 exit:
         return result;
 }
 
 static void __exit pci_hotplug_exit (void)
 {
- cpci_hotplug_exit();
-
- unregister_filesystem(&pcihpfs_type);
-
 #ifdef CONFIG_PROC_FS
         if (slotdir)
                 remove_proc_entry(slotdir_name, proc_bus_pci_dir);
 #endif
+
+ cpci_hotplug_exit();
+ subsystem_unregister(&hotplug_slots_subsys);
 }
 
 module_init(pci_hotplug_init);
@@ -1320,4 +605,3 @@
 EXPORT_SYMBOL_GPL(pci_hp_register);
 EXPORT_SYMBOL_GPL(pci_hp_deregister);
 EXPORT_SYMBOL_GPL(pci_hp_change_slot_info);
-

===================================================================

This BitKeeper patch contains the following changesets:
1.956..1.957
## Wrapped with gzip_uu ##

begin 664 bkpatch7322
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
%5/HF````
`
end

 

-- 
Opinions expressed are those of the author and do not represent Intel
Corporation

- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/



This archive was generated by hypermail 2b29 : Thu Jan 23 2003 - 22:00:32 EST