Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

phy: qcom-qmp-usb: fix memleak on probe deferral

Switch to using the device-managed of_iomap helper to avoid leaking
memory on probe deferral and driver unbind.

Note that this helper checks for already reserved regions and may fail
if there are multiple devices claiming the same memory.

Two bindings currently rely on overlapping mappings for the PCS region
so fallback to non-exclusive mappings for those for now.

Fixes: e78f3d15e115 ("phy: qcom-qmp: new qmp phy driver for qcom-chipsets")
Signed-off-by: Johan Hovold <johan+linaro@kernel.org>
Link: https://lore.kernel.org/r/20220916102340.11520-7-johan+linaro@kernel.org
Signed-off-by: Vinod Koul <vkoul@kernel.org>

authored by

Johan Hovold and committed by
Vinod Koul
a5d6b1ac ef74a97f

+42 -15
+42 -15
drivers/phy/qualcomm/phy-qcom-qmp-usb.c
··· 2606 2606 .owner = THIS_MODULE, 2607 2607 }; 2608 2608 2609 + static void __iomem *qmp_usb_iomap(struct device *dev, struct device_node *np, 2610 + int index, bool exclusive) 2611 + { 2612 + struct resource res; 2613 + 2614 + if (!exclusive) { 2615 + if (of_address_to_resource(np, index, &res)) 2616 + return IOMEM_ERR_PTR(-EINVAL); 2617 + 2618 + return devm_ioremap(dev, res.start, resource_size(&res)); 2619 + } 2620 + 2621 + return devm_of_iomap(dev, np, index, NULL); 2622 + } 2623 + 2609 2624 static 2610 2625 int qmp_usb_create(struct device *dev, struct device_node *np, int id, 2611 2626 void __iomem *serdes, const struct qmp_phy_cfg *cfg) ··· 2628 2613 struct qcom_qmp *qmp = dev_get_drvdata(dev); 2629 2614 struct phy *generic_phy; 2630 2615 struct qmp_phy *qphy; 2616 + bool exclusive = true; 2631 2617 int ret; 2618 + 2619 + /* 2620 + * FIXME: These bindings should be fixed to not rely on overlapping 2621 + * mappings for PCS. 2622 + */ 2623 + if (of_device_is_compatible(dev->of_node, "qcom,sdx65-qmp-usb3-uni-phy")) 2624 + exclusive = false; 2625 + if (of_device_is_compatible(dev->of_node, "qcom,sm8350-qmp-usb3-uni-phy")) 2626 + exclusive = false; 2632 2627 2633 2628 qphy = devm_kzalloc(dev, sizeof(*qphy), GFP_KERNEL); 2634 2629 if (!qphy) ··· 2652 2627 * For dual lane PHYs: tx2 -> 3, rx2 -> 4, pcs_misc (optional) -> 5 2653 2628 * For single lane PHYs: pcs_misc (optional) -> 3. 2654 2629 */ 2655 - qphy->tx = of_iomap(np, 0); 2656 - if (!qphy->tx) 2657 - return -ENOMEM; 2630 + qphy->tx = devm_of_iomap(dev, np, 0, NULL); 2631 + if (IS_ERR(qphy->tx)) 2632 + return PTR_ERR(qphy->tx); 2658 2633 2659 - qphy->rx = of_iomap(np, 1); 2660 - if (!qphy->rx) 2661 - return -ENOMEM; 2634 + qphy->rx = devm_of_iomap(dev, np, 1, NULL); 2635 + if (IS_ERR(qphy->rx)) 2636 + return PTR_ERR(qphy->rx); 2662 2637 2663 - qphy->pcs = of_iomap(np, 2); 2664 - if (!qphy->pcs) 2665 - return -ENOMEM; 2638 + qphy->pcs = qmp_usb_iomap(dev, np, 2, exclusive); 2639 + if (IS_ERR(qphy->pcs)) 2640 + return PTR_ERR(qphy->pcs); 2666 2641 2667 2642 if (cfg->pcs_usb_offset) 2668 2643 qphy->pcs_usb = qphy->pcs + cfg->pcs_usb_offset; ··· 2674 2649 * offset from the first lane. 2675 2650 */ 2676 2651 if (cfg->is_dual_lane_phy) { 2677 - qphy->tx2 = of_iomap(np, 3); 2678 - qphy->rx2 = of_iomap(np, 4); 2679 - if (!qphy->tx2 || !qphy->rx2) { 2652 + qphy->tx2 = devm_of_iomap(dev, np, 3, NULL); 2653 + qphy->rx2 = devm_of_iomap(dev, np, 4, NULL); 2654 + if (IS_ERR(qphy->tx2) || IS_ERR(qphy->rx2)) { 2680 2655 dev_warn(dev, 2681 2656 "Underspecified device tree, falling back to legacy register regions\n"); 2682 2657 ··· 2686 2661 qphy->rx2 = qphy->rx + QMP_PHY_LEGACY_LANE_STRIDE; 2687 2662 2688 2663 } else { 2689 - qphy->pcs_misc = of_iomap(np, 5); 2664 + qphy->pcs_misc = devm_of_iomap(dev, np, 5, NULL); 2690 2665 } 2691 2666 2692 2667 } else { 2693 - qphy->pcs_misc = of_iomap(np, 3); 2668 + qphy->pcs_misc = devm_of_iomap(dev, np, 3, NULL); 2694 2669 } 2695 2670 2696 - if (!qphy->pcs_misc) 2671 + if (IS_ERR(qphy->pcs_misc)) { 2697 2672 dev_vdbg(dev, "PHY pcs_misc-reg not used\n"); 2673 + qphy->pcs_misc = NULL; 2674 + } 2698 2675 2699 2676 qphy->pipe_clk = devm_get_clk_from_child(dev, np, NULL); 2700 2677 if (IS_ERR(qphy->pipe_clk)) {