diff mbox series

[2/4] cdc-acm: Convert acm_minors to XArray

Message ID 20190318211713.3462-3-willy@infradead.org (mailing list archive)
State New, archived
Headers show
Series Convert USB subsystem to XArray | expand

Commit Message

Matthew Wilcox March 18, 2019, 9:17 p.m. UTC
Signed-off-by: Matthew Wilcox <willy@infradead.org>
---
 drivers/usb/class/cdc-acm.c | 33 ++++++++++++++-------------------
 1 file changed, 14 insertions(+), 19 deletions(-)

Comments

Greg KH March 19, 2019, 12:14 p.m. UTC | #1
On Mon, Mar 18, 2019 at 02:17:11PM -0700, Matthew Wilcox wrote:
> Signed-off-by: Matthew Wilcox <willy@infradead.org>

Also something here saying acm_minors was an idr structure that is being
converted to xarray.

> ---
>  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);

So, the only thing "better" here is that you don't need a lock anymore?

Why not just replace the idr api "underneath" with xarray and then drop
all of the locks over time?

idr was just a wrapper on top of ida, what's one more :)

Anyway, no objection from me, I like tree-wide changes, and appreciate
the effort that goes into it.  Thanks for doing it.  If you fix up the
changelog entries for the ones that have none, I'll be glad to queue
these up.

thanks,

greg k-h
Oliver Neukum March 19, 2019, 12:39 p.m. UTC | #2
On Mo, 2019-03-18 at 14:17 -0700, Matthew Wilcox wrote:
> Signed-off-by: Matthew Wilcox <willy@infradead.org>

Straight replacement. Looks fine to me. But without
a commit message Greg would dismember both of us.

	Regards
		Oliver
Oliver Neukum March 19, 2019, 12:41 p.m. UTC | #3
On Di, 2019-03-19 at 13:14 +0100, Greg KH wrote:
> On Mon, Mar 18, 2019 at 02:17:11PM -0700, Matthew Wilcox wrote:
> > Signed-off-by: Matthew Wilcox <willy@infradead.org>

[..]
> >  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);
> 
> So, the only thing "better" here is that you don't need a lock anymore?

Once this is accepted I can reduce the locking to a per instance
spinlock. But to start with a straight conversion is best.

	Regards
		Oliver
Matthew Wilcox March 19, 2019, 1:29 p.m. UTC | #4
On Tue, Mar 19, 2019 at 01:14:20PM +0100, Greg KH wrote:
> On Mon, Mar 18, 2019 at 02:17:11PM -0700, Matthew Wilcox wrote:
> > Signed-off-by: Matthew Wilcox <willy@infradead.org>
> 
> Also something here saying acm_minors was an idr structure that is being
> converted to xarray.

ACK.

> > @@ -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);
> 
> So, the only thing "better" here is that you don't need a lock anymore?

As far as this driver is concerned, I think that's the only advantage.
Other drivers see more advantages.

> Why not just replace the idr api "underneath" with xarray and then drop
> all of the locks over time?
> 
> idr was just a wrapper on top of ida, what's one more :)

umm, IDR was never a wrapper over IDA.  Originally, it was its own data
structure, then IDA was grafted on top of IDR, then I merged the IDR
and radix tree, now I'm replacing both the IDR and the radix tree.

> Anyway, no objection from me, I like tree-wide changes, and appreciate
> the effort that goes into it.  Thanks for doing it.  If you fix up the
> changelog entries for the ones that have none, I'll be glad to queue
> these up.

Thanks.
diff mbox series

Patch

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);