From mboxrd@z Thu Jan 1 00:00:00 1970 From: Ville =?iso-8859-1?Q?Syrj=E4l=E4?= Subject: Re: [PATCH v2 13/18] DRM/KMS/EDID: Cache EDID blobs with extensions (v2) Date: Thu, 22 Nov 2012 16:14:08 +0200 Message-ID: <20121122141408.GG3296@intel.com> References: <1353356598-10634-1-git-send-email-eich@suse.de> <1353579788-30637-1-git-send-email-eich@suse.com> <1353579788-30637-14-git-send-email-eich@suse.com> Mime-Version: 1.0 Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: quoted-printable Return-path: Received: from mga02.intel.com (mga02.intel.com [134.134.136.20]) by gabe.freedesktop.org (Postfix) with ESMTP id 2F8EAE5C24 for ; Thu, 22 Nov 2012 06:14:12 -0800 (PST) Content-Disposition: inline In-Reply-To: <1353579788-30637-14-git-send-email-eich@suse.com> List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: dri-devel-bounces+sf-dri-devel=m.gmane.org@lists.freedesktop.org Errors-To: dri-devel-bounces+sf-dri-devel=m.gmane.org@lists.freedesktop.org To: Egbert Eich Cc: tiwai@suse.com, dri-devel@lists.freedesktop.org List-Id: dri-devel@lists.freedesktop.org On Thu, Nov 22, 2012 at 05:23:03AM -0500, Egbert Eich wrote: > According the the VESA specs there can be up to 254 EEDID extension block= s. > Since we may read the EDID (including extensions) in 10 second intervals = to > probe for display hotplugging (at least in cases where no hardware hotplug > detection exists) and I2C transfer is rather slow we may end up consuming > a considerable amount on CPU time for just that. > This patch caches the EDID block if it contains at least one extension. > To determine if the blocks match we only tranfer the base block, on a mat= ch > we use the cached data. > = > V2: Use kmemdup() instead of a kmalloc()/memcpy() combo, > erase cache when reading a 'firmware'-supplied EDID or on error. > = > Signed-off-by: Egbert Eich > --- > drivers/gpu/drm/drm_crtc.c | 1 + > drivers/gpu/drm/drm_edid.c | 57 +++++++++++++++++++++++++++++++++++++-= ----- > include/drm/drm_crtc.h | 1 + > include/drm/drm_edid.h | 1 + > 4 files changed, 52 insertions(+), 8 deletions(-) > = > diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c > index 3533609..e283355 100644 > --- a/drivers/gpu/drm/drm_crtc.c > +++ b/drivers/gpu/drm/drm_crtc.c > @@ -598,6 +598,7 @@ void drm_connector_cleanup(struct drm_connector *conn= ector) > drm_mode_remove(connector, mode); > = > mutex_lock(&dev->mode_config.mutex); > + drm_cache_edid(connector, NULL); > drm_mode_object_put(dev, &connector->base); > list_del(&connector->head); > dev->mode_config.num_connector--; > diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c > index a47fa7f..28b877c 100644 > --- a/drivers/gpu/drm/drm_edid.c > +++ b/drivers/gpu/drm/drm_edid.c > @@ -419,6 +419,38 @@ fixup_edid(u8 **blockp, int valid_extensions) > } > } > = > +static bool > +compare_get_edid_from_cache(struct drm_connector *connector, struct edid= **edidp) > +{ > + if (connector->edid_cache && > + connector->edid_cache->prod_code[0] =3D=3D (*edidp)->prod_code[0] && > + connector->edid_cache->prod_code[1] =3D=3D (*edidp)->prod_code[1] && > + connector->edid_cache->serial =3D=3D (*edidp)->serial && > + connector->edid_cache->input =3D=3D (*edidp)->input) { > + int size =3D (connector->edid_cache->extensions + 1) * EDID_LENGTH; > + struct edid *new =3D kmemdup(connector->edid_cache, size, GFP_KERNEL); > + if (!new) > + return false; > + DRM_DEBUG_KMS("Got EDID for %s from cache.\n", drm_get_connector_name(= connector)); > + kfree(*edidp); > + *edidp =3D new; > + return true; > + } > + return false; > +} > + > +void > +drm_cache_edid(struct drm_connector *connector, struct edid *edid) > +{ > + struct edid *new =3D NULL; > + kfree(connector->edid_cache); > + if (edid) { > + int size =3D (edid->extensions + 1) * EDID_LENGTH; > + new =3D kmemdup(edid, size, GFP_KERNEL); > + } > + connector->edid_cache =3D new; > +} > + > static u8 * > drm_do_get_edid(struct drm_connector *connector, struct i2c_adapter *ada= pter) > { > @@ -429,28 +461,30 @@ drm_do_get_edid(struct drm_connector *connector, st= ruct i2c_adapter *adapter) > #ifdef CONFIG_DRM_LOAD_EDID_FIRMWARE > /* check if the user has specified a 'firmware' EDID file */ > block =3D (u8 *)drm_load_edid_firmware(connector); > - if (block) > + if (block) { > + drm_cache_edid(connector, NULL); > return block; > + } > #endif > = > if ((block =3D kmalloc(EDID_LENGTH, GFP_KERNEL)) =3D=3D NULL) > - return NULL; > + goto error; > = > /* base block fetch */ > for (i =3D 0; i < 4; i++) { > if (drm_do_probe_ddc_edid(adapter, block, 0, EDID_LENGTH)) > - goto out; > + goto error_free; > if (drm_edid_block_valid(block, 0, print_bad_edid)) > break; > if (i =3D=3D 0 && drm_edid_is_zero(block, EDID_LENGTH)) { > connector->null_edid_counter++; > - goto carp; > + goto error_carp; > } > } > if (i =3D=3D 4) > - goto carp; > + goto error_carp; > = > - /* if there's no extensions, we're done */ > + /* if there are no extensions, we're done - don't bother caching */ > if (block[EDID_EXTENSION_FLAG_OFFSET] =3D=3D 0) > return block; Shouldn't you erase the cache here too? -- = Ville Syrj=E4l=E4 Intel OTC