| From 227e2db762a039dc73db3e24cabac3003ff4a141 Mon Sep 17 00:00:00 2001 |
| From: Guenter Roeck <linux@roeck-us.net> |
| Date: Thu, 4 Apr 2019 11:16:20 -0700 |
| Subject: hwmon: (pc87427) Use request_muxed_region for Super-IO accesses |
| |
| [ Upstream commit 755a9b0f8aaa5639ba5671ca50080852babb89ce ] |
| |
| Super-IO accesses may fail on a system with no or unmapped LPC bus. |
| |
| Also, other drivers may attempt to access the LPC bus at the same time, |
| resulting in undefined behavior. |
| |
| Use request_muxed_region() to ensure that IO access on the requested |
| address space is supported, and to ensure that access by multiple drivers |
| is synchronized. |
| |
| Fixes: ba224e2c4f0a7 ("hwmon: New PC87427 hardware monitoring driver") |
| Reported-by: Kefeng Wang <wangkefeng.wang@huawei.com> |
| Reported-by: John Garry <john.garry@huawei.com> |
| Cc: John Garry <john.garry@huawei.com> |
| Acked-by: John Garry <john.garry@huawei.com> |
| Signed-off-by: Guenter Roeck <linux@roeck-us.net> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| drivers/hwmon/pc87427.c | 14 +++++++++++++- |
| 1 file changed, 13 insertions(+), 1 deletion(-) |
| |
| diff --git a/drivers/hwmon/pc87427.c b/drivers/hwmon/pc87427.c |
| index dc5a9d5ada516..81a05cd1a5121 100644 |
| --- a/drivers/hwmon/pc87427.c |
| +++ b/drivers/hwmon/pc87427.c |
| @@ -106,6 +106,13 @@ static const char *logdev_str[2] = { DRVNAME " FMC", DRVNAME " HMC" }; |
| #define LD_IN 1 |
| #define LD_TEMP 1 |
| |
| +static inline int superio_enter(int sioaddr) |
| +{ |
| + if (!request_muxed_region(sioaddr, 2, DRVNAME)) |
| + return -EBUSY; |
| + return 0; |
| +} |
| + |
| static inline void superio_outb(int sioaddr, int reg, int val) |
| { |
| outb(reg, sioaddr); |
| @@ -122,6 +129,7 @@ static inline void superio_exit(int sioaddr) |
| { |
| outb(0x02, sioaddr); |
| outb(0x02, sioaddr + 1); |
| + release_region(sioaddr, 2); |
| } |
| |
| /* |
| @@ -1220,7 +1228,11 @@ static int __init pc87427_find(int sioaddr, struct pc87427_sio_data *sio_data) |
| { |
| u16 val; |
| u8 cfg, cfg_b; |
| - int i, err = 0; |
| + int i, err; |
| + |
| + err = superio_enter(sioaddr); |
| + if (err) |
| + return err; |
| |
| /* Identify device */ |
| val = force_id ? force_id : superio_inb(sioaddr, SIOREG_DEVID); |
| -- |
| 2.20.1 |
| |