PCI: conditional resource-reallocation through kernel parameter pci=realloc
Ram Pai [Thu, 7 Jul 2011 18:19:10 +0000 (11:19 -0700)]
Multiple attempts to dynamically reallocate pci resources have
unfortunately lead to regressions. Though we continue to fix the
regressions and fine tune the dynamic-reallocation behavior, we have not
reached a acceptable state yet.

This patch provides a interim solution. It disables dynamic reallocation
by default, but adds the ability to enable it through pci=realloc kernel
command line parameter.

Tested-by: Oliver Hartkopp <socketcan@hartkopp.net>
Signed-off-by: Ram Pai <linuxram@us.ibm.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>

Documentation/kernel-parameters.txt
drivers/pci/pci.c
drivers/pci/pci.h
drivers/pci/setup-bus.c

index fd248a3..aa47be7 100644 (file)
@@ -2015,6 +2015,8 @@ 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.
 
        pcie_aspm=      [PCIE] Forcibly enable or disable PCIe Active State Power
                        Management.
index 2c5b9b9..692671b 100644 (file)
@@ -3483,6 +3483,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 (!strcmp(str, "nodomains")) {
                                pci_no_domains();
                        } else if (!strncmp(str, "cbiosize=", 9)) {
index 731e202..3a39bf1 100644 (file)
@@ -146,6 +146,8 @@ 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);
+
 static inline int pci_no_d1d2(struct pci_dev *dev)
 {
        unsigned int parent_dstates = 0;
index 1e9e5a5..9995842 100644 (file)
@@ -47,6 +47,13 @@ struct resource_list_x {
        (head)->next = NULL;                            \
 } while (0)
 
+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
@@ -1025,6 +1032,7 @@ static int __init pci_get_max_depth(void)
        return depth;
 }
 
+
 /*
  * first try will not touch pci bridge res
  * second  and later try will clear small leaf bridge res
@@ -1068,6 +1076,13 @@ again:
        /* any device complain? */
        if (!head.next)
                goto enable_and_dump;
+
+       /* don't realloc if asked to do so */
+       if (!pci_realloc_enabled()) {
+               free_list(resource_list_x, &head);
+               goto enable_and_dump;
+       }
+
        failed_type = 0;
        for (list = head.next; list;) {
                failed_type |= list->flags;