diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2008-07-28 21:14:24 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-07-28 21:14:24 -0400 |
| commit | 1d9b9f6a53d77ed801ba875f937d6dabbfc381ce (patch) | |
| tree | 36ea93b80a444c3b37111e352790ebc07f29379f /drivers | |
| parent | a3ad7f128c637b7612ebeacb1f85fec933bb1195 (diff) | |
| parent | 12c0b20fa4afb5c8a377d6987fb2dcf353e1dce1 (diff) | |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jbarnes/pci-2.6
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jbarnes/pci-2.6: (21 commits)
x86/PCI: use dev_printk when possible
PCI: add D3 power state avoidance quirk
PCI: fix bogus "'device' may be used uninitialized" warning in pci_slot
PCI: add an option to allow ASPM enabled forcibly
PCI: disable ASPM on pre-1.1 PCIe devices
PCI: disable ASPM per ACPI FADT setting
PCI MSI: Don't disable MSIs if the mask bit isn't supported
PCI: handle 64-bit resources better on 32-bit machines
PCI: rewrite PCI BAR reading code
PCI: document pci_target_state
PCI hotplug: fix typo in pcie hotplug output
x86 gart: replace to_pages macro with iommu_num_pages
x86, AMD IOMMU: replace to_pages macro with iommu_num_pages
iommu: add iommu_num_pages helper function
dma-coherent: add documentation to new interfaces
Cris: convert to using generic dma-coherent mem allocator
Sh: use generic per-device coherent dma allocator
ARM: support generic per-device coherent dma mem
Generic dma-coherent: fix DMA_MEMORY_EXCLUSIVE
x86: use generic per-device dma coherent allocator
...
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/acpi/pci_slot.c | 18 | ||||
| -rw-r--r-- | drivers/pci/hotplug/pciehp_hpc.c | 2 | ||||
| -rw-r--r-- | drivers/pci/msi.c | 15 | ||||
| -rw-r--r-- | drivers/pci/pci-acpi.c | 7 | ||||
| -rw-r--r-- | drivers/pci/pci.c | 10 | ||||
| -rw-r--r-- | drivers/pci/pcie/aspm.c | 32 | ||||
| -rw-r--r-- | drivers/pci/probe.c | 245 | ||||
| -rw-r--r-- | drivers/pci/quirks.c | 13 |
8 files changed, 204 insertions, 138 deletions
diff --git a/drivers/acpi/pci_slot.c b/drivers/acpi/pci_slot.c index dd376f7ad090..d5b4ef898879 100644 --- a/drivers/acpi/pci_slot.c +++ b/drivers/acpi/pci_slot.c | |||
| @@ -76,9 +76,9 @@ static struct acpi_pci_driver acpi_pci_slot_driver = { | |||
| 76 | }; | 76 | }; |
| 77 | 77 | ||
| 78 | static int | 78 | static int |
| 79 | check_slot(acpi_handle handle, int *device, unsigned long *sun) | 79 | check_slot(acpi_handle handle, unsigned long *sun) |
| 80 | { | 80 | { |
| 81 | int retval = 0; | 81 | int device = -1; |
| 82 | unsigned long adr, sta; | 82 | unsigned long adr, sta; |
| 83 | acpi_status status; | 83 | acpi_status status; |
| 84 | struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; | 84 | struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; |
| @@ -89,32 +89,27 @@ check_slot(acpi_handle handle, int *device, unsigned long *sun) | |||
| 89 | if (check_sta_before_sun) { | 89 | if (check_sta_before_sun) { |
| 90 | /* If SxFy doesn't have _STA, we just assume it's there */ | 90 | /* If SxFy doesn't have _STA, we just assume it's there */ |
| 91 | status = acpi_evaluate_integer(handle, "_STA", NULL, &sta); | 91 | status = acpi_evaluate_integer(handle, "_STA", NULL, &sta); |
| 92 | if (ACPI_SUCCESS(status) && !(sta & ACPI_STA_DEVICE_PRESENT)) { | 92 | if (ACPI_SUCCESS(status) && !(sta & ACPI_STA_DEVICE_PRESENT)) |
| 93 | retval = -1; | ||
| 94 | goto out; | 93 | goto out; |
| 95 | } | ||
| 96 | } | 94 | } |
| 97 | 95 | ||
| 98 | status = acpi_evaluate_integer(handle, "_ADR", NULL, &adr); | 96 | status = acpi_evaluate_integer(handle, "_ADR", NULL, &adr); |
| 99 | if (ACPI_FAILURE(status)) { | 97 | if (ACPI_FAILURE(status)) { |
| 100 | dbg("_ADR returned %d on %s\n", status, (char *)buffer.pointer); | 98 | dbg("_ADR returned %d on %s\n", status, (char *)buffer.pointer); |
| 101 | retval = -1; | ||
| 102 | goto out; | 99 | goto out; |
| 103 | } | 100 | } |
| 104 | 101 | ||
| 105 | *device = (adr >> 16) & 0xffff; | ||
| 106 | |||
| 107 | /* No _SUN == not a slot == bail */ | 102 | /* No _SUN == not a slot == bail */ |
| 108 | status = acpi_evaluate_integer(handle, "_SUN", NULL, sun); | 103 | status = acpi_evaluate_integer(handle, "_SUN", NULL, sun); |
| 109 | if (ACPI_FAILURE(status)) { | 104 | if (ACPI_FAILURE(status)) { |
| 110 | dbg("_SUN returned %d on %s\n", status, (char *)buffer.pointer); | 105 | dbg("_SUN returned %d on %s\n", status, (char *)buffer.pointer); |
| 111 | retval = -1; | ||
| 112 | goto out; | 106 | goto out; |
| 113 | } | 107 | } |
| 114 | 108 | ||
| 109 | device = (adr >> 16) & 0xffff; | ||
| 115 | out: | 110 | out: |
| 116 | kfree(buffer.pointer); | 111 | kfree(buffer.pointer); |
| 117 | return retval; | 112 | return device; |
| 118 | } | 113 | } |
| 119 | 114 | ||
| 120 | struct callback_args { | 115 | struct callback_args { |
| @@ -144,7 +139,8 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv) | |||
| 144 | struct callback_args *parent_context = context; | 139 | struct callback_args *parent_context = context; |
| 145 | struct pci_bus *pci_bus = parent_context->pci_bus; | 140 | struct pci_bus *pci_bus = parent_context->pci_bus; |
| 146 | 141 | ||
| 147 | if (check_slot(handle, &device, &sun)) | 142 | device = check_slot(handle, &sun); |
| 143 | if (device < 0) | ||
| 148 | return AE_OK; | 144 | return AE_OK; |
| 149 | 145 | ||
| 150 | slot = kmalloc(sizeof(*slot), GFP_KERNEL); | 146 | slot = kmalloc(sizeof(*slot), GFP_KERNEL); |
diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c index 1323a43285d7..ad27e9e225a6 100644 --- a/drivers/pci/hotplug/pciehp_hpc.c +++ b/drivers/pci/hotplug/pciehp_hpc.c | |||
| @@ -1103,7 +1103,7 @@ static inline void dbg_ctrl(struct controller *ctrl) | |||
| 1103 | dbg(" Power Indicator : %3s\n", PWR_LED(ctrl) ? "yes" : "no"); | 1103 | dbg(" Power Indicator : %3s\n", PWR_LED(ctrl) ? "yes" : "no"); |
| 1104 | dbg(" Hot-Plug Surprise : %3s\n", HP_SUPR_RM(ctrl) ? "yes" : "no"); | 1104 | dbg(" Hot-Plug Surprise : %3s\n", HP_SUPR_RM(ctrl) ? "yes" : "no"); |
| 1105 | dbg(" EMI Present : %3s\n", EMI(ctrl) ? "yes" : "no"); | 1105 | dbg(" EMI Present : %3s\n", EMI(ctrl) ? "yes" : "no"); |
| 1106 | dbg(" Comamnd Completed : %3s\n", NO_CMD_CMPL(ctrl)? "no" : "yes"); | 1106 | dbg(" Command Completed : %3s\n", NO_CMD_CMPL(ctrl)? "no" : "yes"); |
| 1107 | pciehp_readw(ctrl, SLOTSTATUS, ®16); | 1107 | pciehp_readw(ctrl, SLOTSTATUS, ®16); |
| 1108 | dbg("Slot Status : 0x%04x\n", reg16); | 1108 | dbg("Slot Status : 0x%04x\n", reg16); |
| 1109 | pciehp_readw(ctrl, SLOTCTRL, ®16); | 1109 | pciehp_readw(ctrl, SLOTCTRL, ®16); |
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index 15af618d36e2..18354817173c 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c | |||
| @@ -126,7 +126,16 @@ static void msix_flush_writes(unsigned int irq) | |||
| 126 | } | 126 | } |
| 127 | } | 127 | } |
| 128 | 128 | ||
| 129 | static void msi_set_mask_bits(unsigned int irq, u32 mask, u32 flag) | 129 | /* |
| 130 | * PCI 2.3 does not specify mask bits for each MSI interrupt. Attempting to | ||
| 131 | * mask all MSI interrupts by clearing the MSI enable bit does not work | ||
| 132 | * reliably as devices without an INTx disable bit will then generate a | ||
| 133 | * level IRQ which will never be cleared. | ||
| 134 | * | ||
| 135 | * Returns 1 if it succeeded in masking the interrupt and 0 if the device | ||
| 136 | * doesn't support MSI masking. | ||
| 137 | */ | ||
| 138 | static int msi_set_mask_bits(unsigned int irq, u32 mask, u32 flag) | ||
| 130 | { | 139 | { |
| 131 | struct msi_desc *entry; | 140 | struct msi_desc *entry; |
| 132 | 141 | ||
| @@ -144,8 +153,7 @@ static void msi_set_mask_bits(unsigned int irq, u32 mask, u32 flag) | |||
| 144 | mask_bits |= flag & mask; | 153 | mask_bits |= flag & mask; |
| 145 | pci_write_config_dword(entry->dev, pos, mask_bits); | 154 | pci_write_config_dword(entry->dev, pos, mask_bits); |
| 146 | } else { | 155 | } else { |
| 147 | __msi_set_enable(entry->dev, entry->msi_attrib.pos, | 156 | return 0; |
| 148 | !flag); | ||
| 149 | } | 157 | } |
| 150 | break; | 158 | break; |
| 151 | case PCI_CAP_ID_MSIX: | 159 | case PCI_CAP_ID_MSIX: |
| @@ -161,6 +169,7 @@ static void msi_set_mask_bits(unsigned int irq, u32 mask, u32 flag) | |||
| 161 | break; | 169 | break; |
| 162 | } | 170 | } |
| 163 | entry->msi_attrib.masked = !!flag; | 171 | entry->msi_attrib.masked = !!flag; |
| 172 | return 1; | ||
| 164 | } | 173 | } |
| 165 | 174 | ||
| 166 | void read_msi_msg(unsigned int irq, struct msi_msg *msg) | 175 | void read_msi_msg(unsigned int irq, struct msi_msg *msg) |
diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c index 7764768b6a0e..89a2f0fa10f9 100644 --- a/drivers/pci/pci-acpi.c +++ b/drivers/pci/pci-acpi.c | |||
| @@ -11,6 +11,7 @@ | |||
| 11 | #include <linux/init.h> | 11 | #include <linux/init.h> |
| 12 | #include <linux/pci.h> | 12 | #include <linux/pci.h> |
| 13 | #include <linux/module.h> | 13 | #include <linux/module.h> |
| 14 | #include <linux/pci-aspm.h> | ||
| 14 | #include <acpi/acpi.h> | 15 | #include <acpi/acpi.h> |
| 15 | #include <acpi/acnamesp.h> | 16 | #include <acpi/acnamesp.h> |
| 16 | #include <acpi/acresrc.h> | 17 | #include <acpi/acresrc.h> |
| @@ -372,6 +373,12 @@ static int __init acpi_pci_init(void) | |||
| 372 | printk(KERN_INFO"ACPI FADT declares the system doesn't support MSI, so disable it\n"); | 373 | printk(KERN_INFO"ACPI FADT declares the system doesn't support MSI, so disable it\n"); |
| 373 | pci_no_msi(); | 374 | pci_no_msi(); |
| 374 | } | 375 | } |
| 376 | |||
| 377 | if (acpi_gbl_FADT.boot_flags & BAF_PCIE_ASPM_CONTROL) { | ||
| 378 | printk(KERN_INFO"ACPI FADT declares the system doesn't support PCIe ASPM, so disable it\n"); | ||
| 379 | pcie_no_aspm(); | ||
| 380 | } | ||
| 381 | |||
| 375 | ret = register_acpi_bus_type(&acpi_pci_bus); | 382 | ret = register_acpi_bus_type(&acpi_pci_bus); |
| 376 | if (ret) | 383 | if (ret) |
| 377 | return 0; | 384 | return 0; |
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index e9c356236d27..0a3d856833fc 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c | |||
| @@ -572,6 +572,10 @@ int pci_set_power_state(struct pci_dev *dev, pci_power_t state) | |||
| 572 | if (!ret) | 572 | if (!ret) |
| 573 | pci_update_current_state(dev); | 573 | pci_update_current_state(dev); |
| 574 | } | 574 | } |
| 575 | /* This device is quirked not to be put into D3, so | ||
| 576 | don't put it in D3 */ | ||
| 577 | if (state == PCI_D3hot && (dev->dev_flags & PCI_DEV_FLAGS_NO_D3)) | ||
| 578 | return 0; | ||
| 575 | 579 | ||
| 576 | error = pci_raw_set_power_state(dev, state); | 580 | error = pci_raw_set_power_state(dev, state); |
| 577 | 581 | ||
| @@ -1123,6 +1127,12 @@ int pci_enable_wake(struct pci_dev *dev, pci_power_t state, int enable) | |||
| 1123 | } | 1127 | } |
| 1124 | 1128 | ||
| 1125 | /** | 1129 | /** |
| 1130 | * pci_target_state - find an appropriate low power state for a given PCI dev | ||
| 1131 | * @dev: PCI device | ||
| 1132 | * | ||
| 1133 | * Use underlying platform code to find a supported low power state for @dev. | ||
| 1134 | * If the platform can't manage @dev, return the deepest state from which it | ||
| 1135 | * can generate wake events, based on any available PME info. | ||
| 1126 | */ | 1136 | */ |
| 1127 | pci_power_t pci_target_state(struct pci_dev *dev) | 1137 | pci_power_t pci_target_state(struct pci_dev *dev) |
| 1128 | { | 1138 | { |
diff --git a/drivers/pci/pcie/aspm.c b/drivers/pci/pcie/aspm.c index f82495583e63..9a7c9e1408a4 100644 --- a/drivers/pci/pcie/aspm.c +++ b/drivers/pci/pcie/aspm.c | |||
| @@ -55,7 +55,7 @@ struct pcie_link_state { | |||
| 55 | struct endpoint_state endpoints[8]; | 55 | struct endpoint_state endpoints[8]; |
| 56 | }; | 56 | }; |
| 57 | 57 | ||
| 58 | static int aspm_disabled; | 58 | static int aspm_disabled, aspm_force; |
| 59 | static DEFINE_MUTEX(aspm_lock); | 59 | static DEFINE_MUTEX(aspm_lock); |
| 60 | static LIST_HEAD(link_list); | 60 | static LIST_HEAD(link_list); |
| 61 | 61 | ||
| @@ -510,6 +510,7 @@ static int pcie_aspm_sanity_check(struct pci_dev *pdev) | |||
| 510 | { | 510 | { |
| 511 | struct pci_dev *child_dev; | 511 | struct pci_dev *child_dev; |
| 512 | int child_pos; | 512 | int child_pos; |
| 513 | u32 reg32; | ||
| 513 | 514 | ||
| 514 | /* | 515 | /* |
| 515 | * Some functions in a slot might not all be PCIE functions, very | 516 | * Some functions in a slot might not all be PCIE functions, very |
| @@ -519,6 +520,19 @@ static int pcie_aspm_sanity_check(struct pci_dev *pdev) | |||
| 519 | child_pos = pci_find_capability(child_dev, PCI_CAP_ID_EXP); | 520 | child_pos = pci_find_capability(child_dev, PCI_CAP_ID_EXP); |
| 520 | if (!child_pos) | 521 | if (!child_pos) |
| 521 | return -EINVAL; | 522 | return -EINVAL; |
| 523 | |||
| 524 | /* | ||
| 525 | * Disable ASPM for pre-1.1 PCIe device, we follow MS to use | ||
| 526 | * RBER bit to determine if a function is 1.1 version device | ||
| 527 | */ | ||
| 528 | pci_read_config_dword(child_dev, child_pos + PCI_EXP_DEVCAP, | ||
| 529 | ®32); | ||
| 530 | if (!(reg32 & PCI_EXP_DEVCAP_RBER && !aspm_force)) { | ||
| 531 | printk("Pre-1.1 PCIe device detected, " | ||
| 532 | "disable ASPM for %s. It can be enabled forcedly" | ||
| 533 | " with 'pcie_aspm=force'\n", pci_name(pdev)); | ||
| 534 | return -EINVAL; | ||
| 535 | } | ||
| 522 | } | 536 | } |
| 523 | return 0; | 537 | return 0; |
| 524 | } | 538 | } |
| @@ -802,11 +816,23 @@ void pcie_aspm_remove_sysfs_dev_files(struct pci_dev *pdev) | |||
| 802 | 816 | ||
| 803 | static int __init pcie_aspm_disable(char *str) | 817 | static int __init pcie_aspm_disable(char *str) |
| 804 | { | 818 | { |
| 805 | aspm_disabled = 1; | 819 | if (!strcmp(str, "off")) { |
| 820 | aspm_disabled = 1; | ||
| 821 | printk(KERN_INFO "PCIe ASPM is disabled\n"); | ||
| 822 | } else if (!strcmp(str, "force")) { | ||
| 823 | aspm_force = 1; | ||
| 824 | printk(KERN_INFO "PCIe ASPM is forcedly enabled\n"); | ||
| 825 | } | ||
| 806 | return 1; | 826 | return 1; |
| 807 | } | 827 | } |
| 808 | 828 | ||
| 809 | __setup("pcie_noaspm", pcie_aspm_disable); | 829 | __setup("pcie_aspm=", pcie_aspm_disable); |
| 830 | |||
| 831 | void pcie_no_aspm(void) | ||
| 832 | { | ||
| 833 | if (!aspm_force) | ||
| 834 | aspm_disabled = 1; | ||
| 835 | } | ||
| 810 | 836 | ||
| 811 | #ifdef CONFIG_ACPI | 837 | #ifdef CONFIG_ACPI |
| 812 | #include <acpi/acpi_bus.h> | 838 | #include <acpi/acpi_bus.h> |
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index b1724cf31b66..7098dfb07449 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c | |||
| @@ -163,12 +163,9 @@ static inline unsigned int pci_calc_resource_flags(unsigned int flags) | |||
| 163 | return IORESOURCE_MEM; | 163 | return IORESOURCE_MEM; |
| 164 | } | 164 | } |
| 165 | 165 | ||
| 166 | /* | 166 | static u64 pci_size(u64 base, u64 maxbase, u64 mask) |
| 167 | * Find the extent of a PCI decode.. | ||
| 168 | */ | ||
| 169 | static u32 pci_size(u32 base, u32 maxbase, u32 mask) | ||
| 170 | { | 167 | { |
| 171 | u32 size = mask & maxbase; /* Find the significant bits */ | 168 | u64 size = mask & maxbase; /* Find the significant bits */ |
| 172 | if (!size) | 169 | if (!size) |
| 173 | return 0; | 170 | return 0; |
| 174 | 171 | ||
| @@ -184,135 +181,142 @@ static u32 pci_size(u32 base, u32 maxbase, u32 mask) | |||
| 184 | return size; | 181 | return size; |
| 185 | } | 182 | } |
| 186 | 183 | ||
| 187 | static u64 pci_size64(u64 base, u64 maxbase, u64 mask) | 184 | enum pci_bar_type { |
| 188 | { | 185 | pci_bar_unknown, /* Standard PCI BAR probe */ |
| 189 | u64 size = mask & maxbase; /* Find the significant bits */ | 186 | pci_bar_io, /* An io port BAR */ |
| 190 | if (!size) | 187 | pci_bar_mem32, /* A 32-bit memory BAR */ |
| 191 | return 0; | 188 | pci_bar_mem64, /* A 64-bit memory BAR */ |
| 189 | }; | ||
| 192 | 190 | ||
| 193 | /* Get the lowest of them to find the decode size, and | 191 | static inline enum pci_bar_type decode_bar(struct resource *res, u32 bar) |
| 194 | from that the extent. */ | 192 | { |
| 195 | size = (size & ~(size-1)) - 1; | 193 | if ((bar & PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_IO) { |
| 194 | res->flags = bar & ~PCI_BASE_ADDRESS_IO_MASK; | ||
| 195 | return pci_bar_io; | ||
| 196 | } | ||
| 196 | 197 | ||
| 197 | /* base == maxbase can be valid only if the BAR has | 198 | res->flags = bar & ~PCI_BASE_ADDRESS_MEM_MASK; |
| 198 | already been programmed with all 1s. */ | ||
| 199 | if (base == maxbase && ((base | size) & mask) != mask) | ||
| 200 | return 0; | ||
| 201 | 199 | ||
| 202 | return size; | 200 | if (res->flags == PCI_BASE_ADDRESS_MEM_TYPE_64) |
| 201 | return pci_bar_mem64; | ||
| 202 | return pci_bar_mem32; | ||
| 203 | } | 203 | } |
| 204 | 204 | ||
| 205 | static inline int is_64bit_memory(u32 mask) | 205 | /* |
| 206 | * If the type is not unknown, we assume that the lowest bit is 'enable'. | ||
| 207 | * Returns 1 if the BAR was 64-bit and 0 if it was 32-bit. | ||
| 208 | */ | ||
| 209 | static int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type, | ||
| 210 | struct resource *res, unsigned int pos) | ||
| 206 | { | 211 | { |
| 207 | if ((mask & (PCI_BASE_ADDRESS_SPACE|PCI_BASE_ADDRESS_MEM_TYPE_MASK)) == | 212 | u32 l, sz, mask; |
| 208 | (PCI_BASE_ADDRESS_SPACE_MEMORY|PCI_BASE_ADDRESS_MEM_TYPE_64)) | ||
| 209 | return 1; | ||
| 210 | return 0; | ||
| 211 | } | ||
| 212 | 213 | ||
| 213 | static void pci_read_bases(struct pci_dev *dev, unsigned int howmany, int rom) | 214 | mask = type ? ~PCI_ROM_ADDRESS_ENABLE : ~0; |
| 214 | { | ||
| 215 | unsigned int pos, reg, next; | ||
| 216 | u32 l, sz; | ||
| 217 | struct resource *res; | ||
| 218 | 215 | ||
| 219 | for(pos=0; pos<howmany; pos = next) { | 216 | res->name = pci_name(dev); |
| 220 | u64 l64; | ||
| 221 | u64 sz64; | ||
| 222 | u32 raw_sz; | ||
| 223 | 217 | ||
| 224 | next = pos+1; | 218 | pci_read_config_dword(dev, pos, &l); |
| 225 | res = &dev->resource[pos]; | 219 | pci_write_config_dword(dev, pos, mask); |
| 226 | res->name = pci_name(dev); | 220 | pci_read_config_dword(dev, pos, &sz); |
| 227 | reg = PCI_BASE_ADDRESS_0 + (pos << 2); | 221 | pci_write_config_dword(dev, pos, l); |
| 228 | pci_read_config_dword(dev, reg, &l); | 222 | |
| 229 | pci_write_config_dword(dev, reg, ~0); | 223 | /* |
| 230 | pci_read_config_dword(dev, reg, &sz); | 224 | * All bits set in sz means the device isn't working properly. |
| 231 | pci_write_config_dword(dev, reg, l); | 225 | * If the BAR isn't implemented, all bits must be 0. If it's a |
| 232 | if (!sz || sz == 0xffffffff) | 226 | * memory BAR or a ROM, bit 0 must be clear; if it's an io BAR, bit |
| 233 | continue; | 227 | * 1 must be clear. |
| 234 | if (l == 0xffffffff) | 228 | */ |
| 235 | l = 0; | 229 | if (!sz || sz == 0xffffffff) |
| 236 | raw_sz = sz; | 230 | goto fail; |
| 237 | if ((l & PCI_BASE_ADDRESS_SPACE) == | 231 | |
| 238 | PCI_BASE_ADDRESS_SPACE_MEMORY) { | 232 | /* |
| 239 | sz = pci_size(l, sz, (u32)PCI_BASE_ADDRESS_MEM_MASK); | 233 | * I don't know how l can have all bits set. Copied from old code. |
| 240 | /* | 234 | * Maybe it fixes a bug on some ancient platform. |
| 241 | * For 64bit prefetchable memory sz could be 0, if the | 235 | */ |
| 242 | * real size is bigger than 4G, so we need to check | 236 | if (l == 0xffffffff) |
| 243 | * szhi for that. | 237 | l = 0; |
| 244 | */ | 238 | |
| 245 | if (!is_64bit_memory(l) && !sz) | 239 | if (type == pci_bar_unknown) { |
| 246 | continue; | 240 | type = decode_bar(res, l); |
| 247 | res->start = l & PCI_BASE_ADDRESS_MEM_MASK; | 241 | res->flags |= pci_calc_resource_flags(l) | IORESOURCE_SIZEALIGN; |
| 248 | res->flags |= l & ~PCI_BASE_ADDRESS_MEM_MASK; | 242 | if (type == pci_bar_io) { |
| 243 | l &= PCI_BASE_ADDRESS_IO_MASK; | ||
| 244 | mask = PCI_BASE_ADDRESS_IO_MASK & 0xffff; | ||
| 249 | } else { | 245 | } else { |
| 250 | sz = pci_size(l, sz, PCI_BASE_ADDRESS_IO_MASK & 0xffff); | 246 | l &= PCI_BASE_ADDRESS_MEM_MASK; |
| 251 | if (!sz) | 247 | mask = (u32)PCI_BASE_ADDRESS_MEM_MASK; |
| 252 | continue; | ||
| 253 | res->start = l & PCI_BASE_ADDRESS_IO_MASK; | ||
| 254 | res->flags |= l & ~PCI_BASE_ADDRESS_IO_MASK; | ||
| 255 | } | 248 | } |
| 256 | res->end = res->start + (unsigned long) sz; | 249 | } else { |
| 257 | res->flags |= pci_calc_resource_flags(l) | IORESOURCE_SIZEALIGN; | 250 | res->flags |= (l & IORESOURCE_ROM_ENABLE); |
| 258 | if (is_64bit_memory(l)) { | 251 | l &= PCI_ROM_ADDRESS_MASK; |
| 259 | u32 szhi, lhi; | 252 | mask = (u32)PCI_ROM_ADDRESS_MASK; |
| 260 | 253 | } | |
| 261 | pci_read_config_dword(dev, reg+4, &lhi); | 254 | |
| 262 | pci_write_config_dword(dev, reg+4, ~0); | 255 | if (type == pci_bar_mem64) { |
| 263 | pci_read_config_dword(dev, reg+4, &szhi); | 256 | u64 l64 = l; |
| 264 | pci_write_config_dword(dev, reg+4, lhi); | 257 | u64 sz64 = sz; |
| 265 | sz64 = ((u64)szhi << 32) | raw_sz; | 258 | u64 mask64 = mask | (u64)~0 << 32; |
| 266 | l64 = ((u64)lhi << 32) | l; | 259 | |
| 267 | sz64 = pci_size64(l64, sz64, PCI_BASE_ADDRESS_MEM_MASK); | 260 | pci_read_config_dword(dev, pos + 4, &l); |
| 268 | next++; | 261 | pci_write_config_dword(dev, pos + 4, ~0); |
| 269 | #if BITS_PER_LONG == 64 | 262 | pci_read_config_dword(dev, pos + 4, &sz); |
| 270 | if (!sz64) { | 263 | pci_write_config_dword(dev, pos + 4, l); |
| 271 | res->start = 0; | 264 | |
| 272 | res->end = 0; | 265 | l64 |= ((u64)l << 32); |
| 273 | res->flags = 0; | 266 | sz64 |= ((u64)sz << 32); |
| 274 | continue; | 267 | |
| 275 | } | 268 | sz64 = pci_size(l64, sz64, mask64); |
| 276 | res->start = l64 & PCI_BASE_ADDRESS_MEM_MASK; | 269 | |
| 277 | res->end = res->start + sz64; | 270 | if (!sz64) |
| 278 | #else | 271 | goto fail; |
| 279 | if (sz64 > 0x100000000ULL) { | 272 | |
| 280 | dev_err(&dev->dev, "BAR %d: can't handle 64-bit" | 273 | if ((sizeof(resource_size_t) < 8) && (sz64 > 0x100000000ULL)) { |
| 281 | " BAR\n", pos); | 274 | dev_err(&dev->dev, "can't handle 64-bit BAR\n"); |
| 282 | res->start = 0; | 275 | goto fail; |
| 283 | res->flags = 0; | 276 | } else if ((sizeof(resource_size_t) < 8) && l) { |
| 284 | } else if (lhi) { | 277 | /* Address above 32-bit boundary; disable the BAR */ |
| 285 | /* 64-bit wide address, treat as disabled */ | 278 | pci_write_config_dword(dev, pos, 0); |
| 286 | pci_write_config_dword(dev, reg, | 279 | pci_write_config_dword(dev, pos + 4, 0); |
| 287 | l & ~(u32)PCI_BASE_ADDRESS_MEM_MASK); | 280 | res->start = 0; |
| 288 | pci_write_config_dword(dev, reg+4, 0); | 281 | res->end = sz64; |
| 289 | res->start = 0; | 282 | } else { |
| 290 | res->end = sz; | 283 | res->start = l64; |
| 291 | } | 284 | res->end = l64 + sz64; |
| 292 | #endif | ||
| 293 | } | 285 | } |
| 286 | } else { | ||
| 287 | sz = pci_size(l, sz, mask); | ||
| 288 | |||
| 289 | if (!sz) | ||
| 290 | goto fail; | ||
| 291 | |||
| 292 | res->start = l; | ||
| 293 | res->end = l + sz; | ||
| 294 | } | 294 | } |
| 295 | |||
| 296 | out: | ||
| 297 | return (type == pci_bar_mem64) ? 1 : 0; | ||
| 298 | fail: | ||
| 299 | res->flags = 0; | ||
| 300 | goto out; | ||
| 301 | } | ||
| 302 | |||
| 303 | static void pci_read_bases(struct pci_dev *dev, unsigned int howmany, int rom) | ||
| 304 | { | ||
| 305 | unsigned int pos, reg; | ||
| 306 | |||
| 307 | for (pos = 0; pos < howmany; pos++) { | ||
| 308 | struct resource *res = &dev->resource[pos]; | ||
| 309 | reg = PCI_BASE_ADDRESS_0 + (pos << 2); | ||
| 310 | pos += __pci_read_base(dev, pci_bar_unknown, res, reg); | ||
| 311 | } | ||
| 312 | |||
| 295 | if (rom) { | 313 | if (rom) { |
| 314 | struct resource *res = &dev->resource[PCI_ROM_RESOURCE]; | ||
| 296 | dev->rom_base_reg = rom; | 315 | dev->rom_base_reg = rom; |
| 297 | res = &dev->resource[PCI_ROM_RESOURCE]; | 316 | res->flags = IORESOURCE_MEM | IORESOURCE_PREFETCH | |
| 298 | res->name = pci_name(dev); | 317 | IORESOURCE_READONLY | IORESOURCE_CACHEABLE | |
| 299 | pci_read_config_dword(dev, rom, &l); | 318 | IORESOURCE_SIZEALIGN; |
| 300 | pci_write_config_dword(dev, rom, ~PCI_ROM_ADDRESS_ENABLE); | 319 | __pci_read_base(dev, pci_bar_mem32, res, rom); |
| 301 | pci_read_config_dword(dev, rom, &sz); | ||
| 302 | pci_write_config_dword(dev, rom, l); | ||
| 303 | if (l == 0xffffffff) | ||
| 304 | l = 0; | ||
| 305 | if (sz && sz != 0xffffffff) { | ||
| 306 | sz = pci_size(l, sz, (u32)PCI_ROM_ADDRESS_MASK); | ||
| 307 | if (sz) { | ||
| 308 | res->flags = (l & IORESOURCE_ROM_ENABLE) | | ||
| 309 | IORESOURCE_MEM | IORESOURCE_PREFETCH | | ||
| 310 | IORESOURCE_READONLY | IORESOURCE_CACHEABLE | | ||
| 311 | IORESOURCE_SIZEALIGN; | ||
| 312 | res->start = l & PCI_ROM_ADDRESS_MASK; | ||
| 313 | res->end = res->start + (unsigned long) sz; | ||
| 314 | } | ||
| 315 | } | ||
| 316 | } | 320 | } |
| 317 | } | 321 | } |
| 318 | 322 | ||
| @@ -1053,7 +1057,8 @@ int pci_scan_slot(struct pci_bus *bus, int devfn) | |||
| 1053 | } | 1057 | } |
| 1054 | } | 1058 | } |
| 1055 | 1059 | ||
| 1056 | if (bus->self) | 1060 | /* only one slot has pcie device */ |
| 1061 | if (bus->self && nr) | ||
| 1057 | pcie_aspm_init_link_state(bus->self); | 1062 | pcie_aspm_init_link_state(bus->self); |
| 1058 | 1063 | ||
| 1059 | return nr; | 1064 | return nr; |
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 12d489395fad..0fb365074288 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c | |||
| @@ -923,6 +923,19 @@ static void __init quirk_ide_samemode(struct pci_dev *pdev) | |||
| 923 | } | 923 | } |
| 924 | DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_10, quirk_ide_samemode); | 924 | DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_10, quirk_ide_samemode); |
| 925 | 925 | ||
| 926 | /* | ||
| 927 | * Some ATA devices break if put into D3 | ||
| 928 | */ | ||
| 929 | |||
| 930 | static void __devinit quirk_no_ata_d3(struct pci_dev *pdev) | ||
| 931 | { | ||
| 932 | /* Quirk the legacy ATA devices only. The AHCI ones are ok */ | ||
| 933 | if ((pdev->class >> 8) == PCI_CLASS_STORAGE_IDE) | ||
| 934 | pdev->dev_flags |= PCI_DEV_FLAGS_NO_D3; | ||
| 935 | } | ||
| 936 | DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_SERVERWORKS, PCI_ANY_ID, quirk_no_ata_d3); | ||
| 937 | DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_ATI, PCI_ANY_ID, quirk_no_ata_d3); | ||
| 938 | |||
| 926 | /* This was originally an Alpha specific thing, but it really fits here. | 939 | /* This was originally an Alpha specific thing, but it really fits here. |
| 927 | * The i82375 PCI/EISA bridge appears as non-classified. Fix that. | 940 | * The i82375 PCI/EISA bridge appears as non-classified. Fix that. |
| 928 | */ | 941 | */ |
