Skip to content

Commit

Permalink
Merge tag 'for-linus-5.17-1' of https://github.com/cminyard/linux-ipmi
Browse files Browse the repository at this point in the history
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
  • Loading branch information
Linus Torvalds committed Mar 26, 2022
2 parents a452c4e + 8d10ea1 commit 52d543b
Show file tree
Hide file tree
Showing 6 changed files with 70 additions and 72 deletions.
8 changes: 8 additions & 0 deletions Documentation/devicetree/bindings/ipmi/ipmi-ipmb.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions MAINTAINERS
Original file line number Diff line number Diff line change
Expand Up @@ -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/
Expand Down
60 changes: 51 additions & 9 deletions drivers/char/ipmi/ipmi_ipmb.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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) |
Expand Down Expand Up @@ -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;
}

Expand All @@ -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);
Expand All @@ -464,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;
Expand Down Expand Up @@ -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;
}
Expand Down
4 changes: 2 additions & 2 deletions drivers/char/ipmi/ipmi_ssif.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down Expand Up @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion drivers/char/ipmi/ipmi_watchdog.c
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
67 changes: 7 additions & 60 deletions drivers/char/ipmi/kcs_bmc_aspeed.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;

Expand All @@ -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;
Expand All @@ -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;

Expand Down Expand Up @@ -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);
Expand Down

0 comments on commit 52d543b

Please sign in to comment.