This cherry-picked upstream patch removes an infinite

Surbhi Palande surbhi.palande at canonical.com
Fri Feb 12 10:34:33 UTC 2010


Hi,

Apologies for sending this patch 3 times. There was some problem with
my smtp settings :( Sorry !

Warm Regards,
Surbhi.




Surbhi Palande wrote:
> From 2f8055156e9160f3d83e56122c90c3ece2e09819 Mon Sep 17 00:00:00 2001
> From: Adam Jackson <ajax at redhat.com>
> Date: Thu, 3 Dec 2009 17:44:36 -0500
> Subject: [PATCH] [PATCH] UBUNTU [Lucid]: [Upstream] drm/edid: Unify detailed block parsing between base and extension blocks
> 
> BugLink: http://bugs.launchpad.net/bugs/500999
> 
> Also fix an embarassing bug in standard timing subblock parsing that
> would result in an infinite loop.
> 
> Signed-off-by: Adam Jackson <ajax at redhat.com>
> Signed-off-by: Dave Airlie <airlied at redhat.com>
> (cherry picked from commit 9cf00977da092096c7a983276dad8b3002d23a99)
> 
> Signed-off-by: Surbhi Palande <Surbhi.Palande at canonical.com>
> ---
>  drivers/gpu/drm/drm_edid.c |  163 ++++++++++++++++---------------------------
>  1 files changed, 61 insertions(+), 102 deletions(-)
> 
> diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
> index b54ba63..d5671c3 100644
> --- a/drivers/gpu/drm/drm_edid.c
> +++ b/drivers/gpu/drm/drm_edid.c
> @@ -834,8 +834,57 @@ static int add_standard_modes(struct drm_connector *connector, struct edid *edid
>  	return modes;
>  }
>  
> +static int add_detailed_modes(struct drm_connector *connector,
> +			      struct detailed_timing *timing,
> +			      struct edid *edid, u32 quirks, int preferred)
> +{
> +	int i, modes = 0;
> +	struct detailed_non_pixel *data = &timing->data.other_data;
> +	int timing_level = standard_timing_level(edid);
> +	struct drm_display_mode *newmode;
> +	struct drm_device *dev = connector->dev;
> +
> +	if (timing->pixel_clock) {
> +		newmode = drm_mode_detailed(dev, edid, timing, quirks);
> +		if (!newmode)
> +			return 0;
> +
> +		if (preferred)
> +			newmode->type |= DRM_MODE_TYPE_PREFERRED;
> +
> +		drm_mode_probed_add(connector, newmode);
> +		return 1;
> +	}
> +
> +	/* other timing types */
> +	switch (data->type) {
> +	case EDID_DETAIL_MONITOR_RANGE:
> +		/* Get monitor range data */
> +		break;
> +	case EDID_DETAIL_STD_MODES:
> +		/* Six modes per detailed section */
> +		for (i = 0; i < 6; i++) {
> +			struct std_timing *std;
> +			struct drm_display_mode *newmode;
> +
> +			std = &data->data.timings[i];
> +			newmode = drm_mode_std(dev, std, edid->revision,
> +					       timing_level);
> +			if (newmode) {
> +				drm_mode_probed_add(connector, newmode);
> +				modes++;
> +			}
> +		}
> +		break;
> +	default:
> +		break;
> +	}
> +
> +	return modes;
> +}
> +
>  /**
> - * add_detailed_modes - get detailed mode info from EDID data
> + * add_detailed_info - get detailed mode info from EDID data
>   * @connector: attached connector
>   * @edid: EDID block to scan
>   * @quirks: quirks to apply
> @@ -846,67 +895,24 @@ static int add_standard_modes(struct drm_connector *connector, struct edid *edid
>  static int add_detailed_info(struct drm_connector *connector,
>  			     struct edid *edid, u32 quirks)
>  {
> -	struct drm_device *dev = connector->dev;
> -	int i, j, modes = 0;
> -	int timing_level;
> -
> -	timing_level = standard_timing_level(edid);
> +	int i, modes = 0;
>  
>  	for (i = 0; i < EDID_DETAILED_TIMINGS; i++) {
>  		struct detailed_timing *timing = &edid->detailed_timings[i];
> -		struct detailed_non_pixel *data = &timing->data.other_data;
> -		struct drm_display_mode *newmode;
> -
> -		/* X server check is version 1.1 or higher */
> -		if (edid->version == 1 && edid->revision >= 1 &&
> -		    !timing->pixel_clock) {
> -			/* Other timing or info */
> -			switch (data->type) {
> -			case EDID_DETAIL_MONITOR_SERIAL:
> -				break;
> -			case EDID_DETAIL_MONITOR_STRING:
> -				break;
> -			case EDID_DETAIL_MONITOR_RANGE:
> -				/* Get monitor range data */
> -				break;
> -			case EDID_DETAIL_MONITOR_NAME:
> -				break;
> -			case EDID_DETAIL_MONITOR_CPDATA:
> -				break;
> -			case EDID_DETAIL_STD_MODES:
> -				for (j = 0; j < 6; i++) {
> -					struct std_timing *std;
> -					struct drm_display_mode *newmode;
> -
> -					std = &data->data.timings[j];
> -					newmode = drm_mode_std(dev, std,
> -							       edid->revision,
> -							       timing_level);
> -					if (newmode) {
> -						drm_mode_probed_add(connector, newmode);
> -						modes++;
> -					}
> -				}
> -				break;
> -			default:
> -				break;
> -			}
> -		} else {
> -			newmode = drm_mode_detailed(dev, edid, timing, quirks);
> -			if (!newmode)
> -				continue;
> +		int preferred = (i == 0) && (edid->features & DRM_EDID_FEATURE_PREFERRED_TIMING);
>  
> -			/* First detailed mode is preferred */
> -			if (i == 0 && (edid->features & DRM_EDID_FEATURE_PREFERRED_TIMING))
> -				newmode->type |= DRM_MODE_TYPE_PREFERRED;
> -			drm_mode_probed_add(connector, newmode);
> +		/* In 1.0, only timings are allowed */
> +		if (!timing->pixel_clock && edid->version == 1 &&
> +			edid->revision == 0)
> +			continue;
>  
> -			modes++;
> -		}
> +		modes += add_detailed_modes(connector, timing, edid, quirks,
> +					    preferred);
>  	}
>  
>  	return modes;
>  }
> +
>  /**
>   * add_detailed_mode_eedid - get detailed mode info from addtional timing
>   * 			EDID block
> @@ -920,12 +926,9 @@ static int add_detailed_info(struct drm_connector *connector,
>  static int add_detailed_info_eedid(struct drm_connector *connector,
>  			     struct edid *edid, u32 quirks)
>  {
> -	struct drm_device *dev = connector->dev;
> -	int i, j, modes = 0;
> +	int i, modes = 0;
>  	char *edid_ext = NULL;
>  	struct detailed_timing *timing;
> -	struct detailed_non_pixel *data;
> -	struct drm_display_mode *newmode;
>  	int edid_ext_num;
>  	int start_offset, end_offset;
>  	int timing_level;
> @@ -976,51 +979,7 @@ static int add_detailed_info_eedid(struct drm_connector *connector,
>  	for (i = start_offset; i < end_offset;
>  			i += sizeof(struct detailed_timing)) {
>  		timing = (struct detailed_timing *)(edid_ext + i);
> -		data = &timing->data.other_data;
> -		/* Detailed mode timing */
> -		if (timing->pixel_clock) {
> -			newmode = drm_mode_detailed(dev, edid, timing, quirks);
> -			if (!newmode)
> -				continue;
> -
> -			drm_mode_probed_add(connector, newmode);
> -
> -			modes++;
> -			continue;
> -		}
> -
> -		/* Other timing or info */
> -		switch (data->type) {
> -		case EDID_DETAIL_MONITOR_SERIAL:
> -			break;
> -		case EDID_DETAIL_MONITOR_STRING:
> -			break;
> -		case EDID_DETAIL_MONITOR_RANGE:
> -			/* Get monitor range data */
> -			break;
> -		case EDID_DETAIL_MONITOR_NAME:
> -			break;
> -		case EDID_DETAIL_MONITOR_CPDATA:
> -			break;
> -		case EDID_DETAIL_STD_MODES:
> -			/* Five modes per detailed section */
> -			for (j = 0; j < 5; i++) {
> -				struct std_timing *std;
> -				struct drm_display_mode *newmode;
> -
> -				std = &data->data.timings[j];
> -				newmode = drm_mode_std(dev, std,
> -						       edid->revision,
> -						       timing_level);
> -				if (newmode) {
> -					drm_mode_probed_add(connector, newmode);
> -					modes++;
> -				}
> -			}
> -			break;
> -		default:
> -			break;
> -		}
> +		modes += add_detailed_modes(connector, timing, edid, quirks, 0);
>  	}
>  
>  	return modes;





More information about the kernel-team mailing list