Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932391AbbERLD3 (ORCPT ); Mon, 18 May 2015 07:03:29 -0400 Received: from youngberry.canonical.com ([91.189.89.112]:51501 "EHLO youngberry.canonical.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S932355AbbERLDV (ORCPT ); Mon, 18 May 2015 07:03:21 -0400 Date: Mon, 18 May 2015 12:03:18 +0100 From: Luis Henriques To: Jani Nikula Cc: Jiri Slaby , stable@vger.kernel.org, linux-kernel@vger.kernel.org, Dmitry Torokhov , Ben Hutchings Subject: Re: [PATCH 3.12 071/142] drm/i915: cope with large i2c transfers Message-ID: <20150518110318.GE1719@ares> References: <378e22f618cf6c4274fd7b928fd7b10ec380c6f6.1431761807.git.jslaby@suse.cz> <20150518095602.GD1719@ares> <87a8x22lwv.fsf@intel.com> <877fs62lsb.fsf@intel.com> MIME-Version: 1.0 Content-Type: text/plain; charset=iso-8859-1 Content-Disposition: inline Content-Transfer-Encoding: 8bit In-Reply-To: <877fs62lsb.fsf@intel.com> Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 7523 Lines: 218 On Mon, May 18, 2015 at 02:00:04PM +0300, Jani Nikula wrote: > On Mon, 18 May 2015, Jani Nikula wrote: > > On Mon, 18 May 2015, Luis Henriques wrote: > >> On Sat, May 16, 2015 at 09:37:11AM +0200, Jiri Slaby wrote: > >>> From: Dmitry Torokhov > >>> > >>> 3.12-stable review patch. If anyone has any objections, please let me know. > >>> > >> > >> Ben Hutchings (on CC) just asked about this patch being included on > >> the 3.16 kernel [1]. Is this patch really useful for kernels < 3.17? > >> Should it be reverted from all the other stable kernels (3.10, 3.14 > >> and 3.16), or do you think it's harmless? > > > > The bug fixed by Dmitry's patch has been there since the introduction of > > the gmbus code in v2.6.37 by > > > > commit f899fc64cda8569d0529452aafc0da31c042df2e > > Author: Chris Wilson > > Date: Tue Jul 20 15:44:45 2010 -0700 > > > > drm/i915: use GMBUS to manage i2c links > > > > It's just that nobody noticed before > > > > commit 9d8dc3e529a19e427fd379118acd132520935c5d > > Author: Nick Dyer > > Date: Wed Jul 23 12:49:04 2014 -0700 > > > > Input: atmel_mxt_ts - implement T44 message handling > > So to be clear, I think the fix is worth backporting anywhere you can > easily backport. I did not check, but I think it may be possible to > trigger this from userspace with the i2c interface. > > Great, so it's definitely worth keeping it in all these stable trees. Thanks a lot for the clarification, Jani. Cheers, -- Lu?s > > > > > > BR, > > Jani. > > > > > >> > >> [1] http://thread.gmane.org/gmane.linux.kernel.stable/136673 > >> > >> Cheers, > >> -- > >> Lu?s > >> > >>> =============== > >>> > >>> commit 9535c4757b881e06fae72a857485ad57c422b8d2 upstream. > >>> > >>> The hardware, according to the specs, is limited to 256 byte transfers, > >>> and current driver has no protections in case users attempt to do larger > >>> transfers. The code will just stomp over status register and mayhem > >>> ensues. > >>> > >>> Let's split larger transfers into digestable chunks. Doing this allows > >>> Atmel MXT driver on Pixel 1 function properly (it hasn't since commit > >>> 9d8dc3e529a19e427fd379118acd132520935c5d "Input: atmel_mxt_ts - > >>> implement T44 message handling" which tries to consume multiple > >>> touchscreen/touchpad reports in a single transaction). > >>> > >>> Reviewed-by: Chris Wilson > >>> Signed-off-by: Dmitry Torokhov > >>> Signed-off-by: Jani Nikula > >>> Signed-off-by: Jiri Slaby > >>> --- > >>> drivers/gpu/drm/i915/i915_reg.h | 1 + > >>> drivers/gpu/drm/i915/intel_i2c.c | 66 ++++++++++++++++++++++++++++++++++------ > >>> 2 files changed, 57 insertions(+), 10 deletions(-) > >>> > >>> diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h > >>> index 9d344da55056..4e0053e64f14 100644 > >>> --- a/drivers/gpu/drm/i915/i915_reg.h > >>> +++ b/drivers/gpu/drm/i915/i915_reg.h > >>> @@ -1105,6 +1105,7 @@ > >>> #define GMBUS_CYCLE_INDEX (2<<25) > >>> #define GMBUS_CYCLE_STOP (4<<25) > >>> #define GMBUS_BYTE_COUNT_SHIFT 16 > >>> +#define GMBUS_BYTE_COUNT_MAX 256U > >>> #define GMBUS_SLAVE_INDEX_SHIFT 8 > >>> #define GMBUS_SLAVE_ADDR_SHIFT 1 > >>> #define GMBUS_SLAVE_READ (1<<0) > >>> diff --git a/drivers/gpu/drm/i915/intel_i2c.c b/drivers/gpu/drm/i915/intel_i2c.c > >>> index d1c1e0f7f262..36b720475dc0 100644 > >>> --- a/drivers/gpu/drm/i915/intel_i2c.c > >>> +++ b/drivers/gpu/drm/i915/intel_i2c.c > >>> @@ -276,18 +276,17 @@ gmbus_wait_idle(struct drm_i915_private *dev_priv) > >>> } > >>> > >>> static int > >>> -gmbus_xfer_read(struct drm_i915_private *dev_priv, struct i2c_msg *msg, > >>> - u32 gmbus1_index) > >>> +gmbus_xfer_read_chunk(struct drm_i915_private *dev_priv, > >>> + unsigned short addr, u8 *buf, unsigned int len, > >>> + u32 gmbus1_index) > >>> { > >>> int reg_offset = dev_priv->gpio_mmio_base; > >>> - u16 len = msg->len; > >>> - u8 *buf = msg->buf; > >>> > >>> I915_WRITE(GMBUS1 + reg_offset, > >>> gmbus1_index | > >>> GMBUS_CYCLE_WAIT | > >>> (len << GMBUS_BYTE_COUNT_SHIFT) | > >>> - (msg->addr << GMBUS_SLAVE_ADDR_SHIFT) | > >>> + (addr << GMBUS_SLAVE_ADDR_SHIFT) | > >>> GMBUS_SLAVE_READ | GMBUS_SW_RDY); > >>> while (len) { > >>> int ret; > >>> @@ -309,11 +308,35 @@ gmbus_xfer_read(struct drm_i915_private *dev_priv, struct i2c_msg *msg, > >>> } > >>> > >>> static int > >>> -gmbus_xfer_write(struct drm_i915_private *dev_priv, struct i2c_msg *msg) > >>> +gmbus_xfer_read(struct drm_i915_private *dev_priv, struct i2c_msg *msg, > >>> + u32 gmbus1_index) > >>> { > >>> - int reg_offset = dev_priv->gpio_mmio_base; > >>> - u16 len = msg->len; > >>> u8 *buf = msg->buf; > >>> + unsigned int rx_size = msg->len; > >>> + unsigned int len; > >>> + int ret; > >>> + > >>> + do { > >>> + len = min(rx_size, GMBUS_BYTE_COUNT_MAX); > >>> + > >>> + ret = gmbus_xfer_read_chunk(dev_priv, msg->addr, > >>> + buf, len, gmbus1_index); > >>> + if (ret) > >>> + return ret; > >>> + > >>> + rx_size -= len; > >>> + buf += len; > >>> + } while (rx_size != 0); > >>> + > >>> + return 0; > >>> +} > >>> + > >>> +static int > >>> +gmbus_xfer_write_chunk(struct drm_i915_private *dev_priv, > >>> + unsigned short addr, u8 *buf, unsigned int len) > >>> +{ > >>> + int reg_offset = dev_priv->gpio_mmio_base; > >>> + unsigned int chunk_size = len; > >>> u32 val, loop; > >>> > >>> val = loop = 0; > >>> @@ -325,8 +348,8 @@ gmbus_xfer_write(struct drm_i915_private *dev_priv, struct i2c_msg *msg) > >>> I915_WRITE(GMBUS3 + reg_offset, val); > >>> I915_WRITE(GMBUS1 + reg_offset, > >>> GMBUS_CYCLE_WAIT | > >>> - (msg->len << GMBUS_BYTE_COUNT_SHIFT) | > >>> - (msg->addr << GMBUS_SLAVE_ADDR_SHIFT) | > >>> + (chunk_size << GMBUS_BYTE_COUNT_SHIFT) | > >>> + (addr << GMBUS_SLAVE_ADDR_SHIFT) | > >>> GMBUS_SLAVE_WRITE | GMBUS_SW_RDY); > >>> while (len) { > >>> int ret; > >>> @@ -343,6 +366,29 @@ gmbus_xfer_write(struct drm_i915_private *dev_priv, struct i2c_msg *msg) > >>> if (ret) > >>> return ret; > >>> } > >>> + > >>> + return 0; > >>> +} > >>> + > >>> +static int > >>> +gmbus_xfer_write(struct drm_i915_private *dev_priv, struct i2c_msg *msg) > >>> +{ > >>> + u8 *buf = msg->buf; > >>> + unsigned int tx_size = msg->len; > >>> + unsigned int len; > >>> + int ret; > >>> + > >>> + do { > >>> + len = min(tx_size, GMBUS_BYTE_COUNT_MAX); > >>> + > >>> + ret = gmbus_xfer_write_chunk(dev_priv, msg->addr, buf, len); > >>> + if (ret) > >>> + return ret; > >>> + > >>> + buf += len; > >>> + tx_size -= len; > >>> + } while (tx_size != 0); > >>> + > >>> return 0; > >>> } > >>> > >>> -- > >>> 2.3.7 > >>> > >>> -- > >>> To unsubscribe from this list: send the line "unsubscribe stable" in > >>> the body of a message to majordomo@vger.kernel.org > >>> More majordomo info at http://vger.kernel.org/majordomo-info.html > > > > -- > > Jani Nikula, Intel Open Source Technology Center > > -- > Jani Nikula, Intel Open Source Technology Center -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/