Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/hid

Pull HID fixes from Jiri Kosina:
- fix hid-sony PS3 sixaxxis breakage from Benjamin Tissories
- fix hidraw race condition from Yonghua Zheng
- fix/bandaid for rare device enumeration problems of Logitech Unifying
receivers from Nestor Lopez Casado

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/hid:
HID: hidraw: fix improper mutex release
HID: sony: fix HID mapping for PS3 sixaxis controller
HID: hid-logitech-dj: querying_devices was never set
HID: Revert "Revert "HID: Fix logitech-dj: missing Unifying device issue""

+51 -2
+47
drivers/hid/hid-logitech-dj.c
··· 192 192 static int logi_dj_output_hidraw_report(struct hid_device *hid, u8 * buf, 193 193 size_t count, 194 194 unsigned char report_type); 195 + static int logi_dj_recv_query_paired_devices(struct dj_receiver_dev *djrcv_dev); 195 196 196 197 static void logi_dj_recv_destroy_djhid_device(struct dj_receiver_dev *djrcv_dev, 197 198 struct dj_report *dj_report) ··· 233 232 if (dj_report->report_params[DEVICE_PAIRED_PARAM_SPFUNCTION] & 234 233 SPFUNCTION_DEVICE_LIST_EMPTY) { 235 234 dbg_hid("%s: device list is empty\n", __func__); 235 + djrcv_dev->querying_devices = false; 236 236 return; 237 237 } 238 238 ··· 241 239 (dj_report->device_index > DJ_DEVICE_INDEX_MAX)) { 242 240 dev_err(&djrcv_hdev->dev, "%s: invalid device index:%d\n", 243 241 __func__, dj_report->device_index); 242 + return; 243 + } 244 + 245 + if (djrcv_dev->paired_dj_devices[dj_report->device_index]) { 246 + /* The device is already known. No need to reallocate it. */ 247 + dbg_hid("%s: device is already known\n", __func__); 244 248 return; 245 249 } 246 250 ··· 313 305 struct dj_report dj_report; 314 306 unsigned long flags; 315 307 int count; 308 + int retval; 316 309 317 310 dbg_hid("%s\n", __func__); 318 311 ··· 346 337 logi_dj_recv_destroy_djhid_device(djrcv_dev, &dj_report); 347 338 break; 348 339 default: 340 + /* A normal report (i. e. not belonging to a pair/unpair notification) 341 + * arriving here, means that the report arrived but we did not have a 342 + * paired dj_device associated to the report's device_index, this 343 + * means that the original "device paired" notification corresponding 344 + * to this dj_device never arrived to this driver. The reason is that 345 + * hid-core discards all packets coming from a device while probe() is 346 + * executing. */ 347 + if (!djrcv_dev->paired_dj_devices[dj_report.device_index]) { 348 + /* ok, we don't know the device, just re-ask the 349 + * receiver for the list of connected devices. */ 350 + retval = logi_dj_recv_query_paired_devices(djrcv_dev); 351 + if (!retval) { 352 + /* everything went fine, so just leave */ 353 + break; 354 + } 355 + dev_err(&djrcv_dev->hdev->dev, 356 + "%s:logi_dj_recv_query_paired_devices " 357 + "error:%d\n", __func__, retval); 358 + } 349 359 dbg_hid("%s: unexpected report type\n", __func__); 350 360 } 351 361 } ··· 395 367 if (!djdev) { 396 368 dbg_hid("djrcv_dev->paired_dj_devices[dj_report->device_index]" 397 369 " is NULL, index %d\n", dj_report->device_index); 370 + kfifo_in(&djrcv_dev->notif_fifo, dj_report, sizeof(struct dj_report)); 371 + 372 + if (schedule_work(&djrcv_dev->work) == 0) { 373 + dbg_hid("%s: did not schedule the work item, was already " 374 + "queued\n", __func__); 375 + } 398 376 return; 399 377 } 400 378 ··· 431 397 if (dj_device == NULL) { 432 398 dbg_hid("djrcv_dev->paired_dj_devices[dj_report->device_index]" 433 399 " is NULL, index %d\n", dj_report->device_index); 400 + kfifo_in(&djrcv_dev->notif_fifo, dj_report, sizeof(struct dj_report)); 401 + 402 + if (schedule_work(&djrcv_dev->work) == 0) { 403 + dbg_hid("%s: did not schedule the work item, was already " 404 + "queued\n", __func__); 405 + } 434 406 return; 435 407 } 436 408 ··· 484 444 struct dj_report *dj_report; 485 445 int retval; 486 446 447 + /* no need to protect djrcv_dev->querying_devices */ 448 + if (djrcv_dev->querying_devices) 449 + return 0; 450 + 451 + djrcv_dev->querying_devices = true; 452 + 487 453 dj_report = kzalloc(sizeof(struct dj_report), GFP_KERNEL); 488 454 if (!dj_report) 489 455 return -ENOMEM; ··· 500 454 kfree(dj_report); 501 455 return retval; 502 456 } 457 + 503 458 504 459 static int logi_dj_recv_switch_to_dj_mode(struct dj_receiver_dev *djrcv_dev, 505 460 unsigned timeout)
+1
drivers/hid/hid-logitech-dj.h
··· 101 101 struct work_struct work; 102 102 struct kfifo notif_fifo; 103 103 spinlock_t lock; 104 + bool querying_devices; 104 105 }; 105 106 106 107 struct dj_device {
+2 -1
drivers/hid/hid-sony.c
··· 369 369 if (sc->quirks & PS3REMOTE) 370 370 return ps3remote_mapping(hdev, hi, field, usage, bit, max); 371 371 372 - return -1; 372 + /* Let hid-core decide for the others */ 373 + return 0; 373 374 } 374 375 375 376 /*
+1 -1
drivers/hid/hidraw.c
··· 518 518 goto out; 519 519 } 520 520 521 - mutex_unlock(&minors_lock); 522 521 init_waitqueue_head(&dev->wait); 523 522 INIT_LIST_HEAD(&dev->list); 524 523 ··· 527 528 dev->exist = 1; 528 529 hid->hidraw = dev; 529 530 531 + mutex_unlock(&minors_lock); 530 532 out: 531 533 return result; 532 534