Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1289199 > unrolled thread
| Started by | Yinghai Lu <yinghai@kernel.org> |
|---|---|
| First post | 2015-12-11 06:30 +0100 |
| Last post | 2015-12-11 07:10 +0100 |
| Articles | 17 — 1 participant |
Back to article view | Back to linux.kernel
[PATCH v9 00/60] PCI: Resource allocation cleanup for v4.5 Yinghai Lu <yinghai@kernel.org> - 2015-12-11 06:30 +0100
[PATCH v9 21/60] PCI: Get new realloc size for bridge for last try Yinghai Lu <yinghai@kernel.org> - 2015-12-11 06:30 +0100
[PATCH v9 08/60] powerpc/PCI: Keep resource idx order with bridge register number Yinghai Lu <yinghai@kernel.org> - 2015-12-11 06:30 +0100
[PATCH v9 09/60] powerpc/PCI: Add IORESOURCE_MEM_64 for 64-bit resource in OF parsing Yinghai Lu <yinghai@kernel.org> - 2015-12-11 06:30 +0100
[PATCH v9 22/60] PCI: Don't release sibling bridge resources during hotplug Yinghai Lu <yinghai@kernel.org> - 2015-12-11 06:30 +0100
[PATCH v9 14/60] PCI: Only treat non-pref mmio64 as pref if host bridge has mmio64 Yinghai Lu <yinghai@kernel.org> - 2015-12-11 06:30 +0100
[PATCH v9 33/60] PCI: Add debug printout during releasing partial assigned resources Yinghai Lu <yinghai@kernel.org> - 2015-12-11 06:30 +0100
[PATCH v9 40/60] PCI: Separate required+optional assigning to another function Yinghai Lu <yinghai@kernel.org> - 2015-12-11 06:30 +0100
[PATCH v9 10/60] OF/PCI: Add IORESOURCE_MEM_64 for 64-bit resource Yinghai Lu <yinghai@kernel.org> - 2015-12-11 06:40 +0100
[PATCH v9 13/60] PCI: Add has_mem64 for struct host_bridge Yinghai Lu <yinghai@kernel.org> - 2015-12-11 06:40 +0100
[PATCH v9 25/60] PCI: Use correct align for optional only resources during sorting Yinghai Lu <yinghai@kernel.org> - 2015-12-11 06:40 +0100
[PATCH v9 31/60] PCI: Rename pdev_sort_resources() to pdev_assign_resources_prepare() Yinghai Lu <yinghai@kernel.org> - 2015-12-11 07:10 +0100
[PATCH v9 56/60] PCI: Add debug print out for min_align and alt_size Yinghai Lu <yinghai@kernel.org> - 2015-12-11 07:10 +0100
[PATCH v9 46/60] PCI: Don't add too much optional size for hotplug bridge io Yinghai Lu <yinghai@kernel.org> - 2015-12-11 07:10 +0100
[PATCH v9 27/60] PCI: Optimize bus align/size calculation for optional during sizing Yinghai Lu <yinghai@kernel.org> - 2015-12-11 07:10 +0100
[PATCH v9 34/60] PCI: Simplify res reference using in __assign_resources_sorted() Yinghai Lu <yinghai@kernel.org> - 2015-12-11 07:10 +0100
[PATCH v9 43/60] PCI: Add alt_size ressource allocation support Yinghai Lu <yinghai@kernel.org> - 2015-12-11 07:10 +0100
| From | Yinghai Lu <yinghai@kernel.org> |
|---|---|
| Date | 2015-12-11 06:30 +0100 |
| Subject | [PATCH v9 00/60] PCI: Resource allocation cleanup for v4.5 |
| Message-ID | <qEo7T-84p-3@gated-at.bofh.it> |
Hi,
After 5b28541552ef (PCI: Restrict 64-bit prefetchable bridge windows
to 64-bit resources), we have several reports on resource allocation
failure, and we try to fix the problem with resource clip, and find
more problems.
One is realloc fail with two graphics cards above 4G.
One is from sparc that have problem with clip as we don't parse
mem64 for it.
Other report is about pci remove/rescan does not work on some setup
when BIOS tend to allocate small bus size.
This patchset enhance resource allocation to address those problems.
patch 1-10: parse MEM64 for sparc and other system with OF
patch 11-15: MMIO64 allocation enhancement
treat non-pref mmio64 if parent bridges are all pcie.
restore old pref allocation logic if hostbridge does not support mmio64.
patch 16-18: FIXED resource handling during realloc
don't realloc resource if device firmware does not support bar change.
patch 19-22: bridge MMIO allocation with hotplug and last try.
treat optional as required on first try when hotplug.
MMIO size set to 0 for last try during realloc
patch 23-56: enhancement for mmio resource allocation:
optimize bus mmio alignment calculation.
optimize bus mmio optional alignment calculation.
add support for alt size to prefer small bus size to small bus alignment.
treat ROM bar as optional resource.
during allocation, will pick up best fit resource, and allocate near end.
patch 57: add pci=assign_pref_bars to clear and assign pref bars.
patch 58-59: don't clear resource when allocation fails
patch 60: don't try io port allocation if root bus does not have io port.
I put latest copy at:
git://git.kernel.org/pub/scm/linux/kernel/git/yinghai/linux-yinghai.git for-pci-v4.5-next
That is based on v4.4-rc4.
Yijing and Wei Yang both tested the branch, and the patchset fixs rescan
problem, and is working well on powerpc setup.
Khalid Aziz tested on some sparc platforms that have different offset to
mem space start or support 64bit mmio.
Thanks
Yinghai
v2:
- fix resource_disabled allocation from powerpc.
- other warnings that were found by Fengguang's build robot.
- io port alignment clean up.
- rebased to v4.2-rc2.
- better for two alt_size support.
v3:
- fix reset bridge resource on last try: only with bridge resources.
- remove/rescan path checking with old_size.
v4:
- Update changelog according to Bjorn.
- split calculate_size patch to two.
- use required instead of must.
v5:
- update changelog.
- add one debug patch.
- add one patch that get resource allocation near end of avialable window.
v6:
- reorder patches according to Bjorn.
v7:
- add some patches that fix problems on sparc that Khalid Aziz found.
v8:
- update patch 2, 3 to remove the assumpation about mem64_offset == mem_offset.
- add one patch for pci_find_root_bus_resource() to support above change.
- update pref_compatible flags handling after pci_find_root_bus_resource().
- add patch for quirk that ignore BAR for M1533 PCI-ISA bridge.
v9: rebased for v4.5
Yinghai Lu (60):
PCI: Add pci_find_root_bus_resource()
sparc/PCI: Use correct bus address to resource offset
sparc/PCI: Reserve legacy mmio after PCI mmio
sparc/PCI: Add IORESOURCE_MEM_64 for 64-bit resource in OF parsing
sparc/PCI: Keep resource idx order with bridge register number
PCI: Kill wrong quirk about M7101
PCI: Ignore BAR for ALi M1533 PCI-ISA bridge
powerpc/PCI: Keep resource idx order with bridge register number
powerpc/PCI: Add IORESOURCE_MEM_64 for 64-bit resource in OF parsing
OF/PCI: Add IORESOURCE_MEM_64 for 64-bit resource
PCI: Check pref compatible bit for mem64 resource of PCIe device
PCI: Only treat non-pref mmio64 as pref if all bridges have MEM_64
PCI: Add has_mem64 for struct host_bridge
PCI: Only treat non-pref mmio64 as pref if host bridge has mmio64
PCI: Restore pref MMIO allocation logic for host bridge without mmio64
PCI: Don't release fixed resource for realloc
PCI: Claim fixed resource during remove/rescan path
PCI: Set resource to FIXED for LSI devices
PCI: Separate realloc list checking after allocation
PCI: Treat optional as required in first try for bridge rescan
PCI: Get new realloc size for bridge for last try
PCI: Don't release sibling bridge resources during hotplug
PCI: Cleanup res_to_dev_res() printout
PCI: Reuse res_to_dev_res() in reassign_resources_sorted()
PCI: Use correct align for optional only resources during sorting
PCI: Optimize bus min_align/size calculation during sizing
PCI: Optimize bus align/size calculation for optional during sizing
PCI: Don't add too much optional size for hotplug bridge MMIO
PCI: Reorder resources list for required/optional resources
PCI: Remove duplicated code for resource sorting
PCI: Rename pdev_sort_resources() to pdev_assign_resources_prepare()
PCI: Treat ROM resource as optional during realloc
PCI: Add debug printout during releasing partial assigned resources
PCI: Simplify res reference using in __assign_resources_sorted()
PCI: Add __add_to_list()
PCI: Cache window alignment value during bus sizing
PCI: Check if resource is allocated before trying to assign one
PCI: Separate out save_resources()/restore_resources()
PCI: Move comment to pci_need_to_release()
PCI: Separate required+optional assigning to another function
PCI: Skip required+optional if there is no optional
PCI: Move saved required resource list out of required+optional assigning
PCI: Add alt_size ressource allocation support
PCI: Add support for more than two alt_size entries under same bridge
PCI: Fix size calculation with old_size on rescan path
PCI: Don't add too much optional size for hotplug bridge io
PCI: Move ISA io port align out of calculate_iosize()
PCI: Don't add too much io port for hotplug bridge with old size
PCI: Unify calculate_size() for io port and MMIO
PCI: Allow bridge optional only io port resource required size to be 0
PCI: Unify skip_ioresource_align()
PCI: Kill macro checking for bus io port sizing
resources: Split out __allocate_resource()
resources: Make allocate_resource() return best fit resource
PCI, x86: Allocate from high in available window for MMIO
PCI: Add debug print out for min_align and alt_size
PCI, x86: Add pci=assign_pref_bars to reallocate pref BARs
PCI: Introduce resource_disabled()
PCI: Don't set flags to 0 when assign resource fail
PCI: Only try to assign io port only for root bus that support it
arch/alpha/kernel/pci.c | 2 +-
arch/ia64/pci/pci.c | 4 +-
arch/microblaze/pci/pci-common.c | 23 +-
arch/mn10300/unit-asb2305/pci-asb2305.c | 4 +-
arch/mn10300/unit-asb2305/pci.c | 4 +-
arch/powerpc/kernel/pci-common.c | 27 +-
arch/powerpc/kernel/pci_of_scan.c | 12 +-
arch/powerpc/platforms/powernv/pci-ioda.c | 12 +-
arch/s390/pci/pci.c | 2 +-
arch/sparc/kernel/of_device_32.c | 5 +-
arch/sparc/kernel/of_device_64.c | 5 +-
arch/sparc/kernel/pci.c | 61 +-
arch/sparc/kernel/pci_common.c | 91 +-
arch/sparc/kernel/pci_impl.h | 5 +
arch/x86/include/asm/pci_x86.h | 2 +-
arch/x86/pci/common.c | 7 +-
arch/x86/pci/i386.c | 86 +-
arch/xtensa/kernel/pci.c | 4 +-
drivers/iommu/intel-iommu.c | 3 +-
drivers/of/address.c | 4 +-
drivers/pci/bus.c | 6 +-
drivers/pci/host/pcie-rcar.c | 2 +-
drivers/pci/hotplug/acpiphp_glue.c | 1 +
drivers/pci/iov.c | 2 +-
drivers/pci/pci.c | 40 +-
drivers/pci/pci.h | 4 +
drivers/pci/probe.c | 48 +-
drivers/pci/quirks.c | 60 +-
drivers/pci/rom.c | 2 +-
drivers/pci/setup-bus.c | 1316 +++++++++++++++++++++--------
drivers/pci/setup-res.c | 18 +-
include/asm-generic/pci-bridge.h | 2 +
include/linux/ioport.h | 6 +-
include/linux/pci.h | 8 +
kernel/resource.c | 175 +++-
35 files changed, 1493 insertions(+), 560 deletions(-)
--
1.8.4.5
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [next] | [standalone]
| From | Yinghai Lu <yinghai@kernel.org> |
|---|---|
| Date | 2015-12-11 06:30 +0100 |
| Subject | [PATCH v9 21/60] PCI: Get new realloc size for bridge for last try |
| Message-ID | <qEorg-8dZ-17@gated-at.bofh.it> |
| In reply to | #1289199 |
Current realloc path would not shrink bridge resource through
pbus_size_mem() checking with the old size.
That cause problem: when "required+optional" resource allocation fails,
the cached bridge resource size will prevent "required" resource to get
allocated smaller resource.
Clear the old resource size for last try or third and later try.
Link: https://bugzilla.kernel.org/show_bug.cgi?id=81431
Tested-by: TJ <linux@iam.tj>
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
---
drivers/pci/setup-bus.c | 23 +++++++++++++++++++++--
1 file changed, 21 insertions(+), 2 deletions(-)
diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c
index e4972f5..c2e3999 100644
--- a/drivers/pci/setup-bus.c
+++ b/drivers/pci/setup-bus.c
@@ -1739,6 +1739,17 @@ static enum enable_type pci_realloc_detect(struct pci_bus *bus,
}
#endif
+static void reset_bridge_resource_size(struct pci_dev *dev,
+ struct resource *res)
+{
+ int idx = res - &dev->resource[0];
+
+ if (idx >= PCI_BRIDGE_RESOURCES && idx <= PCI_BRIDGE_RESOURCE_END) {
+ res->start = 0;
+ res->end = res->start - 1;
+ }
+}
+
/*
* first try will not touch pci bridge res
* second and later try will clear small leaf bridge res
@@ -1823,8 +1834,13 @@ again:
res->start = fail_res->start;
res->end = fail_res->end;
res->flags = fail_res->flags;
- if (fail_res->dev->subordinate)
+ if (fail_res->dev->subordinate) {
res->flags = 0;
+ /* last or third times and later */
+ if (tried_times + 1 == pci_try_num ||
+ tried_times + 1 > 2)
+ reset_bridge_resource_size(fail_res->dev, res);
+ }
}
free_list(&fail_head);
@@ -1898,8 +1914,11 @@ again:
res->start = fail_res->start;
res->end = fail_res->end;
res->flags = fail_res->flags;
- if (fail_res->dev->subordinate)
+ if (fail_res->dev->subordinate) {
res->flags = 0;
+ /* last time */
+ reset_bridge_resource_size(fail_res->dev, res);
+ }
}
free_list(&fail_head);
--
1.8.4.5
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Yinghai Lu <yinghai@kernel.org> |
|---|---|
| Date | 2015-12-11 06:30 +0100 |
| Subject | [PATCH v9 08/60] powerpc/PCI: Keep resource idx order with bridge register number |
| Message-ID | <qEorh-8dZ-25@gated-at.bofh.it> |
| In reply to | #1289199 |
Same as sparc version.
Make resource with consistent sequence
like other arch or directly from pci_read_bridge_bases(),
even non-pref mmio is missing, or out of ordering in firmware reporting.
So hold i = 1 for non pref mmio, and i = 2 for pref mmio.
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
---
arch/powerpc/kernel/pci_of_scan.c | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/arch/powerpc/kernel/pci_of_scan.c b/arch/powerpc/kernel/pci_of_scan.c
index 2e710c1..349ed11 100644
--- a/arch/powerpc/kernel/pci_of_scan.c
+++ b/arch/powerpc/kernel/pci_of_scan.c
@@ -255,7 +255,7 @@ void of_scan_pci_bridge(struct pci_dev *dev)
bus->resource[i] = res;
++res;
}
- i = 1;
+ i = 3;
for (; len >= 32; len -= 32, ranges += 8) {
flags = pci_parse_of_flags(of_read_number(ranges, 1), 1);
size = of_read_number(&ranges[6], 2);
@@ -268,6 +268,12 @@ void of_scan_pci_bridge(struct pci_dev *dev)
" for bridge %s\n", node->full_name);
continue;
}
+ } else if ((flags & IORESOURCE_PREFETCH) &&
+ !bus->resource[2]->flags) {
+ res = bus->resource[2];
+ } else if (((flags & (IORESOURCE_MEM | IORESOURCE_PREFETCH)) ==
+ IORESOURCE_MEM) && !bus->resource[1]->flags) {
+ res = bus->resource[1];
} else {
if (i >= PCI_NUM_RESOURCES - PCI_BRIDGE_RESOURCES) {
printk(KERN_ERR "PCI: too many memory ranges"
--
1.8.4.5
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Yinghai Lu <yinghai@kernel.org> |
|---|---|
| Date | 2015-12-11 06:30 +0100 |
| Subject | [PATCH v9 09/60] powerpc/PCI: Add IORESOURCE_MEM_64 for 64-bit resource in OF parsing |
| Message-ID | <qEorh-8dZ-23@gated-at.bofh.it> |
| In reply to | #1289199 |
For device resource PREF bit setting under bridge 64-bit pref resource,
we need to make sure only set PREF for 64bit resource, so set
IORESOUCE_MEM_64 for 64bit resource during of device resource flags
parsing.
Link: https://bugzilla.kernel.org/show_bug.cgi?id=96261
Link: https://bugzilla.kernel.org/show_bug.cgi?id=96241
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Michael Ellerman <mpe@ellerman.id.au>
Cc: Gavin Shan <gwshan@linux.vnet.ibm.com>
Cc: Yijing Wang <wangyijing@huawei.com>
Cc: Anton Blanchard <anton@samba.org>
Cc: linuxppc-dev@lists.ozlabs.org
---
arch/powerpc/kernel/pci_of_scan.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/arch/powerpc/kernel/pci_of_scan.c b/arch/powerpc/kernel/pci_of_scan.c
index 349ed11..d7305d7 100644
--- a/arch/powerpc/kernel/pci_of_scan.c
+++ b/arch/powerpc/kernel/pci_of_scan.c
@@ -44,8 +44,10 @@ static unsigned int pci_parse_of_flags(u32 addr0, int bridge)
if (addr0 & 0x02000000) {
flags = IORESOURCE_MEM | PCI_BASE_ADDRESS_SPACE_MEMORY;
- flags |= (addr0 >> 22) & PCI_BASE_ADDRESS_MEM_TYPE_64;
flags |= (addr0 >> 28) & PCI_BASE_ADDRESS_MEM_TYPE_1M;
+ if (addr0 & 0x01000000)
+ flags |= IORESOURCE_MEM_64
+ | PCI_BASE_ADDRESS_MEM_TYPE_64;
if (addr0 & 0x40000000)
flags |= IORESOURCE_PREFETCH
| PCI_BASE_ADDRESS_MEM_PREFETCH;
--
1.8.4.5
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Yinghai Lu <yinghai@kernel.org> |
|---|---|
| Date | 2015-12-11 06:30 +0100 |
| Subject | [PATCH v9 22/60] PCI: Don't release sibling bridge resources during hotplug |
| Message-ID | <qEorh-8dZ-35@gated-at.bofh.it> |
| In reply to | #1289199 |
On hotplug path, we can not touch sibling bridges that is outside
of the slot.
That could happen when BIOS does not assign some bridge BARs and
later kernel can not assign resource to them in first try.
Check if fail dev is the parent bridge, then just use subordinate
bus instead use parent bus.
Reported-by: Andreas Noever <andreas.noever@gmail.com>
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
---
drivers/pci/setup-bus.c | 10 ++++++++--
1 file changed, 8 insertions(+), 2 deletions(-)
diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c
index c2e3999..7f7f46c 100644
--- a/drivers/pci/setup-bus.c
+++ b/drivers/pci/setup-bus.c
@@ -1902,10 +1902,16 @@ again:
* Try to release leaf bridge's resources that doesn't fit resource of
* child device under that bridge
*/
- list_for_each_entry(fail_res, &fail_head, list)
- pci_bus_release_bridge_resources(fail_res->dev->bus,
+ list_for_each_entry(fail_res, &fail_head, list) {
+ struct pci_bus *bus = fail_res->dev->bus;
+
+ if (fail_res->dev == bridge)
+ bus = bridge->subordinate;
+
+ pci_bus_release_bridge_resources(bus,
fail_res->flags & type_mask,
whole_subtree);
+ }
/* restore size and flags */
list_for_each_entry(fail_res, &fail_head, list) {
--
1.8.4.5
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Yinghai Lu <yinghai@kernel.org> |
|---|---|
| Date | 2015-12-11 06:30 +0100 |
| Subject | [PATCH v9 14/60] PCI: Only treat non-pref mmio64 as pref if host bridge has mmio64 |
| Message-ID | <qEori-8dZ-37@gated-at.bofh.it> |
| In reply to | #1289199 |
If host bridge does not have mmio64 above 4G, We don't need to
treat device non-pref mmio64 as as pref mmio64.
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
Tested-by: Khalid Aziz <khalid.aziz@oracle.com>
---
drivers/pci/setup-bus.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c
index d627218..0befb0a 100644
--- a/drivers/pci/setup-bus.c
+++ b/drivers/pci/setup-bus.c
@@ -742,7 +742,7 @@ int pci_claim_bridge_resource(struct pci_dev *bridge, int i)
static bool pci_up_path_over_pref_mem64(struct pci_bus *bus)
{
if (pci_is_root_bus(bus))
- return true;
+ return to_pci_host_bridge(bus->bridge)->has_mem64;
if (bus->self) {
int i;
--
1.8.4.5
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Yinghai Lu <yinghai@kernel.org> |
|---|---|
| Date | 2015-12-11 06:30 +0100 |
| Subject | [PATCH v9 33/60] PCI: Add debug printout during releasing partial assigned resources |
| Message-ID | <qEorj-8dZ-51@gated-at.bofh.it> |
| In reply to | #1289199 |
We try to assign required+optional at first, and we only accept the result
if all resources get allocated. Otherwise will release assigned in the
list, and try to assign required and expand to optional.
We have to do that to make sure any required has priority over any optional.
When that happens, we only print out "assigned" info, that is confusing
as it looks like same range is assigned to two peer resources at the same
time.
Add printout for releasing so we have whole picture in debug messages.
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
---
drivers/pci/setup-bus.c | 14 +++++++++++---
1 file changed, 11 insertions(+), 3 deletions(-)
diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c
index e9e67bc..0fc9659 100644
--- a/drivers/pci/setup-bus.c
+++ b/drivers/pci/setup-bus.c
@@ -526,9 +526,17 @@ static void __assign_resources_sorted(struct list_head *head,
free_list(&local_fail_head);
/* Release assigned resource */
- list_for_each_entry(dev_res, head, list)
- if (dev_res->res->parent)
- release_resource(dev_res->res);
+ list_for_each_entry(dev_res, head, list) {
+ struct resource *res = dev_res->res;
+
+ if (res->parent) {
+ dev_printk(KERN_DEBUG, &dev_res->dev->dev,
+ "BAR %d: released %pR\n",
+ (int)(res - &dev_res->dev->resource[0]),
+ res);
+ release_resource(res);
+ }
+ }
/* Restore start/end/flags from saved list */
list_for_each_entry(save_res, &save_head, list) {
struct resource *res = save_res->res;
--
1.8.4.5
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Yinghai Lu <yinghai@kernel.org> |
|---|---|
| Date | 2015-12-11 06:30 +0100 |
| Subject | [PATCH v9 40/60] PCI: Separate required+optional assigning to another function |
| Message-ID | <qEorj-8dZ-53@gated-at.bofh.it> |
| In reply to | #1289199 |
__assign_resources_sorted() is getting too big if we put alt_size support
into it. Split out required+optional assigning code to another function.
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
---
drivers/pci/setup-bus.c | 47 +++++++++++++++++++++++++++--------------------
1 file changed, 27 insertions(+), 20 deletions(-)
diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c
index a8e3eaa..b813340 100644
--- a/drivers/pci/setup-bus.c
+++ b/drivers/pci/setup-bus.c
@@ -473,20 +473,9 @@ static void restore_resource(struct pci_dev_resource *save_res,
res->flags = save_res->flags;
}
-static void __assign_resources_sorted(struct list_head *head,
- struct list_head *realloc_head,
- struct list_head *fail_head)
+static bool __assign_resources_required_optional_sorted(struct list_head *head,
+ struct list_head *realloc_head)
{
- /*
- * Should not assign requested resources at first.
- * they could be adjacent, so later reassign can not reallocate
- * them one by one in parent resource window.
- * Try to assign requested + add_size at beginning
- * if could do that, could get out early.
- * if could not do that, we still try to assign requested at first,
- * then try to reassign add_size for some resources.
- */
-
LIST_HEAD(save_head);
LIST_HEAD(local_fail_head);
struct pci_dev_resource *save_res;
@@ -495,12 +484,8 @@ static void __assign_resources_sorted(struct list_head *head,
resource_size_t add_align;
struct resource *res;
- /* Check if optional add_size is there */
- if (!realloc_head || list_empty(realloc_head))
- goto requested_and_reassign;
-
if (!save_resources(head, &save_head))
- goto requested_and_reassign;
+ return false;
/* Update res in head list with add_size in realloc_head list */
list_for_each_entry(dev_res, head, list) {
@@ -539,7 +524,8 @@ static void __assign_resources_sorted(struct list_head *head,
remove_from_list(realloc_head, dev_res->res);
free_list(&save_head);
free_list(head);
- return;
+
+ return true;
}
/* check failed type */
@@ -574,7 +560,28 @@ static void __assign_resources_sorted(struct list_head *head,
free_list(&save_head);
-requested_and_reassign:
+ return false;
+}
+
+static void __assign_resources_sorted(struct list_head *head,
+ struct list_head *realloc_head,
+ struct list_head *fail_head)
+{
+ /*
+ * Should not assign required resources at first.
+ * they could be adjacent, so later reassign can not reallocate
+ * them one by one in parent resource window.
+ * Try to assign required + optional at beginning
+ * if could do that, could get out early.
+ * if could not do that, we still try to assign required at first,
+ * then try to reassign add_size for some resources.
+ */
+
+ /* Check required+optional add */
+ if (realloc_head && !list_empty(realloc_head) &&
+ __assign_resources_required_optional_sorted(head, realloc_head))
+ return;
+
sort_resources(head);
/* Satisfy the must-have resource requests */
--
1.8.4.5
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Yinghai Lu <yinghai@kernel.org> |
|---|---|
| Date | 2015-12-11 06:40 +0100 |
| Subject | [PATCH v9 10/60] OF/PCI: Add IORESOURCE_MEM_64 for 64-bit resource |
| Message-ID | <qEoAW-8hO-5@gated-at.bofh.it> |
| In reply to | #1289199 |
For device resource PREF bit setting under bridge 64-bit pref resource, we need to make sure only set PREF for 64bit resource, so set IORESOUCE_MEM_64 for 64bit resource during OF device resource flags parsing. Link: https://bugzilla.kernel.org/show_bug.cgi?id=96261 Link: https://bugzilla.kernel.org/show_bug.cgi?id=96241 Signed-off-by: Yinghai Lu <yinghai@kernel.org> Cc: Grant Likely <grant.likely@linaro.org> Cc: Rob Herring <robh+dt@kernel.org> Cc: devicetree@vger.kernel.org Tested-by: Khalid Aziz <khalid.aziz@oracle.com> --- drivers/of/address.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/of/address.c b/drivers/of/address.c index 9582c57..95c39c8 100644 --- a/drivers/of/address.c +++ b/drivers/of/address.c @@ -128,9 +128,11 @@ static unsigned int of_bus_pci_get_flags(const __be32 *addr) flags |= IORESOURCE_IO; break; case 0x02: /* 32 bits */ - case 0x03: /* 64 bits */ flags |= IORESOURCE_MEM; break; + case 0x03: /* 64 bits */ + flags |= IORESOURCE_MEM | IORESOURCE_MEM_64; + break; } if (w & 0x40000000) flags |= IORESOURCE_PREFETCH; -- 1.8.4.5 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Yinghai Lu <yinghai@kernel.org> |
|---|---|
| Date | 2015-12-11 06:40 +0100 |
| Subject | [PATCH v9 13/60] PCI: Add has_mem64 for struct host_bridge |
| Message-ID | <qEoAV-8hO-1@gated-at.bofh.it> |
| In reply to | #1289199 |
Add has_mem64 for struct host_bridge, on root bus that does not support
mmio64 above 4g, will not set that.
We will use that info next two following patches:
1. Don't treat non-pref mmio64 as pref mmio, so will not put
it under bridge's pref range when rescan the devices
2. will keep pref mmio64 and pref mmio32 under bridge pref bar.
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
Tested-by: Khalid Aziz <khalid.aziz@oracle.com>
---
drivers/pci/probe.c | 7 +++++++
include/linux/pci.h | 1 +
2 files changed, 8 insertions(+)
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index 6faabe3..b89daef 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -2194,6 +2194,13 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus,
} else
bus_addr[0] = '\0';
dev_info(&b->dev, "root bus resource %pR%s\n", res, bus_addr);
+
+ if (resource_type(res) == IORESOURCE_MEM) {
+ if ((res->end - offset) > 0xffffffff)
+ bridge->has_mem64 = 1;
+ if ((res->start - offset) > 0xffffffff)
+ res->flags |= IORESOURCE_MEM_64;
+ }
}
down_write(&pci_bus_sem);
diff --git a/include/linux/pci.h b/include/linux/pci.h
index f96f86a..c135edc 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -413,6 +413,7 @@ struct pci_host_bridge {
void (*release_fn)(struct pci_host_bridge *);
void *release_data;
unsigned int ignore_reset_delay:1; /* for entire hierarchy */
+ unsigned int has_mem64:1;
/* Resource alignment requirements */
resource_size_t (*align_resource)(struct pci_dev *dev,
const struct resource *res,
--
1.8.4.5
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Yinghai Lu <yinghai@kernel.org> |
|---|---|
| Date | 2015-12-11 06:40 +0100 |
| Subject | [PATCH v9 25/60] PCI: Use correct align for optional only resources during sorting |
| Message-ID | <qEoAW-8hO-3@gated-at.bofh.it> |
| In reply to | #1289199 |
During sorting before assign, we only put resource with non-zero align
in the sorted list, so for optional resources that required size is 0 and
only have optional parts, we need to have correct align.
While treating SRIOV as optional resources, we always read alignment for
SRIOV bars every time, so they are ok.
Hotplug bridge resources are using STARTALIGN so it is ok when size is 0
if we have correct start for them.
Later we want to treat the ROM BAR as optional resource, and it has
SIZEALIGN, so align=size will be 0. We need to find a way to get align
for them.
We can use optional resource align instead in that case, and it
is ok for SRIOV path and hotplug bridge resource path.
We need to pass realloc list from sizing stage to sorting stage, and
get entry from realloc list and calculate align from the entry.
Link: https://bugzilla.kernel.org/show_bug.cgi?id=81431
Reported-by: TJ <linux@iam.tj>
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
---
drivers/pci/setup-bus.c | 49 ++++++++++++++++++++++++++++++++++++++++++-------
1 file changed, 42 insertions(+), 7 deletions(-)
diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c
index 6f6cf25..31334a1 100644
--- a/drivers/pci/setup-bus.c
+++ b/drivers/pci/setup-bus.c
@@ -145,9 +145,42 @@ static resource_size_t get_res_add_align(struct list_head *head,
return dev_res->min_align;
}
+static resource_size_t __pci_resource_alignment(
+ struct pci_dev *dev,
+ struct resource *r,
+ struct list_head *realloc_head)
+{
+ resource_size_t r_align = pci_resource_alignment(dev, r);
+ resource_size_t orig_start, orig_end;
+ struct pci_dev_resource *dev_res;
+
+ if (r_align || !realloc_head)
+ return r_align;
+
+ dev_res = res_to_dev_res(realloc_head, r);
+ if (!dev_res || !dev_res->add_size)
+ return r_align;
+
+ orig_start = r->start;
+ orig_end = r->end;
+ r->end += dev_res->add_size;
+ if ((r->flags & IORESOURCE_STARTALIGN)) {
+ resource_size_t r_size = resource_size(r);
+
+ r->start = dev_res->min_align;
+ r->end = r->start + r_size - 1;
+ }
+ r_align = pci_resource_alignment(dev, r);
+ r->start = orig_start;
+ r->end = orig_end;
+
+ return r_align;
+}
/* Sort resources by alignment */
-static void pdev_sort_resources(struct pci_dev *dev, struct list_head *head)
+static void pdev_sort_resources(struct pci_dev *dev,
+ struct list_head *realloc_head,
+ struct list_head *head)
{
int i;
@@ -165,7 +198,7 @@ static void pdev_sort_resources(struct pci_dev *dev, struct list_head *head)
if (!(r->flags) || r->parent)
continue;
- r_align = pci_resource_alignment(dev, r);
+ r_align = __pci_resource_alignment(dev, r, realloc_head);
if (!r_align) {
dev_warn(&dev->dev, "BAR %d: %pR has bogus alignment\n",
i, r);
@@ -183,8 +216,9 @@ static void pdev_sort_resources(struct pci_dev *dev, struct list_head *head)
list_for_each_entry(dev_res, head, list) {
resource_size_t align;
- align = pci_resource_alignment(dev_res->dev,
- dev_res->res);
+ align = __pci_resource_alignment(dev_res->dev,
+ dev_res->res,
+ realloc_head);
if (r_align > align) {
n = &dev_res->list;
@@ -197,6 +231,7 @@ static void pdev_sort_resources(struct pci_dev *dev, struct list_head *head)
}
static void __dev_sort_resources(struct pci_dev *dev,
+ struct list_head *realloc_head,
struct list_head *head)
{
u16 class = dev->class >> 8;
@@ -213,7 +248,7 @@ static void __dev_sort_resources(struct pci_dev *dev,
return;
}
- pdev_sort_resources(dev, head);
+ pdev_sort_resources(dev, realloc_head, head);
}
static inline void reset_resource(struct resource *res)
@@ -507,7 +542,7 @@ static void pdev_assign_resources_sorted(struct pci_dev *dev,
{
LIST_HEAD(head);
- __dev_sort_resources(dev, &head);
+ __dev_sort_resources(dev, add_head, &head);
__assign_resources_sorted(&head, add_head, fail_head);
}
@@ -520,7 +555,7 @@ static void pbus_assign_resources_sorted(const struct pci_bus *bus,
LIST_HEAD(head);
list_for_each_entry(dev, &bus->devices, bus_list)
- __dev_sort_resources(dev, &head);
+ __dev_sort_resources(dev, realloc_head, &head);
__assign_resources_sorted(&head, realloc_head, fail_head);
}
--
1.8.4.5
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Yinghai Lu <yinghai@kernel.org> |
|---|---|
| Date | 2015-12-11 07:10 +0100 |
| Subject | [PATCH v9 31/60] PCI: Rename pdev_sort_resources() to pdev_assign_resources_prepare() |
| Message-ID | <qEp3Z-gf-5@gated-at.bofh.it> |
| In reply to | #1289199 |
pdev_sort_resources() etc was checking devices resources and putting
resources that need to assign to one list in sorted order.
Now we don't do sorting in those functions anymore, so change to
pdev_assign_resources_prepare() instead.
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
---
drivers/pci/setup-bus.c | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c
index cba7ccc..194d5da 100644
--- a/drivers/pci/setup-bus.c
+++ b/drivers/pci/setup-bus.c
@@ -205,8 +205,8 @@ static resource_size_t __pci_resource_alignment(
return r_align;
}
-/* Sort resources by alignment */
-static void pdev_sort_resources(struct pci_dev *dev,
+/* check resources and save to the list */
+static void pdev_assign_resources_prepare(struct pci_dev *dev,
struct list_head *realloc_head,
struct list_head *head)
{
@@ -242,7 +242,7 @@ static void pdev_sort_resources(struct pci_dev *dev,
}
}
-static void __dev_sort_resources(struct pci_dev *dev,
+static void __dev_assign_resources_prepare(struct pci_dev *dev,
struct list_head *realloc_head,
struct list_head *head)
{
@@ -260,7 +260,7 @@ static void __dev_sort_resources(struct pci_dev *dev,
return;
}
- pdev_sort_resources(dev, realloc_head, head);
+ pdev_assign_resources_prepare(dev, realloc_head, head);
}
static inline void reset_resource(struct resource *res)
@@ -566,7 +566,7 @@ static void pdev_assign_resources_sorted(struct pci_dev *dev,
{
LIST_HEAD(head);
- __dev_sort_resources(dev, add_head, &head);
+ __dev_assign_resources_prepare(dev, add_head, &head);
__assign_resources_sorted(&head, add_head, fail_head);
}
@@ -579,7 +579,7 @@ static void pbus_assign_resources_sorted(const struct pci_bus *bus,
LIST_HEAD(head);
list_for_each_entry(dev, &bus->devices, bus_list)
- __dev_sort_resources(dev, realloc_head, &head);
+ __dev_assign_resources_prepare(dev, realloc_head, &head);
__assign_resources_sorted(&head, realloc_head, fail_head);
}
--
1.8.4.5
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Yinghai Lu <yinghai@kernel.org> |
|---|---|
| Date | 2015-12-11 07:10 +0100 |
| Subject | [PATCH v9 56/60] PCI: Add debug print out for min_align and alt_size |
| Message-ID | <qEp3Z-gf-15@gated-at.bofh.it> |
| In reply to | #1289199 |
Put all print out for all children align/size and result align/size
together.
We can print out device name at same time with min_align/alt_size
calculation.
So we can shut off debug print out from get_res_add_size() and
get_res_add_align().
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
---
drivers/pci/setup-bus.c | 76 ++++++++++++++++++++++++++++++++++++-------------
1 file changed, 56 insertions(+), 20 deletions(-)
diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c
index 081eb08..901d2f6 100644
--- a/drivers/pci/setup-bus.c
+++ b/drivers/pci/setup-bus.c
@@ -159,11 +159,6 @@ static resource_size_t get_res_add_size(struct list_head *head,
if (!dev_res || !dev_res->add_size)
return 0;
- dev_printk(KERN_DEBUG, &dev_res->dev->dev,
- "BAR %d: %pR get_res_add_size add_size %#llx\n",
- (int)(res - &dev_res->dev->resource[0]),
- res, (unsigned long long)dev_res->add_size);
-
return dev_res->add_size;
}
@@ -176,11 +171,6 @@ static resource_size_t get_res_add_align(struct list_head *head,
if (!dev_res || !dev_res->min_align)
return 0;
- dev_printk(KERN_DEBUG, &dev_res->dev->dev,
- "BAR %d: %pR get_res_add_align min_align %#llx\n",
- (int)(res - &dev_res->dev->resource[0]),
- res, (unsigned long long)dev_res->min_align);
-
return dev_res->min_align;
}
@@ -1271,6 +1261,8 @@ struct align_test_res {
struct resource res;
resource_size_t size;
resource_size_t align;
+ struct device *dev;
+ int idx;
};
static void free_align_test_list(struct list_head *head)
@@ -1284,7 +1276,8 @@ static void free_align_test_list(struct list_head *head)
}
static int add_to_align_test_list(struct list_head *head,
- resource_size_t align, resource_size_t size)
+ resource_size_t align, resource_size_t size,
+ struct device *dev, int idx)
{
struct align_test_res *tmp;
@@ -1294,6 +1287,8 @@ static int add_to_align_test_list(struct list_head *head,
tmp->align = align;
tmp->size = size;
+ tmp->dev = dev;
+ tmp->idx = idx;
list_add_tail(&tmp->list, head);
@@ -1359,6 +1354,19 @@ static resource_size_t calculate_mem_align(struct list_head *head,
resource_size_t min_align, good_align, aligned_size, start;
int count = 0;
+ list_for_each_entry(p, head, list)
+ count++;
+
+ printk(KERN_DEBUG " ===========BEGIN===calculate_mem_align========\n");
+ if (count) {
+ printk(KERN_DEBUG " align/size:\n");
+ list_for_each_entry(p, head, list)
+ dev_printk(KERN_DEBUG, p->dev,
+ "BAR %d: %08llx/%08llx\n", p->idx,
+ (unsigned long long)p->align,
+ (unsigned long long)p->size);
+ }
+
if (max_align <= align_low) {
good_align = align_low;
goto out;
@@ -1366,9 +1374,6 @@ static resource_size_t calculate_mem_align(struct list_head *head,
good_align = max_align;
- list_for_each_entry(p, head, list)
- count++;
-
if (count <= 1)
goto out;
@@ -1393,6 +1398,11 @@ static resource_size_t calculate_mem_align(struct list_head *head,
} while (min_align > align_low);
out:
+ printk(KERN_DEBUG " min_align/aligned_size: %08llx/%08llx\n",
+ (unsigned long long)good_align,
+ (unsigned long long)ALIGN(size, good_align));
+ printk(KERN_DEBUG " ===========END===calculate_mem_align==========\n");
+
return good_align;
}
@@ -1410,6 +1420,16 @@ static resource_size_t calculate_mem_alt_size(struct list_head *head,
list_for_each_entry(p, head, list)
count++;
+ printk(KERN_DEBUG " ===========BEGIN===calculate_mem_alt_size=====\n");
+ if (count) {
+ printk(KERN_DEBUG " align/size:\n");
+ list_for_each_entry(p, head, list)
+ dev_printk(KERN_DEBUG, p->dev,
+ "BAR %d: %08llx/%08llx\n", p->idx,
+ (unsigned long long)p->align,
+ (unsigned long long)p->size);
+ }
+
if (count <= 1)
goto out;
@@ -1434,6 +1454,11 @@ static resource_size_t calculate_mem_alt_size(struct list_head *head,
}
out:
+ printk(KERN_DEBUG " alt_align/alt_size: %08llx/%08llx\n",
+ (unsigned long long)max_align,
+ (unsigned long long)good_size);
+ printk(KERN_DEBUG " ===========END===calculate_mem_alt_size=======\n");
+
return good_size;
}
@@ -1516,7 +1541,7 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask,
/* put SRIOV/ROM res to realloc list */
if (realloc_head && is_optional(i)) {
add_to_align_test_list(&align_test_add_list,
- align, r_size);
+ align, r_size, &dev->dev, i);
r->end = r->start - 1;
__add_to_list(realloc_head, dev, r,
r_size, align, 0, 0);
@@ -1535,7 +1560,7 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask,
if (r_size > 1) {
add_to_align_test_list(&align_test_list,
- align, r_size);
+ align, r_size, &dev->dev, i);
size += r_size;
if (align > max_align)
max_align = align;
@@ -1552,7 +1577,8 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask,
add_align = align;
add_to_align_test_list(&align_test_add_list,
add_align,
- r_size + add_r_size);
+ r_size + add_r_size,
+ &dev->dev, i);
sum_add_size += r_size + add_r_size;
if (add_align > max_add_align)
max_add_align = add_align;
@@ -1562,14 +1588,14 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask,
add_to_align_test_list(
&align_test_alt_list,
dev_res->alt_align,
- dev_res->alt_size);
+ dev_res->alt_size, &dev->dev, i);
alt_size += dev_res->alt_size;
if (alt_align < dev_res->alt_align)
alt_align = dev_res->alt_align;
} else if (r_size > 1) {
add_to_align_test_list(
&align_test_alt_list,
- align, r_size);
+ align, r_size, &dev->dev, i);
alt_size += r_size;
if (alt_align < align)
alt_align = align;
@@ -1580,6 +1606,9 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask,
max_align = max(max_align, window_align);
if (size || min_size) {
+ dev_printk(KERN_DEBUG, &bus->self->dev,
+ "BAR %d: bridge window %pR to %pR calculate_mem for MUST\n",
+ (int)(b_res - &bus->self->resource[0]), b_res, &bus->busn_res);
min_align = calculate_mem_align(&align_test_list, max_align,
size, window_align);
size0 = calculate_size(size, min_size,
@@ -1589,6 +1618,9 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask,
if (size0 && realloc_head) {
alt_align = max(alt_align, window_align);
+ dev_printk(KERN_DEBUG, &bus->self->dev,
+ "BAR %d: bridge window %pR to %pR calculate_mem for ALT\n",
+ (int)(b_res - &bus->self->resource[0]), b_res, &bus->busn_res);
/* need to increase size to fit more alt */
alt_size = calculate_mem_alt_size(&align_test_alt_list,
alt_align, alt_size,
@@ -1604,6 +1636,9 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask,
if (sum_add_size < min_sum_size)
sum_add_size = min_sum_size;
if (sum_add_size > size && realloc_head) {
+ dev_printk(KERN_DEBUG, &bus->self->dev,
+ "BAR %d: bridge window %pR to %pR calculate_mem for ADD\n",
+ (int)(b_res - &bus->self->resource[0]), b_res, &bus->busn_res);
min_add_align = calculate_mem_align(&align_test_add_list,
max_add_align, sum_add_size,
window_align);
@@ -1661,7 +1696,8 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask,
final_add_size, min_add_align,
alt_size, alt_align);
dev_printk(KERN_DEBUG, &bus->self->dev,
- "bridge window %pR to %pR add_size %llx add_align %llx alt_size %llx alt_align %llx req_size %llx req_align %llx\n",
+ "BAR %d: bridge window %pR to %pR add_size %llx add_align %llx alt_size %llx alt_align %llx req_size %llx req_align %llx\n",
+ (int)(b_res - &bus->self->resource[0]),
b_res, &bus->busn_res,
(unsigned long long)final_add_size,
(unsigned long long)min_add_align,
--
1.8.4.5
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Yinghai Lu <yinghai@kernel.org> |
|---|---|
| Date | 2015-12-11 07:10 +0100 |
| Subject | [PATCH v9 46/60] PCI: Don't add too much optional size for hotplug bridge io |
| Message-ID | <qEp3Z-gf-27@gated-at.bofh.it> |
| In reply to | #1289199 |
Same as patch for MMIO (PCI: Don't add too much optional size for hotplug
bridge MMIO), and this one is for io port.
It will compare required+optional with min_sum_size to get smaller
optional size.
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
---
drivers/pci/setup-bus.c | 26 ++++++++++++++++----------
1 file changed, 16 insertions(+), 10 deletions(-)
diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c
index c8b3ea6..0ece6b6 100644
--- a/drivers/pci/setup-bus.c
+++ b/drivers/pci/setup-bus.c
@@ -1177,7 +1177,6 @@ static resource_size_t window_alignment(struct pci_bus *bus,
*
* @bus : the bus
* @min_size : the minimum io window that must to be allocated
- * @add_size : additional optional io window
* @realloc_head : track the additional io window on this list
*
* Sizing the IO windows of the PCI-PCI bridge is trivial,
@@ -1186,9 +1185,11 @@ static resource_size_t window_alignment(struct pci_bus *bus,
* We must be careful with the ISA aliasing though.
*/
static void pbus_size_io(struct pci_bus *bus, resource_size_t min_size,
- resource_size_t add_size, struct list_head *realloc_head)
+ struct list_head *realloc_head)
{
struct pci_dev *dev;
+ resource_size_t min_sum_size = 0;
+ resource_size_t sum_add_size;
struct resource *b_res = find_free_bus_resource(bus, IORESOURCE_IO,
IORESOURCE_IO);
resource_size_t size = 0, size0 = 0, size1 = 0;
@@ -1198,6 +1199,11 @@ static void pbus_size_io(struct pci_bus *bus, resource_size_t min_size,
if (!b_res)
return;
+ if (realloc_head) {
+ min_sum_size = min_size;
+ min_size = 0;
+ }
+
min_align = window_alignment(bus, IORESOURCE_IO);
list_for_each_entry(dev, &bus->devices, bus_list) {
int i;
@@ -1227,10 +1233,11 @@ static void pbus_size_io(struct pci_bus *bus, resource_size_t min_size,
size0 = calculate_iosize(size, min_size, size1,
resource_size(b_res), min_align);
- if (children_add_size > add_size)
- add_size = children_add_size;
- size1 = (!realloc_head || (realloc_head && !add_size)) ? size0 :
- calculate_iosize(size, min_size, add_size + size1,
+ sum_add_size = children_add_size + size + size1;
+ if (sum_add_size < min_sum_size)
+ sum_add_size = min_sum_size;
+ size1 = !realloc_head ? size0 :
+ calculate_iosize(size, min_size, sum_add_size - size,
resource_size(b_res), min_align);
if (!size0 && !size1) {
if (b_res->start || b_res->end)
@@ -1758,7 +1765,7 @@ void __pci_bus_size_bridges(struct pci_bus *bus, struct list_head *realloc_head)
{
struct pci_dev *dev;
unsigned long mask, prefmask, type2 = 0, type3 = 0;
- resource_size_t min_mem_size = 0, additional_io_size = 0;
+ resource_size_t min_mem_size = 0, min_io_size = 0;
struct resource *b_res;
int ret;
@@ -1794,13 +1801,12 @@ void __pci_bus_size_bridges(struct pci_bus *bus, struct list_head *realloc_head)
case PCI_CLASS_BRIDGE_PCI:
if (bus->self->is_hotplug_bridge) {
- additional_io_size = pci_hotplug_io_size;
+ min_io_size = pci_hotplug_io_size;
min_mem_size = pci_hotplug_mem_size;
}
/* Fall through */
default:
- pbus_size_io(bus, realloc_head ? 0 : additional_io_size,
- additional_io_size, realloc_head);
+ pbus_size_io(bus, min_io_size, realloc_head);
/*
* If there's a 64-bit prefetchable MMIO window, compute
--
1.8.4.5
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Yinghai Lu <yinghai@kernel.org> |
|---|---|
| Date | 2015-12-11 07:10 +0100 |
| Subject | [PATCH v9 27/60] PCI: Optimize bus align/size calculation for optional during sizing |
| Message-ID | <qEp3Z-gf-21@gated-at.bofh.it> |
| In reply to | #1289199 |
Current add_align always use max align, that make required+optional
to get allocated more than needed in some cases.
Now we have new calculate_mem_align(), so we could use it for
add_align calculation.
Need to create separated list for required+optional align/size info.
After that we can get smaller add_align/size, and we have more chance
to make required+optional to get allocated sucessfully.
The result for bridge that have Intel 4x10g card installed:
pci 0000:20:03.2: bridge window [mem 0x00000000-0x000fffff 64bit pref]
to [bus 2a-31] calculate_mem for required
align/size:
00800000/00800000, 00800000/00800000, 00800000/00800000,
00800000/00800000, 00008000/00008000, 00008000/00008000,
00008000/00008000, 00008000/00008000
original min_align/min_size: 00400000/02400000
new min_align/min_size: 00400000/02400000
pci 0000:20:03.2: bridge window [mem 0x00000000-0x000fffff 64bit pref]
to [bus 2a-31] calculate_mem for required+optional
align/size:
00800000/00800000, 00800000/00800000, 00800000/00800000,
00800000/00800000, 00010000/00200000, 00010000/00200000,
00010000/00200000, 00010000/00200000, 00008000/00008000,
00008000/00008000, 00008000/00008000, 00008000/00008000,
00004000/00080000, 00004000/00080000, 00004000/00080000,
00004000/00080000
original code min_align/min_size: 00800000/03000000
new min_align/min_size: 00100000/02b00000
so required align/size: 0x400000/0x2400000, and
new required+optional align/size: 0x100000/0x2b00000, and it is much better
than original required+optional align/size: 0x800000/0x3000000
and even have smaller min_align than required.
-v2: remove not used size1 in calculate_memsize
Link: https://bugzilla.kernel.org/show_bug.cgi?id=81431
Reported-by: TJ <linux@iam.tj>
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
drivers/pci/setup-bus.c | 82 +++++++++++++++++++++++++++++-------------------
1 file changed, 51 insertions(+), 31 deletions(-)
---
drivers/pci/setup-bus.c | 82 ++++++++++++++++++++++++++++++-------------------
1 file changed, 51 insertions(+), 31 deletions(-)
diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c
index 6e67608..d8db9e3 100644
--- a/drivers/pci/setup-bus.c
+++ b/drivers/pci/setup-bus.c
@@ -944,7 +944,6 @@ static resource_size_t calculate_iosize(resource_size_t size,
static resource_size_t calculate_memsize(resource_size_t size,
resource_size_t min_size,
- resource_size_t size1,
resource_size_t old_size,
resource_size_t align)
{
@@ -954,7 +953,7 @@ static resource_size_t calculate_memsize(resource_size_t size,
old_size = 0;
if (size < old_size)
size = old_size;
- size = ALIGN(size + size1, align);
+ size = ALIGN(size, align);
return size;
}
@@ -1217,26 +1216,23 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask,
struct list_head *realloc_head)
{
struct pci_dev *dev;
- resource_size_t min_align, align, size, size0, size1;
- resource_size_t max_align = 0;
+ resource_size_t min_align = 0, min_add_align = 0;
+ resource_size_t max_align = 0, max_add_align = 0;
+ resource_size_t size = 0, size0 = 0, size1 = 0, sum_add_size = 0;
struct resource *b_res = find_free_bus_resource(bus,
mask | IORESOURCE_PREFETCH, type);
- resource_size_t children_add_size = 0;
- resource_size_t children_add_align = 0;
- resource_size_t add_align = 0;
LIST_HEAD(align_test_list);
+ LIST_HEAD(align_test_add_list);
if (!b_res)
return -ENOSPC;
- size = 0;
-
list_for_each_entry(dev, &bus->devices, bus_list) {
int i;
for (i = 0; i < PCI_NUM_RESOURCES; i++) {
struct resource *r = &dev->resource[i];
- resource_size_t r_size;
+ resource_size_t r_size, align;
int flags = pci_resource_pref_compatible(dev, r);
if (r->parent || (flags & IORESOURCE_PCI_FIXED) ||
@@ -1244,19 +1240,23 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask,
(flags & mask) != type2 &&
(flags & mask) != type3))
continue;
+
r_size = resource_size(r);
+ align = pci_resource_alignment(dev, r);
#ifdef CONFIG_PCI_IOV
/* put SRIOV requested res to the optional list */
if (realloc_head && i >= PCI_IOV_RESOURCES &&
i <= PCI_IOV_RESOURCE_END) {
- add_align = max(pci_resource_alignment(dev, r), add_align);
+ add_to_align_test_list(&align_test_add_list,
+ align, r_size);
r->end = r->start - 1;
add_to_list(realloc_head, dev, r, r_size, 0/* don't care */);
- children_add_size += r_size;
+ sum_add_size += r_size;
+ if (align > max_add_align)
+ max_add_align = align;
continue;
}
#endif
- align = pci_resource_alignment(dev, r);
if (align > (1ULL<<37)) { /*128 Gb*/
dev_warn(&dev->dev, "disabling BAR %d: %pR (bad alignment %#llx)\n",
i, r, (unsigned long long) align);
@@ -1264,33 +1264,52 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask,
continue;
}
- if (r_size > 1)
+ if (r_size > 1) {
add_to_align_test_list(&align_test_list,
align, r_size);
- size += r_size;
- if (align > max_align)
- max_align = align;
+ size += r_size;
+ if (align > max_align)
+ max_align = align;
+ }
if (realloc_head) {
- children_add_size += get_res_add_size(realloc_head, r);
- children_add_align = get_res_add_align(realloc_head, r);
- add_align = max(add_align, children_add_align);
+ resource_size_t add_r_size, add_align;
+
+ add_r_size = get_res_add_size(realloc_head, r);
+ add_align = get_res_add_align(realloc_head, r);
+ /* no add on ? */
+ if (add_align < align)
+ add_align = align;
+ add_to_align_test_list(&align_test_add_list,
+ add_align,
+ r_size + add_r_size);
+ sum_add_size += r_size + add_r_size;
+ if (add_align > max_add_align)
+ max_add_align = add_align;
}
}
}
max_align = max(max_align, window_alignment(bus, b_res->flags));
- min_align = calculate_mem_align(&align_test_list, max_align, size,
- window_alignment(bus, b_res->flags));
- size0 = calculate_memsize(size, min_size, 0,
+ if (size || min_size) {
+ min_align = calculate_mem_align(&align_test_list, max_align,
+ size, window_alignment(bus, b_res->flags));
+ size0 = calculate_memsize(size, min_size,
resource_size(b_res), min_align);
+ }
free_align_test_list(&align_test_list);
- add_align = max(min_align, add_align);
- if (children_add_size > add_size)
- add_size = children_add_size;
- size1 = (!realloc_head || (realloc_head && !add_size)) ? size0 :
- calculate_memsize(size, min_size, add_size,
- resource_size(b_res), add_align);
+
+ if ((sum_add_size - size) < add_size)
+ sum_add_size = size + add_size;
+ if (sum_add_size > size && realloc_head) {
+ min_add_align = calculate_mem_align(&align_test_add_list,
+ max_add_align, sum_add_size,
+ window_alignment(bus, b_res->flags));
+ size1 = calculate_memsize(sum_add_size, min_size,
+ resource_size(b_res), min_add_align);
+ }
+ free_align_test_list(&align_test_add_list);
+
if (!size0 && !size1) {
if (b_res->start || b_res->end)
dev_info(&bus->self->dev, "disabling bridge window %pR to %pR (unused)\n",
@@ -1302,11 +1321,12 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask,
b_res->end = size0 + min_align - 1;
b_res->flags |= IORESOURCE_STARTALIGN;
if (size1 > size0 && realloc_head) {
- add_to_list(realloc_head, bus->self, b_res, size1-size0, add_align);
+ add_to_list(realloc_head, bus->self, b_res, size1 - size0,
+ min_add_align);
dev_printk(KERN_DEBUG, &bus->self->dev, "bridge window %pR to %pR add_size %llx add_align %llx\n",
b_res, &bus->busn_res,
(unsigned long long) (size1 - size0),
- (unsigned long long) add_align);
+ (unsigned long long) min_add_align);
}
return 0;
}
--
1.8.4.5
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Yinghai Lu <yinghai@kernel.org> |
|---|---|
| Date | 2015-12-11 07:10 +0100 |
| Subject | [PATCH v9 34/60] PCI: Simplify res reference using in __assign_resources_sorted() |
| Message-ID | <qEp40-gf-33@gated-at.bofh.it> |
| In reply to | #1289199 |
There are couples of dev_res->res reference, to make code more readable
use res instead of dev_res->res directly.
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
---
drivers/pci/setup-bus.c | 32 ++++++++++++++++----------------
1 file changed, 16 insertions(+), 16 deletions(-)
diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c
index 0fc9659..715e627 100644
--- a/drivers/pci/setup-bus.c
+++ b/drivers/pci/setup-bus.c
@@ -458,6 +458,7 @@ static void __assign_resources_sorted(struct list_head *head,
struct pci_dev_resource *dev_res, *tmp_res;
unsigned long fail_type;
resource_size_t add_align;
+ struct resource *res;
/* Check if optional add_size is there */
if (!realloc_head || list_empty(realloc_head))
@@ -473,8 +474,8 @@ static void __assign_resources_sorted(struct list_head *head,
/* Update res in head list with add_size in realloc_head list */
list_for_each_entry(dev_res, head, list) {
- dev_res->res->end += get_res_add_size(realloc_head,
- dev_res->res);
+ res = dev_res->res;
+ res->end += get_res_add_size(realloc_head, res);
/*
* There are two kinds of additional resources in the list:
@@ -483,16 +484,16 @@ static void __assign_resources_sorted(struct list_head *head,
* 2. resource with IORESOURCE_SIZEALIGN
* update size above already change alignment.
*/
- if (!(dev_res->res->flags & IORESOURCE_STARTALIGN))
+ if (!(res->flags & IORESOURCE_STARTALIGN))
continue;
- add_align = get_res_add_align(realloc_head, dev_res->res);
+ add_align = get_res_add_align(realloc_head, res);
if (add_align) {
- resource_size_t r_size = resource_size(dev_res->res);
+ resource_size_t r_size = resource_size(res);
- dev_res->res->start = add_align;
- dev_res->res->end = add_align + r_size - 1;
+ res->start = add_align;
+ res->end = add_align + r_size - 1;
}
}
@@ -514,21 +515,21 @@ static void __assign_resources_sorted(struct list_head *head,
/* check failed type */
fail_type = pci_fail_res_type_mask(&local_fail_head);
/* remove not need to be released assigned res from head list etc */
- list_for_each_entry_safe(dev_res, tmp_res, head, list)
- if (dev_res->res->parent &&
- !pci_need_to_release(fail_type, dev_res->res)) {
+ list_for_each_entry_safe(dev_res, tmp_res, head, list) {
+ res = dev_res->res;
+ if (res->parent && !pci_need_to_release(fail_type, res)) {
/* remove it from realloc_head list */
- remove_from_list(realloc_head, dev_res->res);
- remove_from_list(&save_head, dev_res->res);
+ remove_from_list(realloc_head, res);
+ remove_from_list(&save_head, res);
list_del(&dev_res->list);
kfree(dev_res);
}
+ }
free_list(&local_fail_head);
/* Release assigned resource */
list_for_each_entry(dev_res, head, list) {
- struct resource *res = dev_res->res;
-
+ res = dev_res->res;
if (res->parent) {
dev_printk(KERN_DEBUG, &dev_res->dev->dev,
"BAR %d: released %pR\n",
@@ -539,8 +540,7 @@ static void __assign_resources_sorted(struct list_head *head,
}
/* Restore start/end/flags from saved list */
list_for_each_entry(save_res, &save_head, list) {
- struct resource *res = save_res->res;
-
+ res = save_res->res;
res->start = save_res->start;
res->end = save_res->end;
res->flags = save_res->flags;
--
1.8.4.5
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Yinghai Lu <yinghai@kernel.org> |
|---|---|
| Date | 2015-12-11 07:10 +0100 |
| Subject | [PATCH v9 43/60] PCI: Add alt_size ressource allocation support |
| Message-ID | <qEp40-gf-29@gated-at.bofh.it> |
| In reply to | #1289199 |
On system with several pcie switches, BIOS allocate very tight resources
to the bridge bar, and it is not aligned to min_align as kernel allocation
code.
For example:
02:03.0---0c:00.0---0d:04.0---18:00.0
18:00.0 need 0x10000000, and 0x00010000.
BIOS only allocate 0x10100000 to 0d:04.0 and above bridges.
Later after using /sys/bus/pci/devices/0000:0c:00.0/remove to remove 0c:00.0,
rescan with /sys/bus/pci/rescan can not allocate 0x18000000 to 0c:00.0.
as current min_align solution will need 0x18000000.
Another example:
00:1c.0---02:00.0---03:01.0---04:00.0---05:19.0---06:00.0
06:00.0 need 0x4000000 and 0x800000.
BIOS only allocate 0x4800000 to 05:19.0 and 04:00.0.
when 05:19.0 get removed via /sys/bus/pci/devices/0000:05:19.0/remove,
rescan with /sys/bus/pci/rescan will fail.
pci 0000:05:19.0: BAR 14: no space for [mem size 0x06000000]
pci 0000:05:19.0: BAR 14: failed to assign [mem size 0x06000000]
pci 0000:06:00.0: BAR 2: no space for [mem size 0x04000000 64bit]
pci 0000:06:00.0: BAR 2: failed to assign [mem size 0x04000000 64bit]
pci 0000:06:00.0: BAR 0: no space for [mem size 0x00800000]
pci 0000:06:00.0: BAR 0: failed to assign [mem size 0x00800000]
current code try to use align 0x2000000 and size 0x6000000, but parent
bridge only have 0x4800000.
Introduce alt_align/alt_size and store them in realloc list in addition
to addon info, and will try it after min_align/min_size allocation fails.
The alt_align is max_align, and alt_size is aligned size with bridge
minimum window alignment.
On my test setup:
00:1c.7---61:00.0---62:00.0
62:00.0 needs 0x800000 and 0x20000, and 00:1c.7 only have 9M allocated
for mmio, with this patch we have
pci 0000:61:00.0: bridge window [mem 0x00400000-0x00ffffff] to [bus 62]
add_size 0 add_align 0 alt_size 900000 alt_align 800000
req_size c00000 req_align 400000
pci 0000:61:00.0: BAR 14: no space for [mem size 0x00c00000]
pci 0000:61:00.0: BAR 14: failed to assign [mem size 0x00c00000]
pci 0000:61:00.0: BAR 14: assigned [mem 0xdf000000-0xdf8fffff]
pci 0000:62:00.0: BAR 0: assigned [mem 0xdf000000-0xdf7fffff pref]
pci 0000:62:00.0: BAR 1: assigned [mem 0xdf800000-0xdf81ffff]
pci 0000:61:00.0: PCI bridge to [bus 62]
pci 0000:61:00.0: bridge window [io 0x6000-0x6fff]
pci 0000:61:00.0: bridge window [mem 0xdf000000-0xdf8fffff]
pci 0000:00:1c.7: PCI bridge to [bus 61-68]
pci 0000:00:1c.7: bridge window [io 0x6000-0x6fff]
pci 0000:00:1c.7: bridge window [mem 0xdf000000-0xdf8fffff]
So for 61:00.0 first try with 12M fails, and second try with 9M the
alt_size works. Later 62:00.0 get correct resource allocated too.
Link: https://bugzilla.kernel.org/show_bug.cgi?id=100451
Reported-by: Yijing Wang <wangyijing@huawei.com>
Tested-by: Yijing Wang <wangyijing@huawei.com>
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
---
drivers/pci/setup-bus.c | 203 +++++++++++++++++++++++++++++++++++++++++++++---
1 file changed, 191 insertions(+), 12 deletions(-)
diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c
index 1df6345..51c3b3d 100644
--- a/drivers/pci/setup-bus.c
+++ b/drivers/pci/setup-bus.c
@@ -323,7 +323,7 @@ static void reassign_resources_sorted(struct list_head *realloc_head,
{
struct resource *res;
struct pci_dev_resource *add_res, *tmp;
- resource_size_t add_size, align;
+ resource_size_t add_size, align, r_size;
int idx;
list_for_each_entry_safe(add_res, tmp, realloc_head, list) {
@@ -339,12 +339,23 @@ static void reassign_resources_sorted(struct list_head *realloc_head,
idx = res - &add_res->dev->resource[0];
add_size = add_res->add_size;
align = add_res->min_align;
- if (!resource_size(res)) {
+ if (!add_size || !align) /* alt_size only */
+ goto out;
+
+ r_size = resource_size(res);
+ if (!r_size) {
res->start = align;
res->end = res->start + add_size - 1;
if (pci_assign_resource(add_res->dev, idx))
reset_resource(res);
} else {
+ /* could just assigned with alt, add difference ? */
+ resource_size_t size;
+
+ size = add_res->end - add_res->start + 1;
+ if (r_size < size)
+ add_size += size - r_size;
+
res->flags |= add_res->flags &
(IORESOURCE_STARTALIGN|IORESOURCE_SIZEALIGN);
if (pci_reassign_resource(add_res->dev, idx,
@@ -583,6 +594,104 @@ static bool __assign_resources_required_optional_sorted(struct list_head *head,
return false;
}
+static bool __has_alt(struct list_head *head,
+ struct list_head *realloc_head)
+{
+ int alt_count = 0;
+ struct pci_dev_resource *dev_res, *alt_res;
+
+ if (!realloc_head)
+ return false;
+
+ /* check if we have alt really */
+ list_for_each_entry(dev_res, head, list) {
+ alt_res = res_to_dev_res(realloc_head, dev_res->res);
+ if (!alt_res || !alt_res->alt_size)
+ continue;
+
+ alt_count++;
+ }
+
+ if (!alt_count)
+ return false;
+
+ return true;
+}
+
+static void __assign_resources_alt_sorted(struct list_head *head,
+ struct list_head *save_head,
+ struct list_head *realloc_head,
+ struct list_head *local_fail_head)
+{
+ LIST_HEAD(local_alt_fail_head);
+ struct pci_dev_resource *dev_res;
+ struct pci_dev_resource *alt_res, *fail_res, *save_res;
+ unsigned long fail_type;
+ struct resource *res;
+
+ /* check failed type */
+ fail_type = pci_fail_res_type_mask(local_fail_head);
+ /* release resource with same type that failes */
+ list_for_each_entry(dev_res, head, list) {
+ res = dev_res->res;
+ if (res->parent) {
+ if (!pci_need_to_release(fail_type, res))
+ continue;
+
+ /*
+ * have to use saved info, as resource that does not
+ * have addon/alt is not in realloc list.
+ */
+ save_res = res_to_dev_res(save_head, res);
+ if (!save_res)
+ continue;
+
+ dev_printk(KERN_DEBUG, &dev_res->dev->dev,
+ "BAR %d: released %pR\n",
+ (int)(res - &dev_res->dev->resource[0]),
+ res);
+ release_resource(dev_res->res);
+ restore_resource(save_res, res);
+ } else {
+ /* restore fail one */
+ fail_res = res_to_dev_res(local_fail_head, res);
+ if (fail_res) {
+ restore_resource(fail_res, res);
+ remove_from_list(local_fail_head, res);
+ }
+ }
+
+ alt_res = res_to_dev_res(realloc_head, res);
+ if (!alt_res || !alt_res->alt_size)
+ continue;
+
+ /* change res to alt */
+ if (res->flags & IORESOURCE_STARTALIGN)
+ res->start = alt_res->alt_align;
+ else
+ res->start = 0;
+ res->end = res->start + alt_res->alt_size - 1;
+ }
+
+ sort_resources(head);
+ /* Satisfy the alt resource requests */
+ assign_requested_resources_sorted(head, &local_alt_fail_head);
+
+ /* update local fail list */
+ list_for_each_entry(fail_res, &local_alt_fail_head, list) {
+ res = fail_res->res;
+ dev_res = res_to_dev_res(realloc_head, res);
+ /* change res back to required */
+ if (dev_res && dev_res->alt_size)
+ restore_resource(dev_res, res);
+
+ if (!res_to_dev_res(local_fail_head, res))
+ add_to_list(local_fail_head, fail_res->dev, res);
+ reset_resource(res);
+ }
+ free_list(&local_alt_fail_head);
+}
+
static void __assign_resources_sorted(struct list_head *head,
struct list_head *realloc_head,
struct list_head *fail_head)
@@ -598,6 +707,8 @@ static void __assign_resources_sorted(struct list_head *head,
*/
LIST_HEAD(save_head);
+ LIST_HEAD(local_fail_head);
+ bool has_alt;
/* Check required+optional add */
if (has_addon(head, realloc_head) &&
@@ -610,15 +721,29 @@ static void __assign_resources_sorted(struct list_head *head,
sort_resources(head);
+ has_alt = __has_alt(head, realloc_head);
+ if (has_alt && list_empty(&save_head))
+ save_resources(head, &save_head);
+
/* Satisfy the must-have resource requests */
- assign_requested_resources_sorted(head, fail_head);
+ assign_requested_resources_sorted(head, &local_fail_head);
+
+ if (has_alt && !list_empty(&local_fail_head) && !list_empty(&save_head))
+ __assign_resources_alt_sorted(head, &save_head,
+ realloc_head,
+ &local_fail_head);
free_list(&save_head);
- /* Try to satisfy any additional optional resource
- requests */
+ /* Try to satisfy any additional optional resource requests */
if (realloc_head)
reassign_resources_sorted(realloc_head, head);
+
+ if (fail_head)
+ list_splice_tail(&local_fail_head, fail_head);
+ else
+ free_list(&local_fail_head);
+
free_list(head);
}
@@ -1294,6 +1419,7 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask,
mask | IORESOURCE_PREFETCH, type);
LIST_HEAD(align_test_list);
LIST_HEAD(align_test_add_list);
+ resource_size_t alt_size = 0, alt_align = 0;
resource_size_t window_align;
if (!b_res)
@@ -1352,6 +1478,7 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask,
if (realloc_head) {
resource_size_t add_r_size, add_align;
+ struct pci_dev_resource *dev_res;
add_r_size = get_res_add_size(realloc_head, r);
add_align = get_res_add_align(realloc_head, r);
@@ -1364,6 +1491,17 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask,
sum_add_size += r_size + add_r_size;
if (add_align > max_add_align)
max_add_align = add_align;
+
+ dev_res = res_to_dev_res(realloc_head, r);
+ if (dev_res && dev_res->alt_size) {
+ alt_size += dev_res->alt_size;
+ if (alt_align < dev_res->alt_align)
+ alt_align = dev_res->alt_align;
+ } else if (r_size > 1) {
+ alt_size += r_size;
+ if (alt_align < align)
+ alt_align = align;
+ }
}
}
}
@@ -1377,6 +1515,17 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask,
}
free_align_test_list(&align_test_list);
+ if (size0 && realloc_head) {
+ alt_align = max(alt_align, window_align);
+ alt_size = calculate_memsize(alt_size, min_size,
+ 0, window_align);
+ /* required is better ? */
+ if (alt_size >= size0) {
+ alt_align = 0;
+ alt_size = 0;
+ }
+ }
+
if (sum_add_size < min_sum_size)
sum_add_size = min_sum_size;
if (sum_add_size > size && realloc_head) {
@@ -1398,13 +1547,43 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask,
b_res->start = min_align;
b_res->end = size0 + min_align - 1;
b_res->flags |= IORESOURCE_STARTALIGN;
- if (size1 > size0 && realloc_head) {
- __add_to_list(realloc_head, bus->self, b_res, size1 - size0,
- min_add_align, 0, 0);
- dev_printk(KERN_DEBUG, &bus->self->dev, "bridge window %pR to %pR add_size %llx add_align %llx\n",
- b_res, &bus->busn_res,
- (unsigned long long) (size1 - size0),
- (unsigned long long) min_add_align);
+ if (realloc_head) {
+ resource_size_t final_add_size = 0;
+
+ if (size1 > size0)
+ final_add_size = size1 - size0;
+ else
+ min_add_align = 0;
+
+ /*
+ * realloc list include three type entries
+ * 1. optional only:
+ * add_size != 0, alt_size == 0, req_size == 0
+ * 2. required only with smaller alt_size.
+ * add_size == 0, alt_size != 0, req_size > alt_size
+ * 3. required + optional:
+ * add_size != 0, alt_size < req_size, req_size != 0
+ *
+ * So there is no req_size != 0, and alt_size == req_size.
+ * in that case, we already set alt_size = 0.
+ *
+ * req_align/req_size is not stored directly, and we
+ * have dev_res start/end/flags instead.
+ */
+ if (final_add_size || alt_size) {
+ __add_to_list(realloc_head, bus->self, b_res,
+ final_add_size, min_add_align,
+ alt_size, alt_align);
+ dev_printk(KERN_DEBUG, &bus->self->dev,
+ "bridge window %pR to %pR add_size %llx add_align %llx alt_size %llx alt_align %llx req_size %llx req_align %llx\n",
+ b_res, &bus->busn_res,
+ (unsigned long long)final_add_size,
+ (unsigned long long)min_add_align,
+ (unsigned long long)alt_size,
+ (unsigned long long)alt_align,
+ (unsigned long long)size0,
+ (unsigned long long)min_align);
+ }
}
return 0;
}
--
1.8.4.5
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [standalone]
Back to top | Article view | linux.kernel
csiph-web