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

Input: iforce - fix oops on device disconnect

Do not try to free iforce device when we closing input device; disconnect
is the only place where it should be deleted.

Reported-by: Johannes Ebke <johannes.ebke@physik.uni-muenchen.de>
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>

+12 -44
+5 -21
drivers/input/joystick/iforce/iforce-main.c
··· 210 210 return 0; 211 211 } 212 212 213 - static void iforce_release(struct input_dev *dev) 213 + static void iforce_close(struct input_dev *dev) 214 214 { 215 215 struct iforce *iforce = input_get_drvdata(dev); 216 216 int i; ··· 232 232 233 233 switch (iforce->bus) { 234 234 #ifdef CONFIG_JOYSTICK_IFORCE_USB 235 - case IFORCE_USB: 236 - usb_kill_urb(iforce->irq); 237 - 238 - /* The device was unplugged before the file 239 - * was released */ 240 - if (iforce->usbdev == NULL) { 241 - iforce_delete_device(iforce); 242 - kfree(iforce); 243 - } 244 - break; 245 - #endif 246 - } 247 - } 248 - 249 - void iforce_delete_device(struct iforce *iforce) 250 - { 251 - switch (iforce->bus) { 252 - #ifdef CONFIG_JOYSTICK_IFORCE_USB 253 235 case IFORCE_USB: 254 - iforce_usb_delete(iforce); 236 + usb_kill_urb(iforce->irq); 237 + usb_kill_urb(iforce->out); 238 + usb_kill_urb(iforce->ctrl); 255 239 break; 256 240 #endif 257 241 #ifdef CONFIG_JOYSTICK_IFORCE_232 ··· 287 303 288 304 input_dev->name = "Unknown I-Force device"; 289 305 input_dev->open = iforce_open; 290 - input_dev->close = iforce_release; 306 + input_dev->close = iforce_close; 291 307 292 308 /* 293 309 * On-device memory allocation.
+7 -21
drivers/input/joystick/iforce/iforce-usb.c
··· 186 186 return err; 187 187 } 188 188 189 - /* Called by iforce_delete() */ 190 - void iforce_usb_delete(struct iforce* iforce) 189 + static void iforce_usb_disconnect(struct usb_interface *intf) 191 190 { 192 - usb_kill_urb(iforce->irq); 193 - usb_kill_urb(iforce->out); 194 - usb_kill_urb(iforce->ctrl); 191 + struct iforce *iforce = usb_get_intfdata(intf); 192 + 193 + usb_set_intfdata(intf, NULL); 194 + 195 + input_unregister_device(iforce->dev); 195 196 196 197 usb_free_urb(iforce->irq); 197 198 usb_free_urb(iforce->out); 198 199 usb_free_urb(iforce->ctrl); 199 - } 200 200 201 - static void iforce_usb_disconnect(struct usb_interface *intf) 202 - { 203 - struct iforce *iforce = usb_get_intfdata(intf); 204 - int open = 0; /* FIXME! iforce->dev.handle->open; */ 205 - 206 - usb_set_intfdata(intf, NULL); 207 - if (iforce) { 208 - iforce->usbdev = NULL; 209 - input_unregister_device(iforce->dev); 210 - 211 - if (!open) { 212 - iforce_delete_device(iforce); 213 - kfree(iforce); 214 - } 215 - } 201 + kfree(iforce); 216 202 } 217 203 218 204 static struct usb_device_id iforce_usb_ids [] = {
-2
drivers/input/joystick/iforce/iforce.h
··· 150 150 151 151 /* iforce-usb.c */ 152 152 void iforce_usb_xmit(struct iforce *iforce); 153 - void iforce_usb_delete(struct iforce *iforce); 154 153 155 154 /* iforce-main.c */ 156 155 int iforce_init_device(struct iforce *iforce); 157 - void iforce_delete_device(struct iforce *iforce); 158 156 159 157 /* iforce-packets.c */ 160 158 int iforce_control_playback(struct iforce*, u16 id, unsigned int);