Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a1259041 authored by Bjorn Helgaas's avatar Bjorn Helgaas
Browse files

Merge branch 'pci/mjg-rom' into for-linus

* pci/mjg-rom:
  radeon: Attempt to use platform-provided ROM image
  nouveau: Attempt to use platform-provided ROM image
  PCI: Add PCI ROM helper for platform-provided ROM images
parents 8bb96604 06a08570
Loading
Loading
Loading
Loading
+17 −0
Original line number Diff line number Diff line
@@ -248,6 +248,22 @@ nouveau_bios_shadow_pci(struct nouveau_bios *bios)
	}
}

static void
nouveau_bios_shadow_platform(struct nouveau_bios *bios)
{
	struct pci_dev *pdev = nv_device(bios)->pdev;
	size_t size;

	void __iomem *rom = pci_platform_rom(pdev, &size);
	if (rom && size) {
		bios->data = kmalloc(size, GFP_KERNEL);
		if (bios->data) {
			memcpy_fromio(bios->data, rom, size);
			bios->size = size;
		}
	}
}

static int
nouveau_bios_score(struct nouveau_bios *bios, const bool writeable)
{
@@ -288,6 +304,7 @@ nouveau_bios_shadow(struct nouveau_bios *bios)
		{ "PROM", nouveau_bios_shadow_prom, false, 0, 0, NULL },
		{ "ACPI", nouveau_bios_shadow_acpi, true, 0, 0, NULL },
		{ "PCIROM", nouveau_bios_shadow_pci, true, 0, 0, NULL },
		{ "PLATFORM", nouveau_bios_shadow_platform, true, 0, 0, NULL },
		{}
	};
	struct methods *mthd, *best;
+26 −0
Original line number Diff line number Diff line
@@ -99,6 +99,29 @@ static bool radeon_read_bios(struct radeon_device *rdev)
	return true;
}

static bool radeon_read_platform_bios(struct radeon_device *rdev)
{
	uint8_t __iomem *bios;
	size_t size;

	rdev->bios = NULL;

	bios = pci_platform_rom(rdev->pdev, &size);
	if (!bios) {
		return false;
	}

	if (size == 0 || bios[0] != 0x55 || bios[1] != 0xaa) {
		return false;
	}
	rdev->bios = kmemdup(bios, size, GFP_KERNEL);
	if (rdev->bios == NULL) {
		return false;
	}

	return true;
}

#ifdef CONFIG_ACPI
/* ATRM is used to get the BIOS on the discrete cards in
 * dual-gpu systems.
@@ -620,6 +643,9 @@ bool radeon_get_bios(struct radeon_device *rdev)
	if (r == false) {
		r = radeon_read_disabled_bios(rdev);
	}
	if (r == false) {
		r = radeon_read_platform_bios(rdev);
	}
	if (r == false || rdev->bios == NULL) {
		DRM_ERROR("Unable to locate a BIOS ROM\n");
		rdev->bios = NULL;
+31 −36
Original line number Diff line number Diff line
@@ -100,27 +100,6 @@ size_t pci_get_rom_size(struct pci_dev *pdev, void __iomem *rom, size_t size)
	return min((size_t)(image - rom), size);
}

static loff_t pci_find_rom(struct pci_dev *pdev, size_t *size)
{
	struct resource *res = &pdev->resource[PCI_ROM_RESOURCE];
	loff_t start;

	/* assign the ROM an address if it doesn't have one */
	if (res->parent == NULL && pci_assign_resource(pdev, PCI_ROM_RESOURCE))
		return 0;
	start = pci_resource_start(pdev, PCI_ROM_RESOURCE);
	*size = pci_resource_len(pdev, PCI_ROM_RESOURCE);

	if (*size == 0)
		return 0;

	/* Enable ROM space decodes */
	if (pci_enable_rom(pdev))
		return 0;

	return start;
}

/**
 * pci_map_rom - map a PCI ROM to kernel space
 * @pdev: pointer to pci device struct
@@ -135,7 +114,7 @@ static loff_t pci_find_rom(struct pci_dev *pdev, size_t *size)
void __iomem *pci_map_rom(struct pci_dev *pdev, size_t *size)
{
	struct resource *res = &pdev->resource[PCI_ROM_RESOURCE];
	loff_t start = 0;
	loff_t start;
	void __iomem *rom;

	/*
@@ -154,20 +133,20 @@ void __iomem *pci_map_rom(struct pci_dev *pdev, size_t *size)
			return (void __iomem *)(unsigned long)
				pci_resource_start(pdev, PCI_ROM_RESOURCE);
		} else {
			start = pci_find_rom(pdev, size);
		}
	}

	/*
	 * Some devices may provide ROMs via a source other than the BAR
	 */
	if (!start && pdev->rom && pdev->romlen) {
		*size = pdev->romlen;
		return phys_to_virt(pdev->rom);
	}
			/* assign the ROM an address if it doesn't have one */
			if (res->parent == NULL &&
			    pci_assign_resource(pdev,PCI_ROM_RESOURCE))
				return NULL;
			start = pci_resource_start(pdev, PCI_ROM_RESOURCE);
			*size = pci_resource_len(pdev, PCI_ROM_RESOURCE);
			if (*size == 0)
				return NULL;

	if (!start)
			/* Enable ROM space decodes */
			if (pci_enable_rom(pdev))
				return NULL;
		}
	}

	rom = ioremap(start, *size);
	if (!rom) {
@@ -202,7 +181,6 @@ void pci_unmap_rom(struct pci_dev *pdev, void __iomem *rom)
	if (res->flags & (IORESOURCE_ROM_COPY | IORESOURCE_ROM_BIOS_COPY))
		return;

	if (!pdev->rom || !pdev->romlen)
	iounmap(rom);

	/* Disable again before continuing, leave enabled if pci=rom */
@@ -227,7 +205,24 @@ void pci_cleanup_rom(struct pci_dev *pdev)
	}
}

/**
 * pci_platform_rom - provides a pointer to any ROM image provided by the
 * platform
 * @pdev: pointer to pci device struct
 * @size: pointer to receive size of pci window over ROM
 */
void __iomem *pci_platform_rom(struct pci_dev *pdev, size_t *size)
{
	if (pdev->rom && pdev->romlen) {
		*size = pdev->romlen;
		return phys_to_virt((phys_addr_t)pdev->rom);
	}

	return NULL;
}

EXPORT_SYMBOL(pci_map_rom);
EXPORT_SYMBOL(pci_unmap_rom);
EXPORT_SYMBOL_GPL(pci_enable_rom);
EXPORT_SYMBOL_GPL(pci_disable_rom);
EXPORT_SYMBOL(pci_platform_rom);
+1 −0
Original line number Diff line number Diff line
@@ -916,6 +916,7 @@ void pci_disable_rom(struct pci_dev *pdev);
void __iomem __must_check *pci_map_rom(struct pci_dev *pdev, size_t *size);
void pci_unmap_rom(struct pci_dev *pdev, void __iomem *rom);
size_t pci_get_rom_size(struct pci_dev *pdev, void __iomem *rom, size_t size);
void __iomem __must_check *pci_platform_rom(struct pci_dev *pdev, size_t *size);

/* Power management related routines */
int pci_save_state(struct pci_dev *dev);