diff mbox

This cherry-picked upstream patch removes an infinite

Message ID 1265970453-4375-1-git-send-email-surbhi.palande@canonical.com
State Accepted
Delegated to: Andy Whitcroft
Headers show

Commit Message

Surbhi Palande Feb. 12, 2010, 10:27 a.m. UTC
From 2f8055156e9160f3d83e56122c90c3ece2e09819 Mon Sep 17 00:00:00 2001
From: Adam Jackson <ajax@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@redhat.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
(cherry picked from commit 9cf00977da092096c7a983276dad8b3002d23a99)

Signed-off-by: Surbhi Palande <Surbhi.Palande@canonical.com>
---
 drivers/gpu/drm/drm_edid.c |  163 ++++++++++++++++---------------------------
 1 files changed, 61 insertions(+), 102 deletions(-)

Comments

Surbhi Palande Feb. 12, 2010, 10:34 a.m. UTC | #1
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@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@redhat.com>
> Signed-off-by: Dave Airlie <airlied@redhat.com>
> (cherry picked from commit 9cf00977da092096c7a983276dad8b3002d23a99)
> 
> Signed-off-by: Surbhi Palande <Surbhi.Palande@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;
Tim Gardner Feb. 12, 2010, 2:15 p.m. UTC | #2
Surbhi Palande wrote:
> From 2f8055156e9160f3d83e56122c90c3ece2e09819 Mon Sep 17 00:00:00 2001
> From: Adam Jackson <ajax@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@redhat.com>
> Signed-off-by: Dave Airlie <airlied@redhat.com>
> (cherry picked from commit 9cf00977da092096c7a983276dad8b3002d23a99)
> 
> Signed-off-by: Surbhi Palande <Surbhi.Palande@canonical.com>
> ---
>  drivers/gpu/drm/drm_edid.c |  163 ++++++++++++++++---------------------------
>  1 files changed, 61 insertions(+), 102 deletions(-)
> 

ACK
diff mbox

Patch

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;