PCI: Clean up resource_alignment parameter to not require static buffer
authorLogan Gunthorpe <logang@deltatee.com>
Thu, 22 Aug 2019 16:10:11 +0000 (10:10 -0600)
committerBjorn Helgaas <bhelgaas@google.com>
Thu, 5 Sep 2019 18:26:46 +0000 (13:26 -0500)
Clean up the 'resource_alignment' parameter code to use kstrdup() in the
initcall routine instead of a static buffer that wastes memory regardless
of whether the feature is used.  This allows us to drop 'COMMAND_LINE_SIZE'
bytes (typically 256-4096 depending on architecture) of static data.

This is similar to what has been done for the 'disable_acs_redir'
parameter.

Link: https://lore.kernel.org/r/20190822161013.5481-2-logang@deltatee.com
Signed-off-by: Logan Gunthorpe <logang@deltatee.com>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
drivers/pci/pci.c

index 08dfb16bd084274ba72c9ce5512fad366dbf91bb..fbfb64ba447d70170a57eaafb5bc6912b3aeb1a7 100644 (file)
@@ -5932,8 +5932,7 @@ resource_size_t __weak pcibios_default_alignment(void)
        return 0;
 }
 
-#define RESOURCE_ALIGNMENT_PARAM_SIZE COMMAND_LINE_SIZE
-static char resource_alignment_param[RESOURCE_ALIGNMENT_PARAM_SIZE] = {0};
+static char *resource_alignment_param;
 static DEFINE_SPINLOCK(resource_alignment_lock);
 
 /**
@@ -5954,7 +5953,7 @@ static resource_size_t pci_specified_resource_alignment(struct pci_dev *dev,
 
        spin_lock(&resource_alignment_lock);
        p = resource_alignment_param;
-       if (!*p && !align)
+       if (!p || !*p)
                goto out;
        if (pci_has_flag(PCI_PROBE_ONLY)) {
                align = 0;
@@ -6120,21 +6119,25 @@ void pci_reassigndev_resource_alignment(struct pci_dev *dev)
 
 static ssize_t pci_set_resource_alignment_param(const char *buf, size_t count)
 {
-       if (count > RESOURCE_ALIGNMENT_PARAM_SIZE - 1)
-               count = RESOURCE_ALIGNMENT_PARAM_SIZE - 1;
        spin_lock(&resource_alignment_lock);
-       strncpy(resource_alignment_param, buf, count);
-       resource_alignment_param[count] = '\0';
+
+       kfree(resource_alignment_param);
+       resource_alignment_param = kstrndup(buf, count, GFP_KERNEL);
+
        spin_unlock(&resource_alignment_lock);
-       return count;
+
+       return resource_alignment_param ? count : -ENOMEM;
 }
 
 static ssize_t pci_get_resource_alignment_param(char *buf, size_t size)
 {
-       size_t count;
+       size_t count = 0;
+
        spin_lock(&resource_alignment_lock);
-       count = snprintf(buf, size, "%s", resource_alignment_param);
+       if (resource_alignment_param)
+               count = snprintf(buf, size, "%s", resource_alignment_param);
        spin_unlock(&resource_alignment_lock);
+
        return count;
 }
 
@@ -6275,8 +6278,7 @@ static int __init pci_setup(char *str)
                        } else if (!strncmp(str, "cbmemsize=", 10)) {
                                pci_cardbus_mem_size = memparse(str + 10, &str);
                        } else if (!strncmp(str, "resource_alignment=", 19)) {
-                               pci_set_resource_alignment_param(str + 19,
-                                                       strlen(str + 19));
+                               resource_alignment_param = str + 19;
                        } else if (!strncmp(str, "ecrc=", 5)) {
                                pcie_ecrc_get_policy(str + 5);
                        } else if (!strncmp(str, "hpiosize=", 9)) {
@@ -6311,15 +6313,18 @@ static int __init pci_setup(char *str)
 early_param("pci", pci_setup);
 
 /*
- * 'disable_acs_redir_param' is initialized in pci_setup(), above, to point
- * to data in the __initdata section which will be freed after the init
- * sequence is complete. We can't allocate memory in pci_setup() because some
- * architectures do not have any memory allocation service available during
- * an early_param() call. So we allocate memory and copy the variable here
- * before the init section is freed.
+ * 'resource_alignment_param' and 'disable_acs_redir_param' are initialized
+ * in pci_setup(), above, to point to data in the __initdata section which
+ * will be freed after the init sequence is complete. We can't allocate memory
+ * in pci_setup() because some architectures do not have any memory allocation
+ * service available during an early_param() call. So we allocate memory and
+ * copy the variable here before the init section is freed.
+ *
  */
 static int __init pci_realloc_setup_params(void)
 {
+       resource_alignment_param = kstrdup(resource_alignment_param,
+                                          GFP_KERNEL);
        disable_acs_redir_param = kstrdup(disable_acs_redir_param, GFP_KERNEL);
 
        return 0;