Minor fixes for IPMI

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.
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCgAdFiEE/Q1c5nzg9ZpmiCaGYfOMkJGb/4EFAmI8qi4ACgkQYfOMkJGb
 /4EVoBAAqHQ0DlNxMDF/oLLqV1j+Hw6BEo8s5IoYpN/U9A5lfz0YnWPXxSd00Cvx
 S49bVVnF+PhjWnB7t6UTqqOQIOJFSr9fAdrWGKUbO6tneO9Sq3EIWNHlzuTw4ZRw
 A/BL4MnCkDI4pxqvI3zOdghEBuY2nIsMHV3SrFsQ7XSYE0Llf1KRn+VFPidfDAO7
 4zHbu2+I7kGYU1zXw/IuTTyFEUbXbMhJjdxDCzOmXny5lta1jBvviL760uWSTT2c
 Hz14bCX4typA3dVdvfTMOQOOF1X6j+3fNT+Yq4mSIDBuib0pZxycx0/DkyiG3tVb
 8rTWnZFQWx6b5z6zKSTF522GwhFjHubKp04CHdNxwp0hhULSEVhn7JULzRbBz3Wm
 dVHGcX7uJFtazZy2ckGgRy0hLiKa11h/tE5ZIi3fgDOX0HkSxObJ7M75LfzkqAhP
 1KIQc2YPkQkj/XOVGX2o2fCRZ/4DG5uSkq/RFmDYmTyrHLnioyZthzWvhrBYR6r4
 hrCb89zwiow9HYxaOxLx3GygRitExdTlmv1ORsXioVls024ulYs0arefH04zqVt3
 J/QvaO1+hsh681IBelsxj+TCwYSZXZ1zWH4MnS6A8bTkiwHny3xrAtQG9Qq1qivd
 EhhB3Z6VIsQ0ry5Hdp+TLgU3fTHUFcas4DqVRZwDfydlz7/pPdQ=
 =FQQz
 -----END PGP SIGNATURE-----

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
This commit is contained in:
Linus Torvalds 2022-03-25 17:46:22 -07:00
commit 52d543b549
6 changed files with 71 additions and 73 deletions

View File

@ -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

View File

@ -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/

View File

@ -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,15 +473,46 @@ 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;
rv = i2c_slave_register(client, ipmi_ipmb_slave_cb);
if (rv)
return rv;
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);
slave->flags |= I2C_CLIENT_SLAVE;
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;
iidev->handlers.shutdown = ipmi_ipmb_shutdown;
@ -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;
}

View File

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

View File

@ -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"

View File

@ -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);