]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
5.15-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 19 May 2022 12:59:46 +0000 (14:59 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 19 May 2022 12:59:46 +0000 (14:59 +0200)
added patches:
floppy-use-a-statically-allocated-error-counter.patch
i2c-piix4-add-efch-mmio-support-for-smbus-port-select.patch
i2c-piix4-add-efch-mmio-support-to-region-request-and-release.patch
i2c-piix4-add-efch-mmio-support-to-smbus-base-address-detect.patch
i2c-piix4-enable-efch-mmio-for-family-17h.patch
i2c-piix4-move-port-i-o-region-request-release-code-into-functions.patch
i2c-piix4-move-smbus-controller-base-address-detect-into-function.patch
i2c-piix4-move-smbus-port-selection-into-function.patch
i2c-piix4-replace-hardcoded-memory-map-size-with-a-define.patch
io_uring-arm-poll-for-non-nowait-files.patch
kernel-resource-introduce-request_mem_region_muxed.patch
mm-kfence-reset-pg_slab-and-memcg_data-before-freeing-__kfence_pool.patch
watchdog-sp5100_tco-add-initialization-using-efch-mmio.patch
watchdog-sp5100_tco-enable-family-17h-cpus.patch
watchdog-sp5100_tco-move-timer-initialization-into-function.patch
watchdog-sp5100_tco-refactor-mmio-base-address-initialization.patch

17 files changed:
queue-5.15/floppy-use-a-statically-allocated-error-counter.patch [new file with mode: 0644]
queue-5.15/i2c-piix4-add-efch-mmio-support-for-smbus-port-select.patch [new file with mode: 0644]
queue-5.15/i2c-piix4-add-efch-mmio-support-to-region-request-and-release.patch [new file with mode: 0644]
queue-5.15/i2c-piix4-add-efch-mmio-support-to-smbus-base-address-detect.patch [new file with mode: 0644]
queue-5.15/i2c-piix4-enable-efch-mmio-for-family-17h.patch [new file with mode: 0644]
queue-5.15/i2c-piix4-move-port-i-o-region-request-release-code-into-functions.patch [new file with mode: 0644]
queue-5.15/i2c-piix4-move-smbus-controller-base-address-detect-into-function.patch [new file with mode: 0644]
queue-5.15/i2c-piix4-move-smbus-port-selection-into-function.patch [new file with mode: 0644]
queue-5.15/i2c-piix4-replace-hardcoded-memory-map-size-with-a-define.patch [new file with mode: 0644]
queue-5.15/io_uring-arm-poll-for-non-nowait-files.patch [new file with mode: 0644]
queue-5.15/kernel-resource-introduce-request_mem_region_muxed.patch [new file with mode: 0644]
queue-5.15/mm-kfence-reset-pg_slab-and-memcg_data-before-freeing-__kfence_pool.patch [new file with mode: 0644]
queue-5.15/series
queue-5.15/watchdog-sp5100_tco-add-initialization-using-efch-mmio.patch [new file with mode: 0644]
queue-5.15/watchdog-sp5100_tco-enable-family-17h-cpus.patch [new file with mode: 0644]
queue-5.15/watchdog-sp5100_tco-move-timer-initialization-into-function.patch [new file with mode: 0644]
queue-5.15/watchdog-sp5100_tco-refactor-mmio-base-address-initialization.patch [new file with mode: 0644]

diff --git a/queue-5.15/floppy-use-a-statically-allocated-error-counter.patch b/queue-5.15/floppy-use-a-statically-allocated-error-counter.patch
new file mode 100644 (file)
index 0000000..2c29de4
--- /dev/null
@@ -0,0 +1,105 @@
+From f71f01394f742fc4558b3f9f4c7ef4c4cf3b07c8 Mon Sep 17 00:00:00 2001
+From: Willy Tarreau <w@1wt.eu>
+Date: Sun, 8 May 2022 11:37:07 +0200
+Subject: floppy: use a statically allocated error counter
+
+From: Willy Tarreau <w@1wt.eu>
+
+commit f71f01394f742fc4558b3f9f4c7ef4c4cf3b07c8 upstream.
+
+Interrupt handler bad_flp_intr() may cause a UAF on the recently freed
+request just to increment the error count.  There's no point keeping
+that one in the request anyway, and since the interrupt handler uses a
+static pointer to the error which cannot be kept in sync with the
+pending request, better make it use a static error counter that's reset
+for each new request.  This reset now happens when entering
+redo_fd_request() for a new request via set_next_request().
+
+One initial concern about a single error counter was that errors on one
+floppy drive could be reported on another one, but this problem is not
+real given that the driver uses a single drive at a time, as that
+PC-compatible controllers also have this limitation by using shared
+signals.  As such the error count is always for the "current" drive.
+
+Reported-by: Minh Yuan <yuanmingbuaa@gmail.com>
+Suggested-by: Linus Torvalds <torvalds@linuxfoundation.org>
+Tested-by: Denis Efremov <efremov@linux.com>
+Signed-off-by: Willy Tarreau <w@1wt.eu>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/block/floppy.c |   18 ++++++++----------
+ 1 file changed, 8 insertions(+), 10 deletions(-)
+
+--- a/drivers/block/floppy.c
++++ b/drivers/block/floppy.c
+@@ -509,8 +509,8 @@ static unsigned long fdc_busy;
+ static DECLARE_WAIT_QUEUE_HEAD(fdc_wait);
+ static DECLARE_WAIT_QUEUE_HEAD(command_done);
+-/* Errors during formatting are counted here. */
+-static int format_errors;
++/* errors encountered on the current (or last) request */
++static int floppy_errors;
+ /* Format request descriptor. */
+ static struct format_descr format_req;
+@@ -530,7 +530,6 @@ static struct format_descr format_req;
+ static char *floppy_track_buffer;
+ static int max_buffer_sectors;
+-static int *errors;
+ typedef void (*done_f)(int);
+ static const struct cont_t {
+       void (*interrupt)(void);
+@@ -1455,7 +1454,7 @@ static int interpret_errors(void)
+                       if (drive_params[current_drive].flags & FTD_MSG)
+                               DPRINT("Over/Underrun - retrying\n");
+                       bad = 0;
+-              } else if (*errors >= drive_params[current_drive].max_errors.reporting) {
++              } else if (floppy_errors >= drive_params[current_drive].max_errors.reporting) {
+                       print_errors();
+               }
+               if (reply_buffer[ST2] & ST2_WC || reply_buffer[ST2] & ST2_BC)
+@@ -2095,7 +2094,7 @@ static void bad_flp_intr(void)
+               if (!next_valid_format(current_drive))
+                       return;
+       }
+-      err_count = ++(*errors);
++      err_count = ++floppy_errors;
+       INFBOUND(write_errors[current_drive].badness, err_count);
+       if (err_count > drive_params[current_drive].max_errors.abort)
+               cont->done(0);
+@@ -2241,9 +2240,8 @@ static int do_format(int drive, struct f
+               return -EINVAL;
+       }
+       format_req = *tmp_format_req;
+-      format_errors = 0;
+       cont = &format_cont;
+-      errors = &format_errors;
++      floppy_errors = 0;
+       ret = wait_til_done(redo_format, true);
+       if (ret == -EINTR)
+               return -EINTR;
+@@ -2761,10 +2759,11 @@ static int set_next_request(void)
+       current_req = list_first_entry_or_null(&floppy_reqs, struct request,
+                                              queuelist);
+       if (current_req) {
+-              current_req->error_count = 0;
++              floppy_errors = 0;
+               list_del_init(&current_req->queuelist);
++              return 1;
+       }
+-      return current_req != NULL;
++      return 0;
+ }
+ /* Starts or continues processing request. Will automatically unlock the
+@@ -2823,7 +2822,6 @@ do_request:
+               _floppy = floppy_type + drive_params[current_drive].autodetect[drive_state[current_drive].probed_format];
+       } else
+               probing = 0;
+-      errors = &(current_req->error_count);
+       tmp = make_raw_rw_request();
+       if (tmp < 2) {
+               request_done(tmp);
diff --git a/queue-5.15/i2c-piix4-add-efch-mmio-support-for-smbus-port-select.patch b/queue-5.15/i2c-piix4-add-efch-mmio-support-for-smbus-port-select.patch
new file mode 100644 (file)
index 0000000..78d212e
--- /dev/null
@@ -0,0 +1,63 @@
+From 381a3083c6747ae5cdbef9b176d57d1b966db49f Mon Sep 17 00:00:00 2001
+From: Terry Bowman <terry.bowman@amd.com>
+Date: Wed, 9 Feb 2022 11:27:16 -0600
+Subject: i2c: piix4: Add EFCH MMIO support for SMBus port select
+
+From: Terry Bowman <terry.bowman@amd.com>
+
+commit 381a3083c6747ae5cdbef9b176d57d1b966db49f upstream.
+
+AMD processors include registers capable of selecting between 2 SMBus
+ports. Port selection is made during each user access by writing to
+FCH::PM::DECODEEN[smbus0sel]. Change the driver to use MMIO during
+SMBus port selection because cd6h/cd7h port I/O is not available on
+later AMD processors.
+
+Signed-off-by: Terry Bowman <terry.bowman@amd.com>
+Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com>
+Reviewed-by: Jean Delvare <jdelvare@suse.de>
+Signed-off-by: Wolfram Sang <wsa@kernel.org>
+Cc: Mario Limonciello <Mario.Limonciello@amd.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/i2c/busses/i2c-piix4.c |   15 ++++++++++++---
+ 1 file changed, 12 insertions(+), 3 deletions(-)
+
+--- a/drivers/i2c/busses/i2c-piix4.c
++++ b/drivers/i2c/busses/i2c-piix4.c
+@@ -753,10 +753,19 @@ static void piix4_imc_wakeup(void)
+       release_region(KERNCZ_IMC_IDX, 2);
+ }
+-static int piix4_sb800_port_sel(u8 port)
++static int piix4_sb800_port_sel(u8 port, struct sb800_mmio_cfg *mmio_cfg)
+ {
+       u8 smba_en_lo, val;
++      if (mmio_cfg->use_mmio) {
++              smba_en_lo = ioread8(mmio_cfg->addr + piix4_port_sel_sb800);
++              val = (smba_en_lo & ~piix4_port_mask_sb800) | port;
++              if (smba_en_lo != val)
++                      iowrite8(val, mmio_cfg->addr + piix4_port_sel_sb800);
++
++              return (smba_en_lo & piix4_port_mask_sb800);
++      }
++
+       outb_p(piix4_port_sel_sb800, SB800_PIIX4_SMB_IDX);
+       smba_en_lo = inb_p(SB800_PIIX4_SMB_IDX + 1);
+@@ -843,12 +852,12 @@ static s32 piix4_access_sb800(struct i2c
+               }
+       }
+-      prev_port = piix4_sb800_port_sel(adapdata->port);
++      prev_port = piix4_sb800_port_sel(adapdata->port, &adapdata->mmio_cfg);
+       retval = piix4_access(adap, addr, flags, read_write,
+                             command, size, data);
+-      piix4_sb800_port_sel(prev_port);
++      piix4_sb800_port_sel(prev_port, &adapdata->mmio_cfg);
+       /* Release the semaphore */
+       outb_p(smbslvcnt | 0x20, SMBSLVCNT);
diff --git a/queue-5.15/i2c-piix4-add-efch-mmio-support-to-region-request-and-release.patch b/queue-5.15/i2c-piix4-add-efch-mmio-support-to-region-request-and-release.patch
new file mode 100644 (file)
index 0000000..b1bb2f7
--- /dev/null
@@ -0,0 +1,182 @@
+From 7c148722d074c29fb998578eea5de3c14b9608c9 Mon Sep 17 00:00:00 2001
+From: Terry Bowman <terry.bowman@amd.com>
+Date: Wed, 9 Feb 2022 11:27:14 -0600
+Subject: i2c: piix4: Add EFCH MMIO support to region request and release
+
+From: Terry Bowman <terry.bowman@amd.com>
+
+commit 7c148722d074c29fb998578eea5de3c14b9608c9 upstream.
+
+EFCH cd6h/cd7h port I/O may no longer be available on later AMD
+processors and it is recommended to use MMIO instead. Update the
+request and release functions to support MMIO.
+
+MMIO request/release and mmapping require details during cleanup.
+Add a MMIO configuration structure containing resource and vaddress
+details for mapping the region, accessing the region, and releasing
+the region.
+
+Signed-off-by: Terry Bowman <terry.bowman@amd.com>
+Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com>
+Reviewed-by: Jean Delvare <jdelvare@suse.de>
+[wsa: rebased after fixup in previous patch]
+Signed-off-by: Wolfram Sang <wsa@kernel.org>
+Cc: Mario Limonciello <Mario.Limonciello@amd.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/i2c/busses/i2c-piix4.c |   66 ++++++++++++++++++++++++++++++++++++-----
+ 1 file changed, 58 insertions(+), 8 deletions(-)
+
+--- a/drivers/i2c/busses/i2c-piix4.c
++++ b/drivers/i2c/busses/i2c-piix4.c
+@@ -98,6 +98,9 @@
+ #define SB800_PIIX4_PORT_IDX_MASK_KERNCZ      0x18
+ #define SB800_PIIX4_PORT_IDX_SHIFT_KERNCZ     3
++#define SB800_PIIX4_FCH_PM_ADDR                       0xFED80300
++#define SB800_PIIX4_FCH_PM_SIZE                       8
++
+ /* insmod parameters */
+ /* If force is set to anything different from 0, we forcibly enable the
+@@ -156,6 +159,12 @@ static const char *piix4_main_port_names
+ };
+ static const char *piix4_aux_port_name_sb800 = " port 1";
++struct sb800_mmio_cfg {
++      void __iomem *addr;
++      struct resource *res;
++      bool use_mmio;
++};
++
+ struct i2c_piix4_adapdata {
+       unsigned short smba;
+@@ -163,10 +172,40 @@ struct i2c_piix4_adapdata {
+       bool sb800_main;
+       bool notify_imc;
+       u8 port;                /* Port number, shifted */
++      struct sb800_mmio_cfg mmio_cfg;
+ };
+-static int piix4_sb800_region_request(struct device *dev)
++static int piix4_sb800_region_request(struct device *dev,
++                                    struct sb800_mmio_cfg *mmio_cfg)
+ {
++      if (mmio_cfg->use_mmio) {
++              struct resource *res;
++              void __iomem *addr;
++
++              res = request_mem_region_muxed(SB800_PIIX4_FCH_PM_ADDR,
++                                             SB800_PIIX4_FCH_PM_SIZE,
++                                             "sb800_piix4_smb");
++              if (!res) {
++                      dev_err(dev,
++                              "SMBus base address memory region 0x%x already in use.\n",
++                              SB800_PIIX4_FCH_PM_ADDR);
++                      return -EBUSY;
++              }
++
++              addr = ioremap(SB800_PIIX4_FCH_PM_ADDR,
++                             SB800_PIIX4_FCH_PM_SIZE);
++              if (!addr) {
++                      release_resource(res);
++                      dev_err(dev, "SMBus base address mapping failed.\n");
++                      return -ENOMEM;
++              }
++
++              mmio_cfg->res = res;
++              mmio_cfg->addr = addr;
++
++              return 0;
++      }
++
+       if (!request_muxed_region(SB800_PIIX4_SMB_IDX, SB800_PIIX4_SMB_MAP_SIZE,
+                                 "sb800_piix4_smb")) {
+               dev_err(dev,
+@@ -178,8 +217,15 @@ static int piix4_sb800_region_request(st
+       return 0;
+ }
+-static void piix4_sb800_region_release(struct device *dev)
++static void piix4_sb800_region_release(struct device *dev,
++                                     struct sb800_mmio_cfg *mmio_cfg)
+ {
++      if (mmio_cfg->use_mmio) {
++              iounmap(mmio_cfg->addr);
++              release_resource(mmio_cfg->res);
++              return;
++      }
++
+       release_region(SB800_PIIX4_SMB_IDX, SB800_PIIX4_SMB_MAP_SIZE);
+ }
+@@ -288,11 +334,13 @@ static int piix4_setup_sb800_smba(struct
+                                 u8 *smb_en_status,
+                                 unsigned short *piix4_smba)
+ {
++      struct sb800_mmio_cfg mmio_cfg;
+       u8 smba_en_lo;
+       u8 smba_en_hi;
+       int retval;
+-      retval = piix4_sb800_region_request(&PIIX4_dev->dev);
++      mmio_cfg.use_mmio = 0;
++      retval = piix4_sb800_region_request(&PIIX4_dev->dev, &mmio_cfg);
+       if (retval)
+               return retval;
+@@ -301,7 +349,7 @@ static int piix4_setup_sb800_smba(struct
+       outb_p(smb_en + 1, SB800_PIIX4_SMB_IDX);
+       smba_en_hi = inb_p(SB800_PIIX4_SMB_IDX + 1);
+-      piix4_sb800_region_release(&PIIX4_dev->dev);
++      piix4_sb800_region_release(&PIIX4_dev->dev, &mmio_cfg);
+       if (!smb_en) {
+               *smb_en_status = smba_en_lo & 0x10;
+@@ -328,6 +376,7 @@ static int piix4_setup_sb800(struct pci_
+       unsigned short piix4_smba;
+       u8 smb_en, smb_en_status, port_sel;
+       u8 i2ccfg, i2ccfg_offset = 0x10;
++      struct sb800_mmio_cfg mmio_cfg;
+       int retval;
+       /* SB800 and later SMBus does not support forcing address */
+@@ -407,7 +456,8 @@ static int piix4_setup_sb800(struct pci_
+                       piix4_port_shift_sb800 = SB800_PIIX4_PORT_IDX_SHIFT;
+               }
+       } else {
+-              retval = piix4_sb800_region_request(&PIIX4_dev->dev);
++              mmio_cfg.use_mmio = 0;
++              retval = piix4_sb800_region_request(&PIIX4_dev->dev, &mmio_cfg);
+               if (retval) {
+                       release_region(piix4_smba, SMBIOSIZE);
+                       return retval;
+@@ -420,7 +470,7 @@ static int piix4_setup_sb800(struct pci_
+                                      SB800_PIIX4_PORT_IDX;
+               piix4_port_mask_sb800 = SB800_PIIX4_PORT_IDX_MASK;
+               piix4_port_shift_sb800 = SB800_PIIX4_PORT_IDX_SHIFT;
+-              piix4_sb800_region_release(&PIIX4_dev->dev);
++              piix4_sb800_region_release(&PIIX4_dev->dev, &mmio_cfg);
+       }
+       dev_info(&PIIX4_dev->dev,
+@@ -731,7 +781,7 @@ static s32 piix4_access_sb800(struct i2c
+       u8 prev_port;
+       int retval;
+-      retval = piix4_sb800_region_request(&adap->dev);
++      retval = piix4_sb800_region_request(&adap->dev, &adapdata->mmio_cfg);
+       if (retval)
+               return retval;
+@@ -802,7 +852,7 @@ static s32 piix4_access_sb800(struct i2c
+               piix4_imc_wakeup();
+ release:
+-      piix4_sb800_region_release(&adap->dev);
++      piix4_sb800_region_release(&adap->dev, &adapdata->mmio_cfg);
+       return retval;
+ }
diff --git a/queue-5.15/i2c-piix4-add-efch-mmio-support-to-smbus-base-address-detect.patch b/queue-5.15/i2c-piix4-add-efch-mmio-support-to-smbus-base-address-detect.patch
new file mode 100644 (file)
index 0000000..6a93f44
--- /dev/null
@@ -0,0 +1,47 @@
+From 46967bc1ee93acd1d8953c87dc16f43de4076f93 Mon Sep 17 00:00:00 2001
+From: Terry Bowman <terry.bowman@amd.com>
+Date: Wed, 9 Feb 2022 11:27:15 -0600
+Subject: i2c: piix4: Add EFCH MMIO support to SMBus base address detect
+
+From: Terry Bowman <terry.bowman@amd.com>
+
+commit 46967bc1ee93acd1d8953c87dc16f43de4076f93 upstream.
+
+The EFCH SMBus controller's base address is determined using details in
+FCH::PM::DECODEEN[smbusasfiobase] and FCH::PM::DECODEEN[smbusasfioen].These
+register fields were accessed using cd6h/cd7h port I/O. cd6h/cd7h port I/O
+is no longer available in later AMD processors. Change base address
+detection to use MMIO instead of port I/O cd6h/cd7h.
+
+Signed-off-by: Terry Bowman <terry.bowman@amd.com>
+Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com>
+Reviewed-by: Jean Delvare <jdelvare@suse.de>
+Signed-off-by: Wolfram Sang <wsa@kernel.org>
+Cc: Mario Limonciello <Mario.Limonciello@amd.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/i2c/busses/i2c-piix4.c |   13 +++++++++----
+ 1 file changed, 9 insertions(+), 4 deletions(-)
+
+--- a/drivers/i2c/busses/i2c-piix4.c
++++ b/drivers/i2c/busses/i2c-piix4.c
+@@ -344,10 +344,15 @@ static int piix4_setup_sb800_smba(struct
+       if (retval)
+               return retval;
+-      outb_p(smb_en, SB800_PIIX4_SMB_IDX);
+-      smba_en_lo = inb_p(SB800_PIIX4_SMB_IDX + 1);
+-      outb_p(smb_en + 1, SB800_PIIX4_SMB_IDX);
+-      smba_en_hi = inb_p(SB800_PIIX4_SMB_IDX + 1);
++      if (mmio_cfg.use_mmio) {
++              smba_en_lo = ioread8(mmio_cfg.addr);
++              smba_en_hi = ioread8(mmio_cfg.addr + 1);
++      } else {
++              outb_p(smb_en, SB800_PIIX4_SMB_IDX);
++              smba_en_lo = inb_p(SB800_PIIX4_SMB_IDX + 1);
++              outb_p(smb_en + 1, SB800_PIIX4_SMB_IDX);
++              smba_en_hi = inb_p(SB800_PIIX4_SMB_IDX + 1);
++      }
+       piix4_sb800_region_release(&PIIX4_dev->dev, &mmio_cfg);
diff --git a/queue-5.15/i2c-piix4-enable-efch-mmio-for-family-17h.patch b/queue-5.15/i2c-piix4-enable-efch-mmio-for-family-17h.patch
new file mode 100644 (file)
index 0000000..3f3cdb2
--- /dev/null
@@ -0,0 +1,70 @@
+From 6cf72f41808ab5db1d7718b999b3ff0166e67e45 Mon Sep 17 00:00:00 2001
+From: Terry Bowman <terry.bowman@amd.com>
+Date: Wed, 9 Feb 2022 11:27:17 -0600
+Subject: i2c: piix4: Enable EFCH MMIO for Family 17h+
+
+From: Terry Bowman <terry.bowman@amd.com>
+
+commit 6cf72f41808ab5db1d7718b999b3ff0166e67e45 upstream.
+
+Enable EFCH MMIO using check for SMBus PCI revision ID value 0x51 or
+greater. This PCI revision ID check will enable family 17h and future
+AMD processors with the same EFCH SMBus controller HW.
+
+Signed-off-by: Terry Bowman <terry.bowman@amd.com>
+Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com>
+Reviewed-by: Jean Delvare <jdelvare@suse.de>
+Signed-off-by: Wolfram Sang <wsa@kernel.org>
+Cc: Mario Limonciello <Mario.Limonciello@amd.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/i2c/busses/i2c-piix4.c |   17 +++++++++++++++--
+ 1 file changed, 15 insertions(+), 2 deletions(-)
+
+--- a/drivers/i2c/busses/i2c-piix4.c
++++ b/drivers/i2c/busses/i2c-piix4.c
+@@ -229,6 +229,18 @@ static void piix4_sb800_region_release(s
+       release_region(SB800_PIIX4_SMB_IDX, SB800_PIIX4_SMB_MAP_SIZE);
+ }
++static bool piix4_sb800_use_mmio(struct pci_dev *PIIX4_dev)
++{
++      /*
++       * cd6h/cd7h port I/O accesses can be disabled on AMD processors
++       * w/ SMBus PCI revision ID 0x51 or greater. MMIO is supported on
++       * the same processors and is the recommended access method.
++       */
++      return (PIIX4_dev->vendor == PCI_VENDOR_ID_AMD &&
++              PIIX4_dev->device == PCI_DEVICE_ID_AMD_KERNCZ_SMBUS &&
++              PIIX4_dev->revision >= 0x51);
++}
++
+ static int piix4_setup(struct pci_dev *PIIX4_dev,
+                      const struct pci_device_id *id)
+ {
+@@ -339,7 +351,7 @@ static int piix4_setup_sb800_smba(struct
+       u8 smba_en_hi;
+       int retval;
+-      mmio_cfg.use_mmio = 0;
++      mmio_cfg.use_mmio = piix4_sb800_use_mmio(PIIX4_dev);
+       retval = piix4_sb800_region_request(&PIIX4_dev->dev, &mmio_cfg);
+       if (retval)
+               return retval;
+@@ -461,7 +473,7 @@ static int piix4_setup_sb800(struct pci_
+                       piix4_port_shift_sb800 = SB800_PIIX4_PORT_IDX_SHIFT;
+               }
+       } else {
+-              mmio_cfg.use_mmio = 0;
++              mmio_cfg.use_mmio = piix4_sb800_use_mmio(PIIX4_dev);
+               retval = piix4_sb800_region_request(&PIIX4_dev->dev, &mmio_cfg);
+               if (retval) {
+                       release_region(piix4_smba, SMBIOSIZE);
+@@ -944,6 +956,7 @@ static int piix4_add_adapter(struct pci_
+               return -ENOMEM;
+       }
++      adapdata->mmio_cfg.use_mmio = piix4_sb800_use_mmio(dev);
+       adapdata->smba = smba;
+       adapdata->sb800_main = sb800_main;
+       adapdata->port = port << piix4_port_shift_sb800;
diff --git a/queue-5.15/i2c-piix4-move-port-i-o-region-request-release-code-into-functions.patch b/queue-5.15/i2c-piix4-move-port-i-o-region-request-release-code-into-functions.patch
new file mode 100644 (file)
index 0000000..e063de2
--- /dev/null
@@ -0,0 +1,129 @@
+From a3325d225b00889f4b7fdb25d83033cae1048a92 Mon Sep 17 00:00:00 2001
+From: Terry Bowman <terry.bowman@amd.com>
+Date: Wed, 9 Feb 2022 11:27:11 -0600
+Subject: i2c: piix4: Move port I/O region request/release code into functions
+
+From: Terry Bowman <terry.bowman@amd.com>
+
+commit a3325d225b00889f4b7fdb25d83033cae1048a92 upstream.
+
+Move duplicated region request and release code into a function. Move is
+in preparation for following MMIO changes.
+
+Signed-off-by: Terry Bowman <terry.bowman@amd.com>
+Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com>
+Reviewed-by: Jean Delvare <jdelvare@suse.de>
+[wsa: added missing curly brace]
+Signed-off-by: Wolfram Sang <wsa@kernel.org>
+Cc: Mario Limonciello <Mario.Limonciello@amd.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/i2c/busses/i2c-piix4.c |   48 ++++++++++++++++++++++++++---------------
+ 1 file changed, 31 insertions(+), 17 deletions(-)
+
+--- a/drivers/i2c/busses/i2c-piix4.c
++++ b/drivers/i2c/busses/i2c-piix4.c
+@@ -165,6 +165,24 @@ struct i2c_piix4_adapdata {
+       u8 port;                /* Port number, shifted */
+ };
++static int piix4_sb800_region_request(struct device *dev)
++{
++      if (!request_muxed_region(SB800_PIIX4_SMB_IDX, SB800_PIIX4_SMB_MAP_SIZE,
++                                "sb800_piix4_smb")) {
++              dev_err(dev,
++                      "SMBus base address index region 0x%x already in use.\n",
++                      SB800_PIIX4_SMB_IDX);
++              return -EBUSY;
++      }
++
++      return 0;
++}
++
++static void piix4_sb800_region_release(struct device *dev)
++{
++      release_region(SB800_PIIX4_SMB_IDX, SB800_PIIX4_SMB_MAP_SIZE);
++}
++
+ static int piix4_setup(struct pci_dev *PIIX4_dev,
+                      const struct pci_device_id *id)
+ {
+@@ -270,6 +288,7 @@ static int piix4_setup_sb800(struct pci_
+       unsigned short piix4_smba;
+       u8 smba_en_lo, smba_en_hi, smb_en, smb_en_status, port_sel;
+       u8 i2ccfg, i2ccfg_offset = 0x10;
++      int retval;
+       /* SB800 and later SMBus does not support forcing address */
+       if (force || force_addr) {
+@@ -291,20 +310,16 @@ static int piix4_setup_sb800(struct pci_
+       else
+               smb_en = (aux) ? 0x28 : 0x2c;
+-      if (!request_muxed_region(SB800_PIIX4_SMB_IDX, SB800_PIIX4_SMB_MAP_SIZE,
+-                                "sb800_piix4_smb")) {
+-              dev_err(&PIIX4_dev->dev,
+-                      "SMB base address index region 0x%x already in use.\n",
+-                      SB800_PIIX4_SMB_IDX);
+-              return -EBUSY;
+-      }
++      retval = piix4_sb800_region_request(&PIIX4_dev->dev);
++      if (retval)
++              return retval;
+       outb_p(smb_en, SB800_PIIX4_SMB_IDX);
+       smba_en_lo = inb_p(SB800_PIIX4_SMB_IDX + 1);
+       outb_p(smb_en + 1, SB800_PIIX4_SMB_IDX);
+       smba_en_hi = inb_p(SB800_PIIX4_SMB_IDX + 1);
+-      release_region(SB800_PIIX4_SMB_IDX, SB800_PIIX4_SMB_MAP_SIZE);
++      piix4_sb800_region_release(&PIIX4_dev->dev);
+       if (!smb_en) {
+               smb_en_status = smba_en_lo & 0x10;
+@@ -373,11 +388,10 @@ static int piix4_setup_sb800(struct pci_
+                       piix4_port_shift_sb800 = SB800_PIIX4_PORT_IDX_SHIFT;
+               }
+       } else {
+-              if (!request_muxed_region(SB800_PIIX4_SMB_IDX,
+-                                        SB800_PIIX4_SMB_MAP_SIZE,
+-                                        "sb800_piix4_smb")) {
++              retval = piix4_sb800_region_request(&PIIX4_dev->dev);
++              if (retval) {
+                       release_region(piix4_smba, SMBIOSIZE);
+-                      return -EBUSY;
++                      return retval;
+               }
+               outb_p(SB800_PIIX4_PORT_IDX_SEL, SB800_PIIX4_SMB_IDX);
+@@ -387,7 +401,7 @@ static int piix4_setup_sb800(struct pci_
+                                      SB800_PIIX4_PORT_IDX;
+               piix4_port_mask_sb800 = SB800_PIIX4_PORT_IDX_MASK;
+               piix4_port_shift_sb800 = SB800_PIIX4_PORT_IDX_SHIFT;
+-              release_region(SB800_PIIX4_SMB_IDX, SB800_PIIX4_SMB_MAP_SIZE);
++              piix4_sb800_region_release(&PIIX4_dev->dev);
+       }
+       dev_info(&PIIX4_dev->dev,
+@@ -685,9 +699,9 @@ static s32 piix4_access_sb800(struct i2c
+       u8 port;
+       int retval;
+-      if (!request_muxed_region(SB800_PIIX4_SMB_IDX, SB800_PIIX4_SMB_MAP_SIZE,
+-                                "sb800_piix4_smb"))
+-              return -EBUSY;
++      retval = piix4_sb800_region_request(&adap->dev);
++      if (retval)
++              return retval;
+       /* Request the SMBUS semaphore, avoid conflicts with the IMC */
+       smbslvcnt  = inb_p(SMBSLVCNT);
+@@ -762,7 +776,7 @@ static s32 piix4_access_sb800(struct i2c
+               piix4_imc_wakeup();
+ release:
+-      release_region(SB800_PIIX4_SMB_IDX, SB800_PIIX4_SMB_MAP_SIZE);
++      piix4_sb800_region_release(&adap->dev);
+       return retval;
+ }
diff --git a/queue-5.15/i2c-piix4-move-smbus-controller-base-address-detect-into-function.patch b/queue-5.15/i2c-piix4-move-smbus-controller-base-address-detect-into-function.patch
new file mode 100644 (file)
index 0000000..832397f
--- /dev/null
@@ -0,0 +1,114 @@
+From 0a59a24e14e9b21dcbb6b8ea41422e2fdfa437fd Mon Sep 17 00:00:00 2001
+From: Terry Bowman <terry.bowman@amd.com>
+Date: Wed, 9 Feb 2022 11:27:12 -0600
+Subject: i2c: piix4: Move SMBus controller base address detect into function
+
+From: Terry Bowman <terry.bowman@amd.com>
+
+commit 0a59a24e14e9b21dcbb6b8ea41422e2fdfa437fd upstream.
+
+Move SMBus controller base address detection into function. Refactor
+is in preparation for following MMIO changes.
+
+Signed-off-by: Terry Bowman <terry.bowman@amd.com>
+Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com>
+Reviewed-by: Jean Delvare <jdelvare@suse.de>
+Signed-off-by: Wolfram Sang <wsa@kernel.org>
+Cc: Mario Limonciello <Mario.Limonciello@amd.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/i2c/busses/i2c-piix4.c |   69 ++++++++++++++++++++++++++---------------
+ 1 file changed, 44 insertions(+), 25 deletions(-)
+
+--- a/drivers/i2c/busses/i2c-piix4.c
++++ b/drivers/i2c/busses/i2c-piix4.c
+@@ -282,11 +282,51 @@ static int piix4_setup(struct pci_dev *P
+       return piix4_smba;
+ }
++static int piix4_setup_sb800_smba(struct pci_dev *PIIX4_dev,
++                                u8 smb_en,
++                                u8 aux,
++                                u8 *smb_en_status,
++                                unsigned short *piix4_smba)
++{
++      u8 smba_en_lo;
++      u8 smba_en_hi;
++      int retval;
++
++      retval = piix4_sb800_region_request(&PIIX4_dev->dev);
++      if (retval)
++              return retval;
++
++      outb_p(smb_en, SB800_PIIX4_SMB_IDX);
++      smba_en_lo = inb_p(SB800_PIIX4_SMB_IDX + 1);
++      outb_p(smb_en + 1, SB800_PIIX4_SMB_IDX);
++      smba_en_hi = inb_p(SB800_PIIX4_SMB_IDX + 1);
++
++      piix4_sb800_region_release(&PIIX4_dev->dev);
++
++      if (!smb_en) {
++              *smb_en_status = smba_en_lo & 0x10;
++              *piix4_smba = smba_en_hi << 8;
++              if (aux)
++                      *piix4_smba |= 0x20;
++      } else {
++              *smb_en_status = smba_en_lo & 0x01;
++              *piix4_smba = ((smba_en_hi << 8) | smba_en_lo) & 0xffe0;
++      }
++
++      if (!*smb_en_status) {
++              dev_err(&PIIX4_dev->dev,
++                      "SMBus Host Controller not enabled!\n");
++              return -ENODEV;
++      }
++
++      return 0;
++}
++
+ static int piix4_setup_sb800(struct pci_dev *PIIX4_dev,
+                            const struct pci_device_id *id, u8 aux)
+ {
+       unsigned short piix4_smba;
+-      u8 smba_en_lo, smba_en_hi, smb_en, smb_en_status, port_sel;
++      u8 smb_en, smb_en_status, port_sel;
+       u8 i2ccfg, i2ccfg_offset = 0x10;
+       int retval;
+@@ -310,33 +350,12 @@ static int piix4_setup_sb800(struct pci_
+       else
+               smb_en = (aux) ? 0x28 : 0x2c;
+-      retval = piix4_sb800_region_request(&PIIX4_dev->dev);
++      retval = piix4_setup_sb800_smba(PIIX4_dev, smb_en, aux, &smb_en_status,
++                                      &piix4_smba);
++
+       if (retval)
+               return retval;
+-      outb_p(smb_en, SB800_PIIX4_SMB_IDX);
+-      smba_en_lo = inb_p(SB800_PIIX4_SMB_IDX + 1);
+-      outb_p(smb_en + 1, SB800_PIIX4_SMB_IDX);
+-      smba_en_hi = inb_p(SB800_PIIX4_SMB_IDX + 1);
+-
+-      piix4_sb800_region_release(&PIIX4_dev->dev);
+-
+-      if (!smb_en) {
+-              smb_en_status = smba_en_lo & 0x10;
+-              piix4_smba = smba_en_hi << 8;
+-              if (aux)
+-                      piix4_smba |= 0x20;
+-      } else {
+-              smb_en_status = smba_en_lo & 0x01;
+-              piix4_smba = ((smba_en_hi << 8) | smba_en_lo) & 0xffe0;
+-      }
+-
+-      if (!smb_en_status) {
+-              dev_err(&PIIX4_dev->dev,
+-                      "SMBus Host Controller not enabled!\n");
+-              return -ENODEV;
+-      }
+-
+       if (acpi_check_region(piix4_smba, SMBIOSIZE, piix4_driver.name))
+               return -ENODEV;
diff --git a/queue-5.15/i2c-piix4-move-smbus-port-selection-into-function.patch b/queue-5.15/i2c-piix4-move-smbus-port-selection-into-function.patch
new file mode 100644 (file)
index 0000000..39fc24c
--- /dev/null
@@ -0,0 +1,76 @@
+From fbafbd51bff52cb3a920fd98d4dae2a78dd433d0 Mon Sep 17 00:00:00 2001
+From: Terry Bowman <terry.bowman@amd.com>
+Date: Wed, 9 Feb 2022 11:27:13 -0600
+Subject: i2c: piix4: Move SMBus port selection into function
+
+From: Terry Bowman <terry.bowman@amd.com>
+
+commit fbafbd51bff52cb3a920fd98d4dae2a78dd433d0 upstream.
+
+Move port selection code into a separate function. Refactor is in
+preparation for following MMIO changes.
+
+Signed-off-by: Terry Bowman <terry.bowman@amd.com>
+Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com>
+Reviewed-by: Jean Delvare <jdelvare@suse.de>
+Signed-off-by: Wolfram Sang <wsa@kernel.org>
+Cc: Mario Limonciello <Mario.Limonciello@amd.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/i2c/busses/i2c-piix4.c |   27 +++++++++++++++++----------
+ 1 file changed, 17 insertions(+), 10 deletions(-)
+
+--- a/drivers/i2c/busses/i2c-piix4.c
++++ b/drivers/i2c/busses/i2c-piix4.c
+@@ -698,6 +698,20 @@ static void piix4_imc_wakeup(void)
+       release_region(KERNCZ_IMC_IDX, 2);
+ }
++static int piix4_sb800_port_sel(u8 port)
++{
++      u8 smba_en_lo, val;
++
++      outb_p(piix4_port_sel_sb800, SB800_PIIX4_SMB_IDX);
++      smba_en_lo = inb_p(SB800_PIIX4_SMB_IDX + 1);
++
++      val = (smba_en_lo & ~piix4_port_mask_sb800) | port;
++      if (smba_en_lo != val)
++              outb_p(val, SB800_PIIX4_SMB_IDX + 1);
++
++      return (smba_en_lo & piix4_port_mask_sb800);
++}
++
+ /*
+  * Handles access to multiple SMBus ports on the SB800.
+  * The port is selected by bits 2:1 of the smb_en register (0x2c).
+@@ -714,8 +728,7 @@ static s32 piix4_access_sb800(struct i2c
+       unsigned short piix4_smba = adapdata->smba;
+       int retries = MAX_TIMEOUT;
+       int smbslvcnt;
+-      u8 smba_en_lo;
+-      u8 port;
++      u8 prev_port;
+       int retval;
+       retval = piix4_sb800_region_request(&adap->dev);
+@@ -775,18 +788,12 @@ static s32 piix4_access_sb800(struct i2c
+               }
+       }
+-      outb_p(piix4_port_sel_sb800, SB800_PIIX4_SMB_IDX);
+-      smba_en_lo = inb_p(SB800_PIIX4_SMB_IDX + 1);
+-
+-      port = adapdata->port;
+-      if ((smba_en_lo & piix4_port_mask_sb800) != port)
+-              outb_p((smba_en_lo & ~piix4_port_mask_sb800) | port,
+-                     SB800_PIIX4_SMB_IDX + 1);
++      prev_port = piix4_sb800_port_sel(adapdata->port);
+       retval = piix4_access(adap, addr, flags, read_write,
+                             command, size, data);
+-      outb_p(smba_en_lo, SB800_PIIX4_SMB_IDX + 1);
++      piix4_sb800_port_sel(prev_port);
+       /* Release the semaphore */
+       outb_p(smbslvcnt | 0x20, SMBSLVCNT);
diff --git a/queue-5.15/i2c-piix4-replace-hardcoded-memory-map-size-with-a-define.patch b/queue-5.15/i2c-piix4-replace-hardcoded-memory-map-size-with-a-define.patch
new file mode 100644 (file)
index 0000000..f05ef3b
--- /dev/null
@@ -0,0 +1,89 @@
+From 93102cb449780f7b4eecf713451627b78373ce49 Mon Sep 17 00:00:00 2001
+From: Terry Bowman <terry.bowman@amd.com>
+Date: Wed, 9 Feb 2022 11:27:10 -0600
+Subject: i2c: piix4: Replace hardcoded memory map size with a #define
+
+From: Terry Bowman <terry.bowman@amd.com>
+
+commit 93102cb449780f7b4eecf713451627b78373ce49 upstream.
+
+Replace number constant with #define to improve readability and
+maintainability.
+
+Signed-off-by: Terry Bowman <terry.bowman@amd.com>
+Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com>
+Reviewed-by: Jean Delvare <jdelvare@suse.de>
+Signed-off-by: Wolfram Sang <wsa@kernel.org>
+Cc: Mario Limonciello <Mario.Limonciello@amd.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/i2c/busses/i2c-piix4.c |   16 ++++++++++------
+ 1 file changed, 10 insertions(+), 6 deletions(-)
+
+--- a/drivers/i2c/busses/i2c-piix4.c
++++ b/drivers/i2c/busses/i2c-piix4.c
+@@ -77,6 +77,7 @@
+ /* SB800 constants */
+ #define SB800_PIIX4_SMB_IDX           0xcd6
++#define SB800_PIIX4_SMB_MAP_SIZE      2
+ #define KERNCZ_IMC_IDX                        0x3e
+ #define KERNCZ_IMC_DATA                       0x3f
+@@ -290,7 +291,8 @@ static int piix4_setup_sb800(struct pci_
+       else
+               smb_en = (aux) ? 0x28 : 0x2c;
+-      if (!request_muxed_region(SB800_PIIX4_SMB_IDX, 2, "sb800_piix4_smb")) {
++      if (!request_muxed_region(SB800_PIIX4_SMB_IDX, SB800_PIIX4_SMB_MAP_SIZE,
++                                "sb800_piix4_smb")) {
+               dev_err(&PIIX4_dev->dev,
+                       "SMB base address index region 0x%x already in use.\n",
+                       SB800_PIIX4_SMB_IDX);
+@@ -302,7 +304,7 @@ static int piix4_setup_sb800(struct pci_
+       outb_p(smb_en + 1, SB800_PIIX4_SMB_IDX);
+       smba_en_hi = inb_p(SB800_PIIX4_SMB_IDX + 1);
+-      release_region(SB800_PIIX4_SMB_IDX, 2);
++      release_region(SB800_PIIX4_SMB_IDX, SB800_PIIX4_SMB_MAP_SIZE);
+       if (!smb_en) {
+               smb_en_status = smba_en_lo & 0x10;
+@@ -371,7 +373,8 @@ static int piix4_setup_sb800(struct pci_
+                       piix4_port_shift_sb800 = SB800_PIIX4_PORT_IDX_SHIFT;
+               }
+       } else {
+-              if (!request_muxed_region(SB800_PIIX4_SMB_IDX, 2,
++              if (!request_muxed_region(SB800_PIIX4_SMB_IDX,
++                                        SB800_PIIX4_SMB_MAP_SIZE,
+                                         "sb800_piix4_smb")) {
+                       release_region(piix4_smba, SMBIOSIZE);
+                       return -EBUSY;
+@@ -384,7 +387,7 @@ static int piix4_setup_sb800(struct pci_
+                                      SB800_PIIX4_PORT_IDX;
+               piix4_port_mask_sb800 = SB800_PIIX4_PORT_IDX_MASK;
+               piix4_port_shift_sb800 = SB800_PIIX4_PORT_IDX_SHIFT;
+-              release_region(SB800_PIIX4_SMB_IDX, 2);
++              release_region(SB800_PIIX4_SMB_IDX, SB800_PIIX4_SMB_MAP_SIZE);
+       }
+       dev_info(&PIIX4_dev->dev,
+@@ -682,7 +685,8 @@ static s32 piix4_access_sb800(struct i2c
+       u8 port;
+       int retval;
+-      if (!request_muxed_region(SB800_PIIX4_SMB_IDX, 2, "sb800_piix4_smb"))
++      if (!request_muxed_region(SB800_PIIX4_SMB_IDX, SB800_PIIX4_SMB_MAP_SIZE,
++                                "sb800_piix4_smb"))
+               return -EBUSY;
+       /* Request the SMBUS semaphore, avoid conflicts with the IMC */
+@@ -758,7 +762,7 @@ static s32 piix4_access_sb800(struct i2c
+               piix4_imc_wakeup();
+ release:
+-      release_region(SB800_PIIX4_SMB_IDX, 2);
++      release_region(SB800_PIIX4_SMB_IDX, SB800_PIIX4_SMB_MAP_SIZE);
+       return retval;
+ }
diff --git a/queue-5.15/io_uring-arm-poll-for-non-nowait-files.patch b/queue-5.15/io_uring-arm-poll-for-non-nowait-files.patch
new file mode 100644 (file)
index 0000000..27cd875
--- /dev/null
@@ -0,0 +1,60 @@
+From e74ead135bc4459f7d40b1f8edab1333a28b54e8 Mon Sep 17 00:00:00 2001
+From: Pavel Begunkov <asml.silence@gmail.com>
+Date: Sun, 17 Oct 2021 00:07:08 +0100
+Subject: io_uring: arm poll for non-nowait files
+
+From: Pavel Begunkov <asml.silence@gmail.com>
+
+commit e74ead135bc4459f7d40b1f8edab1333a28b54e8 upstream.
+
+Don't check if we can do nowait before arming apoll, there are several
+reasons for that. First, we don't care much about files that don't
+support nowait. Second, it may be useful -- we don't want to be taking
+away extra workers from io-wq when it can go in some async. Even if it
+will go through io-wq eventually, it make difference in the numbers of
+workers actually used. And the last one, it's needed to clean nowait in
+future commits.
+
+[kernel test robot: fix unused-var]
+
+Signed-off-by: Pavel Begunkov <asml.silence@gmail.com>
+Link: https://lore.kernel.org/r/9d06f3cb2c8b686d970269a87986f154edb83043.1634425438.git.asml.silence@gmail.com
+Signed-off-by: Jens Axboe <axboe@kernel.dk>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/io_uring.c |    7 -------
+ 1 file changed, 7 deletions(-)
+
+--- a/fs/io_uring.c
++++ b/fs/io_uring.c
+@@ -5662,7 +5662,6 @@ static int io_arm_poll_handler(struct io
+       struct async_poll *apoll;
+       struct io_poll_table ipt;
+       __poll_t ret, mask = EPOLLONESHOT | POLLERR | POLLPRI;
+-      int rw;
+       if (!req->file || !file_can_poll(req->file))
+               return IO_APOLL_ABORTED;
+@@ -5672,7 +5671,6 @@ static int io_arm_poll_handler(struct io
+               return IO_APOLL_ABORTED;
+       if (def->pollin) {
+-              rw = READ;
+               mask |= POLLIN | POLLRDNORM;
+               /* If reading from MSG_ERRQUEUE using recvmsg, ignore POLLIN */
+@@ -5680,14 +5678,9 @@ static int io_arm_poll_handler(struct io
+                   (req->sr_msg.msg_flags & MSG_ERRQUEUE))
+                       mask &= ~POLLIN;
+       } else {
+-              rw = WRITE;
+               mask |= POLLOUT | POLLWRNORM;
+       }
+-      /* if we can't nonblock try, then no point in arming a poll handler */
+-      if (!io_file_supports_nowait(req, rw))
+-              return IO_APOLL_ABORTED;
+-
+       apoll = kmalloc(sizeof(*apoll), GFP_ATOMIC);
+       if (unlikely(!apoll))
+               return IO_APOLL_ABORTED;
diff --git a/queue-5.15/kernel-resource-introduce-request_mem_region_muxed.patch b/queue-5.15/kernel-resource-introduce-request_mem_region_muxed.patch
new file mode 100644 (file)
index 0000000..f77f036
--- /dev/null
@@ -0,0 +1,38 @@
+From 27c196c7b73cb70bbed3a9df46563bab60e63415 Mon Sep 17 00:00:00 2001
+From: Terry Bowman <terry.bowman@amd.com>
+Date: Wed, 9 Feb 2022 11:27:09 -0600
+Subject: kernel/resource: Introduce request_mem_region_muxed()
+
+From: Terry Bowman <terry.bowman@amd.com>
+
+commit 27c196c7b73cb70bbed3a9df46563bab60e63415 upstream.
+
+Support for requesting muxed memory region is implemented but not
+currently callable as a macro. Add the request muxed memory
+region macro.
+
+MMIO memory accesses can be synchronized using request_mem_region() which
+is already available. This call will return failure if the resource is
+busy. The 'muxed' version of this macro will handle a busy resource by
+using a wait queue to retry until the resource is available.
+
+Signed-off-by: Terry Bowman <terry.bowman@amd.com>
+Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com>
+Signed-off-by: Wolfram Sang <wsa@kernel.org>
+Cc: Mario Limonciello <Mario.Limonciello@amd.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ include/linux/ioport.h |    2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/include/linux/ioport.h
++++ b/include/linux/ioport.h
+@@ -262,6 +262,8 @@ resource_union(struct resource *r1, stru
+ #define request_muxed_region(start,n,name)    __request_region(&ioport_resource, (start), (n), (name), IORESOURCE_MUXED)
+ #define __request_mem_region(start,n,name, excl) __request_region(&iomem_resource, (start), (n), (name), excl)
+ #define request_mem_region(start,n,name) __request_region(&iomem_resource, (start), (n), (name), 0)
++#define request_mem_region_muxed(start, n, name) \
++      __request_region(&iomem_resource, (start), (n), (name), IORESOURCE_MUXED)
+ #define request_mem_region_exclusive(start,n,name) \
+       __request_region(&iomem_resource, (start), (n), (name), IORESOURCE_EXCLUSIVE)
+ #define rename_region(region, newname) do { (region)->name = (newname); } while (0)
diff --git a/queue-5.15/mm-kfence-reset-pg_slab-and-memcg_data-before-freeing-__kfence_pool.patch b/queue-5.15/mm-kfence-reset-pg_slab-and-memcg_data-before-freeing-__kfence_pool.patch
new file mode 100644 (file)
index 0000000..ad3ffa0
--- /dev/null
@@ -0,0 +1,85 @@
+From 2839b0999c20c9f6bf353849c69370e121e2fa1a Mon Sep 17 00:00:00 2001
+From: Hyeonggon Yoo <42.hyeyoo@gmail.com>
+Date: Mon, 9 May 2022 17:34:29 -0700
+Subject: mm/kfence: reset PG_slab and memcg_data before freeing __kfence_pool
+
+From: Hyeonggon Yoo <42.hyeyoo@gmail.com>
+
+commit 2839b0999c20c9f6bf353849c69370e121e2fa1a upstream.
+
+When kfence fails to initialize kfence pool, it frees the pool.  But it
+does not reset memcg_data and PG_slab flag.
+
+Below is a BUG because of this. Let's fix it by resetting memcg_data
+and PG_slab flag before free.
+
+[    0.089149] BUG: Bad page state in process swapper/0  pfn:3d8e06
+[    0.089149] page:ffffea46cf638180 refcount:0 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0x3d8e06
+[    0.089150] memcg:ffffffff94a475d1
+[    0.089150] flags: 0x17ffffc0000200(slab|node=0|zone=2|lastcpupid=0x1fffff)
+[    0.089151] raw: 0017ffffc0000200 ffffea46cf638188 ffffea46cf638188 0000000000000000
+[    0.089152] raw: 0000000000000000 0000000000000000 00000000ffffffff ffffffff94a475d1
+[    0.089152] page dumped because: page still charged to cgroup
+[    0.089153] Modules linked in:
+[    0.089153] CPU: 0 PID: 0 Comm: swapper/0 Tainted: G    B   W         5.18.0-rc1+ #965
+[    0.089154] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.14.0-2 04/01/2014
+[    0.089154] Call Trace:
+[    0.089155]  <TASK>
+[    0.089155]  dump_stack_lvl+0x49/0x5f
+[    0.089157]  dump_stack+0x10/0x12
+[    0.089158]  bad_page.cold+0x63/0x94
+[    0.089159]  check_free_page_bad+0x66/0x70
+[    0.089160]  __free_pages_ok+0x423/0x530
+[    0.089161]  __free_pages_core+0x8e/0xa0
+[    0.089162]  memblock_free_pages+0x10/0x12
+[    0.089164]  memblock_free_late+0x8f/0xb9
+[    0.089165]  kfence_init+0x68/0x92
+[    0.089166]  start_kernel+0x789/0x992
+[    0.089167]  x86_64_start_reservations+0x24/0x26
+[    0.089168]  x86_64_start_kernel+0xa9/0xaf
+[    0.089170]  secondary_startup_64_no_verify+0xd5/0xdb
+[    0.089171]  </TASK>
+
+Link: https://lkml.kernel.org/r/YnPG3pQrqfcgOlVa@hyeyoo
+Fixes: 0ce20dd84089 ("mm: add Kernel Electric-Fence infrastructure")
+Fixes: 8f0b36497303 ("mm: kfence: fix objcgs vector allocation")
+Signed-off-by: Hyeonggon Yoo <42.hyeyoo@gmail.com>
+Reviewed-by: Marco Elver <elver@google.com>
+Reviewed-by: Muchun Song <songmuchun@bytedance.com>
+Cc: Alexander Potapenko <glider@google.com>
+Cc: Dmitry Vyukov <dvyukov@google.com>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+[42.hyeyoo@gmail.com: backport - use struct page]
+Signed-off-by: Hyeonggon Yoo <42.hyeyoo@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ mm/kfence/core.c |   11 +++++++++++
+ 1 file changed, 11 insertions(+)
+
+--- a/mm/kfence/core.c
++++ b/mm/kfence/core.c
+@@ -510,6 +510,7 @@ static bool __init kfence_init_pool(void
+       unsigned long addr = (unsigned long)__kfence_pool;
+       struct page *pages;
+       int i;
++      char *p;
+       if (!__kfence_pool)
+               return false;
+@@ -592,6 +593,16 @@ err:
+        * fails for the first page, and therefore expect addr==__kfence_pool in
+        * most failure cases.
+        */
++      for (p = (char *)addr; p < __kfence_pool + KFENCE_POOL_SIZE; p += PAGE_SIZE) {
++              struct page *page = virt_to_page(p);
++
++              if (!PageSlab(page))
++                      continue;
++#ifdef CONFIG_MEMCG
++              page->memcg_data = 0;
++#endif
++              __ClearPageSlab(page);
++      }
+       memblock_free_late(__pa(addr), KFENCE_POOL_SIZE - (addr - (unsigned long)__kfence_pool));
+       __kfence_pool = NULL;
+       return false;
index 7ac09b3bef66e435d89dfb89d22dbde807cfb168..42818de93f09f9496d55d6bf88732a0aff6d237e 100644 (file)
@@ -1 +1,17 @@
 usb-gadget-fix-race-when-gadget-driver-register-via-ioctl.patch
+io_uring-arm-poll-for-non-nowait-files.patch
+floppy-use-a-statically-allocated-error-counter.patch
+kernel-resource-introduce-request_mem_region_muxed.patch
+i2c-piix4-replace-hardcoded-memory-map-size-with-a-define.patch
+i2c-piix4-move-port-i-o-region-request-release-code-into-functions.patch
+i2c-piix4-move-smbus-controller-base-address-detect-into-function.patch
+i2c-piix4-move-smbus-port-selection-into-function.patch
+i2c-piix4-add-efch-mmio-support-to-region-request-and-release.patch
+i2c-piix4-add-efch-mmio-support-to-smbus-base-address-detect.patch
+i2c-piix4-add-efch-mmio-support-for-smbus-port-select.patch
+i2c-piix4-enable-efch-mmio-for-family-17h.patch
+watchdog-sp5100_tco-move-timer-initialization-into-function.patch
+watchdog-sp5100_tco-refactor-mmio-base-address-initialization.patch
+watchdog-sp5100_tco-add-initialization-using-efch-mmio.patch
+watchdog-sp5100_tco-enable-family-17h-cpus.patch
+mm-kfence-reset-pg_slab-and-memcg_data-before-freeing-__kfence_pool.patch
diff --git a/queue-5.15/watchdog-sp5100_tco-add-initialization-using-efch-mmio.patch b/queue-5.15/watchdog-sp5100_tco-add-initialization-using-efch-mmio.patch
new file mode 100644 (file)
index 0000000..91fe800
--- /dev/null
@@ -0,0 +1,172 @@
+From 0578fff4aae5bce3f09875f58e68e9ffbab8daf5 Mon Sep 17 00:00:00 2001
+From: Terry Bowman <terry.bowman@amd.com>
+Date: Wed, 2 Feb 2022 09:35:24 -0600
+Subject: Watchdog: sp5100_tco: Add initialization using EFCH MMIO
+
+From: Terry Bowman <terry.bowman@amd.com>
+
+commit 0578fff4aae5bce3f09875f58e68e9ffbab8daf5 upstream.
+
+cd6h/cd7h port I/O can be disabled on recent AMD hardware. Read
+accesses to disabled cd6h/cd7h port I/O will return F's and written
+data is dropped. It is recommended to replace the cd6h/cd7h
+port I/O with MMIO.
+
+Co-developed-by: Robert Richter <rrichter@amd.com>
+Signed-off-by: Robert Richter <rrichter@amd.com>
+Signed-off-by: Terry Bowman <terry.bowman@amd.com>
+Tested-by: Jean Delvare <jdelvare@suse.de>
+Reviewed-by: Jean Delvare <jdelvare@suse.de>
+Reviewed-by: Guenter Roeck <linux@roeck-us.net>
+Link: https://lore.kernel.org/r/20220202153525.1693378-4-terry.bowman@amd.com
+Signed-off-by: Guenter Roeck <linux@roeck-us.net>
+Signed-off-by: Wim Van Sebroeck <wim@linux-watchdog.org>
+Cc: Mario Limonciello <Mario.Limonciello@amd.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/watchdog/sp5100_tco.c |  100 +++++++++++++++++++++++++++++++++++++++++-
+ drivers/watchdog/sp5100_tco.h |    5 ++
+ 2 files changed, 104 insertions(+), 1 deletion(-)
+
+--- a/drivers/watchdog/sp5100_tco.c
++++ b/drivers/watchdog/sp5100_tco.c
+@@ -48,7 +48,7 @@
+ /* internal variables */
+ enum tco_reg_layout {
+-      sp5100, sb800, efch
++      sp5100, sb800, efch, efch_mmio
+ };
+ struct sp5100_tco {
+@@ -201,6 +201,8 @@ static void tco_timer_enable(struct sp51
+                                         ~EFCH_PM_WATCHDOG_DISABLE,
+                                         EFCH_PM_DECODEEN_SECOND_RES);
+               break;
++      default:
++              break;
+       }
+ }
+@@ -299,6 +301,99 @@ static int sp5100_tco_timer_init(struct
+       return 0;
+ }
++static u8 efch_read_pm_reg8(void __iomem *addr, u8 index)
++{
++      return readb(addr + index);
++}
++
++static void efch_update_pm_reg8(void __iomem *addr, u8 index, u8 reset, u8 set)
++{
++      u8 val;
++
++      val = readb(addr + index);
++      val &= reset;
++      val |= set;
++      writeb(val, addr + index);
++}
++
++static void tco_timer_enable_mmio(void __iomem *addr)
++{
++      efch_update_pm_reg8(addr, EFCH_PM_DECODEEN3,
++                          ~EFCH_PM_WATCHDOG_DISABLE,
++                          EFCH_PM_DECODEEN_SECOND_RES);
++}
++
++static int sp5100_tco_setupdevice_mmio(struct device *dev,
++                                     struct watchdog_device *wdd)
++{
++      struct sp5100_tco *tco = watchdog_get_drvdata(wdd);
++      const char *dev_name = SB800_DEVNAME;
++      u32 mmio_addr = 0, alt_mmio_addr = 0;
++      struct resource *res;
++      void __iomem *addr;
++      int ret;
++      u32 val;
++
++      res = request_mem_region_muxed(EFCH_PM_ACPI_MMIO_PM_ADDR,
++                                     EFCH_PM_ACPI_MMIO_PM_SIZE,
++                                     "sp5100_tco");
++
++      if (!res) {
++              dev_err(dev,
++                      "Memory region 0x%08x already in use\n",
++                      EFCH_PM_ACPI_MMIO_PM_ADDR);
++              return -EBUSY;
++      }
++
++      addr = ioremap(EFCH_PM_ACPI_MMIO_PM_ADDR, EFCH_PM_ACPI_MMIO_PM_SIZE);
++      if (!addr) {
++              dev_err(dev, "Address mapping failed\n");
++              ret = -ENOMEM;
++              goto out;
++      }
++
++      /*
++       * EFCH_PM_DECODEEN_WDT_TMREN is dual purpose. This bitfield
++       * enables sp5100_tco register MMIO space decoding. The bitfield
++       * also starts the timer operation. Enable if not already enabled.
++       */
++      val = efch_read_pm_reg8(addr, EFCH_PM_DECODEEN);
++      if (!(val & EFCH_PM_DECODEEN_WDT_TMREN)) {
++              efch_update_pm_reg8(addr, EFCH_PM_DECODEEN, 0xff,
++                                  EFCH_PM_DECODEEN_WDT_TMREN);
++      }
++
++      /* Error if the timer could not be enabled */
++      val = efch_read_pm_reg8(addr, EFCH_PM_DECODEEN);
++      if (!(val & EFCH_PM_DECODEEN_WDT_TMREN)) {
++              dev_err(dev, "Failed to enable the timer\n");
++              ret = -EFAULT;
++              goto out;
++      }
++
++      mmio_addr = EFCH_PM_WDT_ADDR;
++
++      /* Determine alternate MMIO base address */
++      val = efch_read_pm_reg8(addr, EFCH_PM_ISACONTROL);
++      if (val & EFCH_PM_ISACONTROL_MMIOEN)
++              alt_mmio_addr = EFCH_PM_ACPI_MMIO_ADDR +
++                      EFCH_PM_ACPI_MMIO_WDT_OFFSET;
++
++      ret = sp5100_tco_prepare_base(tco, mmio_addr, alt_mmio_addr, dev_name);
++      if (!ret) {
++              tco_timer_enable_mmio(addr);
++              ret = sp5100_tco_timer_init(tco);
++      }
++
++out:
++      if (addr)
++              iounmap(addr);
++
++      release_resource(res);
++
++      return ret;
++}
++
+ static int sp5100_tco_setupdevice(struct device *dev,
+                                 struct watchdog_device *wdd)
+ {
+@@ -308,6 +403,9 @@ static int sp5100_tco_setupdevice(struct
+       u32 alt_mmio_addr = 0;
+       int ret;
++      if (tco->tco_reg_layout == efch_mmio)
++              return sp5100_tco_setupdevice_mmio(dev, wdd);
++
+       /* Request the IO ports used by this driver */
+       if (!request_muxed_region(SP5100_IO_PM_INDEX_REG,
+                                 SP5100_PM_IOPORTS_SIZE, "sp5100_tco")) {
+--- a/drivers/watchdog/sp5100_tco.h
++++ b/drivers/watchdog/sp5100_tco.h
+@@ -83,4 +83,9 @@
+ #define EFCH_PM_ISACONTROL_MMIOEN     BIT(1)
+ #define EFCH_PM_ACPI_MMIO_ADDR                0xfed80000
++#define EFCH_PM_ACPI_MMIO_PM_OFFSET   0x00000300
+ #define EFCH_PM_ACPI_MMIO_WDT_OFFSET  0x00000b00
++
++#define EFCH_PM_ACPI_MMIO_PM_ADDR     (EFCH_PM_ACPI_MMIO_ADDR +       \
++                                       EFCH_PM_ACPI_MMIO_PM_OFFSET)
++#define EFCH_PM_ACPI_MMIO_PM_SIZE     8
diff --git a/queue-5.15/watchdog-sp5100_tco-enable-family-17h-cpus.patch b/queue-5.15/watchdog-sp5100_tco-enable-family-17h-cpus.patch
new file mode 100644 (file)
index 0000000..1c44308
--- /dev/null
@@ -0,0 +1,75 @@
+From 826270373f17fd8ebd10753ca0a5fd2ceb1dc38e Mon Sep 17 00:00:00 2001
+From: Terry Bowman <terry.bowman@amd.com>
+Date: Wed, 2 Feb 2022 09:35:25 -0600
+Subject: Watchdog: sp5100_tco: Enable Family 17h+ CPUs
+
+From: Terry Bowman <terry.bowman@amd.com>
+
+commit 826270373f17fd8ebd10753ca0a5fd2ceb1dc38e upstream.
+
+The driver currently uses a CPU family match of 17h to determine
+EFCH_PM_DECODEEN_WDT_TMREN register support. This family check will not
+support future AMD CPUs and instead will require driver updates to add
+support.
+
+Remove the family 17h family check and add a check for SMBus PCI
+revision ID 0x51 or greater. The MMIO access method has been available
+since at least SMBus controllers using PCI revision 0x51. This revision
+check will support family 17h and future AMD processors including EFCH
+functionality without requiring driver changes.
+
+Co-developed-by: Robert Richter <rrichter@amd.com>
+Signed-off-by: Robert Richter <rrichter@amd.com>
+Signed-off-by: Terry Bowman <terry.bowman@amd.com>
+Tested-by: Jean Delvare <jdelvare@suse.de>
+Reviewed-by: Jean Delvare <jdelvare@suse.de>
+Reviewed-by: Guenter Roeck <linux@roeck-us.net>
+Link: https://lore.kernel.org/r/20220202153525.1693378-5-terry.bowman@amd.com
+Signed-off-by: Guenter Roeck <linux@roeck-us.net>
+Signed-off-by: Wim Van Sebroeck <wim@linux-watchdog.org>
+Cc: Mario Limonciello <Mario.Limonciello@amd.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/watchdog/sp5100_tco.c |   16 ++++------------
+ drivers/watchdog/sp5100_tco.h |    1 +
+ 2 files changed, 5 insertions(+), 12 deletions(-)
+
+--- a/drivers/watchdog/sp5100_tco.c
++++ b/drivers/watchdog/sp5100_tco.c
+@@ -86,6 +86,10 @@ static enum tco_reg_layout tco_reg_layou
+           dev->revision < 0x40) {
+               return sp5100;
+       } else if (dev->vendor == PCI_VENDOR_ID_AMD &&
++          sp5100_tco_pci->device == PCI_DEVICE_ID_AMD_KERNCZ_SMBUS &&
++          sp5100_tco_pci->revision >= AMD_ZEN_SMBUS_PCI_REV) {
++              return efch_mmio;
++      } else if (dev->vendor == PCI_VENDOR_ID_AMD &&
+           ((dev->device == PCI_DEVICE_ID_AMD_HUDSON2_SMBUS &&
+            dev->revision >= 0x41) ||
+           (dev->device == PCI_DEVICE_ID_AMD_KERNCZ_SMBUS &&
+@@ -451,18 +455,6 @@ static int sp5100_tco_setupdevice(struct
+               break;
+       case efch:
+               dev_name = SB800_DEVNAME;
+-              /*
+-               * On Family 17h devices, the EFCH_PM_DECODEEN_WDT_TMREN bit of
+-               * EFCH_PM_DECODEEN not only enables the EFCH_PM_WDT_ADDR memory
+-               * region, it also enables the watchdog itself.
+-               */
+-              if (boot_cpu_data.x86 == 0x17) {
+-                      val = sp5100_tco_read_pm_reg8(EFCH_PM_DECODEEN);
+-                      if (!(val & EFCH_PM_DECODEEN_WDT_TMREN)) {
+-                              sp5100_tco_update_pm_reg8(EFCH_PM_DECODEEN, 0xff,
+-                                                        EFCH_PM_DECODEEN_WDT_TMREN);
+-                      }
+-              }
+               val = sp5100_tco_read_pm_reg8(EFCH_PM_DECODEEN);
+               if (val & EFCH_PM_DECODEEN_WDT_TMREN)
+                       mmio_addr = EFCH_PM_WDT_ADDR;
+--- a/drivers/watchdog/sp5100_tco.h
++++ b/drivers/watchdog/sp5100_tco.h
+@@ -89,3 +89,4 @@
+ #define EFCH_PM_ACPI_MMIO_PM_ADDR     (EFCH_PM_ACPI_MMIO_ADDR +       \
+                                        EFCH_PM_ACPI_MMIO_PM_OFFSET)
+ #define EFCH_PM_ACPI_MMIO_PM_SIZE     8
++#define AMD_ZEN_SMBUS_PCI_REV         0x51
diff --git a/queue-5.15/watchdog-sp5100_tco-move-timer-initialization-into-function.patch b/queue-5.15/watchdog-sp5100_tco-move-timer-initialization-into-function.patch
new file mode 100644 (file)
index 0000000..4dc8ac6
--- /dev/null
@@ -0,0 +1,109 @@
+From abd71a948f7aab47ca49d3e7fe6afa6c48c8aae0 Mon Sep 17 00:00:00 2001
+From: Terry Bowman <terry.bowman@amd.com>
+Date: Wed, 2 Feb 2022 09:35:22 -0600
+Subject: Watchdog: sp5100_tco: Move timer initialization into function
+
+From: Terry Bowman <terry.bowman@amd.com>
+
+commit abd71a948f7aab47ca49d3e7fe6afa6c48c8aae0 upstream.
+
+Refactor driver's timer initialization into new function. This is needed
+inorder to support adding new device layouts while using common timer
+initialization.
+
+Co-developed-by: Robert Richter <rrichter@amd.com>
+Signed-off-by: Robert Richter <rrichter@amd.com>
+Signed-off-by: Terry Bowman <terry.bowman@amd.com>
+Tested-by: Jean Delvare <jdelvare@suse.de>
+Reviewed-by: Jean Delvare <jdelvare@suse.de>
+Reviewed-by: Guenter Roeck <linux@roeck-us.net>
+Link: https://lore.kernel.org/r/20220202153525.1693378-2-terry.bowman@amd.com
+Signed-off-by: Guenter Roeck <linux@roeck-us.net>
+Signed-off-by: Wim Van Sebroeck <wim@linux-watchdog.org>
+Cc: Mario Limonciello <Mario.Limonciello@amd.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/watchdog/sp5100_tco.c |   65 +++++++++++++++++++++++-------------------
+ 1 file changed, 36 insertions(+), 29 deletions(-)
+
+--- a/drivers/watchdog/sp5100_tco.c
++++ b/drivers/watchdog/sp5100_tco.c
+@@ -215,6 +215,41 @@ static u32 sp5100_tco_read_pm_reg32(u8 i
+       return val;
+ }
++static int sp5100_tco_timer_init(struct sp5100_tco *tco)
++{
++      struct watchdog_device *wdd = &tco->wdd;
++      struct device *dev = wdd->parent;
++      u32 val;
++
++      val = readl(SP5100_WDT_CONTROL(tco->tcobase));
++      if (val & SP5100_WDT_DISABLED) {
++              dev_err(dev, "Watchdog hardware is disabled\n");
++              return -ENODEV;
++      }
++
++      /*
++       * Save WatchDogFired status, because WatchDogFired flag is
++       * cleared here.
++       */
++      if (val & SP5100_WDT_FIRED)
++              wdd->bootstatus = WDIOF_CARDRESET;
++
++      /* Set watchdog action to reset the system */
++      val &= ~SP5100_WDT_ACTION_RESET;
++      writel(val, SP5100_WDT_CONTROL(tco->tcobase));
++
++      /* Set a reasonable heartbeat before we stop the timer */
++      tco_timer_set_timeout(wdd, wdd->timeout);
++
++      /*
++       * Stop the TCO before we change anything so we don't race with
++       * a zeroed timer.
++       */
++      tco_timer_stop(wdd);
++
++      return 0;
++}
++
+ static int sp5100_tco_setupdevice(struct device *dev,
+                                 struct watchdog_device *wdd)
+ {
+@@ -340,35 +375,7 @@ static int sp5100_tco_setupdevice(struct
+       /* Setup the watchdog timer */
+       tco_timer_enable(tco);
+-      val = readl(SP5100_WDT_CONTROL(tco->tcobase));
+-      if (val & SP5100_WDT_DISABLED) {
+-              dev_err(dev, "Watchdog hardware is disabled\n");
+-              ret = -ENODEV;
+-              goto unreg_region;
+-      }
+-
+-      /*
+-       * Save WatchDogFired status, because WatchDogFired flag is
+-       * cleared here.
+-       */
+-      if (val & SP5100_WDT_FIRED)
+-              wdd->bootstatus = WDIOF_CARDRESET;
+-      /* Set watchdog action to reset the system */
+-      val &= ~SP5100_WDT_ACTION_RESET;
+-      writel(val, SP5100_WDT_CONTROL(tco->tcobase));
+-
+-      /* Set a reasonable heartbeat before we stop the timer */
+-      tco_timer_set_timeout(wdd, wdd->timeout);
+-
+-      /*
+-       * Stop the TCO before we change anything so we don't race with
+-       * a zeroed timer.
+-       */
+-      tco_timer_stop(wdd);
+-
+-      release_region(SP5100_IO_PM_INDEX_REG, SP5100_PM_IOPORTS_SIZE);
+-
+-      return 0;
++      ret = sp5100_tco_timer_init(tco);
+ unreg_region:
+       release_region(SP5100_IO_PM_INDEX_REG, SP5100_PM_IOPORTS_SIZE);
diff --git a/queue-5.15/watchdog-sp5100_tco-refactor-mmio-base-address-initialization.patch b/queue-5.15/watchdog-sp5100_tco-refactor-mmio-base-address-initialization.patch
new file mode 100644 (file)
index 0000000..72c1844
--- /dev/null
@@ -0,0 +1,240 @@
+From 1f182aca230086d4a4469c0f9136a6ea762d6385 Mon Sep 17 00:00:00 2001
+From: Terry Bowman <terry.bowman@amd.com>
+Date: Wed, 2 Feb 2022 09:35:23 -0600
+Subject: Watchdog: sp5100_tco: Refactor MMIO base address initialization
+
+From: Terry Bowman <terry.bowman@amd.com>
+
+commit 1f182aca230086d4a4469c0f9136a6ea762d6385 upstream.
+
+Combine MMIO base address and alternate base address detection. Combine
+based on layout type. This will simplify the function by eliminating
+a switch case.
+
+Move existing request/release code into functions. This currently only
+supports port I/O request/release. The move into a separate function
+will make it ready for adding MMIO region support.
+
+Co-developed-by: Robert Richter <rrichter@amd.com>
+Signed-off-by: Robert Richter <rrichter@amd.com>
+Signed-off-by: Terry Bowman <terry.bowman@amd.com>
+Tested-by: Jean Delvare <jdelvare@suse.de>
+Reviewed-by: Jean Delvare <jdelvare@suse.de>
+Reviewed-by: Guenter Roeck <linux@roeck-us.net>
+Link: https://lore.kernel.org/r/20220202153525.1693378-3-terry.bowman@amd.com
+Signed-off-by: Guenter Roeck <linux@roeck-us.net>
+Signed-off-by: Wim Van Sebroeck <wim@linux-watchdog.org>
+Cc: Mario Limonciello <Mario.Limonciello@amd.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/watchdog/sp5100_tco.c |  155 +++++++++++++++++++++---------------------
+ drivers/watchdog/sp5100_tco.h |    1 
+ 2 files changed, 82 insertions(+), 74 deletions(-)
+
+--- a/drivers/watchdog/sp5100_tco.c
++++ b/drivers/watchdog/sp5100_tco.c
+@@ -215,6 +215,55 @@ static u32 sp5100_tco_read_pm_reg32(u8 i
+       return val;
+ }
++static u32 sp5100_tco_request_region(struct device *dev,
++                                   u32 mmio_addr,
++                                   const char *dev_name)
++{
++      if (!devm_request_mem_region(dev, mmio_addr, SP5100_WDT_MEM_MAP_SIZE,
++                                   dev_name)) {
++              dev_dbg(dev, "MMIO address 0x%08x already in use\n", mmio_addr);
++              return 0;
++      }
++
++      return mmio_addr;
++}
++
++static u32 sp5100_tco_prepare_base(struct sp5100_tco *tco,
++                                 u32 mmio_addr,
++                                 u32 alt_mmio_addr,
++                                 const char *dev_name)
++{
++      struct device *dev = tco->wdd.parent;
++
++      dev_dbg(dev, "Got 0x%08x from SBResource_MMIO register\n", mmio_addr);
++
++      if (!mmio_addr && !alt_mmio_addr)
++              return -ENODEV;
++
++      /* Check for MMIO address and alternate MMIO address conflicts */
++      if (mmio_addr)
++              mmio_addr = sp5100_tco_request_region(dev, mmio_addr, dev_name);
++
++      if (!mmio_addr && alt_mmio_addr)
++              mmio_addr = sp5100_tco_request_region(dev, alt_mmio_addr, dev_name);
++
++      if (!mmio_addr) {
++              dev_err(dev, "Failed to reserve MMIO or alternate MMIO region\n");
++              return -EBUSY;
++      }
++
++      tco->tcobase = devm_ioremap(dev, mmio_addr, SP5100_WDT_MEM_MAP_SIZE);
++      if (!tco->tcobase) {
++              dev_err(dev, "MMIO address 0x%08x failed mapping\n", mmio_addr);
++              devm_release_mem_region(dev, mmio_addr, SP5100_WDT_MEM_MAP_SIZE);
++              return -ENOMEM;
++      }
++
++      dev_info(dev, "Using 0x%08x for watchdog MMIO address\n", mmio_addr);
++
++      return 0;
++}
++
+ static int sp5100_tco_timer_init(struct sp5100_tco *tco)
+ {
+       struct watchdog_device *wdd = &tco->wdd;
+@@ -256,6 +305,7 @@ static int sp5100_tco_setupdevice(struct
+       struct sp5100_tco *tco = watchdog_get_drvdata(wdd);
+       const char *dev_name;
+       u32 mmio_addr = 0, val;
++      u32 alt_mmio_addr = 0;
+       int ret;
+       /* Request the IO ports used by this driver */
+@@ -274,11 +324,32 @@ static int sp5100_tco_setupdevice(struct
+               dev_name = SP5100_DEVNAME;
+               mmio_addr = sp5100_tco_read_pm_reg32(SP5100_PM_WATCHDOG_BASE) &
+                                                               0xfffffff8;
++
++              /*
++               * Secondly, find the watchdog timer MMIO address
++               * from SBResource_MMIO register.
++               */
++
++              /* Read SBResource_MMIO from PCI config(PCI_Reg: 9Ch) */
++              pci_read_config_dword(sp5100_tco_pci,
++                                    SP5100_SB_RESOURCE_MMIO_BASE,
++                                    &val);
++
++              /* Verify MMIO is enabled and using bar0 */
++              if ((val & SB800_ACPI_MMIO_MASK) == SB800_ACPI_MMIO_DECODE_EN)
++                      alt_mmio_addr = (val & ~0xfff) + SB800_PM_WDT_MMIO_OFFSET;
+               break;
+       case sb800:
+               dev_name = SB800_DEVNAME;
+               mmio_addr = sp5100_tco_read_pm_reg32(SB800_PM_WATCHDOG_BASE) &
+                                                               0xfffffff8;
++
++              /* Read SBResource_MMIO from AcpiMmioEn(PM_Reg: 24h) */
++              val = sp5100_tco_read_pm_reg32(SB800_PM_ACPI_MMIO_EN);
++
++              /* Verify MMIO is enabled and using bar0 */
++              if ((val & SB800_ACPI_MMIO_MASK) == SB800_ACPI_MMIO_DECODE_EN)
++                      alt_mmio_addr = (val & ~0xfff) + SB800_PM_WDT_MMIO_OFFSET;
+               break;
+       case efch:
+               dev_name = SB800_DEVNAME;
+@@ -297,87 +368,23 @@ static int sp5100_tco_setupdevice(struct
+               val = sp5100_tco_read_pm_reg8(EFCH_PM_DECODEEN);
+               if (val & EFCH_PM_DECODEEN_WDT_TMREN)
+                       mmio_addr = EFCH_PM_WDT_ADDR;
++
++              val = sp5100_tco_read_pm_reg8(EFCH_PM_ISACONTROL);
++              if (val & EFCH_PM_ISACONTROL_MMIOEN)
++                      alt_mmio_addr = EFCH_PM_ACPI_MMIO_ADDR +
++                              EFCH_PM_ACPI_MMIO_WDT_OFFSET;
+               break;
+       default:
+               return -ENODEV;
+       }
+-      /* Check MMIO address conflict */
+-      if (!mmio_addr ||
+-          !devm_request_mem_region(dev, mmio_addr, SP5100_WDT_MEM_MAP_SIZE,
+-                                   dev_name)) {
+-              if (mmio_addr)
+-                      dev_dbg(dev, "MMIO address 0x%08x already in use\n",
+-                              mmio_addr);
+-              switch (tco->tco_reg_layout) {
+-              case sp5100:
+-                      /*
+-                       * Secondly, Find the watchdog timer MMIO address
+-                       * from SBResource_MMIO register.
+-                       */
+-                      /* Read SBResource_MMIO from PCI config(PCI_Reg: 9Ch) */
+-                      pci_read_config_dword(sp5100_tco_pci,
+-                                            SP5100_SB_RESOURCE_MMIO_BASE,
+-                                            &mmio_addr);
+-                      if ((mmio_addr & (SB800_ACPI_MMIO_DECODE_EN |
+-                                        SB800_ACPI_MMIO_SEL)) !=
+-                                                SB800_ACPI_MMIO_DECODE_EN) {
+-                              ret = -ENODEV;
+-                              goto unreg_region;
+-                      }
+-                      mmio_addr &= ~0xFFF;
+-                      mmio_addr += SB800_PM_WDT_MMIO_OFFSET;
+-                      break;
+-              case sb800:
+-                      /* Read SBResource_MMIO from AcpiMmioEn(PM_Reg: 24h) */
+-                      mmio_addr =
+-                              sp5100_tco_read_pm_reg32(SB800_PM_ACPI_MMIO_EN);
+-                      if ((mmio_addr & (SB800_ACPI_MMIO_DECODE_EN |
+-                                        SB800_ACPI_MMIO_SEL)) !=
+-                                                SB800_ACPI_MMIO_DECODE_EN) {
+-                              ret = -ENODEV;
+-                              goto unreg_region;
+-                      }
+-                      mmio_addr &= ~0xFFF;
+-                      mmio_addr += SB800_PM_WDT_MMIO_OFFSET;
+-                      break;
+-              case efch:
+-                      val = sp5100_tco_read_pm_reg8(EFCH_PM_ISACONTROL);
+-                      if (!(val & EFCH_PM_ISACONTROL_MMIOEN)) {
+-                              ret = -ENODEV;
+-                              goto unreg_region;
+-                      }
+-                      mmio_addr = EFCH_PM_ACPI_MMIO_ADDR +
+-                                  EFCH_PM_ACPI_MMIO_WDT_OFFSET;
+-                      break;
+-              }
+-              dev_dbg(dev, "Got 0x%08x from SBResource_MMIO register\n",
+-                      mmio_addr);
+-              if (!devm_request_mem_region(dev, mmio_addr,
+-                                           SP5100_WDT_MEM_MAP_SIZE,
+-                                           dev_name)) {
+-                      dev_dbg(dev, "MMIO address 0x%08x already in use\n",
+-                              mmio_addr);
+-                      ret = -EBUSY;
+-                      goto unreg_region;
+-              }
++      ret = sp5100_tco_prepare_base(tco, mmio_addr, alt_mmio_addr, dev_name);
++      if (!ret) {
++              /* Setup the watchdog timer */
++              tco_timer_enable(tco);
++              ret = sp5100_tco_timer_init(tco);
+       }
+-      tco->tcobase = devm_ioremap(dev, mmio_addr, SP5100_WDT_MEM_MAP_SIZE);
+-      if (!tco->tcobase) {
+-              dev_err(dev, "failed to get tcobase address\n");
+-              ret = -ENOMEM;
+-              goto unreg_region;
+-      }
+-
+-      dev_info(dev, "Using 0x%08x for watchdog MMIO address\n", mmio_addr);
+-
+-      /* Setup the watchdog timer */
+-      tco_timer_enable(tco);
+-
+-      ret = sp5100_tco_timer_init(tco);
+-
+-unreg_region:
+       release_region(SP5100_IO_PM_INDEX_REG, SP5100_PM_IOPORTS_SIZE);
+       return ret;
+ }
+--- a/drivers/watchdog/sp5100_tco.h
++++ b/drivers/watchdog/sp5100_tco.h
+@@ -58,6 +58,7 @@
+ #define SB800_PM_WATCHDOG_SECOND_RES  GENMASK(1, 0)
+ #define SB800_ACPI_MMIO_DECODE_EN     BIT(0)
+ #define SB800_ACPI_MMIO_SEL           BIT(1)
++#define SB800_ACPI_MMIO_MASK          GENMASK(1, 0)
+ #define SB800_PM_WDT_MMIO_OFFSET      0xB00