Skip to content

Commit de76809

Browse files
claudiubezneavinodkoul
authored andcommitted
phy: renesas: rcar-gen3-usb2: Move IRQ request in probe
Commit 08b0ad3 ("phy: renesas: rcar-gen3-usb2: move IRQ registration to init") moved the IRQ request operation from probe to struct phy_ops::phy_init API to avoid triggering interrupts (which lead to register accesses) while the PHY clocks (enabled through runtime PM APIs) are not active. If this happens, it results in a synchronous abort. One way to reproduce this issue is by enabling CONFIG_DEBUG_SHIRQ, which calls free_irq() on driver removal. Move the IRQ request and free operations back to probe, and take the runtime PM state into account in IRQ handler. This commit is preparatory for the subsequent fixes in this series. Reviewed-by: Yoshihiro Shimoda <[email protected]> Tested-by: Yoshihiro Shimoda <[email protected]> Reviewed-by: Lad Prabhakar <[email protected]> Signed-off-by: Claudiu Beznea <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Vinod Koul <[email protected]>
1 parent 54c4c58 commit de76809

File tree

1 file changed

+26
-20
lines changed

1 file changed

+26
-20
lines changed

drivers/phy/renesas/phy-rcar-gen3-usb2.c

Lines changed: 26 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,6 @@ struct rcar_gen3_chan {
120120
struct work_struct work;
121121
struct mutex lock; /* protects rphys[...].powered */
122122
enum usb_dr_mode dr_mode;
123-
int irq;
124123
u32 obint_enable_bits;
125124
bool extcon_host;
126125
bool is_otg_channel;
@@ -428,16 +427,25 @@ static irqreturn_t rcar_gen3_phy_usb2_irq(int irq, void *_ch)
428427
{
429428
struct rcar_gen3_chan *ch = _ch;
430429
void __iomem *usb2_base = ch->base;
431-
u32 status = readl(usb2_base + USB2_OBINTSTA);
430+
struct device *dev = ch->dev;
432431
irqreturn_t ret = IRQ_NONE;
432+
u32 status;
433433

434+
pm_runtime_get_noresume(dev);
435+
436+
if (pm_runtime_suspended(dev))
437+
goto rpm_put;
438+
439+
status = readl(usb2_base + USB2_OBINTSTA);
434440
if (status & ch->obint_enable_bits) {
435-
dev_vdbg(ch->dev, "%s: %08x\n", __func__, status);
441+
dev_vdbg(dev, "%s: %08x\n", __func__, status);
436442
writel(ch->obint_enable_bits, usb2_base + USB2_OBINTSTA);
437443
rcar_gen3_device_recognition(ch);
438444
ret = IRQ_HANDLED;
439445
}
440446

447+
rpm_put:
448+
pm_runtime_put_noidle(dev);
441449
return ret;
442450
}
443451

@@ -447,17 +455,6 @@ static int rcar_gen3_phy_usb2_init(struct phy *p)
447455
struct rcar_gen3_chan *channel = rphy->ch;
448456
void __iomem *usb2_base = channel->base;
449457
u32 val;
450-
int ret;
451-
452-
if (!rcar_gen3_is_any_rphy_initialized(channel) && channel->irq >= 0) {
453-
INIT_WORK(&channel->work, rcar_gen3_phy_usb2_work);
454-
ret = request_irq(channel->irq, rcar_gen3_phy_usb2_irq,
455-
IRQF_SHARED, dev_name(channel->dev), channel);
456-
if (ret < 0) {
457-
dev_err(channel->dev, "No irq handler (%d)\n", channel->irq);
458-
return ret;
459-
}
460-
}
461458

462459
/* Initialize USB2 part */
463460
val = readl(usb2_base + USB2_INT_ENABLE);
@@ -490,9 +487,6 @@ static int rcar_gen3_phy_usb2_exit(struct phy *p)
490487
val &= ~USB2_INT_ENABLE_UCOM_INTEN;
491488
writel(val, usb2_base + USB2_INT_ENABLE);
492489

493-
if (channel->irq >= 0 && !rcar_gen3_is_any_rphy_initialized(channel))
494-
free_irq(channel->irq, channel);
495-
496490
return 0;
497491
}
498492

@@ -698,7 +692,7 @@ static int rcar_gen3_phy_usb2_probe(struct platform_device *pdev)
698692
struct device *dev = &pdev->dev;
699693
struct rcar_gen3_chan *channel;
700694
struct phy_provider *provider;
701-
int ret = 0, i;
695+
int ret = 0, i, irq;
702696

703697
if (!dev->of_node) {
704698
dev_err(dev, "This driver needs device tree\n");
@@ -714,8 +708,6 @@ static int rcar_gen3_phy_usb2_probe(struct platform_device *pdev)
714708
return PTR_ERR(channel->base);
715709

716710
channel->obint_enable_bits = USB2_OBINT_BITS;
717-
/* get irq number here and request_irq for OTG in phy_init */
718-
channel->irq = platform_get_irq_optional(pdev, 0);
719711
channel->dr_mode = rcar_gen3_get_dr_mode(dev->of_node);
720712
if (channel->dr_mode != USB_DR_MODE_UNKNOWN) {
721713
channel->is_otg_channel = true;
@@ -784,6 +776,20 @@ static int rcar_gen3_phy_usb2_probe(struct platform_device *pdev)
784776
channel->vbus = NULL;
785777
}
786778

779+
irq = platform_get_irq_optional(pdev, 0);
780+
if (irq < 0 && irq != -ENXIO) {
781+
ret = irq;
782+
goto error;
783+
} else if (irq > 0) {
784+
INIT_WORK(&channel->work, rcar_gen3_phy_usb2_work);
785+
ret = devm_request_irq(dev, irq, rcar_gen3_phy_usb2_irq,
786+
IRQF_SHARED, dev_name(dev), channel);
787+
if (ret < 0) {
788+
dev_err(dev, "Failed to request irq (%d)\n", irq);
789+
goto error;
790+
}
791+
}
792+
787793
provider = devm_of_phy_provider_register(dev, rcar_gen3_phy_usb2_xlate);
788794
if (IS_ERR(provider)) {
789795
dev_err(dev, "Failed to register PHY provider\n");

0 commit comments

Comments
 (0)