From 6ee82524b0aa6433944db7a3999b9e122eb4d48f Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 29 Aug 2022 10:07:09 +0200 Subject: [PATCH] Revert "usbnet: smsc95xx: Forward PHY interrupts to PHY driver to avoid polling" This reverts commit eaf3a094d8924ecb0baacf6df62ae1c6a96083cf which is upstream commit 1ce8b37241ed291af56f7a49bbdbf20c08728e88. It is reported to cause problems, so drop it from the 5.15.y tree until the root cause can be determined. Reported-by: Lukas Wunner Cc: Oleksij Rempel Cc: Ferry Toth Cc: Andrew Lunn Cc: Andre Edich Cc: David S. Miller Cc: Sasha Levin Link: https://lore.kernel.org/r/20220826132137.GA24932@wunner.de Signed-off-by: Greg Kroah-Hartman --- drivers/net/usb/smsc95xx.c | 113 +++++++++++++++++++++------------------------ 1 file changed, 52 insertions(+), 61 deletions(-) diff --git a/drivers/net/usb/smsc95xx.c b/drivers/net/usb/smsc95xx.c index 3eb6219..7cf9206 100644 --- a/drivers/net/usb/smsc95xx.c +++ b/drivers/net/usb/smsc95xx.c @@ -18,8 +18,6 @@ #include #include #include -#include -#include #include #include #include "smsc95xx.h" @@ -53,9 +51,6 @@ #define SUSPEND_ALLMODES (SUSPEND_SUSPEND0 | SUSPEND_SUSPEND1 | \ SUSPEND_SUSPEND2 | SUSPEND_SUSPEND3) -#define SMSC95XX_NR_IRQS (1) /* raise to 12 for GPIOs */ -#define PHY_HWIRQ (SMSC95XX_NR_IRQS - 1) - struct smsc95xx_priv { u32 mac_cr; u32 hash_hi; @@ -64,9 +59,6 @@ struct smsc95xx_priv { spinlock_t mac_cr_lock; u8 features; u8 suspend_flags; - struct irq_chip irqchip; - struct irq_domain *irqdomain; - struct fwnode_handle *irqfwnode; struct mii_bus *mdiobus; struct phy_device *phydev; }; @@ -603,8 +595,6 @@ static void smsc95xx_mac_update_fullduplex(struct usbnet *dev) static void smsc95xx_status(struct usbnet *dev, struct urb *urb) { - struct smsc95xx_priv *pdata = dev->driver_priv; - unsigned long flags; u32 intdata; if (urb->actual_length != 4) { @@ -616,15 +606,11 @@ static void smsc95xx_status(struct usbnet *dev, struct urb *urb) intdata = get_unaligned_le32(urb->transfer_buffer); netif_dbg(dev, link, dev->net, "intdata: 0x%08X\n", intdata); - local_irq_save(flags); - if (intdata & INT_ENP_PHY_INT_) - generic_handle_domain_irq(pdata->irqdomain, PHY_HWIRQ); + ; else netdev_warn(dev->net, "unexpected interrupt, intdata=0x%08X\n", intdata); - - local_irq_restore(flags); } /* Enable or disable Tx & Rx checksum offload engines */ @@ -1086,9 +1072,8 @@ static int smsc95xx_bind(struct usbnet *dev, struct usb_interface *intf) { struct smsc95xx_priv *pdata; bool is_internal_phy; - char usb_path[64]; - int ret, phy_irq; u32 val; + int ret; printk(KERN_INFO SMSC_CHIPNAME " v" SMSC_DRIVER_VERSION "\n"); @@ -1128,38 +1113,10 @@ static int smsc95xx_bind(struct usbnet *dev, struct usb_interface *intf) if (ret) goto free_pdata; - /* create irq domain for use by PHY driver and GPIO consumers */ - usb_make_path(dev->udev, usb_path, sizeof(usb_path)); - pdata->irqfwnode = irq_domain_alloc_named_fwnode(usb_path); - if (!pdata->irqfwnode) { - ret = -ENOMEM; - goto free_pdata; - } - - pdata->irqdomain = irq_domain_create_linear(pdata->irqfwnode, - SMSC95XX_NR_IRQS, - &irq_domain_simple_ops, - pdata); - if (!pdata->irqdomain) { - ret = -ENOMEM; - goto free_irqfwnode; - } - - phy_irq = irq_create_mapping(pdata->irqdomain, PHY_HWIRQ); - if (!phy_irq) { - ret = -ENOENT; - goto remove_irqdomain; - } - - pdata->irqchip = dummy_irq_chip; - pdata->irqchip.name = SMSC_CHIPNAME; - irq_set_chip_and_handler_name(phy_irq, &pdata->irqchip, - handle_simple_irq, "phy"); - pdata->mdiobus = mdiobus_alloc(); if (!pdata->mdiobus) { ret = -ENOMEM; - goto dispose_irq; + goto free_pdata; } ret = smsc95xx_read_reg(dev, HW_CFG, &val); @@ -1192,7 +1149,6 @@ static int smsc95xx_bind(struct usbnet *dev, struct usb_interface *intf) goto unregister_mdio; } - pdata->phydev->irq = phy_irq; pdata->phydev->is_internal = is_internal_phy; /* detect device revision as different features may be available */ @@ -1235,15 +1191,6 @@ unregister_mdio: free_mdio: mdiobus_free(pdata->mdiobus); -dispose_irq: - irq_dispose_mapping(phy_irq); - -remove_irqdomain: - irq_domain_remove(pdata->irqdomain); - -free_irqfwnode: - irq_domain_free_fwnode(pdata->irqfwnode); - free_pdata: kfree(pdata); return ret; @@ -1256,9 +1203,6 @@ static void smsc95xx_unbind(struct usbnet *dev, struct usb_interface *intf) phy_disconnect(dev->net->phydev); mdiobus_unregister(pdata->mdiobus); mdiobus_free(pdata->mdiobus); - irq_dispose_mapping(irq_find_mapping(pdata->irqdomain, PHY_HWIRQ)); - irq_domain_remove(pdata->irqdomain); - irq_domain_free_fwnode(pdata->irqfwnode); netif_dbg(dev, ifdown, dev->net, "free pdata\n"); kfree(pdata); } @@ -1283,6 +1227,29 @@ static u32 smsc_crc(const u8 *buffer, size_t len, int filter) return crc << ((filter % 2) * 16); } +static int smsc95xx_enable_phy_wakeup_interrupts(struct usbnet *dev, u16 mask) +{ + int ret; + + netdev_dbg(dev->net, "enabling PHY wakeup interrupts\n"); + + /* read to clear */ + ret = smsc95xx_mdio_read_nopm(dev, PHY_INT_SRC); + if (ret < 0) + return ret; + + /* enable interrupt source */ + ret = smsc95xx_mdio_read_nopm(dev, PHY_INT_MASK); + if (ret < 0) + return ret; + + ret |= mask; + + smsc95xx_mdio_write_nopm(dev, PHY_INT_MASK, ret); + + return 0; +} + static int smsc95xx_link_ok_nopm(struct usbnet *dev) { int ret; @@ -1449,6 +1416,7 @@ static int smsc95xx_enter_suspend3(struct usbnet *dev) static int smsc95xx_autosuspend(struct usbnet *dev, u32 link_up) { struct smsc95xx_priv *pdata = dev->driver_priv; + int ret; if (!netif_running(dev->net)) { /* interface is ifconfig down so fully power down hw */ @@ -1467,10 +1435,27 @@ static int smsc95xx_autosuspend(struct usbnet *dev, u32 link_up) } netdev_dbg(dev->net, "autosuspend entering SUSPEND1\n"); + + /* enable PHY wakeup events for if cable is attached */ + ret = smsc95xx_enable_phy_wakeup_interrupts(dev, + PHY_INT_MASK_ANEG_COMP_); + if (ret < 0) { + netdev_warn(dev->net, "error enabling PHY wakeup ints\n"); + return ret; + } + netdev_info(dev->net, "entering SUSPEND1 mode\n"); return smsc95xx_enter_suspend1(dev); } + /* enable PHY wakeup events so we remote wakeup if cable is pulled */ + ret = smsc95xx_enable_phy_wakeup_interrupts(dev, + PHY_INT_MASK_LINK_DOWN_); + if (ret < 0) { + netdev_warn(dev->net, "error enabling PHY wakeup ints\n"); + return ret; + } + netdev_dbg(dev->net, "autosuspend entering SUSPEND3\n"); return smsc95xx_enter_suspend3(dev); } @@ -1536,6 +1521,13 @@ static int smsc95xx_suspend(struct usb_interface *intf, pm_message_t message) } if (pdata->wolopts & WAKE_PHY) { + ret = smsc95xx_enable_phy_wakeup_interrupts(dev, + (PHY_INT_MASK_ANEG_COMP_ | PHY_INT_MASK_LINK_DOWN_)); + if (ret < 0) { + netdev_warn(dev->net, "error enabling PHY wakeup ints\n"); + goto done; + } + /* if link is down then configure EDPD and enter SUSPEND1, * otherwise enter SUSPEND0 below */ @@ -1769,12 +1761,11 @@ static int smsc95xx_resume(struct usb_interface *intf) return ret; } - phy_init_hw(pdata->phydev); - ret = usbnet_resume(intf); if (ret < 0) netdev_warn(dev->net, "usbnet_resume error\n"); + phy_init_hw(pdata->phydev); return ret; } -- 2.7.4