Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1373865 > unrolled thread
| Started by | Yinghai Lu <yinghai@kernel.org> |
|---|---|
| First post | 2016-04-08 02:30 +0200 |
| Last post | 2016-04-08 03:20 +0200 |
| Articles | 20 on this page of 43 — 3 participants |
Back to article view | Back to linux.kernel
[PATCH v11 00/60] PCI: Resource allocation cleanup for v4.7 Yinghai Lu <yinghai@kernel.org> - 2016-04-08 02:30 +0200
[PATCH v11 22/60] PCI: Get new realloc size for bridge for last try Yinghai Lu <yinghai@kernel.org> - 2016-04-08 02:30 +0200
[PATCH v11 42/60] PCI: Skip required+optional if there is no optional Yinghai Lu <yinghai@kernel.org> - 2016-04-08 02:30 +0200
[PATCH v11 25/60] PCI: Reuse res_to_dev_res() in reassign_resources_sorted() Yinghai Lu <yinghai@kernel.org> - 2016-04-08 02:30 +0200
[PATCH v11 29/60] PCI: Don't add too much optional size for hotplug bridge MMIO Yinghai Lu <yinghai@kernel.org> - 2016-04-08 02:30 +0200
[PATCH v11 35/60] PCI: Simplify res reference using in __assign_resources_sorted() Yinghai Lu <yinghai@kernel.org> - 2016-04-08 02:30 +0200
[PATCH v11 32/60] PCI: Rename pdev_sort_resources() to pdev_assign_resources_prepare() Yinghai Lu <yinghai@kernel.org> - 2016-04-08 02:30 +0200
[PATCH v11 34/60] PCI: Add debug printout during releasing partial assigned resources Yinghai Lu <yinghai@kernel.org> - 2016-04-08 02:30 +0200
[PATCH v11 26/60] PCI: Use correct align for optional only resources during sorting Yinghai Lu <yinghai@kernel.org> - 2016-04-08 02:30 +0200
[PATCH v11 38/60] PCI: Check if resource is allocated before trying to assign one Yinghai Lu <yinghai@kernel.org> - 2016-04-08 02:30 +0200
[PATCH v11 31/60] PCI: Remove duplicated code for resource sorting Yinghai Lu <yinghai@kernel.org> - 2016-04-08 02:30 +0200
[PATCH v11 56/60] PCI: Add debug print out for min_align and alt_size Yinghai Lu <yinghai@kernel.org> - 2016-04-08 02:30 +0200
[PATCH v11 12/60] PCI: Check pref compatible bit for mem64 resource of PCIe device Yinghai Lu <yinghai@kernel.org> - 2016-04-08 02:30 +0200
[PATCH v11 58/60] PCI: Introduce resource_disabled() Yinghai Lu <yinghai@kernel.org> - 2016-04-08 02:30 +0200
[PATCH v11 24/60] PCI: Cleanup res_to_dev_res() printout Yinghai Lu <yinghai@kernel.org> - 2016-04-08 02:30 +0200
[PATCH v11 39/60] PCI: Separate out save_resources()/restore_resources() Yinghai Lu <yinghai@kernel.org> - 2016-04-08 02:30 +0200
[PATCH v11 49/60] PCI: Don't add too much io port for hotplug bridge with old size Yinghai Lu <yinghai@kernel.org> - 2016-04-08 02:30 +0200
[PATCH v11 54/60] resources: Make allocate_resource() return best fit resource Yinghai Lu <yinghai@kernel.org> - 2016-04-08 02:30 +0200
[PATCH v11 46/60] PCI: Fix size calculation with old_size on rescan path Yinghai Lu <yinghai@kernel.org> - 2016-04-08 02:30 +0200
[PATCH v11 48/60] PCI: Move ISA io port align out of calculate_iosize() Yinghai Lu <yinghai@kernel.org> - 2016-04-08 02:30 +0200
[PATCH v11 02/60] alpha/PCI: Only check iomem_is_exclusive() for IORESOURCE_MEM, not IORESOURCE_IO Yinghai Lu <yinghai@kernel.org> - 2016-04-08 02:30 +0200
[PATCH v11 41/60] PCI: Separate required+optional assigning to another function Yinghai Lu <yinghai@kernel.org> - 2016-04-08 02:30 +0200
[PATCH v11 33/60] PCI: Treat ROM resource as optional during realloc Yinghai Lu <yinghai@kernel.org> - 2016-04-08 02:30 +0200
[PATCH v11 28/60] PCI: Optimize bus align/size calculation for optional during sizing Yinghai Lu <yinghai@kernel.org> - 2016-04-08 02:40 +0200
[PATCH v11 04/60] sparc/PCI: Use correct offset for bus address to resource Yinghai Lu <yinghai@kernel.org> - 2016-04-08 02:40 +0200
[PATCH v11 23/60] PCI: Don't release sibling bridge resources during hotplug Yinghai Lu <yinghai@kernel.org> - 2016-04-08 02:40 +0200
[PATCH v11 05/60] sparc/PCI: Reserve legacy mmio after PCI mmio Yinghai Lu <yinghai@kernel.org> - 2016-04-08 02:40 +0200
[PATCH v11 53/60] PCI: Kill macro checking for bus io port sizing Yinghai Lu <yinghai@kernel.org> - 2016-04-08 02:40 +0200
[PATCH v11 03/60] PCI: Add pci_find_bus_resource() Yinghai Lu <yinghai@kernel.org> - 2016-04-08 02:40 +0200
[PATCH v11 11/60] OF/PCI: Add IORESOURCE_MEM_64 for 64-bit resource Yinghai Lu <yinghai@kernel.org> - 2016-04-08 02:40 +0200
[PATCH v11 06/60] sparc/PCI: Add IORESOURCE_MEM_64 for 64-bit resource in OF parsing Yinghai Lu <yinghai@kernel.org> - 2016-04-08 02:40 +0200
[PATCH v11 08/60] PCI: Kill wrong quirk about M7101 Yinghai Lu <yinghai@kernel.org> - 2016-04-08 02:40 +0200
[PATCH v11 14/60] PCI: Add has_mem64 for struct host_bridge Yinghai Lu <yinghai@kernel.org> - 2016-04-08 02:40 +0200
[PATCH v11 30/60] PCI: Reorder resources list for required/optional resources Yinghai Lu <yinghai@kernel.org> - 2016-04-08 02:40 +0200
[PATCH v11 44/60] PCI: Add alt_size ressource allocation support Yinghai Lu <yinghai@kernel.org> - 2016-04-08 02:40 +0200
Re: [PATCH v11 44/60] PCI: Add alt_size ressource allocation support Linus Torvalds <torvalds@linux-foundation.org> - 2016-04-08 03:00 +0200
Re: [PATCH v11 44/60] PCI: Add alt_size ressource allocation support Yinghai Lu <yinghai@kernel.org> - 2016-04-08 08:00 +0200
Re: [PATCH v11 44/60] PCI: Add alt_size ressource allocation support Benjamin Herrenschmidt <benh@kernel.crashing.org> - 2016-04-08 08:40 +0200
[PATCH v11 13/60] PCI: Only treat non-pref mmio64 as pref if all bridges have MEM_64 Yinghai Lu <yinghai@kernel.org> - 2016-04-08 02:40 +0200
[PATCH v11 19/60] PCI: Set resource to FIXED for LSI devices Yinghai Lu <yinghai@kernel.org> - 2016-04-08 02:40 +0200
Re: [PATCH v11 00/60] PCI: Resource allocation cleanup for v4.7 Linus Torvalds <torvalds@linux-foundation.org> - 2016-04-08 03:00 +0200
Re: [PATCH v11 00/60] PCI: Resource allocation cleanup for v4.7 Yinghai Lu <yinghai@kernel.org> - 2016-04-09 07:40 +0200
[PATCH v11 50/60] PCI: Unify calculate_size() for io port and MMIO Yinghai Lu <yinghai@kernel.org> - 2016-04-08 03:20 +0200
Page 1 of 3 [1] 2 3 Next page →
| From | Yinghai Lu <yinghai@kernel.org> |
|---|---|
| Date | 2016-04-08 02:30 +0200 |
| Subject | [PATCH v11 00/60] PCI: Resource allocation cleanup for v4.7 |
| Message-ID | <rlsjv-3zZ-3@gated-at.bofh.it> |
Hi Bjorn,
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-11: parse MEM64 for sparc and other system with OF
patch 12-16: 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 17-19: FIXED resource handling during realloc
don't realloc resource if device firmware does not support bar change.
patch 20-23: 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 24-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.7-next
That is rebased on v4.6-rc2+.
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.
-v11: replace pci_find_root_bus_resource with pci_find_bus_resource
add two patches from Bjorn for checking with pci_mmap.
refreshed to current linus tree v4.6-rc2+
Hope at least patch 1-16 could get into v4.7.
Patch 3-16 has been Oracle UEK4 for a while to boot on some sparc platforms as
them have 64bt mmio above 4G.
Thanks
Yinghai
Bjorn Helgaas (2):
PCI: Fix iomem_is_exclusive() checking in pci_mmap_resource()
alpha/PCI: Only check iomem_is_exclusive() for IORESOURCE_MEM, not IORESOURCE_IO
Yinghai Lu (58):
PCI: Add pci_find_bus_resource()
sparc/PCI: Use correct offset for bus address to resource
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
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: 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-sysfs.c | 4 +-
arch/alpha/kernel/pci.c | 2 +-
arch/ia64/pci/pci.c | 4 +-
arch/microblaze/pci/pci-common.c | 15 +-
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 | 65 +-
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 | 85 +-
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-sysfs.c | 7 +-
drivers/pci/pci.c | 31 +-
drivers/pci/pci.h | 4 +
drivers/pci/probe.c | 48 +-
drivers/pci/quirks.c | 55 +-
drivers/pci/rom.c | 2 +-
drivers/pci/setup-bus.c | 1316 +++++++++++++++++++++--------
drivers/pci/setup-res.c | 18 +-
include/linux/ioport.h | 6 +-
include/linux/pci.h | 10 +
kernel/resource.c | 104 ++-
36 files changed, 1427 insertions(+), 547 deletions(-)
--
1.8.4.5
[toc] | [next] | [standalone]
| From | Yinghai Lu <yinghai@kernel.org> |
|---|---|
| Date | 2016-04-08 02:30 +0200 |
| Subject | [PATCH v11 22/60] PCI: Get new realloc size for bridge for last try |
| Message-ID | <rlstd-3DX-25@gated-at.bofh.it> |
| In reply to | #1373865 |
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.
-v3: for last or third time and later.
change reset_bridge_resource_size to static according to Fengguang.
-v4: don't clear size for bridge's normal resources.
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 3dc4ac9..d3a39b7 100644
--- a/drivers/pci/setup-bus.c
+++ b/drivers/pci/setup-bus.c
@@ -1738,6 +1738,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
@@ -1822,8 +1833,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);
@@ -1897,8 +1913,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
[toc] | [prev] | [next] | [standalone]
| From | Yinghai Lu <yinghai@kernel.org> |
|---|---|
| Date | 2016-04-08 02:30 +0200 |
| Subject | [PATCH v11 42/60] PCI: Skip required+optional if there is no optional |
| Message-ID | <rlstd-3DX-23@gated-at.bofh.it> |
| In reply to | #1373865 |
If the bridge does not support hotplug and has no child with sriov support,
We will not have optional resources. We could get out early and
don't try required+optional allocation.
Also in the loop that update res with optional add info, skip resource
that add_size is 0.
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
---
drivers/pci/setup-bus.c | 32 +++++++++++++++++++++++++++++---
1 file changed, 29 insertions(+), 3 deletions(-)
diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c
index a4f53ec..373f76f 100644
--- a/drivers/pci/setup-bus.c
+++ b/drivers/pci/setup-bus.c
@@ -449,6 +449,24 @@ static bool pci_need_to_release(unsigned long mask, struct resource *res)
return false; /* should not get here */
}
+static bool has_addon(struct list_head *head,
+ struct list_head *realloc_head)
+{
+ int add_count = 0;
+ struct pci_dev_resource *dev_res, *tmp_res;
+
+ /* check if we have add really */
+ list_for_each_entry(dev_res, head, list) {
+ tmp_res = res_to_dev_res(realloc_head, dev_res->res);
+ if (!tmp_res || !tmp_res->add_size)
+ continue;
+
+ add_count++;
+ }
+
+ return add_count != 0;
+}
+
static bool save_resources(struct list_head *head,
struct list_head *save_head)
{
@@ -480,16 +498,24 @@ static bool __assign_resources_required_optional_sorted(struct list_head *head,
struct pci_dev_resource *save_res;
struct pci_dev_resource *dev_res, *tmp_res;
unsigned long fail_type;
- resource_size_t add_align;
+ resource_size_t add_align, add_size;
struct resource *res;
+ if (!has_addon(head, realloc_head))
+ return false;
+
if (!save_resources(head, &save_head))
return false;
/* Update res in head list with add_size in realloc_head list */
list_for_each_entry(dev_res, head, list) {
res = dev_res->res;
- res->end += get_res_add_size(realloc_head, res);
+ add_size = get_res_add_size(realloc_head, res);
+
+ if (!add_size)
+ continue;
+
+ res->end += add_size;
/*
* There are two kinds of additional resources in the list:
@@ -577,7 +603,7 @@ static void __assign_resources_sorted(struct list_head *head,
*/
/* Check required+optional add */
- if (realloc_head && !list_empty(realloc_head) &&
+ if (realloc_head &&
__assign_resources_required_optional_sorted(head, realloc_head))
return;
--
1.8.4.5
[toc] | [prev] | [next] | [standalone]
| From | Yinghai Lu <yinghai@kernel.org> |
|---|---|
| Date | 2016-04-08 02:30 +0200 |
| Subject | [PATCH v11 25/60] PCI: Reuse res_to_dev_res() in reassign_resources_sorted() |
| Message-ID | <rlstd-3DX-27@gated-at.bofh.it> |
| In reply to | #1373865 |
Now res_to_dev_res() does not print out debug message anymore, so
we can reuse it in reassign_resource_sorted() without confusing printout.
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
---
drivers/pci/setup-bus.c | 11 +----------
1 file changed, 1 insertion(+), 10 deletions(-)
diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c
index dd33234..fc30f80 100644
--- a/drivers/pci/setup-bus.c
+++ b/drivers/pci/setup-bus.c
@@ -239,26 +239,17 @@ static void reassign_resources_sorted(struct list_head *realloc_head,
{
struct resource *res;
struct pci_dev_resource *add_res, *tmp;
- struct pci_dev_resource *dev_res;
resource_size_t add_size, align;
int idx;
list_for_each_entry_safe(add_res, tmp, realloc_head, list) {
- bool found_match = false;
-
res = add_res->res;
/* skip resource that has been reset */
if (!res->flags)
goto out;
/* skip this resource if not found in head list */
- list_for_each_entry(dev_res, head, list) {
- if (dev_res->res == res) {
- found_match = true;
- break;
- }
- }
- if (!found_match)/* just skip */
+ if (!res_to_dev_res(head, res))
continue;
idx = res - &add_res->dev->resource[0];
--
1.8.4.5
[toc] | [prev] | [next] | [standalone]
| From | Yinghai Lu <yinghai@kernel.org> |
|---|---|
| Date | 2016-04-08 02:30 +0200 |
| Subject | [PATCH v11 29/60] PCI: Don't add too much optional size for hotplug bridge MMIO |
| Message-ID | <rlstd-3DX-29@gated-at.bofh.it> |
| In reply to | #1373865 |
Current code will always add 2M for hotplug bridge MMIO even
there is child device under it already.
For example:
40:03.0 --- 43:00.0 --- 44:02.0 -+- 45:00.0
\- 45:00.1
44:02.0 will need 1M as must for 45:00.0 and 45:00.1
When we calculate add_size for 44:02.0, we pass 2M as additional
size for hotplug bridge, total will be 3M.
That is different from code before changes for optional support,
or even current code that treat optional as required directly by
not passing realloc list. We only need 2M as total.
The optional size should be 1M, and total size should be 2M.
This patch change to comparing required+optional with min_sum_size to
get smaller optional size.
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
---
drivers/pci/setup-bus.c | 28 +++++++++++++++-------------
1 file changed, 15 insertions(+), 13 deletions(-)
diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c
index 12fd6d9..f6b7b8f 100644
--- a/drivers/pci/setup-bus.c
+++ b/drivers/pci/setup-bus.c
@@ -1198,7 +1198,6 @@ out:
* @type2: second match type
* @type3: third match type
* @min_size : the minimum memory window that must to be allocated
- * @add_size : additional optional memory window
* @realloc_head : track the additional memory window on this list
*
* Calculate the size of the bus and minimal alignment which
@@ -1211,10 +1210,11 @@ out:
static int pbus_size_mem(struct pci_bus *bus, unsigned long mask,
unsigned long type, unsigned long type2,
unsigned long type3,
- resource_size_t min_size, resource_size_t add_size,
+ resource_size_t min_size,
struct list_head *realloc_head)
{
struct pci_dev *dev;
+ resource_size_t min_sum_size = 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;
@@ -1226,6 +1226,11 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask,
if (!b_res)
return -ENOSPC;
+ if (realloc_head) {
+ min_sum_size = min_size;
+ min_size = 0;
+ }
+
list_for_each_entry(dev, &bus->devices, bus_list) {
int i;
@@ -1298,8 +1303,8 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask,
}
free_align_test_list(&align_test_list);
- if ((sum_add_size - size) < add_size)
- sum_add_size = size + add_size;
+ if (sum_add_size < min_sum_size)
+ sum_add_size = min_sum_size;
if (sum_add_size > size && realloc_head) {
min_add_align = calculate_mem_align(&align_test_add_list,
max_add_align, sum_add_size,
@@ -1436,7 +1441,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 additional_mem_size = 0, additional_io_size = 0;
+ resource_size_t min_mem_size = 0, additional_io_size = 0;
struct resource *b_res;
int ret;
@@ -1473,7 +1478,7 @@ 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;
- additional_mem_size = pci_hotplug_mem_size;
+ min_mem_size = pci_hotplug_mem_size;
}
/* Fall through */
default:
@@ -1493,8 +1498,7 @@ void __pci_bus_size_bridges(struct pci_bus *bus, struct list_head *realloc_head)
prefmask |= IORESOURCE_MEM_64;
ret = pbus_size_mem(bus, prefmask, prefmask,
prefmask, prefmask,
- realloc_head ? 0 : additional_mem_size,
- additional_mem_size, realloc_head);
+ min_mem_size, realloc_head);
/*
* If successful, all non-prefetchable resources
@@ -1517,8 +1521,7 @@ void __pci_bus_size_bridges(struct pci_bus *bus, struct list_head *realloc_head)
prefmask &= ~IORESOURCE_MEM_64;
ret = pbus_size_mem(bus, prefmask, prefmask,
prefmask, prefmask,
- realloc_head ? 0 : additional_mem_size,
- additional_mem_size, realloc_head);
+ min_mem_size, realloc_head);
/*
* If successful, only non-prefetchable resources
@@ -1527,7 +1530,7 @@ void __pci_bus_size_bridges(struct pci_bus *bus, struct list_head *realloc_head)
if (ret == 0)
mask = prefmask;
else
- additional_mem_size += additional_mem_size;
+ min_mem_size += min_mem_size;
type2 = type3 = IORESOURCE_MEM;
}
@@ -1548,8 +1551,7 @@ void __pci_bus_size_bridges(struct pci_bus *bus, struct list_head *realloc_head)
* window.
*/
pbus_size_mem(bus, mask, IORESOURCE_MEM, type2, type3,
- realloc_head ? 0 : additional_mem_size,
- additional_mem_size, realloc_head);
+ min_mem_size, realloc_head);
break;
}
}
--
1.8.4.5
[toc] | [prev] | [next] | [standalone]
| From | Yinghai Lu <yinghai@kernel.org> |
|---|---|
| Date | 2016-04-08 02:30 +0200 |
| Subject | [PATCH v11 35/60] PCI: Simplify res reference using in __assign_resources_sorted() |
| Message-ID | <rlstd-3DX-33@gated-at.bofh.it> |
| In reply to | #1373865 |
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 b22eb5f..7865e44 100644
--- a/drivers/pci/setup-bus.c
+++ b/drivers/pci/setup-bus.c
@@ -457,6 +457,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))
@@ -472,8 +473,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:
@@ -482,16 +483,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;
}
}
@@ -513,21 +514,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",
@@ -538,8 +539,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
[toc] | [prev] | [next] | [standalone]
| From | Yinghai Lu <yinghai@kernel.org> |
|---|---|
| Date | 2016-04-08 02:30 +0200 |
| Subject | [PATCH v11 32/60] PCI: Rename pdev_sort_resources() to pdev_assign_resources_prepare() |
| Message-ID | <rlste-3DX-35@gated-at.bofh.it> |
| In reply to | #1373865 |
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 0e3be10..9cd0411 100644
--- a/drivers/pci/setup-bus.c
+++ b/drivers/pci/setup-bus.c
@@ -204,8 +204,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)
{
@@ -241,7 +241,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)
{
@@ -259,7 +259,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)
@@ -565,7 +565,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);
}
@@ -578,7 +578,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
[toc] | [prev] | [next] | [standalone]
| From | Yinghai Lu <yinghai@kernel.org> |
|---|---|
| Date | 2016-04-08 02:30 +0200 |
| Subject | [PATCH v11 34/60] PCI: Add debug printout during releasing partial assigned resources |
| Message-ID | <rlstd-3DX-31@gated-at.bofh.it> |
| In reply to | #1373865 |
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 f9e6a00..b22eb5f 100644
--- a/drivers/pci/setup-bus.c
+++ b/drivers/pci/setup-bus.c
@@ -525,9 +525,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
[toc] | [prev] | [next] | [standalone]
| From | Yinghai Lu <yinghai@kernel.org> |
|---|---|
| Date | 2016-04-08 02:30 +0200 |
| Subject | [PATCH v11 26/60] PCI: Use correct align for optional only resources during sorting |
| Message-ID | <rlste-3DX-39@gated-at.bofh.it> |
| In reply to | #1373865 |
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 fc30f80..544f518 100644
--- a/drivers/pci/setup-bus.c
+++ b/drivers/pci/setup-bus.c
@@ -144,9 +144,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;
@@ -164,7 +197,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);
@@ -182,8 +215,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;
@@ -196,6 +230,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;
@@ -212,7 +247,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)
@@ -506,7 +541,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);
}
@@ -519,7 +554,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
[toc] | [prev] | [next] | [standalone]
| From | Yinghai Lu <yinghai@kernel.org> |
|---|---|
| Date | 2016-04-08 02:30 +0200 |
| Subject | [PATCH v11 38/60] PCI: Check if resource is allocated before trying to assign one |
| Message-ID | <rlste-3DX-41@gated-at.bofh.it> |
| In reply to | #1373865 |
In following alt_size support, we will call pci_assign_resource() several
times on one resource list, and some resources could have been assigned
already.
Skip allocated resource in the list, as pci_assign_resource()
only can handle not assigned resource.
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
---
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 4d2898d..b5529cc 100644
--- a/drivers/pci/setup-bus.c
+++ b/drivers/pci/setup-bus.c
@@ -385,7 +385,7 @@ static void assign_requested_resources_sorted(struct list_head *head,
list_for_each_entry(dev_res, head, list) {
res = dev_res->res;
idx = res - &dev_res->dev->resource[0];
- if (resource_size(res) &&
+ if (!res->parent && resource_size(res) &&
pci_assign_resource(dev_res->dev, idx)) {
if (fail_head)
add_to_list(fail_head, dev_res->dev, res);
--
1.8.4.5
[toc] | [prev] | [next] | [standalone]
| From | Yinghai Lu <yinghai@kernel.org> |
|---|---|
| Date | 2016-04-08 02:30 +0200 |
| Subject | [PATCH v11 31/60] PCI: Remove duplicated code for resource sorting |
| Message-ID | <rlste-3DX-43@gated-at.bofh.it> |
| In reply to | #1373865 |
Now sort_resources() and pdev_sort_resources() all have sorting
code.
As we are going to call sort_resources() several places later for
alt_size support, so choose to remove related code in
pdev_sort_resources().
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
---
drivers/pci/setup-bus.c | 22 +++-------------------
1 file changed, 3 insertions(+), 19 deletions(-)
diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c
index aed62cc..0e3be10 100644
--- a/drivers/pci/setup-bus.c
+++ b/drivers/pci/setup-bus.c
@@ -213,9 +213,8 @@ static void pdev_sort_resources(struct pci_dev *dev,
for (i = 0; i < PCI_NUM_RESOURCES; i++) {
struct resource *r;
- struct pci_dev_resource *dev_res, *tmp;
+ struct pci_dev_resource *tmp;
resource_size_t r_align;
- struct list_head *n;
r = &dev->resource[i];
@@ -238,22 +237,7 @@ static void pdev_sort_resources(struct pci_dev *dev,
tmp->res = r;
tmp->dev = dev;
- /* fallback is smallest one or list is empty*/
- n = head;
- list_for_each_entry(dev_res, head, list) {
- resource_size_t align;
-
- align = __pci_resource_alignment(dev_res->dev,
- dev_res->res,
- realloc_head);
-
- if (r_align > align) {
- n = &dev_res->list;
- break;
- }
- }
- /* Insert it just before n*/
- list_add_tail(&tmp->list, n);
+ list_add_tail(&tmp->list, head);
}
}
@@ -562,9 +546,9 @@ static void __assign_resources_sorted(struct list_head *head,
}
free_list(&save_head);
+requested_and_reassign:
sort_resources(head);
-requested_and_reassign:
/* Satisfy the must-have resource requests */
assign_requested_resources_sorted(head, fail_head);
--
1.8.4.5
[toc] | [prev] | [next] | [standalone]
| From | Yinghai Lu <yinghai@kernel.org> |
|---|---|
| Date | 2016-04-08 02:30 +0200 |
| Subject | [PATCH v11 56/60] PCI: Add debug print out for min_align and alt_size |
| Message-ID | <rlste-3DX-45@gated-at.bofh.it> |
| In reply to | #1373865 |
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 c282b86..bd74349 100644
--- a/drivers/pci/setup-bus.c
+++ b/drivers/pci/setup-bus.c
@@ -158,11 +158,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;
}
@@ -175,11 +170,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;
}
@@ -1270,6 +1260,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)
@@ -1283,7 +1275,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;
@@ -1293,6 +1286,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);
@@ -1358,6 +1353,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;
@@ -1365,9 +1373,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;
@@ -1392,6 +1397,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;
}
@@ -1409,6 +1419,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;
@@ -1433,6 +1453,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;
}
@@ -1515,7 +1540,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);
@@ -1534,7 +1559,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;
@@ -1551,7 +1576,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;
@@ -1561,14 +1587,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;
@@ -1579,6 +1605,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,
@@ -1588,6 +1617,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,
@@ -1603,6 +1635,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);
@@ -1660,7 +1695,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
[toc] | [prev] | [next] | [standalone]
| From | Yinghai Lu <yinghai@kernel.org> |
|---|---|
| Date | 2016-04-08 02:30 +0200 |
| Subject | [PATCH v11 12/60] PCI: Check pref compatible bit for mem64 resource of PCIe device |
| Message-ID | <rlste-3DX-49@gated-at.bofh.it> |
| In reply to | #1373865 |
We still get "no compatible bridge window" warning on sparc T5-8
after we add support for 64bit resource parsing for root bus.
PCI: scan_bus[/pci@300/pci@1/pci@0/pci@6] bus no 8
PCI: Claiming 0000:00:01.0: Resource 15: 0000800100000000..00008004afffffff [220c]
PCI: Claiming 0000:01:00.0: Resource 15: 0000800100000000..00008004afffffff [220c]
PCI: Claiming 0000:02:04.0: Resource 15: 0000800100000000..000080012fffffff [220c]
PCI: Claiming 0000:03:00.0: Resource 15: 0000800100000000..000080012fffffff [220c]
PCI: Claiming 0000:04:06.0: Resource 14: 0000800100000000..000080010fffffff [220c]
PCI: Claiming 0000:05:00.0: Resource 0: 0000800100000000..0000800100001fff [204]
pci 0000:05:00.0: can't claim BAR 0 [mem 0x800100000000-0x800100001fff]: no compatible bridge window
All the bridges 64-bit resource have pref bit, but the device resource does not
have pref set, then we can not find parent for the device resource,
as we can not put non-pref mmio under pref mmio.
According to pcie spec errta
https://www.pcisig.com/specifications/pciexpress/base2/PCIe_Base_r2.1_Errata_08Jun10.pdf
page 13, in some case it is ok to mark some as pref.
Mark if the entire path from the host to the adapter is over PCI Express.
Set pref compatible bit for claim/sizing/assign for 64bit mem resource
on that pcie device.
-v2: set pref for mmio 64 when whole path is PCI Express, according to David Miller.
-v3: don't set pref directly, change to UNDER_PREF, and set PREF before
sizing and assign resource, and cleart PREF afterwards. requested by BenH.
-v4: use on_all_pcie_path device flag instead.
-v6: update after pci_find_bus_resource() change
Fixes: commit d63e2e1f3df9 ("sparc/PCI: Clip bridge windows to fit in upstream windows")
Link: http://lkml.kernel.org/r/CAE9FiQU1gJY1LYrxs+ma5LCTEEe4xmtjRG0aXJ9K_Tsu+m9Wuw@mail.gmail.com
Reported-by: David Ahern <david.ahern@oracle.com>
Tested-by: David Ahern <david.ahern@oracle.com>
Link: https://bugzilla.kernel.org/show_bug.cgi?id=81431
Tested-by: TJ <linux@iam.tj>
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
Tested-by: Khalid Aziz <khalid.aziz@oracle.com>
---
arch/sparc/kernel/pci.c | 2 +-
arch/sparc/kernel/pci_common.c | 2 +-
drivers/pci/pci.c | 8 +++++---
drivers/pci/pci.h | 2 ++
drivers/pci/probe.c | 33 +++++++++++++++++++++++++++++++++
drivers/pci/setup-bus.c | 23 +++++++++++++++++++----
drivers/pci/setup-res.c | 4 ++++
include/linux/pci.h | 3 ++-
8 files changed, 67 insertions(+), 10 deletions(-)
diff --git a/arch/sparc/kernel/pci.c b/arch/sparc/kernel/pci.c
index 9415abc..e46e739 100644
--- a/arch/sparc/kernel/pci.c
+++ b/arch/sparc/kernel/pci.c
@@ -761,7 +761,7 @@ static int __pci_mmap_make_offset_bus(struct pci_dev *pdev, struct vm_area_struc
bus = pdev->bus;
while (bus->parent)
bus = bus->parent;
- root_bus_res = pci_find_bus_resource(bus, &res);
+ root_bus_res = pci_find_bus_resource(bus, &res, res.flags);
if (!root_bus_res)
return -EINVAL;
diff --git a/arch/sparc/kernel/pci_common.c b/arch/sparc/kernel/pci_common.c
index 1ebc7ff..6f206a1 100644
--- a/arch/sparc/kernel/pci_common.c
+++ b/arch/sparc/kernel/pci_common.c
@@ -343,7 +343,7 @@ static void pci_register_region(struct pci_bus *bus, const char *name,
region.start = rstart;
region.end = rstart + size - 1UL;
pcibios_bus_to_resource(bus, res, ®ion);
- bus_res = pci_find_bus_resource(bus, res);
+ bus_res = pci_find_bus_resource(bus, res, res->flags);
if (!bus_res) {
kfree(res);
return;
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 313dea5..bd72df3 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -415,7 +415,7 @@ int pci_find_ht_capability(struct pci_dev *dev, int ht_cap)
EXPORT_SYMBOL_GPL(pci_find_ht_capability);
struct resource *pci_find_bus_resource(const struct pci_bus *bus,
- struct resource *res)
+ struct resource *res, int flags)
{
struct resource *r;
int i;
@@ -430,7 +430,7 @@ struct resource *pci_find_bus_resource(const struct pci_bus *bus,
* not, the allocator made a mistake.
*/
if (r->flags & IORESOURCE_PREFETCH &&
- !(res->flags & IORESOURCE_PREFETCH))
+ !(flags & IORESOURCE_PREFETCH))
return NULL;
/*
@@ -458,7 +458,9 @@ struct resource *pci_find_bus_resource(const struct pci_bus *bus,
struct resource *pci_find_parent_resource(const struct pci_dev *dev,
struct resource *res)
{
- return pci_find_bus_resource(dev->bus, res);
+ int flags = pci_resource_pref_compatible(dev, res);
+
+ return pci_find_bus_resource(dev->bus, res, flags);
}
EXPORT_SYMBOL(pci_find_parent_resource);
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
index d0fb934..90e6e3e 100644
--- a/drivers/pci/pci.h
+++ b/drivers/pci/pci.h
@@ -335,4 +335,6 @@ static inline int pci_dev_specific_reset(struct pci_dev *dev, int probe)
}
#endif
+int pci_resource_pref_compatible(const struct pci_dev *dev,
+ struct resource *res);
#endif /* DRIVERS_PCI_H */
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index 8004f67..48e6f29 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -1731,6 +1731,36 @@ static void pci_dma_configure(struct pci_dev *dev)
pci_put_host_bridge_device(bridge);
}
+static bool pci_up_path_over_pcie(struct pci_bus *bus)
+{
+ if (pci_is_root_bus(bus))
+ return true;
+
+ if (bus->self && !pci_is_pcie(bus->self))
+ return false;
+
+ return pci_up_path_over_pcie(bus->parent);
+}
+
+/*
+ * According to
+ * https://www.pcisig.com/specifications/pciexpress/base2/PCIe_Base_r2.1_Errata_08Jun10.pdf
+ * page 13, system firmware could put some 64bit non-pref under 64bit pref,
+ * on some cases.
+ * Let's mark if entire path from the host to the adapter is over PCI
+ * Express. later will use that compute pref compaitable bit.
+ */
+static void pci_set_on_all_pcie_path(struct pci_dev *dev)
+{
+ if (!pci_is_pcie(dev))
+ return;
+
+ if (!pci_up_path_over_pcie(dev->bus))
+ return;
+
+ dev->on_all_pcie_path = 1;
+}
+
void pci_device_add(struct pci_dev *dev, struct pci_bus *bus)
{
int ret;
@@ -1761,6 +1791,9 @@ void pci_device_add(struct pci_dev *dev, struct pci_bus *bus)
/* Initialize various capabilities */
pci_init_capabilities(dev);
+ /* After pcie_cap is assigned */
+ pci_set_on_all_pcie_path(dev);
+
/*
* Add the device to our list of discovered devices
* and the bus list for fixup functions, etc.
diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c
index 55641a3..b3b1565 100644
--- a/drivers/pci/setup-bus.c
+++ b/drivers/pci/setup-bus.c
@@ -738,6 +738,20 @@ int pci_claim_bridge_resource(struct pci_dev *bridge, int i)
return -EINVAL;
}
+int pci_resource_pref_compatible(const struct pci_dev *dev,
+ struct resource *res)
+{
+ if (res->flags & IORESOURCE_PREFETCH)
+ return res->flags;
+
+ if ((res->flags & IORESOURCE_MEM) &&
+ (res->flags & IORESOURCE_MEM_64) &&
+ dev->on_all_pcie_path)
+ return res->flags | IORESOURCE_PREFETCH;
+
+ return res->flags;
+}
+
/* Check whether the bridge supports optional I/O and
prefetchable memory ranges. If not, the respective
base/limit registers must be read-only and read as 0. */
@@ -1035,11 +1049,12 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask,
for (i = 0; i < PCI_NUM_RESOURCES; i++) {
struct resource *r = &dev->resource[i];
resource_size_t r_size;
+ int flags = pci_resource_pref_compatible(dev, r);
- if (r->parent || (r->flags & IORESOURCE_PCI_FIXED) ||
- ((r->flags & mask) != type &&
- (r->flags & mask) != type2 &&
- (r->flags & mask) != type3))
+ if (r->parent || (flags & IORESOURCE_PCI_FIXED) ||
+ ((flags & mask) != type &&
+ (flags & mask) != type2 &&
+ (flags & mask) != type3))
continue;
r_size = resource_size(r);
#ifdef CONFIG_PCI_IOV
diff --git a/drivers/pci/setup-res.c b/drivers/pci/setup-res.c
index 66c4d8f..f741fed 100644
--- a/drivers/pci/setup-res.c
+++ b/drivers/pci/setup-res.c
@@ -257,15 +257,19 @@ static int __pci_assign_resource(struct pci_bus *bus, struct pci_dev *dev,
static int _pci_assign_resource(struct pci_dev *dev, int resno,
resource_size_t size, resource_size_t min_align)
{
+ struct resource *res = dev->resource + resno;
+ int old_flags = res->flags;
struct pci_bus *bus;
int ret;
+ res->flags = pci_resource_pref_compatible(dev, res);
bus = dev->bus;
while ((ret = __pci_assign_resource(bus, dev, resno, size, min_align))) {
if (!bus->parent || !bus->self->transparent)
break;
bus = bus->parent;
}
+ res->flags = old_flags;
return ret;
}
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 795b4c7..1527735 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -305,6 +305,7 @@ struct pci_dev {
powered on/off by the
corresponding bridge */
unsigned int ignore_hotplug:1; /* Ignore hotplug events */
+ unsigned int on_all_pcie_path:1; /* up to host-bridge all pcie */
unsigned int d3_delay; /* D3->D0 transition time in ms */
unsigned int d3cold_delay; /* D3cold->D0 transition time in ms */
@@ -808,7 +809,7 @@ void pcibios_resource_to_bus(struct pci_bus *bus, struct pci_bus_region *region,
void pcibios_bus_to_resource(struct pci_bus *bus, struct resource *res,
struct pci_bus_region *region);
struct resource *pci_find_bus_resource(const struct pci_bus *bus,
- struct resource *res);
+ struct resource *res, int flags);
void pcibios_scan_specific_bus(int busn);
struct pci_bus *pci_find_bus(int domain, int busnr);
void pci_bus_add_devices(const struct pci_bus *bus);
--
1.8.4.5
[toc] | [prev] | [next] | [standalone]
| From | Yinghai Lu <yinghai@kernel.org> |
|---|---|
| Date | 2016-04-08 02:30 +0200 |
| Subject | [PATCH v11 58/60] PCI: Introduce resource_disabled() |
| Message-ID | <rlste-3DX-51@gated-at.bofh.it> |
| In reply to | #1373865 |
Current is using !flags, and we are going to use
IORESOURCE_DISABLED instead of clearing resource flags.
Let's convert all !flags to helper function resource_disabled().
resource_disabled will check !flags and IORESOURCE_DISABLED both.
Cc: linux-alpha@vger.kernel.org
Cc: linux-ia64@vger.kernel.org
Cc: linux-am33-list@redhat.com
Cc: linuxppc-dev@lists.ozlabs.org
Cc: linux-s390@vger.kernel.org
Cc: sparclinux@vger.kernel.org
Cc: linux-pci@vger.kernel.org
Cc: linux-xtensa@linux-xtensa.org
Cc: iommu@lists.linux-foundation.org
Cc: linux-sh@vger.kernel.org
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
Acked-by: Michael Ellerman <mpe@ellerman.id.au>
---
arch/alpha/kernel/pci.c | 2 +-
arch/ia64/pci/pci.c | 4 ++--
arch/microblaze/pci/pci-common.c | 15 ++++++++-------
arch/mn10300/unit-asb2305/pci-asb2305.c | 4 ++--
arch/mn10300/unit-asb2305/pci.c | 4 ++--
arch/powerpc/kernel/pci-common.c | 16 +++++++++-------
arch/powerpc/platforms/powernv/pci-ioda.c | 12 ++++++------
arch/s390/pci/pci.c | 2 +-
arch/sparc/kernel/pci.c | 2 +-
arch/x86/pci/i386.c | 4 ++--
arch/xtensa/kernel/pci.c | 4 ++--
drivers/iommu/intel-iommu.c | 3 ++-
drivers/pci/host/pcie-rcar.c | 2 +-
drivers/pci/iov.c | 2 +-
drivers/pci/probe.c | 2 +-
drivers/pci/quirks.c | 4 ++--
drivers/pci/rom.c | 2 +-
drivers/pci/setup-bus.c | 8 ++++----
drivers/pci/setup-res.c | 2 +-
include/linux/ioport.h | 4 ++++
20 files changed, 53 insertions(+), 45 deletions(-)
diff --git a/arch/alpha/kernel/pci.c b/arch/alpha/kernel/pci.c
index 5f387ee..c89c8ef 100644
--- a/arch/alpha/kernel/pci.c
+++ b/arch/alpha/kernel/pci.c
@@ -282,7 +282,7 @@ pcibios_claim_one_bus(struct pci_bus *b)
for (i = 0; i < PCI_NUM_RESOURCES; i++) {
struct resource *r = &dev->resource[i];
- if (r->parent || !r->start || !r->flags)
+ if (r->parent || !r->start || resource_disabled(r))
continue;
if (pci_has_flag(PCI_PROBE_ONLY) ||
(r->flags & IORESOURCE_PCI_FIXED)) {
diff --git a/arch/ia64/pci/pci.c b/arch/ia64/pci/pci.c
index 8f6ac2f..f00373f 100644
--- a/arch/ia64/pci/pci.c
+++ b/arch/ia64/pci/pci.c
@@ -333,7 +333,7 @@ void pcibios_fixup_device_resources(struct pci_dev *dev)
for (idx = 0; idx < PCI_BRIDGE_RESOURCES; idx++) {
struct resource *r = &dev->resource[idx];
- if (!r->flags || r->parent || !r->start)
+ if (resource_disabled(r) || r->parent || !r->start)
continue;
pci_claim_resource(dev, idx);
@@ -351,7 +351,7 @@ static void pcibios_fixup_bridge_resources(struct pci_dev *dev)
for (idx = PCI_BRIDGE_RESOURCES; idx < PCI_NUM_RESOURCES; idx++) {
struct resource *r = &dev->resource[idx];
- if (!r->flags || r->parent || !r->start)
+ if (resource_disabled(r) || r->parent || !r->start)
continue;
pci_claim_bridge_resource(dev, idx);
diff --git a/arch/microblaze/pci/pci-common.c b/arch/microblaze/pci/pci-common.c
index 35654be..4cc5ed0 100644
--- a/arch/microblaze/pci/pci-common.c
+++ b/arch/microblaze/pci/pci-common.c
@@ -694,7 +694,7 @@ static void pcibios_fixup_resources(struct pci_dev *dev)
}
for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
struct resource *res = dev->resource + i;
- if (!res->flags)
+ if (resource_disabled(res))
continue;
if (res->start == 0) {
pr_debug("PCI:%s Resource %d %016llx-%016llx [%x]",
@@ -795,7 +795,7 @@ static void pcibios_fixup_bridge(struct pci_bus *bus)
pci_bus_for_each_resource(bus, res, i) {
if (!res)
continue;
- if (!res->flags)
+ if (resource_disabled(res))
continue;
if (i >= 3 && bus->self->transparent)
continue;
@@ -964,7 +964,7 @@ static void pcibios_allocate_bus_resources(struct pci_bus *bus)
pci_domain_nr(bus), bus->number);
pci_bus_for_each_resource(bus, res, i) {
- if (!res || !res->flags
+ if (!res || resource_disabled(res)
|| res->start > res->end || res->parent)
continue;
if (bus->parent == NULL)
@@ -1066,7 +1066,8 @@ static void __init pcibios_allocate_resources(int pass)
r = &dev->resource[idx];
if (r->parent) /* Already allocated */
continue;
- if (!r->flags || (r->flags & IORESOURCE_UNSET))
+ if (resource_disabled(r) ||
+ (r->flags & IORESOURCE_UNSET))
continue; /* Not assigned at all */
/* We only allocate ROMs on pass 1 just in case they
* have been screwed up by firmware
@@ -1197,7 +1198,7 @@ void pcibios_claim_one_bus(struct pci_bus *bus)
for (i = 0; i < PCI_NUM_RESOURCES; i++) {
struct resource *r = &dev->resource[i];
- if (r->parent || !r->start || !r->flags)
+ if (r->parent || !r->start || resource_disabled(r))
continue;
pr_debug("PCI: Claiming %s: ", pci_name(dev));
@@ -1257,7 +1258,7 @@ static void pcibios_setup_phb_resources(struct pci_controller *hose,
res->start = (res->start + io_offset) & 0xffffffffu;
res->end = (res->end + io_offset) & 0xffffffffu;
- if (!res->flags) {
+ if (resource_disabled(res)) {
pr_warn("PCI: I/O resource not set for host ");
pr_cont("bridge %s (domain %d)\n",
hose->dn->full_name, hose->global_number);
@@ -1277,7 +1278,7 @@ static void pcibios_setup_phb_resources(struct pci_controller *hose,
/* Hookup PHB Memory resources */
for (i = 0; i < 3; ++i) {
res = &hose->mem_resources[i];
- if (!res->flags) {
+ if (resource_disabled(res)) {
if (i > 0)
continue;
pr_err("PCI: Memory resource 0 not set for ");
diff --git a/arch/mn10300/unit-asb2305/pci-asb2305.c b/arch/mn10300/unit-asb2305/pci-asb2305.c
index b7ab837..7e70e51 100644
--- a/arch/mn10300/unit-asb2305/pci-asb2305.c
+++ b/arch/mn10300/unit-asb2305/pci-asb2305.c
@@ -103,7 +103,7 @@ static void __init pcibios_allocate_bus_resources(struct list_head *bus_list)
idx < PCI_NUM_RESOURCES;
idx++) {
r = &dev->resource[idx];
- if (!r->flags)
+ if (resource_disabled(r))
continue;
if (!r->start ||
pci_claim_bridge_resource(dev, idx) < 0) {
@@ -188,7 +188,7 @@ static int __init pcibios_assign_resources(void)
addresses. */
for_each_pci_dev(dev) {
r = &dev->resource[PCI_ROM_RESOURCE];
- if (!r->flags || !r->start)
+ if (resource_disabled(r) || !r->start)
continue;
if (pci_claim_resource(dev, PCI_ROM_RESOURCE) < 0) {
r->end -= r->start;
diff --git a/arch/mn10300/unit-asb2305/pci.c b/arch/mn10300/unit-asb2305/pci.c
index 3dfe2d3..ad77b18 100644
--- a/arch/mn10300/unit-asb2305/pci.c
+++ b/arch/mn10300/unit-asb2305/pci.c
@@ -291,7 +291,7 @@ static void pcibios_fixup_device_resources(struct pci_dev *dev)
for (idx = 0; idx < PCI_BRIDGE_RESOURCES; idx++) {
struct resource *r = &dev->resource[idx];
- if (!r->flags || r->parent || !r->start)
+ if (resource_disabled(r) || r->parent || !r->start)
continue;
pci_claim_resource(dev, idx);
@@ -308,7 +308,7 @@ static void pcibios_fixup_bridge_resources(struct pci_dev *dev)
for (idx = PCI_BRIDGE_RESOURCES; idx < PCI_NUM_RESOURCES; idx++) {
struct resource *r = &dev->resource[idx];
- if (!r->flags || r->parent || !r->start)
+ if (resource_disabled(r) || r->parent || !r->start)
continue;
pci_claim_bridge_resource(dev, idx);
diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c
index 2a7f4fd..94d11f9 100644
--- a/arch/powerpc/kernel/pci-common.c
+++ b/arch/powerpc/kernel/pci-common.c
@@ -811,7 +811,7 @@ static void pcibios_fixup_resources(struct pci_dev *dev)
for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
struct resource *res = dev->resource + i;
struct pci_bus_region reg;
- if (!res->flags)
+ if (resource_disabled(res))
continue;
/* If we're going to re-assign everything, we mark all resources
@@ -920,7 +920,7 @@ static void pcibios_fixup_bridge(struct pci_bus *bus)
struct pci_dev *dev = bus->self;
pci_bus_for_each_resource(bus, res, i) {
- if (!res || !res->flags)
+ if (!res || resource_disabled(res))
continue;
if (i >= 3 && bus->self->transparent)
continue;
@@ -1161,7 +1161,8 @@ static void pcibios_allocate_bus_resources(struct pci_bus *bus)
pci_domain_nr(bus), bus->number);
pci_bus_for_each_resource(bus, res, i) {
- if (!res || !res->flags || res->start > res->end || res->parent)
+ if (!res || resource_disabled(res) ||
+ res->start > res->end || res->parent)
continue;
/* If the resource was left unset at this point, we clear it */
@@ -1256,7 +1257,8 @@ static void __init pcibios_allocate_resources(int pass)
r = &dev->resource[idx];
if (r->parent) /* Already allocated */
continue;
- if (!r->flags || (r->flags & IORESOURCE_UNSET))
+ if (resource_disabled(r) ||
+ (r->flags & IORESOURCE_UNSET))
continue; /* Not assigned at all */
/* We only allocate ROMs on pass 1 just in case they
* have been screwed up by firmware
@@ -1394,7 +1396,7 @@ void pcibios_claim_one_bus(struct pci_bus *bus)
for (i = 0; i < PCI_NUM_RESOURCES; i++) {
struct resource *r = &dev->resource[i];
- if (r->parent || !r->start || !r->flags)
+ if (r->parent || !r->start || resource_disabled(r))
continue;
pr_debug("PCI: Claiming %s: Resource %d: %pR\n",
@@ -1475,7 +1477,7 @@ static void pcibios_setup_phb_resources(struct pci_controller *hose,
/* Hookup PHB IO resource */
res = &hose->io_resource;
- if (!res->flags) {
+ if (resource_disabled(res)) {
pr_info("PCI: I/O resource not set for host"
" bridge %s (domain %d)\n",
hose->dn->full_name, hose->global_number);
@@ -1490,7 +1492,7 @@ static void pcibios_setup_phb_resources(struct pci_controller *hose,
/* Hookup PHB Memory resources */
for (i = 0; i < 3; ++i) {
res = &hose->mem_resources[i];
- if (!res->flags) {
+ if (resource_disabled(res)) {
if (i == 0)
printk(KERN_ERR "PCI: Memory resource 0 not set for "
"host bridge %s (domain %d)\n",
diff --git a/arch/powerpc/platforms/powernv/pci-ioda.c b/arch/powerpc/platforms/powernv/pci-ioda.c
index c5baaf3..e621a68 100644
--- a/arch/powerpc/platforms/powernv/pci-ioda.c
+++ b/arch/powerpc/platforms/powernv/pci-ioda.c
@@ -869,7 +869,7 @@ static int pnv_pci_vf_resource_shift(struct pci_dev *dev, int offset)
num_vfs = pdn->num_vfs;
for (i = 0; i < PCI_SRIOV_NUM_BARS; i++) {
res = &dev->resource[i + PCI_IOV_RESOURCES];
- if (!res->flags || !res->parent)
+ if (resource_disabled(res) || !res->parent)
continue;
/*
@@ -897,7 +897,7 @@ static int pnv_pci_vf_resource_shift(struct pci_dev *dev, int offset)
*/
for (i = 0; i < PCI_SRIOV_NUM_BARS; i++) {
res = &dev->resource[i + PCI_IOV_RESOURCES];
- if (!res->flags || !res->parent)
+ if (resource_disabled(res) || !res->parent)
continue;
size = pci_iov_resource_size(dev, i + PCI_IOV_RESOURCES);
@@ -1260,7 +1260,7 @@ static int pnv_pci_vf_assign_m64(struct pci_dev *pdev, u16 num_vfs)
for (i = 0; i < PCI_SRIOV_NUM_BARS; i++) {
res = &pdev->resource[i + PCI_IOV_RESOURCES];
- if (!res->flags || !res->parent)
+ if (resource_disabled(res) || !res->parent)
continue;
for (j = 0; j < m64_bars; j++) {
@@ -2863,7 +2863,7 @@ static void pnv_pci_ioda_fixup_iov_resources(struct pci_dev *pdev)
for (i = 0; i < PCI_SRIOV_NUM_BARS; i++) {
res = &pdev->resource[i + PCI_IOV_RESOURCES];
- if (!res->flags || res->parent)
+ if (resource_disabled(res) || res->parent)
continue;
if (!pnv_pci_is_mem_pref_64(res->flags)) {
dev_warn(&pdev->dev, "Don't support SR-IOV with"
@@ -2899,7 +2899,7 @@ static void pnv_pci_ioda_fixup_iov_resources(struct pci_dev *pdev)
for (i = 0; i < PCI_SRIOV_NUM_BARS; i++) {
res = &pdev->resource[i + PCI_IOV_RESOURCES];
- if (!res->flags || res->parent)
+ if (resource_disabled(res) || res->parent)
continue;
size = pci_iov_resource_size(pdev, i + PCI_IOV_RESOURCES);
@@ -2951,7 +2951,7 @@ static void pnv_ioda_setup_pe_seg(struct pci_controller *hose,
BUG_ON(!(pe->flags & (PNV_IODA_PE_BUS | PNV_IODA_PE_BUS_ALL)));
pci_bus_for_each_resource(pe->pbus, res, i) {
- if (!res || !res->flags ||
+ if (!res || resource_disabled(res) ||
res->start > res->end)
continue;
diff --git a/arch/s390/pci/pci.c b/arch/s390/pci/pci.c
index 871af75..79e89fb 100644
--- a/arch/s390/pci/pci.c
+++ b/arch/s390/pci/pci.c
@@ -646,7 +646,7 @@ int pcibios_add_device(struct pci_dev *pdev)
for (i = 0; i < PCI_BAR_COUNT; i++) {
res = &pdev->resource[i];
- if (res->parent || !res->flags)
+ if (res->parent || resource_disabled(res))
continue;
pci_claim_resource(pdev, i);
}
diff --git a/arch/sparc/kernel/pci.c b/arch/sparc/kernel/pci.c
index e46e739..fa82e8e8 100644
--- a/arch/sparc/kernel/pci.c
+++ b/arch/sparc/kernel/pci.c
@@ -631,7 +631,7 @@ static void pci_claim_bus_resources(struct pci_bus *bus)
for (i = 0; i < PCI_NUM_RESOURCES; i++) {
struct resource *r = &dev->resource[i];
- if (r->parent || !r->start || !r->flags)
+ if (r->parent || !r->start || resource_disabled(r))
continue;
if (ofpci_verbose)
diff --git a/arch/x86/pci/i386.c b/arch/x86/pci/i386.c
index 2df7723..dcd5beb 100644
--- a/arch/x86/pci/i386.c
+++ b/arch/x86/pci/i386.c
@@ -223,7 +223,7 @@ static void pcibios_allocate_bridge_resources(struct pci_dev *dev)
for (idx = PCI_BRIDGE_RESOURCES; idx < PCI_NUM_RESOURCES; idx++) {
r = &dev->resource[idx];
- if (!r->flags)
+ if (resource_disabled(r))
continue;
if (r->parent) /* Already allocated */
continue;
@@ -352,7 +352,7 @@ static void pcibios_allocate_dev_rom_resource(struct pci_dev *dev)
* addresses.
*/
r = &dev->resource[PCI_ROM_RESOURCE];
- if (!r->flags || !r->start)
+ if (resource_disabled(r) || !r->start)
return;
if (r->parent) /* Already allocated */
return;
diff --git a/arch/xtensa/kernel/pci.c b/arch/xtensa/kernel/pci.c
index b848cc3..f34d061 100644
--- a/arch/xtensa/kernel/pci.c
+++ b/arch/xtensa/kernel/pci.c
@@ -142,7 +142,7 @@ static void __init pci_controller_apertures(struct pci_controller *pci_ctrl,
io_offset = (unsigned long)pci_ctrl->io_space.base;
res = &pci_ctrl->io_resource;
- if (!res->flags) {
+ if (resource_disabled(res)) {
if (io_offset)
printk (KERN_ERR "I/O resource not set for host"
" bridge %d\n", pci_ctrl->index);
@@ -156,7 +156,7 @@ static void __init pci_controller_apertures(struct pci_controller *pci_ctrl,
for (i = 0; i < 3; i++) {
res = &pci_ctrl->mem_resources[i];
- if (!res->flags) {
+ if (resource_disabled(res)) {
if (i > 0)
continue;
printk(KERN_ERR "Memory resource not set for "
diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c
index a2e1b7f..1b8a7f6 100644
--- a/drivers/iommu/intel-iommu.c
+++ b/drivers/iommu/intel-iommu.c
@@ -1825,7 +1825,8 @@ static int dmar_init_reserved_ranges(void)
for (i = 0; i < PCI_NUM_RESOURCES; i++) {
r = &pdev->resource[i];
- if (!r->flags || !(r->flags & IORESOURCE_MEM))
+ if (resource_disabled(r) ||
+ !(r->flags & IORESOURCE_MEM))
continue;
iova = reserve_iova(&reserved_iova_list,
IOVA_PFN(r->start),
diff --git a/drivers/pci/host/pcie-rcar.c b/drivers/pci/host/pcie-rcar.c
index 3509218..716efd5 100644
--- a/drivers/pci/host/pcie-rcar.c
+++ b/drivers/pci/host/pcie-rcar.c
@@ -361,7 +361,7 @@ static int rcar_pcie_setup(struct list_head *resource, struct rcar_pcie *pci)
resource_list_for_each_entry(win, &pci->resources) {
struct resource *res = win->res;
- if (!res->flags)
+ if (resource_disabled(res))
continue;
switch (resource_type(res)) {
diff --git a/drivers/pci/iov.c b/drivers/pci/iov.c
index 2194b44..a275c98 100644
--- a/drivers/pci/iov.c
+++ b/drivers/pci/iov.c
@@ -434,7 +434,7 @@ found:
else
bar64 = __pci_read_base(dev, pci_bar_unknown, res,
pos + PCI_SRIOV_BAR + i * 4);
- if (!res->flags)
+ if (resource_disabled(res))
continue;
if (resource_size(res) & (PAGE_SIZE - 1)) {
rc = -EIO;
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index 6b079f4..52ddc45 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -2308,7 +2308,7 @@ void pci_bus_release_busn_res(struct pci_bus *b)
struct resource *res = &b->busn_res;
int ret;
- if (!res->flags || !res->parent)
+ if (resource_disabled(res) || !res->parent)
return;
ret = release_resource(res);
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index a7cd617..61f87d5 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -348,7 +348,7 @@ static void quirk_bar_fixed(struct pci_dev *dev)
for (i = 0; i < PCI_STD_RESOURCE_END; i++) {
struct resource *r = &dev->resource[i];
- if (!r->start || !r->flags)
+ if (!r->start || resource_disabled(r))
continue;
r->flags |= IORESOURCE_PCI_FIXED;
}
@@ -362,7 +362,7 @@ static void quirk_allocate_fixed(struct pci_dev *dev)
for (i = 0; i < PCI_NUM_RESOURCES; i++) {
struct resource *r = &dev->resource[i];
- if (r->parent ||
+ if (r->parent || resource_disabled(r) ||
!(r->flags & IORESOURCE_PCI_FIXED) ||
!(r->flags & (IORESOURCE_IO | IORESOURCE_MEM)))
continue;
diff --git a/drivers/pci/rom.c b/drivers/pci/rom.c
index 06663d3..cb40e8b 100644
--- a/drivers/pci/rom.c
+++ b/drivers/pci/rom.c
@@ -28,7 +28,7 @@ int pci_enable_rom(struct pci_dev *pdev)
struct pci_bus_region region;
u32 rom_addr;
- if (!res->flags)
+ if (resource_disabled(res))
return -1;
/* Nothing to enable if we're using a shadow copy in RAM */
diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c
index bd74349..c77c204 100644
--- a/drivers/pci/setup-bus.c
+++ b/drivers/pci/setup-bus.c
@@ -222,7 +222,7 @@ static void pdev_assign_resources_prepare(struct pci_dev *dev,
if (r->flags & IORESOURCE_PCI_FIXED)
continue;
- if (!(r->flags) || r->parent)
+ if (resource_disabled(r) || r->parent)
continue;
r_align = __pci_resource_alignment(dev, r, realloc_head);
@@ -318,7 +318,7 @@ static void reassign_resources_sorted(struct list_head *realloc_head,
list_for_each_entry_safe(add_res, tmp, realloc_head, list) {
res = add_res->res;
/* skip resource that has been reset */
- if (!res->flags)
+ if (resource_disabled(res))
goto out;
/* skip this resource if not found in head list */
@@ -2167,7 +2167,7 @@ static void pci_bus_dump_res(struct pci_bus *bus)
int i;
pci_bus_for_each_resource(bus, res, i) {
- if (!res || !res->end || !res->flags)
+ if (!res || !res->end || resource_disabled(res))
continue;
dev_printk(KERN_DEBUG, &bus->dev, "resource %d %pR\n", i, res);
@@ -2250,7 +2250,7 @@ static int iov_resources_unassigned(struct pci_dev *dev, void *data)
struct pci_bus_region region;
/* Not assigned or rejected by kernel? */
- if (!r->flags)
+ if (resource_disabled(r))
continue;
pcibios_resource_to_bus(dev->bus, ®ion, r);
diff --git a/drivers/pci/setup-res.c b/drivers/pci/setup-res.c
index 59271ee..2f901f7 100644
--- a/drivers/pci/setup-res.c
+++ b/drivers/pci/setup-res.c
@@ -45,7 +45,7 @@ void pci_update_resource(struct pci_dev *dev, int resno)
* Ignore resources for unimplemented BARs and unused resource slots
* for 64 bit BARs.
*/
- if (!res->flags)
+ if (resource_disabled(res))
return;
if (res->flags & IORESOURCE_UNSET)
diff --git a/include/linux/ioport.h b/include/linux/ioport.h
index 9053ac9..b388127 100644
--- a/include/linux/ioport.h
+++ b/include/linux/ioport.h
@@ -208,6 +208,10 @@ static inline bool resource_contains(struct resource *r1, struct resource *r2)
return r1->start <= r2->start && r1->end >= r2->end;
}
+static inline bool resource_disabled(struct resource *r)
+{
+ return !r->flags || (r->flags & IORESOURCE_DISABLED);
+}
/* Convenience shorthand with allocation */
#define request_region(start,n,name) __request_region(&ioport_resource, (start), (n), (name), 0)
--
1.8.4.5
[toc] | [prev] | [next] | [standalone]
| From | Yinghai Lu <yinghai@kernel.org> |
|---|---|
| Date | 2016-04-08 02:30 +0200 |
| Subject | [PATCH v11 24/60] PCI: Cleanup res_to_dev_res() printout |
| Message-ID | <rlste-3DX-55@gated-at.bofh.it> |
| In reply to | #1373865 |
Now get_res_add_size() and get_res_add_align() all have same printout
from res_to_dev_res(), and it is confusing.
Move out debug messages printout from res_to_dev_res(),
so later we will reuse res_to_dev_res() in other functions.
-v2: does not print out when add_size or min_align is 0
-v3: change to %#llx according to Bjorn.
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
---
drivers/pci/setup-bus.c | 34 ++++++++++++++++++++--------------
1 file changed, 20 insertions(+), 14 deletions(-)
diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c
index 4674e6b..dd33234 100644
--- a/drivers/pci/setup-bus.c
+++ b/drivers/pci/setup-bus.c
@@ -103,19 +103,9 @@ static struct pci_dev_resource *res_to_dev_res(struct list_head *head,
{
struct pci_dev_resource *dev_res;
- list_for_each_entry(dev_res, head, list) {
- if (dev_res->res == res) {
- int idx = res - &dev_res->dev->resource[0];
-
- dev_printk(KERN_DEBUG, &dev_res->dev->dev,
- "res[%d]=%pR res_to_dev_res add_size %llx min_align %llx\n",
- idx, dev_res->res,
- (unsigned long long)dev_res->add_size,
- (unsigned long long)dev_res->min_align);
-
+ list_for_each_entry(dev_res, head, list)
+ if (dev_res->res == res)
return dev_res;
- }
- }
return NULL;
}
@@ -126,7 +116,15 @@ static resource_size_t get_res_add_size(struct list_head *head,
struct pci_dev_resource *dev_res;
dev_res = res_to_dev_res(head, res);
- return dev_res ? dev_res->add_size : 0;
+ 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;
}
static resource_size_t get_res_add_align(struct list_head *head,
@@ -135,7 +133,15 @@ static resource_size_t get_res_add_align(struct list_head *head,
struct pci_dev_resource *dev_res;
dev_res = res_to_dev_res(head, res);
- return dev_res ? dev_res->min_align : 0;
+ 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;
}
--
1.8.4.5
[toc] | [prev] | [next] | [standalone]
| From | Yinghai Lu <yinghai@kernel.org> |
|---|---|
| Date | 2016-04-08 02:30 +0200 |
| Subject | [PATCH v11 39/60] PCI: Separate out save_resources()/restore_resources() |
| Message-ID | <rlstf-3DX-61@gated-at.bofh.it> |
| In reply to | #1373865 |
We need to save/restore resources several times for alt_size support,
separate the save_resources()/resources() to save some lines later.
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
---
drivers/pci/setup-bus.c | 49 ++++++++++++++++++++++++++++++-------------------
1 file changed, 30 insertions(+), 19 deletions(-)
diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c
index b5529cc..1571245 100644
--- a/drivers/pci/setup-bus.c
+++ b/drivers/pci/setup-bus.c
@@ -435,6 +435,29 @@ static bool pci_need_to_release(unsigned long mask, struct resource *res)
return false; /* should not get here */
}
+static bool save_resources(struct list_head *head,
+ struct list_head *save_head)
+{
+ struct pci_dev_resource *dev_res;
+
+ /* Save original start, end, flags etc at first */
+ list_for_each_entry(dev_res, head, list)
+ if (add_to_list(save_head, dev_res->dev, dev_res->res)) {
+ free_list(save_head);
+ return false;
+ }
+
+ return true;
+}
+
+static void restore_resource(struct pci_dev_resource *save_res,
+ struct resource *res)
+{
+ res->start = save_res->start;
+ res->end = save_res->end;
+ res->flags = save_res->flags;
+}
+
static void __assign_resources_sorted(struct list_head *head,
struct list_head *realloc_head,
struct list_head *fail_head)
@@ -472,13 +495,8 @@ static void __assign_resources_sorted(struct list_head *head,
if (!realloc_head || list_empty(realloc_head))
goto requested_and_reassign;
- /* Save original start, end, flags etc at first */
- list_for_each_entry(dev_res, head, list) {
- if (add_to_list(&save_head, dev_res->dev, dev_res->res)) {
- free_list(&save_head);
- goto requested_and_reassign;
- }
- }
+ if (!save_resources(head, &save_head))
+ goto requested_and_reassign;
/* Update res in head list with add_size in realloc_head list */
list_for_each_entry(dev_res, head, list) {
@@ -547,12 +565,9 @@ 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) {
- res = save_res->res;
- res->start = save_res->start;
- res->end = save_res->end;
- res->flags = save_res->flags;
- }
+ list_for_each_entry(save_res, &save_head, list)
+ restore_resource(save_res, save_res->res);
+
free_list(&save_head);
requested_and_reassign:
@@ -2024,9 +2039,7 @@ again:
list_for_each_entry(fail_res, &fail_head, list) {
struct resource *res = fail_res->res;
- res->start = fail_res->start;
- res->end = fail_res->end;
- res->flags = fail_res->flags;
+ restore_resource(fail_res, res);
if (fail_res->dev->subordinate) {
res->flags = 0;
/* last or third times and later */
@@ -2110,9 +2123,7 @@ again:
list_for_each_entry(fail_res, &fail_head, list) {
struct resource *res = fail_res->res;
- res->start = fail_res->start;
- res->end = fail_res->end;
- res->flags = fail_res->flags;
+ restore_resource(fail_res, res);
if (fail_res->dev->subordinate) {
res->flags = 0;
/* last time */
--
1.8.4.5
[toc] | [prev] | [next] | [standalone]
| From | Yinghai Lu <yinghai@kernel.org> |
|---|---|
| Date | 2016-04-08 02:30 +0200 |
| Subject | [PATCH v11 49/60] PCI: Don't add too much io port for hotplug bridge with old size |
| Message-ID | <rlste-3DX-53@gated-at.bofh.it> |
| In reply to | #1373865 |
Now we add too much for hotplug bridge io port.
For example, when hotplug bridge has two children bridges,
every child bridge will need 0x1000, so size1 will be 0x2000
and size is 0. The min_size for the hotplug bridge is 0x100.
with old version calculate_iosize, we get 0x3000 for final
size as we are using size to compare with min_size at first.
That is not right, we should have 0x2000.
We can check size+size1 with min_size for io port, and just add size1
to size without passing extra size1 into calculate_iosize().
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
---
drivers/pci/setup-bus.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c
index c202854..930dcbd 100644
--- a/drivers/pci/setup-bus.c
+++ b/drivers/pci/setup-bus.c
@@ -1105,7 +1105,6 @@ static struct resource *find_free_bus_resource(struct pci_bus *bus,
static resource_size_t calculate_iosize(resource_size_t size,
resource_size_t min_size,
- resource_size_t size1,
resource_size_t old_size,
resource_size_t align)
{
@@ -1113,7 +1112,7 @@ static resource_size_t calculate_iosize(resource_size_t size,
size = min_size;
if (old_size == 1)
old_size = 0;
- size = ALIGN(size + size1, align);
+ size = ALIGN(size, align);
if (size < old_size)
size = old_size;
return size;
@@ -1244,14 +1243,15 @@ static void pbus_size_io(struct pci_bus *bus, resource_size_t min_size,
}
size = size_aligned_for_isa(size);
- size0 = calculate_iosize(size, min_size, size1,
+ size += size1;
+ size0 = calculate_iosize(size, min_size,
resource_size(b_res), min_align);
sum_add_size = size_aligned_for_isa(sum_add_size);
sum_add_size += sum_add_size1;
if (sum_add_size < min_sum_size)
sum_add_size = min_sum_size;
size1 = !realloc_head ? size0 :
- calculate_iosize(sum_add_size, min_size, 0,
+ calculate_iosize(sum_add_size, min_size,
resource_size(b_res), min_align);
if (!size0 && !size1) {
if (b_res->start || b_res->end)
--
1.8.4.5
[toc] | [prev] | [next] | [standalone]
| From | Yinghai Lu <yinghai@kernel.org> |
|---|---|
| Date | 2016-04-08 02:30 +0200 |
| Subject | [PATCH v11 54/60] resources: Make allocate_resource() return best fit resource |
| Message-ID | <rlste-3DX-59@gated-at.bofh.it> |
| In reply to | #1373865 |
Current code just allocate from first avail window.
We can find all suitable empty slots and pick one with smallest size, so
we could save the big slot for needed ones later when we have several pci
bridges under parent bridge and some bridges get assigned from bios and we
need to assign others in kernel.
For examples: we have window
[0xc0000000, 0xd0000000), and [0xe0000000,0xe1000000)
and we try allocate 0x200000 size resource.
in this patch will reserve [0xc0000000, 0xd0000000) and
[0xe0000000,0xe1000000) at first, then pick [0xe0000000,0xe1000000)
to allocate 0x200000 size.
-v2: updated after __allocate_resource change, and add field in constraint
instead of passing it directly.
-v3: Use best fit instead of just fit according to Bjorn.
-v4: fix the warning found by Huang Ying.
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
---
kernel/resource.c | 76 ++++++++++++++++++++++++++++++++++++++++++++-----------
1 file changed, 61 insertions(+), 15 deletions(-)
diff --git a/kernel/resource.c b/kernel/resource.c
index c5dbe02..d91ebc5 100644
--- a/kernel/resource.c
+++ b/kernel/resource.c
@@ -611,7 +611,7 @@ static void resource_clip(struct resource *res, resource_size_t min,
* alignment constraints
*/
static int __find_resource(struct resource *root, struct resource *old,
- struct resource *new,
+ struct resource *new, struct resource *availx,
resource_size_t size,
struct resource_constraint *constraint)
{
@@ -651,6 +651,11 @@ static int __find_resource(struct resource *root, struct resource *old,
if (resource_contains(&avail, &alloc)) {
new->start = alloc.start;
new->end = alloc.end;
+ if (availx) {
+ availx->start = avail.start;
+ availx->end = avail.end;
+ availx->flags = avail.flags;
+ }
return 0;
}
}
@@ -665,16 +670,6 @@ next: if (!this || this->end == root->end)
return -EBUSY;
}
-/*
- * Find empty slot in the resource tree given range and alignment.
- */
-static int find_resource(struct resource *root, struct resource *new,
- resource_size_t size,
- struct resource_constraint *constraint)
-{
- return __find_resource(root, NULL, new, size, constraint);
-}
-
/**
* reallocate_resource - allocate a slot in the resource tree given range & alignment.
* The resource will be relocated if the new size cannot be reallocated in the
@@ -694,8 +689,8 @@ static int reallocate_resource(struct resource *root, struct resource *old,
struct resource *conflict;
write_lock(&resource_lock);
-
- if ((err = __find_resource(root, old, &new, newsize, constraint)))
+ err = __find_resource(root, old, &new, NULL, newsize, constraint);
+ if (err)
goto out;
if (resource_contains(&new, old)) {
@@ -723,10 +718,16 @@ out:
return err;
}
+struct good_resource {
+ struct list_head list;
+ struct resource avail;
+ struct resource new;
+};
/**
* allocate_resource - allocate empty slot in the resource tree given range & alignment.
- * The resource will be reallocated with a new size if it was already allocated
+ * The resource will be reallocated with a new size if it was already
+ * allocated
* @root: root resource descriptor
* @new: resource descriptor desired by caller
* @size: requested resource region size
@@ -747,6 +748,9 @@ int allocate_resource(struct resource *root, struct resource *new,
{
int err;
struct resource_constraint constraint;
+ LIST_HEAD(head);
+ struct good_resource *good, *tmp;
+ resource_size_t avail_size = (resource_size_t)-1ULL;
if (!alignf)
alignf = simple_align_resource;
@@ -763,11 +767,53 @@ int allocate_resource(struct resource *root, struct resource *new,
return reallocate_resource(root, new, size, &constraint);
}
+ /* find all suitable ones and add to the list */
+ for (;;) {
+ good = kzalloc(sizeof(*good), GFP_KERNEL);
+ if (!good) {
+ err = -ENOMEM;
+ break;
+ }
+
+ good->new.start = new->start;
+ good->new.end = new->end;
+ good->new.flags = new->flags;
+
+ write_lock(&resource_lock);
+ err = __find_resource(root, NULL, &good->new, &good->avail,
+ size, &constraint);
+ if (err || __request_resource(root, &good->avail)) {
+ err = -EBUSY;
+ kfree(good);
+ write_unlock(&resource_lock);
+ break;
+ }
+ write_unlock(&resource_lock);
+
+ list_add(&good->list, &head);
+ }
+
+ /* pick up the smallest one */
write_lock(&resource_lock);
- err = find_resource(root, new, size, &constraint);
+ list_for_each_entry(good, &head, list) {
+ if (resource_size(&good->avail) < avail_size) {
+ avail_size = resource_size(&good->avail);
+ new->start = good->new.start;
+ new->end = good->new.end;
+ err = 0;
+ }
+ __release_resource(&good->avail, false);
+ }
if (err >= 0 && __request_resource(root, new))
err = -EBUSY;
write_unlock(&resource_lock);
+
+ /* delete the list */
+ list_for_each_entry_safe(good, tmp, &head, list) {
+ list_del(&good->list);
+ kfree(good);
+ }
+
return err;
}
--
1.8.4.5
[toc] | [prev] | [next] | [standalone]
| From | Yinghai Lu <yinghai@kernel.org> |
|---|---|
| Date | 2016-04-08 02:30 +0200 |
| Subject | [PATCH v11 46/60] PCI: Fix size calculation with old_size on rescan path |
| Message-ID | <rlstf-3DX-65@gated-at.bofh.it> |
| In reply to | #1373865 |
On booting path, we don't pass realloc at first, and treat all optional just as required, in some case we can have smaller size/align with optional than required only. 04:00.0 has children bridges: 05:03.0, 05:04.0 pref layout after booting path like followings: pci 0000:04:00.0: BAR 9: assigned [mem 0x84000000-0x9fffffff 64bit pref] pci 0000:05:04.0: BAR 9: assigned [mem 0x88000000-0x9fffffff 64bit pref] pci 0000:05:03.0: BAR 9: assigned [mem 0x84000000-0x841fffff 64bit pref] pci 0000:05:03.0: PCI bridge to [bus 08-0f] pci 0000:05:03.0: bridge window [mem 0x84000000-0x841fffff 64bit pref] pci 0000:05:04.0: PCI bridge to [bus 10] pci 0000:05:04.0: bridge window [mem 0x88000000-0x9fffffff 64bit pref] pci 0000:04:00.0: PCI bridge to [bus 05-10] pci 0000:04:00.0: bridge window [mem 0x84000000-0x9fffffff 64bit pref] so the old size in rescan for 04:00.0 would be 0x1c000000, and align is 0x4000000 during remove and rescan: pci 0000:05:03.0: bridge window [mem 0x00000000-0xffffffffffffffff 64bit pref] to [bus 08-0f] add_size 200000 add_align 100000 alt_size 0 alt_align 0 must_size 0 must_align 0 pci 0000:05:03.0: bridge window [mem 0x00000000-0xffffffffffffffff] to [bus 08-0f] add_size 200000 add_align 100000 alt_size 0 alt_align 0 must_size 0 must_align 0 pci 0000:05:04.0: bridge window [mem 0x08000000-0x1fffffff 64bit pref] to [bus 10] add_size 0 add_align 0 alt_size 10100000 alt_align 10000000 must_size 18000000 must_align 8000000 pci 0000:05:03.0: BAR 9: [mem 0x00000000-0xffffffffffffffff 64bit pref] get_res_add_size add_size 200000 pci 0000:05:03.0: BAR 9: [mem 0x00000000-0xffffffffffffffff 64bit pref] get_res_add_align min_align 100000 pci 0000:04:00.0: bridge window [mem 0x08000000-0x27ffffff 64bit pref] to [bus 05-10] add_size 0 add_align 0 alt_size 10100000 alt_align 10000000 must_size 20000000 must_align 8000000 align old size 0x1c000000 to 0x2000000 as size0, 0x1c000000 as size1. so for 04:00.0 will have big must and no optional size anymore. So don't align old size, then we will have same size0 and size1, and use smaller add_align as must align. After the patch, rescan works properly. Signed-off-by: Yinghai Lu <yinghai@kernel.org> --- drivers/pci/setup-bus.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c index 88557b9..d2712d8 100644 --- a/drivers/pci/setup-bus.c +++ b/drivers/pci/setup-bus.c @@ -1133,9 +1133,9 @@ static resource_size_t calculate_memsize(resource_size_t size, size = min_size; if (old_size == 1) old_size = 0; + size = ALIGN(size, align); if (size < old_size) size = old_size; - size = ALIGN(size, align); return size; } @@ -1595,6 +1595,17 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask, b_res->flags = 0; return 0; } + + /* + * It happens when boot path is not passing realloc + * and later rescan is passing realloc. + * The old value from boot path is bigger, and calculate_size will + * use old value as size0 and size1, and also have + * chance optional align is smaller than must only align. + */ + if(size0 == size1 && min_align > min_add_align) + min_align = min_add_align; + b_res->start = min_align; b_res->end = size0 + min_align - 1; b_res->flags |= IORESOURCE_STARTALIGN; -- 1.8.4.5
[toc] | [prev] | [next] | [standalone]
| From | Yinghai Lu <yinghai@kernel.org> |
|---|---|
| Date | 2016-04-08 02:30 +0200 |
| Subject | [PATCH v11 48/60] PCI: Move ISA io port align out of calculate_iosize() |
| Message-ID | <rlstf-3DX-67@gated-at.bofh.it> |
| In reply to | #1373865 |
We need to move ISA io port align out of calculate_iosize(),
so we could unify calculate_iosize and calculate_memsize later.
That extra aligning or offset is to work around ISA devices:
When one bridge have several children devices, and every device
has several io port resources and resource size < 0x400.
We need to check size, and add extra size to make sure bit8/9
to be zero.
Also need to apply same checking for optional size path.
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
---
drivers/pci/setup-bus.c | 39 +++++++++++++++++++++++++++------------
1 file changed, 27 insertions(+), 12 deletions(-)
diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c
index 11a4c1d..c202854 100644
--- a/drivers/pci/setup-bus.c
+++ b/drivers/pci/setup-bus.c
@@ -1113,11 +1113,6 @@ static resource_size_t calculate_iosize(resource_size_t size,
size = min_size;
if (old_size == 1)
old_size = 0;
- /* To be fixed in 2.5: we should have sort of HAVE_ISA
- flag in the struct pci_bus. */
-#if defined(CONFIG_ISA) || defined(CONFIG_EISA)
- size = (size & 0xff) + ((size & ~0xffUL) << 2);
-#endif
size = ALIGN(size + size1, align);
if (size < old_size)
size = old_size;
@@ -1171,6 +1166,18 @@ static resource_size_t window_alignment(struct pci_bus *bus,
return max(align, arch_align);
}
+static resource_size_t size_aligned_for_isa(resource_size_t size)
+{
+ /*
+ * To be fixed in 2.5: we should have sort of HAVE_ISA
+ * flag in the struct pci_bus.
+ */
+#if defined(CONFIG_ISA) || defined(CONFIG_EISA)
+ size = (size & 0xff) + ((size & ~0xffUL) << 2);
+#endif
+ return size;
+}
+
/**
* pbus_size_io() - size the io window of a given bus
*
@@ -1188,11 +1195,10 @@ static void pbus_size_io(struct pci_bus *bus, resource_size_t min_size,
{
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;
- resource_size_t children_add_size = 0;
+ resource_size_t sum_add_size = 0, sum_add_size1 = 0;
resource_size_t min_align, align;
if (!b_res)
@@ -1209,7 +1215,7 @@ static void pbus_size_io(struct pci_bus *bus, resource_size_t min_size,
for (i = 0; i < PCI_NUM_RESOURCES; i++) {
struct resource *r = &dev->resource[i];
- unsigned long r_size;
+ unsigned long r_size, r_add_size;
if (r->parent || !(r->flags & IORESOURCE_IO))
continue;
@@ -1225,18 +1231,27 @@ static void pbus_size_io(struct pci_bus *bus, resource_size_t min_size,
if (align > min_align)
min_align = align;
- if (realloc_head)
- children_add_size += get_res_add_size(realloc_head, r);
+ if (realloc_head) {
+ r_add_size = get_res_add_size(realloc_head, r);
+ r_add_size += r_size;
+ if (r_add_size < 0x400)
+ /* Might be re-aligned for ISA */
+ sum_add_size += r_add_size;
+ else
+ sum_add_size1 += r_add_size;
+ }
}
}
+ size = size_aligned_for_isa(size);
size0 = calculate_iosize(size, min_size, size1,
resource_size(b_res), min_align);
- sum_add_size = children_add_size + size + size1;
+ sum_add_size = size_aligned_for_isa(sum_add_size);
+ sum_add_size += sum_add_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,
+ calculate_iosize(sum_add_size, min_size, 0,
resource_size(b_res), min_align);
if (!size0 && !size1) {
if (b_res->start || b_res->end)
--
1.8.4.5
[toc] | [prev] | [next] | [standalone]
Page 1 of 3 [1] 2 3 Next page →
Back to top | Article view | linux.kernel
csiph-web