Signed-off-by: Matthew Wilcox <[email protected]>
---
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