From patchwork Fri Sep 16 14:18:04 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bartosz Golaszewski X-Patchwork-Id: 76384 Delivered-To: patch@linaro.org Received: by 10.140.106.72 with SMTP id d66csp522451qgf; Fri, 16 Sep 2016 07:18:13 -0700 (PDT) X-Received: by 10.66.26.77 with SMTP id j13mr23743466pag.129.1474035493296; Fri, 16 Sep 2016 07:18:13 -0700 (PDT) Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id 143si36716855pfu.156.2016.09.16.07.18.13; Fri, 16 Sep 2016 07:18:13 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-i2c-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@baylibre-com.20150623.gappssmtp.com; spf=pass (google.com: best guess record for domain of linux-i2c-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-i2c-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755048AbcIPOSM (ORCPT + 1 other); Fri, 16 Sep 2016 10:18:12 -0400 Received: from mail-wm0-f50.google.com ([74.125.82.50]:34956 "EHLO mail-wm0-f50.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751905AbcIPOSL (ORCPT ); Fri, 16 Sep 2016 10:18:11 -0400 Received: by mail-wm0-f50.google.com with SMTP id l132so40456620wmf.0 for ; Fri, 16 Sep 2016 07:18:10 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=baylibre-com.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id; bh=yhIcfL9O7vfLdfe8zu/Ms8vHwYPfHQZOS47oV2vx3YI=; b=To0tcgP5a3PsXtz2R2yioQl6ywpj6S+GKDA4njIeJpBZ85O5rmyHF1Gecv02HFXFm7 /NI4yDuPF4FAB0cikb2U0IOkZItGyPmVRBDZ7TCvRlCrINOKp4RyceTgk+4LknCWsOjC rfMQ/IENcBt/iOSCOqGOWJgRNFedraqnXoUnhNBFOmudv77+cpc01gyNxJrxO91bhIoi uaYOalccTAwKc8DBQvASi5IEWVuRYRxZ/zuecNHr0emb2EHAd7TyUMD5skzRmBLwKzWL vskVAjyoMf7jkJbU5vDXtZ0CzoMWLeBFhR/ETzcelD0pc69IYxbG0c0qpjcn7uDiIXHY Ocnw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id; bh=yhIcfL9O7vfLdfe8zu/Ms8vHwYPfHQZOS47oV2vx3YI=; b=lB388N4A6O/ucDudX9If10SyK0L9z1NmSPCDAEFRqXXRnkUCnACXdfgt8IFpsgS4JA xQtZ2+dh3o5UUp4IGPlSkMLc+VJ7dMTwsG0UD7IsjcA1dTkpNrsovqJqI8uJNNP/sKHN pHM4s3Mr7cDd2sV6nQmM8sjY2nZ81jJKcOoFb7eX/DIFn7bRqW5SzLgg8gH08GR6xwp3 gpQgV582lcqSNl09wlIG5+euDB8LYLoZ5pL7Cra+hzO9y6B/79wjkm51mLs1ehQ70zbv uFuIysvztzctfDcIAVIQ81i9sR1M4+f7IWhEdRCuGVMOUA9L+qrJZj1p89foUJANpB4I sZAw== X-Gm-Message-State: AE9vXwMFyV/yi7rud26JuYvJ16lGbz1Rix4dxWpYwXuKWMGfrA+cZh2oNJ8fSEMqHUleeBQ5 X-Received: by 10.194.106.234 with SMTP id gx10mr6193030wjb.202.1474035489175; Fri, 16 Sep 2016 07:18:09 -0700 (PDT) Received: from localhost.localdomain ([90.63.244.31]) by smtp.gmail.com with ESMTPSA id m75sm3090253wmi.0.2016.09.16.07.18.08 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Fri, 16 Sep 2016 07:18:08 -0700 (PDT) From: Bartosz Golaszewski To: Linus Walleij , Alexandre Courbot , Andy Shevchenko , Vignesh R , Yong Li , Geert Uytterhoeven , Peter Zijlstra , Ingo Molnar , Wolfram Sang Cc: linux-i2c , linux-gpio , LKML , Bartosz Golaszewski Subject: [PATCH] gpio: pca953x: fix an incorrect lockdep warning Date: Fri, 16 Sep 2016 16:18:04 +0200 Message-Id: <1474035484-25134-1-git-send-email-bgolaszewski@baylibre.com> X-Mailer: git-send-email 2.1.4 Sender: linux-i2c-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-i2c@vger.kernel.org If an I2C GPIO multiplexer is driven by a GPIO provided by an expander when there's a second expander using the same device driver on one of the I2C bus segments, lockdep prints a deadlock warning when trying to set the direction or the value of the GPIOs provided by the second expander. The below diagram presents the setup: - - - - - ------- --------- Bus segment 1 | | | | | |--------------- Devices | | SCL/SDA | | | | | Linux |-----------| I2C MUX | - - - - - | | | | | Bus segment 2 | | | | |------------------- ------- | --------- | | | - - - - - ------------ | MUX GPIO | | | | | Devices | GPIO | | | | | Expander 1 |---- - - - - - | | | ------------ | SCL/SDA | ------------ | | | GPIO | | Expander 2 | | | ------------ The reason for lockdep warning is that we take the chip->i2c_lock in pca953x_gpio_set_value() or pca953x_gpio_direction_output() and then come right back to pca953x_gpio_set_value() when the GPIO mux kicks in. The locks actually protect different expanders, but for lockdep both are of the same class, so it says: Possible unsafe locking scenario: CPU0 ---- lock(&chip->i2c_lock); lock(&chip->i2c_lock); *** DEADLOCK *** May be due to missing lock nesting notation In order to get rid of the warning, check if the i2c adapter of the expander is multiplexed (by checking if it has a parent adapter) and, if so, set a different lock subclass for chip->i2c_lock. Signed-off-by: Bartosz Golaszewski --- Note: a similar issue would occur with other gpio expanders under similar circumstances. If this patch get's merged, I'll prepare a common solution for all gpio drivers which use an internal i2c lock. drivers/gpio/gpio-pca953x.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) -- 2.7.4 -- To unsubscribe from this list: send the line "unsubscribe linux-i2c" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c index 02f2a56..2d49b25 100644 --- a/drivers/gpio/gpio-pca953x.c +++ b/drivers/gpio/gpio-pca953x.c @@ -787,6 +787,18 @@ static int pca953x_probe(struct i2c_client *client, mutex_init(&chip->i2c_lock); + /* + * If the i2c adapter we're connected to is multiplexed (which is + * indicated by it having a parent adapter) we need to use a + * different lock subclass. It's caused by the fact that in a rare + * case of using an i2c-gpio multiplexer controlled by a gpio + * provided by an expander using the same driver, lockdep would + * incorrectly detect a deadlock, since we'd take a second lock + * of the same class without releasing the first one. + */ + if (i2c_parent_is_i2c_adapter(client->adapter)) + lockdep_set_subclass(&chip->i2c_lock, SINGLE_DEPTH_NESTING); + /* initialize cached registers from their original values. * we can't share this chip with another i2c master. */