| From 8a2f0343234198a83d0d3c890bb30447f96599e7 Mon Sep 17 00:00:00 2001 |
| From: Guenter Roeck <linux@roeck-us.net> |
| Date: Fri, 5 Apr 2019 08:53:08 -0700 |
| Subject: hwmon: (vt1211) Use request_muxed_region for Super-IO accesses |
| |
| [ Upstream commit 14b97ba5c20056102b3dd22696bf17b057e60976 ] |
| |
| 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: 2219cd81a6cd ("hwmon/vt1211: Add probing of alternate config index port") |
| Signed-off-by: Guenter Roeck <linux@roeck-us.net> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| drivers/hwmon/vt1211.c | 15 ++++++++++++--- |
| 1 file changed, 12 insertions(+), 3 deletions(-) |
| |
| diff --git a/drivers/hwmon/vt1211.c b/drivers/hwmon/vt1211.c |
| index 3a6bfa51cb94f..95d5e8ec8b7fc 100644 |
| --- a/drivers/hwmon/vt1211.c |
| +++ b/drivers/hwmon/vt1211.c |
| @@ -226,15 +226,21 @@ static inline void superio_select(int sio_cip, int ldn) |
| outb(ldn, sio_cip + 1); |
| } |
| |
| -static inline void superio_enter(int sio_cip) |
| +static inline int superio_enter(int sio_cip) |
| { |
| + if (!request_muxed_region(sio_cip, 2, DRVNAME)) |
| + return -EBUSY; |
| + |
| outb(0x87, sio_cip); |
| outb(0x87, sio_cip); |
| + |
| + return 0; |
| } |
| |
| static inline void superio_exit(int sio_cip) |
| { |
| outb(0xaa, sio_cip); |
| + release_region(sio_cip, 2); |
| } |
| |
| /* --------------------------------------------------------------------- |
| @@ -1282,11 +1288,14 @@ static int __init vt1211_device_add(unsigned short address) |
| |
| static int __init vt1211_find(int sio_cip, unsigned short *address) |
| { |
| - int err = -ENODEV; |
| + int err; |
| int devid; |
| |
| - superio_enter(sio_cip); |
| + err = superio_enter(sio_cip); |
| + if (err) |
| + return err; |
| |
| + err = -ENODEV; |
| devid = force_id ? force_id : superio_inb(sio_cip, SIO_VT1211_DEVID); |
| if (devid != SIO_VT1211_ID) |
| goto EXIT; |
| -- |
| 2.20.1 |
| |