On Mon, Jan 16, 2012 at 9:13 AM, Yinghai Lu <yinghai@xxxxxxxxxx> wrote: > that will make case 2: do not go extra level. > > or we can do: > We try to auto detect if we need to enable realloc. > (something like sriov is enabled, but some SRIOV registers are not assigned) > (or card bus are there etc) > > and > pci=realloc become > pci=realloc=off and pci=realloc=on > so user can forcely turn it or off. ok, updated one patch and add one new patch to enable pci realloc only when sriov is not assigned. please check attached two patches. updated for-pci2 branch git://git.kernel.org/pub/scm/linux/kernel/git/yinghai/linux-yinghai.git for-pci2 Can you please check that branch to see if it works on your setups ? Thanks Yinghai
Subject: [PATCH 8/8] PCI: Make pci bridge reallocating enabled/disabled Let the user could enable and disable with pci=realloc=on or pci=realloc=off Also 1. move variable and functions near the place they are used. 2. change macro to function 3. change related functions and variable to static and _init 4. update parameter description accordingly. Signed-off-by: Yinghai Lu <yinghai@xxxxxxxxxx> --- Documentation/kernel-parameters.txt | 7 +++++-- drivers/pci/pci.c | 4 ++-- drivers/pci/pci.h | 2 +- drivers/pci/setup-bus.c | 25 ++++++++++++++++++------- 4 files changed, 26 insertions(+), 12 deletions(-) Index: linux-2.6/drivers/pci/setup-bus.c =================================================================== --- linux-2.6.orig/drivers/pci/setup-bus.c +++ linux-2.6/drivers/pci/setup-bus.c @@ -48,13 +48,6 @@ static void free_list(struct list_head * } } -int pci_realloc_enable = 0; -#define pci_realloc_enabled() pci_realloc_enable -void pci_realloc(void) -{ - pci_realloc_enable = 1; -} - /** * add_to_list() - add a new resource tracker to the list * @head: Head of the list @@ -1259,6 +1252,24 @@ static int __init pci_get_max_depth(void return depth; } +/* + * -1: undefined, will auto detect later + * 0: disabled by user + * 1: enabled by user + * 2: enabled by auto detect + */ +static int pci_realloc_enable __initdata = -1; +void __init pci_realloc_get_opt(char *str) +{ + if (strncmp(str, "off", 3)) + pci_realloc_enable = 0; + else if (strncmp(str, "on", 2)) + pci_realloc_enable = 1; +} +static bool __init pci_realloc_enabled(void) +{ + return pci_realloc_enable > 0; +} /* * first try will not touch pci bridge res Index: linux-2.6/drivers/pci/pci.c =================================================================== --- linux-2.6.orig/drivers/pci/pci.c +++ linux-2.6/drivers/pci/pci.c @@ -3714,8 +3714,8 @@ static int __init pci_setup(char *str) pci_no_msi(); } else if (!strcmp(str, "noaer")) { pci_no_aer(); - } else if (!strncmp(str, "realloc", 7)) { - pci_realloc(); + } else if (!strncmp(str, "realloc=", 8)) { + pci_realloc_get_opt(str + 8); } else if (!strcmp(str, "nodomains")) { pci_no_domains(); } else if (!strncmp(str, "cbiosize=", 9)) { Index: linux-2.6/Documentation/kernel-parameters.txt =================================================================== --- linux-2.6.orig/Documentation/kernel-parameters.txt +++ linux-2.6/Documentation/kernel-parameters.txt @@ -2104,8 +2104,11 @@ bytes respectively. Such letter suffixes the default. off: Turn ECRC off on: Turn ECRC on. - realloc reallocate PCI resources if allocations done by BIOS - are erroneous. + realloc= Enable/disable reallocating PCI bridge resources + if allocations done by BIOS are too small to fit + resources required by children devices. + off: Turn realloc off + on: Turn realloc on pcie_aspm= [PCIE] Forcibly enable or disable PCIe Active State Power Management. Index: linux-2.6/drivers/pci/pci.h =================================================================== --- linux-2.6.orig/drivers/pci/pci.h +++ linux-2.6/drivers/pci/pci.h @@ -148,7 +148,7 @@ static inline void pci_no_msi(void) { } static inline void pci_msi_init_pci_dev(struct pci_dev *dev) { } #endif -extern void pci_realloc(void); +void pci_realloc_get_opt(char *); static inline int pci_no_d1d2(struct pci_dev *dev) {
Subject: [PATCH] PCI: only enable pci realloc when SRIOV bar is not assigned If bios does not assign those BAR or wrong address, then kernel will try to do pci realloc. in that case, user still can use pci=realloc=off to override it. Signed-off-by: Yinghai Lu <yinghai@xxxxxxxxxx> --- drivers/pci/setup-bus.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) Index: linux-2.6/drivers/pci/setup-bus.c =================================================================== --- linux-2.6.orig/drivers/pci/setup-bus.c +++ linux-2.6/drivers/pci/setup-bus.c @@ -1271,6 +1271,31 @@ static bool __init pci_realloc_enabled(v return pci_realloc_enable > 0; } +static void __init pci_realloc_detect(void) +{ + struct pci_dev *dev = NULL; + + if (pci_realloc_enable != -1) + return; + +#ifdef CONFIG_PCI_IOV + for_each_pci_dev(dev) { + int i; + + for (i = PCI_IOV_RESOURCES; i <= PCI_IOV_RESOURCE_END; i++) { + struct resource *r = &dev->resource[i]; + + /* Not assigned, or rejected by kernel */ + if (r->flags && !r->start) { + pci_realloc_enable = 2; + + return; + } + } + } +#endif +} + /* * first try will not touch pci bridge res * second and later try will clear small leaf bridge res @@ -1292,6 +1317,7 @@ pci_assign_unassigned_resources(void) int pci_try_num = 1; /* don't realloc if asked to do so */ + pci_realloc_detect(); if (pci_realloc_enabled()) { int max_depth = pci_get_max_depth();