diff options
author | Russell King <rmk+kernel@arm.linux.org.uk> | 2015-10-03 14:13:02 -0400 |
---|---|---|
committer | Bjorn Helgaas <bhelgaas@google.com> | 2015-10-09 12:20:23 -0400 |
commit | 37bfa771cda1734454e4304050cfddbcda5f16ed (patch) | |
tree | f736c99b0145684331f1a1a8cbea2f1dc861b895 | |
parent | 49cb1f718360f86075341e35fad57748a5c182f9 (diff) |
PCI: mvebu: Fix memory leaks and refcount leaks
The mvebu PCI port parsing is weak due to:
1) allocations via kasprintf() were not cleaned up when we encounter an
error or decide to skip the port.
2) kasprintf() wasn't checked for failure.
3) of_get_named_gpio_flags() returns EPROBE_DEFER if the GPIO is not
present, not devm_gpio_request_one().
4) the of_node was not being put when terminating the loop.
Fix these oversights.
Tested-by: Willy Tarreau <w@1wt.eu> (Iomega iConnect Kirkwood, MiraBox Armada 370)
Tested-by: Andrew Lunn <andrew@lunn.ch> (D-Link DIR664 Kirkwood)
Tested-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com> (Armada XP GP)
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Reviewed-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
-rw-r--r-- | drivers/pci/host/pci-mvebu.c | 50 |
1 files changed, 43 insertions, 7 deletions
diff --git a/drivers/pci/host/pci-mvebu.c b/drivers/pci/host/pci-mvebu.c index 13ab0350f7fb..e8c51bb58e99 100644 --- a/drivers/pci/host/pci-mvebu.c +++ b/drivers/pci/host/pci-mvebu.c | |||
@@ -928,6 +928,13 @@ static int mvebu_pcie_resume(struct device *dev) | |||
928 | return 0; | 928 | return 0; |
929 | } | 929 | } |
930 | 930 | ||
931 | static void mvebu_pcie_port_clk_put(void *data) | ||
932 | { | ||
933 | struct mvebu_pcie_port *port = data; | ||
934 | |||
935 | clk_put(port->clk); | ||
936 | } | ||
937 | |||
931 | static int mvebu_pcie_parse_port(struct mvebu_pcie *pcie, | 938 | static int mvebu_pcie_parse_port(struct mvebu_pcie *pcie, |
932 | struct mvebu_pcie_port *port, struct device_node *child) | 939 | struct mvebu_pcie_port *port, struct device_node *child) |
933 | { | 940 | { |
@@ -946,7 +953,12 @@ static int mvebu_pcie_parse_port(struct mvebu_pcie *pcie, | |||
946 | if (of_property_read_u32(child, "marvell,pcie-lane", &port->lane)) | 953 | if (of_property_read_u32(child, "marvell,pcie-lane", &port->lane)) |
947 | port->lane = 0; | 954 | port->lane = 0; |
948 | 955 | ||
949 | port->name = kasprintf(GFP_KERNEL, "pcie%d.%d", port->port, port->lane); | 956 | port->name = devm_kasprintf(dev, GFP_KERNEL, "pcie%d.%d", port->port, |
957 | port->lane); | ||
958 | if (!port->name) { | ||
959 | ret = -ENOMEM; | ||
960 | goto err; | ||
961 | } | ||
950 | 962 | ||
951 | port->devfn = of_pci_get_devfn(child); | 963 | port->devfn = of_pci_get_devfn(child); |
952 | if (port->devfn < 0) | 964 | if (port->devfn < 0) |
@@ -960,20 +972,29 @@ static int mvebu_pcie_parse_port(struct mvebu_pcie *pcie, | |||
960 | goto skip; | 972 | goto skip; |
961 | } | 973 | } |
962 | 974 | ||
963 | if (resource_size(&pcie->io) != 0) | 975 | if (resource_size(&pcie->io) != 0) { |
964 | mvebu_get_tgt_attr(dev->of_node, port->devfn, IORESOURCE_IO, | 976 | mvebu_get_tgt_attr(dev->of_node, port->devfn, IORESOURCE_IO, |
965 | &port->io_target, &port->io_attr); | 977 | &port->io_target, &port->io_attr); |
966 | else { | 978 | } else { |
967 | port->io_target = -1; | 979 | port->io_target = -1; |
968 | port->io_attr = -1; | 980 | port->io_attr = -1; |
969 | } | 981 | } |
970 | 982 | ||
971 | port->reset_gpio = of_get_named_gpio_flags(child, "reset-gpios", 0, | 983 | port->reset_gpio = of_get_named_gpio_flags(child, "reset-gpios", 0, |
972 | &flags); | 984 | &flags); |
985 | if (port->reset_gpio == -EPROBE_DEFER) { | ||
986 | ret = port->reset_gpio; | ||
987 | goto err; | ||
988 | } | ||
989 | |||
973 | if (gpio_is_valid(port->reset_gpio)) { | 990 | if (gpio_is_valid(port->reset_gpio)) { |
974 | port->reset_active_low = flags & OF_GPIO_ACTIVE_LOW; | 991 | port->reset_active_low = flags & OF_GPIO_ACTIVE_LOW; |
975 | port->reset_name = kasprintf(GFP_KERNEL, "%s-reset", | 992 | port->reset_name = devm_kasprintf(dev, GFP_KERNEL, "%s-reset", |
976 | port->name); | 993 | port->name); |
994 | if (!port->reset_name) { | ||
995 | ret = -ENOMEM; | ||
996 | goto err; | ||
997 | } | ||
977 | 998 | ||
978 | ret = devm_gpio_request_one(dev, port->reset_gpio, | 999 | ret = devm_gpio_request_one(dev, port->reset_gpio, |
979 | GPIOF_DIR_OUT, port->reset_name); | 1000 | GPIOF_DIR_OUT, port->reset_name); |
@@ -990,10 +1011,23 @@ static int mvebu_pcie_parse_port(struct mvebu_pcie *pcie, | |||
990 | goto skip; | 1011 | goto skip; |
991 | } | 1012 | } |
992 | 1013 | ||
1014 | ret = devm_add_action(dev, mvebu_pcie_port_clk_put, port); | ||
1015 | if (ret < 0) { | ||
1016 | clk_put(port->clk); | ||
1017 | goto err; | ||
1018 | } | ||
1019 | |||
993 | return 1; | 1020 | return 1; |
994 | 1021 | ||
995 | skip: | 1022 | skip: |
996 | ret = 0; | 1023 | ret = 0; |
1024 | |||
1025 | /* In the case of skipping, we need to free these */ | ||
1026 | devm_kfree(dev, port->reset_name); | ||
1027 | port->reset_name = NULL; | ||
1028 | devm_kfree(dev, port->name); | ||
1029 | port->name = NULL; | ||
1030 | |||
997 | err: | 1031 | err: |
998 | return ret; | 1032 | return ret; |
999 | } | 1033 | } |
@@ -1052,10 +1086,12 @@ static int mvebu_pcie_probe(struct platform_device *pdev) | |||
1052 | struct mvebu_pcie_port *port = &pcie->ports[i]; | 1086 | struct mvebu_pcie_port *port = &pcie->ports[i]; |
1053 | 1087 | ||
1054 | ret = mvebu_pcie_parse_port(pcie, port, child); | 1088 | ret = mvebu_pcie_parse_port(pcie, port, child); |
1055 | if (ret < 0) | 1089 | if (ret < 0) { |
1090 | of_node_put(child); | ||
1056 | return ret; | 1091 | return ret; |
1057 | else if (ret == 0) | 1092 | } else if (ret == 0) { |
1058 | continue; | 1093 | continue; |
1094 | } | ||
1059 | 1095 | ||
1060 | if (gpio_is_valid(port->reset_gpio)) { | 1096 | if (gpio_is_valid(port->reset_gpio)) { |
1061 | u32 reset_udelay = 20000; | 1097 | u32 reset_udelay = 20000; |