Skip to content

Commit 316b7ea

Browse files
committed
Merge tag 'for-linus-5.16-1' of https://github.com/cminyard/linux-ipmi
Pull IPMI driver updates from Corey Minyard: "A new type of low-level IPMI driver is added for direct communication over the IPMI message bus without a BMC between the driver and the bus. Other than that, lots of little bug fixes and enhancements" * tag 'for-linus-5.16-1' of https://github.com/cminyard/linux-ipmi: ipmi: kcs_bmc: Fix a memory leak in the error handling path of 'kcs_bmc_serio_add_device()' char: ipmi: replace snprintf in show functions with sysfs_emit ipmi: ipmb: fix dependencies to eliminate build error ipmi:ipmb: Add OF support ipmi: bt: Add ast2600 compatible string ipmi: bt-bmc: Use registers directly ipmi: ipmb: Fix off-by-one size check on rcvlen ipmi:ssif: Use depends on, not select, for I2C ipmi: Add docs for the IPMI IPMB driver ipmi: Add docs for IPMB direct addressing ipmi:ipmb: Add initial support for IPMI over IPMB ipmi: Add support for IPMB direct messages ipmi: Export ipmb_checksum() ipmi: Fix a typo ipmi: Check error code before processing BMC response ipmi:devintf: Return a proper error when recv buffer too small ipmi: Disable some operations during a panic ipmi:watchdog: Set panic count to proper value on a panic
2 parents 4dee060 + f281d01 commit 316b7ea

File tree

16 files changed

+1078
-123
lines changed

16 files changed

+1078
-123
lines changed

Documentation/devicetree/bindings/ipmi/aspeed,ast2400-ibt-bmc.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ Required properties:
99
- compatible : should be one of
1010
"aspeed,ast2400-ibt-bmc"
1111
"aspeed,ast2500-ibt-bmc"
12+
"aspeed,ast2600-ibt-bmc"
1213
- reg: physical address and size of the registers
1314

1415
Optional properties:
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
2+
%YAML 1.2
3+
---
4+
$id: http://devicetree.org/schemas/ipmi/ipmi-ipmb.yaml#
5+
$schema: http://devicetree.org/meta-schemas/core.yaml#
6+
7+
title: IPMI IPMB device bindings
8+
9+
description: IPMI IPMB device bindings
10+
11+
maintainers:
12+
- Corey Minyard <[email protected]>
13+
14+
properties:
15+
compatible:
16+
enum:
17+
- ipmi-ipmb
18+
19+
device_type:
20+
items:
21+
- const: "ipmi"
22+
23+
reg:
24+
maxItems: 1
25+
26+
bmcaddr:
27+
$ref: /schemas/types.yaml#/definitions/uint8
28+
description: The address of the BMC on the IPMB bus. Defaults to 0x20.
29+
30+
retry-time:
31+
$ref: /schemas/types.yaml#/definitions/uint32
32+
description: |
33+
Time between retries of sends, in milliseconds. Defaults to 250.
34+
35+
max-retries:
36+
$ref: /schemas/types.yaml#/definitions/uint32
37+
description: Number of retries before a failure is declared. Defaults to 1.
38+
39+
required:
40+
- compatible
41+
- reg
42+
43+
additionalProperties: false
44+
45+
examples:
46+
- |
47+
i2c {
48+
#address-cells = <1>;
49+
#size-cells = <0>;
50+
51+
ipmi-ipmb@40 {
52+
compatible = "ipmi-ipmb";
53+
device_type = "ipmi";
54+
reg = <0x40>;
55+
bmcaddr = /bits/ 8 <0x20>;
56+
retry-time = <250>;
57+
max-retries = <1>;
58+
};
59+
};

Documentation/driver-api/ipmi.rst

Lines changed: 62 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -166,8 +166,8 @@ and the type is IPMI_SYSTEM_INTERFACE_ADDR_TYPE. This is used for talking
166166
straight to the BMC on the current card. The channel must be
167167
IPMI_BMC_CHANNEL.
168168

169-
Messages that are destined to go out on the IPMB bus use the
170-
IPMI_IPMB_ADDR_TYPE address type. The format is::
169+
Messages that are destined to go out on the IPMB bus going through the
170+
BMC use the IPMI_IPMB_ADDR_TYPE address type. The format is::
171171

172172
struct ipmi_ipmb_addr
173173
{
@@ -181,6 +181,23 @@ The "channel" here is generally zero, but some devices support more
181181
than one channel, it corresponds to the channel as defined in the IPMI
182182
spec.
183183

184+
There is also an IPMB direct address for a situation where the sender
185+
is directly on an IPMB bus and doesn't have to go through the BMC.
186+
You can send messages to a specific management controller (MC) on the
187+
IPMB using the IPMI_IPMB_DIRECT_ADDR_TYPE with the following format::
188+
189+
struct ipmi_ipmb_direct_addr
190+
{
191+
int addr_type;
192+
short channel;
193+
unsigned char slave_addr;
194+
unsigned char rq_lun;
195+
unsigned char rs_lun;
196+
};
197+
198+
The channel is always zero. You can also receive commands from other
199+
MCs that you have registered to handle and respond to them, so you can
200+
use this to implement a management controller on a bus..
184201

185202
Messages
186203
--------
@@ -348,6 +365,10 @@ user may be registered for each netfn/cmd/channel, but different users
348365
may register for different commands, or the same command if the
349366
channel bitmasks do not overlap.
350367

368+
To respond to a received command, set the response bit in the returned
369+
netfn, use the address from the received message, and use the same
370+
msgid that you got in the receive message.
371+
351372
From userland, equivalent IOCTLs are provided to do these functions.
352373

353374

@@ -570,6 +591,45 @@ web page.
570591
The driver supports a hot add and remove of interfaces through the I2C
571592
sysfs interface.
572593

594+
The IPMI IPMB Driver
595+
--------------------
596+
597+
This driver is for supporting a system that sits on an IPMB bus; it
598+
allows the interface to look like a normal IPMI interface. Sending
599+
system interface addressed messages to it will cause the message to go
600+
to the registered BMC on the system (default at IPMI address 0x20).
601+
602+
It also allows you to directly address other MCs on the bus using the
603+
ipmb direct addressing. You can receive commands from other MCs on
604+
the bus and they will be handled through the normal received command
605+
mechanism described above.
606+
607+
Parameters are::
608+
609+
ipmi_ipmb.bmcaddr=<address to use for system interface addresses messages>
610+
ipmi_ipmb.retry_time_ms=<Time between retries on IPMB>
611+
ipmi_ipmb.max_retries=<Number of times to retry a message>
612+
613+
Loading the module will not result in the driver automatcially
614+
starting unless there is device tree information setting it up. If
615+
you want to instantiate one of these by hand, do::
616+
617+
echo ipmi-ipmb <addr> > /sys/class/i2c-dev/i2c-<n>/device/new_device
618+
619+
Note that the address you give here is the I2C address, not the IPMI
620+
address. So if you want your MC address to be 0x60, you put 0x30
621+
here. See the I2C driver info for more details.
622+
623+
Command bridging to other IPMB busses through this interface does not
624+
work. The receive message queue is not implemented, by design. There
625+
is only one receive message queue on a BMC, and that is meant for the
626+
host drivers, not something on the IPMB bus.
627+
628+
A BMC may have multiple IPMB busses, which bus your device sits on
629+
depends on how the system is wired. You can fetch the channels with
630+
"ipmitool channel info <n>" where <n> is the channel, with the
631+
channels being 0-7 and try the IPMB channels.
632+
573633
Other Pieces
574634
------------
575635

drivers/char/ipmi/Kconfig

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,12 +69,21 @@ config IPMI_SI
6969

7070
config IPMI_SSIF
7171
tristate 'IPMI SMBus handler (SSIF)'
72-
select I2C
72+
depends on I2C
7373
help
7474
Provides a driver for a SMBus interface to a BMC, meaning that you
7575
have a driver that must be accessed over an I2C bus instead of a
7676
standard interface. This module requires I2C support.
7777

78+
config IPMI_IPMB
79+
tristate 'IPMI IPMB interface'
80+
depends on I2C && I2C_SLAVE
81+
help
82+
Provides a driver for a system running right on the IPMB bus.
83+
It supports normal system interface messages to a BMC on the IPMB
84+
bus, and it also supports direct messaging on the bus using
85+
IPMB direct messages. This module requires I2C support.
86+
7887
config IPMI_POWERNV
7988
depends on PPC_POWERNV
8089
tristate 'POWERNV (OPAL firmware) IPMI interface'

drivers/char/ipmi/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ obj-$(CONFIG_IPMI_SI) += ipmi_si.o
1919
obj-$(CONFIG_IPMI_DMI_DECODE) += ipmi_dmi.o
2020
obj-$(CONFIG_IPMI_PLAT_DATA) += ipmi_plat_data.o
2121
obj-$(CONFIG_IPMI_SSIF) += ipmi_ssif.o
22+
obj-$(CONFIG_IPMI_IPMB) += ipmi_ipmb.o
2223
obj-$(CONFIG_IPMI_POWERNV) += ipmi_powernv.o
2324
obj-$(CONFIG_IPMI_WATCHDOG) += ipmi_watchdog.o
2425
obj-$(CONFIG_IPMI_POWEROFF) += ipmi_poweroff.o

drivers/char/ipmi/bt-bmc.c

Lines changed: 17 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,11 @@
88
#include <linux/errno.h>
99
#include <linux/interrupt.h>
1010
#include <linux/io.h>
11-
#include <linux/mfd/syscon.h>
1211
#include <linux/miscdevice.h>
1312
#include <linux/module.h>
1413
#include <linux/of.h>
1514
#include <linux/platform_device.h>
1615
#include <linux/poll.h>
17-
#include <linux/regmap.h>
1816
#include <linux/sched.h>
1917
#include <linux/timer.h>
2018

@@ -59,8 +57,7 @@
5957
struct bt_bmc {
6058
struct device dev;
6159
struct miscdevice miscdev;
62-
struct regmap *map;
63-
int offset;
60+
void __iomem *base;
6461
int irq;
6562
wait_queue_head_t queue;
6663
struct timer_list poll_timer;
@@ -69,29 +66,14 @@ struct bt_bmc {
6966

7067
static atomic_t open_count = ATOMIC_INIT(0);
7168

72-
static const struct regmap_config bt_regmap_cfg = {
73-
.reg_bits = 32,
74-
.val_bits = 32,
75-
.reg_stride = 4,
76-
};
77-
7869
static u8 bt_inb(struct bt_bmc *bt_bmc, int reg)
7970
{
80-
uint32_t val = 0;
81-
int rc;
82-
83-
rc = regmap_read(bt_bmc->map, bt_bmc->offset + reg, &val);
84-
WARN(rc != 0, "regmap_read() failed: %d\n", rc);
85-
86-
return rc == 0 ? (u8) val : 0;
71+
return readb(bt_bmc->base + reg);
8772
}
8873

8974
static void bt_outb(struct bt_bmc *bt_bmc, u8 data, int reg)
9075
{
91-
int rc;
92-
93-
rc = regmap_write(bt_bmc->map, bt_bmc->offset + reg, data);
94-
WARN(rc != 0, "regmap_write() failed: %d\n", rc);
76+
writeb(data, bt_bmc->base + reg);
9577
}
9678

9779
static void clr_rd_ptr(struct bt_bmc *bt_bmc)
@@ -376,18 +358,15 @@ static irqreturn_t bt_bmc_irq(int irq, void *arg)
376358
{
377359
struct bt_bmc *bt_bmc = arg;
378360
u32 reg;
379-
int rc;
380361

381-
rc = regmap_read(bt_bmc->map, bt_bmc->offset + BT_CR2, &reg);
382-
if (rc)
383-
return IRQ_NONE;
362+
reg = readl(bt_bmc->base + BT_CR2);
384363

385364
reg &= BT_CR2_IRQ_H2B | BT_CR2_IRQ_HBUSY;
386365
if (!reg)
387366
return IRQ_NONE;
388367

389368
/* ack pending IRQs */
390-
regmap_write(bt_bmc->map, bt_bmc->offset + BT_CR2, reg);
369+
writel(reg, bt_bmc->base + BT_CR2);
391370

392371
wake_up(&bt_bmc->queue);
393372
return IRQ_HANDLED;
@@ -398,6 +377,7 @@ static int bt_bmc_config_irq(struct bt_bmc *bt_bmc,
398377
{
399378
struct device *dev = &pdev->dev;
400379
int rc;
380+
u32 reg;
401381

402382
bt_bmc->irq = platform_get_irq_optional(pdev, 0);
403383
if (bt_bmc->irq < 0)
@@ -417,11 +397,11 @@ static int bt_bmc_config_irq(struct bt_bmc *bt_bmc,
417397
* will be cleared (along with B2H) when we can write the next
418398
* message to the BT buffer
419399
*/
420-
rc = regmap_update_bits(bt_bmc->map, bt_bmc->offset + BT_CR1,
421-
(BT_CR1_IRQ_H2B | BT_CR1_IRQ_HBUSY),
422-
(BT_CR1_IRQ_H2B | BT_CR1_IRQ_HBUSY));
400+
reg = readl(bt_bmc->base + BT_CR1);
401+
reg |= BT_CR1_IRQ_H2B | BT_CR1_IRQ_HBUSY;
402+
writel(reg, bt_bmc->base + BT_CR1);
423403

424-
return rc;
404+
return 0;
425405
}
426406

427407
static int bt_bmc_probe(struct platform_device *pdev)
@@ -439,25 +419,9 @@ static int bt_bmc_probe(struct platform_device *pdev)
439419

440420
dev_set_drvdata(&pdev->dev, bt_bmc);
441421

442-
bt_bmc->map = syscon_node_to_regmap(pdev->dev.parent->of_node);
443-
if (IS_ERR(bt_bmc->map)) {
444-
void __iomem *base;
445-
446-
/*
447-
* Assume it's not the MFD-based devicetree description, in
448-
* which case generate a regmap ourselves
449-
*/
450-
base = devm_platform_ioremap_resource(pdev, 0);
451-
if (IS_ERR(base))
452-
return PTR_ERR(base);
453-
454-
bt_bmc->map = devm_regmap_init_mmio(dev, base, &bt_regmap_cfg);
455-
bt_bmc->offset = 0;
456-
} else {
457-
rc = of_property_read_u32(dev->of_node, "reg", &bt_bmc->offset);
458-
if (rc)
459-
return rc;
460-
}
422+
bt_bmc->base = devm_platform_ioremap_resource(pdev, 0);
423+
if (IS_ERR(bt_bmc->base))
424+
return PTR_ERR(bt_bmc->base);
461425

462426
mutex_init(&bt_bmc->mutex);
463427
init_waitqueue_head(&bt_bmc->queue);
@@ -483,12 +447,12 @@ static int bt_bmc_probe(struct platform_device *pdev)
483447
add_timer(&bt_bmc->poll_timer);
484448
}
485449

486-
regmap_write(bt_bmc->map, bt_bmc->offset + BT_CR0,
487-
(BT_IO_BASE << BT_CR0_IO_BASE) |
450+
writel((BT_IO_BASE << BT_CR0_IO_BASE) |
488451
(BT_IRQ << BT_CR0_IRQ) |
489452
BT_CR0_EN_CLR_SLV_RDP |
490453
BT_CR0_EN_CLR_SLV_WRP |
491-
BT_CR0_ENABLE_IBT);
454+
BT_CR0_ENABLE_IBT,
455+
bt_bmc->base + BT_CR0);
492456

493457
clr_b_busy(bt_bmc);
494458

@@ -508,6 +472,7 @@ static int bt_bmc_remove(struct platform_device *pdev)
508472
static const struct of_device_id bt_bmc_match[] = {
509473
{ .compatible = "aspeed,ast2400-ibt-bmc" },
510474
{ .compatible = "aspeed,ast2500-ibt-bmc" },
475+
{ .compatible = "aspeed,ast2600-ibt-bmc" },
511476
{ },
512477
};
513478

drivers/char/ipmi/ipmi_devintf.c

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -247,11 +247,13 @@ static int handle_recv(struct ipmi_file_private *priv,
247247

248248
if (msg->msg.data_len > 0) {
249249
if (rsp->msg.data_len < msg->msg.data_len) {
250-
rv2 = -EMSGSIZE;
251-
if (trunc)
250+
if (trunc) {
251+
rv2 = -EMSGSIZE;
252252
msg->msg.data_len = rsp->msg.data_len;
253-
else
253+
} else {
254+
rv = -EMSGSIZE;
254255
goto recv_putback_on_err;
256+
}
255257
}
256258

257259
if (copy_to_user(rsp->msg.data,

0 commit comments

Comments
 (0)