From 82dbc15a05125a812c140a3c8cff81c366482229 Mon Sep 17 00:00:00 2001 From: "Jason M. Bills" Date: Mon, 7 Dec 2020 13:45:20 -0800 Subject: Update to internal 0.26 Signed-off-by: Jason M. Bills --- .../0040-i2c-Add-mux-hold-unhold-msg-types.patch | 488 --------------------- 1 file changed, 488 deletions(-) delete mode 100644 meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0040-i2c-Add-mux-hold-unhold-msg-types.patch (limited to 'meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0040-i2c-Add-mux-hold-unhold-msg-types.patch') diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0040-i2c-Add-mux-hold-unhold-msg-types.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0040-i2c-Add-mux-hold-unhold-msg-types.patch deleted file mode 100644 index 198beaa93..000000000 --- a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0040-i2c-Add-mux-hold-unhold-msg-types.patch +++ /dev/null @@ -1,488 +0,0 @@ -From ee9cee93b96b791f52295d7763985fdb10903e2b Mon Sep 17 00:00:00 2001 -From: Jae Hyun Yoo -Date: Fri, 15 Feb 2019 16:05:09 -0800 -Subject: [PATCH] i2c: Add mux hold/unhold msg types - -This commit adds mux hold/unhold message types to support extended -mux control for IPMB and MCTP devices. A hold or an unhold message -can be added at the end of I2C message stream wrapped by -repeated-start, also can be used as a single message independantly. - -This mux hold/unhold message will be delivered throughout all mux -levels in the path. Means that if it goes to multi-level mux path, -all muxes will be held/unheld by this message. - -1. Hold message - struct i2c_msg msg; - uint16_t timeout = 5000; // timeout in ms. 5 secs in this example. - - msg.addr = 0x0; // any value can be used. addr will be ignored in this packet. - msg.flags = I2C_M_HOLD; // set this flag to indicate it's a hold message. - msg.len = sizeof(uint16_t); // timeout value will be delivered using two bytes buffer. - msg.buf = (uint8_t *)&timeout; // set timeout value. - -2. Unhold message - struct i2c_msg msg; - uint16_t timeout = 0; // set 0 for an unhold message. - - msg.addr = 0x0; // any value can be used. addr will be ignored in this packet. - msg.flags = I2C_M_HOLD; // set this flag to indicate it's an unhold message. - msg.len = sizeof(uint16_t); // timeout value will be delivered using two bytes buffer. - msg.buf = (uint8_t *)&timeout; // set timeout value. - - This unhold message can be delivered to a mux adapter even when - a bus is locked so that any holding state can be unheld - immediately by invoking this unhold message. - -This patch would not be welcomed from upstream so it should be kept -in downstream only. - -Signed-off-by: Jae Hyun Yoo ---- - drivers/i2c/i2c-core-base.c | 70 +++++++++++++++++++++++++-- - drivers/i2c/i2c-core-smbus.c | 22 +++++++-- - drivers/i2c/i2c-mux.c | 109 +++++++++++++++++++++++++++++++++++++++---- - include/linux/i2c-mux.h | 3 ++ - include/linux/i2c.h | 25 ++++++++++ - include/uapi/linux/i2c.h | 1 + - 6 files changed, 214 insertions(+), 16 deletions(-) - -diff --git a/drivers/i2c/i2c-core-base.c b/drivers/i2c/i2c-core-base.c -index 5f6a4985f2bc..d1cd7afe4068 100644 ---- a/drivers/i2c/i2c-core-base.c -+++ b/drivers/i2c/i2c-core-base.c -@@ -1297,6 +1297,25 @@ int i2c_handle_smbus_host_notify(struct i2c_adapter *adap, unsigned short addr) - } - EXPORT_SYMBOL_GPL(i2c_handle_smbus_host_notify); - -+static void i2c_adapter_hold(struct i2c_adapter *adapter, unsigned long timeout) -+{ -+ mutex_lock(&adapter->hold_lock); -+ mod_timer(&adapter->hold_timer, jiffies + timeout); -+} -+ -+static void i2c_adapter_unhold(struct i2c_adapter *adapter) -+{ -+ del_timer_sync(&adapter->hold_timer); -+ mutex_unlock(&adapter->hold_lock); -+} -+ -+static void i2c_adapter_hold_timer_callback(struct timer_list *t) -+{ -+ struct i2c_adapter *adapter = from_timer(adapter, t, hold_timer); -+ -+ i2c_adapter_unhold(adapter); -+} -+ - static int i2c_register_adapter(struct i2c_adapter *adap) - { - int res = -EINVAL; -@@ -1379,6 +1398,9 @@ static int i2c_register_adapter(struct i2c_adapter *adap) - bus_for_each_drv(&i2c_bus_type, NULL, adap, __process_new_adapter); - mutex_unlock(&core_lock); - -+ mutex_init(&adap->hold_lock); -+ timer_setup(&adap->hold_timer, i2c_adapter_hold_timer_callback, 0); -+ - return 0; - - out_reg: -@@ -1599,6 +1621,8 @@ void i2c_del_adapter(struct i2c_adapter *adap) - idr_remove(&i2c_adapter_idr, adap->nr); - mutex_unlock(&core_lock); - -+ i2c_adapter_unhold(adap); -+ - /* Clear the device structure in case this adapter is ever going to be - added again */ - memset(&adap->dev, 0, sizeof(adap->dev)); -@@ -1948,7 +1972,9 @@ static int i2c_check_for_quirks(struct i2c_adapter *adap, struct i2c_msg *msgs, - */ - int __i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) - { -+ enum i2c_hold_msg_type hold_msg = I2C_HOLD_MSG_NONE; - unsigned long orig_jiffies; -+ unsigned long timeout; - int ret, try; - - if (WARN_ON(!msgs || num < 1)) -@@ -1961,6 +1987,25 @@ int __i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) - if (adap->quirks && i2c_check_for_quirks(adap, msgs, num)) - return -EOPNOTSUPP; - -+ /* Do not deliver a mux hold msg to root bus adapter */ -+ if (!i2c_parent_is_i2c_adapter(adap)) { -+ hold_msg = i2c_check_hold_msg(msgs[num - 1].flags, -+ msgs[num - 1].len, -+ (u16 *)msgs[num - 1].buf); -+ if (hold_msg == I2C_HOLD_MSG_SET) { -+ timeout = msecs_to_jiffies(*(u16 *)msgs[num - 1].buf); -+ i2c_adapter_hold(adap, timeout); -+ -+ if (--num == 0) -+ return 0; -+ } else if (hold_msg == I2C_HOLD_MSG_RESET) { -+ i2c_adapter_unhold(adap); -+ return 0; -+ } else if (hold_msg == I2C_HOLD_MSG_NONE) { -+ mutex_lock(&adap->hold_lock); -+ } -+ } -+ - /* - * i2c_trace_msg_key gets enabled when tracepoint i2c_transfer gets - * enabled. This is an efficient way of keeping the for-loop from -@@ -1997,6 +2042,9 @@ int __i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) - trace_i2c_result(adap, num, ret); - } - -+ if (!i2c_parent_is_i2c_adapter(adap) && hold_msg == I2C_HOLD_MSG_NONE) -+ mutex_unlock(&adap->hold_lock); -+ - return ret; - } - EXPORT_SYMBOL(__i2c_transfer); -@@ -2015,6 +2063,7 @@ EXPORT_SYMBOL(__i2c_transfer); - */ - int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) - { -+ bool do_bus_lock = true; - int ret; - - if (!adap->algo->master_xfer) { -@@ -2038,12 +2087,25 @@ int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) - * one (discarding status on the second message) or errno - * (discarding status on the first one). - */ -- ret = __i2c_lock_bus_helper(adap); -- if (ret) -- return ret; -+ /* -+ * Do not lock a bus for delivering an unhold msg to a mux -+ * adpater. This is just for a single length unhold msg case. -+ */ -+ if (num == 1 && i2c_parent_is_i2c_adapter(adap) && -+ i2c_check_hold_msg(msgs[0].flags, msgs[0].len, -+ (u16 *)msgs[0].buf) == -+ I2C_HOLD_MSG_RESET) -+ do_bus_lock = false; -+ -+ if (do_bus_lock) { -+ ret = __i2c_lock_bus_helper(adap); -+ if (ret) -+ return ret; -+ } - - ret = __i2c_transfer(adap, msgs, num); -- i2c_unlock_bus(adap, I2C_LOCK_SEGMENT); -+ if (do_bus_lock) -+ i2c_unlock_bus(adap, I2C_LOCK_SEGMENT); - - return ret; - } -diff --git a/drivers/i2c/i2c-core-smbus.c b/drivers/i2c/i2c-core-smbus.c -index 3ac426a8ab5a..f7bf95101e34 100644 ---- a/drivers/i2c/i2c-core-smbus.c -+++ b/drivers/i2c/i2c-core-smbus.c -@@ -526,15 +526,29 @@ 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) - { -+ bool do_bus_lock = true; - s32 res; - -- res = __i2c_lock_bus_helper(adapter); -- if (res) -- return res; -+ /* -+ * Do not lock a bus for delivering an unhold msg to a mux adpater. -+ * This is just for a single length unhold msg case. -+ */ -+ if (i2c_parent_is_i2c_adapter(adapter) && -+ i2c_check_hold_msg(flags, -+ protocol == I2C_SMBUS_WORD_DATA ? 2 : 0, -+ &data->word) == I2C_HOLD_MSG_RESET) -+ do_bus_lock = false; -+ -+ if (do_bus_lock) { -+ res = __i2c_lock_bus_helper(adapter); -+ if (res) -+ return res; -+ } - - res = __i2c_smbus_xfer(adapter, addr, flags, read_write, - command, protocol, data); -- i2c_unlock_bus(adapter, I2C_LOCK_SEGMENT); -+ if (do_bus_lock) -+ i2c_unlock_bus(adapter, I2C_LOCK_SEGMENT); - - return res; - } -diff --git a/drivers/i2c/i2c-mux.c b/drivers/i2c/i2c-mux.c -index 774507b54b57..c6e433238b22 100644 ---- a/drivers/i2c/i2c-mux.c -+++ b/drivers/i2c/i2c-mux.c -@@ -27,6 +27,7 @@ - #include - #include - #include -+#include - - /* multiplexer per channel data */ - struct i2c_mux_priv { -@@ -36,21 +37,57 @@ struct i2c_mux_priv { - u32 chan_id; - }; - -+static void i2c_mux_hold(struct i2c_mux_core *muxc, unsigned long timeout) -+{ -+ mutex_lock(&muxc->hold_lock); -+ mod_timer(&muxc->hold_timer, jiffies + timeout); -+} -+ -+static void i2c_mux_unhold(struct i2c_mux_core *muxc) -+{ -+ del_timer_sync(&muxc->hold_timer); -+ mutex_unlock(&muxc->hold_lock); -+} -+ -+static void i2c_mux_hold_timer_callback(struct timer_list *t) -+{ -+ struct i2c_mux_core *muxc = from_timer(muxc, t, hold_timer); -+ -+ i2c_mux_unhold(muxc); -+} -+ - static int __i2c_mux_master_xfer(struct i2c_adapter *adap, - struct i2c_msg msgs[], int num) - { - struct i2c_mux_priv *priv = adap->algo_data; - struct i2c_mux_core *muxc = priv->muxc; - struct i2c_adapter *parent = muxc->parent; -+ enum i2c_hold_msg_type hold_msg; -+ unsigned long timeout; - int ret; - - /* Switch to the right mux port and perform the transfer. */ - -+ hold_msg = i2c_check_hold_msg(msgs[num - 1].flags, -+ msgs[num - 1].len, -+ (u16 *)msgs[num - 1].buf); -+ if (hold_msg == I2C_HOLD_MSG_SET) { -+ timeout = msecs_to_jiffies(*(u16 *)msgs[num - 1].buf); -+ i2c_mux_hold(muxc, timeout); -+ } else if (hold_msg == I2C_HOLD_MSG_NONE) { -+ mutex_lock(&muxc->hold_lock); -+ } - ret = muxc->select(muxc, priv->chan_id); - if (ret >= 0) - ret = __i2c_transfer(parent, msgs, num); -- if (muxc->deselect) -- muxc->deselect(muxc, priv->chan_id); -+ if (hold_msg != I2C_HOLD_MSG_SET) { -+ if (muxc->deselect) -+ muxc->deselect(muxc, priv->chan_id); -+ if (hold_msg == I2C_HOLD_MSG_RESET) -+ i2c_mux_unhold(muxc); -+ else -+ mutex_unlock(&muxc->hold_lock); -+ } - - return ret; - } -@@ -61,15 +98,32 @@ static int i2c_mux_master_xfer(struct i2c_adapter *adap, - struct i2c_mux_priv *priv = adap->algo_data; - struct i2c_mux_core *muxc = priv->muxc; - struct i2c_adapter *parent = muxc->parent; -+ enum i2c_hold_msg_type hold_msg; -+ unsigned long timeout; - int ret; - - /* Switch to the right mux port and perform the transfer. */ - -+ hold_msg = i2c_check_hold_msg(msgs[num - 1].flags, -+ msgs[num - 1].len, -+ (u16 *)msgs[num - 1].buf); -+ if (hold_msg == I2C_HOLD_MSG_SET) { -+ timeout = msecs_to_jiffies(*(u16 *)msgs[num - 1].buf); -+ i2c_mux_hold(muxc, timeout); -+ } else if (hold_msg == I2C_HOLD_MSG_NONE) { -+ mutex_lock(&muxc->hold_lock); -+ } - ret = muxc->select(muxc, priv->chan_id); - if (ret >= 0) - ret = i2c_transfer(parent, msgs, num); -- if (muxc->deselect) -- muxc->deselect(muxc, priv->chan_id); -+ if (hold_msg != I2C_HOLD_MSG_SET) { -+ if (muxc->deselect) -+ muxc->deselect(muxc, priv->chan_id); -+ if (hold_msg == I2C_HOLD_MSG_RESET) -+ i2c_mux_unhold(muxc); -+ else -+ mutex_unlock(&muxc->hold_lock); -+ } - - return ret; - } -@@ -82,16 +136,33 @@ static int __i2c_mux_smbus_xfer(struct i2c_adapter *adap, - struct i2c_mux_priv *priv = adap->algo_data; - struct i2c_mux_core *muxc = priv->muxc; - struct i2c_adapter *parent = muxc->parent; -+ enum i2c_hold_msg_type hold_msg; -+ unsigned long timeout; - int ret; - - /* Select the right mux port and perform the transfer. */ - -+ hold_msg = i2c_check_hold_msg(flags, -+ size == I2C_SMBUS_WORD_DATA ? 2 : 0, -+ &data->word); -+ if (hold_msg == I2C_HOLD_MSG_SET) { -+ timeout = msecs_to_jiffies(data->word); -+ i2c_mux_hold(muxc, timeout); -+ } else if (hold_msg == I2C_HOLD_MSG_NONE) { -+ mutex_lock(&muxc->hold_lock); -+ } - ret = muxc->select(muxc, priv->chan_id); - if (ret >= 0) - ret = __i2c_smbus_xfer(parent, addr, flags, - read_write, command, size, data); -- if (muxc->deselect) -- muxc->deselect(muxc, priv->chan_id); -+ if (hold_msg != I2C_HOLD_MSG_SET) { -+ if (muxc->deselect) -+ muxc->deselect(muxc, priv->chan_id); -+ if (hold_msg == I2C_HOLD_MSG_RESET) -+ i2c_mux_unhold(muxc); -+ else -+ mutex_unlock(&muxc->hold_lock); -+ } - - return ret; - } -@@ -104,16 +175,33 @@ static int i2c_mux_smbus_xfer(struct i2c_adapter *adap, - struct i2c_mux_priv *priv = adap->algo_data; - struct i2c_mux_core *muxc = priv->muxc; - struct i2c_adapter *parent = muxc->parent; -+ enum i2c_hold_msg_type hold_msg; -+ unsigned long timeout; - int ret; - - /* Select the right mux port and perform the transfer. */ - -+ hold_msg = i2c_check_hold_msg(flags, -+ size == I2C_SMBUS_WORD_DATA ? 2 : 0, -+ &data->word); -+ if (hold_msg == I2C_HOLD_MSG_SET) { -+ timeout = msecs_to_jiffies(data->word); -+ i2c_mux_hold(muxc, timeout); -+ } else if (hold_msg == I2C_HOLD_MSG_NONE) { -+ mutex_lock(&muxc->hold_lock); -+ } - ret = muxc->select(muxc, priv->chan_id); - if (ret >= 0) - ret = i2c_smbus_xfer(parent, addr, flags, - read_write, command, size, data); -- if (muxc->deselect) -- muxc->deselect(muxc, priv->chan_id); -+ if (hold_msg != I2C_HOLD_MSG_SET) { -+ if (muxc->deselect) -+ muxc->deselect(muxc, priv->chan_id); -+ if (hold_msg == I2C_HOLD_MSG_RESET) -+ i2c_mux_unhold(muxc); -+ else -+ mutex_unlock(&muxc->hold_lock); -+ } - - return ret; - } -@@ -263,6 +351,9 @@ struct i2c_mux_core *i2c_mux_alloc(struct i2c_adapter *parent, - muxc->deselect = deselect; - muxc->max_adapters = max_adapters; - -+ mutex_init(&muxc->hold_lock); -+ timer_setup(&muxc->hold_timer, i2c_mux_hold_timer_callback, 0); -+ - return muxc; - } - EXPORT_SYMBOL_GPL(i2c_mux_alloc); -@@ -441,6 +532,8 @@ void i2c_mux_del_adapters(struct i2c_mux_core *muxc) - { - char symlink_name[20]; - -+ i2c_mux_unhold(muxc); -+ - while (muxc->num_adapters) { - struct i2c_adapter *adap = muxc->adapter[--muxc->num_adapters]; - struct i2c_mux_priv *priv = adap->algo_data; -diff --git a/include/linux/i2c-mux.h b/include/linux/i2c-mux.h -index c5a977320f82..47f8763d6ed2 100644 ---- a/include/linux/i2c-mux.h -+++ b/include/linux/i2c-mux.h -@@ -27,6 +27,9 @@ struct i2c_mux_core { - int (*select)(struct i2c_mux_core *, u32 chan_id); - int (*deselect)(struct i2c_mux_core *, u32 chan_id); - -+ struct mutex hold_lock; /* mutex for channel holding */ -+ struct timer_list hold_timer; -+ - int num_adapters; - int max_adapters; - struct i2c_adapter *adapter[0]; -diff --git a/include/linux/i2c.h b/include/linux/i2c.h -index 1361637c369d..b4055d133338 100644 ---- a/include/linux/i2c.h -+++ b/include/linux/i2c.h -@@ -711,6 +711,13 @@ struct i2c_adapter { - const struct i2c_adapter_quirks *quirks; - - struct irq_domain *host_notify_domain; -+ -+ /* -+ * These will be used by root adpaters only. For muxes, each mux core -+ * has these individually. -+ */ -+ struct mutex hold_lock; /* mutex for bus holding */ -+ struct timer_list hold_timer; - }; - #define to_i2c_adapter(d) container_of(d, struct i2c_adapter, dev) - -@@ -1005,4 +1012,22 @@ static inline struct i2c_adapter *i2c_acpi_find_adapter_by_handle(acpi_handle ha - } - #endif /* CONFIG_ACPI */ - -+enum i2c_hold_msg_type { -+ I2C_HOLD_MSG_NONE, -+ I2C_HOLD_MSG_SET, -+ I2C_HOLD_MSG_RESET -+}; -+ -+static inline enum i2c_hold_msg_type i2c_check_hold_msg(u16 flags, u16 len, u16 *buf) -+{ -+ if (flags & I2C_M_HOLD && len == sizeof(u16)) { -+ if (*buf) -+ return I2C_HOLD_MSG_SET; -+ -+ return I2C_HOLD_MSG_RESET; -+ } -+ -+ return I2C_HOLD_MSG_NONE; -+} -+ - #endif /* _LINUX_I2C_H */ -diff --git a/include/uapi/linux/i2c.h b/include/uapi/linux/i2c.h -index f71a1751cacf..a1db9b17ed36 100644 ---- a/include/uapi/linux/i2c.h -+++ b/include/uapi/linux/i2c.h -@@ -72,6 +72,7 @@ struct i2c_msg { - #define I2C_M_RD 0x0001 /* read data, from slave to master */ - /* I2C_M_RD is guaranteed to be 0x0001! */ - #define I2C_M_TEN 0x0010 /* this is a ten bit chip address */ -+#define I2C_M_HOLD 0x0100 /* for holding a mux path */ - #define I2C_M_DMA_SAFE 0x0200 /* the buffer of this message is DMA safe */ - /* makes only sense in kernelspace */ - /* userspace buffers are copied anyway */ --- -2.7.4 - -- cgit v1.2.3