]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/commitdiff
hwmon: (w83627hf) Use request_muxed_region for Super-IO accesses
authorGuenter Roeck <linux@roeck-us.net>
Fri, 5 Apr 2019 15:44:41 +0000 (08:44 -0700)
committerKhalid Elmously <khalid.elmously@canonical.com>
Fri, 14 Feb 2020 05:29:37 +0000 (00:29 -0500)
BugLink: https://bugs.launchpad.net/bugs/1863019
[ 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>
Signed-off-by: Kamal Mostafa <kamal@canonical.com>
Signed-off-by: Khalid Elmously <khalid.elmously@canonical.com>
drivers/hwmon/w83627hf.c

index 8ac89d0781ccc68336eff6f13270063ed69a3ee9..a575e1cdb81a80206a97ca2057c738ed7be17802 100644 (file)
@@ -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
@@ -1278,7 +1284,7 @@ static DEVICE_ATTR_RO(name);
 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[] = {
@@ -1290,7 +1296,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:
@@ -1644,9 +1654,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");
@@ -1677,7 +1699,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 */