Commit 52d543b5 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'for-linus-5.17-1' of https://github.com/cminyard/linux-ipmi

Pull IPMI updates from Corey Minyard:

 - Little fixes for various things people have noticed.

 - One enhancement, the IPMI over IPMB (I2c) is modified to allow it to
   take a separate sender and receiver device. The Raspberry Pi has an
   I2C slave device that cannot send.

* tag 'for-linus-5.17-1' of https://github.com/cminyard/linux-ipmi:
  ipmi: initialize len variable
  ipmi: kcs: aspeed: Remove old bindings support
  ipmi:ipmb: Add the ability to have a separate slave and master device
  ipmi:ipmi_ipmb: Unregister the SMI on remove
  ipmi: kcs: aspeed: Add AST2600 compatible string
  ipmi: ssif: replace strlcpy with strscpy
  ipmi/watchdog: Constify ident
  ipmi: Add the git repository to the MAINTAINERS file
parents a452c4eb 8d10ea15
......@@ -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
......
......@@ -10171,6 +10171,7 @@ M: Corey Minyard <minyard@acm.org>
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/
......
......@@ -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,12 +428,17 @@ 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);
return 0;
}
......@@ -441,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);
......@@ -464,14 +473,45 @@ static int ipmi_ipmb_probe(struct i2c_client *client,
&iidev->max_retries) != 0)
iidev->max_retries = max_retries;
i2c_set_clientdata(client, iidev);
client->flags |= I2C_CLIENT_SLAVE;
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;
}
}
rv = i2c_slave_register(client, ipmi_ipmb_slave_cb);
if (rv)
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);
slave->flags |= I2C_CLIENT_SLAVE;
iidev->client = client;
rv = i2c_slave_register(slave, ipmi_ipmb_slave_cb);
if (rv)
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;
......@@ -502,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;
}
......
......@@ -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;
}
......@@ -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;
......
......@@ -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"
......
......@@ -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,21 +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,ast2400-kcs-bmc-v2" },
{ .compatible = "aspeed,ast2500-kcs-bmc-v2" },
{ .compatible = "aspeed,ast2600-kcs-bmc" },
{ }
};
MODULE_DEVICE_TABLE(of, ast_kcs_bmc_match);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment