# This is a BitKeeper generated patch for the following project:
# Project Name: Linux kernel tree
# This patch format is intended for GNU patch command version 2.5 or higher.
# This patch includes the following deltas:
#	           ChangeSet	1.422   -> 1.423  
#	drivers/hotplug/pci_hotplug_core.c	1.10    -> 1.11   
#
# The following is the BitKeeper ChangeSet Log
# --------------------------------------------
# 02/02/27	greg@kroah.com	1.423
# PCI Hotplug Core cleanups:
# 	- pcihpfs cleanup, removing unneeded file operations.
# 	- Added facility to have the files change their timestamps if the data
# 	  within the file changes.
# --------------------------------------------
#
diff -Nru a/drivers/hotplug/pci_hotplug_core.c b/drivers/hotplug/pci_hotplug_core.c
--- a/drivers/hotplug/pci_hotplug_core.c	Wed Feb 27 14:21:17 2002
+++ b/drivers/hotplug/pci_hotplug_core.c	Wed Feb 27 14:21:17 2002
@@ -1,8 +1,8 @@
 /*
  * PCI HotPlug Controller Core
  *
- * Copyright (c) 2001 Greg Kroah-Hartman (greg@kroah.com)
- * Copyright (c) 2001 IBM Corp.
+ * Copyright (c) 2001-2002 Greg Kroah-Hartman (greg@kroah.com)
+ * Copyright (c) 2001-2002 IBM Corp.
  *
  * All rights reserved.
  *
@@ -23,6 +23,8 @@
  *
  * Send feedback to <greg@kroah.com>
  *
+ * Filesystem portion based on work done by Pat Mochel on ddfs/driverfs
+ *
  */
 
 #include <linux/config.h>
@@ -54,7 +56,7 @@
 /* local variables */
 static int debug;
 
-#define DRIVER_VERSION	"0.3"
+#define DRIVER_VERSION	"0.4"
 #define DRIVER_AUTHOR	"Greg Kroah-Hartman <greg@kroah.com>"
 #define DRIVER_DESC	"PCI Hot Plug PCI Core"
 
@@ -74,7 +76,6 @@
 };
 
 static struct super_operations pcihpfs_ops;
-static struct address_space_operations pcihpfs_aops;
 static struct file_operations pcihpfs_dir_operations;
 static struct file_operations default_file_operations;
 static struct inode_operations pcihpfs_dir_inode_operations;
@@ -112,7 +113,6 @@
 		inode->i_blksize = PAGE_CACHE_SIZE;
 		inode->i_blocks = 0;
 		inode->i_rdev = NODEV;
-		inode->i_mapping->a_ops = &pcihpfs_aops;
 		inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
 		switch (mode & S_IFMT) {
 		default:
@@ -154,18 +154,6 @@
  	return pcihpfs_mknod (dir, dentry, mode | S_IFREG, 0);
 }
 
-static int pcihpfs_link (struct dentry *old_dentry, struct inode *dir,
-			 struct dentry *dentry)
-{
-	struct inode *inode = old_dentry->d_inode;
-
-	inode->i_nlink++;
-	atomic_inc(&inode->i_count);
- 	dget(dentry);
-	d_instantiate(dentry, inode);
-	return 0;
-}
-
 static inline int pcihpfs_positive (struct dentry *dentry)
 {
 	return dentry->d_inode && !d_unhashed(dentry);
@@ -196,29 +184,15 @@
 	if (pcihpfs_empty(dentry)) {
 		struct inode *inode = dentry->d_inode;
 
+		lock_kernel();
 		inode->i_nlink--;
+		unlock_kernel();
 		dput(dentry);
 		error = 0;
 	}
 	return error;
 }
 
-static int pcihpfs_rename (struct inode *old_dir, struct dentry *old_dentry,
-			   struct inode *new_dir, struct dentry *new_dentry)
-{
-	int error = -ENOTEMPTY;
-
-	if (pcihpfs_empty(new_dentry)) {
-		struct inode *inode = new_dentry->d_inode;
-		if (inode) {
-			inode->i_nlink--;
-			dput(new_dentry);
-		}
-		error = 0;
-	}
-	return error;
-}
-
 #define pcihpfs_rmdir pcihpfs_unlink
 
 /* default file operations */
@@ -238,6 +212,7 @@
 {
 	loff_t retval = -EINVAL;
 
+	lock_kernel();
 	switch(orig) {
 	case 0:
 		if (offset > 0) {
@@ -254,6 +229,7 @@
 	default:
 		break;
 	}
+	unlock_kernel();
 	return retval;
 }
 
@@ -265,18 +241,9 @@
 	return 0;
 }
 
-static int default_sync_file (struct file *file, struct dentry *dentry, int datasync)
-{
-	return 0;
-}
-
-static struct address_space_operations pcihpfs_aops = {
-};
-
 static struct file_operations pcihpfs_dir_operations = {
 	read:		generic_read_dir,
 	readdir:	dcache_readdir,
-	fsync:		default_sync_file,
 };
 
 static struct file_operations default_file_operations = {
@@ -284,8 +251,6 @@
 	write:		default_write_file,
 	open:		default_open,
 	llseek:		default_file_lseek,
-	fsync:		default_sync_file,
-	mmap:		generic_file_mmap,
 };
 
 /* file ops for the "power" files */
@@ -296,8 +261,6 @@
 	write:		power_write_file,
 	open:		default_open,
 	llseek:		default_file_lseek,
-	fsync:		default_sync_file,
-	mmap:		generic_file_mmap,
 };
 
 /* file ops for the "attention" files */
@@ -308,8 +271,6 @@
 	write:		attention_write_file,
 	open:		default_open,
 	llseek:		default_file_lseek,
-	fsync:		default_sync_file,
-	mmap:		generic_file_mmap,
 };
 
 /* file ops for the "latch" files */
@@ -319,8 +280,6 @@
 	write:		default_write_file,
 	open:		default_open,
 	llseek:		default_file_lseek,
-	fsync:		default_sync_file,
-	mmap:		generic_file_mmap,
 };
 
 /* file ops for the "presence" files */
@@ -330,8 +289,6 @@
 	write:		default_write_file,
 	open:		default_open,
 	llseek:		default_file_lseek,
-	fsync:		default_sync_file,
-	mmap:		generic_file_mmap,
 };
 
 /* file ops for the "test" files */
@@ -341,19 +298,15 @@
 	write:		test_write_file,
 	open:		default_open,
 	llseek:		default_file_lseek,
-	fsync:		default_sync_file,
-	mmap:		generic_file_mmap,
 };
 
 static struct inode_operations pcihpfs_dir_inode_operations = {
 	create:		pcihpfs_create,
 	lookup:		pcihpfs_lookup,
-	link:		pcihpfs_link,
 	unlink:		pcihpfs_unlink,
 	mkdir:		pcihpfs_mkdir,
 	rmdir:		pcihpfs_rmdir,
 	mknod:		pcihpfs_mknod,
-	rename:		pcihpfs_rename,
 };
 
 static struct super_operations pcihpfs_ops = {
@@ -485,7 +438,7 @@
 
 	if (!parent) {
 		dbg("Ah! can not find a parent!\n");
-		return -EFAULT;
+		return -EINVAL;
 	}
 
 	*dentry = NULL;
@@ -686,7 +639,7 @@
 
 		default:
 			err ("Illegal value specified for power\n");
-			retval = -EFAULT;
+			retval = -EINVAL;
 	}
 
 exit:	
@@ -1019,7 +972,7 @@
 	if (slot == NULL)
 		return -ENODEV;
 	if ((slot->info == NULL) || (slot->ops == NULL))
-		return -EFAULT;
+		return -EINVAL;
 
 	core = kmalloc (sizeof (struct hotplug_slot_core), GFP_KERNEL);
 	if (!core)
@@ -1030,7 +983,7 @@
 	if (get_slot_from_name (slot->name) != NULL) {
 		spin_unlock (&list_lock);
 		kfree (core);
-		return -EFAULT;
+		return -EINVAL;
 	}
 
 	slot->core_priv = core;
@@ -1076,6 +1029,12 @@
 	return 0;
 }
 
+static inline void update_inode_time (struct inode *inode)
+{
+	if (inode)
+		inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
+}
+
 /**
  * pci_hp_change_slot_info - changes the slot's information structure in the core
  * @name: the name of the slot whose info has changed
@@ -1089,6 +1048,7 @@
 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;
@@ -1099,6 +1059,24 @@
 		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_inode_time (core->power_dentry->d_inode);
+	if ((core->attention_dentry) &&
+	    (temp->info->attention_status != info->attention_status))
+		update_inode_time (core->attention_dentry->d_inode);
+	if ((core->latch_dentry) &&
+	    (temp->info->latch_status != info->latch_status))
+		update_inode_time (core->latch_dentry->d_inode);
+	if ((core->adapter_dentry) &&
+	    (temp->info->adapter_status != info->adapter_status))
+		update_inode_time (core->adapter_dentry->d_inode);
 
 	memcpy (temp->info, info, sizeof (struct hotplug_slot_info));
 	spin_unlock (&list_lock);
