Contents of /trunk/kernel-alx/patches-5.4/0287-5.4.188-all-fixes.patch
Parent Directory | Revision Log
Revision 3637 -
(show annotations)
(download)
Mon Oct 24 12:40:44 2022 UTC (19 months, 1 week ago) by niro
File size: 39853 byte(s)
Mon Oct 24 12:40:44 2022 UTC (19 months, 1 week ago) by niro
File size: 39853 byte(s)
-add missing
1 | diff --git a/Makefile b/Makefile |
2 | index d07421bc5c2fb..8684857148066 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 = 187 |
10 | +SUBLEVEL = 188 |
11 | EXTRAVERSION = |
12 | NAME = Kleptomaniac Octopus |
13 | |
14 | diff --git a/arch/nds32/include/asm/uaccess.h b/arch/nds32/include/asm/uaccess.h |
15 | index 8916ad9f9f139..e205b1db8c807 100644 |
16 | --- a/arch/nds32/include/asm/uaccess.h |
17 | +++ b/arch/nds32/include/asm/uaccess.h |
18 | @@ -71,9 +71,7 @@ static inline void set_fs(mm_segment_t fs) |
19 | * versions are void (ie, don't return a value as such). |
20 | */ |
21 | |
22 | -#define get_user __get_user \ |
23 | - |
24 | -#define __get_user(x, ptr) \ |
25 | +#define get_user(x, ptr) \ |
26 | ({ \ |
27 | long __gu_err = 0; \ |
28 | __get_user_check((x), (ptr), __gu_err); \ |
29 | @@ -86,6 +84,14 @@ static inline void set_fs(mm_segment_t fs) |
30 | (void)0; \ |
31 | }) |
32 | |
33 | +#define __get_user(x, ptr) \ |
34 | +({ \ |
35 | + long __gu_err = 0; \ |
36 | + const __typeof__(*(ptr)) __user *__p = (ptr); \ |
37 | + __get_user_err((x), __p, (__gu_err)); \ |
38 | + __gu_err; \ |
39 | +}) |
40 | + |
41 | #define __get_user_check(x, ptr, err) \ |
42 | ({ \ |
43 | const __typeof__(*(ptr)) __user *__p = (ptr); \ |
44 | @@ -166,12 +172,18 @@ do { \ |
45 | : "r"(addr), "i"(-EFAULT) \ |
46 | : "cc") |
47 | |
48 | -#define put_user __put_user \ |
49 | +#define put_user(x, ptr) \ |
50 | +({ \ |
51 | + long __pu_err = 0; \ |
52 | + __put_user_check((x), (ptr), __pu_err); \ |
53 | + __pu_err; \ |
54 | +}) |
55 | |
56 | #define __put_user(x, ptr) \ |
57 | ({ \ |
58 | long __pu_err = 0; \ |
59 | - __put_user_err((x), (ptr), __pu_err); \ |
60 | + __typeof__(*(ptr)) __user *__p = (ptr); \ |
61 | + __put_user_err((x), __p, __pu_err); \ |
62 | __pu_err; \ |
63 | }) |
64 | |
65 | diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c |
66 | index 4137a7342d687..7b75658b7e9ac 100644 |
67 | --- a/arch/x86/kernel/acpi/boot.c |
68 | +++ b/arch/x86/kernel/acpi/boot.c |
69 | @@ -1339,6 +1339,17 @@ static int __init disable_acpi_pci(const struct dmi_system_id *d) |
70 | return 0; |
71 | } |
72 | |
73 | +static int __init disable_acpi_xsdt(const struct dmi_system_id *d) |
74 | +{ |
75 | + if (!acpi_force) { |
76 | + pr_notice("%s detected: force use of acpi=rsdt\n", d->ident); |
77 | + acpi_gbl_do_not_use_xsdt = TRUE; |
78 | + } else { |
79 | + pr_notice("Warning: DMI blacklist says broken, but acpi XSDT forced\n"); |
80 | + } |
81 | + return 0; |
82 | +} |
83 | + |
84 | static int __init dmi_disable_acpi(const struct dmi_system_id *d) |
85 | { |
86 | if (!acpi_force) { |
87 | @@ -1463,6 +1474,19 @@ static const struct dmi_system_id acpi_dmi_table[] __initconst = { |
88 | DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 360"), |
89 | }, |
90 | }, |
91 | + /* |
92 | + * Boxes that need ACPI XSDT use disabled due to corrupted tables |
93 | + */ |
94 | + { |
95 | + .callback = disable_acpi_xsdt, |
96 | + .ident = "Advantech DAC-BJ01", |
97 | + .matches = { |
98 | + DMI_MATCH(DMI_SYS_VENDOR, "NEC"), |
99 | + DMI_MATCH(DMI_PRODUCT_NAME, "Bearlake CRB Board"), |
100 | + DMI_MATCH(DMI_BIOS_VERSION, "V1.12"), |
101 | + DMI_MATCH(DMI_BIOS_DATE, "02/01/2011"), |
102 | + }, |
103 | + }, |
104 | {} |
105 | }; |
106 | |
107 | diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c |
108 | index 4e0aea5f008e3..974c2df13da1d 100644 |
109 | --- a/drivers/acpi/battery.c |
110 | +++ b/drivers/acpi/battery.c |
111 | @@ -77,6 +77,10 @@ extern void *acpi_unlock_battery_dir(struct proc_dir_entry *acpi_battery_dir); |
112 | |
113 | static const struct acpi_device_id battery_device_ids[] = { |
114 | {"PNP0C0A", 0}, |
115 | + |
116 | + /* Microsoft Surface Go 3 */ |
117 | + {"MSHW0146", 0}, |
118 | + |
119 | {"", 0}, |
120 | }; |
121 | |
122 | @@ -1403,6 +1407,14 @@ static const struct dmi_system_id bat_dmi_table[] __initconst = { |
123 | DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad"), |
124 | }, |
125 | }, |
126 | + { |
127 | + /* Microsoft Surface Go 3 */ |
128 | + .callback = battery_notification_delay_quirk, |
129 | + .matches = { |
130 | + DMI_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"), |
131 | + DMI_MATCH(DMI_PRODUCT_NAME, "Surface Go 3"), |
132 | + }, |
133 | + }, |
134 | {}, |
135 | }; |
136 | |
137 | diff --git a/drivers/acpi/video_detect.c b/drivers/acpi/video_detect.c |
138 | index e7978d983b263..de4142723ff48 100644 |
139 | --- a/drivers/acpi/video_detect.c |
140 | +++ b/drivers/acpi/video_detect.c |
141 | @@ -372,6 +372,81 @@ static const struct dmi_system_id video_detect_dmi_table[] = { |
142 | DMI_MATCH(DMI_BOARD_NAME, "BA51_MV"), |
143 | }, |
144 | }, |
145 | + /* |
146 | + * Clevo NL5xRU and NL5xNU/TUXEDO Aura 15 Gen1 and Gen2 have both a |
147 | + * working native and video interface. However the default detection |
148 | + * mechanism first registers the video interface before unregistering |
149 | + * it again and switching to the native interface during boot. This |
150 | + * results in a dangling SBIOS request for backlight change for some |
151 | + * reason, causing the backlight to switch to ~2% once per boot on the |
152 | + * first power cord connect or disconnect event. Setting the native |
153 | + * interface explicitly circumvents this buggy behaviour, by avoiding |
154 | + * the unregistering process. |
155 | + */ |
156 | + { |
157 | + .callback = video_detect_force_native, |
158 | + .ident = "Clevo NL5xRU", |
159 | + .matches = { |
160 | + DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"), |
161 | + DMI_MATCH(DMI_BOARD_NAME, "NL5xRU"), |
162 | + }, |
163 | + }, |
164 | + { |
165 | + .callback = video_detect_force_native, |
166 | + .ident = "Clevo NL5xRU", |
167 | + .matches = { |
168 | + DMI_MATCH(DMI_SYS_VENDOR, "SchenkerTechnologiesGmbH"), |
169 | + DMI_MATCH(DMI_BOARD_NAME, "NL5xRU"), |
170 | + }, |
171 | + }, |
172 | + { |
173 | + .callback = video_detect_force_native, |
174 | + .ident = "Clevo NL5xRU", |
175 | + .matches = { |
176 | + DMI_MATCH(DMI_SYS_VENDOR, "Notebook"), |
177 | + DMI_MATCH(DMI_BOARD_NAME, "NL5xRU"), |
178 | + }, |
179 | + }, |
180 | + { |
181 | + .callback = video_detect_force_native, |
182 | + .ident = "Clevo NL5xRU", |
183 | + .matches = { |
184 | + DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"), |
185 | + DMI_MATCH(DMI_BOARD_NAME, "AURA1501"), |
186 | + }, |
187 | + }, |
188 | + { |
189 | + .callback = video_detect_force_native, |
190 | + .ident = "Clevo NL5xRU", |
191 | + .matches = { |
192 | + DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"), |
193 | + DMI_MATCH(DMI_BOARD_NAME, "EDUBOOK1502"), |
194 | + }, |
195 | + }, |
196 | + { |
197 | + .callback = video_detect_force_native, |
198 | + .ident = "Clevo NL5xNU", |
199 | + .matches = { |
200 | + DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"), |
201 | + DMI_MATCH(DMI_BOARD_NAME, "NL5xNU"), |
202 | + }, |
203 | + }, |
204 | + { |
205 | + .callback = video_detect_force_native, |
206 | + .ident = "Clevo NL5xNU", |
207 | + .matches = { |
208 | + DMI_MATCH(DMI_SYS_VENDOR, "SchenkerTechnologiesGmbH"), |
209 | + DMI_MATCH(DMI_BOARD_NAME, "NL5xNU"), |
210 | + }, |
211 | + }, |
212 | + { |
213 | + .callback = video_detect_force_native, |
214 | + .ident = "Clevo NL5xNU", |
215 | + .matches = { |
216 | + DMI_MATCH(DMI_SYS_VENDOR, "Notebook"), |
217 | + DMI_MATCH(DMI_BOARD_NAME, "NL5xNU"), |
218 | + }, |
219 | + }, |
220 | |
221 | /* |
222 | * Desktops which falsely report a backlight and which our heuristics |
223 | diff --git a/drivers/char/tpm/tpm-dev-common.c b/drivers/char/tpm/tpm-dev-common.c |
224 | index 1784530b8387b..b99e1941c52c9 100644 |
225 | --- a/drivers/char/tpm/tpm-dev-common.c |
226 | +++ b/drivers/char/tpm/tpm-dev-common.c |
227 | @@ -70,7 +70,13 @@ static void tpm_dev_async_work(struct work_struct *work) |
228 | ret = tpm_dev_transmit(priv->chip, priv->space, priv->data_buffer, |
229 | sizeof(priv->data_buffer)); |
230 | tpm_put_ops(priv->chip); |
231 | - if (ret > 0) { |
232 | + |
233 | + /* |
234 | + * If ret is > 0 then tpm_dev_transmit returned the size of the |
235 | + * response. If ret is < 0 then tpm_dev_transmit failed and |
236 | + * returned an error code. |
237 | + */ |
238 | + if (ret != 0) { |
239 | priv->response_length = ret; |
240 | mod_timer(&priv->user_read_timer, jiffies + (120 * HZ)); |
241 | } |
242 | diff --git a/drivers/char/tpm/tpm2-space.c b/drivers/char/tpm/tpm2-space.c |
243 | index 97e916856cf3e..d2225020e4d2c 100644 |
244 | --- a/drivers/char/tpm/tpm2-space.c |
245 | +++ b/drivers/char/tpm/tpm2-space.c |
246 | @@ -58,12 +58,12 @@ int tpm2_init_space(struct tpm_space *space, unsigned int buf_size) |
247 | |
248 | void tpm2_del_space(struct tpm_chip *chip, struct tpm_space *space) |
249 | { |
250 | - mutex_lock(&chip->tpm_mutex); |
251 | - if (!tpm_chip_start(chip)) { |
252 | + |
253 | + if (tpm_try_get_ops(chip) == 0) { |
254 | tpm2_flush_sessions(chip, space); |
255 | - tpm_chip_stop(chip); |
256 | + tpm_put_ops(chip); |
257 | } |
258 | - mutex_unlock(&chip->tpm_mutex); |
259 | + |
260 | kfree(space->context_buf); |
261 | kfree(space->session_buf); |
262 | } |
263 | diff --git a/drivers/crypto/qat/qat_common/qat_crypto.c b/drivers/crypto/qat/qat_common/qat_crypto.c |
264 | index 3852d31ce0a4b..37a9f969c59cd 100644 |
265 | --- a/drivers/crypto/qat/qat_common/qat_crypto.c |
266 | +++ b/drivers/crypto/qat/qat_common/qat_crypto.c |
267 | @@ -170,6 +170,14 @@ int qat_crypto_dev_config(struct adf_accel_dev *accel_dev) |
268 | goto err; |
269 | if (adf_cfg_section_add(accel_dev, "Accelerator0")) |
270 | goto err; |
271 | + |
272 | + /* Temporarily set the number of crypto instances to zero to avoid |
273 | + * registering the crypto algorithms. |
274 | + * This will be removed when the algorithms will support the |
275 | + * CRYPTO_TFM_REQ_MAY_BACKLOG flag |
276 | + */ |
277 | + instances = 0; |
278 | + |
279 | for (i = 0; i < instances; i++) { |
280 | val = i; |
281 | snprintf(key, sizeof(key), ADF_CY "%d" ADF_RING_BANK_NUM, i); |
282 | diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c |
283 | index cc8031ae9aa3f..ce4e617a6ec49 100644 |
284 | --- a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c |
285 | +++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c |
286 | @@ -696,6 +696,12 @@ static int xgene_enet_rx_frame(struct xgene_enet_desc_ring *rx_ring, |
287 | buf_pool->rx_skb[skb_index] = NULL; |
288 | |
289 | datalen = xgene_enet_get_data_len(le64_to_cpu(raw_desc->m1)); |
290 | + |
291 | + /* strip off CRC as HW isn't doing this */ |
292 | + nv = GET_VAL(NV, le64_to_cpu(raw_desc->m0)); |
293 | + if (!nv) |
294 | + datalen -= 4; |
295 | + |
296 | skb_put(skb, datalen); |
297 | prefetch(skb->data - NET_IP_ALIGN); |
298 | skb->protocol = eth_type_trans(skb, ndev); |
299 | @@ -717,12 +723,8 @@ static int xgene_enet_rx_frame(struct xgene_enet_desc_ring *rx_ring, |
300 | } |
301 | } |
302 | |
303 | - nv = GET_VAL(NV, le64_to_cpu(raw_desc->m0)); |
304 | - if (!nv) { |
305 | - /* strip off CRC as HW isn't doing this */ |
306 | - datalen -= 4; |
307 | + if (!nv) |
308 | goto skip_jumbo; |
309 | - } |
310 | |
311 | slots = page_pool->slots - 1; |
312 | head = page_pool->head; |
313 | diff --git a/drivers/nfc/st21nfca/se.c b/drivers/nfc/st21nfca/se.c |
314 | index 6586378cacb05..a7ab6dab0f32d 100644 |
315 | --- a/drivers/nfc/st21nfca/se.c |
316 | +++ b/drivers/nfc/st21nfca/se.c |
317 | @@ -321,6 +321,11 @@ int st21nfca_connectivity_event_received(struct nfc_hci_dev *hdev, u8 host, |
318 | return -ENOMEM; |
319 | |
320 | transaction->aid_len = skb->data[1]; |
321 | + |
322 | + /* Checking if the length of the AID is valid */ |
323 | + if (transaction->aid_len > sizeof(transaction->aid)) |
324 | + return -EINVAL; |
325 | + |
326 | memcpy(transaction->aid, &skb->data[2], |
327 | transaction->aid_len); |
328 | |
329 | @@ -330,6 +335,11 @@ int st21nfca_connectivity_event_received(struct nfc_hci_dev *hdev, u8 host, |
330 | return -EPROTO; |
331 | |
332 | transaction->params_len = skb->data[transaction->aid_len + 3]; |
333 | + |
334 | + /* Total size is allocated (skb->len - 2) minus fixed array members */ |
335 | + if (transaction->params_len > ((skb->len - 2) - sizeof(struct nfc_evt_transaction))) |
336 | + return -EINVAL; |
337 | + |
338 | memcpy(transaction->params, skb->data + |
339 | transaction->aid_len + 4, transaction->params_len); |
340 | |
341 | diff --git a/drivers/staging/fbtft/fb_st7789v.c b/drivers/staging/fbtft/fb_st7789v.c |
342 | index 3c3f387936e80..30086ae03605f 100644 |
343 | --- a/drivers/staging/fbtft/fb_st7789v.c |
344 | +++ b/drivers/staging/fbtft/fb_st7789v.c |
345 | @@ -76,6 +76,8 @@ enum st7789v_command { |
346 | */ |
347 | static int init_display(struct fbtft_par *par) |
348 | { |
349 | + par->fbtftops.reset(par); |
350 | + |
351 | /* turn off sleep mode */ |
352 | write_reg(par, MIPI_DCS_EXIT_SLEEP_MODE); |
353 | mdelay(120); |
354 | diff --git a/drivers/thermal/intel/int340x_thermal/int3400_thermal.c b/drivers/thermal/intel/int340x_thermal/int3400_thermal.c |
355 | index 3517883b5cdb9..a31163547fbaa 100644 |
356 | --- a/drivers/thermal/intel/int340x_thermal/int3400_thermal.c |
357 | +++ b/drivers/thermal/intel/int340x_thermal/int3400_thermal.c |
358 | @@ -216,6 +216,10 @@ static void int3400_notify(acpi_handle handle, |
359 | thermal_prop[4] = NULL; |
360 | kobject_uevent_env(&priv->thermal->device.kobj, KOBJ_CHANGE, |
361 | thermal_prop); |
362 | + kfree(thermal_prop[0]); |
363 | + kfree(thermal_prop[1]); |
364 | + kfree(thermal_prop[2]); |
365 | + kfree(thermal_prop[3]); |
366 | break; |
367 | default: |
368 | /* Ignore unknown notification codes sent to INT3400 device */ |
369 | diff --git a/fs/nfsd/filecache.c b/fs/nfsd/filecache.c |
370 | index 662937472e9bd..79ad6b2c96082 100644 |
371 | --- a/fs/nfsd/filecache.c |
372 | +++ b/fs/nfsd/filecache.c |
373 | @@ -44,6 +44,17 @@ struct nfsd_fcache_bucket { |
374 | |
375 | static DEFINE_PER_CPU(unsigned long, nfsd_file_cache_hits); |
376 | |
377 | +struct nfsd_fcache_disposal { |
378 | + struct list_head list; |
379 | + struct work_struct work; |
380 | + struct net *net; |
381 | + spinlock_t lock; |
382 | + struct list_head freeme; |
383 | + struct rcu_head rcu; |
384 | +}; |
385 | + |
386 | +struct workqueue_struct *nfsd_filecache_wq __read_mostly; |
387 | + |
388 | static struct kmem_cache *nfsd_file_slab; |
389 | static struct kmem_cache *nfsd_file_mark_slab; |
390 | static struct nfsd_fcache_bucket *nfsd_file_hashtbl; |
391 | @@ -52,32 +63,21 @@ static long nfsd_file_lru_flags; |
392 | static struct fsnotify_group *nfsd_file_fsnotify_group; |
393 | static atomic_long_t nfsd_filecache_count; |
394 | static struct delayed_work nfsd_filecache_laundrette; |
395 | +static DEFINE_SPINLOCK(laundrette_lock); |
396 | +static LIST_HEAD(laundrettes); |
397 | |
398 | -enum nfsd_file_laundrette_ctl { |
399 | - NFSD_FILE_LAUNDRETTE_NOFLUSH = 0, |
400 | - NFSD_FILE_LAUNDRETTE_MAY_FLUSH |
401 | -}; |
402 | +static void nfsd_file_gc(void); |
403 | |
404 | static void |
405 | -nfsd_file_schedule_laundrette(enum nfsd_file_laundrette_ctl ctl) |
406 | +nfsd_file_schedule_laundrette(void) |
407 | { |
408 | long count = atomic_long_read(&nfsd_filecache_count); |
409 | |
410 | if (count == 0 || test_bit(NFSD_FILE_SHUTDOWN, &nfsd_file_lru_flags)) |
411 | return; |
412 | |
413 | - /* Be more aggressive about scanning if over the threshold */ |
414 | - if (count > NFSD_FILE_LRU_THRESHOLD) |
415 | - mod_delayed_work(system_wq, &nfsd_filecache_laundrette, 0); |
416 | - else |
417 | - schedule_delayed_work(&nfsd_filecache_laundrette, NFSD_LAUNDRETTE_DELAY); |
418 | - |
419 | - if (ctl == NFSD_FILE_LAUNDRETTE_NOFLUSH) |
420 | - return; |
421 | - |
422 | - /* ...and don't delay flushing if we're out of control */ |
423 | - if (count >= NFSD_FILE_LRU_LIMIT) |
424 | - flush_delayed_work(&nfsd_filecache_laundrette); |
425 | + queue_delayed_work(system_wq, &nfsd_filecache_laundrette, |
426 | + NFSD_LAUNDRETTE_DELAY); |
427 | } |
428 | |
429 | static void |
430 | @@ -260,8 +260,6 @@ nfsd_file_do_unhash(struct nfsd_file *nf) |
431 | nfsd_reset_boot_verifier(net_generic(nf->nf_net, nfsd_net_id)); |
432 | --nfsd_file_hashtbl[nf->nf_hashval].nfb_count; |
433 | hlist_del_rcu(&nf->nf_node); |
434 | - if (!list_empty(&nf->nf_lru)) |
435 | - list_lru_del(&nfsd_file_lru, &nf->nf_lru); |
436 | atomic_long_dec(&nfsd_filecache_count); |
437 | } |
438 | |
439 | @@ -270,6 +268,8 @@ nfsd_file_unhash(struct nfsd_file *nf) |
440 | { |
441 | if (test_and_clear_bit(NFSD_FILE_HASHED, &nf->nf_flags)) { |
442 | nfsd_file_do_unhash(nf); |
443 | + if (!list_empty(&nf->nf_lru)) |
444 | + list_lru_del(&nfsd_file_lru, &nf->nf_lru); |
445 | return true; |
446 | } |
447 | return false; |
448 | @@ -316,7 +316,9 @@ nfsd_file_put(struct nfsd_file *nf) |
449 | |
450 | set_bit(NFSD_FILE_REFERENCED, &nf->nf_flags); |
451 | if (nfsd_file_put_noref(nf) == 1 && is_hashed && unused) |
452 | - nfsd_file_schedule_laundrette(NFSD_FILE_LAUNDRETTE_MAY_FLUSH); |
453 | + nfsd_file_schedule_laundrette(); |
454 | + if (atomic_long_read(&nfsd_filecache_count) >= NFSD_FILE_LRU_LIMIT) |
455 | + nfsd_file_gc(); |
456 | } |
457 | |
458 | struct nfsd_file * |
459 | @@ -357,6 +359,58 @@ nfsd_file_dispose_list_sync(struct list_head *dispose) |
460 | flush_delayed_fput(); |
461 | } |
462 | |
463 | +static void |
464 | +nfsd_file_list_remove_disposal(struct list_head *dst, |
465 | + struct nfsd_fcache_disposal *l) |
466 | +{ |
467 | + spin_lock(&l->lock); |
468 | + list_splice_init(&l->freeme, dst); |
469 | + spin_unlock(&l->lock); |
470 | +} |
471 | + |
472 | +static void |
473 | +nfsd_file_list_add_disposal(struct list_head *files, struct net *net) |
474 | +{ |
475 | + struct nfsd_fcache_disposal *l; |
476 | + |
477 | + rcu_read_lock(); |
478 | + list_for_each_entry_rcu(l, &laundrettes, list) { |
479 | + if (l->net == net) { |
480 | + spin_lock(&l->lock); |
481 | + list_splice_tail_init(files, &l->freeme); |
482 | + spin_unlock(&l->lock); |
483 | + queue_work(nfsd_filecache_wq, &l->work); |
484 | + break; |
485 | + } |
486 | + } |
487 | + rcu_read_unlock(); |
488 | +} |
489 | + |
490 | +static void |
491 | +nfsd_file_list_add_pernet(struct list_head *dst, struct list_head *src, |
492 | + struct net *net) |
493 | +{ |
494 | + struct nfsd_file *nf, *tmp; |
495 | + |
496 | + list_for_each_entry_safe(nf, tmp, src, nf_lru) { |
497 | + if (nf->nf_net == net) |
498 | + list_move_tail(&nf->nf_lru, dst); |
499 | + } |
500 | +} |
501 | + |
502 | +static void |
503 | +nfsd_file_dispose_list_delayed(struct list_head *dispose) |
504 | +{ |
505 | + LIST_HEAD(list); |
506 | + struct nfsd_file *nf; |
507 | + |
508 | + while(!list_empty(dispose)) { |
509 | + nf = list_first_entry(dispose, struct nfsd_file, nf_lru); |
510 | + nfsd_file_list_add_pernet(&list, dispose, nf->nf_net); |
511 | + nfsd_file_list_add_disposal(&list, nf->nf_net); |
512 | + } |
513 | +} |
514 | + |
515 | /* |
516 | * Note this can deadlock with nfsd_file_cache_purge. |
517 | */ |
518 | @@ -403,18 +457,40 @@ out_skip: |
519 | return LRU_SKIP; |
520 | } |
521 | |
522 | -static void |
523 | -nfsd_file_lru_dispose(struct list_head *head) |
524 | +static unsigned long |
525 | +nfsd_file_lru_walk_list(struct shrink_control *sc) |
526 | { |
527 | - while(!list_empty(head)) { |
528 | - struct nfsd_file *nf = list_first_entry(head, |
529 | - struct nfsd_file, nf_lru); |
530 | - list_del_init(&nf->nf_lru); |
531 | + LIST_HEAD(head); |
532 | + struct nfsd_file *nf; |
533 | + unsigned long ret; |
534 | + |
535 | + if (sc) |
536 | + ret = list_lru_shrink_walk(&nfsd_file_lru, sc, |
537 | + nfsd_file_lru_cb, &head); |
538 | + else |
539 | + ret = list_lru_walk(&nfsd_file_lru, |
540 | + nfsd_file_lru_cb, |
541 | + &head, LONG_MAX); |
542 | + list_for_each_entry(nf, &head, nf_lru) { |
543 | spin_lock(&nfsd_file_hashtbl[nf->nf_hashval].nfb_lock); |
544 | nfsd_file_do_unhash(nf); |
545 | spin_unlock(&nfsd_file_hashtbl[nf->nf_hashval].nfb_lock); |
546 | - nfsd_file_put_noref(nf); |
547 | } |
548 | + nfsd_file_dispose_list_delayed(&head); |
549 | + return ret; |
550 | +} |
551 | + |
552 | +static void |
553 | +nfsd_file_gc(void) |
554 | +{ |
555 | + nfsd_file_lru_walk_list(NULL); |
556 | +} |
557 | + |
558 | +static void |
559 | +nfsd_file_gc_worker(struct work_struct *work) |
560 | +{ |
561 | + nfsd_file_gc(); |
562 | + nfsd_file_schedule_laundrette(); |
563 | } |
564 | |
565 | static unsigned long |
566 | @@ -426,12 +502,7 @@ nfsd_file_lru_count(struct shrinker *s, struct shrink_control *sc) |
567 | static unsigned long |
568 | nfsd_file_lru_scan(struct shrinker *s, struct shrink_control *sc) |
569 | { |
570 | - LIST_HEAD(head); |
571 | - unsigned long ret; |
572 | - |
573 | - ret = list_lru_shrink_walk(&nfsd_file_lru, sc, nfsd_file_lru_cb, &head); |
574 | - nfsd_file_lru_dispose(&head); |
575 | - return ret; |
576 | + return nfsd_file_lru_walk_list(sc); |
577 | } |
578 | |
579 | static struct shrinker nfsd_file_shrinker = { |
580 | @@ -493,7 +564,7 @@ nfsd_file_close_inode(struct inode *inode) |
581 | |
582 | __nfsd_file_close_inode(inode, hashval, &dispose); |
583 | trace_nfsd_file_close_inode(inode, hashval, !list_empty(&dispose)); |
584 | - nfsd_file_dispose_list(&dispose); |
585 | + nfsd_file_dispose_list_delayed(&dispose); |
586 | } |
587 | |
588 | /** |
589 | @@ -509,16 +580,11 @@ static void |
590 | nfsd_file_delayed_close(struct work_struct *work) |
591 | { |
592 | LIST_HEAD(head); |
593 | + struct nfsd_fcache_disposal *l = container_of(work, |
594 | + struct nfsd_fcache_disposal, work); |
595 | |
596 | - list_lru_walk(&nfsd_file_lru, nfsd_file_lru_cb, &head, LONG_MAX); |
597 | - |
598 | - if (test_and_clear_bit(NFSD_FILE_LRU_RESCAN, &nfsd_file_lru_flags)) |
599 | - nfsd_file_schedule_laundrette(NFSD_FILE_LAUNDRETTE_NOFLUSH); |
600 | - |
601 | - if (!list_empty(&head)) { |
602 | - nfsd_file_lru_dispose(&head); |
603 | - flush_delayed_fput(); |
604 | - } |
605 | + nfsd_file_list_remove_disposal(&head, l); |
606 | + nfsd_file_dispose_list(&head); |
607 | } |
608 | |
609 | static int |
610 | @@ -579,6 +645,10 @@ nfsd_file_cache_init(void) |
611 | if (nfsd_file_hashtbl) |
612 | return 0; |
613 | |
614 | + nfsd_filecache_wq = alloc_workqueue("nfsd_filecache", 0, 0); |
615 | + if (!nfsd_filecache_wq) |
616 | + goto out; |
617 | + |
618 | nfsd_file_hashtbl = kcalloc(NFSD_FILE_HASH_SIZE, |
619 | sizeof(*nfsd_file_hashtbl), GFP_KERNEL); |
620 | if (!nfsd_file_hashtbl) { |
621 | @@ -632,7 +702,7 @@ nfsd_file_cache_init(void) |
622 | spin_lock_init(&nfsd_file_hashtbl[i].nfb_lock); |
623 | } |
624 | |
625 | - INIT_DELAYED_WORK(&nfsd_filecache_laundrette, nfsd_file_delayed_close); |
626 | + INIT_DELAYED_WORK(&nfsd_filecache_laundrette, nfsd_file_gc_worker); |
627 | out: |
628 | return ret; |
629 | out_notifier: |
630 | @@ -648,6 +718,8 @@ out_err: |
631 | nfsd_file_mark_slab = NULL; |
632 | kfree(nfsd_file_hashtbl); |
633 | nfsd_file_hashtbl = NULL; |
634 | + destroy_workqueue(nfsd_filecache_wq); |
635 | + nfsd_filecache_wq = NULL; |
636 | goto out; |
637 | } |
638 | |
639 | @@ -686,6 +758,88 @@ nfsd_file_cache_purge(struct net *net) |
640 | } |
641 | } |
642 | |
643 | +static struct nfsd_fcache_disposal * |
644 | +nfsd_alloc_fcache_disposal(struct net *net) |
645 | +{ |
646 | + struct nfsd_fcache_disposal *l; |
647 | + |
648 | + l = kmalloc(sizeof(*l), GFP_KERNEL); |
649 | + if (!l) |
650 | + return NULL; |
651 | + INIT_WORK(&l->work, nfsd_file_delayed_close); |
652 | + l->net = net; |
653 | + spin_lock_init(&l->lock); |
654 | + INIT_LIST_HEAD(&l->freeme); |
655 | + return l; |
656 | +} |
657 | + |
658 | +static void |
659 | +nfsd_free_fcache_disposal(struct nfsd_fcache_disposal *l) |
660 | +{ |
661 | + rcu_assign_pointer(l->net, NULL); |
662 | + cancel_work_sync(&l->work); |
663 | + nfsd_file_dispose_list(&l->freeme); |
664 | + kfree_rcu(l, rcu); |
665 | +} |
666 | + |
667 | +static void |
668 | +nfsd_add_fcache_disposal(struct nfsd_fcache_disposal *l) |
669 | +{ |
670 | + spin_lock(&laundrette_lock); |
671 | + list_add_tail_rcu(&l->list, &laundrettes); |
672 | + spin_unlock(&laundrette_lock); |
673 | +} |
674 | + |
675 | +static void |
676 | +nfsd_del_fcache_disposal(struct nfsd_fcache_disposal *l) |
677 | +{ |
678 | + spin_lock(&laundrette_lock); |
679 | + list_del_rcu(&l->list); |
680 | + spin_unlock(&laundrette_lock); |
681 | +} |
682 | + |
683 | +static int |
684 | +nfsd_alloc_fcache_disposal_net(struct net *net) |
685 | +{ |
686 | + struct nfsd_fcache_disposal *l; |
687 | + |
688 | + l = nfsd_alloc_fcache_disposal(net); |
689 | + if (!l) |
690 | + return -ENOMEM; |
691 | + nfsd_add_fcache_disposal(l); |
692 | + return 0; |
693 | +} |
694 | + |
695 | +static void |
696 | +nfsd_free_fcache_disposal_net(struct net *net) |
697 | +{ |
698 | + struct nfsd_fcache_disposal *l; |
699 | + |
700 | + rcu_read_lock(); |
701 | + list_for_each_entry_rcu(l, &laundrettes, list) { |
702 | + if (l->net != net) |
703 | + continue; |
704 | + nfsd_del_fcache_disposal(l); |
705 | + rcu_read_unlock(); |
706 | + nfsd_free_fcache_disposal(l); |
707 | + return; |
708 | + } |
709 | + rcu_read_unlock(); |
710 | +} |
711 | + |
712 | +int |
713 | +nfsd_file_cache_start_net(struct net *net) |
714 | +{ |
715 | + return nfsd_alloc_fcache_disposal_net(net); |
716 | +} |
717 | + |
718 | +void |
719 | +nfsd_file_cache_shutdown_net(struct net *net) |
720 | +{ |
721 | + nfsd_file_cache_purge(net); |
722 | + nfsd_free_fcache_disposal_net(net); |
723 | +} |
724 | + |
725 | void |
726 | nfsd_file_cache_shutdown(void) |
727 | { |
728 | @@ -712,6 +866,8 @@ nfsd_file_cache_shutdown(void) |
729 | nfsd_file_mark_slab = NULL; |
730 | kfree(nfsd_file_hashtbl); |
731 | nfsd_file_hashtbl = NULL; |
732 | + destroy_workqueue(nfsd_filecache_wq); |
733 | + nfsd_filecache_wq = NULL; |
734 | } |
735 | |
736 | static bool |
737 | @@ -881,7 +1037,8 @@ open_file: |
738 | nfsd_file_hashtbl[hashval].nfb_maxcount = max(nfsd_file_hashtbl[hashval].nfb_maxcount, |
739 | nfsd_file_hashtbl[hashval].nfb_count); |
740 | spin_unlock(&nfsd_file_hashtbl[hashval].nfb_lock); |
741 | - atomic_long_inc(&nfsd_filecache_count); |
742 | + if (atomic_long_inc_return(&nfsd_filecache_count) >= NFSD_FILE_LRU_THRESHOLD) |
743 | + nfsd_file_gc(); |
744 | |
745 | nf->nf_mark = nfsd_file_mark_find_or_create(nf); |
746 | if (nf->nf_mark) |
747 | diff --git a/fs/nfsd/filecache.h b/fs/nfsd/filecache.h |
748 | index 851d9abf54c25..79a7d6808d979 100644 |
749 | --- a/fs/nfsd/filecache.h |
750 | +++ b/fs/nfsd/filecache.h |
751 | @@ -51,6 +51,8 @@ struct nfsd_file { |
752 | int nfsd_file_cache_init(void); |
753 | void nfsd_file_cache_purge(struct net *); |
754 | void nfsd_file_cache_shutdown(void); |
755 | +int nfsd_file_cache_start_net(struct net *net); |
756 | +void nfsd_file_cache_shutdown_net(struct net *net); |
757 | void nfsd_file_put(struct nfsd_file *nf); |
758 | struct nfsd_file *nfsd_file_get(struct nfsd_file *nf); |
759 | void nfsd_file_close_inode_sync(struct inode *inode); |
760 | diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c |
761 | index 155a4e43b24ee..d63cdda1782d4 100644 |
762 | --- a/fs/nfsd/nfssvc.c |
763 | +++ b/fs/nfsd/nfssvc.c |
764 | @@ -394,13 +394,18 @@ static int nfsd_startup_net(int nrservs, struct net *net, const struct cred *cre |
765 | nn->lockd_up = 1; |
766 | } |
767 | |
768 | - ret = nfs4_state_start_net(net); |
769 | + ret = nfsd_file_cache_start_net(net); |
770 | if (ret) |
771 | goto out_lockd; |
772 | + ret = nfs4_state_start_net(net); |
773 | + if (ret) |
774 | + goto out_filecache; |
775 | |
776 | nn->nfsd_net_up = true; |
777 | return 0; |
778 | |
779 | +out_filecache: |
780 | + nfsd_file_cache_shutdown_net(net); |
781 | out_lockd: |
782 | if (nn->lockd_up) { |
783 | lockd_down(net); |
784 | @@ -415,7 +420,7 @@ static void nfsd_shutdown_net(struct net *net) |
785 | { |
786 | struct nfsd_net *nn = net_generic(net, nfsd_net_id); |
787 | |
788 | - nfsd_file_cache_purge(net); |
789 | + nfsd_file_cache_shutdown_net(net); |
790 | nfs4_state_shutdown_net(net); |
791 | if (nn->lockd_up) { |
792 | lockd_down(net); |
793 | diff --git a/include/net/esp.h b/include/net/esp.h |
794 | index 117652eb6ea32..465e38890ee98 100644 |
795 | --- a/include/net/esp.h |
796 | +++ b/include/net/esp.h |
797 | @@ -4,6 +4,8 @@ |
798 | |
799 | #include <linux/skbuff.h> |
800 | |
801 | +#define ESP_SKB_FRAG_MAXSIZE (PAGE_SIZE << SKB_FRAG_PAGE_ORDER) |
802 | + |
803 | struct ip_esp_hdr; |
804 | |
805 | static inline struct ip_esp_hdr *ip_esp_hdr(const struct sk_buff *skb) |
806 | diff --git a/include/net/sock.h b/include/net/sock.h |
807 | index 079b5f6f13d81..7f213cfcb3cc6 100644 |
808 | --- a/include/net/sock.h |
809 | +++ b/include/net/sock.h |
810 | @@ -2583,6 +2583,9 @@ extern int sysctl_optmem_max; |
811 | extern __u32 sysctl_wmem_default; |
812 | extern __u32 sysctl_rmem_default; |
813 | |
814 | + |
815 | +/* On 32bit arches, an skb frag is limited to 2^15 */ |
816 | +#define SKB_FRAG_PAGE_ORDER get_order(32768) |
817 | DECLARE_STATIC_KEY_FALSE(net_high_order_alloc_disable_key); |
818 | |
819 | static inline int sk_get_wmem0(const struct sock *sk, const struct proto *proto) |
820 | diff --git a/kernel/rcu/tree_plugin.h b/kernel/rcu/tree_plugin.h |
821 | index a71a4a272515d..2c127d438fe0a 100644 |
822 | --- a/kernel/rcu/tree_plugin.h |
823 | +++ b/kernel/rcu/tree_plugin.h |
824 | @@ -523,16 +523,17 @@ rcu_preempt_deferred_qs_irqrestore(struct task_struct *t, unsigned long flags) |
825 | raw_spin_unlock_irqrestore_rcu_node(rnp, flags); |
826 | } |
827 | |
828 | - /* Unboost if we were boosted. */ |
829 | - if (IS_ENABLED(CONFIG_RCU_BOOST) && drop_boost_mutex) |
830 | - rt_mutex_futex_unlock(&rnp->boost_mtx); |
831 | - |
832 | /* |
833 | * If this was the last task on the expedited lists, |
834 | * then we need to report up the rcu_node hierarchy. |
835 | */ |
836 | if (!empty_exp && empty_exp_now) |
837 | rcu_report_exp_rnp(rnp, true); |
838 | + |
839 | + /* Unboost if we were boosted. */ |
840 | + if (IS_ENABLED(CONFIG_RCU_BOOST) && drop_boost_mutex) |
841 | + rt_mutex_futex_unlock(&rnp->boost_mtx); |
842 | + |
843 | } else { |
844 | local_irq_restore(flags); |
845 | } |
846 | diff --git a/net/core/sock.c b/net/core/sock.c |
847 | index 57b7a10703c36..c84f68bff7f58 100644 |
848 | --- a/net/core/sock.c |
849 | +++ b/net/core/sock.c |
850 | @@ -2355,8 +2355,6 @@ static void sk_leave_memory_pressure(struct sock *sk) |
851 | } |
852 | } |
853 | |
854 | -/* On 32bit arches, an skb frag is limited to 2^15 */ |
855 | -#define SKB_FRAG_PAGE_ORDER get_order(32768) |
856 | DEFINE_STATIC_KEY_FALSE(net_high_order_alloc_disable_key); |
857 | |
858 | /** |
859 | diff --git a/net/ipv4/esp4.c b/net/ipv4/esp4.c |
860 | index 00210e55b4cd1..ef20f550d2f81 100644 |
861 | --- a/net/ipv4/esp4.c |
862 | +++ b/net/ipv4/esp4.c |
863 | @@ -277,6 +277,7 @@ int esp_output_head(struct xfrm_state *x, struct sk_buff *skb, struct esp_info * |
864 | struct page *page; |
865 | struct sk_buff *trailer; |
866 | int tailen = esp->tailen; |
867 | + unsigned int allocsz; |
868 | |
869 | /* this is non-NULL only with UDP Encapsulation */ |
870 | if (x->encap) { |
871 | @@ -286,6 +287,10 @@ int esp_output_head(struct xfrm_state *x, struct sk_buff *skb, struct esp_info * |
872 | return err; |
873 | } |
874 | |
875 | + allocsz = ALIGN(skb->data_len + tailen, L1_CACHE_BYTES); |
876 | + if (allocsz > ESP_SKB_FRAG_MAXSIZE) |
877 | + goto cow; |
878 | + |
879 | if (!skb_cloned(skb)) { |
880 | if (tailen <= skb_tailroom(skb)) { |
881 | nfrags = 1; |
882 | diff --git a/net/ipv6/esp6.c b/net/ipv6/esp6.c |
883 | index 7a739f16d82b2..79f117e33b80e 100644 |
884 | --- a/net/ipv6/esp6.c |
885 | +++ b/net/ipv6/esp6.c |
886 | @@ -230,6 +230,11 @@ int esp6_output_head(struct xfrm_state *x, struct sk_buff *skb, struct esp_info |
887 | struct page *page; |
888 | struct sk_buff *trailer; |
889 | int tailen = esp->tailen; |
890 | + unsigned int allocsz; |
891 | + |
892 | + allocsz = ALIGN(skb->data_len + tailen, L1_CACHE_BYTES); |
893 | + if (allocsz > ESP_SKB_FRAG_MAXSIZE) |
894 | + goto cow; |
895 | |
896 | if (!skb_cloned(skb)) { |
897 | if (tailen <= skb_tailroom(skb)) { |
898 | diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c |
899 | index 918a9520d1f17..3606796009572 100644 |
900 | --- a/net/ipv6/ip6_output.c |
901 | +++ b/net/ipv6/ip6_output.c |
902 | @@ -1429,8 +1429,8 @@ static int __ip6_append_data(struct sock *sk, |
903 | sizeof(struct frag_hdr) : 0) + |
904 | rt->rt6i_nfheader_len; |
905 | |
906 | - if (mtu < fragheaderlen || |
907 | - ((mtu - fragheaderlen) & ~7) + fragheaderlen < sizeof(struct frag_hdr)) |
908 | + if (mtu <= fragheaderlen || |
909 | + ((mtu - fragheaderlen) & ~7) + fragheaderlen <= sizeof(struct frag_hdr)) |
910 | goto emsgsize; |
911 | |
912 | maxfraglen = ((mtu - fragheaderlen) & ~7) + fragheaderlen - |
913 | diff --git a/net/llc/af_llc.c b/net/llc/af_llc.c |
914 | index 0b3adf7594ffe..3b1ea89a340e3 100644 |
915 | --- a/net/llc/af_llc.c |
916 | +++ b/net/llc/af_llc.c |
917 | @@ -276,6 +276,7 @@ static int llc_ui_autobind(struct socket *sock, struct sockaddr_llc *addr) |
918 | { |
919 | struct sock *sk = sock->sk; |
920 | struct llc_sock *llc = llc_sk(sk); |
921 | + struct net_device *dev = NULL; |
922 | struct llc_sap *sap; |
923 | int rc = -EINVAL; |
924 | |
925 | @@ -287,14 +288,14 @@ static int llc_ui_autobind(struct socket *sock, struct sockaddr_llc *addr) |
926 | goto out; |
927 | rc = -ENODEV; |
928 | if (sk->sk_bound_dev_if) { |
929 | - llc->dev = dev_get_by_index(&init_net, sk->sk_bound_dev_if); |
930 | - if (llc->dev && addr->sllc_arphrd != llc->dev->type) { |
931 | - dev_put(llc->dev); |
932 | - llc->dev = NULL; |
933 | + dev = dev_get_by_index(&init_net, sk->sk_bound_dev_if); |
934 | + if (dev && addr->sllc_arphrd != dev->type) { |
935 | + dev_put(dev); |
936 | + dev = NULL; |
937 | } |
938 | } else |
939 | - llc->dev = dev_getfirstbyhwtype(&init_net, addr->sllc_arphrd); |
940 | - if (!llc->dev) |
941 | + dev = dev_getfirstbyhwtype(&init_net, addr->sllc_arphrd); |
942 | + if (!dev) |
943 | goto out; |
944 | rc = -EUSERS; |
945 | llc->laddr.lsap = llc_ui_autoport(); |
946 | @@ -304,6 +305,11 @@ static int llc_ui_autobind(struct socket *sock, struct sockaddr_llc *addr) |
947 | sap = llc_sap_open(llc->laddr.lsap, NULL); |
948 | if (!sap) |
949 | goto out; |
950 | + |
951 | + /* Note: We do not expect errors from this point. */ |
952 | + llc->dev = dev; |
953 | + dev = NULL; |
954 | + |
955 | memcpy(llc->laddr.mac, llc->dev->dev_addr, IFHWADDRLEN); |
956 | memcpy(&llc->addr, addr, sizeof(llc->addr)); |
957 | /* assign new connection to its SAP */ |
958 | @@ -311,6 +317,7 @@ static int llc_ui_autobind(struct socket *sock, struct sockaddr_llc *addr) |
959 | sock_reset_flag(sk, SOCK_ZAPPED); |
960 | rc = 0; |
961 | out: |
962 | + dev_put(dev); |
963 | return rc; |
964 | } |
965 | |
966 | @@ -333,6 +340,7 @@ static int llc_ui_bind(struct socket *sock, struct sockaddr *uaddr, int addrlen) |
967 | struct sockaddr_llc *addr = (struct sockaddr_llc *)uaddr; |
968 | struct sock *sk = sock->sk; |
969 | struct llc_sock *llc = llc_sk(sk); |
970 | + struct net_device *dev = NULL; |
971 | struct llc_sap *sap; |
972 | int rc = -EINVAL; |
973 | |
974 | @@ -348,25 +356,26 @@ static int llc_ui_bind(struct socket *sock, struct sockaddr *uaddr, int addrlen) |
975 | rc = -ENODEV; |
976 | rcu_read_lock(); |
977 | if (sk->sk_bound_dev_if) { |
978 | - llc->dev = dev_get_by_index_rcu(&init_net, sk->sk_bound_dev_if); |
979 | - if (llc->dev) { |
980 | + dev = dev_get_by_index_rcu(&init_net, sk->sk_bound_dev_if); |
981 | + if (dev) { |
982 | if (is_zero_ether_addr(addr->sllc_mac)) |
983 | - memcpy(addr->sllc_mac, llc->dev->dev_addr, |
984 | + memcpy(addr->sllc_mac, dev->dev_addr, |
985 | IFHWADDRLEN); |
986 | - if (addr->sllc_arphrd != llc->dev->type || |
987 | + if (addr->sllc_arphrd != dev->type || |
988 | !ether_addr_equal(addr->sllc_mac, |
989 | - llc->dev->dev_addr)) { |
990 | + dev->dev_addr)) { |
991 | rc = -EINVAL; |
992 | - llc->dev = NULL; |
993 | + dev = NULL; |
994 | } |
995 | } |
996 | - } else |
997 | - llc->dev = dev_getbyhwaddr_rcu(&init_net, addr->sllc_arphrd, |
998 | + } else { |
999 | + dev = dev_getbyhwaddr_rcu(&init_net, addr->sllc_arphrd, |
1000 | addr->sllc_mac); |
1001 | - if (llc->dev) |
1002 | - dev_hold(llc->dev); |
1003 | + } |
1004 | + if (dev) |
1005 | + dev_hold(dev); |
1006 | rcu_read_unlock(); |
1007 | - if (!llc->dev) |
1008 | + if (!dev) |
1009 | goto out; |
1010 | if (!addr->sllc_sap) { |
1011 | rc = -EUSERS; |
1012 | @@ -399,6 +408,11 @@ static int llc_ui_bind(struct socket *sock, struct sockaddr *uaddr, int addrlen) |
1013 | goto out_put; |
1014 | } |
1015 | } |
1016 | + |
1017 | + /* Note: We do not expect errors from this point. */ |
1018 | + llc->dev = dev; |
1019 | + dev = NULL; |
1020 | + |
1021 | llc->laddr.lsap = addr->sllc_sap; |
1022 | memcpy(llc->laddr.mac, addr->sllc_mac, IFHWADDRLEN); |
1023 | memcpy(&llc->addr, addr, sizeof(llc->addr)); |
1024 | @@ -409,6 +423,7 @@ static int llc_ui_bind(struct socket *sock, struct sockaddr *uaddr, int addrlen) |
1025 | out_put: |
1026 | llc_sap_put(sap); |
1027 | out: |
1028 | + dev_put(dev); |
1029 | release_sock(sk); |
1030 | return rc; |
1031 | } |
1032 | diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c |
1033 | index 1b50bbf030ed8..16f37fd0ac0e5 100644 |
1034 | --- a/net/mac80211/cfg.c |
1035 | +++ b/net/mac80211/cfg.c |
1036 | @@ -1949,13 +1949,11 @@ static int copy_mesh_setup(struct ieee80211_if_mesh *ifmsh, |
1037 | const struct mesh_setup *setup) |
1038 | { |
1039 | u8 *new_ie; |
1040 | - const u8 *old_ie; |
1041 | struct ieee80211_sub_if_data *sdata = container_of(ifmsh, |
1042 | struct ieee80211_sub_if_data, u.mesh); |
1043 | |
1044 | /* allocate information elements */ |
1045 | new_ie = NULL; |
1046 | - old_ie = ifmsh->ie; |
1047 | |
1048 | if (setup->ie_len) { |
1049 | new_ie = kmemdup(setup->ie, setup->ie_len, |
1050 | @@ -1965,7 +1963,6 @@ static int copy_mesh_setup(struct ieee80211_if_mesh *ifmsh, |
1051 | } |
1052 | ifmsh->ie_len = setup->ie_len; |
1053 | ifmsh->ie = new_ie; |
1054 | - kfree(old_ie); |
1055 | |
1056 | /* now copy the rest of the setup parameters */ |
1057 | ifmsh->mesh_id_len = setup->mesh_id_len; |
1058 | diff --git a/net/netfilter/nf_tables_core.c b/net/netfilter/nf_tables_core.c |
1059 | index 96c74c4c71762..ceb0ef437e23e 100644 |
1060 | --- a/net/netfilter/nf_tables_core.c |
1061 | +++ b/net/netfilter/nf_tables_core.c |
1062 | @@ -153,7 +153,7 @@ nft_do_chain(struct nft_pktinfo *pkt, void *priv) |
1063 | struct nft_rule *const *rules; |
1064 | const struct nft_rule *rule; |
1065 | const struct nft_expr *expr, *last; |
1066 | - struct nft_regs regs; |
1067 | + struct nft_regs regs = {}; |
1068 | unsigned int stackptr = 0; |
1069 | struct nft_jumpstack jumpstack[NFT_JUMP_STACK_SIZE]; |
1070 | bool genbit = READ_ONCE(net->nft.gencursor); |
1071 | diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c |
1072 | index 841c0a12cc929..ad4e0af2d0d03 100644 |
1073 | --- a/sound/core/oss/pcm_oss.c |
1074 | +++ b/sound/core/oss/pcm_oss.c |
1075 | @@ -774,6 +774,11 @@ static int snd_pcm_oss_period_size(struct snd_pcm_substream *substream, |
1076 | |
1077 | if (oss_period_size < 16) |
1078 | return -EINVAL; |
1079 | + |
1080 | + /* don't allocate too large period; 1MB period must be enough */ |
1081 | + if (oss_period_size > 1024 * 1024) |
1082 | + return -ENOMEM; |
1083 | + |
1084 | runtime->oss.period_bytes = oss_period_size; |
1085 | runtime->oss.period_frames = 1; |
1086 | runtime->oss.periods = oss_periods; |
1087 | @@ -1045,10 +1050,9 @@ static int snd_pcm_oss_change_params_locked(struct snd_pcm_substream *substream) |
1088 | goto failure; |
1089 | } |
1090 | #endif |
1091 | - oss_period_size *= oss_frame_size; |
1092 | - |
1093 | - oss_buffer_size = oss_period_size * runtime->oss.periods; |
1094 | - if (oss_buffer_size < 0) { |
1095 | + oss_period_size = array_size(oss_period_size, oss_frame_size); |
1096 | + oss_buffer_size = array_size(oss_period_size, runtime->oss.periods); |
1097 | + if (oss_buffer_size <= 0) { |
1098 | err = -EINVAL; |
1099 | goto failure; |
1100 | } |
1101 | diff --git a/sound/core/oss/pcm_plugin.c b/sound/core/oss/pcm_plugin.c |
1102 | index da400da1fafe6..8b7bbabeea24b 100644 |
1103 | --- a/sound/core/oss/pcm_plugin.c |
1104 | +++ b/sound/core/oss/pcm_plugin.c |
1105 | @@ -61,7 +61,10 @@ static int snd_pcm_plugin_alloc(struct snd_pcm_plugin *plugin, snd_pcm_uframes_t |
1106 | } |
1107 | if ((width = snd_pcm_format_physical_width(format->format)) < 0) |
1108 | return width; |
1109 | - size = frames * format->channels * width; |
1110 | + size = array3_size(frames, format->channels, width); |
1111 | + /* check for too large period size once again */ |
1112 | + if (size > 1024 * 1024) |
1113 | + return -ENOMEM; |
1114 | if (snd_BUG_ON(size % 8)) |
1115 | return -ENXIO; |
1116 | size /= 8; |
1117 | diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c |
1118 | index 0c5b7a54ca81c..dbe9a65cc1d45 100644 |
1119 | --- a/sound/core/pcm_native.c |
1120 | +++ b/sound/core/pcm_native.c |
1121 | @@ -1656,21 +1656,25 @@ static int snd_pcm_do_reset(struct snd_pcm_substream *substream, int state) |
1122 | int err = substream->ops->ioctl(substream, SNDRV_PCM_IOCTL1_RESET, NULL); |
1123 | if (err < 0) |
1124 | return err; |
1125 | + snd_pcm_stream_lock_irq(substream); |
1126 | runtime->hw_ptr_base = 0; |
1127 | runtime->hw_ptr_interrupt = runtime->status->hw_ptr - |
1128 | runtime->status->hw_ptr % runtime->period_size; |
1129 | runtime->silence_start = runtime->status->hw_ptr; |
1130 | runtime->silence_filled = 0; |
1131 | + snd_pcm_stream_unlock_irq(substream); |
1132 | return 0; |
1133 | } |
1134 | |
1135 | static void snd_pcm_post_reset(struct snd_pcm_substream *substream, int state) |
1136 | { |
1137 | struct snd_pcm_runtime *runtime = substream->runtime; |
1138 | + snd_pcm_stream_lock_irq(substream); |
1139 | runtime->control->appl_ptr = runtime->status->hw_ptr; |
1140 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && |
1141 | runtime->silence_size > 0) |
1142 | snd_pcm_playback_silence(substream, ULONG_MAX); |
1143 | + snd_pcm_stream_unlock_irq(substream); |
1144 | } |
1145 | |
1146 | static const struct action_ops snd_pcm_action_reset = { |
1147 | diff --git a/sound/pci/ac97/ac97_codec.c b/sound/pci/ac97/ac97_codec.c |
1148 | index 66f6c3bf08e31..6fb192a94762f 100644 |
1149 | --- a/sound/pci/ac97/ac97_codec.c |
1150 | +++ b/sound/pci/ac97/ac97_codec.c |
1151 | @@ -938,8 +938,8 @@ static int snd_ac97_ad18xx_pcm_get_volume(struct snd_kcontrol *kcontrol, struct |
1152 | int codec = kcontrol->private_value & 3; |
1153 | |
1154 | mutex_lock(&ac97->page_mutex); |
1155 | - ucontrol->value.integer.value[0] = 31 - ((ac97->spec.ad18xx.pcmreg[codec] >> 0) & 31); |
1156 | - ucontrol->value.integer.value[1] = 31 - ((ac97->spec.ad18xx.pcmreg[codec] >> 8) & 31); |
1157 | + ucontrol->value.integer.value[0] = 31 - ((ac97->spec.ad18xx.pcmreg[codec] >> 8) & 31); |
1158 | + ucontrol->value.integer.value[1] = 31 - ((ac97->spec.ad18xx.pcmreg[codec] >> 0) & 31); |
1159 | mutex_unlock(&ac97->page_mutex); |
1160 | return 0; |
1161 | } |
1162 | diff --git a/sound/pci/cmipci.c b/sound/pci/cmipci.c |
1163 | index df720881eb991..db9d89ba36587 100644 |
1164 | --- a/sound/pci/cmipci.c |
1165 | +++ b/sound/pci/cmipci.c |
1166 | @@ -302,7 +302,6 @@ MODULE_PARM_DESC(joystick_port, "Joystick port address."); |
1167 | #define CM_MICGAINZ 0x01 /* mic boost */ |
1168 | #define CM_MICGAINZ_SHIFT 0 |
1169 | |
1170 | -#define CM_REG_MIXER3 0x24 |
1171 | #define CM_REG_AUX_VOL 0x26 |
1172 | #define CM_VAUXL_MASK 0xf0 |
1173 | #define CM_VAUXR_MASK 0x0f |
1174 | @@ -3310,7 +3309,7 @@ static void snd_cmipci_remove(struct pci_dev *pci) |
1175 | */ |
1176 | static unsigned char saved_regs[] = { |
1177 | CM_REG_FUNCTRL1, CM_REG_CHFORMAT, CM_REG_LEGACY_CTRL, CM_REG_MISC_CTRL, |
1178 | - CM_REG_MIXER0, CM_REG_MIXER1, CM_REG_MIXER2, CM_REG_MIXER3, CM_REG_PLL, |
1179 | + CM_REG_MIXER0, CM_REG_MIXER1, CM_REG_MIXER2, CM_REG_AUX_VOL, CM_REG_PLL, |
1180 | CM_REG_CH0_FRAME1, CM_REG_CH0_FRAME2, |
1181 | CM_REG_CH1_FRAME1, CM_REG_CH1_FRAME2, CM_REG_EXT_MISC, |
1182 | CM_REG_INT_STATUS, CM_REG_INT_HLDCLR, CM_REG_FUNCTRL0, |
1183 | diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c |
1184 | index c03448ea8a203..d201043d661c1 100644 |
1185 | --- a/sound/pci/hda/patch_realtek.c |
1186 | +++ b/sound/pci/hda/patch_realtek.c |
1187 | @@ -8183,6 +8183,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { |
1188 | SND_PCI_QUIRK(0x1043, 0x1e51, "ASUS Zephyrus M15", ALC294_FIXUP_ASUS_GU502_PINS), |
1189 | SND_PCI_QUIRK(0x1043, 0x1e8e, "ASUS Zephyrus G15", ALC289_FIXUP_ASUS_GA401), |
1190 | SND_PCI_QUIRK(0x1043, 0x1f11, "ASUS Zephyrus G14", ALC289_FIXUP_ASUS_GA401), |
1191 | + SND_PCI_QUIRK(0x1043, 0x1d42, "ASUS Zephyrus G14 2022", ALC289_FIXUP_ASUS_GA401), |
1192 | SND_PCI_QUIRK(0x1043, 0x16b2, "ASUS GU603", ALC289_FIXUP_ASUS_GA401), |
1193 | SND_PCI_QUIRK(0x1043, 0x3030, "ASUS ZN270IE", ALC256_FIXUP_ASUS_AIO_GPIO2), |
1194 | SND_PCI_QUIRK(0x1043, 0x831a, "ASUS P901", ALC269_FIXUP_STEREO_DMIC), |
1195 | @@ -10201,6 +10202,7 @@ static const struct snd_pci_quirk alc662_fixup_tbl[] = { |
1196 | SND_PCI_QUIRK(0x1028, 0x069f, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE), |
1197 | SND_PCI_QUIRK(0x103c, 0x1632, "HP RP5800", ALC662_FIXUP_HP_RP5800), |
1198 | SND_PCI_QUIRK(0x103c, 0x873e, "HP", ALC671_FIXUP_HP_HEADSET_MIC2), |
1199 | + SND_PCI_QUIRK(0x103c, 0x885f, "HP 288 Pro G8", ALC671_FIXUP_HP_HEADSET_MIC2), |
1200 | SND_PCI_QUIRK(0x1043, 0x1080, "Asus UX501VW", ALC668_FIXUP_HEADSET_MODE), |
1201 | SND_PCI_QUIRK(0x1043, 0x11cd, "Asus N550", ALC662_FIXUP_ASUS_Nx50), |
1202 | SND_PCI_QUIRK(0x1043, 0x129d, "Asus N750", ALC662_FIXUP_ASUS_Nx50), |
1203 | diff --git a/sound/soc/sti/uniperif_player.c b/sound/soc/sti/uniperif_player.c |
1204 | index 2ed92c990b97c..dd9013c476649 100644 |
1205 | --- a/sound/soc/sti/uniperif_player.c |
1206 | +++ b/sound/soc/sti/uniperif_player.c |
1207 | @@ -91,7 +91,7 @@ static irqreturn_t uni_player_irq_handler(int irq, void *dev_id) |
1208 | SET_UNIPERIF_ITM_BCLR_FIFO_ERROR(player); |
1209 | |
1210 | /* Stop the player */ |
1211 | - snd_pcm_stop_xrun(player->substream); |
1212 | + snd_pcm_stop(player->substream, SNDRV_PCM_STATE_XRUN); |
1213 | } |
1214 | |
1215 | ret = IRQ_HANDLED; |
1216 | @@ -105,7 +105,7 @@ static irqreturn_t uni_player_irq_handler(int irq, void *dev_id) |
1217 | SET_UNIPERIF_ITM_BCLR_DMA_ERROR(player); |
1218 | |
1219 | /* Stop the player */ |
1220 | - snd_pcm_stop_xrun(player->substream); |
1221 | + snd_pcm_stop(player->substream, SNDRV_PCM_STATE_XRUN); |
1222 | |
1223 | ret = IRQ_HANDLED; |
1224 | } |
1225 | @@ -138,7 +138,7 @@ static irqreturn_t uni_player_irq_handler(int irq, void *dev_id) |
1226 | dev_err(player->dev, "Underflow recovery failed\n"); |
1227 | |
1228 | /* Stop the player */ |
1229 | - snd_pcm_stop_xrun(player->substream); |
1230 | + snd_pcm_stop(player->substream, SNDRV_PCM_STATE_XRUN); |
1231 | |
1232 | ret = IRQ_HANDLED; |
1233 | } |
1234 | diff --git a/sound/soc/sti/uniperif_reader.c b/sound/soc/sti/uniperif_reader.c |
1235 | index 136059331211d..065c5f0d1f5f0 100644 |
1236 | --- a/sound/soc/sti/uniperif_reader.c |
1237 | +++ b/sound/soc/sti/uniperif_reader.c |
1238 | @@ -65,7 +65,7 @@ static irqreturn_t uni_reader_irq_handler(int irq, void *dev_id) |
1239 | if (unlikely(status & UNIPERIF_ITS_FIFO_ERROR_MASK(reader))) { |
1240 | dev_err(reader->dev, "FIFO error detected\n"); |
1241 | |
1242 | - snd_pcm_stop_xrun(reader->substream); |
1243 | + snd_pcm_stop(reader->substream, SNDRV_PCM_STATE_XRUN); |
1244 | |
1245 | ret = IRQ_HANDLED; |
1246 | } |
1247 | diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c |
1248 | index d926869c031b1..1f7c80541d03b 100644 |
1249 | --- a/sound/usb/mixer_quirks.c |
1250 | +++ b/sound/usb/mixer_quirks.c |
1251 | @@ -2370,9 +2370,10 @@ void snd_usb_mixer_fu_apply_quirk(struct usb_mixer_interface *mixer, |
1252 | if (unitid == 7 && cval->control == UAC_FU_VOLUME) |
1253 | snd_dragonfly_quirk_db_scale(mixer, cval, kctl); |
1254 | break; |
1255 | - /* lowest playback value is muted on C-Media devices */ |
1256 | - case USB_ID(0x0d8c, 0x000c): |
1257 | - case USB_ID(0x0d8c, 0x0014): |
1258 | + /* lowest playback value is muted on some devices */ |
1259 | + case USB_ID(0x0d8c, 0x000c): /* C-Media */ |
1260 | + case USB_ID(0x0d8c, 0x0014): /* C-Media */ |
1261 | + case USB_ID(0x19f7, 0x0003): /* RODE NT-USB */ |
1262 | if (strstr(kctl->id.name, "Playback")) |
1263 | cval->min_mute = 1; |
1264 | break; |