]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blame - releases/4.9.180/hwmon-smsc47m1-use-request_muxed_region-for-super-io.patch
Linux 4.9.180
[thirdparty/kernel/stable-queue.git] / releases / 4.9.180 / hwmon-smsc47m1-use-request_muxed_region-for-super-io.patch
CommitLineData
2f47b8fc
SL
1From 04ed1d0353c6dc8f4fd77ee214fc2a81fafdfd82 Mon Sep 17 00:00:00 2001
2From: Guenter Roeck <linux@roeck-us.net>
3Date: Thu, 4 Apr 2019 11:28:37 -0700
4Subject: hwmon: (smsc47m1) Use request_muxed_region for Super-IO accesses
5
6[ Upstream commit d6410408ad2a798c4cc685252c1baa713be0ad69 ]
7
8Super-IO accesses may fail on a system with no or unmapped LPC bus.
9
10Also, other drivers may attempt to access the LPC bus at the same time,
11resulting in undefined behavior.
12
13Use request_muxed_region() to ensure that IO access on the requested
14address space is supported, and to ensure that access by multiple drivers
15is synchronized.
16
17Fixes: 8d5d45fb1468 ("I2C: Move hwmon drivers (2/3)")
18Reported-by: Kefeng Wang <wangkefeng.wang@huawei.com>
19Reported-by: John Garry <john.garry@huawei.com>
20Cc: John Garry <john.garry@huawei.com>
21Acked-by: John Garry <john.garry@huawei.com>
22Signed-off-by: Guenter Roeck <linux@roeck-us.net>
23Signed-off-by: Sasha Levin <sashal@kernel.org>
24---
25 drivers/hwmon/smsc47m1.c | 28 +++++++++++++++++++---------
26 1 file changed, 19 insertions(+), 9 deletions(-)
27
28diff --git a/drivers/hwmon/smsc47m1.c b/drivers/hwmon/smsc47m1.c
29index 5d323186d2c10..d24df0c50bea4 100644
30--- a/drivers/hwmon/smsc47m1.c
31+++ b/drivers/hwmon/smsc47m1.c
32@@ -73,16 +73,21 @@ superio_inb(int reg)
33 /* logical device for fans is 0x0A */
34 #define superio_select() superio_outb(0x07, 0x0A)
35
36-static inline void
37+static inline int
38 superio_enter(void)
39 {
40+ if (!request_muxed_region(REG, 2, DRVNAME))
41+ return -EBUSY;
42+
43 outb(0x55, REG);
44+ return 0;
45 }
46
47 static inline void
48 superio_exit(void)
49 {
50 outb(0xAA, REG);
51+ release_region(REG, 2);
52 }
53
54 #define SUPERIO_REG_ACT 0x30
55@@ -531,8 +536,12 @@ static int __init smsc47m1_find(struct smsc47m1_sio_data *sio_data)
56 {
57 u8 val;
58 unsigned short addr;
59+ int err;
60+
61+ err = superio_enter();
62+ if (err)
63+ return err;
64
65- superio_enter();
66 val = force_id ? force_id : superio_inb(SUPERIO_REG_DEVID);
67
68 /*
69@@ -608,13 +617,14 @@ static int __init smsc47m1_find(struct smsc47m1_sio_data *sio_data)
70 static void smsc47m1_restore(const struct smsc47m1_sio_data *sio_data)
71 {
72 if ((sio_data->activate & 0x01) == 0) {
73- superio_enter();
74- superio_select();
75-
76- pr_info("Disabling device\n");
77- superio_outb(SUPERIO_REG_ACT, sio_data->activate);
78-
79- superio_exit();
80+ if (!superio_enter()) {
81+ superio_select();
82+ pr_info("Disabling device\n");
83+ superio_outb(SUPERIO_REG_ACT, sio_data->activate);
84+ superio_exit();
85+ } else {
86+ pr_warn("Failed to disable device\n");
87+ }
88 }
89 }
90
91--
922.20.1
93