--- /dev/null
+From a2d57ebec1e15f0ac256eb8397e82b07adfaaacc Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Kacper=20Michaj=C5=82ow?= <kasper93@gmail.com>
+Date: Sat, 27 Aug 2022 22:33:28 +0200
+Subject: ALSA: hda/realtek: Add speaker AMP init for Samsung laptops with ALC298
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Kacper Michajłow <kasper93@gmail.com>
+
+commit a2d57ebec1e15f0ac256eb8397e82b07adfaaacc upstream.
+
+Magic initialization sequence was extracted from Windows driver and
+cleaned up manually.
+
+Fixes internal speakers output.
+
+Link: https://bugzilla.kernel.org/show_bug.cgi?id=207423
+Link: https://bugs.launchpad.net/ubuntu/+source/linux/+bug/1851518
+Signed-off-by: Kacper Michajłow <kasper93@gmail.com>
+Cc: <stable@vger.kernel.org>
+Link: https://lore.kernel.org/r/20220827203328.30363-1-kasper93@gmail.com
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ sound/pci/hda/patch_realtek.c | 63 +++++++++++++++++++++++++++++++++++++-----
+ 1 file changed, 56 insertions(+), 7 deletions(-)
+
+--- a/sound/pci/hda/patch_realtek.c
++++ b/sound/pci/hda/patch_realtek.c
+@@ -4689,6 +4689,48 @@ static void alc236_fixup_hp_mute_led_mic
+ alc236_fixup_hp_micmute_led_vref(codec, fix, action);
+ }
+
++static inline void alc298_samsung_write_coef_pack(struct hda_codec *codec,
++ const unsigned short coefs[2])
++{
++ alc_write_coef_idx(codec, 0x23, coefs[0]);
++ alc_write_coef_idx(codec, 0x25, coefs[1]);
++ alc_write_coef_idx(codec, 0x26, 0xb011);
++}
++
++struct alc298_samsung_amp_desc {
++ unsigned char nid;
++ unsigned short init_seq[2][2];
++};
++
++static void alc298_fixup_samsung_amp(struct hda_codec *codec,
++ const struct hda_fixup *fix, int action)
++{
++ int i, j;
++ static const unsigned short init_seq[][2] = {
++ { 0x19, 0x00 }, { 0x20, 0xc0 }, { 0x22, 0x44 }, { 0x23, 0x08 },
++ { 0x24, 0x85 }, { 0x25, 0x41 }, { 0x35, 0x40 }, { 0x36, 0x01 },
++ { 0x38, 0x81 }, { 0x3a, 0x03 }, { 0x3b, 0x81 }, { 0x40, 0x3e },
++ { 0x41, 0x07 }, { 0x400, 0x1 }
++ };
++ static const struct alc298_samsung_amp_desc amps[] = {
++ { 0x3a, { { 0x18, 0x1 }, { 0x26, 0x0 } } },
++ { 0x39, { { 0x18, 0x2 }, { 0x26, 0x1 } } }
++ };
++
++ if (action != HDA_FIXUP_ACT_INIT)
++ return;
++
++ for (i = 0; i < ARRAY_SIZE(amps); i++) {
++ alc_write_coef_idx(codec, 0x22, amps[i].nid);
++
++ for (j = 0; j < ARRAY_SIZE(amps[i].init_seq); j++)
++ alc298_samsung_write_coef_pack(codec, amps[i].init_seq[j]);
++
++ for (j = 0; j < ARRAY_SIZE(init_seq); j++)
++ alc298_samsung_write_coef_pack(codec, init_seq[j]);
++ }
++}
++
+ #if IS_REACHABLE(CONFIG_INPUT)
+ static void gpio2_mic_hotkey_event(struct hda_codec *codec,
+ struct hda_jack_callback *event)
+@@ -7000,6 +7042,7 @@ enum {
+ ALC236_FIXUP_HP_GPIO_LED,
+ ALC236_FIXUP_HP_MUTE_LED,
+ ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF,
++ ALC298_FIXUP_SAMSUNG_AMP,
+ ALC298_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET,
+ ALC256_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET,
+ ALC295_FIXUP_ASUS_MIC_NO_PRESENCE,
+@@ -8365,6 +8408,12 @@ static const struct hda_fixup alc269_fix
+ .type = HDA_FIXUP_FUNC,
+ .v.func = alc236_fixup_hp_mute_led_micmute_vref,
+ },
++ [ALC298_FIXUP_SAMSUNG_AMP] = {
++ .type = HDA_FIXUP_FUNC,
++ .v.func = alc298_fixup_samsung_amp,
++ .chained = true,
++ .chain_id = ALC298_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET
++ },
+ [ALC298_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET] = {
+ .type = HDA_FIXUP_VERBS,
+ .v.verbs = (const struct hda_verb[]) {
+@@ -9307,13 +9356,13 @@ static const struct snd_pci_quirk alc269
+ SND_PCI_QUIRK(0x10ec, 0x1254, "Intel Reference board", ALC295_FIXUP_CHROME_BOOK),
+ SND_PCI_QUIRK(0x10f7, 0x8338, "Panasonic CF-SZ6", ALC269_FIXUP_HEADSET_MODE),
+ SND_PCI_QUIRK(0x144d, 0xc109, "Samsung Ativ book 9 (NP900X3G)", ALC269_FIXUP_INV_DMIC),
+- SND_PCI_QUIRK(0x144d, 0xc169, "Samsung Notebook 9 Pen (NP930SBE-K01US)", ALC298_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET),
+- SND_PCI_QUIRK(0x144d, 0xc176, "Samsung Notebook 9 Pro (NP930MBE-K04US)", ALC298_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET),
+- SND_PCI_QUIRK(0x144d, 0xc189, "Samsung Galaxy Flex Book (NT950QCG-X716)", ALC298_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET),
+- SND_PCI_QUIRK(0x144d, 0xc18a, "Samsung Galaxy Book Ion (NP930XCJ-K01US)", ALC298_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET),
++ SND_PCI_QUIRK(0x144d, 0xc169, "Samsung Notebook 9 Pen (NP930SBE-K01US)", ALC298_FIXUP_SAMSUNG_AMP),
++ SND_PCI_QUIRK(0x144d, 0xc176, "Samsung Notebook 9 Pro (NP930MBE-K04US)", ALC298_FIXUP_SAMSUNG_AMP),
++ SND_PCI_QUIRK(0x144d, 0xc189, "Samsung Galaxy Flex Book (NT950QCG-X716)", ALC298_FIXUP_SAMSUNG_AMP),
++ SND_PCI_QUIRK(0x144d, 0xc18a, "Samsung Galaxy Book Ion (NP930XCJ-K01US)", ALC298_FIXUP_SAMSUNG_AMP),
+ SND_PCI_QUIRK(0x144d, 0xc740, "Samsung Ativ book 8 (NP870Z5G)", ALC269_FIXUP_ATIV_BOOK_8),
+- SND_PCI_QUIRK(0x144d, 0xc812, "Samsung Notebook Pen S (NT950SBE-X58)", ALC298_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET),
+- SND_PCI_QUIRK(0x144d, 0xc830, "Samsung Galaxy Book Ion (NT950XCJ-X716A)", ALC298_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET),
++ SND_PCI_QUIRK(0x144d, 0xc812, "Samsung Notebook Pen S (NT950SBE-X58)", ALC298_FIXUP_SAMSUNG_AMP),
++ SND_PCI_QUIRK(0x144d, 0xc830, "Samsung Galaxy Book Ion (NT950XCJ-X716A)", ALC298_FIXUP_SAMSUNG_AMP),
+ SND_PCI_QUIRK(0x144d, 0xc832, "Samsung Galaxy Book Flex Alpha (NP730QCJ)", ALC256_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET),
+ SND_PCI_QUIRK(0x1458, 0xfa53, "Gigabyte BXBT-2807", ALC283_FIXUP_HEADSET_MIC),
+ SND_PCI_QUIRK(0x1462, 0xb120, "MSI Cubi MS-B120", ALC283_FIXUP_HEADSET_MIC),
+@@ -9679,7 +9728,7 @@ static const struct hda_model_fixup alc2
+ {.id = ALC299_FIXUP_PREDATOR_SPK, .name = "predator-spk"},
+ {.id = ALC298_FIXUP_HUAWEI_MBX_STEREO, .name = "huawei-mbx-stereo"},
+ {.id = ALC256_FIXUP_MEDION_HEADSET_NO_PRESENCE, .name = "alc256-medion-headset"},
+- {.id = ALC298_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET, .name = "alc298-samsung-headphone"},
++ {.id = ALC298_FIXUP_SAMSUNG_AMP, .name = "alc298-samsung-amp"},
+ {.id = ALC256_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET, .name = "alc256-samsung-headphone"},
+ {.id = ALC255_FIXUP_XIAOMI_HEADSET_MIC, .name = "alc255-xiaomi-headset"},
+ {.id = ALC274_FIXUP_HP_MIC, .name = "alc274-hp-mic-detect"},
--- /dev/null
+From a8d302a0b77057568350fe0123e639d02dba0745 Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Sun, 21 Aug 2022 17:59:11 +0200
+Subject: ALSA: memalloc: Revive x86-specific WC page allocations again
+
+From: Takashi Iwai <tiwai@suse.de>
+
+commit a8d302a0b77057568350fe0123e639d02dba0745 upstream.
+
+We dropped the x86-specific hack for WC-page allocations with a hope
+that the standard dma_alloc_wc() works nowadays. Alas, it doesn't,
+and we need to take back some workaround again, but in a different
+form, as the previous one was broken for some platforms.
+
+This patch re-introduces the x86-specific WC-page allocations, but it
+uses rather the manual page allocations instead of
+dma_alloc_coherent(). The use of dma_alloc_coherent() was also a
+potential problem in the recent addition of the fallback allocation
+for noncontig pages, and this patch eliminates both at once.
+
+Fixes: 9882d63bea14 ("ALSA: memalloc: Drop x86-specific hack for WC allocations")
+Cc: <stable@vger.kernel.org>
+BugLink: https://bugzilla.kernel.org/show_bug.cgi?id=216363
+Link: https://lore.kernel.org/r/20220821155911.10715-1-tiwai@suse.de
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ sound/core/memalloc.c | 87 ++++++++++++++++++++++++++++++++++++++++----------
+ 1 file changed, 71 insertions(+), 16 deletions(-)
+
+--- a/sound/core/memalloc.c
++++ b/sound/core/memalloc.c
+@@ -20,6 +20,13 @@
+
+ static const struct snd_malloc_ops *snd_dma_get_ops(struct snd_dma_buffer *dmab);
+
++#ifdef CONFIG_SND_DMA_SGBUF
++static void *do_alloc_fallback_pages(struct device *dev, size_t size,
++ dma_addr_t *addr, bool wc);
++static void do_free_fallback_pages(void *p, size_t size, bool wc);
++static void *snd_dma_sg_fallback_alloc(struct snd_dma_buffer *dmab, size_t size);
++#endif
++
+ /* a cast to gfp flag from the dev pointer; for CONTINUOUS and VMALLOC types */
+ static inline gfp_t snd_mem_get_gfp_flags(const struct snd_dma_buffer *dmab,
+ gfp_t default_gfp)
+@@ -269,16 +276,21 @@ EXPORT_SYMBOL(snd_sgbuf_get_chunk_size);
+ /*
+ * Continuous pages allocator
+ */
+-static void *snd_dma_continuous_alloc(struct snd_dma_buffer *dmab, size_t size)
++static void *do_alloc_pages(size_t size, dma_addr_t *addr, gfp_t gfp)
+ {
+- gfp_t gfp = snd_mem_get_gfp_flags(dmab, GFP_KERNEL);
+ void *p = alloc_pages_exact(size, gfp);
+
+ if (p)
+- dmab->addr = page_to_phys(virt_to_page(p));
++ *addr = page_to_phys(virt_to_page(p));
+ return p;
+ }
+
++static void *snd_dma_continuous_alloc(struct snd_dma_buffer *dmab, size_t size)
++{
++ return do_alloc_pages(size, &dmab->addr,
++ snd_mem_get_gfp_flags(dmab, GFP_KERNEL));
++}
++
+ static void snd_dma_continuous_free(struct snd_dma_buffer *dmab)
+ {
+ free_pages_exact(dmab->area, dmab->bytes);
+@@ -455,6 +467,25 @@ static const struct snd_malloc_ops snd_d
+ /*
+ * Write-combined pages
+ */
++/* x86-specific allocations */
++#ifdef CONFIG_SND_DMA_SGBUF
++static void *snd_dma_wc_alloc(struct snd_dma_buffer *dmab, size_t size)
++{
++ return do_alloc_fallback_pages(dmab->dev.dev, size, &dmab->addr, true);
++}
++
++static void snd_dma_wc_free(struct snd_dma_buffer *dmab)
++{
++ do_free_fallback_pages(dmab->area, dmab->bytes, true);
++}
++
++static int snd_dma_wc_mmap(struct snd_dma_buffer *dmab,
++ struct vm_area_struct *area)
++{
++ area->vm_page_prot = pgprot_writecombine(area->vm_page_prot);
++ return snd_dma_continuous_mmap(dmab, area);
++}
++#else
+ static void *snd_dma_wc_alloc(struct snd_dma_buffer *dmab, size_t size)
+ {
+ return dma_alloc_wc(dmab->dev.dev, size, &dmab->addr, DEFAULT_GFP);
+@@ -471,6 +502,7 @@ static int snd_dma_wc_mmap(struct snd_dm
+ return dma_mmap_wc(dmab->dev.dev, area,
+ dmab->area, dmab->addr, dmab->bytes);
+ }
++#endif /* CONFIG_SND_DMA_SGBUF */
+
+ static const struct snd_malloc_ops snd_dma_wc_ops = {
+ .alloc = snd_dma_wc_alloc,
+@@ -478,10 +510,6 @@ static const struct snd_malloc_ops snd_d
+ .mmap = snd_dma_wc_mmap,
+ };
+
+-#ifdef CONFIG_SND_DMA_SGBUF
+-static void *snd_dma_sg_fallback_alloc(struct snd_dma_buffer *dmab, size_t size);
+-#endif
+-
+ /*
+ * Non-contiguous pages allocator
+ */
+@@ -661,6 +689,37 @@ static const struct snd_malloc_ops snd_d
+ .get_chunk_size = snd_dma_noncontig_get_chunk_size,
+ };
+
++/* manual page allocations with wc setup */
++static void *do_alloc_fallback_pages(struct device *dev, size_t size,
++ dma_addr_t *addr, bool wc)
++{
++ gfp_t gfp = GFP_KERNEL | __GFP_NORETRY | __GFP_NOWARN;
++ void *p;
++
++ again:
++ p = do_alloc_pages(size, addr, gfp);
++ if (!p || (*addr + size - 1) & ~dev->coherent_dma_mask) {
++ if (IS_ENABLED(CONFIG_ZONE_DMA32) && !(gfp & GFP_DMA32)) {
++ gfp |= GFP_DMA32;
++ goto again;
++ }
++ if (IS_ENABLED(CONFIG_ZONE_DMA) && !(gfp & GFP_DMA)) {
++ gfp = (gfp & ~GFP_DMA32) | GFP_DMA;
++ goto again;
++ }
++ }
++ if (p && wc)
++ set_memory_wc((unsigned long)(p), size >> PAGE_SHIFT);
++ return p;
++}
++
++static void do_free_fallback_pages(void *p, size_t size, bool wc)
++{
++ if (wc)
++ set_memory_wb((unsigned long)(p), size >> PAGE_SHIFT);
++ free_pages_exact(p, size);
++}
++
+ /* Fallback SG-buffer allocations for x86 */
+ struct snd_dma_sg_fallback {
+ size_t count;
+@@ -671,14 +730,11 @@ struct snd_dma_sg_fallback {
+ static void __snd_dma_sg_fallback_free(struct snd_dma_buffer *dmab,
+ struct snd_dma_sg_fallback *sgbuf)
+ {
++ bool wc = dmab->dev.type == SNDRV_DMA_TYPE_DEV_WC_SG_FALLBACK;
+ size_t i;
+
+- if (sgbuf->count && dmab->dev.type == SNDRV_DMA_TYPE_DEV_WC_SG_FALLBACK)
+- set_pages_array_wb(sgbuf->pages, sgbuf->count);
+ for (i = 0; i < sgbuf->count && sgbuf->pages[i]; i++)
+- dma_free_coherent(dmab->dev.dev, PAGE_SIZE,
+- page_address(sgbuf->pages[i]),
+- sgbuf->addrs[i]);
++ do_free_fallback_pages(page_address(sgbuf->pages[i]), PAGE_SIZE, wc);
+ kvfree(sgbuf->pages);
+ kvfree(sgbuf->addrs);
+ kfree(sgbuf);
+@@ -690,6 +746,7 @@ static void *snd_dma_sg_fallback_alloc(s
+ struct page **pages;
+ size_t i, count;
+ void *p;
++ bool wc = dmab->dev.type == SNDRV_DMA_TYPE_DEV_WC_SG_FALLBACK;
+
+ sgbuf = kzalloc(sizeof(*sgbuf), GFP_KERNEL);
+ if (!sgbuf)
+@@ -704,15 +761,13 @@ static void *snd_dma_sg_fallback_alloc(s
+ goto error;
+
+ for (i = 0; i < count; sgbuf->count++, i++) {
+- p = dma_alloc_coherent(dmab->dev.dev, PAGE_SIZE,
+- &sgbuf->addrs[i], DEFAULT_GFP);
++ p = do_alloc_fallback_pages(dmab->dev.dev, PAGE_SIZE,
++ &sgbuf->addrs[i], wc);
+ if (!p)
+ goto error;
+ sgbuf->pages[i] = virt_to_page(p);
+ }
+
+- if (dmab->dev.type == SNDRV_DMA_TYPE_DEV_WC_SG_FALLBACK)
+- set_pages_array_wc(pages, count);
+ p = vmap(pages, count, VM_MAP, PAGE_KERNEL);
+ if (!p)
+ goto error;
--- /dev/null
+From 3e7e04b747adea36f349715d9f0998eeebf15d72 Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Tue, 23 Aug 2022 09:27:17 +0200
+Subject: ALSA: seq: Fix data-race at module auto-loading
+
+From: Takashi Iwai <tiwai@suse.de>
+
+commit 3e7e04b747adea36f349715d9f0998eeebf15d72 upstream.
+
+It's been reported that there is a possible data-race accessing to the
+global card_requested[] array at ALSA sequencer core, which is used
+for determining whether to call request_module() for the card or not.
+This data race itself is almost harmless, as it might end up with one
+extra request_module() call for the already loaded module at most.
+But it's still better to fix.
+
+This patch addresses the possible data race of card_requested[] and
+client_requested[] arrays by replacing them with bitmask.
+It's an atomic operation and can work without locks.
+
+Reported-by: Abhishek Shah <abhishek.shah@columbia.edu>
+Cc: <stable@vger.kernel.org>
+Link: https://lore.kernel.org/r/CAEHB24_ay6YzARpA1zgCsE7=H9CSJJzux618E=Ka4h0YdKn=qA@mail.gmail.com
+Link: https://lore.kernel.org/r/20220823072717.1706-2-tiwai@suse.de
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ sound/core/seq/seq_clientmgr.c | 12 +++++-------
+ 1 file changed, 5 insertions(+), 7 deletions(-)
+
+--- a/sound/core/seq/seq_clientmgr.c
++++ b/sound/core/seq/seq_clientmgr.c
+@@ -121,13 +121,13 @@ struct snd_seq_client *snd_seq_client_us
+ spin_unlock_irqrestore(&clients_lock, flags);
+ #ifdef CONFIG_MODULES
+ if (!in_interrupt()) {
+- static char client_requested[SNDRV_SEQ_GLOBAL_CLIENTS];
+- static char card_requested[SNDRV_CARDS];
++ static DECLARE_BITMAP(client_requested, SNDRV_SEQ_GLOBAL_CLIENTS);
++ static DECLARE_BITMAP(card_requested, SNDRV_CARDS);
++
+ if (clientid < SNDRV_SEQ_GLOBAL_CLIENTS) {
+ int idx;
+
+- if (!client_requested[clientid]) {
+- client_requested[clientid] = 1;
++ if (!test_and_set_bit(clientid, client_requested)) {
+ for (idx = 0; idx < 15; idx++) {
+ if (seq_client_load[idx] < 0)
+ break;
+@@ -142,10 +142,8 @@ struct snd_seq_client *snd_seq_client_us
+ int card = (clientid - SNDRV_SEQ_GLOBAL_CLIENTS) /
+ SNDRV_SEQ_CLIENTS_PER_CARD;
+ if (card < snd_ecards_limit) {
+- if (! card_requested[card]) {
+- card_requested[card] = 1;
++ if (!test_and_set_bit(card, card_requested))
+ snd_request_card(card);
+- }
+ snd_seq_device_load_drivers();
+ }
+ }
--- /dev/null
+From 22dec134dbfa825b963f8a1807ad19b943e46a56 Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Tue, 23 Aug 2022 09:27:16 +0200
+Subject: ALSA: seq: oss: Fix data-race for max_midi_devs access
+
+From: Takashi Iwai <tiwai@suse.de>
+
+commit 22dec134dbfa825b963f8a1807ad19b943e46a56 upstream.
+
+ALSA OSS sequencer refers to a global variable max_midi_devs at
+creating a new port, storing it to its own field. Meanwhile this
+variable may be changed by other sequencer events at
+snd_seq_oss_midi_check_exit_port() in parallel, which may cause a data
+race.
+
+OTOH, this data race itself is almost harmless, as the access to the
+MIDI device is done via get_mdev() and it's protected with a refcount,
+hence its presence is guaranteed.
+
+Though, it's sill better to address the data-race from the code sanity
+POV, and this patch adds the proper spinlock for the protection.
+
+Reported-by: Abhishek Shah <abhishek.shah@columbia.edu>
+Cc: <stable@vger.kernel.org>
+Link: https://lore.kernel.org/r/CAEHB2493pZRXs863w58QWnUTtv3HHfg85aYhLn5HJHCwxqtHQg@mail.gmail.com
+Link: https://lore.kernel.org/r/20220823072717.1706-1-tiwai@suse.de
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ sound/core/seq/oss/seq_oss_midi.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/sound/core/seq/oss/seq_oss_midi.c
++++ b/sound/core/seq/oss/seq_oss_midi.c
+@@ -270,7 +270,9 @@ snd_seq_oss_midi_clear_all(void)
+ void
+ snd_seq_oss_midi_setup(struct seq_oss_devinfo *dp)
+ {
++ spin_lock_irq(®ister_lock);
+ dp->max_mididev = max_midi_devs;
++ spin_unlock_irq(®ister_lock);
+ }
+
+ /*
--- /dev/null
+From 51fbbe8a3f8b9dd128fa98f6ea36058dfa3f36de Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Jouni=20H=C3=B6gander?= <jouni.hogander@intel.com>
+Date: Mon, 22 Aug 2022 17:08:36 +0300
+Subject: drm/i915/backlight: Disable pps power hook for aux based backlight
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Jouni Högander <jouni.hogander@intel.com>
+
+commit 51fbbe8a3f8b9dd128fa98f6ea36058dfa3f36de upstream.
+
+Pps power hook seems to be problematic for backlight controlled via
+aux channel. Disable it for such cases.
+
+Closes: https://gitlab.freedesktop.org/drm/intel/-/issues/3657
+Cc: stable@vger.kernel.org
+Signed-off-by: Jouni Högander <jouni.hogander@intel.com>
+Signed-off-by: Jani Nikula <jani.nikula@intel.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20220822140836.534432-1-jouni.hogander@intel.com
+(cherry picked from commit 869e3bb7acb59d88c1226892136661810e8223a4)
+Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/i915/display/intel_backlight.c | 11 ++++++++---
+ drivers/gpu/drm/i915/display/intel_dp.c | 2 --
+ 2 files changed, 8 insertions(+), 5 deletions(-)
+
+--- a/drivers/gpu/drm/i915/display/intel_backlight.c
++++ b/drivers/gpu/drm/i915/display/intel_backlight.c
+@@ -15,6 +15,7 @@
+ #include "intel_dsi_dcs_backlight.h"
+ #include "intel_panel.h"
+ #include "intel_pci_config.h"
++#include "intel_pps.h"
+
+ /**
+ * scale - scale values from one range to another
+@@ -1769,9 +1770,13 @@ void intel_backlight_init_funcs(struct i
+ panel->backlight.pwm_funcs = &i9xx_pwm_funcs;
+ }
+
+- if (connector->base.connector_type == DRM_MODE_CONNECTOR_eDP &&
+- intel_dp_aux_init_backlight_funcs(connector) == 0)
+- return;
++ if (connector->base.connector_type == DRM_MODE_CONNECTOR_eDP) {
++ if (intel_dp_aux_init_backlight_funcs(connector) == 0)
++ return;
++
++ if (!(dev_priv->quirks & QUIRK_NO_PPS_BACKLIGHT_POWER_HOOK))
++ connector->panel.backlight.power = intel_pps_backlight_power;
++ }
+
+ /* We're using a standard PWM backlight interface */
+ panel->backlight.funcs = &pwm_bl_funcs;
+--- a/drivers/gpu/drm/i915/display/intel_dp.c
++++ b/drivers/gpu/drm/i915/display/intel_dp.c
+@@ -5248,8 +5248,6 @@ static bool intel_edp_init_connector(str
+
+ intel_panel_init(intel_connector);
+
+- if (!(dev_priv->quirks & QUIRK_NO_PPS_BACKLIGHT_POWER_HOOK))
+- intel_connector->panel.backlight.power = intel_pps_backlight_power;
+ intel_backlight_setup(intel_connector, pipe);
+
+ intel_edp_add_properties(intel_dp);
--- /dev/null
+From 919bef7a106ade2bda73681bbc2f3678198f44fc Mon Sep 17 00:00:00 2001
+From: Diego Santa Cruz <Diego.SantaCruz@spinetix.com>
+Date: Thu, 16 Jun 2022 15:41:37 +0300
+Subject: drm/i915/glk: ECS Liva Q2 needs GLK HDMI port timing quirk
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Diego Santa Cruz <Diego.SantaCruz@spinetix.com>
+
+commit 919bef7a106ade2bda73681bbc2f3678198f44fc upstream.
+
+The quirk added in upstream commit 90c3e2198777 ("drm/i915/glk: Add
+Quirk for GLK NUC HDMI port issues.") is also required on the ECS Liva
+Q2.
+
+Note: Would be nicer to figure out the extra delay required for the
+retimer without quirks, however don't know how to check for that.
+
+Cc: stable@vger.kernel.org
+Closes: https://gitlab.freedesktop.org/drm/intel/-/issues/1326
+Signed-off-by: Diego Santa Cruz <Diego.SantaCruz@spinetix.com>
+Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
+Signed-off-by: Jani Nikula <jani.nikula@intel.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20220616124137.3184371-1-jani.nikula@intel.com
+(cherry picked from commit 08e9505fa8f9aa00072a47b6f234d89b6b27a89c)
+Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/i915/display/intel_quirks.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+--- a/drivers/gpu/drm/i915/display/intel_quirks.c
++++ b/drivers/gpu/drm/i915/display/intel_quirks.c
+@@ -191,6 +191,9 @@ static struct intel_quirk intel_quirks[]
+ /* ASRock ITX*/
+ { 0x3185, 0x1849, 0x2212, quirk_increase_ddi_disabled_time },
+ { 0x3184, 0x1849, 0x2212, quirk_increase_ddi_disabled_time },
++ /* ECS Liva Q2 */
++ { 0x3185, 0x1019, 0xa94d, quirk_increase_ddi_disabled_time },
++ { 0x3184, 0x1019, 0xa94d, quirk_increase_ddi_disabled_time },
+ };
+
+ void intel_init_quirks(struct drm_i915_private *i915)
--- /dev/null
+From 4595a25443447b9542b2a5ee7961eb290e94b496 Mon Sep 17 00:00:00 2001
+From: Daniele Ceraolo Spurio <daniele.ceraolospurio@intel.com>
+Date: Thu, 11 Aug 2022 14:08:12 -0700
+Subject: drm/i915/guc: clear stalled request after a reset
+
+From: Daniele Ceraolo Spurio <daniele.ceraolospurio@intel.com>
+
+commit 4595a25443447b9542b2a5ee7961eb290e94b496 upstream.
+
+If the GuC CTs are full and we need to stall the request submission
+while waiting for space, we save the stalled request and where the stall
+occurred; when the CTs have space again we pick up the request submission
+from where we left off.
+
+If a full GT reset occurs, the state of all contexts is cleared and all
+non-guilty requests are unsubmitted, therefore we need to restart the
+stalled request submission from scratch. To make sure that we do so,
+clear the saved request after a reset.
+
+Fixes note: the patch that introduced the bug is in 5.15, but no
+officially supported platform had GuC submission enabled by default
+in that kernel, so the backport to that particular version (and only
+that one) can potentially be skipped.
+
+Fixes: 925dc1cf58ed ("drm/i915/guc: Implement GuC submission tasklet")
+Signed-off-by: Daniele Ceraolo Spurio <daniele.ceraolospurio@intel.com>
+Cc: Matthew Brost <matthew.brost@intel.com>
+Cc: John Harrison <john.c.harrison@intel.com>
+Cc: <stable@vger.kernel.org> # v5.15+
+Reviewed-by: John Harrison <John.C.Harrison@Intel.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20220811210812.3239621-1-daniele.ceraolospurio@intel.com
+(cherry picked from commit f922fbb0f2ad1fd3e3186f39c46673419e6d9281)
+Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+--- a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c
++++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c
+@@ -4011,6 +4011,13 @@ static inline void guc_init_lrc_mapping(
+ xa_destroy(&guc->context_lookup);
+
+ /*
++ * A reset might have occurred while we had a pending stalled request,
++ * so make sure we clean that up.
++ */
++ guc->stalled_request = NULL;
++ guc->submission_stall_reason = STALL_NONE;
++
++ /*
+ * Some contexts might have been pinned before we enabled GuC
+ * submission, so we need to add them to the GuC bookeeping.
+ * Also, after a reset the of the GuC we want to make sure that the
--- /dev/null
+From 0211c2a0ea600e25db3044daaeff4fe41c3ed6d9 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= <ville.syrjala@linux.intel.com>
+Date: Fri, 17 Jun 2022 22:59:48 +0300
+Subject: drm/i915: Skip wm/ddb readout for disabled pipes
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Ville Syrjälä <ville.syrjala@linux.intel.com>
+
+commit 0211c2a0ea600e25db3044daaeff4fe41c3ed6d9 upstream.
+
+The stuff programmed into the wm/ddb registers of planes
+on disabled pipes doesn't matter. So during readout just
+leave our software state tracking for those zeroed.
+
+This should avoid us trying too hard to clean up after
+whatever mess the VBIOS/GOP left in there. The actual
+hardware state will get cleaned up if/when we enable
+the pipe anyway.
+
+Cc: stable@vger.kernel.org
+Closes: https://gitlab.freedesktop.org/drm/intel/-/issues/5711
+Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20220617195948.24007-1-ville.syrjala@linux.intel.com
+Reviewed-by: Stanislav Lisovskiy <stanislav.lisovskiy@intel.com>
+(cherry picked from commit b183db8f4783ca2efc9b47734f15aad9477a108a)
+Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/i915/intel_pm.c | 8 +++++++-
+ 1 file changed, 7 insertions(+), 1 deletion(-)
+
+--- a/drivers/gpu/drm/i915/intel_pm.c
++++ b/drivers/gpu/drm/i915/intel_pm.c
+@@ -6560,7 +6560,10 @@ void skl_wm_get_hw_state(struct drm_i915
+ enum plane_id plane_id;
+ u8 slices;
+
+- skl_pipe_wm_get_hw_state(crtc, &crtc_state->wm.skl.optimal);
++ memset(&crtc_state->wm.skl.optimal, 0,
++ sizeof(crtc_state->wm.skl.optimal));
++ if (crtc_state->hw.active)
++ skl_pipe_wm_get_hw_state(crtc, &crtc_state->wm.skl.optimal);
+ crtc_state->wm.skl.raw = crtc_state->wm.skl.optimal;
+
+ memset(&dbuf_state->ddb[pipe], 0, sizeof(dbuf_state->ddb[pipe]));
+@@ -6571,6 +6574,9 @@ void skl_wm_get_hw_state(struct drm_i915
+ struct skl_ddb_entry *ddb_y =
+ &crtc_state->wm.skl.plane_ddb_y[plane_id];
+
++ if (!crtc_state->hw.active)
++ continue;
++
+ skl_ddb_get_hw_plane_state(dev_priv, crtc->pipe,
+ plane_id, ddb, ddb_y);
+
--- /dev/null
+From eb55dc09b5dd040232d5de32812cc83001a23da6 Mon Sep 17 00:00:00 2001
+From: Nicolas Dichtel <nicolas.dichtel@6wind.com>
+Date: Mon, 29 Aug 2022 12:01:21 +0200
+Subject: ip: fix triggering of 'icmp redirect'
+
+From: Nicolas Dichtel <nicolas.dichtel@6wind.com>
+
+commit eb55dc09b5dd040232d5de32812cc83001a23da6 upstream.
+
+__mkroute_input() uses fib_validate_source() to trigger an icmp redirect.
+My understanding is that fib_validate_source() is used to know if the src
+address and the gateway address are on the same link. For that,
+fib_validate_source() returns 1 (same link) or 0 (not the same network).
+__mkroute_input() is the only user of these positive values, all other
+callers only look if the returned value is negative.
+
+Since the below patch, fib_validate_source() didn't return anymore 1 when
+both addresses are on the same network, because the route lookup returns
+RT_SCOPE_LINK instead of RT_SCOPE_HOST. But this is, in fact, right.
+Let's adapat the test to return 1 again when both addresses are on the same
+link.
+
+CC: stable@vger.kernel.org
+Fixes: 747c14307214 ("ip: fix dflt addr selection for connected nexthop")
+Reported-by: kernel test robot <yujie.liu@intel.com>
+Reported-by: Heng Qi <hengqi@linux.alibaba.com>
+Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
+Reviewed-by: David Ahern <dsahern@kernel.org>
+Link: https://lore.kernel.org/r/20220829100121.3821-1-nicolas.dichtel@6wind.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/ipv4/fib_frontend.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/net/ipv4/fib_frontend.c
++++ b/net/ipv4/fib_frontend.c
+@@ -389,7 +389,7 @@ static int __fib_validate_source(struct
+ dev_match = dev_match || (res.type == RTN_LOCAL &&
+ dev == net->loopback_dev);
+ if (dev_match) {
+- ret = FIB_RES_NHC(res)->nhc_scope >= RT_SCOPE_HOST;
++ ret = FIB_RES_NHC(res)->nhc_scope >= RT_SCOPE_LINK;
+ return ret;
+ }
+ if (no_addr)
+@@ -401,7 +401,7 @@ static int __fib_validate_source(struct
+ ret = 0;
+ if (fib_lookup(net, &fl4, &res, FIB_LOOKUP_IGNORE_LINKSTATE) == 0) {
+ if (res.type == RTN_UNICAST)
+- ret = FIB_RES_NHC(res)->nhc_scope >= RT_SCOPE_HOST;
++ ret = FIB_RES_NHC(res)->nhc_scope >= RT_SCOPE_LINK;
+ }
+ return ret;
+
--- /dev/null
+From f0da47118c7e93cdbbc6fb403dd729a5f2c90ee3 Mon Sep 17 00:00:00 2001
+From: Miquel Raynal <miquel.raynal@bootlin.com>
+Date: Fri, 26 Aug 2022 16:29:54 +0200
+Subject: net: mac802154: Fix a condition in the receive path
+
+From: Miquel Raynal <miquel.raynal@bootlin.com>
+
+commit f0da47118c7e93cdbbc6fb403dd729a5f2c90ee3 upstream.
+
+Upon reception, a packet must be categorized, either it's destination is
+the host, or it is another host. A packet with no destination addressing
+fields may be valid in two situations:
+- the packet has no source field: only ACKs are built like that, we
+ consider the host as the destination.
+- the packet has a valid source field: it is directed to the PAN
+ coordinator, as for know we don't have this information we consider we
+ are not the PAN coordinator.
+
+There was likely a copy/paste error made during a previous cleanup
+because the if clause is now containing exactly the same condition as in
+the switch case, which can never be true. In the past the destination
+address was used in the switch and the source address was used in the
+if, which matches what the spec says.
+
+Cc: stable@vger.kernel.org
+Fixes: ae531b9475f6 ("ieee802154: use ieee802154_addr instead of *_sa variants")
+Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
+Link: https://lore.kernel.org/r/20220826142954.254853-1-miquel.raynal@bootlin.com
+Signed-off-by: Stefan Schmidt <stefan@datenfreihafen.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/mac802154/rx.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/net/mac802154/rx.c
++++ b/net/mac802154/rx.c
+@@ -44,7 +44,7 @@ ieee802154_subif_frame(struct ieee802154
+
+ switch (mac_cb(skb)->dest.mode) {
+ case IEEE802154_ADDR_NONE:
+- if (mac_cb(skb)->dest.mode != IEEE802154_ADDR_NONE)
++ if (hdr->source.mode != IEEE802154_ADDR_NONE)
+ /* FIXME: check if we are PAN coordinator */
+ skb->pkt_type = PACKET_OTHERHOST;
+ else
--- /dev/null
+From 278d3ba61563ceed3cb248383ced19e14ec7bc1f Mon Sep 17 00:00:00 2001
+From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Date: Thu, 25 Aug 2022 13:36:45 +0200
+Subject: net: Use u64_stats_fetch_begin_irq() for stats fetch.
+
+From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+
+commit 278d3ba61563ceed3cb248383ced19e14ec7bc1f upstream.
+
+On 32bit-UP u64_stats_fetch_begin() disables only preemption. If the
+reader is in preemptible context and the writer side
+(u64_stats_update_begin*()) runs in an interrupt context (IRQ or
+softirq) then the writer can update the stats during the read operation.
+This update remains undetected.
+
+Use u64_stats_fetch_begin_irq() to ensure the stats fetch on 32bit-UP
+are not interrupted by a writer. 32bit-SMP remains unaffected by this
+change.
+
+Cc: "David S. Miller" <davem@davemloft.net>
+Cc: Catherine Sullivan <csully@google.com>
+Cc: David Awogbemila <awogbemila@google.com>
+Cc: Dimitris Michailidis <dmichail@fungible.com>
+Cc: Eric Dumazet <edumazet@google.com>
+Cc: Hans Ulli Kroll <ulli.kroll@googlemail.com>
+Cc: Jakub Kicinski <kuba@kernel.org>
+Cc: Jeroen de Borst <jeroendb@google.com>
+Cc: Johannes Berg <johannes@sipsolutions.net>
+Cc: Linus Walleij <linus.walleij@linaro.org>
+Cc: Paolo Abeni <pabeni@redhat.com>
+Cc: Simon Horman <simon.horman@corigine.com>
+Cc: linux-arm-kernel@lists.infradead.org
+Cc: linux-wireless@vger.kernel.org
+Cc: netdev@vger.kernel.org
+Cc: oss-drivers@corigine.com
+Cc: stable@vger.kernel.org
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Reviewed-by: Simon Horman <simon.horman@corigine.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/ethernet/cortina/gemini.c | 24 +++++++++----------
+ drivers/net/ethernet/fungible/funeth/funeth_txrx.h | 4 +--
+ drivers/net/ethernet/google/gve/gve_ethtool.c | 16 ++++++------
+ drivers/net/ethernet/google/gve/gve_main.c | 12 ++++-----
+ drivers/net/ethernet/huawei/hinic/hinic_rx.c | 4 +--
+ drivers/net/ethernet/huawei/hinic/hinic_tx.c | 4 +--
+ drivers/net/ethernet/netronome/nfp/nfp_net_common.c | 8 +++---
+ drivers/net/ethernet/netronome/nfp/nfp_net_ethtool.c | 8 +++---
+ drivers/net/netdevsim/netdev.c | 4 +--
+ net/mac80211/sta_info.c | 8 +++---
+ net/mpls/af_mpls.c | 4 +--
+ 11 files changed, 48 insertions(+), 48 deletions(-)
+
+--- a/drivers/net/ethernet/cortina/gemini.c
++++ b/drivers/net/ethernet/cortina/gemini.c
+@@ -1919,7 +1919,7 @@ static void gmac_get_stats64(struct net_
+
+ /* Racing with RX NAPI */
+ do {
+- start = u64_stats_fetch_begin(&port->rx_stats_syncp);
++ start = u64_stats_fetch_begin_irq(&port->rx_stats_syncp);
+
+ stats->rx_packets = port->stats.rx_packets;
+ stats->rx_bytes = port->stats.rx_bytes;
+@@ -1931,11 +1931,11 @@ static void gmac_get_stats64(struct net_
+ stats->rx_crc_errors = port->stats.rx_crc_errors;
+ stats->rx_frame_errors = port->stats.rx_frame_errors;
+
+- } while (u64_stats_fetch_retry(&port->rx_stats_syncp, start));
++ } while (u64_stats_fetch_retry_irq(&port->rx_stats_syncp, start));
+
+ /* Racing with MIB and TX completion interrupts */
+ do {
+- start = u64_stats_fetch_begin(&port->ir_stats_syncp);
++ start = u64_stats_fetch_begin_irq(&port->ir_stats_syncp);
+
+ stats->tx_errors = port->stats.tx_errors;
+ stats->tx_packets = port->stats.tx_packets;
+@@ -1945,15 +1945,15 @@ static void gmac_get_stats64(struct net_
+ stats->rx_missed_errors = port->stats.rx_missed_errors;
+ stats->rx_fifo_errors = port->stats.rx_fifo_errors;
+
+- } while (u64_stats_fetch_retry(&port->ir_stats_syncp, start));
++ } while (u64_stats_fetch_retry_irq(&port->ir_stats_syncp, start));
+
+ /* Racing with hard_start_xmit */
+ do {
+- start = u64_stats_fetch_begin(&port->tx_stats_syncp);
++ start = u64_stats_fetch_begin_irq(&port->tx_stats_syncp);
+
+ stats->tx_dropped = port->stats.tx_dropped;
+
+- } while (u64_stats_fetch_retry(&port->tx_stats_syncp, start));
++ } while (u64_stats_fetch_retry_irq(&port->tx_stats_syncp, start));
+
+ stats->rx_dropped += stats->rx_missed_errors;
+ }
+@@ -2031,18 +2031,18 @@ static void gmac_get_ethtool_stats(struc
+ /* Racing with MIB interrupt */
+ do {
+ p = values;
+- start = u64_stats_fetch_begin(&port->ir_stats_syncp);
++ start = u64_stats_fetch_begin_irq(&port->ir_stats_syncp);
+
+ for (i = 0; i < RX_STATS_NUM; i++)
+ *p++ = port->hw_stats[i];
+
+- } while (u64_stats_fetch_retry(&port->ir_stats_syncp, start));
++ } while (u64_stats_fetch_retry_irq(&port->ir_stats_syncp, start));
+ values = p;
+
+ /* Racing with RX NAPI */
+ do {
+ p = values;
+- start = u64_stats_fetch_begin(&port->rx_stats_syncp);
++ start = u64_stats_fetch_begin_irq(&port->rx_stats_syncp);
+
+ for (i = 0; i < RX_STATUS_NUM; i++)
+ *p++ = port->rx_stats[i];
+@@ -2050,13 +2050,13 @@ static void gmac_get_ethtool_stats(struc
+ *p++ = port->rx_csum_stats[i];
+ *p++ = port->rx_napi_exits;
+
+- } while (u64_stats_fetch_retry(&port->rx_stats_syncp, start));
++ } while (u64_stats_fetch_retry_irq(&port->rx_stats_syncp, start));
+ values = p;
+
+ /* Racing with TX start_xmit */
+ do {
+ p = values;
+- start = u64_stats_fetch_begin(&port->tx_stats_syncp);
++ start = u64_stats_fetch_begin_irq(&port->tx_stats_syncp);
+
+ for (i = 0; i < TX_MAX_FRAGS; i++) {
+ *values++ = port->tx_frag_stats[i];
+@@ -2065,7 +2065,7 @@ static void gmac_get_ethtool_stats(struc
+ *values++ = port->tx_frags_linearized;
+ *values++ = port->tx_hw_csummed;
+
+- } while (u64_stats_fetch_retry(&port->tx_stats_syncp, start));
++ } while (u64_stats_fetch_retry_irq(&port->tx_stats_syncp, start));
+ }
+
+ static int gmac_get_ksettings(struct net_device *netdev,
+--- a/drivers/net/ethernet/fungible/funeth/funeth_txrx.h
++++ b/drivers/net/ethernet/fungible/funeth/funeth_txrx.h
+@@ -205,9 +205,9 @@ struct funeth_rxq {
+
+ #define FUN_QSTAT_READ(q, seq, stats_copy) \
+ do { \
+- seq = u64_stats_fetch_begin(&(q)->syncp); \
++ seq = u64_stats_fetch_begin_irq(&(q)->syncp); \
+ stats_copy = (q)->stats; \
+- } while (u64_stats_fetch_retry(&(q)->syncp, (seq)))
++ } while (u64_stats_fetch_retry_irq(&(q)->syncp, (seq)))
+
+ #define FUN_INT_NAME_LEN (IFNAMSIZ + 16)
+
+--- a/drivers/net/ethernet/google/gve/gve_ethtool.c
++++ b/drivers/net/ethernet/google/gve/gve_ethtool.c
+@@ -177,14 +177,14 @@ gve_get_ethtool_stats(struct net_device
+ struct gve_rx_ring *rx = &priv->rx[ring];
+
+ start =
+- u64_stats_fetch_begin(&priv->rx[ring].statss);
++ u64_stats_fetch_begin_irq(&priv->rx[ring].statss);
+ tmp_rx_pkts = rx->rpackets;
+ tmp_rx_bytes = rx->rbytes;
+ tmp_rx_skb_alloc_fail = rx->rx_skb_alloc_fail;
+ tmp_rx_buf_alloc_fail = rx->rx_buf_alloc_fail;
+ tmp_rx_desc_err_dropped_pkt =
+ rx->rx_desc_err_dropped_pkt;
+- } while (u64_stats_fetch_retry(&priv->rx[ring].statss,
++ } while (u64_stats_fetch_retry_irq(&priv->rx[ring].statss,
+ start));
+ rx_pkts += tmp_rx_pkts;
+ rx_bytes += tmp_rx_bytes;
+@@ -198,10 +198,10 @@ gve_get_ethtool_stats(struct net_device
+ if (priv->tx) {
+ do {
+ start =
+- u64_stats_fetch_begin(&priv->tx[ring].statss);
++ u64_stats_fetch_begin_irq(&priv->tx[ring].statss);
+ tmp_tx_pkts = priv->tx[ring].pkt_done;
+ tmp_tx_bytes = priv->tx[ring].bytes_done;
+- } while (u64_stats_fetch_retry(&priv->tx[ring].statss,
++ } while (u64_stats_fetch_retry_irq(&priv->tx[ring].statss,
+ start));
+ tx_pkts += tmp_tx_pkts;
+ tx_bytes += tmp_tx_bytes;
+@@ -259,13 +259,13 @@ gve_get_ethtool_stats(struct net_device
+ data[i++] = rx->fill_cnt - rx->cnt;
+ do {
+ start =
+- u64_stats_fetch_begin(&priv->rx[ring].statss);
++ u64_stats_fetch_begin_irq(&priv->rx[ring].statss);
+ tmp_rx_bytes = rx->rbytes;
+ tmp_rx_skb_alloc_fail = rx->rx_skb_alloc_fail;
+ tmp_rx_buf_alloc_fail = rx->rx_buf_alloc_fail;
+ tmp_rx_desc_err_dropped_pkt =
+ rx->rx_desc_err_dropped_pkt;
+- } while (u64_stats_fetch_retry(&priv->rx[ring].statss,
++ } while (u64_stats_fetch_retry_irq(&priv->rx[ring].statss,
+ start));
+ data[i++] = tmp_rx_bytes;
+ data[i++] = rx->rx_cont_packet_cnt;
+@@ -331,9 +331,9 @@ gve_get_ethtool_stats(struct net_device
+ }
+ do {
+ start =
+- u64_stats_fetch_begin(&priv->tx[ring].statss);
++ u64_stats_fetch_begin_irq(&priv->tx[ring].statss);
+ tmp_tx_bytes = tx->bytes_done;
+- } while (u64_stats_fetch_retry(&priv->tx[ring].statss,
++ } while (u64_stats_fetch_retry_irq(&priv->tx[ring].statss,
+ start));
+ data[i++] = tmp_tx_bytes;
+ data[i++] = tx->wake_queue;
+--- a/drivers/net/ethernet/google/gve/gve_main.c
++++ b/drivers/net/ethernet/google/gve/gve_main.c
+@@ -51,10 +51,10 @@ static void gve_get_stats(struct net_dev
+ for (ring = 0; ring < priv->rx_cfg.num_queues; ring++) {
+ do {
+ start =
+- u64_stats_fetch_begin(&priv->rx[ring].statss);
++ u64_stats_fetch_begin_irq(&priv->rx[ring].statss);
+ packets = priv->rx[ring].rpackets;
+ bytes = priv->rx[ring].rbytes;
+- } while (u64_stats_fetch_retry(&priv->rx[ring].statss,
++ } while (u64_stats_fetch_retry_irq(&priv->rx[ring].statss,
+ start));
+ s->rx_packets += packets;
+ s->rx_bytes += bytes;
+@@ -64,10 +64,10 @@ static void gve_get_stats(struct net_dev
+ for (ring = 0; ring < priv->tx_cfg.num_queues; ring++) {
+ do {
+ start =
+- u64_stats_fetch_begin(&priv->tx[ring].statss);
++ u64_stats_fetch_begin_irq(&priv->tx[ring].statss);
+ packets = priv->tx[ring].pkt_done;
+ bytes = priv->tx[ring].bytes_done;
+- } while (u64_stats_fetch_retry(&priv->tx[ring].statss,
++ } while (u64_stats_fetch_retry_irq(&priv->tx[ring].statss,
+ start));
+ s->tx_packets += packets;
+ s->tx_bytes += bytes;
+@@ -1274,9 +1274,9 @@ void gve_handle_report_stats(struct gve_
+ }
+
+ do {
+- start = u64_stats_fetch_begin(&priv->tx[idx].statss);
++ start = u64_stats_fetch_begin_irq(&priv->tx[idx].statss);
+ tx_bytes = priv->tx[idx].bytes_done;
+- } while (u64_stats_fetch_retry(&priv->tx[idx].statss, start));
++ } while (u64_stats_fetch_retry_irq(&priv->tx[idx].statss, start));
+ stats[stats_idx++] = (struct stats) {
+ .stat_name = cpu_to_be32(TX_WAKE_CNT),
+ .value = cpu_to_be64(priv->tx[idx].wake_queue),
+--- a/drivers/net/ethernet/huawei/hinic/hinic_rx.c
++++ b/drivers/net/ethernet/huawei/hinic/hinic_rx.c
+@@ -74,14 +74,14 @@ void hinic_rxq_get_stats(struct hinic_rx
+ unsigned int start;
+
+ do {
+- start = u64_stats_fetch_begin(&rxq_stats->syncp);
++ start = u64_stats_fetch_begin_irq(&rxq_stats->syncp);
+ stats->pkts = rxq_stats->pkts;
+ stats->bytes = rxq_stats->bytes;
+ stats->errors = rxq_stats->csum_errors +
+ rxq_stats->other_errors;
+ stats->csum_errors = rxq_stats->csum_errors;
+ stats->other_errors = rxq_stats->other_errors;
+- } while (u64_stats_fetch_retry(&rxq_stats->syncp, start));
++ } while (u64_stats_fetch_retry_irq(&rxq_stats->syncp, start));
+ }
+
+ /**
+--- a/drivers/net/ethernet/huawei/hinic/hinic_tx.c
++++ b/drivers/net/ethernet/huawei/hinic/hinic_tx.c
+@@ -99,14 +99,14 @@ void hinic_txq_get_stats(struct hinic_tx
+ unsigned int start;
+
+ do {
+- start = u64_stats_fetch_begin(&txq_stats->syncp);
++ start = u64_stats_fetch_begin_irq(&txq_stats->syncp);
+ stats->pkts = txq_stats->pkts;
+ stats->bytes = txq_stats->bytes;
+ stats->tx_busy = txq_stats->tx_busy;
+ stats->tx_wake = txq_stats->tx_wake;
+ stats->tx_dropped = txq_stats->tx_dropped;
+ stats->big_frags_pkts = txq_stats->big_frags_pkts;
+- } while (u64_stats_fetch_retry(&txq_stats->syncp, start));
++ } while (u64_stats_fetch_retry_irq(&txq_stats->syncp, start));
+ }
+
+ /**
+--- a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
++++ b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
+@@ -1629,21 +1629,21 @@ static void nfp_net_stat64(struct net_de
+ unsigned int start;
+
+ do {
+- start = u64_stats_fetch_begin(&r_vec->rx_sync);
++ start = u64_stats_fetch_begin_irq(&r_vec->rx_sync);
+ data[0] = r_vec->rx_pkts;
+ data[1] = r_vec->rx_bytes;
+ data[2] = r_vec->rx_drops;
+- } while (u64_stats_fetch_retry(&r_vec->rx_sync, start));
++ } while (u64_stats_fetch_retry_irq(&r_vec->rx_sync, start));
+ stats->rx_packets += data[0];
+ stats->rx_bytes += data[1];
+ stats->rx_dropped += data[2];
+
+ do {
+- start = u64_stats_fetch_begin(&r_vec->tx_sync);
++ start = u64_stats_fetch_begin_irq(&r_vec->tx_sync);
+ data[0] = r_vec->tx_pkts;
+ data[1] = r_vec->tx_bytes;
+ data[2] = r_vec->tx_errors;
+- } while (u64_stats_fetch_retry(&r_vec->tx_sync, start));
++ } while (u64_stats_fetch_retry_irq(&r_vec->tx_sync, start));
+ stats->tx_packets += data[0];
+ stats->tx_bytes += data[1];
+ stats->tx_errors += data[2];
+--- a/drivers/net/ethernet/netronome/nfp/nfp_net_ethtool.c
++++ b/drivers/net/ethernet/netronome/nfp/nfp_net_ethtool.c
+@@ -494,7 +494,7 @@ static u64 *nfp_vnic_get_sw_stats(struct
+ unsigned int start;
+
+ do {
+- start = u64_stats_fetch_begin(&nn->r_vecs[i].rx_sync);
++ start = u64_stats_fetch_begin_irq(&nn->r_vecs[i].rx_sync);
+ data[0] = nn->r_vecs[i].rx_pkts;
+ tmp[0] = nn->r_vecs[i].hw_csum_rx_ok;
+ tmp[1] = nn->r_vecs[i].hw_csum_rx_inner_ok;
+@@ -502,10 +502,10 @@ static u64 *nfp_vnic_get_sw_stats(struct
+ tmp[3] = nn->r_vecs[i].hw_csum_rx_error;
+ tmp[4] = nn->r_vecs[i].rx_replace_buf_alloc_fail;
+ tmp[5] = nn->r_vecs[i].hw_tls_rx;
+- } while (u64_stats_fetch_retry(&nn->r_vecs[i].rx_sync, start));
++ } while (u64_stats_fetch_retry_irq(&nn->r_vecs[i].rx_sync, start));
+
+ do {
+- start = u64_stats_fetch_begin(&nn->r_vecs[i].tx_sync);
++ start = u64_stats_fetch_begin_irq(&nn->r_vecs[i].tx_sync);
+ data[1] = nn->r_vecs[i].tx_pkts;
+ data[2] = nn->r_vecs[i].tx_busy;
+ tmp[6] = nn->r_vecs[i].hw_csum_tx;
+@@ -515,7 +515,7 @@ static u64 *nfp_vnic_get_sw_stats(struct
+ tmp[10] = nn->r_vecs[i].hw_tls_tx;
+ tmp[11] = nn->r_vecs[i].tls_tx_fallback;
+ tmp[12] = nn->r_vecs[i].tls_tx_no_fallback;
+- } while (u64_stats_fetch_retry(&nn->r_vecs[i].tx_sync, start));
++ } while (u64_stats_fetch_retry_irq(&nn->r_vecs[i].tx_sync, start));
+
+ data += NN_RVEC_PER_Q_STATS;
+
+--- a/drivers/net/netdevsim/netdev.c
++++ b/drivers/net/netdevsim/netdev.c
+@@ -67,10 +67,10 @@ nsim_get_stats64(struct net_device *dev,
+ unsigned int start;
+
+ do {
+- start = u64_stats_fetch_begin(&ns->syncp);
++ start = u64_stats_fetch_begin_irq(&ns->syncp);
+ stats->tx_bytes = ns->tx_bytes;
+ stats->tx_packets = ns->tx_packets;
+- } while (u64_stats_fetch_retry(&ns->syncp, start));
++ } while (u64_stats_fetch_retry_irq(&ns->syncp, start));
+ }
+
+ static int
+--- a/net/mac80211/sta_info.c
++++ b/net/mac80211/sta_info.c
+@@ -2221,9 +2221,9 @@ static inline u64 sta_get_tidstats_msdu(
+ u64 value;
+
+ do {
+- start = u64_stats_fetch_begin(&rxstats->syncp);
++ start = u64_stats_fetch_begin_irq(&rxstats->syncp);
+ value = rxstats->msdu[tid];
+- } while (u64_stats_fetch_retry(&rxstats->syncp, start));
++ } while (u64_stats_fetch_retry_irq(&rxstats->syncp, start));
+
+ return value;
+ }
+@@ -2289,9 +2289,9 @@ static inline u64 sta_get_stats_bytes(st
+ u64 value;
+
+ do {
+- start = u64_stats_fetch_begin(&rxstats->syncp);
++ start = u64_stats_fetch_begin_irq(&rxstats->syncp);
+ value = rxstats->bytes;
+- } while (u64_stats_fetch_retry(&rxstats->syncp, start));
++ } while (u64_stats_fetch_retry_irq(&rxstats->syncp, start));
+
+ return value;
+ }
+--- a/net/mpls/af_mpls.c
++++ b/net/mpls/af_mpls.c
+@@ -1079,9 +1079,9 @@ static void mpls_get_stats(struct mpls_d
+
+ p = per_cpu_ptr(mdev->stats, i);
+ do {
+- start = u64_stats_fetch_begin(&p->syncp);
++ start = u64_stats_fetch_begin_irq(&p->syncp);
+ local = p->stats;
+- } while (u64_stats_fetch_retry(&p->syncp, start));
++ } while (u64_stats_fetch_retry_irq(&p->syncp, start));
+
+ stats->rx_packets += local.rx_packets;
+ stats->rx_bytes += local.rx_bytes;
dma-buf-dma-resv-check-if-the-new-fence-is-really-later.patch
arm64-kexec-fix-missing-extra-range-for-crashkres_low.patch
driver-core-don-t-probe-devices-after-bus_type.match-probe-deferral.patch
+wifi-mac80211-don-t-finalize-csa-in-ibss-mode-if-state-is-disconnected.patch
+wifi-mac80211-fix-uaf-in-ieee80211_scan_rx.patch
+ip-fix-triggering-of-icmp-redirect.patch
+net-use-u64_stats_fetch_begin_irq-for-stats-fetch.patch
+net-mac802154-fix-a-condition-in-the-receive-path.patch
+alsa-memalloc-revive-x86-specific-wc-page-allocations-again.patch
+alsa-hda-realtek-add-speaker-amp-init-for-samsung-laptops-with-alc298.patch
+alsa-seq-oss-fix-data-race-for-max_midi_devs-access.patch
+alsa-seq-fix-data-race-at-module-auto-loading.patch
+drm-i915-backlight-disable-pps-power-hook-for-aux-based-backlight.patch
+drm-i915-guc-clear-stalled-request-after-a-reset.patch
+drm-i915-glk-ecs-liva-q2-needs-glk-hdmi-port-timing-quirk.patch
+drm-i915-skip-wm-ddb-readout-for-disabled-pipes.patch
+tty-n_gsm-add-sanity-check-for-gsm-receive-in-gsm_receive_buf.patch
+tty-n_gsm-initialize-more-members-at-gsm_alloc_mux.patch
+tty-n_gsm-replace-kicktimer-with-delayed_work.patch
+tty-n_gsm-avoid-call-of-sleeping-functions-from-atomic-context.patch
--- /dev/null
+From f16c6d2e58a4c2b972efcf9eb12390ee0ba3befb Mon Sep 17 00:00:00 2001
+From: Mazin Al Haddad <mazinalhaddad05@gmail.com>
+Date: Sun, 14 Aug 2022 04:52:12 +0300
+Subject: tty: n_gsm: add sanity check for gsm->receive in gsm_receive_buf()
+
+From: Mazin Al Haddad <mazinalhaddad05@gmail.com>
+
+commit f16c6d2e58a4c2b972efcf9eb12390ee0ba3befb upstream.
+
+A null pointer dereference can happen when attempting to access the
+"gsm->receive()" function in gsmld_receive_buf(). Currently, the code
+assumes that gsm->recieve is only called after MUX activation.
+Since the gsmld_receive_buf() function can be accessed without the need to
+initialize the MUX, the gsm->receive() function will not be set and a
+NULL pointer dereference will occur.
+
+Fix this by avoiding the call to "gsm->receive()" in case the function is
+not initialized by adding a sanity check.
+
+Call Trace:
+ <TASK>
+ gsmld_receive_buf+0x1c2/0x2f0 drivers/tty/n_gsm.c:2861
+ tiocsti drivers/tty/tty_io.c:2293 [inline]
+ tty_ioctl+0xa75/0x15d0 drivers/tty/tty_io.c:2692
+ vfs_ioctl fs/ioctl.c:51 [inline]
+ __do_sys_ioctl fs/ioctl.c:870 [inline]
+ __se_sys_ioctl fs/ioctl.c:856 [inline]
+ __x64_sys_ioctl+0x193/0x200 fs/ioctl.c:856
+ do_syscall_x64 arch/x86/entry/common.c:50 [inline]
+ do_syscall_64+0x35/0xb0 arch/x86/entry/common.c:80
+ entry_SYSCALL_64_after_hwframe+0x63/0xcd
+
+Link: https://syzkaller.appspot.com/bug?id=bdf035c61447f8c6e0e6920315d577cb5cc35ac5
+Fixes: 01aecd917114 ("tty: n_gsm: fix tty registration before control channel open")
+Cc: stable <stable@kernel.org>
+Reported-and-tested-by: syzbot+e3563f0c94e188366dbb@syzkaller.appspotmail.com
+Signed-off-by: Mazin Al Haddad <mazinalhaddad05@gmail.com>
+Link: https://lore.kernel.org/r/20220814015211.84180-1-mazinalhaddad05@gmail.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/tty/n_gsm.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/drivers/tty/n_gsm.c
++++ b/drivers/tty/n_gsm.c
+@@ -2858,7 +2858,8 @@ static void gsmld_receive_buf(struct tty
+ flags = *fp++;
+ switch (flags) {
+ case TTY_NORMAL:
+- gsm->receive(gsm, *cp);
++ if (gsm->receive)
++ gsm->receive(gsm, *cp);
+ break;
+ case TTY_OVERRUN:
+ case TTY_BREAK:
--- /dev/null
+From 902e02ea9385373ce4b142576eef41c642703955 Mon Sep 17 00:00:00 2001
+From: Fedor Pchelkin <pchelkin@ispras.ru>
+Date: Mon, 29 Aug 2022 16:16:40 +0300
+Subject: tty: n_gsm: avoid call of sleeping functions from atomic context
+
+From: Fedor Pchelkin <pchelkin@ispras.ru>
+
+commit 902e02ea9385373ce4b142576eef41c642703955 upstream.
+
+Syzkaller reports the following problem:
+
+BUG: sleeping function called from invalid context at kernel/printk/printk.c:2347
+in_atomic(): 1, irqs_disabled(): 1, non_block: 0, pid: 1105, name: syz-executor423
+3 locks held by syz-executor423/1105:
+ #0: ffff8881468b9098 (&tty->ldisc_sem){++++}-{0:0}, at: tty_ldisc_ref_wait+0x22/0x90 drivers/tty/tty_ldisc.c:266
+ #1: ffff8881468b9130 (&tty->atomic_write_lock){+.+.}-{3:3}, at: tty_write_lock drivers/tty/tty_io.c:952 [inline]
+ #1: ffff8881468b9130 (&tty->atomic_write_lock){+.+.}-{3:3}, at: do_tty_write drivers/tty/tty_io.c:975 [inline]
+ #1: ffff8881468b9130 (&tty->atomic_write_lock){+.+.}-{3:3}, at: file_tty_write.constprop.0+0x2a8/0x8e0 drivers/tty/tty_io.c:1118
+ #2: ffff88801b06c398 (&gsm->tx_lock){....}-{2:2}, at: gsmld_write+0x5e/0x150 drivers/tty/n_gsm.c:2717
+irq event stamp: 3482
+hardirqs last enabled at (3481): [<ffffffff81d13343>] __get_reqs_available+0x143/0x2f0 fs/aio.c:946
+hardirqs last disabled at (3482): [<ffffffff87d39722>] __raw_spin_lock_irqsave include/linux/spinlock_api_smp.h:108 [inline]
+hardirqs last disabled at (3482): [<ffffffff87d39722>] _raw_spin_lock_irqsave+0x52/0x60 kernel/locking/spinlock.c:159
+softirqs last enabled at (3408): [<ffffffff87e01002>] asm_call_irq_on_stack+0x12/0x20
+softirqs last disabled at (3401): [<ffffffff87e01002>] asm_call_irq_on_stack+0x12/0x20
+Preemption disabled at:
+[<0000000000000000>] 0x0
+CPU: 2 PID: 1105 Comm: syz-executor423 Not tainted 5.10.137-syzkaller #0
+Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.12.0-1 04/01/2014
+Call Trace:
+ __dump_stack lib/dump_stack.c:77 [inline]
+ dump_stack+0x107/0x167 lib/dump_stack.c:118
+ ___might_sleep.cold+0x1e8/0x22e kernel/sched/core.c:7304
+ console_lock+0x19/0x80 kernel/printk/printk.c:2347
+ do_con_write+0x113/0x1de0 drivers/tty/vt/vt.c:2909
+ con_write+0x22/0xc0 drivers/tty/vt/vt.c:3296
+ gsmld_write+0xd0/0x150 drivers/tty/n_gsm.c:2720
+ do_tty_write drivers/tty/tty_io.c:1028 [inline]
+ file_tty_write.constprop.0+0x502/0x8e0 drivers/tty/tty_io.c:1118
+ call_write_iter include/linux/fs.h:1903 [inline]
+ aio_write+0x355/0x7b0 fs/aio.c:1580
+ __io_submit_one fs/aio.c:1952 [inline]
+ io_submit_one+0xf45/0x1a90 fs/aio.c:1999
+ __do_sys_io_submit fs/aio.c:2058 [inline]
+ __se_sys_io_submit fs/aio.c:2028 [inline]
+ __x64_sys_io_submit+0x18c/0x2f0 fs/aio.c:2028
+ do_syscall_64+0x33/0x40 arch/x86/entry/common.c:46
+ entry_SYSCALL_64_after_hwframe+0x61/0xc6
+
+The problem happens in the following control flow:
+
+gsmld_write(...)
+spin_lock_irqsave(&gsm->tx_lock, flags) // taken a spinlock on TX data
+ con_write(...)
+ do_con_write(...)
+ console_lock()
+ might_sleep() // -> bug
+
+As far as console_lock() might sleep it should not be called with
+spinlock held.
+
+The patch replaces tx_lock spinlock with mutex in order to avoid the
+problem.
+
+Found by Linux Verification Center (linuxtesting.org) with Syzkaller.
+
+Fixes: 32dd59f96924 ("tty: n_gsm: fix race condition in gsmld_write()")
+Cc: stable <stable@kernel.org>
+Signed-off-by: Fedor Pchelkin <pchelkin@ispras.ru>
+Signed-off-by: Alexey Khoroshilov <khoroshilov@ispras.ru>
+Link: https://lore.kernel.org/r/20220829131640.69254-3-pchelkin@ispras.ru
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/tty/n_gsm.c | 53 +++++++++++++++++++++++-----------------------------
+ 1 file changed, 24 insertions(+), 29 deletions(-)
+
+--- a/drivers/tty/n_gsm.c
++++ b/drivers/tty/n_gsm.c
+@@ -248,7 +248,7 @@ struct gsm_mux {
+ bool constipated; /* Asked by remote to shut up */
+ bool has_devices; /* Devices were registered */
+
+- spinlock_t tx_lock;
++ struct mutex tx_mutex;
+ unsigned int tx_bytes; /* TX data outstanding */
+ #define TX_THRESH_HI 8192
+ #define TX_THRESH_LO 2048
+@@ -680,7 +680,6 @@ static int gsm_send(struct gsm_mux *gsm,
+ struct gsm_msg *msg;
+ u8 *dp;
+ int ocr;
+- unsigned long flags;
+
+ msg = gsm_data_alloc(gsm, addr, 0, control);
+ if (!msg)
+@@ -702,10 +701,10 @@ static int gsm_send(struct gsm_mux *gsm,
+
+ gsm_print_packet("Q->", addr, cr, control, NULL, 0);
+
+- spin_lock_irqsave(&gsm->tx_lock, flags);
++ mutex_lock(&gsm->tx_mutex);
+ list_add_tail(&msg->list, &gsm->tx_ctrl_list);
+ gsm->tx_bytes += msg->len;
+- spin_unlock_irqrestore(&gsm->tx_lock, flags);
++ mutex_unlock(&gsm->tx_mutex);
+ gsmld_write_trigger(gsm);
+
+ return 0;
+@@ -730,7 +729,7 @@ static void gsm_dlci_clear_queues(struct
+ spin_unlock_irqrestore(&dlci->lock, flags);
+
+ /* Clear data packets in MUX write queue */
+- spin_lock_irqsave(&gsm->tx_lock, flags);
++ mutex_lock(&gsm->tx_mutex);
+ list_for_each_entry_safe(msg, nmsg, &gsm->tx_data_list, list) {
+ if (msg->addr != addr)
+ continue;
+@@ -738,7 +737,7 @@ static void gsm_dlci_clear_queues(struct
+ list_del(&msg->list);
+ kfree(msg);
+ }
+- spin_unlock_irqrestore(&gsm->tx_lock, flags);
++ mutex_unlock(&gsm->tx_mutex);
+ }
+
+ /**
+@@ -1024,10 +1023,9 @@ static void __gsm_data_queue(struct gsm_
+
+ static void gsm_data_queue(struct gsm_dlci *dlci, struct gsm_msg *msg)
+ {
+- unsigned long flags;
+- spin_lock_irqsave(&dlci->gsm->tx_lock, flags);
++ mutex_lock(&dlci->gsm->tx_mutex);
+ __gsm_data_queue(dlci, msg);
+- spin_unlock_irqrestore(&dlci->gsm->tx_lock, flags);
++ mutex_unlock(&dlci->gsm->tx_mutex);
+ }
+
+ /**
+@@ -1039,7 +1037,7 @@ static void gsm_data_queue(struct gsm_dl
+ * is data. Keep to the MRU of the mux. This path handles the usual tty
+ * interface which is a byte stream with optional modem data.
+ *
+- * Caller must hold the tx_lock of the mux.
++ * Caller must hold the tx_mutex of the mux.
+ */
+
+ static int gsm_dlci_data_output(struct gsm_mux *gsm, struct gsm_dlci *dlci)
+@@ -1099,7 +1097,7 @@ static int gsm_dlci_data_output(struct g
+ * is data. Keep to the MRU of the mux. This path handles framed data
+ * queued as skbuffs to the DLCI.
+ *
+- * Caller must hold the tx_lock of the mux.
++ * Caller must hold the tx_mutex of the mux.
+ */
+
+ static int gsm_dlci_data_output_framed(struct gsm_mux *gsm,
+@@ -1115,7 +1113,7 @@ static int gsm_dlci_data_output_framed(s
+ if (dlci->adaption == 4)
+ overhead = 1;
+
+- /* dlci->skb is locked by tx_lock */
++ /* dlci->skb is locked by tx_mutex */
+ if (dlci->skb == NULL) {
+ dlci->skb = skb_dequeue_tail(&dlci->skb_list);
+ if (dlci->skb == NULL)
+@@ -1169,7 +1167,7 @@ static int gsm_dlci_data_output_framed(s
+ * Push an empty frame in to the transmit queue to update the modem status
+ * bits and to transmit an optional break.
+ *
+- * Caller must hold the tx_lock of the mux.
++ * Caller must hold the tx_mutex of the mux.
+ */
+
+ static int gsm_dlci_modem_output(struct gsm_mux *gsm, struct gsm_dlci *dlci,
+@@ -1283,13 +1281,12 @@ static int gsm_dlci_data_sweep(struct gs
+
+ static void gsm_dlci_data_kick(struct gsm_dlci *dlci)
+ {
+- unsigned long flags;
+ int sweep;
+
+ if (dlci->constipated)
+ return;
+
+- spin_lock_irqsave(&dlci->gsm->tx_lock, flags);
++ mutex_lock(&dlci->gsm->tx_mutex);
+ /* If we have nothing running then we need to fire up */
+ sweep = (dlci->gsm->tx_bytes < TX_THRESH_LO);
+ if (dlci->gsm->tx_bytes == 0) {
+@@ -1300,7 +1297,7 @@ static void gsm_dlci_data_kick(struct gs
+ }
+ if (sweep)
+ gsm_dlci_data_sweep(dlci->gsm);
+- spin_unlock_irqrestore(&dlci->gsm->tx_lock, flags);
++ mutex_unlock(&dlci->gsm->tx_mutex);
+ }
+
+ /*
+@@ -1994,14 +1991,13 @@ static void gsm_dlci_command(struct gsm_
+ static void gsm_kick_timeout(struct work_struct *work)
+ {
+ struct gsm_mux *gsm = container_of(work, struct gsm_mux, kick_timeout.work);
+- unsigned long flags;
+ int sent = 0;
+
+- spin_lock_irqsave(&gsm->tx_lock, flags);
++ mutex_lock(&gsm->tx_mutex);
+ /* If we have nothing running then we need to fire up */
+ if (gsm->tx_bytes < TX_THRESH_LO)
+ sent = gsm_dlci_data_sweep(gsm);
+- spin_unlock_irqrestore(&gsm->tx_lock, flags);
++ mutex_unlock(&gsm->tx_mutex);
+
+ if (sent && debug & 4)
+ pr_info("%s TX queue stalled\n", __func__);
+@@ -2531,6 +2527,7 @@ static void gsm_free_mux(struct gsm_mux
+ break;
+ }
+ }
++ mutex_destroy(&gsm->tx_mutex);
+ mutex_destroy(&gsm->mutex);
+ kfree(gsm->txframe);
+ kfree(gsm->buf);
+@@ -2602,6 +2599,7 @@ static struct gsm_mux *gsm_alloc_mux(voi
+ }
+ spin_lock_init(&gsm->lock);
+ mutex_init(&gsm->mutex);
++ mutex_init(&gsm->tx_mutex);
+ kref_init(&gsm->ref);
+ INIT_LIST_HEAD(&gsm->tx_ctrl_list);
+ INIT_LIST_HEAD(&gsm->tx_data_list);
+@@ -2610,7 +2608,6 @@ static struct gsm_mux *gsm_alloc_mux(voi
+ INIT_WORK(&gsm->tx_work, gsmld_write_task);
+ init_waitqueue_head(&gsm->event);
+ spin_lock_init(&gsm->control_lock);
+- spin_lock_init(&gsm->tx_lock);
+
+ gsm->t1 = T1;
+ gsm->t2 = T2;
+@@ -2635,6 +2632,7 @@ static struct gsm_mux *gsm_alloc_mux(voi
+ }
+ spin_unlock(&gsm_mux_lock);
+ if (i == MAX_MUX) {
++ mutex_destroy(&gsm->tx_mutex);
+ mutex_destroy(&gsm->mutex);
+ kfree(gsm->txframe);
+ kfree(gsm->buf);
+@@ -2790,17 +2788,16 @@ static void gsmld_write_trigger(struct g
+ static void gsmld_write_task(struct work_struct *work)
+ {
+ struct gsm_mux *gsm = container_of(work, struct gsm_mux, tx_work);
+- unsigned long flags;
+ int i, ret;
+
+ /* All outstanding control channel and control messages and one data
+ * frame is sent.
+ */
+ ret = -ENODEV;
+- spin_lock_irqsave(&gsm->tx_lock, flags);
++ mutex_lock(&gsm->tx_mutex);
+ if (gsm->tty)
+ ret = gsm_data_kick(gsm);
+- spin_unlock_irqrestore(&gsm->tx_lock, flags);
++ mutex_unlock(&gsm->tx_mutex);
+
+ if (ret >= 0)
+ for (i = 0; i < NUM_DLCI; i++)
+@@ -3008,7 +3005,6 @@ static ssize_t gsmld_write(struct tty_st
+ const unsigned char *buf, size_t nr)
+ {
+ struct gsm_mux *gsm = tty->disc_data;
+- unsigned long flags;
+ int space;
+ int ret;
+
+@@ -3016,13 +3012,13 @@ static ssize_t gsmld_write(struct tty_st
+ return -ENODEV;
+
+ ret = -ENOBUFS;
+- spin_lock_irqsave(&gsm->tx_lock, flags);
++ mutex_lock(&gsm->tx_mutex);
+ space = tty_write_room(tty);
+ if (space >= nr)
+ ret = tty->ops->write(tty, buf, nr);
+ else
+ set_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
+- spin_unlock_irqrestore(&gsm->tx_lock, flags);
++ mutex_unlock(&gsm->tx_mutex);
+
+ return ret;
+ }
+@@ -3319,14 +3315,13 @@ static struct tty_ldisc_ops tty_ldisc_pa
+ static void gsm_modem_upd_via_data(struct gsm_dlci *dlci, u8 brk)
+ {
+ struct gsm_mux *gsm = dlci->gsm;
+- unsigned long flags;
+
+ if (dlci->state != DLCI_OPEN || dlci->adaption != 2)
+ return;
+
+- spin_lock_irqsave(&gsm->tx_lock, flags);
++ mutex_lock(&gsm->tx_mutex);
+ gsm_dlci_modem_output(gsm, dlci, brk);
+- spin_unlock_irqrestore(&gsm->tx_lock, flags);
++ mutex_unlock(&gsm->tx_mutex);
+ }
+
+ /**
--- /dev/null
+From 4bb1a53be85fcb1e24c14860e326a00cdd362c28 Mon Sep 17 00:00:00 2001
+From: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
+Date: Sat, 27 Aug 2022 22:47:19 +0900
+Subject: tty: n_gsm: initialize more members at gsm_alloc_mux()
+
+From: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
+
+commit 4bb1a53be85fcb1e24c14860e326a00cdd362c28 upstream.
+
+syzbot is reporting use of uninitialized spinlock at gsmld_write() [1], for
+commit 32dd59f96924f45e ("tty: n_gsm: fix race condition in gsmld_write()")
+allows accessing gsm->tx_lock before gsm_activate_mux() initializes it.
+
+Since object initialization should be done right after allocation in order
+to avoid accessing uninitialized memory, move initialization of
+timer/work/waitqueue/spinlock from gsmld_open()/gsm_activate_mux() to
+gsm_alloc_mux().
+
+Link: https://syzkaller.appspot.com/bug?extid=cf155def4e717db68a12 [1]
+Fixes: 32dd59f96924f45e ("tty: n_gsm: fix race condition in gsmld_write()")
+Reported-by: syzbot <syzbot+cf155def4e717db68a12@syzkaller.appspotmail.com>
+Tested-by: syzbot <syzbot+cf155def4e717db68a12@syzkaller.appspotmail.com>
+Cc: stable <stable@kernel.org>
+Acked-by: Jiri Slaby <jirislaby@kernel.org>
+Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
+Link: https://lore.kernel.org/r/2110618e-57f0-c1ce-b2ad-b6cacef3f60e@I-love.SAKURA.ne.jp
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/tty/n_gsm.c | 17 ++++++-----------
+ 1 file changed, 6 insertions(+), 11 deletions(-)
+
+--- a/drivers/tty/n_gsm.c
++++ b/drivers/tty/n_gsm.c
+@@ -2501,13 +2501,6 @@ static int gsm_activate_mux(struct gsm_m
+ if (dlci == NULL)
+ return -ENOMEM;
+
+- timer_setup(&gsm->kick_timer, gsm_kick_timer, 0);
+- timer_setup(&gsm->t2_timer, gsm_control_retransmit, 0);
+- INIT_WORK(&gsm->tx_work, gsmld_write_task);
+- init_waitqueue_head(&gsm->event);
+- spin_lock_init(&gsm->control_lock);
+- spin_lock_init(&gsm->tx_lock);
+-
+ if (gsm->encoding == 0)
+ gsm->receive = gsm0_receive;
+ else
+@@ -2612,6 +2605,12 @@ static struct gsm_mux *gsm_alloc_mux(voi
+ kref_init(&gsm->ref);
+ INIT_LIST_HEAD(&gsm->tx_ctrl_list);
+ INIT_LIST_HEAD(&gsm->tx_data_list);
++ timer_setup(&gsm->kick_timer, gsm_kick_timer, 0);
++ timer_setup(&gsm->t2_timer, gsm_control_retransmit, 0);
++ INIT_WORK(&gsm->tx_work, gsmld_write_task);
++ init_waitqueue_head(&gsm->event);
++ spin_lock_init(&gsm->control_lock);
++ spin_lock_init(&gsm->tx_lock);
+
+ gsm->t1 = T1;
+ gsm->t2 = T2;
+@@ -2947,10 +2946,6 @@ static int gsmld_open(struct tty_struct
+
+ gsmld_attach_gsm(tty, gsm);
+
+- timer_setup(&gsm->kick_timer, gsm_kick_timer, 0);
+- timer_setup(&gsm->t2_timer, gsm_control_retransmit, 0);
+- INIT_WORK(&gsm->tx_work, gsmld_write_task);
+-
+ return 0;
+ }
+
--- /dev/null
+From c9ab053e56ce13a949977398c8edc12e6c02fc95 Mon Sep 17 00:00:00 2001
+From: Fedor Pchelkin <pchelkin@ispras.ru>
+Date: Mon, 29 Aug 2022 16:16:39 +0300
+Subject: tty: n_gsm: replace kicktimer with delayed_work
+
+From: Fedor Pchelkin <pchelkin@ispras.ru>
+
+commit c9ab053e56ce13a949977398c8edc12e6c02fc95 upstream.
+
+A kick_timer timer_list is replaced with kick_timeout delayed_work to be
+able to synchronize with mutexes as a prerequisite for the introduction
+of tx_mutex.
+
+Found by Linux Verification Center (linuxtesting.org) with Syzkaller.
+
+Fixes: c568f7086c6e ("tty: n_gsm: fix missing timer to handle stalled links")
+Cc: stable <stable@kernel.org>
+Reviewed-by: Jiri Slaby <jirislaby@kernel.org>
+Suggested-by: Hillf Danton <hdanton@sina.com>
+Signed-off-by: Fedor Pchelkin <pchelkin@ispras.ru>
+Signed-off-by: Alexey Khoroshilov <khoroshilov@ispras.ru>
+Link: https://lore.kernel.org/r/20220829131640.69254-2-pchelkin@ispras.ru
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/tty/n_gsm.c | 16 ++++++++--------
+ 1 file changed, 8 insertions(+), 8 deletions(-)
+
+diff --git a/drivers/tty/n_gsm.c b/drivers/tty/n_gsm.c
+index d6598ca3640f..e23225aff5d9 100644
+--- a/drivers/tty/n_gsm.c
++++ b/drivers/tty/n_gsm.c
+@@ -256,7 +256,7 @@ struct gsm_mux {
+ struct list_head tx_data_list; /* Pending data packets */
+
+ /* Control messages */
+- struct timer_list kick_timer; /* Kick TX queuing on timeout */
++ struct delayed_work kick_timeout; /* Kick TX queuing on timeout */
+ struct timer_list t2_timer; /* Retransmit timer for commands */
+ int cretries; /* Command retry counter */
+ struct gsm_control *pending_cmd;/* Our current pending command */
+@@ -1009,7 +1009,7 @@ static void __gsm_data_queue(struct gsm_dlci *dlci, struct gsm_msg *msg)
+ gsm->tx_bytes += msg->len;
+
+ gsmld_write_trigger(gsm);
+- mod_timer(&gsm->kick_timer, jiffies + 10 * gsm->t1 * HZ / 100);
++ schedule_delayed_work(&gsm->kick_timeout, 10 * gsm->t1 * HZ / 100);
+ }
+
+ /**
+@@ -1984,16 +1984,16 @@ static void gsm_dlci_command(struct gsm_dlci *dlci, const u8 *data, int len)
+ }
+
+ /**
+- * gsm_kick_timer - transmit if possible
+- * @t: timer contained in our gsm object
++ * gsm_kick_timeout - transmit if possible
++ * @work: work contained in our gsm object
+ *
+ * Transmit data from DLCIs if the queue is empty. We can't rely on
+ * a tty wakeup except when we filled the pipe so we need to fire off
+ * new data ourselves in other cases.
+ */
+-static void gsm_kick_timer(struct timer_list *t)
++static void gsm_kick_timeout(struct work_struct *work)
+ {
+- struct gsm_mux *gsm = from_timer(gsm, t, kick_timer);
++ struct gsm_mux *gsm = container_of(work, struct gsm_mux, kick_timeout.work);
+ unsigned long flags;
+ int sent = 0;
+
+@@ -2458,7 +2458,7 @@ static void gsm_cleanup_mux(struct gsm_mux *gsm, bool disc)
+ }
+
+ /* Finish outstanding timers, making sure they are done */
+- del_timer_sync(&gsm->kick_timer);
++ cancel_delayed_work_sync(&gsm->kick_timeout);
+ del_timer_sync(&gsm->t2_timer);
+
+ /* Finish writing to ldisc */
+@@ -2605,7 +2605,7 @@ static struct gsm_mux *gsm_alloc_mux(void)
+ kref_init(&gsm->ref);
+ INIT_LIST_HEAD(&gsm->tx_ctrl_list);
+ INIT_LIST_HEAD(&gsm->tx_data_list);
+- timer_setup(&gsm->kick_timer, gsm_kick_timer, 0);
++ INIT_DELAYED_WORK(&gsm->kick_timeout, gsm_kick_timeout);
+ timer_setup(&gsm->t2_timer, gsm_control_retransmit, 0);
+ INIT_WORK(&gsm->tx_work, gsmld_write_task);
+ init_waitqueue_head(&gsm->event);
+--
+2.37.3
+
--- /dev/null
+From 15bc8966b6d3a5b9bfe4c9facfa02f2b69b1e5f0 Mon Sep 17 00:00:00 2001
+From: Siddh Raman Pant <code@siddh.me>
+Date: Sun, 14 Aug 2022 20:45:12 +0530
+Subject: wifi: mac80211: Don't finalize CSA in IBSS mode if state is disconnected
+
+From: Siddh Raman Pant <code@siddh.me>
+
+commit 15bc8966b6d3a5b9bfe4c9facfa02f2b69b1e5f0 upstream.
+
+When we are not connected to a channel, sending channel "switch"
+announcement doesn't make any sense.
+
+The BSS list is empty in that case. This causes the for loop in
+cfg80211_get_bss() to be bypassed, so the function returns NULL
+(check line 1424 of net/wireless/scan.c), causing the WARN_ON()
+in ieee80211_ibss_csa_beacon() to get triggered (check line 500
+of net/mac80211/ibss.c), which was consequently reported on the
+syzkaller dashboard.
+
+Thus, check if we have an existing connection before generating
+the CSA beacon in ieee80211_ibss_finish_csa().
+
+Cc: stable@vger.kernel.org
+Fixes: cd7760e62c2a ("mac80211: add support for CSA in IBSS mode")
+Link: https://syzkaller.appspot.com/bug?id=05603ef4ae8926761b678d2939a3b2ad28ab9ca6
+Reported-by: syzbot+b6c9fe29aefe68e4ad34@syzkaller.appspotmail.com
+Signed-off-by: Siddh Raman Pant <code@siddh.me>
+Tested-by: syzbot+b6c9fe29aefe68e4ad34@syzkaller.appspotmail.com
+Link: https://lore.kernel.org/r/20220814151512.9985-1-code@siddh.me
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/mac80211/ibss.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+--- a/net/mac80211/ibss.c
++++ b/net/mac80211/ibss.c
+@@ -534,6 +534,10 @@ int ieee80211_ibss_finish_csa(struct iee
+
+ sdata_assert_lock(sdata);
+
++ /* When not connected/joined, sending CSA doesn't make sense. */
++ if (ifibss->state != IEEE80211_IBSS_MLME_JOINED)
++ return -ENOLINK;
++
+ /* update cfg80211 bss information with the new channel */
+ if (!is_zero_ether_addr(ifibss->bssid)) {
+ cbss = cfg80211_get_bss(sdata->local->hw.wiphy,
--- /dev/null
+From 60deb9f10eec5c6a20252ed36238b55d8b614a2c Mon Sep 17 00:00:00 2001
+From: Siddh Raman Pant <code@siddh.me>
+Date: Sat, 20 Aug 2022 01:33:40 +0530
+Subject: wifi: mac80211: Fix UAF in ieee80211_scan_rx()
+
+From: Siddh Raman Pant <code@siddh.me>
+
+commit 60deb9f10eec5c6a20252ed36238b55d8b614a2c upstream.
+
+ieee80211_scan_rx() tries to access scan_req->flags after a
+null check, but a UAF is observed when the scan is completed
+and __ieee80211_scan_completed() executes, which then calls
+cfg80211_scan_done() leading to the freeing of scan_req.
+
+Since scan_req is rcu_dereference()'d, prevent the racing in
+__ieee80211_scan_completed() by ensuring that from mac80211's
+POV it is no longer accessed from an RCU read critical section
+before we call cfg80211_scan_done().
+
+Cc: stable@vger.kernel.org
+Link: https://syzkaller.appspot.com/bug?extid=f9acff9bf08a845f225d
+Reported-by: syzbot+f9acff9bf08a845f225d@syzkaller.appspotmail.com
+Suggested-by: Johannes Berg <johannes@sipsolutions.net>
+Signed-off-by: Siddh Raman Pant <code@siddh.me>
+Link: https://lore.kernel.org/r/20220819200340.34826-1-code@siddh.me
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/mac80211/scan.c | 11 +++++++----
+ 1 file changed, 7 insertions(+), 4 deletions(-)
+
+--- a/net/mac80211/scan.c
++++ b/net/mac80211/scan.c
+@@ -465,16 +465,19 @@ static void __ieee80211_scan_completed(s
+ scan_req = rcu_dereference_protected(local->scan_req,
+ lockdep_is_held(&local->mtx));
+
+- if (scan_req != local->int_scan_req) {
+- local->scan_info.aborted = aborted;
+- cfg80211_scan_done(scan_req, &local->scan_info);
+- }
+ RCU_INIT_POINTER(local->scan_req, NULL);
+ RCU_INIT_POINTER(local->scan_sdata, NULL);
+
+ local->scanning = 0;
+ local->scan_chandef.chan = NULL;
+
++ synchronize_rcu();
++
++ if (scan_req != local->int_scan_req) {
++ local->scan_info.aborted = aborted;
++ cfg80211_scan_done(scan_req, &local->scan_info);
++ }
++
+ /* Set power back to normal operating levels. */
+ ieee80211_hw_config(local, 0);
+