Loading Documentation/DocBook/kernel-api.tmpl +3 −1 Original line number Diff line number Diff line Loading @@ -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> Loading arch/i386/pci/fixup.c +59 −0 Original line number Diff line number Diff line Loading @@ -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" Loading Loading @@ -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); drivers/pci/access.c +89 −0 Original line number Diff line number Diff line Loading @@ -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); drivers/pci/hotplug/acpiphp_glue.c +8 −0 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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) { Loading drivers/pci/hotplug/cpcihp_zt5550.c +21 −4 Original line number Diff line number Diff line Loading @@ -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)); Loading @@ -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 = Loading @@ -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; Loading @@ -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) Loading @@ -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; } Loading Loading
Documentation/DocBook/kernel-api.tmpl +3 −1 Original line number Diff line number Diff line Loading @@ -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> Loading
arch/i386/pci/fixup.c +59 −0 Original line number Diff line number Diff line Loading @@ -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" Loading Loading @@ -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);
drivers/pci/access.c +89 −0 Original line number Diff line number Diff line Loading @@ -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);
drivers/pci/hotplug/acpiphp_glue.c +8 −0 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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) { Loading
drivers/pci/hotplug/cpcihp_zt5550.c +21 −4 Original line number Diff line number Diff line Loading @@ -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)); Loading @@ -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 = Loading @@ -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; Loading @@ -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) Loading @@ -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; } Loading