Skip to content

Commit

Permalink
Merge branch 'pci/resource' into next
Browse files Browse the repository at this point in the history
* pci/resource:
  PCI: Simplify pci_create_attr() control flow
  PCI: Don't leak memory if sysfs_create_bin_file() fails
  PCI: Simplify sysfs ROM cleanup
  PCI: Remove unused IORESOURCE_ROM_COPY and IORESOURCE_ROM_BIOS_COPY
  MIPS: Loongson 3: Keep CPU physical (not virtual) addresses in shadow ROM resource
  MIPS: Loongson 3: Use temporary struct resource * to avoid repetition
  ia64/PCI: Keep CPU physical (not virtual) addresses in shadow ROM resource
  ia64/PCI: Use ioremap() instead of open-coded equivalent
  ia64/PCI: Use temporary struct resource * to avoid repetition
  PCI: Clean up pci_map_rom() whitespace
  PCI: Remove arch-specific IORESOURCE_ROM_SHADOW size from sysfs
  PCI: Set ROM shadow location in arch code, not in PCI core
  PCI: Don't enable/disable ROM BAR if we're using a RAM shadow copy
  PCI: Don't assign or reassign immutable resources
  PCI: Mark shadow copy of VGA ROM as IORESOURCE_PCI_FIXED
  x86/PCI: Mark Broadwell-EP Home Agent & PCU as having non-compliant BARs
  PCI: Disable IO/MEM decoding for devices with non-compliant BARs
  • Loading branch information
bjorn-helgaas committed Mar 15, 2016
2 parents cfeb813 + bd5174d commit 6e6f498
Show file tree
Hide file tree
Showing 12 changed files with 162 additions and 160 deletions.
21 changes: 16 additions & 5 deletions arch/ia64/pci/fixup.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,21 +17,22 @@
*
* The standard boot ROM sequence for an x86 machine uses the BIOS
* to select an initial video card for boot display. This boot video
* card will have it's BIOS copied to C0000 in system RAM.
* card will have its BIOS copied to 0xC0000 in system RAM.
* IORESOURCE_ROM_SHADOW is used to associate the boot video
* card with this copy. On laptops this copy has to be used since
* the main ROM may be compressed or combined with another image.
* See pci_map_rom() for use of this flag. Before marking the device
* with IORESOURCE_ROM_SHADOW check if a vga_default_device is already set
* by either arch cde or vga-arbitration, if so only apply the fixup to this
* already determined primary video card.
* by either arch code or vga-arbitration; if so only apply the fixup to this
* already-determined primary video card.
*/

static void pci_fixup_video(struct pci_dev *pdev)
{
struct pci_dev *bridge;
struct pci_bus *bus;
u16 config;
struct resource *res;

if ((strcmp(ia64_platform_name, "dig") != 0)
&& (strcmp(ia64_platform_name, "hpzx1") != 0))
Expand Down Expand Up @@ -61,8 +62,18 @@ static void pci_fixup_video(struct pci_dev *pdev)
if (!vga_default_device() || pdev == vga_default_device()) {
pci_read_config_word(pdev, PCI_COMMAND, &config);
if (config & (PCI_COMMAND_IO | PCI_COMMAND_MEMORY)) {
pdev->resource[PCI_ROM_RESOURCE].flags |= IORESOURCE_ROM_SHADOW;
dev_printk(KERN_DEBUG, &pdev->dev, "Video device with shadowed ROM\n");
res = &pdev->resource[PCI_ROM_RESOURCE];

pci_disable_rom(pdev);
if (res->parent)
release_resource(res);

res->start = 0xC0000;
res->end = res->start + 0x20000 - 1;
res->flags = IORESOURCE_MEM | IORESOURCE_ROM_SHADOW |
IORESOURCE_PCI_FIXED;
dev_info(&pdev->dev, "Video device with shadowed ROM at %pR\n",
res);
}
}
}
Expand Down
22 changes: 13 additions & 9 deletions arch/ia64/sn/kernel/io_acpi_init.c
Original file line number Diff line number Diff line change
Expand Up @@ -429,7 +429,8 @@ sn_acpi_slot_fixup(struct pci_dev *dev)
void __iomem *addr;
struct pcidev_info *pcidev_info = NULL;
struct sn_irq_info *sn_irq_info = NULL;
size_t image_size, size;
struct resource *res;
size_t size;

if (sn_acpi_get_pcidev_info(dev, &pcidev_info, &sn_irq_info)) {
panic("%s: Failure obtaining pcidev_info for %s\n",
Expand All @@ -443,17 +444,20 @@ sn_acpi_slot_fixup(struct pci_dev *dev)
* of the shadowed copy, and the actual length of the ROM image.
*/
size = pci_resource_len(dev, PCI_ROM_RESOURCE);
addr = ioremap(pcidev_info->pdi_pio_mapped_addr[PCI_ROM_RESOURCE],
size);
image_size = pci_get_rom_size(dev, addr, size);
dev->resource[PCI_ROM_RESOURCE].start = (unsigned long) addr;
dev->resource[PCI_ROM_RESOURCE].end =
(unsigned long) addr + image_size - 1;
dev->resource[PCI_ROM_RESOURCE].flags |= IORESOURCE_ROM_BIOS_COPY;

res = &dev->resource[PCI_ROM_RESOURCE];

pci_disable_rom(dev);
if (res->parent)
release_resource(res);

res->start = pcidev_info->pdi_pio_mapped_addr[PCI_ROM_RESOURCE];
res->end = res->start + size - 1;
res->flags = IORESOURCE_MEM | IORESOURCE_ROM_SHADOW |
IORESOURCE_PCI_FIXED;
}
sn_pci_fixup_slot(dev, pcidev_info, sn_irq_info);
}

EXPORT_SYMBOL(sn_acpi_slot_fixup);


Expand Down
51 changes: 19 additions & 32 deletions arch/ia64/sn/kernel/io_init.c
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,8 @@ void
sn_io_slot_fixup(struct pci_dev *dev)
{
int idx;
unsigned long addr, end, size, start;
struct resource *res;
unsigned long addr, size;
struct pcidev_info *pcidev_info;
struct sn_irq_info *sn_irq_info;
int status;
Expand All @@ -175,55 +176,41 @@ sn_io_slot_fixup(struct pci_dev *dev)

/* Copy over PIO Mapped Addresses */
for (idx = 0; idx <= PCI_ROM_RESOURCE; idx++) {

if (!pcidev_info->pdi_pio_mapped_addr[idx]) {
if (!pcidev_info->pdi_pio_mapped_addr[idx])
continue;
}

start = dev->resource[idx].start;
end = dev->resource[idx].end;
size = end - start;
if (size == 0) {
res = &dev->resource[idx];

size = res->end - res->start;
if (size == 0)
continue;
}
addr = pcidev_info->pdi_pio_mapped_addr[idx];
addr = ((addr << 4) >> 4) | __IA64_UNCACHED_OFFSET;
dev->resource[idx].start = addr;
dev->resource[idx].end = addr + size;

res->start = pcidev_info->pdi_pio_mapped_addr[idx];
res->end = addr + size;

/*
* if it's already in the device structure, remove it before
* inserting
*/
if (dev->resource[idx].parent && dev->resource[idx].parent->child)
release_resource(&dev->resource[idx]);
if (res->parent && res->parent->child)
release_resource(res);

if (dev->resource[idx].flags & IORESOURCE_IO)
insert_resource(&ioport_resource, &dev->resource[idx]);
if (res->flags & IORESOURCE_IO)
insert_resource(&ioport_resource, res);
else
insert_resource(&iomem_resource, &dev->resource[idx]);
insert_resource(&iomem_resource, res);
/*
* If ROM, set the actual ROM image size, and mark as
* shadowed in PROM.
* If ROM, mark as shadowed in PROM.
*/
if (idx == PCI_ROM_RESOURCE) {
size_t image_size;
void __iomem *rom;

rom = ioremap(pci_resource_start(dev, PCI_ROM_RESOURCE),
size + 1);
image_size = pci_get_rom_size(dev, rom, size + 1);
dev->resource[PCI_ROM_RESOURCE].end =
dev->resource[PCI_ROM_RESOURCE].start +
image_size - 1;
dev->resource[PCI_ROM_RESOURCE].flags |=
IORESOURCE_ROM_BIOS_COPY;
pci_disable_rom(dev);
res->flags = IORESOURCE_MEM | IORESOURCE_ROM_SHADOW |
IORESOURCE_PCI_FIXED;
}
}

sn_pci_fixup_slot(dev, pcidev_info, sn_irq_info);
}

EXPORT_SYMBOL(sn_io_slot_fixup);

/*
Expand Down
19 changes: 12 additions & 7 deletions arch/mips/pci/fixup-loongson3.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,20 +40,25 @@ int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)

static void pci_fixup_radeon(struct pci_dev *pdev)
{
if (pdev->resource[PCI_ROM_RESOURCE].start)
struct resource *res = &pdev->resource[PCI_ROM_RESOURCE];

if (res->start)
return;

if (!loongson_sysconf.vgabios_addr)
return;

pdev->resource[PCI_ROM_RESOURCE].start =
loongson_sysconf.vgabios_addr;
pdev->resource[PCI_ROM_RESOURCE].end =
loongson_sysconf.vgabios_addr + 256*1024 - 1;
pdev->resource[PCI_ROM_RESOURCE].flags |= IORESOURCE_ROM_COPY;
pci_disable_rom(pdev);
if (res->parent)
release_resource(res);

res->start = virt_to_phys((void *) loongson_sysconf.vgabios_addr);
res->end = res->start + 256*1024 - 1;
res->flags = IORESOURCE_MEM | IORESOURCE_ROM_SHADOW |
IORESOURCE_PCI_FIXED;

dev_info(&pdev->dev, "BAR %d: assigned %pR for Radeon ROM\n",
PCI_ROM_RESOURCE, &pdev->resource[PCI_ROM_RESOURCE]);
PCI_ROM_RESOURCE, res);
}

DECLARE_PCI_FIXUP_CLASS_FINAL(PCI_VENDOR_ID_ATI, PCI_ANY_ID,
Expand Down
28 changes: 23 additions & 5 deletions arch/x86/pci/fixup.c
Original file line number Diff line number Diff line change
Expand Up @@ -297,21 +297,22 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_MCH_PC1, pcie_r
*
* The standard boot ROM sequence for an x86 machine uses the BIOS
* to select an initial video card for boot display. This boot video
* card will have it's BIOS copied to C0000 in system RAM.
* card will have its BIOS copied to 0xC0000 in system RAM.
* IORESOURCE_ROM_SHADOW is used to associate the boot video
* card with this copy. On laptops this copy has to be used since
* the main ROM may be compressed or combined with another image.
* See pci_map_rom() for use of this flag. Before marking the device
* with IORESOURCE_ROM_SHADOW check if a vga_default_device is already set
* by either arch cde or vga-arbitration, if so only apply the fixup to this
* already determined primary video card.
* by either arch code or vga-arbitration; if so only apply the fixup to this
* already-determined primary video card.
*/

static void pci_fixup_video(struct pci_dev *pdev)
{
struct pci_dev *bridge;
struct pci_bus *bus;
u16 config;
struct resource *res;

/* Is VGA routed to us? */
bus = pdev->bus;
Expand All @@ -336,8 +337,18 @@ static void pci_fixup_video(struct pci_dev *pdev)
if (!vga_default_device() || pdev == vga_default_device()) {
pci_read_config_word(pdev, PCI_COMMAND, &config);
if (config & (PCI_COMMAND_IO | PCI_COMMAND_MEMORY)) {
pdev->resource[PCI_ROM_RESOURCE].flags |= IORESOURCE_ROM_SHADOW;
dev_printk(KERN_DEBUG, &pdev->dev, "Video device with shadowed ROM\n");
res = &pdev->resource[PCI_ROM_RESOURCE];

pci_disable_rom(pdev);
if (res->parent)
release_resource(res);

res->start = 0xC0000;
res->end = res->start + 0x20000 - 1;
res->flags = IORESOURCE_MEM | IORESOURCE_ROM_SHADOW |
IORESOURCE_PCI_FIXED;
dev_info(&pdev->dev, "Video device with shadowed ROM at %pR\n",
res);
}
}
}
Expand Down Expand Up @@ -540,3 +551,10 @@ static void twinhead_reserve_killing_zone(struct pci_dev *dev)
}
}
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x27B9, twinhead_reserve_killing_zone);

static void pci_bdwep_bar(struct pci_dev *dev)
{
dev->non_compliant_bars = 1;
}
DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x6fa0, pci_bdwep_bar);
DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x6fc0, pci_bdwep_bar);
72 changes: 32 additions & 40 deletions drivers/pci/pci-sysfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -1138,33 +1138,36 @@ static int pci_create_attr(struct pci_dev *pdev, int num, int write_combine)
/* allocate attribute structure, piggyback attribute name */
int name_len = write_combine ? 13 : 10;
struct bin_attribute *res_attr;
char *res_attr_name;
int retval;

res_attr = kzalloc(sizeof(*res_attr) + name_len, GFP_ATOMIC);
if (res_attr) {
char *res_attr_name = (char *)(res_attr + 1);

sysfs_bin_attr_init(res_attr);
if (write_combine) {
pdev->res_attr_wc[num] = res_attr;
sprintf(res_attr_name, "resource%d_wc", num);
res_attr->mmap = pci_mmap_resource_wc;
} else {
pdev->res_attr[num] = res_attr;
sprintf(res_attr_name, "resource%d", num);
res_attr->mmap = pci_mmap_resource_uc;
}
if (pci_resource_flags(pdev, num) & IORESOURCE_IO) {
res_attr->read = pci_read_resource_io;
res_attr->write = pci_write_resource_io;
}
res_attr->attr.name = res_attr_name;
res_attr->attr.mode = S_IRUSR | S_IWUSR;
res_attr->size = pci_resource_len(pdev, num);
res_attr->private = &pdev->resource[num];
retval = sysfs_create_bin_file(&pdev->dev.kobj, res_attr);
} else
retval = -ENOMEM;
if (!res_attr)
return -ENOMEM;

res_attr_name = (char *)(res_attr + 1);

sysfs_bin_attr_init(res_attr);
if (write_combine) {
pdev->res_attr_wc[num] = res_attr;
sprintf(res_attr_name, "resource%d_wc", num);
res_attr->mmap = pci_mmap_resource_wc;
} else {
pdev->res_attr[num] = res_attr;
sprintf(res_attr_name, "resource%d", num);
res_attr->mmap = pci_mmap_resource_uc;
}
if (pci_resource_flags(pdev, num) & IORESOURCE_IO) {
res_attr->read = pci_read_resource_io;
res_attr->write = pci_write_resource_io;
}
res_attr->attr.name = res_attr_name;
res_attr->attr.mode = S_IRUSR | S_IWUSR;
res_attr->size = pci_resource_len(pdev, num);
res_attr->private = &pdev->resource[num];
retval = sysfs_create_bin_file(&pdev->dev.kobj, res_attr);
if (retval)
kfree(res_attr);

return retval;
}
Expand Down Expand Up @@ -1360,7 +1363,7 @@ static int pci_create_capabilities_sysfs(struct pci_dev *dev)
int __must_check pci_create_sysfs_dev_files(struct pci_dev *pdev)
{
int retval;
int rom_size = 0;
int rom_size;
struct bin_attribute *attr;

if (!sysfs_initialized)
Expand All @@ -1377,12 +1380,8 @@ int __must_check pci_create_sysfs_dev_files(struct pci_dev *pdev)
if (retval)
goto err_config_file;

if (pci_resource_len(pdev, PCI_ROM_RESOURCE))
rom_size = pci_resource_len(pdev, PCI_ROM_RESOURCE);
else if (pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW)
rom_size = 0x20000;

/* If the device has a ROM, try to expose it in sysfs. */
rom_size = pci_resource_len(pdev, PCI_ROM_RESOURCE);
if (rom_size) {
attr = kzalloc(sizeof(*attr), GFP_ATOMIC);
if (!attr) {
Expand Down Expand Up @@ -1413,7 +1412,7 @@ int __must_check pci_create_sysfs_dev_files(struct pci_dev *pdev)
return 0;

err_rom_file:
if (rom_size) {
if (pdev->rom_attr) {
sysfs_remove_bin_file(&pdev->dev.kobj, pdev->rom_attr);
kfree(pdev->rom_attr);
pdev->rom_attr = NULL;
Expand Down Expand Up @@ -1451,8 +1450,6 @@ static void pci_remove_capabilities_sysfs(struct pci_dev *dev)
*/
void pci_remove_sysfs_dev_files(struct pci_dev *pdev)
{
int rom_size = 0;

if (!sysfs_initialized)
return;

Expand All @@ -1465,18 +1462,13 @@ void pci_remove_sysfs_dev_files(struct pci_dev *pdev)

pci_remove_resource_files(pdev);

if (pci_resource_len(pdev, PCI_ROM_RESOURCE))
rom_size = pci_resource_len(pdev, PCI_ROM_RESOURCE);
else if (pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW)
rom_size = 0x20000;

if (rom_size && pdev->rom_attr) {
if (pdev->rom_attr) {
sysfs_remove_bin_file(&pdev->dev.kobj, pdev->rom_attr);
kfree(pdev->rom_attr);
pdev->rom_attr = NULL;
}

pci_remove_firmware_label_files(pdev);

}

static int __init pci_sysfs_init(void)
Expand Down
Loading

0 comments on commit 6e6f498

Please sign in to comment.