From 993220ba6706dddbc73d9fc6bc21d371b9b4570c Mon Sep 17 00:00:00 2001 From: Corey Minyard Date: Fri, 26 Nov 2021 18:12:14 -0600 Subject: [PATCH 1/8] ipmi: Add the git repository to the MAINTAINERS file Advertise where the IPMI git repository is stored. Signed-off-by: Corey Minyard --- MAINTAINERS | 1 + 1 file changed, 1 insertion(+) diff --git a/MAINTAINERS b/MAINTAINERS index a58544f7b6999..9dc675a8bdddf 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -10074,6 +10074,7 @@ M: Corey Minyard L: openipmi-developer@lists.sourceforge.net (moderated for non-subscribers) S: Supported W: http://openipmi.sourceforge.net/ +T: git https://github.com/cminyard/linux-ipmi.git for-next F: Documentation/driver-api/ipmi.rst F: Documentation/devicetree/bindings/ipmi/ F: drivers/char/ipmi/ From 7281599201c3336e350406781e7d88ca92453727 Mon Sep 17 00:00:00 2001 From: Rikard Falkeborn Date: Sun, 28 Nov 2021 23:01:54 +0100 Subject: [PATCH 2/8] ipmi/watchdog: Constify ident ident is not modified and can be made const to allow the compiler to put it in read-only memory. Signed-off-by: Rikard Falkeborn Message-Id: <20211128220154.32927-1-rikard.falkeborn@gmail.com> Signed-off-by: Corey Minyard --- drivers/char/ipmi/ipmi_watchdog.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/char/ipmi/ipmi_watchdog.c b/drivers/char/ipmi/ipmi_watchdog.c index 883b4a3410122..0604abdd249a1 100644 --- a/drivers/char/ipmi/ipmi_watchdog.c +++ b/drivers/char/ipmi/ipmi_watchdog.c @@ -668,7 +668,7 @@ static int ipmi_heartbeat(void) return rv; } -static struct watchdog_info ident = { +static const struct watchdog_info ident = { .options = 0, /* WDIOF_SETTIMEOUT, */ .firmware_version = 1, .identity = "IPMI" From d134ad2574a1c9b5c34659709769bdb25295fd25 Mon Sep 17 00:00:00 2001 From: Jason Wang Date: Wed, 22 Dec 2021 11:27:07 +0800 Subject: [PATCH 3/8] ipmi: ssif: replace strlcpy with strscpy The strlcpy should not be used because it doesn't limit the source length. So that it will lead some potential bugs. But the strscpy doesn't require reading memory from the src string beyond the specified "count" bytes, and since the return value is easier to error-check than strlcpy()'s. In addition, the implementation is robust to the string changing out from underneath it, unlike the current strlcpy() implementation. Thus, replace strlcpy with strscpy. Signed-off-by: Jason Wang Message-Id: <20211222032707.1912186-1-wangborong@cdjrlc.com> Signed-off-by: Corey Minyard --- drivers/char/ipmi/ipmi_ssif.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/char/ipmi/ipmi_ssif.c b/drivers/char/ipmi/ipmi_ssif.c index 48aab77abebf1..ba779f1abb5b2 100644 --- a/drivers/char/ipmi/ipmi_ssif.c +++ b/drivers/char/ipmi/ipmi_ssif.c @@ -1354,7 +1354,7 @@ static int ssif_detect(struct i2c_client *client, struct i2c_board_info *info) if (rv) rv = -ENODEV; else - strlcpy(info->type, DEVICE_NAME, I2C_NAME_SIZE); + strscpy(info->type, DEVICE_NAME, I2C_NAME_SIZE); kfree(resp); return rv; } From 2596f6b93a606332c0e5759991e880fbe76e6c8d Mon Sep 17 00:00:00 2001 From: Joel Stanley Date: Mon, 21 Feb 2022 17:33:51 +1030 Subject: [PATCH 4/8] ipmi: kcs: aspeed: Add AST2600 compatible string The AST2600 is already described in the bindings, but the driver never gained a compatible string. Signed-off-by: Joel Stanley Message-Id: <20220221070351.121905-1-joel@jms.id.au> Signed-off-by: Corey Minyard --- drivers/char/ipmi/kcs_bmc_aspeed.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/char/ipmi/kcs_bmc_aspeed.c b/drivers/char/ipmi/kcs_bmc_aspeed.c index 92a37b33494cb..b555286016b10 100644 --- a/drivers/char/ipmi/kcs_bmc_aspeed.c +++ b/drivers/char/ipmi/kcs_bmc_aspeed.c @@ -693,6 +693,7 @@ static const struct of_device_id ast_kcs_bmc_match[] = { { .compatible = "aspeed,ast2500-kcs-bmc", .data = &of_v1_ops }, { .compatible = "aspeed,ast2400-kcs-bmc-v2", .data = &of_v2_ops }, { .compatible = "aspeed,ast2500-kcs-bmc-v2", .data = &of_v2_ops }, + { .compatible = "aspeed,ast2600-kcs-bmc", .data = &of_v2_ops }, { } }; MODULE_DEVICE_TABLE(of, ast_kcs_bmc_match); From 57c9e3c9a374ff1419e5559f8979c0b43a0bffbd Mon Sep 17 00:00:00 2001 From: Corey Minyard Date: Wed, 23 Feb 2022 07:38:12 -0600 Subject: [PATCH 5/8] ipmi:ipmi_ipmb: Unregister the SMI on remove Otherwise it will continue to be hooked into the IPMI framework. Signed-off-by: Corey Minyard --- drivers/char/ipmi/ipmi_ipmb.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/char/ipmi/ipmi_ipmb.c b/drivers/char/ipmi/ipmi_ipmb.c index ba0c2d2c6bbe0..88d7316b3babc 100644 --- a/drivers/char/ipmi/ipmi_ipmb.c +++ b/drivers/char/ipmi/ipmi_ipmb.c @@ -433,6 +433,8 @@ static int ipmi_ipmb_remove(struct i2c_client *client) } ipmi_ipmb_stop_thread(iidev); + ipmi_unregister_smi(iidev->intf); + return 0; } From 00d93611f00219bd142aa119c5121793cac30ff0 Mon Sep 17 00:00:00 2001 From: Corey Minyard Date: Sun, 20 Feb 2022 14:38:39 -0600 Subject: [PATCH 6/8] ipmi:ipmb: Add the ability to have a separate slave and master device A situation has come up where there is a slave-only device for the slave and a separate master device on the same bug. Allow a separate slave device to be registered. Signed-off-by: Corey Minyard --- .../devicetree/bindings/ipmi/ipmi-ipmb.yaml | 8 +++ drivers/char/ipmi/ipmi_ipmb.c | 58 ++++++++++++++++--- 2 files changed, 57 insertions(+), 9 deletions(-) diff --git a/Documentation/devicetree/bindings/ipmi/ipmi-ipmb.yaml b/Documentation/devicetree/bindings/ipmi/ipmi-ipmb.yaml index 93d8f8e88cf56..71bc031c4fde6 100644 --- a/Documentation/devicetree/bindings/ipmi/ipmi-ipmb.yaml +++ b/Documentation/devicetree/bindings/ipmi/ipmi-ipmb.yaml @@ -36,6 +36,14 @@ properties: $ref: /schemas/types.yaml#/definitions/uint32 description: Number of retries before a failure is declared. Defaults to 1. + slave-dev: + $ref: /schemas/types.yaml#/definitions/phandle + description: | + The slave i2c device. If not present, the main device is used. This + lets you use two devices on the IPMB, one for master and one for slave, + in case you have a slave device that can only be a slave. The slave + will receive messages and the master will transmit. + required: - compatible - reg diff --git a/drivers/char/ipmi/ipmi_ipmb.c b/drivers/char/ipmi/ipmi_ipmb.c index 88d7316b3babc..b81b862532fb0 100644 --- a/drivers/char/ipmi/ipmi_ipmb.c +++ b/drivers/char/ipmi/ipmi_ipmb.c @@ -39,6 +39,7 @@ MODULE_PARM_DESC(max_retries, "Max resends of a command before timing out."); struct ipmi_ipmb_dev { struct ipmi_smi *intf; struct i2c_client *client; + struct i2c_client *slave; struct ipmi_smi_handlers handlers; @@ -257,7 +258,7 @@ static void ipmi_ipmb_format_for_xmit(struct ipmi_ipmb_dev *iidev, memcpy(iidev->xmitmsg + 5, msg->data + 1, msg->data_size - 1); iidev->xmitlen = msg->data_size + 4; } - iidev->xmitmsg[3] = iidev->client->addr << 1; + iidev->xmitmsg[3] = iidev->slave->addr << 1; if (((msg->data[0] >> 2) & 1) == 0) /* If it's a command, put in our own sequence number. */ iidev->xmitmsg[4] = ((iidev->xmitmsg[4] & 0x03) | @@ -427,10 +428,13 @@ static int ipmi_ipmb_remove(struct i2c_client *client) { struct ipmi_ipmb_dev *iidev = i2c_get_clientdata(client); - if (iidev->client) { - iidev->client = NULL; - i2c_slave_unregister(client); + if (iidev->slave) { + i2c_slave_unregister(iidev->slave); + if (iidev->slave != iidev->client) + i2c_unregister_device(iidev->slave); } + iidev->slave = NULL; + iidev->client = NULL; ipmi_ipmb_stop_thread(iidev); ipmi_unregister_smi(iidev->intf); @@ -443,6 +447,9 @@ static int ipmi_ipmb_probe(struct i2c_client *client, { struct device *dev = &client->dev; struct ipmi_ipmb_dev *iidev; + struct device_node *slave_np; + struct i2c_adapter *slave_adap = NULL; + struct i2c_client *slave = NULL; int rv; iidev = devm_kzalloc(&client->dev, sizeof(*iidev), GFP_KERNEL); @@ -466,14 +473,45 @@ static int ipmi_ipmb_probe(struct i2c_client *client, &iidev->max_retries) != 0) iidev->max_retries = max_retries; + slave_np = of_parse_phandle(dev->of_node, "slave-dev", 0); + if (slave_np) { + slave_adap = of_get_i2c_adapter_by_node(slave_np); + if (!slave_adap) { + dev_notice(&client->dev, + "Could not find slave adapter\n"); + return -EINVAL; + } + } + + iidev->client = client; + + if (slave_adap) { + struct i2c_board_info binfo; + + memset(&binfo, 0, sizeof(binfo)); + strscpy(binfo.type, "ipmb-slave", I2C_NAME_SIZE); + binfo.addr = client->addr; + binfo.flags = I2C_CLIENT_SLAVE; + slave = i2c_new_client_device(slave_adap, &binfo); + i2c_put_adapter(slave_adap); + if (IS_ERR(slave)) { + rv = PTR_ERR(slave); + dev_notice(&client->dev, + "Could not allocate slave device: %d\n", rv); + return rv; + } + i2c_set_clientdata(slave, iidev); + } else { + slave = client; + } i2c_set_clientdata(client, iidev); - client->flags |= I2C_CLIENT_SLAVE; + slave->flags |= I2C_CLIENT_SLAVE; - rv = i2c_slave_register(client, ipmi_ipmb_slave_cb); + rv = i2c_slave_register(slave, ipmi_ipmb_slave_cb); if (rv) - return rv; - - iidev->client = client; + goto out_err; + iidev->slave = slave; + slave = NULL; iidev->handlers.flags = IPMI_SMI_CAN_HANDLE_IPMB_DIRECT; iidev->handlers.start_processing = ipmi_ipmb_start_processing; @@ -504,6 +542,8 @@ static int ipmi_ipmb_probe(struct i2c_client *client, return 0; out_err: + if (slave && slave != client) + i2c_unregister_device(slave); ipmi_ipmb_remove(client); return rv; } From f4676c8ec39689c6370bd58f4266c5c613de2a28 Mon Sep 17 00:00:00 2001 From: Joel Stanley Date: Mon, 28 Feb 2022 16:58:40 +1030 Subject: [PATCH 7/8] ipmi: kcs: aspeed: Remove old bindings support It's been a few releases since we depreciated the "v1" bindings. Remove support from the driver as all known device trees have been updated to use the new bindings. Signed-off-by: Joel Stanley Message-Id: <20220228062840.449215-1-joel@jms.id.au> Signed-off-by: Corey Minyard --- drivers/char/ipmi/kcs_bmc_aspeed.c | 68 +++--------------------------- 1 file changed, 7 insertions(+), 61 deletions(-) diff --git a/drivers/char/ipmi/kcs_bmc_aspeed.c b/drivers/char/ipmi/kcs_bmc_aspeed.c index b555286016b10..cdc88cde1e9aa 100644 --- a/drivers/char/ipmi/kcs_bmc_aspeed.c +++ b/drivers/char/ipmi/kcs_bmc_aspeed.c @@ -128,11 +128,6 @@ struct aspeed_kcs_bmc { } obe; }; -struct aspeed_kcs_of_ops { - int (*get_channel)(struct platform_device *pdev); - int (*get_io_address)(struct platform_device *pdev, u32 addrs[2]); -}; - static inline struct aspeed_kcs_bmc *to_aspeed_kcs_bmc(struct kcs_bmc_device *kcs_bmc) { return container_of(kcs_bmc, struct aspeed_kcs_bmc, kcs_bmc); @@ -475,38 +470,7 @@ static const struct kcs_ioreg ast_kcs_bmc_ioregs[KCS_CHANNEL_MAX] = { { .idr = LPC_IDR4, .odr = LPC_ODR4, .str = LPC_STR4 }, }; -static int aspeed_kcs_of_v1_get_channel(struct platform_device *pdev) -{ - struct device_node *np; - u32 channel; - int rc; - - np = pdev->dev.of_node; - - rc = of_property_read_u32(np, "kcs_chan", &channel); - if ((rc != 0) || (channel == 0 || channel > KCS_CHANNEL_MAX)) { - dev_err(&pdev->dev, "no valid 'kcs_chan' configured\n"); - return -EINVAL; - } - - return channel; -} - -static int -aspeed_kcs_of_v1_get_io_address(struct platform_device *pdev, u32 addrs[2]) -{ - int rc; - - rc = of_property_read_u32(pdev->dev.of_node, "kcs_addr", addrs); - if (rc || addrs[0] > 0xffff) { - dev_err(&pdev->dev, "no valid 'kcs_addr' configured\n"); - return -EINVAL; - } - - return 1; -} - -static int aspeed_kcs_of_v2_get_channel(struct platform_device *pdev) +static int aspeed_kcs_of_get_channel(struct platform_device *pdev) { struct device_node *np; struct kcs_ioreg ioreg; @@ -535,12 +499,11 @@ static int aspeed_kcs_of_v2_get_channel(struct platform_device *pdev) if (!memcmp(&ast_kcs_bmc_ioregs[i], &ioreg, sizeof(ioreg))) return i + 1; } - return -EINVAL; } static int -aspeed_kcs_of_v2_get_io_address(struct platform_device *pdev, u32 addrs[2]) +aspeed_kcs_of_get_io_address(struct platform_device *pdev, u32 addrs[2]) { int rc; @@ -567,7 +530,6 @@ aspeed_kcs_of_v2_get_io_address(struct platform_device *pdev, u32 addrs[2]) static int aspeed_kcs_probe(struct platform_device *pdev) { - const struct aspeed_kcs_of_ops *ops; struct kcs_bmc_device *kcs_bmc; struct aspeed_kcs_bmc *priv; struct device_node *np; @@ -585,15 +547,11 @@ static int aspeed_kcs_probe(struct platform_device *pdev) return -ENODEV; } - ops = of_device_get_match_data(&pdev->dev); - if (!ops) - return -EINVAL; - - channel = ops->get_channel(pdev); + channel = aspeed_kcs_of_get_channel(pdev); if (channel < 0) return channel; - nr_addrs = ops->get_io_address(pdev, addrs); + nr_addrs = aspeed_kcs_of_get_io_address(pdev, addrs); if (nr_addrs < 0) return nr_addrs; @@ -678,22 +636,10 @@ static int aspeed_kcs_remove(struct platform_device *pdev) return 0; } -static const struct aspeed_kcs_of_ops of_v1_ops = { - .get_channel = aspeed_kcs_of_v1_get_channel, - .get_io_address = aspeed_kcs_of_v1_get_io_address, -}; - -static const struct aspeed_kcs_of_ops of_v2_ops = { - .get_channel = aspeed_kcs_of_v2_get_channel, - .get_io_address = aspeed_kcs_of_v2_get_io_address, -}; - static const struct of_device_id ast_kcs_bmc_match[] = { - { .compatible = "aspeed,ast2400-kcs-bmc", .data = &of_v1_ops }, - { .compatible = "aspeed,ast2500-kcs-bmc", .data = &of_v1_ops }, - { .compatible = "aspeed,ast2400-kcs-bmc-v2", .data = &of_v2_ops }, - { .compatible = "aspeed,ast2500-kcs-bmc-v2", .data = &of_v2_ops }, - { .compatible = "aspeed,ast2600-kcs-bmc", .data = &of_v2_ops }, + { .compatible = "aspeed,ast2400-kcs-bmc-v2" }, + { .compatible = "aspeed,ast2500-kcs-bmc-v2" }, + { .compatible = "aspeed,ast2600-kcs-bmc" }, { } }; MODULE_DEVICE_TABLE(of, ast_kcs_bmc_match); From 8d10ea152e2fb9b4a42b282cb90bfc4d98e319a3 Mon Sep 17 00:00:00 2001 From: Tom Rix Date: Sun, 20 Mar 2022 06:59:54 -0700 Subject: [PATCH 8/8] ipmi: initialize len variable Clang static analysis reports this issue ipmi_ssif.c:1731:3: warning: 4th function call argument is an uninitialized value dev_info(&ssif_info->client->dev, ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The 4th parameter is the 'len' variable. len is only set by a successful call to do_cmd(). Initialize to len 0. Signed-off-by: Tom Rix Message-Id: <20220320135954.2258545-1-trix@redhat.com> Signed-off-by: Corey Minyard --- drivers/char/ipmi/ipmi_ssif.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/char/ipmi/ipmi_ssif.c b/drivers/char/ipmi/ipmi_ssif.c index ba779f1abb5b2..f199cc1948446 100644 --- a/drivers/char/ipmi/ipmi_ssif.c +++ b/drivers/char/ipmi/ipmi_ssif.c @@ -1625,7 +1625,7 @@ static int ssif_probe(struct i2c_client *client, const struct i2c_device_id *id) unsigned char *resp; struct ssif_info *ssif_info; int rv = 0; - int len; + int len = 0; int i; u8 slave_addr = 0; struct ssif_addr_info *addr_info = NULL;