diff --git a/ipmi-fixes.patch b/ipmi-fixes.patch new file mode 100644 index 0000000..b1838ef --- /dev/null +++ b/ipmi-fixes.patch @@ -0,0 +1,2460 @@ +From 20d60f61c58e8c937f3653819816dd203e6e3cb4 Mon Sep 17 00:00:00 2001 +From: Haiyue Wang +Date: Fri, 2 Feb 2018 10:16:10 +0800 +Subject: [PATCH 1/9] ipmi: add a KCS IPMI BMC driver + +Provides a device driver for the KCS (Keyboard Controller Style) +IPMI interface which meets the requirement of the BMC (Baseboard +Management Controllers) side for handling the IPMI request from +host system software. + +Signed-off-by: Haiyue Wang +[Removed the selectability of IPMI_KCS_BMC, as it doesn't do much + good to have it by itself.] +Signed-off-by: Corey Minyard +--- + drivers/char/ipmi/Kconfig | 3 + + drivers/char/ipmi/Makefile | 1 + + drivers/char/ipmi/kcs_bmc.c | 464 ++++++++++++++++++++++++++++++++++++++++++ + drivers/char/ipmi/kcs_bmc.h | 106 ++++++++++ + include/uapi/linux/ipmi_bmc.h | 14 ++ + 5 files changed, 588 insertions(+) + create mode 100644 drivers/char/ipmi/kcs_bmc.c + create mode 100644 drivers/char/ipmi/kcs_bmc.h + create mode 100644 include/uapi/linux/ipmi_bmc.h + +diff --git a/drivers/char/ipmi/Kconfig b/drivers/char/ipmi/Kconfig +index 3544abc0f9f9..7641b8a2f632 100644 +--- a/drivers/char/ipmi/Kconfig ++++ b/drivers/char/ipmi/Kconfig +@@ -96,6 +96,9 @@ config IPMI_POWEROFF + + endif # IPMI_HANDLER + ++config IPMI_KCS_BMC ++ tristate ++ + config ASPEED_BT_IPMI_BMC + depends on ARCH_ASPEED || COMPILE_TEST + depends on REGMAP && REGMAP_MMIO && MFD_SYSCON +diff --git a/drivers/char/ipmi/Makefile b/drivers/char/ipmi/Makefile +index 33b899fcf14a..2abccb30016a 100644 +--- a/drivers/char/ipmi/Makefile ++++ b/drivers/char/ipmi/Makefile +@@ -21,4 +21,5 @@ obj-$(CONFIG_IPMI_SSIF) += ipmi_ssif.o + obj-$(CONFIG_IPMI_POWERNV) += ipmi_powernv.o + obj-$(CONFIG_IPMI_WATCHDOG) += ipmi_watchdog.o + obj-$(CONFIG_IPMI_POWEROFF) += ipmi_poweroff.o ++obj-$(CONFIG_IPMI_KCS_BMC) += kcs_bmc.o + obj-$(CONFIG_ASPEED_BT_IPMI_BMC) += bt-bmc.o +diff --git a/drivers/char/ipmi/kcs_bmc.c b/drivers/char/ipmi/kcs_bmc.c +new file mode 100644 +index 000000000000..3a3498afa427 +--- /dev/null ++++ b/drivers/char/ipmi/kcs_bmc.c +@@ -0,0 +1,464 @@ ++// SPDX-License-Identifier: GPL-2.0 ++// Copyright (c) 2015-2018, Intel Corporation. ++ ++#define pr_fmt(fmt) "kcs-bmc: " fmt ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "kcs_bmc.h" ++ ++#define KCS_MSG_BUFSIZ 1000 ++ ++#define KCS_ZERO_DATA 0 ++ ++ ++/* IPMI 2.0 - Table 9-1, KCS Interface Status Register Bits */ ++#define KCS_STATUS_STATE(state) (state << 6) ++#define KCS_STATUS_STATE_MASK GENMASK(7, 6) ++#define KCS_STATUS_CMD_DAT BIT(3) ++#define KCS_STATUS_SMS_ATN BIT(2) ++#define KCS_STATUS_IBF BIT(1) ++#define KCS_STATUS_OBF BIT(0) ++ ++/* IPMI 2.0 - Table 9-2, KCS Interface State Bits */ ++enum kcs_states { ++ IDLE_STATE = 0, ++ READ_STATE = 1, ++ WRITE_STATE = 2, ++ ERROR_STATE = 3, ++}; ++ ++/* IPMI 2.0 - Table 9-3, KCS Interface Control Codes */ ++#define KCS_CMD_GET_STATUS_ABORT 0x60 ++#define KCS_CMD_WRITE_START 0x61 ++#define KCS_CMD_WRITE_END 0x62 ++#define KCS_CMD_READ_BYTE 0x68 ++ ++static inline u8 read_data(struct kcs_bmc *kcs_bmc) ++{ ++ return kcs_bmc->io_inputb(kcs_bmc, kcs_bmc->ioreg.idr); ++} ++ ++static inline void write_data(struct kcs_bmc *kcs_bmc, u8 data) ++{ ++ kcs_bmc->io_outputb(kcs_bmc, kcs_bmc->ioreg.odr, data); ++} ++ ++static inline u8 read_status(struct kcs_bmc *kcs_bmc) ++{ ++ return kcs_bmc->io_inputb(kcs_bmc, kcs_bmc->ioreg.str); ++} ++ ++static inline void write_status(struct kcs_bmc *kcs_bmc, u8 data) ++{ ++ kcs_bmc->io_outputb(kcs_bmc, kcs_bmc->ioreg.str, data); ++} ++ ++static void update_status_bits(struct kcs_bmc *kcs_bmc, u8 mask, u8 val) ++{ ++ u8 tmp = read_status(kcs_bmc); ++ ++ tmp &= ~mask; ++ tmp |= val & mask; ++ ++ write_status(kcs_bmc, tmp); ++} ++ ++static inline void set_state(struct kcs_bmc *kcs_bmc, u8 state) ++{ ++ update_status_bits(kcs_bmc, KCS_STATUS_STATE_MASK, ++ KCS_STATUS_STATE(state)); ++} ++ ++static void kcs_force_abort(struct kcs_bmc *kcs_bmc) ++{ ++ set_state(kcs_bmc, ERROR_STATE); ++ read_data(kcs_bmc); ++ write_data(kcs_bmc, KCS_ZERO_DATA); ++ ++ kcs_bmc->phase = KCS_PHASE_ERROR; ++ kcs_bmc->data_in_avail = false; ++ kcs_bmc->data_in_idx = 0; ++} ++ ++static void kcs_bmc_handle_data(struct kcs_bmc *kcs_bmc) ++{ ++ u8 data; ++ ++ switch (kcs_bmc->phase) { ++ case KCS_PHASE_WRITE_START: ++ kcs_bmc->phase = KCS_PHASE_WRITE_DATA; ++ ++ case KCS_PHASE_WRITE_DATA: ++ if (kcs_bmc->data_in_idx < KCS_MSG_BUFSIZ) { ++ set_state(kcs_bmc, WRITE_STATE); ++ write_data(kcs_bmc, KCS_ZERO_DATA); ++ kcs_bmc->data_in[kcs_bmc->data_in_idx++] = ++ read_data(kcs_bmc); ++ } else { ++ kcs_force_abort(kcs_bmc); ++ kcs_bmc->error = KCS_LENGTH_ERROR; ++ } ++ break; ++ ++ case KCS_PHASE_WRITE_END_CMD: ++ if (kcs_bmc->data_in_idx < KCS_MSG_BUFSIZ) { ++ set_state(kcs_bmc, READ_STATE); ++ kcs_bmc->data_in[kcs_bmc->data_in_idx++] = ++ read_data(kcs_bmc); ++ kcs_bmc->phase = KCS_PHASE_WRITE_DONE; ++ kcs_bmc->data_in_avail = true; ++ wake_up_interruptible(&kcs_bmc->queue); ++ } else { ++ kcs_force_abort(kcs_bmc); ++ kcs_bmc->error = KCS_LENGTH_ERROR; ++ } ++ break; ++ ++ case KCS_PHASE_READ: ++ if (kcs_bmc->data_out_idx == kcs_bmc->data_out_len) ++ set_state(kcs_bmc, IDLE_STATE); ++ ++ data = read_data(kcs_bmc); ++ if (data != KCS_CMD_READ_BYTE) { ++ set_state(kcs_bmc, ERROR_STATE); ++ write_data(kcs_bmc, KCS_ZERO_DATA); ++ break; ++ } ++ ++ if (kcs_bmc->data_out_idx == kcs_bmc->data_out_len) { ++ write_data(kcs_bmc, KCS_ZERO_DATA); ++ kcs_bmc->phase = KCS_PHASE_IDLE; ++ break; ++ } ++ ++ write_data(kcs_bmc, ++ kcs_bmc->data_out[kcs_bmc->data_out_idx++]); ++ break; ++ ++ case KCS_PHASE_ABORT_ERROR1: ++ set_state(kcs_bmc, READ_STATE); ++ read_data(kcs_bmc); ++ write_data(kcs_bmc, kcs_bmc->error); ++ kcs_bmc->phase = KCS_PHASE_ABORT_ERROR2; ++ break; ++ ++ case KCS_PHASE_ABORT_ERROR2: ++ set_state(kcs_bmc, IDLE_STATE); ++ read_data(kcs_bmc); ++ write_data(kcs_bmc, KCS_ZERO_DATA); ++ kcs_bmc->phase = KCS_PHASE_IDLE; ++ break; ++ ++ default: ++ kcs_force_abort(kcs_bmc); ++ break; ++ } ++} ++ ++static void kcs_bmc_handle_cmd(struct kcs_bmc *kcs_bmc) ++{ ++ u8 cmd; ++ ++ set_state(kcs_bmc, WRITE_STATE); ++ write_data(kcs_bmc, KCS_ZERO_DATA); ++ ++ cmd = read_data(kcs_bmc); ++ switch (cmd) { ++ case KCS_CMD_WRITE_START: ++ kcs_bmc->phase = KCS_PHASE_WRITE_START; ++ kcs_bmc->error = KCS_NO_ERROR; ++ kcs_bmc->data_in_avail = false; ++ kcs_bmc->data_in_idx = 0; ++ break; ++ ++ case KCS_CMD_WRITE_END: ++ if (kcs_bmc->phase != KCS_PHASE_WRITE_DATA) { ++ kcs_force_abort(kcs_bmc); ++ break; ++ } ++ ++ kcs_bmc->phase = KCS_PHASE_WRITE_END_CMD; ++ break; ++ ++ case KCS_CMD_GET_STATUS_ABORT: ++ if (kcs_bmc->error == KCS_NO_ERROR) ++ kcs_bmc->error = KCS_ABORTED_BY_COMMAND; ++ ++ kcs_bmc->phase = KCS_PHASE_ABORT_ERROR1; ++ kcs_bmc->data_in_avail = false; ++ kcs_bmc->data_in_idx = 0; ++ break; ++ ++ default: ++ kcs_force_abort(kcs_bmc); ++ kcs_bmc->error = KCS_ILLEGAL_CONTROL_CODE; ++ break; ++ } ++} ++ ++int kcs_bmc_handle_event(struct kcs_bmc *kcs_bmc) ++{ ++ unsigned long flags; ++ int ret = 0; ++ u8 status; ++ ++ spin_lock_irqsave(&kcs_bmc->lock, flags); ++ ++ if (!kcs_bmc->running) { ++ kcs_force_abort(kcs_bmc); ++ ret = -ENODEV; ++ goto out_unlock; ++ } ++ ++ status = read_status(kcs_bmc) & (KCS_STATUS_IBF | KCS_STATUS_CMD_DAT); ++ ++ switch (status) { ++ case KCS_STATUS_IBF | KCS_STATUS_CMD_DAT: ++ kcs_bmc_handle_cmd(kcs_bmc); ++ break; ++ ++ case KCS_STATUS_IBF: ++ kcs_bmc_handle_data(kcs_bmc); ++ break; ++ ++ default: ++ ret = -ENODATA; ++ break; ++ } ++ ++out_unlock: ++ spin_unlock_irqrestore(&kcs_bmc->lock, flags); ++ ++ return ret; ++} ++EXPORT_SYMBOL(kcs_bmc_handle_event); ++ ++static inline struct kcs_bmc *file_to_kcs_bmc(struct file *filp) ++{ ++ return container_of(filp->private_data, struct kcs_bmc, miscdev); ++} ++ ++static int kcs_bmc_open(struct inode *inode, struct file *filp) ++{ ++ struct kcs_bmc *kcs_bmc = file_to_kcs_bmc(filp); ++ int ret = 0; ++ ++ spin_lock_irq(&kcs_bmc->lock); ++ if (!kcs_bmc->running) ++ kcs_bmc->running = 1; ++ else ++ ret = -EBUSY; ++ spin_unlock_irq(&kcs_bmc->lock); ++ ++ return ret; ++} ++ ++static unsigned int kcs_bmc_poll(struct file *filp, poll_table *wait) ++{ ++ struct kcs_bmc *kcs_bmc = file_to_kcs_bmc(filp); ++ unsigned int mask = 0; ++ ++ poll_wait(filp, &kcs_bmc->queue, wait); ++ ++ spin_lock_irq(&kcs_bmc->lock); ++ if (kcs_bmc->data_in_avail) ++ mask |= POLLIN; ++ spin_unlock_irq(&kcs_bmc->lock); ++ ++ return mask; ++} ++ ++static ssize_t kcs_bmc_read(struct file *filp, char *buf, ++ size_t count, loff_t *offset) ++{ ++ struct kcs_bmc *kcs_bmc = file_to_kcs_bmc(filp); ++ bool data_avail; ++ size_t data_len; ++ ssize_t ret; ++ ++ if (!(filp->f_flags & O_NONBLOCK)) ++ wait_event_interruptible(kcs_bmc->queue, ++ kcs_bmc->data_in_avail); ++ ++ mutex_lock(&kcs_bmc->mutex); ++ ++ spin_lock_irq(&kcs_bmc->lock); ++ data_avail = kcs_bmc->data_in_avail; ++ if (data_avail) { ++ data_len = kcs_bmc->data_in_idx; ++ memcpy(kcs_bmc->kbuffer, kcs_bmc->data_in, data_len); ++ } ++ spin_unlock_irq(&kcs_bmc->lock); ++ ++ if (!data_avail) { ++ ret = -EAGAIN; ++ goto out_unlock; ++ } ++ ++ if (count < data_len) { ++ pr_err("channel=%u with too large data : %zu\n", ++ kcs_bmc->channel, data_len); ++ ++ spin_lock_irq(&kcs_bmc->lock); ++ kcs_force_abort(kcs_bmc); ++ spin_unlock_irq(&kcs_bmc->lock); ++ ++ ret = -EOVERFLOW; ++ goto out_unlock; ++ } ++ ++ if (copy_to_user(buf, kcs_bmc->kbuffer, data_len)) { ++ ret = -EFAULT; ++ goto out_unlock; ++ } ++ ++ ret = data_len; ++ ++ spin_lock_irq(&kcs_bmc->lock); ++ if (kcs_bmc->phase == KCS_PHASE_WRITE_DONE) { ++ kcs_bmc->phase = KCS_PHASE_WAIT_READ; ++ kcs_bmc->data_in_avail = false; ++ kcs_bmc->data_in_idx = 0; ++ } else { ++ ret = -EAGAIN; ++ } ++ spin_unlock_irq(&kcs_bmc->lock); ++ ++out_unlock: ++ mutex_unlock(&kcs_bmc->mutex); ++ ++ return ret; ++} ++ ++static ssize_t kcs_bmc_write(struct file *filp, const char *buf, ++ size_t count, loff_t *offset) ++{ ++ struct kcs_bmc *kcs_bmc = file_to_kcs_bmc(filp); ++ ssize_t ret; ++ ++ /* a minimum response size '3' : netfn + cmd + ccode */ ++ if (count < 3 || count > KCS_MSG_BUFSIZ) ++ return -EINVAL; ++ ++ mutex_lock(&kcs_bmc->mutex); ++ ++ if (copy_from_user(kcs_bmc->kbuffer, buf, count)) { ++ ret = -EFAULT; ++ goto out_unlock; ++ } ++ ++ spin_lock_irq(&kcs_bmc->lock); ++ if (kcs_bmc->phase == KCS_PHASE_WAIT_READ) { ++ kcs_bmc->phase = KCS_PHASE_READ; ++ kcs_bmc->data_out_idx = 1; ++ kcs_bmc->data_out_len = count; ++ memcpy(kcs_bmc->data_out, kcs_bmc->kbuffer, count); ++ write_data(kcs_bmc, kcs_bmc->data_out[0]); ++ ret = count; ++ } else { ++ ret = -EINVAL; ++ } ++ spin_unlock_irq(&kcs_bmc->lock); ++ ++out_unlock: ++ mutex_unlock(&kcs_bmc->mutex); ++ ++ return ret; ++} ++ ++static long kcs_bmc_ioctl(struct file *filp, unsigned int cmd, ++ unsigned long arg) ++{ ++ struct kcs_bmc *kcs_bmc = file_to_kcs_bmc(filp); ++ long ret = 0; ++ ++ spin_lock_irq(&kcs_bmc->lock); ++ ++ switch (cmd) { ++ case IPMI_BMC_IOCTL_SET_SMS_ATN: ++ update_status_bits(kcs_bmc, KCS_STATUS_SMS_ATN, ++ KCS_STATUS_SMS_ATN); ++ break; ++ ++ case IPMI_BMC_IOCTL_CLEAR_SMS_ATN: ++ update_status_bits(kcs_bmc, KCS_STATUS_SMS_ATN, ++ 0); ++ break; ++ ++ case IPMI_BMC_IOCTL_FORCE_ABORT: ++ kcs_force_abort(kcs_bmc); ++ break; ++ ++ default: ++ ret = -EINVAL; ++ break; ++ } ++ ++ spin_unlock_irq(&kcs_bmc->lock); ++ ++ return ret; ++} ++ ++static int kcs_bmc_release(struct inode *inode, struct file *filp) ++{ ++ struct kcs_bmc *kcs_bmc = file_to_kcs_bmc(filp); ++ ++ spin_lock_irq(&kcs_bmc->lock); ++ kcs_bmc->running = 0; ++ kcs_force_abort(kcs_bmc); ++ spin_unlock_irq(&kcs_bmc->lock); ++ ++ return 0; ++} ++ ++static const struct file_operations kcs_bmc_fops = { ++ .owner = THIS_MODULE, ++ .open = kcs_bmc_open, ++ .read = kcs_bmc_read, ++ .write = kcs_bmc_write, ++ .release = kcs_bmc_release, ++ .poll = kcs_bmc_poll, ++ .unlocked_ioctl = kcs_bmc_ioctl, ++}; ++ ++struct kcs_bmc *kcs_bmc_alloc(struct device *dev, int sizeof_priv, u32 channel) ++{ ++ struct kcs_bmc *kcs_bmc; ++ ++ kcs_bmc = devm_kzalloc(dev, sizeof(*kcs_bmc) + sizeof_priv, GFP_KERNEL); ++ if (!kcs_bmc) ++ return NULL; ++ ++ dev_set_name(dev, "ipmi-kcs%u", channel); ++ ++ spin_lock_init(&kcs_bmc->lock); ++ kcs_bmc->channel = channel; ++ ++ mutex_init(&kcs_bmc->mutex); ++ init_waitqueue_head(&kcs_bmc->queue); ++ ++ kcs_bmc->data_in = devm_kmalloc(dev, KCS_MSG_BUFSIZ, GFP_KERNEL); ++ kcs_bmc->data_out = devm_kmalloc(dev, KCS_MSG_BUFSIZ, GFP_KERNEL); ++ kcs_bmc->kbuffer = devm_kmalloc(dev, KCS_MSG_BUFSIZ, GFP_KERNEL); ++ if (!kcs_bmc->data_in || !kcs_bmc->data_out || !kcs_bmc->kbuffer) ++ return NULL; ++ ++ kcs_bmc->miscdev.minor = MISC_DYNAMIC_MINOR; ++ kcs_bmc->miscdev.name = dev_name(dev); ++ kcs_bmc->miscdev.fops = &kcs_bmc_fops; ++ ++ return kcs_bmc; ++} ++EXPORT_SYMBOL(kcs_bmc_alloc); ++ ++MODULE_LICENSE("GPL v2"); ++MODULE_AUTHOR("Haiyue Wang "); ++MODULE_DESCRIPTION("KCS BMC to handle the IPMI request from system software"); +diff --git a/drivers/char/ipmi/kcs_bmc.h b/drivers/char/ipmi/kcs_bmc.h +new file mode 100644 +index 000000000000..c19501db0236 +--- /dev/null ++++ b/drivers/char/ipmi/kcs_bmc.h +@@ -0,0 +1,106 @@ ++// SPDX-License-Identifier: GPL-2.0 ++// Copyright (c) 2015-2018, Intel Corporation. ++ ++#ifndef __KCS_BMC_H__ ++#define __KCS_BMC_H__ ++ ++#include ++ ++/* Different phases of the KCS BMC module : ++ * KCS_PHASE_IDLE : ++ * BMC should not be expecting nor sending any data. ++ * KCS_PHASE_WRITE_START : ++ * BMC is receiving a WRITE_START command from system software. ++ * KCS_PHASE_WRITE_DATA : ++ * BMC is receiving a data byte from system software. ++ * KCS_PHASE_WRITE_END_CMD : ++ * BMC is waiting a last data byte from system software. ++ * KCS_PHASE_WRITE_DONE : ++ * BMC has received the whole request from system software. ++ * KCS_PHASE_WAIT_READ : ++ * BMC is waiting the response from the upper IPMI service. ++ * KCS_PHASE_READ : ++ * BMC is transferring the response to system software. ++ * KCS_PHASE_ABORT_ERROR1 : ++ * BMC is waiting error status request from system software. ++ * KCS_PHASE_ABORT_ERROR2 : ++ * BMC is waiting for idle status afer error from system software. ++ * KCS_PHASE_ERROR : ++ * BMC has detected a protocol violation at the interface level. ++ */ ++enum kcs_phases { ++ KCS_PHASE_IDLE, ++ ++ KCS_PHASE_WRITE_START, ++ KCS_PHASE_WRITE_DATA, ++ KCS_PHASE_WRITE_END_CMD, ++ KCS_PHASE_WRITE_DONE, ++ ++ KCS_PHASE_WAIT_READ, ++ KCS_PHASE_READ, ++ ++ KCS_PHASE_ABORT_ERROR1, ++ KCS_PHASE_ABORT_ERROR2, ++ KCS_PHASE_ERROR ++}; ++ ++/* IPMI 2.0 - Table 9-4, KCS Interface Status Codes */ ++enum kcs_errors { ++ KCS_NO_ERROR = 0x00, ++ KCS_ABORTED_BY_COMMAND = 0x01, ++ KCS_ILLEGAL_CONTROL_CODE = 0x02, ++ KCS_LENGTH_ERROR = 0x06, ++ KCS_UNSPECIFIED_ERROR = 0xFF ++}; ++ ++/* IPMI 2.0 - 9.5, KCS Interface Registers ++ * @idr : Input Data Register ++ * @odr : Output Data Register ++ * @str : Status Register ++ */ ++struct kcs_ioreg { ++ u32 idr; ++ u32 odr; ++ u32 str; ++}; ++ ++struct kcs_bmc { ++ spinlock_t lock; ++ ++ u32 channel; ++ int running; ++ ++ /* Setup by BMC KCS controller driver */ ++ struct kcs_ioreg ioreg; ++ u8 (*io_inputb)(struct kcs_bmc *kcs_bmc, u32 reg); ++ void (*io_outputb)(struct kcs_bmc *kcs_bmc, u32 reg, u8 b); ++ ++ enum kcs_phases phase; ++ enum kcs_errors error; ++ ++ wait_queue_head_t queue; ++ bool data_in_avail; ++ int data_in_idx; ++ u8 *data_in; ++ ++ int data_out_idx; ++ int data_out_len; ++ u8 *data_out; ++ ++ struct mutex mutex; ++ u8 *kbuffer; ++ ++ struct miscdevice miscdev; ++ ++ unsigned long priv[]; ++}; ++ ++static inline void *kcs_bmc_priv(struct kcs_bmc *kcs_bmc) ++{ ++ return kcs_bmc->priv; ++} ++ ++int kcs_bmc_handle_event(struct kcs_bmc *kcs_bmc); ++struct kcs_bmc *kcs_bmc_alloc(struct device *dev, int sizeof_priv, ++ u32 channel); ++#endif +diff --git a/include/uapi/linux/ipmi_bmc.h b/include/uapi/linux/ipmi_bmc.h +new file mode 100644 +index 000000000000..2f9f97e6123a +--- /dev/null ++++ b/include/uapi/linux/ipmi_bmc.h +@@ -0,0 +1,14 @@ ++// SPDX-License-Identifier: GPL-2.0 ++// Copyright (c) 2015-2018, Intel Corporation. ++ ++#ifndef _UAPI_LINUX_IPMI_BMC_H ++#define _UAPI_LINUX_IPMI_BMC_H ++ ++#include ++ ++#define __IPMI_BMC_IOCTL_MAGIC 0xB1 ++#define IPMI_BMC_IOCTL_SET_SMS_ATN _IO(__IPMI_BMC_IOCTL_MAGIC, 0x00) ++#define IPMI_BMC_IOCTL_CLEAR_SMS_ATN _IO(__IPMI_BMC_IOCTL_MAGIC, 0x01) ++#define IPMI_BMC_IOCTL_FORCE_ABORT _IO(__IPMI_BMC_IOCTL_MAGIC, 0x02) ++ ++#endif /* _UAPI_LINUX_KCS_BMC_H */ +-- +2.14.3 + + +From be2ed207e3745392478e85afa0bb02acdf44c966 Mon Sep 17 00:00:00 2001 +From: Haiyue Wang +Date: Fri, 2 Feb 2018 10:16:11 +0800 +Subject: [PATCH 2/9] ipmi: add an Aspeed KCS IPMI BMC driver + +The KCS (Keyboard Controller Style) interface is used to perform in-band +IPMI communication between a server host and its BMC (BaseBoard Management +Controllers). + +This driver exposes the KCS interface on ASpeed SOCs (AST2400 and AST2500) +as a character device. Such SOCs are commonly used as BMCs and this driver +implements the BMC side of the KCS interface. + +Signed-off-by: Haiyue Wang +Signed-off-by: Corey Minyard +--- + .../devicetree/bindings/ipmi/aspeed-kcs-bmc.txt | 25 ++ + drivers/char/ipmi/Kconfig | 12 + + drivers/char/ipmi/Makefile | 1 + + drivers/char/ipmi/kcs_bmc_aspeed.c | 319 +++++++++++++++++++++ + 4 files changed, 357 insertions(+) + create mode 100644 Documentation/devicetree/bindings/ipmi/aspeed-kcs-bmc.txt + create mode 100644 drivers/char/ipmi/kcs_bmc_aspeed.c + +diff --git a/Documentation/devicetree/bindings/ipmi/aspeed-kcs-bmc.txt b/Documentation/devicetree/bindings/ipmi/aspeed-kcs-bmc.txt +new file mode 100644 +index 000000000000..d98a9bf45d6c +--- /dev/null ++++ b/Documentation/devicetree/bindings/ipmi/aspeed-kcs-bmc.txt +@@ -0,0 +1,25 @@ ++* Aspeed KCS (Keyboard Controller Style) IPMI interface ++ ++The Aspeed SOCs (AST2400 and AST2500) are commonly used as BMCs ++(Baseboard Management Controllers) and the KCS interface can be ++used to perform in-band IPMI communication with their host. ++ ++Required properties: ++- compatible : should be one of ++ "aspeed,ast2400-kcs-bmc" ++ "aspeed,ast2500-kcs-bmc" ++- interrupts : interrupt generated by the controller ++- kcs_chan : The LPC channel number in the controller ++- kcs_addr : The host CPU IO map address ++ ++ ++Example: ++ ++ kcs3: kcs3@0 { ++ compatible = "aspeed,ast2500-kcs-bmc"; ++ reg = <0x0 0x80>; ++ interrupts = <8>; ++ kcs_chan = <3>; ++ kcs_addr = <0xCA2>; ++ status = "okay"; ++ }; +diff --git a/drivers/char/ipmi/Kconfig b/drivers/char/ipmi/Kconfig +index 7641b8a2f632..3bda116c8aa0 100644 +--- a/drivers/char/ipmi/Kconfig ++++ b/drivers/char/ipmi/Kconfig +@@ -99,6 +99,18 @@ endif # IPMI_HANDLER + config IPMI_KCS_BMC + tristate + ++config ASPEED_KCS_IPMI_BMC ++ depends on ARCH_ASPEED || COMPILE_TEST ++ select IPMI_KCS_BMC ++ select REGMAP_MMIO ++ tristate "Aspeed KCS IPMI BMC driver" ++ help ++ Provides a driver for the KCS (Keyboard Controller Style) IPMI ++ interface found on Aspeed SOCs (AST2400 and AST2500). ++ ++ The driver implements the BMC side of the KCS contorller, it ++ provides the access of KCS IO space for BMC side. ++ + config ASPEED_BT_IPMI_BMC + depends on ARCH_ASPEED || COMPILE_TEST + depends on REGMAP && REGMAP_MMIO && MFD_SYSCON +diff --git a/drivers/char/ipmi/Makefile b/drivers/char/ipmi/Makefile +index 2abccb30016a..21e9e872d973 100644 +--- a/drivers/char/ipmi/Makefile ++++ b/drivers/char/ipmi/Makefile +@@ -23,3 +23,4 @@ obj-$(CONFIG_IPMI_WATCHDOG) += ipmi_watchdog.o + obj-$(CONFIG_IPMI_POWEROFF) += ipmi_poweroff.o + obj-$(CONFIG_IPMI_KCS_BMC) += kcs_bmc.o + obj-$(CONFIG_ASPEED_BT_IPMI_BMC) += bt-bmc.o ++obj-$(CONFIG_ASPEED_KCS_IPMI_BMC) += kcs_bmc_aspeed.o +diff --git a/drivers/char/ipmi/kcs_bmc_aspeed.c b/drivers/char/ipmi/kcs_bmc_aspeed.c +new file mode 100644 +index 000000000000..0c4d1a36dae4 +--- /dev/null ++++ b/drivers/char/ipmi/kcs_bmc_aspeed.c +@@ -0,0 +1,319 @@ ++// SPDX-License-Identifier: GPL-2.0 ++// Copyright (c) 2015-2018, Intel Corporation. ++ ++#define pr_fmt(fmt) "aspeed-kcs-bmc: " fmt ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "kcs_bmc.h" ++ ++ ++#define DEVICE_NAME "ast-kcs-bmc" ++ ++#define KCS_CHANNEL_MAX 4 ++ ++/* mapped to lpc-bmc@0 IO space */ ++#define LPC_HICR0 0x000 ++#define LPC_HICR0_LPC3E BIT(7) ++#define LPC_HICR0_LPC2E BIT(6) ++#define LPC_HICR0_LPC1E BIT(5) ++#define LPC_HICR2 0x008 ++#define LPC_HICR2_IBFIF3 BIT(3) ++#define LPC_HICR2_IBFIF2 BIT(2) ++#define LPC_HICR2_IBFIF1 BIT(1) ++#define LPC_HICR4 0x010 ++#define LPC_HICR4_LADR12AS BIT(7) ++#define LPC_HICR4_KCSENBL BIT(2) ++#define LPC_LADR3H 0x014 ++#define LPC_LADR3L 0x018 ++#define LPC_LADR12H 0x01C ++#define LPC_LADR12L 0x020 ++#define LPC_IDR1 0x024 ++#define LPC_IDR2 0x028 ++#define LPC_IDR3 0x02C ++#define LPC_ODR1 0x030 ++#define LPC_ODR2 0x034 ++#define LPC_ODR3 0x038 ++#define LPC_STR1 0x03C ++#define LPC_STR2 0x040 ++#define LPC_STR3 0x044 ++ ++/* mapped to lpc-host@80 IO space */ ++#define LPC_HICRB 0x080 ++#define LPC_HICRB_IBFIF4 BIT(1) ++#define LPC_HICRB_LPC4E BIT(0) ++#define LPC_LADR4 0x090 ++#define LPC_IDR4 0x094 ++#define LPC_ODR4 0x098 ++#define LPC_STR4 0x09C ++ ++struct aspeed_kcs_bmc { ++ struct regmap *map; ++}; ++ ++ ++static u8 aspeed_kcs_inb(struct kcs_bmc *kcs_bmc, u32 reg) ++{ ++ struct aspeed_kcs_bmc *priv = kcs_bmc_priv(kcs_bmc); ++ u32 val = 0; ++ int rc; ++ ++ rc = regmap_read(priv->map, reg, &val); ++ WARN(rc != 0, "regmap_read() failed: %d\n", rc); ++ ++ return rc == 0 ? (u8) val : 0; ++} ++ ++static void aspeed_kcs_outb(struct kcs_bmc *kcs_bmc, u32 reg, u8 data) ++{ ++ struct aspeed_kcs_bmc *priv = kcs_bmc_priv(kcs_bmc); ++ int rc; ++ ++ rc = regmap_write(priv->map, reg, data); ++ WARN(rc != 0, "regmap_write() failed: %d\n", rc); ++} ++ ++ ++/* ++ * AST_usrGuide_KCS.pdf ++ * 2. Background: ++ * we note D for Data, and C for Cmd/Status, default rules are ++ * A. KCS1 / KCS2 ( D / C:X / X+4 ) ++ * D / C : CA0h / CA4h ++ * D / C : CA8h / CACh ++ * B. KCS3 ( D / C:XX2h / XX3h ) ++ * D / C : CA2h / CA3h ++ * D / C : CB2h / CB3h ++ * C. KCS4 ++ * D / C : CA4h / CA5h ++ */ ++static void aspeed_kcs_set_address(struct kcs_bmc *kcs_bmc, u16 addr) ++{ ++ struct aspeed_kcs_bmc *priv = kcs_bmc_priv(kcs_bmc); ++ ++ switch (kcs_bmc->channel) { ++ case 1: ++ regmap_update_bits(priv->map, LPC_HICR4, ++ LPC_HICR4_LADR12AS, 0); ++ regmap_write(priv->map, LPC_LADR12H, addr >> 8); ++ regmap_write(priv->map, LPC_LADR12L, addr & 0xFF); ++ break; ++ ++ case 2: ++ regmap_update_bits(priv->map, LPC_HICR4, ++ LPC_HICR4_LADR12AS, LPC_HICR4_LADR12AS); ++ regmap_write(priv->map, LPC_LADR12H, addr >> 8); ++ regmap_write(priv->map, LPC_LADR12L, addr & 0xFF); ++ break; ++ ++ case 3: ++ regmap_write(priv->map, LPC_LADR3H, addr >> 8); ++ regmap_write(priv->map, LPC_LADR3L, addr & 0xFF); ++ break; ++ ++ case 4: ++ regmap_write(priv->map, LPC_LADR4, ((addr + 1) << 16) | ++ addr); ++ break; ++ ++ default: ++ break; ++ } ++} ++ ++static void aspeed_kcs_enable_channel(struct kcs_bmc *kcs_bmc, bool enable) ++{ ++ struct aspeed_kcs_bmc *priv = kcs_bmc_priv(kcs_bmc); ++ ++ switch (kcs_bmc->channel) { ++ case 1: ++ if (enable) { ++ regmap_update_bits(priv->map, LPC_HICR2, ++ LPC_HICR2_IBFIF1, LPC_HICR2_IBFIF1); ++ regmap_update_bits(priv->map, LPC_HICR0, ++ LPC_HICR0_LPC1E, LPC_HICR0_LPC1E); ++ } else { ++ regmap_update_bits(priv->map, LPC_HICR0, ++ LPC_HICR0_LPC1E, 0); ++ regmap_update_bits(priv->map, LPC_HICR2, ++ LPC_HICR2_IBFIF1, 0); ++ } ++ break; ++ ++ case 2: ++ if (enable) { ++ regmap_update_bits(priv->map, LPC_HICR2, ++ LPC_HICR2_IBFIF2, LPC_HICR2_IBFIF2); ++ regmap_update_bits(priv->map, LPC_HICR0, ++ LPC_HICR0_LPC2E, LPC_HICR0_LPC2E); ++ } else { ++ regmap_update_bits(priv->map, LPC_HICR0, ++ LPC_HICR0_LPC2E, 0); ++ regmap_update_bits(priv->map, LPC_HICR2, ++ LPC_HICR2_IBFIF2, 0); ++ } ++ break; ++ ++ case 3: ++ if (enable) { ++ regmap_update_bits(priv->map, LPC_HICR2, ++ LPC_HICR2_IBFIF3, LPC_HICR2_IBFIF3); ++ regmap_update_bits(priv->map, LPC_HICR0, ++ LPC_HICR0_LPC3E, LPC_HICR0_LPC3E); ++ regmap_update_bits(priv->map, LPC_HICR4, ++ LPC_HICR4_KCSENBL, LPC_HICR4_KCSENBL); ++ } else { ++ regmap_update_bits(priv->map, LPC_HICR0, ++ LPC_HICR0_LPC3E, 0); ++ regmap_update_bits(priv->map, LPC_HICR4, ++ LPC_HICR4_KCSENBL, 0); ++ regmap_update_bits(priv->map, LPC_HICR2, ++ LPC_HICR2_IBFIF3, 0); ++ } ++ break; ++ ++ case 4: ++ if (enable) ++ regmap_update_bits(priv->map, LPC_HICRB, ++ LPC_HICRB_IBFIF4 | LPC_HICRB_LPC4E, ++ LPC_HICRB_IBFIF4 | LPC_HICRB_LPC4E); ++ else ++ regmap_update_bits(priv->map, LPC_HICRB, ++ LPC_HICRB_IBFIF4 | LPC_HICRB_LPC4E, ++ 0); ++ break; ++ ++ default: ++ break; ++ } ++} ++ ++static irqreturn_t aspeed_kcs_irq(int irq, void *arg) ++{ ++ struct kcs_bmc *kcs_bmc = arg; ++ ++ if (!kcs_bmc_handle_event(kcs_bmc)) ++ return IRQ_HANDLED; ++ ++ return IRQ_NONE; ++} ++ ++static int aspeed_kcs_config_irq(struct kcs_bmc *kcs_bmc, ++ struct platform_device *pdev) ++{ ++ struct device *dev = &pdev->dev; ++ int irq; ++ ++ irq = platform_get_irq(pdev, 0); ++ if (irq < 0) ++ return irq; ++ ++ return devm_request_irq(dev, irq, aspeed_kcs_irq, IRQF_SHARED, ++ dev_name(dev), kcs_bmc); ++} ++ ++static const struct kcs_ioreg ast_kcs_bmc_ioregs[KCS_CHANNEL_MAX] = { ++ { .idr = LPC_IDR1, .odr = LPC_ODR1, .str = LPC_STR1 }, ++ { .idr = LPC_IDR2, .odr = LPC_ODR2, .str = LPC_STR2 }, ++ { .idr = LPC_IDR3, .odr = LPC_ODR3, .str = LPC_STR3 }, ++ { .idr = LPC_IDR4, .odr = LPC_ODR4, .str = LPC_STR4 }, ++}; ++ ++static int aspeed_kcs_probe(struct platform_device *pdev) ++{ ++ struct device *dev = &pdev->dev; ++ struct aspeed_kcs_bmc *priv; ++ struct kcs_bmc *kcs_bmc; ++ u32 chan, addr; ++ int rc; ++ ++ rc = of_property_read_u32(dev->of_node, "kcs_chan", &chan); ++ if ((rc != 0) || (chan == 0 || chan > KCS_CHANNEL_MAX)) { ++ dev_err(dev, "no valid 'kcs_chan' configured\n"); ++ return -ENODEV; ++ } ++ ++ rc = of_property_read_u32(dev->of_node, "kcs_addr", &addr); ++ if (rc) { ++ dev_err(dev, "no valid 'kcs_addr' configured\n"); ++ return -ENODEV; ++ } ++ ++ kcs_bmc = kcs_bmc_alloc(dev, sizeof(*priv), chan); ++ if (!kcs_bmc) ++ return -ENOMEM; ++ ++ priv = kcs_bmc_priv(kcs_bmc); ++ priv->map = syscon_node_to_regmap(dev->parent->of_node); ++ if (IS_ERR(priv->map)) { ++ dev_err(dev, "Couldn't get regmap\n"); ++ return -ENODEV; ++ } ++ ++ kcs_bmc->ioreg = ast_kcs_bmc_ioregs[chan - 1]; ++ kcs_bmc->io_inputb = aspeed_kcs_inb; ++ kcs_bmc->io_outputb = aspeed_kcs_outb; ++ ++ dev_set_drvdata(dev, kcs_bmc); ++ ++ aspeed_kcs_set_address(kcs_bmc, addr); ++ aspeed_kcs_enable_channel(kcs_bmc, true); ++ rc = aspeed_kcs_config_irq(kcs_bmc, pdev); ++ if (rc) ++ return rc; ++ ++ rc = misc_register(&kcs_bmc->miscdev); ++ if (rc) { ++ dev_err(dev, "Unable to register device\n"); ++ return rc; ++ } ++ ++ pr_info("channel=%u addr=0x%x idr=0x%x odr=0x%x str=0x%x\n", ++ chan, addr, ++ kcs_bmc->ioreg.idr, kcs_bmc->ioreg.odr, kcs_bmc->ioreg.str); ++ ++ return 0; ++} ++ ++static int aspeed_kcs_remove(struct platform_device *pdev) ++{ ++ struct kcs_bmc *kcs_bmc = dev_get_drvdata(&pdev->dev); ++ ++ misc_deregister(&kcs_bmc->miscdev); ++ ++ return 0; ++} ++ ++static const struct of_device_id ast_kcs_bmc_match[] = { ++ { .compatible = "aspeed,ast2400-kcs-bmc" }, ++ { .compatible = "aspeed,ast2500-kcs-bmc" }, ++ { } ++}; ++ ++static struct platform_driver ast_kcs_bmc_driver = { ++ .driver = { ++ .name = DEVICE_NAME, ++ .of_match_table = ast_kcs_bmc_match, ++ }, ++ .probe = aspeed_kcs_probe, ++ .remove = aspeed_kcs_remove, ++}; ++ ++module_platform_driver(ast_kcs_bmc_driver); ++ ++MODULE_DEVICE_TABLE(of, ast_kcs_bmc_match); ++MODULE_LICENSE("GPL v2"); ++MODULE_AUTHOR("Haiyue Wang "); ++MODULE_DESCRIPTION("Aspeed device interface to the KCS BMC device"); +-- +2.14.3 + + +From aaf1bbe90a36a6d11dbedc4a99b24096963280c8 Mon Sep 17 00:00:00 2001 +From: "Gustavo A. R. Silva" +Date: Wed, 14 Feb 2018 11:30:29 -0600 +Subject: [PATCH 3/9] ipmi: kcs_bmc: mark expected switch fall-through in + kcs_bmc_handle_data + +In preparation to enabling -Wimplicit-fallthrough, mark switch cases +where we are expecting to fall through. + +Addresses-Coverity-ID: 1465255 ("Missing break in switch") +Signed-off-by: Gustavo A. R. Silva +Cc: Haiyue Wang +Signed-off-by: Corey Minyard +--- + drivers/char/ipmi/kcs_bmc.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/char/ipmi/kcs_bmc.c b/drivers/char/ipmi/kcs_bmc.c +index 3a3498afa427..6476bfb79f44 100644 +--- a/drivers/char/ipmi/kcs_bmc.c ++++ b/drivers/char/ipmi/kcs_bmc.c +@@ -95,6 +95,7 @@ static void kcs_bmc_handle_data(struct kcs_bmc *kcs_bmc) + switch (kcs_bmc->phase) { + case KCS_PHASE_WRITE_START: + kcs_bmc->phase = KCS_PHASE_WRITE_DATA; ++ /* fall through */ + + case KCS_PHASE_WRITE_DATA: + if (kcs_bmc->data_in_idx < KCS_MSG_BUFSIZ) { +-- +2.14.3 + + +From 364993a95888916b8906f655c8654aa60877a35b Mon Sep 17 00:00:00 2001 +From: Aishwarya Pant +Date: Sat, 24 Feb 2018 14:36:45 +0530 +Subject: [PATCH 4/9] char/ipmi: add documentation for sysfs interface + +This is an attempt to document the sysfs interface for the IPMI drivers. +Descriptions were collected from v2.0 of the IPMI specification and from +code comments. + +Signed-off-by: Aishwarya Pant +Signed-off-by: Corey Minyard +--- + .../ABI/testing/sysfs-devices-platform-ipmi | 238 +++++++++++++++++++++ + 1 file changed, 238 insertions(+) + create mode 100644 Documentation/ABI/testing/sysfs-devices-platform-ipmi + +diff --git a/Documentation/ABI/testing/sysfs-devices-platform-ipmi b/Documentation/ABI/testing/sysfs-devices-platform-ipmi +new file mode 100644 +index 000000000000..2a781e7513b7 +--- /dev/null ++++ b/Documentation/ABI/testing/sysfs-devices-platform-ipmi +@@ -0,0 +1,238 @@ ++What: /sys/devices/platform/ipmi_bmc.*/firmware_revision ++Date: Mar, 2006 ++KernelVersion: v2.6.17 ++Contact: openipmi-developer@lists.sourceforge.net ++Description: ++ (RO) The major and minor revision of the firmware. ++ ++ ++What: /sys/devices/platform/ipmi_bmc.*/aux_firmware_revision ++Date: Mar, 2006 ++KernelVersion: v2.6.17 ++Contact: openipmi-developer@lists.sourceforge.net ++Description: ++ (RO) Holds additional information about the firmware revision, ++ such as boot block or internal data structure version numbers. ++ The meanings of the numbers are specific to the vendor ++ identified by Manufacturer ID. ++ ++ ++What: /sys/devices/platform/ipmi_bmc.*/revision ++Date: Mar, 2006 ++KernelVersion: v2.6.17 ++Contact: openipmi-developer@lists.sourceforge.net ++Description: ++ (RO) Device revision. Useful for identifying if significant ++ hardware changes have been made to the implementation of the ++ management controller. ++ ++ ++What: /sys/devices/platform/ipmi_bmc.*/provides_device_sdrs ++Date: Mar, 2006 ++KernelVersion: v2.6.17 ++Contact: openipmi-developer@lists.sourceforge.net ++Description: ++ (RO) Indicates whether device provides device sensor data ++ records (1) or not (0). ++ ++ ++What: /sys/devices/platform/ipmi_bmc.*/device_id ++Date: Mar, 2006 ++KernelVersion: v2.6.17 ++Contact: openipmi-developer@lists.sourceforge.net ++Description: ++ (RO) Device id is specified by the manufacturer identified by ++ the Manufacturer ID field. This field allows controller specific ++ software to identify the unique application command, OEM ++ fields, and functionality that are provided by the controller ++ ++ ++What: /sys/devices/platform/ipmi_bmc.*/additional_device_support ++Date: Mar, 2006 ++KernelVersion: v2.6.17 ++Contact: openipmi-developer@lists.sourceforge.net ++Description: ++ (RO) Lists the IPMI ‘logical device’ commands and functions ++ that the controller supports that are in addition to the ++ mandatory IPM and Application commands. ++ ++ ++What: /sys/devices/platform/ipmi_bmc.*/ipmi_version ++Date: Mar, 2006 ++KernelVersion: v2.6.17 ++Contact: openipmi-developer@lists.sourceforge.net ++Description: ++ (RO) Displays the IPMI Command Specification Version. ++ ++ ++What: /sys/devices/platform/ipmi_bmc.*/manufacturer_id ++Date: Mar, 2006 ++KernelVersion: v2.6.17 ++Contact: openipmi-developer@lists.sourceforge.net ++Description: ++ (RO) Identifies the manufacturer responsible for the ++ specification of functionality of the vendor (OEM)-specific ++ commands, codes, and interfaces used in the controller. ++ ++ ++What: /sys/devices/platform/ipmi_bmc.*/product_id ++Date: Mar, 2006 ++KernelVersion: v2.6.17 ++Contact: openipmi-developer@lists.sourceforge.net ++Description: ++ (RO) Displays a number that identifies a particular system, ++ module, add-in card, or board set. The number is specified ++ according to the manufacturer given by Manufacturer ID. ++ ++For detailed definitions of the above attributes, refer to section 20.1 'Get ++Device ID Command' of the IPMI specification v2.0. ++ ++ ++What: /sys/devices/platform/ipmi_bmc.*/guid ++Date: Mar, 2006 ++KernelVersion: v2.6.17 ++Contact: openipmi-developer@lists.sourceforge.net ++Description: ++ (RO) A GUID (Globally Unique ID), also referred to as a UUID ++ (Universally Unique Identifier), for the management controller, ++ as described in section 20.8 'Get Device GUID Command' of the ++ IPMI specification v2.0. ++ ++ ++What: /sys/devices/platform/ipmi_si.*/type ++Date: Sep, 2017 ++KernelVersion: v4.15 ++Contact: openipmi-developer@lists.sourceforge.net ++Description: ++ (RO) The device interface for IPMI "kcs", "smic", "bt" or ++ "invalid" ++ ++What: /sys/devices/platform/ipmi_si.*/idles ++What: /sys/devices/platform/ipmi_si.*/watchdog_pretimeouts ++What: /sys/devices/platform/ipmi_si.*/complete_transactions ++What: /sys/devices/platform/ipmi_si.*/events ++What: /sys/devices/platform/ipmi_si.*/interrupts ++What: /sys/devices/platform/ipmi_si.*/hosed_count ++What: /sys/devices/platform/ipmi_si.*/long_timeouts ++What: /sys/devices/platform/ipmi_si.*/flag_fetches ++What: /sys/devices/platform/ipmi_si.*/attentions ++What: /sys/devices/platform/ipmi_si.*/incoming_messages ++What: /sys/devices/platform/ipmi_si.*/short_timeouts ++Date: Sep, 2017 ++KernelVersion: v4.15 ++Contact: openipmi-developer@lists.sourceforge.net ++Description: ++ ++ idles: (RO) Number of times the interface was ++ idle while being polled. ++ ++ watchdog_pretimeouts: (RO) Number of watchdog pretimeouts. ++ ++ complete_transactions: (RO) Number of completed messages. ++ ++ events: (RO) Number of IPMI events received from ++ the hardware. ++ ++ interrupts: (RO) Number of interrupts the driver ++ handled. ++ ++ hosed_count: (RO) Number of times the hardware didn't ++ follow the state machine. ++ ++ long_timeouts: (RO) Number of times the driver ++ requested a timer while nothing was in ++ progress. ++ ++ flag_fetches: (RO) Number of times the driver ++ requested flags from the hardware. ++ ++ attentions: (RO) Number of time the driver got an ++ ATTN from the hardware. ++ ++ incoming_messages: (RO) Number of asynchronous messages ++ received. ++ ++ short_timeouts: (RO) Number of times the driver ++ requested a timer while an operation was ++ in progress. ++ ++ ++What: /sys/devices/platform/ipmi_si.*/interrupts_enabled ++Date: Sep, 2017 ++KernelVersion: v4.15 ++Contact: openipmi-developer@lists.sourceforge.net ++Description: ++ (RO) Indicates whether interrupts are enabled or not. The driver ++ disables interrupts when it gets into a situation where it ++ cannot handle messages due to lack of memory. Once that ++ situation clears up, it will re-enable interrupts. ++ ++ ++What: /sys/devices/platform/ipmi_si.*/params ++Date: Sep, 2017 ++KernelVersion: v4.15 ++Contact: openipmi-developer@lists.sourceforge.net ++Description: ++ [to be documented] ++ ++ ++What: /sys/devices/platform/dmi-ipmi-ssif.*/type ++Date: Sep, 2017 ++KernelVersion: v4.15 ++Contact: openipmi-developer@lists.sourceforge.net ++Description: ++ (RO) Shows the IMPI device interface type - "ssif" here. ++ ++ ++What: /sys/devices/platform/dmi-ipmi-ssif.*/hosed ++What: /sys/devices/platform/dmi-ipmi-ssif.*/alerts ++What: /sys/devices/platform/dmi-ipmi-ssif.*/sent_messages ++What: /sys/devices/platform/dmi-ipmi-ssif.*/sent_messages_parts ++What: /sys/devices/platform/dmi-ipmi-ssif.*/received_messages ++What: /sys/devices/platform/dmi-ipmi-ssif.*/received_message_parts ++What: /sys/devices/platform/dmi-ipmi-ssif.*/events ++What: /sys/devices/platform/dmi-ipmi-ssif.*/watchdog_pretimeouts ++What: /sys/devices/platform/dmi-ipmi-ssif.*/flag_fetches ++What: /sys/devices/platform/dmi-ipmi-ssif.*/send_retries ++What: /sys/devices/platform/dmi-ipmi-ssif.*/receive_retries ++What: /sys/devices/platform/dmi-ipmi-ssif.*/send_errors ++What: /sys/devices/platform/dmi-ipmi-ssif.*/receive_errors ++Date: Sep, 2017 ++KernelVersion: v4.15 ++Contact: openipmi-developer@lists.sourceforge.net ++Description: ++ hosed: (RO) Number of times the hardware didn't ++ follow the state machine. ++ ++ alerts: (RO) Number of alerts received. ++ ++ sent_messages: (RO) Number of total messages sent. ++ ++ sent_message_parts: (RO) Number of message parts sent. ++ Messages may be broken into parts if ++ they are long. ++ ++ receieved_messages: (RO) Number of message responses ++ received. ++ ++ received_message_parts: (RO) Number of message fragments ++ received. ++ ++ events: (RO) Number of received events. ++ ++ watchdog_pretimeouts: (RO) Number of watchdog pretimeouts. ++ ++ flag_fetches: (RO) Number of times a flag fetch was ++ requested. ++ ++ send_retries: (RO) Number of time a message was ++ retried. ++ ++ receive_retries: (RO) Number of times the receive of a ++ message was retried. ++ ++ send_errors: (RO) Number of times the send of a ++ message failed. ++ ++ receive_errors: (RO) Number of errors in receiving ++ messages. +-- +2.14.3 + + +From 3b6d082f0dfc2b7b9def494d2ab67fd4d3862ea1 Mon Sep 17 00:00:00 2001 +From: Haiyue Wang +Date: Mon, 26 Feb 2018 23:48:14 +0800 +Subject: [PATCH 5/9] ipmi: kcs_bmc: coding-style fixes and use new poll type + +Many for coding-style fixes, and update the poll API with the new +type '__poll_t', this is new commit from linux-4.16-rc1. + +Signed-off-by: Haiyue Wang +Signed-off-by: Corey Minyard +--- + drivers/char/ipmi/kcs_bmc.c | 32 +++++++++++++++++--------------- + drivers/char/ipmi/kcs_bmc.h | 36 +++++++++++++++++++----------------- + drivers/char/ipmi/kcs_bmc_aspeed.c | 9 +++++---- + include/uapi/linux/ipmi_bmc.h | 8 +++++--- + 4 files changed, 46 insertions(+), 39 deletions(-) + +diff --git a/drivers/char/ipmi/kcs_bmc.c b/drivers/char/ipmi/kcs_bmc.c +index 6476bfb79f44..fbfc05e3f3d1 100644 +--- a/drivers/char/ipmi/kcs_bmc.c ++++ b/drivers/char/ipmi/kcs_bmc.c +@@ -1,5 +1,7 @@ + // SPDX-License-Identifier: GPL-2.0 +-// Copyright (c) 2015-2018, Intel Corporation. ++/* ++ * Copyright (c) 2015-2018, Intel Corporation. ++ */ + + #define pr_fmt(fmt) "kcs-bmc: " fmt + +@@ -242,14 +244,14 @@ int kcs_bmc_handle_event(struct kcs_bmc *kcs_bmc) + } + EXPORT_SYMBOL(kcs_bmc_handle_event); + +-static inline struct kcs_bmc *file_to_kcs_bmc(struct file *filp) ++static inline struct kcs_bmc *to_kcs_bmc(struct file *filp) + { + return container_of(filp->private_data, struct kcs_bmc, miscdev); + } + + static int kcs_bmc_open(struct inode *inode, struct file *filp) + { +- struct kcs_bmc *kcs_bmc = file_to_kcs_bmc(filp); ++ struct kcs_bmc *kcs_bmc = to_kcs_bmc(filp); + int ret = 0; + + spin_lock_irq(&kcs_bmc->lock); +@@ -262,25 +264,25 @@ static int kcs_bmc_open(struct inode *inode, struct file *filp) + return ret; + } + +-static unsigned int kcs_bmc_poll(struct file *filp, poll_table *wait) ++static __poll_t kcs_bmc_poll(struct file *filp, poll_table *wait) + { +- struct kcs_bmc *kcs_bmc = file_to_kcs_bmc(filp); +- unsigned int mask = 0; ++ struct kcs_bmc *kcs_bmc = to_kcs_bmc(filp); ++ __poll_t mask = 0; + + poll_wait(filp, &kcs_bmc->queue, wait); + + spin_lock_irq(&kcs_bmc->lock); + if (kcs_bmc->data_in_avail) +- mask |= POLLIN; ++ mask |= EPOLLIN; + spin_unlock_irq(&kcs_bmc->lock); + + return mask; + } + +-static ssize_t kcs_bmc_read(struct file *filp, char *buf, +- size_t count, loff_t *offset) ++static ssize_t kcs_bmc_read(struct file *filp, char __user *buf, ++ size_t count, loff_t *ppos) + { +- struct kcs_bmc *kcs_bmc = file_to_kcs_bmc(filp); ++ struct kcs_bmc *kcs_bmc = to_kcs_bmc(filp); + bool data_avail; + size_t data_len; + ssize_t ret; +@@ -339,10 +341,10 @@ static ssize_t kcs_bmc_read(struct file *filp, char *buf, + return ret; + } + +-static ssize_t kcs_bmc_write(struct file *filp, const char *buf, +- size_t count, loff_t *offset) ++static ssize_t kcs_bmc_write(struct file *filp, const char __user *buf, ++ size_t count, loff_t *ppos) + { +- struct kcs_bmc *kcs_bmc = file_to_kcs_bmc(filp); ++ struct kcs_bmc *kcs_bmc = to_kcs_bmc(filp); + ssize_t ret; + + /* a minimum response size '3' : netfn + cmd + ccode */ +@@ -378,7 +380,7 @@ static ssize_t kcs_bmc_write(struct file *filp, const char *buf, + static long kcs_bmc_ioctl(struct file *filp, unsigned int cmd, + unsigned long arg) + { +- struct kcs_bmc *kcs_bmc = file_to_kcs_bmc(filp); ++ struct kcs_bmc *kcs_bmc = to_kcs_bmc(filp); + long ret = 0; + + spin_lock_irq(&kcs_bmc->lock); +@@ -410,7 +412,7 @@ static long kcs_bmc_ioctl(struct file *filp, unsigned int cmd, + + static int kcs_bmc_release(struct inode *inode, struct file *filp) + { +- struct kcs_bmc *kcs_bmc = file_to_kcs_bmc(filp); ++ struct kcs_bmc *kcs_bmc = to_kcs_bmc(filp); + + spin_lock_irq(&kcs_bmc->lock); + kcs_bmc->running = 0; +diff --git a/drivers/char/ipmi/kcs_bmc.h b/drivers/char/ipmi/kcs_bmc.h +index c19501db0236..eb9ea4ce78b8 100644 +--- a/drivers/char/ipmi/kcs_bmc.h ++++ b/drivers/char/ipmi/kcs_bmc.h +@@ -1,31 +1,33 @@ +-// SPDX-License-Identifier: GPL-2.0 +-// Copyright (c) 2015-2018, Intel Corporation. ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * Copyright (c) 2015-2018, Intel Corporation. ++ */ + + #ifndef __KCS_BMC_H__ + #define __KCS_BMC_H__ + + #include + +-/* Different phases of the KCS BMC module : +- * KCS_PHASE_IDLE : ++/* Different phases of the KCS BMC module. ++ * KCS_PHASE_IDLE: + * BMC should not be expecting nor sending any data. +- * KCS_PHASE_WRITE_START : ++ * KCS_PHASE_WRITE_START: + * BMC is receiving a WRITE_START command from system software. +- * KCS_PHASE_WRITE_DATA : ++ * KCS_PHASE_WRITE_DATA: + * BMC is receiving a data byte from system software. +- * KCS_PHASE_WRITE_END_CMD : ++ * KCS_PHASE_WRITE_END_CMD: + * BMC is waiting a last data byte from system software. +- * KCS_PHASE_WRITE_DONE : ++ * KCS_PHASE_WRITE_DONE: + * BMC has received the whole request from system software. +- * KCS_PHASE_WAIT_READ : ++ * KCS_PHASE_WAIT_READ: + * BMC is waiting the response from the upper IPMI service. +- * KCS_PHASE_READ : ++ * KCS_PHASE_READ: + * BMC is transferring the response to system software. +- * KCS_PHASE_ABORT_ERROR1 : ++ * KCS_PHASE_ABORT_ERROR1: + * BMC is waiting error status request from system software. +- * KCS_PHASE_ABORT_ERROR2 : ++ * KCS_PHASE_ABORT_ERROR2: + * BMC is waiting for idle status afer error from system software. +- * KCS_PHASE_ERROR : ++ * KCS_PHASE_ERROR: + * BMC has detected a protocol violation at the interface level. + */ + enum kcs_phases { +@@ -54,9 +56,9 @@ enum kcs_errors { + }; + + /* IPMI 2.0 - 9.5, KCS Interface Registers +- * @idr : Input Data Register +- * @odr : Output Data Register +- * @str : Status Register ++ * @idr: Input Data Register ++ * @odr: Output Data Register ++ * @str: Status Register + */ + struct kcs_ioreg { + u32 idr; +@@ -103,4 +105,4 @@ static inline void *kcs_bmc_priv(struct kcs_bmc *kcs_bmc) + int kcs_bmc_handle_event(struct kcs_bmc *kcs_bmc); + struct kcs_bmc *kcs_bmc_alloc(struct device *dev, int sizeof_priv, + u32 channel); +-#endif ++#endif /* __KCS_BMC_H__ */ +diff --git a/drivers/char/ipmi/kcs_bmc_aspeed.c b/drivers/char/ipmi/kcs_bmc_aspeed.c +index 0c4d1a36dae4..3c955946e647 100644 +--- a/drivers/char/ipmi/kcs_bmc_aspeed.c ++++ b/drivers/char/ipmi/kcs_bmc_aspeed.c +@@ -1,5 +1,7 @@ + // SPDX-License-Identifier: GPL-2.0 +-// Copyright (c) 2015-2018, Intel Corporation. ++/* ++ * Copyright (c) 2015-2018, Intel Corporation. ++ */ + + #define pr_fmt(fmt) "aspeed-kcs-bmc: " fmt + +@@ -301,19 +303,18 @@ static const struct of_device_id ast_kcs_bmc_match[] = { + { .compatible = "aspeed,ast2500-kcs-bmc" }, + { } + }; ++MODULE_DEVICE_TABLE(of, ast_kcs_bmc_match); + + static struct platform_driver ast_kcs_bmc_driver = { + .driver = { + .name = DEVICE_NAME, + .of_match_table = ast_kcs_bmc_match, + }, +- .probe = aspeed_kcs_probe, ++ .probe = aspeed_kcs_probe, + .remove = aspeed_kcs_remove, + }; +- + module_platform_driver(ast_kcs_bmc_driver); + +-MODULE_DEVICE_TABLE(of, ast_kcs_bmc_match); + MODULE_LICENSE("GPL v2"); + MODULE_AUTHOR("Haiyue Wang "); + MODULE_DESCRIPTION("Aspeed device interface to the KCS BMC device"); +diff --git a/include/uapi/linux/ipmi_bmc.h b/include/uapi/linux/ipmi_bmc.h +index 2f9f97e6123a..1670f0944227 100644 +--- a/include/uapi/linux/ipmi_bmc.h ++++ b/include/uapi/linux/ipmi_bmc.h +@@ -1,5 +1,7 @@ +-// SPDX-License-Identifier: GPL-2.0 +-// Copyright (c) 2015-2018, Intel Corporation. ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * Copyright (c) 2015-2018, Intel Corporation. ++ */ + + #ifndef _UAPI_LINUX_IPMI_BMC_H + #define _UAPI_LINUX_IPMI_BMC_H +@@ -11,4 +13,4 @@ + #define IPMI_BMC_IOCTL_CLEAR_SMS_ATN _IO(__IPMI_BMC_IOCTL_MAGIC, 0x01) + #define IPMI_BMC_IOCTL_FORCE_ABORT _IO(__IPMI_BMC_IOCTL_MAGIC, 0x02) + +-#endif /* _UAPI_LINUX_KCS_BMC_H */ ++#endif /* _UAPI_LINUX_IPMI_BMC_H */ +-- +2.14.3 + + +From ad2575f8600d068edb10a9bef7f945482e3c5ca9 Mon Sep 17 00:00:00 2001 +From: Corey Minyard +Date: Mon, 26 Feb 2018 12:46:26 -0600 +Subject: [PATCH 6/9] ipmi:pci: Make the PCI defines consistent with normal + Linux ones + +Signed-off-by: Corey Minyard +--- + drivers/char/ipmi/ipmi_si_pci.c | 31 ++++++++++++++----------------- + 1 file changed, 14 insertions(+), 17 deletions(-) + +diff --git a/drivers/char/ipmi/ipmi_si_pci.c b/drivers/char/ipmi/ipmi_si_pci.c +index 27dd11c49d21..ad4e20b94c08 100644 +--- a/drivers/char/ipmi/ipmi_si_pci.c ++++ b/drivers/char/ipmi/ipmi_si_pci.c +@@ -17,16 +17,12 @@ module_param_named(trypci, si_trypci, bool, 0); + MODULE_PARM_DESC(trypci, "Setting this to zero will disable the" + " default scan of the interfaces identified via pci"); + +-#define PCI_ERMC_CLASSCODE 0x0C0700 +-#define PCI_ERMC_CLASSCODE_MASK 0xffffff00 +-#define PCI_ERMC_CLASSCODE_TYPE_MASK 0xff +-#define PCI_ERMC_CLASSCODE_TYPE_SMIC 0x00 +-#define PCI_ERMC_CLASSCODE_TYPE_KCS 0x01 +-#define PCI_ERMC_CLASSCODE_TYPE_BT 0x02 ++#define PCI_CLASS_SERIAL_IPMI 0x0c07 ++#define PCI_CLASS_SERIAL_IPMI_SMIC 0x0c0700 ++#define PCI_CLASS_SERIAL_IPMI_KCS 0x0c0701 ++#define PCI_CLASS_SERIAL_IPMI_BT 0x0c0702 + +-#define PCI_HP_VENDOR_ID 0x103C +-#define PCI_MMC_DEVICE_ID 0x121A +-#define PCI_MMC_ADDR_CW 0x10 ++#define PCI_DEVICE_ID_HP_MMC 0x121A + + static void ipmi_pci_cleanup(struct si_sm_io *io) + { +@@ -69,28 +65,27 @@ static int ipmi_pci_probe(struct pci_dev *pdev, + const struct pci_device_id *ent) + { + int rv; +- int class_type = pdev->class & PCI_ERMC_CLASSCODE_TYPE_MASK; + struct si_sm_io io; + + memset(&io, 0, sizeof(io)); + io.addr_source = SI_PCI; + dev_info(&pdev->dev, "probing via PCI"); + +- switch (class_type) { +- case PCI_ERMC_CLASSCODE_TYPE_SMIC: ++ switch (pdev->class) { ++ case PCI_CLASS_SERIAL_IPMI_SMIC: + io.si_type = SI_SMIC; + break; + +- case PCI_ERMC_CLASSCODE_TYPE_KCS: ++ case PCI_CLASS_SERIAL_IPMI_KCS: + io.si_type = SI_KCS; + break; + +- case PCI_ERMC_CLASSCODE_TYPE_BT: ++ case PCI_CLASS_SERIAL_IPMI_BT: + io.si_type = SI_BT; + break; + + default: +- dev_info(&pdev->dev, "Unknown IPMI type: %d\n", class_type); ++ dev_info(&pdev->dev, "Unknown IPMI class: %x\n", pdev->class); + return -ENOMEM; + } + +@@ -138,8 +133,10 @@ static void ipmi_pci_remove(struct pci_dev *pdev) + } + + static const struct pci_device_id ipmi_pci_devices[] = { +- { PCI_DEVICE(PCI_HP_VENDOR_ID, PCI_MMC_DEVICE_ID) }, +- { PCI_DEVICE_CLASS(PCI_ERMC_CLASSCODE, PCI_ERMC_CLASSCODE_MASK) }, ++ { PCI_VDEVICE(HP, PCI_DEVICE_ID_HP_MMC) }, ++ { PCI_DEVICE_CLASS(PCI_CLASS_SERIAL_IPMI_SMIC, ~0) }, ++ { PCI_DEVICE_CLASS(PCI_CLASS_SERIAL_IPMI_KCS, ~0) }, ++ { PCI_DEVICE_CLASS(PCI_CLASS_SERIAL_IPMI_BT, ~0) }, + { 0, } + }; + MODULE_DEVICE_TABLE(pci, ipmi_pci_devices); +-- +2.14.3 + + +From 243ac21035176ac9692c1308a9f3b8f6a4e5d733 Mon Sep 17 00:00:00 2001 +From: Corey Minyard +Date: Tue, 20 Feb 2018 07:30:22 -0600 +Subject: [PATCH 8/9] ipmi: Add or fix SPDX-License-Identifier in all files + +And get rid of the license text that is no longer necessary. + +Signed-off-by: Corey Minyard +Cc: Kees Cook +Cc: Alistair Popple +Cc: Jeremy Kerr +Cc: Joel Stanley +Cc: Rocky Craig +--- + drivers/char/ipmi/bt-bmc.c | 6 +----- + drivers/char/ipmi/ipmi_bt_sm.c | 22 ++-------------------- + drivers/char/ipmi/ipmi_devintf.c | 22 +--------------------- + drivers/char/ipmi/ipmi_dmi.c | 2 +- + drivers/char/ipmi/ipmi_dmi.h | 2 +- + drivers/char/ipmi/ipmi_kcs_sm.c | 22 +--------------------- + drivers/char/ipmi/ipmi_msghandler.c | 22 +--------------------- + drivers/char/ipmi/ipmi_powernv.c | 6 +----- + drivers/char/ipmi/ipmi_poweroff.c | 22 +--------------------- + drivers/char/ipmi/ipmi_si.h | 1 + + drivers/char/ipmi/ipmi_si_hardcode.c | 1 + + drivers/char/ipmi/ipmi_si_hotmod.c | 1 + + drivers/char/ipmi/ipmi_si_intf.c | 22 +--------------------- + drivers/char/ipmi/ipmi_si_mem_io.c | 1 + + drivers/char/ipmi/ipmi_si_parisc.c | 1 + + drivers/char/ipmi/ipmi_si_pci.c | 1 + + drivers/char/ipmi/ipmi_si_platform.c | 1 + + drivers/char/ipmi/ipmi_si_port_io.c | 1 + + drivers/char/ipmi/ipmi_si_sm.h | 22 +--------------------- + drivers/char/ipmi/ipmi_smic_sm.c | 24 ++---------------------- + drivers/char/ipmi/ipmi_ssif.c | 6 +----- + drivers/char/ipmi/ipmi_watchdog.c | 22 +--------------------- + include/linux/ipmi-fru.h | 3 +-- + include/linux/ipmi.h | 21 +-------------------- + include/linux/ipmi_smi.h | 21 +-------------------- + include/uapi/linux/ipmi.h | 20 -------------------- + include/uapi/linux/ipmi_msgdefs.h | 20 -------------------- + 27 files changed, 27 insertions(+), 288 deletions(-) + +diff --git a/drivers/char/ipmi/bt-bmc.c b/drivers/char/ipmi/bt-bmc.c +index c95b93b7598b..40b9927c072c 100644 +--- a/drivers/char/ipmi/bt-bmc.c ++++ b/drivers/char/ipmi/bt-bmc.c +@@ -1,10 +1,6 @@ ++// SPDX-License-Identifier: GPL-2.0+ + /* + * Copyright (c) 2015-2016, IBM Corporation. +- * +- * This program is free software; you can redistribute it and/or +- * modify it under the terms of the GNU General Public License +- * as published by the Free Software Foundation; either version +- * 2 of the License, or (at your option) any later version. + */ + + #include +diff --git a/drivers/char/ipmi/ipmi_bt_sm.c b/drivers/char/ipmi/ipmi_bt_sm.c +index feafdab734ae..fd4ea8d87d4b 100644 +--- a/drivers/char/ipmi/ipmi_bt_sm.c ++++ b/drivers/char/ipmi/ipmi_bt_sm.c +@@ -1,3 +1,4 @@ ++// SPDX-License-Identifier: GPL-2.0+ + /* + * ipmi_bt_sm.c + * +@@ -5,26 +6,7 @@ + * of the driver architecture at http://sourceforge.net/projects/openipmi + * + * Author: Rocky Craig +- * +- * This program is free software; you can redistribute it and/or modify it +- * under the terms of the GNU General Public License as published by the +- * Free Software Foundation; either version 2 of the License, or (at your +- * option) any later version. +- * +- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED +- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR +- * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE +- * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +- * +- * You should have received a copy of the GNU General Public License along +- * with this program; if not, write to the Free Software Foundation, Inc., +- * 675 Mass Ave, Cambridge, MA 02139, USA. */ ++ */ + + #include /* For printk. */ + #include +diff --git a/drivers/char/ipmi/ipmi_devintf.c b/drivers/char/ipmi/ipmi_devintf.c +index 5f1bc9174735..8ecfd47806fa 100644 +--- a/drivers/char/ipmi/ipmi_devintf.c ++++ b/drivers/char/ipmi/ipmi_devintf.c +@@ -1,3 +1,4 @@ ++// SPDX-License-Identifier: GPL-2.0+ + /* + * ipmi_devintf.c + * +@@ -8,27 +9,6 @@ + * source@mvista.com + * + * Copyright 2002 MontaVista Software Inc. +- * +- * This program is free software; you can redistribute it and/or modify it +- * under the terms of the GNU General Public License as published by the +- * Free Software Foundation; either version 2 of the License, or (at your +- * option) any later version. +- * +- * +- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED +- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR +- * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE +- * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +- * +- * You should have received a copy of the GNU General Public License along +- * with this program; if not, write to the Free Software Foundation, Inc., +- * 675 Mass Ave, Cambridge, MA 02139, USA. + */ + + #include +diff --git a/drivers/char/ipmi/ipmi_dmi.c b/drivers/char/ipmi/ipmi_dmi.c +index f1df63bc859a..e2c143861b1e 100644 +--- a/drivers/char/ipmi/ipmi_dmi.c ++++ b/drivers/char/ipmi/ipmi_dmi.c +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: GPL-2.0 ++// SPDX-License-Identifier: GPL-2.0+ + /* + * A hack to create a platform device from a DMI entry. This will + * allow autoloading of the IPMI drive based on SMBIOS entries. +diff --git a/drivers/char/ipmi/ipmi_dmi.h b/drivers/char/ipmi/ipmi_dmi.h +index 6c21018e3668..8d2b094db8e6 100644 +--- a/drivers/char/ipmi/ipmi_dmi.h ++++ b/drivers/char/ipmi/ipmi_dmi.h +@@ -1,4 +1,4 @@ +-/* SPDX-License-Identifier: GPL-2.0 */ ++/* SPDX-License-Identifier: GPL-2.0+ */ + /* + * DMI defines for use by IPMI + */ +diff --git a/drivers/char/ipmi/ipmi_kcs_sm.c b/drivers/char/ipmi/ipmi_kcs_sm.c +index 1da61af7f576..f4ea9f47230a 100644 +--- a/drivers/char/ipmi/ipmi_kcs_sm.c ++++ b/drivers/char/ipmi/ipmi_kcs_sm.c +@@ -1,3 +1,4 @@ ++// SPDX-License-Identifier: GPL-2.0+ + /* + * ipmi_kcs_sm.c + * +@@ -8,27 +9,6 @@ + * source@mvista.com + * + * Copyright 2002 MontaVista Software Inc. +- * +- * This program is free software; you can redistribute it and/or modify it +- * under the terms of the GNU General Public License as published by the +- * Free Software Foundation; either version 2 of the License, or (at your +- * option) any later version. +- * +- * +- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED +- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR +- * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE +- * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +- * +- * You should have received a copy of the GNU General Public License along +- * with this program; if not, write to the Free Software Foundation, Inc., +- * 675 Mass Ave, Cambridge, MA 02139, USA. + */ + + /* +diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c +index e0b0d7e2d976..361148938801 100644 +--- a/drivers/char/ipmi/ipmi_msghandler.c ++++ b/drivers/char/ipmi/ipmi_msghandler.c +@@ -1,3 +1,4 @@ ++// SPDX-License-Identifier: GPL-2.0+ + /* + * ipmi_msghandler.c + * +@@ -8,27 +9,6 @@ + * source@mvista.com + * + * Copyright 2002 MontaVista Software Inc. +- * +- * This program is free software; you can redistribute it and/or modify it +- * under the terms of the GNU General Public License as published by the +- * Free Software Foundation; either version 2 of the License, or (at your +- * option) any later version. +- * +- * +- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED +- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR +- * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE +- * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +- * +- * You should have received a copy of the GNU General Public License along +- * with this program; if not, write to the Free Software Foundation, Inc., +- * 675 Mass Ave, Cambridge, MA 02139, USA. + */ + + #include +diff --git a/drivers/char/ipmi/ipmi_powernv.c b/drivers/char/ipmi/ipmi_powernv.c +index bcf493d8e238..e96500372ce2 100644 +--- a/drivers/char/ipmi/ipmi_powernv.c ++++ b/drivers/char/ipmi/ipmi_powernv.c +@@ -1,12 +1,8 @@ ++// SPDX-License-Identifier: GPL-2.0+ + /* + * PowerNV OPAL IPMI driver + * + * Copyright 2014 IBM Corp. +- * +- * This program is free software; you can redistribute it and/or modify it +- * under the terms of the GNU General Public License as published by the Free +- * Software Foundation; either version 2 of the License, or (at your option) +- * any later version. + */ + + #define pr_fmt(fmt) "ipmi-powernv: " fmt +diff --git a/drivers/char/ipmi/ipmi_poweroff.c b/drivers/char/ipmi/ipmi_poweroff.c +index 38e6af1c8e38..07fa366bc8f0 100644 +--- a/drivers/char/ipmi/ipmi_poweroff.c ++++ b/drivers/char/ipmi/ipmi_poweroff.c +@@ -1,3 +1,4 @@ ++// SPDX-License-Identifier: GPL-2.0+ + /* + * ipmi_poweroff.c + * +@@ -9,27 +10,6 @@ + * source@mvista.com + * + * Copyright 2002,2004 MontaVista Software Inc. +- * +- * This program is free software; you can redistribute it and/or modify it +- * under the terms of the GNU General Public License as published by the +- * Free Software Foundation; either version 2 of the License, or (at your +- * option) any later version. +- * +- * +- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED +- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR +- * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE +- * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +- * +- * You should have received a copy of the GNU General Public License along +- * with this program; if not, write to the Free Software Foundation, Inc., +- * 675 Mass Ave, Cambridge, MA 02139, USA. + */ + #include + #include +diff --git a/drivers/char/ipmi/ipmi_si.h b/drivers/char/ipmi/ipmi_si.h +index 17ce5f7b89ab..52f6152d1fcb 100644 +--- a/drivers/char/ipmi/ipmi_si.h ++++ b/drivers/char/ipmi/ipmi_si.h +@@ -1,3 +1,4 @@ ++/* SPDX-License-Identifier: GPL-2.0+ */ + /* + * ipmi_si.h + * +diff --git a/drivers/char/ipmi/ipmi_si_hardcode.c b/drivers/char/ipmi/ipmi_si_hardcode.c +index fa9a4780de36..10219f24546b 100644 +--- a/drivers/char/ipmi/ipmi_si_hardcode.c ++++ b/drivers/char/ipmi/ipmi_si_hardcode.c +@@ -1,3 +1,4 @@ ++// SPDX-License-Identifier: GPL-2.0+ + + #include + #include "ipmi_si.h" +diff --git a/drivers/char/ipmi/ipmi_si_hotmod.c b/drivers/char/ipmi/ipmi_si_hotmod.c +index fc03b9be2f3d..a98ca42a50b1 100644 +--- a/drivers/char/ipmi/ipmi_si_hotmod.c ++++ b/drivers/char/ipmi/ipmi_si_hotmod.c +@@ -1,3 +1,4 @@ ++// SPDX-License-Identifier: GPL-2.0+ + /* + * ipmi_si_hotmod.c + * +diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c +index 6768cb2dd740..5141ccf0b958 100644 +--- a/drivers/char/ipmi/ipmi_si_intf.c ++++ b/drivers/char/ipmi/ipmi_si_intf.c +@@ -1,3 +1,4 @@ ++// SPDX-License-Identifier: GPL-2.0+ + /* + * ipmi_si.c + * +@@ -10,27 +11,6 @@ + * + * Copyright 2002 MontaVista Software Inc. + * Copyright 2006 IBM Corp., Christian Krafft +- * +- * This program is free software; you can redistribute it and/or modify it +- * under the terms of the GNU General Public License as published by the +- * Free Software Foundation; either version 2 of the License, or (at your +- * option) any later version. +- * +- * +- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED +- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR +- * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE +- * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +- * +- * You should have received a copy of the GNU General Public License along +- * with this program; if not, write to the Free Software Foundation, Inc., +- * 675 Mass Ave, Cambridge, MA 02139, USA. + */ + + /* +diff --git a/drivers/char/ipmi/ipmi_si_mem_io.c b/drivers/char/ipmi/ipmi_si_mem_io.c +index 8796396ecd0f..1b869d530884 100644 +--- a/drivers/char/ipmi/ipmi_si_mem_io.c ++++ b/drivers/char/ipmi/ipmi_si_mem_io.c +@@ -1,3 +1,4 @@ ++// SPDX-License-Identifier: GPL-2.0+ + + #include + #include "ipmi_si.h" +diff --git a/drivers/char/ipmi/ipmi_si_parisc.c b/drivers/char/ipmi/ipmi_si_parisc.c +index 6b10f0e18a95..f3c99820f564 100644 +--- a/drivers/char/ipmi/ipmi_si_parisc.c ++++ b/drivers/char/ipmi/ipmi_si_parisc.c +@@ -1,3 +1,4 @@ ++// SPDX-License-Identifier: GPL-2.0+ + + #include + #include /* for register_parisc_driver() stuff */ +diff --git a/drivers/char/ipmi/ipmi_si_pci.c b/drivers/char/ipmi/ipmi_si_pci.c +index ad4e20b94c08..b1c055540b26 100644 +--- a/drivers/char/ipmi/ipmi_si_pci.c ++++ b/drivers/char/ipmi/ipmi_si_pci.c +@@ -1,3 +1,4 @@ ++// SPDX-License-Identifier: GPL-2.0+ + /* + * ipmi_si_pci.c + * +diff --git a/drivers/char/ipmi/ipmi_si_platform.c b/drivers/char/ipmi/ipmi_si_platform.c +index f4214870d726..3d45bf1ee5bc 100644 +--- a/drivers/char/ipmi/ipmi_si_platform.c ++++ b/drivers/char/ipmi/ipmi_si_platform.c +@@ -1,3 +1,4 @@ ++// SPDX-License-Identifier: GPL-2.0+ + /* + * ipmi_si_platform.c + * +diff --git a/drivers/char/ipmi/ipmi_si_port_io.c b/drivers/char/ipmi/ipmi_si_port_io.c +index e5ce174fbeeb..ef6dffcea9fa 100644 +--- a/drivers/char/ipmi/ipmi_si_port_io.c ++++ b/drivers/char/ipmi/ipmi_si_port_io.c +@@ -1,3 +1,4 @@ ++// SPDX-License-Identifier: GPL-2.0+ + + #include + #include "ipmi_si.h" +diff --git a/drivers/char/ipmi/ipmi_si_sm.h b/drivers/char/ipmi/ipmi_si_sm.h +index aa8d88ab4433..aaddf047d923 100644 +--- a/drivers/char/ipmi/ipmi_si_sm.h ++++ b/drivers/char/ipmi/ipmi_si_sm.h +@@ -1,3 +1,4 @@ ++/* SPDX-License-Identifier: GPL-2.0+ */ + /* + * ipmi_si_sm.h + * +@@ -11,27 +12,6 @@ + * source@mvista.com + * + * Copyright 2002 MontaVista Software Inc. +- * +- * This program is free software; you can redistribute it and/or modify it +- * under the terms of the GNU General Public License as published by the +- * Free Software Foundation; either version 2 of the License, or (at your +- * option) any later version. +- * +- * +- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED +- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR +- * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE +- * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +- * +- * You should have received a copy of the GNU General Public License along +- * with this program; if not, write to the Free Software Foundation, Inc., +- * 675 Mass Ave, Cambridge, MA 02139, USA. + */ + + #include +diff --git a/drivers/char/ipmi/ipmi_smic_sm.c b/drivers/char/ipmi/ipmi_smic_sm.c +index 8f7c73ff58f2..466a5aac5298 100644 +--- a/drivers/char/ipmi/ipmi_smic_sm.c ++++ b/drivers/char/ipmi/ipmi_smic_sm.c +@@ -1,3 +1,4 @@ ++// SPDX-License-Identifier: GPL-2.0+ + /* + * ipmi_smic_sm.c + * +@@ -18,28 +19,7 @@ + * copyright notice: + * (c) Copyright 2001 Grant Grundler (c) Copyright + * 2001 Hewlett-Packard Company +- * +- * +- * This program is free software; you can redistribute it and/or modify it +- * under the terms of the GNU General Public License as published by the +- * Free Software Foundation; either version 2 of the License, or (at your +- * option) any later version. +- * +- * +- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED +- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR +- * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE +- * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +- * +- * You should have received a copy of the GNU General Public License along +- * with this program; if not, write to the Free Software Foundation, Inc., +- * 675 Mass Ave, Cambridge, MA 02139, USA. */ ++ */ + + #include /* For printk. */ + #include +diff --git a/drivers/char/ipmi/ipmi_ssif.c b/drivers/char/ipmi/ipmi_ssif.c +index f929e72bdac8..9d3b0fa27560 100644 +--- a/drivers/char/ipmi/ipmi_ssif.c ++++ b/drivers/char/ipmi/ipmi_ssif.c +@@ -1,3 +1,4 @@ ++// SPDX-License-Identifier: GPL-2.0+ + /* + * ipmi_ssif.c + * +@@ -13,11 +14,6 @@ + * + * Copyright 2003 Intel Corporation + * Copyright 2005 MontaVista Software +- * +- * This program is free software; you can redistribute it and/or modify it +- * under the terms of the GNU General Public License as published by the +- * Free Software Foundation; either version 2 of the License, or (at your +- * option) any later version. + */ + + /* +diff --git a/drivers/char/ipmi/ipmi_watchdog.c b/drivers/char/ipmi/ipmi_watchdog.c +index a58acdcf7414..22bc287eac2d 100644 +--- a/drivers/char/ipmi/ipmi_watchdog.c ++++ b/drivers/char/ipmi/ipmi_watchdog.c +@@ -1,3 +1,4 @@ ++// SPDX-License-Identifier: GPL-2.0+ + /* + * ipmi_watchdog.c + * +@@ -8,27 +9,6 @@ + * source@mvista.com + * + * Copyright 2002 MontaVista Software Inc. +- * +- * This program is free software; you can redistribute it and/or modify it +- * under the terms of the GNU General Public License as published by the +- * Free Software Foundation; either version 2 of the License, or (at your +- * option) any later version. +- * +- * +- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED +- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR +- * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE +- * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +- * +- * You should have received a copy of the GNU General Public License along +- * with this program; if not, write to the Free Software Foundation, Inc., +- * 675 Mass Ave, Cambridge, MA 02139, USA. + */ + + #include +diff --git a/include/linux/ipmi-fru.h b/include/linux/ipmi-fru.h +index 4d3a76380e32..05c9422624c6 100644 +--- a/include/linux/ipmi-fru.h ++++ b/include/linux/ipmi-fru.h +@@ -1,9 +1,8 @@ ++/* SPDX-License-Identifier: GPL-2.0+ */ + /* + * Copyright (C) 2012 CERN (www.cern.ch) + * Author: Alessandro Rubini + * +- * Released according to the GNU GPL, version 2 or any later version. +- * + * This work is part of the White Rabbit project, a research effort led + * by CERN, the European Institute for Nuclear Research. + */ +diff --git a/include/linux/ipmi.h b/include/linux/ipmi.h +index f4ffacf4fe9d..8b0626cec980 100644 +--- a/include/linux/ipmi.h ++++ b/include/linux/ipmi.h +@@ -1,3 +1,4 @@ ++/* SPDX-License-Identifier: GPL-2.0+ */ + /* + * ipmi.h + * +@@ -9,26 +10,6 @@ + * + * Copyright 2002 MontaVista Software Inc. + * +- * This program is free software; you can redistribute it and/or modify it +- * under the terms of the GNU General Public License as published by the +- * Free Software Foundation; either version 2 of the License, or (at your +- * option) any later version. +- * +- * +- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED +- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR +- * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE +- * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +- * +- * You should have received a copy of the GNU General Public License along +- * with this program; if not, write to the Free Software Foundation, Inc., +- * 675 Mass Ave, Cambridge, MA 02139, USA. + */ + #ifndef __LINUX_IPMI_H + #define __LINUX_IPMI_H +diff --git a/include/linux/ipmi_smi.h b/include/linux/ipmi_smi.h +index 5be51281e14d..af457b5a689e 100644 +--- a/include/linux/ipmi_smi.h ++++ b/include/linux/ipmi_smi.h +@@ -1,3 +1,4 @@ ++/* SPDX-License-Identifier: GPL-2.0+ */ + /* + * ipmi_smi.h + * +@@ -9,26 +10,6 @@ + * + * Copyright 2002 MontaVista Software Inc. + * +- * This program is free software; you can redistribute it and/or modify it +- * under the terms of the GNU General Public License as published by the +- * Free Software Foundation; either version 2 of the License, or (at your +- * option) any later version. +- * +- * +- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED +- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR +- * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE +- * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +- * +- * You should have received a copy of the GNU General Public License along +- * with this program; if not, write to the Free Software Foundation, Inc., +- * 675 Mass Ave, Cambridge, MA 02139, USA. + */ + + #ifndef __LINUX_IPMI_SMI_H +diff --git a/include/uapi/linux/ipmi.h b/include/uapi/linux/ipmi.h +index b076f7a47407..32d148309b16 100644 +--- a/include/uapi/linux/ipmi.h ++++ b/include/uapi/linux/ipmi.h +@@ -10,26 +10,6 @@ + * + * Copyright 2002 MontaVista Software Inc. + * +- * This program is free software; you can redistribute it and/or modify it +- * under the terms of the GNU General Public License as published by the +- * Free Software Foundation; either version 2 of the License, or (at your +- * option) any later version. +- * +- * +- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED +- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR +- * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE +- * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +- * +- * You should have received a copy of the GNU General Public License along +- * with this program; if not, write to the Free Software Foundation, Inc., +- * 675 Mass Ave, Cambridge, MA 02139, USA. + */ + + #ifndef _UAPI__LINUX_IPMI_H +diff --git a/include/uapi/linux/ipmi_msgdefs.h b/include/uapi/linux/ipmi_msgdefs.h +index 17f349459587..c2b23a9fdf3d 100644 +--- a/include/uapi/linux/ipmi_msgdefs.h ++++ b/include/uapi/linux/ipmi_msgdefs.h +@@ -10,26 +10,6 @@ + * + * Copyright 2002 MontaVista Software Inc. + * +- * This program is free software; you can redistribute it and/or modify it +- * under the terms of the GNU General Public License as published by the +- * Free Software Foundation; either version 2 of the License, or (at your +- * option) any later version. +- * +- * +- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED +- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR +- * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE +- * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +- * +- * You should have received a copy of the GNU General Public License along +- * with this program; if not, write to the Free Software Foundation, Inc., +- * 675 Mass Ave, Cambridge, MA 02139, USA. + */ + + #ifndef __LINUX_IPMI_MSGDEFS_H +-- +2.14.3 + + +From 426fa6179dae677134dfb37b21d057819418515b Mon Sep 17 00:00:00 2001 +From: Corey Minyard +Date: Wed, 28 Feb 2018 08:09:49 -0600 +Subject: [PATCH 9/9] ipmi: Fix some error cleanup issues + +device_remove_group() was called on any cleanup, even if the +device attrs had not been added yet. That can occur in certain +error scenarios, so add a flag to know if it has been added. + +Also make sure we remove the dev if we added it ourselves. + +Signed-off-by: Corey Minyard +Cc: stable@vger.kernel.org # 4.15 +--- + drivers/char/ipmi/ipmi_si_intf.c | 18 ++++++++++++++---- + 1 file changed, 14 insertions(+), 4 deletions(-) + +diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c +index 5141ccf0b958..2b9f434775d4 100644 +--- a/drivers/char/ipmi/ipmi_si_intf.c ++++ b/drivers/char/ipmi/ipmi_si_intf.c +@@ -232,6 +232,9 @@ struct smi_info { + /* Default driver model device. */ + struct platform_device *pdev; + ++ /* Have we added the device group to the device? */ ++ bool dev_group_added; ++ + /* Counters and things for the proc filesystem. */ + atomic_t stats[SI_NUM_STATS]; + +@@ -2007,8 +2010,8 @@ int ipmi_si_add_smi(struct si_sm_io *io) + if (initialized) { + rv = try_smi_init(new_smi); + if (rv) { +- mutex_unlock(&smi_infos_lock); + cleanup_one_si(new_smi); ++ mutex_unlock(&smi_infos_lock); + return rv; + } + } +@@ -2167,6 +2170,7 @@ static int try_smi_init(struct smi_info *new_smi) + rv); + goto out_err_stop_timer; + } ++ new_smi->dev_group_added = true; + + rv = ipmi_register_smi(&handlers, + new_smi, +@@ -2220,7 +2224,10 @@ static int try_smi_init(struct smi_info *new_smi) + return 0; + + out_err_remove_attrs: +- device_remove_group(new_smi->io.dev, &ipmi_si_dev_attr_group); ++ if (new_smi->dev_group_added) { ++ device_remove_group(new_smi->io.dev, &ipmi_si_dev_attr_group); ++ new_smi->dev_group_added = false; ++ } + dev_set_drvdata(new_smi->io.dev, NULL); + + out_err_stop_timer: +@@ -2268,6 +2275,7 @@ static int try_smi_init(struct smi_info *new_smi) + else + platform_device_put(new_smi->pdev); + new_smi->pdev = NULL; ++ new_smi->io.dev = NULL; + } + + kfree(init_name); +@@ -2364,8 +2372,10 @@ static void cleanup_one_si(struct smi_info *to_clean) + } + } + +- device_remove_group(to_clean->io.dev, &ipmi_si_dev_attr_group); +- dev_set_drvdata(to_clean->io.dev, NULL); ++ if (to_clean->dev_group_added) ++ device_remove_group(to_clean->io.dev, &ipmi_si_dev_attr_group); ++ if (to_clean->io.dev) ++ dev_set_drvdata(to_clean->io.dev, NULL); + + list_del(&to_clean->link); + +-- +2.14.3 + diff --git a/kernel.spec b/kernel.spec index 2569967..52edcc1 100644 --- a/kernel.spec +++ b/kernel.spec @@ -630,6 +630,10 @@ Patch503: v3-2-2-Input-synaptics---Lenovo-X1-Carbon-5-should-use-SMBUS-RMI.patch # rhbz 1558977 Patch504: sunrpc-remove-incorrect-HMAC-request-initialization.patch +# In v4.17 +# rhbz 1549316 +Patch505: ipmi-fixes.patch + # END OF PATCH DEFINITIONS %endif @@ -1882,6 +1886,9 @@ fi # # %changelog +* Mon Apr 09 2018 Jeremy Cline +- Include the KCS IPMI BMC driver that's in F27 + * Mon Apr 9 2018 Peter Robinson - More fixes for Raspberry Pi 3+ lan78xx ethernet interface - Fixes for Cavium ThunderX ZIP driver stability