From patchwork Wed Sep 2 07:17:34 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrew Jeffery X-Patchwork-Id: 1355562 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.ozlabs.org (lists.ozlabs.org [203.11.71.2]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4BhFgf5bF3z9sR4 for ; Wed, 2 Sep 2020 17:19:42 +1000 (AEST) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=aj.id.au Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=aj.id.au header.i=@aj.id.au header.a=rsa-sha256 header.s=fm3 header.b=Fzfy+mt8; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=messagingengine.com header.i=@messagingengine.com header.a=rsa-sha256 header.s=fm3 header.b=CSkx8Rtb; dkim-atps=neutral Received: from bilbo.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) by lists.ozlabs.org (Postfix) with ESMTP id 4BhFgd3SnlzDqd0 for ; Wed, 2 Sep 2020 17:19:41 +1000 (AEST) X-Original-To: openbmc@lists.ozlabs.org Delivered-To: openbmc@lists.ozlabs.org Authentication-Results: lists.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=aj.id.au (client-ip=66.111.4.27; helo=out3-smtp.messagingengine.com; envelope-from=andrew@aj.id.au; receiver=) Authentication-Results: lists.ozlabs.org; dmarc=none (p=none dis=none) header.from=aj.id.au Authentication-Results: lists.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=aj.id.au header.i=@aj.id.au header.a=rsa-sha256 header.s=fm3 header.b=Fzfy+mt8; dkim=pass (2048-bit key; unprotected) header.d=messagingengine.com header.i=@messagingengine.com header.a=rsa-sha256 header.s=fm3 header.b=CSkx8Rtb; dkim-atps=neutral Received: from out3-smtp.messagingengine.com (out3-smtp.messagingengine.com [66.111.4.27]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by lists.ozlabs.org (Postfix) with ESMTPS id 4BhFf30FzJzDqLl for ; Wed, 2 Sep 2020 17:18:18 +1000 (AEST) Received: from compute3.internal (compute3.nyi.internal [10.202.2.43]) by mailout.nyi.internal (Postfix) with ESMTP id C234A5C0189; Wed, 2 Sep 2020 03:18:15 -0400 (EDT) Received: from mailfrontend1 ([10.202.2.162]) by compute3.internal (MEProxy); Wed, 02 Sep 2020 03:18:15 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=aj.id.au; h=from :to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; s=fm3; bh=apf0w6uSspxIj iE/gEi4e8hpQHuG54bqfxnADmsjXn0=; b=Fzfy+mt8VQNtQCtlGYh7MK4NOYKMc zbQPzkRhdMbLRc4vLZO89XWvDAriotZfP+SBcOCM7qEgz2kwXrG8eVJl6G4YQ8AG JCsWHcvvdV/i7BVgXp798NKwH5mr+luoZ3OCOweeqe9QAM3C4tBUyh51dRuZSC/p b4ojazBqeg67/7PbUNwq59UvrGJYc3oys2rAI/rjpLyHd7QQNGBmOY6qb1OYiLeL wkzI9RVPrTyjjYhHalU1+ca7mKsK58LoELXV1CkTpuqAJiAJcOEvcnuw4eegm2si xyRy8a2irPCd/O05xeK+U07Puo2vAleFIzsCfT2HZLscFHx9ER5vSb8uQ== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:content-transfer-encoding:date:from :in-reply-to:message-id:mime-version:references:subject:to :x-me-proxy:x-me-proxy:x-me-sender:x-me-sender:x-sasl-enc; s= fm3; bh=apf0w6uSspxIjiE/gEi4e8hpQHuG54bqfxnADmsjXn0=; b=CSkx8Rtb lhCL9KQ+LTTFxYADzGGtosgxBoLBOcnMgq/hnfB1o9XXtKz0poG3LJt69paFWoab J0lkLRxFM/ujn413rpJApZWr9YsyPyVTgnSY1UBha7t9inEdyYqdnl9G7iE7Ri6F lZTpCkR74RwEzzmsWfO+7dg7WBkUyL7TLuMXoJRmHwLRv2quR75e1D9SDjuSWNnU 0g178+URx7KFrVVVfegPMRRz9oO4rbqNEAp+qfR0ik+UoON/lXVIfez53ekWZSLW TP4ybDIZ3n6RLgM234GozIQZbIosuTn35t7+GV74Q4REEjDejrLlLrUOuRXZZBYC O5NRvu5EFFc0pA== X-ME-Sender: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgeduiedrudefkedguddukecutefuodetggdotefrod ftvfcurfhrohhfihhlvgemucfhrghsthforghilhdpqfgfvfdpuffrtefokffrpgfnqfgh necuuegrihhlohhuthemuceftddtnecunecujfgurhephffvufffkffojghfggfgsedtke ertdertddtnecuhfhrohhmpeetnhgurhgvficulfgvfhhfvghrhicuoegrnhgurhgvfies rghjrdhiugdrrghuqeenucggtffrrghtthgvrhhnpeejgfdvveehteekveeggeellefgle etteejffelffdvudduveeiffegteelvefhteenucfkphepudegrddvrddutdelrdekheen ucevlhhushhtvghrufhiiigvpedtnecurfgrrhgrmhepmhgrihhlfhhrohhmpegrnhgurh gvfiesrghjrdhiugdrrghu X-ME-Proxy: Received: from localhost.localdomain (ppp14-2-109-85.adl-apt-pir-bras32.tpg.internode.on.net [14.2.109.85]) by mail.messagingengine.com (Postfix) with ESMTPA id 90D7C3280066; Wed, 2 Sep 2020 03:18:14 -0400 (EDT) From: Andrew Jeffery To: openbmc@lists.ozlabs.org Subject: [PATCH linux dev-5.8 1/3] i2c: Allow throttling of transfers to client devices Date: Wed, 2 Sep 2020 16:47:34 +0930 Message-Id: <20200902071736.2578715-2-andrew@aj.id.au> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20200902071736.2578715-1-andrew@aj.id.au> References: <20200902071736.2578715-1-andrew@aj.id.au> MIME-Version: 1.0 X-BeenThere: openbmc@lists.ozlabs.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Development list for OpenBMC List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: openbmc-bounces+incoming=patchwork.ozlabs.org@lists.ozlabs.org Sender: "openbmc" Some devices fail to cope in disastrous ways with the small command turn-around times enabled by in-kernel device drivers. Introduce per-client throttling of transfers to avoid these issues. Signed-off-by: Andrew Jeffery --- drivers/i2c/i2c-core-base.c | 8 +- drivers/i2c/i2c-core-smbus.c | 169 +++++++++++++++++++++++++++++------ drivers/i2c/i2c-core.h | 21 +++++ include/linux/i2c.h | 5 ++ 4 files changed, 172 insertions(+), 31 deletions(-) diff --git a/drivers/i2c/i2c-core-base.c b/drivers/i2c/i2c-core-base.c index 26f03a14a478..caf23868e490 100644 --- a/drivers/i2c/i2c-core-base.c +++ b/drivers/i2c/i2c-core-base.c @@ -741,13 +741,17 @@ int i2c_dev_irq_from_resources(const struct resource *resources, struct i2c_client * i2c_new_client_device(struct i2c_adapter *adap, struct i2c_board_info const *info) { + struct i2c_client_priv *priv; struct i2c_client *client; int status; - client = kzalloc(sizeof *client, GFP_KERNEL); - if (!client) + priv = kzalloc(sizeof *priv, GFP_KERNEL); + if (!priv) return ERR_PTR(-ENOMEM); + mutex_init(&priv->throttle_lock); + client = &priv->client; + client->adapter = adap; client->dev.platform_data = info->platform_data; diff --git a/drivers/i2c/i2c-core-smbus.c b/drivers/i2c/i2c-core-smbus.c index f5c9787992e9..1dde58c8a387 100644 --- a/drivers/i2c/i2c-core-smbus.c +++ b/drivers/i2c/i2c-core-smbus.c @@ -10,6 +10,7 @@ * SMBus 2.0 support by Mark Studebaker and * Jean Delvare */ +#include #include #include #include @@ -21,6 +22,9 @@ #define CREATE_TRACE_POINTS #include +static s32 i2c_smbus_throttle_xfer(const struct i2c_client *client, + char read_write, u8 command, int protocol, + union i2c_smbus_data *data); /* The SMBus parts */ @@ -95,9 +99,9 @@ s32 i2c_smbus_read_byte(const struct i2c_client *client) union i2c_smbus_data data; int status; - status = i2c_smbus_xfer(client->adapter, client->addr, client->flags, - I2C_SMBUS_READ, 0, - I2C_SMBUS_BYTE, &data); + status = i2c_smbus_throttle_xfer(client, I2C_SMBUS_READ, 0, + I2C_SMBUS_BYTE, &data); + return (status < 0) ? status : data.byte; } EXPORT_SYMBOL(i2c_smbus_read_byte); @@ -112,8 +116,8 @@ EXPORT_SYMBOL(i2c_smbus_read_byte); */ s32 i2c_smbus_write_byte(const struct i2c_client *client, u8 value) { - return i2c_smbus_xfer(client->adapter, client->addr, client->flags, - I2C_SMBUS_WRITE, value, I2C_SMBUS_BYTE, NULL); + return i2c_smbus_throttle_xfer(client, I2C_SMBUS_WRITE, value, + I2C_SMBUS_BYTE, NULL); } EXPORT_SYMBOL(i2c_smbus_write_byte); @@ -130,9 +134,9 @@ s32 i2c_smbus_read_byte_data(const struct i2c_client *client, u8 command) union i2c_smbus_data data; int status; - status = i2c_smbus_xfer(client->adapter, client->addr, client->flags, - I2C_SMBUS_READ, command, - I2C_SMBUS_BYTE_DATA, &data); + status = i2c_smbus_throttle_xfer(client, I2C_SMBUS_READ, command, + I2C_SMBUS_BYTE_DATA, &data); + return (status < 0) ? status : data.byte; } EXPORT_SYMBOL(i2c_smbus_read_byte_data); @@ -150,10 +154,10 @@ s32 i2c_smbus_write_byte_data(const struct i2c_client *client, u8 command, u8 value) { union i2c_smbus_data data; + data.byte = value; - return i2c_smbus_xfer(client->adapter, client->addr, client->flags, - I2C_SMBUS_WRITE, command, - I2C_SMBUS_BYTE_DATA, &data); + return i2c_smbus_throttle_xfer(client, I2C_SMBUS_WRITE, command, + I2C_SMBUS_BYTE_DATA, &data); } EXPORT_SYMBOL(i2c_smbus_write_byte_data); @@ -170,9 +174,9 @@ s32 i2c_smbus_read_word_data(const struct i2c_client *client, u8 command) union i2c_smbus_data data; int status; - status = i2c_smbus_xfer(client->adapter, client->addr, client->flags, - I2C_SMBUS_READ, command, - I2C_SMBUS_WORD_DATA, &data); + status = i2c_smbus_throttle_xfer(client, I2C_SMBUS_READ, command, + I2C_SMBUS_WORD_DATA, &data); + return (status < 0) ? status : data.word; } EXPORT_SYMBOL(i2c_smbus_read_word_data); @@ -190,10 +194,10 @@ s32 i2c_smbus_write_word_data(const struct i2c_client *client, u8 command, u16 value) { union i2c_smbus_data data; + data.word = value; - return i2c_smbus_xfer(client->adapter, client->addr, client->flags, - I2C_SMBUS_WRITE, command, - I2C_SMBUS_WORD_DATA, &data); + return i2c_smbus_throttle_xfer(client, I2C_SMBUS_WRITE, command, + I2C_SMBUS_WORD_DATA, &data); } EXPORT_SYMBOL(i2c_smbus_write_word_data); @@ -218,9 +222,9 @@ s32 i2c_smbus_read_block_data(const struct i2c_client *client, u8 command, union i2c_smbus_data data; int status; - status = i2c_smbus_xfer(client->adapter, client->addr, client->flags, - I2C_SMBUS_READ, command, - I2C_SMBUS_BLOCK_DATA, &data); + status = i2c_smbus_throttle_xfer(client, I2C_SMBUS_READ, command, + I2C_SMBUS_BLOCK_DATA, &data); + if (status) return status; @@ -248,9 +252,8 @@ s32 i2c_smbus_write_block_data(const struct i2c_client *client, u8 command, length = I2C_SMBUS_BLOCK_MAX; data.block[0] = length; memcpy(&data.block[1], values, length); - return i2c_smbus_xfer(client->adapter, client->addr, client->flags, - I2C_SMBUS_WRITE, command, - I2C_SMBUS_BLOCK_DATA, &data); + return i2c_smbus_throttle_xfer(client, I2C_SMBUS_WRITE, command, + I2C_SMBUS_BLOCK_DATA, &data); } EXPORT_SYMBOL(i2c_smbus_write_block_data); @@ -264,9 +267,9 @@ s32 i2c_smbus_read_i2c_block_data(const struct i2c_client *client, u8 command, if (length > I2C_SMBUS_BLOCK_MAX) length = I2C_SMBUS_BLOCK_MAX; data.block[0] = length; - status = i2c_smbus_xfer(client->adapter, client->addr, client->flags, - I2C_SMBUS_READ, command, - I2C_SMBUS_I2C_BLOCK_DATA, &data); + status = i2c_smbus_throttle_xfer(client, I2C_SMBUS_READ, command, + I2C_SMBUS_I2C_BLOCK_DATA, &data); + if (status < 0) return status; @@ -284,9 +287,8 @@ s32 i2c_smbus_write_i2c_block_data(const struct i2c_client *client, u8 command, length = I2C_SMBUS_BLOCK_MAX; data.block[0] = length; memcpy(data.block + 1, values, length); - return i2c_smbus_xfer(client->adapter, client->addr, client->flags, - I2C_SMBUS_WRITE, command, - I2C_SMBUS_I2C_BLOCK_DATA, &data); + return i2c_smbus_throttle_xfer(client, I2C_SMBUS_WRITE, command, + I2C_SMBUS_I2C_BLOCK_DATA, &data); } EXPORT_SYMBOL(i2c_smbus_write_i2c_block_data); @@ -547,6 +549,71 @@ s32 i2c_smbus_xfer(struct i2c_adapter *adapter, u16 addr, } EXPORT_SYMBOL(i2c_smbus_xfer); +static int i2c_smbus_throttle_enter(const struct i2c_client *client) + __acquires(&priv->throttle_lock) +{ + struct i2c_client_priv *priv; + ktime_t earliest; + int rc; + + priv = to_i2c_client_priv(client); + + if (i2c_in_atomic_xfer_mode()) { + if (!mutex_trylock(&priv->throttle_lock)) + return -EAGAIN; + } else { + rc = mutex_lock_interruptible(&priv->throttle_lock); + if (rc) + return rc; + } + earliest = ktime_add_us(priv->last, priv->delay_us); + + if (priv->delay_us && ktime_before(ktime_get(), earliest)) { + if (i2c_in_atomic_xfer_mode()) { + mutex_unlock(&priv->throttle_lock); + return -EAGAIN; + } + + usleep_range(priv->delay_us, 2 * priv->delay_us); + } + + return 0; +} + +static void i2c_smbus_throttle_exit(const struct i2c_client *client) + __releases(&priv->throttle_lock) +{ + struct i2c_client_priv *priv; + + priv = to_i2c_client_priv(client); + + if (priv->delay_us) + priv->last = ktime_get(); + mutex_unlock(&priv->throttle_lock); +} + +static s32 i2c_smbus_throttle_xfer(const struct i2c_client *client, + char read_write, u8 command, int protocol, + union i2c_smbus_data *data) +{ + s32 res; + + res = i2c_smbus_throttle_enter(client); + if (res) + return res; + + res = __i2c_lock_bus_helper(client->adapter); + if (!res) + res = __i2c_smbus_xfer(client->adapter, client->addr, + client->flags, read_write, command, + protocol, data); + i2c_unlock_bus(client->adapter, I2C_LOCK_SEGMENT); + + i2c_smbus_throttle_exit(client); + + return res; +} + s32 __i2c_smbus_xfer(struct i2c_adapter *adapter, u16 addr, unsigned short flags, char read_write, u8 command, int protocol, union i2c_smbus_data *data) @@ -715,3 +782,47 @@ int of_i2c_setup_smbus_alert(struct i2c_adapter *adapter) } EXPORT_SYMBOL_GPL(of_i2c_setup_smbus_alert); #endif + +int i2c_smbus_throttle_client(struct i2c_client *client, + unsigned long delay_us) +{ + struct i2c_client_priv *priv; + int rc; + + priv = to_i2c_client_priv(client); + + if (i2c_in_atomic_xfer_mode()) { + if (!mutex_trylock(&priv->throttle_lock)) + return -EAGAIN; + } else { + rc = mutex_lock_interruptible(&priv->throttle_lock); + if (rc) + return rc; + } + priv->delay_us = delay_us; + priv->last = ktime_get(); + mutex_unlock(&priv->throttle_lock); + + return 0; +} + +int i2c_smbus_throttle_value(struct i2c_client *client, unsigned long *delay_us) +{ + struct i2c_client_priv *priv; + int rc; + + priv = to_i2c_client_priv(client); + + if (i2c_in_atomic_xfer_mode()) { + if (!mutex_trylock(&priv->throttle_lock)) + return -EAGAIN; + } else { + rc = mutex_lock_interruptible(&priv->throttle_lock); + if (rc) + return rc; + } + *delay_us = priv->delay_us; + mutex_unlock(&priv->throttle_lock); + + return 0; +} diff --git a/drivers/i2c/i2c-core.h b/drivers/i2c/i2c-core.h index 94ff1693b391..d56ee47da5b3 100644 --- a/drivers/i2c/i2c-core.h +++ b/drivers/i2c/i2c-core.h @@ -4,6 +4,27 @@ */ #include +#include +#include +#include +#include + +struct i2c_client_priv { + struct i2c_client client; + + /* + * Per-client access throttling, described in terms of microsecond + * delay between the end of the nth transfer and the start of the + * (n+1)th transfer + * + * Do it in a wrapper struct to preserve const-ness of the i2c_smbus_* + * interfaces. + */ + struct mutex throttle_lock; + unsigned long delay_us; + ktime_t last; +}; +#define to_i2c_client_priv(c) container_of(c, struct i2c_client_priv, client) struct i2c_devinfo { struct list_head list; diff --git a/include/linux/i2c.h b/include/linux/i2c.h index 4e7714c88f95..941dde784472 100644 --- a/include/linux/i2c.h +++ b/include/linux/i2c.h @@ -181,8 +181,13 @@ s32 i2c_smbus_write_i2c_block_data(const struct i2c_client *client, s32 i2c_smbus_read_i2c_block_data_or_emulated(const struct i2c_client *client, u8 command, u8 length, u8 *values); +int i2c_smbus_throttle_client(struct i2c_client *client, + unsigned long delay_us); +int i2c_smbus_throttle_value(struct i2c_client *client, + unsigned long *delay_us); int i2c_get_device_id(const struct i2c_client *client, struct i2c_device_identity *id); + #endif /* I2C */ /** From patchwork Wed Sep 2 07:17:35 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrew Jeffery X-Patchwork-Id: 1355564 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.ozlabs.org (lists.ozlabs.org [203.11.71.2]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4BhFkd08hsz9sTM for ; Wed, 2 Sep 2020 17:22:17 +1000 (AEST) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=aj.id.au Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=aj.id.au header.i=@aj.id.au header.a=rsa-sha256 header.s=fm3 header.b=VzXzG+GT; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=messagingengine.com header.i=@messagingengine.com header.a=rsa-sha256 header.s=fm3 header.b=XR6ZK8R+; dkim-atps=neutral Received: from bilbo.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) by lists.ozlabs.org (Postfix) with ESMTP id 4BhFkc5RxtzDqlc for ; Wed, 2 Sep 2020 17:22:16 +1000 (AEST) X-Original-To: openbmc@lists.ozlabs.org Delivered-To: openbmc@lists.ozlabs.org Authentication-Results: lists.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=aj.id.au (client-ip=66.111.4.27; helo=out3-smtp.messagingengine.com; envelope-from=andrew@aj.id.au; receiver=) Authentication-Results: lists.ozlabs.org; dmarc=none (p=none dis=none) header.from=aj.id.au Authentication-Results: lists.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=aj.id.au header.i=@aj.id.au header.a=rsa-sha256 header.s=fm3 header.b=VzXzG+GT; dkim=pass (2048-bit key; unprotected) header.d=messagingengine.com header.i=@messagingengine.com header.a=rsa-sha256 header.s=fm3 header.b=XR6ZK8R+; dkim-atps=neutral Received: from out3-smtp.messagingengine.com (out3-smtp.messagingengine.com [66.111.4.27]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by lists.ozlabs.org (Postfix) with ESMTPS id 4BhFf345r8zDqMt for ; Wed, 2 Sep 2020 17:18:19 +1000 (AEST) Received: from compute3.internal (compute3.nyi.internal [10.202.2.43]) by mailout.nyi.internal (Postfix) with ESMTP id 479CC5C015B; Wed, 2 Sep 2020 03:18:17 -0400 (EDT) Received: from mailfrontend1 ([10.202.2.162]) by compute3.internal (MEProxy); Wed, 02 Sep 2020 03:18:17 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=aj.id.au; h=from :to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; s=fm3; bh=su/KvZ9gwUaQr V9Eu6qfA9NKeJhc/8IMlA0nFzAli0U=; b=VzXzG+GTpoAkPrG4PE/DZrgPji8e4 1vO9Nvt/Tra5Y3aN3fOHtAvYq8YIBsYgOoASzUFC7sQ5Hj/3/JBhy1CYj4FvbRyn 0kPgxBI/zVFzD7V6j0bgMjtsOxa1URvGZZIfeXHLjHxCyOyk99p0/pQNkVTyMXiD eYt/bameBnzsLdXOZLSXbS5Q4Qy8jyBVs6OitBEzLk4+onZJjVwew4hoR5tkzQqg VU0Kr9uNfMeG/QaVa/yMJiC7UtHL++To/HzYAQ7nEsBzlAduz5Xmkmu0hHIogOBU ORE4+EynLvKUwPHt7g6vZ8cynJ4MbC6xodfsrMN/TlFQh/Vp/aFRG+hXw== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:content-transfer-encoding:date:from :in-reply-to:message-id:mime-version:references:subject:to :x-me-proxy:x-me-proxy:x-me-sender:x-me-sender:x-sasl-enc; s= fm3; bh=su/KvZ9gwUaQrV9Eu6qfA9NKeJhc/8IMlA0nFzAli0U=; b=XR6ZK8R+ V4kQYqtKRoM2gLRArbC6JFrI7sz9Ka/kX30M8wlkaPB6D/yEdoOa8yBey42eq8ZJ BdRnLSZ5uGEE67Nyl1obB1pR+zYvL8g6euhUc97Xpp0dNBXIZwNo+nfJxwxih4Wk wIEgH8C3G2s6jxxxnlF/pzY8hhNTdItjZ4avQxUXi7EpyhKTS0lj19z215VgQ8i9 7NF9+BKNsw5SouYECNNt8BeD46QjT8Gb46/0p21wJbrUsat1DbbKDy3zzNx/bB1+ NFL0QHRfM17PhxzTMofVqTe8IpVf4LZneHWDeP4+YkYZJmV5DfkvrrZUyz88onI0 MQfjhpGluU62+w== X-ME-Sender: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgeduiedrudefkedguddukecutefuodetggdotefrod ftvfcurfhrohhfihhlvgemucfhrghsthforghilhdpqfgfvfdpuffrtefokffrpgfnqfgh necuuegrihhlohhuthemuceftddtnecunecujfgurhephffvufffkffojghfggfgsedtke ertdertddtnecuhfhrohhmpeetnhgurhgvficulfgvfhhfvghrhicuoegrnhgurhgvfies rghjrdhiugdrrghuqeenucggtffrrghtthgvrhhnpeejgfdvveehteekveeggeellefgle etteejffelffdvudduveeiffegteelvefhteenucfkphepudegrddvrddutdelrdekheen ucevlhhushhtvghrufhiiigvpedtnecurfgrrhgrmhepmhgrihhlfhhrohhmpegrnhgurh gvfiesrghjrdhiugdrrghu X-ME-Proxy: Received: from localhost.localdomain (ppp14-2-109-85.adl-apt-pir-bras32.tpg.internode.on.net [14.2.109.85]) by mail.messagingengine.com (Postfix) with ESMTPA id 18DE6328005E; Wed, 2 Sep 2020 03:18:15 -0400 (EDT) From: Andrew Jeffery To: openbmc@lists.ozlabs.org Subject: [PATCH linux dev-5.8 2/3] pmbus: (ucd9000) Throttle SMBus transfers to avoid poor behaviour Date: Wed, 2 Sep 2020 16:47:35 +0930 Message-Id: <20200902071736.2578715-3-andrew@aj.id.au> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20200902071736.2578715-1-andrew@aj.id.au> References: <20200902071736.2578715-1-andrew@aj.id.au> MIME-Version: 1.0 X-BeenThere: openbmc@lists.ozlabs.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Development list for OpenBMC List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: openbmc-bounces+incoming=patchwork.ozlabs.org@lists.ozlabs.org Sender: "openbmc" Short turn-around times between transfers to UCD9000 devices can lead to problematic behaviour, including unnecessary clock stretching, bus lockups and potential corruption of the device's volatile state. Introduce transfer throttling for the device with a minimum access delay of 1ms. Signed-off-by: Andrew Jeffery --- drivers/hwmon/pmbus/ucd9000.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/hwmon/pmbus/ucd9000.c b/drivers/hwmon/pmbus/ucd9000.c index 81f4c4f166cd..7ba400d62475 100644 --- a/drivers/hwmon/pmbus/ucd9000.c +++ b/drivers/hwmon/pmbus/ucd9000.c @@ -487,6 +487,8 @@ static int ucd9000_init_debugfs(struct i2c_client *client, } #endif /* CONFIG_DEBUG_FS */ +#define UCD9000_SMBUS_THROTTLE_US 1000 + static int ucd9000_probe(struct i2c_client *client, const struct i2c_device_id *id) { @@ -502,6 +504,8 @@ static int ucd9000_probe(struct i2c_client *client, I2C_FUNC_SMBUS_BLOCK_DATA)) return -ENODEV; + i2c_smbus_throttle_client(client, UCD9000_SMBUS_THROTTLE_US); + ret = i2c_smbus_read_block_data(client, UCD9000_DEVICE_ID, block_buffer); if (ret < 0) { From patchwork Wed Sep 2 07:17:36 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrew Jeffery X-Patchwork-Id: 1355563 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.ozlabs.org (lists.ozlabs.org [203.11.71.2]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4BhFjD4mXRz9sR4 for ; Wed, 2 Sep 2020 17:21:04 +1000 (AEST) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=aj.id.au Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=aj.id.au header.i=@aj.id.au header.a=rsa-sha256 header.s=fm3 header.b=FP/wi00h; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=messagingengine.com header.i=@messagingengine.com header.a=rsa-sha256 header.s=fm3 header.b=kBTWsLvZ; dkim-atps=neutral Received: from bilbo.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) by lists.ozlabs.org (Postfix) with ESMTP id 4BhFjD3NY4zDqMt for ; Wed, 2 Sep 2020 17:21:04 +1000 (AEST) X-Original-To: openbmc@lists.ozlabs.org Delivered-To: openbmc@lists.ozlabs.org Authentication-Results: lists.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=aj.id.au (client-ip=66.111.4.27; helo=out3-smtp.messagingengine.com; envelope-from=andrew@aj.id.au; receiver=) Authentication-Results: lists.ozlabs.org; dmarc=none (p=none dis=none) header.from=aj.id.au Authentication-Results: lists.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=aj.id.au header.i=@aj.id.au header.a=rsa-sha256 header.s=fm3 header.b=FP/wi00h; dkim=pass (2048-bit key; unprotected) header.d=messagingengine.com header.i=@messagingengine.com header.a=rsa-sha256 header.s=fm3 header.b=kBTWsLvZ; dkim-atps=neutral Received: from out3-smtp.messagingengine.com (out3-smtp.messagingengine.com [66.111.4.27]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by lists.ozlabs.org (Postfix) with ESMTPS id 4BhFf50hrHzDqNC for ; Wed, 2 Sep 2020 17:18:20 +1000 (AEST) Received: from compute3.internal (compute3.nyi.internal [10.202.2.43]) by mailout.nyi.internal (Postfix) with ESMTP id C71A95C015A; Wed, 2 Sep 2020 03:18:18 -0400 (EDT) Received: from mailfrontend1 ([10.202.2.162]) by compute3.internal (MEProxy); Wed, 02 Sep 2020 03:18:18 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=aj.id.au; h=from :to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; s=fm3; bh=DF+8WFKZkNfE/ hAl8yMNRNK11HZVnTOJW81VOZQCus0=; b=FP/wi00hr4FvKkskg+PMRDgMfiuQX aoDi3LCdxbCxMpnFp9AJ9naI1+gLA96PcUF8O6Cu33/OQ/8mcDyTsKhPN1YTsHj/ tCcL4wnoICE5Aift2N9dDkmoooOmoG0SlrlCXyDzEHvKwuGwhk9avd/AsRZnvFxY piGj7HRK7eIRb9Qhd4yOpFCt3+qHKchfZTC0jEO3d3MrX+DR/w2z0nFwJokPwocL 5FDsbLTlxfVqzqOtwNc+Ax3M1ihiBgSqxScHZ9Ur5PSo4uA+QE+CHTsaN8y2GcAi 57GKlYflZdtVUyJQfCTrLCQ7ZV+4fqPGN/LWtV+T9Pp7ftlU0KPFNfH/Q== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:content-transfer-encoding:date:from :in-reply-to:message-id:mime-version:references:subject:to :x-me-proxy:x-me-proxy:x-me-sender:x-me-sender:x-sasl-enc; s= fm3; bh=DF+8WFKZkNfE/hAl8yMNRNK11HZVnTOJW81VOZQCus0=; b=kBTWsLvZ M+3QoNxLpmOgH00sk+F84yKpVyaQxZJOq61/KIakbGSY/grzsN/ob/+2R03maz6O gtHiNYUbZm2jAqtjPV17JtvF8Mm6Sw5yK3yMsKflRVArWxKk3Mlx30Jv7Ydvj+Jw kaoVhvG22meuHoe4yWsJtYvvJZBCXFTKwoITNROSe9ctrcmZJ4jQHJJYW5J9UWQc xpHtwlfSDZnuwHC9b7nVzbqyYBKBndib5DLK9bWkBf11ij2dQ+rGo37G7kq0xuvH nqniOuo69XmSdv4eJeXj6JUdHsNTUya3MfUVvoPY7PlELJXPxU11QqYC0yLgguPk 7AsMx+4RNib6TQ== X-ME-Sender: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgeduiedrudefkedguddukecutefuodetggdotefrod ftvfcurfhrohhfihhlvgemucfhrghsthforghilhdpqfgfvfdpuffrtefokffrpgfnqfgh necuuegrihhlohhuthemuceftddtnecunecujfgurhephffvufffkffojghfggfgsedtke ertdertddtnecuhfhrohhmpeetnhgurhgvficulfgvfhhfvghrhicuoegrnhgurhgvfies rghjrdhiugdrrghuqeenucggtffrrghtthgvrhhnpeejgfdvveehteekveeggeellefgle etteejffelffdvudduveeiffegteelvefhteenucfkphepudegrddvrddutdelrdekheen ucevlhhushhtvghrufhiiigvpedtnecurfgrrhgrmhepmhgrihhlfhhrohhmpegrnhgurh gvfiesrghjrdhiugdrrghu X-ME-Proxy: Received: from localhost.localdomain (ppp14-2-109-85.adl-apt-pir-bras32.tpg.internode.on.net [14.2.109.85]) by mail.messagingengine.com (Postfix) with ESMTPA id 93F0E328005D; Wed, 2 Sep 2020 03:18:17 -0400 (EDT) From: Andrew Jeffery To: openbmc@lists.ozlabs.org Subject: [PATCH linux dev-5.8 3/3] ucd9000: Add a throttle delay attribute in debugfs Date: Wed, 2 Sep 2020 16:47:36 +0930 Message-Id: <20200902071736.2578715-4-andrew@aj.id.au> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20200902071736.2578715-1-andrew@aj.id.au> References: <20200902071736.2578715-1-andrew@aj.id.au> MIME-Version: 1.0 X-BeenThere: openbmc@lists.ozlabs.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Development list for OpenBMC List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: openbmc-bounces+incoming=patchwork.ozlabs.org@lists.ozlabs.org Sender: "openbmc" Signed-off-by: Andrew Jeffery --- drivers/hwmon/pmbus/ucd9000.c | 39 ++++++++++++++++++++++++++++++++--- 1 file changed, 36 insertions(+), 3 deletions(-) diff --git a/drivers/hwmon/pmbus/ucd9000.c b/drivers/hwmon/pmbus/ucd9000.c index 7ba400d62475..23036f1b1bd1 100644 --- a/drivers/hwmon/pmbus/ucd9000.c +++ b/drivers/hwmon/pmbus/ucd9000.c @@ -401,6 +401,37 @@ static int ucd9000_debugfs_show_mfr_status_bit(void *data, u64 *val) DEFINE_DEBUGFS_ATTRIBUTE(ucd9000_debugfs_mfr_status_bit, ucd9000_debugfs_show_mfr_status_bit, NULL, "%1lld\n"); +#define UCD9000_SMBUS_THROTTLE_US 1000 +static int throttle_delay_us = UCD9000_SMBUS_THROTTLE_US; + +static int ucd9000_debugfs_show_smbus_throttle_delay(void *data, + u64 *val) +{ + struct i2c_client *client = data; + unsigned long ulval; + int rc; + + rc = i2c_smbus_throttle_value(client, &ulval); + if (rc) + return rc; + + *val = ulval; + + return 0; +} + +static int ucd9000_debugfs_store_smbus_throttle_delay(void *data, + u64 val) +{ + struct i2c_client *client = data; + + throttle_delay_us = val; + return i2c_smbus_throttle_client(client, val); +} +DEFINE_DEBUGFS_ATTRIBUTE(ucd9000_debugfs_smbus_throttle_delay, + ucd9000_debugfs_show_smbus_throttle_delay, + ucd9000_debugfs_store_smbus_throttle_delay, "%llu\n"); + static ssize_t ucd9000_debugfs_read_mfr_status(struct file *file, char __user *buf, size_t count, loff_t *ppos) @@ -475,6 +506,8 @@ static int ucd9000_init_debugfs(struct i2c_client *client, scnprintf(name, UCD9000_DEBUGFS_NAME_LEN, "mfr_status"); debugfs_create_file(name, 0444, data->debugfs, client, &ucd9000_debugfs_show_mfr_status_fops); + debugfs_create_file("smbus_throttle_delay", 0664, data->debugfs, client, + &ucd9000_debugfs_smbus_throttle_delay); return 0; } @@ -487,8 +520,6 @@ static int ucd9000_init_debugfs(struct i2c_client *client, } #endif /* CONFIG_DEBUG_FS */ -#define UCD9000_SMBUS_THROTTLE_US 1000 - static int ucd9000_probe(struct i2c_client *client, const struct i2c_device_id *id) { @@ -504,7 +535,9 @@ static int ucd9000_probe(struct i2c_client *client, I2C_FUNC_SMBUS_BLOCK_DATA)) return -ENODEV; - i2c_smbus_throttle_client(client, UCD9000_SMBUS_THROTTLE_US); + ret = i2c_smbus_throttle_client(client, throttle_delay_us); + if (ret) + return ret; ret = i2c_smbus_read_block_data(client, UCD9000_DEVICE_ID, block_buffer);