]>
Commit | Line | Data |
---|---|---|
2f47b8fc SL |
1 | From 04ed1d0353c6dc8f4fd77ee214fc2a81fafdfd82 Mon Sep 17 00:00:00 2001 |
2 | From: Guenter Roeck <linux@roeck-us.net> | |
3 | Date: Thu, 4 Apr 2019 11:28:37 -0700 | |
4 | Subject: hwmon: (smsc47m1) Use request_muxed_region for Super-IO accesses | |
5 | ||
6 | [ Upstream commit d6410408ad2a798c4cc685252c1baa713be0ad69 ] | |
7 | ||
8 | Super-IO accesses may fail on a system with no or unmapped LPC bus. | |
9 | ||
10 | Also, other drivers may attempt to access the LPC bus at the same time, | |
11 | resulting in undefined behavior. | |
12 | ||
13 | Use request_muxed_region() to ensure that IO access on the requested | |
14 | address space is supported, and to ensure that access by multiple drivers | |
15 | is synchronized. | |
16 | ||
17 | Fixes: 8d5d45fb1468 ("I2C: Move hwmon drivers (2/3)") | |
18 | Reported-by: Kefeng Wang <wangkefeng.wang@huawei.com> | |
19 | Reported-by: John Garry <john.garry@huawei.com> | |
20 | Cc: John Garry <john.garry@huawei.com> | |
21 | Acked-by: John Garry <john.garry@huawei.com> | |
22 | Signed-off-by: Guenter Roeck <linux@roeck-us.net> | |
23 | Signed-off-by: Sasha Levin <sashal@kernel.org> | |
24 | --- | |
25 | drivers/hwmon/smsc47m1.c | 28 +++++++++++++++++++--------- | |
26 | 1 file changed, 19 insertions(+), 9 deletions(-) | |
27 | ||
28 | diff --git a/drivers/hwmon/smsc47m1.c b/drivers/hwmon/smsc47m1.c | |
29 | index 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 | -- | |
92 | 2.20.1 | |
93 |