Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge branch 'pci/resource' into next

* pci/resource:
PCI: Don't resize resources when realigning all devices in system
PCI: Don't reassign resources that are already aligned
PCI: Factor pci_reassigndev_resource_alignment()
powerpc/powernv: Override pcibios_default_alignment() to force PCI devices to be page aligned
PCI: Add pcibios_default_alignment() for arch-specific alignment control
PCI: Fix calculation of bridge window's size and alignment
PCI: Ignore requested alignment for IOV BARs
PCI: Make PCI_ROM_ADDRESS_MASK a 32-bit constant

+104 -31
+2
arch/powerpc/include/asm/machdep.h
··· 173 173 /* Called after scan and before resource survey */ 174 174 void (*pcibios_fixup_phb)(struct pci_controller *hose); 175 175 176 + resource_size_t (*pcibios_default_alignment)(void); 177 + 176 178 #ifdef CONFIG_PCI_IOV 177 179 void (*pcibios_fixup_sriov)(struct pci_dev *pdev); 178 180 resource_size_t (*pcibios_iov_resource_alignment)(struct pci_dev *, int resno);
+8
arch/powerpc/kernel/pci-common.c
··· 233 233 pci_reset_secondary_bus(dev); 234 234 } 235 235 236 + resource_size_t pcibios_default_alignment(void) 237 + { 238 + if (ppc_md.pcibios_default_alignment) 239 + return ppc_md.pcibios_default_alignment(); 240 + 241 + return 0; 242 + } 243 + 236 244 #ifdef CONFIG_PCI_IOV 237 245 resource_size_t pcibios_iov_resource_alignment(struct pci_dev *pdev, int resno) 238 246 {
+7
arch/powerpc/platforms/powernv/pci-ioda.c
··· 3287 3287 } 3288 3288 } 3289 3289 3290 + static resource_size_t pnv_pci_default_alignment(void) 3291 + { 3292 + return PAGE_SIZE; 3293 + } 3294 + 3290 3295 #ifdef CONFIG_PCI_IOV 3291 3296 static resource_size_t pnv_pci_iov_resource_alignment(struct pci_dev *pdev, 3292 3297 int resno) ··· 3824 3819 phb->dma_dev_setup = pnv_pci_ioda_dma_dev_setup; 3825 3820 hose->controller_ops = pnv_pci_ioda_controller_ops; 3826 3821 } 3822 + 3823 + ppc_md.pcibios_default_alignment = pnv_pci_default_alignment; 3827 3824 3828 3825 #ifdef CONFIG_PCI_IOV 3829 3826 ppc_md.pcibios_fixup_sriov = pnv_pci_ioda_fixup_iov_resources;
+82 -26
drivers/pci/pci.c
··· 5036 5036 } 5037 5037 EXPORT_SYMBOL_GPL(pci_ignore_hotplug); 5038 5038 5039 + resource_size_t __weak pcibios_default_alignment(void) 5040 + { 5041 + return 0; 5042 + } 5043 + 5039 5044 #define RESOURCE_ALIGNMENT_PARAM_SIZE COMMAND_LINE_SIZE 5040 5045 static char resource_alignment_param[RESOURCE_ALIGNMENT_PARAM_SIZE] = {0}; 5041 5046 static DEFINE_SPINLOCK(resource_alignment_lock); ··· 5048 5043 /** 5049 5044 * pci_specified_resource_alignment - get resource alignment specified by user. 5050 5045 * @dev: the PCI device to get 5046 + * @resize: whether or not to change resources' size when reassigning alignment 5051 5047 * 5052 5048 * RETURNS: Resource alignment if it is specified. 5053 5049 * Zero if it is not specified. 5054 5050 */ 5055 - static resource_size_t pci_specified_resource_alignment(struct pci_dev *dev) 5051 + static resource_size_t pci_specified_resource_alignment(struct pci_dev *dev, 5052 + bool *resize) 5056 5053 { 5057 5054 int seg, bus, slot, func, align_order, count; 5058 5055 unsigned short vendor, device, subsystem_vendor, subsystem_device; 5059 - resource_size_t align = 0; 5056 + resource_size_t align = pcibios_default_alignment(); 5060 5057 char *p; 5061 5058 5062 5059 spin_lock(&resource_alignment_lock); 5063 5060 p = resource_alignment_param; 5064 - if (!*p) 5061 + if (!*p && !align) 5065 5062 goto out; 5066 5063 if (pci_has_flag(PCI_PROBE_ONLY)) { 5064 + align = 0; 5067 5065 pr_info_once("PCI: Ignoring requested alignments (PCI_PROBE_ONLY)\n"); 5068 5066 goto out; 5069 5067 } ··· 5096 5088 (!device || (device == dev->device)) && 5097 5089 (!subsystem_vendor || (subsystem_vendor == dev->subsystem_vendor)) && 5098 5090 (!subsystem_device || (subsystem_device == dev->subsystem_device))) { 5091 + *resize = true; 5099 5092 if (align_order == -1) 5100 5093 align = PAGE_SIZE; 5101 5094 else ··· 5122 5113 bus == dev->bus->number && 5123 5114 slot == PCI_SLOT(dev->devfn) && 5124 5115 func == PCI_FUNC(dev->devfn)) { 5116 + *resize = true; 5125 5117 if (align_order == -1) 5126 5118 align = PAGE_SIZE; 5127 5119 else ··· 5142 5132 return align; 5143 5133 } 5144 5134 5135 + static void pci_request_resource_alignment(struct pci_dev *dev, int bar, 5136 + resource_size_t align, bool resize) 5137 + { 5138 + struct resource *r = &dev->resource[bar]; 5139 + resource_size_t size; 5140 + 5141 + if (!(r->flags & IORESOURCE_MEM)) 5142 + return; 5143 + 5144 + if (r->flags & IORESOURCE_PCI_FIXED) { 5145 + dev_info(&dev->dev, "BAR%d %pR: ignoring requested alignment %#llx\n", 5146 + bar, r, (unsigned long long)align); 5147 + return; 5148 + } 5149 + 5150 + size = resource_size(r); 5151 + if (size >= align) 5152 + return; 5153 + 5154 + /* 5155 + * Increase the alignment of the resource. There are two ways we 5156 + * can do this: 5157 + * 5158 + * 1) Increase the size of the resource. BARs are aligned on their 5159 + * size, so when we reallocate space for this resource, we'll 5160 + * allocate it with the larger alignment. This also prevents 5161 + * assignment of any other BARs inside the alignment region, so 5162 + * if we're requesting page alignment, this means no other BARs 5163 + * will share the page. 5164 + * 5165 + * The disadvantage is that this makes the resource larger than 5166 + * the hardware BAR, which may break drivers that compute things 5167 + * based on the resource size, e.g., to find registers at a 5168 + * fixed offset before the end of the BAR. 5169 + * 5170 + * 2) Retain the resource size, but use IORESOURCE_STARTALIGN and 5171 + * set r->start to the desired alignment. By itself this 5172 + * doesn't prevent other BARs being put inside the alignment 5173 + * region, but if we realign *every* resource of every device in 5174 + * the system, none of them will share an alignment region. 5175 + * 5176 + * When the user has requested alignment for only some devices via 5177 + * the "pci=resource_alignment" argument, "resize" is true and we 5178 + * use the first method. Otherwise we assume we're aligning all 5179 + * devices and we use the second. 5180 + */ 5181 + 5182 + dev_info(&dev->dev, "BAR%d %pR: requesting alignment to %#llx\n", 5183 + bar, r, (unsigned long long)align); 5184 + 5185 + if (resize) { 5186 + r->start = 0; 5187 + r->end = align - 1; 5188 + } else { 5189 + r->flags &= ~IORESOURCE_SIZEALIGN; 5190 + r->flags |= IORESOURCE_STARTALIGN; 5191 + r->start = align; 5192 + r->end = r->start + size - 1; 5193 + } 5194 + r->flags |= IORESOURCE_UNSET; 5195 + } 5196 + 5145 5197 /* 5146 5198 * This function disables memory decoding and releases memory resources 5147 5199 * of the device specified by kernel's boot parameter 'pci=resource_alignment='. ··· 5215 5143 { 5216 5144 int i; 5217 5145 struct resource *r; 5218 - resource_size_t align, size; 5146 + resource_size_t align; 5219 5147 u16 command; 5148 + bool resize = false; 5220 5149 5221 5150 /* 5222 5151 * VF BARs are read-only zero according to SR-IOV spec r1.1, sec ··· 5229 5156 return; 5230 5157 5231 5158 /* check if specified PCI is target device to reassign */ 5232 - align = pci_specified_resource_alignment(dev); 5159 + align = pci_specified_resource_alignment(dev, &resize); 5233 5160 if (!align) 5234 5161 return; 5235 5162 ··· 5246 5173 command &= ~PCI_COMMAND_MEMORY; 5247 5174 pci_write_config_word(dev, PCI_COMMAND, command); 5248 5175 5249 - for (i = 0; i < PCI_BRIDGE_RESOURCES; i++) { 5250 - r = &dev->resource[i]; 5251 - if (!(r->flags & IORESOURCE_MEM)) 5252 - continue; 5253 - if (r->flags & IORESOURCE_PCI_FIXED) { 5254 - dev_info(&dev->dev, "Ignoring requested alignment for BAR%d: %pR\n", 5255 - i, r); 5256 - continue; 5257 - } 5176 + for (i = 0; i <= PCI_ROM_RESOURCE; i++) 5177 + pci_request_resource_alignment(dev, i, align, resize); 5258 5178 5259 - size = resource_size(r); 5260 - if (size < align) { 5261 - size = align; 5262 - dev_info(&dev->dev, 5263 - "Rounding up size of resource #%d to %#llx.\n", 5264 - i, (unsigned long long)size); 5265 - } 5266 - r->flags |= IORESOURCE_UNSET; 5267 - r->end = size - 1; 5268 - r->start = 0; 5269 - } 5270 - /* Need to disable bridge's resource window, 5179 + /* 5180 + * Need to disable bridge's resource window, 5271 5181 * to enable the kernel to reassign new resource 5272 5182 * window later on. 5273 5183 */
+1 -1
drivers/pci/probe.c
··· 231 231 res->flags |= IORESOURCE_ROM_ENABLE; 232 232 l64 = l & PCI_ROM_ADDRESS_MASK; 233 233 sz64 = sz & PCI_ROM_ADDRESS_MASK; 234 - mask64 = (u32)PCI_ROM_ADDRESS_MASK; 234 + mask64 = PCI_ROM_ADDRESS_MASK; 235 235 } 236 236 237 237 if (res->flags & IORESOURCE_MEM_64) {
+2 -2
drivers/pci/setup-bus.c
··· 1066 1066 r->flags = 0; 1067 1067 continue; 1068 1068 } 1069 - size += r_size; 1069 + size += max(r_size, align); 1070 1070 /* Exclude ranges with size > align from 1071 1071 calculation of the alignment. */ 1072 - if (r_size == align) 1072 + if (r_size <= align) 1073 1073 aligns[order] += align; 1074 1074 if (order > max_order) 1075 1075 max_order = order;
+1 -1
drivers/pci/setup-res.c
··· 63 63 mask = (u32)PCI_BASE_ADDRESS_IO_MASK; 64 64 new |= res->flags & ~PCI_BASE_ADDRESS_IO_MASK; 65 65 } else if (resno == PCI_ROM_RESOURCE) { 66 - mask = (u32)PCI_ROM_ADDRESS_MASK; 66 + mask = PCI_ROM_ADDRESS_MASK; 67 67 } else { 68 68 mask = (u32)PCI_BASE_ADDRESS_MEM_MASK; 69 69 new |= res->flags & ~PCI_BASE_ADDRESS_MEM_MASK;
+1 -1
include/uapi/linux/pci_regs.h
··· 114 114 #define PCI_SUBSYSTEM_ID 0x2e 115 115 #define PCI_ROM_ADDRESS 0x30 /* Bits 31..11 are address, 10..1 reserved */ 116 116 #define PCI_ROM_ADDRESS_ENABLE 0x01 117 - #define PCI_ROM_ADDRESS_MASK (~0x7ffUL) 117 + #define PCI_ROM_ADDRESS_MASK (~0x7ffU) 118 118 119 119 #define PCI_CAPABILITY_LIST 0x34 /* Offset of first capability list entry */ 120 120