Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 83ef344a authored by brian@murphy.dk's avatar brian@murphy.dk Committed by Greg Kroah-Hartman
Browse files

[PATCH] USB: fix usb reference count bug in cdc-acm driver



This increases the reference count on the usb cdc acm control interface
which is referred to by the tty interface provided by the driver. This
allows the deferred removal of the tty after the physical device is
disconnected if the tty is held open at the time of disconnection.

Signed-off-by: default avatar <brian@murphy.dk>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent a3fdf4eb
Loading
Loading
Loading
Loading
+16 −15
Original line number Diff line number Diff line
@@ -422,6 +422,17 @@ static int acm_tty_open(struct tty_struct *tty, struct file *filp)
	return -EIO;
}

static void acm_tty_unregister(struct acm *acm)
{
	tty_unregister_device(acm_tty_driver, acm->minor);
	usb_put_intf(acm->control);
	acm_table[acm->minor] = NULL;
	usb_free_urb(acm->ctrlurb);
	usb_free_urb(acm->readurb);
	usb_free_urb(acm->writeurb);
	kfree(acm);
}

static void acm_tty_close(struct tty_struct *tty, struct file *filp)
{
	struct acm *acm = tty->driver_data;
@@ -436,14 +447,8 @@ static void acm_tty_close(struct tty_struct *tty, struct file *filp)
			usb_kill_urb(acm->ctrlurb);
			usb_kill_urb(acm->writeurb);
			usb_kill_urb(acm->readurb);
		} else {
			tty_unregister_device(acm_tty_driver, acm->minor);
			acm_table[acm->minor] = NULL;
			usb_free_urb(acm->ctrlurb);
			usb_free_urb(acm->readurb);
			usb_free_urb(acm->writeurb);
			kfree(acm);
		}
		} else
			acm_tty_unregister(acm);
	}
	up(&open_sem);
}
@@ -905,7 +910,8 @@ static int acm_probe (struct usb_interface *intf,

	usb_driver_claim_interface(&acm_driver, data_interface, acm);

	tty_register_device(acm_tty_driver, minor, &intf->dev);
	usb_get_intf(control_interface);
	tty_register_device(acm_tty_driver, minor, &control_interface->dev);

	acm_table[minor] = acm;
	usb_set_intfdata (intf, acm);
@@ -954,12 +960,7 @@ static void acm_disconnect(struct usb_interface *intf)
	usb_driver_release_interface(&acm_driver, acm->data);

	if (!acm->used) {
		tty_unregister_device(acm_tty_driver, acm->minor);
		acm_table[acm->minor] = NULL;
		usb_free_urb(acm->ctrlurb);
		usb_free_urb(acm->readurb);
		usb_free_urb(acm->writeurb);
		kfree(acm);
		acm_tty_unregister(acm);
		up(&open_sem);
		return;
	}