# 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.981 -> 1.982 # drivers/hotplug/cpcihp_zt5550.h 1.1 -> 1.2 # drivers/hotplug/cpci_hotplug.h 1.1 -> 1.2 # drivers/hotplug/pci_hotplug.h 1.4 -> 1.5 # drivers/hotplug/cpci_hotplug_core.c 1.2 -> 1.3 # drivers/hotplug/cpcihp_zt5550.c 1.1 -> 1.2 # drivers/hotplug/cpci_hotplug_pci.c 1.3 -> 1.4 # drivers/hotplug/pci_hotplug_core.c 1.31 -> 1.32 # # The following is the BitKeeper ChangeSet Log # -------------------------------------------- # 03/02/04 rusty@penguin.co.intel.com 1.982 # Adding Scott's latest changes and the sysfs interface for hotplug # -------------------------------------------- # diff -Nru a/drivers/hotplug/cpci_hotplug.h b/drivers/hotplug/cpci_hotplug.h --- a/drivers/hotplug/cpci_hotplug.h Tue Feb 4 13:51:54 2003 +++ b/drivers/hotplug/cpci_hotplug.h Tue Feb 4 13:51:54 2003 @@ -75,7 +75,6 @@ extern int cpci_hp_unregister_controller(struct cpci_hp_controller *controller); extern int cpci_hp_register_bus(struct pci_bus *bus, u8 first, u8 last); extern int cpci_hp_unregister_bus(struct pci_bus *bus); -extern struct slot *cpci_find_slot(struct pci_bus *bus, unsigned int devfn); extern int cpci_hp_start(void); extern int cpci_hp_stop(void); diff -Nru a/drivers/hotplug/cpci_hotplug_core.c b/drivers/hotplug/cpci_hotplug_core.c --- a/drivers/hotplug/cpci_hotplug_core.c Tue Feb 4 13:51:54 2003 +++ b/drivers/hotplug/cpci_hotplug_core.c Tue Feb 4 13:51:54 2003 @@ -417,34 +417,6 @@ return 0; } -struct slot * -cpci_find_slot(struct pci_bus *bus, unsigned int devfn) -{ - struct slot *slot; - struct slot *found; - struct list_head *tmp; - - if(!bus) { - return NULL; - } - - spin_lock(&list_lock); - if(!slots) { - spin_unlock(&list_lock); - return NULL; - } - found = NULL; - list_for_each(tmp, &slot_list) { - slot = list_entry(tmp, struct slot, slot_list); - if(slot->bus == bus && slot->devfn == devfn) { - found = slot; - break; - } - } - spin_unlock(&list_lock); - return found; -} - /* This is the interrupt mode interrupt handler */ void cpci_hp_intr(int irq, void *data, struct pt_regs *regs) @@ -915,6 +887,5 @@ EXPORT_SYMBOL_GPL(cpci_hp_unregister_controller); EXPORT_SYMBOL_GPL(cpci_hp_register_bus); EXPORT_SYMBOL_GPL(cpci_hp_unregister_bus); -EXPORT_SYMBOL_GPL(cpci_find_slot); EXPORT_SYMBOL_GPL(cpci_hp_start); EXPORT_SYMBOL_GPL(cpci_hp_stop); diff -Nru a/drivers/hotplug/cpci_hotplug_pci.c b/drivers/hotplug/cpci_hotplug_pci.c --- a/drivers/hotplug/cpci_hotplug_pci.c Tue Feb 4 13:51:54 2003 +++ b/drivers/hotplug/cpci_hotplug_pci.c Tue Feb 4 13:51:54 2003 @@ -446,7 +446,7 @@ } static int configure_visit_pci_dev(struct pci_dev_wrapped *wrapped_dev, - struct pci_bus_wrapped *wrapped_bus) + struct pci_bus_wrapped *wrapped_bus) { int rc; struct pci_dev *dev = wrapped_dev->dev; @@ -459,8 +459,8 @@ * We need to fix up the hotplug representation with the Linux * representation. */ - slot = cpci_find_slot(dev->bus, dev->devfn); - if(slot) { + if(wrapped_dev->data) { + slot = (struct slot*) wrapped_dev->data; slot->dev = dev; } @@ -482,7 +482,7 @@ } static int unconfigure_visit_pci_dev_phase1(struct pci_dev_wrapped *wrapped_dev, - struct pci_bus_wrapped *wrapped_bus) + struct pci_bus_wrapped *wrapped_bus) { struct pci_dev *dev = wrapped_dev->dev; @@ -525,8 +525,8 @@ /* * Now remove the hotplug representation. */ - slot = cpci_find_slot(dev->bus, dev->devfn); - if(slot) { + if(wrapped_dev->data) { + slot = (struct slot*) wrapped_dev->data; slot->dev = NULL; } else { dbg("No hotplug representation for %02x:%02x.%x", @@ -634,6 +634,10 @@ continue; wrapped_dev.dev = dev; wrapped_bus.bus = slot->dev->bus; + if(i) + wrapped_dev.data = NULL; + else + wrapped_dev.data = (void*) slot; rc = pci_visit_dev(&configure_functions, &wrapped_dev, &wrapped_bus); } } @@ -666,16 +670,21 @@ if(dev) { wrapped_dev.dev = dev; wrapped_bus.bus = dev->bus; + if(i) + wrapped_dev.data = NULL; + else + wrapped_dev.data = (void*) slot; dbg("%s - unconfigure phase 1", __FUNCTION__); rc = pci_visit_dev(&unconfigure_functions_phase1, - &wrapped_dev, &wrapped_bus); - if(rc) { + &wrapped_dev, + &wrapped_bus); + if(rc) break; - } dbg("%s - unconfigure phase 2", __FUNCTION__); rc = pci_visit_dev(&unconfigure_functions_phase2, - &wrapped_dev, &wrapped_bus); + &wrapped_dev, + &wrapped_bus); if(rc) break; } diff -Nru a/drivers/hotplug/cpcihp_zt5550.c b/drivers/hotplug/cpcihp_zt5550.c --- a/drivers/hotplug/cpcihp_zt5550.c Tue Feb 4 13:51:54 2003 +++ b/drivers/hotplug/cpcihp_zt5550.c Tue Feb 4 13:51:54 2003 @@ -38,7 +38,7 @@ #include "cpci_hotplug.h" #include "cpcihp_zt5550.h" -#define DRIVER_VERSION "0.2" +#define DRIVER_VERSION "0.3" #define DRIVER_AUTHOR "Scott Murray " #define DRIVER_DESC "ZT5550 CompactPCI Hot Plug Driver" @@ -64,9 +64,11 @@ static struct cpci_hp_controller_ops zt5550_hpc_ops; static struct cpci_hp_controller zt5550_hpc; -/* Primary cPCI bus bridge device */ -static struct pci_dev *bus0_dev; -static struct pci_bus *bus0; +/* cPCI bus bridge devices */ +static struct pci_dev *bus1_dev; +static struct pci_bus *bus1; +static struct pci_dev *bus2_dev; +static struct pci_bus *bus2; /* Host controller device */ static struct pci_dev *hc_dev; @@ -75,9 +77,11 @@ static void *hc_registers; static void *csr_hc_index; static void *csr_hc_data; -static void *csr_int_status; -static void *csr_int_mask; +static void *csr_intstat; +static void *csr_intmask; +/* Host controller status register */ +static u32 hcf_hcs; static int zt5550_hc_config(struct pci_dev *pdev) { @@ -109,23 +113,28 @@ csr_hc_index = hc_registers + CSR_HCINDEX; csr_hc_data = hc_registers + CSR_HCDATA; - csr_int_status = hc_registers + CSR_INTSTAT; - csr_int_mask = hc_registers + CSR_INTMASK; + csr_intstat = hc_registers + CSR_INTSTAT; + csr_intmask = hc_registers + CSR_INTMASK; + + /* Read Host Control Status register */ + writeb((u8) HCF_HCS, csr_hc_index); + hcf_hcs = readl(csr_hc_data); + info("HCF_HCS = 0x%08x", hcf_hcs); /* * Disable host control, fault and serial interrupts */ dbg("disabling host control, fault and serial interrupts"); - writeb((u8) HC_INT_MASK_REG, csr_hc_index); - writeb((u8) ALL_INDEXED_INTS_MASK, csr_hc_data); + writeb((u8) HCF_HCI, csr_hc_index); + writeb((u8) HCI_ALL_INTS_MASK, csr_hc_data); dbg("disabled host control, fault and serial interrupts"); /* - * Disable timer0, timer1 and ENUM interrupts + * Disable timer0, timer1 and ENUM# interrupts */ - dbg("disabling timer0, timer1 and ENUM interrupts"); - writeb((u8) ALL_DIRECT_INTS_MASK, csr_int_mask); - dbg("disabled timer0, timer1 and ENUM interrupts"); + dbg("disabling timer0, timer1 and ENUM# interrupts"); + writeb((u8) INTMASK_ALL_INTS_MASK, csr_intmask); + dbg("disabled timer0, timer1 and ENUM# interrupts"); return 0; } @@ -153,7 +162,7 @@ ret = 0; if(dev_id == zt5550_hpc.dev_id) { - reg = readb(csr_int_status); + reg = readb(csr_intstat); if(reg) ret = 1; } @@ -167,9 +176,9 @@ if(hc_dev == NULL) { return -ENODEV; } - reg = readb(csr_int_mask); - reg = reg & ~ENUM_INT_MASK; - writeb(reg, csr_int_mask); + reg = readb(csr_intmask); + reg = reg & ~INTMASK_ENUM_INT_MASK; + writeb(reg, csr_intmask); return 0; } @@ -181,16 +190,42 @@ return -ENODEV; } - reg = readb(csr_int_mask); - reg = reg | ENUM_INT_MASK; - writeb(reg, csr_int_mask); + reg = readb(csr_intmask); + reg = reg | INTMASK_ENUM_INT_MASK; + writeb(reg, csr_intmask); return 0; } +static int __devinit zt5550_register_bus(unsigned int slot, + struct pci_dev **dev, + struct pci_bus **bus) +{ + int status; + + /* Look for slot's device */ + if(!(*dev = pci_find_slot(0, PCI_DEVFN(slot, 0)))) { + return -ENODEV; + } + if(!((*dev)->vendor == PCI_VENDOR_ID_DEC && \ + (*dev)->device == PCI_DEVICE_ID_DEC_21154)) { + return -ENODEV; + } + *bus = (*dev)->subordinate; + + status = cpci_hp_register_bus(*bus, 0x0a, 0x0f); + if(status) { + err("could not register cPCI hotplug bus %d", (*bus)->number); + } else { + dbg("registered bus %d", (*bus)->number); + } + return status; +} + static int __devinit zt5550_hc_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) { int status; + struct resource* r; status = zt5550_hc_config(pdev); if(status != 0) { @@ -198,6 +233,10 @@ } dbg("returned from zt5550_hc_config"); + r = request_region(ENUM_PORT, 1, "ENUM# hotswap signal register"); + if(!r) + return -EBUSY; + memset(&zt5550_hpc, 0, sizeof (struct cpci_hp_controller)); zt5550_hpc_ops.query_enum = zt5550_hc_query_enum; zt5550_hpc.ops = &zt5550_hpc_ops; @@ -220,31 +259,30 @@ } dbg("registered controller"); - /* Look for first device matching cPCI bus's bridge vendor and device IDs */ - if(!(bus0_dev = pci_find_device(PCI_VENDOR_ID_DEC, - PCI_DEVICE_ID_DEC_21154, NULL))) { - status = -ENODEV; - goto init_register_error; - } - bus0 = bus0_dev->subordinate; - - status = cpci_hp_register_bus(bus0, 0x0a, 0x0f); - if(status != 0) { - err("could not register cPCI hotplug bus"); - goto init_register_error; + if(hcf_hcs & HCS_BUS1_ACTIVE) { + status = zt5550_register_bus(BUS1_SLOT, &bus1_dev, &bus1); + if(status) + goto init_register_error; + } + if(hcf_hcs & HCS_BUS2_ACTIVE) { + status = zt5550_register_bus(BUS2_SLOT, &bus2_dev, &bus2); + if(status) + goto init_register_error; } - dbg("registered bus"); status = cpci_hp_start(); if(status != 0) { err("could not started cPCI hotplug system"); - cpci_hp_unregister_bus(bus0); goto init_register_error; } - dbg("started cpci hp system"); + dbg("started cPCI hotplug system"); return 0; init_register_error: + if(bus1) + cpci_hp_unregister_bus(bus1); + if(bus2) + cpci_hp_unregister_bus(bus2); cpci_hp_unregister_controller(&zt5550_hpc); init_hc_error: err("status = %d", status); @@ -256,7 +294,10 @@ static void __devexit zt5550_hc_remove_one(struct pci_dev *pdev) { cpci_hp_stop(); - cpci_hp_unregister_bus(bus0); + if(bus1) + cpci_hp_unregister_bus(bus1); + if(bus2) + cpci_hp_unregister_bus(bus2); cpci_hp_unregister_controller(&zt5550_hpc); zt5550_hc_cleanup(); } @@ -277,13 +318,7 @@ static int __init zt5550_init(void) { - struct resource* r; - info(DRIVER_DESC " version: " DRIVER_VERSION); - r = request_region(ENUM_PORT, 1, "#ENUM hotswap signal register"); - if(!r) - return -EBUSY; - return pci_module_init(&zt5550_hc_driver); } @@ -303,4 +338,4 @@ MODULE_PARM(debug, "i"); MODULE_PARM_DESC(debug, "Debugging mode enabled or not"); MODULE_PARM(poll, "i"); -MODULE_PARM_DESC(poll, "#ENUM polling mode enabled or not"); +MODULE_PARM_DESC(poll, "ENUM# polling mode enabled or not"); diff -Nru a/drivers/hotplug/cpcihp_zt5550.h b/drivers/hotplug/cpcihp_zt5550.h --- a/drivers/hotplug/cpcihp_zt5550.h Tue Feb 4 13:51:54 2003 +++ b/drivers/hotplug/cpcihp_zt5550.h Tue Feb 4 13:51:54 2003 @@ -38,38 +38,55 @@ #define CSR_HCDATA 0x04 #define CSR_INTSTAT 0x08 #define CSR_INTMASK 0x09 -#define CSR_CNT0CMD 0x0C -#define CSR_CNT1CMD 0x0E -#define CSR_CNT0 0x10 -#define CSR_CNT1 0x14 +#define CSR_ENET 0x0A +#define CSR_T0_C 0x0C +#define CSR_T1_C 0x0E +#define CSR_TIM0 0x10 +#define CSR_TIM1 0x14 /* Masks for interrupt bits in CSR_INTMASK direct register */ -#define CNT0_INT_MASK 0x01 -#define CNT1_INT_MASK 0x02 -#define ENUM_INT_MASK 0x04 -#define ALL_DIRECT_INTS_MASK 0x07 +#define INTMASK_TIM0_INT_MASK 0x01 +#define INTMASK_TIM1_INT_MASK 0x02 +#define INTMASK_ENUM_INT_MASK 0x04 +#define INTMASK_ALL_INTS_MASK 0x07 -/* Indexed registers (through CSR_INDEX, CSR_DATA) */ -#define HC_INT_MASK_REG 0x04 -#define HC_STATUS_REG 0x08 -#define HC_CMD_REG 0x0C -#define ARB_CONFIG_GNT_REG 0x10 -#define ARB_CONFIG_CFG_REG 0x12 -#define ARB_CONFIG_REG 0x10 -#define ISOL_CONFIG_REG 0x18 -#define FAULT_STATUS_REG 0x20 -#define FAULT_CONFIG_REG 0x24 -#define WD_CONFIG_REG 0x2C -#define HC_DIAG_REG 0x30 -#define SERIAL_COMM_REG 0x34 -#define SERIAL_OUT_REG 0x38 -#define SERIAL_IN_REG 0x3C +/* Indexed registers (through CSR_HCINDEX, CSR_HCDATA) */ +#define HCF_HCI 0x04 +#define HCF_HCS 0x08 +#define HCF_HCC 0x0C +#define HCF_ARBC 0x10 +#define HCF_ISOC 0x18 +#define HCF_FLTS 0x20 +#define HCF_FLTC 0x24 +#define HCF_PMCC 0x28 +#define HCF_WDC 0x2C +#define HCF_DIAG 0x30 +#define HCF_SERC 0x34 +#define HCF_SDO 0x38 +#define HCF_SDI 0x3C -/* Masks for interrupt bits in HC_INT_MASK_REG indexed register */ -#define SERIAL_INT_MASK 0x01 -#define FAULT_INT_MASK 0x02 -#define HCF_INT_MASK 0x04 -#define ALL_INDEXED_INTS_MASK 0x07 +/* Masks for interrupt bits in HCF_HCI indexed register */ +#define HCI_SERIAL_INT_MASK 0x01 +#define HCI_FAULT_INT_MASK 0x02 +#define HCI_HCF_INT_MASK 0x04 +#define HCI_ALL_INTS_MASK 0x07 + +/* Masks for the bits in the HCF_HCS indexed register */ +#define HCS_HA 0x00000001 +#define HCS_ACTIVE 0x00000002 +#define HCS_RH_STATE 0x00000004 +#define HCS_HARD_RESET 0x00000008 +#define HCS_SOFT_RESET 0x00000010 +#define HCS_RH_ALIVE 0x00000020 +#define HCS_SWITCH_OVER 0x00000040 +#define HCS_TAKEOVER_TYPE 0x00000080 +#define HCS_BUS1_ACTIVE 0x00000100 +#define HCS_BUS2_ACTIVE 0x00000200 +#define HCS_SPLIT_MODE_ERROR 0x00000400 + +/* CompactPCI bus segment device slot numbers */ +#define BUS1_SLOT 0x08 +#define BUS2_SLOT 0x0C /* Digital I/O port storing ENUM# */ #define ENUM_PORT 0xE1 diff -Nru a/drivers/hotplug/pci_hotplug.h b/drivers/hotplug/pci_hotplug.h --- a/drivers/hotplug/pci_hotplug.h Tue Feb 4 13:51:54 2003 +++ b/drivers/hotplug/pci_hotplug.h Tue Feb 4 13:51:54 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 Tue Feb 4 13:51:54 2003 +++ b/drivers/hotplug/pci_hotplug_core.c Tue Feb 4 13:51:54 2003 @@ -40,8 +40,9 @@ #include #include #include -#include #include +#include +#include #include "pci_hotplug.h" @@ -67,29 +68,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[] = { @@ -115,12 +130,6 @@ "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 - #ifdef CONFIG_HOTPLUG_PCI_CPCI extern int cpci_hotplug_init(int debug); extern void cpci_hotplug_exit(void); @@ -129,438 +138,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 +161,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 +207,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 +252,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 +318,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 +344,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 +375,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); - remove_mount(); + if (slot->ops->get_max_bus_speed) + sysfs_remove_file(&slot->kobj, &hotplug_slot_attr_max_bus_speed.attr); + + 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 +464,6 @@ */ int pci_hp_register (struct hotplug_slot *slot) { - struct hotplug_slot_core *core; int result; if (slot == NULL) @@ -1146,21 +471,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 +522,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 @@ -1224,7 +540,6 @@ 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; @@ -1240,22 +555,16 @@ * 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); + if (temp->info->power_status != info->power_status) + inode_dir_notify(temp->kobj.dentry->d_inode, DN_MODIFY); + if (temp->info->attention_status != info->attention_status) + inode_dir_notify(temp->kobj.dentry->d_inode, DN_MODIFY); + if (temp->info->latch_status != info->latch_status) + inode_dir_notify(temp->kobj.dentry->d_inode, DN_MODIFY); + if (temp->info->adapter_status != info->adapter_status) + inode_dir_notify(temp->kobj.dentry->d_inode, DN_MODIFY); + if (temp->info->cur_bus_speed != info->cur_bus_speed) + inode_dir_notify(temp->kobj.dentry->d_inode, DN_MODIFY); memcpy (temp->info, info, sizeof (struct hotplug_slot_info)); spin_unlock (&list_lock); @@ -1266,32 +575,25 @@ { 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 - /* create mount point for pcihpfs */ - slotdir = proc_mkdir(slotdir_name, proc_bus_pci_dir); -#endif - 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; } @@ -1299,13 +601,7 @@ 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 + subsystem_unregister(&hotplug_slots_subsys); } module_init(pci_hotplug_init); @@ -1320,4 +616,3 @@ EXPORT_SYMBOL_GPL(pci_hp_register); EXPORT_SYMBOL_GPL(pci_hp_deregister); EXPORT_SYMBOL_GPL(pci_hp_change_slot_info); -