summaryrefslogtreecommitdiffstats
path: root/drivers/pci/pci.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pci/pci.c')
-rw-r--r--drivers/pci/pci.c87
1 files changed, 53 insertions, 34 deletions
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 1b27b5af3d55..e7982af9a5d8 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -890,8 +890,8 @@ static int pci_raw_set_power_state(struct pci_dev *dev, pci_power_t state)
890 890
891 pci_read_config_word(dev, dev->pm_cap + PCI_PM_CTRL, &pmcsr); 891 pci_read_config_word(dev, dev->pm_cap + PCI_PM_CTRL, &pmcsr);
892 dev->current_state = (pmcsr & PCI_PM_CTRL_STATE_MASK); 892 dev->current_state = (pmcsr & PCI_PM_CTRL_STATE_MASK);
893 if (dev->current_state != state && printk_ratelimit()) 893 if (dev->current_state != state)
894 pci_info(dev, "Refused to change power state, currently in D%d\n", 894 pci_info_ratelimited(dev, "Refused to change power state, currently in D%d\n",
895 dev->current_state); 895 dev->current_state);
896 896
897 /* 897 /*
@@ -1443,7 +1443,7 @@ static void pci_restore_rebar_state(struct pci_dev *pdev)
1443 pci_read_config_dword(pdev, pos + PCI_REBAR_CTRL, &ctrl); 1443 pci_read_config_dword(pdev, pos + PCI_REBAR_CTRL, &ctrl);
1444 bar_idx = ctrl & PCI_REBAR_CTRL_BAR_IDX; 1444 bar_idx = ctrl & PCI_REBAR_CTRL_BAR_IDX;
1445 res = pdev->resource + bar_idx; 1445 res = pdev->resource + bar_idx;
1446 size = order_base_2((resource_size(res) >> 20) | 1) - 1; 1446 size = ilog2(resource_size(res)) - 20;
1447 ctrl &= ~PCI_REBAR_CTRL_BAR_SIZE; 1447 ctrl &= ~PCI_REBAR_CTRL_BAR_SIZE;
1448 ctrl |= size << PCI_REBAR_CTRL_BAR_SHIFT; 1448 ctrl |= size << PCI_REBAR_CTRL_BAR_SHIFT;
1449 pci_write_config_dword(pdev, pos + PCI_REBAR_CTRL, ctrl); 1449 pci_write_config_dword(pdev, pos + PCI_REBAR_CTRL, ctrl);
@@ -3581,7 +3581,7 @@ int pci_enable_atomic_ops_to_root(struct pci_dev *dev, u32 cap_mask)
3581 } 3581 }
3582 3582
3583 /* Ensure upstream ports don't block AtomicOps on egress */ 3583 /* Ensure upstream ports don't block AtomicOps on egress */
3584 if (!bridge->has_secondary_link) { 3584 if (pci_pcie_type(bridge) == PCI_EXP_TYPE_UPSTREAM) {
3585 pcie_capability_read_dword(bridge, PCI_EXP_DEVCTL2, 3585 pcie_capability_read_dword(bridge, PCI_EXP_DEVCTL2,
3586 &ctl2); 3586 &ctl2);
3587 if (ctl2 & PCI_EXP_DEVCTL2_ATOMIC_EGRESS_BLOCK) 3587 if (ctl2 & PCI_EXP_DEVCTL2_ATOMIC_EGRESS_BLOCK)
@@ -5923,8 +5923,19 @@ resource_size_t __weak pcibios_default_alignment(void)
5923 return 0; 5923 return 0;
5924} 5924}
5925 5925
5926#define RESOURCE_ALIGNMENT_PARAM_SIZE COMMAND_LINE_SIZE 5926/*
5927static char resource_alignment_param[RESOURCE_ALIGNMENT_PARAM_SIZE] = {0}; 5927 * Arches that don't want to expose struct resource to userland as-is in
5928 * sysfs and /proc can implement their own pci_resource_to_user().
5929 */
5930void __weak pci_resource_to_user(const struct pci_dev *dev, int bar,
5931 const struct resource *rsrc,
5932 resource_size_t *start, resource_size_t *end)
5933{
5934 *start = rsrc->start;
5935 *end = rsrc->end;
5936}
5937
5938static char *resource_alignment_param;
5928static DEFINE_SPINLOCK(resource_alignment_lock); 5939static DEFINE_SPINLOCK(resource_alignment_lock);
5929 5940
5930/** 5941/**
@@ -5945,7 +5956,7 @@ static resource_size_t pci_specified_resource_alignment(struct pci_dev *dev,
5945 5956
5946 spin_lock(&resource_alignment_lock); 5957 spin_lock(&resource_alignment_lock);
5947 p = resource_alignment_param; 5958 p = resource_alignment_param;
5948 if (!*p && !align) 5959 if (!p || !*p)
5949 goto out; 5960 goto out;
5950 if (pci_has_flag(PCI_PROBE_ONLY)) { 5961 if (pci_has_flag(PCI_PROBE_ONLY)) {
5951 align = 0; 5962 align = 0;
@@ -6109,35 +6120,41 @@ void pci_reassigndev_resource_alignment(struct pci_dev *dev)
6109 } 6120 }
6110} 6121}
6111 6122
6112static ssize_t pci_set_resource_alignment_param(const char *buf, size_t count) 6123static ssize_t resource_alignment_show(struct bus_type *bus, char *buf)
6113{ 6124{
6114 if (count > RESOURCE_ALIGNMENT_PARAM_SIZE - 1) 6125 size_t count = 0;
6115 count = RESOURCE_ALIGNMENT_PARAM_SIZE - 1;
6116 spin_lock(&resource_alignment_lock);
6117 strncpy(resource_alignment_param, buf, count);
6118 resource_alignment_param[count] = '\0';
6119 spin_unlock(&resource_alignment_lock);
6120 return count;
6121}
6122 6126
6123static ssize_t pci_get_resource_alignment_param(char *buf, size_t size)
6124{
6125 size_t count;
6126 spin_lock(&resource_alignment_lock); 6127 spin_lock(&resource_alignment_lock);
6127 count = snprintf(buf, size, "%s", resource_alignment_param); 6128 if (resource_alignment_param)
6129 count = snprintf(buf, PAGE_SIZE, "%s", resource_alignment_param);
6128 spin_unlock(&resource_alignment_lock); 6130 spin_unlock(&resource_alignment_lock);
6129 return count;
6130}
6131 6131
6132static ssize_t resource_alignment_show(struct bus_type *bus, char *buf) 6132 /*
6133{ 6133 * When set by the command line, resource_alignment_param will not
6134 return pci_get_resource_alignment_param(buf, PAGE_SIZE); 6134 * have a trailing line feed, which is ugly. So conditionally add
6135 * it here.
6136 */
6137 if (count >= 2 && buf[count - 2] != '\n' && count < PAGE_SIZE - 1) {
6138 buf[count - 1] = '\n';
6139 buf[count++] = 0;
6140 }
6141
6142 return count;
6135} 6143}
6136 6144
6137static ssize_t resource_alignment_store(struct bus_type *bus, 6145static ssize_t resource_alignment_store(struct bus_type *bus,
6138 const char *buf, size_t count) 6146 const char *buf, size_t count)
6139{ 6147{
6140 return pci_set_resource_alignment_param(buf, count); 6148 char *param = kstrndup(buf, count, GFP_KERNEL);
6149
6150 if (!param)
6151 return -ENOMEM;
6152
6153 spin_lock(&resource_alignment_lock);
6154 kfree(resource_alignment_param);
6155 resource_alignment_param = param;
6156 spin_unlock(&resource_alignment_lock);
6157 return count;
6141} 6158}
6142 6159
6143static BUS_ATTR_RW(resource_alignment); 6160static BUS_ATTR_RW(resource_alignment);
@@ -6266,8 +6283,7 @@ static int __init pci_setup(char *str)
6266 } else if (!strncmp(str, "cbmemsize=", 10)) { 6283 } else if (!strncmp(str, "cbmemsize=", 10)) {
6267 pci_cardbus_mem_size = memparse(str + 10, &str); 6284 pci_cardbus_mem_size = memparse(str + 10, &str);
6268 } else if (!strncmp(str, "resource_alignment=", 19)) { 6285 } else if (!strncmp(str, "resource_alignment=", 19)) {
6269 pci_set_resource_alignment_param(str + 19, 6286 resource_alignment_param = str + 19;
6270 strlen(str + 19));
6271 } else if (!strncmp(str, "ecrc=", 5)) { 6287 } else if (!strncmp(str, "ecrc=", 5)) {
6272 pcie_ecrc_get_policy(str + 5); 6288 pcie_ecrc_get_policy(str + 5);
6273 } else if (!strncmp(str, "hpiosize=", 9)) { 6289 } else if (!strncmp(str, "hpiosize=", 9)) {
@@ -6302,15 +6318,18 @@ static int __init pci_setup(char *str)
6302early_param("pci", pci_setup); 6318early_param("pci", pci_setup);
6303 6319
6304/* 6320/*
6305 * 'disable_acs_redir_param' is initialized in pci_setup(), above, to point 6321 * 'resource_alignment_param' and 'disable_acs_redir_param' are initialized
6306 * to data in the __initdata section which will be freed after the init 6322 * in pci_setup(), above, to point to data in the __initdata section which
6307 * sequence is complete. We can't allocate memory in pci_setup() because some 6323 * will be freed after the init sequence is complete. We can't allocate memory
6308 * architectures do not have any memory allocation service available during 6324 * in pci_setup() because some architectures do not have any memory allocation
6309 * an early_param() call. So we allocate memory and copy the variable here 6325 * service available during an early_param() call. So we allocate memory and
6310 * before the init section is freed. 6326 * copy the variable here before the init section is freed.
6327 *
6311 */ 6328 */
6312static int __init pci_realloc_setup_params(void) 6329static int __init pci_realloc_setup_params(void)
6313{ 6330{
6331 resource_alignment_param = kstrdup(resource_alignment_param,
6332 GFP_KERNEL);
6314 disable_acs_redir_param = kstrdup(disable_acs_redir_param, GFP_KERNEL); 6333 disable_acs_redir_param = kstrdup(disable_acs_redir_param, GFP_KERNEL);
6315 6334
6316 return 0; 6335 return 0;