drm/i915/bios: fold pci rom map/unmap into copy function

We don't need to keep the pci rom mapped during the entire
intel_bios_init() anymore. Move it to the previous copy_vbt() function
and rename it to oprom_get_vbt() since now it's responsible to to all
operations related to get the vbt from the oprom.

v2: fix double __iomem attribute detected by sparse
v3: fix missing unmap on success (Ville)

Signed-off-by: Lucas De Marchi <lucas.demarchi@intel.com>
Reviewed-by: Jani Nikula <jani.nikula@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20191126225110.8127-3-lucas.demarchi@intel.com
This commit is contained in:
Lucas De Marchi 2019-11-26 14:51:09 -08:00
parent fd0186ce18
commit 2cded152ad
1 changed files with 21 additions and 21 deletions

View File

@ -1925,12 +1925,17 @@ bool intel_bios_is_valid_vbt(const void *buf, size_t size)
return vbt; return vbt;
} }
static struct vbt_header *copy_vbt(void __iomem *oprom, size_t size) static struct vbt_header *oprom_get_vbt(struct drm_i915_private *dev_priv)
{ {
void __iomem *p = NULL; struct pci_dev *pdev = dev_priv->drm.pdev;
void __iomem *p = NULL, *oprom;
struct vbt_header *vbt; struct vbt_header *vbt;
u16 vbt_size; u16 vbt_size;
size_t i; size_t i, size;
oprom = pci_map_rom(pdev, &size);
if (!oprom)
return NULL;
/* Scour memory looking for the VBT signature. */ /* Scour memory looking for the VBT signature. */
for (i = 0; i + 4 < size; i++) { for (i = 0; i + 4 < size; i++) {
@ -1943,33 +1948,37 @@ static struct vbt_header *copy_vbt(void __iomem *oprom, size_t size)
} }
if (!p) if (!p)
return NULL; goto err_unmap_oprom;
if (sizeof(struct vbt_header) > size) { if (sizeof(struct vbt_header) > size) {
DRM_DEBUG_DRIVER("VBT header incomplete\n"); DRM_DEBUG_DRIVER("VBT header incomplete\n");
return NULL; goto err_unmap_oprom;
} }
vbt_size = ioread16(p + offsetof(struct vbt_header, vbt_size)); vbt_size = ioread16(p + offsetof(struct vbt_header, vbt_size));
if (vbt_size > size) { if (vbt_size > size) {
DRM_DEBUG_DRIVER("VBT incomplete (vbt_size overflows)\n"); DRM_DEBUG_DRIVER("VBT incomplete (vbt_size overflows)\n");
return NULL; goto err_unmap_oprom;
} }
/* The rest will be validated by intel_bios_is_valid_vbt() */ /* The rest will be validated by intel_bios_is_valid_vbt() */
vbt = kmalloc(vbt_size, GFP_KERNEL); vbt = kmalloc(vbt_size, GFP_KERNEL);
if (!vbt) if (!vbt)
return NULL; goto err_unmap_oprom;
memcpy_fromio(vbt, p, vbt_size); memcpy_fromio(vbt, p, vbt_size);
if (!intel_bios_is_valid_vbt(vbt, vbt_size)) if (!intel_bios_is_valid_vbt(vbt, vbt_size))
goto err_free_vbt; goto err_free_vbt;
pci_unmap_rom(pdev, oprom);
return vbt; return vbt;
err_free_vbt: err_free_vbt:
kfree(vbt); kfree(vbt);
err_unmap_oprom:
pci_unmap_rom(pdev, oprom);
return NULL; return NULL;
} }
@ -1984,10 +1993,9 @@ err_free_vbt:
*/ */
void intel_bios_init(struct drm_i915_private *dev_priv) void intel_bios_init(struct drm_i915_private *dev_priv)
{ {
struct pci_dev *pdev = dev_priv->drm.pdev;
const struct vbt_header *vbt = dev_priv->opregion.vbt; const struct vbt_header *vbt = dev_priv->opregion.vbt;
struct vbt_header *oprom_vbt = NULL;
const struct bdb_header *bdb; const struct bdb_header *bdb;
u8 __iomem *oprom = NULL;
INIT_LIST_HEAD(&dev_priv->vbt.display_devices); INIT_LIST_HEAD(&dev_priv->vbt.display_devices);
@ -2000,15 +2008,11 @@ void intel_bios_init(struct drm_i915_private *dev_priv)
/* If the OpRegion does not have VBT, look in PCI ROM. */ /* If the OpRegion does not have VBT, look in PCI ROM. */
if (!vbt) { if (!vbt) {
size_t size; oprom_vbt = oprom_get_vbt(dev_priv);
if (!oprom_vbt)
oprom = pci_map_rom(pdev, &size);
if (!oprom)
goto out; goto out;
vbt = copy_vbt(oprom, size); vbt = oprom_vbt;
if (!vbt)
goto out;
DRM_DEBUG_KMS("Found valid VBT in PCI ROM\n"); DRM_DEBUG_KMS("Found valid VBT in PCI ROM\n");
} }
@ -2042,11 +2046,7 @@ out:
init_vbt_missing_defaults(dev_priv); init_vbt_missing_defaults(dev_priv);
} }
if (oprom) kfree(oprom_vbt);
pci_unmap_rom(pdev, oprom);
if (vbt != dev_priv->opregion.vbt)
kfree(vbt);
} }
/** /**