Hi Jiri,

Mika Westerberg [email protected] reported a bug introduced in 
hid driver after 
commit 212a871a393 (HID: hidraw: correctly deallocate memory on device 
disconnect) 
that hidraw doesn't close the underlying hid device when the device node is 
closed last time.

I am proposing following patch as fix.  Please review it.  Mika will help in 
testing.

----------------------------------------
>From b37519b65be0d51b90c5fc177c0dc0cd2f6358b1 Mon Sep 17 00:00:00 2001
From: Manoj Chourasia <[email protected]>
Date: Tue, 1 Oct 2013 15:39:00 +0530
Subject: [PATCH] HID: hidraw: close underlying device at removal of last reader

Even though device exist bit is set the underlying
HW device should be closed when the last reader
of the device is closed i.e. open count drops to zero.

Signed-off-by: Manoj Chourasia <[email protected]>
---
 drivers/hid/hidraw.c |   21 +++++++++++++++------
 1 file changed, 15 insertions(+), 6 deletions(-)

diff --git a/drivers/hid/hidraw.c b/drivers/hid/hidraw.c
index dbfe300..3c0dd44 100644
--- a/drivers/hid/hidraw.c
+++ b/drivers/hid/hidraw.c
@@ -305,19 +305,28 @@ static int hidraw_fasync(int fd, struct file *file, int 
on)
 static void drop_ref(struct hidraw *hidraw, int exists_bit)
 {
        if (exists_bit) {
-               hid_hw_close(hidraw->hid);
                hidraw->exist = 0;
-               if (hidraw->open)
+               if (hidraw->open) {
+                       hid_hw_close(hidraw->hid);
                        wake_up_interruptible(&hidraw->wait);
+               }
        } else {
                --hidraw->open;
        }

-       if (!hidraw->open && !hidraw->exist) {
-               device_destroy(hidraw_class, MKDEV(hidraw_major, 
hidraw->minor));
-               hidraw_table[hidraw->minor] = NULL;
-               kfree(hidraw);
+       if (!hidraw->open) {
+               if (!hidraw->exist) {
+                       device_destroy(hidraw_class,
+                               MKDEV(hidraw_major, hidraw->minor));
+                       hidraw_table[hidraw->minor] = NULL;
+                       kfree(hidraw);
+               } else {
+                       /* close device for last reader */
+                       hid_hw_power(hidraw->hid, PM_HINT_NORMAL);
+                       hid_hw_close(hidraw->hid);
+               }
        }
+
 }

 static int hidraw_release(struct inode * inode, struct file * file)
--
1.7.9.5


-Regards
Manoj

Attachment: PATCH-hidraw-close-underlying-device-at-removal-of-las.patch
Description: PATCH-hidraw-close-underlying-device-at-removal-of-las.patch

Reply via email to