summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/hotplug/cpqphp.h9
-rw-r--r--drivers/hotplug/cpqphp_core.c66
-rw-r--r--drivers/hotplug/cpqphp_ctrl.c4
-rw-r--r--drivers/hotplug/ibmphp_core.c32
-rw-r--r--drivers/hotplug/pci_hotplug.h28
-rw-r--r--drivers/hotplug/pci_hotplug_core.c290
-rw-r--r--drivers/pci/proc.c3
-rw-r--r--kernel/exit.c3
-rw-r--r--kernel/ksyms.c2
9 files changed, 354 insertions, 83 deletions
diff --git a/drivers/hotplug/cpqphp.h b/drivers/hotplug/cpqphp.h
index 18f99fad6989..0be973674055 100644
--- a/drivers/hotplug/cpqphp.h
+++ b/drivers/hotplug/cpqphp.h
@@ -305,8 +305,8 @@ struct controller {
u8 first_slot;
u8 add_support;
u8 push_flag;
- u8 speed; /* 0 = 33MHz, 1 = 66MHz */
- u8 speed_capability; /* 0 = 33MHz, 1 = 66MHz */
+ enum pci_bus_speed speed;
+ enum pci_bus_speed speed_capability;
u8 push_button; /* 0 = no pushbutton, 1 = pushbutton present */
u8 slot_switch_type; /* 0 = no switch, 1 = switch present */
u8 defeature_PHP; /* 0 = PHP not supported, 1 = PHP supported */
@@ -321,9 +321,6 @@ struct controller {
wait_queue_head_t queue; /* sleep & wake process */
};
-#define CTRL_SPEED_33MHz 0
-#define CTRL_SPEED_66MHz 1
-
struct irq_mapping {
u8 barber_pole;
u8 valid_INT;
@@ -635,7 +632,7 @@ static inline u8 get_controller_speed (struct controller *ctrl)
u16 misc;
misc = readw(ctrl->hpc_reg + MISC);
- return (misc & 0x0800) ? 1 : 0;
+ return (misc & 0x0800) ? PCI_SPEED_66MHz : PCI_SPEED_33MHz;
}
diff --git a/drivers/hotplug/cpqphp_core.c b/drivers/hotplug/cpqphp_core.c
index aec0ecc145bc..4241575713e8 100644
--- a/drivers/hotplug/cpqphp_core.c
+++ b/drivers/hotplug/cpqphp_core.c
@@ -79,6 +79,8 @@ static int get_power_status (struct hotplug_slot *slot, u8 *value);
static int get_attention_status (struct hotplug_slot *slot, u8 *value);
static int get_latch_status (struct hotplug_slot *slot, u8 *value);
static int get_adapter_status (struct hotplug_slot *slot, u8 *value);
+static int get_max_bus_speed (struct hotplug_slot *slot, enum pci_bus_speed *value);
+static int get_cur_bus_speed (struct hotplug_slot *slot, enum pci_bus_speed *value);
static struct hotplug_slot_ops cpqphp_hotplug_slot_ops = {
.owner = THIS_MODULE,
@@ -90,6 +92,8 @@ static struct hotplug_slot_ops cpqphp_hotplug_slot_ops = {
.get_attention_status = get_attention_status,
.get_latch_status = get_latch_status,
.get_adapter_status = get_adapter_status,
+ .get_max_bus_speed = get_max_bus_speed,
+ .get_cur_bus_speed = get_cur_bus_speed,
};
@@ -378,7 +382,7 @@ static int ctrl_slot_setup (struct controller * ctrl, void *smbios_start, void *
new_slot->capabilities |= PCISLOT_64_BIT_SUPPORTED;
if (is_slot66mhz(new_slot))
new_slot->capabilities |= PCISLOT_66_MHZ_SUPPORTED;
- if (ctrl->speed == 1)
+ if (ctrl->speed == PCI_SPEED_66MHz)
new_slot->capabilities |= PCISLOT_66_MHZ_OPERATION;
ctrl_slot = slot_device - (readb(ctrl->hpc_reg + SLOT_MASK) >> 4);
@@ -782,6 +786,44 @@ static int get_adapter_status (struct hotplug_slot *hotplug_slot, u8 *value)
return 0;
}
+static int get_max_bus_speed (struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value)
+{
+ struct slot *slot = get_slot (hotplug_slot, __FUNCTION__);
+ struct controller *ctrl;
+
+ if (slot == NULL)
+ return -ENODEV;
+
+ dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
+
+ ctrl = slot->ctrl;
+ if (ctrl == NULL)
+ return -ENODEV;
+
+ *value = ctrl->speed_capability;
+
+ return 0;
+}
+
+static int get_cur_bus_speed (struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value)
+{
+ struct slot *slot = get_slot (hotplug_slot, __FUNCTION__);
+ struct controller *ctrl;
+
+ if (slot == NULL)
+ return -ENODEV;
+
+ dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
+
+ ctrl = slot->ctrl;
+ if (ctrl == NULL)
+ return -ENODEV;
+
+ *value = ctrl->speed;
+
+ return 0;
+}
+
static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
{
u8 num_of_slots = 0;
@@ -853,28 +895,28 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
case PCI_SUB_HPC_ID:
/* Original 6500/7000 implementation */
ctrl->slot_switch_type = 1; // Switch is present
- ctrl->speed_capability = CTRL_SPEED_33MHz;
+ ctrl->speed_capability = PCI_SPEED_33MHz;
ctrl->push_button = 0; // No pushbutton
ctrl->pci_config_space = 1; // Index/data access to working registers 0 = not supported, 1 = supported
- ctrl->defeature_PHP = 1; // PHP is supported
+ ctrl->defeature_PHP = 1; // PHP is supported
ctrl->pcix_support = 0; // PCI-X not supported
- ctrl->pcix_speed_capability = 0; // N/A since PCI-X not supported
+ ctrl->pcix_speed_capability = 0; // N/A since PCI-X not supported
break;
case PCI_SUB_HPC_ID2:
/* First Pushbutton implementation */
ctrl->push_flag = 1;
ctrl->slot_switch_type = 1; // Switch is present
- ctrl->speed_capability = CTRL_SPEED_33MHz;
+ ctrl->speed_capability = PCI_SPEED_33MHz;
ctrl->push_button = 1; // Pushbutton is present
ctrl->pci_config_space = 1; // Index/data access to working registers 0 = not supported, 1 = supported
- ctrl->defeature_PHP = 1; // PHP is supported
+ ctrl->defeature_PHP = 1; // PHP is supported
ctrl->pcix_support = 0; // PCI-X not supported
- ctrl->pcix_speed_capability = 0; // N/A since PCI-X not supported
+ ctrl->pcix_speed_capability = 0; // N/A since PCI-X not supported
break;
case PCI_SUB_HPC_ID_INTC:
/* Third party (6500/7000) */
ctrl->slot_switch_type = 1; // Switch is present
- ctrl->speed_capability = CTRL_SPEED_33MHz;
+ ctrl->speed_capability = PCI_SPEED_33MHz;
ctrl->push_button = 0; // No pushbutton
ctrl->pci_config_space = 1; // Index/data access to working registers 0 = not supported, 1 = supported
ctrl->defeature_PHP = 1; // PHP is supported
@@ -885,7 +927,7 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
/* First 66 Mhz implementation */
ctrl->push_flag = 1;
ctrl->slot_switch_type = 1; // Switch is present
- ctrl->speed_capability = CTRL_SPEED_66MHz;
+ ctrl->speed_capability = PCI_SPEED_66MHz;
ctrl->push_button = 1; // Pushbutton is present
ctrl->pci_config_space = 1; // Index/data access to working registers 0 = not supported, 1 = supported
ctrl->defeature_PHP = 1; // PHP is supported
@@ -903,9 +945,9 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
case PCI_VENDOR_ID_INTEL:
/* Check for speed capability (0=33, 1=66) */
if (subsystem_deviceid & 0x0001) {
- ctrl->speed_capability = CTRL_SPEED_66MHz;
+ ctrl->speed_capability = PCI_SPEED_66MHz;
} else {
- ctrl->speed_capability = CTRL_SPEED_33MHz;
+ ctrl->speed_capability = PCI_SPEED_33MHz;
}
/* Check for push button */
@@ -982,7 +1024,7 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
info("Initializing the PCI hot plug controller residing on PCI bus %d\n", pdev->bus->number);
dbg ("Hotplug controller capabilities:\n");
- dbg (" speed_capability %s\n", ctrl->speed_capability == CTRL_SPEED_33MHz ? "33MHz" : "66Mhz");
+ dbg (" speed_capability %s\n", ctrl->speed_capability == PCI_SPEED_33MHz ? "33MHz" : "66Mhz");
dbg (" slot_switch_type %s\n", ctrl->slot_switch_type == 0 ? "no switch" : "switch present");
dbg (" defeature_PHP %s\n", ctrl->defeature_PHP == 0 ? "PHP not supported" : "PHP supported");
dbg (" alternate_base_address %s\n", ctrl->alternate_base_address == 0 ? "not supported" : "supported");
diff --git a/drivers/hotplug/cpqphp_ctrl.c b/drivers/hotplug/cpqphp_ctrl.c
index e30b88ac17f6..d90f7eaee445 100644
--- a/drivers/hotplug/cpqphp_ctrl.c
+++ b/drivers/hotplug/cpqphp_ctrl.c
@@ -1187,7 +1187,7 @@ static u32 board_replaced(struct pci_func * func, struct controller * ctrl)
//*********************************
rc = CARD_FUNCTIONING;
} else {
- if (ctrl->speed == 1) {
+ if (ctrl->speed == PCI_SPEED_66MHz) {
// Wait for exclusive access to hardware
down(&ctrl->crit_sect);
@@ -1385,7 +1385,7 @@ static u32 board_added(struct pci_func * func, struct controller * ctrl)
dbg("%s: func->device, slot_offset, hp_slot = %d, %d ,%d\n",
__FUNCTION__, func->device, ctrl->slot_device_offset, hp_slot);
- if (ctrl->speed == 1) {
+ if (ctrl->speed == PCI_SPEED_66MHz) {
// Wait for exclusive access to hardware
down(&ctrl->crit_sect);
diff --git a/drivers/hotplug/ibmphp_core.c b/drivers/hotplug/ibmphp_core.c
index 5113d30f93f1..04354bc93a57 100644
--- a/drivers/hotplug/ibmphp_core.c
+++ b/drivers/hotplug/ibmphp_core.c
@@ -384,14 +384,15 @@ static int get_adapter_present (struct hotplug_slot *hotplug_slot, u8 * value)
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 @@ static int get_max_bus_speed (struct hotplug_slot *hotplug_slot, u8 * value)
*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 @@ static int get_cur_bus_speed (struct hotplug_slot *hotplug_slot, u8 * value)
*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 @@ static int get_cur_bus_speed (struct hotplug_slot *hotplug_slot, u8 * value)
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 @@ struct hotplug_slot_ops ibmphp_hotplug_slot_ops = {
.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_cur_bus_speed_status = get_cur_bus_speed,
+ .get_max_bus_speed = get_max_bus_speed,
+ .get_cur_bus_speed = get_cur_bus_speed,
+/* .get_max_adapter_speed = get_max_adapter_speed,
.get_bus_name_status = get_bus_name,
*/
};
diff --git a/drivers/hotplug/pci_hotplug.h b/drivers/hotplug/pci_hotplug.h
index ae13d0c7ee5b..c7cd9e968193 100644
--- a/drivers/hotplug/pci_hotplug.h
+++ b/drivers/hotplug/pci_hotplug.h
@@ -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 @@ struct hotplug_slot_core;
* @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: 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: 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 @@ struct hotplug_slot_ops {
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) (struct hotplug_slot *slot, enum pci_bus_speed *value);
+ int (*get_cur_bus_speed) (struct hotplug_slot *slot, enum pci_bus_speed *value);
};
/**
@@ -85,6 +109,8 @@ struct hotplug_slot_info {
u8 attention_status;
u8 latch_status;
u8 adapter_status;
+ enum pci_bus_speed max_bus_speed;
+ enum pci_bus_speed cur_bus_speed;
};
/**
diff --git a/drivers/hotplug/pci_hotplug_core.c b/drivers/hotplug/pci_hotplug_core.c
index 15bc11a842c8..89e2247acd80 100644
--- a/drivers/hotplug/pci_hotplug_core.c
+++ b/drivers/hotplug/pci_hotplug_core.c
@@ -38,6 +38,8 @@
#include <linux/init.h>
#include <linux/namei.h>
#include <linux/pci.h>
+#include <linux/dnotify.h>
+#include <linux/proc_fs.h>
#include <asm/uaccess.h>
#include "pci_hotplug.h"
@@ -74,6 +76,8 @@ struct hotplug_slot_core {
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 +90,35 @@ static spinlock_t list_lock;
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 */
+};
+
+#ifdef CONFIG_PROC_FS
+extern struct proc_dir_entry *proc_bus_pci_dir;
+static struct proc_dir_entry *slotdir = NULL;
+static const char *slotdir_name = "slots";
+#endif
static struct inode *pcihpfs_get_inode (struct super_block *sb, int mode, int dev)
{
@@ -274,6 +307,24 @@ static struct file_operations presence_file_operations = {
.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,26 +552,28 @@ static void fs_remove_file (struct dentry *dentry)
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 (struct hotplug_slot *slot, type *value) \
{ \
struct hotplug_slot_ops *ops = slot->ops; \
int retval = 0; \
if (ops->owner) \
__MOD_INC_USE_COUNT(ops->owner); \
- if (ops->get_##name##_status) \
- retval = ops->get_##name##_status (slot, value); \
+ if (ops->get_##name) \
+ retval = ops->get_##name (slot, value); \
else \
- *value = slot->info->name##_status; \
+ *value = slot->info->name; \
if (ops->owner) \
__MOD_DEC_USE_COUNT(ops->owner); \
return retval; \
}
-GET_STATUS(power)
-GET_STATUS(attention)
-GET_STATUS(latch)
-GET_STATUS(adapter)
+GET_STATUS(power_status, u8)
+GET_STATUS(attention_status, u8)
+GET_STATUS(latch_status, u8)
+GET_STATUS(adapter_status, 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)
{
@@ -575,7 +628,7 @@ static ssize_t power_write_file (struct file *file, const char *ubuff, size_t co
if (*offset < 0)
return -EINVAL;
- if (count <= 0)
+ if (count == 0 || count > 16384)
return 0;
if (*offset != 0)
return 0;
@@ -686,7 +739,7 @@ static ssize_t attention_write_file (struct file *file, const char *ubuff, size_
if (*offset < 0)
return -EINVAL;
- if (count <= 0)
+ if (count == 0 || count > 16384)
return 0;
if (*offset != 0)
return 0;
@@ -769,7 +822,6 @@ exit:
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 +865,108 @@ exit:
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 (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 (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;
@@ -823,7 +977,7 @@ static ssize_t test_write_file (struct file *file, const char *ubuff, size_t cou
if (*offset < 0)
return -EINVAL;
- if (count <= 0)
+ if (count == 0 || count > 16384)
return 0;
if (*offset != 0)
return 0;
@@ -876,30 +1030,57 @@ static int fs_add_slot (struct hotplug_slot *slot)
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)
+ 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);
}
return 0;
}
@@ -917,6 +1098,10 @@ static void fs_remove_slot (struct hotplug_slot *slot)
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 +1154,7 @@ int pci_hp_register (struct hotplug_slot *slot)
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 +1198,13 @@ int pci_hp_deregister (struct hotplug_slot *slot)
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 +1239,19 @@ int pci_hp_change_slot_info (const char *name, struct hotplug_slot_info *info)
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 != 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);
@@ -1080,6 +1272,11 @@ static int __init pci_hotplug_init (void)
goto exit;
}
+#ifdef CONFIG_PROC_FS
+ /* create mount point for pcihpfs */
+ slotdir = proc_mkdir(slotdir_name, proc_bus_pci_dir);
+#endif
+
info (DRIVER_DESC " version: " DRIVER_VERSION "\n");
exit:
@@ -1089,6 +1286,11 @@ exit:
static void __exit pci_hotplug_exit (void)
{
unregister_filesystem(&pcihpfs_type);
+
+#ifdef CONFIG_PROC_FS
+ if (slotdir)
+ remove_proc_entry(slotdir_name, proc_bus_pci_dir);
+#endif
}
module_init(pci_hotplug_init);
diff --git a/drivers/pci/proc.c b/drivers/pci/proc.c
index 582fac9f16f7..cc72b3a8251d 100644
--- a/drivers/pci/proc.c
+++ b/drivers/pci/proc.c
@@ -371,7 +371,7 @@ static struct seq_operations proc_bus_pci_devices_op = {
show: show_device
};
-static struct proc_dir_entry *proc_bus_pci_dir;
+struct proc_dir_entry *proc_bus_pci_dir;
/* driverfs files */
static ssize_t pci_show_irq(struct device * dev, char * buf, size_t count, loff_t off)
@@ -621,5 +621,6 @@ EXPORT_SYMBOL(pci_proc_attach_device);
EXPORT_SYMBOL(pci_proc_detach_device);
EXPORT_SYMBOL(pci_proc_attach_bus);
EXPORT_SYMBOL(pci_proc_detach_bus);
+EXPORT_SYMBOL(proc_bus_pci_dir);
#endif
diff --git a/kernel/exit.c b/kernel/exit.c
index 6d14cb4d7090..4b051cb290c2 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -610,8 +610,7 @@ NORET_TYPE void do_exit(long code)
if (tsk->pid == 1)
panic("Attempted to kill init!");
tsk->flags |= PF_EXITING;
- if (timer_pending(&tsk->real_timer))
- del_timer_sync(&tsk->real_timer);
+ del_timer_sync(&tsk->real_timer);
if (unlikely(preempt_count()))
printk(KERN_INFO "note: %s[%d] exited with preempt_count %d\n",
diff --git a/kernel/ksyms.c b/kernel/ksyms.c
index 70ea14a87a8a..4dc1840a8b70 100644
--- a/kernel/ksyms.c
+++ b/kernel/ksyms.c
@@ -53,6 +53,7 @@
#include <linux/root_dev.h>
#include <linux/percpu.h>
#include <linux/smp_lock.h>
+#include <linux/dnotify.h>
#include <asm/checksum.h>
#if defined(CONFIG_PROC_FS)
@@ -560,6 +561,7 @@ EXPORT_SYMBOL(buffer_insert_list);
EXPORT_SYMBOL(make_bad_inode);
EXPORT_SYMBOL(is_bad_inode);
EXPORT_SYMBOL(event);
+EXPORT_SYMBOL(__inode_dir_notify);
#ifdef CONFIG_UID16
EXPORT_SYMBOL(overflowuid);