Signed-off-by: Matthew Wilcox <willy@xxxxxxxxxxxxx> --- drivers/usb/class/cdc-acm.c | 33 ++++++++++++++------------------- 1 file changed, 14 insertions(+), 19 deletions(-) diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index 739f8960811a..28eb9a898b4a 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -47,7 +47,7 @@ static struct usb_driver acm_driver; static struct tty_driver *acm_tty_driver; -static DEFINE_IDR(acm_minors); +static DEFINE_XARRAY_ALLOC(acm_minors); static DEFINE_MUTEX(acm_minors_lock); static void acm_tty_set_termios(struct tty_struct *tty, @@ -66,7 +66,7 @@ static struct acm *acm_get_by_minor(unsigned int minor) struct acm *acm; mutex_lock(&acm_minors_lock); - acm = idr_find(&acm_minors, minor); + acm = xa_load(&acm_minors, minor); if (acm) { mutex_lock(&acm->mutex); if (acm->disconnected) { @@ -86,20 +86,15 @@ static struct acm *acm_get_by_minor(unsigned int minor) */ static int acm_alloc_minor(struct acm *acm) { - int minor; - - mutex_lock(&acm_minors_lock); - minor = idr_alloc(&acm_minors, acm, 0, ACM_TTY_MINORS, GFP_KERNEL); - mutex_unlock(&acm_minors_lock); - - return minor; + return xa_alloc(&acm_minors, &acm->minor, acm, + XA_LIMIT(0, ACM_TTY_MINORS - 1), GFP_KERNEL); } /* Release the minor number associated with 'acm'. */ static void acm_release_minor(struct acm *acm) { mutex_lock(&acm_minors_lock); - idr_remove(&acm_minors, acm->minor); + xa_erase(&acm_minors, acm->minor); mutex_unlock(&acm_minors_lock); } @@ -1130,7 +1125,6 @@ static int acm_probe(struct usb_interface *intf, struct usb_device *usb_dev = interface_to_usbdev(intf); struct usb_cdc_parsed_header h; struct acm *acm; - int minor; int ctrlsize, readsize; u8 *buf; int call_intf_num = -1; @@ -1302,9 +1296,10 @@ static int acm_probe(struct usb_interface *intf, tty_port_init(&acm->port); acm->port.ops = &acm_port_ops; - minor = acm_alloc_minor(acm); - if (minor < 0) - goto alloc_fail1; + rv = acm_alloc_minor(acm); + if (rv < 0) + goto alloc_fail0; + rv = -ENOMEM; ctrlsize = usb_endpoint_maxp(epctrl); readsize = usb_endpoint_maxp(epread) * @@ -1313,7 +1308,6 @@ static int acm_probe(struct usb_interface *intf, acm->writesize = usb_endpoint_maxp(epwrite) * 20; acm->control = control_interface; acm->data = data_interface; - acm->minor = minor; acm->dev = usb_dev; if (h.usb_cdc_acm_descriptor) acm->ctrl_caps = h.usb_cdc_acm_descriptor->bmCapabilities; @@ -1450,7 +1444,7 @@ static int acm_probe(struct usb_interface *intf, acm->nb_index = 0; acm->nb_size = 0; - dev_info(&intf->dev, "ttyACM%d: USB ACM device\n", minor); + dev_info(&intf->dev, "ttyACM%d: USB ACM device\n", acm->minor); acm->line.dwDTERate = cpu_to_le32(9600); acm->line.bDataBits = 8; @@ -1460,8 +1454,8 @@ static int acm_probe(struct usb_interface *intf, usb_set_intfdata(data_interface, acm); usb_get_intf(control_interface); - tty_dev = tty_port_register_device(&acm->port, acm_tty_driver, minor, - &control_interface->dev); + tty_dev = tty_port_register_device(&acm->port, acm_tty_driver, + acm->minor, &control_interface->dev); if (IS_ERR(tty_dev)) { rv = PTR_ERR(tty_dev); goto alloc_fail6; @@ -1496,6 +1490,8 @@ static int acm_probe(struct usb_interface *intf, alloc_fail2: usb_free_coherent(usb_dev, ctrlsize, acm->ctrl_buffer, acm->ctrl_dma); alloc_fail1: + acm_release_minor(acm); +alloc_fail0: tty_port_put(&acm->port); alloc_fail: return rv; @@ -1986,7 +1982,6 @@ static void __exit acm_exit(void) usb_deregister(&acm_driver); tty_unregister_driver(acm_tty_driver); put_tty_driver(acm_tty_driver); - idr_destroy(&acm_minors); } module_init(acm_init); -- 2.20.1