diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-03-26 19:34:29 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-03-26 19:34:29 -0400 |
| commit | b72c40949b0f04728f2993a1434598d3bad094ea (patch) | |
| tree | 612b99ceac1f713d15cb288d370578e138537e49 | |
| parent | e4d50423d773fb8d5b714430ba5358e8a1b87c14 (diff) | |
| parent | d558b483d5a73f5718705b270cb2090f66ea48c8 (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:
x86/PCI: truncate _CRS windows with _LEN > _MAX - _MIN + 1
x86/PCI: for host bridge address space collisions, show conflicting resource
frv/PCI: remove redundant warnings
x86/PCI: remove redundant warnings
PCI: don't say we claimed a resource if we failed
PCI quirk: Disable MSI on VIA K8T890 systems
PCI quirk: RS780/RS880: work around missing MSI initialization
PCI quirk: only apply CX700 PCI bus parking quirk if external VT6212L is present
PCI: complain about devices that seem to be broken
PCI: print resources consistently with %pR
PCI: make disabled window printk style match the enabled ones
PCI: break out primary/secondary/subordinate for readability
PCI: for address space collisions, show conflicting resource
resources: add interfaces that return conflict information
PCI: cleanup error return for pcix get and set mmrbc functions
PCI: fix access of PCI_X_CMD by pcix get and set mmrbc functions
PCI: kill off pci_register_set_vga_state() symbol export.
PCI: fix return value from pcix_get_max_mmrbc()
| -rw-r--r-- | arch/frv/mb93090-mb00/pci-frv.c | 4 | ||||
| -rw-r--r-- | arch/x86/pci/acpi.c | 22 | ||||
| -rw-r--r-- | arch/x86/pci/i386.c | 5 | ||||
| -rw-r--r-- | drivers/gpu/drm/radeon/radeon_irq_kms.c | 8 | ||||
| -rw-r--r-- | drivers/pci/hotplug/pciehp_hpc.c | 5 | ||||
| -rw-r--r-- | drivers/pci/ioapic.c | 9 | ||||
| -rw-r--r-- | drivers/pci/pci.c | 44 | ||||
| -rw-r--r-- | drivers/pci/probe.c | 53 | ||||
| -rw-r--r-- | drivers/pci/quirks.c | 59 | ||||
| -rw-r--r-- | drivers/pci/setup-res.c | 14 | ||||
| -rw-r--r-- | drivers/pcmcia/rsrc_nonstatic.c | 12 | ||||
| -rw-r--r-- | include/linux/ioport.h | 2 | ||||
| -rw-r--r-- | kernel/resource.c | 44 |
13 files changed, 184 insertions, 97 deletions
diff --git a/arch/frv/mb93090-mb00/pci-frv.c b/arch/frv/mb93090-mb00/pci-frv.c index 1ed15d7fea20..16bc2cb5649a 100644 --- a/arch/frv/mb93090-mb00/pci-frv.c +++ b/arch/frv/mb93090-mb00/pci-frv.c | |||
| @@ -94,8 +94,7 @@ static void __init pcibios_allocate_bus_resources(struct list_head *bus_list) | |||
| 94 | r = &dev->resource[idx]; | 94 | r = &dev->resource[idx]; |
| 95 | if (!r->start) | 95 | if (!r->start) |
| 96 | continue; | 96 | continue; |
| 97 | if (pci_claim_resource(dev, idx) < 0) | 97 | pci_claim_resource(dev, idx); |
| 98 | printk(KERN_ERR "PCI: Cannot allocate resource region %d of bridge %s\n", idx, pci_name(dev)); | ||
| 99 | } | 98 | } |
| 100 | } | 99 | } |
| 101 | pcibios_allocate_bus_resources(&bus->children); | 100 | pcibios_allocate_bus_resources(&bus->children); |
| @@ -125,7 +124,6 @@ static void __init pcibios_allocate_resources(int pass) | |||
| 125 | DBG("PCI: Resource %08lx-%08lx (f=%lx, d=%d, p=%d)\n", | 124 | DBG("PCI: Resource %08lx-%08lx (f=%lx, d=%d, p=%d)\n", |
| 126 | r->start, r->end, r->flags, disabled, pass); | 125 | r->start, r->end, r->flags, disabled, pass); |
| 127 | if (pci_claim_resource(dev, idx) < 0) { | 126 | if (pci_claim_resource(dev, idx) < 0) { |
| 128 | printk(KERN_ERR "PCI: Cannot allocate resource region %d of device %s\n", idx, pci_name(dev)); | ||
| 129 | /* We'll assign a new address later */ | 127 | /* We'll assign a new address later */ |
| 130 | r->end -= r->start; | 128 | r->end -= r->start; |
| 131 | r->start = 0; | 129 | r->start = 0; |
diff --git a/arch/x86/pci/acpi.c b/arch/x86/pci/acpi.c index 6e22454bfaa6..e31160216efb 100644 --- a/arch/x86/pci/acpi.c +++ b/arch/x86/pci/acpi.c | |||
| @@ -122,8 +122,8 @@ setup_resource(struct acpi_resource *acpi_res, void *data) | |||
| 122 | struct acpi_resource_address64 addr; | 122 | struct acpi_resource_address64 addr; |
| 123 | acpi_status status; | 123 | acpi_status status; |
| 124 | unsigned long flags; | 124 | unsigned long flags; |
| 125 | struct resource *root; | 125 | struct resource *root, *conflict; |
| 126 | u64 start, end; | 126 | u64 start, end, max_len; |
| 127 | 127 | ||
| 128 | status = resource_to_addr(acpi_res, &addr); | 128 | status = resource_to_addr(acpi_res, &addr); |
| 129 | if (!ACPI_SUCCESS(status)) | 129 | if (!ACPI_SUCCESS(status)) |
| @@ -140,6 +140,17 @@ setup_resource(struct acpi_resource *acpi_res, void *data) | |||
| 140 | } else | 140 | } else |
| 141 | return AE_OK; | 141 | return AE_OK; |
| 142 | 142 | ||
| 143 | max_len = addr.maximum - addr.minimum + 1; | ||
| 144 | if (addr.address_length > max_len) { | ||
| 145 | dev_printk(KERN_DEBUG, &info->bridge->dev, | ||
| 146 | "host bridge window length %#llx doesn't fit in " | ||
| 147 | "%#llx-%#llx, trimming\n", | ||
| 148 | (unsigned long long) addr.address_length, | ||
| 149 | (unsigned long long) addr.minimum, | ||
| 150 | (unsigned long long) addr.maximum); | ||
| 151 | addr.address_length = max_len; | ||
| 152 | } | ||
| 153 | |||
| 143 | start = addr.minimum + addr.translation_offset; | 154 | start = addr.minimum + addr.translation_offset; |
| 144 | end = start + addr.address_length - 1; | 155 | end = start + addr.address_length - 1; |
| 145 | 156 | ||
| @@ -157,9 +168,12 @@ setup_resource(struct acpi_resource *acpi_res, void *data) | |||
| 157 | return AE_OK; | 168 | return AE_OK; |
| 158 | } | 169 | } |
| 159 | 170 | ||
| 160 | if (insert_resource(root, res)) { | 171 | conflict = insert_resource_conflict(root, res); |
| 172 | if (conflict) { | ||
| 161 | dev_err(&info->bridge->dev, | 173 | dev_err(&info->bridge->dev, |
| 162 | "can't allocate host bridge window %pR\n", res); | 174 | "address space collision: host bridge window %pR " |
| 175 | "conflicts with %s %pR\n", | ||
| 176 | res, conflict->name, conflict); | ||
| 163 | } else { | 177 | } else { |
| 164 | pci_bus_add_resource(info->bus, res, 0); | 178 | pci_bus_add_resource(info->bus, res, 0); |
| 165 | info->res_num++; | 179 | info->res_num++; |
diff --git a/arch/x86/pci/i386.c b/arch/x86/pci/i386.c index dece3eb9c906..46fd43f79103 100644 --- a/arch/x86/pci/i386.c +++ b/arch/x86/pci/i386.c | |||
| @@ -127,9 +127,6 @@ static void __init pcibios_allocate_bus_resources(struct list_head *bus_list) | |||
| 127 | continue; | 127 | continue; |
| 128 | if (!r->start || | 128 | if (!r->start || |
| 129 | pci_claim_resource(dev, idx) < 0) { | 129 | pci_claim_resource(dev, idx) < 0) { |
| 130 | dev_info(&dev->dev, | ||
| 131 | "can't reserve window %pR\n", | ||
| 132 | r); | ||
| 133 | /* | 130 | /* |
| 134 | * Something is wrong with the region. | 131 | * Something is wrong with the region. |
| 135 | * Invalidate the resource to prevent | 132 | * Invalidate the resource to prevent |
| @@ -181,8 +178,6 @@ static void __init pcibios_allocate_resources(int pass) | |||
| 181 | "BAR %d: reserving %pr (d=%d, p=%d)\n", | 178 | "BAR %d: reserving %pr (d=%d, p=%d)\n", |
| 182 | idx, r, disabled, pass); | 179 | idx, r, disabled, pass); |
| 183 | if (pci_claim_resource(dev, idx) < 0) { | 180 | if (pci_claim_resource(dev, idx) < 0) { |
| 184 | dev_info(&dev->dev, | ||
| 185 | "can't reserve %pR\n", r); | ||
| 186 | /* We'll assign a new address later */ | 181 | /* We'll assign a new address later */ |
| 187 | r->end -= r->start; | 182 | r->end -= r->start; |
| 188 | r->start = 0; | 183 | r->start = 0; |
diff --git a/drivers/gpu/drm/radeon/radeon_irq_kms.c b/drivers/gpu/drm/radeon/radeon_irq_kms.c index 3cfd60fd0083..ea4c645ece11 100644 --- a/drivers/gpu/drm/radeon/radeon_irq_kms.c +++ b/drivers/gpu/drm/radeon/radeon_irq_kms.c | |||
| @@ -116,13 +116,7 @@ int radeon_irq_kms_init(struct radeon_device *rdev) | |||
| 116 | } | 116 | } |
| 117 | /* enable msi */ | 117 | /* enable msi */ |
| 118 | rdev->msi_enabled = 0; | 118 | rdev->msi_enabled = 0; |
| 119 | /* MSIs don't seem to work on my rs780; | 119 | if (rdev->family >= CHIP_RV380) { |
| 120 | * not sure about rs880 or other rs780s. | ||
| 121 | * Needs more investigation. | ||
| 122 | */ | ||
| 123 | if ((rdev->family >= CHIP_RV380) && | ||
| 124 | (rdev->family != CHIP_RS780) && | ||
| 125 | (rdev->family != CHIP_RS880)) { | ||
| 126 | int ret = pci_enable_msi(rdev->pdev); | 120 | int ret = pci_enable_msi(rdev->pdev); |
| 127 | if (!ret) { | 121 | if (!ret) { |
| 128 | rdev->msi_enabled = 1; | 122 | rdev->msi_enabled = 1; |
diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c index 40b48f569b1e..9665d6b17a2a 100644 --- a/drivers/pci/hotplug/pciehp_hpc.c +++ b/drivers/pci/hotplug/pciehp_hpc.c | |||
| @@ -832,9 +832,8 @@ static inline void dbg_ctrl(struct controller *ctrl) | |||
| 832 | for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) { | 832 | for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) { |
| 833 | if (!pci_resource_len(pdev, i)) | 833 | if (!pci_resource_len(pdev, i)) |
| 834 | continue; | 834 | continue; |
| 835 | ctrl_info(ctrl, " PCI resource [%d] : 0x%llx@0x%llx\n", | 835 | ctrl_info(ctrl, " PCI resource [%d] : %pR\n", |
| 836 | i, (unsigned long long)pci_resource_len(pdev, i), | 836 | i, &pdev->resource[i]); |
| 837 | (unsigned long long)pci_resource_start(pdev, i)); | ||
| 838 | } | 837 | } |
| 839 | ctrl_info(ctrl, "Slot Capabilities : 0x%08x\n", ctrl->slot_cap); | 838 | ctrl_info(ctrl, "Slot Capabilities : 0x%08x\n", ctrl->slot_cap); |
| 840 | ctrl_info(ctrl, " Physical Slot Number : %d\n", PSN(ctrl)); | 839 | ctrl_info(ctrl, " Physical Slot Number : %d\n", PSN(ctrl)); |
diff --git a/drivers/pci/ioapic.c b/drivers/pci/ioapic.c index 3e0d7b5dd1b9..fb9fdf4a42bf 100644 --- a/drivers/pci/ioapic.c +++ b/drivers/pci/ioapic.c | |||
| @@ -31,9 +31,9 @@ static int ioapic_probe(struct pci_dev *dev, const struct pci_device_id *ent) | |||
| 31 | acpi_status status; | 31 | acpi_status status; |
| 32 | unsigned long long gsb; | 32 | unsigned long long gsb; |
| 33 | struct ioapic *ioapic; | 33 | struct ioapic *ioapic; |
| 34 | u64 addr; | ||
| 35 | int ret; | 34 | int ret; |
| 36 | char *type; | 35 | char *type; |
| 36 | struct resource *res; | ||
| 37 | 37 | ||
| 38 | handle = DEVICE_ACPI_HANDLE(&dev->dev); | 38 | handle = DEVICE_ACPI_HANDLE(&dev->dev); |
| 39 | if (!handle) | 39 | if (!handle) |
| @@ -69,13 +69,12 @@ static int ioapic_probe(struct pci_dev *dev, const struct pci_device_id *ent) | |||
| 69 | if (pci_request_region(dev, 0, type)) | 69 | if (pci_request_region(dev, 0, type)) |
| 70 | goto exit_disable; | 70 | goto exit_disable; |
| 71 | 71 | ||
| 72 | addr = pci_resource_start(dev, 0); | 72 | res = &dev->resource[0]; |
| 73 | if (acpi_register_ioapic(ioapic->handle, addr, ioapic->gsi_base)) | 73 | if (acpi_register_ioapic(ioapic->handle, res->start, ioapic->gsi_base)) |
| 74 | goto exit_release; | 74 | goto exit_release; |
| 75 | 75 | ||
| 76 | pci_set_drvdata(dev, ioapic); | 76 | pci_set_drvdata(dev, ioapic); |
| 77 | dev_info(&dev->dev, "%s at %#llx, GSI %u\n", type, addr, | 77 | dev_info(&dev->dev, "%s at %pR, GSI %u\n", type, res, ioapic->gsi_base); |
| 78 | ioapic->gsi_base); | ||
| 79 | return 0; | 78 | return 0; |
| 80 | 79 | ||
| 81 | exit_release: | 80 | exit_release: |
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index cb1dd5f4988c..1531f3a49879 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c | |||
| @@ -2576,18 +2576,17 @@ EXPORT_SYMBOL_GPL(pci_reset_function); | |||
| 2576 | */ | 2576 | */ |
| 2577 | int pcix_get_max_mmrbc(struct pci_dev *dev) | 2577 | int pcix_get_max_mmrbc(struct pci_dev *dev) |
| 2578 | { | 2578 | { |
| 2579 | int err, cap; | 2579 | int cap; |
| 2580 | u32 stat; | 2580 | u32 stat; |
| 2581 | 2581 | ||
| 2582 | cap = pci_find_capability(dev, PCI_CAP_ID_PCIX); | 2582 | cap = pci_find_capability(dev, PCI_CAP_ID_PCIX); |
| 2583 | if (!cap) | 2583 | if (!cap) |
| 2584 | return -EINVAL; | 2584 | return -EINVAL; |
| 2585 | 2585 | ||
| 2586 | err = pci_read_config_dword(dev, cap + PCI_X_STATUS, &stat); | 2586 | if (pci_read_config_dword(dev, cap + PCI_X_STATUS, &stat)) |
| 2587 | if (err) | ||
| 2588 | return -EINVAL; | 2587 | return -EINVAL; |
| 2589 | 2588 | ||
| 2590 | return (stat & PCI_X_STATUS_MAX_READ) >> 12; | 2589 | return 512 << ((stat & PCI_X_STATUS_MAX_READ) >> 21); |
| 2591 | } | 2590 | } |
| 2592 | EXPORT_SYMBOL(pcix_get_max_mmrbc); | 2591 | EXPORT_SYMBOL(pcix_get_max_mmrbc); |
| 2593 | 2592 | ||
| @@ -2600,18 +2599,17 @@ EXPORT_SYMBOL(pcix_get_max_mmrbc); | |||
| 2600 | */ | 2599 | */ |
| 2601 | int pcix_get_mmrbc(struct pci_dev *dev) | 2600 | int pcix_get_mmrbc(struct pci_dev *dev) |
| 2602 | { | 2601 | { |
| 2603 | int ret, cap; | 2602 | int cap; |
| 2604 | u32 cmd; | 2603 | u16 cmd; |
| 2605 | 2604 | ||
| 2606 | cap = pci_find_capability(dev, PCI_CAP_ID_PCIX); | 2605 | cap = pci_find_capability(dev, PCI_CAP_ID_PCIX); |
| 2607 | if (!cap) | 2606 | if (!cap) |
| 2608 | return -EINVAL; | 2607 | return -EINVAL; |
| 2609 | 2608 | ||
| 2610 | ret = pci_read_config_dword(dev, cap + PCI_X_CMD, &cmd); | 2609 | if (pci_read_config_word(dev, cap + PCI_X_CMD, &cmd)) |
| 2611 | if (!ret) | 2610 | return -EINVAL; |
| 2612 | ret = 512 << ((cmd & PCI_X_CMD_MAX_READ) >> 2); | ||
| 2613 | 2611 | ||
| 2614 | return ret; | 2612 | return 512 << ((cmd & PCI_X_CMD_MAX_READ) >> 2); |
| 2615 | } | 2613 | } |
| 2616 | EXPORT_SYMBOL(pcix_get_mmrbc); | 2614 | EXPORT_SYMBOL(pcix_get_mmrbc); |
| 2617 | 2615 | ||
| @@ -2626,28 +2624,27 @@ EXPORT_SYMBOL(pcix_get_mmrbc); | |||
| 2626 | */ | 2624 | */ |
| 2627 | int pcix_set_mmrbc(struct pci_dev *dev, int mmrbc) | 2625 | int pcix_set_mmrbc(struct pci_dev *dev, int mmrbc) |
| 2628 | { | 2626 | { |
| 2629 | int cap, err = -EINVAL; | 2627 | int cap; |
| 2630 | u32 stat, cmd, v, o; | 2628 | u32 stat, v, o; |
| 2629 | u16 cmd; | ||
| 2631 | 2630 | ||
| 2632 | if (mmrbc < 512 || mmrbc > 4096 || !is_power_of_2(mmrbc)) | 2631 | if (mmrbc < 512 || mmrbc > 4096 || !is_power_of_2(mmrbc)) |
| 2633 | goto out; | 2632 | return -EINVAL; |
| 2634 | 2633 | ||
| 2635 | v = ffs(mmrbc) - 10; | 2634 | v = ffs(mmrbc) - 10; |
| 2636 | 2635 | ||
| 2637 | cap = pci_find_capability(dev, PCI_CAP_ID_PCIX); | 2636 | cap = pci_find_capability(dev, PCI_CAP_ID_PCIX); |
| 2638 | if (!cap) | 2637 | if (!cap) |
| 2639 | goto out; | 2638 | return -EINVAL; |
| 2640 | 2639 | ||
| 2641 | err = pci_read_config_dword(dev, cap + PCI_X_STATUS, &stat); | 2640 | if (pci_read_config_dword(dev, cap + PCI_X_STATUS, &stat)) |
| 2642 | if (err) | 2641 | return -EINVAL; |
| 2643 | goto out; | ||
| 2644 | 2642 | ||
| 2645 | if (v > (stat & PCI_X_STATUS_MAX_READ) >> 21) | 2643 | if (v > (stat & PCI_X_STATUS_MAX_READ) >> 21) |
| 2646 | return -E2BIG; | 2644 | return -E2BIG; |
| 2647 | 2645 | ||
| 2648 | err = pci_read_config_dword(dev, cap + PCI_X_CMD, &cmd); | 2646 | if (pci_read_config_word(dev, cap + PCI_X_CMD, &cmd)) |
| 2649 | if (err) | 2647 | return -EINVAL; |
| 2650 | goto out; | ||
| 2651 | 2648 | ||
| 2652 | o = (cmd & PCI_X_CMD_MAX_READ) >> 2; | 2649 | o = (cmd & PCI_X_CMD_MAX_READ) >> 2; |
| 2653 | if (o != v) { | 2650 | if (o != v) { |
| @@ -2657,10 +2654,10 @@ int pcix_set_mmrbc(struct pci_dev *dev, int mmrbc) | |||
| 2657 | 2654 | ||
| 2658 | cmd &= ~PCI_X_CMD_MAX_READ; | 2655 | cmd &= ~PCI_X_CMD_MAX_READ; |
| 2659 | cmd |= v << 2; | 2656 | cmd |= v << 2; |
| 2660 | err = pci_write_config_dword(dev, cap + PCI_X_CMD, cmd); | 2657 | if (pci_write_config_word(dev, cap + PCI_X_CMD, cmd)) |
| 2658 | return -EIO; | ||
| 2661 | } | 2659 | } |
| 2662 | out: | 2660 | return 0; |
| 2663 | return err; | ||
| 2664 | } | 2661 | } |
| 2665 | EXPORT_SYMBOL(pcix_set_mmrbc); | 2662 | EXPORT_SYMBOL(pcix_set_mmrbc); |
| 2666 | 2663 | ||
| @@ -3023,7 +3020,6 @@ EXPORT_SYMBOL(pcim_pin_device); | |||
| 3023 | EXPORT_SYMBOL(pci_disable_device); | 3020 | EXPORT_SYMBOL(pci_disable_device); |
| 3024 | EXPORT_SYMBOL(pci_find_capability); | 3021 | EXPORT_SYMBOL(pci_find_capability); |
| 3025 | EXPORT_SYMBOL(pci_bus_find_capability); | 3022 | EXPORT_SYMBOL(pci_bus_find_capability); |
| 3026 | EXPORT_SYMBOL(pci_register_set_vga_state); | ||
| 3027 | EXPORT_SYMBOL(pci_release_regions); | 3023 | EXPORT_SYMBOL(pci_release_regions); |
| 3028 | EXPORT_SYMBOL(pci_request_regions); | 3024 | EXPORT_SYMBOL(pci_request_regions); |
| 3029 | EXPORT_SYMBOL(pci_request_regions_exclusive); | 3025 | EXPORT_SYMBOL(pci_request_regions_exclusive); |
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 2a943090a3b7..882bd8d29fe3 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c | |||
| @@ -174,14 +174,19 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type, | |||
| 174 | pci_read_config_dword(dev, pos, &sz); | 174 | pci_read_config_dword(dev, pos, &sz); |
| 175 | pci_write_config_dword(dev, pos, l); | 175 | pci_write_config_dword(dev, pos, l); |
| 176 | 176 | ||
| 177 | if (!sz) | ||
| 178 | goto fail; /* BAR not implemented */ | ||
| 179 | |||
| 177 | /* | 180 | /* |
| 178 | * All bits set in sz means the device isn't working properly. | 181 | * All bits set in sz means the device isn't working properly. |
| 179 | * If the BAR isn't implemented, all bits must be 0. If it's a | 182 | * If it's a memory BAR or a ROM, bit 0 must be clear; if it's |
| 180 | * memory BAR or a ROM, bit 0 must be clear; if it's an io BAR, bit | 183 | * an io BAR, bit 1 must be clear. |
| 181 | * 1 must be clear. | ||
| 182 | */ | 184 | */ |
| 183 | if (!sz || sz == 0xffffffff) | 185 | if (sz == 0xffffffff) { |
| 186 | dev_err(&dev->dev, "reg %x: invalid size %#x; broken device?\n", | ||
| 187 | pos, sz); | ||
| 184 | goto fail; | 188 | goto fail; |
| 189 | } | ||
| 185 | 190 | ||
| 186 | /* | 191 | /* |
| 187 | * I don't know how l can have all bits set. Copied from old code. | 192 | * I don't know how l can have all bits set. Copied from old code. |
| @@ -244,13 +249,17 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type, | |||
| 244 | pos, res); | 249 | pos, res); |
| 245 | } | 250 | } |
| 246 | } else { | 251 | } else { |
| 247 | sz = pci_size(l, sz, mask); | 252 | u32 size = pci_size(l, sz, mask); |
| 248 | 253 | ||
| 249 | if (!sz) | 254 | if (!size) { |
| 255 | dev_err(&dev->dev, "reg %x: invalid size " | ||
| 256 | "(l %#x sz %#x mask %#x); broken device?", | ||
| 257 | pos, l, sz, mask); | ||
| 250 | goto fail; | 258 | goto fail; |
| 259 | } | ||
| 251 | 260 | ||
| 252 | res->start = l; | 261 | res->start = l; |
| 253 | res->end = l + sz; | 262 | res->end = l + size; |
| 254 | 263 | ||
| 255 | dev_printk(KERN_DEBUG, &dev->dev, "reg %x: %pR\n", pos, res); | 264 | dev_printk(KERN_DEBUG, &dev->dev, "reg %x: %pR\n", pos, res); |
| 256 | } | 265 | } |
| @@ -312,7 +321,7 @@ static void __devinit pci_read_bridge_io(struct pci_bus *child) | |||
| 312 | dev_printk(KERN_DEBUG, &dev->dev, " bridge window %pR\n", res); | 321 | dev_printk(KERN_DEBUG, &dev->dev, " bridge window %pR\n", res); |
| 313 | } else { | 322 | } else { |
| 314 | dev_printk(KERN_DEBUG, &dev->dev, | 323 | dev_printk(KERN_DEBUG, &dev->dev, |
| 315 | " bridge window [io %04lx - %04lx] reg reading\n", | 324 | " bridge window [io %#06lx-%#06lx] (disabled)\n", |
| 316 | base, limit); | 325 | base, limit); |
| 317 | } | 326 | } |
| 318 | } | 327 | } |
| @@ -336,7 +345,7 @@ static void __devinit pci_read_bridge_mmio(struct pci_bus *child) | |||
| 336 | dev_printk(KERN_DEBUG, &dev->dev, " bridge window %pR\n", res); | 345 | dev_printk(KERN_DEBUG, &dev->dev, " bridge window %pR\n", res); |
| 337 | } else { | 346 | } else { |
| 338 | dev_printk(KERN_DEBUG, &dev->dev, | 347 | dev_printk(KERN_DEBUG, &dev->dev, |
| 339 | " bridge window [mem 0x%08lx - 0x%08lx] reg reading\n", | 348 | " bridge window [mem %#010lx-%#010lx] (disabled)\n", |
| 340 | base, limit + 0xfffff); | 349 | base, limit + 0xfffff); |
| 341 | } | 350 | } |
| 342 | } | 351 | } |
| @@ -387,7 +396,7 @@ static void __devinit pci_read_bridge_mmio_pref(struct pci_bus *child) | |||
| 387 | dev_printk(KERN_DEBUG, &dev->dev, " bridge window %pR\n", res); | 396 | dev_printk(KERN_DEBUG, &dev->dev, " bridge window %pR\n", res); |
| 388 | } else { | 397 | } else { |
| 389 | dev_printk(KERN_DEBUG, &dev->dev, | 398 | dev_printk(KERN_DEBUG, &dev->dev, |
| 390 | " bridge window [mem 0x%08lx - %08lx pref] reg reading\n", | 399 | " bridge window [mem %#010lx-%#010lx pref] (disabled)\n", |
| 391 | base, limit + 0xfffff); | 400 | base, limit + 0xfffff); |
| 392 | } | 401 | } |
| 393 | } | 402 | } |
| @@ -673,16 +682,20 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max, | |||
| 673 | int is_cardbus = (dev->hdr_type == PCI_HEADER_TYPE_CARDBUS); | 682 | int is_cardbus = (dev->hdr_type == PCI_HEADER_TYPE_CARDBUS); |
| 674 | u32 buses, i, j = 0; | 683 | u32 buses, i, j = 0; |
| 675 | u16 bctl; | 684 | u16 bctl; |
| 685 | u8 primary, secondary, subordinate; | ||
| 676 | int broken = 0; | 686 | int broken = 0; |
| 677 | 687 | ||
| 678 | pci_read_config_dword(dev, PCI_PRIMARY_BUS, &buses); | 688 | pci_read_config_dword(dev, PCI_PRIMARY_BUS, &buses); |
| 689 | primary = buses & 0xFF; | ||
| 690 | secondary = (buses >> 8) & 0xFF; | ||
| 691 | subordinate = (buses >> 16) & 0xFF; | ||
| 679 | 692 | ||
| 680 | dev_dbg(&dev->dev, "scanning behind bridge, config %06x, pass %d\n", | 693 | dev_dbg(&dev->dev, "scanning [bus %02x-%02x] behind bridge, pass %d\n", |
| 681 | buses & 0xffffff, pass); | 694 | secondary, subordinate, pass); |
| 682 | 695 | ||
| 683 | /* Check if setup is sensible at all */ | 696 | /* Check if setup is sensible at all */ |
| 684 | if (!pass && | 697 | if (!pass && |
| 685 | ((buses & 0xff) != bus->number || ((buses >> 8) & 0xff) <= bus->number)) { | 698 | (primary != bus->number || secondary <= bus->number)) { |
| 686 | dev_dbg(&dev->dev, "bus configuration invalid, reconfiguring\n"); | 699 | dev_dbg(&dev->dev, "bus configuration invalid, reconfiguring\n"); |
| 687 | broken = 1; | 700 | broken = 1; |
| 688 | } | 701 | } |
| @@ -693,15 +706,15 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max, | |||
| 693 | pci_write_config_word(dev, PCI_BRIDGE_CONTROL, | 706 | pci_write_config_word(dev, PCI_BRIDGE_CONTROL, |
| 694 | bctl & ~PCI_BRIDGE_CTL_MASTER_ABORT); | 707 | bctl & ~PCI_BRIDGE_CTL_MASTER_ABORT); |
| 695 | 708 | ||
| 696 | if ((buses & 0xffff00) && !pcibios_assign_all_busses() && !is_cardbus && !broken) { | 709 | if ((secondary || subordinate) && !pcibios_assign_all_busses() && |
| 697 | unsigned int cmax, busnr; | 710 | !is_cardbus && !broken) { |
| 711 | unsigned int cmax; | ||
| 698 | /* | 712 | /* |
| 699 | * Bus already configured by firmware, process it in the first | 713 | * Bus already configured by firmware, process it in the first |
| 700 | * pass and just note the configuration. | 714 | * pass and just note the configuration. |
| 701 | */ | 715 | */ |
| 702 | if (pass) | 716 | if (pass) |
| 703 | goto out; | 717 | goto out; |
| 704 | busnr = (buses >> 8) & 0xFF; | ||
| 705 | 718 | ||
| 706 | /* | 719 | /* |
| 707 | * If we already got to this bus through a different bridge, | 720 | * If we already got to this bus through a different bridge, |
| @@ -710,13 +723,13 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max, | |||
| 710 | * However, we continue to descend down the hierarchy and | 723 | * However, we continue to descend down the hierarchy and |
| 711 | * scan remaining child buses. | 724 | * scan remaining child buses. |
| 712 | */ | 725 | */ |
| 713 | child = pci_find_bus(pci_domain_nr(bus), busnr); | 726 | child = pci_find_bus(pci_domain_nr(bus), secondary); |
| 714 | if (!child) { | 727 | if (!child) { |
| 715 | child = pci_add_new_bus(bus, dev, busnr); | 728 | child = pci_add_new_bus(bus, dev, secondary); |
| 716 | if (!child) | 729 | if (!child) |
| 717 | goto out; | 730 | goto out; |
| 718 | child->primary = buses & 0xFF; | 731 | child->primary = primary; |
| 719 | child->subordinate = (buses >> 16) & 0xFF; | 732 | child->subordinate = subordinate; |
| 720 | child->bridge_ctl = bctl; | 733 | child->bridge_ctl = bctl; |
| 721 | } | 734 | } |
| 722 | 735 | ||
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 81d19d5683ac..3ea0b29c0104 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c | |||
| @@ -368,8 +368,9 @@ static void __devinit quirk_io_region(struct pci_dev *dev, unsigned region, | |||
| 368 | bus_region.end = res->end; | 368 | bus_region.end = res->end; |
| 369 | pcibios_bus_to_resource(dev, res, &bus_region); | 369 | pcibios_bus_to_resource(dev, res, &bus_region); |
| 370 | 370 | ||
| 371 | pci_claim_resource(dev, nr); | 371 | if (pci_claim_resource(dev, nr) == 0) |
| 372 | dev_info(&dev->dev, "quirk: %pR claimed by %s\n", res, name); | 372 | dev_info(&dev->dev, "quirk: %pR claimed by %s\n", |
| 373 | res, name); | ||
| 373 | } | 374 | } |
| 374 | } | 375 | } |
| 375 | 376 | ||
| @@ -1977,11 +1978,25 @@ static void __devinit quirk_via_cx700_pci_parking_caching(struct pci_dev *dev) | |||
| 1977 | /* | 1978 | /* |
| 1978 | * Disable PCI Bus Parking and PCI Master read caching on CX700 | 1979 | * Disable PCI Bus Parking and PCI Master read caching on CX700 |
| 1979 | * which causes unspecified timing errors with a VT6212L on the PCI | 1980 | * which causes unspecified timing errors with a VT6212L on the PCI |
| 1980 | * bus leading to USB2.0 packet loss. The defaults are that these | 1981 | * bus leading to USB2.0 packet loss. |
| 1981 | * features are turned off but some BIOSes turn them on. | 1982 | * |
| 1983 | * This quirk is only enabled if a second (on the external PCI bus) | ||
| 1984 | * VT6212L is found -- the CX700 core itself also contains a USB | ||
| 1985 | * host controller with the same PCI ID as the VT6212L. | ||
| 1982 | */ | 1986 | */ |
| 1983 | 1987 | ||
| 1988 | /* Count VT6212L instances */ | ||
| 1989 | struct pci_dev *p = pci_get_device(PCI_VENDOR_ID_VIA, | ||
| 1990 | PCI_DEVICE_ID_VIA_8235_USB_2, NULL); | ||
| 1984 | uint8_t b; | 1991 | uint8_t b; |
| 1992 | |||
| 1993 | /* p should contain the first (internal) VT6212L -- see if we have | ||
| 1994 | an external one by searching again */ | ||
| 1995 | p = pci_get_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8235_USB_2, p); | ||
| 1996 | if (!p) | ||
| 1997 | return; | ||
| 1998 | pci_dev_put(p); | ||
| 1999 | |||
| 1985 | if (pci_read_config_byte(dev, 0x76, &b) == 0) { | 2000 | if (pci_read_config_byte(dev, 0x76, &b) == 0) { |
| 1986 | if (b & 0x40) { | 2001 | if (b & 0x40) { |
| 1987 | /* Turn off PCI Bus Parking */ | 2002 | /* Turn off PCI Bus Parking */ |
| @@ -2008,7 +2023,7 @@ static void __devinit quirk_via_cx700_pci_parking_caching(struct pci_dev *dev) | |||
| 2008 | } | 2023 | } |
| 2009 | } | 2024 | } |
| 2010 | } | 2025 | } |
| 2011 | DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_VIA, 0x324e, quirk_via_cx700_pci_parking_caching); | 2026 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, 0x324e, quirk_via_cx700_pci_parking_caching); |
| 2012 | 2027 | ||
| 2013 | /* | 2028 | /* |
| 2014 | * For Broadcom 5706, 5708, 5709 rev. A nics, any read beyond the | 2029 | * For Broadcom 5706, 5708, 5709 rev. A nics, any read beyond the |
| @@ -2108,6 +2123,7 @@ static void __devinit quirk_disable_msi(struct pci_dev *dev) | |||
| 2108 | } | 2123 | } |
| 2109 | } | 2124 | } |
| 2110 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8131_BRIDGE, quirk_disable_msi); | 2125 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8131_BRIDGE, quirk_disable_msi); |
| 2126 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, 0xa238, quirk_disable_msi); | ||
| 2111 | 2127 | ||
| 2112 | /* Go through the list of Hypertransport capabilities and | 2128 | /* Go through the list of Hypertransport capabilities and |
| 2113 | * return 1 if a HT MSI capability is found and enabled */ | 2129 | * return 1 if a HT MSI capability is found and enabled */ |
| @@ -2479,6 +2495,39 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x4374, | |||
| 2479 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x4375, | 2495 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x4375, |
| 2480 | quirk_msi_intx_disable_bug); | 2496 | quirk_msi_intx_disable_bug); |
| 2481 | 2497 | ||
| 2498 | /* | ||
| 2499 | * MSI does not work with the AMD RS780/RS880 internal graphics and HDMI audio | ||
| 2500 | * devices unless the BIOS has initialized the nb_cntl.strap_msi_enable bit. | ||
| 2501 | */ | ||
| 2502 | static void __init rs780_int_gfx_disable_msi(struct pci_dev *int_gfx_bridge) | ||
| 2503 | { | ||
| 2504 | u32 nb_cntl; | ||
| 2505 | |||
| 2506 | if (!int_gfx_bridge->subordinate) | ||
| 2507 | return; | ||
| 2508 | |||
| 2509 | pci_bus_write_config_dword(int_gfx_bridge->bus, PCI_DEVFN(0, 0), | ||
| 2510 | 0x60, 0); | ||
| 2511 | pci_bus_read_config_dword(int_gfx_bridge->bus, PCI_DEVFN(0, 0), | ||
| 2512 | 0x64, &nb_cntl); | ||
| 2513 | |||
| 2514 | if (!(nb_cntl & BIT(10))) { | ||
| 2515 | dev_warn(&int_gfx_bridge->dev, | ||
| 2516 | FW_WARN "RS780: MSI for internal graphics disabled\n"); | ||
| 2517 | int_gfx_bridge->subordinate->bus_flags |= PCI_BUS_FLAGS_NO_MSI; | ||
| 2518 | } | ||
| 2519 | } | ||
| 2520 | |||
| 2521 | #define PCI_DEVICE_ID_AMD_RS780_P2P_INT_GFX 0x9602 | ||
| 2522 | |||
| 2523 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, | ||
| 2524 | PCI_DEVICE_ID_AMD_RS780_P2P_INT_GFX, | ||
| 2525 | rs780_int_gfx_disable_msi); | ||
| 2526 | /* wrong vendor ID on M4A785TD motherboard: */ | ||
| 2527 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ASUSTEK, | ||
| 2528 | PCI_DEVICE_ID_AMD_RS780_P2P_INT_GFX, | ||
| 2529 | rs780_int_gfx_disable_msi); | ||
| 2530 | |||
| 2482 | #endif /* CONFIG_PCI_MSI */ | 2531 | #endif /* CONFIG_PCI_MSI */ |
| 2483 | 2532 | ||
| 2484 | #ifdef CONFIG_PCI_IOV | 2533 | #ifdef CONFIG_PCI_IOV |
diff --git a/drivers/pci/setup-res.c b/drivers/pci/setup-res.c index 7d678bb15ffb..17bed18d24ad 100644 --- a/drivers/pci/setup-res.c +++ b/drivers/pci/setup-res.c | |||
| @@ -93,8 +93,7 @@ void pci_update_resource(struct pci_dev *dev, int resno) | |||
| 93 | int pci_claim_resource(struct pci_dev *dev, int resource) | 93 | int pci_claim_resource(struct pci_dev *dev, int resource) |
| 94 | { | 94 | { |
| 95 | struct resource *res = &dev->resource[resource]; | 95 | struct resource *res = &dev->resource[resource]; |
| 96 | struct resource *root; | 96 | struct resource *root, *conflict; |
| 97 | int err; | ||
| 98 | 97 | ||
| 99 | root = pci_find_parent_resource(dev, res); | 98 | root = pci_find_parent_resource(dev, res); |
| 100 | if (!root) { | 99 | if (!root) { |
| @@ -103,12 +102,15 @@ int pci_claim_resource(struct pci_dev *dev, int resource) | |||
| 103 | return -EINVAL; | 102 | return -EINVAL; |
| 104 | } | 103 | } |
| 105 | 104 | ||
| 106 | err = request_resource(root, res); | 105 | conflict = request_resource_conflict(root, res); |
| 107 | if (err) | 106 | if (conflict) { |
| 108 | dev_err(&dev->dev, | 107 | dev_err(&dev->dev, |
| 109 | "address space collision: %pR already in use\n", res); | 108 | "address space collision: %pR conflicts with %s %pR\n", |
| 109 | res, conflict->name, conflict); | ||
| 110 | return -EBUSY; | ||
| 111 | } | ||
| 110 | 112 | ||
| 111 | return err; | 113 | return 0; |
| 112 | } | 114 | } |
| 113 | EXPORT_SYMBOL(pci_claim_resource); | 115 | EXPORT_SYMBOL(pci_claim_resource); |
| 114 | 116 | ||
diff --git a/drivers/pcmcia/rsrc_nonstatic.c b/drivers/pcmcia/rsrc_nonstatic.c index dcc602134d90..2e47991eccf6 100644 --- a/drivers/pcmcia/rsrc_nonstatic.c +++ b/drivers/pcmcia/rsrc_nonstatic.c | |||
| @@ -874,10 +874,8 @@ static int nonstatic_autoadd_resources(struct pcmcia_socket *s) | |||
| 874 | if (res == &ioport_resource) | 874 | if (res == &ioport_resource) |
| 875 | continue; | 875 | continue; |
| 876 | dev_printk(KERN_INFO, &s->cb_dev->dev, | 876 | dev_printk(KERN_INFO, &s->cb_dev->dev, |
| 877 | "pcmcia: parent PCI bridge I/O " | 877 | "pcmcia: parent PCI bridge window: %pR\n", |
| 878 | "window: 0x%llx - 0x%llx\n", | 878 | res); |
| 879 | (unsigned long long)res->start, | ||
| 880 | (unsigned long long)res->end); | ||
| 881 | if (!adjust_io(s, ADD_MANAGED_RESOURCE, res->start, res->end)) | 879 | if (!adjust_io(s, ADD_MANAGED_RESOURCE, res->start, res->end)) |
| 882 | done |= IORESOURCE_IO; | 880 | done |= IORESOURCE_IO; |
| 883 | 881 | ||
| @@ -887,10 +885,8 @@ static int nonstatic_autoadd_resources(struct pcmcia_socket *s) | |||
| 887 | if (res == &iomem_resource) | 885 | if (res == &iomem_resource) |
| 888 | continue; | 886 | continue; |
| 889 | dev_printk(KERN_INFO, &s->cb_dev->dev, | 887 | dev_printk(KERN_INFO, &s->cb_dev->dev, |
| 890 | "pcmcia: parent PCI bridge Memory " | 888 | "pcmcia: parent PCI bridge window: %pR\n", |
| 891 | "window: 0x%llx - 0x%llx\n", | 889 | res); |
| 892 | (unsigned long long)res->start, | ||
| 893 | (unsigned long long)res->end); | ||
| 894 | if (!adjust_memory(s, ADD_MANAGED_RESOURCE, res->start, res->end)) | 890 | if (!adjust_memory(s, ADD_MANAGED_RESOURCE, res->start, res->end)) |
| 895 | done |= IORESOURCE_MEM; | 891 | done |= IORESOURCE_MEM; |
| 896 | } | 892 | } |
diff --git a/include/linux/ioport.h b/include/linux/ioport.h index 71ab79da7e7f..26fad187d661 100644 --- a/include/linux/ioport.h +++ b/include/linux/ioport.h | |||
| @@ -112,12 +112,14 @@ struct resource_list { | |||
| 112 | extern struct resource ioport_resource; | 112 | extern struct resource ioport_resource; |
| 113 | extern struct resource iomem_resource; | 113 | extern struct resource iomem_resource; |
| 114 | 114 | ||
| 115 | extern struct resource *request_resource_conflict(struct resource *root, struct resource *new); | ||
| 115 | extern int request_resource(struct resource *root, struct resource *new); | 116 | extern int request_resource(struct resource *root, struct resource *new); |
| 116 | extern int release_resource(struct resource *new); | 117 | extern int release_resource(struct resource *new); |
| 117 | void release_child_resources(struct resource *new); | 118 | void release_child_resources(struct resource *new); |
| 118 | extern void reserve_region_with_split(struct resource *root, | 119 | extern void reserve_region_with_split(struct resource *root, |
| 119 | resource_size_t start, resource_size_t end, | 120 | resource_size_t start, resource_size_t end, |
| 120 | const char *name); | 121 | const char *name); |
| 122 | extern struct resource *insert_resource_conflict(struct resource *parent, struct resource *new); | ||
| 121 | extern int insert_resource(struct resource *parent, struct resource *new); | 123 | extern int insert_resource(struct resource *parent, struct resource *new); |
| 122 | extern void insert_resource_expand_to_fit(struct resource *root, struct resource *new); | 124 | extern void insert_resource_expand_to_fit(struct resource *root, struct resource *new); |
| 123 | extern int allocate_resource(struct resource *root, struct resource *new, | 125 | extern int allocate_resource(struct resource *root, struct resource *new, |
diff --git a/kernel/resource.c b/kernel/resource.c index 2d5be5d9bf5f..9c358e263534 100644 --- a/kernel/resource.c +++ b/kernel/resource.c | |||
| @@ -219,19 +219,34 @@ void release_child_resources(struct resource *r) | |||
| 219 | } | 219 | } |
| 220 | 220 | ||
| 221 | /** | 221 | /** |
| 222 | * request_resource - request and reserve an I/O or memory resource | 222 | * request_resource_conflict - request and reserve an I/O or memory resource |
| 223 | * @root: root resource descriptor | 223 | * @root: root resource descriptor |
| 224 | * @new: resource descriptor desired by caller | 224 | * @new: resource descriptor desired by caller |
| 225 | * | 225 | * |
| 226 | * Returns 0 for success, negative error code on error. | 226 | * Returns 0 for success, conflict resource on error. |
| 227 | */ | 227 | */ |
| 228 | int request_resource(struct resource *root, struct resource *new) | 228 | struct resource *request_resource_conflict(struct resource *root, struct resource *new) |
| 229 | { | 229 | { |
| 230 | struct resource *conflict; | 230 | struct resource *conflict; |
| 231 | 231 | ||
| 232 | write_lock(&resource_lock); | 232 | write_lock(&resource_lock); |
| 233 | conflict = __request_resource(root, new); | 233 | conflict = __request_resource(root, new); |
| 234 | write_unlock(&resource_lock); | 234 | write_unlock(&resource_lock); |
| 235 | return conflict; | ||
| 236 | } | ||
| 237 | |||
| 238 | /** | ||
| 239 | * request_resource - request and reserve an I/O or memory resource | ||
| 240 | * @root: root resource descriptor | ||
| 241 | * @new: resource descriptor desired by caller | ||
| 242 | * | ||
| 243 | * Returns 0 for success, negative error code on error. | ||
| 244 | */ | ||
| 245 | int request_resource(struct resource *root, struct resource *new) | ||
| 246 | { | ||
| 247 | struct resource *conflict; | ||
| 248 | |||
| 249 | conflict = request_resource_conflict(root, new); | ||
| 235 | return conflict ? -EBUSY : 0; | 250 | return conflict ? -EBUSY : 0; |
| 236 | } | 251 | } |
| 237 | 252 | ||
| @@ -474,25 +489,40 @@ static struct resource * __insert_resource(struct resource *parent, struct resou | |||
| 474 | } | 489 | } |
| 475 | 490 | ||
| 476 | /** | 491 | /** |
| 477 | * insert_resource - Inserts a resource in the resource tree | 492 | * insert_resource_conflict - Inserts resource in the resource tree |
| 478 | * @parent: parent of the new resource | 493 | * @parent: parent of the new resource |
| 479 | * @new: new resource to insert | 494 | * @new: new resource to insert |
| 480 | * | 495 | * |
| 481 | * Returns 0 on success, -EBUSY if the resource can't be inserted. | 496 | * Returns 0 on success, conflict resource if the resource can't be inserted. |
| 482 | * | 497 | * |
| 483 | * This function is equivalent to request_resource when no conflict | 498 | * This function is equivalent to request_resource_conflict when no conflict |
| 484 | * happens. If a conflict happens, and the conflicting resources | 499 | * happens. If a conflict happens, and the conflicting resources |
| 485 | * entirely fit within the range of the new resource, then the new | 500 | * entirely fit within the range of the new resource, then the new |
| 486 | * resource is inserted and the conflicting resources become children of | 501 | * resource is inserted and the conflicting resources become children of |
| 487 | * the new resource. | 502 | * the new resource. |
| 488 | */ | 503 | */ |
| 489 | int insert_resource(struct resource *parent, struct resource *new) | 504 | struct resource *insert_resource_conflict(struct resource *parent, struct resource *new) |
| 490 | { | 505 | { |
| 491 | struct resource *conflict; | 506 | struct resource *conflict; |
| 492 | 507 | ||
| 493 | write_lock(&resource_lock); | 508 | write_lock(&resource_lock); |
| 494 | conflict = __insert_resource(parent, new); | 509 | conflict = __insert_resource(parent, new); |
| 495 | write_unlock(&resource_lock); | 510 | write_unlock(&resource_lock); |
| 511 | return conflict; | ||
| 512 | } | ||
| 513 | |||
| 514 | /** | ||
| 515 | * insert_resource - Inserts a resource in the resource tree | ||
| 516 | * @parent: parent of the new resource | ||
| 517 | * @new: new resource to insert | ||
| 518 | * | ||
| 519 | * Returns 0 on success, -EBUSY if the resource can't be inserted. | ||
| 520 | */ | ||
| 521 | int insert_resource(struct resource *parent, struct resource *new) | ||
| 522 | { | ||
| 523 | struct resource *conflict; | ||
| 524 | |||
| 525 | conflict = insert_resource_conflict(parent, new); | ||
| 496 | return conflict ? -EBUSY : 0; | 526 | return conflict ? -EBUSY : 0; |
| 497 | } | 527 | } |
| 498 | 528 | ||
