From patchwork Mon Jan 10 17:28:56 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Guenter Roeck X-Patchwork-Id: 1578033 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: bilbo.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20210112 header.b=MQ5CdHLt; dkim-atps=neutral Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org (client-ip=23.128.96.18; helo=vger.kernel.org; envelope-from=linux-i2c-owner@vger.kernel.org; receiver=) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by bilbo.ozlabs.org (Postfix) with ESMTP id 4JXgmM1ngWz9sPC for ; Tue, 11 Jan 2022 04:29:07 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S238288AbiAJR3F (ORCPT ); Mon, 10 Jan 2022 12:29:05 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:47542 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S238284AbiAJR3E (ORCPT ); Mon, 10 Jan 2022 12:29:04 -0500 Received: from mail-ot1-x32f.google.com (mail-ot1-x32f.google.com [IPv6:2607:f8b0:4864:20::32f]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 72069C06173F; Mon, 10 Jan 2022 09:29:04 -0800 (PST) Received: by mail-ot1-x32f.google.com with SMTP id a23-20020a9d4717000000b0056c15d6d0caso15715075otf.12; Mon, 10 Jan 2022 09:29:04 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=sender:from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=fm3Y+5F0MohN4olHGLQvRyoAifK70Yk5FnnM8OBOnaY=; b=MQ5CdHLt8ziCfryvpihlDJ4ZX85Tcy9aduZDqgAPNXFqWCfkVB3g53gklEatbykw9O s06GJKKMFGf0h9XgsqxL3Vk55iIaILIJK5qjz50k3DLDi93RDx3uufwoSONbr5HVO8JJ oF+Fp4MuXHSO7HCKDA7tESwPWsLOIdTQUnPEdfInm3tdj8yQEyKpOyxOb8zkUw8HjvWR NN1RaGE+dnvPQ44Mz27r2a5Tx1A+AR9ru6qdzQ/TYmva0bjD/KNRfX/uz4Qun8g1Qb5n UDU34TIo0n2i3GElXebI6y49GvorEqSFAfso8DRBE5hxrT1UyhWzidW7WnmDM1L7RZdZ TTsA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:sender:from:to:cc:subject:date:message-id :in-reply-to:references:mime-version:content-transfer-encoding; bh=fm3Y+5F0MohN4olHGLQvRyoAifK70Yk5FnnM8OBOnaY=; b=FW/2jXyjeSja+p4hd0lVvscI2vEPa7z//ScTLptpIlVlRK+Pyj7bsBG5wYFLtjGe5+ 1SvxrJ8qrvCTJo2xOTsvU7vfXSmn1FjEqbIAmS+DxhVgs2PgskACURpf5r/7HlgsS9Ld JK7hX7No2QE/Ix9cQLk1a9bSut+69DaiZt2RuI9lX0Q8/5YtQLs/IxV42I6huTxN/PeH W9hLgg3eojpyeUTR/vap3DhFxi0iAE//TfqC94J7WLyxrKrFNBTk0u25uImbA7OTkJ34 CuoXyTnPpki7uu5VsCH0hamyDmp5RDr+vv7SouwM669RoHBMDI7MscIEbNBJ0EfwH0ou V8Dg== X-Gm-Message-State: AOAM5318aJcoLvjzerwJEoMdNWh87KPwxo4B6XWkRrl3jh6pi0jyVqgW ZoLyrK0z3Q34ypOHHeYdqfQ= X-Google-Smtp-Source: ABdhPJxrSaYVUajgkoTx8YKk397pJEjp52052DAoOiu2AGsb0YgzgvbMizN+/LBOAfKZx1FErgLxpw== X-Received: by 2002:a9d:6b0c:: with SMTP id g12mr623948otp.312.1641835743836; Mon, 10 Jan 2022 09:29:03 -0800 (PST) Received: from server.roeck-us.net ([2600:1700:e321:62f0:329c:23ff:fee3:9d7c]) by smtp.gmail.com with ESMTPSA id k19sm1419757oot.32.2022.01.10.09.29.02 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 10 Jan 2022 09:29:03 -0800 (PST) Sender: Guenter Roeck From: Guenter Roeck To: Wolfram Sang Cc: Jean Delvare , linux-i2c@vger.kernel.org, linux-kernel@vger.kernel.org, Guenter Roeck Subject: [PATCH 1/2] i2c: smbus: Improve handling of stuck alerts Date: Mon, 10 Jan 2022 09:28:56 -0800 Message-Id: <20220110172857.2980523-2-linux@roeck-us.net> X-Mailer: git-send-email 2.33.0 In-Reply-To: <20220110172857.2980523-1-linux@roeck-us.net> References: <20220110172857.2980523-1-linux@roeck-us.net> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-i2c@vger.kernel.org The following messages were observed while testing alert functionality on systems with multiple I2C devices on a single bus if alert was active on more than one chip. smbus_alert 3-000c: SMBALERT# from dev 0x0c, flag 0 smbus_alert 3-000c: no driver alert()! and: smbus_alert 3-000c: SMBALERT# from dev 0x28, flag 0 Once it starts, this message repeats forever at high rate. There is no device at any of the reported addresses. Analysis shows that this is seen if multiple devices have the alert pin active. Apparently some devices do not support SMBus arbitration correctly. They keep sending address bits after detecting an address collision and handle the collision not at all or too late. Specifically, address 0x0c is seen with ADT7461A at address 0x4c and ADM1021 at address 0x18 if alert is active on both chips. Address 0x28 is seen with ADT7483 at address 0x2a and ADT7461 at address 0x4c if alert is active on both chips. Once the system is in bad state (alert is set by more than one chip), it often only recovers by power cycling. To reduce the impact of this problem, abort the endless loop in smbus_alert() if the same address is read more than once and not handled by a driver. Fixes: b5527a7766f0 ("i2c: Add SMBus alert support") Signed-off-by: Guenter Roeck --- drivers/i2c/i2c-smbus.c | 30 ++++++++++++++++++++++++------ 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/drivers/i2c/i2c-smbus.c b/drivers/i2c/i2c-smbus.c index d3d06e3b4f3b..533c885b99ac 100644 --- a/drivers/i2c/i2c-smbus.c +++ b/drivers/i2c/i2c-smbus.c @@ -34,6 +34,7 @@ static int smbus_do_alert(struct device *dev, void *addrp) struct i2c_client *client = i2c_verify_client(dev); struct alert_data *data = addrp; struct i2c_driver *driver; + int ret; if (!client || client->addr != data->addr) return 0; @@ -47,16 +48,21 @@ static int smbus_do_alert(struct device *dev, void *addrp) device_lock(dev); if (client->dev.driver) { driver = to_i2c_driver(client->dev.driver); - if (driver->alert) + if (driver->alert) { driver->alert(client, data->type, data->data); - else + ret = -EBUSY; + } else { dev_warn(&client->dev, "no driver alert()!\n"); - } else + ret = -EOPNOTSUPP; + } + } else { dev_dbg(&client->dev, "alert with no driver\n"); + ret = -ENODEV; + } device_unlock(dev); /* Stop iterating after we find the device */ - return -EBUSY; + return ret; } /* @@ -67,6 +73,7 @@ static irqreturn_t smbus_alert(int irq, void *d) { struct i2c_smbus_alert *alert = d; struct i2c_client *ara; + unsigned short prev_addr = 0; /* Not a valid address */ ara = alert->ara; @@ -94,8 +101,19 @@ static irqreturn_t smbus_alert(int irq, void *d) data.addr, data.data); /* Notify driver for the device which issued the alert */ - device_for_each_child(&ara->adapter->dev, &data, - smbus_do_alert); + status = device_for_each_child(&ara->adapter->dev, &data, + smbus_do_alert); + /* + * If we read the same address more than once, and the alert + * was not handled by a driver, it won't do any good to repeat + * the loop because it will never terminate. + * Bail out in this case. + * Note: This assumes that a driver with alert handler handles + * the alert properly and clears it if necessary. + */ + if (data.addr == prev_addr && status != -EBUSY) + break; + prev_addr = data.addr; } return IRQ_HANDLED; From patchwork Mon Jan 10 17:28:57 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Guenter Roeck X-Patchwork-Id: 1578034 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: bilbo.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20210112 header.b=KfxnQt6E; dkim-atps=neutral Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org (client-ip=23.128.96.18; helo=vger.kernel.org; envelope-from=linux-i2c-owner@vger.kernel.org; receiver=) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by bilbo.ozlabs.org (Postfix) with ESMTP id 4JXgmQ181Xz9sPC for ; Tue, 11 Jan 2022 04:29:10 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S238359AbiAJR3J (ORCPT ); Mon, 10 Jan 2022 12:29:09 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:47554 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S238350AbiAJR3H (ORCPT ); Mon, 10 Jan 2022 12:29:07 -0500 Received: from mail-ot1-x329.google.com (mail-ot1-x329.google.com [IPv6:2607:f8b0:4864:20::329]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id ABC77C06173F; Mon, 10 Jan 2022 09:29:06 -0800 (PST) Received: by mail-ot1-x329.google.com with SMTP id c3-20020a9d6c83000000b00590b9c8819aso6271961otr.6; Mon, 10 Jan 2022 09:29:06 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=sender:from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=3arUIq63vNkv0j9deYGRwsb6acRjeiR9Ll7tBXR1ckY=; b=KfxnQt6E4jhETkBYRW6RgjpaOewUsqAv3+5n7Qbagdyen8Mo0Z70sbHSFse0rfEnvR V5EBEMM1hvovVG0sNctLNgRJrlHf7TL2fqqVocdNtQqm5XWNqpT/pZjCetBOVYcXo3zl f7MaDWmhUUwLcKjvc5c0Y8eBZ2T98TV55/fLF6kZrrQJRcfFTdGbOibVHo7tFms7MPWs u+6PME91vyXW8R0SQ2MNO/tgMABtjhuEenFEgaFNItFoi6I/bz0PsfEWaY+xEozBfeUE bklikwqZqo1lmxpH3ZK2yhi9EAaOPhTayWw8YsmHDRJ1nStfzzlag+9lycTy6SFiGZZw jeQg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:sender:from:to:cc:subject:date:message-id :in-reply-to:references:mime-version:content-transfer-encoding; bh=3arUIq63vNkv0j9deYGRwsb6acRjeiR9Ll7tBXR1ckY=; b=OFPhj+urUuSzBQAcHCy8JIEMtD2msscL3P64jr5MVZsh2MioazR4ctyVtscF8AruIx O2WjHVyz1Ehtsd0qyZcQDlU9Lblrku1KJ/Eei1DhLJgefWe67+26U4JDeE+MUqGDkqTc BCno0Oi+51GK60K4sDH6bvxrbhw1GcDhSzA0a1ds9nOkFCCtTYfX73tG9wwLZ3hLLZwY dIT835S+gPk+h4PN4hjEYidsNAg4/KFcOxYhp5yuCiIcVkH9l74fqKsvQYQtqXnmD55H wRL2pHCM4lyvIH//W9hRNR0XA4sb7iyWj8+nrXQ7Y/ZZmMjm7X7XPThLcJeZ6VQbIOZQ 4anA== X-Gm-Message-State: AOAM53295ktTWkMwiwZCPRoPjmgJ3S0oQ1yFQSmnzGjXRaP6gwOwZsv2 c96KNoBe7xcmBZ3+kTFncSY39GW/RWM= X-Google-Smtp-Source: ABdhPJy31UYaR9emLBbPr2+/92GUNa+ayCindvUPDU4MVjEJzuglp0vPcFmpQBScXNM1OlIQA3I9fA== X-Received: by 2002:a05:6830:1e6b:: with SMTP id m11mr627285otr.29.1641835745772; Mon, 10 Jan 2022 09:29:05 -0800 (PST) Received: from server.roeck-us.net ([2600:1700:e321:62f0:329c:23ff:fee3:9d7c]) by smtp.gmail.com with ESMTPSA id d3sm1274717oiw.52.2022.01.10.09.29.04 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 10 Jan 2022 09:29:05 -0800 (PST) Sender: Guenter Roeck From: Guenter Roeck To: Wolfram Sang Cc: Jean Delvare , linux-i2c@vger.kernel.org, linux-kernel@vger.kernel.org, Guenter Roeck Subject: [PATCH 2/2] i2c: smbus: Send alert notifications to all devices if source not found Date: Mon, 10 Jan 2022 09:28:57 -0800 Message-Id: <20220110172857.2980523-3-linux@roeck-us.net> X-Mailer: git-send-email 2.33.0 In-Reply-To: <20220110172857.2980523-1-linux@roeck-us.net> References: <20220110172857.2980523-1-linux@roeck-us.net> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-i2c@vger.kernel.org If a SMBUs alert is received and the originating device is not found, the reason may be that the address reported on the SMBus alert address is corrupted, for example because multiple devices asserted alert and do not correctly implement SMBus arbitration. If this happens, call alert handlers on all devices connected to the given I2C bus, in the hope that this cleans up the situation. Retry twice before giving up. This change reliably fixed the problem on a system with multiple devices on a single bus. Example log where the device on address 0x18 (ADM1021) and on address 0x4c (ADM7461A) both had the alert line asserted: smbus_alert 3-000c: SMBALERT# from dev 0x0c, flag 0 smbus_alert 3-000c: no driver alert()! smbus_alert 3-000c: SMBALERT# from dev 0x0c, flag 0 smbus_alert 3-000c: no driver alert()! lm90 3-0018: temp1 out of range, please check! lm90 3-0018: Disabling ALERT# lm90 3-0029: Everything OK lm90 3-002a: Everything OK lm90 3-004c: temp1 out of range, please check! lm90 3-004c: temp2 out of range, please check! lm90 3-004c: Disabling ALERT# Fixes: b5527a7766f0 ("i2c: Add SMBus alert support") Signed-off-by: Guenter Roeck --- drivers/i2c/i2c-smbus.c | 38 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 36 insertions(+), 2 deletions(-) diff --git a/drivers/i2c/i2c-smbus.c b/drivers/i2c/i2c-smbus.c index 533c885b99ac..f48cec19db41 100644 --- a/drivers/i2c/i2c-smbus.c +++ b/drivers/i2c/i2c-smbus.c @@ -65,6 +65,32 @@ static int smbus_do_alert(struct device *dev, void *addrp) return ret; } +/* Same as above, but call back all drivers with alert handler */ + +static int smbus_do_alert_force(struct device *dev, void *addrp) +{ + struct i2c_client *client = i2c_verify_client(dev); + struct alert_data *data = addrp; + struct i2c_driver *driver; + + if (!client || (client->flags & I2C_CLIENT_TEN)) + return 0; + + /* + * Drivers should either disable alerts, or provide at least + * a minimal handler. Lock so the driver won't change. + */ + device_lock(dev); + if (client->dev.driver) { + driver = to_i2c_driver(client->dev.driver); + if (driver->alert) + driver->alert(client, data->type, data->data); + } + device_unlock(dev); + + return 0; +} + /* * The alert IRQ handler needs to hand work off to a task which can issue * SMBus calls, because those sleeping calls can't be made in IRQ context. @@ -74,6 +100,7 @@ static irqreturn_t smbus_alert(int irq, void *d) struct i2c_smbus_alert *alert = d; struct i2c_client *ara; unsigned short prev_addr = 0; /* Not a valid address */ + int retries = 0; ara = alert->ara; @@ -111,8 +138,15 @@ static irqreturn_t smbus_alert(int irq, void *d) * Note: This assumes that a driver with alert handler handles * the alert properly and clears it if necessary. */ - if (data.addr == prev_addr && status != -EBUSY) - break; + if (data.addr == prev_addr && status != -EBUSY) { + /* retry once */ + if (retries++) + break; + device_for_each_child(&ara->adapter->dev, &data, + smbus_do_alert_force); + } else { + retries = 0; + } prev_addr = data.addr; }