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

Configure Feed

Select the types of activity you want to include in your feed.

Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jbarnes/pci-2.6

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jbarnes/pci-2.6:
PCI: sysfs: fix printk warnings
PCI: fix pci_bus_alloc_resource() hang, prefer positive decode
PCI: read current power state at enable time
PCI: fix size checks for mmap() on /proc/bus/pci files
x86/PCI: coalesce overlapping host bridge windows
PCI hotplug: ibmphp: Add check to prevent reading beyond mapped area

+175 -50
+84 -21
arch/x86/pci/acpi.c
··· 138 138 struct acpi_resource_address64 addr; 139 139 acpi_status status; 140 140 unsigned long flags; 141 - struct resource *root, *conflict; 142 141 u64 start, end; 143 142 144 143 status = resource_to_addr(acpi_res, &addr); ··· 145 146 return AE_OK; 146 147 147 148 if (addr.resource_type == ACPI_MEMORY_RANGE) { 148 - root = &iomem_resource; 149 149 flags = IORESOURCE_MEM; 150 150 if (addr.info.mem.caching == ACPI_PREFETCHABLE_MEMORY) 151 151 flags |= IORESOURCE_PREFETCH; 152 152 } else if (addr.resource_type == ACPI_IO_RANGE) { 153 - root = &ioport_resource; 154 153 flags = IORESOURCE_IO; 155 154 } else 156 155 return AE_OK; ··· 169 172 return AE_OK; 170 173 } 171 174 172 - conflict = insert_resource_conflict(root, res); 173 - if (conflict) { 174 - dev_err(&info->bridge->dev, 175 - "address space collision: host bridge window %pR " 176 - "conflicts with %s %pR\n", 177 - res, conflict->name, conflict); 178 - } else { 179 - pci_bus_add_resource(info->bus, res, 0); 180 - info->res_num++; 181 - if (addr.translation_offset) 182 - dev_info(&info->bridge->dev, "host bridge window %pR " 183 - "(PCI address [%#llx-%#llx])\n", 184 - res, res->start - addr.translation_offset, 185 - res->end - addr.translation_offset); 186 - else 187 - dev_info(&info->bridge->dev, 188 - "host bridge window %pR\n", res); 189 - } 175 + info->res_num++; 176 + if (addr.translation_offset) 177 + dev_info(&info->bridge->dev, "host bridge window %pR " 178 + "(PCI address [%#llx-%#llx])\n", 179 + res, res->start - addr.translation_offset, 180 + res->end - addr.translation_offset); 181 + else 182 + dev_info(&info->bridge->dev, "host bridge window %pR\n", res); 183 + 190 184 return AE_OK; 185 + } 186 + 187 + static bool resource_contains(struct resource *res, resource_size_t point) 188 + { 189 + if (res->start <= point && point <= res->end) 190 + return true; 191 + return false; 192 + } 193 + 194 + static void coalesce_windows(struct pci_root_info *info, int type) 195 + { 196 + int i, j; 197 + struct resource *res1, *res2; 198 + 199 + for (i = 0; i < info->res_num; i++) { 200 + res1 = &info->res[i]; 201 + if (!(res1->flags & type)) 202 + continue; 203 + 204 + for (j = i + 1; j < info->res_num; j++) { 205 + res2 = &info->res[j]; 206 + if (!(res2->flags & type)) 207 + continue; 208 + 209 + /* 210 + * I don't like throwing away windows because then 211 + * our resources no longer match the ACPI _CRS, but 212 + * the kernel resource tree doesn't allow overlaps. 213 + */ 214 + if (resource_contains(res1, res2->start) || 215 + resource_contains(res1, res2->end) || 216 + resource_contains(res2, res1->start) || 217 + resource_contains(res2, res1->end)) { 218 + res1->start = min(res1->start, res2->start); 219 + res1->end = max(res1->end, res2->end); 220 + dev_info(&info->bridge->dev, 221 + "host bridge window expanded to %pR; %pR ignored\n", 222 + res1, res2); 223 + res2->flags = 0; 224 + } 225 + } 226 + } 227 + } 228 + 229 + static void add_resources(struct pci_root_info *info) 230 + { 231 + int i; 232 + struct resource *res, *root, *conflict; 233 + 234 + if (!pci_use_crs) 235 + return; 236 + 237 + coalesce_windows(info, IORESOURCE_MEM); 238 + coalesce_windows(info, IORESOURCE_IO); 239 + 240 + for (i = 0; i < info->res_num; i++) { 241 + res = &info->res[i]; 242 + 243 + if (res->flags & IORESOURCE_MEM) 244 + root = &iomem_resource; 245 + else if (res->flags & IORESOURCE_IO) 246 + root = &ioport_resource; 247 + else 248 + continue; 249 + 250 + conflict = insert_resource_conflict(root, res); 251 + if (conflict) 252 + dev_err(&info->bridge->dev, 253 + "address space collision: host bridge window %pR " 254 + "conflicts with %s %pR\n", 255 + res, conflict->name, conflict); 256 + else 257 + pci_bus_add_resource(info->bus, res, 0); 258 + } 191 259 } 192 260 193 261 static void ··· 286 224 acpi_walk_resources(device->handle, METHOD_NAME__CRS, setup_resource, 287 225 &info); 288 226 227 + add_resources(&info); 289 228 return; 290 229 291 230 name_alloc_fail:
+49 -21
drivers/pci/bus.c
··· 64 64 } 65 65 } 66 66 67 + static bool pci_bus_resource_better(struct resource *res1, bool pos1, 68 + struct resource *res2, bool pos2) 69 + { 70 + /* If exactly one is positive decode, always prefer that one */ 71 + if (pos1 != pos2) 72 + return pos1 ? true : false; 73 + 74 + /* Prefer the one that contains the highest address */ 75 + if (res1->end != res2->end) 76 + return (res1->end > res2->end) ? true : false; 77 + 78 + /* Otherwise, prefer the one with highest "center of gravity" */ 79 + if (res1->start != res2->start) 80 + return (res1->start > res2->start) ? true : false; 81 + 82 + /* Otherwise, choose one arbitrarily (but consistently) */ 83 + return (res1 > res2) ? true : false; 84 + } 85 + 86 + static bool pci_bus_resource_positive(struct pci_bus *bus, struct resource *res) 87 + { 88 + struct pci_bus_resource *bus_res; 89 + 90 + /* 91 + * This relies on the fact that pci_bus.resource[] refers to P2P or 92 + * CardBus bridge base/limit registers, which are always positively 93 + * decoded. The pci_bus.resources list contains host bridge or 94 + * subtractively decoded resources. 95 + */ 96 + list_for_each_entry(bus_res, &bus->resources, list) { 97 + if (bus_res->res == res) 98 + return (bus_res->flags & PCI_SUBTRACTIVE_DECODE) ? 99 + false : true; 100 + } 101 + return true; 102 + } 103 + 67 104 /* 68 - * Find the highest-address bus resource below the cursor "res". If the 69 - * cursor is NULL, return the highest resource. 105 + * Find the next-best bus resource after the cursor "res". If the cursor is 106 + * NULL, return the best resource. "Best" means that we prefer positive 107 + * decode regions over subtractive decode, then those at higher addresses. 70 108 */ 71 109 static struct resource *pci_bus_find_resource_prev(struct pci_bus *bus, 72 110 unsigned int type, 73 111 struct resource *res) 74 112 { 113 + bool res_pos, r_pos, prev_pos = false; 75 114 struct resource *r, *prev = NULL; 76 115 int i; 77 116 117 + res_pos = pci_bus_resource_positive(bus, res); 78 118 pci_bus_for_each_resource(bus, r, i) { 79 119 if (!r) 80 120 continue; ··· 122 82 if ((r->flags & IORESOURCE_TYPE_BITS) != type) 123 83 continue; 124 84 125 - /* If this resource is at or past the cursor, skip it */ 126 - if (res) { 127 - if (r == res) 128 - continue; 129 - if (r->end > res->end) 130 - continue; 131 - if (r->end == res->end && r->start > res->start) 132 - continue; 85 + r_pos = pci_bus_resource_positive(bus, r); 86 + if (!res || pci_bus_resource_better(res, res_pos, r, r_pos)) { 87 + if (!prev || pci_bus_resource_better(r, r_pos, 88 + prev, prev_pos)) { 89 + prev = r; 90 + prev_pos = r_pos; 91 + } 133 92 } 134 - 135 - if (!prev) 136 - prev = r; 137 - 138 - /* 139 - * A small resource is higher than a large one that ends at 140 - * the same address. 141 - */ 142 - if (r->end > prev->end || 143 - (r->end == prev->end && r->start > prev->start)) 144 - prev = r; 145 93 } 146 94 147 95 return prev;
+6
drivers/pci/hotplug/ibmphp_ebda.c
··· 276 276 277 277 for (;;) { 278 278 offset = next_offset; 279 + 280 + /* Make sure what we read is still in the mapped section */ 281 + if (WARN(offset > (ebda_sz * 1024 - 4), 282 + "ibmphp_ebda: next read is beyond ebda_sz\n")) 283 + break; 284 + 279 285 next_offset = readw (io_mem + offset); /* offset of next blk */ 280 286 281 287 offset += 2;
+17 -6
drivers/pci/pci-sysfs.c
··· 705 705 706 706 #ifdef HAVE_PCI_MMAP 707 707 708 - int pci_mmap_fits(struct pci_dev *pdev, int resno, struct vm_area_struct *vma) 708 + int pci_mmap_fits(struct pci_dev *pdev, int resno, struct vm_area_struct *vma, 709 + enum pci_mmap_api mmap_api) 709 710 { 710 - unsigned long nr, start, size; 711 + unsigned long nr, start, size, pci_start; 711 712 713 + if (pci_resource_len(pdev, resno) == 0) 714 + return 0; 712 715 nr = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT; 713 716 start = vma->vm_pgoff; 714 717 size = ((pci_resource_len(pdev, resno) - 1) >> PAGE_SHIFT) + 1; 715 - if (start < size && size - start >= nr) 718 + pci_start = (mmap_api == PCI_MMAP_SYSFS) ? 719 + pci_resource_start(pdev, resno) >> PAGE_SHIFT : 0; 720 + if (start >= pci_start && start < pci_start + size && 721 + start + nr <= pci_start + size) 716 722 return 1; 717 - WARN(1, "process \"%s\" tried to map 0x%08lx-0x%08lx on %s BAR %d (size 0x%08lx)\n", 718 - current->comm, start, start+nr, pci_name(pdev), resno, size); 719 723 return 0; 720 724 } 721 725 ··· 749 745 if (i >= PCI_ROM_RESOURCE) 750 746 return -ENODEV; 751 747 752 - if (!pci_mmap_fits(pdev, i, vma)) 748 + if (!pci_mmap_fits(pdev, i, vma, PCI_MMAP_SYSFS)) { 749 + WARN(1, "process \"%s\" tried to map 0x%08lx bytes " 750 + "at page 0x%08lx on %s BAR %d (start 0x%16Lx, size 0x%16Lx)\n", 751 + current->comm, vma->vm_end-vma->vm_start, vma->vm_pgoff, 752 + pci_name(pdev), i, 753 + (u64)pci_resource_start(pdev, i), 754 + (u64)pci_resource_len(pdev, i)); 753 755 return -EINVAL; 756 + } 754 757 755 758 /* pci_mmap_page_range() expects the same kind of entry as coming 756 759 * from /proc/bus/pci/ which is a "user visible" value. If this is
+12
drivers/pci/pci.c
··· 1007 1007 int err; 1008 1008 int i, bars = 0; 1009 1009 1010 + /* 1011 + * Power state could be unknown at this point, either due to a fresh 1012 + * boot or a device removal call. So get the current power state 1013 + * so that things like MSI message writing will behave as expected 1014 + * (e.g. if the device really is in D0 at enable time). 1015 + */ 1016 + if (dev->pm_cap) { 1017 + u16 pmcsr; 1018 + pci_read_config_word(dev, dev->pm_cap + PCI_PM_CTRL, &pmcsr); 1019 + dev->current_state = (pmcsr & PCI_PM_CTRL_STATE_MASK); 1020 + } 1021 + 1010 1022 if (atomic_add_return(1, &dev->enable_cnt) > 1) 1011 1023 return 0; /* already enabled */ 1012 1024
+6 -1
drivers/pci/pci.h
··· 22 22 #endif 23 23 extern void pci_cleanup_rom(struct pci_dev *dev); 24 24 #ifdef HAVE_PCI_MMAP 25 + enum pci_mmap_api { 26 + PCI_MMAP_SYSFS, /* mmap on /sys/bus/pci/devices/<BDF>/resource<N> */ 27 + PCI_MMAP_PROCFS /* mmap on /proc/bus/pci/<BDF> */ 28 + }; 25 29 extern int pci_mmap_fits(struct pci_dev *pdev, int resno, 26 - struct vm_area_struct *vma); 30 + struct vm_area_struct *vmai, 31 + enum pci_mmap_api mmap_api); 27 32 #endif 28 33 int pci_probe_reset_function(struct pci_dev *dev); 29 34
+1 -1
drivers/pci/proc.c
··· 257 257 258 258 /* Make sure the caller is mapping a real resource for this device */ 259 259 for (i = 0; i < PCI_ROM_RESOURCE; i++) { 260 - if (pci_mmap_fits(dev, i, vma)) 260 + if (pci_mmap_fits(dev, i, vma, PCI_MMAP_PROCFS)) 261 261 break; 262 262 } 263 263