Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1614950 > unrolled thread
| Started by | Zoltan Boszormenyi <zboszor@pr.hu> |
|---|---|
| First post | 2017-04-03 10:00 +0200 |
| Last post | 2017-04-03 10:00 +0200 |
| Articles | 3 — 1 participant |
Back to article view | Back to linux.kernel
This discussion starts older than the indexed window; earlier articles aren't shown. The article labeled Started by
below is the oldest one visible, not the original post.
[PATCH 0/3 v2] Fix regression in the sp5100_tco driver Zoltan Boszormenyi <zboszor@pr.hu> - 2017-04-03 10:00 +0200
[PATCH 1/3 v2] usb: pci-quirks: Add a common mutex for the I/O port pair of SB800 Zoltan Boszormenyi <zboszor@pr.hu> - 2017-04-03 10:00 +0200
[PATCH 3/3 v2] watchdog: sp5100_tco: Use the common mutex Zoltan Boszormenyi <zboszor@pr.hu> - 2017-04-03 10:00 +0200
| From | Zoltan Boszormenyi <zboszor@pr.hu> |
|---|---|
| Date | 2017-04-03 10:00 +0200 |
| Subject | [PATCH 0/3 v2] Fix regression in the sp5100_tco driver |
| Message-ID | <ts545-3XB-5@gated-at.bofh.it> |
Three drivers are accessing the same I/O ports (0xcd6 / 0xcd7) on
AMD SB800 based machines without synchronization or with excluding
each other out:
* the USB quirk for isochronous transfers on SB800 (no locking)
* sp5100_tco (request_region)
* i2c-piix4 (request_region)
Historically, the sp5100_tco watchdog driver used request_region()
for these I/O ports but an i2c-piix4 improvement for SB800 in
Linux 4.4-rc4 also added a request_region() call. Because of this
and the load order, this cause a regression and the watchdog function
became non-functional. The commit that caused the regression is:
commit 2fee61d22e606fc99ade9079fda15fdee83ec33e
Author: Christian Fetzer <fetzer.ch@gmail.com>
Date: Thu Nov 19 20:13:48 2015 +0100
i2c: piix4: Add support for multiplexed main adapter in SB800
I was informed by Guenter Roeck <linux@roeck-us.net> that the
alternative, i.e. using request_muxed_region() can fail, either
because of a resource allocation failure, which is quite possible
with long uptimes, or because there are no guarantees that an as yet
unknown driver would also use request_muxed_region() consistently.
Because of this, a solution using a common mutex was chosen to
synchronize I/O port accesses and request_region() calls are removed
from both i2c-piix4 and sp5100_tco to make the code uniform.
This patch series implements this and restores the watchdog function.
v2: Don't introduce a new header, reference sb800_mutex explicitly
Signed-off-by: Zoltan Boszormenyi <zboszor@pr.hu>
drivers/i2c/busses/i2c-piix4.c | 43 +++++++++++++------------------------------
drivers/usb/host/pci-quirks.c | 5 +++++
drivers/watchdog/sp5100_tco.c | 31 ++++++++++++++++++-------------
3 files changed, 36 insertions(+), 43 deletions(-)
[toc] | [next] | [standalone]
| From | Zoltan Boszormenyi <zboszor@pr.hu> |
|---|---|
| Date | 2017-04-03 10:00 +0200 |
| Subject | [PATCH 1/3 v2] usb: pci-quirks: Add a common mutex for the I/O port pair of SB800 |
| Message-ID | <ts545-3XB-7@gated-at.bofh.it> |
| In reply to | #1614950 |
This patch adds a common mutex in the USB PCI quirks code and starts
using it to synchronize access to the I/O port pair 0xcd6 / 0xcd7 on
SB800.
These I/O ports are also used by i2c-piix4 and sp5100_tco, the next
two patches port these drivers to use this common mutex.
v2: No extra header and no wrapper for mutex_lock() / mutex_unlock()
Signed-off-by: Zoltan Boszormenyi <zboszor@pr.hu>
---
drivers/usb/host/pci-quirks.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c
index a9a1e4c..1ef0ada 100644
--- a/drivers/usb/host/pci-quirks.c
+++ b/drivers/usb/host/pci-quirks.c
@@ -279,6 +279,9 @@ bool usb_amd_prefetch_quirk(void)
}
EXPORT_SYMBOL_GPL(usb_amd_prefetch_quirk);
+DEFINE_MUTEX(sb800_mutex);
+EXPORT_SYMBOL_GPL(sb800_mutex);
+
/*
* The hardware normally enables the A-link power management feature, which
* lets the system lower the power consumption in idle states.
@@ -314,11 +317,13 @@ static void usb_amd_quirk_pll(int disable)
if (amd_chipset.sb_type.gen == AMD_CHIPSET_SB800 ||
amd_chipset.sb_type.gen == AMD_CHIPSET_HUDSON2 ||
amd_chipset.sb_type.gen == AMD_CHIPSET_BOLTON) {
+ mutex_lock(&sb800_mutex);
outb_p(AB_REG_BAR_LOW, 0xcd6);
addr_low = inb_p(0xcd7);
outb_p(AB_REG_BAR_HIGH, 0xcd6);
addr_high = inb_p(0xcd7);
addr = addr_high << 8 | addr_low;
+ mutex_unlock(&sb800_mutex);
outl_p(0x30, AB_INDX(addr));
outl_p(0x40, AB_DATA(addr));
--
2.9.3
[toc] | [prev] | [next] | [standalone]
| From | Zoltan Boszormenyi <zboszor@pr.hu> |
|---|---|
| Date | 2017-04-03 10:00 +0200 |
| Subject | [PATCH 3/3 v2] watchdog: sp5100_tco: Use the common mutex |
| Message-ID | <ts546-3XB-19@gated-at.bofh.it> |
| In reply to | #1614950 |
Use the common mutex from usb/host/pci-quirks.c to synchronize
accesses to the SB800 I/O port pair (0xcd6 / 0xcd7) with the
PCI quirk for isochronous USB transfers and with the i2c-piix4
driver.
At the same time, remove the request_region() call to reserve
these I/O ports, similarly to i2c-piix4 so the code is now uniform
across the three individual drivers.
v2: Explicit extern reference for sb800_mutex
Signed-off-by: Zoltan Boszormenyi <zboszor@pr.hu>
---
drivers/watchdog/sp5100_tco.c | 31 ++++++++++++++++++-------------
1 file changed, 18 insertions(+), 13 deletions(-)
diff --git a/drivers/watchdog/sp5100_tco.c b/drivers/watchdog/sp5100_tco.c
index 028618c..4dca9e89 100644
--- a/drivers/watchdog/sp5100_tco.c
+++ b/drivers/watchdog/sp5100_tco.c
@@ -36,9 +36,16 @@
#include <linux/platform_device.h>
#include <linux/uaccess.h>
#include <linux/io.h>
+#include <linux/mutex.h>
#include "sp5100_tco.h"
+/*
+ * sb800_mutex in drivers/usb/host/pci-quirks.c protects
+ * parallel access to the I/O port pair 0xCD6 / 0xCD7.
+ */
+extern struct mutex sb800_mutex;
+
/* Module and version information */
#define TCO_VERSION "0.05"
#define TCO_MODULE_NAME "SP5100 TCO timer"
@@ -48,7 +55,6 @@
static u32 tcobase_phys;
static u32 tco_wdt_fired;
static void __iomem *tcobase;
-static unsigned int pm_iobase;
static DEFINE_SPINLOCK(tco_lock); /* Guards the hardware */
static unsigned long timer_alive;
static char tco_expect_close;
@@ -138,6 +144,8 @@ static void tco_timer_enable(void)
if (!tco_has_sp5100_reg_layout(sp5100_tco_pci)) {
/* For SB800 or later */
+ mutex_lock(&sb800_mutex);
+
/* Set the Watchdog timer resolution to 1 sec */
outb(SB800_PM_WATCHDOG_CONFIG, SB800_IO_PM_INDEX_REG);
val = inb(SB800_IO_PM_DATA_REG);
@@ -150,6 +158,8 @@ static void tco_timer_enable(void)
val |= SB800_PCI_WATCHDOG_DECODE_EN;
val &= ~SB800_PM_WATCHDOG_DISABLE;
outb(val, SB800_IO_PM_DATA_REG);
+
+ mutex_unlock(&sb800_mutex);
} else {
/* For SP5100 or SB7x0 */
/* Enable watchdog decode bit */
@@ -164,11 +174,13 @@ static void tco_timer_enable(void)
val);
/* Enable Watchdog timer and set the resolution to 1 sec */
+ mutex_lock(&sb800_mutex);
outb(SP5100_PM_WATCHDOG_CONTROL, SP5100_IO_PM_INDEX_REG);
val = inb(SP5100_IO_PM_DATA_REG);
val |= SP5100_PM_WATCHDOG_SECOND_RES;
val &= ~SP5100_PM_WATCHDOG_DISABLE;
outb(val, SP5100_IO_PM_DATA_REG);
+ mutex_unlock(&sb800_mutex);
}
}
@@ -361,16 +373,10 @@ static unsigned char sp5100_tco_setupdevice(void)
base_addr = SB800_PM_WATCHDOG_BASE;
}
- /* Request the IO ports used by this driver */
- pm_iobase = SP5100_IO_PM_INDEX_REG;
- if (!request_region(pm_iobase, SP5100_PM_IOPORTS_SIZE, dev_name)) {
- pr_err("I/O address 0x%04x already in use\n", pm_iobase);
- goto exit;
- }
-
/*
* First, Find the watchdog timer MMIO address from indirect I/O.
*/
+ mutex_lock(&sb800_mutex);
outb(base_addr+3, index_reg);
val = inb(data_reg);
outb(base_addr+2, index_reg);
@@ -380,6 +386,7 @@ static unsigned char sp5100_tco_setupdevice(void)
outb(base_addr+0, index_reg);
/* Low three bits of BASE are reserved */
val = val << 8 | (inb(data_reg) & 0xf8);
+ mutex_unlock(&sb800_mutex);
pr_debug("Got 0x%04x from indirect I/O\n", val);
@@ -400,6 +407,7 @@ static unsigned char sp5100_tco_setupdevice(void)
SP5100_SB_RESOURCE_MMIO_BASE, &val);
} else {
/* Read SBResource_MMIO from AcpiMmioEn(PM_Reg: 24h) */
+ mutex_lock(&sb800_mutex);
outb(SB800_PM_ACPI_MMIO_EN+3, SB800_IO_PM_INDEX_REG);
val = inb(SB800_IO_PM_DATA_REG);
outb(SB800_PM_ACPI_MMIO_EN+2, SB800_IO_PM_INDEX_REG);
@@ -408,6 +416,7 @@ static unsigned char sp5100_tco_setupdevice(void)
val = val << 8 | inb(SB800_IO_PM_DATA_REG);
outb(SB800_PM_ACPI_MMIO_EN+0, SB800_IO_PM_INDEX_REG);
val = val << 8 | inb(SB800_IO_PM_DATA_REG);
+ mutex_unlock(&sb800_mutex);
}
/* The SBResource_MMIO is enabled and mapped memory space? */
@@ -429,7 +438,7 @@ static unsigned char sp5100_tco_setupdevice(void)
pr_debug("SBResource_MMIO is disabled(0x%04x)\n", val);
pr_notice("failed to find MMIO address, giving up.\n");
- goto unreg_region;
+ goto exit;
setup_wdt:
tcobase_phys = val;
@@ -469,8 +478,6 @@ static unsigned char sp5100_tco_setupdevice(void)
unreg_mem_region:
release_mem_region(tcobase_phys, SP5100_WDT_MEM_MAP_SIZE);
-unreg_region:
- release_region(pm_iobase, SP5100_PM_IOPORTS_SIZE);
exit:
return 0;
}
@@ -517,7 +524,6 @@ static int sp5100_tco_init(struct platform_device *dev)
exit:
iounmap(tcobase);
release_mem_region(tcobase_phys, SP5100_WDT_MEM_MAP_SIZE);
- release_region(pm_iobase, SP5100_PM_IOPORTS_SIZE);
return ret;
}
@@ -531,7 +537,6 @@ static void sp5100_tco_cleanup(void)
misc_deregister(&sp5100_tco_miscdev);
iounmap(tcobase);
release_mem_region(tcobase_phys, SP5100_WDT_MEM_MAP_SIZE);
- release_region(pm_iobase, SP5100_PM_IOPORTS_SIZE);
}
static int sp5100_tco_remove(struct platform_device *dev)
--
2.9.3
[toc] | [prev] | [standalone]
Back to top | Article view | linux.kernel
csiph-web