diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c index ad2f3b0d922f..c08368c03dad 100644 --- a/drivers/gpu/drm/i915/intel_bios.c +++ b/drivers/gpu/drm/i915/intel_bios.c @@ -447,6 +447,12 @@ parse_general_definitions(struct drm_i915_private *dev_priv, } } +static union child_device_config * +child_device_ptr(struct bdb_general_definitions *p_defs, int i) +{ + return (void *) &p_defs->devices[i * p_defs->child_dev_size]; +} + static void parse_sdvo_device_mapping(struct drm_i915_private *dev_priv, struct bdb_header *bdb) @@ -476,10 +482,10 @@ parse_sdvo_device_mapping(struct drm_i915_private *dev_priv, block_size = get_blocksize(p_defs); /* get the number of child device */ child_device_num = (block_size - sizeof(*p_defs)) / - sizeof(*p_child); + p_defs->child_dev_size; count = 0; for (i = 0; i < child_device_num; i++) { - p_child = &(p_defs->devices[i]); + p_child = child_device_ptr(p_defs, i); if (!p_child->old.device_type) { /* skip the device block if device type is invalid */ continue; @@ -1067,25 +1073,19 @@ parse_device_mapping(struct drm_i915_private *dev_priv, DRM_DEBUG_KMS("No general definition block is found, no devices defined.\n"); return; } - /* judge whether the size of child device meets the requirements. - * If the child device size obtained from general definition block - * is different with sizeof(struct child_device_config), skip the - * parsing of sdvo device info - */ - if (p_defs->child_dev_size != sizeof(*p_child)) { - /* different child dev size . Ignore it */ - DRM_DEBUG_KMS("different child size is found. Invalid.\n"); + if (p_defs->child_dev_size < sizeof(*p_child)) { + DRM_ERROR("General definiton block child device size is too small.\n"); return; } /* get the block size of general definitions */ block_size = get_blocksize(p_defs); /* get the number of child device */ child_device_num = (block_size - sizeof(*p_defs)) / - sizeof(*p_child); + p_defs->child_dev_size; count = 0; /* get the number of child device that is present */ for (i = 0; i < child_device_num; i++) { - p_child = &(p_defs->devices[i]); + p_child = child_device_ptr(p_defs, i); if (!p_child->common.device_type) { /* skip the device block if device type is invalid */ continue; @@ -1105,7 +1105,7 @@ parse_device_mapping(struct drm_i915_private *dev_priv, dev_priv->vbt.child_dev_num = count; count = 0; for (i = 0; i < child_device_num; i++) { - p_child = &(p_defs->devices[i]); + p_child = child_device_ptr(p_defs, i); if (!p_child->common.device_type) { /* skip the device block if device type is invalid */ continue; diff --git a/drivers/gpu/drm/i915/intel_bios.h b/drivers/gpu/drm/i915/intel_bios.h index 6afd5be33367..af0b47652752 100644 --- a/drivers/gpu/drm/i915/intel_bios.h +++ b/drivers/gpu/drm/i915/intel_bios.h @@ -277,9 +277,9 @@ struct bdb_general_definitions { * And the device num is related with the size of general definition * block. It is obtained by using the following formula: * number = (block_size - sizeof(bdb_general_definitions))/ - * sizeof(child_device_config); + * defs->child_dev_size; */ - union child_device_config devices[0]; + uint8_t devices[0]; } __packed; /* Mask for DRRS / Panel Channel / SSC / BLT control bits extraction */