diff options
author | Daniel Vetter <daniel.vetter@ffwll.ch> | 2017-07-26 16:26:47 +0300 |
---|---|---|
committer | Daniel Vetter <daniel.vetter@ffwll.ch> | 2017-07-27 11:05:48 +0300 |
commit | a85066840d29fc68d95ce7dbd6bcf15ef2775d66 (patch) | |
tree | 86c0619b327a1c103444d8ed2f646be347684a57 /drivers/gpu/drm/i915/intel_i2c.c | |
parent | 8fb6a5df4612757d6aa4218750aa3ecaca609bd0 (diff) | |
download | linux-a85066840d29fc68d95ce7dbd6bcf15ef2775d66.tar.xz |
drm/i915: Rework sdvo proxy i2c locking
lockdep complaints about a locking recursion for the i2c bus lock
because both the sdvo ddc proxy bus and the gmbus nested within use
the same locking class. It's not really a deadlock since we never nest
the other way round, but it's annoying.
Fix it by pulling the gmbus locking into the i2c lock_ops for both
i2c_adapater and making sure that the ddc_proxy_xfer function is
entirely lockless.
Re-layouting the extracted function resulted in some whitespace
cleanups, I figured we might as well keep them.
v2: Review from Chris:
- s/locked/unlocked/ since I got the naming backwards
- Use the vfuncs of the proxied adatper instead of re-rolling copies.
That's more consistent with the other proxying we're doing.
Cc: Chris Wilson <chris@chris-wilson.co.uk>
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20170726132647.31833-1-daniel.vetter@ffwll.ch
Diffstat (limited to 'drivers/gpu/drm/i915/intel_i2c.c')
-rw-r--r-- | drivers/gpu/drm/i915/intel_i2c.c | 36 |
1 files changed, 34 insertions, 2 deletions
diff --git a/drivers/gpu/drm/i915/intel_i2c.c b/drivers/gpu/drm/i915/intel_i2c.c index 3c9e00d4ba5a..6698826954e1 100644 --- a/drivers/gpu/drm/i915/intel_i2c.c +++ b/drivers/gpu/drm/i915/intel_i2c.c @@ -592,7 +592,6 @@ gmbus_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, int num) int ret; intel_display_power_get(dev_priv, POWER_DOMAIN_GMBUS); - mutex_lock(&dev_priv->gmbus_mutex); if (bus->force_bit) { ret = i2c_bit_algo.master_xfer(adapter, msgs, num); @@ -604,7 +603,6 @@ gmbus_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, int num) bus->force_bit |= GMBUS_FORCE_BIT_RETRY; } - mutex_unlock(&dev_priv->gmbus_mutex); intel_display_power_put(dev_priv, POWER_DOMAIN_GMBUS); return ret; @@ -624,6 +622,39 @@ static const struct i2c_algorithm gmbus_algorithm = { .functionality = gmbus_func }; +static void gmbus_lock_bus(struct i2c_adapter *adapter, + unsigned int flags) +{ + struct intel_gmbus *bus = to_intel_gmbus(adapter); + struct drm_i915_private *dev_priv = bus->dev_priv; + + mutex_lock(&dev_priv->gmbus_mutex); +} + +static int gmbus_trylock_bus(struct i2c_adapter *adapter, + unsigned int flags) +{ + struct intel_gmbus *bus = to_intel_gmbus(adapter); + struct drm_i915_private *dev_priv = bus->dev_priv; + + return mutex_trylock(&dev_priv->gmbus_mutex); +} + +static void gmbus_unlock_bus(struct i2c_adapter *adapter, + unsigned int flags) +{ + struct intel_gmbus *bus = to_intel_gmbus(adapter); + struct drm_i915_private *dev_priv = bus->dev_priv; + + mutex_unlock(&dev_priv->gmbus_mutex); +} + +const struct i2c_lock_operations gmbus_lock_ops = { + .lock_bus = gmbus_lock_bus, + .trylock_bus = gmbus_trylock_bus, + .unlock_bus = gmbus_unlock_bus, +}; + /** * intel_gmbus_setup - instantiate all Intel i2c GMBuses * @dev_priv: i915 device private @@ -665,6 +696,7 @@ int intel_setup_gmbus(struct drm_i915_private *dev_priv) bus->dev_priv = dev_priv; bus->adapter.algo = &gmbus_algorithm; + bus->adapter.lock_ops = &gmbus_lock_ops; /* * We wish to retry with bit banging |