Merge tag 'v5.15.64' into rpi-5.15.y
authorDom Cobley <popcornmix@gmail.com>
Mon, 5 Sep 2022 11:46:18 +0000 (12:46 +0100)
committerDom Cobley <popcornmix@gmail.com>
Mon, 5 Sep 2022 11:46:18 +0000 (12:46 +0100)
This is the 5.15.64 stable release

1  2 
drivers/net/usb/smsc95xx.c
kernel/cgroup/cgroup.c

@@@ -18,8 -18,6 +18,6 @@@
  #include <linux/usb/usbnet.h>
  #include <linux/slab.h>
  #include <linux/of_net.h>
- #include <linux/irq.h>
- #include <linux/irqdomain.h>
  #include <linux/mdio.h>
  #include <linux/phy.h>
  #include "smsc95xx.h"
  #define SUSPEND_SUSPEND3              (0x08)
  #define SUSPEND_ALLMODES              (SUSPEND_SUSPEND0 | SUSPEND_SUSPEND1 | \
                                         SUSPEND_SUSPEND2 | SUSPEND_SUSPEND3)
 +#define MAC_ADDR_LEN                    (6)
  
- #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;
        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;
-       struct task_struct *pm_task;
  };
  
  static bool turbo_mode = true;
  module_param(turbo_mode, bool, 0644);
  MODULE_PARM_DESC(turbo_mode, "Enable multiple frames per Rx transaction");
  
 +static bool truesize_mode = false;
 +module_param(truesize_mode, bool, 0644);
 +MODULE_PARM_DESC(truesize_mode, "Report larger truesize value");
 +
 +static int packetsize = 2560;
 +module_param(packetsize, int, 0644);
 +MODULE_PARM_DESC(packetsize, "Override the RX URB packet size");
 +
 +static char *macaddr = ":";
 +module_param(macaddr, charp, 0);
 +MODULE_PARM_DESC(macaddr, "MAC address");
 +
  static int __must_check __smsc95xx_read_reg(struct usbnet *dev, u32 index,
                                            u32 *data, int in_pm)
  {
-       struct smsc95xx_priv *pdata = dev->driver_priv;
        u32 buf;
        int ret;
        int (*fn)(struct usbnet *, u8, u8, u16, u16, void *, u16);
  
        BUG_ON(!dev);
  
-       if (current != pdata->pm_task)
+       if (!in_pm)
                fn = usbnet_read_cmd;
        else
                fn = usbnet_read_cmd_nopm;
  static int __must_check __smsc95xx_write_reg(struct usbnet *dev, u32 index,
                                             u32 data, int in_pm)
  {
-       struct smsc95xx_priv *pdata = dev->driver_priv;
        u32 buf;
        int ret;
        int (*fn)(struct usbnet *, u8, u8, u16, u16, const void *, u16);
  
        BUG_ON(!dev);
  
-       if (current != pdata->pm_task)
+       if (!in_pm)
                fn = usbnet_write_cmd;
        else
                fn = usbnet_write_cmd_nopm;
@@@ -619,8 -595,6 +608,6 @@@ static void smsc95xx_mac_update_fulldup
  
  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) {
        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 */
@@@ -793,53 -763,6 +776,53 @@@ static int smsc95xx_ioctl(struct net_de
        return phy_mii_ioctl(netdev->phydev, rq, cmd);
  }
  
 +/* Check the macaddr module parameter for a MAC address */
 +static int smsc95xx_is_macaddr_param(struct usbnet *dev, u8 *dev_mac)
 +{
 +       int i, j, got_num, num;
 +       u8 mtbl[MAC_ADDR_LEN];
 +
 +       if (macaddr[0] == ':')
 +               return 0;
 +
 +       i = 0;
 +       j = 0;
 +       num = 0;
 +       got_num = 0;
 +       while (j < MAC_ADDR_LEN) {
 +               if (macaddr[i] && macaddr[i] != ':') {
 +                       got_num++;
 +                       if ('0' <= macaddr[i] && macaddr[i] <= '9')
 +                               num = num * 16 + macaddr[i] - '0';
 +                       else if ('A' <= macaddr[i] && macaddr[i] <= 'F')
 +                               num = num * 16 + 10 + macaddr[i] - 'A';
 +                       else if ('a' <= macaddr[i] && macaddr[i] <= 'f')
 +                               num = num * 16 + 10 + macaddr[i] - 'a';
 +                       else
 +                               break;
 +                       i++;
 +               } else if (got_num == 2) {
 +                       mtbl[j++] = (u8) num;
 +                       num = 0;
 +                       got_num = 0;
 +                       i++;
 +               } else {
 +                       break;
 +               }
 +       }
 +
 +       if (j == MAC_ADDR_LEN) {
 +               netif_dbg(dev, ifup, dev->net, "Overriding MAC address with: "
 +               "%02x:%02x:%02x:%02x:%02x:%02x\n", mtbl[0], mtbl[1], mtbl[2],
 +                                               mtbl[3], mtbl[4], mtbl[5]);
 +               for (i = 0; i < MAC_ADDR_LEN; i++)
 +                       dev_mac[i] = mtbl[i];
 +               return 1;
 +       } else {
 +               return 0;
 +       }
 +}
 +
  static void smsc95xx_init_mac_address(struct usbnet *dev)
  {
        /* maybe the boot loader passed the MAC address in devicetree */
                }
        }
  
 +      /* Check module parameters */
 +      if (smsc95xx_is_macaddr_param(dev, dev->net->dev_addr))
 +              return;
 +
        /* no useful static MAC address found. generate a random one */
        eth_hw_addr_random(dev->net);
        netif_dbg(dev, ifup, dev->net, "MAC address set to eth_random_addr\n");
@@@ -992,13 -911,13 +975,13 @@@ static int smsc95xx_reset(struct usbne
  
        if (!turbo_mode) {
                burst_cap = 0;
 -              dev->rx_urb_size = MAX_SINGLE_PACKET_SIZE;
 +              dev->rx_urb_size = packetsize ? packetsize : MAX_SINGLE_PACKET_SIZE;
        } else if (dev->udev->speed == USB_SPEED_HIGH) {
 -              burst_cap = DEFAULT_HS_BURST_CAP_SIZE / HS_USB_PKT_SIZE;
 -              dev->rx_urb_size = DEFAULT_HS_BURST_CAP_SIZE;
 +              dev->rx_urb_size = packetsize ? packetsize : DEFAULT_HS_BURST_CAP_SIZE;
 +              burst_cap = dev->rx_urb_size / HS_USB_PKT_SIZE;
        } else {
 -              burst_cap = DEFAULT_FS_BURST_CAP_SIZE / FS_USB_PKT_SIZE;
 -              dev->rx_urb_size = DEFAULT_FS_BURST_CAP_SIZE;
 +              dev->rx_urb_size = packetsize ? packetsize : DEFAULT_FS_BURST_CAP_SIZE;
 +              burst_cap = dev->rx_urb_size / FS_USB_PKT_SIZE;
        }
  
        netif_dbg(dev, ifup, dev->net, "rx_urb_size=%ld\n",
@@@ -1153,9 -1072,8 +1136,8 @@@ static int smsc95xx_bind(struct usbnet 
  {
        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");
  
        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);
                goto unregister_mdio;
        }
  
-       pdata->phydev->irq = phy_irq;
        pdata->phydev->is_internal = is_internal_phy;
  
        /* detect device revision as different features may be available */
@@@ -1302,15 -1191,6 +1255,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;
@@@ -1323,9 -1203,6 +1267,6 @@@ static void smsc95xx_unbind(struct usbn
        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);
  }
@@@ -1350,6 -1227,29 +1291,29 @@@ static u32 smsc_crc(const u8 *buffer, s
        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;
@@@ -1516,6 -1416,7 +1480,7 @@@ static int smsc95xx_enter_suspend3(stru
  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 */
                }
  
                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);
  }
@@@ -1549,12 -1467,9 +1531,9 @@@ static int smsc95xx_suspend(struct usb_
        u32 val, link_up;
        int ret;
  
-       pdata->pm_task = current;
        ret = usbnet_suspend(intf, message);
        if (ret < 0) {
                netdev_warn(dev->net, "usbnet_suspend error\n");
-               pdata->pm_task = NULL;
                return ret;
        }
  
        }
  
        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
                 */
@@@ -1794,7 -1716,6 +1780,6 @@@ done
        if (ret && PMSG_IS_AUTO(message))
                usbnet_resume(intf);
  
-       pdata->pm_task = NULL;
        return ret;
  }
  
@@@ -1815,53 -1736,45 +1800,45 @@@ static int smsc95xx_resume(struct usb_i
        /* do this first to ensure it's cleared even in error case */
        pdata->suspend_flags = 0;
  
-       pdata->pm_task = current;
        if (suspend_flags & SUSPEND_ALLMODES) {
                /* clear wake-up sources */
                ret = smsc95xx_read_reg_nopm(dev, WUCSR, &val);
                if (ret < 0)
-                       goto done;
+                       return ret;
  
                val &= ~(WUCSR_WAKE_EN_ | WUCSR_MPEN_);
  
                ret = smsc95xx_write_reg_nopm(dev, WUCSR, val);
                if (ret < 0)
-                       goto done;
+                       return ret;
  
                /* clear wake-up status */
                ret = smsc95xx_read_reg_nopm(dev, PM_CTRL, &val);
                if (ret < 0)
-                       goto done;
+                       return ret;
  
                val &= ~PM_CTL_WOL_EN_;
                val |= PM_CTL_WUPS_;
  
                ret = smsc95xx_write_reg_nopm(dev, PM_CTRL, val);
                if (ret < 0)
-                       goto done;
+                       return ret;
        }
  
-       phy_init_hw(pdata->phydev);
        ret = usbnet_resume(intf);
        if (ret < 0)
                netdev_warn(dev->net, "usbnet_resume error\n");
  
- done:
-       pdata->pm_task = NULL;
+       phy_init_hw(pdata->phydev);
        return ret;
  }
  
  static int smsc95xx_reset_resume(struct usb_interface *intf)
  {
        struct usbnet *dev = usb_get_intfdata(intf);
-       struct smsc95xx_priv *pdata = dev->driver_priv;
        int ret;
  
-       pdata->pm_task = current;
        ret = smsc95xx_reset(dev);
-       pdata->pm_task = NULL;
        if (ret < 0)
                return ret;
  
@@@ -1924,8 -1837,7 +1901,8 @@@ static int smsc95xx_rx_fixup(struct usb
                                if (dev->net->features & NETIF_F_RXCSUM)
                                        smsc95xx_rx_csum_offload(skb);
                                skb_trim(skb, skb->len - 4); /* remove fcs */
 -                              skb->truesize = size + sizeof(struct sk_buff);
 +                              if (truesize_mode)
 +                                      skb->truesize = size + sizeof(struct sk_buff);
  
                                return 1;
                        }
                        if (dev->net->features & NETIF_F_RXCSUM)
                                smsc95xx_rx_csum_offload(ax_skb);
                        skb_trim(ax_skb, ax_skb->len - 4); /* remove fcs */
 -                      ax_skb->truesize = size + sizeof(struct sk_buff);
 +                      if (truesize_mode)
 +                              ax_skb->truesize = size + sizeof(struct sk_buff);
  
                        usbnet_skb_return(dev, ax_skb);
                }
diff --combined kernel/cgroup/cgroup.c
@@@ -1810,6 -1810,7 +1810,7 @@@ int rebind_subsystems(struct cgroup_roo
  
                if (ss->css_rstat_flush) {
                        list_del_rcu(&css->rstat_css_node);
+                       synchronize_rcu();
                        list_add_rcu(&css->rstat_css_node,
                                     &dcgrp->rstat_css_list);
                }
@@@ -5833,9 -5834,6 +5834,9 @@@ int __init cgroup_init_early(void
        return 0;
  }
  
 +static u16 cgroup_enable_mask __initdata;
 +static int __init cgroup_disable(char *str);
 +
  /**
   * cgroup_init - cgroup initialization
   *
@@@ -5874,12 -5872,6 +5875,12 @@@ int __init cgroup_init(void
  
        mutex_unlock(&cgroup_mutex);
  
 +      /*
 +       * Apply an implicit disable, knowing that an explicit enable will
 +       * prevent if from doing anything.
 +       */
 +      cgroup_disable("memory");
 +
        for_each_subsys(ss, ssid) {
                if (ss->early_init) {
                        struct cgroup_subsys_state *css =
@@@ -6464,10 -6456,6 +6465,10 @@@ static int __init cgroup_disable(char *
                            strcmp(token, ss->legacy_name))
                                continue;
  
 +                      /* An explicit cgroup_enable overrides a disable */
 +                      if (cgroup_enable_mask & (1 << i))
 +                              continue;
 +
                        static_branch_disable(cgroup_subsys_enabled_key[i]);
                        pr_info("Disabling %s control group subsystem\n",
                                ss->name);
  }
  __setup("cgroup_disable=", cgroup_disable);
  
 +static int __init cgroup_enable(char *str)
 +{
 +      struct cgroup_subsys *ss;
 +      char *token;
 +      int i;
 +
 +      while ((token = strsep(&str, ",")) != NULL) {
 +              if (!*token)
 +                      continue;
 +
 +              for_each_subsys(ss, i) {
 +                      if (strcmp(token, ss->name) &&
 +                          strcmp(token, ss->legacy_name))
 +                              continue;
 +
 +                      cgroup_enable_mask |= 1 << i;
 +                      static_branch_enable(cgroup_subsys_enabled_key[i]);
 +                      pr_info("Enabling %s control group subsystem\n",
 +                              ss->name);
 +              }
 +      }
 +      return 1;
 +}
 +__setup("cgroup_enable=", cgroup_enable);
 +
  void __init __weak enable_debug_cgroup(void) { }
  
  static int __init enable_cgroup_debug(char *str)