# This is a BitKeeper generated patch for the following project: # Project Name: greg k-h's linux 2.5 USB kernel tree # This patch format is intended for GNU patch command version 2.5 or higher. # This patch includes the following deltas: # ChangeSet 1.814 -> 1.819 # kernel/ksyms.c 1.49 -> 1.51 # drivers/hotplug/pci_hotplug.h 1.3 -> 1.4 # drivers/hotplug/pci_hotplug_core.c 1.22 -> 1.24 # drivers/hotplug/ibmphp_core.c 1.11 -> 1.12 # # The following is the BitKeeper ChangeSet Log # -------------------------------------------- # 02/09/17 scottm@somanetworks.com 1.815 # [PATCH] Small pcihpfs dnotify fix # # I've been working on a userspace daemon to go with my CompactPCI driver, # and yesterday I discovered an oversight in pci_hp_change_slot_info - it # doesn't call dnotify_parent, so dnotify based clients basically don't # work against pcihpfs. The following patch (against 2.5 BK) reworks # things to just update the mtime (since we're modifying the file after # all), and then call dnotify_parent. # -------------------------------------------- # 02/09/17 greg@kroah.com 1.816 # added max bus speed and current bus speed files to the pci hotplug core. # # Patch based on work done by Irene Zubarev # -------------------------------------------- # 02/09/17 greg@kroah.com 1.817 # uncommented max bus speed and current bus speed functions from the ibm pci hotplug driver # -------------------------------------------- # 02/09/17 greg@kroah.com 1.818 # added __inode_dir_notify to the list of exported symbols so that dnotify_parent() # can be called from a module. # -------------------------------------------- # 02/09/17 greg@kroah.com 1.819 # forgot to include dnotify.h in ksyms.c :( # -------------------------------------------- # diff -Nru a/drivers/hotplug/ibmphp_core.c b/drivers/hotplug/ibmphp_core.c --- a/drivers/hotplug/ibmphp_core.c Tue Sep 17 17:06:43 2002 +++ b/drivers/hotplug/ibmphp_core.c Tue Sep 17 17:06:43 2002 @@ -384,14 +384,15 @@ debug ("get_adapter_present - Exit rc[%d] hpcrc[%x] value[%x]\n", rc, hpcrc, *value); return rc; } -/* -static int get_max_bus_speed (struct hotplug_slot *hotplug_slot, u8 * value) + +static int get_max_bus_speed (struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value) { int rc = -ENODEV; struct slot *pslot; u8 mode = 0; - debug ("get_max_bus_speed - Entry hotplug_slot[%lx] pvalue[%lx]\n", (ulong)hotplug_slot, (ulong) value); + debug ("%s - Entry hotplug_slot[%p] pvalue[%p]\n", __FUNCTION__, + hotplug_slot, value); ibmphp_lock_operations (); @@ -413,25 +414,26 @@ *value = pslot->supported_speed + 0x01; break; default: -*/ /* Note (will need to change): there would be soon 256, 512 also */ -/* rc = -ENODEV; + /* Note (will need to change): there would be soon 256, 512 also */ + rc = -ENODEV; } } } else rc = -ENODEV; ibmphp_unlock_operations (); - debug ("get_max_bus_speed - Exit rc[%d] value[%x]\n", rc, *value); + debug ("%s - Exit rc[%d] value[%x]\n", __FUNCTION__, rc, *value); return rc; } -static int get_cur_bus_speed (struct hotplug_slot *hotplug_slot, u8 * value) +static int get_cur_bus_speed (struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value) { int rc = -ENODEV; struct slot *pslot; u8 mode = 0; - debug ("get_cur_bus_speed - Entry hotplug_slot[%lx] pvalue[%lx]\n", (ulong)hotplug_slot, (ulong) value); + debug ("%s - Entry hotplug_slot[%p] pvalue[%p]\n", __FUNCTION__, + hotplug_slot, value); ibmphp_lock_operations (); @@ -458,8 +460,8 @@ *value += 0x01; break; default: -*/ /* Note of change: there would also be 256, 512 soon */ -/* rc = -ENODEV; + /* Note of change: there would also be 256, 512 soon */ + rc = -ENODEV; } } } @@ -467,10 +469,10 @@ rc = -ENODEV; ibmphp_unlock_operations (); - debug ("get_cur_bus_speed - Exit rc[%d] value[%x]\n", rc, *value); + debug ("%s - Exit rc[%d] value[%x]\n", __FUNCTION__, rc, *value); return rc; } - +/* static int get_max_adapter_speed_1 (struct hotplug_slot *hotplug_slot, u8 * value, u8 flag) { int rc = -ENODEV; @@ -1584,9 +1586,9 @@ .get_attention_status = get_attention_status, .get_latch_status = get_latch_status, .get_adapter_status = get_adapter_present, -/* .get_max_bus_speed_status = get_max_bus_speed, - .get_max_adapter_speed_status = get_max_adapter_speed, + .get_max_bus_speed_status = get_max_bus_speed, .get_cur_bus_speed_status = get_cur_bus_speed, +/* .get_max_adapter_speed_status = get_max_adapter_speed, .get_bus_name_status = get_bus_name, */ }; diff -Nru a/drivers/hotplug/pci_hotplug.h b/drivers/hotplug/pci_hotplug.h --- a/drivers/hotplug/pci_hotplug.h Tue Sep 17 17:06:43 2002 +++ b/drivers/hotplug/pci_hotplug.h Tue Sep 17 17:06:43 2002 @@ -29,6 +29,22 @@ #define _PCI_HOTPLUG_H +/* These values come from the PCI Hotplug Spec */ +enum pci_bus_speed { + PCI_SPEED_33MHz = 0x00, + PCI_SPEED_66MHz = 0x01, + PCI_SPEED_66MHz_PCIX = 0x02, + PCI_SPEED_100MHz_PCIX = 0x03, + PCI_SPEED_133MHz_PCIX = 0x04, + PCI_SPEED_66MHz_PCIX_266 = 0x09, + PCI_SPEED_100MHz_PCIX_266 = 0x0a, + PCI_SPEED_133MHz_PCIX_266 = 0x0b, + PCI_SPEED_66MHz_PCIX_533 = 0x11, + PCI_SPEED_100MHz_PCIX_533 = 0X12, + PCI_SPEED_133MHz_PCIX_533 = 0x13, + PCI_SPEED_UNKNOWN = 0xff, +}; + struct hotplug_slot; struct hotplug_slot_core; @@ -50,7 +66,13 @@ * @get_latch_status: Called to get the current latch status of a slot. * If this field is NULL, the value passed in the struct hotplug_slot_info * will be used when this value is requested by a user. - * @get_adapter_present: Called to get see if an adapter is present in the slot or not. + * @get_adapter_status: Called to get see if an adapter is present in the slot or not. + * If this field is NULL, the value passed in the struct hotplug_slot_info + * will be used when this value is requested by a user. + * @get_max_bus_speed_status: Called to get the max bus speed for a slot. + * If this field is NULL, the value passed in the struct hotplug_slot_info + * will be used when this value is requested by a user. + * @get_cur_bus_speed_status: Called to get the current bus speed for a slot. * If this field is NULL, the value passed in the struct hotplug_slot_info * will be used when this value is requested by a user. * @@ -69,6 +91,8 @@ int (*get_attention_status) (struct hotplug_slot *slot, u8 *value); int (*get_latch_status) (struct hotplug_slot *slot, u8 *value); int (*get_adapter_status) (struct hotplug_slot *slot, u8 *value); + int (*get_max_bus_speed_status) (struct hotplug_slot *slot, enum pci_bus_speed *value); + int (*get_cur_bus_speed_status) (struct hotplug_slot *slot, enum pci_bus_speed *value); }; /** @@ -85,6 +109,8 @@ u8 attention_status; u8 latch_status; u8 adapter_status; + enum pci_bus_speed max_bus_speed_status; + enum pci_bus_speed cur_bus_speed_status; }; /** diff -Nru a/drivers/hotplug/pci_hotplug_core.c b/drivers/hotplug/pci_hotplug_core.c --- a/drivers/hotplug/pci_hotplug_core.c Tue Sep 17 17:06:43 2002 +++ b/drivers/hotplug/pci_hotplug_core.c Tue Sep 17 17:06:43 2002 @@ -38,6 +38,7 @@ #include #include #include +#include #include #include "pci_hotplug.h" @@ -74,6 +75,8 @@ 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 super_operations pcihpfs_ops; @@ -86,6 +89,29 @@ LIST_HEAD(pci_hotplug_slot_list); +/* these strings match up with the values in pci_bus_speed */ +static char *pci_bus_speed_strings[] = { + "33 MHz PCI", /* 0x00 */ + "66 MHz PCI", /* 0x01 */ + "66 MHz PCIX", /* 0x02 */ + "100 MHz PCIX", /* 0x03 */ + "133 MHz PCIX", /* 0x04 */ + NULL, /* 0x05 */ + NULL, /* 0x06 */ + NULL, /* 0x07 */ + NULL, /* 0x08 */ + "66 MHz PCIX 266", /* 0x09 */ + "100 MHz PCIX 266", /* 0x0a */ + "133 MHz PCIX 266", /* 0x0b */ + NULL, /* 0x0c */ + NULL, /* 0x0d */ + NULL, /* 0x0e */ + NULL, /* 0x0f */ + NULL, /* 0x10 */ + "66 MHz PCIX 533", /* 0x11 */ + "100 MHz PCIX 533", /* 0x12 */ + "133 MHz PCIX 533", /* 0x13 */ +}; static struct inode *pcihpfs_get_inode (struct super_block *sb, int mode, int dev) { @@ -274,6 +300,24 @@ .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 = { @@ -501,8 +545,8 @@ up(&parent->d_inode->i_sem); } -#define GET_STATUS(name) \ -static int get_##name##_status (struct hotplug_slot *slot, u8 *value) \ +#define GET_STATUS(name,type) \ +static int get_##name##_status (struct hotplug_slot *slot, type *value) \ { \ struct hotplug_slot_ops *ops = slot->ops; \ int retval = 0; \ @@ -517,10 +561,12 @@ return retval; \ } -GET_STATUS(power) -GET_STATUS(attention) -GET_STATUS(latch) -GET_STATUS(adapter) +GET_STATUS(power, u8) +GET_STATUS(attention, u8) +GET_STATUS(latch, u8) +GET_STATUS(adapter, u8) +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) { @@ -769,7 +815,6 @@ return retval; } - static ssize_t presence_read_file (struct file *file, char *buf, size_t count, loff_t *offset) { struct hotplug_slot *slot = file->private_data; @@ -813,6 +858,108 @@ return retval; } +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) +{ + 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_status (slot, &value); + if (retval) + goto exit; + + if (value == PCI_SPEED_UNKNOWN) + speed_string = unknown_speed; + 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; + +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) +{ + 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_status (slot, &value); + if (retval) + goto exit; + + if (value == PCI_SPEED_UNKNOWN) + speed_string = unknown_speed; + 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; + +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) { struct hotplug_slot *slot = file->private_data; @@ -876,30 +1023,57 @@ S_IFDIR | S_IXUGO | S_IRUGO, NULL, NULL, NULL); if (core->dir_dentry != NULL) { - core->power_dentry = fs_create_file ("power", - S_IFREG | S_IRUGO | S_IWUSR, - core->dir_dentry, slot, - &power_file_operations); - - core->attention_dentry = fs_create_file ("attention", - S_IFREG | S_IRUGO | S_IWUSR, - core->dir_dentry, slot, - &attention_file_operations); - - core->latch_dentry = fs_create_file ("latch", - S_IFREG | S_IRUGO, - core->dir_dentry, slot, - &latch_file_operations); - - core->adapter_dentry = fs_create_file ("adapter", - S_IFREG | S_IRUGO, - core->dir_dentry, slot, - &presence_file_operations); - - core->test_dentry = fs_create_file ("test", - S_IFREG | S_IRUGO | S_IWUSR, - core->dir_dentry, slot, - &test_file_operations); + 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_status) + 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_status) + 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); } return 0; } @@ -917,6 +1091,10 @@ 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); @@ -969,6 +1147,7 @@ return -EINVAL; } + memset (core, 0, sizeof (struct hotplug_slot_core)); slot->core_priv = core; list_add (&slot->slot_list, &pci_hotplug_slot_list); @@ -1012,10 +1191,13 @@ return 0; } -static inline void update_inode_time (struct inode *inode) +static inline void update_dentry_inode_time (struct dentry *dentry) { - if (inode) - inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; + struct inode *inode = dentry->d_inode; + if (inode) { + inode->i_mtime = CURRENT_TIME; + dnotify_parent(dentry, DN_MODIFY); + } } /** @@ -1050,16 +1232,19 @@ core = temp->core_priv; if ((core->power_dentry) && (temp->info->power_status != info->power_status)) - update_inode_time (core->power_dentry->d_inode); + update_dentry_inode_time (core->power_dentry); if ((core->attention_dentry) && (temp->info->attention_status != info->attention_status)) - update_inode_time (core->attention_dentry->d_inode); + update_dentry_inode_time (core->attention_dentry); if ((core->latch_dentry) && (temp->info->latch_status != info->latch_status)) - update_inode_time (core->latch_dentry->d_inode); + update_dentry_inode_time (core->latch_dentry); if ((core->adapter_dentry) && (temp->info->adapter_status != info->adapter_status)) - update_inode_time (core->adapter_dentry->d_inode); + update_dentry_inode_time (core->adapter_dentry); + if ((core->cur_bus_speed_dentry) && + (temp->info->cur_bus_speed_status != info->cur_bus_speed_status)) + update_dentry_inode_time (core->cur_bus_speed_dentry); memcpy (temp->info, info, sizeof (struct hotplug_slot_info)); spin_unlock (&list_lock); diff -Nru a/kernel/ksyms.c b/kernel/ksyms.c --- a/kernel/ksyms.c Tue Sep 17 17:06:43 2002 +++ b/kernel/ksyms.c Tue Sep 17 17:06:43 2002 @@ -53,6 +53,7 @@ #include #include #include +#include #include #if defined(CONFIG_PROC_FS) @@ -559,6 +560,7 @@ EXPORT_SYMBOL(make_bad_inode); EXPORT_SYMBOL(is_bad_inode); EXPORT_SYMBOL(event); +EXPORT_SYMBOL(__inode_dir_notify); #ifdef CONFIG_UID16 EXPORT_SYMBOL(overflowuid);