Annotation of /trunk/kernel-alx/patches-5.4/0274-5.4.175-all-fixes.patch
Parent Directory | Revision Log
Revision 3635 -
(hide annotations)
(download)
Mon Oct 24 12:34:12 2022 UTC (19 months ago) by niro
File size: 27341 byte(s)
Mon Oct 24 12:34:12 2022 UTC (19 months ago) by niro
File size: 27341 byte(s)
-sync kernel patches
1 | niro | 3635 | diff --git a/Makefile b/Makefile |
2 | index 3075f06f77131..2f6c51097d003 100644 | ||
3 | --- a/Makefile | ||
4 | +++ b/Makefile | ||
5 | @@ -1,7 +1,7 @@ | ||
6 | # SPDX-License-Identifier: GPL-2.0 | ||
7 | VERSION = 5 | ||
8 | PATCHLEVEL = 4 | ||
9 | -SUBLEVEL = 174 | ||
10 | +SUBLEVEL = 175 | ||
11 | EXTRAVERSION = | ||
12 | NAME = Kleptomaniac Octopus | ||
13 | |||
14 | diff --git a/arch/arm/boot/dts/bcm283x.dtsi b/arch/arm/boot/dts/bcm283x.dtsi | ||
15 | index 50c64146d4926..af81f386793ca 100644 | ||
16 | --- a/arch/arm/boot/dts/bcm283x.dtsi | ||
17 | +++ b/arch/arm/boot/dts/bcm283x.dtsi | ||
18 | @@ -183,6 +183,7 @@ | ||
19 | |||
20 | interrupt-controller; | ||
21 | #interrupt-cells = <2>; | ||
22 | + gpio-ranges = <&gpio 0 0 54>; | ||
23 | |||
24 | /* Defines pin muxing groups according to | ||
25 | * BCM2835-ARM-Peripherals.pdf page 102. | ||
26 | diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object_types.h b/drivers/gpu/drm/i915/gem/i915_gem_object_types.h | ||
27 | index 08b35587bc6dc..352c102f3459c 100644 | ||
28 | --- a/drivers/gpu/drm/i915/gem/i915_gem_object_types.h | ||
29 | +++ b/drivers/gpu/drm/i915/gem/i915_gem_object_types.h | ||
30 | @@ -118,6 +118,9 @@ struct drm_i915_gem_object { | ||
31 | |||
32 | I915_SELFTEST_DECLARE(struct list_head st_link); | ||
33 | |||
34 | + unsigned long flags; | ||
35 | +#define I915_BO_WAS_BOUND_BIT 0 | ||
36 | + | ||
37 | /* | ||
38 | * Is the object to be mapped as read-only to the GPU | ||
39 | * Only honoured if hardware has relevant pte bit | ||
40 | diff --git a/drivers/gpu/drm/i915/gem/i915_gem_pages.c b/drivers/gpu/drm/i915/gem/i915_gem_pages.c | ||
41 | index 18f0ce0135c17..aa63fa0ab575e 100644 | ||
42 | --- a/drivers/gpu/drm/i915/gem/i915_gem_pages.c | ||
43 | +++ b/drivers/gpu/drm/i915/gem/i915_gem_pages.c | ||
44 | @@ -8,6 +8,8 @@ | ||
45 | #include "i915_gem_object.h" | ||
46 | #include "i915_scatterlist.h" | ||
47 | |||
48 | +#include "gt/intel_gt.h" | ||
49 | + | ||
50 | void __i915_gem_object_set_pages(struct drm_i915_gem_object *obj, | ||
51 | struct sg_table *pages, | ||
52 | unsigned int sg_page_sizes) | ||
53 | @@ -176,6 +178,14 @@ __i915_gem_object_unset_pages(struct drm_i915_gem_object *obj) | ||
54 | __i915_gem_object_reset_page_iter(obj); | ||
55 | obj->mm.page_sizes.phys = obj->mm.page_sizes.sg = 0; | ||
56 | |||
57 | + if (test_and_clear_bit(I915_BO_WAS_BOUND_BIT, &obj->flags)) { | ||
58 | + struct drm_i915_private *i915 = to_i915(obj->base.dev); | ||
59 | + intel_wakeref_t wakeref; | ||
60 | + | ||
61 | + with_intel_runtime_pm_if_in_use(&i915->runtime_pm, wakeref) | ||
62 | + intel_gt_invalidate_tlbs(&i915->gt); | ||
63 | + } | ||
64 | + | ||
65 | return pages; | ||
66 | } | ||
67 | |||
68 | diff --git a/drivers/gpu/drm/i915/gt/intel_gt.c b/drivers/gpu/drm/i915/gt/intel_gt.c | ||
69 | index d48ec9a76ed16..c8c070375d298 100644 | ||
70 | --- a/drivers/gpu/drm/i915/gt/intel_gt.c | ||
71 | +++ b/drivers/gpu/drm/i915/gt/intel_gt.c | ||
72 | @@ -15,6 +15,8 @@ void intel_gt_init_early(struct intel_gt *gt, struct drm_i915_private *i915) | ||
73 | |||
74 | spin_lock_init(>->irq_lock); | ||
75 | |||
76 | + mutex_init(>->tlb_invalidate_lock); | ||
77 | + | ||
78 | INIT_LIST_HEAD(>->closed_vma); | ||
79 | spin_lock_init(>->closed_lock); | ||
80 | |||
81 | @@ -266,3 +268,100 @@ void intel_gt_driver_late_release(struct intel_gt *gt) | ||
82 | intel_uc_driver_late_release(>->uc); | ||
83 | intel_gt_fini_reset(gt); | ||
84 | } | ||
85 | + | ||
86 | +struct reg_and_bit { | ||
87 | + i915_reg_t reg; | ||
88 | + u32 bit; | ||
89 | +}; | ||
90 | + | ||
91 | +static struct reg_and_bit | ||
92 | +get_reg_and_bit(const struct intel_engine_cs *engine, const bool gen8, | ||
93 | + const i915_reg_t *regs, const unsigned int num) | ||
94 | +{ | ||
95 | + const unsigned int class = engine->class; | ||
96 | + struct reg_and_bit rb = { }; | ||
97 | + | ||
98 | + if (WARN_ON_ONCE(class >= num || !regs[class].reg)) | ||
99 | + return rb; | ||
100 | + | ||
101 | + rb.reg = regs[class]; | ||
102 | + if (gen8 && class == VIDEO_DECODE_CLASS) | ||
103 | + rb.reg.reg += 4 * engine->instance; /* GEN8_M2TCR */ | ||
104 | + else | ||
105 | + rb.bit = engine->instance; | ||
106 | + | ||
107 | + rb.bit = BIT(rb.bit); | ||
108 | + | ||
109 | + return rb; | ||
110 | +} | ||
111 | + | ||
112 | +void intel_gt_invalidate_tlbs(struct intel_gt *gt) | ||
113 | +{ | ||
114 | + static const i915_reg_t gen8_regs[] = { | ||
115 | + [RENDER_CLASS] = GEN8_RTCR, | ||
116 | + [VIDEO_DECODE_CLASS] = GEN8_M1TCR, /* , GEN8_M2TCR */ | ||
117 | + [VIDEO_ENHANCEMENT_CLASS] = GEN8_VTCR, | ||
118 | + [COPY_ENGINE_CLASS] = GEN8_BTCR, | ||
119 | + }; | ||
120 | + static const i915_reg_t gen12_regs[] = { | ||
121 | + [RENDER_CLASS] = GEN12_GFX_TLB_INV_CR, | ||
122 | + [VIDEO_DECODE_CLASS] = GEN12_VD_TLB_INV_CR, | ||
123 | + [VIDEO_ENHANCEMENT_CLASS] = GEN12_VE_TLB_INV_CR, | ||
124 | + [COPY_ENGINE_CLASS] = GEN12_BLT_TLB_INV_CR, | ||
125 | + }; | ||
126 | + struct drm_i915_private *i915 = gt->i915; | ||
127 | + struct intel_uncore *uncore = gt->uncore; | ||
128 | + struct intel_engine_cs *engine; | ||
129 | + enum intel_engine_id id; | ||
130 | + const i915_reg_t *regs; | ||
131 | + unsigned int num = 0; | ||
132 | + | ||
133 | + if (I915_SELFTEST_ONLY(gt->awake == -ENODEV)) | ||
134 | + return; | ||
135 | + | ||
136 | + if (INTEL_GEN(i915) == 12) { | ||
137 | + regs = gen12_regs; | ||
138 | + num = ARRAY_SIZE(gen12_regs); | ||
139 | + } else if (INTEL_GEN(i915) >= 8 && INTEL_GEN(i915) <= 11) { | ||
140 | + regs = gen8_regs; | ||
141 | + num = ARRAY_SIZE(gen8_regs); | ||
142 | + } else if (INTEL_GEN(i915) < 8) { | ||
143 | + return; | ||
144 | + } | ||
145 | + | ||
146 | + if (WARN_ONCE(!num, "Platform does not implement TLB invalidation!")) | ||
147 | + return; | ||
148 | + | ||
149 | + GEM_TRACE("\n"); | ||
150 | + | ||
151 | + assert_rpm_wakelock_held(&i915->runtime_pm); | ||
152 | + | ||
153 | + mutex_lock(>->tlb_invalidate_lock); | ||
154 | + intel_uncore_forcewake_get(uncore, FORCEWAKE_ALL); | ||
155 | + | ||
156 | + for_each_engine(engine, gt, id) { | ||
157 | + /* | ||
158 | + * HW architecture suggest typical invalidation time at 40us, | ||
159 | + * with pessimistic cases up to 100us and a recommendation to | ||
160 | + * cap at 1ms. We go a bit higher just in case. | ||
161 | + */ | ||
162 | + const unsigned int timeout_us = 100; | ||
163 | + const unsigned int timeout_ms = 4; | ||
164 | + struct reg_and_bit rb; | ||
165 | + | ||
166 | + rb = get_reg_and_bit(engine, regs == gen8_regs, regs, num); | ||
167 | + if (!i915_mmio_reg_offset(rb.reg)) | ||
168 | + continue; | ||
169 | + | ||
170 | + intel_uncore_write_fw(uncore, rb.reg, rb.bit); | ||
171 | + if (__intel_wait_for_register_fw(uncore, | ||
172 | + rb.reg, rb.bit, 0, | ||
173 | + timeout_us, timeout_ms, | ||
174 | + NULL)) | ||
175 | + DRM_ERROR_RATELIMITED("%s TLB invalidation did not complete in %ums!\n", | ||
176 | + engine->name, timeout_ms); | ||
177 | + } | ||
178 | + | ||
179 | + intel_uncore_forcewake_put(uncore, FORCEWAKE_ALL); | ||
180 | + mutex_unlock(>->tlb_invalidate_lock); | ||
181 | +} | ||
182 | diff --git a/drivers/gpu/drm/i915/gt/intel_gt.h b/drivers/gpu/drm/i915/gt/intel_gt.h | ||
183 | index 4920cb351f109..4eab15bdcd97b 100644 | ||
184 | --- a/drivers/gpu/drm/i915/gt/intel_gt.h | ||
185 | +++ b/drivers/gpu/drm/i915/gt/intel_gt.h | ||
186 | @@ -57,4 +57,6 @@ static inline bool intel_gt_is_wedged(struct intel_gt *gt) | ||
187 | |||
188 | void intel_gt_queue_hangcheck(struct intel_gt *gt); | ||
189 | |||
190 | +void intel_gt_invalidate_tlbs(struct intel_gt *gt); | ||
191 | + | ||
192 | #endif /* __INTEL_GT_H__ */ | ||
193 | diff --git a/drivers/gpu/drm/i915/gt/intel_gt_types.h b/drivers/gpu/drm/i915/gt/intel_gt_types.h | ||
194 | index dc295c196d11c..82a78719b32d5 100644 | ||
195 | --- a/drivers/gpu/drm/i915/gt/intel_gt_types.h | ||
196 | +++ b/drivers/gpu/drm/i915/gt/intel_gt_types.h | ||
197 | @@ -40,6 +40,8 @@ struct intel_gt { | ||
198 | |||
199 | struct intel_uc uc; | ||
200 | |||
201 | + struct mutex tlb_invalidate_lock; | ||
202 | + | ||
203 | struct intel_gt_timelines { | ||
204 | spinlock_t lock; /* protects active_list */ | ||
205 | struct list_head active_list; | ||
206 | diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h | ||
207 | index 7b6e68f082f8c..1386d0f5eac63 100644 | ||
208 | --- a/drivers/gpu/drm/i915/i915_reg.h | ||
209 | +++ b/drivers/gpu/drm/i915/i915_reg.h | ||
210 | @@ -2519,6 +2519,12 @@ static inline bool i915_mmio_reg_valid(i915_reg_t reg) | ||
211 | #define GAMT_CHKN_DISABLE_DYNAMIC_CREDIT_SHARING (1 << 28) | ||
212 | #define GAMT_CHKN_DISABLE_I2M_CYCLE_ON_WR_PORT (1 << 24) | ||
213 | |||
214 | +#define GEN8_RTCR _MMIO(0x4260) | ||
215 | +#define GEN8_M1TCR _MMIO(0x4264) | ||
216 | +#define GEN8_M2TCR _MMIO(0x4268) | ||
217 | +#define GEN8_BTCR _MMIO(0x426c) | ||
218 | +#define GEN8_VTCR _MMIO(0x4270) | ||
219 | + | ||
220 | #if 0 | ||
221 | #define PRB0_TAIL _MMIO(0x2030) | ||
222 | #define PRB0_HEAD _MMIO(0x2034) | ||
223 | @@ -2602,6 +2608,11 @@ static inline bool i915_mmio_reg_valid(i915_reg_t reg) | ||
224 | #define FAULT_VA_HIGH_BITS (0xf << 0) | ||
225 | #define FAULT_GTT_SEL (1 << 4) | ||
226 | |||
227 | +#define GEN12_GFX_TLB_INV_CR _MMIO(0xced8) | ||
228 | +#define GEN12_VD_TLB_INV_CR _MMIO(0xcedc) | ||
229 | +#define GEN12_VE_TLB_INV_CR _MMIO(0xcee0) | ||
230 | +#define GEN12_BLT_TLB_INV_CR _MMIO(0xcee4) | ||
231 | + | ||
232 | #define FPGA_DBG _MMIO(0x42300) | ||
233 | #define FPGA_DBG_RM_NOCLAIM (1 << 31) | ||
234 | |||
235 | diff --git a/drivers/gpu/drm/i915/i915_vma.c b/drivers/gpu/drm/i915/i915_vma.c | ||
236 | index e0e677b2a3a94..c24f49ee10d73 100644 | ||
237 | --- a/drivers/gpu/drm/i915/i915_vma.c | ||
238 | +++ b/drivers/gpu/drm/i915/i915_vma.c | ||
239 | @@ -341,6 +341,10 @@ int i915_vma_bind(struct i915_vma *vma, enum i915_cache_level cache_level, | ||
240 | return ret; | ||
241 | |||
242 | vma->flags |= bind_flags; | ||
243 | + | ||
244 | + if (vma->obj) | ||
245 | + set_bit(I915_BO_WAS_BOUND_BIT, &vma->obj->flags); | ||
246 | + | ||
247 | return 0; | ||
248 | } | ||
249 | |||
250 | diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h | ||
251 | index 5eb73ded8e07a..765f7a62870db 100644 | ||
252 | --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h | ||
253 | +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h | ||
254 | @@ -1002,15 +1002,14 @@ extern int vmw_execbuf_fence_commands(struct drm_file *file_priv, | ||
255 | struct vmw_private *dev_priv, | ||
256 | struct vmw_fence_obj **p_fence, | ||
257 | uint32_t *p_handle); | ||
258 | -extern void vmw_execbuf_copy_fence_user(struct vmw_private *dev_priv, | ||
259 | +extern int vmw_execbuf_copy_fence_user(struct vmw_private *dev_priv, | ||
260 | struct vmw_fpriv *vmw_fp, | ||
261 | int ret, | ||
262 | struct drm_vmw_fence_rep __user | ||
263 | *user_fence_rep, | ||
264 | struct vmw_fence_obj *fence, | ||
265 | uint32_t fence_handle, | ||
266 | - int32_t out_fence_fd, | ||
267 | - struct sync_file *sync_file); | ||
268 | + int32_t out_fence_fd); | ||
269 | bool vmw_cmd_describe(const void *buf, u32 *size, char const **cmd); | ||
270 | |||
271 | /** | ||
272 | diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c | ||
273 | index ff86d49dc5e8a..e3d20048075bf 100644 | ||
274 | --- a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c | ||
275 | +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c | ||
276 | @@ -3413,17 +3413,17 @@ int vmw_execbuf_fence_commands(struct drm_file *file_priv, | ||
277 | * Also if copying fails, user-space will be unable to signal the fence object | ||
278 | * so we wait for it immediately, and then unreference the user-space reference. | ||
279 | */ | ||
280 | -void | ||
281 | +int | ||
282 | vmw_execbuf_copy_fence_user(struct vmw_private *dev_priv, | ||
283 | struct vmw_fpriv *vmw_fp, int ret, | ||
284 | struct drm_vmw_fence_rep __user *user_fence_rep, | ||
285 | struct vmw_fence_obj *fence, uint32_t fence_handle, | ||
286 | - int32_t out_fence_fd, struct sync_file *sync_file) | ||
287 | + int32_t out_fence_fd) | ||
288 | { | ||
289 | struct drm_vmw_fence_rep fence_rep; | ||
290 | |||
291 | if (user_fence_rep == NULL) | ||
292 | - return; | ||
293 | + return 0; | ||
294 | |||
295 | memset(&fence_rep, 0, sizeof(fence_rep)); | ||
296 | |||
297 | @@ -3451,20 +3451,14 @@ vmw_execbuf_copy_fence_user(struct vmw_private *dev_priv, | ||
298 | * handle. | ||
299 | */ | ||
300 | if (unlikely(ret != 0) && (fence_rep.error == 0)) { | ||
301 | - if (sync_file) | ||
302 | - fput(sync_file->file); | ||
303 | - | ||
304 | - if (fence_rep.fd != -1) { | ||
305 | - put_unused_fd(fence_rep.fd); | ||
306 | - fence_rep.fd = -1; | ||
307 | - } | ||
308 | - | ||
309 | ttm_ref_object_base_unref(vmw_fp->tfile, fence_handle, | ||
310 | TTM_REF_USAGE); | ||
311 | VMW_DEBUG_USER("Fence copy error. Syncing.\n"); | ||
312 | (void) vmw_fence_obj_wait(fence, false, false, | ||
313 | VMW_FENCE_WAIT_TIMEOUT); | ||
314 | } | ||
315 | + | ||
316 | + return ret ? -EFAULT : 0; | ||
317 | } | ||
318 | |||
319 | /** | ||
320 | @@ -3806,16 +3800,23 @@ int vmw_execbuf_process(struct drm_file *file_priv, | ||
321 | |||
322 | (void) vmw_fence_obj_wait(fence, false, false, | ||
323 | VMW_FENCE_WAIT_TIMEOUT); | ||
324 | + } | ||
325 | + } | ||
326 | + | ||
327 | + ret = vmw_execbuf_copy_fence_user(dev_priv, vmw_fpriv(file_priv), ret, | ||
328 | + user_fence_rep, fence, handle, out_fence_fd); | ||
329 | + | ||
330 | + if (sync_file) { | ||
331 | + if (ret) { | ||
332 | + /* usercopy of fence failed, put the file object */ | ||
333 | + fput(sync_file->file); | ||
334 | + put_unused_fd(out_fence_fd); | ||
335 | } else { | ||
336 | /* Link the fence with the FD created earlier */ | ||
337 | fd_install(out_fence_fd, sync_file->file); | ||
338 | } | ||
339 | } | ||
340 | |||
341 | - vmw_execbuf_copy_fence_user(dev_priv, vmw_fpriv(file_priv), ret, | ||
342 | - user_fence_rep, fence, handle, out_fence_fd, | ||
343 | - sync_file); | ||
344 | - | ||
345 | /* Don't unreference when handing fence out */ | ||
346 | if (unlikely(out_fence != NULL)) { | ||
347 | *out_fence = fence; | ||
348 | @@ -3833,7 +3834,7 @@ int vmw_execbuf_process(struct drm_file *file_priv, | ||
349 | */ | ||
350 | vmw_validation_unref_lists(&val_ctx); | ||
351 | |||
352 | - return 0; | ||
353 | + return ret; | ||
354 | |||
355 | out_unlock_binding: | ||
356 | mutex_unlock(&dev_priv->binding_mutex); | ||
357 | diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c b/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c | ||
358 | index 178a6cd1a06fe..874093a0b04f0 100644 | ||
359 | --- a/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c | ||
360 | +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c | ||
361 | @@ -1171,7 +1171,7 @@ int vmw_fence_event_ioctl(struct drm_device *dev, void *data, | ||
362 | } | ||
363 | |||
364 | vmw_execbuf_copy_fence_user(dev_priv, vmw_fp, 0, user_fence_rep, fence, | ||
365 | - handle, -1, NULL); | ||
366 | + handle, -1); | ||
367 | vmw_fence_obj_unreference(&fence); | ||
368 | return 0; | ||
369 | out_no_create: | ||
370 | diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | ||
371 | index 33b1519887474..0b800c3540492 100644 | ||
372 | --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | ||
373 | +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | ||
374 | @@ -2570,7 +2570,7 @@ void vmw_kms_helper_validation_finish(struct vmw_private *dev_priv, | ||
375 | if (file_priv) | ||
376 | vmw_execbuf_copy_fence_user(dev_priv, vmw_fpriv(file_priv), | ||
377 | ret, user_fence_rep, fence, | ||
378 | - handle, -1, NULL); | ||
379 | + handle, -1); | ||
380 | if (out_fence) | ||
381 | *out_fence = fence; | ||
382 | else | ||
383 | diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c | ||
384 | index 2c01e2ebef7aa..d97c19ef75830 100644 | ||
385 | --- a/drivers/mmc/host/sdhci-esdhc-imx.c | ||
386 | +++ b/drivers/mmc/host/sdhci-esdhc-imx.c | ||
387 | @@ -218,8 +218,7 @@ static struct esdhc_soc_data usdhc_imx7ulp_data = { | ||
388 | static struct esdhc_soc_data usdhc_imx8qxp_data = { | ||
389 | .flags = ESDHC_FLAG_USDHC | ESDHC_FLAG_STD_TUNING | ||
390 | | ESDHC_FLAG_HAVE_CAP1 | ESDHC_FLAG_HS200 | ||
391 | - | ESDHC_FLAG_HS400 | ESDHC_FLAG_HS400_ES | ||
392 | - | ESDHC_FLAG_CQHCI, | ||
393 | + | ESDHC_FLAG_HS400 | ESDHC_FLAG_HS400_ES, | ||
394 | }; | ||
395 | |||
396 | struct pltfm_imx_data { | ||
397 | diff --git a/drivers/pinctrl/bcm/pinctrl-bcm2835.c b/drivers/pinctrl/bcm/pinctrl-bcm2835.c | ||
398 | index 0de1a3a96984c..fa742535f6791 100644 | ||
399 | --- a/drivers/pinctrl/bcm/pinctrl-bcm2835.c | ||
400 | +++ b/drivers/pinctrl/bcm/pinctrl-bcm2835.c | ||
401 | @@ -19,6 +19,7 @@ | ||
402 | #include <linux/irq.h> | ||
403 | #include <linux/irqdesc.h> | ||
404 | #include <linux/init.h> | ||
405 | +#include <linux/interrupt.h> | ||
406 | #include <linux/of_address.h> | ||
407 | #include <linux/of.h> | ||
408 | #include <linux/of_irq.h> | ||
409 | @@ -37,12 +38,10 @@ | ||
410 | |||
411 | #define MODULE_NAME "pinctrl-bcm2835" | ||
412 | #define BCM2835_NUM_GPIOS 54 | ||
413 | +#define BCM2711_NUM_GPIOS 58 | ||
414 | #define BCM2835_NUM_BANKS 2 | ||
415 | #define BCM2835_NUM_IRQS 3 | ||
416 | |||
417 | -#define BCM2835_PIN_BITMAP_SZ \ | ||
418 | - DIV_ROUND_UP(BCM2835_NUM_GPIOS, sizeof(unsigned long) * 8) | ||
419 | - | ||
420 | /* GPIO register offsets */ | ||
421 | #define GPFSEL0 0x0 /* Function Select */ | ||
422 | #define GPSET0 0x1c /* Pin Output Set */ | ||
423 | @@ -78,13 +77,15 @@ | ||
424 | struct bcm2835_pinctrl { | ||
425 | struct device *dev; | ||
426 | void __iomem *base; | ||
427 | + int *wake_irq; | ||
428 | |||
429 | /* note: locking assumes each bank will have its own unsigned long */ | ||
430 | unsigned long enabled_irq_map[BCM2835_NUM_BANKS]; | ||
431 | - unsigned int irq_type[BCM2835_NUM_GPIOS]; | ||
432 | + unsigned int irq_type[BCM2711_NUM_GPIOS]; | ||
433 | |||
434 | struct pinctrl_dev *pctl_dev; | ||
435 | struct gpio_chip gpio_chip; | ||
436 | + struct pinctrl_desc pctl_desc; | ||
437 | struct pinctrl_gpio_range gpio_range; | ||
438 | |||
439 | raw_spinlock_t irq_lock[BCM2835_NUM_BANKS]; | ||
440 | @@ -147,6 +148,10 @@ static struct pinctrl_pin_desc bcm2835_gpio_pins[] = { | ||
441 | BCM2835_GPIO_PIN(51), | ||
442 | BCM2835_GPIO_PIN(52), | ||
443 | BCM2835_GPIO_PIN(53), | ||
444 | + BCM2835_GPIO_PIN(54), | ||
445 | + BCM2835_GPIO_PIN(55), | ||
446 | + BCM2835_GPIO_PIN(56), | ||
447 | + BCM2835_GPIO_PIN(57), | ||
448 | }; | ||
449 | |||
450 | /* one pin per group */ | ||
451 | @@ -205,6 +210,10 @@ static const char * const bcm2835_gpio_groups[] = { | ||
452 | "gpio51", | ||
453 | "gpio52", | ||
454 | "gpio53", | ||
455 | + "gpio54", | ||
456 | + "gpio55", | ||
457 | + "gpio56", | ||
458 | + "gpio57", | ||
459 | }; | ||
460 | |||
461 | enum bcm2835_fsel { | ||
462 | @@ -355,6 +364,22 @@ static const struct gpio_chip bcm2835_gpio_chip = { | ||
463 | .can_sleep = false, | ||
464 | }; | ||
465 | |||
466 | +static const struct gpio_chip bcm2711_gpio_chip = { | ||
467 | + .label = "pinctrl-bcm2711", | ||
468 | + .owner = THIS_MODULE, | ||
469 | + .request = gpiochip_generic_request, | ||
470 | + .free = gpiochip_generic_free, | ||
471 | + .direction_input = bcm2835_gpio_direction_input, | ||
472 | + .direction_output = bcm2835_gpio_direction_output, | ||
473 | + .get_direction = bcm2835_gpio_get_direction, | ||
474 | + .get = bcm2835_gpio_get, | ||
475 | + .set = bcm2835_gpio_set, | ||
476 | + .set_config = gpiochip_generic_config, | ||
477 | + .base = -1, | ||
478 | + .ngpio = BCM2711_NUM_GPIOS, | ||
479 | + .can_sleep = false, | ||
480 | +}; | ||
481 | + | ||
482 | static void bcm2835_gpio_irq_handle_bank(struct bcm2835_pinctrl *pc, | ||
483 | unsigned int bank, u32 mask) | ||
484 | { | ||
485 | @@ -401,7 +426,7 @@ static void bcm2835_gpio_irq_handler(struct irq_desc *desc) | ||
486 | bcm2835_gpio_irq_handle_bank(pc, 0, 0xf0000000); | ||
487 | bcm2835_gpio_irq_handle_bank(pc, 1, 0x00003fff); | ||
488 | break; | ||
489 | - case 2: /* IRQ2 covers GPIOs 46-53 */ | ||
490 | + case 2: /* IRQ2 covers GPIOs 46-57 */ | ||
491 | bcm2835_gpio_irq_handle_bank(pc, 1, 0x003fc000); | ||
492 | break; | ||
493 | } | ||
494 | @@ -409,6 +434,11 @@ static void bcm2835_gpio_irq_handler(struct irq_desc *desc) | ||
495 | chained_irq_exit(host_chip, desc); | ||
496 | } | ||
497 | |||
498 | +static irqreturn_t bcm2835_gpio_wake_irq_handler(int irq, void *dev_id) | ||
499 | +{ | ||
500 | + return IRQ_HANDLED; | ||
501 | +} | ||
502 | + | ||
503 | static inline void __bcm2835_gpio_irq_config(struct bcm2835_pinctrl *pc, | ||
504 | unsigned reg, unsigned offset, bool enable) | ||
505 | { | ||
506 | @@ -608,6 +638,34 @@ static void bcm2835_gpio_irq_ack(struct irq_data *data) | ||
507 | bcm2835_gpio_set_bit(pc, GPEDS0, gpio); | ||
508 | } | ||
509 | |||
510 | +static int bcm2835_gpio_irq_set_wake(struct irq_data *data, unsigned int on) | ||
511 | +{ | ||
512 | + struct gpio_chip *chip = irq_data_get_irq_chip_data(data); | ||
513 | + struct bcm2835_pinctrl *pc = gpiochip_get_data(chip); | ||
514 | + unsigned gpio = irqd_to_hwirq(data); | ||
515 | + unsigned int irqgroup; | ||
516 | + int ret = -EINVAL; | ||
517 | + | ||
518 | + if (!pc->wake_irq) | ||
519 | + return ret; | ||
520 | + | ||
521 | + if (gpio <= 27) | ||
522 | + irqgroup = 0; | ||
523 | + else if (gpio >= 28 && gpio <= 45) | ||
524 | + irqgroup = 1; | ||
525 | + else if (gpio >= 46 && gpio <= 57) | ||
526 | + irqgroup = 2; | ||
527 | + else | ||
528 | + return ret; | ||
529 | + | ||
530 | + if (on) | ||
531 | + ret = enable_irq_wake(pc->wake_irq[irqgroup]); | ||
532 | + else | ||
533 | + ret = disable_irq_wake(pc->wake_irq[irqgroup]); | ||
534 | + | ||
535 | + return ret; | ||
536 | +} | ||
537 | + | ||
538 | static struct irq_chip bcm2835_gpio_irq_chip = { | ||
539 | .name = MODULE_NAME, | ||
540 | .irq_enable = bcm2835_gpio_irq_enable, | ||
541 | @@ -616,11 +674,13 @@ static struct irq_chip bcm2835_gpio_irq_chip = { | ||
542 | .irq_ack = bcm2835_gpio_irq_ack, | ||
543 | .irq_mask = bcm2835_gpio_irq_disable, | ||
544 | .irq_unmask = bcm2835_gpio_irq_enable, | ||
545 | + .irq_set_wake = bcm2835_gpio_irq_set_wake, | ||
546 | + .flags = IRQCHIP_MASK_ON_SUSPEND, | ||
547 | }; | ||
548 | |||
549 | static int bcm2835_pctl_get_groups_count(struct pinctrl_dev *pctldev) | ||
550 | { | ||
551 | - return ARRAY_SIZE(bcm2835_gpio_groups); | ||
552 | + return BCM2835_NUM_GPIOS; | ||
553 | } | ||
554 | |||
555 | static const char *bcm2835_pctl_get_group_name(struct pinctrl_dev *pctldev, | ||
556 | @@ -778,7 +838,7 @@ static int bcm2835_pctl_dt_node_to_map(struct pinctrl_dev *pctldev, | ||
557 | err = of_property_read_u32_index(np, "brcm,pins", i, &pin); | ||
558 | if (err) | ||
559 | goto out; | ||
560 | - if (pin >= ARRAY_SIZE(bcm2835_gpio_pins)) { | ||
561 | + if (pin >= pc->pctl_desc.npins) { | ||
562 | dev_err(pc->dev, "%pOF: invalid brcm,pins value %d\n", | ||
563 | np, pin); | ||
564 | err = -EINVAL; | ||
565 | @@ -854,7 +914,7 @@ static int bcm2835_pmx_get_function_groups(struct pinctrl_dev *pctldev, | ||
566 | { | ||
567 | /* every pin can do every function */ | ||
568 | *groups = bcm2835_gpio_groups; | ||
569 | - *num_groups = ARRAY_SIZE(bcm2835_gpio_groups); | ||
570 | + *num_groups = BCM2835_NUM_GPIOS; | ||
571 | |||
572 | return 0; | ||
573 | } | ||
574 | @@ -1054,29 +1114,66 @@ static const struct pinconf_ops bcm2711_pinconf_ops = { | ||
575 | .pin_config_set = bcm2711_pinconf_set, | ||
576 | }; | ||
577 | |||
578 | -static struct pinctrl_desc bcm2835_pinctrl_desc = { | ||
579 | +static const struct pinctrl_desc bcm2835_pinctrl_desc = { | ||
580 | .name = MODULE_NAME, | ||
581 | .pins = bcm2835_gpio_pins, | ||
582 | - .npins = ARRAY_SIZE(bcm2835_gpio_pins), | ||
583 | + .npins = BCM2835_NUM_GPIOS, | ||
584 | .pctlops = &bcm2835_pctl_ops, | ||
585 | .pmxops = &bcm2835_pmx_ops, | ||
586 | .confops = &bcm2835_pinconf_ops, | ||
587 | .owner = THIS_MODULE, | ||
588 | }; | ||
589 | |||
590 | -static struct pinctrl_gpio_range bcm2835_pinctrl_gpio_range = { | ||
591 | +static const struct pinctrl_desc bcm2711_pinctrl_desc = { | ||
592 | + .name = "pinctrl-bcm2711", | ||
593 | + .pins = bcm2835_gpio_pins, | ||
594 | + .npins = BCM2711_NUM_GPIOS, | ||
595 | + .pctlops = &bcm2835_pctl_ops, | ||
596 | + .pmxops = &bcm2835_pmx_ops, | ||
597 | + .confops = &bcm2711_pinconf_ops, | ||
598 | + .owner = THIS_MODULE, | ||
599 | +}; | ||
600 | + | ||
601 | +static const struct pinctrl_gpio_range bcm2835_pinctrl_gpio_range = { | ||
602 | .name = MODULE_NAME, | ||
603 | .npins = BCM2835_NUM_GPIOS, | ||
604 | }; | ||
605 | |||
606 | +static const struct pinctrl_gpio_range bcm2711_pinctrl_gpio_range = { | ||
607 | + .name = "pinctrl-bcm2711", | ||
608 | + .npins = BCM2711_NUM_GPIOS, | ||
609 | +}; | ||
610 | + | ||
611 | +struct bcm_plat_data { | ||
612 | + const struct gpio_chip *gpio_chip; | ||
613 | + const struct pinctrl_desc *pctl_desc; | ||
614 | + const struct pinctrl_gpio_range *gpio_range; | ||
615 | +}; | ||
616 | + | ||
617 | +static const struct bcm_plat_data bcm2835_plat_data = { | ||
618 | + .gpio_chip = &bcm2835_gpio_chip, | ||
619 | + .pctl_desc = &bcm2835_pinctrl_desc, | ||
620 | + .gpio_range = &bcm2835_pinctrl_gpio_range, | ||
621 | +}; | ||
622 | + | ||
623 | +static const struct bcm_plat_data bcm2711_plat_data = { | ||
624 | + .gpio_chip = &bcm2711_gpio_chip, | ||
625 | + .pctl_desc = &bcm2711_pinctrl_desc, | ||
626 | + .gpio_range = &bcm2711_pinctrl_gpio_range, | ||
627 | +}; | ||
628 | + | ||
629 | static const struct of_device_id bcm2835_pinctrl_match[] = { | ||
630 | { | ||
631 | .compatible = "brcm,bcm2835-gpio", | ||
632 | - .data = &bcm2835_pinconf_ops, | ||
633 | + .data = &bcm2835_plat_data, | ||
634 | }, | ||
635 | { | ||
636 | .compatible = "brcm,bcm2711-gpio", | ||
637 | - .data = &bcm2711_pinconf_ops, | ||
638 | + .data = &bcm2711_plat_data, | ||
639 | + }, | ||
640 | + { | ||
641 | + .compatible = "brcm,bcm7211-gpio", | ||
642 | + .data = &bcm2711_plat_data, | ||
643 | }, | ||
644 | {} | ||
645 | }; | ||
646 | @@ -1085,14 +1182,16 @@ static int bcm2835_pinctrl_probe(struct platform_device *pdev) | ||
647 | { | ||
648 | struct device *dev = &pdev->dev; | ||
649 | struct device_node *np = dev->of_node; | ||
650 | + const struct bcm_plat_data *pdata; | ||
651 | struct bcm2835_pinctrl *pc; | ||
652 | struct gpio_irq_chip *girq; | ||
653 | struct resource iomem; | ||
654 | int err, i; | ||
655 | const struct of_device_id *match; | ||
656 | + int is_7211 = 0; | ||
657 | |||
658 | - BUILD_BUG_ON(ARRAY_SIZE(bcm2835_gpio_pins) != BCM2835_NUM_GPIOS); | ||
659 | - BUILD_BUG_ON(ARRAY_SIZE(bcm2835_gpio_groups) != BCM2835_NUM_GPIOS); | ||
660 | + BUILD_BUG_ON(ARRAY_SIZE(bcm2835_gpio_pins) != BCM2711_NUM_GPIOS); | ||
661 | + BUILD_BUG_ON(ARRAY_SIZE(bcm2835_gpio_groups) != BCM2711_NUM_GPIOS); | ||
662 | |||
663 | pc = devm_kzalloc(dev, sizeof(*pc), GFP_KERNEL); | ||
664 | if (!pc) | ||
665 | @@ -1111,7 +1210,14 @@ static int bcm2835_pinctrl_probe(struct platform_device *pdev) | ||
666 | if (IS_ERR(pc->base)) | ||
667 | return PTR_ERR(pc->base); | ||
668 | |||
669 | - pc->gpio_chip = bcm2835_gpio_chip; | ||
670 | + match = of_match_node(bcm2835_pinctrl_match, pdev->dev.of_node); | ||
671 | + if (!match) | ||
672 | + return -EINVAL; | ||
673 | + | ||
674 | + pdata = match->data; | ||
675 | + is_7211 = of_device_is_compatible(np, "brcm,bcm7211-gpio"); | ||
676 | + | ||
677 | + pc->gpio_chip = *pdata->gpio_chip; | ||
678 | pc->gpio_chip.parent = dev; | ||
679 | pc->gpio_chip.of_node = np; | ||
680 | |||
681 | @@ -1135,6 +1241,18 @@ static int bcm2835_pinctrl_probe(struct platform_device *pdev) | ||
682 | raw_spin_lock_init(&pc->irq_lock[i]); | ||
683 | } | ||
684 | |||
685 | + pc->pctl_desc = *pdata->pctl_desc; | ||
686 | + pc->pctl_dev = devm_pinctrl_register(dev, &pc->pctl_desc, pc); | ||
687 | + if (IS_ERR(pc->pctl_dev)) { | ||
688 | + gpiochip_remove(&pc->gpio_chip); | ||
689 | + return PTR_ERR(pc->pctl_dev); | ||
690 | + } | ||
691 | + | ||
692 | + pc->gpio_range = *pdata->gpio_range; | ||
693 | + pc->gpio_range.base = pc->gpio_chip.base; | ||
694 | + pc->gpio_range.gc = &pc->gpio_chip; | ||
695 | + pinctrl_add_gpio_range(pc->pctl_dev, &pc->gpio_range); | ||
696 | + | ||
697 | girq = &pc->gpio_chip.irq; | ||
698 | girq->chip = &bcm2835_gpio_irq_chip; | ||
699 | girq->parent_handler = bcm2835_gpio_irq_handler; | ||
700 | @@ -1142,8 +1260,19 @@ static int bcm2835_pinctrl_probe(struct platform_device *pdev) | ||
701 | girq->parents = devm_kcalloc(dev, BCM2835_NUM_IRQS, | ||
702 | sizeof(*girq->parents), | ||
703 | GFP_KERNEL); | ||
704 | - if (!girq->parents) | ||
705 | + if (!girq->parents) { | ||
706 | + pinctrl_remove_gpio_range(pc->pctl_dev, &pc->gpio_range); | ||
707 | return -ENOMEM; | ||
708 | + } | ||
709 | + | ||
710 | + if (is_7211) { | ||
711 | + pc->wake_irq = devm_kcalloc(dev, BCM2835_NUM_IRQS, | ||
712 | + sizeof(*pc->wake_irq), | ||
713 | + GFP_KERNEL); | ||
714 | + if (!pc->wake_irq) | ||
715 | + return -ENOMEM; | ||
716 | + } | ||
717 | + | ||
718 | /* | ||
719 | * Use the same handler for all groups: this is necessary | ||
720 | * since we use one gpiochip to cover all lines - the | ||
721 | @@ -1151,34 +1280,44 @@ static int bcm2835_pinctrl_probe(struct platform_device *pdev) | ||
722 | * bank that was firing the IRQ and look up the per-group | ||
723 | * and bank data. | ||
724 | */ | ||
725 | - for (i = 0; i < BCM2835_NUM_IRQS; i++) | ||
726 | + for (i = 0; i < BCM2835_NUM_IRQS; i++) { | ||
727 | + int len; | ||
728 | + char *name; | ||
729 | + | ||
730 | girq->parents[i] = irq_of_parse_and_map(np, i); | ||
731 | + if (!is_7211) | ||
732 | + continue; | ||
733 | + | ||
734 | + /* Skip over the all banks interrupts */ | ||
735 | + pc->wake_irq[i] = irq_of_parse_and_map(np, i + | ||
736 | + BCM2835_NUM_IRQS + 1); | ||
737 | + | ||
738 | + len = strlen(dev_name(pc->dev)) + 16; | ||
739 | + name = devm_kzalloc(pc->dev, len, GFP_KERNEL); | ||
740 | + if (!name) | ||
741 | + return -ENOMEM; | ||
742 | + | ||
743 | + snprintf(name, len, "%s:bank%d", dev_name(pc->dev), i); | ||
744 | + | ||
745 | + /* These are optional interrupts */ | ||
746 | + err = devm_request_irq(dev, pc->wake_irq[i], | ||
747 | + bcm2835_gpio_wake_irq_handler, | ||
748 | + IRQF_SHARED, name, pc); | ||
749 | + if (err) | ||
750 | + dev_warn(dev, "unable to request wake IRQ %d\n", | ||
751 | + pc->wake_irq[i]); | ||
752 | + } | ||
753 | + | ||
754 | girq->default_type = IRQ_TYPE_NONE; | ||
755 | girq->handler = handle_level_irq; | ||
756 | |||
757 | err = gpiochip_add_data(&pc->gpio_chip, pc); | ||
758 | if (err) { | ||
759 | dev_err(dev, "could not add GPIO chip\n"); | ||
760 | + pinctrl_remove_gpio_range(pc->pctl_dev, &pc->gpio_range); | ||
761 | return err; | ||
762 | } | ||
763 | |||
764 | - match = of_match_node(bcm2835_pinctrl_match, pdev->dev.of_node); | ||
765 | - if (match) { | ||
766 | - bcm2835_pinctrl_desc.confops = | ||
767 | - (const struct pinconf_ops *)match->data; | ||
768 | - } | ||
769 | - | ||
770 | - pc->pctl_dev = devm_pinctrl_register(dev, &bcm2835_pinctrl_desc, pc); | ||
771 | - if (IS_ERR(pc->pctl_dev)) { | ||
772 | - gpiochip_remove(&pc->gpio_chip); | ||
773 | - return PTR_ERR(pc->pctl_dev); | ||
774 | - } | ||
775 | - | ||
776 | - pc->gpio_range = bcm2835_pinctrl_gpio_range; | ||
777 | - pc->gpio_range.base = pc->gpio_chip.base; | ||
778 | - pc->gpio_range.gc = &pc->gpio_chip; | ||
779 | - pinctrl_add_gpio_range(pc->pctl_dev, &pc->gpio_range); | ||
780 | - | ||
781 | return 0; | ||
782 | } | ||
783 | |||
784 | diff --git a/fs/select.c b/fs/select.c | ||
785 | index e51796063cb6e..7716d9d5be1e8 100644 | ||
786 | --- a/fs/select.c | ||
787 | +++ b/fs/select.c | ||
788 | @@ -458,9 +458,11 @@ get_max: | ||
789 | return max; | ||
790 | } | ||
791 | |||
792 | -#define POLLIN_SET (EPOLLRDNORM | EPOLLRDBAND | EPOLLIN | EPOLLHUP | EPOLLERR) | ||
793 | -#define POLLOUT_SET (EPOLLWRBAND | EPOLLWRNORM | EPOLLOUT | EPOLLERR) | ||
794 | -#define POLLEX_SET (EPOLLPRI) | ||
795 | +#define POLLIN_SET (EPOLLRDNORM | EPOLLRDBAND | EPOLLIN | EPOLLHUP | EPOLLERR |\ | ||
796 | + EPOLLNVAL) | ||
797 | +#define POLLOUT_SET (EPOLLWRBAND | EPOLLWRNORM | EPOLLOUT | EPOLLERR |\ | ||
798 | + EPOLLNVAL) | ||
799 | +#define POLLEX_SET (EPOLLPRI | EPOLLNVAL) | ||
800 | |||
801 | static inline void wait_key_set(poll_table *wait, unsigned long in, | ||
802 | unsigned long out, unsigned long bit, | ||
803 | @@ -527,6 +529,7 @@ static int do_select(int n, fd_set_bits *fds, struct timespec64 *end_time) | ||
804 | break; | ||
805 | if (!(bit & all_bits)) | ||
806 | continue; | ||
807 | + mask = EPOLLNVAL; | ||
808 | f = fdget(i); | ||
809 | if (f.file) { | ||
810 | wait_key_set(wait, in, out, bit, | ||
811 | @@ -534,34 +537,34 @@ static int do_select(int n, fd_set_bits *fds, struct timespec64 *end_time) | ||
812 | mask = vfs_poll(f.file, wait); | ||
813 | |||
814 | fdput(f); | ||
815 | - if ((mask & POLLIN_SET) && (in & bit)) { | ||
816 | - res_in |= bit; | ||
817 | - retval++; | ||
818 | - wait->_qproc = NULL; | ||
819 | - } | ||
820 | - if ((mask & POLLOUT_SET) && (out & bit)) { | ||
821 | - res_out |= bit; | ||
822 | - retval++; | ||
823 | - wait->_qproc = NULL; | ||
824 | - } | ||
825 | - if ((mask & POLLEX_SET) && (ex & bit)) { | ||
826 | - res_ex |= bit; | ||
827 | - retval++; | ||
828 | - wait->_qproc = NULL; | ||
829 | - } | ||
830 | - /* got something, stop busy polling */ | ||
831 | - if (retval) { | ||
832 | - can_busy_loop = false; | ||
833 | - busy_flag = 0; | ||
834 | - | ||
835 | - /* | ||
836 | - * only remember a returned | ||
837 | - * POLL_BUSY_LOOP if we asked for it | ||
838 | - */ | ||
839 | - } else if (busy_flag & mask) | ||
840 | - can_busy_loop = true; | ||
841 | - | ||
842 | } | ||
843 | + if ((mask & POLLIN_SET) && (in & bit)) { | ||
844 | + res_in |= bit; | ||
845 | + retval++; | ||
846 | + wait->_qproc = NULL; | ||
847 | + } | ||
848 | + if ((mask & POLLOUT_SET) && (out & bit)) { | ||
849 | + res_out |= bit; | ||
850 | + retval++; | ||
851 | + wait->_qproc = NULL; | ||
852 | + } | ||
853 | + if ((mask & POLLEX_SET) && (ex & bit)) { | ||
854 | + res_ex |= bit; | ||
855 | + retval++; | ||
856 | + wait->_qproc = NULL; | ||
857 | + } | ||
858 | + /* got something, stop busy polling */ | ||
859 | + if (retval) { | ||
860 | + can_busy_loop = false; | ||
861 | + busy_flag = 0; | ||
862 | + | ||
863 | + /* | ||
864 | + * only remember a returned | ||
865 | + * POLL_BUSY_LOOP if we asked for it | ||
866 | + */ | ||
867 | + } else if (busy_flag & mask) | ||
868 | + can_busy_loop = true; | ||
869 | + | ||
870 | } | ||
871 | if (res_in) | ||
872 | *rinp = res_in; | ||
873 | diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c | ||
874 | index 7777c35e0a171..5797cf2909b00 100644 | ||
875 | --- a/kernel/rcu/tree.c | ||
876 | +++ b/kernel/rcu/tree.c | ||
877 | @@ -1358,10 +1358,11 @@ static void __maybe_unused rcu_advance_cbs_nowake(struct rcu_node *rnp, | ||
878 | struct rcu_data *rdp) | ||
879 | { | ||
880 | rcu_lockdep_assert_cblist_protected(rdp); | ||
881 | - if (!rcu_seq_state(rcu_seq_current(&rnp->gp_seq)) || | ||
882 | - !raw_spin_trylock_rcu_node(rnp)) | ||
883 | + if (!rcu_seq_state(rcu_seq_current(&rnp->gp_seq)) || !raw_spin_trylock_rcu_node(rnp)) | ||
884 | return; | ||
885 | - WARN_ON_ONCE(rcu_advance_cbs(rnp, rdp)); | ||
886 | + // The grace period cannot end while we hold the rcu_node lock. | ||
887 | + if (rcu_seq_state(rcu_seq_current(&rnp->gp_seq))) | ||
888 | + WARN_ON_ONCE(rcu_advance_cbs(rnp, rdp)); | ||
889 | raw_spin_unlock_rcu_node(rnp); | ||
890 | } | ||
891 |