From: Greg Kroah-Hartman Date: Thu, 19 May 2022 12:57:39 +0000 (+0200) Subject: 5.17-stable patches X-Git-Tag: v4.9.316~63 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=fa755afe709752b4c8f31988970b74696cb4ec9d;p=thirdparty%2Fkernel%2Fstable-queue.git 5.17-stable patches 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 kernel-resource-introduce-request_mem_region_muxed.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 --- diff --git a/queue-5.17/floppy-use-a-statically-allocated-error-counter.patch b/queue-5.17/floppy-use-a-statically-allocated-error-counter.patch new file mode 100644 index 00000000000..2c29de40005 --- /dev/null +++ b/queue-5.17/floppy-use-a-statically-allocated-error-counter.patch @@ -0,0 +1,105 @@ +From f71f01394f742fc4558b3f9f4c7ef4c4cf3b07c8 Mon Sep 17 00:00:00 2001 +From: Willy Tarreau +Date: Sun, 8 May 2022 11:37:07 +0200 +Subject: floppy: use a statically allocated error counter + +From: Willy Tarreau + +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 +Suggested-by: Linus Torvalds +Tested-by: Denis Efremov +Signed-off-by: Willy Tarreau +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman +--- + 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(¤t_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.17/i2c-piix4-add-efch-mmio-support-for-smbus-port-select.patch b/queue-5.17/i2c-piix4-add-efch-mmio-support-for-smbus-port-select.patch new file mode 100644 index 00000000000..78d212ea28f --- /dev/null +++ b/queue-5.17/i2c-piix4-add-efch-mmio-support-for-smbus-port-select.patch @@ -0,0 +1,63 @@ +From 381a3083c6747ae5cdbef9b176d57d1b966db49f Mon Sep 17 00:00:00 2001 +From: Terry Bowman +Date: Wed, 9 Feb 2022 11:27:16 -0600 +Subject: i2c: piix4: Add EFCH MMIO support for SMBus port select + +From: Terry Bowman + +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 +Reviewed-by: Andy Shevchenko +Reviewed-by: Jean Delvare +Signed-off-by: Wolfram Sang +Cc: Mario Limonciello +Signed-off-by: Greg Kroah-Hartman +--- + 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.17/i2c-piix4-add-efch-mmio-support-to-region-request-and-release.patch b/queue-5.17/i2c-piix4-add-efch-mmio-support-to-region-request-and-release.patch new file mode 100644 index 00000000000..b1bb2f7dfb9 --- /dev/null +++ b/queue-5.17/i2c-piix4-add-efch-mmio-support-to-region-request-and-release.patch @@ -0,0 +1,182 @@ +From 7c148722d074c29fb998578eea5de3c14b9608c9 Mon Sep 17 00:00:00 2001 +From: Terry Bowman +Date: Wed, 9 Feb 2022 11:27:14 -0600 +Subject: i2c: piix4: Add EFCH MMIO support to region request and release + +From: Terry Bowman + +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 +Reviewed-by: Andy Shevchenko +Reviewed-by: Jean Delvare +[wsa: rebased after fixup in previous patch] +Signed-off-by: Wolfram Sang +Cc: Mario Limonciello +Signed-off-by: Greg Kroah-Hartman +--- + 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.17/i2c-piix4-add-efch-mmio-support-to-smbus-base-address-detect.patch b/queue-5.17/i2c-piix4-add-efch-mmio-support-to-smbus-base-address-detect.patch new file mode 100644 index 00000000000..6a93f446751 --- /dev/null +++ b/queue-5.17/i2c-piix4-add-efch-mmio-support-to-smbus-base-address-detect.patch @@ -0,0 +1,47 @@ +From 46967bc1ee93acd1d8953c87dc16f43de4076f93 Mon Sep 17 00:00:00 2001 +From: Terry Bowman +Date: Wed, 9 Feb 2022 11:27:15 -0600 +Subject: i2c: piix4: Add EFCH MMIO support to SMBus base address detect + +From: Terry Bowman + +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 +Reviewed-by: Andy Shevchenko +Reviewed-by: Jean Delvare +Signed-off-by: Wolfram Sang +Cc: Mario Limonciello +Signed-off-by: Greg Kroah-Hartman +--- + 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.17/i2c-piix4-enable-efch-mmio-for-family-17h.patch b/queue-5.17/i2c-piix4-enable-efch-mmio-for-family-17h.patch new file mode 100644 index 00000000000..3f3cdb2aae9 --- /dev/null +++ b/queue-5.17/i2c-piix4-enable-efch-mmio-for-family-17h.patch @@ -0,0 +1,70 @@ +From 6cf72f41808ab5db1d7718b999b3ff0166e67e45 Mon Sep 17 00:00:00 2001 +From: Terry Bowman +Date: Wed, 9 Feb 2022 11:27:17 -0600 +Subject: i2c: piix4: Enable EFCH MMIO for Family 17h+ + +From: Terry Bowman + +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 +Reviewed-by: Andy Shevchenko +Reviewed-by: Jean Delvare +Signed-off-by: Wolfram Sang +Cc: Mario Limonciello +Signed-off-by: Greg Kroah-Hartman +--- + 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.17/i2c-piix4-move-port-i-o-region-request-release-code-into-functions.patch b/queue-5.17/i2c-piix4-move-port-i-o-region-request-release-code-into-functions.patch new file mode 100644 index 00000000000..e063de23ddb --- /dev/null +++ b/queue-5.17/i2c-piix4-move-port-i-o-region-request-release-code-into-functions.patch @@ -0,0 +1,129 @@ +From a3325d225b00889f4b7fdb25d83033cae1048a92 Mon Sep 17 00:00:00 2001 +From: Terry Bowman +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 + +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 +Reviewed-by: Andy Shevchenko +Reviewed-by: Jean Delvare +[wsa: added missing curly brace] +Signed-off-by: Wolfram Sang +Cc: Mario Limonciello +Signed-off-by: Greg Kroah-Hartman +--- + 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.17/i2c-piix4-move-smbus-controller-base-address-detect-into-function.patch b/queue-5.17/i2c-piix4-move-smbus-controller-base-address-detect-into-function.patch new file mode 100644 index 00000000000..832397f6b70 --- /dev/null +++ b/queue-5.17/i2c-piix4-move-smbus-controller-base-address-detect-into-function.patch @@ -0,0 +1,114 @@ +From 0a59a24e14e9b21dcbb6b8ea41422e2fdfa437fd Mon Sep 17 00:00:00 2001 +From: Terry Bowman +Date: Wed, 9 Feb 2022 11:27:12 -0600 +Subject: i2c: piix4: Move SMBus controller base address detect into function + +From: Terry Bowman + +commit 0a59a24e14e9b21dcbb6b8ea41422e2fdfa437fd upstream. + +Move SMBus controller base address detection into function. Refactor +is in preparation for following MMIO changes. + +Signed-off-by: Terry Bowman +Reviewed-by: Andy Shevchenko +Reviewed-by: Jean Delvare +Signed-off-by: Wolfram Sang +Cc: Mario Limonciello +Signed-off-by: Greg Kroah-Hartman +--- + 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.17/i2c-piix4-move-smbus-port-selection-into-function.patch b/queue-5.17/i2c-piix4-move-smbus-port-selection-into-function.patch new file mode 100644 index 00000000000..39fc24cba1b --- /dev/null +++ b/queue-5.17/i2c-piix4-move-smbus-port-selection-into-function.patch @@ -0,0 +1,76 @@ +From fbafbd51bff52cb3a920fd98d4dae2a78dd433d0 Mon Sep 17 00:00:00 2001 +From: Terry Bowman +Date: Wed, 9 Feb 2022 11:27:13 -0600 +Subject: i2c: piix4: Move SMBus port selection into function + +From: Terry Bowman + +commit fbafbd51bff52cb3a920fd98d4dae2a78dd433d0 upstream. + +Move port selection code into a separate function. Refactor is in +preparation for following MMIO changes. + +Signed-off-by: Terry Bowman +Reviewed-by: Andy Shevchenko +Reviewed-by: Jean Delvare +Signed-off-by: Wolfram Sang +Cc: Mario Limonciello +Signed-off-by: Greg Kroah-Hartman +--- + 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.17/i2c-piix4-replace-hardcoded-memory-map-size-with-a-define.patch b/queue-5.17/i2c-piix4-replace-hardcoded-memory-map-size-with-a-define.patch new file mode 100644 index 00000000000..f05ef3bfc9b --- /dev/null +++ b/queue-5.17/i2c-piix4-replace-hardcoded-memory-map-size-with-a-define.patch @@ -0,0 +1,89 @@ +From 93102cb449780f7b4eecf713451627b78373ce49 Mon Sep 17 00:00:00 2001 +From: Terry Bowman +Date: Wed, 9 Feb 2022 11:27:10 -0600 +Subject: i2c: piix4: Replace hardcoded memory map size with a #define + +From: Terry Bowman + +commit 93102cb449780f7b4eecf713451627b78373ce49 upstream. + +Replace number constant with #define to improve readability and +maintainability. + +Signed-off-by: Terry Bowman +Reviewed-by: Andy Shevchenko +Reviewed-by: Jean Delvare +Signed-off-by: Wolfram Sang +Cc: Mario Limonciello +Signed-off-by: Greg Kroah-Hartman +--- + 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.17/kernel-resource-introduce-request_mem_region_muxed.patch b/queue-5.17/kernel-resource-introduce-request_mem_region_muxed.patch new file mode 100644 index 00000000000..f77f036313f --- /dev/null +++ b/queue-5.17/kernel-resource-introduce-request_mem_region_muxed.patch @@ -0,0 +1,38 @@ +From 27c196c7b73cb70bbed3a9df46563bab60e63415 Mon Sep 17 00:00:00 2001 +From: Terry Bowman +Date: Wed, 9 Feb 2022 11:27:09 -0600 +Subject: kernel/resource: Introduce request_mem_region_muxed() + +From: Terry Bowman + +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 +Reviewed-by: Andy Shevchenko +Signed-off-by: Wolfram Sang +Cc: Mario Limonciello +Signed-off-by: Greg Kroah-Hartman +--- + 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.17/series b/queue-5.17/series index 7ac09b3bef6..79c3a60d7bd 100644 --- a/queue-5.17/series +++ b/queue-5.17/series @@ -1 +1,15 @@ usb-gadget-fix-race-when-gadget-driver-register-via-ioctl.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 diff --git a/queue-5.17/watchdog-sp5100_tco-add-initialization-using-efch-mmio.patch b/queue-5.17/watchdog-sp5100_tco-add-initialization-using-efch-mmio.patch new file mode 100644 index 00000000000..1dbecb35c95 --- /dev/null +++ b/queue-5.17/watchdog-sp5100_tco-add-initialization-using-efch-mmio.patch @@ -0,0 +1,172 @@ +From 0578fff4aae5bce3f09875f58e68e9ffbab8daf5 Mon Sep 17 00:00:00 2001 +From: Terry Bowman +Date: Wed, 2 Feb 2022 09:35:24 -0600 +Subject: Watchdog: sp5100_tco: Add initialization using EFCH MMIO + +From: Terry Bowman + +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 +Signed-off-by: Robert Richter +Signed-off-by: Terry Bowman +Tested-by: Jean Delvare +Reviewed-by: Jean Delvare +Reviewed-by: Guenter Roeck +Link: https://lore.kernel.org/r/20220202153525.1693378-4-terry.bowman@amd.com +Signed-off-by: Guenter Roeck +Signed-off-by: Wim Van Sebroeck +Cc: Mario Limonciello +Signed-off-by: Greg Kroah-Hartman +--- + 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 +@@ -49,7 +49,7 @@ + /* internal variables */ + + enum tco_reg_layout { +- sp5100, sb800, efch ++ sp5100, sb800, efch, efch_mmio + }; + + struct sp5100_tco { +@@ -209,6 +209,8 @@ static void tco_timer_enable(struct sp51 + ~EFCH_PM_WATCHDOG_DISABLE, + EFCH_PM_DECODEEN_SECOND_RES); + break; ++ default: ++ break; + } + } + +@@ -307,6 +309,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) + { +@@ -316,6 +411,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.17/watchdog-sp5100_tco-enable-family-17h-cpus.patch b/queue-5.17/watchdog-sp5100_tco-enable-family-17h-cpus.patch new file mode 100644 index 00000000000..1d996dbeebd --- /dev/null +++ b/queue-5.17/watchdog-sp5100_tco-enable-family-17h-cpus.patch @@ -0,0 +1,75 @@ +From 826270373f17fd8ebd10753ca0a5fd2ceb1dc38e Mon Sep 17 00:00:00 2001 +From: Terry Bowman +Date: Wed, 2 Feb 2022 09:35:25 -0600 +Subject: Watchdog: sp5100_tco: Enable Family 17h+ CPUs + +From: Terry Bowman + +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 +Signed-off-by: Robert Richter +Signed-off-by: Terry Bowman +Tested-by: Jean Delvare +Reviewed-by: Jean Delvare +Reviewed-by: Guenter Roeck +Link: https://lore.kernel.org/r/20220202153525.1693378-5-terry.bowman@amd.com +Signed-off-by: Guenter Roeck +Signed-off-by: Wim Van Sebroeck +Cc: Mario Limonciello +Signed-off-by: Greg Kroah-Hartman +--- + 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 +@@ -87,6 +87,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 && +@@ -459,18 +463,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.17/watchdog-sp5100_tco-move-timer-initialization-into-function.patch b/queue-5.17/watchdog-sp5100_tco-move-timer-initialization-into-function.patch new file mode 100644 index 00000000000..f0b33022f39 --- /dev/null +++ b/queue-5.17/watchdog-sp5100_tco-move-timer-initialization-into-function.patch @@ -0,0 +1,109 @@ +From abd71a948f7aab47ca49d3e7fe6afa6c48c8aae0 Mon Sep 17 00:00:00 2001 +From: Terry Bowman +Date: Wed, 2 Feb 2022 09:35:22 -0600 +Subject: Watchdog: sp5100_tco: Move timer initialization into function + +From: Terry Bowman + +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 +Signed-off-by: Robert Richter +Signed-off-by: Terry Bowman +Tested-by: Jean Delvare +Reviewed-by: Jean Delvare +Reviewed-by: Guenter Roeck +Link: https://lore.kernel.org/r/20220202153525.1693378-2-terry.bowman@amd.com +Signed-off-by: Guenter Roeck +Signed-off-by: Wim Van Sebroeck +Cc: Mario Limonciello +Signed-off-by: Greg Kroah-Hartman +--- + 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 +@@ -223,6 +223,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) + { +@@ -348,35 +383,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.17/watchdog-sp5100_tco-refactor-mmio-base-address-initialization.patch b/queue-5.17/watchdog-sp5100_tco-refactor-mmio-base-address-initialization.patch new file mode 100644 index 00000000000..fc39dcbb7b9 --- /dev/null +++ b/queue-5.17/watchdog-sp5100_tco-refactor-mmio-base-address-initialization.patch @@ -0,0 +1,240 @@ +From 1f182aca230086d4a4469c0f9136a6ea762d6385 Mon Sep 17 00:00:00 2001 +From: Terry Bowman +Date: Wed, 2 Feb 2022 09:35:23 -0600 +Subject: Watchdog: sp5100_tco: Refactor MMIO base address initialization + +From: Terry Bowman + +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 +Signed-off-by: Robert Richter +Signed-off-by: Terry Bowman +Tested-by: Jean Delvare +Reviewed-by: Jean Delvare +Reviewed-by: Guenter Roeck +Link: https://lore.kernel.org/r/20220202153525.1693378-3-terry.bowman@amd.com +Signed-off-by: Guenter Roeck +Signed-off-by: Wim Van Sebroeck +Cc: Mario Limonciello +Signed-off-by: Greg Kroah-Hartman +--- + 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 +@@ -223,6 +223,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; +@@ -264,6 +313,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 */ +@@ -282,11 +332,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; +@@ -305,87 +376,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 +