commit:     5646f140920c548b890e8513ed749a05c8ab56ca
Author:     Mike Pagano <mpagano <AT> gentoo <DOT> org>
AuthorDate: Sat Jan 29 17:44:02 2022 +0000
Commit:     Mike Pagano <mpagano <AT> gentoo <DOT> org>
CommitDate: Sat Jan 29 17:44:02 2022 +0000
URL:        https://gitweb.gentoo.org/proj/linux-patches.git/commit/?id=5646f140

Linux patch 5.4.175

Signed-off-by: Mike Pagano <mpagano <AT> gentoo.org>

 0000_README              |   4 +
 1174_linux-5.4.175.patch | 891 +++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 895 insertions(+)

diff --git a/0000_README b/0000_README
index 865a37b6..2c90c35b 100644
--- a/0000_README
+++ b/0000_README
@@ -739,6 +739,10 @@ Patch:  1173_linux-5.4.174.patch
 From:   http://www.kernel.org
 Desc:   Linux 5.4.174
 
+Patch:  1174_linux-5.4.175.patch
+From:   http://www.kernel.org
+Desc:   Linux 5.4.175
+
 Patch:  1500_XATTR_USER_PREFIX.patch
 From:   https://bugs.gentoo.org/show_bug.cgi?id=470644
 Desc:   Support for namespace user.pax.* on tmpfs.

diff --git a/1174_linux-5.4.175.patch b/1174_linux-5.4.175.patch
new file mode 100644
index 00000000..acd7452d
--- /dev/null
+++ b/1174_linux-5.4.175.patch
@@ -0,0 +1,891 @@
+diff --git a/Makefile b/Makefile
+index 3075f06f77131..2f6c51097d003 100644
+--- a/Makefile
++++ b/Makefile
+@@ -1,7 +1,7 @@
+ # SPDX-License-Identifier: GPL-2.0
+ VERSION = 5
+ PATCHLEVEL = 4
+-SUBLEVEL = 174
++SUBLEVEL = 175
+ EXTRAVERSION =
+ NAME = Kleptomaniac Octopus
+ 
+diff --git a/arch/arm/boot/dts/bcm283x.dtsi b/arch/arm/boot/dts/bcm283x.dtsi
+index 50c64146d4926..af81f386793ca 100644
+--- a/arch/arm/boot/dts/bcm283x.dtsi
++++ b/arch/arm/boot/dts/bcm283x.dtsi
+@@ -183,6 +183,7 @@
+ 
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
++                      gpio-ranges = <&gpio 0 0 54>;
+ 
+                       /* Defines pin muxing groups according to
+                        * BCM2835-ARM-Peripherals.pdf page 102.
+diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object_types.h 
b/drivers/gpu/drm/i915/gem/i915_gem_object_types.h
+index 08b35587bc6dc..352c102f3459c 100644
+--- a/drivers/gpu/drm/i915/gem/i915_gem_object_types.h
++++ b/drivers/gpu/drm/i915/gem/i915_gem_object_types.h
+@@ -118,6 +118,9 @@ struct drm_i915_gem_object {
+ 
+       I915_SELFTEST_DECLARE(struct list_head st_link);
+ 
++      unsigned long flags;
++#define I915_BO_WAS_BOUND_BIT    0
++
+       /*
+        * Is the object to be mapped as read-only to the GPU
+        * Only honoured if hardware has relevant pte bit
+diff --git a/drivers/gpu/drm/i915/gem/i915_gem_pages.c 
b/drivers/gpu/drm/i915/gem/i915_gem_pages.c
+index 18f0ce0135c17..aa63fa0ab575e 100644
+--- a/drivers/gpu/drm/i915/gem/i915_gem_pages.c
++++ b/drivers/gpu/drm/i915/gem/i915_gem_pages.c
+@@ -8,6 +8,8 @@
+ #include "i915_gem_object.h"
+ #include "i915_scatterlist.h"
+ 
++#include "gt/intel_gt.h"
++
+ void __i915_gem_object_set_pages(struct drm_i915_gem_object *obj,
+                                struct sg_table *pages,
+                                unsigned int sg_page_sizes)
+@@ -176,6 +178,14 @@ __i915_gem_object_unset_pages(struct drm_i915_gem_object 
*obj)
+       __i915_gem_object_reset_page_iter(obj);
+       obj->mm.page_sizes.phys = obj->mm.page_sizes.sg = 0;
+ 
++      if (test_and_clear_bit(I915_BO_WAS_BOUND_BIT, &obj->flags)) {
++              struct drm_i915_private *i915 = to_i915(obj->base.dev);
++              intel_wakeref_t wakeref;
++
++              with_intel_runtime_pm_if_in_use(&i915->runtime_pm, wakeref)
++                      intel_gt_invalidate_tlbs(&i915->gt);
++      }
++
+       return pages;
+ }
+ 
+diff --git a/drivers/gpu/drm/i915/gt/intel_gt.c 
b/drivers/gpu/drm/i915/gt/intel_gt.c
+index d48ec9a76ed16..c8c070375d298 100644
+--- a/drivers/gpu/drm/i915/gt/intel_gt.c
++++ b/drivers/gpu/drm/i915/gt/intel_gt.c
+@@ -15,6 +15,8 @@ void intel_gt_init_early(struct intel_gt *gt, struct 
drm_i915_private *i915)
+ 
+       spin_lock_init(&gt->irq_lock);
+ 
++      mutex_init(&gt->tlb_invalidate_lock);
++
+       INIT_LIST_HEAD(&gt->closed_vma);
+       spin_lock_init(&gt->closed_lock);
+ 
+@@ -266,3 +268,100 @@ void intel_gt_driver_late_release(struct intel_gt *gt)
+       intel_uc_driver_late_release(&gt->uc);
+       intel_gt_fini_reset(gt);
+ }
++
++struct reg_and_bit {
++      i915_reg_t reg;
++      u32 bit;
++};
++
++static struct reg_and_bit
++get_reg_and_bit(const struct intel_engine_cs *engine, const bool gen8,
++              const i915_reg_t *regs, const unsigned int num)
++{
++      const unsigned int class = engine->class;
++      struct reg_and_bit rb = { };
++
++      if (WARN_ON_ONCE(class >= num || !regs[class].reg))
++              return rb;
++
++      rb.reg = regs[class];
++      if (gen8 && class == VIDEO_DECODE_CLASS)
++              rb.reg.reg += 4 * engine->instance; /* GEN8_M2TCR */
++      else
++              rb.bit = engine->instance;
++
++      rb.bit = BIT(rb.bit);
++
++      return rb;
++}
++
++void intel_gt_invalidate_tlbs(struct intel_gt *gt)
++{
++      static const i915_reg_t gen8_regs[] = {
++              [RENDER_CLASS]                  = GEN8_RTCR,
++              [VIDEO_DECODE_CLASS]            = GEN8_M1TCR, /* , GEN8_M2TCR */
++              [VIDEO_ENHANCEMENT_CLASS]       = GEN8_VTCR,
++              [COPY_ENGINE_CLASS]             = GEN8_BTCR,
++      };
++      static const i915_reg_t gen12_regs[] = {
++              [RENDER_CLASS]                  = GEN12_GFX_TLB_INV_CR,
++              [VIDEO_DECODE_CLASS]            = GEN12_VD_TLB_INV_CR,
++              [VIDEO_ENHANCEMENT_CLASS]       = GEN12_VE_TLB_INV_CR,
++              [COPY_ENGINE_CLASS]             = GEN12_BLT_TLB_INV_CR,
++      };
++      struct drm_i915_private *i915 = gt->i915;
++      struct intel_uncore *uncore = gt->uncore;
++      struct intel_engine_cs *engine;
++      enum intel_engine_id id;
++      const i915_reg_t *regs;
++      unsigned int num = 0;
++
++      if (I915_SELFTEST_ONLY(gt->awake == -ENODEV))
++              return;
++
++      if (INTEL_GEN(i915) == 12) {
++              regs = gen12_regs;
++              num = ARRAY_SIZE(gen12_regs);
++      } else if (INTEL_GEN(i915) >= 8 && INTEL_GEN(i915) <= 11) {
++              regs = gen8_regs;
++              num = ARRAY_SIZE(gen8_regs);
++      } else if (INTEL_GEN(i915) < 8) {
++              return;
++      }
++
++      if (WARN_ONCE(!num, "Platform does not implement TLB invalidation!"))
++              return;
++
++      GEM_TRACE("\n");
++
++      assert_rpm_wakelock_held(&i915->runtime_pm);
++
++      mutex_lock(&gt->tlb_invalidate_lock);
++      intel_uncore_forcewake_get(uncore, FORCEWAKE_ALL);
++
++      for_each_engine(engine, gt, id) {
++              /*
++               * HW architecture suggest typical invalidation time at 40us,
++               * with pessimistic cases up to 100us and a recommendation to
++               * cap at 1ms. We go a bit higher just in case.
++               */
++              const unsigned int timeout_us = 100;
++              const unsigned int timeout_ms = 4;
++              struct reg_and_bit rb;
++
++              rb = get_reg_and_bit(engine, regs == gen8_regs, regs, num);
++              if (!i915_mmio_reg_offset(rb.reg))
++                      continue;
++
++              intel_uncore_write_fw(uncore, rb.reg, rb.bit);
++              if (__intel_wait_for_register_fw(uncore,
++                                               rb.reg, rb.bit, 0,
++                                               timeout_us, timeout_ms,
++                                               NULL))
++                      DRM_ERROR_RATELIMITED("%s TLB invalidation did not 
complete in %ums!\n",
++                                            engine->name, timeout_ms);
++      }
++
++      intel_uncore_forcewake_put(uncore, FORCEWAKE_ALL);
++      mutex_unlock(&gt->tlb_invalidate_lock);
++}
+diff --git a/drivers/gpu/drm/i915/gt/intel_gt.h 
b/drivers/gpu/drm/i915/gt/intel_gt.h
+index 4920cb351f109..4eab15bdcd97b 100644
+--- a/drivers/gpu/drm/i915/gt/intel_gt.h
++++ b/drivers/gpu/drm/i915/gt/intel_gt.h
+@@ -57,4 +57,6 @@ static inline bool intel_gt_is_wedged(struct intel_gt *gt)
+ 
+ void intel_gt_queue_hangcheck(struct intel_gt *gt);
+ 
++void intel_gt_invalidate_tlbs(struct intel_gt *gt);
++
+ #endif /* __INTEL_GT_H__ */
+diff --git a/drivers/gpu/drm/i915/gt/intel_gt_types.h 
b/drivers/gpu/drm/i915/gt/intel_gt_types.h
+index dc295c196d11c..82a78719b32d5 100644
+--- a/drivers/gpu/drm/i915/gt/intel_gt_types.h
++++ b/drivers/gpu/drm/i915/gt/intel_gt_types.h
+@@ -40,6 +40,8 @@ struct intel_gt {
+ 
+       struct intel_uc uc;
+ 
++      struct mutex tlb_invalidate_lock;
++
+       struct intel_gt_timelines {
+               spinlock_t lock; /* protects active_list */
+               struct list_head active_list;
+diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
+index 7b6e68f082f8c..1386d0f5eac63 100644
+--- a/drivers/gpu/drm/i915/i915_reg.h
++++ b/drivers/gpu/drm/i915/i915_reg.h
+@@ -2519,6 +2519,12 @@ static inline bool i915_mmio_reg_valid(i915_reg_t reg)
+ #define   GAMT_CHKN_DISABLE_DYNAMIC_CREDIT_SHARING    (1 << 28)
+ #define   GAMT_CHKN_DISABLE_I2M_CYCLE_ON_WR_PORT      (1 << 24)
+ 
++#define GEN8_RTCR     _MMIO(0x4260)
++#define GEN8_M1TCR    _MMIO(0x4264)
++#define GEN8_M2TCR    _MMIO(0x4268)
++#define GEN8_BTCR     _MMIO(0x426c)
++#define GEN8_VTCR     _MMIO(0x4270)
++
+ #if 0
+ #define PRB0_TAIL     _MMIO(0x2030)
+ #define PRB0_HEAD     _MMIO(0x2034)
+@@ -2602,6 +2608,11 @@ static inline bool i915_mmio_reg_valid(i915_reg_t reg)
+ #define   FAULT_VA_HIGH_BITS          (0xf << 0)
+ #define   FAULT_GTT_SEL                       (1 << 4)
+ 
++#define GEN12_GFX_TLB_INV_CR  _MMIO(0xced8)
++#define GEN12_VD_TLB_INV_CR   _MMIO(0xcedc)
++#define GEN12_VE_TLB_INV_CR   _MMIO(0xcee0)
++#define GEN12_BLT_TLB_INV_CR  _MMIO(0xcee4)
++
+ #define FPGA_DBG              _MMIO(0x42300)
+ #define   FPGA_DBG_RM_NOCLAIM (1 << 31)
+ 
+diff --git a/drivers/gpu/drm/i915/i915_vma.c b/drivers/gpu/drm/i915/i915_vma.c
+index e0e677b2a3a94..c24f49ee10d73 100644
+--- a/drivers/gpu/drm/i915/i915_vma.c
++++ b/drivers/gpu/drm/i915/i915_vma.c
+@@ -341,6 +341,10 @@ int i915_vma_bind(struct i915_vma *vma, enum 
i915_cache_level cache_level,
+               return ret;
+ 
+       vma->flags |= bind_flags;
++
++      if (vma->obj)
++              set_bit(I915_BO_WAS_BOUND_BIT, &vma->obj->flags);
++
+       return 0;
+ }
+ 
+diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h 
b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
+index 5eb73ded8e07a..765f7a62870db 100644
+--- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
++++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
+@@ -1002,15 +1002,14 @@ extern int vmw_execbuf_fence_commands(struct drm_file 
*file_priv,
+                                     struct vmw_private *dev_priv,
+                                     struct vmw_fence_obj **p_fence,
+                                     uint32_t *p_handle);
+-extern void vmw_execbuf_copy_fence_user(struct vmw_private *dev_priv,
++extern int vmw_execbuf_copy_fence_user(struct vmw_private *dev_priv,
+                                       struct vmw_fpriv *vmw_fp,
+                                       int ret,
+                                       struct drm_vmw_fence_rep __user
+                                       *user_fence_rep,
+                                       struct vmw_fence_obj *fence,
+                                       uint32_t fence_handle,
+-                                      int32_t out_fence_fd,
+-                                      struct sync_file *sync_file);
++                                      int32_t out_fence_fd);
+ bool vmw_cmd_describe(const void *buf, u32 *size, char const **cmd);
+ 
+ /**
+diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c 
b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
+index ff86d49dc5e8a..e3d20048075bf 100644
+--- a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
++++ b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
+@@ -3413,17 +3413,17 @@ int vmw_execbuf_fence_commands(struct drm_file 
*file_priv,
+  * Also if copying fails, user-space will be unable to signal the fence object
+  * so we wait for it immediately, and then unreference the user-space 
reference.
+  */
+-void
++int
+ vmw_execbuf_copy_fence_user(struct vmw_private *dev_priv,
+                           struct vmw_fpriv *vmw_fp, int ret,
+                           struct drm_vmw_fence_rep __user *user_fence_rep,
+                           struct vmw_fence_obj *fence, uint32_t fence_handle,
+-                          int32_t out_fence_fd, struct sync_file *sync_file)
++                          int32_t out_fence_fd)
+ {
+       struct drm_vmw_fence_rep fence_rep;
+ 
+       if (user_fence_rep == NULL)
+-              return;
++              return 0;
+ 
+       memset(&fence_rep, 0, sizeof(fence_rep));
+ 
+@@ -3451,20 +3451,14 @@ vmw_execbuf_copy_fence_user(struct vmw_private 
*dev_priv,
+        * handle.
+        */
+       if (unlikely(ret != 0) && (fence_rep.error == 0)) {
+-              if (sync_file)
+-                      fput(sync_file->file);
+-
+-              if (fence_rep.fd != -1) {
+-                      put_unused_fd(fence_rep.fd);
+-                      fence_rep.fd = -1;
+-              }
+-
+               ttm_ref_object_base_unref(vmw_fp->tfile, fence_handle,
+                                         TTM_REF_USAGE);
+               VMW_DEBUG_USER("Fence copy error. Syncing.\n");
+               (void) vmw_fence_obj_wait(fence, false, false,
+                                         VMW_FENCE_WAIT_TIMEOUT);
+       }
++
++      return ret ? -EFAULT : 0;
+ }
+ 
+ /**
+@@ -3806,16 +3800,23 @@ int vmw_execbuf_process(struct drm_file *file_priv,
+ 
+                       (void) vmw_fence_obj_wait(fence, false, false,
+                                                 VMW_FENCE_WAIT_TIMEOUT);
++              }
++      }
++
++      ret = vmw_execbuf_copy_fence_user(dev_priv, vmw_fpriv(file_priv), ret,
++                                  user_fence_rep, fence, handle, 
out_fence_fd);
++
++      if (sync_file) {
++              if (ret) {
++                      /* usercopy of fence failed, put the file object */
++                      fput(sync_file->file);
++                      put_unused_fd(out_fence_fd);
+               } else {
+                       /* Link the fence with the FD created earlier */
+                       fd_install(out_fence_fd, sync_file->file);
+               }
+       }
+ 
+-      vmw_execbuf_copy_fence_user(dev_priv, vmw_fpriv(file_priv), ret,
+-                                  user_fence_rep, fence, handle, out_fence_fd,
+-                                  sync_file);
+-
+       /* Don't unreference when handing fence out */
+       if (unlikely(out_fence != NULL)) {
+               *out_fence = fence;
+@@ -3833,7 +3834,7 @@ int vmw_execbuf_process(struct drm_file *file_priv,
+        */
+       vmw_validation_unref_lists(&val_ctx);
+ 
+-      return 0;
++      return ret;
+ 
+ out_unlock_binding:
+       mutex_unlock(&dev_priv->binding_mutex);
+diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c 
b/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c
+index 178a6cd1a06fe..874093a0b04f0 100644
+--- a/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c
++++ b/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c
+@@ -1171,7 +1171,7 @@ int vmw_fence_event_ioctl(struct drm_device *dev, void 
*data,
+       }
+ 
+       vmw_execbuf_copy_fence_user(dev_priv, vmw_fp, 0, user_fence_rep, fence,
+-                                  handle, -1, NULL);
++                                  handle, -1);
+       vmw_fence_obj_unreference(&fence);
+       return 0;
+ out_no_create:
+diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c 
b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
+index 33b1519887474..0b800c3540492 100644
+--- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
++++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
+@@ -2570,7 +2570,7 @@ void vmw_kms_helper_validation_finish(struct vmw_private 
*dev_priv,
+       if (file_priv)
+               vmw_execbuf_copy_fence_user(dev_priv, vmw_fpriv(file_priv),
+                                           ret, user_fence_rep, fence,
+-                                          handle, -1, NULL);
++                                          handle, -1);
+       if (out_fence)
+               *out_fence = fence;
+       else
+diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c 
b/drivers/mmc/host/sdhci-esdhc-imx.c
+index 2c01e2ebef7aa..d97c19ef75830 100644
+--- a/drivers/mmc/host/sdhci-esdhc-imx.c
++++ b/drivers/mmc/host/sdhci-esdhc-imx.c
+@@ -218,8 +218,7 @@ static struct esdhc_soc_data usdhc_imx7ulp_data = {
+ static struct esdhc_soc_data usdhc_imx8qxp_data = {
+       .flags = ESDHC_FLAG_USDHC | ESDHC_FLAG_STD_TUNING
+                       | ESDHC_FLAG_HAVE_CAP1 | ESDHC_FLAG_HS200
+-                      | ESDHC_FLAG_HS400 | ESDHC_FLAG_HS400_ES
+-                      | ESDHC_FLAG_CQHCI,
++                      | ESDHC_FLAG_HS400 | ESDHC_FLAG_HS400_ES,
+ };
+ 
+ struct pltfm_imx_data {
+diff --git a/drivers/pinctrl/bcm/pinctrl-bcm2835.c 
b/drivers/pinctrl/bcm/pinctrl-bcm2835.c
+index 0de1a3a96984c..fa742535f6791 100644
+--- a/drivers/pinctrl/bcm/pinctrl-bcm2835.c
++++ b/drivers/pinctrl/bcm/pinctrl-bcm2835.c
+@@ -19,6 +19,7 @@
+ #include <linux/irq.h>
+ #include <linux/irqdesc.h>
+ #include <linux/init.h>
++#include <linux/interrupt.h>
+ #include <linux/of_address.h>
+ #include <linux/of.h>
+ #include <linux/of_irq.h>
+@@ -37,12 +38,10 @@
+ 
+ #define MODULE_NAME "pinctrl-bcm2835"
+ #define BCM2835_NUM_GPIOS 54
++#define BCM2711_NUM_GPIOS 58
+ #define BCM2835_NUM_BANKS 2
+ #define BCM2835_NUM_IRQS  3
+ 
+-#define BCM2835_PIN_BITMAP_SZ \
+-      DIV_ROUND_UP(BCM2835_NUM_GPIOS, sizeof(unsigned long) * 8)
+-
+ /* GPIO register offsets */
+ #define GPFSEL0               0x0     /* Function Select */
+ #define GPSET0                0x1c    /* Pin Output Set */
+@@ -78,13 +77,15 @@
+ struct bcm2835_pinctrl {
+       struct device *dev;
+       void __iomem *base;
++      int *wake_irq;
+ 
+       /* note: locking assumes each bank will have its own unsigned long */
+       unsigned long enabled_irq_map[BCM2835_NUM_BANKS];
+-      unsigned int irq_type[BCM2835_NUM_GPIOS];
++      unsigned int irq_type[BCM2711_NUM_GPIOS];
+ 
+       struct pinctrl_dev *pctl_dev;
+       struct gpio_chip gpio_chip;
++      struct pinctrl_desc pctl_desc;
+       struct pinctrl_gpio_range gpio_range;
+ 
+       raw_spinlock_t irq_lock[BCM2835_NUM_BANKS];
+@@ -147,6 +148,10 @@ static struct pinctrl_pin_desc bcm2835_gpio_pins[] = {
+       BCM2835_GPIO_PIN(51),
+       BCM2835_GPIO_PIN(52),
+       BCM2835_GPIO_PIN(53),
++      BCM2835_GPIO_PIN(54),
++      BCM2835_GPIO_PIN(55),
++      BCM2835_GPIO_PIN(56),
++      BCM2835_GPIO_PIN(57),
+ };
+ 
+ /* one pin per group */
+@@ -205,6 +210,10 @@ static const char * const bcm2835_gpio_groups[] = {
+       "gpio51",
+       "gpio52",
+       "gpio53",
++      "gpio54",
++      "gpio55",
++      "gpio56",
++      "gpio57",
+ };
+ 
+ enum bcm2835_fsel {
+@@ -355,6 +364,22 @@ static const struct gpio_chip bcm2835_gpio_chip = {
+       .can_sleep = false,
+ };
+ 
++static const struct gpio_chip bcm2711_gpio_chip = {
++      .label = "pinctrl-bcm2711",
++      .owner = THIS_MODULE,
++      .request = gpiochip_generic_request,
++      .free = gpiochip_generic_free,
++      .direction_input = bcm2835_gpio_direction_input,
++      .direction_output = bcm2835_gpio_direction_output,
++      .get_direction = bcm2835_gpio_get_direction,
++      .get = bcm2835_gpio_get,
++      .set = bcm2835_gpio_set,
++      .set_config = gpiochip_generic_config,
++      .base = -1,
++      .ngpio = BCM2711_NUM_GPIOS,
++      .can_sleep = false,
++};
++
+ static void bcm2835_gpio_irq_handle_bank(struct bcm2835_pinctrl *pc,
+                                        unsigned int bank, u32 mask)
+ {
+@@ -401,7 +426,7 @@ static void bcm2835_gpio_irq_handler(struct irq_desc *desc)
+               bcm2835_gpio_irq_handle_bank(pc, 0, 0xf0000000);
+               bcm2835_gpio_irq_handle_bank(pc, 1, 0x00003fff);
+               break;
+-      case 2: /* IRQ2 covers GPIOs 46-53 */
++      case 2: /* IRQ2 covers GPIOs 46-57 */
+               bcm2835_gpio_irq_handle_bank(pc, 1, 0x003fc000);
+               break;
+       }
+@@ -409,6 +434,11 @@ static void bcm2835_gpio_irq_handler(struct irq_desc 
*desc)
+       chained_irq_exit(host_chip, desc);
+ }
+ 
++static irqreturn_t bcm2835_gpio_wake_irq_handler(int irq, void *dev_id)
++{
++      return IRQ_HANDLED;
++}
++
+ static inline void __bcm2835_gpio_irq_config(struct bcm2835_pinctrl *pc,
+       unsigned reg, unsigned offset, bool enable)
+ {
+@@ -608,6 +638,34 @@ static void bcm2835_gpio_irq_ack(struct irq_data *data)
+       bcm2835_gpio_set_bit(pc, GPEDS0, gpio);
+ }
+ 
++static int bcm2835_gpio_irq_set_wake(struct irq_data *data, unsigned int on)
++{
++      struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
++      struct bcm2835_pinctrl *pc = gpiochip_get_data(chip);
++      unsigned gpio = irqd_to_hwirq(data);
++      unsigned int irqgroup;
++      int ret = -EINVAL;
++
++      if (!pc->wake_irq)
++              return ret;
++
++      if (gpio <= 27)
++              irqgroup = 0;
++      else if (gpio >= 28 && gpio <= 45)
++              irqgroup = 1;
++      else if (gpio >= 46 && gpio <= 57)
++              irqgroup = 2;
++      else
++              return ret;
++
++      if (on)
++              ret = enable_irq_wake(pc->wake_irq[irqgroup]);
++      else
++              ret = disable_irq_wake(pc->wake_irq[irqgroup]);
++
++      return ret;
++}
++
+ static struct irq_chip bcm2835_gpio_irq_chip = {
+       .name = MODULE_NAME,
+       .irq_enable = bcm2835_gpio_irq_enable,
+@@ -616,11 +674,13 @@ static struct irq_chip bcm2835_gpio_irq_chip = {
+       .irq_ack = bcm2835_gpio_irq_ack,
+       .irq_mask = bcm2835_gpio_irq_disable,
+       .irq_unmask = bcm2835_gpio_irq_enable,
++      .irq_set_wake = bcm2835_gpio_irq_set_wake,
++      .flags = IRQCHIP_MASK_ON_SUSPEND,
+ };
+ 
+ static int bcm2835_pctl_get_groups_count(struct pinctrl_dev *pctldev)
+ {
+-      return ARRAY_SIZE(bcm2835_gpio_groups);
++      return BCM2835_NUM_GPIOS;
+ }
+ 
+ static const char *bcm2835_pctl_get_group_name(struct pinctrl_dev *pctldev,
+@@ -778,7 +838,7 @@ static int bcm2835_pctl_dt_node_to_map(struct pinctrl_dev 
*pctldev,
+               err = of_property_read_u32_index(np, "brcm,pins", i, &pin);
+               if (err)
+                       goto out;
+-              if (pin >= ARRAY_SIZE(bcm2835_gpio_pins)) {
++              if (pin >= pc->pctl_desc.npins) {
+                       dev_err(pc->dev, "%pOF: invalid brcm,pins value %d\n",
+                               np, pin);
+                       err = -EINVAL;
+@@ -854,7 +914,7 @@ static int bcm2835_pmx_get_function_groups(struct 
pinctrl_dev *pctldev,
+ {
+       /* every pin can do every function */
+       *groups = bcm2835_gpio_groups;
+-      *num_groups = ARRAY_SIZE(bcm2835_gpio_groups);
++      *num_groups = BCM2835_NUM_GPIOS;
+ 
+       return 0;
+ }
+@@ -1054,29 +1114,66 @@ static const struct pinconf_ops bcm2711_pinconf_ops = {
+       .pin_config_set = bcm2711_pinconf_set,
+ };
+ 
+-static struct pinctrl_desc bcm2835_pinctrl_desc = {
++static const struct pinctrl_desc bcm2835_pinctrl_desc = {
+       .name = MODULE_NAME,
+       .pins = bcm2835_gpio_pins,
+-      .npins = ARRAY_SIZE(bcm2835_gpio_pins),
++      .npins = BCM2835_NUM_GPIOS,
+       .pctlops = &bcm2835_pctl_ops,
+       .pmxops = &bcm2835_pmx_ops,
+       .confops = &bcm2835_pinconf_ops,
+       .owner = THIS_MODULE,
+ };
+ 
+-static struct pinctrl_gpio_range bcm2835_pinctrl_gpio_range = {
++static const struct pinctrl_desc bcm2711_pinctrl_desc = {
++      .name = "pinctrl-bcm2711",
++      .pins = bcm2835_gpio_pins,
++      .npins = BCM2711_NUM_GPIOS,
++      .pctlops = &bcm2835_pctl_ops,
++      .pmxops = &bcm2835_pmx_ops,
++      .confops = &bcm2711_pinconf_ops,
++      .owner = THIS_MODULE,
++};
++
++static const struct pinctrl_gpio_range bcm2835_pinctrl_gpio_range = {
+       .name = MODULE_NAME,
+       .npins = BCM2835_NUM_GPIOS,
+ };
+ 
++static const struct pinctrl_gpio_range bcm2711_pinctrl_gpio_range = {
++      .name = "pinctrl-bcm2711",
++      .npins = BCM2711_NUM_GPIOS,
++};
++
++struct bcm_plat_data {
++      const struct gpio_chip *gpio_chip;
++      const struct pinctrl_desc *pctl_desc;
++      const struct pinctrl_gpio_range *gpio_range;
++};
++
++static const struct bcm_plat_data bcm2835_plat_data = {
++      .gpio_chip = &bcm2835_gpio_chip,
++      .pctl_desc = &bcm2835_pinctrl_desc,
++      .gpio_range = &bcm2835_pinctrl_gpio_range,
++};
++
++static const struct bcm_plat_data bcm2711_plat_data = {
++      .gpio_chip = &bcm2711_gpio_chip,
++      .pctl_desc = &bcm2711_pinctrl_desc,
++      .gpio_range = &bcm2711_pinctrl_gpio_range,
++};
++
+ static const struct of_device_id bcm2835_pinctrl_match[] = {
+       {
+               .compatible = "brcm,bcm2835-gpio",
+-              .data = &bcm2835_pinconf_ops,
++              .data = &bcm2835_plat_data,
+       },
+       {
+               .compatible = "brcm,bcm2711-gpio",
+-              .data = &bcm2711_pinconf_ops,
++              .data = &bcm2711_plat_data,
++      },
++      {
++              .compatible = "brcm,bcm7211-gpio",
++              .data = &bcm2711_plat_data,
+       },
+       {}
+ };
+@@ -1085,14 +1182,16 @@ static int bcm2835_pinctrl_probe(struct 
platform_device *pdev)
+ {
+       struct device *dev = &pdev->dev;
+       struct device_node *np = dev->of_node;
++      const struct bcm_plat_data *pdata;
+       struct bcm2835_pinctrl *pc;
+       struct gpio_irq_chip *girq;
+       struct resource iomem;
+       int err, i;
+       const struct of_device_id *match;
++      int is_7211 = 0;
+ 
+-      BUILD_BUG_ON(ARRAY_SIZE(bcm2835_gpio_pins) != BCM2835_NUM_GPIOS);
+-      BUILD_BUG_ON(ARRAY_SIZE(bcm2835_gpio_groups) != BCM2835_NUM_GPIOS);
++      BUILD_BUG_ON(ARRAY_SIZE(bcm2835_gpio_pins) != BCM2711_NUM_GPIOS);
++      BUILD_BUG_ON(ARRAY_SIZE(bcm2835_gpio_groups) != BCM2711_NUM_GPIOS);
+ 
+       pc = devm_kzalloc(dev, sizeof(*pc), GFP_KERNEL);
+       if (!pc)
+@@ -1111,7 +1210,14 @@ static int bcm2835_pinctrl_probe(struct platform_device 
*pdev)
+       if (IS_ERR(pc->base))
+               return PTR_ERR(pc->base);
+ 
+-      pc->gpio_chip = bcm2835_gpio_chip;
++      match = of_match_node(bcm2835_pinctrl_match, pdev->dev.of_node);
++      if (!match)
++              return -EINVAL;
++
++      pdata = match->data;
++      is_7211 = of_device_is_compatible(np, "brcm,bcm7211-gpio");
++
++      pc->gpio_chip = *pdata->gpio_chip;
+       pc->gpio_chip.parent = dev;
+       pc->gpio_chip.of_node = np;
+ 
+@@ -1135,6 +1241,18 @@ static int bcm2835_pinctrl_probe(struct platform_device 
*pdev)
+               raw_spin_lock_init(&pc->irq_lock[i]);
+       }
+ 
++      pc->pctl_desc = *pdata->pctl_desc;
++      pc->pctl_dev = devm_pinctrl_register(dev, &pc->pctl_desc, pc);
++      if (IS_ERR(pc->pctl_dev)) {
++              gpiochip_remove(&pc->gpio_chip);
++              return PTR_ERR(pc->pctl_dev);
++      }
++
++      pc->gpio_range = *pdata->gpio_range;
++      pc->gpio_range.base = pc->gpio_chip.base;
++      pc->gpio_range.gc = &pc->gpio_chip;
++      pinctrl_add_gpio_range(pc->pctl_dev, &pc->gpio_range);
++
+       girq = &pc->gpio_chip.irq;
+       girq->chip = &bcm2835_gpio_irq_chip;
+       girq->parent_handler = bcm2835_gpio_irq_handler;
+@@ -1142,8 +1260,19 @@ static int bcm2835_pinctrl_probe(struct platform_device 
*pdev)
+       girq->parents = devm_kcalloc(dev, BCM2835_NUM_IRQS,
+                                    sizeof(*girq->parents),
+                                    GFP_KERNEL);
+-      if (!girq->parents)
++      if (!girq->parents) {
++              pinctrl_remove_gpio_range(pc->pctl_dev, &pc->gpio_range);
+               return -ENOMEM;
++      }
++
++      if (is_7211) {
++              pc->wake_irq = devm_kcalloc(dev, BCM2835_NUM_IRQS,
++                                          sizeof(*pc->wake_irq),
++                                          GFP_KERNEL);
++              if (!pc->wake_irq)
++                      return -ENOMEM;
++      }
++
+       /*
+        * Use the same handler for all groups: this is necessary
+        * since we use one gpiochip to cover all lines - the
+@@ -1151,34 +1280,44 @@ static int bcm2835_pinctrl_probe(struct 
platform_device *pdev)
+        * bank that was firing the IRQ and look up the per-group
+        * and bank data.
+        */
+-      for (i = 0; i < BCM2835_NUM_IRQS; i++)
++      for (i = 0; i < BCM2835_NUM_IRQS; i++) {
++              int len;
++              char *name;
++
+               girq->parents[i] = irq_of_parse_and_map(np, i);
++              if (!is_7211)
++                      continue;
++
++              /* Skip over the all banks interrupts */
++              pc->wake_irq[i] = irq_of_parse_and_map(np, i +
++                                                     BCM2835_NUM_IRQS + 1);
++
++              len = strlen(dev_name(pc->dev)) + 16;
++              name = devm_kzalloc(pc->dev, len, GFP_KERNEL);
++              if (!name)
++                      return -ENOMEM;
++
++              snprintf(name, len, "%s:bank%d", dev_name(pc->dev), i);
++
++              /* These are optional interrupts */
++              err = devm_request_irq(dev, pc->wake_irq[i],
++                                     bcm2835_gpio_wake_irq_handler,
++                                     IRQF_SHARED, name, pc);
++              if (err)
++                      dev_warn(dev, "unable to request wake IRQ %d\n",
++                               pc->wake_irq[i]);
++      }
++
+       girq->default_type = IRQ_TYPE_NONE;
+       girq->handler = handle_level_irq;
+ 
+       err = gpiochip_add_data(&pc->gpio_chip, pc);
+       if (err) {
+               dev_err(dev, "could not add GPIO chip\n");
++              pinctrl_remove_gpio_range(pc->pctl_dev, &pc->gpio_range);
+               return err;
+       }
+ 
+-      match = of_match_node(bcm2835_pinctrl_match, pdev->dev.of_node);
+-      if (match) {
+-              bcm2835_pinctrl_desc.confops =
+-                      (const struct pinconf_ops *)match->data;
+-      }
+-
+-      pc->pctl_dev = devm_pinctrl_register(dev, &bcm2835_pinctrl_desc, pc);
+-      if (IS_ERR(pc->pctl_dev)) {
+-              gpiochip_remove(&pc->gpio_chip);
+-              return PTR_ERR(pc->pctl_dev);
+-      }
+-
+-      pc->gpio_range = bcm2835_pinctrl_gpio_range;
+-      pc->gpio_range.base = pc->gpio_chip.base;
+-      pc->gpio_range.gc = &pc->gpio_chip;
+-      pinctrl_add_gpio_range(pc->pctl_dev, &pc->gpio_range);
+-
+       return 0;
+ }
+ 
+diff --git a/fs/select.c b/fs/select.c
+index e51796063cb6e..7716d9d5be1e8 100644
+--- a/fs/select.c
++++ b/fs/select.c
+@@ -458,9 +458,11 @@ get_max:
+       return max;
+ }
+ 
+-#define POLLIN_SET (EPOLLRDNORM | EPOLLRDBAND | EPOLLIN | EPOLLHUP | EPOLLERR)
+-#define POLLOUT_SET (EPOLLWRBAND | EPOLLWRNORM | EPOLLOUT | EPOLLERR)
+-#define POLLEX_SET (EPOLLPRI)
++#define POLLIN_SET (EPOLLRDNORM | EPOLLRDBAND | EPOLLIN | EPOLLHUP | EPOLLERR 
|\
++                      EPOLLNVAL)
++#define POLLOUT_SET (EPOLLWRBAND | EPOLLWRNORM | EPOLLOUT | EPOLLERR |\
++                       EPOLLNVAL)
++#define POLLEX_SET (EPOLLPRI | EPOLLNVAL)
+ 
+ static inline void wait_key_set(poll_table *wait, unsigned long in,
+                               unsigned long out, unsigned long bit,
+@@ -527,6 +529,7 @@ static int do_select(int n, fd_set_bits *fds, struct 
timespec64 *end_time)
+                                       break;
+                               if (!(bit & all_bits))
+                                       continue;
++                              mask = EPOLLNVAL;
+                               f = fdget(i);
+                               if (f.file) {
+                                       wait_key_set(wait, in, out, bit,
+@@ -534,34 +537,34 @@ static int do_select(int n, fd_set_bits *fds, struct 
timespec64 *end_time)
+                                       mask = vfs_poll(f.file, wait);
+ 
+                                       fdput(f);
+-                                      if ((mask & POLLIN_SET) && (in & bit)) {
+-                                              res_in |= bit;
+-                                              retval++;
+-                                              wait->_qproc = NULL;
+-                                      }
+-                                      if ((mask & POLLOUT_SET) && (out & 
bit)) {
+-                                              res_out |= bit;
+-                                              retval++;
+-                                              wait->_qproc = NULL;
+-                                      }
+-                                      if ((mask & POLLEX_SET) && (ex & bit)) {
+-                                              res_ex |= bit;
+-                                              retval++;
+-                                              wait->_qproc = NULL;
+-                                      }
+-                                      /* got something, stop busy polling */
+-                                      if (retval) {
+-                                              can_busy_loop = false;
+-                                              busy_flag = 0;
+-
+-                                      /*
+-                                       * only remember a returned
+-                                       * POLL_BUSY_LOOP if we asked for it
+-                                       */
+-                                      } else if (busy_flag & mask)
+-                                              can_busy_loop = true;
+-
+                               }
++                              if ((mask & POLLIN_SET) && (in & bit)) {
++                                      res_in |= bit;
++                                      retval++;
++                                      wait->_qproc = NULL;
++                              }
++                              if ((mask & POLLOUT_SET) && (out & bit)) {
++                                      res_out |= bit;
++                                      retval++;
++                                      wait->_qproc = NULL;
++                              }
++                              if ((mask & POLLEX_SET) && (ex & bit)) {
++                                      res_ex |= bit;
++                                      retval++;
++                                      wait->_qproc = NULL;
++                              }
++                              /* got something, stop busy polling */
++                              if (retval) {
++                                      can_busy_loop = false;
++                                      busy_flag = 0;
++
++                              /*
++                               * only remember a returned
++                               * POLL_BUSY_LOOP if we asked for it
++                               */
++                              } else if (busy_flag & mask)
++                                      can_busy_loop = true;
++
+                       }
+                       if (res_in)
+                               *rinp = res_in;
+diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c
+index 7777c35e0a171..5797cf2909b00 100644
+--- a/kernel/rcu/tree.c
++++ b/kernel/rcu/tree.c
+@@ -1358,10 +1358,11 @@ static void __maybe_unused 
rcu_advance_cbs_nowake(struct rcu_node *rnp,
+                                                 struct rcu_data *rdp)
+ {
+       rcu_lockdep_assert_cblist_protected(rdp);
+-      if (!rcu_seq_state(rcu_seq_current(&rnp->gp_seq)) ||
+-          !raw_spin_trylock_rcu_node(rnp))
++      if (!rcu_seq_state(rcu_seq_current(&rnp->gp_seq)) || 
!raw_spin_trylock_rcu_node(rnp))
+               return;
+-      WARN_ON_ONCE(rcu_advance_cbs(rnp, rdp));
++      // The grace period cannot end while we hold the rcu_node lock.
++      if (rcu_seq_state(rcu_seq_current(&rnp->gp_seq)))
++              WARN_ON_ONCE(rcu_advance_cbs(rnp, rdp));
+       raw_spin_unlock_rcu_node(rnp);
+ }
+ 

Reply via email to