From 894c957383bef0cd48b2528fe09a1647bd23acc2 Mon Sep 17 00:00:00 2001 From: Yufeng Shen Date: Mon, 13 Feb 2012 17:36:54 -0500 Subject: [PATCH] --- yaml --- r: 293599 b: refs/heads/master c: 8a8ed1f5143b3df312e436ab15290e4a7ca6a559 h: refs/heads/master i: 293597: 657468e7caab58b58f73da16296c87003bdfae5b 293595: 317b765fee804a4a688307a26a18f9e85bbc3911 293591: e85339a7125cc2bd8b23ae7d8a5f99096fb7e750 293583: 96ec1c51125c98991467b252030f6c736b561c3d 293567: 26128c43cc1c4302980a1f6db5eaf6fd527e27d6 v: v3 --- [refs] | 2 +- trunk/drivers/gpu/drm/i915/i915_drv.h | 4 ++++ trunk/drivers/gpu/drm/i915/intel_i2c.c | 24 +++++++++++++++++------- 3 files changed, 22 insertions(+), 8 deletions(-) diff --git a/[refs] b/[refs] index 6eb2e4624fc4..aca780eea0a1 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: b1d7e4b41fd0f72ea8149056778db5d737739305 +refs/heads/master: 8a8ed1f5143b3df312e436ab15290e4a7ca6a559 diff --git a/trunk/drivers/gpu/drm/i915/i915_drv.h b/trunk/drivers/gpu/drm/i915/i915_drv.h index caec1fdb7dda..8e3eb5e282a1 100644 --- a/trunk/drivers/gpu/drm/i915/i915_drv.h +++ b/trunk/drivers/gpu/drm/i915/i915_drv.h @@ -313,6 +313,10 @@ typedef struct drm_i915_private { u32 reg0; } *gmbus; + /** gmbus_mutex protects against concurrent usage of the single hw gmbus + * controller on different i2c buses. */ + struct mutex gmbus_mutex; + struct pci_dev *bridge_dev; struct intel_ring_buffer ring[I915_NUM_RINGS]; uint32_t next_seqno; diff --git a/trunk/drivers/gpu/drm/i915/intel_i2c.c b/trunk/drivers/gpu/drm/i915/intel_i2c.c index d30ccccb9d73..fc75d71de53b 100644 --- a/trunk/drivers/gpu/drm/i915/intel_i2c.c +++ b/trunk/drivers/gpu/drm/i915/intel_i2c.c @@ -233,11 +233,15 @@ gmbus_xfer(struct i2c_adapter *adapter, struct intel_gmbus, adapter); struct drm_i915_private *dev_priv = adapter->algo_data; - int i, reg_offset; + int i, reg_offset, ret; - if (bus->force_bit) - return intel_i2c_quirk_xfer(dev_priv, + mutex_lock(&dev_priv->gmbus_mutex); + + if (bus->force_bit) { + ret = intel_i2c_quirk_xfer(dev_priv, bus->force_bit, msgs, num); + goto out; + } reg_offset = HAS_PCH_SPLIT(dev_priv->dev) ? PCH_GMBUS0 - GMBUS0 : 0; @@ -321,7 +325,8 @@ gmbus_xfer(struct i2c_adapter *adapter, * start of the next xfer, till then let it sleep. */ I915_WRITE(GMBUS0 + reg_offset, 0); - return i; + ret = i; + goto out; timeout: DRM_INFO("GMBUS timed out, falling back to bit banging on pin %d [%s]\n", @@ -331,9 +336,12 @@ gmbus_xfer(struct i2c_adapter *adapter, /* Hardware may not support GMBUS over these pins? Try GPIO bitbanging instead. */ bus->force_bit = intel_gpio_create(dev_priv, bus->reg0 & 0xff); if (!bus->force_bit) - return -ENOMEM; - - return intel_i2c_quirk_xfer(dev_priv, bus->force_bit, msgs, num); + ret = -ENOMEM; + else + ret = intel_i2c_quirk_xfer(dev_priv, bus->force_bit, msgs, num); +out: + mutex_unlock(&dev_priv->gmbus_mutex); + return ret; } static u32 gmbus_func(struct i2c_adapter *adapter) @@ -380,6 +388,8 @@ int intel_setup_gmbus(struct drm_device *dev) if (dev_priv->gmbus == NULL) return -ENOMEM; + mutex_init(&dev_priv->gmbus_mutex); + for (i = 0; i < GMBUS_NUM_PORTS; i++) { struct intel_gmbus *bus = &dev_priv->gmbus[i];