aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hid/hid-cp2112.c
diff options
context:
space:
mode:
authorBenjamin Tissoires <benjamin.tissoires@redhat.com>2016-11-21 05:48:39 -0500
committerJiri Kosina <jkosina@suse.cz>2016-11-23 11:38:12 -0500
commit1ffb3c40ffb5c51bc39736409b11816c4260218e (patch)
tree68eff7671b986b67cbcbab2b5c9f7739be0228dc /drivers/hid/hid-cp2112.c
parent4c4480aad0d8eaf0d52b6f2c8c5dfbe0531cbbea (diff)
HID: cp2112: make transfer buffers DMA capable
Kernel v4.9 strictly enforces DMA capable buffers, so we need to remove buffers allocated on the stack. Use a spinlock to prevent concurrent accesses to the buffer. Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com> Signed-off-by: Jiri Kosina <jkosina@suse.cz>
Diffstat (limited to 'drivers/hid/hid-cp2112.c')
-rw-r--r--drivers/hid/hid-cp2112.c115
1 files changed, 79 insertions, 36 deletions
diff --git a/drivers/hid/hid-cp2112.c b/drivers/hid/hid-cp2112.c
index 086d8a507157..60d30203a5fa 100644
--- a/drivers/hid/hid-cp2112.c
+++ b/drivers/hid/hid-cp2112.c
@@ -32,6 +32,11 @@
32#include <linux/usb/ch9.h> 32#include <linux/usb/ch9.h>
33#include "hid-ids.h" 33#include "hid-ids.h"
34 34
35#define CP2112_REPORT_MAX_LENGTH 64
36#define CP2112_GPIO_CONFIG_LENGTH 5
37#define CP2112_GPIO_GET_LENGTH 2
38#define CP2112_GPIO_SET_LENGTH 3
39
35enum { 40enum {
36 CP2112_GPIO_CONFIG = 0x02, 41 CP2112_GPIO_CONFIG = 0x02,
37 CP2112_GPIO_GET = 0x03, 42 CP2112_GPIO_GET = 0x03,
@@ -161,6 +166,8 @@ struct cp2112_device {
161 atomic_t read_avail; 166 atomic_t read_avail;
162 atomic_t xfer_avail; 167 atomic_t xfer_avail;
163 struct gpio_chip gc; 168 struct gpio_chip gc;
169 u8 *in_out_buffer;
170 spinlock_t lock;
164}; 171};
165 172
166static int gpio_push_pull = 0xFF; 173static int gpio_push_pull = 0xFF;
@@ -171,62 +178,86 @@ static int cp2112_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
171{ 178{
172 struct cp2112_device *dev = gpiochip_get_data(chip); 179 struct cp2112_device *dev = gpiochip_get_data(chip);
173 struct hid_device *hdev = dev->hdev; 180 struct hid_device *hdev = dev->hdev;
174 u8 buf[5]; 181 u8 *buf = dev->in_out_buffer;
182 unsigned long flags;
175 int ret; 183 int ret;
176 184
185 spin_lock_irqsave(&dev->lock, flags);
186
177 ret = hid_hw_raw_request(hdev, CP2112_GPIO_CONFIG, buf, 187 ret = hid_hw_raw_request(hdev, CP2112_GPIO_CONFIG, buf,
178 sizeof(buf), HID_FEATURE_REPORT, 188 CP2112_GPIO_CONFIG_LENGTH, HID_FEATURE_REPORT,
179 HID_REQ_GET_REPORT); 189 HID_REQ_GET_REPORT);
180 if (ret != sizeof(buf)) { 190 if (ret != CP2112_GPIO_CONFIG_LENGTH) {
181 hid_err(hdev, "error requesting GPIO config: %d\n", ret); 191 hid_err(hdev, "error requesting GPIO config: %d\n", ret);
182 return ret; 192 goto exit;
183 } 193 }
184 194
185 buf[1] &= ~(1 << offset); 195 buf[1] &= ~(1 << offset);
186 buf[2] = gpio_push_pull; 196 buf[2] = gpio_push_pull;
187 197
188 ret = hid_hw_raw_request(hdev, CP2112_GPIO_CONFIG, buf, sizeof(buf), 198 ret = hid_hw_raw_request(hdev, CP2112_GPIO_CONFIG, buf,
189 HID_FEATURE_REPORT, HID_REQ_SET_REPORT); 199 CP2112_GPIO_CONFIG_LENGTH, HID_FEATURE_REPORT,
200 HID_REQ_SET_REPORT);
190 if (ret < 0) { 201 if (ret < 0) {
191 hid_err(hdev, "error setting GPIO config: %d\n", ret); 202 hid_err(hdev, "error setting GPIO config: %d\n", ret);
192 return ret; 203 goto exit;
193 } 204 }
194 205
195 return 0; 206 ret = 0;
207
208exit:
209 spin_unlock_irqrestore(&dev->lock, flags);
210 return ret <= 0 ? ret : -EIO;
196} 211}
197 212
198static void cp2112_gpio_set(struct gpio_chip *chip, unsigned offset, int value) 213static void cp2112_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
199{ 214{
200 struct cp2112_device *dev = gpiochip_get_data(chip); 215 struct cp2112_device *dev = gpiochip_get_data(chip);
201 struct hid_device *hdev = dev->hdev; 216 struct hid_device *hdev = dev->hdev;
202 u8 buf[3]; 217 u8 *buf = dev->in_out_buffer;
218 unsigned long flags;
203 int ret; 219 int ret;
204 220
221 spin_lock_irqsave(&dev->lock, flags);
222
205 buf[0] = CP2112_GPIO_SET; 223 buf[0] = CP2112_GPIO_SET;
206 buf[1] = value ? 0xff : 0; 224 buf[1] = value ? 0xff : 0;
207 buf[2] = 1 << offset; 225 buf[2] = 1 << offset;
208 226
209 ret = hid_hw_raw_request(hdev, CP2112_GPIO_SET, buf, sizeof(buf), 227 ret = hid_hw_raw_request(hdev, CP2112_GPIO_SET, buf,
210 HID_FEATURE_REPORT, HID_REQ_SET_REPORT); 228 CP2112_GPIO_SET_LENGTH, HID_FEATURE_REPORT,
229 HID_REQ_SET_REPORT);
211 if (ret < 0) 230 if (ret < 0)
212 hid_err(hdev, "error setting GPIO values: %d\n", ret); 231 hid_err(hdev, "error setting GPIO values: %d\n", ret);
232
233 spin_unlock_irqrestore(&dev->lock, flags);
213} 234}
214 235
215static int cp2112_gpio_get(struct gpio_chip *chip, unsigned offset) 236static int cp2112_gpio_get(struct gpio_chip *chip, unsigned offset)
216{ 237{
217 struct cp2112_device *dev = gpiochip_get_data(chip); 238 struct cp2112_device *dev = gpiochip_get_data(chip);
218 struct hid_device *hdev = dev->hdev; 239 struct hid_device *hdev = dev->hdev;
219 u8 buf[2]; 240 u8 *buf = dev->in_out_buffer;
241 unsigned long flags;
220 int ret; 242 int ret;
221 243
222 ret = hid_hw_raw_request(hdev, CP2112_GPIO_GET, buf, sizeof(buf), 244 spin_lock_irqsave(&dev->lock, flags);
223 HID_FEATURE_REPORT, HID_REQ_GET_REPORT); 245
224 if (ret != sizeof(buf)) { 246 ret = hid_hw_raw_request(hdev, CP2112_GPIO_GET, buf,
247 CP2112_GPIO_GET_LENGTH, HID_FEATURE_REPORT,
248 HID_REQ_GET_REPORT);
249 if (ret != CP2112_GPIO_GET_LENGTH) {
225 hid_err(hdev, "error requesting GPIO values: %d\n", ret); 250 hid_err(hdev, "error requesting GPIO values: %d\n", ret);
226 return ret; 251 ret = ret < 0 ? ret : -EIO;
252 goto exit;
227 } 253 }
228 254
229 return (buf[1] >> offset) & 1; 255 ret = (buf[1] >> offset) & 1;
256
257exit:
258 spin_unlock_irqrestore(&dev->lock, flags);
259
260 return ret;
230} 261}
231 262
232static int cp2112_gpio_direction_output(struct gpio_chip *chip, 263static int cp2112_gpio_direction_output(struct gpio_chip *chip,
@@ -234,27 +265,33 @@ static int cp2112_gpio_direction_output(struct gpio_chip *chip,
234{ 265{
235 struct cp2112_device *dev = gpiochip_get_data(chip); 266 struct cp2112_device *dev = gpiochip_get_data(chip);
236 struct hid_device *hdev = dev->hdev; 267 struct hid_device *hdev = dev->hdev;
237 u8 buf[5]; 268 u8 *buf = dev->in_out_buffer;
269 unsigned long flags;
238 int ret; 270 int ret;
239 271
272 spin_lock_irqsave(&dev->lock, flags);
273
240 ret = hid_hw_raw_request(hdev, CP2112_GPIO_CONFIG, buf, 274 ret = hid_hw_raw_request(hdev, CP2112_GPIO_CONFIG, buf,
241 sizeof(buf), HID_FEATURE_REPORT, 275 CP2112_GPIO_CONFIG_LENGTH, HID_FEATURE_REPORT,
242 HID_REQ_GET_REPORT); 276 HID_REQ_GET_REPORT);
243 if (ret != sizeof(buf)) { 277 if (ret != CP2112_GPIO_CONFIG_LENGTH) {
244 hid_err(hdev, "error requesting GPIO config: %d\n", ret); 278 hid_err(hdev, "error requesting GPIO config: %d\n", ret);
245 return ret; 279 goto fail;
246 } 280 }
247 281
248 buf[1] |= 1 << offset; 282 buf[1] |= 1 << offset;
249 buf[2] = gpio_push_pull; 283 buf[2] = gpio_push_pull;
250 284
251 ret = hid_hw_raw_request(hdev, CP2112_GPIO_CONFIG, buf, sizeof(buf), 285 ret = hid_hw_raw_request(hdev, CP2112_GPIO_CONFIG, buf,
252 HID_FEATURE_REPORT, HID_REQ_SET_REPORT); 286 CP2112_GPIO_CONFIG_LENGTH, HID_FEATURE_REPORT,
287 HID_REQ_SET_REPORT);
253 if (ret < 0) { 288 if (ret < 0) {
254 hid_err(hdev, "error setting GPIO config: %d\n", ret); 289 hid_err(hdev, "error setting GPIO config: %d\n", ret);
255 return ret; 290 goto fail;
256 } 291 }
257 292
293 spin_unlock_irqrestore(&dev->lock, flags);
294
258 /* 295 /*
259 * Set gpio value when output direction is already set, 296 * Set gpio value when output direction is already set,
260 * as specified in AN495, Rev. 0.2, cpt. 4.4 297 * as specified in AN495, Rev. 0.2, cpt. 4.4
@@ -262,6 +299,10 @@ static int cp2112_gpio_direction_output(struct gpio_chip *chip,
262 cp2112_gpio_set(chip, offset, value); 299 cp2112_gpio_set(chip, offset, value);
263 300
264 return 0; 301 return 0;
302
303fail:
304 spin_unlock_irqrestore(&dev->lock, flags);
305 return ret < 0 ? ret : -EIO;
265} 306}
266 307
267static int cp2112_hid_get(struct hid_device *hdev, unsigned char report_number, 308static int cp2112_hid_get(struct hid_device *hdev, unsigned char report_number,
@@ -1007,6 +1048,17 @@ static int cp2112_probe(struct hid_device *hdev, const struct hid_device_id *id)
1007 struct cp2112_smbus_config_report config; 1048 struct cp2112_smbus_config_report config;
1008 int ret; 1049 int ret;
1009 1050
1051 dev = devm_kzalloc(&hdev->dev, sizeof(*dev), GFP_KERNEL);
1052 if (!dev)
1053 return -ENOMEM;
1054
1055 dev->in_out_buffer = devm_kzalloc(&hdev->dev, CP2112_REPORT_MAX_LENGTH,
1056 GFP_KERNEL);
1057 if (!dev->in_out_buffer)
1058 return -ENOMEM;
1059
1060 spin_lock_init(&dev->lock);
1061
1010 ret = hid_parse(hdev); 1062 ret = hid_parse(hdev);
1011 if (ret) { 1063 if (ret) {
1012 hid_err(hdev, "parse failed\n"); 1064 hid_err(hdev, "parse failed\n");
@@ -1063,12 +1115,6 @@ static int cp2112_probe(struct hid_device *hdev, const struct hid_device_id *id)
1063 goto err_power_normal; 1115 goto err_power_normal;
1064 } 1116 }
1065 1117
1066 dev = kzalloc(sizeof(*dev), GFP_KERNEL);
1067 if (!dev) {
1068 ret = -ENOMEM;
1069 goto err_power_normal;
1070 }
1071
1072 hid_set_drvdata(hdev, (void *)dev); 1118 hid_set_drvdata(hdev, (void *)dev);
1073 dev->hdev = hdev; 1119 dev->hdev = hdev;
1074 dev->adap.owner = THIS_MODULE; 1120 dev->adap.owner = THIS_MODULE;
@@ -1087,7 +1133,7 @@ static int cp2112_probe(struct hid_device *hdev, const struct hid_device_id *id)
1087 1133
1088 if (ret) { 1134 if (ret) {
1089 hid_err(hdev, "error registering i2c adapter\n"); 1135 hid_err(hdev, "error registering i2c adapter\n");
1090 goto err_free_dev; 1136 goto err_power_normal;
1091 } 1137 }
1092 1138
1093 hid_dbg(hdev, "adapter registered\n"); 1139 hid_dbg(hdev, "adapter registered\n");
@@ -1123,8 +1169,6 @@ err_gpiochip_remove:
1123 gpiochip_remove(&dev->gc); 1169 gpiochip_remove(&dev->gc);
1124err_free_i2c: 1170err_free_i2c:
1125 i2c_del_adapter(&dev->adap); 1171 i2c_del_adapter(&dev->adap);
1126err_free_dev:
1127 kfree(dev);
1128err_power_normal: 1172err_power_normal:
1129 hid_hw_power(hdev, PM_HINT_NORMAL); 1173 hid_hw_power(hdev, PM_HINT_NORMAL);
1130err_hid_close: 1174err_hid_close:
@@ -1149,7 +1193,6 @@ static void cp2112_remove(struct hid_device *hdev)
1149 */ 1193 */
1150 hid_hw_close(hdev); 1194 hid_hw_close(hdev);
1151 hid_hw_stop(hdev); 1195 hid_hw_stop(hdev);
1152 kfree(dev);
1153} 1196}
1154 1197
1155static int cp2112_raw_event(struct hid_device *hdev, struct hid_report *report, 1198static int cp2112_raw_event(struct hid_device *hdev, struct hid_report *report,