diff options
-rw-r--r-- | 0000_README | 4 | ||||
-rw-r--r-- | 1174_linux-5.4.175.patch | 891 |
2 files changed, 895 insertions, 0 deletions
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(>->irq_lock); + ++ mutex_init(>->tlb_invalidate_lock); ++ + INIT_LIST_HEAD(>->closed_vma); + spin_lock_init(>->closed_lock); + +@@ -266,3 +268,100 @@ void intel_gt_driver_late_release(struct intel_gt *gt) + intel_uc_driver_late_release(>->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(>->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(>->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); + } + |