| From e7093a55ecf24f575eeaef1bbf277a6f5a5d55c9 Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Fri, 5 Apr 2019 08:44:41 -0700 |
| Subject: hwmon: (w83627hf) Use request_muxed_region for Super-IO accesses |
| |
| From: Guenter Roeck <linux@roeck-us.net> |
| |
| [ Upstream commit e95fd518d05bfc087da6fcdea4900a57cfb083bd ] |
| |
| 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: b72656dbc491 ("hwmon: (w83627hf) Stop using globals for I/O port numbers") |
| Signed-off-by: Guenter Roeck <linux@roeck-us.net> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| drivers/hwmon/w83627hf.c | 42 +++++++++++++++++++++++++++++++++++----- |
| 1 file changed, 37 insertions(+), 5 deletions(-) |
| |
| diff --git a/drivers/hwmon/w83627hf.c b/drivers/hwmon/w83627hf.c |
| index 721295b9a0517..43c0f89cefdf0 100644 |
| --- a/drivers/hwmon/w83627hf.c |
| +++ b/drivers/hwmon/w83627hf.c |
| @@ -130,17 +130,23 @@ superio_select(struct w83627hf_sio_data *sio, int ld) |
| outb(ld, sio->sioaddr + 1); |
| } |
| |
| -static inline void |
| +static inline int |
| superio_enter(struct w83627hf_sio_data *sio) |
| { |
| + if (!request_muxed_region(sio->sioaddr, 2, DRVNAME)) |
| + return -EBUSY; |
| + |
| outb(0x87, sio->sioaddr); |
| outb(0x87, sio->sioaddr); |
| + |
| + return 0; |
| } |
| |
| static inline void |
| superio_exit(struct w83627hf_sio_data *sio) |
| { |
| outb(0xAA, sio->sioaddr); |
| + release_region(sio->sioaddr, 2); |
| } |
| |
| #define W627_DEVID 0x52 |
| @@ -1275,7 +1281,7 @@ static DEVICE_ATTR(name, S_IRUGO, show_name, NULL); |
| static int __init w83627hf_find(int sioaddr, unsigned short *addr, |
| struct w83627hf_sio_data *sio_data) |
| { |
| - int err = -ENODEV; |
| + int err; |
| u16 val; |
| |
| static __initconst char *const names[] = { |
| @@ -1287,7 +1293,11 @@ static int __init w83627hf_find(int sioaddr, unsigned short *addr, |
| }; |
| |
| sio_data->sioaddr = sioaddr; |
| - superio_enter(sio_data); |
| + err = superio_enter(sio_data); |
| + if (err) |
| + return err; |
| + |
| + err = -ENODEV; |
| val = force_id ? force_id : superio_inb(sio_data, DEVID); |
| switch (val) { |
| case W627_DEVID: |
| @@ -1641,9 +1651,21 @@ static int w83627thf_read_gpio5(struct platform_device *pdev) |
| struct w83627hf_sio_data *sio_data = dev_get_platdata(&pdev->dev); |
| int res = 0xff, sel; |
| |
| - superio_enter(sio_data); |
| + if (superio_enter(sio_data)) { |
| + /* |
| + * Some other driver reserved the address space for itself. |
| + * We don't want to fail driver instantiation because of that, |
| + * so display a warning and keep going. |
| + */ |
| + dev_warn(&pdev->dev, |
| + "Can not read VID data: Failed to enable SuperIO access\n"); |
| + return res; |
| + } |
| + |
| superio_select(sio_data, W83627HF_LD_GPIO5); |
| |
| + res = 0xff; |
| + |
| /* Make sure these GPIO pins are enabled */ |
| if (!(superio_inb(sio_data, W83627THF_GPIO5_EN) & (1<<3))) { |
| dev_dbg(&pdev->dev, "GPIO5 disabled, no VID function\n"); |
| @@ -1674,7 +1696,17 @@ static int w83687thf_read_vid(struct platform_device *pdev) |
| struct w83627hf_sio_data *sio_data = dev_get_platdata(&pdev->dev); |
| int res = 0xff; |
| |
| - superio_enter(sio_data); |
| + if (superio_enter(sio_data)) { |
| + /* |
| + * Some other driver reserved the address space for itself. |
| + * We don't want to fail driver instantiation because of that, |
| + * so display a warning and keep going. |
| + */ |
| + dev_warn(&pdev->dev, |
| + "Can not read VID data: Failed to enable SuperIO access\n"); |
| + return res; |
| + } |
| + |
| superio_select(sio_data, W83627HF_LD_HWM); |
| |
| /* Make sure these GPIO pins are enabled */ |
| -- |
| 2.20.1 |
| |