diff options
author | Linus Torvalds <torvalds@g5.osdl.org> | 2005-10-28 15:57:32 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2005-10-28 15:57:32 -0700 |
commit | 7efe5d7c3e3a82e43b0f8fb29c6797317bce7a9a (patch) | |
tree | 2e246004dfc130947574e340a4968239b3f2d20b | |
parent | dbe0580d0d2fccf63b0349840a7ae3dbb16f3074 (diff) | |
parent | f8977d0a9b7ac84cfe700278a2ca64cb33c93a13 (diff) |
Merge master.kernel.org:/pub/scm/linux/kernel/git/gregkh/pci-2.6
37 files changed, 739 insertions, 6349 deletions
diff --git a/Documentation/DocBook/kernel-api.tmpl b/Documentation/DocBook/kernel-api.tmpl index d650ce36485..4d9b66d8b4d 100644 --- a/Documentation/DocBook/kernel-api.tmpl +++ b/Documentation/DocBook/kernel-api.tmpl @@ -286,7 +286,9 @@ X!Edrivers/pci/search.c --> !Edrivers/pci/msi.c !Edrivers/pci/bus.c -!Edrivers/pci/hotplug.c +<!-- FIXME: Removed for now since no structured comments in source +X!Edrivers/pci/hotplug.c +--> !Edrivers/pci/probe.c !Edrivers/pci/rom.c </sect1> diff --git a/arch/i386/pci/fixup.c b/arch/i386/pci/fixup.c index 8e8e895e1b5..330fd2b6807 100644 --- a/arch/i386/pci/fixup.c +++ b/arch/i386/pci/fixup.c @@ -2,6 +2,8 @@ * Exceptions for specific devices. Usually work-arounds for fatal design flaws. */ +#include <linux/delay.h> +#include <linux/dmi.h> #include <linux/pci.h> #include <linux/init.h> #include "pci.h" @@ -384,3 +386,60 @@ static void __devinit pci_fixup_video(struct pci_dev *pdev) } } DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pci_fixup_video); + +/* + * Some Toshiba laptops need extra code to enable their TI TSB43AB22/A. + * + * We pretend to bring them out of full D3 state, and restore the proper + * IRQ, PCI cache line size, and BARs, otherwise the device won't function + * properly. In some cases, the device will generate an interrupt on + * the wrong IRQ line, causing any devices sharing the the line it's + * *supposed* to use to be disabled by the kernel's IRQ debug code. + */ +static u16 toshiba_line_size; + +static struct dmi_system_id __devinit toshiba_ohci1394_dmi_table[] = { + { + .ident = "Toshiba PS5 based laptop", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), + DMI_MATCH(DMI_PRODUCT_VERSION, "PS5"), + }, + }, + { + .ident = "Toshiba PSM4 based laptop", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), + DMI_MATCH(DMI_PRODUCT_VERSION, "PSM4"), + }, + }, + { } +}; + +static void __devinit pci_pre_fixup_toshiba_ohci1394(struct pci_dev *dev) +{ + if (!dmi_check_system(toshiba_ohci1394_dmi_table)) + return; /* only applies to certain Toshibas (so far) */ + + dev->current_state = PCI_D3cold; + pci_read_config_word(dev, PCI_CACHE_LINE_SIZE, &toshiba_line_size); +} +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_TI, 0x8032, + pci_pre_fixup_toshiba_ohci1394); + +static void __devinit pci_post_fixup_toshiba_ohci1394(struct pci_dev *dev) +{ + if (!dmi_check_system(toshiba_ohci1394_dmi_table)) + return; /* only applies to certain Toshibas (so far) */ + + /* Restore config space on Toshiba laptops */ + mdelay(10); + pci_write_config_word(dev, PCI_CACHE_LINE_SIZE, toshiba_line_size); + pci_write_config_word(dev, PCI_INTERRUPT_LINE, dev->irq); + pci_write_config_dword(dev, PCI_BASE_ADDRESS_0, + pci_resource_start(dev, 0)); + pci_write_config_dword(dev, PCI_BASE_ADDRESS_1, + pci_resource_start(dev, 1)); +} +DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_TI, 0x8032, + pci_post_fixup_toshiba_ohci1394); diff --git a/drivers/pci/access.c b/drivers/pci/access.c index 24a76de49f4..2a42add7f56 100644 --- a/drivers/pci/access.c +++ b/drivers/pci/access.c @@ -60,3 +60,92 @@ EXPORT_SYMBOL(pci_bus_read_config_dword); EXPORT_SYMBOL(pci_bus_write_config_byte); EXPORT_SYMBOL(pci_bus_write_config_word); EXPORT_SYMBOL(pci_bus_write_config_dword); + +static u32 pci_user_cached_config(struct pci_dev *dev, int pos) +{ + u32 data; + + data = dev->saved_config_space[pos/sizeof(dev->saved_config_space[0])]; + data >>= (pos % sizeof(dev->saved_config_space[0])) * 8; + return data; +} + +#define PCI_USER_READ_CONFIG(size,type) \ +int pci_user_read_config_##size \ + (struct pci_dev *dev, int pos, type *val) \ +{ \ + unsigned long flags; \ + int ret = 0; \ + u32 data = -1; \ + if (PCI_##size##_BAD) return PCIBIOS_BAD_REGISTER_NUMBER; \ + spin_lock_irqsave(&pci_lock, flags); \ + if (likely(!dev->block_ucfg_access)) \ + ret = dev->bus->ops->read(dev->bus, dev->devfn, \ + pos, sizeof(type), &data); \ + else if (pos < sizeof(dev->saved_config_space)) \ + data = pci_user_cached_config(dev, pos); \ + spin_unlock_irqrestore(&pci_lock, flags); \ + *val = (type)data; \ + return ret; \ +} + +#define PCI_USER_WRITE_CONFIG(size,type) \ +int pci_user_write_config_##size \ + (struct pci_dev *dev, int pos, type val) \ +{ \ + unsigned long flags; \ + int ret = -EIO; \ + if (PCI_##size##_BAD) return PCIBIOS_BAD_REGISTER_NUMBER; \ + spin_lock_irqsave(&pci_lock, flags); \ + if (likely(!dev->block_ucfg_access)) \ + ret = dev->bus->ops->write(dev->bus, dev->devfn, \ + pos, sizeof(type), val); \ + spin_unlock_irqrestore(&pci_lock, flags); \ + return ret; \ +} + +PCI_USER_READ_CONFIG(byte, u8) +PCI_USER_READ_CONFIG(word, u16) +PCI_USER_READ_CONFIG(dword, u32) +PCI_USER_WRITE_CONFIG(byte, u8) +PCI_USER_WRITE_CONFIG(word, u16) +PCI_USER_WRITE_CONFIG(dword, u32) + +/** + * pci_block_user_cfg_access - Block userspace PCI config reads/writes + * @dev: pci device struct + * + * This function blocks any userspace PCI config accesses from occurring. + * When blocked, any writes will be bit bucketed and reads will return the + * data saved using pci_save_state for the first 64 bytes of config + * space and return 0xff for all other config reads. + **/ +void pci_block_user_cfg_access(struct pci_dev *dev) +{ + unsigned long flags; + + pci_save_state(dev); + + /* spinlock to synchronize with anyone reading config space now */ + spin_lock_irqsave(&pci_lock, flags); + dev->block_ucfg_access = 1; + spin_unlock_irqrestore(&pci_lock, flags); +} +EXPORT_SYMBOL_GPL(pci_block_user_cfg_access); + +/** + * pci_unblock_user_cfg_access - Unblock userspace PCI config reads/writes + * @dev: pci device struct + * + * This function allows userspace PCI config accesses to resume. + **/ +void pci_unblock_user_cfg_access(struct pci_dev *dev) +{ + unsigned long flags; + + /* spinlock to synchronize with anyone reading saved config space */ + spin_lock_irqsave(&pci_lock, flags); + dev->block_ucfg_access = 0; + spin_unlock_irqrestore(&pci_lock, flags); +} +EXPORT_SYMBOL_GPL(pci_unblock_user_cfg_access); diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index 424e7de181a..8e21f6ab89a 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c @@ -58,6 +58,9 @@ static LIST_HEAD(bridge_list); static void handle_hotplug_event_bridge (acpi_handle, u32, void *); static void handle_hotplug_event_func (acpi_handle, u32, void *); +static void acpiphp_sanitize_bus(struct pci_bus *bus); +static void acpiphp_set_hpp_values(acpi_handle handle, struct pci_bus *bus); + /* * initialization & terminatation routines @@ -796,8 +799,13 @@ static int enable_device(struct acpiphp_slot *slot) } } + pci_bus_size_bridges(bus); pci_bus_assign_resources(bus); + acpiphp_sanitize_bus(bus); + pci_enable_bridges(bus); pci_bus_add_devices(bus); + acpiphp_set_hpp_values(DEVICE_ACPI_HANDLE(&bus->self->dev), bus); + acpiphp_configure_ioapics(DEVICE_ACPI_HANDLE(&bus->self->dev)); /* associate pci_dev to our representation */ list_for_each (l, &slot->funcs) { diff --git a/drivers/pci/hotplug/cpcihp_zt5550.c b/drivers/pci/hotplug/cpcihp_zt5550.c index e9928024be7..790abadd816 100644 --- a/drivers/pci/hotplug/cpcihp_zt5550.c +++ b/drivers/pci/hotplug/cpcihp_zt5550.c @@ -78,11 +78,20 @@ static void __iomem *csr_int_mask; static int zt5550_hc_config(struct pci_dev *pdev) { + int ret; + /* Since we know that no boards exist with two HC chips, treat it as an error */ if(hc_dev) { err("too many host controller devices?"); return -EBUSY; } + + ret = pci_enable_device(pdev); + if(ret) { + err("cannot enable %s\n", pci_name(pdev)); + return ret; + } + hc_dev = pdev; dbg("hc_dev = %p", hc_dev); dbg("pci resource start %lx", pci_resource_start(hc_dev, 1)); @@ -91,7 +100,8 @@ static int zt5550_hc_config(struct pci_dev *pdev) if(!request_mem_region(pci_resource_start(hc_dev, 1), pci_resource_len(hc_dev, 1), MY_NAME)) { err("cannot reserve MMIO region"); - return -ENOMEM; + ret = -ENOMEM; + goto exit_disable_device; } hc_registers = @@ -99,9 +109,8 @@ static int zt5550_hc_config(struct pci_dev *pdev) if(!hc_registers) { err("cannot remap MMIO region %lx @ %lx", pci_resource_len(hc_dev, 1), pci_resource_start(hc_dev, 1)); - release_mem_region(pci_resource_start(hc_dev, 1), - pci_resource_len(hc_dev, 1)); - return -ENODEV; + ret = -ENODEV; + goto exit_release_region; } csr_hc_index = hc_registers + CSR_HCINDEX; @@ -124,6 +133,13 @@ static int zt5550_hc_config(struct pci_dev *pdev) writeb((u8) ALL_DIRECT_INTS_MASK, csr_int_mask); dbg("disabled timer0, timer1 and ENUM interrupts"); return 0; + +exit_release_region: + release_mem_region(pci_resource_start(hc_dev, 1), + pci_resource_len(hc_dev, 1)); +exit_disable_device: + pci_disable_device(hc_dev); + return ret; } static int zt5550_hc_cleanup(void) @@ -134,6 +150,7 @@ static int zt5550_hc_cleanup(void) iounmap(hc_registers); release_mem_region(pci_resource_start(hc_dev, 1), pci_resource_len(hc_dev, 1)); + pci_disable_device(hc_dev); return 0; } diff --git a/drivers/pci/hotplug/cpqphp_core.c b/drivers/pci/hotplug/cpqphp_core.c index 8c6d3987d46..9aed8efe6a1 100644 --- a/drivers/pci/hotplug/cpqphp_core.c +++ b/drivers/pci/hotplug/cpqphp_core.c @@ -794,12 +794,21 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) u32 rc; struct controller *ctrl; struct pci_func *func; + int err; + + err = pci_enable_device(pdev); + if (err) { + printk(KERN_ERR MY_NAME ": cannot enable PCI device %s (%d)\n", + pci_name(pdev), err); + return err; + } // Need to read VID early b/c it's used to differentiate CPQ and INTC discovery rc = pci_read_config_word(pdev, PCI_VENDOR_ID, &vendor_id); if (rc || ((vendor_id != PCI_VENDOR_ID_COMPAQ) && (vendor_id != PCI_VENDOR_ID_INTEL))) { err(msg_HPC_non_compaq_or_intel); - return -ENODEV; + rc = -ENODEV; + goto err_disable_device; } dbg("Vendor ID: %x\n", vendor_id); @@ -807,7 +816,8 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) dbg("revision: %d\n", rev); if (rc || ((vendor_id == PCI_VENDOR_ID_COMPAQ) && (!rev))) { err(msg_HPC_rev_error); - return -ENODEV; + rc = -ENODEV; + goto err_disable_device; } /* Check for the proper subsytem ID's @@ -820,18 +830,20 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) rc = pci_read_config_word(pdev, PCI_SUBSYSTEM_VENDOR_ID, &subsystem_vid); if (rc) { err("%s : pci_read_config_word failed\n", __FUNCTION__); - return rc; + goto err_disable_device; } dbg("Subsystem Vendor ID: %x\n", subsystem_vid); if ((subsystem_vid != PCI_VENDOR_ID_COMPAQ) && (subsystem_vid != PCI_VENDOR_ID_INTEL)) { err(msg_HPC_non_compaq_or_intel); - return -ENODEV; + rc = -ENODEV; + goto err_disable_device; } ctrl = (struct controller *) kmalloc(sizeof(struct controller), GFP_KERNEL); if (!ctrl) { err("%s : out of memory\n", __FUNCTION__); - return -ENOMEM; + rc = -ENOMEM; + goto err_disable_device; } memset(ctrl, 0, sizeof(struct controller)); @@ -1264,6 +1276,8 @@ err_free_bus: kfree(ctrl->pci_bus); err_free_ctrl: kfree(ctrl); +err_disable_device: + pci_disable_device(pdev); return rc; } diff --git a/drivers/pci/hotplug/rpaphp.h b/drivers/pci/hotplug/rpaphp.h index 61d94d1e29c..71ea5f9bb28 100644 --- a/drivers/pci/hotplug/rpaphp.h +++ b/drivers/pci/hotplug/rpaphp.h @@ -92,9 +92,10 @@ extern struct pci_bus *rpaphp_find_pci_bus(struct device_node *dn); extern int rpaphp_claim_resource(struct pci_dev *dev, int resource); extern int rpaphp_enable_pci_slot(struct slot *slot); extern int register_pci_slot(struct slot *slot); -extern int rpaphp_unconfig_pci_adapter(struct slot *slot); extern int rpaphp_get_pci_adapter_status(struct slot *slot, int is_init, u8 * value); + extern int rpaphp_config_pci_adapter(struct pci_bus *bus); +extern int rpaphp_unconfig_pci_adapter(struct pci_bus *bus); /* rpaphp_core.c */ extern int rpaphp_add_slot(struct device_node *dn); diff --git a/drivers/pci/hotplug/rpaphp_core.c b/drivers/pci/hotplug/rpaphp_core.c index c830ff0acdc..cf075c34b57 100644 --- a/drivers/pci/hotplug/rpaphp_core.c +++ b/drivers/pci/hotplug/rpaphp_core.c @@ -426,8 +426,11 @@ static int disable_slot(struct hotplug_slot *hotplug_slot) dbg("DISABLING SLOT %s\n", slot->name); down(&rpaphp_sem); - retval = rpaphp_unconfig_pci_adapter(slot); + retval = rpaphp_unconfig_pci_adapter(slot->bus); up(&rpaphp_sem); + slot->state = NOT_CONFIGURED; + info("%s: devices in slot[%s] unconfigured.\n", __FUNCTION__, + slot->name); exit: dbg("%s - Exit: rc[%d]\n", __FUNCTION__, retval); return retval; diff --git a/drivers/pci/hotplug/rpaphp_pci.c b/drivers/pci/hotplug/rpaphp_pci.c index 49e4d10a648..46c157d26a2 100644 --- a/drivers/pci/hotplug/rpaphp_pci.c +++ b/drivers/pci/hotplug/rpaphp_pci.c @@ -319,20 +319,15 @@ static void rpaphp_eeh_remove_bus_device(struct pci_dev *dev) return; } -int rpaphp_unconfig_pci_adapter(struct slot *slot) +int rpaphp_unconfig_pci_adapter(struct pci_bus *bus) { struct pci_dev *dev, *tmp; - int retval = 0; - list_for_each_entry_safe(dev, tmp, slot->pci_devs, bus_list) { + list_for_each_entry_safe(dev, tmp, &bus->devices, bus_list) { rpaphp_eeh_remove_bus_device(dev); pci_remove_bus_device(dev); } - - slot->state = NOT_CONFIGURED; - info("%s: devices in slot[%s] unconfigured.\n", __FUNCTION__, - slot->name); - return retval; + return 0; } static int setup_pci_hotplug_slot_info(struct slot *slot) diff --git a/drivers/pci/hotplug/shpchp.h b/drivers/pci/hotplug/shpchp.h index b7d1c61d6bb..abe2cf411e6 100644 --- a/drivers/pci/hotplug/shpchp.h +++ b/drivers/pci/hotplug/shpchp.h @@ -32,8 +32,6 @@ #include <linux/types.h> #include <linux/pci.h> #include <linux/delay.h> -#include <asm/semaphore.h> -#include <asm/io.h> #include "pci_hotplug.h" #if !defined(MODULE) @@ -52,42 +50,18 @@ extern int shpchp_debug; #define info(format, arg...) printk(KERN_INFO "%s: " format, MY_NAME , ## arg) #define warn(format, arg...) printk(KERN_WARNING "%s: " format, MY_NAME , ## arg) -struct pci_func { - struct pci_func *next; - u8 bus; - u8 device; - u8 function; - u8 is_a_board; - u16 status; - u8 configured; - u8 switch_save; - u8 presence_save; - u8 pwr_save; - u32 base_length[0x06]; - u8 base_type[0x06]; - u16 reserved2; - u32 config_space[0x20]; - struct pci_resource *mem_head; - struct pci_resource *p_mem_head; - struct pci_resource *io_head; - struct pci_resource *bus_head; - struct pci_dev* pci_dev; -}; - #define SLOT_MAGIC 0x67267321 struct slot { u32 magic; struct slot *next; u8 bus; u8 device; + u16 status; u32 number; u8 is_a_board; - u8 configured; u8 state; - u8 switch_save; u8 presence_save; - u32 capabilities; - u16 reserved2; + u8 pwr_save; struct timer_list task_event; u8 hp_slot; struct controller *ctrl; @@ -96,12 +70,6 @@ struct slot { struct list_head slot_list; }; -struct pci_resource { - struct pci_resource * next; - u32 base; - u32 length; -}; - struct event_info { u32 event_type; u8 hp_slot; @@ -110,13 +78,9 @@ struct event_info { struct controller { struct controller *next; struct semaphore crit_sect; /* critical section semaphore */ - void * hpc_ctlr_handle; /* HPC controller handle */ + struct php_ctlr_state_s *hpc_ctlr_handle; /* HPC controller handle */ int num_slots; /* Number of slots on ctlr */ int slot_num_inc; /* 1 or -1 */ - struct pci_resource *mem_head; - struct pci_resource *p_mem_head; - struct pci_resource *io_head; - struct pci_resource *bus_head; struct pci_dev *pci_dev; struct pci_bus *pci_bus; struct event_info event_queue[10]; @@ -124,33 +88,21 @@ struct controller { struct hpc_ops *hpc_ops; wait_queue_head_t queue; /* sleep & wake process */ u8 next_event; - u8 seg; u8 bus; u8 device; u8 function; - u8 rev; u8 slot_device_offset; u8 add_support; enum pci_bus_speed speed; u32 first_slot; /* First physical slot number */ u8 slot_bus; /* Bus where the slots handled by this controller sit */ - u8 push_flag; - u16 ctlrcap; - u16 vendor_id; -}; - -struct irq_mapping { - u8 barber_pole; - u8 valid_INT; - u8 interrupt[4]; }; -struct resource_lists { - struct pci_resource *mem_head; - struct pci_resource *p_mem_head; - struct pci_resource *io_head; - struct pci_resource *bus_head; - struct irq_mapping *irqs; +struct hotplug_params { + u8 cache_line_size; + u8 latency_timer; + u8 enable_serr; + u8 enable_perr; }; /* Define AMD SHPC ID */ @@ -194,24 +146,16 @@ struct resource_lists { * error Messages */ #define msg_initialization_err "Initialization failure, error=%d\n" -#define msg_HPC_rev_error "Unsupported revision of the PCI hot plug controller found.\n" -#define msg_HPC_non_shpc "The PCI hot plug controller is not supported by this driver.\n" -#define msg_HPC_not_supported "This system is not supported by this version of shpcphd mdoule. Upgrade to a newer version of shpchpd\n" -#define msg_unable_to_save "Unable to store PCI hot plug add resource information. This system must be rebooted before adding any PCI devices.\n" #define msg_button_on "PCI slot #%d - powering on due to button press.\n" #define msg_button_off "PCI slot #%d - powering off due to button press.\n" #define msg_button_cancel "PCI slot #%d - action canceled due to button press.\n" -#define msg_button_ignore "PCI slot #%d - button press ignored. (action in progress...)\n" /* sysfs functions for the hotplug controller info */ extern void shpchp_create_ctrl_files (struct controller *ctrl); /* controller functions */ -extern int shpchprm_find_available_resources(struct controller *ctrl); extern int shpchp_event_start_thread(void); extern void shpchp_event_stop_thread(void); -extern struct pci_func *shpchp_slot_create(unsigned char busnumber); -extern struct pci_func *shpchp_slot_find(unsigned char bus, unsigned char device, unsigned char index); extern int shpchp_enable_slot(struct slot *slot); extern int shpchp_disable_slot(struct slot *slot); @@ -220,29 +164,20 @@ extern u8 shpchp_handle_switch_change(u8 hp_slot, void *inst_id); extern u8 shpchp_handle_presence_change(u8 hp_slot, void *inst_id); extern u8 shpchp_handle_power_fault(u8 hp_slot, void *inst_id); -/* resource functions */ -extern int shpchp_resource_sort_and_combine(struct pci_resource **head); - /* pci functions */ -extern int shpchp_set_irq(u8 bus_num, u8 dev_num, u8 int_pin, u8 irq_num); -/*extern int shpchp_get_bus_dev(struct controller *ctrl, u8 *bus_num, u8 *dev_num, struct slot *slot);*/ extern int shpchp_save_config(struct controller *ctrl, int busnumber, int num_ctlr_slots, int first_device_num); -extern int shpchp_save_used_resources(struct controller *ctrl, struct pci_func * func, int flag); -extern int shpchp_save_slot_config(struct controller *ctrl, struct pci_func * new_slot); -extern void shpchp_destroy_board_resources(struct pci_func * func); -extern int shpchp_return_board_resources(struct pci_func * func, struct resource_lists * resources); -extern void shpchp_destroy_resource_list(struct resource_lists * resources); -extern int shpchp_configure_device(struct controller* ctrl, struct pci_func* func); -extern int shpchp_unconfigure_device(struct pci_func* func); +extern int shpchp_configure_device(struct slot *p_slot); +extern int shpchp_unconfigure_device(struct slot *p_slot); +extern void get_hp_hw_control_from_firmware(struct pci_dev *dev); +extern void get_hp_params_from_firmware(struct pci_dev *dev, + struct hotplug_params *hpp); +extern int shpchprm_get_physical_slot_number(struct controller *ctrl, + u32 *sun, u8 busnum, u8 devnum); +extern void shpchp_remove_ctrl_files(struct controller *ctrl); /* Global variables */ extern struct controller *shpchp_ctrl_list; -extern struct pci_func *shpchp_slot_list[256]; - -/* These are added to support AMD shpc */ -extern u8 shpchp_nic_irq; -extern u8 shpchp_disk_irq; struct ctrl_reg { volatile u32 base_offset; @@ -298,7 +233,7 @@ enum ctrl_offsets { SLOT11 = offsetof(struct ctrl_reg, slot11), SLOT12 = offsetof(struct ctrl_reg, slot12), }; -typedef u8(*php_intr_callback_t) (unsigned int change_id, void *instance_id); +typedef u8(*php_intr_callback_t) (u8 hp_slot, void *instance_id); struct php_ctlr_state_s { struct php_ctlr_state_s *pnext; struct pci_dev *pci_dev; @@ -359,12 +294,9 @@ static inline struct slot *shpchp_find_slot (struct controller *ctrl, u8 device) p_slot = ctrl->slot; - dbg("p_slot = %p\n", p_slot); - while (p_slot && (p_slot->device != device)) { tmp_slot = p_slot; p_slot = p_slot->next; - dbg("In while loop, p_slot = %p\n", p_slot); } if (p_slot == NULL) { err("ERROR: shpchp_find_slot device=0x%x\n", device); @@ -379,8 +311,6 @@ static inline int wait_for_ctrl_irq (struct controller *ctrl) DECLARE_WAITQUEUE(wait, current); int retval = 0; - dbg("%s : start\n",__FUNCTION__); - add_wait_queue(&ctrl->queue, &wait); if (!shpchp_poll_mode) { @@ -394,19 +324,9 @@ static inline int wait_for_ctrl_irq (struct controller *ctrl) if (signal_pending(current)) retval = -EINTR; - dbg("%s : end\n", __FUNCTION__); return retval; } -/* Puts node back in the resource list pointed to by head */ -static inline void return_resource(struct pci_resource **head, struct pci_resource *node) -{ - if (!node || !head) - return; - node->next = *head; - *head = node; -} - #define SLOT_NAME_SIZE 10 static inline void make_slot_name(char *buffer, int buffer_size, struct slot *slot) @@ -420,11 +340,7 @@ enum php_ctlr_type { ACPI }; -int shpc_init( struct controller *ctrl, struct pci_dev *pdev, - php_intr_callback_t attention_button_callback, - php_intr_callback_t switch_change_callback, - php_intr_callback_t presence_change_callback, - php_intr_callback_t power_fault_callback); +int shpc_init( struct controller *ctrl, struct pci_dev *pdev); int shpc_get_ctlr_slot_config( struct controller *ctrl, int *num_ctlr_slots, @@ -437,8 +353,6 @@ struct hpc_ops { int (*power_on_slot ) (struct slot *slot); int (*slot_enable ) (struct slot *slot); int (*slot_disable ) (struct slot *slot); - int (*enable_all_slots) (struct slot *slot); - int (*pwr_on_all_slots) (struct slot *slot); int (*set_bus_speed_mode) (struct slot *slot, enum pci_bus_speed speed); int (*get_power_status) (struct slot *slot, u8 *status); int (*get_attention_status) (struct slot *slot, u8 *status); diff --git a/drivers/pci/hotplug/shpchp_core.c b/drivers/pci/hotplug/shpchp_core.c index 6f7d8a29957..63628e01dd4 100644 --- a/drivers/pci/hotplug/shpchp_core.c +++ b/drivers/pci/hotplug/shpchp_core.c @@ -27,26 +27,18 @@ * */ -#include <linux/config.h> #include <linux/module.h> #include <linux/moduleparam.h> #include <linux/kernel.h> #include <linux/types.h> -#include <linux/proc_fs.h> -#include <linux/slab.h> -#include <linux/workqueue.h> #include <linux/pci.h> -#include <linux/init.h> -#include <asm/uaccess.h> #include "shpchp.h" -#include "shpchprm.h" /* Global variables */ int shpchp_debug; int shpchp_poll_mode; int shpchp_poll_time; struct controller *shpchp_ctrl_list; /* = NULL */ -struct pci_func *shpchp_slot_list[256]; #define DRIVER_VERSION "0.4" #define DRIVER_AUTHOR "Dan Zink <dan.zink@compaq.com>, Greg Kroah-Hartman <greg@kroah.com>, Dely Sy <dely.l.sy@intel.com>" @@ -113,8 +105,6 @@ static int init_slots(struct controller *ctrl) u32 slot_number, sun; int result = -ENOMEM; - dbg("%s\n",__FUNCTION__); - number_of_slots = ctrl->num_slots; slot_device = ctrl->slot_device_offset; slot_number = ctrl->first_slot; @@ -352,6 +342,17 @@ static int get_cur_bus_speed (struct hotplug_slot *hotplug_slot, enum pci_bus_sp return 0; } +static int is_shpc_capable(struct pci_dev *dev) +{ + if ((dev->vendor == PCI_VENDOR_ID_AMD) || (dev->device == + PCI_DEVICE_ID_AMD_GOLAM_7450)) + return 1; + if (pci_find_capability(dev, PCI_CAP_ID_SHPC)) + return 1; + + return 0; +} + static int shpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { int rc; @@ -360,6 +361,9 @@ static int shpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) int first_device_num; /* first PCI device number supported by this SHPC */ int num_ctlr_slots; /* number of slots supported by this SHPC */ + if (!is_shpc_capable(pdev)) + return -ENODEV; + ctrl = (struct controller *) kmalloc(sizeof(struct controller), GFP_KERNEL); if (!ctrl) { err("%s : out of memory\n", __FUNCTION__); @@ -367,19 +371,12 @@ static int shpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) } memset(ctrl, 0, sizeof(struct controller)); - dbg("DRV_thread pid = %d\n", current->pid); - - rc = shpc_init(ctrl, pdev, - (php_intr_callback_t) shpchp_handle_attention_button, - (php_intr_callback_t) shpchp_handle_switch_change, - (php_intr_callback_t) shpchp_handle_presence_change, - (php_intr_callback_t) shpchp_handle_power_fault); + rc = shpc_init(ctrl, pdev); if (rc) { dbg("%s: controller initialization failed\n", SHPC_MODULE_NAME); goto err_out_free_ctrl; } - dbg("%s: controller initialization success\n", __FUNCTION__); ctrl->pci_dev = pdev; /* pci_dev of the P2P bridge */ pci_set_drvdata(pdev, ctrl); @@ -411,23 +408,8 @@ static int shpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) first_device_num = ctrl->slot_device_offset; num_ctlr_slots = ctrl->num_slots; |