diff options
author | Roger Quadros <rogerq@ti.com> | 2013-05-24 09:06:58 -0400 |
---|---|---|
committer | Tony Lindgren <tony@atomide.com> | 2013-06-12 13:04:10 -0400 |
commit | e41a5f88b374f7b1d87a72740d186be20cae4aa8 (patch) | |
tree | ab78d492ad43bc2d2fa4da344c1301edc9e5abf6 /arch/arm/mach-omap2/usb-host.c | |
parent | 82702ea11ddfe0e43382e1fa5b66d807d8114916 (diff) |
ARM: OMAP2+: omap-usb-host: Fix memory leaks
Fix memory leaks in the error path.
Also, use platform_device_register_full() to allocate
the platform devices and set platform data.
Signed-off-by: Roger Quadros <rogerq@ti.com>
Signed-off-by: Tony Lindgren <tony@atomide.com>
Diffstat (limited to 'arch/arm/mach-omap2/usb-host.c')
-rw-r--r-- | arch/arm/mach-omap2/usb-host.c | 106 |
1 files changed, 56 insertions, 50 deletions
diff --git a/arch/arm/mach-omap2/usb-host.c b/arch/arm/mach-omap2/usb-host.c index aa27d7f5cbb7..609b330e5110 100644 --- a/arch/arm/mach-omap2/usb-host.c +++ b/arch/arm/mach-omap2/usb-host.c | |||
@@ -28,6 +28,7 @@ | |||
28 | #include <linux/io.h> | 28 | #include <linux/io.h> |
29 | #include <linux/gpio.h> | 29 | #include <linux/gpio.h> |
30 | #include <linux/usb/phy.h> | 30 | #include <linux/usb/phy.h> |
31 | #include <linux/usb/nop-usb-xceiv.h> | ||
31 | 32 | ||
32 | #include "soc.h" | 33 | #include "soc.h" |
33 | #include "omap_device.h" | 34 | #include "omap_device.h" |
@@ -560,7 +561,8 @@ static int usbhs_add_regulator(char *name, char *dev_id, char *dev_supply, | |||
560 | struct regulator_init_data *reg_data; | 561 | struct regulator_init_data *reg_data; |
561 | struct fixed_voltage_config *config; | 562 | struct fixed_voltage_config *config; |
562 | struct platform_device *pdev; | 563 | struct platform_device *pdev; |
563 | int ret; | 564 | struct platform_device_info pdevinfo; |
565 | int ret = -ENOMEM; | ||
564 | 566 | ||
565 | supplies = kzalloc(sizeof(*supplies), GFP_KERNEL); | 567 | supplies = kzalloc(sizeof(*supplies), GFP_KERNEL); |
566 | if (!supplies) | 568 | if (!supplies) |
@@ -571,7 +573,7 @@ static int usbhs_add_regulator(char *name, char *dev_id, char *dev_supply, | |||
571 | 573 | ||
572 | reg_data = kzalloc(sizeof(*reg_data), GFP_KERNEL); | 574 | reg_data = kzalloc(sizeof(*reg_data), GFP_KERNEL); |
573 | if (!reg_data) | 575 | if (!reg_data) |
574 | return -ENOMEM; | 576 | goto err_data; |
575 | 577 | ||
576 | reg_data->constraints.valid_ops_mask = REGULATOR_CHANGE_STATUS; | 578 | reg_data->constraints.valid_ops_mask = REGULATOR_CHANGE_STATUS; |
577 | reg_data->consumer_supplies = supplies; | 579 | reg_data->consumer_supplies = supplies; |
@@ -580,39 +582,53 @@ static int usbhs_add_regulator(char *name, char *dev_id, char *dev_supply, | |||
580 | config = kmemdup(&hsusb_reg_config, sizeof(hsusb_reg_config), | 582 | config = kmemdup(&hsusb_reg_config, sizeof(hsusb_reg_config), |
581 | GFP_KERNEL); | 583 | GFP_KERNEL); |
582 | if (!config) | 584 | if (!config) |
583 | return -ENOMEM; | 585 | goto err_config; |
586 | |||
587 | config->supply_name = kstrdup(name, GFP_KERNEL); | ||
588 | if (!config->supply_name) | ||
589 | goto err_supplyname; | ||
584 | 590 | ||
585 | config->supply_name = name; | ||
586 | config->gpio = gpio; | 591 | config->gpio = gpio; |
587 | config->enable_high = polarity; | 592 | config->enable_high = polarity; |
588 | config->init_data = reg_data; | 593 | config->init_data = reg_data; |
589 | 594 | ||
590 | /* create a regulator device */ | 595 | /* create a regulator device */ |
591 | pdev = kzalloc(sizeof(*pdev), GFP_KERNEL); | 596 | memset(&pdevinfo, 0, sizeof(pdevinfo)); |
592 | if (!pdev) | 597 | pdevinfo.name = reg_name; |
593 | return -ENOMEM; | 598 | pdevinfo.id = PLATFORM_DEVID_AUTO; |
599 | pdevinfo.data = config; | ||
600 | pdevinfo.size_data = sizeof(*config); | ||
594 | 601 | ||
595 | pdev->id = PLATFORM_DEVID_AUTO; | 602 | pdev = platform_device_register_full(&pdevinfo); |
596 | pdev->name = reg_name; | 603 | if (IS_ERR(pdev)) { |
597 | pdev->dev.platform_data = config; | 604 | ret = PTR_ERR(pdev); |
605 | pr_err("%s: Failed registering regulator %s for %s : %d\n", | ||
606 | __func__, name, dev_id, ret); | ||
607 | goto err_register; | ||
608 | } | ||
598 | 609 | ||
599 | ret = platform_device_register(pdev); | 610 | return 0; |
600 | if (ret) | ||
601 | pr_err("%s: Failed registering regulator %s for %s\n", | ||
602 | __func__, name, dev_id); | ||
603 | 611 | ||
612 | err_register: | ||
613 | kfree(config->supply_name); | ||
614 | err_supplyname: | ||
615 | kfree(config); | ||
616 | err_config: | ||
617 | kfree(reg_data); | ||
618 | err_data: | ||
619 | kfree(supplies); | ||
604 | return ret; | 620 | return ret; |
605 | } | 621 | } |
606 | 622 | ||
623 | #define MAX_STR 20 | ||
624 | |||
607 | int usbhs_init_phys(struct usbhs_phy_data *phy, int num_phys) | 625 | int usbhs_init_phys(struct usbhs_phy_data *phy, int num_phys) |
608 | { | 626 | { |
609 | char *rail_name; | 627 | char rail_name[MAX_STR]; |
610 | int i, len; | 628 | int i; |
611 | struct platform_device *pdev; | 629 | struct platform_device *pdev; |
612 | char *phy_id; | 630 | char *phy_id; |
613 | 631 | struct platform_device_info pdevinfo; | |
614 | /* the phy_id will be something like "nop_usb_xceiv.1" */ | ||
615 | len = strlen(nop_name) + 3; /* 3 -> ".1" and NULL terminator */ | ||
616 | 632 | ||
617 | for (i = 0; i < num_phys; i++) { | 633 | for (i = 0; i < num_phys; i++) { |
618 | 634 | ||
@@ -627,25 +643,26 @@ int usbhs_init_phys(struct usbhs_phy_data *phy, int num_phys) | |||
627 | !gpio_is_valid(phy->vcc_gpio)) | 643 | !gpio_is_valid(phy->vcc_gpio)) |
628 | continue; | 644 | continue; |
629 | 645 | ||
630 | /* create a NOP PHY device */ | 646 | phy_id = kmalloc(MAX_STR, GFP_KERNEL); |
631 | pdev = kzalloc(sizeof(*pdev), GFP_KERNEL); | 647 | if (!phy_id) { |
632 | if (!pdev) | 648 | pr_err("%s: kmalloc() failed\n", __func__); |
633 | return -ENOMEM; | ||
634 | |||
635 | pdev->id = phy->port; | ||
636 | pdev->name = nop_name; | ||
637 | pdev->dev.platform_data = phy->platform_data; | ||
638 | |||
639 | phy_id = kmalloc(len, GFP_KERNEL); | ||
640 | if (!phy_id) | ||
641 | return -ENOMEM; | 649 | return -ENOMEM; |
650 | } | ||
642 | 651 | ||
643 | scnprintf(phy_id, len, "nop_usb_xceiv.%d\n", | 652 | /* create a NOP PHY device */ |
644 | pdev->id); | 653 | memset(&pdevinfo, 0, sizeof(pdevinfo)); |
645 | 654 | pdevinfo.name = nop_name; | |
646 | if (platform_device_register(pdev)) { | 655 | pdevinfo.id = phy->port; |
647 | pr_err("%s: Failed to register device %s\n", | 656 | pdevinfo.data = phy->platform_data; |
648 | __func__, phy_id); | 657 | pdevinfo.size_data = sizeof(struct nop_usb_xceiv_platform_data); |
658 | |||
659 | scnprintf(phy_id, MAX_STR, "nop_usb_xceiv.%d", | ||
660 | phy->port); | ||
661 | pdev = platform_device_register_full(&pdevinfo); | ||
662 | if (IS_ERR(pdev)) { | ||
663 | pr_err("%s: Failed to register device %s : %ld\n", | ||
664 | __func__, phy_id, PTR_ERR(pdev)); | ||
665 | kfree(phy_id); | ||
649 | continue; | 666 | continue; |
650 | } | 667 | } |
651 | 668 | ||
@@ -653,26 +670,15 @@ int usbhs_init_phys(struct usbhs_phy_data *phy, int num_phys) | |||
653 | 670 | ||
654 | /* Do we need RESET regulator ? */ | 671 | /* Do we need RESET regulator ? */ |
655 | if (gpio_is_valid(phy->reset_gpio)) { | 672 | if (gpio_is_valid(phy->reset_gpio)) { |
656 | 673 | scnprintf(rail_name, MAX_STR, | |
657 | rail_name = kmalloc(13, GFP_KERNEL); | 674 | "hsusb%d_reset", phy->port); |
658 | if (!rail_name) | ||
659 | return -ENOMEM; | ||
660 | |||
661 | scnprintf(rail_name, 13, "hsusb%d_reset", phy->port); | ||
662 | |||
663 | usbhs_add_regulator(rail_name, phy_id, "reset", | 675 | usbhs_add_regulator(rail_name, phy_id, "reset", |
664 | phy->reset_gpio, 1); | 676 | phy->reset_gpio, 1); |
665 | } | 677 | } |
666 | 678 | ||
667 | /* Do we need VCC regulator ? */ | 679 | /* Do we need VCC regulator ? */ |
668 | if (gpio_is_valid(phy->vcc_gpio)) { | 680 | if (gpio_is_valid(phy->vcc_gpio)) { |
669 | 681 | scnprintf(rail_name, MAX_STR, "hsusb%d_vcc", phy->port); | |
670 | rail_name = kmalloc(13, GFP_KERNEL); | ||
671 | if (!rail_name) | ||
672 | return -ENOMEM; | ||
673 | |||
674 | scnprintf(rail_name, 13, "hsusb%d_vcc", phy->port); | ||
675 | |||
676 | usbhs_add_regulator(rail_name, phy_id, "vcc", | 682 | usbhs_add_regulator(rail_name, phy_id, "vcc", |
677 | phy->vcc_gpio, phy->vcc_polarity); | 683 | phy->vcc_gpio, phy->vcc_polarity); |
678 | } | 684 | } |