summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThorsten Leemhuis <fedora@leemhuis.info>2018-04-12 12:58:29 +0200
committerThorsten Leemhuis <fedora@leemhuis.info>2018-04-12 12:58:29 +0200
commit81dccd5a6e8233ec7cd8f406f5ae6f205cb1a30d (patch)
treee4c20c4e3dd4daa476cdbdacd021187806074a9d
parente7dc2ec924aef9df70453f676835c42dc68bfc84 (diff)
parent326828aa4ac885ea1e440e2633f66c29582769ed (diff)
downloadkernel-81dccd5a6e8233ec7cd8f406f5ae6f205cb1a30d.tar.gz
kernel-81dccd5a6e8233ec7cd8f406f5ae6f205cb1a30d.tar.xz
kernel-81dccd5a6e8233ec7cd8f406f5ae6f205cb1a30d.zip
Merge remote-tracking branch 'origin/stabilization' into stabilization-user-thl-vanilla-fedora
-rw-r--r--arm-revert-mmc-omap_hsmmc-Use-dma_request_chan-for-reque.patch100
-rw-r--r--arm64-Revert-allwinner-a64-pine64-Use-dcdc1-regulato.patch41
-rw-r--r--arm64-thunderx-crypto-zip-fixes.patch403
-rw-r--r--bcm2837-lan78xx-fixes.patch355
-rw-r--r--ipmi-fixes.patch2460
-rw-r--r--kernel.spec52
6 files changed, 3250 insertions, 161 deletions
diff --git a/arm-revert-mmc-omap_hsmmc-Use-dma_request_chan-for-reque.patch b/arm-revert-mmc-omap_hsmmc-Use-dma_request_chan-for-reque.patch
deleted file mode 100644
index b55dec0cb..000000000
--- a/arm-revert-mmc-omap_hsmmc-Use-dma_request_chan-for-reque.patch
+++ /dev/null
@@ -1,100 +0,0 @@
-From bb3e08008c0e48fd4f51a0f0957eecae61a24d69 Mon Sep 17 00:00:00 2001
-From: Peter Robinson <pbrobinson@gmail.com>
-Date: Tue, 1 Nov 2016 09:35:30 +0000
-Subject: [PATCH] Revert "mmc: omap_hsmmc: Use dma_request_chan() for
- requesting DMA channel"
-
-This reverts commit 81eef6ca92014845d40e3f1310e42b7010303acc.
----
- drivers/mmc/host/omap_hsmmc.c | 50 ++++++++++++++++++++++++++++++++++---------
- 1 file changed, 40 insertions(+), 10 deletions(-)
-
-diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
-index 24ebc9a..3563321 100644
---- a/drivers/mmc/host/omap_hsmmc.c
-+++ b/drivers/mmc/host/omap_hsmmc.c
-@@ -32,6 +32,7 @@
- #include <linux/of_irq.h>
- #include <linux/of_gpio.h>
- #include <linux/of_device.h>
-+#include <linux/omap-dmaengine.h>
- #include <linux/mmc/host.h>
- #include <linux/mmc/core.h>
- #include <linux/mmc/mmc.h>
-@@ -1992,6 +1993,8 @@ static int omap_hsmmc_probe(struct platform_device *pdev)
- struct resource *res;
- int ret, irq;
- const struct of_device_id *match;
-+ dma_cap_mask_t mask;
-+ unsigned tx_req, rx_req;
- const struct omap_mmc_of_data *data;
- void __iomem *base;
-
-@@ -2121,17 +2124,44 @@ static int omap_hsmmc_probe(struct platform_device *pdev)
-
- omap_hsmmc_conf_bus_power(host);
-
-- host->rx_chan = dma_request_chan(&pdev->dev, "rx");
-- if (IS_ERR(host->rx_chan)) {
-- dev_err(mmc_dev(host->mmc), "RX DMA channel request failed\n");
-- ret = PTR_ERR(host->rx_chan);
-+ if (!pdev->dev.of_node) {
-+ res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "tx");
-+ if (!res) {
-+ dev_err(mmc_dev(host->mmc), "cannot get DMA TX channel\n");
-+ ret = -ENXIO;
-+ goto err_irq;
-+ }
-+ tx_req = res->start;
-+
-+ res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "rx");
-+ if (!res) {
-+ dev_err(mmc_dev(host->mmc), "cannot get DMA RX channel\n");
-+ ret = -ENXIO;
-+ goto err_irq;
-+ }
-+ rx_req = res->start;
-+ }
-+
-+ dma_cap_zero(mask);
-+ dma_cap_set(DMA_SLAVE, mask);
-+
-+ host->rx_chan =
-+ dma_request_slave_channel_compat(mask, omap_dma_filter_fn,
-+ &rx_req, &pdev->dev, "rx");
-+
-+ if (!host->rx_chan) {
-+ dev_err(mmc_dev(host->mmc), "unable to obtain RX DMA engine channel\n");
-+ ret = -ENXIO;
- goto err_irq;
- }
-
-- host->tx_chan = dma_request_chan(&pdev->dev, "tx");
-- if (IS_ERR(host->tx_chan)) {
-- dev_err(mmc_dev(host->mmc), "TX DMA channel request failed\n");
-- ret = PTR_ERR(host->tx_chan);
-+ host->tx_chan =
-+ dma_request_slave_channel_compat(mask, omap_dma_filter_fn,
-+ &tx_req, &pdev->dev, "tx");
-+
-+ if (!host->tx_chan) {
-+ dev_err(mmc_dev(host->mmc), "unable to obtain TX DMA engine channel\n");
-+ ret = -ENXIO;
- goto err_irq;
- }
-
-@@ -2189,9 +2219,9 @@ err_slot_name:
- mmc_remove_host(mmc);
- err_irq:
- device_init_wakeup(&pdev->dev, false);
-- if (!IS_ERR_OR_NULL(host->tx_chan))
-+ if (host->tx_chan)
- dma_release_channel(host->tx_chan);
-- if (!IS_ERR_OR_NULL(host->rx_chan))
-+ if (host->rx_chan)
- dma_release_channel(host->rx_chan);
- pm_runtime_dont_use_autosuspend(host->dev);
- pm_runtime_put_sync(host->dev);
---
-2.9.3
-
diff --git a/arm64-Revert-allwinner-a64-pine64-Use-dcdc1-regulato.patch b/arm64-Revert-allwinner-a64-pine64-Use-dcdc1-regulato.patch
deleted file mode 100644
index 33f9271b7..000000000
--- a/arm64-Revert-allwinner-a64-pine64-Use-dcdc1-regulato.patch
+++ /dev/null
@@ -1,41 +0,0 @@
-From 90e388ca5d8bbee022f9ed5fc24137b31579fa6e Mon Sep 17 00:00:00 2001
-From: Peter Robinson <pbrobinson@gmail.com>
-Date: Wed, 22 Nov 2017 15:52:36 +0000
-Subject: [PATCH] Revert "arm64: allwinner: a64: pine64: Use dcdc1 regulator
- for mmc0"
-
-This reverts commit 3f241bfa60bdc9c4fde63fa6664a8ce00fd668c6.
----
- arch/arm64/boot/dts/allwinner/sun50i-a64-pine64.dts | 9 ++++++++-
- 1 file changed, 8 insertions(+), 1 deletion(-)
-
-diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64.dts
-index d06e34b5d192..caf8b6fbe5e3 100644
---- a/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64.dts
-+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64.dts
-@@ -61,6 +61,13 @@
- chosen {
- stdout-path = "serial0:115200n8";
- };
-+
-+ reg_vcc3v3: vcc3v3 {
-+ compatible = "regulator-fixed";
-+ regulator-name = "vcc3v3";
-+ regulator-min-microvolt = <3300000>;
-+ regulator-max-microvolt = <3300000>;
-+ };
- };
-
- &ehci0 {
-@@ -84,7 +91,7 @@
- &mmc0 {
- pinctrl-names = "default";
- pinctrl-0 = <&mmc0_pins>;
-- vmmc-supply = <&reg_dcdc1>;
-+ vmmc-supply = <&reg_vcc3v3>;
- cd-gpios = <&pio 5 6 GPIO_ACTIVE_HIGH>;
- cd-inverted;
- disable-wp;
---
-2.14.3
-
diff --git a/arm64-thunderx-crypto-zip-fixes.patch b/arm64-thunderx-crypto-zip-fixes.patch
new file mode 100644
index 000000000..7f970ee30
--- /dev/null
+++ b/arm64-thunderx-crypto-zip-fixes.patch
@@ -0,0 +1,403 @@
+From patchwork Mon Apr 9 15:45:50 2018
+Content-Type: text/plain; charset="utf-8"
+MIME-Version: 1.0
+Content-Transfer-Encoding: 7bit
+Subject: [v2,1/5] crypto: thunderx_zip: Fix fallout from CONFIG_VMAP_STACK
+From: Jan Glauber <jglauber@cavium.com>
+X-Patchwork-Id: 10331719
+Message-Id: <20180409154554.7578-2-jglauber@cavium.com>
+To: Herbert Xu <herbert@gondor.apana.org.au>
+Cc: "David S . Miller" <davem@davemloft.net>,
+ linux-crypto@vger.kernel.org, linux-kernel@vger.kernel.org,
+ Mahipal Challa <Mahipal.Challa@cavium.com>,
+ Robert Richter <rrichter@cavium.com>, Jan Glauber <jglauber@cavium.com>,
+ stable <stable@vger.kernel.org>
+Date: Mon, 9 Apr 2018 17:45:50 +0200
+
+Enabling virtual mapped kernel stacks breaks the thunderx_zip
+driver. On compression or decompression the executing CPU hangs
+in an endless loop. The reason for this is the usage of __pa
+by the driver which does no longer work for an address that is
+not part of the 1:1 mapping.
+
+The zip driver allocates a result struct on the stack and needs
+to tell the hardware the physical address within this struct
+that is used to signal the completion of the request.
+
+As the hardware gets the wrong address after the broken __pa
+conversion it writes to an arbitrary address. The zip driver then
+waits forever for the completion byte to contain a non-zero value.
+
+Allocating the result struct from 1:1 mapped memory resolves this
+bug.
+
+Signed-off-by: Jan Glauber <jglauber@cavium.com>
+Reviewed-by: Robert Richter <rrichter@cavium.com>
+Cc: stable <stable@vger.kernel.org> # 4.14
+---
+ drivers/crypto/cavium/zip/zip_crypto.c | 22 ++++++++++++++--------
+ 1 file changed, 14 insertions(+), 8 deletions(-)
+
+diff --git a/drivers/crypto/cavium/zip/zip_crypto.c b/drivers/crypto/cavium/zip/zip_crypto.c
+index 8df4d26cf9d4..b92b6e7e100f 100644
+--- a/drivers/crypto/cavium/zip/zip_crypto.c
++++ b/drivers/crypto/cavium/zip/zip_crypto.c
+@@ -124,7 +124,7 @@ int zip_compress(const u8 *src, unsigned int slen,
+ struct zip_kernel_ctx *zip_ctx)
+ {
+ struct zip_operation *zip_ops = NULL;
+- struct zip_state zip_state;
++ struct zip_state *zip_state;
+ struct zip_device *zip = NULL;
+ int ret;
+
+@@ -135,20 +135,23 @@ int zip_compress(const u8 *src, unsigned int slen,
+ if (!zip)
+ return -ENODEV;
+
+- memset(&zip_state, 0, sizeof(struct zip_state));
++ zip_state = kzalloc(sizeof(*zip_state), GFP_ATOMIC);
++ if (!zip_state)
++ return -ENOMEM;
++
+ zip_ops = &zip_ctx->zip_comp;
+
+ zip_ops->input_len = slen;
+ zip_ops->output_len = *dlen;
+ memcpy(zip_ops->input, src, slen);
+
+- ret = zip_deflate(zip_ops, &zip_state, zip);
++ ret = zip_deflate(zip_ops, zip_state, zip);
+
+ if (!ret) {
+ *dlen = zip_ops->output_len;
+ memcpy(dst, zip_ops->output, *dlen);
+ }
+-
++ kfree(zip_state);
+ return ret;
+ }
+
+@@ -157,7 +160,7 @@ int zip_decompress(const u8 *src, unsigned int slen,
+ struct zip_kernel_ctx *zip_ctx)
+ {
+ struct zip_operation *zip_ops = NULL;
+- struct zip_state zip_state;
++ struct zip_state *zip_state;
+ struct zip_device *zip = NULL;
+ int ret;
+
+@@ -168,7 +171,10 @@ int zip_decompress(const u8 *src, unsigned int slen,
+ if (!zip)
+ return -ENODEV;
+
+- memset(&zip_state, 0, sizeof(struct zip_state));
++ zip_state = kzalloc(sizeof(*zip_state), GFP_ATOMIC);
++ if (!zip_state)
++ return -ENOMEM;
++
+ zip_ops = &zip_ctx->zip_decomp;
+ memcpy(zip_ops->input, src, slen);
+
+@@ -179,13 +185,13 @@ int zip_decompress(const u8 *src, unsigned int slen,
+ zip_ops->input_len = slen;
+ zip_ops->output_len = *dlen;
+
+- ret = zip_inflate(zip_ops, &zip_state, zip);
++ ret = zip_inflate(zip_ops, zip_state, zip);
+
+ if (!ret) {
+ *dlen = zip_ops->output_len;
+ memcpy(dst, zip_ops->output, *dlen);
+ }
+-
++ kfree(zip_state);
+ return ret;
+ }
+
+From patchwork Mon Apr 9 15:45:51 2018
+Content-Type: text/plain; charset="utf-8"
+MIME-Version: 1.0
+Content-Transfer-Encoding: 7bit
+Subject: [v2,2/5] crypto: thunderx_zip: Limit result reading attempts
+From: Jan Glauber <jglauber@cavium.com>
+X-Patchwork-Id: 10331705
+Message-Id: <20180409154554.7578-3-jglauber@cavium.com>
+To: Herbert Xu <herbert@gondor.apana.org.au>
+Cc: "David S . Miller" <davem@davemloft.net>,
+ linux-crypto@vger.kernel.org, linux-kernel@vger.kernel.org,
+ Mahipal Challa <Mahipal.Challa@cavium.com>,
+ Robert Richter <rrichter@cavium.com>, Jan Glauber <jglauber@cavium.com>,
+ stable <stable@vger.kernel.org>
+Date: Mon, 9 Apr 2018 17:45:51 +0200
+
+After issuing a request an endless loop was used to read the
+completion state from memory which is asynchronously updated
+by the ZIP coprocessor.
+
+Add an upper bound to the retry attempts to prevent a CPU getting stuck
+forever in case of an error. Additionally, add a read memory barrier
+and a small delay between the reading attempts.
+
+Signed-off-by: Jan Glauber <jglauber@cavium.com>
+Reviewed-by: Robert Richter <rrichter@cavium.com>
+Cc: stable <stable@vger.kernel.org> # 4.14
+---
+ drivers/crypto/cavium/zip/common.h | 21 +++++++++++++++++++++
+ drivers/crypto/cavium/zip/zip_deflate.c | 4 ++--
+ drivers/crypto/cavium/zip/zip_inflate.c | 4 ++--
+ 3 files changed, 25 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/crypto/cavium/zip/common.h b/drivers/crypto/cavium/zip/common.h
+index dc451e0a43c5..58fb3ed6e644 100644
+--- a/drivers/crypto/cavium/zip/common.h
++++ b/drivers/crypto/cavium/zip/common.h
+@@ -46,8 +46,10 @@
+ #ifndef __COMMON_H__
+ #define __COMMON_H__
+
++#include <linux/delay.h>
+ #include <linux/init.h>
+ #include <linux/interrupt.h>
++#include <linux/io.h>
+ #include <linux/kernel.h>
+ #include <linux/module.h>
+ #include <linux/pci.h>
+@@ -149,6 +151,25 @@ struct zip_operation {
+ u32 sizeofzops;
+ };
+
++static inline int zip_poll_result(union zip_zres_s *result)
++{
++ int retries = 1000;
++
++ while (!result->s.compcode) {
++ if (!--retries) {
++ pr_err("ZIP ERR: request timed out");
++ return -ETIMEDOUT;
++ }
++ udelay(10);
++ /*
++ * Force re-reading of compcode which is updated
++ * by the ZIP coprocessor.
++ */
++ rmb();
++ }
++ return 0;
++}
++
+ /* error messages */
+ #define zip_err(fmt, args...) pr_err("ZIP ERR:%s():%d: " \
+ fmt "\n", __func__, __LINE__, ## args)
+diff --git a/drivers/crypto/cavium/zip/zip_deflate.c b/drivers/crypto/cavium/zip/zip_deflate.c
+index 9a944b8c1e29..d7133f857d67 100644
+--- a/drivers/crypto/cavium/zip/zip_deflate.c
++++ b/drivers/crypto/cavium/zip/zip_deflate.c
+@@ -129,8 +129,8 @@ int zip_deflate(struct zip_operation *zip_ops, struct zip_state *s,
+ /* Stats update for compression requests submitted */
+ atomic64_inc(&zip_dev->stats.comp_req_submit);
+
+- while (!result_ptr->s.compcode)
+- continue;
++ /* Wait for completion or error */
++ zip_poll_result(result_ptr);
+
+ /* Stats update for compression requests completed */
+ atomic64_inc(&zip_dev->stats.comp_req_complete);
+diff --git a/drivers/crypto/cavium/zip/zip_inflate.c b/drivers/crypto/cavium/zip/zip_inflate.c
+index 50cbdd83dbf2..7e0d73e2f89e 100644
+--- a/drivers/crypto/cavium/zip/zip_inflate.c
++++ b/drivers/crypto/cavium/zip/zip_inflate.c
+@@ -143,8 +143,8 @@ int zip_inflate(struct zip_operation *zip_ops, struct zip_state *s,
+ /* Decompression requests submitted stats update */
+ atomic64_inc(&zip_dev->stats.decomp_req_submit);
+
+- while (!result_ptr->s.compcode)
+- continue;
++ /* Wait for completion or error */
++ zip_poll_result(result_ptr);
+
+ /* Decompression requests completed stats update */
+ atomic64_inc(&zip_dev->stats.decomp_req_complete);
+From patchwork Mon Apr 9 15:45:52 2018
+Content-Type: text/plain; charset="utf-8"
+MIME-Version: 1.0
+Content-Transfer-Encoding: 7bit
+Subject: [v2,3/5] crypto: thunderx_zip: Prevent division by zero
+From: Jan Glauber <jglauber@cavium.com>
+X-Patchwork-Id: 10331709
+Message-Id: <20180409154554.7578-4-jglauber@cavium.com>
+To: Herbert Xu <herbert@gondor.apana.org.au>
+Cc: "David S . Miller" <davem@davemloft.net>,
+ linux-crypto@vger.kernel.org, linux-kernel@vger.kernel.org,
+ Mahipal Challa <Mahipal.Challa@cavium.com>,
+ Robert Richter <rrichter@cavium.com>, Jan Glauber <jglauber@cavium.com>
+Date: Mon, 9 Apr 2018 17:45:52 +0200
+
+Avoid two potential divisions by zero when calculating average
+values for the zip statistics.
+
+Signed-off-by: Jan Glauber <jglauber@cavium.com>
+Reviewed-by: Robert Richter <rrichter@cavium.com>
+---
+ drivers/crypto/cavium/zip/zip_main.c | 9 +++++----
+ 1 file changed, 5 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/crypto/cavium/zip/zip_main.c b/drivers/crypto/cavium/zip/zip_main.c
+index 1cd8aa488185..79b449e0f955 100644
+--- a/drivers/crypto/cavium/zip/zip_main.c
++++ b/drivers/crypto/cavium/zip/zip_main.c
+@@ -482,10 +482,11 @@ static int zip_show_stats(struct seq_file *s, void *unused)
+ atomic64_add(val, &st->pending_req);
+ }
+
+- avg_chunk = (atomic64_read(&st->comp_in_bytes) /
+- atomic64_read(&st->comp_req_complete));
+- avg_cr = (atomic64_read(&st->comp_in_bytes) /
+- atomic64_read(&st->comp_out_bytes));
++ val = atomic64_read(&st->comp_req_complete);
++ avg_chunk = (val) ? atomic64_read(&st->comp_in_bytes) / val : 0;
++
++ val = atomic64_read(&st->comp_out_bytes);
++ avg_cr = (val) ? atomic64_read(&st->comp_in_bytes) / val : 0;
+ seq_printf(s, " ZIP Device %d Stats\n"
+ "-----------------------------------\n"
+ "Comp Req Submitted : \t%lld\n"
+From patchwork Mon Apr 9 15:45:53 2018
+Content-Type: text/plain; charset="utf-8"
+MIME-Version: 1.0
+Content-Transfer-Encoding: 7bit
+Subject: [v2,4/5] crypto: thunderx_zip: Fix statistics pending request value
+From: Jan Glauber <jglauber@cavium.com>
+X-Patchwork-Id: 10331711
+Message-Id: <20180409154554.7578-5-jglauber@cavium.com>
+To: Herbert Xu <herbert@gondor.apana.org.au>
+Cc: "David S . Miller" <davem@davemloft.net>,
+ linux-crypto@vger.kernel.org, linux-kernel@vger.kernel.org,
+ Mahipal Challa <Mahipal.Challa@cavium.com>,
+ Robert Richter <rrichter@cavium.com>, Jan Glauber <jglauber@cavium.com>
+Date: Mon, 9 Apr 2018 17:45:53 +0200
+
+The pending request counter was read from the wrong register. While
+at it, there is no need to use an atomic for it as it is only read
+localy in a loop.
+
+Signed-off-by: Jan Glauber <jglauber@cavium.com>
+Reviewed-by: Robert Richter <rrichter@cavium.com>
+---
+ drivers/crypto/cavium/zip/zip_main.c | 13 +++++--------
+ drivers/crypto/cavium/zip/zip_main.h | 1 -
+ 2 files changed, 5 insertions(+), 9 deletions(-)
+
+diff --git a/drivers/crypto/cavium/zip/zip_main.c b/drivers/crypto/cavium/zip/zip_main.c
+index 79b449e0f955..ae5b20c695ca 100644
+--- a/drivers/crypto/cavium/zip/zip_main.c
++++ b/drivers/crypto/cavium/zip/zip_main.c
+@@ -469,6 +469,8 @@ static int zip_show_stats(struct seq_file *s, void *unused)
+ struct zip_stats *st;
+
+ for (index = 0; index < MAX_ZIP_DEVICES; index++) {
++ u64 pending = 0;
++
+ if (zip_dev[index]) {
+ zip = zip_dev[index];
+ st = &zip->stats;
+@@ -476,10 +478,8 @@ static int zip_show_stats(struct seq_file *s, void *unused)
+ /* Get all the pending requests */
+ for (q = 0; q < ZIP_NUM_QUEUES; q++) {
+ val = zip_reg_read((zip->reg_base +
+- ZIP_DBG_COREX_STA(q)));
+- val = (val >> 32);
+- val = val & 0xffffff;
+- atomic64_add(val, &st->pending_req);
++ ZIP_DBG_QUEX_STA(q)));
++ pending += val >> 32 & 0xffffff;
+ }
+
+ val = atomic64_read(&st->comp_req_complete);
+@@ -514,10 +514,7 @@ static int zip_show_stats(struct seq_file *s, void *unused)
+ (u64)atomic64_read(&st->decomp_in_bytes),
+ (u64)atomic64_read(&st->decomp_out_bytes),
+ (u64)atomic64_read(&st->decomp_bad_reqs),
+- (u64)atomic64_read(&st->pending_req));
+-
+- /* Reset pending requests count */
+- atomic64_set(&st->pending_req, 0);
++ pending);
+ }
+ }
+ return 0;
+diff --git a/drivers/crypto/cavium/zip/zip_main.h b/drivers/crypto/cavium/zip/zip_main.h
+index 64e051f60784..e1e4fa92ce80 100644
+--- a/drivers/crypto/cavium/zip/zip_main.h
++++ b/drivers/crypto/cavium/zip/zip_main.h
+@@ -74,7 +74,6 @@ struct zip_stats {
+ atomic64_t comp_req_complete;
+ atomic64_t decomp_req_submit;
+ atomic64_t decomp_req_complete;
+- atomic64_t pending_req;
+ atomic64_t comp_in_bytes;
+ atomic64_t comp_out_bytes;
+ atomic64_t decomp_in_bytes;
+From patchwork Mon Apr 9 15:45:54 2018
+Content-Type: text/plain; charset="utf-8"
+MIME-Version: 1.0
+Content-Transfer-Encoding: 7bit
+Subject: [v2,5/5] crypto: thunderx_zip: Fix smp_processor_id() warnings
+From: Jan Glauber <jglauber@cavium.com>
+X-Patchwork-Id: 10331715
+Message-Id: <20180409154554.7578-6-jglauber@cavium.com>
+To: Herbert Xu <herbert@gondor.apana.org.au>
+Cc: "David S . Miller" <davem@davemloft.net>,
+ linux-crypto@vger.kernel.org, linux-kernel@vger.kernel.org,
+ Mahipal Challa <Mahipal.Challa@cavium.com>,
+ Robert Richter <rrichter@cavium.com>, Jan Glauber <jglauber@cavium.com>
+Date: Mon, 9 Apr 2018 17:45:54 +0200
+
+Switch to raw_smp_processor_id() to prevent a number of
+warnings from kernel debugging. We do not care about
+preemption here, as the CPU number is only used as a
+poor mans load balancing or device selection. If preemption
+happens during a compress/decompress operation a small performance
+hit will occur but everything will continue to work, so just
+ignore it.
+
+Signed-off-by: Jan Glauber <jglauber@cavium.com>
+Reviewed-by: Robert Richter <rrichter@cavium.com>
+---
+ drivers/crypto/cavium/zip/zip_device.c | 4 ++--
+ drivers/crypto/cavium/zip/zip_main.c | 2 +-
+ 2 files changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/crypto/cavium/zip/zip_device.c b/drivers/crypto/cavium/zip/zip_device.c
+index ccf21fb91513..f174ec29ed69 100644
+--- a/drivers/crypto/cavium/zip/zip_device.c
++++ b/drivers/crypto/cavium/zip/zip_device.c
+@@ -87,12 +87,12 @@ u32 zip_load_instr(union zip_inst_s *instr,
+ * Distribute the instructions between the enabled queues based on
+ * the CPU id.
+ */
+- if (smp_processor_id() % 2 == 0)
++ if (raw_smp_processor_id() % 2 == 0)
+ queue = 0;
+ else
+ queue = 1;
+
+- zip_dbg("CPU Core: %d Queue number:%d", smp_processor_id(), queue);
++ zip_dbg("CPU Core: %d Queue number:%d", raw_smp_processor_id(), queue);
+
+ /* Take cmd buffer lock */
+ spin_lock(&zip_dev->iq[queue].lock);
+diff --git a/drivers/crypto/cavium/zip/zip_main.c b/drivers/crypto/cavium/zip/zip_main.c
+index ae5b20c695ca..be055b9547f6 100644
+--- a/drivers/crypto/cavium/zip/zip_main.c
++++ b/drivers/crypto/cavium/zip/zip_main.c
+@@ -113,7 +113,7 @@ struct zip_device *zip_get_device(int node)
+ */
+ int zip_get_node_id(void)
+ {
+- return cpu_to_node(smp_processor_id());
++ return cpu_to_node(raw_smp_processor_id());
+ }
+
+ /* Initializes the ZIP h/w sub-system */
diff --git a/bcm2837-lan78xx-fixes.patch b/bcm2837-lan78xx-fixes.patch
index f877ac15b..1cb1dea08 100644
--- a/bcm2837-lan78xx-fixes.patch
+++ b/bcm2837-lan78xx-fixes.patch
@@ -106,3 +106,358 @@ index 60a604cc7647..a21039852f8d 100644
addr_lo = addr[0] | (addr[1] << 8) |
(addr[2] << 16) | (addr[3] << 24);
addr_hi = addr[4] | (addr[5] << 8);
+From b5284e5d2d3562dac311443969a538b7fecb9848 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Wed, 28 Mar 2018 12:18:13 +0100
+Subject: [PATCH 1/5] lan78xx: Ignore DT MAC address if already valid
+
+The patch to set the lan78xx MAC address from DT does so regardless of
+whether or not the interface already has a valid address. As the
+initialisation function is called from the reset handler when the
+interface is brought up, it is impossible to change the MAC address
+in a way that persists across the interface being brought up.
+
+Fix the problem by moving the DT reading code after the check for a
+valid address.
+
+See: https://www.raspberrypi.org/forums/viewtopic.php?f=28&t=209309
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ drivers/net/usb/lan78xx.c | 17 +++++++++--------
+ 1 file changed, 9 insertions(+), 8 deletions(-)
+
+diff --git a/drivers/net/usb/lan78xx.c b/drivers/net/usb/lan78xx.c
+index b43b16b6e7ee..97ee7d3f749d 100644
+--- a/drivers/net/usb/lan78xx.c
++++ b/drivers/net/usb/lan78xx.c
+@@ -1641,14 +1641,6 @@ static void lan78xx_init_mac_address(struct lan78xx_net *dev)
+ u32 addr_lo, addr_hi;
+ int ret;
+ u8 addr[6];
+- const u8 *mac_addr;
+-
+- /* maybe the boot loader passed the MAC address in devicetree */
+- mac_addr = of_get_mac_address(dev->udev->dev.of_node);
+- if (mac_addr) {
+- ether_addr_copy(addr, mac_addr);
+- goto set_mac_addr;
+- }
+
+ ret = lan78xx_read_reg(dev, RX_ADDRL, &addr_lo);
+ ret = lan78xx_read_reg(dev, RX_ADDRH, &addr_hi);
+@@ -1661,6 +1653,15 @@ static void lan78xx_init_mac_address(struct lan78xx_net *dev)
+ addr[5] = (addr_hi >> 8) & 0xFF;
+
+ if (!is_valid_ether_addr(addr)) {
++ const u8 *mac_addr;
++
++ /* maybe the boot loader passed the MAC address in devicetree */
++ mac_addr = of_get_mac_address(dev->udev->dev.of_node);
++ if (mac_addr) {
++ ether_addr_copy(addr, mac_addr);
++ goto set_mac_addr;
++ }
++
+ /* reading mac address from EEPROM or OTP */
+ if ((lan78xx_read_eeprom(dev, EEPROM_MAC_OFFSET, ETH_ALEN,
+ addr) == 0) ||
+--
+2.17.0
+
+From 2c5d6ac9133cbfed05b97b34246121bddaf2aea4 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Wed, 4 Apr 2018 16:34:24 +0100
+Subject: [PATCH 2/5] net: lan78xx: Allow for VLAN headers in timeout.
+
+The frame abort timeout being set by lan78xx_set_rx_max_frame_length
+didn't account for any VLAN headers, resulting in very low
+throughput if used with tagged VLANs.
+Use VLAN_ETH_HLEN instead of ETH_HLEN to correct for this.
+
+See https://github.com/raspberrypi/linux/issues/2458
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/net/usb/lan78xx.c | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/net/usb/lan78xx.c b/drivers/net/usb/lan78xx.c
+index 97ee7d3f749d..5fd7b8569cba 100644
+--- a/drivers/net/usb/lan78xx.c
++++ b/drivers/net/usb/lan78xx.c
+@@ -2193,7 +2193,7 @@ static int lan78xx_change_mtu(struct net_device *netdev, int new_mtu)
+ if ((ll_mtu % dev->maxpacket) == 0)
+ return -EDOM;
+
+- ret = lan78xx_set_rx_max_frame_length(dev, new_mtu + ETH_HLEN);
++ ret = lan78xx_set_rx_max_frame_length(dev, new_mtu + VLAN_ETH_HLEN);
+
+ netdev->mtu = new_mtu;
+
+@@ -2488,7 +2488,8 @@ static int lan78xx_reset(struct lan78xx_net *dev)
+ buf |= FCT_TX_CTL_EN_;
+ ret = lan78xx_write_reg(dev, FCT_TX_CTL, buf);
+
+- ret = lan78xx_set_rx_max_frame_length(dev, dev->net->mtu + ETH_HLEN);
++ ret = lan78xx_set_rx_max_frame_length(dev,
++ dev->net->mtu + VLAN_ETH_HLEN);
+
+ ret = lan78xx_read_reg(dev, MAC_RX, &buf);
+ buf |= MAC_RX_RXEN_;
+--
+2.17.0
+
+From 833315351413d94d7db407847448dfeddfafe127 Mon Sep 17 00:00:00 2001
+From: Peter Robinson <pbrobinson@gmail.com>
+Date: Mon, 9 Apr 2018 17:51:35 +0100
+Subject: [PATCH 3/5] lan78xx: Connect phy early
+
+When using wicked with a lan78xx device attached to the system, we
+end up with ethtool commands issued on the device before an ifup
+got issued. That lead to the following crash:
+
+ Unable to handle kernel NULL pointer dereference at virtual address 0000039c
+ pgd = ffff800035b30000
+ [0000039c] *pgd=0000000000000000
+ Internal error: Oops: 96000004 [#1] SMP
+ Modules linked in: [...]
+ Supported: Yes
+ CPU: 3 PID: 638 Comm: wickedd Tainted: G E 4.12.14-0-default #1
+ Hardware name: raspberrypi rpi/rpi, BIOS 2018.03-rc2 02/21/2018
+ task: ffff800035e74180 task.stack: ffff800036718000
+ PC is at phy_ethtool_ksettings_get+0x20/0x98
+ LR is at lan78xx_get_link_ksettings+0x44/0x60 [lan78xx]
+ pc : [<ffff0000086f7f30>] lr : [<ffff000000dcca84>] pstate: 20000005
+ sp : ffff80003671bb20
+ x29: ffff80003671bb20 x28: ffff800035e74180
+ x27: ffff000008912000 x26: 000000000000001d
+ x25: 0000000000000124 x24: ffff000008f74d00
+ x23: 0000004000114809 x22: 0000000000000000
+ x21: ffff80003671bbd0 x20: 0000000000000000
+ x19: ffff80003671bbd0 x18: 000000000000040d
+ x17: 0000000000000001 x16: 0000000000000000
+ x15: 0000000000000000 x14: ffffffffffffffff
+ x13: 0000000000000000 x12: 0000000000000020
+ x11: 0101010101010101 x10: fefefefefefefeff
+ x9 : 7f7f7f7f7f7f7f7f x8 : fefefeff31677364
+ x7 : 0000000080808080 x6 : ffff80003671bc9c
+ x5 : ffff80003671b9f8 x4 : ffff80002c296190
+ x3 : 0000000000000000 x2 : 0000000000000000
+ x1 : ffff80003671bbd0 x0 : ffff80003671bc00
+ Process wickedd (pid: 638, stack limit = 0xffff800036718000)
+ Call trace:
+ Exception stack(0xffff80003671b9e0 to 0xffff80003671bb20)
+ b9e0: ffff80003671bc00 ffff80003671bbd0 0000000000000000 0000000000000000
+ ba00: ffff80002c296190 ffff80003671b9f8 ffff80003671bc9c 0000000080808080
+ ba20: fefefeff31677364 7f7f7f7f7f7f7f7f fefefefefefefeff 0101010101010101
+ ba40: 0000000000000020 0000000000000000 ffffffffffffffff 0000000000000000
+ ba60: 0000000000000000 0000000000000001 000000000000040d ffff80003671bbd0
+ ba80: 0000000000000000 ffff80003671bbd0 0000000000000000 0000004000114809
+ baa0: ffff000008f74d00 0000000000000124 000000000000001d ffff000008912000
+ bac0: ffff800035e74180 ffff80003671bb20 ffff000000dcca84 ffff80003671bb20
+ bae0: ffff0000086f7f30 0000000020000005 ffff80002c296000 ffff800035223900
+ bb00: 0000ffffffffffff 0000000000000000 ffff80003671bb20 ffff0000086f7f30
+ [<ffff0000086f7f30>] phy_ethtool_ksettings_get+0x20/0x98
+ [<ffff000000dcca84>] lan78xx_get_link_ksettings+0x44/0x60 [lan78xx]
+ [<ffff0000087cbc40>] ethtool_get_settings+0x68/0x210
+ [<ffff0000087cc0d4>] dev_ethtool+0x214/0x2180
+ [<ffff0000087e5008>] dev_ioctl+0x400/0x630
+ [<ffff00000879dd00>] sock_do_ioctl+0x70/0x88
+ [<ffff00000879f5f8>] sock_ioctl+0x208/0x368
+ [<ffff0000082cde10>] do_vfs_ioctl+0xb0/0x848
+ [<ffff0000082ce634>] SyS_ioctl+0x8c/0xa8
+ Exception stack(0xffff80003671bec0 to 0xffff80003671c000)
+ bec0: 0000000000000009 0000000000008946 0000fffff4e841d0 0000aa0032687465
+ bee0: 0000aaaafa2319d4 0000fffff4e841d4 0000000032687465 0000000032687465
+ bf00: 000000000000001d 7f7fff7f7f7f7f7f 72606b622e71ff4c 7f7f7f7f7f7f7f7f
+ bf20: 0101010101010101 0000000000000020 ffffffffffffffff 0000ffff7f510c68
+ bf40: 0000ffff7f6a9d18 0000ffff7f44ce30 000000000000040d 0000ffff7f6f98f0
+ bf60: 0000fffff4e842c0 0000000000000001 0000aaaafa2c2e00 0000ffff7f6ab000
+ bf80: 0000fffff4e842c0 0000ffff7f62a000 0000aaaafa2b9f20 0000aaaafa2c2e00
+ bfa0: 0000fffff4e84818 0000fffff4e841a0 0000ffff7f5ad0cc 0000fffff4e841a0
+ bfc0: 0000ffff7f44ce3c 0000000080000000 0000000000000009 000000000000001d
+ bfe0: 0000000000000000 0000000000000000 0000000000000000 0000000000000000
+
+The culprit is quite simple: The driver tries to access the phy left and right,
+but only actually has a working reference to it when the device is up.
+
+The fix thus is quite simple too: Get a reference to the phy on probe already
+and keep it even when the device is going down.
+
+With this patch applied, I can successfully run wicked on my system and bring
+the interface up and down as many times as I want, without getting NULL pointer
+dereferences in between.
+
+Signed-off-by: Alexander Graf <agraf@suse.de>
+---
+ drivers/net/usb/lan78xx.c | 34 ++++++++++++++++++----------------
+ 1 file changed, 18 insertions(+), 16 deletions(-)
+
+diff --git a/drivers/net/usb/lan78xx.c b/drivers/net/usb/lan78xx.c
+index 5fd7b8569cba..60fa1257721c 100644
+--- a/drivers/net/usb/lan78xx.c
++++ b/drivers/net/usb/lan78xx.c
+@@ -2094,10 +2094,6 @@ static int lan78xx_phy_init(struct lan78xx_net *dev)
+
+ dev->fc_autoneg = phydev->autoneg;
+
+- phy_start(phydev);
+-
+- netif_dbg(dev, ifup, dev->net, "phy initialised successfully");
+-
+ return 0;
+
+ error:
+@@ -2541,9 +2537,9 @@ static int lan78xx_open(struct net_device *net)
+ if (ret < 0)
+ goto done;
+
+- ret = lan78xx_phy_init(dev);
+- if (ret < 0)
+- goto done;
++ phy_start(net->phydev);
++
++ netif_dbg(dev, ifup, dev->net, "phy initialised successfully");
+
+ /* for Link Check */
+ if (dev->urb_intr) {
+@@ -2604,13 +2600,8 @@ static int lan78xx_stop(struct net_device *net)
+ if (timer_pending(&dev->stat_monitor))
+ del_timer_sync(&dev->stat_monitor);
+
+- phy_unregister_fixup_for_uid(PHY_KSZ9031RNX, 0xfffffff0);
+- phy_unregister_fixup_for_uid(PHY_LAN8835, 0xfffffff0);
+-
+- phy_stop(net->phydev);
+- phy_disconnect(net->phydev);
+-
+- net->phydev = NULL;
++ if (net->phydev)
++ phy_stop(net->phydev);
+
+ clear_bit(EVENT_DEV_OPEN, &dev->flags);
+ netif_stop_queue(net);
+@@ -3525,8 +3516,13 @@ static void lan78xx_disconnect(struct usb_interface *intf)
+ return;
+
+ udev = interface_to_usbdev(intf);
+-
+ net = dev->net;
++
++ phy_unregister_fixup_for_uid(PHY_KSZ9031RNX, 0xfffffff0);
++ phy_unregister_fixup_for_uid(PHY_LAN8835, 0xfffffff0);
++
++ phy_disconnect(net->phydev);
++
+ unregister_netdev(net);
+
+ cancel_delayed_work_sync(&dev->wq);
+@@ -3682,8 +3678,14 @@ static int lan78xx_probe(struct usb_interface *intf,
+ pm_runtime_set_autosuspend_delay(&udev->dev,
+ DEFAULT_AUTOSUSPEND_DELAY);
+
++ ret = lan78xx_phy_init(dev);
++ if (ret < 0)
++ goto out4;
++
+ return 0;
+
++out4:
++ unregister_netdev(netdev);
+ out3:
+ lan78xx_unbind(dev, intf);
+ out2:
+@@ -4031,7 +4033,7 @@ static int lan78xx_reset_resume(struct usb_interface *intf)
+
+ lan78xx_reset(dev);
+
+- lan78xx_phy_init(dev);
++ phy_start(dev->net->phydev);
+
+ return lan78xx_resume(intf);
+ }
+--
+2.17.0
+
+From 7b4cc4a0af02c0d798007a143efa7509711d52d7 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Wed, 4 Apr 2018 16:39:44 +0100
+Subject: [PATCH 4/5] lan78xx: Don't reset the interface on open
+
+With Alexander Graf's patch ("lan78xx: Connect phy early") applied,
+the call to lan78xx_reset within lan78xx_open prevents the phy
+interrupt from being generated (even though the link is up).
+
+Avoid this issue by removing the lan78xx_reset call.
+
+See: https://github.com/raspberrypi/linux/issues/2437
+ https://github.com/raspberrypi/linux/issues/2442
+ https://github.com/raspberrypi/linux/issues/2457
+---
+ drivers/net/usb/lan78xx.c | 4 ----
+ 1 file changed, 4 deletions(-)
+
+diff --git a/drivers/net/usb/lan78xx.c b/drivers/net/usb/lan78xx.c
+index 60fa1257721c..293ed1847932 100644
+--- a/drivers/net/usb/lan78xx.c
++++ b/drivers/net/usb/lan78xx.c
+@@ -2533,10 +2533,6 @@ static int lan78xx_open(struct net_device *net)
+ if (ret < 0)
+ goto out;
+
+- ret = lan78xx_reset(dev);
+- if (ret < 0)
+- goto done;
+-
+ phy_start(net->phydev);
+
+ netif_dbg(dev, ifup, dev->net, "phy initialised successfully");
+--
+2.17.0
+
+From ddbd11509f01c388b968872aeabf630654275b0a Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Mon, 9 Apr 2018 14:31:54 +0100
+Subject: [PATCH 5/5] net: lan78xx: Request s/w csum check on VLAN tagged
+ packets.
+
+There appears to be some issue in the LAN78xx where the checksum
+computed on a VLAN tagged packet is incorrect, or at least not
+in the form that the kernel is after. This is most easily shown
+by pinging a device via a VLAN tagged interface and it will dump
+out the error message and stack trace from netdev_rx_csum_fault.
+It has also been seen with standard TCP and UDP packets.
+
+Until this is fully understood, request that the network stack
+computes the checksum on packets signalled as having a VLAN tag
+applied.
+
+See https://github.com/raspberrypi/linux/issues/2458
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/net/usb/lan78xx.c | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/net/usb/lan78xx.c b/drivers/net/usb/lan78xx.c
+index 293ed1847932..44cabda17bb6 100644
+--- a/drivers/net/usb/lan78xx.c
++++ b/drivers/net/usb/lan78xx.c
+@@ -2937,8 +2937,12 @@ static void lan78xx_rx_csum_offload(struct lan78xx_net *dev,
+ struct sk_buff *skb,
+ u32 rx_cmd_a, u32 rx_cmd_b)
+ {
++ /* Checksum offload appears to be flawed if used with VLANs.
++ * Elect for sw checksum check instead.
++ */
+ if (!(dev->net->features & NETIF_F_RXCSUM) ||
+- unlikely(rx_cmd_a & RX_CMD_A_ICSM_)) {
++ unlikely(rx_cmd_a & RX_CMD_A_ICSM_) ||
++ (rx_cmd_a & RX_CMD_A_FVTG_)) {
+ skb->ip_summed = CHECKSUM_NONE;
+ } else {
+ skb->csum = ntohs((u16)(rx_cmd_b >> RX_CMD_B_CSUM_SHIFT_));
+--
+2.17.0
+
diff --git a/ipmi-fixes.patch b/ipmi-fixes.patch
new file mode 100644
index 000000000..b1838efa0
--- /dev/null
+++ b/ipmi-fixes.patch
@@ -0,0 +1,2460 @@
+From 20d60f61c58e8c937f3653819816dd203e6e3cb4 Mon Sep 17 00:00:00 2001
+From: Haiyue Wang <haiyue.wang@linux.intel.com>
+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 <haiyue.wang@linux.intel.com>
+[Removed the selectability of IPMI_KCS_BMC, as it doesn't do much
+ good to have it by itself.]
+Signed-off-by: Corey Minyard <cminyard@mvista.com>
+---
+ 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 <linux/errno.h>
++#include <linux/io.h>
++#include <linux/ipmi_bmc.h>
++#include <linux/module.h>
++#include <linux/platform_device.h>
++#include <linux/poll.h>
++#include <linux/sched.h>
++#include <linux/slab.h>
++
++#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 <haiyue.wang@linux.intel.com>");
++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 <linux/miscdevice.h>
++
++/* 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 <linux/ioctl.h>
++
++#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 <haiyue.wang@linux.intel.com>
+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 <haiyue.wang@linux.intel.com>
+Signed-off-by: Corey Minyard <cminyard@mvista.com>
+---
+ .../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 <linux/atomic.h>
++#include <linux/errno.h>
++#include <linux/interrupt.h>
++#include <linux/io.h>
++#include <linux/mfd/syscon.h>
++#include <linux/module.h>
++#include <linux/of.h>
++#include <linux/platform_device.h>
++#include <linux/poll.h>
++#include <linux/regmap.h>
++#include <linux/sched.h>
++#include <linux/slab.h>
++#include <linux/timer.h>
++
++#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 <haiyue.wang@linux.intel.com>");
++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" <garsilva@embeddedor.com>
+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 <garsilva@embeddedor.com>
+Cc: Haiyue Wang <haiyue.wang@linux.intel.com>
+Signed-off-by: Corey Minyard <cminyard@mvista.com>
+---
+ 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 <aishpant@gmail.com>
+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 <aishpant@gmail.com>
+Signed-off-by: Corey Minyard <cminyard@mvista.com>
+---
+ .../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 <haiyue.wang@linux.intel.com>
+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 <haiyue.wang@linux.intel.com>
+Signed-off-by: Corey Minyard <cminyard@mvista.com>
+---
+ 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 <linux/miscdevice.h>
+
+-/* 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 <haiyue.wang@linux.intel.com>");
+ 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 <cminyard@mvista.com>
+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 <cminyard@mvista.com>
+---
+ 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 <cminyard@mvista.com>
+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 <cminyard@mvista.com>
+Cc: Kees Cook <keescook@chromium.org>
+Cc: Alistair Popple <alistair@popple.id.au>
+Cc: Jeremy Kerr <jk@ozlabs.org>
+Cc: Joel Stanley <joel@jms.id.au>
+Cc: Rocky Craig <rocky.craig@hp.com>
+---
+ 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 <linux/atomic.h>
+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 <first.last@hp.com>
+- *
+- * 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 <linux/kernel.h> /* For printk. */
+ #include <linux/string.h>
+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 <linux/module.h>
+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 <linux/module.h>
+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 <linux/module.h>
+ #include <linux/moduleparam.h>
+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 <linux/moduleparam.h>
+ #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 <krafft@de.ibm.com>
+- *
+- * 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 <linux/io.h>
+ #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 <linux/module.h>
+ #include <asm/hardware.h> /* 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 <linux/io.h>
+ #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 <linux/ipmi.h>
+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 <linux/kernel.h> /* For printk. */
+ #include <linux/string.h>
+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 <linux/module.h>
+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 <rubini@gnudd.com>
+ *
+- * 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 <cminyard@mvista.com>
+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 <cminyard@mvista.com>
+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 9c6b6d4ab..acc61cb35 100644
--- a/kernel.spec
+++ b/kernel.spec
@@ -575,48 +575,46 @@ Patch300: arm64-Add-option-of-13-for-FORCE_MAX_ZONEORDER.patch
# http://www.spinics.net/lists/linux-tegra/msg26029.html
Patch301: usb-phy-tegra-Add-38.4MHz-clock-table-entry.patch
-# Fix OMAP4 (pandaboard)
-Patch302: arm-revert-mmc-omap_hsmmc-Use-dma_request_chan-for-reque.patch
-
# http://patchwork.ozlabs.org/patch/587554/
-Patch303: ARM-tegra-usb-no-reset.patch
-
-Patch304: arm64-Revert-allwinner-a64-pine64-Use-dcdc1-regulato.patch
+Patch302: ARM-tegra-usb-no-reset.patch
# https://patchwork.kernel.org/patch/9820417/
-Patch305: qcom-msm89xx-fixes.patch
+Patch303: qcom-msm89xx-fixes.patch
# https://patchwork.kernel.org/patch/10173115/
-Patch306: arm-dts-imx6qdl-udoo-Disable-usbh1-to-avoid-kernel-hang.patch
+Patch304: arm-dts-imx6qdl-udoo-Disable-usbh1-to-avoid-kernel-hang.patch
# http://patches.linaro.org/patch/131764/
-Patch307: wcn36xx-Fix-firmware-crash-due-to-corrupted-buffer-address.patch
+Patch305: wcn36xx-Fix-firmware-crash-due-to-corrupted-buffer-address.patch
# https://patchwork.kernel.org/patch/10245303/
-Patch308: wcn36xx-reduce-verbosity-of-drivers-messages.patch
+Patch306: wcn36xx-reduce-verbosity-of-drivers-messages.patch
# https://www.spinics.net/lists/arm-kernel/msg632925.html
-Patch309: arm-crypto-sunxi-ss-Add-MODULE_ALIAS-to-sun4i-ss.patch
+Patch307: arm-crypto-sunxi-ss-Add-MODULE_ALIAS-to-sun4i-ss.patch
# Fix USB on the RPi https://patchwork.kernel.org/patch/9879371/
-Patch310: bcm283x-dma-mapping-skip-USB-devices-when-configuring-DMA-during-probe.patch
+Patch308: bcm283x-dma-mapping-skip-USB-devices-when-configuring-DMA-during-probe.patch
# https://www.spinics.net/lists/arm-kernel/msg621982.html
-Patch311: bcm283x-Fix-probing-of-bcm2835-i2s.patch
+Patch309: bcm283x-Fix-probing-of-bcm2835-i2s.patch
# https://www.spinics.net/lists/arm-kernel/msg633942.html
-Patch312: mmc-sdhci-iproc-Disable-preset-values-for-BCM2835.patch
+Patch310: mmc-sdhci-iproc-Disable-preset-values-for-BCM2835.patch
# https://www.spinics.net/lists/arm-kernel/msg633945.html
-Patch313: bcm2835-hwrng-Handle-deferred-clock-properly.patch
+Patch311: bcm2835-hwrng-Handle-deferred-clock-properly.patch
-Patch314: bcm283x-clk-audio-fixes.patch
+Patch312: bcm283x-clk-audio-fixes.patch
+
+# https://marc.info/?l=linux-kernel&m=152328880417846&w=2
+Patch313: arm64-thunderx-crypto-zip-fixes.patch
# Enabling Patches for the RPi3+
-Patch330: bcm2837-rpi-initial-support-for-the-3.patch
-Patch331: bcm2837-gpio-expander.patch
-Patch332: bcm2837-enable-pmu.patch
-Patch333: bcm2837-lan78xx-fixes.patch
+Patch320: bcm2837-rpi-initial-support-for-the-3.patch
+Patch321: bcm2837-gpio-expander.patch
+Patch322: bcm2837-enable-pmu.patch
+Patch323: bcm2837-lan78xx-fixes.patch
# 400 - IBM (ppc/s390x) patches
@@ -634,6 +632,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
@@ -1886,6 +1888,16 @@ fi
#
#
%changelog
+* Mon Apr 09 2018 Jeremy Cline <jeremy@jcline.org>
+- Include the KCS IPMI BMC driver that's in F27
+
+* Mon Apr 9 2018 Peter Robinson <pbrobinson@fedoraproject.org>
+- More fixes for Raspberry Pi 3+ lan78xx ethernet interface
+- Fixes for Cavium ThunderX ZIP driver stability
+
+* Mon Apr 09 2018 Jeremy Cline <jeremy@jcline.org> - 4.16.1-200
+- Linux v4.16.1
+
* Thu Apr 05 2018 Jeremy Cline <jeremy@jcline.org> - 4.16.0-200
- Linux v4.16