diff options
author | Takashi Iwai <tiwai@suse.de> | 2015-01-23 06:27:39 -0500 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2015-01-28 01:20:21 -0500 |
commit | 6b562f63dd603443c97c885daa2b88bff700b2dc (patch) | |
tree | 9ea79c17cbc302284385739f95ccbe5d23ba0677 /sound/usb/line6 | |
parent | 644d90850c65c6ac5698e4fadb01682196a25eea (diff) |
ALSA: line6: Fix memory leak at probe error path
Fix memory leak at probe error path by rearranging the call order in
line6_destruct() so that the common destructor is always called.
Also this simplifies the error path to a single goto label.
Tested-by: Chris Rorvick <chris@rorvick.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/usb/line6')
-rw-r--r-- | sound/usb/line6/driver.c | 59 |
1 files changed, 30 insertions, 29 deletions
diff --git a/sound/usb/line6/driver.c b/sound/usb/line6/driver.c index b783c0788e45..bf9630cd2395 100644 --- a/sound/usb/line6/driver.c +++ b/sound/usb/line6/driver.c | |||
@@ -507,39 +507,20 @@ int line6_probe(struct usb_interface *interface, | |||
507 | int interface_number; | 507 | int interface_number; |
508 | int ret; | 508 | int ret; |
509 | 509 | ||
510 | /* we don't handle multiple configurations */ | 510 | ret = snd_card_new(&interface->dev, |
511 | if (usbdev->descriptor.bNumConfigurations != 1) { | 511 | SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1, |
512 | ret = -ENODEV; | 512 | THIS_MODULE, 0, &card); |
513 | goto err_put; | ||
514 | } | ||
515 | |||
516 | /* initialize device info: */ | ||
517 | dev_info(&interface->dev, "Line 6 %s found\n", properties->name); | ||
518 | |||
519 | /* query interface number */ | ||
520 | interface_number = interface->cur_altsetting->desc.bInterfaceNumber; | ||
521 | |||
522 | ret = usb_set_interface(usbdev, interface_number, | ||
523 | properties->altsetting); | ||
524 | if (ret < 0) { | 513 | if (ret < 0) { |
525 | dev_err(&interface->dev, "set_interface failed\n"); | 514 | kfree(line6); |
526 | goto err_put; | 515 | return ret; |
527 | } | 516 | } |
528 | 517 | ||
529 | /* store basic data: */ | 518 | /* store basic data: */ |
519 | line6->card = card; | ||
530 | line6->properties = properties; | 520 | line6->properties = properties; |
531 | line6->usbdev = usbdev; | 521 | line6->usbdev = usbdev; |
532 | line6->ifcdev = &interface->dev; | 522 | line6->ifcdev = &interface->dev; |
533 | 523 | ||
534 | line6_get_interval(line6); | ||
535 | |||
536 | ret = snd_card_new(line6->ifcdev, | ||
537 | SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1, | ||
538 | THIS_MODULE, 0, &card); | ||
539 | if (ret < 0) | ||
540 | goto err_put; | ||
541 | |||
542 | line6->card = card; | ||
543 | strcpy(card->id, line6->properties->id); | 524 | strcpy(card->id, line6->properties->id); |
544 | strcpy(card->driver, DRIVER_NAME); | 525 | strcpy(card->driver, DRIVER_NAME); |
545 | strcpy(card->shortname, line6->properties->name); | 526 | strcpy(card->shortname, line6->properties->name); |
@@ -553,16 +534,37 @@ int line6_probe(struct usb_interface *interface, | |||
553 | /* increment reference counters: */ | 534 | /* increment reference counters: */ |
554 | usb_get_dev(usbdev); | 535 | usb_get_dev(usbdev); |
555 | 536 | ||
537 | /* we don't handle multiple configurations */ | ||
538 | if (usbdev->descriptor.bNumConfigurations != 1) { | ||
539 | ret = -ENODEV; | ||
540 | goto error; | ||
541 | } | ||
542 | |||
543 | /* initialize device info: */ | ||
544 | dev_info(&interface->dev, "Line 6 %s found\n", properties->name); | ||
545 | |||
546 | /* query interface number */ | ||
547 | interface_number = interface->cur_altsetting->desc.bInterfaceNumber; | ||
548 | |||
549 | ret = usb_set_interface(usbdev, interface_number, | ||
550 | properties->altsetting); | ||
551 | if (ret < 0) { | ||
552 | dev_err(&interface->dev, "set_interface failed\n"); | ||
553 | goto error; | ||
554 | } | ||
555 | |||
556 | line6_get_interval(line6); | ||
557 | |||
556 | if (properties->capabilities & LINE6_CAP_CONTROL) { | 558 | if (properties->capabilities & LINE6_CAP_CONTROL) { |
557 | ret = line6_init_cap_control(line6); | 559 | ret = line6_init_cap_control(line6); |
558 | if (ret < 0) | 560 | if (ret < 0) |
559 | goto err_destruct; | 561 | goto error; |
560 | } | 562 | } |
561 | 563 | ||
562 | /* initialize device data based on device: */ | 564 | /* initialize device data based on device: */ |
563 | ret = private_init(interface, line6); | 565 | ret = private_init(interface, line6); |
564 | if (ret < 0) | 566 | if (ret < 0) |
565 | goto err_destruct; | 567 | goto error; |
566 | 568 | ||
567 | /* creation of additional special files should go here */ | 569 | /* creation of additional special files should go here */ |
568 | 570 | ||
@@ -571,11 +573,10 @@ int line6_probe(struct usb_interface *interface, | |||
571 | 573 | ||
572 | return 0; | 574 | return 0; |
573 | 575 | ||
574 | err_destruct: | 576 | error: |
575 | if (line6->disconnect) | 577 | if (line6->disconnect) |
576 | line6->disconnect(interface); | 578 | line6->disconnect(interface); |
577 | snd_card_free(card); | 579 | snd_card_free(card); |
578 | err_put: | ||
579 | return ret; | 580 | return ret; |
580 | } | 581 | } |
581 | EXPORT_SYMBOL_GPL(line6_probe); | 582 | EXPORT_SYMBOL_GPL(line6_probe); |