PCI : bridge resource reallocation patchset -- followup
Subsystems (2)
cover PCI : bridge resource reallocation patchset -- followup
1663c18: PCI: only enable pci realloc when SRIOV bar is not assigned
fee9a73: PCI: print out suggestion about using pci=realloc 29266b2: PCI: Make pci bridge reallocating enabled/disabled 9d5e126: PCI: Retry on type IORESOURCE_IO allocation. 837e4eb: PCI: Skip reset cardbus assigned resource during pci bus rescan
fcd3462: PCI: Fix cardbus bridge resources as optional size handling
da81f2e: PCI: Disable cardbus bridge MEM1 pref CTL
are left over after Jesse pickup more of them.
it will try to auto detect if need to use pci=realloc, and print out suggestion.
including fixing some pci carbus handling.
could get from
git://git.kernel.org/pub/scm/linux/kernel/git/yinghai/linux-yinghai.git for-pci4
-v3: Resend according to Jesse. Update ack and etc.
last one add CONFIG_PCI_REALLOC_ENABLE_DETECT according to Jesse.
Thanks
Yinghai
Documentation/kernel-parameters.txt | 9 ++- drivers/pci/Kconfig | 10 ++ drivers/pci/pci.c | 4 +- drivers/pci/pci.h | 2 +- drivers/pci/setup-bus.c | 159 +++++++++++++++++++++++++---------- 5 files changed, 136 insertions(+), 48 deletions(-)
PATCH 1/7 PCI: Disable cardbus bridge MEM1 pref CTL
Some BIOS enable both pref for MEM0 and MEM1.
but we assume MEM1 is non-pref...
Discussion could be found at:
https://lkml.org/lkml/2012/1/12/1 https://bugzilla.kernel.org/show_bug.cgi?id=41622#c23
--- drivers/pci/setup-bus.c | 8 ++++++++ 1 files changed, 8 insertions(+), 0 deletions(-)
drivers/pci/setup-bus.c +8 -0
@@ -914,6 +914,14 @@ static void pci_bus_size_cardbus(struct pci_bus *bus,if (realloc_head)add_to_list (realloc_head, bridge, b_res+1 , pci_cardbus_io_size,0 /* dont care */ ); +/* MEM1 must not be pref mmio */ +pci_read_config_word (bridge,PCI_CB_BRIDGE_CONTROL , &ctrl); +if (ctrl &PCI_CB_BRIDGE_CTL_PREFETCH_MEM1 ) { + ctrl &= ~PCI_CB_BRIDGE_CTL_PREFETCH_MEM1 ; +pci_write_config_word (bridge,PCI_CB_BRIDGE_CONTROL , ctrl); +pci_read_config_word (bridge,PCI_CB_BRIDGE_CONTROL , &ctrl); + } +/* * Check whether prefetchable memory is supported * by this bridge.
Signature · 1 line
1.7.7
PATCH 2/7 PCI: Fix cardbus bridge resources as optional size handling
In reply to Yinghai LuWe should not set the requested size to -2.
that will confuse the resource list sorting with align when SIZEALIGN is used.
Change to STARTALIGN and pass align from start.
We are safe to do that just as we do that regular pci bridge.
In the long run, we should just treat cardbus like regular pci bridge.
Also fix when realloc is not passed, should keep the requested size.
--- drivers/pci/setup-bus.c | 63 ++++++++++++++++++++++++++-------------------- 1 files changed, 36 insertions(+), 27 deletions(-)
drivers/pci/setup-bus.c +36 -27
@@ -898,21 +898,30 @@ static void pci_bus_size_cardbus(struct pci_bus *bus, {struct pci_dev *bridge = bus->self;struct resource *b_res = &bridge->resource[PCI_BRIDGE_RESOURCES ]; +resource_size_t b_res_3_size = pci_cardbus_mem_size *2 ;u16 ctrl;/* * Reserve some resources for CardBus. We reserve * a fixed amount of bus space for CardBus bridges. */ - b_res[0 ].start =0 ; - b_res[0 ].flags |=IORESOURCE_IO |IORESOURCE_SIZEALIGN ; -if (realloc_head) -add_to_list (realloc_head, bridge, b_res, pci_cardbus_io_size,0 /* dont care */ ); + b_res[0 ].start = pci_cardbus_io_size; + b_res[0 ].end = b_res[0 ].start + pci_cardbus_io_size -1 ; + b_res[0 ].flags |=IORESOURCE_IO |IORESOURCE_STARTALIGN ; +if (realloc_head) { + b_res[0 ].end -= pci_cardbus_io_size; +add_to_list (realloc_head, bridge, b_res, pci_cardbus_io_size, + pci_cardbus_io_size); + } - b_res[1 ].start =0 ; - b_res[1 ].flags |=IORESOURCE_IO |IORESOURCE_SIZEALIGN ; -if (realloc_head) -add_to_list (realloc_head, bridge, b_res+1 , pci_cardbus_io_size,0 /* dont care */ ); + b_res[1 ].start = pci_cardbus_io_size; + b_res[1 ].end = b_res[1 ].start + pci_cardbus_io_size -1 ; + b_res[1 ].flags |=IORESOURCE_IO |IORESOURCE_STARTALIGN ; +if (realloc_head) { + b_res[1 ].end -= pci_cardbus_io_size; +add_to_list (realloc_head, bridge, b_res+1 , pci_cardbus_io_size, + pci_cardbus_io_size); + }/* MEM1 must not be pref mmio */ pci_read_config_word (bridge,PCI_CB_BRIDGE_CONTROL , &ctrl);
@@ -939,28 +948,28 @@ static void pci_bus_size_cardbus(struct pci_bus *bus,* twice the size. */ if (ctrl &PCI_CB_BRIDGE_CTL_PREFETCH_MEM0 ) { - b_res[2 ].start =0 ; - b_res[2 ].flags |=IORESOURCE_MEM |IORESOURCE_PREFETCH |IORESOURCE_SIZEALIGN ; -if (realloc_head) -add_to_list (realloc_head, bridge, b_res+2 , pci_cardbus_mem_size,0 /* dont care */ ); + b_res[2 ].start = pci_cardbus_mem_size; + b_res[2 ].end = b_res[2 ].start + pci_cardbus_mem_size -1 ; + b_res[2 ].flags |=IORESOURCE_MEM |IORESOURCE_PREFETCH | +IORESOURCE_STARTALIGN ; +if (realloc_head) { + b_res[2 ].end -= pci_cardbus_mem_size; +add_to_list (realloc_head, bridge, b_res+2 , + pci_cardbus_mem_size, pci_cardbus_mem_size); + } - b_res[3 ].start =0 ; - b_res[3 ].flags |=IORESOURCE_MEM |IORESOURCE_SIZEALIGN ; -if (realloc_head) -add_to_list (realloc_head, bridge, b_res+3 , pci_cardbus_mem_size,0 /* dont care */ ); - }else { - b_res[3 ].start =0 ; - b_res[3 ].flags |=IORESOURCE_MEM |IORESOURCE_SIZEALIGN ; -if (realloc_head) -add_to_list (realloc_head, bridge, b_res+3 , pci_cardbus_mem_size *2 ,0 /* dont care */ ); +/* reduce that to half */ + b_res_3_size = pci_cardbus_mem_size; } -/* set the size of the resource to zero, so that the resource does not -* get assigned during required-resource allocation cycle but gets assigned -* during the optional-resource allocation cycle. -*/ - b_res[0 ].start = b_res[1 ].start = b_res[2 ].start = b_res[3 ].start =1 ; - b_res[0 ].end = b_res[1 ].end = b_res[2 ].end = b_res[3 ].end =0 ; + b_res[3 ].start = pci_cardbus_mem_size; + b_res[3 ].end = b_res[3 ].start + b_res_3_size -1 ; + b_res[3 ].flags |=IORESOURCE_MEM |IORESOURCE_STARTALIGN ; +if (realloc_head) { + b_res[3 ].end -= b_res_3_size; +add_to_list (realloc_head, bridge, b_res+3 , b_res_3_size, + pci_cardbus_mem_size); + } } void __ref __pci_bus_size_bridges(struct pci_bus *bus,
Signature · 1 line
1.7.7
PATCH 3/7 PCI: Skip reset cardbus assigned resource during pci bus rescan
In reply to Yinghai Luotherwise when rescan is used for cardbus, assigned resource will get cleared.
--- drivers/pci/setup-bus.c | 14 ++++++++++++++ 1 files changed, 14 insertions(+), 0 deletions(-)
drivers/pci/setup-bus.c +14 -0
@@ -901,6 +901,8 @@ static void pci_bus_size_cardbus(struct pci_bus *bus,resource_size_t b_res_3_size = pci_cardbus_mem_size *2 ;u16 ctrl; +if (b_res[0 ].parent) + goto handle_b_res_1;/* * Reserve some resources for CardBus. We reserve * a fixed amount of bus space for CardBus bridges.
@@ -914,6 +916,9 @@ static void pci_bus_size_cardbus(struct pci_bus *bus, pci_cardbus_io_size); } +handle_b_res_1: +if (b_res[1 ].parent) + goto handle_b_res_2; b_res[1 ].start = pci_cardbus_io_size; b_res[1 ].end = b_res[1 ].start + pci_cardbus_io_size -1 ; b_res[1 ].flags |=IORESOURCE_IO |IORESOURCE_STARTALIGN ;
@@ -923,6 +928,7 @@ static void pci_bus_size_cardbus(struct pci_bus *bus, pci_cardbus_io_size); } +handle_b_res_2:/* MEM1 must not be pref mmio */ pci_read_config_word (bridge,PCI_CB_BRIDGE_CONTROL , &ctrl);if (ctrl &PCI_CB_BRIDGE_CTL_PREFETCH_MEM1 ) {
@@ -942,6 +948,8 @@ static void pci_bus_size_cardbus(struct pci_bus *bus,pci_read_config_word (bridge,PCI_CB_BRIDGE_CONTROL , &ctrl); } +if (b_res[2 ].parent) + goto handle_b_res_3;/* * If we have prefetchable memory support, allocate * two regions. Otherwise, allocate one region of
@@ -962,6 +970,9 @@ static void pci_bus_size_cardbus(struct pci_bus *bus, b_res_3_size = pci_cardbus_mem_size; } +handle_b_res_3: +if (b_res[3 ].parent) + goto handle_done; b_res[3 ].start = pci_cardbus_mem_size; b_res[3 ].end = b_res[3 ].start + b_res_3_size -1 ; b_res[3 ].flags |=IORESOURCE_MEM |IORESOURCE_STARTALIGN ;
@@ -970,6 +981,9 @@ static void pci_bus_size_cardbus(struct pci_bus *bus,add_to_list (realloc_head, bridge, b_res+3 , b_res_3_size, pci_cardbus_mem_size); } + +handle_done: + ; } void __ref __pci_bus_size_bridges(struct pci_bus *bus,
Signature · 1 line
1.7.7
Re: [PATCH 3/7] PCI: Skip reset cardbus assigned resource during pci bus rescan
Quoted 5 lines · On Fri, 10 Feb 2012 15:33:48 -0800 Yinghai Lu <[email protected]> wrote:
otherwise when rescan is used for cardbus, assigned resource will get cleared.
Signed-off-by Yinghai Lu <[email protected]>Tested-by Dominik Brodowski <[email protected]>
Applied 1-3, thanks guys.
Signature · 1 line
Jesse Barnes, Intel Open Source Technology Center
PATCH 4/7 PCI: Retry on type IORESOURCE_IO allocation.
In reply to Yinghai LuDuring reenabling pci reallocating for pci bridge by clean the small size in bridge and assign with requested + optional size for first several try, Ram mention could have problem with one case
https://bugzilla.kernel.org/show_bug.cgi?id=15960
After checking the booting log in
https://lkml.org/lkml/2010/4/19/44 [regression, bisected] Xonar DX invalid PCI I/O range since 977d17bb174
We should not stop too early for io ports.
Apr 19 10:19:38 [kernel] pci 0000:04:00.0: BAR 7: can't assign io (size 0x4000) Apr 19 10:19:38 [kernel] pci 0000:05:01.0: BAR 8: assigned [mem 0x80400000-0x805fffff] Apr 19 10:19:38 [kernel] pci 0000:05:01.0: BAR 7: can't assign io (size 0x2000) Apr 19 10:19:38 [kernel] pci 0000:05:02.0: BAR 7: can't assign io (size 0x1000) Apr 19 10:19:38 [kernel] pci 0000:05:03.0: BAR 7: can't assign io (size 0x1000) Apr 19 10:19:38 [kernel] pci 0000:08:00.0: BAR 7: can't assign io (size 0x1000) Apr 19 10:19:38 [kernel] pci 0000:09:04.0: BAR 0: can't assign io (size 0x100)
and clear 00:1c.0 to retry again.
The patch remove the IORESOUCE_IO checking, and try one more time. and we will have chance to get allocation for 00:1c.0 io port range because from 0x4000 to 0x8000 could be used.
--- drivers/pci/setup-bus.c | 12 +----------- 1 files changed, 1 insertions(+), 11 deletions(-)
drivers/pci/setup-bus.c +1 -11
@@ -1292,7 +1292,6 @@ pci_assign_unassigned_resources(void)struct pci_dev_resource *fail_res;unsigned long type_mask =IORESOURCE_IO |IORESOURCE_MEM |IORESOURCE_PREFETCH ; -unsigned long failed_type;int pci_try_num =1 ;/* don't realloc if asked to do so */
@@ -1327,16 +1326,7 @@ again:if (list_empty (&fail_head)) goto enable_and_dump; - failed_type =0 ; -list_for_each_entry (fail_res, &fail_head, list) - failed_type |= fail_res->flags; - -/* -* io port are tight, don't try extra -* or if reach the limit, don't want to try more -*/ - failed_type &= type_mask; -if ((failed_type ==IORESOURCE_IO ) || (tried_times >= pci_try_num)) { +if (tried_times >= pci_try_num) {free_list (&fail_head); goto enable_and_dump; }
Signature · 1 line
1.7.7
Re: [PATCH 4/7] PCI: Retry on type IORESOURCE_IO allocation.
Quoted 17 lines · On Fri, 10 Feb 2012 15:33:49 -0800 Yinghai Lu <[email protected]> wrote:
During reenabling pci reallocating for pci bridge by clean the small size in bridge and assign with requested + optional size for first several try, Ram mention could have problem with one case
https://bugzilla.kernel.org/show_bug.cgi?id=15960After checking the booting log in
https://lkml.org/lkml/2010/4/19/44 [regression, bisected] Xonar DX invalid PCI I/O range since 977d17bb174We should not stop too early for io ports.
Apr 19 10:19:38 [kernel] pci 0000:04:00.0: BAR 7: can't assign io (size 0x4000) Apr 19 10:19:38 [kernel] pci 0000:05:01.0: BAR 8: assigned [mem 0x80400000-0x805fffff] Apr 19 10:19:38 [kernel] pci 0000:05:01.0: BAR 7: can't assign io (size 0x2000) Apr 19 10:19:38 [kernel] pci 0000:05:02.0: BAR 7: can't assign io (size 0x1000) Apr 19 10:19:38 [kernel] pci 0000:05:03.0: BAR 7: can't assign io (size 0x1000) Apr 19 10:19:38 [kernel] pci 0000:08:00.0: BAR 7: can't assign io (size 0x1000) Apr 19 10:19:38 [kernel] pci 0000:09:04.0: BAR 0: can't assign io (size 0x100)
Quoted 5 lines
and clear 00:1c.0 to retry again.
The patch remove the
IORESOUCE_IOchecking, and try one more time. and we will have chance to get allocation for 00:1c.0 io port range because from0x4000to0x8000could be used.
This one no longer applies, can you send an update against my linux-next branch later today or tomorrow when I've pushed?
I'm still a little worried about the automatic re-alloction stuff, but since it's under a new config option it ought to be ok. See my other mails for comments there.
Signature · 1 line
Jesse Barnes, Intel Open Source Technology Center
PATCH 5/7 PCI: Make pci bridge reallocating enabled/disabled
In reply to Yinghai LuLet 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.
-v2: still honor pci=realloc, and treat it as pci=realloc=on
also use enum instead of ...
-v3: update kernel-paramenters.txt according to Jesse.
--- Documentation/kernel-parameters.txt | 9 +++++++-- drivers/pci/pci.c | 4 +++- drivers/pci/pci.h | 2 +- drivers/pci/setup-bus.c | 33 ++++++++++++++++++++++++++------- 4 files changed, 37 insertions(+), 11 deletions(-)
Documentation/kernel-parameters.txt +7 -2
@@ -2109,8 +2109,13 @@ bytes respectively. Such letter suffixes can also be entirely omitted. 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 + accommodate resources required by all child + devices. + off: Turn realloc off + on: Turn realloc on + realloc same as realloc=on pcie_aspm= [PCIE] Forcibly enable or disable PCIe Active State Power Management.
drivers/pci/pci.c +3 -1
@@ -3744,8 +3744,10 @@ static int __init pci_setup(char *str)pci_no_msi (); }else if (!strcmp (str,"noaer" )) {pci_no_aer (); + }else if (!strncmp (str,"realloc=" ,8 )) { +pci_realloc_get_opt (str +8 ); }else if (!strncmp (str,"realloc" ,7 )) { -pci_realloc (); +pci_realloc_get_opt ("on" ); }else if (!strcmp (str,"nodomains" )) {pci_no_domains (); }else if (!strncmp (str,"cbiosize=" ,9 )) {
drivers/pci/pci.h +1 -1
@@ -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) {
drivers/pci/setup-bus.c +26 -7
@@ -48,13 +48,6 @@ static void free_list(struct list_head *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
@@ -1273,6 +1266,32 @@ 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 +*/ +enum enable_type { + enable_not_set =-1 , + enable_no_user, + enable_no_detected, + enable_yes_user, + enable_yes_detected, +}; + +static enum enable_type pci_realloc_enable__initdata = enable_not_set; +void __init pci_realloc_get_opt (char *str) +{ +if (!strncmp (str,"off" ,3 )) + pci_realloc_enable = enable_no_user; +else if (!strncmp (str,"on" ,2 )) + pci_realloc_enable = enable_yes_user; +} +static bool __init pci_realloc_enabled (void ) +{ +return pci_realloc_enable >= enable_yes_user; +}/* * first try will not touch pci bridge res
Signature · 1 line
1.7.7
Re: [PATCH 5/7] PCI: Make pci bridge reallocating enabled/disabled
drivers/pci/setup-bus.c static int __init pci_get_max_depth(void) · line 1281
Quoted 7 lines · On Fri, 10 Feb 2012 15:33:50 -0800 Yinghai Lu <[email protected]> wrote:
drivers/pci/setup-bus.c +7
-0+enum enable_type { + enable_not_set =-1 , + enable_no_user, + enable_no_detected, + enable_yes_user, + enable_yes_detected, +};
How about:
user_enabled
user_disabled
auto_enabled
auto_disabled
?
enable_no_* seems a bit confusing...
also the help text in kernel-parameters.txt should mention the config option and describe default behavior with and without that config option enabled.
Thanks,
Signature · 1 line
Jesse Barnes, Intel Open Source Technology Center
PATCH 6/7 PCI: print out suggestion about using pci=realloc
In reply to Yinghai Lulet user know they could try if pci=realloc could help.
-v2: update suggestion text.
--- drivers/pci/setup-bus.c | 3 +++ 1 files changed, 3 insertions(+), 0 deletions(-)
drivers/pci/setup-bus.c +3 -0
@@ -1346,6 +1346,9 @@ again: goto enable_and_dump;if (tried_times >= pci_try_num) { +if (pci_realloc_enable == enable_not_set) +printk (KERN_INFO "Some PCI device resources are unassigned, try booting with pci=realloc\n" ); +free_list (&fail_head); goto enable_and_dump; }
Signature · 1 line
1.7.7
PATCH 7/7 PCI: only enable pci realloc when SRIOV bar is not assigned
In reply to Yinghai LuIf 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.
-v2: According to Jesse, adding one CONFIG option for distribution to
disable it or enable it.
--- drivers/pci/Kconfig | 10 ++++++++++ drivers/pci/setup-bus.c | 28 ++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+), 0 deletions(-)
drivers/pci/Kconfig +10 -0
@@ -31,6 +31,16 @@ config PCI_DEBUG When in doubt, say N. +config PCI_REALLOC_ENABLE_DETECT + bool "PCI Realloc Enable Detecting" + depends on PCI + help + Say Y here if you want the PCI core to detect if pci realloc + need to be enabled. You can always use pci=realloc=on or + pci=realloc=off to override it. + + When in doubt, say N. + config PCI_STUB tristate "PCI Stub driver" depends on PCI
drivers/pci/setup-bus.c +28 -0
@@ -1293,6 +1293,31 @@ static bool __init pci_realloc_enabled(void)return pci_realloc_enable >= enable_yes_user; } +static void __init pci_realloc_detect (void ) +{ +#if defined(CONFIG_PCI_IOV ) && defined(CONFIG_PCI_REALLOC_ENABLE_DETECT ) +struct pci_dev *dev =NULL ; + +if (pci_realloc_enable != enable_not_set) +return ; + +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 = enable_yes_detected; + +return ; + } + } + } +#endif +} +/* * first try will not touch pci bridge res * second and later try will clear small leaf bridge res
@@ -1314,6 +1339,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 ();
@@ -1348,6 +1374,8 @@ again:if (tried_times >= pci_try_num) {if (pci_realloc_enable == enable_not_set)printk (KERN_INFO "Some PCI device resources are unassigned, try booting with pci=realloc\n" ); +else if (pci_realloc_enable == enable_yes_detected) +printk (KERN_INFO "Automatically enabled pci realloc, if you have problem, try booting with pci=realloc=off\n" );free_list (&fail_head); goto enable_and_dump;
Signature · 1 line
1.7.7