1 |
commit: ec8aeec54749f14f8b881db887d76fd471265b76 |
2 |
Author: Mike Pagano <mpagano <AT> gentoo <DOT> org> |
3 |
AuthorDate: Tue May 5 17:41:28 2020 +0000 |
4 |
Commit: Mike Pagano <mpagano <AT> gentoo <DOT> org> |
5 |
CommitDate: Tue May 5 17:41:28 2020 +0000 |
6 |
URL: https://gitweb.gentoo.org/proj/linux-patches.git/commit/?id=ec8aeec5 |
7 |
|
8 |
Linux patch 4.14.179 |
9 |
|
10 |
Signed-off-by: Mike Pagano <mpagano <AT> gentoo.org> |
11 |
|
12 |
0000_README | 4 + |
13 |
1178_linux-4.14.179.patch | 793 ++++++++++++++++++++++++++++++++++++++++++++++ |
14 |
2 files changed, 797 insertions(+) |
15 |
|
16 |
diff --git a/0000_README b/0000_README |
17 |
index 36bc305..0eb3dcb 100644 |
18 |
--- a/0000_README |
19 |
+++ b/0000_README |
20 |
@@ -755,6 +755,10 @@ Patch: 1177_linux-4.14.178.patch |
21 |
From: https://www.kernel.org |
22 |
Desc: Linux 4.14.178 |
23 |
|
24 |
+Patch: 1178_linux-4.14.179.patch |
25 |
+From: https://www.kernel.org |
26 |
+Desc: Linux 4.14.179 |
27 |
+ |
28 |
Patch: 1500_XATTR_USER_PREFIX.patch |
29 |
From: https://bugs.gentoo.org/show_bug.cgi?id=470644 |
30 |
Desc: Support for namespace user.pax.* on tmpfs. |
31 |
|
32 |
diff --git a/1178_linux-4.14.179.patch b/1178_linux-4.14.179.patch |
33 |
new file mode 100644 |
34 |
index 0000000..9eae485 |
35 |
--- /dev/null |
36 |
+++ b/1178_linux-4.14.179.patch |
37 |
@@ -0,0 +1,793 @@ |
38 |
+diff --git a/Makefile b/Makefile |
39 |
+index 73e93e596e50..d2baacc1b0f6 100644 |
40 |
+--- a/Makefile |
41 |
++++ b/Makefile |
42 |
+@@ -1,7 +1,7 @@ |
43 |
+ # SPDX-License-Identifier: GPL-2.0 |
44 |
+ VERSION = 4 |
45 |
+ PATCHLEVEL = 14 |
46 |
+-SUBLEVEL = 178 |
47 |
++SUBLEVEL = 179 |
48 |
+ EXTRAVERSION = |
49 |
+ NAME = Petit Gorille |
50 |
+ |
51 |
+diff --git a/drivers/acpi/device_pm.c b/drivers/acpi/device_pm.c |
52 |
+index fc300ce3ae8e..afb1bc104a6f 100644 |
53 |
+--- a/drivers/acpi/device_pm.c |
54 |
++++ b/drivers/acpi/device_pm.c |
55 |
+@@ -227,13 +227,13 @@ int acpi_device_set_power(struct acpi_device *device, int state) |
56 |
+ end: |
57 |
+ if (result) { |
58 |
+ dev_warn(&device->dev, "Failed to change power state to %s\n", |
59 |
+- acpi_power_state_string(state)); |
60 |
++ acpi_power_state_string(target_state)); |
61 |
+ } else { |
62 |
+ device->power.state = target_state; |
63 |
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO, |
64 |
+ "Device [%s] transitioned to %s\n", |
65 |
+ device->pnp.bus_id, |
66 |
+- acpi_power_state_string(state))); |
67 |
++ acpi_power_state_string(target_state))); |
68 |
+ } |
69 |
+ |
70 |
+ return result; |
71 |
+diff --git a/drivers/dma/dmatest.c b/drivers/dma/dmatest.c |
72 |
+index e39336127741..d19a602beebd 100644 |
73 |
+--- a/drivers/dma/dmatest.c |
74 |
++++ b/drivers/dma/dmatest.c |
75 |
+@@ -552,8 +552,8 @@ static int dmatest_func(void *data) |
76 |
+ flags = DMA_CTRL_ACK | DMA_PREP_INTERRUPT; |
77 |
+ |
78 |
+ ktime = ktime_get(); |
79 |
+- while (!kthread_should_stop() |
80 |
+- && !(params->iterations && total_tests >= params->iterations)) { |
81 |
++ while (!(kthread_should_stop() || |
82 |
++ (params->iterations && total_tests >= params->iterations))) { |
83 |
+ struct dma_async_tx_descriptor *tx = NULL; |
84 |
+ struct dmaengine_unmap_data *um; |
85 |
+ dma_addr_t srcs[src_cnt]; |
86 |
+diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c |
87 |
+index dfdc7d3147fb..51276dd0d864 100644 |
88 |
+--- a/drivers/gpu/drm/drm_edid.c |
89 |
++++ b/drivers/gpu/drm/drm_edid.c |
90 |
+@@ -4502,7 +4502,7 @@ static struct drm_display_mode *drm_mode_displayid_detailed(struct drm_device *d |
91 |
+ struct drm_display_mode *mode; |
92 |
+ unsigned pixel_clock = (timings->pixel_clock[0] | |
93 |
+ (timings->pixel_clock[1] << 8) | |
94 |
+- (timings->pixel_clock[2] << 16)); |
95 |
++ (timings->pixel_clock[2] << 16)) + 1; |
96 |
+ unsigned hactive = (timings->hactive[0] | timings->hactive[1] << 8) + 1; |
97 |
+ unsigned hblank = (timings->hblank[0] | timings->hblank[1] << 8) + 1; |
98 |
+ unsigned hsync = (timings->hsync[0] | (timings->hsync[1] & 0x7f) << 8) + 1; |
99 |
+diff --git a/drivers/gpu/drm/qxl/qxl_cmd.c b/drivers/gpu/drm/qxl/qxl_cmd.c |
100 |
+index 3eb920851141..8334afa70b94 100644 |
101 |
+--- a/drivers/gpu/drm/qxl/qxl_cmd.c |
102 |
++++ b/drivers/gpu/drm/qxl/qxl_cmd.c |
103 |
+@@ -504,9 +504,10 @@ int qxl_hw_surface_alloc(struct qxl_device *qdev, |
104 |
+ return ret; |
105 |
+ |
106 |
+ ret = qxl_release_reserve_list(release, true); |
107 |
+- if (ret) |
108 |
++ if (ret) { |
109 |
++ qxl_release_free(qdev, release); |
110 |
+ return ret; |
111 |
+- |
112 |
++ } |
113 |
+ cmd = (struct qxl_surface_cmd *)qxl_release_map(qdev, release); |
114 |
+ cmd->type = QXL_SURFACE_CMD_CREATE; |
115 |
+ cmd->flags = QXL_SURF_FLAG_KEEP_DATA; |
116 |
+@@ -532,8 +533,8 @@ int qxl_hw_surface_alloc(struct qxl_device *qdev, |
117 |
+ /* no need to add a release to the fence for this surface bo, |
118 |
+ since it is only released when we ask to destroy the surface |
119 |
+ and it would never signal otherwise */ |
120 |
+- qxl_push_command_ring_release(qdev, release, QXL_CMD_SURFACE, false); |
121 |
+ qxl_release_fence_buffer_objects(release); |
122 |
++ qxl_push_command_ring_release(qdev, release, QXL_CMD_SURFACE, false); |
123 |
+ |
124 |
+ surf->hw_surf_alloc = true; |
125 |
+ spin_lock(&qdev->surf_id_idr_lock); |
126 |
+@@ -575,9 +576,8 @@ int qxl_hw_surface_dealloc(struct qxl_device *qdev, |
127 |
+ cmd->surface_id = id; |
128 |
+ qxl_release_unmap(qdev, release, &cmd->release_info); |
129 |
+ |
130 |
+- qxl_push_command_ring_release(qdev, release, QXL_CMD_SURFACE, false); |
131 |
+- |
132 |
+ qxl_release_fence_buffer_objects(release); |
133 |
++ qxl_push_command_ring_release(qdev, release, QXL_CMD_SURFACE, false); |
134 |
+ |
135 |
+ return 0; |
136 |
+ } |
137 |
+diff --git a/drivers/gpu/drm/qxl/qxl_display.c b/drivers/gpu/drm/qxl/qxl_display.c |
138 |
+index 573bab222123..b209a25e307d 100644 |
139 |
+--- a/drivers/gpu/drm/qxl/qxl_display.c |
140 |
++++ b/drivers/gpu/drm/qxl/qxl_display.c |
141 |
+@@ -533,8 +533,8 @@ static int qxl_primary_apply_cursor(struct drm_plane *plane) |
142 |
+ cmd->u.set.visible = 1; |
143 |
+ qxl_release_unmap(qdev, release, &cmd->release_info); |
144 |
+ |
145 |
+- qxl_push_cursor_ring_release(qdev, release, QXL_CMD_CURSOR, false); |
146 |
+ qxl_release_fence_buffer_objects(release); |
147 |
++ qxl_push_cursor_ring_release(qdev, release, QXL_CMD_CURSOR, false); |
148 |
+ |
149 |
+ return ret; |
150 |
+ |
151 |
+@@ -701,8 +701,8 @@ static void qxl_cursor_atomic_update(struct drm_plane *plane, |
152 |
+ cmd->u.position.y = plane->state->crtc_y + fb->hot_y; |
153 |
+ |
154 |
+ qxl_release_unmap(qdev, release, &cmd->release_info); |
155 |
+- qxl_push_cursor_ring_release(qdev, release, QXL_CMD_CURSOR, false); |
156 |
+ qxl_release_fence_buffer_objects(release); |
157 |
++ qxl_push_cursor_ring_release(qdev, release, QXL_CMD_CURSOR, false); |
158 |
+ |
159 |
+ if (old_cursor_bo) |
160 |
+ qxl_bo_unref(&old_cursor_bo); |
161 |
+@@ -747,8 +747,8 @@ static void qxl_cursor_atomic_disable(struct drm_plane *plane, |
162 |
+ cmd->type = QXL_CURSOR_HIDE; |
163 |
+ qxl_release_unmap(qdev, release, &cmd->release_info); |
164 |
+ |
165 |
+- qxl_push_cursor_ring_release(qdev, release, QXL_CMD_CURSOR, false); |
166 |
+ qxl_release_fence_buffer_objects(release); |
167 |
++ qxl_push_cursor_ring_release(qdev, release, QXL_CMD_CURSOR, false); |
168 |
+ } |
169 |
+ |
170 |
+ static int qxl_plane_prepare_fb(struct drm_plane *plane, |
171 |
+diff --git a/drivers/gpu/drm/qxl/qxl_draw.c b/drivers/gpu/drm/qxl/qxl_draw.c |
172 |
+index 4d8681e84e68..d009f2bc28e9 100644 |
173 |
+--- a/drivers/gpu/drm/qxl/qxl_draw.c |
174 |
++++ b/drivers/gpu/drm/qxl/qxl_draw.c |
175 |
+@@ -241,8 +241,8 @@ void qxl_draw_opaque_fb(const struct qxl_fb_image *qxl_fb_image, |
176 |
+ qxl_bo_physical_address(qdev, dimage->bo, 0); |
177 |
+ qxl_release_unmap(qdev, release, &drawable->release_info); |
178 |
+ |
179 |
+- qxl_push_command_ring_release(qdev, release, QXL_CMD_DRAW, false); |
180 |
+ qxl_release_fence_buffer_objects(release); |
181 |
++ qxl_push_command_ring_release(qdev, release, QXL_CMD_DRAW, false); |
182 |
+ |
183 |
+ out_free_palette: |
184 |
+ if (palette_bo) |
185 |
+@@ -348,9 +348,10 @@ void qxl_draw_dirty_fb(struct qxl_device *qdev, |
186 |
+ goto out_release_backoff; |
187 |
+ |
188 |
+ rects = drawable_set_clipping(qdev, num_clips, clips_bo); |
189 |
+- if (!rects) |
190 |
++ if (!rects) { |
191 |
++ ret = -EINVAL; |
192 |
+ goto out_release_backoff; |
193 |
+- |
194 |
++ } |
195 |
+ drawable = (struct qxl_drawable *)qxl_release_map(qdev, release); |
196 |
+ |
197 |
+ drawable->clip.type = SPICE_CLIP_TYPE_RECTS; |
198 |
+@@ -381,8 +382,8 @@ void qxl_draw_dirty_fb(struct qxl_device *qdev, |
199 |
+ } |
200 |
+ qxl_bo_kunmap(clips_bo); |
201 |
+ |
202 |
+- qxl_push_command_ring_release(qdev, release, QXL_CMD_DRAW, false); |
203 |
+ qxl_release_fence_buffer_objects(release); |
204 |
++ qxl_push_command_ring_release(qdev, release, QXL_CMD_DRAW, false); |
205 |
+ |
206 |
+ out_release_backoff: |
207 |
+ if (ret) |
208 |
+@@ -432,8 +433,8 @@ void qxl_draw_copyarea(struct qxl_device *qdev, |
209 |
+ drawable->u.copy_bits.src_pos.y = sy; |
210 |
+ qxl_release_unmap(qdev, release, &drawable->release_info); |
211 |
+ |
212 |
+- qxl_push_command_ring_release(qdev, release, QXL_CMD_DRAW, false); |
213 |
+ qxl_release_fence_buffer_objects(release); |
214 |
++ qxl_push_command_ring_release(qdev, release, QXL_CMD_DRAW, false); |
215 |
+ |
216 |
+ out_free_release: |
217 |
+ if (ret) |
218 |
+@@ -476,8 +477,8 @@ void qxl_draw_fill(struct qxl_draw_fill *qxl_draw_fill_rec) |
219 |
+ |
220 |
+ qxl_release_unmap(qdev, release, &drawable->release_info); |
221 |
+ |
222 |
+- qxl_push_command_ring_release(qdev, release, QXL_CMD_DRAW, false); |
223 |
+ qxl_release_fence_buffer_objects(release); |
224 |
++ qxl_push_command_ring_release(qdev, release, QXL_CMD_DRAW, false); |
225 |
+ |
226 |
+ out_free_release: |
227 |
+ if (ret) |
228 |
+diff --git a/drivers/gpu/drm/qxl/qxl_ioctl.c b/drivers/gpu/drm/qxl/qxl_ioctl.c |
229 |
+index 31effed4a3c8..cede17585525 100644 |
230 |
+--- a/drivers/gpu/drm/qxl/qxl_ioctl.c |
231 |
++++ b/drivers/gpu/drm/qxl/qxl_ioctl.c |
232 |
+@@ -257,11 +257,8 @@ static int qxl_process_single_command(struct qxl_device *qdev, |
233 |
+ apply_surf_reloc(qdev, &reloc_info[i]); |
234 |
+ } |
235 |
+ |
236 |
++ qxl_release_fence_buffer_objects(release); |
237 |
+ ret = qxl_push_command_ring_release(qdev, release, cmd->type, true); |
238 |
+- if (ret) |
239 |
+- qxl_release_backoff_reserve_list(release); |
240 |
+- else |
241 |
+- qxl_release_fence_buffer_objects(release); |
242 |
+ |
243 |
+ out_free_bos: |
244 |
+ out_free_release: |
245 |
+diff --git a/drivers/infiniband/hw/mlx4/main.c b/drivers/infiniband/hw/mlx4/main.c |
246 |
+index 7e73a1a6cb67..3f8511104c5b 100644 |
247 |
+--- a/drivers/infiniband/hw/mlx4/main.c |
248 |
++++ b/drivers/infiniband/hw/mlx4/main.c |
249 |
+@@ -1614,8 +1614,9 @@ static int __mlx4_ib_create_default_rules( |
250 |
+ int i; |
251 |
+ |
252 |
+ for (i = 0; i < ARRAY_SIZE(pdefault_rules->rules_create_list); i++) { |
253 |
++ union ib_flow_spec ib_spec = {}; |
254 |
+ int ret; |
255 |
+- union ib_flow_spec ib_spec; |
256 |
++ |
257 |
+ switch (pdefault_rules->rules_create_list[i]) { |
258 |
+ case 0: |
259 |
+ /* no rule */ |
260 |
+diff --git a/drivers/infiniband/hw/mlx5/qp.c b/drivers/infiniband/hw/mlx5/qp.c |
261 |
+index 0cb60072c82f..d835ef2ce23c 100644 |
262 |
+--- a/drivers/infiniband/hw/mlx5/qp.c |
263 |
++++ b/drivers/infiniband/hw/mlx5/qp.c |
264 |
+@@ -4362,7 +4362,9 @@ static void to_rdma_ah_attr(struct mlx5_ib_dev *ibdev, |
265 |
+ rdma_ah_set_path_bits(ah_attr, path->grh_mlid & 0x7f); |
266 |
+ rdma_ah_set_static_rate(ah_attr, |
267 |
+ path->static_rate ? path->static_rate - 5 : 0); |
268 |
+- if (path->grh_mlid & (1 << 7)) { |
269 |
++ |
270 |
++ if (path->grh_mlid & (1 << 7) || |
271 |
++ ah_attr->type == RDMA_AH_ATTR_TYPE_ROCE) { |
272 |
+ u32 tc_fl = be32_to_cpu(path->tclass_flowlabel); |
273 |
+ |
274 |
+ rdma_ah_set_grh(ah_attr, NULL, |
275 |
+diff --git a/drivers/iommu/amd_iommu_init.c b/drivers/iommu/amd_iommu_init.c |
276 |
+index 4d2920988d60..6c228144b3da 100644 |
277 |
+--- a/drivers/iommu/amd_iommu_init.c |
278 |
++++ b/drivers/iommu/amd_iommu_init.c |
279 |
+@@ -2809,7 +2809,7 @@ static int __init parse_amd_iommu_intr(char *str) |
280 |
+ { |
281 |
+ for (; *str; ++str) { |
282 |
+ if (strncmp(str, "legacy", 6) == 0) { |
283 |
+- amd_iommu_guest_ir = AMD_IOMMU_GUEST_IR_LEGACY; |
284 |
++ amd_iommu_guest_ir = AMD_IOMMU_GUEST_IR_LEGACY_GA; |
285 |
+ break; |
286 |
+ } |
287 |
+ if (strncmp(str, "vapic", 5) == 0) { |
288 |
+diff --git a/drivers/iommu/qcom_iommu.c b/drivers/iommu/qcom_iommu.c |
289 |
+index b08002851e06..920a5df319bc 100644 |
290 |
+--- a/drivers/iommu/qcom_iommu.c |
291 |
++++ b/drivers/iommu/qcom_iommu.c |
292 |
+@@ -775,8 +775,11 @@ static int qcom_iommu_device_probe(struct platform_device *pdev) |
293 |
+ qcom_iommu->dev = dev; |
294 |
+ |
295 |
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
296 |
+- if (res) |
297 |
++ if (res) { |
298 |
+ qcom_iommu->local_base = devm_ioremap_resource(dev, res); |
299 |
++ if (IS_ERR(qcom_iommu->local_base)) |
300 |
++ return PTR_ERR(qcom_iommu->local_base); |
301 |
++ } |
302 |
+ |
303 |
+ qcom_iommu->iface_clk = devm_clk_get(dev, "iface"); |
304 |
+ if (IS_ERR(qcom_iommu->iface_clk)) { |
305 |
+diff --git a/drivers/md/dm-verity-fec.c b/drivers/md/dm-verity-fec.c |
306 |
+index 285148100cde..0fe6cc3007f5 100644 |
307 |
+--- a/drivers/md/dm-verity-fec.c |
308 |
++++ b/drivers/md/dm-verity-fec.c |
309 |
+@@ -436,7 +436,7 @@ int verity_fec_decode(struct dm_verity *v, struct dm_verity_io *io, |
310 |
+ fio->level++; |
311 |
+ |
312 |
+ if (type == DM_VERITY_BLOCK_TYPE_METADATA) |
313 |
+- block += v->data_blocks; |
314 |
++ block = block - v->hash_start + v->data_blocks; |
315 |
+ |
316 |
+ /* |
317 |
+ * For RS(M, N), the continuous FEC data is divided into blocks of N |
318 |
+diff --git a/drivers/mmc/host/sdhci-pci-core.c b/drivers/mmc/host/sdhci-pci-core.c |
319 |
+index 0e386f5cc836..4bc89551229b 100644 |
320 |
+--- a/drivers/mmc/host/sdhci-pci-core.c |
321 |
++++ b/drivers/mmc/host/sdhci-pci-core.c |
322 |
+@@ -490,6 +490,9 @@ static int intel_select_drive_strength(struct mmc_card *card, |
323 |
+ struct sdhci_pci_slot *slot = sdhci_priv(host); |
324 |
+ struct intel_host *intel_host = sdhci_pci_priv(slot); |
325 |
+ |
326 |
++ if (!(mmc_driver_type_mask(intel_host->drv_strength) & card_drv)) |
327 |
++ return 0; |
328 |
++ |
329 |
+ return intel_host->drv_strength; |
330 |
+ } |
331 |
+ |
332 |
+diff --git a/drivers/mmc/host/sdhci-xenon.c b/drivers/mmc/host/sdhci-xenon.c |
333 |
+index a0b5089b3274..fafb02644efd 100644 |
334 |
+--- a/drivers/mmc/host/sdhci-xenon.c |
335 |
++++ b/drivers/mmc/host/sdhci-xenon.c |
336 |
+@@ -238,6 +238,16 @@ static void xenon_voltage_switch(struct sdhci_host *host) |
337 |
+ { |
338 |
+ /* Wait for 5ms after set 1.8V signal enable bit */ |
339 |
+ usleep_range(5000, 5500); |
340 |
++ |
341 |
++ /* |
342 |
++ * For some reason the controller's Host Control2 register reports |
343 |
++ * the bit representing 1.8V signaling as 0 when read after it was |
344 |
++ * written as 1. Subsequent read reports 1. |
345 |
++ * |
346 |
++ * Since this may cause some issues, do an empty read of the Host |
347 |
++ * Control2 register here to circumvent this. |
348 |
++ */ |
349 |
++ sdhci_readw(host, SDHCI_HOST_CONTROL2); |
350 |
+ } |
351 |
+ |
352 |
+ static const struct sdhci_ops sdhci_xenon_ops = { |
353 |
+diff --git a/drivers/target/target_core_iblock.c b/drivers/target/target_core_iblock.c |
354 |
+index 60429011292a..2a9e023f5429 100644 |
355 |
+--- a/drivers/target/target_core_iblock.c |
356 |
++++ b/drivers/target/target_core_iblock.c |
357 |
+@@ -447,7 +447,7 @@ iblock_execute_zero_out(struct block_device *bdev, struct se_cmd *cmd) |
358 |
+ target_to_linux_sector(dev, cmd->t_task_lba), |
359 |
+ target_to_linux_sector(dev, |
360 |
+ sbc_get_write_same_sectors(cmd)), |
361 |
+- GFP_KERNEL, false); |
362 |
++ GFP_KERNEL, BLKDEV_ZERO_NOUNMAP); |
363 |
+ if (ret) |
364 |
+ return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; |
365 |
+ |
366 |
+diff --git a/drivers/vfio/vfio_iommu_type1.c b/drivers/vfio/vfio_iommu_type1.c |
367 |
+index f77a9b3370b5..35a3750a6ddd 100644 |
368 |
+--- a/drivers/vfio/vfio_iommu_type1.c |
369 |
++++ b/drivers/vfio/vfio_iommu_type1.c |
370 |
+@@ -378,8 +378,8 @@ static int vaddr_get_pfn(struct mm_struct *mm, unsigned long vaddr, |
371 |
+ vma = find_vma_intersection(mm, vaddr, vaddr + 1); |
372 |
+ |
373 |
+ if (vma && vma->vm_flags & VM_PFNMAP) { |
374 |
+- *pfn = ((vaddr - vma->vm_start) >> PAGE_SHIFT) + vma->vm_pgoff; |
375 |
+- if (is_invalid_reserved_pfn(*pfn)) |
376 |
++ if (!follow_pfn(vma, vaddr, pfn) && |
377 |
++ is_invalid_reserved_pfn(*pfn)) |
378 |
+ ret = 0; |
379 |
+ } |
380 |
+ |
381 |
+@@ -591,7 +591,7 @@ static int vfio_iommu_type1_pin_pages(void *iommu_data, |
382 |
+ continue; |
383 |
+ } |
384 |
+ |
385 |
+- remote_vaddr = dma->vaddr + iova - dma->iova; |
386 |
++ remote_vaddr = dma->vaddr + (iova - dma->iova); |
387 |
+ ret = vfio_pin_page_external(dma, remote_vaddr, &phys_pfn[i], |
388 |
+ do_accounting); |
389 |
+ if (ret) |
390 |
+diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c |
391 |
+index fd15f396b3a0..51e26f90f0bb 100644 |
392 |
+--- a/fs/btrfs/extent-tree.c |
393 |
++++ b/fs/btrfs/extent-tree.c |
394 |
+@@ -10554,7 +10554,7 @@ int btrfs_remove_block_group(struct btrfs_trans_handle *trans, |
395 |
+ path = btrfs_alloc_path(); |
396 |
+ if (!path) { |
397 |
+ ret = -ENOMEM; |
398 |
+- goto out; |
399 |
++ goto out_put_group; |
400 |
+ } |
401 |
+ |
402 |
+ /* |
403 |
+@@ -10591,7 +10591,7 @@ int btrfs_remove_block_group(struct btrfs_trans_handle *trans, |
404 |
+ ret = btrfs_orphan_add(trans, BTRFS_I(inode)); |
405 |
+ if (ret) { |
406 |
+ btrfs_add_delayed_iput(inode); |
407 |
+- goto out; |
408 |
++ goto out_put_group; |
409 |
+ } |
410 |
+ clear_nlink(inode); |
411 |
+ /* One for the block groups ref */ |
412 |
+@@ -10614,13 +10614,13 @@ int btrfs_remove_block_group(struct btrfs_trans_handle *trans, |
413 |
+ |
414 |
+ ret = btrfs_search_slot(trans, tree_root, &key, path, -1, 1); |
415 |
+ if (ret < 0) |
416 |
+- goto out; |
417 |
++ goto out_put_group; |
418 |
+ if (ret > 0) |
419 |
+ btrfs_release_path(path); |
420 |
+ if (ret == 0) { |
421 |
+ ret = btrfs_del_item(trans, tree_root, path); |
422 |
+ if (ret) |
423 |
+- goto out; |
424 |
++ goto out_put_group; |
425 |
+ btrfs_release_path(path); |
426 |
+ } |
427 |
+ |
428 |
+@@ -10778,9 +10778,9 @@ int btrfs_remove_block_group(struct btrfs_trans_handle *trans, |
429 |
+ |
430 |
+ ret = remove_block_group_free_space(trans, fs_info, block_group); |
431 |
+ if (ret) |
432 |
+- goto out; |
433 |
++ goto out_put_group; |
434 |
+ |
435 |
+- btrfs_put_block_group(block_group); |
436 |
++ /* Once for the block groups rbtree */ |
437 |
+ btrfs_put_block_group(block_group); |
438 |
+ |
439 |
+ ret = btrfs_search_slot(trans, root, &key, path, -1, 1); |
440 |
+@@ -10790,6 +10790,10 @@ int btrfs_remove_block_group(struct btrfs_trans_handle *trans, |
441 |
+ goto out; |
442 |
+ |
443 |
+ ret = btrfs_del_item(trans, root, path); |
444 |
++ |
445 |
++out_put_group: |
446 |
++ /* Once for the lookup reference */ |
447 |
++ btrfs_put_block_group(block_group); |
448 |
+ out: |
449 |
+ btrfs_free_path(path); |
450 |
+ return ret; |
451 |
+diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c |
452 |
+index 0b62c8080af0..bcfb7a772c8e 100644 |
453 |
+--- a/fs/btrfs/tree-log.c |
454 |
++++ b/fs/btrfs/tree-log.c |
455 |
+@@ -4155,6 +4155,9 @@ static int btrfs_log_prealloc_extents(struct btrfs_trans_handle *trans, |
456 |
+ const u64 ino = btrfs_ino(inode); |
457 |
+ struct btrfs_path *dst_path = NULL; |
458 |
+ bool dropped_extents = false; |
459 |
++ u64 truncate_offset = i_size; |
460 |
++ struct extent_buffer *leaf; |
461 |
++ int slot; |
462 |
+ int ins_nr = 0; |
463 |
+ int start_slot; |
464 |
+ int ret; |
465 |
+@@ -4169,9 +4172,43 @@ static int btrfs_log_prealloc_extents(struct btrfs_trans_handle *trans, |
466 |
+ if (ret < 0) |
467 |
+ goto out; |
468 |
+ |
469 |
++ /* |
470 |
++ * We must check if there is a prealloc extent that starts before the |
471 |
++ * i_size and crosses the i_size boundary. This is to ensure later we |
472 |
++ * truncate down to the end of that extent and not to the i_size, as |
473 |
++ * otherwise we end up losing part of the prealloc extent after a log |
474 |
++ * replay and with an implicit hole if there is another prealloc extent |
475 |
++ * that starts at an offset beyond i_size. |
476 |
++ */ |
477 |
++ ret = btrfs_previous_item(root, path, ino, BTRFS_EXTENT_DATA_KEY); |
478 |
++ if (ret < 0) |
479 |
++ goto out; |
480 |
++ |
481 |
++ if (ret == 0) { |
482 |
++ struct btrfs_file_extent_item *ei; |
483 |
++ |
484 |
++ leaf = path->nodes[0]; |
485 |
++ slot = path->slots[0]; |
486 |
++ ei = btrfs_item_ptr(leaf, slot, struct btrfs_file_extent_item); |
487 |
++ |
488 |
++ if (btrfs_file_extent_type(leaf, ei) == |
489 |
++ BTRFS_FILE_EXTENT_PREALLOC) { |
490 |
++ u64 extent_end; |
491 |
++ |
492 |
++ btrfs_item_key_to_cpu(leaf, &key, slot); |
493 |
++ extent_end = key.offset + |
494 |
++ btrfs_file_extent_num_bytes(leaf, ei); |
495 |
++ |
496 |
++ if (extent_end > i_size) |
497 |
++ truncate_offset = extent_end; |
498 |
++ } |
499 |
++ } else { |
500 |
++ ret = 0; |
501 |
++ } |
502 |
++ |
503 |
+ while (true) { |
504 |
+- struct extent_buffer *leaf = path->nodes[0]; |
505 |
+- int slot = path->slots[0]; |
506 |
++ leaf = path->nodes[0]; |
507 |
++ slot = path->slots[0]; |
508 |
+ |
509 |
+ if (slot >= btrfs_header_nritems(leaf)) { |
510 |
+ if (ins_nr > 0) { |
511 |
+@@ -4209,7 +4246,7 @@ static int btrfs_log_prealloc_extents(struct btrfs_trans_handle *trans, |
512 |
+ ret = btrfs_truncate_inode_items(trans, |
513 |
+ root->log_root, |
514 |
+ &inode->vfs_inode, |
515 |
+- i_size, |
516 |
++ truncate_offset, |
517 |
+ BTRFS_EXTENT_DATA_KEY); |
518 |
+ } while (ret == -EAGAIN); |
519 |
+ if (ret) |
520 |
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c |
521 |
+index 1bc0037c50aa..5f03a4fabeaa 100644 |
522 |
+--- a/fs/ext4/inode.c |
523 |
++++ b/fs/ext4/inode.c |
524 |
+@@ -4715,7 +4715,7 @@ struct inode *__ext4_iget(struct super_block *sb, unsigned long ino, |
525 |
+ gid_t i_gid; |
526 |
+ projid_t i_projid; |
527 |
+ |
528 |
+- if (((flags & EXT4_IGET_NORMAL) && |
529 |
++ if ((!(flags & EXT4_IGET_SPECIAL) && |
530 |
+ (ino < EXT4_FIRST_INO(sb) && ino != EXT4_ROOT_INO)) || |
531 |
+ (ino < EXT4_ROOT_INO) || |
532 |
+ (ino > le32_to_cpu(EXT4_SB(sb)->s_es->s_inodes_count))) { |
533 |
+diff --git a/fs/nfs/nfs3acl.c b/fs/nfs/nfs3acl.c |
534 |
+index 7173a4ee862c..5e9f9c70fe70 100644 |
535 |
+--- a/fs/nfs/nfs3acl.c |
536 |
++++ b/fs/nfs/nfs3acl.c |
537 |
+@@ -253,37 +253,45 @@ int nfs3_proc_setacls(struct inode *inode, struct posix_acl *acl, |
538 |
+ |
539 |
+ int nfs3_set_acl(struct inode *inode, struct posix_acl *acl, int type) |
540 |
+ { |
541 |
+- struct posix_acl *alloc = NULL, *dfacl = NULL; |
542 |
++ struct posix_acl *orig = acl, *dfacl = NULL, *alloc; |
543 |
+ int status; |
544 |
+ |
545 |
+ if (S_ISDIR(inode->i_mode)) { |
546 |
+ switch(type) { |
547 |
+ case ACL_TYPE_ACCESS: |
548 |
+- alloc = dfacl = get_acl(inode, ACL_TYPE_DEFAULT); |
549 |
++ alloc = get_acl(inode, ACL_TYPE_DEFAULT); |
550 |
+ if (IS_ERR(alloc)) |
551 |
+ goto fail; |
552 |
++ dfacl = alloc; |
553 |
+ break; |
554 |
+ |
555 |
+ case ACL_TYPE_DEFAULT: |
556 |
+- dfacl = acl; |
557 |
+- alloc = acl = get_acl(inode, ACL_TYPE_ACCESS); |
558 |
++ alloc = get_acl(inode, ACL_TYPE_ACCESS); |
559 |
+ if (IS_ERR(alloc)) |
560 |
+ goto fail; |
561 |
++ dfacl = acl; |
562 |
++ acl = alloc; |
563 |
+ break; |
564 |
+ } |
565 |
+ } |
566 |
+ |
567 |
+ if (acl == NULL) { |
568 |
+- alloc = acl = posix_acl_from_mode(inode->i_mode, GFP_KERNEL); |
569 |
++ alloc = posix_acl_from_mode(inode->i_mode, GFP_KERNEL); |
570 |
+ if (IS_ERR(alloc)) |
571 |
+ goto fail; |
572 |
++ acl = alloc; |
573 |
+ } |
574 |
+ status = __nfs3_proc_setacls(inode, acl, dfacl); |
575 |
+- posix_acl_release(alloc); |
576 |
++out: |
577 |
++ if (acl != orig) |
578 |
++ posix_acl_release(acl); |
579 |
++ if (dfacl != orig) |
580 |
++ posix_acl_release(dfacl); |
581 |
+ return status; |
582 |
+ |
583 |
+ fail: |
584 |
+- return PTR_ERR(alloc); |
585 |
++ status = PTR_ERR(alloc); |
586 |
++ goto out; |
587 |
+ } |
588 |
+ |
589 |
+ const struct xattr_handler *nfs3_xattr_handlers[] = { |
590 |
+diff --git a/kernel/power/hibernate.c b/kernel/power/hibernate.c |
591 |
+index 2d6d14ad7b4f..2e65aacfa116 100644 |
592 |
+--- a/kernel/power/hibernate.c |
593 |
++++ b/kernel/power/hibernate.c |
594 |
+@@ -892,6 +892,13 @@ static int software_resume(void) |
595 |
+ error = freeze_processes(); |
596 |
+ if (error) |
597 |
+ goto Close_Finish; |
598 |
++ |
599 |
++ error = freeze_kernel_threads(); |
600 |
++ if (error) { |
601 |
++ thaw_processes(); |
602 |
++ goto Close_Finish; |
603 |
++ } |
604 |
++ |
605 |
+ error = load_image_and_restore(); |
606 |
+ thaw_processes(); |
607 |
+ Finish: |
608 |
+diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c |
609 |
+index 5f7bfc65c446..5def19ec1179 100644 |
610 |
+--- a/security/selinux/hooks.c |
611 |
++++ b/security/selinux/hooks.c |
612 |
+@@ -5121,39 +5121,59 @@ static int selinux_tun_dev_open(void *security) |
613 |
+ |
614 |
+ static int selinux_nlmsg_perm(struct sock *sk, struct sk_buff *skb) |
615 |
+ { |
616 |
+- int err = 0; |
617 |
+- u32 perm; |
618 |
++ int rc = 0; |
619 |
++ unsigned int msg_len; |
620 |
++ unsigned int data_len = skb->len; |
621 |
++ unsigned char *data = skb->data; |
622 |
+ struct nlmsghdr *nlh; |
623 |
+ struct sk_security_struct *sksec = sk->sk_security; |
624 |
++ u16 sclass = sksec->sclass; |
625 |
++ u32 perm; |
626 |
+ |
627 |
+- if (skb->len < NLMSG_HDRLEN) { |
628 |
+- err = -EINVAL; |
629 |
+- goto out; |
630 |
+- } |
631 |
+- nlh = nlmsg_hdr(skb); |
632 |
++ while (data_len >= nlmsg_total_size(0)) { |
633 |
++ nlh = (struct nlmsghdr *)data; |
634 |
+ |
635 |
+- err = selinux_nlmsg_lookup(sksec->sclass, nlh->nlmsg_type, &perm); |
636 |
+- if (err) { |
637 |
+- if (err == -EINVAL) { |
638 |
++ /* NOTE: the nlmsg_len field isn't reliably set by some netlink |
639 |
++ * users which means we can't reject skb's with bogus |
640 |
++ * length fields; our solution is to follow what |
641 |
++ * netlink_rcv_skb() does and simply skip processing at |
642 |
++ * messages with length fields that are clearly junk |
643 |
++ */ |
644 |
++ if (nlh->nlmsg_len < NLMSG_HDRLEN || nlh->nlmsg_len > data_len) |
645 |
++ return 0; |
646 |
++ |
647 |
++ rc = selinux_nlmsg_lookup(sclass, nlh->nlmsg_type, &perm); |
648 |
++ if (rc == 0) { |
649 |
++ rc = sock_has_perm(sk, perm); |
650 |
++ if (rc) |
651 |
++ return rc; |
652 |
++ } else if (rc == -EINVAL) { |
653 |
++ /* -EINVAL is a missing msg/perm mapping */ |
654 |
+ pr_warn_ratelimited("SELinux: unrecognized netlink" |
655 |
+- " message: protocol=%hu nlmsg_type=%hu sclass=%s" |
656 |
+- " pig=%d comm=%s\n", |
657 |
+- sk->sk_protocol, nlh->nlmsg_type, |
658 |
+- secclass_map[sksec->sclass - 1].name, |
659 |
+- task_pid_nr(current), current->comm); |
660 |
+- if (!selinux_enforcing || security_get_allow_unknown()) |
661 |
+- err = 0; |
662 |
++ " message: protocol=%hu nlmsg_type=%hu sclass=%s" |
663 |
++ " pid=%d comm=%s\n", |
664 |
++ sk->sk_protocol, nlh->nlmsg_type, |
665 |
++ secclass_map[sclass - 1].name, |
666 |
++ task_pid_nr(current), current->comm); |
667 |
++ if (selinux_enforcing && !security_get_allow_unknown()) |
668 |
++ return rc; |
669 |
++ rc = 0; |
670 |
++ } else if (rc == -ENOENT) { |
671 |
++ /* -ENOENT is a missing socket/class mapping, ignore */ |
672 |
++ rc = 0; |
673 |
++ } else { |
674 |
++ return rc; |
675 |
+ } |
676 |
+ |
677 |
+- /* Ignore */ |
678 |
+- if (err == -ENOENT) |
679 |
+- err = 0; |
680 |
+- goto out; |
681 |
++ /* move to the next message after applying netlink padding */ |
682 |
++ msg_len = NLMSG_ALIGN(nlh->nlmsg_len); |
683 |
++ if (msg_len >= data_len) |
684 |
++ return 0; |
685 |
++ data_len -= msg_len; |
686 |
++ data += msg_len; |
687 |
+ } |
688 |
+ |
689 |
+- err = sock_has_perm(sk, perm); |
690 |
+-out: |
691 |
+- return err; |
692 |
++ return rc; |
693 |
+ } |
694 |
+ |
695 |
+ #ifdef CONFIG_NETFILTER |
696 |
+diff --git a/sound/core/oss/pcm_plugin.c b/sound/core/oss/pcm_plugin.c |
697 |
+index 3ecc070738e8..c1315ce98b54 100644 |
698 |
+--- a/sound/core/oss/pcm_plugin.c |
699 |
++++ b/sound/core/oss/pcm_plugin.c |
700 |
+@@ -211,21 +211,23 @@ static snd_pcm_sframes_t plug_client_size(struct snd_pcm_substream *plug, |
701 |
+ if (stream == SNDRV_PCM_STREAM_PLAYBACK) { |
702 |
+ plugin = snd_pcm_plug_last(plug); |
703 |
+ while (plugin && drv_frames > 0) { |
704 |
+- if (check_size && drv_frames > plugin->buf_frames) |
705 |
+- drv_frames = plugin->buf_frames; |
706 |
+ plugin_prev = plugin->prev; |
707 |
+ if (plugin->src_frames) |
708 |
+ drv_frames = plugin->src_frames(plugin, drv_frames); |
709 |
++ if (check_size && plugin->buf_frames && |
710 |
++ drv_frames > plugin->buf_frames) |
711 |
++ drv_frames = plugin->buf_frames; |
712 |
+ plugin = plugin_prev; |
713 |
+ } |
714 |
+ } else if (stream == SNDRV_PCM_STREAM_CAPTURE) { |
715 |
+ plugin = snd_pcm_plug_first(plug); |
716 |
+ while (plugin && drv_frames > 0) { |
717 |
+ plugin_next = plugin->next; |
718 |
++ if (check_size && plugin->buf_frames && |
719 |
++ drv_frames > plugin->buf_frames) |
720 |
++ drv_frames = plugin->buf_frames; |
721 |
+ if (plugin->dst_frames) |
722 |
+ drv_frames = plugin->dst_frames(plugin, drv_frames); |
723 |
+- if (check_size && drv_frames > plugin->buf_frames) |
724 |
+- drv_frames = plugin->buf_frames; |
725 |
+ plugin = plugin_next; |
726 |
+ } |
727 |
+ } else |
728 |
+@@ -251,26 +253,28 @@ static snd_pcm_sframes_t plug_slave_size(struct snd_pcm_substream *plug, |
729 |
+ plugin = snd_pcm_plug_first(plug); |
730 |
+ while (plugin && frames > 0) { |
731 |
+ plugin_next = plugin->next; |
732 |
++ if (check_size && plugin->buf_frames && |
733 |
++ frames > plugin->buf_frames) |
734 |
++ frames = plugin->buf_frames; |
735 |
+ if (plugin->dst_frames) { |
736 |
+ frames = plugin->dst_frames(plugin, frames); |
737 |
+ if (frames < 0) |
738 |
+ return frames; |
739 |
+ } |
740 |
+- if (check_size && frames > plugin->buf_frames) |
741 |
+- frames = plugin->buf_frames; |
742 |
+ plugin = plugin_next; |
743 |
+ } |
744 |
+ } else if (stream == SNDRV_PCM_STREAM_CAPTURE) { |
745 |
+ plugin = snd_pcm_plug_last(plug); |
746 |
+ while (plugin) { |
747 |
+- if (check_size && frames > plugin->buf_frames) |
748 |
+- frames = plugin->buf_frames; |
749 |
+ plugin_prev = plugin->prev; |
750 |
+ if (plugin->src_frames) { |
751 |
+ frames = plugin->src_frames(plugin, frames); |
752 |
+ if (frames < 0) |
753 |
+ return frames; |
754 |
+ } |
755 |
++ if (check_size && plugin->buf_frames && |
756 |
++ frames > plugin->buf_frames) |
757 |
++ frames = plugin->buf_frames; |
758 |
+ plugin = plugin_prev; |
759 |
+ } |
760 |
+ } else |
761 |
+diff --git a/sound/isa/opti9xx/miro.c b/sound/isa/opti9xx/miro.c |
762 |
+index 8894c7c18ad6..d92c3c6b6051 100644 |
763 |
+--- a/sound/isa/opti9xx/miro.c |
764 |
++++ b/sound/isa/opti9xx/miro.c |
765 |
+@@ -875,10 +875,13 @@ static void snd_miro_write(struct snd_miro *chip, unsigned char reg, |
766 |
+ spin_unlock_irqrestore(&chip->lock, flags); |
767 |
+ } |
768 |
+ |
769 |
++static inline void snd_miro_write_mask(struct snd_miro *chip, |
770 |
++ unsigned char reg, unsigned char value, unsigned char mask) |
771 |
++{ |
772 |
++ unsigned char oldval = snd_miro_read(chip, reg); |
773 |
+ |
774 |
+-#define snd_miro_write_mask(chip, reg, value, mask) \ |
775 |
+- snd_miro_write(chip, reg, \ |
776 |
+- (snd_miro_read(chip, reg) & ~(mask)) | ((value) & (mask))) |
777 |
++ snd_miro_write(chip, reg, (oldval & ~mask) | (value & mask)); |
778 |
++} |
779 |
+ |
780 |
+ /* |
781 |
+ * Proc Interface |
782 |
+diff --git a/sound/isa/opti9xx/opti92x-ad1848.c b/sound/isa/opti9xx/opti92x-ad1848.c |
783 |
+index 505cd81e19fa..4ef3caaf4354 100644 |
784 |
+--- a/sound/isa/opti9xx/opti92x-ad1848.c |
785 |
++++ b/sound/isa/opti9xx/opti92x-ad1848.c |
786 |
+@@ -327,10 +327,13 @@ static void snd_opti9xx_write(struct snd_opti9xx *chip, unsigned char reg, |
787 |
+ } |
788 |
+ |
789 |
+ |
790 |
+-#define snd_opti9xx_write_mask(chip, reg, value, mask) \ |
791 |
+- snd_opti9xx_write(chip, reg, \ |
792 |
+- (snd_opti9xx_read(chip, reg) & ~(mask)) | ((value) & (mask))) |
793 |
++static inline void snd_opti9xx_write_mask(struct snd_opti9xx *chip, |
794 |
++ unsigned char reg, unsigned char value, unsigned char mask) |
795 |
++{ |
796 |
++ unsigned char oldval = snd_opti9xx_read(chip, reg); |
797 |
+ |
798 |
++ snd_opti9xx_write(chip, reg, (oldval & ~mask) | (value & mask)); |
799 |
++} |
800 |
+ |
801 |
+ static int snd_opti9xx_configure(struct snd_opti9xx *chip, |
802 |
+ long port, |
803 |
+diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c |
804 |
+index 12913368c231..435c0efb9bf2 100644 |
805 |
+--- a/sound/pci/hda/patch_hdmi.c |
806 |
++++ b/sound/pci/hda/patch_hdmi.c |
807 |
+@@ -1849,8 +1849,10 @@ static bool check_non_pcm_per_cvt(struct hda_codec *codec, hda_nid_t cvt_nid) |
808 |
+ /* Add sanity check to pass klockwork check. |
809 |
+ * This should never happen. |
810 |
+ */ |
811 |
+- if (WARN_ON(spdif == NULL)) |
812 |
++ if (WARN_ON(spdif == NULL)) { |
813 |
++ mutex_unlock(&codec->spdif_mutex); |
814 |
+ return true; |
815 |
++ } |
816 |
+ non_pcm = !!(spdif->status & IEC958_AES0_NONAUDIO); |
817 |
+ mutex_unlock(&codec->spdif_mutex); |
818 |
+ return non_pcm; |
819 |
+diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c |
820 |
+index 288ea05dfa3c..b2aec97414fb 100644 |
821 |
+--- a/sound/pci/hda/patch_realtek.c |
822 |
++++ b/sound/pci/hda/patch_realtek.c |
823 |
+@@ -6590,6 +6590,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { |
824 |
+ SND_PCI_QUIRK(0x1462, 0xb120, "MSI Cubi MS-B120", ALC283_FIXUP_HEADSET_MIC), |
825 |
+ SND_PCI_QUIRK(0x1462, 0xb171, "Cubi N 8GL (MS-B171)", ALC283_FIXUP_HEADSET_MIC), |
826 |
+ SND_PCI_QUIRK(0x17aa, 0x1036, "Lenovo P520", ALC233_FIXUP_LENOVO_MULTI_CODECS), |
827 |
++ SND_PCI_QUIRK(0x17aa, 0x1048, "ThinkCentre Station", ALC283_FIXUP_HEADSET_MIC), |
828 |
+ SND_PCI_QUIRK(0x17aa, 0x20f2, "Thinkpad SL410/510", ALC269_FIXUP_SKU_IGNORE), |
829 |
+ SND_PCI_QUIRK(0x17aa, 0x215e, "Thinkpad L512", ALC269_FIXUP_SKU_IGNORE), |
830 |
+ SND_PCI_QUIRK(0x17aa, 0x21b8, "Thinkpad Edge 14", ALC269_FIXUP_SKU_IGNORE), |