diff options
-rw-r--r-- | Documentation/devicetree/bindings/i2c/i2c.txt | 4 | ||||
-rw-r--r-- | Documentation/devicetree/bindings/net/mctp-i2c-controller.yaml | 92 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-aspeed.c | 5 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-npcm7xx.c | 3 | ||||
-rw-r--r-- | drivers/i2c/i2c-core-smbus.c | 20 | ||||
-rw-r--r-- | drivers/i2c/i2c-dev.c | 93 | ||||
-rw-r--r-- | drivers/net/mctp/Kconfig | 12 | ||||
-rw-r--r-- | drivers/net/mctp/Makefile | 1 | ||||
-rw-r--r-- | drivers/net/mctp/mctp-i2c.c | 982 | ||||
-rw-r--r-- | include/linux/i2c.h | 13 | ||||
-rw-r--r-- | include/uapi/linux/i2c-dev.h | 2 | ||||
-rw-r--r-- | include/uapi/linux/i2c.h | 7 |
12 files changed, 25 insertions, 1209 deletions
diff --git a/Documentation/devicetree/bindings/i2c/i2c.txt b/Documentation/devicetree/bindings/i2c/i2c.txt index fc3dd7ec0445..b864916e087f 100644 --- a/Documentation/devicetree/bindings/i2c/i2c.txt +++ b/Documentation/devicetree/bindings/i2c/i2c.txt @@ -95,10 +95,6 @@ wants to support one of the below features, it should adapt these bindings. - smbus-alert states that the optional SMBus-Alert feature apply to this bus. -- mctp-controller - indicates that the system is accessible via this bus as an endpoint for - MCTP over I2C transport. - Required properties (per child device) -------------------------------------- diff --git a/Documentation/devicetree/bindings/net/mctp-i2c-controller.yaml b/Documentation/devicetree/bindings/net/mctp-i2c-controller.yaml deleted file mode 100644 index afd11c9422fa..000000000000 --- a/Documentation/devicetree/bindings/net/mctp-i2c-controller.yaml +++ /dev/null @@ -1,92 +0,0 @@ -# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) -%YAML 1.2 ---- -$id: http://devicetree.org/schemas/net/mctp-i2c-controller.yaml# -$schema: http://devicetree.org/meta-schemas/core.yaml# - -title: MCTP I2C transport binding - -maintainers: - - Matt Johnston <matt@codeconstruct.com.au> - -description: | - An mctp-i2c-controller defines a local MCTP endpoint on an I2C controller. - MCTP I2C is specified by DMTF DSP0237. - - An mctp-i2c-controller must be attached to an I2C adapter which supports - slave functionality. I2C busses (either directly or as subordinate mux - busses) are attached to the mctp-i2c-controller with a 'mctp-controller' - property on each used bus. Each mctp-controller I2C bus will be presented - to the host system as a separate MCTP I2C instance. - -properties: - compatible: - const: mctp-i2c-controller - - reg: - minimum: 0x40000000 - maximum: 0x4000007f - description: | - 7 bit I2C address of the local endpoint. - I2C_OWN_SLAVE_ADDRESS (1<<30) flag must be set. - -additionalProperties: false - -required: - - compatible - - reg - -examples: - - | - // Basic case of a single I2C bus - #include <dt-bindings/i2c/i2c.h> - - i2c { - #address-cells = <1>; - #size-cells = <0>; - mctp-controller; - - mctp@30 { - compatible = "mctp-i2c-controller"; - reg = <(0x30 | I2C_OWN_SLAVE_ADDRESS)>; - }; - }; - - - | - // Mux topology with multiple MCTP-handling busses under - // a single mctp-i2c-controller. - // i2c1 and i2c6 can have MCTP devices, i2c5 does not. - #include <dt-bindings/i2c/i2c.h> - - i2c1: i2c { - #address-cells = <1>; - #size-cells = <0>; - mctp-controller; - - mctp@50 { - compatible = "mctp-i2c-controller"; - reg = <(0x50 | I2C_OWN_SLAVE_ADDRESS)>; - }; - }; - - i2c-mux { - #address-cells = <1>; - #size-cells = <0>; - i2c-parent = <&i2c1>; - - i2c5: i2c@0 { - #address-cells = <1>; - #size-cells = <0>; - reg = <0>; - eeprom@33 { - reg = <0x33>; - }; - }; - - i2c6: i2c@1 { - #address-cells = <1>; - #size-cells = <0>; - reg = <1>; - mctp-controller; - }; - }; diff --git a/drivers/i2c/busses/i2c-aspeed.c b/drivers/i2c/busses/i2c-aspeed.c index 7395f3702fae..67e8b97c0c95 100644 --- a/drivers/i2c/busses/i2c-aspeed.c +++ b/drivers/i2c/busses/i2c-aspeed.c @@ -533,7 +533,7 @@ static u32 aspeed_i2c_master_irq(struct aspeed_i2c_bus *bus, u32 irq_status) msg->buf[bus->buf_index++] = recv_byte; if (msg->flags & I2C_M_RECV_LEN) { - if (unlikely(recv_byte > I2C_SMBUS_V3_BLOCK_MAX)) { + if (unlikely(recv_byte > I2C_SMBUS_BLOCK_MAX)) { bus->cmd_err = -EPROTO; aspeed_i2c_do_stop(bus); goto out_no_complete; @@ -718,8 +718,7 @@ static int aspeed_i2c_master_xfer(struct i2c_adapter *adap, static u32 aspeed_i2c_functionality(struct i2c_adapter *adap) { - return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | - I2C_FUNC_SMBUS_BLOCK_DATA | I2C_FUNC_SMBUS_V3_BLOCK; + return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | I2C_FUNC_SMBUS_BLOCK_DATA; } #if IS_ENABLED(CONFIG_I2C_SLAVE) diff --git a/drivers/i2c/busses/i2c-npcm7xx.c b/drivers/i2c/busses/i2c-npcm7xx.c index 6d60f65add85..2ad166355ec9 100644 --- a/drivers/i2c/busses/i2c-npcm7xx.c +++ b/drivers/i2c/busses/i2c-npcm7xx.c @@ -1399,7 +1399,7 @@ static void npcm_i2c_irq_master_handler_read(struct npcm_i2c *bus) if (bus->read_block_use) { /* first byte in block protocol is the size: */ data = npcm_i2c_rd_byte(bus); - data = clamp_val(data, 1, I2C_SMBUS_V3_BLOCK_MAX); + data = clamp_val(data, 1, I2C_SMBUS_BLOCK_MAX); bus->rd_size = data + block_extra_bytes_size; bus->rd_buf[bus->rd_ind++] = data; @@ -2187,7 +2187,6 @@ static u32 npcm_i2c_functionality(struct i2c_adapter *adap) I2C_FUNC_SMBUS_EMUL | I2C_FUNC_SMBUS_BLOCK_DATA | I2C_FUNC_SMBUS_PEC | - I2C_FUNC_SMBUS_V3_BLOCK | I2C_FUNC_SLAVE; } diff --git a/drivers/i2c/i2c-core-smbus.c b/drivers/i2c/i2c-core-smbus.c index 743415584aba..e5b2d1465e7e 100644 --- a/drivers/i2c/i2c-core-smbus.c +++ b/drivers/i2c/i2c-core-smbus.c @@ -303,8 +303,7 @@ static void i2c_smbus_try_get_dmabuf(struct i2c_msg *msg, u8 init_val) bool is_read = msg->flags & I2C_M_RD; unsigned char *dma_buf; - dma_buf = kzalloc(I2C_SMBUS_V3_BLOCK_MAX + (is_read ? 2 : 3), - GFP_KERNEL); + dma_buf = kzalloc(I2C_SMBUS_BLOCK_MAX + (is_read ? 2 : 3), GFP_KERNEL); if (!dma_buf) return; @@ -330,10 +329,9 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter *adapter, u16 addr, * initialize most things with sane defaults, to keep the code below * somewhat simpler. */ - unsigned char msgbuf0[I2C_SMBUS_V3_BLOCK_MAX+3]; - unsigned char msgbuf1[I2C_SMBUS_V3_BLOCK_MAX+2]; + unsigned char msgbuf0[I2C_SMBUS_BLOCK_MAX+3]; + unsigned char msgbuf1[I2C_SMBUS_BLOCK_MAX+2]; int nmsgs = read_write == I2C_SMBUS_READ ? 2 : 1; - u16 block_max; u8 partial_pec = 0; int status; struct i2c_msg msg[2] = { @@ -352,10 +350,6 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter *adapter, u16 addr, bool wants_pec = ((flags & I2C_CLIENT_PEC) && size != I2C_SMBUS_QUICK && size != I2C_SMBUS_I2C_BLOCK_DATA); - /* Drivers must opt in to 255 byte max block size */ - block_max = i2c_check_functionality(adapter, I2C_FUNC_SMBUS_V3_BLOCK) - ? I2C_SMBUS_V3_BLOCK_MAX : I2C_SMBUS_BLOCK_MAX; - msgbuf0[0] = command; switch (size) { case I2C_SMBUS_QUICK: @@ -405,7 +399,7 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter *adapter, u16 addr, i2c_smbus_try_get_dmabuf(&msg[1], 0); } else { msg[0].len = data->block[0] + 2; - if (msg[0].len > block_max + 2) { + if (msg[0].len > I2C_SMBUS_BLOCK_MAX + 2) { dev_err(&adapter->dev, "Invalid block write size %d\n", data->block[0]); @@ -419,7 +413,7 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter *adapter, u16 addr, case I2C_SMBUS_BLOCK_PROC_CALL: nmsgs = 2; /* Another special case */ read_write = I2C_SMBUS_READ; - if (data->block[0] > block_max) { + if (data->block[0] > I2C_SMBUS_BLOCK_MAX) { dev_err(&adapter->dev, "Invalid block write size %d\n", data->block[0]); @@ -436,7 +430,7 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter *adapter, u16 addr, i2c_smbus_try_get_dmabuf(&msg[1], 0); break; case I2C_SMBUS_I2C_BLOCK_DATA: - if (data->block[0] > block_max) { + if (data->block[0] > I2C_SMBUS_BLOCK_MAX) { dev_err(&adapter->dev, "Invalid block %s size %d\n", read_write == I2C_SMBUS_READ ? "read" : "write", data->block[0]); @@ -504,7 +498,7 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter *adapter, u16 addr, break; case I2C_SMBUS_BLOCK_DATA: case I2C_SMBUS_BLOCK_PROC_CALL: - if (msg[1].buf[0] > block_max) { + if (msg[1].buf[0] > I2C_SMBUS_BLOCK_MAX) { dev_err(&adapter->dev, "Invalid block size returned: %d\n", msg[1].buf[0]); diff --git a/drivers/i2c/i2c-dev.c b/drivers/i2c/i2c-dev.c index 5ee9118c0407..bce0e8bb7852 100644 --- a/drivers/i2c/i2c-dev.c +++ b/drivers/i2c/i2c-dev.c @@ -46,24 +46,6 @@ struct i2c_dev { struct cdev cdev; }; -/* The userspace union i2c_smbus_data for I2C_SMBUS ioctl is limited - * to 32 bytes (I2C_SMBUS_BLOCK_MAX) for compatibility. - */ -union compat_i2c_smbus_data { - __u8 byte; - __u16 word; - __u8 block[I2C_SMBUS_BLOCK_MAX + 2]; /* block[0] is used for length */ - /* and one more for user-space compatibility */ -}; - -/* Must match i2c-dev.h definition with compat .data member */ -struct i2c_smbus_ioctl_data { - __u8 read_write; - __u8 command; - __u32 size; - union compat_i2c_smbus_data __user *data; -}; - #define I2C_MINORS (MINORMASK + 1) static LIST_HEAD(i2c_dev_list); static DEFINE_SPINLOCK(i2c_dev_list_lock); @@ -253,17 +235,14 @@ static int i2cdev_check_addr(struct i2c_adapter *adapter, unsigned int addr) static noinline int i2cdev_ioctl_rdwr(struct i2c_client *client, unsigned nmsgs, struct i2c_msg *msgs) { - u8 __user **data_ptrs = NULL; - u16 *orig_lens = NULL; + u8 __user **data_ptrs; int i, res; - res = -ENOMEM; data_ptrs = kmalloc_array(nmsgs, sizeof(u8 __user *), GFP_KERNEL); - if (data_ptrs == NULL) - goto out; - orig_lens = kmalloc_array(nmsgs, sizeof(u16), GFP_KERNEL); - if (orig_lens == NULL) - goto out; + if (data_ptrs == NULL) { + kfree(msgs); + return -ENOMEM; + } res = 0; for (i = 0; i < nmsgs; i++) { @@ -274,30 +253,12 @@ static noinline int i2cdev_ioctl_rdwr(struct i2c_client *client, } data_ptrs[i] = (u8 __user *)msgs[i].buf; - msgs[i].buf = NULL; - if (msgs[i].len < 1) { - /* Sanity check */ - res = -EINVAL; - break; - - } - /* Allocate a larger buffer to accommodate possible 255 byte - * blocks. Read results will be dropped later - * if they are too large for the original length. - */ - orig_lens[i] = msgs[i].len; - msgs[i].buf = kmalloc(msgs[i].len + I2C_SMBUS_V3_BLOCK_MAX, - GFP_USER | __GFP_NOWARN); + msgs[i].buf = memdup_user(data_ptrs[i], msgs[i].len); if (IS_ERR(msgs[i].buf)) { res = PTR_ERR(msgs[i].buf); break; } - if (copy_from_user(msgs[i].buf, data_ptrs[i], msgs[i].len)) { - kfree(msgs[i].buf); - res = -EFAULT; - break; - } - /* Buffer from kmalloc, so DMA is ok */ + /* memdup_user allocates with GFP_KERNEL, so DMA is ok */ msgs[i].flags |= I2C_M_DMA_SAFE; /* @@ -313,7 +274,7 @@ static noinline int i2cdev_ioctl_rdwr(struct i2c_client *client, */ if (msgs[i].flags & I2C_M_RECV_LEN) { if (!(msgs[i].flags & I2C_M_RD) || - msgs[i].buf[0] < 1 || + msgs[i].len < 1 || msgs[i].buf[0] < 1 || msgs[i].len < msgs[i].buf[0] + I2C_SMBUS_BLOCK_MAX) { i++; @@ -336,16 +297,12 @@ static noinline int i2cdev_ioctl_rdwr(struct i2c_client *client, res = i2c_transfer(client->adapter, msgs, nmsgs); while (i-- > 0) { if (res >= 0 && (msgs[i].flags & I2C_M_RD)) { - if (orig_lens[i] < msgs[i].len) - res = -EINVAL; - else if (copy_to_user(data_ptrs[i], msgs[i].buf, - msgs[i].len)) + if (copy_to_user(data_ptrs[i], msgs[i].buf, + msgs[i].len)) res = -EFAULT; } kfree(msgs[i].buf); } -out: - kfree(orig_lens); kfree(data_ptrs); kfree(msgs); return res; @@ -353,7 +310,7 @@ out: static noinline int i2cdev_ioctl_smbus(struct i2c_client *client, u8 read_write, u8 command, u32 size, - union compat_i2c_smbus_data __user *data) + union i2c_smbus_data __user *data) { union i2c_smbus_data temp = {}; int datasize, res; @@ -414,16 +371,6 @@ static noinline int i2cdev_ioctl_smbus(struct i2c_client *client, if (copy_from_user(&temp, data, datasize)) return -EFAULT; } - if ((size == I2C_SMBUS_BLOCK_PROC_CALL || - size == I2C_SMBUS_I2C_BLOCK_DATA || - size == I2C_SMBUS_BLOCK_DATA) && - read_write == I2C_SMBUS_WRITE && - temp.block[0] > I2C_SMBUS_BLOCK_MAX) { - /* Don't accept writes larger than the buffer size */ - dev_dbg(&client->adapter->dev, "block write is too large"); - return -EINVAL; - - } if (size == I2C_SMBUS_I2C_BLOCK_BROKEN) { /* Convert old I2C block commands to the new convention. This preserves binary compatibility. */ @@ -433,21 +380,9 @@ static noinline int i2cdev_ioctl_smbus(struct i2c_client *client, } res = i2c_smbus_xfer(client->adapter, client->addr, client->flags, read_write, command, size, &temp); - if (res) - return res; - if ((size == I2C_SMBUS_BLOCK_PROC_CALL || - size == I2C_SMBUS_I2C_BLOCK_DATA || - size == I2C_SMBUS_BLOCK_DATA) && - read_write == I2C_SMBUS_READ && - temp.block[0] > I2C_SMBUS_BLOCK_MAX) { - /* Don't accept reads larger than the buffer size */ - dev_dbg(&client->adapter->dev, "block read is too large"); - return -EINVAL; - - } - if ((size == I2C_SMBUS_PROC_CALL) || - (size == I2C_SMBUS_BLOCK_PROC_CALL) || - (read_write == I2C_SMBUS_READ)) { + if (!res && ((size == I2C_SMBUS_PROC_CALL) || + (size == I2C_SMBUS_BLOCK_PROC_CALL) || + (read_write == I2C_SMBUS_READ))) { if (copy_to_user(data, &temp, datasize)) return -EFAULT; } diff --git a/drivers/net/mctp/Kconfig b/drivers/net/mctp/Kconfig index b758b29c2ddf..d8f966cedc89 100644 --- a/drivers/net/mctp/Kconfig +++ b/drivers/net/mctp/Kconfig @@ -3,18 +3,6 @@ if MCTP menu "MCTP Device Drivers" -config MCTP_TRANSPORT_I2C - tristate "MCTP SMBus/I2C transport" - # i2c-mux is optional, but we must build as a module if i2c-mux is a module - depends on I2C_MUX || !I2C_MUX - depends on I2C - depends on I2C_SLAVE - select MCTP_FLOWS - help - Provides a driver to access MCTP devices over SMBus/I2C transport, - from DMTF specification DSP0237. A MCTP protocol network device is - created for each I2C bus that has been assigned a mctp-i2c device. - endmenu endif diff --git a/drivers/net/mctp/Makefile b/drivers/net/mctp/Makefile index 73dc411986a6..e69de29bb2d1 100644 --- a/drivers/net/mctp/Makefile +++ b/drivers/net/mctp/Makefile @@ -1 +0,0 @@ -obj-$(CONFIG_MCTP_TRANSPORT_I2C) += mctp-i2c.o diff --git a/drivers/net/mctp/mctp-i2c.c b/drivers/net/mctp/mctp-i2c.c deleted file mode 100644 index ed213b4765a1..000000000000 --- a/drivers/net/mctp/mctp-i2c.c +++ /dev/null @@ -1,982 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Management Controller Transport Protocol (MCTP) - * - * Copyright (c) 2021 Code Construct - * Copyright (c) 2021 Google - */ - -#include <linux/module.h> -#include <linux/netdevice.h> -#include <linux/i2c.h> -#include <linux/i2c-mux.h> -#include <linux/if_arp.h> -#include <net/mctp.h> -#include <net/mctpdevice.h> - -/* SMBus 3.0 allows 255 data bytes (plus PEC), but the - * first byte is taken for source slave address. - */ -#define MCTP_I2C_MAXBLOCK 255 -#define MCTP_I2C_MAXMTU (MCTP_I2C_MAXBLOCK - 1) -#define MCTP_I2C_MINMTU (64 + 4) -/* Allow space for address, command, byte_count, databytes, PEC */ -#define MCTP_I2C_RXBUFSZ (3 + MCTP_I2C_MAXBLOCK + 1) -#define MCTP_I2C_MINLEN 8 -#define MCTP_I2C_COMMANDCODE 0x0f -#define MCTP_I2C_TX_WORK_LEN 100 -// sufficient for 64kB at min mtu -#define MCTP_I2C_TX_QUEUE_LEN 1100 - -#define MCTP_I2C_OF_PROP "mctp-controller" - -enum { - MCTP_I2C_FLOW_STATE_NEW = 0, - MCTP_I2C_FLOW_STATE_ACTIVE, -}; - -static struct { - /* lock protects clients and also prevents adding/removing adapters - * during mctp_i2c_client probe/remove. - */ - struct mutex lock; - // list of struct mctp_i2c_client - struct list_head clients; -} mi_driver_state; - -struct mctp_i2c_client; - -// The netdev structure. One of these per I2C adapter. -struct mctp_i2c_dev { - struct net_device *ndev; - struct i2c_adapter *adapter; - struct mctp_i2c_client *client; - struct list_head list; // for mctp_i2c_client.devs - - size_t pos; - u8 buffer[MCTP_I2C_RXBUFSZ]; - - struct task_struct *tx_thread; - wait_queue_head_t tx_wq; - struct sk_buff_head tx_queue; - - // a fake entry in our tx queue to perform an unlock operation - struct sk_buff unlock_marker; - - spinlock_t flow_lock; // protects i2c_lock_count and release_count - int i2c_lock_count; - int release_count; -}; - -/* The i2c client structure. One per hardware i2c bus at the top of the - * mux tree, shared by multiple netdevs - */ -struct mctp_i2c_client { - struct i2c_client *client; - u8 lladdr; - - struct mctp_i2c_dev *sel; - struct list_head devs; - spinlock_t curr_lock; // protects sel - - struct list_head list; // for mi_driver_state.clients -}; - -// Header on the wire -struct mctp_i2c_hdr { - u8 dest_slave; - u8 command; - u8 byte_count; - u8 source_slave; -}; - -static int mctp_i2c_recv(struct mctp_i2c_dev *midev); -static int mctp_i2c_slave_cb(struct i2c_client *client, - enum i2c_slave_event event, u8 *val); - -static struct i2c_adapter *mux_root_adapter(struct i2c_adapter *adap) -{ -#if IS_ENABLED(CONFIG_I2C_MUX) - return i2c_root_adapter(&adap->dev); -#else - /* In non-mux config all i2c adapters are root adapters */ - return adap; -#endif -} - -static ssize_t mctp_current_mux_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct mctp_i2c_client *mcli = i2c_get_clientdata(to_i2c_client(dev)); - struct net_device *ndev = NULL; - unsigned long flags; - ssize_t l; - - spin_lock_irqsave(&mcli->curr_lock, flags); - if (mcli->sel) { - ndev = mcli->sel->ndev; - dev_hold(ndev); - } - spin_unlock_irqrestore(&mcli->curr_lock, flags); - l = scnprintf(buf, PAGE_SIZE, "%s\n", ndev ? ndev->name : "(none)"); - if (ndev) - dev_put(ndev); - return l; -} -static DEVICE_ATTR_RO(mctp_current_mux); - -/* Creates a new i2c slave device attached to the root adapter. - * Sets up the slave callback. - * Must be called with a client on a root adapter. - */ -static struct mctp_i2c_client *mctp_i2c_new_client(struct i2c_client *client) -{ - struct mctp_i2c_client *mcli = NULL; - struct i2c_adapter *root = NULL; - int rc; - - if (client->flags & I2C_CLIENT_TEN) { - dev_err(&client->dev, "%s failed, MCTP requires a 7-bit I2C address, addr=0x%x", - __func__, client->addr); - rc = -EINVAL; - goto err; - } - - root = mux_root_adapter(client->adapter); - if (!root) { - dev_err(&client->dev, "%s failed to find root adapter\n", __func__); - rc = -ENOENT; - goto err; - } - if (root != client->adapter) { - dev_err(&client->dev, - "A mctp-i2c-controller client cannot be placed on an I2C mux adapter.\n" - " It should be placed on the mux tree root adapter\n" - " then set mctp-controller property on adapters to attach\n"); - rc = -EINVAL; - goto err; - } - - mcli = kzalloc(sizeof(*mcli), GFP_KERNEL); - if (!mcli) { - rc = -ENOMEM; - goto err; - } - spin_lock_init(&mcli->curr_lock); - INIT_LIST_HEAD(&mcli->devs); - INIT_LIST_HEAD(&mcli->list); - mcli->lladdr = client->addr & 0xff; - mcli->client = client; - i2c_set_clientdata(client, mcli); - - rc = i2c_slave_register(mcli->client, mctp_i2c_slave_cb); - if (rc) { - dev_err(&client->dev, "%s i2c register failed %d\n", __func__, rc); - mcli->client = NULL; - i2c_set_clientdata(client, NULL); - goto err; - } - - rc = device_create_file(&client->dev, &dev_attr_mctp_current_mux); - if (rc) { - dev_err(&client->dev, "%s adding sysfs \"%s\" failed %d\n", __func__, - dev_attr_mctp_current_mux.attr.name, rc); - // continue anyway - } - - return mcli; -err: - if (mcli) { - if (mcli->client) { - device_remove_file(&mcli->client->dev, &dev_attr_mctp_current_mux); - i2c_unregister_device(mcli->client); - } - kfree(mcli); - } - return ERR_PTR(rc); -} - -static void mctp_i2c_free_client(struct mctp_i2c_client *mcli) -{ - int rc; - - WARN_ON(!mutex_is_locked(&mi_driver_state.lock)); - WARN_ON(!list_empty(&mcli->devs)); - WARN_ON(mcli->sel); // sanity check, no locking - - device_remove_file(&mcli->client->dev, &dev_attr_mctp_current_mux); - rc = i2c_slave_unregister(mcli->client); - // leak if it fails, we can't propagate errors upwards - if (rc) - dev_err(&mcli->client->dev, "%s i2c unregister failed %d\n", __func__, rc); - else - kfree(mcli); -} - -/* Switch the mctp i2c device to receive responses. - * Call with curr_lock held - */ -static void __mctp_i2c_device_select(struct mctp_i2c_client *mcli, - struct mctp_i2c_dev *midev) -{ - assert_spin_locked(&mcli->curr_lock); - if (midev) - dev_hold(midev->ndev); - if (mcli->sel) - dev_put(mcli->sel->ndev); - mcli->sel = midev; -} - -// Switch the mctp i2c device to receive responses -static void mctp_i2c_device_select(struct mctp_i2c_client *mcli, - struct mctp_i2c_dev *midev) -{ - unsigned long flags; - - spin_lock_irqsave(&mcli->curr_lock, flags); - __mctp_i2c_device_select(mcli, midev); - spin_unlock_irqrestore(&mcli->curr_lock, flags); -} - -static int mctp_i2c_slave_cb(struct i2c_client *client, - enum i2c_slave_event event, u8 *val) -{ - struct mctp_i2c_client *mcli = i2c_get_clientdata(client); - struct mctp_i2c_dev *midev = NULL; - unsigned long flags; - int rc = 0; - - spin_lock_irqsave(&mcli->curr_lock, flags); - midev = mcli->sel; - if (midev) - dev_hold(midev->ndev); - spin_unlock_irqrestore(&mcli->curr_lock, flags); - - if (!midev) - return 0; - - switch (event) { - case I2C_SLAVE_WRITE_RECEIVED: - if (midev->pos < MCTP_I2C_RXBUFSZ) { - midev->buffer[midev->pos] = *val; - midev->pos++; - } else { - midev->ndev->stats.rx_over_errors++; - } - - break; - case I2C_SLAVE_WRITE_REQUESTED: - /* dest_slave as first byte */ - midev->buffer[0] = mcli->lladdr << 1; - midev->pos = 1; - break; - case I2C_SLAVE_STOP: - rc = mctp_i2c_recv(midev); - break; - default: - break; - } - - dev_put(midev->ndev); - return rc; -} - -// Processes incoming data that has been accumulated by the slave cb -static int mctp_i2c_recv(struct mctp_i2c_dev *midev) -{ - struct net_device *ndev = midev->ndev; - struct mctp_i2c_hdr *hdr; - struct mctp_skb_cb *cb; - struct sk_buff *skb; - u8 pec, calc_pec; - size_t recvlen; - - /* + 1 for the PEC */ - if (midev->pos < MCTP_I2C_MINLEN + 1) { - ndev->stats.rx_length_errors++; - return -EINVAL; - } - recvlen = midev->pos - 1; - - hdr = (void *)midev->buffer; - if (hdr->command != MCTP_I2C_COMMANDCODE) { - ndev->stats.rx_dropped++; - return -EINVAL; - } - - pec = midev->buffer[midev->pos - 1]; - calc_pec = i2c_smbus_pec(0, midev->buffer, recvlen); - if (pec != calc_pec) { - ndev->stats.rx_crc_errors++; - return -EINVAL; - } - - skb = netdev_alloc_skb(ndev, recvlen); - if (!skb) { - ndev->stats.rx_dropped++; - return -ENOMEM; - } - - skb->protocol = htons(ETH_P_MCTP); - skb_put_data(skb, midev->buffer, recvlen); - skb_reset_mac_header(skb); - skb_pull(skb, sizeof(struct mctp_i2c_hdr)); - skb_reset_network_header(skb); - - cb = __mctp_cb(skb); - cb->halen = 1; - cb->haddr[0] = hdr->source_slave; - - if (netif_rx(skb) == NET_RX_SUCCESS) { - ndev->stats.rx_packets++; - ndev->stats.rx_bytes += skb->len; - } else { - ndev->stats.rx_dropped++; - } - return 0; -} - -enum mctp_i2c_flow_state { - MCTP_I2C_TX_FLOW_INVALID, - MCTP_I2C_TX_FLOW_NONE, - MCTP_I2C_TX_FLOW_NEW, - MCTP_I2C_TX_FLOW_EXISTING, -}; - -static enum mctp_i2c_flow_state -mctp_i2c_get_tx_flow_state(struct mctp_i2c_dev *midev, struct sk_buff *skb) -{ - enum mctp_i2c_flow_state state; - struct mctp_sk_key *key; - struct mctp_flow *flow; - unsigned long flags; - - flow = skb_ext_find(skb, SKB_EXT_MCTP); - if (!flow) - return MCTP_I2C_TX_FLOW_NONE; - - key = flow->key; - if (!key) - return MCTP_I2C_TX_FLOW_NONE; - - spin_lock_irqsave(&key->lock, flags); - /* if the key is present but invalid, we're unlikely to be able - * to handle the flow at all; just drop now - */ - if (!key->valid) { - state = MCTP_I2C_TX_FLOW_INVALID; - - } else if (key->dev_flow_state == MCTP_I2C_FLOW_STATE_NEW) { - key->dev_flow_state = MCTP_I2C_FLOW_STATE_ACTIVE; - state = MCTP_I2C_TX_FLOW_NEW; - } else { - state = MCTP_I2C_TX_FLOW_EXISTING; - } - - spin_unlock_irqrestore(&key->lock, flags); - - return state; -} - -/* We're not contending with ourselves here; we only need to exclude other - * i2c clients from using the bus. refcounts are simply to prevent - * recursive locking. - */ -static void mctp_i2c_lock_nest(struct mctp_i2c_dev *midev) -{ - unsigned long flags; - bool lock; - - spin_lock_irqsave(&midev->flow_lock, flags); - lock = midev->i2c_lock_count == 0; - midev->i2c_lock_count++; - spin_unlock_irqrestore(&midev->flow_lock, flags); - - if (lock) - i2c_lock_bus(midev->adapter, I2C_LOCK_SEGMENT); -} - -static void mctp_i2c_unlock_nest(struct mctp_i2c_dev *midev) -{ - unsigned long flags; - bool unlock; - - spin_lock_irqsave(&midev->flow_lock, flags); - if (!WARN_ONCE(midev->i2c_lock_count == 0, "lock count underflow!")) - midev->i2c_lock_count--; - unlock = midev->i2c_lock_count == 0; - spin_unlock_irqrestore(&midev->flow_lock, flags); - - if (unlock) - i2c_unlock_bus(midev->adapter, I2C_LOCK_SEGMENT); -} - -static void mctp_i2c_xmit(struct mctp_i2c_dev *midev, struct sk_buff *skb) -{ - struct net_device_stats *stats = &midev->ndev->stats; - enum mctp_i2c_flow_state fs; - union i2c_smbus_data *data; - struct mctp_i2c_hdr *hdr; - unsigned int len; - u16 daddr; - int rc; - - fs = mctp_i2c_get_tx_flow_state(midev, skb); - - len = skb->len; - hdr = (void *)skb_mac_header(skb); - data = (void *)&hdr->byte_count; - daddr = hdr->dest_slave >> 1; - - switch (fs) { - case MCTP_I2C_TX_FLOW_NONE: - /* no flow: full lock & unlock */ - mctp_i2c_lock_nest(midev); - mctp_i2c_device_select(midev->client, midev); - rc = __i2c_smbus_xfer(midev->adapter, daddr, I2C_CLIENT_PEC, - I2C_SMBUS_WRITE, hdr->command, - I2C_SMBUS_BLOCK_DATA, data); - mctp_i2c_unlock_nest(midev); - break; - - case MCTP_I2C_TX_FLOW_NEW: - /* new flow: lock, tx, but don't unlock; that will happen - * on flow release - */ - mctp_i2c_lock_nest(midev); - mctp_i2c_device_select(midev->client, midev); - fallthrough; - - case MCTP_I2C_TX_FLOW_EXISTING: - /* existing flow: we already have the lock; just tx */ - rc = __i2c_smbus_xfer(midev->adapter, daddr, I2C_CLIENT_PEC, - I2C_SMBUS_WRITE, hdr->command, - I2C_SMBUS_BLOCK_DATA, data); - break; - - case MCTP_I2C_TX_FLOW_INVALID: - return; - } - - if (rc) { - dev_warn_ratelimited(&midev->adapter->dev, - "%s i2c_smbus_xfer failed %d", __func__, rc); - stats->tx_errors++; - } else { - stats->tx_bytes += len; - stats->tx_packets++; - } -} - -static void mctp_i2c_flow_release(struct mctp_i2c_dev *midev) -{ - unsigned long flags; - bool unlock; - - spin_lock_irqsave(&midev->flow_lock, flags); - if (midev->release_count > midev->i2c_lock_count) { - WARN_ONCE(1, "release count overflow"); - midev->release_count = midev->i2c_lock_count; - } - - midev->i2c_lock_count -= midev->release_count; - unlock = midev->i2c_lock_count == 0 && midev->release_count > 0; - midev->release_count = 0; - spin_unlock_irqrestore(&midev->flow_lock, flags); - - if (unlock) - i2c_unlock_bus(midev->adapter, I2C_LOCK_SEGMENT); -} - -static int mctp_i2c_header_create(struct sk_buff *skb, struct net_device *dev, - unsigned short type, const void *daddr, - const void *saddr, unsigned int len) -{ - struct mctp_i2c_hdr *hdr; - struct mctp_hdr *mhdr; - u8 lldst, llsrc; - - lldst = *((u8 *)daddr); - llsrc = *((u8 *)saddr); - - skb_push(skb, sizeof(struct mctp_i2c_hdr)); - skb_reset_mac_header(skb); - hdr = (void *)skb_mac_header(skb); - mhdr = mctp_hdr(skb); - hdr->dest_slave = (lldst << 1) & 0xff; - hdr->command = MCTP_I2C_COMMANDCODE; - hdr->byte_count = len + 1; - if (hdr->byte_count > MCTP_I2C_MAXBLOCK) - return -EMSGSIZE; - hdr->source_slave = ((llsrc << 1) & 0xff) | 0x01; - mhdr->ver = 0x01; - - return 0; -} - -static int mctp_i2c_tx_thread(void *data) -{ - struct mctp_i2c_dev *midev = data; - struct sk_buff *skb; - unsigned long flags; - - for (;;) { - if (kthread_should_stop()) - break; - - spin_lock_irqsave(&midev->tx_queue.lock, flags); - skb = __skb_dequeue(&midev->tx_queue); - if (netif_queue_stopped(midev->ndev)) - netif_wake_queue(midev->ndev); - spin_unlock_irqrestore(&midev->tx_queue.lock, flags); - - if (skb == &midev->unlock_marker) { - mctp_i2c_flow_release(midev); - - } else if (skb) { - mctp_i2c_xmit(midev, skb); - kfree_skb(skb); - - } else { - wait_event(midev->tx_wq, - !skb_queue_empty(&midev->tx_queue) || - kthread_should_stop()); - } - } - - return 0; -} - -static netdev_tx_t mctp_i2c_start_xmit(struct sk_buff *skb, - struct net_device *dev) -{ - struct mctp_i2c_dev *midev = netdev_priv(dev); - unsigned long flags; - - spin_lock_irqsave(&midev->tx_queue.lock, flags); - if (skb_queue_len(&midev->tx_queue) >= MCTP_I2C_TX_WORK_LEN) { - netif_stop_queue(dev); - spin_unlock_irqrestore(&midev->tx_queue.lock, flags); - netdev_err(dev, "BUG! Tx Ring full when queue awake!\n"); - return NETDEV_TX_BUSY; - } - - __skb_queue_tail(&midev->tx_queue, skb); - if (skb_queue_len(&midev->tx_queue) == MCTP_I2C_TX_WORK_LEN) - netif_stop_queue(dev); - spin_unlock_irqrestore(&midev->tx_queue.lock, flags); - - wake_up(&midev->tx_wq); - return NETDEV_TX_OK; -} - -static void mctp_i2c_release_flow(struct mctp_dev *mdev, - struct mctp_sk_key *key) - -{ - struct mctp_i2c_dev *midev = netdev_priv(mdev->dev); - unsigned long flags; - - spin_lock_irqsave(&midev->flow_lock, flags); - midev->release_count++; - spin_unlock_irqrestore(&midev->flow_lock, flags); - - /* Ensure we have a release operation queued, through the fake - * marker skb - */ - spin_lock(&midev->tx_queue.lock); - if (!midev->unlock_marker.next) - __skb_queue_tail(&midev->tx_queue, &midev->unlock_marker); - spin_unlock(&midev->tx_queue.lock); - - wake_up(&midev->tx_wq); -} - -static const struct net_device_ops mctp_i2c_ops = { - .ndo_start_xmit = mctp_i2c_start_xmit, -}; - -static const struct header_ops mctp_i2c_headops = { - .create = mctp_i2c_header_create, -}; - -static const struct mctp_netdev_ops mctp_i2c_mctp_ops = { - .release_flow = mctp_i2c_release_flow, -}; - -static void mctp_i2c_net_setup(struct net_device *dev) -{ - dev->type = ARPHRD_MCTP; - - dev->mtu = MCTP_I2C_MAXMTU; - dev->min_mtu = MCTP_I2C_MINMTU; - dev->max_mtu = MCTP_I2C_MAXMTU; - dev->tx_queue_len = MCTP_I2C_TX_QUEUE_LEN; - - dev->hard_header_len = sizeof(struct mctp_i2c_hdr); - dev->addr_len = 1; - - dev->netdev_ops = &mctp_i2c_ops; - dev->header_ops = &mctp_i2c_headops; - dev->needs_free_netdev = true; -} - -static int mctp_i2c_add_netdev(struct mctp_i2c_client *mcli, - struct i2c_adapter *adap) -{ - unsigned long flags; - struct mctp_i2c_dev *midev = NULL; - struct net_device *ndev = NULL; - struct i2c_adapter *root; - char namebuf[30]; - int rc; - - root = mux_root_adapter(adap); - if (root != mcli->client->adapter) { - dev_err(&mcli->client->dev, - "I2C adapter %s is not a child bus of %s", - mcli->client->adapter->name, root->name); - return -EINVAL; - } - - WARN_ON(!mutex_is_locked(&mi_driver_state.lock)); - snprintf(namebuf, sizeof(namebuf), "mctpi2c%d", adap->nr); - ndev = alloc_netdev(sizeof(*midev), namebuf, NET_NAME_ENUM, mctp_i2c_net_setup); - if (!ndev) { - dev_err(&mcli->client->dev, "%s alloc netdev failed\n", __func__); - rc = -ENOMEM; - goto err; - } - dev_net_set(ndev, current->nsproxy->net_ns); - SET_NETDEV_DEV(ndev, &adap->dev); - ndev->dev_addr = &mcli->lladdr; - - midev = netdev_priv(ndev); - skb_queue_head_init(&midev->tx_queue); - INIT_LIST_HEAD(&midev->list); - midev->adapter = adap; - midev->client = mcli; - spin_lock_init(&midev->flow_lock); - midev->i2c_lock_count = 0; - midev->release_count = 0; - /* Hold references */ - get_device(&midev->adapter->dev); - get_device(&midev->client->client->dev); - midev->ndev = ndev; - init_waitqueue_head(&midev->tx_wq); - midev->tx_thread = kthread_create(mctp_i2c_tx_thread, midev, - "%s/tx", namebuf); - if (IS_ERR_OR_NULL(midev->tx_thread)) { - rc = -ENOMEM; - goto err_free; - } - - rc = mctp_register_netdev(ndev, &mctp_i2c_mctp_ops); - if (rc) { - dev_err(&mcli->client->dev, - "%s register netdev \"%s\" failed %d\n", __func__, - ndev->name, rc); - goto err_stop_kthread; - } - spin_lock_irqsave(&mcli->curr_lock, flags); - list_add(&midev->list, &mcli->devs); - // Select a device by default - if (!mcli->sel) - __mctp_i2c_device_select(mcli, midev); - spin_unlock_irqrestore(&mcli->curr_lock, flags); - - wake_up_process(midev->tx_thread); - - return 0; - -err_stop_kthread: - kthread_stop(midev->tx_thread); - -err_free: - free_netdev(ndev); - -err: - return rc; -} - -// Removes and unregisters a mctp-i2c netdev -static void mctp_i2c_free_netdev(struct mctp_i2c_dev *midev) -{ - struct mctp_i2c_client *mcli = midev->client; - unsigned long flags; - - netif_stop_queue(midev->ndev); - kthread_stop(midev->tx_thread); - skb_queue_purge(&midev->tx_queue); - - /* Release references, used only for TX which has stopped */ - put_device(&midev->adapter->dev); - put_device(&mcli->client->dev); - - /* Remove it from the parent mcli */ - spin_lock_irqsave(&mcli->curr_lock, flags); - list_del(&midev->list); - if (mcli->sel == midev) { - struct mctp_i2c_dev *first; - - first = list_first_entry_or_null(&mcli->devs, struct mctp_i2c_dev, list); - __mctp_i2c_device_select(mcli, first); - } - spin_unlock_irqrestore(&mcli->curr_lock, flags); - - /* Remove netdev. mctp_i2c_slave_cb() takes a dev_hold() so removing - * it now is safe. unregister_netdev() frees ndev and midev. - */ - mctp_unregister_netdev(midev->ndev); -} - -// Removes any netdev for adap. mcli is the parent root i2c client -static void mctp_i2c_remove_netdev(struct mctp_i2c_client *mcli, - struct i2c_adapter *adap) -{ - unsigned long flags; - struct mctp_i2c_dev *midev = NULL, *m = NULL; - - WARN_ON(!mutex_is_locked(&mi_driver_state.lock)); - spin_lock_irqsave(&mcli->curr_lock, flags); - // list size is limited by number of MCTP netdevs on a single hardware bus - list_for_each_entry(m, &mcli->devs, list) - if (m->adapter == adap) { - midev = m; - break; - } - spin_unlock_irqrestore(&mcli->curr_lock, flags); - - if (midev) - mctp_i2c_free_netdev(midev); -} - -/* Determines whether a device is an i2c adapter. - * Optionally returns the root i2c_adapter - */ -static struct i2c_adapter *mctp_i2c_get_adapter(struct device *dev, - struct i2c_adapter **ret_root) -{ - struct i2c_adapter *root, *adap; - - if (dev->type != &i2c_adapter_type) - return NULL; - adap = to_i2c_adapter(dev); - root = mux_root_adapter(adap); - WARN_ONCE(!root, "%s failed to find root adapter for %s\n", - __func__, dev_name(dev)); - if (!root) - return NULL; - if (ret_root) - *ret_root = root; - return adap; -} - -/* Determines whether a device is an i2c adapter with the "mctp-controller" - * devicetree property set. If adap is not an OF node, returns match_no_of - */ -static bool mctp_i2c_adapter_match(struct i2c_adapter *adap, bool match_no_of) -{ - if (!adap->dev.of_node) - return match_no_of; - return of_property_read_bool(adap->dev.of_node, MCTP_I2C_OF_PROP); -} - -/* Called for each existing i2c device (adapter or client) when a - * new mctp-i2c client is probed. - */ -static int mctp_i2c_client_try_attach(struct device *dev, void *data) -{ - struct i2c_adapter *adap = NULL, *root = NULL; - struct mctp_i2c_client *mcli = data; - - adap = mctp_i2c_get_adapter(dev, &root); - if (!adap) - return 0; - if (mcli->client->adapter != root) - return 0; - // Must either have mctp-controller property on the adapter, or - // be a root adapter if it's non-devicetree - if (!mctp_i2c_adapter_match(adap, adap == root)) - return 0; - - return mctp_i2c_add_netdev(mcli, adap); -} - -static void mctp_i2c_notify_add(struct device *dev) -{ - struct mctp_i2c_client *mcli = NULL, *m = NULL; - struct i2c_adapter *root = NULL, *adap = NULL; - int rc; - - adap = mctp_i2c_get_adapter(dev, &root); - if (!adap) - return; - // Check for mctp-controller property on the adapter - if (!mctp_i2c_adapter_match(adap, false)) - return; - - /* Find an existing mcli for adap's root */ - mutex_lock(&mi_driver_state.lock); - list_for_each_entry(m, &mi_driver_state.clients, list) { - if (m->client->adapter == root) { - mcli = m; - break; - } - } - - if (mcli) { - rc = mctp_i2c_add_netdev(mcli, adap); - if (rc) - dev_warn(dev, "%s Failed adding mctp-i2c device", - __func__); - } - mutex_unlock(&mi_driver_state.lock); -} - -static void mctp_i2c_notify_del(struct device *dev) -{ - struct i2c_adapter *root = NULL, *adap = NULL; - struct mctp_i2c_client *mcli = NULL; - - adap = mctp_i2c_get_adapter(dev, &root); - if (!adap) - return; - - mutex_lock(&mi_driver_state.lock); - list_for_each_entry(mcli, &mi_driver_state.clients, list) { - if (mcli->client->adapter == root) { - mctp_i2c_remove_netdev(mcli, adap); - break; - } - } - mutex_unlock(&mi_driver_state.lock); -} - -static int mctp_i2c_probe(struct i2c_client *client) -{ - struct mctp_i2c_client *mcli = NULL; - int rc; - - /* Check for >32 byte block support required for MCTP */ - if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_V3_BLOCK)) { - dev_err(&client->dev, - "%s failed, I2C bus driver does not support 255 byte block transfer\n", - __func__); - return -EOPNOTSUPP; - } - - mutex_lock(&mi_driver_state.lock); - mcli = mctp_i2c_new_client(client); - if (IS_ERR(mcli)) { - rc = PTR_ERR(mcli); - mcli = NULL; - goto out; - } else { - list_add(&mcli->list, &mi_driver_state.clients); - } - - // Add a netdev for adapters that have a 'mctp-controller' property - i2c_for_each_dev(mcli, mctp_i2c_client_try_attach); - rc = 0; -out: - mutex_unlock(&mi_driver_state.lock); - return rc; -} - -static int mctp_i2c_remove(struct i2c_client *client) -{ - struct mctp_i2c_client *mcli = i2c_get_clientdata(client); - struct mctp_i2c_dev *midev = NULL, *tmp = NULL; - - mutex_lock(&mi_driver_state.lock); - list_del(&mcli->list); - // Remove all child adapter netdevs - list_for_each_entry_safe(midev, tmp, &mcli->devs, list) - mctp_i2c_free_netdev(midev); - - mctp_i2c_free_client(mcli); - mutex_unlock(&mi_driver_state.lock); - // Callers ignore return code - return 0; -} - -/* We look for a 'mctp-controller' property on I2C busses as they are - * added/deleted, creating/removing netdevs as required. - */ -static int mctp_i2c_notifier_call(struct notifier_block *nb, - unsigned long action, void *data) -{ - struct device *dev = data; - - switch (action) { - case BUS_NOTIFY_ADD_DEVICE: - mctp_i2c_notify_add(dev); - break; - case BUS_NOTIFY_DEL_DEVICE: - mctp_i2c_notify_del(dev); - break; - } - return NOTIFY_DONE; -} - -static struct notifier_block mctp_i2c_notifier = { - .notifier_call = mctp_i2c_notifier_call, -}; - -static const struct i2c_device_id mctp_i2c_id[] = { - { "mctp-i2c", 0 }, - {}, -}; -MODULE_DEVICE_TABLE(i2c, mctp_i2c_id); - -static const struct of_device_id mctp_i2c_of_match[] = { - { .compatible = "mctp-i2c-controller" }, - {}, -}; -MODULE_DEVICE_TABLE(of, mctp_i2c_of_match); - -static struct i2c_driver mctp_i2c_driver = { - .driver = { - .name = "mctp-i2c", - .of_match_table = mctp_i2c_of_match, - }, - .probe_new = mctp_i2c_probe, - .remove = mctp_i2c_remove, - .id_table = mctp_i2c_id, -}; - -static __init int mctp_i2c_init(void) -{ - int rc; - - INIT_LIST_HEAD(&mi_driver_state.clients); - mutex_init(&mi_driver_state.lock); - pr_info("MCTP SMBus/I2C transport driver\n"); - rc = i2c_add_driver(&mctp_i2c_driver); - if (rc) - return rc; - rc = bus_register_notifier(&i2c_bus_type, &mctp_i2c_notifier); - if (rc) { - i2c_del_driver(&mctp_i2c_driver); - return rc; - } - return 0; -} - -static __exit void mctp_i2c_exit(void) -{ - int rc; - - rc = bus_unregister_notifier(&i2c_bus_type, &mctp_i2c_notifier); - if (rc) - pr_warn("%s Could not unregister notifier, %d", __func__, rc); - i2c_del_driver(&mctp_i2c_driver); -} - -module_init(mctp_i2c_init); -module_exit(mctp_i2c_exit); - -MODULE_DESCRIPTION("MCTP SMBus/I2C device"); -MODULE_LICENSE("GPL v2"); -MODULE_AUTHOR("Matt Johnston <matt@codeconstruct.com.au>"); diff --git a/include/linux/i2c.h b/include/linux/i2c.h index 353d6b4e7a53..16119ac1aa97 100644 --- a/include/linux/i2c.h +++ b/include/linux/i2c.h @@ -52,19 +52,6 @@ typedef int (*i2c_slave_cb_t)(struct i2c_client *client, struct module; struct property_entry; -/* SMBus 3.0 extends the maximum block read/write size to 255 (from 32). - * The larger size is only supported by some drivers, indicated by - * the I2C_FUNC_SMBUS_V3_BLOCK functionality bit. - */ -#define I2C_SMBUS_V3_BLOCK_MAX 255 /* As specified in SMBus 3.0 standard */ - -/* Note compatibility definition in uapi header with 32 byte block */ -union i2c_smbus_data { - __u8 byte; - __u16 word; - __u8 block[I2C_SMBUS_V3_BLOCK_MAX + 1]; /* block[0] is used for length */ -}; - #if IS_ENABLED(CONFIG_I2C) /* Return the Frequency mode string based on the bus frequency */ const char *i2c_freq_mode_string(u32 bus_freq_hz); diff --git a/include/uapi/linux/i2c-dev.h b/include/uapi/linux/i2c-dev.h index 46ce31d42f7d..1c4cec4ddd84 100644 --- a/include/uapi/linux/i2c-dev.h +++ b/include/uapi/linux/i2c-dev.h @@ -39,14 +39,12 @@ /* This is the structure as used in the I2C_SMBUS ioctl call */ -#ifndef __KERNEL__ struct i2c_smbus_ioctl_data { __u8 read_write; __u8 command; __u32 size; union i2c_smbus_data __user *data; }; -#endif /* This is the structure as used in the I2C_RDWR ioctl call */ struct i2c_rdwr_ioctl_data { diff --git a/include/uapi/linux/i2c.h b/include/uapi/linux/i2c.h index c3534ab1ae53..92326ebde350 100644 --- a/include/uapi/linux/i2c.h +++ b/include/uapi/linux/i2c.h @@ -108,9 +108,6 @@ struct i2c_msg { #define I2C_FUNC_SMBUS_READ_I2C_BLOCK 0x04000000 /* I2C-like block xfer */ #define I2C_FUNC_SMBUS_WRITE_I2C_BLOCK 0x08000000 /* w/ 1-byte reg. addr. */ #define I2C_FUNC_SMBUS_HOST_NOTIFY 0x10000000 /* SMBus 2.0 or later */ -#define I2C_FUNC_SMBUS_V3_BLOCK 0x20000000 /* Device supports 255 byte block */ - /* Note that I2C_SMBUS ioctl only */ - /* supports a 32 byte block */ #define I2C_FUNC_SMBUS_BYTE (I2C_FUNC_SMBUS_READ_BYTE | \ I2C_FUNC_SMBUS_WRITE_BYTE) @@ -140,15 +137,13 @@ struct i2c_msg { /* * Data for SMBus Messages */ -#define I2C_SMBUS_BLOCK_MAX 32 /* As specified in SMBus 2.0 standard */ -#ifndef __KERNEL__ +#define I2C_SMBUS_BLOCK_MAX 32 /* As specified in SMBus standard */ union i2c_smbus_data { __u8 byte; __u16 word; __u8 block[I2C_SMBUS_BLOCK_MAX + 2]; /* block[0] is used for length */ /* and one more for user-space compatibility */ }; -#endif /* i2c_smbus_xfer read or write markers */ #define I2C_SMBUS_READ 1 |