On Mon, May 18, 2015 at 02:00:04PM +0300, Jani Nikula wrote: > On Mon, 18 May 2015, Jani Nikula <jani.nikula@xxxxxxxxx> wrote: > > On Mon, 18 May 2015, Luis Henriques <luis.henriques@xxxxxxxxxxxxx> wrote: > >> On Sat, May 16, 2015 at 09:37:11AM +0200, Jiri Slaby wrote: > >>> From: Dmitry Torokhov <dmitry.torokhov@xxxxxxxxx> > >>> > >>> 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 <chris@xxxxxxxxxxxxxxxxxx> > > 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 <nick.dyer@xxxxxxxxxxx> > > 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 <chris@xxxxxxxxxxxxxxxxxx> > >>> Signed-off-by: Dmitry Torokhov <dmitry.torokhov@xxxxxxxxx> > >>> Signed-off-by: Jani Nikula <jani.nikula@xxxxxxxxx> > >>> Signed-off-by: Jiri Slaby <jslaby@xxxxxxx> > >>> --- > >>> 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@xxxxxxxxxxxxxxx > >>> 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 stable" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html