Annotation of /trunk/kernel-alx/patches-5.4/0105-5.4.6-all-fixes.patch
Parent Directory
|
Revision Log
Revision 3486 -
(hide annotations)
(download)
Mon May 11 14:36:00 2020 UTC (4 years, 1 month ago) by niro
File size: 115349 byte(s)
Mon May 11 14:36:00 2020 UTC (4 years, 1 month ago) by niro
File size: 115349 byte(s)
-linux-5.4.6
1 | niro | 3486 | diff --git a/Makefile b/Makefile |
2 | index 0f6e72d5e4f1..20ec7c20279e 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 = 5 | ||
10 | +SUBLEVEL = 6 | ||
11 | EXTRAVERSION = | ||
12 | NAME = Kleptomaniac Octopus | ||
13 | |||
14 | diff --git a/arch/arm/boot/dts/s3c6410-mini6410.dts b/arch/arm/boot/dts/s3c6410-mini6410.dts | ||
15 | index 0e159c884f97..1aeac33b0d34 100644 | ||
16 | --- a/arch/arm/boot/dts/s3c6410-mini6410.dts | ||
17 | +++ b/arch/arm/boot/dts/s3c6410-mini6410.dts | ||
18 | @@ -165,6 +165,10 @@ | ||
19 | }; | ||
20 | }; | ||
21 | |||
22 | +&clocks { | ||
23 | + clocks = <&fin_pll>; | ||
24 | +}; | ||
25 | + | ||
26 | &sdhci0 { | ||
27 | pinctrl-names = "default"; | ||
28 | pinctrl-0 = <&sd0_clk>, <&sd0_cmd>, <&sd0_cd>, <&sd0_bus4>; | ||
29 | diff --git a/arch/arm/boot/dts/s3c6410-smdk6410.dts b/arch/arm/boot/dts/s3c6410-smdk6410.dts | ||
30 | index a9a5689dc462..3bf6c450a26e 100644 | ||
31 | --- a/arch/arm/boot/dts/s3c6410-smdk6410.dts | ||
32 | +++ b/arch/arm/boot/dts/s3c6410-smdk6410.dts | ||
33 | @@ -69,6 +69,10 @@ | ||
34 | }; | ||
35 | }; | ||
36 | |||
37 | +&clocks { | ||
38 | + clocks = <&fin_pll>; | ||
39 | +}; | ||
40 | + | ||
41 | &sdhci0 { | ||
42 | pinctrl-names = "default"; | ||
43 | pinctrl-0 = <&sd0_clk>, <&sd0_cmd>, <&sd0_cd>, <&sd0_bus4>; | ||
44 | diff --git a/arch/arm/mach-tegra/reset-handler.S b/arch/arm/mach-tegra/reset-handler.S | ||
45 | index 67b763fea005..e3f34815c9da 100644 | ||
46 | --- a/arch/arm/mach-tegra/reset-handler.S | ||
47 | +++ b/arch/arm/mach-tegra/reset-handler.S | ||
48 | @@ -44,16 +44,16 @@ ENTRY(tegra_resume) | ||
49 | cmp r6, #TEGRA20 | ||
50 | beq 1f @ Yes | ||
51 | /* Clear the flow controller flags for this CPU. */ | ||
52 | - cpu_to_csr_reg r1, r0 | ||
53 | + cpu_to_csr_reg r3, r0 | ||
54 | mov32 r2, TEGRA_FLOW_CTRL_BASE | ||
55 | - ldr r1, [r2, r1] | ||
56 | + ldr r1, [r2, r3] | ||
57 | /* Clear event & intr flag */ | ||
58 | orr r1, r1, \ | ||
59 | #FLOW_CTRL_CSR_INTR_FLAG | FLOW_CTRL_CSR_EVENT_FLAG | ||
60 | movw r0, #0x3FFD @ enable, cluster_switch, immed, bitmaps | ||
61 | @ & ext flags for CPU power mgnt | ||
62 | bic r1, r1, r0 | ||
63 | - str r1, [r2] | ||
64 | + str r1, [r2, r3] | ||
65 | 1: | ||
66 | |||
67 | mov32 r9, 0xc09 | ||
68 | diff --git a/arch/xtensa/include/asm/syscall.h b/arch/xtensa/include/asm/syscall.h | ||
69 | index 359ab40e935a..c90fb944f9d8 100644 | ||
70 | --- a/arch/xtensa/include/asm/syscall.h | ||
71 | +++ b/arch/xtensa/include/asm/syscall.h | ||
72 | @@ -51,7 +51,7 @@ static inline void syscall_set_return_value(struct task_struct *task, | ||
73 | struct pt_regs *regs, | ||
74 | int error, long val) | ||
75 | { | ||
76 | - regs->areg[0] = (long) error ? error : val; | ||
77 | + regs->areg[2] = (long) error ? error : val; | ||
78 | } | ||
79 | |||
80 | #define SYSCALL_MAX_ARGS 6 | ||
81 | diff --git a/arch/xtensa/mm/kasan_init.c b/arch/xtensa/mm/kasan_init.c | ||
82 | index af7152560bc3..b771459778fe 100644 | ||
83 | --- a/arch/xtensa/mm/kasan_init.c | ||
84 | +++ b/arch/xtensa/mm/kasan_init.c | ||
85 | @@ -56,7 +56,9 @@ static void __init populate(void *start, void *end) | ||
86 | |||
87 | for (k = 0; k < PTRS_PER_PTE; ++k, ++j) { | ||
88 | phys_addr_t phys = | ||
89 | - memblock_phys_alloc(PAGE_SIZE, PAGE_SIZE); | ||
90 | + memblock_phys_alloc_range(PAGE_SIZE, PAGE_SIZE, | ||
91 | + 0, | ||
92 | + MEMBLOCK_ALLOC_ANYWHERE); | ||
93 | |||
94 | if (!phys) | ||
95 | panic("Failed to allocate page table page\n"); | ||
96 | diff --git a/arch/xtensa/mm/tlb.c b/arch/xtensa/mm/tlb.c | ||
97 | index 59153d0aa890..b43f03620843 100644 | ||
98 | --- a/arch/xtensa/mm/tlb.c | ||
99 | +++ b/arch/xtensa/mm/tlb.c | ||
100 | @@ -216,6 +216,8 @@ static int check_tlb_entry(unsigned w, unsigned e, bool dtlb) | ||
101 | unsigned tlbidx = w | (e << PAGE_SHIFT); | ||
102 | unsigned r0 = dtlb ? | ||
103 | read_dtlb_virtual(tlbidx) : read_itlb_virtual(tlbidx); | ||
104 | + unsigned r1 = dtlb ? | ||
105 | + read_dtlb_translation(tlbidx) : read_itlb_translation(tlbidx); | ||
106 | unsigned vpn = (r0 & PAGE_MASK) | (e << PAGE_SHIFT); | ||
107 | unsigned pte = get_pte_for_vaddr(vpn); | ||
108 | unsigned mm_asid = (get_rasid_register() >> 8) & ASID_MASK; | ||
109 | @@ -231,8 +233,6 @@ static int check_tlb_entry(unsigned w, unsigned e, bool dtlb) | ||
110 | } | ||
111 | |||
112 | if (tlb_asid == mm_asid) { | ||
113 | - unsigned r1 = dtlb ? read_dtlb_translation(tlbidx) : | ||
114 | - read_itlb_translation(tlbidx); | ||
115 | if ((pte ^ r1) & PAGE_MASK) { | ||
116 | pr_err("%cTLB: way: %u, entry: %u, mapping: %08x->%08x, PTE: %08x\n", | ||
117 | dtlb ? 'D' : 'I', w, e, r0, r1, pte); | ||
118 | diff --git a/block/bio.c b/block/bio.c | ||
119 | index b1170ec18464..43df756b68c4 100644 | ||
120 | --- a/block/bio.c | ||
121 | +++ b/block/bio.c | ||
122 | @@ -751,10 +751,12 @@ bool __bio_try_merge_page(struct bio *bio, struct page *page, | ||
123 | if (WARN_ON_ONCE(bio_flagged(bio, BIO_CLONED))) | ||
124 | return false; | ||
125 | |||
126 | - if (bio->bi_vcnt > 0 && !bio_full(bio, len)) { | ||
127 | + if (bio->bi_vcnt > 0) { | ||
128 | struct bio_vec *bv = &bio->bi_io_vec[bio->bi_vcnt - 1]; | ||
129 | |||
130 | if (page_is_mergeable(bv, page, len, off, same_page)) { | ||
131 | + if (bio->bi_iter.bi_size > UINT_MAX - len) | ||
132 | + return false; | ||
133 | bv->bv_len += len; | ||
134 | bio->bi_iter.bi_size += len; | ||
135 | return true; | ||
136 | diff --git a/drivers/dma-buf/sync_file.c b/drivers/dma-buf/sync_file.c | ||
137 | index 25c5c071645b..91185db9a952 100644 | ||
138 | --- a/drivers/dma-buf/sync_file.c | ||
139 | +++ b/drivers/dma-buf/sync_file.c | ||
140 | @@ -221,7 +221,7 @@ static struct sync_file *sync_file_merge(const char *name, struct sync_file *a, | ||
141 | a_fences = get_fences(a, &a_num_fences); | ||
142 | b_fences = get_fences(b, &b_num_fences); | ||
143 | if (a_num_fences > INT_MAX - b_num_fences) | ||
144 | - return NULL; | ||
145 | + goto err; | ||
146 | |||
147 | num_fences = a_num_fences + b_num_fences; | ||
148 | |||
149 | diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h | ||
150 | index b6e1d98ef01e..aef6c396bd58 100644 | ||
151 | --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h | ||
152 | +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h | ||
153 | @@ -77,6 +77,7 @@ struct amdgpu_gmc_fault { | ||
154 | struct amdgpu_vmhub { | ||
155 | uint32_t ctx0_ptb_addr_lo32; | ||
156 | uint32_t ctx0_ptb_addr_hi32; | ||
157 | + uint32_t vm_inv_eng0_sem; | ||
158 | uint32_t vm_inv_eng0_req; | ||
159 | uint32_t vm_inv_eng0_ack; | ||
160 | uint32_t vm_context0_cntl; | ||
161 | diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c | ||
162 | index 53090eae0082..596722e79a26 100644 | ||
163 | --- a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c | ||
164 | +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c | ||
165 | @@ -1785,27 +1785,52 @@ static void gfx_v10_0_enable_gui_idle_interrupt(struct amdgpu_device *adev, | ||
166 | WREG32_SOC15(GC, 0, mmCP_INT_CNTL_RING0, tmp); | ||
167 | } | ||
168 | |||
169 | -static void gfx_v10_0_init_csb(struct amdgpu_device *adev) | ||
170 | +static int gfx_v10_0_init_csb(struct amdgpu_device *adev) | ||
171 | { | ||
172 | + int r; | ||
173 | + | ||
174 | + if (adev->in_gpu_reset) { | ||
175 | + r = amdgpu_bo_reserve(adev->gfx.rlc.clear_state_obj, false); | ||
176 | + if (r) | ||
177 | + return r; | ||
178 | + | ||
179 | + r = amdgpu_bo_kmap(adev->gfx.rlc.clear_state_obj, | ||
180 | + (void **)&adev->gfx.rlc.cs_ptr); | ||
181 | + if (!r) { | ||
182 | + adev->gfx.rlc.funcs->get_csb_buffer(adev, | ||
183 | + adev->gfx.rlc.cs_ptr); | ||
184 | + amdgpu_bo_kunmap(adev->gfx.rlc.clear_state_obj); | ||
185 | + } | ||
186 | + | ||
187 | + amdgpu_bo_unreserve(adev->gfx.rlc.clear_state_obj); | ||
188 | + if (r) | ||
189 | + return r; | ||
190 | + } | ||
191 | + | ||
192 | /* csib */ | ||
193 | WREG32_SOC15(GC, 0, mmRLC_CSIB_ADDR_HI, | ||
194 | adev->gfx.rlc.clear_state_gpu_addr >> 32); | ||
195 | WREG32_SOC15(GC, 0, mmRLC_CSIB_ADDR_LO, | ||
196 | adev->gfx.rlc.clear_state_gpu_addr & 0xfffffffc); | ||
197 | WREG32_SOC15(GC, 0, mmRLC_CSIB_LENGTH, adev->gfx.rlc.clear_state_size); | ||
198 | + | ||
199 | + return 0; | ||
200 | } | ||
201 | |||
202 | -static void gfx_v10_0_init_pg(struct amdgpu_device *adev) | ||
203 | +static int gfx_v10_0_init_pg(struct amdgpu_device *adev) | ||
204 | { | ||
205 | int i; | ||
206 | + int r; | ||
207 | |||
208 | - gfx_v10_0_init_csb(adev); | ||
209 | + r = gfx_v10_0_init_csb(adev); | ||
210 | + if (r) | ||
211 | + return r; | ||
212 | |||
213 | for (i = 0; i < adev->num_vmhubs; i++) | ||
214 | amdgpu_gmc_flush_gpu_tlb(adev, 0, i, 0); | ||
215 | |||
216 | /* TODO: init power gating */ | ||
217 | - return; | ||
218 | + return 0; | ||
219 | } | ||
220 | |||
221 | void gfx_v10_0_rlc_stop(struct amdgpu_device *adev) | ||
222 | @@ -1907,7 +1932,10 @@ static int gfx_v10_0_rlc_resume(struct amdgpu_device *adev) | ||
223 | r = gfx_v10_0_wait_for_rlc_autoload_complete(adev); | ||
224 | if (r) | ||
225 | return r; | ||
226 | - gfx_v10_0_init_pg(adev); | ||
227 | + | ||
228 | + r = gfx_v10_0_init_pg(adev); | ||
229 | + if (r) | ||
230 | + return r; | ||
231 | |||
232 | /* enable RLC SRM */ | ||
233 | gfx_v10_0_rlc_enable_srm(adev); | ||
234 | @@ -1933,7 +1961,10 @@ static int gfx_v10_0_rlc_resume(struct amdgpu_device *adev) | ||
235 | return r; | ||
236 | } | ||
237 | |||
238 | - gfx_v10_0_init_pg(adev); | ||
239 | + r = gfx_v10_0_init_pg(adev); | ||
240 | + if (r) | ||
241 | + return r; | ||
242 | + | ||
243 | adev->gfx.rlc.funcs->start(adev); | ||
244 | |||
245 | if (adev->firmware.load_type == AMDGPU_FW_LOAD_RLC_BACKDOOR_AUTO) { | ||
246 | @@ -2400,7 +2431,7 @@ static int gfx_v10_0_wait_for_rlc_autoload_complete(struct amdgpu_device *adev) | ||
247 | return 0; | ||
248 | } | ||
249 | |||
250 | -static void gfx_v10_0_cp_gfx_enable(struct amdgpu_device *adev, bool enable) | ||
251 | +static int gfx_v10_0_cp_gfx_enable(struct amdgpu_device *adev, bool enable) | ||
252 | { | ||
253 | int i; | ||
254 | u32 tmp = RREG32_SOC15(GC, 0, mmCP_ME_CNTL); | ||
255 | @@ -2413,7 +2444,17 @@ static void gfx_v10_0_cp_gfx_enable(struct amdgpu_device *adev, bool enable) | ||
256 | adev->gfx.gfx_ring[i].sched.ready = false; | ||
257 | } | ||
258 | WREG32_SOC15(GC, 0, mmCP_ME_CNTL, tmp); | ||
259 | - udelay(50); | ||
260 | + | ||
261 | + for (i = 0; i < adev->usec_timeout; i++) { | ||
262 | + if (RREG32_SOC15(GC, 0, mmCP_STAT) == 0) | ||
263 | + break; | ||
264 | + udelay(1); | ||
265 | + } | ||
266 | + | ||
267 | + if (i >= adev->usec_timeout) | ||
268 | + DRM_ERROR("failed to %s cp gfx\n", enable ? "unhalt" : "halt"); | ||
269 | + | ||
270 | + return 0; | ||
271 | } | ||
272 | |||
273 | static int gfx_v10_0_cp_gfx_load_pfp_microcode(struct amdgpu_device *adev) | ||
274 | diff --git a/drivers/gpu/drm/amd/amdgpu/gfxhub_v1_0.c b/drivers/gpu/drm/amd/amdgpu/gfxhub_v1_0.c | ||
275 | index 6ce37ce77d14..d6fbdc6c0548 100644 | ||
276 | --- a/drivers/gpu/drm/amd/amdgpu/gfxhub_v1_0.c | ||
277 | +++ b/drivers/gpu/drm/amd/amdgpu/gfxhub_v1_0.c | ||
278 | @@ -365,6 +365,8 @@ void gfxhub_v1_0_init(struct amdgpu_device *adev) | ||
279 | hub->ctx0_ptb_addr_hi32 = | ||
280 | SOC15_REG_OFFSET(GC, 0, | ||
281 | mmVM_CONTEXT0_PAGE_TABLE_BASE_ADDR_HI32); | ||
282 | + hub->vm_inv_eng0_sem = | ||
283 | + SOC15_REG_OFFSET(GC, 0, mmVM_INVALIDATE_ENG0_SEM); | ||
284 | hub->vm_inv_eng0_req = | ||
285 | SOC15_REG_OFFSET(GC, 0, mmVM_INVALIDATE_ENG0_REQ); | ||
286 | hub->vm_inv_eng0_ack = | ||
287 | diff --git a/drivers/gpu/drm/amd/amdgpu/gfxhub_v2_0.c b/drivers/gpu/drm/amd/amdgpu/gfxhub_v2_0.c | ||
288 | index db10640a3b2f..fbe06c13a09c 100644 | ||
289 | --- a/drivers/gpu/drm/amd/amdgpu/gfxhub_v2_0.c | ||
290 | +++ b/drivers/gpu/drm/amd/amdgpu/gfxhub_v2_0.c | ||
291 | @@ -350,6 +350,8 @@ void gfxhub_v2_0_init(struct amdgpu_device *adev) | ||
292 | hub->ctx0_ptb_addr_hi32 = | ||
293 | SOC15_REG_OFFSET(GC, 0, | ||
294 | mmGCVM_CONTEXT0_PAGE_TABLE_BASE_ADDR_HI32); | ||
295 | + hub->vm_inv_eng0_sem = | ||
296 | + SOC15_REG_OFFSET(GC, 0, mmGCVM_INVALIDATE_ENG0_SEM); | ||
297 | hub->vm_inv_eng0_req = | ||
298 | SOC15_REG_OFFSET(GC, 0, mmGCVM_INVALIDATE_ENG0_REQ); | ||
299 | hub->vm_inv_eng0_ack = | ||
300 | diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c | ||
301 | index 5c7d5f73f54f..a7ba4c6cf7a1 100644 | ||
302 | --- a/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c | ||
303 | +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c | ||
304 | @@ -235,6 +235,29 @@ static void gmc_v10_0_flush_vm_hub(struct amdgpu_device *adev, uint32_t vmid, | ||
305 | const unsigned eng = 17; | ||
306 | unsigned int i; | ||
307 | |||
308 | + spin_lock(&adev->gmc.invalidate_lock); | ||
309 | + /* | ||
310 | + * It may lose gpuvm invalidate acknowldege state across power-gating | ||
311 | + * off cycle, add semaphore acquire before invalidation and semaphore | ||
312 | + * release after invalidation to avoid entering power gated state | ||
313 | + * to WA the Issue | ||
314 | + */ | ||
315 | + | ||
316 | + /* TODO: It needs to continue working on debugging with semaphore for GFXHUB as well. */ | ||
317 | + if (vmhub == AMDGPU_MMHUB_0 || | ||
318 | + vmhub == AMDGPU_MMHUB_1) { | ||
319 | + for (i = 0; i < adev->usec_timeout; i++) { | ||
320 | + /* a read return value of 1 means semaphore acuqire */ | ||
321 | + tmp = RREG32_NO_KIQ(hub->vm_inv_eng0_sem + eng); | ||
322 | + if (tmp & 0x1) | ||
323 | + break; | ||
324 | + udelay(1); | ||
325 | + } | ||
326 | + | ||
327 | + if (i >= adev->usec_timeout) | ||
328 | + DRM_ERROR("Timeout waiting for sem acquire in VM flush!\n"); | ||
329 | + } | ||
330 | + | ||
331 | WREG32_NO_KIQ(hub->vm_inv_eng0_req + eng, tmp); | ||
332 | |||
333 | /* | ||
334 | @@ -254,6 +277,17 @@ static void gmc_v10_0_flush_vm_hub(struct amdgpu_device *adev, uint32_t vmid, | ||
335 | udelay(1); | ||
336 | } | ||
337 | |||
338 | + /* TODO: It needs to continue working on debugging with semaphore for GFXHUB as well. */ | ||
339 | + if (vmhub == AMDGPU_MMHUB_0 || | ||
340 | + vmhub == AMDGPU_MMHUB_1) | ||
341 | + /* | ||
342 | + * add semaphore release after invalidation, | ||
343 | + * write with 0 means semaphore release | ||
344 | + */ | ||
345 | + WREG32_NO_KIQ(hub->vm_inv_eng0_sem + eng, 0); | ||
346 | + | ||
347 | + spin_unlock(&adev->gmc.invalidate_lock); | ||
348 | + | ||
349 | if (i < adev->usec_timeout) | ||
350 | return; | ||
351 | |||
352 | @@ -338,6 +372,20 @@ static uint64_t gmc_v10_0_emit_flush_gpu_tlb(struct amdgpu_ring *ring, | ||
353 | uint32_t req = gmc_v10_0_get_invalidate_req(vmid, 0); | ||
354 | unsigned eng = ring->vm_inv_eng; | ||
355 | |||
356 | + /* | ||
357 | + * It may lose gpuvm invalidate acknowldege state across power-gating | ||
358 | + * off cycle, add semaphore acquire before invalidation and semaphore | ||
359 | + * release after invalidation to avoid entering power gated state | ||
360 | + * to WA the Issue | ||
361 | + */ | ||
362 | + | ||
363 | + /* TODO: It needs to continue working on debugging with semaphore for GFXHUB as well. */ | ||
364 | + if (ring->funcs->vmhub == AMDGPU_MMHUB_0 || | ||
365 | + ring->funcs->vmhub == AMDGPU_MMHUB_1) | ||
366 | + /* a read return value of 1 means semaphore acuqire */ | ||
367 | + amdgpu_ring_emit_reg_wait(ring, | ||
368 | + hub->vm_inv_eng0_sem + eng, 0x1, 0x1); | ||
369 | + | ||
370 | amdgpu_ring_emit_wreg(ring, hub->ctx0_ptb_addr_lo32 + (2 * vmid), | ||
371 | lower_32_bits(pd_addr)); | ||
372 | |||
373 | @@ -348,6 +396,15 @@ static uint64_t gmc_v10_0_emit_flush_gpu_tlb(struct amdgpu_ring *ring, | ||
374 | hub->vm_inv_eng0_ack + eng, | ||
375 | req, 1 << vmid); | ||
376 | |||
377 | + /* TODO: It needs to continue working on debugging with semaphore for GFXHUB as well. */ | ||
378 | + if (ring->funcs->vmhub == AMDGPU_MMHUB_0 || | ||
379 | + ring->funcs->vmhub == AMDGPU_MMHUB_1) | ||
380 | + /* | ||
381 | + * add semaphore release after invalidation, | ||
382 | + * write with 0 means semaphore release | ||
383 | + */ | ||
384 | + amdgpu_ring_emit_wreg(ring, hub->vm_inv_eng0_sem + eng, 0); | ||
385 | + | ||
386 | return pd_addr; | ||
387 | } | ||
388 | |||
389 | diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c | ||
390 | index f91337030dc0..d7caca042173 100644 | ||
391 | --- a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c | ||
392 | +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c | ||
393 | @@ -448,6 +448,24 @@ static uint32_t gmc_v9_0_get_invalidate_req(unsigned int vmid, | ||
394 | return req; | ||
395 | } | ||
396 | |||
397 | +/** | ||
398 | + * gmc_v9_0_use_invalidate_semaphore - judge whether to use semaphore | ||
399 | + * | ||
400 | + * @adev: amdgpu_device pointer | ||
401 | + * @vmhub: vmhub type | ||
402 | + * | ||
403 | + */ | ||
404 | +static bool gmc_v9_0_use_invalidate_semaphore(struct amdgpu_device *adev, | ||
405 | + uint32_t vmhub) | ||
406 | +{ | ||
407 | + return ((vmhub == AMDGPU_MMHUB_0 || | ||
408 | + vmhub == AMDGPU_MMHUB_1) && | ||
409 | + (!amdgpu_sriov_vf(adev)) && | ||
410 | + (!(adev->asic_type == CHIP_RAVEN && | ||
411 | + adev->rev_id < 0x8 && | ||
412 | + adev->pdev->device == 0x15d8))); | ||
413 | +} | ||
414 | + | ||
415 | /* | ||
416 | * GART | ||
417 | * VMID 0 is the physical GPU addresses as used by the kernel. | ||
418 | @@ -467,6 +485,7 @@ static uint32_t gmc_v9_0_get_invalidate_req(unsigned int vmid, | ||
419 | static void gmc_v9_0_flush_gpu_tlb(struct amdgpu_device *adev, uint32_t vmid, | ||
420 | uint32_t vmhub, uint32_t flush_type) | ||
421 | { | ||
422 | + bool use_semaphore = gmc_v9_0_use_invalidate_semaphore(adev, vmhub); | ||
423 | const unsigned eng = 17; | ||
424 | u32 j, tmp; | ||
425 | struct amdgpu_vmhub *hub; | ||
426 | @@ -491,6 +510,28 @@ static void gmc_v9_0_flush_gpu_tlb(struct amdgpu_device *adev, uint32_t vmid, | ||
427 | } | ||
428 | |||
429 | spin_lock(&adev->gmc.invalidate_lock); | ||
430 | + | ||
431 | + /* | ||
432 | + * It may lose gpuvm invalidate acknowldege state across power-gating | ||
433 | + * off cycle, add semaphore acquire before invalidation and semaphore | ||
434 | + * release after invalidation to avoid entering power gated state | ||
435 | + * to WA the Issue | ||
436 | + */ | ||
437 | + | ||
438 | + /* TODO: It needs to continue working on debugging with semaphore for GFXHUB as well. */ | ||
439 | + if (use_semaphore) { | ||
440 | + for (j = 0; j < adev->usec_timeout; j++) { | ||
441 | + /* a read return value of 1 means semaphore acuqire */ | ||
442 | + tmp = RREG32_NO_KIQ(hub->vm_inv_eng0_sem + eng); | ||
443 | + if (tmp & 0x1) | ||
444 | + break; | ||
445 | + udelay(1); | ||
446 | + } | ||
447 | + | ||
448 | + if (j >= adev->usec_timeout) | ||
449 | + DRM_ERROR("Timeout waiting for sem acquire in VM flush!\n"); | ||
450 | + } | ||
451 | + | ||
452 | WREG32_NO_KIQ(hub->vm_inv_eng0_req + eng, tmp); | ||
453 | |||
454 | /* | ||
455 | @@ -506,7 +547,17 @@ static void gmc_v9_0_flush_gpu_tlb(struct amdgpu_device *adev, uint32_t vmid, | ||
456 | break; | ||
457 | udelay(1); | ||
458 | } | ||
459 | + | ||
460 | + /* TODO: It needs to continue working on debugging with semaphore for GFXHUB as well. */ | ||
461 | + if (use_semaphore) | ||
462 | + /* | ||
463 | + * add semaphore release after invalidation, | ||
464 | + * write with 0 means semaphore release | ||
465 | + */ | ||
466 | + WREG32_NO_KIQ(hub->vm_inv_eng0_sem + eng, 0); | ||
467 | + | ||
468 | spin_unlock(&adev->gmc.invalidate_lock); | ||
469 | + | ||
470 | if (j < adev->usec_timeout) | ||
471 | return; | ||
472 | |||
473 | @@ -516,11 +567,25 @@ static void gmc_v9_0_flush_gpu_tlb(struct amdgpu_device *adev, uint32_t vmid, | ||
474 | static uint64_t gmc_v9_0_emit_flush_gpu_tlb(struct amdgpu_ring *ring, | ||
475 | unsigned vmid, uint64_t pd_addr) | ||
476 | { | ||
477 | + bool use_semaphore = gmc_v9_0_use_invalidate_semaphore(ring->adev, ring->funcs->vmhub); | ||
478 | struct amdgpu_device *adev = ring->adev; | ||
479 | struct amdgpu_vmhub *hub = &adev->vmhub[ring->funcs->vmhub]; | ||
480 | uint32_t req = gmc_v9_0_get_invalidate_req(vmid, 0); | ||
481 | unsigned eng = ring->vm_inv_eng; | ||
482 | |||
483 | + /* | ||
484 | + * It may lose gpuvm invalidate acknowldege state across power-gating | ||
485 | + * off cycle, add semaphore acquire before invalidation and semaphore | ||
486 | + * release after invalidation to avoid entering power gated state | ||
487 | + * to WA the Issue | ||
488 | + */ | ||
489 | + | ||
490 | + /* TODO: It needs to continue working on debugging with semaphore for GFXHUB as well. */ | ||
491 | + if (use_semaphore) | ||
492 | + /* a read return value of 1 means semaphore acuqire */ | ||
493 | + amdgpu_ring_emit_reg_wait(ring, | ||
494 | + hub->vm_inv_eng0_sem + eng, 0x1, 0x1); | ||
495 | + | ||
496 | amdgpu_ring_emit_wreg(ring, hub->ctx0_ptb_addr_lo32 + (2 * vmid), | ||
497 | lower_32_bits(pd_addr)); | ||
498 | |||
499 | @@ -531,6 +596,14 @@ static uint64_t gmc_v9_0_emit_flush_gpu_tlb(struct amdgpu_ring *ring, | ||
500 | hub->vm_inv_eng0_ack + eng, | ||
501 | req, 1 << vmid); | ||
502 | |||
503 | + /* TODO: It needs to continue working on debugging with semaphore for GFXHUB as well. */ | ||
504 | + if (use_semaphore) | ||
505 | + /* | ||
506 | + * add semaphore release after invalidation, | ||
507 | + * write with 0 means semaphore release | ||
508 | + */ | ||
509 | + amdgpu_ring_emit_wreg(ring, hub->vm_inv_eng0_sem + eng, 0); | ||
510 | + | ||
511 | return pd_addr; | ||
512 | } | ||
513 | |||
514 | diff --git a/drivers/gpu/drm/amd/amdgpu/mmhub_v1_0.c b/drivers/gpu/drm/amd/amdgpu/mmhub_v1_0.c | ||
515 | index 04cd4b6f95d4..641f1258f08d 100644 | ||
516 | --- a/drivers/gpu/drm/amd/amdgpu/mmhub_v1_0.c | ||
517 | +++ b/drivers/gpu/drm/amd/amdgpu/mmhub_v1_0.c | ||
518 | @@ -418,6 +418,8 @@ void mmhub_v1_0_init(struct amdgpu_device *adev) | ||
519 | hub->ctx0_ptb_addr_hi32 = | ||
520 | SOC15_REG_OFFSET(MMHUB, 0, | ||
521 | mmVM_CONTEXT0_PAGE_TABLE_BASE_ADDR_HI32); | ||
522 | + hub->vm_inv_eng0_sem = | ||
523 | + SOC15_REG_OFFSET(MMHUB, 0, mmVM_INVALIDATE_ENG0_SEM); | ||
524 | hub->vm_inv_eng0_req = | ||
525 | SOC15_REG_OFFSET(MMHUB, 0, mmVM_INVALIDATE_ENG0_REQ); | ||
526 | hub->vm_inv_eng0_ack = | ||
527 | diff --git a/drivers/gpu/drm/amd/amdgpu/mmhub_v2_0.c b/drivers/gpu/drm/amd/amdgpu/mmhub_v2_0.c | ||
528 | index b39bea6f54e9..096bb883c29d 100644 | ||
529 | --- a/drivers/gpu/drm/amd/amdgpu/mmhub_v2_0.c | ||
530 | +++ b/drivers/gpu/drm/amd/amdgpu/mmhub_v2_0.c | ||
531 | @@ -341,6 +341,8 @@ void mmhub_v2_0_init(struct amdgpu_device *adev) | ||
532 | hub->ctx0_ptb_addr_hi32 = | ||
533 | SOC15_REG_OFFSET(MMHUB, 0, | ||
534 | mmMMVM_CONTEXT0_PAGE_TABLE_BASE_ADDR_HI32); | ||
535 | + hub->vm_inv_eng0_sem = | ||
536 | + SOC15_REG_OFFSET(MMHUB, 0, mmMMVM_INVALIDATE_ENG0_SEM); | ||
537 | hub->vm_inv_eng0_req = | ||
538 | SOC15_REG_OFFSET(MMHUB, 0, mmMMVM_INVALIDATE_ENG0_REQ); | ||
539 | hub->vm_inv_eng0_ack = | ||
540 | diff --git a/drivers/gpu/drm/amd/amdgpu/mmhub_v9_4.c b/drivers/gpu/drm/amd/amdgpu/mmhub_v9_4.c | ||
541 | index 9ed178fa241c..fb161c83e409 100644 | ||
542 | --- a/drivers/gpu/drm/amd/amdgpu/mmhub_v9_4.c | ||
543 | +++ b/drivers/gpu/drm/amd/amdgpu/mmhub_v9_4.c | ||
544 | @@ -502,6 +502,10 @@ void mmhub_v9_4_init(struct amdgpu_device *adev) | ||
545 | SOC15_REG_OFFSET(MMHUB, 0, | ||
546 | mmVML2VC0_VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_HI32) + | ||
547 | i * MMHUB_INSTANCE_REGISTER_OFFSET; | ||
548 | + hub[i]->vm_inv_eng0_sem = | ||
549 | + SOC15_REG_OFFSET(MMHUB, 0, | ||
550 | + mmVML2VC0_VM_INVALIDATE_ENG0_SEM) + | ||
551 | + i * MMHUB_INSTANCE_REGISTER_OFFSET; | ||
552 | hub[i]->vm_inv_eng0_req = | ||
553 | SOC15_REG_OFFSET(MMHUB, 0, | ||
554 | mmVML2VC0_VM_INVALIDATE_ENG0_REQ) + | ||
555 | diff --git a/drivers/gpu/drm/amd/amdgpu/soc15.h b/drivers/gpu/drm/amd/amdgpu/soc15.h | ||
556 | index a3dde0c31f57..a1d4ea69a284 100644 | ||
557 | --- a/drivers/gpu/drm/amd/amdgpu/soc15.h | ||
558 | +++ b/drivers/gpu/drm/amd/amdgpu/soc15.h | ||
559 | @@ -28,8 +28,8 @@ | ||
560 | #include "nbio_v7_0.h" | ||
561 | #include "nbio_v7_4.h" | ||
562 | |||
563 | -#define SOC15_FLUSH_GPU_TLB_NUM_WREG 4 | ||
564 | -#define SOC15_FLUSH_GPU_TLB_NUM_REG_WAIT 1 | ||
565 | +#define SOC15_FLUSH_GPU_TLB_NUM_WREG 6 | ||
566 | +#define SOC15_FLUSH_GPU_TLB_NUM_REG_WAIT 3 | ||
567 | |||
568 | extern const struct amd_ip_funcs soc15_common_ip_funcs; | ||
569 | |||
570 | diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_pp_smu.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_pp_smu.c | ||
571 | index f4cfa0caeba8..785322cd4c6c 100644 | ||
572 | --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_pp_smu.c | ||
573 | +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_pp_smu.c | ||
574 | @@ -342,7 +342,8 @@ bool dm_pp_get_clock_levels_by_type( | ||
575 | if (adev->powerplay.pp_funcs && adev->powerplay.pp_funcs->get_clock_by_type) { | ||
576 | if (adev->powerplay.pp_funcs->get_clock_by_type(pp_handle, | ||
577 | dc_to_pp_clock_type(clk_type), &pp_clks)) { | ||
578 | - /* Error in pplib. Provide default values. */ | ||
579 | + /* Error in pplib. Provide default values. */ | ||
580 | + get_default_clock_levels(clk_type, dc_clks); | ||
581 | return true; | ||
582 | } | ||
583 | } else if (adev->smu.funcs && adev->smu.funcs->get_clock_by_type) { | ||
584 | diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c | ||
585 | index 1212da12c414..b3ae1c41fc69 100644 | ||
586 | --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c | ||
587 | +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c | ||
588 | @@ -1103,6 +1103,25 @@ void dcn20_pipe_control_lock( | ||
589 | if (pipe->plane_state != NULL) | ||
590 | flip_immediate = pipe->plane_state->flip_immediate; | ||
591 | |||
592 | + if (flip_immediate && lock) { | ||
593 | + const int TIMEOUT_FOR_FLIP_PENDING = 100000; | ||
594 | + int i; | ||
595 | + | ||
596 | + for (i = 0; i < TIMEOUT_FOR_FLIP_PENDING; ++i) { | ||
597 | + if (!pipe->plane_res.hubp->funcs->hubp_is_flip_pending(pipe->plane_res.hubp)) | ||
598 | + break; | ||
599 | + udelay(1); | ||
600 | + } | ||
601 | + | ||
602 | + if (pipe->bottom_pipe != NULL) { | ||
603 | + for (i = 0; i < TIMEOUT_FOR_FLIP_PENDING; ++i) { | ||
604 | + if (!pipe->bottom_pipe->plane_res.hubp->funcs->hubp_is_flip_pending(pipe->bottom_pipe->plane_res.hubp)) | ||
605 | + break; | ||
606 | + udelay(1); | ||
607 | + } | ||
608 | + } | ||
609 | + } | ||
610 | + | ||
611 | /* In flip immediate and pipe splitting case, we need to use GSL | ||
612 | * for synchronization. Only do setup on locking and on flip type change. | ||
613 | */ | ||
614 | diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c b/drivers/gpu/drm/drm_dp_mst_topology.c | ||
615 | index 82add736e17d..86c17896b532 100644 | ||
616 | --- a/drivers/gpu/drm/drm_dp_mst_topology.c | ||
617 | +++ b/drivers/gpu/drm/drm_dp_mst_topology.c | ||
618 | @@ -2465,9 +2465,11 @@ int drm_dp_update_payload_part1(struct drm_dp_mst_topology_mgr *mgr) | ||
619 | drm_dp_mst_topology_put_port(port); | ||
620 | } | ||
621 | |||
622 | - for (i = 0; i < mgr->max_payloads; i++) { | ||
623 | - if (mgr->payloads[i].payload_state != DP_PAYLOAD_DELETE_LOCAL) | ||
624 | + for (i = 0; i < mgr->max_payloads; /* do nothing */) { | ||
625 | + if (mgr->payloads[i].payload_state != DP_PAYLOAD_DELETE_LOCAL) { | ||
626 | + i++; | ||
627 | continue; | ||
628 | + } | ||
629 | |||
630 | DRM_DEBUG_KMS("removing payload %d\n", i); | ||
631 | for (j = i; j < mgr->max_payloads - 1; j++) { | ||
632 | diff --git a/drivers/gpu/drm/i915/display/intel_fbc.c b/drivers/gpu/drm/i915/display/intel_fbc.c | ||
633 | index 16ed44bfd734..07a038f21619 100644 | ||
634 | --- a/drivers/gpu/drm/i915/display/intel_fbc.c | ||
635 | +++ b/drivers/gpu/drm/i915/display/intel_fbc.c | ||
636 | @@ -1284,7 +1284,7 @@ static int intel_sanitize_fbc_option(struct drm_i915_private *dev_priv) | ||
637 | return 0; | ||
638 | |||
639 | /* https://bugs.freedesktop.org/show_bug.cgi?id=108085 */ | ||
640 | - if (IS_GEMINILAKE(dev_priv)) | ||
641 | + if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv)) | ||
642 | return 0; | ||
643 | |||
644 | if (IS_BROADWELL(dev_priv) || INTEL_GEN(dev_priv) >= 9) | ||
645 | diff --git a/drivers/gpu/drm/i915/gvt/cmd_parser.c b/drivers/gpu/drm/i915/gvt/cmd_parser.c | ||
646 | index e753b1e706e2..fc29a3705354 100644 | ||
647 | --- a/drivers/gpu/drm/i915/gvt/cmd_parser.c | ||
648 | +++ b/drivers/gpu/drm/i915/gvt/cmd_parser.c | ||
649 | @@ -1597,9 +1597,9 @@ static int cmd_handler_mi_op_2f(struct parser_exec_state *s) | ||
650 | if (!(cmd_val(s, 0) & (1 << 22))) | ||
651 | return ret; | ||
652 | |||
653 | - /* check if QWORD */ | ||
654 | - if (DWORD_FIELD(0, 20, 19) == 1) | ||
655 | - valid_len += 8; | ||
656 | + /* check inline data */ | ||
657 | + if (cmd_val(s, 0) & BIT(18)) | ||
658 | + valid_len = CMD_LEN(9); | ||
659 | ret = gvt_check_valid_cmd_length(cmd_length(s), | ||
660 | valid_len); | ||
661 | if (ret) | ||
662 | diff --git a/drivers/gpu/drm/meson/meson_venc_cvbs.c b/drivers/gpu/drm/meson/meson_venc_cvbs.c | ||
663 | index 9ab27aecfcf3..1bd6b6d15ffb 100644 | ||
664 | --- a/drivers/gpu/drm/meson/meson_venc_cvbs.c | ||
665 | +++ b/drivers/gpu/drm/meson/meson_venc_cvbs.c | ||
666 | @@ -64,6 +64,25 @@ struct meson_cvbs_mode meson_cvbs_modes[MESON_CVBS_MODES_COUNT] = { | ||
667 | }, | ||
668 | }; | ||
669 | |||
670 | +static const struct meson_cvbs_mode * | ||
671 | +meson_cvbs_get_mode(const struct drm_display_mode *req_mode) | ||
672 | +{ | ||
673 | + int i; | ||
674 | + | ||
675 | + for (i = 0; i < MESON_CVBS_MODES_COUNT; ++i) { | ||
676 | + struct meson_cvbs_mode *meson_mode = &meson_cvbs_modes[i]; | ||
677 | + | ||
678 | + if (drm_mode_match(req_mode, &meson_mode->mode, | ||
679 | + DRM_MODE_MATCH_TIMINGS | | ||
680 | + DRM_MODE_MATCH_CLOCK | | ||
681 | + DRM_MODE_MATCH_FLAGS | | ||
682 | + DRM_MODE_MATCH_3D_FLAGS)) | ||
683 | + return meson_mode; | ||
684 | + } | ||
685 | + | ||
686 | + return NULL; | ||
687 | +} | ||
688 | + | ||
689 | /* Connector */ | ||
690 | |||
691 | static void meson_cvbs_connector_destroy(struct drm_connector *connector) | ||
692 | @@ -136,14 +155,8 @@ static int meson_venc_cvbs_encoder_atomic_check(struct drm_encoder *encoder, | ||
693 | struct drm_crtc_state *crtc_state, | ||
694 | struct drm_connector_state *conn_state) | ||
695 | { | ||
696 | - int i; | ||
697 | - | ||
698 | - for (i = 0; i < MESON_CVBS_MODES_COUNT; ++i) { | ||
699 | - struct meson_cvbs_mode *meson_mode = &meson_cvbs_modes[i]; | ||
700 | - | ||
701 | - if (drm_mode_equal(&crtc_state->mode, &meson_mode->mode)) | ||
702 | - return 0; | ||
703 | - } | ||
704 | + if (meson_cvbs_get_mode(&crtc_state->mode)) | ||
705 | + return 0; | ||
706 | |||
707 | return -EINVAL; | ||
708 | } | ||
709 | @@ -191,24 +204,17 @@ static void meson_venc_cvbs_encoder_mode_set(struct drm_encoder *encoder, | ||
710 | struct drm_display_mode *mode, | ||
711 | struct drm_display_mode *adjusted_mode) | ||
712 | { | ||
713 | + const struct meson_cvbs_mode *meson_mode = meson_cvbs_get_mode(mode); | ||
714 | struct meson_venc_cvbs *meson_venc_cvbs = | ||
715 | encoder_to_meson_venc_cvbs(encoder); | ||
716 | struct meson_drm *priv = meson_venc_cvbs->priv; | ||
717 | - int i; | ||
718 | |||
719 | - for (i = 0; i < MESON_CVBS_MODES_COUNT; ++i) { | ||
720 | - struct meson_cvbs_mode *meson_mode = &meson_cvbs_modes[i]; | ||
721 | + if (meson_mode) { | ||
722 | + meson_venci_cvbs_mode_set(priv, meson_mode->enci); | ||
723 | |||
724 | - if (drm_mode_equal(mode, &meson_mode->mode)) { | ||
725 | - meson_venci_cvbs_mode_set(priv, | ||
726 | - meson_mode->enci); | ||
727 | - | ||
728 | - /* Setup 27MHz vclk2 for ENCI and VDAC */ | ||
729 | - meson_vclk_setup(priv, MESON_VCLK_TARGET_CVBS, | ||
730 | - MESON_VCLK_CVBS, MESON_VCLK_CVBS, | ||
731 | - MESON_VCLK_CVBS, true); | ||
732 | - break; | ||
733 | - } | ||
734 | + /* Setup 27MHz vclk2 for ENCI and VDAC */ | ||
735 | + meson_vclk_setup(priv, MESON_VCLK_TARGET_CVBS, MESON_VCLK_CVBS, | ||
736 | + MESON_VCLK_CVBS, MESON_VCLK_CVBS, true); | ||
737 | } | ||
738 | } | ||
739 | |||
740 | diff --git a/drivers/gpu/drm/mgag200/mgag200_drv.c b/drivers/gpu/drm/mgag200/mgag200_drv.c | ||
741 | index afd9119b6cf1..c96c4393b124 100644 | ||
742 | --- a/drivers/gpu/drm/mgag200/mgag200_drv.c | ||
743 | +++ b/drivers/gpu/drm/mgag200/mgag200_drv.c | ||
744 | @@ -30,7 +30,8 @@ module_param_named(modeset, mgag200_modeset, int, 0400); | ||
745 | static struct drm_driver driver; | ||
746 | |||
747 | static const struct pci_device_id pciidlist[] = { | ||
748 | - { PCI_VENDOR_ID_MATROX, 0x522, PCI_ANY_ID, PCI_ANY_ID, 0, 0, G200_SE_A }, | ||
749 | + { PCI_VENDOR_ID_MATROX, 0x522, PCI_ANY_ID, PCI_ANY_ID, 0, 0, | ||
750 | + G200_SE_A | MGAG200_FLAG_HW_BUG_NO_STARTADD}, | ||
751 | { PCI_VENDOR_ID_MATROX, 0x524, PCI_ANY_ID, PCI_ANY_ID, 0, 0, G200_SE_B }, | ||
752 | { PCI_VENDOR_ID_MATROX, 0x530, PCI_ANY_ID, PCI_ANY_ID, 0, 0, G200_EV }, | ||
753 | { PCI_VENDOR_ID_MATROX, 0x532, PCI_ANY_ID, PCI_ANY_ID, 0, 0, G200_WB }, | ||
754 | @@ -63,6 +64,35 @@ static const struct file_operations mgag200_driver_fops = { | ||
755 | DRM_VRAM_MM_FILE_OPERATIONS | ||
756 | }; | ||
757 | |||
758 | +static bool mgag200_pin_bo_at_0(const struct mga_device *mdev) | ||
759 | +{ | ||
760 | + return mdev->flags & MGAG200_FLAG_HW_BUG_NO_STARTADD; | ||
761 | +} | ||
762 | + | ||
763 | +int mgag200_driver_dumb_create(struct drm_file *file, | ||
764 | + struct drm_device *dev, | ||
765 | + struct drm_mode_create_dumb *args) | ||
766 | +{ | ||
767 | + struct mga_device *mdev = dev->dev_private; | ||
768 | + unsigned long pg_align; | ||
769 | + | ||
770 | + if (WARN_ONCE(!dev->vram_mm, "VRAM MM not initialized")) | ||
771 | + return -EINVAL; | ||
772 | + | ||
773 | + pg_align = 0ul; | ||
774 | + | ||
775 | + /* | ||
776 | + * Aligning scanout buffers to the size of the video ram forces | ||
777 | + * placement at offset 0. Works around a bug where HW does not | ||
778 | + * respect 'startadd' field. | ||
779 | + */ | ||
780 | + if (mgag200_pin_bo_at_0(mdev)) | ||
781 | + pg_align = PFN_UP(mdev->mc.vram_size); | ||
782 | + | ||
783 | + return drm_gem_vram_fill_create_dumb(file, dev, &dev->vram_mm->bdev, | ||
784 | + pg_align, false, args); | ||
785 | +} | ||
786 | + | ||
787 | static struct drm_driver driver = { | ||
788 | .driver_features = DRIVER_GEM | DRIVER_MODESET, | ||
789 | .load = mgag200_driver_load, | ||
790 | @@ -74,7 +104,9 @@ static struct drm_driver driver = { | ||
791 | .major = DRIVER_MAJOR, | ||
792 | .minor = DRIVER_MINOR, | ||
793 | .patchlevel = DRIVER_PATCHLEVEL, | ||
794 | - DRM_GEM_VRAM_DRIVER | ||
795 | + .dumb_create = mgag200_driver_dumb_create, | ||
796 | + .dumb_map_offset = drm_gem_vram_driver_dumb_mmap_offset, | ||
797 | + .gem_prime_mmap = drm_gem_prime_mmap, | ||
798 | }; | ||
799 | |||
800 | static struct pci_driver mgag200_pci_driver = { | ||
801 | diff --git a/drivers/gpu/drm/mgag200/mgag200_drv.h b/drivers/gpu/drm/mgag200/mgag200_drv.h | ||
802 | index 1c93f8dc08c7..7cc1a242df5f 100644 | ||
803 | --- a/drivers/gpu/drm/mgag200/mgag200_drv.h | ||
804 | +++ b/drivers/gpu/drm/mgag200/mgag200_drv.h | ||
805 | @@ -159,6 +159,12 @@ enum mga_type { | ||
806 | G200_EW3, | ||
807 | }; | ||
808 | |||
809 | +/* HW does not handle 'startadd' field correct. */ | ||
810 | +#define MGAG200_FLAG_HW_BUG_NO_STARTADD (1ul << 8) | ||
811 | + | ||
812 | +#define MGAG200_TYPE_MASK (0x000000ff) | ||
813 | +#define MGAG200_FLAG_MASK (0x00ffff00) | ||
814 | + | ||
815 | #define IS_G200_SE(mdev) (mdev->type == G200_SE_A || mdev->type == G200_SE_B) | ||
816 | |||
817 | struct mga_device { | ||
818 | @@ -188,6 +194,18 @@ struct mga_device { | ||
819 | u32 unique_rev_id; | ||
820 | }; | ||
821 | |||
822 | +static inline enum mga_type | ||
823 | +mgag200_type_from_driver_data(kernel_ulong_t driver_data) | ||
824 | +{ | ||
825 | + return (enum mga_type)(driver_data & MGAG200_TYPE_MASK); | ||
826 | +} | ||
827 | + | ||
828 | +static inline unsigned long | ||
829 | +mgag200_flags_from_driver_data(kernel_ulong_t driver_data) | ||
830 | +{ | ||
831 | + return driver_data & MGAG200_FLAG_MASK; | ||
832 | +} | ||
833 | + | ||
834 | /* mgag200_mode.c */ | ||
835 | int mgag200_modeset_init(struct mga_device *mdev); | ||
836 | void mgag200_modeset_fini(struct mga_device *mdev); | ||
837 | diff --git a/drivers/gpu/drm/mgag200/mgag200_main.c b/drivers/gpu/drm/mgag200/mgag200_main.c | ||
838 | index a9773334dedf..388212b2d63f 100644 | ||
839 | --- a/drivers/gpu/drm/mgag200/mgag200_main.c | ||
840 | +++ b/drivers/gpu/drm/mgag200/mgag200_main.c | ||
841 | @@ -94,7 +94,8 @@ static int mgag200_device_init(struct drm_device *dev, | ||
842 | struct mga_device *mdev = dev->dev_private; | ||
843 | int ret, option; | ||
844 | |||
845 | - mdev->type = flags; | ||
846 | + mdev->flags = mgag200_flags_from_driver_data(flags); | ||
847 | + mdev->type = mgag200_type_from_driver_data(flags); | ||
848 | |||
849 | /* Hardcode the number of CRTCs to 1 */ | ||
850 | mdev->num_crtc = 1; | ||
851 | diff --git a/drivers/gpu/drm/nouveau/dispnv50/atom.h b/drivers/gpu/drm/nouveau/dispnv50/atom.h | ||
852 | index 43df86c38f58..24f7700768da 100644 | ||
853 | --- a/drivers/gpu/drm/nouveau/dispnv50/atom.h | ||
854 | +++ b/drivers/gpu/drm/nouveau/dispnv50/atom.h | ||
855 | @@ -114,6 +114,7 @@ struct nv50_head_atom { | ||
856 | u8 nhsync:1; | ||
857 | u8 nvsync:1; | ||
858 | u8 depth:4; | ||
859 | + u8 bpc; | ||
860 | } or; | ||
861 | |||
862 | /* Currently only used for MST */ | ||
863 | diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c b/drivers/gpu/drm/nouveau/dispnv50/disp.c | ||
864 | index b46be8a091e9..b5b1a34f896f 100644 | ||
865 | --- a/drivers/gpu/drm/nouveau/dispnv50/disp.c | ||
866 | +++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c | ||
867 | @@ -353,10 +353,20 @@ nv50_outp_atomic_check(struct drm_encoder *encoder, | ||
868 | struct drm_crtc_state *crtc_state, | ||
869 | struct drm_connector_state *conn_state) | ||
870 | { | ||
871 | - struct nouveau_connector *nv_connector = | ||
872 | - nouveau_connector(conn_state->connector); | ||
873 | - return nv50_outp_atomic_check_view(encoder, crtc_state, conn_state, | ||
874 | - nv_connector->native_mode); | ||
875 | + struct drm_connector *connector = conn_state->connector; | ||
876 | + struct nouveau_connector *nv_connector = nouveau_connector(connector); | ||
877 | + struct nv50_head_atom *asyh = nv50_head_atom(crtc_state); | ||
878 | + int ret; | ||
879 | + | ||
880 | + ret = nv50_outp_atomic_check_view(encoder, crtc_state, conn_state, | ||
881 | + nv_connector->native_mode); | ||
882 | + if (ret) | ||
883 | + return ret; | ||
884 | + | ||
885 | + if (crtc_state->mode_changed || crtc_state->connectors_changed) | ||
886 | + asyh->or.bpc = connector->display_info.bpc; | ||
887 | + | ||
888 | + return 0; | ||
889 | } | ||
890 | |||
891 | /****************************************************************************** | ||
892 | @@ -770,32 +780,54 @@ nv50_msto_atomic_check(struct drm_encoder *encoder, | ||
893 | struct nv50_mstm *mstm = mstc->mstm; | ||
894 | struct nv50_head_atom *asyh = nv50_head_atom(crtc_state); | ||
895 | int slots; | ||
896 | + int ret; | ||
897 | + | ||
898 | + ret = nv50_outp_atomic_check_view(encoder, crtc_state, conn_state, | ||
899 | + mstc->native); | ||
900 | + if (ret) | ||
901 | + return ret; | ||
902 | + | ||
903 | + if (!crtc_state->mode_changed && !crtc_state->connectors_changed) | ||
904 | + return 0; | ||
905 | + | ||
906 | + /* | ||
907 | + * When restoring duplicated states, we need to make sure that the bw | ||
908 | + * remains the same and avoid recalculating it, as the connector's bpc | ||
909 | + * may have changed after the state was duplicated | ||
910 | + */ | ||
911 | + if (!state->duplicated) { | ||
912 | + const int clock = crtc_state->adjusted_mode.clock; | ||
913 | |||
914 | - if (crtc_state->mode_changed || crtc_state->connectors_changed) { | ||
915 | /* | ||
916 | - * When restoring duplicated states, we need to make sure that | ||
917 | - * the bw remains the same and avoid recalculating it, as the | ||
918 | - * connector's bpc may have changed after the state was | ||
919 | - * duplicated | ||
920 | + * XXX: Since we don't use HDR in userspace quite yet, limit | ||
921 | + * the bpc to 8 to save bandwidth on the topology. In the | ||
922 | + * future, we'll want to properly fix this by dynamically | ||
923 | + * selecting the highest possible bpc that would fit in the | ||
924 | + * topology | ||
925 | */ | ||
926 | - if (!state->duplicated) { | ||
927 | - const int bpp = connector->display_info.bpc * 3; | ||
928 | - const int clock = crtc_state->adjusted_mode.clock; | ||
929 | + asyh->or.bpc = min(connector->display_info.bpc, 8U); | ||
930 | + asyh->dp.pbn = drm_dp_calc_pbn_mode(clock, asyh->or.bpc * 3); | ||
931 | + } | ||
932 | |||
933 | - asyh->dp.pbn = drm_dp_calc_pbn_mode(clock, bpp); | ||
934 | - } | ||
935 | + slots = drm_dp_atomic_find_vcpi_slots(state, &mstm->mgr, mstc->port, | ||
936 | + asyh->dp.pbn); | ||
937 | + if (slots < 0) | ||
938 | + return slots; | ||
939 | |||
940 | - slots = drm_dp_atomic_find_vcpi_slots(state, &mstm->mgr, | ||
941 | - mstc->port, | ||
942 | - asyh->dp.pbn); | ||
943 | - if (slots < 0) | ||
944 | - return slots; | ||
945 | + asyh->dp.tu = slots; | ||
946 | |||
947 | - asyh->dp.tu = slots; | ||
948 | - } | ||
949 | + return 0; | ||
950 | +} | ||
951 | |||
952 | - return nv50_outp_atomic_check_view(encoder, crtc_state, conn_state, | ||
953 | - mstc->native); | ||
954 | +static u8 | ||
955 | +nv50_dp_bpc_to_depth(unsigned int bpc) | ||
956 | +{ | ||
957 | + switch (bpc) { | ||
958 | + case 6: return 0x2; | ||
959 | + case 8: return 0x5; | ||
960 | + case 10: /* fall-through */ | ||
961 | + default: return 0x6; | ||
962 | + } | ||
963 | } | ||
964 | |||
965 | static void | ||
966 | @@ -808,7 +840,7 @@ nv50_msto_enable(struct drm_encoder *encoder) | ||
967 | struct nv50_mstm *mstm = NULL; | ||
968 | struct drm_connector *connector; | ||
969 | struct drm_connector_list_iter conn_iter; | ||
970 | - u8 proto, depth; | ||
971 | + u8 proto; | ||
972 | bool r; | ||
973 | |||
974 | drm_connector_list_iter_begin(encoder->dev, &conn_iter); | ||
975 | @@ -837,14 +869,8 @@ nv50_msto_enable(struct drm_encoder *encoder) | ||
976 | else | ||
977 | proto = 0x9; | ||
978 | |||
979 | - switch (mstc->connector.display_info.bpc) { | ||
980 | - case 6: depth = 0x2; break; | ||
981 | - case 8: depth = 0x5; break; | ||
982 | - case 10: | ||
983 | - default: depth = 0x6; break; | ||
984 | - } | ||
985 | - | ||
986 | - mstm->outp->update(mstm->outp, head->base.index, armh, proto, depth); | ||
987 | + mstm->outp->update(mstm->outp, head->base.index, armh, proto, | ||
988 | + nv50_dp_bpc_to_depth(armh->or.bpc)); | ||
989 | |||
990 | msto->head = head; | ||
991 | msto->mstc = mstc; | ||
992 | @@ -1498,20 +1524,14 @@ nv50_sor_enable(struct drm_encoder *encoder) | ||
993 | lvds.lvds.script |= 0x0200; | ||
994 | } | ||
995 | |||
996 | - if (nv_connector->base.display_info.bpc == 8) | ||
997 | + if (asyh->or.bpc == 8) | ||
998 | lvds.lvds.script |= 0x0200; | ||
999 | } | ||
1000 | |||
1001 | nvif_mthd(&disp->disp->object, 0, &lvds, sizeof(lvds)); | ||
1002 | break; | ||
1003 | case DCB_OUTPUT_DP: | ||
1004 | - if (nv_connector->base.display_info.bpc == 6) | ||
1005 | - depth = 0x2; | ||
1006 | - else | ||
1007 | - if (nv_connector->base.display_info.bpc == 8) | ||
1008 | - depth = 0x5; | ||
1009 | - else | ||
1010 | - depth = 0x6; | ||
1011 | + depth = nv50_dp_bpc_to_depth(asyh->or.bpc); | ||
1012 | |||
1013 | if (nv_encoder->link & 1) | ||
1014 | proto = 0x8; | ||
1015 | @@ -1662,7 +1682,7 @@ nv50_pior_enable(struct drm_encoder *encoder) | ||
1016 | nv50_outp_acquire(nv_encoder); | ||
1017 | |||
1018 | nv_connector = nouveau_encoder_connector_get(nv_encoder); | ||
1019 | - switch (nv_connector->base.display_info.bpc) { | ||
1020 | + switch (asyh->or.bpc) { | ||
1021 | case 10: asyh->or.depth = 0x6; break; | ||
1022 | case 8: asyh->or.depth = 0x5; break; | ||
1023 | case 6: asyh->or.depth = 0x2; break; | ||
1024 | diff --git a/drivers/gpu/drm/nouveau/dispnv50/head.c b/drivers/gpu/drm/nouveau/dispnv50/head.c | ||
1025 | index 71c23bf1fe25..c9692df2b76c 100644 | ||
1026 | --- a/drivers/gpu/drm/nouveau/dispnv50/head.c | ||
1027 | +++ b/drivers/gpu/drm/nouveau/dispnv50/head.c | ||
1028 | @@ -81,18 +81,17 @@ nv50_head_atomic_check_dither(struct nv50_head_atom *armh, | ||
1029 | struct nv50_head_atom *asyh, | ||
1030 | struct nouveau_conn_atom *asyc) | ||
1031 | { | ||
1032 | - struct drm_connector *connector = asyc->state.connector; | ||
1033 | u32 mode = 0x00; | ||
1034 | |||
1035 | if (asyc->dither.mode == DITHERING_MODE_AUTO) { | ||
1036 | - if (asyh->base.depth > connector->display_info.bpc * 3) | ||
1037 | + if (asyh->base.depth > asyh->or.bpc * 3) | ||
1038 | mode = DITHERING_MODE_DYNAMIC2X2; | ||
1039 | } else { | ||
1040 | mode = asyc->dither.mode; | ||
1041 | } | ||
1042 | |||
1043 | if (asyc->dither.depth == DITHERING_DEPTH_AUTO) { | ||
1044 | - if (connector->display_info.bpc >= 8) | ||
1045 | + if (asyh->or.bpc >= 8) | ||
1046 | mode |= DITHERING_DEPTH_8BPC; | ||
1047 | } else { | ||
1048 | mode |= asyc->dither.depth; | ||
1049 | diff --git a/drivers/gpu/drm/panfrost/panfrost_drv.c b/drivers/gpu/drm/panfrost/panfrost_drv.c | ||
1050 | index bdf91b75328e..1c67ac434e10 100644 | ||
1051 | --- a/drivers/gpu/drm/panfrost/panfrost_drv.c | ||
1052 | +++ b/drivers/gpu/drm/panfrost/panfrost_drv.c | ||
1053 | @@ -303,14 +303,17 @@ static int panfrost_ioctl_mmap_bo(struct drm_device *dev, void *data, | ||
1054 | } | ||
1055 | |||
1056 | /* Don't allow mmapping of heap objects as pages are not pinned. */ | ||
1057 | - if (to_panfrost_bo(gem_obj)->is_heap) | ||
1058 | - return -EINVAL; | ||
1059 | + if (to_panfrost_bo(gem_obj)->is_heap) { | ||
1060 | + ret = -EINVAL; | ||
1061 | + goto out; | ||
1062 | + } | ||
1063 | |||
1064 | ret = drm_gem_create_mmap_offset(gem_obj); | ||
1065 | if (ret == 0) | ||
1066 | args->offset = drm_vma_node_offset_addr(&gem_obj->vma_node); | ||
1067 | - drm_gem_object_put_unlocked(gem_obj); | ||
1068 | |||
1069 | +out: | ||
1070 | + drm_gem_object_put_unlocked(gem_obj); | ||
1071 | return ret; | ||
1072 | } | ||
1073 | |||
1074 | @@ -347,20 +350,19 @@ static int panfrost_ioctl_madvise(struct drm_device *dev, void *data, | ||
1075 | return -ENOENT; | ||
1076 | } | ||
1077 | |||
1078 | + mutex_lock(&pfdev->shrinker_lock); | ||
1079 | args->retained = drm_gem_shmem_madvise(gem_obj, args->madv); | ||
1080 | |||
1081 | if (args->retained) { | ||
1082 | struct panfrost_gem_object *bo = to_panfrost_bo(gem_obj); | ||
1083 | |||
1084 | - mutex_lock(&pfdev->shrinker_lock); | ||
1085 | - | ||
1086 | if (args->madv == PANFROST_MADV_DONTNEED) | ||
1087 | - list_add_tail(&bo->base.madv_list, &pfdev->shrinker_list); | ||
1088 | + list_add_tail(&bo->base.madv_list, | ||
1089 | + &pfdev->shrinker_list); | ||
1090 | else if (args->madv == PANFROST_MADV_WILLNEED) | ||
1091 | list_del_init(&bo->base.madv_list); | ||
1092 | - | ||
1093 | - mutex_unlock(&pfdev->shrinker_lock); | ||
1094 | } | ||
1095 | + mutex_unlock(&pfdev->shrinker_lock); | ||
1096 | |||
1097 | drm_gem_object_put_unlocked(gem_obj); | ||
1098 | return 0; | ||
1099 | diff --git a/drivers/gpu/drm/panfrost/panfrost_gem.c b/drivers/gpu/drm/panfrost/panfrost_gem.c | ||
1100 | index bc3ff22e5e85..92a95210a899 100644 | ||
1101 | --- a/drivers/gpu/drm/panfrost/panfrost_gem.c | ||
1102 | +++ b/drivers/gpu/drm/panfrost/panfrost_gem.c | ||
1103 | @@ -19,6 +19,16 @@ static void panfrost_gem_free_object(struct drm_gem_object *obj) | ||
1104 | struct panfrost_gem_object *bo = to_panfrost_bo(obj); | ||
1105 | struct panfrost_device *pfdev = obj->dev->dev_private; | ||
1106 | |||
1107 | + /* | ||
1108 | + * Make sure the BO is no longer inserted in the shrinker list before | ||
1109 | + * taking care of the destruction itself. If we don't do that we have a | ||
1110 | + * race condition between this function and what's done in | ||
1111 | + * panfrost_gem_shrinker_scan(). | ||
1112 | + */ | ||
1113 | + mutex_lock(&pfdev->shrinker_lock); | ||
1114 | + list_del_init(&bo->base.madv_list); | ||
1115 | + mutex_unlock(&pfdev->shrinker_lock); | ||
1116 | + | ||
1117 | if (bo->sgts) { | ||
1118 | int i; | ||
1119 | int n_sgt = bo->base.base.size / SZ_2M; | ||
1120 | @@ -33,11 +43,6 @@ static void panfrost_gem_free_object(struct drm_gem_object *obj) | ||
1121 | kfree(bo->sgts); | ||
1122 | } | ||
1123 | |||
1124 | - mutex_lock(&pfdev->shrinker_lock); | ||
1125 | - if (!list_empty(&bo->base.madv_list)) | ||
1126 | - list_del(&bo->base.madv_list); | ||
1127 | - mutex_unlock(&pfdev->shrinker_lock); | ||
1128 | - | ||
1129 | drm_gem_shmem_free_object(obj); | ||
1130 | } | ||
1131 | |||
1132 | diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c | ||
1133 | index 7089dfc8c2a9..110fb38004b1 100644 | ||
1134 | --- a/drivers/gpu/drm/radeon/r100.c | ||
1135 | +++ b/drivers/gpu/drm/radeon/r100.c | ||
1136 | @@ -1826,8 +1826,8 @@ static int r100_packet0_check(struct radeon_cs_parser *p, | ||
1137 | track->textures[i].use_pitch = 1; | ||
1138 | } else { | ||
1139 | track->textures[i].use_pitch = 0; | ||
1140 | - track->textures[i].width = 1 << ((idx_value >> RADEON_TXFORMAT_WIDTH_SHIFT) & RADEON_TXFORMAT_WIDTH_MASK); | ||
1141 | - track->textures[i].height = 1 << ((idx_value >> RADEON_TXFORMAT_HEIGHT_SHIFT) & RADEON_TXFORMAT_HEIGHT_MASK); | ||
1142 | + track->textures[i].width = 1 << ((idx_value & RADEON_TXFORMAT_WIDTH_MASK) >> RADEON_TXFORMAT_WIDTH_SHIFT); | ||
1143 | + track->textures[i].height = 1 << ((idx_value & RADEON_TXFORMAT_HEIGHT_MASK) >> RADEON_TXFORMAT_HEIGHT_SHIFT); | ||
1144 | } | ||
1145 | if (idx_value & RADEON_TXFORMAT_CUBIC_MAP_ENABLE) | ||
1146 | track->textures[i].tex_coord_type = 2; | ||
1147 | diff --git a/drivers/gpu/drm/radeon/r200.c b/drivers/gpu/drm/radeon/r200.c | ||
1148 | index 840401413c58..f5f2ffea5ab2 100644 | ||
1149 | --- a/drivers/gpu/drm/radeon/r200.c | ||
1150 | +++ b/drivers/gpu/drm/radeon/r200.c | ||
1151 | @@ -476,8 +476,8 @@ int r200_packet0_check(struct radeon_cs_parser *p, | ||
1152 | track->textures[i].use_pitch = 1; | ||
1153 | } else { | ||
1154 | track->textures[i].use_pitch = 0; | ||
1155 | - track->textures[i].width = 1 << ((idx_value >> RADEON_TXFORMAT_WIDTH_SHIFT) & RADEON_TXFORMAT_WIDTH_MASK); | ||
1156 | - track->textures[i].height = 1 << ((idx_value >> RADEON_TXFORMAT_HEIGHT_SHIFT) & RADEON_TXFORMAT_HEIGHT_MASK); | ||
1157 | + track->textures[i].width = 1 << ((idx_value & RADEON_TXFORMAT_WIDTH_MASK) >> RADEON_TXFORMAT_WIDTH_SHIFT); | ||
1158 | + track->textures[i].height = 1 << ((idx_value & RADEON_TXFORMAT_HEIGHT_MASK) >> RADEON_TXFORMAT_HEIGHT_SHIFT); | ||
1159 | } | ||
1160 | if (idx_value & R200_TXFORMAT_LOOKUP_DISABLE) | ||
1161 | track->textures[i].lookup_disable = true; | ||
1162 | diff --git a/drivers/md/dm-clone-metadata.c b/drivers/md/dm-clone-metadata.c | ||
1163 | index 6bc8c1d1c351..54e4fdd607e1 100644 | ||
1164 | --- a/drivers/md/dm-clone-metadata.c | ||
1165 | +++ b/drivers/md/dm-clone-metadata.c | ||
1166 | @@ -67,23 +67,34 @@ struct superblock_disk { | ||
1167 | * To save constantly doing look ups on disk we keep an in core copy of the | ||
1168 | * on-disk bitmap, the region_map. | ||
1169 | * | ||
1170 | - * To further reduce metadata I/O overhead we use a second bitmap, the dmap | ||
1171 | - * (dirty bitmap), which tracks the dirty words, i.e. longs, of the region_map. | ||
1172 | + * In order to track which regions are hydrated during a metadata transaction, | ||
1173 | + * we use a second set of bitmaps, the dmap (dirty bitmap), which includes two | ||
1174 | + * bitmaps, namely dirty_regions and dirty_words. The dirty_regions bitmap | ||
1175 | + * tracks the regions that got hydrated during the current metadata | ||
1176 | + * transaction. The dirty_words bitmap tracks the dirty words, i.e. longs, of | ||
1177 | + * the dirty_regions bitmap. | ||
1178 | + * | ||
1179 | + * This allows us to precisely track the regions that were hydrated during the | ||
1180 | + * current metadata transaction and update the metadata accordingly, when we | ||
1181 | + * commit the current transaction. This is important because dm-clone should | ||
1182 | + * only commit the metadata of regions that were properly flushed to the | ||
1183 | + * destination device beforehand. Otherwise, in case of a crash, we could end | ||
1184 | + * up with a corrupted dm-clone device. | ||
1185 | * | ||
1186 | * When a region finishes hydrating dm-clone calls | ||
1187 | * dm_clone_set_region_hydrated(), or for discard requests | ||
1188 | * dm_clone_cond_set_range(), which sets the corresponding bits in region_map | ||
1189 | * and dmap. | ||
1190 | * | ||
1191 | - * During a metadata commit we scan the dmap for dirty region_map words (longs) | ||
1192 | - * and update accordingly the on-disk metadata. Thus, we don't have to flush to | ||
1193 | - * disk the whole region_map. We can just flush the dirty region_map words. | ||
1194 | + * During a metadata commit we scan dmap->dirty_words and dmap->dirty_regions | ||
1195 | + * and update the on-disk metadata accordingly. Thus, we don't have to flush to | ||
1196 | + * disk the whole region_map. We can just flush the dirty region_map bits. | ||
1197 | * | ||
1198 | - * We use a dirty bitmap, which is smaller than the original region_map, to | ||
1199 | - * reduce the amount of memory accesses during a metadata commit. As dm-bitset | ||
1200 | - * accesses the on-disk bitmap in 64-bit word granularity, there is no | ||
1201 | - * significant benefit in tracking the dirty region_map bits with a smaller | ||
1202 | - * granularity. | ||
1203 | + * We use the helper dmap->dirty_words bitmap, which is smaller than the | ||
1204 | + * original region_map, to reduce the amount of memory accesses during a | ||
1205 | + * metadata commit. Moreover, as dm-bitset also accesses the on-disk bitmap in | ||
1206 | + * 64-bit word granularity, the dirty_words bitmap helps us avoid useless disk | ||
1207 | + * accesses. | ||
1208 | * | ||
1209 | * We could update directly the on-disk bitmap, when dm-clone calls either | ||
1210 | * dm_clone_set_region_hydrated() or dm_clone_cond_set_range(), buts this | ||
1211 | @@ -92,12 +103,13 @@ struct superblock_disk { | ||
1212 | * e.g., in a hooked overwrite bio's completion routine, and further reduce the | ||
1213 | * I/O completion latency. | ||
1214 | * | ||
1215 | - * We maintain two dirty bitmaps. During a metadata commit we atomically swap | ||
1216 | - * the currently used dmap with the unused one. This allows the metadata update | ||
1217 | - * functions to run concurrently with an ongoing commit. | ||
1218 | + * We maintain two dirty bitmap sets. During a metadata commit we atomically | ||
1219 | + * swap the currently used dmap with the unused one. This allows the metadata | ||
1220 | + * update functions to run concurrently with an ongoing commit. | ||
1221 | */ | ||
1222 | struct dirty_map { | ||
1223 | unsigned long *dirty_words; | ||
1224 | + unsigned long *dirty_regions; | ||
1225 | unsigned int changed; | ||
1226 | }; | ||
1227 | |||
1228 | @@ -115,6 +127,9 @@ struct dm_clone_metadata { | ||
1229 | struct dirty_map dmap[2]; | ||
1230 | struct dirty_map *current_dmap; | ||
1231 | |||
1232 | + /* Protected by lock */ | ||
1233 | + struct dirty_map *committing_dmap; | ||
1234 | + | ||
1235 | /* | ||
1236 | * In core copy of the on-disk bitmap to save constantly doing look ups | ||
1237 | * on disk. | ||
1238 | @@ -461,34 +476,53 @@ static size_t bitmap_size(unsigned long nr_bits) | ||
1239 | return BITS_TO_LONGS(nr_bits) * sizeof(long); | ||
1240 | } | ||
1241 | |||
1242 | -static int dirty_map_init(struct dm_clone_metadata *cmd) | ||
1243 | +static int __dirty_map_init(struct dirty_map *dmap, unsigned long nr_words, | ||
1244 | + unsigned long nr_regions) | ||
1245 | { | ||
1246 | - cmd->dmap[0].changed = 0; | ||
1247 | - cmd->dmap[0].dirty_words = kvzalloc(bitmap_size(cmd->nr_words), GFP_KERNEL); | ||
1248 | + dmap->changed = 0; | ||
1249 | |||
1250 | - if (!cmd->dmap[0].dirty_words) { | ||
1251 | - DMERR("Failed to allocate dirty bitmap"); | ||
1252 | + dmap->dirty_words = kvzalloc(bitmap_size(nr_words), GFP_KERNEL); | ||
1253 | + if (!dmap->dirty_words) | ||
1254 | + return -ENOMEM; | ||
1255 | + | ||
1256 | + dmap->dirty_regions = kvzalloc(bitmap_size(nr_regions), GFP_KERNEL); | ||
1257 | + if (!dmap->dirty_regions) { | ||
1258 | + kvfree(dmap->dirty_words); | ||
1259 | return -ENOMEM; | ||
1260 | } | ||
1261 | |||
1262 | - cmd->dmap[1].changed = 0; | ||
1263 | - cmd->dmap[1].dirty_words = kvzalloc(bitmap_size(cmd->nr_words), GFP_KERNEL); | ||
1264 | + return 0; | ||
1265 | +} | ||
1266 | + | ||
1267 | +static void __dirty_map_exit(struct dirty_map *dmap) | ||
1268 | +{ | ||
1269 | + kvfree(dmap->dirty_words); | ||
1270 | + kvfree(dmap->dirty_regions); | ||
1271 | +} | ||
1272 | + | ||
1273 | +static int dirty_map_init(struct dm_clone_metadata *cmd) | ||
1274 | +{ | ||
1275 | + if (__dirty_map_init(&cmd->dmap[0], cmd->nr_words, cmd->nr_regions)) { | ||
1276 | + DMERR("Failed to allocate dirty bitmap"); | ||
1277 | + return -ENOMEM; | ||
1278 | + } | ||
1279 | |||
1280 | - if (!cmd->dmap[1].dirty_words) { | ||
1281 | + if (__dirty_map_init(&cmd->dmap[1], cmd->nr_words, cmd->nr_regions)) { | ||
1282 | DMERR("Failed to allocate dirty bitmap"); | ||
1283 | - kvfree(cmd->dmap[0].dirty_words); | ||
1284 | + __dirty_map_exit(&cmd->dmap[0]); | ||
1285 | return -ENOMEM; | ||
1286 | } | ||
1287 | |||
1288 | cmd->current_dmap = &cmd->dmap[0]; | ||
1289 | + cmd->committing_dmap = NULL; | ||
1290 | |||
1291 | return 0; | ||
1292 | } | ||
1293 | |||
1294 | static void dirty_map_exit(struct dm_clone_metadata *cmd) | ||
1295 | { | ||
1296 | - kvfree(cmd->dmap[0].dirty_words); | ||
1297 | - kvfree(cmd->dmap[1].dirty_words); | ||
1298 | + __dirty_map_exit(&cmd->dmap[0]); | ||
1299 | + __dirty_map_exit(&cmd->dmap[1]); | ||
1300 | } | ||
1301 | |||
1302 | static int __load_bitset_in_core(struct dm_clone_metadata *cmd) | ||
1303 | @@ -633,21 +667,23 @@ unsigned long dm_clone_find_next_unhydrated_region(struct dm_clone_metadata *cmd | ||
1304 | return find_next_zero_bit(cmd->region_map, cmd->nr_regions, start); | ||
1305 | } | ||
1306 | |||
1307 | -static int __update_metadata_word(struct dm_clone_metadata *cmd, unsigned long word) | ||
1308 | +static int __update_metadata_word(struct dm_clone_metadata *cmd, | ||
1309 | + unsigned long *dirty_regions, | ||
1310 | + unsigned long word) | ||
1311 | { | ||
1312 | int r; | ||
1313 | unsigned long index = word * BITS_PER_LONG; | ||
1314 | unsigned long max_index = min(cmd->nr_regions, (word + 1) * BITS_PER_LONG); | ||
1315 | |||
1316 | while (index < max_index) { | ||
1317 | - if (test_bit(index, cmd->region_map)) { | ||
1318 | + if (test_bit(index, dirty_regions)) { | ||
1319 | r = dm_bitset_set_bit(&cmd->bitset_info, cmd->bitset_root, | ||
1320 | index, &cmd->bitset_root); | ||
1321 | - | ||
1322 | if (r) { | ||
1323 | DMERR("dm_bitset_set_bit failed"); | ||
1324 | return r; | ||
1325 | } | ||
1326 | + __clear_bit(index, dirty_regions); | ||
1327 | } | ||
1328 | index++; | ||
1329 | } | ||
1330 | @@ -721,7 +757,7 @@ static int __flush_dmap(struct dm_clone_metadata *cmd, struct dirty_map *dmap) | ||
1331 | if (word == cmd->nr_words) | ||
1332 | break; | ||
1333 | |||
1334 | - r = __update_metadata_word(cmd, word); | ||
1335 | + r = __update_metadata_word(cmd, dmap->dirty_regions, word); | ||
1336 | |||
1337 | if (r) | ||
1338 | return r; | ||
1339 | @@ -743,16 +779,18 @@ static int __flush_dmap(struct dm_clone_metadata *cmd, struct dirty_map *dmap) | ||
1340 | return 0; | ||
1341 | } | ||
1342 | |||
1343 | -int dm_clone_metadata_commit(struct dm_clone_metadata *cmd) | ||
1344 | +int dm_clone_metadata_pre_commit(struct dm_clone_metadata *cmd) | ||
1345 | { | ||
1346 | - int r = -EPERM; | ||
1347 | + int r = 0; | ||
1348 | unsigned long flags; | ||
1349 | struct dirty_map *dmap, *next_dmap; | ||
1350 | |||
1351 | down_write(&cmd->lock); | ||
1352 | |||
1353 | - if (cmd->fail_io || dm_bm_is_read_only(cmd->bm)) | ||
1354 | + if (cmd->fail_io || dm_bm_is_read_only(cmd->bm)) { | ||
1355 | + r = -EPERM; | ||
1356 | goto out; | ||
1357 | + } | ||
1358 | |||
1359 | /* Get current dirty bitmap */ | ||
1360 | dmap = cmd->current_dmap; | ||
1361 | @@ -764,7 +802,7 @@ int dm_clone_metadata_commit(struct dm_clone_metadata *cmd) | ||
1362 | * The last commit failed, so we don't have a clean dirty-bitmap to | ||
1363 | * use. | ||
1364 | */ | ||
1365 | - if (WARN_ON(next_dmap->changed)) { | ||
1366 | + if (WARN_ON(next_dmap->changed || cmd->committing_dmap)) { | ||
1367 | r = -EINVAL; | ||
1368 | goto out; | ||
1369 | } | ||
1370 | @@ -774,11 +812,33 @@ int dm_clone_metadata_commit(struct dm_clone_metadata *cmd) | ||
1371 | cmd->current_dmap = next_dmap; | ||
1372 | spin_unlock_irqrestore(&cmd->bitmap_lock, flags); | ||
1373 | |||
1374 | - /* | ||
1375 | - * No one is accessing the old dirty bitmap anymore, so we can flush | ||
1376 | - * it. | ||
1377 | - */ | ||
1378 | - r = __flush_dmap(cmd, dmap); | ||
1379 | + /* Set old dirty bitmap as currently committing */ | ||
1380 | + cmd->committing_dmap = dmap; | ||
1381 | +out: | ||
1382 | + up_write(&cmd->lock); | ||
1383 | + | ||
1384 | + return r; | ||
1385 | +} | ||
1386 | + | ||
1387 | +int dm_clone_metadata_commit(struct dm_clone_metadata *cmd) | ||
1388 | +{ | ||
1389 | + int r = -EPERM; | ||
1390 | + | ||
1391 | + down_write(&cmd->lock); | ||
1392 | + | ||
1393 | + if (cmd->fail_io || dm_bm_is_read_only(cmd->bm)) | ||
1394 | + goto out; | ||
1395 | + | ||
1396 | + if (WARN_ON(!cmd->committing_dmap)) { | ||
1397 | + r = -EINVAL; | ||
1398 | + goto out; | ||
1399 | + } | ||
1400 | + | ||
1401 | + r = __flush_dmap(cmd, cmd->committing_dmap); | ||
1402 | + if (!r) { | ||
1403 | + /* Clear committing dmap */ | ||
1404 | + cmd->committing_dmap = NULL; | ||
1405 | + } | ||
1406 | out: | ||
1407 | up_write(&cmd->lock); | ||
1408 | |||
1409 | @@ -803,6 +863,7 @@ int dm_clone_set_region_hydrated(struct dm_clone_metadata *cmd, unsigned long re | ||
1410 | dmap = cmd->current_dmap; | ||
1411 | |||
1412 | __set_bit(word, dmap->dirty_words); | ||
1413 | + __set_bit(region_nr, dmap->dirty_regions); | ||
1414 | __set_bit(region_nr, cmd->region_map); | ||
1415 | dmap->changed = 1; | ||
1416 | |||
1417 | @@ -831,6 +892,7 @@ int dm_clone_cond_set_range(struct dm_clone_metadata *cmd, unsigned long start, | ||
1418 | if (!test_bit(region_nr, cmd->region_map)) { | ||
1419 | word = region_nr / BITS_PER_LONG; | ||
1420 | __set_bit(word, dmap->dirty_words); | ||
1421 | + __set_bit(region_nr, dmap->dirty_regions); | ||
1422 | __set_bit(region_nr, cmd->region_map); | ||
1423 | dmap->changed = 1; | ||
1424 | } | ||
1425 | diff --git a/drivers/md/dm-clone-metadata.h b/drivers/md/dm-clone-metadata.h | ||
1426 | index 434bff08508b..c7848c49aef8 100644 | ||
1427 | --- a/drivers/md/dm-clone-metadata.h | ||
1428 | +++ b/drivers/md/dm-clone-metadata.h | ||
1429 | @@ -73,7 +73,23 @@ void dm_clone_metadata_close(struct dm_clone_metadata *cmd); | ||
1430 | |||
1431 | /* | ||
1432 | * Commit dm-clone metadata to disk. | ||
1433 | + * | ||
1434 | + * We use a two phase commit: | ||
1435 | + * | ||
1436 | + * 1. dm_clone_metadata_pre_commit(): Prepare the current transaction for | ||
1437 | + * committing. After this is called, all subsequent metadata updates, done | ||
1438 | + * through either dm_clone_set_region_hydrated() or | ||
1439 | + * dm_clone_cond_set_range(), will be part of the **next** transaction. | ||
1440 | + * | ||
1441 | + * 2. dm_clone_metadata_commit(): Actually commit the current transaction to | ||
1442 | + * disk and start a new transaction. | ||
1443 | + * | ||
1444 | + * This allows dm-clone to flush the destination device after step (1) to | ||
1445 | + * ensure that all freshly hydrated regions, for which we are updating the | ||
1446 | + * metadata, are properly written to non-volatile storage and won't be lost in | ||
1447 | + * case of a crash. | ||
1448 | */ | ||
1449 | +int dm_clone_metadata_pre_commit(struct dm_clone_metadata *cmd); | ||
1450 | int dm_clone_metadata_commit(struct dm_clone_metadata *cmd); | ||
1451 | |||
1452 | /* | ||
1453 | @@ -110,6 +126,7 @@ int dm_clone_metadata_abort(struct dm_clone_metadata *cmd); | ||
1454 | * Switches metadata to a read only mode. Once read-only mode has been entered | ||
1455 | * the following functions will return -EPERM: | ||
1456 | * | ||
1457 | + * dm_clone_metadata_pre_commit() | ||
1458 | * dm_clone_metadata_commit() | ||
1459 | * dm_clone_set_region_hydrated() | ||
1460 | * dm_clone_cond_set_range() | ||
1461 | diff --git a/drivers/md/dm-clone-target.c b/drivers/md/dm-clone-target.c | ||
1462 | index 4ca8f1977222..e6e5d24a79f5 100644 | ||
1463 | --- a/drivers/md/dm-clone-target.c | ||
1464 | +++ b/drivers/md/dm-clone-target.c | ||
1465 | @@ -86,6 +86,12 @@ struct clone { | ||
1466 | |||
1467 | struct dm_clone_metadata *cmd; | ||
1468 | |||
1469 | + /* | ||
1470 | + * bio used to flush the destination device, before committing the | ||
1471 | + * metadata. | ||
1472 | + */ | ||
1473 | + struct bio flush_bio; | ||
1474 | + | ||
1475 | /* Region hydration hash table */ | ||
1476 | struct hash_table_bucket *ht; | ||
1477 | |||
1478 | @@ -1106,10 +1112,13 @@ static bool need_commit_due_to_time(struct clone *clone) | ||
1479 | /* | ||
1480 | * A non-zero return indicates read-only or fail mode. | ||
1481 | */ | ||
1482 | -static int commit_metadata(struct clone *clone) | ||
1483 | +static int commit_metadata(struct clone *clone, bool *dest_dev_flushed) | ||
1484 | { | ||
1485 | int r = 0; | ||
1486 | |||
1487 | + if (dest_dev_flushed) | ||
1488 | + *dest_dev_flushed = false; | ||
1489 | + | ||
1490 | mutex_lock(&clone->commit_lock); | ||
1491 | |||
1492 | if (!dm_clone_changed_this_transaction(clone->cmd)) | ||
1493 | @@ -1120,8 +1129,26 @@ static int commit_metadata(struct clone *clone) | ||
1494 | goto out; | ||
1495 | } | ||
1496 | |||
1497 | - r = dm_clone_metadata_commit(clone->cmd); | ||
1498 | + r = dm_clone_metadata_pre_commit(clone->cmd); | ||
1499 | + if (unlikely(r)) { | ||
1500 | + __metadata_operation_failed(clone, "dm_clone_metadata_pre_commit", r); | ||
1501 | + goto out; | ||
1502 | + } | ||
1503 | |||
1504 | + bio_reset(&clone->flush_bio); | ||
1505 | + bio_set_dev(&clone->flush_bio, clone->dest_dev->bdev); | ||
1506 | + clone->flush_bio.bi_opf = REQ_OP_WRITE | REQ_PREFLUSH; | ||
1507 | + | ||
1508 | + r = submit_bio_wait(&clone->flush_bio); | ||
1509 | + if (unlikely(r)) { | ||
1510 | + __metadata_operation_failed(clone, "flush destination device", r); | ||
1511 | + goto out; | ||
1512 | + } | ||
1513 | + | ||
1514 | + if (dest_dev_flushed) | ||
1515 | + *dest_dev_flushed = true; | ||
1516 | + | ||
1517 | + r = dm_clone_metadata_commit(clone->cmd); | ||
1518 | if (unlikely(r)) { | ||
1519 | __metadata_operation_failed(clone, "dm_clone_metadata_commit", r); | ||
1520 | goto out; | ||
1521 | @@ -1194,6 +1221,7 @@ static void process_deferred_flush_bios(struct clone *clone) | ||
1522 | { | ||
1523 | struct bio *bio; | ||
1524 | unsigned long flags; | ||
1525 | + bool dest_dev_flushed; | ||
1526 | struct bio_list bios = BIO_EMPTY_LIST; | ||
1527 | struct bio_list bio_completions = BIO_EMPTY_LIST; | ||
1528 | |||
1529 | @@ -1213,7 +1241,7 @@ static void process_deferred_flush_bios(struct clone *clone) | ||
1530 | !(dm_clone_changed_this_transaction(clone->cmd) && need_commit_due_to_time(clone))) | ||
1531 | return; | ||
1532 | |||
1533 | - if (commit_metadata(clone)) { | ||
1534 | + if (commit_metadata(clone, &dest_dev_flushed)) { | ||
1535 | bio_list_merge(&bios, &bio_completions); | ||
1536 | |||
1537 | while ((bio = bio_list_pop(&bios))) | ||
1538 | @@ -1227,8 +1255,17 @@ static void process_deferred_flush_bios(struct clone *clone) | ||
1539 | while ((bio = bio_list_pop(&bio_completions))) | ||
1540 | bio_endio(bio); | ||
1541 | |||
1542 | - while ((bio = bio_list_pop(&bios))) | ||
1543 | - generic_make_request(bio); | ||
1544 | + while ((bio = bio_list_pop(&bios))) { | ||
1545 | + if ((bio->bi_opf & REQ_PREFLUSH) && dest_dev_flushed) { | ||
1546 | + /* We just flushed the destination device as part of | ||
1547 | + * the metadata commit, so there is no reason to send | ||
1548 | + * another flush. | ||
1549 | + */ | ||
1550 | + bio_endio(bio); | ||
1551 | + } else { | ||
1552 | + generic_make_request(bio); | ||
1553 | + } | ||
1554 | + } | ||
1555 | } | ||
1556 | |||
1557 | static void do_worker(struct work_struct *work) | ||
1558 | @@ -1400,7 +1437,7 @@ static void clone_status(struct dm_target *ti, status_type_t type, | ||
1559 | |||
1560 | /* Commit to ensure statistics aren't out-of-date */ | ||
1561 | if (!(status_flags & DM_STATUS_NOFLUSH_FLAG) && !dm_suspended(ti)) | ||
1562 | - (void) commit_metadata(clone); | ||
1563 | + (void) commit_metadata(clone, NULL); | ||
1564 | |||
1565 | r = dm_clone_get_free_metadata_block_count(clone->cmd, &nr_free_metadata_blocks); | ||
1566 | |||
1567 | @@ -1834,6 +1871,7 @@ static int clone_ctr(struct dm_target *ti, unsigned int argc, char **argv) | ||
1568 | bio_list_init(&clone->deferred_flush_completions); | ||
1569 | clone->hydration_offset = 0; | ||
1570 | atomic_set(&clone->hydrations_in_flight, 0); | ||
1571 | + bio_init(&clone->flush_bio, NULL, 0); | ||
1572 | |||
1573 | clone->wq = alloc_workqueue("dm-" DM_MSG_PREFIX, WQ_MEM_RECLAIM, 0); | ||
1574 | if (!clone->wq) { | ||
1575 | @@ -1907,6 +1945,7 @@ static void clone_dtr(struct dm_target *ti) | ||
1576 | struct clone *clone = ti->private; | ||
1577 | |||
1578 | mutex_destroy(&clone->commit_lock); | ||
1579 | + bio_uninit(&clone->flush_bio); | ||
1580 | |||
1581 | for (i = 0; i < clone->nr_ctr_args; i++) | ||
1582 | kfree(clone->ctr_args[i]); | ||
1583 | @@ -1961,7 +2000,7 @@ static void clone_postsuspend(struct dm_target *ti) | ||
1584 | wait_event(clone->hydration_stopped, !atomic_read(&clone->hydrations_in_flight)); | ||
1585 | flush_workqueue(clone->wq); | ||
1586 | |||
1587 | - (void) commit_metadata(clone); | ||
1588 | + (void) commit_metadata(clone, NULL); | ||
1589 | } | ||
1590 | |||
1591 | static void clone_resume(struct dm_target *ti) | ||
1592 | diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c | ||
1593 | index dbcc1e41cd57..e0c32793c248 100644 | ||
1594 | --- a/drivers/md/dm-mpath.c | ||
1595 | +++ b/drivers/md/dm-mpath.c | ||
1596 | @@ -599,45 +599,10 @@ static struct pgpath *__map_bio(struct multipath *m, struct bio *bio) | ||
1597 | return pgpath; | ||
1598 | } | ||
1599 | |||
1600 | -static struct pgpath *__map_bio_fast(struct multipath *m, struct bio *bio) | ||
1601 | -{ | ||
1602 | - struct pgpath *pgpath; | ||
1603 | - unsigned long flags; | ||
1604 | - | ||
1605 | - /* Do we need to select a new pgpath? */ | ||
1606 | - /* | ||
1607 | - * FIXME: currently only switching path if no path (due to failure, etc) | ||
1608 | - * - which negates the point of using a path selector | ||
1609 | - */ | ||
1610 | - pgpath = READ_ONCE(m->current_pgpath); | ||
1611 | - if (!pgpath) | ||
1612 | - pgpath = choose_pgpath(m, bio->bi_iter.bi_size); | ||
1613 | - | ||
1614 | - if (!pgpath) { | ||
1615 | - if (test_bit(MPATHF_QUEUE_IF_NO_PATH, &m->flags)) { | ||
1616 | - /* Queue for the daemon to resubmit */ | ||
1617 | - spin_lock_irqsave(&m->lock, flags); | ||
1618 | - bio_list_add(&m->queued_bios, bio); | ||
1619 | - spin_unlock_irqrestore(&m->lock, flags); | ||
1620 | - queue_work(kmultipathd, &m->process_queued_bios); | ||
1621 | - | ||
1622 | - return ERR_PTR(-EAGAIN); | ||
1623 | - } | ||
1624 | - return NULL; | ||
1625 | - } | ||
1626 | - | ||
1627 | - return pgpath; | ||
1628 | -} | ||
1629 | - | ||
1630 | static int __multipath_map_bio(struct multipath *m, struct bio *bio, | ||
1631 | struct dm_mpath_io *mpio) | ||
1632 | { | ||
1633 | - struct pgpath *pgpath; | ||
1634 | - | ||
1635 | - if (!m->hw_handler_name) | ||
1636 | - pgpath = __map_bio_fast(m, bio); | ||
1637 | - else | ||
1638 | - pgpath = __map_bio(m, bio); | ||
1639 | + struct pgpath *pgpath = __map_bio(m, bio); | ||
1640 | |||
1641 | if (IS_ERR(pgpath)) | ||
1642 | return DM_MAPIO_SUBMITTED; | ||
1643 | diff --git a/drivers/md/dm-thin-metadata.c b/drivers/md/dm-thin-metadata.c | ||
1644 | index 4c68a7b93d5e..b88d6d701f5b 100644 | ||
1645 | --- a/drivers/md/dm-thin-metadata.c | ||
1646 | +++ b/drivers/md/dm-thin-metadata.c | ||
1647 | @@ -188,6 +188,15 @@ struct dm_pool_metadata { | ||
1648 | unsigned long flags; | ||
1649 | sector_t data_block_size; | ||
1650 | |||
1651 | + /* | ||
1652 | + * Pre-commit callback. | ||
1653 | + * | ||
1654 | + * This allows the thin provisioning target to run a callback before | ||
1655 | + * the metadata are committed. | ||
1656 | + */ | ||
1657 | + dm_pool_pre_commit_fn pre_commit_fn; | ||
1658 | + void *pre_commit_context; | ||
1659 | + | ||
1660 | /* | ||
1661 | * We reserve a section of the metadata for commit overhead. | ||
1662 | * All reported space does *not* include this. | ||
1663 | @@ -826,6 +835,14 @@ static int __commit_transaction(struct dm_pool_metadata *pmd) | ||
1664 | if (unlikely(!pmd->in_service)) | ||
1665 | return 0; | ||
1666 | |||
1667 | + if (pmd->pre_commit_fn) { | ||
1668 | + r = pmd->pre_commit_fn(pmd->pre_commit_context); | ||
1669 | + if (r < 0) { | ||
1670 | + DMERR("pre-commit callback failed"); | ||
1671 | + return r; | ||
1672 | + } | ||
1673 | + } | ||
1674 | + | ||
1675 | r = __write_changed_details(pmd); | ||
1676 | if (r < 0) | ||
1677 | return r; | ||
1678 | @@ -892,6 +909,8 @@ struct dm_pool_metadata *dm_pool_metadata_open(struct block_device *bdev, | ||
1679 | pmd->in_service = false; | ||
1680 | pmd->bdev = bdev; | ||
1681 | pmd->data_block_size = data_block_size; | ||
1682 | + pmd->pre_commit_fn = NULL; | ||
1683 | + pmd->pre_commit_context = NULL; | ||
1684 | |||
1685 | r = __create_persistent_data_objects(pmd, format_device); | ||
1686 | if (r) { | ||
1687 | @@ -2044,6 +2063,16 @@ int dm_pool_register_metadata_threshold(struct dm_pool_metadata *pmd, | ||
1688 | return r; | ||
1689 | } | ||
1690 | |||
1691 | +void dm_pool_register_pre_commit_callback(struct dm_pool_metadata *pmd, | ||
1692 | + dm_pool_pre_commit_fn fn, | ||
1693 | + void *context) | ||
1694 | +{ | ||
1695 | + pmd_write_lock_in_core(pmd); | ||
1696 | + pmd->pre_commit_fn = fn; | ||
1697 | + pmd->pre_commit_context = context; | ||
1698 | + pmd_write_unlock(pmd); | ||
1699 | +} | ||
1700 | + | ||
1701 | int dm_pool_metadata_set_needs_check(struct dm_pool_metadata *pmd) | ||
1702 | { | ||
1703 | int r = -EINVAL; | ||
1704 | diff --git a/drivers/md/dm-thin-metadata.h b/drivers/md/dm-thin-metadata.h | ||
1705 | index f6be0d733c20..7ef56bd2a7e3 100644 | ||
1706 | --- a/drivers/md/dm-thin-metadata.h | ||
1707 | +++ b/drivers/md/dm-thin-metadata.h | ||
1708 | @@ -230,6 +230,13 @@ bool dm_pool_metadata_needs_check(struct dm_pool_metadata *pmd); | ||
1709 | */ | ||
1710 | void dm_pool_issue_prefetches(struct dm_pool_metadata *pmd); | ||
1711 | |||
1712 | +/* Pre-commit callback */ | ||
1713 | +typedef int (*dm_pool_pre_commit_fn)(void *context); | ||
1714 | + | ||
1715 | +void dm_pool_register_pre_commit_callback(struct dm_pool_metadata *pmd, | ||
1716 | + dm_pool_pre_commit_fn fn, | ||
1717 | + void *context); | ||
1718 | + | ||
1719 | /*----------------------------------------------------------------*/ | ||
1720 | |||
1721 | #endif | ||
1722 | diff --git a/drivers/md/dm-thin.c b/drivers/md/dm-thin.c | ||
1723 | index fcd887703f95..1696bfd23ad1 100644 | ||
1724 | --- a/drivers/md/dm-thin.c | ||
1725 | +++ b/drivers/md/dm-thin.c | ||
1726 | @@ -328,6 +328,7 @@ struct pool_c { | ||
1727 | dm_block_t low_water_blocks; | ||
1728 | struct pool_features requested_pf; /* Features requested during table load */ | ||
1729 | struct pool_features adjusted_pf; /* Features used after adjusting for constituent devices */ | ||
1730 | + struct bio flush_bio; | ||
1731 | }; | ||
1732 | |||
1733 | /* | ||
1734 | @@ -2392,8 +2393,16 @@ static void process_deferred_bios(struct pool *pool) | ||
1735 | while ((bio = bio_list_pop(&bio_completions))) | ||
1736 | bio_endio(bio); | ||
1737 | |||
1738 | - while ((bio = bio_list_pop(&bios))) | ||
1739 | - generic_make_request(bio); | ||
1740 | + while ((bio = bio_list_pop(&bios))) { | ||
1741 | + /* | ||
1742 | + * The data device was flushed as part of metadata commit, | ||
1743 | + * so complete redundant flushes immediately. | ||
1744 | + */ | ||
1745 | + if (bio->bi_opf & REQ_PREFLUSH) | ||
1746 | + bio_endio(bio); | ||
1747 | + else | ||
1748 | + generic_make_request(bio); | ||
1749 | + } | ||
1750 | } | ||
1751 | |||
1752 | static void do_worker(struct work_struct *ws) | ||
1753 | @@ -3127,6 +3136,7 @@ static void pool_dtr(struct dm_target *ti) | ||
1754 | __pool_dec(pt->pool); | ||
1755 | dm_put_device(ti, pt->metadata_dev); | ||
1756 | dm_put_device(ti, pt->data_dev); | ||
1757 | + bio_uninit(&pt->flush_bio); | ||
1758 | kfree(pt); | ||
1759 | |||
1760 | mutex_unlock(&dm_thin_pool_table.mutex); | ||
1761 | @@ -3192,6 +3202,29 @@ static void metadata_low_callback(void *context) | ||
1762 | dm_table_event(pool->ti->table); | ||
1763 | } | ||
1764 | |||
1765 | +/* | ||
1766 | + * We need to flush the data device **before** committing the metadata. | ||
1767 | + * | ||
1768 | + * This ensures that the data blocks of any newly inserted mappings are | ||
1769 | + * properly written to non-volatile storage and won't be lost in case of a | ||
1770 | + * crash. | ||
1771 | + * | ||
1772 | + * Failure to do so can result in data corruption in the case of internal or | ||
1773 | + * external snapshots and in the case of newly provisioned blocks, when block | ||
1774 | + * zeroing is enabled. | ||
1775 | + */ | ||
1776 | +static int metadata_pre_commit_callback(void *context) | ||
1777 | +{ | ||
1778 | + struct pool_c *pt = context; | ||
1779 | + struct bio *flush_bio = &pt->flush_bio; | ||
1780 | + | ||
1781 | + bio_reset(flush_bio); | ||
1782 | + bio_set_dev(flush_bio, pt->data_dev->bdev); | ||
1783 | + flush_bio->bi_opf = REQ_OP_WRITE | REQ_PREFLUSH; | ||
1784 | + | ||
1785 | + return submit_bio_wait(flush_bio); | ||
1786 | +} | ||
1787 | + | ||
1788 | static sector_t get_dev_size(struct block_device *bdev) | ||
1789 | { | ||
1790 | return i_size_read(bdev->bd_inode) >> SECTOR_SHIFT; | ||
1791 | @@ -3360,6 +3393,7 @@ static int pool_ctr(struct dm_target *ti, unsigned argc, char **argv) | ||
1792 | pt->data_dev = data_dev; | ||
1793 | pt->low_water_blocks = low_water_blocks; | ||
1794 | pt->adjusted_pf = pt->requested_pf = pf; | ||
1795 | + bio_init(&pt->flush_bio, NULL, 0); | ||
1796 | ti->num_flush_bios = 1; | ||
1797 | |||
1798 | /* | ||
1799 | @@ -3386,6 +3420,10 @@ static int pool_ctr(struct dm_target *ti, unsigned argc, char **argv) | ||
1800 | if (r) | ||
1801 | goto out_flags_changed; | ||
1802 | |||
1803 | + dm_pool_register_pre_commit_callback(pt->pool->pmd, | ||
1804 | + metadata_pre_commit_callback, | ||
1805 | + pt); | ||
1806 | + | ||
1807 | pt->callbacks.congested_fn = pool_is_congested; | ||
1808 | dm_table_add_target_callbacks(ti->table, &pt->callbacks); | ||
1809 | |||
1810 | diff --git a/drivers/md/persistent-data/dm-btree-remove.c b/drivers/md/persistent-data/dm-btree-remove.c | ||
1811 | index 21ea537bd55e..eff04fa23dfa 100644 | ||
1812 | --- a/drivers/md/persistent-data/dm-btree-remove.c | ||
1813 | +++ b/drivers/md/persistent-data/dm-btree-remove.c | ||
1814 | @@ -203,7 +203,13 @@ static void __rebalance2(struct dm_btree_info *info, struct btree_node *parent, | ||
1815 | struct btree_node *right = r->n; | ||
1816 | uint32_t nr_left = le32_to_cpu(left->header.nr_entries); | ||
1817 | uint32_t nr_right = le32_to_cpu(right->header.nr_entries); | ||
1818 | - unsigned threshold = 2 * merge_threshold(left) + 1; | ||
1819 | + /* | ||
1820 | + * Ensure the number of entries in each child will be greater | ||
1821 | + * than or equal to (max_entries / 3 + 1), so no matter which | ||
1822 | + * child is used for removal, the number will still be not | ||
1823 | + * less than (max_entries / 3). | ||
1824 | + */ | ||
1825 | + unsigned int threshold = 2 * (merge_threshold(left) + 1); | ||
1826 | |||
1827 | if (nr_left + nr_right < threshold) { | ||
1828 | /* | ||
1829 | diff --git a/drivers/mmc/core/block.c b/drivers/mmc/core/block.c | ||
1830 | index 2c71a434c915..95b41c0891d0 100644 | ||
1831 | --- a/drivers/mmc/core/block.c | ||
1832 | +++ b/drivers/mmc/core/block.c | ||
1833 | @@ -408,38 +408,6 @@ static int mmc_blk_ioctl_copy_to_user(struct mmc_ioc_cmd __user *ic_ptr, | ||
1834 | return 0; | ||
1835 | } | ||
1836 | |||
1837 | -static int ioctl_rpmb_card_status_poll(struct mmc_card *card, u32 *status, | ||
1838 | - u32 retries_max) | ||
1839 | -{ | ||
1840 | - int err; | ||
1841 | - u32 retry_count = 0; | ||
1842 | - | ||
1843 | - if (!status || !retries_max) | ||
1844 | - return -EINVAL; | ||
1845 | - | ||
1846 | - do { | ||
1847 | - err = __mmc_send_status(card, status, 5); | ||
1848 | - if (err) | ||
1849 | - break; | ||
1850 | - | ||
1851 | - if (!R1_STATUS(*status) && | ||
1852 | - (R1_CURRENT_STATE(*status) != R1_STATE_PRG)) | ||
1853 | - break; /* RPMB programming operation complete */ | ||
1854 | - | ||
1855 | - /* | ||
1856 | - * Rechedule to give the MMC device a chance to continue | ||
1857 | - * processing the previous command without being polled too | ||
1858 | - * frequently. | ||
1859 | - */ | ||
1860 | - usleep_range(1000, 5000); | ||
1861 | - } while (++retry_count < retries_max); | ||
1862 | - | ||
1863 | - if (retry_count == retries_max) | ||
1864 | - err = -EPERM; | ||
1865 | - | ||
1866 | - return err; | ||
1867 | -} | ||
1868 | - | ||
1869 | static int ioctl_do_sanitize(struct mmc_card *card) | ||
1870 | { | ||
1871 | int err; | ||
1872 | @@ -468,6 +436,58 @@ out: | ||
1873 | return err; | ||
1874 | } | ||
1875 | |||
1876 | +static inline bool mmc_blk_in_tran_state(u32 status) | ||
1877 | +{ | ||
1878 | + /* | ||
1879 | + * Some cards mishandle the status bits, so make sure to check both the | ||
1880 | + * busy indication and the card state. | ||
1881 | + */ | ||
1882 | + return status & R1_READY_FOR_DATA && | ||
1883 | + (R1_CURRENT_STATE(status) == R1_STATE_TRAN); | ||
1884 | +} | ||
1885 | + | ||
1886 | +static int card_busy_detect(struct mmc_card *card, unsigned int timeout_ms, | ||
1887 | + u32 *resp_errs) | ||
1888 | +{ | ||
1889 | + unsigned long timeout = jiffies + msecs_to_jiffies(timeout_ms); | ||
1890 | + int err = 0; | ||
1891 | + u32 status; | ||
1892 | + | ||
1893 | + do { | ||
1894 | + bool done = time_after(jiffies, timeout); | ||
1895 | + | ||
1896 | + err = __mmc_send_status(card, &status, 5); | ||
1897 | + if (err) { | ||
1898 | + dev_err(mmc_dev(card->host), | ||
1899 | + "error %d requesting status\n", err); | ||
1900 | + return err; | ||
1901 | + } | ||
1902 | + | ||
1903 | + /* Accumulate any response error bits seen */ | ||
1904 | + if (resp_errs) | ||
1905 | + *resp_errs |= status; | ||
1906 | + | ||
1907 | + /* | ||
1908 | + * Timeout if the device never becomes ready for data and never | ||
1909 | + * leaves the program state. | ||
1910 | + */ | ||
1911 | + if (done) { | ||
1912 | + dev_err(mmc_dev(card->host), | ||
1913 | + "Card stuck in wrong state! %s status: %#x\n", | ||
1914 | + __func__, status); | ||
1915 | + return -ETIMEDOUT; | ||
1916 | + } | ||
1917 | + | ||
1918 | + /* | ||
1919 | + * Some cards mishandle the status bits, | ||
1920 | + * so make sure to check both the busy | ||
1921 | + * indication and the card state. | ||
1922 | + */ | ||
1923 | + } while (!mmc_blk_in_tran_state(status)); | ||
1924 | + | ||
1925 | + return err; | ||
1926 | +} | ||
1927 | + | ||
1928 | static int __mmc_blk_ioctl_cmd(struct mmc_card *card, struct mmc_blk_data *md, | ||
1929 | struct mmc_blk_ioc_data *idata) | ||
1930 | { | ||
1931 | @@ -477,7 +497,6 @@ static int __mmc_blk_ioctl_cmd(struct mmc_card *card, struct mmc_blk_data *md, | ||
1932 | struct scatterlist sg; | ||
1933 | int err; | ||
1934 | unsigned int target_part; | ||
1935 | - u32 status = 0; | ||
1936 | |||
1937 | if (!card || !md || !idata) | ||
1938 | return -EINVAL; | ||
1939 | @@ -611,16 +630,12 @@ static int __mmc_blk_ioctl_cmd(struct mmc_card *card, struct mmc_blk_data *md, | ||
1940 | |||
1941 | memcpy(&(idata->ic.response), cmd.resp, sizeof(cmd.resp)); | ||
1942 | |||
1943 | - if (idata->rpmb) { | ||
1944 | + if (idata->rpmb || (cmd.flags & MMC_RSP_R1B)) { | ||
1945 | /* | ||
1946 | - * Ensure RPMB command has completed by polling CMD13 | ||
1947 | + * Ensure RPMB/R1B command has completed by polling CMD13 | ||
1948 | * "Send Status". | ||
1949 | */ | ||
1950 | - err = ioctl_rpmb_card_status_poll(card, &status, 5); | ||
1951 | - if (err) | ||
1952 | - dev_err(mmc_dev(card->host), | ||
1953 | - "%s: Card Status=0x%08X, error %d\n", | ||
1954 | - __func__, status, err); | ||
1955 | + err = card_busy_detect(card, MMC_BLK_TIMEOUT_MS, NULL); | ||
1956 | } | ||
1957 | |||
1958 | return err; | ||
1959 | @@ -970,58 +985,6 @@ static unsigned int mmc_blk_data_timeout_ms(struct mmc_host *host, | ||
1960 | return ms; | ||
1961 | } | ||
1962 | |||
1963 | -static inline bool mmc_blk_in_tran_state(u32 status) | ||
1964 | -{ | ||
1965 | - /* | ||
1966 | - * Some cards mishandle the status bits, so make sure to check both the | ||
1967 | - * busy indication and the card state. | ||
1968 | - */ | ||
1969 | - return status & R1_READY_FOR_DATA && | ||
1970 | - (R1_CURRENT_STATE(status) == R1_STATE_TRAN); | ||
1971 | -} | ||
1972 | - | ||
1973 | -static int card_busy_detect(struct mmc_card *card, unsigned int timeout_ms, | ||
1974 | - struct request *req, u32 *resp_errs) | ||
1975 | -{ | ||
1976 | - unsigned long timeout = jiffies + msecs_to_jiffies(timeout_ms); | ||
1977 | - int err = 0; | ||
1978 | - u32 status; | ||
1979 | - | ||
1980 | - do { | ||
1981 | - bool done = time_after(jiffies, timeout); | ||
1982 | - | ||
1983 | - err = __mmc_send_status(card, &status, 5); | ||
1984 | - if (err) { | ||
1985 | - pr_err("%s: error %d requesting status\n", | ||
1986 | - req->rq_disk->disk_name, err); | ||
1987 | - return err; | ||
1988 | - } | ||
1989 | - | ||
1990 | - /* Accumulate any response error bits seen */ | ||
1991 | - if (resp_errs) | ||
1992 | - *resp_errs |= status; | ||
1993 | - | ||
1994 | - /* | ||
1995 | - * Timeout if the device never becomes ready for data and never | ||
1996 | - * leaves the program state. | ||
1997 | - */ | ||
1998 | - if (done) { | ||
1999 | - pr_err("%s: Card stuck in wrong state! %s %s status: %#x\n", | ||
2000 | - mmc_hostname(card->host), | ||
2001 | - req->rq_disk->disk_name, __func__, status); | ||
2002 | - return -ETIMEDOUT; | ||
2003 | - } | ||
2004 | - | ||
2005 | - /* | ||
2006 | - * Some cards mishandle the status bits, | ||
2007 | - * so make sure to check both the busy | ||
2008 | - * indication and the card state. | ||
2009 | - */ | ||
2010 | - } while (!mmc_blk_in_tran_state(status)); | ||
2011 | - | ||
2012 | - return err; | ||
2013 | -} | ||
2014 | - | ||
2015 | static int mmc_blk_reset(struct mmc_blk_data *md, struct mmc_host *host, | ||
2016 | int type) | ||
2017 | { | ||
2018 | @@ -1671,7 +1634,7 @@ static int mmc_blk_fix_state(struct mmc_card *card, struct request *req) | ||
2019 | |||
2020 | mmc_blk_send_stop(card, timeout); | ||
2021 | |||
2022 | - err = card_busy_detect(card, timeout, req, NULL); | ||
2023 | + err = card_busy_detect(card, timeout, NULL); | ||
2024 | |||
2025 | mmc_retune_release(card->host); | ||
2026 | |||
2027 | @@ -1895,7 +1858,7 @@ static int mmc_blk_card_busy(struct mmc_card *card, struct request *req) | ||
2028 | if (mmc_host_is_spi(card->host) || rq_data_dir(req) == READ) | ||
2029 | return 0; | ||
2030 | |||
2031 | - err = card_busy_detect(card, MMC_BLK_TIMEOUT_MS, req, &status); | ||
2032 | + err = card_busy_detect(card, MMC_BLK_TIMEOUT_MS, &status); | ||
2033 | |||
2034 | /* | ||
2035 | * Do not assume data transferred correctly if there are any error bits | ||
2036 | diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c | ||
2037 | index 221127324709..abf8f5eb0a1c 100644 | ||
2038 | --- a/drivers/mmc/core/core.c | ||
2039 | +++ b/drivers/mmc/core/core.c | ||
2040 | @@ -1469,8 +1469,7 @@ void mmc_detach_bus(struct mmc_host *host) | ||
2041 | mmc_bus_put(host); | ||
2042 | } | ||
2043 | |||
2044 | -static void _mmc_detect_change(struct mmc_host *host, unsigned long delay, | ||
2045 | - bool cd_irq) | ||
2046 | +void _mmc_detect_change(struct mmc_host *host, unsigned long delay, bool cd_irq) | ||
2047 | { | ||
2048 | /* | ||
2049 | * If the device is configured as wakeup, we prevent a new sleep for | ||
2050 | @@ -2129,7 +2128,7 @@ int mmc_hw_reset(struct mmc_host *host) | ||
2051 | ret = host->bus_ops->hw_reset(host); | ||
2052 | mmc_bus_put(host); | ||
2053 | |||
2054 | - if (ret) | ||
2055 | + if (ret < 0) | ||
2056 | pr_warn("%s: tried to HW reset card, got error %d\n", | ||
2057 | mmc_hostname(host), ret); | ||
2058 | |||
2059 | @@ -2297,11 +2296,8 @@ void mmc_rescan(struct work_struct *work) | ||
2060 | |||
2061 | mmc_bus_get(host); | ||
2062 | |||
2063 | - /* | ||
2064 | - * if there is a _removable_ card registered, check whether it is | ||
2065 | - * still present | ||
2066 | - */ | ||
2067 | - if (host->bus_ops && !host->bus_dead && mmc_card_is_removable(host)) | ||
2068 | + /* Verify a registered card to be functional, else remove it. */ | ||
2069 | + if (host->bus_ops && !host->bus_dead) | ||
2070 | host->bus_ops->detect(host); | ||
2071 | |||
2072 | host->detect_change = 0; | ||
2073 | diff --git a/drivers/mmc/core/core.h b/drivers/mmc/core/core.h | ||
2074 | index 328c78dbee66..575ac0257af2 100644 | ||
2075 | --- a/drivers/mmc/core/core.h | ||
2076 | +++ b/drivers/mmc/core/core.h | ||
2077 | @@ -70,6 +70,8 @@ void mmc_rescan(struct work_struct *work); | ||
2078 | void mmc_start_host(struct mmc_host *host); | ||
2079 | void mmc_stop_host(struct mmc_host *host); | ||
2080 | |||
2081 | +void _mmc_detect_change(struct mmc_host *host, unsigned long delay, | ||
2082 | + bool cd_irq); | ||
2083 | int _mmc_detect_card_removed(struct mmc_host *host); | ||
2084 | int mmc_detect_card_removed(struct mmc_host *host); | ||
2085 | |||
2086 | diff --git a/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c | ||
2087 | index 26cabd53ddc5..ebb387aa5158 100644 | ||
2088 | --- a/drivers/mmc/core/sdio.c | ||
2089 | +++ b/drivers/mmc/core/sdio.c | ||
2090 | @@ -1048,9 +1048,35 @@ static int mmc_sdio_runtime_resume(struct mmc_host *host) | ||
2091 | return ret; | ||
2092 | } | ||
2093 | |||
2094 | +/* | ||
2095 | + * SDIO HW reset | ||
2096 | + * | ||
2097 | + * Returns 0 if the HW reset was executed synchronously, returns 1 if the HW | ||
2098 | + * reset was asynchronously scheduled, else a negative error code. | ||
2099 | + */ | ||
2100 | static int mmc_sdio_hw_reset(struct mmc_host *host) | ||
2101 | { | ||
2102 | - mmc_power_cycle(host, host->card->ocr); | ||
2103 | + struct mmc_card *card = host->card; | ||
2104 | + | ||
2105 | + /* | ||
2106 | + * In case the card is shared among multiple func drivers, reset the | ||
2107 | + * card through a rescan work. In this way it will be removed and | ||
2108 | + * re-detected, thus all func drivers becomes informed about it. | ||
2109 | + */ | ||
2110 | + if (atomic_read(&card->sdio_funcs_probed) > 1) { | ||
2111 | + if (mmc_card_removed(card)) | ||
2112 | + return 1; | ||
2113 | + host->rescan_entered = 0; | ||
2114 | + mmc_card_set_removed(card); | ||
2115 | + _mmc_detect_change(host, 0, false); | ||
2116 | + return 1; | ||
2117 | + } | ||
2118 | + | ||
2119 | + /* | ||
2120 | + * A single func driver has been probed, then let's skip the heavy | ||
2121 | + * hotplug dance above and execute the reset immediately. | ||
2122 | + */ | ||
2123 | + mmc_power_cycle(host, card->ocr); | ||
2124 | return mmc_sdio_reinit_card(host); | ||
2125 | } | ||
2126 | |||
2127 | diff --git a/drivers/mmc/core/sdio_bus.c b/drivers/mmc/core/sdio_bus.c | ||
2128 | index 2963e6542958..3cc928282af7 100644 | ||
2129 | --- a/drivers/mmc/core/sdio_bus.c | ||
2130 | +++ b/drivers/mmc/core/sdio_bus.c | ||
2131 | @@ -138,6 +138,8 @@ static int sdio_bus_probe(struct device *dev) | ||
2132 | if (ret) | ||
2133 | return ret; | ||
2134 | |||
2135 | + atomic_inc(&func->card->sdio_funcs_probed); | ||
2136 | + | ||
2137 | /* Unbound SDIO functions are always suspended. | ||
2138 | * During probe, the function is set active and the usage count | ||
2139 | * is incremented. If the driver supports runtime PM, | ||
2140 | @@ -153,7 +155,10 @@ static int sdio_bus_probe(struct device *dev) | ||
2141 | /* Set the default block size so the driver is sure it's something | ||
2142 | * sensible. */ | ||
2143 | sdio_claim_host(func); | ||
2144 | - ret = sdio_set_block_size(func, 0); | ||
2145 | + if (mmc_card_removed(func->card)) | ||
2146 | + ret = -ENOMEDIUM; | ||
2147 | + else | ||
2148 | + ret = sdio_set_block_size(func, 0); | ||
2149 | sdio_release_host(func); | ||
2150 | if (ret) | ||
2151 | goto disable_runtimepm; | ||
2152 | @@ -165,6 +170,7 @@ static int sdio_bus_probe(struct device *dev) | ||
2153 | return 0; | ||
2154 | |||
2155 | disable_runtimepm: | ||
2156 | + atomic_dec(&func->card->sdio_funcs_probed); | ||
2157 | if (func->card->host->caps & MMC_CAP_POWER_OFF_CARD) | ||
2158 | pm_runtime_put_noidle(dev); | ||
2159 | dev_pm_domain_detach(dev, false); | ||
2160 | @@ -181,6 +187,7 @@ static int sdio_bus_remove(struct device *dev) | ||
2161 | pm_runtime_get_sync(dev); | ||
2162 | |||
2163 | drv->remove(func); | ||
2164 | + atomic_dec(&func->card->sdio_funcs_probed); | ||
2165 | |||
2166 | if (func->irq_handler) { | ||
2167 | pr_warn("WARNING: driver %s did not remove its interrupt handler!\n", | ||
2168 | diff --git a/drivers/pci/controller/pcie-rcar.c b/drivers/pci/controller/pcie-rcar.c | ||
2169 | index f6a669a9af41..1ad0b56f11b4 100644 | ||
2170 | --- a/drivers/pci/controller/pcie-rcar.c | ||
2171 | +++ b/drivers/pci/controller/pcie-rcar.c | ||
2172 | @@ -93,8 +93,11 @@ | ||
2173 | #define LINK_SPEED_2_5GTS (1 << 16) | ||
2174 | #define LINK_SPEED_5_0GTS (2 << 16) | ||
2175 | #define MACCTLR 0x011058 | ||
2176 | +#define MACCTLR_NFTS_MASK GENMASK(23, 16) /* The name is from SH7786 */ | ||
2177 | #define SPEED_CHANGE BIT(24) | ||
2178 | #define SCRAMBLE_DISABLE BIT(27) | ||
2179 | +#define LTSMDIS BIT(31) | ||
2180 | +#define MACCTLR_INIT_VAL (LTSMDIS | MACCTLR_NFTS_MASK) | ||
2181 | #define PMSR 0x01105c | ||
2182 | #define MACS2R 0x011078 | ||
2183 | #define MACCGSPSETR 0x011084 | ||
2184 | @@ -615,6 +618,8 @@ static int rcar_pcie_hw_init(struct rcar_pcie *pcie) | ||
2185 | if (IS_ENABLED(CONFIG_PCI_MSI)) | ||
2186 | rcar_pci_write_reg(pcie, 0x801f0000, PCIEMSITXR); | ||
2187 | |||
2188 | + rcar_pci_write_reg(pcie, MACCTLR_INIT_VAL, MACCTLR); | ||
2189 | + | ||
2190 | /* Finish initialization - establish a PCI Express link */ | ||
2191 | rcar_pci_write_reg(pcie, CFINIT, PCIETCTLR); | ||
2192 | |||
2193 | @@ -1237,6 +1242,7 @@ static int rcar_pcie_resume_noirq(struct device *dev) | ||
2194 | return 0; | ||
2195 | |||
2196 | /* Re-establish the PCIe link */ | ||
2197 | + rcar_pci_write_reg(pcie, MACCTLR_INIT_VAL, MACCTLR); | ||
2198 | rcar_pci_write_reg(pcie, CFINIT, PCIETCTLR); | ||
2199 | return rcar_pcie_wait_for_dl(pcie); | ||
2200 | } | ||
2201 | diff --git a/drivers/pci/hotplug/pciehp.h b/drivers/pci/hotplug/pciehp.h | ||
2202 | index 654c972b8ea0..882ce82c4699 100644 | ||
2203 | --- a/drivers/pci/hotplug/pciehp.h | ||
2204 | +++ b/drivers/pci/hotplug/pciehp.h | ||
2205 | @@ -72,6 +72,7 @@ extern int pciehp_poll_time; | ||
2206 | * @reset_lock: prevents access to the Data Link Layer Link Active bit in the | ||
2207 | * Link Status register and to the Presence Detect State bit in the Slot | ||
2208 | * Status register during a slot reset which may cause them to flap | ||
2209 | + * @ist_running: flag to keep user request waiting while IRQ thread is running | ||
2210 | * @request_result: result of last user request submitted to the IRQ thread | ||
2211 | * @requester: wait queue to wake up on completion of user request, | ||
2212 | * used for synchronous slot enable/disable request via sysfs | ||
2213 | @@ -101,6 +102,7 @@ struct controller { | ||
2214 | |||
2215 | struct hotplug_slot hotplug_slot; /* hotplug core interface */ | ||
2216 | struct rw_semaphore reset_lock; | ||
2217 | + unsigned int ist_running; | ||
2218 | int request_result; | ||
2219 | wait_queue_head_t requester; | ||
2220 | }; | ||
2221 | diff --git a/drivers/pci/hotplug/pciehp_ctrl.c b/drivers/pci/hotplug/pciehp_ctrl.c | ||
2222 | index 21af7b16d7a4..dd8e4a5fb282 100644 | ||
2223 | --- a/drivers/pci/hotplug/pciehp_ctrl.c | ||
2224 | +++ b/drivers/pci/hotplug/pciehp_ctrl.c | ||
2225 | @@ -375,7 +375,8 @@ int pciehp_sysfs_enable_slot(struct hotplug_slot *hotplug_slot) | ||
2226 | ctrl->request_result = -ENODEV; | ||
2227 | pciehp_request(ctrl, PCI_EXP_SLTSTA_PDC); | ||
2228 | wait_event(ctrl->requester, | ||
2229 | - !atomic_read(&ctrl->pending_events)); | ||
2230 | + !atomic_read(&ctrl->pending_events) && | ||
2231 | + !ctrl->ist_running); | ||
2232 | return ctrl->request_result; | ||
2233 | case POWERON_STATE: | ||
2234 | ctrl_info(ctrl, "Slot(%s): Already in powering on state\n", | ||
2235 | @@ -408,7 +409,8 @@ int pciehp_sysfs_disable_slot(struct hotplug_slot *hotplug_slot) | ||
2236 | mutex_unlock(&ctrl->state_lock); | ||
2237 | pciehp_request(ctrl, DISABLE_SLOT); | ||
2238 | wait_event(ctrl->requester, | ||
2239 | - !atomic_read(&ctrl->pending_events)); | ||
2240 | + !atomic_read(&ctrl->pending_events) && | ||
2241 | + !ctrl->ist_running); | ||
2242 | return ctrl->request_result; | ||
2243 | case POWEROFF_STATE: | ||
2244 | ctrl_info(ctrl, "Slot(%s): Already in powering off state\n", | ||
2245 | diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c | ||
2246 | index 1a522c1c4177..86d97f3112f0 100644 | ||
2247 | --- a/drivers/pci/hotplug/pciehp_hpc.c | ||
2248 | +++ b/drivers/pci/hotplug/pciehp_hpc.c | ||
2249 | @@ -583,6 +583,7 @@ static irqreturn_t pciehp_ist(int irq, void *dev_id) | ||
2250 | irqreturn_t ret; | ||
2251 | u32 events; | ||
2252 | |||
2253 | + ctrl->ist_running = true; | ||
2254 | pci_config_pm_runtime_get(pdev); | ||
2255 | |||
2256 | /* rerun pciehp_isr() if the port was inaccessible on interrupt */ | ||
2257 | @@ -629,6 +630,7 @@ static irqreturn_t pciehp_ist(int irq, void *dev_id) | ||
2258 | up_read(&ctrl->reset_lock); | ||
2259 | |||
2260 | pci_config_pm_runtime_put(pdev); | ||
2261 | + ctrl->ist_running = false; | ||
2262 | wake_up(&ctrl->requester); | ||
2263 | return IRQ_HANDLED; | ||
2264 | } | ||
2265 | diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c | ||
2266 | index 0884bedcfc7a..771041784e64 100644 | ||
2267 | --- a/drivers/pci/msi.c | ||
2268 | +++ b/drivers/pci/msi.c | ||
2269 | @@ -213,12 +213,13 @@ u32 __pci_msix_desc_mask_irq(struct msi_desc *desc, u32 flag) | ||
2270 | |||
2271 | if (pci_msi_ignore_mask) | ||
2272 | return 0; | ||
2273 | + | ||
2274 | desc_addr = pci_msix_desc_addr(desc); | ||
2275 | if (!desc_addr) | ||
2276 | return 0; | ||
2277 | |||
2278 | mask_bits &= ~PCI_MSIX_ENTRY_CTRL_MASKBIT; | ||
2279 | - if (flag) | ||
2280 | + if (flag & PCI_MSIX_ENTRY_CTRL_MASKBIT) | ||
2281 | mask_bits |= PCI_MSIX_ENTRY_CTRL_MASKBIT; | ||
2282 | |||
2283 | writel(mask_bits, desc_addr + PCI_MSIX_ENTRY_VECTOR_CTRL); | ||
2284 | diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c | ||
2285 | index a8124e47bf6e..d4ac8ce8c1f9 100644 | ||
2286 | --- a/drivers/pci/pci-driver.c | ||
2287 | +++ b/drivers/pci/pci-driver.c | ||
2288 | @@ -1076,17 +1076,22 @@ static int pci_pm_thaw_noirq(struct device *dev) | ||
2289 | return error; | ||
2290 | } | ||
2291 | |||
2292 | - if (pci_has_legacy_pm_support(pci_dev)) | ||
2293 | - return pci_legacy_resume_early(dev); | ||
2294 | - | ||
2295 | /* | ||
2296 | - * pci_restore_state() requires the device to be in D0 (because of MSI | ||
2297 | - * restoration among other things), so force it into D0 in case the | ||
2298 | - * driver's "freeze" callbacks put it into a low-power state directly. | ||
2299 | + * Both the legacy ->resume_early() and the new pm->thaw_noirq() | ||
2300 | + * callbacks assume the device has been returned to D0 and its | ||
2301 | + * config state has been restored. | ||
2302 | + * | ||
2303 | + * In addition, pci_restore_state() restores MSI-X state in MMIO | ||
2304 | + * space, which requires the device to be in D0, so return it to D0 | ||
2305 | + * in case the driver's "freeze" callbacks put it into a low-power | ||
2306 | + * state. | ||
2307 | */ | ||
2308 | pci_set_power_state(pci_dev, PCI_D0); | ||
2309 | pci_restore_state(pci_dev); | ||
2310 | |||
2311 | + if (pci_has_legacy_pm_support(pci_dev)) | ||
2312 | + return pci_legacy_resume_early(dev); | ||
2313 | + | ||
2314 | if (drv && drv->pm && drv->pm->thaw_noirq) | ||
2315 | error = drv->pm->thaw_noirq(dev); | ||
2316 | |||
2317 | diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c | ||
2318 | index 3d5271a7a849..64ebe3e5e611 100644 | ||
2319 | --- a/drivers/pci/probe.c | ||
2320 | +++ b/drivers/pci/probe.c | ||
2321 | @@ -1089,14 +1089,15 @@ static unsigned int pci_scan_child_bus_extend(struct pci_bus *bus, | ||
2322 | * @sec: updated with secondary bus number from EA | ||
2323 | * @sub: updated with subordinate bus number from EA | ||
2324 | * | ||
2325 | - * If @dev is a bridge with EA capability, update @sec and @sub with | ||
2326 | - * fixed bus numbers from the capability and return true. Otherwise, | ||
2327 | - * return false. | ||
2328 | + * If @dev is a bridge with EA capability that specifies valid secondary | ||
2329 | + * and subordinate bus numbers, return true with the bus numbers in @sec | ||
2330 | + * and @sub. Otherwise return false. | ||
2331 | */ | ||
2332 | static bool pci_ea_fixed_busnrs(struct pci_dev *dev, u8 *sec, u8 *sub) | ||
2333 | { | ||
2334 | int ea, offset; | ||
2335 | u32 dw; | ||
2336 | + u8 ea_sec, ea_sub; | ||
2337 | |||
2338 | if (dev->hdr_type != PCI_HEADER_TYPE_BRIDGE) | ||
2339 | return false; | ||
2340 | @@ -1108,8 +1109,13 @@ static bool pci_ea_fixed_busnrs(struct pci_dev *dev, u8 *sec, u8 *sub) | ||
2341 | |||
2342 | offset = ea + PCI_EA_FIRST_ENT; | ||
2343 | pci_read_config_dword(dev, offset, &dw); | ||
2344 | - *sec = dw & PCI_EA_SEC_BUS_MASK; | ||
2345 | - *sub = (dw & PCI_EA_SUB_BUS_MASK) >> PCI_EA_SUB_BUS_SHIFT; | ||
2346 | + ea_sec = dw & PCI_EA_SEC_BUS_MASK; | ||
2347 | + ea_sub = (dw & PCI_EA_SUB_BUS_MASK) >> PCI_EA_SUB_BUS_SHIFT; | ||
2348 | + if (ea_sec == 0 || ea_sub < ea_sec) | ||
2349 | + return false; | ||
2350 | + | ||
2351 | + *sec = ea_sec; | ||
2352 | + *sub = ea_sub; | ||
2353 | return true; | ||
2354 | } | ||
2355 | |||
2356 | diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c | ||
2357 | index 320255e5e8f8..308f744393eb 100644 | ||
2358 | --- a/drivers/pci/quirks.c | ||
2359 | +++ b/drivers/pci/quirks.c | ||
2360 | @@ -4313,15 +4313,21 @@ static int pci_quirk_amd_sb_acs(struct pci_dev *dev, u16 acs_flags) | ||
2361 | |||
2362 | static bool pci_quirk_cavium_acs_match(struct pci_dev *dev) | ||
2363 | { | ||
2364 | + if (!pci_is_pcie(dev) || pci_pcie_type(dev) != PCI_EXP_TYPE_ROOT_PORT) | ||
2365 | + return false; | ||
2366 | + | ||
2367 | + switch (dev->device) { | ||
2368 | /* | ||
2369 | - * Effectively selects all downstream ports for whole ThunderX 1 | ||
2370 | - * family by 0xf800 mask (which represents 8 SoCs), while the lower | ||
2371 | - * bits of device ID are used to indicate which subdevice is used | ||
2372 | - * within the SoC. | ||
2373 | + * Effectively selects all downstream ports for whole ThunderX1 | ||
2374 | + * (which represents 8 SoCs). | ||
2375 | */ | ||
2376 | - return (pci_is_pcie(dev) && | ||
2377 | - (pci_pcie_type(dev) == PCI_EXP_TYPE_ROOT_PORT) && | ||
2378 | - ((dev->device & 0xf800) == 0xa000)); | ||
2379 | + case 0xa000 ... 0xa7ff: /* ThunderX1 */ | ||
2380 | + case 0xaf84: /* ThunderX2 */ | ||
2381 | + case 0xb884: /* ThunderX3 */ | ||
2382 | + return true; | ||
2383 | + default: | ||
2384 | + return false; | ||
2385 | + } | ||
2386 | } | ||
2387 | |||
2388 | static int pci_quirk_cavium_acs(struct pci_dev *dev, u16 acs_flags) | ||
2389 | @@ -4706,7 +4712,7 @@ int pci_dev_specific_acs_enabled(struct pci_dev *dev, u16 acs_flags) | ||
2390 | #define INTEL_BSPR_REG_BPPD (1 << 9) | ||
2391 | |||
2392 | /* Upstream Peer Decode Configuration Register */ | ||
2393 | -#define INTEL_UPDCR_REG 0x1114 | ||
2394 | +#define INTEL_UPDCR_REG 0x1014 | ||
2395 | /* 5:0 Peer Decode Enable bits */ | ||
2396 | #define INTEL_UPDCR_REG_MASK 0x3f | ||
2397 | |||
2398 | diff --git a/drivers/pci/switch/switchtec.c b/drivers/pci/switch/switchtec.c | ||
2399 | index 8c94cd3fd1f2..465d6afd826e 100644 | ||
2400 | --- a/drivers/pci/switch/switchtec.c | ||
2401 | +++ b/drivers/pci/switch/switchtec.c | ||
2402 | @@ -675,7 +675,7 @@ static int ioctl_event_summary(struct switchtec_dev *stdev, | ||
2403 | return -ENOMEM; | ||
2404 | |||
2405 | s->global = ioread32(&stdev->mmio_sw_event->global_summary); | ||
2406 | - s->part_bitmap = ioread32(&stdev->mmio_sw_event->part_event_bitmap); | ||
2407 | + s->part_bitmap = ioread64(&stdev->mmio_sw_event->part_event_bitmap); | ||
2408 | s->local_part = ioread32(&stdev->mmio_part_cfg->part_event_summary); | ||
2409 | |||
2410 | for (i = 0; i < stdev->partition_count; i++) { | ||
2411 | diff --git a/drivers/rpmsg/qcom_glink_native.c b/drivers/rpmsg/qcom_glink_native.c | ||
2412 | index 621f1afd4d6b..1995f5b3ea67 100644 | ||
2413 | --- a/drivers/rpmsg/qcom_glink_native.c | ||
2414 | +++ b/drivers/rpmsg/qcom_glink_native.c | ||
2415 | @@ -241,10 +241,31 @@ static void qcom_glink_channel_release(struct kref *ref) | ||
2416 | { | ||
2417 | struct glink_channel *channel = container_of(ref, struct glink_channel, | ||
2418 | refcount); | ||
2419 | + struct glink_core_rx_intent *intent; | ||
2420 | + struct glink_core_rx_intent *tmp; | ||
2421 | unsigned long flags; | ||
2422 | + int iid; | ||
2423 | + | ||
2424 | + /* cancel pending rx_done work */ | ||
2425 | + cancel_work_sync(&channel->intent_work); | ||
2426 | |||
2427 | spin_lock_irqsave(&channel->intent_lock, flags); | ||
2428 | + /* Free all non-reuse intents pending rx_done work */ | ||
2429 | + list_for_each_entry_safe(intent, tmp, &channel->done_intents, node) { | ||
2430 | + if (!intent->reuse) { | ||
2431 | + kfree(intent->data); | ||
2432 | + kfree(intent); | ||
2433 | + } | ||
2434 | + } | ||
2435 | + | ||
2436 | + idr_for_each_entry(&channel->liids, tmp, iid) { | ||
2437 | + kfree(tmp->data); | ||
2438 | + kfree(tmp); | ||
2439 | + } | ||
2440 | idr_destroy(&channel->liids); | ||
2441 | + | ||
2442 | + idr_for_each_entry(&channel->riids, tmp, iid) | ||
2443 | + kfree(tmp); | ||
2444 | idr_destroy(&channel->riids); | ||
2445 | spin_unlock_irqrestore(&channel->intent_lock, flags); | ||
2446 | |||
2447 | @@ -1094,13 +1115,12 @@ static int qcom_glink_create_remote(struct qcom_glink *glink, | ||
2448 | close_link: | ||
2449 | /* | ||
2450 | * Send a close request to "undo" our open-ack. The close-ack will | ||
2451 | - * release the last reference. | ||
2452 | + * release qcom_glink_send_open_req() reference and the last reference | ||
2453 | + * will be relesed after receiving remote_close or transport unregister | ||
2454 | + * by calling qcom_glink_native_remove(). | ||
2455 | */ | ||
2456 | qcom_glink_send_close_req(glink, channel); | ||
2457 | |||
2458 | - /* Release qcom_glink_send_open_req() reference */ | ||
2459 | - kref_put(&channel->refcount, qcom_glink_channel_release); | ||
2460 | - | ||
2461 | return ret; | ||
2462 | } | ||
2463 | |||
2464 | @@ -1415,15 +1435,13 @@ static int qcom_glink_rx_open(struct qcom_glink *glink, unsigned int rcid, | ||
2465 | |||
2466 | ret = rpmsg_register_device(rpdev); | ||
2467 | if (ret) | ||
2468 | - goto free_rpdev; | ||
2469 | + goto rcid_remove; | ||
2470 | |||
2471 | channel->rpdev = rpdev; | ||
2472 | } | ||
2473 | |||
2474 | return 0; | ||
2475 | |||
2476 | -free_rpdev: | ||
2477 | - kfree(rpdev); | ||
2478 | rcid_remove: | ||
2479 | spin_lock_irqsave(&glink->idr_lock, flags); | ||
2480 | idr_remove(&glink->rcids, channel->rcid); | ||
2481 | @@ -1544,6 +1562,18 @@ static void qcom_glink_work(struct work_struct *work) | ||
2482 | } | ||
2483 | } | ||
2484 | |||
2485 | +static void qcom_glink_cancel_rx_work(struct qcom_glink *glink) | ||
2486 | +{ | ||
2487 | + struct glink_defer_cmd *dcmd; | ||
2488 | + struct glink_defer_cmd *tmp; | ||
2489 | + | ||
2490 | + /* cancel any pending deferred rx_work */ | ||
2491 | + cancel_work_sync(&glink->rx_work); | ||
2492 | + | ||
2493 | + list_for_each_entry_safe(dcmd, tmp, &glink->rx_queue, node) | ||
2494 | + kfree(dcmd); | ||
2495 | +} | ||
2496 | + | ||
2497 | struct qcom_glink *qcom_glink_native_probe(struct device *dev, | ||
2498 | unsigned long features, | ||
2499 | struct qcom_glink_pipe *rx, | ||
2500 | @@ -1619,23 +1649,24 @@ void qcom_glink_native_remove(struct qcom_glink *glink) | ||
2501 | struct glink_channel *channel; | ||
2502 | int cid; | ||
2503 | int ret; | ||
2504 | - unsigned long flags; | ||
2505 | |||
2506 | disable_irq(glink->irq); | ||
2507 | - cancel_work_sync(&glink->rx_work); | ||
2508 | + qcom_glink_cancel_rx_work(glink); | ||
2509 | |||
2510 | ret = device_for_each_child(glink->dev, NULL, qcom_glink_remove_device); | ||
2511 | if (ret) | ||
2512 | dev_warn(glink->dev, "Can't remove GLINK devices: %d\n", ret); | ||
2513 | |||
2514 | - spin_lock_irqsave(&glink->idr_lock, flags); | ||
2515 | /* Release any defunct local channels, waiting for close-ack */ | ||
2516 | idr_for_each_entry(&glink->lcids, channel, cid) | ||
2517 | kref_put(&channel->refcount, qcom_glink_channel_release); | ||
2518 | |||
2519 | + /* Release any defunct local channels, waiting for close-req */ | ||
2520 | + idr_for_each_entry(&glink->rcids, channel, cid) | ||
2521 | + kref_put(&channel->refcount, qcom_glink_channel_release); | ||
2522 | + | ||
2523 | idr_destroy(&glink->lcids); | ||
2524 | idr_destroy(&glink->rcids); | ||
2525 | - spin_unlock_irqrestore(&glink->idr_lock, flags); | ||
2526 | mbox_free_channel(glink->mbox_chan); | ||
2527 | } | ||
2528 | EXPORT_SYMBOL_GPL(qcom_glink_native_remove); | ||
2529 | diff --git a/drivers/rpmsg/qcom_glink_smem.c b/drivers/rpmsg/qcom_glink_smem.c | ||
2530 | index 4238383d8685..579bc4443f6d 100644 | ||
2531 | --- a/drivers/rpmsg/qcom_glink_smem.c | ||
2532 | +++ b/drivers/rpmsg/qcom_glink_smem.c | ||
2533 | @@ -105,7 +105,7 @@ static void glink_smem_rx_advance(struct qcom_glink_pipe *np, | ||
2534 | tail = le32_to_cpu(*pipe->tail); | ||
2535 | |||
2536 | tail += count; | ||
2537 | - if (tail > pipe->native.length) | ||
2538 | + if (tail >= pipe->native.length) | ||
2539 | tail -= pipe->native.length; | ||
2540 | |||
2541 | *pipe->tail = cpu_to_le32(tail); | ||
2542 | diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c | ||
2543 | index ebd47c0cf9e9..70b99c0e2e67 100644 | ||
2544 | --- a/drivers/scsi/libiscsi.c | ||
2545 | +++ b/drivers/scsi/libiscsi.c | ||
2546 | @@ -1945,7 +1945,7 @@ enum blk_eh_timer_return iscsi_eh_cmd_timed_out(struct scsi_cmnd *sc) | ||
2547 | |||
2548 | ISCSI_DBG_EH(session, "scsi cmd %p timedout\n", sc); | ||
2549 | |||
2550 | - spin_lock(&session->frwd_lock); | ||
2551 | + spin_lock_bh(&session->frwd_lock); | ||
2552 | task = (struct iscsi_task *)sc->SCp.ptr; | ||
2553 | if (!task) { | ||
2554 | /* | ||
2555 | @@ -2072,7 +2072,7 @@ enum blk_eh_timer_return iscsi_eh_cmd_timed_out(struct scsi_cmnd *sc) | ||
2556 | done: | ||
2557 | if (task) | ||
2558 | task->last_timeout = jiffies; | ||
2559 | - spin_unlock(&session->frwd_lock); | ||
2560 | + spin_unlock_bh(&session->frwd_lock); | ||
2561 | ISCSI_DBG_EH(session, "return %s\n", rc == BLK_EH_RESET_TIMER ? | ||
2562 | "timer reset" : "shutdown or nh"); | ||
2563 | return rc; | ||
2564 | diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c | ||
2565 | index 7259bce85e0e..1fbc5c6c6c14 100644 | ||
2566 | --- a/drivers/scsi/qla2xxx/qla_attr.c | ||
2567 | +++ b/drivers/scsi/qla2xxx/qla_attr.c | ||
2568 | @@ -176,6 +176,7 @@ qla2x00_sysfs_read_nvram(struct file *filp, struct kobject *kobj, | ||
2569 | |||
2570 | faddr = ha->flt_region_nvram; | ||
2571 | if (IS_QLA28XX(ha)) { | ||
2572 | + qla28xx_get_aux_images(vha, &active_regions); | ||
2573 | if (active_regions.aux.vpd_nvram == QLA27XX_SECONDARY_IMAGE) | ||
2574 | faddr = ha->flt_region_nvram_sec; | ||
2575 | } | ||
2576 | diff --git a/drivers/scsi/qla2xxx/qla_bsg.c b/drivers/scsi/qla2xxx/qla_bsg.c | ||
2577 | index 99f0a1a08143..cbaf178fc979 100644 | ||
2578 | --- a/drivers/scsi/qla2xxx/qla_bsg.c | ||
2579 | +++ b/drivers/scsi/qla2xxx/qla_bsg.c | ||
2580 | @@ -2399,7 +2399,7 @@ qla2x00_get_flash_image_status(struct bsg_job *bsg_job) | ||
2581 | struct qla_active_regions regions = { }; | ||
2582 | struct active_regions active_regions = { }; | ||
2583 | |||
2584 | - qla28xx_get_aux_images(vha, &active_regions); | ||
2585 | + qla27xx_get_active_image(vha, &active_regions); | ||
2586 | regions.global_image = active_regions.global; | ||
2587 | |||
2588 | if (IS_QLA28XX(ha)) { | ||
2589 | diff --git a/drivers/scsi/qla2xxx/qla_fw.h b/drivers/scsi/qla2xxx/qla_fw.h | ||
2590 | index 732bb871c433..dc2366a29665 100644 | ||
2591 | --- a/drivers/scsi/qla2xxx/qla_fw.h | ||
2592 | +++ b/drivers/scsi/qla2xxx/qla_fw.h | ||
2593 | @@ -1523,6 +1523,10 @@ struct qla_flt_header { | ||
2594 | #define FLT_REG_NVRAM_SEC_28XX_1 0x10F | ||
2595 | #define FLT_REG_NVRAM_SEC_28XX_2 0x111 | ||
2596 | #define FLT_REG_NVRAM_SEC_28XX_3 0x113 | ||
2597 | +#define FLT_REG_MPI_PRI_28XX 0xD3 | ||
2598 | +#define FLT_REG_MPI_SEC_28XX 0xF0 | ||
2599 | +#define FLT_REG_PEP_PRI_28XX 0xD1 | ||
2600 | +#define FLT_REG_PEP_SEC_28XX 0xF1 | ||
2601 | |||
2602 | struct qla_flt_region { | ||
2603 | uint16_t code; | ||
2604 | diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c | ||
2605 | index d400b51929a6..5d31e3d52b6b 100644 | ||
2606 | --- a/drivers/scsi/qla2xxx/qla_init.c | ||
2607 | +++ b/drivers/scsi/qla2xxx/qla_init.c | ||
2608 | @@ -534,6 +534,7 @@ static int qla_post_els_plogi_work(struct scsi_qla_host *vha, fc_port_t *fcport) | ||
2609 | |||
2610 | e->u.fcport.fcport = fcport; | ||
2611 | fcport->flags |= FCF_ASYNC_ACTIVE; | ||
2612 | + fcport->disc_state = DSC_LOGIN_PEND; | ||
2613 | return qla2x00_post_work(vha, e); | ||
2614 | } | ||
2615 | |||
2616 | @@ -4847,6 +4848,7 @@ qla2x00_alloc_fcport(scsi_qla_host_t *vha, gfp_t flags) | ||
2617 | } | ||
2618 | |||
2619 | INIT_WORK(&fcport->del_work, qla24xx_delete_sess_fn); | ||
2620 | + INIT_WORK(&fcport->free_work, qlt_free_session_done); | ||
2621 | INIT_WORK(&fcport->reg_work, qla_register_fcport_fn); | ||
2622 | INIT_LIST_HEAD(&fcport->gnl_entry); | ||
2623 | INIT_LIST_HEAD(&fcport->list); | ||
2624 | diff --git a/drivers/scsi/qla2xxx/qla_sup.c b/drivers/scsi/qla2xxx/qla_sup.c | ||
2625 | index f2d5115b2d8d..bbe90354f49b 100644 | ||
2626 | --- a/drivers/scsi/qla2xxx/qla_sup.c | ||
2627 | +++ b/drivers/scsi/qla2xxx/qla_sup.c | ||
2628 | @@ -847,15 +847,15 @@ qla2xxx_get_flt_info(scsi_qla_host_t *vha, uint32_t flt_addr) | ||
2629 | ha->flt_region_img_status_pri = start; | ||
2630 | break; | ||
2631 | case FLT_REG_IMG_SEC_27XX: | ||
2632 | - if (IS_QLA27XX(ha) && !IS_QLA28XX(ha)) | ||
2633 | + if (IS_QLA27XX(ha) || IS_QLA28XX(ha)) | ||
2634 | ha->flt_region_img_status_sec = start; | ||
2635 | break; | ||
2636 | case FLT_REG_FW_SEC_27XX: | ||
2637 | - if (IS_QLA27XX(ha) && !IS_QLA28XX(ha)) | ||
2638 | + if (IS_QLA27XX(ha) || IS_QLA28XX(ha)) | ||
2639 | ha->flt_region_fw_sec = start; | ||
2640 | break; | ||
2641 | case FLT_REG_BOOTLOAD_SEC_27XX: | ||
2642 | - if (IS_QLA27XX(ha) && !IS_QLA28XX(ha)) | ||
2643 | + if (IS_QLA27XX(ha) || IS_QLA28XX(ha)) | ||
2644 | ha->flt_region_boot_sec = start; | ||
2645 | break; | ||
2646 | case FLT_REG_AUX_IMG_PRI_28XX: | ||
2647 | @@ -2725,8 +2725,11 @@ qla28xx_write_flash_data(scsi_qla_host_t *vha, uint32_t *dwptr, uint32_t faddr, | ||
2648 | ql_log(ql_log_warn + ql_dbg_verbose, vha, 0xffff, | ||
2649 | "Region %x is secure\n", region.code); | ||
2650 | |||
2651 | - if (region.code == FLT_REG_FW || | ||
2652 | - region.code == FLT_REG_FW_SEC_27XX) { | ||
2653 | + switch (region.code) { | ||
2654 | + case FLT_REG_FW: | ||
2655 | + case FLT_REG_FW_SEC_27XX: | ||
2656 | + case FLT_REG_MPI_PRI_28XX: | ||
2657 | + case FLT_REG_MPI_SEC_28XX: | ||
2658 | fw_array = dwptr; | ||
2659 | |||
2660 | /* 1st fw array */ | ||
2661 | @@ -2757,9 +2760,23 @@ qla28xx_write_flash_data(scsi_qla_host_t *vha, uint32_t *dwptr, uint32_t faddr, | ||
2662 | buf_size_without_sfub += risc_size; | ||
2663 | fw_array += risc_size; | ||
2664 | } | ||
2665 | - } else { | ||
2666 | - ql_log(ql_log_warn + ql_dbg_verbose, vha, 0xffff, | ||
2667 | - "Secure region %x not supported\n", | ||
2668 | + break; | ||
2669 | + | ||
2670 | + case FLT_REG_PEP_PRI_28XX: | ||
2671 | + case FLT_REG_PEP_SEC_28XX: | ||
2672 | + fw_array = dwptr; | ||
2673 | + | ||
2674 | + /* 1st fw array */ | ||
2675 | + risc_size = be32_to_cpu(fw_array[3]); | ||
2676 | + risc_attr = be32_to_cpu(fw_array[9]); | ||
2677 | + | ||
2678 | + buf_size_without_sfub = risc_size; | ||
2679 | + fw_array += risc_size; | ||
2680 | + break; | ||
2681 | + | ||
2682 | + default: | ||
2683 | + ql_log(ql_log_warn + ql_dbg_verbose, vha, | ||
2684 | + 0xffff, "Secure region %x not supported\n", | ||
2685 | region.code); | ||
2686 | rval = QLA_COMMAND_ERROR; | ||
2687 | goto done; | ||
2688 | @@ -2880,7 +2897,7 @@ qla28xx_write_flash_data(scsi_qla_host_t *vha, uint32_t *dwptr, uint32_t faddr, | ||
2689 | "Sending Secure Flash MB Cmd\n"); | ||
2690 | rval = qla28xx_secure_flash_update(vha, 0, region.code, | ||
2691 | buf_size_without_sfub, sfub_dma, | ||
2692 | - sizeof(struct secure_flash_update_block)); | ||
2693 | + sizeof(struct secure_flash_update_block) >> 2); | ||
2694 | if (rval != QLA_SUCCESS) { | ||
2695 | ql_log(ql_log_warn, vha, 0xffff, | ||
2696 | "Secure Flash MB Cmd failed %x.", rval); | ||
2697 | diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c | ||
2698 | index a06e56224a55..a9bd0f513316 100644 | ||
2699 | --- a/drivers/scsi/qla2xxx/qla_target.c | ||
2700 | +++ b/drivers/scsi/qla2xxx/qla_target.c | ||
2701 | @@ -1160,7 +1160,6 @@ void qlt_unreg_sess(struct fc_port *sess) | ||
2702 | sess->last_rscn_gen = sess->rscn_gen; | ||
2703 | sess->last_login_gen = sess->login_gen; | ||
2704 | |||
2705 | - INIT_WORK(&sess->free_work, qlt_free_session_done); | ||
2706 | queue_work(sess->vha->hw->wq, &sess->free_work); | ||
2707 | } | ||
2708 | EXPORT_SYMBOL(qlt_unreg_sess); | ||
2709 | diff --git a/drivers/scsi/qla2xxx/tcm_qla2xxx.c b/drivers/scsi/qla2xxx/tcm_qla2xxx.c | ||
2710 | index 042a24314edc..bab2073c1f72 100644 | ||
2711 | --- a/drivers/scsi/qla2xxx/tcm_qla2xxx.c | ||
2712 | +++ b/drivers/scsi/qla2xxx/tcm_qla2xxx.c | ||
2713 | @@ -246,6 +246,8 @@ static void tcm_qla2xxx_complete_mcmd(struct work_struct *work) | ||
2714 | */ | ||
2715 | static void tcm_qla2xxx_free_mcmd(struct qla_tgt_mgmt_cmd *mcmd) | ||
2716 | { | ||
2717 | + if (!mcmd) | ||
2718 | + return; | ||
2719 | INIT_WORK(&mcmd->free_work, tcm_qla2xxx_complete_mcmd); | ||
2720 | queue_work(tcm_qla2xxx_free_wq, &mcmd->free_work); | ||
2721 | } | ||
2722 | diff --git a/drivers/scsi/ufs/cdns-pltfrm.c b/drivers/scsi/ufs/cdns-pltfrm.c | ||
2723 | index b2af04c57a39..6feeb0faf123 100644 | ||
2724 | --- a/drivers/scsi/ufs/cdns-pltfrm.c | ||
2725 | +++ b/drivers/scsi/ufs/cdns-pltfrm.c | ||
2726 | @@ -99,6 +99,12 @@ static int cdns_ufs_link_startup_notify(struct ufs_hba *hba, | ||
2727 | */ | ||
2728 | ufshcd_dme_set(hba, UIC_ARG_MIB(PA_LOCAL_TX_LCC_ENABLE), 0); | ||
2729 | |||
2730 | + /* | ||
2731 | + * Disabling Autohibern8 feature in cadence UFS | ||
2732 | + * to mask unexpected interrupt trigger. | ||
2733 | + */ | ||
2734 | + hba->ahit = 0; | ||
2735 | + | ||
2736 | return 0; | ||
2737 | } | ||
2738 | |||
2739 | diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c | ||
2740 | index f225eaa98ff8..d0f45600b669 100644 | ||
2741 | --- a/drivers/usb/core/hcd.c | ||
2742 | +++ b/drivers/usb/core/hcd.c | ||
2743 | @@ -1409,7 +1409,17 @@ int usb_hcd_map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb, | ||
2744 | if (usb_endpoint_xfer_control(&urb->ep->desc)) { | ||
2745 | if (hcd->self.uses_pio_for_control) | ||
2746 | return ret; | ||
2747 | - if (hcd_uses_dma(hcd)) { | ||
2748 | + if (hcd->localmem_pool) { | ||
2749 | + ret = hcd_alloc_coherent( | ||
2750 | + urb->dev->bus, mem_flags, | ||
2751 | + &urb->setup_dma, | ||
2752 | + (void **)&urb->setup_packet, | ||
2753 | + sizeof(struct usb_ctrlrequest), | ||
2754 | + DMA_TO_DEVICE); | ||
2755 | + if (ret) | ||
2756 | + return ret; | ||
2757 | + urb->transfer_flags |= URB_SETUP_MAP_LOCAL; | ||
2758 | + } else if (hcd_uses_dma(hcd)) { | ||
2759 | if (is_vmalloc_addr(urb->setup_packet)) { | ||
2760 | WARN_ONCE(1, "setup packet is not dma capable\n"); | ||
2761 | return -EAGAIN; | ||
2762 | @@ -1427,23 +1437,22 @@ int usb_hcd_map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb, | ||
2763 | urb->setup_dma)) | ||
2764 | return -EAGAIN; | ||
2765 | urb->transfer_flags |= URB_SETUP_MAP_SINGLE; | ||
2766 | - } else if (hcd->localmem_pool) { | ||
2767 | - ret = hcd_alloc_coherent( | ||
2768 | - urb->dev->bus, mem_flags, | ||
2769 | - &urb->setup_dma, | ||
2770 | - (void **)&urb->setup_packet, | ||
2771 | - sizeof(struct usb_ctrlrequest), | ||
2772 | - DMA_TO_DEVICE); | ||
2773 | - if (ret) | ||
2774 | - return ret; | ||
2775 | - urb->transfer_flags |= URB_SETUP_MAP_LOCAL; | ||
2776 | } | ||
2777 | } | ||
2778 | |||
2779 | dir = usb_urb_dir_in(urb) ? DMA_FROM_DEVICE : DMA_TO_DEVICE; | ||
2780 | if (urb->transfer_buffer_length != 0 | ||
2781 | && !(urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP)) { | ||
2782 | - if (hcd_uses_dma(hcd)) { | ||
2783 | + if (hcd->localmem_pool) { | ||
2784 | + ret = hcd_alloc_coherent( | ||
2785 | + urb->dev->bus, mem_flags, | ||
2786 | + &urb->transfer_dma, | ||
2787 | + &urb->transfer_buffer, | ||
2788 | + urb->transfer_buffer_length, | ||
2789 | + dir); | ||
2790 | + if (ret == 0) | ||
2791 | + urb->transfer_flags |= URB_MAP_LOCAL; | ||
2792 | + } else if (hcd_uses_dma(hcd)) { | ||
2793 | if (urb->num_sgs) { | ||
2794 | int n; | ||
2795 | |||
2796 | @@ -1497,15 +1506,6 @@ int usb_hcd_map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb, | ||
2797 | else | ||
2798 | urb->transfer_flags |= URB_DMA_MAP_SINGLE; | ||
2799 | } | ||
2800 | - } else if (hcd->localmem_pool) { | ||
2801 | - ret = hcd_alloc_coherent( | ||
2802 | - urb->dev->bus, mem_flags, | ||
2803 | - &urb->transfer_dma, | ||
2804 | - &urb->transfer_buffer, | ||
2805 | - urb->transfer_buffer_length, | ||
2806 | - dir); | ||
2807 | - if (ret == 0) | ||
2808 | - urb->transfer_flags |= URB_MAP_LOCAL; | ||
2809 | } | ||
2810 | if (ret && (urb->transfer_flags & (URB_SETUP_MAP_SINGLE | | ||
2811 | URB_SETUP_MAP_LOCAL))) | ||
2812 | diff --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c | ||
2813 | index 54a3c8195c96..2adcabe060c5 100644 | ||
2814 | --- a/drivers/usb/storage/scsiglue.c | ||
2815 | +++ b/drivers/usb/storage/scsiglue.c | ||
2816 | @@ -135,7 +135,8 @@ static int slave_configure(struct scsi_device *sdev) | ||
2817 | * For such controllers we need to make sure the block layer sets | ||
2818 | * up bounce buffers in addressable memory. | ||
2819 | */ | ||
2820 | - if (!hcd_uses_dma(bus_to_hcd(us->pusb_dev->bus))) | ||
2821 | + if (!hcd_uses_dma(bus_to_hcd(us->pusb_dev->bus)) || | ||
2822 | + (bus_to_hcd(us->pusb_dev->bus)->localmem_pool != NULL)) | ||
2823 | blk_queue_bounce_limit(sdev->request_queue, BLK_BOUNCE_HIGH); | ||
2824 | |||
2825 | /* | ||
2826 | diff --git a/drivers/vfio/pci/vfio_pci_intrs.c b/drivers/vfio/pci/vfio_pci_intrs.c | ||
2827 | index 3fa3f728fb39..2056f3f85f59 100644 | ||
2828 | --- a/drivers/vfio/pci/vfio_pci_intrs.c | ||
2829 | +++ b/drivers/vfio/pci/vfio_pci_intrs.c | ||
2830 | @@ -294,8 +294,8 @@ static int vfio_msi_set_vector_signal(struct vfio_pci_device *vdev, | ||
2831 | irq = pci_irq_vector(pdev, vector); | ||
2832 | |||
2833 | if (vdev->ctx[vector].trigger) { | ||
2834 | - free_irq(irq, vdev->ctx[vector].trigger); | ||
2835 | irq_bypass_unregister_producer(&vdev->ctx[vector].producer); | ||
2836 | + free_irq(irq, vdev->ctx[vector].trigger); | ||
2837 | kfree(vdev->ctx[vector].name); | ||
2838 | eventfd_ctx_put(vdev->ctx[vector].trigger); | ||
2839 | vdev->ctx[vector].trigger = NULL; | ||
2840 | diff --git a/fs/cifs/cifs_debug.c b/fs/cifs/cifs_debug.c | ||
2841 | index 0b4eee3bed66..efb2928ff6c8 100644 | ||
2842 | --- a/fs/cifs/cifs_debug.c | ||
2843 | +++ b/fs/cifs/cifs_debug.c | ||
2844 | @@ -256,6 +256,11 @@ static int cifs_debug_data_proc_show(struct seq_file *m, void *v) | ||
2845 | if (!server->rdma) | ||
2846 | goto skip_rdma; | ||
2847 | |||
2848 | + if (!server->smbd_conn) { | ||
2849 | + seq_printf(m, "\nSMBDirect transport not available"); | ||
2850 | + goto skip_rdma; | ||
2851 | + } | ||
2852 | + | ||
2853 | seq_printf(m, "\nSMBDirect (in hex) protocol version: %x " | ||
2854 | "transport status: %x", | ||
2855 | server->smbd_conn->protocol, | ||
2856 | diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h | ||
2857 | index d78bfcc19156..5d2dd04b55a6 100644 | ||
2858 | --- a/fs/cifs/cifsglob.h | ||
2859 | +++ b/fs/cifs/cifsglob.h | ||
2860 | @@ -1524,6 +1524,7 @@ struct mid_q_entry { | ||
2861 | struct TCP_Server_Info *server; /* server corresponding to this mid */ | ||
2862 | __u64 mid; /* multiplex id */ | ||
2863 | __u16 credits; /* number of credits consumed by this mid */ | ||
2864 | + __u16 credits_received; /* number of credits from the response */ | ||
2865 | __u32 pid; /* process id */ | ||
2866 | __u32 sequence_number; /* for CIFS signing */ | ||
2867 | unsigned long when_alloc; /* when mid was created */ | ||
2868 | diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c | ||
2869 | index ccaa8bad336f..20c70cbab1ad 100644 | ||
2870 | --- a/fs/cifs/connect.c | ||
2871 | +++ b/fs/cifs/connect.c | ||
2872 | @@ -905,6 +905,20 @@ dequeue_mid(struct mid_q_entry *mid, bool malformed) | ||
2873 | spin_unlock(&GlobalMid_Lock); | ||
2874 | } | ||
2875 | |||
2876 | +static unsigned int | ||
2877 | +smb2_get_credits_from_hdr(char *buffer, struct TCP_Server_Info *server) | ||
2878 | +{ | ||
2879 | + struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)buffer; | ||
2880 | + | ||
2881 | + /* | ||
2882 | + * SMB1 does not use credits. | ||
2883 | + */ | ||
2884 | + if (server->vals->header_preamble_size) | ||
2885 | + return 0; | ||
2886 | + | ||
2887 | + return le16_to_cpu(shdr->CreditRequest); | ||
2888 | +} | ||
2889 | + | ||
2890 | static void | ||
2891 | handle_mid(struct mid_q_entry *mid, struct TCP_Server_Info *server, | ||
2892 | char *buf, int malformed) | ||
2893 | @@ -912,6 +926,7 @@ handle_mid(struct mid_q_entry *mid, struct TCP_Server_Info *server, | ||
2894 | if (server->ops->check_trans2 && | ||
2895 | server->ops->check_trans2(mid, server, buf, malformed)) | ||
2896 | return; | ||
2897 | + mid->credits_received = smb2_get_credits_from_hdr(buf, server); | ||
2898 | mid->resp_buf = buf; | ||
2899 | mid->large_buf = server->large_buf; | ||
2900 | /* Was previous buf put in mpx struct for multi-rsp? */ | ||
2901 | @@ -1222,12 +1237,6 @@ next_pdu: | ||
2902 | for (i = 0; i < num_mids; i++) { | ||
2903 | if (mids[i] != NULL) { | ||
2904 | mids[i]->resp_buf_size = server->pdu_size; | ||
2905 | - if ((mids[i]->mid_flags & MID_WAIT_CANCELLED) && | ||
2906 | - mids[i]->mid_state == MID_RESPONSE_RECEIVED && | ||
2907 | - server->ops->handle_cancelled_mid) | ||
2908 | - server->ops->handle_cancelled_mid( | ||
2909 | - mids[i]->resp_buf, | ||
2910 | - server); | ||
2911 | |||
2912 | if (!mids[i]->multiRsp || mids[i]->multiEnd) | ||
2913 | mids[i]->callback(mids[i]); | ||
2914 | @@ -4700,6 +4709,17 @@ static int is_path_remote(struct cifs_sb_info *cifs_sb, struct smb_vol *vol, | ||
2915 | } | ||
2916 | |||
2917 | #ifdef CONFIG_CIFS_DFS_UPCALL | ||
2918 | +static inline void set_root_tcon(struct cifs_sb_info *cifs_sb, | ||
2919 | + struct cifs_tcon *tcon, | ||
2920 | + struct cifs_tcon **root) | ||
2921 | +{ | ||
2922 | + spin_lock(&cifs_tcp_ses_lock); | ||
2923 | + tcon->tc_count++; | ||
2924 | + tcon->remap = cifs_remap(cifs_sb); | ||
2925 | + spin_unlock(&cifs_tcp_ses_lock); | ||
2926 | + *root = tcon; | ||
2927 | +} | ||
2928 | + | ||
2929 | int cifs_mount(struct cifs_sb_info *cifs_sb, struct smb_vol *vol) | ||
2930 | { | ||
2931 | int rc = 0; | ||
2932 | @@ -4801,18 +4821,10 @@ int cifs_mount(struct cifs_sb_info *cifs_sb, struct smb_vol *vol) | ||
2933 | /* Cache out resolved root server */ | ||
2934 | (void)dfs_cache_find(xid, ses, cifs_sb->local_nls, cifs_remap(cifs_sb), | ||
2935 | root_path + 1, NULL, NULL); | ||
2936 | - /* | ||
2937 | - * Save root tcon for additional DFS requests to update or create a new | ||
2938 | - * DFS cache entry, or even perform DFS failover. | ||
2939 | - */ | ||
2940 | - spin_lock(&cifs_tcp_ses_lock); | ||
2941 | - tcon->tc_count++; | ||
2942 | - tcon->dfs_path = root_path; | ||
2943 | + kfree(root_path); | ||
2944 | root_path = NULL; | ||
2945 | - tcon->remap = cifs_remap(cifs_sb); | ||
2946 | - spin_unlock(&cifs_tcp_ses_lock); | ||
2947 | |||
2948 | - root_tcon = tcon; | ||
2949 | + set_root_tcon(cifs_sb, tcon, &root_tcon); | ||
2950 | |||
2951 | for (count = 1; ;) { | ||
2952 | if (!rc && tcon) { | ||
2953 | @@ -4849,6 +4861,15 @@ int cifs_mount(struct cifs_sb_info *cifs_sb, struct smb_vol *vol) | ||
2954 | mount_put_conns(cifs_sb, xid, server, ses, tcon); | ||
2955 | rc = mount_get_conns(vol, cifs_sb, &xid, &server, &ses, | ||
2956 | &tcon); | ||
2957 | + /* | ||
2958 | + * Ensure that DFS referrals go through new root server. | ||
2959 | + */ | ||
2960 | + if (!rc && tcon && | ||
2961 | + (tcon->share_flags & (SHI1005_FLAGS_DFS | | ||
2962 | + SHI1005_FLAGS_DFS_ROOT))) { | ||
2963 | + cifs_put_tcon(root_tcon); | ||
2964 | + set_root_tcon(cifs_sb, tcon, &root_tcon); | ||
2965 | + } | ||
2966 | } | ||
2967 | if (rc) { | ||
2968 | if (rc == -EACCES || rc == -EOPNOTSUPP) | ||
2969 | diff --git a/fs/cifs/file.c b/fs/cifs/file.c | ||
2970 | index a3b6be80f8a9..c32650f14c9b 100644 | ||
2971 | --- a/fs/cifs/file.c | ||
2972 | +++ b/fs/cifs/file.c | ||
2973 | @@ -729,6 +729,13 @@ cifs_reopen_file(struct cifsFileInfo *cfile, bool can_flush) | ||
2974 | if (backup_cred(cifs_sb)) | ||
2975 | create_options |= CREATE_OPEN_BACKUP_INTENT; | ||
2976 | |||
2977 | + /* O_SYNC also has bit for O_DSYNC so following check picks up either */ | ||
2978 | + if (cfile->f_flags & O_SYNC) | ||
2979 | + create_options |= CREATE_WRITE_THROUGH; | ||
2980 | + | ||
2981 | + if (cfile->f_flags & O_DIRECT) | ||
2982 | + create_options |= CREATE_NO_BUFFER; | ||
2983 | + | ||
2984 | if (server->ops->get_lease_key) | ||
2985 | server->ops->get_lease_key(inode, &cfile->fid); | ||
2986 | |||
2987 | diff --git a/fs/cifs/smb2misc.c b/fs/cifs/smb2misc.c | ||
2988 | index 449d1584ff72..766974fe637a 100644 | ||
2989 | --- a/fs/cifs/smb2misc.c | ||
2990 | +++ b/fs/cifs/smb2misc.c | ||
2991 | @@ -743,36 +743,67 @@ smb2_cancelled_close_fid(struct work_struct *work) | ||
2992 | kfree(cancelled); | ||
2993 | } | ||
2994 | |||
2995 | +/* Caller should already has an extra reference to @tcon */ | ||
2996 | +static int | ||
2997 | +__smb2_handle_cancelled_close(struct cifs_tcon *tcon, __u64 persistent_fid, | ||
2998 | + __u64 volatile_fid) | ||
2999 | +{ | ||
3000 | + struct close_cancelled_open *cancelled; | ||
3001 | + | ||
3002 | + cancelled = kzalloc(sizeof(*cancelled), GFP_KERNEL); | ||
3003 | + if (!cancelled) | ||
3004 | + return -ENOMEM; | ||
3005 | + | ||
3006 | + cancelled->fid.persistent_fid = persistent_fid; | ||
3007 | + cancelled->fid.volatile_fid = volatile_fid; | ||
3008 | + cancelled->tcon = tcon; | ||
3009 | + INIT_WORK(&cancelled->work, smb2_cancelled_close_fid); | ||
3010 | + WARN_ON(queue_work(cifsiod_wq, &cancelled->work) == false); | ||
3011 | + | ||
3012 | + return 0; | ||
3013 | +} | ||
3014 | + | ||
3015 | +int | ||
3016 | +smb2_handle_cancelled_close(struct cifs_tcon *tcon, __u64 persistent_fid, | ||
3017 | + __u64 volatile_fid) | ||
3018 | +{ | ||
3019 | + int rc; | ||
3020 | + | ||
3021 | + cifs_dbg(FYI, "%s: tc_count=%d\n", __func__, tcon->tc_count); | ||
3022 | + spin_lock(&cifs_tcp_ses_lock); | ||
3023 | + tcon->tc_count++; | ||
3024 | + spin_unlock(&cifs_tcp_ses_lock); | ||
3025 | + | ||
3026 | + rc = __smb2_handle_cancelled_close(tcon, persistent_fid, volatile_fid); | ||
3027 | + if (rc) | ||
3028 | + cifs_put_tcon(tcon); | ||
3029 | + | ||
3030 | + return rc; | ||
3031 | +} | ||
3032 | + | ||
3033 | int | ||
3034 | smb2_handle_cancelled_mid(char *buffer, struct TCP_Server_Info *server) | ||
3035 | { | ||
3036 | struct smb2_sync_hdr *sync_hdr = (struct smb2_sync_hdr *)buffer; | ||
3037 | struct smb2_create_rsp *rsp = (struct smb2_create_rsp *)buffer; | ||
3038 | struct cifs_tcon *tcon; | ||
3039 | - struct close_cancelled_open *cancelled; | ||
3040 | + int rc; | ||
3041 | |||
3042 | if (sync_hdr->Command != SMB2_CREATE || | ||
3043 | sync_hdr->Status != STATUS_SUCCESS) | ||
3044 | return 0; | ||
3045 | |||
3046 | - cancelled = kzalloc(sizeof(*cancelled), GFP_KERNEL); | ||
3047 | - if (!cancelled) | ||
3048 | - return -ENOMEM; | ||
3049 | - | ||
3050 | tcon = smb2_find_smb_tcon(server, sync_hdr->SessionId, | ||
3051 | sync_hdr->TreeId); | ||
3052 | - if (!tcon) { | ||
3053 | - kfree(cancelled); | ||
3054 | + if (!tcon) | ||
3055 | return -ENOENT; | ||
3056 | - } | ||
3057 | |||
3058 | - cancelled->fid.persistent_fid = rsp->PersistentFileId; | ||
3059 | - cancelled->fid.volatile_fid = rsp->VolatileFileId; | ||
3060 | - cancelled->tcon = tcon; | ||
3061 | - INIT_WORK(&cancelled->work, smb2_cancelled_close_fid); | ||
3062 | - queue_work(cifsiod_wq, &cancelled->work); | ||
3063 | + rc = __smb2_handle_cancelled_close(tcon, rsp->PersistentFileId, | ||
3064 | + rsp->VolatileFileId); | ||
3065 | + if (rc) | ||
3066 | + cifs_put_tcon(tcon); | ||
3067 | |||
3068 | - return 0; | ||
3069 | + return rc; | ||
3070 | } | ||
3071 | |||
3072 | /** | ||
3073 | diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c | ||
3074 | index cd55af9b7cc5..b5c1cba3e6a1 100644 | ||
3075 | --- a/fs/cifs/smb2ops.c | ||
3076 | +++ b/fs/cifs/smb2ops.c | ||
3077 | @@ -151,13 +151,7 @@ smb2_get_credits_field(struct TCP_Server_Info *server, const int optype) | ||
3078 | static unsigned int | ||
3079 | smb2_get_credits(struct mid_q_entry *mid) | ||
3080 | { | ||
3081 | - struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)mid->resp_buf; | ||
3082 | - | ||
3083 | - if (mid->mid_state == MID_RESPONSE_RECEIVED | ||
3084 | - || mid->mid_state == MID_RESPONSE_MALFORMED) | ||
3085 | - return le16_to_cpu(shdr->CreditRequest); | ||
3086 | - | ||
3087 | - return 0; | ||
3088 | + return mid->credits_received; | ||
3089 | } | ||
3090 | |||
3091 | static int | ||
3092 | diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c | ||
3093 | index 05149862aea4..c985caa2d955 100644 | ||
3094 | --- a/fs/cifs/smb2pdu.c | ||
3095 | +++ b/fs/cifs/smb2pdu.c | ||
3096 | @@ -2972,7 +2972,21 @@ int | ||
3097 | SMB2_close(const unsigned int xid, struct cifs_tcon *tcon, | ||
3098 | u64 persistent_fid, u64 volatile_fid) | ||
3099 | { | ||
3100 | - return SMB2_close_flags(xid, tcon, persistent_fid, volatile_fid, 0); | ||
3101 | + int rc; | ||
3102 | + int tmp_rc; | ||
3103 | + | ||
3104 | + rc = SMB2_close_flags(xid, tcon, persistent_fid, volatile_fid, 0); | ||
3105 | + | ||
3106 | + /* retry close in a worker thread if this one is interrupted */ | ||
3107 | + if (rc == -EINTR) { | ||
3108 | + tmp_rc = smb2_handle_cancelled_close(tcon, persistent_fid, | ||
3109 | + volatile_fid); | ||
3110 | + if (tmp_rc) | ||
3111 | + cifs_dbg(VFS, "handle cancelled close fid 0x%llx returned error %d\n", | ||
3112 | + persistent_fid, tmp_rc); | ||
3113 | + } | ||
3114 | + | ||
3115 | + return rc; | ||
3116 | } | ||
3117 | |||
3118 | int | ||
3119 | diff --git a/fs/cifs/smb2proto.h b/fs/cifs/smb2proto.h | ||
3120 | index 71b2930b8e0b..2a12a2fa38a2 100644 | ||
3121 | --- a/fs/cifs/smb2proto.h | ||
3122 | +++ b/fs/cifs/smb2proto.h | ||
3123 | @@ -212,6 +212,9 @@ extern int SMB2_set_compression(const unsigned int xid, struct cifs_tcon *tcon, | ||
3124 | extern int SMB2_oplock_break(const unsigned int xid, struct cifs_tcon *tcon, | ||
3125 | const u64 persistent_fid, const u64 volatile_fid, | ||
3126 | const __u8 oplock_level); | ||
3127 | +extern int smb2_handle_cancelled_close(struct cifs_tcon *tcon, | ||
3128 | + __u64 persistent_fid, | ||
3129 | + __u64 volatile_fid); | ||
3130 | extern int smb2_handle_cancelled_mid(char *buffer, | ||
3131 | struct TCP_Server_Info *server); | ||
3132 | void smb2_cancelled_close_fid(struct work_struct *work); | ||
3133 | diff --git a/fs/cifs/smbdirect.c b/fs/cifs/smbdirect.c | ||
3134 | index 3c91fa97c9a8..5b1b97e9e0c9 100644 | ||
3135 | --- a/fs/cifs/smbdirect.c | ||
3136 | +++ b/fs/cifs/smbdirect.c | ||
3137 | @@ -1069,7 +1069,7 @@ static int smbd_post_send_data( | ||
3138 | |||
3139 | if (n_vec > SMBDIRECT_MAX_SGE) { | ||
3140 | cifs_dbg(VFS, "Can't fit data to SGL, n_vec=%d\n", n_vec); | ||
3141 | - return -ENOMEM; | ||
3142 | + return -EINVAL; | ||
3143 | } | ||
3144 | |||
3145 | sg_init_table(sgl, n_vec); | ||
3146 | @@ -1476,6 +1476,7 @@ void smbd_destroy(struct TCP_Server_Info *server) | ||
3147 | info->transport_status = SMBD_DESTROYED; | ||
3148 | |||
3149 | destroy_workqueue(info->workqueue); | ||
3150 | + log_rdma_event(INFO, "rdma session destroyed\n"); | ||
3151 | kfree(info); | ||
3152 | } | ||
3153 | |||
3154 | @@ -1505,8 +1506,9 @@ create_conn: | ||
3155 | log_rdma_event(INFO, "creating rdma session\n"); | ||
3156 | server->smbd_conn = smbd_get_connection( | ||
3157 | server, (struct sockaddr *) &server->dstaddr); | ||
3158 | - log_rdma_event(INFO, "created rdma session info=%p\n", | ||
3159 | - server->smbd_conn); | ||
3160 | + | ||
3161 | + if (server->smbd_conn) | ||
3162 | + cifs_dbg(VFS, "RDMA transport re-established\n"); | ||
3163 | |||
3164 | return server->smbd_conn ? 0 : -ENOENT; | ||
3165 | } | ||
3166 | @@ -1970,7 +1972,7 @@ read_rfc1002_done: | ||
3167 | |||
3168 | if (info->transport_status != SMBD_CONNECTED) { | ||
3169 | log_read(ERR, "disconnected\n"); | ||
3170 | - return 0; | ||
3171 | + return -ECONNABORTED; | ||
3172 | } | ||
3173 | |||
3174 | goto again; | ||
3175 | @@ -2269,12 +2271,7 @@ static void smbd_mr_recovery_work(struct work_struct *work) | ||
3176 | int rc; | ||
3177 | |||
3178 | list_for_each_entry(smbdirect_mr, &info->mr_list, list) { | ||
3179 | - if (smbdirect_mr->state == MR_INVALIDATED) | ||
3180 | - ib_dma_unmap_sg( | ||
3181 | - info->id->device, smbdirect_mr->sgl, | ||
3182 | - smbdirect_mr->sgl_count, | ||
3183 | - smbdirect_mr->dir); | ||
3184 | - else if (smbdirect_mr->state == MR_ERROR) { | ||
3185 | + if (smbdirect_mr->state == MR_ERROR) { | ||
3186 | |||
3187 | /* recover this MR entry */ | ||
3188 | rc = ib_dereg_mr(smbdirect_mr->mr); | ||
3189 | @@ -2602,11 +2599,20 @@ int smbd_deregister_mr(struct smbd_mr *smbdirect_mr) | ||
3190 | */ | ||
3191 | smbdirect_mr->state = MR_INVALIDATED; | ||
3192 | |||
3193 | - /* | ||
3194 | - * Schedule the work to do MR recovery for future I/Os | ||
3195 | - * MR recovery is slow and we don't want it to block the current I/O | ||
3196 | - */ | ||
3197 | - queue_work(info->workqueue, &info->mr_recovery_work); | ||
3198 | + if (smbdirect_mr->state == MR_INVALIDATED) { | ||
3199 | + ib_dma_unmap_sg( | ||
3200 | + info->id->device, smbdirect_mr->sgl, | ||
3201 | + smbdirect_mr->sgl_count, | ||
3202 | + smbdirect_mr->dir); | ||
3203 | + smbdirect_mr->state = MR_READY; | ||
3204 | + if (atomic_inc_return(&info->mr_ready_count) == 1) | ||
3205 | + wake_up_interruptible(&info->wait_mr); | ||
3206 | + } else | ||
3207 | + /* | ||
3208 | + * Schedule the work to do MR recovery for future I/Os MR | ||
3209 | + * recovery is slow and don't want it to block current I/O | ||
3210 | + */ | ||
3211 | + queue_work(info->workqueue, &info->mr_recovery_work); | ||
3212 | |||
3213 | done: | ||
3214 | if (atomic_dec_and_test(&info->mr_used_count)) | ||
3215 | diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c | ||
3216 | index ca3de62688d6..755434d5e4e7 100644 | ||
3217 | --- a/fs/cifs/transport.c | ||
3218 | +++ b/fs/cifs/transport.c | ||
3219 | @@ -93,8 +93,14 @@ static void _cifs_mid_q_entry_release(struct kref *refcount) | ||
3220 | __u16 smb_cmd = le16_to_cpu(midEntry->command); | ||
3221 | unsigned long now; | ||
3222 | unsigned long roundtrip_time; | ||
3223 | - struct TCP_Server_Info *server = midEntry->server; | ||
3224 | #endif | ||
3225 | + struct TCP_Server_Info *server = midEntry->server; | ||
3226 | + | ||
3227 | + if (midEntry->resp_buf && (midEntry->mid_flags & MID_WAIT_CANCELLED) && | ||
3228 | + midEntry->mid_state == MID_RESPONSE_RECEIVED && | ||
3229 | + server->ops->handle_cancelled_mid) | ||
3230 | + server->ops->handle_cancelled_mid(midEntry->resp_buf, server); | ||
3231 | + | ||
3232 | midEntry->mid_state = MID_FREE; | ||
3233 | atomic_dec(&midCount); | ||
3234 | if (midEntry->large_buf) | ||
3235 | @@ -319,8 +325,11 @@ __smb_send_rqst(struct TCP_Server_Info *server, int num_rqst, | ||
3236 | int val = 1; | ||
3237 | __be32 rfc1002_marker; | ||
3238 | |||
3239 | - if (cifs_rdma_enabled(server) && server->smbd_conn) { | ||
3240 | - rc = smbd_send(server, num_rqst, rqst); | ||
3241 | + if (cifs_rdma_enabled(server)) { | ||
3242 | + /* return -EAGAIN when connecting or reconnecting */ | ||
3243 | + rc = -EAGAIN; | ||
3244 | + if (server->smbd_conn) | ||
3245 | + rc = smbd_send(server, num_rqst, rqst); | ||
3246 | goto smbd_done; | ||
3247 | } | ||
3248 | |||
3249 | @@ -1119,8 +1128,8 @@ compound_send_recv(const unsigned int xid, struct cifs_ses *ses, | ||
3250 | midQ[i]->mid, le16_to_cpu(midQ[i]->command)); | ||
3251 | send_cancel(server, &rqst[i], midQ[i]); | ||
3252 | spin_lock(&GlobalMid_Lock); | ||
3253 | + midQ[i]->mid_flags |= MID_WAIT_CANCELLED; | ||
3254 | if (midQ[i]->mid_state == MID_REQUEST_SUBMITTED) { | ||
3255 | - midQ[i]->mid_flags |= MID_WAIT_CANCELLED; | ||
3256 | midQ[i]->callback = cifs_cancelled_callback; | ||
3257 | cancelled_mid[i] = true; | ||
3258 | credits[i].value = 0; | ||
3259 | diff --git a/fs/gfs2/file.c b/fs/gfs2/file.c | ||
3260 | index 997b326247e2..c53e3b892210 100644 | ||
3261 | --- a/fs/gfs2/file.c | ||
3262 | +++ b/fs/gfs2/file.c | ||
3263 | @@ -381,27 +381,28 @@ static void gfs2_size_hint(struct file *filep, loff_t offset, size_t size) | ||
3264 | /** | ||
3265 | * gfs2_allocate_page_backing - Allocate blocks for a write fault | ||
3266 | * @page: The (locked) page to allocate backing for | ||
3267 | + * @length: Size of the allocation | ||
3268 | * | ||
3269 | * We try to allocate all the blocks required for the page in one go. This | ||
3270 | * might fail for various reasons, so we keep trying until all the blocks to | ||
3271 | * back this page are allocated. If some of the blocks are already allocated, | ||
3272 | * that is ok too. | ||
3273 | */ | ||
3274 | -static int gfs2_allocate_page_backing(struct page *page) | ||
3275 | +static int gfs2_allocate_page_backing(struct page *page, unsigned int length) | ||
3276 | { | ||
3277 | u64 pos = page_offset(page); | ||
3278 | - u64 size = PAGE_SIZE; | ||
3279 | |||
3280 | do { | ||
3281 | struct iomap iomap = { }; | ||
3282 | |||
3283 | - if (gfs2_iomap_get_alloc(page->mapping->host, pos, 1, &iomap)) | ||
3284 | + if (gfs2_iomap_get_alloc(page->mapping->host, pos, length, &iomap)) | ||
3285 | return -EIO; | ||
3286 | |||
3287 | - iomap.length = min(iomap.length, size); | ||
3288 | - size -= iomap.length; | ||
3289 | + if (length < iomap.length) | ||
3290 | + iomap.length = length; | ||
3291 | + length -= iomap.length; | ||
3292 | pos += iomap.length; | ||
3293 | - } while (size > 0); | ||
3294 | + } while (length > 0); | ||
3295 | |||
3296 | return 0; | ||
3297 | } | ||
3298 | @@ -501,7 +502,7 @@ static vm_fault_t gfs2_page_mkwrite(struct vm_fault *vmf) | ||
3299 | if (gfs2_is_stuffed(ip)) | ||
3300 | ret = gfs2_unstuff_dinode(ip, page); | ||
3301 | if (ret == 0) | ||
3302 | - ret = gfs2_allocate_page_backing(page); | ||
3303 | + ret = gfs2_allocate_page_backing(page, PAGE_SIZE); | ||
3304 | |||
3305 | out_trans_end: | ||
3306 | if (ret) | ||
3307 | diff --git a/fs/gfs2/log.c b/fs/gfs2/log.c | ||
3308 | index 58e237fba565..2aed73666a65 100644 | ||
3309 | --- a/fs/gfs2/log.c | ||
3310 | +++ b/fs/gfs2/log.c | ||
3311 | @@ -609,6 +609,14 @@ void gfs2_add_revoke(struct gfs2_sbd *sdp, struct gfs2_bufdata *bd) | ||
3312 | list_add(&bd->bd_list, &sdp->sd_log_revokes); | ||
3313 | } | ||
3314 | |||
3315 | +void gfs2_glock_remove_revoke(struct gfs2_glock *gl) | ||
3316 | +{ | ||
3317 | + if (atomic_dec_return(&gl->gl_revokes) == 0) { | ||
3318 | + clear_bit(GLF_LFLUSH, &gl->gl_flags); | ||
3319 | + gfs2_glock_queue_put(gl); | ||
3320 | + } | ||
3321 | +} | ||
3322 | + | ||
3323 | void gfs2_write_revokes(struct gfs2_sbd *sdp) | ||
3324 | { | ||
3325 | struct gfs2_trans *tr; | ||
3326 | diff --git a/fs/gfs2/log.h b/fs/gfs2/log.h | ||
3327 | index 2315fca47a2b..c762da494546 100644 | ||
3328 | --- a/fs/gfs2/log.h | ||
3329 | +++ b/fs/gfs2/log.h | ||
3330 | @@ -77,6 +77,7 @@ extern void gfs2_ail1_flush(struct gfs2_sbd *sdp, struct writeback_control *wbc) | ||
3331 | extern void gfs2_log_shutdown(struct gfs2_sbd *sdp); | ||
3332 | extern int gfs2_logd(void *data); | ||
3333 | extern void gfs2_add_revoke(struct gfs2_sbd *sdp, struct gfs2_bufdata *bd); | ||
3334 | +extern void gfs2_glock_remove_revoke(struct gfs2_glock *gl); | ||
3335 | extern void gfs2_write_revokes(struct gfs2_sbd *sdp); | ||
3336 | |||
3337 | #endif /* __LOG_DOT_H__ */ | ||
3338 | diff --git a/fs/gfs2/lops.c b/fs/gfs2/lops.c | ||
3339 | index 5b17979af539..e2437b775456 100644 | ||
3340 | --- a/fs/gfs2/lops.c | ||
3341 | +++ b/fs/gfs2/lops.c | ||
3342 | @@ -882,10 +882,7 @@ static void revoke_lo_after_commit(struct gfs2_sbd *sdp, struct gfs2_trans *tr) | ||
3343 | bd = list_entry(head->next, struct gfs2_bufdata, bd_list); | ||
3344 | list_del_init(&bd->bd_list); | ||
3345 | gl = bd->bd_gl; | ||
3346 | - if (atomic_dec_return(&gl->gl_revokes) == 0) { | ||
3347 | - clear_bit(GLF_LFLUSH, &gl->gl_flags); | ||
3348 | - gfs2_glock_queue_put(gl); | ||
3349 | - } | ||
3350 | + gfs2_glock_remove_revoke(gl); | ||
3351 | kmem_cache_free(gfs2_bufdata_cachep, bd); | ||
3352 | } | ||
3353 | } | ||
3354 | diff --git a/fs/gfs2/trans.c b/fs/gfs2/trans.c | ||
3355 | index 35e3059255fe..9d4227330de4 100644 | ||
3356 | --- a/fs/gfs2/trans.c | ||
3357 | +++ b/fs/gfs2/trans.c | ||
3358 | @@ -262,6 +262,8 @@ void gfs2_trans_remove_revoke(struct gfs2_sbd *sdp, u64 blkno, unsigned int len) | ||
3359 | list_del_init(&bd->bd_list); | ||
3360 | gfs2_assert_withdraw(sdp, sdp->sd_log_num_revoke); | ||
3361 | sdp->sd_log_num_revoke--; | ||
3362 | + if (bd->bd_gl) | ||
3363 | + gfs2_glock_remove_revoke(bd->bd_gl); | ||
3364 | kmem_cache_free(gfs2_bufdata_cachep, bd); | ||
3365 | tr->tr_num_revoke--; | ||
3366 | if (--n == 0) | ||
3367 | diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h | ||
3368 | index 9b6336ad3266..e459b38ef33c 100644 | ||
3369 | --- a/include/linux/mmc/card.h | ||
3370 | +++ b/include/linux/mmc/card.h | ||
3371 | @@ -291,6 +291,7 @@ struct mmc_card { | ||
3372 | struct sd_switch_caps sw_caps; /* switch (CMD6) caps */ | ||
3373 | |||
3374 | unsigned int sdio_funcs; /* number of SDIO functions */ | ||
3375 | + atomic_t sdio_funcs_probed; /* number of probed SDIO funcs */ | ||
3376 | struct sdio_cccr cccr; /* common card info */ | ||
3377 | struct sdio_cis cis; /* common tuple info */ | ||
3378 | struct sdio_func *sdio_func[SDIO_MAX_FUNCS]; /* SDIO functions (devices) */ | ||
3379 | diff --git a/include/linux/pm_qos.h b/include/linux/pm_qos.h | ||
3380 | index ebf5ef17cc2a..24a6263c9931 100644 | ||
3381 | --- a/include/linux/pm_qos.h | ||
3382 | +++ b/include/linux/pm_qos.h | ||
3383 | @@ -256,7 +256,7 @@ static inline s32 dev_pm_qos_raw_resume_latency(struct device *dev) | ||
3384 | #endif | ||
3385 | |||
3386 | #define FREQ_QOS_MIN_DEFAULT_VALUE 0 | ||
3387 | -#define FREQ_QOS_MAX_DEFAULT_VALUE (-1) | ||
3388 | +#define FREQ_QOS_MAX_DEFAULT_VALUE S32_MAX | ||
3389 | |||
3390 | enum freq_qos_req_type { | ||
3391 | FREQ_QOS_MIN = 1, | ||
3392 | diff --git a/sound/hda/hdac_stream.c b/sound/hda/hdac_stream.c | ||
3393 | index f9707fb05efe..682ed39f79b0 100644 | ||
3394 | --- a/sound/hda/hdac_stream.c | ||
3395 | +++ b/sound/hda/hdac_stream.c | ||
3396 | @@ -120,10 +120,8 @@ void snd_hdac_stream_clear(struct hdac_stream *azx_dev) | ||
3397 | snd_hdac_stream_updateb(azx_dev, SD_CTL, | ||
3398 | SD_CTL_DMA_START | SD_INT_MASK, 0); | ||
3399 | snd_hdac_stream_writeb(azx_dev, SD_STS, SD_INT_MASK); /* to be sure */ | ||
3400 | - if (azx_dev->stripe) { | ||
3401 | + if (azx_dev->stripe) | ||
3402 | snd_hdac_stream_updateb(azx_dev, SD_CTL_3B, SD_CTL_STRIPE_MASK, 0); | ||
3403 | - azx_dev->stripe = 0; | ||
3404 | - } | ||
3405 | azx_dev->running = false; | ||
3406 | } | ||
3407 | EXPORT_SYMBOL_GPL(snd_hdac_stream_clear); | ||
3408 | diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c | ||
3409 | index 4dafc864d765..488c17c9f375 100644 | ||
3410 | --- a/sound/pci/hda/patch_hdmi.c | ||
3411 | +++ b/sound/pci/hda/patch_hdmi.c | ||
3412 | @@ -1983,6 +1983,8 @@ static int hdmi_pcm_close(struct hda_pcm_stream *hinfo, | ||
3413 | per_cvt->assigned = 0; | ||
3414 | hinfo->nid = 0; | ||
3415 | |||
3416 | + azx_stream(get_azx_dev(substream))->stripe = 0; | ||
3417 | + | ||
3418 | mutex_lock(&spec->pcm_lock); | ||
3419 | snd_hda_spdif_ctls_unassign(codec, pcm_idx); | ||
3420 | clear_bit(pcm_idx, &spec->pcm_in_use); |