From: Sasha Levin Date: Sun, 1 Dec 2024 12:06:12 +0000 (-0500) Subject: Fixes for 6.12 X-Git-Tag: v4.19.325~126 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=fd2ab3767d9e5fb0097ea605d4f9529c11995444;p=thirdparty%2Fkernel%2Fstable-queue.git Fixes for 6.12 Signed-off-by: Sasha Levin --- diff --git a/queue-6.12/accel-ivpu-prevent-recovery-invocation-during-probe-.patch b/queue-6.12/accel-ivpu-prevent-recovery-invocation-during-probe-.patch new file mode 100644 index 00000000000..fb54c133f3e --- /dev/null +++ b/queue-6.12/accel-ivpu-prevent-recovery-invocation-during-probe-.patch @@ -0,0 +1,179 @@ +From 0803cdf276267b9ec11cf286093a2a75a6cf1c11 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 30 Sep 2024 21:53:13 +0200 +Subject: accel/ivpu: Prevent recovery invocation during probe and resume + +From: Karol Wachowski + +[ Upstream commit 5eaa497411197c41b0813d61ba3fbd6267049082 ] + +Refactor IPC send and receive functions to allow correct +handling of operations that should not trigger a recovery process. + +Expose ivpu_send_receive_internal(), which is now utilized by the D0i3 +entry, DCT initialization, and HWS initialization functions. +These functions have been modified to return error codes gracefully, +rather than initiating recovery. + +The updated functions are invoked within ivpu_probe() and ivpu_resume(), +ensuring that any errors encountered during these stages result in a proper +teardown or shutdown sequence. The previous approach of triggering recovery +within these functions could lead to a race condition, potentially causing +undefined behavior and kernel crashes due to null pointer dereferences. + +Fixes: 45e45362e095 ("accel/ivpu: Introduce ivpu_ipc_send_receive_active()") +Signed-off-by: Karol Wachowski +Reviewed-by: Jacek Lawrynowicz +Link: https://patchwork.freedesktop.org/patch/msgid/20240930195322.461209-23-jacek.lawrynowicz@linux.intel.com +Signed-off-by: Jacek Lawrynowicz +Signed-off-by: Sasha Levin +--- + drivers/accel/ivpu/ivpu_ipc.c | 35 +++++++++++-------------------- + drivers/accel/ivpu/ivpu_ipc.h | 7 +++---- + drivers/accel/ivpu/ivpu_jsm_msg.c | 19 +++++++---------- + 3 files changed, 23 insertions(+), 38 deletions(-) + +diff --git a/drivers/accel/ivpu/ivpu_ipc.c b/drivers/accel/ivpu/ivpu_ipc.c +index 78b32a8232419..29b723039a345 100644 +--- a/drivers/accel/ivpu/ivpu_ipc.c ++++ b/drivers/accel/ivpu/ivpu_ipc.c +@@ -291,15 +291,16 @@ int ivpu_ipc_receive(struct ivpu_device *vdev, struct ivpu_ipc_consumer *cons, + return ret; + } + +-static int ++int + ivpu_ipc_send_receive_internal(struct ivpu_device *vdev, struct vpu_jsm_msg *req, + enum vpu_ipc_msg_type expected_resp_type, +- struct vpu_jsm_msg *resp, u32 channel, +- unsigned long timeout_ms) ++ struct vpu_jsm_msg *resp, u32 channel, unsigned long timeout_ms) + { + struct ivpu_ipc_consumer cons; + int ret; + ++ drm_WARN_ON(&vdev->drm, pm_runtime_status_suspended(vdev->drm.dev)); ++ + ivpu_ipc_consumer_add(vdev, &cons, channel, NULL); + + ret = ivpu_ipc_send(vdev, &cons, req); +@@ -325,19 +326,21 @@ ivpu_ipc_send_receive_internal(struct ivpu_device *vdev, struct vpu_jsm_msg *req + return ret; + } + +-int ivpu_ipc_send_receive_active(struct ivpu_device *vdev, struct vpu_jsm_msg *req, +- enum vpu_ipc_msg_type expected_resp, struct vpu_jsm_msg *resp, +- u32 channel, unsigned long timeout_ms) ++int ivpu_ipc_send_receive(struct ivpu_device *vdev, struct vpu_jsm_msg *req, ++ enum vpu_ipc_msg_type expected_resp, struct vpu_jsm_msg *resp, ++ u32 channel, unsigned long timeout_ms) + { + struct vpu_jsm_msg hb_req = { .type = VPU_JSM_MSG_QUERY_ENGINE_HB }; + struct vpu_jsm_msg hb_resp; + int ret, hb_ret; + +- drm_WARN_ON(&vdev->drm, pm_runtime_status_suspended(vdev->drm.dev)); ++ ret = ivpu_rpm_get(vdev); ++ if (ret < 0) ++ return ret; + + ret = ivpu_ipc_send_receive_internal(vdev, req, expected_resp, resp, channel, timeout_ms); + if (ret != -ETIMEDOUT) +- return ret; ++ goto rpm_put; + + hb_ret = ivpu_ipc_send_receive_internal(vdev, &hb_req, VPU_JSM_MSG_QUERY_ENGINE_HB_DONE, + &hb_resp, VPU_IPC_CHAN_ASYNC_CMD, +@@ -345,21 +348,7 @@ int ivpu_ipc_send_receive_active(struct ivpu_device *vdev, struct vpu_jsm_msg *r + if (hb_ret == -ETIMEDOUT) + ivpu_pm_trigger_recovery(vdev, "IPC timeout"); + +- return ret; +-} +- +-int ivpu_ipc_send_receive(struct ivpu_device *vdev, struct vpu_jsm_msg *req, +- enum vpu_ipc_msg_type expected_resp, struct vpu_jsm_msg *resp, +- u32 channel, unsigned long timeout_ms) +-{ +- int ret; +- +- ret = ivpu_rpm_get(vdev); +- if (ret < 0) +- return ret; +- +- ret = ivpu_ipc_send_receive_active(vdev, req, expected_resp, resp, channel, timeout_ms); +- ++rpm_put: + ivpu_rpm_put(vdev); + return ret; + } +diff --git a/drivers/accel/ivpu/ivpu_ipc.h b/drivers/accel/ivpu/ivpu_ipc.h +index 4fe38141045ea..fb4de7fb8210e 100644 +--- a/drivers/accel/ivpu/ivpu_ipc.h ++++ b/drivers/accel/ivpu/ivpu_ipc.h +@@ -101,10 +101,9 @@ int ivpu_ipc_send(struct ivpu_device *vdev, struct ivpu_ipc_consumer *cons, + int ivpu_ipc_receive(struct ivpu_device *vdev, struct ivpu_ipc_consumer *cons, + struct ivpu_ipc_hdr *ipc_buf, struct vpu_jsm_msg *jsm_msg, + unsigned long timeout_ms); +- +-int ivpu_ipc_send_receive_active(struct ivpu_device *vdev, struct vpu_jsm_msg *req, +- enum vpu_ipc_msg_type expected_resp, struct vpu_jsm_msg *resp, +- u32 channel, unsigned long timeout_ms); ++int ivpu_ipc_send_receive_internal(struct ivpu_device *vdev, struct vpu_jsm_msg *req, ++ enum vpu_ipc_msg_type expected_resp_type, ++ struct vpu_jsm_msg *resp, u32 channel, unsigned long timeout_ms); + int ivpu_ipc_send_receive(struct ivpu_device *vdev, struct vpu_jsm_msg *req, + enum vpu_ipc_msg_type expected_resp, struct vpu_jsm_msg *resp, + u32 channel, unsigned long timeout_ms); +diff --git a/drivers/accel/ivpu/ivpu_jsm_msg.c b/drivers/accel/ivpu/ivpu_jsm_msg.c +index 46ef16c3c0691..88105963c1b28 100644 +--- a/drivers/accel/ivpu/ivpu_jsm_msg.c ++++ b/drivers/accel/ivpu/ivpu_jsm_msg.c +@@ -270,9 +270,8 @@ int ivpu_jsm_pwr_d0i3_enter(struct ivpu_device *vdev) + + req.payload.pwr_d0i3_enter.send_response = 1; + +- ret = ivpu_ipc_send_receive_active(vdev, &req, VPU_JSM_MSG_PWR_D0I3_ENTER_DONE, +- &resp, VPU_IPC_CHAN_GEN_CMD, +- vdev->timeout.d0i3_entry_msg); ++ ret = ivpu_ipc_send_receive_internal(vdev, &req, VPU_JSM_MSG_PWR_D0I3_ENTER_DONE, &resp, ++ VPU_IPC_CHAN_GEN_CMD, vdev->timeout.d0i3_entry_msg); + if (ret) + return ret; + +@@ -430,8 +429,8 @@ int ivpu_jsm_hws_setup_priority_bands(struct ivpu_device *vdev) + + req.payload.hws_priority_band_setup.normal_band_percentage = 10; + +- ret = ivpu_ipc_send_receive_active(vdev, &req, VPU_JSM_MSG_SET_PRIORITY_BAND_SETUP_RSP, +- &resp, VPU_IPC_CHAN_ASYNC_CMD, vdev->timeout.jsm); ++ ret = ivpu_ipc_send_receive_internal(vdev, &req, VPU_JSM_MSG_SET_PRIORITY_BAND_SETUP_RSP, ++ &resp, VPU_IPC_CHAN_ASYNC_CMD, vdev->timeout.jsm); + if (ret) + ivpu_warn_ratelimited(vdev, "Failed to set priority bands: %d\n", ret); + +@@ -544,9 +543,8 @@ int ivpu_jsm_dct_enable(struct ivpu_device *vdev, u32 active_us, u32 inactive_us + req.payload.pwr_dct_control.dct_active_us = active_us; + req.payload.pwr_dct_control.dct_inactive_us = inactive_us; + +- return ivpu_ipc_send_receive_active(vdev, &req, VPU_JSM_MSG_DCT_ENABLE_DONE, +- &resp, VPU_IPC_CHAN_ASYNC_CMD, +- vdev->timeout.jsm); ++ return ivpu_ipc_send_receive_internal(vdev, &req, VPU_JSM_MSG_DCT_ENABLE_DONE, &resp, ++ VPU_IPC_CHAN_ASYNC_CMD, vdev->timeout.jsm); + } + + int ivpu_jsm_dct_disable(struct ivpu_device *vdev) +@@ -554,7 +552,6 @@ int ivpu_jsm_dct_disable(struct ivpu_device *vdev) + struct vpu_jsm_msg req = { .type = VPU_JSM_MSG_DCT_DISABLE }; + struct vpu_jsm_msg resp; + +- return ivpu_ipc_send_receive_active(vdev, &req, VPU_JSM_MSG_DCT_DISABLE_DONE, +- &resp, VPU_IPC_CHAN_ASYNC_CMD, +- vdev->timeout.jsm); ++ return ivpu_ipc_send_receive_internal(vdev, &req, VPU_JSM_MSG_DCT_DISABLE_DONE, &resp, ++ VPU_IPC_CHAN_ASYNC_CMD, vdev->timeout.jsm); + } +-- +2.43.0 + diff --git a/queue-6.12/acpi-arm64-adjust-error-handling-procedure-in-gtdt_p.patch b/queue-6.12/acpi-arm64-adjust-error-handling-procedure-in-gtdt_p.patch new file mode 100644 index 00000000000..23302ea5eeb --- /dev/null +++ b/queue-6.12/acpi-arm64-adjust-error-handling-procedure-in-gtdt_p.patch @@ -0,0 +1,46 @@ +From c6f84b1d1afa91a22790c70e4c5b929c4feb4027 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 27 Aug 2024 13:12:39 +0300 +Subject: acpi/arm64: Adjust error handling procedure in + gtdt_parse_timer_block() + +From: Aleksandr Mishin + +[ Upstream commit 1a9de2f6fda69d5f105dd8af776856a66abdaa64 ] + +In case of error in gtdt_parse_timer_block() invalid 'gtdt_frame' +will be used in 'do {} while (i-- >= 0 && gtdt_frame--);' statement block +because do{} block will be executed even if 'i == 0'. + +Adjust error handling procedure by replacing 'i-- >= 0' with 'i-- > 0'. + +Found by Linux Verification Center (linuxtesting.org) with SVACE. + +Fixes: a712c3ed9b8a ("acpi/arm64: Add memory-mapped timer support in GTDT driver") +Signed-off-by: Aleksandr Mishin +Acked-by: Hanjun Guo +Acked-by: Sudeep Holla +Acked-by: Aleksandr Mishin +Link: https://lore.kernel.org/r/20240827101239.22020-1-amishin@t-argos.ru +Signed-off-by: Catalin Marinas +Signed-off-by: Sasha Levin +--- + drivers/acpi/arm64/gtdt.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/acpi/arm64/gtdt.c b/drivers/acpi/arm64/gtdt.c +index c0e77c1c8e09d..eb6c2d3603874 100644 +--- a/drivers/acpi/arm64/gtdt.c ++++ b/drivers/acpi/arm64/gtdt.c +@@ -283,7 +283,7 @@ static int __init gtdt_parse_timer_block(struct acpi_gtdt_timer_block *block, + if (frame->virt_irq > 0) + acpi_unregister_gsi(gtdt_frame->virtual_timer_interrupt); + frame->virt_irq = 0; +- } while (i-- >= 0 && gtdt_frame--); ++ } while (i-- > 0 && gtdt_frame--); + + return -EINVAL; + } +-- +2.43.0 + diff --git a/queue-6.12/acpi-cppc-fix-_cpc-register-setting-issue.patch b/queue-6.12/acpi-cppc-fix-_cpc-register-setting-issue.patch new file mode 100644 index 00000000000..a663796df49 --- /dev/null +++ b/queue-6.12/acpi-cppc-fix-_cpc-register-setting-issue.patch @@ -0,0 +1,42 @@ +From 8536b1f4b3871c132c35be0a17735459989f15a9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 13 Nov 2024 18:33:09 +0800 +Subject: ACPI: CPPC: Fix _CPC register setting issue + +From: Lifeng Zheng + +[ Upstream commit 2388b266c9fcc7c9169ba85c7f9ebe325b7622d7 ] + +Since commit 60949b7b8054 ("ACPI: CPPC: Fix MASK_VAL() usage"), _CPC +registers cannot be changed from 1 to 0. + +It turns out that there is an extra OR after MASK_VAL_WRITE(), which +has already ORed prev_val with the register mask. + +Remove the extra OR to fix the problem. + +Fixes: 60949b7b8054 ("ACPI: CPPC: Fix MASK_VAL() usage") +Signed-off-by: Lifeng Zheng +Link: https://patch.msgid.link/20241113103309.761031-1-zhenglifeng1@huawei.com +[ rjw: Subject and changelog edits ] +Signed-off-by: Rafael J. Wysocki +Signed-off-by: Sasha Levin +--- + drivers/acpi/cppc_acpi.c | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/drivers/acpi/cppc_acpi.c b/drivers/acpi/cppc_acpi.c +index 5c0cc7aae8726..e78e3754d99e1 100644 +--- a/drivers/acpi/cppc_acpi.c ++++ b/drivers/acpi/cppc_acpi.c +@@ -1140,7 +1140,6 @@ static int cpc_write(int cpu, struct cpc_register_resource *reg_res, u64 val) + return -EFAULT; + } + val = MASK_VAL_WRITE(reg, prev_val, val); +- val |= prev_val; + } + + switch (size) { +-- +2.43.0 + diff --git a/queue-6.12/alsa-6fire-release-resources-at-card-release.patch b/queue-6.12/alsa-6fire-release-resources-at-card-release.patch new file mode 100644 index 00000000000..8c1d258c1db --- /dev/null +++ b/queue-6.12/alsa-6fire-release-resources-at-card-release.patch @@ -0,0 +1,78 @@ +From b21fb66a61b1bb2a4b2c48650b5f523a81c2ee68 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 13 Nov 2024 12:10:39 +0100 +Subject: ALSA: 6fire: Release resources at card release + +From: Takashi Iwai + +[ Upstream commit a0810c3d6dd2d29a9b92604d682eacd2902ce947 ] + +The current 6fire code tries to release the resources right after the +call of usb6fire_chip_abort(). But at this moment, the card object +might be still in use (as we're calling snd_card_free_when_closed()). + +For avoid potential UAFs, move the release of resources to the card's +private_free instead of the manual call of usb6fire_chip_destroy() at +the USB disconnect callback. + +Fixes: c6d43ba816d1 ("ALSA: usb/6fire - Driver for TerraTec DMX 6Fire USB") +Signed-off-by: Takashi Iwai +Link: https://patch.msgid.link/20241113111042.15058-6-tiwai@suse.de +Signed-off-by: Sasha Levin +--- + sound/usb/6fire/chip.c | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +diff --git a/sound/usb/6fire/chip.c b/sound/usb/6fire/chip.c +index 33e962178c936..d562a30b087f0 100644 +--- a/sound/usb/6fire/chip.c ++++ b/sound/usb/6fire/chip.c +@@ -61,8 +61,10 @@ static void usb6fire_chip_abort(struct sfire_chip *chip) + } + } + +-static void usb6fire_chip_destroy(struct sfire_chip *chip) ++static void usb6fire_card_free(struct snd_card *card) + { ++ struct sfire_chip *chip = card->private_data; ++ + if (chip) { + if (chip->pcm) + usb6fire_pcm_destroy(chip); +@@ -72,8 +74,6 @@ static void usb6fire_chip_destroy(struct sfire_chip *chip) + usb6fire_comm_destroy(chip); + if (chip->control) + usb6fire_control_destroy(chip); +- if (chip->card) +- snd_card_free(chip->card); + } + } + +@@ -136,6 +136,7 @@ static int usb6fire_chip_probe(struct usb_interface *intf, + chip->regidx = regidx; + chip->intf_count = 1; + chip->card = card; ++ card->private_free = usb6fire_card_free; + + ret = usb6fire_comm_init(chip); + if (ret < 0) +@@ -162,7 +163,7 @@ static int usb6fire_chip_probe(struct usb_interface *intf, + return 0; + + destroy_chip: +- usb6fire_chip_destroy(chip); ++ snd_card_free(card); + return ret; + } + +@@ -181,7 +182,6 @@ static void usb6fire_chip_disconnect(struct usb_interface *intf) + + chip->shutdown = true; + usb6fire_chip_abort(chip); +- usb6fire_chip_destroy(chip); + } + } + } +-- +2.43.0 + diff --git a/queue-6.12/alsa-caiaq-use-snd_card_free_when_closed-at-disconne.patch b/queue-6.12/alsa-caiaq-use-snd_card_free_when_closed-at-disconne.patch new file mode 100644 index 00000000000..c38f2032c74 --- /dev/null +++ b/queue-6.12/alsa-caiaq-use-snd_card_free_when_closed-at-disconne.patch @@ -0,0 +1,168 @@ +From ff7897d1ffdb644296ed9dd4e16d3fb3a88fc6e2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 13 Nov 2024 12:10:38 +0100 +Subject: ALSA: caiaq: Use snd_card_free_when_closed() at disconnection + +From: Takashi Iwai + +[ Upstream commit b04dcbb7f7b1908806b7dc22671cdbe78ff2b82c ] + +The USB disconnect callback is supposed to be short and not too-long +waiting. OTOH, the current code uses snd_card_free() at +disconnection, but this waits for the close of all used fds, hence it +can take long. It eventually blocks the upper layer USB ioctls, which +may trigger a soft lockup. + +An easy workaround is to replace snd_card_free() with +snd_card_free_when_closed(). This variant returns immediately while +the release of resources is done asynchronously by the card device +release at the last close. + +This patch also splits the code to the disconnect and the free phases; +the former is called immediately at the USB disconnect callback while +the latter is called from the card destructor. + +Fixes: 523f1dce3743 ("[ALSA] Add Native Instrument usb audio device support") +Signed-off-by: Takashi Iwai +Link: https://patch.msgid.link/20241113111042.15058-5-tiwai@suse.de +Signed-off-by: Sasha Levin +--- + sound/usb/caiaq/audio.c | 10 ++++++++-- + sound/usb/caiaq/audio.h | 1 + + sound/usb/caiaq/device.c | 19 +++++++++++++++---- + sound/usb/caiaq/input.c | 12 +++++++++--- + sound/usb/caiaq/input.h | 1 + + 5 files changed, 34 insertions(+), 9 deletions(-) + +diff --git a/sound/usb/caiaq/audio.c b/sound/usb/caiaq/audio.c +index 772c0ecb70773..05f964347ed6c 100644 +--- a/sound/usb/caiaq/audio.c ++++ b/sound/usb/caiaq/audio.c +@@ -858,14 +858,20 @@ int snd_usb_caiaq_audio_init(struct snd_usb_caiaqdev *cdev) + return 0; + } + +-void snd_usb_caiaq_audio_free(struct snd_usb_caiaqdev *cdev) ++void snd_usb_caiaq_audio_disconnect(struct snd_usb_caiaqdev *cdev) + { + struct device *dev = caiaqdev_to_dev(cdev); + + dev_dbg(dev, "%s(%p)\n", __func__, cdev); + stream_stop(cdev); ++} ++ ++void snd_usb_caiaq_audio_free(struct snd_usb_caiaqdev *cdev) ++{ ++ struct device *dev = caiaqdev_to_dev(cdev); ++ ++ dev_dbg(dev, "%s(%p)\n", __func__, cdev); + free_urbs(cdev->data_urbs_in); + free_urbs(cdev->data_urbs_out); + kfree(cdev->data_cb_info); + } +- +diff --git a/sound/usb/caiaq/audio.h b/sound/usb/caiaq/audio.h +index 869bf6264d6a0..07f5d064456cf 100644 +--- a/sound/usb/caiaq/audio.h ++++ b/sound/usb/caiaq/audio.h +@@ -3,6 +3,7 @@ + #define CAIAQ_AUDIO_H + + int snd_usb_caiaq_audio_init(struct snd_usb_caiaqdev *cdev); ++void snd_usb_caiaq_audio_disconnect(struct snd_usb_caiaqdev *cdev); + void snd_usb_caiaq_audio_free(struct snd_usb_caiaqdev *cdev); + + #endif /* CAIAQ_AUDIO_H */ +diff --git a/sound/usb/caiaq/device.c b/sound/usb/caiaq/device.c +index b5cbf1f195c48..dfd820483849e 100644 +--- a/sound/usb/caiaq/device.c ++++ b/sound/usb/caiaq/device.c +@@ -376,6 +376,17 @@ static void setup_card(struct snd_usb_caiaqdev *cdev) + dev_err(dev, "Unable to set up control system (ret=%d)\n", ret); + } + ++static void card_free(struct snd_card *card) ++{ ++ struct snd_usb_caiaqdev *cdev = caiaqdev(card); ++ ++#ifdef CONFIG_SND_USB_CAIAQ_INPUT ++ snd_usb_caiaq_input_free(cdev); ++#endif ++ snd_usb_caiaq_audio_free(cdev); ++ usb_reset_device(cdev->chip.dev); ++} ++ + static int create_card(struct usb_device *usb_dev, + struct usb_interface *intf, + struct snd_card **cardp) +@@ -489,6 +500,7 @@ static int init_card(struct snd_usb_caiaqdev *cdev) + cdev->vendor_name, cdev->product_name, usbpath); + + setup_card(cdev); ++ card->private_free = card_free; + return 0; + + err_kill_urb: +@@ -534,15 +546,14 @@ static void snd_disconnect(struct usb_interface *intf) + snd_card_disconnect(card); + + #ifdef CONFIG_SND_USB_CAIAQ_INPUT +- snd_usb_caiaq_input_free(cdev); ++ snd_usb_caiaq_input_disconnect(cdev); + #endif +- snd_usb_caiaq_audio_free(cdev); ++ snd_usb_caiaq_audio_disconnect(cdev); + + usb_kill_urb(&cdev->ep1_in_urb); + usb_kill_urb(&cdev->midi_out_urb); + +- snd_card_free(card); +- usb_reset_device(interface_to_usbdev(intf)); ++ snd_card_free_when_closed(card); + } + + +diff --git a/sound/usb/caiaq/input.c b/sound/usb/caiaq/input.c +index 84f26dce7f5d0..a9130891bb696 100644 +--- a/sound/usb/caiaq/input.c ++++ b/sound/usb/caiaq/input.c +@@ -829,15 +829,21 @@ int snd_usb_caiaq_input_init(struct snd_usb_caiaqdev *cdev) + return ret; + } + +-void snd_usb_caiaq_input_free(struct snd_usb_caiaqdev *cdev) ++void snd_usb_caiaq_input_disconnect(struct snd_usb_caiaqdev *cdev) + { + if (!cdev || !cdev->input_dev) + return; + + usb_kill_urb(cdev->ep4_in_urb); ++ input_unregister_device(cdev->input_dev); ++} ++ ++void snd_usb_caiaq_input_free(struct snd_usb_caiaqdev *cdev) ++{ ++ if (!cdev || !cdev->input_dev) ++ return; ++ + usb_free_urb(cdev->ep4_in_urb); + cdev->ep4_in_urb = NULL; +- +- input_unregister_device(cdev->input_dev); + cdev->input_dev = NULL; + } +diff --git a/sound/usb/caiaq/input.h b/sound/usb/caiaq/input.h +index c42891e7be884..fbe267f85d025 100644 +--- a/sound/usb/caiaq/input.h ++++ b/sound/usb/caiaq/input.h +@@ -4,6 +4,7 @@ + + void snd_usb_caiaq_input_dispatch(struct snd_usb_caiaqdev *cdev, char *buf, unsigned int len); + int snd_usb_caiaq_input_init(struct snd_usb_caiaqdev *cdev); ++void snd_usb_caiaq_input_disconnect(struct snd_usb_caiaqdev *cdev); + void snd_usb_caiaq_input_free(struct snd_usb_caiaqdev *cdev); + + #endif +-- +2.43.0 + diff --git a/queue-6.12/alsa-core-fix-possible-null-dereference-caused-by-ku.patch b/queue-6.12/alsa-core-fix-possible-null-dereference-caused-by-ku.patch new file mode 100644 index 00000000000..0de545bee2b --- /dev/null +++ b/queue-6.12/alsa-core-fix-possible-null-dereference-caused-by-ku.patch @@ -0,0 +1,79 @@ +From 99cbad1722b420106b8262a9861b55069acbd6ff Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 26 Nov 2024 13:24:49 -0600 +Subject: ALSA: core: Fix possible NULL dereference caused by kunit_kzalloc() + +From: Zichen Xie + +[ Upstream commit 9ad467a2b2716d4ed12f003b041aa6c776a13ff5 ] + +kunit_kzalloc() may return a NULL pointer, dereferencing it without +NULL check may lead to NULL dereference. +Add NULL checks for all the kunit_kzalloc() in sound_kunit.c + +Fixes: 3e39acf56ede ("ALSA: core: Add sound core KUnit test") +Signed-off-by: Zichen Xie +Link: https://patch.msgid.link/20241126192448.12645-1-zichenxie0106@gmail.com +Signed-off-by: Takashi Iwai +Signed-off-by: Sasha Levin +--- + sound/core/sound_kunit.c | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +diff --git a/sound/core/sound_kunit.c b/sound/core/sound_kunit.c +index bfed1a25fc8f7..84e337ecbddd0 100644 +--- a/sound/core/sound_kunit.c ++++ b/sound/core/sound_kunit.c +@@ -172,6 +172,7 @@ static void test_format_fill_silence(struct kunit *test) + u32 i, j; + + buffer = kunit_kzalloc(test, SILENCE_BUFFER_SIZE, GFP_KERNEL); ++ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, buffer); + + for (i = 0; i < ARRAY_SIZE(buf_samples); i++) { + for (j = 0; j < ARRAY_SIZE(valid_fmt); j++) +@@ -208,8 +209,12 @@ static void test_playback_avail(struct kunit *test) + struct snd_pcm_runtime *r = kunit_kzalloc(test, sizeof(*r), GFP_KERNEL); + u32 i; + ++ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, r); ++ + r->status = kunit_kzalloc(test, sizeof(*r->status), GFP_KERNEL); + r->control = kunit_kzalloc(test, sizeof(*r->control), GFP_KERNEL); ++ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, r->status); ++ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, r->control); + + for (i = 0; i < ARRAY_SIZE(p_avail_data); i++) { + r->buffer_size = p_avail_data[i].buffer_size; +@@ -232,8 +237,12 @@ static void test_capture_avail(struct kunit *test) + struct snd_pcm_runtime *r = kunit_kzalloc(test, sizeof(*r), GFP_KERNEL); + u32 i; + ++ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, r); ++ + r->status = kunit_kzalloc(test, sizeof(*r->status), GFP_KERNEL); + r->control = kunit_kzalloc(test, sizeof(*r->control), GFP_KERNEL); ++ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, r->status); ++ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, r->control); + + for (i = 0; i < ARRAY_SIZE(c_avail_data); i++) { + r->buffer_size = c_avail_data[i].buffer_size; +@@ -247,6 +256,7 @@ static void test_capture_avail(struct kunit *test) + static void test_card_set_id(struct kunit *test) + { + struct snd_card *card = kunit_kzalloc(test, sizeof(*card), GFP_KERNEL); ++ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, card); + + snd_card_set_id(card, VALID_NAME); + KUNIT_EXPECT_STREQ(test, card->id, VALID_NAME); +@@ -280,6 +290,7 @@ static void test_pcm_format_name(struct kunit *test) + static void test_card_add_component(struct kunit *test) + { + struct snd_card *card = kunit_kzalloc(test, sizeof(*card), GFP_KERNEL); ++ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, card); + + snd_component_add(card, TEST_FIRST_COMPONENT); + KUNIT_ASSERT_STREQ(test, card->components, TEST_FIRST_COMPONENT); +-- +2.43.0 + diff --git a/queue-6.12/alsa-hda-realtek-update-alc256-depop-procedure.patch b/queue-6.12/alsa-hda-realtek-update-alc256-depop-procedure.patch new file mode 100644 index 00000000000..acae123e3fd --- /dev/null +++ b/queue-6.12/alsa-hda-realtek-update-alc256-depop-procedure.patch @@ -0,0 +1,102 @@ +From 8c13a1787d40723f571e89d598da894ad273cbd4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 14 Nov 2024 15:21:09 +0800 +Subject: ALSA: hda/realtek: Update ALC256 depop procedure + +From: Kailang Yang + +[ Upstream commit cc3d0b5dd989d3238d456f9fd385946379a9c13d ] + +Old procedure has a chance to meet Headphone no output. + +Fixes: 4a219ef8f370 ("ALSA: hda/realtek - Add ALC256 HP depop function") +Signed-off-by: Kailang Yang +Link: https://lore.kernel.org/463c5f93715d4714967041a0a8cec28e@realtek.com +Signed-off-by: Takashi Iwai +Signed-off-by: Sasha Levin +--- + sound/pci/hda/patch_realtek.c | 42 ++++++++++++++++------------------- + 1 file changed, 19 insertions(+), 23 deletions(-) + +diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c +index 24b4fe99304a4..61d7d8b937676 100644 +--- a/sound/pci/hda/patch_realtek.c ++++ b/sound/pci/hda/patch_realtek.c +@@ -3613,25 +3613,22 @@ static void alc256_init(struct hda_codec *codec) + + hp_pin_sense = snd_hda_jack_detect(codec, hp_pin); + +- if (hp_pin_sense) ++ if (hp_pin_sense) { + msleep(2); ++ alc_update_coefex_idx(codec, 0x57, 0x04, 0x0007, 0x1); /* Low power */ + +- alc_update_coefex_idx(codec, 0x57, 0x04, 0x0007, 0x1); /* Low power */ +- +- snd_hda_codec_write(codec, hp_pin, 0, +- AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE); +- +- if (hp_pin_sense || spec->ultra_low_power) +- msleep(85); +- +- snd_hda_codec_write(codec, hp_pin, 0, ++ snd_hda_codec_write(codec, hp_pin, 0, + AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT); + +- if (hp_pin_sense || spec->ultra_low_power) +- msleep(100); ++ msleep(75); ++ ++ snd_hda_codec_write(codec, hp_pin, 0, ++ AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE); + ++ msleep(75); ++ alc_update_coefex_idx(codec, 0x57, 0x04, 0x0007, 0x4); /* Hight power */ ++ } + alc_update_coef_idx(codec, 0x46, 3 << 12, 0); +- alc_update_coefex_idx(codec, 0x57, 0x04, 0x0007, 0x4); /* Hight power */ + alc_update_coefex_idx(codec, 0x53, 0x02, 0x8000, 1 << 15); /* Clear bit */ + alc_update_coefex_idx(codec, 0x53, 0x02, 0x8000, 0 << 15); + /* +@@ -3655,29 +3652,28 @@ static void alc256_shutup(struct hda_codec *codec) + alc_update_coefex_idx(codec, 0x57, 0x04, 0x0007, 0x1); /* Low power */ + hp_pin_sense = snd_hda_jack_detect(codec, hp_pin); + +- if (hp_pin_sense) ++ if (hp_pin_sense) { + msleep(2); + +- snd_hda_codec_write(codec, hp_pin, 0, ++ snd_hda_codec_write(codec, hp_pin, 0, + AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE); + +- if (hp_pin_sense || spec->ultra_low_power) +- msleep(85); ++ msleep(75); + + /* 3k pull low control for Headset jack. */ + /* NOTE: call this before clearing the pin, otherwise codec stalls */ + /* If disable 3k pulldown control for alc257, the Mic detection will not work correctly + * when booting with headset plugged. So skip setting it for the codec alc257 + */ +- if (spec->en_3kpull_low) +- alc_update_coef_idx(codec, 0x46, 0, 3 << 12); ++ if (spec->en_3kpull_low) ++ alc_update_coef_idx(codec, 0x46, 0, 3 << 12); + +- if (!spec->no_shutup_pins) +- snd_hda_codec_write(codec, hp_pin, 0, ++ if (!spec->no_shutup_pins) ++ snd_hda_codec_write(codec, hp_pin, 0, + AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0); + +- if (hp_pin_sense || spec->ultra_low_power) +- msleep(100); ++ msleep(75); ++ } + + alc_auto_setup_eapd(codec, false); + alc_shutup_pins(codec); +-- +2.43.0 + diff --git a/queue-6.12/alsa-us122l-use-snd_card_free_when_closed-at-disconn.patch b/queue-6.12/alsa-us122l-use-snd_card_free_when_closed-at-disconn.patch new file mode 100644 index 00000000000..80c594910bd --- /dev/null +++ b/queue-6.12/alsa-us122l-use-snd_card_free_when_closed-at-disconn.patch @@ -0,0 +1,50 @@ +From 89d8d23450993106948704f5d915d52ec213cb7b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 13 Nov 2024 12:10:36 +0100 +Subject: ALSA: us122l: Use snd_card_free_when_closed() at disconnection + +From: Takashi Iwai + +[ Upstream commit b7df09bb348016943f56b09dcaafe221e3f73947 ] + +The USB disconnect callback is supposed to be short and not too-long +waiting. OTOH, the current code uses snd_card_free() at +disconnection, but this waits for the close of all used fds, hence it +can take long. It eventually blocks the upper layer USB ioctls, which +may trigger a soft lockup. + +An easy workaround is to replace snd_card_free() with +snd_card_free_when_closed(). This variant returns immediately while +the release of resources is done asynchronously by the card device +release at the last close. + +The loop of us122l->mmap_count check is dropped as well. The check is +useless for the asynchronous operation with *_when_closed(). + +Fixes: 030a07e44129 ("ALSA: Add USB US122L driver") +Signed-off-by: Takashi Iwai +Link: https://patch.msgid.link/20241113111042.15058-3-tiwai@suse.de +Signed-off-by: Sasha Levin +--- + sound/usb/usx2y/us122l.c | 5 +---- + 1 file changed, 1 insertion(+), 4 deletions(-) + +diff --git a/sound/usb/usx2y/us122l.c b/sound/usb/usx2y/us122l.c +index 1be0e980feb95..ca5fac03ec798 100644 +--- a/sound/usb/usx2y/us122l.c ++++ b/sound/usb/usx2y/us122l.c +@@ -606,10 +606,7 @@ static void snd_us122l_disconnect(struct usb_interface *intf) + usb_put_intf(usb_ifnum_to_if(us122l->dev, 1)); + usb_put_dev(us122l->dev); + +- while (atomic_read(&us122l->mmap_count)) +- msleep(500); +- +- snd_card_free(card); ++ snd_card_free_when_closed(card); + } + + static int snd_us122l_suspend(struct usb_interface *intf, pm_message_t message) +-- +2.43.0 + diff --git a/queue-6.12/alsa-usx2y-use-snd_card_free_when_closed-at-disconne.patch b/queue-6.12/alsa-usx2y-use-snd_card_free_when_closed-at-disconne.patch new file mode 100644 index 00000000000..ca44c09cf34 --- /dev/null +++ b/queue-6.12/alsa-usx2y-use-snd_card_free_when_closed-at-disconne.patch @@ -0,0 +1,46 @@ +From 46bc844710587de72da72e1ea89de687ab2040f6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 13 Nov 2024 12:10:35 +0100 +Subject: ALSA: usx2y: Use snd_card_free_when_closed() at disconnection + +From: Takashi Iwai + +[ Upstream commit dafb28f02be407e07a6f679e922a626592b481b0 ] + +The USB disconnect callback is supposed to be short and not too-long +waiting. OTOH, the current code uses snd_card_free() at +disconnection, but this waits for the close of all used fds, hence it +can take long. It eventually blocks the upper layer USB ioctls, which +may trigger a soft lockup. + +An easy workaround is to replace snd_card_free() with +snd_card_free_when_closed(). This variant returns immediately while +the release of resources is done asynchronously by the card device +release at the last close. + +Fixes: 230cd5e24853 ("[ALSA] prevent oops & dead keyboard on usb unplugging while the device is be ing used") +Reported-by: syzbot+73582d08864d8268b6fd@syzkaller.appspotmail.com +Closes: https://syzkaller.appspot.com/bug?extid=73582d08864d8268b6fd +Signed-off-by: Takashi Iwai +Link: https://patch.msgid.link/20241113111042.15058-2-tiwai@suse.de +Signed-off-by: Sasha Levin +--- + sound/usb/usx2y/usbusx2y.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/sound/usb/usx2y/usbusx2y.c b/sound/usb/usx2y/usbusx2y.c +index 2f9cede242b3a..5f81c68fd42b6 100644 +--- a/sound/usb/usx2y/usbusx2y.c ++++ b/sound/usb/usx2y/usbusx2y.c +@@ -422,7 +422,7 @@ static void snd_usx2y_disconnect(struct usb_interface *intf) + } + if (usx2y->us428ctls_sharedmem) + wake_up(&usx2y->us428ctls_wait_queue_head); +- snd_card_free(card); ++ snd_card_free_when_closed(card); + } + + static int snd_usx2y_probe(struct usb_interface *intf, +-- +2.43.0 + diff --git a/queue-6.12/amd-pstate-set-min_perf-to-nominal_perf-for-active-m.patch b/queue-6.12/amd-pstate-set-min_perf-to-nominal_perf-for-active-m.patch new file mode 100644 index 00000000000..562161db638 --- /dev/null +++ b/queue-6.12/amd-pstate-set-min_perf-to-nominal_perf-for-active-m.patch @@ -0,0 +1,45 @@ +From 71903eb804ef0c387b189c0a0c8137140735ea98 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 21 Oct 2024 15:48:35 +0530 +Subject: amd-pstate: Set min_perf to nominal_perf for active mode performance + gov + +From: Gautham R. Shenoy + +[ Upstream commit 0c411b39e4f4ce8861301fa201cb4f817751311e ] + +The amd-pstate driver sets CPPC_REQ.min_perf to CPPC_REQ.max_perf when +in active mode with performance governor. Typically CPPC_REQ.max_perf +is set to CPPC.highest_perf. This causes frequency throttling on +power-limited platforms which causes performance regressions on +certain classes of workloads. + +Hence, set the CPPC_REQ.min_perf to the CPPC.nominal_perf or +CPPC_REQ.max_perf, whichever is lower of the two. + +Fixes: ffa5096a7c33 ("cpufreq: amd-pstate: implement Pstate EPP support for the AMD processors") +Signed-off-by: Gautham R. Shenoy +Reviewed-by: Mario Limonciello +Link: https://lore.kernel.org/r/20241021101836.9047-2-gautham.shenoy@amd.com +Signed-off-by: Mario Limonciello +Signed-off-by: Sasha Levin +--- + drivers/cpufreq/amd-pstate.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/cpufreq/amd-pstate.c b/drivers/cpufreq/amd-pstate.c +index 5138aa42caf22..91d3c3b1c2d3b 100644 +--- a/drivers/cpufreq/amd-pstate.c ++++ b/drivers/cpufreq/amd-pstate.c +@@ -1513,7 +1513,7 @@ static int amd_pstate_epp_update_limit(struct cpufreq_policy *policy) + value = READ_ONCE(cpudata->cppc_req_cached); + + if (cpudata->policy == CPUFREQ_POLICY_PERFORMANCE) +- min_perf = max_perf; ++ min_perf = min(cpudata->nominal_perf, max_perf); + + /* Initial min/max values for CPPC Performance Controls Register */ + value &= ~AMD_CPPC_MIN_PERF(~0L); +-- +2.43.0 + diff --git a/queue-6.12/apparmor-fix-do-simple-duplicate-message-elimination.patch b/queue-6.12/apparmor-fix-do-simple-duplicate-message-elimination.patch new file mode 100644 index 00000000000..5879a4eb9a8 --- /dev/null +++ b/queue-6.12/apparmor-fix-do-simple-duplicate-message-elimination.patch @@ -0,0 +1,35 @@ +From e25f0ace9b4f0c0d0ed485d0608a8e592b1b9bab Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 27 Jun 2023 10:03:16 +0800 +Subject: apparmor: fix 'Do simple duplicate message elimination' + +From: chao liu + +[ Upstream commit 9b897132424fe76bf6c61f22f9cf12af7f1d1e6a ] + +Multiple profiles shared 'ent->caps', so some logs missed. + +Fixes: 0ed3b28ab8bf ("AppArmor: mediation of non file objects") +Signed-off-by: chao liu +Signed-off-by: John Johansen +Signed-off-by: Sasha Levin +--- + security/apparmor/capability.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/security/apparmor/capability.c b/security/apparmor/capability.c +index 9934df16c8431..bf7df60868308 100644 +--- a/security/apparmor/capability.c ++++ b/security/apparmor/capability.c +@@ -96,6 +96,8 @@ static int audit_caps(struct apparmor_audit_data *ad, struct aa_profile *profile + return error; + } else { + aa_put_profile(ent->profile); ++ if (profile != ent->profile) ++ cap_clear(ent->caps); + ent->profile = aa_get_profile(profile); + cap_raise(ent->caps, cap); + } +-- +2.43.0 + diff --git a/queue-6.12/arm-dts-cubieboard4-fix-dcdc5-regulator-constraints.patch b/queue-6.12/arm-dts-cubieboard4-fix-dcdc5-regulator-constraints.patch new file mode 100644 index 00000000000..028f1688937 --- /dev/null +++ b/queue-6.12/arm-dts-cubieboard4-fix-dcdc5-regulator-constraints.patch @@ -0,0 +1,56 @@ +From 6dd2b8e753559e42d742fc89f946c9ad3006819b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 7 Oct 2024 23:29:16 +0100 +Subject: ARM: dts: cubieboard4: Fix DCDC5 regulator constraints + +From: Andre Przywara + +[ Upstream commit dd36ad71ad65968f97630808bc8d605c929b128e ] + +The DCDC5 voltage rail in the X-Powers AXP809 PMIC has a resolution of +50mV, so the currently enforced limits of 1.475 and 1.525 volts cannot +be set, when the existing regulator value is beyond this range. + +This will lead to the whole regulator driver to give up and fail +probing, which in turn will hang the system, as essential devices depend +on the PMIC. +In this case a bug in U-Boot set the voltage to 1.75V (meant for DCDC4), +and the AXP driver's attempt to correct this lead to this error: +================== +[ 4.447653] axp20x-rsb sunxi-rsb-3a3: AXP20X driver loaded +[ 4.450066] vcc-dram: Bringing 1750000uV into 1575000-1575000uV +[ 4.460272] vcc-dram: failed to apply 1575000-1575000uV constraint: -EINVAL +[ 4.474788] axp20x-regulator axp20x-regulator.0: Failed to register dcdc5 +[ 4.482276] axp20x-regulator axp20x-regulator.0: probe with driver axp20x-regulator failed with error -22 +================== + +Set the limits to values that can be programmed, so any correction will +be successful. + +Signed-off-by: Andre Przywara +Fixes: 1e1dea72651b ("ARM: dts: sun9i: cubieboard4: Add AXP809 PMIC device node and regulators") +Link: https://patch.msgid.link/20241007222916.19013-1-andre.przywara@arm.com +Signed-off-by: Chen-Yu Tsai +Signed-off-by: Sasha Levin +--- + arch/arm/boot/dts/allwinner/sun9i-a80-cubieboard4.dts | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/arch/arm/boot/dts/allwinner/sun9i-a80-cubieboard4.dts b/arch/arm/boot/dts/allwinner/sun9i-a80-cubieboard4.dts +index c8ca8cb7f5c94..52ad95a2063aa 100644 +--- a/arch/arm/boot/dts/allwinner/sun9i-a80-cubieboard4.dts ++++ b/arch/arm/boot/dts/allwinner/sun9i-a80-cubieboard4.dts +@@ -280,8 +280,8 @@ reg_dcdc4: dcdc4 { + + reg_dcdc5: dcdc5 { + regulator-always-on; +- regulator-min-microvolt = <1425000>; +- regulator-max-microvolt = <1575000>; ++ regulator-min-microvolt = <1450000>; ++ regulator-max-microvolt = <1550000>; + regulator-name = "vcc-dram"; + }; + +-- +2.43.0 + diff --git a/queue-6.12/arm-dts-microchip-sam9x60-add-missing-property-atmel.patch b/queue-6.12/arm-dts-microchip-sam9x60-add-missing-property-atmel.patch new file mode 100644 index 00000000000..a7854bb04f8 --- /dev/null +++ b/queue-6.12/arm-dts-microchip-sam9x60-add-missing-property-atmel.patch @@ -0,0 +1,137 @@ +From ba5cc848f91bf84fed55e0fb4b8f35522b9c1ded Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 12 Sep 2024 12:33:07 +0300 +Subject: ARM: dts: microchip: sam9x60: Add missing property atmel,usart-mode + +From: Andrei Simion + +[ Upstream commit 2f9d013a0c6f1b9109ada5acb28ee26eefc77c03 ] + +Add the atmel,usart-mode property to the UART nodes. This ensures +compliance with the atmel,at91-usart.yaml schema and resolves the errors +below: +serial@200: $nodename:0: 'serial@200' does not match +'^spi(@.*|-([0-9]|[1-9][0-9]+))?$' +serial@200: atmel,use-dma-rx: False schema does not allow True +serial@200: atmel,use-dma-tx: False schema does not allow True +serial@200: atmel,fifo-size: False schema does not allow [[16]] + +These errors indicate that the property +atmel,usart-mode = is missing for +UART nodes 0, 1, 2, 3, 4, 6, 7, 8, 9, 10, 11, and 12. + +Fixes: 99c808335877 ("ARM: dts: at91: sam9x60: Add missing flexcom definitions") +Acked-by: Nicolas Ferre +Signed-off-by: Andrei Simion +Link: https://lore.kernel.org/r/20240912093307.40488-1-andrei.simion@microchip.com +[claudiu.beznea: move the atmel,usart-mode close to vendor specific + properties to cope with DTS coding style] +Signed-off-by: Claudiu Beznea +Signed-off-by: Sasha Levin +--- + arch/arm/boot/dts/microchip/sam9x60.dtsi | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +diff --git a/arch/arm/boot/dts/microchip/sam9x60.dtsi b/arch/arm/boot/dts/microchip/sam9x60.dtsi +index 04a6d716ecaf8..1e8fcb5d4700d 100644 +--- a/arch/arm/boot/dts/microchip/sam9x60.dtsi ++++ b/arch/arm/boot/dts/microchip/sam9x60.dtsi +@@ -186,6 +186,7 @@ AT91_XDMAC_DT_PER_IF(1) | + dma-names = "tx", "rx"; + clocks = <&pmc PMC_TYPE_PERIPHERAL 13>; + clock-names = "usart"; ++ atmel,usart-mode = ; + atmel,use-dma-rx; + atmel,use-dma-tx; + atmel,fifo-size = <16>; +@@ -388,6 +389,7 @@ AT91_XDMAC_DT_PER_IF(1) | + dma-names = "tx", "rx"; + clocks = <&pmc PMC_TYPE_PERIPHERAL 32>; + clock-names = "usart"; ++ atmel,usart-mode = ; + atmel,use-dma-rx; + atmel,use-dma-tx; + atmel,fifo-size = <16>; +@@ -439,6 +441,7 @@ AT91_XDMAC_DT_PER_IF(1) | + dma-names = "tx", "rx"; + clocks = <&pmc PMC_TYPE_PERIPHERAL 33>; + clock-names = "usart"; ++ atmel,usart-mode = ; + atmel,use-dma-rx; + atmel,use-dma-tx; + atmel,fifo-size = <16>; +@@ -598,6 +601,7 @@ AT91_XDMAC_DT_PER_IF(1) | + dma-names = "tx", "rx"; + clocks = <&pmc PMC_TYPE_PERIPHERAL 9>; + clock-names = "usart"; ++ atmel,usart-mode = ; + atmel,use-dma-rx; + atmel,use-dma-tx; + atmel,fifo-size = <16>; +@@ -649,6 +653,7 @@ AT91_XDMAC_DT_PER_IF(1) | + dma-names = "tx", "rx"; + clocks = <&pmc PMC_TYPE_PERIPHERAL 10>; + clock-names = "usart"; ++ atmel,usart-mode = ; + atmel,use-dma-rx; + atmel,use-dma-tx; + atmel,fifo-size = <16>; +@@ -700,6 +705,7 @@ AT91_XDMAC_DT_PER_IF(1) | + dma-names = "tx", "rx"; + clocks = <&pmc PMC_TYPE_PERIPHERAL 11>; + clock-names = "usart"; ++ atmel,usart-mode = ; + atmel,use-dma-rx; + atmel,use-dma-tx; + atmel,fifo-size = <16>; +@@ -751,6 +757,7 @@ AT91_XDMAC_DT_PER_IF(1) | + dma-names = "tx", "rx"; + clocks = <&pmc PMC_TYPE_PERIPHERAL 5>; + clock-names = "usart"; ++ atmel,usart-mode = ; + atmel,use-dma-rx; + atmel,use-dma-tx; + atmel,fifo-size = <16>; +@@ -821,6 +828,7 @@ AT91_XDMAC_DT_PER_IF(1) | + dma-names = "tx", "rx"; + clocks = <&pmc PMC_TYPE_PERIPHERAL 6>; + clock-names = "usart"; ++ atmel,usart-mode = ; + atmel,use-dma-rx; + atmel,use-dma-tx; + atmel,fifo-size = <16>; +@@ -891,6 +899,7 @@ AT91_XDMAC_DT_PER_IF(1) | + dma-names = "tx", "rx"; + clocks = <&pmc PMC_TYPE_PERIPHERAL 7>; + clock-names = "usart"; ++ atmel,usart-mode = ; + atmel,use-dma-rx; + atmel,use-dma-tx; + atmel,fifo-size = <16>; +@@ -961,6 +970,7 @@ AT91_XDMAC_DT_PER_IF(1) | + dma-names = "tx", "rx"; + clocks = <&pmc PMC_TYPE_PERIPHERAL 8>; + clock-names = "usart"; ++ atmel,usart-mode = ; + atmel,use-dma-rx; + atmel,use-dma-tx; + atmel,fifo-size = <16>; +@@ -1086,6 +1096,7 @@ AT91_XDMAC_DT_PER_IF(1) | + dma-names = "tx", "rx"; + clocks = <&pmc PMC_TYPE_PERIPHERAL 15>; + clock-names = "usart"; ++ atmel,usart-mode = ; + atmel,use-dma-rx; + atmel,use-dma-tx; + atmel,fifo-size = <16>; +@@ -1137,6 +1148,7 @@ AT91_XDMAC_DT_PER_IF(1) | + dma-names = "tx", "rx"; + clocks = <&pmc PMC_TYPE_PERIPHERAL 16>; + clock-names = "usart"; ++ atmel,usart-mode = ; + atmel,use-dma-rx; + atmel,use-dma-tx; + atmel,fifo-size = <16>; +-- +2.43.0 + diff --git a/queue-6.12/arm-dts-renesas-genmai-fix-partition-size-for-qspi-n.patch b/queue-6.12/arm-dts-renesas-genmai-fix-partition-size-for-qspi-n.patch new file mode 100644 index 00000000000..ad4c2ede683 --- /dev/null +++ b/queue-6.12/arm-dts-renesas-genmai-fix-partition-size-for-qspi-n.patch @@ -0,0 +1,40 @@ +From 6f027dda0b40fadf6ddc430c452a2bae1c298d5e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 14 Sep 2024 20:28:44 +0200 +Subject: ARM: dts: renesas: genmai: Fix partition size for QSPI NOR Flash + +From: Wolfram Sang + +[ Upstream commit 48e17816c3effa3545e21cd4f7d5a00c55c17a18 ] + +Second partition was too large, looks like two digits got mixed up. +Fixes: + +mtd: partition "user1" extends beyond the end of device "18000000.flash" -- size truncated to 0x4000000 + +Fixes: 30e0a8cf886c ("ARM: dts: renesas: genmai: Add FLASH nodes") +Signed-off-by: Wolfram Sang +Reviewed-by: Geert Uytterhoeven +Link: https://lore.kernel.org/20240914182948.94031-2-wsa+renesas@sang-engineering.com +Signed-off-by: Geert Uytterhoeven +Signed-off-by: Sasha Levin +--- + arch/arm/boot/dts/renesas/r7s72100-genmai.dts | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/arch/arm/boot/dts/renesas/r7s72100-genmai.dts b/arch/arm/boot/dts/renesas/r7s72100-genmai.dts +index 29ba098f5dd5e..28e703e0f152b 100644 +--- a/arch/arm/boot/dts/renesas/r7s72100-genmai.dts ++++ b/arch/arm/boot/dts/renesas/r7s72100-genmai.dts +@@ -53,7 +53,7 @@ partition@0 { + + partition@4000000 { + label = "user1"; +- reg = <0x04000000 0x40000000>; ++ reg = <0x04000000 0x04000000>; + }; + }; + }; +-- +2.43.0 + diff --git a/queue-6.12/arm64-dts-imx8mn-tqma8mqnl-mba8mx-usbot-fix-coexiste.patch b/queue-6.12/arm64-dts-imx8mn-tqma8mqnl-mba8mx-usbot-fix-coexiste.patch new file mode 100644 index 00000000000..384f69a5175 --- /dev/null +++ b/queue-6.12/arm64-dts-imx8mn-tqma8mqnl-mba8mx-usbot-fix-coexiste.patch @@ -0,0 +1,78 @@ +From 4cc9a9f53c879c2dd27dc31bb00ef2d57730ed20 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 23 Oct 2024 17:03:13 -0400 +Subject: arm64: dts: imx8mn-tqma8mqnl-mba8mx-usbot: fix coexistence of + output-low and output-high in GPIO + +From: Frank Li + +[ Upstream commit c771d311b1901cd4679c8fc7f89a882fe07cf4a0 ] + +Fix the issue where both 'output-low' and 'output-high' exist under GPIO +hog nodes (rst_usb_hub_hog and sel_usb_hub_hog) when applying device +tree overlays. Since /delete-property/ is not supported in the overlays, +setting 'output-low' results in both properties being present. The +workaround is to disable these hogs and create new ones with 'output-low' +as needed. + +Fix below CHECK_DTBS warning: +arch/arm64/boot/dts/freescale/imx8mn-tqma8mqnl-mba8mx-usbotg.dtb: sel-usb-hub-hog: + {'output-low': True, 'gpio-hog': True, 'gpios': [[1, 0]], 'output-high': True, 'phandle': 108, '$nodename': ['sel-usb-hub-hog']} + is valid under each of {'required': ['output-low']}, {'required': ['output-high'] + +Fixes: 3f6fc30abebc ("arm64: dts: imx8mn: tqma8mqnl-mba8mx: Add USB DR overlay") +Signed-off-by: Frank Li +Reviewed-by: Alexander Stein +Signed-off-by: Shawn Guo +Signed-off-by: Sasha Levin +--- + .../imx8mn-tqma8mqnl-mba8mx-usbotg.dtso | 29 +++++++++++++++++-- + 1 file changed, 27 insertions(+), 2 deletions(-) + +diff --git a/arch/arm64/boot/dts/freescale/imx8mn-tqma8mqnl-mba8mx-usbotg.dtso b/arch/arm64/boot/dts/freescale/imx8mn-tqma8mqnl-mba8mx-usbotg.dtso +index 96db07fc9bece..1f2a0fe70a0a2 100644 +--- a/arch/arm64/boot/dts/freescale/imx8mn-tqma8mqnl-mba8mx-usbotg.dtso ++++ b/arch/arm64/boot/dts/freescale/imx8mn-tqma8mqnl-mba8mx-usbotg.dtso +@@ -29,12 +29,37 @@ usb_dr_connector: endpoint { + }; + }; + ++/* ++ * rst_usb_hub_hog and sel_usb_hub_hog have property 'output-high', ++ * dt overlay don't support /delete-property/. Both 'output-low' and ++ * 'output-high' will be exist under hog nodes if overlay file set ++ * 'output-low'. Workaround is disable these hog and create new hog with ++ * 'output-low'. ++ */ ++ + &rst_usb_hub_hog { +- output-low; ++ status = "disabled"; ++}; ++ ++&expander0 { ++ rst-usb-low-hub-hog { ++ gpio-hog; ++ gpios = <13 0>; ++ output-low; ++ line-name = "RST_USB_HUB#"; ++ }; + }; + + &sel_usb_hub_hog { +- output-low; ++ status = "disabled"; ++}; ++ ++&gpio2 { ++ sel-usb-low-hub-hog { ++ gpio-hog; ++ gpios = <1 GPIO_ACTIVE_HIGH>; ++ output-low; ++ }; + }; + + &usbotg1 { +-- +2.43.0 + diff --git a/queue-6.12/arm64-dts-mediatek-mt6358-fix-dtbs_check-error.patch b/queue-6.12/arm64-dts-mediatek-mt6358-fix-dtbs_check-error.patch new file mode 100644 index 00000000000..956e85ab9e6 --- /dev/null +++ b/queue-6.12/arm64-dts-mediatek-mt6358-fix-dtbs_check-error.patch @@ -0,0 +1,47 @@ +From 6b993b3b53778c91b6be41e253c726fd4d7c09ce Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 29 Oct 2024 14:46:47 +0800 +Subject: arm64: dts: mediatek: mt6358: fix dtbs_check error + +From: Macpaul Lin + +[ Upstream commit 76ab2ae0ab9ebb2d70e6ee8a9f59911621192c37 ] + +Fix DTBS check errors for 'mt6358codec' and 'mt6358regulator': + +Error message is: +pmic: 'mt6358codec' and 'mt6358regulator' does not match any of the +regexes: 'pinctrl-[0-9]+'. +Rename these two device node to generic 'audio-codec' and 'regulators'. + +Fixes: 9f8872221674 ("arm64: dts: mt6358: add PMIC MT6358 related nodes") +Signed-off-by: Macpaul Lin +Link: https://lore.kernel.org/r/20241029064647.13370-1-macpaul.lin@mediatek.com +Signed-off-by: AngeloGioacchino Del Regno +Signed-off-by: Sasha Levin +--- + arch/arm64/boot/dts/mediatek/mt6358.dtsi | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/arch/arm64/boot/dts/mediatek/mt6358.dtsi b/arch/arm64/boot/dts/mediatek/mt6358.dtsi +index 641d452fbc083..e23672a2eea4a 100644 +--- a/arch/arm64/boot/dts/mediatek/mt6358.dtsi ++++ b/arch/arm64/boot/dts/mediatek/mt6358.dtsi +@@ -15,12 +15,12 @@ pmic_adc: adc { + #io-channel-cells = <1>; + }; + +- mt6358codec: mt6358codec { ++ mt6358codec: audio-codec { + compatible = "mediatek,mt6358-sound"; + mediatek,dmic-mode = <0>; /* two-wires */ + }; + +- mt6358regulator: mt6358regulator { ++ mt6358regulator: regulators { + compatible = "mediatek,mt6358-regulator"; + + mt6358_vdram1_reg: buck_vdram1 { +-- +2.43.0 + diff --git a/queue-6.12/arm64-dts-mediatek-mt8173-elm-hana-add-vdd-supply-to.patch b/queue-6.12/arm64-dts-mediatek-mt8173-elm-hana-add-vdd-supply-to.patch new file mode 100644 index 00000000000..23191ccc79d --- /dev/null +++ b/queue-6.12/arm64-dts-mediatek-mt8173-elm-hana-add-vdd-supply-to.patch @@ -0,0 +1,50 @@ +From 3451d716b56d2474b1a9b449b1d50c2118a103c2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 18 Oct 2024 16:20:00 +0800 +Subject: arm64: dts: mediatek: mt8173-elm-hana: Add vdd-supply to second + source trackpad + +From: Chen-Yu Tsai + +[ Upstream commit f766fae08f6a2eaeb45d8d2c053724c91526835c ] + +The Hana device has a second source option trackpad, but it is missing +its regulator supply. It only works because the regulator is marked as +always-on. + +Add the regulator supply, but leave out the post-power-on delay. Instead, +document the post-power-on delay along with the reason for not adding +it in a comment. + +Fixes: 689b937bedde ("arm64: dts: mediatek: add mt8173 elm and hana board") +Signed-off-by: Chen-Yu Tsai +Reviewed-by: AngeloGioacchino Del Regno +Link: https://lore.kernel.org/r/20241018082001.1296963-1-wenst@chromium.org +Signed-off-by: AngeloGioacchino Del Regno +Signed-off-by: Sasha Levin +--- + arch/arm64/boot/dts/mediatek/mt8173-elm-hana.dtsi | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/arch/arm64/boot/dts/mediatek/mt8173-elm-hana.dtsi b/arch/arm64/boot/dts/mediatek/mt8173-elm-hana.dtsi +index 8d1cbc92bce32..ae0379fd42a91 100644 +--- a/arch/arm64/boot/dts/mediatek/mt8173-elm-hana.dtsi ++++ b/arch/arm64/boot/dts/mediatek/mt8173-elm-hana.dtsi +@@ -49,6 +49,14 @@ trackpad2: trackpad@2c { + interrupts-extended = <&pio 117 IRQ_TYPE_LEVEL_LOW>; + reg = <0x2c>; + hid-descr-addr = <0x0020>; ++ /* ++ * The trackpad needs a post-power-on delay of 100ms, ++ * but at time of writing, the power supply for it on ++ * this board is always on. The delay is therefore not ++ * added to avoid impacting the readiness of the ++ * trackpad. ++ */ ++ vdd-supply = <&mt6397_vgp6_reg>; + wakeup-source; + }; + }; +-- +2.43.0 + diff --git a/queue-6.12/arm64-dts-mediatek-mt8183-kukui-disable-dpi-display-.patch b/queue-6.12/arm64-dts-mediatek-mt8183-kukui-disable-dpi-display-.patch new file mode 100644 index 00000000000..b450b525709 --- /dev/null +++ b/queue-6.12/arm64-dts-mediatek-mt8183-kukui-disable-dpi-display-.patch @@ -0,0 +1,54 @@ +From 8934fff7190272c0579b3feaeb58da80b3e86956 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 16 Sep 2024 19:29:32 +0300 +Subject: arm64: dts: mediatek: mt8183-kukui: Disable DPI display interface + +From: Alper Nebi Yasak + +[ Upstream commit 377548f05bd0905db52a1d50e5b328b9b4eb049d ] + +Commit 009d855a26fd ("arm64: dts: mt8183: add dpi node to mt8183") adds +a device-tree node for the DPI display interface that feeds the external +display pipeline, to enable HDMI support on the Pumpkin board. + +However, the external display is not fully described on Chrome devices, +blocked by further work on DP / USB-C muxing graph bindings. This +incomplete description currently breaks internal display at least on the +Cozmo board. The same issue was found and fixed on MT8186 devices with +commit 3079fb09ddac ("arm64: dts: mediatek: mt8186-corsola: Disable DPI +display interface"), but the MT8183 change wasn't merged until then. + +Disable the external display interface for the Kukui device family until +the necessary work is done, like in the MT8186 Corsola case. + +Fixes: 009d855a26fd ("arm64: dts: mt8183: add dpi node to mt8183") +Link: https://lore.kernel.org/linux-mediatek/20240821042836.2631815-1-wenst@chromium.org/ +Signed-off-by: Alper Nebi Yasak +Reviewed-by: Pin-yen Lin +Reviewed-by: AngeloGioacchino Del Regno +Link: https://lore.kernel.org/r/20240916162956.267340-1-alpernebiyasak@gmail.com +Signed-off-by: AngeloGioacchino Del Regno +Signed-off-by: Sasha Levin +--- + arch/arm64/boot/dts/mediatek/mt8183-kukui.dtsi | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/arch/arm64/boot/dts/mediatek/mt8183-kukui.dtsi b/arch/arm64/boot/dts/mediatek/mt8183-kukui.dtsi +index 22924f61ec9ed..07ae3c8e897b7 100644 +--- a/arch/arm64/boot/dts/mediatek/mt8183-kukui.dtsi ++++ b/arch/arm64/boot/dts/mediatek/mt8183-kukui.dtsi +@@ -290,6 +290,11 @@ dsi_out: endpoint { + }; + }; + ++&dpi0 { ++ /* TODO Re-enable after DP to Type-C port muxing can be described */ ++ status = "disabled"; ++}; ++ + &gic { + mediatek,broken-save-restore-fw; + }; +-- +2.43.0 + diff --git a/queue-6.12/arm64-dts-mediatek-mt8183-kukui-jacuzzi-add-supplies.patch b/queue-6.12/arm64-dts-mediatek-mt8183-kukui-jacuzzi-add-supplies.patch new file mode 100644 index 00000000000..6ccb55e46f4 --- /dev/null +++ b/queue-6.12/arm64-dts-mediatek-mt8183-kukui-jacuzzi-add-supplies.patch @@ -0,0 +1,64 @@ +From 2ce174fda90a22435a2591ff40cd4e2a7e7df438 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 30 Oct 2024 15:02:22 +0800 +Subject: arm64: dts: mediatek: mt8183-kukui-jacuzzi: Add supplies for fixed + regulators + +From: Chen-Yu Tsai + +[ Upstream commit aaecb1da58a72bfbd2c35d4aadc43caa02f11862 ] + +When the fixed regulators for the LCD panel and DP bridge were added, +their supplies were not modeled in. These, except for the 1.0V supply, +are just load switches, and need and have a supply. + +Add the supplies for each of the fixed regulators. + +Fixes: cabc71b08eb5 ("arm64: dts: mt8183: Add kukui-jacuzzi-damu board") +Signed-off-by: Chen-Yu Tsai +Link: https://lore.kernel.org/r/20241030070224.1006331-4-wenst@chromium.org +Signed-off-by: AngeloGioacchino Del Regno +Signed-off-by: Sasha Levin +--- + arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi.dtsi | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi.dtsi b/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi.dtsi +index ac7ec0676e147..49e053b932e76 100644 +--- a/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi.dtsi ++++ b/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi.dtsi +@@ -20,6 +20,7 @@ pp1000_mipibrdg: pp1000-mipibrdg { + regulator-boot-on; + + gpio = <&pio 54 GPIO_ACTIVE_HIGH>; ++ vin-supply = <&pp1800_alw>; + }; + + pp1800_mipibrdg: pp1800-mipibrdg { +@@ -32,6 +33,7 @@ pp1800_mipibrdg: pp1800-mipibrdg { + regulator-boot-on; + + gpio = <&pio 36 GPIO_ACTIVE_HIGH>; ++ vin-supply = <&pp1800_alw>; + }; + + pp3300_panel: pp3300-panel { +@@ -46,6 +48,7 @@ pp3300_panel: pp3300-panel { + regulator-boot-on; + + gpio = <&pio 35 GPIO_ACTIVE_HIGH>; ++ vin-supply = <&pp3300_alw>; + }; + + pp3300_mipibrdg: pp3300-mipibrdg { +@@ -58,6 +61,7 @@ pp3300_mipibrdg: pp3300-mipibrdg { + regulator-boot-on; + + gpio = <&pio 37 GPIO_ACTIVE_HIGH>; ++ vin-supply = <&pp3300_alw>; + }; + + volume_buttons: volume-buttons { +-- +2.43.0 + diff --git a/queue-6.12/arm64-dts-mediatek-mt8183-kukui-jacuzzi-fix-dp-bridg.patch b/queue-6.12/arm64-dts-mediatek-mt8183-kukui-jacuzzi-fix-dp-bridg.patch new file mode 100644 index 00000000000..65a355687fd --- /dev/null +++ b/queue-6.12/arm64-dts-mediatek-mt8183-kukui-jacuzzi-fix-dp-bridg.patch @@ -0,0 +1,112 @@ +From 6d0b23134cc7fee5b7843743063294bf17b82fae Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 30 Oct 2024 15:02:21 +0800 +Subject: arm64: dts: mediatek: mt8183-kukui-jacuzzi: Fix DP bridge supply + names + +From: Chen-Yu Tsai + +[ Upstream commit c4e8cf13f1740037483565d5b802764e2426515b ] + +Some of the regulator supplies for the MIPI-DPI-to-DP bridge and their +associated nodes are incorrectly named. In particular, the 1.0V supply +was modeled as a 1.2V supply. + +Fix all the incorrect names, and also fix the voltage of the 1.0V +regulator. + +Fixes: cabc71b08eb5 ("arm64: dts: mt8183: Add kukui-jacuzzi-damu board") +Signed-off-by: Chen-Yu Tsai +Link: https://lore.kernel.org/r/20241030070224.1006331-3-wenst@chromium.org +Signed-off-by: AngeloGioacchino Del Regno +Signed-off-by: Sasha Levin +--- + .../dts/mediatek/mt8183-kukui-jacuzzi.dtsi | 26 ++++++++++--------- + 1 file changed, 14 insertions(+), 12 deletions(-) + +diff --git a/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi.dtsi b/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi.dtsi +index 783c333107bcb..ac7ec0676e147 100644 +--- a/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi.dtsi ++++ b/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi.dtsi +@@ -8,11 +8,13 @@ + #include + + / { +- pp1200_mipibrdg: pp1200-mipibrdg { ++ pp1000_mipibrdg: pp1000-mipibrdg { + compatible = "regulator-fixed"; +- regulator-name = "pp1200_mipibrdg"; ++ regulator-name = "pp1000_mipibrdg"; ++ regulator-min-microvolt = <1000000>; ++ regulator-max-microvolt = <1000000>; + pinctrl-names = "default"; +- pinctrl-0 = <&pp1200_mipibrdg_en>; ++ pinctrl-0 = <&pp1000_mipibrdg_en>; + + enable-active-high; + regulator-boot-on; +@@ -24,7 +26,7 @@ pp1800_mipibrdg: pp1800-mipibrdg { + compatible = "regulator-fixed"; + regulator-name = "pp1800_mipibrdg"; + pinctrl-names = "default"; +- pinctrl-0 = <&pp1800_lcd_en>; ++ pinctrl-0 = <&pp1800_mipibrdg_en>; + + enable-active-high; + regulator-boot-on; +@@ -46,11 +48,11 @@ pp3300_panel: pp3300-panel { + gpio = <&pio 35 GPIO_ACTIVE_HIGH>; + }; + +- vddio_mipibrdg: vddio-mipibrdg { ++ pp3300_mipibrdg: pp3300-mipibrdg { + compatible = "regulator-fixed"; +- regulator-name = "vddio_mipibrdg"; ++ regulator-name = "pp3300_mipibrdg"; + pinctrl-names = "default"; +- pinctrl-0 = <&vddio_mipibrdg_en>; ++ pinctrl-0 = <&pp3300_mipibrdg_en>; + + enable-active-high; + regulator-boot-on; +@@ -146,9 +148,9 @@ anx_bridge: anx7625@58 { + pinctrl-0 = <&anx7625_pins>; + enable-gpios = <&pio 45 GPIO_ACTIVE_HIGH>; + reset-gpios = <&pio 73 GPIO_ACTIVE_HIGH>; +- vdd10-supply = <&pp1200_mipibrdg>; ++ vdd10-supply = <&pp1000_mipibrdg>; + vdd18-supply = <&pp1800_mipibrdg>; +- vdd33-supply = <&vddio_mipibrdg>; ++ vdd33-supply = <&pp3300_mipibrdg>; + + ports { + #address-cells = <1>; +@@ -391,14 +393,14 @@ &pio { + "", + ""; + +- pp1200_mipibrdg_en: pp1200-mipibrdg-en { ++ pp1000_mipibrdg_en: pp1000-mipibrdg-en { + pins1 { + pinmux = ; + output-low; + }; + }; + +- pp1800_lcd_en: pp1800-lcd-en { ++ pp1800_mipibrdg_en: pp1800-mipibrdg-en { + pins1 { + pinmux = ; + output-low; +@@ -460,7 +462,7 @@ trackpad-int { + }; + }; + +- vddio_mipibrdg_en: vddio-mipibrdg-en { ++ pp3300_mipibrdg_en: pp3300-mipibrdg-en { + pins1 { + pinmux = ; + output-low; +-- +2.43.0 + diff --git a/queue-6.12/arm64-dts-mediatek-mt8188-fix-usb3-phy-port-default-.patch b/queue-6.12/arm64-dts-mediatek-mt8188-fix-usb3-phy-port-default-.patch new file mode 100644 index 00000000000..d85f2bed912 --- /dev/null +++ b/queue-6.12/arm64-dts-mediatek-mt8188-fix-usb3-phy-port-default-.patch @@ -0,0 +1,42 @@ +From c2b69ad7e9fbdff1094c855ef6f69430aac86d65 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 21 Oct 2024 16:10:47 +0800 +Subject: arm64: dts: mediatek: mt8188: Fix USB3 PHY port default status + +From: Fei Shao + +[ Upstream commit 6bb64877a41561bc78e0f4e9e04d524a0155d6aa ] + +The T-PHY controller at 0x11e40000 controls two underlying USB2 and USB3 +PHY ports. The USB3 port works normally just like the others, so there's +no point in disabling it separately. Otherwise, board DTs would have to +enable both the T-PHY controller and one of its sub-nodes in particular, +which is slightly redundant and confusing. + +Remove the status line in the u3port1 node, so it's ready to be used +once the T-PHY controller is enabled. + +Fixes: 9461e0caac9e ("arm64: dts: Add MediaTek MT8188 dts and evaluation board and Makefile") +Signed-off-by: Fei Shao +Link: https://lore.kernel.org/r/20241021081311.543625-1-fshao@chromium.org +Signed-off-by: AngeloGioacchino Del Regno +Signed-off-by: Sasha Levin +--- + arch/arm64/boot/dts/mediatek/mt8188.dtsi | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/arch/arm64/boot/dts/mediatek/mt8188.dtsi b/arch/arm64/boot/dts/mediatek/mt8188.dtsi +index 02a5bb4dbd1f8..91beef22e0a9c 100644 +--- a/arch/arm64/boot/dts/mediatek/mt8188.dtsi ++++ b/arch/arm64/boot/dts/mediatek/mt8188.dtsi +@@ -1689,7 +1689,6 @@ u3port1: usb-phy@700 { + <&clk26m>; + clock-names = "ref", "da_ref"; + #phy-cells = <1>; +- status = "disabled"; + }; + }; + +-- +2.43.0 + diff --git a/queue-6.12/arm64-dts-mediatek-mt8188-fix-wrong-clock-provider-i.patch b/queue-6.12/arm64-dts-mediatek-mt8188-fix-wrong-clock-provider-i.patch new file mode 100644 index 00000000000..0823096e88f --- /dev/null +++ b/queue-6.12/arm64-dts-mediatek-mt8188-fix-wrong-clock-provider-i.patch @@ -0,0 +1,45 @@ +From 04db84282f8ec070816f82324a915ee2c568e938 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 2 Oct 2024 10:21:33 +0800 +Subject: arm64: dts: mediatek: mt8188: Fix wrong clock provider in MFG1 power + domain + +From: Pablo Sun + +[ Upstream commit 4007651c25553b10dbc6e7bff6b7abd2863c1702 ] + +The clock index "CLK_APMIXED_MFGPLL" belongs to the "apmixedsys" provider, +so fix the index. + +In addition, add a "mfg1" label so following commits could set +domain-supply for MFG1 power domain. + +Fixes: eaf73e4224a3 ("arm64: dts: mediatek: mt8188: Add support for SoC power domains") +Signed-off-by: Pablo Sun +Reviewed-by: AngeloGioacchino Del Regno +Link: https://lore.kernel.org/r/20241002022138.29241-2-pablo.sun@mediatek.com +Signed-off-by: AngeloGioacchino Del Regno +Signed-off-by: Sasha Levin +--- + arch/arm64/boot/dts/mediatek/mt8188.dtsi | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/arch/arm64/boot/dts/mediatek/mt8188.dtsi b/arch/arm64/boot/dts/mediatek/mt8188.dtsi +index cd27966d2e3c0..02a5bb4dbd1f8 100644 +--- a/arch/arm64/boot/dts/mediatek/mt8188.dtsi ++++ b/arch/arm64/boot/dts/mediatek/mt8188.dtsi +@@ -956,9 +956,9 @@ mfg0: power-domain@MT8188_POWER_DOMAIN_MFG0 { + #size-cells = <0>; + #power-domain-cells = <1>; + +- power-domain@MT8188_POWER_DOMAIN_MFG1 { ++ mfg1: power-domain@MT8188_POWER_DOMAIN_MFG1 { + reg = ; +- clocks = <&topckgen CLK_APMIXED_MFGPLL>, ++ clocks = <&apmixedsys CLK_APMIXED_MFGPLL>, + <&topckgen CLK_TOP_MFG_CORE_TMP>; + clock-names = "mfg", "alt"; + mediatek,infracfg = <&infracfg_ao>; +-- +2.43.0 + diff --git a/queue-6.12/arm64-dts-mediatek-mt8195-cherry-use-correct-audio-c.patch b/queue-6.12/arm64-dts-mediatek-mt8195-cherry-use-correct-audio-c.patch new file mode 100644 index 00000000000..e558af802e0 --- /dev/null +++ b/queue-6.12/arm64-dts-mediatek-mt8195-cherry-use-correct-audio-c.patch @@ -0,0 +1,62 @@ +From 3487211a20ac13693192d4c56f409389d9b8184e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 21 Oct 2024 19:39:33 +0800 +Subject: arm64: dts: mediatek: mt8195-cherry: Use correct audio codec DAI + +From: Fei Shao + +[ Upstream commit 7d5794e6d964940e46286fadbe69a3245fa51e44 ] + +The RT5682i and RT5682s drivers describe two DAIs: AIF1 supports both +playback and capture, while AIF2 supports capture only. + +Cherry doesn't specify which DAI to use. Although this doesn't cause +real issues because AIF1 happens to be the first DAI, it should be +corrected: + codec@1a: #sound-dai-cells: 1 was expected + +Update #sound-dai-cells to 1 and adjust DAI link usages accordingly. + +Fixes: 87728e3ccf35 ("arm64: dts: mediatek: mt8195-cherry: Specify sound DAI links and routing") +Signed-off-by: Fei Shao +Link: https://lore.kernel.org/r/20241021114318.1358681-1-fshao@chromium.org +Signed-off-by: AngeloGioacchino Del Regno +Signed-off-by: Sasha Levin +--- + arch/arm64/boot/dts/mediatek/mt8195-cherry.dtsi | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/arch/arm64/boot/dts/mediatek/mt8195-cherry.dtsi b/arch/arm64/boot/dts/mediatek/mt8195-cherry.dtsi +index 75d56b2d5a3d3..2c7b2223ee76b 100644 +--- a/arch/arm64/boot/dts/mediatek/mt8195-cherry.dtsi ++++ b/arch/arm64/boot/dts/mediatek/mt8195-cherry.dtsi +@@ -438,7 +438,7 @@ audio_codec: codec@1a { + /* Realtek RT5682i or RT5682s, sharing the same configuration */ + reg = <0x1a>; + interrupts-extended = <&pio 89 IRQ_TYPE_EDGE_BOTH>; +- #sound-dai-cells = <0>; ++ #sound-dai-cells = <1>; + realtek,jd-src = <1>; + + AVDD-supply = <&mt6359_vio18_ldo_reg>; +@@ -1181,7 +1181,7 @@ hs-playback-dai-link { + link-name = "ETDM1_OUT_BE"; + mediatek,clk-provider = "cpu"; + codec { +- sound-dai = <&audio_codec>; ++ sound-dai = <&audio_codec 0>; + }; + }; + +@@ -1189,7 +1189,7 @@ hs-capture-dai-link { + link-name = "ETDM2_IN_BE"; + mediatek,clk-provider = "cpu"; + codec { +- sound-dai = <&audio_codec>; ++ sound-dai = <&audio_codec 0>; + }; + }; + +-- +2.43.0 + diff --git a/queue-6.12/arm64-dts-mediatek-mt8395-genio-1200-evk-fix-dtbs_ch.patch b/queue-6.12/arm64-dts-mediatek-mt8395-genio-1200-evk-fix-dtbs_ch.patch new file mode 100644 index 00000000000..a11c9a5487d --- /dev/null +++ b/queue-6.12/arm64-dts-mediatek-mt8395-genio-1200-evk-fix-dtbs_ch.patch @@ -0,0 +1,42 @@ +From 4235f2371522d458a6022e174ea8b27b6c2b1be3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 2 Oct 2024 13:16:18 +0800 +Subject: arm64: dts: mediatek: mt8395-genio-1200-evk: Fix dtbs_check error for + phy + +From: Macpaul Lin + +[ Upstream commit 752804acea010959bb3a00c65acdf78086a8474c ] + +The ethernet-phy node in mt8395-genio-1200-evk.dts was triggering a +dtbs_check error. The error message was: + eth-phy0@1: $nodename:0: 'eth-phy0@1' does not match + '^ethernet-phy(@[a-f0-9]+)?$' +Fix this issue by replacing 'eth-phy' node to generic 'ethernet-phy'. + +Fixes: f2b543a191b6 ("arm64: dts: mediatek: add device-tree for Genio 1200 EVK board") +Signed-off-by: Macpaul Lin +Reviewed-by: AngeloGioacchino Del Regno +Link: https://lore.kernel.org/r/20241002051620.2050-3-macpaul.lin@mediatek.com +Signed-off-by: AngeloGioacchino Del Regno +Signed-off-by: Sasha Levin +--- + arch/arm64/boot/dts/mediatek/mt8395-genio-1200-evk.dts | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/arch/arm64/boot/dts/mediatek/mt8395-genio-1200-evk.dts b/arch/arm64/boot/dts/mediatek/mt8395-genio-1200-evk.dts +index 1ef6262b65c9a..b4b48eb93f3c5 100644 +--- a/arch/arm64/boot/dts/mediatek/mt8395-genio-1200-evk.dts ++++ b/arch/arm64/boot/dts/mediatek/mt8395-genio-1200-evk.dts +@@ -187,7 +187,7 @@ mdio { + compatible = "snps,dwmac-mdio"; + #address-cells = <1>; + #size-cells = <0>; +- eth_phy0: eth-phy0@1 { ++ eth_phy0: ethernet-phy@1 { + compatible = "ethernet-phy-id001c.c916"; + reg = <0x1>; + }; +-- +2.43.0 + diff --git a/queue-6.12/arm64-dts-mt8183-add-port-node-to-dpi-node.patch b/queue-6.12/arm64-dts-mt8183-add-port-node-to-dpi-node.patch new file mode 100644 index 00000000000..b0dd778f9cc --- /dev/null +++ b/queue-6.12/arm64-dts-mt8183-add-port-node-to-dpi-node.patch @@ -0,0 +1,40 @@ +From c2842bb0b4d49c7aec12ea059b070e57fdab6c39 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 12 Sep 2024 22:43:59 +0800 +Subject: arm64: dts: mt8183: Add port node to dpi node + +From: Pin-yen Lin + +[ Upstream commit ec1a37b3cd0cf9a1bf88816a5342fb06e3316b34 ] + +Add the port node to fix the binding schema check. + +Fixes: 009d855a26fd ("arm64: dts: mt8183: add dpi node to mt8183") +Signed-off-by: Pin-yen Lin +Reported-by: kernel test robot +Closes: https://lore.kernel.org/oe-kbuild-all/202409110843.Hm5W9upr-lkp@intel.com/ +Link: https://lore.kernel.org/r/20240912144430.3161717-3-treapking@chromium.org +Signed-off-by: AngeloGioacchino Del Regno +Signed-off-by: Sasha Levin +--- + arch/arm64/boot/dts/mediatek/mt8183.dtsi | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/arch/arm64/boot/dts/mediatek/mt8183.dtsi b/arch/arm64/boot/dts/mediatek/mt8183.dtsi +index 266441e999f21..0a6578aacf828 100644 +--- a/arch/arm64/boot/dts/mediatek/mt8183.dtsi ++++ b/arch/arm64/boot/dts/mediatek/mt8183.dtsi +@@ -1845,6 +1845,10 @@ dpi0: dpi@14015000 { + <&mmsys CLK_MM_DPI_MM>, + <&apmixedsys CLK_APMIXED_TVDPLL>; + clock-names = "pixel", "engine", "pll"; ++ ++ port { ++ dpi_out: endpoint { }; ++ }; + }; + + mutex: mutex@14016000 { +-- +2.43.0 + diff --git a/queue-6.12/arm64-dts-mt8183-burnet-add-i2c2-s-i2c-scl-internal-.patch b/queue-6.12/arm64-dts-mt8183-burnet-add-i2c2-s-i2c-scl-internal-.patch new file mode 100644 index 00000000000..f8d6dbeef7c --- /dev/null +++ b/queue-6.12/arm64-dts-mt8183-burnet-add-i2c2-s-i2c-scl-internal-.patch @@ -0,0 +1,37 @@ +From 5eaa06f0cfc987fcd0e55cd59ddc406a4d736d59 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 25 Oct 2024 16:03:49 +0800 +Subject: arm64: dts: mt8183: burnet: add i2c2's i2c-scl-internal-delay-ns + +From: Daolong Zhu + +[ Upstream commit 85af64983889c621e8868b744c8ca03bd5038c02 ] + +Add i2c2's i2c-scl-internal-delay-ns. + +Fixes: dd6e3b06214f ("arm64: dts: mt8183: Add kukui-jacuzzi-burnet board") +Reviewed-by: Matthias Brugger +Reviewed-by: AngeloGioacchino Del Regno +Signed-off-by: Daolong Zhu +Signed-off-by: Hsin-Te Yuan +Link: https://lore.kernel.org/r/20241025-i2c-delay-v2-2-9be1bcaf35e0@chromium.org +Signed-off-by: AngeloGioacchino Del Regno +Signed-off-by: Sasha Levin +--- + arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-burnet.dts | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-burnet.dts b/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-burnet.dts +index 19c1e2bee494c..20b71f2e7159a 100644 +--- a/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-burnet.dts ++++ b/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-burnet.dts +@@ -30,3 +30,6 @@ touchscreen@2c { + }; + }; + ++&i2c2 { ++ i2c-scl-internal-delay-ns = <4100>; ++}; +-- +2.43.0 + diff --git a/queue-6.12/arm64-dts-mt8183-cozmo-add-i2c2-s-i2c-scl-internal-d.patch b/queue-6.12/arm64-dts-mt8183-cozmo-add-i2c2-s-i2c-scl-internal-d.patch new file mode 100644 index 00000000000..1d11271ae1d --- /dev/null +++ b/queue-6.12/arm64-dts-mt8183-cozmo-add-i2c2-s-i2c-scl-internal-d.patch @@ -0,0 +1,39 @@ +From 1828b4694801d96a86628ed639dfc7b447981652 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 25 Oct 2024 16:03:50 +0800 +Subject: arm64: dts: mt8183: cozmo: add i2c2's i2c-scl-internal-delay-ns + +From: Daolong Zhu + +[ Upstream commit bd0eb3b1f7aee698b86513edf10a50e2d0c7cb14 ] + +Add i2c2's i2c-scl-internal-delay-ns. + +Fixes: 52e84f233459 ("arm64: dts: mt8183: Add kukui-jacuzzi-cozmo board") +Reviewed-by: Matthias Brugger +Reviewed-by: AngeloGioacchino Del Regno +Signed-off-by: Daolong Zhu +Signed-off-by: Hsin-Te Yuan +Link: https://lore.kernel.org/r/20241025-i2c-delay-v2-3-9be1bcaf35e0@chromium.org +Signed-off-by: AngeloGioacchino Del Regno +Signed-off-by: Sasha Levin +--- + arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-cozmo.dts | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-cozmo.dts b/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-cozmo.dts +index f34964afe39b5..83bbcfe620835 100644 +--- a/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-cozmo.dts ++++ b/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-cozmo.dts +@@ -18,6 +18,8 @@ &i2c_tunnel { + }; + + &i2c2 { ++ i2c-scl-internal-delay-ns = <25000>; ++ + trackpad@2c { + compatible = "hid-over-i2c"; + reg = <0x2c>; +-- +2.43.0 + diff --git a/queue-6.12/arm64-dts-mt8183-damu-add-i2c2-s-i2c-scl-internal-de.patch b/queue-6.12/arm64-dts-mt8183-damu-add-i2c2-s-i2c-scl-internal-de.patch new file mode 100644 index 00000000000..a6041d484ee --- /dev/null +++ b/queue-6.12/arm64-dts-mt8183-damu-add-i2c2-s-i2c-scl-internal-de.patch @@ -0,0 +1,37 @@ +From 89db67d282c28317ccba474f5c1418eda3b4eac3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 25 Oct 2024 16:03:51 +0800 +Subject: arm64: dts: mt8183: Damu: add i2c2's i2c-scl-internal-delay-ns + +From: Daolong Zhu + +[ Upstream commit 6ff2d45f2121c698a57c959ae21885a048615908 ] + +Add i2c2's i2c-scl-internal-delay-ns. + +Fixes: cabc71b08eb5 ("arm64: dts: mt8183: Add kukui-jacuzzi-damu board") +Reviewed-by: Matthias Brugger +Reviewed-by: AngeloGioacchino Del Regno +Signed-off-by: Daolong Zhu +Signed-off-by: Hsin-Te Yuan +Link: https://lore.kernel.org/r/20241025-i2c-delay-v2-4-9be1bcaf35e0@chromium.org +Signed-off-by: AngeloGioacchino Del Regno +Signed-off-by: Sasha Levin +--- + arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-damu.dts | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-damu.dts b/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-damu.dts +index 0b45aee2e2995..65860b33c01fe 100644 +--- a/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-damu.dts ++++ b/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-damu.dts +@@ -30,3 +30,6 @@ &qca_wifi { + qcom,ath10k-calibration-variant = "GO_DAMU"; + }; + ++&i2c2 { ++ i2c-scl-internal-delay-ns = <20000>; ++}; +-- +2.43.0 + diff --git a/queue-6.12/arm64-dts-mt8183-fennel-add-i2c2-s-i2c-scl-internal-.patch b/queue-6.12/arm64-dts-mt8183-fennel-add-i2c2-s-i2c-scl-internal-.patch new file mode 100644 index 00000000000..f78438ea2eb --- /dev/null +++ b/queue-6.12/arm64-dts-mt8183-fennel-add-i2c2-s-i2c-scl-internal-.patch @@ -0,0 +1,38 @@ +From b90a1873d95c978ab92bc10fa8d4b4516f6ec179 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 25 Oct 2024 16:03:48 +0800 +Subject: arm64: dts: mt8183: fennel: add i2c2's i2c-scl-internal-delay-ns + +From: Daolong Zhu + +[ Upstream commit c802db127dfb9602aaa9338e433c0553d34f1a9c ] + +Add i2c2's i2c-scl-internal-delay-ns. + +Fixes: 6cd7fdc8c530 ("arm64: dts: mt8183: Add kukui-jacuzzi-fennel board") +Reviewed-by: Matthias Brugger +Reviewed-by: AngeloGioacchino Del Regno +Signed-off-by: Daolong Zhu +Signed-off-by: Hsin-Te Yuan +Reviewed-by: +Link: https://lore.kernel.org/r/20241025-i2c-delay-v2-1-9be1bcaf35e0@chromium.org +Signed-off-by: AngeloGioacchino Del Regno +Signed-off-by: Sasha Levin +--- + arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-fennel.dtsi | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-fennel.dtsi b/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-fennel.dtsi +index bbe6c338f465e..f9c1ec366b266 100644 +--- a/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-fennel.dtsi ++++ b/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-fennel.dtsi +@@ -25,3 +25,6 @@ trackpad@2c { + }; + }; + ++&i2c2 { ++ i2c-scl-internal-delay-ns = <21500>; ++}; +-- +2.43.0 + diff --git a/queue-6.12/arm64-dts-mt8183-krane-fix-the-address-of-eeprom-at-.patch b/queue-6.12/arm64-dts-mt8183-krane-fix-the-address-of-eeprom-at-.patch new file mode 100644 index 00000000000..5aeee9ceac0 --- /dev/null +++ b/queue-6.12/arm64-dts-mt8183-krane-fix-the-address-of-eeprom-at-.patch @@ -0,0 +1,41 @@ +From aa1d89c520ae4a09d9ea1cfd5c9e655054350950 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 9 Sep 2024 08:33:46 +0000 +Subject: arm64: dts: mt8183: krane: Fix the address of eeprom at i2c4 + +From: Hsin-Te Yuan + +[ Upstream commit e9c60c34948662b5d47573490ee538439b29e462 ] + +The address of eeprom should be 50. + +Fixes: cd894e274b74 ("arm64: dts: mt8183: Add krane-sku176 board") +Signed-off-by: Hsin-Te Yuan +Reviewed-by: AngeloGioacchino Del Regno +Reviewed-by: Matthias Brugger +Link: https://lore.kernel.org/r/20240909-eeprom-v1-1-1ed2bc5064f4@chromium.org +Signed-off-by: AngeloGioacchino Del Regno +Signed-off-by: Sasha Levin +--- + arch/arm64/boot/dts/mediatek/mt8183-kukui-krane.dtsi | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/arch/arm64/boot/dts/mediatek/mt8183-kukui-krane.dtsi b/arch/arm64/boot/dts/mediatek/mt8183-kukui-krane.dtsi +index 0f5fa893a7742..8b56b8564ed7a 100644 +--- a/arch/arm64/boot/dts/mediatek/mt8183-kukui-krane.dtsi ++++ b/arch/arm64/boot/dts/mediatek/mt8183-kukui-krane.dtsi +@@ -88,9 +88,9 @@ &i2c4 { + clock-frequency = <400000>; + vbus-supply = <&mt6358_vcn18_reg>; + +- eeprom@54 { ++ eeprom@50 { + compatible = "atmel,24c32"; +- reg = <0x54>; ++ reg = <0x50>; + pagesize = <32>; + vcc-supply = <&mt6358_vcn18_reg>; + }; +-- +2.43.0 + diff --git a/queue-6.12/arm64-dts-mt8183-kukui-fix-the-address-of-eeprom-at-.patch b/queue-6.12/arm64-dts-mt8183-kukui-fix-the-address-of-eeprom-at-.patch new file mode 100644 index 00000000000..67e3885a3fe --- /dev/null +++ b/queue-6.12/arm64-dts-mt8183-kukui-fix-the-address-of-eeprom-at-.patch @@ -0,0 +1,59 @@ +From dcb7e9365e3598b5592bae546a44c039c992daeb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 9 Sep 2024 08:33:47 +0000 +Subject: arm64: dts: mt8183: kukui: Fix the address of eeprom at i2c4 + +From: Hsin-Te Yuan + +[ Upstream commit edbde4923f208aa83abb48d4b2463299e5fc2586 ] + +The address of eeprom should be 50. + +Fixes: ff33d889567e ("arm64: dts: mt8183: Add kukui kodama board") +Fixes: d1eaf77f2c66 ("arm64: dts: mt8183: Add kukui kakadu board") +Signed-off-by: Hsin-Te Yuan +Reviewed-by: Matthias Brugger +Reviewed-by: AngeloGioacchino Del Regno +Link: https://lore.kernel.org/r/20240909-eeprom-v1-2-1ed2bc5064f4@chromium.org +Signed-off-by: AngeloGioacchino Del Regno +Signed-off-by: Sasha Levin +--- + arch/arm64/boot/dts/mediatek/mt8183-kukui-kakadu.dtsi | 4 ++-- + arch/arm64/boot/dts/mediatek/mt8183-kukui-kodama.dtsi | 4 ++-- + 2 files changed, 4 insertions(+), 4 deletions(-) + +diff --git a/arch/arm64/boot/dts/mediatek/mt8183-kukui-kakadu.dtsi b/arch/arm64/boot/dts/mediatek/mt8183-kukui-kakadu.dtsi +index bfb9e42c8acaa..ff02f63bac29b 100644 +--- a/arch/arm64/boot/dts/mediatek/mt8183-kukui-kakadu.dtsi ++++ b/arch/arm64/boot/dts/mediatek/mt8183-kukui-kakadu.dtsi +@@ -92,9 +92,9 @@ &i2c4 { + clock-frequency = <400000>; + vbus-supply = <&mt6358_vcn18_reg>; + +- eeprom@54 { ++ eeprom@50 { + compatible = "atmel,24c32"; +- reg = <0x54>; ++ reg = <0x50>; + pagesize = <32>; + vcc-supply = <&mt6358_vcn18_reg>; + }; +diff --git a/arch/arm64/boot/dts/mediatek/mt8183-kukui-kodama.dtsi b/arch/arm64/boot/dts/mediatek/mt8183-kukui-kodama.dtsi +index 5c1bf6a1e4758..da6e767b4ceed 100644 +--- a/arch/arm64/boot/dts/mediatek/mt8183-kukui-kodama.dtsi ++++ b/arch/arm64/boot/dts/mediatek/mt8183-kukui-kodama.dtsi +@@ -79,9 +79,9 @@ &i2c4 { + clock-frequency = <400000>; + vbus-supply = <&mt6358_vcn18_reg>; + +- eeprom@54 { ++ eeprom@50 { + compatible = "atmel,24c64"; +- reg = <0x54>; ++ reg = <0x50>; + pagesize = <32>; + vcc-supply = <&mt6358_vcn18_reg>; + }; +-- +2.43.0 + diff --git a/queue-6.12/arm64-dts-mt8195-fix-dtbs_check-error-for-infracfg_a.patch b/queue-6.12/arm64-dts-mt8195-fix-dtbs_check-error-for-infracfg_a.patch new file mode 100644 index 00000000000..4c7fe3af0b2 --- /dev/null +++ b/queue-6.12/arm64-dts-mt8195-fix-dtbs_check-error-for-infracfg_a.patch @@ -0,0 +1,44 @@ +From fe539cc6b9e657e7cffa0fedd59fdd3d509a8514 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 2 Oct 2024 13:16:16 +0800 +Subject: arm64: dts: mt8195: Fix dtbs_check error for infracfg_ao node + +From: Macpaul Lin + +[ Upstream commit c14ab45f5d458073248ddc62d31045d5d616806f ] + +The infracfg_ao node in mt8195.dtsi was causing a dtbs_check error. +The error message was: + +syscon@10001000: compatible: ['mediatek,mt8195-infracfg_ao', 'syscon', + 'simple-mfd'] is too long + +To resolve this, remove 'simple-mfd' from the 'compatible' property of the +infracfg_ao node. + +Fixes: 37f2582883be ("arm64: dts: Add mediatek SoC mt8195 and evaluation board") +Signed-off-by: Macpaul Lin +Reviewed-by: AngeloGioacchino Del Regno +Link: https://lore.kernel.org/r/20241002051620.2050-1-macpaul.lin@mediatek.com +Signed-off-by: AngeloGioacchino Del Regno +Signed-off-by: Sasha Levin +--- + arch/arm64/boot/dts/mediatek/mt8195.dtsi | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/arch/arm64/boot/dts/mediatek/mt8195.dtsi b/arch/arm64/boot/dts/mediatek/mt8195.dtsi +index 3a2ba8aac66bb..ade685ed2190b 100644 +--- a/arch/arm64/boot/dts/mediatek/mt8195.dtsi ++++ b/arch/arm64/boot/dts/mediatek/mt8195.dtsi +@@ -487,7 +487,7 @@ topckgen: syscon@10000000 { + }; + + infracfg_ao: syscon@10001000 { +- compatible = "mediatek,mt8195-infracfg_ao", "syscon", "simple-mfd"; ++ compatible = "mediatek,mt8195-infracfg_ao", "syscon"; + reg = <0 0x10001000 0 0x1000>; + #clock-cells = <1>; + #reset-cells = <1>; +-- +2.43.0 + diff --git a/queue-6.12/arm64-dts-mt8195-fix-dtbs_check-error-for-mutex-node.patch b/queue-6.12/arm64-dts-mt8195-fix-dtbs_check-error-for-mutex-node.patch new file mode 100644 index 00000000000..eb23134bdff --- /dev/null +++ b/queue-6.12/arm64-dts-mt8195-fix-dtbs_check-error-for-mutex-node.patch @@ -0,0 +1,45 @@ +From bd8c6cbf4ea1e10c5686565ee434e620a556d341 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 2 Oct 2024 13:16:19 +0800 +Subject: arm64: dts: mt8195: Fix dtbs_check error for mutex node + +From: Macpaul Lin + +[ Upstream commit 0fc557b539a1e11bdc5053a308b12d84ea754786 ] + +The mutex node in mt8195.dtsi was triggering a dtbs_check error: + mutex@1c101000: 'clock-names', 'reg-names' do not match any of the + regexes: 'pinctrl-[0-9]+' + +This seems no need by inspecting the DT schemas and other reference boards, +so drop 'clock-names' and 'reg-names' in mt8195.dtsi. + +Fixes: 92d2c23dc269 ("arm64: dts: mt8195: add display node for vdosys1") +Signed-off-by: Macpaul Lin +Reviewed-by: AngeloGioacchino Del Regno +Link: https://lore.kernel.org/r/20241002051620.2050-4-macpaul.lin@mediatek.com +Signed-off-by: AngeloGioacchino Del Regno +Signed-off-by: Sasha Levin +--- + arch/arm64/boot/dts/mediatek/mt8195.dtsi | 2 -- + 1 file changed, 2 deletions(-) + +diff --git a/arch/arm64/boot/dts/mediatek/mt8195.dtsi b/arch/arm64/boot/dts/mediatek/mt8195.dtsi +index e89ba384c4aaf..3a2ba8aac66bb 100644 +--- a/arch/arm64/boot/dts/mediatek/mt8195.dtsi ++++ b/arch/arm64/boot/dts/mediatek/mt8195.dtsi +@@ -3331,11 +3331,9 @@ &larb19 &larb21 &larb24 &larb25 + mutex1: mutex@1c101000 { + compatible = "mediatek,mt8195-disp-mutex"; + reg = <0 0x1c101000 0 0x1000>; +- reg-names = "vdo1_mutex"; + interrupts = ; + power-domains = <&spm MT8195_POWER_DOMAIN_VDOSYS1>; + clocks = <&vdosys1 CLK_VDO1_DISP_MUTEX>; +- clock-names = "vdo1_mutex"; + mediatek,gce-client-reg = <&gce0 SUBSYS_1c10XXXX 0x1000 0x1000>; + mediatek,gce-events = ; + }; +-- +2.43.0 + diff --git a/queue-6.12/arm64-dts-qcom-qcs6390-rb3gen2-use-modem.mbn-for-mod.patch b/queue-6.12/arm64-dts-qcom-qcs6390-rb3gen2-use-modem.mbn-for-mod.patch new file mode 100644 index 00000000000..086c9c77d19 --- /dev/null +++ b/queue-6.12/arm64-dts-qcom-qcs6390-rb3gen2-use-modem.mbn-for-mod.patch @@ -0,0 +1,39 @@ +From 82cd15e7a17034aeae3c21af5311cde3aaea3afe Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 7 Sep 2024 15:51:24 +0300 +Subject: arm64: dts: qcom: qcs6390-rb3gen2: use modem.mbn for modem DSP + +From: Dmitry Baryshkov + +[ Upstream commit 6317aad0e1525f3e3609d9a0fea762a37799943a ] + +Newer boards should always use squashed MBN firmware instead of split +MDT+bNN. Use qcom/qcs6490/modem.mbn as the firmware for the modem on +RB3gen2. + +Fixes: ac6d35b9b74c ("arm64: dts: qcom: qcs6490-rb3gen2: Enable various remoteprocs") +Signed-off-by: Dmitry Baryshkov +Reviewed-by: Konrad Dybcio +Link: https://lore.kernel.org/r/20240907-rb3g2-fixes-v1-1-eb9da98e9f80@linaro.org +Signed-off-by: Bjorn Andersson +Signed-off-by: Sasha Levin +--- + arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts b/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts +index 0d45662b8028b..5d0167fbc7098 100644 +--- a/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts ++++ b/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts +@@ -707,7 +707,7 @@ &remoteproc_cdsp { + }; + + &remoteproc_mpss { +- firmware-name = "qcom/qcs6490/modem.mdt"; ++ firmware-name = "qcom/qcs6490/modem.mbn"; + status = "okay"; + }; + +-- +2.43.0 + diff --git a/queue-6.12/arm64-dts-qcom-sc8180x-add-a-soc-specific-compatible.patch b/queue-6.12/arm64-dts-qcom-sc8180x-add-a-soc-specific-compatible.patch new file mode 100644 index 00000000000..bff9d59ce5b --- /dev/null +++ b/queue-6.12/arm64-dts-qcom-sc8180x-add-a-soc-specific-compatible.patch @@ -0,0 +1,40 @@ +From 5753968940fbfa0c529c0b94623baa08222b0ed1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 16 Nov 2024 12:31:18 +0100 +Subject: arm64: dts: qcom: sc8180x: Add a SoC-specific compatible to + cpufreq-hw + +From: Konrad Dybcio + +[ Upstream commit 5df30684415d5a902f23862ab5bbed2a2df7fbf1 ] + +Comply with bindings guidelines and get rid of errors such as: + +cpufreq@18323000: compatible: 'oneOf' conditional failed, one must be fixed: + ['qcom,cpufreq-hw'] is too short + +Fixes: 8575f197b077 ("arm64: dts: qcom: Introduce the SC8180x platform") +Signed-off-by: Konrad Dybcio +Reviewed-by: Dmitry Baryshkov +Signed-off-by: Viresh Kumar +Signed-off-by: Sasha Levin +--- + arch/arm64/boot/dts/qcom/sc8180x.dtsi | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/arch/arm64/boot/dts/qcom/sc8180x.dtsi b/arch/arm64/boot/dts/qcom/sc8180x.dtsi +index 0e9429684dd97..60f71b4902615 100644 +--- a/arch/arm64/boot/dts/qcom/sc8180x.dtsi ++++ b/arch/arm64/boot/dts/qcom/sc8180x.dtsi +@@ -3889,7 +3889,7 @@ lmh@18358800 { + }; + + cpufreq_hw: cpufreq@18323000 { +- compatible = "qcom,cpufreq-hw"; ++ compatible = "qcom,sc8180x-cpufreq-hw", "qcom,cpufreq-hw"; + reg = <0 0x18323000 0 0x1400>, <0 0x18325800 0 0x1400>; + reg-names = "freq-domain0", "freq-domain1"; + +-- +2.43.0 + diff --git a/queue-6.12/arm64-dts-qcom-sda660-ifc6560-fix-l10a-voltage-range.patch b/queue-6.12/arm64-dts-qcom-sda660-ifc6560-fix-l10a-voltage-range.patch new file mode 100644 index 00000000000..0fd77e63529 --- /dev/null +++ b/queue-6.12/arm64-dts-qcom-sda660-ifc6560-fix-l10a-voltage-range.patch @@ -0,0 +1,39 @@ +From cdf63900f7728cda289766b4fd25ce1c726686cc Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 7 Sep 2024 21:48:15 +0300 +Subject: arm64: dts: qcom: sda660-ifc6560: fix l10a voltage ranges + +From: Dmitry Baryshkov + +[ Upstream commit 1dd7d9d41dedf8d42e04c0f2febd4dbe5a062d4a ] + +L10A, being a fixed regulator, should have min_voltage = max_voltage, +otherwise fixed rulator fails to probe. Fix the max_voltage range to be +equal to minimum. + +Fixes: 4edbcf264fe2 ("arm64: dts: qcom: sda660-ifc6560: document missing USB PHY supplies") +Signed-off-by: Dmitry Baryshkov +Reviewed-by: Konrad Dybcio +Link: https://lore.kernel.org/r/20240907-sdm660-wifi-v1-4-e316055142f8@linaro.org +Signed-off-by: Bjorn Andersson +Signed-off-by: Sasha Levin +--- + arch/arm64/boot/dts/qcom/sda660-inforce-ifc6560.dts | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/arch/arm64/boot/dts/qcom/sda660-inforce-ifc6560.dts b/arch/arm64/boot/dts/qcom/sda660-inforce-ifc6560.dts +index 60412281ab27d..962c8aa400440 100644 +--- a/arch/arm64/boot/dts/qcom/sda660-inforce-ifc6560.dts ++++ b/arch/arm64/boot/dts/qcom/sda660-inforce-ifc6560.dts +@@ -104,7 +104,7 @@ vreg_l10a_1p8: vreg-l10a-regulator { + compatible = "regulator-fixed"; + regulator-name = "vreg_l10a_1p8"; + regulator-min-microvolt = <1804000>; +- regulator-max-microvolt = <1896000>; ++ regulator-max-microvolt = <1804000>; + regulator-always-on; + regulator-boot-on; + }; +-- +2.43.0 + diff --git a/queue-6.12/arm64-dts-qcom-sm6350-fix-gpu-frequencies-missing-on.patch b/queue-6.12/arm64-dts-qcom-sm6350-fix-gpu-frequencies-missing-on.patch new file mode 100644 index 00000000000..6337572ddda --- /dev/null +++ b/queue-6.12/arm64-dts-qcom-sm6350-fix-gpu-frequencies-missing-on.patch @@ -0,0 +1,88 @@ +From 678f8e95f7a66150014e373ab6aa779d0edc7e04 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 2 Oct 2024 14:58:06 +0200 +Subject: arm64: dts: qcom: sm6350: Fix GPU frequencies missing on some + speedbins + +From: Luca Weiss + +[ Upstream commit 600c499f8f5297c2c91e8146a8217f299e445ef6 ] + +Make sure the GPU frequencies are marked as supported for the respective +speedbins according to downstream msm-4.19 kernel: + +* 850 MHz: Speedbins 0 + 180 +* 800 MHz: Speedbins 0 + 180 + 169 +* 650 MHz: Speedbins 0 + 180 + 169 + 138 +* 565 MHz: Speedbins 0 + 180 + 169 + 138 + 120 +* 430 MHz: Speedbins 0 + 180 + 169 + 138 + 120 +* 355 MHz: Speedbins 0 + 180 + 169 + 138 + 120 +* 253 MHz: Speedbins 0 + 180 + 169 + 138 + 120 + +Fixes: bd9b76750280 ("arm64: dts: qcom: sm6350: Add GPU nodes") +Signed-off-by: Luca Weiss +Link: https://lore.kernel.org/r/20241002-sm6350-gpu-speedbin-fix-v1-1-8a5d90c5097d@fairphone.com +Signed-off-by: Bjorn Andersson +Signed-off-by: Sasha Levin +--- + arch/arm64/boot/dts/qcom/sm6350.dtsi | 14 +++++++------- + 1 file changed, 7 insertions(+), 7 deletions(-) + +diff --git a/arch/arm64/boot/dts/qcom/sm6350.dtsi b/arch/arm64/boot/dts/qcom/sm6350.dtsi +index 7986ddb30f6e8..4f8477de7e1b1 100644 +--- a/arch/arm64/boot/dts/qcom/sm6350.dtsi ++++ b/arch/arm64/boot/dts/qcom/sm6350.dtsi +@@ -1376,43 +1376,43 @@ gpu_opp_table: opp-table { + opp-850000000 { + opp-hz = /bits/ 64 <850000000>; + opp-level = ; +- opp-supported-hw = <0x02>; ++ opp-supported-hw = <0x03>; + }; + + opp-800000000 { + opp-hz = /bits/ 64 <800000000>; + opp-level = ; +- opp-supported-hw = <0x04>; ++ opp-supported-hw = <0x07>; + }; + + opp-650000000 { + opp-hz = /bits/ 64 <650000000>; + opp-level = ; +- opp-supported-hw = <0x08>; ++ opp-supported-hw = <0x0f>; + }; + + opp-565000000 { + opp-hz = /bits/ 64 <565000000>; + opp-level = ; +- opp-supported-hw = <0x10>; ++ opp-supported-hw = <0x1f>; + }; + + opp-430000000 { + opp-hz = /bits/ 64 <430000000>; + opp-level = ; +- opp-supported-hw = <0xff>; ++ opp-supported-hw = <0x1f>; + }; + + opp-355000000 { + opp-hz = /bits/ 64 <355000000>; + opp-level = ; +- opp-supported-hw = <0xff>; ++ opp-supported-hw = <0x1f>; + }; + + opp-253000000 { + opp-hz = /bits/ 64 <253000000>; + opp-level = ; +- opp-supported-hw = <0xff>; ++ opp-supported-hw = <0x1f>; + }; + }; + }; +-- +2.43.0 + diff --git a/queue-6.12/arm64-dts-qcom-x1e80100-resize-gic-redistributor-reg.patch b/queue-6.12/arm64-dts-qcom-x1e80100-resize-gic-redistributor-reg.patch new file mode 100644 index 00000000000..4431218095f --- /dev/null +++ b/queue-6.12/arm64-dts-qcom-x1e80100-resize-gic-redistributor-reg.patch @@ -0,0 +1,39 @@ +From 0f284ea704e52c60ca05d48c80737349d3c1a990 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 12 Jun 2024 18:10:54 +0530 +Subject: arm64: dts: qcom: x1e80100: Resize GIC Redistributor register region + +From: Sibi Sankar + +[ Upstream commit 9ed1a2b8784262e85ec300792a1a37ebd8473be2 ] + +Resize the GICR register region as it currently seeps into the CPU Control +Processor mailbox RX region. + +Fixes: af16b00578a7 ("arm64: dts: qcom: Add base X1E80100 dtsi and the QCP dts") +Reviewed-by: Dmitry Baryshkov +Reviewed-by: Konrad Dybcio +Signed-off-by: Sibi Sankar +Link: https://lore.kernel.org/r/20240612124056.39230-4-quic_sibis@quicinc.com +Signed-off-by: Bjorn Andersson +Signed-off-by: Sasha Levin +--- + arch/arm64/boot/dts/qcom/x1e80100.dtsi | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/arch/arm64/boot/dts/qcom/x1e80100.dtsi b/arch/arm64/boot/dts/qcom/x1e80100.dtsi +index 0510abc0edf0f..a073336ca0bed 100644 +--- a/arch/arm64/boot/dts/qcom/x1e80100.dtsi ++++ b/arch/arm64/boot/dts/qcom/x1e80100.dtsi +@@ -5752,7 +5752,7 @@ apps_smmu: iommu@15000000 { + intc: interrupt-controller@17000000 { + compatible = "arm,gic-v3"; + reg = <0 0x17000000 0 0x10000>, /* GICD */ +- <0 0x17080000 0 0x480000>; /* GICR * 12 */ ++ <0 0x17080000 0 0x300000>; /* GICR * 12 */ + + interrupts = ; + +-- +2.43.0 + diff --git a/queue-6.12/arm64-dts-qcom-x1e80100-slim7x-drop-orientation-swit.patch b/queue-6.12/arm64-dts-qcom-x1e80100-slim7x-drop-orientation-swit.patch new file mode 100644 index 00000000000..45ac55e25fc --- /dev/null +++ b/queue-6.12/arm64-dts-qcom-x1e80100-slim7x-drop-orientation-swit.patch @@ -0,0 +1,47 @@ +From 4fe743646fc32b5530d1dfec69f4327569a29c18 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 14 Oct 2024 14:21:48 +0300 +Subject: arm64: dts: qcom: x1e80100-slim7x: Drop orientation-switch from USB + SS[0-1] QMP PHYs + +From: Abel Vesa + +[ Upstream commit eb2dd93d03b16ed0e8b09311f8d35cc5a691a9b7 ] + +The orientation-switch is already set in the x1e80100 SoC dtsi, +so drop from Slim 7X dts. + +Fixes: 45247fe17db2 ("arm64: dts: qcom: x1e80100: add Lenovo Thinkpad Yoga slim 7x devicetree") +Signed-off-by: Abel Vesa +Link: https://lore.kernel.org/r/20241014-x1e80100-dts-drop-orientation-switch-v1-1-26afa6d4afd9@linaro.org +Signed-off-by: Bjorn Andersson +Signed-off-by: Sasha Levin +--- + arch/arm64/boot/dts/qcom/x1e80100-lenovo-yoga-slim7x.dts | 4 ---- + 1 file changed, 4 deletions(-) + +diff --git a/arch/arm64/boot/dts/qcom/x1e80100-lenovo-yoga-slim7x.dts b/arch/arm64/boot/dts/qcom/x1e80100-lenovo-yoga-slim7x.dts +index 0cdaff9c8cf0f..f22e5c840a2e5 100644 +--- a/arch/arm64/boot/dts/qcom/x1e80100-lenovo-yoga-slim7x.dts ++++ b/arch/arm64/boot/dts/qcom/x1e80100-lenovo-yoga-slim7x.dts +@@ -898,8 +898,6 @@ &usb_1_ss0_qmpphy { + vdda-phy-supply = <&vreg_l3e_1p2>; + vdda-pll-supply = <&vreg_l1j_0p8>; + +- orientation-switch; +- + status = "okay"; + }; + +@@ -932,8 +930,6 @@ &usb_1_ss1_qmpphy { + vdda-phy-supply = <&vreg_l3e_1p2>; + vdda-pll-supply = <&vreg_l2d_0p9>; + +- orientation-switch; +- + status = "okay"; + }; + +-- +2.43.0 + diff --git a/queue-6.12/arm64-dts-qcom-x1e80100-update-c4-c5-residency-exit-.patch b/queue-6.12/arm64-dts-qcom-x1e80100-update-c4-c5-residency-exit-.patch new file mode 100644 index 00000000000..29f154faf15 --- /dev/null +++ b/queue-6.12/arm64-dts-qcom-x1e80100-update-c4-c5-residency-exit-.patch @@ -0,0 +1,47 @@ +From 29bc5f21f8ea7938ada6aeb6ccdbdd18442cc783 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 16 Jul 2024 12:35:04 +0200 +Subject: arm64: dts: qcom: x1e80100: Update C4/C5 residency/exit numbers + +From: Konrad Dybcio + +[ Upstream commit 2e65616ef07fa4c72c3898b22e5bede7d468cf32 ] + +Update the numbers based on the information found in the DSDT. + +Fixes: af16b00578a7 ("arm64: dts: qcom: Add base X1E80100 dtsi and the QCP dts") +Signed-off-by: Konrad Dybcio +Link: https://lore.kernel.org/r/20240716-topic-h_bits-v1-2-f6c5d3ff982c@linaro.org +Signed-off-by: Bjorn Andersson +Signed-off-by: Sasha Levin +--- + arch/arm64/boot/dts/qcom/x1e80100.dtsi | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/arch/arm64/boot/dts/qcom/x1e80100.dtsi b/arch/arm64/boot/dts/qcom/x1e80100.dtsi +index a073336ca0bed..914f9cb3aca21 100644 +--- a/arch/arm64/boot/dts/qcom/x1e80100.dtsi ++++ b/arch/arm64/boot/dts/qcom/x1e80100.dtsi +@@ -279,8 +279,8 @@ CLUSTER_C4: cpu-sleep-0 { + idle-state-name = "ret"; + arm,psci-suspend-param = <0x00000004>; + entry-latency-us = <180>; +- exit-latency-us = <320>; +- min-residency-us = <1000>; ++ exit-latency-us = <500>; ++ min-residency-us = <600>; + }; + }; + +@@ -299,7 +299,7 @@ CLUSTER_CL5: cluster-sleep-1 { + idle-state-name = "ret-pll-off"; + arm,psci-suspend-param = <0x01000054>; + entry-latency-us = <2200>; +- exit-latency-us = <2500>; ++ exit-latency-us = <4000>; + min-residency-us = <7000>; + }; + }; +-- +2.43.0 + diff --git a/queue-6.12/arm64-dts-qcom-x1e80100-vivobook-s15-drop-orientatio.patch b/queue-6.12/arm64-dts-qcom-x1e80100-vivobook-s15-drop-orientatio.patch new file mode 100644 index 00000000000..c7861a23000 --- /dev/null +++ b/queue-6.12/arm64-dts-qcom-x1e80100-vivobook-s15-drop-orientatio.patch @@ -0,0 +1,47 @@ +From c99b5653c55173c24ef88df453991810da07c5d8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 14 Oct 2024 14:21:49 +0300 +Subject: arm64: dts: qcom: x1e80100-vivobook-s15: Drop orientation-switch from + USB SS[0-1] QMP PHYs + +From: Abel Vesa + +[ Upstream commit 27344eb70c8fd60fe7c570e2e12f169ff89d2c47 ] + +The orientation-switch is already set in the x1e80100 SoC dtsi, +so drop from Vivobook S15 dts. + +Fixes: d0e2f8f62dff ("arm64: dts: qcom: Add device tree for ASUS Vivobook S 15") +Signed-off-by: Abel Vesa +Link: https://lore.kernel.org/r/20241014-x1e80100-dts-drop-orientation-switch-v1-2-26afa6d4afd9@linaro.org +Signed-off-by: Bjorn Andersson +Signed-off-by: Sasha Levin +--- + arch/arm64/boot/dts/qcom/x1e80100-asus-vivobook-s15.dts | 4 ---- + 1 file changed, 4 deletions(-) + +diff --git a/arch/arm64/boot/dts/qcom/x1e80100-asus-vivobook-s15.dts b/arch/arm64/boot/dts/qcom/x1e80100-asus-vivobook-s15.dts +index fb4a48a1e2a8a..2926a1aba7687 100644 +--- a/arch/arm64/boot/dts/qcom/x1e80100-asus-vivobook-s15.dts ++++ b/arch/arm64/boot/dts/qcom/x1e80100-asus-vivobook-s15.dts +@@ -594,8 +594,6 @@ &usb_1_ss0_qmpphy { + vdda-phy-supply = <&vreg_l3e_1p2>; + vdda-pll-supply = <&vreg_l1j_0p8>; + +- orientation-switch; +- + status = "okay"; + }; + +@@ -628,8 +626,6 @@ &usb_1_ss1_qmpphy { + vdda-phy-supply = <&vreg_l3e_1p2>; + vdda-pll-supply = <&vreg_l2d_0p9>; + +- orientation-switch; +- + status = "okay"; + }; + +-- +2.43.0 + diff --git a/queue-6.12/arm64-dts-renesas-hihope-drop-sound-dai-cells.patch b/queue-6.12/arm64-dts-renesas-hihope-drop-sound-dai-cells.patch new file mode 100644 index 00000000000..e9e2baebca2 --- /dev/null +++ b/queue-6.12/arm64-dts-renesas-hihope-drop-sound-dai-cells.patch @@ -0,0 +1,61 @@ +From 893980336cd4198ca5bc5d36e1e472f5faefc99d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 10 Oct 2024 14:53:31 +0100 +Subject: arm64: dts: renesas: hihope: Drop #sound-dai-cells + +From: Lad Prabhakar + +[ Upstream commit 9cc926e3fab42dd292219796cfc94e41f4ab749d ] + +"#sound-dai-cells" is required if the board is using "simple-card". +However, the HiHope board uses "audio-graph", thus remove the unneeded +`#sound-dai-cells`. + +Commit 9e72606cd2db ("arm64: dts: renesas: #sound-dai-cells is used when +simple-card") updated the comment regarding usage of "#sound-dai-cells" +in the SoC DTSI but missed to remove "#sound-dai-cells" from board DTS +files. + +Fixes: 9e72606cd2db ("arm64: dts: renesas: #sound-dai-cells is used when simple-card") +Signed-off-by: Lad Prabhakar +Reviewed-by: Geert Uytterhoeven +Acked-by: Kuninori Morimoto +Link: https://lore.kernel.org/20241010135332.710648-1-prabhakar.mahadev-lad.rj@bp.renesas.com +Signed-off-by: Geert Uytterhoeven +Signed-off-by: Sasha Levin +--- + arch/arm64/boot/dts/renesas/hihope-rev2.dtsi | 3 --- + arch/arm64/boot/dts/renesas/hihope-rev4.dtsi | 3 --- + 2 files changed, 6 deletions(-) + +diff --git a/arch/arm64/boot/dts/renesas/hihope-rev2.dtsi b/arch/arm64/boot/dts/renesas/hihope-rev2.dtsi +index 8e2db1d6ca81e..25c55b32aafe5 100644 +--- a/arch/arm64/boot/dts/renesas/hihope-rev2.dtsi ++++ b/arch/arm64/boot/dts/renesas/hihope-rev2.dtsi +@@ -69,9 +69,6 @@ &rcar_sound { + + status = "okay"; + +- /* Single DAI */ +- #sound-dai-cells = <0>; +- + rsnd_port: port { + rsnd_endpoint: endpoint { + remote-endpoint = <&dw_hdmi0_snd_in>; +diff --git a/arch/arm64/boot/dts/renesas/hihope-rev4.dtsi b/arch/arm64/boot/dts/renesas/hihope-rev4.dtsi +index 66f3affe04697..deb69c2727756 100644 +--- a/arch/arm64/boot/dts/renesas/hihope-rev4.dtsi ++++ b/arch/arm64/boot/dts/renesas/hihope-rev4.dtsi +@@ -84,9 +84,6 @@ &rcar_sound { + pinctrl-names = "default"; + status = "okay"; + +- /* Single DAI */ +- #sound-dai-cells = <0>; +- + /* audio_clkout0/1/2/3 */ + #clock-cells = <1>; + clock-frequency = <12288000 11289600>; +-- +2.43.0 + diff --git a/queue-6.12/arm64-dts-rockchip-correct-analog-audio-name-on-indi.patch b/queue-6.12/arm64-dts-rockchip-correct-analog-audio-name-on-indi.patch new file mode 100644 index 00000000000..0964baa50c6 --- /dev/null +++ b/queue-6.12/arm64-dts-rockchip-correct-analog-audio-name-on-indi.patch @@ -0,0 +1,39 @@ +From d9a81d090649fc1bc23c98c91b7ea0525122a792 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 31 Oct 2024 10:05:03 -0500 +Subject: arm64: dts: rockchip: correct analog audio name on Indiedroid Nova + +From: Chris Morgan + +[ Upstream commit 42d85557527266804579bc5d20c101d93f6be3c6 ] + +Correct the audio name for the Indiedroid Nova from +rockchip,es8388-codec to rockchip,es8388. This name change corrects a +kernel log error of "ASoC: driver name too long 'rockchip,es8388-codec' +-> 'rockchip_es8388'". + +Fixes: 3900160e164b ("arm64: dts: rockchip: Add Indiedroid Nova board") +Signed-off-by: Chris Morgan +Link: https://lore.kernel.org/r/20241031150505.967909-2-macroalpha82@gmail.com +Signed-off-by: Heiko Stuebner +Signed-off-by: Sasha Levin +--- + arch/arm64/boot/dts/rockchip/rk3588s-indiedroid-nova.dts | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/arch/arm64/boot/dts/rockchip/rk3588s-indiedroid-nova.dts b/arch/arm64/boot/dts/rockchip/rk3588s-indiedroid-nova.dts +index 8ba111d9283fe..d9d2bf822443b 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3588s-indiedroid-nova.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3588s-indiedroid-nova.dts +@@ -62,7 +62,7 @@ sdio_pwrseq: sdio-pwrseq { + + sound { + compatible = "audio-graph-card"; +- label = "rockchip,es8388-codec"; ++ label = "rockchip,es8388"; + widgets = "Microphone", "Mic Jack", + "Headphone", "Headphones"; + routing = "LINPUT2", "Mic Jack", +-- +2.43.0 + diff --git a/queue-6.12/arm64-dts-rockchip-remove-enable-active-low-from-two.patch b/queue-6.12/arm64-dts-rockchip-remove-enable-active-low-from-two.patch new file mode 100644 index 00000000000..4b7c82772c3 --- /dev/null +++ b/queue-6.12/arm64-dts-rockchip-remove-enable-active-low-from-two.patch @@ -0,0 +1,62 @@ +From cdffa54ace62793a4bc487b7e6b0f6aaecaddc28 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 8 Oct 2024 22:39:35 +0200 +Subject: arm64: dts: rockchip: Remove 'enable-active-low' from two boards + +From: Heiko Stuebner + +[ Upstream commit 4a9d7e6596f90631f21bca9cb46c6de05d8e86d4 ] + +The 'enable-active-low' property is not a valid, because it is the +default behaviour of the fixed regulator. + +Only 'enable-active-high' is valid, and when this property is absent +the fixed regulator will act as active low by default. + +Both the rk3588-orange-pi-5 and the Wolfvision pf5 io expander overlay +smuggled those enable-active-low properties in, so remove them to +make dtbscheck happier. + +Fixes: 28799a7734a0 ("arm64: dts: rockchip: add wolfvision pf5 io expander board") +Cc: Michael Riesch +Fixes: b6bc755d806e ("arm64: dts: rockchip: Add Orange Pi 5") +Cc: Muhammed Efe Cetin + +Reviewed-by: Michael Riesch +Reviewed-by: Dragan Simic +Signed-off-by: Heiko Stuebner +Link: https://lore.kernel.org/r/20241008203940.2573684-10-heiko@sntech.de +Signed-off-by: Heiko Stuebner +Signed-off-by: Sasha Levin +--- + .../boot/dts/rockchip/rk3568-wolfvision-pf5-io-expander.dtso | 1 - + arch/arm64/boot/dts/rockchip/rk3588s-orangepi-5.dts | 1 - + 2 files changed, 2 deletions(-) + +diff --git a/arch/arm64/boot/dts/rockchip/rk3568-wolfvision-pf5-io-expander.dtso b/arch/arm64/boot/dts/rockchip/rk3568-wolfvision-pf5-io-expander.dtso +index ebcaeafc3800d..fa61633aea152 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3568-wolfvision-pf5-io-expander.dtso ++++ b/arch/arm64/boot/dts/rockchip/rk3568-wolfvision-pf5-io-expander.dtso +@@ -49,7 +49,6 @@ vcc1v8_eth: vcc1v8-eth-regulator { + + vcc3v3_eth: vcc3v3-eth-regulator { + compatible = "regulator-fixed"; +- enable-active-low; + gpio = <&gpio0 RK_PC0 GPIO_ACTIVE_LOW>; + pinctrl-names = "default"; + pinctrl-0 = <&vcc3v3_eth_enn>; +diff --git a/arch/arm64/boot/dts/rockchip/rk3588s-orangepi-5.dts b/arch/arm64/boot/dts/rockchip/rk3588s-orangepi-5.dts +index feea6b20a6bf5..6b77be6432495 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3588s-orangepi-5.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3588s-orangepi-5.dts +@@ -71,7 +71,6 @@ vcc5v0_sys: vcc5v0-sys-regulator { + + vcc_3v3_sd_s0: vcc-3v3-sd-s0-regulator { + compatible = "regulator-fixed"; +- enable-active-low; + gpios = <&gpio4 RK_PB5 GPIO_ACTIVE_LOW>; + regulator-name = "vcc_3v3_sd_s0"; + regulator-boot-on; +-- +2.43.0 + diff --git a/queue-6.12/arm64-dts-ti-k3-am62x-phyboard-lyra-drop-unnecessary.patch b/queue-6.12/arm64-dts-ti-k3-am62x-phyboard-lyra-drop-unnecessary.patch new file mode 100644 index 00000000000..9674ac1f8dd --- /dev/null +++ b/queue-6.12/arm64-dts-ti-k3-am62x-phyboard-lyra-drop-unnecessary.patch @@ -0,0 +1,38 @@ +From 895e1c8a0947aca4fe888ce23b4e1445b4cac2a8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 2 Oct 2024 15:47:54 -0700 +Subject: arm64: dts: ti: k3-am62x-phyboard-lyra: Drop unnecessary McASP AFIFOs + +From: Nathan Morrisson + +[ Upstream commit c33a0a02a29bde53a85407f86f332ac4bbc5ab87 ] + +Drop the McASP AFIFOs for better audio latency. This adds back a +change that was lost while refactoring the device tree. + +Fixes: 554dd562a5f2 ("arm64: dts: ti: k3-am625-phyboard-lyra-rdk: Drop McASP AFIFOs") +Signed-off-by: Nathan Morrisson +Reviewed-by: Wadim Egorov +Link: https://lore.kernel.org/r/20241002224754.2917895-1-nmorrisson@phytec.com +Signed-off-by: Vignesh Raghavendra +Signed-off-by: Sasha Levin +--- + arch/arm64/boot/dts/ti/k3-am62x-phyboard-lyra.dtsi | 2 -- + 1 file changed, 2 deletions(-) + +diff --git a/arch/arm64/boot/dts/ti/k3-am62x-phyboard-lyra.dtsi b/arch/arm64/boot/dts/ti/k3-am62x-phyboard-lyra.dtsi +index e4633af87eb9c..d6ce53c6d7481 100644 +--- a/arch/arm64/boot/dts/ti/k3-am62x-phyboard-lyra.dtsi ++++ b/arch/arm64/boot/dts/ti/k3-am62x-phyboard-lyra.dtsi +@@ -433,8 +433,6 @@ &mcasp2 { + 0 0 0 0 + 0 0 0 0 + >; +- tx-num-evt = <32>; +- rx-num-evt = <32>; + status = "okay"; + }; + +-- +2.43.0 + diff --git a/queue-6.12/arm64-dts-ti-k3-j7200-fix-clock-ids-for-mcspi-instan.patch b/queue-6.12/arm64-dts-ti-k3-j7200-fix-clock-ids-for-mcspi-instan.patch new file mode 100644 index 00000000000..eb34cb17d89 --- /dev/null +++ b/queue-6.12/arm64-dts-ti-k3-j7200-fix-clock-ids-for-mcspi-instan.patch @@ -0,0 +1,139 @@ +From 59e7984258cf39fbf0f40e9fd402f73a41c9a341 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 23 Oct 2024 16:15:29 +0530 +Subject: arm64: dts: ti: k3-j7200: Fix clock ids for MCSPI instances + +From: Anurag Dutta + +[ Upstream commit 3a47e381670f130870caef6e1155ac531b17b032 ] + +The clock IDs for multiple MCSPI instances across wakeup as +well as main domain in J7200 are incorrect when compared with +documentation [1]. This results in kernel crashes when the said +instances are enabled. Fix the clock ids to their appropriate +values. + +[1]https://software-dl.ti.com/tisci/esd/latest/5_soc_doc/j7200/clocks.html + +Fixes: 8f6c475f4ca7 ("arm64: dts: ti: k3-j7200: Add MCSPI nodes") + +Signed-off-by: Anurag Dutta +Reviewed-by: Aniket Limaye +Link: https://lore.kernel.org/r/20241023104532.3438851-2-a-dutta@ti.com +Signed-off-by: Vignesh Raghavendra +Signed-off-by: Sasha Levin +--- + arch/arm64/boot/dts/ti/k3-j7200-main.dtsi | 16 ++++++++-------- + arch/arm64/boot/dts/ti/k3-j7200-mcu-wakeup.dtsi | 6 +++--- + 2 files changed, 11 insertions(+), 11 deletions(-) + +diff --git a/arch/arm64/boot/dts/ti/k3-j7200-main.dtsi b/arch/arm64/boot/dts/ti/k3-j7200-main.dtsi +index 41adfa64418d0..1d11da926a871 100644 +--- a/arch/arm64/boot/dts/ti/k3-j7200-main.dtsi ++++ b/arch/arm64/boot/dts/ti/k3-j7200-main.dtsi +@@ -1163,7 +1163,7 @@ main_spi0: spi@2100000 { + #address-cells = <1>; + #size-cells = <0>; + power-domains = <&k3_pds 266 TI_SCI_PD_EXCLUSIVE>; +- clocks = <&k3_clks 266 1>; ++ clocks = <&k3_clks 266 4>; + status = "disabled"; + }; + +@@ -1174,7 +1174,7 @@ main_spi1: spi@2110000 { + #address-cells = <1>; + #size-cells = <0>; + power-domains = <&k3_pds 267 TI_SCI_PD_EXCLUSIVE>; +- clocks = <&k3_clks 267 1>; ++ clocks = <&k3_clks 267 4>; + status = "disabled"; + }; + +@@ -1185,7 +1185,7 @@ main_spi2: spi@2120000 { + #address-cells = <1>; + #size-cells = <0>; + power-domains = <&k3_pds 268 TI_SCI_PD_EXCLUSIVE>; +- clocks = <&k3_clks 268 1>; ++ clocks = <&k3_clks 268 4>; + status = "disabled"; + }; + +@@ -1196,7 +1196,7 @@ main_spi3: spi@2130000 { + #address-cells = <1>; + #size-cells = <0>; + power-domains = <&k3_pds 269 TI_SCI_PD_EXCLUSIVE>; +- clocks = <&k3_clks 269 1>; ++ clocks = <&k3_clks 269 4>; + status = "disabled"; + }; + +@@ -1207,7 +1207,7 @@ main_spi4: spi@2140000 { + #address-cells = <1>; + #size-cells = <0>; + power-domains = <&k3_pds 270 TI_SCI_PD_EXCLUSIVE>; +- clocks = <&k3_clks 270 1>; ++ clocks = <&k3_clks 270 2>; + status = "disabled"; + }; + +@@ -1218,7 +1218,7 @@ main_spi5: spi@2150000 { + #address-cells = <1>; + #size-cells = <0>; + power-domains = <&k3_pds 271 TI_SCI_PD_EXCLUSIVE>; +- clocks = <&k3_clks 271 1>; ++ clocks = <&k3_clks 271 4>; + status = "disabled"; + }; + +@@ -1229,7 +1229,7 @@ main_spi6: spi@2160000 { + #address-cells = <1>; + #size-cells = <0>; + power-domains = <&k3_pds 272 TI_SCI_PD_EXCLUSIVE>; +- clocks = <&k3_clks 272 1>; ++ clocks = <&k3_clks 272 4>; + status = "disabled"; + }; + +@@ -1240,7 +1240,7 @@ main_spi7: spi@2170000 { + #address-cells = <1>; + #size-cells = <0>; + power-domains = <&k3_pds 273 TI_SCI_PD_EXCLUSIVE>; +- clocks = <&k3_clks 273 1>; ++ clocks = <&k3_clks 273 4>; + status = "disabled"; + }; + +diff --git a/arch/arm64/boot/dts/ti/k3-j7200-mcu-wakeup.dtsi b/arch/arm64/boot/dts/ti/k3-j7200-mcu-wakeup.dtsi +index 5097d192c2b20..b18b2f2deb969 100644 +--- a/arch/arm64/boot/dts/ti/k3-j7200-mcu-wakeup.dtsi ++++ b/arch/arm64/boot/dts/ti/k3-j7200-mcu-wakeup.dtsi +@@ -494,7 +494,7 @@ mcu_spi0: spi@40300000 { + #address-cells = <1>; + #size-cells = <0>; + power-domains = <&k3_pds 274 TI_SCI_PD_EXCLUSIVE>; +- clocks = <&k3_clks 274 0>; ++ clocks = <&k3_clks 274 4>; + status = "disabled"; + }; + +@@ -505,7 +505,7 @@ mcu_spi1: spi@40310000 { + #address-cells = <1>; + #size-cells = <0>; + power-domains = <&k3_pds 275 TI_SCI_PD_EXCLUSIVE>; +- clocks = <&k3_clks 275 0>; ++ clocks = <&k3_clks 275 4>; + status = "disabled"; + }; + +@@ -516,7 +516,7 @@ mcu_spi2: spi@40320000 { + #address-cells = <1>; + #size-cells = <0>; + power-domains = <&k3_pds 276 TI_SCI_PD_EXCLUSIVE>; +- clocks = <&k3_clks 276 0>; ++ clocks = <&k3_clks 276 2>; + status = "disabled"; + }; + +-- +2.43.0 + diff --git a/queue-6.12/arm64-dts-ti-k3-j7200-fix-register-map-for-main-doma.patch b/queue-6.12/arm64-dts-ti-k3-j7200-fix-register-map-for-main-doma.patch new file mode 100644 index 00000000000..5e75b0a103a --- /dev/null +++ b/queue-6.12/arm64-dts-ti-k3-j7200-fix-register-map-for-main-doma.patch @@ -0,0 +1,100 @@ +From eadd415f24f4e54cf92fc57835eb6f08aab0dc3b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 26 Sep 2024 15:55:33 +0530 +Subject: arm64: dts: ti: k3-j7200: Fix register map for main domain pmx + +From: Jared McArthur + +[ Upstream commit b7af8b4acb3e08c710cd48f098ce8cd07cf43a1e ] + +Commit 0d0a0b441346 ("arm64: dts: ti: k3-j7200: fix main pinmux +range") split the main_pmx0 into two nodes: main_pmx0 and main_pmx1 +due to a non-addressable region, but incorrectly represented the +ranges. As a result, the memory map for the pinctrl is incorrect. Fix +this by introducing the correct ranges. + +The ranges are taken from the J7200 TRM [1] (Table 5-695. CTRL_MMR0 +Registers). + +Padconfig starting addresses and ranges: +- 0 to 66: 0x11c000, 0x10c +- 68: 0x11c110, 0x004 +- 71 to 73: 0x11c11c, 0x00c +- 89 to 90: 0x11c164, 0x008 + +The datasheet [2] doesn't contain PADCONFIG63 (Table 6-106. Pin +Multiplexing), but the pin is necessary for enabling the MMC1 CLKLP +pad loopback and should be included in the pinmux register map. + +Due to the change in pinmux node addresses, change the pinmux node for +the USB0_DRVVBUS pin to main_pmx2. The offset has not changed since the +new main_pmx2 node has the same base address and range as the original +main_pmx1 node. All other pinmuxing done within J7200 dts or dtso files +only uses main_pmx0 which has not changed. + +[1] https://www.ti.com/lit/pdf/spruiu1 +[2] https://www.ti.com/lit/gpn/dra821u + +Fixes: 0d0a0b441346 ("arm64: dts: ti: k3-j7200: fix main pinmux range") +Signed-off-by: Aniket Limaye +Signed-off-by: Jared McArthur +Reviewed-by: Vaishnav Achath +Link: https://lore.kernel.org/r/20240926102533.398139-1-a-limaye@ti.com +Signed-off-by: Vignesh Raghavendra +Signed-off-by: Sasha Levin +--- + .../dts/ti/k3-j7200-common-proc-board.dts | 2 +- + arch/arm64/boot/dts/ti/k3-j7200-main.dtsi | 22 +++++++++++++++++-- + 2 files changed, 21 insertions(+), 3 deletions(-) + +diff --git a/arch/arm64/boot/dts/ti/k3-j7200-common-proc-board.dts b/arch/arm64/boot/dts/ti/k3-j7200-common-proc-board.dts +index 6593c5da82c06..df39f2b1ff6ba 100644 +--- a/arch/arm64/boot/dts/ti/k3-j7200-common-proc-board.dts ++++ b/arch/arm64/boot/dts/ti/k3-j7200-common-proc-board.dts +@@ -254,7 +254,7 @@ J721E_IOPAD(0x38, PIN_OUTPUT, 0) /* (Y21) MCAN3_TX */ + }; + }; + +-&main_pmx1 { ++&main_pmx2 { + main_usbss0_pins_default: main-usbss0-default-pins { + pinctrl-single,pins = < + J721E_IOPAD(0x04, PIN_OUTPUT, 0) /* (T4) USB0_DRVVBUS */ +diff --git a/arch/arm64/boot/dts/ti/k3-j7200-main.dtsi b/arch/arm64/boot/dts/ti/k3-j7200-main.dtsi +index 9386bf3ef9f68..41adfa64418d0 100644 +--- a/arch/arm64/boot/dts/ti/k3-j7200-main.dtsi ++++ b/arch/arm64/boot/dts/ti/k3-j7200-main.dtsi +@@ -426,10 +426,28 @@ main_pmx0: pinctrl@11c000 { + pinctrl-single,function-mask = <0xffffffff>; + }; + +- main_pmx1: pinctrl@11c11c { ++ main_pmx1: pinctrl@11c110 { + compatible = "ti,j7200-padconf", "pinctrl-single"; + /* Proxy 0 addressing */ +- reg = <0x00 0x11c11c 0x00 0xc>; ++ reg = <0x00 0x11c110 0x00 0x004>; ++ #pinctrl-cells = <1>; ++ pinctrl-single,register-width = <32>; ++ pinctrl-single,function-mask = <0xffffffff>; ++ }; ++ ++ main_pmx2: pinctrl@11c11c { ++ compatible = "ti,j7200-padconf", "pinctrl-single"; ++ /* Proxy 0 addressing */ ++ reg = <0x00 0x11c11c 0x00 0x00c>; ++ #pinctrl-cells = <1>; ++ pinctrl-single,register-width = <32>; ++ pinctrl-single,function-mask = <0xffffffff>; ++ }; ++ ++ main_pmx3: pinctrl@11c164 { ++ compatible = "ti,j7200-padconf", "pinctrl-single"; ++ /* Proxy 0 addressing */ ++ reg = <0x00 0x11c164 0x00 0x008>; + #pinctrl-cells = <1>; + pinctrl-single,register-width = <32>; + pinctrl-single,function-mask = <0xffffffff>; +-- +2.43.0 + diff --git a/queue-6.12/arm64-dts-ti-k3-j721e-fix-clock-ids-for-mcspi-instan.patch b/queue-6.12/arm64-dts-ti-k3-j721e-fix-clock-ids-for-mcspi-instan.patch new file mode 100644 index 00000000000..f8c0b59d669 --- /dev/null +++ b/queue-6.12/arm64-dts-ti-k3-j721e-fix-clock-ids-for-mcspi-instan.patch @@ -0,0 +1,59 @@ +From 820eecd28008287cf299127269575f54eac84c66 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 23 Oct 2024 16:15:30 +0530 +Subject: arm64: dts: ti: k3-j721e: Fix clock IDs for MCSPI instances + +From: Anurag Dutta + +[ Upstream commit ab09a68f3be04b2f9d1fc7cfc0e2225025cb9421 ] + +The clock IDs for multiple MCSPI instances across wakeup domain +in J721e are incorrect when compared with documentation [1]. Fix +the clock ids to their appropriate values. + +[1]https://software-dl.ti.com/tisci/esd/latest/5_soc_doc/j721e/clocks.html + +Fixes: 76aa309f9fa7 ("arm64: dts: ti: k3-j721e: Add MCSPI nodes") + +Signed-off-by: Anurag Dutta +Link: https://lore.kernel.org/r/20241023104532.3438851-3-a-dutta@ti.com +Signed-off-by: Vignesh Raghavendra +Signed-off-by: Sasha Levin +--- + arch/arm64/boot/dts/ti/k3-j721e-mcu-wakeup.dtsi | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/arch/arm64/boot/dts/ti/k3-j721e-mcu-wakeup.dtsi b/arch/arm64/boot/dts/ti/k3-j721e-mcu-wakeup.dtsi +index 3731ffb4a5c96..6f5c1401ebd6a 100644 +--- a/arch/arm64/boot/dts/ti/k3-j721e-mcu-wakeup.dtsi ++++ b/arch/arm64/boot/dts/ti/k3-j721e-mcu-wakeup.dtsi +@@ -654,7 +654,7 @@ mcu_spi0: spi@40300000 { + #address-cells = <1>; + #size-cells = <0>; + power-domains = <&k3_pds 274 TI_SCI_PD_EXCLUSIVE>; +- clocks = <&k3_clks 274 0>; ++ clocks = <&k3_clks 274 1>; + status = "disabled"; + }; + +@@ -665,7 +665,7 @@ mcu_spi1: spi@40310000 { + #address-cells = <1>; + #size-cells = <0>; + power-domains = <&k3_pds 275 TI_SCI_PD_EXCLUSIVE>; +- clocks = <&k3_clks 275 0>; ++ clocks = <&k3_clks 275 1>; + status = "disabled"; + }; + +@@ -676,7 +676,7 @@ mcu_spi2: spi@40320000 { + #address-cells = <1>; + #size-cells = <0>; + power-domains = <&k3_pds 276 TI_SCI_PD_EXCLUSIVE>; +- clocks = <&k3_clks 276 0>; ++ clocks = <&k3_clks 276 1>; + status = "disabled"; + }; + +-- +2.43.0 + diff --git a/queue-6.12/arm64-dts-ti-k3-j721s2-fix-clock-ids-for-mcspi-insta.patch b/queue-6.12/arm64-dts-ti-k3-j721s2-fix-clock-ids-for-mcspi-insta.patch new file mode 100644 index 00000000000..bc7793e9458 --- /dev/null +++ b/queue-6.12/arm64-dts-ti-k3-j721s2-fix-clock-ids-for-mcspi-insta.patch @@ -0,0 +1,136 @@ +From 4fca2a7a83edd78111233eccff4f515bb71a92ed Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 23 Oct 2024 16:15:31 +0530 +Subject: arm64: dts: ti: k3-j721s2: Fix clock IDs for MCSPI instances + +From: Anurag Dutta + +[ Upstream commit 891874f015e98f67ab2fda76f2e859921e136621 ] + +The clock IDs for multiple MCSPI instances across wakeup domain +in J721s2 are incorrect when compared with documentation [1]. Fix the +clock IDs to their appropriate values. + +[1]https://software-dl.ti.com/tisci/esd/latest/5_soc_doc/j721s2/clocks.html + +Fixes: 04d7cb647b85 ("arm64: dts: ti: k3-j721s2: Add MCSPI nodes") + +Signed-off-by: Anurag Dutta +Link: https://lore.kernel.org/r/20241023104532.3438851-4-a-dutta@ti.com +Signed-off-by: Vignesh Raghavendra +Signed-off-by: Sasha Levin +--- + arch/arm64/boot/dts/ti/k3-j721s2-main.dtsi | 16 ++++++++-------- + arch/arm64/boot/dts/ti/k3-j721s2-mcu-wakeup.dtsi | 6 +++--- + 2 files changed, 11 insertions(+), 11 deletions(-) + +diff --git a/arch/arm64/boot/dts/ti/k3-j721s2-main.dtsi b/arch/arm64/boot/dts/ti/k3-j721s2-main.dtsi +index 9ed6949b40e9d..fae534b5c8a43 100644 +--- a/arch/arm64/boot/dts/ti/k3-j721s2-main.dtsi ++++ b/arch/arm64/boot/dts/ti/k3-j721s2-main.dtsi +@@ -1708,7 +1708,7 @@ main_spi0: spi@2100000 { + #address-cells = <1>; + #size-cells = <0>; + power-domains = <&k3_pds 339 TI_SCI_PD_EXCLUSIVE>; +- clocks = <&k3_clks 339 1>; ++ clocks = <&k3_clks 339 2>; + status = "disabled"; + }; + +@@ -1719,7 +1719,7 @@ main_spi1: spi@2110000 { + #address-cells = <1>; + #size-cells = <0>; + power-domains = <&k3_pds 340 TI_SCI_PD_EXCLUSIVE>; +- clocks = <&k3_clks 340 1>; ++ clocks = <&k3_clks 340 2>; + status = "disabled"; + }; + +@@ -1730,7 +1730,7 @@ main_spi2: spi@2120000 { + #address-cells = <1>; + #size-cells = <0>; + power-domains = <&k3_pds 341 TI_SCI_PD_EXCLUSIVE>; +- clocks = <&k3_clks 341 1>; ++ clocks = <&k3_clks 341 2>; + status = "disabled"; + }; + +@@ -1741,7 +1741,7 @@ main_spi3: spi@2130000 { + #address-cells = <1>; + #size-cells = <0>; + power-domains = <&k3_pds 342 TI_SCI_PD_EXCLUSIVE>; +- clocks = <&k3_clks 342 1>; ++ clocks = <&k3_clks 342 2>; + status = "disabled"; + }; + +@@ -1752,7 +1752,7 @@ main_spi4: spi@2140000 { + #address-cells = <1>; + #size-cells = <0>; + power-domains = <&k3_pds 343 TI_SCI_PD_EXCLUSIVE>; +- clocks = <&k3_clks 343 1>; ++ clocks = <&k3_clks 343 2>; + status = "disabled"; + }; + +@@ -1763,7 +1763,7 @@ main_spi5: spi@2150000 { + #address-cells = <1>; + #size-cells = <0>; + power-domains = <&k3_pds 344 TI_SCI_PD_EXCLUSIVE>; +- clocks = <&k3_clks 344 1>; ++ clocks = <&k3_clks 344 2>; + status = "disabled"; + }; + +@@ -1774,7 +1774,7 @@ main_spi6: spi@2160000 { + #address-cells = <1>; + #size-cells = <0>; + power-domains = <&k3_pds 345 TI_SCI_PD_EXCLUSIVE>; +- clocks = <&k3_clks 345 1>; ++ clocks = <&k3_clks 345 2>; + status = "disabled"; + }; + +@@ -1785,7 +1785,7 @@ main_spi7: spi@2170000 { + #address-cells = <1>; + #size-cells = <0>; + power-domains = <&k3_pds 346 TI_SCI_PD_EXCLUSIVE>; +- clocks = <&k3_clks 346 1>; ++ clocks = <&k3_clks 346 2>; + status = "disabled"; + }; + +diff --git a/arch/arm64/boot/dts/ti/k3-j721s2-mcu-wakeup.dtsi b/arch/arm64/boot/dts/ti/k3-j721s2-mcu-wakeup.dtsi +index 9d96b19d0e7cf..8232d308c23cc 100644 +--- a/arch/arm64/boot/dts/ti/k3-j721s2-mcu-wakeup.dtsi ++++ b/arch/arm64/boot/dts/ti/k3-j721s2-mcu-wakeup.dtsi +@@ -425,7 +425,7 @@ mcu_spi0: spi@40300000 { + #address-cells = <1>; + #size-cells = <0>; + power-domains = <&k3_pds 347 TI_SCI_PD_EXCLUSIVE>; +- clocks = <&k3_clks 347 0>; ++ clocks = <&k3_clks 347 2>; + status = "disabled"; + }; + +@@ -436,7 +436,7 @@ mcu_spi1: spi@40310000 { + #address-cells = <1>; + #size-cells = <0>; + power-domains = <&k3_pds 348 TI_SCI_PD_EXCLUSIVE>; +- clocks = <&k3_clks 348 0>; ++ clocks = <&k3_clks 348 2>; + status = "disabled"; + }; + +@@ -447,7 +447,7 @@ mcu_spi2: spi@40320000 { + #address-cells = <1>; + #size-cells = <0>; + power-domains = <&k3_pds 349 TI_SCI_PD_EXCLUSIVE>; +- clocks = <&k3_clks 349 0>; ++ clocks = <&k3_clks 349 2>; + status = "disabled"; + }; + +-- +2.43.0 + diff --git a/queue-6.12/arm64-expose-id_aa64isar1_el1.xs-to-sanitised-featur.patch b/queue-6.12/arm64-expose-id_aa64isar1_el1.xs-to-sanitised-featur.patch new file mode 100644 index 00000000000..8cb905d7a34 --- /dev/null +++ b/queue-6.12/arm64-expose-id_aa64isar1_el1.xs-to-sanitised-featur.patch @@ -0,0 +1,40 @@ +From e32b0d815b7b4c09b95263c43bd9b9c2aa1c427d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 31 Oct 2024 08:35:19 +0000 +Subject: arm64: Expose ID_AA64ISAR1_EL1.XS to sanitised feature consumers + +From: Marc Zyngier + +[ Upstream commit 2287a4c1e11822d05a70d22f28b26bd810dd204e ] + +Despite KVM now being able to deal with XS-tagged TLBIs, we still don't +expose these feature bits to KVM. + +Plumb in the feature in ID_AA64ISAR1_EL1. + +Fixes: 0feec7769a63 ("KVM: arm64: nv: Add handling of NXS-flavoured TLBI operations") +Signed-off-by: Marc Zyngier +Acked-by: Catalin Marinas +Reviewed-by: Oliver Upton +Link: https://lore.kernel.org/r/20241031083519.364313-1-maz@kernel.org +Signed-off-by: Catalin Marinas +Signed-off-by: Sasha Levin +--- + arch/arm64/kernel/cpufeature.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c +index 718728a85430f..db994d1fd97e7 100644 +--- a/arch/arm64/kernel/cpufeature.c ++++ b/arch/arm64/kernel/cpufeature.c +@@ -228,6 +228,7 @@ static const struct arm64_ftr_bits ftr_id_aa64isar0[] = { + }; + + static const struct arm64_ftr_bits ftr_id_aa64isar1[] = { ++ ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64ISAR1_EL1_XS_SHIFT, 4, 0), + ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64ISAR1_EL1_I8MM_SHIFT, 4, 0), + ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64ISAR1_EL1_DGH_SHIFT, 4, 0), + ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64ISAR1_EL1_BF16_SHIFT, 4, 0), +-- +2.43.0 + diff --git a/queue-6.12/arm64-fix-.data.rel.ro-size-assertion-when-config_lt.patch b/queue-6.12/arm64-fix-.data.rel.ro-size-assertion-when-config_lt.patch new file mode 100644 index 00000000000..6dede5d968e --- /dev/null +++ b/queue-6.12/arm64-fix-.data.rel.ro-size-assertion-when-config_lt.patch @@ -0,0 +1,56 @@ +From 2b1355982e0840a24d7a1b10ff156140e0c3e416 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 7 Nov 2024 01:18:42 +0900 +Subject: arm64: fix .data.rel.ro size assertion when CONFIG_LTO_CLANG + +From: Masahiro Yamada + +[ Upstream commit 340fd66c856651d8c1d29f392dd26ad674d2db0e ] + +Commit be2881824ae9 ("arm64/build: Assert for unwanted sections") +introduced an assertion to ensure that the .data.rel.ro section does +not exist. + +However, this check does not work when CONFIG_LTO_CLANG is enabled, +because .data.rel.ro matches the .data.[0-9a-zA-Z_]* pattern in the +DATA_MAIN macro. + +Move the ASSERT() above the RW_DATA() line. + +Fixes: be2881824ae9 ("arm64/build: Assert for unwanted sections") +Signed-off-by: Masahiro Yamada +Acked-by: Will Deacon +Link: https://lore.kernel.org/r/20241106161843.189927-1-masahiroy@kernel.org +Signed-off-by: Catalin Marinas +Signed-off-by: Sasha Levin +--- + arch/arm64/kernel/vmlinux.lds.S | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/arch/arm64/kernel/vmlinux.lds.S b/arch/arm64/kernel/vmlinux.lds.S +index 58d89d997d050..f84c71f04d9ea 100644 +--- a/arch/arm64/kernel/vmlinux.lds.S ++++ b/arch/arm64/kernel/vmlinux.lds.S +@@ -287,6 +287,9 @@ SECTIONS + __initdata_end = .; + __init_end = .; + ++ .data.rel.ro : { *(.data.rel.ro) } ++ ASSERT(SIZEOF(.data.rel.ro) == 0, "Unexpected RELRO detected!") ++ + _data = .; + _sdata = .; + RW_DATA(L1_CACHE_BYTES, PAGE_SIZE, THREAD_ALIGN) +@@ -343,9 +346,6 @@ SECTIONS + *(.plt) *(.plt.*) *(.iplt) *(.igot .igot.plt) + } + ASSERT(SIZEOF(.plt) == 0, "Unexpected run-time procedure linkages detected!") +- +- .data.rel.ro : { *(.data.rel.ro) } +- ASSERT(SIZEOF(.data.rel.ro) == 0, "Unexpected RELRO detected!") + } + + #include "image-vars.h" +-- +2.43.0 + diff --git a/queue-6.12/arm64-probes-disable-kprobes-uprobes-on-mops-instruc.patch b/queue-6.12/arm64-probes-disable-kprobes-uprobes-on-mops-instruc.patch new file mode 100644 index 00000000000..7a91eeceb53 --- /dev/null +++ b/queue-6.12/arm64-probes-disable-kprobes-uprobes-on-mops-instruc.patch @@ -0,0 +1,60 @@ +From efc5f648d41bc288976ccb0d710eae6d98eee6e1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 30 Sep 2024 17:10:47 +0100 +Subject: arm64: probes: Disable kprobes/uprobes on MOPS instructions + +From: Kristina Martsenko + +[ Upstream commit c56c599d9002d44f559be3852b371db46adac87c ] + +FEAT_MOPS instructions require that all three instructions (prologue, +main and epilogue) appear consecutively in memory. Placing a +kprobe/uprobe on one of them doesn't work as only a single instruction +gets executed out-of-line or simulated. So don't allow placing a probe +on a MOPS instruction. + +Fixes: b7564127ffcb ("arm64: mops: detect and enable FEAT_MOPS") +Signed-off-by: Kristina Martsenko +Link: https://lore.kernel.org/r/20240930161051.3777828-2-kristina.martsenko@arm.com +Signed-off-by: Catalin Marinas +Signed-off-by: Sasha Levin +--- + arch/arm64/include/asm/insn.h | 1 + + arch/arm64/kernel/probes/decode-insn.c | 7 +++++-- + 2 files changed, 6 insertions(+), 2 deletions(-) + +diff --git a/arch/arm64/include/asm/insn.h b/arch/arm64/include/asm/insn.h +index 8c0a36f72d6fc..bc77869dbd43b 100644 +--- a/arch/arm64/include/asm/insn.h ++++ b/arch/arm64/include/asm/insn.h +@@ -353,6 +353,7 @@ __AARCH64_INSN_FUNCS(ldrsw_lit, 0xFF000000, 0x98000000) + __AARCH64_INSN_FUNCS(exclusive, 0x3F800000, 0x08000000) + __AARCH64_INSN_FUNCS(load_ex, 0x3F400000, 0x08400000) + __AARCH64_INSN_FUNCS(store_ex, 0x3F400000, 0x08000000) ++__AARCH64_INSN_FUNCS(mops, 0x3B200C00, 0x19000400) + __AARCH64_INSN_FUNCS(stp, 0x7FC00000, 0x29000000) + __AARCH64_INSN_FUNCS(ldp, 0x7FC00000, 0x29400000) + __AARCH64_INSN_FUNCS(stp_post, 0x7FC00000, 0x28800000) +diff --git a/arch/arm64/kernel/probes/decode-insn.c b/arch/arm64/kernel/probes/decode-insn.c +index 3496d6169e59b..42b69936cee34 100644 +--- a/arch/arm64/kernel/probes/decode-insn.c ++++ b/arch/arm64/kernel/probes/decode-insn.c +@@ -58,10 +58,13 @@ static bool __kprobes aarch64_insn_is_steppable(u32 insn) + * Instructions which load PC relative literals are not going to work + * when executed from an XOL slot. Instructions doing an exclusive + * load/store are not going to complete successfully when single-step +- * exception handling happens in the middle of the sequence. ++ * exception handling happens in the middle of the sequence. Memory ++ * copy/set instructions require that all three instructions be placed ++ * consecutively in memory. + */ + if (aarch64_insn_uses_literal(insn) || +- aarch64_insn_is_exclusive(insn)) ++ aarch64_insn_is_exclusive(insn) || ++ aarch64_insn_is_mops(insn)) + return false; + + return true; +-- +2.43.0 + diff --git a/queue-6.12/arm64-tegra-p2180-add-mandatory-compatible-for-wifi-.patch b/queue-6.12/arm64-tegra-p2180-add-mandatory-compatible-for-wifi-.patch new file mode 100644 index 00000000000..6c9f9b39671 --- /dev/null +++ b/queue-6.12/arm64-tegra-p2180-add-mandatory-compatible-for-wifi-.patch @@ -0,0 +1,38 @@ +From b20f6fb3c1b281f6338613833fdb0faa9dfeab20 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 3 Sep 2024 15:21:48 +0200 +Subject: arm64: tegra: p2180: Add mandatory compatible for WiFi node + +From: Tomasz Maciej Nowak + +[ Upstream commit 2e57d3dc7bff60b9fb05eaaf4ebad87cd3651068 ] + +The dtschema requires to specify common ancestor which all SDIO chips are +derived from, so add accordingly. + +Fixes: a50d5dcd2815 ("arm64: tegra: Wire up WiFi on Jetson TX1 module") +Reported-by: kernel test robot +Closes: https://lore.kernel.org/oe-kbuild-all/202409030438.8tumAnp1-lkp@intel.com +Signed-off-by: Tomasz Maciej Nowak +Signed-off-by: Thierry Reding +Signed-off-by: Sasha Levin +--- + arch/arm64/boot/dts/nvidia/tegra210-p2180.dtsi | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/arch/arm64/boot/dts/nvidia/tegra210-p2180.dtsi b/arch/arm64/boot/dts/nvidia/tegra210-p2180.dtsi +index c00db75e39105..1c53ccc5e3cbf 100644 +--- a/arch/arm64/boot/dts/nvidia/tegra210-p2180.dtsi ++++ b/arch/arm64/boot/dts/nvidia/tegra210-p2180.dtsi +@@ -351,7 +351,7 @@ mmc@700b0200 { + #size-cells = <0>; + + wifi@1 { +- compatible = "brcm,bcm4354-fmac"; ++ compatible = "brcm,bcm4354-fmac", "brcm,bcm4329-fmac"; + reg = <1>; + interrupt-parent = <&gpio>; + interrupts = ; +-- +2.43.0 + diff --git a/queue-6.12/asoc-amd-acp-fix-for-cpu-dai-index-logic.patch b/queue-6.12/asoc-amd-acp-fix-for-cpu-dai-index-logic.patch new file mode 100644 index 00000000000..5c42fa168c7 --- /dev/null +++ b/queue-6.12/asoc-amd-acp-fix-for-cpu-dai-index-logic.patch @@ -0,0 +1,67 @@ +From c442fc23dc1310313bcefe6ac80d4bb4cf73bc7c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 7 Oct 2024 14:23:20 +0530 +Subject: ASoC: amd: acp: fix for cpu dai index logic + +From: Vijendar Mukunda + +[ Upstream commit 7ce8e4d380d68f34edc96c7efcf95b1476e7f033 ] + +Multi link aggregation is not supported for acp6.3 platform. +Below combinations are supported. +- one sdw BE DAI <---> one-cpu DAI <---> one-codec DAI +- one sdw BE DAI <---> one-cpu DAI <---> multi-codec DAIs +As Single cpu dai is going to be created, In create_sdw_dailink() function +cpu dai index won't be incremented. +Refactor cpu dai index logic to fix below smatch static checker warning. +sound/soc/amd/acp/acp-sdw-sof-mach.c:157 create_sdw_dailink() +warn: iterator 'i' not incremented. + +Reported-by: Dan Carpenter +Closes: https://lore.kernel.org/all/a201e871-375e-43eb-960d-5c048956c2ff@amd.com/T/ +Fixes: 6d8348ddc56e ("ASoC: amd: acp: refactor SoundWire machine driver code") +Signed-off-by: Vijendar Mukunda +Link: https://patch.msgid.link/20241007085321.3991149-3-Vijendar.Mukunda@amd.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/amd/acp/acp-sdw-sof-mach.c | 14 +++++++------- + 1 file changed, 7 insertions(+), 7 deletions(-) + +diff --git a/sound/soc/amd/acp/acp-sdw-sof-mach.c b/sound/soc/amd/acp/acp-sdw-sof-mach.c +index acab2675d1f5c..3be401c722704 100644 +--- a/sound/soc/amd/acp/acp-sdw-sof-mach.c ++++ b/sound/soc/amd/acp/acp-sdw-sof-mach.c +@@ -154,7 +154,7 @@ static int create_sdw_dailink(struct snd_soc_card *card, + int num_cpus = hweight32(sof_dai->link_mask[stream]); + int num_codecs = sof_dai->num_devs[stream]; + int playback, capture; +- int i = 0, j = 0; ++ int j = 0; + char *name; + + if (!sof_dai->num_devs[stream]) +@@ -213,14 +213,14 @@ static int create_sdw_dailink(struct snd_soc_card *card, + + int link_num = ffs(sof_end->link_mask) - 1; + +- cpus[i].dai_name = devm_kasprintf(dev, GFP_KERNEL, +- "SDW%d Pin%d", +- link_num, cpu_pin_id); +- dev_dbg(dev, "cpu[%d].dai_name:%s\n", i, cpus[i].dai_name); +- if (!cpus[i].dai_name) ++ cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL, ++ "SDW%d Pin%d", ++ link_num, cpu_pin_id); ++ dev_dbg(dev, "cpu->dai_name:%s\n", cpus->dai_name); ++ if (!cpus->dai_name) + return -ENOMEM; + +- codec_maps[j].cpu = i; ++ codec_maps[j].cpu = 0; + codec_maps[j].codec = j; + + codecs[j].name = sof_end->codec_name; +-- +2.43.0 + diff --git a/queue-6.12/asoc-amd-acp-fix-for-inconsistent-indenting.patch b/queue-6.12/asoc-amd-acp-fix-for-inconsistent-indenting.patch new file mode 100644 index 00000000000..e238e07dd0d --- /dev/null +++ b/queue-6.12/asoc-amd-acp-fix-for-inconsistent-indenting.patch @@ -0,0 +1,41 @@ +From 1eba4f4b6c12453d04ab80b183e158e345eed3d6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 7 Oct 2024 14:23:19 +0530 +Subject: ASoC: amd: acp: fix for inconsistent indenting + +From: Vijendar Mukunda + +[ Upstream commit 914219d74931211e719907e0eed03d8133f8b1b7 ] + +Fix below Smatch static checker warning: + +sound/soc/amd/acp/acp-sdw-sof-mach.c:365 sof_card_dai_links_create() +warn: inconsistent indenting + +Reported-by: Dan Carpenter +Closes: https://lore.kernel.org/all/a201e871-375e-43eb-960d-5c048956c2ff@amd.com/T/ +Fixes: 6d8348ddc56e ("ASoC: amd: acp: refactor SoundWire machine driver code") +Signed-off-by: Vijendar Mukunda +Link: https://patch.msgid.link/20241007085321.3991149-2-Vijendar.Mukunda@amd.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/amd/acp/acp-sdw-sof-mach.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/sound/soc/amd/acp/acp-sdw-sof-mach.c b/sound/soc/amd/acp/acp-sdw-sof-mach.c +index 306854fb08e3d..acab2675d1f5c 100644 +--- a/sound/soc/amd/acp/acp-sdw-sof-mach.c ++++ b/sound/soc/amd/acp/acp-sdw-sof-mach.c +@@ -362,7 +362,7 @@ static int sof_card_dai_links_create(struct snd_soc_card *card) + dai_links = devm_kcalloc(dev, num_links, sizeof(*dai_links), GFP_KERNEL); + if (!dai_links) { + ret = -ENOMEM; +- goto err_end; ++ goto err_end; + } + + card->codec_conf = codec_conf; +-- +2.43.0 + diff --git a/queue-6.12/asoc-amd-yc-fix-for-enabling-dmic-on-acp6x-via-_dsd-.patch b/queue-6.12/asoc-amd-yc-fix-for-enabling-dmic-on-acp6x-via-_dsd-.patch new file mode 100644 index 00000000000..9a77481539b --- /dev/null +++ b/queue-6.12/asoc-amd-yc-fix-for-enabling-dmic-on-acp6x-via-_dsd-.patch @@ -0,0 +1,65 @@ +From a2897db3462099526183483fceaaecebd8d9e93b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 27 Nov 2024 16:52:25 +0530 +Subject: ASoC: amd: yc: Fix for enabling DMIC on acp6x via _DSD entry + +From: Venkata Prasad Potturu + +[ Upstream commit 4095cf872084ecfdfdb0e681f3e9ff9745acfa75 ] + +Add condition check to register ACP PDM sound card by reading +_WOV acpi entry. + +Fixes: 5426f506b584 ("ASoC: amd: Add support for enabling DMIC on acp6x via _DSD") + +Signed-off-by: Venkata Prasad Potturu +Link: https://patch.msgid.link/20241127112227.227106-1-venkataprasad.potturu@amd.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/amd/yc/acp6x-mach.c | 18 +++++++++++++++++- + 1 file changed, 17 insertions(+), 1 deletion(-) + +diff --git a/sound/soc/amd/yc/acp6x-mach.c b/sound/soc/amd/yc/acp6x-mach.c +index 2436e8deb2be4..639e7136ef2a7 100644 +--- a/sound/soc/amd/yc/acp6x-mach.c ++++ b/sound/soc/amd/yc/acp6x-mach.c +@@ -537,8 +537,14 @@ static int acp6x_probe(struct platform_device *pdev) + struct acp6x_pdm *machine = NULL; + struct snd_soc_card *card; + struct acpi_device *adev; ++ acpi_handle handle; ++ acpi_integer dmic_status; + int ret; ++ bool is_dmic_enable, wov_en; + ++ /* IF WOV entry not found, enable dmic based on AcpDmicConnected entry*/ ++ is_dmic_enable = false; ++ wov_en = true; + /* check the parent device's firmware node has _DSD or not */ + adev = ACPI_COMPANION(pdev->dev.parent); + if (adev) { +@@ -546,9 +552,19 @@ static int acp6x_probe(struct platform_device *pdev) + + if (!acpi_dev_get_property(adev, "AcpDmicConnected", ACPI_TYPE_INTEGER, &obj) && + obj->integer.value == 1) +- platform_set_drvdata(pdev, &acp6x_card); ++ is_dmic_enable = true; + } + ++ handle = ACPI_HANDLE(pdev->dev.parent); ++ ret = acpi_evaluate_integer(handle, "_WOV", NULL, &dmic_status); ++ if (!ACPI_FAILURE(ret)) ++ wov_en = dmic_status; ++ ++ if (is_dmic_enable && wov_en) ++ platform_set_drvdata(pdev, &acp6x_card); ++ else ++ return 0; ++ + /* check for any DMI overrides */ + dmi_id = dmi_first_match(yc_acp_quirk_table); + if (dmi_id) +-- +2.43.0 + diff --git a/queue-6.12/asoc-dt-bindings-mt6359-update-generic-node-name-and.patch b/queue-6.12/asoc-dt-bindings-mt6359-update-generic-node-name-and.patch new file mode 100644 index 00000000000..eb4be8e4c84 --- /dev/null +++ b/queue-6.12/asoc-dt-bindings-mt6359-update-generic-node-name-and.patch @@ -0,0 +1,77 @@ +From 17cb20c98cf6d12fd073ed02b6dd29828daa4eb3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 30 Sep 2024 15:54:50 +0800 +Subject: ASoC: dt-bindings: mt6359: Update generic node name and dmic-mode + +From: Macpaul Lin + +[ Upstream commit 4649cbd97fdae5069e9a71cd7669b62b90e03669 ] + +Some fix and updates in the following items: +1. examples: + Update generic node name to 'audio-codec' to comply with the + coming change in 'mt6359.dtsi'. This change is necessary to fix the + dtbs_check error: + pmic: 'mt6359codec' does not match any of the regexes: 'pinctrl-[0-9]+' + +2. mediatek,dmic-mode: + After inspecting the .dts and .dtsi files using 'mt6359-codec', it was + discovered that the definitions of 'two wires' and 'one wire' are + inverted compared to the DT schema. + For example, the following boards using MT6359 PMIC: + - mt8192-asurada.dtsi + - mt8195-cherry.dtsi + These boards use the same definitions of 'dmic-mode' as other boards + using MT6358 PMIC. The meaning of '0' or '1' has been noted as comments + in the device trees. + + Upon examining the code in [1] and [2], it was confirmed that the + definitions of 'dmic-mode' are consistent between "MT6359 PMIC" and + "MT6358 PMIC". Therefore, the DT Schema should be correct as is. + +References: +[1] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/sound/soc/codecs/mt6358.c#n1875 +[2] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/sound/soc/codecs/mt6359.c#L1515 + +Fixes: 539237d1c609 ("dt-bindings: mediatek: mt6359: add codec document") +Signed-off-by: Jiaxin Yu +Signed-off-by: Macpaul Lin +Reviewed-by: AngeloGioacchino Del Regno +Link: https://patch.msgid.link/20240930075451.14196-1-macpaul.lin@mediatek.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + Documentation/devicetree/bindings/sound/mt6359.yaml | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +diff --git a/Documentation/devicetree/bindings/sound/mt6359.yaml b/Documentation/devicetree/bindings/sound/mt6359.yaml +index 23d411fc4200e..128698630c865 100644 +--- a/Documentation/devicetree/bindings/sound/mt6359.yaml ++++ b/Documentation/devicetree/bindings/sound/mt6359.yaml +@@ -23,8 +23,8 @@ properties: + Indicates how many data pins are used to transmit two channels of PDM + signal. 0 means two wires, 1 means one wire. Default value is 0. + enum: +- - 0 # one wire +- - 1 # two wires ++ - 0 # two wires ++ - 1 # one wire + + mediatek,mic-type-0: + $ref: /schemas/types.yaml#/definitions/uint32 +@@ -53,9 +53,9 @@ additionalProperties: false + + examples: + - | +- mt6359codec: mt6359codec { +- mediatek,dmic-mode = <0>; +- mediatek,mic-type-0 = <2>; ++ mt6359codec: audio-codec { ++ mediatek,dmic-mode = <0>; ++ mediatek,mic-type-0 = <2>; + }; + + ... +-- +2.43.0 + diff --git a/queue-6.12/asoc-fsl-asoc-card-add-missing-handling-of-hp-mic-dt.patch b/queue-6.12/asoc-fsl-asoc-card-add-missing-handling-of-hp-mic-dt.patch new file mode 100644 index 00000000000..573e39cd1cd --- /dev/null +++ b/queue-6.12/asoc-fsl-asoc-card-add-missing-handling-of-hp-mic-dt.patch @@ -0,0 +1,63 @@ +From 6753b3b5ec8b3b16121703f7a265854cef15b44d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 27 Sep 2024 14:42:16 +0200 +Subject: ASoC: fsl-asoc-card: Add missing handling of {hp,mic}-dt-gpios + +From: Geert Uytterhoeven + +[ Upstream commit cfd1054c65eefec30972416a83eb62920bc1ff8d ] + +The DT bindings deprecated the "hp-det-gpio" and "mic-det-gpio" +properties in favor of "hp-det-gpios" and "mic-det-gpios", but the +driver was never updated to support the latter. + +Even before, there existed users of "hp-det-gpios" and "mic-det-gpios". +While this may have been handled fine by the ASoC core, this was missed +by the Freescale-specific part. + +Fixes: 4189b54220e5af15 ("ASoC: dt-bindings: fsl-asoc-card: convert to YAML") +Fixes: 40ba2eda0a7b727f ("arm64: dts: imx8mm-nitrogen-r2: add audio") +Signed-off-by: Geert Uytterhoeven +Reviewed-by: Krzysztof Kozlowski +Link: https://patch.msgid.link/dbcb5bfea005a468ec6dc38374fe6d02bc693c22.1727438777.git.geert+renesas@glider.be +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/fsl/fsl-asoc-card.c | 8 +++++--- + 1 file changed, 5 insertions(+), 3 deletions(-) + +diff --git a/sound/soc/fsl/fsl-asoc-card.c b/sound/soc/fsl/fsl-asoc-card.c +index f6c3aeff0d8ea..a0c2ce84c32b1 100644 +--- a/sound/soc/fsl/fsl-asoc-card.c ++++ b/sound/soc/fsl/fsl-asoc-card.c +@@ -1033,14 +1033,15 @@ static int fsl_asoc_card_probe(struct platform_device *pdev) + } + + /* +- * Properties "hp-det-gpio" and "mic-det-gpio" are optional, and ++ * Properties "hp-det-gpios" and "mic-det-gpios" are optional, and + * simple_util_init_jack() uses these properties for creating + * Headphone Jack and Microphone Jack. + * + * The notifier is initialized in snd_soc_card_jack_new(), then + * snd_soc_jack_notifier_register can be called. + */ +- if (of_property_read_bool(np, "hp-det-gpio")) { ++ if (of_property_read_bool(np, "hp-det-gpios") || ++ of_property_read_bool(np, "hp-det-gpio") /* deprecated */) { + ret = simple_util_init_jack(&priv->card, &priv->hp_jack, + 1, NULL, "Headphone Jack"); + if (ret) +@@ -1049,7 +1050,8 @@ static int fsl_asoc_card_probe(struct platform_device *pdev) + snd_soc_jack_notifier_register(&priv->hp_jack.jack, &hp_jack_nb); + } + +- if (of_property_read_bool(np, "mic-det-gpio")) { ++ if (of_property_read_bool(np, "mic-det-gpios") || ++ of_property_read_bool(np, "mic-det-gpio") /* deprecated */) { + ret = simple_util_init_jack(&priv->card, &priv->mic_jack, + 0, NULL, "Mic Jack"); + if (ret) +-- +2.43.0 + diff --git a/queue-6.12/asoc-fsl_micfil-fix-regmap_write_bits-usage.patch b/queue-6.12/asoc-fsl_micfil-fix-regmap_write_bits-usage.patch new file mode 100644 index 00000000000..b9c4a0184ca --- /dev/null +++ b/queue-6.12/asoc-fsl_micfil-fix-regmap_write_bits-usage.patch @@ -0,0 +1,47 @@ +From ac3c13f23f4601486699f18e969ecc8411df3551 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 27 Sep 2024 16:00:29 +0800 +Subject: ASoC: fsl_micfil: fix regmap_write_bits usage + +From: Shengjiu Wang + +[ Upstream commit 06df673d20230afb0e383e39235a4fa8b9a62464 ] + +The last parameter 1 means BIT(0), which should be the +correct BIT(X). + +Fixes: 47a70e6fc9a8 ("ASoC: Add MICFIL SoC Digital Audio Interface driver.") +Signed-off-by: Shengjiu Wang +Reviewed-by: Daniel Baluta +Link: https://patch.msgid.link/1727424031-19551-2-git-send-email-shengjiu.wang@nxp.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/fsl/fsl_micfil.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/sound/soc/fsl/fsl_micfil.c b/sound/soc/fsl/fsl_micfil.c +index 0c71a73476dfa..67c2d4cb0dea2 100644 +--- a/sound/soc/fsl/fsl_micfil.c ++++ b/sound/soc/fsl/fsl_micfil.c +@@ -1061,7 +1061,7 @@ static irqreturn_t micfil_isr(int irq, void *devid) + regmap_write_bits(micfil->regmap, + REG_MICFIL_STAT, + MICFIL_STAT_CHXF(i), +- 1); ++ MICFIL_STAT_CHXF(i)); + } + + for (i = 0; i < MICFIL_FIFO_NUM; i++) { +@@ -1096,7 +1096,7 @@ static irqreturn_t micfil_err_isr(int irq, void *devid) + if (stat_reg & MICFIL_STAT_LOWFREQF) { + dev_dbg(&pdev->dev, "isr: ipg_clk_app is too low\n"); + regmap_write_bits(micfil->regmap, REG_MICFIL_STAT, +- MICFIL_STAT_LOWFREQF, 1); ++ MICFIL_STAT_LOWFREQF, MICFIL_STAT_LOWFREQF); + } + + return IRQ_HANDLED; +-- +2.43.0 + diff --git a/queue-6.12/asoc-imx-audmix-add-null-check-in-imx_audmix_probe.patch b/queue-6.12/asoc-imx-audmix-add-null-check-in-imx_audmix_probe.patch new file mode 100644 index 00000000000..73b0869004f --- /dev/null +++ b/queue-6.12/asoc-imx-audmix-add-null-check-in-imx_audmix_probe.patch @@ -0,0 +1,40 @@ +From bdc3094c3147f1ef2ca5d2a333c1cd9ddf516cf6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 18 Nov 2024 16:45:53 +0800 +Subject: ASoC: imx-audmix: Add NULL check in imx_audmix_probe + +From: Charles Han + +[ Upstream commit e038f43edaf0083f6aa7c9415d86cf28dfd152f9 ] + +devm_kasprintf() can return a NULL pointer on failure,but this +returned value in imx_audmix_probe() is not checked. +Add NULL check in imx_audmix_probe(), to handle kernel NULL +pointer dereference error. + +Fixes: 05d996e11348 ("ASoC: imx-audmix: Split capture device for audmix") +Signed-off-by: Charles Han +Link: https://patch.msgid.link/20241118084553.4195-1-hanchunchao@inspur.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/fsl/imx-audmix.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/sound/soc/fsl/imx-audmix.c b/sound/soc/fsl/imx-audmix.c +index 6fbcf33fd0dea..8e7b75cf64db4 100644 +--- a/sound/soc/fsl/imx-audmix.c ++++ b/sound/soc/fsl/imx-audmix.c +@@ -275,6 +275,9 @@ static int imx_audmix_probe(struct platform_device *pdev) + /* Add AUDMIX Backend */ + be_name = devm_kasprintf(&pdev->dev, GFP_KERNEL, + "audmix-%d", i); ++ if (!be_name) ++ return -ENOMEM; ++ + priv->dai[num_dai + i].cpus = &dlc[1]; + priv->dai[num_dai + i].codecs = &snd_soc_dummy_dlc; + +-- +2.43.0 + diff --git a/queue-6.12/asoc-mediatek-check-num_codecs-is-not-zero-to-avoid-.patch b/queue-6.12/asoc-mediatek-check-num_codecs-is-not-zero-to-avoid-.patch new file mode 100644 index 00000000000..21464f6bb35 --- /dev/null +++ b/queue-6.12/asoc-mediatek-check-num_codecs-is-not-zero-to-avoid-.patch @@ -0,0 +1,140 @@ +From 007334ef5b0cdb2b2849b15a1218573a21beaeb5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 26 Nov 2024 15:09:43 -0500 +Subject: ASoC: mediatek: Check num_codecs is not zero to avoid panic during + probe +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Nícolas F. R. A. Prado + +[ Upstream commit 2f2020327cc8561d7c520d2f2d9acea84fa7b3a3 ] + +Following commit 13f58267cda3 ("ASoC: soc.h: don't create dummy +Component via COMP_DUMMY()"), COMP_DUMMY() became an array with zero +length, and only gets populated with the dummy struct after the card is +registered. Since the sound card driver's probe happens before the card +registration, accessing any of the members of a dummy component during +probe will result in undefined behavior. + +This can be observed in the mt8188 and mt8195 machine sound drivers. By +omitting a dai link subnode in the sound card's node in the Devicetree, +the default uninitialized dummy codec is used, and when its dai_name +pointer gets passed to strcmp() it results in a null pointer dereference +and a kernel panic. + +In addition to that, set_card_codec_info() in the generic helpers file, +mtk-soundcard-driver.c, will populate a dai link with a dummy codec when +a dai link node is present in DT but with no codec property. + +The result is that at probe time, a dummy codec can either be +uninitialized with num_codecs = 0, or be an initialized dummy codec, +with num_codecs = 1 and dai_name = "snd-soc-dummy-dai". In order to +accommodate for both situations, check that num_codecs is not zero +before accessing the codecs' fields but still check for the codec's dai +name against "snd-soc-dummy-dai" as needed. + +While at it, also drop the check that dai_name is not null in the mt8192 +driver, introduced in commit 4d4e1b6319e5 ("ASoC: mediatek: mt8192: +Check existence of dai_name before dereferencing"), as it is actually +redundant given the preceding num_codecs != 0 check. + +Fixes: 13f58267cda3 ("ASoC: soc.h: don't create dummy Component via COMP_DUMMY()") +Signed-off-by: Nícolas F. R. A. Prado +Reviewed-by: AngeloGioacchino Del Regno +Acked-by: Kuninori Morimoto +Reviewed-by: Fei Shao +Acked-by: Trevor Wu +Link: https://patch.msgid.link/20241126-asoc-mtk-dummy-panic-v1-1-42d53e168d2e@collabora.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/mediatek/mt8188/mt8188-mt6359.c | 9 +++++++-- + sound/soc/mediatek/mt8192/mt8192-mt6359-rt1015-rt5682.c | 4 ++-- + sound/soc/mediatek/mt8195/mt8195-mt6359.c | 9 +++++++-- + 3 files changed, 16 insertions(+), 6 deletions(-) + +diff --git a/sound/soc/mediatek/mt8188/mt8188-mt6359.c b/sound/soc/mediatek/mt8188/mt8188-mt6359.c +index 08ae962afeb92..4eed90d13a532 100644 +--- a/sound/soc/mediatek/mt8188/mt8188-mt6359.c ++++ b/sound/soc/mediatek/mt8188/mt8188-mt6359.c +@@ -1279,10 +1279,12 @@ static int mt8188_mt6359_soc_card_probe(struct mtk_soc_card_data *soc_card_data, + + for_each_card_prelinks(card, i, dai_link) { + if (strcmp(dai_link->name, "DPTX_BE") == 0) { +- if (strcmp(dai_link->codecs->dai_name, "snd-soc-dummy-dai")) ++ if (dai_link->num_codecs && ++ strcmp(dai_link->codecs->dai_name, "snd-soc-dummy-dai")) + dai_link->init = mt8188_dptx_codec_init; + } else if (strcmp(dai_link->name, "ETDM3_OUT_BE") == 0) { +- if (strcmp(dai_link->codecs->dai_name, "snd-soc-dummy-dai")) ++ if (dai_link->num_codecs && ++ strcmp(dai_link->codecs->dai_name, "snd-soc-dummy-dai")) + dai_link->init = mt8188_hdmi_codec_init; + } else if (strcmp(dai_link->name, "DL_SRC_BE") == 0 || + strcmp(dai_link->name, "UL_SRC_BE") == 0) { +@@ -1294,6 +1296,9 @@ static int mt8188_mt6359_soc_card_probe(struct mtk_soc_card_data *soc_card_data, + strcmp(dai_link->name, "ETDM2_OUT_BE") == 0 || + strcmp(dai_link->name, "ETDM1_IN_BE") == 0 || + strcmp(dai_link->name, "ETDM2_IN_BE") == 0) { ++ if (!dai_link->num_codecs) ++ continue; ++ + if (!strcmp(dai_link->codecs->dai_name, MAX98390_CODEC_DAI)) { + /* + * The TDM protocol settings with fixed 4 slots are defined in +diff --git a/sound/soc/mediatek/mt8192/mt8192-mt6359-rt1015-rt5682.c b/sound/soc/mediatek/mt8192/mt8192-mt6359-rt1015-rt5682.c +index db00704e206d6..943f811684037 100644 +--- a/sound/soc/mediatek/mt8192/mt8192-mt6359-rt1015-rt5682.c ++++ b/sound/soc/mediatek/mt8192/mt8192-mt6359-rt1015-rt5682.c +@@ -1099,7 +1099,7 @@ static int mt8192_mt6359_legacy_probe(struct mtk_soc_card_data *soc_card_data) + dai_link->ignore = 0; + } + +- if (dai_link->num_codecs && dai_link->codecs[0].dai_name && ++ if (dai_link->num_codecs && + strcmp(dai_link->codecs[0].dai_name, RT1015_CODEC_DAI) == 0) + dai_link->ops = &mt8192_rt1015_i2s_ops; + } +@@ -1127,7 +1127,7 @@ static int mt8192_mt6359_soc_card_probe(struct mtk_soc_card_data *soc_card_data, + int i; + + for_each_card_prelinks(card, i, dai_link) +- if (dai_link->num_codecs && dai_link->codecs[0].dai_name && ++ if (dai_link->num_codecs && + strcmp(dai_link->codecs[0].dai_name, RT1015_CODEC_DAI) == 0) + dai_link->ops = &mt8192_rt1015_i2s_ops; + } +diff --git a/sound/soc/mediatek/mt8195/mt8195-mt6359.c b/sound/soc/mediatek/mt8195/mt8195-mt6359.c +index 2832ef78eaed7..8ebf6c7502aa3 100644 +--- a/sound/soc/mediatek/mt8195/mt8195-mt6359.c ++++ b/sound/soc/mediatek/mt8195/mt8195-mt6359.c +@@ -1380,10 +1380,12 @@ static int mt8195_mt6359_soc_card_probe(struct mtk_soc_card_data *soc_card_data, + + for_each_card_prelinks(card, i, dai_link) { + if (strcmp(dai_link->name, "DPTX_BE") == 0) { +- if (strcmp(dai_link->codecs->dai_name, "snd-soc-dummy-dai")) ++ if (dai_link->num_codecs && ++ strcmp(dai_link->codecs->dai_name, "snd-soc-dummy-dai")) + dai_link->init = mt8195_dptx_codec_init; + } else if (strcmp(dai_link->name, "ETDM3_OUT_BE") == 0) { +- if (strcmp(dai_link->codecs->dai_name, "snd-soc-dummy-dai")) ++ if (dai_link->num_codecs && ++ strcmp(dai_link->codecs->dai_name, "snd-soc-dummy-dai")) + dai_link->init = mt8195_hdmi_codec_init; + } else if (strcmp(dai_link->name, "DL_SRC_BE") == 0 || + strcmp(dai_link->name, "UL_SRC1_BE") == 0 || +@@ -1396,6 +1398,9 @@ static int mt8195_mt6359_soc_card_probe(struct mtk_soc_card_data *soc_card_data, + strcmp(dai_link->name, "ETDM2_OUT_BE") == 0 || + strcmp(dai_link->name, "ETDM1_IN_BE") == 0 || + strcmp(dai_link->name, "ETDM2_IN_BE") == 0) { ++ if (!dai_link->num_codecs) ++ continue; ++ + if (!strcmp(dai_link->codecs->dai_name, MAX98390_CODEC_DAI)) { + if (!(codec_init & MAX98390_CODEC_INIT)) { + dai_link->init = mt8195_max98390_init; +-- +2.43.0 + diff --git a/queue-6.12/asoc-rt722-sdca-remove-logically-deadcode-in-rt722-s.patch b/queue-6.12/asoc-rt722-sdca-remove-logically-deadcode-in-rt722-s.patch new file mode 100644 index 00000000000..70084aed7e9 --- /dev/null +++ b/queue-6.12/asoc-rt722-sdca-remove-logically-deadcode-in-rt722-s.patch @@ -0,0 +1,47 @@ +From e9e55f7fdec6073a8858482cb123d538a6991a62 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 10 Oct 2024 11:57:54 -0600 +Subject: ASoC: rt722-sdca: Remove logically deadcode in rt722-sdca.c + +From: Everest K.C + +[ Upstream commit 22206e569fb54bf9c95db9a0138a7485ba9e13bc ] + +As the same condition was checked in inner and outer if statements. +The code never reaches the inner else statement. +Fix this by removing the logically dead inner else statement. + +Fixes: 7f5d6036ca00 ("ASoC: rt722-sdca: Add RT722 SDCA driver") +Reported-by: Shuah Khan +Closes: https://lore.kernel.org/all/e44527e8-b7c6-4712-97a6-d54f02ad2dc9@linuxfoundation.org/ +Signed-off-by: Everest K.C. +Reviewed-by: Shuah Khan +Link: https://patch.msgid.link/20241010175755.5278-1-everestkc@everestkc.com.np +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/codecs/rt722-sdca.c | 8 ++------ + 1 file changed, 2 insertions(+), 6 deletions(-) + +diff --git a/sound/soc/codecs/rt722-sdca.c b/sound/soc/codecs/rt722-sdca.c +index e5bd9ef812de1..f9f7512ca3608 100644 +--- a/sound/soc/codecs/rt722-sdca.c ++++ b/sound/soc/codecs/rt722-sdca.c +@@ -607,12 +607,8 @@ static int rt722_sdca_dmic_set_gain_get(struct snd_kcontrol *kcontrol, + + if (!adc_vol_flag) /* boost gain */ + ctl = regvalue / boost_step; +- else { /* ADC gain */ +- if (adc_vol_flag) +- ctl = p->max - (((vol_max - regvalue) & 0xffff) / interval_offset); +- else +- ctl = p->max - (((0 - regvalue) & 0xffff) / interval_offset); +- } ++ else /* ADC gain */ ++ ctl = p->max - (((vol_max - regvalue) & 0xffff) / interval_offset); + + ucontrol->value.integer.value[i] = ctl; + } +-- +2.43.0 + diff --git a/queue-6.12/block-fix-bio_split_rw_at-to-take-zone_write_granula.patch b/queue-6.12/block-fix-bio_split_rw_at-to-take-zone_write_granula.patch new file mode 100644 index 00000000000..3915a9100ea --- /dev/null +++ b/queue-6.12/block-fix-bio_split_rw_at-to-take-zone_write_granula.patch @@ -0,0 +1,54 @@ +From a0837d31d0087c66cdf0f78a29f51150f79472c9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 4 Nov 2024 07:26:30 +0100 +Subject: block: fix bio_split_rw_at to take zone_write_granularity into + account + +From: Christoph Hellwig + +[ Upstream commit 7ecd2cd4fae3e8410c0a6620f3a83dcdbb254f02 ] + +Otherwise it can create unaligned writes on zoned devices. + +Fixes: a805a4fa4fa3 ("block: introduce zone_write_granularity limit") +Signed-off-by: Christoph Hellwig +Reviewed-by: Damien Le Moal +Reviewed-by: Johannes Thumshirn +Link: https://lore.kernel.org/r/20241104062647.91160-3-hch@lst.de +Signed-off-by: Jens Axboe +Signed-off-by: Sasha Levin +--- + block/blk-merge.c | 10 +++++++++- + 1 file changed, 9 insertions(+), 1 deletion(-) + +diff --git a/block/blk-merge.c b/block/blk-merge.c +index 75d2461b69e40..5baa950f34fe2 100644 +--- a/block/blk-merge.c ++++ b/block/blk-merge.c +@@ -287,6 +287,14 @@ static bool bvec_split_segs(const struct queue_limits *lim, + return len > 0 || bv->bv_len > max_len; + } + ++static unsigned int bio_split_alignment(struct bio *bio, ++ const struct queue_limits *lim) ++{ ++ if (op_is_write(bio_op(bio)) && lim->zone_write_granularity) ++ return lim->zone_write_granularity; ++ return lim->logical_block_size; ++} ++ + /** + * bio_split_rw_at - check if and where to split a read/write bio + * @bio: [in] bio to be split +@@ -349,7 +357,7 @@ int bio_split_rw_at(struct bio *bio, const struct queue_limits *lim, + * split size so that each bio is properly block size aligned, even if + * we do not use the full hardware limits. + */ +- bytes = ALIGN_DOWN(bytes, lim->logical_block_size); ++ bytes = ALIGN_DOWN(bytes, bio_split_alignment(bio, lim)); + + /* + * Bio splitting may cause subtle trouble such as hang when doing sync +-- +2.43.0 + diff --git a/queue-6.12/block-fs-pass-an-iocb-to-generic_atomic_write_valid.patch b/queue-6.12/block-fs-pass-an-iocb-to-generic_atomic_write_valid.patch new file mode 100644 index 00000000000..1ada533d4fb --- /dev/null +++ b/queue-6.12/block-fs-pass-an-iocb-to-generic_atomic_write_valid.patch @@ -0,0 +1,100 @@ +From 2746438377ee02d0fc68ad77fd86f43839de966e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 19 Oct 2024 12:51:06 +0000 +Subject: block/fs: Pass an iocb to generic_atomic_write_valid() + +From: John Garry + +[ Upstream commit 9a8dbdadae509e5717ff6e5aa572ca0974d2101d ] + +Darrick and Hannes both thought it better that generic_atomic_write_valid() +should be passed a struct iocb, and not just the member of that struct +which is referenced; see [0] and [1]. + +I think that makes a more generic and clean API, so make that change. + +[0] https://lore.kernel.org/linux-block/680ce641-729b-4150-b875-531a98657682@suse.de/ +[1] https://lore.kernel.org/linux-xfs/20240620212401.GA3058325@frogsfrogsfrogs/ + +Fixes: c34fc6f26ab8 ("fs: Initial atomic write support") +Suggested-by: Darrick J. Wong +Suggested-by: Hannes Reinecke +Reviewed-by: Darrick J. Wong +Reviewed-by: Christoph Hellwig +Signed-off-by: John Garry +Link: https://lore.kernel.org/r/20241019125113.369994-2-john.g.garry@oracle.com +Signed-off-by: Jens Axboe +Signed-off-by: Sasha Levin +--- + block/fops.c | 8 ++++---- + fs/read_write.c | 4 ++-- + include/linux/fs.h | 2 +- + 3 files changed, 7 insertions(+), 7 deletions(-) + +diff --git a/block/fops.c b/block/fops.c +index e696ae53bf1e0..968b47b615c4b 100644 +--- a/block/fops.c ++++ b/block/fops.c +@@ -35,13 +35,13 @@ static blk_opf_t dio_bio_write_op(struct kiocb *iocb) + return opf; + } + +-static bool blkdev_dio_invalid(struct block_device *bdev, loff_t pos, ++static bool blkdev_dio_invalid(struct block_device *bdev, struct kiocb *iocb, + struct iov_iter *iter, bool is_atomic) + { +- if (is_atomic && !generic_atomic_write_valid(iter, pos)) ++ if (is_atomic && !generic_atomic_write_valid(iocb, iter)) + return true; + +- return pos & (bdev_logical_block_size(bdev) - 1) || ++ return iocb->ki_pos & (bdev_logical_block_size(bdev) - 1) || + !bdev_iter_is_aligned(bdev, iter); + } + +@@ -374,7 +374,7 @@ static ssize_t blkdev_direct_IO(struct kiocb *iocb, struct iov_iter *iter) + if (!iov_iter_count(iter)) + return 0; + +- if (blkdev_dio_invalid(bdev, iocb->ki_pos, iter, is_atomic)) ++ if (blkdev_dio_invalid(bdev, iocb, iter, is_atomic)) + return -EINVAL; + + nr_pages = bio_iov_vecs_to_alloc(iter, BIO_MAX_VECS + 1); +diff --git a/fs/read_write.c b/fs/read_write.c +index 64dc24afdb3a7..2c32635308281 100644 +--- a/fs/read_write.c ++++ b/fs/read_write.c +@@ -1830,7 +1830,7 @@ int generic_file_rw_checks(struct file *file_in, struct file *file_out) + return 0; + } + +-bool generic_atomic_write_valid(struct iov_iter *iter, loff_t pos) ++bool generic_atomic_write_valid(struct kiocb *iocb, struct iov_iter *iter) + { + size_t len = iov_iter_count(iter); + +@@ -1840,7 +1840,7 @@ bool generic_atomic_write_valid(struct iov_iter *iter, loff_t pos) + if (!is_power_of_2(len)) + return false; + +- if (!IS_ALIGNED(pos, len)) ++ if (!IS_ALIGNED(iocb->ki_pos, len)) + return false; + + return true; +diff --git a/include/linux/fs.h b/include/linux/fs.h +index 3559446279c15..faf7596ace971 100644 +--- a/include/linux/fs.h ++++ b/include/linux/fs.h +@@ -3726,6 +3726,6 @@ static inline bool vfs_empty_path(int dfd, const char __user *path) + return !c; + } + +-bool generic_atomic_write_valid(struct iov_iter *iter, loff_t pos); ++bool generic_atomic_write_valid(struct kiocb *iocb, struct iov_iter *iter); + + #endif /* _LINUX_FS_H */ +-- +2.43.0 + diff --git a/queue-6.12/block-take-chunk_sectors-into-account-in-bio_split_w.patch b/queue-6.12/block-take-chunk_sectors-into-account-in-bio_split_w.patch new file mode 100644 index 00000000000..7e8379a4320 --- /dev/null +++ b/queue-6.12/block-take-chunk_sectors-into-account-in-bio_split_w.patch @@ -0,0 +1,90 @@ +From e9fc6ae5b0584341d34ca44de105d3b1d323d9a3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 4 Nov 2024 07:26:29 +0100 +Subject: block: take chunk_sectors into account in bio_split_write_zeroes + +From: Christoph Hellwig + +[ Upstream commit 60dc5ea6bcfd078b71419640d49afa649acf9450 ] + +For zoned devices, write zeroes must be split at the zone boundary +which is represented as chunk_sectors. For other uses like the +internally RAIDed NVMe devices it is probably at least useful. + +Enhance get_max_io_size to know about write zeroes and use it in +bio_split_write_zeroes. Also add a comment about the seemingly +nonsensical zero max_write_zeroes limit. + +Fixes: 885fa13f6559 ("block: implement splitting of REQ_OP_WRITE_ZEROES bios") +Signed-off-by: Christoph Hellwig +Reviewed-by: Damien Le Moal +Link: https://lore.kernel.org/r/20241104062647.91160-2-hch@lst.de +Signed-off-by: Jens Axboe +Signed-off-by: Sasha Levin +--- + block/blk-merge.c | 35 +++++++++++++++++++++++------------ + 1 file changed, 23 insertions(+), 12 deletions(-) + +diff --git a/block/blk-merge.c b/block/blk-merge.c +index ad763ec313b6a..75d2461b69e40 100644 +--- a/block/blk-merge.c ++++ b/block/blk-merge.c +@@ -166,17 +166,6 @@ struct bio *bio_split_discard(struct bio *bio, const struct queue_limits *lim, + return bio_submit_split(bio, split_sectors); + } + +-struct bio *bio_split_write_zeroes(struct bio *bio, +- const struct queue_limits *lim, unsigned *nsegs) +-{ +- *nsegs = 0; +- if (!lim->max_write_zeroes_sectors) +- return bio; +- if (bio_sectors(bio) <= lim->max_write_zeroes_sectors) +- return bio; +- return bio_submit_split(bio, lim->max_write_zeroes_sectors); +-} +- + static inline unsigned int blk_boundary_sectors(const struct queue_limits *lim, + bool is_atomic) + { +@@ -211,7 +200,9 @@ static inline unsigned get_max_io_size(struct bio *bio, + * We ignore lim->max_sectors for atomic writes because it may less + * than the actual bio size, which we cannot tolerate. + */ +- if (is_atomic) ++ if (bio_op(bio) == REQ_OP_WRITE_ZEROES) ++ max_sectors = lim->max_write_zeroes_sectors; ++ else if (is_atomic) + max_sectors = lim->atomic_write_max_sectors; + else + max_sectors = lim->max_sectors; +@@ -398,6 +389,26 @@ struct bio *bio_split_zone_append(struct bio *bio, + return bio_submit_split(bio, split_sectors); + } + ++struct bio *bio_split_write_zeroes(struct bio *bio, ++ const struct queue_limits *lim, unsigned *nsegs) ++{ ++ unsigned int max_sectors = get_max_io_size(bio, lim); ++ ++ *nsegs = 0; ++ ++ /* ++ * An unset limit should normally not happen, as bio submission is keyed ++ * off having a non-zero limit. But SCSI can clear the limit in the ++ * I/O completion handler, and we can race and see this. Splitting to a ++ * zero limit obviously doesn't make sense, so band-aid it here. ++ */ ++ if (!max_sectors) ++ return bio; ++ if (bio_sectors(bio) <= max_sectors) ++ return bio; ++ return bio_submit_split(bio, max_sectors); ++} ++ + /** + * bio_split_to_limits - split a bio to fit the queue limits + * @bio: bio to be split +-- +2.43.0 + diff --git a/queue-6.12/bluetooth-btbcm-fix-missing-of_node_put-in-btbcm_get.patch b/queue-6.12/bluetooth-btbcm-fix-missing-of_node_put-in-btbcm_get.patch new file mode 100644 index 00000000000..e593e1ef96f --- /dev/null +++ b/queue-6.12/bluetooth-btbcm-fix-missing-of_node_put-in-btbcm_get.patch @@ -0,0 +1,56 @@ +From 8d29ed68bfe3f3e92192cc0de874a04de2a33127 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 31 Oct 2024 13:11:23 +0100 +Subject: Bluetooth: btbcm: fix missing of_node_put() in btbcm_get_board_name() + +From: Javier Carrasco + +[ Upstream commit e42eec0f182ac0605e658145f6fe3b6a7c256c45 ] + +of_find_node_by_path() returns a pointer to a device_node with its +refcount incremented, and a call to of_node_put() is required to +decrement the refcount again and avoid leaking the resource. + +If 'of_property_read_string_index(root, "compatible", 0, &tmp)' fails, +the function returns without calling of_node_put(root) before doing so. + +The automatic cleanup attribute can be used by means of the __free() +macro to automatically call of_node_put() when the variable goes out of +scope, fixing the issue and also accounting for new error paths. + +Fixes: 63fac3343b99 ("Bluetooth: btbcm: Support per-board firmware variants") +Signed-off-by: Javier Carrasco +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + drivers/bluetooth/btbcm.c | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +diff --git a/drivers/bluetooth/btbcm.c b/drivers/bluetooth/btbcm.c +index eef00467905eb..a1153ada74d20 100644 +--- a/drivers/bluetooth/btbcm.c ++++ b/drivers/bluetooth/btbcm.c +@@ -541,11 +541,10 @@ static const struct bcm_subver_table bcm_usb_subver_table[] = { + static const char *btbcm_get_board_name(struct device *dev) + { + #ifdef CONFIG_OF +- struct device_node *root; ++ struct device_node *root __free(device_node) = of_find_node_by_path("/"); + char *board_type; + const char *tmp; + +- root = of_find_node_by_path("/"); + if (!root) + return NULL; + +@@ -555,7 +554,6 @@ static const char *btbcm_get_board_name(struct device *dev) + /* get rid of any '/' in the compatible string */ + board_type = devm_kstrdup(dev, tmp, GFP_KERNEL); + strreplace(board_type, '/', '-'); +- of_node_put(root); + + return board_type; + #else +-- +2.43.0 + diff --git a/queue-6.12/bluetooth-btintel-do-no-pass-vendor-events-to-stack.patch b/queue-6.12/bluetooth-btintel-do-no-pass-vendor-events-to-stack.patch new file mode 100644 index 00000000000..c00bee1ae2a --- /dev/null +++ b/queue-6.12/bluetooth-btintel-do-no-pass-vendor-events-to-stack.patch @@ -0,0 +1,86 @@ +From 2378e20a65637ba65a5046d4d7ffb8bfab095fd1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 17 Oct 2024 17:21:56 +0530 +Subject: Bluetooth: btintel: Do no pass vendor events to stack + +From: Kiran K + +[ Upstream commit 510e8380b0382ee3b070748656b00f83c9a5bf80 ] + +During firmware download, vendor specific events like boot up and +secure send result are generated. These events can be safely processed at +the driver level. Passing on these events to stack prints unnecessary +log as below. + + Bluetooth: hci0: Malformed MSFT vendor event: 0x02 + +Fixes: 3368aa357f3b ("Bluetooth: msft: Handle MSFT Monitor Device Event") +Signed-off-by: Kiran K +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + drivers/bluetooth/btintel.c | 6 ++++-- + drivers/bluetooth/btintel_pcie.c | 9 ++++++--- + 2 files changed, 10 insertions(+), 5 deletions(-) + +diff --git a/drivers/bluetooth/btintel.c b/drivers/bluetooth/btintel.c +index 4b17202075b00..645047fb92fd2 100644 +--- a/drivers/bluetooth/btintel.c ++++ b/drivers/bluetooth/btintel.c +@@ -3368,7 +3368,8 @@ int btintel_recv_event(struct hci_dev *hdev, struct sk_buff *skb) + * indicating that the bootup completed. + */ + btintel_bootup(hdev, ptr, len); +- break; ++ kfree_skb(skb); ++ return 0; + case 0x06: + /* When the firmware loading completes the + * device sends out a vendor specific event +@@ -3376,7 +3377,8 @@ int btintel_recv_event(struct hci_dev *hdev, struct sk_buff *skb) + * loading. + */ + btintel_secure_send_result(hdev, ptr, len); +- break; ++ kfree_skb(skb); ++ return 0; + } + } + +diff --git a/drivers/bluetooth/btintel_pcie.c b/drivers/bluetooth/btintel_pcie.c +index 16ee962d40861..8bd663f4bac1b 100644 +--- a/drivers/bluetooth/btintel_pcie.c ++++ b/drivers/bluetooth/btintel_pcie.c +@@ -536,7 +536,8 @@ static int btintel_pcie_recv_event(struct hci_dev *hdev, struct sk_buff *skb) + if (btintel_pcie_in_op(data)) { + btintel_pcie_wr_sleep_cntrl(data, BTINTEL_PCIE_STATE_D0); + data->alive_intr_ctxt = BTINTEL_PCIE_INTEL_HCI_RESET2; +- break; ++ kfree_skb(skb); ++ return 0; + } + + if (btintel_pcie_in_iml(data)) { +@@ -553,7 +554,8 @@ static int btintel_pcie_recv_event(struct hci_dev *hdev, struct sk_buff *skb) + btintel_wake_up_flag(data->hdev, + INTEL_WAIT_FOR_D0); + } +- break; ++ kfree_skb(skb); ++ return 0; + case 0x06: + /* When the firmware loading completes the + * device sends out a vendor specific event +@@ -561,7 +563,8 @@ static int btintel_pcie_recv_event(struct hci_dev *hdev, struct sk_buff *skb) + * loading. + */ + btintel_secure_send_result(hdev, ptr, len); +- break; ++ kfree_skb(skb); ++ return 0; + } + } + +-- +2.43.0 + diff --git a/queue-6.12/bluetooth-btintel_pcie-add-handshake-between-driver-.patch b/queue-6.12/bluetooth-btintel_pcie-add-handshake-between-driver-.patch new file mode 100644 index 00000000000..76e8b51cb57 --- /dev/null +++ b/queue-6.12/bluetooth-btintel_pcie-add-handshake-between-driver-.patch @@ -0,0 +1,584 @@ +From 4713fbb16e3e059c9b7e61a6dc7e208e5b6426e1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 1 Oct 2024 16:14:50 +0530 +Subject: Bluetooth: btintel_pcie: Add handshake between driver and firmware + +From: Kiran K + +[ Upstream commit 05c200c8f0295c9c91beeb3ee0552331c1f8adbe ] + +The following handshake mechanism needs be followed after firmware +download is completed to bring the firmware to running state. + +After firmware fragments of Operational image are downloaded and +secure sends result of the image succeeds, + +1. Driver sends HCI Intel reset with boot option #1 to switch FW image. +2. FW sends Alive GP[0] MSIx +3. Driver enables data path (doorbell 0x460 for RBDs, etc...) +4. Driver gets Bootup event from firmware +5. Driver performs D0 entry to device (WRITE to IPC_Sleep_Control =0x0) +6. FW sends Alive GP[0] MSIx +7. Device host interface is fully set for BT protocol stack operation. +8. Driver may optionally get debug event with ID 0x97 which can be dropped + +For Intermediate loadger image, all the above steps are applicable +expcept #5 and #6. + +On HCI_OP_RESET, firmware raises alive interrupt. Driver needs to wait +for it before passing control over to bluetooth stack. + +Co-developed-by: Devegowda Chandrashekar +Signed-off-by: Devegowda Chandrashekar +Signed-off-by: Kiran K +Signed-off-by: Luiz Augusto von Dentz +Stable-dep-of: 510e8380b038 ("Bluetooth: btintel: Do no pass vendor events to stack") +Signed-off-by: Sasha Levin +--- + drivers/bluetooth/btintel.c | 56 ++++++- + drivers/bluetooth/btintel.h | 7 + + drivers/bluetooth/btintel_pcie.c | 262 ++++++++++++++++++++++++++++++- + drivers/bluetooth/btintel_pcie.h | 16 +- + 4 files changed, 329 insertions(+), 12 deletions(-) + +diff --git a/drivers/bluetooth/btintel.c b/drivers/bluetooth/btintel.c +index 30a32ebbcc681..4b17202075b00 100644 +--- a/drivers/bluetooth/btintel.c ++++ b/drivers/bluetooth/btintel.c +@@ -1841,6 +1841,37 @@ static int btintel_boot_wait(struct hci_dev *hdev, ktime_t calltime, int msec) + return 0; + } + ++static int btintel_boot_wait_d0(struct hci_dev *hdev, ktime_t calltime, ++ int msec) ++{ ++ ktime_t delta, rettime; ++ unsigned long long duration; ++ int err; ++ ++ bt_dev_info(hdev, "Waiting for device transition to d0"); ++ ++ err = btintel_wait_on_flag_timeout(hdev, INTEL_WAIT_FOR_D0, ++ TASK_INTERRUPTIBLE, ++ msecs_to_jiffies(msec)); ++ if (err == -EINTR) { ++ bt_dev_err(hdev, "Device d0 move interrupted"); ++ return -EINTR; ++ } ++ ++ if (err) { ++ bt_dev_err(hdev, "Device d0 move timeout"); ++ return -ETIMEDOUT; ++ } ++ ++ rettime = ktime_get(); ++ delta = ktime_sub(rettime, calltime); ++ duration = (unsigned long long)ktime_to_ns(delta) >> 10; ++ ++ bt_dev_info(hdev, "Device moved to D0 in %llu usecs", duration); ++ ++ return 0; ++} ++ + static int btintel_boot(struct hci_dev *hdev, u32 boot_addr) + { + ktime_t calltime; +@@ -1849,6 +1880,7 @@ static int btintel_boot(struct hci_dev *hdev, u32 boot_addr) + calltime = ktime_get(); + + btintel_set_flag(hdev, INTEL_BOOTING); ++ btintel_set_flag(hdev, INTEL_WAIT_FOR_D0); + + err = btintel_send_intel_reset(hdev, boot_addr); + if (err) { +@@ -1861,13 +1893,28 @@ static int btintel_boot(struct hci_dev *hdev, u32 boot_addr) + * is done by the operational firmware sending bootup notification. + * + * Booting into operational firmware should not take longer than +- * 1 second. However if that happens, then just fail the setup ++ * 5 second. However if that happens, then just fail the setup + * since something went wrong. + */ +- err = btintel_boot_wait(hdev, calltime, 1000); +- if (err == -ETIMEDOUT) ++ err = btintel_boot_wait(hdev, calltime, 5000); ++ if (err == -ETIMEDOUT) { + btintel_reset_to_bootloader(hdev); ++ goto exit_error; ++ } + ++ if (hdev->bus == HCI_PCI) { ++ /* In case of PCIe, after receiving bootup event, driver performs ++ * D0 entry by writing 0 to sleep control register (check ++ * btintel_pcie_recv_event()) ++ * Firmware acks with alive interrupt indicating host is full ready to ++ * perform BT operation. Lets wait here till INTEL_WAIT_FOR_D0 ++ * bit is cleared. ++ */ ++ calltime = ktime_get(); ++ err = btintel_boot_wait_d0(hdev, calltime, 2000); ++ } ++ ++exit_error: + return err; + } + +@@ -3273,7 +3320,7 @@ int btintel_configure_setup(struct hci_dev *hdev, const char *driver_name) + } + EXPORT_SYMBOL_GPL(btintel_configure_setup); + +-static int btintel_diagnostics(struct hci_dev *hdev, struct sk_buff *skb) ++int btintel_diagnostics(struct hci_dev *hdev, struct sk_buff *skb) + { + struct intel_tlv *tlv = (void *)&skb->data[5]; + +@@ -3301,6 +3348,7 @@ static int btintel_diagnostics(struct hci_dev *hdev, struct sk_buff *skb) + recv_frame: + return hci_recv_frame(hdev, skb); + } ++EXPORT_SYMBOL_GPL(btintel_diagnostics); + + int btintel_recv_event(struct hci_dev *hdev, struct sk_buff *skb) + { +diff --git a/drivers/bluetooth/btintel.h b/drivers/bluetooth/btintel.h +index aa70e4c274165..b448c67e8ed94 100644 +--- a/drivers/bluetooth/btintel.h ++++ b/drivers/bluetooth/btintel.h +@@ -178,6 +178,7 @@ enum { + INTEL_ROM_LEGACY, + INTEL_ROM_LEGACY_NO_WBS_SUPPORT, + INTEL_ACPI_RESET_ACTIVE, ++ INTEL_WAIT_FOR_D0, + + __INTEL_NUM_FLAGS, + }; +@@ -249,6 +250,7 @@ int btintel_bootloader_setup_tlv(struct hci_dev *hdev, + int btintel_shutdown_combined(struct hci_dev *hdev); + void btintel_hw_error(struct hci_dev *hdev, u8 code); + void btintel_print_fseq_info(struct hci_dev *hdev); ++int btintel_diagnostics(struct hci_dev *hdev, struct sk_buff *skb); + #else + + static inline int btintel_check_bdaddr(struct hci_dev *hdev) +@@ -382,4 +384,9 @@ static inline void btintel_hw_error(struct hci_dev *hdev, u8 code) + static inline void btintel_print_fseq_info(struct hci_dev *hdev) + { + } ++ ++static inline int btintel_diagnostics(struct hci_dev *hdev, struct sk_buff *skb) ++{ ++ return -EOPNOTSUPP; ++} + #endif +diff --git a/drivers/bluetooth/btintel_pcie.c b/drivers/bluetooth/btintel_pcie.c +index 5252125b003f5..16ee962d40861 100644 +--- a/drivers/bluetooth/btintel_pcie.c ++++ b/drivers/bluetooth/btintel_pcie.c +@@ -48,6 +48,17 @@ MODULE_DEVICE_TABLE(pci, btintel_pcie_table); + #define BTINTEL_PCIE_HCI_EVT_PKT 0x00000004 + #define BTINTEL_PCIE_HCI_ISO_PKT 0x00000005 + ++/* Alive interrupt context */ ++enum { ++ BTINTEL_PCIE_ROM, ++ BTINTEL_PCIE_FW_DL, ++ BTINTEL_PCIE_HCI_RESET, ++ BTINTEL_PCIE_INTEL_HCI_RESET1, ++ BTINTEL_PCIE_INTEL_HCI_RESET2, ++ BTINTEL_PCIE_D0, ++ BTINTEL_PCIE_D3 ++}; ++ + static inline void ipc_print_ia_ring(struct hci_dev *hdev, struct ia *ia, + u16 queue_num) + { +@@ -290,8 +301,9 @@ static int btintel_pcie_enable_bt(struct btintel_pcie_data *data) + /* wait for interrupt from the device after booting up to primary + * bootloader. + */ ++ data->alive_intr_ctxt = BTINTEL_PCIE_ROM; + err = wait_event_timeout(data->gp0_wait_q, data->gp0_received, +- msecs_to_jiffies(BTINTEL_DEFAULT_INTR_TIMEOUT)); ++ msecs_to_jiffies(BTINTEL_DEFAULT_INTR_TIMEOUT_MS)); + if (!err) + return -ETIME; + +@@ -302,12 +314,78 @@ static int btintel_pcie_enable_bt(struct btintel_pcie_data *data) + return 0; + } + ++/* BIT(0) - ROM, BIT(1) - IML and BIT(3) - OP ++ * Sometimes during firmware image switching from ROM to IML or IML to OP image, ++ * the previous image bit is not cleared by firmware when alive interrupt is ++ * received. Driver needs to take care of these sticky bits when deciding the ++ * current image running on controller. ++ * Ex: 0x10 and 0x11 - both represents that controller is running IML ++ */ ++static inline bool btintel_pcie_in_rom(struct btintel_pcie_data *data) ++{ ++ return data->boot_stage_cache & BTINTEL_PCIE_CSR_BOOT_STAGE_ROM && ++ !(data->boot_stage_cache & BTINTEL_PCIE_CSR_BOOT_STAGE_IML) && ++ !(data->boot_stage_cache & BTINTEL_PCIE_CSR_BOOT_STAGE_OPFW); ++} ++ ++static inline bool btintel_pcie_in_op(struct btintel_pcie_data *data) ++{ ++ return data->boot_stage_cache & BTINTEL_PCIE_CSR_BOOT_STAGE_OPFW; ++} ++ ++static inline bool btintel_pcie_in_iml(struct btintel_pcie_data *data) ++{ ++ return data->boot_stage_cache & BTINTEL_PCIE_CSR_BOOT_STAGE_IML && ++ !(data->boot_stage_cache & BTINTEL_PCIE_CSR_BOOT_STAGE_OPFW); ++} ++ ++static inline bool btintel_pcie_in_d3(struct btintel_pcie_data *data) ++{ ++ return data->boot_stage_cache & BTINTEL_PCIE_CSR_BOOT_STAGE_D3_STATE_READY; ++} ++ ++static inline bool btintel_pcie_in_d0(struct btintel_pcie_data *data) ++{ ++ return !(data->boot_stage_cache & BTINTEL_PCIE_CSR_BOOT_STAGE_D3_STATE_READY); ++} ++ ++static void btintel_pcie_wr_sleep_cntrl(struct btintel_pcie_data *data, ++ u32 dxstate) ++{ ++ bt_dev_dbg(data->hdev, "writing sleep_ctl_reg: 0x%8.8x", dxstate); ++ btintel_pcie_wr_reg32(data, BTINTEL_PCIE_CSR_IPC_SLEEP_CTL_REG, dxstate); ++} ++ ++static inline char *btintel_pcie_alivectxt_state2str(u32 alive_intr_ctxt) ++{ ++ switch (alive_intr_ctxt) { ++ case BTINTEL_PCIE_ROM: ++ return "rom"; ++ case BTINTEL_PCIE_FW_DL: ++ return "fw_dl"; ++ case BTINTEL_PCIE_D0: ++ return "d0"; ++ case BTINTEL_PCIE_D3: ++ return "d3"; ++ case BTINTEL_PCIE_HCI_RESET: ++ return "hci_reset"; ++ case BTINTEL_PCIE_INTEL_HCI_RESET1: ++ return "intel_reset1"; ++ case BTINTEL_PCIE_INTEL_HCI_RESET2: ++ return "intel_reset2"; ++ default: ++ return "unknown"; ++ } ++ return "null"; ++} ++ + /* This function handles the MSI-X interrupt for gp0 cause (bit 0 in + * BTINTEL_PCIE_CSR_MSIX_HW_INT_CAUSES) which is sent for boot stage and image response. + */ + static void btintel_pcie_msix_gp0_handler(struct btintel_pcie_data *data) + { +- u32 reg; ++ bool submit_rx, signal_waitq; ++ u32 reg, old_ctxt; + + /* This interrupt is for three different causes and it is not easy to + * know what causes the interrupt. So, it compares each register value +@@ -317,20 +395,87 @@ static void btintel_pcie_msix_gp0_handler(struct btintel_pcie_data *data) + if (reg != data->boot_stage_cache) + data->boot_stage_cache = reg; + ++ bt_dev_dbg(data->hdev, "Alive context: %s old_boot_stage: 0x%8.8x new_boot_stage: 0x%8.8x", ++ btintel_pcie_alivectxt_state2str(data->alive_intr_ctxt), ++ data->boot_stage_cache, reg); + reg = btintel_pcie_rd_reg32(data, BTINTEL_PCIE_CSR_IMG_RESPONSE_REG); + if (reg != data->img_resp_cache) + data->img_resp_cache = reg; + + data->gp0_received = true; + +- /* If the boot stage is OP or IML, reset IA and start RX again */ +- if (data->boot_stage_cache & BTINTEL_PCIE_CSR_BOOT_STAGE_OPFW || +- data->boot_stage_cache & BTINTEL_PCIE_CSR_BOOT_STAGE_IML) { ++ old_ctxt = data->alive_intr_ctxt; ++ submit_rx = false; ++ signal_waitq = false; ++ ++ switch (data->alive_intr_ctxt) { ++ case BTINTEL_PCIE_ROM: ++ data->alive_intr_ctxt = BTINTEL_PCIE_FW_DL; ++ signal_waitq = true; ++ break; ++ case BTINTEL_PCIE_FW_DL: ++ /* Error case is already handled. Ideally control shall not ++ * reach here ++ */ ++ break; ++ case BTINTEL_PCIE_INTEL_HCI_RESET1: ++ if (btintel_pcie_in_op(data)) { ++ submit_rx = true; ++ break; ++ } ++ ++ if (btintel_pcie_in_iml(data)) { ++ submit_rx = true; ++ data->alive_intr_ctxt = BTINTEL_PCIE_FW_DL; ++ break; ++ } ++ break; ++ case BTINTEL_PCIE_INTEL_HCI_RESET2: ++ if (btintel_test_and_clear_flag(data->hdev, INTEL_WAIT_FOR_D0)) { ++ btintel_wake_up_flag(data->hdev, INTEL_WAIT_FOR_D0); ++ data->alive_intr_ctxt = BTINTEL_PCIE_D0; ++ } ++ break; ++ case BTINTEL_PCIE_D0: ++ if (btintel_pcie_in_d3(data)) { ++ data->alive_intr_ctxt = BTINTEL_PCIE_D3; ++ signal_waitq = true; ++ break; ++ } ++ break; ++ case BTINTEL_PCIE_D3: ++ if (btintel_pcie_in_d0(data)) { ++ data->alive_intr_ctxt = BTINTEL_PCIE_D0; ++ submit_rx = true; ++ signal_waitq = true; ++ break; ++ } ++ break; ++ case BTINTEL_PCIE_HCI_RESET: ++ data->alive_intr_ctxt = BTINTEL_PCIE_D0; ++ submit_rx = true; ++ signal_waitq = true; ++ break; ++ default: ++ bt_dev_err(data->hdev, "Unknown state: 0x%2.2x", ++ data->alive_intr_ctxt); ++ break; ++ } ++ ++ if (submit_rx) { + btintel_pcie_reset_ia(data); + btintel_pcie_start_rx(data); + } + +- wake_up(&data->gp0_wait_q); ++ if (signal_waitq) { ++ bt_dev_dbg(data->hdev, "wake up gp0 wait_q"); ++ wake_up(&data->gp0_wait_q); ++ } ++ ++ if (old_ctxt != data->alive_intr_ctxt) ++ bt_dev_dbg(data->hdev, "alive context changed: %s -> %s", ++ btintel_pcie_alivectxt_state2str(old_ctxt), ++ btintel_pcie_alivectxt_state2str(data->alive_intr_ctxt)); + } + + /* This function handles the MSX-X interrupt for rx queue 0 which is for TX +@@ -364,6 +509,80 @@ static void btintel_pcie_msix_tx_handle(struct btintel_pcie_data *data) + } + } + ++static int btintel_pcie_recv_event(struct hci_dev *hdev, struct sk_buff *skb) ++{ ++ struct hci_event_hdr *hdr = (void *)skb->data; ++ const char diagnostics_hdr[] = { 0x87, 0x80, 0x03 }; ++ struct btintel_pcie_data *data = hci_get_drvdata(hdev); ++ ++ if (skb->len > HCI_EVENT_HDR_SIZE && hdr->evt == 0xff && ++ hdr->plen > 0) { ++ const void *ptr = skb->data + HCI_EVENT_HDR_SIZE + 1; ++ unsigned int len = skb->len - HCI_EVENT_HDR_SIZE - 1; ++ ++ if (btintel_test_flag(hdev, INTEL_BOOTLOADER)) { ++ switch (skb->data[2]) { ++ case 0x02: ++ /* When switching to the operational firmware ++ * the device sends a vendor specific event ++ * indicating that the bootup completed. ++ */ ++ btintel_bootup(hdev, ptr, len); ++ ++ /* If bootup event is from operational image, ++ * driver needs to write sleep control register to ++ * move into D0 state ++ */ ++ if (btintel_pcie_in_op(data)) { ++ btintel_pcie_wr_sleep_cntrl(data, BTINTEL_PCIE_STATE_D0); ++ data->alive_intr_ctxt = BTINTEL_PCIE_INTEL_HCI_RESET2; ++ break; ++ } ++ ++ if (btintel_pcie_in_iml(data)) { ++ /* In case of IML, there is no concept ++ * of D0 transition. Just mimic as if ++ * IML moved to D0 by clearing INTEL_WAIT_FOR_D0 ++ * bit and waking up the task waiting on ++ * INTEL_WAIT_FOR_D0. This is required ++ * as intel_boot() is common function for ++ * both IML and OP image loading. ++ */ ++ if (btintel_test_and_clear_flag(data->hdev, ++ INTEL_WAIT_FOR_D0)) ++ btintel_wake_up_flag(data->hdev, ++ INTEL_WAIT_FOR_D0); ++ } ++ break; ++ case 0x06: ++ /* When the firmware loading completes the ++ * device sends out a vendor specific event ++ * indicating the result of the firmware ++ * loading. ++ */ ++ btintel_secure_send_result(hdev, ptr, len); ++ break; ++ } ++ } ++ ++ /* Handle all diagnostics events separately. May still call ++ * hci_recv_frame. ++ */ ++ if (len >= sizeof(diagnostics_hdr) && ++ memcmp(&skb->data[2], diagnostics_hdr, ++ sizeof(diagnostics_hdr)) == 0) { ++ return btintel_diagnostics(hdev, skb); ++ } ++ ++ /* This is a debug event that comes from IML and OP image when it ++ * starts execution. There is no need pass this event to stack. ++ */ ++ if (skb->data[2] == 0x97) ++ return 0; ++ } ++ ++ return hci_recv_frame(hdev, skb); ++} + /* Process the received rx data + * It check the frame header to identify the data type and create skb + * and calling HCI API +@@ -465,7 +684,7 @@ static int btintel_pcie_recv_frame(struct btintel_pcie_data *data, + hdev->stat.byte_rx += plen; + + if (pcie_pkt_type == BTINTEL_PCIE_HCI_EVT_PKT) +- ret = btintel_recv_event(hdev, new_skb); ++ ret = btintel_pcie_recv_event(hdev, new_skb); + else + ret = hci_recv_frame(hdev, new_skb); + +@@ -1053,8 +1272,11 @@ static int btintel_pcie_send_frame(struct hci_dev *hdev, + struct sk_buff *skb) + { + struct btintel_pcie_data *data = hci_get_drvdata(hdev); ++ struct hci_command_hdr *cmd; ++ __u16 opcode = ~0; + int ret; + u32 type; ++ u32 old_ctxt; + + /* Due to the fw limitation, the type header of the packet should be + * 4 bytes unlike 1 byte for UART. In UART, the firmware can read +@@ -1073,6 +1295,8 @@ static int btintel_pcie_send_frame(struct hci_dev *hdev, + switch (hci_skb_pkt_type(skb)) { + case HCI_COMMAND_PKT: + type = BTINTEL_PCIE_HCI_CMD_PKT; ++ cmd = (void *)skb->data; ++ opcode = le16_to_cpu(cmd->opcode); + if (btintel_test_flag(hdev, INTEL_BOOTLOADER)) { + struct hci_command_hdr *cmd = (void *)skb->data; + __u16 opcode = le16_to_cpu(cmd->opcode); +@@ -1111,6 +1335,30 @@ static int btintel_pcie_send_frame(struct hci_dev *hdev, + bt_dev_err(hdev, "Failed to send frame (%d)", ret); + goto exit_error; + } ++ ++ if (type == BTINTEL_PCIE_HCI_CMD_PKT && ++ (opcode == HCI_OP_RESET || opcode == 0xfc01)) { ++ old_ctxt = data->alive_intr_ctxt; ++ data->alive_intr_ctxt = ++ (opcode == 0xfc01 ? BTINTEL_PCIE_INTEL_HCI_RESET1 : ++ BTINTEL_PCIE_HCI_RESET); ++ bt_dev_dbg(data->hdev, "sent cmd: 0x%4.4x alive context changed: %s -> %s", ++ opcode, btintel_pcie_alivectxt_state2str(old_ctxt), ++ btintel_pcie_alivectxt_state2str(data->alive_intr_ctxt)); ++ if (opcode == HCI_OP_RESET) { ++ data->gp0_received = false; ++ ret = wait_event_timeout(data->gp0_wait_q, ++ data->gp0_received, ++ msecs_to_jiffies(BTINTEL_DEFAULT_INTR_TIMEOUT_MS)); ++ if (!ret) { ++ hdev->stat.err_tx++; ++ bt_dev_err(hdev, "No alive interrupt received for %s", ++ btintel_pcie_alivectxt_state2str(data->alive_intr_ctxt)); ++ ret = -ETIME; ++ goto exit_error; ++ } ++ } ++ } + hdev->stat.byte_tx += skb->len; + kfree_skb(skb); + +diff --git a/drivers/bluetooth/btintel_pcie.h b/drivers/bluetooth/btintel_pcie.h +index baaff70420f57..8b7824ad005a2 100644 +--- a/drivers/bluetooth/btintel_pcie.h ++++ b/drivers/bluetooth/btintel_pcie.h +@@ -12,6 +12,7 @@ + #define BTINTEL_PCIE_CSR_HW_REV_REG (BTINTEL_PCIE_CSR_BASE + 0x028) + #define BTINTEL_PCIE_CSR_RF_ID_REG (BTINTEL_PCIE_CSR_BASE + 0x09C) + #define BTINTEL_PCIE_CSR_BOOT_STAGE_REG (BTINTEL_PCIE_CSR_BASE + 0x108) ++#define BTINTEL_PCIE_CSR_IPC_SLEEP_CTL_REG (BTINTEL_PCIE_CSR_BASE + 0x114) + #define BTINTEL_PCIE_CSR_CI_ADDR_LSB_REG (BTINTEL_PCIE_CSR_BASE + 0x118) + #define BTINTEL_PCIE_CSR_CI_ADDR_MSB_REG (BTINTEL_PCIE_CSR_BASE + 0x11C) + #define BTINTEL_PCIE_CSR_IMG_RESPONSE_REG (BTINTEL_PCIE_CSR_BASE + 0x12C) +@@ -32,6 +33,7 @@ + #define BTINTEL_PCIE_CSR_BOOT_STAGE_IML_LOCKDOWN (BIT(11)) + #define BTINTEL_PCIE_CSR_BOOT_STAGE_MAC_ACCESS_ON (BIT(16)) + #define BTINTEL_PCIE_CSR_BOOT_STAGE_ALIVE (BIT(23)) ++#define BTINTEL_PCIE_CSR_BOOT_STAGE_D3_STATE_READY (BIT(24)) + + /* Registers for MSI-X */ + #define BTINTEL_PCIE_CSR_MSIX_BASE (0x2000) +@@ -55,6 +57,16 @@ enum msix_hw_int_causes { + BTINTEL_PCIE_MSIX_HW_INT_CAUSES_GP0 = BIT(0), /* cause 32 */ + }; + ++/* PCIe device states ++ * Host-Device interface is active ++ * Host-Device interface is inactive(as reflected by IPC_SLEEP_CONTROL_CSR_AD) ++ * Host-Device interface is inactive(as reflected by IPC_SLEEP_CONTROL_CSR_AD) ++ */ ++enum { ++ BTINTEL_PCIE_STATE_D0 = 0, ++ BTINTEL_PCIE_STATE_D3_HOT = 2, ++ BTINTEL_PCIE_STATE_D3_COLD = 3, ++}; + #define BTINTEL_PCIE_MSIX_NON_AUTO_CLEAR_CAUSE BIT(7) + + /* Minimum and Maximum number of MSI-X Vector +@@ -67,7 +79,7 @@ enum msix_hw_int_causes { + #define BTINTEL_DEFAULT_MAC_ACCESS_TIMEOUT_US 200000 + + /* Default interrupt timeout in msec */ +-#define BTINTEL_DEFAULT_INTR_TIMEOUT 3000 ++#define BTINTEL_DEFAULT_INTR_TIMEOUT_MS 3000 + + /* The number of descriptors in TX/RX queues */ + #define BTINTEL_DESCS_COUNT 16 +@@ -343,6 +355,7 @@ struct rxq { + * @ia: Index Array struct + * @txq: TX Queue struct + * @rxq: RX Queue struct ++ * @alive_intr_ctxt: Alive interrupt context + */ + struct btintel_pcie_data { + struct pci_dev *pdev; +@@ -389,6 +402,7 @@ struct btintel_pcie_data { + struct ia ia; + struct txq txq; + struct rxq rxq; ++ u32 alive_intr_ctxt; + }; + + static inline u32 btintel_pcie_rd_reg32(struct btintel_pcie_data *data, +-- +2.43.0 + diff --git a/queue-6.12/bluetooth-btmtk-adjust-the-position-to-init-iso-data.patch b/queue-6.12/bluetooth-btmtk-adjust-the-position-to-init-iso-data.patch new file mode 100644 index 00000000000..c96e9bd0439 --- /dev/null +++ b/queue-6.12/bluetooth-btmtk-adjust-the-position-to-init-iso-data.patch @@ -0,0 +1,98 @@ +From bf8ffb876efd4d88128215d2c37fb92c2dd37eed Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 25 Oct 2024 14:07:17 +0800 +Subject: Bluetooth: btmtk: adjust the position to init iso data anchor + +From: Chris Lu + +[ Upstream commit 61c5a3def90ac729a538e5ca5ff7f461cff72776 ] + +MediaTek iso data anchor init should be moved to where MediaTek +claims iso data interface. +If there is an unexpected BT usb disconnect during setup flow, +it will cause a NULL pointer crash issue when releasing iso +anchor since the anchor wasn't been init yet. Adjust the position +to do iso data anchor init. + +[ 17.137991] pc : usb_kill_anchored_urbs+0x60/0x168 +[ 17.137998] lr : usb_kill_anchored_urbs+0x44/0x168 +[ 17.137999] sp : ffffffc0890cb5f0 +[ 17.138000] x29: ffffffc0890cb5f0 x28: ffffff80bb6c2e80 +[ 17.144081] gpio gpiochip0: registered chardev handle for 1 lines +[ 17.148421] x27: 0000000000000000 +[ 17.148422] x26: ffffffd301ff4298 x25: 0000000000000003 x24: 00000000000000f0 +[ 17.148424] x23: 0000000000000000 x22: 00000000ffffffff x21: 0000000000000001 +[ 17.148425] x20: ffffffffffffffd8 x19: ffffff80c0f25560 x18: 0000000000000000 +[ 17.148427] x17: ffffffd33864e408 x16: ffffffd33808f7c8 x15: 0000000000200000 +[ 17.232789] x14: e0cd73cf80ffffff x13: 50f2137c0a0338c9 x12: 0000000000000001 +[ 17.239912] x11: 0000000080150011 x10: 0000000000000002 x9 : 0000000000000001 +[ 17.247035] x8 : 0000000000000000 x7 : 0000000000008080 x6 : 8080000000000000 +[ 17.254158] x5 : ffffffd33808ebc0 x4 : fffffffe033dcf20 x3 : 0000000080150011 +[ 17.261281] x2 : ffffff8087a91400 x1 : 0000000000000000 x0 : ffffff80c0f25588 +[ 17.268404] Call trace: +[ 17.270841] usb_kill_anchored_urbs+0x60/0x168 +[ 17.275274] btusb_mtk_release_iso_intf+0x2c/0xd8 [btusb (HASH:5afe 6)] +[ 17.284226] btusb_mtk_disconnect+0x14/0x28 [btusb (HASH:5afe 6)] +[ 17.292652] btusb_disconnect+0x70/0x140 [btusb (HASH:5afe 6)] +[ 17.300818] usb_unbind_interface+0xc4/0x240 +[ 17.305079] device_release_driver_internal+0x18c/0x258 +[ 17.310296] device_release_driver+0x1c/0x30 +[ 17.314557] bus_remove_device+0x140/0x160 +[ 17.318643] device_del+0x1c0/0x330 +[ 17.322121] usb_disable_device+0x80/0x180 +[ 17.326207] usb_disconnect+0xec/0x300 +[ 17.329948] hub_quiesce+0x80/0xd0 +[ 17.333339] hub_disconnect+0x44/0x190 +[ 17.337078] usb_unbind_interface+0xc4/0x240 +[ 17.341337] device_release_driver_internal+0x18c/0x258 +[ 17.346551] device_release_driver+0x1c/0x30 +[ 17.350810] usb_driver_release_interface+0x70/0x88 +[ 17.355677] proc_ioctl+0x13c/0x228 +[ 17.359157] proc_ioctl_default+0x50/0x80 +[ 17.363155] usbdev_ioctl+0x830/0xd08 +[ 17.366808] __arm64_sys_ioctl+0x94/0xd0 +[ 17.370723] invoke_syscall+0x6c/0xf8 +[ 17.374377] el0_svc_common+0x84/0xe0 +[ 17.378030] do_el0_svc+0x20/0x30 +[ 17.381334] el0_svc+0x34/0x60 +[ 17.384382] el0t_64_sync_handler+0x88/0xf0 +[ 17.388554] el0t_64_sync+0x180/0x188 +[ 17.392208] Code: f9400677 f100a2f4 54fffea0 d503201f (b8350288) +[ 17.398289] ---[ end trace 0000000000000000 ]--- + +Fixes: ceac1cb0259d ("Bluetooth: btusb: mediatek: add ISO data transmission functions") +Signed-off-by: Chris Lu +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + drivers/bluetooth/btmtk.c | 1 - + drivers/bluetooth/btusb.c | 1 + + 2 files changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/bluetooth/btmtk.c b/drivers/bluetooth/btmtk.c +index 9bbf205021634..480e4adba9faa 100644 +--- a/drivers/bluetooth/btmtk.c ++++ b/drivers/bluetooth/btmtk.c +@@ -1215,7 +1215,6 @@ static int btmtk_usb_isointf_init(struct hci_dev *hdev) + struct sk_buff *skb; + int err; + +- init_usb_anchor(&btmtk_data->isopkt_anchor); + spin_lock_init(&btmtk_data->isorxlock); + + __set_mtk_intr_interface(hdev); +diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c +index e9534fbc92e32..4ccaddb46ddd8 100644 +--- a/drivers/bluetooth/btusb.c ++++ b/drivers/bluetooth/btusb.c +@@ -2616,6 +2616,7 @@ static void btusb_mtk_claim_iso_intf(struct btusb_data *data) + } + + set_bit(BTMTK_ISOPKT_OVER_INTR, &btmtk_data->flags); ++ init_usb_anchor(&btmtk_data->isopkt_anchor); + } + + static void btusb_mtk_release_iso_intf(struct btusb_data *data) +-- +2.43.0 + diff --git a/queue-6.12/bluetooth-fix-use-after-free-in-device_for_each_chil.patch b/queue-6.12/bluetooth-fix-use-after-free-in-device_for_each_chil.patch new file mode 100644 index 00000000000..931d6df93b7 --- /dev/null +++ b/queue-6.12/bluetooth-fix-use-after-free-in-device_for_each_chil.patch @@ -0,0 +1,150 @@ +From 7174fc78cb1896e89cc21b8b8f14c1058f1f08ba Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 1 Nov 2024 14:44:10 +0300 +Subject: Bluetooth: fix use-after-free in device_for_each_child() + +From: Dmitry Antipov + +[ Upstream commit 27aabf27fd014ae037cc179c61b0bee7cff55b3d ] + +Syzbot has reported the following KASAN splat: + +BUG: KASAN: slab-use-after-free in device_for_each_child+0x18f/0x1a0 +Read of size 8 at addr ffff88801f605308 by task kbnepd bnep0/4980 + +CPU: 0 UID: 0 PID: 4980 Comm: kbnepd bnep0 Not tainted 6.12.0-rc4-00161-gae90f6a6170d #1 +Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.16.3-2.fc40 04/01/2014 +Call Trace: + + dump_stack_lvl+0x100/0x190 + ? device_for_each_child+0x18f/0x1a0 + print_report+0x13a/0x4cb + ? __virt_addr_valid+0x5e/0x590 + ? __phys_addr+0xc6/0x150 + ? device_for_each_child+0x18f/0x1a0 + kasan_report+0xda/0x110 + ? device_for_each_child+0x18f/0x1a0 + ? __pfx_dev_memalloc_noio+0x10/0x10 + device_for_each_child+0x18f/0x1a0 + ? __pfx_device_for_each_child+0x10/0x10 + pm_runtime_set_memalloc_noio+0xf2/0x180 + netdev_unregister_kobject+0x1ed/0x270 + unregister_netdevice_many_notify+0x123c/0x1d80 + ? __mutex_trylock_common+0xde/0x250 + ? __pfx_unregister_netdevice_many_notify+0x10/0x10 + ? trace_contention_end+0xe6/0x140 + ? __mutex_lock+0x4e7/0x8f0 + ? __pfx_lock_acquire.part.0+0x10/0x10 + ? rcu_is_watching+0x12/0xc0 + ? unregister_netdev+0x12/0x30 + unregister_netdevice_queue+0x30d/0x3f0 + ? __pfx_unregister_netdevice_queue+0x10/0x10 + ? __pfx_down_write+0x10/0x10 + unregister_netdev+0x1c/0x30 + bnep_session+0x1fb3/0x2ab0 + ? __pfx_bnep_session+0x10/0x10 + ? __pfx_lock_release+0x10/0x10 + ? __pfx_woken_wake_function+0x10/0x10 + ? __kthread_parkme+0x132/0x200 + ? __pfx_bnep_session+0x10/0x10 + ? kthread+0x13a/0x370 + ? __pfx_bnep_session+0x10/0x10 + kthread+0x2b7/0x370 + ? __pfx_kthread+0x10/0x10 + ret_from_fork+0x48/0x80 + ? __pfx_kthread+0x10/0x10 + ret_from_fork_asm+0x1a/0x30 + + +Allocated by task 4974: + kasan_save_stack+0x30/0x50 + kasan_save_track+0x14/0x30 + __kasan_kmalloc+0xaa/0xb0 + __kmalloc_noprof+0x1d1/0x440 + hci_alloc_dev_priv+0x1d/0x2820 + __vhci_create_device+0xef/0x7d0 + vhci_write+0x2c7/0x480 + vfs_write+0x6a0/0xfc0 + ksys_write+0x12f/0x260 + do_syscall_64+0xc7/0x250 + entry_SYSCALL_64_after_hwframe+0x77/0x7f + +Freed by task 4979: + kasan_save_stack+0x30/0x50 + kasan_save_track+0x14/0x30 + kasan_save_free_info+0x3b/0x60 + __kasan_slab_free+0x4f/0x70 + kfree+0x141/0x490 + hci_release_dev+0x4d9/0x600 + bt_host_release+0x6a/0xb0 + device_release+0xa4/0x240 + kobject_put+0x1ec/0x5a0 + put_device+0x1f/0x30 + vhci_release+0x81/0xf0 + __fput+0x3f6/0xb30 + task_work_run+0x151/0x250 + do_exit+0xa79/0x2c30 + do_group_exit+0xd5/0x2a0 + get_signal+0x1fcd/0x2210 + arch_do_signal_or_restart+0x93/0x780 + syscall_exit_to_user_mode+0x140/0x290 + do_syscall_64+0xd4/0x250 + entry_SYSCALL_64_after_hwframe+0x77/0x7f + +In 'hci_conn_del_sysfs()', 'device_unregister()' may be called when +an underlying (kobject) reference counter is greater than 1. This +means that reparenting (happened when the device is actually freed) +is delayed and, during that delay, parent controller device (hciX) +may be deleted. Since the latter may create a dangling pointer to +freed parent, avoid that scenario by reparenting to NULL explicitly. + +Reported-by: syzbot+6cf5652d3df49fae2e3f@syzkaller.appspotmail.com +Tested-by: syzbot+6cf5652d3df49fae2e3f@syzkaller.appspotmail.com +Closes: https://syzkaller.appspot.com/bug?extid=6cf5652d3df49fae2e3f +Fixes: a85fb91e3d72 ("Bluetooth: Fix double free in hci_conn_cleanup") +Signed-off-by: Dmitry Antipov +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + net/bluetooth/hci_sysfs.c | 15 ++++----------- + 1 file changed, 4 insertions(+), 11 deletions(-) + +diff --git a/net/bluetooth/hci_sysfs.c b/net/bluetooth/hci_sysfs.c +index 367e32fe30eb8..4b54dbbf0729a 100644 +--- a/net/bluetooth/hci_sysfs.c ++++ b/net/bluetooth/hci_sysfs.c +@@ -21,16 +21,6 @@ static const struct device_type bt_link = { + .release = bt_link_release, + }; + +-/* +- * The rfcomm tty device will possibly retain even when conn +- * is down, and sysfs doesn't support move zombie device, +- * so we should move the device before conn device is destroyed. +- */ +-static int __match_tty(struct device *dev, void *data) +-{ +- return !strncmp(dev_name(dev), "rfcomm", 6); +-} +- + void hci_conn_init_sysfs(struct hci_conn *conn) + { + struct hci_dev *hdev = conn->hdev; +@@ -73,10 +63,13 @@ void hci_conn_del_sysfs(struct hci_conn *conn) + return; + } + ++ /* If there are devices using the connection as parent reset it to NULL ++ * before unregistering the device. ++ */ + while (1) { + struct device *dev; + +- dev = device_find_child(&conn->dev, NULL, __match_tty); ++ dev = device_find_any_child(&conn->dev); + if (!dev) + break; + device_move(dev, NULL, DPM_ORDER_DEV_LAST); +-- +2.43.0 + diff --git a/queue-6.12/bluetooth-iso-do-not-emit-le-big-create-sync-if-prev.patch b/queue-6.12/bluetooth-iso-do-not-emit-le-big-create-sync-if-prev.patch new file mode 100644 index 00000000000..f1568040f05 --- /dev/null +++ b/queue-6.12/bluetooth-iso-do-not-emit-le-big-create-sync-if-prev.patch @@ -0,0 +1,284 @@ +From 56eb5b0fb52f01af35399c111e9bda91a59a8a34 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 1 Nov 2024 10:23:38 +0200 +Subject: Bluetooth: ISO: Do not emit LE BIG Create Sync if previous is pending + +From: Iulia Tanasescu + +[ Upstream commit 42ecf1947135110ea08abeaca39741636f9a2285 ] + +The Bluetooth Core spec does not allow a LE BIG Create sync command to be +sent to Controller if another one is pending (Vol 4, Part E, page 2586). + +In order to avoid this issue, the HCI_CONN_CREATE_BIG_SYNC was added +to mark that the LE BIG Create Sync command has been sent for a hcon. +Once the BIG Sync Established event is received, the hcon flag is +erased and the next pending hcon is handled. + +Signed-off-by: Iulia Tanasescu +Signed-off-by: Luiz Augusto von Dentz +Stable-dep-of: 07a9342b94a9 ("Bluetooth: ISO: Send BIG Create Sync via hci_sync") +Signed-off-by: Sasha Levin +--- + include/net/bluetooth/hci.h | 1 + + include/net/bluetooth/hci_core.h | 29 +++++++++++ + net/bluetooth/hci_conn.c | 87 +++++++++++++++++++++++++++----- + net/bluetooth/hci_event.c | 20 +++++++- + net/bluetooth/iso.c | 4 +- + 5 files changed, 125 insertions(+), 16 deletions(-) + +diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h +index 4734e9e99972f..a1864cff616ae 100644 +--- a/include/net/bluetooth/hci.h ++++ b/include/net/bluetooth/hci.h +@@ -29,6 +29,7 @@ + #define HCI_MAX_ACL_SIZE 1024 + #define HCI_MAX_SCO_SIZE 255 + #define HCI_MAX_ISO_SIZE 251 ++#define HCI_MAX_ISO_BIS 31 + #define HCI_MAX_EVENT_SIZE 260 + #define HCI_MAX_FRAME_SIZE (HCI_MAX_ACL_SIZE + 4) + +diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h +index 494fcd68f8311..4c185a08c3a3a 100644 +--- a/include/net/bluetooth/hci_core.h ++++ b/include/net/bluetooth/hci_core.h +@@ -711,6 +711,9 @@ struct hci_conn { + __s8 tx_power; + __s8 max_tx_power; + struct bt_iso_qos iso_qos; ++ __u8 num_bis; ++ __u8 bis[HCI_MAX_ISO_BIS]; ++ + unsigned long flags; + + enum conn_reasons conn_reason; +@@ -946,6 +949,7 @@ enum { + HCI_CONN_PER_ADV, + HCI_CONN_BIG_CREATED, + HCI_CONN_CREATE_CIS, ++ HCI_CONN_CREATE_BIG_SYNC, + HCI_CONN_BIG_SYNC, + HCI_CONN_BIG_SYNC_FAILED, + HCI_CONN_CREATE_PA_SYNC, +@@ -1295,6 +1299,30 @@ static inline struct hci_conn *hci_conn_hash_lookup_big(struct hci_dev *hdev, + return NULL; + } + ++static inline struct hci_conn * ++hci_conn_hash_lookup_big_sync_pend(struct hci_dev *hdev, ++ __u8 handle, __u8 num_bis) ++{ ++ struct hci_conn_hash *h = &hdev->conn_hash; ++ struct hci_conn *c; ++ ++ rcu_read_lock(); ++ ++ list_for_each_entry_rcu(c, &h->list, list) { ++ if (c->type != ISO_LINK) ++ continue; ++ ++ if (handle == c->iso_qos.bcast.big && num_bis == c->num_bis) { ++ rcu_read_unlock(); ++ return c; ++ } ++ } ++ ++ rcu_read_unlock(); ++ ++ return NULL; ++} ++ + static inline struct hci_conn * + hci_conn_hash_lookup_big_state(struct hci_dev *hdev, __u8 handle, __u16 state) + { +@@ -1479,6 +1507,7 @@ void hci_sco_setup(struct hci_conn *conn, __u8 status); + bool hci_iso_setup_path(struct hci_conn *conn); + int hci_le_create_cis_pending(struct hci_dev *hdev); + int hci_pa_create_sync_pending(struct hci_dev *hdev); ++int hci_le_big_create_sync_pending(struct hci_dev *hdev); + int hci_conn_check_create_cis(struct hci_conn *conn); + + struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst, +diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c +index 6878fc5206c0b..1ff62bf9d41b4 100644 +--- a/net/bluetooth/hci_conn.c ++++ b/net/bluetooth/hci_conn.c +@@ -2180,34 +2180,93 @@ struct hci_conn *hci_pa_create_sync(struct hci_dev *hdev, bdaddr_t *dst, + return conn; + } + ++static bool hci_conn_check_create_big_sync(struct hci_conn *conn) ++{ ++ if (!conn->num_bis) ++ return false; ++ ++ return true; ++} ++ ++int hci_le_big_create_sync_pending(struct hci_dev *hdev) ++{ ++ DEFINE_FLEX(struct hci_cp_le_big_create_sync, pdu, bis, num_bis, 0x11); ++ struct hci_conn *conn; ++ ++ rcu_read_lock(); ++ ++ pdu->num_bis = 0; ++ ++ /* The spec allows only one pending LE BIG Create Sync command at ++ * a time. If the command is pending now, don't do anything. We ++ * check for pending connections after each BIG Sync Established ++ * event. ++ * ++ * BLUETOOTH CORE SPECIFICATION Version 5.3 | Vol 4, Part E ++ * page 2586: ++ * ++ * If the Host sends this command when the Controller is in the ++ * process of synchronizing to any BIG, i.e. the HCI_LE_BIG_Sync_ ++ * Established event has not been generated, the Controller shall ++ * return the error code Command Disallowed (0x0C). ++ */ ++ list_for_each_entry_rcu(conn, &hdev->conn_hash.list, list) { ++ if (test_bit(HCI_CONN_CREATE_BIG_SYNC, &conn->flags)) ++ goto unlock; ++ } ++ ++ list_for_each_entry_rcu(conn, &hdev->conn_hash.list, list) { ++ if (hci_conn_check_create_big_sync(conn)) { ++ struct bt_iso_qos *qos = &conn->iso_qos; ++ ++ set_bit(HCI_CONN_CREATE_BIG_SYNC, &conn->flags); ++ ++ pdu->handle = qos->bcast.big; ++ pdu->sync_handle = cpu_to_le16(conn->sync_handle); ++ pdu->encryption = qos->bcast.encryption; ++ memcpy(pdu->bcode, qos->bcast.bcode, ++ sizeof(pdu->bcode)); ++ pdu->mse = qos->bcast.mse; ++ pdu->timeout = cpu_to_le16(qos->bcast.timeout); ++ pdu->num_bis = conn->num_bis; ++ memcpy(pdu->bis, conn->bis, conn->num_bis); ++ ++ break; ++ } ++ } ++ ++unlock: ++ rcu_read_unlock(); ++ ++ if (!pdu->num_bis) ++ return 0; ++ ++ return hci_send_cmd(hdev, HCI_OP_LE_BIG_CREATE_SYNC, ++ struct_size(pdu, bis, pdu->num_bis), pdu); ++} ++ + int hci_le_big_create_sync(struct hci_dev *hdev, struct hci_conn *hcon, + struct bt_iso_qos *qos, + __u16 sync_handle, __u8 num_bis, __u8 bis[]) + { +- DEFINE_FLEX(struct hci_cp_le_big_create_sync, pdu, bis, num_bis, 0x11); + int err; + +- if (num_bis < 0x01 || num_bis > pdu->num_bis) ++ if (num_bis < 0x01 || num_bis > ISO_MAX_NUM_BIS) + return -EINVAL; + + err = qos_set_big(hdev, qos); + if (err) + return err; + +- if (hcon) +- hcon->iso_qos.bcast.big = qos->bcast.big; ++ if (hcon) { ++ /* Update hcon QoS */ ++ hcon->iso_qos = *qos; + +- pdu->handle = qos->bcast.big; +- pdu->sync_handle = cpu_to_le16(sync_handle); +- pdu->encryption = qos->bcast.encryption; +- memcpy(pdu->bcode, qos->bcast.bcode, sizeof(pdu->bcode)); +- pdu->mse = qos->bcast.mse; +- pdu->timeout = cpu_to_le16(qos->bcast.timeout); +- pdu->num_bis = num_bis; +- memcpy(pdu->bis, bis, num_bis); ++ hcon->num_bis = num_bis; ++ memcpy(hcon->bis, bis, num_bis); ++ } + +- return hci_send_cmd(hdev, HCI_OP_LE_BIG_CREATE_SYNC, +- struct_size(pdu, bis, num_bis), pdu); ++ return hci_le_big_create_sync_pending(hdev); + } + + static void create_big_complete(struct hci_dev *hdev, void *data, int err) +diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c +index 81001cd53e01c..2e4bd3e961ce0 100644 +--- a/net/bluetooth/hci_event.c ++++ b/net/bluetooth/hci_event.c +@@ -6913,7 +6913,7 @@ static void hci_le_big_sync_established_evt(struct hci_dev *hdev, void *data, + struct sk_buff *skb) + { + struct hci_evt_le_big_sync_estabilished *ev = data; +- struct hci_conn *bis; ++ struct hci_conn *bis, *conn; + int i; + + bt_dev_dbg(hdev, "status 0x%2.2x", ev->status); +@@ -6924,6 +6924,20 @@ static void hci_le_big_sync_established_evt(struct hci_dev *hdev, void *data, + + hci_dev_lock(hdev); + ++ conn = hci_conn_hash_lookup_big_sync_pend(hdev, ev->handle, ++ ev->num_bis); ++ if (!conn) { ++ bt_dev_err(hdev, ++ "Unable to find connection for big 0x%2.2x", ++ ev->handle); ++ goto unlock; ++ } ++ ++ clear_bit(HCI_CONN_CREATE_BIG_SYNC, &conn->flags); ++ ++ conn->num_bis = 0; ++ memset(conn->bis, 0, sizeof(conn->num_bis)); ++ + for (i = 0; i < ev->num_bis; i++) { + u16 handle = le16_to_cpu(ev->bis[i]); + __le32 interval; +@@ -6973,6 +6987,10 @@ static void hci_le_big_sync_established_evt(struct hci_dev *hdev, void *data, + hci_connect_cfm(bis, ev->status); + } + ++unlock: ++ /* Handle any other pending BIG sync command */ ++ hci_le_big_create_sync_pending(hdev); ++ + hci_dev_unlock(hdev); + } + +diff --git a/net/bluetooth/iso.c b/net/bluetooth/iso.c +index 109bf58c982ae..463c61712b249 100644 +--- a/net/bluetooth/iso.c ++++ b/net/bluetooth/iso.c +@@ -1996,6 +1996,7 @@ int iso_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 *flags) + + if (sk) { + int err; ++ struct hci_conn *hcon = iso_pi(sk)->conn->hcon; + + iso_pi(sk)->qos.bcast.encryption = ev2->encryption; + +@@ -2004,7 +2005,8 @@ int iso_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 *flags) + + if (!test_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags) && + !test_and_set_bit(BT_SK_BIG_SYNC, &iso_pi(sk)->flags)) { +- err = hci_le_big_create_sync(hdev, NULL, ++ err = hci_le_big_create_sync(hdev, ++ hcon, + &iso_pi(sk)->qos, + iso_pi(sk)->sync_handle, + iso_pi(sk)->bc_num_bis, +-- +2.43.0 + diff --git a/queue-6.12/bluetooth-iso-do-not-emit-le-pa-create-sync-if-previ.patch b/queue-6.12/bluetooth-iso-do-not-emit-le-pa-create-sync-if-previ.patch new file mode 100644 index 00000000000..39d40f40e9c --- /dev/null +++ b/queue-6.12/bluetooth-iso-do-not-emit-le-pa-create-sync-if-previ.patch @@ -0,0 +1,339 @@ +From 1355b8eba4622a8badd8d3514eac04bb6f968643 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 1 Nov 2024 10:23:36 +0200 +Subject: Bluetooth: ISO: Do not emit LE PA Create Sync if previous is pending + +From: Iulia Tanasescu + +[ Upstream commit 4a5e0ba68676b3a77298cf646cd2b39c94fbd2f5 ] + +The Bluetooth Core spec does not allow a LE PA Create sync command to be +sent to Controller if another one is pending (Vol 4, Part E, page 2493). + +In order to avoid this issue, the HCI_CONN_CREATE_PA_SYNC was added +to mark that the LE PA Create Sync command has been sent for a hcon. +Once the PA Sync Established event is received, the hcon flag is +erased and the next pending hcon is handled. + +Signed-off-by: Iulia Tanasescu +Signed-off-by: Luiz Augusto von Dentz +Stable-dep-of: 07a9342b94a9 ("Bluetooth: ISO: Send BIG Create Sync via hci_sync") +Signed-off-by: Sasha Levin +--- + include/net/bluetooth/hci.h | 3 +- + include/net/bluetooth/hci_core.h | 34 +++++++++ + net/bluetooth/hci_conn.c | 123 +++++++++++++++++++++---------- + net/bluetooth/hci_event.c | 19 ++++- + 4 files changed, 139 insertions(+), 40 deletions(-) + +diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h +index bab1e3d7452a2..4734e9e99972f 100644 +--- a/include/net/bluetooth/hci.h ++++ b/include/net/bluetooth/hci.h +@@ -1,7 +1,7 @@ + /* + BlueZ - Bluetooth protocol stack for Linux + Copyright (C) 2000-2001 Qualcomm Incorporated +- Copyright 2023 NXP ++ Copyright 2023-2024 NXP + + Written 2000,2001 by Maxim Krasnyansky + +@@ -683,6 +683,7 @@ enum { + #define HCI_RSSI_INVALID 127 + + #define HCI_SYNC_HANDLE_INVALID 0xffff ++#define HCI_SID_INVALID 0xff + + #define HCI_ROLE_MASTER 0x00 + #define HCI_ROLE_SLAVE 0x01 +diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h +index 88265d37aa72e..494fcd68f8311 100644 +--- a/include/net/bluetooth/hci_core.h ++++ b/include/net/bluetooth/hci_core.h +@@ -668,6 +668,7 @@ struct hci_conn { + __u8 adv_instance; + __u16 handle; + __u16 sync_handle; ++ __u8 sid; + __u16 state; + __u16 mtu; + __u8 mode; +@@ -947,6 +948,7 @@ enum { + HCI_CONN_CREATE_CIS, + HCI_CONN_BIG_SYNC, + HCI_CONN_BIG_SYNC_FAILED, ++ HCI_CONN_CREATE_PA_SYNC, + HCI_CONN_PA_SYNC, + HCI_CONN_PA_SYNC_FAILED, + }; +@@ -1099,6 +1101,30 @@ static inline struct hci_conn *hci_conn_hash_lookup_bis(struct hci_dev *hdev, + return NULL; + } + ++static inline struct hci_conn *hci_conn_hash_lookup_sid(struct hci_dev *hdev, ++ __u8 sid, ++ bdaddr_t *dst, ++ __u8 dst_type) ++{ ++ struct hci_conn_hash *h = &hdev->conn_hash; ++ struct hci_conn *c; ++ ++ rcu_read_lock(); ++ ++ list_for_each_entry_rcu(c, &h->list, list) { ++ if (c->type != ISO_LINK || bacmp(&c->dst, dst) || ++ c->dst_type != dst_type || c->sid != sid) ++ continue; ++ ++ rcu_read_unlock(); ++ return c; ++ } ++ ++ rcu_read_unlock(); ++ ++ return NULL; ++} ++ + static inline struct hci_conn * + hci_conn_hash_lookup_per_adv_bis(struct hci_dev *hdev, + bdaddr_t *ba, +@@ -1328,6 +1354,13 @@ hci_conn_hash_lookup_pa_sync_handle(struct hci_dev *hdev, __u16 sync_handle) + if (c->type != ISO_LINK) + continue; + ++ /* Ignore the listen hcon, we are looking ++ * for the child hcon that was created as ++ * a result of the PA sync established event. ++ */ ++ if (c->state == BT_LISTEN) ++ continue; ++ + if (c->sync_handle == sync_handle) { + rcu_read_unlock(); + return c; +@@ -1445,6 +1478,7 @@ bool hci_setup_sync(struct hci_conn *conn, __u16 handle); + void hci_sco_setup(struct hci_conn *conn, __u8 status); + bool hci_iso_setup_path(struct hci_conn *conn); + int hci_le_create_cis_pending(struct hci_dev *hdev); ++int hci_pa_create_sync_pending(struct hci_dev *hdev); + int hci_conn_check_create_cis(struct hci_conn *conn); + + struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst, +diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c +index c4c74b82ed211..6878fc5206c0b 100644 +--- a/net/bluetooth/hci_conn.c ++++ b/net/bluetooth/hci_conn.c +@@ -952,6 +952,7 @@ static struct hci_conn *__hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t + conn->tx_power = HCI_TX_POWER_INVALID; + conn->max_tx_power = HCI_TX_POWER_INVALID; + conn->sync_handle = HCI_SYNC_HANDLE_INVALID; ++ conn->sid = HCI_SID_INVALID; + + set_bit(HCI_CONN_POWER_SAVE, &conn->flags); + conn->disc_timeout = HCI_DISCONN_TIMEOUT; +@@ -2062,73 +2063,119 @@ static int create_big_sync(struct hci_dev *hdev, void *data) + + static void create_pa_complete(struct hci_dev *hdev, void *data, int err) + { +- struct hci_cp_le_pa_create_sync *cp = data; +- + bt_dev_dbg(hdev, ""); + + if (err) + bt_dev_err(hdev, "Unable to create PA: %d", err); ++} ++ ++static bool hci_conn_check_create_pa_sync(struct hci_conn *conn) ++{ ++ if (conn->type != ISO_LINK || conn->sid == HCI_SID_INVALID) ++ return false; + +- kfree(cp); ++ return true; + } + + static int create_pa_sync(struct hci_dev *hdev, void *data) + { +- struct hci_cp_le_pa_create_sync *cp = data; +- int err; ++ struct hci_cp_le_pa_create_sync *cp = NULL; ++ struct hci_conn *conn; ++ int err = 0; + +- err = __hci_cmd_sync_status(hdev, HCI_OP_LE_PA_CREATE_SYNC, +- sizeof(*cp), cp, HCI_CMD_TIMEOUT); +- if (err) { +- hci_dev_clear_flag(hdev, HCI_PA_SYNC); +- return err; ++ hci_dev_lock(hdev); ++ ++ rcu_read_lock(); ++ ++ /* The spec allows only one pending LE Periodic Advertising Create ++ * Sync command at a time. If the command is pending now, don't do ++ * anything. We check for pending connections after each PA Sync ++ * Established event. ++ * ++ * BLUETOOTH CORE SPECIFICATION Version 5.3 | Vol 4, Part E ++ * page 2493: ++ * ++ * If the Host issues this command when another HCI_LE_Periodic_ ++ * Advertising_Create_Sync command is pending, the Controller shall ++ * return the error code Command Disallowed (0x0C). ++ */ ++ list_for_each_entry_rcu(conn, &hdev->conn_hash.list, list) { ++ if (test_bit(HCI_CONN_CREATE_PA_SYNC, &conn->flags)) ++ goto unlock; + } + +- return hci_update_passive_scan_sync(hdev); ++ list_for_each_entry_rcu(conn, &hdev->conn_hash.list, list) { ++ if (hci_conn_check_create_pa_sync(conn)) { ++ struct bt_iso_qos *qos = &conn->iso_qos; ++ ++ cp = kzalloc(sizeof(*cp), GFP_KERNEL); ++ if (!cp) { ++ err = -ENOMEM; ++ goto unlock; ++ } ++ ++ cp->options = qos->bcast.options; ++ cp->sid = conn->sid; ++ cp->addr_type = conn->dst_type; ++ bacpy(&cp->addr, &conn->dst); ++ cp->skip = cpu_to_le16(qos->bcast.skip); ++ cp->sync_timeout = cpu_to_le16(qos->bcast.sync_timeout); ++ cp->sync_cte_type = qos->bcast.sync_cte_type; ++ ++ break; ++ } ++ } ++ ++unlock: ++ rcu_read_unlock(); ++ ++ hci_dev_unlock(hdev); ++ ++ if (cp) { ++ hci_dev_set_flag(hdev, HCI_PA_SYNC); ++ set_bit(HCI_CONN_CREATE_PA_SYNC, &conn->flags); ++ ++ err = __hci_cmd_sync_status(hdev, HCI_OP_LE_PA_CREATE_SYNC, ++ sizeof(*cp), cp, HCI_CMD_TIMEOUT); ++ if (!err) ++ err = hci_update_passive_scan_sync(hdev); ++ ++ kfree(cp); ++ ++ if (err) { ++ hci_dev_clear_flag(hdev, HCI_PA_SYNC); ++ clear_bit(HCI_CONN_CREATE_PA_SYNC, &conn->flags); ++ } ++ } ++ ++ return err; ++} ++ ++int hci_pa_create_sync_pending(struct hci_dev *hdev) ++{ ++ /* Queue start pa_create_sync and scan */ ++ return hci_cmd_sync_queue(hdev, create_pa_sync, ++ NULL, create_pa_complete); + } + + struct hci_conn *hci_pa_create_sync(struct hci_dev *hdev, bdaddr_t *dst, + __u8 dst_type, __u8 sid, + struct bt_iso_qos *qos) + { +- struct hci_cp_le_pa_create_sync *cp; + struct hci_conn *conn; +- int err; +- +- if (hci_dev_test_and_set_flag(hdev, HCI_PA_SYNC)) +- return ERR_PTR(-EBUSY); + + conn = hci_conn_add_unset(hdev, ISO_LINK, dst, HCI_ROLE_SLAVE); + if (IS_ERR(conn)) + return conn; + + conn->iso_qos = *qos; ++ conn->dst_type = dst_type; ++ conn->sid = sid; + conn->state = BT_LISTEN; + + hci_conn_hold(conn); + +- cp = kzalloc(sizeof(*cp), GFP_KERNEL); +- if (!cp) { +- hci_dev_clear_flag(hdev, HCI_PA_SYNC); +- hci_conn_drop(conn); +- return ERR_PTR(-ENOMEM); +- } +- +- cp->options = qos->bcast.options; +- cp->sid = sid; +- cp->addr_type = dst_type; +- bacpy(&cp->addr, dst); +- cp->skip = cpu_to_le16(qos->bcast.skip); +- cp->sync_timeout = cpu_to_le16(qos->bcast.sync_timeout); +- cp->sync_cte_type = qos->bcast.sync_cte_type; +- +- /* Queue start pa_create_sync and scan */ +- err = hci_cmd_sync_queue(hdev, create_pa_sync, cp, create_pa_complete); +- if (err < 0) { +- hci_conn_drop(conn); +- kfree(cp); +- return ERR_PTR(err); +- } ++ hci_pa_create_sync_pending(hdev); + + return conn; + } +diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c +index 0bbad90ddd6f8..81001cd53e01c 100644 +--- a/net/bluetooth/hci_event.c ++++ b/net/bluetooth/hci_event.c +@@ -6345,7 +6345,7 @@ static void hci_le_pa_sync_estabilished_evt(struct hci_dev *hdev, void *data, + struct hci_ev_le_pa_sync_established *ev = data; + int mask = hdev->link_mode; + __u8 flags = 0; +- struct hci_conn *pa_sync; ++ struct hci_conn *pa_sync, *conn; + + bt_dev_dbg(hdev, "status 0x%2.2x", ev->status); + +@@ -6353,6 +6353,20 @@ static void hci_le_pa_sync_estabilished_evt(struct hci_dev *hdev, void *data, + + hci_dev_clear_flag(hdev, HCI_PA_SYNC); + ++ conn = hci_conn_hash_lookup_sid(hdev, ev->sid, &ev->bdaddr, ++ ev->bdaddr_type); ++ if (!conn) { ++ bt_dev_err(hdev, ++ "Unable to find connection for dst %pMR sid 0x%2.2x", ++ &ev->bdaddr, ev->sid); ++ goto unlock; ++ } ++ ++ clear_bit(HCI_CONN_CREATE_PA_SYNC, &conn->flags); ++ ++ conn->sync_handle = le16_to_cpu(ev->handle); ++ conn->sid = HCI_SID_INVALID; ++ + mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ISO_LINK, &flags); + if (!(mask & HCI_LM_ACCEPT)) { + hci_le_pa_term_sync(hdev, ev->handle); +@@ -6379,6 +6393,9 @@ static void hci_le_pa_sync_estabilished_evt(struct hci_dev *hdev, void *data, + } + + unlock: ++ /* Handle any other pending PA sync command */ ++ hci_pa_create_sync_pending(hdev); ++ + hci_dev_unlock(hdev); + } + +-- +2.43.0 + diff --git a/queue-6.12/bluetooth-iso-send-big-create-sync-via-hci_sync.patch b/queue-6.12/bluetooth-iso-send-big-create-sync-via-hci_sync.patch new file mode 100644 index 00000000000..e766341331d --- /dev/null +++ b/queue-6.12/bluetooth-iso-send-big-create-sync-via-hci_sync.patch @@ -0,0 +1,114 @@ +From 9bff43b82f78262c49d7e664f90b4f131358bb87 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 11 Nov 2024 13:47:08 +0200 +Subject: Bluetooth: ISO: Send BIG Create Sync via hci_sync + +From: Iulia Tanasescu + +[ Upstream commit 07a9342b94a91b306ed1cf6aa8254aea210764c9 ] + +Before issuing the LE BIG Create Sync command, an available BIG handle +is chosen by iterating through the conn_hash list and finding the first +unused value. + +If a BIG is terminated, the associated hcons are removed from the list +and the LE BIG Terminate Sync command is sent via hci_sync queue. +However, a new LE BIG Create sync command might be issued via +hci_send_cmd, before the previous BIG sync was terminated. This +can cause the same BIG handle to be reused and the LE BIG Create Sync +to fail with Command Disallowed. + +< HCI Command: LE Broadcast Isochronous Group Create Sync (0x08|0x006b) + BIG Handle: 0x00 + BIG Sync Handle: 0x0002 + Encryption: Unencrypted (0x00) + Broadcast Code[16]: 00000000000000000000000000000000 + Maximum Number Subevents: 0x00 + Timeout: 20000 ms (0x07d0) + Number of BIS: 1 + BIS ID: 0x01 +> HCI Event: Command Status (0x0f) plen 4 + LE Broadcast Isochronous Group Create Sync (0x08|0x006b) ncmd 1 + Status: Command Disallowed (0x0c) +< HCI Command: LE Broadcast Isochronous Group Terminate Sync (0x08|0x006c) + BIG Handle: 0x00 + +This commit fixes the ordering of the LE BIG Create Sync/LE BIG Terminate +Sync commands, to make sure that either the previous BIG sync is +terminated before reusing the handle, or that a new handle is chosen +for a new sync. + +Fixes: eca0ae4aea66 ("Bluetooth: Add initial implementation of BIS connections") +Signed-off-by: Iulia Tanasescu +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + net/bluetooth/hci_conn.c | 17 ++++++++++++++++- + net/bluetooth/iso.c | 9 +++++++++ + 2 files changed, 25 insertions(+), 1 deletion(-) + +diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c +index 1ff62bf9d41b4..6354cdf9c2b37 100644 +--- a/net/bluetooth/hci_conn.c ++++ b/net/bluetooth/hci_conn.c +@@ -2188,7 +2188,15 @@ static bool hci_conn_check_create_big_sync(struct hci_conn *conn) + return true; + } + +-int hci_le_big_create_sync_pending(struct hci_dev *hdev) ++static void big_create_sync_complete(struct hci_dev *hdev, void *data, int err) ++{ ++ bt_dev_dbg(hdev, ""); ++ ++ if (err) ++ bt_dev_err(hdev, "Unable to create BIG sync: %d", err); ++} ++ ++static int big_create_sync(struct hci_dev *hdev, void *data) + { + DEFINE_FLEX(struct hci_cp_le_big_create_sync, pdu, bis, num_bis, 0x11); + struct hci_conn *conn; +@@ -2245,6 +2253,13 @@ int hci_le_big_create_sync_pending(struct hci_dev *hdev) + struct_size(pdu, bis, pdu->num_bis), pdu); + } + ++int hci_le_big_create_sync_pending(struct hci_dev *hdev) ++{ ++ /* Queue big_create_sync */ ++ return hci_cmd_sync_queue_once(hdev, big_create_sync, ++ NULL, big_create_sync_complete); ++} ++ + int hci_le_big_create_sync(struct hci_dev *hdev, struct hci_conn *hcon, + struct bt_iso_qos *qos, + __u16 sync_handle, __u8 num_bis, __u8 bis[]) +diff --git a/net/bluetooth/iso.c b/net/bluetooth/iso.c +index 463c61712b249..5e2d9758bd3c1 100644 +--- a/net/bluetooth/iso.c ++++ b/net/bluetooth/iso.c +@@ -1392,6 +1392,13 @@ static void iso_conn_big_sync(struct sock *sk) + if (!hdev) + return; + ++ /* hci_le_big_create_sync requires hdev lock to be held, since ++ * it enqueues the HCI LE BIG Create Sync command via ++ * hci_cmd_sync_queue_once, which checks hdev flags that might ++ * change. ++ */ ++ hci_dev_lock(hdev); ++ + if (!test_and_set_bit(BT_SK_BIG_SYNC, &iso_pi(sk)->flags)) { + err = hci_le_big_create_sync(hdev, iso_pi(sk)->conn->hcon, + &iso_pi(sk)->qos, +@@ -1402,6 +1409,8 @@ static void iso_conn_big_sync(struct sock *sk) + bt_dev_err(hdev, "hci_le_big_create_sync: %d", + err); + } ++ ++ hci_dev_unlock(hdev); + } + + static int iso_sock_recvmsg(struct socket *sock, struct msghdr *msg, +-- +2.43.0 + diff --git a/queue-6.12/bluetooth-iso-use-kref-to-track-lifetime-of-iso_conn.patch b/queue-6.12/bluetooth-iso-use-kref-to-track-lifetime-of-iso_conn.patch new file mode 100644 index 00000000000..fb8ff79d0d1 --- /dev/null +++ b/queue-6.12/bluetooth-iso-use-kref-to-track-lifetime-of-iso_conn.patch @@ -0,0 +1,211 @@ +From efa4949621f8021beb586b35f77521c49f6a6588 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 1 Oct 2024 16:15:51 -0400 +Subject: Bluetooth: ISO: Use kref to track lifetime of iso_conn + +From: Luiz Augusto von Dentz + +[ Upstream commit dc26097bdb864a0d5955b9a25e43376ffc1af99b ] + +This make use of kref to keep track of reference of iso_conn which +allows better tracking of its lifetime with usage of things like +kref_get_unless_zero in a similar way as used in l2cap_chan. + +In addition to it remove call to iso_sock_set_timer on iso_sock_disconn +since at that point it is useless to set a timer as the sk will be freed +there is nothing to be done in iso_sock_timeout. + +Fixes: ccf74f2390d6 ("Bluetooth: Add BTPROTO_ISO socket type") +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + net/bluetooth/iso.c | 88 ++++++++++++++++++++++++++++++++++++--------- + 1 file changed, 71 insertions(+), 17 deletions(-) + +diff --git a/net/bluetooth/iso.c b/net/bluetooth/iso.c +index 7a83e400ac77a..109bf58c982ae 100644 +--- a/net/bluetooth/iso.c ++++ b/net/bluetooth/iso.c +@@ -35,6 +35,7 @@ struct iso_conn { + struct sk_buff *rx_skb; + __u32 rx_len; + __u16 tx_sn; ++ struct kref ref; + }; + + #define iso_conn_lock(c) spin_lock(&(c)->lock) +@@ -93,6 +94,49 @@ static struct sock *iso_get_sock(bdaddr_t *src, bdaddr_t *dst, + #define ISO_CONN_TIMEOUT (HZ * 40) + #define ISO_DISCONN_TIMEOUT (HZ * 2) + ++static void iso_conn_free(struct kref *ref) ++{ ++ struct iso_conn *conn = container_of(ref, struct iso_conn, ref); ++ ++ BT_DBG("conn %p", conn); ++ ++ if (conn->sk) ++ iso_pi(conn->sk)->conn = NULL; ++ ++ if (conn->hcon) { ++ conn->hcon->iso_data = NULL; ++ hci_conn_drop(conn->hcon); ++ } ++ ++ /* Ensure no more work items will run since hci_conn has been dropped */ ++ disable_delayed_work_sync(&conn->timeout_work); ++ ++ kfree(conn); ++} ++ ++static void iso_conn_put(struct iso_conn *conn) ++{ ++ if (!conn) ++ return; ++ ++ BT_DBG("conn %p refcnt %d", conn, kref_read(&conn->ref)); ++ ++ kref_put(&conn->ref, iso_conn_free); ++} ++ ++static struct iso_conn *iso_conn_hold_unless_zero(struct iso_conn *conn) ++{ ++ if (!conn) ++ return NULL; ++ ++ BT_DBG("conn %p refcnt %u", conn, kref_read(&conn->ref)); ++ ++ if (!kref_get_unless_zero(&conn->ref)) ++ return NULL; ++ ++ return conn; ++} ++ + static struct sock *iso_sock_hold(struct iso_conn *conn) + { + if (!conn || !bt_sock_linked(&iso_sk_list, conn->sk)) +@@ -109,9 +153,14 @@ static void iso_sock_timeout(struct work_struct *work) + timeout_work.work); + struct sock *sk; + ++ conn = iso_conn_hold_unless_zero(conn); ++ if (!conn) ++ return; ++ + iso_conn_lock(conn); + sk = iso_sock_hold(conn); + iso_conn_unlock(conn); ++ iso_conn_put(conn); + + if (!sk) + return; +@@ -149,9 +198,14 @@ static struct iso_conn *iso_conn_add(struct hci_conn *hcon) + { + struct iso_conn *conn = hcon->iso_data; + ++ conn = iso_conn_hold_unless_zero(conn); + if (conn) { +- if (!conn->hcon) ++ if (!conn->hcon) { ++ iso_conn_lock(conn); + conn->hcon = hcon; ++ iso_conn_unlock(conn); ++ } ++ iso_conn_put(conn); + return conn; + } + +@@ -159,6 +213,7 @@ static struct iso_conn *iso_conn_add(struct hci_conn *hcon) + if (!conn) + return NULL; + ++ kref_init(&conn->ref); + spin_lock_init(&conn->lock); + INIT_DELAYED_WORK(&conn->timeout_work, iso_sock_timeout); + +@@ -178,17 +233,15 @@ static void iso_chan_del(struct sock *sk, int err) + struct sock *parent; + + conn = iso_pi(sk)->conn; ++ iso_pi(sk)->conn = NULL; + + BT_DBG("sk %p, conn %p, err %d", sk, conn, err); + + if (conn) { + iso_conn_lock(conn); + conn->sk = NULL; +- iso_pi(sk)->conn = NULL; + iso_conn_unlock(conn); +- +- if (conn->hcon) +- hci_conn_drop(conn->hcon); ++ iso_conn_put(conn); + } + + sk->sk_state = BT_CLOSED; +@@ -210,6 +263,7 @@ static void iso_conn_del(struct hci_conn *hcon, int err) + struct iso_conn *conn = hcon->iso_data; + struct sock *sk; + ++ conn = iso_conn_hold_unless_zero(conn); + if (!conn) + return; + +@@ -219,20 +273,18 @@ static void iso_conn_del(struct hci_conn *hcon, int err) + iso_conn_lock(conn); + sk = iso_sock_hold(conn); + iso_conn_unlock(conn); ++ iso_conn_put(conn); + +- if (sk) { +- lock_sock(sk); +- iso_sock_clear_timer(sk); +- iso_chan_del(sk, err); +- release_sock(sk); +- sock_put(sk); ++ if (!sk) { ++ iso_conn_put(conn); ++ return; + } + +- /* Ensure no more work items will run before freeing conn. */ +- cancel_delayed_work_sync(&conn->timeout_work); +- +- hcon->iso_data = NULL; +- kfree(conn); ++ lock_sock(sk); ++ iso_sock_clear_timer(sk); ++ iso_chan_del(sk, err); ++ release_sock(sk); ++ sock_put(sk); + } + + static int __iso_chan_add(struct iso_conn *conn, struct sock *sk, +@@ -652,6 +704,8 @@ static void iso_sock_destruct(struct sock *sk) + { + BT_DBG("sk %p", sk); + ++ iso_conn_put(iso_pi(sk)->conn); ++ + skb_queue_purge(&sk->sk_receive_queue); + skb_queue_purge(&sk->sk_write_queue); + } +@@ -711,6 +765,7 @@ static void iso_sock_disconn(struct sock *sk) + */ + if (bis_sk) { + hcon->state = BT_OPEN; ++ hcon->iso_data = NULL; + iso_pi(sk)->conn->hcon = NULL; + iso_sock_clear_timer(sk); + iso_chan_del(sk, bt_to_errno(hcon->abort_reason)); +@@ -720,7 +775,6 @@ static void iso_sock_disconn(struct sock *sk) + } + + sk->sk_state = BT_DISCONN; +- iso_sock_set_timer(sk, ISO_DISCONN_TIMEOUT); + iso_conn_lock(iso_pi(sk)->conn); + hci_conn_drop(iso_pi(sk)->conn->hcon); + iso_pi(sk)->conn->hcon = NULL; +-- +2.43.0 + diff --git a/queue-6.12/bluetooth-mgmt-fix-possible-deadlocks.patch b/queue-6.12/bluetooth-mgmt-fix-possible-deadlocks.patch new file mode 100644 index 00000000000..910ab3ac827 --- /dev/null +++ b/queue-6.12/bluetooth-mgmt-fix-possible-deadlocks.patch @@ -0,0 +1,150 @@ +From 5e2b19188589140cdfcd5cf8e6fa4949e6e96c9b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 21 Nov 2024 11:09:22 -0500 +Subject: Bluetooth: MGMT: Fix possible deadlocks + +From: Luiz Augusto von Dentz + +[ Upstream commit a66dfaf18fd61bb75ef8cee83db46b2aadf153d0 ] + +This fixes possible deadlocks like the following caused by +hci_cmd_sync_dequeue causing the destroy function to run: + + INFO: task kworker/u19:0:143 blocked for more than 120 seconds. + Tainted: G W O 6.8.0-2024-03-19-intel-next-iLS-24ww14 #1 + "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message. + task:kworker/u19:0 state:D stack:0 pid:143 tgid:143 ppid:2 flags:0x00004000 + Workqueue: hci0 hci_cmd_sync_work [bluetooth] + Call Trace: + + __schedule+0x374/0xaf0 + schedule+0x3c/0xf0 + schedule_preempt_disabled+0x1c/0x30 + __mutex_lock.constprop.0+0x3ef/0x7a0 + __mutex_lock_slowpath+0x13/0x20 + mutex_lock+0x3c/0x50 + mgmt_set_connectable_complete+0xa4/0x150 [bluetooth] + ? kfree+0x211/0x2a0 + hci_cmd_sync_dequeue+0xae/0x130 [bluetooth] + ? __pfx_cmd_complete_rsp+0x10/0x10 [bluetooth] + cmd_complete_rsp+0x26/0x80 [bluetooth] + mgmt_pending_foreach+0x4d/0x70 [bluetooth] + __mgmt_power_off+0x8d/0x180 [bluetooth] + ? _raw_spin_unlock_irq+0x23/0x40 + hci_dev_close_sync+0x445/0x5b0 [bluetooth] + hci_set_powered_sync+0x149/0x250 [bluetooth] + set_powered_sync+0x24/0x60 [bluetooth] + hci_cmd_sync_work+0x90/0x150 [bluetooth] + process_one_work+0x13e/0x300 + worker_thread+0x2f7/0x420 + ? __pfx_worker_thread+0x10/0x10 + kthread+0x107/0x140 + ? __pfx_kthread+0x10/0x10 + ret_from_fork+0x3d/0x60 + ? __pfx_kthread+0x10/0x10 + ret_from_fork_asm+0x1b/0x30 + + +Tested-by: Kiran K +Fixes: f53e1c9c726d ("Bluetooth: MGMT: Fix possible crash on mgmt_index_removed") +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + net/bluetooth/mgmt.c | 27 ++++++++++++++++++--------- + 1 file changed, 18 insertions(+), 9 deletions(-) + +diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c +index 37e9175be0576..2343e15f8938e 100644 +--- a/net/bluetooth/mgmt.c ++++ b/net/bluetooth/mgmt.c +@@ -1517,7 +1517,8 @@ static void mgmt_set_discoverable_complete(struct hci_dev *hdev, void *data, + bt_dev_dbg(hdev, "err %d", err); + + /* Make sure cmd still outstanding. */ +- if (cmd != pending_find(MGMT_OP_SET_DISCOVERABLE, hdev)) ++ if (err == -ECANCELED || ++ cmd != pending_find(MGMT_OP_SET_DISCOVERABLE, hdev)) + return; + + hci_dev_lock(hdev); +@@ -1691,7 +1692,8 @@ static void mgmt_set_connectable_complete(struct hci_dev *hdev, void *data, + bt_dev_dbg(hdev, "err %d", err); + + /* Make sure cmd still outstanding. */ +- if (cmd != pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) ++ if (err == -ECANCELED || ++ cmd != pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) + return; + + hci_dev_lock(hdev); +@@ -1923,7 +1925,7 @@ static void set_ssp_complete(struct hci_dev *hdev, void *data, int err) + bool changed; + + /* Make sure cmd still outstanding. */ +- if (cmd != pending_find(MGMT_OP_SET_SSP, hdev)) ++ if (err == -ECANCELED || cmd != pending_find(MGMT_OP_SET_SSP, hdev)) + return; + + if (err) { +@@ -3789,7 +3791,8 @@ static void set_name_complete(struct hci_dev *hdev, void *data, int err) + + bt_dev_dbg(hdev, "err %d", err); + +- if (cmd != pending_find(MGMT_OP_SET_LOCAL_NAME, hdev)) ++ if (err == -ECANCELED || ++ cmd != pending_find(MGMT_OP_SET_LOCAL_NAME, hdev)) + return; + + if (status) { +@@ -3964,7 +3967,8 @@ static void set_default_phy_complete(struct hci_dev *hdev, void *data, int err) + struct sk_buff *skb = cmd->skb; + u8 status = mgmt_status(err); + +- if (cmd != pending_find(MGMT_OP_SET_PHY_CONFIGURATION, hdev)) ++ if (err == -ECANCELED || ++ cmd != pending_find(MGMT_OP_SET_PHY_CONFIGURATION, hdev)) + return; + + if (!status) { +@@ -5855,13 +5859,16 @@ static void start_discovery_complete(struct hci_dev *hdev, void *data, int err) + { + struct mgmt_pending_cmd *cmd = data; + ++ bt_dev_dbg(hdev, "err %d", err); ++ ++ if (err == -ECANCELED) ++ return; ++ + if (cmd != pending_find(MGMT_OP_START_DISCOVERY, hdev) && + cmd != pending_find(MGMT_OP_START_LIMITED_DISCOVERY, hdev) && + cmd != pending_find(MGMT_OP_START_SERVICE_DISCOVERY, hdev)) + return; + +- bt_dev_dbg(hdev, "err %d", err); +- + mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, mgmt_status(err), + cmd->param, 1); + mgmt_pending_remove(cmd); +@@ -6094,7 +6101,8 @@ static void stop_discovery_complete(struct hci_dev *hdev, void *data, int err) + { + struct mgmt_pending_cmd *cmd = data; + +- if (cmd != pending_find(MGMT_OP_STOP_DISCOVERY, hdev)) ++ if (err == -ECANCELED || ++ cmd != pending_find(MGMT_OP_STOP_DISCOVERY, hdev)) + return; + + bt_dev_dbg(hdev, "err %d", err); +@@ -8085,7 +8093,8 @@ static void read_local_oob_ext_data_complete(struct hci_dev *hdev, void *data, + u8 status = mgmt_status(err); + u16 eir_len; + +- if (cmd != pending_find(MGMT_OP_READ_LOCAL_OOB_EXT_DATA, hdev)) ++ if (err == -ECANCELED || ++ cmd != pending_find(MGMT_OP_READ_LOCAL_OOB_EXT_DATA, hdev)) + return; + + if (!status) { +-- +2.43.0 + diff --git a/queue-6.12/bluetooth-mgmt-fix-slab-use-after-free-read-in-set_p.patch b/queue-6.12/bluetooth-mgmt-fix-slab-use-after-free-read-in-set_p.patch new file mode 100644 index 00000000000..2024d87f77b --- /dev/null +++ b/queue-6.12/bluetooth-mgmt-fix-slab-use-after-free-read-in-set_p.patch @@ -0,0 +1,126 @@ +From 42ab8ee1d39744de41857416b0e9418ec07e18a5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 15 Nov 2024 10:45:31 -0500 +Subject: Bluetooth: MGMT: Fix slab-use-after-free Read in set_powered_sync + +From: Luiz Augusto von Dentz + +[ Upstream commit 0b882940665ca2849386ee459d4331aa2f8c4e7d ] + +This fixes the following crash: + +================================================================== +BUG: KASAN: slab-use-after-free in set_powered_sync+0x3a/0xc0 net/bluetooth/mgmt.c:1353 +Read of size 8 at addr ffff888029b4dd18 by task kworker/u9:0/54 + +CPU: 1 UID: 0 PID: 54 Comm: kworker/u9:0 Not tainted 6.11.0-rc6-syzkaller-01155-gf723224742fc #0 +Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 08/06/2024 +Workqueue: hci0 hci_cmd_sync_work +Call Trace: + + __dump_stack lib/dump_stack.c:93 [inline] + dump_stack_lvl+0x241/0x360 lib/dump_stack.c:119 + print_address_description mm/kasan/report.c:377 [inline] + print_report+0x169/0x550 mm/kasan/report.c:488 +q kasan_report+0x143/0x180 mm/kasan/report.c:601 + set_powered_sync+0x3a/0xc0 net/bluetooth/mgmt.c:1353 + hci_cmd_sync_work+0x22b/0x400 net/bluetooth/hci_sync.c:328 + process_one_work kernel/workqueue.c:3231 [inline] + process_scheduled_works+0xa2c/0x1830 kernel/workqueue.c:3312 + worker_thread+0x86d/0xd10 kernel/workqueue.c:3389 + kthread+0x2f0/0x390 kernel/kthread.c:389 + ret_from_fork+0x4b/0x80 arch/x86/kernel/process.c:147 + ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:244 + + +Allocated by task 5247: + kasan_save_stack mm/kasan/common.c:47 [inline] + kasan_save_track+0x3f/0x80 mm/kasan/common.c:68 + poison_kmalloc_redzone mm/kasan/common.c:370 [inline] + __kasan_kmalloc+0x98/0xb0 mm/kasan/common.c:387 + kasan_kmalloc include/linux/kasan.h:211 [inline] + __kmalloc_cache_noprof+0x19c/0x2c0 mm/slub.c:4193 + kmalloc_noprof include/linux/slab.h:681 [inline] + kzalloc_noprof include/linux/slab.h:807 [inline] + mgmt_pending_new+0x65/0x250 net/bluetooth/mgmt_util.c:269 + mgmt_pending_add+0x36/0x120 net/bluetooth/mgmt_util.c:296 + set_powered+0x3cd/0x5e0 net/bluetooth/mgmt.c:1394 + hci_mgmt_cmd+0xc47/0x11d0 net/bluetooth/hci_sock.c:1712 + hci_sock_sendmsg+0x7b8/0x11c0 net/bluetooth/hci_sock.c:1832 + sock_sendmsg_nosec net/socket.c:730 [inline] + __sock_sendmsg+0x221/0x270 net/socket.c:745 + sock_write_iter+0x2dd/0x400 net/socket.c:1160 + new_sync_write fs/read_write.c:497 [inline] + vfs_write+0xa72/0xc90 fs/read_write.c:590 + ksys_write+0x1a0/0x2c0 fs/read_write.c:643 + do_syscall_x64 arch/x86/entry/common.c:52 [inline] + do_syscall_64+0xf3/0x230 arch/x86/entry/common.c:83 + entry_SYSCALL_64_after_hwframe+0x77/0x7f + +Freed by task 5246: + kasan_save_stack mm/kasan/common.c:47 [inline] + kasan_save_track+0x3f/0x80 mm/kasan/common.c:68 + kasan_save_free_info+0x40/0x50 mm/kasan/generic.c:579 + poison_slab_object+0xe0/0x150 mm/kasan/common.c:240 + __kasan_slab_free+0x37/0x60 mm/kasan/common.c:256 + kasan_slab_free include/linux/kasan.h:184 [inline] + slab_free_hook mm/slub.c:2256 [inline] + slab_free mm/slub.c:4477 [inline] + kfree+0x149/0x360 mm/slub.c:4598 + settings_rsp+0x2bc/0x390 net/bluetooth/mgmt.c:1443 + mgmt_pending_foreach+0xd1/0x130 net/bluetooth/mgmt_util.c:259 + __mgmt_power_off+0x112/0x420 net/bluetooth/mgmt.c:9455 + hci_dev_close_sync+0x665/0x11a0 net/bluetooth/hci_sync.c:5191 + hci_dev_do_close net/bluetooth/hci_core.c:483 [inline] + hci_dev_close+0x112/0x210 net/bluetooth/hci_core.c:508 + sock_do_ioctl+0x158/0x460 net/socket.c:1222 + sock_ioctl+0x629/0x8e0 net/socket.c:1341 + vfs_ioctl fs/ioctl.c:51 [inline] + __do_sys_ioctl fs/ioctl.c:907 [inline] + __se_sys_ioctl+0xfc/0x170 fs/ioctl.c:893 + do_syscall_x64 arch/x86/entry/common.c:52 [inline] + do_syscall_64+0xf3/0x230 arch/x86/entry/common.c:83gv + entry_SYSCALL_64_after_hwframe+0x77/0x7f + +Reported-by: syzbot+03d6270b6425df1605bf@syzkaller.appspotmail.com +Tested-by: syzbot+03d6270b6425df1605bf@syzkaller.appspotmail.com +Closes: https://syzkaller.appspot.com/bug?extid=03d6270b6425df1605bf +Fixes: 275f3f648702 ("Bluetooth: Fix not checking MGMT cmd pending queue") +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + net/bluetooth/mgmt.c | 11 +++++++++-- + 1 file changed, 9 insertions(+), 2 deletions(-) + +diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c +index a429661b676a8..37e9175be0576 100644 +--- a/net/bluetooth/mgmt.c ++++ b/net/bluetooth/mgmt.c +@@ -1317,7 +1317,8 @@ static void mgmt_set_powered_complete(struct hci_dev *hdev, void *data, int err) + struct mgmt_mode *cp; + + /* Make sure cmd still outstanding. */ +- if (cmd != pending_find(MGMT_OP_SET_POWERED, hdev)) ++ if (err == -ECANCELED || ++ cmd != pending_find(MGMT_OP_SET_POWERED, hdev)) + return; + + cp = cmd->param; +@@ -1350,7 +1351,13 @@ static void mgmt_set_powered_complete(struct hci_dev *hdev, void *data, int err) + static int set_powered_sync(struct hci_dev *hdev, void *data) + { + struct mgmt_pending_cmd *cmd = data; +- struct mgmt_mode *cp = cmd->param; ++ struct mgmt_mode *cp; ++ ++ /* Make sure cmd still outstanding. */ ++ if (cmd != pending_find(MGMT_OP_SET_POWERED, hdev)) ++ return -ECANCELED; ++ ++ cp = cmd->param; + + BT_DBG("%s", hdev->name); + +-- +2.43.0 + diff --git a/queue-6.12/bnxt_en-fix-queue-start-to-update-vnic-rss-table.patch b/queue-6.12/bnxt_en-fix-queue-start-to-update-vnic-rss-table.patch new file mode 100644 index 00000000000..9c7f2d60711 --- /dev/null +++ b/queue-6.12/bnxt_en-fix-queue-start-to-update-vnic-rss-table.patch @@ -0,0 +1,49 @@ +From 099585adf8c13fae85fd9db0fb395294fc4290f3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 22 Nov 2024 14:45:43 -0800 +Subject: bnxt_en: Fix queue start to update vnic RSS table + +From: Somnath Kotur + +[ Upstream commit 5ac066b7b062ee753a14557ea11bdc62364c8090 ] + +HWRM_RING_FREE followed by a HWRM_RING_ALLOC is not guaranteed to +have the same FW ring ID as before. So we must reinitialize the +RSS table with the correct ring IDs. Otherwise, traffic may not +resume properly if the restarted ring ID is stale. Since this +feature is only supported on P5_PLUS chips, we call +bnxt_vnic_set_rss_p5() to update the HW RSS table. + +Fixes: 2d694c27d32e ("bnxt_en: implement netdev_queue_mgmt_ops") +Cc: David Wei +Reviewed-by: Kalesh AP +Reviewed-by: Andy Gospodarek +Signed-off-by: Somnath Kotur +Signed-off-by: Michael Chan +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/broadcom/bnxt/bnxt.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c +index 20a8cb26bc0a6..908ce838eedbb 100644 +--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c ++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c +@@ -15231,6 +15231,13 @@ static int bnxt_queue_start(struct net_device *dev, void *qmem, int idx) + + for (i = 0; i <= BNXT_VNIC_NTUPLE; i++) { + vnic = &bp->vnic_info[i]; ++ ++ rc = bnxt_hwrm_vnic_set_rss_p5(bp, vnic, true); ++ if (rc) { ++ netdev_err(bp->dev, "hwrm vnic %d set rss failure rc: %d\n", ++ vnic->vnic_id, rc); ++ return rc; ++ } + vnic->mru = bp->dev->mtu + ETH_HLEN + VLAN_HLEN; + bnxt_hwrm_vnic_update(bp, vnic, + VNIC_UPDATE_REQ_ENABLES_MRU_VALID); +-- +2.43.0 + diff --git a/queue-6.12/bnxt_en-fix-receive-ring-space-parameters-when-xdp-i.patch b/queue-6.12/bnxt_en-fix-receive-ring-space-parameters-when-xdp-i.patch new file mode 100644 index 00000000000..2e9a1b4ccf9 --- /dev/null +++ b/queue-6.12/bnxt_en-fix-receive-ring-space-parameters-when-xdp-i.patch @@ -0,0 +1,91 @@ +From d74935cc4946ce6e46c8f6da50d84c49d1dc86d0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 22 Nov 2024 14:45:44 -0800 +Subject: bnxt_en: Fix receive ring space parameters when XDP is active + +From: Shravya KN + +[ Upstream commit 3051a77a09dfe3022aa012071346937fdf059033 ] + +The MTU setting at the time an XDP multi-buffer is attached +determines whether the aggregation ring will be used and the +rx_skb_func handler. This is done in bnxt_set_rx_skb_mode(). + +If the MTU is later changed, the aggregation ring setting may need +to be changed and it may become out-of-sync with the settings +initially done in bnxt_set_rx_skb_mode(). This may result in +random memory corruption and crashes as the HW may DMA data larger +than the allocated buffer size, such as: + +BUG: kernel NULL pointer dereference, address: 00000000000003c0 +PGD 0 P4D 0 +Oops: 0000 [#1] PREEMPT SMP NOPTI +CPU: 17 PID: 0 Comm: swapper/17 Kdump: loaded Tainted: G S OE 6.1.0-226bf9805506 #1 +Hardware name: Wiwynn Delta Lake PVT BZA.02601.0150/Delta Lake-Class1, BIOS F0E_3A12 08/26/2021 +RIP: 0010:bnxt_rx_pkt+0xe97/0x1ae0 [bnxt_en] +Code: 8b 95 70 ff ff ff 4c 8b 9d 48 ff ff ff 66 41 89 87 b4 00 00 00 e9 0b f7 ff ff 0f b7 43 0a 49 8b 95 a8 04 00 00 25 ff 0f 00 00 <0f> b7 14 42 48 c1 e2 06 49 03 95 a0 04 00 00 0f b6 42 33f +RSP: 0018:ffffa19f40cc0d18 EFLAGS: 00010202 +RAX: 00000000000001e0 RBX: ffff8e2c805c6100 RCX: 00000000000007ff +RDX: 0000000000000000 RSI: ffff8e2c271ab990 RDI: ffff8e2c84f12380 +RBP: ffffa19f40cc0e48 R08: 000000000001000d R09: 974ea2fcddfa4cbf +R10: 0000000000000000 R11: ffffa19f40cc0ff8 R12: ffff8e2c94b58980 +R13: ffff8e2c952d6600 R14: 0000000000000016 R15: ffff8e2c271ab990 +FS: 0000000000000000(0000) GS:ffff8e3b3f840000(0000) knlGS:0000000000000000 +CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +CR2: 00000000000003c0 CR3: 0000000e8580a004 CR4: 00000000007706e0 +DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 +DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 +PKRU: 55555554 +Call Trace: + + __bnxt_poll_work+0x1c2/0x3e0 [bnxt_en] + +To address the issue, we now call bnxt_set_rx_skb_mode() within +bnxt_change_mtu() to properly set the AGG rings configuration and +update rx_skb_func based on the new MTU value. +Additionally, BNXT_FLAG_NO_AGG_RINGS is cleared at the beginning of +bnxt_set_rx_skb_mode() to make sure it gets set or cleared based on +the current MTU. + +Fixes: 08450ea98ae9 ("bnxt_en: Fix max_mtu setting for multi-buf XDP") +Co-developed-by: Somnath Kotur +Signed-off-by: Somnath Kotur +Signed-off-by: Shravya KN +Signed-off-by: Michael Chan +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/broadcom/bnxt/bnxt.c | 10 +++++++++- + 1 file changed, 9 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c +index 908ce838eedbb..913acd80d6483 100644 +--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c ++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c +@@ -4558,7 +4558,7 @@ int bnxt_set_rx_skb_mode(struct bnxt *bp, bool page_mode) + struct net_device *dev = bp->dev; + + if (page_mode) { +- bp->flags &= ~BNXT_FLAG_AGG_RINGS; ++ bp->flags &= ~(BNXT_FLAG_AGG_RINGS | BNXT_FLAG_NO_AGG_RINGS); + bp->flags |= BNXT_FLAG_RX_PAGE_MODE; + + if (bp->xdp_prog->aux->xdp_has_frags) +@@ -14494,6 +14494,14 @@ static int bnxt_change_mtu(struct net_device *dev, int new_mtu) + bnxt_close_nic(bp, true, false); + + WRITE_ONCE(dev->mtu, new_mtu); ++ ++ /* MTU change may change the AGG ring settings if an XDP multi-buffer ++ * program is attached. We need to set the AGG rings settings and ++ * rx_skb_func accordingly. ++ */ ++ if (READ_ONCE(bp->xdp_prog)) ++ bnxt_set_rx_skb_mode(bp, true); ++ + bnxt_set_ring_params(bp); + + if (netif_running(dev)) +-- +2.43.0 + diff --git a/queue-6.12/bnxt_en-refactor-bnxt_ptp_init.patch b/queue-6.12/bnxt_en-refactor-bnxt_ptp_init.patch new file mode 100644 index 00000000000..3fbca72082c --- /dev/null +++ b/queue-6.12/bnxt_en-refactor-bnxt_ptp_init.patch @@ -0,0 +1,98 @@ +From 3293def5994a78cc6e5214560af0bdc9d18aa6ca Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 22 Nov 2024 14:45:45 -0800 +Subject: bnxt_en: Refactor bnxt_ptp_init() + +From: Michael Chan + +[ Upstream commit 1e9614cd956268e10a669c0593e7e54d03d0c087 ] + +Instead of passing the 2nd parameter phc_cfg to bnxt_ptp_init(). +Store it in bp->ptp_cfg so that the caller doesn't need to know what +the value should be. + +In the next patch, we'll need to call bnxt_ptp_init() in bnxt_resume() +and this will make it easier. + +Reviewed-by: Somnath Kotur +Reviewed-by: Pavan Chebbi +Reviewed-by: Kalesh AP +Signed-off-by: Michael Chan +Signed-off-by: Paolo Abeni +Stable-dep-of: 3661c05c54e8 ("bnxt_en: Unregister PTP during PCI shutdown and suspend") +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/broadcom/bnxt/bnxt.c | 6 +++--- + drivers/net/ethernet/broadcom/bnxt/bnxt_ptp.c | 4 ++-- + drivers/net/ethernet/broadcom/bnxt/bnxt_ptp.h | 3 ++- + 3 files changed, 7 insertions(+), 6 deletions(-) + +diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c +index 913acd80d6483..015ad2b0bcd1c 100644 +--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c ++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c +@@ -9053,7 +9053,6 @@ static int __bnxt_hwrm_ptp_qcfg(struct bnxt *bp) + struct hwrm_port_mac_ptp_qcfg_output *resp; + struct hwrm_port_mac_ptp_qcfg_input *req; + struct bnxt_ptp_cfg *ptp = bp->ptp_cfg; +- bool phc_cfg; + u8 flags; + int rc; + +@@ -9100,8 +9099,9 @@ static int __bnxt_hwrm_ptp_qcfg(struct bnxt *bp) + rc = -ENODEV; + goto exit; + } +- phc_cfg = (flags & PORT_MAC_PTP_QCFG_RESP_FLAGS_RTC_CONFIGURED) != 0; +- rc = bnxt_ptp_init(bp, phc_cfg); ++ ptp->rtc_configured = ++ (flags & PORT_MAC_PTP_QCFG_RESP_FLAGS_RTC_CONFIGURED) != 0; ++ rc = bnxt_ptp_init(bp); + if (rc) + netdev_warn(bp->dev, "PTP initialization failed.\n"); + exit: +diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_ptp.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_ptp.c +index fa514be876502..781225d3ba8ff 100644 +--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_ptp.c ++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_ptp.c +@@ -1024,7 +1024,7 @@ static void bnxt_ptp_free(struct bnxt *bp) + } + } + +-int bnxt_ptp_init(struct bnxt *bp, bool phc_cfg) ++int bnxt_ptp_init(struct bnxt *bp) + { + struct bnxt_ptp_cfg *ptp = bp->ptp_cfg; + int rc; +@@ -1047,7 +1047,7 @@ int bnxt_ptp_init(struct bnxt *bp, bool phc_cfg) + + if (BNXT_PTP_USE_RTC(bp)) { + bnxt_ptp_timecounter_init(bp, false); +- rc = bnxt_ptp_init_rtc(bp, phc_cfg); ++ rc = bnxt_ptp_init_rtc(bp, ptp->rtc_configured); + if (rc) + goto out; + } else { +diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_ptp.h b/drivers/net/ethernet/broadcom/bnxt/bnxt_ptp.h +index f322466ecad35..61e89bb2d2690 100644 +--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_ptp.h ++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_ptp.h +@@ -133,6 +133,7 @@ struct bnxt_ptp_cfg { + BNXT_PTP_MSG_PDELAY_REQ | \ + BNXT_PTP_MSG_PDELAY_RESP) + u8 tx_tstamp_en:1; ++ u8 rtc_configured:1; + int rx_filter; + u32 tstamp_filters; + +@@ -180,6 +181,6 @@ void bnxt_tx_ts_cmp(struct bnxt *bp, struct bnxt_napi *bnapi, + struct tx_ts_cmp *tscmp); + void bnxt_ptp_rtc_timecounter_init(struct bnxt_ptp_cfg *ptp, u64 ns); + int bnxt_ptp_init_rtc(struct bnxt *bp, bool phc_cfg); +-int bnxt_ptp_init(struct bnxt *bp, bool phc_cfg); ++int bnxt_ptp_init(struct bnxt *bp); + void bnxt_ptp_clear(struct bnxt *bp); + #endif +-- +2.43.0 + diff --git a/queue-6.12/bnxt_en-reserve-rings-after-pcie-aer-recovery-if-nic.patch b/queue-6.12/bnxt_en-reserve-rings-after-pcie-aer-recovery-if-nic.patch new file mode 100644 index 00000000000..61989526c89 --- /dev/null +++ b/queue-6.12/bnxt_en-reserve-rings-after-pcie-aer-recovery-if-nic.patch @@ -0,0 +1,54 @@ +From d321628cb426ddd9c776de1edc82a3dabbf1e5a2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 22 Nov 2024 14:45:41 -0800 +Subject: bnxt_en: Reserve rings after PCIe AER recovery if NIC interface is + down + +From: Saravanan Vajravel + +[ Upstream commit 5311598f7f3293683cdc761df71ae3469327332c ] + +After successful PCIe AER recovery, FW will reset all resource +reservations. If it is IF_UP, the driver will call bnxt_open() and +all resources will be reserved again. It it is IF_DOWN, we should +call bnxt_reserve_rings() so that we can reserve resources including +RoCE resources to allow RoCE to resume after AER. Without this +patch, RoCE fails to resume in this IF_DOWN scenario. + +Later, if it becomes IF_UP, bnxt_open() will see that resources have +been reserved and will not reserve again. + +Fixes: fb1e6e562b37 ("bnxt_en: Fix AER recovery.") +Reviewed-by: Somnath Kotur +Reviewed-by: Pavan Chebbi +Reviewed-by: Kashyap Desai +Signed-off-by: Saravanan Vajravel +Signed-off-by: Michael Chan +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/broadcom/bnxt/bnxt.c | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c +index 99d025b69079a..20a8cb26bc0a6 100644 +--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c ++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c +@@ -16232,8 +16232,12 @@ static void bnxt_io_resume(struct pci_dev *pdev) + rtnl_lock(); + + err = bnxt_hwrm_func_qcaps(bp); +- if (!err && netif_running(netdev)) +- err = bnxt_open(netdev); ++ if (!err) { ++ if (netif_running(netdev)) ++ err = bnxt_open(netdev); ++ else ++ err = bnxt_reserve_rings(bp, true); ++ } + + if (!err) + netif_device_attach(netdev); +-- +2.43.0 + diff --git a/queue-6.12/bnxt_en-set-backplane-link-modes-correctly-for-ethto.patch b/queue-6.12/bnxt_en-set-backplane-link-modes-correctly-for-ethto.patch new file mode 100644 index 00000000000..02a8a37521a --- /dev/null +++ b/queue-6.12/bnxt_en-set-backplane-link-modes-correctly-for-ethto.patch @@ -0,0 +1,58 @@ +From 14cb9691e1abfcab99d3c3143b0e07e52265fbe7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 22 Nov 2024 14:45:42 -0800 +Subject: bnxt_en: Set backplane link modes correctly for ethtool + +From: Shravya KN + +[ Upstream commit 5007991670941c132fb3bc0484c009cf4bcea30f ] + +Use the return value from bnxt_get_media() to determine the port and +link modes. bnxt_get_media() returns the proper BNXT_MEDIA_KR when +the PHY is backplane. This will correct the ethtool settings for +backplane devices. + +Fixes: 5d4e1bf60664 ("bnxt_en: extend media types to supported and autoneg modes") +Reviewed-by: Somnath Kotur +Signed-off-by: Shravya KN +Signed-off-by: Michael Chan +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c | 9 +++++++-- + 1 file changed, 7 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c +index f71cc8188b4e5..20ba14eb87e00 100644 +--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c ++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c +@@ -2838,19 +2838,24 @@ static int bnxt_get_link_ksettings(struct net_device *dev, + } + + base->port = PORT_NONE; +- if (link_info->media_type == PORT_PHY_QCFG_RESP_MEDIA_TYPE_TP) { ++ if (media == BNXT_MEDIA_TP) { + base->port = PORT_TP; + linkmode_set_bit(ETHTOOL_LINK_MODE_TP_BIT, + lk_ksettings->link_modes.supported); + linkmode_set_bit(ETHTOOL_LINK_MODE_TP_BIT, + lk_ksettings->link_modes.advertising); ++ } else if (media == BNXT_MEDIA_KR) { ++ linkmode_set_bit(ETHTOOL_LINK_MODE_Backplane_BIT, ++ lk_ksettings->link_modes.supported); ++ linkmode_set_bit(ETHTOOL_LINK_MODE_Backplane_BIT, ++ lk_ksettings->link_modes.advertising); + } else { + linkmode_set_bit(ETHTOOL_LINK_MODE_FIBRE_BIT, + lk_ksettings->link_modes.supported); + linkmode_set_bit(ETHTOOL_LINK_MODE_FIBRE_BIT, + lk_ksettings->link_modes.advertising); + +- if (link_info->media_type == PORT_PHY_QCFG_RESP_MEDIA_TYPE_DAC) ++ if (media == BNXT_MEDIA_CR) + base->port = PORT_DA; + else + base->port = PORT_FIBRE; +-- +2.43.0 + diff --git a/queue-6.12/bnxt_en-unregister-ptp-during-pci-shutdown-and-suspe.patch b/queue-6.12/bnxt_en-unregister-ptp-during-pci-shutdown-and-suspe.patch new file mode 100644 index 00000000000..afd1897c20e --- /dev/null +++ b/queue-6.12/bnxt_en-unregister-ptp-during-pci-shutdown-and-suspe.patch @@ -0,0 +1,66 @@ +From 593b6a4f00caa850694aecac2271bc4746d8b715 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 22 Nov 2024 14:45:46 -0800 +Subject: bnxt_en: Unregister PTP during PCI shutdown and suspend + +From: Michael Chan + +[ Upstream commit 3661c05c54e8db7064aa96a0774654740974dffc ] + +If we go through the PCI shutdown or suspend path, we shutdown the +NIC but PTP remains registered. If the kernel continues to run for +a little bit, the periodic PTP .do_aux_work() function may be called +and it will read the PHC from the BAR register. Since the device +has already been disabled, it will cause a PCIe completion timeout. +Fix it by calling bnxt_ptp_clear() in the PCI shutdown/suspend +handlers. bnxt_ptp_clear() will unregister from PTP and +.do_aux_work() will be canceled. + +In bnxt_resume(), we need to re-initialize PTP. + +Fixes: a521c8a01d26 ("bnxt_en: Move bnxt_ptp_init() from bnxt_open() back to bnxt_init_one()") +Cc: Richard Cochran +Reviewed-by: Somnath Kotur +Reviewed-by: Pavan Chebbi +Reviewed-by: Kalesh AP +Signed-off-by: Michael Chan +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/broadcom/bnxt/bnxt.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c +index 015ad2b0bcd1c..3d9ee91e1f8be 100644 +--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c ++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c +@@ -15999,6 +15999,7 @@ static void bnxt_shutdown(struct pci_dev *pdev) + if (netif_running(dev)) + dev_close(dev); + ++ bnxt_ptp_clear(bp); + bnxt_clear_int_mode(bp); + pci_disable_device(pdev); + +@@ -16026,6 +16027,7 @@ static int bnxt_suspend(struct device *device) + rc = bnxt_close(dev); + } + bnxt_hwrm_func_drv_unrgtr(bp); ++ bnxt_ptp_clear(bp); + pci_disable_device(bp->pdev); + bnxt_free_ctx_mem(bp); + rtnl_unlock(); +@@ -16069,6 +16071,10 @@ static int bnxt_resume(struct device *device) + if (bp->fw_crash_mem) + bnxt_hwrm_crash_dump_mem_cfg(bp); + ++ if (bnxt_ptp_init(bp)) { ++ kfree(bp->ptp_cfg); ++ bp->ptp_cfg = NULL; ++ } + bnxt_get_wol_settings(bp); + if (netif_running(dev)) { + rc = bnxt_open(dev); +-- +2.43.0 + diff --git a/queue-6.12/bpf-add-kernel-symbol-for-struct_ops-trampoline.patch b/queue-6.12/bpf-add-kernel-symbol-for-struct_ops-trampoline.patch new file mode 100644 index 00000000000..71b01e73ad8 --- /dev/null +++ b/queue-6.12/bpf-add-kernel-symbol-for-struct_ops-trampoline.patch @@ -0,0 +1,306 @@ +From 7bdb3167bccdd5888d898334d92a479f26af5b76 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 12 Nov 2024 22:58:49 +0800 +Subject: bpf: Add kernel symbol for struct_ops trampoline + +From: Xu Kuohai + +[ Upstream commit 7c8ce4ffb684676039b1ff9ff81c126794e8d88e ] + +Without kernel symbols for struct_ops trampoline, the unwinder may +produce unexpected stacktraces. + +For example, the x86 ORC and FP unwinders check if an IP is in kernel +text by verifying the presence of the IP's kernel symbol. When a +struct_ops trampoline address is encountered, the unwinder stops due +to the absence of symbol, resulting in an incomplete stacktrace that +consists only of direct and indirect child functions called from the +trampoline. + +The arm64 unwinder is another example. While the arm64 unwinder can +proceed across a struct_ops trampoline address, the corresponding +symbol name is displayed as "unknown", which is confusing. + +Thus, add kernel symbol for struct_ops trampoline. The name is +bpf___, where is the +type name of the struct_ops, and is the name of +the member that the trampoline is linked to. + +Below is a comparison of stacktraces captured on x86 by perf record, +before and after this patch. + +Before: +ffffffff8116545d __lock_acquire+0xad ([kernel.kallsyms]) +ffffffff81167fcc lock_acquire+0xcc ([kernel.kallsyms]) +ffffffff813088f4 __bpf_prog_enter+0x34 ([kernel.kallsyms]) + +After: +ffffffff811656bd __lock_acquire+0x30d ([kernel.kallsyms]) +ffffffff81167fcc lock_acquire+0xcc ([kernel.kallsyms]) +ffffffff81309024 __bpf_prog_enter+0x34 ([kernel.kallsyms]) +ffffffffc000d7e9 bpf__tcp_congestion_ops_cong_avoid+0x3e ([kernel.kallsyms]) +ffffffff81f250a5 tcp_ack+0x10d5 ([kernel.kallsyms]) +ffffffff81f27c66 tcp_rcv_established+0x3b6 ([kernel.kallsyms]) +ffffffff81f3ad03 tcp_v4_do_rcv+0x193 ([kernel.kallsyms]) +ffffffff81d65a18 __release_sock+0xd8 ([kernel.kallsyms]) +ffffffff81d65af4 release_sock+0x34 ([kernel.kallsyms]) +ffffffff81f15c4b tcp_sendmsg+0x3b ([kernel.kallsyms]) +ffffffff81f663d7 inet_sendmsg+0x47 ([kernel.kallsyms]) +ffffffff81d5ab40 sock_write_iter+0x160 ([kernel.kallsyms]) +ffffffff8149c67b vfs_write+0x3fb ([kernel.kallsyms]) +ffffffff8149caf6 ksys_write+0xc6 ([kernel.kallsyms]) +ffffffff8149cb5d __x64_sys_write+0x1d ([kernel.kallsyms]) +ffffffff81009200 x64_sys_call+0x1d30 ([kernel.kallsyms]) +ffffffff82232d28 do_syscall_64+0x68 ([kernel.kallsyms]) +ffffffff8240012f entry_SYSCALL_64_after_hwframe+0x76 ([kernel.kallsyms]) + +Fixes: 85d33df357b6 ("bpf: Introduce BPF_MAP_TYPE_STRUCT_OPS") +Signed-off-by: Xu Kuohai +Acked-by: Yonghong Song +Link: https://lore.kernel.org/r/20241112145849.3436772-4-xukuohai@huaweicloud.com +Signed-off-by: Alexei Starovoitov +Signed-off-by: Sasha Levin +--- + include/linux/bpf.h | 3 +- + kernel/bpf/bpf_struct_ops.c | 79 ++++++++++++++++++++++++++++++++++++- + kernel/bpf/dispatcher.c | 3 +- + kernel/bpf/trampoline.c | 9 ++++- + 4 files changed, 89 insertions(+), 5 deletions(-) + +diff --git a/include/linux/bpf.h b/include/linux/bpf.h +index e863b5d06043a..bc2e3dab0487e 100644 +--- a/include/linux/bpf.h ++++ b/include/linux/bpf.h +@@ -1373,7 +1373,8 @@ int arch_prepare_bpf_dispatcher(void *image, void *buf, s64 *funcs, int num_func + void bpf_dispatcher_change_prog(struct bpf_dispatcher *d, struct bpf_prog *from, + struct bpf_prog *to); + /* Called only from JIT-enabled code, so there's no need for stubs. */ +-void bpf_image_ksym_add(void *data, unsigned int size, struct bpf_ksym *ksym); ++void bpf_image_ksym_init(void *data, unsigned int size, struct bpf_ksym *ksym); ++void bpf_image_ksym_add(struct bpf_ksym *ksym); + void bpf_image_ksym_del(struct bpf_ksym *ksym); + void bpf_ksym_add(struct bpf_ksym *ksym); + void bpf_ksym_del(struct bpf_ksym *ksym); +diff --git a/kernel/bpf/bpf_struct_ops.c b/kernel/bpf/bpf_struct_ops.c +index 5058d1536c554..b3a2ce1e5e22e 100644 +--- a/kernel/bpf/bpf_struct_ops.c ++++ b/kernel/bpf/bpf_struct_ops.c +@@ -32,6 +32,8 @@ struct bpf_struct_ops_map { + * (in kvalue.data). + */ + struct bpf_link **links; ++ /* ksyms for bpf trampolines */ ++ struct bpf_ksym **ksyms; + u32 funcs_cnt; + u32 image_pages_cnt; + /* image_pages is an array of pages that has all the trampolines +@@ -586,6 +588,49 @@ int bpf_struct_ops_prepare_trampoline(struct bpf_tramp_links *tlinks, + return 0; + } + ++static void bpf_struct_ops_ksym_init(const char *tname, const char *mname, ++ void *image, unsigned int size, ++ struct bpf_ksym *ksym) ++{ ++ snprintf(ksym->name, KSYM_NAME_LEN, "bpf__%s_%s", tname, mname); ++ INIT_LIST_HEAD_RCU(&ksym->lnode); ++ bpf_image_ksym_init(image, size, ksym); ++} ++ ++static void bpf_struct_ops_map_add_ksyms(struct bpf_struct_ops_map *st_map) ++{ ++ u32 i; ++ ++ for (i = 0; i < st_map->funcs_cnt; i++) { ++ if (!st_map->ksyms[i]) ++ break; ++ bpf_image_ksym_add(st_map->ksyms[i]); ++ } ++} ++ ++static void bpf_struct_ops_map_del_ksyms(struct bpf_struct_ops_map *st_map) ++{ ++ u32 i; ++ ++ for (i = 0; i < st_map->funcs_cnt; i++) { ++ if (!st_map->ksyms[i]) ++ break; ++ bpf_image_ksym_del(st_map->ksyms[i]); ++ } ++} ++ ++static void bpf_struct_ops_map_free_ksyms(struct bpf_struct_ops_map *st_map) ++{ ++ u32 i; ++ ++ for (i = 0; i < st_map->funcs_cnt; i++) { ++ if (!st_map->ksyms[i]) ++ break; ++ kfree(st_map->ksyms[i]); ++ st_map->ksyms[i] = NULL; ++ } ++} ++ + static long bpf_struct_ops_map_update_elem(struct bpf_map *map, void *key, + void *value, u64 flags) + { +@@ -602,6 +647,8 @@ static long bpf_struct_ops_map_update_elem(struct bpf_map *map, void *key, + u32 i, trampoline_start, image_off = 0; + void *cur_image = NULL, *image = NULL; + struct bpf_link **plink; ++ struct bpf_ksym **pksym; ++ const char *tname, *mname; + + if (flags) + return -EINVAL; +@@ -641,14 +688,18 @@ static long bpf_struct_ops_map_update_elem(struct bpf_map *map, void *key, + kdata = &kvalue->data; + + plink = st_map->links; ++ pksym = st_map->ksyms; ++ tname = btf_name_by_offset(st_map->btf, t->name_off); + module_type = btf_type_by_id(btf_vmlinux, st_ops_ids[IDX_MODULE_ID]); + for_each_member(i, t, member) { + const struct btf_type *mtype, *ptype; + struct bpf_prog *prog; + struct bpf_tramp_link *link; ++ struct bpf_ksym *ksym; + u32 moff; + + moff = __btf_member_bit_offset(t, member) / 8; ++ mname = btf_name_by_offset(st_map->btf, member->name_off); + ptype = btf_type_resolve_ptr(st_map->btf, member->type, NULL); + if (ptype == module_type) { + if (*(void **)(udata + moff)) +@@ -718,6 +769,13 @@ static long bpf_struct_ops_map_update_elem(struct bpf_map *map, void *key, + &bpf_struct_ops_link_lops, prog); + *plink++ = &link->link; + ++ ksym = kzalloc(sizeof(*ksym), GFP_USER); ++ if (!ksym) { ++ err = -ENOMEM; ++ goto reset_unlock; ++ } ++ *pksym++ = ksym; ++ + trampoline_start = image_off; + err = bpf_struct_ops_prepare_trampoline(tlinks, link, + &st_ops->func_models[i], +@@ -737,6 +795,12 @@ static long bpf_struct_ops_map_update_elem(struct bpf_map *map, void *key, + + /* put prog_id to udata */ + *(unsigned long *)(udata + moff) = prog->aux->id; ++ ++ /* init ksym for this trampoline */ ++ bpf_struct_ops_ksym_init(tname, mname, ++ image + trampoline_start, ++ image_off - trampoline_start, ++ ksym); + } + + if (st_ops->validate) { +@@ -785,6 +849,7 @@ static long bpf_struct_ops_map_update_elem(struct bpf_map *map, void *key, + */ + + reset_unlock: ++ bpf_struct_ops_map_free_ksyms(st_map); + bpf_struct_ops_map_free_image(st_map); + bpf_struct_ops_map_put_progs(st_map); + memset(uvalue, 0, map->value_size); +@@ -792,6 +857,8 @@ static long bpf_struct_ops_map_update_elem(struct bpf_map *map, void *key, + unlock: + kfree(tlinks); + mutex_unlock(&st_map->lock); ++ if (!err) ++ bpf_struct_ops_map_add_ksyms(st_map); + return err; + } + +@@ -851,7 +918,10 @@ static void __bpf_struct_ops_map_free(struct bpf_map *map) + + if (st_map->links) + bpf_struct_ops_map_put_progs(st_map); ++ if (st_map->ksyms) ++ bpf_struct_ops_map_free_ksyms(st_map); + bpf_map_area_free(st_map->links); ++ bpf_map_area_free(st_map->ksyms); + bpf_struct_ops_map_free_image(st_map); + bpf_map_area_free(st_map->uvalue); + bpf_map_area_free(st_map); +@@ -868,6 +938,8 @@ static void bpf_struct_ops_map_free(struct bpf_map *map) + if (btf_is_module(st_map->btf)) + module_put(st_map->st_ops_desc->st_ops->owner); + ++ bpf_struct_ops_map_del_ksyms(st_map); ++ + /* The struct_ops's function may switch to another struct_ops. + * + * For example, bpf_tcp_cc_x->init() may switch to +@@ -980,7 +1052,11 @@ static struct bpf_map *bpf_struct_ops_map_alloc(union bpf_attr *attr) + st_map->links = + bpf_map_area_alloc(st_map->funcs_cnt * sizeof(struct bpf_link *), + NUMA_NO_NODE); +- if (!st_map->uvalue || !st_map->links) { ++ ++ st_map->ksyms = ++ bpf_map_area_alloc(st_map->funcs_cnt * sizeof(struct bpf_ksym *), ++ NUMA_NO_NODE); ++ if (!st_map->uvalue || !st_map->links || !st_map->ksyms) { + ret = -ENOMEM; + goto errout_free; + } +@@ -1010,6 +1086,7 @@ static u64 bpf_struct_ops_map_mem_usage(const struct bpf_map *map) + vt->size - sizeof(struct bpf_struct_ops_value); + usage += vt->size; + usage += st_map->funcs_cnt * sizeof(struct bpf_link *); ++ usage += st_map->funcs_cnt * sizeof(struct bpf_ksym *); + usage += PAGE_SIZE; + return usage; + } +diff --git a/kernel/bpf/dispatcher.c b/kernel/bpf/dispatcher.c +index 70fb82bf16370..b77db7413f8c7 100644 +--- a/kernel/bpf/dispatcher.c ++++ b/kernel/bpf/dispatcher.c +@@ -154,7 +154,8 @@ void bpf_dispatcher_change_prog(struct bpf_dispatcher *d, struct bpf_prog *from, + d->image = NULL; + goto out; + } +- bpf_image_ksym_add(d->image, PAGE_SIZE, &d->ksym); ++ bpf_image_ksym_init(d->image, PAGE_SIZE, &d->ksym); ++ bpf_image_ksym_add(&d->ksym); + } + + prev_num_progs = d->num_progs; +diff --git a/kernel/bpf/trampoline.c b/kernel/bpf/trampoline.c +index f8302a5ca400d..1166d9dd3e8b5 100644 +--- a/kernel/bpf/trampoline.c ++++ b/kernel/bpf/trampoline.c +@@ -115,10 +115,14 @@ bool bpf_prog_has_trampoline(const struct bpf_prog *prog) + (ptype == BPF_PROG_TYPE_LSM && eatype == BPF_LSM_MAC); + } + +-void bpf_image_ksym_add(void *data, unsigned int size, struct bpf_ksym *ksym) ++void bpf_image_ksym_init(void *data, unsigned int size, struct bpf_ksym *ksym) + { + ksym->start = (unsigned long) data; + ksym->end = ksym->start + size; ++} ++ ++void bpf_image_ksym_add(struct bpf_ksym *ksym) ++{ + bpf_ksym_add(ksym); + perf_event_ksymbol(PERF_RECORD_KSYMBOL_TYPE_BPF, ksym->start, + PAGE_SIZE, false, ksym->name); +@@ -377,7 +381,8 @@ static struct bpf_tramp_image *bpf_tramp_image_alloc(u64 key, int size) + ksym = &im->ksym; + INIT_LIST_HEAD_RCU(&ksym->lnode); + snprintf(ksym->name, KSYM_NAME_LEN, "bpf_trampoline_%llu", key); +- bpf_image_ksym_add(image, size, ksym); ++ bpf_image_ksym_init(image, size, ksym); ++ bpf_image_ksym_add(ksym); + return im; + + out_free_image: +-- +2.43.0 + diff --git a/queue-6.12/bpf-allow-return-values-0-and-1-for-kprobe-session.patch b/queue-6.12/bpf-allow-return-values-0-and-1-for-kprobe-session.patch new file mode 100644 index 00000000000..4c4643e775d --- /dev/null +++ b/queue-6.12/bpf-allow-return-values-0-and-1-for-kprobe-session.patch @@ -0,0 +1,45 @@ +From 6e5c2d600896776fcb7263ad221d03ea5cd43820 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 8 Nov 2024 14:45:32 +0100 +Subject: bpf: Allow return values 0 and 1 for kprobe session + +From: Jiri Olsa + +[ Upstream commit 17c4b65a24938c6dd79496cce5df15f70d9c253c ] + +The kprobe session program can return only 0 or 1, +instruct verifier to check for that. + +Fixes: 535a3692ba72 ("bpf: Add support for kprobe session attach") +Signed-off-by: Jiri Olsa +Signed-off-by: Andrii Nakryiko +Acked-by: Andrii Nakryiko +Link: https://lore.kernel.org/bpf/20241108134544.480660-2-jolsa@kernel.org +Signed-off-by: Sasha Levin +--- + kernel/bpf/verifier.c | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c +index 71a1877aac687..91317857ea3ee 100644 +--- a/kernel/bpf/verifier.c ++++ b/kernel/bpf/verifier.c +@@ -15988,6 +15988,15 @@ static int check_return_code(struct bpf_verifier_env *env, int regno, const char + return -ENOTSUPP; + } + break; ++ case BPF_PROG_TYPE_KPROBE: ++ switch (env->prog->expected_attach_type) { ++ case BPF_TRACE_KPROBE_SESSION: ++ range = retval_range(0, 1); ++ break; ++ default: ++ return 0; ++ } ++ break; + case BPF_PROG_TYPE_SK_LOOKUP: + range = retval_range(SK_DROP, SK_PASS); + break; +-- +2.43.0 + diff --git a/queue-6.12/bpf-arm64-remove-garbage-frame-for-struct_ops-trampo.patch b/queue-6.12/bpf-arm64-remove-garbage-frame-for-struct_ops-trampo.patch new file mode 100644 index 00000000000..8d3d7b22400 --- /dev/null +++ b/queue-6.12/bpf-arm64-remove-garbage-frame-for-struct_ops-trampo.patch @@ -0,0 +1,140 @@ +From e56620efaf3e992e19199694038751ddc5734d49 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 25 Oct 2024 16:52:20 +0800 +Subject: bpf, arm64: Remove garbage frame for struct_ops trampoline + +From: Xu Kuohai + +[ Upstream commit 87cb58aebdf7005661a07e9fd5a900f924d48c75 ] + +The callsite layout for arm64 fentry is: + +mov x9, lr +nop + +When a bpf prog is attached, the nop instruction is patched to a call +to bpf trampoline: + +mov x9, lr +bl + +So two return addresses are passed to bpf trampoline: the return address +for the traced function/prog, stored in x9, and the return address for +the bpf trampoline itself, stored in lr. To obtain a full and accurate +call stack, the bpf trampoline constructs two fake function frames using +x9 and lr. + +However, struct_ops progs are invoked directly as function callbacks, +meaning that x9 is not set as it is in the fentry callsite. In this case, +the frame constructed using x9 is garbage. The following stack trace for +struct_ops, captured by perf sampling, illustrates this issue, where +tcp_ack+0x404 is a garbage frame: + +ffffffc0801a04b4 bpf_prog_50992e55a0f655a9_bpf_cubic_cong_avoid+0x98 (bpf_prog_50992e55a0f655a9_bpf_cubic_cong_avoid) +ffffffc0801a228c [unknown] ([kernel.kallsyms]) // bpf trampoline +ffffffd08d362590 tcp_ack+0x798 ([kernel.kallsyms]) // caller for bpf trampoline +ffffffd08d3621fc tcp_ack+0x404 ([kernel.kallsyms]) // garbage frame +ffffffd08d36452c tcp_rcv_established+0x4ac ([kernel.kallsyms]) +ffffffd08d375c58 tcp_v4_do_rcv+0x1f0 ([kernel.kallsyms]) +ffffffd08d378630 tcp_v4_rcv+0xeb8 ([kernel.kallsyms]) + +To fix it, construct only one frame using lr for struct_ops. + +The above stack trace also indicates that there is no kernel symbol for +struct_ops bpf trampoline. This will be addressed in a follow-up patch. + +Fixes: efc9909fdce0 ("bpf, arm64: Add bpf trampoline for arm64") +Signed-off-by: Xu Kuohai +Acked-by: Puranjay Mohan +Tested-by: Puranjay Mohan +Link: https://lore.kernel.org/r/20241025085220.533949-1-xukuohai@huaweicloud.com +Signed-off-by: Alexei Starovoitov +Signed-off-by: Sasha Levin +--- + arch/arm64/net/bpf_jit_comp.c | 47 +++++++++++++++++++++++------------ + 1 file changed, 31 insertions(+), 16 deletions(-) + +diff --git a/arch/arm64/net/bpf_jit_comp.c b/arch/arm64/net/bpf_jit_comp.c +index 5db82bfc9dc11..27ef366363e4e 100644 +--- a/arch/arm64/net/bpf_jit_comp.c ++++ b/arch/arm64/net/bpf_jit_comp.c +@@ -2094,6 +2094,12 @@ static void restore_args(struct jit_ctx *ctx, int args_off, int nregs) + } + } + ++static bool is_struct_ops_tramp(const struct bpf_tramp_links *fentry_links) ++{ ++ return fentry_links->nr_links == 1 && ++ fentry_links->links[0]->link.type == BPF_LINK_TYPE_STRUCT_OPS; ++} ++ + /* Based on the x86's implementation of arch_prepare_bpf_trampoline(). + * + * bpf prog and function entry before bpf trampoline hooked: +@@ -2123,6 +2129,7 @@ static int prepare_trampoline(struct jit_ctx *ctx, struct bpf_tramp_image *im, + struct bpf_tramp_links *fmod_ret = &tlinks[BPF_TRAMP_MODIFY_RETURN]; + bool save_ret; + __le32 **branches = NULL; ++ bool is_struct_ops = is_struct_ops_tramp(fentry); + + /* trampoline stack layout: + * [ parent ip ] +@@ -2191,11 +2198,14 @@ static int prepare_trampoline(struct jit_ctx *ctx, struct bpf_tramp_image *im, + */ + emit_bti(A64_BTI_JC, ctx); + +- /* frame for parent function */ +- emit(A64_PUSH(A64_FP, A64_R(9), A64_SP), ctx); +- emit(A64_MOV(1, A64_FP, A64_SP), ctx); ++ /* x9 is not set for struct_ops */ ++ if (!is_struct_ops) { ++ /* frame for parent function */ ++ emit(A64_PUSH(A64_FP, A64_R(9), A64_SP), ctx); ++ emit(A64_MOV(1, A64_FP, A64_SP), ctx); ++ } + +- /* frame for patched function */ ++ /* frame for patched function for tracing, or caller for struct_ops */ + emit(A64_PUSH(A64_FP, A64_LR, A64_SP), ctx); + emit(A64_MOV(1, A64_FP, A64_SP), ctx); + +@@ -2289,19 +2299,24 @@ static int prepare_trampoline(struct jit_ctx *ctx, struct bpf_tramp_image *im, + /* reset SP */ + emit(A64_MOV(1, A64_SP, A64_FP), ctx); + +- /* pop frames */ +- emit(A64_POP(A64_FP, A64_LR, A64_SP), ctx); +- emit(A64_POP(A64_FP, A64_R(9), A64_SP), ctx); +- +- if (flags & BPF_TRAMP_F_SKIP_FRAME) { +- /* skip patched function, return to parent */ +- emit(A64_MOV(1, A64_LR, A64_R(9)), ctx); +- emit(A64_RET(A64_R(9)), ctx); ++ if (is_struct_ops) { ++ emit(A64_POP(A64_FP, A64_LR, A64_SP), ctx); ++ emit(A64_RET(A64_LR), ctx); + } else { +- /* return to patched function */ +- emit(A64_MOV(1, A64_R(10), A64_LR), ctx); +- emit(A64_MOV(1, A64_LR, A64_R(9)), ctx); +- emit(A64_RET(A64_R(10)), ctx); ++ /* pop frames */ ++ emit(A64_POP(A64_FP, A64_LR, A64_SP), ctx); ++ emit(A64_POP(A64_FP, A64_R(9), A64_SP), ctx); ++ ++ if (flags & BPF_TRAMP_F_SKIP_FRAME) { ++ /* skip patched function, return to parent */ ++ emit(A64_MOV(1, A64_LR, A64_R(9)), ctx); ++ emit(A64_RET(A64_R(9)), ctx); ++ } else { ++ /* return to patched function */ ++ emit(A64_MOV(1, A64_R(10), A64_LR), ctx); ++ emit(A64_MOV(1, A64_LR, A64_R(9)), ctx); ++ emit(A64_RET(A64_R(10)), ctx); ++ } + } + + kfree(branches); +-- +2.43.0 + diff --git a/queue-6.12/bpf-bpftool-fix-incorrect-disasm-pc.patch b/queue-6.12/bpf-bpftool-fix-incorrect-disasm-pc.patch new file mode 100644 index 00000000000..86c6a534939 --- /dev/null +++ b/queue-6.12/bpf-bpftool-fix-incorrect-disasm-pc.patch @@ -0,0 +1,163 @@ +From a0e0f102f09e59f71d73b439c7ffcf76349c61f2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 31 Oct 2024 23:28:44 +0800 +Subject: bpf, bpftool: Fix incorrect disasm pc + +From: Leon Hwang + +[ Upstream commit 4d99e509c161f8610de125202c648fa4acd00541 ] + +This patch addresses the bpftool issue "Wrong callq address displayed"[0]. + +The issue stemmed from an incorrect program counter (PC) value used during +disassembly with LLVM or libbfd. + +For LLVM: The PC argument must represent the actual address in the kernel +to compute the correct relative address. + +For libbfd: The relative address can be adjusted by adding func_ksym within +the custom info->print_address_func to yield the correct address. + +Links: +[0] https://github.com/libbpf/bpftool/issues/109 + +Changes: +v2 -> v3: + * Address comment from Quentin: + * Remove the typedef. + +v1 -> v2: + * Fix the broken libbfd disassembler. + +Fixes: e1947c750ffe ("bpftool: Refactor disassembler for JIT-ed programs") +Signed-off-by: Leon Hwang +Signed-off-by: Andrii Nakryiko +Tested-by: Quentin Monnet +Reviewed-by: Quentin Monnet +Acked-by: Yonghong Song +Link: https://lore.kernel.org/bpf/20241031152844.68817-1-leon.hwang@linux.dev +Signed-off-by: Sasha Levin +--- + tools/bpf/bpftool/jit_disasm.c | 40 ++++++++++++++++++++++++---------- + 1 file changed, 29 insertions(+), 11 deletions(-) + +diff --git a/tools/bpf/bpftool/jit_disasm.c b/tools/bpf/bpftool/jit_disasm.c +index 7b8d9ec89ebd3..c032d2c6ab6d5 100644 +--- a/tools/bpf/bpftool/jit_disasm.c ++++ b/tools/bpf/bpftool/jit_disasm.c +@@ -80,7 +80,8 @@ symbol_lookup_callback(__maybe_unused void *disasm_info, + static int + init_context(disasm_ctx_t *ctx, const char *arch, + __maybe_unused const char *disassembler_options, +- __maybe_unused unsigned char *image, __maybe_unused ssize_t len) ++ __maybe_unused unsigned char *image, __maybe_unused ssize_t len, ++ __maybe_unused __u64 func_ksym) + { + char *triple; + +@@ -109,12 +110,13 @@ static void destroy_context(disasm_ctx_t *ctx) + } + + static int +-disassemble_insn(disasm_ctx_t *ctx, unsigned char *image, ssize_t len, int pc) ++disassemble_insn(disasm_ctx_t *ctx, unsigned char *image, ssize_t len, int pc, ++ __u64 func_ksym) + { + char buf[256]; + int count; + +- count = LLVMDisasmInstruction(*ctx, image + pc, len - pc, pc, ++ count = LLVMDisasmInstruction(*ctx, image + pc, len - pc, func_ksym + pc, + buf, sizeof(buf)); + if (json_output) + printf_json(buf); +@@ -136,8 +138,21 @@ int disasm_init(void) + #ifdef HAVE_LIBBFD_SUPPORT + #define DISASM_SPACER "\t" + ++struct disasm_info { ++ struct disassemble_info info; ++ __u64 func_ksym; ++}; ++ ++static void disasm_print_addr(bfd_vma addr, struct disassemble_info *info) ++{ ++ struct disasm_info *dinfo = container_of(info, struct disasm_info, info); ++ ++ addr += dinfo->func_ksym; ++ generic_print_address(addr, info); ++} ++ + typedef struct { +- struct disassemble_info *info; ++ struct disasm_info *info; + disassembler_ftype disassemble; + bfd *bfdf; + } disasm_ctx_t; +@@ -215,7 +230,7 @@ static int fprintf_json_styled(void *out, + + static int init_context(disasm_ctx_t *ctx, const char *arch, + const char *disassembler_options, +- unsigned char *image, ssize_t len) ++ unsigned char *image, ssize_t len, __u64 func_ksym) + { + struct disassemble_info *info; + char tpath[PATH_MAX]; +@@ -238,12 +253,13 @@ static int init_context(disasm_ctx_t *ctx, const char *arch, + } + bfdf = ctx->bfdf; + +- ctx->info = malloc(sizeof(struct disassemble_info)); ++ ctx->info = malloc(sizeof(struct disasm_info)); + if (!ctx->info) { + p_err("mem alloc failed"); + goto err_close; + } +- info = ctx->info; ++ ctx->info->func_ksym = func_ksym; ++ info = &ctx->info->info; + + if (json_output) + init_disassemble_info_compat(info, stdout, +@@ -272,6 +288,7 @@ static int init_context(disasm_ctx_t *ctx, const char *arch, + info->disassembler_options = disassembler_options; + info->buffer = image; + info->buffer_length = len; ++ info->print_address_func = disasm_print_addr; + + disassemble_init_for_target(info); + +@@ -304,9 +321,10 @@ static void destroy_context(disasm_ctx_t *ctx) + + static int + disassemble_insn(disasm_ctx_t *ctx, __maybe_unused unsigned char *image, +- __maybe_unused ssize_t len, int pc) ++ __maybe_unused ssize_t len, int pc, ++ __maybe_unused __u64 func_ksym) + { +- return ctx->disassemble(pc, ctx->info); ++ return ctx->disassemble(pc, &ctx->info->info); + } + + int disasm_init(void) +@@ -331,7 +349,7 @@ int disasm_print_insn(unsigned char *image, ssize_t len, int opcodes, + if (!len) + return -1; + +- if (init_context(&ctx, arch, disassembler_options, image, len)) ++ if (init_context(&ctx, arch, disassembler_options, image, len, func_ksym)) + return -1; + + if (json_output) +@@ -360,7 +378,7 @@ int disasm_print_insn(unsigned char *image, ssize_t len, int opcodes, + printf("%4x:" DISASM_SPACER, pc); + } + +- count = disassemble_insn(&ctx, image, len, pc); ++ count = disassemble_insn(&ctx, image, len, pc, func_ksym); + + if (json_output) { + /* Operand array, was started in fprintf_json. Before +-- +2.43.0 + diff --git a/queue-6.12/bpf-fix-recursive-lock-when-verdict-program-return-s.patch b/queue-6.12/bpf-fix-recursive-lock-when-verdict-program-return-s.patch new file mode 100644 index 00000000000..5824209c84c --- /dev/null +++ b/queue-6.12/bpf-fix-recursive-lock-when-verdict-program-return-s.patch @@ -0,0 +1,66 @@ +From 1dd13d15808d1de4cf0b98b7fb34dba4ea507f70 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 18 Nov 2024 11:09:09 +0800 +Subject: bpf: fix recursive lock when verdict program return SK_PASS + +From: Jiayuan Chen + +[ Upstream commit 8ca2a1eeadf09862190b2810697702d803ceef2d ] + +When the stream_verdict program returns SK_PASS, it places the received skb +into its own receive queue, but a recursive lock eventually occurs, leading +to an operating system deadlock. This issue has been present since v6.9. + +''' +sk_psock_strp_data_ready + write_lock_bh(&sk->sk_callback_lock) + strp_data_ready + strp_read_sock + read_sock -> tcp_read_sock + strp_recv + cb.rcv_msg -> sk_psock_strp_read + # now stream_verdict return SK_PASS without peer sock assign + __SK_PASS = sk_psock_map_verd(SK_PASS, NULL) + sk_psock_verdict_apply + sk_psock_skb_ingress_self + sk_psock_skb_ingress_enqueue + sk_psock_data_ready + read_lock_bh(&sk->sk_callback_lock) <= dead lock + +''' + +This topic has been discussed before, but it has not been fixed. +Previous discussion: +https://lore.kernel.org/all/6684a5864ec86_403d20898@john.notmuch + +Fixes: 6648e613226e ("bpf, skmsg: Fix NULL pointer dereference in sk_psock_skb_ingress_enqueue") +Reported-by: Vincent Whitchurch +Signed-off-by: Jiayuan Chen +Signed-off-by: John Fastabend +Acked-by: Martin KaFai Lau +Link: https://patch.msgid.link/20241118030910.36230-2-mrpre@163.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/core/skmsg.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/net/core/skmsg.c b/net/core/skmsg.c +index b1dcbd3be89e1..e90fbab703b2d 100644 +--- a/net/core/skmsg.c ++++ b/net/core/skmsg.c +@@ -1117,9 +1117,9 @@ static void sk_psock_strp_data_ready(struct sock *sk) + if (tls_sw_has_ctx_rx(sk)) { + psock->saved_data_ready(sk); + } else { +- write_lock_bh(&sk->sk_callback_lock); ++ read_lock_bh(&sk->sk_callback_lock); + strp_data_ready(&psock->strp); +- write_unlock_bh(&sk->sk_callback_lock); ++ read_unlock_bh(&sk->sk_callback_lock); + } + } + rcu_read_unlock(); +-- +2.43.0 + diff --git a/queue-6.12/bpf-fix-the-xdp_adjust_tail-sample-prog-issue.patch b/queue-6.12/bpf-fix-the-xdp_adjust_tail-sample-prog-issue.patch new file mode 100644 index 00000000000..3700be6f8a1 --- /dev/null +++ b/queue-6.12/bpf-fix-the-xdp_adjust_tail-sample-prog-issue.patch @@ -0,0 +1,41 @@ +From ab29ca534d98528135a487922df84e873a3690a3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 30 Sep 2024 10:41:15 +0800 +Subject: bpf: Fix the xdp_adjust_tail sample prog issue + +From: Yuan Chen + +[ Upstream commit 4236f114a3ffbbfd217436c08852e94cae372f57 ] + +During the xdp_adjust_tail test, probabilistic failure occurs and SKB package +is discarded by the kernel. After checking the issues by tracking SKB package, +it is identified that they were caused by checksum errors. Refer to checksum +of the arch/arm64/include/asm/checksum.h for fixing. + +v2: Based on Alexei Starovoitov's suggestions, it is necessary to keep the code + implementation consistent. + +Fixes: c6ffd1ff7856 (bpf: add bpf_xdp_adjust_tail sample prog) +Signed-off-by: Yuan Chen +Signed-off-by: Andrii Nakryiko +Link: https://lore.kernel.org/bpf/20240930024115.52841-1-chenyuan_fl@163.com +Signed-off-by: Sasha Levin +--- + samples/bpf/xdp_adjust_tail_kern.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/samples/bpf/xdp_adjust_tail_kern.c b/samples/bpf/xdp_adjust_tail_kern.c +index ffdd548627f0a..da67bcad1c638 100644 +--- a/samples/bpf/xdp_adjust_tail_kern.c ++++ b/samples/bpf/xdp_adjust_tail_kern.c +@@ -57,6 +57,7 @@ static __always_inline void swap_mac(void *data, struct ethhdr *orig_eth) + + static __always_inline __u16 csum_fold_helper(__u32 csum) + { ++ csum = (csum & 0xffff) + (csum >> 16); + return ~((csum & 0xffff) + (csum >> 16)); + } + +-- +2.43.0 + diff --git a/queue-6.12/bpf-force-uprobe-bpf-program-to-always-return-0.patch b/queue-6.12/bpf-force-uprobe-bpf-program-to-always-return-0.patch new file mode 100644 index 00000000000..b7dfe0fdaa1 --- /dev/null +++ b/queue-6.12/bpf-force-uprobe-bpf-program-to-always-return-0.patch @@ -0,0 +1,59 @@ +From f21baf015f31bc28f452836b1abe5fb6d533dbf9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 8 Nov 2024 14:45:33 +0100 +Subject: bpf: Force uprobe bpf program to always return 0 + +From: Jiri Olsa + +[ Upstream commit f505005bc7426f4309880da94cfbfc37efa225bd ] + +As suggested by Andrii make uprobe multi bpf programs to always return 0, +so they can't force uprobe removal. + +Keeping the int return type for uprobe_prog_run, because it will be used +in following session changes. + +Fixes: 89ae89f53d20 ("bpf: Add multi uprobe link") +Suggested-by: Andrii Nakryiko +Signed-off-by: Jiri Olsa +Signed-off-by: Andrii Nakryiko +Acked-by: Andrii Nakryiko +Link: https://lore.kernel.org/bpf/20241108134544.480660-3-jolsa@kernel.org +Signed-off-by: Sasha Levin +--- + kernel/trace/bpf_trace.c | 5 ++--- + 1 file changed, 2 insertions(+), 3 deletions(-) + +diff --git a/kernel/trace/bpf_trace.c b/kernel/trace/bpf_trace.c +index 630b763e52402..792dc35414a3c 100644 +--- a/kernel/trace/bpf_trace.c ++++ b/kernel/trace/bpf_trace.c +@@ -3205,7 +3205,6 @@ static int uprobe_prog_run(struct bpf_uprobe *uprobe, + struct bpf_prog *prog = link->link.prog; + bool sleepable = prog->sleepable; + struct bpf_run_ctx *old_run_ctx; +- int err = 0; + + if (link->task && !same_thread_group(current, link->task)) + return 0; +@@ -3218,7 +3217,7 @@ static int uprobe_prog_run(struct bpf_uprobe *uprobe, + migrate_disable(); + + old_run_ctx = bpf_set_run_ctx(&run_ctx.run_ctx); +- err = bpf_prog_run(link->link.prog, regs); ++ bpf_prog_run(link->link.prog, regs); + bpf_reset_run_ctx(old_run_ctx); + + migrate_enable(); +@@ -3227,7 +3226,7 @@ static int uprobe_prog_run(struct bpf_uprobe *uprobe, + rcu_read_unlock_trace(); + else + rcu_read_unlock(); +- return err; ++ return 0; + } + + static bool +-- +2.43.0 + diff --git a/queue-6.12/bpf-mark-raw_tp-arguments-with-ptr_maybe_null.patch b/queue-6.12/bpf-mark-raw_tp-arguments-with-ptr_maybe_null.patch new file mode 100644 index 00000000000..b7885fda878 --- /dev/null +++ b/queue-6.12/bpf-mark-raw_tp-arguments-with-ptr_maybe_null.patch @@ -0,0 +1,362 @@ +From b9107bac01d2722320c79dc695b6c8b9119bacbe Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 4 Nov 2024 09:19:57 -0800 +Subject: bpf: Mark raw_tp arguments with PTR_MAYBE_NULL + +From: Kumar Kartikeya Dwivedi + +[ Upstream commit cb4158ce8ec8a5bb528cc1693356a5eb8058094d ] + +Arguments to a raw tracepoint are tagged as trusted, which carries the +semantics that the pointer will be non-NULL. However, in certain cases, +a raw tracepoint argument may end up being NULL. More context about this +issue is available in [0]. + +Thus, there is a discrepancy between the reality, that raw_tp arguments +can actually be NULL, and the verifier's knowledge, that they are never +NULL, causing explicit NULL checks to be deleted, and accesses to such +pointers potentially crashing the kernel. + +To fix this, mark raw_tp arguments as PTR_MAYBE_NULL, and then special +case the dereference and pointer arithmetic to permit it, and allow +passing them into helpers/kfuncs; these exceptions are made for raw_tp +programs only. Ensure that we don't do this when ref_obj_id > 0, as in +that case this is an acquired object and doesn't need such adjustment. + +The reason we do mask_raw_tp_trusted_reg logic is because other will +recheck in places whether the register is a trusted_reg, and then +consider our register as untrusted when detecting the presence of the +PTR_MAYBE_NULL flag. + +To allow safe dereference, we enable PROBE_MEM marking when we see loads +into trusted pointers with PTR_MAYBE_NULL. + +While trusted raw_tp arguments can also be passed into helpers or kfuncs +where such broken assumption may cause issues, a future patch set will +tackle their case separately, as PTR_TO_BTF_ID (without PTR_TRUSTED) can +already be passed into helpers and causes similar problems. Thus, they +are left alone for now. + +It is possible that these checks also permit passing non-raw_tp args +that are trusted PTR_TO_BTF_ID with null marking. In such a case, +allowing dereference when pointer is NULL expands allowed behavior, so +won't regress existing programs, and the case of passing these into +helpers is the same as above and will be dealt with later. + +Also update the failure case in tp_btf_nullable selftest to capture the +new behavior, as the verifier will no longer cause an error when +directly dereference a raw tracepoint argument marked as __nullable. + + [0]: https://lore.kernel.org/bpf/ZrCZS6nisraEqehw@jlelli-thinkpadt14gen4.remote.csb + +Reviewed-by: Jiri Olsa +Reported-by: Juri Lelli +Tested-by: Juri Lelli +Fixes: 3f00c5239344 ("bpf: Allow trusted pointers to be passed to KF_TRUSTED_ARGS kfuncs") +Signed-off-by: Kumar Kartikeya Dwivedi +Link: https://lore.kernel.org/r/20241104171959.2938862-2-memxor@gmail.com +Signed-off-by: Alexei Starovoitov +Signed-off-by: Sasha Levin +--- + include/linux/bpf.h | 6 ++ + kernel/bpf/btf.c | 5 +- + kernel/bpf/verifier.c | 79 +++++++++++++++++-- + .../bpf/progs/test_tp_btf_nullable.c | 6 +- + 4 files changed, 87 insertions(+), 9 deletions(-) + +diff --git a/include/linux/bpf.h b/include/linux/bpf.h +index bdadb0bb6cecd..e863b5d06043a 100644 +--- a/include/linux/bpf.h ++++ b/include/linux/bpf.h +@@ -3461,4 +3461,10 @@ static inline bool bpf_is_subprog(const struct bpf_prog *prog) + return prog->aux->func_idx != 0; + } + ++static inline bool bpf_prog_is_raw_tp(const struct bpf_prog *prog) ++{ ++ return prog->type == BPF_PROG_TYPE_TRACING && ++ prog->expected_attach_type == BPF_TRACE_RAW_TP; ++} ++ + #endif /* _LINUX_BPF_H */ +diff --git a/kernel/bpf/btf.c b/kernel/bpf/btf.c +index 5cd1c7a23848c..346826e3c933d 100644 +--- a/kernel/bpf/btf.c ++++ b/kernel/bpf/btf.c +@@ -6564,7 +6564,10 @@ bool btf_ctx_access(int off, int size, enum bpf_access_type type, + if (prog_args_trusted(prog)) + info->reg_type |= PTR_TRUSTED; + +- if (btf_param_match_suffix(btf, &args[arg], "__nullable")) ++ /* Raw tracepoint arguments always get marked as maybe NULL */ ++ if (bpf_prog_is_raw_tp(prog)) ++ info->reg_type |= PTR_MAYBE_NULL; ++ else if (btf_param_match_suffix(btf, &args[arg], "__nullable")) + info->reg_type |= PTR_MAYBE_NULL; + + if (tgt_prog) { +diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c +index 011b4a86e2b3b..71a1877aac687 100644 +--- a/kernel/bpf/verifier.c ++++ b/kernel/bpf/verifier.c +@@ -418,6 +418,25 @@ static struct btf_record *reg_btf_record(const struct bpf_reg_state *reg) + return rec; + } + ++static bool mask_raw_tp_reg_cond(const struct bpf_verifier_env *env, struct bpf_reg_state *reg) { ++ return reg->type == (PTR_TO_BTF_ID | PTR_TRUSTED | PTR_MAYBE_NULL) && ++ bpf_prog_is_raw_tp(env->prog) && !reg->ref_obj_id; ++} ++ ++static bool mask_raw_tp_reg(const struct bpf_verifier_env *env, struct bpf_reg_state *reg) ++{ ++ if (!mask_raw_tp_reg_cond(env, reg)) ++ return false; ++ reg->type &= ~PTR_MAYBE_NULL; ++ return true; ++} ++ ++static void unmask_raw_tp_reg(struct bpf_reg_state *reg, bool result) ++{ ++ if (result) ++ reg->type |= PTR_MAYBE_NULL; ++} ++ + static bool subprog_is_global(const struct bpf_verifier_env *env, int subprog) + { + struct bpf_func_info_aux *aux = env->prog->aux->func_info_aux; +@@ -6595,6 +6614,7 @@ static int check_ptr_to_btf_access(struct bpf_verifier_env *env, + const char *field_name = NULL; + enum bpf_type_flag flag = 0; + u32 btf_id = 0; ++ bool mask; + int ret; + + if (!env->allow_ptr_leaks) { +@@ -6666,7 +6686,21 @@ static int check_ptr_to_btf_access(struct bpf_verifier_env *env, + + if (ret < 0) + return ret; +- ++ /* For raw_tp progs, we allow dereference of PTR_MAYBE_NULL ++ * trusted PTR_TO_BTF_ID, these are the ones that are possibly ++ * arguments to the raw_tp. Since internal checks in for trusted ++ * reg in check_ptr_to_btf_access would consider PTR_MAYBE_NULL ++ * modifier as problematic, mask it out temporarily for the ++ * check. Don't apply this to pointers with ref_obj_id > 0, as ++ * those won't be raw_tp args. ++ * ++ * We may end up applying this relaxation to other trusted ++ * PTR_TO_BTF_ID with maybe null flag, since we cannot ++ * distinguish PTR_MAYBE_NULL tagged for arguments vs normal ++ * tagging, but that should expand allowed behavior, and not ++ * cause regression for existing behavior. ++ */ ++ mask = mask_raw_tp_reg(env, reg); + if (ret != PTR_TO_BTF_ID) { + /* just mark; */ + +@@ -6727,8 +6761,13 @@ static int check_ptr_to_btf_access(struct bpf_verifier_env *env, + clear_trusted_flags(&flag); + } + +- if (atype == BPF_READ && value_regno >= 0) ++ if (atype == BPF_READ && value_regno >= 0) { + mark_btf_ld_reg(env, regs, value_regno, ret, reg->btf, btf_id, flag); ++ /* We've assigned a new type to regno, so don't undo masking. */ ++ if (regno == value_regno) ++ mask = false; ++ } ++ unmask_raw_tp_reg(reg, mask); + + return 0; + } +@@ -7103,7 +7142,7 @@ static int check_mem_access(struct bpf_verifier_env *env, int insn_idx, u32 regn + if (!err && t == BPF_READ && value_regno >= 0) + mark_reg_unknown(env, regs, value_regno); + } else if (base_type(reg->type) == PTR_TO_BTF_ID && +- !type_may_be_null(reg->type)) { ++ (mask_raw_tp_reg_cond(env, reg) || !type_may_be_null(reg->type))) { + err = check_ptr_to_btf_access(env, regs, regno, off, size, t, + value_regno); + } else if (reg->type == CONST_PTR_TO_MAP) { +@@ -8796,6 +8835,7 @@ static int check_func_arg(struct bpf_verifier_env *env, u32 arg, + enum bpf_reg_type type = reg->type; + u32 *arg_btf_id = NULL; + int err = 0; ++ bool mask; + + if (arg_type == ARG_DONTCARE) + return 0; +@@ -8836,11 +8876,11 @@ static int check_func_arg(struct bpf_verifier_env *env, u32 arg, + base_type(arg_type) == ARG_PTR_TO_SPIN_LOCK) + arg_btf_id = fn->arg_btf_id[arg]; + ++ mask = mask_raw_tp_reg(env, reg); + err = check_reg_type(env, regno, arg_type, arg_btf_id, meta); +- if (err) +- return err; + +- err = check_func_arg_reg_off(env, reg, regno, arg_type); ++ err = err ?: check_func_arg_reg_off(env, reg, regno, arg_type); ++ unmask_raw_tp_reg(reg, mask); + if (err) + return err; + +@@ -9635,14 +9675,17 @@ static int btf_check_func_arg_match(struct bpf_verifier_env *env, int subprog, + return ret; + } else if (base_type(arg->arg_type) == ARG_PTR_TO_BTF_ID) { + struct bpf_call_arg_meta meta; ++ bool mask; + int err; + + if (register_is_null(reg) && type_may_be_null(arg->arg_type)) + continue; + + memset(&meta, 0, sizeof(meta)); /* leave func_id as zero */ ++ mask = mask_raw_tp_reg(env, reg); + err = check_reg_type(env, regno, arg->arg_type, &arg->btf_id, &meta); + err = err ?: check_func_arg_reg_off(env, reg, regno, arg->arg_type); ++ unmask_raw_tp_reg(reg, mask); + if (err) + return err; + } else { +@@ -11957,6 +12000,7 @@ static int check_kfunc_args(struct bpf_verifier_env *env, struct bpf_kfunc_call_ + enum bpf_arg_type arg_type = ARG_DONTCARE; + u32 regno = i + 1, ref_id, type_size; + bool is_ret_buf_sz = false; ++ bool mask = false; + int kf_arg_type; + + t = btf_type_skip_modifiers(btf, args[i].type, NULL); +@@ -12015,12 +12059,15 @@ static int check_kfunc_args(struct bpf_verifier_env *env, struct bpf_kfunc_call_ + return -EINVAL; + } + ++ mask = mask_raw_tp_reg(env, reg); + if ((is_kfunc_trusted_args(meta) || is_kfunc_rcu(meta)) && + (register_is_null(reg) || type_may_be_null(reg->type)) && + !is_kfunc_arg_nullable(meta->btf, &args[i])) { + verbose(env, "Possibly NULL pointer passed to trusted arg%d\n", i); ++ unmask_raw_tp_reg(reg, mask); + return -EACCES; + } ++ unmask_raw_tp_reg(reg, mask); + + if (reg->ref_obj_id) { + if (is_kfunc_release(meta) && meta->ref_obj_id) { +@@ -12078,16 +12125,24 @@ static int check_kfunc_args(struct bpf_verifier_env *env, struct bpf_kfunc_call_ + if (!is_kfunc_trusted_args(meta) && !is_kfunc_rcu(meta)) + break; + ++ /* Allow passing maybe NULL raw_tp arguments to ++ * kfuncs for compatibility. Don't apply this to ++ * arguments with ref_obj_id > 0. ++ */ ++ mask = mask_raw_tp_reg(env, reg); + if (!is_trusted_reg(reg)) { + if (!is_kfunc_rcu(meta)) { + verbose(env, "R%d must be referenced or trusted\n", regno); ++ unmask_raw_tp_reg(reg, mask); + return -EINVAL; + } + if (!is_rcu_reg(reg)) { + verbose(env, "R%d must be a rcu pointer\n", regno); ++ unmask_raw_tp_reg(reg, mask); + return -EINVAL; + } + } ++ unmask_raw_tp_reg(reg, mask); + fallthrough; + case KF_ARG_PTR_TO_CTX: + case KF_ARG_PTR_TO_DYNPTR: +@@ -12110,7 +12165,9 @@ static int check_kfunc_args(struct bpf_verifier_env *env, struct bpf_kfunc_call_ + + if (is_kfunc_release(meta) && reg->ref_obj_id) + arg_type |= OBJ_RELEASE; ++ mask = mask_raw_tp_reg(env, reg); + ret = check_func_arg_reg_off(env, reg, regno, arg_type); ++ unmask_raw_tp_reg(reg, mask); + if (ret < 0) + return ret; + +@@ -12287,6 +12344,7 @@ static int check_kfunc_args(struct bpf_verifier_env *env, struct bpf_kfunc_call_ + ref_tname = btf_name_by_offset(btf, ref_t->name_off); + fallthrough; + case KF_ARG_PTR_TO_BTF_ID: ++ mask = mask_raw_tp_reg(env, reg); + /* Only base_type is checked, further checks are done here */ + if ((base_type(reg->type) != PTR_TO_BTF_ID || + (bpf_type_has_unsafe_modifiers(reg->type) && !is_rcu_reg(reg))) && +@@ -12295,9 +12353,11 @@ static int check_kfunc_args(struct bpf_verifier_env *env, struct bpf_kfunc_call_ + verbose(env, "expected %s or socket\n", + reg_type_str(env, base_type(reg->type) | + (type_flag(reg->type) & BPF_REG_TRUSTED_MODIFIERS))); ++ unmask_raw_tp_reg(reg, mask); + return -EINVAL; + } + ret = process_kf_arg_ptr_to_btf_id(env, reg, ref_t, ref_tname, ref_id, meta, i); ++ unmask_raw_tp_reg(reg, mask); + if (ret < 0) + return ret; + break; +@@ -13267,7 +13327,7 @@ static int sanitize_check_bounds(struct bpf_verifier_env *env, + */ + static int adjust_ptr_min_max_vals(struct bpf_verifier_env *env, + struct bpf_insn *insn, +- const struct bpf_reg_state *ptr_reg, ++ struct bpf_reg_state *ptr_reg, + const struct bpf_reg_state *off_reg) + { + struct bpf_verifier_state *vstate = env->cur_state; +@@ -13281,6 +13341,7 @@ static int adjust_ptr_min_max_vals(struct bpf_verifier_env *env, + struct bpf_sanitize_info info = {}; + u8 opcode = BPF_OP(insn->code); + u32 dst = insn->dst_reg; ++ bool mask; + int ret; + + dst_reg = ®s[dst]; +@@ -13307,11 +13368,14 @@ static int adjust_ptr_min_max_vals(struct bpf_verifier_env *env, + return -EACCES; + } + ++ mask = mask_raw_tp_reg(env, ptr_reg); + if (ptr_reg->type & PTR_MAYBE_NULL) { + verbose(env, "R%d pointer arithmetic on %s prohibited, null-check it first\n", + dst, reg_type_str(env, ptr_reg->type)); ++ unmask_raw_tp_reg(ptr_reg, mask); + return -EACCES; + } ++ unmask_raw_tp_reg(ptr_reg, mask); + + switch (base_type(ptr_reg->type)) { + case PTR_TO_CTX: +@@ -19852,6 +19916,7 @@ static int convert_ctx_accesses(struct bpf_verifier_env *env) + * for this case. + */ + case PTR_TO_BTF_ID | MEM_ALLOC | PTR_UNTRUSTED: ++ case PTR_TO_BTF_ID | PTR_TRUSTED | PTR_MAYBE_NULL: + if (type == BPF_READ) { + if (BPF_MODE(insn->code) == BPF_MEM) + insn->code = BPF_LDX | BPF_PROBE_MEM | +diff --git a/tools/testing/selftests/bpf/progs/test_tp_btf_nullable.c b/tools/testing/selftests/bpf/progs/test_tp_btf_nullable.c +index bba3e37f749b8..5aaf2b065f86c 100644 +--- a/tools/testing/selftests/bpf/progs/test_tp_btf_nullable.c ++++ b/tools/testing/selftests/bpf/progs/test_tp_btf_nullable.c +@@ -7,7 +7,11 @@ + #include "bpf_misc.h" + + SEC("tp_btf/bpf_testmod_test_nullable_bare") +-__failure __msg("R1 invalid mem access 'trusted_ptr_or_null_'") ++/* This used to be a failure test, but raw_tp nullable arguments can now ++ * directly be dereferenced, whether they have nullable annotation or not, ++ * and don't need to be explicitly checked. ++ */ ++__success + int BPF_PROG(handle_tp_btf_nullable_bare1, struct bpf_testmod_test_read_ctx *nullable_ctx) + { + return nullable_ctx->len; +-- +2.43.0 + diff --git a/queue-6.12/bpf-sockmap-fix-sk_msg_reset_curr.patch b/queue-6.12/bpf-sockmap-fix-sk_msg_reset_curr.patch new file mode 100644 index 00000000000..a276dba518d --- /dev/null +++ b/queue-6.12/bpf-sockmap-fix-sk_msg_reset_curr.patch @@ -0,0 +1,70 @@ +From d1c806d96884237f851c13954c2c3071a129a4c3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 6 Nov 2024 22:25:20 +0000 +Subject: bpf, sockmap: Fix sk_msg_reset_curr + +From: Zijian Zhang + +[ Upstream commit 955afd57dc4bf7e8c620a0a9e3af3c881c2c6dff ] + +Found in the test_txmsg_pull in test_sockmap, +``` +txmsg_cork = 512; // corking is importrant here +opt->iov_length = 3; +opt->iov_count = 1; +opt->rate = 512; // sendmsg will be invoked 512 times +``` +The first sendmsg will send an sk_msg with size 3, and bpf_msg_pull_data +will be invoked the first time. sk_msg_reset_curr will reset the copybreak +from 3 to 0. In the second sendmsg, since we are in the stage of corking, +psock->cork will be reused in func sk_msg_alloc. msg->sg.copybreak is 0 +now, the second msg will overwrite the first msg. As a result, we could +not pass the data integrity test. + +The same problem happens in push and pop test. Thus, fix sk_msg_reset_curr +to restore the correct copybreak. + +Fixes: bb9aefde5bba ("bpf: sockmap, updating the sg structure should also update curr") +Signed-off-by: Zijian Zhang +Link: https://lore.kernel.org/r/20241106222520.527076-9-zijianzhang@bytedance.com +Signed-off-by: Martin KaFai Lau +Signed-off-by: Sasha Levin +--- + net/core/filter.c | 20 +++++++++----------- + 1 file changed, 9 insertions(+), 11 deletions(-) + +diff --git a/net/core/filter.c b/net/core/filter.c +index 60c6e1e4662bd..9a459213d283f 100644 +--- a/net/core/filter.c ++++ b/net/core/filter.c +@@ -2621,18 +2621,16 @@ BPF_CALL_2(bpf_msg_cork_bytes, struct sk_msg *, msg, u32, bytes) + + static void sk_msg_reset_curr(struct sk_msg *msg) + { +- u32 i = msg->sg.start; +- u32 len = 0; +- +- do { +- len += sk_msg_elem(msg, i)->length; +- sk_msg_iter_var_next(i); +- if (len >= msg->sg.size) +- break; +- } while (i != msg->sg.end); ++ if (!msg->sg.size) { ++ msg->sg.curr = msg->sg.start; ++ msg->sg.copybreak = 0; ++ } else { ++ u32 i = msg->sg.end; + +- msg->sg.curr = i; +- msg->sg.copybreak = 0; ++ sk_msg_iter_var_prev(i); ++ msg->sg.curr = i; ++ msg->sg.copybreak = msg->sg.data[i].length; ++ } + } + + static const struct bpf_func_proto bpf_msg_cork_bytes_proto = { +-- +2.43.0 + diff --git a/queue-6.12/bpf-sockmap-several-fixes-to-bpf_msg_pop_data.patch b/queue-6.12/bpf-sockmap-several-fixes-to-bpf_msg_pop_data.patch new file mode 100644 index 00000000000..a9d58bbf4a5 --- /dev/null +++ b/queue-6.12/bpf-sockmap-several-fixes-to-bpf_msg_pop_data.patch @@ -0,0 +1,104 @@ +From aaf1220041df880e5153bad3a4f9cfb0715e2fe6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 6 Nov 2024 22:25:19 +0000 +Subject: bpf, sockmap: Several fixes to bpf_msg_pop_data + +From: Zijian Zhang + +[ Upstream commit 5d609ba262475db450ba69b8e8a557bd768ac07a ] + +Several fixes to bpf_msg_pop_data, +1. In sk_msg_shift_left, we should put_page +2. if (len == 0), return early is better +3. pop the entire sk_msg (last == msg->sg.size) should be supported +4. Fix for the value of variable "a" +5. In sk_msg_shift_left, after shifting, i has already pointed to the next +element. Addtional sk_msg_iter_var_next may result in BUG. + +Fixes: 7246d8ed4dcc ("bpf: helper to pop data from messages") +Signed-off-by: Zijian Zhang +Reviewed-by: John Fastabend +Link: https://lore.kernel.org/r/20241106222520.527076-8-zijianzhang@bytedance.com +Signed-off-by: Martin KaFai Lau +Signed-off-by: Sasha Levin +--- + net/core/filter.c | 15 +++++++++------ + 1 file changed, 9 insertions(+), 6 deletions(-) + +diff --git a/net/core/filter.c b/net/core/filter.c +index 0315ebbabe728..60c6e1e4662bd 100644 +--- a/net/core/filter.c ++++ b/net/core/filter.c +@@ -2921,8 +2921,10 @@ static const struct bpf_func_proto bpf_msg_push_data_proto = { + + static void sk_msg_shift_left(struct sk_msg *msg, int i) + { ++ struct scatterlist *sge = sk_msg_elem(msg, i); + int prev; + ++ put_page(sg_page(sge)); + do { + prev = i; + sk_msg_iter_var_next(i); +@@ -2959,6 +2961,9 @@ BPF_CALL_4(bpf_msg_pop_data, struct sk_msg *, msg, u32, start, + if (unlikely(flags)) + return -EINVAL; + ++ if (unlikely(len == 0)) ++ return 0; ++ + /* First find the starting scatterlist element */ + i = msg->sg.start; + do { +@@ -2971,7 +2976,7 @@ BPF_CALL_4(bpf_msg_pop_data, struct sk_msg *, msg, u32, start, + } while (i != msg->sg.end); + + /* Bounds checks: start and pop must be inside message */ +- if (start >= offset + l || last >= msg->sg.size) ++ if (start >= offset + l || last > msg->sg.size) + return -EINVAL; + + space = MAX_MSG_FRAGS - sk_msg_elem_used(msg); +@@ -3000,12 +3005,12 @@ BPF_CALL_4(bpf_msg_pop_data, struct sk_msg *, msg, u32, start, + */ + if (start != offset) { + struct scatterlist *nsge, *sge = sk_msg_elem(msg, i); +- int a = start; ++ int a = start - offset; + int b = sge->length - pop - a; + + sk_msg_iter_var_next(i); + +- if (pop < sge->length - a) { ++ if (b > 0) { + if (space) { + sge->length = a; + sk_msg_shift_right(msg, i); +@@ -3024,7 +3029,6 @@ BPF_CALL_4(bpf_msg_pop_data, struct sk_msg *, msg, u32, start, + if (unlikely(!page)) + return -ENOMEM; + +- sge->length = a; + orig = sg_page(sge); + from = sg_virt(sge); + to = page_address(page); +@@ -3034,7 +3038,7 @@ BPF_CALL_4(bpf_msg_pop_data, struct sk_msg *, msg, u32, start, + put_page(orig); + } + pop = 0; +- } else if (pop >= sge->length - a) { ++ } else { + pop -= (sge->length - a); + sge->length = a; + } +@@ -3068,7 +3072,6 @@ BPF_CALL_4(bpf_msg_pop_data, struct sk_msg *, msg, u32, start, + pop -= sge->length; + sk_msg_shift_left(msg, i); + } +- sk_msg_iter_var_next(i); + } + + sk_mem_uncharge(msg->sk, len - pop); +-- +2.43.0 + diff --git a/queue-6.12/bpf-sockmap-several-fixes-to-bpf_msg_push_data.patch b/queue-6.12/bpf-sockmap-several-fixes-to-bpf_msg_push_data.patch new file mode 100644 index 00000000000..b0c1428bbe8 --- /dev/null +++ b/queue-6.12/bpf-sockmap-several-fixes-to-bpf_msg_push_data.patch @@ -0,0 +1,132 @@ +From 96eb4771f2b5dcf777cfab3b91c569fc93101a16 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 6 Nov 2024 22:25:18 +0000 +Subject: bpf, sockmap: Several fixes to bpf_msg_push_data + +From: Zijian Zhang + +[ Upstream commit 15ab0548e3107665c34579ae523b2b6e7c22082a ] + +Several fixes to bpf_msg_push_data, +1. test_sockmap has tests where bpf_msg_push_data is invoked to push some +data at the end of a message, but -EINVAL is returned. In this case, in +bpf_msg_push_data, after the first loop, i will be set to msg->sg.end, add +the logic to handle it. +2. In the code block of "if (start - offset)", it's possible that "i" +points to the last of sk_msg_elem. In this case, "sk_msg_iter_next(msg, +end)" might still be called twice, another invoking is in "if (!copy)" +code block, but actually only one is needed. Add the logic to handle it, +and reconstruct the code to make the logic more clear. + +Fixes: 6fff607e2f14 ("bpf: sk_msg program helper bpf_msg_push_data") +Signed-off-by: Zijian Zhang +Link: https://lore.kernel.org/r/20241106222520.527076-7-zijianzhang@bytedance.com +Signed-off-by: Martin KaFai Lau +Signed-off-by: Sasha Levin +--- + net/core/filter.c | 53 +++++++++++++++++++++++++++++------------------ + 1 file changed, 33 insertions(+), 20 deletions(-) + +diff --git a/net/core/filter.c b/net/core/filter.c +index fb56567c551ed..0315ebbabe728 100644 +--- a/net/core/filter.c ++++ b/net/core/filter.c +@@ -2795,7 +2795,7 @@ BPF_CALL_4(bpf_msg_push_data, struct sk_msg *, msg, u32, start, + sk_msg_iter_var_next(i); + } while (i != msg->sg.end); + +- if (start >= offset + l) ++ if (start > offset + l) + return -EINVAL; + + space = MAX_MSG_FRAGS - sk_msg_elem_used(msg); +@@ -2820,6 +2820,8 @@ BPF_CALL_4(bpf_msg_push_data, struct sk_msg *, msg, u32, start, + + raw = page_address(page); + ++ if (i == msg->sg.end) ++ sk_msg_iter_var_prev(i); + psge = sk_msg_elem(msg, i); + front = start - offset; + back = psge->length - front; +@@ -2836,7 +2838,13 @@ BPF_CALL_4(bpf_msg_push_data, struct sk_msg *, msg, u32, start, + } + + put_page(sg_page(psge)); +- } else if (start - offset) { ++ new = i; ++ goto place_new; ++ } ++ ++ if (start - offset) { ++ if (i == msg->sg.end) ++ sk_msg_iter_var_prev(i); + psge = sk_msg_elem(msg, i); + rsge = sk_msg_elem_cpy(msg, i); + +@@ -2847,39 +2855,44 @@ BPF_CALL_4(bpf_msg_push_data, struct sk_msg *, msg, u32, start, + sk_msg_iter_var_next(i); + sg_unmark_end(psge); + sg_unmark_end(&rsge); +- sk_msg_iter_next(msg, end); + } + + /* Slot(s) to place newly allocated data */ ++ sk_msg_iter_next(msg, end); + new = i; ++ sk_msg_iter_var_next(i); ++ ++ if (i == msg->sg.end) { ++ if (!rsge.length) ++ goto place_new; ++ sk_msg_iter_next(msg, end); ++ goto place_new; ++ } + + /* Shift one or two slots as needed */ +- if (!copy) { +- sge = sk_msg_elem_cpy(msg, i); ++ sge = sk_msg_elem_cpy(msg, new); ++ sg_unmark_end(&sge); + ++ nsge = sk_msg_elem_cpy(msg, i); ++ if (rsge.length) { + sk_msg_iter_var_next(i); +- sg_unmark_end(&sge); ++ nnsge = sk_msg_elem_cpy(msg, i); + sk_msg_iter_next(msg, end); ++ } + +- nsge = sk_msg_elem_cpy(msg, i); ++ while (i != msg->sg.end) { ++ msg->sg.data[i] = sge; ++ sge = nsge; ++ sk_msg_iter_var_next(i); + if (rsge.length) { +- sk_msg_iter_var_next(i); ++ nsge = nnsge; + nnsge = sk_msg_elem_cpy(msg, i); +- } +- +- while (i != msg->sg.end) { +- msg->sg.data[i] = sge; +- sge = nsge; +- sk_msg_iter_var_next(i); +- if (rsge.length) { +- nsge = nnsge; +- nnsge = sk_msg_elem_cpy(msg, i); +- } else { +- nsge = sk_msg_elem_cpy(msg, i); +- } ++ } else { ++ nsge = sk_msg_elem_cpy(msg, i); + } + } + ++place_new: + /* Place newly allocated data buffer */ + sk_mem_charge(msg->sk, len); + msg->sg.size += len; +-- +2.43.0 + diff --git a/queue-6.12/bpf-tighten-tail-call-checks-for-lingering-locks-rcu.patch b/queue-6.12/bpf-tighten-tail-call-checks-for-lingering-locks-rcu.patch new file mode 100644 index 00000000000..032e4f73070 --- /dev/null +++ b/queue-6.12/bpf-tighten-tail-call-checks-for-lingering-locks-rcu.patch @@ -0,0 +1,64 @@ +From 8b0008e117552310cf0bf36910302895242f1cc9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 3 Nov 2024 14:59:38 -0800 +Subject: bpf: Tighten tail call checks for lingering locks, RCU, + preempt_disable + +From: Kumar Kartikeya Dwivedi + +[ Upstream commit 46f7ed32f7a873d6675ea72e1d6317df41a55f81 ] + +There are three situations when a program logically exits and transfers +control to the kernel or another program: bpf_throw, BPF_EXIT, and tail +calls. The former two check for any lingering locks and references, but +tail calls currently do not. Expand the checks to check for spin locks, +RCU read sections and preempt disabled sections. + +Spin locks are indirectly preventing tail calls as function calls are +disallowed, but the checks for preemption and RCU are more relaxed, +hence ensure tail calls are prevented in their presence. + +Fixes: 9bb00b2895cb ("bpf: Add kfunc bpf_rcu_read_lock/unlock()") +Fixes: fc7566ad0a82 ("bpf: Introduce bpf_preempt_[disable,enable] kfuncs") +Signed-off-by: Kumar Kartikeya Dwivedi +Link: https://lore.kernel.org/r/20241103225940.1408302-2-memxor@gmail.com +Signed-off-by: Alexei Starovoitov +Signed-off-by: Sasha Levin +--- + kernel/bpf/verifier.c | 15 +++++++++++++++ + 1 file changed, 15 insertions(+) + +diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c +index bb99bada7e2ed..011b4a86e2b3b 100644 +--- a/kernel/bpf/verifier.c ++++ b/kernel/bpf/verifier.c +@@ -10583,11 +10583,26 @@ static int check_helper_call(struct bpf_verifier_env *env, struct bpf_insn *insn + + switch (func_id) { + case BPF_FUNC_tail_call: ++ if (env->cur_state->active_lock.ptr) { ++ verbose(env, "tail_call cannot be used inside bpf_spin_lock-ed region\n"); ++ return -EINVAL; ++ } ++ + err = check_reference_leak(env, false); + if (err) { + verbose(env, "tail_call would lead to reference leak\n"); + return err; + } ++ ++ if (env->cur_state->active_rcu_lock) { ++ verbose(env, "tail_call cannot be used inside bpf_rcu_read_lock-ed region\n"); ++ return -EINVAL; ++ } ++ ++ if (env->cur_state->active_preempt_lock) { ++ verbose(env, "tail_call cannot be used inside bpf_preempt_disable-ed region\n"); ++ return -EINVAL; ++ } + break; + case BPF_FUNC_get_local_storage: + /* check that flags argument in get_local_storage(map, flags) is 0, +-- +2.43.0 + diff --git a/queue-6.12/bpf-use-function-pointers-count-as-struct_ops-links-.patch b/queue-6.12/bpf-use-function-pointers-count-as-struct_ops-links-.patch new file mode 100644 index 00000000000..1d7b2a529ee --- /dev/null +++ b/queue-6.12/bpf-use-function-pointers-count-as-struct_ops-links-.patch @@ -0,0 +1,122 @@ +From 0a1ae8c4094d6ee1bd4bd336dc8abd399849943a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 12 Nov 2024 22:58:48 +0800 +Subject: bpf: Use function pointers count as struct_ops links count + +From: Xu Kuohai + +[ Upstream commit 821a3fa32bbe3bc0fa23b3189325d3720a49a24c ] + +Only function pointers in a struct_ops structure can be linked to bpf +progs, so set the links count to the function pointers count, instead +of the total members count in the structure. + +Suggested-by: Martin KaFai Lau +Signed-off-by: Xu Kuohai +Link: https://lore.kernel.org/r/20241112145849.3436772-3-xukuohai@huaweicloud.com +Signed-off-by: Alexei Starovoitov +Stable-dep-of: 7c8ce4ffb684 ("bpf: Add kernel symbol for struct_ops trampoline") +Signed-off-by: Sasha Levin +--- + kernel/bpf/bpf_struct_ops.c | 35 +++++++++++++++++++++++++---------- + 1 file changed, 25 insertions(+), 10 deletions(-) + +diff --git a/kernel/bpf/bpf_struct_ops.c b/kernel/bpf/bpf_struct_ops.c +index fda3dd2ee9844..5058d1536c554 100644 +--- a/kernel/bpf/bpf_struct_ops.c ++++ b/kernel/bpf/bpf_struct_ops.c +@@ -32,7 +32,7 @@ struct bpf_struct_ops_map { + * (in kvalue.data). + */ + struct bpf_link **links; +- u32 links_cnt; ++ u32 funcs_cnt; + u32 image_pages_cnt; + /* image_pages is an array of pages that has all the trampolines + * that stores the func args before calling the bpf_prog. +@@ -481,11 +481,11 @@ static void bpf_struct_ops_map_put_progs(struct bpf_struct_ops_map *st_map) + { + u32 i; + +- for (i = 0; i < st_map->links_cnt; i++) { +- if (st_map->links[i]) { +- bpf_link_put(st_map->links[i]); +- st_map->links[i] = NULL; +- } ++ for (i = 0; i < st_map->funcs_cnt; i++) { ++ if (!st_map->links[i]) ++ break; ++ bpf_link_put(st_map->links[i]); ++ st_map->links[i] = NULL; + } + } + +@@ -601,6 +601,7 @@ static long bpf_struct_ops_map_update_elem(struct bpf_map *map, void *key, + int prog_fd, err; + u32 i, trampoline_start, image_off = 0; + void *cur_image = NULL, *image = NULL; ++ struct bpf_link **plink; + + if (flags) + return -EINVAL; +@@ -639,6 +640,7 @@ static long bpf_struct_ops_map_update_elem(struct bpf_map *map, void *key, + udata = &uvalue->data; + kdata = &kvalue->data; + ++ plink = st_map->links; + module_type = btf_type_by_id(btf_vmlinux, st_ops_ids[IDX_MODULE_ID]); + for_each_member(i, t, member) { + const struct btf_type *mtype, *ptype; +@@ -714,7 +716,7 @@ static long bpf_struct_ops_map_update_elem(struct bpf_map *map, void *key, + } + bpf_link_init(&link->link, BPF_LINK_TYPE_STRUCT_OPS, + &bpf_struct_ops_link_lops, prog); +- st_map->links[i] = &link->link; ++ *plink++ = &link->link; + + trampoline_start = image_off; + err = bpf_struct_ops_prepare_trampoline(tlinks, link, +@@ -895,6 +897,19 @@ static int bpf_struct_ops_map_alloc_check(union bpf_attr *attr) + return 0; + } + ++static u32 count_func_ptrs(const struct btf *btf, const struct btf_type *t) ++{ ++ int i; ++ u32 count; ++ const struct btf_member *member; ++ ++ count = 0; ++ for_each_member(i, t, member) ++ if (btf_type_resolve_func_ptr(btf, member->type, NULL)) ++ count++; ++ return count; ++} ++ + static struct bpf_map *bpf_struct_ops_map_alloc(union bpf_attr *attr) + { + const struct bpf_struct_ops_desc *st_ops_desc; +@@ -961,9 +976,9 @@ static struct bpf_map *bpf_struct_ops_map_alloc(union bpf_attr *attr) + map = &st_map->map; + + st_map->uvalue = bpf_map_area_alloc(vt->size, NUMA_NO_NODE); +- st_map->links_cnt = btf_type_vlen(t); ++ st_map->funcs_cnt = count_func_ptrs(btf, t); + st_map->links = +- bpf_map_area_alloc(st_map->links_cnt * sizeof(struct bpf_links *), ++ bpf_map_area_alloc(st_map->funcs_cnt * sizeof(struct bpf_link *), + NUMA_NO_NODE); + if (!st_map->uvalue || !st_map->links) { + ret = -ENOMEM; +@@ -994,7 +1009,7 @@ static u64 bpf_struct_ops_map_mem_usage(const struct bpf_map *map) + usage = sizeof(*st_map) + + vt->size - sizeof(struct bpf_struct_ops_value); + usage += vt->size; +- usage += btf_type_vlen(vt) * sizeof(struct bpf_links *); ++ usage += st_map->funcs_cnt * sizeof(struct bpf_link *); + usage += PAGE_SIZE; + return usage; + } +-- +2.43.0 + diff --git a/queue-6.12/brd-defer-automatic-disk-creation-until-module-initi.patch b/queue-6.12/brd-defer-automatic-disk-creation-until-module-initi.patch new file mode 100644 index 00000000000..f1028b8cfb2 --- /dev/null +++ b/queue-6.12/brd-defer-automatic-disk-creation-until-module-initi.patch @@ -0,0 +1,209 @@ +From 21fbd89da13a6ef7b8182e85163817df29705941 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 30 Oct 2024 11:49:14 +0800 +Subject: brd: defer automatic disk creation until module initialization + succeeds + +From: Yang Erkun + +[ Upstream commit 826cc42adf44930a633d11a5993676d85ddb0842 ] + +My colleague Wupeng found the following problems during fault injection: + +BUG: unable to handle page fault for address: fffffbfff809d073 +PGD 6e648067 P4D 123ec8067 PUD 123ec4067 PMD 100e38067 PTE 0 +Oops: Oops: 0000 [#1] PREEMPT SMP KASAN NOPTI +CPU: 5 UID: 0 PID: 755 Comm: modprobe Not tainted 6.12.0-rc3+ #17 +Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS +1.16.1-2.fc37 04/01/2014 +RIP: 0010:__asan_load8+0x4c/0xa0 +... +Call Trace: + + blkdev_put_whole+0x41/0x70 + bdev_release+0x1a3/0x250 + blkdev_release+0x11/0x20 + __fput+0x1d7/0x4a0 + task_work_run+0xfc/0x180 + syscall_exit_to_user_mode+0x1de/0x1f0 + do_syscall_64+0x6b/0x170 + entry_SYSCALL_64_after_hwframe+0x76/0x7e + +loop_init() is calling loop_add() after __register_blkdev() succeeds and +is ignoring disk_add() failure from loop_add(), for loop_add() failure +is not fatal and successfully created disks are already visible to +bdev_open(). + +brd_init() is currently calling brd_alloc() before __register_blkdev() +succeeds and is releasing successfully created disks when brd_init() +returns an error. This can cause UAF for the latter two case: + +case 1: + T1: +modprobe brd + brd_init + brd_alloc(0) // success + add_disk + disk_scan_partitions + bdev_file_open_by_dev // alloc file + fput // won't free until back to userspace + brd_alloc(1) // failed since mem alloc error inject + // error path for modprobe will release code segment + // back to userspace + __fput + blkdev_release + bdev_release + blkdev_put_whole + bdev->bd_disk->fops->release // fops is freed now, UAF! + +case 2: + T1: T2: +modprobe brd + brd_init + brd_alloc(0) // success + open(/dev/ram0) + brd_alloc(1) // fail + // error path for modprobe + + close(/dev/ram0) + ... + /* UAF! */ + bdev->bd_disk->fops->release + +Fix this problem by following what loop_init() does. Besides, +reintroduce brd_devices_mutex to help serialize modifications to +brd_list. + +Fixes: 7f9b348cb5e9 ("brd: convert to blk_alloc_disk/blk_cleanup_disk") +Reported-by: Wupeng Ma +Signed-off-by: Yang Erkun +Reviewed-by: Christoph Hellwig +Link: https://lore.kernel.org/r/20241030034914.907829-1-yangerkun@huaweicloud.com +Signed-off-by: Jens Axboe +Signed-off-by: Sasha Levin +--- + drivers/block/brd.c | 66 ++++++++++++++++++++++++++++++--------------- + 1 file changed, 44 insertions(+), 22 deletions(-) + +diff --git a/drivers/block/brd.c b/drivers/block/brd.c +index 2fd1ed1017481..5a95671d81515 100644 +--- a/drivers/block/brd.c ++++ b/drivers/block/brd.c +@@ -316,8 +316,40 @@ __setup("ramdisk_size=", ramdisk_size); + * (should share code eventually). + */ + static LIST_HEAD(brd_devices); ++static DEFINE_MUTEX(brd_devices_mutex); + static struct dentry *brd_debugfs_dir; + ++static struct brd_device *brd_find_or_alloc_device(int i) ++{ ++ struct brd_device *brd; ++ ++ mutex_lock(&brd_devices_mutex); ++ list_for_each_entry(brd, &brd_devices, brd_list) { ++ if (brd->brd_number == i) { ++ mutex_unlock(&brd_devices_mutex); ++ return ERR_PTR(-EEXIST); ++ } ++ } ++ ++ brd = kzalloc(sizeof(*brd), GFP_KERNEL); ++ if (!brd) { ++ mutex_unlock(&brd_devices_mutex); ++ return ERR_PTR(-ENOMEM); ++ } ++ brd->brd_number = i; ++ list_add_tail(&brd->brd_list, &brd_devices); ++ mutex_unlock(&brd_devices_mutex); ++ return brd; ++} ++ ++static void brd_free_device(struct brd_device *brd) ++{ ++ mutex_lock(&brd_devices_mutex); ++ list_del(&brd->brd_list); ++ mutex_unlock(&brd_devices_mutex); ++ kfree(brd); ++} ++ + static int brd_alloc(int i) + { + struct brd_device *brd; +@@ -340,14 +372,9 @@ static int brd_alloc(int i) + BLK_FEAT_NOWAIT, + }; + +- list_for_each_entry(brd, &brd_devices, brd_list) +- if (brd->brd_number == i) +- return -EEXIST; +- brd = kzalloc(sizeof(*brd), GFP_KERNEL); +- if (!brd) +- return -ENOMEM; +- brd->brd_number = i; +- list_add_tail(&brd->brd_list, &brd_devices); ++ brd = brd_find_or_alloc_device(i); ++ if (IS_ERR(brd)) ++ return PTR_ERR(brd); + + xa_init(&brd->brd_pages); + +@@ -378,8 +405,7 @@ static int brd_alloc(int i) + out_cleanup_disk: + put_disk(disk); + out_free_dev: +- list_del(&brd->brd_list); +- kfree(brd); ++ brd_free_device(brd); + return err; + } + +@@ -398,8 +424,7 @@ static void brd_cleanup(void) + del_gendisk(brd->brd_disk); + put_disk(brd->brd_disk); + brd_free_pages(brd); +- list_del(&brd->brd_list); +- kfree(brd); ++ brd_free_device(brd); + } + } + +@@ -426,16 +451,6 @@ static int __init brd_init(void) + { + int err, i; + +- brd_check_and_reset_par(); +- +- brd_debugfs_dir = debugfs_create_dir("ramdisk_pages", NULL); +- +- for (i = 0; i < rd_nr; i++) { +- err = brd_alloc(i); +- if (err) +- goto out_free; +- } +- + /* + * brd module now has a feature to instantiate underlying device + * structure on-demand, provided that there is an access dev node. +@@ -451,11 +466,18 @@ static int __init brd_init(void) + * dynamically. + */ + ++ brd_check_and_reset_par(); ++ ++ brd_debugfs_dir = debugfs_create_dir("ramdisk_pages", NULL); ++ + if (__register_blkdev(RAMDISK_MAJOR, "ramdisk", brd_probe)) { + err = -EIO; + goto out_free; + } + ++ for (i = 0; i < rd_nr; i++) ++ brd_alloc(i); ++ + pr_info("brd: module loaded\n"); + return 0; + +-- +2.43.0 + diff --git a/queue-6.12/bus-mhi-host-switch-trace_mhi_gen_tre-fields-to-nati.patch b/queue-6.12/bus-mhi-host-switch-trace_mhi_gen_tre-fields-to-nati.patch new file mode 100644 index 00000000000..7f8dcbcc581 --- /dev/null +++ b/queue-6.12/bus-mhi-host-switch-trace_mhi_gen_tre-fields-to-nati.patch @@ -0,0 +1,97 @@ +From 6ed8d3e931f039f10dfe0fb11faeede09103d137 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 4 Oct 2024 10:03:20 -0700 +Subject: bus: mhi: host: Switch trace_mhi_gen_tre fields to native endian + +From: Carl Vanderlip + +[ Upstream commit 23388a1b305e8aac714fafd5fdc72a580586bd0c ] + +Each of the __field() macros were triggering sparse warnings similar to: +trace.h:87:1: sparse: sparse: cast to restricted __le64 +trace.h:87:1: sparse: sparse: restricted __le64 degrades to integer +trace.h:87:1: sparse: sparse: restricted __le64 degrades to integer + +Change each little endian type to its similarly sized native integer. +Convert inputs into native endian. + +Reported-by: kernel test robot +Closes: https://lore.kernel.org/oe-kbuild-all/202402071859.8qMhgJEQ-lkp@intel.com/ +Fixes: ceeb64f41fe6 ("bus: mhi: host: Add tracing support") +Signed-off-by: Carl Vanderlip +Reviewed-by: Jeffrey Hugo +Reviewed-by: Mayank Rana +Reviewed-by: Manivannan Sadhasivam +Link: https://lore.kernel.org/r/20241004170321.4047492-1-quic_carlv@quicinc.com +Signed-off-by: Manivannan Sadhasivam +Signed-off-by: Sasha Levin +--- + drivers/bus/mhi/host/trace.h | 25 +++++++++++++------------ + 1 file changed, 13 insertions(+), 12 deletions(-) + +diff --git a/drivers/bus/mhi/host/trace.h b/drivers/bus/mhi/host/trace.h +index 95613c8ebe069..3e0c41777429e 100644 +--- a/drivers/bus/mhi/host/trace.h ++++ b/drivers/bus/mhi/host/trace.h +@@ -9,6 +9,7 @@ + #if !defined(_TRACE_EVENT_MHI_HOST_H) || defined(TRACE_HEADER_MULTI_READ) + #define _TRACE_EVENT_MHI_HOST_H + ++#include + #include + #include + #include "../common.h" +@@ -97,18 +98,18 @@ TRACE_EVENT(mhi_gen_tre, + __string(name, mhi_cntrl->mhi_dev->name) + __field(int, ch_num) + __field(void *, wp) +- __field(__le64, tre_ptr) +- __field(__le32, dword0) +- __field(__le32, dword1) ++ __field(uint64_t, tre_ptr) ++ __field(uint32_t, dword0) ++ __field(uint32_t, dword1) + ), + + TP_fast_assign( + __assign_str(name); + __entry->ch_num = mhi_chan->chan; + __entry->wp = mhi_tre; +- __entry->tre_ptr = mhi_tre->ptr; +- __entry->dword0 = mhi_tre->dword[0]; +- __entry->dword1 = mhi_tre->dword[1]; ++ __entry->tre_ptr = le64_to_cpu(mhi_tre->ptr); ++ __entry->dword0 = le32_to_cpu(mhi_tre->dword[0]); ++ __entry->dword1 = le32_to_cpu(mhi_tre->dword[1]); + ), + + TP_printk("%s: Chan: %d TRE: 0x%p TRE buf: 0x%llx DWORD0: 0x%08x DWORD1: 0x%08x\n", +@@ -176,19 +177,19 @@ DECLARE_EVENT_CLASS(mhi_process_event_ring, + + TP_STRUCT__entry( + __string(name, mhi_cntrl->mhi_dev->name) +- __field(__le32, dword0) +- __field(__le32, dword1) ++ __field(uint32_t, dword0) ++ __field(uint32_t, dword1) + __field(int, state) +- __field(__le64, ptr) ++ __field(uint64_t, ptr) + __field(void *, rp) + ), + + TP_fast_assign( + __assign_str(name); + __entry->rp = rp; +- __entry->ptr = rp->ptr; +- __entry->dword0 = rp->dword[0]; +- __entry->dword1 = rp->dword[1]; ++ __entry->ptr = le64_to_cpu(rp->ptr); ++ __entry->dword0 = le32_to_cpu(rp->dword[0]); ++ __entry->dword1 = le32_to_cpu(rp->dword[1]); + __entry->state = MHI_TRE_GET_EV_STATE(rp); + ), + +-- +2.43.0 + diff --git a/queue-6.12/cachefiles-fix-incorrect-length-return-value-in-cach.patch b/queue-6.12/cachefiles-fix-incorrect-length-return-value-in-cach.patch new file mode 100644 index 00000000000..221fa792a51 --- /dev/null +++ b/queue-6.12/cachefiles-fix-incorrect-length-return-value-in-cach.patch @@ -0,0 +1,65 @@ +From 4a3663bced28ee1e9affba5dbb46463f0975d488 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 7 Nov 2024 19:06:45 +0800 +Subject: cachefiles: Fix incorrect length return value in + cachefiles_ondemand_fd_write_iter() + +From: Zizhi Wo + +[ Upstream commit 10c35abd35aa62c9aac56898ae0c63b4d7d115e5 ] + +cachefiles_ondemand_fd_write_iter() function first aligns "pos" and "len" +to block boundaries. When calling __cachefiles_write(), the aligned "pos" +is passed in, but "len" is the original unaligned value(iter->count). +Additionally, the returned length of the write operation is the modified +"len" aligned by block size, which is unreasonable. + +The alignment of "pos" and "len" is intended only to check whether the +cache has enough space. But the modified len should not be used as the +return value of cachefiles_ondemand_fd_write_iter() because the length we +passed to __cachefiles_write() is the previous "len". Doing so would result +in a mismatch in the data written on-demand. For example, if the length of +the user state passed in is not aligned to the block size (the preread +scene/DIO writes only need 512 alignment/Fault injection), the length of +the write will differ from the actual length of the return. + +To solve this issue, since the __cachefiles_prepare_write() modifies the +size of "len", we pass "aligned_len" to __cachefiles_prepare_write() to +calculate the free blocks and use the original "len" as the return value of +cachefiles_ondemand_fd_write_iter(). + +Fixes: c8383054506c ("cachefiles: notify the user daemon when looking up cookie") +Signed-off-by: Zizhi Wo +Link: https://lore.kernel.org/r/20241107110649.3980193-2-wozizhi@huawei.com +Reviewed-by: David Howells +Signed-off-by: Christian Brauner +Signed-off-by: Sasha Levin +--- + fs/cachefiles/ondemand.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/fs/cachefiles/ondemand.c b/fs/cachefiles/ondemand.c +index 470c966583850..bdd321017f1c4 100644 +--- a/fs/cachefiles/ondemand.c ++++ b/fs/cachefiles/ondemand.c +@@ -61,7 +61,7 @@ static ssize_t cachefiles_ondemand_fd_write_iter(struct kiocb *kiocb, + struct cachefiles_object *object = kiocb->ki_filp->private_data; + struct cachefiles_cache *cache = object->volume->cache; + struct file *file = object->file; +- size_t len = iter->count; ++ size_t len = iter->count, aligned_len = len; + loff_t pos = kiocb->ki_pos; + const struct cred *saved_cred; + int ret; +@@ -70,7 +70,7 @@ static ssize_t cachefiles_ondemand_fd_write_iter(struct kiocb *kiocb, + return -ENOBUFS; + + cachefiles_begin_secure(cache, &saved_cred); +- ret = __cachefiles_prepare_write(object, file, &pos, &len, len, true); ++ ret = __cachefiles_prepare_write(object, file, &pos, &aligned_len, len, true); + cachefiles_end_secure(cache, saved_cred); + if (ret < 0) + return ret; +-- +2.43.0 + diff --git a/queue-6.12/cachefiles-fix-missing-pos-updates-in-cachefiles_ond.patch b/queue-6.12/cachefiles-fix-missing-pos-updates-in-cachefiles_ond.patch new file mode 100644 index 00000000000..20ffb68622f --- /dev/null +++ b/queue-6.12/cachefiles-fix-missing-pos-updates-in-cachefiles_ond.patch @@ -0,0 +1,51 @@ +From 747ea5bead8b8fa76badddd1d4308ee8aa038758 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 7 Nov 2024 19:06:46 +0800 +Subject: cachefiles: Fix missing pos updates in + cachefiles_ondemand_fd_write_iter() + +From: Zizhi Wo + +[ Upstream commit 56f4856b425a30e1d8b3e41e6cde8bfba90ba5f8 ] + +In the erofs on-demand loading scenario, read and write operations are +usually delivered through "off" and "len" contained in read req in user +mode. Naturally, pwrite is used to specify a specific offset to complete +write operations. + +However, if the write(not pwrite) syscall is called multiple times in the +read-ahead scenario, we need to manually update ki_pos after each write +operation to update file->f_pos. + +This step is currently missing from the cachefiles_ondemand_fd_write_iter +function, added to address this issue. + +Fixes: c8383054506c ("cachefiles: notify the user daemon when looking up cookie") +Signed-off-by: Zizhi Wo +Link: https://lore.kernel.org/r/20241107110649.3980193-3-wozizhi@huawei.com +Acked-by: David Howells +Signed-off-by: Christian Brauner +Signed-off-by: Sasha Levin +--- + fs/cachefiles/ondemand.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/fs/cachefiles/ondemand.c b/fs/cachefiles/ondemand.c +index bdd321017f1c4..38ca6dce8ef29 100644 +--- a/fs/cachefiles/ondemand.c ++++ b/fs/cachefiles/ondemand.c +@@ -77,8 +77,10 @@ static ssize_t cachefiles_ondemand_fd_write_iter(struct kiocb *kiocb, + + trace_cachefiles_ondemand_fd_write(object, file_inode(file), pos, len); + ret = __cachefiles_write(object, file, pos, iter, NULL, NULL); +- if (!ret) ++ if (!ret) { + ret = len; ++ kiocb->ki_pos += ret; ++ } + + return ret; + } +-- +2.43.0 + diff --git a/queue-6.12/cachefiles-fix-null-pointer-dereference-in-object-fi.patch b/queue-6.12/cachefiles-fix-null-pointer-dereference-in-object-fi.patch new file mode 100644 index 00000000000..b0f88c05a68 --- /dev/null +++ b/queue-6.12/cachefiles-fix-null-pointer-dereference-in-object-fi.patch @@ -0,0 +1,144 @@ +From 0d99df2b0da7898904a8f1c4192998783a5ddcf5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 7 Nov 2024 19:06:48 +0800 +Subject: cachefiles: Fix NULL pointer dereference in object->file + +From: Zizhi Wo + +[ Upstream commit 31ad74b20227ce6b40910ff78b1c604e42975cf1 ] + +At present, the object->file has the NULL pointer dereference problem in +ondemand-mode. The root cause is that the allocated fd and object->file +lifetime are inconsistent, and the user-space invocation to anon_fd uses +object->file. Following is the process that triggers the issue: + + [write fd] [umount] +cachefiles_ondemand_fd_write_iter + fscache_cookie_state_machine + cachefiles_withdraw_cookie + if (!file) return -ENOBUFS + cachefiles_clean_up_object + cachefiles_unmark_inode_in_use + fput(object->file) + object->file = NULL + // file NULL pointer dereference! + __cachefiles_write(..., file, ...) + +Fix this issue by add an additional reference count to the object->file +before write/llseek, and decrement after it finished. + +Fixes: c8383054506c ("cachefiles: notify the user daemon when looking up cookie") +Signed-off-by: Zizhi Wo +Link: https://lore.kernel.org/r/20241107110649.3980193-5-wozizhi@huawei.com +Reviewed-by: David Howells +Signed-off-by: Christian Brauner +Signed-off-by: Sasha Levin +--- + fs/cachefiles/interface.c | 14 ++++++++++---- + fs/cachefiles/ondemand.c | 30 ++++++++++++++++++++++++------ + 2 files changed, 34 insertions(+), 10 deletions(-) + +diff --git a/fs/cachefiles/interface.c b/fs/cachefiles/interface.c +index 35ba2117a6f65..3e63cfe158747 100644 +--- a/fs/cachefiles/interface.c ++++ b/fs/cachefiles/interface.c +@@ -327,6 +327,8 @@ static void cachefiles_commit_object(struct cachefiles_object *object, + static void cachefiles_clean_up_object(struct cachefiles_object *object, + struct cachefiles_cache *cache) + { ++ struct file *file; ++ + if (test_bit(FSCACHE_COOKIE_RETIRED, &object->cookie->flags)) { + if (!test_bit(CACHEFILES_OBJECT_USING_TMPFILE, &object->flags)) { + cachefiles_see_object(object, cachefiles_obj_see_clean_delete); +@@ -342,10 +344,14 @@ static void cachefiles_clean_up_object(struct cachefiles_object *object, + } + + cachefiles_unmark_inode_in_use(object, object->file); +- if (object->file) { +- fput(object->file); +- object->file = NULL; +- } ++ ++ spin_lock(&object->lock); ++ file = object->file; ++ object->file = NULL; ++ spin_unlock(&object->lock); ++ ++ if (file) ++ fput(file); + } + + /* +diff --git a/fs/cachefiles/ondemand.c b/fs/cachefiles/ondemand.c +index 38ca6dce8ef29..fe3de9ad57bf6 100644 +--- a/fs/cachefiles/ondemand.c ++++ b/fs/cachefiles/ondemand.c +@@ -60,20 +60,26 @@ static ssize_t cachefiles_ondemand_fd_write_iter(struct kiocb *kiocb, + { + struct cachefiles_object *object = kiocb->ki_filp->private_data; + struct cachefiles_cache *cache = object->volume->cache; +- struct file *file = object->file; ++ struct file *file; + size_t len = iter->count, aligned_len = len; + loff_t pos = kiocb->ki_pos; + const struct cred *saved_cred; + int ret; + +- if (!file) ++ spin_lock(&object->lock); ++ file = object->file; ++ if (!file) { ++ spin_unlock(&object->lock); + return -ENOBUFS; ++ } ++ get_file(file); ++ spin_unlock(&object->lock); + + cachefiles_begin_secure(cache, &saved_cred); + ret = __cachefiles_prepare_write(object, file, &pos, &aligned_len, len, true); + cachefiles_end_secure(cache, saved_cred); + if (ret < 0) +- return ret; ++ goto out; + + trace_cachefiles_ondemand_fd_write(object, file_inode(file), pos, len); + ret = __cachefiles_write(object, file, pos, iter, NULL, NULL); +@@ -82,6 +88,8 @@ static ssize_t cachefiles_ondemand_fd_write_iter(struct kiocb *kiocb, + kiocb->ki_pos += ret; + } + ++out: ++ fput(file); + return ret; + } + +@@ -89,12 +97,22 @@ static loff_t cachefiles_ondemand_fd_llseek(struct file *filp, loff_t pos, + int whence) + { + struct cachefiles_object *object = filp->private_data; +- struct file *file = object->file; ++ struct file *file; ++ loff_t ret; + +- if (!file) ++ spin_lock(&object->lock); ++ file = object->file; ++ if (!file) { ++ spin_unlock(&object->lock); + return -ENOBUFS; ++ } ++ get_file(file); ++ spin_unlock(&object->lock); + +- return vfs_llseek(file, pos, whence); ++ ret = vfs_llseek(file, pos, whence); ++ fput(file); ++ ++ return ret; + } + + static long cachefiles_ondemand_fd_ioctl(struct file *filp, unsigned int ioctl, +-- +2.43.0 + diff --git a/queue-6.12/cgroup-bpf-only-cgroup-v2-can-be-attached-by-bpf-pro.patch b/queue-6.12/cgroup-bpf-only-cgroup-v2-can-be-attached-by-bpf-pro.patch new file mode 100644 index 00000000000..8d33e758216 --- /dev/null +++ b/queue-6.12/cgroup-bpf-only-cgroup-v2-can-be-attached-by-bpf-pro.patch @@ -0,0 +1,70 @@ +From 863d3614678ff701a364fb65c3cdea50c3c5f9d9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 18 Oct 2024 08:15:20 +0000 +Subject: cgroup/bpf: only cgroup v2 can be attached by bpf programs + +From: Chen Ridong + +[ Upstream commit 2190df6c91373fdec6db9fc07e427084f232f57e ] + +Only cgroup v2 can be attached by bpf programs, so this patch introduces +that cgroup_bpf_inherit and cgroup_bpf_offline can only be called in +cgroup v2, and this can fix the memleak mentioned by commit 04f8ef5643bc +("cgroup: Fix memory leak caused by missing cgroup_bpf_offline"), which +has been reverted. + +Fixes: 2b0d3d3e4fcf ("percpu_ref: reduce memory footprint of percpu_ref in fast path") +Fixes: 4bfc0bb2c60e ("bpf: decouple the lifetime of cgroup_bpf from cgroup itself") +Link: https://lore.kernel.org/cgroups/aka2hk5jsel5zomucpwlxsej6iwnfw4qu5jkrmjhyfhesjlfdw@46zxhg5bdnr7/ +Signed-off-by: Chen Ridong +Signed-off-by: Tejun Heo +Signed-off-by: Sasha Levin +--- + kernel/cgroup/cgroup.c | 17 +++++++++++------ + 1 file changed, 11 insertions(+), 6 deletions(-) + +diff --git a/kernel/cgroup/cgroup.c b/kernel/cgroup/cgroup.c +index 30444e0960276..e275eaf2de7f8 100644 +--- a/kernel/cgroup/cgroup.c ++++ b/kernel/cgroup/cgroup.c +@@ -2140,8 +2140,10 @@ int cgroup_setup_root(struct cgroup_root *root, u16 ss_mask) + if (ret) + goto exit_stats; + +- ret = cgroup_bpf_inherit(root_cgrp); +- WARN_ON_ONCE(ret); ++ if (root == &cgrp_dfl_root) { ++ ret = cgroup_bpf_inherit(root_cgrp); ++ WARN_ON_ONCE(ret); ++ } + + trace_cgroup_setup_root(root); + +@@ -5708,9 +5710,11 @@ static struct cgroup *cgroup_create(struct cgroup *parent, const char *name, + if (ret) + goto out_kernfs_remove; + +- ret = cgroup_bpf_inherit(cgrp); +- if (ret) +- goto out_psi_free; ++ if (cgrp->root == &cgrp_dfl_root) { ++ ret = cgroup_bpf_inherit(cgrp); ++ if (ret) ++ goto out_psi_free; ++ } + + /* + * New cgroup inherits effective freeze counter, and +@@ -6024,7 +6028,8 @@ static int cgroup_destroy_locked(struct cgroup *cgrp) + + cgroup1_check_for_release(parent); + +- cgroup_bpf_offline(cgrp); ++ if (cgrp->root == &cgrp_dfl_root) ++ cgroup_bpf_offline(cgrp); + + /* put the base reference */ + percpu_ref_kill(&cgrp->self.refcnt); +-- +2.43.0 + diff --git a/queue-6.12/checkpatch-always-parse-orig_commit-in-fixes-tag.patch b/queue-6.12/checkpatch-always-parse-orig_commit-in-fixes-tag.patch new file mode 100644 index 00000000000..9e1efff8c5d --- /dev/null +++ b/queue-6.12/checkpatch-always-parse-orig_commit-in-fixes-tag.patch @@ -0,0 +1,120 @@ +From 6cdfdc1261420006b3776129a0e60a05ff92e052 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 25 Oct 2024 19:43:19 -0400 +Subject: checkpatch: always parse orig_commit in fixes tag +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Tamir Duberstein + +[ Upstream commit 2f07b652384969f5d0b317e1daa5f2eb967bc73d ] + +Do not require the presence of `$balanced_parens` to get the commit SHA; +this allows a `Fixes: deadbeef` tag to get a correct suggestion rather +than a suggestion containing a reference to HEAD. + +Given this patch: + +: From: Tamir Duberstein +: Subject: Test patch +: Date: Fri, 25 Oct 2024 19:30:51 -0400 +: +: This is a test patch. +: +: Fixes: bd17e036b495 +: Signed-off-by: Tamir Duberstein +: --- /dev/null +: +++ b/new-file +: @@ -0,0 +1 @@ +: +Test. + +Before: + +WARNING: Please use correct Fixes: style 'Fixes: <12 chars of sha1> ("")' - ie: 'Fixes: c10a7d25e68f ("Test patch")' + +After: + +WARNING: Please use correct Fixes: style 'Fixes: <12 chars of sha1> ("<title line>")' - ie: 'Fixes: bd17e036b495 ("checkpatch: warn for non-standard fixes tag style")' + +The prior behavior incorrectly suggested the patch's own SHA and title +line rather than the referenced commit's. This fixes that. + +Ironically this: + +Fixes: bd17e036b495 ("checkpatch: warn for non-standard fixes tag style") +Signed-off-by: Tamir Duberstein <tamird@gmail.com> +Cc: Andy Whitcroft <apw@canonical.com> +Cc: Dwaipayan Ray <dwaipayanray1@gmail.com> +Cc: Joe Perches <joe@perches.com> +Cc: Louis Peens <louis.peens@corigine.com> +Cc: Lukas Bulwahn <lukas.bulwahn@gmail.com> +Cc: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se> +Cc: Philippe Schenker <philippe.schenker@toradex.com> +Cc: Simon Horman <horms@kernel.org> +Signed-off-by: Andrew Morton <akpm@linux-foundation.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + scripts/checkpatch.pl | 37 ++++++++++++++++--------------------- + 1 file changed, 16 insertions(+), 21 deletions(-) + +diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl +index 4427572b24771..b03d526e4c454 100755 +--- a/scripts/checkpatch.pl ++++ b/scripts/checkpatch.pl +@@ -3209,36 +3209,31 @@ sub process { + + # Check Fixes: styles is correct + if (!$in_header_lines && +- $line =~ /^\s*fixes:?\s*(?:commit\s*)?[0-9a-f]{5,}\b/i) { +- my $orig_commit = ""; +- my $id = "0123456789ab"; +- my $title = "commit title"; +- my $tag_case = 1; +- my $tag_space = 1; +- my $id_length = 1; +- my $id_case = 1; ++ $line =~ /^\s*(fixes:?)\s*(?:commit\s*)?([0-9a-f]{5,40})(?:\s*($balanced_parens))?/i) { ++ my $tag = $1; ++ my $orig_commit = $2; ++ my $title; + my $title_has_quotes = 0; + $fixes_tag = 1; +- +- if ($line =~ /(\s*fixes:?)\s+([0-9a-f]{5,})\s+($balanced_parens)/i) { +- my $tag = $1; +- $orig_commit = $2; +- $title = $3; +- +- $tag_case = 0 if $tag eq "Fixes:"; +- $tag_space = 0 if ($line =~ /^fixes:? [0-9a-f]{5,} ($balanced_parens)/i); +- +- $id_length = 0 if ($orig_commit =~ /^[0-9a-f]{12}$/i); +- $id_case = 0 if ($orig_commit !~ /[A-F]/); +- ++ if (defined $3) { + # Always strip leading/trailing parens then double quotes if existing +- $title = substr($title, 1, -1); ++ $title = substr($3, 1, -1); + if ($title =~ /^".*"$/) { + $title = substr($title, 1, -1); + $title_has_quotes = 1; + } ++ } else { ++ $title = "commit title" + } + ++ ++ my $tag_case = not ($tag eq "Fixes:"); ++ my $tag_space = not ($line =~ /^fixes:? [0-9a-f]{5,40} ($balanced_parens)/i); ++ ++ my $id_length = not ($orig_commit =~ /^[0-9a-f]{12}$/i); ++ my $id_case = not ($orig_commit !~ /[A-F]/); ++ ++ my $id = "0123456789ab"; + my ($cid, $ctitle) = git_commit_info($orig_commit, $id, + $title); + +-- +2.43.0 + diff --git a/queue-6.12/cleanup-remove-address-space-of-returned-pointer.patch b/queue-6.12/cleanup-remove-address-space-of-returned-pointer.patch new file mode 100644 index 00000000000..170c02eade8 --- /dev/null +++ b/queue-6.12/cleanup-remove-address-space-of-returned-pointer.patch @@ -0,0 +1,60 @@ +From f45f80fa577d2ac39bcb6c7e6d98b788e6e4e597 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Mon, 19 Aug 2024 09:41:15 +0200 +Subject: cleanup: Remove address space of returned pointer + +From: Uros Bizjak <ubizjak@gmail.com> + +[ Upstream commit f730fd535fc51573f982fad629f2fc6b4a0cde2f ] + +Guard functions in local_lock.h are defined using DEFINE_GUARD() and +DEFINE_LOCK_GUARD_1() macros having lock type defined as pointer in +the percpu address space. The functions, defined by these macros +return value in generic address space, causing: + +cleanup.h:157:18: error: return from pointer to non-enclosed address space + +and + +cleanup.h:214:18: error: return from pointer to non-enclosed address space + +when strict percpu checks are enabled. + +Add explicit casts to remove address space of the returned pointer. + +Found by GCC's named address space checks. + +Fixes: e4ab322fbaaa ("cleanup: Add conditional guard support") +Signed-off-by: Uros Bizjak <ubizjak@gmail.com> +Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> +Link: https://lkml.kernel.org/r/20240819074124.143565-1-ubizjak@gmail.com +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + include/linux/cleanup.h | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/include/linux/cleanup.h b/include/linux/cleanup.h +index 038b2d523bf88..518bd1fd86fbe 100644 +--- a/include/linux/cleanup.h ++++ b/include/linux/cleanup.h +@@ -290,7 +290,7 @@ static inline class_##_name##_t class_##_name##ext##_constructor(_init_args) \ + #define DEFINE_GUARD(_name, _type, _lock, _unlock) \ + DEFINE_CLASS(_name, _type, if (_T) { _unlock; }, ({ _lock; _T; }), _type _T); \ + static inline void * class_##_name##_lock_ptr(class_##_name##_t *_T) \ +- { return *_T; } ++ { return (void *)(__force unsigned long)*_T; } + + #define DEFINE_GUARD_COND(_name, _ext, _condlock) \ + EXTEND_CLASS(_name, _ext, \ +@@ -347,7 +347,7 @@ static inline void class_##_name##_destructor(class_##_name##_t *_T) \ + \ + static inline void *class_##_name##_lock_ptr(class_##_name##_t *_T) \ + { \ +- return _T->lock; \ ++ return (void *)(__force unsigned long)_T->lock; \ + } + + +-- +2.43.0 + diff --git a/queue-6.12/clk-allow-kunit-tests-to-run-without-of_overlay-enab.patch b/queue-6.12/clk-allow-kunit-tests-to-run-without-of_overlay-enab.patch new file mode 100644 index 00000000000..33f42476b47 --- /dev/null +++ b/queue-6.12/clk-allow-kunit-tests-to-run-without-of_overlay-enab.patch @@ -0,0 +1,61 @@ +From 3f42e3cd7cf72198e1d16e2605a28811f286be84 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Wed, 16 Oct 2024 14:27:37 -0700 +Subject: clk: Allow kunit tests to run without OF_OVERLAY enabled + +From: Stephen Boyd <sboyd@kernel.org> + +[ Upstream commit 94e6fdd028a12ff2abe7d915f8b6bbdb923cc04d ] + +Some configurations want to enable CONFIG_KUNIT without enabling +CONFIG_OF_OVERLAY. The kunit overlay code already skips if +CONFIG_OF_OVERLAY isn't enabled, so these selects here aren't really +doing anything besides making it easier to run the tests without them +skipping. Remove the select and move the config setting to the +drivers/clk/.kunitconfig file so that the clk tests can be run with or +without CONFIG_OF_OVERLAY set to test either behavior. + +Fixes: 5776526beb95 ("clk: Add KUnit tests for clk fixed rate basic type") +Fixes: 274aff8711b2 ("clk: Add KUnit tests for clks registered with struct clk_parent_data") +Signed-off-by: Stephen Boyd <sboyd@kernel.org> +Link: https://lore.kernel.org/r/20241016212738.897691-1-sboyd@kernel.org +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/clk/.kunitconfig | 1 + + drivers/clk/Kconfig | 2 -- + 2 files changed, 1 insertion(+), 2 deletions(-) + +diff --git a/drivers/clk/.kunitconfig b/drivers/clk/.kunitconfig +index 54ece92070552..08e26137f3d9c 100644 +--- a/drivers/clk/.kunitconfig ++++ b/drivers/clk/.kunitconfig +@@ -1,5 +1,6 @@ + CONFIG_KUNIT=y + CONFIG_OF=y ++CONFIG_OF_OVERLAY=y + CONFIG_COMMON_CLK=y + CONFIG_CLK_KUNIT_TEST=y + CONFIG_CLK_FIXED_RATE_KUNIT_TEST=y +diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig +index 299bc678ed1b9..0fe07a594b4e1 100644 +--- a/drivers/clk/Kconfig ++++ b/drivers/clk/Kconfig +@@ -517,7 +517,6 @@ config CLK_KUNIT_TEST + tristate "Basic Clock Framework Kunit Tests" if !KUNIT_ALL_TESTS + depends on KUNIT + default KUNIT_ALL_TESTS +- select OF_OVERLAY if OF + select DTC + help + Kunit tests for the common clock framework. +@@ -526,7 +525,6 @@ config CLK_FIXED_RATE_KUNIT_TEST + tristate "Basic fixed rate clk type KUnit test" if !KUNIT_ALL_TESTS + depends on KUNIT + default KUNIT_ALL_TESTS +- select OF_OVERLAY if OF + select DTC + help + KUnit tests for the basic fixed rate clk type. +-- +2.43.0 + diff --git a/queue-6.12/clk-clk-apple-nco-add-null-check-in-applnco_probe.patch b/queue-6.12/clk-clk-apple-nco-add-null-check-in-applnco_probe.patch new file mode 100644 index 00000000000..82eb42ff901 --- /dev/null +++ b/queue-6.12/clk-clk-apple-nco-add-null-check-in-applnco_probe.patch @@ -0,0 +1,42 @@ +From 5fcebb5682977f8c3be7d08a96584f8e97813188 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Thu, 14 Nov 2024 15:28:20 +0800 +Subject: clk: clk-apple-nco: Add NULL check in applnco_probe +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Charles Han <hanchunchao@inspur.com> + +[ Upstream commit 969c765e2b508cca9099d246c010a1e48dcfd089 ] + +Add NULL check in applnco_probe, to handle kernel NULL pointer +dereference error. + +Fixes: 6641057d5dba ("clk: clk-apple-nco: Add driver for Apple NCO") +Signed-off-by: Charles Han <hanchunchao@inspur.com> +Link: https://lore.kernel.org/r/20241114072820.3071-1-hanchunchao@inspur.com +Reviewed-by: Martin PoviÅ¡er <povik+lin@cutebit.org> +Signed-off-by: Stephen Boyd <sboyd@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/clk/clk-apple-nco.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/clk/clk-apple-nco.c b/drivers/clk/clk-apple-nco.c +index 39472a51530a3..457a48d489412 100644 +--- a/drivers/clk/clk-apple-nco.c ++++ b/drivers/clk/clk-apple-nco.c +@@ -297,6 +297,9 @@ static int applnco_probe(struct platform_device *pdev) + memset(&init, 0, sizeof(init)); + init.name = devm_kasprintf(&pdev->dev, GFP_KERNEL, + "%s-%d", np->name, i); ++ if (!init.name) ++ return -ENOMEM; ++ + init.ops = &applnco_ops; + init.parent_data = &pdata; + init.num_parents = 1; +-- +2.43.0 + diff --git a/queue-6.12/clk-clk-axi-clkgen-make-sure-to-enable-the-axi-bus-c.patch b/queue-6.12/clk-clk-axi-clkgen-make-sure-to-enable-the-axi-bus-c.patch new file mode 100644 index 00000000000..fc1ad9045a9 --- /dev/null +++ b/queue-6.12/clk-clk-axi-clkgen-make-sure-to-enable-the-axi-bus-c.patch @@ -0,0 +1,82 @@ +From 76b3a137415f2f8799981df9a87499b2acc96ef8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Tue, 29 Oct 2024 14:59:42 +0100 +Subject: clk: clk-axi-clkgen: make sure to enable the AXI bus clock + +From: Nuno Sa <nuno.sa@analog.com> + +[ Upstream commit c64ef7e4851d1a9abbb7f7833e4936973ac5ba79 ] + +In order to access the registers of the HW, we need to make sure that +the AXI bus clock is enabled. Hence let's increase the number of clocks +by one. + +In order to keep backward compatibility and make sure old DTs still work +we check if clock-names is available or not. If it is, then we can +disambiguate between really having the AXI clock or a parent clock and +so we can enable the bus clock. If not, we fallback to what was done +before and don't explicitly enable the AXI bus clock. + +Note that if clock-names is given, the axi clock must be the last one in +the phandle array (also enforced in the DT bindings) so that we can reuse +as much code as possible. + +Fixes: 0e646c52cf0e ("clk: Add axi-clkgen driver") +Signed-off-by: Nuno Sa <nuno.sa@analog.com> +Link: https://lore.kernel.org/r/20241029-axi-clkgen-fix-axiclk-v2-2-bc5e0733ad76@analog.com +Signed-off-by: Stephen Boyd <sboyd@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/clk/clk-axi-clkgen.c | 22 ++++++++++++++++++++-- + 1 file changed, 20 insertions(+), 2 deletions(-) + +diff --git a/drivers/clk/clk-axi-clkgen.c b/drivers/clk/clk-axi-clkgen.c +index bf4d8ddc93aea..934e53a96ddda 100644 +--- a/drivers/clk/clk-axi-clkgen.c ++++ b/drivers/clk/clk-axi-clkgen.c +@@ -7,6 +7,7 @@ + */ + + #include <linux/platform_device.h> ++#include <linux/clk.h> + #include <linux/clk-provider.h> + #include <linux/slab.h> + #include <linux/io.h> +@@ -512,6 +513,7 @@ static int axi_clkgen_probe(struct platform_device *pdev) + struct clk_init_data init; + const char *parent_names[2]; + const char *clk_name; ++ struct clk *axi_clk; + unsigned int i; + int ret; + +@@ -528,8 +530,24 @@ static int axi_clkgen_probe(struct platform_device *pdev) + return PTR_ERR(axi_clkgen->base); + + init.num_parents = of_clk_get_parent_count(pdev->dev.of_node); +- if (init.num_parents < 1 || init.num_parents > 2) +- return -EINVAL; ++ ++ axi_clk = devm_clk_get_enabled(&pdev->dev, "s_axi_aclk"); ++ if (!IS_ERR(axi_clk)) { ++ if (init.num_parents < 2 || init.num_parents > 3) ++ return -EINVAL; ++ ++ init.num_parents -= 1; ++ } else { ++ /* ++ * Legacy... So that old DTs which do not have clock-names still ++ * work. In this case we don't explicitly enable the AXI bus ++ * clock. ++ */ ++ if (PTR_ERR(axi_clk) != -ENOENT) ++ return PTR_ERR(axi_clk); ++ if (init.num_parents < 1 || init.num_parents > 2) ++ return -EINVAL; ++ } + + for (i = 0; i < init.num_parents; i++) { + parent_names[i] = of_clk_get_parent_name(pdev->dev.of_node, i); +-- +2.43.0 + diff --git a/queue-6.12/clk-en7523-fix-estimation-of-fixed-rate-for-en7581.patch b/queue-6.12/clk-en7523-fix-estimation-of-fixed-rate-for-en7581.patch new file mode 100644 index 00000000000..3be2adf5d25 --- /dev/null +++ b/queue-6.12/clk-en7523-fix-estimation-of-fixed-rate-for-en7581.patch @@ -0,0 +1,162 @@ +From 13cec9c56c267ccba57ab8f0e3f593696db54f62 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Tue, 12 Nov 2024 01:08:52 +0100 +Subject: clk: en7523: fix estimation of fixed rate for EN7581 + +From: Lorenzo Bianconi <lorenzo@kernel.org> + +[ Upstream commit f98eded9e9ab048c88ff59c5523e703a6ced5523 ] + +Introduce en7581_base_clks array in order to define per-SoC fixed-rate +clock parameters and fix wrong parameters for emi, npu and crypto EN7581 +clocks + +Fixes: 66bc47326ce2 ("clk: en7523: Add EN7581 support") +Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org> +Link: https://lore.kernel.org/r/20241112-clk-en7581-syscon-v2-5-8ada5e394ae4@kernel.org +Signed-off-by: Stephen Boyd <sboyd@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/clk/clk-en7523.c | 105 ++++++++++++++++++++++++++++++++++++++- + 1 file changed, 103 insertions(+), 2 deletions(-) + +diff --git a/drivers/clk/clk-en7523.c b/drivers/clk/clk-en7523.c +index 7f83cbce01eeb..fdd8ea989ed24 100644 +--- a/drivers/clk/clk-en7523.c ++++ b/drivers/clk/clk-en7523.c +@@ -37,6 +37,7 @@ + #define REG_NP_SCU_SSTR 0x9c + #define REG_PCIE_XSI0_SEL_MASK GENMASK(14, 13) + #define REG_PCIE_XSI1_SEL_MASK GENMASK(12, 11) ++#define REG_CRYPTO_CLKSRC2 0x20c + + #define REG_RST_CTRL2 0x00 + #define REG_RST_CTRL1 0x04 +@@ -89,6 +90,10 @@ static const u32 emi_base[] = { 333000000, 400000000 }; + static const u32 bus_base[] = { 500000000, 540000000 }; + static const u32 slic_base[] = { 100000000, 3125000 }; + static const u32 npu_base[] = { 333000000, 400000000, 500000000 }; ++/* EN7581 */ ++static const u32 emi7581_base[] = { 540000000, 480000000, 400000000, 300000000 }; ++static const u32 npu7581_base[] = { 800000000, 750000000, 720000000, 600000000 }; ++static const u32 crypto_base[] = { 540000000, 480000000 }; + + static const struct en_clk_desc en7523_base_clks[] = { + { +@@ -186,6 +191,102 @@ static const struct en_clk_desc en7523_base_clks[] = { + } + }; + ++static const struct en_clk_desc en7581_base_clks[] = { ++ { ++ .id = EN7523_CLK_GSW, ++ .name = "gsw", ++ ++ .base_reg = REG_GSW_CLK_DIV_SEL, ++ .base_bits = 1, ++ .base_shift = 8, ++ .base_values = gsw_base, ++ .n_base_values = ARRAY_SIZE(gsw_base), ++ ++ .div_bits = 3, ++ .div_shift = 0, ++ .div_step = 1, ++ .div_offset = 1, ++ }, { ++ .id = EN7523_CLK_EMI, ++ .name = "emi", ++ ++ .base_reg = REG_EMI_CLK_DIV_SEL, ++ .base_bits = 2, ++ .base_shift = 8, ++ .base_values = emi7581_base, ++ .n_base_values = ARRAY_SIZE(emi7581_base), ++ ++ .div_bits = 3, ++ .div_shift = 0, ++ .div_step = 1, ++ .div_offset = 1, ++ }, { ++ .id = EN7523_CLK_BUS, ++ .name = "bus", ++ ++ .base_reg = REG_BUS_CLK_DIV_SEL, ++ .base_bits = 1, ++ .base_shift = 8, ++ .base_values = bus_base, ++ .n_base_values = ARRAY_SIZE(bus_base), ++ ++ .div_bits = 3, ++ .div_shift = 0, ++ .div_step = 1, ++ .div_offset = 1, ++ }, { ++ .id = EN7523_CLK_SLIC, ++ .name = "slic", ++ ++ .base_reg = REG_SPI_CLK_FREQ_SEL, ++ .base_bits = 1, ++ .base_shift = 0, ++ .base_values = slic_base, ++ .n_base_values = ARRAY_SIZE(slic_base), ++ ++ .div_reg = REG_SPI_CLK_DIV_SEL, ++ .div_bits = 5, ++ .div_shift = 24, ++ .div_val0 = 20, ++ .div_step = 2, ++ }, { ++ .id = EN7523_CLK_SPI, ++ .name = "spi", ++ ++ .base_reg = REG_SPI_CLK_DIV_SEL, ++ ++ .base_value = 400000000, ++ ++ .div_bits = 5, ++ .div_shift = 8, ++ .div_val0 = 40, ++ .div_step = 2, ++ }, { ++ .id = EN7523_CLK_NPU, ++ .name = "npu", ++ ++ .base_reg = REG_NPU_CLK_DIV_SEL, ++ .base_bits = 2, ++ .base_shift = 8, ++ .base_values = npu7581_base, ++ .n_base_values = ARRAY_SIZE(npu7581_base), ++ ++ .div_bits = 3, ++ .div_shift = 0, ++ .div_step = 1, ++ .div_offset = 1, ++ }, { ++ .id = EN7523_CLK_CRYPTO, ++ .name = "crypto", ++ ++ .base_reg = REG_CRYPTO_CLKSRC2, ++ .base_bits = 1, ++ .base_shift = 0, ++ .base_values = crypto_base, ++ .n_base_values = ARRAY_SIZE(crypto_base), ++ } ++}; ++ + static const u16 en7581_rst_ofs[] = { + REG_RST_CTRL2, + REG_RST_CTRL1, +@@ -457,8 +558,8 @@ static void en7581_register_clocks(struct device *dev, struct clk_hw_onecell_dat + u32 rate; + int i; + +- for (i = 0; i < ARRAY_SIZE(en7523_base_clks); i++) { +- const struct en_clk_desc *desc = &en7523_base_clks[i]; ++ for (i = 0; i < ARRAY_SIZE(en7581_base_clks); i++) { ++ const struct en_clk_desc *desc = &en7581_base_clks[i]; + u32 val, reg = desc->div_reg ? desc->div_reg : desc->base_reg; + int err; + +-- +2.43.0 + diff --git a/queue-6.12/clk-en7523-introduce-chip_scu-regmap.patch b/queue-6.12/clk-en7523-introduce-chip_scu-regmap.patch new file mode 100644 index 00000000000..1c8024dd527 --- /dev/null +++ b/queue-6.12/clk-en7523-introduce-chip_scu-regmap.patch @@ -0,0 +1,173 @@ +From d179b824d711645f3a01ae28fb5b51141cc3868f Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Tue, 12 Nov 2024 01:08:51 +0100 +Subject: clk: en7523: introduce chip_scu regmap + +From: Lorenzo Bianconi <lorenzo@kernel.org> + +[ Upstream commit f72fc22038dd544fa4d39c06e8c81c09c0041ed4 ] + +Introduce chip_scu regmap pointer since EN7581 SoC will access chip-scu +memory area via a syscon node. Remove first memory region mapping +for EN7581 SoC. This patch does not introduce any backward incompatibility +since the dts for EN7581 SoC is not upstream yet. + +Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org> +Link: https://lore.kernel.org/r/20241112-clk-en7581-syscon-v2-4-8ada5e394ae4@kernel.org +Signed-off-by: Stephen Boyd <sboyd@kernel.org> +Stable-dep-of: f98eded9e9ab ("clk: en7523: fix estimation of fixed rate for EN7581") +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/clk/clk-en7523.c | 81 ++++++++++++++++++++++++++++++---------- + 1 file changed, 61 insertions(+), 20 deletions(-) + +diff --git a/drivers/clk/clk-en7523.c b/drivers/clk/clk-en7523.c +index da112c9fe8ef9..7f83cbce01eeb 100644 +--- a/drivers/clk/clk-en7523.c ++++ b/drivers/clk/clk-en7523.c +@@ -3,8 +3,10 @@ + #include <linux/delay.h> + #include <linux/clk-provider.h> + #include <linux/io.h> ++#include <linux/mfd/syscon.h> + #include <linux/platform_device.h> + #include <linux/property.h> ++#include <linux/regmap.h> + #include <linux/reset-controller.h> + #include <dt-bindings/clock/en7523-clk.h> + #include <dt-bindings/reset/airoha,en7581-reset.h> +@@ -247,15 +249,11 @@ static const u16 en7581_rst_map[] = { + [EN7581_XPON_MAC_RST] = RST_NR_PER_BANK + 31, + }; + +-static unsigned int en7523_get_base_rate(void __iomem *base, unsigned int i) ++static u32 en7523_get_base_rate(const struct en_clk_desc *desc, u32 val) + { +- const struct en_clk_desc *desc = &en7523_base_clks[i]; +- u32 val; +- + if (!desc->base_bits) + return desc->base_value; + +- val = readl(base + desc->base_reg); + val >>= desc->base_shift; + val &= (1 << desc->base_bits) - 1; + +@@ -265,16 +263,11 @@ static unsigned int en7523_get_base_rate(void __iomem *base, unsigned int i) + return desc->base_values[val]; + } + +-static u32 en7523_get_div(void __iomem *base, int i) ++static u32 en7523_get_div(const struct en_clk_desc *desc, u32 val) + { +- const struct en_clk_desc *desc = &en7523_base_clks[i]; +- u32 reg, val; +- + if (!desc->div_bits) + return 1; + +- reg = desc->div_reg ? desc->div_reg : desc->base_reg; +- val = readl(base + reg); + val >>= desc->div_shift; + val &= (1 << desc->div_bits) - 1; + +@@ -416,9 +409,12 @@ static void en7523_register_clocks(struct device *dev, struct clk_hw_onecell_dat + + for (i = 0; i < ARRAY_SIZE(en7523_base_clks); i++) { + const struct en_clk_desc *desc = &en7523_base_clks[i]; ++ u32 reg = desc->div_reg ? desc->div_reg : desc->base_reg; ++ u32 val = readl(base + desc->base_reg); + +- rate = en7523_get_base_rate(base, i); +- rate /= en7523_get_div(base, i); ++ rate = en7523_get_base_rate(desc, val); ++ val = readl(base + reg); ++ rate /= en7523_get_div(desc, val); + + hw = clk_hw_register_fixed_rate(dev, desc->name, NULL, 0, rate); + if (IS_ERR(hw)) { +@@ -454,21 +450,66 @@ static int en7523_clk_hw_init(struct platform_device *pdev, + return 0; + } + ++static void en7581_register_clocks(struct device *dev, struct clk_hw_onecell_data *clk_data, ++ struct regmap *map, void __iomem *base) ++{ ++ struct clk_hw *hw; ++ u32 rate; ++ int i; ++ ++ for (i = 0; i < ARRAY_SIZE(en7523_base_clks); i++) { ++ const struct en_clk_desc *desc = &en7523_base_clks[i]; ++ u32 val, reg = desc->div_reg ? desc->div_reg : desc->base_reg; ++ int err; ++ ++ err = regmap_read(map, desc->base_reg, &val); ++ if (err) { ++ pr_err("Failed reading fixed clk rate %s: %d\n", ++ desc->name, err); ++ continue; ++ } ++ rate = en7523_get_base_rate(desc, val); ++ ++ err = regmap_read(map, reg, &val); ++ if (err) { ++ pr_err("Failed reading fixed clk div %s: %d\n", ++ desc->name, err); ++ continue; ++ } ++ rate /= en7523_get_div(desc, val); ++ ++ hw = clk_hw_register_fixed_rate(dev, desc->name, NULL, 0, rate); ++ if (IS_ERR(hw)) { ++ pr_err("Failed to register clk %s: %ld\n", ++ desc->name, PTR_ERR(hw)); ++ continue; ++ } ++ ++ clk_data->hws[desc->id] = hw; ++ } ++ ++ hw = en7523_register_pcie_clk(dev, base); ++ clk_data->hws[EN7523_CLK_PCIE] = hw; ++ ++ clk_data->num = EN7523_NUM_CLOCKS; ++} ++ + static int en7581_clk_hw_init(struct platform_device *pdev, + struct clk_hw_onecell_data *clk_data) + { +- void __iomem *base, *np_base; ++ void __iomem *np_base; ++ struct regmap *map; + u32 val; + +- base = devm_platform_ioremap_resource(pdev, 0); +- if (IS_ERR(base)) +- return PTR_ERR(base); ++ map = syscon_regmap_lookup_by_compatible("airoha,en7581-chip-scu"); ++ if (IS_ERR(map)) ++ return PTR_ERR(map); + +- np_base = devm_platform_ioremap_resource(pdev, 1); ++ np_base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(np_base)) + return PTR_ERR(np_base); + +- en7523_register_clocks(&pdev->dev, clk_data, base, np_base); ++ en7581_register_clocks(&pdev->dev, clk_data, map, np_base); + + val = readl(np_base + REG_NP_SCU_SSTR); + val &= ~(REG_PCIE_XSI0_SEL_MASK | REG_PCIE_XSI1_SEL_MASK); +@@ -545,7 +586,7 @@ static int en7523_reset_register(struct platform_device *pdev, + if (!soc_data->reset.idx_map_nr) + return 0; + +- base = devm_platform_ioremap_resource(pdev, 2); ++ base = devm_platform_ioremap_resource(pdev, 1); + if (IS_ERR(base)) + return PTR_ERR(base); + +-- +2.43.0 + diff --git a/queue-6.12/clk-en7523-move-clock_register-in-hw_init-callback.patch b/queue-6.12/clk-en7523-move-clock_register-in-hw_init-callback.patch new file mode 100644 index 00000000000..5b35d9c2868 --- /dev/null +++ b/queue-6.12/clk-en7523-move-clock_register-in-hw_init-callback.patch @@ -0,0 +1,157 @@ +From b4b117fe43282f533a57c7eeace080750afe9385 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Tue, 12 Nov 2024 01:08:50 +0100 +Subject: clk: en7523: move clock_register in hw_init callback + +From: Lorenzo Bianconi <lorenzo@kernel.org> + +[ Upstream commit b8bdfc666bc5f58caf46e67b615132fccbaca3d4 ] + +Move en7523_register_clocks routine in hw_init callback. +Introduce en7523_clk_hw_init callback for EN7523 SoC. +This is a preliminary patch to differentiate IO mapped region between +EN7523 and EN7581 SoCs in order to access chip-scu IO region +<0x1fa20000 0x384> on EN7581 SoC as syscon device since it contains +miscellaneous registers needed by multiple devices (clock, pinctrl ..). + +Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org> +Link: https://lore.kernel.org/r/20241112-clk-en7581-syscon-v2-3-8ada5e394ae4@kernel.org +Signed-off-by: Stephen Boyd <sboyd@kernel.org> +Stable-dep-of: f98eded9e9ab ("clk: en7523: fix estimation of fixed rate for EN7581") +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/clk/clk-en7523.c | 82 ++++++++++++++++++++++++---------------- + 1 file changed, 50 insertions(+), 32 deletions(-) + +diff --git a/drivers/clk/clk-en7523.c b/drivers/clk/clk-en7523.c +index ec6716844fdcf..da112c9fe8ef9 100644 +--- a/drivers/clk/clk-en7523.c ++++ b/drivers/clk/clk-en7523.c +@@ -78,7 +78,8 @@ struct en_clk_soc_data { + const u16 *idx_map; + u16 idx_map_nr; + } reset; +- int (*hw_init)(struct platform_device *pdev, void __iomem *np_base); ++ int (*hw_init)(struct platform_device *pdev, ++ struct clk_hw_onecell_data *clk_data); + }; + + static const u32 gsw_base[] = { 400000000, 500000000 }; +@@ -406,20 +407,6 @@ static void en7581_pci_disable(struct clk_hw *hw) + usleep_range(1000, 2000); + } + +-static int en7581_clk_hw_init(struct platform_device *pdev, +- void __iomem *np_base) +-{ +- u32 val; +- +- val = readl(np_base + REG_NP_SCU_SSTR); +- val &= ~(REG_PCIE_XSI0_SEL_MASK | REG_PCIE_XSI1_SEL_MASK); +- writel(val, np_base + REG_NP_SCU_SSTR); +- val = readl(np_base + REG_NP_SCU_PCIC); +- writel(val | 3, np_base + REG_NP_SCU_PCIC); +- +- return 0; +-} +- + static void en7523_register_clocks(struct device *dev, struct clk_hw_onecell_data *clk_data, + void __iomem *base, void __iomem *np_base) + { +@@ -449,6 +436,49 @@ static void en7523_register_clocks(struct device *dev, struct clk_hw_onecell_dat + clk_data->num = EN7523_NUM_CLOCKS; + } + ++static int en7523_clk_hw_init(struct platform_device *pdev, ++ struct clk_hw_onecell_data *clk_data) ++{ ++ void __iomem *base, *np_base; ++ ++ base = devm_platform_ioremap_resource(pdev, 0); ++ if (IS_ERR(base)) ++ return PTR_ERR(base); ++ ++ np_base = devm_platform_ioremap_resource(pdev, 1); ++ if (IS_ERR(np_base)) ++ return PTR_ERR(np_base); ++ ++ en7523_register_clocks(&pdev->dev, clk_data, base, np_base); ++ ++ return 0; ++} ++ ++static int en7581_clk_hw_init(struct platform_device *pdev, ++ struct clk_hw_onecell_data *clk_data) ++{ ++ void __iomem *base, *np_base; ++ u32 val; ++ ++ base = devm_platform_ioremap_resource(pdev, 0); ++ if (IS_ERR(base)) ++ return PTR_ERR(base); ++ ++ np_base = devm_platform_ioremap_resource(pdev, 1); ++ if (IS_ERR(np_base)) ++ return PTR_ERR(np_base); ++ ++ en7523_register_clocks(&pdev->dev, clk_data, base, np_base); ++ ++ val = readl(np_base + REG_NP_SCU_SSTR); ++ val &= ~(REG_PCIE_XSI0_SEL_MASK | REG_PCIE_XSI1_SEL_MASK); ++ writel(val, np_base + REG_NP_SCU_SSTR); ++ val = readl(np_base + REG_NP_SCU_PCIC); ++ writel(val | 3, np_base + REG_NP_SCU_PCIC); ++ ++ return 0; ++} ++ + static int en7523_reset_update(struct reset_controller_dev *rcdev, + unsigned long id, bool assert) + { +@@ -543,31 +573,18 @@ static int en7523_clk_probe(struct platform_device *pdev) + struct device_node *node = pdev->dev.of_node; + const struct en_clk_soc_data *soc_data; + struct clk_hw_onecell_data *clk_data; +- void __iomem *base, *np_base; + int r; + +- base = devm_platform_ioremap_resource(pdev, 0); +- if (IS_ERR(base)) +- return PTR_ERR(base); +- +- np_base = devm_platform_ioremap_resource(pdev, 1); +- if (IS_ERR(np_base)) +- return PTR_ERR(np_base); +- +- soc_data = device_get_match_data(&pdev->dev); +- if (soc_data->hw_init) { +- r = soc_data->hw_init(pdev, np_base); +- if (r) +- return r; +- } +- + clk_data = devm_kzalloc(&pdev->dev, + struct_size(clk_data, hws, EN7523_NUM_CLOCKS), + GFP_KERNEL); + if (!clk_data) + return -ENOMEM; + +- en7523_register_clocks(&pdev->dev, clk_data, base, np_base); ++ soc_data = device_get_match_data(&pdev->dev); ++ r = soc_data->hw_init(pdev, clk_data); ++ if (r) ++ return r; + + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); + if (r) +@@ -590,6 +607,7 @@ static const struct en_clk_soc_data en7523_data = { + .prepare = en7523_pci_prepare, + .unprepare = en7523_pci_unprepare, + }, ++ .hw_init = en7523_clk_hw_init, + }; + + static const struct en_clk_soc_data en7581_data = { +-- +2.43.0 + diff --git a/queue-6.12/clk-en7523-remove-reg_pcie-_-mem-mem_mask-configurat.patch b/queue-6.12/clk-en7523-remove-reg_pcie-_-mem-mem_mask-configurat.patch new file mode 100644 index 00000000000..875bdaec630 --- /dev/null +++ b/queue-6.12/clk-en7523-remove-reg_pcie-_-mem-mem_mask-configurat.patch @@ -0,0 +1,72 @@ +From 2c03ec18973799fed12d33a95713e9dfc4630395 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Tue, 12 Nov 2024 01:08:49 +0100 +Subject: clk: en7523: remove REG_PCIE*_{MEM,MEM_MASK} configuration + +From: Lorenzo Bianconi <lorenzo@kernel.org> + +[ Upstream commit c31d1cdd7bff1d2c13d435bb9d0c76bfaa332097 ] + +REG_PCIE*_MEM and REG_PCIE*_MEM_MASK regs (PBUS_CSR memory region) are not +part of the scu block on the EN7581 SoC and they are used to select the +PCIE ports on the PBUS, so remove this configuration from the clock driver +and set these registers in the PCIE host driver instead. +This patch does not introduce any backward incompatibility since the dts +for EN7581 SoC is not upstream yet. + +Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org> +Link: https://lore.kernel.org/r/20241112-clk-en7581-syscon-v2-2-8ada5e394ae4@kernel.org +Signed-off-by: Stephen Boyd <sboyd@kernel.org> +Stable-dep-of: f98eded9e9ab ("clk: en7523: fix estimation of fixed rate for EN7581") +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/clk/clk-en7523.c | 18 ------------------ + 1 file changed, 18 deletions(-) + +diff --git a/drivers/clk/clk-en7523.c b/drivers/clk/clk-en7523.c +index 22fbea61c3dcc..ec6716844fdcf 100644 +--- a/drivers/clk/clk-en7523.c ++++ b/drivers/clk/clk-en7523.c +@@ -31,12 +31,6 @@ + #define REG_RESET_CONTROL_PCIE1 BIT(27) + #define REG_RESET_CONTROL_PCIE2 BIT(26) + /* EN7581 */ +-#define REG_PCIE0_MEM 0x00 +-#define REG_PCIE0_MEM_MASK 0x04 +-#define REG_PCIE1_MEM 0x08 +-#define REG_PCIE1_MEM_MASK 0x0c +-#define REG_PCIE2_MEM 0x10 +-#define REG_PCIE2_MEM_MASK 0x14 + #define REG_NP_SCU_PCIC 0x88 + #define REG_NP_SCU_SSTR 0x9c + #define REG_PCIE_XSI0_SEL_MASK GENMASK(14, 13) +@@ -415,26 +409,14 @@ static void en7581_pci_disable(struct clk_hw *hw) + static int en7581_clk_hw_init(struct platform_device *pdev, + void __iomem *np_base) + { +- void __iomem *pb_base; + u32 val; + +- pb_base = devm_platform_ioremap_resource(pdev, 3); +- if (IS_ERR(pb_base)) +- return PTR_ERR(pb_base); +- + val = readl(np_base + REG_NP_SCU_SSTR); + val &= ~(REG_PCIE_XSI0_SEL_MASK | REG_PCIE_XSI1_SEL_MASK); + writel(val, np_base + REG_NP_SCU_SSTR); + val = readl(np_base + REG_NP_SCU_PCIC); + writel(val | 3, np_base + REG_NP_SCU_PCIC); + +- writel(0x20000000, pb_base + REG_PCIE0_MEM); +- writel(0xfc000000, pb_base + REG_PCIE0_MEM_MASK); +- writel(0x24000000, pb_base + REG_PCIE1_MEM); +- writel(0xfc000000, pb_base + REG_PCIE1_MEM_MASK); +- writel(0x28000000, pb_base + REG_PCIE2_MEM); +- writel(0xfc000000, pb_base + REG_PCIE2_MEM_MASK); +- + return 0; + } + +-- +2.43.0 + diff --git a/queue-6.12/clk-imx-clk-scu-fix-clk-enable-state-save-and-restor.patch b/queue-6.12/clk-imx-clk-scu-fix-clk-enable-state-save-and-restor.patch new file mode 100644 index 00000000000..30b88338c87 --- /dev/null +++ b/queue-6.12/clk-imx-clk-scu-fix-clk-enable-state-save-and-restor.patch @@ -0,0 +1,45 @@ +From 071a1821e9366849dd1f8e5c3f07c90a349c195e Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Sun, 27 Oct 2024 20:00:10 +0800 +Subject: clk: imx: clk-scu: fix clk enable state save and restore + +From: Dong Aisheng <aisheng.dong@nxp.com> + +[ Upstream commit e81361f6cf9bf4a1848b0813bc4becb2250870b8 ] + +The scu clk_ops only inplements prepare() and unprepare() callback. +Saving the clock state during suspend by checking clk_hw_is_enabled() +is not safe as it's possible that some device drivers may only +disable the clocks without unprepare. Then the state retention will not +work for such clocks. + +Fixing it by checking clk_hw_is_prepared() which is more reasonable +and safe. + +Fixes: d0409631f466 ("clk: imx: scu: add suspend/resume support") +Reviewed-by: Peng Fan <peng.fan@nxp.com> +Tested-by: Carlos Song <carlos.song@nxp.com> +Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com> +Link: https://lore.kernel.org/r/20241027-imx-clk-v1-v3-4-89152574d1d7@nxp.com +Signed-off-by: Abel Vesa <abel.vesa@linaro.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/clk/imx/clk-scu.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/clk/imx/clk-scu.c b/drivers/clk/imx/clk-scu.c +index b1dd0c08e091b..b27186aaf2a15 100644 +--- a/drivers/clk/imx/clk-scu.c ++++ b/drivers/clk/imx/clk-scu.c +@@ -596,7 +596,7 @@ static int __maybe_unused imx_clk_scu_suspend(struct device *dev) + clk->rate = clk_scu_recalc_rate(&clk->hw, 0); + else + clk->rate = clk_hw_get_rate(&clk->hw); +- clk->is_enabled = clk_hw_is_enabled(&clk->hw); ++ clk->is_enabled = clk_hw_is_prepared(&clk->hw); + + if (clk->parent) + dev_dbg(dev, "save parent %s idx %u\n", clk_hw_get_name(clk->parent), +-- +2.43.0 + diff --git a/queue-6.12/clk-imx-fracn-gppll-correct-pll-initialization-flow.patch b/queue-6.12/clk-imx-fracn-gppll-correct-pll-initialization-flow.patch new file mode 100644 index 00000000000..11aa5fe672a --- /dev/null +++ b/queue-6.12/clk-imx-fracn-gppll-correct-pll-initialization-flow.patch @@ -0,0 +1,60 @@ +From d16f996aa14c8fc18ece8eada3eec96c071de058 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Sun, 27 Oct 2024 20:00:08 +0800 +Subject: clk: imx: fracn-gppll: correct PLL initialization flow +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Peng Fan <peng.fan@nxp.com> + +[ Upstream commit 557be501c38e1864b948fc6ccdf4b035d610a2ea ] + +Per i.MX93 Reference Mannual 22.4 Initialization information +1. Program appropriate value of DIV[ODIV], DIV[RDIV] and DIV[MFI] + as per Integer mode. +2. Wait for 5 μs. +3. Program the following field in CTRL register. + Set CTRL[POWERUP] to 1'b1 to enable PLL block. +4. Poll PLL_STATUS[PLL_LOCK] register, and wait till PLL_STATUS[PLL_LOCK] + is 1'b1 and pll_lock output signal is 1'b1. +5. Set CTRL[CLKMUX_EN] to 1'b1 to enable PLL output clock. + +So move the CLKMUX_EN operation after PLL locked. + +Fixes: 1b26cb8a77a4 ("clk: imx: support fracn gppll") +Co-developed-by: Jacky Bai <ping.bai@nxp.com> +Signed-off-by: Jacky Bai <ping.bai@nxp.com> +Signed-off-by: Peng Fan <peng.fan@nxp.com> +Reviewed-by: Abel Vesa <abel.vesa@linaro.org> +Link: https://lore.kernel.org/r/20241027-imx-clk-v1-v3-2-89152574d1d7@nxp.com +Signed-off-by: Abel Vesa <abel.vesa@linaro.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/clk/imx/clk-fracn-gppll.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/drivers/clk/imx/clk-fracn-gppll.c b/drivers/clk/imx/clk-fracn-gppll.c +index 591e0364ee5c1..4749c3e0b7051 100644 +--- a/drivers/clk/imx/clk-fracn-gppll.c ++++ b/drivers/clk/imx/clk-fracn-gppll.c +@@ -303,13 +303,13 @@ static int clk_fracn_gppll_prepare(struct clk_hw *hw) + val |= POWERUP_MASK; + writel_relaxed(val, pll->base + PLL_CTRL); + +- val |= CLKMUX_EN; +- writel_relaxed(val, pll->base + PLL_CTRL); +- + ret = clk_fracn_gppll_wait_lock(pll); + if (ret) + return ret; + ++ val |= CLKMUX_EN; ++ writel_relaxed(val, pll->base + PLL_CTRL); ++ + val &= ~CLKMUX_BYPASS; + writel_relaxed(val, pll->base + PLL_CTRL); + +-- +2.43.0 + diff --git a/queue-6.12/clk-imx-fracn-gppll-fix-pll-power-up.patch b/queue-6.12/clk-imx-fracn-gppll-fix-pll-power-up.patch new file mode 100644 index 00000000000..10bf8129bc0 --- /dev/null +++ b/queue-6.12/clk-imx-fracn-gppll-fix-pll-power-up.patch @@ -0,0 +1,87 @@ +From 9277b5274e78f8e8549797310f56b93d78fd8e07 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Sun, 27 Oct 2024 20:00:09 +0800 +Subject: clk: imx: fracn-gppll: fix pll power up + +From: Peng Fan <peng.fan@nxp.com> + +[ Upstream commit ff4279618f0aec350b0fb41b2b35841324fbd96e ] + +To i.MX93 which features dual Cortex-A55 cores and DSU, when using +writel_relaxed to write value to PLL registers, the value might be +buffered. To make sure the value has been written into the hardware, +using readl to read back the register could achieve the goal. + +current PLL power up flow can be simplified as below: + 1. writel_relaxed to set the PLL POWERUP bit; + 2. readl_poll_timeout to check the PLL lock bit: + a). timeout = ktime_add_us(ktime_get(), timeout_us); + b). readl the pll the lock reg; + c). check if the pll lock bit ready + d). check if timeout + +But in some corner cases, both the write in step 1 and read in +step 2 will be blocked by other bus transaction in the SoC for a +long time, saying the value into real hardware is just before step b). +That means the timeout counting has begins for quite sometime since +step a), but value still not written into real hardware until bus +released just at a point before step b). + +Then there maybe chances that the pll lock bit is not ready +when readl done but the timeout happens. readl_poll_timeout will +err return due to timeout. To avoid such unexpected failure, +read back the reg to make sure the write has been done in HW +reg. + +So use readl after writel_relaxed to fix the issue. + +Since we are here, to avoid udelay to run before writel_relaxed, use +readl before udelay. + +Fixes: 1b26cb8a77a4 ("clk: imx: support fracn gppll") +Co-developed-by: Jacky Bai <ping.bai@nxp.com> +Signed-off-by: Jacky Bai <ping.bai@nxp.com> +Signed-off-by: Peng Fan <peng.fan@nxp.com> +Reviewed-by: Abel Vesa <abel.vesa@linaro.org> +Link: https://lore.kernel.org/r/20241027-imx-clk-v1-v3-3-89152574d1d7@nxp.com +Signed-off-by: Abel Vesa <abel.vesa@linaro.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/clk/imx/clk-fracn-gppll.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/drivers/clk/imx/clk-fracn-gppll.c b/drivers/clk/imx/clk-fracn-gppll.c +index 4749c3e0b7051..85771afd4698a 100644 +--- a/drivers/clk/imx/clk-fracn-gppll.c ++++ b/drivers/clk/imx/clk-fracn-gppll.c +@@ -254,9 +254,11 @@ static int clk_fracn_gppll_set_rate(struct clk_hw *hw, unsigned long drate, + pll_div = FIELD_PREP(PLL_RDIV_MASK, rate->rdiv) | rate->odiv | + FIELD_PREP(PLL_MFI_MASK, rate->mfi); + writel_relaxed(pll_div, pll->base + PLL_DIV); ++ readl(pll->base + PLL_DIV); + if (pll->flags & CLK_FRACN_GPPLL_FRACN) { + writel_relaxed(rate->mfd, pll->base + PLL_DENOMINATOR); + writel_relaxed(FIELD_PREP(PLL_MFN_MASK, rate->mfn), pll->base + PLL_NUMERATOR); ++ readl(pll->base + PLL_NUMERATOR); + } + + /* Wait for 5us according to fracn mode pll doc */ +@@ -265,6 +267,7 @@ static int clk_fracn_gppll_set_rate(struct clk_hw *hw, unsigned long drate, + /* Enable Powerup */ + tmp |= POWERUP_MASK; + writel_relaxed(tmp, pll->base + PLL_CTRL); ++ readl(pll->base + PLL_CTRL); + + /* Wait Lock */ + ret = clk_fracn_gppll_wait_lock(pll); +@@ -302,6 +305,7 @@ static int clk_fracn_gppll_prepare(struct clk_hw *hw) + + val |= POWERUP_MASK; + writel_relaxed(val, pll->base + PLL_CTRL); ++ readl(pll->base + PLL_CTRL); + + ret = clk_fracn_gppll_wait_lock(pll); + if (ret) +-- +2.43.0 + diff --git a/queue-6.12/clk-imx-imx8-acm-fix-return-value-check-in-clk_imx_a.patch b/queue-6.12/clk-imx-imx8-acm-fix-return-value-check-in-clk_imx_a.patch new file mode 100644 index 00000000000..d20203315f2 --- /dev/null +++ b/queue-6.12/clk-imx-imx8-acm-fix-return-value-check-in-clk_imx_a.patch @@ -0,0 +1,43 @@ +From caa507228139f0dbc1660ad7d7492b6f56b6028b Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Sat, 26 Oct 2024 19:24:52 +0800 +Subject: clk: imx: imx8-acm: Fix return value check in + clk_imx_acm_attach_pm_domains() + +From: Yang Yingliang <yangyingliang@huawei.com> + +[ Upstream commit 81a206d736c19139d3863b79e7174f9e98b45499 ] + +If device_link_add() fails, it returns NULL pointer not ERR_PTR(), +replace IS_ERR() with NULL pointer check, and return -EINVAL. + +Fixes: d3a0946d7ac9 ("clk: imx: imx8: add audio clock mux driver") +Signed-off-by: Yang Yingliang <yangyingliang@huawei.com> +Reviewed-by: Peng Fan <peng.fan@nxp.com> +Reviewed-by: Abel Vesa <abel.vesa@linaro.org> +Link: https://lore.kernel.org/r/20241026112452.1523-1-yangyingliang@huaweicloud.com +Signed-off-by: Abel Vesa <abel.vesa@linaro.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/clk/imx/clk-imx8-acm.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/clk/imx/clk-imx8-acm.c b/drivers/clk/imx/clk-imx8-acm.c +index 6c351050b82ae..c169fe53a35f8 100644 +--- a/drivers/clk/imx/clk-imx8-acm.c ++++ b/drivers/clk/imx/clk-imx8-acm.c +@@ -294,9 +294,9 @@ static int clk_imx_acm_attach_pm_domains(struct device *dev, + DL_FLAG_STATELESS | + DL_FLAG_PM_RUNTIME | + DL_FLAG_RPM_ACTIVE); +- if (IS_ERR(dev_pm->pd_dev_link[i])) { ++ if (!dev_pm->pd_dev_link[i]) { + dev_pm_domain_detach(dev_pm->pd_dev[i], false); +- ret = PTR_ERR(dev_pm->pd_dev_link[i]); ++ ret = -EINVAL; + goto detach_pm; + } + } +-- +2.43.0 + diff --git a/queue-6.12/clk-imx-lpcg-scu-sw-workaround-for-errata-e10858.patch b/queue-6.12/clk-imx-lpcg-scu-sw-workaround-for-errata-e10858.patch new file mode 100644 index 00000000000..ea1115cddaa --- /dev/null +++ b/queue-6.12/clk-imx-lpcg-scu-sw-workaround-for-errata-e10858.patch @@ -0,0 +1,113 @@ +From c9885dad12fa893dc88672b1f080713dbc71e2a1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Sun, 27 Oct 2024 20:00:07 +0800 +Subject: clk: imx: lpcg-scu: SW workaround for errata (e10858) + +From: Peng Fan <peng.fan@nxp.com> + +[ Upstream commit 5ee063fac85656bea9cfe3570af147ba1701ba18 ] + +Back-to-back LPCG writes can be ignored by the LPCG register due to +a HW bug. The writes need to be separated by at least 4 cycles of +the gated clock. See https://www.nxp.com.cn/docs/en/errata/IMX8_1N94W.pdf + +The workaround is implemented as follows: +1. For clocks running greater than or equal to 24MHz, a read +followed by the write will provide sufficient delay. +2. For clocks running below 24MHz, add a delay of 4 clock cylces +after the write to the LPCG register. + +Fixes: 2f77296d3df9 ("clk: imx: add lpcg clock support") +Signed-off-by: Peng Fan <peng.fan@nxp.com> +Reviewed-by: Abel Vesa <abel.vesa@linaro.org> +Link: https://lore.kernel.org/r/20241027-imx-clk-v1-v3-1-89152574d1d7@nxp.com +Signed-off-by: Abel Vesa <abel.vesa@linaro.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/clk/imx/clk-lpcg-scu.c | 37 ++++++++++++++++++++++++++-------- + 1 file changed, 29 insertions(+), 8 deletions(-) + +diff --git a/drivers/clk/imx/clk-lpcg-scu.c b/drivers/clk/imx/clk-lpcg-scu.c +index dd5abd09f3e20..620afdf8dc03e 100644 +--- a/drivers/clk/imx/clk-lpcg-scu.c ++++ b/drivers/clk/imx/clk-lpcg-scu.c +@@ -6,10 +6,12 @@ + + #include <linux/bits.h> + #include <linux/clk-provider.h> ++#include <linux/delay.h> + #include <linux/err.h> + #include <linux/io.h> + #include <linux/slab.h> + #include <linux/spinlock.h> ++#include <linux/units.h> + + #include "clk-scu.h" + +@@ -41,6 +43,29 @@ struct clk_lpcg_scu { + + #define to_clk_lpcg_scu(_hw) container_of(_hw, struct clk_lpcg_scu, hw) + ++/* e10858 -LPCG clock gating register synchronization errata */ ++static void lpcg_e10858_writel(unsigned long rate, void __iomem *reg, u32 val) ++{ ++ writel(val, reg); ++ ++ if (rate >= 24 * HZ_PER_MHZ || rate == 0) { ++ /* ++ * The time taken to access the LPCG registers from the AP core ++ * through the interconnect is longer than the minimum delay ++ * of 4 clock cycles required by the errata. ++ * Adding a readl will provide sufficient delay to prevent ++ * back-to-back writes. ++ */ ++ readl(reg); ++ } else { ++ /* ++ * For clocks running below 24MHz, wait a minimum of ++ * 4 clock cycles. ++ */ ++ ndelay(4 * (DIV_ROUND_UP(1000 * HZ_PER_MHZ, rate))); ++ } ++} ++ + static int clk_lpcg_scu_enable(struct clk_hw *hw) + { + struct clk_lpcg_scu *clk = to_clk_lpcg_scu(hw); +@@ -57,7 +82,8 @@ static int clk_lpcg_scu_enable(struct clk_hw *hw) + val |= CLK_GATE_SCU_LPCG_HW_SEL; + + reg |= val << clk->bit_idx; +- writel(reg, clk->reg); ++ ++ lpcg_e10858_writel(clk_hw_get_rate(hw), clk->reg, reg); + + spin_unlock_irqrestore(&imx_lpcg_scu_lock, flags); + +@@ -74,7 +100,7 @@ static void clk_lpcg_scu_disable(struct clk_hw *hw) + + reg = readl_relaxed(clk->reg); + reg &= ~(CLK_GATE_SCU_LPCG_MASK << clk->bit_idx); +- writel(reg, clk->reg); ++ lpcg_e10858_writel(clk_hw_get_rate(hw), clk->reg, reg); + + spin_unlock_irqrestore(&imx_lpcg_scu_lock, flags); + } +@@ -145,13 +171,8 @@ static int __maybe_unused imx_clk_lpcg_scu_resume(struct device *dev) + { + struct clk_lpcg_scu *clk = dev_get_drvdata(dev); + +- /* +- * FIXME: Sometimes writes don't work unless the CPU issues +- * them twice +- */ +- +- writel(clk->state, clk->reg); + writel(clk->state, clk->reg); ++ lpcg_e10858_writel(0, clk->reg, clk->state); + dev_dbg(dev, "restore lpcg state 0x%x\n", clk->state); + + return 0; +-- +2.43.0 + diff --git a/queue-6.12/clk-mediatek-drop-two-dead-config-options.patch b/queue-6.12/clk-mediatek-drop-two-dead-config-options.patch new file mode 100644 index 00000000000..93109dd4165 --- /dev/null +++ b/queue-6.12/clk-mediatek-drop-two-dead-config-options.patch @@ -0,0 +1,64 @@ +From 286e9cebc6f4ed8b78934a9fc1c79bd9e722693e Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Fri, 27 Sep 2024 11:22:32 +0200 +Subject: clk: mediatek: drop two dead config options + +From: Lukas Bulwahn <lukas.bulwahn@redhat.com> + +[ Upstream commit 98619dc3cecc2b3943d6abe1db235c868dc72f8d ] + +Commit 0f471d31e5e8 ("clk: mediatek: Split MT8195 clock drivers and allow +module build") adds a number of new COMMON_CLK_MT8195_* config options. +Among those, the config options COMMON_CLK_MT8195_AUDSYS and +COMMON_CLK_MT8195_MSDC have no reference in the source tree and are not +used in the Makefile to include a specific file. + +Drop the dead config options COMMON_CLK_MT8195_AUDSYS and +COMMON_CLK_MT8195_MSDC. + +Fixes: 0f471d31e5e8 ("clk: mediatek: Split MT8195 clock drivers and allow module build") +Signed-off-by: Lukas Bulwahn <lukas.bulwahn@redhat.com> +Link: https://lore.kernel.org/r/20240927092232.386511-1-lukas.bulwahn@redhat.com +Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com> +Signed-off-by: Stephen Boyd <sboyd@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/clk/mediatek/Kconfig | 15 --------------- + 1 file changed, 15 deletions(-) + +diff --git a/drivers/clk/mediatek/Kconfig b/drivers/clk/mediatek/Kconfig +index 70a005e7e1b18..486401e1f2f19 100644 +--- a/drivers/clk/mediatek/Kconfig ++++ b/drivers/clk/mediatek/Kconfig +@@ -887,13 +887,6 @@ config COMMON_CLK_MT8195_APUSYS + help + This driver supports MediaTek MT8195 AI Processor Unit System clocks. + +-config COMMON_CLK_MT8195_AUDSYS +- tristate "Clock driver for MediaTek MT8195 audsys" +- depends on COMMON_CLK_MT8195 +- default COMMON_CLK_MT8195 +- help +- This driver supports MediaTek MT8195 audsys clocks. +- + config COMMON_CLK_MT8195_IMP_IIC_WRAP + tristate "Clock driver for MediaTek MT8195 imp_iic_wrap" + depends on COMMON_CLK_MT8195 +@@ -908,14 +901,6 @@ config COMMON_CLK_MT8195_MFGCFG + help + This driver supports MediaTek MT8195 mfgcfg clocks. + +-config COMMON_CLK_MT8195_MSDC +- tristate "Clock driver for MediaTek MT8195 msdc" +- depends on COMMON_CLK_MT8195 +- default COMMON_CLK_MT8195 +- help +- This driver supports MediaTek MT8195 MMC and SD Controller's +- msdc and msdc_top clocks. +- + config COMMON_CLK_MT8195_SCP_ADSP + tristate "Clock driver for MediaTek MT8195 scp_adsp" + depends on COMMON_CLK_MT8195 +-- +2.43.0 + diff --git a/queue-6.12/clk-qcom-videocc-sm8550-depend-on-either-gcc-sm8550-.patch b/queue-6.12/clk-qcom-videocc-sm8550-depend-on-either-gcc-sm8550-.patch new file mode 100644 index 00000000000..7db83ac9fe7 --- /dev/null +++ b/queue-6.12/clk-qcom-videocc-sm8550-depend-on-either-gcc-sm8550-.patch @@ -0,0 +1,44 @@ +From ab4b89de58c3b405ba364dcb3c904c00b5da74a5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Sat, 5 Oct 2024 10:40:46 -0400 +Subject: clk: qcom: videocc-sm8550: depend on either gcc-sm8550 or gcc-sm8650 + +From: Jonathan Marek <jonathan@marek.ca> + +[ Upstream commit aab8d53711346d5569261aec9702b7579eecf1ab ] + +This driver is compatible with both sm8550 and sm8650, fix the Kconfig +entry to reflect that. + +Fixes: da1f361c887c ("clk: qcom: videocc-sm8550: Add SM8650 video clock controller") +Signed-off-by: Jonathan Marek <jonathan@marek.ca> +Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org> +Reviewed-by: Neil Armstrong <neil.armstrong@linaro.org> +Link: https://lore.kernel.org/r/20241005144047.2226-1-jonathan@marek.ca +Signed-off-by: Bjorn Andersson <andersson@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/clk/qcom/Kconfig | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig +index a3e2a09e2105b..4444dafa4e3df 100644 +--- a/drivers/clk/qcom/Kconfig ++++ b/drivers/clk/qcom/Kconfig +@@ -1230,11 +1230,11 @@ config SM_VIDEOCC_8350 + config SM_VIDEOCC_8550 + tristate "SM8550 Video Clock Controller" + depends on ARM64 || COMPILE_TEST +- select SM_GCC_8550 ++ depends on SM_GCC_8550 || SM_GCC_8650 + select QCOM_GDSC + help + Support for the video clock controller on Qualcomm Technologies, Inc. +- SM8550 devices. ++ SM8550 or SM8650 devices. + Say Y if you want to support video devices and functionality such as + video encode/decode. + +-- +2.43.0 + diff --git a/queue-6.12/clk-ralink-mtmips-fix-clock-plan-for-ralink-soc-rt38.patch b/queue-6.12/clk-ralink-mtmips-fix-clock-plan-for-ralink-soc-rt38.patch new file mode 100644 index 00000000000..0b9675cfb85 --- /dev/null +++ b/queue-6.12/clk-ralink-mtmips-fix-clock-plan-for-ralink-soc-rt38.patch @@ -0,0 +1,58 @@ +From 7523b2b775e3d34688e118d3f71b190ea6ea0856 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Tue, 10 Sep 2024 06:40:22 +0200 +Subject: clk: ralink: mtmips: fix clock plan for Ralink SoC RT3883 + +From: Sergio Paracuellos <sergio.paracuellos@gmail.com> + +[ Upstream commit 33239152305567b3e9bf052f71fd4baecd626341 ] + +Clock plan for Ralink SoC RT3883 needs an extra 'periph' clock to properly +set some peripherals that has this clock as their parent. When this driver +was mainlined we could not find any active users of this SoC so we cannot +perform any real tests for it. Now, one user of a Belkin f9k1109 version 1 +device which uses this SoC appear and reported some issues in openWRT: +- https://github.com/openwrt/openwrt/issues/16054 +The peripherals that are wrong are 'uart', 'i2c', 'i2s' and 'uartlite' which +has a not defined 'periph' clock as parent. Hence, introduce it to have a +properly working clock plan for this SoC. + +Fixes: 6f3b15586eef ("clk: ralink: add clock and reset driver for MTMIPS SoCs") +Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com> +Link: https://lore.kernel.org/r/20240910044024.120009-2-sergio.paracuellos@gmail.com +Signed-off-by: Stephen Boyd <sboyd@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/clk/ralink/clk-mtmips.c | 9 +++++++-- + 1 file changed, 7 insertions(+), 2 deletions(-) + +diff --git a/drivers/clk/ralink/clk-mtmips.c b/drivers/clk/ralink/clk-mtmips.c +index 50a443bf79ecd..62f9801ecd3a4 100644 +--- a/drivers/clk/ralink/clk-mtmips.c ++++ b/drivers/clk/ralink/clk-mtmips.c +@@ -267,6 +267,11 @@ static struct mtmips_clk_fixed rt305x_fixed_clocks[] = { + CLK_FIXED("xtal", NULL, 40000000) + }; + ++static struct mtmips_clk_fixed rt3883_fixed_clocks[] = { ++ CLK_FIXED("xtal", NULL, 40000000), ++ CLK_FIXED("periph", "xtal", 40000000) ++}; ++ + static struct mtmips_clk_fixed rt3352_fixed_clocks[] = { + CLK_FIXED("periph", "xtal", 40000000) + }; +@@ -779,8 +784,8 @@ static const struct mtmips_clk_data rt3352_clk_data = { + static const struct mtmips_clk_data rt3883_clk_data = { + .clk_base = rt3883_clks_base, + .num_clk_base = ARRAY_SIZE(rt3883_clks_base), +- .clk_fixed = rt305x_fixed_clocks, +- .num_clk_fixed = ARRAY_SIZE(rt305x_fixed_clocks), ++ .clk_fixed = rt3883_fixed_clocks, ++ .num_clk_fixed = ARRAY_SIZE(rt3883_fixed_clocks), + .clk_factor = NULL, + .num_clk_factor = 0, + .clk_periph = rt5350_pherip_clks, +-- +2.43.0 + diff --git a/queue-6.12/clk-ralink-mtmips-fix-clocks-probe-order-in-oldest-r.patch b/queue-6.12/clk-ralink-mtmips-fix-clocks-probe-order-in-oldest-r.patch new file mode 100644 index 00000000000..4196c162e6b --- /dev/null +++ b/queue-6.12/clk-ralink-mtmips-fix-clocks-probe-order-in-oldest-r.patch @@ -0,0 +1,133 @@ +From 4883a391fc7cdb1118219e9c5620ab9088d7e15d Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Tue, 10 Sep 2024 06:40:23 +0200 +Subject: clk: ralink: mtmips: fix clocks probe order in oldest ralink SoCs + +From: Sergio Paracuellos <sergio.paracuellos@gmail.com> + +[ Upstream commit d34db686a3d74bd564bfce2ada15011c556269fc ] + +Base clocks are the first in being probed and are real dependencies of the +rest of fixed, factor and peripheral clocks. For old ralink SoCs RT2880, +RT305x and RT3883 'xtal' must be defined first since in any other case, +when fixed clocks are probed they are delayed until 'xtal' is probed so the +following warning appears: + + WARNING: CPU: 0 PID: 0 at drivers/clk/ralink/clk-mtmips.c:499 rt3883_bus_recalc_rate+0x98/0x138 + Modules linked in: + CPU: 0 PID: 0 Comm: swapper Not tainted 6.6.43 #0 + Stack : 805e58d0 00000000 00000004 8004f950 00000000 00000004 00000000 00000000 + 80669c54 80830000 80700000 805ae570 80670068 00000001 80669bf8 00000000 + 00000000 00000000 805ae570 80669b38 00000020 804db7dc 00000000 00000000 + 203a6d6d 80669b78 80669e48 70617773 00000000 805ae570 00000000 00000009 + 00000000 00000001 00000004 00000001 00000000 00000000 83fe43b0 00000000 + ... + Call Trace: + [<800065d0>] show_stack+0x64/0xf4 + [<804bca14>] dump_stack_lvl+0x38/0x60 + [<800218ac>] __warn+0x94/0xe4 + [<8002195c>] warn_slowpath_fmt+0x60/0x94 + [<80259ff8>] rt3883_bus_recalc_rate+0x98/0x138 + [<80254530>] __clk_register+0x568/0x688 + [<80254838>] of_clk_hw_register+0x18/0x2c + [<8070b910>] rt2880_clk_of_clk_init_driver+0x18c/0x594 + [<8070b628>] of_clk_init+0x1c0/0x23c + [<806fc448>] plat_time_init+0x58/0x18c + [<806fdaf0>] time_init+0x10/0x6c + [<806f9bc4>] start_kernel+0x458/0x67c + + ---[ end trace 0000000000000000 ]--- + +When this driver was mainlined we could not find any active users of old +ralink SoCs so we cannot perform any real tests for them. Now, one user +of a Belkin f9k1109 version 1 device which uses RT3883 SoC appeared and +reported some issues in openWRT: +- https://github.com/openwrt/openwrt/issues/16054 + +Thus, define a 'rt2880_xtal_recalc_rate()' just returning the expected +frequency 40Mhz and use it along the old ralink SoCs to have a correct +boot trace with no warnings and a working clock plan from the beggining. + +Fixes: 6f3b15586eef ("clk: ralink: add clock and reset driver for MTMIPS SoCs") +Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com> +Link: https://lore.kernel.org/r/20240910044024.120009-3-sergio.paracuellos@gmail.com +Signed-off-by: Stephen Boyd <sboyd@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/clk/ralink/clk-mtmips.c | 21 +++++++++++++-------- + 1 file changed, 13 insertions(+), 8 deletions(-) + +diff --git a/drivers/clk/ralink/clk-mtmips.c b/drivers/clk/ralink/clk-mtmips.c +index 62f9801ecd3a4..76285fbbdeaa2 100644 +--- a/drivers/clk/ralink/clk-mtmips.c ++++ b/drivers/clk/ralink/clk-mtmips.c +@@ -263,10 +263,6 @@ static int mtmips_register_pherip_clocks(struct device_node *np, + .rate = _rate \ + } + +-static struct mtmips_clk_fixed rt305x_fixed_clocks[] = { +- CLK_FIXED("xtal", NULL, 40000000) +-}; +- + static struct mtmips_clk_fixed rt3883_fixed_clocks[] = { + CLK_FIXED("xtal", NULL, 40000000), + CLK_FIXED("periph", "xtal", 40000000) +@@ -371,6 +367,12 @@ static inline struct mtmips_clk *to_mtmips_clk(struct clk_hw *hw) + return container_of(hw, struct mtmips_clk, hw); + } + ++static unsigned long rt2880_xtal_recalc_rate(struct clk_hw *hw, ++ unsigned long parent_rate) ++{ ++ return 40000000; ++} ++ + static unsigned long rt5350_xtal_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) + { +@@ -682,10 +684,12 @@ static unsigned long mt76x8_cpu_recalc_rate(struct clk_hw *hw, + } + + static struct mtmips_clk rt2880_clks_base[] = { ++ { CLK_BASE("xtal", NULL, rt2880_xtal_recalc_rate) }, + { CLK_BASE("cpu", "xtal", rt2880_cpu_recalc_rate) } + }; + + static struct mtmips_clk rt305x_clks_base[] = { ++ { CLK_BASE("xtal", NULL, rt2880_xtal_recalc_rate) }, + { CLK_BASE("cpu", "xtal", rt305x_cpu_recalc_rate) } + }; + +@@ -695,6 +699,7 @@ static struct mtmips_clk rt3352_clks_base[] = { + }; + + static struct mtmips_clk rt3883_clks_base[] = { ++ { CLK_BASE("xtal", NULL, rt2880_xtal_recalc_rate) }, + { CLK_BASE("cpu", "xtal", rt3883_cpu_recalc_rate) }, + { CLK_BASE("bus", "cpu", rt3883_bus_recalc_rate) } + }; +@@ -751,8 +756,8 @@ static int mtmips_register_clocks(struct device_node *np, + static const struct mtmips_clk_data rt2880_clk_data = { + .clk_base = rt2880_clks_base, + .num_clk_base = ARRAY_SIZE(rt2880_clks_base), +- .clk_fixed = rt305x_fixed_clocks, +- .num_clk_fixed = ARRAY_SIZE(rt305x_fixed_clocks), ++ .clk_fixed = NULL, ++ .num_clk_fixed = 0, + .clk_factor = rt2880_factor_clocks, + .num_clk_factor = ARRAY_SIZE(rt2880_factor_clocks), + .clk_periph = rt2880_pherip_clks, +@@ -762,8 +767,8 @@ static const struct mtmips_clk_data rt2880_clk_data = { + static const struct mtmips_clk_data rt305x_clk_data = { + .clk_base = rt305x_clks_base, + .num_clk_base = ARRAY_SIZE(rt305x_clks_base), +- .clk_fixed = rt305x_fixed_clocks, +- .num_clk_fixed = ARRAY_SIZE(rt305x_fixed_clocks), ++ .clk_fixed = NULL, ++ .num_clk_fixed = 0, + .clk_factor = rt305x_factor_clocks, + .num_clk_factor = ARRAY_SIZE(rt305x_factor_clocks), + .clk_periph = rt305x_pherip_clks, +-- +2.43.0 + diff --git a/queue-6.12/clk-renesas-rzg2l-fix-foutpostdiv-clk.patch b/queue-6.12/clk-renesas-rzg2l-fix-foutpostdiv-clk.patch new file mode 100644 index 00000000000..0e186ff2c71 --- /dev/null +++ b/queue-6.12/clk-renesas-rzg2l-fix-foutpostdiv-clk.patch @@ -0,0 +1,56 @@ +From da0f67fbdd34a7945a94c9f341fbbfc7d1ebfc8e Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Thu, 24 Oct 2024 14:42:11 +0100 +Subject: clk: renesas: rzg2l: Fix FOUTPOSTDIV clk + +From: Biju Das <biju.das.jz@bp.renesas.com> + +[ Upstream commit dabf72b85f298970e86891b5218459c17b57b26a ] + +While computing foutpostdiv_rate, the value of params->pl5_fracin +is discarded, which results in the wrong refresh rate. Fix the formula +for computing foutpostdiv_rate. + +Fixes: 1561380ee72f ("clk: renesas: rzg2l: Add FOUTPOSTDIV clk support") +Signed-off-by: Hien Huynh <hien.huynh.px@renesas.com> +Signed-off-by: Biju Das <biju.das.jz@bp.renesas.com> +Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be> +Link: https://lore.kernel.org/20241024134236.315289-1-biju.das.jz@bp.renesas.com +Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/clk/renesas/rzg2l-cpg.c | 11 ++++++----- + 1 file changed, 6 insertions(+), 5 deletions(-) + +diff --git a/drivers/clk/renesas/rzg2l-cpg.c b/drivers/clk/renesas/rzg2l-cpg.c +index 88bf39e8c79c8..b43b763dfe186 100644 +--- a/drivers/clk/renesas/rzg2l-cpg.c ++++ b/drivers/clk/renesas/rzg2l-cpg.c +@@ -548,7 +548,7 @@ static unsigned long + rzg2l_cpg_get_foutpostdiv_rate(struct rzg2l_pll5_param *params, + unsigned long rate) + { +- unsigned long foutpostdiv_rate; ++ unsigned long foutpostdiv_rate, foutvco_rate; + + params->pl5_intin = rate / MEGA; + params->pl5_fracin = div_u64(((u64)rate % MEGA) << 24, MEGA); +@@ -557,10 +557,11 @@ rzg2l_cpg_get_foutpostdiv_rate(struct rzg2l_pll5_param *params, + params->pl5_postdiv2 = 1; + params->pl5_spread = 0x16; + +- foutpostdiv_rate = +- EXTAL_FREQ_IN_MEGA_HZ * MEGA / params->pl5_refdiv * +- ((((params->pl5_intin << 24) + params->pl5_fracin)) >> 24) / +- (params->pl5_postdiv1 * params->pl5_postdiv2); ++ foutvco_rate = div_u64(mul_u32_u32(EXTAL_FREQ_IN_MEGA_HZ * MEGA, ++ (params->pl5_intin << 24) + params->pl5_fracin), ++ params->pl5_refdiv) >> 24; ++ foutpostdiv_rate = DIV_ROUND_CLOSEST_ULL(foutvco_rate, ++ params->pl5_postdiv1 * params->pl5_postdiv2); + + return foutpostdiv_rate; + } +-- +2.43.0 + diff --git a/queue-6.12/clk-sophgo-avoid-integer-overflow-in-sg2042_pll_reca.patch b/queue-6.12/clk-sophgo-avoid-integer-overflow-in-sg2042_pll_reca.patch new file mode 100644 index 00000000000..070933317f5 --- /dev/null +++ b/queue-6.12/clk-sophgo-avoid-integer-overflow-in-sg2042_pll_reca.patch @@ -0,0 +1,44 @@ +From 50b0c2c8fc42a09dc3112d881ea2d1637d92ce48 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Wed, 23 Oct 2024 09:51:47 -0500 +Subject: clk: sophgo: avoid integer overflow in sg2042_pll_recalc_rate() + +From: Zichen Xie <zichenxie0106@gmail.com> + +[ Upstream commit 00f8f70a0e8c6601861628be26270a0b6f4bbb34 ] + +This was found by a static analyzer. +There may be a potential integer overflow issue in +sg2042_pll_recalc_rate(). numerator is defined as u64 while +parent_rate is defined as unsigned long and ctrl_table.fbdiv +is defined as unsigned int. On 32-bit machine, the result of +the calculation will be limited to "u32" without correct casting. +Integer overflow may occur on high-performance systems. + +Fixes: 48cf7e01386e ("clk: sophgo: Add SG2042 clock driver") +Signed-off-by: Zichen Xie <zichenxie0106@gmail.com> +Reviewed-by: Chen Wang <unicorn_wang@outlook.com> +Link: https://lore.kernel.org/r/20241023145146.13130-1-zichenxie0106@gmail.com +Reviewed-by: Dan Carpenter <dan.carpenter@linaro.org> +Signed-off-by: Stephen Boyd <sboyd@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/clk/sophgo/clk-sg2042-pll.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/clk/sophgo/clk-sg2042-pll.c b/drivers/clk/sophgo/clk-sg2042-pll.c +index ff9deeef509b8..1537f4f05860e 100644 +--- a/drivers/clk/sophgo/clk-sg2042-pll.c ++++ b/drivers/clk/sophgo/clk-sg2042-pll.c +@@ -153,7 +153,7 @@ static unsigned long sg2042_pll_recalc_rate(unsigned int reg_value, + + sg2042_pll_ctrl_decode(reg_value, &ctrl_table); + +- numerator = parent_rate * ctrl_table.fbdiv; ++ numerator = (u64)parent_rate * ctrl_table.fbdiv; + denominator = ctrl_table.refdiv * ctrl_table.postdiv1 * ctrl_table.postdiv2; + do_div(numerator, denominator); + return numerator; +-- +2.43.0 + diff --git a/queue-6.12/clk-sunxi-ng-d1-fix-pll_audio0-preset.patch b/queue-6.12/clk-sunxi-ng-d1-fix-pll_audio0-preset.patch new file mode 100644 index 00000000000..7543d80a949 --- /dev/null +++ b/queue-6.12/clk-sunxi-ng-d1-fix-pll_audio0-preset.patch @@ -0,0 +1,42 @@ +From ba5c79db48f7e272b1fd940c93a1fb3dad826587 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Tue, 1 Oct 2024 11:50:16 +0100 +Subject: clk: sunxi-ng: d1: Fix PLL_AUDIO0 preset + +From: Andre Przywara <andre.przywara@arm.com> + +[ Upstream commit e0f253a52ccee3cf3eb987e99756e20c68a1aac9 ] + +To work around a limitation in our clock modelling, we try to force two +bits in the AUDIO0 PLL to 0, in the CCU probe routine. +However the ~ operator only applies to the first expression, and does +not cover the second bit, so we end up clearing only bit 1. + +Group the bit-ORing with parentheses, to make it both clearer to read +and actually correct. + +Fixes: 35b97bb94111 ("clk: sunxi-ng: Add support for the D1 SoC clocks") +Signed-off-by: Andre Przywara <andre.przywara@arm.com> +Link: https://patch.msgid.link/20241001105016.1068558-1-andre.przywara@arm.com +Signed-off-by: Chen-Yu Tsai <wens@csie.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/clk/sunxi-ng/ccu-sun20i-d1.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/clk/sunxi-ng/ccu-sun20i-d1.c b/drivers/clk/sunxi-ng/ccu-sun20i-d1.c +index 9b5cfac2ee70c..3f095515f54f9 100644 +--- a/drivers/clk/sunxi-ng/ccu-sun20i-d1.c ++++ b/drivers/clk/sunxi-ng/ccu-sun20i-d1.c +@@ -1371,7 +1371,7 @@ static int sun20i_d1_ccu_probe(struct platform_device *pdev) + + /* Enforce m1 = 0, m0 = 0 for PLL_AUDIO0 */ + val = readl(reg + SUN20I_D1_PLL_AUDIO0_REG); +- val &= ~BIT(1) | BIT(0); ++ val &= ~(BIT(1) | BIT(0)); + writel(val, reg + SUN20I_D1_PLL_AUDIO0_REG); + + /* Force fanout-27M factor N to 0. */ +-- +2.43.0 + diff --git a/queue-6.12/clocksource-drivers-sp804-make-user-selectable.patch b/queue-6.12/clocksource-drivers-sp804-make-user-selectable.patch new file mode 100644 index 00000000000..6416e62e486 --- /dev/null +++ b/queue-6.12/clocksource-drivers-sp804-make-user-selectable.patch @@ -0,0 +1,49 @@ +From d812c109f3a7b3bee525cad64d701c095681bc25 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Tue, 1 Oct 2024 12:23:56 +0100 +Subject: clocksource/drivers:sp804: Make user selectable + +From: Mark Brown <broonie@kernel.org> + +[ Upstream commit 0309f714a0908e947af1c902cf6a330cb593e75e ] + +The sp804 is currently only user selectable if COMPILE_TEST, this was +done by commit dfc82faad725 ("clocksource/drivers/sp804: Add +COMPILE_TEST to CONFIG_ARM_TIMER_SP804") in order to avoid it being +spuriously offered on platforms that won't have the hardware since it's +generally only seen on Arm based platforms. This config is overly +restrictive, while platforms that rely on the SP804 do select it in +their Kconfig there are others such as the Arm fast models which have a +SP804 available but currently unused by Linux. Relax the dependency to +allow it to be user selectable on arm and arm64 to avoid surprises and +in case someone comes up with a use for extra timer hardware. + +Fixes: dfc82faad725 ("clocksource/drivers/sp804: Add COMPILE_TEST to CONFIG_ARM_TIMER_SP804") +Reported-by: Ross Burton <ross.burton@arm.com> +Reviewed-by: Sudeep Holla <sudeep.holla@arm.com> +Acked-by: Mark Rutland <mark.rutland@arm.com> +Signed-off-by: Mark Brown <broonie@kernel.org> +Link: https://lore.kernel.org/r/20241001-arm64-vexpress-sp804-v3-1-0a2d3f7883e4@kernel.org +Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/clocksource/Kconfig | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig +index 95dd4660b5b65..d546903dba4f3 100644 +--- a/drivers/clocksource/Kconfig ++++ b/drivers/clocksource/Kconfig +@@ -400,7 +400,8 @@ config ARM_GT_INITIAL_PRESCALER_VAL + This affects CPU_FREQ max delta from the initial frequency. + + config ARM_TIMER_SP804 +- bool "Support for Dual Timer SP804 module" if COMPILE_TEST ++ bool "Support for Dual Timer SP804 module" ++ depends on ARM || ARM64 || COMPILE_TEST + depends on GENERIC_SCHED_CLOCK && HAVE_CLK + select CLKSRC_MMIO + select TIMER_OF if OF +-- +2.43.0 + diff --git a/queue-6.12/clocksource-drivers-timer-ti-dm-fix-child-node-refco.patch b/queue-6.12/clocksource-drivers-timer-ti-dm-fix-child-node-refco.patch new file mode 100644 index 00000000000..cb99b431830 --- /dev/null +++ b/queue-6.12/clocksource-drivers-timer-ti-dm-fix-child-node-refco.patch @@ -0,0 +1,46 @@ +From 69099e37f799c38f43cca4b922219a107a7e8e2c Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Thu, 31 Oct 2024 13:54:23 +0100 +Subject: clocksource/drivers/timer-ti-dm: Fix child node refcount handling + +From: Javier Carrasco <javier.carrasco.cruz@gmail.com> + +[ Upstream commit e5cfc0989d9a2849c51c720a16b90b2c061a1aeb ] + +of_find_compatible_node() increments the node's refcount, and it must be +decremented again with a call to of_node_put() when the pointer is no +longer required to avoid leaking the resource. + +Instead of adding the missing calls to of_node_put() in all execution +paths, use the cleanup attribute for 'arm_timer' by means of the +__free() macro, which automatically calls of_node_put() when the +variable goes out of scope. + +Fixes: 25de4ce5ed02 ("clocksource/drivers/timer-ti-dm: Handle dra7 timer wrap errata i940") +Signed-off-by: Javier Carrasco <javier.carrasco.cruz@gmail.com> +Link: https://lore.kernel.org/r/20241031-timer-ti-dm-systimer-of_node_put-v3-1-063ee822b73a@gmail.com +Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/clocksource/timer-ti-dm-systimer.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/clocksource/timer-ti-dm-systimer.c b/drivers/clocksource/timer-ti-dm-systimer.c +index c2dcd8d68e458..d1c144d6f328c 100644 +--- a/drivers/clocksource/timer-ti-dm-systimer.c ++++ b/drivers/clocksource/timer-ti-dm-systimer.c +@@ -686,9 +686,9 @@ subsys_initcall(dmtimer_percpu_timer_startup); + + static int __init dmtimer_percpu_quirk_init(struct device_node *np, u32 pa) + { +- struct device_node *arm_timer; ++ struct device_node *arm_timer __free(device_node) = ++ of_find_compatible_node(NULL, NULL, "arm,armv7-timer"); + +- arm_timer = of_find_compatible_node(NULL, NULL, "arm,armv7-timer"); + if (of_device_is_available(arm_timer)) { + pr_warn_once("ARM architected timer wrap issue i940 detected\n"); + return 0; +-- +2.43.0 + diff --git a/queue-6.12/counter-stm32-timer-cnt-add-check-for-clk_enable.patch b/queue-6.12/counter-stm32-timer-cnt-add-check-for-clk_enable.patch new file mode 100644 index 00000000000..ced343b96c1 --- /dev/null +++ b/queue-6.12/counter-stm32-timer-cnt-add-check-for-clk_enable.patch @@ -0,0 +1,62 @@ +From 9c78f3c658d8991a321665b0c109517a4479f8b6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Mon, 4 Nov 2024 19:18:25 +0000 +Subject: counter: stm32-timer-cnt: Add check for clk_enable() + +From: Jiasheng Jiang <jiashengjiangcool@gmail.com> + +[ Upstream commit 842c3755a6bfbfcafa4a1438078d2485a9eb1d87 ] + +Add check for the return value of clk_enable() in order to catch the +potential exception. + +Fixes: c5b8425514da ("counter: stm32-timer-cnt: add power management support") +Fixes: ad29937e206f ("counter: Add STM32 Timer quadrature encoder") +Signed-off-by: Jiasheng Jiang <jiashengjiangcool@gmail.com> +Link: https://lore.kernel.org/r/20241104191825.40155-1-jiashengjiangcool@gmail.com +Signed-off-by: William Breathitt Gray <wbg@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/counter/stm32-timer-cnt.c | 16 +++++++++++++--- + 1 file changed, 13 insertions(+), 3 deletions(-) + +diff --git a/drivers/counter/stm32-timer-cnt.c b/drivers/counter/stm32-timer-cnt.c +index 186e73d6ccb45..9c188d9edd89f 100644 +--- a/drivers/counter/stm32-timer-cnt.c ++++ b/drivers/counter/stm32-timer-cnt.c +@@ -214,11 +214,17 @@ static int stm32_count_enable_write(struct counter_device *counter, + { + struct stm32_timer_cnt *const priv = counter_priv(counter); + u32 cr1; ++ int ret; + + if (enable) { + regmap_read(priv->regmap, TIM_CR1, &cr1); +- if (!(cr1 & TIM_CR1_CEN)) +- clk_enable(priv->clk); ++ if (!(cr1 & TIM_CR1_CEN)) { ++ ret = clk_enable(priv->clk); ++ if (ret) { ++ dev_err(counter->parent, "Cannot enable clock %d\n", ret); ++ return ret; ++ } ++ } + + regmap_update_bits(priv->regmap, TIM_CR1, TIM_CR1_CEN, + TIM_CR1_CEN); +@@ -816,7 +822,11 @@ static int __maybe_unused stm32_timer_cnt_resume(struct device *dev) + return ret; + + if (priv->enabled) { +- clk_enable(priv->clk); ++ ret = clk_enable(priv->clk); ++ if (ret) { ++ dev_err(dev, "Cannot enable clock %d\n", ret); ++ return ret; ++ } + + /* Restore registers that may have been lost */ + regmap_write(priv->regmap, TIM_SMCR, priv->bak.smcr); +-- +2.43.0 + diff --git a/queue-6.12/counter-ti-ecap-capture-add-check-for-clk_enable.patch b/queue-6.12/counter-ti-ecap-capture-add-check-for-clk_enable.patch new file mode 100644 index 00000000000..246c0aeb84b --- /dev/null +++ b/queue-6.12/counter-ti-ecap-capture-add-check-for-clk_enable.patch @@ -0,0 +1,44 @@ +From f77e65a4cc4234b454d6f74e37b0949a70308a21 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Mon, 4 Nov 2024 19:40:59 +0000 +Subject: counter: ti-ecap-capture: Add check for clk_enable() + +From: Jiasheng Jiang <jiashengjiangcool@gmail.com> + +[ Upstream commit 1437d9f1c56fce9c24e566508bce1d218dd5497a ] + +Add check for the return value of clk_enable() in order to catch the +potential exception. + +Fixes: 4e2f42aa00b6 ("counter: ti-ecap-capture: capture driver support for ECAP") +Reviewed-by: Julien Panis <jpanis@baylibre.com> +Signed-off-by: Jiasheng Jiang <jiashengjiangcool@gmail.com> +Link: https://lore.kernel.org/r/20241104194059.47924-1-jiashengjiangcool@gmail.com +Signed-off-by: William Breathitt Gray <wbg@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/counter/ti-ecap-capture.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +diff --git a/drivers/counter/ti-ecap-capture.c b/drivers/counter/ti-ecap-capture.c +index 675447315cafb..b119aeede693e 100644 +--- a/drivers/counter/ti-ecap-capture.c ++++ b/drivers/counter/ti-ecap-capture.c +@@ -574,8 +574,13 @@ static int ecap_cnt_resume(struct device *dev) + { + struct counter_device *counter_dev = dev_get_drvdata(dev); + struct ecap_cnt_dev *ecap_dev = counter_priv(counter_dev); ++ int ret; + +- clk_enable(ecap_dev->clk); ++ ret = clk_enable(ecap_dev->clk); ++ if (ret) { ++ dev_err(dev, "Cannot enable clock %d\n", ret); ++ return ret; ++ } + + ecap_cnt_capture_set_evmode(counter_dev, ecap_dev->pm_ctx.ev_mode); + +-- +2.43.0 + diff --git a/queue-6.12/cppc_cpufreq-use-desired-perf-if-feedback-ctrs-are-0.patch b/queue-6.12/cppc_cpufreq-use-desired-perf-if-feedback-ctrs-are-0.patch new file mode 100644 index 00000000000..dfe564753ec --- /dev/null +++ b/queue-6.12/cppc_cpufreq-use-desired-perf-if-feedback-ctrs-are-0.patch @@ -0,0 +1,128 @@ +From 74ba9fcd8a548e3a5a434f9865aaeb7a54fb2387 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Sun, 29 Sep 2024 11:32:13 +0800 +Subject: cppc_cpufreq: Use desired perf if feedback ctrs are 0 or unchanged + +From: Jie Zhan <zhanjie9@hisilicon.com> + +[ Upstream commit c47195631960b626058c335aec31f186fa854f97 ] + +The CPPC performance feedback counters could be 0 or unchanged when the +target cpu is in a low-power idle state, e.g. power-gated or clock-gated. + +When the counters are 0, cppc_cpufreq_get_rate() returns 0 KHz, which makes +cpufreq_online() get a false error and fail to generate a cpufreq policy. + +When the counters are unchanged, the existing cppc_perf_from_fbctrs() +returns a cached desired perf, but some platforms may update the real +frequency back to the desired perf reg. + +For the above cases in cppc_cpufreq_get_rate(), get the latest desired perf +from the CPPC reg to reflect the frequency because some platforms may +update the actual frequency back there; if failed, use the cached desired +perf. + +Fixes: 6a4fec4f6d30 ("cpufreq: cppc: cppc_cpufreq_get_rate() returns zero in all error cases.") +Signed-off-by: Jie Zhan <zhanjie9@hisilicon.com> +Reviewed-by: Zeng Heng <zengheng4@huawei.com> +Reviewed-by: Ionela Voinescu <ionela.voinescu@arm.com> +Reviewed-by: Huisong Li <lihuisong@huawei.com> +Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/cpufreq/cppc_cpufreq.c | 57 +++++++++++++++++++++++++++------- + 1 file changed, 46 insertions(+), 11 deletions(-) + +diff --git a/drivers/cpufreq/cppc_cpufreq.c b/drivers/cpufreq/cppc_cpufreq.c +index 2b8708475ac77..1a8f95e6cc8d0 100644 +--- a/drivers/cpufreq/cppc_cpufreq.c ++++ b/drivers/cpufreq/cppc_cpufreq.c +@@ -118,6 +118,9 @@ static void cppc_scale_freq_workfn(struct kthread_work *work) + + perf = cppc_perf_from_fbctrs(cpu_data, &cppc_fi->prev_perf_fb_ctrs, + &fb_ctrs); ++ if (!perf) ++ return; ++ + cppc_fi->prev_perf_fb_ctrs = fb_ctrs; + + perf <<= SCHED_CAPACITY_SHIFT; +@@ -724,13 +727,31 @@ static int cppc_perf_from_fbctrs(struct cppc_cpudata *cpu_data, + delta_delivered = get_delta(fb_ctrs_t1->delivered, + fb_ctrs_t0->delivered); + +- /* Check to avoid divide-by zero and invalid delivered_perf */ ++ /* ++ * Avoid divide-by zero and unchanged feedback counters. ++ * Leave it for callers to handle. ++ */ + if (!delta_reference || !delta_delivered) +- return cpu_data->perf_ctrls.desired_perf; ++ return 0; + + return (reference_perf * delta_delivered) / delta_reference; + } + ++static int cppc_get_perf_ctrs_sample(int cpu, ++ struct cppc_perf_fb_ctrs *fb_ctrs_t0, ++ struct cppc_perf_fb_ctrs *fb_ctrs_t1) ++{ ++ int ret; ++ ++ ret = cppc_get_perf_ctrs(cpu, fb_ctrs_t0); ++ if (ret) ++ return ret; ++ ++ udelay(2); /* 2usec delay between sampling */ ++ ++ return cppc_get_perf_ctrs(cpu, fb_ctrs_t1); ++} ++ + static unsigned int cppc_cpufreq_get_rate(unsigned int cpu) + { + struct cppc_perf_fb_ctrs fb_ctrs_t0 = {0}, fb_ctrs_t1 = {0}; +@@ -746,18 +767,32 @@ static unsigned int cppc_cpufreq_get_rate(unsigned int cpu) + + cpufreq_cpu_put(policy); + +- ret = cppc_get_perf_ctrs(cpu, &fb_ctrs_t0); +- if (ret) +- return 0; +- +- udelay(2); /* 2usec delay between sampling */ +- +- ret = cppc_get_perf_ctrs(cpu, &fb_ctrs_t1); +- if (ret) +- return 0; ++ ret = cppc_get_perf_ctrs_sample(cpu, &fb_ctrs_t0, &fb_ctrs_t1); ++ if (ret) { ++ if (ret == -EFAULT) ++ /* Any of the associated CPPC regs is 0. */ ++ goto out_invalid_counters; ++ else ++ return 0; ++ } + + delivered_perf = cppc_perf_from_fbctrs(cpu_data, &fb_ctrs_t0, + &fb_ctrs_t1); ++ if (!delivered_perf) ++ goto out_invalid_counters; ++ ++ return cppc_perf_to_khz(&cpu_data->perf_caps, delivered_perf); ++ ++out_invalid_counters: ++ /* ++ * Feedback counters could be unchanged or 0 when a cpu enters a ++ * low-power idle state, e.g. clock-gated or power-gated. ++ * Use desired perf for reflecting frequency. Get the latest register ++ * value first as some platforms may update the actual delivered perf ++ * there; if failed, resort to the cached desired perf. ++ */ ++ if (cppc_get_desired_perf(cpu, &delivered_perf)) ++ delivered_perf = cpu_data->perf_ctrls.desired_perf; + + return cppc_perf_to_khz(&cpu_data->perf_caps, delivered_perf); + } +-- +2.43.0 + diff --git a/queue-6.12/cpufreq-amd-pstate-don-t-update-cppc-request-in-amd_.patch b/queue-6.12/cpufreq-amd-pstate-don-t-update-cppc-request-in-amd_.patch new file mode 100644 index 00000000000..13fabed3f6e --- /dev/null +++ b/queue-6.12/cpufreq-amd-pstate-don-t-update-cppc-request-in-amd_.patch @@ -0,0 +1,69 @@ +From f5e18c9cc255d9a8d96fe2772e3083b31cb82f25 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Sat, 12 Oct 2024 12:45:17 -0500 +Subject: cpufreq/amd-pstate: Don't update CPPC request in + amd_pstate_cpu_boost_update() + +From: Mario Limonciello <mario.limonciello@amd.com> + +[ Upstream commit 67c08d303e0a1a5665b3f198037c9fae2d808090 ] + +When boost is changed the CPPC value is changed in amd_pstate_cpu_boost_update() +but then changed again when refresh_frequency_limits() and all it's callbacks +occur. The first is a pointless write, so instead just update the limits for +the policy and let the policy refresh anchor everything properly. + +Fixes: c8c68c38b56f ("cpufreq: amd-pstate: initialize core precision boost state") +Reviewed-by: Gautham R. Shenoy <gautham.shenoy@amd.com> +Reviewed-by: Perry Yuan <perry.yuan@amd.com> +Tested-by: Dhananjay Ugwekar <dhananjay.ugwekar@amd.com> +Link: https://lore.kernel.org/r/20241012174519.897-2-mario.limonciello@amd.com +Signed-off-by: Mario Limonciello <mario.limonciello@amd.com> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/cpufreq/amd-pstate.c | 24 +----------------------- + 1 file changed, 1 insertion(+), 23 deletions(-) + +diff --git a/drivers/cpufreq/amd-pstate.c b/drivers/cpufreq/amd-pstate.c +index b63863f77c677..5138aa42caf22 100644 +--- a/drivers/cpufreq/amd-pstate.c ++++ b/drivers/cpufreq/amd-pstate.c +@@ -665,34 +665,12 @@ static void amd_pstate_adjust_perf(unsigned int cpu, + static int amd_pstate_cpu_boost_update(struct cpufreq_policy *policy, bool on) + { + struct amd_cpudata *cpudata = policy->driver_data; +- struct cppc_perf_ctrls perf_ctrls; +- u32 highest_perf, nominal_perf, nominal_freq, max_freq; ++ u32 nominal_freq, max_freq; + int ret = 0; + +- highest_perf = READ_ONCE(cpudata->highest_perf); +- nominal_perf = READ_ONCE(cpudata->nominal_perf); + nominal_freq = READ_ONCE(cpudata->nominal_freq); + max_freq = READ_ONCE(cpudata->max_freq); + +- if (boot_cpu_has(X86_FEATURE_CPPC)) { +- u64 value = READ_ONCE(cpudata->cppc_req_cached); +- +- value &= ~GENMASK_ULL(7, 0); +- value |= on ? highest_perf : nominal_perf; +- WRITE_ONCE(cpudata->cppc_req_cached, value); +- +- wrmsrl_on_cpu(cpudata->cpu, MSR_AMD_CPPC_REQ, value); +- } else { +- perf_ctrls.max_perf = on ? highest_perf : nominal_perf; +- ret = cppc_set_perf(cpudata->cpu, &perf_ctrls); +- if (ret) { +- cpufreq_cpu_release(policy); +- pr_debug("Failed to set max perf on CPU:%d. ret:%d\n", +- cpudata->cpu, ret); +- return ret; +- } +- } +- + if (on) + policy->cpuinfo.max_freq = max_freq; + else if (policy->cpuinfo.max_freq > nominal_freq * 1000) +-- +2.43.0 + diff --git a/queue-6.12/cpufreq-cppc-fix-possible-null-ptr-deref-for-cppc_ge.patch b/queue-6.12/cpufreq-cppc-fix-possible-null-ptr-deref-for-cppc_ge.patch new file mode 100644 index 00000000000..e0d68a56431 --- /dev/null +++ b/queue-6.12/cpufreq-cppc-fix-possible-null-ptr-deref-for-cppc_ge.patch @@ -0,0 +1,38 @@ +From a336fc3aa02ce4d187ccda529214218f465daefd Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Wed, 30 Oct 2024 16:24:49 +0800 +Subject: cpufreq: CPPC: Fix possible null-ptr-deref for cppc_get_cpu_cost() + +From: Jinjie Ruan <ruanjinjie@huawei.com> + +[ Upstream commit 1a1374bb8c5926674973d849feed500bc61ad535 ] + +cpufreq_cpu_get_raw() may return NULL if the cpu is not in +policy->cpus cpu mask and it will cause null pointer dereference, +so check NULL for cppc_get_cpu_cost(). + +Fixes: 740fcdc2c20e ("cpufreq: CPPC: Register EM based on efficiency class information") +Signed-off-by: Jinjie Ruan <ruanjinjie@huawei.com> +Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/cpufreq/cppc_cpufreq.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/cpufreq/cppc_cpufreq.c b/drivers/cpufreq/cppc_cpufreq.c +index c907638810057..975fb9fa23cac 100644 +--- a/drivers/cpufreq/cppc_cpufreq.c ++++ b/drivers/cpufreq/cppc_cpufreq.c +@@ -493,6 +493,9 @@ static int cppc_get_cpu_cost(struct device *cpu_dev, unsigned long KHz, + int step; + + policy = cpufreq_cpu_get_raw(cpu_dev->id); ++ if (!policy) ++ return 0; ++ + cpu_data = policy->driver_data; + perf_caps = &cpu_data->perf_caps; + max_cap = arch_scale_cpu_capacity(cpu_dev->id); +-- +2.43.0 + diff --git a/queue-6.12/cpufreq-cppc-fix-possible-null-ptr-deref-for-cpufreq.patch b/queue-6.12/cpufreq-cppc-fix-possible-null-ptr-deref-for-cpufreq.patch new file mode 100644 index 00000000000..4f367715500 --- /dev/null +++ b/queue-6.12/cpufreq-cppc-fix-possible-null-ptr-deref-for-cpufreq.patch @@ -0,0 +1,37 @@ +From 49d531d5424356ee07031968802648a6adb3e985 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Wed, 30 Oct 2024 09:20:19 +0800 +Subject: cpufreq: CPPC: Fix possible null-ptr-deref for cpufreq_cpu_get_raw() + +From: Jinjie Ruan <ruanjinjie@huawei.com> + +[ Upstream commit a78e7207564258db6e373e86294a85f9d646d35a ] + +cpufreq_cpu_get_raw() may return NULL if the cpu is not in +policy->cpus cpu mask and it will cause null pointer dereference. + +Fixes: 740fcdc2c20e ("cpufreq: CPPC: Register EM based on efficiency class information") +Signed-off-by: Jinjie Ruan <ruanjinjie@huawei.com> +Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/cpufreq/cppc_cpufreq.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/cpufreq/cppc_cpufreq.c b/drivers/cpufreq/cppc_cpufreq.c +index 1a8f95e6cc8d0..c907638810057 100644 +--- a/drivers/cpufreq/cppc_cpufreq.c ++++ b/drivers/cpufreq/cppc_cpufreq.c +@@ -423,6 +423,9 @@ static int cppc_get_cpu_power(struct device *cpu_dev, + struct cppc_cpudata *cpu_data; + + policy = cpufreq_cpu_get_raw(cpu_dev->id); ++ if (!policy) ++ return 0; ++ + cpu_data = policy->driver_data; + perf_caps = &cpu_data->perf_caps; + max_cap = arch_scale_cpu_capacity(cpu_dev->id); +-- +2.43.0 + diff --git a/queue-6.12/cpufreq-cppc-fix-wrong-return-value-in-cppc_get_cpu_.patch b/queue-6.12/cpufreq-cppc-fix-wrong-return-value-in-cppc_get_cpu_.patch new file mode 100644 index 00000000000..148290b4438 --- /dev/null +++ b/queue-6.12/cpufreq-cppc-fix-wrong-return-value-in-cppc_get_cpu_.patch @@ -0,0 +1,42 @@ +From 28296238f3929094fccfcf83630299e8b905c991 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Wed, 6 Nov 2024 09:12:38 +0800 +Subject: cpufreq: CPPC: Fix wrong return value in cppc_get_cpu_cost() + +From: Jinjie Ruan <ruanjinjie@huawei.com> + +[ Upstream commit be392aa80f1e5b0b65ccc2a540b9304fefcfe3d8 ] + +cppc_get_cpu_cost() return 0 if the policy is NULL. Then in +em_compute_costs(), the later zero check for cost is not valid +as cost is uninitialized. As Quentin pointed out, kernel energy model +core check the return value of get_cost() first, so if the callback +failed it should tell the core. Return -EINVAL to fix it. + +Fixes: 1a1374bb8c59 ("cpufreq: CPPC: Fix possible null-ptr-deref for cppc_get_cpu_cost()") +Reported-by: Dan Carpenter <dan.carpenter@linaro.org> +Closes: https://lore.kernel.org/all/c4765377-7830-44c2-84fa-706b6e304e10@stanley.mountain/ +Signed-off-by: Jinjie Ruan <ruanjinjie@huawei.com> +Suggested-by: Quentin Perret <qperret@google.com> +Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/cpufreq/cppc_cpufreq.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/cpufreq/cppc_cpufreq.c b/drivers/cpufreq/cppc_cpufreq.c +index 975fb9fa23cac..2993b8a4c7f17 100644 +--- a/drivers/cpufreq/cppc_cpufreq.c ++++ b/drivers/cpufreq/cppc_cpufreq.c +@@ -494,7 +494,7 @@ static int cppc_get_cpu_cost(struct device *cpu_dev, unsigned long KHz, + + policy = cpufreq_cpu_get_raw(cpu_dev->id); + if (!policy) +- return 0; ++ return -EINVAL; + + cpu_data = policy->driver_data; + perf_caps = &cpu_data->perf_caps; +-- +2.43.0 + diff --git a/queue-6.12/cpufreq-cppc-fix-wrong-return-value-in-cppc_get_cpu_.patch-26269 b/queue-6.12/cpufreq-cppc-fix-wrong-return-value-in-cppc_get_cpu_.patch-26269 new file mode 100644 index 00000000000..6ebcce252cf --- /dev/null +++ b/queue-6.12/cpufreq-cppc-fix-wrong-return-value-in-cppc_get_cpu_.patch-26269 @@ -0,0 +1,40 @@ +From 4a0f5ec191f775ba43b3b657c8da938bef248b9c Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Wed, 6 Nov 2024 09:01:11 +0800 +Subject: cpufreq: CPPC: Fix wrong return value in cppc_get_cpu_power() + +From: Jinjie Ruan <ruanjinjie@huawei.com> + +[ Upstream commit b51eb0874d8170028434fbd259e80b78ed9b8eca ] + +cppc_get_cpu_power() return 0 if the policy is NULL. Then in +em_create_perf_table(), the later zero check for power is not valid +as power is uninitialized. As Quentin pointed out, kernel energy model +core check the return value of active_power() first, so if the callback +failed it should tell the core. So return -EINVAL to fix it. + +Fixes: a78e72075642 ("cpufreq: CPPC: Fix possible null-ptr-deref for cpufreq_cpu_get_raw()") +Signed-off-by: Jinjie Ruan <ruanjinjie@huawei.com> +Suggested-by: Quentin Perret <qperret@google.com> +Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/cpufreq/cppc_cpufreq.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/cpufreq/cppc_cpufreq.c b/drivers/cpufreq/cppc_cpufreq.c +index 2993b8a4c7f17..c1cdf0f4d0ddd 100644 +--- a/drivers/cpufreq/cppc_cpufreq.c ++++ b/drivers/cpufreq/cppc_cpufreq.c +@@ -424,7 +424,7 @@ static int cppc_get_cpu_power(struct device *cpu_dev, + + policy = cpufreq_cpu_get_raw(cpu_dev->id); + if (!policy) +- return 0; ++ return -EINVAL; + + cpu_data = policy->driver_data; + perf_caps = &cpu_data->perf_caps; +-- +2.43.0 + diff --git a/queue-6.12/cpufreq-loongson2-unregister-platform_driver-on-fail.patch b/queue-6.12/cpufreq-loongson2-unregister-platform_driver-on-fail.patch new file mode 100644 index 00000000000..ac693e56b7f --- /dev/null +++ b/queue-6.12/cpufreq-loongson2-unregister-platform_driver-on-fail.patch @@ -0,0 +1,39 @@ +From 19e62a4328154bd61f77252c2c3f2a3a2aeab6df Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Wed, 16 Oct 2024 17:06:15 +0800 +Subject: cpufreq: loongson2: Unregister platform_driver on failure + +From: Yuan Can <yuancan@huawei.com> + +[ Upstream commit 5f856d71ccdf89b4bac0ff70ebb0bb582e7f7f18 ] + +When cpufreq_register_driver() returns error, the cpufreq_init() returns +without unregister platform_driver, fix by add missing +platform_driver_unregister() when cpufreq_register_driver() failed. + +Fixes: f8ede0f700f5 ("MIPS: Loongson 2F: Add CPU frequency scaling support") +Signed-off-by: Yuan Can <yuancan@huawei.com> +Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/cpufreq/loongson2_cpufreq.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/cpufreq/loongson2_cpufreq.c b/drivers/cpufreq/loongson2_cpufreq.c +index 6a8e97896d38c..ed1a6dbad6389 100644 +--- a/drivers/cpufreq/loongson2_cpufreq.c ++++ b/drivers/cpufreq/loongson2_cpufreq.c +@@ -148,7 +148,9 @@ static int __init cpufreq_init(void) + + ret = cpufreq_register_driver(&loongson2_cpufreq_driver); + +- if (!ret && !nowait) { ++ if (ret) { ++ platform_driver_unregister(&platform_driver); ++ } else if (!nowait) { + saved_cpu_wait = cpu_wait; + cpu_wait = loongson2_cpu_wait; + } +-- +2.43.0 + diff --git a/queue-6.12/cpufreq-loongson3-check-for-error-code-from-devm_mut.patch b/queue-6.12/cpufreq-loongson3-check-for-error-code-from-devm_mut.patch new file mode 100644 index 00000000000..f0c5d8725aa --- /dev/null +++ b/queue-6.12/cpufreq-loongson3-check-for-error-code-from-devm_mut.patch @@ -0,0 +1,43 @@ +From 54cba916a25ea2f9c04ce2c6bad5011b647948ac Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Thu, 31 Oct 2024 15:46:34 +0200 +Subject: cpufreq: loongson3: Check for error code from devm_mutex_init() call + +From: Andy Shevchenko <andriy.shevchenko@linux.intel.com> + +[ Upstream commit db01e46689e9a986ca6b5d2f41b57d7a81551a4f ] + +Even if it's not critical, the avoidance of checking the error code +from devm_mutex_init() call today diminishes the point of using devm +variant of it. Tomorrow it may even leak something. Add the missed +check. + +Fixes: ccf51454145b ("cpufreq: Add Loongson-3 CPUFreq driver support") +Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com> +Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/cpufreq/loongson3_cpufreq.c | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +diff --git a/drivers/cpufreq/loongson3_cpufreq.c b/drivers/cpufreq/loongson3_cpufreq.c +index 6b5e6798d9a28..a923e196ec86e 100644 +--- a/drivers/cpufreq/loongson3_cpufreq.c ++++ b/drivers/cpufreq/loongson3_cpufreq.c +@@ -346,8 +346,11 @@ static int loongson3_cpufreq_probe(struct platform_device *pdev) + { + int i, ret; + +- for (i = 0; i < MAX_PACKAGES; i++) +- devm_mutex_init(&pdev->dev, &cpufreq_mutex[i]); ++ for (i = 0; i < MAX_PACKAGES; i++) { ++ ret = devm_mutex_init(&pdev->dev, &cpufreq_mutex[i]); ++ if (ret) ++ return ret; ++ } + + ret = do_service_request(0, 0, CMD_GET_VERSION, 0, 0); + if (ret <= 0) +-- +2.43.0 + diff --git a/queue-6.12/crypto-aes-gcm-p10-use-the-correct-bit-to-test-for-p.patch b/queue-6.12/crypto-aes-gcm-p10-use-the-correct-bit-to-test-for-p.patch new file mode 100644 index 00000000000..6dfb01426c2 --- /dev/null +++ b/queue-6.12/crypto-aes-gcm-p10-use-the-correct-bit-to-test-for-p.patch @@ -0,0 +1,38 @@ +From b975373aff190b74ef52cb1bc908658758f00129 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Wed, 6 Nov 2024 13:09:33 +0100 +Subject: crypto: aes-gcm-p10 - Use the correct bit to test for P10 + +From: Michal Suchanek <msuchanek@suse.de> + +[ Upstream commit 3574a5168ff3b6bddc4cd235878491f75967c8d4 ] + +A hwcap feature bit is passed to cpu_has_feature, resulting in testing +for CPU_FTR_MMCRA instead of the 3.1 platform revision. + +Fixes: c954b252dee9 ("crypto: powerpc/p10-aes-gcm - Register modules as SIMD") +Reported-by: Nicolai Stange <nstange@suse.com> +Signed-off-by: Michal Suchanek <msuchanek@suse.de> +Acked-by: Michael Ellerman <mpe@ellerman.id.au> (powerpc) +Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + arch/powerpc/crypto/aes-gcm-p10-glue.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/arch/powerpc/crypto/aes-gcm-p10-glue.c b/arch/powerpc/crypto/aes-gcm-p10-glue.c +index 4a029d2fe06ce..f37b3d13fc530 100644 +--- a/arch/powerpc/crypto/aes-gcm-p10-glue.c ++++ b/arch/powerpc/crypto/aes-gcm-p10-glue.c +@@ -414,7 +414,7 @@ static int __init p10_init(void) + { + int ret; + +- if (!cpu_has_feature(PPC_FEATURE2_ARCH_3_1)) ++ if (!cpu_has_feature(CPU_FTR_ARCH_31)) + return 0; + + ret = simd_register_aeads_compat(gcm_aes_algs, +-- +2.43.0 + diff --git a/queue-6.12/crypto-bcm-add-error-check-in-the-ahash_hmac_init-fu.patch b/queue-6.12/crypto-bcm-add-error-check-in-the-ahash_hmac_init-fu.patch new file mode 100644 index 00000000000..c63c817f5ef --- /dev/null +++ b/queue-6.12/crypto-bcm-add-error-check-in-the-ahash_hmac_init-fu.patch @@ -0,0 +1,47 @@ +From 464de47a3fd069deed27f192adef728a7078e6a1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Mon, 4 Nov 2024 12:17:45 +0000 +Subject: crypto: bcm - add error check in the ahash_hmac_init function + +From: Chen Ridong <chenridong@huawei.com> + +[ Upstream commit 19630cf57233e845b6ac57c9c969a4888925467b ] + +The ahash_init functions may return fails. The ahash_hmac_init should +not return ok when ahash_init returns error. For an example, ahash_init +will return -ENOMEM when allocation memory is error. + +Fixes: 9d12ba86f818 ("crypto: brcm - Add Broadcom SPU driver") +Signed-off-by: Chen Ridong <chenridong@huawei.com> +Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/crypto/bcm/cipher.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/drivers/crypto/bcm/cipher.c b/drivers/crypto/bcm/cipher.c +index 1a3ecd44cbaf6..20f6453670aa4 100644 +--- a/drivers/crypto/bcm/cipher.c ++++ b/drivers/crypto/bcm/cipher.c +@@ -2415,6 +2415,7 @@ static int ahash_hmac_setkey(struct crypto_ahash *ahash, const u8 *key, + + static int ahash_hmac_init(struct ahash_request *req) + { ++ int ret; + struct iproc_reqctx_s *rctx = ahash_request_ctx(req); + struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); + struct iproc_ctx_s *ctx = crypto_ahash_ctx(tfm); +@@ -2424,7 +2425,9 @@ static int ahash_hmac_init(struct ahash_request *req) + flow_log("ahash_hmac_init()\n"); + + /* init the context as a hash */ +- ahash_init(req); ++ ret = ahash_init(req); ++ if (ret) ++ return ret; + + if (!spu_no_incr_hash(ctx)) { + /* SPU-M can do incr hashing but needs sw for outer HMAC */ +-- +2.43.0 + diff --git a/queue-6.12/crypto-caam-add-error-check-to-caam_rsa_set_priv_key.patch b/queue-6.12/crypto-caam-add-error-check-to-caam_rsa_set_priv_key.patch new file mode 100644 index 00000000000..95e10d8e059 --- /dev/null +++ b/queue-6.12/crypto-caam-add-error-check-to-caam_rsa_set_priv_key.patch @@ -0,0 +1,78 @@ +From 857d98cf14a6b904199411ac5990a05e4bf150a6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Mon, 4 Nov 2024 12:15:11 +0000 +Subject: crypto: caam - add error check to caam_rsa_set_priv_key_form +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Chen Ridong <chenridong@huawei.com> + +[ Upstream commit b64140c74e954f1db6eae5548ca3a1f41b6fad79 ] + +The caam_rsa_set_priv_key_form did not check for memory allocation errors. +Add the checks to the caam_rsa_set_priv_key_form functions. + +Fixes: 52e26d77b8b3 ("crypto: caam - add support for RSA key form 2") +Signed-off-by: Chen Ridong <chenridong@huawei.com> +Reviewed-by: Gaurav Jain <gaurav.jain@nxp.com> +Reviewed-by: Horia Geantă <horia.geanta@nxp.com> +Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/crypto/caam/caampkc.c | 11 +++++++---- + 1 file changed, 7 insertions(+), 4 deletions(-) + +diff --git a/drivers/crypto/caam/caampkc.c b/drivers/crypto/caam/caampkc.c +index 887a5f2fb9279..cb001aa1de661 100644 +--- a/drivers/crypto/caam/caampkc.c ++++ b/drivers/crypto/caam/caampkc.c +@@ -984,7 +984,7 @@ static int caam_rsa_set_pub_key(struct crypto_akcipher *tfm, const void *key, + return -ENOMEM; + } + +-static void caam_rsa_set_priv_key_form(struct caam_rsa_ctx *ctx, ++static int caam_rsa_set_priv_key_form(struct caam_rsa_ctx *ctx, + struct rsa_key *raw_key) + { + struct caam_rsa_key *rsa_key = &ctx->key; +@@ -994,7 +994,7 @@ static void caam_rsa_set_priv_key_form(struct caam_rsa_ctx *ctx, + + rsa_key->p = caam_read_raw_data(raw_key->p, &p_sz); + if (!rsa_key->p) +- return; ++ return -ENOMEM; + rsa_key->p_sz = p_sz; + + rsa_key->q = caam_read_raw_data(raw_key->q, &q_sz); +@@ -1029,7 +1029,7 @@ static void caam_rsa_set_priv_key_form(struct caam_rsa_ctx *ctx, + + rsa_key->priv_form = FORM3; + +- return; ++ return 0; + + free_dq: + kfree_sensitive(rsa_key->dq); +@@ -1043,6 +1043,7 @@ static void caam_rsa_set_priv_key_form(struct caam_rsa_ctx *ctx, + kfree_sensitive(rsa_key->q); + free_p: + kfree_sensitive(rsa_key->p); ++ return -ENOMEM; + } + + static int caam_rsa_set_priv_key(struct crypto_akcipher *tfm, const void *key, +@@ -1088,7 +1089,9 @@ static int caam_rsa_set_priv_key(struct crypto_akcipher *tfm, const void *key, + rsa_key->e_sz = raw_key.e_sz; + rsa_key->n_sz = raw_key.n_sz; + +- caam_rsa_set_priv_key_form(ctx, &raw_key); ++ ret = caam_rsa_set_priv_key_form(ctx, &raw_key); ++ if (ret) ++ goto err; + + return 0; + +-- +2.43.0 + diff --git a/queue-6.12/crypto-caam-fix-the-pointer-passed-to-caam_qi_shutdo.patch b/queue-6.12/crypto-caam-fix-the-pointer-passed-to-caam_qi_shutdo.patch new file mode 100644 index 00000000000..75f64560b8f --- /dev/null +++ b/queue-6.12/crypto-caam-fix-the-pointer-passed-to-caam_qi_shutdo.patch @@ -0,0 +1,40 @@ +From 2e747260244205c29ecbb6205db402808c142398 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Sun, 15 Sep 2024 12:22:12 +0200 +Subject: crypto: caam - Fix the pointer passed to caam_qi_shutdown() + +From: Christophe JAILLET <christophe.jaillet@wanadoo.fr> + +[ Upstream commit ad980b04f51f7fb503530bd1cb328ba5e75a250e ] + +The type of the last parameter given to devm_add_action_or_reset() is +"struct caam_drv_private *", but in caam_qi_shutdown(), it is casted to +"struct device *". + +Pass the correct parameter to devm_add_action_or_reset() so that the +resources are released as expected. + +Fixes: f414de2e2fff ("crypto: caam - use devres to de-initialize QI") +Signed-off-by: Christophe JAILLET <christophe.jaillet@wanadoo.fr> +Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/crypto/caam/qi.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/crypto/caam/qi.c b/drivers/crypto/caam/qi.c +index f6111ee9ed342..8ed2bb01a619f 100644 +--- a/drivers/crypto/caam/qi.c ++++ b/drivers/crypto/caam/qi.c +@@ -794,7 +794,7 @@ int caam_qi_init(struct platform_device *caam_pdev) + + caam_debugfs_qi_init(ctrlpriv); + +- err = devm_add_action_or_reset(qidev, caam_qi_shutdown, ctrlpriv); ++ err = devm_add_action_or_reset(qidev, caam_qi_shutdown, qidev); + if (err) + goto fail2; + +-- +2.43.0 + diff --git a/queue-6.12/crypto-cavium-fix-an-error-handling-path-in-cpt_ucod.patch b/queue-6.12/crypto-cavium-fix-an-error-handling-path-in-cpt_ucod.patch new file mode 100644 index 00000000000..fc5b74da112 --- /dev/null +++ b/queue-6.12/crypto-cavium-fix-an-error-handling-path-in-cpt_ucod.patch @@ -0,0 +1,38 @@ +From da1a054fb7d3b321c41df595f2dd6b1d5241a425 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Fri, 8 Nov 2024 18:22:27 +0100 +Subject: crypto: cavium - Fix an error handling path in cpt_ucode_load_fw() + +From: Christophe JAILLET <christophe.jaillet@wanadoo.fr> + +[ Upstream commit 572b7cf08403b6c67dfe0dc3e0f2efb42443254f ] + +If do_cpt_init() fails, a previous dma_alloc_coherent() call needs to be +undone. + +Add the needed dma_free_coherent() before returning. + +Fixes: 9e2c7d99941d ("crypto: cavium - Add Support for Octeon-tx CPT Engine") +Signed-off-by: Christophe JAILLET <christophe.jaillet@wanadoo.fr> +Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/crypto/cavium/cpt/cptpf_main.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/crypto/cavium/cpt/cptpf_main.c b/drivers/crypto/cavium/cpt/cptpf_main.c +index ec17beee24c07..54de869e5374c 100644 +--- a/drivers/crypto/cavium/cpt/cptpf_main.c ++++ b/drivers/crypto/cavium/cpt/cptpf_main.c +@@ -302,6 +302,8 @@ static int cpt_ucode_load_fw(struct cpt_device *cpt, const u8 *fw, bool is_ae) + + ret = do_cpt_init(cpt, mcode); + if (ret) { ++ dma_free_coherent(&cpt->pdev->dev, mcode->code_size, ++ mcode->code, mcode->phys_base); + dev_err(dev, "do_cpt_init failed with ret: %d\n", ret); + goto fw_release; + } +-- +2.43.0 + diff --git a/queue-6.12/crypto-cavium-fix-the-if-condition-to-exit-loop-afte.patch b/queue-6.12/crypto-cavium-fix-the-if-condition-to-exit-loop-afte.patch new file mode 100644 index 00000000000..26efc0ca32d --- /dev/null +++ b/queue-6.12/crypto-cavium-fix-the-if-condition-to-exit-loop-afte.patch @@ -0,0 +1,53 @@ +From aed9cc667ecffb7bd121d1d35f1f75ff40444cb5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Fri, 18 Oct 2024 10:23:10 -0600 +Subject: crypto: cavium - Fix the if condition to exit loop after timeout + +From: Everest K.C <everestkc@everestkc.com.np> + +[ Upstream commit 53d91ca76b6c426c546542a44c78507b42008c9e ] + +The while loop breaks in the first run because of incorrect +if condition. It also causes the statements after the if to +appear dead. +Fix this by changing the condition from if(timeout--) to +if(!timeout--). + +This bug was reported by Coverity Scan. +Report: +CID 1600859: (#1 of 1): Logically dead code (DEADCODE) +dead_error_line: Execution cannot reach this statement: udelay(30UL); + +Fixes: 9e2c7d99941d ("crypto: cavium - Add Support for Octeon-tx CPT Engine") +Signed-off-by: Everest K.C. <everestkc@everestkc.com.np> +Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/crypto/cavium/cpt/cptpf_main.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/crypto/cavium/cpt/cptpf_main.c b/drivers/crypto/cavium/cpt/cptpf_main.c +index 6872ac3440010..ec17beee24c07 100644 +--- a/drivers/crypto/cavium/cpt/cptpf_main.c ++++ b/drivers/crypto/cavium/cpt/cptpf_main.c +@@ -44,7 +44,7 @@ static void cpt_disable_cores(struct cpt_device *cpt, u64 coremask, + dev_err(dev, "Cores still busy %llx", coremask); + grp = cpt_read_csr64(cpt->reg_base, + CPTX_PF_EXEC_BUSY(0)); +- if (timeout--) ++ if (!timeout--) + break; + + udelay(CSR_DELAY); +@@ -394,7 +394,7 @@ static void cpt_disable_all_cores(struct cpt_device *cpt) + dev_err(dev, "Cores still busy"); + grp = cpt_read_csr64(cpt->reg_base, + CPTX_PF_EXEC_BUSY(0)); +- if (timeout--) ++ if (!timeout--) + break; + + udelay(CSR_DELAY); +-- +2.43.0 + diff --git a/queue-6.12/crypto-hisilicon-qm-disable-same-error-report-before.patch b/queue-6.12/crypto-hisilicon-qm-disable-same-error-report-before.patch new file mode 100644 index 00000000000..180a5fc8355 --- /dev/null +++ b/queue-6.12/crypto-hisilicon-qm-disable-same-error-report-before.patch @@ -0,0 +1,340 @@ +From f229dae7858c36d2a355d29c1225085ef8536064 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Sat, 26 Oct 2024 19:44:29 +0800 +Subject: crypto: hisilicon/qm - disable same error report before resetting + +From: Weili Qian <qianweili@huawei.com> + +[ Upstream commit c418ba6baca3ae10ffaf47b0803d2a9e6bf1af96 ] + +If an error indicating that the device needs to be reset is reported, +disable the error reporting before device reset is complete, +enable the error reporting after the reset is complete to prevent +the same error from being reported repeatedly. + +Fixes: eaebf4c3b103 ("crypto: hisilicon - Unify hardware error init/uninit into QM") +Signed-off-by: Weili Qian <qianweili@huawei.com> +Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/crypto/hisilicon/hpre/hpre_main.c | 35 ++++++++++++++--- + drivers/crypto/hisilicon/qm.c | 47 +++++++---------------- + drivers/crypto/hisilicon/sec2/sec_main.c | 35 ++++++++++++++--- + drivers/crypto/hisilicon/zip/zip_main.c | 35 ++++++++++++++--- + include/linux/hisi_acc_qm.h | 8 +++- + 5 files changed, 110 insertions(+), 50 deletions(-) + +diff --git a/drivers/crypto/hisilicon/hpre/hpre_main.c b/drivers/crypto/hisilicon/hpre/hpre_main.c +index 6b536ad2ada52..34d30b7838134 100644 +--- a/drivers/crypto/hisilicon/hpre/hpre_main.c ++++ b/drivers/crypto/hisilicon/hpre/hpre_main.c +@@ -1280,11 +1280,15 @@ static u32 hpre_get_hw_err_status(struct hisi_qm *qm) + + static void hpre_clear_hw_err_status(struct hisi_qm *qm, u32 err_sts) + { +- u32 nfe; +- + writel(err_sts, qm->io_base + HPRE_HAC_SOURCE_INT); +- nfe = hisi_qm_get_hw_info(qm, hpre_basic_info, HPRE_NFE_MASK_CAP, qm->cap_ver); +- writel(nfe, qm->io_base + HPRE_RAS_NFE_ENB); ++} ++ ++static void hpre_disable_error_report(struct hisi_qm *qm, u32 err_type) ++{ ++ u32 nfe_mask; ++ ++ nfe_mask = hisi_qm_get_hw_info(qm, hpre_basic_info, HPRE_NFE_MASK_CAP, qm->cap_ver); ++ writel(nfe_mask & (~err_type), qm->io_base + HPRE_RAS_NFE_ENB); + } + + static void hpre_open_axi_master_ooo(struct hisi_qm *qm) +@@ -1298,6 +1302,27 @@ static void hpre_open_axi_master_ooo(struct hisi_qm *qm) + qm->io_base + HPRE_AM_OOO_SHUTDOWN_ENB); + } + ++static enum acc_err_result hpre_get_err_result(struct hisi_qm *qm) ++{ ++ u32 err_status; ++ ++ err_status = hpre_get_hw_err_status(qm); ++ if (err_status) { ++ if (err_status & qm->err_info.ecc_2bits_mask) ++ qm->err_status.is_dev_ecc_mbit = true; ++ hpre_log_hw_error(qm, err_status); ++ ++ if (err_status & qm->err_info.dev_reset_mask) { ++ /* Disable the same error reporting until device is recovered. */ ++ hpre_disable_error_report(qm, err_status); ++ return ACC_ERR_NEED_RESET; ++ } ++ hpre_clear_hw_err_status(qm, err_status); ++ } ++ ++ return ACC_ERR_RECOVERED; ++} ++ + static void hpre_err_info_init(struct hisi_qm *qm) + { + struct hisi_qm_err_info *err_info = &qm->err_info; +@@ -1324,12 +1349,12 @@ static const struct hisi_qm_err_ini hpre_err_ini = { + .hw_err_disable = hpre_hw_error_disable, + .get_dev_hw_err_status = hpre_get_hw_err_status, + .clear_dev_hw_err_status = hpre_clear_hw_err_status, +- .log_dev_hw_err = hpre_log_hw_error, + .open_axi_master_ooo = hpre_open_axi_master_ooo, + .open_sva_prefetch = hpre_open_sva_prefetch, + .close_sva_prefetch = hpre_close_sva_prefetch, + .show_last_dfx_regs = hpre_show_last_dfx_regs, + .err_info_init = hpre_err_info_init, ++ .get_err_result = hpre_get_err_result, + }; + + static int hpre_pf_probe_init(struct hpre *hpre) +diff --git a/drivers/crypto/hisilicon/qm.c b/drivers/crypto/hisilicon/qm.c +index 07983af9e3e22..b18692ee7fd56 100644 +--- a/drivers/crypto/hisilicon/qm.c ++++ b/drivers/crypto/hisilicon/qm.c +@@ -271,12 +271,6 @@ enum vft_type { + SHAPER_VFT, + }; + +-enum acc_err_result { +- ACC_ERR_NONE, +- ACC_ERR_NEED_RESET, +- ACC_ERR_RECOVERED, +-}; +- + enum qm_alg_type { + ALG_TYPE_0, + ALG_TYPE_1, +@@ -1425,22 +1419,25 @@ static void qm_log_hw_error(struct hisi_qm *qm, u32 error_status) + + static enum acc_err_result qm_hw_error_handle_v2(struct hisi_qm *qm) + { +- u32 error_status, tmp; +- +- /* read err sts */ +- tmp = readl(qm->io_base + QM_ABNORMAL_INT_STATUS); +- error_status = qm->error_mask & tmp; ++ u32 error_status; + +- if (error_status) { ++ error_status = qm_get_hw_error_status(qm); ++ if (error_status & qm->error_mask) { + if (error_status & QM_ECC_MBIT) + qm->err_status.is_qm_ecc_mbit = true; + + qm_log_hw_error(qm, error_status); +- if (error_status & qm->err_info.qm_reset_mask) ++ if (error_status & qm->err_info.qm_reset_mask) { ++ /* Disable the same error reporting until device is recovered. */ ++ writel(qm->err_info.nfe & (~error_status), ++ qm->io_base + QM_RAS_NFE_ENABLE); + return ACC_ERR_NEED_RESET; ++ } + ++ /* Clear error source if not need reset. */ + writel(error_status, qm->io_base + QM_ABNORMAL_INT_SOURCE); + writel(qm->err_info.nfe, qm->io_base + QM_RAS_NFE_ENABLE); ++ writel(qm->err_info.ce, qm->io_base + QM_RAS_CE_ENABLE); + } + + return ACC_ERR_RECOVERED; +@@ -3861,30 +3858,12 @@ EXPORT_SYMBOL_GPL(hisi_qm_sriov_configure); + + static enum acc_err_result qm_dev_err_handle(struct hisi_qm *qm) + { +- u32 err_sts; +- +- if (!qm->err_ini->get_dev_hw_err_status) { +- dev_err(&qm->pdev->dev, "Device doesn't support get hw error status!\n"); ++ if (!qm->err_ini->get_err_result) { ++ dev_err(&qm->pdev->dev, "Device doesn't support reset!\n"); + return ACC_ERR_NONE; + } + +- /* get device hardware error status */ +- err_sts = qm->err_ini->get_dev_hw_err_status(qm); +- if (err_sts) { +- if (err_sts & qm->err_info.ecc_2bits_mask) +- qm->err_status.is_dev_ecc_mbit = true; +- +- if (qm->err_ini->log_dev_hw_err) +- qm->err_ini->log_dev_hw_err(qm, err_sts); +- +- if (err_sts & qm->err_info.dev_reset_mask) +- return ACC_ERR_NEED_RESET; +- +- if (qm->err_ini->clear_dev_hw_err_status) +- qm->err_ini->clear_dev_hw_err_status(qm, err_sts); +- } +- +- return ACC_ERR_RECOVERED; ++ return qm->err_ini->get_err_result(qm); + } + + static enum acc_err_result qm_process_dev_error(struct hisi_qm *qm) +diff --git a/drivers/crypto/hisilicon/sec2/sec_main.c b/drivers/crypto/hisilicon/sec2/sec_main.c +index c35533d8930b2..75c25f0d5f2b8 100644 +--- a/drivers/crypto/hisilicon/sec2/sec_main.c ++++ b/drivers/crypto/hisilicon/sec2/sec_main.c +@@ -1010,11 +1010,15 @@ static u32 sec_get_hw_err_status(struct hisi_qm *qm) + + static void sec_clear_hw_err_status(struct hisi_qm *qm, u32 err_sts) + { +- u32 nfe; +- + writel(err_sts, qm->io_base + SEC_CORE_INT_SOURCE); +- nfe = hisi_qm_get_hw_info(qm, sec_basic_info, SEC_NFE_MASK_CAP, qm->cap_ver); +- writel(nfe, qm->io_base + SEC_RAS_NFE_REG); ++} ++ ++static void sec_disable_error_report(struct hisi_qm *qm, u32 err_type) ++{ ++ u32 nfe_mask; ++ ++ nfe_mask = hisi_qm_get_hw_info(qm, sec_basic_info, SEC_NFE_MASK_CAP, qm->cap_ver); ++ writel(nfe_mask & (~err_type), qm->io_base + SEC_RAS_NFE_REG); + } + + static void sec_open_axi_master_ooo(struct hisi_qm *qm) +@@ -1026,6 +1030,27 @@ static void sec_open_axi_master_ooo(struct hisi_qm *qm) + writel(val | SEC_AXI_SHUTDOWN_ENABLE, qm->io_base + SEC_CONTROL_REG); + } + ++static enum acc_err_result sec_get_err_result(struct hisi_qm *qm) ++{ ++ u32 err_status; ++ ++ err_status = sec_get_hw_err_status(qm); ++ if (err_status) { ++ if (err_status & qm->err_info.ecc_2bits_mask) ++ qm->err_status.is_dev_ecc_mbit = true; ++ sec_log_hw_error(qm, err_status); ++ ++ if (err_status & qm->err_info.dev_reset_mask) { ++ /* Disable the same error reporting until device is recovered. */ ++ sec_disable_error_report(qm, err_status); ++ return ACC_ERR_NEED_RESET; ++ } ++ sec_clear_hw_err_status(qm, err_status); ++ } ++ ++ return ACC_ERR_RECOVERED; ++} ++ + static void sec_err_info_init(struct hisi_qm *qm) + { + struct hisi_qm_err_info *err_info = &qm->err_info; +@@ -1052,12 +1077,12 @@ static const struct hisi_qm_err_ini sec_err_ini = { + .hw_err_disable = sec_hw_error_disable, + .get_dev_hw_err_status = sec_get_hw_err_status, + .clear_dev_hw_err_status = sec_clear_hw_err_status, +- .log_dev_hw_err = sec_log_hw_error, + .open_axi_master_ooo = sec_open_axi_master_ooo, + .open_sva_prefetch = sec_open_sva_prefetch, + .close_sva_prefetch = sec_close_sva_prefetch, + .show_last_dfx_regs = sec_show_last_dfx_regs, + .err_info_init = sec_err_info_init, ++ .get_err_result = sec_get_err_result, + }; + + static int sec_pf_probe_init(struct sec_dev *sec) +diff --git a/drivers/crypto/hisilicon/zip/zip_main.c b/drivers/crypto/hisilicon/zip/zip_main.c +index d07e47b48be06..80c2fcb1d26dc 100644 +--- a/drivers/crypto/hisilicon/zip/zip_main.c ++++ b/drivers/crypto/hisilicon/zip/zip_main.c +@@ -1059,11 +1059,15 @@ static u32 hisi_zip_get_hw_err_status(struct hisi_qm *qm) + + static void hisi_zip_clear_hw_err_status(struct hisi_qm *qm, u32 err_sts) + { +- u32 nfe; +- + writel(err_sts, qm->io_base + HZIP_CORE_INT_SOURCE); +- nfe = hisi_qm_get_hw_info(qm, zip_basic_cap_info, ZIP_NFE_MASK_CAP, qm->cap_ver); +- writel(nfe, qm->io_base + HZIP_CORE_INT_RAS_NFE_ENB); ++} ++ ++static void hisi_zip_disable_error_report(struct hisi_qm *qm, u32 err_type) ++{ ++ u32 nfe_mask; ++ ++ nfe_mask = hisi_qm_get_hw_info(qm, zip_basic_cap_info, ZIP_NFE_MASK_CAP, qm->cap_ver); ++ writel(nfe_mask & (~err_type), qm->io_base + HZIP_CORE_INT_RAS_NFE_ENB); + } + + static void hisi_zip_open_axi_master_ooo(struct hisi_qm *qm) +@@ -1093,6 +1097,27 @@ static void hisi_zip_close_axi_master_ooo(struct hisi_qm *qm) + qm->io_base + HZIP_CORE_INT_SET); + } + ++static enum acc_err_result hisi_zip_get_err_result(struct hisi_qm *qm) ++{ ++ u32 err_status; ++ ++ err_status = hisi_zip_get_hw_err_status(qm); ++ if (err_status) { ++ if (err_status & qm->err_info.ecc_2bits_mask) ++ qm->err_status.is_dev_ecc_mbit = true; ++ hisi_zip_log_hw_error(qm, err_status); ++ ++ if (err_status & qm->err_info.dev_reset_mask) { ++ /* Disable the same error reporting until device is recovered. */ ++ hisi_zip_disable_error_report(qm, err_status); ++ return ACC_ERR_NEED_RESET; ++ } ++ hisi_zip_clear_hw_err_status(qm, err_status); ++ } ++ ++ return ACC_ERR_RECOVERED; ++} ++ + static void hisi_zip_err_info_init(struct hisi_qm *qm) + { + struct hisi_qm_err_info *err_info = &qm->err_info; +@@ -1120,13 +1145,13 @@ static const struct hisi_qm_err_ini hisi_zip_err_ini = { + .hw_err_disable = hisi_zip_hw_error_disable, + .get_dev_hw_err_status = hisi_zip_get_hw_err_status, + .clear_dev_hw_err_status = hisi_zip_clear_hw_err_status, +- .log_dev_hw_err = hisi_zip_log_hw_error, + .open_axi_master_ooo = hisi_zip_open_axi_master_ooo, + .close_axi_master_ooo = hisi_zip_close_axi_master_ooo, + .open_sva_prefetch = hisi_zip_open_sva_prefetch, + .close_sva_prefetch = hisi_zip_close_sva_prefetch, + .show_last_dfx_regs = hisi_zip_show_last_dfx_regs, + .err_info_init = hisi_zip_err_info_init, ++ .get_err_result = hisi_zip_get_err_result, + }; + + static int hisi_zip_pf_probe_init(struct hisi_zip *hisi_zip) +diff --git a/include/linux/hisi_acc_qm.h b/include/linux/hisi_acc_qm.h +index 9d7754ad5e9b0..43ad280935e36 100644 +--- a/include/linux/hisi_acc_qm.h ++++ b/include/linux/hisi_acc_qm.h +@@ -229,6 +229,12 @@ struct hisi_qm_status { + + struct hisi_qm; + ++enum acc_err_result { ++ ACC_ERR_NONE, ++ ACC_ERR_NEED_RESET, ++ ACC_ERR_RECOVERED, ++}; ++ + struct hisi_qm_err_info { + char *acpi_rst; + u32 msi_wr_port; +@@ -257,9 +263,9 @@ struct hisi_qm_err_ini { + void (*close_axi_master_ooo)(struct hisi_qm *qm); + void (*open_sva_prefetch)(struct hisi_qm *qm); + void (*close_sva_prefetch)(struct hisi_qm *qm); +- void (*log_dev_hw_err)(struct hisi_qm *qm, u32 err_sts); + void (*show_last_dfx_regs)(struct hisi_qm *qm); + void (*err_info_init)(struct hisi_qm *qm); ++ enum acc_err_result (*get_err_result)(struct hisi_qm *qm); + }; + + struct hisi_qm_cap_info { +-- +2.43.0 + diff --git a/queue-6.12/crypto-inside-secure-fix-the-return-value-of-safexce.patch b/queue-6.12/crypto-inside-secure-fix-the-return-value-of-safexce.patch new file mode 100644 index 00000000000..f1101e34b8a --- /dev/null +++ b/queue-6.12/crypto-inside-secure-fix-the-return-value-of-safexce.patch @@ -0,0 +1,41 @@ +From 8b693f8beb9700bff1e5282dc76f5efedbf9f141 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Thu, 31 Oct 2024 19:27:55 +0800 +Subject: crypto: inside-secure - Fix the return value of + safexcel_xcbcmac_cra_init() + +From: Li Huafei <lihuafei1@huawei.com> + +[ Upstream commit a10549fcce2913be7dc581562ffd8ea35653853e ] + +The commit 320406cb60b6 ("crypto: inside-secure - Replace generic aes +with libaes") replaced crypto_alloc_cipher() with kmalloc(), but did not +modify the handling of the return value. When kmalloc() returns NULL, +PTR_ERR_OR_ZERO(NULL) returns 0, but in fact, the memory allocation has +failed, and -ENOMEM should be returned. + +Fixes: 320406cb60b6 ("crypto: inside-secure - Replace generic aes with libaes") +Signed-off-by: Li Huafei <lihuafei1@huawei.com> +Acked-by: Antoine Tenart <atenart@kernel.org> +Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/crypto/inside-secure/safexcel_hash.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/crypto/inside-secure/safexcel_hash.c b/drivers/crypto/inside-secure/safexcel_hash.c +index e17577b785c33..f44c08f5f5ec4 100644 +--- a/drivers/crypto/inside-secure/safexcel_hash.c ++++ b/drivers/crypto/inside-secure/safexcel_hash.c +@@ -2093,7 +2093,7 @@ static int safexcel_xcbcmac_cra_init(struct crypto_tfm *tfm) + + safexcel_ahash_cra_init(tfm); + ctx->aes = kmalloc(sizeof(*ctx->aes), GFP_KERNEL); +- return PTR_ERR_OR_ZERO(ctx->aes); ++ return ctx->aes == NULL ? -ENOMEM : 0; + } + + static void safexcel_xcbcmac_cra_exit(struct crypto_tfm *tfm) +-- +2.43.0 + diff --git a/queue-6.12/crypto-mxs-dcp-fix-aes-cbc-with-hardware-bound-keys.patch b/queue-6.12/crypto-mxs-dcp-fix-aes-cbc-with-hardware-bound-keys.patch new file mode 100644 index 00000000000..5e92dcb1492 --- /dev/null +++ b/queue-6.12/crypto-mxs-dcp-fix-aes-cbc-with-hardware-bound-keys.patch @@ -0,0 +1,69 @@ +From 28a258a0f5bee1b3f170cc880f9c455d0cf115a6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Fri, 13 Sep 2024 11:11:43 +0200 +Subject: crypto: mxs-dcp - Fix AES-CBC with hardware-bound keys + +From: Tomas Paukrt <tomaspaukrt@email.cz> + +[ Upstream commit 0dbb6854ca14933e194e8e46c894ca7bff95d0f3 ] + +Fix passing an initialization vector in the payload field which +is necessary for AES in CBC mode even with hardware-bound keys. + +Fixes: 3d16af0b4cfa ("crypto: mxs-dcp: Add support for hardware-bound keys") +Signed-off-by: Tomas Paukrt <tomaspaukrt@email.cz> +Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/crypto/mxs-dcp.c | 20 ++++++++++++-------- + 1 file changed, 12 insertions(+), 8 deletions(-) + +diff --git a/drivers/crypto/mxs-dcp.c b/drivers/crypto/mxs-dcp.c +index c82775dbb557a..77a6301f37f0a 100644 +--- a/drivers/crypto/mxs-dcp.c ++++ b/drivers/crypto/mxs-dcp.c +@@ -225,21 +225,22 @@ static int mxs_dcp_start_dma(struct dcp_async_ctx *actx) + static int mxs_dcp_run_aes(struct dcp_async_ctx *actx, + struct skcipher_request *req, int init) + { +- dma_addr_t key_phys = 0; +- dma_addr_t src_phys, dst_phys; ++ dma_addr_t key_phys, src_phys, dst_phys; + struct dcp *sdcp = global_sdcp; + struct dcp_dma_desc *desc = &sdcp->coh->desc[actx->chan]; + struct dcp_aes_req_ctx *rctx = skcipher_request_ctx(req); + bool key_referenced = actx->key_referenced; + int ret; + +- if (!key_referenced) { ++ if (key_referenced) ++ key_phys = dma_map_single(sdcp->dev, sdcp->coh->aes_key + AES_KEYSIZE_128, ++ AES_KEYSIZE_128, DMA_TO_DEVICE); ++ else + key_phys = dma_map_single(sdcp->dev, sdcp->coh->aes_key, + 2 * AES_KEYSIZE_128, DMA_TO_DEVICE); +- ret = dma_mapping_error(sdcp->dev, key_phys); +- if (ret) +- return ret; +- } ++ ret = dma_mapping_error(sdcp->dev, key_phys); ++ if (ret) ++ return ret; + + src_phys = dma_map_single(sdcp->dev, sdcp->coh->aes_in_buf, + DCP_BUF_SZ, DMA_TO_DEVICE); +@@ -300,7 +301,10 @@ static int mxs_dcp_run_aes(struct dcp_async_ctx *actx, + err_dst: + dma_unmap_single(sdcp->dev, src_phys, DCP_BUF_SZ, DMA_TO_DEVICE); + err_src: +- if (!key_referenced) ++ if (key_referenced) ++ dma_unmap_single(sdcp->dev, key_phys, AES_KEYSIZE_128, ++ DMA_TO_DEVICE); ++ else + dma_unmap_single(sdcp->dev, key_phys, 2 * AES_KEYSIZE_128, + DMA_TO_DEVICE); + return ret; +-- +2.43.0 + diff --git a/queue-6.12/crypto-pcrypt-call-crypto-layer-directly-when-padata.patch b/queue-6.12/crypto-pcrypt-call-crypto-layer-directly-when-padata.patch new file mode 100644 index 00000000000..2610a046b1e --- /dev/null +++ b/queue-6.12/crypto-pcrypt-call-crypto-layer-directly-when-padata.patch @@ -0,0 +1,59 @@ +From 564c74c2286b9983b4c559c368c29746591b8091 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Tue, 15 Oct 2024 02:09:35 +0000 +Subject: crypto: pcrypt - Call crypto layer directly when padata_do_parallel() + return -EBUSY + +From: Yi Yang <yiyang13@huawei.com> + +[ Upstream commit 662f2f13e66d3883b9238b0b96b17886179e60e2 ] + +Since commit 8f4f68e788c3 ("crypto: pcrypt - Fix hungtask for +PADATA_RESET"), the pcrypt encryption and decryption operations return +-EAGAIN when the CPU goes online or offline. In alg_test(), a WARN is +generated when pcrypt_aead_decrypt() or pcrypt_aead_encrypt() returns +-EAGAIN, the unnecessary panic will occur when panic_on_warn set 1. +Fix this issue by calling crypto layer directly without parallelization +in that case. + +Fixes: 8f4f68e788c3 ("crypto: pcrypt - Fix hungtask for PADATA_RESET") +Signed-off-by: Yi Yang <yiyang13@huawei.com> +Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + crypto/pcrypt.c | 12 ++++++++---- + 1 file changed, 8 insertions(+), 4 deletions(-) + +diff --git a/crypto/pcrypt.c b/crypto/pcrypt.c +index d0d954fe9d54f..7fc79e7dce44a 100644 +--- a/crypto/pcrypt.c ++++ b/crypto/pcrypt.c +@@ -117,8 +117,10 @@ static int pcrypt_aead_encrypt(struct aead_request *req) + err = padata_do_parallel(ictx->psenc, padata, &ctx->cb_cpu); + if (!err) + return -EINPROGRESS; +- if (err == -EBUSY) +- return -EAGAIN; ++ if (err == -EBUSY) { ++ /* try non-parallel mode */ ++ return crypto_aead_encrypt(creq); ++ } + + return err; + } +@@ -166,8 +168,10 @@ static int pcrypt_aead_decrypt(struct aead_request *req) + err = padata_do_parallel(ictx->psdec, padata, &ctx->cb_cpu); + if (!err) + return -EINPROGRESS; +- if (err == -EBUSY) +- return -EAGAIN; ++ if (err == -EBUSY) { ++ /* try non-parallel mode */ ++ return crypto_aead_decrypt(creq); ++ } + + return err; + } +-- +2.43.0 + diff --git a/queue-6.12/crypto-powerpc-p10-aes-gcm-add-dependency-on-crypto_.patch b/queue-6.12/crypto-powerpc-p10-aes-gcm-add-dependency-on-crypto_.patch new file mode 100644 index 00000000000..16f9b29a6f2 --- /dev/null +++ b/queue-6.12/crypto-powerpc-p10-aes-gcm-add-dependency-on-crypto_.patch @@ -0,0 +1,42 @@ +From ee259ed184c5e5d53e9077b1a7f7e71d4082fe7f Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Mon, 23 Sep 2024 09:30:40 -0400 +Subject: crypto: powerpc/p10-aes-gcm - Add dependency on CRYPTO_SIMDand + re-enable CRYPTO_AES_GCM_P10 + +From: Danny Tsen <dtsen@linux.ibm.com> + +[ Upstream commit 8b6c1e466eecab70c2ed686f636d56eda19f4cd6 ] + +Added CRYPTO_SIMD for CRYPTO_AES_GCM_P10. + +Fixes: 45a4672b9a6e ("crypto: p10-aes-gcm - Update Kconfig and Makefile") + +Signed-off-by: Danny Tsen <dtsen@linux.ibm.com> +Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + arch/powerpc/crypto/Kconfig | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/arch/powerpc/crypto/Kconfig b/arch/powerpc/crypto/Kconfig +index 46a4c85e85e24..951a437264611 100644 +--- a/arch/powerpc/crypto/Kconfig ++++ b/arch/powerpc/crypto/Kconfig +@@ -107,12 +107,12 @@ config CRYPTO_AES_PPC_SPE + + config CRYPTO_AES_GCM_P10 + tristate "Stitched AES/GCM acceleration support on P10 or later CPU (PPC)" +- depends on BROKEN + depends on PPC64 && CPU_LITTLE_ENDIAN && VSX + select CRYPTO_LIB_AES + select CRYPTO_ALGAPI + select CRYPTO_AEAD + select CRYPTO_SKCIPHER ++ select CRYPTO_SIMD + help + AEAD cipher: AES cipher algorithms (FIPS-197) + GCM (Galois/Counter Mode) authenticated encryption mode (NIST SP800-38D) +-- +2.43.0 + diff --git a/queue-6.12/crypto-powerpc-p10-aes-gcm-register-modules-as-simd.patch b/queue-6.12/crypto-powerpc-p10-aes-gcm-register-modules-as-simd.patch new file mode 100644 index 00000000000..1a524a64820 --- /dev/null +++ b/queue-6.12/crypto-powerpc-p10-aes-gcm-register-modules-as-simd.patch @@ -0,0 +1,310 @@ +From f02072319a18d85cd1a84395892e8ead9f2c878b Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Mon, 23 Sep 2024 09:30:39 -0400 +Subject: crypto: powerpc/p10-aes-gcm - Register modules as SIMD + +From: Danny Tsen <dtsen@linux.ibm.com> + +[ Upstream commit c954b252dee956d33ee59f594710af28fb3037d9 ] + +This patch is to fix an issue when simd is not usable that data mismatch +may occur. The fix is to register algs as SIMD modules so that the +algorithm is excecuted when SIMD instructions is usable. Called +gcm_update() to generate the final digest if needed. + +A new module rfc4106(gcm(aes)) is also added. + +Fixes: cdcecfd9991f ("crypto: p10-aes-gcm - Glue code for AES/GCM stitched implementation") + +Signed-off-by: Danny Tsen <dtsen@linux.ibm.com> +Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + arch/powerpc/crypto/aes-gcm-p10-glue.c | 141 +++++++++++++++++++++---- + 1 file changed, 118 insertions(+), 23 deletions(-) + +diff --git a/arch/powerpc/crypto/aes-gcm-p10-glue.c b/arch/powerpc/crypto/aes-gcm-p10-glue.c +index f66ad56e765f0..4a029d2fe06ce 100644 +--- a/arch/powerpc/crypto/aes-gcm-p10-glue.c ++++ b/arch/powerpc/crypto/aes-gcm-p10-glue.c +@@ -8,6 +8,7 @@ + #include <linux/unaligned.h> + #include <asm/simd.h> + #include <asm/switch_to.h> ++#include <crypto/gcm.h> + #include <crypto/aes.h> + #include <crypto/algapi.h> + #include <crypto/b128ops.h> +@@ -24,6 +25,7 @@ + + #define PPC_ALIGN 16 + #define GCM_IV_SIZE 12 ++#define RFC4106_NONCE_SIZE 4 + + MODULE_DESCRIPTION("PPC64le AES-GCM with Stitched implementation"); + MODULE_AUTHOR("Danny Tsen <dtsen@linux.ibm.com"); +@@ -31,7 +33,7 @@ MODULE_LICENSE("GPL v2"); + MODULE_ALIAS_CRYPTO("aes"); + + asmlinkage int aes_p10_set_encrypt_key(const u8 *userKey, const int bits, +- void *key); ++ void *key); + asmlinkage void aes_p10_encrypt(const u8 *in, u8 *out, const void *key); + asmlinkage void aes_p10_gcm_encrypt(u8 *in, u8 *out, size_t len, + void *rkey, u8 *iv, void *Xi); +@@ -39,7 +41,8 @@ asmlinkage void aes_p10_gcm_decrypt(u8 *in, u8 *out, size_t len, + void *rkey, u8 *iv, void *Xi); + asmlinkage void gcm_init_htable(unsigned char htable[], unsigned char Xi[]); + asmlinkage void gcm_ghash_p10(unsigned char *Xi, unsigned char *Htable, +- unsigned char *aad, unsigned int alen); ++ unsigned char *aad, unsigned int alen); ++asmlinkage void gcm_update(u8 *iv, void *Xi); + + struct aes_key { + u8 key[AES_MAX_KEYLENGTH]; +@@ -52,6 +55,7 @@ struct gcm_ctx { + u8 aad_hash[16]; + u64 aadLen; + u64 Plen; /* offset 56 - used in aes_p10_gcm_{en/de}crypt */ ++ u8 pblock[16]; + }; + struct Hash_ctx { + u8 H[16]; /* subkey */ +@@ -60,17 +64,20 @@ struct Hash_ctx { + + struct p10_aes_gcm_ctx { + struct aes_key enc_key; ++ u8 nonce[RFC4106_NONCE_SIZE]; + }; + + static void vsx_begin(void) + { + preempt_disable(); ++ pagefault_disable(); + enable_kernel_vsx(); + } + + static void vsx_end(void) + { + disable_kernel_vsx(); ++ pagefault_enable(); + preempt_enable(); + } + +@@ -185,7 +192,7 @@ static int set_authsize(struct crypto_aead *tfm, unsigned int authsize) + } + + static int p10_aes_gcm_setkey(struct crypto_aead *aead, const u8 *key, +- unsigned int keylen) ++ unsigned int keylen) + { + struct crypto_tfm *tfm = crypto_aead_tfm(aead); + struct p10_aes_gcm_ctx *ctx = crypto_tfm_ctx(tfm); +@@ -198,7 +205,8 @@ static int p10_aes_gcm_setkey(struct crypto_aead *aead, const u8 *key, + return ret ? -EINVAL : 0; + } + +-static int p10_aes_gcm_crypt(struct aead_request *req, int enc) ++static int p10_aes_gcm_crypt(struct aead_request *req, u8 *riv, ++ int assoclen, int enc) + { + struct crypto_tfm *tfm = req->base.tfm; + struct p10_aes_gcm_ctx *ctx = crypto_tfm_ctx(tfm); +@@ -210,7 +218,6 @@ static int p10_aes_gcm_crypt(struct aead_request *req, int enc) + struct skcipher_walk walk; + u8 *assocmem = NULL; + u8 *assoc; +- unsigned int assoclen = req->assoclen; + unsigned int cryptlen = req->cryptlen; + unsigned char ivbuf[AES_BLOCK_SIZE+PPC_ALIGN]; + unsigned char *iv = PTR_ALIGN((void *)ivbuf, PPC_ALIGN); +@@ -218,11 +225,12 @@ static int p10_aes_gcm_crypt(struct aead_request *req, int enc) + unsigned long auth_tag_len = crypto_aead_authsize(__crypto_aead_cast(tfm)); + u8 otag[16]; + int total_processed = 0; ++ int nbytes; + + memset(databuf, 0, sizeof(databuf)); + memset(hashbuf, 0, sizeof(hashbuf)); + memset(ivbuf, 0, sizeof(ivbuf)); +- memcpy(iv, req->iv, GCM_IV_SIZE); ++ memcpy(iv, riv, GCM_IV_SIZE); + + /* Linearize assoc, if not already linear */ + if (req->src->length >= assoclen && req->src->length) { +@@ -257,19 +265,25 @@ static int p10_aes_gcm_crypt(struct aead_request *req, int enc) + if (ret) + return ret; + +- while (walk.nbytes > 0 && ret == 0) { ++ while ((nbytes = walk.nbytes) > 0 && ret == 0) { ++ u8 *src = walk.src.virt.addr; ++ u8 *dst = walk.dst.virt.addr; ++ u8 buf[AES_BLOCK_SIZE]; ++ ++ if (unlikely(nbytes > 0 && nbytes < AES_BLOCK_SIZE)) ++ src = dst = memcpy(buf, src, nbytes); + + vsx_begin(); + if (enc) +- aes_p10_gcm_encrypt(walk.src.virt.addr, +- walk.dst.virt.addr, +- walk.nbytes, ++ aes_p10_gcm_encrypt(src, dst, nbytes, + &ctx->enc_key, gctx->iv, hash->Htable); + else +- aes_p10_gcm_decrypt(walk.src.virt.addr, +- walk.dst.virt.addr, +- walk.nbytes, ++ aes_p10_gcm_decrypt(src, dst, nbytes, + &ctx->enc_key, gctx->iv, hash->Htable); ++ ++ if (unlikely(nbytes > 0 && nbytes < AES_BLOCK_SIZE)) ++ memcpy(walk.dst.virt.addr, buf, nbytes); ++ + vsx_end(); + + total_processed += walk.nbytes; +@@ -281,6 +295,7 @@ static int p10_aes_gcm_crypt(struct aead_request *req, int enc) + + /* Finalize hash */ + vsx_begin(); ++ gcm_update(gctx->iv, hash->Htable); + finish_tag(gctx, hash, total_processed); + vsx_end(); + +@@ -302,17 +317,63 @@ static int p10_aes_gcm_crypt(struct aead_request *req, int enc) + return 0; + } + ++static int rfc4106_setkey(struct crypto_aead *tfm, const u8 *inkey, ++ unsigned int keylen) ++{ ++ struct p10_aes_gcm_ctx *ctx = crypto_aead_ctx(tfm); ++ int err; ++ ++ keylen -= RFC4106_NONCE_SIZE; ++ err = p10_aes_gcm_setkey(tfm, inkey, keylen); ++ if (err) ++ return err; ++ ++ memcpy(ctx->nonce, inkey + keylen, RFC4106_NONCE_SIZE); ++ return 0; ++} ++ ++static int rfc4106_setauthsize(struct crypto_aead *tfm, unsigned int authsize) ++{ ++ return crypto_rfc4106_check_authsize(authsize); ++} ++ ++static int rfc4106_encrypt(struct aead_request *req) ++{ ++ struct crypto_aead *aead = crypto_aead_reqtfm(req); ++ struct p10_aes_gcm_ctx *ctx = crypto_aead_ctx(aead); ++ u8 iv[AES_BLOCK_SIZE]; ++ ++ memcpy(iv, ctx->nonce, RFC4106_NONCE_SIZE); ++ memcpy(iv + RFC4106_NONCE_SIZE, req->iv, GCM_RFC4106_IV_SIZE); ++ ++ return crypto_ipsec_check_assoclen(req->assoclen) ?: ++ p10_aes_gcm_crypt(req, iv, req->assoclen - GCM_RFC4106_IV_SIZE, 1); ++} ++ ++static int rfc4106_decrypt(struct aead_request *req) ++{ ++ struct crypto_aead *aead = crypto_aead_reqtfm(req); ++ struct p10_aes_gcm_ctx *ctx = crypto_aead_ctx(aead); ++ u8 iv[AES_BLOCK_SIZE]; ++ ++ memcpy(iv, ctx->nonce, RFC4106_NONCE_SIZE); ++ memcpy(iv + RFC4106_NONCE_SIZE, req->iv, GCM_RFC4106_IV_SIZE); ++ ++ return crypto_ipsec_check_assoclen(req->assoclen) ?: ++ p10_aes_gcm_crypt(req, iv, req->assoclen - GCM_RFC4106_IV_SIZE, 0); ++} ++ + static int p10_aes_gcm_encrypt(struct aead_request *req) + { +- return p10_aes_gcm_crypt(req, 1); ++ return p10_aes_gcm_crypt(req, req->iv, req->assoclen, 1); + } + + static int p10_aes_gcm_decrypt(struct aead_request *req) + { +- return p10_aes_gcm_crypt(req, 0); ++ return p10_aes_gcm_crypt(req, req->iv, req->assoclen, 0); + } + +-static struct aead_alg gcm_aes_alg = { ++static struct aead_alg gcm_aes_algs[] = {{ + .ivsize = GCM_IV_SIZE, + .maxauthsize = 16, + +@@ -321,23 +382,57 @@ static struct aead_alg gcm_aes_alg = { + .encrypt = p10_aes_gcm_encrypt, + .decrypt = p10_aes_gcm_decrypt, + +- .base.cra_name = "gcm(aes)", +- .base.cra_driver_name = "aes_gcm_p10", ++ .base.cra_name = "__gcm(aes)", ++ .base.cra_driver_name = "__aes_gcm_p10", + .base.cra_priority = 2100, + .base.cra_blocksize = 1, +- .base.cra_ctxsize = sizeof(struct p10_aes_gcm_ctx), ++ .base.cra_ctxsize = sizeof(struct p10_aes_gcm_ctx)+ ++ 4 * sizeof(u64[2]), + .base.cra_module = THIS_MODULE, +-}; ++ .base.cra_flags = CRYPTO_ALG_INTERNAL, ++}, { ++ .ivsize = GCM_RFC4106_IV_SIZE, ++ .maxauthsize = 16, ++ .setkey = rfc4106_setkey, ++ .setauthsize = rfc4106_setauthsize, ++ .encrypt = rfc4106_encrypt, ++ .decrypt = rfc4106_decrypt, ++ ++ .base.cra_name = "__rfc4106(gcm(aes))", ++ .base.cra_driver_name = "__rfc4106_aes_gcm_p10", ++ .base.cra_priority = 2100, ++ .base.cra_blocksize = 1, ++ .base.cra_ctxsize = sizeof(struct p10_aes_gcm_ctx) + ++ 4 * sizeof(u64[2]), ++ .base.cra_module = THIS_MODULE, ++ .base.cra_flags = CRYPTO_ALG_INTERNAL, ++}}; ++ ++static struct simd_aead_alg *p10_simd_aeads[ARRAY_SIZE(gcm_aes_algs)]; + + static int __init p10_init(void) + { +- return crypto_register_aead(&gcm_aes_alg); ++ int ret; ++ ++ if (!cpu_has_feature(PPC_FEATURE2_ARCH_3_1)) ++ return 0; ++ ++ ret = simd_register_aeads_compat(gcm_aes_algs, ++ ARRAY_SIZE(gcm_aes_algs), ++ p10_simd_aeads); ++ if (ret) { ++ simd_unregister_aeads(gcm_aes_algs, ARRAY_SIZE(gcm_aes_algs), ++ p10_simd_aeads); ++ return ret; ++ } ++ return 0; + } + + static void __exit p10_exit(void) + { +- crypto_unregister_aead(&gcm_aes_alg); ++ simd_unregister_aeads(gcm_aes_algs, ARRAY_SIZE(gcm_aes_algs), ++ p10_simd_aeads); + } + +-module_cpu_feature_match(PPC_MODULE_FEATURE_P10, p10_init); ++module_init(p10_init); + module_exit(p10_exit); +-- +2.43.0 + diff --git a/queue-6.12/crypto-qat-fix-missing-destroy_workqueue-in-adf_init.patch b/queue-6.12/crypto-qat-fix-missing-destroy_workqueue-in-adf_init.patch new file mode 100644 index 00000000000..9c4ebe00ed2 --- /dev/null +++ b/queue-6.12/crypto-qat-fix-missing-destroy_workqueue-in-adf_init.patch @@ -0,0 +1,41 @@ +From 3a7e20a34b437bb562423a72d4e9c0930b647bd8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Tue, 29 Oct 2024 23:05:23 +0800 +Subject: crypto: qat - Fix missing destroy_workqueue in adf_init_aer() + +From: Wang Hai <wanghai38@huawei.com> + +[ Upstream commit d8920a722a8cec625267c09ed40af8fd433d7f9a ] + +The adf_init_aer() won't destroy device_reset_wq when alloc_workqueue() +for device_sriov_wq failed. Add destroy_workqueue for device_reset_wq to +fix this issue. + +Fixes: 4469f9b23468 ("crypto: qat - re-enable sriov after pf reset") +Signed-off-by: Wang Hai <wanghai38@huawei.com> +Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/crypto/intel/qat/qat_common/adf_aer.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/drivers/crypto/intel/qat/qat_common/adf_aer.c b/drivers/crypto/intel/qat/qat_common/adf_aer.c +index ec7913ab00a2c..4cb8bd83f5707 100644 +--- a/drivers/crypto/intel/qat/qat_common/adf_aer.c ++++ b/drivers/crypto/intel/qat/qat_common/adf_aer.c +@@ -281,8 +281,11 @@ int adf_init_aer(void) + return -EFAULT; + + device_sriov_wq = alloc_workqueue("qat_device_sriov_wq", 0, 0); +- if (!device_sriov_wq) ++ if (!device_sriov_wq) { ++ destroy_workqueue(device_reset_wq); ++ device_reset_wq = NULL; + return -EFAULT; ++ } + + return 0; + } +-- +2.43.0 + diff --git a/queue-6.12/crypto-qat-qat_420xx-fix-off-by-one-in-uof_get_name.patch b/queue-6.12/crypto-qat-qat_420xx-fix-off-by-one-in-uof_get_name.patch new file mode 100644 index 00000000000..57793ba8077 --- /dev/null +++ b/queue-6.12/crypto-qat-qat_420xx-fix-off-by-one-in-uof_get_name.patch @@ -0,0 +1,38 @@ +From c32cd2bf4164b699380d8350346dbc18e78e32e4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Sat, 28 Sep 2024 13:05:01 +0300 +Subject: crypto: qat/qat_420xx - fix off by one in uof_get_name() + +From: Dan Carpenter <dan.carpenter@linaro.org> + +[ Upstream commit 93a11608fb3720e1bc2b19a2649ac2b49cca1921 ] + +This is called from uof_get_name_420xx() where "num_objs" is the +ARRAY_SIZE() of fw_objs[]. The > needs to be >= to prevent an out of +bounds access. + +Fixes: fcf60f4bcf54 ("crypto: qat - add support for 420xx devices") +Signed-off-by: Dan Carpenter <dan.carpenter@linaro.org> +Acked-by: Giovanni Cabiddu <giovanni.cabiddu@intel.com> +Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/crypto/intel/qat/qat_420xx/adf_420xx_hw_data.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/crypto/intel/qat/qat_420xx/adf_420xx_hw_data.c b/drivers/crypto/intel/qat/qat_420xx/adf_420xx_hw_data.c +index 78f0ea49254db..9faef33e54bd3 100644 +--- a/drivers/crypto/intel/qat/qat_420xx/adf_420xx_hw_data.c ++++ b/drivers/crypto/intel/qat/qat_420xx/adf_420xx_hw_data.c +@@ -375,7 +375,7 @@ static const char *uof_get_name(struct adf_accel_dev *accel_dev, u32 obj_num, + else + id = -EINVAL; + +- if (id < 0 || id > num_objs) ++ if (id < 0 || id >= num_objs) + return NULL; + + return fw_objs[id]; +-- +2.43.0 + diff --git a/queue-6.12/crypto-qat-qat_4xxx-fix-off-by-one-in-uof_get_name.patch b/queue-6.12/crypto-qat-qat_4xxx-fix-off-by-one-in-uof_get_name.patch new file mode 100644 index 00000000000..035a2459582 --- /dev/null +++ b/queue-6.12/crypto-qat-qat_4xxx-fix-off-by-one-in-uof_get_name.patch @@ -0,0 +1,37 @@ +From 661f421a40346cd102f75996c6898e372533b7f6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Sat, 28 Sep 2024 13:05:08 +0300 +Subject: crypto: qat/qat_4xxx - fix off by one in uof_get_name() + +From: Dan Carpenter <dan.carpenter@linaro.org> + +[ Upstream commit 475b5098043eef6e72751aadeab687992a5b63d1 ] + +The fw_objs[] array has "num_objs" elements so the > needs to be >= to +prevent an out of bounds read. + +Fixes: 10484c647af6 ("crypto: qat - refactor fw config logic for 4xxx") +Signed-off-by: Dan Carpenter <dan.carpenter@linaro.org> +Acked-by: Giovanni Cabiddu <giovanni.cabiddu@intel.com> +Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/crypto/intel/qat/qat_4xxx/adf_4xxx_hw_data.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/crypto/intel/qat/qat_4xxx/adf_4xxx_hw_data.c b/drivers/crypto/intel/qat/qat_4xxx/adf_4xxx_hw_data.c +index 9fd7ec53b9f3d..bbd92c017c28e 100644 +--- a/drivers/crypto/intel/qat/qat_4xxx/adf_4xxx_hw_data.c ++++ b/drivers/crypto/intel/qat/qat_4xxx/adf_4xxx_hw_data.c +@@ -334,7 +334,7 @@ static const char *uof_get_name(struct adf_accel_dev *accel_dev, u32 obj_num, + else + id = -EINVAL; + +- if (id < 0 || id > num_objs) ++ if (id < 0 || id >= num_objs) + return NULL; + + return fw_objs[id]; +-- +2.43.0 + diff --git a/queue-6.12/crypto-qat-remove-check-after-debugfs_create_dir.patch b/queue-6.12/crypto-qat-remove-check-after-debugfs_create_dir.patch new file mode 100644 index 00000000000..1e486c7f64b --- /dev/null +++ b/queue-6.12/crypto-qat-remove-check-after-debugfs_create_dir.patch @@ -0,0 +1,76 @@ +From dc5dfe7e0c9aef04a8e8ef39ee979a753b249ca1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Mon, 16 Sep 2024 10:42:51 +0100 +Subject: crypto: qat - remove check after debugfs_create_dir() + +From: Cabiddu, Giovanni <giovanni.cabiddu@intel.com> + +[ Upstream commit 23717055a79981daf7fafa09a4b0d7566f8384aa ] + +The debugfs functions are guaranteed to return a valid error code +instead of NULL upon failure. Consequently, the driver can directly +propagate any error returned without additional checks. + +Remove the unnecessary `if` statement after debugfs_create_dir(). If +this function fails, the error code is stored in accel_dev->debugfs_dir +and utilized in subsequent debugfs calls. + +Additionally, since accel_dev->debugfs_dir is assured to be non-NULL, +remove the superfluous NULL pointer checks within the adf_dbgfs_add() +and adf_dbgfs_rm(). + +Fixes: 9260db6640a6 ("crypto: qat - move dbgfs init to separate file") +Signed-off-by: Giovanni Cabiddu <giovanni.cabiddu@intel.com> +Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/crypto/intel/qat/qat_common/adf_dbgfs.c | 13 +------------ + 1 file changed, 1 insertion(+), 12 deletions(-) + +diff --git a/drivers/crypto/intel/qat/qat_common/adf_dbgfs.c b/drivers/crypto/intel/qat/qat_common/adf_dbgfs.c +index c42f5c25aabdf..4c11ad1ebcf0f 100644 +--- a/drivers/crypto/intel/qat/qat_common/adf_dbgfs.c ++++ b/drivers/crypto/intel/qat/qat_common/adf_dbgfs.c +@@ -22,18 +22,13 @@ + void adf_dbgfs_init(struct adf_accel_dev *accel_dev) + { + char name[ADF_DEVICE_NAME_LENGTH]; +- void *ret; + + /* Create dev top level debugfs entry */ + snprintf(name, sizeof(name), "%s%s_%s", ADF_DEVICE_NAME_PREFIX, + accel_dev->hw_device->dev_class->name, + pci_name(accel_dev->accel_pci_dev.pci_dev)); + +- ret = debugfs_create_dir(name, NULL); +- if (IS_ERR_OR_NULL(ret)) +- return; +- +- accel_dev->debugfs_dir = ret; ++ accel_dev->debugfs_dir = debugfs_create_dir(name, NULL); + + adf_cfg_dev_dbgfs_add(accel_dev); + } +@@ -59,9 +54,6 @@ EXPORT_SYMBOL_GPL(adf_dbgfs_exit); + */ + void adf_dbgfs_add(struct adf_accel_dev *accel_dev) + { +- if (!accel_dev->debugfs_dir) +- return; +- + if (!accel_dev->is_vf) { + adf_fw_counters_dbgfs_add(accel_dev); + adf_heartbeat_dbgfs_add(accel_dev); +@@ -77,9 +69,6 @@ void adf_dbgfs_add(struct adf_accel_dev *accel_dev) + */ + void adf_dbgfs_rm(struct adf_accel_dev *accel_dev) + { +- if (!accel_dev->debugfs_dir) +- return; +- + if (!accel_dev->is_vf) { + adf_tl_dbgfs_rm(accel_dev); + adf_cnv_dbgfs_rm(accel_dev); +-- +2.43.0 + diff --git a/queue-6.12/crypto-qat-remove-faulty-arbiter-config-reset.patch b/queue-6.12/crypto-qat-remove-faulty-arbiter-config-reset.patch new file mode 100644 index 00000000000..2b9a1474fde --- /dev/null +++ b/queue-6.12/crypto-qat-remove-faulty-arbiter-config-reset.patch @@ -0,0 +1,45 @@ +From 51eef276b271195d80d3d4bdd2d288b238f068ad Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Mon, 7 Oct 2024 14:42:40 +0100 +Subject: crypto: qat - remove faulty arbiter config reset + +From: Ahsan Atta <ahsan.atta@intel.com> + +[ Upstream commit 70199359902f1c7187dcb28a1be679a7081de7cc ] + +Resetting the service arbiter config can cause potential issues +related to response ordering and ring flow control check in the +event of AER or device hang. This is because it results in changing +the default response ring size from 32 bytes to 16 bytes. The service +arbiter config reset also disables response ring flow control check. +Thus, by removing this reset we can prevent the service arbiter from +being configured inappropriately, which leads to undesired device +behaviour in the event of errors. + +Fixes: 7afa232e76ce ("crypto: qat - Intel(R) QAT DH895xcc accelerator") +Signed-off-by: Ahsan Atta <ahsan.atta@intel.com> +Reviewed-by: Giovanni Cabiddu <giovanni.cabiddu@intel.com> +Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/crypto/intel/qat/qat_common/adf_hw_arbiter.c | 4 ---- + 1 file changed, 4 deletions(-) + +diff --git a/drivers/crypto/intel/qat/qat_common/adf_hw_arbiter.c b/drivers/crypto/intel/qat/qat_common/adf_hw_arbiter.c +index 65bd26b25abce..f93d9cca70cee 100644 +--- a/drivers/crypto/intel/qat/qat_common/adf_hw_arbiter.c ++++ b/drivers/crypto/intel/qat/qat_common/adf_hw_arbiter.c +@@ -90,10 +90,6 @@ void adf_exit_arb(struct adf_accel_dev *accel_dev) + + hw_data->get_arb_info(&info); + +- /* Reset arbiter configuration */ +- for (i = 0; i < ADF_ARB_NUM; i++) +- WRITE_CSR_ARB_SARCONFIG(csr, arb_off, i, 0); +- + /* Unmap worker threads to service arbiters */ + for (i = 0; i < hw_data->num_engines; i++) + WRITE_CSR_ARB_WT2SAM(csr, arb_off, wt_off, i, 0); +-- +2.43.0 + diff --git a/queue-6.12/dax-delete-a-stale-directory-pmem.patch b/queue-6.12/dax-delete-a-stale-directory-pmem.patch new file mode 100644 index 00000000000..ee0b7922225 --- /dev/null +++ b/queue-6.12/dax-delete-a-stale-directory-pmem.patch @@ -0,0 +1,61 @@ +From 91bdba1891ae602f95bbc768454b12d2fce34cef Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Thu, 17 Oct 2024 03:11:25 -0700 +Subject: dax: delete a stale directory pmem + +From: Harshit Mogalapalli <harshit.m.mogalapalli@oracle.com> + +[ Upstream commit b8e6d7ce50673c39514921ac61f7af00bbb58b87 ] + +After commit: 83762cb5c7c4 ("dax: Kill DEV_DAX_PMEM_COMPAT") the pmem/ +directory is not needed anymore and Makefile changes were made +accordingly in this commit, but there is a Makefile and pmem.c in pmem/ +which are now stale and pmem.c is empty, remove them. + +Fixes: 83762cb5c7c4 ("dax: Kill DEV_DAX_PMEM_COMPAT") +Suggested-by: Vegard Nossum <vegard.nossum@oracle.com> +Signed-off-by: Harshit Mogalapalli <harshit.m.mogalapalli@oracle.com> +Reviewed-by: Dan Williams <dan.j.williams@intel.com> +Reviewed-by: Ira Weiny <ira.weiny@intel.com> +Link: https://patch.msgid.link/20241017101144.1654085-1-harshit.m.mogalapalli@oracle.com +Signed-off-by: Ira Weiny <ira.weiny@intel.com> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/dax/pmem/Makefile | 7 ------- + drivers/dax/pmem/pmem.c | 10 ---------- + 2 files changed, 17 deletions(-) + delete mode 100644 drivers/dax/pmem/Makefile + delete mode 100644 drivers/dax/pmem/pmem.c + +diff --git a/drivers/dax/pmem/Makefile b/drivers/dax/pmem/Makefile +deleted file mode 100644 +index 191c31f0d4f00..0000000000000 +--- a/drivers/dax/pmem/Makefile ++++ /dev/null +@@ -1,7 +0,0 @@ +-# SPDX-License-Identifier: GPL-2.0-only +-obj-$(CONFIG_DEV_DAX_PMEM) += dax_pmem.o +-obj-$(CONFIG_DEV_DAX_PMEM) += dax_pmem_core.o +- +-dax_pmem-y := pmem.o +-dax_pmem_core-y := core.o +-dax_pmem_compat-y := compat.o +diff --git a/drivers/dax/pmem/pmem.c b/drivers/dax/pmem/pmem.c +deleted file mode 100644 +index dfe91a2990fec..0000000000000 +--- a/drivers/dax/pmem/pmem.c ++++ /dev/null +@@ -1,10 +0,0 @@ +-// SPDX-License-Identifier: GPL-2.0 +-/* Copyright(c) 2016 - 2018 Intel Corporation. All rights reserved. */ +-#include <linux/percpu-refcount.h> +-#include <linux/memremap.h> +-#include <linux/module.h> +-#include <linux/pfn_t.h> +-#include <linux/nd.h> +-#include "../bus.h" +- +- +-- +2.43.0 + diff --git a/queue-6.12/devres-fix-page-faults-when-tracing-devres-from-unlo.patch b/queue-6.12/devres-fix-page-faults-when-tracing-devres-from-unlo.patch new file mode 100644 index 00000000000..bdfeb6ea79c --- /dev/null +++ b/queue-6.12/devres-fix-page-faults-when-tracing-devres-from-unlo.patch @@ -0,0 +1,73 @@ +From f91adca0d339b3975bc44a23ec16f101425031bb Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Sat, 28 Sep 2024 20:50:05 +0800 +Subject: devres: Fix page faults when tracing devres from unloaded modules + +From: Keita Morisaki <keyz@google.com> + +[ Upstream commit 765399553714e934a219d698953d435f4f99caa7 ] + +The devres ftrace event logs the name of the devres node, which is often a +function name (e.g., "devm_work_drop") stringified by macros like +devm_add_action. Currently, ftrace stores this name as a string literal +address, which can become invalid when the module containing the string is +unloaded. This results in page faults when ftrace tries to access the name. + +This behavior is problematic because the devres ftrace event is designed to +trace resource management throughout a device driver's lifecycle, including +during module unload. The event should be available even after the module +is unloaded to properly diagnose resource issues. + +Fix the issue by copying the devres node name into the ftrace ring buffer +using __assign_str(), instead of storing just the address. This ensures +that ftrace can always access the name, even if the module is unloaded. + +This change increases the memory usage for each of the ftrace entry by +12-16 bytes assuming the average devres node name is 20 bytes long, +depending on the size of const char *. + +Note that this change does not affect anything unless all of following +conditions are met. +- CONFIG_DEBUG_DEVRES is enabled +- ftrace tracing is enabled +- The devres event is enabled in ftrace tracing + +Fixes: 09705dcb63d2 ("devres: Enable trace events") +Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com> +Signed-off-by: Keita Morisaki <keyz@google.com> +Link: https://lore.kernel.org/r/20240928125005.714781-1-keyz@google.com +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/base/trace.h | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/drivers/base/trace.h b/drivers/base/trace.h +index e52b6eae060dd..3b83b13a57ff1 100644 +--- a/drivers/base/trace.h ++++ b/drivers/base/trace.h +@@ -24,18 +24,18 @@ DECLARE_EVENT_CLASS(devres, + __field(struct device *, dev) + __field(const char *, op) + __field(void *, node) +- __field(const char *, name) ++ __string(name, name) + __field(size_t, size) + ), + TP_fast_assign( + __assign_str(devname); + __entry->op = op; + __entry->node = node; +- __entry->name = name; ++ __assign_str(name); + __entry->size = size; + ), + TP_printk("%s %3s %p %s (%zu bytes)", __get_str(devname), +- __entry->op, __entry->node, __entry->name, __entry->size) ++ __entry->op, __entry->node, __get_str(name), __entry->size) + ); + + DEFINE_EVENT(devres, devres_log, +-- +2.43.0 + diff --git a/queue-6.12/dlm-fix-dlm_recover_members-refcount-on-error.patch b/queue-6.12/dlm-fix-dlm_recover_members-refcount-on-error.patch new file mode 100644 index 00000000000..196f3b58745 --- /dev/null +++ b/queue-6.12/dlm-fix-dlm_recover_members-refcount-on-error.patch @@ -0,0 +1,38 @@ +From d7cf6be4b6b57f8ae288568fb8115d28075ca909 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Mon, 18 Nov 2024 11:01:49 -0500 +Subject: dlm: fix dlm_recover_members refcount on error + +From: Alexander Aring <aahringo@redhat.com> + +[ Upstream commit 200b977ebbc313a59174ba971006a231b3533dc5 ] + +If dlm_recover_members() fails we don't drop the references of the +previous created root_list that holds and keep all rsbs alive during the +recovery. It might be not an unlikely event because ping_members() could +run into an -EINTR if another recovery progress was triggered again. + +Fixes: 3a747f4a2ee8 ("dlm: move rsb root_list to ls_recover() stack") +Signed-off-by: Alexander Aring <aahringo@redhat.com> +Signed-off-by: David Teigland <teigland@redhat.com> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + fs/dlm/recoverd.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/fs/dlm/recoverd.c b/fs/dlm/recoverd.c +index 34f4f9f49a6ce..12272a8f6d75f 100644 +--- a/fs/dlm/recoverd.c ++++ b/fs/dlm/recoverd.c +@@ -151,7 +151,7 @@ static int ls_recover(struct dlm_ls *ls, struct dlm_recover *rv) + error = dlm_recover_members(ls, rv, &neg); + if (error) { + log_rinfo(ls, "dlm_recover_members error %d", error); +- goto fail; ++ goto fail_root_list; + } + + dlm_recover_dir_nodeid(ls, &root_list); +-- +2.43.0 + diff --git a/queue-6.12/dlm-fix-swapped-args-sb_flags-vs-sb_status.patch b/queue-6.12/dlm-fix-swapped-args-sb_flags-vs-sb_status.patch new file mode 100644 index 00000000000..304ae2202ec --- /dev/null +++ b/queue-6.12/dlm-fix-swapped-args-sb_flags-vs-sb_status.patch @@ -0,0 +1,36 @@ +From e9d66988aeff06f1f5aa1c2891d21ac5eb25dcf8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Fri, 4 Oct 2024 11:13:37 -0400 +Subject: dlm: fix swapped args sb_flags vs sb_status + +From: Alexander Aring <aahringo@redhat.com> + +[ Upstream commit 6d59f2fbfb18965f76ebcff40ab38da717cde798 ] + +The arguments got swapped by commit 986ae3c2a8df ("dlm: fix race between +final callback and remove") fixing this now. + +Fixes: 986ae3c2a8df ("dlm: fix race between final callback and remove") +Signed-off-by: Alexander Aring <aahringo@redhat.com> +Signed-off-by: David Teigland <teigland@redhat.com> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + fs/dlm/ast.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/fs/dlm/ast.c b/fs/dlm/ast.c +index 742b30b61c196..0fe8d80ce5e8d 100644 +--- a/fs/dlm/ast.c ++++ b/fs/dlm/ast.c +@@ -30,7 +30,7 @@ static void dlm_run_callback(uint32_t ls_id, uint32_t lkb_id, int8_t mode, + trace_dlm_bast(ls_id, lkb_id, mode, res_name, res_length); + bastfn(astparam, mode); + } else if (flags & DLM_CB_CAST) { +- trace_dlm_ast(ls_id, lkb_id, sb_status, sb_flags, res_name, ++ trace_dlm_ast(ls_id, lkb_id, sb_flags, sb_status, res_name, + res_length); + lksb->sb_status = sb_status; + lksb->sb_flags = sb_flags; +-- +2.43.0 + diff --git a/queue-6.12/doc-rcu-update-printed-dynticks-counter-bits.patch b/queue-6.12/doc-rcu-update-printed-dynticks-counter-bits.patch new file mode 100644 index 00000000000..66ecd0ac34a --- /dev/null +++ b/queue-6.12/doc-rcu-update-printed-dynticks-counter-bits.patch @@ -0,0 +1,38 @@ +From e22100f358b612db8a101f3e2b4ab3dd0d765b50 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Sun, 18 Aug 2024 11:18:17 +0300 +Subject: doc: rcu: update printed dynticks counter bits + +From: Baruch Siach <baruch@tkos.co.il> + +[ Upstream commit 4a09e358922381f9b258e863bcd9c910584203b9 ] + +The stall warning prints 16 bits since commit 171476775d32 +("context_tracking: Convert state to atomic_t"). + +Fixes: 171476775d32 ("context_tracking: Convert state to atomic_t") +Signed-off-by: Baruch Siach <baruch@tkos.co.il> +Reviewed-by: "Paul E. McKenney" <paulmck@kernel.org> +Signed-off-by: Neeraj Upadhyay <neeraj.upadhyay@kernel.org> +Signed-off-by: Frederic Weisbecker <frederic@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + Documentation/RCU/stallwarn.rst | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/Documentation/RCU/stallwarn.rst b/Documentation/RCU/stallwarn.rst +index ca7b7cd806a16..30080ff6f4062 100644 +--- a/Documentation/RCU/stallwarn.rst ++++ b/Documentation/RCU/stallwarn.rst +@@ -249,7 +249,7 @@ ticks this GP)" indicates that this CPU has not taken any scheduling-clock + interrupts during the current stalled grace period. + + The "idle=" portion of the message prints the dyntick-idle state. +-The hex number before the first "/" is the low-order 12 bits of the ++The hex number before the first "/" is the low-order 16 bits of the + dynticks counter, which will have an even-numbered value if the CPU + is in dyntick-idle mode and an odd-numbered value otherwise. The hex + number between the two "/"s is the value of the nesting, which will be +-- +2.43.0 + diff --git a/queue-6.12/drivers-soc-xilinx-add-the-missing-kfree-in-xlnx_add.patch b/queue-6.12/drivers-soc-xilinx-add-the-missing-kfree-in-xlnx_add.patch new file mode 100644 index 00000000000..f1eaf1b8e88 --- /dev/null +++ b/queue-6.12/drivers-soc-xilinx-add-the-missing-kfree-in-xlnx_add.patch @@ -0,0 +1,42 @@ +From 4ec13e1f3c589f70e85b63127e2c4fbb18e856c5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Sat, 6 Jul 2024 14:51:55 +0800 +Subject: drivers: soc: xilinx: add the missing kfree in + xlnx_add_cb_for_suspend() + +From: Gaosheng Cui <cuigaosheng1@huawei.com> + +[ Upstream commit 44ed4f90a97ff6f339e50ac01db71544e0990efc ] + +If we fail to allocate memory for cb_data by kmalloc, the memory +allocation for eve_data is never freed, add the missing kfree() +in the error handling path. + +Fixes: 05e5ba40ea7a ("driver: soc: xilinx: Add support of multiple callbacks for same event in event management driver") +Signed-off-by: Gaosheng Cui <cuigaosheng1@huawei.com> +Link: https://lore.kernel.org/r/20240706065155.452764-1-cuigaosheng1@huawei.com +Signed-off-by: Michal Simek <michal.simek@amd.com> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/soc/xilinx/xlnx_event_manager.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/soc/xilinx/xlnx_event_manager.c b/drivers/soc/xilinx/xlnx_event_manager.c +index f529e1346247c..85df6b9c04ee6 100644 +--- a/drivers/soc/xilinx/xlnx_event_manager.c ++++ b/drivers/soc/xilinx/xlnx_event_manager.c +@@ -188,8 +188,10 @@ static int xlnx_add_cb_for_suspend(event_cb_func_t cb_fun, void *data) + INIT_LIST_HEAD(&eve_data->cb_list_head); + + cb_data = kmalloc(sizeof(*cb_data), GFP_KERNEL); +- if (!cb_data) ++ if (!cb_data) { ++ kfree(eve_data); + return -ENOMEM; ++ } + cb_data->eve_cb = cb_fun; + cb_data->agent_data = data; + +-- +2.43.0 + diff --git a/queue-6.12/drm-amd-display-fix-a-memleak-issue-when-driver-is-r.patch b/queue-6.12/drm-amd-display-fix-a-memleak-issue-when-driver-is-r.patch new file mode 100644 index 00000000000..ea5ad4a4fb5 --- /dev/null +++ b/queue-6.12/drm-amd-display-fix-a-memleak-issue-when-driver-is-r.patch @@ -0,0 +1,184 @@ +From 7f1ff380e1d8562829decd94467677902cb5dd63 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Mon, 23 Sep 2024 20:07:25 +0000 +Subject: drm/amd/display: fix a memleak issue when driver is removed + +From: Aurabindo Pillai <aurabindo.pillai@amd.com> + +[ Upstream commit d4f36e5fd800de7db74c1c4e62baf24a091a5ff6 ] + +Running "modprobe amdgpu" the second time (followed by a modprobe -r +amdgpu) causes a call trace like: + +[ 845.212163] Memory manager not clean during takedown. +[ 845.212170] WARNING: CPU: 4 PID: 2481 at drivers/gpu/drm/drm_mm.c:999 drm_mm_takedown+0x2b/0x40 +[ 845.212177] Modules linked in: amdgpu(OE-) amddrm_ttm_helper(OE) amddrm_buddy(OE) amdxcp(OE) amd_sched(OE) drm_exec drm_suballoc_helper drm_display_helper i2c_algo_bit amdttm(OE) amdkcl(OE) cec rc_core sunrpc qrtr intel_rapl_msr intel_rapl_common snd_hda_codec_hdmi edac_mce_amd snd_hda_intel snd_intel_dspcfg snd_intel_sdw_acpi snd_usb_audio snd_hda_codec snd_usbmidi_lib kvm_amd snd_hda_core snd_ump mc snd_hwdep kvm snd_pcm snd_seq_midi snd_seq_midi_event irqbypass crct10dif_pclmul snd_rawmidi polyval_clmulni polyval_generic ghash_clmulni_intel sha256_ssse3 sha1_ssse3 snd_seq aesni_intel crypto_simd snd_seq_device cryptd snd_timer mfd_aaeon asus_nb_wmi eeepc_wmi joydev asus_wmi snd ledtrig_audio sparse_keymap ccp wmi_bmof input_leds k10temp i2c_piix4 platform_profile rapl soundcore gpio_amdpt mac_hid binfmt_misc msr parport_pc ppdev lp parport efi_pstore nfnetlink dmi_sysfs ip_tables x_tables autofs4 hid_logitech_hidpp hid_logitech_dj hid_generic usbhid hid ahci xhci_pci igc crc32_pclmul libahci xhci_pci_renesas video +[ 845.212284] wmi [last unloaded: amddrm_ttm_helper(OE)] +[ 845.212290] CPU: 4 PID: 2481 Comm: modprobe Tainted: G W OE 6.8.0-31-generic #31-Ubuntu +[ 845.212296] RIP: 0010:drm_mm_takedown+0x2b/0x40 +[ 845.212300] Code: 1f 44 00 00 48 8b 47 38 48 83 c7 38 48 39 f8 75 09 31 c0 31 ff e9 90 2e 86 00 55 48 c7 c7 d0 f6 8e 8a 48 89 e5 e8 f5 db 45 ff <0f> 0b 5d 31 c0 31 ff e9 74 2e 86 00 66 0f 1f 84 00 00 00 00 00 90 +[ 845.212302] RSP: 0018:ffffb11302127ae0 EFLAGS: 00010246 +[ 845.212305] RAX: 0000000000000000 RBX: ffff92aa5020fc08 RCX: 0000000000000000 +[ 845.212307] RDX: 0000000000000000 RSI: 0000000000000000 RDI: 0000000000000000 +[ 845.212309] RBP: ffffb11302127ae0 R08: 0000000000000000 R09: 0000000000000000 +[ 845.212310] R10: 0000000000000000 R11: 0000000000000000 R12: 0000000000000004 +[ 845.212312] R13: ffff92aa50200000 R14: ffff92aa5020fb10 R15: ffff92aa5020faa0 +[ 845.212313] FS: 0000707dd7c7c080(0000) GS:ffff92b93de00000(0000) knlGS:0000000000000000 +[ 845.212316] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +[ 845.212318] CR2: 00007d48b0aee200 CR3: 0000000115a58000 CR4: 0000000000f50ef0 +[ 845.212320] PKRU: 55555554 +[ 845.212321] Call Trace: +[ 845.212323] <TASK> +[ 845.212328] ? show_regs+0x6d/0x80 +[ 845.212333] ? __warn+0x89/0x160 +[ 845.212339] ? drm_mm_takedown+0x2b/0x40 +[ 845.212344] ? report_bug+0x17e/0x1b0 +[ 845.212350] ? handle_bug+0x51/0xa0 +[ 845.212355] ? exc_invalid_op+0x18/0x80 +[ 845.212359] ? asm_exc_invalid_op+0x1b/0x20 +[ 845.212366] ? drm_mm_takedown+0x2b/0x40 +[ 845.212371] amdgpu_gtt_mgr_fini+0xa9/0x130 [amdgpu] +[ 845.212645] amdgpu_ttm_fini+0x264/0x340 [amdgpu] +[ 845.212770] amdgpu_bo_fini+0x2e/0xc0 [amdgpu] +[ 845.212894] gmc_v12_0_sw_fini+0x2a/0x40 [amdgpu] +[ 845.213036] amdgpu_device_fini_sw+0x11a/0x590 [amdgpu] +[ 845.213159] amdgpu_driver_release_kms+0x16/0x40 [amdgpu] +[ 845.213302] devm_drm_dev_init_release+0x5e/0x90 +[ 845.213305] devm_action_release+0x12/0x30 +[ 845.213308] release_nodes+0x42/0xd0 +[ 845.213311] devres_release_all+0x97/0xe0 +[ 845.213314] device_unbind_cleanup+0x12/0x80 +[ 845.213317] device_release_driver_internal+0x230/0x270 +[ 845.213319] ? srso_alias_return_thunk+0x5/0xfbef5 + +This is caused by lost memory during early init phase. First time driver +is removed, memory is freed but when second time the driver is inserted, +VBIOS dmub is not active, since the PSP policy is to retain the driver +loaded version on subsequent warm boots. Hence, communication with VBIOS +DMUB fails. + +Fix this by aborting further communication with vbios dmub and release +the memory immediately. + +Fixes: f59549c7e705 ("drm/amd/display: free bo used for dmub bounding box") +Reviewed-by: Rodrigo Siqueira <rodrigo.siqueira@amd.com> +Signed-off-by: Aurabindo Pillai <aurabindo.pillai@amd.com> +Signed-off-by: Rodrigo Siqueira <rodrigo.siqueira@amd.com> +Tested-by: Daniel Wheeler <daniel.wheeler@amd.com> +Signed-off-by: Alex Deucher <alexander.deucher@amd.com> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 32 ++++++++++++++++--- + .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h | 3 ++ + .../amd/display/amdgpu_dm/amdgpu_dm_helpers.c | 13 ++------ + 3 files changed, 33 insertions(+), 15 deletions(-) + +diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +index 8d97f17ffe662..24fbde7dd1c42 100644 +--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c ++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +@@ -1696,6 +1696,26 @@ dm_allocate_gpu_mem( + return da->cpu_ptr; + } + ++void ++dm_free_gpu_mem( ++ struct amdgpu_device *adev, ++ enum dc_gpu_mem_alloc_type type, ++ void *pvMem) ++{ ++ struct dal_allocation *da; ++ ++ /* walk the da list in DM */ ++ list_for_each_entry(da, &adev->dm.da_list, list) { ++ if (pvMem == da->cpu_ptr) { ++ amdgpu_bo_free_kernel(&da->bo, &da->gpu_addr, &da->cpu_ptr); ++ list_del(&da->list); ++ kfree(da); ++ break; ++ } ++ } ++ ++} ++ + static enum dmub_status + dm_dmub_send_vbios_gpint_command(struct amdgpu_device *adev, + enum dmub_gpint_command command_code, +@@ -1762,16 +1782,20 @@ static struct dml2_soc_bb *dm_dmub_get_vbios_bounding_box(struct amdgpu_device * + /* Send the chunk */ + ret = dm_dmub_send_vbios_gpint_command(adev, send_addrs[i], chunk, 30000); + if (ret != DMUB_STATUS_OK) +- /* No need to free bb here since it shall be done in dm_sw_fini() */ +- return NULL; ++ goto free_bb; + } + + /* Now ask DMUB to copy the bb */ + ret = dm_dmub_send_vbios_gpint_command(adev, DMUB_GPINT__BB_COPY, 1, 200000); + if (ret != DMUB_STATUS_OK) +- return NULL; ++ goto free_bb; + + return bb; ++ ++free_bb: ++ dm_free_gpu_mem(adev, DC_MEM_ALLOC_TYPE_GART, (void *) bb); ++ return NULL; ++ + } + + static enum dmub_ips_disable_type dm_get_default_ips_mode( +@@ -2541,11 +2565,11 @@ static int dm_sw_fini(void *handle) + amdgpu_bo_free_kernel(&da->bo, &da->gpu_addr, &da->cpu_ptr); + list_del(&da->list); + kfree(da); ++ adev->dm.bb_from_dmub = NULL; + break; + } + } + +- adev->dm.bb_from_dmub = NULL; + + kfree(adev->dm.dmub_fb_info); + adev->dm.dmub_fb_info = NULL; +diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h +index 90dfffec33cf4..a0bc2c0ac04d9 100644 +--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h ++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h +@@ -1004,6 +1004,9 @@ void *dm_allocate_gpu_mem(struct amdgpu_device *adev, + enum dc_gpu_mem_alloc_type type, + size_t size, + long long *addr); ++void dm_free_gpu_mem(struct amdgpu_device *adev, ++ enum dc_gpu_mem_alloc_type type, ++ void *addr); + + bool amdgpu_dm_is_headless(struct amdgpu_device *adev); + +diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c +index eea317dcbe8c3..9752548cc5b21 100644 +--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c ++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c +@@ -1055,17 +1055,8 @@ void dm_helpers_free_gpu_mem( + void *pvMem) + { + struct amdgpu_device *adev = ctx->driver_context; +- struct dal_allocation *da; +- +- /* walk the da list in DM */ +- list_for_each_entry(da, &adev->dm.da_list, list) { +- if (pvMem == da->cpu_ptr) { +- amdgpu_bo_free_kernel(&da->bo, &da->gpu_addr, &da->cpu_ptr); +- list_del(&da->list); +- kfree(da); +- break; +- } +- } ++ ++ dm_free_gpu_mem(adev, type, pvMem); + } + + bool dm_helpers_dmub_outbox_interrupt_control(struct dc_context *ctx, bool enable) +-- +2.43.0 + diff --git a/queue-6.12/drm-amd-display-fix-incorrect-dsc-recompute-trigger.patch b/queue-6.12/drm-amd-display-fix-incorrect-dsc-recompute-trigger.patch new file mode 100644 index 00000000000..4ca9228a3c8 --- /dev/null +++ b/queue-6.12/drm-amd-display-fix-incorrect-dsc-recompute-trigger.patch @@ -0,0 +1,42 @@ +From 8e4fe63081d3908994e6d2e1a79eabd592c8ff14 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Wed, 4 Sep 2024 16:56:45 -0400 +Subject: drm/amd/display: Fix incorrect DSC recompute trigger + +From: Fangzhi Zuo <Jerry.Zuo@amd.com> + +[ Upstream commit 4641169a8c95d9efc35d2d3c55c3948f3b375ff9 ] + +A stream without dsc_aux should not be eliminated from +the dsc determination. Whether it needs a dsc recompute depends on +whether its mode has changed or not. Eliminating such a no-dsc stream +from the dsc determination policy will end up with inconsistencies +in the new dc_state when compared to the current dc_state, +triggering a dsc recompute that should not have happened. + +Reviewed-by: Rodrigo Siqueira <rodrigo.siqueira@amd.com> +Signed-off-by: Fangzhi Zuo <Jerry.Zuo@amd.com> +Signed-off-by: Aurabindo Pillai <aurabindo.pillai@amd.com> +Tested-by: Daniel Wheeler <daniel.wheeler@amd.com> +Signed-off-by: Alex Deucher <alexander.deucher@amd.com> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c +index f756640048fee..32b025c92c63c 100644 +--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c ++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c +@@ -1313,7 +1313,7 @@ static bool is_dsc_need_re_compute( + continue; + + aconnector = (struct amdgpu_dm_connector *) stream->dm_stream_context; +- if (!aconnector || !aconnector->dsc_aux) ++ if (!aconnector) + continue; + + stream_on_link[new_stream_on_link_num] = aconnector; +-- +2.43.0 + diff --git a/queue-6.12/drm-amd-display-fix-null-check-for-pipe_ctx-plane_st.patch b/queue-6.12/drm-amd-display-fix-null-check-for-pipe_ctx-plane_st.patch new file mode 100644 index 00000000000..e8b4dbfc12c --- /dev/null +++ b/queue-6.12/drm-amd-display-fix-null-check-for-pipe_ctx-plane_st.patch @@ -0,0 +1,49 @@ +From b80ddea96b9c3f27f79c6b04696c1104d3853e75 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Tue, 5 Nov 2024 14:01:36 +0000 +Subject: drm/amd/display: Fix null check for pipe_ctx->plane_state in + dcn20_program_pipe + +From: Zicheng Qu <quzicheng@huawei.com> + +[ Upstream commit 6a057072ddd127255350357dd880903e8fa23f36 ] + +This commit addresses a null pointer dereference issue in +dcn20_program_pipe(). Previously, commit 8e4ed3cf1642 ("drm/amd/display: +Add null check for pipe_ctx->plane_state in dcn20_program_pipe") +partially fixed the null pointer dereference issue. However, in +dcn20_update_dchubp_dpp(), the variable pipe_ctx is passed in, and +plane_state is accessed again through pipe_ctx. Multiple if statements +directly call attributes of plane_state, leading to potential null +pointer dereference issues. This patch adds necessary null checks to +ensure stability. + +Fixes: 8e4ed3cf1642 ("drm/amd/display: Add null check for pipe_ctx->plane_state in dcn20_program_pipe") +Reviewed-by: Tom Chung <chiahsuan.chung@amd.com> +Signed-off-by: Zicheng Qu <quzicheng@huawei.com> +Signed-off-by: Alex Deucher <alexander.deucher@amd.com> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c +index a80c085829320..36d12db8d0225 100644 +--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c ++++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c +@@ -1923,9 +1923,9 @@ static void dcn20_program_pipe( + dc->res_pool->hubbub, pipe_ctx->plane_res.hubp->inst, pipe_ctx->hubp_regs.det_size); + } + +- if (pipe_ctx->update_flags.raw || +- (pipe_ctx->plane_state && pipe_ctx->plane_state->update_flags.raw) || +- pipe_ctx->stream->update_flags.raw) ++ if (pipe_ctx->plane_state && (pipe_ctx->update_flags.raw || ++ pipe_ctx->plane_state->update_flags.raw || ++ pipe_ctx->stream->update_flags.raw)) + dcn20_update_dchubp_dpp(dc, pipe_ctx, context); + + if (pipe_ctx->plane_state && (pipe_ctx->update_flags.bits.enable || +-- +2.43.0 + diff --git a/queue-6.12/drm-amd-display-fix-null-check-for-pipe_ctx-plane_st.patch-32135 b/queue-6.12/drm-amd-display-fix-null-check-for-pipe_ctx-plane_st.patch-32135 new file mode 100644 index 00000000000..be84369e852 --- /dev/null +++ b/queue-6.12/drm-amd-display-fix-null-check-for-pipe_ctx-plane_st.patch-32135 @@ -0,0 +1,41 @@ +From 1f6649eaf7e31cc19383a40c54902b387921fdd5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Tue, 5 Nov 2024 14:01:37 +0000 +Subject: drm/amd/display: Fix null check for pipe_ctx->plane_state in + hwss_setup_dpp + +From: Zicheng Qu <quzicheng@huawei.com> + +[ Upstream commit 2bc96c95070571c6c824e0d4c7783bee25a37876 ] + +This commit addresses a null pointer dereference issue in +hwss_setup_dpp(). The issue could occur when pipe_ctx->plane_state is +null. The fix adds a check to ensure `pipe_ctx->plane_state` is not null +before accessing. This prevents a null pointer dereference. + +Fixes: 0baae6246307 ("drm/amd/display: Refactor fast update to use new HWSS build sequence") +Reviewed-by: Tom Chung <chiahsuan.chung@amd.com> +Signed-off-by: Zicheng Qu <quzicheng@huawei.com> +Signed-off-by: Alex Deucher <alexander.deucher@amd.com> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c +index 7ee2be8f82c46..bb766c2a74176 100644 +--- a/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c ++++ b/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c +@@ -881,6 +881,9 @@ void hwss_setup_dpp(union block_sequence_params *params) + struct dpp *dpp = pipe_ctx->plane_res.dpp; + struct dc_plane_state *plane_state = pipe_ctx->plane_state; + ++ if (!plane_state) ++ return; ++ + if (dpp && dpp->funcs->dpp_setup) { + // program the input csc + dpp->funcs->dpp_setup(dpp, +-- +2.43.0 + diff --git a/queue-6.12/drm-amd-display-increase-idle-worker-hpd-detection-t.patch b/queue-6.12/drm-amd-display-increase-idle-worker-hpd-detection-t.patch new file mode 100644 index 00000000000..56d7d2ce6e7 --- /dev/null +++ b/queue-6.12/drm-amd-display-increase-idle-worker-hpd-detection-t.patch @@ -0,0 +1,42 @@ +From 7d1e809fe3bf57a7f2322bf9e0d3343b283a2280 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Mon, 30 Sep 2024 18:07:16 -0400 +Subject: drm/amd/display: Increase idle worker HPD detection time + +From: Roman Li <Roman.Li@amd.com> + +[ Upstream commit 60612f75992d96955fb7154468c58d5d168cf1ab ] + +[Why] +Idle worker thread waits HPD_DETECTION_TIME for HPD processing complete. +Some displays require longer time for that. + +[How] +Increase HPD_DETECTION_TIME to 100ms. + +Reviewed-by: Sun peng Li <sunpeng.li@amd.com> +Signed-off-by: Roman Li <Roman.Li@amd.com> +Tested-by: Daniel Wheeler <daniel.wheeler@amd.com> +Signed-off-by: Alex Deucher <alexander.deucher@amd.com> +Stable-dep-of: a88b19b13fb4 ("drm/amd/display: Reduce HPD Detection Interval for IPS") +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c +index 288be19db7c1b..8780d4737680f 100644 +--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c ++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c +@@ -36,7 +36,7 @@ + #include "amdgpu_dm_debugfs.h" + + #define HPD_DETECTION_PERIOD_uS 5000000 +-#define HPD_DETECTION_TIME_uS 1000 ++#define HPD_DETECTION_TIME_uS 100000 + + void amdgpu_dm_crtc_handle_vblank(struct amdgpu_crtc *acrtc) + { +-- +2.43.0 + diff --git a/queue-6.12/drm-amd-display-reduce-hpd-detection-interval-for-ip.patch b/queue-6.12/drm-amd-display-reduce-hpd-detection-interval-for-ip.patch new file mode 100644 index 00000000000..74c58f1397f --- /dev/null +++ b/queue-6.12/drm-amd-display-reduce-hpd-detection-interval-for-ip.patch @@ -0,0 +1,44 @@ +From 7642b129e42a29d76c80f1f754ca0e9fa6ddbe50 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Tue, 15 Oct 2024 14:22:32 -0400 +Subject: drm/amd/display: Reduce HPD Detection Interval for IPS + +From: Fangzhi Zuo <Jerry.Zuo@amd.com> + +[ Upstream commit a88b19b13fb41a3fa03ec67b5f57cc267fbfb160 ] + +Fix DP Compliance test 4.2.1.3, 4.2.2.8, 4.3.1.12, 4.3.1.13 +when IPS enabled. + +Original HPD detection interval is set to 5s which violates DP +compliance. +Reduce the interval parameter, such that link training can be +finished within 5 seconds. + +Fixes: afca033f10d3 ("drm/amd/display: Add periodic detection for IPS") +Reviewed-by: Roman Li <roman.li@amd.com> +Signed-off-by: Fangzhi Zuo <Jerry.Zuo@amd.com> +Signed-off-by: Tom Chung <chiahsuan.chung@amd.com> +Tested-by: Daniel Wheeler <daniel.wheeler@amd.com> +Signed-off-by: Alex Deucher <alexander.deucher@amd.com> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c +index 8780d4737680f..9be87b5325173 100644 +--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c ++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c +@@ -35,7 +35,7 @@ + #include "amdgpu_dm_trace.h" + #include "amdgpu_dm_debugfs.h" + +-#define HPD_DETECTION_PERIOD_uS 5000000 ++#define HPD_DETECTION_PERIOD_uS 2000000 + #define HPD_DETECTION_TIME_uS 100000 + + void amdgpu_dm_crtc_handle_vblank(struct amdgpu_crtc *acrtc) +-- +2.43.0 + diff --git a/queue-6.12/drm-amd-display-skip-invalid-streams-from-dsc-policy.patch b/queue-6.12/drm-amd-display-skip-invalid-streams-from-dsc-policy.patch new file mode 100644 index 00000000000..5512b36c011 --- /dev/null +++ b/queue-6.12/drm-amd-display-skip-invalid-streams-from-dsc-policy.patch @@ -0,0 +1,70 @@ +From d3c4a1c715212350a55bc54cb53f999632261bd2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Mon, 23 Sep 2024 16:20:40 -0400 +Subject: drm/amd/display: Skip Invalid Streams from DSC Policy + +From: Fangzhi Zuo <Jerry.Zuo@amd.com> + +[ Upstream commit 9afeda04964281e9f708b92c2a9c4f8a1387b46e ] + +Streams with invalid new connector state should be elimiated from +dsc policy. + +Reviewed-by: Aurabindo Pillai <aurabindo.pillai@amd.com> +Signed-off-by: Fangzhi Zuo <Jerry.Zuo@amd.com> +Signed-off-by: Rodrigo Siqueira <rodrigo.siqueira@amd.com> +Tested-by: Daniel Wheeler <daniel.wheeler@amd.com> +Signed-off-by: Alex Deucher <alexander.deucher@amd.com> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + .../drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c | 13 ++++++++++++- + 1 file changed, 12 insertions(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c +index a08e8a0b696c6..f756640048fee 100644 +--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c ++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c +@@ -1120,6 +1120,7 @@ static int compute_mst_dsc_configs_for_link(struct drm_atomic_state *state, + int i, k, ret; + bool debugfs_overwrite = false; + uint16_t fec_overhead_multiplier_x1000 = get_fec_overhead_multiplier(dc_link); ++ struct drm_connector_state *new_conn_state; + + memset(params, 0, sizeof(params)); + +@@ -1127,7 +1128,7 @@ static int compute_mst_dsc_configs_for_link(struct drm_atomic_state *state, + return PTR_ERR(mst_state); + + /* Set up params */ +- DRM_DEBUG_DRIVER("%s: MST_DSC Set up params for %d streams\n", __func__, dc_state->stream_count); ++ DRM_DEBUG_DRIVER("%s: MST_DSC Try to set up params from %d streams\n", __func__, dc_state->stream_count); + for (i = 0; i < dc_state->stream_count; i++) { + struct dc_dsc_policy dsc_policy = {0}; + +@@ -1143,6 +1144,14 @@ static int compute_mst_dsc_configs_for_link(struct drm_atomic_state *state, + if (!aconnector->mst_output_port) + continue; + ++ new_conn_state = drm_atomic_get_new_connector_state(state, &aconnector->base); ++ ++ if (!new_conn_state) { ++ DRM_DEBUG_DRIVER("%s:%d MST_DSC Skip the stream 0x%p with invalid new_conn_state\n", ++ __func__, __LINE__, stream); ++ continue; ++ } ++ + stream->timing.flags.DSC = 0; + + params[count].timing = &stream->timing; +@@ -1175,6 +1184,8 @@ static int compute_mst_dsc_configs_for_link(struct drm_atomic_state *state, + count++; + } + ++ DRM_DEBUG_DRIVER("%s: MST_DSC Params set up for %d streams\n", __func__, count); ++ + if (count == 0) { + ASSERT(0); + return 0; +-- +2.43.0 + diff --git a/queue-6.12/drm-amdgpu-fix-aca-bank-count-boundary-check-error.patch b/queue-6.12/drm-amdgpu-fix-aca-bank-count-boundary-check-error.patch new file mode 100644 index 00000000000..93811b0943c --- /dev/null +++ b/queue-6.12/drm-amdgpu-fix-aca-bank-count-boundary-check-error.patch @@ -0,0 +1,36 @@ +From 85c4361152c0c3be0d0db720b0099037c1530f27 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Wed, 6 Nov 2024 14:49:56 +0800 +Subject: drm/amdgpu: fix ACA bank count boundary check error + +From: Yang Wang <kevinyang.wang@amd.com> + +[ Upstream commit 2bb7dced1c2f8c0e705cc74840f776406db492c3 ] + +fix ACA bank count boundary check error. + +Fixes: f5e4cc8461c4 ("drm/amdgpu: implement RAS ACA driver framework") +Signed-off-by: Yang Wang <kevinyang.wang@amd.com> +Reviewed-by: Tao Zhou <tao.zhou1@amd.com> +Signed-off-by: Alex Deucher <alexander.deucher@amd.com> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/gpu/drm/amd/amdgpu/amdgpu_aca.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_aca.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_aca.c +index 2ca1271731357..9d6345146495f 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_aca.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_aca.c +@@ -158,7 +158,7 @@ static int aca_smu_get_valid_aca_banks(struct amdgpu_device *adev, enum aca_smu_ + return -EINVAL; + } + +- if (start + count >= max_count) ++ if (start + count > max_count) + return -EINVAL; + + count = min_t(int, count, max_count); +-- +2.43.0 + diff --git a/queue-6.12/drm-amdgpu-fix-jpeg-v4.0.3-register-write.patch b/queue-6.12/drm-amdgpu-fix-jpeg-v4.0.3-register-write.patch new file mode 100644 index 00000000000..34b5d1c1397 --- /dev/null +++ b/queue-6.12/drm-amdgpu-fix-jpeg-v4.0.3-register-write.patch @@ -0,0 +1,63 @@ +From 4f8423b0c6b41bae3e1ccf162e784298ea5f67ca Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Fri, 6 Sep 2024 14:10:19 +0530 +Subject: drm/amdgpu: Fix JPEG v4.0.3 register write + +From: Lijo Lazar <lijo.lazar@amd.com> + +[ Upstream commit 8c50bf9beb889fd2bdcbf95b27a5d101eede51fc ] + +EXTERNAL_REG_INTERNAL_OFFSET/EXTERNAL_REG_WRITE_ADDR should be used in +pairs. If an external register shouldn't be written, both packets +shouldn't be sent. + +Fixes: a78b48146972 ("drm/amdgpu: Skip PCTL0_MMHUB_DEEPSLEEP_IB write in jpegv4.0.3 under SRIOV") +Signed-off-by: Lijo Lazar <lijo.lazar@amd.com> +Acked-by: Leo Liu <leo.liu@amd.com> +Signed-off-by: Alex Deucher <alexander.deucher@amd.com> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_3.c | 18 ++++++++++-------- + 1 file changed, 10 insertions(+), 8 deletions(-) + +diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_3.c b/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_3.c +index 86958cb2c2ab2..aa5815bd633eb 100644 +--- a/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_3.c ++++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_3.c +@@ -674,11 +674,12 @@ void jpeg_v4_0_3_dec_ring_insert_start(struct amdgpu_ring *ring) + amdgpu_ring_write(ring, PACKETJ(regUVD_JRBC_EXTERNAL_REG_INTERNAL_OFFSET, + 0, 0, PACKETJ_TYPE0)); + amdgpu_ring_write(ring, 0x62a04); /* PCTL0_MMHUB_DEEPSLEEP_IB */ +- } + +- amdgpu_ring_write(ring, PACKETJ(JRBC_DEC_EXTERNAL_REG_WRITE_ADDR, +- 0, 0, PACKETJ_TYPE0)); +- amdgpu_ring_write(ring, 0x80004000); ++ amdgpu_ring_write(ring, ++ PACKETJ(JRBC_DEC_EXTERNAL_REG_WRITE_ADDR, 0, ++ 0, PACKETJ_TYPE0)); ++ amdgpu_ring_write(ring, 0x80004000); ++ } + } + + /** +@@ -694,11 +695,12 @@ void jpeg_v4_0_3_dec_ring_insert_end(struct amdgpu_ring *ring) + amdgpu_ring_write(ring, PACKETJ(regUVD_JRBC_EXTERNAL_REG_INTERNAL_OFFSET, + 0, 0, PACKETJ_TYPE0)); + amdgpu_ring_write(ring, 0x62a04); +- } + +- amdgpu_ring_write(ring, PACKETJ(JRBC_DEC_EXTERNAL_REG_WRITE_ADDR, +- 0, 0, PACKETJ_TYPE0)); +- amdgpu_ring_write(ring, 0x00004000); ++ amdgpu_ring_write(ring, ++ PACKETJ(JRBC_DEC_EXTERNAL_REG_WRITE_ADDR, 0, ++ 0, PACKETJ_TYPE0)); ++ amdgpu_ring_write(ring, 0x00004000); ++ } + } + + /** +-- +2.43.0 + diff --git a/queue-6.12/drm-amdgpu-fix-map-unmap-queue-logic.patch b/queue-6.12/drm-amdgpu-fix-map-unmap-queue-logic.patch new file mode 100644 index 00000000000..84def774a50 --- /dev/null +++ b/queue-6.12/drm-amdgpu-fix-map-unmap-queue-logic.patch @@ -0,0 +1,199 @@ +From 55ed3a0faa180713b24f8eb08f741ad8cc6a68a5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Tue, 5 Nov 2024 10:30:20 +0530 +Subject: drm/amdgpu: Fix map/unmap queue logic + +From: Lijo Lazar <lijo.lazar@amd.com> + +[ Upstream commit fa31798582882740f2b13d19e1bd43b4ef918e2f ] + +In current logic, it calls ring_alloc followed by a ring_test. ring_test +in turn will call another ring_alloc. This is illegal usage as a +ring_alloc is expected to be closed properly with a ring_commit. Change +to commit the map/unmap queue packet first followed by a ring_test. Add a +comment about the usage of ring_test. + +Also, reorder the current pre-condition checks of job hang or kiq ring +scheduler not ready. Without them being met, it is not useful to attempt +ring or memory allocations. + +Fixes tag refers to the original patch which introduced this issue which +then got carried over into newer code. + +Signed-off-by: Lijo Lazar <lijo.lazar@amd.com> +Reviewed-by: Le Ma <le.ma@amd.com> +Signed-off-by: Alex Deucher <alexander.deucher@amd.com> +Fixes: 6c10b5cc4eaa ("drm/amdgpu: Remove duplicate code in gfx_v8_0.c") +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c | 13 ++++- + drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c | 63 +++++++++++++++------- + drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c | 7 +++ + 3 files changed, 63 insertions(+), 20 deletions(-) + +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c +index 4f08b153cb66d..e41318bfbf457 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c +@@ -834,6 +834,9 @@ int amdgpu_amdkfd_unmap_hiq(struct amdgpu_device *adev, u32 doorbell_off, + if (!kiq->pmf || !kiq->pmf->kiq_unmap_queues) + return -EINVAL; + ++ if (!kiq_ring->sched.ready || adev->job_hang) ++ return 0; ++ + ring_funcs = kzalloc(sizeof(*ring_funcs), GFP_KERNEL); + if (!ring_funcs) + return -ENOMEM; +@@ -858,8 +861,14 @@ int amdgpu_amdkfd_unmap_hiq(struct amdgpu_device *adev, u32 doorbell_off, + + kiq->pmf->kiq_unmap_queues(kiq_ring, ring, RESET_QUEUES, 0, 0); + +- if (kiq_ring->sched.ready && !adev->job_hang) +- r = amdgpu_ring_test_helper(kiq_ring); ++ /* Submit unmap queue packet */ ++ amdgpu_ring_commit(kiq_ring); ++ /* ++ * Ring test will do a basic scratch register change check. Just run ++ * this to ensure that unmap queues that is submitted before got ++ * processed successfully before returning. ++ */ ++ r = amdgpu_ring_test_helper(kiq_ring); + + spin_unlock(&kiq->ring_lock); + +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c +index f1ffab5a1eaed..156abd2ba5a6c 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c +@@ -525,6 +525,17 @@ int amdgpu_gfx_disable_kcq(struct amdgpu_device *adev, int xcc_id) + if (!kiq->pmf || !kiq->pmf->kiq_unmap_queues) + return -EINVAL; + ++ if (!kiq_ring->sched.ready || adev->job_hang) ++ return 0; ++ /** ++ * This is workaround: only skip kiq_ring test ++ * during ras recovery in suspend stage for gfx9.4.3 ++ */ ++ if ((amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(9, 4, 3) || ++ amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(9, 4, 4)) && ++ amdgpu_ras_in_recovery(adev)) ++ return 0; ++ + spin_lock(&kiq->ring_lock); + if (amdgpu_ring_alloc(kiq_ring, kiq->pmf->unmap_queues_size * + adev->gfx.num_compute_rings)) { +@@ -538,20 +549,15 @@ int amdgpu_gfx_disable_kcq(struct amdgpu_device *adev, int xcc_id) + &adev->gfx.compute_ring[j], + RESET_QUEUES, 0, 0); + } +- +- /** +- * This is workaround: only skip kiq_ring test +- * during ras recovery in suspend stage for gfx9.4.3 ++ /* Submit unmap queue packet */ ++ amdgpu_ring_commit(kiq_ring); ++ /* ++ * Ring test will do a basic scratch register change check. Just run ++ * this to ensure that unmap queues that is submitted before got ++ * processed successfully before returning. + */ +- if ((amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(9, 4, 3) || +- amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(9, 4, 4)) && +- amdgpu_ras_in_recovery(adev)) { +- spin_unlock(&kiq->ring_lock); +- return 0; +- } ++ r = amdgpu_ring_test_helper(kiq_ring); + +- if (kiq_ring->sched.ready && !adev->job_hang) +- r = amdgpu_ring_test_helper(kiq_ring); + spin_unlock(&kiq->ring_lock); + + return r; +@@ -579,8 +585,11 @@ int amdgpu_gfx_disable_kgq(struct amdgpu_device *adev, int xcc_id) + if (!kiq->pmf || !kiq->pmf->kiq_unmap_queues) + return -EINVAL; + +- spin_lock(&kiq->ring_lock); ++ if (!adev->gfx.kiq[0].ring.sched.ready || adev->job_hang) ++ return 0; ++ + if (amdgpu_gfx_is_master_xcc(adev, xcc_id)) { ++ spin_lock(&kiq->ring_lock); + if (amdgpu_ring_alloc(kiq_ring, kiq->pmf->unmap_queues_size * + adev->gfx.num_gfx_rings)) { + spin_unlock(&kiq->ring_lock); +@@ -593,11 +602,17 @@ int amdgpu_gfx_disable_kgq(struct amdgpu_device *adev, int xcc_id) + &adev->gfx.gfx_ring[j], + PREEMPT_QUEUES, 0, 0); + } +- } ++ /* Submit unmap queue packet */ ++ amdgpu_ring_commit(kiq_ring); + +- if (adev->gfx.kiq[0].ring.sched.ready && !adev->job_hang) ++ /* ++ * Ring test will do a basic scratch register change check. ++ * Just run this to ensure that unmap queues that is submitted ++ * before got processed successfully before returning. ++ */ + r = amdgpu_ring_test_helper(kiq_ring); +- spin_unlock(&kiq->ring_lock); ++ spin_unlock(&kiq->ring_lock); ++ } + + return r; + } +@@ -702,7 +717,13 @@ int amdgpu_gfx_enable_kcq(struct amdgpu_device *adev, int xcc_id) + kiq->pmf->kiq_map_queues(kiq_ring, + &adev->gfx.compute_ring[j]); + } +- ++ /* Submit map queue packet */ ++ amdgpu_ring_commit(kiq_ring); ++ /* ++ * Ring test will do a basic scratch register change check. Just run ++ * this to ensure that map queues that is submitted before got ++ * processed successfully before returning. ++ */ + r = amdgpu_ring_test_helper(kiq_ring); + spin_unlock(&kiq->ring_lock); + if (r) +@@ -753,7 +774,13 @@ int amdgpu_gfx_enable_kgq(struct amdgpu_device *adev, int xcc_id) + &adev->gfx.gfx_ring[j]); + } + } +- ++ /* Submit map queue packet */ ++ amdgpu_ring_commit(kiq_ring); ++ /* ++ * Ring test will do a basic scratch register change check. Just run ++ * this to ensure that map queues that is submitted before got ++ * processed successfully before returning. ++ */ + r = amdgpu_ring_test_helper(kiq_ring); + spin_unlock(&kiq->ring_lock); + if (r) +diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c +index bc8295812cc84..9d741695ca07d 100644 +--- a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c ++++ b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c +@@ -4823,6 +4823,13 @@ static int gfx_v8_0_kcq_disable(struct amdgpu_device *adev) + amdgpu_ring_write(kiq_ring, 0); + amdgpu_ring_write(kiq_ring, 0); + } ++ /* Submit unmap queue packet */ ++ amdgpu_ring_commit(kiq_ring); ++ /* ++ * Ring test will do a basic scratch register change check. Just run ++ * this to ensure that unmap queues that is submitted before got ++ * processed successfully before returning. ++ */ + r = amdgpu_ring_test_helper(kiq_ring); + if (r) + DRM_ERROR("KCQ disable failed\n"); +-- +2.43.0 + diff --git a/queue-6.12/drm-amdgpu-fix-the-memory-allocation-issue-in-amdgpu.patch b/queue-6.12/drm-amdgpu-fix-the-memory-allocation-issue-in-amdgpu.patch new file mode 100644 index 00000000000..744fa3d2b36 --- /dev/null +++ b/queue-6.12/drm-amdgpu-fix-the-memory-allocation-issue-in-amdgpu.patch @@ -0,0 +1,57 @@ +From d014d04854e7ad3c34d9ff0b2fed45771563f9e1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Wed, 30 Oct 2024 04:27:58 +0800 +Subject: drm/amdgpu: Fix the memory allocation issue in + amdgpu_discovery_get_nps_info() + +From: Li Huafei <lihuafei1@huawei.com> + +[ Upstream commit a1144da794adedb9447437c57d69add56494309d ] + +Fix two issues with memory allocation in amdgpu_discovery_get_nps_info() +for mem_ranges: + + - Add a check for allocation failure to avoid dereferencing a null + pointer. + + - As suggested by Christophe, use kvcalloc() for memory allocation, + which checks for multiplication overflow. + +Additionally, assign the output parameters nps_type and range_cnt after +the kvcalloc() call to prevent modifying the output parameters in case +of an error return. + +Fixes: b194d21b9bcc ("drm/amdgpu: Use NPS ranges from discovery table") +Suggested-by: Christophe JAILLET <christophe.jaillet@wanadoo.fr> +Reviewed-by: Lijo Lazar <lijo.lazar@amd.com> +Signed-off-by: Li Huafei <lihuafei1@huawei.com> +Signed-off-by: Alex Deucher <alexander.deucher@amd.com> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c | 8 +++++--- + 1 file changed, 5 insertions(+), 3 deletions(-) + +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c +index 4bd61c169ca8d..ca8091fd3a24f 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c +@@ -1757,11 +1757,13 @@ int amdgpu_discovery_get_nps_info(struct amdgpu_device *adev, + + switch (le16_to_cpu(nps_info->v1.header.version_major)) { + case 1: ++ mem_ranges = kvcalloc(nps_info->v1.count, ++ sizeof(*mem_ranges), ++ GFP_KERNEL); ++ if (!mem_ranges) ++ return -ENOMEM; + *nps_type = nps_info->v1.nps_type; + *range_cnt = nps_info->v1.count; +- mem_ranges = kvzalloc( +- *range_cnt * sizeof(struct amdgpu_gmc_memrange), +- GFP_KERNEL); + for (i = 0; i < *range_cnt; i++) { + mem_ranges[i].base_address = + nps_info->v1.instance_info[i].base_address; +-- +2.43.0 + diff --git a/queue-6.12/drm-amdgpu-gfx9-add-cleaner-shader-deinitialization-.patch b/queue-6.12/drm-amdgpu-gfx9-add-cleaner-shader-deinitialization-.patch new file mode 100644 index 00000000000..c0197d88edb --- /dev/null +++ b/queue-6.12/drm-amdgpu-gfx9-add-cleaner-shader-deinitialization-.patch @@ -0,0 +1,51 @@ +From 72ea145563a74168e6b63b281f67bf8e283f6aca Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Tue, 1 Oct 2024 12:26:46 +0530 +Subject: drm/amdgpu/gfx9: Add Cleaner Shader Deinitialization in gfx_v9_0 + Module +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Srinivasan Shanmugam <srinivasan.shanmugam@amd.com> + +[ Upstream commit e47cb9d2533200d49dd5364d4a148119492f8a3d ] + +This commit addresses an omission in the previous patch related to the +cleaner shader support for GFX9 hardware. Specifically, it adds the +necessary deinitialization code for the cleaner shader in the +gfx_v9_0_sw_fini function. + +The added line amdgpu_gfx_cleaner_shader_sw_fini(adev); ensures that any +allocated resources for the cleaner shader are freed correctly, avoiding +potential memory leaks and ensuring that the GPU state is clean for the +next initialization sequence. + +Cc: Christian König <christian.koenig@amd.com> +Cc: Alex Deucher <alexander.deucher@amd.com> +Fixes: c2e70d307f44 ("drm/amdgpu/gfx9: Implement cleaner shader support for GFX9 hardware") +Signed-off-by: Srinivasan Shanmugam <srinivasan.shanmugam@amd.com> +Acked-by: Christian König <christian.koenig@amd.com> +Acked-by: Alex Deucher <alexander.deucher@amd.com> +Signed-off-by: Alex Deucher <alexander.deucher@amd.com> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c +index 23f0573ae47b3..785a343a95f0f 100644 +--- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c ++++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c +@@ -2418,6 +2418,8 @@ static int gfx_v9_0_sw_fini(void *handle) + amdgpu_gfx_kiq_free_ring(&adev->gfx.kiq[0].ring); + amdgpu_gfx_kiq_fini(adev, 0); + ++ amdgpu_gfx_cleaner_shader_sw_fini(adev); ++ + gfx_v9_0_mec_fini(adev); + amdgpu_bo_free_kernel(&adev->gfx.rlc.clear_state_obj, + &adev->gfx.rlc.clear_state_gpu_addr, +-- +2.43.0 + diff --git a/queue-6.12/drm-amdkfd-fix-wrong-usage-of-init_work.patch b/queue-6.12/drm-amdkfd-fix-wrong-usage-of-init_work.patch new file mode 100644 index 00000000000..e757066e952 --- /dev/null +++ b/queue-6.12/drm-amdkfd-fix-wrong-usage-of-init_work.patch @@ -0,0 +1,49 @@ +From 50a2e505e196e9f4400dd8839d9e4db0aada8d85 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Wed, 6 Nov 2024 09:35:41 +0800 +Subject: drm/amdkfd: Fix wrong usage of INIT_WORK() + +From: Yuan Can <yuancan@huawei.com> + +[ Upstream commit 21cae8debc6a1d243f64fa82cd1b41cb612b5c61 ] + +In kfd_procfs_show(), the sdma_activity_work_handler is a local variable +and the sdma_activity_work_handler.sdma_activity_work should initialize +with INIT_WORK_ONSTACK() instead of INIT_WORK(). + +Fixes: 32cb59f31362 ("drm/amdkfd: Track SDMA utilization per process") +Signed-off-by: Yuan Can <yuancan@huawei.com> +Signed-off-by: Felix Kuehling <felix.kuehling@amd.com> +Reviewed-by: Felix Kuehling <felix.kuehling@amd.com> +Signed-off-by: Alex Deucher <alexander.deucher@amd.com> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/gpu/drm/amd/amdkfd/kfd_process.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process.c b/drivers/gpu/drm/amd/amdkfd/kfd_process.c +index 6bab6fc6a35d6..ff34bb1ac9db7 100644 +--- a/drivers/gpu/drm/amd/amdkfd/kfd_process.c ++++ b/drivers/gpu/drm/amd/amdkfd/kfd_process.c +@@ -341,8 +341,8 @@ static ssize_t kfd_procfs_show(struct kobject *kobj, struct attribute *attr, + attr_sdma); + struct kfd_sdma_activity_handler_workarea sdma_activity_work_handler; + +- INIT_WORK(&sdma_activity_work_handler.sdma_activity_work, +- kfd_sdma_activity_worker); ++ INIT_WORK_ONSTACK(&sdma_activity_work_handler.sdma_activity_work, ++ kfd_sdma_activity_worker); + + sdma_activity_work_handler.pdd = pdd; + sdma_activity_work_handler.sdma_activity_counter = 0; +@@ -350,6 +350,7 @@ static ssize_t kfd_procfs_show(struct kobject *kobj, struct attribute *attr, + schedule_work(&sdma_activity_work_handler.sdma_activity_work); + + flush_work(&sdma_activity_work_handler.sdma_activity_work); ++ destroy_work_on_stack(&sdma_activity_work_handler.sdma_activity_work); + + return snprintf(buffer, PAGE_SIZE, "%llu\n", + (sdma_activity_work_handler.sdma_activity_counter)/ +-- +2.43.0 + diff --git a/queue-6.12/drm-amdkfd-use-dynamic-allocation-for-cu-occupancy-a.patch b/queue-6.12/drm-amdkfd-use-dynamic-allocation-for-cu-occupancy-a.patch new file mode 100644 index 00000000000..69c7a1fd718 --- /dev/null +++ b/queue-6.12/drm-amdkfd-use-dynamic-allocation-for-cu-occupancy-a.patch @@ -0,0 +1,83 @@ +From b599064a7f7cf76984c91e803f1992383d7817b3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Fri, 4 Oct 2024 09:12:39 +0530 +Subject: drm/amdkfd: Use dynamic allocation for CU occupancy array in + 'kfd_get_cu_occupancy()' +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Srinivasan Shanmugam <srinivasan.shanmugam@amd.com> + +[ Upstream commit 922f0e00017b09d9d47e3efac008c8b20ed546a0 ] + +The `kfd_get_cu_occupancy` function previously declared a large +`cu_occupancy` array as a local variable, which could lead to stack +overflows due to excessive stack usage. This commit replaces the static +array allocation with dynamic memory allocation using `kcalloc`, +thereby reducing the stack size. + +This change avoids the risk of stack overflows in kernel space, in +scenarios where `AMDGPU_MAX_QUEUES` is large. The allocated memory is +freed using `kfree` before the function returns to prevent memory +leaks. + +Fixes the below with gcc W=1: +drivers/gpu/drm/amd/amdgpu/../amdkfd/kfd_process.c: In function ‘kfd_get_cu_occupancy’: +drivers/gpu/drm/amd/amdgpu/../amdkfd/kfd_process.c:322:1: warning: the frame size of 1056 bytes is larger than 1024 bytes [-Wframe-larger-than=] + 322 | } + | ^ + +Fixes: 6ae9e1aba97e ("drm/amdkfd: Update logic for CU occupancy calculations") +Cc: Harish Kasiviswanathan <Harish.Kasiviswanathan@amd.com> +Cc: Felix Kuehling <felix.kuehling@amd.com> +Cc: Christian König <christian.koenig@amd.com> +Cc: Alex Deucher <alexander.deucher@amd.com> +Signed-off-by: Srinivasan Shanmugam <srinivasan.shanmugam@amd.com> +Suggested-by: Mukul Joshi <mukul.joshi@amd.com> +Reviewed-by: Mukul Joshi <mukul.joshi@amd.com> +Signed-off-by: Alex Deucher <alexander.deucher@amd.com> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/gpu/drm/amd/amdkfd/kfd_process.c | 9 ++++++--- + 1 file changed, 6 insertions(+), 3 deletions(-) + +diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process.c b/drivers/gpu/drm/amd/amdkfd/kfd_process.c +index d4aa843aacfdd..6bab6fc6a35d6 100644 +--- a/drivers/gpu/drm/amd/amdkfd/kfd_process.c ++++ b/drivers/gpu/drm/amd/amdkfd/kfd_process.c +@@ -271,11 +271,9 @@ static int kfd_get_cu_occupancy(struct attribute *attr, char *buffer) + struct kfd_process *proc = NULL; + struct kfd_process_device *pdd = NULL; + int i; +- struct kfd_cu_occupancy cu_occupancy[AMDGPU_MAX_QUEUES]; ++ struct kfd_cu_occupancy *cu_occupancy; + u32 queue_format; + +- memset(cu_occupancy, 0x0, sizeof(cu_occupancy)); +- + pdd = container_of(attr, struct kfd_process_device, attr_cu_occupancy); + dev = pdd->dev; + if (dev->kfd2kgd->get_cu_occupancy == NULL) +@@ -293,6 +291,10 @@ static int kfd_get_cu_occupancy(struct attribute *attr, char *buffer) + wave_cnt = 0; + max_waves_per_cu = 0; + ++ cu_occupancy = kcalloc(AMDGPU_MAX_QUEUES, sizeof(*cu_occupancy), GFP_KERNEL); ++ if (!cu_occupancy) ++ return -ENOMEM; ++ + /* + * For GFX 9.4.3, fetch the CU occupancy from the first XCC in the partition. + * For AQL queues, because of cooperative dispatch we multiply the wave count +@@ -318,6 +320,7 @@ static int kfd_get_cu_occupancy(struct attribute *attr, char *buffer) + + /* Translate wave count to number of compute units */ + cu_cnt = (wave_cnt + (max_waves_per_cu - 1)) / max_waves_per_cu; ++ kfree(cu_occupancy); + return snprintf(buffer, PAGE_SIZE, "%d\n", cu_cnt); + } + +-- +2.43.0 + diff --git a/queue-6.12/drm-bridge-anx7625-drop-edid-cache-on-bridge-power-o.patch b/queue-6.12/drm-bridge-anx7625-drop-edid-cache-on-bridge-power-o.patch new file mode 100644 index 00000000000..8780ec2e888 --- /dev/null +++ b/queue-6.12/drm-bridge-anx7625-drop-edid-cache-on-bridge-power-o.patch @@ -0,0 +1,45 @@ +From 51f255fa2316ff441a9f40202b31d70b30117a09 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Thu, 26 Sep 2024 17:29:08 +0800 +Subject: drm/bridge: anx7625: Drop EDID cache on bridge power off + +From: Pin-yen Lin <treapking@chromium.org> + +[ Upstream commit 00ae002116a14c2e6a342c4c9ae080cdbb9b4b21 ] + +The bridge might miss the display change events when it's powered off. +This happens when a user changes the external monitor when the system +is suspended and the embedded controller doesn't not wake AP up. + +It's also observed that one DP-to-HDMI bridge doesn't work correctly +when there is no EDID read after it is powered on. + +Drop the cache to force an EDID read after system resume to fix this. + +Fixes: 8bdfc5dae4e3 ("drm/bridge: anx7625: Add anx7625 MIPI DSI/DPI to DP") +Signed-off-by: Pin-yen Lin <treapking@chromium.org> +Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org> +Reviewed-by: Douglas Anderson <dianders@chromium.org> +Signed-off-by: Douglas Anderson <dianders@chromium.org> +Link: https://patchwork.freedesktop.org/patch/msgid/20240926092931.3870342-2-treapking@chromium.org +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/gpu/drm/bridge/analogix/anx7625.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.c b/drivers/gpu/drm/bridge/analogix/anx7625.c +index a2e9bb485c366..a2675b121fe44 100644 +--- a/drivers/gpu/drm/bridge/analogix/anx7625.c ++++ b/drivers/gpu/drm/bridge/analogix/anx7625.c +@@ -2551,6 +2551,8 @@ static int __maybe_unused anx7625_runtime_pm_suspend(struct device *dev) + mutex_lock(&ctx->lock); + + anx7625_stop_dp_work(ctx); ++ if (!ctx->pdata.panel_bridge) ++ anx7625_remove_edid(ctx); + anx7625_power_standby(ctx); + + mutex_unlock(&ctx->lock); +-- +2.43.0 + diff --git a/queue-6.12/drm-bridge-it6505-drop-edid-cache-on-bridge-power-of.patch b/queue-6.12/drm-bridge-it6505-drop-edid-cache-on-bridge-power-of.patch new file mode 100644 index 00000000000..efeb4df89c5 --- /dev/null +++ b/queue-6.12/drm-bridge-it6505-drop-edid-cache-on-bridge-power-of.patch @@ -0,0 +1,45 @@ +From 0d4cd5a4fc1ee7d8da948e01009129fded554498 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Thu, 26 Sep 2024 17:29:09 +0800 +Subject: drm/bridge: it6505: Drop EDID cache on bridge power off + +From: Pin-yen Lin <treapking@chromium.org> + +[ Upstream commit 574c558ddb68591c9a4b7a95e45e935ab22c0fc6 ] + +The bridge might miss the display change events when it's powered off. +This happens when a user changes the external monitor when the system +is suspended and the embedded controller doesn't not wake AP up. + +It's also observed that one DP-to-HDMI bridge doesn't work correctly +when there is no EDID read after it is powered on. + +Drop the cache to force an EDID read after system resume to fix this. + +Fixes: 11feaef69d0c ("drm/bridge: it6505: Add caching for EDID") +Signed-off-by: Pin-yen Lin <treapking@chromium.org> +Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org> +Reviewed-by: Douglas Anderson <dianders@chromium.org> +Signed-off-by: Douglas Anderson <dianders@chromium.org> +Link: https://patchwork.freedesktop.org/patch/msgid/20240926092931.3870342-3-treapking@chromium.org +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/gpu/drm/bridge/ite-it6505.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/gpu/drm/bridge/ite-it6505.c b/drivers/gpu/drm/bridge/ite-it6505.c +index 87b8545fccc0a..e3a9832c742cb 100644 +--- a/drivers/gpu/drm/bridge/ite-it6505.c ++++ b/drivers/gpu/drm/bridge/ite-it6505.c +@@ -3107,6 +3107,8 @@ static __maybe_unused int it6505_bridge_suspend(struct device *dev) + { + struct it6505 *it6505 = dev_get_drvdata(dev); + ++ it6505_remove_edid(it6505); ++ + return it6505_poweroff(it6505); + } + +-- +2.43.0 + diff --git a/queue-6.12/drm-bridge-tc358767-fix-link-properties-discovery.patch b/queue-6.12/drm-bridge-tc358767-fix-link-properties-discovery.patch new file mode 100644 index 00000000000..43a65b7469c --- /dev/null +++ b/queue-6.12/drm-bridge-tc358767-fix-link-properties-discovery.patch @@ -0,0 +1,60 @@ +From 037442f0f18baa359833c897b1ffa60cf4228f41 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Wed, 8 Nov 2023 13:27:23 +0200 +Subject: drm/bridge: tc358767: Fix link properties discovery + +From: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com> + +[ Upstream commit 2d343723c7e1f9f6d64f721f07cfdfc2993758d1 ] + +When a display controller driver uses DRM_BRIDGE_ATTACH_NO_CONNECTOR, +tc358767 will behave properly and skip the creation of the connector. + +However, tc_get_display_props(), which is used to find out about the DP +monitor and link, is only called from two places: .atomic_enable() and +tc_connector_get_modes(). The latter is only used when tc358767 creates +its own connector, i.e. when DRM_BRIDGE_ATTACH_NO_CONNECTOR is _not_ +set. + +Thus, the driver never finds out the link properties before get_edid() +is called. With num_lanes of 0 and link_rate of 0 there are not many +valid modes... + +Fix this by adding tc_get_display_props() call at the beginning of +get_edid(), so that we have up to date information before looking at the +modes. + +Reported-by: Jan Kiszka <jan.kiszka@siemens.com> +Closes: https://lore.kernel.org/all/24282420-b4dd-45b3-bb1c-fc37fe4a8205@siemens.com/ +Fixes: de5e6c027ae6 ("drm/bridge: tc358767: add drm_panel_bridge support") +Reviewed-by: Aradhya Bhatia <a-bhatia1@ti.com> +Tested-by: Jan Kiszka <jan.kiszka@siemens.com> +Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com> +Link: https://patchwork.freedesktop.org/patch/msgid/20231108-tc358767-v2-2-25c5f70a2159@ideasonboard.com +Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/gpu/drm/bridge/tc358767.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/drivers/gpu/drm/bridge/tc358767.c b/drivers/gpu/drm/bridge/tc358767.c +index f3afdab55c113..47189587643a1 100644 +--- a/drivers/gpu/drm/bridge/tc358767.c ++++ b/drivers/gpu/drm/bridge/tc358767.c +@@ -1714,6 +1714,13 @@ static const struct drm_edid *tc_edid_read(struct drm_bridge *bridge, + struct drm_connector *connector) + { + struct tc_data *tc = bridge_to_tc(bridge); ++ int ret; ++ ++ ret = tc_get_display_props(tc); ++ if (ret < 0) { ++ dev_err(tc->dev, "failed to read display props: %d\n", ret); ++ return 0; ++ } + + return drm_edid_read_ddc(connector, &tc->aux.ddc); + } +-- +2.43.0 + diff --git a/queue-6.12/drm-etnaviv-hold-gpu-lock-across-perfmon-sampling.patch b/queue-6.12/drm-etnaviv-hold-gpu-lock-across-perfmon-sampling.patch new file mode 100644 index 00000000000..3edf6077c2c --- /dev/null +++ b/queue-6.12/drm-etnaviv-hold-gpu-lock-across-perfmon-sampling.patch @@ -0,0 +1,78 @@ +From aaf57cdf67030a5a8f875b50d521c8cc330c979e Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Fri, 5 Jul 2024 22:00:09 +0200 +Subject: drm/etnaviv: hold GPU lock across perfmon sampling + +From: Lucas Stach <l.stach@pengutronix.de> + +[ Upstream commit 37dc4737447a7667f8e9ec790dac251da057eb27 ] + +The perfmon sampling mutates shared GPU state (e.g. VIVS_HI_CLOCK_CONTROL +to select the pipe for the perf counter reads). To avoid clashing with +other functions mutating the same state (e.g. etnaviv_gpu_update_clock) +the perfmon sampling needs to hold the GPU lock. + +Fixes: 68dc0b295dcb ("drm/etnaviv: use 'sync points' for performance monitor requests") +Reviewed-by: Christian Gmeiner <cgmeiner@igalia.com> +Signed-off-by: Lucas Stach <l.stach@pengutronix.de> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/gpu/drm/etnaviv/etnaviv_gpu.c | 20 ++++++++++++++------ + 1 file changed, 14 insertions(+), 6 deletions(-) + +diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gpu.c b/drivers/gpu/drm/etnaviv/etnaviv_gpu.c +index 5e753dd42f721..df0bc828a2348 100644 +--- a/drivers/gpu/drm/etnaviv/etnaviv_gpu.c ++++ b/drivers/gpu/drm/etnaviv/etnaviv_gpu.c +@@ -1322,6 +1322,8 @@ static void sync_point_perfmon_sample_pre(struct etnaviv_gpu *gpu, + { + u32 val; + ++ mutex_lock(&gpu->lock); ++ + /* disable clock gating */ + val = gpu_read_power(gpu, VIVS_PM_POWER_CONTROLS); + val &= ~VIVS_PM_POWER_CONTROLS_ENABLE_MODULE_CLOCK_GATING; +@@ -1333,6 +1335,8 @@ static void sync_point_perfmon_sample_pre(struct etnaviv_gpu *gpu, + gpu_write(gpu, VIVS_HI_CLOCK_CONTROL, val); + + sync_point_perfmon_sample(gpu, event, ETNA_PM_PROCESS_PRE); ++ ++ mutex_unlock(&gpu->lock); + } + + static void sync_point_perfmon_sample_post(struct etnaviv_gpu *gpu, +@@ -1342,13 +1346,9 @@ static void sync_point_perfmon_sample_post(struct etnaviv_gpu *gpu, + unsigned int i; + u32 val; + +- sync_point_perfmon_sample(gpu, event, ETNA_PM_PROCESS_POST); +- +- for (i = 0; i < submit->nr_pmrs; i++) { +- const struct etnaviv_perfmon_request *pmr = submit->pmrs + i; ++ mutex_lock(&gpu->lock); + +- *pmr->bo_vma = pmr->sequence; +- } ++ sync_point_perfmon_sample(gpu, event, ETNA_PM_PROCESS_POST); + + /* disable debug register */ + val = gpu_read(gpu, VIVS_HI_CLOCK_CONTROL); +@@ -1359,6 +1359,14 @@ static void sync_point_perfmon_sample_post(struct etnaviv_gpu *gpu, + val = gpu_read_power(gpu, VIVS_PM_POWER_CONTROLS); + val |= VIVS_PM_POWER_CONTROLS_ENABLE_MODULE_CLOCK_GATING; + gpu_write_power(gpu, VIVS_PM_POWER_CONTROLS, val); ++ ++ mutex_unlock(&gpu->lock); ++ ++ for (i = 0; i < submit->nr_pmrs; i++) { ++ const struct etnaviv_perfmon_request *pmr = submit->pmrs + i; ++ ++ *pmr->bo_vma = pmr->sequence; ++ } + } + + +-- +2.43.0 + diff --git a/queue-6.12/drm-etnaviv-request-pages-from-dma32-zone-on-address.patch b/queue-6.12/drm-etnaviv-request-pages-from-dma32-zone-on-address.patch new file mode 100644 index 00000000000..aa3f637d060 --- /dev/null +++ b/queue-6.12/drm-etnaviv-request-pages-from-dma32-zone-on-address.patch @@ -0,0 +1,68 @@ +From 8973a55f999180b486f8d18c3785e61b0aada167 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Wed, 2 Oct 2024 07:34:30 +0800 +Subject: drm/etnaviv: Request pages from DMA32 zone on addressing_limited + +From: Xiaolei Wang <xiaolei.wang@windriver.com> + +[ Upstream commit 13c96ac9a3f0f1c7ba1ff0656ea508e7fa065e7e ] + +Remove __GFP_HIGHMEM when requesting a page from DMA32 zone, +and since all vivante GPUs in the system will share the same +DMA constraints, move the check of whether to get a page from +DMA32 to etnaviv_bind(). + +Fixes: b72af445cd38 ("drm/etnaviv: request pages from DMA32 zone when needed") +Suggested-by: Sui Jingfeng <sui.jingfeng@linux.dev> +Signed-off-by: Xiaolei Wang <xiaolei.wang@windriver.com> +Reviewed-by: Christian Gmeiner <cgmeiner@igalia.com> +Signed-off-by: Lucas Stach <l.stach@pengutronix.de> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/gpu/drm/etnaviv/etnaviv_drv.c | 10 ++++++++++ + drivers/gpu/drm/etnaviv/etnaviv_gpu.c | 8 -------- + 2 files changed, 10 insertions(+), 8 deletions(-) + +diff --git a/drivers/gpu/drm/etnaviv/etnaviv_drv.c b/drivers/gpu/drm/etnaviv/etnaviv_drv.c +index 6500f3999c5fa..19ec67a5a918e 100644 +--- a/drivers/gpu/drm/etnaviv/etnaviv_drv.c ++++ b/drivers/gpu/drm/etnaviv/etnaviv_drv.c +@@ -538,6 +538,16 @@ static int etnaviv_bind(struct device *dev) + priv->num_gpus = 0; + priv->shm_gfp_mask = GFP_HIGHUSER | __GFP_RETRY_MAYFAIL | __GFP_NOWARN; + ++ /* ++ * If the GPU is part of a system with DMA addressing limitations, ++ * request pages for our SHM backend buffers from the DMA32 zone to ++ * hopefully avoid performance killing SWIOTLB bounce buffering. ++ */ ++ if (dma_addressing_limited(dev)) { ++ priv->shm_gfp_mask |= GFP_DMA32; ++ priv->shm_gfp_mask &= ~__GFP_HIGHMEM; ++ } ++ + priv->cmdbuf_suballoc = etnaviv_cmdbuf_suballoc_new(drm->dev); + if (IS_ERR(priv->cmdbuf_suballoc)) { + dev_err(drm->dev, "Failed to create cmdbuf suballocator\n"); +diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gpu.c b/drivers/gpu/drm/etnaviv/etnaviv_gpu.c +index 7c7f97793ddd0..5e753dd42f721 100644 +--- a/drivers/gpu/drm/etnaviv/etnaviv_gpu.c ++++ b/drivers/gpu/drm/etnaviv/etnaviv_gpu.c +@@ -839,14 +839,6 @@ int etnaviv_gpu_init(struct etnaviv_gpu *gpu) + if (ret) + goto fail; + +- /* +- * If the GPU is part of a system with DMA addressing limitations, +- * request pages for our SHM backend buffers from the DMA32 zone to +- * hopefully avoid performance killing SWIOTLB bounce buffering. +- */ +- if (dma_addressing_limited(gpu->dev)) +- priv->shm_gfp_mask |= GFP_DMA32; +- + /* Create buffer: */ + ret = etnaviv_cmdbuf_init(priv->cmdbuf_suballoc, &gpu->buffer, + PAGE_SIZE); +-- +2.43.0 + diff --git a/queue-6.12/drm-fsl-dcu-enable-pixclk-on-ls1021a.patch b/queue-6.12/drm-fsl-dcu-enable-pixclk-on-ls1021a.patch new file mode 100644 index 00000000000..08bed18fa96 --- /dev/null +++ b/queue-6.12/drm-fsl-dcu-enable-pixclk-on-ls1021a.patch @@ -0,0 +1,88 @@ +From 1f0fa21c14bd33a32aba58e3acf60c7e0d3d229a Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Thu, 26 Sep 2024 07:55:51 +0200 +Subject: drm: fsl-dcu: enable PIXCLK on LS1021A + +From: Matthias Schiffer <matthias.schiffer@tq-group.com> + +[ Upstream commit ffcde9e44d3e18fde3d18bfff8d9318935413bfd ] + +The PIXCLK needs to be enabled in SCFG before accessing certain DCU +registers, or the access will hang. For simplicity, the PIXCLK is enabled +unconditionally, resulting in increased power consumption. + +Signed-off-by: Matthias Schiffer <matthias.schiffer@tq-group.com> +Signed-off-by: Alexander Stein <alexander.stein@ew.tq-group.com> +Fixes: 109eee2f2a18 ("drm/layerscape: Add Freescale DCU DRM driver") +Acked-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org> +Link: https://patchwork.freedesktop.org/patch/msgid/20240926055552.1632448-2-alexander.stein@ew.tq-group.com +Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/gpu/drm/fsl-dcu/Kconfig | 1 + + drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c | 15 +++++++++++++++ + drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.h | 3 +++ + 3 files changed, 19 insertions(+) + +diff --git a/drivers/gpu/drm/fsl-dcu/Kconfig b/drivers/gpu/drm/fsl-dcu/Kconfig +index 5ca71ef873259..c9ee98693b48a 100644 +--- a/drivers/gpu/drm/fsl-dcu/Kconfig ++++ b/drivers/gpu/drm/fsl-dcu/Kconfig +@@ -8,6 +8,7 @@ config DRM_FSL_DCU + select DRM_PANEL + select REGMAP_MMIO + select VIDEOMODE_HELPERS ++ select MFD_SYSCON if SOC_LS1021A + help + Choose this option if you have an Freescale DCU chipset. + If M is selected the module will be called fsl-dcu-drm. +diff --git a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c +index ab6c0c6cd0e2e..c4c3d41ee5309 100644 +--- a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c ++++ b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c +@@ -100,6 +100,7 @@ static void fsl_dcu_irq_uninstall(struct drm_device *dev) + static int fsl_dcu_load(struct drm_device *dev, unsigned long flags) + { + struct fsl_dcu_drm_device *fsl_dev = dev->dev_private; ++ struct regmap *scfg; + int ret; + + ret = fsl_dcu_drm_modeset_init(fsl_dev); +@@ -108,6 +109,20 @@ static int fsl_dcu_load(struct drm_device *dev, unsigned long flags) + return ret; + } + ++ scfg = syscon_regmap_lookup_by_compatible("fsl,ls1021a-scfg"); ++ if (PTR_ERR(scfg) != -ENODEV) { ++ /* ++ * For simplicity, enable the PIXCLK unconditionally, ++ * resulting in increased power consumption. Disabling ++ * the clock in PM or on unload could be implemented as ++ * a future improvement. ++ */ ++ ret = regmap_update_bits(scfg, SCFG_PIXCLKCR, SCFG_PIXCLKCR_PXCEN, ++ SCFG_PIXCLKCR_PXCEN); ++ if (ret < 0) ++ return dev_err_probe(dev->dev, ret, "failed to enable pixclk\n"); ++ } ++ + ret = drm_vblank_init(dev, dev->mode_config.num_crtc); + if (ret < 0) { + dev_err(dev->dev, "failed to initialize vblank\n"); +diff --git a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.h b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.h +index e2049a0e8a92a..566396013c04a 100644 +--- a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.h ++++ b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.h +@@ -160,6 +160,9 @@ + #define FSL_DCU_ARGB4444 12 + #define FSL_DCU_YUV422 14 + ++#define SCFG_PIXCLKCR 0x28 ++#define SCFG_PIXCLKCR_PXCEN BIT(31) ++ + #define VF610_LAYER_REG_NUM 9 + #define LS1021A_LAYER_REG_NUM 10 + +-- +2.43.0 + diff --git a/queue-6.12/drm-imagination-convert-to-use-time_before-macro.patch b/queue-6.12/drm-imagination-convert-to-use-time_before-macro.patch new file mode 100644 index 00000000000..46807bb6fcd --- /dev/null +++ b/queue-6.12/drm-imagination-convert-to-use-time_before-macro.patch @@ -0,0 +1,38 @@ +From 41c6d3cab2c1fb12c5913bb8f10dbda1e4bbde62 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Fri, 23 Aug 2024 17:39:24 +0800 +Subject: drm/imagination: Convert to use time_before macro + +From: Chen Yufan <chenyufan@vivo.com> + +[ Upstream commit 7a5115ba1d691bd14db91d2fcc3ce0b056574ce9 ] + +Use time_*() macros instead of using jiffies directly to handle overflow +issues. + +Fixes: cc1aeedb98ad ("drm/imagination: Implement firmware infrastructure and META FW support") +Signed-off-by: Chen Yufan <chenyufan@vivo.com> +Reviewed-by: Matt Coster <matt.coster@imgtec.com> +Link: https://patchwork.freedesktop.org/patch/msgid/20240823093925.9599-1-chenyufan@vivo.com +Signed-off-by: Matt Coster <matt.coster@imgtec.com> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/gpu/drm/imagination/pvr_ccb.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/imagination/pvr_ccb.c b/drivers/gpu/drm/imagination/pvr_ccb.c +index 4deeac7ed40a4..2bbdc05a3b977 100644 +--- a/drivers/gpu/drm/imagination/pvr_ccb.c ++++ b/drivers/gpu/drm/imagination/pvr_ccb.c +@@ -321,7 +321,7 @@ static int pvr_kccb_reserve_slot_sync(struct pvr_device *pvr_dev) + bool reserved = false; + u32 retries = 0; + +- while ((jiffies - start_timestamp) < (u32)RESERVE_SLOT_TIMEOUT || ++ while (time_before(jiffies, start_timestamp + RESERVE_SLOT_TIMEOUT) || + retries < RESERVE_SLOT_MIN_RETRIES) { + reserved = pvr_kccb_try_reserve_slot(pvr_dev); + if (reserved) +-- +2.43.0 + diff --git a/queue-6.12/drm-imagination-use-pvr_vm_context_get.patch b/queue-6.12/drm-imagination-use-pvr_vm_context_get.patch new file mode 100644 index 00000000000..004d7ed944a --- /dev/null +++ b/queue-6.12/drm-imagination-use-pvr_vm_context_get.patch @@ -0,0 +1,40 @@ +From 5e7d48268bb0b6b7716e4726ec32bfb1e1ebfb0f Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Fri, 30 Aug 2024 15:06:01 +0000 +Subject: drm/imagination: Use pvr_vm_context_get() + +From: Matt Coster <Matt.Coster@imgtec.com> + +[ Upstream commit eb4accc5234525e2cb2b720187ccaf6db99b705f ] + +I missed this open-coded kref_get() while trying to debug a refcount +bug, so let's use the helper function here to avoid that waste of time +again in the future. + +Fixes: ff5f643de0bf ("drm/imagination: Add GEM and VM related code") +Reviewed-by: Frank Binns <frank.binns@imgtec.com> +Link: https://patchwork.freedesktop.org/patch/msgid/8616641d-6005-4b25-bc0a-0b53985a0e08@imgtec.com +Signed-off-by: Matt Coster <matt.coster@imgtec.com> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/gpu/drm/imagination/pvr_vm.c | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +diff --git a/drivers/gpu/drm/imagination/pvr_vm.c b/drivers/gpu/drm/imagination/pvr_vm.c +index 7bd6ba4c6e8ab..363f885a70982 100644 +--- a/drivers/gpu/drm/imagination/pvr_vm.c ++++ b/drivers/gpu/drm/imagination/pvr_vm.c +@@ -654,9 +654,7 @@ pvr_vm_context_lookup(struct pvr_file *pvr_file, u32 handle) + + xa_lock(&pvr_file->vm_ctx_handles); + vm_ctx = xa_load(&pvr_file->vm_ctx_handles, handle); +- if (vm_ctx) +- kref_get(&vm_ctx->ref_count); +- ++ pvr_vm_context_get(vm_ctx); + xa_unlock(&pvr_file->vm_ctx_handles); + + return vm_ctx; +-- +2.43.0 + diff --git a/queue-6.12/drm-imx-add-missing-drm_bridge_connector-dependency.patch b/queue-6.12/drm-imx-add-missing-drm_bridge_connector-dependency.patch new file mode 100644 index 00000000000..b413a022199 --- /dev/null +++ b/queue-6.12/drm-imx-add-missing-drm_bridge_connector-dependency.patch @@ -0,0 +1,46 @@ +From 6e6dc43aa7317c932ac4cf44e9cd58fa8375a6db Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Fri, 6 Sep 2024 08:38:56 +0200 +Subject: drm/imx: Add missing DRM_BRIDGE_CONNECTOR dependency + +From: Alexander Stein <alexander.stein@ew.tq-group.com> + +[ Upstream commit f673055a46784ccea04465b9213e999f7bc5187e ] + +When drm/bridge-connector was moved to DRM_DISPLAY_HELPER not all +users were updated. Add missing Kconfig selections. + +Fixes: 9da7ec9b19d8 ("drm/bridge-connector: move to DRM_DISPLAY_HELPER module") +Signed-off-by: Alexander Stein <alexander.stein@ew.tq-group.com> +Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org> +Acked-by: Philipp Zabel <p.zabel@pengutronix.de> +Link: https://patchwork.freedesktop.org/patch/msgid/20240906063857.2223442-1-alexander.stein@ew.tq-group.com +Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/gpu/drm/imx/ipuv3/Kconfig | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/gpu/drm/imx/ipuv3/Kconfig b/drivers/gpu/drm/imx/ipuv3/Kconfig +index f083d313d1d3a..7a427551f4341 100644 +--- a/drivers/gpu/drm/imx/ipuv3/Kconfig ++++ b/drivers/gpu/drm/imx/ipuv3/Kconfig +@@ -13,6 +13,7 @@ config DRM_IMX_PARALLEL_DISPLAY + tristate "Support for parallel displays" + depends on DRM_IMX + select DRM_BRIDGE ++ select DRM_BRIDGE_CONNECTOR + select DRM_PANEL_BRIDGE + select VIDEOMODE_HELPERS + +@@ -31,6 +32,7 @@ config DRM_IMX_LDB + depends on COMMON_CLK + select MFD_SYSCON + select DRM_BRIDGE ++ select DRM_BRIDGE_CONNECTOR + select DRM_PANEL_BRIDGE + help + Choose this to enable the internal LVDS Display Bridge (LDB) +-- +2.43.0 + diff --git a/queue-6.12/drm-imx-dcss-use-irqf_no_autoen-flag-in-request_irq.patch b/queue-6.12/drm-imx-dcss-use-irqf_no_autoen-flag-in-request_irq.patch new file mode 100644 index 00000000000..65d09f0b688 --- /dev/null +++ b/queue-6.12/drm-imx-dcss-use-irqf_no_autoen-flag-in-request_irq.patch @@ -0,0 +1,49 @@ +From 7d577c10b72a63a6460017be7a5af59ad3a04539 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Thu, 12 Sep 2024 16:30:16 +0800 +Subject: drm/imx/dcss: Use IRQF_NO_AUTOEN flag in request_irq() + +From: Jinjie Ruan <ruanjinjie@huawei.com> + +[ Upstream commit 1af01e14db7e0b45ae502d822776a58c86688763 ] + +disable_irq() after request_irq() still has a time gap in which +interrupts can come. request_irq() with IRQF_NO_AUTOEN flag will +disable IRQ auto-enable when request IRQ. + +Fixes: 9021c317b770 ("drm/imx: Add initial support for DCSS on iMX8MQ") +Signed-off-by: Jinjie Ruan <ruanjinjie@huawei.com> +Reviewed-by: Laurentiu Palcu <laurentiu.palcu@oss.nxp.com> +Link: https://patchwork.freedesktop.org/patch/msgid/20240912083020.3720233-2-ruanjinjie@huawei.com +[DB: fixed the subject] +Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/gpu/drm/imx/dcss/dcss-crtc.c | 6 ++---- + 1 file changed, 2 insertions(+), 4 deletions(-) + +diff --git a/drivers/gpu/drm/imx/dcss/dcss-crtc.c b/drivers/gpu/drm/imx/dcss/dcss-crtc.c +index 31267c00782fc..af91e45b5d13b 100644 +--- a/drivers/gpu/drm/imx/dcss/dcss-crtc.c ++++ b/drivers/gpu/drm/imx/dcss/dcss-crtc.c +@@ -206,15 +206,13 @@ int dcss_crtc_init(struct dcss_crtc *crtc, struct drm_device *drm) + if (crtc->irq < 0) + return crtc->irq; + +- ret = request_irq(crtc->irq, dcss_crtc_irq_handler, +- 0, "dcss_drm", crtc); ++ ret = request_irq(crtc->irq, dcss_crtc_irq_handler, IRQF_NO_AUTOEN, ++ "dcss_drm", crtc); + if (ret) { + dev_err(dcss->dev, "irq request failed with %d.\n", ret); + return ret; + } + +- disable_irq(crtc->irq); +- + return 0; + } + +-- +2.43.0 + diff --git a/queue-6.12/drm-imx-ipuv3-use-irqf_no_autoen-flag-in-request_irq.patch b/queue-6.12/drm-imx-ipuv3-use-irqf_no_autoen-flag-in-request_irq.patch new file mode 100644 index 00000000000..b12ef9f2e46 --- /dev/null +++ b/queue-6.12/drm-imx-ipuv3-use-irqf_no_autoen-flag-in-request_irq.patch @@ -0,0 +1,48 @@ +From e117e0b1c1407ae7193bfcde47004e81b3b1bb80 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Thu, 12 Sep 2024 16:30:18 +0800 +Subject: drm/imx/ipuv3: Use IRQF_NO_AUTOEN flag in request_irq() + +From: Jinjie Ruan <ruanjinjie@huawei.com> + +[ Upstream commit 40004709a3d3b07041a473a163ca911ef04ab8bd ] + +disable_irq() after request_irq() still has a time gap in which +interrupts can come. request_irq() with IRQF_NO_AUTOEN flag will +disable IRQ auto-enable when request IRQ. + +Fixes: 47b1be5c0f4e ("staging: imx/drm: request irq only after adding the crtc") +Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org> +Signed-off-by: Jinjie Ruan <ruanjinjie@huawei.com> +Reviewed-by: Philipp Zabel <p.zabel@pengutronix.de> +Link: https://patchwork.freedesktop.org/patch/msgid/20240912083020.3720233-4-ruanjinjie@huawei.com +Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/gpu/drm/imx/ipuv3/ipuv3-crtc.c | 6 ++---- + 1 file changed, 2 insertions(+), 4 deletions(-) + +diff --git a/drivers/gpu/drm/imx/ipuv3/ipuv3-crtc.c b/drivers/gpu/drm/imx/ipuv3/ipuv3-crtc.c +index ef29c9a61a461..99db53e167bd0 100644 +--- a/drivers/gpu/drm/imx/ipuv3/ipuv3-crtc.c ++++ b/drivers/gpu/drm/imx/ipuv3/ipuv3-crtc.c +@@ -410,14 +410,12 @@ static int ipu_drm_bind(struct device *dev, struct device *master, void *data) + } + + ipu_crtc->irq = ipu_plane_irq(ipu_crtc->plane[0]); +- ret = devm_request_irq(ipu_crtc->dev, ipu_crtc->irq, ipu_irq_handler, 0, +- "imx_drm", ipu_crtc); ++ ret = devm_request_irq(ipu_crtc->dev, ipu_crtc->irq, ipu_irq_handler, ++ IRQF_NO_AUTOEN, "imx_drm", ipu_crtc); + if (ret < 0) { + dev_err(ipu_crtc->dev, "irq request failed with %d.\n", ret); + return ret; + } +- /* Only enable IRQ when we actually need it to trigger work. */ +- disable_irq(ipu_crtc->irq); + + return 0; + } +-- +2.43.0 + diff --git a/queue-6.12/drm-imx-ldb-drop-custom-ddc-bus-support.patch b/queue-6.12/drm-imx-ldb-drop-custom-ddc-bus-support.patch new file mode 100644 index 00000000000..f028b65b78a --- /dev/null +++ b/queue-6.12/drm-imx-ldb-drop-custom-ddc-bus-support.patch @@ -0,0 +1,156 @@ +From f8525b6c29db9357ffe2d73533cd0cc66b9deefc Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Sun, 2 Jun 2024 15:04:46 +0300 +Subject: drm/imx: ldb: drop custom DDC bus support + +From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org> + +[ Upstream commit b2f3418b516e3485a14f10bfc09f20211dedc156 ] + +None of the boards ever supported by the upstream kernel used the custom +DDC bus support with the LDB connector. If a need arises to do so, one +should use panel-simple and its DDC bus code. Drop ddc-i2c-bus support +from the imx-ldb driver. + +Reviewed-by: Philipp Zabel <p.zabel@pengutronix.de> +Tested-by: Chris Healy <cphealy@gmail.com> +Tested-by: Philipp Zabel <p.zabel@pengutronix.de> # on imx6q-nitrogen6x +Link: https://patchwork.freedesktop.org/patch/msgid/20240602-drm-imx-cleanup-v3-6-e549e2a43100@linaro.org +Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org> +Stable-dep-of: f673055a4678 ("drm/imx: Add missing DRM_BRIDGE_CONNECTOR dependency") +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/gpu/drm/imx/ipuv3/imx-ldb.c | 73 ++++------------------------- + 1 file changed, 10 insertions(+), 63 deletions(-) + +diff --git a/drivers/gpu/drm/imx/ipuv3/imx-ldb.c b/drivers/gpu/drm/imx/ipuv3/imx-ldb.c +index 1924d8921c620..3f669604377e7 100644 +--- a/drivers/gpu/drm/imx/ipuv3/imx-ldb.c ++++ b/drivers/gpu/drm/imx/ipuv3/imx-ldb.c +@@ -25,7 +25,6 @@ + #include <drm/drm_atomic.h> + #include <drm/drm_atomic_helper.h> + #include <drm/drm_bridge.h> +-#include <drm/drm_edid.h> + #include <drm/drm_managed.h> + #include <drm/drm_of.h> + #include <drm/drm_panel.h> +@@ -70,7 +69,6 @@ struct imx_ldb_channel { + struct drm_bridge *bridge; + + struct device_node *child; +- struct i2c_adapter *ddc; + int chno; + struct drm_display_mode mode; + int mode_valid; +@@ -141,18 +139,6 @@ static int imx_ldb_connector_get_modes(struct drm_connector *connector) + if (num_modes > 0) + return num_modes; + +- if (imx_ldb_ch->ddc) { +- const struct drm_edid *edid = drm_edid_read_ddc(connector, +- imx_ldb_ch->ddc); +- +- if (edid) { +- drm_edid_connector_update(connector, edid); +- drm_edid_free(edid); +- +- return drm_edid_connector_add_modes(connector); +- } +- } +- + if (imx_ldb_ch->mode_valid) { + struct drm_display_mode *mode; + +@@ -481,10 +467,9 @@ static int imx_ldb_register(struct drm_device *drm, + */ + drm_connector_helper_add(connector, + &imx_ldb_connector_helper_funcs); +- drm_connector_init_with_ddc(drm, connector, +- &imx_ldb_connector_funcs, +- DRM_MODE_CONNECTOR_LVDS, +- imx_ldb_ch->ddc); ++ drm_connector_init(drm, connector, ++ &imx_ldb_connector_funcs, ++ DRM_MODE_CONNECTOR_LVDS); + drm_connector_attach_encoder(connector, encoder); + } + +@@ -551,39 +536,6 @@ static const struct of_device_id imx_ldb_dt_ids[] = { + }; + MODULE_DEVICE_TABLE(of, imx_ldb_dt_ids); + +-static int imx_ldb_panel_ddc(struct device *dev, +- struct imx_ldb_channel *channel, struct device_node *child) +-{ +- struct device_node *ddc_node; +- int ret; +- +- ddc_node = of_parse_phandle(child, "ddc-i2c-bus", 0); +- if (ddc_node) { +- channel->ddc = of_find_i2c_adapter_by_node(ddc_node); +- of_node_put(ddc_node); +- if (!channel->ddc) { +- dev_warn(dev, "failed to get ddc i2c adapter\n"); +- return -EPROBE_DEFER; +- } +- } +- +- if (!channel->ddc) { +- /* if no DDC available, fallback to hardcoded EDID */ +- dev_dbg(dev, "no ddc available\n"); +- +- if (!channel->panel) { +- /* fallback to display-timings node */ +- ret = of_get_drm_display_mode(child, +- &channel->mode, +- &channel->bus_flags, +- OF_USE_NATIVE_MODE); +- if (!ret) +- channel->mode_valid = 1; +- } +- } +- return 0; +-} +- + static int imx_ldb_bind(struct device *dev, struct device *master, void *data) + { + struct drm_device *drm = data; +@@ -694,11 +646,15 @@ static int imx_ldb_probe(struct platform_device *pdev) + if (ret && ret != -ENODEV) + goto free_child; + +- /* panel ddc only if there is no bridge */ +- if (!channel->bridge) { +- ret = imx_ldb_panel_ddc(dev, channel, child); ++ if (!channel->bridge && !channel->panel) { ++ ret = of_get_drm_display_mode(child, ++ &channel->mode, ++ &channel->bus_flags, ++ OF_USE_NATIVE_MODE); + if (ret) + goto free_child; ++ ++ channel->mode_valid = 1; + } + + bus_format = of_get_bus_format(dev, child); +@@ -732,15 +688,6 @@ static int imx_ldb_probe(struct platform_device *pdev) + + static void imx_ldb_remove(struct platform_device *pdev) + { +- struct imx_ldb *imx_ldb = platform_get_drvdata(pdev); +- int i; +- +- for (i = 0; i < 2; i++) { +- struct imx_ldb_channel *channel = &imx_ldb->channel[i]; +- +- i2c_put_adapter(channel->ddc); +- } +- + component_del(&pdev->dev, &imx_ldb_ops); + } + +-- +2.43.0 + diff --git a/queue-6.12/drm-imx-ldb-drop-custom-edid-support.patch b/queue-6.12/drm-imx-ldb-drop-custom-edid-support.patch new file mode 100644 index 00000000000..fe53fc2fb44 --- /dev/null +++ b/queue-6.12/drm-imx-ldb-drop-custom-edid-support.patch @@ -0,0 +1,92 @@ +From 88b0e939aca406bfd89f9af70eb1b1d87b6914d6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Sun, 2 Jun 2024 15:04:45 +0300 +Subject: drm/imx: ldb: drop custom EDID support + +From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org> + +[ Upstream commit aed7b500315004a917463d571fa9cd12e0e94370 ] + +Bindings for the imx-ldb never allowed specifying the EDID in DT. None +of the existing DT files use it. Drop it now in favour of using debugfs +overrides or the drm.edid_firmware support. + +Reviewed-by: Philipp Zabel <p.zabel@pengutronix.de> +Tested-by: Chris Healy <cphealy@gmail.com> +Tested-by: Philipp Zabel <p.zabel@pengutronix.de> # on imx6q-nitrogen6x +Link: https://patchwork.freedesktop.org/patch/msgid/20240602-drm-imx-cleanup-v3-5-e549e2a43100@linaro.org +Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org> +Stable-dep-of: f673055a4678 ("drm/imx: Add missing DRM_BRIDGE_CONNECTOR dependency") +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/gpu/drm/imx/ipuv3/imx-ldb.c | 29 +++++++++++------------------ + 1 file changed, 11 insertions(+), 18 deletions(-) + +diff --git a/drivers/gpu/drm/imx/ipuv3/imx-ldb.c b/drivers/gpu/drm/imx/ipuv3/imx-ldb.c +index 793dfb1a3ed00..1924d8921c620 100644 +--- a/drivers/gpu/drm/imx/ipuv3/imx-ldb.c ++++ b/drivers/gpu/drm/imx/ipuv3/imx-ldb.c +@@ -72,7 +72,6 @@ struct imx_ldb_channel { + struct device_node *child; + struct i2c_adapter *ddc; + int chno; +- const struct drm_edid *drm_edid; + struct drm_display_mode mode; + int mode_valid; + u32 bus_format; +@@ -142,14 +141,17 @@ static int imx_ldb_connector_get_modes(struct drm_connector *connector) + if (num_modes > 0) + return num_modes; + +- if (!imx_ldb_ch->drm_edid && imx_ldb_ch->ddc) { +- imx_ldb_ch->drm_edid = drm_edid_read_ddc(connector, +- imx_ldb_ch->ddc); +- drm_edid_connector_update(connector, imx_ldb_ch->drm_edid); +- } ++ if (imx_ldb_ch->ddc) { ++ const struct drm_edid *edid = drm_edid_read_ddc(connector, ++ imx_ldb_ch->ddc); + +- if (imx_ldb_ch->drm_edid) +- num_modes = drm_edid_connector_add_modes(connector); ++ if (edid) { ++ drm_edid_connector_update(connector, edid); ++ drm_edid_free(edid); ++ ++ return drm_edid_connector_add_modes(connector); ++ } ++ } + + if (imx_ldb_ch->mode_valid) { + struct drm_display_mode *mode; +@@ -566,18 +568,10 @@ static int imx_ldb_panel_ddc(struct device *dev, + } + + if (!channel->ddc) { +- const void *edidp; +- int edid_len; +- + /* if no DDC available, fallback to hardcoded EDID */ + dev_dbg(dev, "no ddc available\n"); + +- edidp = of_get_property(child, "edid", &edid_len); +- if (edidp) { +- channel->drm_edid = drm_edid_alloc(edidp, edid_len); +- if (!channel->drm_edid) +- return -ENOMEM; +- } else if (!channel->panel) { ++ if (!channel->panel) { + /* fallback to display-timings node */ + ret = of_get_drm_display_mode(child, + &channel->mode, +@@ -744,7 +738,6 @@ static void imx_ldb_remove(struct platform_device *pdev) + for (i = 0; i < 2; i++) { + struct imx_ldb_channel *channel = &imx_ldb->channel[i]; + +- drm_edid_free(channel->drm_edid); + i2c_put_adapter(channel->ddc); + } + +-- +2.43.0 + diff --git a/queue-6.12/drm-imx-ldb-switch-to-drm_panel_bridge.patch b/queue-6.12/drm-imx-ldb-switch-to-drm_panel_bridge.patch new file mode 100644 index 00000000000..de9f423ec11 --- /dev/null +++ b/queue-6.12/drm-imx-ldb-switch-to-drm_panel_bridge.patch @@ -0,0 +1,158 @@ +From 85ce007c2e40611b1823b5e8406c69f97b8d0f9e Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Sun, 2 Jun 2024 15:04:47 +0300 +Subject: drm/imx: ldb: switch to drm_panel_bridge + +From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org> + +[ Upstream commit 5c5843b20bbb1e4b4de2359573c20e416b41cb48 ] + +Defer panel handling to drm_panel_bridge, unifying codepaths for the +panel and bridge cases. The MFD_SYSCON symbol is moved to select to +prevent Kconfig symbol loops. + +Reviewed-by: Philipp Zabel <p.zabel@pengutronix.de> +Tested-by: Chris Healy <cphealy@gmail.com> +Tested-by: Philipp Zabel <p.zabel@pengutronix.de> # on imx6q-nitrogen6x +Link: https://patchwork.freedesktop.org/patch/msgid/20240602-drm-imx-cleanup-v3-7-e549e2a43100@linaro.org +Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org> +Stable-dep-of: f673055a4678 ("drm/imx: Add missing DRM_BRIDGE_CONNECTOR dependency") +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/gpu/drm/imx/ipuv3/Kconfig | 6 ++-- + drivers/gpu/drm/imx/ipuv3/imx-ldb.c | 44 +++++++++-------------------- + 2 files changed, 18 insertions(+), 32 deletions(-) + +diff --git a/drivers/gpu/drm/imx/ipuv3/Kconfig b/drivers/gpu/drm/imx/ipuv3/Kconfig +index bacf0655ebaf3..6abcf9c833d44 100644 +--- a/drivers/gpu/drm/imx/ipuv3/Kconfig ++++ b/drivers/gpu/drm/imx/ipuv3/Kconfig +@@ -26,9 +26,11 @@ config DRM_IMX_TVE + + config DRM_IMX_LDB + tristate "Support for LVDS displays" +- depends on DRM_IMX && MFD_SYSCON ++ depends on DRM_IMX + depends on COMMON_CLK +- select DRM_PANEL ++ select MFD_SYSCON ++ select DRM_BRIDGE ++ select DRM_PANEL_BRIDGE + help + Choose this to enable the internal LVDS Display Bridge (LDB) + found on i.MX53 and i.MX6 processors. +diff --git a/drivers/gpu/drm/imx/ipuv3/imx-ldb.c b/drivers/gpu/drm/imx/ipuv3/imx-ldb.c +index 3f669604377e7..bc7ad96971308 100644 +--- a/drivers/gpu/drm/imx/ipuv3/imx-ldb.c ++++ b/drivers/gpu/drm/imx/ipuv3/imx-ldb.c +@@ -27,7 +27,6 @@ + #include <drm/drm_bridge.h> + #include <drm/drm_managed.h> + #include <drm/drm_of.h> +-#include <drm/drm_panel.h> + #include <drm/drm_print.h> + #include <drm/drm_probe_helper.h> + #include <drm/drm_simple_kms_helper.h> +@@ -64,8 +63,6 @@ struct imx_ldb; + struct imx_ldb_channel { + struct imx_ldb *ldb; + +- /* Defines what is connected to the ldb, only one at a time */ +- struct drm_panel *panel; + struct drm_bridge *bridge; + + struct device_node *child; +@@ -135,10 +132,6 @@ static int imx_ldb_connector_get_modes(struct drm_connector *connector) + struct imx_ldb_channel *imx_ldb_ch = con_to_imx_ldb_ch(connector); + int num_modes; + +- num_modes = drm_panel_get_modes(imx_ldb_ch->panel, connector); +- if (num_modes > 0) +- return num_modes; +- + if (imx_ldb_ch->mode_valid) { + struct drm_display_mode *mode; + +@@ -193,8 +186,6 @@ static void imx_ldb_encoder_enable(struct drm_encoder *encoder) + return; + } + +- drm_panel_prepare(imx_ldb_ch->panel); +- + if (dual) { + clk_set_parent(ldb->clk_sel[mux], ldb->clk[0]); + clk_set_parent(ldb->clk_sel[mux], ldb->clk[1]); +@@ -233,8 +224,6 @@ static void imx_ldb_encoder_enable(struct drm_encoder *encoder) + } + + regmap_write(ldb->regmap, IOMUXC_GPR2, ldb->ldb_ctrl); +- +- drm_panel_enable(imx_ldb_ch->panel); + } + + static void +@@ -311,8 +300,6 @@ static void imx_ldb_encoder_disable(struct drm_encoder *encoder) + int dual = ldb->ldb_ctrl & LDB_SPLIT_MODE_EN; + int mux, ret; + +- drm_panel_disable(imx_ldb_ch->panel); +- + if (imx_ldb_ch == &ldb->channel[0] || dual) + ldb->ldb_ctrl &= ~LDB_CH0_MODE_EN_MASK; + if (imx_ldb_ch == &ldb->channel[1] || dual) +@@ -346,8 +333,6 @@ static void imx_ldb_encoder_disable(struct drm_encoder *encoder) + dev_err(ldb->dev, + "unable to set di%d parent clock to original parent\n", + mux); +- +- drm_panel_unprepare(imx_ldb_ch->panel); + } + + static int imx_ldb_encoder_atomic_check(struct drm_encoder *encoder, +@@ -640,13 +625,15 @@ static int imx_ldb_probe(struct platform_device *pdev) + * The output port is port@4 with an external 4-port mux or + * port@2 with the internal 2-port mux. + */ +- ret = drm_of_find_panel_or_bridge(child, +- imx_ldb->lvds_mux ? 4 : 2, 0, +- &channel->panel, &channel->bridge); +- if (ret && ret != -ENODEV) +- goto free_child; ++ channel->bridge = devm_drm_of_get_bridge(dev, child, ++ imx_ldb->lvds_mux ? 4 : 2, 0); ++ if (IS_ERR(channel->bridge)) { ++ ret = PTR_ERR(channel->bridge); ++ if (ret != -ENODEV) ++ goto free_child; ++ ++ channel->bridge = NULL; + +- if (!channel->bridge && !channel->panel) { + ret = of_get_drm_display_mode(child, + &channel->mode, + &channel->bus_flags, +@@ -658,15 +645,12 @@ static int imx_ldb_probe(struct platform_device *pdev) + } + + bus_format = of_get_bus_format(dev, child); +- if (bus_format == -EINVAL) { +- /* +- * If no bus format was specified in the device tree, +- * we can still get it from the connected panel later. +- */ +- if (channel->panel && channel->panel->funcs && +- channel->panel->funcs->get_modes) +- bus_format = 0; +- } ++ /* ++ * If no bus format was specified in the device tree, ++ * we can still get it from the connected panel later. ++ */ ++ if (bus_format == -EINVAL && channel->bridge) ++ bus_format = 0; + if (bus_format < 0) { + dev_err(dev, "could not determine data mapping: %d\n", + bus_format); +-- +2.43.0 + diff --git a/queue-6.12/drm-imx-parallel-display-drop-edid-override-support.patch b/queue-6.12/drm-imx-parallel-display-drop-edid-override-support.patch new file mode 100644 index 00000000000..ebf5df31f23 --- /dev/null +++ b/queue-6.12/drm-imx-parallel-display-drop-edid-override-support.patch @@ -0,0 +1,97 @@ +From 8446ec5be2445171bb392c4d51ad46e10b17013d Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Sun, 2 Jun 2024 15:04:44 +0300 +Subject: drm/imx: parallel-display: drop edid override support + +From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org> + +[ Upstream commit fe30fabf229f7542a10dd249079fdb83844a7dba ] + +None of the in-kernel DT files ever used edid override with the +fsl-imx-drm driver. In case the EDID needs to be specified manually, DRM +core allows one to either override it via the debugfs or to load it via +request_firmware by using DRM_LOAD_EDID_FIRMWARE. In all other cases +EDID and/or modes are to be provided as a part of the panel driver. + +Drop support for the edid property. + +Reviewed-by: Philipp Zabel <p.zabel@pengutronix.de> +Acked-by: Rob Herring <robh@kernel.org> +Tested-by: Chris Healy <cphealy@gmail.com> +Tested-by: Philipp Zabel <p.zabel@pengutronix.de> # on imx6q-nitrogen6x +Link: https://patchwork.freedesktop.org/patch/msgid/20240602-drm-imx-cleanup-v3-4-e549e2a43100@linaro.org +Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org> +Stable-dep-of: f673055a4678 ("drm/imx: Add missing DRM_BRIDGE_CONNECTOR dependency") +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/gpu/drm/imx/ipuv3/parallel-display.c | 17 ----------------- + 1 file changed, 17 deletions(-) + +diff --git a/drivers/gpu/drm/imx/ipuv3/parallel-display.c b/drivers/gpu/drm/imx/ipuv3/parallel-display.c +index 91d7808a2d8d3..4d17fb96e77c5 100644 +--- a/drivers/gpu/drm/imx/ipuv3/parallel-display.c ++++ b/drivers/gpu/drm/imx/ipuv3/parallel-display.c +@@ -16,7 +16,6 @@ + + #include <drm/drm_atomic_helper.h> + #include <drm/drm_bridge.h> +-#include <drm/drm_edid.h> + #include <drm/drm_managed.h> + #include <drm/drm_of.h> + #include <drm/drm_panel.h> +@@ -34,7 +33,6 @@ struct imx_parallel_display_encoder { + + struct imx_parallel_display { + struct device *dev; +- const struct drm_edid *drm_edid; + u32 bus_format; + u32 bus_flags; + struct drm_display_mode mode; +@@ -62,11 +60,6 @@ static int imx_pd_connector_get_modes(struct drm_connector *connector) + if (num_modes > 0) + return num_modes; + +- if (imxpd->drm_edid) { +- drm_edid_connector_update(connector, imxpd->drm_edid); +- num_modes = drm_edid_connector_add_modes(connector); +- } +- + if (np) { + struct drm_display_mode *mode = drm_mode_create(connector->dev); + int ret; +@@ -312,9 +305,7 @@ static int imx_pd_probe(struct platform_device *pdev) + { + struct device *dev = &pdev->dev; + struct device_node *np = dev->of_node; +- const u8 *edidp; + struct imx_parallel_display *imxpd; +- int edid_len; + int ret; + u32 bus_format = 0; + const char *fmt; +@@ -329,10 +320,6 @@ static int imx_pd_probe(struct platform_device *pdev) + if (ret && ret != -ENODEV) + return ret; + +- edidp = of_get_property(np, "edid", &edid_len); +- if (edidp) +- imxpd->drm_edid = drm_edid_alloc(edidp, edid_len); +- + ret = of_property_read_string(np, "interface-pix-fmt", &fmt); + if (!ret) { + if (!strcmp(fmt, "rgb24")) +@@ -355,11 +342,7 @@ static int imx_pd_probe(struct platform_device *pdev) + + static void imx_pd_remove(struct platform_device *pdev) + { +- struct imx_parallel_display *imxpd = platform_get_drvdata(pdev); +- + component_del(&pdev->dev, &imx_pd_ops); +- +- drm_edid_free(imxpd->drm_edid); + } + + static const struct of_device_id imx_pd_dt_ids[] = { +-- +2.43.0 + diff --git a/queue-6.12/drm-imx-parallel-display-switch-to-drm_panel_bridge.patch b/queue-6.12/drm-imx-parallel-display-switch-to-drm_panel_bridge.patch new file mode 100644 index 00000000000..d2074aa60c7 --- /dev/null +++ b/queue-6.12/drm-imx-parallel-display-switch-to-drm_panel_bridge.patch @@ -0,0 +1,124 @@ +From 5033af6707f6d993fcd65b3b24d84829edc7fb53 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Sun, 2 Jun 2024 15:04:48 +0300 +Subject: drm/imx: parallel-display: switch to drm_panel_bridge + +From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org> + +[ Upstream commit 5f6e56d3319d2fd20d4c81b4f0212f4d09d7c1f1 ] + +Defer panel handling to drm_panel_bridge, unifying codepaths for the +panel and bridge cases. + +Reviewed-by: Philipp Zabel <p.zabel@pengutronix.de> +Tested-by: Chris Healy <cphealy@gmail.com> +Tested-by: Philipp Zabel <p.zabel@pengutronix.de> # on imx6q-nitrogen6x +Link: https://patchwork.freedesktop.org/patch/msgid/20240602-drm-imx-cleanup-v3-8-e549e2a43100@linaro.org +Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org> +Stable-dep-of: f673055a4678 ("drm/imx: Add missing DRM_BRIDGE_CONNECTOR dependency") +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/gpu/drm/imx/ipuv3/Kconfig | 3 +- + drivers/gpu/drm/imx/ipuv3/parallel-display.c | 36 +++++--------------- + 2 files changed, 10 insertions(+), 29 deletions(-) + +diff --git a/drivers/gpu/drm/imx/ipuv3/Kconfig b/drivers/gpu/drm/imx/ipuv3/Kconfig +index 6abcf9c833d44..f083d313d1d3a 100644 +--- a/drivers/gpu/drm/imx/ipuv3/Kconfig ++++ b/drivers/gpu/drm/imx/ipuv3/Kconfig +@@ -11,8 +11,9 @@ config DRM_IMX + + config DRM_IMX_PARALLEL_DISPLAY + tristate "Support for parallel displays" +- select DRM_PANEL + depends on DRM_IMX ++ select DRM_BRIDGE ++ select DRM_PANEL_BRIDGE + select VIDEOMODE_HELPERS + + config DRM_IMX_TVE +diff --git a/drivers/gpu/drm/imx/ipuv3/parallel-display.c b/drivers/gpu/drm/imx/ipuv3/parallel-display.c +index 4d17fb96e77c5..9ac2a94fa62be 100644 +--- a/drivers/gpu/drm/imx/ipuv3/parallel-display.c ++++ b/drivers/gpu/drm/imx/ipuv3/parallel-display.c +@@ -18,7 +18,6 @@ + #include <drm/drm_bridge.h> + #include <drm/drm_managed.h> + #include <drm/drm_of.h> +-#include <drm/drm_panel.h> + #include <drm/drm_probe_helper.h> + #include <drm/drm_simple_kms_helper.h> + +@@ -36,7 +35,6 @@ struct imx_parallel_display { + u32 bus_format; + u32 bus_flags; + struct drm_display_mode mode; +- struct drm_panel *panel; + struct drm_bridge *next_bridge; + }; + +@@ -56,10 +54,6 @@ static int imx_pd_connector_get_modes(struct drm_connector *connector) + struct device_node *np = imxpd->dev->of_node; + int num_modes; + +- num_modes = drm_panel_get_modes(imxpd->panel, connector); +- if (num_modes > 0) +- return num_modes; +- + if (np) { + struct drm_display_mode *mode = drm_mode_create(connector->dev); + int ret; +@@ -84,22 +78,6 @@ static int imx_pd_connector_get_modes(struct drm_connector *connector) + return num_modes; + } + +-static void imx_pd_bridge_enable(struct drm_bridge *bridge) +-{ +- struct imx_parallel_display *imxpd = bridge_to_imxpd(bridge); +- +- drm_panel_prepare(imxpd->panel); +- drm_panel_enable(imxpd->panel); +-} +- +-static void imx_pd_bridge_disable(struct drm_bridge *bridge) +-{ +- struct imx_parallel_display *imxpd = bridge_to_imxpd(bridge); +- +- drm_panel_disable(imxpd->panel); +- drm_panel_unprepare(imxpd->panel); +-} +- + static const u32 imx_pd_bus_fmts[] = { + MEDIA_BUS_FMT_RGB888_1X24, + MEDIA_BUS_FMT_BGR888_1X24, +@@ -237,8 +215,6 @@ static const struct drm_connector_helper_funcs imx_pd_connector_helper_funcs = { + }; + + static const struct drm_bridge_funcs imx_pd_bridge_funcs = { +- .enable = imx_pd_bridge_enable, +- .disable = imx_pd_bridge_disable, + .atomic_reset = drm_atomic_helper_bridge_reset, + .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state, + .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state, +@@ -315,10 +291,14 @@ static int imx_pd_probe(struct platform_device *pdev) + return -ENOMEM; + + /* port@1 is the output port */ +- ret = drm_of_find_panel_or_bridge(np, 1, 0, &imxpd->panel, +- &imxpd->next_bridge); +- if (ret && ret != -ENODEV) +- return ret; ++ imxpd->next_bridge = devm_drm_of_get_bridge(dev, np, 1, 0); ++ if (IS_ERR(imxpd->next_bridge)) { ++ ret = PTR_ERR(imxpd->next_bridge); ++ if (ret != -ENODEV) ++ return ret; ++ ++ imxpd->next_bridge = NULL; ++ } + + ret = of_property_read_string(np, "interface-pix-fmt", &fmt); + if (!ret) { +-- +2.43.0 + diff --git a/queue-6.12/drm-mm-mark-drm_mm_interval_tree-functions-with-__ma.patch b/queue-6.12/drm-mm-mark-drm_mm_interval_tree-functions-with-__ma.patch new file mode 100644 index 00000000000..585d8402f2a --- /dev/null +++ b/queue-6.12/drm-mm-mark-drm_mm_interval_tree-functions-with-__ma.patch @@ -0,0 +1,52 @@ +From 06ce6ac09b8e29cf31aabfb3eb2e0189b5853b1f Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Thu, 29 Aug 2024 18:46:40 +0300 +Subject: drm/mm: Mark drm_mm_interval_tree*() functions with __maybe_unused + +From: Andy Shevchenko <andriy.shevchenko@linux.intel.com> + +[ Upstream commit 53bd7c1c0077db533472ae32799157758302ef48 ] + +The INTERVAL_TREE_DEFINE() uncoditionally provides a bunch of helper +functions which in some cases may be not used. This, in particular, +prevents kernel builds with clang, `make W=1` and CONFIG_WERROR=y: + +.../drm/drm_mm.c:152:1: error: unused function 'drm_mm_interval_tree_insert' [-Werror,-Wunused-function] + 152 | INTERVAL_TREE_DEFINE(struct drm_mm_node, rb, + | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + 153 | u64, __subtree_last, + | ~~~~~~~~~~~~~~~~~~~~ + 154 | START, LAST, static inline, drm_mm_interval_tree) + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Fix this by marking drm_mm_interval_tree*() functions with __maybe_unused. + +See also commit 6863f5643dd7 ("kbuild: allow Clang to find unused static +inline functions for W=1 build"). + +Fixes: 202b52b7fbf7 ("drm: Track drm_mm nodes with an interval tree") +Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com> +Reviewed-by: Jani Nikula <jani.nikula@intel.com> +Link: https://patchwork.freedesktop.org/patch/msgid/20240829154640.1120050-1-andriy.shevchenko@linux.intel.com +Signed-off-by: Jani Nikula <jani.nikula@intel.com> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/gpu/drm/drm_mm.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/drm_mm.c b/drivers/gpu/drm/drm_mm.c +index 5ace481c19011..1ed68d3cd80ba 100644 +--- a/drivers/gpu/drm/drm_mm.c ++++ b/drivers/gpu/drm/drm_mm.c +@@ -151,7 +151,7 @@ static void show_leaks(struct drm_mm *mm) { } + + INTERVAL_TREE_DEFINE(struct drm_mm_node, rb, + u64, __subtree_last, +- START, LAST, static inline, drm_mm_interval_tree) ++ START, LAST, static inline __maybe_unused, drm_mm_interval_tree) + + struct drm_mm_node * + __drm_mm_interval_first(const struct drm_mm *mm, u64 start, u64 last) +-- +2.43.0 + diff --git a/queue-6.12/drm-msm-adreno-use-irqf_no_autoen-flag-in-request_ir.patch b/queue-6.12/drm-msm-adreno-use-irqf_no_autoen-flag-in-request_ir.patch new file mode 100644 index 00000000000..adbdc2c069a --- /dev/null +++ b/queue-6.12/drm-msm-adreno-use-irqf_no_autoen-flag-in-request_ir.patch @@ -0,0 +1,47 @@ +From b377ade03839c2e3eafb4448c6816264076b0bc0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Thu, 12 Sep 2024 16:30:20 +0800 +Subject: drm/msm/adreno: Use IRQF_NO_AUTOEN flag in request_irq() + +From: Jinjie Ruan <ruanjinjie@huawei.com> + +[ Upstream commit 394679f322649d06fea3c646ba65f5a0887f52c3 ] + +disable_irq() after request_irq() still has a time gap in which +interrupts can come. request_irq() with IRQF_NO_AUTOEN flag will +disable IRQ auto-enable when request IRQ. + +Fixes: 4b565ca5a2cb ("drm/msm: Add A6XX device support") +Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org> +Signed-off-by: Jinjie Ruan <ruanjinjie@huawei.com> +Patchwork: https://patchwork.freedesktop.org/patch/614075/ +Signed-off-by: Rob Clark <robdclark@chromium.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/gpu/drm/msm/adreno/a6xx_gmu.c | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c +index 37927bdd6fbed..14db7376c712d 100644 +--- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c ++++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c +@@ -1522,15 +1522,13 @@ static int a6xx_gmu_get_irq(struct a6xx_gmu *gmu, struct platform_device *pdev, + + irq = platform_get_irq_byname(pdev, name); + +- ret = request_irq(irq, handler, IRQF_TRIGGER_HIGH, name, gmu); ++ ret = request_irq(irq, handler, IRQF_TRIGGER_HIGH | IRQF_NO_AUTOEN, name, gmu); + if (ret) { + DRM_DEV_ERROR(&pdev->dev, "Unable to get interrupt %s %d\n", + name, ret); + return ret; + } + +- disable_irq(irq); +- + return irq; + } + +-- +2.43.0 + diff --git a/queue-6.12/drm-msm-dpu-cast-crtc_clk-calculation-to-u64-in-_dpu.patch b/queue-6.12/drm-msm-dpu-cast-crtc_clk-calculation-to-u64-in-_dpu.patch new file mode 100644 index 00000000000..c9987ca629f --- /dev/null +++ b/queue-6.12/drm-msm-dpu-cast-crtc_clk-calculation-to-u64-in-_dpu.patch @@ -0,0 +1,46 @@ +From a6f117d5a23a8b7d11f7d33b4ab0e53339d76d02 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Tue, 29 Oct 2024 14:42:10 -0500 +Subject: drm/msm/dpu: cast crtc_clk calculation to u64 in + _dpu_core_perf_calc_clk() + +From: Zichen Xie <zichenxie0106@gmail.com> + +[ Upstream commit 20c7b42d9dbd048019bfe0af39229e3014007a98 ] + +There may be a potential integer overflow issue in +_dpu_core_perf_calc_clk(). crtc_clk is defined as u64, while +mode->vtotal, mode->hdisplay, and drm_mode_vrefresh(mode) are defined as +a smaller data type. The result of the calculation will be limited to +"int" in this case without correct casting. In screen with high +resolution and high refresh rate, integer overflow may happen. +So, we recommend adding an extra cast to prevent potential +integer overflow. + +Fixes: c33b7c0389e1 ("drm/msm/dpu: add support for clk and bw scaling for display") +Signed-off-by: Zichen Xie <zichenxie0106@gmail.com> +Reviewed-by: Abhinav Kumar <quic_abhinavk@quicinc.com> +Patchwork: https://patchwork.freedesktop.org/patch/622206/ +Link: https://lore.kernel.org/r/20241029194209.23684-1-zichenxie0106@gmail.com +Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c +index 68fae048a9a83..260accc151d4b 100644 +--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c ++++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c +@@ -80,7 +80,7 @@ static u64 _dpu_core_perf_calc_clk(const struct dpu_perf_cfg *perf_cfg, + + mode = &state->adjusted_mode; + +- crtc_clk = mode->vtotal * mode->hdisplay * drm_mode_vrefresh(mode); ++ crtc_clk = (u64)mode->vtotal * mode->hdisplay * drm_mode_vrefresh(mode); + + drm_atomic_crtc_for_each_plane(plane, crtc) { + pstate = to_dpu_plane_state(plane->state); +-- +2.43.0 + diff --git a/queue-6.12/drm-msm-dpu-drop-lm_3-lm_4-on-msm8998.patch b/queue-6.12/drm-msm-dpu-drop-lm_3-lm_4-on-msm8998.patch new file mode 100644 index 00000000000..48671b96e34 --- /dev/null +++ b/queue-6.12/drm-msm-dpu-drop-lm_3-lm_4-on-msm8998.patch @@ -0,0 +1,49 @@ +From 21d05d1d2a995a27e8412524d99f78e6635fd372 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Thu, 5 Sep 2024 06:26:15 +0300 +Subject: drm/msm/dpu: drop LM_3 / LM_4 on MSM8998 + +From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org> + +[ Upstream commit c59afe50773d5c972f6684f9bbd9a2ddb2fb92fa ] + +On the MSM8998 platform ther are no LM_3 and LM_4 blocks. Drop them from +the MSM8998 catalog. + +Fixes: 94391a14fc27 ("drm/msm/dpu1: Add MSM8998 to hw catalog") +Reported-by: Abhinav Kumar <quic_abhinavk@quicinc.com> +Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org> +Reviewed-by: Abhinav Kumar <quic_abhinavk@quicinc.com> +Patchwork: https://patchwork.freedesktop.org/patch/612585/ +Link: https://lore.kernel.org/r/20240905-dpu-fix-sdm845-catalog-v1-3-3363d03998bd@linaro.org +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + .../gpu/drm/msm/disp/dpu1/catalog/dpu_3_0_msm8998.h | 12 ------------ + 1 file changed, 12 deletions(-) + +diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_3_0_msm8998.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_3_0_msm8998.h +index 1d3e9666c7411..64c94e919a698 100644 +--- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_3_0_msm8998.h ++++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_3_0_msm8998.h +@@ -156,18 +156,6 @@ static const struct dpu_lm_cfg msm8998_lm[] = { + .sblk = &msm8998_lm_sblk, + .lm_pair = LM_5, + .pingpong = PINGPONG_2, +- }, { +- .name = "lm_3", .id = LM_3, +- .base = 0x47000, .len = 0x320, +- .features = MIXER_MSM8998_MASK, +- .sblk = &msm8998_lm_sblk, +- .pingpong = PINGPONG_NONE, +- }, { +- .name = "lm_4", .id = LM_4, +- .base = 0x48000, .len = 0x320, +- .features = MIXER_MSM8998_MASK, +- .sblk = &msm8998_lm_sblk, +- .pingpong = PINGPONG_NONE, + }, { + .name = "lm_5", .id = LM_5, + .base = 0x49000, .len = 0x320, +-- +2.43.0 + diff --git a/queue-6.12/drm-msm-dpu-drop-lm_3-lm_4-on-sdm845.patch b/queue-6.12/drm-msm-dpu-drop-lm_3-lm_4-on-sdm845.patch new file mode 100644 index 00000000000..0d30137ea9a --- /dev/null +++ b/queue-6.12/drm-msm-dpu-drop-lm_3-lm_4-on-sdm845.patch @@ -0,0 +1,48 @@ +From 294daee3afdd89452d9b89c547758bdbca23a466 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Thu, 5 Sep 2024 06:26:14 +0300 +Subject: drm/msm/dpu: drop LM_3 / LM_4 on SDM845 + +From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org> + +[ Upstream commit d39271061d67c6fcbe8f361c532b493069232cf8 ] + +On the SDM845 platform ther are no LM_3 and LM_4 blocks. Drop them from +the SDM845 catalog. + +Fixes: 25fdd5933e4c ("drm/msm: Add SDM845 DPU support") +Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org> +Reviewed-by: Abhinav Kumar <quic_abhinavk@quicinc.com> +Patchwork: https://patchwork.freedesktop.org/patch/612586/ +Link: https://lore.kernel.org/r/20240905-dpu-fix-sdm845-catalog-v1-2-3363d03998bd@linaro.org +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + .../gpu/drm/msm/disp/dpu1/catalog/dpu_4_0_sdm845.h | 12 ------------ + 1 file changed, 12 deletions(-) + +diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_4_0_sdm845.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_4_0_sdm845.h +index 59eeea3dd2e9f..72bd4f7e9e504 100644 +--- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_4_0_sdm845.h ++++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_4_0_sdm845.h +@@ -155,18 +155,6 @@ static const struct dpu_lm_cfg sdm845_lm[] = { + .lm_pair = LM_5, + .pingpong = PINGPONG_2, + .dspp = DSPP_2, +- }, { +- .name = "lm_3", .id = LM_3, +- .base = 0x0, .len = 0x320, +- .features = MIXER_SDM845_MASK, +- .sblk = &sdm845_lm_sblk, +- .pingpong = PINGPONG_NONE, +- }, { +- .name = "lm_4", .id = LM_4, +- .base = 0x0, .len = 0x320, +- .features = MIXER_SDM845_MASK, +- .sblk = &sdm845_lm_sblk, +- .pingpong = PINGPONG_NONE, + }, { + .name = "lm_5", .id = LM_5, + .base = 0x49000, .len = 0x320, +-- +2.43.0 + diff --git a/queue-6.12/drm-msm-dpu-on-sdm845-move-dspp_3-to-lm_5-block.patch b/queue-6.12/drm-msm-dpu-on-sdm845-move-dspp_3-to-lm_5-block.patch new file mode 100644 index 00000000000..562a8ba9845 --- /dev/null +++ b/queue-6.12/drm-msm-dpu-on-sdm845-move-dspp_3-to-lm_5-block.patch @@ -0,0 +1,45 @@ +From c25bd58c8ae143bebc9834a5995b174cef3b6167 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Thu, 5 Sep 2024 06:26:13 +0300 +Subject: drm/msm/dpu: on SDM845 move DSPP_3 to LM_5 block + +From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org> + +[ Upstream commit 768a272d5357269b17b4b06dd8647e21bdc0ca3c ] + +On the SDM845 platform the DSPP_3 is used by the LM_5. Correct +corresponding entries in the sdm845_lm array. + +Fixes: c72375172194 ("drm/msm/dpu/catalog: define DSPP blocks found on sdm845") +Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org> +Reviewed-by: Abhinav Kumar <quic_abhinavk@quicinc.com> +Patchwork: https://patchwork.freedesktop.org/patch/612584/ +Link: https://lore.kernel.org/r/20240905-dpu-fix-sdm845-catalog-v1-1-3363d03998bd@linaro.org +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_4_0_sdm845.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_4_0_sdm845.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_4_0_sdm845.h +index 7a23389a57327..59eeea3dd2e9f 100644 +--- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_4_0_sdm845.h ++++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_4_0_sdm845.h +@@ -161,7 +161,6 @@ static const struct dpu_lm_cfg sdm845_lm[] = { + .features = MIXER_SDM845_MASK, + .sblk = &sdm845_lm_sblk, + .pingpong = PINGPONG_NONE, +- .dspp = DSPP_3, + }, { + .name = "lm_4", .id = LM_4, + .base = 0x0, .len = 0x320, +@@ -175,6 +174,7 @@ static const struct dpu_lm_cfg sdm845_lm[] = { + .sblk = &sdm845_lm_sblk, + .lm_pair = LM_2, + .pingpong = PINGPONG_3, ++ .dspp = DSPP_3, + }, + }; + +-- +2.43.0 + diff --git a/queue-6.12/drm-msm-gpu-check-the-status-of-registration-to-pm-q.patch b/queue-6.12/drm-msm-gpu-check-the-status-of-registration-to-pm-q.patch new file mode 100644 index 00000000000..55dcf3777a6 --- /dev/null +++ b/queue-6.12/drm-msm-gpu-check-the-status-of-registration-to-pm-q.patch @@ -0,0 +1,51 @@ +From 70b985259c80ced0c737d517d20111c1e38ce85c Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Fri, 18 Oct 2024 12:18:11 +0100 +Subject: drm/msm/gpu: Check the status of registration to PM QoS + +From: Lukasz Luba <lukasz.luba@arm.com> + +[ Upstream commit 8f32ddd87e499ba6d2dc74ce30b6932baf1e1fc3 ] + +There is a need to check the returned value of the registration function. +In case of returned error, print that and stop the init process. + +Fixes: 7c0ffcd40b16 ("drm/msm/gpu: Respect PM QoS constraints") +Signed-off-by: Lukasz Luba <lukasz.luba@arm.com> +Patchwork: https://patchwork.freedesktop.org/patch/620336/ +Signed-off-by: Rob Clark <robdclark@chromium.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/gpu/drm/msm/msm_gpu_devfreq.c | 9 +++++++-- + 1 file changed, 7 insertions(+), 2 deletions(-) + +diff --git a/drivers/gpu/drm/msm/msm_gpu_devfreq.c b/drivers/gpu/drm/msm/msm_gpu_devfreq.c +index ea70c1c32d940..6970b0f7f457c 100644 +--- a/drivers/gpu/drm/msm/msm_gpu_devfreq.c ++++ b/drivers/gpu/drm/msm/msm_gpu_devfreq.c +@@ -140,6 +140,7 @@ void msm_devfreq_init(struct msm_gpu *gpu) + { + struct msm_gpu_devfreq *df = &gpu->devfreq; + struct msm_drm_private *priv = gpu->dev->dev_private; ++ int ret; + + /* We need target support to do devfreq */ + if (!gpu->funcs->gpu_busy) +@@ -156,8 +157,12 @@ void msm_devfreq_init(struct msm_gpu *gpu) + + mutex_init(&df->lock); + +- dev_pm_qos_add_request(&gpu->pdev->dev, &df->boost_freq, +- DEV_PM_QOS_MIN_FREQUENCY, 0); ++ ret = dev_pm_qos_add_request(&gpu->pdev->dev, &df->boost_freq, ++ DEV_PM_QOS_MIN_FREQUENCY, 0); ++ if (ret < 0) { ++ DRM_DEV_ERROR(&gpu->pdev->dev, "Couldn't initialize QoS\n"); ++ return; ++ } + + msm_devfreq_profile.initial_freq = gpu->fast_rate; + +-- +2.43.0 + diff --git a/queue-6.12/drm-nouveau-gr-gf100-fix-missing-unlock-in-gf100_gr_.patch b/queue-6.12/drm-nouveau-gr-gf100-fix-missing-unlock-in-gf100_gr_.patch new file mode 100644 index 00000000000..5291843616b --- /dev/null +++ b/queue-6.12/drm-nouveau-gr-gf100-fix-missing-unlock-in-gf100_gr_.patch @@ -0,0 +1,41 @@ +From 0e06892d968632a5a42e2bb8bd1a8689b4927cd1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Sun, 27 Oct 2024 01:38:44 +0800 +Subject: drm/nouveau/gr/gf100: Fix missing unlock in gf100_gr_chan_new() + +From: Li Huafei <lihuafei1@huawei.com> + +[ Upstream commit a2f599046c671d6b46d93aed95b37241ce4504cf ] + +When the call to gf100_grctx_generate() fails, unlock gr->fecs.mutex +before returning the error. + +Fixes smatch warning: + +drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c:480 gf100_gr_chan_new() warn: inconsistent returns '&gr->fecs.mutex'. + +Fixes: ca081fff6ecc ("drm/nouveau/gr/gf100-: generate golden context during first object alloc") +Signed-off-by: Li Huafei <lihuafei1@huawei.com> +Reviewed-by: Lyude Paul <lyude@redhat.com> +Signed-off-by: Lyude Paul <lyude@redhat.com> +Link: https://patchwork.freedesktop.org/patch/msgid/20241026173844.2392679-1-lihuafei1@huawei.com +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c +index 060c74a80eb14..3ea447f6a45b5 100644 +--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c ++++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c +@@ -443,6 +443,7 @@ gf100_gr_chan_new(struct nvkm_gr *base, struct nvkm_chan *fifoch, + ret = gf100_grctx_generate(gr, chan, fifoch->inst); + if (ret) { + nvkm_error(&base->engine.subdev, "failed to construct context\n"); ++ mutex_unlock(&gr->fecs.mutex); + return ret; + } + } +-- +2.43.0 + diff --git a/queue-6.12/drm-omap-fix-locking-in-omap_gem_new_dmabuf.patch b/queue-6.12/drm-omap-fix-locking-in-omap_gem_new_dmabuf.patch new file mode 100644 index 00000000000..af662c4e200 --- /dev/null +++ b/queue-6.12/drm-omap-fix-locking-in-omap_gem_new_dmabuf.patch @@ -0,0 +1,75 @@ +From 9747ea8ed7aa7a86d9608e8f7a8cf6e362e215b5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Tue, 6 Aug 2024 16:50:29 +0300 +Subject: drm/omap: Fix locking in omap_gem_new_dmabuf() + +From: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com> + +[ Upstream commit e6a1c4037227539373c8cf484ace83833e2ad6a2 ] + +omap_gem_new_dmabuf() creates the new gem object, and then takes and +holds the omap_obj->lock for the rest of the function. This has two +issues: + +- omap_gem_free_object(), which is called in the error paths, also takes + the same lock, leading to deadlock +- Even if the above wouldn't happen, in the error cases + omap_gem_new_dmabuf() still unlocks omap_obj->lock, even after the + omap_obj has already been freed. + +Furthermore, I don't think there's any reason to take the lock at all, +as the object was just created and not yet shared with anyone else. + +To fix all this, drop taking the lock. + +Fixes: 3cbd0c587b12 ("drm/omap: gem: Replace struct_mutex usage with omap_obj private lock") +Reported-by: Dan Carpenter <dan.carpenter@linaro.org> +Closes: https://lore.kernel.org/all/511b99d7-aade-4f92-bd3e-63163a13d617@stanley.mountain/ +Reviewed-by: Sebastian Reichel <sebastian.reichel@collabora.com> +Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com> +Link: https://patchwork.freedesktop.org/patch/msgid/20240806-omapdrm-misc-fixes-v1-3-15d31aea0831@ideasonboard.com +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/gpu/drm/omapdrm/omap_gem.c | 10 ++-------- + 1 file changed, 2 insertions(+), 8 deletions(-) + +diff --git a/drivers/gpu/drm/omapdrm/omap_gem.c b/drivers/gpu/drm/omapdrm/omap_gem.c +index fdae677558f3e..b9c67e4ca3605 100644 +--- a/drivers/gpu/drm/omapdrm/omap_gem.c ++++ b/drivers/gpu/drm/omapdrm/omap_gem.c +@@ -1402,8 +1402,6 @@ struct drm_gem_object *omap_gem_new_dmabuf(struct drm_device *dev, size_t size, + + omap_obj = to_omap_bo(obj); + +- mutex_lock(&omap_obj->lock); +- + omap_obj->sgt = sgt; + + if (omap_gem_sgt_is_contiguous(sgt, size)) { +@@ -1418,21 +1416,17 @@ struct drm_gem_object *omap_gem_new_dmabuf(struct drm_device *dev, size_t size, + pages = kcalloc(npages, sizeof(*pages), GFP_KERNEL); + if (!pages) { + omap_gem_free_object(obj); +- obj = ERR_PTR(-ENOMEM); +- goto done; ++ return ERR_PTR(-ENOMEM); + } + + omap_obj->pages = pages; + ret = drm_prime_sg_to_page_array(sgt, pages, npages); + if (ret) { + omap_gem_free_object(obj); +- obj = ERR_PTR(-ENOMEM); +- goto done; ++ return ERR_PTR(-ENOMEM); + } + } + +-done: +- mutex_unlock(&omap_obj->lock); + return obj; + } + +-- +2.43.0 + diff --git a/queue-6.12/drm-omap-fix-possible-null-dereference.patch b/queue-6.12/drm-omap-fix-possible-null-dereference.patch new file mode 100644 index 00000000000..5869a95bfd3 --- /dev/null +++ b/queue-6.12/drm-omap-fix-possible-null-dereference.patch @@ -0,0 +1,135 @@ +From e6430045448b23cfe0ff9a759c2ab14af21ae82c Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Tue, 6 Aug 2024 16:50:27 +0300 +Subject: drm/omap: Fix possible NULL dereference + +From: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com> + +[ Upstream commit a88fee2d67d9b78c24630a987a88ccf886b2498b ] + +smatch reports: + +drivers/gpu/drm/omapdrm/dss/base.c:176 omapdss_device_disconnect() error: we previously assumed 'src' could be null (see line 169) + +This code is mostly from a time when omapdrm had its own display device +model. I can't honestly remember the details, and I don't think it's +worth digging in deeply into that for a legacy driver. + +However, it looks like we only call omapdss_device_disconnect() and +omapdss_device_connect() with NULL as the src parameter. We can thus +drop the src parameter from both functions, and fix the smatch warning. + +I don't think omapdss_device_disconnect() ever gets NULL for the dst +parameter (if it did, we'd crash soon after returning from the +function), but I have kept the !dst check, just in case, but I added a +WARN_ON() there. + +Also, if the dst parameter can be NULL, we can't always get the struct +dss_device pointer from dst->dss (which is only used for a debug print). +To make sure we can't hit that issue, do it similarly to the +omapdss_device_connect() function: add 'struct dss_device *dss' as the +first parameter, so that we always have it regardless of the dst. + +Fixes: 79107f274b2f ("drm/omap: Add support for drm_bridge") +Reviewed-by: Sebastian Reichel <sebastian.reichel@collabora.com> +Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com> +Link: https://patchwork.freedesktop.org/patch/msgid/20240806-omapdrm-misc-fixes-v1-1-15d31aea0831@ideasonboard.com +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/gpu/drm/omapdrm/dss/base.c | 25 ++++++------------------- + drivers/gpu/drm/omapdrm/dss/omapdss.h | 3 +-- + drivers/gpu/drm/omapdrm/omap_drv.c | 4 ++-- + 3 files changed, 9 insertions(+), 23 deletions(-) + +diff --git a/drivers/gpu/drm/omapdrm/dss/base.c b/drivers/gpu/drm/omapdrm/dss/base.c +index 5f8002f6bb7a5..a4ac113e16904 100644 +--- a/drivers/gpu/drm/omapdrm/dss/base.c ++++ b/drivers/gpu/drm/omapdrm/dss/base.c +@@ -139,21 +139,13 @@ static bool omapdss_device_is_connected(struct omap_dss_device *dssdev) + } + + int omapdss_device_connect(struct dss_device *dss, +- struct omap_dss_device *src, + struct omap_dss_device *dst) + { +- dev_dbg(&dss->pdev->dev, "connect(%s, %s)\n", +- src ? dev_name(src->dev) : "NULL", ++ dev_dbg(&dss->pdev->dev, "connect(%s)\n", + dst ? dev_name(dst->dev) : "NULL"); + +- if (!dst) { +- /* +- * The destination is NULL when the source is connected to a +- * bridge instead of a DSS device. Stop here, we will attach +- * the bridge later when we will have a DRM encoder. +- */ +- return src && src->bridge ? 0 : -EINVAL; +- } ++ if (!dst) ++ return -EINVAL; + + if (omapdss_device_is_connected(dst)) + return -EBUSY; +@@ -163,19 +155,14 @@ int omapdss_device_connect(struct dss_device *dss, + return 0; + } + +-void omapdss_device_disconnect(struct omap_dss_device *src, ++void omapdss_device_disconnect(struct dss_device *dss, + struct omap_dss_device *dst) + { +- struct dss_device *dss = src ? src->dss : dst->dss; +- +- dev_dbg(&dss->pdev->dev, "disconnect(%s, %s)\n", +- src ? dev_name(src->dev) : "NULL", ++ dev_dbg(&dss->pdev->dev, "disconnect(%s)\n", + dst ? dev_name(dst->dev) : "NULL"); + +- if (!dst) { +- WARN_ON(!src->bridge); ++ if (WARN_ON(!dst)) + return; +- } + + if (!dst->id && !omapdss_device_is_connected(dst)) { + WARN_ON(1); +diff --git a/drivers/gpu/drm/omapdrm/dss/omapdss.h b/drivers/gpu/drm/omapdrm/dss/omapdss.h +index 040d5a3e33d68..4c22c09c93d52 100644 +--- a/drivers/gpu/drm/omapdrm/dss/omapdss.h ++++ b/drivers/gpu/drm/omapdrm/dss/omapdss.h +@@ -242,9 +242,8 @@ struct omap_dss_device *omapdss_device_get(struct omap_dss_device *dssdev); + void omapdss_device_put(struct omap_dss_device *dssdev); + struct omap_dss_device *omapdss_find_device_by_node(struct device_node *node); + int omapdss_device_connect(struct dss_device *dss, +- struct omap_dss_device *src, + struct omap_dss_device *dst); +-void omapdss_device_disconnect(struct omap_dss_device *src, ++void omapdss_device_disconnect(struct dss_device *dss, + struct omap_dss_device *dst); + + int omap_dss_get_num_overlay_managers(void); +diff --git a/drivers/gpu/drm/omapdrm/omap_drv.c b/drivers/gpu/drm/omapdrm/omap_drv.c +index d3eac4817d768..a982378aa1411 100644 +--- a/drivers/gpu/drm/omapdrm/omap_drv.c ++++ b/drivers/gpu/drm/omapdrm/omap_drv.c +@@ -307,7 +307,7 @@ static void omap_disconnect_pipelines(struct drm_device *ddev) + for (i = 0; i < priv->num_pipes; i++) { + struct omap_drm_pipeline *pipe = &priv->pipes[i]; + +- omapdss_device_disconnect(NULL, pipe->output); ++ omapdss_device_disconnect(priv->dss, pipe->output); + + omapdss_device_put(pipe->output); + pipe->output = NULL; +@@ -325,7 +325,7 @@ static int omap_connect_pipelines(struct drm_device *ddev) + int r; + + for_each_dss_output(output) { +- r = omapdss_device_connect(priv->dss, NULL, output); ++ r = omapdss_device_connect(priv->dss, output); + if (r == -EPROBE_DEFER) { + omapdss_device_put(output); + return r; +-- +2.43.0 + diff --git a/queue-6.12/drm-panel-nt35510-make-new-commands-optional.patch b/queue-6.12/drm-panel-nt35510-make-new-commands-optional.patch new file mode 100644 index 00000000000..c06526fa85b --- /dev/null +++ b/queue-6.12/drm-panel-nt35510-make-new-commands-optional.patch @@ -0,0 +1,70 @@ +From f3718eaa6948635c87918f0eff00b48e06e51d50 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Sun, 8 Sep 2024 23:50:30 +0200 +Subject: drm/panel: nt35510: Make new commands optional + +From: Linus Walleij <linus.walleij@linaro.org> + +[ Upstream commit 2418aa8516b26c5e332a1a8c216d4d620f965a56 ] + +The commit introducing the Frida display started to write the +SETVCMOFF registers unconditionally, and some (not all!) Hydis +display seem to be affected by ghosting after the commit. + +Make SETVCMOFF optional and only send these commands on the +Frida display for now. + +Reported-by: Stefan Hansson <newbyte@postmarketos.org> +Fixes: 219a1f49094f ("drm/panel: nt35510: support FRIDA FRD400B25025-A-CTK") +Acked-by: Jessica Zhang <quic_jesszhan@quicinc.com> +Tested-by: Stefan Hansson <newbyte@postmarketos.org> +Signed-off-by: Linus Walleij <linus.walleij@linaro.org> +Link: https://patchwork.freedesktop.org/patch/msgid/20240908-fix-nt35510-v2-1-d4834b9cdb9b@linaro.org +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/gpu/drm/panel/panel-novatek-nt35510.c | 15 +++++++++------ + 1 file changed, 9 insertions(+), 6 deletions(-) + +diff --git a/drivers/gpu/drm/panel/panel-novatek-nt35510.c b/drivers/gpu/drm/panel/panel-novatek-nt35510.c +index 57686340de49f..549b86f2cc288 100644 +--- a/drivers/gpu/drm/panel/panel-novatek-nt35510.c ++++ b/drivers/gpu/drm/panel/panel-novatek-nt35510.c +@@ -38,6 +38,7 @@ + + #define NT35510_CMD_CORRECT_GAMMA BIT(0) + #define NT35510_CMD_CONTROL_DISPLAY BIT(1) ++#define NT35510_CMD_SETVCMOFF BIT(2) + + #define MCS_CMD_MAUCCTR 0xF0 /* Manufacturer command enable */ + #define MCS_CMD_READ_ID1 0xDA +@@ -721,11 +722,13 @@ static int nt35510_setup_power(struct nt35510 *nt) + if (ret) + return ret; + +- ret = nt35510_send_long(nt, dsi, NT35510_P1_SETVCMOFF, +- NT35510_P1_VCMOFF_LEN, +- nt->conf->vcmoff); +- if (ret) +- return ret; ++ if (nt->conf->cmds & NT35510_CMD_SETVCMOFF) { ++ ret = nt35510_send_long(nt, dsi, NT35510_P1_SETVCMOFF, ++ NT35510_P1_VCMOFF_LEN, ++ nt->conf->vcmoff); ++ if (ret) ++ return ret; ++ } + + /* Typically 10 ms */ + usleep_range(10000, 20000); +@@ -1319,7 +1322,7 @@ static const struct nt35510_config nt35510_frida_frd400b25025 = { + }, + .mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST | + MIPI_DSI_MODE_LPM, +- .cmds = NT35510_CMD_CONTROL_DISPLAY, ++ .cmds = NT35510_CMD_CONTROL_DISPLAY | NT35510_CMD_SETVCMOFF, + /* 0x03: AVDD = 6.2V */ + .avdd = { 0x03, 0x03, 0x03 }, + /* 0x46: PCK = 2 x Hsync, BTP = 2.5 x VDDB */ +-- +2.43.0 + diff --git a/queue-6.12/drm-panel-nv3052c-correct-spi_device_id-for-rg35xx-p.patch b/queue-6.12/drm-panel-nv3052c-correct-spi_device_id-for-rg35xx-p.patch new file mode 100644 index 00000000000..30b1226e783 --- /dev/null +++ b/queue-6.12/drm-panel-nv3052c-correct-spi_device_id-for-rg35xx-p.patch @@ -0,0 +1,46 @@ +From 35eb4eb0ef7b675c646f546b9e9c3c0c5f5485c3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Sun, 20 Oct 2024 21:37:41 +1300 +Subject: drm: panel: nv3052c: correct spi_device_id for RG35XX panel + +From: Ryan Walklin <ryan@testtoast.com> + +[ Upstream commit 45608a3eb4902f32010a8328c0a01ccda4b38c9b ] + +The Anbernic RG35XX devices use an SPI LCD panel from an unknown OEM, +with an NV3052C driver chip. + +As discussed previously, the integrating vendor and device name are +preferred instead of the OEM serial. A previous patch corrected the +device tree binding and of_device_id in the NV3052C driver, however the +spi_device_id also needs correction. + +Correct the spi_device_id for the RG35XX panel. + +Signed-off-by: Ryan Walklin <ryan@testtoast.com> +Fixes: 76dce2a96c0f ("drm: panel: nv3052c: Correct WL-355608-A8 panel compatible") +Reviewed-by: Neil Armstrong <neil.armstrong@linaro.org> +Link: https://patchwork.freedesktop.org/patch/msgid/20241020083836.175733-1-ryan@testtoast.com +[DB: corrected the Fixes tag] +Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/gpu/drm/panel/panel-newvision-nv3052c.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/panel/panel-newvision-nv3052c.c b/drivers/gpu/drm/panel/panel-newvision-nv3052c.c +index d3baccfe6286b..06e16a7c14a75 100644 +--- a/drivers/gpu/drm/panel/panel-newvision-nv3052c.c ++++ b/drivers/gpu/drm/panel/panel-newvision-nv3052c.c +@@ -917,7 +917,7 @@ static const struct nv3052c_panel_info wl_355608_a8_panel_info = { + static const struct spi_device_id nv3052c_ids[] = { + { "ltk035c5444t", }, + { "fs035vg158", }, +- { "wl-355608-a8", }, ++ { "rg35xx-plus-panel", }, + { /* sentinel */ } + }; + MODULE_DEVICE_TABLE(spi, nv3052c_ids); +-- +2.43.0 + diff --git a/queue-6.12/drm-panfrost-add-missing-opp-table-refcnt-decrementa.patch b/queue-6.12/drm-panfrost-add-missing-opp-table-refcnt-decrementa.patch new file mode 100644 index 00000000000..37342c9e2d9 --- /dev/null +++ b/queue-6.12/drm-panfrost-add-missing-opp-table-refcnt-decrementa.patch @@ -0,0 +1,56 @@ +From b05831bb602c2578ffe6819147566a5d893ce950 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Tue, 5 Nov 2024 20:54:55 +0000 +Subject: drm/panfrost: Add missing OPP table refcnt decremental +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Adrián Larumbe <adrian.larumbe@collabora.com> + +[ Upstream commit 043e8afebf6c19abde9da1ac3d5cbf8b7ac8393f ] + +Commit f11b0417eec2 ("drm/panfrost: Add fdinfo support GPU load metrics") +retrieves the OPP for the maximum device clock frequency, but forgets to +keep the reference count balanced by putting the returned OPP object. This +eventually leads to an OPP core warning when removing the device. + +Fix it by putting OPP objects as many times as they're retrieved. + +Also remove an unnecessary whitespace. + +Signed-off-by: Adrián Larumbe <adrian.larumbe@collabora.com> +Fixes: f11b0417eec2 ("drm/panfrost: Add fdinfo support GPU load metrics") +Reviewed-by: Steven Price <steven.price@arm.com> +Reviewed-by: Liviu Dudau <liviu.dudau@arm.com> +Signed-off-by: Steven Price <steven.price@arm.com> +Link: https://patchwork.freedesktop.org/patch/msgid/20241105205458.1318989-1-adrian.larumbe@collabora.com +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/gpu/drm/panfrost/panfrost_devfreq.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/panfrost/panfrost_devfreq.c b/drivers/gpu/drm/panfrost/panfrost_devfreq.c +index 2d30da38c2c3e..3385fd3ef41a4 100644 +--- a/drivers/gpu/drm/panfrost/panfrost_devfreq.c ++++ b/drivers/gpu/drm/panfrost/panfrost_devfreq.c +@@ -38,7 +38,7 @@ static int panfrost_devfreq_target(struct device *dev, unsigned long *freq, + return PTR_ERR(opp); + dev_pm_opp_put(opp); + +- err = dev_pm_opp_set_rate(dev, *freq); ++ err = dev_pm_opp_set_rate(dev, *freq); + if (!err) + ptdev->pfdevfreq.current_frequency = *freq; + +@@ -182,6 +182,7 @@ int panfrost_devfreq_init(struct panfrost_device *pfdev) + * if any and will avoid a switch off by regulator_late_cleanup() + */ + ret = dev_pm_opp_set_opp(dev, opp); ++ dev_pm_opp_put(opp); + if (ret) { + DRM_DEV_ERROR(dev, "Couldn't set recommended OPP\n"); + return ret; +-- +2.43.0 + diff --git a/queue-6.12/drm-panfrost-remove-unused-id_mask-from-struct-panfr.patch b/queue-6.12/drm-panfrost-remove-unused-id_mask-from-struct-panfr.patch new file mode 100644 index 00000000000..a35a3aa2653 --- /dev/null +++ b/queue-6.12/drm-panfrost-remove-unused-id_mask-from-struct-panfr.patch @@ -0,0 +1,35 @@ +From 6682646be51bacf1b12a30a914d235250ec7c451 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Fri, 25 Oct 2024 15:00:07 +0100 +Subject: drm/panfrost: Remove unused id_mask from struct panfrost_model + +From: Steven Price <steven.price@arm.com> + +[ Upstream commit 581d1f8248550f2b67847e6d84f29fbe3751ea0a ] + +The id_mask field of struct panfrost_model has never been used. + +Fixes: f3ba91228e8e ("drm/panfrost: Add initial panfrost driver") +Signed-off-by: Steven Price <steven.price@arm.com> +Reviewed-by: Boris Brezillon <boris.brezillon@collabora.com> +Link: https://patchwork.freedesktop.org/patch/msgid/20241025140008.385081-1-steven.price@arm.com +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/gpu/drm/panfrost/panfrost_gpu.c | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/drivers/gpu/drm/panfrost/panfrost_gpu.c b/drivers/gpu/drm/panfrost/panfrost_gpu.c +index fd8e44992184f..b52dd510e0367 100644 +--- a/drivers/gpu/drm/panfrost/panfrost_gpu.c ++++ b/drivers/gpu/drm/panfrost/panfrost_gpu.c +@@ -177,7 +177,6 @@ static void panfrost_gpu_init_quirks(struct panfrost_device *pfdev) + struct panfrost_model { + const char *name; + u32 id; +- u32 id_mask; + u64 features; + u64 issues; + struct { +-- +2.43.0 + diff --git a/queue-6.12/drm-panic-select-zlib_deflate-for-drm_panic_screen_q.patch b/queue-6.12/drm-panic-select-zlib_deflate-for-drm_panic_screen_q.patch new file mode 100644 index 00000000000..0d629cc739b --- /dev/null +++ b/queue-6.12/drm-panic-select-zlib_deflate-for-drm_panic_screen_q.patch @@ -0,0 +1,42 @@ +From 71159af0e6d247c7217ae99fe2228c86ad30e0db Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Fri, 4 Oct 2024 01:07:34 +0200 +Subject: drm/panic: Select ZLIB_DEFLATE for DRM_PANIC_SCREEN_QR_CODE + +From: Miguel Ojeda <ojeda@kernel.org> + +[ Upstream commit 2ad84af4cff9121827d3dd35e293478bdb0b58bb ] + +Under `CONFIG_DRM_PANIC_SCREEN_QR_CODE=y`, zlib is used: + + ld.lld: error: undefined symbol: zlib_deflate_workspacesize + >>> referenced by drm_panic.c + >>> drivers/gpu/drm/drm_panic.o:(drm_panic_qr_init) in archive vmlinux.a + +Thus select `CONFIG_ZLIB_DEFLATE`. + +Fixes: cb5164ac43d0 ("drm/panic: Add a QR code panic screen") +Signed-off-by: Miguel Ojeda <ojeda@kernel.org> +Reviewed-by: Jocelyn Falempe <jfalempe@redhat.com> +Signed-off-by: Jocelyn Falempe <jfalempe@redhat.com> +Link: https://patchwork.freedesktop.org/patch/msgid/20241003230734.653717-1-ojeda@kernel.org +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/gpu/drm/Kconfig | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig +index 1cb5a4f192933..cf5bc77e2362c 100644 +--- a/drivers/gpu/drm/Kconfig ++++ b/drivers/gpu/drm/Kconfig +@@ -152,6 +152,7 @@ config DRM_PANIC_SCREEN + config DRM_PANIC_SCREEN_QR_CODE + bool "Add a panic screen with a QR code" + depends on DRM_PANIC && RUST ++ select ZLIB_DEFLATE + help + This option adds a QR code generator, and a panic screen with a QR + code. The QR code will contain the last lines of kmsg and other debug +-- +2.43.0 + diff --git a/queue-6.12/drm-panthor-fix-opp-refcnt-leaks-in-devfreq-initiali.patch b/queue-6.12/drm-panthor-fix-opp-refcnt-leaks-in-devfreq-initiali.patch new file mode 100644 index 00000000000..9f9b464d5b0 --- /dev/null +++ b/queue-6.12/drm-panthor-fix-opp-refcnt-leaks-in-devfreq-initiali.patch @@ -0,0 +1,74 @@ +From 315b55a99735fd0eee602e1c145aafa0741428ee Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Tue, 5 Nov 2024 20:54:56 +0000 +Subject: drm/panthor: Fix OPP refcnt leaks in devfreq initialisation +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Adrián Larumbe <adrian.larumbe@collabora.com> + +[ Upstream commit 21c23e4b64e360d74d31b480f0572c2add0e8558 ] + +Rearrange lookup of recommended OPP for the Mali GPU device and its refcnt +decremental to make sure no OPP object leaks happen in the error path. + +Signed-off-by: Adrián Larumbe <adrian.larumbe@collabora.com> +Fixes: fac9b22df4b1 ("drm/panthor: Add the devfreq logical block") +Reviewed-by: Steven Price <steven.price@arm.com> +Reviewed-by: Liviu Dudau <liviu.dudau@arm.com> +Signed-off-by: Steven Price <steven.price@arm.com> +Link: https://patchwork.freedesktop.org/patch/msgid/20241105205458.1318989-2-adrian.larumbe@collabora.com +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/gpu/drm/panthor/panthor_devfreq.c | 17 ++++++++--------- + 1 file changed, 8 insertions(+), 9 deletions(-) + +diff --git a/drivers/gpu/drm/panthor/panthor_devfreq.c b/drivers/gpu/drm/panthor/panthor_devfreq.c +index 9d0f891b9b534..ecc7a52bd688e 100644 +--- a/drivers/gpu/drm/panthor/panthor_devfreq.c ++++ b/drivers/gpu/drm/panthor/panthor_devfreq.c +@@ -163,13 +163,6 @@ int panthor_devfreq_init(struct panthor_device *ptdev) + + cur_freq = clk_get_rate(ptdev->clks.core); + +- opp = devfreq_recommended_opp(dev, &cur_freq, 0); +- if (IS_ERR(opp)) +- return PTR_ERR(opp); +- +- panthor_devfreq_profile.initial_freq = cur_freq; +- ptdev->current_frequency = cur_freq; +- + /* Regulator coupling only takes care of synchronizing/balancing voltage + * updates, but the coupled regulator needs to be enabled manually. + * +@@ -200,18 +193,24 @@ int panthor_devfreq_init(struct panthor_device *ptdev) + return ret; + } + ++ opp = devfreq_recommended_opp(dev, &cur_freq, 0); ++ if (IS_ERR(opp)) ++ return PTR_ERR(opp); ++ ++ panthor_devfreq_profile.initial_freq = cur_freq; ++ ptdev->current_frequency = cur_freq; ++ + /* + * Set the recommend OPP this will enable and configure the regulator + * if any and will avoid a switch off by regulator_late_cleanup() + */ + ret = dev_pm_opp_set_opp(dev, opp); ++ dev_pm_opp_put(opp); + if (ret) { + DRM_DEV_ERROR(dev, "Couldn't set recommended OPP\n"); + return ret; + } + +- dev_pm_opp_put(opp); +- + /* Find the fastest defined rate */ + opp = dev_pm_opp_find_freq_floor(dev, &freq); + if (IS_ERR(opp)) +-- +2.43.0 + diff --git a/queue-6.12/drm-panthor-introduce-job-cycle-and-timestamp-accoun.patch b/queue-6.12/drm-panthor-introduce-job-cycle-and-timestamp-accoun.patch new file mode 100644 index 00000000000..5845de268e2 --- /dev/null +++ b/queue-6.12/drm-panthor-introduce-job-cycle-and-timestamp-accoun.patch @@ -0,0 +1,543 @@ +From 42eb40bab5b4a0ce79d19403f998f5babd88931b Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Tue, 24 Sep 2024 00:06:21 +0100 +Subject: drm/panthor: introduce job cycle and timestamp accounting +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Adrián Larumbe <adrian.larumbe@collabora.com> + +[ Upstream commit f8ff51a4708451763e6cfa36cc83dea8513d3318 ] + +Enable calculations of job submission times in clock cycles and wall +time. This is done by expanding the boilerplate command stream when running +a job to include instructions that compute said times right before and +after a user CS. + +A separate kernel BO is created per queue to store those values. Jobs can +access their sampled data through an index different from that of the +queue's ringbuffer. The reason for this is saving memory on the profiling +information kernel BO, since the amount of simultaneous profiled jobs we +can write into the queue's ringbuffer might be much smaller than for +regular jobs, as the former take more CSF instructions. + +This commit is done in preparation for enabling DRM fdinfo support in the +Panthor driver, which depends on the numbers calculated herein. + +A profile mode mask has been added that will in a future commit allow UM to +toggle performance metric sampling behaviour, which is disabled by default +to save power. When a ringbuffer CS is constructed, timestamp and cycling +sampling instructions are added depending on the enabled flags in the +profiling mask. + +A helper was provided that calculates the number of instructions for a +given set of enablement mask, and these are passed as the number of credits +when initialising a DRM scheduler job. + +Signed-off-by: Adrián Larumbe <adrian.larumbe@collabora.com> +Reviewed-by: Boris Brezillon <boris.brezillon@collabora.com> +Reviewed-by: Liviu Dudau <liviu.dudau@arm.com> +Reviewed-by: Steven Price <steven.price@arm.com> +Signed-off-by: Boris Brezillon <boris.brezillon@collabora.com> +Link: https://patchwork.freedesktop.org/patch/msgid/20240923230912.2207320-2-adrian.larumbe@collabora.com +Stable-dep-of: 21c23e4b64e3 ("drm/panthor: Fix OPP refcnt leaks in devfreq initialisation") +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/gpu/drm/panthor/panthor_device.h | 22 ++ + drivers/gpu/drm/panthor/panthor_sched.c | 333 +++++++++++++++++++---- + 2 files changed, 306 insertions(+), 49 deletions(-) + +diff --git a/drivers/gpu/drm/panthor/panthor_device.h b/drivers/gpu/drm/panthor/panthor_device.h +index e388c0472ba78..a48e30d0af309 100644 +--- a/drivers/gpu/drm/panthor/panthor_device.h ++++ b/drivers/gpu/drm/panthor/panthor_device.h +@@ -66,6 +66,25 @@ struct panthor_irq { + atomic_t suspended; + }; + ++/** ++ * enum panthor_device_profiling_mode - Profiling state ++ */ ++enum panthor_device_profiling_flags { ++ /** @PANTHOR_DEVICE_PROFILING_DISABLED: Profiling is disabled. */ ++ PANTHOR_DEVICE_PROFILING_DISABLED = 0, ++ ++ /** @PANTHOR_DEVICE_PROFILING_CYCLES: Sampling job cycles. */ ++ PANTHOR_DEVICE_PROFILING_CYCLES = BIT(0), ++ ++ /** @PANTHOR_DEVICE_PROFILING_TIMESTAMP: Sampling job timestamp. */ ++ PANTHOR_DEVICE_PROFILING_TIMESTAMP = BIT(1), ++ ++ /** @PANTHOR_DEVICE_PROFILING_ALL: Sampling everything. */ ++ PANTHOR_DEVICE_PROFILING_ALL = ++ PANTHOR_DEVICE_PROFILING_CYCLES | ++ PANTHOR_DEVICE_PROFILING_TIMESTAMP, ++}; ++ + /** + * struct panthor_device - Panthor device + */ +@@ -162,6 +181,9 @@ struct panthor_device { + */ + struct page *dummy_latest_flush; + } pm; ++ ++ /** @profile_mask: User-set profiling flags for job accounting. */ ++ u32 profile_mask; + }; + + /** +diff --git a/drivers/gpu/drm/panthor/panthor_sched.c b/drivers/gpu/drm/panthor/panthor_sched.c +index 9929e22f4d8d2..20135a9bc026e 100644 +--- a/drivers/gpu/drm/panthor/panthor_sched.c ++++ b/drivers/gpu/drm/panthor/panthor_sched.c +@@ -93,6 +93,9 @@ + #define MIN_CSGS 3 + #define MAX_CSG_PRIO 0xf + ++#define NUM_INSTRS_PER_CACHE_LINE (64 / sizeof(u64)) ++#define MAX_INSTRS_PER_JOB 24 ++ + struct panthor_group; + + /** +@@ -476,6 +479,18 @@ struct panthor_queue { + */ + struct list_head in_flight_jobs; + } fence_ctx; ++ ++ /** @profiling: Job profiling data slots and access information. */ ++ struct { ++ /** @slots: Kernel BO holding the slots. */ ++ struct panthor_kernel_bo *slots; ++ ++ /** @slot_count: Number of jobs ringbuffer can hold at once. */ ++ u32 slot_count; ++ ++ /** @seqno: Index of the next available profiling information slot. */ ++ u32 seqno; ++ } profiling; + }; + + /** +@@ -662,6 +677,18 @@ struct panthor_group { + struct list_head wait_node; + }; + ++struct panthor_job_profiling_data { ++ struct { ++ u64 before; ++ u64 after; ++ } cycles; ++ ++ struct { ++ u64 before; ++ u64 after; ++ } time; ++}; ++ + /** + * group_queue_work() - Queue a group work + * @group: Group to queue the work for. +@@ -775,6 +802,15 @@ struct panthor_job { + + /** @done_fence: Fence signaled when the job is finished or cancelled. */ + struct dma_fence *done_fence; ++ ++ /** @profiling: Job profiling information. */ ++ struct { ++ /** @mask: Current device job profiling enablement bitmask. */ ++ u32 mask; ++ ++ /** @slot: Job index in the profiling slots BO. */ ++ u32 slot; ++ } profiling; + }; + + static void +@@ -839,6 +875,7 @@ static void group_free_queue(struct panthor_group *group, struct panthor_queue * + + panthor_kernel_bo_destroy(queue->ringbuf); + panthor_kernel_bo_destroy(queue->iface.mem); ++ panthor_kernel_bo_destroy(queue->profiling.slots); + + /* Release the last_fence we were holding, if any. */ + dma_fence_put(queue->fence_ctx.last_fence); +@@ -1989,8 +2026,6 @@ tick_ctx_init(struct panthor_scheduler *sched, + } + } + +-#define NUM_INSTRS_PER_SLOT 16 +- + static void + group_term_post_processing(struct panthor_group *group) + { +@@ -2829,65 +2864,198 @@ static void group_sync_upd_work(struct work_struct *work) + group_put(group); + } + +-static struct dma_fence * +-queue_run_job(struct drm_sched_job *sched_job) ++struct panthor_job_ringbuf_instrs { ++ u64 buffer[MAX_INSTRS_PER_JOB]; ++ u32 count; ++}; ++ ++struct panthor_job_instr { ++ u32 profile_mask; ++ u64 instr; ++}; ++ ++#define JOB_INSTR(__prof, __instr) \ ++ { \ ++ .profile_mask = __prof, \ ++ .instr = __instr, \ ++ } ++ ++static void ++copy_instrs_to_ringbuf(struct panthor_queue *queue, ++ struct panthor_job *job, ++ struct panthor_job_ringbuf_instrs *instrs) ++{ ++ u64 ringbuf_size = panthor_kernel_bo_size(queue->ringbuf); ++ u64 start = job->ringbuf.start & (ringbuf_size - 1); ++ u64 size, written; ++ ++ /* ++ * We need to write a whole slot, including any trailing zeroes ++ * that may come at the end of it. Also, because instrs.buffer has ++ * been zero-initialised, there's no need to pad it with 0's ++ */ ++ instrs->count = ALIGN(instrs->count, NUM_INSTRS_PER_CACHE_LINE); ++ size = instrs->count * sizeof(u64); ++ WARN_ON(size > ringbuf_size); ++ written = min(ringbuf_size - start, size); ++ ++ memcpy(queue->ringbuf->kmap + start, instrs->buffer, written); ++ ++ if (written < size) ++ memcpy(queue->ringbuf->kmap, ++ &instrs->buffer[written / sizeof(u64)], ++ size - written); ++} ++ ++struct panthor_job_cs_params { ++ u32 profile_mask; ++ u64 addr_reg; u64 val_reg; ++ u64 cycle_reg; u64 time_reg; ++ u64 sync_addr; u64 times_addr; ++ u64 cs_start; u64 cs_size; ++ u32 last_flush; u32 waitall_mask; ++}; ++ ++static void ++get_job_cs_params(struct panthor_job *job, struct panthor_job_cs_params *params) + { +- struct panthor_job *job = container_of(sched_job, struct panthor_job, base); + struct panthor_group *group = job->group; + struct panthor_queue *queue = group->queues[job->queue_idx]; + struct panthor_device *ptdev = group->ptdev; + struct panthor_scheduler *sched = ptdev->scheduler; +- u32 ringbuf_size = panthor_kernel_bo_size(queue->ringbuf); +- u32 ringbuf_insert = queue->iface.input->insert & (ringbuf_size - 1); +- u64 addr_reg = ptdev->csif_info.cs_reg_count - +- ptdev->csif_info.unpreserved_cs_reg_count; +- u64 val_reg = addr_reg + 2; +- u64 sync_addr = panthor_kernel_bo_gpuva(group->syncobjs) + +- job->queue_idx * sizeof(struct panthor_syncobj_64b); +- u32 waitall_mask = GENMASK(sched->sb_slot_count - 1, 0); +- struct dma_fence *done_fence; +- int ret; + +- u64 call_instrs[NUM_INSTRS_PER_SLOT] = { +- /* MOV32 rX+2, cs.latest_flush */ +- (2ull << 56) | (val_reg << 48) | job->call_info.latest_flush, ++ params->addr_reg = ptdev->csif_info.cs_reg_count - ++ ptdev->csif_info.unpreserved_cs_reg_count; ++ params->val_reg = params->addr_reg + 2; ++ params->cycle_reg = params->addr_reg; ++ params->time_reg = params->val_reg; + +- /* FLUSH_CACHE2.clean_inv_all.no_wait.signal(0) rX+2 */ +- (36ull << 56) | (0ull << 48) | (val_reg << 40) | (0 << 16) | 0x233, ++ params->sync_addr = panthor_kernel_bo_gpuva(group->syncobjs) + ++ job->queue_idx * sizeof(struct panthor_syncobj_64b); ++ params->times_addr = panthor_kernel_bo_gpuva(queue->profiling.slots) + ++ (job->profiling.slot * sizeof(struct panthor_job_profiling_data)); ++ params->waitall_mask = GENMASK(sched->sb_slot_count - 1, 0); + +- /* MOV48 rX:rX+1, cs.start */ +- (1ull << 56) | (addr_reg << 48) | job->call_info.start, ++ params->cs_start = job->call_info.start; ++ params->cs_size = job->call_info.size; ++ params->last_flush = job->call_info.latest_flush; + +- /* MOV32 rX+2, cs.size */ +- (2ull << 56) | (val_reg << 48) | job->call_info.size, ++ params->profile_mask = job->profiling.mask; ++} + +- /* WAIT(0) => waits for FLUSH_CACHE2 instruction */ +- (3ull << 56) | (1 << 16), ++#define JOB_INSTR_ALWAYS(instr) \ ++ JOB_INSTR(PANTHOR_DEVICE_PROFILING_DISABLED, (instr)) ++#define JOB_INSTR_TIMESTAMP(instr) \ ++ JOB_INSTR(PANTHOR_DEVICE_PROFILING_TIMESTAMP, (instr)) ++#define JOB_INSTR_CYCLES(instr) \ ++ JOB_INSTR(PANTHOR_DEVICE_PROFILING_CYCLES, (instr)) + ++static void ++prepare_job_instrs(const struct panthor_job_cs_params *params, ++ struct panthor_job_ringbuf_instrs *instrs) ++{ ++ const struct panthor_job_instr instr_seq[] = { ++ /* MOV32 rX+2, cs.latest_flush */ ++ JOB_INSTR_ALWAYS((2ull << 56) | (params->val_reg << 48) | params->last_flush), ++ /* FLUSH_CACHE2.clean_inv_all.no_wait.signal(0) rX+2 */ ++ JOB_INSTR_ALWAYS((36ull << 56) | (0ull << 48) | (params->val_reg << 40) | ++ (0 << 16) | 0x233), ++ /* MOV48 rX:rX+1, cycles_offset */ ++ JOB_INSTR_CYCLES((1ull << 56) | (params->cycle_reg << 48) | ++ (params->times_addr + ++ offsetof(struct panthor_job_profiling_data, cycles.before))), ++ /* STORE_STATE cycles */ ++ JOB_INSTR_CYCLES((40ull << 56) | (params->cycle_reg << 40) | (1ll << 32)), ++ /* MOV48 rX:rX+1, time_offset */ ++ JOB_INSTR_TIMESTAMP((1ull << 56) | (params->time_reg << 48) | ++ (params->times_addr + ++ offsetof(struct panthor_job_profiling_data, time.before))), ++ /* STORE_STATE timer */ ++ JOB_INSTR_TIMESTAMP((40ull << 56) | (params->time_reg << 40) | (0ll << 32)), ++ /* MOV48 rX:rX+1, cs.start */ ++ JOB_INSTR_ALWAYS((1ull << 56) | (params->addr_reg << 48) | params->cs_start), ++ /* MOV32 rX+2, cs.size */ ++ JOB_INSTR_ALWAYS((2ull << 56) | (params->val_reg << 48) | params->cs_size), ++ /* WAIT(0) => waits for FLUSH_CACHE2 instruction */ ++ JOB_INSTR_ALWAYS((3ull << 56) | (1 << 16)), + /* CALL rX:rX+1, rX+2 */ +- (32ull << 56) | (addr_reg << 40) | (val_reg << 32), +- ++ JOB_INSTR_ALWAYS((32ull << 56) | (params->addr_reg << 40) | ++ (params->val_reg << 32)), ++ /* MOV48 rX:rX+1, cycles_offset */ ++ JOB_INSTR_CYCLES((1ull << 56) | (params->cycle_reg << 48) | ++ (params->times_addr + ++ offsetof(struct panthor_job_profiling_data, cycles.after))), ++ /* STORE_STATE cycles */ ++ JOB_INSTR_CYCLES((40ull << 56) | (params->cycle_reg << 40) | (1ll << 32)), ++ /* MOV48 rX:rX+1, time_offset */ ++ JOB_INSTR_TIMESTAMP((1ull << 56) | (params->time_reg << 48) | ++ (params->times_addr + ++ offsetof(struct panthor_job_profiling_data, time.after))), ++ /* STORE_STATE timer */ ++ JOB_INSTR_TIMESTAMP((40ull << 56) | (params->time_reg << 40) | (0ll << 32)), + /* MOV48 rX:rX+1, sync_addr */ +- (1ull << 56) | (addr_reg << 48) | sync_addr, +- ++ JOB_INSTR_ALWAYS((1ull << 56) | (params->addr_reg << 48) | params->sync_addr), + /* MOV48 rX+2, #1 */ +- (1ull << 56) | (val_reg << 48) | 1, +- ++ JOB_INSTR_ALWAYS((1ull << 56) | (params->val_reg << 48) | 1), + /* WAIT(all) */ +- (3ull << 56) | (waitall_mask << 16), +- ++ JOB_INSTR_ALWAYS((3ull << 56) | (params->waitall_mask << 16)), + /* SYNC_ADD64.system_scope.propage_err.nowait rX:rX+1, rX+2*/ +- (51ull << 56) | (0ull << 48) | (addr_reg << 40) | (val_reg << 32) | (0 << 16) | 1, ++ JOB_INSTR_ALWAYS((51ull << 56) | (0ull << 48) | (params->addr_reg << 40) | ++ (params->val_reg << 32) | (0 << 16) | 1), ++ /* ERROR_BARRIER, so we can recover from faults at job boundaries. */ ++ JOB_INSTR_ALWAYS((47ull << 56)), ++ }; ++ u32 pad; + +- /* ERROR_BARRIER, so we can recover from faults at job +- * boundaries. +- */ +- (47ull << 56), ++ instrs->count = 0; ++ ++ /* NEED to be cacheline aligned to please the prefetcher. */ ++ static_assert(sizeof(instrs->buffer) % 64 == 0, ++ "panthor_job_ringbuf_instrs::buffer is not aligned on a cacheline"); ++ ++ /* Make sure we have enough storage to store the whole sequence. */ ++ static_assert(ALIGN(ARRAY_SIZE(instr_seq), NUM_INSTRS_PER_CACHE_LINE) == ++ ARRAY_SIZE(instrs->buffer), ++ "instr_seq vs panthor_job_ringbuf_instrs::buffer size mismatch"); ++ ++ for (u32 i = 0; i < ARRAY_SIZE(instr_seq); i++) { ++ /* If the profile mask of this instruction is not enabled, skip it. */ ++ if (instr_seq[i].profile_mask && ++ !(instr_seq[i].profile_mask & params->profile_mask)) ++ continue; ++ ++ instrs->buffer[instrs->count++] = instr_seq[i].instr; ++ } ++ ++ pad = ALIGN(instrs->count, NUM_INSTRS_PER_CACHE_LINE); ++ memset(&instrs->buffer[instrs->count], 0, ++ (pad - instrs->count) * sizeof(instrs->buffer[0])); ++ instrs->count = pad; ++} ++ ++static u32 calc_job_credits(u32 profile_mask) ++{ ++ struct panthor_job_ringbuf_instrs instrs; ++ struct panthor_job_cs_params params = { ++ .profile_mask = profile_mask, + }; + +- /* Need to be cacheline aligned to please the prefetcher. */ +- static_assert(sizeof(call_instrs) % 64 == 0, +- "call_instrs is not aligned on a cacheline"); ++ prepare_job_instrs(¶ms, &instrs); ++ return instrs.count; ++} ++ ++static struct dma_fence * ++queue_run_job(struct drm_sched_job *sched_job) ++{ ++ struct panthor_job *job = container_of(sched_job, struct panthor_job, base); ++ struct panthor_group *group = job->group; ++ struct panthor_queue *queue = group->queues[job->queue_idx]; ++ struct panthor_device *ptdev = group->ptdev; ++ struct panthor_scheduler *sched = ptdev->scheduler; ++ struct panthor_job_ringbuf_instrs instrs; ++ struct panthor_job_cs_params cs_params; ++ struct dma_fence *done_fence; ++ int ret; + + /* Stream size is zero, nothing to do except making sure all previously + * submitted jobs are done before we signal the +@@ -2914,17 +3082,23 @@ queue_run_job(struct drm_sched_job *sched_job) + queue->fence_ctx.id, + atomic64_inc_return(&queue->fence_ctx.seqno)); + +- memcpy(queue->ringbuf->kmap + ringbuf_insert, +- call_instrs, sizeof(call_instrs)); ++ job->profiling.slot = queue->profiling.seqno++; ++ if (queue->profiling.seqno == queue->profiling.slot_count) ++ queue->profiling.seqno = 0; ++ ++ job->ringbuf.start = queue->iface.input->insert; ++ ++ get_job_cs_params(job, &cs_params); ++ prepare_job_instrs(&cs_params, &instrs); ++ copy_instrs_to_ringbuf(queue, job, &instrs); ++ ++ job->ringbuf.end = job->ringbuf.start + (instrs.count * sizeof(u64)); + + panthor_job_get(&job->base); + spin_lock(&queue->fence_ctx.lock); + list_add_tail(&job->node, &queue->fence_ctx.in_flight_jobs); + spin_unlock(&queue->fence_ctx.lock); + +- job->ringbuf.start = queue->iface.input->insert; +- job->ringbuf.end = job->ringbuf.start + sizeof(call_instrs); +- + /* Make sure the ring buffer is updated before the INSERT + * register. + */ +@@ -3017,6 +3191,33 @@ static const struct drm_sched_backend_ops panthor_queue_sched_ops = { + .free_job = queue_free_job, + }; + ++static u32 calc_profiling_ringbuf_num_slots(struct panthor_device *ptdev, ++ u32 cs_ringbuf_size) ++{ ++ u32 min_profiled_job_instrs = U32_MAX; ++ u32 last_flag = fls(PANTHOR_DEVICE_PROFILING_ALL); ++ ++ /* ++ * We want to calculate the minimum size of a profiled job's CS, ++ * because since they need additional instructions for the sampling ++ * of performance metrics, they might take up further slots in ++ * the queue's ringbuffer. This means we might not need as many job ++ * slots for keeping track of their profiling information. What we ++ * need is the maximum number of slots we should allocate to this end, ++ * which matches the maximum number of profiled jobs we can place ++ * simultaneously in the queue's ring buffer. ++ * That has to be calculated separately for every single job profiling ++ * flag, but not in the case job profiling is disabled, since unprofiled ++ * jobs don't need to keep track of this at all. ++ */ ++ for (u32 i = 0; i < last_flag; i++) { ++ min_profiled_job_instrs = ++ min(min_profiled_job_instrs, calc_job_credits(BIT(i))); ++ } ++ ++ return DIV_ROUND_UP(cs_ringbuf_size, min_profiled_job_instrs * sizeof(u64)); ++} ++ + static struct panthor_queue * + group_create_queue(struct panthor_group *group, + const struct drm_panthor_queue_create *args) +@@ -3070,9 +3271,35 @@ group_create_queue(struct panthor_group *group, + goto err_free_queue; + } + ++ queue->profiling.slot_count = ++ calc_profiling_ringbuf_num_slots(group->ptdev, args->ringbuf_size); ++ ++ queue->profiling.slots = ++ panthor_kernel_bo_create(group->ptdev, group->vm, ++ queue->profiling.slot_count * ++ sizeof(struct panthor_job_profiling_data), ++ DRM_PANTHOR_BO_NO_MMAP, ++ DRM_PANTHOR_VM_BIND_OP_MAP_NOEXEC | ++ DRM_PANTHOR_VM_BIND_OP_MAP_UNCACHED, ++ PANTHOR_VM_KERNEL_AUTO_VA); ++ ++ if (IS_ERR(queue->profiling.slots)) { ++ ret = PTR_ERR(queue->profiling.slots); ++ goto err_free_queue; ++ } ++ ++ ret = panthor_kernel_bo_vmap(queue->profiling.slots); ++ if (ret) ++ goto err_free_queue; ++ ++ /* ++ * Credit limit argument tells us the total number of instructions ++ * across all CS slots in the ringbuffer, with some jobs requiring ++ * twice as many as others, depending on their profiling status. ++ */ + ret = drm_sched_init(&queue->scheduler, &panthor_queue_sched_ops, + group->ptdev->scheduler->wq, 1, +- args->ringbuf_size / (NUM_INSTRS_PER_SLOT * sizeof(u64)), ++ args->ringbuf_size / sizeof(u64), + 0, msecs_to_jiffies(JOB_TIMEOUT_MS), + group->ptdev->reset.wq, + NULL, "panthor-queue", group->ptdev->base.dev); +@@ -3380,6 +3607,7 @@ panthor_job_create(struct panthor_file *pfile, + { + struct panthor_group_pool *gpool = pfile->groups; + struct panthor_job *job; ++ u32 credits; + int ret; + + if (qsubmit->pad) +@@ -3438,9 +3666,16 @@ panthor_job_create(struct panthor_file *pfile, + } + } + ++ job->profiling.mask = pfile->ptdev->profile_mask; ++ credits = calc_job_credits(job->profiling.mask); ++ if (credits == 0) { ++ ret = -EINVAL; ++ goto err_put_job; ++ } ++ + ret = drm_sched_job_init(&job->base, + &job->group->queues[job->queue_idx]->entity, +- 1, job->group); ++ credits, job->group); + if (ret) + goto err_put_job; + +-- +2.43.0 + diff --git a/queue-6.12/drm-panthor-record-current-and-maximum-device-clock-.patch b/queue-6.12/drm-panthor-record-current-and-maximum-device-clock-.patch new file mode 100644 index 00000000000..5fdf71effb5 --- /dev/null +++ b/queue-6.12/drm-panthor-record-current-and-maximum-device-clock-.patch @@ -0,0 +1,105 @@ +From af42aa44808fa52fdeed39c4aef9876e1ad6b4f7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Tue, 24 Sep 2024 00:06:22 +0100 +Subject: drm/panthor: record current and maximum device clock frequencies +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Adrián Larumbe <adrian.larumbe@collabora.com> + +[ Upstream commit 37591ae11f89cdfc0a647945a589468642a44c17 ] + +In order to support UM in calculating rates of GPU utilisation, the current +operating and maximum GPU clock frequencies must be recorded during device +initialisation, and also during OPP state transitions. + +Signed-off-by: Adrián Larumbe <adrian.larumbe@collabora.com> +Reviewed-by: Steven Price <steven.price@arm.com> +Reviewed-by: Boris Brezillon <boris.brezillon@collabora.com> +Signed-off-by: Boris Brezillon <boris.brezillon@collabora.com> +Link: https://patchwork.freedesktop.org/patch/msgid/20240923230912.2207320-3-adrian.larumbe@collabora.com +Stable-dep-of: 21c23e4b64e3 ("drm/panthor: Fix OPP refcnt leaks in devfreq initialisation") +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/gpu/drm/panthor/panthor_devfreq.c | 18 +++++++++++++++++- + drivers/gpu/drm/panthor/panthor_device.h | 6 ++++++ + 2 files changed, 23 insertions(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/panthor/panthor_devfreq.c b/drivers/gpu/drm/panthor/panthor_devfreq.c +index c6d3c327cc24c..9d0f891b9b534 100644 +--- a/drivers/gpu/drm/panthor/panthor_devfreq.c ++++ b/drivers/gpu/drm/panthor/panthor_devfreq.c +@@ -62,14 +62,20 @@ static void panthor_devfreq_update_utilization(struct panthor_devfreq *pdevfreq) + static int panthor_devfreq_target(struct device *dev, unsigned long *freq, + u32 flags) + { ++ struct panthor_device *ptdev = dev_get_drvdata(dev); + struct dev_pm_opp *opp; ++ int err; + + opp = devfreq_recommended_opp(dev, freq, flags); + if (IS_ERR(opp)) + return PTR_ERR(opp); + dev_pm_opp_put(opp); + +- return dev_pm_opp_set_rate(dev, *freq); ++ err = dev_pm_opp_set_rate(dev, *freq); ++ if (!err) ++ ptdev->current_frequency = *freq; ++ ++ return err; + } + + static void panthor_devfreq_reset(struct panthor_devfreq *pdevfreq) +@@ -130,6 +136,7 @@ int panthor_devfreq_init(struct panthor_device *ptdev) + struct panthor_devfreq *pdevfreq; + struct dev_pm_opp *opp; + unsigned long cur_freq; ++ unsigned long freq = ULONG_MAX; + int ret; + + pdevfreq = drmm_kzalloc(&ptdev->base, sizeof(*ptdev->devfreq), GFP_KERNEL); +@@ -161,6 +168,7 @@ int panthor_devfreq_init(struct panthor_device *ptdev) + return PTR_ERR(opp); + + panthor_devfreq_profile.initial_freq = cur_freq; ++ ptdev->current_frequency = cur_freq; + + /* Regulator coupling only takes care of synchronizing/balancing voltage + * updates, but the coupled regulator needs to be enabled manually. +@@ -204,6 +212,14 @@ int panthor_devfreq_init(struct panthor_device *ptdev) + + dev_pm_opp_put(opp); + ++ /* Find the fastest defined rate */ ++ opp = dev_pm_opp_find_freq_floor(dev, &freq); ++ if (IS_ERR(opp)) ++ return PTR_ERR(opp); ++ ptdev->fast_rate = freq; ++ ++ dev_pm_opp_put(opp); ++ + /* + * Setup default thresholds for the simple_ondemand governor. + * The values are chosen based on experiments. +diff --git a/drivers/gpu/drm/panthor/panthor_device.h b/drivers/gpu/drm/panthor/panthor_device.h +index a48e30d0af309..2109905813e8c 100644 +--- a/drivers/gpu/drm/panthor/panthor_device.h ++++ b/drivers/gpu/drm/panthor/panthor_device.h +@@ -184,6 +184,12 @@ struct panthor_device { + + /** @profile_mask: User-set profiling flags for job accounting. */ + u32 profile_mask; ++ ++ /** @current_frequency: Device clock frequency at present. Set by DVFS*/ ++ unsigned long current_frequency; ++ ++ /** @fast_rate: Maximum device clock frequency. Set by DVFS */ ++ unsigned long fast_rate; + }; + + /** +-- +2.43.0 + diff --git a/queue-6.12/drm-radeon-fix-spurious-unplug-event-on-radeon-hdmi.patch b/queue-6.12/drm-radeon-fix-spurious-unplug-event-on-radeon-hdmi.patch new file mode 100644 index 00000000000..d7335b3b4b2 --- /dev/null +++ b/queue-6.12/drm-radeon-fix-spurious-unplug-event-on-radeon-hdmi.patch @@ -0,0 +1,64 @@ +From f50b3ca2b45f3abe039d60da8c4af67bd6bbccb7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Fri, 15 Nov 2024 21:17:58 +0000 +Subject: drm/radeon: Fix spurious unplug event on radeon HDMI + +From: Steven 'Steve' Kendall <skend@chromium.org> + +[ Upstream commit 7037bb04265ef05c6ffad56d884b0df76f57b095 ] + +On several HP models (tested on HP 3125 and HP Probook 455 G2), +spurious unplug events are emitted upon login on Chrome OS. +This is likely due to the way Chrome OS restarts graphics +upon login, so it's possible it's an issue on other +distributions but not as common, though I haven't +reproduced the issue elsewhere. +Use logic from an earlier version of the merged change +(see link below) which iterates over connectors and finds +matching encoders, rather than the other way around. +Also fixes an issue with screen mirroring on Chrome OS. +I've deployed this patch on Fedora and did not observe +any regression on these devices. + +Link: https://gitlab.freedesktop.org/drm/amd/-/issues/1569#note_1603002 +Link: https://gitlab.freedesktop.org/drm/amd/-/issues/3771 +Fixes: 20ea34710f7b ("drm/radeon: Add HD-audio component notifier support (v6)") +Signed-off-by: Steven 'Steve' Kendall <skend@chromium.org> +Signed-off-by: Alex Deucher <alexander.deucher@amd.com> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/gpu/drm/radeon/radeon_audio.c | 12 ++++++++---- + 1 file changed, 8 insertions(+), 4 deletions(-) + +diff --git a/drivers/gpu/drm/radeon/radeon_audio.c b/drivers/gpu/drm/radeon/radeon_audio.c +index 47aa06a9a9422..5b69cc8011b42 100644 +--- a/drivers/gpu/drm/radeon/radeon_audio.c ++++ b/drivers/gpu/drm/radeon/radeon_audio.c +@@ -760,16 +760,20 @@ static int radeon_audio_component_get_eld(struct device *kdev, int port, + if (!rdev->audio.enabled || !rdev->mode_info.mode_config_initialized) + return 0; + +- list_for_each_entry(encoder, &rdev_to_drm(rdev)->mode_config.encoder_list, head) { ++ list_for_each_entry(connector, &dev->mode_config.connector_list, head) { ++ const struct drm_connector_helper_funcs *connector_funcs = ++ connector->helper_private; ++ encoder = connector_funcs->best_encoder(connector); ++ ++ if (!encoder) ++ continue; ++ + if (!radeon_encoder_is_digital(encoder)) + continue; + radeon_encoder = to_radeon_encoder(encoder); + dig = radeon_encoder->enc_priv; + if (!dig->pin || dig->pin->id != port) + continue; +- connector = radeon_get_connector_for_encoder(encoder); +- if (!connector) +- continue; + *enabled = true; + ret = drm_eld_size(connector->eld); + memcpy(buf, connector->eld, min(max_bytes, ret)); +-- +2.43.0 + diff --git a/queue-6.12/drm-use-atomic64_init-for-atomic64_t.patch b/queue-6.12/drm-use-atomic64_init-for-atomic64_t.patch new file mode 100644 index 00000000000..d2bc5fdbb02 --- /dev/null +++ b/queue-6.12/drm-use-atomic64_init-for-atomic64_t.patch @@ -0,0 +1,37 @@ +From 99eb9bc3ca908368e09b7145afe097bcda36d1dc Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Thu, 11 Jan 2024 13:30:45 +1100 +Subject: drm: use ATOMIC64_INIT() for atomic64_t + +From: Jonathan Gray <jsg@jsg.id.au> + +[ Upstream commit 9877bb2775d020fb7000af5ca989331d09d0e372 ] + +use ATOMIC64_INIT() not ATOMIC_INIT() for atomic64_t + +Fixes: 3f09a0cd4ea3 ("drm: Add common fdinfo helper") +Signed-off-by: Jonathan Gray <jsg@jsg.id.au> +Reviewed-by: Jani Nikula <jani.nikula@intel.com> +Link: https://patchwork.freedesktop.org/patch/msgid/20240111023045.50013-1-jsg@jsg.id.au +Signed-off-by: Jani Nikula <jani.nikula@intel.com> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/gpu/drm/drm_file.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/drm_file.c b/drivers/gpu/drm/drm_file.c +index ad1dc638c83bb..ce82c9451dfe7 100644 +--- a/drivers/gpu/drm/drm_file.c ++++ b/drivers/gpu/drm/drm_file.c +@@ -129,7 +129,7 @@ bool drm_dev_needs_global_mutex(struct drm_device *dev) + */ + struct drm_file *drm_file_alloc(struct drm_minor *minor) + { +- static atomic64_t ident = ATOMIC_INIT(0); ++ static atomic64_t ident = ATOMIC64_INIT(0); + struct drm_device *dev = minor->dev; + struct drm_file *file; + int ret; +-- +2.43.0 + diff --git a/queue-6.12/drm-v3d-address-race-condition-in-mmu-flush.patch b/queue-6.12/drm-v3d-address-race-condition-in-mmu-flush.patch new file mode 100644 index 00000000000..2daadc582dc --- /dev/null +++ b/queue-6.12/drm-v3d-address-race-condition-in-mmu-flush.patch @@ -0,0 +1,80 @@ +From dd37154469ebbaa8922c7d113fc37cf0e1f03991 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Mon, 23 Sep 2024 10:55:05 -0300 +Subject: drm/v3d: Address race-condition in MMU flush +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Maíra Canal <mcanal@igalia.com> + +[ Upstream commit cf1becb7f996a0a23ea2c270cf6bb0911ec3ca1a ] + +We must first flush the MMU cache and then, flush the TLB, not the other +way around. Currently, we can see a race condition between the MMU cache +and the TLB when running multiple rendering processes at the same time. +This is evidenced by MMU errors triggered by the IRQ. + +Fix the MMU flush order by flushing the MMU cache and then the TLB. +Also, in order to address the race condition, wait for the MMU cache flush +to finish before starting the TLB flush. + +Fixes: 57692c94dcbe ("drm/v3d: Introduce a new DRM driver for Broadcom V3D V3.x+") +Signed-off-by: Maíra Canal <mcanal@igalia.com> +Reviewed-by: Iago Toral Quiroga <itoral@igalia.com> +Link: https://patchwork.freedesktop.org/patch/msgid/20240923141348.2422499-2-mcanal@igalia.com +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/gpu/drm/v3d/v3d_mmu.c | 29 ++++++++++------------------- + 1 file changed, 10 insertions(+), 19 deletions(-) + +diff --git a/drivers/gpu/drm/v3d/v3d_mmu.c b/drivers/gpu/drm/v3d/v3d_mmu.c +index 14f3af40d6f6d..e36ec3343b06e 100644 +--- a/drivers/gpu/drm/v3d/v3d_mmu.c ++++ b/drivers/gpu/drm/v3d/v3d_mmu.c +@@ -32,32 +32,23 @@ static int v3d_mmu_flush_all(struct v3d_dev *v3d) + { + int ret; + +- /* Make sure that another flush isn't already running when we +- * start this one. +- */ +- ret = wait_for(!(V3D_READ(V3D_MMU_CTL) & +- V3D_MMU_CTL_TLB_CLEARING), 100); +- if (ret) +- dev_err(v3d->drm.dev, "TLB clear wait idle pre-wait failed\n"); +- +- V3D_WRITE(V3D_MMU_CTL, V3D_READ(V3D_MMU_CTL) | +- V3D_MMU_CTL_TLB_CLEAR); +- +- V3D_WRITE(V3D_MMUC_CONTROL, +- V3D_MMUC_CONTROL_FLUSH | ++ V3D_WRITE(V3D_MMUC_CONTROL, V3D_MMUC_CONTROL_FLUSH | + V3D_MMUC_CONTROL_ENABLE); + +- ret = wait_for(!(V3D_READ(V3D_MMU_CTL) & +- V3D_MMU_CTL_TLB_CLEARING), 100); ++ ret = wait_for(!(V3D_READ(V3D_MMUC_CONTROL) & ++ V3D_MMUC_CONTROL_FLUSHING), 100); + if (ret) { +- dev_err(v3d->drm.dev, "TLB clear wait idle failed\n"); ++ dev_err(v3d->drm.dev, "MMUC flush wait idle failed\n"); + return ret; + } + +- ret = wait_for(!(V3D_READ(V3D_MMUC_CONTROL) & +- V3D_MMUC_CONTROL_FLUSHING), 100); ++ V3D_WRITE(V3D_MMU_CTL, V3D_READ(V3D_MMU_CTL) | ++ V3D_MMU_CTL_TLB_CLEAR); ++ ++ ret = wait_for(!(V3D_READ(V3D_MMU_CTL) & ++ V3D_MMU_CTL_TLB_CLEARING), 100); + if (ret) +- dev_err(v3d->drm.dev, "MMUC flush wait idle failed\n"); ++ dev_err(v3d->drm.dev, "MMU TLB clear wait idle failed\n"); + + return ret; + } +-- +2.43.0 + diff --git a/queue-6.12/drm-v3d-appease-lockdep-while-updating-gpu-stats.patch b/queue-6.12/drm-v3d-appease-lockdep-while-updating-gpu-stats.patch new file mode 100644 index 00000000000..7f5b40b849d --- /dev/null +++ b/queue-6.12/drm-v3d-appease-lockdep-while-updating-gpu-stats.patch @@ -0,0 +1,162 @@ +From 5d36f3399ca2880e5f8350d220887ecd2ca52a42 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Tue, 13 Aug 2024 11:25:05 +0100 +Subject: drm/v3d: Appease lockdep while updating GPU stats +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Tvrtko Ursulin <tvrtko.ursulin@igalia.com> + +[ Upstream commit 06c3c406850e5495bb56ccf624d0c9477e1ba901 ] + +Lockdep thinks our seqcount_t usage is unsafe because the update path can +be both from irq and worker context: + + [ ] ================================ + [ ] WARNING: inconsistent lock state + [ ] 6.10.3-v8-16k-numa #159 Tainted: G WC + [ ] -------------------------------- + [ ] inconsistent {HARDIRQ-ON-W} -> {IN-HARDIRQ-W} usage. + [ ] swapper/0/0 [HC1[1]:SC0[0]:HE0:SE1] takes: + [ ] ffff80003d7c08d0 (&v3d_priv->stats[i].lock){?.+.}-{0:0}, at: v3d_irq+0xc8/0x660 [v3d] + [ ] {HARDIRQ-ON-W} state was registered at: + [ ] lock_acquire+0x1f8/0x328 + [ ] v3d_job_start_stats.isra.0+0xd8/0x218 [v3d] + [ ] v3d_bin_job_run+0x23c/0x388 [v3d] + [ ] drm_sched_run_job_work+0x520/0x6d0 [gpu_sched] + [ ] process_one_work+0x62c/0xb48 + [ ] worker_thread+0x468/0x5b0 + [ ] kthread+0x1c4/0x1e0 + [ ] ret_from_fork+0x10/0x20 + [ ] irq event stamp: 337094 + [ ] hardirqs last enabled at (337093): [<ffffc0008144ce7c>] default_idle_call+0x11c/0x140 + [ ] hardirqs last disabled at (337094): [<ffffc0008144a354>] el1_interrupt+0x24/0x58 + [ ] softirqs last enabled at (337082): [<ffffc00080061d90>] handle_softirqs+0x4e0/0x538 + [ ] softirqs last disabled at (337073): [<ffffc00080010364>] __do_softirq+0x1c/0x28 + [ ] + other info that might help us debug this: + [ ] Possible unsafe locking scenario: + + [ ] CPU0 + [ ] ---- + [ ] lock(&v3d_priv->stats[i].lock); + [ ] <Interrupt> + [ ] lock(&v3d_priv->stats[i].lock); + [ ] + *** DEADLOCK *** + + [ ] no locks held by swapper/0/0. + [ ] + stack backtrace: + [ ] CPU: 0 PID: 0 Comm: swapper/0 Tainted: G WC 6.10.3-v8-16k-numa #159 + [ ] Hardware name: Raspberry Pi 5 Model B Rev 1.0 (DT) + [ ] Call trace: + [ ] dump_backtrace+0x170/0x1b8 + [ ] show_stack+0x20/0x38 + [ ] dump_stack_lvl+0xb4/0xd0 + [ ] dump_stack+0x18/0x28 + [ ] print_usage_bug+0x3cc/0x3f0 + [ ] mark_lock+0x4d0/0x968 + [ ] __lock_acquire+0x784/0x18c8 + [ ] lock_acquire+0x1f8/0x328 + [ ] v3d_job_update_stats+0xec/0x2e0 [v3d] + [ ] v3d_irq+0xc8/0x660 [v3d] + [ ] __handle_irq_event_percpu+0x1f8/0x488 + [ ] handle_irq_event+0x88/0x128 + [ ] handle_fasteoi_irq+0x298/0x408 + [ ] generic_handle_domain_irq+0x50/0x78 + +But it is a false positive because all the queue-stats pairs have their +own lock and jobs are also one at a time. + +Nevertheless we can appease lockdep by disabling local interrupts to make +it see lock usage is consistent. + +Cc: Maíra Canal <mcanal@igalia.com> +Fixes: 6abe93b621ab ("drm/v3d: Fix race-condition between sysfs/fdinfo and interrupt handler") +Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@igalia.com> +Signed-off-by: Maíra Canal <mcanal@igalia.com> +Link: https://patchwork.freedesktop.org/patch/msgid/20240813102505.80512-2-tursulin@igalia.com +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/gpu/drm/v3d/v3d_sched.c | 46 +++++++++++++++++++++++++++++---- + 1 file changed, 41 insertions(+), 5 deletions(-) + +diff --git a/drivers/gpu/drm/v3d/v3d_sched.c b/drivers/gpu/drm/v3d/v3d_sched.c +index 08d2a27395828..4f935f1d50a94 100644 +--- a/drivers/gpu/drm/v3d/v3d_sched.c ++++ b/drivers/gpu/drm/v3d/v3d_sched.c +@@ -135,8 +135,31 @@ v3d_job_start_stats(struct v3d_job *job, enum v3d_queue queue) + struct v3d_stats *global_stats = &v3d->queue[queue].stats; + struct v3d_stats *local_stats = &file->stats[queue]; + u64 now = local_clock(); +- +- preempt_disable(); ++ unsigned long flags; ++ ++ /* ++ * We only need to disable local interrupts to appease lockdep who ++ * otherwise would think v3d_job_start_stats vs v3d_stats_update has an ++ * unsafe in-irq vs no-irq-off usage problem. This is a false positive ++ * because all the locks are per queue and stats type, and all jobs are ++ * completely one at a time serialised. More specifically: ++ * ++ * 1. Locks for GPU queues are updated from interrupt handlers under a ++ * spin lock and started here with preemption disabled. ++ * ++ * 2. Locks for CPU queues are updated from the worker with preemption ++ * disabled and equally started here with preemption disabled. ++ * ++ * Therefore both are consistent. ++ * ++ * 3. Because next job can only be queued after the previous one has ++ * been signaled, and locks are per queue, there is also no scope for ++ * the start part to race with the update part. ++ */ ++ if (IS_ENABLED(CONFIG_LOCKDEP)) ++ local_irq_save(flags); ++ else ++ preempt_disable(); + + write_seqcount_begin(&local_stats->lock); + local_stats->start_ns = now; +@@ -146,7 +169,10 @@ v3d_job_start_stats(struct v3d_job *job, enum v3d_queue queue) + global_stats->start_ns = now; + write_seqcount_end(&global_stats->lock); + +- preempt_enable(); ++ if (IS_ENABLED(CONFIG_LOCKDEP)) ++ local_irq_restore(flags); ++ else ++ preempt_enable(); + } + + static void +@@ -167,11 +193,21 @@ v3d_job_update_stats(struct v3d_job *job, enum v3d_queue queue) + struct v3d_stats *global_stats = &v3d->queue[queue].stats; + struct v3d_stats *local_stats = &file->stats[queue]; + u64 now = local_clock(); ++ unsigned long flags; ++ ++ /* See comment in v3d_job_start_stats() */ ++ if (IS_ENABLED(CONFIG_LOCKDEP)) ++ local_irq_save(flags); ++ else ++ preempt_disable(); + +- preempt_disable(); + v3d_stats_update(local_stats, now); + v3d_stats_update(global_stats, now); +- preempt_enable(); ++ ++ if (IS_ENABLED(CONFIG_LOCKDEP)) ++ local_irq_restore(flags); ++ else ++ preempt_enable(); + } + + static struct dma_fence *v3d_bin_job_run(struct drm_sched_job *sched_job) +-- +2.43.0 + diff --git a/queue-6.12/drm-v3d-flush-the-mmu-before-we-supply-more-memory-t.patch b/queue-6.12/drm-v3d-flush-the-mmu-before-we-supply-more-memory-t.patch new file mode 100644 index 00000000000..e20d5029bb3 --- /dev/null +++ b/queue-6.12/drm-v3d-flush-the-mmu-before-we-supply-more-memory-t.patch @@ -0,0 +1,68 @@ +From b3260b30c9db411d6321dce3a7840f52c8be3803 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Mon, 23 Sep 2024 10:55:06 -0300 +Subject: drm/v3d: Flush the MMU before we supply more memory to the binner +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Maíra Canal <mcanal@igalia.com> + +[ Upstream commit d2fb8811108b2c1285c56f4fba4fff8fe3525593 ] + +We must ensure that the MMU is flushed before we supply more memory to +the binner, otherwise we might end up with invalid MMU accesses by the +GPU. + +Fixes: 57692c94dcbe ("drm/v3d: Introduce a new DRM driver for Broadcom V3D V3.x+") +Signed-off-by: Maíra Canal <mcanal@igalia.com> +Reviewed-by: Iago Toral Quiroga <itoral@igalia.com> +Link: https://patchwork.freedesktop.org/patch/msgid/20240923141348.2422499-3-mcanal@igalia.com +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/gpu/drm/v3d/v3d_drv.h | 1 + + drivers/gpu/drm/v3d/v3d_irq.c | 2 ++ + drivers/gpu/drm/v3d/v3d_mmu.c | 2 +- + 3 files changed, 4 insertions(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/v3d/v3d_drv.h b/drivers/gpu/drm/v3d/v3d_drv.h +index cf4b23369dc44..75b4725d49c7e 100644 +--- a/drivers/gpu/drm/v3d/v3d_drv.h ++++ b/drivers/gpu/drm/v3d/v3d_drv.h +@@ -553,6 +553,7 @@ void v3d_irq_disable(struct v3d_dev *v3d); + void v3d_irq_reset(struct v3d_dev *v3d); + + /* v3d_mmu.c */ ++int v3d_mmu_flush_all(struct v3d_dev *v3d); + int v3d_mmu_set_page_table(struct v3d_dev *v3d); + void v3d_mmu_insert_ptes(struct v3d_bo *bo); + void v3d_mmu_remove_ptes(struct v3d_bo *bo); +diff --git a/drivers/gpu/drm/v3d/v3d_irq.c b/drivers/gpu/drm/v3d/v3d_irq.c +index d469bda52c1a5..20bf33702c3c4 100644 +--- a/drivers/gpu/drm/v3d/v3d_irq.c ++++ b/drivers/gpu/drm/v3d/v3d_irq.c +@@ -70,6 +70,8 @@ v3d_overflow_mem_work(struct work_struct *work) + list_add_tail(&bo->unref_head, &v3d->bin_job->render->unref_list); + spin_unlock_irqrestore(&v3d->job_lock, irqflags); + ++ v3d_mmu_flush_all(v3d); ++ + V3D_CORE_WRITE(0, V3D_PTB_BPOA, bo->node.start << V3D_MMU_PAGE_SHIFT); + V3D_CORE_WRITE(0, V3D_PTB_BPOS, obj->size); + +diff --git a/drivers/gpu/drm/v3d/v3d_mmu.c b/drivers/gpu/drm/v3d/v3d_mmu.c +index e36ec3343b06e..5bb7821c0243c 100644 +--- a/drivers/gpu/drm/v3d/v3d_mmu.c ++++ b/drivers/gpu/drm/v3d/v3d_mmu.c +@@ -28,7 +28,7 @@ + #define V3D_PTE_WRITEABLE BIT(29) + #define V3D_PTE_VALID BIT(28) + +-static int v3d_mmu_flush_all(struct v3d_dev *v3d) ++int v3d_mmu_flush_all(struct v3d_dev *v3d) + { + int ret; + +-- +2.43.0 + diff --git a/queue-6.12/drm-vc4-correct-generation-check-in-vc4_hvs_lut_load.patch b/queue-6.12/drm-vc4-correct-generation-check-in-vc4_hvs_lut_load.patch new file mode 100644 index 00000000000..ac579f2beba --- /dev/null +++ b/queue-6.12/drm-vc4-correct-generation-check-in-vc4_hvs_lut_load.patch @@ -0,0 +1,47 @@ +From b2cbe3bb6220be2fda9135a83bc46556d1e76141 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Tue, 8 Oct 2024 17:44:36 +0100 +Subject: drm/vc4: Correct generation check in vc4_hvs_lut_load +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Dave Stevenson <dave.stevenson@raspberrypi.com> + +[ Upstream commit 42aa18d1c3e7762bcebd89a5857ed7774e669d92 ] + +Commit 24c5ed3ddf27 ("drm/vc4: Introduce generation number enum") +incorrectly swapped a check of hvs->vc4->is_vc5 to +hvs->vc4->gen == VC4_GEN_4 in vc4_hvs_lut_load, hence breaking +loading the gamma look up table on Pi0-3. + +Correct that conditional. + +Fixes: 24c5ed3ddf27 ("drm/vc4: Introduce generation number enum") +Reported-by: Marek Szyprowski <m.szyprowski@samsung.com> +Closes: https://lore.kernel.org/dri-devel/37051126-3921-4afe-a936-5f828bff5752@samsung.com/ +Tested-by: Marek Szyprowski <m.szyprowski@samsung.com> +Reviewed-by: Maíra Canal <mcanal@igalia.com> +Link: https://patchwork.freedesktop.org/patch/msgid/20241008-drm-vc4-fixes-v1-3-9d0396ca9f42@raspberrypi.com +Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/gpu/drm/vc4/vc4_hvs.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/vc4/vc4_hvs.c b/drivers/gpu/drm/vc4/vc4_hvs.c +index f30022a360a8a..863539e1f7e04 100644 +--- a/drivers/gpu/drm/vc4/vc4_hvs.c ++++ b/drivers/gpu/drm/vc4/vc4_hvs.c +@@ -224,7 +224,7 @@ static void vc4_hvs_lut_load(struct vc4_hvs *hvs, + if (!drm_dev_enter(drm, &idx)) + return; + +- if (hvs->vc4->gen == VC4_GEN_4) ++ if (hvs->vc4->gen != VC4_GEN_4) + goto exit; + + /* The LUT memory is laid out with each HVS channel in order, +-- +2.43.0 + diff --git a/queue-6.12/drm-vc4-hdmi-avoid-hang-with-debug-registers-when-su.patch b/queue-6.12/drm-vc4-hdmi-avoid-hang-with-debug-registers-when-su.patch new file mode 100644 index 00000000000..d98bc03bb7e --- /dev/null +++ b/queue-6.12/drm-vc4-hdmi-avoid-hang-with-debug-registers-when-su.patch @@ -0,0 +1,53 @@ +From 80d4353188b6b0b7079e0e00fe9124c12e2ec0af Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Fri, 21 Jun 2024 16:20:40 +0100 +Subject: drm/vc4: hdmi: Avoid hang with debug registers when suspended + +From: Dom Cobley <popcornmix@gmail.com> + +[ Upstream commit 223ee2567a55e4f80315c768d2969e6a3b9fb23d ] + +Trying to read /sys/kernel/debug/dri/1/hdmi1_regs +when the hdmi is disconnected results in a fatal system hang. + +This is due to the pm suspend code disabling the dvp clock. +That is just a gate of the 108MHz clock in DVP_HT_RPI_MISC_CONFIG, +which results in accesses hanging AXI bus. + +Protect against this. + +Fixes: 25eb441d55d4 ("drm/vc4: hdmi: Add all the vc5 HDMI registers into the debugfs dumps") +Signed-off-by: Dom Cobley <popcornmix@gmail.com> +Reviewed-by: Maxime Ripard <mripard@kernel.org> +Link: https://patchwork.freedesktop.org/patch/msgid/20240621152055.4180873-17-dave.stevenson@raspberrypi.com +Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/gpu/drm/vc4/vc4_hdmi.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c +index 6611ab7c26a63..6c2215068c537 100644 +--- a/drivers/gpu/drm/vc4/vc4_hdmi.c ++++ b/drivers/gpu/drm/vc4/vc4_hdmi.c +@@ -147,6 +147,8 @@ static int vc4_hdmi_debugfs_regs(struct seq_file *m, void *unused) + if (!drm_dev_enter(drm, &idx)) + return -ENODEV; + ++ WARN_ON(pm_runtime_resume_and_get(&vc4_hdmi->pdev->dev)); ++ + drm_print_regset32(&p, &vc4_hdmi->hdmi_regset); + drm_print_regset32(&p, &vc4_hdmi->hd_regset); + drm_print_regset32(&p, &vc4_hdmi->cec_regset); +@@ -156,6 +158,8 @@ static int vc4_hdmi_debugfs_regs(struct seq_file *m, void *unused) + drm_print_regset32(&p, &vc4_hdmi->ram_regset); + drm_print_regset32(&p, &vc4_hdmi->rm_regset); + ++ pm_runtime_put(&vc4_hdmi->pdev->dev); ++ + drm_dev_exit(idx); + + return 0; +-- +2.43.0 + diff --git a/queue-6.12/drm-vc4-hdmi-increase-audio-mai-fifo-dreq-threshold.patch b/queue-6.12/drm-vc4-hdmi-increase-audio-mai-fifo-dreq-threshold.patch new file mode 100644 index 00000000000..ae304399bb8 --- /dev/null +++ b/queue-6.12/drm-vc4-hdmi-increase-audio-mai-fifo-dreq-threshold.patch @@ -0,0 +1,64 @@ +From 8afa5b53e9881683b5c245a9c0083d12c7d4d99a Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Fri, 21 Jun 2024 16:20:31 +0100 +Subject: drm/vc4: hdmi: Increase audio MAI fifo dreq threshold + +From: Dom Cobley <popcornmix@gmail.com> + +[ Upstream commit 59f8b2b7fb8e460881d21c7d5b32604993973879 ] + +Now we wait for write responses and have a burst +size of 4, we can set the fifo threshold much higher. + +Set it to 28 (of the 32 entry size) to keep fifo +fuller and reduce chance of underflow. + +Signed-off-by: Dom Cobley <popcornmix@gmail.com> +Reviewed-by: Maxime Ripard <mripard@kernel.org> +Link: https://patchwork.freedesktop.org/patch/msgid/20240621152055.4180873-8-dave.stevenson@raspberrypi.com +Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com> +Stable-dep-of: cf1c87d978d4 ("drm/vc4: Match drm_dev_enter and exit calls in vc4_hvs_lut_load") +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/gpu/drm/vc4/vc4_hdmi.c | 18 +++++++++++++----- + 1 file changed, 13 insertions(+), 5 deletions(-) + +diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c +index 6c2215068c537..0117c5495b893 100644 +--- a/drivers/gpu/drm/vc4/vc4_hdmi.c ++++ b/drivers/gpu/drm/vc4/vc4_hdmi.c +@@ -2051,6 +2051,7 @@ static int vc4_hdmi_audio_prepare(struct device *dev, void *data, + struct vc4_hdmi *vc4_hdmi = dev_get_drvdata(dev); + struct drm_device *drm = vc4_hdmi->connector.dev; + struct drm_connector *connector = &vc4_hdmi->connector; ++ struct vc4_dev *vc4 = to_vc4_dev(drm); + unsigned int sample_rate = params->sample_rate; + unsigned int channels = params->channels; + unsigned long flags; +@@ -2108,11 +2109,18 @@ static int vc4_hdmi_audio_prepare(struct device *dev, void *data, + VC4_HDMI_AUDIO_PACKET_CEA_MASK); + + /* Set the MAI threshold */ +- HDMI_WRITE(HDMI_MAI_THR, +- VC4_SET_FIELD(0x08, VC4_HD_MAI_THR_PANICHIGH) | +- VC4_SET_FIELD(0x08, VC4_HD_MAI_THR_PANICLOW) | +- VC4_SET_FIELD(0x06, VC4_HD_MAI_THR_DREQHIGH) | +- VC4_SET_FIELD(0x08, VC4_HD_MAI_THR_DREQLOW)); ++ if (vc4->is_vc5) ++ HDMI_WRITE(HDMI_MAI_THR, ++ VC4_SET_FIELD(0x10, VC4_HD_MAI_THR_PANICHIGH) | ++ VC4_SET_FIELD(0x10, VC4_HD_MAI_THR_PANICLOW) | ++ VC4_SET_FIELD(0x1c, VC4_HD_MAI_THR_DREQHIGH) | ++ VC4_SET_FIELD(0x1c, VC4_HD_MAI_THR_DREQLOW)); ++ else ++ HDMI_WRITE(HDMI_MAI_THR, ++ VC4_SET_FIELD(0x8, VC4_HD_MAI_THR_PANICHIGH) | ++ VC4_SET_FIELD(0x8, VC4_HD_MAI_THR_PANICLOW) | ++ VC4_SET_FIELD(0x6, VC4_HD_MAI_THR_DREQHIGH) | ++ VC4_SET_FIELD(0x8, VC4_HD_MAI_THR_DREQLOW)); + + HDMI_WRITE(HDMI_MAI_CONFIG, + VC4_HDMI_MAI_CONFIG_BIT_REVERSE | +-- +2.43.0 + diff --git a/queue-6.12/drm-vc4-hvs-correct-logic-on-stopping-an-hvs-channel.patch b/queue-6.12/drm-vc4-hvs-correct-logic-on-stopping-an-hvs-channel.patch new file mode 100644 index 00000000000..4c036a31ee8 --- /dev/null +++ b/queue-6.12/drm-vc4-hvs-correct-logic-on-stopping-an-hvs-channel.patch @@ -0,0 +1,55 @@ +From 661b76f812d1137e10ecf53ba1e6ddcc9e89fdaf Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Fri, 21 Jun 2024 16:20:55 +0100 +Subject: drm/vc4: hvs: Correct logic on stopping an HVS channel + +From: Dave Stevenson <dave.stevenson@raspberrypi.com> + +[ Upstream commit 7ab6512e7942889c0962588355cb92424a690be6 ] + +When factoring out __vc4_hvs_stop_channel, the logic got inverted from + if (condition) + // stop channel +to + if (condition) + goto out + //stop channel + out: +and also changed the exact register writes used to stop the channel. + +Correct the logic so that the channel is actually stopped, and revert +to the original register writes. + +Fixes: 6d01a106b4c8 ("drm/vc4: crtc: Move HVS init and close to a function") +Reviewed-by: Maxime Ripard <mripard@kernel.org> +Link: https://patchwork.freedesktop.org/patch/msgid/20240621152055.4180873-32-dave.stevenson@raspberrypi.com +Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/gpu/drm/vc4/vc4_hvs.c | 8 +++----- + 1 file changed, 3 insertions(+), 5 deletions(-) + +diff --git a/drivers/gpu/drm/vc4/vc4_hvs.c b/drivers/gpu/drm/vc4/vc4_hvs.c +index 14415943a1157..1d011fa8a7eac 100644 +--- a/drivers/gpu/drm/vc4/vc4_hvs.c ++++ b/drivers/gpu/drm/vc4/vc4_hvs.c +@@ -420,13 +420,11 @@ void vc4_hvs_stop_channel(struct vc4_hvs *hvs, unsigned int chan) + if (!drm_dev_enter(drm, &idx)) + return; + +- if (HVS_READ(SCALER_DISPCTRLX(chan)) & SCALER_DISPCTRLX_ENABLE) ++ if (!(HVS_READ(SCALER_DISPCTRLX(chan)) & SCALER_DISPCTRLX_ENABLE)) + goto out; + +- HVS_WRITE(SCALER_DISPCTRLX(chan), +- HVS_READ(SCALER_DISPCTRLX(chan)) | SCALER_DISPCTRLX_RESET); +- HVS_WRITE(SCALER_DISPCTRLX(chan), +- HVS_READ(SCALER_DISPCTRLX(chan)) & ~SCALER_DISPCTRLX_ENABLE); ++ HVS_WRITE(SCALER_DISPCTRLX(chan), SCALER_DISPCTRLX_RESET); ++ HVS_WRITE(SCALER_DISPCTRLX(chan), 0); + + /* Once we leave, the scaler should be disabled and its fifo empty. */ + WARN_ON_ONCE(HVS_READ(SCALER_DISPCTRLX(chan)) & SCALER_DISPCTRLX_RESET); +-- +2.43.0 + diff --git a/queue-6.12/drm-vc4-hvs-don-t-write-gamma-luts-on-2711.patch b/queue-6.12/drm-vc4-hvs-don-t-write-gamma-luts-on-2711.patch new file mode 100644 index 00000000000..59f31e9a050 --- /dev/null +++ b/queue-6.12/drm-vc4-hvs-don-t-write-gamma-luts-on-2711.patch @@ -0,0 +1,41 @@ +From 490eb5d5b036dd78b0a092c4d5868607b8909b55 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Fri, 21 Jun 2024 16:20:38 +0100 +Subject: drm/vc4: hvs: Don't write gamma luts on 2711 + +From: Dave Stevenson <dave.stevenson@raspberrypi.com> + +[ Upstream commit 52efe364d1968ee3e3ed45eb44eb924b63635315 ] + +The gamma block has changed in 2711, therefore writing the lut +in vc4_hvs_lut_load is incorrect. + +Whilst the gamma property isn't created for 2711, it is called +from vc4_hvs_init_channel, so abort if attempted. + +Fixes: c54619b0bfb3 ("drm/vc4: Add support for the BCM2711 HVS5") +Reviewed-by: Maxime Ripard <mripard@kernel.org> +Link: https://patchwork.freedesktop.org/patch/msgid/20240621152055.4180873-15-dave.stevenson@raspberrypi.com +Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/gpu/drm/vc4/vc4_hvs.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/gpu/drm/vc4/vc4_hvs.c b/drivers/gpu/drm/vc4/vc4_hvs.c +index 2a835a5cff9dd..ac112dc3d592d 100644 +--- a/drivers/gpu/drm/vc4/vc4_hvs.c ++++ b/drivers/gpu/drm/vc4/vc4_hvs.c +@@ -222,6 +222,9 @@ static void vc4_hvs_lut_load(struct vc4_hvs *hvs, + if (!drm_dev_enter(drm, &idx)) + return; + ++ if (hvs->vc4->is_vc5) ++ return; ++ + /* The LUT memory is laid out with each HVS channel in order, + * each of which takes 256 writes for R, 256 for G, then 256 + * for B. +-- +2.43.0 + diff --git a/queue-6.12/drm-vc4-hvs-fix-dlist-debug-not-resetting-the-next-e.patch b/queue-6.12/drm-vc4-hvs-fix-dlist-debug-not-resetting-the-next-e.patch new file mode 100644 index 00000000000..59c8a1dc8a2 --- /dev/null +++ b/queue-6.12/drm-vc4-hvs-fix-dlist-debug-not-resetting-the-next-e.patch @@ -0,0 +1,46 @@ +From 2137be6d184443a99ac3585a0184bbe6866b4c59 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Fri, 21 Jun 2024 16:20:41 +0100 +Subject: drm/vc4: hvs: Fix dlist debug not resetting the next entry pointer + +From: Dave Stevenson <dave.stevenson@raspberrypi.com> + +[ Upstream commit 6d5f76e0544b04ec5bdd2a09c19d90aeeb2cd479 ] + +The debug function to display the dlists didn't reset next_entry_start +when starting each display, so resulting in not stopping the +list at the correct place. + +Fixes: c6dac00340fc ("drm/vc4: hvs: Add debugfs node that dumps the current display lists") +Reviewed-by: Maxime Ripard <mripard@kernel.org> +Link: https://patchwork.freedesktop.org/patch/msgid/20240621152055.4180873-18-dave.stevenson@raspberrypi.com +Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/gpu/drm/vc4/vc4_hvs.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/vc4/vc4_hvs.c b/drivers/gpu/drm/vc4/vc4_hvs.c +index ac112dc3d592d..2cd9ad9c031c1 100644 +--- a/drivers/gpu/drm/vc4/vc4_hvs.c ++++ b/drivers/gpu/drm/vc4/vc4_hvs.c +@@ -110,7 +110,7 @@ static int vc4_hvs_debugfs_dlist(struct seq_file *m, void *data) + struct vc4_dev *vc4 = to_vc4_dev(dev); + struct vc4_hvs *hvs = vc4->hvs; + struct drm_printer p = drm_seq_file_printer(m); +- unsigned int next_entry_start = 0; ++ unsigned int next_entry_start; + unsigned int i, j; + u32 dlist_word, dispstat; + +@@ -124,6 +124,7 @@ static int vc4_hvs_debugfs_dlist(struct seq_file *m, void *data) + } + + drm_printf(&p, "HVS chan %u:\n", i); ++ next_entry_start = 0; + + for (j = HVS_READ(SCALER_DISPLISTX(i)); j < 256; j++) { + dlist_word = readl((u32 __iomem *)vc4->hvs->dlist + j); +-- +2.43.0 + diff --git a/queue-6.12/drm-vc4-hvs-remove-incorrect-limit-from-hvs_dlist-de.patch b/queue-6.12/drm-vc4-hvs-remove-incorrect-limit-from-hvs_dlist-de.patch new file mode 100644 index 00000000000..bd2184186bd --- /dev/null +++ b/queue-6.12/drm-vc4-hvs-remove-incorrect-limit-from-hvs_dlist-de.patch @@ -0,0 +1,74 @@ +From e66d33724f859b6d8ef0df90c927887e6c0adb4d Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Fri, 21 Jun 2024 16:20:42 +0100 +Subject: drm/vc4: hvs: Remove incorrect limit from hvs_dlist debugfs function + +From: Dave Stevenson <dave.stevenson@raspberrypi.com> + +[ Upstream commit d285bb622ebdfaa84f51df3a1abccb87036157ea ] + +The debugfs function to dump dlists aborted at 256 bytes, +when actually the dlist memory is generally significantly +larger but varies based on SoC. + +We already have the correct limit in __vc4_hvs_alloc, so +store it for use in the debugfs dlist function. + +Fixes: c6dac00340fc ("drm/vc4: hvs: Add debugfs node that dumps the current display lists") +Reviewed-by: Maxime Ripard <mripard@kernel.org> +Link: https://patchwork.freedesktop.org/patch/msgid/20240621152055.4180873-19-dave.stevenson@raspberrypi.com +Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/gpu/drm/vc4/vc4_drv.h | 1 + + drivers/gpu/drm/vc4/vc4_hvs.c | 6 ++++-- + 2 files changed, 5 insertions(+), 2 deletions(-) + +diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h +index 08e29fa825635..d463fabf5ecce 100644 +--- a/drivers/gpu/drm/vc4/vc4_drv.h ++++ b/drivers/gpu/drm/vc4/vc4_drv.h +@@ -315,6 +315,7 @@ struct vc4_hvs { + struct platform_device *pdev; + void __iomem *regs; + u32 __iomem *dlist; ++ unsigned int dlist_mem_size; + + struct clk *core_clk; + +diff --git a/drivers/gpu/drm/vc4/vc4_hvs.c b/drivers/gpu/drm/vc4/vc4_hvs.c +index 2cd9ad9c031c1..14415943a1157 100644 +--- a/drivers/gpu/drm/vc4/vc4_hvs.c ++++ b/drivers/gpu/drm/vc4/vc4_hvs.c +@@ -110,6 +110,7 @@ static int vc4_hvs_debugfs_dlist(struct seq_file *m, void *data) + struct vc4_dev *vc4 = to_vc4_dev(dev); + struct vc4_hvs *hvs = vc4->hvs; + struct drm_printer p = drm_seq_file_printer(m); ++ unsigned int dlist_mem_size = hvs->dlist_mem_size; + unsigned int next_entry_start; + unsigned int i, j; + u32 dlist_word, dispstat; +@@ -126,7 +127,7 @@ static int vc4_hvs_debugfs_dlist(struct seq_file *m, void *data) + drm_printf(&p, "HVS chan %u:\n", i); + next_entry_start = 0; + +- for (j = HVS_READ(SCALER_DISPLISTX(i)); j < 256; j++) { ++ for (j = HVS_READ(SCALER_DISPLISTX(i)); j < dlist_mem_size; j++) { + dlist_word = readl((u32 __iomem *)vc4->hvs->dlist + j); + drm_printf(&p, "dlist: %02d: 0x%08x\n", j, + dlist_word); +@@ -804,9 +805,10 @@ struct vc4_hvs *__vc4_hvs_alloc(struct vc4_dev *vc4, struct platform_device *pde + * our 16K), since we don't want to scramble the screen when + * transitioning from the firmware's boot setup to runtime. + */ ++ hvs->dlist_mem_size = (SCALER_DLIST_SIZE >> 2) - HVS_BOOTLOADER_DLIST_END; + drm_mm_init(&hvs->dlist_mm, + HVS_BOOTLOADER_DLIST_END, +- (SCALER_DLIST_SIZE >> 2) - HVS_BOOTLOADER_DLIST_END); ++ hvs->dlist_mem_size); + + /* Set up the HVS LBM memory manager. We could have some more + * complicated data structure that allowed reuse of LBM areas +-- +2.43.0 + diff --git a/queue-6.12/drm-vc4-introduce-generation-number-enum.patch b/queue-6.12/drm-vc4-introduce-generation-number-enum.patch new file mode 100644 index 00000000000..9a63f5f0074 --- /dev/null +++ b/queue-6.12/drm-vc4-introduce-generation-number-enum.patch @@ -0,0 +1,1031 @@ +From 908daa5ae69c60103eb6a11ac67edd183bc96978 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Fri, 21 Jun 2024 16:20:44 +0100 +Subject: drm/vc4: Introduce generation number enum + +From: Maxime Ripard <mripard@kernel.org> + +[ Upstream commit 24c5ed3ddf27313b248900455b0312bd7a9d3554 ] + +With the introduction of the BCM2712 support, we will get yet another +generation of display engine to support. + +The binary check of whether it's VC5 or not thus doesn't work anymore, +especially since some parts of the driver will have changed with BCM2711, +and some others with BCM2712. + +Let's introduce an enum to store the generation the driver is running +on, which should provide more flexibility. + +Signed-off-by: Maxime Ripard <mripard@kernel.org> +Reviewed-by: Maxime Ripard <mripard@kernel.org> +Link: https://patchwork.freedesktop.org/patch/msgid/20240621152055.4180873-21-dave.stevenson@raspberrypi.com +Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com> +Stable-dep-of: cf1c87d978d4 ("drm/vc4: Match drm_dev_enter and exit calls in vc4_hvs_lut_load") +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/gpu/drm/vc4/tests/vc4_mock.c | 12 +++---- + drivers/gpu/drm/vc4/vc4_bo.c | 28 +++++++-------- + drivers/gpu/drm/vc4/vc4_crtc.c | 13 ++++--- + drivers/gpu/drm/vc4/vc4_drv.c | 22 +++++++----- + drivers/gpu/drm/vc4/vc4_drv.h | 7 +++- + drivers/gpu/drm/vc4/vc4_gem.c | 24 ++++++------- + drivers/gpu/drm/vc4/vc4_hdmi.c | 2 +- + drivers/gpu/drm/vc4/vc4_hvs.c | 42 ++++++++++++---------- + drivers/gpu/drm/vc4/vc4_irq.c | 10 +++--- + drivers/gpu/drm/vc4/vc4_kms.c | 14 ++++---- + drivers/gpu/drm/vc4/vc4_perfmon.c | 20 +++++------ + drivers/gpu/drm/vc4/vc4_plane.c | 12 +++---- + drivers/gpu/drm/vc4/vc4_render_cl.c | 2 +- + drivers/gpu/drm/vc4/vc4_v3d.c | 10 +++--- + drivers/gpu/drm/vc4/vc4_validate.c | 8 ++--- + drivers/gpu/drm/vc4/vc4_validate_shaders.c | 2 +- + 16 files changed, 121 insertions(+), 107 deletions(-) + +diff --git a/drivers/gpu/drm/vc4/tests/vc4_mock.c b/drivers/gpu/drm/vc4/tests/vc4_mock.c +index 0731a7d85d7ab..922849dd4b478 100644 +--- a/drivers/gpu/drm/vc4/tests/vc4_mock.c ++++ b/drivers/gpu/drm/vc4/tests/vc4_mock.c +@@ -155,11 +155,11 @@ KUNIT_DEFINE_ACTION_WRAPPER(kunit_action_drm_dev_unregister, + drm_dev_unregister, + struct drm_device *); + +-static struct vc4_dev *__mock_device(struct kunit *test, bool is_vc5) ++static struct vc4_dev *__mock_device(struct kunit *test, enum vc4_gen gen) + { + struct drm_device *drm; +- const struct drm_driver *drv = is_vc5 ? &vc5_drm_driver : &vc4_drm_driver; +- const struct vc4_mock_desc *desc = is_vc5 ? &vc5_mock : &vc4_mock; ++ const struct drm_driver *drv = (gen == VC4_GEN_5) ? &vc5_drm_driver : &vc4_drm_driver; ++ const struct vc4_mock_desc *desc = (gen == VC4_GEN_5) ? &vc5_mock : &vc4_mock; + struct vc4_dev *vc4; + struct device *dev; + int ret; +@@ -173,7 +173,7 @@ static struct vc4_dev *__mock_device(struct kunit *test, bool is_vc5) + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, vc4); + + vc4->dev = dev; +- vc4->is_vc5 = is_vc5; ++ vc4->gen = gen; + + vc4->hvs = __vc4_hvs_alloc(vc4, NULL); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, vc4->hvs); +@@ -198,10 +198,10 @@ static struct vc4_dev *__mock_device(struct kunit *test, bool is_vc5) + + struct vc4_dev *vc4_mock_device(struct kunit *test) + { +- return __mock_device(test, false); ++ return __mock_device(test, VC4_GEN_4); + } + + struct vc4_dev *vc5_mock_device(struct kunit *test) + { +- return __mock_device(test, true); ++ return __mock_device(test, VC4_GEN_5); + } +diff --git a/drivers/gpu/drm/vc4/vc4_bo.c b/drivers/gpu/drm/vc4/vc4_bo.c +index 3f72be7490d5b..2a85d08b19852 100644 +--- a/drivers/gpu/drm/vc4/vc4_bo.c ++++ b/drivers/gpu/drm/vc4/vc4_bo.c +@@ -251,7 +251,7 @@ void vc4_bo_add_to_purgeable_pool(struct vc4_bo *bo) + { + struct vc4_dev *vc4 = to_vc4_dev(bo->base.base.dev); + +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return; + + mutex_lock(&vc4->purgeable.lock); +@@ -265,7 +265,7 @@ static void vc4_bo_remove_from_purgeable_pool_locked(struct vc4_bo *bo) + { + struct vc4_dev *vc4 = to_vc4_dev(bo->base.base.dev); + +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return; + + /* list_del_init() is used here because the caller might release +@@ -396,7 +396,7 @@ struct drm_gem_object *vc4_create_object(struct drm_device *dev, size_t size) + struct vc4_dev *vc4 = to_vc4_dev(dev); + struct vc4_bo *bo; + +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return ERR_PTR(-ENODEV); + + bo = kzalloc(sizeof(*bo), GFP_KERNEL); +@@ -427,7 +427,7 @@ struct vc4_bo *vc4_bo_create(struct drm_device *dev, size_t unaligned_size, + struct drm_gem_dma_object *dma_obj; + struct vc4_bo *bo; + +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return ERR_PTR(-ENODEV); + + if (size == 0) +@@ -496,7 +496,7 @@ int vc4_bo_dumb_create(struct drm_file *file_priv, + struct vc4_bo *bo = NULL; + int ret; + +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return -ENODEV; + + ret = vc4_dumb_fixup_args(args); +@@ -622,7 +622,7 @@ int vc4_bo_inc_usecnt(struct vc4_bo *bo) + struct vc4_dev *vc4 = to_vc4_dev(bo->base.base.dev); + int ret; + +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return -ENODEV; + + /* Fast path: if the BO is already retained by someone, no need to +@@ -661,7 +661,7 @@ void vc4_bo_dec_usecnt(struct vc4_bo *bo) + { + struct vc4_dev *vc4 = to_vc4_dev(bo->base.base.dev); + +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return; + + /* Fast path: if the BO is still retained by someone, no need to test +@@ -783,7 +783,7 @@ int vc4_create_bo_ioctl(struct drm_device *dev, void *data, + struct vc4_bo *bo = NULL; + int ret; + +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return -ENODEV; + + ret = vc4_grab_bin_bo(vc4, vc4file); +@@ -813,7 +813,7 @@ int vc4_mmap_bo_ioctl(struct drm_device *dev, void *data, + struct drm_vc4_mmap_bo *args = data; + struct drm_gem_object *gem_obj; + +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return -ENODEV; + + gem_obj = drm_gem_object_lookup(file_priv, args->handle); +@@ -839,7 +839,7 @@ vc4_create_shader_bo_ioctl(struct drm_device *dev, void *data, + struct vc4_bo *bo = NULL; + int ret; + +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return -ENODEV; + + if (args->size == 0) +@@ -918,7 +918,7 @@ int vc4_set_tiling_ioctl(struct drm_device *dev, void *data, + struct vc4_bo *bo; + bool t_format; + +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return -ENODEV; + + if (args->flags != 0) +@@ -964,7 +964,7 @@ int vc4_get_tiling_ioctl(struct drm_device *dev, void *data, + struct drm_gem_object *gem_obj; + struct vc4_bo *bo; + +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return -ENODEV; + + if (args->flags != 0 || args->modifier != 0) +@@ -1007,7 +1007,7 @@ int vc4_bo_cache_init(struct drm_device *dev) + int ret; + int i; + +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return -ENODEV; + + /* Create the initial set of BO labels that the kernel will +@@ -1071,7 +1071,7 @@ int vc4_label_bo_ioctl(struct drm_device *dev, void *data, + struct drm_gem_object *gem_obj; + int ret = 0, label; + +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return -ENODEV; + + if (!args->len) +diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c +index 8b5a7e5eb1466..26a7cf7f64651 100644 +--- a/drivers/gpu/drm/vc4/vc4_crtc.c ++++ b/drivers/gpu/drm/vc4/vc4_crtc.c +@@ -263,7 +263,7 @@ static u32 vc4_get_fifo_full_level(struct vc4_crtc *vc4_crtc, u32 format) + * Removing 1 from the FIFO full level however + * seems to completely remove that issue. + */ +- if (!vc4->is_vc5) ++ if (vc4->gen == VC4_GEN_4) + return fifo_len_bytes - 3 * HVS_FIFO_LATENCY_PIX - 1; + + return fifo_len_bytes - 3 * HVS_FIFO_LATENCY_PIX; +@@ -428,7 +428,7 @@ static void vc4_crtc_config_pv(struct drm_crtc *crtc, struct drm_encoder *encode + if (is_dsi) + CRTC_WRITE(PV_HACT_ACT, mode->hdisplay * pixel_rep); + +- if (vc4->is_vc5) ++ if (vc4->gen == VC4_GEN_5) + CRTC_WRITE(PV_MUX_CFG, + VC4_SET_FIELD(PV_MUX_CFG_RGB_PIXEL_MUX_MODE_NO_SWAP, + PV_MUX_CFG_RGB_PIXEL_MUX_MODE)); +@@ -913,7 +913,7 @@ static int vc4_async_set_fence_cb(struct drm_device *dev, + struct dma_fence *fence; + int ret; + +- if (!vc4->is_vc5) { ++ if (vc4->gen == VC4_GEN_4) { + struct vc4_bo *bo = to_vc4_bo(&dma_bo->base); + + return vc4_queue_seqno_cb(dev, &flip_state->cb.seqno, bo->seqno, +@@ -1000,7 +1000,7 @@ static int vc4_async_page_flip(struct drm_crtc *crtc, + struct vc4_bo *bo = to_vc4_bo(&dma_bo->base); + int ret; + +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return -ENODEV; + + /* +@@ -1043,7 +1043,7 @@ int vc4_page_flip(struct drm_crtc *crtc, + struct drm_device *dev = crtc->dev; + struct vc4_dev *vc4 = to_vc4_dev(dev); + +- if (vc4->is_vc5) ++ if (vc4->gen == VC4_GEN_5) + return vc5_async_page_flip(crtc, fb, event, flags); + else + return vc4_async_page_flip(crtc, fb, event, flags); +@@ -1338,9 +1338,8 @@ int __vc4_crtc_init(struct drm_device *drm, + + drm_crtc_helper_add(crtc, crtc_helper_funcs); + +- if (!vc4->is_vc5) { ++ if (vc4->gen == VC4_GEN_4) { + drm_mode_crtc_set_gamma_size(crtc, ARRAY_SIZE(vc4_crtc->lut_r)); +- + drm_crtc_enable_color_mgmt(crtc, 0, false, crtc->gamma_size); + + /* We support CTM, but only for one CRTC at a time. It's therefore +diff --git a/drivers/gpu/drm/vc4/vc4_drv.c b/drivers/gpu/drm/vc4/vc4_drv.c +index c133e96b8aca2..550324819f37f 100644 +--- a/drivers/gpu/drm/vc4/vc4_drv.c ++++ b/drivers/gpu/drm/vc4/vc4_drv.c +@@ -98,7 +98,7 @@ static int vc4_get_param_ioctl(struct drm_device *dev, void *data, + if (args->pad != 0) + return -EINVAL; + +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return -ENODEV; + + if (!vc4->v3d) +@@ -147,7 +147,7 @@ static int vc4_open(struct drm_device *dev, struct drm_file *file) + struct vc4_dev *vc4 = to_vc4_dev(dev); + struct vc4_file *vc4file; + +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return -ENODEV; + + vc4file = kzalloc(sizeof(*vc4file), GFP_KERNEL); +@@ -165,7 +165,7 @@ static void vc4_close(struct drm_device *dev, struct drm_file *file) + struct vc4_dev *vc4 = to_vc4_dev(dev); + struct vc4_file *vc4file = file->driver_priv; + +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return; + + if (vc4file->bin_bo_used) +@@ -291,13 +291,17 @@ static int vc4_drm_bind(struct device *dev) + struct vc4_dev *vc4; + struct device_node *node; + struct drm_crtc *crtc; +- bool is_vc5; ++ enum vc4_gen gen; + int ret = 0; + + dev->coherent_dma_mask = DMA_BIT_MASK(32); + +- is_vc5 = of_device_is_compatible(dev->of_node, "brcm,bcm2711-vc5"); +- if (is_vc5) ++ if (of_device_is_compatible(dev->of_node, "brcm,bcm2711-vc5")) ++ gen = VC4_GEN_5; ++ else ++ gen = VC4_GEN_4; ++ ++ if (gen == VC4_GEN_5) + driver = &vc5_drm_driver; + else + driver = &vc4_drm_driver; +@@ -315,13 +319,13 @@ static int vc4_drm_bind(struct device *dev) + vc4 = devm_drm_dev_alloc(dev, driver, struct vc4_dev, base); + if (IS_ERR(vc4)) + return PTR_ERR(vc4); +- vc4->is_vc5 = is_vc5; ++ vc4->gen = gen; + vc4->dev = dev; + + drm = &vc4->base; + platform_set_drvdata(pdev, drm); + +- if (!is_vc5) { ++ if (gen == VC4_GEN_4) { + ret = drmm_mutex_init(drm, &vc4->bin_bo_lock); + if (ret) + goto err; +@@ -335,7 +339,7 @@ static int vc4_drm_bind(struct device *dev) + if (ret) + goto err; + +- if (!is_vc5) { ++ if (gen == VC4_GEN_4) { + ret = vc4_gem_init(drm); + if (ret) + goto err; +diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h +index d463fabf5ecce..dd452e6a11430 100644 +--- a/drivers/gpu/drm/vc4/vc4_drv.h ++++ b/drivers/gpu/drm/vc4/vc4_drv.h +@@ -80,11 +80,16 @@ struct vc4_perfmon { + u64 counters[] __counted_by(ncounters); + }; + ++enum vc4_gen { ++ VC4_GEN_4, ++ VC4_GEN_5, ++}; ++ + struct vc4_dev { + struct drm_device base; + struct device *dev; + +- bool is_vc5; ++ enum vc4_gen gen; + + unsigned int irq; + +diff --git a/drivers/gpu/drm/vc4/vc4_gem.c b/drivers/gpu/drm/vc4/vc4_gem.c +index 24fb1b57e1dd9..be9c0b72ebe86 100644 +--- a/drivers/gpu/drm/vc4/vc4_gem.c ++++ b/drivers/gpu/drm/vc4/vc4_gem.c +@@ -76,7 +76,7 @@ vc4_get_hang_state_ioctl(struct drm_device *dev, void *data, + u32 i; + int ret = 0; + +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return -ENODEV; + + if (!vc4->v3d) { +@@ -389,7 +389,7 @@ vc4_wait_for_seqno(struct drm_device *dev, uint64_t seqno, uint64_t timeout_ns, + unsigned long timeout_expire; + DEFINE_WAIT(wait); + +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return -ENODEV; + + if (vc4->finished_seqno >= seqno) +@@ -474,7 +474,7 @@ vc4_submit_next_bin_job(struct drm_device *dev) + struct vc4_dev *vc4 = to_vc4_dev(dev); + struct vc4_exec_info *exec; + +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return; + + again: +@@ -522,7 +522,7 @@ vc4_submit_next_render_job(struct drm_device *dev) + if (!exec) + return; + +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return; + + /* A previous RCL may have written to one of our textures, and +@@ -543,7 +543,7 @@ vc4_move_job_to_render(struct drm_device *dev, struct vc4_exec_info *exec) + struct vc4_dev *vc4 = to_vc4_dev(dev); + bool was_empty = list_empty(&vc4->render_job_list); + +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return; + + list_move_tail(&exec->head, &vc4->render_job_list); +@@ -970,7 +970,7 @@ vc4_job_handle_completed(struct vc4_dev *vc4) + unsigned long irqflags; + struct vc4_seqno_cb *cb, *cb_temp; + +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return; + + spin_lock_irqsave(&vc4->job_lock, irqflags); +@@ -1009,7 +1009,7 @@ int vc4_queue_seqno_cb(struct drm_device *dev, + struct vc4_dev *vc4 = to_vc4_dev(dev); + unsigned long irqflags; + +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return -ENODEV; + + cb->func = func; +@@ -1065,7 +1065,7 @@ vc4_wait_seqno_ioctl(struct drm_device *dev, void *data, + struct vc4_dev *vc4 = to_vc4_dev(dev); + struct drm_vc4_wait_seqno *args = data; + +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return -ENODEV; + + return vc4_wait_for_seqno_ioctl_helper(dev, args->seqno, +@@ -1082,7 +1082,7 @@ vc4_wait_bo_ioctl(struct drm_device *dev, void *data, + struct drm_gem_object *gem_obj; + struct vc4_bo *bo; + +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return -ENODEV; + + if (args->pad != 0) +@@ -1131,7 +1131,7 @@ vc4_submit_cl_ioctl(struct drm_device *dev, void *data, + args->shader_rec_size, + args->bo_handle_count); + +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return -ENODEV; + + if (!vc4->v3d) { +@@ -1267,7 +1267,7 @@ int vc4_gem_init(struct drm_device *dev) + struct vc4_dev *vc4 = to_vc4_dev(dev); + int ret; + +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return -ENODEV; + + vc4->dma_fence_context = dma_fence_context_alloc(1); +@@ -1326,7 +1326,7 @@ int vc4_gem_madvise_ioctl(struct drm_device *dev, void *data, + struct vc4_bo *bo; + int ret; + +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return -ENODEV; + + switch (args->madv) { +diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c +index 0117c5495b893..2d7d3e90f3be4 100644 +--- a/drivers/gpu/drm/vc4/vc4_hdmi.c ++++ b/drivers/gpu/drm/vc4/vc4_hdmi.c +@@ -2109,7 +2109,7 @@ static int vc4_hdmi_audio_prepare(struct device *dev, void *data, + VC4_HDMI_AUDIO_PACKET_CEA_MASK); + + /* Set the MAI threshold */ +- if (vc4->is_vc5) ++ if (vc4->gen >= VC4_GEN_5) + HDMI_WRITE(HDMI_MAI_THR, + VC4_SET_FIELD(0x10, VC4_HD_MAI_THR_PANICHIGH) | + VC4_SET_FIELD(0x10, VC4_HD_MAI_THR_PANICLOW) | +diff --git a/drivers/gpu/drm/vc4/vc4_hvs.c b/drivers/gpu/drm/vc4/vc4_hvs.c +index 1d011fa8a7eac..3787c070d15e3 100644 +--- a/drivers/gpu/drm/vc4/vc4_hvs.c ++++ b/drivers/gpu/drm/vc4/vc4_hvs.c +@@ -224,7 +224,7 @@ static void vc4_hvs_lut_load(struct vc4_hvs *hvs, + if (!drm_dev_enter(drm, &idx)) + return; + +- if (hvs->vc4->is_vc5) ++ if (hvs->vc4->gen == VC4_GEN_4) + return; + + /* The LUT memory is laid out with each HVS channel in order, +@@ -296,7 +296,7 @@ int vc4_hvs_get_fifo_from_output(struct vc4_hvs *hvs, unsigned int output) + u32 reg; + int ret; + +- if (!vc4->is_vc5) ++ if (vc4->gen == VC4_GEN_4) + return output; + + /* +@@ -377,7 +377,7 @@ static int vc4_hvs_init_channel(struct vc4_hvs *hvs, struct drm_crtc *crtc, + dispctrl = SCALER_DISPCTRLX_ENABLE; + dispbkgndx = HVS_READ(SCALER_DISPBKGNDX(chan)); + +- if (!vc4->is_vc5) { ++ if (vc4->gen == VC4_GEN_4) { + dispctrl |= VC4_SET_FIELD(mode->hdisplay, + SCALER_DISPCTRLX_WIDTH) | + VC4_SET_FIELD(mode->vdisplay, +@@ -399,7 +399,7 @@ static int vc4_hvs_init_channel(struct vc4_hvs *hvs, struct drm_crtc *crtc, + dispbkgndx &= ~SCALER_DISPBKGND_INTERLACE; + + HVS_WRITE(SCALER_DISPBKGNDX(chan), dispbkgndx | +- ((!vc4->is_vc5) ? SCALER_DISPBKGND_GAMMA : 0) | ++ ((vc4->gen == VC4_GEN_4) ? SCALER_DISPBKGND_GAMMA : 0) | + (interlace ? SCALER_DISPBKGND_INTERLACE : 0)); + + /* Reload the LUT, since the SRAMs would have been disabled if +@@ -671,7 +671,8 @@ void vc4_hvs_atomic_flush(struct drm_crtc *crtc, + + void vc4_hvs_mask_underrun(struct vc4_hvs *hvs, int channel) + { +- struct drm_device *drm = &hvs->vc4->base; ++ struct vc4_dev *vc4 = hvs->vc4; ++ struct drm_device *drm = &vc4->base; + u32 dispctrl; + int idx; + +@@ -679,8 +680,9 @@ void vc4_hvs_mask_underrun(struct vc4_hvs *hvs, int channel) + return; + + dispctrl = HVS_READ(SCALER_DISPCTRL); +- dispctrl &= ~(hvs->vc4->is_vc5 ? SCALER5_DISPCTRL_DSPEISLUR(channel) : +- SCALER_DISPCTRL_DSPEISLUR(channel)); ++ dispctrl &= ~((vc4->gen == VC4_GEN_5) ? ++ SCALER5_DISPCTRL_DSPEISLUR(channel) : ++ SCALER_DISPCTRL_DSPEISLUR(channel)); + + HVS_WRITE(SCALER_DISPCTRL, dispctrl); + +@@ -689,7 +691,8 @@ void vc4_hvs_mask_underrun(struct vc4_hvs *hvs, int channel) + + void vc4_hvs_unmask_underrun(struct vc4_hvs *hvs, int channel) + { +- struct drm_device *drm = &hvs->vc4->base; ++ struct vc4_dev *vc4 = hvs->vc4; ++ struct drm_device *drm = &vc4->base; + u32 dispctrl; + int idx; + +@@ -697,8 +700,9 @@ void vc4_hvs_unmask_underrun(struct vc4_hvs *hvs, int channel) + return; + + dispctrl = HVS_READ(SCALER_DISPCTRL); +- dispctrl |= (hvs->vc4->is_vc5 ? SCALER5_DISPCTRL_DSPEISLUR(channel) : +- SCALER_DISPCTRL_DSPEISLUR(channel)); ++ dispctrl |= ((vc4->gen == VC4_GEN_5) ? ++ SCALER5_DISPCTRL_DSPEISLUR(channel) : ++ SCALER_DISPCTRL_DSPEISLUR(channel)); + + HVS_WRITE(SCALER_DISPSTAT, + SCALER_DISPSTAT_EUFLOW(channel)); +@@ -741,8 +745,10 @@ static irqreturn_t vc4_hvs_irq_handler(int irq, void *data) + control = HVS_READ(SCALER_DISPCTRL); + + for (channel = 0; channel < SCALER_CHANNELS_COUNT; channel++) { +- dspeislur = vc4->is_vc5 ? SCALER5_DISPCTRL_DSPEISLUR(channel) : +- SCALER_DISPCTRL_DSPEISLUR(channel); ++ dspeislur = (vc4->gen == VC4_GEN_5) ? ++ SCALER5_DISPCTRL_DSPEISLUR(channel) : ++ SCALER_DISPCTRL_DSPEISLUR(channel); ++ + /* Interrupt masking is not always honored, so check it here. */ + if (status & SCALER_DISPSTAT_EUFLOW(channel) && + control & dspeislur) { +@@ -770,7 +776,7 @@ int vc4_hvs_debugfs_init(struct drm_minor *minor) + if (!vc4->hvs) + return -ENODEV; + +- if (!vc4->is_vc5) ++ if (vc4->gen == VC4_GEN_4) + debugfs_create_bool("hvs_load_tracker", S_IRUGO | S_IWUSR, + minor->debugfs_root, + &vc4->load_tracker_enabled); +@@ -813,7 +819,7 @@ struct vc4_hvs *__vc4_hvs_alloc(struct vc4_dev *vc4, struct platform_device *pde + * between planes when they don't overlap on the screen, but + * for now we just allocate globally. + */ +- if (!vc4->is_vc5) ++ if (vc4->gen == VC4_GEN_4) + /* 48k words of 2x12-bit pixels */ + drm_mm_init(&hvs->lbm_mm, 0, 48 * 1024); + else +@@ -847,7 +853,7 @@ static int vc4_hvs_bind(struct device *dev, struct device *master, void *data) + hvs->regset.regs = hvs_regs; + hvs->regset.nregs = ARRAY_SIZE(hvs_regs); + +- if (vc4->is_vc5) { ++ if (vc4->gen == VC4_GEN_5) { + struct rpi_firmware *firmware; + struct device_node *node; + unsigned int max_rate; +@@ -885,7 +891,7 @@ static int vc4_hvs_bind(struct device *dev, struct device *master, void *data) + } + } + +- if (!vc4->is_vc5) ++ if (vc4->gen == VC4_GEN_4) + hvs->dlist = hvs->regs + SCALER_DLIST_START; + else + hvs->dlist = hvs->regs + SCALER5_DLIST_START; +@@ -926,7 +932,7 @@ static int vc4_hvs_bind(struct device *dev, struct device *master, void *data) + SCALER_DISPCTRL_DISPEIRQ(1) | + SCALER_DISPCTRL_DISPEIRQ(2); + +- if (!vc4->is_vc5) ++ if (vc4->gen == VC4_GEN_4) + dispctrl &= ~(SCALER_DISPCTRL_DMAEIRQ | + SCALER_DISPCTRL_SLVWREIRQ | + SCALER_DISPCTRL_SLVRDEIRQ | +@@ -970,7 +976,7 @@ static int vc4_hvs_bind(struct device *dev, struct device *master, void *data) + + /* Recompute Composite Output Buffer (COB) allocations for the displays + */ +- if (!vc4->is_vc5) { ++ if (vc4->gen == VC4_GEN_4) { + /* The COB is 20736 pixels, or just over 10 lines at 2048 wide. + * The bottom 2048 pixels are full 32bpp RGBA (intended for the + * TXP composing RGBA to memory), whilst the remainder are only +diff --git a/drivers/gpu/drm/vc4/vc4_irq.c b/drivers/gpu/drm/vc4/vc4_irq.c +index ef93d8e22a35a..968356d1b91df 100644 +--- a/drivers/gpu/drm/vc4/vc4_irq.c ++++ b/drivers/gpu/drm/vc4/vc4_irq.c +@@ -263,7 +263,7 @@ vc4_irq_enable(struct drm_device *dev) + { + struct vc4_dev *vc4 = to_vc4_dev(dev); + +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return; + + if (!vc4->v3d) +@@ -280,7 +280,7 @@ vc4_irq_disable(struct drm_device *dev) + { + struct vc4_dev *vc4 = to_vc4_dev(dev); + +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return; + + if (!vc4->v3d) +@@ -303,7 +303,7 @@ int vc4_irq_install(struct drm_device *dev, int irq) + struct vc4_dev *vc4 = to_vc4_dev(dev); + int ret; + +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return -ENODEV; + + if (irq == IRQ_NOTCONNECTED) +@@ -324,7 +324,7 @@ void vc4_irq_uninstall(struct drm_device *dev) + { + struct vc4_dev *vc4 = to_vc4_dev(dev); + +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return; + + vc4_irq_disable(dev); +@@ -337,7 +337,7 @@ void vc4_irq_reset(struct drm_device *dev) + struct vc4_dev *vc4 = to_vc4_dev(dev); + unsigned long irqflags; + +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return; + + /* Acknowledge any stale IRQs. */ +diff --git a/drivers/gpu/drm/vc4/vc4_kms.c b/drivers/gpu/drm/vc4/vc4_kms.c +index 5495f2a94fa92..bddfcad109501 100644 +--- a/drivers/gpu/drm/vc4/vc4_kms.c ++++ b/drivers/gpu/drm/vc4/vc4_kms.c +@@ -369,7 +369,7 @@ static void vc4_atomic_commit_tail(struct drm_atomic_state *state) + old_hvs_state->fifo_state[channel].pending_commit = NULL; + } + +- if (vc4->is_vc5) { ++ if (vc4->gen == VC4_GEN_5) { + unsigned long state_rate = max(old_hvs_state->core_clock_rate, + new_hvs_state->core_clock_rate); + unsigned long core_rate = clamp_t(unsigned long, state_rate, +@@ -388,7 +388,7 @@ static void vc4_atomic_commit_tail(struct drm_atomic_state *state) + + vc4_ctm_commit(vc4, state); + +- if (vc4->is_vc5) ++ if (vc4->gen == VC4_GEN_5) + vc5_hvs_pv_muxing_commit(vc4, state); + else + vc4_hvs_pv_muxing_commit(vc4, state); +@@ -406,7 +406,7 @@ static void vc4_atomic_commit_tail(struct drm_atomic_state *state) + + drm_atomic_helper_cleanup_planes(dev, state); + +- if (vc4->is_vc5) { ++ if (vc4->gen == VC4_GEN_5) { + unsigned long core_rate = min_t(unsigned long, + hvs->max_core_rate, + new_hvs_state->core_clock_rate); +@@ -461,7 +461,7 @@ static struct drm_framebuffer *vc4_fb_create(struct drm_device *dev, + struct vc4_dev *vc4 = to_vc4_dev(dev); + struct drm_mode_fb_cmd2 mode_cmd_local; + +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return ERR_PTR(-ENODEV); + + /* If the user didn't specify a modifier, use the +@@ -1040,7 +1040,7 @@ int vc4_kms_load(struct drm_device *dev) + * the BCM2711, but the load tracker computations are used for + * the core clock rate calculation. + */ +- if (!vc4->is_vc5) { ++ if (vc4->gen == VC4_GEN_4) { + /* Start with the load tracker enabled. Can be + * disabled through the debugfs load_tracker file. + */ +@@ -1056,7 +1056,7 @@ int vc4_kms_load(struct drm_device *dev) + return ret; + } + +- if (vc4->is_vc5) { ++ if (vc4->gen == VC4_GEN_5) { + dev->mode_config.max_width = 7680; + dev->mode_config.max_height = 7680; + } else { +@@ -1064,7 +1064,7 @@ int vc4_kms_load(struct drm_device *dev) + dev->mode_config.max_height = 2048; + } + +- dev->mode_config.funcs = vc4->is_vc5 ? &vc5_mode_funcs : &vc4_mode_funcs; ++ dev->mode_config.funcs = (vc4->gen > VC4_GEN_4) ? &vc5_mode_funcs : &vc4_mode_funcs; + dev->mode_config.helper_private = &vc4_mode_config_helpers; + dev->mode_config.preferred_depth = 24; + dev->mode_config.async_page_flip = true; +diff --git a/drivers/gpu/drm/vc4/vc4_perfmon.c b/drivers/gpu/drm/vc4/vc4_perfmon.c +index c00a5cc2316d2..e4fda72c19f92 100644 +--- a/drivers/gpu/drm/vc4/vc4_perfmon.c ++++ b/drivers/gpu/drm/vc4/vc4_perfmon.c +@@ -23,7 +23,7 @@ void vc4_perfmon_get(struct vc4_perfmon *perfmon) + return; + + vc4 = perfmon->dev; +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return; + + refcount_inc(&perfmon->refcnt); +@@ -37,7 +37,7 @@ void vc4_perfmon_put(struct vc4_perfmon *perfmon) + return; + + vc4 = perfmon->dev; +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return; + + if (refcount_dec_and_test(&perfmon->refcnt)) +@@ -49,7 +49,7 @@ void vc4_perfmon_start(struct vc4_dev *vc4, struct vc4_perfmon *perfmon) + unsigned int i; + u32 mask; + +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return; + + if (WARN_ON_ONCE(!perfmon || vc4->active_perfmon)) +@@ -69,7 +69,7 @@ void vc4_perfmon_stop(struct vc4_dev *vc4, struct vc4_perfmon *perfmon, + { + unsigned int i; + +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return; + + if (WARN_ON_ONCE(!vc4->active_perfmon || +@@ -90,7 +90,7 @@ struct vc4_perfmon *vc4_perfmon_find(struct vc4_file *vc4file, int id) + struct vc4_dev *vc4 = vc4file->dev; + struct vc4_perfmon *perfmon; + +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return NULL; + + mutex_lock(&vc4file->perfmon.lock); +@@ -105,7 +105,7 @@ void vc4_perfmon_open_file(struct vc4_file *vc4file) + { + struct vc4_dev *vc4 = vc4file->dev; + +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return; + + mutex_init(&vc4file->perfmon.lock); +@@ -131,7 +131,7 @@ void vc4_perfmon_close_file(struct vc4_file *vc4file) + { + struct vc4_dev *vc4 = vc4file->dev; + +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return; + + mutex_lock(&vc4file->perfmon.lock); +@@ -151,7 +151,7 @@ int vc4_perfmon_create_ioctl(struct drm_device *dev, void *data, + unsigned int i; + int ret; + +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return -ENODEV; + + if (!vc4->v3d) { +@@ -205,7 +205,7 @@ int vc4_perfmon_destroy_ioctl(struct drm_device *dev, void *data, + struct drm_vc4_perfmon_destroy *req = data; + struct vc4_perfmon *perfmon; + +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return -ENODEV; + + if (!vc4->v3d) { +@@ -233,7 +233,7 @@ int vc4_perfmon_get_values_ioctl(struct drm_device *dev, void *data, + struct vc4_perfmon *perfmon; + int ret; + +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return -ENODEV; + + if (!vc4->v3d) { +diff --git a/drivers/gpu/drm/vc4/vc4_plane.c b/drivers/gpu/drm/vc4/vc4_plane.c +index 07caf2a47c6ce..866bc46ee6d53 100644 +--- a/drivers/gpu/drm/vc4/vc4_plane.c ++++ b/drivers/gpu/drm/vc4/vc4_plane.c +@@ -587,10 +587,10 @@ static u32 vc4_lbm_size(struct drm_plane_state *state) + } + + /* Align it to 64 or 128 (hvs5) bytes */ +- lbm = roundup(lbm, vc4->is_vc5 ? 128 : 64); ++ lbm = roundup(lbm, vc4->gen == VC4_GEN_5 ? 128 : 64); + + /* Each "word" of the LBM memory contains 2 or 4 (hvs5) pixels */ +- lbm /= vc4->is_vc5 ? 4 : 2; ++ lbm /= vc4->gen == VC4_GEN_5 ? 4 : 2; + + return lbm; + } +@@ -706,7 +706,7 @@ static int vc4_plane_allocate_lbm(struct drm_plane_state *state) + ret = drm_mm_insert_node_generic(&vc4->hvs->lbm_mm, + &vc4_state->lbm, + lbm_size, +- vc4->is_vc5 ? 64 : 32, ++ vc4->gen == VC4_GEN_5 ? 64 : 32, + 0, 0); + spin_unlock_irqrestore(&vc4->hvs->mm_lock, irqflags); + +@@ -1057,7 +1057,7 @@ static int vc4_plane_mode_set(struct drm_plane *plane, + mix_plane_alpha = state->alpha != DRM_BLEND_ALPHA_OPAQUE && + fb->format->has_alpha; + +- if (!vc4->is_vc5) { ++ if (vc4->gen == VC4_GEN_4) { + /* Control word */ + vc4_dlist_write(vc4_state, + SCALER_CTL0_VALID | +@@ -1632,7 +1632,7 @@ struct drm_plane *vc4_plane_init(struct drm_device *dev, + }; + + for (i = 0; i < ARRAY_SIZE(hvs_formats); i++) { +- if (!hvs_formats[i].hvs5_only || vc4->is_vc5) { ++ if (!hvs_formats[i].hvs5_only || vc4->gen == VC4_GEN_5) { + formats[num_formats] = hvs_formats[i].drm; + num_formats++; + } +@@ -1647,7 +1647,7 @@ struct drm_plane *vc4_plane_init(struct drm_device *dev, + return ERR_CAST(vc4_plane); + plane = &vc4_plane->base; + +- if (vc4->is_vc5) ++ if (vc4->gen == VC4_GEN_5) + drm_plane_helper_add(plane, &vc5_plane_helper_funcs); + else + drm_plane_helper_add(plane, &vc4_plane_helper_funcs); +diff --git a/drivers/gpu/drm/vc4/vc4_render_cl.c b/drivers/gpu/drm/vc4/vc4_render_cl.c +index 1bda5010f15a8..ae4ad956f04ff 100644 +--- a/drivers/gpu/drm/vc4/vc4_render_cl.c ++++ b/drivers/gpu/drm/vc4/vc4_render_cl.c +@@ -599,7 +599,7 @@ int vc4_get_rcl(struct drm_device *dev, struct vc4_exec_info *exec) + bool has_bin = args->bin_cl_size != 0; + int ret; + +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return -ENODEV; + + if (args->min_x_tile > args->max_x_tile || +diff --git a/drivers/gpu/drm/vc4/vc4_v3d.c b/drivers/gpu/drm/vc4/vc4_v3d.c +index bf5c4e36c94e4..43f69d74e8761 100644 +--- a/drivers/gpu/drm/vc4/vc4_v3d.c ++++ b/drivers/gpu/drm/vc4/vc4_v3d.c +@@ -127,7 +127,7 @@ static int vc4_v3d_debugfs_ident(struct seq_file *m, void *unused) + int + vc4_v3d_pm_get(struct vc4_dev *vc4) + { +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return -ENODEV; + + mutex_lock(&vc4->power_lock); +@@ -148,7 +148,7 @@ vc4_v3d_pm_get(struct vc4_dev *vc4) + void + vc4_v3d_pm_put(struct vc4_dev *vc4) + { +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return; + + mutex_lock(&vc4->power_lock); +@@ -178,7 +178,7 @@ int vc4_v3d_get_bin_slot(struct vc4_dev *vc4) + uint64_t seqno = 0; + struct vc4_exec_info *exec; + +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return -ENODEV; + + try_again: +@@ -325,7 +325,7 @@ int vc4_v3d_bin_bo_get(struct vc4_dev *vc4, bool *used) + { + int ret = 0; + +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return -ENODEV; + + mutex_lock(&vc4->bin_bo_lock); +@@ -360,7 +360,7 @@ static void bin_bo_release(struct kref *ref) + + void vc4_v3d_bin_bo_put(struct vc4_dev *vc4) + { +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return; + + mutex_lock(&vc4->bin_bo_lock); +diff --git a/drivers/gpu/drm/vc4/vc4_validate.c b/drivers/gpu/drm/vc4/vc4_validate.c +index 0c17284bf6f5b..f3d7fdbe9083c 100644 +--- a/drivers/gpu/drm/vc4/vc4_validate.c ++++ b/drivers/gpu/drm/vc4/vc4_validate.c +@@ -109,7 +109,7 @@ vc4_use_bo(struct vc4_exec_info *exec, uint32_t hindex) + struct drm_gem_dma_object *obj; + struct vc4_bo *bo; + +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return NULL; + + if (hindex >= exec->bo_count) { +@@ -169,7 +169,7 @@ vc4_check_tex_size(struct vc4_exec_info *exec, struct drm_gem_dma_object *fbo, + uint32_t utile_w = utile_width(cpp); + uint32_t utile_h = utile_height(cpp); + +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return false; + + /* The shaded vertex format stores signed 12.4 fixed point +@@ -495,7 +495,7 @@ vc4_validate_bin_cl(struct drm_device *dev, + uint32_t dst_offset = 0; + uint32_t src_offset = 0; + +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return -ENODEV; + + while (src_offset < len) { +@@ -942,7 +942,7 @@ vc4_validate_shader_recs(struct drm_device *dev, + uint32_t i; + int ret = 0; + +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return -ENODEV; + + for (i = 0; i < exec->shader_state_count; i++) { +diff --git a/drivers/gpu/drm/vc4/vc4_validate_shaders.c b/drivers/gpu/drm/vc4/vc4_validate_shaders.c +index 9745f8810eca6..afb1a4d826846 100644 +--- a/drivers/gpu/drm/vc4/vc4_validate_shaders.c ++++ b/drivers/gpu/drm/vc4/vc4_validate_shaders.c +@@ -786,7 +786,7 @@ vc4_validate_shader(struct drm_gem_dma_object *shader_obj) + struct vc4_validated_shader_info *validated_shader = NULL; + struct vc4_shader_validation_state validation_state; + +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return NULL; + + memset(&validation_state, 0, sizeof(validation_state)); +-- +2.43.0 + diff --git a/queue-6.12/drm-vc4-match-drm_dev_enter-and-exit-calls-in-vc4_hv.patch b/queue-6.12/drm-vc4-match-drm_dev_enter-and-exit-calls-in-vc4_hv.patch new file mode 100644 index 00000000000..e97fdceb01f --- /dev/null +++ b/queue-6.12/drm-vc4-match-drm_dev_enter-and-exit-calls-in-vc4_hv.patch @@ -0,0 +1,54 @@ +From 8012e548c2e90ebe2704c95cc053a99d2353ce49 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Tue, 8 Oct 2024 17:44:34 +0100 +Subject: drm/vc4: Match drm_dev_enter and exit calls in vc4_hvs_lut_load +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Dave Stevenson <dave.stevenson@raspberrypi.com> + +[ Upstream commit cf1c87d978d47339a39bfa7a6133ecd3f8f87525 ] + +Commit 52efe364d196 ("drm/vc4: hvs: Don't write gamma luts on 2711") +added a return path to vc4_hvs_lut_load that had called +drm_dev_enter, but not drm_dev_exit. + +Ensure we call drm_dev_exit. + +Fixes: 52efe364d196 ("drm/vc4: hvs: Don't write gamma luts on 2711") +Reported-by: Marek Szyprowski <m.szyprowski@samsung.com> +Closes: https://lore.kernel.org/dri-devel/37051126-3921-4afe-a936-5f828bff5752@samsung.com/ +Tested-by: Marek Szyprowski <m.szyprowski@samsung.com> +Reviewed-by: Maíra Canal <mcanal@igalia.com> +Link: https://patchwork.freedesktop.org/patch/msgid/20241008-drm-vc4-fixes-v1-1-9d0396ca9f42@raspberrypi.com +Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/gpu/drm/vc4/vc4_hvs.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/vc4/vc4_hvs.c b/drivers/gpu/drm/vc4/vc4_hvs.c +index 3787c070d15e3..15e4c888c4afd 100644 +--- a/drivers/gpu/drm/vc4/vc4_hvs.c ++++ b/drivers/gpu/drm/vc4/vc4_hvs.c +@@ -225,7 +225,7 @@ static void vc4_hvs_lut_load(struct vc4_hvs *hvs, + return; + + if (hvs->vc4->gen == VC4_GEN_4) +- return; ++ goto exit; + + /* The LUT memory is laid out with each HVS channel in order, + * each of which takes 256 writes for R, 256 for G, then 256 +@@ -242,6 +242,7 @@ static void vc4_hvs_lut_load(struct vc4_hvs *hvs, + for (i = 0; i < crtc->gamma_size; i++) + HVS_WRITE(SCALER_GAMDATA, vc4_crtc->lut_b[i]); + ++exit: + drm_dev_exit(idx); + } + +-- +2.43.0 + diff --git a/queue-6.12/drm-vc4-match-drm_dev_enter-and-exit-calls-in-vc4_hv.patch-24148 b/queue-6.12/drm-vc4-match-drm_dev_enter-and-exit-calls-in-vc4_hv.patch-24148 new file mode 100644 index 00000000000..780c7ad1852 --- /dev/null +++ b/queue-6.12/drm-vc4-match-drm_dev_enter-and-exit-calls-in-vc4_hv.patch-24148 @@ -0,0 +1,51 @@ +From 0de90dac1c898843bce075199f1cfbfdd85231fa Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Tue, 8 Oct 2024 17:44:35 +0100 +Subject: drm/vc4: Match drm_dev_enter and exit calls in vc4_hvs_atomic_flush +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Dave Stevenson <dave.stevenson@raspberrypi.com> + +[ Upstream commit 6b0bd1b02ea24b10522c92b2503981970b26d1a2 ] + +Commit 92c17d16476c ("drm/vc4: hvs: Ignore atomic_flush if we're disabled") +added a path which returned early without having called drm_dev_exit. + +Ensure all paths call drm_dev_exit. + +Fixes: 92c17d16476c ("drm/vc4: hvs: Ignore atomic_flush if we're disabled") +Tested-by: Marek Szyprowski <m.szyprowski@samsung.com> +Reviewed-by: Maíra Canal <mcanal@igalia.com> +Link: https://patchwork.freedesktop.org/patch/msgid/20241008-drm-vc4-fixes-v1-2-9d0396ca9f42@raspberrypi.com +Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/gpu/drm/vc4/vc4_hvs.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/vc4/vc4_hvs.c b/drivers/gpu/drm/vc4/vc4_hvs.c +index 15e4c888c4afd..f30022a360a8a 100644 +--- a/drivers/gpu/drm/vc4/vc4_hvs.c ++++ b/drivers/gpu/drm/vc4/vc4_hvs.c +@@ -584,7 +584,7 @@ void vc4_hvs_atomic_flush(struct drm_crtc *crtc, + } + + if (vc4_state->assigned_channel == VC4_HVS_CHANNEL_DISABLED) +- return; ++ goto exit; + + if (debug_dump_regs) { + DRM_INFO("CRTC %d HVS before:\n", drm_crtc_index(crtc)); +@@ -667,6 +667,7 @@ void vc4_hvs_atomic_flush(struct drm_crtc *crtc, + vc4_hvs_dump_state(hvs); + } + ++exit: + drm_dev_exit(idx); + } + +-- +2.43.0 + diff --git a/queue-6.12/drm-vkms-drop-unnecessary-call-to-drm_crtc_cleanup.patch b/queue-6.12/drm-vkms-drop-unnecessary-call-to-drm_crtc_cleanup.patch new file mode 100644 index 00000000000..f49562459c6 --- /dev/null +++ b/queue-6.12/drm-vkms-drop-unnecessary-call-to-drm_crtc_cleanup.patch @@ -0,0 +1,52 @@ +From 15aeade2500b1c2d8da8ef90cfefa3fffdbc646c Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Thu, 31 Oct 2024 19:38:35 +0100 +Subject: drm/vkms: Drop unnecessary call to drm_crtc_cleanup() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: José Expósito <jose.exposito89@gmail.com> + +[ Upstream commit 1d43dddd7c38ea1aa93f78f7ee10087afb0a561f ] + +CRTC creation uses drmm_crtc_init_with_planes(), which automatically +handles cleanup. However, an unnecessary call to drm_crtc_cleanup() is +still present in the vkms_output_init() error path. + +Fixes: 99cc528ebe92 ("drm/vkms: Use drmm_crtc_init_with_planes()") +Signed-off-by: José Expósito <jose.exposito89@gmail.com> +Reviewed-by: Maíra Canal <mcanal@igalia.com> +Link: https://patchwork.freedesktop.org/patch/msgid/20241031183835.3633-1-jose.exposito89@gmail.com +Acked-by: Louis Chauvet <louis.chauvet@bootlin.com> +Signed-off-by: Louis Chauvet <louis.chauvet@bootlin.com> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/gpu/drm/vkms/vkms_output.c | 5 +---- + 1 file changed, 1 insertion(+), 4 deletions(-) + +diff --git a/drivers/gpu/drm/vkms/vkms_output.c b/drivers/gpu/drm/vkms/vkms_output.c +index 5ce70dd946aa6..24589b947dea3 100644 +--- a/drivers/gpu/drm/vkms/vkms_output.c ++++ b/drivers/gpu/drm/vkms/vkms_output.c +@@ -84,7 +84,7 @@ int vkms_output_init(struct vkms_device *vkmsdev, int index) + DRM_MODE_CONNECTOR_VIRTUAL); + if (ret) { + DRM_ERROR("Failed to init connector\n"); +- goto err_connector; ++ return ret; + } + + drm_connector_helper_add(connector, &vkms_conn_helper_funcs); +@@ -119,8 +119,5 @@ int vkms_output_init(struct vkms_device *vkmsdev, int index) + err_encoder: + drm_connector_cleanup(connector); + +-err_connector: +- drm_crtc_cleanup(crtc); +- + return ret; + } +-- +2.43.0 + diff --git a/queue-6.12/drm-xe-hdcp-fix-gsc-structure-check-in-fw-check-stat.patch b/queue-6.12/drm-xe-hdcp-fix-gsc-structure-check-in-fw-check-stat.patch new file mode 100644 index 00000000000..541b58170a6 --- /dev/null +++ b/queue-6.12/drm-xe-hdcp-fix-gsc-structure-check-in-fw-check-stat.patch @@ -0,0 +1,38 @@ +From 941645c03f0a1793c66a60874f6c57e4b34be0f8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Fri, 25 Oct 2024 21:38:35 +0530 +Subject: drm/xe/hdcp: Fix gsc structure check in fw check status + +From: Suraj Kandpal <suraj.kandpal@intel.com> + +[ Upstream commit 182a32bcc223203c57761889fac7fa2dbb34684b ] + +Fix the condition for gsc structure validity in +gsc_cs_status_check(). It needs to be an OR and not an AND +condition + +Fixes: b4224f6bae38 ("drm/xe/hdcp: Check GSC structure validity") +Signed-off-by: Suraj Kandpal <suraj.kandpal@intel.com> +Reviewed-by: Matt Roper <matthew.d.roper@intel.com> +Link: https://patchwork.freedesktop.org/patch/msgid/20241025160834.8785-1-suraj.kandpal@intel.com +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/gpu/drm/xe/display/xe_hdcp_gsc.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/xe/display/xe_hdcp_gsc.c b/drivers/gpu/drm/xe/display/xe_hdcp_gsc.c +index 6619a40aed153..f4332f06b6c80 100644 +--- a/drivers/gpu/drm/xe/display/xe_hdcp_gsc.c ++++ b/drivers/gpu/drm/xe/display/xe_hdcp_gsc.c +@@ -42,7 +42,7 @@ bool intel_hdcp_gsc_check_status(struct xe_device *xe) + struct xe_gsc *gsc = >->uc.gsc; + bool ret = true; + +- if (!gsc && !xe_uc_fw_is_enabled(&gsc->fw)) { ++ if (!gsc || !xe_uc_fw_is_enabled(&gsc->fw)) { + drm_dbg_kms(&xe->drm, + "GSC Components not ready for HDCP2.x\n"); + return false; +-- +2.43.0 + diff --git a/queue-6.12/drm-xe-ufence-wake-up-waiters-after-setting-ufence-s.patch b/queue-6.12/drm-xe-ufence-wake-up-waiters-after-setting-ufence-s.patch new file mode 100644 index 00000000000..b021b67116b --- /dev/null +++ b/queue-6.12/drm-xe-ufence-wake-up-waiters-after-setting-ufence-s.patch @@ -0,0 +1,51 @@ +From 50b591fdf05b9e3e2df013e2cf5c4204c2a3a428 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Thu, 14 Nov 2024 16:05:37 +0100 +Subject: drm/xe/ufence: Wake up waiters after setting ufence->signalled +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Nirmoy Das <nirmoy.das@intel.com> + +[ Upstream commit 37a1cf288e4538eb39b38dbc745fe0da7ae53d94 ] + +If a previous ufence is not signalled, vm_bind will return -EBUSY. +Delaying the modification of ufence->signalled can cause issues if the +UMD reuses the same ufence so update ufence->signalled before waking up +waiters. + +Cc: Matthew Brost <matthew.brost@intel.com> +Link: https://gitlab.freedesktop.org/drm/xe/kernel/-/issues/3233 +Fixes: 977e5b82e090 ("drm/xe: Expose user fence from xe_sync_entry") +Reviewed-by: Matthew Brost <matthew.brost@intel.com> +Link: https://patchwork.freedesktop.org/patch/msgid/20241114150537.4161573-1-nirmoy.das@intel.com +Signed-off-by: Nirmoy Das <nirmoy.das@intel.com> +(cherry picked from commit 553a5d14fcd927194c409b10faced6a6dbc678d1) +Signed-off-by: Thomas Hellström <thomas.hellstrom@linux.intel.com> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/gpu/drm/xe/xe_sync.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/xe/xe_sync.c b/drivers/gpu/drm/xe/xe_sync.c +index 2e72c06fd40d0..b0684e6d2047b 100644 +--- a/drivers/gpu/drm/xe/xe_sync.c ++++ b/drivers/gpu/drm/xe/xe_sync.c +@@ -85,8 +85,12 @@ static void user_fence_worker(struct work_struct *w) + mmput(ufence->mm); + } + +- wake_up_all(&ufence->xe->ufence_wq); ++ /* ++ * Wake up waiters only after updating the ufence state, allowing the UMD ++ * to safely reuse the same ufence without encountering -EBUSY errors. ++ */ + WRITE_ONCE(ufence->signalled, 1); ++ wake_up_all(&ufence->xe->ufence_wq); + user_fence_put(ufence); + } + +-- +2.43.0 + diff --git a/queue-6.12/drm-xlnx-zynqmp_disp-layer-may-be-null-while-releasi.patch b/queue-6.12/drm-xlnx-zynqmp_disp-layer-may-be-null-while-releasi.patch new file mode 100644 index 00000000000..729388123ce --- /dev/null +++ b/queue-6.12/drm-xlnx-zynqmp_disp-layer-may-be-null-while-releasi.patch @@ -0,0 +1,38 @@ +From afa99912744d2437b26af2cdfa020fe87bc778b5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Mon, 28 Oct 2024 14:39:40 +0100 +Subject: drm: xlnx: zynqmp_disp: layer may be null while releasing + +From: Steffen Dirkwinkel <s.dirkwinkel@beckhoff.com> + +[ Upstream commit 223842c7702b52846b1c5aef8aca7474ec1fd29b ] + +layer->info can be null if we have an error on the first layer in +zynqmp_disp_create_layers + +Fixes: 1836fd5ed98d ("drm: xlnx: zynqmp_dpsub: Minimize usage of global flag") +Signed-off-by: Steffen Dirkwinkel <s.dirkwinkel@beckhoff.com> +Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com> +Link: https://patchwork.freedesktop.org/patch/msgid/20241028133941.54264-1-lists@steffen.cc +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/gpu/drm/xlnx/zynqmp_disp.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/gpu/drm/xlnx/zynqmp_disp.c b/drivers/gpu/drm/xlnx/zynqmp_disp.c +index 9368acf56eaf7..e4e0e299e8a7d 100644 +--- a/drivers/gpu/drm/xlnx/zynqmp_disp.c ++++ b/drivers/gpu/drm/xlnx/zynqmp_disp.c +@@ -1200,6 +1200,9 @@ static void zynqmp_disp_layer_release_dma(struct zynqmp_disp *disp, + { + unsigned int i; + ++ if (!layer->info) ++ return; ++ + for (i = 0; i < layer->info->num_channels; i++) { + struct zynqmp_disp_layer_dma *dma = &layer->dmas[i]; + +-- +2.43.0 + diff --git a/queue-6.12/drm-zynqmp_kms-unplug-drm-device-before-removal.patch b/queue-6.12/drm-zynqmp_kms-unplug-drm-device-before-removal.patch new file mode 100644 index 00000000000..a7c52ce8981 --- /dev/null +++ b/queue-6.12/drm-zynqmp_kms-unplug-drm-device-before-removal.patch @@ -0,0 +1,40 @@ +From f26ac4dc30c6f253edbacd5b3074a437bcdf50ad Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Fri, 9 Aug 2024 15:35:53 -0400 +Subject: drm: zynqmp_kms: Unplug DRM device before removal + +From: Sean Anderson <sean.anderson@linux.dev> + +[ Upstream commit 2e07c88914fc5289c21820b1aa94f058feb38197 ] + +Prevent userspace accesses to the DRM device from causing +use-after-frees by unplugging the device before we remove it. This +causes any further userspace accesses to result in an error without +further calls into this driver's internals. + +Fixes: d76271d22694 ("drm: xlnx: DRM/KMS driver for Xilinx ZynqMP DisplayPort Subsystem") +Closes: https://lore.kernel.org/dri-devel/4d8f4c9b-2efb-4774-9a37-2f257f79b2c9@linux.dev/ +Signed-off-by: Sean Anderson <sean.anderson@linux.dev> +Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com> +Link: https://patchwork.freedesktop.org/patch/msgid/20240809193600.3360015-2-sean.anderson@linux.dev +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/gpu/drm/xlnx/zynqmp_kms.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/xlnx/zynqmp_kms.c b/drivers/gpu/drm/xlnx/zynqmp_kms.c +index bd1368df78703..4556af2faa0f1 100644 +--- a/drivers/gpu/drm/xlnx/zynqmp_kms.c ++++ b/drivers/gpu/drm/xlnx/zynqmp_kms.c +@@ -536,7 +536,7 @@ void zynqmp_dpsub_drm_cleanup(struct zynqmp_dpsub *dpsub) + { + struct drm_device *drm = &dpsub->drm->dev; + +- drm_dev_unregister(drm); ++ drm_dev_unplug(drm); + drm_atomic_helper_shutdown(drm); + drm_encoder_cleanup(&dpsub->drm->encoder); + drm_kms_helper_poll_fini(drm); +-- +2.43.0 + diff --git a/queue-6.12/dt-bindings-cache-qcom-llcc-fix-x1e80100-reg-entries.patch b/queue-6.12/dt-bindings-cache-qcom-llcc-fix-x1e80100-reg-entries.patch new file mode 100644 index 00000000000..32db4a7204c --- /dev/null +++ b/queue-6.12/dt-bindings-cache-qcom-llcc-fix-x1e80100-reg-entries.patch @@ -0,0 +1,97 @@ +From ecc75f84a9e704617eef80cd5546c997bdb4ced9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Fri, 18 Oct 2024 16:13:47 +0300 +Subject: dt-bindings: cache: qcom,llcc: Fix X1E80100 reg entries + +From: Abel Vesa <abel.vesa@linaro.org> + +[ Upstream commit f9759e2b57049f9c4ea8d7254ba6afcf6eb10cd6 ] + +Document the missing Broadcast_AND region for x1e80100. + +Fixes: e9ceb595c2d3 ("dt-bindings: cache: qcom,llcc: Add X1E80100 compatible") +Reported-by: kernel test robot <lkp@intel.com> +Closes: https://lore.kernel.org/oe-kbuild-all/202410181235.L7MF7z48-lkp@intel.com/ +Signed-off-by: Abel Vesa <abel.vesa@linaro.org> +Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org> +Link: https://lore.kernel.org/r/20241018-qcom-llcc-bindings-reg-ranges-fix-v1-1-88693cb7723b@linaro.org +Signed-off-by: Rob Herring (Arm) <robh@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + .../devicetree/bindings/cache/qcom,llcc.yaml | 36 +++++++++++++++++-- + 1 file changed, 34 insertions(+), 2 deletions(-) + +diff --git a/Documentation/devicetree/bindings/cache/qcom,llcc.yaml b/Documentation/devicetree/bindings/cache/qcom,llcc.yaml +index 68ea5f70b75f0..ee7edc6f60e2b 100644 +--- a/Documentation/devicetree/bindings/cache/qcom,llcc.yaml ++++ b/Documentation/devicetree/bindings/cache/qcom,llcc.yaml +@@ -39,11 +39,11 @@ properties: + + reg: + minItems: 2 +- maxItems: 9 ++ maxItems: 10 + + reg-names: + minItems: 2 +- maxItems: 9 ++ maxItems: 10 + + interrupts: + maxItems: 1 +@@ -134,6 +134,36 @@ allOf: + - qcom,qdu1000-llcc + - qcom,sc8180x-llcc + - qcom,sc8280xp-llcc ++ then: ++ properties: ++ reg: ++ items: ++ - description: LLCC0 base register region ++ - description: LLCC1 base register region ++ - description: LLCC2 base register region ++ - description: LLCC3 base register region ++ - description: LLCC4 base register region ++ - description: LLCC5 base register region ++ - description: LLCC6 base register region ++ - description: LLCC7 base register region ++ - description: LLCC broadcast base register region ++ reg-names: ++ items: ++ - const: llcc0_base ++ - const: llcc1_base ++ - const: llcc2_base ++ - const: llcc3_base ++ - const: llcc4_base ++ - const: llcc5_base ++ - const: llcc6_base ++ - const: llcc7_base ++ - const: llcc_broadcast_base ++ ++ - if: ++ properties: ++ compatible: ++ contains: ++ enum: + - qcom,x1e80100-llcc + then: + properties: +@@ -148,6 +178,7 @@ allOf: + - description: LLCC6 base register region + - description: LLCC7 base register region + - description: LLCC broadcast base register region ++ - description: LLCC broadcast AND register region + reg-names: + items: + - const: llcc0_base +@@ -159,6 +190,7 @@ allOf: + - const: llcc6_base + - const: llcc7_base + - const: llcc_broadcast_base ++ - const: llcc_broadcast_and_base + + - if: + properties: +-- +2.43.0 + diff --git a/queue-6.12/dt-bindings-clock-axi-clkgen-include-axi-clk.patch b/queue-6.12/dt-bindings-clock-axi-clkgen-include-axi-clk.patch new file mode 100644 index 00000000000..43f08c8744d --- /dev/null +++ b/queue-6.12/dt-bindings-clock-axi-clkgen-include-axi-clk.patch @@ -0,0 +1,72 @@ +From 03a3c7784262c11427d7678cccf9d3e9d52fc6ca Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Tue, 29 Oct 2024 14:59:41 +0100 +Subject: dt-bindings: clock: axi-clkgen: include AXI clk + +From: Nuno Sa <nuno.sa@analog.com> + +[ Upstream commit 47f3f5a82a31527e027929c5cec3dd1ef5ef30f5 ] + +In order to access the registers of the HW, we need to make sure that +the AXI bus clock is enabled. Hence let's increase the number of clocks +by one and add clock-names to differentiate between parent clocks and +the bus clock. + +Fixes: 0e646c52cf0e ("clk: Add axi-clkgen driver") +Signed-off-by: Nuno Sa <nuno.sa@analog.com> +Link: https://lore.kernel.org/r/20241029-axi-clkgen-fix-axiclk-v2-1-bc5e0733ad76@analog.com +Reviewed-by: Conor Dooley <conor.dooley@microchip.com> +Signed-off-by: Stephen Boyd <sboyd@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + .../bindings/clock/adi,axi-clkgen.yaml | 22 +++++++++++++++---- + 1 file changed, 18 insertions(+), 4 deletions(-) + +diff --git a/Documentation/devicetree/bindings/clock/adi,axi-clkgen.yaml b/Documentation/devicetree/bindings/clock/adi,axi-clkgen.yaml +index 5e942bccf2778..2b2041818a0a4 100644 +--- a/Documentation/devicetree/bindings/clock/adi,axi-clkgen.yaml ++++ b/Documentation/devicetree/bindings/clock/adi,axi-clkgen.yaml +@@ -26,9 +26,21 @@ properties: + description: + Specifies the reference clock(s) from which the output frequency is + derived. This must either reference one clock if only the first clock +- input is connected or two if both clock inputs are connected. +- minItems: 1 +- maxItems: 2 ++ input is connected or two if both clock inputs are connected. The last ++ clock is the AXI bus clock that needs to be enabled so we can access the ++ core registers. ++ minItems: 2 ++ maxItems: 3 ++ ++ clock-names: ++ oneOf: ++ - items: ++ - const: clkin1 ++ - const: s_axi_aclk ++ - items: ++ - const: clkin1 ++ - const: clkin2 ++ - const: s_axi_aclk + + '#clock-cells': + const: 0 +@@ -40,6 +52,7 @@ required: + - compatible + - reg + - clocks ++ - clock-names + - '#clock-cells' + + additionalProperties: false +@@ -50,5 +63,6 @@ examples: + compatible = "adi,axi-clkgen-2.00.a"; + #clock-cells = <0>; + reg = <0xff000000 0x1000>; +- clocks = <&osc 1>; ++ clocks = <&osc 1>, <&clkc 15>; ++ clock-names = "clkin1", "s_axi_aclk"; + }; +-- +2.43.0 + diff --git a/queue-6.12/dt-bindings-pci-mediatek-gen3-allow-exact-number-of-.patch b/queue-6.12/dt-bindings-pci-mediatek-gen3-allow-exact-number-of-.patch new file mode 100644 index 00000000000..b2a95b4e9f4 --- /dev/null +++ b/queue-6.12/dt-bindings-pci-mediatek-gen3-allow-exact-number-of-.patch @@ -0,0 +1,67 @@ +From ec65f9235ee3d31854d2e0abb412907a8d35897a Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Wed, 25 Sep 2024 18:57:46 +0800 +Subject: dt-bindings: PCI: mediatek-gen3: Allow exact number of clocks only + +From: Fei Shao <fshao@chromium.org> + +[ Upstream commit 5efa23224bf573d4bceb51bc646dd67b6ccb83b5 ] + +In MediaTek PCIe gen3 bindings, "clocks" accepts a range of 1-6 clocks +across all SoCs. But in practice, each SoC requires a particular number of +clocks as defined in "clock-names", and the length of "clocks" and +"clock-names" can be inconsistent with current bindings. + +For example: + + - MT8188, MT8192 and MT8195 all require 6 clocks, while the bindings + accept 4-6 clocks. + + - MT7986 requires 4 clocks, while the bindings accept 4-6 clocks. + +Update minItems and maxItems properties for individual SoCs as needed to +only accept the correct number of clocks. + +Fixes: c6abd0eadec6 ("dt-bindings: PCI: mediatek-gen3: Add support for Airoha EN7581") +Link: https://lore.kernel.org/r/20240925110044.3678055-3-fshao@chromium.org +Signed-off-by: Fei Shao <fshao@chromium.org> +Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> +Reviewed-by: Krzysztof Kozlowski <krzk@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + .../devicetree/bindings/pci/mediatek-pcie-gen3.yaml | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/Documentation/devicetree/bindings/pci/mediatek-pcie-gen3.yaml b/Documentation/devicetree/bindings/pci/mediatek-pcie-gen3.yaml +index 898c1be2d6a43..f05aab2b1addc 100644 +--- a/Documentation/devicetree/bindings/pci/mediatek-pcie-gen3.yaml ++++ b/Documentation/devicetree/bindings/pci/mediatek-pcie-gen3.yaml +@@ -149,7 +149,7 @@ allOf: + then: + properties: + clocks: +- minItems: 4 ++ minItems: 6 + + clock-names: + items: +@@ -178,7 +178,7 @@ allOf: + then: + properties: + clocks: +- minItems: 4 ++ minItems: 6 + + clock-names: + items: +@@ -207,6 +207,7 @@ allOf: + properties: + clocks: + minItems: 4 ++ maxItems: 4 + + clock-names: + items: +-- +2.43.0 + diff --git a/queue-6.12/dt-bindings-vendor-prefixes-add-neofidelity-inc.patch b/queue-6.12/dt-bindings-vendor-prefixes-add-neofidelity-inc.patch new file mode 100644 index 00000000000..3da0c8d1383 --- /dev/null +++ b/queue-6.12/dt-bindings-vendor-prefixes-add-neofidelity-inc.patch @@ -0,0 +1,36 @@ +From 9c4840c6e7209fa28430e5c776e2ed0810fa9560 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Wed, 25 Sep 2024 17:52:39 +0300 +Subject: dt-bindings: vendor-prefixes: Add NeoFidelity, Inc + +From: Igor Prusov <ivprusov@salutedevices.com> + +[ Upstream commit 5d9e6d6fc1b98c8c22d110ee931b3b233d43cd13 ] + +Add vendor prefix for NeoFidelity, Inc + +Signed-off-by: Igor Prusov <ivprusov@salutedevices.com> +Acked-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org> +Link: https://patch.msgid.link/20240925-ntp-amps-8918-8835-v3-1-e2459a8191a6@salutedevices.com +Signed-off-by: Mark Brown <broonie@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + Documentation/devicetree/bindings/vendor-prefixes.yaml | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/Documentation/devicetree/bindings/vendor-prefixes.yaml b/Documentation/devicetree/bindings/vendor-prefixes.yaml +index b320a39de7fe4..fbfce9b4ae6b8 100644 +--- a/Documentation/devicetree/bindings/vendor-prefixes.yaml ++++ b/Documentation/devicetree/bindings/vendor-prefixes.yaml +@@ -1013,6 +1013,8 @@ patternProperties: + description: Shanghai Neardi Technology Co., Ltd. + "^nec,.*": + description: NEC LCD Technologies, Ltd. ++ "^neofidelity,.*": ++ description: Neofidelity Inc. + "^neonode,.*": + description: Neonode Inc. + "^netgear,.*": +-- +2.43.0 + diff --git a/queue-6.12/edac-bluefield-fix-potential-integer-overflow.patch b/queue-6.12/edac-bluefield-fix-potential-integer-overflow.patch new file mode 100644 index 00000000000..8c5c8d2c031 --- /dev/null +++ b/queue-6.12/edac-bluefield-fix-potential-integer-overflow.patch @@ -0,0 +1,43 @@ +From ffb0e62a357a9a3c3ec9f97d6419b115198d895c Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Mon, 30 Sep 2024 11:10:56 -0400 +Subject: EDAC/bluefield: Fix potential integer overflow + +From: David Thompson <davthompson@nvidia.com> + +[ Upstream commit 1fe774a93b46bb029b8f6fa9d1f25affa53f06c6 ] + +The 64-bit argument for the "get DIMM info" SMC call consists of mem_ctrl_idx +left-shifted 16 bits and OR-ed with DIMM index. With mem_ctrl_idx defined as +32-bits wide the left-shift operation truncates the upper 16 bits of +information during the calculation of the SMC argument. + +The mem_ctrl_idx stack variable must be defined as 64-bits wide to prevent any +potential integer overflow, i.e. loss of data from upper 16 bits. + +Fixes: 82413e562ea6 ("EDAC, mellanox: Add ECC support for BlueField DDR4") +Signed-off-by: David Thompson <davthompson@nvidia.com> +Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de> +Reviewed-by: Shravan Kumar Ramani <shravankr@nvidia.com> +Link: https://lore.kernel.org/r/20240930151056.10158-1-davthompson@nvidia.com +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/edac/bluefield_edac.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/edac/bluefield_edac.c b/drivers/edac/bluefield_edac.c +index 5b3164560648e..0e539c1073510 100644 +--- a/drivers/edac/bluefield_edac.c ++++ b/drivers/edac/bluefield_edac.c +@@ -180,7 +180,7 @@ static void bluefield_edac_check(struct mem_ctl_info *mci) + static void bluefield_edac_init_dimms(struct mem_ctl_info *mci) + { + struct bluefield_edac_priv *priv = mci->pvt_info; +- int mem_ctrl_idx = mci->mc_idx; ++ u64 mem_ctrl_idx = mci->mc_idx; + struct dimm_info *dimm; + u64 smc_info, smc_arg; + int is_empty = 1, i; +-- +2.43.0 + diff --git a/queue-6.12/edac-fsl_ddr-fix-bad-bit-shift-operations.patch b/queue-6.12/edac-fsl_ddr-fix-bad-bit-shift-operations.patch new file mode 100644 index 00000000000..054904b4790 --- /dev/null +++ b/queue-6.12/edac-fsl_ddr-fix-bad-bit-shift-operations.patch @@ -0,0 +1,75 @@ +From 627149eb9c1d532568b8e71057125b09a5aa2b3b Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Wed, 16 Oct 2024 16:31:11 -0400 +Subject: EDAC/fsl_ddr: Fix bad bit shift operations + +From: Priyanka Singh <priyanka.singh@nxp.com> + +[ Upstream commit 9ec22ac4fe766c6abba845290d5139a3fbe0153b ] + +Fix undefined behavior caused by left-shifting a negative value in the +expression: + + cap_high ^ (1 << (bad_data_bit - 32)) + +The variable bad_data_bit ranges from 0 to 63. When it is less than 32, +bad_data_bit - 32 becomes negative, and left-shifting by a negative +value in C is undefined behavior. + +Fix this by combining cap_high and cap_low into a 64-bit variable. + + [ bp: Massage commit message, simplify error bits handling. ] + +Fixes: ea2eb9a8b620 ("EDAC, fsl-ddr: Separate FSL DDR driver from MPC85xx") +Signed-off-by: Priyanka Singh <priyanka.singh@nxp.com> +Signed-off-by: Li Yang <leoyang.li@nxp.com> +Signed-off-by: Frank Li <Frank.Li@nxp.com> +Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de> +Link: https://lore.kernel.org/r/20241016-imx95_edac-v3-3-86ae6fc2756a@nxp.com +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/edac/fsl_ddr_edac.c | 22 +++++++++++++--------- + 1 file changed, 13 insertions(+), 9 deletions(-) + +diff --git a/drivers/edac/fsl_ddr_edac.c b/drivers/edac/fsl_ddr_edac.c +index d148d262d0d4d..339d94b3d04c7 100644 +--- a/drivers/edac/fsl_ddr_edac.c ++++ b/drivers/edac/fsl_ddr_edac.c +@@ -328,21 +328,25 @@ static void fsl_mc_check(struct mem_ctl_info *mci) + * TODO: Add support for 32-bit wide buses + */ + if ((err_detect & DDR_EDE_SBE) && (bus_width == 64)) { ++ u64 cap = (u64)cap_high << 32 | cap_low; ++ u32 s = syndrome; ++ + sbe_ecc_decode(cap_high, cap_low, syndrome, + &bad_data_bit, &bad_ecc_bit); + +- if (bad_data_bit != -1) +- fsl_mc_printk(mci, KERN_ERR, +- "Faulty Data bit: %d\n", bad_data_bit); +- if (bad_ecc_bit != -1) +- fsl_mc_printk(mci, KERN_ERR, +- "Faulty ECC bit: %d\n", bad_ecc_bit); ++ if (bad_data_bit >= 0) { ++ fsl_mc_printk(mci, KERN_ERR, "Faulty Data bit: %d\n", bad_data_bit); ++ cap ^= 1ULL << bad_data_bit; ++ } ++ ++ if (bad_ecc_bit >= 0) { ++ fsl_mc_printk(mci, KERN_ERR, "Faulty ECC bit: %d\n", bad_ecc_bit); ++ s ^= 1 << bad_ecc_bit; ++ } + + fsl_mc_printk(mci, KERN_ERR, + "Expected Data / ECC:\t%#8.8x_%08x / %#2.2x\n", +- cap_high ^ (1 << (bad_data_bit - 32)), +- cap_low ^ (1 << bad_data_bit), +- syndrome ^ (1 << bad_ecc_bit)); ++ upper_32_bits(cap), lower_32_bits(cap), s); + } + + fsl_mc_printk(mci, KERN_ERR, +-- +2.43.0 + diff --git a/queue-6.12/edac-igen6-avoid-segmentation-fault-on-module-unload.patch b/queue-6.12/edac-igen6-avoid-segmentation-fault-on-module-unload.patch new file mode 100644 index 00000000000..859c21c1dc2 --- /dev/null +++ b/queue-6.12/edac-igen6-avoid-segmentation-fault-on-module-unload.patch @@ -0,0 +1,56 @@ +From 91d56b35102df92653ae712cf7ba3be95e86c197 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Mon, 4 Nov 2024 12:40:52 +0000 +Subject: EDAC/igen6: Avoid segmentation fault on module unload + +From: Orange Kao <orange@aiven.io> + +[ Upstream commit fefaae90398d38a1100ccd73b46ab55ff4610fba ] + +The segmentation fault happens because: + +During modprobe: +1. In igen6_probe(), igen6_pvt will be allocated with kzalloc() +2. In igen6_register_mci(), mci->pvt_info will point to + &igen6_pvt->imc[mc] + +During rmmod: +1. In mci_release() in edac_mc.c, it will kfree(mci->pvt_info) +2. In igen6_remove(), it will kfree(igen6_pvt); + +Fix this issue by setting mci->pvt_info to NULL to avoid the double +kfree. + +Fixes: 10590a9d4f23 ("EDAC/igen6: Add EDAC driver for Intel client SoCs using IBECC") +Closes: https://bugzilla.kernel.org/show_bug.cgi?id=219360 +Signed-off-by: Orange Kao <orange@aiven.io> +Signed-off-by: Tony Luck <tony.luck@intel.com> +Link: https://lore.kernel.org/r/20241104124237.124109-2-orange@aiven.io +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/edac/igen6_edac.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/edac/igen6_edac.c b/drivers/edac/igen6_edac.c +index 189a2fc29e74f..07dacf8c10be3 100644 +--- a/drivers/edac/igen6_edac.c ++++ b/drivers/edac/igen6_edac.c +@@ -1245,6 +1245,7 @@ static int igen6_register_mci(int mc, u64 mchbar, struct pci_dev *pdev) + imc->mci = mci; + return 0; + fail3: ++ mci->pvt_info = NULL; + kfree(mci->ctl_name); + fail2: + edac_mc_free(mci); +@@ -1269,6 +1270,7 @@ static void igen6_unregister_mcis(void) + + edac_mc_del_mc(mci->pdev); + kfree(mci->ctl_name); ++ mci->pvt_info = NULL; + edac_mc_free(mci); + iounmap(imc->window); + } +-- +2.43.0 + diff --git a/queue-6.12/edac-skx_common-differentiate-memory-error-sources.patch b/queue-6.12/edac-skx_common-differentiate-memory-error-sources.patch new file mode 100644 index 00000000000..02452964df5 --- /dev/null +++ b/queue-6.12/edac-skx_common-differentiate-memory-error-sources.patch @@ -0,0 +1,147 @@ +From b9e3abfca612ac0ab83c11403a7a417ebf3a2d02 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Tue, 15 Oct 2024 15:22:35 +0800 +Subject: EDAC/skx_common: Differentiate memory error sources + +From: Qiuxu Zhuo <qiuxu.zhuo@intel.com> + +[ Upstream commit 2397f795735219caa9c2fe61e7bcdd0652e670d3 ] + +The current skx_common determines whether the memory error source is the +near memory of the 2LM system and then retrieves the decoded error results +from the ADXL components (near-memory vs. far-memory) accordingly. + +However, some memory controllers may have limitations in correctly +reporting the memory error source, leading to the retrieval of incorrect +decoded parts from the ADXL. + +To address these limitations, instead of simply determining whether the +memory error is from the near memory of the 2LM system, it is necessary to +distinguish the memory error source details as follows: + + Memory error from the near memory of the 2LM system. + Memory error from the far memory of the 2LM system. + Memory error from the 1LM system. + Not a memory error. + +This will enable the i10nm_edac driver to take appropriate actions for +those memory controllers that have limitations in reporting the memory +error source. + +Fixes: ba987eaaabf9 ("EDAC/i10nm: Add Intel Granite Rapids server support") +Signed-off-by: Qiuxu Zhuo <qiuxu.zhuo@intel.com> +Signed-off-by: Tony Luck <tony.luck@intel.com> +Tested-by: Diego Garcia Rodriguez <diego.garcia.rodriguez@intel.com> +Link: https://lore.kernel.org/r/20241015072236.24543-2-qiuxu.zhuo@intel.com +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/edac/skx_common.c | 34 ++++++++++++++++------------------ + drivers/edac/skx_common.h | 7 +++++++ + 2 files changed, 23 insertions(+), 18 deletions(-) + +diff --git a/drivers/edac/skx_common.c b/drivers/edac/skx_common.c +index 85713646957b3..52b4628998700 100644 +--- a/drivers/edac/skx_common.c ++++ b/drivers/edac/skx_common.c +@@ -119,7 +119,7 @@ void skx_adxl_put(void) + } + EXPORT_SYMBOL_GPL(skx_adxl_put); + +-static bool skx_adxl_decode(struct decoded_addr *res, bool error_in_1st_level_mem) ++static bool skx_adxl_decode(struct decoded_addr *res, enum error_source err_src) + { + struct skx_dev *d; + int i, len = 0; +@@ -136,7 +136,7 @@ static bool skx_adxl_decode(struct decoded_addr *res, bool error_in_1st_level_me + } + + res->socket = (int)adxl_values[component_indices[INDEX_SOCKET]]; +- if (error_in_1st_level_mem) { ++ if (err_src == ERR_SRC_2LM_NM) { + res->imc = (adxl_nm_bitmap & BIT_NM_MEMCTRL) ? + (int)adxl_values[component_indices[INDEX_NM_MEMCTRL]] : -1; + res->channel = (adxl_nm_bitmap & BIT_NM_CHANNEL) ? +@@ -620,31 +620,27 @@ static void skx_mce_output_error(struct mem_ctl_info *mci, + optype, skx_msg); + } + +-static bool skx_error_in_1st_level_mem(const struct mce *m) ++static enum error_source skx_error_source(const struct mce *m) + { +- u32 errcode; ++ u32 errcode = GET_BITFIELD(m->status, 0, 15) & MCACOD_MEM_ERR_MASK; + +- if (!skx_mem_cfg_2lm) +- return false; +- +- errcode = GET_BITFIELD(m->status, 0, 15) & MCACOD_MEM_ERR_MASK; +- +- return errcode == MCACOD_EXT_MEM_ERR; +-} ++ if (errcode != MCACOD_MEM_CTL_ERR && errcode != MCACOD_EXT_MEM_ERR) ++ return ERR_SRC_NOT_MEMORY; + +-static bool skx_error_in_mem(const struct mce *m) +-{ +- u32 errcode; ++ if (!skx_mem_cfg_2lm) ++ return ERR_SRC_1LM; + +- errcode = GET_BITFIELD(m->status, 0, 15) & MCACOD_MEM_ERR_MASK; ++ if (errcode == MCACOD_EXT_MEM_ERR) ++ return ERR_SRC_2LM_NM; + +- return (errcode == MCACOD_MEM_CTL_ERR || errcode == MCACOD_EXT_MEM_ERR); ++ return ERR_SRC_2LM_FM; + } + + int skx_mce_check_error(struct notifier_block *nb, unsigned long val, + void *data) + { + struct mce *mce = (struct mce *)data; ++ enum error_source err_src; + struct decoded_addr res; + struct mem_ctl_info *mci; + char *type; +@@ -652,8 +648,10 @@ int skx_mce_check_error(struct notifier_block *nb, unsigned long val, + if (mce->kflags & MCE_HANDLED_CEC) + return NOTIFY_DONE; + ++ err_src = skx_error_source(mce); ++ + /* Ignore unless this is memory related with an address */ +- if (!skx_error_in_mem(mce) || !(mce->status & MCI_STATUS_ADDRV)) ++ if (err_src == ERR_SRC_NOT_MEMORY || !(mce->status & MCI_STATUS_ADDRV)) + return NOTIFY_DONE; + + memset(&res, 0, sizeof(res)); +@@ -667,7 +665,7 @@ int skx_mce_check_error(struct notifier_block *nb, unsigned long val, + /* Try driver decoder first */ + if (!(driver_decode && driver_decode(&res))) { + /* Then try firmware decoder (ACPI DSM methods) */ +- if (!(adxl_component_count && skx_adxl_decode(&res, skx_error_in_1st_level_mem(mce)))) ++ if (!(adxl_component_count && skx_adxl_decode(&res, err_src))) + return NOTIFY_DONE; + } + +diff --git a/drivers/edac/skx_common.h b/drivers/edac/skx_common.h +index f945c1bf5ca46..cd47f81868319 100644 +--- a/drivers/edac/skx_common.h ++++ b/drivers/edac/skx_common.h +@@ -146,6 +146,13 @@ enum { + INDEX_MAX + }; + ++enum error_source { ++ ERR_SRC_1LM, ++ ERR_SRC_2LM_NM, ++ ERR_SRC_2LM_FM, ++ ERR_SRC_NOT_MEMORY, ++}; ++ + #define BIT_NM_MEMCTRL BIT_ULL(INDEX_NM_MEMCTRL) + #define BIT_NM_CHANNEL BIT_ULL(INDEX_NM_CHANNEL) + #define BIT_NM_DIMM BIT_ULL(INDEX_NM_DIMM) +-- +2.43.0 + diff --git a/queue-6.12/edac-skx_common-i10nm-fix-incorrect-far-memory-error.patch b/queue-6.12/edac-skx_common-i10nm-fix-incorrect-far-memory-error.patch new file mode 100644 index 00000000000..e2a6a24c39d --- /dev/null +++ b/queue-6.12/edac-skx_common-i10nm-fix-incorrect-far-memory-error.patch @@ -0,0 +1,107 @@ +From baef89b16246740fe499998abba7a591227a725a Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Tue, 15 Oct 2024 15:22:36 +0800 +Subject: EDAC/{skx_common,i10nm}: Fix incorrect far-memory error source + indicator + +From: Qiuxu Zhuo <qiuxu.zhuo@intel.com> + +[ Upstream commit a36667037a0c0e36c59407f8ae636295390239a5 ] + +The Granite Rapids CPUs with Flat2LM memory configurations may +mistakenly report near-memory errors as far-memory errors, resulting +in the invalid decoded ADXL results: + + EDAC skx: Bad imc -1 + +Fix this incorrect far-memory error source indicator by prefetching the +decoded far-memory controller ID, and adjust the error source indicator +to near-memory if the far-memory controller ID is invalid. + +Fixes: ba987eaaabf9 ("EDAC/i10nm: Add Intel Granite Rapids server support") +Signed-off-by: Qiuxu Zhuo <qiuxu.zhuo@intel.com> +Signed-off-by: Tony Luck <tony.luck@intel.com> +Tested-by: Diego Garcia Rodriguez <diego.garcia.rodriguez@intel.com> +Link: https://lore.kernel.org/r/20241015072236.24543-3-qiuxu.zhuo@intel.com +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/edac/i10nm_base.c | 1 + + drivers/edac/skx_common.c | 23 +++++++++++++++++++++++ + drivers/edac/skx_common.h | 1 + + 3 files changed, 25 insertions(+) + +diff --git a/drivers/edac/i10nm_base.c b/drivers/edac/i10nm_base.c +index e2a954de913b4..51556c72a9674 100644 +--- a/drivers/edac/i10nm_base.c ++++ b/drivers/edac/i10nm_base.c +@@ -1036,6 +1036,7 @@ static int __init i10nm_init(void) + return -ENODEV; + + cfg = (struct res_config *)id->driver_data; ++ skx_set_res_cfg(cfg); + res_cfg = cfg; + + rc = skx_get_hi_lo(0x09a2, off, &tolm, &tohm); +diff --git a/drivers/edac/skx_common.c b/drivers/edac/skx_common.c +index 52b4628998700..6cf17af7d9112 100644 +--- a/drivers/edac/skx_common.c ++++ b/drivers/edac/skx_common.c +@@ -47,6 +47,7 @@ static skx_show_retry_log_f skx_show_retry_rd_err_log; + static u64 skx_tolm, skx_tohm; + static LIST_HEAD(dev_edac_list); + static bool skx_mem_cfg_2lm; ++static struct res_config *skx_res_cfg; + + int skx_adxl_get(void) + { +@@ -135,6 +136,22 @@ static bool skx_adxl_decode(struct decoded_addr *res, enum error_source err_src) + return false; + } + ++ /* ++ * GNR with a Flat2LM memory configuration may mistakenly classify ++ * a near-memory error(DDR5) as a far-memory error(CXL), resulting ++ * in the incorrect selection of decoded ADXL components. ++ * To address this, prefetch the decoded far-memory controller ID ++ * and adjust the error source to near-memory if the far-memory ++ * controller ID is invalid. ++ */ ++ if (skx_res_cfg && skx_res_cfg->type == GNR && err_src == ERR_SRC_2LM_FM) { ++ res->imc = (int)adxl_values[component_indices[INDEX_MEMCTRL]]; ++ if (res->imc == -1) { ++ err_src = ERR_SRC_2LM_NM; ++ edac_dbg(0, "Adjust the error source to near-memory.\n"); ++ } ++ } ++ + res->socket = (int)adxl_values[component_indices[INDEX_SOCKET]]; + if (err_src == ERR_SRC_2LM_NM) { + res->imc = (adxl_nm_bitmap & BIT_NM_MEMCTRL) ? +@@ -191,6 +208,12 @@ void skx_set_mem_cfg(bool mem_cfg_2lm) + } + EXPORT_SYMBOL_GPL(skx_set_mem_cfg); + ++void skx_set_res_cfg(struct res_config *cfg) ++{ ++ skx_res_cfg = cfg; ++} ++EXPORT_SYMBOL_GPL(skx_set_res_cfg); ++ + void skx_set_decode(skx_decode_f decode, skx_show_retry_log_f show_retry_log) + { + driver_decode = decode; +diff --git a/drivers/edac/skx_common.h b/drivers/edac/skx_common.h +index cd47f81868319..54bba8a62f727 100644 +--- a/drivers/edac/skx_common.h ++++ b/drivers/edac/skx_common.h +@@ -241,6 +241,7 @@ int skx_adxl_get(void); + void skx_adxl_put(void); + void skx_set_decode(skx_decode_f decode, skx_show_retry_log_f show_retry_log); + void skx_set_mem_cfg(bool mem_cfg_2lm); ++void skx_set_res_cfg(struct res_config *cfg); + + int skx_get_src_id(struct skx_dev *d, int off, u8 *id); + int skx_get_node_id(struct skx_dev *d, u8 *id); +-- +2.43.0 + diff --git a/queue-6.12/efi-libstub-fix-efi_parse_options-ignoring-the-defau.patch b/queue-6.12/efi-libstub-fix-efi_parse_options-ignoring-the-defau.patch new file mode 100644 index 00000000000..8ef60f24b52 --- /dev/null +++ b/queue-6.12/efi-libstub-fix-efi_parse_options-ignoring-the-defau.patch @@ -0,0 +1,41 @@ +From 394d7a55630e3ee623197cd87b6c773833a9eb92 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Sun, 13 Oct 2024 01:11:56 -0400 +Subject: efi/libstub: fix efi_parse_options() ignoring the default command + line + +From: Jonathan Marek <jonathan@marek.ca> + +[ Upstream commit aacfa0ef247b0130b7a98bb52378f8cd727a66ca ] + +efi_convert_cmdline() always returns a size of at least 1 because it +counts the NUL terminator, so the "cmdline_size == 0" condition is never +satisfied. + +Change it to check if the string starts with a NUL character to get the +intended behavior: to use CONFIG_CMDLINE when load_options_size == 0. + +Fixes: 60f38de7a8d4 ("efi/libstub: Unify command line param parsing") +Signed-off-by: Jonathan Marek <jonathan@marek.ca> +Signed-off-by: Ard Biesheuvel <ardb@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/firmware/efi/libstub/efi-stub.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/firmware/efi/libstub/efi-stub.c b/drivers/firmware/efi/libstub/efi-stub.c +index 958a680e0660d..2a1b43f9e0fa2 100644 +--- a/drivers/firmware/efi/libstub/efi-stub.c ++++ b/drivers/firmware/efi/libstub/efi-stub.c +@@ -129,7 +129,7 @@ efi_status_t efi_handle_cmdline(efi_loaded_image_t *image, char **cmdline_ptr) + + if (IS_ENABLED(CONFIG_CMDLINE_EXTEND) || + IS_ENABLED(CONFIG_CMDLINE_FORCE) || +- cmdline_size == 0) { ++ cmdline[0] == 0) { + status = efi_parse_options(CONFIG_CMDLINE); + if (status != EFI_SUCCESS) { + efi_err("Failed to parse options\n"); +-- +2.43.0 + diff --git a/queue-6.12/efs-fix-the-efs-new-mount-api-implementation.patch b/queue-6.12/efs-fix-the-efs-new-mount-api-implementation.patch new file mode 100644 index 00000000000..25937eef11e --- /dev/null +++ b/queue-6.12/efs-fix-the-efs-new-mount-api-implementation.patch @@ -0,0 +1,131 @@ +From db22aa9fb3a19b4673e3d463333ebeb910e5ef90 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Mon, 14 Oct 2024 14:02:41 -0500 +Subject: efs: fix the efs new mount api implementation + +From: Bill O'Donnell <bodonnel@redhat.com> + +[ Upstream commit 51ceeb1a8142537b9f65aeaac6c301560a948197 ] + +Commit 39a6c668e4 (efs: convert efs to use the new mount api) +did not include anything from v2 and v3 that were also submitted. +Fix this by bringing in those changes that were proposed in v2 and +v3. + +Fixes: 39a6c668e4 efs: convert efs to use the new mount api. + +Signed-off-by: Bill O'Donnell <bodonnel@redhat.com> +Link: https://lore.kernel.org/r/20241014190241.4093825-1-bodonnel@redhat.com +Signed-off-by: Christian Brauner <brauner@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + fs/efs/super.c | 43 +++---------------------------------------- + 1 file changed, 3 insertions(+), 40 deletions(-) + +diff --git a/fs/efs/super.c b/fs/efs/super.c +index e4421c10caebe..c59086b7eabfe 100644 +--- a/fs/efs/super.c ++++ b/fs/efs/super.c +@@ -15,7 +15,6 @@ + #include <linux/vfs.h> + #include <linux/blkdev.h> + #include <linux/fs_context.h> +-#include <linux/fs_parser.h> + #include "efs.h" + #include <linux/efs_vh.h> + #include <linux/efs_fs_sb.h> +@@ -49,15 +48,6 @@ static struct pt_types sgi_pt_types[] = { + {0, NULL} + }; + +-enum { +- Opt_explicit_open, +-}; +- +-static const struct fs_parameter_spec efs_param_spec[] = { +- fsparam_flag ("explicit-open", Opt_explicit_open), +- {} +-}; +- + /* + * File system definition and registration. + */ +@@ -67,7 +57,6 @@ static struct file_system_type efs_fs_type = { + .kill_sb = efs_kill_sb, + .fs_flags = FS_REQUIRES_DEV, + .init_fs_context = efs_init_fs_context, +- .parameters = efs_param_spec, + }; + MODULE_ALIAS_FS("efs"); + +@@ -265,7 +254,8 @@ static int efs_fill_super(struct super_block *s, struct fs_context *fc) + if (!sb_set_blocksize(s, EFS_BLOCKSIZE)) { + pr_err("device does not support %d byte blocks\n", + EFS_BLOCKSIZE); +- return -EINVAL; ++ return invalf(fc, "device does not support %d byte blocks\n", ++ EFS_BLOCKSIZE); + } + + /* read the vh (volume header) block */ +@@ -327,43 +317,22 @@ static int efs_fill_super(struct super_block *s, struct fs_context *fc) + return 0; + } + +-static void efs_free_fc(struct fs_context *fc) +-{ +- kfree(fc->fs_private); +-} +- + static int efs_get_tree(struct fs_context *fc) + { + return get_tree_bdev(fc, efs_fill_super); + } + +-static int efs_parse_param(struct fs_context *fc, struct fs_parameter *param) +-{ +- int token; +- struct fs_parse_result result; +- +- token = fs_parse(fc, efs_param_spec, param, &result); +- if (token < 0) +- return token; +- return 0; +-} +- + static int efs_reconfigure(struct fs_context *fc) + { + sync_filesystem(fc->root->d_sb); ++ fc->sb_flags |= SB_RDONLY; + + return 0; + } + +-struct efs_context { +- unsigned long s_mount_opts; +-}; +- + static const struct fs_context_operations efs_context_opts = { +- .parse_param = efs_parse_param, + .get_tree = efs_get_tree, + .reconfigure = efs_reconfigure, +- .free = efs_free_fc, + }; + + /* +@@ -371,12 +340,6 @@ static const struct fs_context_operations efs_context_opts = { + */ + static int efs_init_fs_context(struct fs_context *fc) + { +- struct efs_context *ctx; +- +- ctx = kzalloc(sizeof(struct efs_context), GFP_KERNEL); +- if (!ctx) +- return -ENOMEM; +- fc->fs_private = ctx; + fc->ops = &efs_context_opts; + + return 0; +-- +2.43.0 + diff --git a/queue-6.12/erofs-fix-blksize-page_size-for-file-backed-mounts.patch b/queue-6.12/erofs-fix-blksize-page_size-for-file-backed-mounts.patch new file mode 100644 index 00000000000..1befc05bb39 --- /dev/null +++ b/queue-6.12/erofs-fix-blksize-page_size-for-file-backed-mounts.patch @@ -0,0 +1,44 @@ +From 932de7ab63436f5ef7768fec373a1c4bc4e3ba53 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Tue, 15 Oct 2024 18:38:36 +0800 +Subject: erofs: fix blksize < PAGE_SIZE for file-backed mounts + +From: Hongzhen Luo <hongzhen@linux.alibaba.com> + +[ Upstream commit bae0854160939a64a092516ff1b2f221402b843b ] + +Adjust sb->s_blocksize{,_bits} directly for file-backed +mounts when the fs block size is smaller than PAGE_SIZE. + +Previously, EROFS used sb_set_blocksize(), which caused +a panic if bdev-backed mounts is not used. + +Fixes: fb176750266a ("erofs: add file-backed mount support") +Signed-off-by: Hongzhen Luo <hongzhen@linux.alibaba.com> +Link: https://lore.kernel.org/r/20241015103836.3757438-1-hongzhen@linux.alibaba.com +Signed-off-by: Gao Xiang <hsiangkao@linux.alibaba.com> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + fs/erofs/super.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/fs/erofs/super.c b/fs/erofs/super.c +index bed3dbe5b7cb8..2dd7d819572f4 100644 +--- a/fs/erofs/super.c ++++ b/fs/erofs/super.c +@@ -631,7 +631,11 @@ static int erofs_fc_fill_super(struct super_block *sb, struct fs_context *fc) + errorfc(fc, "unsupported blksize for fscache mode"); + return -EINVAL; + } +- if (!sb_set_blocksize(sb, 1 << sbi->blkszbits)) { ++ ++ if (erofs_is_fileio_mode(sbi)) { ++ sb->s_blocksize = 1 << sbi->blkszbits; ++ sb->s_blocksize_bits = sbi->blkszbits; ++ } else if (!sb_set_blocksize(sb, 1 << sbi->blkszbits)) { + errorfc(fc, "failed to set erofs blksize"); + return -EINVAL; + } +-- +2.43.0 + diff --git a/queue-6.12/erofs-fix-file-backed-mounts-over-fuse.patch b/queue-6.12/erofs-fix-file-backed-mounts-over-fuse.patch new file mode 100644 index 00000000000..2aa1ee462c3 --- /dev/null +++ b/queue-6.12/erofs-fix-file-backed-mounts-over-fuse.patch @@ -0,0 +1,79 @@ +From 97a9e952fac2018ff9a1dba6f3a7658133532b96 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Fri, 15 Nov 2024 07:49:05 +0800 +Subject: erofs: fix file-backed mounts over FUSE + +From: Gao Xiang <hsiangkao@linux.alibaba.com> + +[ Upstream commit 3a23787ca8756920d65fda39f41353a4be1d1642 ] + +syzbot reported a null-ptr-deref in fuse_read_args_fill: + fuse_read_folio+0xb0/0x100 fs/fuse/file.c:905 + filemap_read_folio+0xc6/0x2a0 mm/filemap.c:2367 + do_read_cache_folio+0x263/0x5c0 mm/filemap.c:3825 + read_mapping_folio include/linux/pagemap.h:1011 [inline] + erofs_bread+0x34d/0x7e0 fs/erofs/data.c:41 + erofs_read_superblock fs/erofs/super.c:281 [inline] + erofs_fc_fill_super+0x2b9/0x2500 fs/erofs/super.c:625 + +Unlike most filesystems, some network filesystems and FUSE need +unavoidable valid `file` pointers for their read I/Os [1]. +Anyway, those use cases need to be supported too. + +[1] https://docs.kernel.org/filesystems/vfs.html + +Reported-by: syzbot+0b1279812c46e48bb0c1@syzkaller.appspotmail.com +Closes: https://lore.kernel.org/r/6727bbdf.050a0220.3c8d68.0a7e.GAE@google.com +Fixes: fb176750266a ("erofs: add file-backed mount support") +Tested-by: syzbot+0b1279812c46e48bb0c1@syzkaller.appspotmail.com +Signed-off-by: Gao Xiang <hsiangkao@linux.alibaba.com> +Link: https://lore.kernel.org/r/20241114234905.1873723-1-hsiangkao@linux.alibaba.com +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + fs/erofs/data.c | 10 ++++++---- + fs/erofs/internal.h | 1 + + 2 files changed, 7 insertions(+), 4 deletions(-) + +diff --git a/fs/erofs/data.c b/fs/erofs/data.c +index 61debd799cf90..fa51437e1d99d 100644 +--- a/fs/erofs/data.c ++++ b/fs/erofs/data.c +@@ -38,7 +38,7 @@ void *erofs_bread(struct erofs_buf *buf, erofs_off_t offset, + } + if (!folio || !folio_contains(folio, index)) { + erofs_put_metabuf(buf); +- folio = read_mapping_folio(buf->mapping, index, NULL); ++ folio = read_mapping_folio(buf->mapping, index, buf->file); + if (IS_ERR(folio)) + return folio; + } +@@ -61,9 +61,11 @@ void erofs_init_metabuf(struct erofs_buf *buf, struct super_block *sb) + { + struct erofs_sb_info *sbi = EROFS_SB(sb); + +- if (erofs_is_fileio_mode(sbi)) +- buf->mapping = file_inode(sbi->fdev)->i_mapping; +- else if (erofs_is_fscache_mode(sb)) ++ buf->file = NULL; ++ if (erofs_is_fileio_mode(sbi)) { ++ buf->file = sbi->fdev; /* some fs like FUSE needs it */ ++ buf->mapping = buf->file->f_mapping; ++ } else if (erofs_is_fscache_mode(sb)) + buf->mapping = sbi->s_fscache->inode->i_mapping; + else + buf->mapping = sb->s_bdev->bd_mapping; +diff --git a/fs/erofs/internal.h b/fs/erofs/internal.h +index 4efd578d7c627..9b03c8f323a76 100644 +--- a/fs/erofs/internal.h ++++ b/fs/erofs/internal.h +@@ -221,6 +221,7 @@ enum erofs_kmap_type { + + struct erofs_buf { + struct address_space *mapping; ++ struct file *file; + struct page *page; + void *base; + enum erofs_kmap_type kmap_type; +-- +2.43.0 + diff --git a/queue-6.12/erofs-handle-nonhead-delta-1-lclusters-gracefully.patch b/queue-6.12/erofs-handle-nonhead-delta-1-lclusters-gracefully.patch new file mode 100644 index 00000000000..25c0b7bd960 --- /dev/null +++ b/queue-6.12/erofs-handle-nonhead-delta-1-lclusters-gracefully.patch @@ -0,0 +1,90 @@ +From 66526ae7d482ab38221ec5ddb6fefab80edbab90 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Sat, 16 Nov 2024 01:36:51 +0800 +Subject: erofs: handle NONHEAD !delta[1] lclusters gracefully + +From: Gao Xiang <hsiangkao@linux.alibaba.com> + +[ Upstream commit 0bc8061ffc733a0a246b8689b2d32a3e9204f43c ] + +syzbot reported a WARNING in iomap_iter_done: + iomap_fiemap+0x73b/0x9b0 fs/iomap/fiemap.c:80 + ioctl_fiemap fs/ioctl.c:220 [inline] + +Generally, NONHEAD lclusters won't have delta[1]==0, except for crafted +images and filesystems created by pre-1.0 mkfs versions. + +Previously, it would immediately bail out if delta[1]==0, which led to +inadequate decompressed lengths (thus FIEMAP is impacted). Treat it as +delta[1]=1 to work around these legacy mkfs versions. + +`lclusterbits > 14` is illegal for compact indexes, error out too. + +Reported-by: syzbot+6c0b301317aa0156f9eb@syzkaller.appspotmail.com +Closes: https://lore.kernel.org/r/67373c0c.050a0220.2a2fcc.0079.GAE@google.com +Tested-by: syzbot+6c0b301317aa0156f9eb@syzkaller.appspotmail.com +Fixes: d95ae5e25326 ("erofs: add support for the full decompressed length") +Fixes: 001b8ccd0650 ("erofs: fix compact 4B support for 16k block size") +Signed-off-by: Gao Xiang <hsiangkao@linux.alibaba.com> +Link: https://lore.kernel.org/r/20241115173651.3339514-1-hsiangkao@linux.alibaba.com +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + fs/erofs/zmap.c | 17 +++++++++-------- + 1 file changed, 9 insertions(+), 8 deletions(-) + +diff --git a/fs/erofs/zmap.c b/fs/erofs/zmap.c +index a076cca1f5473..4535f2f0a0147 100644 +--- a/fs/erofs/zmap.c ++++ b/fs/erofs/zmap.c +@@ -219,7 +219,7 @@ static int z_erofs_load_compact_lcluster(struct z_erofs_maprecorder *m, + unsigned int amortizedshift; + erofs_off_t pos; + +- if (lcn >= totalidx) ++ if (lcn >= totalidx || vi->z_logical_clusterbits > 14) + return -EINVAL; + + m->lcn = lcn; +@@ -390,7 +390,7 @@ static int z_erofs_get_extent_decompressedlen(struct z_erofs_maprecorder *m) + u64 lcn = m->lcn, headlcn = map->m_la >> lclusterbits; + int err; + +- do { ++ while (1) { + /* handle the last EOF pcluster (no next HEAD lcluster) */ + if ((lcn << lclusterbits) >= inode->i_size) { + map->m_llen = inode->i_size - map->m_la; +@@ -402,14 +402,16 @@ static int z_erofs_get_extent_decompressedlen(struct z_erofs_maprecorder *m) + return err; + + if (m->type == Z_EROFS_LCLUSTER_TYPE_NONHEAD) { +- DBG_BUGON(!m->delta[1] && +- m->clusterofs != 1 << lclusterbits); ++ /* work around invalid d1 generated by pre-1.0 mkfs */ ++ if (unlikely(!m->delta[1])) { ++ m->delta[1] = 1; ++ DBG_BUGON(1); ++ } + } else if (m->type == Z_EROFS_LCLUSTER_TYPE_PLAIN || + m->type == Z_EROFS_LCLUSTER_TYPE_HEAD1 || + m->type == Z_EROFS_LCLUSTER_TYPE_HEAD2) { +- /* go on until the next HEAD lcluster */ + if (lcn != headlcn) +- break; ++ break; /* ends at the next HEAD lcluster */ + m->delta[1] = 1; + } else { + erofs_err(inode->i_sb, "unknown type %u @ lcn %llu of nid %llu", +@@ -418,8 +420,7 @@ static int z_erofs_get_extent_decompressedlen(struct z_erofs_maprecorder *m) + return -EOPNOTSUPP; + } + lcn += m->delta[1]; +- } while (m->delta[1]); +- ++ } + map->m_llen = (lcn << lclusterbits) + m->clusterofs - map->m_la; + return 0; + } +-- +2.43.0 + diff --git a/queue-6.12/eth-fbnic-don-t-disable-the-pci-device-twice.patch b/queue-6.12/eth-fbnic-don-t-disable-the-pci-device-twice.patch new file mode 100644 index 00000000000..ac09784f46d --- /dev/null +++ b/queue-6.12/eth-fbnic-don-t-disable-the-pci-device-twice.patch @@ -0,0 +1,43 @@ +From 56ef47df1818f68f6774a958e7841a35d3153ada Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Thu, 14 Nov 2024 17:48:09 -0800 +Subject: eth: fbnic: don't disable the PCI device twice + +From: Jakub Kicinski <kuba@kernel.org> + +[ Upstream commit 62e9c00ea868ceb71156c517747dc69316c25bf1 ] + +We use pcim_enable_device(), there is no need to call pci_disable_device(). + +Fixes: 546dd90be979 ("eth: fbnic: Add scaffolding for Meta's NIC driver") +Reviewed-by: Simon Horman <horms@kernel.org> +Link: https://patch.msgid.link/20241115014809.754860-1-kuba@kernel.org +Signed-off-by: Jakub Kicinski <kuba@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/net/ethernet/meta/fbnic/fbnic_pci.c | 2 -- + 1 file changed, 2 deletions(-) + +diff --git a/drivers/net/ethernet/meta/fbnic/fbnic_pci.c b/drivers/net/ethernet/meta/fbnic/fbnic_pci.c +index a4809fe0fc249..268489b15616f 100644 +--- a/drivers/net/ethernet/meta/fbnic/fbnic_pci.c ++++ b/drivers/net/ethernet/meta/fbnic/fbnic_pci.c +@@ -319,7 +319,6 @@ static int fbnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) + free_irqs: + fbnic_free_irqs(fbd); + free_fbd: +- pci_disable_device(pdev); + fbnic_devlink_free(fbd); + + return err; +@@ -349,7 +348,6 @@ static void fbnic_remove(struct pci_dev *pdev) + fbnic_fw_disable_mbx(fbd); + fbnic_free_irqs(fbd); + +- pci_disable_device(pdev); + fbnic_devlink_free(fbd); + } + +-- +2.43.0 + diff --git a/queue-6.12/exfat-fix-file-being-changed-by-unaligned-direct-wri.patch b/queue-6.12/exfat-fix-file-being-changed-by-unaligned-direct-wri.patch new file mode 100644 index 00000000000..7d2b19bb199 --- /dev/null +++ b/queue-6.12/exfat-fix-file-being-changed-by-unaligned-direct-wri.patch @@ -0,0 +1,47 @@ +From 303c7efb957cdb937fb2ea34fa6351231bdc1cb6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Thu, 17 Oct 2024 09:25:06 +0800 +Subject: exfat: fix file being changed by unaligned direct write + +From: Yuezhang Mo <Yuezhang.Mo@sony.com> + +[ Upstream commit 2e94e5bb94a3e641a25716a560bf474225fda83c ] + +Unaligned direct writes are invalid and should return an error +without making any changes, rather than extending ->valid_size +and then returning an error. Therefore, alignment checking is +required before extending ->valid_size. + +Fixes: 11a347fb6cef ("exfat: change to get file size from DataLength") +Signed-off-by: Yuezhang Mo <Yuezhang.Mo@sony.com> +Co-developed-by: Namjae Jeon <linkinjeon@kernel.org> +Signed-off-by: Namjae Jeon <linkinjeon@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + fs/exfat/file.c | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +diff --git a/fs/exfat/file.c b/fs/exfat/file.c +index a25d7eb789f4c..fb38769c3e39d 100644 +--- a/fs/exfat/file.c ++++ b/fs/exfat/file.c +@@ -584,6 +584,16 @@ static ssize_t exfat_file_write_iter(struct kiocb *iocb, struct iov_iter *iter) + if (ret < 0) + goto unlock; + ++ if (iocb->ki_flags & IOCB_DIRECT) { ++ unsigned long align = pos | iov_iter_alignment(iter); ++ ++ if (!IS_ALIGNED(align, i_blocksize(inode)) && ++ !IS_ALIGNED(align, bdev_logical_block_size(inode->i_sb->s_bdev))) { ++ ret = -EINVAL; ++ goto unlock; ++ } ++ } ++ + if (pos > valid_size) { + ret = exfat_extend_valid_size(file, pos); + if (ret < 0 && ret != -ENOSPC) { +-- +2.43.0 + diff --git a/queue-6.12/ext4-avoid-remount-errors-with-abort-mount-option.patch b/queue-6.12/ext4-avoid-remount-errors-with-abort-mount-option.patch new file mode 100644 index 00000000000..4ece1af0ea0 --- /dev/null +++ b/queue-6.12/ext4-avoid-remount-errors-with-abort-mount-option.patch @@ -0,0 +1,66 @@ +From 9d315092e775617957b9836204869f14b35202ad Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Sat, 5 Oct 2024 00:15:56 +0200 +Subject: ext4: avoid remount errors with 'abort' mount option + +From: Jan Kara <jack@suse.cz> + +[ Upstream commit 76486b104168ae59703190566e372badf433314b ] + +When we remount filesystem with 'abort' mount option while changing +other mount options as well (as is LTP test doing), we can return error +from the system call after commit d3476f3dad4a ("ext4: don't set +SB_RDONLY after filesystem errors") because the application of mount +option changes detects shutdown filesystem and refuses to do anything. +The behavior of application of other mount options in presence of +'abort' mount option is currently rather arbitary as some mount option +changes are handled before 'abort' and some after it. + +Move aborting of the filesystem to the end of remount handling so all +requested changes are properly applied before the filesystem is shutdown +to have a reasonably consistent behavior. + +Fixes: d3476f3dad4a ("ext4: don't set SB_RDONLY after filesystem errors") +Reported-by: Jan Stancek <jstancek@redhat.com> +Link: https://lore.kernel.org/all/Zvp6L+oFnfASaoHl@t14s +Signed-off-by: Jan Kara <jack@suse.cz> +Tested-by: Jan Stancek <jstancek@redhat.com> +Link: https://patch.msgid.link/20241004221556.19222-1-jack@suse.cz +Signed-off-by: Theodore Ts'o <tytso@mit.edu> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + fs/ext4/super.c | 11 ++++++++--- + 1 file changed, 8 insertions(+), 3 deletions(-) + +diff --git a/fs/ext4/super.c b/fs/ext4/super.c +index 16a4ce704460e..4645f16296732 100644 +--- a/fs/ext4/super.c ++++ b/fs/ext4/super.c +@@ -6518,9 +6518,6 @@ static int __ext4_remount(struct fs_context *fc, struct super_block *sb) + goto restore_opts; + } + +- if (test_opt2(sb, ABORT)) +- ext4_abort(sb, ESHUTDOWN, "Abort forced by user"); +- + sb->s_flags = (sb->s_flags & ~SB_POSIXACL) | + (test_opt(sb, POSIX_ACL) ? SB_POSIXACL : 0); + +@@ -6689,6 +6686,14 @@ static int __ext4_remount(struct fs_context *fc, struct super_block *sb) + if (!ext4_has_feature_mmp(sb) || sb_rdonly(sb)) + ext4_stop_mmpd(sbi); + ++ /* ++ * Handle aborting the filesystem as the last thing during remount to ++ * avoid obsure errors during remount when some option changes fail to ++ * apply due to shutdown filesystem. ++ */ ++ if (test_opt2(sb, ABORT)) ++ ext4_abort(sb, ESHUTDOWN, "Abort forced by user"); ++ + return 0; + + restore_opts: +-- +2.43.0 + diff --git a/queue-6.12/ext4-fix-race-in-buffer_head-read-fault-injection.patch b/queue-6.12/ext4-fix-race-in-buffer_head-read-fault-injection.patch new file mode 100644 index 00000000000..435b799ea47 --- /dev/null +++ b/queue-6.12/ext4-fix-race-in-buffer_head-read-fault-injection.patch @@ -0,0 +1,293 @@ +From b3106959d44c3df2c11061cfacedde52b0a16b0b Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Fri, 6 Sep 2024 17:17:46 +0800 +Subject: ext4: fix race in buffer_head read fault injection + +From: Long Li <leo.lilong@huawei.com> + +[ Upstream commit 2f3d93e210b9c2866c8b3662adae427d5bf511ec ] + +When I enabled ext4 debug for fault injection testing, I encountered the +following warning: + + EXT4-fs error (device sda): ext4_read_inode_bitmap:201: comm fsstress: + Cannot read inode bitmap - block_group = 8, inode_bitmap = 1051 + WARNING: CPU: 0 PID: 511 at fs/buffer.c:1181 mark_buffer_dirty+0x1b3/0x1d0 + +The root cause of the issue lies in the improper implementation of ext4's +buffer_head read fault injection. The actual completion of buffer_head +read and the buffer_head fault injection are not atomic, which can lead +to the uptodate flag being cleared on normally used buffer_heads in race +conditions. + +[CPU0] [CPU1] [CPU2] +ext4_read_inode_bitmap + ext4_read_bh() + <bh read complete> + ext4_read_inode_bitmap + if (buffer_uptodate(bh)) + return bh + jbd2_journal_commit_transaction + __jbd2_journal_refile_buffer + __jbd2_journal_unfile_buffer + __jbd2_journal_temp_unlink_buffer + ext4_simulate_fail_bh() + clear_buffer_uptodate + mark_buffer_dirty + <report warning> + WARN_ON_ONCE(!buffer_uptodate(bh)) + +The best approach would be to perform fault injection in the IO completion +callback function, rather than after IO completion. However, the IO +completion callback function cannot get the fault injection code in sb. + +Fix it by passing the result of fault injection into the bh read function, +we simulate faults within the bh read function itself. This requires adding +an extra parameter to the bh read functions that need fault injection. + +Fixes: 46f870d690fe ("ext4: simulate various I/O and checksum errors when reading metadata") +Signed-off-by: Long Li <leo.lilong@huawei.com> +Link: https://patch.msgid.link/20240906091746.510163-1-leo.lilong@huawei.com +Signed-off-by: Theodore Ts'o <tytso@mit.edu> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + fs/ext4/balloc.c | 4 ++-- + fs/ext4/ext4.h | 12 ++---------- + fs/ext4/extents.c | 2 +- + fs/ext4/ialloc.c | 5 +++-- + fs/ext4/indirect.c | 2 +- + fs/ext4/inode.c | 4 ++-- + fs/ext4/mmp.c | 2 +- + fs/ext4/move_extent.c | 2 +- + fs/ext4/resize.c | 2 +- + fs/ext4/super.c | 23 +++++++++++++++-------- + 10 files changed, 29 insertions(+), 29 deletions(-) + +diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c +index 591fb3f710be7..8042ad8738089 100644 +--- a/fs/ext4/balloc.c ++++ b/fs/ext4/balloc.c +@@ -550,7 +550,8 @@ ext4_read_block_bitmap_nowait(struct super_block *sb, ext4_group_t block_group, + trace_ext4_read_block_bitmap_load(sb, block_group, ignore_locked); + ext4_read_bh_nowait(bh, REQ_META | REQ_PRIO | + (ignore_locked ? REQ_RAHEAD : 0), +- ext4_end_bitmap_read); ++ ext4_end_bitmap_read, ++ ext4_simulate_fail(sb, EXT4_SIM_BBITMAP_EIO)); + return bh; + verify: + err = ext4_validate_block_bitmap(sb, desc, block_group, bh); +@@ -577,7 +578,6 @@ int ext4_wait_block_bitmap(struct super_block *sb, ext4_group_t block_group, + if (!desc) + return -EFSCORRUPTED; + wait_on_buffer(bh); +- ext4_simulate_fail_bh(sb, bh, EXT4_SIM_BBITMAP_EIO); + if (!buffer_uptodate(bh)) { + ext4_error_err(sb, EIO, "Cannot read block bitmap - " + "block_group = %u, block_bitmap = %llu", +diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h +index 44b0d418143c2..bbffb76d9a904 100644 +--- a/fs/ext4/ext4.h ++++ b/fs/ext4/ext4.h +@@ -1865,14 +1865,6 @@ static inline bool ext4_simulate_fail(struct super_block *sb, + return false; + } + +-static inline void ext4_simulate_fail_bh(struct super_block *sb, +- struct buffer_head *bh, +- unsigned long code) +-{ +- if (!IS_ERR(bh) && ext4_simulate_fail(sb, code)) +- clear_buffer_uptodate(bh); +-} +- + /* + * Error number codes for s_{first,last}_error_errno + * +@@ -3100,9 +3092,9 @@ extern struct buffer_head *ext4_sb_bread(struct super_block *sb, + extern struct buffer_head *ext4_sb_bread_unmovable(struct super_block *sb, + sector_t block); + extern void ext4_read_bh_nowait(struct buffer_head *bh, blk_opf_t op_flags, +- bh_end_io_t *end_io); ++ bh_end_io_t *end_io, bool simu_fail); + extern int ext4_read_bh(struct buffer_head *bh, blk_opf_t op_flags, +- bh_end_io_t *end_io); ++ bh_end_io_t *end_io, bool simu_fail); + extern int ext4_read_bh_lock(struct buffer_head *bh, blk_opf_t op_flags, bool wait); + extern void ext4_sb_breadahead_unmovable(struct super_block *sb, sector_t block); + extern int ext4_seq_options_show(struct seq_file *seq, void *offset); +diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c +index 34e25eee65219..88f98dc440275 100644 +--- a/fs/ext4/extents.c ++++ b/fs/ext4/extents.c +@@ -568,7 +568,7 @@ __read_extent_tree_block(const char *function, unsigned int line, + + if (!bh_uptodate_or_lock(bh)) { + trace_ext4_ext_load_extent(inode, pblk, _RET_IP_); +- err = ext4_read_bh(bh, 0, NULL); ++ err = ext4_read_bh(bh, 0, NULL, false); + if (err < 0) + goto errout; + } +diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c +index 7f1a5f90dbbdf..21d228073d795 100644 +--- a/fs/ext4/ialloc.c ++++ b/fs/ext4/ialloc.c +@@ -193,8 +193,9 @@ ext4_read_inode_bitmap(struct super_block *sb, ext4_group_t block_group) + * submit the buffer_head for reading + */ + trace_ext4_load_inode_bitmap(sb, block_group); +- ext4_read_bh(bh, REQ_META | REQ_PRIO, ext4_end_bitmap_read); +- ext4_simulate_fail_bh(sb, bh, EXT4_SIM_IBITMAP_EIO); ++ ext4_read_bh(bh, REQ_META | REQ_PRIO, ++ ext4_end_bitmap_read, ++ ext4_simulate_fail(sb, EXT4_SIM_IBITMAP_EIO)); + if (!buffer_uptodate(bh)) { + put_bh(bh); + ext4_error_err(sb, EIO, "Cannot read inode bitmap - " +diff --git a/fs/ext4/indirect.c b/fs/ext4/indirect.c +index 7404f0935c903..7de327fa7b1c5 100644 +--- a/fs/ext4/indirect.c ++++ b/fs/ext4/indirect.c +@@ -170,7 +170,7 @@ static Indirect *ext4_get_branch(struct inode *inode, int depth, + } + + if (!bh_uptodate_or_lock(bh)) { +- if (ext4_read_bh(bh, 0, NULL) < 0) { ++ if (ext4_read_bh(bh, 0, NULL, false) < 0) { + put_bh(bh); + goto failure; + } +diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c +index 54bdd4884fe67..99d09cd9c6a37 100644 +--- a/fs/ext4/inode.c ++++ b/fs/ext4/inode.c +@@ -4497,10 +4497,10 @@ static int __ext4_get_inode_loc(struct super_block *sb, unsigned long ino, + * Read the block from disk. + */ + trace_ext4_load_inode(sb, ino); +- ext4_read_bh_nowait(bh, REQ_META | REQ_PRIO, NULL); ++ ext4_read_bh_nowait(bh, REQ_META | REQ_PRIO, NULL, ++ ext4_simulate_fail(sb, EXT4_SIM_INODE_EIO)); + blk_finish_plug(&plug); + wait_on_buffer(bh); +- ext4_simulate_fail_bh(sb, bh, EXT4_SIM_INODE_EIO); + if (!buffer_uptodate(bh)) { + if (ret_block) + *ret_block = block; +diff --git a/fs/ext4/mmp.c b/fs/ext4/mmp.c +index bd946d0c71b70..d64c04ed061ae 100644 +--- a/fs/ext4/mmp.c ++++ b/fs/ext4/mmp.c +@@ -94,7 +94,7 @@ static int read_mmp_block(struct super_block *sb, struct buffer_head **bh, + } + + lock_buffer(*bh); +- ret = ext4_read_bh(*bh, REQ_META | REQ_PRIO, NULL); ++ ret = ext4_read_bh(*bh, REQ_META | REQ_PRIO, NULL, false); + if (ret) + goto warn_exit; + +diff --git a/fs/ext4/move_extent.c b/fs/ext4/move_extent.c +index b64661ea6e0ed..898443e98efc9 100644 +--- a/fs/ext4/move_extent.c ++++ b/fs/ext4/move_extent.c +@@ -213,7 +213,7 @@ static int mext_page_mkuptodate(struct folio *folio, size_t from, size_t to) + unlock_buffer(bh); + continue; + } +- ext4_read_bh_nowait(bh, 0, NULL); ++ ext4_read_bh_nowait(bh, 0, NULL, false); + nr++; + } while (block++, (bh = bh->b_this_page) != head); + +diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c +index a2704f0643610..72f77f78ae8df 100644 +--- a/fs/ext4/resize.c ++++ b/fs/ext4/resize.c +@@ -1300,7 +1300,7 @@ static struct buffer_head *ext4_get_bitmap(struct super_block *sb, __u64 block) + if (unlikely(!bh)) + return NULL; + if (!bh_uptodate_or_lock(bh)) { +- if (ext4_read_bh(bh, 0, NULL) < 0) { ++ if (ext4_read_bh(bh, 0, NULL, false) < 0) { + brelse(bh); + return NULL; + } +diff --git a/fs/ext4/super.c b/fs/ext4/super.c +index 4645f16296732..95930e70b8aac 100644 +--- a/fs/ext4/super.c ++++ b/fs/ext4/super.c +@@ -161,8 +161,14 @@ MODULE_ALIAS("ext3"); + + + static inline void __ext4_read_bh(struct buffer_head *bh, blk_opf_t op_flags, +- bh_end_io_t *end_io) ++ bh_end_io_t *end_io, bool simu_fail) + { ++ if (simu_fail) { ++ clear_buffer_uptodate(bh); ++ unlock_buffer(bh); ++ return; ++ } ++ + /* + * buffer's verified bit is no longer valid after reading from + * disk again due to write out error, clear it to make sure we +@@ -176,7 +182,7 @@ static inline void __ext4_read_bh(struct buffer_head *bh, blk_opf_t op_flags, + } + + void ext4_read_bh_nowait(struct buffer_head *bh, blk_opf_t op_flags, +- bh_end_io_t *end_io) ++ bh_end_io_t *end_io, bool simu_fail) + { + BUG_ON(!buffer_locked(bh)); + +@@ -184,10 +190,11 @@ void ext4_read_bh_nowait(struct buffer_head *bh, blk_opf_t op_flags, + unlock_buffer(bh); + return; + } +- __ext4_read_bh(bh, op_flags, end_io); ++ __ext4_read_bh(bh, op_flags, end_io, simu_fail); + } + +-int ext4_read_bh(struct buffer_head *bh, blk_opf_t op_flags, bh_end_io_t *end_io) ++int ext4_read_bh(struct buffer_head *bh, blk_opf_t op_flags, ++ bh_end_io_t *end_io, bool simu_fail) + { + BUG_ON(!buffer_locked(bh)); + +@@ -196,7 +203,7 @@ int ext4_read_bh(struct buffer_head *bh, blk_opf_t op_flags, bh_end_io_t *end_io + return 0; + } + +- __ext4_read_bh(bh, op_flags, end_io); ++ __ext4_read_bh(bh, op_flags, end_io, simu_fail); + + wait_on_buffer(bh); + if (buffer_uptodate(bh)) +@@ -208,10 +215,10 @@ int ext4_read_bh_lock(struct buffer_head *bh, blk_opf_t op_flags, bool wait) + { + lock_buffer(bh); + if (!wait) { +- ext4_read_bh_nowait(bh, op_flags, NULL); ++ ext4_read_bh_nowait(bh, op_flags, NULL, false); + return 0; + } +- return ext4_read_bh(bh, op_flags, NULL); ++ return ext4_read_bh(bh, op_flags, NULL, false); + } + + /* +@@ -266,7 +273,7 @@ void ext4_sb_breadahead_unmovable(struct super_block *sb, sector_t block) + + if (likely(bh)) { + if (trylock_buffer(bh)) +- ext4_read_bh_nowait(bh, REQ_RAHEAD, NULL); ++ ext4_read_bh_nowait(bh, REQ_RAHEAD, NULL, false); + brelse(bh); + } + } +-- +2.43.0 + diff --git a/queue-6.12/f2fs-check-curseg-inited-before-write_sum_page-in-ch.patch b/queue-6.12/f2fs-check-curseg-inited-before-write_sum_page-in-ch.patch new file mode 100644 index 00000000000..336349c9086 --- /dev/null +++ b/queue-6.12/f2fs-check-curseg-inited-before-write_sum_page-in-ch.patch @@ -0,0 +1,39 @@ +From 72db591e2941a6877869fc84ac06672b1cf0cf65 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Mon, 21 Oct 2024 12:48:01 +0800 +Subject: f2fs: check curseg->inited before write_sum_page in change_curseg + +From: Yongpeng Yang <yangyongpeng1@oppo.com> + +[ Upstream commit 43563069e1c1df417d2eed6eca8a22fc6b04691d ] + +In the __f2fs_init_atgc_curseg->get_atssr_segment calling, +curseg->segno is NULL_SEGNO, indicating that there is no summary +block that needs to be written. + +Fixes: 093749e296e2 ("f2fs: support age threshold based garbage collection") +Signed-off-by: Yongpeng Yang <yangyongpeng1@oppo.com> +Reviewed-by: Chao Yu <chao@kernel.org> +Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + fs/f2fs/segment.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c +index 7b54b1851d346..edf205093f435 100644 +--- a/fs/f2fs/segment.c ++++ b/fs/f2fs/segment.c +@@ -2926,7 +2926,8 @@ static int change_curseg(struct f2fs_sb_info *sbi, int type) + struct f2fs_summary_block *sum_node; + struct page *sum_page; + +- write_sum_page(sbi, curseg->sum_blk, GET_SUM_BLOCK(sbi, curseg->segno)); ++ if (curseg->inited) ++ write_sum_page(sbi, curseg->sum_blk, GET_SUM_BLOCK(sbi, curseg->segno)); + + __set_test_and_inuse(sbi, new_segno); + +-- +2.43.0 + diff --git a/queue-6.12/f2fs-compress-fix-inconsistent-update-of-i_blocks-in.patch b/queue-6.12/f2fs-compress-fix-inconsistent-update-of-i_blocks-in.patch new file mode 100644 index 00000000000..45c97d040aa --- /dev/null +++ b/queue-6.12/f2fs-compress-fix-inconsistent-update-of-i_blocks-in.patch @@ -0,0 +1,67 @@ +From c06d17e3174de5be16ea796d27efe82c554e72e2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Sun, 29 Sep 2024 02:00:10 -0600 +Subject: f2fs: compress: fix inconsistent update of i_blocks in + release_compress_blocks and reserve_compress_blocks + +From: Qi Han <hanqi@vivo.com> + +[ Upstream commit 26413ce18e85de3dda2cd3d72c3c3e8ab8f4f996 ] + +After release a file and subsequently reserve it, the FSCK flag is set +when the file is deleted, as shown in the following backtrace: + +F2FS-fs (dm-48): Inconsistent i_blocks, ino:401231, iblocks:1448, sectors:1472 +fs_rec_info_write_type+0x58/0x274 +f2fs_rec_info_write+0x1c/0x2c +set_sbi_flag+0x74/0x98 +dec_valid_block_count+0x150/0x190 +f2fs_truncate_data_blocks_range+0x2d4/0x3cc +f2fs_do_truncate_blocks+0x2fc/0x5f0 +f2fs_truncate_blocks+0x68/0x100 +f2fs_truncate+0x80/0x128 +f2fs_evict_inode+0x1a4/0x794 +evict+0xd4/0x280 +iput+0x238/0x284 +do_unlinkat+0x1ac/0x298 +__arm64_sys_unlinkat+0x48/0x68 +invoke_syscall+0x58/0x11c + +For clusters of the following type, i_blocks are decremented by 1 and +i_compr_blocks are incremented by 7 in release_compress_blocks, while +updates to i_blocks and i_compr_blocks are skipped in reserve_compress_blocks. + +raw node: +D D D D D D D D +after compress: +C D D D D D D D +after reserve: +C D D D D D D D + +Let's update i_blocks and i_compr_blocks properly in reserve_compress_blocks. + +Fixes: eb8fbaa53374 ("f2fs: compress: fix to check unreleased compressed cluster") +Signed-off-by: Qi Han <hanqi@vivo.com> +Reviewed-by: Chao Yu <chao@kernel.org> +Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + fs/f2fs/file.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c +index 321d8ffbab6e4..adc7d64a6f47d 100644 +--- a/fs/f2fs/file.c ++++ b/fs/f2fs/file.c +@@ -3792,7 +3792,7 @@ static int reserve_compress_blocks(struct dnode_of_data *dn, pgoff_t count, + to_reserved = cluster_size - compr_blocks - reserved; + + /* for the case all blocks in cluster were reserved */ +- if (to_reserved == 1) { ++ if (reserved && to_reserved == 1) { + dn->ofs_in_node += cluster_size; + goto next; + } +-- +2.43.0 + diff --git a/queue-6.12/f2fs-fix-not-used-variable-index.patch b/queue-6.12/f2fs-fix-not-used-variable-index.patch new file mode 100644 index 00000000000..1edd6fde723 --- /dev/null +++ b/queue-6.12/f2fs-fix-not-used-variable-index.patch @@ -0,0 +1,59 @@ +From cbe736e95ae4cd665f752af59eada23ced9091f5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Wed, 23 Oct 2024 17:48:50 +0800 +Subject: f2fs: Fix not used variable 'index' +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Zeng Heng <zengheng4@huawei.com> + +[ Upstream commit 0c3a38a4b442893f8baca72e44a2a27d52d6cc75 ] + +Fix the following compilation warning: +fs/f2fs/data.c:2391:10: warning: variable ‘index’ set but not used +[-Wunused-but-set-variable] + 2391 | pgoff_t index; + +Only define and set the variable index when the CONFIG_F2FS_FS_COMPRESSION +is enabled. + +Fixes: db92e6c729d8 ("f2fs: convert f2fs_mpage_readpages() to use folio") +Signed-off-by: Zeng Heng <zengheng4@huawei.com> +Reviewed-by: Chao Yu <chao@kernel.org> +Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + fs/f2fs/data.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c +index 94f7b084f6016..9202082a3902c 100644 +--- a/fs/f2fs/data.c ++++ b/fs/f2fs/data.c +@@ -2385,10 +2385,10 @@ static int f2fs_mpage_readpages(struct inode *inode, + .nr_cpages = 0, + }; + pgoff_t nc_cluster_idx = NULL_CLUSTER; ++ pgoff_t index; + #endif + unsigned nr_pages = rac ? readahead_count(rac) : 1; + unsigned max_nr_pages = nr_pages; +- pgoff_t index; + int ret = 0; + + map.m_pblk = 0; +@@ -2406,9 +2406,9 @@ static int f2fs_mpage_readpages(struct inode *inode, + prefetchw(&folio->flags); + } + ++#ifdef CONFIG_F2FS_FS_COMPRESSION + index = folio_index(folio); + +-#ifdef CONFIG_F2FS_FS_COMPRESSION + if (!f2fs_compressed_file(inode)) + goto read_single_page; + +-- +2.43.0 + diff --git a/queue-6.12/f2fs-fix-null-ptr-deref-in-f2fs_submit_page_bio.patch b/queue-6.12/f2fs-fix-null-ptr-deref-in-f2fs_submit_page_bio.patch new file mode 100644 index 00000000000..3492c597acb --- /dev/null +++ b/queue-6.12/f2fs-fix-null-ptr-deref-in-f2fs_submit_page_bio.patch @@ -0,0 +1,100 @@ +From d6426ffb433f071bc49e33199c40cd4400c2ae45 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Sat, 12 Oct 2024 00:44:50 +0800 +Subject: f2fs: fix null-ptr-deref in f2fs_submit_page_bio() + +From: Ye Bin <yebin10@huawei.com> + +[ Upstream commit b7d0a97b28083084ebdd8e5c6bccd12e6ec18faa ] + +There's issue as follows when concurrently installing the f2fs.ko +module and mounting the f2fs file system: +KASAN: null-ptr-deref in range [0x0000000000000020-0x0000000000000027] +RIP: 0010:__bio_alloc+0x2fb/0x6c0 [f2fs] +Call Trace: + <TASK> + f2fs_submit_page_bio+0x126/0x8b0 [f2fs] + __get_meta_page+0x1d4/0x920 [f2fs] + get_checkpoint_version.constprop.0+0x2b/0x3c0 [f2fs] + validate_checkpoint+0xac/0x290 [f2fs] + f2fs_get_valid_checkpoint+0x207/0x950 [f2fs] + f2fs_fill_super+0x1007/0x39b0 [f2fs] + mount_bdev+0x183/0x250 + legacy_get_tree+0xf4/0x1e0 + vfs_get_tree+0x88/0x340 + do_new_mount+0x283/0x5e0 + path_mount+0x2b2/0x15b0 + __x64_sys_mount+0x1fe/0x270 + do_syscall_64+0x5f/0x170 + entry_SYSCALL_64_after_hwframe+0x76/0x7e + +Above issue happens as the biset of the f2fs file system is not +initialized before register "f2fs_fs_type". +To address above issue just register "f2fs_fs_type" at the last in +init_f2fs_fs(). Ensure that all f2fs file system resources are +initialized. + +Fixes: f543805fcd60 ("f2fs: introduce private bioset") +Signed-off-by: Ye Bin <yebin10@huawei.com> +Reviewed-by: Chao Yu <chao@kernel.org> +Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + fs/f2fs/super.c | 12 ++++++------ + 1 file changed, 6 insertions(+), 6 deletions(-) + +diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c +index 87ab5696bd482..8d4ecb2e855e6 100644 +--- a/fs/f2fs/super.c ++++ b/fs/f2fs/super.c +@@ -4991,9 +4991,6 @@ static int __init init_f2fs_fs(void) + err = f2fs_init_shrinker(); + if (err) + goto free_sysfs; +- err = register_filesystem(&f2fs_fs_type); +- if (err) +- goto free_shrinker; + f2fs_create_root_stats(); + err = f2fs_init_post_read_processing(); + if (err) +@@ -5016,7 +5013,12 @@ static int __init init_f2fs_fs(void) + err = f2fs_create_casefold_cache(); + if (err) + goto free_compress_cache; ++ err = register_filesystem(&f2fs_fs_type); ++ if (err) ++ goto free_casefold_cache; + return 0; ++free_casefold_cache: ++ f2fs_destroy_casefold_cache(); + free_compress_cache: + f2fs_destroy_compress_cache(); + free_compress_mempool: +@@ -5031,8 +5033,6 @@ static int __init init_f2fs_fs(void) + f2fs_destroy_post_read_processing(); + free_root_stats: + f2fs_destroy_root_stats(); +- unregister_filesystem(&f2fs_fs_type); +-free_shrinker: + f2fs_exit_shrinker(); + free_sysfs: + f2fs_exit_sysfs(); +@@ -5056,6 +5056,7 @@ static int __init init_f2fs_fs(void) + + static void __exit exit_f2fs_fs(void) + { ++ unregister_filesystem(&f2fs_fs_type); + f2fs_destroy_casefold_cache(); + f2fs_destroy_compress_cache(); + f2fs_destroy_compress_mempool(); +@@ -5064,7 +5065,6 @@ static void __exit exit_f2fs_fs(void) + f2fs_destroy_iostat_processing(); + f2fs_destroy_post_read_processing(); + f2fs_destroy_root_stats(); +- unregister_filesystem(&f2fs_fs_type); + f2fs_exit_shrinker(); + f2fs_exit_sysfs(); + f2fs_destroy_garbage_collection_cache(); +-- +2.43.0 + diff --git a/queue-6.12/f2fs-fix-race-in-concurrent-f2fs_stop_gc_thread.patch b/queue-6.12/f2fs-fix-race-in-concurrent-f2fs_stop_gc_thread.patch new file mode 100644 index 00000000000..2d9ab622d70 --- /dev/null +++ b/queue-6.12/f2fs-fix-race-in-concurrent-f2fs_stop_gc_thread.patch @@ -0,0 +1,93 @@ +From a738a4eaeb6e1066bf18d70e78d922d03982513a Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Mon, 4 Nov 2024 10:05:42 +0800 +Subject: f2fs: fix race in concurrent f2fs_stop_gc_thread + +From: Long Li <leo.lilong@huawei.com> + +[ Upstream commit 7b0033dbc48340a1c1c3f12448ba17d6587ca092 ] + +In my test case, concurrent calls to f2fs shutdown report the following +stack trace: + + Oops: general protection fault, probably for non-canonical address 0xc6cfff63bb5513fc: 0000 [#1] PREEMPT SMP PTI + CPU: 0 UID: 0 PID: 678 Comm: f2fs_rep_shutdo Not tainted 6.12.0-rc5-next-20241029-g6fb2fa9805c5-dirty #85 + Call Trace: + <TASK> + ? show_regs+0x8b/0xa0 + ? __die_body+0x26/0xa0 + ? die_addr+0x54/0x90 + ? exc_general_protection+0x24b/0x5c0 + ? asm_exc_general_protection+0x26/0x30 + ? kthread_stop+0x46/0x390 + f2fs_stop_gc_thread+0x6c/0x110 + f2fs_do_shutdown+0x309/0x3a0 + f2fs_ioc_shutdown+0x150/0x1c0 + __f2fs_ioctl+0xffd/0x2ac0 + f2fs_ioctl+0x76/0xe0 + vfs_ioctl+0x23/0x60 + __x64_sys_ioctl+0xce/0xf0 + x64_sys_call+0x2b1b/0x4540 + do_syscall_64+0xa7/0x240 + entry_SYSCALL_64_after_hwframe+0x76/0x7e + +The root cause is a race condition in f2fs_stop_gc_thread() called from +different f2fs shutdown paths: + + [CPU0] [CPU1] + ---------------------- ----------------------- + f2fs_stop_gc_thread f2fs_stop_gc_thread + gc_th = sbi->gc_thread + gc_th = sbi->gc_thread + kfree(gc_th) + sbi->gc_thread = NULL + < gc_th != NULL > + kthread_stop(gc_th->f2fs_gc_task) //UAF + +The commit c7f114d864ac ("f2fs: fix to avoid use-after-free in +f2fs_stop_gc_thread()") attempted to fix this issue by using a read +semaphore to prevent races between shutdown and remount threads, but +it fails to prevent all race conditions. + +Fix it by converting to write lock of s_umount in f2fs_do_shutdown(). + +Fixes: 7950e9ac638e ("f2fs: stop gc/discard thread after fs shutdown") +Signed-off-by: Long Li <leo.lilong@huawei.com> +Reviewed-by: Chao Yu <chao@kernel.org> +Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + fs/f2fs/file.c | 9 ++++++--- + 1 file changed, 6 insertions(+), 3 deletions(-) + +diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c +index adc7d64a6f47d..b96403ab7a925 100644 +--- a/fs/f2fs/file.c ++++ b/fs/f2fs/file.c +@@ -2343,9 +2343,12 @@ int f2fs_do_shutdown(struct f2fs_sb_info *sbi, unsigned int flag, + if (readonly) + goto out; + +- /* grab sb->s_umount to avoid racing w/ remount() */ ++ /* ++ * grab sb->s_umount to avoid racing w/ remount() and other shutdown ++ * paths. ++ */ + if (need_lock) +- down_read(&sbi->sb->s_umount); ++ down_write(&sbi->sb->s_umount); + + f2fs_stop_gc_thread(sbi); + f2fs_stop_discard_thread(sbi); +@@ -2354,7 +2357,7 @@ int f2fs_do_shutdown(struct f2fs_sb_info *sbi, unsigned int flag, + clear_opt(sbi, DISCARD); + + if (need_lock) +- up_read(&sbi->sb->s_umount); ++ up_write(&sbi->sb->s_umount); + + f2fs_update_time(sbi, REQ_TIME); + out: +-- +2.43.0 + diff --git a/queue-6.12/f2fs-fix-the-wrong-f2fs_bug_on-condition-in-f2fs_do_.patch b/queue-6.12/f2fs-fix-the-wrong-f2fs_bug_on-condition-in-f2fs_do_.patch new file mode 100644 index 00000000000..a24cf0e22b6 --- /dev/null +++ b/queue-6.12/f2fs-fix-the-wrong-f2fs_bug_on-condition-in-f2fs_do_.patch @@ -0,0 +1,40 @@ +From 0337ce078d0919eecc7a2dd9f6fe1fe137054317 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Mon, 21 Oct 2024 10:31:47 +0800 +Subject: f2fs: fix the wrong f2fs_bug_on condition in f2fs_do_replace_block + +From: LongPing Wei <weilongping@oppo.com> + +[ Upstream commit c3af1f13476ec23fd99c98d060a89be28c1e8871 ] + +This f2fs_bug_on was introduced by commit 2c1905042c8c ("f2fs: check +segment type in __f2fs_replace_block") when there were only 6 curseg types. +After commit d0b9e42ab615 ("f2fs: introduce inmem curseg") was introduced, +the condition should be changed to checking curseg->seg_type. + +Fixes: d0b9e42ab615 ("f2fs: introduce inmem curseg") +Signed-off-by: LongPing Wei <weilongping@oppo.com> +Reviewed-by: Chao Yu <chao@kernel.org> +Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + fs/f2fs/segment.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c +index 1766254279d24..7b54b1851d346 100644 +--- a/fs/f2fs/segment.c ++++ b/fs/f2fs/segment.c +@@ -3977,8 +3977,8 @@ void f2fs_do_replace_block(struct f2fs_sb_info *sbi, struct f2fs_summary *sum, + } + } + +- f2fs_bug_on(sbi, !IS_DATASEG(type)); + curseg = CURSEG_I(sbi, type); ++ f2fs_bug_on(sbi, !IS_DATASEG(curseg->seg_type)); + + mutex_lock(&curseg->curseg_mutex); + down_write(&sit_i->sentry_lock); +-- +2.43.0 + diff --git a/queue-6.12/f2fs-fix-to-account-dirty-data-in-__get_secs_require.patch b/queue-6.12/f2fs-fix-to-account-dirty-data-in-__get_secs_require.patch new file mode 100644 index 00000000000..5c1d88f494d --- /dev/null +++ b/queue-6.12/f2fs-fix-to-account-dirty-data-in-__get_secs_require.patch @@ -0,0 +1,132 @@ +From 5e262055c120ca8c3684eeeb6fd423c13afd2fb6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Tue, 15 Oct 2024 11:43:39 +0800 +Subject: f2fs: fix to account dirty data in __get_secs_required() + +From: Chao Yu <chao@kernel.org> + +[ Upstream commit 1acd73edbbfef2c3c5b43cba4006a7797eca7050 ] + +It will trigger system panic w/ testcase in [1]: + +------------[ cut here ]------------ +kernel BUG at fs/f2fs/segment.c:2752! +RIP: 0010:new_curseg+0xc81/0x2110 +Call Trace: + f2fs_allocate_data_block+0x1c91/0x4540 + do_write_page+0x163/0xdf0 + f2fs_outplace_write_data+0x1aa/0x340 + f2fs_do_write_data_page+0x797/0x2280 + f2fs_write_single_data_page+0x16cd/0x2190 + f2fs_write_cache_pages+0x994/0x1c80 + f2fs_write_data_pages+0x9cc/0xea0 + do_writepages+0x194/0x7a0 + filemap_fdatawrite_wbc+0x12b/0x1a0 + __filemap_fdatawrite_range+0xbb/0xf0 + file_write_and_wait_range+0xa1/0x110 + f2fs_do_sync_file+0x26f/0x1c50 + f2fs_sync_file+0x12b/0x1d0 + vfs_fsync_range+0xfa/0x230 + do_fsync+0x3d/0x80 + __x64_sys_fsync+0x37/0x50 + x64_sys_call+0x1e88/0x20d0 + do_syscall_64+0x4b/0x110 + entry_SYSCALL_64_after_hwframe+0x76/0x7e + +The root cause is if checkpoint_disabling and lfs_mode are both on, +it will trigger OPU for all overwritten data, it may cost more free +segment than expected, so f2fs must account those data correctly to +calculate cosumed free segments later, and return ENOSPC earlier to +avoid run out of free segment during block allocation. + +[1] https://lore.kernel.org/fstests/20241015025106.3203676-1-chao@kernel.org/ + +Fixes: 4354994f097d ("f2fs: checkpoint disabling") +Cc: Daniel Rosenberg <drosen@google.com> +Signed-off-by: Chao Yu <chao@kernel.org> +Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + fs/f2fs/segment.h | 35 +++++++++++++++++++++++++---------- + 1 file changed, 25 insertions(+), 10 deletions(-) + +diff --git a/fs/f2fs/segment.h b/fs/f2fs/segment.h +index 71adb4a43bec5..51b2b8c5c749c 100644 +--- a/fs/f2fs/segment.h ++++ b/fs/f2fs/segment.h +@@ -559,18 +559,21 @@ static inline int reserved_sections(struct f2fs_sb_info *sbi) + } + + static inline bool has_curseg_enough_space(struct f2fs_sb_info *sbi, +- unsigned int node_blocks, unsigned int dent_blocks) ++ unsigned int node_blocks, unsigned int data_blocks, ++ unsigned int dent_blocks) + { + +- unsigned segno, left_blocks; ++ unsigned int segno, left_blocks, blocks; + int i; + +- /* check current node sections in the worst case. */ +- for (i = CURSEG_HOT_NODE; i <= CURSEG_COLD_NODE; i++) { ++ /* check current data/node sections in the worst case. */ ++ for (i = CURSEG_HOT_DATA; i < NR_PERSISTENT_LOG; i++) { + segno = CURSEG_I(sbi, i)->segno; + left_blocks = CAP_BLKS_PER_SEC(sbi) - + get_ckpt_valid_blocks(sbi, segno, true); +- if (node_blocks > left_blocks) ++ ++ blocks = i <= CURSEG_COLD_DATA ? data_blocks : node_blocks; ++ if (blocks > left_blocks) + return false; + } + +@@ -584,8 +587,9 @@ static inline bool has_curseg_enough_space(struct f2fs_sb_info *sbi, + } + + /* +- * calculate needed sections for dirty node/dentry +- * and call has_curseg_enough_space ++ * calculate needed sections for dirty node/dentry and call ++ * has_curseg_enough_space, please note that, it needs to account ++ * dirty data as well in lfs mode when checkpoint is disabled. + */ + static inline void __get_secs_required(struct f2fs_sb_info *sbi, + unsigned int *lower_p, unsigned int *upper_p, bool *curseg_p) +@@ -594,19 +598,30 @@ static inline void __get_secs_required(struct f2fs_sb_info *sbi, + get_pages(sbi, F2FS_DIRTY_DENTS) + + get_pages(sbi, F2FS_DIRTY_IMETA); + unsigned int total_dent_blocks = get_pages(sbi, F2FS_DIRTY_DENTS); ++ unsigned int total_data_blocks = 0; + unsigned int node_secs = total_node_blocks / CAP_BLKS_PER_SEC(sbi); + unsigned int dent_secs = total_dent_blocks / CAP_BLKS_PER_SEC(sbi); ++ unsigned int data_secs = 0; + unsigned int node_blocks = total_node_blocks % CAP_BLKS_PER_SEC(sbi); + unsigned int dent_blocks = total_dent_blocks % CAP_BLKS_PER_SEC(sbi); ++ unsigned int data_blocks = 0; ++ ++ if (f2fs_lfs_mode(sbi) && ++ unlikely(is_sbi_flag_set(sbi, SBI_CP_DISABLED))) { ++ total_data_blocks = get_pages(sbi, F2FS_DIRTY_DATA); ++ data_secs = total_data_blocks / CAP_BLKS_PER_SEC(sbi); ++ data_blocks = total_data_blocks % CAP_BLKS_PER_SEC(sbi); ++ } + + if (lower_p) +- *lower_p = node_secs + dent_secs; ++ *lower_p = node_secs + dent_secs + data_secs; + if (upper_p) + *upper_p = node_secs + dent_secs + +- (node_blocks ? 1 : 0) + (dent_blocks ? 1 : 0); ++ (node_blocks ? 1 : 0) + (dent_blocks ? 1 : 0) + ++ (data_blocks ? 1 : 0); + if (curseg_p) + *curseg_p = has_curseg_enough_space(sbi, +- node_blocks, dent_blocks); ++ node_blocks, data_blocks, dent_blocks); + } + + static inline bool has_not_enough_free_secs(struct f2fs_sb_info *sbi, +-- +2.43.0 + diff --git a/queue-6.12/f2fs-fix-to-avoid-forcing-direct-write-to-use-buffer.patch b/queue-6.12/f2fs-fix-to-avoid-forcing-direct-write-to-use-buffer.patch new file mode 100644 index 00000000000..793558ad7f8 --- /dev/null +++ b/queue-6.12/f2fs-fix-to-avoid-forcing-direct-write-to-use-buffer.patch @@ -0,0 +1,49 @@ +From 16337136ade5f21bff16c5564908ac8468f5145c Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Mon, 4 Nov 2024 09:50:16 +0800 +Subject: f2fs: fix to avoid forcing direct write to use buffered IO on + inline_data inode + +From: Chao Yu <chao@kernel.org> + +[ Upstream commit 26e6f59d0bbaac76fa3413462d780bd2b5f9f653 ] + +Jinsu Lee reported a performance regression issue, after commit +5c8764f8679e ("f2fs: fix to force buffered IO on inline_data +inode"), we forced direct write to use buffered IO on inline_data +inode, it will cause performace regression due to memory copy +and data flush. + +It's fine to not force direct write to use buffered IO, as it +can convert inline inode before committing direct write IO. + +Fixes: 5c8764f8679e ("f2fs: fix to force buffered IO on inline_data inode") +Reported-by: Jinsu Lee <jinsu1.lee@samsung.com> +Closes: https://lore.kernel.org/linux-f2fs-devel/af03dd2c-e361-4f80-b2fd-39440766cf6e@kernel.org +Signed-off-by: Chao Yu <chao@kernel.org> +Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + fs/f2fs/file.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c +index b96403ab7a925..71ddecaf771f8 100644 +--- a/fs/f2fs/file.c ++++ b/fs/f2fs/file.c +@@ -863,7 +863,11 @@ static bool f2fs_force_buffered_io(struct inode *inode, int rw) + return true; + if (f2fs_compressed_file(inode)) + return true; +- if (f2fs_has_inline_data(inode)) ++ /* ++ * only force direct read to use buffered IO, for direct write, ++ * it expects inline data conversion before committing IO. ++ */ ++ if (f2fs_has_inline_data(inode) && rw == READ) + return true; + + /* disallow direct IO if any of devices has unaligned blksize */ +-- +2.43.0 + diff --git a/queue-6.12/f2fs-fix-to-avoid-potential-deadlock-in-f2fs_record_.patch b/queue-6.12/f2fs-fix-to-avoid-potential-deadlock-in-f2fs_record_.patch new file mode 100644 index 00000000000..4bc6327a9db --- /dev/null +++ b/queue-6.12/f2fs-fix-to-avoid-potential-deadlock-in-f2fs_record_.patch @@ -0,0 +1,230 @@ +From fae38a6177541dd3d52569174574cade15389330 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Tue, 22 Oct 2024 16:36:23 +0800 +Subject: f2fs: fix to avoid potential deadlock in f2fs_record_stop_reason() + +From: Chao Yu <chao@kernel.org> + +[ Upstream commit f10a890308a7cd8794e21f646f09827c6cb4bf5d ] + +syzbot reports deadlock issue of f2fs as below: + +====================================================== +WARNING: possible circular locking dependency detected +6.12.0-rc3-syzkaller-00087-gc964ced77262 #0 Not tainted +------------------------------------------------------ +kswapd0/79 is trying to acquire lock: +ffff888011824088 (&sbi->sb_lock){++++}-{3:3}, at: f2fs_down_write fs/f2fs/f2fs.h:2199 [inline] +ffff888011824088 (&sbi->sb_lock){++++}-{3:3}, at: f2fs_record_stop_reason+0x52/0x1d0 fs/f2fs/super.c:4068 + +but task is already holding lock: +ffff88804bd92610 (sb_internal#2){.+.+}-{0:0}, at: f2fs_evict_inode+0x662/0x15c0 fs/f2fs/inode.c:842 + +which lock already depends on the new lock. + +the existing dependency chain (in reverse order) is: + +-> #2 (sb_internal#2){.+.+}-{0:0}: + lock_acquire+0x1ed/0x550 kernel/locking/lockdep.c:5825 + percpu_down_read include/linux/percpu-rwsem.h:51 [inline] + __sb_start_write include/linux/fs.h:1716 [inline] + sb_start_intwrite+0x4d/0x1c0 include/linux/fs.h:1899 + f2fs_evict_inode+0x662/0x15c0 fs/f2fs/inode.c:842 + evict+0x4e8/0x9b0 fs/inode.c:725 + f2fs_evict_inode+0x1a4/0x15c0 fs/f2fs/inode.c:807 + evict+0x4e8/0x9b0 fs/inode.c:725 + dispose_list fs/inode.c:774 [inline] + prune_icache_sb+0x239/0x2f0 fs/inode.c:963 + super_cache_scan+0x38c/0x4b0 fs/super.c:223 + do_shrink_slab+0x701/0x1160 mm/shrinker.c:435 + shrink_slab+0x1093/0x14d0 mm/shrinker.c:662 + shrink_one+0x43b/0x850 mm/vmscan.c:4818 + shrink_many mm/vmscan.c:4879 [inline] + lru_gen_shrink_node mm/vmscan.c:4957 [inline] + shrink_node+0x3799/0x3de0 mm/vmscan.c:5937 + kswapd_shrink_node mm/vmscan.c:6765 [inline] + balance_pgdat mm/vmscan.c:6957 [inline] + kswapd+0x1ca3/0x3700 mm/vmscan.c:7226 + kthread+0x2f0/0x390 kernel/kthread.c:389 + ret_from_fork+0x4b/0x80 arch/x86/kernel/process.c:147 + ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:244 + +-> #1 (fs_reclaim){+.+.}-{0:0}: + lock_acquire+0x1ed/0x550 kernel/locking/lockdep.c:5825 + __fs_reclaim_acquire mm/page_alloc.c:3834 [inline] + fs_reclaim_acquire+0x88/0x130 mm/page_alloc.c:3848 + might_alloc include/linux/sched/mm.h:318 [inline] + prepare_alloc_pages+0x147/0x5b0 mm/page_alloc.c:4493 + __alloc_pages_noprof+0x16f/0x710 mm/page_alloc.c:4722 + alloc_pages_mpol_noprof+0x3e8/0x680 mm/mempolicy.c:2265 + alloc_pages_noprof mm/mempolicy.c:2345 [inline] + folio_alloc_noprof+0x128/0x180 mm/mempolicy.c:2352 + filemap_alloc_folio_noprof+0xdf/0x500 mm/filemap.c:1010 + do_read_cache_folio+0x2eb/0x850 mm/filemap.c:3787 + read_mapping_folio include/linux/pagemap.h:1011 [inline] + f2fs_commit_super+0x3c0/0x7d0 fs/f2fs/super.c:4032 + f2fs_record_stop_reason+0x13b/0x1d0 fs/f2fs/super.c:4079 + f2fs_handle_critical_error+0x2ac/0x5c0 fs/f2fs/super.c:4174 + f2fs_write_inode+0x35f/0x4d0 fs/f2fs/inode.c:785 + write_inode fs/fs-writeback.c:1503 [inline] + __writeback_single_inode+0x711/0x10d0 fs/fs-writeback.c:1723 + writeback_single_inode+0x1f3/0x660 fs/fs-writeback.c:1779 + sync_inode_metadata+0xc4/0x120 fs/fs-writeback.c:2849 + f2fs_release_file+0xa8/0x100 fs/f2fs/file.c:1941 + __fput+0x23f/0x880 fs/file_table.c:431 + task_work_run+0x24f/0x310 kernel/task_work.c:228 + resume_user_mode_work include/linux/resume_user_mode.h:50 [inline] + exit_to_user_mode_loop kernel/entry/common.c:114 [inline] + exit_to_user_mode_prepare include/linux/entry-common.h:328 [inline] + __syscall_exit_to_user_mode_work kernel/entry/common.c:207 [inline] + syscall_exit_to_user_mode+0x168/0x370 kernel/entry/common.c:218 + do_syscall_64+0x100/0x230 arch/x86/entry/common.c:89 + entry_SYSCALL_64_after_hwframe+0x77/0x7f + +-> #0 (&sbi->sb_lock){++++}-{3:3}: + check_prev_add kernel/locking/lockdep.c:3161 [inline] + check_prevs_add kernel/locking/lockdep.c:3280 [inline] + validate_chain+0x18ef/0x5920 kernel/locking/lockdep.c:3904 + __lock_acquire+0x1384/0x2050 kernel/locking/lockdep.c:5202 + lock_acquire+0x1ed/0x550 kernel/locking/lockdep.c:5825 + down_write+0x99/0x220 kernel/locking/rwsem.c:1577 + f2fs_down_write fs/f2fs/f2fs.h:2199 [inline] + f2fs_record_stop_reason+0x52/0x1d0 fs/f2fs/super.c:4068 + f2fs_handle_critical_error+0x2ac/0x5c0 fs/f2fs/super.c:4174 + f2fs_evict_inode+0xa61/0x15c0 fs/f2fs/inode.c:883 + evict+0x4e8/0x9b0 fs/inode.c:725 + f2fs_evict_inode+0x1a4/0x15c0 fs/f2fs/inode.c:807 + evict+0x4e8/0x9b0 fs/inode.c:725 + dispose_list fs/inode.c:774 [inline] + prune_icache_sb+0x239/0x2f0 fs/inode.c:963 + super_cache_scan+0x38c/0x4b0 fs/super.c:223 + do_shrink_slab+0x701/0x1160 mm/shrinker.c:435 + shrink_slab+0x1093/0x14d0 mm/shrinker.c:662 + shrink_one+0x43b/0x850 mm/vmscan.c:4818 + shrink_many mm/vmscan.c:4879 [inline] + lru_gen_shrink_node mm/vmscan.c:4957 [inline] + shrink_node+0x3799/0x3de0 mm/vmscan.c:5937 + kswapd_shrink_node mm/vmscan.c:6765 [inline] + balance_pgdat mm/vmscan.c:6957 [inline] + kswapd+0x1ca3/0x3700 mm/vmscan.c:7226 + kthread+0x2f0/0x390 kernel/kthread.c:389 + ret_from_fork+0x4b/0x80 arch/x86/kernel/process.c:147 + ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:244 + +other info that might help us debug this: + +Chain exists of: + &sbi->sb_lock --> fs_reclaim --> sb_internal#2 + + Possible unsafe locking scenario: + + CPU0 CPU1 + ---- ---- + rlock(sb_internal#2); + lock(fs_reclaim); + lock(sb_internal#2); + lock(&sbi->sb_lock); + +Root cause is there will be potential deadlock in between +below tasks: + +Thread A Kswapd +- f2fs_ioc_commit_atomic_write + - mnt_want_write_file -- down_read lock A + - balance_pgdat + - __fs_reclaim_acquire -- lock B + - shrink_node + - prune_icache_sb + - dispose_list + - f2fs_evict_inode + - sb_start_intwrite -- down_read lock A + - f2fs_do_sync_file + - f2fs_write_inode + - f2fs_handle_critical_error + - f2fs_record_stop_reason + - f2fs_commit_super + - read_mapping_folio + - filemap_alloc_folio_noprof + - fs_reclaim_acquire -- lock B + +Both threads try to acquire read lock of lock A, then its upcoming write +lock grabber will trigger deadlock. + +Let's always create an asynchronous task in f2fs_handle_critical_error() +rather than calling f2fs_record_stop_reason() synchronously to avoid +this potential deadlock issue. + +Fixes: b62e71be2110 ("f2fs: support errors=remount-ro|continue|panic mountoption") +Reported-by: syzbot+be4a9983e95a5e25c8d3@syzkaller.appspotmail.com +Closes: https://lore.kernel.org/all/6704d667.050a0220.1e4d62.0081.GAE@google.com +Signed-off-by: Chao Yu <chao@kernel.org> +Reviewed-by: Daejun Park <daejun7.park@samsung.com> +Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + fs/f2fs/checkpoint.c | 2 +- + fs/f2fs/f2fs.h | 3 +-- + fs/f2fs/super.c | 13 +++++++------ + 3 files changed, 9 insertions(+), 9 deletions(-) + +diff --git a/fs/f2fs/checkpoint.c b/fs/f2fs/checkpoint.c +index 7f76460b721f2..efda9a0229816 100644 +--- a/fs/f2fs/checkpoint.c ++++ b/fs/f2fs/checkpoint.c +@@ -32,7 +32,7 @@ void f2fs_stop_checkpoint(struct f2fs_sb_info *sbi, bool end_io, + f2fs_build_fault_attr(sbi, 0, 0); + if (!end_io) + f2fs_flush_merged_writes(sbi); +- f2fs_handle_critical_error(sbi, reason, end_io); ++ f2fs_handle_critical_error(sbi, reason); + } + + /* +diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h +index 33f5449dc22d5..93a5e1c24e566 100644 +--- a/fs/f2fs/f2fs.h ++++ b/fs/f2fs/f2fs.h +@@ -3632,8 +3632,7 @@ int f2fs_quota_sync(struct super_block *sb, int type); + loff_t max_file_blocks(struct inode *inode); + void f2fs_quota_off_umount(struct super_block *sb); + void f2fs_save_errors(struct f2fs_sb_info *sbi, unsigned char flag); +-void f2fs_handle_critical_error(struct f2fs_sb_info *sbi, unsigned char reason, +- bool irq_context); ++void f2fs_handle_critical_error(struct f2fs_sb_info *sbi, unsigned char reason); + void f2fs_handle_error(struct f2fs_sb_info *sbi, unsigned char error); + void f2fs_handle_error_async(struct f2fs_sb_info *sbi, unsigned char error); + int f2fs_commit_super(struct f2fs_sb_info *sbi, bool recover); +diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c +index 8d4ecb2e855e6..0b5114caa37a1 100644 +--- a/fs/f2fs/super.c ++++ b/fs/f2fs/super.c +@@ -4155,8 +4155,7 @@ static bool system_going_down(void) + || system_state == SYSTEM_RESTART; + } + +-void f2fs_handle_critical_error(struct f2fs_sb_info *sbi, unsigned char reason, +- bool irq_context) ++void f2fs_handle_critical_error(struct f2fs_sb_info *sbi, unsigned char reason) + { + struct super_block *sb = sbi->sb; + bool shutdown = reason == STOP_CP_REASON_SHUTDOWN; +@@ -4168,10 +4167,12 @@ void f2fs_handle_critical_error(struct f2fs_sb_info *sbi, unsigned char reason, + if (!f2fs_hw_is_readonly(sbi)) { + save_stop_reason(sbi, reason); + +- if (irq_context && !shutdown) +- schedule_work(&sbi->s_error_work); +- else +- f2fs_record_stop_reason(sbi); ++ /* ++ * always create an asynchronous task to record stop_reason ++ * in order to avoid potential deadlock when running into ++ * f2fs_record_stop_reason() synchronously. ++ */ ++ schedule_work(&sbi->s_error_work); + } + + /* +-- +2.43.0 + diff --git a/queue-6.12/f2fs-fix-to-avoid-use-gc_at-when-setting-gc_mode-as-.patch b/queue-6.12/f2fs-fix-to-avoid-use-gc_at-when-setting-gc_mode-as-.patch new file mode 100644 index 00000000000..545ad61eb84 --- /dev/null +++ b/queue-6.12/f2fs-fix-to-avoid-use-gc_at-when-setting-gc_mode-as-.patch @@ -0,0 +1,70 @@ +From 23de4c99a74a072da7fe4c78a03b8b45a653e860 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Tue, 29 Oct 2024 11:12:49 +0800 +Subject: f2fs: fix to avoid use GC_AT when setting gc_mode as GC_URGENT_LOW or + GC_URGENT_MID + +From: Zhiguo Niu <zhiguo.niu@unisoc.com> + +[ Upstream commit 296b8cb34e65fa93382cf919be5a056f719c9a26 ] + +If gc_mode is set to GC_URGENT_LOW or GC_URGENT_MID, cost benefit GC +approach should be used, but if ATGC is enabled at the same time, +Age-threshold approach will be selected, which can only do amount of +GC and it is much less than the numbers of CB approach. + +some traces: + f2fs_gc-254:48-396 [007] ..... 2311600.684028: f2fs_gc_begin: dev = (254,48), gc_type = Background GC, no_background_GC = 0, nr_free_secs = 0, nodes = 1053, dents = 2, imeta = 18, free_sec:44898, free_seg:44898, rsv_seg:239, prefree_seg:0 + f2fs_gc-254:48-396 [007] ..... 2311600.684527: f2fs_get_victim: dev = (254,48), type = No TYPE, policy = (Background GC, LFS-mode, Age-threshold), victim = 10, cost = 4294364975, ofs_unit = 1, pre_victim_secno = -1, prefree = 0, free = 44898 + f2fs_gc-254:48-396 [007] ..... 2311600.714835: f2fs_gc_end: dev = (254,48), ret = 0, seg_freed = 0, sec_freed = 0, nodes = 1562, dents = 2, imeta = 18, free_sec:44898, free_seg:44898, rsv_seg:239, prefree_seg:0 + f2fs_gc-254:48-396 [007] ..... 2311600.714843: f2fs_background_gc: dev = (254,48), wait_ms = 50, prefree = 0, free = 44898 + f2fs_gc-254:48-396 [007] ..... 2311600.771785: f2fs_gc_begin: dev = (254,48), gc_type = Background GC, no_background_GC = 0, nr_free_secs = 0, nodes = 1562, dents = 2, imeta = 18, free_sec:44898, free_seg:44898, rsv_seg:239, prefree_seg: + f2fs_gc-254:48-396 [007] ..... 2311600.772275: f2fs_gc_end: dev = (254,48), ret = -61, seg_freed = 0, sec_freed = 0, nodes = 1562, dents = 2, imeta = 18, free_sec:44898, free_seg:44898, rsv_seg:239, prefree_seg:0 + +Fixes: 0e5e81114de1 ("f2fs: add GC_URGENT_LOW mode in gc_urgent") +Fixes: d98af5f45520 ("f2fs: introduce gc_urgent_mid mode") +Signed-off-by: Zhiguo Niu <zhiguo.niu@unisoc.com> +Reviewed-by: Chao Yu <chao@kernel.org> +Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + Documentation/ABI/testing/sysfs-fs-f2fs | 7 +++++-- + fs/f2fs/gc.c | 2 ++ + 2 files changed, 7 insertions(+), 2 deletions(-) + +diff --git a/Documentation/ABI/testing/sysfs-fs-f2fs b/Documentation/ABI/testing/sysfs-fs-f2fs +index fdedf1ea944ba..513296bb6f297 100644 +--- a/Documentation/ABI/testing/sysfs-fs-f2fs ++++ b/Documentation/ABI/testing/sysfs-fs-f2fs +@@ -311,10 +311,13 @@ Description: Do background GC aggressively when set. Set to 0 by default. + GC approach and turns SSR mode on. + gc urgent low(2): lowers the bar of checking I/O idling in + order to process outstanding discard commands and GC a +- little bit aggressively. uses cost benefit GC approach. ++ little bit aggressively. always uses cost benefit GC approach, ++ and will override age-threshold GC approach if ATGC is enabled ++ at the same time. + gc urgent mid(3): does GC forcibly in a period of given + gc_urgent_sleep_time and executes a mid level of I/O idling check. +- uses cost benefit GC approach. ++ always uses cost benefit GC approach, and will override ++ age-threshold GC approach if ATGC is enabled at the same time. + + What: /sys/fs/f2fs/<disk>/gc_urgent_sleep_time + Date: August 2017 +diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c +index 9322a7200e310..e0469316c7cd4 100644 +--- a/fs/f2fs/gc.c ++++ b/fs/f2fs/gc.c +@@ -257,6 +257,8 @@ static int select_gc_type(struct f2fs_sb_info *sbi, int gc_type) + + switch (sbi->gc_mode) { + case GC_IDLE_CB: ++ case GC_URGENT_LOW: ++ case GC_URGENT_MID: + gc_mode = GC_CB; + break; + case GC_IDLE_GREEDY: +-- +2.43.0 + diff --git a/queue-6.12/f2fs-fix-to-do-cast-in-f2fs_-blk_to_bytes-btyes_to_b.patch b/queue-6.12/f2fs-fix-to-do-cast-in-f2fs_-blk_to_bytes-btyes_to_b.patch new file mode 100644 index 00000000000..e7c8687e053 --- /dev/null +++ b/queue-6.12/f2fs-fix-to-do-cast-in-f2fs_-blk_to_bytes-btyes_to_b.patch @@ -0,0 +1,56 @@ +From 54de1011f564f49b2301c1c258f428cd6bea6270 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Fri, 8 Nov 2024 09:25:54 +0800 +Subject: f2fs: fix to do cast in F2FS_{BLK_TO_BYTES, BTYES_TO_BLK} to avoid + overflow + +From: Chao Yu <chao@kernel.org> + +[ Upstream commit 3273d8ad947dea925a65a78ca29e5351c960c801 ] + +It missed to cast variable to unsigned long long type before +bit shift, which will cause overflow, fix it. + +Fixes: f7ef9b83b583 ("f2fs: introduce macros to convert bytes and blocks in f2fs") +Signed-off-by: Chao Yu <chao@kernel.org> +Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + fs/f2fs/super.c | 2 +- + include/linux/f2fs_fs.h | 6 +++--- + 2 files changed, 4 insertions(+), 4 deletions(-) + +diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c +index 0b5114caa37a1..dc1cb2e9269f4 100644 +--- a/fs/f2fs/super.c ++++ b/fs/f2fs/super.c +@@ -3322,7 +3322,7 @@ loff_t max_file_blocks(struct inode *inode) + * fit within U32_MAX + 1 data units. + */ + +- result = min(result, F2FS_BYTES_TO_BLK(((loff_t)U32_MAX + 1) * 4096)); ++ result = umin(result, F2FS_BYTES_TO_BLK(((loff_t)U32_MAX + 1) * 4096)); + + return result; + } +diff --git a/include/linux/f2fs_fs.h b/include/linux/f2fs_fs.h +index b0b821edfd97d..3b2ad444c002e 100644 +--- a/include/linux/f2fs_fs.h ++++ b/include/linux/f2fs_fs.h +@@ -24,10 +24,10 @@ + #define NEW_ADDR ((block_t)-1) /* used as block_t addresses */ + #define COMPRESS_ADDR ((block_t)-2) /* used as compressed data flag */ + +-#define F2FS_BYTES_TO_BLK(bytes) ((bytes) >> F2FS_BLKSIZE_BITS) +-#define F2FS_BLK_TO_BYTES(blk) ((blk) << F2FS_BLKSIZE_BITS) ++#define F2FS_BYTES_TO_BLK(bytes) ((unsigned long long)(bytes) >> F2FS_BLKSIZE_BITS) ++#define F2FS_BLK_TO_BYTES(blk) ((unsigned long long)(blk) << F2FS_BLKSIZE_BITS) + #define F2FS_BLK_END_BYTES(blk) (F2FS_BLK_TO_BYTES(blk + 1) - 1) +-#define F2FS_BLK_ALIGN(x) (F2FS_BYTES_TO_BLK((x) + F2FS_BLKSIZE - 1)) ++#define F2FS_BLK_ALIGN(x) (F2FS_BYTES_TO_BLK((x) + F2FS_BLKSIZE - 1)) + + /* 0, 1(node nid), 2(meta nid) are reserved node id */ + #define F2FS_RESERVED_NODE_NUM 3 +-- +2.43.0 + diff --git a/queue-6.12/f2fs-fix-to-map-blocks-correctly-for-direct-write.patch b/queue-6.12/f2fs-fix-to-map-blocks-correctly-for-direct-write.patch new file mode 100644 index 00000000000..e0c966e2a82 --- /dev/null +++ b/queue-6.12/f2fs-fix-to-map-blocks-correctly-for-direct-write.patch @@ -0,0 +1,43 @@ +From 5dec58105496ef09d7a4764c53eab58b97c858d4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Mon, 4 Nov 2024 09:35:51 +0800 +Subject: f2fs: fix to map blocks correctly for direct write + +From: Chao Yu <chao@kernel.org> + +[ Upstream commit 5dd00ebda337b9295e7027691fa70540da369ff2 ] + +f2fs_map_blocks() supports to map continuous holes or preallocated +address, we should avoid setting F2FS_MAP_MAPPED for these cases +only, otherwise, it may fail f2fs_iomap_begin(), and make direct +write fallbacking to use buffered IO and flush, result in performance +regression. + +Fixes: 9f0f6bf42714 ("f2fs: support to map continuous holes or preallocated address") +Reported-by: kernel test robot <oliver.sang@intel.com> +Closes: https://lore.kernel.org/oe-lkp/202409122103.e45aa13b-oliver.sang@intel.com +Cc: Cyril Hrubis <chrubis@suse.cz> +Signed-off-by: Chao Yu <chao@kernel.org> +Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + fs/f2fs/data.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c +index 9202082a3902c..3439f72052ee8 100644 +--- a/fs/f2fs/data.c ++++ b/fs/f2fs/data.c +@@ -1676,7 +1676,8 @@ int f2fs_map_blocks(struct inode *inode, struct f2fs_map_blocks *map, int flag) + /* reserved delalloc block should be mapped for fiemap. */ + if (blkaddr == NEW_ADDR) + map->m_flags |= F2FS_MAP_DELALLOC; +- if (flag != F2FS_GET_BLOCK_DIO || !is_hole) ++ /* DIO READ and hole case, should not map the blocks. */ ++ if (!(flag == F2FS_GET_BLOCK_DIO && is_hole && !map->m_may_create)) + map->m_flags |= F2FS_MAP_MAPPED; + + map->m_pblk = blkaddr; +-- +2.43.0 + diff --git a/queue-6.12/fadump-reserve-param-area-if-below-boot_mem_top.patch b/queue-6.12/fadump-reserve-param-area-if-below-boot_mem_top.patch new file mode 100644 index 00000000000..b979fa0c493 --- /dev/null +++ b/queue-6.12/fadump-reserve-param-area-if-below-boot_mem_top.patch @@ -0,0 +1,46 @@ +From add174fc65fbd783affc5f61983ab87bdd08233f Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Thu, 7 Nov 2024 11:28:17 +0530 +Subject: fadump: reserve param area if below boot_mem_top + +From: Sourabh Jain <sourabhjain@linux.ibm.com> + +[ Upstream commit fb90dca828b6070709093934c6dec56489a2d91d ] + +The param area is a memory region where the kernel places additional +command-line arguments for fadump kernel. Currently, the param memory +area is reserved in fadump kernel if it is above boot_mem_top. However, +it should be reserved if it is below boot_mem_top because the fadump +kernel already reserves memory from boot_mem_top to the end of DRAM. + +Currently, there is no impact from not reserving param memory if it is +below boot_mem_top, as it is not used after the early boot phase of the +fadump kernel. However, if this changes in the future, it could lead to +issues in the fadump kernel. + +Fixes: 3416c9daa6b1 ("powerpc/fadump: pass additional parameters when fadump is active") +Acked-by: Hari Bathini <hbathini@linux.ibm.com> +Signed-off-by: Sourabh Jain <sourabhjain@linux.ibm.com> +Signed-off-by: Michael Ellerman <mpe@ellerman.id.au> +Link: https://patch.msgid.link/20241107055817.489795-2-sourabhjain@linux.ibm.com +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + arch/powerpc/kernel/fadump.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/arch/powerpc/kernel/fadump.c b/arch/powerpc/kernel/fadump.c +index 6ab7934d719f7..4641de75f7fc1 100644 +--- a/arch/powerpc/kernel/fadump.c ++++ b/arch/powerpc/kernel/fadump.c +@@ -136,7 +136,7 @@ void __init fadump_append_bootargs(void) + if (!fw_dump.dump_active || !fw_dump.param_area_supported || !fw_dump.param_area) + return; + +- if (fw_dump.param_area >= fw_dump.boot_mem_top) { ++ if (fw_dump.param_area < fw_dump.boot_mem_top) { + if (memblock_reserve(fw_dump.param_area, COMMAND_LINE_SIZE)) { + pr_warn("WARNING: Can't use additional parameters area!\n"); + fw_dump.param_area = 0; +-- +2.43.0 + diff --git a/queue-6.12/fbdev-sh7760fb-fix-a-possible-memory-leak-in-sh7760f.patch b/queue-6.12/fbdev-sh7760fb-fix-a-possible-memory-leak-in-sh7760f.patch new file mode 100644 index 00000000000..e8842176dee --- /dev/null +++ b/queue-6.12/fbdev-sh7760fb-fix-a-possible-memory-leak-in-sh7760f.patch @@ -0,0 +1,43 @@ +From fe5de6f734322645c0fbf4db1a3dd1ac0629fbd3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Sat, 26 Oct 2024 11:56:34 +0800 +Subject: fbdev: sh7760fb: Fix a possible memory leak in sh7760fb_alloc_mem() + +From: Zhen Lei <thunder.leizhen@huawei.com> + +[ Upstream commit f89d17ae2ac42931be2a0153fecbf8533280c927 ] + +When information such as info->screen_base is not ready, calling +sh7760fb_free_mem() does not release memory correctly. Call +dma_free_coherent() instead. + +Fixes: 4a25e41831ee ("video: sh7760fb: SH7760/SH7763 LCDC framebuffer driver") +Signed-off-by: Zhen Lei <thunder.leizhen@huawei.com> +Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org> +Signed-off-by: Helge Deller <deller@gmx.de> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/video/fbdev/sh7760fb.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/drivers/video/fbdev/sh7760fb.c b/drivers/video/fbdev/sh7760fb.c +index 3d2a27fefc874..130adef2e4686 100644 +--- a/drivers/video/fbdev/sh7760fb.c ++++ b/drivers/video/fbdev/sh7760fb.c +@@ -409,12 +409,11 @@ static int sh7760fb_alloc_mem(struct fb_info *info) + vram = PAGE_SIZE; + + fbmem = dma_alloc_coherent(info->device, vram, &par->fbdma, GFP_KERNEL); +- + if (!fbmem) + return -ENOMEM; + + if ((par->fbdma & SH7760FB_DMA_MASK) != SH7760FB_DMA_MASK) { +- sh7760fb_free_mem(info); ++ dma_free_coherent(info->device, vram, fbmem, par->fbdma); + dev_err(info->device, "kernel gave me memory at 0x%08lx, which is" + "unusable for the LCDC\n", (unsigned long)par->fbdma); + return -ENOMEM; +-- +2.43.0 + diff --git a/queue-6.12/firmware-arm_scpi-check-the-dvfs-opp-count-returned-.patch b/queue-6.12/firmware-arm_scpi-check-the-dvfs-opp-count-returned-.patch new file mode 100644 index 00000000000..87e3a15cc3e --- /dev/null +++ b/queue-6.12/firmware-arm_scpi-check-the-dvfs-opp-count-returned-.patch @@ -0,0 +1,93 @@ +From cf7c42eb4a9ecc9771825669b46a8a5f3ce099d1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Fri, 1 Nov 2024 11:21:15 +0800 +Subject: firmware: arm_scpi: Check the DVFS OPP count returned by the firmware + +From: Luo Qiu <luoqiu@kylinsec.com.cn> + +[ Upstream commit 109aa654f85c5141e813b2cd1bd36d90be678407 ] + +Fix a kernel crash with the below call trace when the SCPI firmware +returns OPP count of zero. + +dvfs_info.opp_count may be zero on some platforms during the reboot +test, and the kernel will crash after dereferencing the pointer to +kcalloc(info->count, sizeof(*opp), GFP_KERNEL). + + | Unable to handle kernel NULL pointer dereference at virtual address 0000000000000028 + | Mem abort info: + | ESR = 0x96000004 + | Exception class = DABT (current EL), IL = 32 bits + | SET = 0, FnV = 0 + | EA = 0, S1PTW = 0 + | Data abort info: + | ISV = 0, ISS = 0x00000004 + | CM = 0, WnR = 0 + | user pgtable: 4k pages, 48-bit VAs, pgdp = 00000000faefa08c + | [0000000000000028] pgd=0000000000000000 + | Internal error: Oops: 96000004 [#1] SMP + | scpi-hwmon: probe of PHYT000D:00 failed with error -110 + | Process systemd-udevd (pid: 1701, stack limit = 0x00000000aaede86c) + | CPU: 2 PID: 1701 Comm: systemd-udevd Not tainted 4.19.90+ #1 + | Hardware name: PHYTIUM LTD Phytium FT2000/4/Phytium FT2000/4, BIOS + | pstate: 60000005 (nZCv daif -PAN -UAO) + | pc : scpi_dvfs_recalc_rate+0x40/0x58 [clk_scpi] + | lr : clk_register+0x438/0x720 + | Call trace: + | scpi_dvfs_recalc_rate+0x40/0x58 [clk_scpi] + | devm_clk_hw_register+0x50/0xa0 + | scpi_clk_ops_init.isra.2+0xa0/0x138 [clk_scpi] + | scpi_clocks_probe+0x528/0x70c [clk_scpi] + | platform_drv_probe+0x58/0xa8 + | really_probe+0x260/0x3d0 + | driver_probe_device+0x12c/0x148 + | device_driver_attach+0x74/0x98 + | __driver_attach+0xb4/0xe8 + | bus_for_each_dev+0x88/0xe0 + | driver_attach+0x30/0x40 + | bus_add_driver+0x178/0x2b0 + | driver_register+0x64/0x118 + | __platform_driver_register+0x54/0x60 + | scpi_clocks_driver_init+0x24/0x1000 [clk_scpi] + | do_one_initcall+0x54/0x220 + | do_init_module+0x54/0x1c8 + | load_module+0x14a4/0x1668 + | __se_sys_finit_module+0xf8/0x110 + | __arm64_sys_finit_module+0x24/0x30 + | el0_svc_common+0x78/0x170 + | el0_svc_handler+0x38/0x78 + | el0_svc+0x8/0x340 + | Code: 937d7c00 a94153f3 a8c27bfd f9400421 (b8606820) + | ---[ end trace 06feb22469d89fa8 ]--- + | Kernel panic - not syncing: Fatal exception + | SMP: stopping secondary CPUs + | Kernel Offset: disabled + | CPU features: 0x10,a0002008 + | Memory Limit: none + +Fixes: 8cb7cf56c9fe ("firmware: add support for ARM System Control and Power Interface(SCPI) protocol") +Signed-off-by: Luo Qiu <luoqiu@kylinsec.com.cn> +Message-Id: <55A2F7A784391686+20241101032115.275977-1-luoqiu@kylinsec.com.cn> +Signed-off-by: Sudeep Holla <sudeep.holla@arm.com> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/firmware/arm_scpi.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/firmware/arm_scpi.c b/drivers/firmware/arm_scpi.c +index 94a6b4e667de1..f4d47577f83ee 100644 +--- a/drivers/firmware/arm_scpi.c ++++ b/drivers/firmware/arm_scpi.c +@@ -630,6 +630,9 @@ static struct scpi_dvfs_info *scpi_dvfs_get_info(u8 domain) + if (ret) + return ERR_PTR(ret); + ++ if (!buf.opp_count) ++ return ERR_PTR(-ENOENT); ++ + info = kmalloc(sizeof(*info), GFP_KERNEL); + if (!info) + return ERR_PTR(-ENOMEM); +-- +2.43.0 + diff --git a/queue-6.12/firmware-google-unregister-driver_info-on-failure.patch b/queue-6.12/firmware-google-unregister-driver_info-on-failure.patch new file mode 100644 index 00000000000..6f5a4aed11e --- /dev/null +++ b/queue-6.12/firmware-google-unregister-driver_info-on-failure.patch @@ -0,0 +1,53 @@ +From 9fbcb6cff57873e4e7791050c6d6aaa0131e34e7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Tue, 15 Oct 2024 21:13:44 +0800 +Subject: firmware: google: Unregister driver_info on failure + +From: Yuan Can <yuancan@huawei.com> + +[ Upstream commit 32b0901e141f6d4cf49d820b53eb09b88b1f72f7 ] + +When platform_device_register_full() returns error, the gsmi_init() returns +without unregister gsmi_driver_info, fix by add missing +platform_driver_unregister() when platform_device_register_full() failed. + +Fixes: 8942b2d5094b ("gsmi: Add GSMI commands to log S0ix info") +Signed-off-by: Yuan Can <yuancan@huawei.com> +Acked-by: Brian Norris <briannorris@chromium.org> +Link: https://lore.kernel.org/r/20241015131344.20272-1-yuancan@huawei.com +Signed-off-by: Tzung-Bi Shih <tzungbi@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/firmware/google/gsmi.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/drivers/firmware/google/gsmi.c b/drivers/firmware/google/gsmi.c +index d304913314e49..24e666d5c3d1a 100644 +--- a/drivers/firmware/google/gsmi.c ++++ b/drivers/firmware/google/gsmi.c +@@ -918,7 +918,8 @@ static __init int gsmi_init(void) + gsmi_dev.pdev = platform_device_register_full(&gsmi_dev_info); + if (IS_ERR(gsmi_dev.pdev)) { + printk(KERN_ERR "gsmi: unable to register platform device\n"); +- return PTR_ERR(gsmi_dev.pdev); ++ ret = PTR_ERR(gsmi_dev.pdev); ++ goto out_unregister; + } + + /* SMI access needs to be serialized */ +@@ -1056,10 +1057,11 @@ static __init int gsmi_init(void) + gsmi_buf_free(gsmi_dev.name_buf); + kmem_cache_destroy(gsmi_dev.mem_pool); + platform_device_unregister(gsmi_dev.pdev); +- pr_info("gsmi: failed to load: %d\n", ret); ++out_unregister: + #ifdef CONFIG_PM + platform_driver_unregister(&gsmi_driver_info); + #endif ++ pr_info("gsmi: failed to load: %d\n", ret); + return ret; + } + +-- +2.43.0 + diff --git a/queue-6.12/firmware_loader-fix-possible-resource-leak-in-fw_log.patch b/queue-6.12/firmware_loader-fix-possible-resource-leak-in-fw_log.patch new file mode 100644 index 00000000000..1cc20a96b6c --- /dev/null +++ b/queue-6.12/firmware_loader-fix-possible-resource-leak-in-fw_log.patch @@ -0,0 +1,58 @@ +From b46cb662cbe9fc51386aaa6edc71f7be88966e9a Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Wed, 16 Oct 2024 19:03:35 +0800 +Subject: firmware_loader: Fix possible resource leak in fw_log_firmware_info() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Gaosheng Cui <cuigaosheng1@huawei.com> + +[ Upstream commit 369a9c046c2fdfe037f05b43b84c386bdbccc103 ] + +The alg instance should be released under the exception path, otherwise +there may be resource leak here. + +To mitigate this, free the alg instance with crypto_free_shash when kmalloc +fails. + +Fixes: 02fe26f25325 ("firmware_loader: Add debug message with checksum for FW file") +Signed-off-by: Gaosheng Cui <cuigaosheng1@huawei.com> +Reviewed-by: Amadeusz Sławiński <amadeuszx.slawinski@linux.intel.com> +Reviewed-by: Russ Weight <russ.weight@linux.dev> +Link: https://lore.kernel.org/r/20241016110335.3677924-1-cuigaosheng1@huawei.com +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/base/firmware_loader/main.c | 5 ++--- + 1 file changed, 2 insertions(+), 3 deletions(-) + +diff --git a/drivers/base/firmware_loader/main.c b/drivers/base/firmware_loader/main.c +index 324a9a3c087aa..c6664a7879697 100644 +--- a/drivers/base/firmware_loader/main.c ++++ b/drivers/base/firmware_loader/main.c +@@ -829,19 +829,18 @@ static void fw_log_firmware_info(const struct firmware *fw, const char *name, st + shash->tfm = alg; + + if (crypto_shash_digest(shash, fw->data, fw->size, sha256buf) < 0) +- goto out_shash; ++ goto out_free; + + for (int i = 0; i < SHA256_DIGEST_SIZE; i++) + sprintf(&outbuf[i * 2], "%02x", sha256buf[i]); + outbuf[SHA256_BLOCK_SIZE] = 0; + dev_dbg(device, "Loaded FW: %s, sha256: %s\n", name, outbuf); + +-out_shash: +- crypto_free_shash(alg); + out_free: + kfree(shash); + kfree(outbuf); + kfree(sha256buf); ++ crypto_free_shash(alg); + } + #else + static void fw_log_firmware_info(const struct firmware *fw, const char *name, +-- +2.43.0 + diff --git a/queue-6.12/fs-block-check-for-iocb_direct-in-generic_atomic_wri.patch b/queue-6.12/fs-block-check-for-iocb_direct-in-generic_atomic_wri.patch new file mode 100644 index 00000000000..b728f8e7093 --- /dev/null +++ b/queue-6.12/fs-block-check-for-iocb_direct-in-generic_atomic_wri.patch @@ -0,0 +1,142 @@ +From 77635008c89a6fe23221f9ba32a133cf328cd9e8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Sat, 19 Oct 2024 12:51:07 +0000 +Subject: fs/block: Check for IOCB_DIRECT in generic_atomic_write_valid() + +From: John Garry <john.g.garry@oracle.com> + +[ Upstream commit c3be7ebbbce5201e151f17e28a6c807602f369c9 ] + +Currently FMODE_CAN_ATOMIC_WRITE is set if the bdev can atomic write and +the file is open for direct IO. This does not work if the file is not +opened for direct IO, yet fcntl(O_DIRECT) is used on the fd later. + +Change to check for direct IO on a per-IO basis in +generic_atomic_write_valid(). Since we want to report -EOPNOTSUPP for +non-direct IO for an atomic write, change to return an error code. + +Relocate the block fops atomic write checks to the common write path, as to +catch non-direct IO. + +Fixes: c34fc6f26ab8 ("fs: Initial atomic write support") +Reviewed-by: Christoph Hellwig <hch@lst.de> +Reviewed-by: Darrick J. Wong <djwong@kernel.org> +Signed-off-by: John Garry <john.g.garry@oracle.com> +Link: https://lore.kernel.org/r/20241019125113.369994-3-john.g.garry@oracle.com +Signed-off-by: Jens Axboe <axboe@kernel.dk> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + block/fops.c | 18 ++++++++++-------- + fs/read_write.c | 13 ++++++++----- + include/linux/fs.h | 2 +- + 3 files changed, 19 insertions(+), 14 deletions(-) + +diff --git a/block/fops.c b/block/fops.c +index 968b47b615c4b..2d01c90076813 100644 +--- a/block/fops.c ++++ b/block/fops.c +@@ -36,11 +36,8 @@ static blk_opf_t dio_bio_write_op(struct kiocb *iocb) + } + + static bool blkdev_dio_invalid(struct block_device *bdev, struct kiocb *iocb, +- struct iov_iter *iter, bool is_atomic) ++ struct iov_iter *iter) + { +- if (is_atomic && !generic_atomic_write_valid(iocb, iter)) +- return true; +- + return iocb->ki_pos & (bdev_logical_block_size(bdev) - 1) || + !bdev_iter_is_aligned(bdev, iter); + } +@@ -368,13 +365,12 @@ static ssize_t __blkdev_direct_IO_async(struct kiocb *iocb, + static ssize_t blkdev_direct_IO(struct kiocb *iocb, struct iov_iter *iter) + { + struct block_device *bdev = I_BDEV(iocb->ki_filp->f_mapping->host); +- bool is_atomic = iocb->ki_flags & IOCB_ATOMIC; + unsigned int nr_pages; + + if (!iov_iter_count(iter)) + return 0; + +- if (blkdev_dio_invalid(bdev, iocb, iter, is_atomic)) ++ if (blkdev_dio_invalid(bdev, iocb, iter)) + return -EINVAL; + + nr_pages = bio_iov_vecs_to_alloc(iter, BIO_MAX_VECS + 1); +@@ -383,7 +379,7 @@ static ssize_t blkdev_direct_IO(struct kiocb *iocb, struct iov_iter *iter) + return __blkdev_direct_IO_simple(iocb, iter, bdev, + nr_pages); + return __blkdev_direct_IO_async(iocb, iter, bdev, nr_pages); +- } else if (is_atomic) { ++ } else if (iocb->ki_flags & IOCB_ATOMIC) { + return -EINVAL; + } + return __blkdev_direct_IO(iocb, iter, bdev, bio_max_segs(nr_pages)); +@@ -625,7 +621,7 @@ static int blkdev_open(struct inode *inode, struct file *filp) + if (!bdev) + return -ENXIO; + +- if (bdev_can_atomic_write(bdev) && filp->f_flags & O_DIRECT) ++ if (bdev_can_atomic_write(bdev)) + filp->f_mode |= FMODE_CAN_ATOMIC_WRITE; + + ret = bdev_open(bdev, mode, filp->private_data, NULL, filp); +@@ -700,6 +696,12 @@ static ssize_t blkdev_write_iter(struct kiocb *iocb, struct iov_iter *from) + if ((iocb->ki_flags & (IOCB_NOWAIT | IOCB_DIRECT)) == IOCB_NOWAIT) + return -EOPNOTSUPP; + ++ if (iocb->ki_flags & IOCB_ATOMIC) { ++ ret = generic_atomic_write_valid(iocb, from); ++ if (ret) ++ return ret; ++ } ++ + size -= iocb->ki_pos; + if (iov_iter_count(from) > size) { + shorted = iov_iter_count(from) - size; +diff --git a/fs/read_write.c b/fs/read_write.c +index 2c32635308281..befec0b5c537a 100644 +--- a/fs/read_write.c ++++ b/fs/read_write.c +@@ -1830,18 +1830,21 @@ int generic_file_rw_checks(struct file *file_in, struct file *file_out) + return 0; + } + +-bool generic_atomic_write_valid(struct kiocb *iocb, struct iov_iter *iter) ++int generic_atomic_write_valid(struct kiocb *iocb, struct iov_iter *iter) + { + size_t len = iov_iter_count(iter); + + if (!iter_is_ubuf(iter)) +- return false; ++ return -EINVAL; + + if (!is_power_of_2(len)) +- return false; ++ return -EINVAL; + + if (!IS_ALIGNED(iocb->ki_pos, len)) +- return false; ++ return -EINVAL; + +- return true; ++ if (!(iocb->ki_flags & IOCB_DIRECT)) ++ return -EOPNOTSUPP; ++ ++ return 0; + } +diff --git a/include/linux/fs.h b/include/linux/fs.h +index faf7596ace971..4b5cad44a1268 100644 +--- a/include/linux/fs.h ++++ b/include/linux/fs.h +@@ -3726,6 +3726,6 @@ static inline bool vfs_empty_path(int dfd, const char __user *path) + return !c; + } + +-bool generic_atomic_write_valid(struct kiocb *iocb, struct iov_iter *iter); ++int generic_atomic_write_valid(struct kiocb *iocb, struct iov_iter *iter); + + #endif /* _LINUX_FS_H */ +-- +2.43.0 + diff --git a/queue-6.12/fs-ntfs3-equivalent-transition-from-page-to-folio.patch b/queue-6.12/fs-ntfs3-equivalent-transition-from-page-to-folio.patch new file mode 100644 index 00000000000..fe25b86eaea --- /dev/null +++ b/queue-6.12/fs-ntfs3-equivalent-transition-from-page-to-folio.patch @@ -0,0 +1,35 @@ +From 316f525c123c908d12023bc0863f67c9d071d664 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Fri, 1 Nov 2024 10:39:36 +0300 +Subject: fs/ntfs3: Equivalent transition from page to folio + +From: Konstantin Komarov <almaz.alexandrovich@paragon-software.com> + +[ Upstream commit 045fff619312fb013540c80cff18aab3c33048ab ] + +If using the proposed function folio_zero_range(), should one switch +from 'start + end' to 'start + length,' or use folio_zero_segment() + +Fixes: 1da86618bdce ("fs: Convert aops->write_begin to take a folio") +Signed-off-by: Konstantin Komarov <almaz.alexandrovich@paragon-software.com> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + fs/ntfs3/file.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/fs/ntfs3/file.c b/fs/ntfs3/file.c +index e370eaf9bfe2e..f704ceef95394 100644 +--- a/fs/ntfs3/file.c ++++ b/fs/ntfs3/file.c +@@ -222,7 +222,7 @@ static int ntfs_extend_initialized_size(struct file *file, + if (err) + goto out; + +- folio_zero_range(folio, zerofrom, folio_size(folio)); ++ folio_zero_range(folio, zerofrom, folio_size(folio) - zerofrom); + + err = ntfs_write_end(file, mapping, pos, len, len, folio, NULL); + if (err < 0) +-- +2.43.0 + diff --git a/queue-6.12/fs-proc-kcore.c-fix-coccinelle-reported-error-instan.patch b/queue-6.12/fs-proc-kcore.c-fix-coccinelle-reported-error-instan.patch new file mode 100644 index 00000000000..a4f0c21b899 --- /dev/null +++ b/queue-6.12/fs-proc-kcore.c-fix-coccinelle-reported-error-instan.patch @@ -0,0 +1,79 @@ +From 3367b60d060b4ef4969276a3a86503b1f053315f Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Tue, 29 Oct 2024 06:46:52 +0100 +Subject: fs/proc/kcore.c: fix coccinelle reported ERROR instances + +From: Mirsad Todorovac <mtodorovac69@gmail.com> + +[ Upstream commit 82e33f249f1126cf3c5f39a31b850d485ac33bc3 ] + +Coccinelle complains about the nested reuse of the pointer `iter' with +different pointer type: + +./fs/proc/kcore.c:515:26-30: ERROR: invalid reference to the index variable of the iterator on line 499 +./fs/proc/kcore.c:534:23-27: ERROR: invalid reference to the index variable of the iterator on line 499 +./fs/proc/kcore.c:550:40-44: ERROR: invalid reference to the index variable of the iterator on line 499 +./fs/proc/kcore.c:568:27-31: ERROR: invalid reference to the index variable of the iterator on line 499 +./fs/proc/kcore.c:581:28-32: ERROR: invalid reference to the index variable of the iterator on line 499 +./fs/proc/kcore.c:599:27-31: ERROR: invalid reference to the index variable of the iterator on line 499 +./fs/proc/kcore.c:607:38-42: ERROR: invalid reference to the index variable of the iterator on line 499 +./fs/proc/kcore.c:614:26-30: ERROR: invalid reference to the index variable of the iterator on line 499 + +Replacing `struct kcore_list *iter' with `struct kcore_list *tmp' doesn't change the +scope and the functionality is the same and coccinelle seems happy. + +NOTE: There was an issue with using `struct kcore_list *pos' as the nested iterator. + The build did not work! + +[akpm@linux-foundation.org: s/tmp/pos/] +Link: https://lkml.kernel.org/r/20241029054651.86356-2-mtodorovac69@gmail.com +Link: https://lore.kernel.org/all/CAHk-=wgRr_D8CB-D9Kg-c=EHreAsk5SqXPwr9Y7k9sA6cWXJ6w@mail.gmail.com/ [1] +Link: https://lkml.kernel.org/r/20220331223700.902556-1-jakobkoschel@gmail.com +Fixes: 04d168c6d42d ("fs/proc/kcore.c: remove check of list iterator against head past the loop body") +Signed-off-by: Jakob Koschel <jakobkoschel@gmail.com> +Signed-off-by: Mirsad Todorovac <mtodorovac69@gmail.com> +Cc: Mike Rapoport <rppt@kernel.org> +Cc: David Hildenbrand <david@redhat.com> +Cc: Oscar Salvador <osalvador@suse.de> +Cc: "Brian Johannesmeyer" <bjohannesmeyer@gmail.com> +Cc: Cristiano Giuffrida <c.giuffrida@vu.nl> +Cc: "Bos, H.J." <h.j.bos@vu.nl> +Cc: Alexey Dobriyan <adobriyan@gmail.com> +Cc: Andrew Morton <akpm@linux-foundation.org> +Cc: Yang Li <yang.lee@linux.alibaba.com> +Cc: Baoquan He <bhe@redhat.com> +Cc: Hari Bathini <hbathini@linux.ibm.com> +Cc: Yan Zhen <yanzhen@vivo.com> +Cc: Alexander Gordeev <agordeev@linux.ibm.com> +Signed-off-by: Andrew Morton <akpm@linux-foundation.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + fs/proc/kcore.c | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +diff --git a/fs/proc/kcore.c b/fs/proc/kcore.c +index 51446c59388f1..7a85735d584f3 100644 +--- a/fs/proc/kcore.c ++++ b/fs/proc/kcore.c +@@ -493,13 +493,13 @@ static ssize_t read_kcore_iter(struct kiocb *iocb, struct iov_iter *iter) + * the previous entry, search for a matching entry. + */ + if (!m || start < m->addr || start >= m->addr + m->size) { +- struct kcore_list *iter; ++ struct kcore_list *pos; + + m = NULL; +- list_for_each_entry(iter, &kclist_head, list) { +- if (start >= iter->addr && +- start < iter->addr + iter->size) { +- m = iter; ++ list_for_each_entry(pos, &kclist_head, list) { ++ if (start >= pos->addr && ++ start < pos->addr + pos->size) { ++ m = pos; + break; + } + } +-- +2.43.0 + diff --git a/queue-6.12/fs_parser-update-mount_api-doc-to-match-function-sig.patch b/queue-6.12/fs_parser-update-mount_api-doc-to-match-function-sig.patch new file mode 100644 index 00000000000..39615b03190 --- /dev/null +++ b/queue-6.12/fs_parser-update-mount_api-doc-to-match-function-sig.patch @@ -0,0 +1,45 @@ +From ade59471c23b2167b2bf67d5542058a846b232b0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Mon, 25 Nov 2024 13:50:21 -0800 +Subject: fs_parser: update mount_api doc to match function signature + +From: Randy Dunlap <rdunlap@infradead.org> + +[ Upstream commit c66f759832a83cb273ba5a55c66dcc99384efa74 ] + +Add the missing 'name' parameter to the mount_api documentation for +fs_validate_description(). + +Fixes: 96cafb9ccb15 ("fs_parser: remove fs_parameter_description name field") +Signed-off-by: Randy Dunlap <rdunlap@infradead.org> +Link: https://lore.kernel.org/r/20241125215021.231758-1-rdunlap@infradead.org +Cc: Eric Sandeen <sandeen@redhat.com> +Cc: David Howells <dhowells@redhat.com> +Cc: Al Viro <viro@zeniv.linux.org.uk> +Cc: Christian Brauner <brauner@kernel.org> +Cc: Jan Kara <jack@suse.cz> +Cc: Jonathan Corbet <corbet@lwn.net> +Cc: linux-doc@vger.kernel.org +Signed-off-by: Christian Brauner <brauner@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + Documentation/filesystems/mount_api.rst | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/Documentation/filesystems/mount_api.rst b/Documentation/filesystems/mount_api.rst +index 317934c9e8fca..d92c276f1575a 100644 +--- a/Documentation/filesystems/mount_api.rst ++++ b/Documentation/filesystems/mount_api.rst +@@ -770,7 +770,8 @@ process the parameters it is given. + + * :: + +- bool fs_validate_description(const struct fs_parameter_description *desc); ++ bool fs_validate_description(const char *name, ++ const struct fs_parameter_description *desc); + + This performs some validation checks on a parameter description. It + returns true if the description is good and false if it is not. It will +-- +2.43.0 + diff --git a/queue-6.12/gfs2-allow-immediate-glf_verify_delete-work.patch b/queue-6.12/gfs2-allow-immediate-glf_verify_delete-work.patch new file mode 100644 index 00000000000..178fe11c243 --- /dev/null +++ b/queue-6.12/gfs2-allow-immediate-glf_verify_delete-work.patch @@ -0,0 +1,64 @@ +From 2935962e49c0952097e9dee3effc474bdc988521 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Tue, 24 Sep 2024 18:38:00 +0200 +Subject: gfs2: Allow immediate GLF_VERIFY_DELETE work + +From: Andreas Gruenbacher <agruenba@redhat.com> + +[ Upstream commit 160bc9555d8654464cbbd7bb1f6687048471d2f6 ] + +Add an argument to gfs2_queue_verify_delete() that allows it to queue +GLF_VERIFY_DELETE work for immediate execution. This is used in the +next patch. + +Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com> +Stable-dep-of: 7c6f714d8847 ("gfs2: Fix unlinked inode cleanup") +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + fs/gfs2/glock.c | 11 ++++++----- + 1 file changed, 6 insertions(+), 5 deletions(-) + +diff --git a/fs/gfs2/glock.c b/fs/gfs2/glock.c +index 5addf4ebf33bd..509115202ccf9 100644 +--- a/fs/gfs2/glock.c ++++ b/fs/gfs2/glock.c +@@ -1013,14 +1013,15 @@ bool gfs2_queue_try_to_evict(struct gfs2_glock *gl) + &gl->gl_delete, 0); + } + +-static bool gfs2_queue_verify_delete(struct gfs2_glock *gl) ++static bool gfs2_queue_verify_delete(struct gfs2_glock *gl, bool later) + { + struct gfs2_sbd *sdp = gl->gl_name.ln_sbd; ++ unsigned long delay; + + if (test_and_set_bit(GLF_VERIFY_DELETE, &gl->gl_flags)) + return false; +- return queue_delayed_work(sdp->sd_delete_wq, +- &gl->gl_delete, 5 * HZ); ++ delay = later ? 5 * HZ : 0; ++ return queue_delayed_work(sdp->sd_delete_wq, &gl->gl_delete, delay); + } + + static void delete_work_func(struct work_struct *work) +@@ -1052,7 +1053,7 @@ static void delete_work_func(struct work_struct *work) + if (gfs2_try_evict(gl)) { + if (test_bit(SDF_KILL, &sdp->sd_flags)) + goto out; +- if (gfs2_queue_verify_delete(gl)) ++ if (gfs2_queue_verify_delete(gl, true)) + return; + } + goto out; +@@ -1064,7 +1065,7 @@ static void delete_work_func(struct work_struct *work) + if (IS_ERR(inode)) { + if (PTR_ERR(inode) == -EAGAIN && + !test_bit(SDF_KILL, &sdp->sd_flags) && +- gfs2_queue_verify_delete(gl)) ++ gfs2_queue_verify_delete(gl, true)) + return; + } else { + d_prune_aliases(inode); +-- +2.43.0 + diff --git a/queue-6.12/gfs2-fix-unlinked-inode-cleanup.patch b/queue-6.12/gfs2-fix-unlinked-inode-cleanup.patch new file mode 100644 index 00000000000..21b085b5d4c --- /dev/null +++ b/queue-6.12/gfs2-fix-unlinked-inode-cleanup.patch @@ -0,0 +1,85 @@ +From 9ab7c0dd0e031d35823c365a245da13fb1b8170d Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Mon, 26 Aug 2024 20:06:21 +0200 +Subject: gfs2: Fix unlinked inode cleanup + +From: Andreas Gruenbacher <agruenba@redhat.com> + +[ Upstream commit 7c6f714d88475ceae5342264858a641eafa19632 ] + +Before commit f0e56edc2ec7 ("gfs2: Split the two kinds of glock "delete" +work"), function delete_work_func() was used to trigger the eviction of +in-memory inodes from remote as well as deleting unlinked inodes at a +later point. These two kinds of work were then split into two kinds of +work, and the two places in the code were deferred deletion of inodes is +required accidentally ended up queuing the wrong kind of work. This +caused unlinked inodes to be left behind, which could in the worst case +fill up filesystems and require a filesystem check to recover. + +Fix that by queuing the right kind of work in try_rgrp_unlink() and +gfs2_drop_inode(). + +Fixes: f0e56edc2ec7 ("gfs2: Split the two kinds of glock "delete" work") +Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + fs/gfs2/glock.c | 2 +- + fs/gfs2/glock.h | 1 + + fs/gfs2/rgrp.c | 2 +- + fs/gfs2/super.c | 2 +- + 4 files changed, 4 insertions(+), 3 deletions(-) + +diff --git a/fs/gfs2/glock.c b/fs/gfs2/glock.c +index 509115202ccf9..a51fe42732c4c 100644 +--- a/fs/gfs2/glock.c ++++ b/fs/gfs2/glock.c +@@ -1013,7 +1013,7 @@ bool gfs2_queue_try_to_evict(struct gfs2_glock *gl) + &gl->gl_delete, 0); + } + +-static bool gfs2_queue_verify_delete(struct gfs2_glock *gl, bool later) ++bool gfs2_queue_verify_delete(struct gfs2_glock *gl, bool later) + { + struct gfs2_sbd *sdp = gl->gl_name.ln_sbd; + unsigned long delay; +diff --git a/fs/gfs2/glock.h b/fs/gfs2/glock.h +index adf0091cc98f9..63e101d448e96 100644 +--- a/fs/gfs2/glock.h ++++ b/fs/gfs2/glock.h +@@ -245,6 +245,7 @@ static inline int gfs2_glock_nq_init(struct gfs2_glock *gl, + void gfs2_glock_cb(struct gfs2_glock *gl, unsigned int state); + void gfs2_glock_complete(struct gfs2_glock *gl, int ret); + bool gfs2_queue_try_to_evict(struct gfs2_glock *gl); ++bool gfs2_queue_verify_delete(struct gfs2_glock *gl, bool later); + void gfs2_cancel_delete_work(struct gfs2_glock *gl); + void gfs2_flush_delete_work(struct gfs2_sbd *sdp); + void gfs2_gl_hash_clear(struct gfs2_sbd *sdp); +diff --git a/fs/gfs2/rgrp.c b/fs/gfs2/rgrp.c +index 29c7728167652..5393031297153 100644 +--- a/fs/gfs2/rgrp.c ++++ b/fs/gfs2/rgrp.c +@@ -1879,7 +1879,7 @@ static void try_rgrp_unlink(struct gfs2_rgrpd *rgd, u64 *last_unlinked, u64 skip + */ + ip = gl->gl_object; + +- if (ip || !gfs2_queue_try_to_evict(gl)) ++ if (ip || !gfs2_queue_verify_delete(gl, false)) + gfs2_glock_put(gl); + else + found++; +diff --git a/fs/gfs2/super.c b/fs/gfs2/super.c +index 6678060ed4d2b..e22c1edc32b39 100644 +--- a/fs/gfs2/super.c ++++ b/fs/gfs2/super.c +@@ -1045,7 +1045,7 @@ static int gfs2_drop_inode(struct inode *inode) + struct gfs2_glock *gl = ip->i_iopen_gh.gh_gl; + + gfs2_glock_hold(gl); +- if (!gfs2_queue_try_to_evict(gl)) ++ if (!gfs2_queue_verify_delete(gl, true)) + gfs2_glock_put_async(gl); + return 0; + } +-- +2.43.0 + diff --git a/queue-6.12/gfs2-rename-glf_verify_evict-to-glf_verify_delete.patch b/queue-6.12/gfs2-rename-glf_verify_evict-to-glf_verify_delete.patch new file mode 100644 index 00000000000..cef70fa57dd --- /dev/null +++ b/queue-6.12/gfs2-rename-glf_verify_evict-to-glf_verify_delete.patch @@ -0,0 +1,99 @@ +From 78cc27e310ff3922ebdd74c0c64bbd66b1eff90e Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Wed, 21 Aug 2024 22:02:05 +0200 +Subject: gfs2: Rename GLF_VERIFY_EVICT to GLF_VERIFY_DELETE + +From: Andreas Gruenbacher <agruenba@redhat.com> + +[ Upstream commit 820ce8ed53ce2111aa5171f7349f289d7e9d0693 ] + +Rename the GLF_VERIFY_EVICT flag to GLF_VERIFY_DELETE: that flag +indicates that we want to delete an inode / verify that it has been +deleted. + +To match, rename gfs2_queue_verify_evict() to +gfs2_queue_verify_delete(). + +Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com> +Stable-dep-of: 7c6f714d8847 ("gfs2: Fix unlinked inode cleanup") +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + fs/gfs2/glock.c | 14 +++++++------- + fs/gfs2/incore.h | 2 +- + 2 files changed, 8 insertions(+), 8 deletions(-) + +diff --git a/fs/gfs2/glock.c b/fs/gfs2/glock.c +index 269c3bc7fced7..5addf4ebf33bd 100644 +--- a/fs/gfs2/glock.c ++++ b/fs/gfs2/glock.c +@@ -1013,11 +1013,11 @@ bool gfs2_queue_try_to_evict(struct gfs2_glock *gl) + &gl->gl_delete, 0); + } + +-static bool gfs2_queue_verify_evict(struct gfs2_glock *gl) ++static bool gfs2_queue_verify_delete(struct gfs2_glock *gl) + { + struct gfs2_sbd *sdp = gl->gl_name.ln_sbd; + +- if (test_and_set_bit(GLF_VERIFY_EVICT, &gl->gl_flags)) ++ if (test_and_set_bit(GLF_VERIFY_DELETE, &gl->gl_flags)) + return false; + return queue_delayed_work(sdp->sd_delete_wq, + &gl->gl_delete, 5 * HZ); +@@ -1052,19 +1052,19 @@ static void delete_work_func(struct work_struct *work) + if (gfs2_try_evict(gl)) { + if (test_bit(SDF_KILL, &sdp->sd_flags)) + goto out; +- if (gfs2_queue_verify_evict(gl)) ++ if (gfs2_queue_verify_delete(gl)) + return; + } + goto out; + } + +- if (test_and_clear_bit(GLF_VERIFY_EVICT, &gl->gl_flags)) { ++ if (test_and_clear_bit(GLF_VERIFY_DELETE, &gl->gl_flags)) { + inode = gfs2_lookup_by_inum(sdp, no_addr, gl->gl_no_formal_ino, + GFS2_BLKST_UNLINKED); + if (IS_ERR(inode)) { + if (PTR_ERR(inode) == -EAGAIN && + !test_bit(SDF_KILL, &sdp->sd_flags) && +- gfs2_queue_verify_evict(gl)) ++ gfs2_queue_verify_delete(gl)) + return; + } else { + d_prune_aliases(inode); +@@ -2118,7 +2118,7 @@ static void glock_hash_walk(glock_examiner examiner, const struct gfs2_sbd *sdp) + void gfs2_cancel_delete_work(struct gfs2_glock *gl) + { + clear_bit(GLF_TRY_TO_EVICT, &gl->gl_flags); +- clear_bit(GLF_VERIFY_EVICT, &gl->gl_flags); ++ clear_bit(GLF_VERIFY_DELETE, &gl->gl_flags); + if (cancel_delayed_work(&gl->gl_delete)) + gfs2_glock_put(gl); + } +@@ -2371,7 +2371,7 @@ static const char *gflags2str(char *buf, const struct gfs2_glock *gl) + *p++ = 'N'; + if (test_bit(GLF_TRY_TO_EVICT, gflags)) + *p++ = 'e'; +- if (test_bit(GLF_VERIFY_EVICT, gflags)) ++ if (test_bit(GLF_VERIFY_DELETE, gflags)) + *p++ = 'E'; + *p = 0; + return buf; +diff --git a/fs/gfs2/incore.h b/fs/gfs2/incore.h +index aa4ef67a34e03..bd1348bff90eb 100644 +--- a/fs/gfs2/incore.h ++++ b/fs/gfs2/incore.h +@@ -329,7 +329,7 @@ enum { + GLF_BLOCKING = 15, + GLF_UNLOCKED = 16, /* Wait for glock to be unlocked */ + GLF_TRY_TO_EVICT = 17, /* iopen glocks only */ +- GLF_VERIFY_EVICT = 18, /* iopen glocks only */ ++ GLF_VERIFY_DELETE = 18, /* iopen glocks only */ + }; + + struct gfs2_glock { +-- +2.43.0 + diff --git a/queue-6.12/gpio-sloppy-logic-analyzer-remove-reference-to-rcu_m.patch b/queue-6.12/gpio-sloppy-logic-analyzer-remove-reference-to-rcu_m.patch new file mode 100644 index 00000000000..367a7a728e6 --- /dev/null +++ b/queue-6.12/gpio-sloppy-logic-analyzer-remove-reference-to-rcu_m.patch @@ -0,0 +1,42 @@ +From 7a759deeeb385154ef3c6c93c72ec88964174c1f Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Wed, 25 Sep 2024 11:16:18 +0530 +Subject: gpio: sloppy-logic-analyzer remove reference to + rcu_momentary_dyntick_idle() + +From: Srikar Dronamraju <srikar@linux.ibm.com> + +[ Upstream commit a0b6594e411dcae0cc563f5157cf062e93603388 ] + +There is one last reference to rcu_momentary_dyntick_idle() after +commit 32a9f26e5e26 ("rcu: Rename rcu_momentary_dyntick_idle() into +rcu_momentary_eqs()") + +Rename it for consistency. + +Fixes: 32a9f26e5e26 ("rcu: Rename rcu_momentary_dyntick_idle() into rcu_momentary_eqs()") +Signed-off-by: Srikar Dronamraju <srikar@linux.ibm.com> +Acked-by: Frederic Weisbecker <frederic@kernel.org> +Link: https://lore.kernel.org/r/20240925054619.568209-1-srikar@linux.ibm.com +Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + tools/gpio/gpio-sloppy-logic-analyzer.sh | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/tools/gpio/gpio-sloppy-logic-analyzer.sh b/tools/gpio/gpio-sloppy-logic-analyzer.sh +index ed21a110df5e5..3ef2278e49f91 100755 +--- a/tools/gpio/gpio-sloppy-logic-analyzer.sh ++++ b/tools/gpio/gpio-sloppy-logic-analyzer.sh +@@ -113,7 +113,7 @@ init_cpu() + taskset -p "$newmask" "$p" || continue + done 2>/dev/null >/dev/null + +- # Big hammer! Working with 'rcu_momentary_dyntick_idle()' for a more fine-grained solution ++ # Big hammer! Working with 'rcu_momentary_eqs()' for a more fine-grained solution + # still printed warnings. Same for re-enabling the stall detector after sampling. + echo 1 > /sys/module/rcupdate/parameters/rcu_cpu_stall_suppress + +-- +2.43.0 + diff --git a/queue-6.12/gpio-zevio-add-missed-label-initialisation.patch b/queue-6.12/gpio-zevio-add-missed-label-initialisation.patch new file mode 100644 index 00000000000..5c343293ff1 --- /dev/null +++ b/queue-6.12/gpio-zevio-add-missed-label-initialisation.patch @@ -0,0 +1,55 @@ +From bee7a0a63b2f0bc4a76b92ab91ba8804dd4f8926 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Mon, 18 Nov 2024 11:27:07 +0200 +Subject: gpio: zevio: Add missed label initialisation + +From: Andy Shevchenko <andriy.shevchenko@linux.intel.com> + +[ Upstream commit 5bbed54ba66925ebca19092d0750630f943d7bf2 ] + +Initialise the GPIO chip label correctly as it was done by +of_mm_gpiochip_add_data() before the below mentioned change. + +Fixes: cf8f4462e5fa ("gpio: zevio: drop of_gpio.h header") +Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com> +Link: https://lore.kernel.org/r/20241118092729.516736-1-andriy.shevchenko@linux.intel.com +Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/gpio/gpio-zevio.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/drivers/gpio/gpio-zevio.c b/drivers/gpio/gpio-zevio.c +index 2de61337ad3b5..d7230fd83f5d6 100644 +--- a/drivers/gpio/gpio-zevio.c ++++ b/drivers/gpio/gpio-zevio.c +@@ -11,6 +11,7 @@ + #include <linux/io.h> + #include <linux/mod_devicetable.h> + #include <linux/platform_device.h> ++#include <linux/property.h> + #include <linux/slab.h> + #include <linux/spinlock.h> + +@@ -169,6 +170,7 @@ static const struct gpio_chip zevio_gpio_chip = { + /* Initialization */ + static int zevio_gpio_probe(struct platform_device *pdev) + { ++ struct device *dev = &pdev->dev; + struct zevio_gpio *controller; + int status, i; + +@@ -180,6 +182,10 @@ static int zevio_gpio_probe(struct platform_device *pdev) + controller->chip = zevio_gpio_chip; + controller->chip.parent = &pdev->dev; + ++ controller->chip.label = devm_kasprintf(dev, GFP_KERNEL, "%pfw", dev_fwnode(dev)); ++ if (!controller->chip.label) ++ return -ENOMEM; ++ + controller->regs = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(controller->regs)) + return dev_err_probe(&pdev->dev, PTR_ERR(controller->regs), +-- +2.43.0 + diff --git a/queue-6.12/hfsplus-don-t-query-the-device-logical-block-size-mu.patch b/queue-6.12/hfsplus-don-t-query-the-device-logical-block-size-mu.patch new file mode 100644 index 00000000000..b4c5c6cd693 --- /dev/null +++ b/queue-6.12/hfsplus-don-t-query-the-device-logical-block-size-mu.patch @@ -0,0 +1,139 @@ +From 2c3a2652038812f44fb680fa4ec8fca154df0a4f Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Thu, 7 Nov 2024 08:41:09 -0300 +Subject: hfsplus: don't query the device logical block size multiple times + +From: Thadeu Lima de Souza Cascardo <cascardo@igalia.com> + +[ Upstream commit 1c82587cb57687de3f18ab4b98a8850c789bedcf ] + +Devices block sizes may change. One of these cases is a loop device by +using ioctl LOOP_SET_BLOCK_SIZE. + +While this may cause other issues like IO being rejected, in the case of +hfsplus, it will allocate a block by using that size and potentially write +out-of-bounds when hfsplus_read_wrapper calls hfsplus_submit_bio and the +latter function reads a different io_size. + +Using a new min_io_size initally set to sb_min_blocksize works for the +purposes of the original fix, since it will be set to the max between +HFSPLUS_SECTOR_SIZE and the first seen logical block size. We still use the +max between HFSPLUS_SECTOR_SIZE and min_io_size in case the latter is not +initialized. + +Tested by mounting an hfsplus filesystem with loop block sizes 512, 1024 +and 4096. + +The produced KASAN report before the fix looks like this: + +[ 419.944641] ================================================================== +[ 419.945655] BUG: KASAN: slab-use-after-free in hfsplus_read_wrapper+0x659/0xa0a +[ 419.946703] Read of size 2 at addr ffff88800721fc00 by task repro/10678 +[ 419.947612] +[ 419.947846] CPU: 0 UID: 0 PID: 10678 Comm: repro Not tainted 6.12.0-rc5-00008-gdf56e0f2f3ca #84 +[ 419.949007] Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.15.0-1 04/01/2014 +[ 419.950035] Call Trace: +[ 419.950384] <TASK> +[ 419.950676] dump_stack_lvl+0x57/0x78 +[ 419.951212] ? hfsplus_read_wrapper+0x659/0xa0a +[ 419.951830] print_report+0x14c/0x49e +[ 419.952361] ? __virt_addr_valid+0x267/0x278 +[ 419.952979] ? kmem_cache_debug_flags+0xc/0x1d +[ 419.953561] ? hfsplus_read_wrapper+0x659/0xa0a +[ 419.954231] kasan_report+0x89/0xb0 +[ 419.954748] ? hfsplus_read_wrapper+0x659/0xa0a +[ 419.955367] hfsplus_read_wrapper+0x659/0xa0a +[ 419.955948] ? __pfx_hfsplus_read_wrapper+0x10/0x10 +[ 419.956618] ? do_raw_spin_unlock+0x59/0x1a9 +[ 419.957214] ? _raw_spin_unlock+0x1a/0x2e +[ 419.957772] hfsplus_fill_super+0x348/0x1590 +[ 419.958355] ? hlock_class+0x4c/0x109 +[ 419.958867] ? __pfx_hfsplus_fill_super+0x10/0x10 +[ 419.959499] ? __pfx_string+0x10/0x10 +[ 419.960006] ? lock_acquire+0x3e2/0x454 +[ 419.960532] ? bdev_name.constprop.0+0xce/0x243 +[ 419.961129] ? __pfx_bdev_name.constprop.0+0x10/0x10 +[ 419.961799] ? pointer+0x3f0/0x62f +[ 419.962277] ? __pfx_pointer+0x10/0x10 +[ 419.962761] ? vsnprintf+0x6c4/0xfba +[ 419.963178] ? __pfx_vsnprintf+0x10/0x10 +[ 419.963621] ? setup_bdev_super+0x376/0x3b3 +[ 419.964029] ? snprintf+0x9d/0xd2 +[ 419.964344] ? __pfx_snprintf+0x10/0x10 +[ 419.964675] ? lock_acquired+0x45c/0x5e9 +[ 419.965016] ? set_blocksize+0x139/0x1c1 +[ 419.965381] ? sb_set_blocksize+0x6d/0xae +[ 419.965742] ? __pfx_hfsplus_fill_super+0x10/0x10 +[ 419.966179] mount_bdev+0x12f/0x1bf +[ 419.966512] ? __pfx_mount_bdev+0x10/0x10 +[ 419.966886] ? vfs_parse_fs_string+0xce/0x111 +[ 419.967293] ? __pfx_vfs_parse_fs_string+0x10/0x10 +[ 419.967702] ? __pfx_hfsplus_mount+0x10/0x10 +[ 419.968073] legacy_get_tree+0x104/0x178 +[ 419.968414] vfs_get_tree+0x86/0x296 +[ 419.968751] path_mount+0xba3/0xd0b +[ 419.969157] ? __pfx_path_mount+0x10/0x10 +[ 419.969594] ? kmem_cache_free+0x1e2/0x260 +[ 419.970311] do_mount+0x99/0xe0 +[ 419.970630] ? __pfx_do_mount+0x10/0x10 +[ 419.971008] __do_sys_mount+0x199/0x1c9 +[ 419.971397] do_syscall_64+0xd0/0x135 +[ 419.971761] entry_SYSCALL_64_after_hwframe+0x76/0x7e +[ 419.972233] RIP: 0033:0x7c3cb812972e +[ 419.972564] Code: 48 8b 0d f5 46 0d 00 f7 d8 64 89 01 48 83 c8 ff c3 66 2e 0f 1f 84 00 00 00 00 00 90 f3 0f 1e fa 49 89 ca b8 a5 00 00 00 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 8b 0d c2 46 0d 00 f7 d8 64 89 01 48 +[ 419.974371] RSP: 002b:00007ffe30632548 EFLAGS: 00000286 ORIG_RAX: 00000000000000a5 +[ 419.975048] RAX: ffffffffffffffda RBX: 00007ffe306328d8 RCX: 00007c3cb812972e +[ 419.975701] RDX: 0000000020000000 RSI: 0000000020000c80 RDI: 00007ffe306325d0 +[ 419.976363] RBP: 00007ffe30632720 R08: 00007ffe30632610 R09: 0000000000000000 +[ 419.977034] R10: 0000000000200008 R11: 0000000000000286 R12: 0000000000000000 +[ 419.977713] R13: 00007ffe306328e8 R14: 00005a0eb298bc68 R15: 00007c3cb8356000 +[ 419.978375] </TASK> +[ 419.978589] + +Fixes: 6596528e391a ("hfsplus: ensure bio requests are not smaller than the hardware sectors") +Signed-off-by: Thadeu Lima de Souza Cascardo <cascardo@igalia.com> +Link: https://lore.kernel.org/r/20241107114109.839253-1-cascardo@igalia.com +Signed-off-by: Christian Brauner <brauner@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + fs/hfsplus/hfsplus_fs.h | 3 ++- + fs/hfsplus/wrapper.c | 2 ++ + 2 files changed, 4 insertions(+), 1 deletion(-) + +diff --git a/fs/hfsplus/hfsplus_fs.h b/fs/hfsplus/hfsplus_fs.h +index 59ce81dca73fc..5389918bbf29d 100644 +--- a/fs/hfsplus/hfsplus_fs.h ++++ b/fs/hfsplus/hfsplus_fs.h +@@ -156,6 +156,7 @@ struct hfsplus_sb_info { + + /* Runtime variables */ + u32 blockoffset; ++ u32 min_io_size; + sector_t part_start; + sector_t sect_count; + int fs_shift; +@@ -307,7 +308,7 @@ struct hfsplus_readdir_data { + */ + static inline unsigned short hfsplus_min_io_size(struct super_block *sb) + { +- return max_t(unsigned short, bdev_logical_block_size(sb->s_bdev), ++ return max_t(unsigned short, HFSPLUS_SB(sb)->min_io_size, + HFSPLUS_SECTOR_SIZE); + } + +diff --git a/fs/hfsplus/wrapper.c b/fs/hfsplus/wrapper.c +index 9592ffcb44e5e..74801911bc1cc 100644 +--- a/fs/hfsplus/wrapper.c ++++ b/fs/hfsplus/wrapper.c +@@ -172,6 +172,8 @@ int hfsplus_read_wrapper(struct super_block *sb) + if (!blocksize) + goto out; + ++ sbi->min_io_size = blocksize; ++ + if (hfsplus_get_last_session(sb, &part_start, &part_size)) + goto out; + +-- +2.43.0 + diff --git a/queue-6.12/hid-hyperv-streamline-driver-probe-to-avoid-devres-i.patch b/queue-6.12/hid-hyperv-streamline-driver-probe-to-avoid-devres-i.patch new file mode 100644 index 00000000000..627da331b32 --- /dev/null +++ b/queue-6.12/hid-hyperv-streamline-driver-probe-to-avoid-devres-i.patch @@ -0,0 +1,182 @@ +From c85aa9066a1d549186b905d6da1305234a8653de Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Mon, 11 Nov 2024 14:12:40 +0100 +Subject: HID: hyperv: streamline driver probe to avoid devres issues + +From: Vitaly Kuznetsov <vkuznets@redhat.com> + +[ Upstream commit 66ef47faa90d838cda131fe1f7776456cc3b59f2 ] + +It was found that unloading 'hid_hyperv' module results in a devres +complaint: + + ... + hv_vmbus: unregistering driver hid_hyperv + ------------[ cut here ]------------ + WARNING: CPU: 2 PID: 3983 at drivers/base/devres.c:691 devres_release_group+0x1f2/0x2c0 + ... + Call Trace: + <TASK> + ? devres_release_group+0x1f2/0x2c0 + ? __warn+0xd1/0x1c0 + ? devres_release_group+0x1f2/0x2c0 + ? report_bug+0x32a/0x3c0 + ? handle_bug+0x53/0xa0 + ? exc_invalid_op+0x18/0x50 + ? asm_exc_invalid_op+0x1a/0x20 + ? devres_release_group+0x1f2/0x2c0 + ? devres_release_group+0x90/0x2c0 + ? rcu_is_watching+0x15/0xb0 + ? __pfx_devres_release_group+0x10/0x10 + hid_device_remove+0xf5/0x220 + device_release_driver_internal+0x371/0x540 + ? klist_put+0xf3/0x170 + bus_remove_device+0x1f1/0x3f0 + device_del+0x33f/0x8c0 + ? __pfx_device_del+0x10/0x10 + ? cleanup_srcu_struct+0x337/0x500 + hid_destroy_device+0xc8/0x130 + mousevsc_remove+0xd2/0x1d0 [hid_hyperv] + device_release_driver_internal+0x371/0x540 + driver_detach+0xc5/0x180 + bus_remove_driver+0x11e/0x2a0 + ? __mutex_unlock_slowpath+0x160/0x5e0 + vmbus_driver_unregister+0x62/0x2b0 [hv_vmbus] + ... + +And the issue seems to be that the corresponding devres group is not +allocated. Normally, devres_open_group() is called from +__hid_device_probe() but Hyper-V HID driver overrides 'hid_dev->driver' +with 'mousevsc_hid_driver' stub and basically re-implements +__hid_device_probe() by calling hid_parse() and hid_hw_start() but not +devres_open_group(). hid_device_probe() does not call __hid_device_probe() +for it. Later, when the driver is removed, hid_device_remove() calls +devres_release_group() as it doesn't check whether hdev->driver was +initially overridden or not. + +The issue seems to be related to the commit 62c68e7cee33 ("HID: ensure +timely release of driver-allocated resources") but the commit itself seems +to be correct. + +Fix the issue by dropping the 'hid_dev->driver' override and using +hid_register_driver()/hid_unregister_driver() instead. Alternatively, it +would have been possible to rely on the default handling but +HID_CONNECT_DEFAULT implies HID_CONNECT_HIDRAW and it doesn't seem to work +for mousevsc as-is. + +Fixes: 62c68e7cee33 ("HID: ensure timely release of driver-allocated resources") +Suggested-by: Michael Kelley <mhklinux@outlook.com> +Signed-off-by: Vitaly Kuznetsov <vkuznets@redhat.com> +Reviewed-by: Michael Kelley <mhklinux@outlook.com> +Tested-by: Saurabh Sengar <ssengar@linux.microsoft.com> +Signed-off-by: Jiri Kosina <jkosina@suse.com> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/hid/hid-hyperv.c | 58 ++++++++++++++++++++++++++++------------ + 1 file changed, 41 insertions(+), 17 deletions(-) + +diff --git a/drivers/hid/hid-hyperv.c b/drivers/hid/hid-hyperv.c +index f33485d83d24f..0fb210e40a412 100644 +--- a/drivers/hid/hid-hyperv.c ++++ b/drivers/hid/hid-hyperv.c +@@ -422,6 +422,25 @@ static int mousevsc_hid_raw_request(struct hid_device *hid, + return 0; + } + ++static int mousevsc_hid_probe(struct hid_device *hid_dev, const struct hid_device_id *id) ++{ ++ int ret; ++ ++ ret = hid_parse(hid_dev); ++ if (ret) { ++ hid_err(hid_dev, "parse failed\n"); ++ return ret; ++ } ++ ++ ret = hid_hw_start(hid_dev, HID_CONNECT_HIDINPUT | HID_CONNECT_HIDDEV); ++ if (ret) { ++ hid_err(hid_dev, "hw start failed\n"); ++ return ret; ++ } ++ ++ return 0; ++} ++ + static const struct hid_ll_driver mousevsc_ll_driver = { + .parse = mousevsc_hid_parse, + .open = mousevsc_hid_open, +@@ -431,7 +450,16 @@ static const struct hid_ll_driver mousevsc_ll_driver = { + .raw_request = mousevsc_hid_raw_request, + }; + +-static struct hid_driver mousevsc_hid_driver; ++static const struct hid_device_id mousevsc_devices[] = { ++ { HID_DEVICE(BUS_VIRTUAL, HID_GROUP_ANY, 0x045E, 0x0621) }, ++ { } ++}; ++ ++static struct hid_driver mousevsc_hid_driver = { ++ .name = "hid-hyperv", ++ .id_table = mousevsc_devices, ++ .probe = mousevsc_hid_probe, ++}; + + static int mousevsc_probe(struct hv_device *device, + const struct hv_vmbus_device_id *dev_id) +@@ -473,7 +501,6 @@ static int mousevsc_probe(struct hv_device *device, + } + + hid_dev->ll_driver = &mousevsc_ll_driver; +- hid_dev->driver = &mousevsc_hid_driver; + hid_dev->bus = BUS_VIRTUAL; + hid_dev->vendor = input_dev->hid_dev_info.vendor; + hid_dev->product = input_dev->hid_dev_info.product; +@@ -488,20 +515,6 @@ static int mousevsc_probe(struct hv_device *device, + if (ret) + goto probe_err2; + +- +- ret = hid_parse(hid_dev); +- if (ret) { +- hid_err(hid_dev, "parse failed\n"); +- goto probe_err2; +- } +- +- ret = hid_hw_start(hid_dev, HID_CONNECT_HIDINPUT | HID_CONNECT_HIDDEV); +- +- if (ret) { +- hid_err(hid_dev, "hw start failed\n"); +- goto probe_err2; +- } +- + device_init_wakeup(&device->device, true); + + input_dev->connected = true; +@@ -579,12 +592,23 @@ static struct hv_driver mousevsc_drv = { + + static int __init mousevsc_init(void) + { +- return vmbus_driver_register(&mousevsc_drv); ++ int ret; ++ ++ ret = hid_register_driver(&mousevsc_hid_driver); ++ if (ret) ++ return ret; ++ ++ ret = vmbus_driver_register(&mousevsc_drv); ++ if (ret) ++ hid_unregister_driver(&mousevsc_hid_driver); ++ ++ return ret; + } + + static void __exit mousevsc_exit(void) + { + vmbus_driver_unregister(&mousevsc_drv); ++ hid_unregister_driver(&mousevsc_hid_driver); + } + + MODULE_LICENSE("GPL"); +-- +2.43.0 + diff --git a/queue-6.12/hwmon-aquacomputer_d5next-fix-length-of-speed_input-.patch b/queue-6.12/hwmon-aquacomputer_d5next-fix-length-of-speed_input-.patch new file mode 100644 index 00000000000..40e402090ca --- /dev/null +++ b/queue-6.12/hwmon-aquacomputer_d5next-fix-length-of-speed_input-.patch @@ -0,0 +1,43 @@ +From dd8f99f61f9de7efd6c71bfffdda0633d10237ff Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Sun, 24 Nov 2024 16:27:24 +0100 +Subject: hwmon: (aquacomputer_d5next) Fix length of speed_input array + +From: Aleksa Savic <savicaleksa83@gmail.com> + +[ Upstream commit 998b5a78a9ce1cc4378e7281e4ea310e37596170 ] + +Commit 120584c728a6 ("hwmon: (aquacomputer_d5next) Add support for Octo +flow sensor") added support for reading Octo flow sensor, but didn't +update the priv->speed_input array length. Since Octo has 8 fans, with +the addition of the flow sensor the proper length for speed_input is 9. + +Reported by Arne Schwabe on Github [1], who received a UBSAN warning. + +Fixes: 120584c728a6 ("hwmon: (aquacomputer_d5next) Add support for Octo flow sensor") +Closes: https://github.com/aleksamagicka/aquacomputer_d5next-hwmon/issues/100 [1] +Reported-by: Arne Schwabe <arne@rfc2549.org> +Signed-off-by: Aleksa Savic <savicaleksa83@gmail.com> +Message-ID: <20241124152725.7205-1-savicaleksa83@gmail.com> +Signed-off-by: Guenter Roeck <linux@roeck-us.net> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/hwmon/aquacomputer_d5next.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/hwmon/aquacomputer_d5next.c b/drivers/hwmon/aquacomputer_d5next.c +index 34cac27e4ddec..0dcb8a3a691d6 100644 +--- a/drivers/hwmon/aquacomputer_d5next.c ++++ b/drivers/hwmon/aquacomputer_d5next.c +@@ -597,7 +597,7 @@ struct aqc_data { + + /* Sensor values */ + s32 temp_input[20]; /* Max 4 physical and 16 virtual or 8 physical and 12 virtual */ +- s32 speed_input[8]; ++ s32 speed_input[9]; + u32 speed_input_min[1]; + u32 speed_input_target[1]; + u32 speed_input_max[1]; +-- +2.43.0 + diff --git a/queue-6.12/hwmon-nct6775-core-fix-overflows-seen-when-writing-l.patch b/queue-6.12/hwmon-nct6775-core-fix-overflows-seen-when-writing-l.patch new file mode 100644 index 00000000000..739c2cc7e0c --- /dev/null +++ b/queue-6.12/hwmon-nct6775-core-fix-overflows-seen-when-writing-l.patch @@ -0,0 +1,58 @@ +From 2ad593451011c2c0a2641332c0e1b5adf9052ecf Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Tue, 12 Nov 2024 09:39:51 +0800 +Subject: hwmon: (nct6775-core) Fix overflows seen when writing limit + attributes + +From: Pei Xiao <xiaopei01@kylinos.cn> + +[ Upstream commit 57ee12b6c514146c19b6a159013b48727a012960 ] + +DIV_ROUND_CLOSEST() after kstrtoul() results in an overflow if a large +number such as 18446744073709551615 is provided by the user. +Fix it by reordering clamp_val() and DIV_ROUND_CLOSEST() operations. + +Signed-off-by: Pei Xiao <xiaopei01@kylinos.cn> +Fixes: c3963bc0a0cf ("hwmon: (nct6775) Split core and platform driver") +Message-ID: <7d5084cea33f7c0fd0578c59adfff71f93de94d9.1731375425.git.xiaopei01@kylinos.cn> +Signed-off-by: Guenter Roeck <linux@roeck-us.net> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/hwmon/nct6775-core.c | 7 +++---- + 1 file changed, 3 insertions(+), 4 deletions(-) + +diff --git a/drivers/hwmon/nct6775-core.c b/drivers/hwmon/nct6775-core.c +index 934fed3dd5866..ee04795b98aab 100644 +--- a/drivers/hwmon/nct6775-core.c ++++ b/drivers/hwmon/nct6775-core.c +@@ -2878,8 +2878,7 @@ store_target_temp(struct device *dev, struct device_attribute *attr, + if (err < 0) + return err; + +- val = clamp_val(DIV_ROUND_CLOSEST(val, 1000), 0, +- data->target_temp_mask); ++ val = DIV_ROUND_CLOSEST(clamp_val(val, 0, data->target_temp_mask * 1000), 1000); + + mutex_lock(&data->update_lock); + data->target_temp[nr] = val; +@@ -2959,7 +2958,7 @@ store_temp_tolerance(struct device *dev, struct device_attribute *attr, + return err; + + /* Limit tolerance as needed */ +- val = clamp_val(DIV_ROUND_CLOSEST(val, 1000), 0, data->tolerance_mask); ++ val = DIV_ROUND_CLOSEST(clamp_val(val, 0, data->tolerance_mask * 1000), 1000); + + mutex_lock(&data->update_lock); + data->temp_tolerance[index][nr] = val; +@@ -3085,7 +3084,7 @@ store_weight_temp(struct device *dev, struct device_attribute *attr, + if (err < 0) + return err; + +- val = clamp_val(DIV_ROUND_CLOSEST(val, 1000), 0, 255); ++ val = DIV_ROUND_CLOSEST(clamp_val(val, 0, 255000), 1000); + + mutex_lock(&data->update_lock); + data->weight_temp[index][nr] = val; +-- +2.43.0 + diff --git a/queue-6.12/hwmon-pmbus-core-clear-faults-after-setting-smbalert.patch b/queue-6.12/hwmon-pmbus-core-clear-faults-after-setting-smbalert.patch new file mode 100644 index 00000000000..a9f92ae139a --- /dev/null +++ b/queue-6.12/hwmon-pmbus-core-clear-faults-after-setting-smbalert.patch @@ -0,0 +1,61 @@ +From df0adf3944cf2b42893e56e24c81bb4218366c89 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Tue, 5 Nov 2024 18:58:42 +0100 +Subject: hwmon: (pmbus/core) clear faults after setting smbalert mask + +From: Jerome Brunet <jbrunet@baylibre.com> + +[ Upstream commit 509c3a362675bc995771df74d545548f98e37621 ] + +pmbus_write_smbalert_mask() ignores the errors if the chip can't set +smbalert mask the standard way. It is not necessarily a problem for the irq +support if the chip is otherwise properly setup but it may leave an +uncleared fault behind. + +pmbus_core will pick the fault on the next register_check(). The register +check will fails regardless of the actual register support by the chip. + +This leads to missing attributes or debugfs entries for chips that should +provide them. + +We cannot rely on register_check() as PMBUS_SMBALERT_MASK may be read-only. + +Unconditionally clear the page fault after setting PMBUS_SMBALERT_MASK to +avoid the problem. + +Suggested-by: Guenter Roeck <linux@roeck-us.net> +Fixes: 221819ca4c36 ("hwmon: (pmbus/core) Add interrupt support") +Signed-off-by: Jerome Brunet <jbrunet@baylibre.com> +Message-ID: <20241105-tps25990-v4-5-0e312ac70b62@baylibre.com> +Signed-off-by: Guenter Roeck <linux@roeck-us.net> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/hwmon/pmbus/pmbus_core.c | 12 +++++++++++- + 1 file changed, 11 insertions(+), 1 deletion(-) + +diff --git a/drivers/hwmon/pmbus/pmbus_core.c b/drivers/hwmon/pmbus/pmbus_core.c +index ce7fd4ca9d89b..a68b0a98e8d4d 100644 +--- a/drivers/hwmon/pmbus/pmbus_core.c ++++ b/drivers/hwmon/pmbus/pmbus_core.c +@@ -3279,7 +3279,17 @@ static int pmbus_regulator_notify(struct pmbus_data *data, int page, int event) + + static int pmbus_write_smbalert_mask(struct i2c_client *client, u8 page, u8 reg, u8 val) + { +- return _pmbus_write_word_data(client, page, PMBUS_SMBALERT_MASK, reg | (val << 8)); ++ int ret; ++ ++ ret = _pmbus_write_word_data(client, page, PMBUS_SMBALERT_MASK, reg | (val << 8)); ++ ++ /* ++ * Clear fault systematically in case writing PMBUS_SMBALERT_MASK ++ * is not supported by the chip. ++ */ ++ pmbus_clear_fault_page(client, page); ++ ++ return ret; + } + + static irqreturn_t pmbus_fault_handler(int irq, void *pdata) +-- +2.43.0 + diff --git a/queue-6.12/hwmon-tps23861-fix-reporting-of-negative-temperature.patch b/queue-6.12/hwmon-tps23861-fix-reporting-of-negative-temperature.patch new file mode 100644 index 00000000000..a68afc35367 --- /dev/null +++ b/queue-6.12/hwmon-tps23861-fix-reporting-of-negative-temperature.patch @@ -0,0 +1,42 @@ +From 4e88260d843f87445c2da4c66f8be8bb38adf872 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Thu, 21 Nov 2024 20:36:03 +0300 +Subject: hwmon: (tps23861) Fix reporting of negative temperatures + +From: Murad Masimov <m.masimov@maxima.ru> + +[ Upstream commit de2bf507fabba9c0c678cf5ed54beb546f5ca29a ] + +Negative temperatures are reported as large positive temperatures +due to missing sign extension from unsigned int to long. Cast unsigned +raw register values to signed before performing the calculations +to fix the problem. + +Found by Linux Verification Center (linuxtesting.org) with SVACE. + +Fixes: fff7b8ab2255 ("hwmon: add Texas Instruments TPS23861 driver") +Signed-off-by: Murad Masimov <m.masimov@maxima.ru> +Message-ID: <20241121173604.2021-1-m.masimov@maxima.ru> +[groeck: Updated subject and description] +Signed-off-by: Guenter Roeck <linux@roeck-us.net> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/hwmon/tps23861.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/hwmon/tps23861.c b/drivers/hwmon/tps23861.c +index dfcfb09d9f3cd..80fb03f30c302 100644 +--- a/drivers/hwmon/tps23861.c ++++ b/drivers/hwmon/tps23861.c +@@ -132,7 +132,7 @@ static int tps23861_read_temp(struct tps23861_data *data, long *val) + if (err < 0) + return err; + +- *val = (regval * TEMPERATURE_LSB) - 20000; ++ *val = ((long)regval * TEMPERATURE_LSB) - 20000; + + return 0; + } +-- +2.43.0 + diff --git a/queue-6.12/i2c-dev-fix-memory-leak-when-underlying-adapter-does.patch b/queue-6.12/i2c-dev-fix-memory-leak-when-underlying-adapter-does.patch new file mode 100644 index 00000000000..45c97a2a8b8 --- /dev/null +++ b/queue-6.12/i2c-dev-fix-memory-leak-when-underlying-adapter-does.patch @@ -0,0 +1,97 @@ +From f3304f5dc5bf8183aac43cac3bd4b71118bf2a58 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Fri, 8 Nov 2024 00:15:42 +0000 +Subject: i2c: dev: Fix memory leak when underlying adapter does not support + I2C + +From: Igor Pylypiv <ipylypiv@google.com> + +[ Upstream commit 48730a9d04ffccda541602d722d1ff81920a85d8 ] + +Early return in i2cdev_ioctl_rdwr() failed to free the memory allocated +by the caller. Move freeing the memory to the function where it has been +allocated to prevent similar leaks in the future. + +Fixes: 97ca843f6ad3 ("i2c: dev: Check for I2C_FUNC_I2C before calling i2c_transfer") +Signed-off-by: Igor Pylypiv <ipylypiv@google.com> +[wsa: replaced '== NULL' with '!'] +Signed-off-by: Wolfram Sang <wsa+renesas@sang-engineering.com> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/i2c/i2c-dev.c | 17 +++++++++-------- + 1 file changed, 9 insertions(+), 8 deletions(-) + +diff --git a/drivers/i2c/i2c-dev.c b/drivers/i2c/i2c-dev.c +index 61f7c4003d2ff..e9577f920286d 100644 +--- a/drivers/i2c/i2c-dev.c ++++ b/drivers/i2c/i2c-dev.c +@@ -251,10 +251,8 @@ static noinline int i2cdev_ioctl_rdwr(struct i2c_client *client, + return -EOPNOTSUPP; + + data_ptrs = kmalloc_array(nmsgs, sizeof(u8 __user *), GFP_KERNEL); +- if (data_ptrs == NULL) { +- kfree(msgs); ++ if (!data_ptrs) + return -ENOMEM; +- } + + res = 0; + for (i = 0; i < nmsgs; i++) { +@@ -302,7 +300,6 @@ static noinline int i2cdev_ioctl_rdwr(struct i2c_client *client, + for (j = 0; j < i; ++j) + kfree(msgs[j].buf); + kfree(data_ptrs); +- kfree(msgs); + return res; + } + +@@ -316,7 +313,6 @@ static noinline int i2cdev_ioctl_rdwr(struct i2c_client *client, + kfree(msgs[i].buf); + } + kfree(data_ptrs); +- kfree(msgs); + return res; + } + +@@ -446,6 +442,7 @@ static long i2cdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg) + case I2C_RDWR: { + struct i2c_rdwr_ioctl_data rdwr_arg; + struct i2c_msg *rdwr_pa; ++ int res; + + if (copy_from_user(&rdwr_arg, + (struct i2c_rdwr_ioctl_data __user *)arg, +@@ -467,7 +464,9 @@ static long i2cdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg) + if (IS_ERR(rdwr_pa)) + return PTR_ERR(rdwr_pa); + +- return i2cdev_ioctl_rdwr(client, rdwr_arg.nmsgs, rdwr_pa); ++ res = i2cdev_ioctl_rdwr(client, rdwr_arg.nmsgs, rdwr_pa); ++ kfree(rdwr_pa); ++ return res; + } + + case I2C_SMBUS: { +@@ -540,7 +539,7 @@ static long compat_i2cdev_ioctl(struct file *file, unsigned int cmd, unsigned lo + struct i2c_rdwr_ioctl_data32 rdwr_arg; + struct i2c_msg32 __user *p; + struct i2c_msg *rdwr_pa; +- int i; ++ int i, res; + + if (copy_from_user(&rdwr_arg, + (struct i2c_rdwr_ioctl_data32 __user *)arg, +@@ -573,7 +572,9 @@ static long compat_i2cdev_ioctl(struct file *file, unsigned int cmd, unsigned lo + }; + } + +- return i2cdev_ioctl_rdwr(client, rdwr_arg.nmsgs, rdwr_pa); ++ res = i2cdev_ioctl_rdwr(client, rdwr_arg.nmsgs, rdwr_pa); ++ kfree(rdwr_pa); ++ return res; + } + case I2C_SMBUS: { + struct i2c_smbus_ioctl_data32 data32; +-- +2.43.0 + diff --git a/queue-6.12/i3c-master-remove-i3c_dev_disable_ibi_locked-olddev-.patch b/queue-6.12/i3c-master-remove-i3c_dev_disable_ibi_locked-olddev-.patch new file mode 100644 index 00000000000..c3d35fbea23 --- /dev/null +++ b/queue-6.12/i3c-master-remove-i3c_dev_disable_ibi_locked-olddev-.patch @@ -0,0 +1,82 @@ +From 3cf5ad0cfec037361bc2948441208b44cd043eb6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Tue, 1 Oct 2024 12:22:32 -0400 +Subject: i3c: master: Remove i3c_dev_disable_ibi_locked(olddev) on device + hotjoin + +From: Frank Li <Frank.Li@nxp.com> + +[ Upstream commit 36faa04ce3d9c962b4b29d285ad07ca29e2988e4 ] + +When a new device hotjoins, a new dynamic address is assigned. +i3c_master_add_i3c_dev_locked() identifies that the device was previously +attached to the bus and locates the olddev. + +i3c_master_add_i3c_dev_locked() +{ + ... + olddev = i3c_master_search_i3c_dev_duplicate(newdev); + ... + if (olddev) { + ... + i3c_dev_disable_ibi_locked(olddev); + ^^^^^^ + The olddev should not receive any commands on the i3c bus as it + does not exist and has been assigned a new address. This will + result in NACK or timeout. So remove it. + } + + i3c_dev_free_ibi_locked(olddev); + ^^^^^^^^ + This function internally calls i3c_dev_disable_ibi_locked() function + causing to send DISEC command with old Address. + + The olddev should not receive any commands on the i3c bus as it + does not exist and has been assigned a new address. This will + result in NACK or timeout. So, update the olddev->ibi->enabled + flag to false to avoid DISEC with OldAddr. +} + +Include part of Ravindra Yashvant Shinde's work: +https://lore.kernel.org/linux-i3c/20240820151917.3904956-1-ravindra.yashvant.shinde@nxp.com/T/#u + +Fixes: 317bacf960a4 ("i3c: master: add enable(disable) hot join in sys entry") +Co-developed-by: Ravindra Yashvant Shinde <ravindra.yashvant.shinde@nxp.com> +Signed-off-by: Ravindra Yashvant Shinde <ravindra.yashvant.shinde@nxp.com> +Reviewed-by: Miquel Raynal <miquel.raynal@bootlin.com> +Signed-off-by: Frank Li <Frank.Li@nxp.com> +Link: https://lore.kernel.org/r/20241001162232.223724-1-Frank.Li@nxp.com +Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/i3c/master.c | 13 +++++++++---- + 1 file changed, 9 insertions(+), 4 deletions(-) + +diff --git a/drivers/i3c/master.c b/drivers/i3c/master.c +index 6f3eb710a75d6..ffe99f0c6acef 100644 +--- a/drivers/i3c/master.c ++++ b/drivers/i3c/master.c +@@ -2051,11 +2051,16 @@ int i3c_master_add_i3c_dev_locked(struct i3c_master_controller *master, + ibireq.max_payload_len = olddev->ibi->max_payload_len; + ibireq.num_slots = olddev->ibi->num_slots; + +- if (olddev->ibi->enabled) { ++ if (olddev->ibi->enabled) + enable_ibi = true; +- i3c_dev_disable_ibi_locked(olddev); +- } +- ++ /* ++ * The olddev should not receive any commands on the ++ * i3c bus as it does not exist and has been assigned ++ * a new address. This will result in NACK or timeout. ++ * So, update the olddev->ibi->enabled flag to false ++ * to avoid DISEC with OldAddr. ++ */ ++ olddev->ibi->enabled = false; + i3c_dev_free_ibi_locked(olddev); + } + mutex_unlock(&olddev->ibi_lock); +-- +2.43.0 + diff --git a/queue-6.12/ice-consistently-use-q_idx-in-ice_vc_cfg_qs_msg.patch b/queue-6.12/ice-consistently-use-q_idx-in-ice_vc_cfg_qs_msg.patch new file mode 100644 index 00000000000..abd98310727 --- /dev/null +++ b/queue-6.12/ice-consistently-use-q_idx-in-ice_vc_cfg_qs_msg.patch @@ -0,0 +1,100 @@ +From 3326f9e9b41df001ddb3a56998204b4afb14a3e9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Mon, 9 Sep 2024 16:07:44 -0700 +Subject: ice: consistently use q_idx in ice_vc_cfg_qs_msg() + +From: Jacob Keller <jacob.e.keller@intel.com> + +[ Upstream commit a884c304e18a40e1c7a6525a9274e64c2c061c3f ] + +The ice_vc_cfg_qs_msg() function is used to configure VF queues in response +to a VIRTCHNL_OP_CONFIG_VSI_QUEUES command. + +The virtchnl command contains an array of queue pair data for configuring +Tx and Rx queues. This data includes a queue ID. When configuring the +queues, the driver generally uses this queue ID to determine which Tx and +Rx ring to program. However, a handful of places use the index into the +queue pair data from the VF. While most VF implementations appear to send +this data in order, it is not mandated by the virtchnl and it is not +verified that the queue pair data comes in order. + +Fix the driver to consistently use the q_idx field instead of the 'i' +iterator value when accessing the rings. For the Rx case, introduce a local +ring variable to keep lines short. + +Fixes: 7ad15440acf8 ("ice: Refactor VIRTCHNL_OP_CONFIG_VSI_QUEUES handling") +Signed-off-by: Jacob Keller <jacob.e.keller@intel.com> +Tested-by: Rafal Romanowski <rafal.romanowski@intel.com> +Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/net/ethernet/intel/ice/ice_virtchnl.c | 21 +++++++++---------- + 1 file changed, 10 insertions(+), 11 deletions(-) + +diff --git a/drivers/net/ethernet/intel/ice/ice_virtchnl.c b/drivers/net/ethernet/intel/ice/ice_virtchnl.c +index 59f62306b9cb0..b6ec01f6fa73e 100644 +--- a/drivers/net/ethernet/intel/ice/ice_virtchnl.c ++++ b/drivers/net/ethernet/intel/ice/ice_virtchnl.c +@@ -1715,8 +1715,8 @@ static int ice_vc_cfg_qs_msg(struct ice_vf *vf, u8 *msg) + + /* copy Tx queue info from VF into VSI */ + if (qpi->txq.ring_len > 0) { +- vsi->tx_rings[i]->dma = qpi->txq.dma_ring_addr; +- vsi->tx_rings[i]->count = qpi->txq.ring_len; ++ vsi->tx_rings[q_idx]->dma = qpi->txq.dma_ring_addr; ++ vsi->tx_rings[q_idx]->count = qpi->txq.ring_len; + + /* Disable any existing queue first */ + if (ice_vf_vsi_dis_single_txq(vf, vsi, q_idx)) +@@ -1725,7 +1725,7 @@ static int ice_vc_cfg_qs_msg(struct ice_vf *vf, u8 *msg) + /* Configure a queue with the requested settings */ + if (ice_vsi_cfg_single_txq(vsi, vsi->tx_rings, q_idx)) { + dev_warn(ice_pf_to_dev(pf), "VF-%d failed to configure TX queue %d\n", +- vf->vf_id, i); ++ vf->vf_id, q_idx); + goto error_param; + } + } +@@ -1733,24 +1733,23 @@ static int ice_vc_cfg_qs_msg(struct ice_vf *vf, u8 *msg) + /* copy Rx queue info from VF into VSI */ + if (qpi->rxq.ring_len > 0) { + u16 max_frame_size = ice_vc_get_max_frame_size(vf); ++ struct ice_rx_ring *ring = vsi->rx_rings[q_idx]; + u32 rxdid; + +- vsi->rx_rings[i]->dma = qpi->rxq.dma_ring_addr; +- vsi->rx_rings[i]->count = qpi->rxq.ring_len; ++ ring->dma = qpi->rxq.dma_ring_addr; ++ ring->count = qpi->rxq.ring_len; + + if (qpi->rxq.crc_disable) +- vsi->rx_rings[q_idx]->flags |= +- ICE_RX_FLAGS_CRC_STRIP_DIS; ++ ring->flags |= ICE_RX_FLAGS_CRC_STRIP_DIS; + else +- vsi->rx_rings[q_idx]->flags &= +- ~ICE_RX_FLAGS_CRC_STRIP_DIS; ++ ring->flags &= ~ICE_RX_FLAGS_CRC_STRIP_DIS; + + if (qpi->rxq.databuffer_size != 0 && + (qpi->rxq.databuffer_size > ((16 * 1024) - 128) || + qpi->rxq.databuffer_size < 1024)) + goto error_param; + vsi->rx_buf_len = qpi->rxq.databuffer_size; +- vsi->rx_rings[i]->rx_buf_len = vsi->rx_buf_len; ++ ring->rx_buf_len = vsi->rx_buf_len; + if (qpi->rxq.max_pkt_size > max_frame_size || + qpi->rxq.max_pkt_size < 64) + goto error_param; +@@ -1765,7 +1764,7 @@ static int ice_vc_cfg_qs_msg(struct ice_vf *vf, u8 *msg) + + if (ice_vsi_cfg_single_rxq(vsi, q_idx)) { + dev_warn(ice_pf_to_dev(pf), "VF-%d failed to configure RX queue %d\n", +- vf->vf_id, i); ++ vf->vf_id, q_idx); + goto error_param; + } + +-- +2.43.0 + diff --git a/queue-6.12/iio-accel-adxl380-fix-raw-sample-read.patch b/queue-6.12/iio-accel-adxl380-fix-raw-sample-read.patch new file mode 100644 index 00000000000..a4d8f7ebc25 --- /dev/null +++ b/queue-6.12/iio-accel-adxl380-fix-raw-sample-read.patch @@ -0,0 +1,39 @@ +From 5088d7be143333aada4e4b476e6489f240cc8c4e Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Fri, 1 Nov 2024 11:52:01 +0200 +Subject: iio: accel: adxl380: fix raw sample read + +From: Antoniu Miclaus <antoniu.miclaus@analog.com> + +[ Upstream commit bfa335f18d91c52fa0f8ba3e4d49afebbd9ee792 ] + +The adxl380_read_chn function returns either a negative value in case an +error occurs or the actual sample. + +Check only for negative values after a channel is read. + +Fixes: df36de13677a ("iio: accel: add ADXL380 driver") +Signed-off-by: Antoniu Miclaus <antoniu.miclaus@analog.com> +Link: https://patch.msgid.link/20241101095202.20121-1-antoniu.miclaus@analog.com +Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/iio/accel/adxl380.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/iio/accel/adxl380.c b/drivers/iio/accel/adxl380.c +index f80527d899be4..b19ee37df7f12 100644 +--- a/drivers/iio/accel/adxl380.c ++++ b/drivers/iio/accel/adxl380.c +@@ -1181,7 +1181,7 @@ static int adxl380_read_raw(struct iio_dev *indio_dev, + + ret = adxl380_read_chn(st, chan->address); + iio_device_release_direct_mode(indio_dev); +- if (ret) ++ if (ret < 0) + return ret; + + *val = sign_extend32(ret >> chan->scan_type.shift, +-- +2.43.0 + diff --git a/queue-6.12/iio-adc-ad4000-check-for-error-code-from-devm_mutex_.patch b/queue-6.12/iio-adc-ad4000-check-for-error-code-from-devm_mutex_.patch new file mode 100644 index 00000000000..f59a707fdcb --- /dev/null +++ b/queue-6.12/iio-adc-ad4000-check-for-error-code-from-devm_mutex_.patch @@ -0,0 +1,41 @@ +From 6d2f7beb521d0c3a9474359c556ce84fe91102fe Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Wed, 30 Oct 2024 18:19:18 +0200 +Subject: iio: adc: ad4000: Check for error code from devm_mutex_init() call + +From: Andy Shevchenko <andriy.shevchenko@linux.intel.com> + +[ Upstream commit 8ebfd09255219ae55f8a101f6aeb0f64dd780d88 ] + +Even if it's not critical, the avoidance of checking the error code +from devm_mutex_init() call today diminishes the point of using devm +variant of it. Tomorrow it may even leak something. Add the missed +check. + +Fixes: 938fd562b974 ("iio: adc: Add support for AD4000") +Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com> +Link: https://patch.msgid.link/20241030162013.2100253-2-andriy.shevchenko@linux.intel.com +Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/iio/adc/ad4000.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/iio/adc/ad4000.c b/drivers/iio/adc/ad4000.c +index fc9c9807f89d2..b3b82535f5c14 100644 +--- a/drivers/iio/adc/ad4000.c ++++ b/drivers/iio/adc/ad4000.c +@@ -639,7 +639,9 @@ static int ad4000_probe(struct spi_device *spi) + indio_dev->name = chip->dev_name; + indio_dev->num_channels = 1; + +- devm_mutex_init(dev, &st->lock); ++ ret = devm_mutex_init(dev, &st->lock); ++ if (ret) ++ return ret; + + st->gain_milli = 1000; + if (chip->has_hardware_gain) { +-- +2.43.0 + diff --git a/queue-6.12/iio-adc-ad4000-fix-reading-unsigned-data.patch b/queue-6.12/iio-adc-ad4000-fix-reading-unsigned-data.patch new file mode 100644 index 00000000000..35765635966 --- /dev/null +++ b/queue-6.12/iio-adc-ad4000-fix-reading-unsigned-data.patch @@ -0,0 +1,39 @@ +From ca48d580ce089579cf1dc73c62d4de611ca54b6b Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Wed, 30 Oct 2024 16:09:41 -0500 +Subject: iio: adc: ad4000: fix reading unsigned data + +From: David Lechner <dlechner@baylibre.com> + +[ Upstream commit 62dd96ac9cdf2814f41cfc55ecaf22a28aad6ccb ] + +Fix reading unsigned data from the AD4000 ADC via the _raw sysfs +attribute by ensuring that *val is set before returning from +ad4000_single_conversion(). This was not being set in any code path +and was causing the attribute to return a random value. + +Fixes: 938fd562b974 ("iio: adc: Add support for AD4000") +Signed-off-by: David Lechner <dlechner@baylibre.com> +Link: https://patch.msgid.link/20241030-iio-adc-ad4000-fix-reading-unsigned-data-v1-1-2e28dd75fe29@baylibre.com +Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/iio/adc/ad4000.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/iio/adc/ad4000.c b/drivers/iio/adc/ad4000.c +index 6ea4912450849..fc9c9807f89d2 100644 +--- a/drivers/iio/adc/ad4000.c ++++ b/drivers/iio/adc/ad4000.c +@@ -344,6 +344,8 @@ static int ad4000_single_conversion(struct iio_dev *indio_dev, + + if (chan->scan_type.sign == 's') + *val = sign_extend32(sample, chan->scan_type.realbits - 1); ++ else ++ *val = sample; + + return IIO_VAL_INT; + } +-- +2.43.0 + diff --git a/queue-6.12/iio-adc-pac1921-check-for-error-code-from-devm_mutex.patch b/queue-6.12/iio-adc-pac1921-check-for-error-code-from-devm_mutex.patch new file mode 100644 index 00000000000..aff1936579c --- /dev/null +++ b/queue-6.12/iio-adc-pac1921-check-for-error-code-from-devm_mutex.patch @@ -0,0 +1,42 @@ +From f0e4dc2bb4f2a286bb8f54f907f4b420911299ed Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Wed, 30 Oct 2024 18:19:19 +0200 +Subject: iio: adc: pac1921: Check for error code from devm_mutex_init() call + +From: Andy Shevchenko <andriy.shevchenko@linux.intel.com> + +[ Upstream commit 869aa5e847696bcda8966be9d03de2560226bcc3 ] + +Even if it's not critical, the avoidance of checking the error code +from devm_mutex_init() call today diminishes the point of using devm +variant of it. Tomorrow it may even leak something. Add the missed +check. + +Fixes: 371f778b83cd ("iio: adc: add support for pac1921") +Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com> +Acked-by: Matteo Martelli <matteomartelli3@gmail.com> +Link: https://patch.msgid.link/20241030162013.2100253-3-andriy.shevchenko@linux.intel.com +Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/iio/adc/pac1921.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/iio/adc/pac1921.c b/drivers/iio/adc/pac1921.c +index 36e813d9c73f1..fe1d9e07fce24 100644 +--- a/drivers/iio/adc/pac1921.c ++++ b/drivers/iio/adc/pac1921.c +@@ -1171,7 +1171,9 @@ static int pac1921_probe(struct i2c_client *client) + return dev_err_probe(dev, (int)PTR_ERR(priv->regmap), + "Cannot initialize register map\n"); + +- devm_mutex_init(dev, &priv->lock); ++ ret = devm_mutex_init(dev, &priv->lock); ++ if (ret) ++ return ret; + + priv->dv_gain = PAC1921_DEFAULT_DV_GAIN; + priv->di_gain = PAC1921_DEFAULT_DI_GAIN; +-- +2.43.0 + diff --git a/queue-6.12/iio-backend-fix-wrong-pointer-passed-to-is_err.patch b/queue-6.12/iio-backend-fix-wrong-pointer-passed-to-is_err.patch new file mode 100644 index 00000000000..11ce41121d0 --- /dev/null +++ b/queue-6.12/iio-backend-fix-wrong-pointer-passed-to-is_err.patch @@ -0,0 +1,38 @@ +From 1fb0fe36818c88c0e6586800b8f092b8c44a501a Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Mon, 28 Oct 2024 21:52:15 +0800 +Subject: iio: backend: fix wrong pointer passed to IS_ERR() + +From: Yang Yingliang <yangyingliang@huawei.com> + +[ Upstream commit fa4076314480bcb2bb32051027735b1cde07eea2 ] + +It should be fwnode_back passed to IS_ERR(). + +Fixes: c464cc610f51 ("iio: add child nodes support in iio backend framework") +Signed-off-by: Yang Yingliang <yangyingliang@huawei.com> +Link: https://patch.msgid.link/20241028135215.1549-1-yangyingliang@huaweicloud.com +Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/iio/industrialio-backend.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/iio/industrialio-backend.c b/drivers/iio/industrialio-backend.c +index 20b3b5212da76..fb34a8e4d04e7 100644 +--- a/drivers/iio/industrialio-backend.c ++++ b/drivers/iio/industrialio-backend.c +@@ -737,8 +737,8 @@ static struct iio_backend *__devm_iio_backend_fwnode_get(struct device *dev, con + } + + fwnode_back = fwnode_find_reference(fwnode, "io-backends", index); +- if (IS_ERR(fwnode)) +- return dev_err_cast_probe(dev, fwnode, ++ if (IS_ERR(fwnode_back)) ++ return dev_err_cast_probe(dev, fwnode_back, + "Cannot get Firmware reference\n"); + + guard(mutex)(&iio_back_lock); +-- +2.43.0 + diff --git a/queue-6.12/iio-light-al3010-fix-an-error-handling-path-in-al301.patch b/queue-6.12/iio-light-al3010-fix-an-error-handling-path-in-al301.patch new file mode 100644 index 00000000000..39bcc77868c --- /dev/null +++ b/queue-6.12/iio-light-al3010-fix-an-error-handling-path-in-al301.patch @@ -0,0 +1,58 @@ +From 21ce4e5afac1e1ed178d6897cc0d0247c93afa26 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Tue, 10 Sep 2024 20:36:06 +0200 +Subject: iio: light: al3010: Fix an error handling path in al3010_probe() + +From: Christophe JAILLET <christophe.jaillet@wanadoo.fr> + +[ Upstream commit a4b7064d34186cf4970fe0333c3b27346cf8f819 ] + +If i2c_smbus_write_byte_data() fails in al3010_init(), +al3010_set_pwr(false) is not called. + +In order to avoid such a situation, move the devm_add_action_or_reset() +witch calls al3010_set_pwr(false) right after a successful +al3010_set_pwr(true). + +Fixes: c36b5195ab70 ("iio: light: add Dyna-Image AL3010 driver") +Signed-off-by: Christophe JAILLET <christophe.jaillet@wanadoo.fr> +Link: https://patch.msgid.link/ee5d10a2dd2b70f29772d5df33774d3974a80f30.1725993353.git.christophe.jaillet@wanadoo.fr +Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/iio/light/al3010.c | 11 +++++------ + 1 file changed, 5 insertions(+), 6 deletions(-) + +diff --git a/drivers/iio/light/al3010.c b/drivers/iio/light/al3010.c +index 53569587ccb7b..7cbb8b2033009 100644 +--- a/drivers/iio/light/al3010.c ++++ b/drivers/iio/light/al3010.c +@@ -87,7 +87,12 @@ static int al3010_init(struct al3010_data *data) + int ret; + + ret = al3010_set_pwr(data->client, true); ++ if (ret < 0) ++ return ret; + ++ ret = devm_add_action_or_reset(&data->client->dev, ++ al3010_set_pwr_off, ++ data); + if (ret < 0) + return ret; + +@@ -190,12 +195,6 @@ static int al3010_probe(struct i2c_client *client) + return ret; + } + +- ret = devm_add_action_or_reset(&client->dev, +- al3010_set_pwr_off, +- data); +- if (ret < 0) +- return ret; +- + return devm_iio_device_register(&client->dev, indio_dev); + } + +-- +2.43.0 + diff --git a/queue-6.12/initramfs-avoid-filename-buffer-overrun.patch b/queue-6.12/initramfs-avoid-filename-buffer-overrun.patch new file mode 100644 index 00000000000..4b0649d14ba --- /dev/null +++ b/queue-6.12/initramfs-avoid-filename-buffer-overrun.patch @@ -0,0 +1,118 @@ +From faf15753e1e0256b9e38f44236c48906f3c94b90 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Wed, 30 Oct 2024 03:55:10 +0000 +Subject: initramfs: avoid filename buffer overrun + +From: David Disseldorp <ddiss@suse.de> + +[ Upstream commit e017671f534dd3f568db9e47b0583e853d2da9b5 ] + +The initramfs filename field is defined in +Documentation/driver-api/early-userspace/buffer-format.rst as: + + 37 cpio_file := ALGN(4) + cpio_header + filename + "\0" + ALGN(4) + data +... + 55 ============= ================== ========================= + 56 Field name Field size Meaning + 57 ============= ================== ========================= +... + 70 c_namesize 8 bytes Length of filename, including final \0 + +When extracting an initramfs cpio archive, the kernel's do_name() path +handler assumes a zero-terminated path at @collected, passing it +directly to filp_open() / init_mkdir() / init_mknod(). + +If a specially crafted cpio entry carries a non-zero-terminated filename +and is followed by uninitialized memory, then a file may be created with +trailing characters that represent the uninitialized memory. The ability +to create an initramfs entry would imply already having full control of +the system, so the buffer overrun shouldn't be considered a security +vulnerability. + +Append the output of the following bash script to an existing initramfs +and observe any created /initramfs_test_fname_overrunAA* path. E.g. + ./reproducer.sh | gzip >> /myinitramfs + +It's easiest to observe non-zero uninitialized memory when the output is +gzipped, as it'll overflow the heap allocated @out_buf in __gunzip(), +rather than the initrd_start+initrd_size block. + +---- reproducer.sh ---- +nilchar="A" # change to "\0" to properly zero terminate / pad +magic="070701" +ino=1 +mode=$(( 0100777 )) +uid=0 +gid=0 +nlink=1 +mtime=1 +filesize=0 +devmajor=0 +devminor=1 +rdevmajor=0 +rdevminor=0 +csum=0 +fname="initramfs_test_fname_overrun" +namelen=$(( ${#fname} + 1 )) # plus one to account for terminator + +printf "%s%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%s" \ + $magic $ino $mode $uid $gid $nlink $mtime $filesize \ + $devmajor $devminor $rdevmajor $rdevminor $namelen $csum $fname + +termpadlen=$(( 1 + ((4 - ((110 + $namelen) & 3)) % 4) )) +printf "%.s${nilchar}" $(seq 1 $termpadlen) +---- reproducer.sh ---- + +Symlink filename fields handled in do_symlink() won't overrun past the +data segment, due to the explicit zero-termination of the symlink +target. + +Fix filename buffer overrun by aborting the initramfs FSM if any cpio +entry doesn't carry a zero-terminator at the expected (name_len - 1) +offset. + +Fixes: 1da177e4c3f41 ("Linux-2.6.12-rc2") +Signed-off-by: David Disseldorp <ddiss@suse.de> +Link: https://lore.kernel.org/r/20241030035509.20194-2-ddiss@suse.de +Signed-off-by: Christian Brauner <brauner@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + init/initramfs.c | 15 +++++++++++++++ + 1 file changed, 15 insertions(+) + +diff --git a/init/initramfs.c b/init/initramfs.c +index bc911e466d5bb..b2f7583bb1f5c 100644 +--- a/init/initramfs.c ++++ b/init/initramfs.c +@@ -360,6 +360,15 @@ static int __init do_name(void) + { + state = SkipIt; + next_state = Reset; ++ ++ /* name_len > 0 && name_len <= PATH_MAX checked in do_header */ ++ if (collected[name_len - 1] != '\0') { ++ pr_err("initramfs name without nulterm: %.*s\n", ++ (int)name_len, collected); ++ error("malformed archive"); ++ return 1; ++ } ++ + if (strcmp(collected, "TRAILER!!!") == 0) { + free_hash(); + return 0; +@@ -424,6 +433,12 @@ static int __init do_copy(void) + + static int __init do_symlink(void) + { ++ if (collected[name_len - 1] != '\0') { ++ pr_err("initramfs symlink without nulterm: %.*s\n", ++ (int)name_len, collected); ++ error("malformed archive"); ++ return 1; ++ } + collected[N_ALIGN(name_len) + body_len] = '\0'; + clean_path(collected, 0); + init_symlink(collected + N_ALIGN(name_len), collected); +-- +2.43.0 + diff --git a/queue-6.12/interconnect-qcom-icc-rpmh-probe-defer-incase-of-mis.patch b/queue-6.12/interconnect-qcom-icc-rpmh-probe-defer-incase-of-mis.patch new file mode 100644 index 00000000000..aea96aa8fb0 --- /dev/null +++ b/queue-6.12/interconnect-qcom-icc-rpmh-probe-defer-incase-of-mis.patch @@ -0,0 +1,43 @@ +From 9436ca5453e4acf94e5e08c7843452e5cd7fae18 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Wed, 11 Sep 2024 09:45:16 +0000 +Subject: interconnect: qcom: icc-rpmh: probe defer incase of missing QoS clock + dependency + +From: Raviteja Laggyshetty <quic_rlaggysh@quicinc.com> + +[ Upstream commit 05123e3299dd6aa02508469b303262338c2a661c ] + +Return -EPROBE_DEFER from interconnect provider incase probe defer is +received from devm_clk_bulk_get_all(). This would help in reattempting +the inteconnect driver probe, once the required QoS clocks are +available. + +Suggested-by: Bjorn Andersson <andersson@kernel.org> +Signed-off-by: Raviteja Laggyshetty <quic_rlaggysh@quicinc.com> +Reviewed-by: Konrad Dybcio <konradybcio@kernel.org> +Fixes: 0a7be6b35da8 ("interconnect: qcom: icc-rpmh: Add QoS configuration support") +Link: https://lore.kernel.org/r/20240911094516.16901-1-quic_rlaggysh@quicinc.com +Signed-off-by: Georgi Djakov <djakov@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/interconnect/qcom/icc-rpmh.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/interconnect/qcom/icc-rpmh.c b/drivers/interconnect/qcom/icc-rpmh.c +index f49a8e0cb03c0..adacd6f7d6a8f 100644 +--- a/drivers/interconnect/qcom/icc-rpmh.c ++++ b/drivers/interconnect/qcom/icc-rpmh.c +@@ -311,6 +311,9 @@ int qcom_icc_rpmh_probe(struct platform_device *pdev) + } + + qp->num_clks = devm_clk_bulk_get_all(qp->dev, &qp->clks); ++ if (qp->num_clks == -EPROBE_DEFER) ++ return dev_err_probe(dev, qp->num_clks, "Failed to get QoS clocks\n"); ++ + if (qp->num_clks < 0 || (!qp->num_clks && desc->qos_clks_required)) { + dev_info(dev, "Skipping QoS, failed to get clk: %d\n", qp->num_clks); + goto skip_qos_config; +-- +2.43.0 + diff --git a/queue-6.12/iommu-amd-pgtbl_v2-take-protection-domain-lock-befor.patch b/queue-6.12/iommu-amd-pgtbl_v2-take-protection-domain-lock-befor.patch new file mode 100644 index 00000000000..dfad385e4d4 --- /dev/null +++ b/queue-6.12/iommu-amd-pgtbl_v2-take-protection-domain-lock-befor.patch @@ -0,0 +1,44 @@ +From 1d90d75e8f75f3b3adcd04d4415d77c954472356 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Wed, 30 Oct 2024 06:35:45 +0000 +Subject: iommu/amd/pgtbl_v2: Take protection domain lock before invalidating + TLB + +From: Vasant Hegde <vasant.hegde@amd.com> + +[ Upstream commit 016991606aa01c4d92e6941be636c0c897aa05c7 ] + +Commit c7fc12354be0 ("iommu/amd/pgtbl_v2: Invalidate updated page ranges +only") missed to take domain lock before calling +amd_iommu_domain_flush_pages(). Fix this by taking protection domain +lock before calling TLB invalidation function. + +Fixes: c7fc12354be0 ("iommu/amd/pgtbl_v2: Invalidate updated page ranges only") +Signed-off-by: Vasant Hegde <vasant.hegde@amd.com> +Reviewed-by: Jason Gunthorpe <jgg@nvidia.com> +Link: https://lore.kernel.org/r/20241030063556.6104-2-vasant.hegde@amd.com +Signed-off-by: Joerg Roedel <jroedel@suse.de> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/iommu/amd/io_pgtable_v2.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/iommu/amd/io_pgtable_v2.c b/drivers/iommu/amd/io_pgtable_v2.c +index 25b9042fa4530..c616de2c5926e 100644 +--- a/drivers/iommu/amd/io_pgtable_v2.c ++++ b/drivers/iommu/amd/io_pgtable_v2.c +@@ -268,8 +268,11 @@ static int iommu_v2_map_pages(struct io_pgtable_ops *ops, unsigned long iova, + out: + if (updated) { + struct protection_domain *pdom = io_pgtable_ops_to_domain(ops); ++ unsigned long flags; + ++ spin_lock_irqsave(&pdom->lock, flags); + amd_iommu_domain_flush_pages(pdom, o_iova, size); ++ spin_unlock_irqrestore(&pdom->lock, flags); + } + + if (mapped) +-- +2.43.0 + diff --git a/queue-6.12/iommu-s390-implement-blocking-domain.patch b/queue-6.12/iommu-s390-implement-blocking-domain.patch new file mode 100644 index 00000000000..7c230a5b428 --- /dev/null +++ b/queue-6.12/iommu-s390-implement-blocking-domain.patch @@ -0,0 +1,263 @@ +From 76d6b57ec66b471b1d76b6b559033e4df018c458 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Tue, 10 Sep 2024 17:15:16 -0400 +Subject: iommu/s390: Implement blocking domain + +From: Matthew Rosato <mjrosato@linux.ibm.com> + +[ Upstream commit ecda483339a5151e3ca30d6b82691ef6f1d17912 ] + +This fixes a crash when surprise hot-unplugging a PCI device. This crash +happens because during hot-unplug __iommu_group_set_domain_nofail() +attaching the default domain fails when the platform no longer +recognizes the device as it has already been removed and we end up with +a NULL domain pointer and UAF. This is exactly the case referred to in +the second comment in __iommu_device_set_domain() and just as stated +there if we can instead attach the blocking domain the UAF is prevented +as this can handle the already removed device. Implement the blocking +domain to use this handling. With this change, the crash is fixed but +we still hit a warning attempting to change DMA ownership on a blocked +device. + +Fixes: c76c067e488c ("s390/pci: Use dma-iommu layer") +Co-developed-by: Niklas Schnelle <schnelle@linux.ibm.com> +Signed-off-by: Niklas Schnelle <schnelle@linux.ibm.com> +Signed-off-by: Matthew Rosato <mjrosato@linux.ibm.com> +Reviewed-by: Niklas Schnelle <schnelle@linux.ibm.com> +Reviewed-by: Jason Gunthorpe <jgg@nvidia.com> +Link: https://lore.kernel.org/r/20240910211516.137933-1-mjrosato@linux.ibm.com +Signed-off-by: Joerg Roedel <jroedel@suse.de> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + arch/s390/include/asm/pci.h | 4 +- + arch/s390/pci/pci.c | 3 ++ + arch/s390/pci/pci_debug.c | 10 ++++- + drivers/iommu/s390-iommu.c | 73 +++++++++++++++++++++++-------------- + 4 files changed, 59 insertions(+), 31 deletions(-) + +diff --git a/arch/s390/include/asm/pci.h b/arch/s390/include/asm/pci.h +index 9d920ced60475..30b20ce9a7003 100644 +--- a/arch/s390/include/asm/pci.h ++++ b/arch/s390/include/asm/pci.h +@@ -96,7 +96,6 @@ struct zpci_bar_struct { + u8 size; /* order 2 exponent */ + }; + +-struct s390_domain; + struct kvm_zdev; + + #define ZPCI_FUNCTIONS_PER_BUS 256 +@@ -181,9 +180,10 @@ struct zpci_dev { + struct dentry *debugfs_dev; + + /* IOMMU and passthrough */ +- struct s390_domain *s390_domain; /* s390 IOMMU domain data */ ++ struct iommu_domain *s390_domain; /* attached IOMMU domain */ + struct kvm_zdev *kzdev; + struct mutex kzdev_lock; ++ spinlock_t dom_lock; /* protect s390_domain change */ + }; + + static inline bool zdev_enabled(struct zpci_dev *zdev) +diff --git a/arch/s390/pci/pci.c b/arch/s390/pci/pci.c +index bd9624c20b802..be3299609f9b6 100644 +--- a/arch/s390/pci/pci.c ++++ b/arch/s390/pci/pci.c +@@ -160,6 +160,7 @@ int zpci_fmb_enable_device(struct zpci_dev *zdev) + u64 req = ZPCI_CREATE_REQ(zdev->fh, 0, ZPCI_MOD_FC_SET_MEASURE); + struct zpci_iommu_ctrs *ctrs; + struct zpci_fib fib = {0}; ++ unsigned long flags; + u8 cc, status; + + if (zdev->fmb || sizeof(*zdev->fmb) < zdev->fmb_length) +@@ -171,6 +172,7 @@ int zpci_fmb_enable_device(struct zpci_dev *zdev) + WARN_ON((u64) zdev->fmb & 0xf); + + /* reset software counters */ ++ spin_lock_irqsave(&zdev->dom_lock, flags); + ctrs = zpci_get_iommu_ctrs(zdev); + if (ctrs) { + atomic64_set(&ctrs->mapped_pages, 0); +@@ -179,6 +181,7 @@ int zpci_fmb_enable_device(struct zpci_dev *zdev) + atomic64_set(&ctrs->sync_map_rpcits, 0); + atomic64_set(&ctrs->sync_rpcits, 0); + } ++ spin_unlock_irqrestore(&zdev->dom_lock, flags); + + + fib.fmb_addr = virt_to_phys(zdev->fmb); +diff --git a/arch/s390/pci/pci_debug.c b/arch/s390/pci/pci_debug.c +index 2cb5043a997d5..38014206c16b9 100644 +--- a/arch/s390/pci/pci_debug.c ++++ b/arch/s390/pci/pci_debug.c +@@ -71,17 +71,23 @@ static void pci_fmb_show(struct seq_file *m, char *name[], int length, + + static void pci_sw_counter_show(struct seq_file *m) + { +- struct zpci_iommu_ctrs *ctrs = zpci_get_iommu_ctrs(m->private); ++ struct zpci_dev *zdev = m->private; ++ struct zpci_iommu_ctrs *ctrs; + atomic64_t *counter; ++ unsigned long flags; + int i; + ++ spin_lock_irqsave(&zdev->dom_lock, flags); ++ ctrs = zpci_get_iommu_ctrs(m->private); + if (!ctrs) +- return; ++ goto unlock; + + counter = &ctrs->mapped_pages; + for (i = 0; i < ARRAY_SIZE(pci_sw_names); i++, counter++) + seq_printf(m, "%26s:\t%llu\n", pci_sw_names[i], + atomic64_read(counter)); ++unlock: ++ spin_unlock_irqrestore(&zdev->dom_lock, flags); + } + + static int pci_perf_show(struct seq_file *m, void *v) +diff --git a/drivers/iommu/s390-iommu.c b/drivers/iommu/s390-iommu.c +index d8eaa7ea380bb..fbdeded3d48b5 100644 +--- a/drivers/iommu/s390-iommu.c ++++ b/drivers/iommu/s390-iommu.c +@@ -33,6 +33,8 @@ struct s390_domain { + struct rcu_head rcu; + }; + ++static struct iommu_domain blocking_domain; ++ + static inline unsigned int calc_rtx(dma_addr_t ptr) + { + return ((unsigned long)ptr >> ZPCI_RT_SHIFT) & ZPCI_INDEX_MASK; +@@ -369,20 +371,36 @@ static void s390_domain_free(struct iommu_domain *domain) + call_rcu(&s390_domain->rcu, s390_iommu_rcu_free_domain); + } + +-static void s390_iommu_detach_device(struct iommu_domain *domain, +- struct device *dev) ++static void zdev_s390_domain_update(struct zpci_dev *zdev, ++ struct iommu_domain *domain) ++{ ++ unsigned long flags; ++ ++ spin_lock_irqsave(&zdev->dom_lock, flags); ++ zdev->s390_domain = domain; ++ spin_unlock_irqrestore(&zdev->dom_lock, flags); ++} ++ ++static int blocking_domain_attach_device(struct iommu_domain *domain, ++ struct device *dev) + { +- struct s390_domain *s390_domain = to_s390_domain(domain); + struct zpci_dev *zdev = to_zpci_dev(dev); ++ struct s390_domain *s390_domain; + unsigned long flags; + ++ if (zdev->s390_domain->type == IOMMU_DOMAIN_BLOCKED) ++ return 0; ++ ++ s390_domain = to_s390_domain(zdev->s390_domain); + spin_lock_irqsave(&s390_domain->list_lock, flags); + list_del_rcu(&zdev->iommu_list); + spin_unlock_irqrestore(&s390_domain->list_lock, flags); + + zpci_unregister_ioat(zdev, 0); +- zdev->s390_domain = NULL; + zdev->dma_table = NULL; ++ zdev_s390_domain_update(zdev, domain); ++ ++ return 0; + } + + static int s390_iommu_attach_device(struct iommu_domain *domain, +@@ -401,20 +419,15 @@ static int s390_iommu_attach_device(struct iommu_domain *domain, + domain->geometry.aperture_end < zdev->start_dma)) + return -EINVAL; + +- if (zdev->s390_domain) +- s390_iommu_detach_device(&zdev->s390_domain->domain, dev); ++ blocking_domain_attach_device(&blocking_domain, dev); + ++ /* If we fail now DMA remains blocked via blocking domain */ + cc = zpci_register_ioat(zdev, 0, zdev->start_dma, zdev->end_dma, + virt_to_phys(s390_domain->dma_table), &status); +- /* +- * If the device is undergoing error recovery the reset code +- * will re-establish the new domain. +- */ + if (cc && status != ZPCI_PCI_ST_FUNC_NOT_AVAIL) + return -EIO; +- + zdev->dma_table = s390_domain->dma_table; +- zdev->s390_domain = s390_domain; ++ zdev_s390_domain_update(zdev, domain); + + spin_lock_irqsave(&s390_domain->list_lock, flags); + list_add_rcu(&zdev->iommu_list, &s390_domain->devices); +@@ -466,19 +479,11 @@ static struct iommu_device *s390_iommu_probe_device(struct device *dev) + if (zdev->tlb_refresh) + dev->iommu->shadow_on_flush = 1; + +- return &zdev->iommu_dev; +-} ++ /* Start with DMA blocked */ ++ spin_lock_init(&zdev->dom_lock); ++ zdev_s390_domain_update(zdev, &blocking_domain); + +-static void s390_iommu_release_device(struct device *dev) +-{ +- struct zpci_dev *zdev = to_zpci_dev(dev); +- +- /* +- * release_device is expected to detach any domain currently attached +- * to the device, but keep it attached to other devices in the group. +- */ +- if (zdev) +- s390_iommu_detach_device(&zdev->s390_domain->domain, dev); ++ return &zdev->iommu_dev; + } + + static int zpci_refresh_all(struct zpci_dev *zdev) +@@ -697,9 +702,15 @@ static size_t s390_iommu_unmap_pages(struct iommu_domain *domain, + + struct zpci_iommu_ctrs *zpci_get_iommu_ctrs(struct zpci_dev *zdev) + { +- if (!zdev || !zdev->s390_domain) ++ struct s390_domain *s390_domain; ++ ++ lockdep_assert_held(&zdev->dom_lock); ++ ++ if (zdev->s390_domain->type == IOMMU_DOMAIN_BLOCKED) + return NULL; +- return &zdev->s390_domain->ctrs; ++ ++ s390_domain = to_s390_domain(zdev->s390_domain); ++ return &s390_domain->ctrs; + } + + int zpci_init_iommu(struct zpci_dev *zdev) +@@ -776,11 +787,19 @@ static int __init s390_iommu_init(void) + } + subsys_initcall(s390_iommu_init); + ++static struct iommu_domain blocking_domain = { ++ .type = IOMMU_DOMAIN_BLOCKED, ++ .ops = &(const struct iommu_domain_ops) { ++ .attach_dev = blocking_domain_attach_device, ++ } ++}; ++ + static const struct iommu_ops s390_iommu_ops = { ++ .blocked_domain = &blocking_domain, ++ .release_domain = &blocking_domain, + .capable = s390_iommu_capable, + .domain_alloc_paging = s390_domain_alloc_paging, + .probe_device = s390_iommu_probe_device, +- .release_device = s390_iommu_release_device, + .device_group = generic_device_group, + .pgsize_bitmap = SZ_4K, + .get_resv_regions = s390_iommu_get_resv_regions, +-- +2.43.0 + diff --git a/queue-6.12/iommu-tegra241-cmdqv-fix-alignment-failure-at-max_n_.patch b/queue-6.12/iommu-tegra241-cmdqv-fix-alignment-failure-at-max_n_.patch new file mode 100644 index 00000000000..ee217c48b9c --- /dev/null +++ b/queue-6.12/iommu-tegra241-cmdqv-fix-alignment-failure-at-max_n_.patch @@ -0,0 +1,46 @@ +From 439e0748ea1ff5b892d4c7101e8483465650f4fa Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Sun, 10 Nov 2024 19:02:26 -0800 +Subject: iommu/tegra241-cmdqv: Fix alignment failure at max_n_shift + +From: Nicolin Chen <nicolinc@nvidia.com> + +[ Upstream commit a3799717b881aa0f4e722afb70e7b8ba84ae4f36 ] + +When configuring a kernel with PAGE_SIZE=4KB, depending on its setting of +CONFIG_CMA_ALIGNMENT, VCMDQ_LOG2SIZE_MAX=19 could fail the alignment test +and trigger a WARN_ON: + WARNING: at drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c:3646 + Call trace: + arm_smmu_init_one_queue+0x15c/0x210 + tegra241_cmdqv_init_structures+0x114/0x338 + arm_smmu_device_probe+0xb48/0x1d90 + +Fix it by capping max_n_shift to CMDQ_MAX_SZ_SHIFT as SMMUv3 CMDQ does. + +Fixes: 918eb5c856f6 ("iommu/arm-smmu-v3: Add in-kernel support for NVIDIA Tegra241 (Grace) CMDQV") +Signed-off-by: Nicolin Chen <nicolinc@nvidia.com> +Link: https://lore.kernel.org/r/20241111030226.1940737-1-nicolinc@nvidia.com +Signed-off-by: Will Deacon <will@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/iommu/arm/arm-smmu-v3/tegra241-cmdqv.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/iommu/arm/arm-smmu-v3/tegra241-cmdqv.c b/drivers/iommu/arm/arm-smmu-v3/tegra241-cmdqv.c +index a243c543598ce..6b479592140c4 100644 +--- a/drivers/iommu/arm/arm-smmu-v3/tegra241-cmdqv.c ++++ b/drivers/iommu/arm/arm-smmu-v3/tegra241-cmdqv.c +@@ -509,7 +509,8 @@ static int tegra241_vcmdq_alloc_smmu_cmdq(struct tegra241_vcmdq *vcmdq) + + snprintf(name, 16, "vcmdq%u", vcmdq->idx); + +- q->llq.max_n_shift = VCMDQ_LOG2SIZE_MAX; ++ /* Queue size, capped to ensure natural alignment */ ++ q->llq.max_n_shift = min_t(u32, CMDQ_MAX_SZ_SHIFT, VCMDQ_LOG2SIZE_MAX); + + /* Use the common helper to init the VCMDQ, and then... */ + ret = arm_smmu_init_one_queue(smmu, q, vcmdq->page0, +-- +2.43.0 + diff --git a/queue-6.12/iommu-tegra241-cmdqv-staticize-cmdqv_debugfs_dir.patch b/queue-6.12/iommu-tegra241-cmdqv-staticize-cmdqv_debugfs_dir.patch new file mode 100644 index 00000000000..fe3c0720e80 --- /dev/null +++ b/queue-6.12/iommu-tegra241-cmdqv-staticize-cmdqv_debugfs_dir.patch @@ -0,0 +1,39 @@ +From 3c023d4d6befc3784d7dcaf69b95badceaccaee1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Mon, 21 Oct 2024 16:08:46 -0700 +Subject: iommu/tegra241-cmdqv: Staticize cmdqv_debugfs_dir + +From: Nicolin Chen <nicolinc@nvidia.com> + +[ Upstream commit 89edbe88db2857880b08ce363a2695eec657f51b ] + +Fix a sparse warning. + +Fixes: 918eb5c856f6 ("iommu/arm-smmu-v3: Add in-kernel support for NVIDIA Tegra241 (Grace) CMDQV") +Reported-by: kernel test robot <lkp@intel.com> +Closes: https://lore.kernel.org/oe-kbuild-all/202410172003.bRQEReTc-lkp@intel.com/ +Signed-off-by: Nicolin Chen <nicolinc@nvidia.com> +Reviewed-by: Jason Gunthorpe <jgg@nvidia.com> +Link: https://lore.kernel.org/r/20241021230847.811218-1-nicolinc@nvidia.com +Signed-off-by: Will Deacon <will@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/iommu/arm/arm-smmu-v3/tegra241-cmdqv.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/iommu/arm/arm-smmu-v3/tegra241-cmdqv.c b/drivers/iommu/arm/arm-smmu-v3/tegra241-cmdqv.c +index fcd13d301fff6..a243c543598ce 100644 +--- a/drivers/iommu/arm/arm-smmu-v3/tegra241-cmdqv.c ++++ b/drivers/iommu/arm/arm-smmu-v3/tegra241-cmdqv.c +@@ -800,7 +800,7 @@ static int tegra241_cmdqv_init_structures(struct arm_smmu_device *smmu) + return 0; + } + +-struct dentry *cmdqv_debugfs_dir; ++static struct dentry *cmdqv_debugfs_dir; + + static struct arm_smmu_device * + __tegra241_cmdqv_probe(struct arm_smmu_device *smmu, struct resource *res, +-- +2.43.0 + diff --git a/queue-6.12/iommu-vt-d-fix-checks-and-print-in-dmar_fault_dump_p.patch b/queue-6.12/iommu-vt-d-fix-checks-and-print-in-dmar_fault_dump_p.patch new file mode 100644 index 00000000000..6d38f7c205a --- /dev/null +++ b/queue-6.12/iommu-vt-d-fix-checks-and-print-in-dmar_fault_dump_p.patch @@ -0,0 +1,131 @@ +From 66b0b4c531c61273ae7daea0e354fe2fa6057448 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Mon, 4 Nov 2024 09:40:32 +0800 +Subject: iommu/vt-d: Fix checks and print in dmar_fault_dump_ptes() + +From: Zhenzhong Duan <zhenzhong.duan@intel.com> + +[ Upstream commit 6ceb93f952f6ca34823ce3650c902c31b8385b40 ] + +There are some issues in dmar_fault_dump_ptes(): + +1. return value of phys_to_virt() is used for checking if an entry is + present. +2. dump is confusing, e.g., "pasid table entry is not present", confusing + by unpresent pasid table vs. unpresent pasid table entry. Current code + means the former. +3. pgtable_walk() is called without checking if page table is present. + +Fix 1 by checking present bit of an entry before dump a lower level entry. +Fix 2 by removing "entry" string, e.g., "pasid table is not present". +Fix 3 by checking page table present before walk. + +Take issue 3 for example, before fix: + +[ 442.240357] DMAR: pasid dir entry: 0x000000012c83e001 +[ 442.246661] DMAR: pasid table entry[0]: 0x0000000000000000 +[ 442.253429] DMAR: pasid table entry[1]: 0x0000000000000000 +[ 442.260203] DMAR: pasid table entry[2]: 0x0000000000000000 +[ 442.266969] DMAR: pasid table entry[3]: 0x0000000000000000 +[ 442.273733] DMAR: pasid table entry[4]: 0x0000000000000000 +[ 442.280479] DMAR: pasid table entry[5]: 0x0000000000000000 +[ 442.287234] DMAR: pasid table entry[6]: 0x0000000000000000 +[ 442.293989] DMAR: pasid table entry[7]: 0x0000000000000000 +[ 442.300742] DMAR: PTE not present at level 2 + +After fix: +... +[ 357.241214] DMAR: pasid table entry[6]: 0x0000000000000000 +[ 357.248022] DMAR: pasid table entry[7]: 0x0000000000000000 +[ 357.254824] DMAR: scalable mode page table is not present + +Fixes: 914ff7719e8a ("iommu/vt-d: Dump DMAR translation structure when DMA fault occurs") +Signed-off-by: Zhenzhong Duan <zhenzhong.duan@intel.com> +Link: https://lore.kernel.org/r/20241024092146.715063-2-zhenzhong.duan@intel.com +Signed-off-by: Lu Baolu <baolu.lu@linux.intel.com> +Signed-off-by: Joerg Roedel <jroedel@suse.de> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/iommu/intel/iommu.c | 29 ++++++++++++++++++++--------- + 1 file changed, 20 insertions(+), 9 deletions(-) + +diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c +index e860bc9439a28..29c4a3bf3acd0 100644 +--- a/drivers/iommu/intel/iommu.c ++++ b/drivers/iommu/intel/iommu.c +@@ -737,11 +737,11 @@ void dmar_fault_dump_ptes(struct intel_iommu *iommu, u16 source_id, + pr_info("Dump %s table entries for IOVA 0x%llx\n", iommu->name, addr); + + /* root entry dump */ +- rt_entry = &iommu->root_entry[bus]; +- if (!rt_entry) { +- pr_info("root table entry is not present\n"); ++ if (!iommu->root_entry) { ++ pr_info("root table is not present\n"); + return; + } ++ rt_entry = &iommu->root_entry[bus]; + + if (sm_supported(iommu)) + pr_info("scalable mode root entry: hi 0x%016llx, low 0x%016llx\n", +@@ -752,7 +752,7 @@ void dmar_fault_dump_ptes(struct intel_iommu *iommu, u16 source_id, + /* context entry dump */ + ctx_entry = iommu_context_addr(iommu, bus, devfn, 0); + if (!ctx_entry) { +- pr_info("context table entry is not present\n"); ++ pr_info("context table is not present\n"); + return; + } + +@@ -761,17 +761,23 @@ void dmar_fault_dump_ptes(struct intel_iommu *iommu, u16 source_id, + + /* legacy mode does not require PASID entries */ + if (!sm_supported(iommu)) { ++ if (!context_present(ctx_entry)) { ++ pr_info("legacy mode page table is not present\n"); ++ return; ++ } + level = agaw_to_level(ctx_entry->hi & 7); + pgtable = phys_to_virt(ctx_entry->lo & VTD_PAGE_MASK); + goto pgtable_walk; + } + +- /* get the pointer to pasid directory entry */ +- dir = phys_to_virt(ctx_entry->lo & VTD_PAGE_MASK); +- if (!dir) { +- pr_info("pasid directory entry is not present\n"); ++ if (!context_present(ctx_entry)) { ++ pr_info("pasid directory table is not present\n"); + return; + } ++ ++ /* get the pointer to pasid directory entry */ ++ dir = phys_to_virt(ctx_entry->lo & VTD_PAGE_MASK); ++ + /* For request-without-pasid, get the pasid from context entry */ + if (intel_iommu_sm && pasid == IOMMU_PASID_INVALID) + pasid = IOMMU_NO_PASID; +@@ -783,7 +789,7 @@ void dmar_fault_dump_ptes(struct intel_iommu *iommu, u16 source_id, + /* get the pointer to the pasid table entry */ + entries = get_pasid_table_from_pde(pde); + if (!entries) { +- pr_info("pasid table entry is not present\n"); ++ pr_info("pasid table is not present\n"); + return; + } + index = pasid & PASID_PTE_MASK; +@@ -791,6 +797,11 @@ void dmar_fault_dump_ptes(struct intel_iommu *iommu, u16 source_id, + for (i = 0; i < ARRAY_SIZE(pte->val); i++) + pr_info("pasid table entry[%d]: 0x%016llx\n", i, pte->val[i]); + ++ if (!pasid_pte_is_present(pte)) { ++ pr_info("scalable mode page table is not present\n"); ++ return; ++ } ++ + if (pasid_pte_get_pgtt(pte) == PASID_ENTRY_PGTT_FL_ONLY) { + level = pte->val[2] & BIT_ULL(2) ? 5 : 4; + pgtable = phys_to_virt(pte->val[2] & VTD_PAGE_MASK); +-- +2.43.0 + diff --git a/queue-6.12/iommu-vt-d-fix-checks-and-print-in-pgtable_walk.patch b/queue-6.12/iommu-vt-d-fix-checks-and-print-in-pgtable_walk.patch new file mode 100644 index 00000000000..7d49d49f53b --- /dev/null +++ b/queue-6.12/iommu-vt-d-fix-checks-and-print-in-pgtable_walk.patch @@ -0,0 +1,62 @@ +From a848be4cafee63649367a8b634ec3743cd8cda58 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Mon, 4 Nov 2024 09:40:33 +0800 +Subject: iommu/vt-d: Fix checks and print in pgtable_walk() + +From: Zhenzhong Duan <zhenzhong.duan@intel.com> + +[ Upstream commit f1645676f25d2c846798f0233c3a953efd62aafb ] + +There are some issues in pgtable_walk(): + +1. Super page is dumped as non-present page +2. dma_pte_superpage() should not check against leaf page table entries +3. Pointer pte is never NULL so checking it is meaningless +4. When an entry is not present, it still makes sense to dump the entry + content. + +Fix 1,2 by checking dma_pte_superpage()'s returned value after level check. +Fix 3 by removing pte check. +Fix 4 by checking present bit after printing. + +By this chance, change to print "page table not present" instead of "PTE +not present" to be clearer. + +Fixes: 914ff7719e8a ("iommu/vt-d: Dump DMAR translation structure when DMA fault occurs") +Signed-off-by: Zhenzhong Duan <zhenzhong.duan@intel.com> +Link: https://lore.kernel.org/r/20241024092146.715063-3-zhenzhong.duan@intel.com +Signed-off-by: Lu Baolu <baolu.lu@linux.intel.com> +Signed-off-by: Joerg Roedel <jroedel@suse.de> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/iommu/intel/iommu.c | 11 ++++++----- + 1 file changed, 6 insertions(+), 5 deletions(-) + +diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c +index 29c4a3bf3acd0..a167d59101ae2 100644 +--- a/drivers/iommu/intel/iommu.c ++++ b/drivers/iommu/intel/iommu.c +@@ -707,14 +707,15 @@ static void pgtable_walk(struct intel_iommu *iommu, unsigned long pfn, + while (1) { + offset = pfn_level_offset(pfn, level); + pte = &parent[offset]; +- if (!pte || (dma_pte_superpage(pte) || !dma_pte_present(pte))) { +- pr_info("PTE not present at level %d\n", level); +- break; +- } + + pr_info("pte level: %d, pte value: 0x%016llx\n", level, pte->val); + +- if (level == 1) ++ if (!dma_pte_present(pte)) { ++ pr_info("page table not present at level %d\n", level - 1); ++ break; ++ } ++ ++ if (level == 1 || dma_pte_superpage(pte)) + break; + + parent = phys_to_virt(dma_pte_addr(pte)); +-- +2.43.0 + diff --git a/queue-6.12/ip6mr-fix-tables-suspicious-rcu-usage.patch b/queue-6.12/ip6mr-fix-tables-suspicious-rcu-usage.patch new file mode 100644 index 00000000000..0eea8b39132 --- /dev/null +++ b/queue-6.12/ip6mr-fix-tables-suspicious-rcu-usage.patch @@ -0,0 +1,140 @@ +From 4ff75c1178e42e3632d133f6ed2460850a531149 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Sun, 24 Nov 2024 16:40:57 +0100 +Subject: ip6mr: fix tables suspicious RCU usage + +From: Paolo Abeni <pabeni@redhat.com> + +[ Upstream commit f1553c9894b4dbeb10a2ab15ab1aa113b3b4047c ] + +Several places call ip6mr_get_table() with no RCU nor RTNL lock. +Add RCU protection inside such helper and provide a lockless variant +for the few callers that already acquired the relevant lock. + +Note that some users additionally reference the table outside the RCU +lock. That is actually safe as the table deletion can happen only +after all table accesses are completed. + +Fixes: e2d57766e674 ("net: Provide compat support for SIOCGETMIFCNT_IN6 and SIOCGETSGCNT_IN6.") +Fixes: d7c31cbde4bc ("net: ip6mr: add RTM_GETROUTE netlink op") +Reviewed-by: David Ahern <dsahern@kernel.org> +Signed-off-by: Paolo Abeni <pabeni@redhat.com> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + net/ipv6/ip6mr.c | 38 +++++++++++++++++++++++++++----------- + 1 file changed, 27 insertions(+), 11 deletions(-) + +diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c +index 2ce4ae0d8dc3b..d5057401701c1 100644 +--- a/net/ipv6/ip6mr.c ++++ b/net/ipv6/ip6mr.c +@@ -125,7 +125,7 @@ static struct mr_table *ip6mr_mr_table_iter(struct net *net, + return ret; + } + +-static struct mr_table *ip6mr_get_table(struct net *net, u32 id) ++static struct mr_table *__ip6mr_get_table(struct net *net, u32 id) + { + struct mr_table *mrt; + +@@ -136,6 +136,16 @@ static struct mr_table *ip6mr_get_table(struct net *net, u32 id) + return NULL; + } + ++static struct mr_table *ip6mr_get_table(struct net *net, u32 id) ++{ ++ struct mr_table *mrt; ++ ++ rcu_read_lock(); ++ mrt = __ip6mr_get_table(net, id); ++ rcu_read_unlock(); ++ return mrt; ++} ++ + static int ip6mr_fib_lookup(struct net *net, struct flowi6 *flp6, + struct mr_table **mrt) + { +@@ -177,7 +187,7 @@ static int ip6mr_rule_action(struct fib_rule *rule, struct flowi *flp, + + arg->table = fib_rule_get_table(rule, arg); + +- mrt = ip6mr_get_table(rule->fr_net, arg->table); ++ mrt = __ip6mr_get_table(rule->fr_net, arg->table); + if (!mrt) + return -EAGAIN; + res->mrt = mrt; +@@ -304,6 +314,8 @@ static struct mr_table *ip6mr_get_table(struct net *net, u32 id) + return net->ipv6.mrt6; + } + ++#define __ip6mr_get_table ip6mr_get_table ++ + static int ip6mr_fib_lookup(struct net *net, struct flowi6 *flp6, + struct mr_table **mrt) + { +@@ -382,7 +394,7 @@ static struct mr_table *ip6mr_new_table(struct net *net, u32 id) + { + struct mr_table *mrt; + +- mrt = ip6mr_get_table(net, id); ++ mrt = __ip6mr_get_table(net, id); + if (mrt) + return mrt; + +@@ -411,13 +423,15 @@ static void *ip6mr_vif_seq_start(struct seq_file *seq, loff_t *pos) + struct net *net = seq_file_net(seq); + struct mr_table *mrt; + +- mrt = ip6mr_get_table(net, RT6_TABLE_DFLT); +- if (!mrt) ++ rcu_read_lock(); ++ mrt = __ip6mr_get_table(net, RT6_TABLE_DFLT); ++ if (!mrt) { ++ rcu_read_unlock(); + return ERR_PTR(-ENOENT); ++ } + + iter->mrt = mrt; + +- rcu_read_lock(); + return mr_vif_seq_start(seq, pos); + } + +@@ -2275,11 +2289,13 @@ int ip6mr_get_route(struct net *net, struct sk_buff *skb, struct rtmsg *rtm, + struct mfc6_cache *cache; + struct rt6_info *rt = dst_rt6_info(skb_dst(skb)); + +- mrt = ip6mr_get_table(net, RT6_TABLE_DFLT); +- if (!mrt) ++ rcu_read_lock(); ++ mrt = __ip6mr_get_table(net, RT6_TABLE_DFLT); ++ if (!mrt) { ++ rcu_read_unlock(); + return -ENOENT; ++ } + +- rcu_read_lock(); + cache = ip6mr_cache_find(mrt, &rt->rt6i_src.addr, &rt->rt6i_dst.addr); + if (!cache && skb->dev) { + int vif = ip6mr_find_vif(mrt, skb->dev); +@@ -2559,7 +2575,7 @@ static int ip6mr_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh, + grp = nla_get_in6_addr(tb[RTA_DST]); + tableid = tb[RTA_TABLE] ? nla_get_u32(tb[RTA_TABLE]) : 0; + +- mrt = ip6mr_get_table(net, tableid ?: RT_TABLE_DEFAULT); ++ mrt = __ip6mr_get_table(net, tableid ?: RT_TABLE_DEFAULT); + if (!mrt) { + NL_SET_ERR_MSG_MOD(extack, "MR table does not exist"); + return -ENOENT; +@@ -2606,7 +2622,7 @@ static int ip6mr_rtm_dumproute(struct sk_buff *skb, struct netlink_callback *cb) + if (filter.table_id) { + struct mr_table *mrt; + +- mrt = ip6mr_get_table(sock_net(skb->sk), filter.table_id); ++ mrt = __ip6mr_get_table(sock_net(skb->sk), filter.table_id); + if (!mrt) { + if (rtnl_msg_family(cb->nlh) != RTNL_FAMILY_IP6MR) + return skb->len; +-- +2.43.0 + diff --git a/queue-6.12/ipmr-fix-tables-suspicious-rcu-usage.patch b/queue-6.12/ipmr-fix-tables-suspicious-rcu-usage.patch new file mode 100644 index 00000000000..5069d985b7c --- /dev/null +++ b/queue-6.12/ipmr-fix-tables-suspicious-rcu-usage.patch @@ -0,0 +1,154 @@ +From 30bc95b8015387ca3748afe19d8009d87ec5a9d2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Sun, 24 Nov 2024 16:40:58 +0100 +Subject: ipmr: fix tables suspicious RCU usage + +From: Paolo Abeni <pabeni@redhat.com> + +[ Upstream commit fc9c273d6daaa9866f349bbe8cae25c67764c456 ] + +Similar to the previous patch, plumb the RCU lock inside +the ipmr_get_table(), provided a lockless variant and apply +the latter in the few spots were the lock is already held. + +Fixes: 709b46e8d90b ("net: Add compat ioctl support for the ipv4 multicast ioctl SIOCGETSGCNT") +Fixes: f0ad0860d01e ("ipv4: ipmr: support multiple tables") +Reviewed-by: David Ahern <dsahern@kernel.org> +Signed-off-by: Paolo Abeni <pabeni@redhat.com> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + net/ipv4/ipmr.c | 42 +++++++++++++++++++++++++++++------------- + 1 file changed, 29 insertions(+), 13 deletions(-) + +diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c +index 089864c6a35ee..449a2ac40bdc0 100644 +--- a/net/ipv4/ipmr.c ++++ b/net/ipv4/ipmr.c +@@ -137,7 +137,7 @@ static struct mr_table *ipmr_mr_table_iter(struct net *net, + return ret; + } + +-static struct mr_table *ipmr_get_table(struct net *net, u32 id) ++static struct mr_table *__ipmr_get_table(struct net *net, u32 id) + { + struct mr_table *mrt; + +@@ -148,6 +148,16 @@ static struct mr_table *ipmr_get_table(struct net *net, u32 id) + return NULL; + } + ++static struct mr_table *ipmr_get_table(struct net *net, u32 id) ++{ ++ struct mr_table *mrt; ++ ++ rcu_read_lock(); ++ mrt = __ipmr_get_table(net, id); ++ rcu_read_unlock(); ++ return mrt; ++} ++ + static int ipmr_fib_lookup(struct net *net, struct flowi4 *flp4, + struct mr_table **mrt) + { +@@ -189,7 +199,7 @@ static int ipmr_rule_action(struct fib_rule *rule, struct flowi *flp, + + arg->table = fib_rule_get_table(rule, arg); + +- mrt = ipmr_get_table(rule->fr_net, arg->table); ++ mrt = __ipmr_get_table(rule->fr_net, arg->table); + if (!mrt) + return -EAGAIN; + res->mrt = mrt; +@@ -315,6 +325,8 @@ static struct mr_table *ipmr_get_table(struct net *net, u32 id) + return net->ipv4.mrt; + } + ++#define __ipmr_get_table ipmr_get_table ++ + static int ipmr_fib_lookup(struct net *net, struct flowi4 *flp4, + struct mr_table **mrt) + { +@@ -403,7 +415,7 @@ static struct mr_table *ipmr_new_table(struct net *net, u32 id) + if (id != RT_TABLE_DEFAULT && id >= 1000000000) + return ERR_PTR(-EINVAL); + +- mrt = ipmr_get_table(net, id); ++ mrt = __ipmr_get_table(net, id); + if (mrt) + return mrt; + +@@ -1374,7 +1386,7 @@ int ip_mroute_setsockopt(struct sock *sk, int optname, sockptr_t optval, + goto out_unlock; + } + +- mrt = ipmr_get_table(net, raw_sk(sk)->ipmr_table ? : RT_TABLE_DEFAULT); ++ mrt = __ipmr_get_table(net, raw_sk(sk)->ipmr_table ? : RT_TABLE_DEFAULT); + if (!mrt) { + ret = -ENOENT; + goto out_unlock; +@@ -2262,11 +2274,13 @@ int ipmr_get_route(struct net *net, struct sk_buff *skb, + struct mr_table *mrt; + int err; + +- mrt = ipmr_get_table(net, RT_TABLE_DEFAULT); +- if (!mrt) ++ rcu_read_lock(); ++ mrt = __ipmr_get_table(net, RT_TABLE_DEFAULT); ++ if (!mrt) { ++ rcu_read_unlock(); + return -ENOENT; ++ } + +- rcu_read_lock(); + cache = ipmr_cache_find(mrt, saddr, daddr); + if (!cache && skb->dev) { + int vif = ipmr_find_vif(mrt, skb->dev); +@@ -2550,7 +2564,7 @@ static int ipmr_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh, + grp = tb[RTA_DST] ? nla_get_in_addr(tb[RTA_DST]) : 0; + tableid = tb[RTA_TABLE] ? nla_get_u32(tb[RTA_TABLE]) : 0; + +- mrt = ipmr_get_table(net, tableid ? tableid : RT_TABLE_DEFAULT); ++ mrt = __ipmr_get_table(net, tableid ? tableid : RT_TABLE_DEFAULT); + if (!mrt) { + err = -ENOENT; + goto errout_free; +@@ -2604,7 +2618,7 @@ static int ipmr_rtm_dumproute(struct sk_buff *skb, struct netlink_callback *cb) + if (filter.table_id) { + struct mr_table *mrt; + +- mrt = ipmr_get_table(sock_net(skb->sk), filter.table_id); ++ mrt = __ipmr_get_table(sock_net(skb->sk), filter.table_id); + if (!mrt) { + if (rtnl_msg_family(cb->nlh) != RTNL_FAMILY_IPMR) + return skb->len; +@@ -2712,7 +2726,7 @@ static int rtm_to_ipmr_mfcc(struct net *net, struct nlmsghdr *nlh, + break; + } + } +- mrt = ipmr_get_table(net, tblid); ++ mrt = __ipmr_get_table(net, tblid); + if (!mrt) { + ret = -ENOENT; + goto out; +@@ -2920,13 +2934,15 @@ static void *ipmr_vif_seq_start(struct seq_file *seq, loff_t *pos) + struct net *net = seq_file_net(seq); + struct mr_table *mrt; + +- mrt = ipmr_get_table(net, RT_TABLE_DEFAULT); +- if (!mrt) ++ rcu_read_lock(); ++ mrt = __ipmr_get_table(net, RT_TABLE_DEFAULT); ++ if (!mrt) { ++ rcu_read_unlock(); + return ERR_PTR(-ENOENT); ++ } + + iter->mrt = mrt; + +- rcu_read_lock(); + return mr_vif_seq_start(seq, pos); + } + +-- +2.43.0 + diff --git a/queue-6.12/ipv6-fix-soft-lockups-in-fib6_select_path-under-high.patch b/queue-6.12/ipv6-fix-soft-lockups-in-fib6_select_path-under-high.patch new file mode 100644 index 00000000000..53f9d8fa147 --- /dev/null +++ b/queue-6.12/ipv6-fix-soft-lockups-in-fib6_select_path-under-high.patch @@ -0,0 +1,536 @@ +From eee1f2250783f29238384214b785f0da204fdebb Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Tue, 5 Nov 2024 17:02:36 -0800 +Subject: ipv6: Fix soft lockups in fib6_select_path under high next hop churn +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Omid Ehtemam-Haghighi <omid.ehtemamhaghighi@menlosecurity.com> + +[ Upstream commit d9ccb18f83ea2bb654289b6ecf014fd267cc988b ] + +Soft lockups have been observed on a cluster of Linux-based edge routers +located in a highly dynamic environment. Using the `bird` service, these +routers continuously update BGP-advertised routes due to frequently +changing nexthop destinations, while also managing significant IPv6 +traffic. The lockups occur during the traversal of the multipath +circular linked-list in the `fib6_select_path` function, particularly +while iterating through the siblings in the list. The issue typically +arises when the nodes of the linked list are unexpectedly deleted +concurrently on a different core—indicated by their 'next' and +'previous' elements pointing back to the node itself and their reference +count dropping to zero. This results in an infinite loop, leading to a +soft lockup that triggers a system panic via the watchdog timer. + +Apply RCU primitives in the problematic code sections to resolve the +issue. Where necessary, update the references to fib6_siblings to +annotate or use the RCU APIs. + +Include a test script that reproduces the issue. The script +periodically updates the routing table while generating a heavy load +of outgoing IPv6 traffic through multiple iperf3 clients. It +consistently induces infinite soft lockups within a couple of minutes. + +Kernel log: + + 0 [ffffbd13003e8d30] machine_kexec at ffffffff8ceaf3eb + 1 [ffffbd13003e8d90] __crash_kexec at ffffffff8d0120e3 + 2 [ffffbd13003e8e58] panic at ffffffff8cef65d4 + 3 [ffffbd13003e8ed8] watchdog_timer_fn at ffffffff8d05cb03 + 4 [ffffbd13003e8f08] __hrtimer_run_queues at ffffffff8cfec62f + 5 [ffffbd13003e8f70] hrtimer_interrupt at ffffffff8cfed756 + 6 [ffffbd13003e8fd0] __sysvec_apic_timer_interrupt at ffffffff8cea01af + 7 [ffffbd13003e8ff0] sysvec_apic_timer_interrupt at ffffffff8df1b83d +-- <IRQ stack> -- + 8 [ffffbd13003d3708] asm_sysvec_apic_timer_interrupt at ffffffff8e000ecb + [exception RIP: fib6_select_path+299] + RIP: ffffffff8ddafe7b RSP: ffffbd13003d37b8 RFLAGS: 00000287 + RAX: ffff975850b43600 RBX: ffff975850b40200 RCX: 0000000000000000 + RDX: 000000003fffffff RSI: 0000000051d383e4 RDI: ffff975850b43618 + RBP: ffffbd13003d3800 R8: 0000000000000000 R9: ffff975850b40200 + R10: 0000000000000000 R11: 0000000000000000 R12: ffffbd13003d3830 + R13: ffff975850b436a8 R14: ffff975850b43600 R15: 0000000000000007 + ORIG_RAX: ffffffffffffffff CS: 0010 SS: 0018 + 9 [ffffbd13003d3808] ip6_pol_route at ffffffff8ddb030c +10 [ffffbd13003d3888] ip6_pol_route_input at ffffffff8ddb068c +11 [ffffbd13003d3898] fib6_rule_lookup at ffffffff8ddf02b5 +12 [ffffbd13003d3928] ip6_route_input at ffffffff8ddb0f47 +13 [ffffbd13003d3a18] ip6_rcv_finish_core.constprop.0 at ffffffff8dd950d0 +14 [ffffbd13003d3a30] ip6_list_rcv_finish.constprop.0 at ffffffff8dd96274 +15 [ffffbd13003d3a98] ip6_sublist_rcv at ffffffff8dd96474 +16 [ffffbd13003d3af8] ipv6_list_rcv at ffffffff8dd96615 +17 [ffffbd13003d3b60] __netif_receive_skb_list_core at ffffffff8dc16fec +18 [ffffbd13003d3be0] netif_receive_skb_list_internal at ffffffff8dc176b3 +19 [ffffbd13003d3c50] napi_gro_receive at ffffffff8dc565b9 +20 [ffffbd13003d3c80] ice_receive_skb at ffffffffc087e4f5 [ice] +21 [ffffbd13003d3c90] ice_clean_rx_irq at ffffffffc0881b80 [ice] +22 [ffffbd13003d3d20] ice_napi_poll at ffffffffc088232f [ice] +23 [ffffbd13003d3d80] __napi_poll at ffffffff8dc18000 +24 [ffffbd13003d3db8] net_rx_action at ffffffff8dc18581 +25 [ffffbd13003d3e40] __do_softirq at ffffffff8df352e9 +26 [ffffbd13003d3eb0] run_ksoftirqd at ffffffff8ceffe47 +27 [ffffbd13003d3ec0] smpboot_thread_fn at ffffffff8cf36a30 +28 [ffffbd13003d3ee8] kthread at ffffffff8cf2b39f +29 [ffffbd13003d3f28] ret_from_fork at ffffffff8ce5fa64 +30 [ffffbd13003d3f50] ret_from_fork_asm at ffffffff8ce03cbb + +Fixes: 66f5d6ce53e6 ("ipv6: replace rwlock with rcu and spinlock in fib6_table") +Reported-by: Adrian Oliver <kernel@aoliver.ca> +Signed-off-by: Omid Ehtemam-Haghighi <omid.ehtemamhaghighi@menlosecurity.com> +Cc: Shuah Khan <shuah@kernel.org> +Cc: Ido Schimmel <idosch@idosch.org> +Cc: Kuniyuki Iwashima <kuniyu@amazon.com> +Cc: Simon Horman <horms@kernel.org> +Reviewed-by: David Ahern <dsahern@kernel.org> +Link: https://patch.msgid.link/20241106010236.1239299-1-omid.ehtemamhaghighi@menlosecurity.com +Signed-off-by: Jakub Kicinski <kuba@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + net/ipv6/ip6_fib.c | 8 +- + net/ipv6/route.c | 45 ++- + tools/testing/selftests/net/Makefile | 1 + + .../net/ipv6_route_update_soft_lockup.sh | 262 ++++++++++++++++++ + 4 files changed, 297 insertions(+), 19 deletions(-) + create mode 100755 tools/testing/selftests/net/ipv6_route_update_soft_lockup.sh + +diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c +index eb111d20615c6..9a1c59275a109 100644 +--- a/net/ipv6/ip6_fib.c ++++ b/net/ipv6/ip6_fib.c +@@ -1190,8 +1190,8 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct fib6_info *rt, + while (sibling) { + if (sibling->fib6_metric == rt->fib6_metric && + rt6_qualify_for_ecmp(sibling)) { +- list_add_tail(&rt->fib6_siblings, +- &sibling->fib6_siblings); ++ list_add_tail_rcu(&rt->fib6_siblings, ++ &sibling->fib6_siblings); + break; + } + sibling = rcu_dereference_protected(sibling->fib6_next, +@@ -1252,7 +1252,7 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct fib6_info *rt, + fib6_siblings) + sibling->fib6_nsiblings--; + rt->fib6_nsiblings = 0; +- list_del_init(&rt->fib6_siblings); ++ list_del_rcu(&rt->fib6_siblings); + rt6_multipath_rebalance(next_sibling); + return err; + } +@@ -1970,7 +1970,7 @@ static void fib6_del_route(struct fib6_table *table, struct fib6_node *fn, + &rt->fib6_siblings, fib6_siblings) + sibling->fib6_nsiblings--; + rt->fib6_nsiblings = 0; +- list_del_init(&rt->fib6_siblings); ++ list_del_rcu(&rt->fib6_siblings); + rt6_multipath_rebalance(next_sibling); + } + +diff --git a/net/ipv6/route.c b/net/ipv6/route.c +index 76bea6db59764..cff4fbbc66efb 100644 +--- a/net/ipv6/route.c ++++ b/net/ipv6/route.c +@@ -416,8 +416,8 @@ void fib6_select_path(const struct net *net, struct fib6_result *res, + struct flowi6 *fl6, int oif, bool have_oif_match, + const struct sk_buff *skb, int strict) + { +- struct fib6_info *sibling, *next_sibling; + struct fib6_info *match = res->f6i; ++ struct fib6_info *sibling; + + if (!match->nh && (!match->fib6_nsiblings || have_oif_match)) + goto out; +@@ -443,8 +443,8 @@ void fib6_select_path(const struct net *net, struct fib6_result *res, + if (fl6->mp_hash <= atomic_read(&match->fib6_nh->fib_nh_upper_bound)) + goto out; + +- list_for_each_entry_safe(sibling, next_sibling, &match->fib6_siblings, +- fib6_siblings) { ++ list_for_each_entry_rcu(sibling, &match->fib6_siblings, ++ fib6_siblings) { + const struct fib6_nh *nh = sibling->fib6_nh; + int nh_upper_bound; + +@@ -5195,14 +5195,18 @@ static void ip6_route_mpath_notify(struct fib6_info *rt, + * nexthop. Since sibling routes are always added at the end of + * the list, find the first sibling of the last route appended + */ ++ rcu_read_lock(); ++ + if ((nlflags & NLM_F_APPEND) && rt_last && rt_last->fib6_nsiblings) { +- rt = list_first_entry(&rt_last->fib6_siblings, +- struct fib6_info, +- fib6_siblings); ++ rt = list_first_or_null_rcu(&rt_last->fib6_siblings, ++ struct fib6_info, ++ fib6_siblings); + } + + if (rt) + inet6_rt_notify(RTM_NEWROUTE, rt, info, nlflags); ++ ++ rcu_read_unlock(); + } + + static bool ip6_route_mpath_should_notify(const struct fib6_info *rt) +@@ -5547,17 +5551,21 @@ static size_t rt6_nlmsg_size(struct fib6_info *f6i) + nexthop_for_each_fib6_nh(f6i->nh, rt6_nh_nlmsg_size, + &nexthop_len); + } else { +- struct fib6_info *sibling, *next_sibling; + struct fib6_nh *nh = f6i->fib6_nh; ++ struct fib6_info *sibling; + + nexthop_len = 0; + if (f6i->fib6_nsiblings) { + rt6_nh_nlmsg_size(nh, &nexthop_len); + +- list_for_each_entry_safe(sibling, next_sibling, +- &f6i->fib6_siblings, fib6_siblings) { ++ rcu_read_lock(); ++ ++ list_for_each_entry_rcu(sibling, &f6i->fib6_siblings, ++ fib6_siblings) { + rt6_nh_nlmsg_size(sibling->fib6_nh, &nexthop_len); + } ++ ++ rcu_read_unlock(); + } + nexthop_len += lwtunnel_get_encap_size(nh->fib_nh_lws); + } +@@ -5721,7 +5729,7 @@ static int rt6_fill_node(struct net *net, struct sk_buff *skb, + lwtunnel_fill_encap(skb, dst->lwtstate, RTA_ENCAP, RTA_ENCAP_TYPE) < 0) + goto nla_put_failure; + } else if (rt->fib6_nsiblings) { +- struct fib6_info *sibling, *next_sibling; ++ struct fib6_info *sibling; + struct nlattr *mp; + + mp = nla_nest_start_noflag(skb, RTA_MULTIPATH); +@@ -5733,14 +5741,21 @@ static int rt6_fill_node(struct net *net, struct sk_buff *skb, + 0) < 0) + goto nla_put_failure; + +- list_for_each_entry_safe(sibling, next_sibling, +- &rt->fib6_siblings, fib6_siblings) { ++ rcu_read_lock(); ++ ++ list_for_each_entry_rcu(sibling, &rt->fib6_siblings, ++ fib6_siblings) { + if (fib_add_nexthop(skb, &sibling->fib6_nh->nh_common, + sibling->fib6_nh->fib_nh_weight, +- AF_INET6, 0) < 0) ++ AF_INET6, 0) < 0) { ++ rcu_read_unlock(); ++ + goto nla_put_failure; ++ } + } + ++ rcu_read_unlock(); ++ + nla_nest_end(skb, mp); + } else if (rt->nh) { + if (nla_put_u32(skb, RTA_NH_ID, rt->nh->id)) +@@ -6177,7 +6192,7 @@ void inet6_rt_notify(int event, struct fib6_info *rt, struct nl_info *info, + err = -ENOBUFS; + seq = info->nlh ? info->nlh->nlmsg_seq : 0; + +- skb = nlmsg_new(rt6_nlmsg_size(rt), gfp_any()); ++ skb = nlmsg_new(rt6_nlmsg_size(rt), GFP_ATOMIC); + if (!skb) + goto errout; + +@@ -6190,7 +6205,7 @@ void inet6_rt_notify(int event, struct fib6_info *rt, struct nl_info *info, + goto errout; + } + rtnl_notify(skb, net, info->portid, RTNLGRP_IPV6_ROUTE, +- info->nlh, gfp_any()); ++ info->nlh, GFP_ATOMIC); + return; + errout: + rtnl_set_sk_err(net, RTNLGRP_IPV6_ROUTE, err); +diff --git a/tools/testing/selftests/net/Makefile b/tools/testing/selftests/net/Makefile +index 5e86f7a51b43c..2c4b6e404a7c7 100644 +--- a/tools/testing/selftests/net/Makefile ++++ b/tools/testing/selftests/net/Makefile +@@ -97,6 +97,7 @@ TEST_PROGS += fdb_flush.sh + TEST_PROGS += fq_band_pktlimit.sh + TEST_PROGS += vlan_hw_filter.sh + TEST_PROGS += bpf_offload.py ++TEST_PROGS += ipv6_route_update_soft_lockup.sh + + # YNL files, must be before "include ..lib.mk" + EXTRA_CLEAN += $(OUTPUT)/libynl.a +diff --git a/tools/testing/selftests/net/ipv6_route_update_soft_lockup.sh b/tools/testing/selftests/net/ipv6_route_update_soft_lockup.sh +new file mode 100755 +index 0000000000000..a6b2b1f9c641c +--- /dev/null ++++ b/tools/testing/selftests/net/ipv6_route_update_soft_lockup.sh +@@ -0,0 +1,262 @@ ++#!/bin/bash ++# SPDX-License-Identifier: GPL-2.0 ++# ++# Testing for potential kernel soft lockup during IPv6 routing table ++# refresh under heavy outgoing IPv6 traffic. If a kernel soft lockup ++# occurs, a kernel panic will be triggered to prevent associated issues. ++# ++# ++# Test Environment Layout ++# ++# ┌----------------┐ ┌----------------┐ ++# | SOURCE_NS | | SINK_NS | ++# | NAMESPACE | | NAMESPACE | ++# |(iperf3 clients)| |(iperf3 servers)| ++# | | | | ++# | | | | ++# | ┌-----------| nexthops |---------┐ | ++# | |veth_source|<--------------------------------------->|veth_sink|<┐ | ++# | └-----------|2001:0DB8:1::0:1/96 2001:0DB8:1::1:1/96 |---------┘ | | ++# | | ^ 2001:0DB8:1::1:2/96 | | | ++# | | . . | fwd | | ++# | ┌---------┐ | . . | | | ++# | | IPv6 | | . . | V | ++# | | routing | | . 2001:0DB8:1::1:80/96| ┌-----┐ | ++# | | table | | . | | lo | | ++# | | nexthop | | . └--------┴-----┴-┘ ++# | | update | | ............................> 2001:0DB8:2::1:1/128 ++# | └-------- ┘ | ++# └----------------┘ ++# ++# The test script sets up two network namespaces, source_ns and sink_ns, ++# connected via a veth link. Within source_ns, it continuously updates the ++# IPv6 routing table by flushing and inserting IPV6_NEXTHOP_ADDR_COUNT nexthop ++# IPs destined for SINK_LOOPBACK_IP_ADDR in sink_ns. This refresh occurs at a ++# rate of 1/ROUTING_TABLE_REFRESH_PERIOD per second for TEST_DURATION seconds. ++# ++# Simultaneously, multiple iperf3 clients within source_ns generate heavy ++# outgoing IPv6 traffic. Each client is assigned a unique port number starting ++# at 5000 and incrementing sequentially. Each client targets a unique iperf3 ++# server running in sink_ns, connected to the SINK_LOOPBACK_IFACE interface ++# using the same port number. ++# ++# The number of iperf3 servers and clients is set to half of the total ++# available cores on each machine. ++# ++# NOTE: We have tested this script on machines with various CPU specifications, ++# ranging from lower to higher performance as listed below. The test script ++# effectively triggered a kernel soft lockup on machines running an unpatched ++# kernel in under a minute: ++# ++# - 1x Intel Xeon E-2278G 8-Core Processor @ 3.40GHz ++# - 1x Intel Xeon E-2378G Processor 8-Core @ 2.80GHz ++# - 1x AMD EPYC 7401P 24-Core Processor @ 2.00GHz ++# - 1x AMD EPYC 7402P 24-Core Processor @ 2.80GHz ++# - 2x Intel Xeon Gold 5120 14-Core Processor @ 2.20GHz ++# - 1x Ampere Altra Q80-30 80-Core Processor @ 3.00GHz ++# - 2x Intel Xeon Gold 5120 14-Core Processor @ 2.20GHz ++# - 2x Intel Xeon Silver 4214 24-Core Processor @ 2.20GHz ++# - 1x AMD EPYC 7502P 32-Core @ 2.50GHz ++# - 1x Intel Xeon Gold 6314U 32-Core Processor @ 2.30GHz ++# - 2x Intel Xeon Gold 6338 32-Core Processor @ 2.00GHz ++# ++# On less performant machines, you may need to increase the TEST_DURATION ++# parameter to enhance the likelihood of encountering a race condition leading ++# to a kernel soft lockup and avoid a false negative result. ++# ++# NOTE: The test may not produce the expected result in virtualized ++# environments (e.g., qemu) due to differences in timing and CPU handling, ++# which can affect the conditions needed to trigger a soft lockup. ++ ++source lib.sh ++source net_helper.sh ++ ++TEST_DURATION=300 ++ROUTING_TABLE_REFRESH_PERIOD=0.01 ++ ++IPERF3_BITRATE="300m" ++ ++ ++IPV6_NEXTHOP_ADDR_COUNT="128" ++IPV6_NEXTHOP_ADDR_MASK="96" ++IPV6_NEXTHOP_PREFIX="2001:0DB8:1" ++ ++ ++SOURCE_TEST_IFACE="veth_source" ++SOURCE_TEST_IP_ADDR="2001:0DB8:1::0:1/96" ++ ++SINK_TEST_IFACE="veth_sink" ++# ${SINK_TEST_IFACE} is populated with the following range of IPv6 addresses: ++# 2001:0DB8:1::1:1 to 2001:0DB8:1::1:${IPV6_NEXTHOP_ADDR_COUNT} ++SINK_LOOPBACK_IFACE="lo" ++SINK_LOOPBACK_IP_MASK="128" ++SINK_LOOPBACK_IP_ADDR="2001:0DB8:2::1:1" ++ ++nexthop_ip_list="" ++termination_signal="" ++kernel_softlokup_panic_prev_val="" ++ ++terminate_ns_processes_by_pattern() { ++ local ns=$1 ++ local pattern=$2 ++ ++ for pid in $(ip netns pids ${ns}); do ++ [ -e /proc/$pid/cmdline ] && grep -qe "${pattern}" /proc/$pid/cmdline && kill -9 $pid ++ done ++} ++ ++cleanup() { ++ echo "info: cleaning up namespaces and terminating all processes within them..." ++ ++ ++ # Terminate iperf3 instances running in the source_ns. To avoid race ++ # conditions, first iterate over the PIDs and terminate those ++ # associated with the bash shells running the ++ # `while true; do iperf3 -c ...; done` loops. In a second iteration, ++ # terminate the individual `iperf3 -c ...` instances. ++ terminate_ns_processes_by_pattern ${source_ns} while ++ terminate_ns_processes_by_pattern ${source_ns} iperf3 ++ ++ # Repeat the same process for sink_ns ++ terminate_ns_processes_by_pattern ${sink_ns} while ++ terminate_ns_processes_by_pattern ${sink_ns} iperf3 ++ ++ # Check if any iperf3 instances are still running. This could happen ++ # if a core has entered an infinite loop and the timeout for detecting ++ # the soft lockup has not expired, but either the test interval has ++ # already elapsed or the test was terminated manually (e.g., with ^C) ++ for pid in $(ip netns pids ${source_ns}); do ++ if [ -e /proc/$pid/cmdline ] && grep -qe 'iperf3' /proc/$pid/cmdline; then ++ echo "FAIL: unable to terminate some iperf3 instances. Soft lockup is underway. A kernel panic is on the way!" ++ exit ${ksft_fail} ++ fi ++ done ++ ++ if [ "$termination_signal" == "SIGINT" ]; then ++ echo "SKIP: Termination due to ^C (SIGINT)" ++ elif [ "$termination_signal" == "SIGALRM" ]; then ++ echo "PASS: No kernel soft lockup occurred during this ${TEST_DURATION} second test" ++ fi ++ ++ cleanup_ns ${source_ns} ${sink_ns} ++ ++ sysctl -qw kernel.softlockup_panic=${kernel_softlokup_panic_prev_val} ++} ++ ++setup_prepare() { ++ setup_ns source_ns sink_ns ++ ++ ip -n ${source_ns} link add name ${SOURCE_TEST_IFACE} type veth peer name ${SINK_TEST_IFACE} netns ${sink_ns} ++ ++ # Setting up the Source namespace ++ ip -n ${source_ns} addr add ${SOURCE_TEST_IP_ADDR} dev ${SOURCE_TEST_IFACE} ++ ip -n ${source_ns} link set dev ${SOURCE_TEST_IFACE} qlen 10000 ++ ip -n ${source_ns} link set dev ${SOURCE_TEST_IFACE} up ++ ip netns exec ${source_ns} sysctl -qw net.ipv6.fib_multipath_hash_policy=1 ++ ++ # Setting up the Sink namespace ++ ip -n ${sink_ns} addr add ${SINK_LOOPBACK_IP_ADDR}/${SINK_LOOPBACK_IP_MASK} dev ${SINK_LOOPBACK_IFACE} ++ ip -n ${sink_ns} link set dev ${SINK_LOOPBACK_IFACE} up ++ ip netns exec ${sink_ns} sysctl -qw net.ipv6.conf.${SINK_LOOPBACK_IFACE}.forwarding=1 ++ ++ ip -n ${sink_ns} link set ${SINK_TEST_IFACE} up ++ ip netns exec ${sink_ns} sysctl -qw net.ipv6.conf.${SINK_TEST_IFACE}.forwarding=1 ++ ++ ++ # Populate nexthop IPv6 addresses on the test interface in the sink_ns ++ echo "info: populating ${IPV6_NEXTHOP_ADDR_COUNT} IPv6 addresses on the ${SINK_TEST_IFACE} interface ..." ++ for IP in $(seq 1 ${IPV6_NEXTHOP_ADDR_COUNT}); do ++ ip -n ${sink_ns} addr add ${IPV6_NEXTHOP_PREFIX}::$(printf "1:%x" "${IP}")/${IPV6_NEXTHOP_ADDR_MASK} dev ${SINK_TEST_IFACE}; ++ done ++ ++ # Preparing list of nexthops ++ for IP in $(seq 1 ${IPV6_NEXTHOP_ADDR_COUNT}); do ++ nexthop_ip_list=$nexthop_ip_list" nexthop via ${IPV6_NEXTHOP_PREFIX}::$(printf "1:%x" $IP) dev ${SOURCE_TEST_IFACE} weight 1" ++ done ++} ++ ++ ++test_soft_lockup_during_routing_table_refresh() { ++ # Start num_of_iperf_servers iperf3 servers in the sink_ns namespace, ++ # each listening on ports starting at 5001 and incrementing ++ # sequentially. Since iperf3 instances may terminate unexpectedly, a ++ # while loop is used to automatically restart them in such cases. ++ echo "info: starting ${num_of_iperf_servers} iperf3 servers in the sink_ns namespace ..." ++ for i in $(seq 1 ${num_of_iperf_servers}); do ++ cmd="iperf3 --bind ${SINK_LOOPBACK_IP_ADDR} -s -p $(printf '5%03d' ${i}) --rcv-timeout 200 &>/dev/null" ++ ip netns exec ${sink_ns} bash -c "while true; do ${cmd}; done &" &>/dev/null ++ done ++ ++ # Wait for the iperf3 servers to be ready ++ for i in $(seq ${num_of_iperf_servers}); do ++ port=$(printf '5%03d' ${i}); ++ wait_local_port_listen ${sink_ns} ${port} tcp ++ done ++ ++ # Continuously refresh the routing table in the background within ++ # the source_ns namespace ++ ip netns exec ${source_ns} bash -c " ++ while \$(ip netns list | grep -q ${source_ns}); do ++ ip -6 route add ${SINK_LOOPBACK_IP_ADDR}/${SINK_LOOPBACK_IP_MASK} ${nexthop_ip_list}; ++ sleep ${ROUTING_TABLE_REFRESH_PERIOD}; ++ ip -6 route delete ${SINK_LOOPBACK_IP_ADDR}/${SINK_LOOPBACK_IP_MASK}; ++ done &" ++ ++ # Start num_of_iperf_servers iperf3 clients in the source_ns namespace, ++ # each sending TCP traffic on sequential ports starting at 5001. ++ # Since iperf3 instances may terminate unexpectedly (e.g., if the route ++ # to the server is deleted in the background during a route refresh), a ++ # while loop is used to automatically restart them in such cases. ++ echo "info: starting ${num_of_iperf_servers} iperf3 clients in the source_ns namespace ..." ++ for i in $(seq 1 ${num_of_iperf_servers}); do ++ cmd="iperf3 -c ${SINK_LOOPBACK_IP_ADDR} -p $(printf '5%03d' ${i}) --length 64 --bitrate ${IPERF3_BITRATE} -t 0 --connect-timeout 150 &>/dev/null" ++ ip netns exec ${source_ns} bash -c "while true; do ${cmd}; done &" &>/dev/null ++ done ++ ++ echo "info: IPv6 routing table is being updated at the rate of $(echo "1/${ROUTING_TABLE_REFRESH_PERIOD}" | bc)/s for ${TEST_DURATION} seconds ..." ++ echo "info: A kernel soft lockup, if detected, results in a kernel panic!" ++ ++ wait ++} ++ ++# Make sure 'iperf3' is installed, skip the test otherwise ++if [ ! -x "$(command -v "iperf3")" ]; then ++ echo "SKIP: 'iperf3' is not installed. Skipping the test." ++ exit ${ksft_skip} ++fi ++ ++# Determine the number of cores on the machine ++num_of_iperf_servers=$(( $(nproc)/2 )) ++ ++# Check if we are running on a multi-core machine, skip the test otherwise ++if [ "${num_of_iperf_servers}" -eq 0 ]; then ++ echo "SKIP: This test is not valid on a single core machine!" ++ exit ${ksft_skip} ++fi ++ ++# Since the kernel soft lockup we're testing causes at least one core to enter ++# an infinite loop, destabilizing the host and likely affecting subsequent ++# tests, we trigger a kernel panic instead of reporting a failure and ++# continuing ++kernel_softlokup_panic_prev_val=$(sysctl -n kernel.softlockup_panic) ++sysctl -qw kernel.softlockup_panic=1 ++ ++handle_sigint() { ++ termination_signal="SIGINT" ++ cleanup ++ exit ${ksft_skip} ++} ++ ++handle_sigalrm() { ++ termination_signal="SIGALRM" ++ cleanup ++ exit ${ksft_pass} ++} ++ ++trap handle_sigint SIGINT ++trap handle_sigalrm SIGALRM ++ ++(sleep ${TEST_DURATION} && kill -s SIGALRM $$)& ++ ++setup_prepare ++test_soft_lockup_during_routing_table_refresh +-- +2.43.0 + diff --git a/queue-6.12/ipv6-release-nexthop-on-device-removal.patch b/queue-6.12/ipv6-release-nexthop-on-device-removal.patch new file mode 100644 index 00000000000..ba83a368b5d --- /dev/null +++ b/queue-6.12/ipv6-release-nexthop-on-device-removal.patch @@ -0,0 +1,99 @@ +From cc28f218d223f0b0f973aa5a824cd0855da37068 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Tue, 5 Nov 2024 19:23:50 +0100 +Subject: ipv6: release nexthop on device removal + +From: Paolo Abeni <pabeni@redhat.com> + +[ Upstream commit eb02688c5c45c3e7af7e71f036a7144f5639cbfe ] + +The CI is hitting some aperiodic hangup at device removal time in the +pmtu.sh self-test: + +unregister_netdevice: waiting for veth_A-R1 to become free. Usage count = 6 +ref_tracker: veth_A-R1@ffff888013df15d8 has 1/5 users at + dst_init+0x84/0x4a0 + dst_alloc+0x97/0x150 + ip6_dst_alloc+0x23/0x90 + ip6_rt_pcpu_alloc+0x1e6/0x520 + ip6_pol_route+0x56f/0x840 + fib6_rule_lookup+0x334/0x630 + ip6_route_output_flags+0x259/0x480 + ip6_dst_lookup_tail.constprop.0+0x5c2/0x940 + ip6_dst_lookup_flow+0x88/0x190 + udp_tunnel6_dst_lookup+0x2a7/0x4c0 + vxlan_xmit_one+0xbde/0x4a50 [vxlan] + vxlan_xmit+0x9ad/0xf20 [vxlan] + dev_hard_start_xmit+0x10e/0x360 + __dev_queue_xmit+0xf95/0x18c0 + arp_solicit+0x4a2/0xe00 + neigh_probe+0xaa/0xf0 + +While the first suspect is the dst_cache, explicitly tracking the dst +owing the last device reference via probes proved such dst is held by +the nexthop in the originating fib6_info. + +Similar to commit f5b51fe804ec ("ipv6: route: purge exception on +removal"), we need to explicitly release the originating fib info when +disconnecting a to-be-removed device from a live ipv6 dst: move the +fib6_info cleanup into ip6_dst_ifdown(). + +Tested running: + +./pmtu.sh cleanup_ipv6_exception + +in a tight loop for more than 400 iterations with no spat, running an +unpatched kernel I observed a splat every ~10 iterations. + +Fixes: f88d8ea67fbd ("ipv6: Plumb support for nexthop object in a fib6_info") +Signed-off-by: Paolo Abeni <pabeni@redhat.com> +Reviewed-by: Eric Dumazet <edumazet@google.com> +Reviewed-by: David Ahern <dsahern@kernel.org> +Link: https://patch.msgid.link/604c45c188c609b732286b47ac2a451a40f6cf6d.1730828007.git.pabeni@redhat.com +Signed-off-by: Jakub Kicinski <kuba@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + net/ipv6/route.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/net/ipv6/route.c b/net/ipv6/route.c +index b4251915585f7..76bea6db59764 100644 +--- a/net/ipv6/route.c ++++ b/net/ipv6/route.c +@@ -374,6 +374,7 @@ static void ip6_dst_ifdown(struct dst_entry *dst, struct net_device *dev) + { + struct rt6_info *rt = dst_rt6_info(dst); + struct inet6_dev *idev = rt->rt6i_idev; ++ struct fib6_info *from; + + if (idev && idev->dev != blackhole_netdev) { + struct inet6_dev *blackhole_idev = in6_dev_get(blackhole_netdev); +@@ -383,6 +384,8 @@ static void ip6_dst_ifdown(struct dst_entry *dst, struct net_device *dev) + in6_dev_put(idev); + } + } ++ from = unrcu_pointer(xchg(&rt->from, NULL)); ++ fib6_info_release(from); + } + + static bool __rt6_check_expired(const struct rt6_info *rt) +@@ -1455,7 +1458,6 @@ static DEFINE_SPINLOCK(rt6_exception_lock); + static void rt6_remove_exception(struct rt6_exception_bucket *bucket, + struct rt6_exception *rt6_ex) + { +- struct fib6_info *from; + struct net *net; + + if (!bucket || !rt6_ex) +@@ -1467,8 +1469,6 @@ static void rt6_remove_exception(struct rt6_exception_bucket *bucket, + /* purge completely the exception to allow releasing the held resources: + * some [sk] cache may keep the dst around for unlimited time + */ +- from = unrcu_pointer(xchg(&rt6_ex->rt6i->from, NULL)); +- fib6_info_release(from); + dst_dev_put(&rt6_ex->rt6i->dst); + + hlist_del_rcu(&rt6_ex->hlist); +-- +2.43.0 + diff --git a/queue-6.12/irqchip-riscv-aplic-prevent-crash-when-msi-domain-is.patch b/queue-6.12/irqchip-riscv-aplic-prevent-crash-when-msi-domain-is.patch new file mode 100644 index 00000000000..fc5c875d065 --- /dev/null +++ b/queue-6.12/irqchip-riscv-aplic-prevent-crash-when-msi-domain-is.patch @@ -0,0 +1,58 @@ +From 70baf55c612148e21ef34f9861dfc68a3bb11d98 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Thu, 14 Nov 2024 12:01:30 -0800 +Subject: irqchip/riscv-aplic: Prevent crash when MSI domain is missing + +From: Samuel Holland <samuel.holland@sifive.com> + +[ Upstream commit 1f181d1cda56c2fbe379c5ace1aa1fac6306669e ] + +If the APLIC driver is probed before the IMSIC driver, the parent MSI +domain will be missing, which causes a NULL pointer dereference in +msi_create_device_irq_domain(). + +Avoid this by deferring probe until the parent MSI domain is available. Use +dev_err_probe() to avoid printing an error message when returning +-EPROBE_DEFER. + +Fixes: ca8df97fe679 ("irqchip/riscv-aplic: Add support for MSI-mode") +Signed-off-by: Samuel Holland <samuel.holland@sifive.com> +Signed-off-by: Thomas Gleixner <tglx@linutronix.de> +Link: https://lore.kernel.org/all/20241114200133.3069460-1-samuel.holland@sifive.com +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/irqchip/irq-riscv-aplic-main.c | 3 ++- + drivers/irqchip/irq-riscv-aplic-msi.c | 3 +++ + 2 files changed, 5 insertions(+), 1 deletion(-) + +diff --git a/drivers/irqchip/irq-riscv-aplic-main.c b/drivers/irqchip/irq-riscv-aplic-main.c +index 900e72541db9e..93e7c51f944ab 100644 +--- a/drivers/irqchip/irq-riscv-aplic-main.c ++++ b/drivers/irqchip/irq-riscv-aplic-main.c +@@ -207,7 +207,8 @@ static int aplic_probe(struct platform_device *pdev) + else + rc = aplic_direct_setup(dev, regs); + if (rc) +- dev_err(dev, "failed to setup APLIC in %s mode\n", msi_mode ? "MSI" : "direct"); ++ dev_err_probe(dev, rc, "failed to setup APLIC in %s mode\n", ++ msi_mode ? "MSI" : "direct"); + + #ifdef CONFIG_ACPI + if (!acpi_disabled) +diff --git a/drivers/irqchip/irq-riscv-aplic-msi.c b/drivers/irqchip/irq-riscv-aplic-msi.c +index 945bff28265cd..fb8d1838609fb 100644 +--- a/drivers/irqchip/irq-riscv-aplic-msi.c ++++ b/drivers/irqchip/irq-riscv-aplic-msi.c +@@ -266,6 +266,9 @@ int aplic_msi_setup(struct device *dev, void __iomem *regs) + if (msi_domain) + dev_set_msi_domain(dev, msi_domain); + } ++ ++ if (!dev_get_msi_domain(dev)) ++ return -EPROBE_DEFER; + } + + if (!msi_create_device_irq_domain(dev, MSI_DEFAULT_DOMAIN, &aplic_msi_template, +-- +2.43.0 + diff --git a/queue-6.12/isofs-avoid-memory-leak-in-iocharset.patch b/queue-6.12/isofs-avoid-memory-leak-in-iocharset.patch new file mode 100644 index 00000000000..a56178d315d --- /dev/null +++ b/queue-6.12/isofs-avoid-memory-leak-in-iocharset.patch @@ -0,0 +1,92 @@ +From 419418204ca14b66f5a26bc6bd15d2f9381db82f Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Wed, 6 Nov 2024 16:28:41 +0800 +Subject: isofs: avoid memory leak in iocharset + +From: Hao Ge <gehao@kylinos.cn> + +[ Upstream commit 0b5bbeee4de616a268db77e2f40f19ab010a367b ] + +A memleak was found as below: + +unreferenced object 0xffff0000d10164d8 (size 8): + comm "pool-udisksd", pid 108217, jiffies 4295408555 + hex dump (first 8 bytes): + 75 74 66 38 00 cc cc cc utf8.... + backtrace (crc de430d31): + [<ffff800081046e6c>] kmemleak_alloc+0xb8/0xc8 + [<ffff8000803e6c3c>] __kmalloc_node_track_caller_noprof+0x380/0x474 + [<ffff800080363b74>] kstrdup+0x70/0xfc + [<ffff80007bb3c6a4>] isofs_parse_param+0x228/0x2c0 [isofs] + [<ffff8000804d7f68>] vfs_parse_fs_param+0xf4/0x164 + [<ffff8000804d8064>] vfs_parse_fs_string+0x8c/0xd4 + [<ffff8000804d815c>] vfs_parse_monolithic_sep+0xb0/0xfc + [<ffff8000804d81d8>] generic_parse_monolithic+0x30/0x3c + [<ffff8000804d8bfc>] parse_monolithic_mount_data+0x40/0x4c + [<ffff8000804b6a64>] path_mount+0x6c4/0x9ec + [<ffff8000804b6e38>] do_mount+0xac/0xc4 + [<ffff8000804b7494>] __arm64_sys_mount+0x16c/0x2b0 + [<ffff80008002b8dc>] invoke_syscall+0x7c/0x104 + [<ffff80008002ba44>] el0_svc_common.constprop.1+0xe0/0x104 + [<ffff80008002ba94>] do_el0_svc+0x2c/0x38 + [<ffff800081041108>] el0_svc+0x3c/0x1b8 + +The opt->iocharset is freed inside the isofs_fill_super function, +But there may be situations where it's not possible to +enter this function. + +For example, in the get_tree_bdev_flags function,when +encountering the situation where "Can't mount, would change RO state," +In such a case, isofs_fill_super will not have the opportunity +to be called,which means that opt->iocharset will not have the chance +to be freed,ultimately leading to a memory leak. + +Let's move the memory freeing of opt->iocharset into +isofs_free_fc function. + +Fixes: 1b17a46c9243 ("isofs: convert isofs to use the new mount API") +Signed-off-by: Hao Ge <gehao@kylinos.cn> +Reviewed-by: Eric Sandeen <sandeen@redhat.com> +Signed-off-by: Jan Kara <jack@suse.cz> +Link: https://patch.msgid.link/20241106082841.51773-1-hao.ge@linux.dev +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + fs/isofs/inode.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/fs/isofs/inode.c b/fs/isofs/inode.c +index f50311a6b4299..47038e6608123 100644 +--- a/fs/isofs/inode.c ++++ b/fs/isofs/inode.c +@@ -948,8 +948,6 @@ static int isofs_fill_super(struct super_block *s, struct fs_context *fc) + goto out_no_inode; + } + +- kfree(opt->iocharset); +- + return 0; + + /* +@@ -987,7 +985,6 @@ static int isofs_fill_super(struct super_block *s, struct fs_context *fc) + brelse(bh); + brelse(pri_bh); + out_freesbi: +- kfree(opt->iocharset); + kfree(sbi); + s->s_fs_info = NULL; + return error; +@@ -1528,7 +1525,10 @@ static int isofs_get_tree(struct fs_context *fc) + + static void isofs_free_fc(struct fs_context *fc) + { +- kfree(fc->fs_private); ++ struct isofs_options *opt = fc->fs_private; ++ ++ kfree(opt->iocharset); ++ kfree(opt); + } + + static const struct fs_context_operations isofs_context_ops = { +-- +2.43.0 + diff --git a/queue-6.12/kasan-move-checks-to-do_strncpy_from_user.patch b/queue-6.12/kasan-move-checks-to-do_strncpy_from_user.patch new file mode 100644 index 00000000000..78f7d85787b --- /dev/null +++ b/queue-6.12/kasan-move-checks-to-do_strncpy_from_user.patch @@ -0,0 +1,85 @@ +From b33503632c9048d7596bfef13f035545ff6f5493 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Wed, 16 Oct 2024 18:18:00 +0500 +Subject: kasan: move checks to do_strncpy_from_user + +From: Sabyrzhan Tasbolatov <snovitoll@gmail.com> + +[ Upstream commit ae193dd79398970ee760e0c8129ac42ef8f5c6ff ] + +Patch series "kasan: migrate the last module test to kunit", v4. + +copy_user_test() is the last KUnit-incompatible test with +CONFIG_KASAN_MODULE_TEST requirement, which we are going to migrate to +KUnit framework and delete the former test and Kconfig as well. + +In this patch series: + + - [1/3] move kasan_check_write() and check_object_size() to + do_strncpy_from_user() to cover with KASAN checks with + multiple conditions in strncpy_from_user(). + + - [2/3] migrated copy_user_test() to KUnit, where we can also test + strncpy_from_user() due to [1/4]. + + KUnits have been tested on: + - x86_64 with CONFIG_KASAN_GENERIC. Passed + - arm64 with CONFIG_KASAN_SW_TAGS. 1 fail. See [1] + - arm64 with CONFIG_KASAN_HW_TAGS. 1 fail. See [1] + [1] https://lore.kernel.org/linux-mm/CACzwLxj21h7nCcS2-KA_q7ybe+5pxH0uCDwu64q_9pPsydneWQ@mail.gmail.com/ + + - [3/3] delete CONFIG_KASAN_MODULE_TEST and documentation occurrences. + +This patch (of 3): + +Since in the commit 2865baf54077("x86: support user address masking +instead of non-speculative conditional") do_strncpy_from_user() is called +from multiple places, we should sanitize the kernel *dst memory and size +which were done in strncpy_from_user() previously. + +Link: https://lkml.kernel.org/r/20241016131802.3115788-1-snovitoll@gmail.com +Link: https://lkml.kernel.org/r/20241016131802.3115788-2-snovitoll@gmail.com +Fixes: 2865baf54077 ("x86: support user address masking instead of non-speculative conditional") +Signed-off-by: Sabyrzhan Tasbolatov <snovitoll@gmail.com> +Reviewed-by: Andrey Konovalov <andreyknvl@gmail.com> +Cc: Alexander Potapenko <glider@google.com> +Cc: Alex Shi <alexs@kernel.org> +Cc: Andrey Ryabinin <ryabinin.a.a@gmail.com> +Cc: Dmitry Vyukov <dvyukov@google.com> +Cc: Hu Haowen <2023002089@link.tyut.edu.cn> +Cc: Jonathan Corbet <corbet@lwn.net> +Cc: Marco Elver <elver@google.com> +Cc: Vincenzo Frascino <vincenzo.frascino@arm.com> +Cc: Yanteng Si <siyanteng@loongson.cn> +Signed-off-by: Andrew Morton <akpm@linux-foundation.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + lib/strncpy_from_user.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/lib/strncpy_from_user.c b/lib/strncpy_from_user.c +index 989a12a678721..6dc234913dd58 100644 +--- a/lib/strncpy_from_user.c ++++ b/lib/strncpy_from_user.c +@@ -120,6 +120,9 @@ long strncpy_from_user(char *dst, const char __user *src, long count) + if (unlikely(count <= 0)) + return 0; + ++ kasan_check_write(dst, count); ++ check_object_size(dst, count, false); ++ + if (can_do_masked_user_access()) { + long retval; + +@@ -142,8 +145,6 @@ long strncpy_from_user(char *dst, const char __user *src, long count) + if (max > count) + max = count; + +- kasan_check_write(dst, count); +- check_object_size(dst, count, false); + if (user_read_access_begin(src, max)) { + retval = do_strncpy_from_user(dst, src, count, max); + user_read_access_end(); +-- +2.43.0 + diff --git a/queue-6.12/kcsan-seqlock-fix-incorrect-assumption-in-read_seqbe.patch b/queue-6.12/kcsan-seqlock-fix-incorrect-assumption-in-read_seqbe.patch new file mode 100644 index 00000000000..86a2c7e98bb --- /dev/null +++ b/queue-6.12/kcsan-seqlock-fix-incorrect-assumption-in-read_seqbe.patch @@ -0,0 +1,78 @@ +From baf8bcbc01772caae75f3f6baadec8ec365f4b06 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Mon, 4 Nov 2024 16:43:09 +0100 +Subject: kcsan, seqlock: Fix incorrect assumption in read_seqbegin() + +From: Marco Elver <elver@google.com> + +[ Upstream commit 183ec5f26b2fc97a4a9871865bfe9b33c41fddb2 ] + +During testing of the preceding changes, I noticed that in some cases, +current->kcsan_ctx.in_flat_atomic remained true until task exit. This is +obviously wrong, because _all_ accesses for the given task will be +treated as atomic, resulting in false negatives i.e. missed data races. + +Debugging led to fs/dcache.c, where we can see this usage of seqlock: + + struct dentry *d_lookup(const struct dentry *parent, const struct qstr *name) + { + struct dentry *dentry; + unsigned seq; + + do { + seq = read_seqbegin(&rename_lock); + dentry = __d_lookup(parent, name); + if (dentry) + break; + } while (read_seqretry(&rename_lock, seq)); + [...] + +As can be seen, read_seqretry() is never called if dentry != NULL; +consequently, current->kcsan_ctx.in_flat_atomic will never be reset to +false by read_seqretry(). + +Give up on the wrong assumption of "assume closing read_seqretry()", and +rely on the already-present annotations in read_seqcount_begin/retry(). + +Fixes: 88ecd153be95 ("seqlock, kcsan: Add annotations for KCSAN") +Signed-off-by: Marco Elver <elver@google.com> +Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> +Link: https://lore.kernel.org/r/20241104161910.780003-6-elver@google.com +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + include/linux/seqlock.h | 12 +----------- + 1 file changed, 1 insertion(+), 11 deletions(-) + +diff --git a/include/linux/seqlock.h b/include/linux/seqlock.h +index 45eee0e5dca01..5298765d6ca48 100644 +--- a/include/linux/seqlock.h ++++ b/include/linux/seqlock.h +@@ -810,11 +810,7 @@ static __always_inline void write_seqcount_latch_end(seqcount_latch_t *s) + */ + static inline unsigned read_seqbegin(const seqlock_t *sl) + { +- unsigned ret = read_seqcount_begin(&sl->seqcount); +- +- kcsan_atomic_next(0); /* non-raw usage, assume closing read_seqretry() */ +- kcsan_flat_atomic_begin(); +- return ret; ++ return read_seqcount_begin(&sl->seqcount); + } + + /** +@@ -830,12 +826,6 @@ static inline unsigned read_seqbegin(const seqlock_t *sl) + */ + static inline unsigned read_seqretry(const seqlock_t *sl, unsigned start) + { +- /* +- * Assume not nested: read_seqretry() may be called multiple times when +- * completing read critical section. +- */ +- kcsan_flat_atomic_end(); +- + return read_seqcount_retry(&sl->seqcount, start); + } + +-- +2.43.0 + diff --git a/queue-6.12/kcsan-seqlock-support-seqcount_latch_t.patch b/queue-6.12/kcsan-seqlock-support-seqcount_latch_t.patch new file mode 100644 index 00000000000..c846be1ab2a --- /dev/null +++ b/queue-6.12/kcsan-seqlock-support-seqcount_latch_t.patch @@ -0,0 +1,210 @@ +From 6334eecb2792f72adfe60c2d99fb49c6cfa60b49 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Mon, 4 Nov 2024 16:43:07 +0100 +Subject: kcsan, seqlock: Support seqcount_latch_t + +From: Marco Elver <elver@google.com> + +[ Upstream commit 5c1806c41ce0a0110db5dd4c483cf2dc28b3ddf0 ] + +While fuzzing an arm64 kernel, Alexander Potapenko reported: + +| BUG: KCSAN: data-race in ktime_get_mono_fast_ns / timekeeping_update +| +| write to 0xffffffc082e74248 of 56 bytes by interrupt on cpu 0: +| update_fast_timekeeper kernel/time/timekeeping.c:430 [inline] +| timekeeping_update+0x1d8/0x2d8 kernel/time/timekeeping.c:768 +| timekeeping_advance+0x9e8/0xb78 kernel/time/timekeeping.c:2344 +| update_wall_time+0x18/0x38 kernel/time/timekeeping.c:2360 +| [...] +| +| read to 0xffffffc082e74258 of 8 bytes by task 5260 on cpu 1: +| __ktime_get_fast_ns kernel/time/timekeeping.c:372 [inline] +| ktime_get_mono_fast_ns+0x88/0x174 kernel/time/timekeeping.c:489 +| init_srcu_struct_fields+0x40c/0x530 kernel/rcu/srcutree.c:263 +| init_srcu_struct+0x14/0x20 kernel/rcu/srcutree.c:311 +| [...] +| +| value changed: 0x000002f875d33266 -> 0x000002f877416866 +| +| Reported by Kernel Concurrency Sanitizer on: +| CPU: 1 UID: 0 PID: 5260 Comm: syz.2.7483 Not tainted 6.12.0-rc3-dirty #78 + +This is a false positive data race between a seqcount latch writer and a reader +accessing stale data. Since its introduction, KCSAN has never understood the +seqcount_latch interface (due to being unannotated). + +Unlike the regular seqlock interface, the seqcount_latch interface for latch +writers never has had a well-defined critical section, making it difficult to +teach tooling where the critical section starts and ends. + +Introduce an instrumentable (non-raw) seqcount_latch interface, with +which we can clearly denote writer critical sections. This both helps +readability and tooling like KCSAN to understand when the writer is done +updating all latch copies. + +Fixes: 88ecd153be95 ("seqlock, kcsan: Add annotations for KCSAN") +Reported-by: Alexander Potapenko <glider@google.com> +Co-developed-by: "Peter Zijlstra (Intel)" <peterz@infradead.org> +Signed-off-by: "Peter Zijlstra (Intel)" <peterz@infradead.org> +Signed-off-by: Marco Elver <elver@google.com> +Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> +Link: https://lore.kernel.org/r/20241104161910.780003-4-elver@google.com +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + Documentation/locking/seqlock.rst | 2 +- + include/linux/seqlock.h | 86 +++++++++++++++++++++++++------ + 2 files changed, 72 insertions(+), 16 deletions(-) + +diff --git a/Documentation/locking/seqlock.rst b/Documentation/locking/seqlock.rst +index bfda1a5fecadc..ec6411d02ac8f 100644 +--- a/Documentation/locking/seqlock.rst ++++ b/Documentation/locking/seqlock.rst +@@ -153,7 +153,7 @@ Use seqcount_latch_t when the write side sections cannot be protected + from interruption by readers. This is typically the case when the read + side can be invoked from NMI handlers. + +-Check `raw_write_seqcount_latch()` for more information. ++Check `write_seqcount_latch()` for more information. + + + .. _seqlock_t: +diff --git a/include/linux/seqlock.h b/include/linux/seqlock.h +index fffeb754880fc..45eee0e5dca01 100644 +--- a/include/linux/seqlock.h ++++ b/include/linux/seqlock.h +@@ -621,6 +621,23 @@ static __always_inline unsigned raw_read_seqcount_latch(const seqcount_latch_t * + return READ_ONCE(s->seqcount.sequence); + } + ++/** ++ * read_seqcount_latch() - pick even/odd latch data copy ++ * @s: Pointer to seqcount_latch_t ++ * ++ * See write_seqcount_latch() for details and a full reader/writer usage ++ * example. ++ * ++ * Return: sequence counter raw value. Use the lowest bit as an index for ++ * picking which data copy to read. The full counter must then be checked ++ * with read_seqcount_latch_retry(). ++ */ ++static __always_inline unsigned read_seqcount_latch(const seqcount_latch_t *s) ++{ ++ kcsan_atomic_next(KCSAN_SEQLOCK_REGION_MAX); ++ return raw_read_seqcount_latch(s); ++} ++ + /** + * raw_read_seqcount_latch_retry() - end a seqcount_latch_t read section + * @s: Pointer to seqcount_latch_t +@@ -635,9 +652,34 @@ raw_read_seqcount_latch_retry(const seqcount_latch_t *s, unsigned start) + return unlikely(READ_ONCE(s->seqcount.sequence) != start); + } + ++/** ++ * read_seqcount_latch_retry() - end a seqcount_latch_t read section ++ * @s: Pointer to seqcount_latch_t ++ * @start: count, from read_seqcount_latch() ++ * ++ * Return: true if a read section retry is required, else false ++ */ ++static __always_inline int ++read_seqcount_latch_retry(const seqcount_latch_t *s, unsigned start) ++{ ++ kcsan_atomic_next(0); ++ return raw_read_seqcount_latch_retry(s, start); ++} ++ + /** + * raw_write_seqcount_latch() - redirect latch readers to even/odd copy + * @s: Pointer to seqcount_latch_t ++ */ ++static __always_inline void raw_write_seqcount_latch(seqcount_latch_t *s) ++{ ++ smp_wmb(); /* prior stores before incrementing "sequence" */ ++ s->seqcount.sequence++; ++ smp_wmb(); /* increment "sequence" before following stores */ ++} ++ ++/** ++ * write_seqcount_latch_begin() - redirect latch readers to odd copy ++ * @s: Pointer to seqcount_latch_t + * + * The latch technique is a multiversion concurrency control method that allows + * queries during non-atomic modifications. If you can guarantee queries never +@@ -665,17 +707,11 @@ raw_read_seqcount_latch_retry(const seqcount_latch_t *s, unsigned start) + * + * void latch_modify(struct latch_struct *latch, ...) + * { +- * smp_wmb(); // Ensure that the last data[1] update is visible +- * latch->seq.sequence++; +- * smp_wmb(); // Ensure that the seqcount update is visible +- * ++ * write_seqcount_latch_begin(&latch->seq); + * modify(latch->data[0], ...); +- * +- * smp_wmb(); // Ensure that the data[0] update is visible +- * latch->seq.sequence++; +- * smp_wmb(); // Ensure that the seqcount update is visible +- * ++ * write_seqcount_latch(&latch->seq); + * modify(latch->data[1], ...); ++ * write_seqcount_latch_end(&latch->seq); + * } + * + * The query will have a form like:: +@@ -686,13 +722,13 @@ raw_read_seqcount_latch_retry(const seqcount_latch_t *s, unsigned start) + * unsigned seq, idx; + * + * do { +- * seq = raw_read_seqcount_latch(&latch->seq); ++ * seq = read_seqcount_latch(&latch->seq); + * + * idx = seq & 0x01; + * entry = data_query(latch->data[idx], ...); + * + * // This includes needed smp_rmb() +- * } while (raw_read_seqcount_latch_retry(&latch->seq, seq)); ++ * } while (read_seqcount_latch_retry(&latch->seq, seq)); + * + * return entry; + * } +@@ -716,11 +752,31 @@ raw_read_seqcount_latch_retry(const seqcount_latch_t *s, unsigned start) + * When data is a dynamic data structure; one should use regular RCU + * patterns to manage the lifetimes of the objects within. + */ +-static inline void raw_write_seqcount_latch(seqcount_latch_t *s) ++static __always_inline void write_seqcount_latch_begin(seqcount_latch_t *s) + { +- smp_wmb(); /* prior stores before incrementing "sequence" */ +- s->seqcount.sequence++; +- smp_wmb(); /* increment "sequence" before following stores */ ++ kcsan_nestable_atomic_begin(); ++ raw_write_seqcount_latch(s); ++} ++ ++/** ++ * write_seqcount_latch() - redirect latch readers to even copy ++ * @s: Pointer to seqcount_latch_t ++ */ ++static __always_inline void write_seqcount_latch(seqcount_latch_t *s) ++{ ++ raw_write_seqcount_latch(s); ++} ++ ++/** ++ * write_seqcount_latch_end() - end a seqcount_latch_t write section ++ * @s: Pointer to seqcount_latch_t ++ * ++ * Marks the end of a seqcount_latch_t writer section, after all copies of the ++ * latch-protected data have been updated. ++ */ ++static __always_inline void write_seqcount_latch_end(seqcount_latch_t *s) ++{ ++ kcsan_nestable_atomic_end(); + } + + #define __SEQLOCK_UNLOCKED(lockname) \ +-- +2.43.0 + diff --git a/queue-6.12/kernel-doc-allow-object-like-macros-in-rest-output.patch b/queue-6.12/kernel-doc-allow-object-like-macros-in-rest-output.patch new file mode 100644 index 00000000000..97cbf8270d2 --- /dev/null +++ b/queue-6.12/kernel-doc-allow-object-like-macros-in-rest-output.patch @@ -0,0 +1,154 @@ +From ec61c7b2cdfc578780f876b4d67e1a24c72be132 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Tue, 15 Oct 2024 11:11:07 -0700 +Subject: kernel-doc: allow object-like macros in ReST output + +From: Randy Dunlap <rdunlap@infradead.org> + +[ Upstream commit bb8fd09e2811e2386bb40b9f0d3c7dd6e7961a1e ] + +output_function_rst() does not handle object-like macros. It presents +a trailing "()" while output_function_man() handles these macros +correctly. + +Update output_function_rst() to handle object-like macros. +Don't show the "Parameters" heading if there are no parameters. + +For output_function_man(), don't show the "ARGUMENTS" heading if there +are no parameters. + +I have tested this quite a bit with my ad hoc test files for both ReST +and man format outputs. The generated output looks good. + +Fixes: cbb4d3e6510b ("scripts/kernel-doc: handle object-like macros") +Signed-off-by: Randy Dunlap <rdunlap@infradead.org> +Cc: Horia Geanta <horia.geanta@freescale.com> +Tested-by: Vlastimil Babka <vbabka@suse.cz> +Signed-off-by: Jonathan Corbet <corbet@lwn.net> +Link: https://lore.kernel.org/r/20241015181107.536894-1-rdunlap@infradead.org +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + scripts/kernel-doc | 43 ++++++++++++++++++++++++++++++------------- + 1 file changed, 30 insertions(+), 13 deletions(-) + +diff --git a/scripts/kernel-doc b/scripts/kernel-doc +index c608820f0bf51..320544321ecba 100755 +--- a/scripts/kernel-doc ++++ b/scripts/kernel-doc +@@ -569,6 +569,8 @@ sub output_function_man(%) { + my %args = %{$_[0]}; + my ($parameter, $section); + my $count; ++ my $func_macro = $args{'func_macro'}; ++ my $paramcount = $#{$args{'parameterlist'}}; # -1 is empty + + print ".TH \"$args{'function'}\" 9 \"$args{'function'}\" \"$man_date\" \"Kernel Hacker's Manual\" LINUX\n"; + +@@ -600,7 +602,10 @@ sub output_function_man(%) { + $parenth = ""; + } + +- print ".SH ARGUMENTS\n"; ++ $paramcount = $#{$args{'parameterlist'}}; # -1 is empty ++ if ($paramcount >= 0) { ++ print ".SH ARGUMENTS\n"; ++ } + foreach $parameter (@{$args{'parameterlist'}}) { + my $parameter_name = $parameter; + $parameter_name =~ s/\[.*//; +@@ -822,10 +827,16 @@ sub output_function_rst(%) { + my $oldprefix = $lineprefix; + + my $signature = ""; +- if ($args{'functiontype'} ne "") { +- $signature = $args{'functiontype'} . " " . $args{'function'} . " ("; +- } else { +- $signature = $args{'function'} . " ("; ++ my $func_macro = $args{'func_macro'}; ++ my $paramcount = $#{$args{'parameterlist'}}; # -1 is empty ++ ++ if ($func_macro) { ++ $signature = $args{'function'}; ++ } else { ++ if ($args{'functiontype'}) { ++ $signature = $args{'functiontype'} . " "; ++ } ++ $signature .= $args{'function'} . " ("; + } + + my $count = 0; +@@ -844,7 +855,9 @@ sub output_function_rst(%) { + } + } + +- $signature .= ")"; ++ if (!$func_macro) { ++ $signature .= ")"; ++ } + + if ($sphinx_major < 3) { + if ($args{'typedef'}) { +@@ -888,9 +901,11 @@ sub output_function_rst(%) { + # Put our descriptive text into a container (thus an HTML <div>) to help + # set the function prototypes apart. + # +- print ".. container:: kernelindent\n\n"; + $lineprefix = " "; +- print $lineprefix . "**Parameters**\n\n"; ++ if ($paramcount >= 0) { ++ print ".. container:: kernelindent\n\n"; ++ print $lineprefix . "**Parameters**\n\n"; ++ } + foreach $parameter (@{$args{'parameterlist'}}) { + my $parameter_name = $parameter; + $parameter_name =~ s/\[.*//; +@@ -1704,7 +1719,7 @@ sub check_return_section { + sub dump_function($$) { + my $prototype = shift; + my $file = shift; +- my $noret = 0; ++ my $func_macro = 0; + + print_lineno($new_start_line); + +@@ -1769,7 +1784,7 @@ sub dump_function($$) { + # declaration_name and opening parenthesis (notice the \s+). + $return_type = $1; + $declaration_name = $2; +- $noret = 1; ++ $func_macro = 1; + } elsif ($prototype =~ m/^()($name)\s*$prototype_end/ || + $prototype =~ m/^($type1)\s+($name)\s*$prototype_end/ || + $prototype =~ m/^($type2+)\s*($name)\s*$prototype_end/) { +@@ -1796,7 +1811,7 @@ sub dump_function($$) { + # of warnings goes sufficiently down, the check is only performed in + # -Wreturn mode. + # TODO: always perform the check. +- if ($Wreturn && !$noret) { ++ if ($Wreturn && !$func_macro) { + check_return_section($file, $declaration_name, $return_type); + } + +@@ -1814,7 +1829,8 @@ sub dump_function($$) { + 'parametertypes' => \%parametertypes, + 'sectionlist' => \@sectionlist, + 'sections' => \%sections, +- 'purpose' => $declaration_purpose ++ 'purpose' => $declaration_purpose, ++ 'func_macro' => $func_macro + }); + } else { + output_declaration($declaration_name, +@@ -1827,7 +1843,8 @@ sub dump_function($$) { + 'parametertypes' => \%parametertypes, + 'sectionlist' => \@sectionlist, + 'sections' => \%sections, +- 'purpose' => $declaration_purpose ++ 'purpose' => $declaration_purpose, ++ 'func_macro' => $func_macro + }); + } + } +-- +2.43.0 + diff --git a/queue-6.12/kselftest-arm64-fix-encoding-for-sve-b16b16-test.patch b/queue-6.12/kselftest-arm64-fix-encoding-for-sve-b16b16-test.patch new file mode 100644 index 00000000000..3d26c7423e0 --- /dev/null +++ b/queue-6.12/kselftest-arm64-fix-encoding-for-sve-b16b16-test.patch @@ -0,0 +1,39 @@ +From 8cbda9b5aa2bda4a6c34e4ee81606df882141c68 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Mon, 28 Oct 2024 20:22:31 +0000 +Subject: kselftest/arm64: Fix encoding for SVE B16B16 test + +From: Mark Brown <broonie@kernel.org> + +[ Upstream commit 69c0d824779843b51ca2339b2163db4d3b40c54c ] + +The test for SVE_B16B16 had a cut'n'paste of a SME instruction, fix it with +a relevant SVE instruction. + +Fixes: 44d10c27bd75 ("kselftest/arm64: Add 2023 DPISA hwcap test coverage") +Signed-off-by: Mark Brown <broonie@kernel.org> +Link: https://lore.kernel.org/r/20241028-arm64-b16b16-test-v1-1-59a4a7449bdf@kernel.org +Signed-off-by: Catalin Marinas <catalin.marinas@arm.com> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + tools/testing/selftests/arm64/abi/hwcap.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/tools/testing/selftests/arm64/abi/hwcap.c b/tools/testing/selftests/arm64/abi/hwcap.c +index 7e95ba5fd4962..265654ec48b9f 100644 +--- a/tools/testing/selftests/arm64/abi/hwcap.c ++++ b/tools/testing/selftests/arm64/abi/hwcap.c +@@ -361,8 +361,8 @@ static void sveaes_sigill(void) + + static void sveb16b16_sigill(void) + { +- /* BFADD ZA.H[W0, 0], {Z0.H-Z1.H} */ +- asm volatile(".inst 0xC1E41C00" : : : ); ++ /* BFADD Z0.H, Z0.H, Z0.H */ ++ asm volatile(".inst 0x65000000" : : : ); + } + + static void svepmull_sigill(void) +-- +2.43.0 + diff --git a/queue-6.12/kselftest-arm64-hwcap-fix-f8dp2-cpuinfo-name.patch b/queue-6.12/kselftest-arm64-hwcap-fix-f8dp2-cpuinfo-name.patch new file mode 100644 index 00000000000..ccf6cb595fd --- /dev/null +++ b/queue-6.12/kselftest-arm64-hwcap-fix-f8dp2-cpuinfo-name.patch @@ -0,0 +1,39 @@ +From b270c72600675f06887993beaba7f9e01e0790ba Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Fri, 16 Aug 2024 16:32:45 +0100 +Subject: kselftest/arm64: hwcap: fix f8dp2 cpuinfo name + +From: Andre Przywara <andre.przywara@arm.com> + +[ Upstream commit b0d80dbc378d52155c9ecf9579986edccceed3aa ] + +The F8DP2 DPISA extension has a separate cpuinfo field, named +accordingly. +Change the erroneously placed name of "f8dp4" to "f8dp2". + +Fixes: 44d10c27bd75 ("kselftest/arm64: Add 2023 DPISA hwcap test coverage") +Signed-off-by: Andre Przywara <andre.przywara@arm.com> +Reviewed-by: Mark Brown <broonie@kernel.org> +Link: https://lore.kernel.org/r/20240816153251.2833702-3-andre.przywara@arm.com +Signed-off-by: Catalin Marinas <catalin.marinas@arm.com> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + tools/testing/selftests/arm64/abi/hwcap.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/tools/testing/selftests/arm64/abi/hwcap.c b/tools/testing/selftests/arm64/abi/hwcap.c +index f2d6007a2b983..7e95ba5fd4962 100644 +--- a/tools/testing/selftests/arm64/abi/hwcap.c ++++ b/tools/testing/selftests/arm64/abi/hwcap.c +@@ -490,7 +490,7 @@ static const struct hwcap_data { + .name = "F8DP2", + .at_hwcap = AT_HWCAP2, + .hwcap_bit = HWCAP2_F8DP2, +- .cpuinfo = "f8dp4", ++ .cpuinfo = "f8dp2", + .sigill_fn = f8dp2_sigill, + }, + { +-- +2.43.0 + diff --git a/queue-6.12/kselftest-arm64-mte-fix-printf-type-warnings-about-_.patch b/queue-6.12/kselftest-arm64-mte-fix-printf-type-warnings-about-_.patch new file mode 100644 index 00000000000..89e73d95c12 --- /dev/null +++ b/queue-6.12/kselftest-arm64-mte-fix-printf-type-warnings-about-_.patch @@ -0,0 +1,59 @@ +From af28dc83a42d49b12229591711563e38c22061b6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Fri, 16 Aug 2024 16:32:49 +0100 +Subject: kselftest/arm64: mte: fix printf type warnings about __u64 + +From: Andre Przywara <andre.przywara@arm.com> + +[ Upstream commit 7e893dc81de3e342156389ea0b83ec7d07f25281 ] + +When printing the signal context's PC, we use a "%lx" format specifier, +which matches the common userland (glibc's) definition of uint64_t as an +"unsigned long". However the structure in question is defined in a +kernel uapi header, which uses a self defined __u64 type, and the arm64 +kernel headers define this using "int-ll64.h", so it becomes an +"unsigned long long". This mismatch leads to the usual compiler warning. + +The common fix would be to use "PRIx64", but because this is defined by +the userland's toolchain libc headers, it wouldn't match as well. Since +we know the exact type of __u64, just use "%llx" here instead, to silence +this warning. + +This also fixes a more severe typo: "$lx" is not a valid format +specifier. + +Fixes: 191e678bdc9b ("kselftest/arm64: Log unexpected asynchronous MTE faults") +Signed-off-by: Andre Przywara <andre.przywara@arm.com> +Reviewed-by: Mark Brown <broonie@kernel.org> +Link: https://lore.kernel.org/r/20240816153251.2833702-7-andre.przywara@arm.com +Signed-off-by: Catalin Marinas <catalin.marinas@arm.com> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + tools/testing/selftests/arm64/mte/mte_common_util.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/tools/testing/selftests/arm64/mte/mte_common_util.c b/tools/testing/selftests/arm64/mte/mte_common_util.c +index 00ffd34c66d30..1120f5aa76550 100644 +--- a/tools/testing/selftests/arm64/mte/mte_common_util.c ++++ b/tools/testing/selftests/arm64/mte/mte_common_util.c +@@ -38,7 +38,7 @@ void mte_default_handler(int signum, siginfo_t *si, void *uc) + if (cur_mte_cxt.trig_si_code == si->si_code) + cur_mte_cxt.fault_valid = true; + else +- ksft_print_msg("Got unexpected SEGV_MTEAERR at pc=$lx, fault addr=%lx\n", ++ ksft_print_msg("Got unexpected SEGV_MTEAERR at pc=%llx, fault addr=%lx\n", + ((ucontext_t *)uc)->uc_mcontext.pc, + addr); + return; +@@ -64,7 +64,7 @@ void mte_default_handler(int signum, siginfo_t *si, void *uc) + exit(1); + } + } else if (signum == SIGBUS) { +- ksft_print_msg("INFO: SIGBUS signal at pc=%lx, fault addr=%lx, si_code=%lx\n", ++ ksft_print_msg("INFO: SIGBUS signal at pc=%llx, fault addr=%lx, si_code=%x\n", + ((ucontext_t *)uc)->uc_mcontext.pc, addr, si->si_code); + if ((cur_mte_cxt.trig_range >= 0 && + addr >= MT_CLEAR_TAG(cur_mte_cxt.trig_addr) && +-- +2.43.0 + diff --git a/queue-6.12/kselftest-arm64-mte-fix-printf-type-warnings-about-l.patch b/queue-6.12/kselftest-arm64-mte-fix-printf-type-warnings-about-l.patch new file mode 100644 index 00000000000..f013b72844b --- /dev/null +++ b/queue-6.12/kselftest-arm64-mte-fix-printf-type-warnings-about-l.patch @@ -0,0 +1,51 @@ +From 38337afa89e7471b96656d695fb63234af3c02eb Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Fri, 16 Aug 2024 16:32:51 +0100 +Subject: kselftest/arm64: mte: fix printf type warnings about longs + +From: Andre Przywara <andre.przywara@arm.com> + +[ Upstream commit 96dddb7b9406259baace9a1831e8da155311be6f ] + +When checking MTE tags, we print some diagnostic messages when the tests +fail. Some variables uses there are "longs", however we only use "%x" +for the format specifier. + +Update the format specifiers to "%lx", to match the variable types they +are supposed to print. + +Fixes: f3b2a26ca78d ("kselftest/arm64: Verify mte tag inclusion via prctl") +Signed-off-by: Andre Przywara <andre.przywara@arm.com> +Reviewed-by: Mark Brown <broonie@kernel.org> +Link: https://lore.kernel.org/r/20240816153251.2833702-9-andre.przywara@arm.com +Signed-off-by: Catalin Marinas <catalin.marinas@arm.com> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + tools/testing/selftests/arm64/mte/check_tags_inclusion.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/tools/testing/selftests/arm64/mte/check_tags_inclusion.c b/tools/testing/selftests/arm64/mte/check_tags_inclusion.c +index 2b1425b92b699..a3d1e23fe02af 100644 +--- a/tools/testing/selftests/arm64/mte/check_tags_inclusion.c ++++ b/tools/testing/selftests/arm64/mte/check_tags_inclusion.c +@@ -65,7 +65,7 @@ static int check_single_included_tags(int mem_type, int mode) + ptr = mte_insert_tags(ptr, BUFFER_SIZE); + /* Check tag value */ + if (MT_FETCH_TAG((uintptr_t)ptr) == tag) { +- ksft_print_msg("FAIL: wrong tag = 0x%x with include mask=0x%x\n", ++ ksft_print_msg("FAIL: wrong tag = 0x%lx with include mask=0x%x\n", + MT_FETCH_TAG((uintptr_t)ptr), + MT_INCLUDE_VALID_TAG(tag)); + result = KSFT_FAIL; +@@ -97,7 +97,7 @@ static int check_multiple_included_tags(int mem_type, int mode) + ptr = mte_insert_tags(ptr, BUFFER_SIZE); + /* Check tag value */ + if (MT_FETCH_TAG((uintptr_t)ptr) < tag) { +- ksft_print_msg("FAIL: wrong tag = 0x%x with include mask=0x%x\n", ++ ksft_print_msg("FAIL: wrong tag = 0x%lx with include mask=0x%lx\n", + MT_FETCH_TAG((uintptr_t)ptr), + MT_INCLUDE_VALID_TAGS(excl_mask)); + result = KSFT_FAIL; +-- +2.43.0 + diff --git a/queue-6.12/kunit-skb-use-gfp-variable-instead-of-hardcoding-gfp.patch b/queue-6.12/kunit-skb-use-gfp-variable-instead-of-hardcoding-gfp.patch new file mode 100644 index 00000000000..fdfb2e27f61 --- /dev/null +++ b/queue-6.12/kunit-skb-use-gfp-variable-instead-of-hardcoding-gfp.patch @@ -0,0 +1,39 @@ +From cef70896928ab2231c7f1c56d30d3de75e060bac Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Mon, 4 Nov 2024 20:16:30 +0300 +Subject: kunit: skb: use "gfp" variable instead of hardcoding GFP_KERNEL + +From: Dan Carpenter <dan.carpenter@linaro.org> + +[ Upstream commit fd0a5afb5455b4561bfc6dfb0c4b2d8226f9ccfe ] + +The intent here was clearly to use the gfp variable flags instead of +hardcoding GFP_KERNEL. All the callers pass GFP_KERNEL as the gfp +flags so this doesn't affect runtime. + +Fixes: b3231d353a51 ("kunit: add a convenience allocation wrapper for SKBs") +Signed-off-by: Dan Carpenter <dan.carpenter@linaro.org> +Reviewed-by: David Gow <davidgow@google.com> +Reviewed-by: Kuan-Wei Chiu <visitorckw@gmail.com> +Signed-off-by: Shuah Khan <skhan@linuxfoundation.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + include/kunit/skbuff.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/include/kunit/skbuff.h b/include/kunit/skbuff.h +index 44d12370939a9..345e1e8f03123 100644 +--- a/include/kunit/skbuff.h ++++ b/include/kunit/skbuff.h +@@ -29,7 +29,7 @@ static void kunit_action_kfree_skb(void *p) + static inline struct sk_buff *kunit_zalloc_skb(struct kunit *test, int len, + gfp_t gfp) + { +- struct sk_buff *res = alloc_skb(len, GFP_KERNEL); ++ struct sk_buff *res = alloc_skb(len, gfp); + + if (!res || skb_pad(res, len)) + return NULL; +-- +2.43.0 + diff --git a/queue-6.12/kvm-ppc-book3s-hv-avoid-returning-to-nested-hypervis.patch b/queue-6.12/kvm-ppc-book3s-hv-avoid-returning-to-nested-hypervis.patch new file mode 100644 index 00000000000..6f7c2db8de3 --- /dev/null +++ b/queue-6.12/kvm-ppc-book3s-hv-avoid-returning-to-nested-hypervis.patch @@ -0,0 +1,78 @@ +From ac3cb86a854358ac97431d5e5dd54558ea8ce545 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Sat, 9 Nov 2024 12:02:57 +0530 +Subject: KVM: PPC: Book3S HV: Avoid returning to nested hypervisor on pending + doorbells + +From: Gautam Menghani <gautam@linux.ibm.com> + +[ Upstream commit 26686db69917399fa30e3b3135360771e90f83ec ] + +Commit 6398326b9ba1 ("KVM: PPC: Book3S HV P9: Stop using vc->dpdes") +dropped the use of vcore->dpdes for msgsndp / SMT emulation. Prior to that +commit, the below code at L1 level (see [1] for terminology) was +responsible for setting vc->dpdes for the respective L2 vCPU: + +if (!nested) { + kvmppc_core_prepare_to_enter(vcpu); + if (vcpu->arch.doorbell_request) { + vc->dpdes = 1; + smp_wmb(); + vcpu->arch.doorbell_request = 0; + } + +L1 then sent vc->dpdes to L0 via kvmhv_save_hv_regs(), and while +servicing H_ENTER_NESTED at L0, the below condition at L0 level made sure +to abort and go back to L1 if vcpu->arch.doorbell_request = 1 so that L1 +sets vc->dpdes as per above if condition: + +} else if (vcpu->arch.pending_exceptions || + vcpu->arch.doorbell_request || + xive_interrupt_pending(vcpu)) { + vcpu->arch.ret = RESUME_HOST; + goto out; +} + +This worked fine since vcpu->arch.doorbell_request was used more like a +flag and vc->dpdes was used to pass around the doorbell state. But after +Commit 6398326b9ba1 ("KVM: PPC: Book3S HV P9: Stop using vc->dpdes"), +vcpu->arch.doorbell_request is the only variable used to pass around +doorbell state. +With the plumbing for handling doorbells for nested guests updated to use +vcpu->arch.doorbell_request over vc->dpdes, the above "else if" stops +doorbells from working correctly as L0 aborts execution of L2 and +instead goes back to L1. + +Remove vcpu->arch.doorbell_request from the above "else if" condition as +it is no longer needed for L0 to correctly handle the doorbell status +while running L2. + +[1] Terminology +1. L0 : PowerNV linux running with HV privileges +2. L1 : Pseries KVM guest running on top of L0 +2. L2 : Nested KVM guest running on top of L1 + +Fixes: 6398326b9ba1 ("KVM: PPC: Book3S HV P9: Stop using vc->dpdes") +Signed-off-by: Gautam Menghani <gautam@linux.ibm.com> +Signed-off-by: Michael Ellerman <mpe@ellerman.id.au> +Link: https://patch.msgid.link/20241109063301.105289-4-gautam@linux.ibm.com +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + arch/powerpc/kvm/book3s_hv.c | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c +index b4c5295bdc31b..59f67a44621b7 100644 +--- a/arch/powerpc/kvm/book3s_hv.c ++++ b/arch/powerpc/kvm/book3s_hv.c +@@ -4921,7 +4921,6 @@ int kvmhv_run_single_vcpu(struct kvm_vcpu *vcpu, u64 time_limit, + lpcr &= ~LPCR_MER; + } + } else if (vcpu->arch.pending_exceptions || +- vcpu->arch.doorbell_request || + xive_interrupt_pending(vcpu)) { + vcpu->arch.ret = RESUME_HOST; + goto out; +-- +2.43.0 + diff --git a/queue-6.12/kvm-ppc-book3s-hv-fix-kmv-kvm-typo.patch b/queue-6.12/kvm-ppc-book3s-hv-fix-kmv-kvm-typo.patch new file mode 100644 index 00000000000..59c30bf5e50 --- /dev/null +++ b/queue-6.12/kvm-ppc-book3s-hv-fix-kmv-kvm-typo.patch @@ -0,0 +1,81 @@ +From d77a04484abc9579f5a99534656f778d8e39f8b2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Thu, 14 Nov 2024 14:20:20 +0530 +Subject: KVM: PPC: Book3S HV: Fix kmv -> kvm typo + +From: Kajol Jain <kjain@linux.ibm.com> + +[ Upstream commit 590d2f9347f7974d7954400e5d937672fd844a8b ] + +Fix typo in the following kvm function names from: + + kmvhv_counters_tracepoint_regfunc -> kvmhv_counters_tracepoint_regfunc + kmvhv_counters_tracepoint_unregfunc -> kvmhv_counters_tracepoint_unregfunc + +Fixes: e1f288d2f9c6 ("KVM: PPC: Book3S HV nestedv2: Add support for reading VPA counters for pseries guests") +Reported-by: Madhavan Srinivasan <maddy@linux.ibm.com> +Reviewed-by: Ritesh Harjani (IBM) <ritesh.list@gmail.com> +Reviewed-by: Amit Machhiwal <amachhiw@linux.ibm.com> +Signed-off-by: Kajol Jain <kjain@linux.ibm.com> +Signed-off-by: Michael Ellerman <mpe@ellerman.id.au> +Link: https://patch.msgid.link/20241114085020.1147912-1-kjain@linux.ibm.com +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + arch/powerpc/include/asm/kvm_book3s_64.h | 4 ++-- + arch/powerpc/kvm/book3s_hv.c | 4 ++-- + arch/powerpc/kvm/trace_hv.h | 2 +- + 3 files changed, 5 insertions(+), 5 deletions(-) + +diff --git a/arch/powerpc/include/asm/kvm_book3s_64.h b/arch/powerpc/include/asm/kvm_book3s_64.h +index 2ef9a5f4e5d14..11065313d4c12 100644 +--- a/arch/powerpc/include/asm/kvm_book3s_64.h ++++ b/arch/powerpc/include/asm/kvm_book3s_64.h +@@ -684,8 +684,8 @@ int kvmhv_nestedv2_set_ptbl_entry(unsigned long lpid, u64 dw0, u64 dw1); + int kvmhv_nestedv2_parse_output(struct kvm_vcpu *vcpu); + int kvmhv_nestedv2_set_vpa(struct kvm_vcpu *vcpu, unsigned long vpa); + +-int kmvhv_counters_tracepoint_regfunc(void); +-void kmvhv_counters_tracepoint_unregfunc(void); ++int kvmhv_counters_tracepoint_regfunc(void); ++void kvmhv_counters_tracepoint_unregfunc(void); + int kvmhv_get_l2_counters_status(void); + void kvmhv_set_l2_counters_status(int cpu, bool status); + +diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c +index 59f67a44621b7..57b6c1ba84d47 100644 +--- a/arch/powerpc/kvm/book3s_hv.c ++++ b/arch/powerpc/kvm/book3s_hv.c +@@ -4154,7 +4154,7 @@ void kvmhv_set_l2_counters_status(int cpu, bool status) + lppaca_of(cpu).l2_counters_enable = 0; + } + +-int kmvhv_counters_tracepoint_regfunc(void) ++int kvmhv_counters_tracepoint_regfunc(void) + { + int cpu; + +@@ -4164,7 +4164,7 @@ int kmvhv_counters_tracepoint_regfunc(void) + return 0; + } + +-void kmvhv_counters_tracepoint_unregfunc(void) ++void kvmhv_counters_tracepoint_unregfunc(void) + { + int cpu; + +diff --git a/arch/powerpc/kvm/trace_hv.h b/arch/powerpc/kvm/trace_hv.h +index 77ebc724e6cdf..35fccaa575cc1 100644 +--- a/arch/powerpc/kvm/trace_hv.h ++++ b/arch/powerpc/kvm/trace_hv.h +@@ -538,7 +538,7 @@ TRACE_EVENT_FN_COND(kvmppc_vcpu_stats, + TP_printk("VCPU %d: l1_to_l2_cs_time=%llu ns l2_to_l1_cs_time=%llu ns l2_runtime=%llu ns", + __entry->vcpu_id, __entry->l1_to_l2_cs, + __entry->l2_to_l1_cs, __entry->l2_runtime), +- kmvhv_counters_tracepoint_regfunc, kmvhv_counters_tracepoint_unregfunc ++ kvmhv_counters_tracepoint_regfunc, kvmhv_counters_tracepoint_unregfunc + ); + #endif + #endif /* _TRACE_KVM_HV_H */ +-- +2.43.0 + diff --git a/queue-6.12/kvm-ppc-book3s-hv-stop-using-vc-dpdes-for-nested-kvm.patch b/queue-6.12/kvm-ppc-book3s-hv-stop-using-vc-dpdes-for-nested-kvm.patch new file mode 100644 index 00000000000..7b8a0361776 --- /dev/null +++ b/queue-6.12/kvm-ppc-book3s-hv-stop-using-vc-dpdes-for-nested-kvm.patch @@ -0,0 +1,113 @@ +From 8761ce53166648cbde918a5dade92443321f02ac Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Sat, 9 Nov 2024 12:02:56 +0530 +Subject: KVM: PPC: Book3S HV: Stop using vc->dpdes for nested KVM guests + +From: Gautam Menghani <gautam@linux.ibm.com> + +[ Upstream commit 0d3c6b28896f9889c8864dab469e0343a0ad1c0c ] + +commit 6398326b9ba1 ("KVM: PPC: Book3S HV P9: Stop using vc->dpdes") +introduced an optimization to use only vcpu->doorbell_request for SMT +emulation for Power9 and above guests, but the code for nested guests +still relies on the old way of handling doorbells, due to which an L2 +guest (see [1]) cannot be booted with XICS with SMT>1. The command to +repro this issue is: + +// To be run in L1 + +qemu-system-ppc64 \ + -drive file=rhel.qcow2,format=qcow2 \ + -m 20G \ + -smp 8,cores=1,threads=8 \ + -cpu host \ + -nographic \ + -machine pseries,ic-mode=xics -accel kvm + +Fix the plumbing to utilize vcpu->doorbell_request instead of vcore->dpdes +for nested KVM guests on P9 and above. + +[1] Terminology +1. L0 : PowerNV linux running with HV privileges +2. L1 : Pseries KVM guest running on top of L0 +2. L2 : Nested KVM guest running on top of L1 + +Fixes: 6398326b9ba1 ("KVM: PPC: Book3S HV P9: Stop using vc->dpdes") +Signed-off-by: Gautam Menghani <gautam@linux.ibm.com> +Signed-off-by: Michael Ellerman <mpe@ellerman.id.au> +Link: https://patch.msgid.link/20241109063301.105289-3-gautam@linux.ibm.com +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + arch/powerpc/kvm/book3s_hv.c | 9 +++++++++ + arch/powerpc/kvm/book3s_hv_nested.c | 14 ++++++++++---- + 2 files changed, 19 insertions(+), 4 deletions(-) + +diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c +index ad8dc4ccdaab9..b4c5295bdc31b 100644 +--- a/arch/powerpc/kvm/book3s_hv.c ++++ b/arch/powerpc/kvm/book3s_hv.c +@@ -4309,6 +4309,15 @@ static int kvmhv_vcpu_entry_p9_nested(struct kvm_vcpu *vcpu, u64 time_limit, uns + } + hvregs.hdec_expiry = time_limit; + ++ /* ++ * hvregs has the doorbell status, so zero it here which ++ * enables us to receive doorbells when H_ENTER_NESTED is ++ * in progress for this vCPU ++ */ ++ ++ if (vcpu->arch.doorbell_request) ++ vcpu->arch.doorbell_request = 0; ++ + /* + * When setting DEC, we must always deal with irq_work_raise + * via NMI vs setting DEC. The problem occurs right as we +diff --git a/arch/powerpc/kvm/book3s_hv_nested.c b/arch/powerpc/kvm/book3s_hv_nested.c +index 05f5220960c63..125440a606ee3 100644 +--- a/arch/powerpc/kvm/book3s_hv_nested.c ++++ b/arch/powerpc/kvm/book3s_hv_nested.c +@@ -32,7 +32,7 @@ void kvmhv_save_hv_regs(struct kvm_vcpu *vcpu, struct hv_guest_state *hr) + struct kvmppc_vcore *vc = vcpu->arch.vcore; + + hr->pcr = vc->pcr | PCR_MASK; +- hr->dpdes = vc->dpdes; ++ hr->dpdes = vcpu->arch.doorbell_request; + hr->hfscr = vcpu->arch.hfscr; + hr->tb_offset = vc->tb_offset; + hr->dawr0 = vcpu->arch.dawr0; +@@ -105,7 +105,7 @@ static void save_hv_return_state(struct kvm_vcpu *vcpu, + { + struct kvmppc_vcore *vc = vcpu->arch.vcore; + +- hr->dpdes = vc->dpdes; ++ hr->dpdes = vcpu->arch.doorbell_request; + hr->purr = vcpu->arch.purr; + hr->spurr = vcpu->arch.spurr; + hr->ic = vcpu->arch.ic; +@@ -143,7 +143,7 @@ static void restore_hv_regs(struct kvm_vcpu *vcpu, const struct hv_guest_state * + struct kvmppc_vcore *vc = vcpu->arch.vcore; + + vc->pcr = hr->pcr | PCR_MASK; +- vc->dpdes = hr->dpdes; ++ vcpu->arch.doorbell_request = hr->dpdes; + vcpu->arch.hfscr = hr->hfscr; + vcpu->arch.dawr0 = hr->dawr0; + vcpu->arch.dawrx0 = hr->dawrx0; +@@ -170,7 +170,13 @@ void kvmhv_restore_hv_return_state(struct kvm_vcpu *vcpu, + { + struct kvmppc_vcore *vc = vcpu->arch.vcore; + +- vc->dpdes = hr->dpdes; ++ /* ++ * This L2 vCPU might have received a doorbell while H_ENTER_NESTED was being handled. ++ * Make sure we preserve the doorbell if it was either: ++ * a) Sent after H_ENTER_NESTED was called on this vCPU (arch.doorbell_request would be 1) ++ * b) Doorbell was not handled and L2 exited for some other reason (hr->dpdes would be 1) ++ */ ++ vcpu->arch.doorbell_request = vcpu->arch.doorbell_request | hr->dpdes; + vcpu->arch.hfscr = hr->hfscr; + vcpu->arch.purr = hr->purr; + vcpu->arch.spurr = hr->spurr; +-- +2.43.0 + diff --git a/queue-6.12/leds-ktd2692-set-missing-timing-properties.patch b/queue-6.12/leds-ktd2692-set-missing-timing-properties.patch new file mode 100644 index 00000000000..ff49589289e --- /dev/null +++ b/queue-6.12/leds-ktd2692-set-missing-timing-properties.patch @@ -0,0 +1,40 @@ +From 7f08c6fddd77e94975640f5d5f00f9a8f06c6bda Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Sun, 3 Nov 2024 08:35:16 +0000 +Subject: leds: ktd2692: Set missing timing properties +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Raymond Hackley <raymondhackley@protonmail.com> + +[ Upstream commit 95c65546f03f888481eda98b499947252e1f3b20 ] + +props.timing is not set after commit b5a8c50e5c18 ("leds: ktd2692: Convert +to use ExpressWire library"). Set it with ktd2692_timing. + +Fixes: b5a8c50e5c18 ("leds: ktd2692: Convert to use ExpressWire library") +Signed-off-by: Raymond Hackley <raymondhackley@protonmail.com> +Acked-by: Duje Mihanović <duje.mihanovic@skole.hr> +Link: https://lore.kernel.org/r/20241103083505.49648-1-raymondhackley@protonmail.com +Signed-off-by: Lee Jones <lee@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/leds/flash/leds-ktd2692.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/leds/flash/leds-ktd2692.c b/drivers/leds/flash/leds-ktd2692.c +index 16a01a200c0b7..b92adf908793e 100644 +--- a/drivers/leds/flash/leds-ktd2692.c ++++ b/drivers/leds/flash/leds-ktd2692.c +@@ -292,6 +292,7 @@ static int ktd2692_probe(struct platform_device *pdev) + + fled_cdev = &led->fled_cdev; + led_cdev = &fled_cdev->led_cdev; ++ led->props.timing = ktd2692_timing; + + ret = ktd2692_parse_dt(led, &pdev->dev, &led_cfg); + if (ret) +-- +2.43.0 + diff --git a/queue-6.12/leds-max5970-fix-unreleased-fwnode_handle-in-probe-f.patch b/queue-6.12/leds-max5970-fix-unreleased-fwnode_handle-in-probe-f.patch new file mode 100644 index 00000000000..e046b247b1a --- /dev/null +++ b/queue-6.12/leds-max5970-fix-unreleased-fwnode_handle-in-probe-f.patch @@ -0,0 +1,51 @@ +From 706546f0fb78ce96c20b4b4ad922a06620cb7900 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Thu, 31 Oct 2024 17:30:30 +0100 +Subject: leds: max5970: Fix unreleased fwnode_handle in probe function + +From: Javier Carrasco <javier.carrasco.cruz@gmail.com> + +[ Upstream commit 02f58f97419c828f58e30f24f54395ac9be159c0 ] + +An object initialized via device_get_named_child_node() requires calls +to fwnode_handle_put() when it is no longer required to avoid leaking +memory. + +Add the automatic cleanup facility for 'led_node' to ensure that +fwnode_handle_put() is called in all execution paths. + +Fixes: 736214b4b02a ("leds: max5970: Add support for max5970") +Signed-off-by: Javier Carrasco <javier.carrasco.cruz@gmail.com> +Link: https://lore.kernel.org/r/20241031-max5970-of_node_put-v2-1-0ffe1f1d3bc9@gmail.com +Signed-off-by: Lee Jones <lee@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/leds/leds-max5970.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/drivers/leds/leds-max5970.c b/drivers/leds/leds-max5970.c +index 56a584311581a..285074c53b234 100644 +--- a/drivers/leds/leds-max5970.c ++++ b/drivers/leds/leds-max5970.c +@@ -45,7 +45,7 @@ static int max5970_led_set_brightness(struct led_classdev *cdev, + + static int max5970_led_probe(struct platform_device *pdev) + { +- struct fwnode_handle *led_node, *child; ++ struct fwnode_handle *child; + struct device *dev = &pdev->dev; + struct regmap *regmap; + struct max5970_led *ddata; +@@ -55,7 +55,8 @@ static int max5970_led_probe(struct platform_device *pdev) + if (!regmap) + return -ENODEV; + +- led_node = device_get_named_child_node(dev->parent, "leds"); ++ struct fwnode_handle *led_node __free(fwnode_handle) = ++ device_get_named_child_node(dev->parent, "leds"); + if (!led_node) + return -ENODEV; + +-- +2.43.0 + diff --git a/queue-6.12/libbpf-add-missing-per-arch-include-path.patch b/queue-6.12/libbpf-add-missing-per-arch-include-path.patch new file mode 100644 index 00000000000..34d6356c250 --- /dev/null +++ b/queue-6.12/libbpf-add-missing-per-arch-include-path.patch @@ -0,0 +1,44 @@ +From 525b256a92af52d0ea780a350426d394e373c830 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Fri, 27 Sep 2024 15:13:52 +0200 +Subject: libbpf: Add missing per-arch include path +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Björn Töpel <bjorn@rivosinc.com> + +[ Upstream commit 710fbca820c721cdd60fa8c5bbe9deb4c0788aae ] + +libbpf does not include the per-arch tools include path, e.g. +tools/arch/riscv/include. Some architectures depend those files to +build properly. + +Include tools/arch/$(SUBARCH)/include in the libbpf build. + +Fixes: 6d74d178fe6e ("tools: Add riscv barrier implementation") +Signed-off-by: Björn Töpel <bjorn@rivosinc.com> +Signed-off-by: Andrii Nakryiko <andrii@kernel.org> +Link: https://lore.kernel.org/bpf/20240927131355.350918-1-bjorn@kernel.org +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + tools/lib/bpf/Makefile | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/tools/lib/bpf/Makefile b/tools/lib/bpf/Makefile +index 1b22f0f372880..857a5f7b413d6 100644 +--- a/tools/lib/bpf/Makefile ++++ b/tools/lib/bpf/Makefile +@@ -61,7 +61,8 @@ ifndef VERBOSE + endif + + INCLUDES = -I$(or $(OUTPUT),.) \ +- -I$(srctree)/tools/include -I$(srctree)/tools/include/uapi ++ -I$(srctree)/tools/include -I$(srctree)/tools/include/uapi \ ++ -I$(srctree)/tools/arch/$(SRCARCH)/include + + export prefix libdir src obj + +-- +2.43.0 + diff --git a/queue-6.12/libbpf-fix-expected_attach_type-set-handling-in-prog.patch b/queue-6.12/libbpf-fix-expected_attach_type-set-handling-in-prog.patch new file mode 100644 index 00000000000..60273fb48cd --- /dev/null +++ b/queue-6.12/libbpf-fix-expected_attach_type-set-handling-in-prog.patch @@ -0,0 +1,68 @@ +From e34e8245073dda68099a3916c1ab6932a462dfc0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Wed, 25 Sep 2024 23:30:12 +0800 +Subject: libbpf: Fix expected_attach_type set handling in program load + callback + +From: Tao Chen <chen.dylane@gmail.com> + +[ Upstream commit a400d08b3014a4f4e939366bb6fd769b9caff4c9 ] + +Referenced commit broke the logic of resetting expected_attach_type to +zero for allowed program types if kernel doesn't yet support such field. +We do need to overwrite and preserve expected_attach_type for +multi-uprobe though, but that can be done explicitly in +libbpf_prepare_prog_load(). + +Fixes: 5902da6d8a52 ("libbpf: Add uprobe multi link support to bpf_program__attach_usdt") +Suggested-by: Jiri Olsa <jolsa@kernel.org> +Signed-off-by: Tao Chen <chen.dylane@gmail.com> +Signed-off-by: Andrii Nakryiko <andrii@kernel.org> +Link: https://lore.kernel.org/bpf/20240925153012.212866-1-chen.dylane@gmail.com +Signed-off-by: Alexei Starovoitov <ast@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + tools/lib/bpf/libbpf.c | 12 ++++++++---- + 1 file changed, 8 insertions(+), 4 deletions(-) + +diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c +index 219facd0e66e8..04389d00849f7 100644 +--- a/tools/lib/bpf/libbpf.c ++++ b/tools/lib/bpf/libbpf.c +@@ -7352,8 +7352,14 @@ static int libbpf_prepare_prog_load(struct bpf_program *prog, + opts->prog_flags |= BPF_F_XDP_HAS_FRAGS; + + /* special check for usdt to use uprobe_multi link */ +- if ((def & SEC_USDT) && kernel_supports(prog->obj, FEAT_UPROBE_MULTI_LINK)) ++ if ((def & SEC_USDT) && kernel_supports(prog->obj, FEAT_UPROBE_MULTI_LINK)) { ++ /* for BPF_TRACE_UPROBE_MULTI, user might want to query expected_attach_type ++ * in prog, and expected_attach_type we set in kernel is from opts, so we ++ * update both. ++ */ + prog->expected_attach_type = BPF_TRACE_UPROBE_MULTI; ++ opts->expected_attach_type = BPF_TRACE_UPROBE_MULTI; ++ } + + if ((def & SEC_ATTACH_BTF) && !prog->attach_btf_id) { + int btf_obj_fd = 0, btf_type_id = 0, err; +@@ -7443,6 +7449,7 @@ static int bpf_object_load_prog(struct bpf_object *obj, struct bpf_program *prog + load_attr.attach_btf_id = prog->attach_btf_id; + load_attr.kern_version = kern_version; + load_attr.prog_ifindex = prog->prog_ifindex; ++ load_attr.expected_attach_type = prog->expected_attach_type; + + /* specify func_info/line_info only if kernel supports them */ + if (obj->btf && btf__fd(obj->btf) >= 0 && kernel_supports(obj, FEAT_BTF_FUNC)) { +@@ -7474,9 +7481,6 @@ static int bpf_object_load_prog(struct bpf_object *obj, struct bpf_program *prog + insns_cnt = prog->insns_cnt; + } + +- /* allow prog_prepare_load_fn to change expected_attach_type */ +- load_attr.expected_attach_type = prog->expected_attach_type; +- + if (obj->gen_loader) { + bpf_gen__prog_load(obj->gen_loader, prog->type, prog->name, + license, insns, insns_cnt, &load_attr, +-- +2.43.0 + diff --git a/queue-6.12/libbpf-fix-output-.symtab-byte-order-during-linking.patch b/queue-6.12/libbpf-fix-output-.symtab-byte-order-during-linking.patch new file mode 100644 index 00000000000..d9740872e5c --- /dev/null +++ b/queue-6.12/libbpf-fix-output-.symtab-byte-order-during-linking.patch @@ -0,0 +1,40 @@ +From a713df2e0dccf2e2b302255915af7a2b69d45cd0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Mon, 16 Sep 2024 01:37:42 -0700 +Subject: libbpf: Fix output .symtab byte-order during linking + +From: Tony Ambardar <tony.ambardar@gmail.com> + +[ Upstream commit f896b4a5399e97af0b451fcf04754ed316935674 ] + +Object linking output data uses the default ELF_T_BYTE type for '.symtab' +section data, which disables any libelf-based translation. Explicitly set +the ELF_T_SYM type for output to restore libelf's byte-order conversion, +noting that input '.symtab' data is already correctly translated. + +Fixes: faf6ed321cf6 ("libbpf: Add BPF static linker APIs") +Signed-off-by: Tony Ambardar <tony.ambardar@gmail.com> +Signed-off-by: Andrii Nakryiko <andrii@kernel.org> +Link: https://lore.kernel.org/bpf/87868bfeccf3f51aec61260073f8778e9077050a.1726475448.git.tony.ambardar@gmail.com +Signed-off-by: Alexei Starovoitov <ast@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + tools/lib/bpf/linker.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/tools/lib/bpf/linker.c b/tools/lib/bpf/linker.c +index e0005c6ade88a..6985ab0f1ca9e 100644 +--- a/tools/lib/bpf/linker.c ++++ b/tools/lib/bpf/linker.c +@@ -396,6 +396,8 @@ static int init_output_elf(struct bpf_linker *linker, const char *file) + pr_warn_elf("failed to create SYMTAB data"); + return -EINVAL; + } ++ /* Ensure libelf translates byte-order of symbol records */ ++ sec->data->d_type = ELF_T_SYM; + + str_off = strset__add_str(linker->strtab_strs, sec->sec_name); + if (str_off < 0) +-- +2.43.0 + diff --git a/queue-6.12/libbpf-fix-sym_is_subprog-logic-for-weak-global-subp.patch b/queue-6.12/libbpf-fix-sym_is_subprog-logic-for-weak-global-subp.patch new file mode 100644 index 00000000000..9a20ff11601 --- /dev/null +++ b/queue-6.12/libbpf-fix-sym_is_subprog-logic-for-weak-global-subp.patch @@ -0,0 +1,49 @@ +From bd6103dbef6a6d6fe4112e3489cd89c1111d512f Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Tue, 8 Oct 2024 18:15:54 -0700 +Subject: libbpf: fix sym_is_subprog() logic for weak global subprogs + +From: Andrii Nakryiko <andrii@kernel.org> + +[ Upstream commit 4073213488be542f563eb4b2457ab4cbcfc2b738 ] + +sym_is_subprog() is incorrectly rejecting relocations against *weak* +global subprogs. Fix that by realizing that STB_WEAK is also a global +function. + +While it seems like verifier doesn't support taking an address of +non-static subprog right now, it's still best to fix support for it on +libbpf side, otherwise users will get a very confusing error during BPF +skeleton generation or static linking due to misinterpreted relocation: + + libbpf: prog 'handle_tp': bad map relo against 'foo' in section '.text' + Error: failed to open BPF object file: Relocation failed + +It's clearly not a map relocation, but is treated and reported as such +without this fix. + +Fixes: 53eddb5e04ac ("libbpf: Support subprog address relocation") +Signed-off-by: Andrii Nakryiko <andrii@kernel.org> +Link: https://lore.kernel.org/r/20241009011554.880168-1-andrii@kernel.org +Signed-off-by: Alexei Starovoitov <ast@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + tools/lib/bpf/libbpf.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c +index 04389d00849f7..dde03484cc42c 100644 +--- a/tools/lib/bpf/libbpf.c ++++ b/tools/lib/bpf/libbpf.c +@@ -3985,7 +3985,7 @@ static bool sym_is_subprog(const Elf64_Sym *sym, int text_shndx) + return true; + + /* global function */ +- return bind == STB_GLOBAL && type == STT_FUNC; ++ return (bind == STB_GLOBAL || bind == STB_WEAK) && type == STT_FUNC; + } + + static int find_extern_btf_id(const struct btf *btf, const char *ext_name) +-- +2.43.0 + diff --git a/queue-6.12/libbpf-move-global-data-mmap-ing-into-bpf_object__lo.patch b/queue-6.12/libbpf-move-global-data-mmap-ing-into-bpf_object__lo.patch new file mode 100644 index 00000000000..049cf9291c1 --- /dev/null +++ b/queue-6.12/libbpf-move-global-data-mmap-ing-into-bpf_object__lo.patch @@ -0,0 +1,180 @@ +From 6d949f8d7baa5208950bf14ed70e2fbdbf4dab65 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Tue, 22 Oct 2024 21:39:07 -0700 +Subject: libbpf: move global data mmap()'ing into bpf_object__load() + +From: Andrii Nakryiko <andrii@kernel.org> + +[ Upstream commit 137978f422516a128326df55c0ba23605f925e21 ] + +Since BPF skeleton inception libbpf has been doing mmap()'ing of global +data ARRAY maps in bpf_object__load_skeleton() API, which is used by +code generated .skel.h files (i.e., by BPF skeletons only). + +This is wrong because if BPF object is loaded through generic +bpf_object__load() API, global data maps won't be re-mmap()'ed after +load step, and memory pointers returned from bpf_map__initial_value() +would be wrong and won't reflect the actual memory shared between BPF +program and user space. + +bpf_map__initial_value() return result is rarely used after load, so +this went unnoticed for a really long time, until bpftrace project +attempted to load BPF object through generic bpf_object__load() API and +then used BPF subskeleton instantiated from such bpf_object. It turned +out that .data/.rodata/.bss data updates through such subskeleton was +"blackholed", all because libbpf wouldn't re-mmap() those maps during +bpf_object__load() phase. + +Long story short, this step should be done by libbpf regardless of BPF +skeleton usage, right after BPF map is created in the kernel. This patch +moves this functionality into bpf_object__populate_internal_map() to +achieve this. And bpf_object__load_skeleton() is now simple and almost +trivial, only propagating these mmap()'ed pointers into user-supplied +skeleton structs. + +We also do trivial adjustments to error reporting inside +bpf_object__populate_internal_map() for consistency with the rest of +libbpf's map-handling code. + +Reported-by: Alastair Robertson <ajor@meta.com> +Reported-by: Jonathan Wiepert <jwiepert@meta.com> +Fixes: d66562fba1ce ("libbpf: Add BPF object skeleton support") +Signed-off-by: Andrii Nakryiko <andrii@kernel.org> +Link: https://lore.kernel.org/r/20241023043908.3834423-3-andrii@kernel.org +Signed-off-by: Alexei Starovoitov <ast@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + tools/lib/bpf/libbpf.c | 83 ++++++++++++++++++++---------------------- + 1 file changed, 40 insertions(+), 43 deletions(-) + +diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c +index 1a54ea3a9208d..5ff643e60d09c 100644 +--- a/tools/lib/bpf/libbpf.c ++++ b/tools/lib/bpf/libbpf.c +@@ -5094,6 +5094,7 @@ bpf_object__populate_internal_map(struct bpf_object *obj, struct bpf_map *map) + enum libbpf_map_type map_type = map->libbpf_type; + char *cp, errmsg[STRERR_BUFSIZE]; + int err, zero = 0; ++ size_t mmap_sz; + + if (obj->gen_loader) { + bpf_gen__map_update_elem(obj->gen_loader, map - obj->maps, +@@ -5107,8 +5108,8 @@ bpf_object__populate_internal_map(struct bpf_object *obj, struct bpf_map *map) + if (err) { + err = -errno; + cp = libbpf_strerror_r(err, errmsg, sizeof(errmsg)); +- pr_warn("Error setting initial map(%s) contents: %s\n", +- map->name, cp); ++ pr_warn("map '%s': failed to set initial contents: %s\n", ++ bpf_map__name(map), cp); + return err; + } + +@@ -5118,11 +5119,43 @@ bpf_object__populate_internal_map(struct bpf_object *obj, struct bpf_map *map) + if (err) { + err = -errno; + cp = libbpf_strerror_r(err, errmsg, sizeof(errmsg)); +- pr_warn("Error freezing map(%s) as read-only: %s\n", +- map->name, cp); ++ pr_warn("map '%s': failed to freeze as read-only: %s\n", ++ bpf_map__name(map), cp); + return err; + } + } ++ ++ /* Remap anonymous mmap()-ed "map initialization image" as ++ * a BPF map-backed mmap()-ed memory, but preserving the same ++ * memory address. This will cause kernel to change process' ++ * page table to point to a different piece of kernel memory, ++ * but from userspace point of view memory address (and its ++ * contents, being identical at this point) will stay the ++ * same. This mapping will be released by bpf_object__close() ++ * as per normal clean up procedure. ++ */ ++ mmap_sz = bpf_map_mmap_sz(map); ++ if (map->def.map_flags & BPF_F_MMAPABLE) { ++ void *mmaped; ++ int prot; ++ ++ if (map->def.map_flags & BPF_F_RDONLY_PROG) ++ prot = PROT_READ; ++ else ++ prot = PROT_READ | PROT_WRITE; ++ mmaped = mmap(map->mmaped, mmap_sz, prot, MAP_SHARED | MAP_FIXED, map->fd, 0); ++ if (mmaped == MAP_FAILED) { ++ err = -errno; ++ pr_warn("map '%s': failed to re-mmap() contents: %d\n", ++ bpf_map__name(map), err); ++ return err; ++ } ++ map->mmaped = mmaped; ++ } else if (map->mmaped) { ++ munmap(map->mmaped, mmap_sz); ++ map->mmaped = NULL; ++ } ++ + return 0; + } + +@@ -5439,8 +5472,7 @@ bpf_object__create_maps(struct bpf_object *obj) + err = bpf_object__populate_internal_map(obj, map); + if (err < 0) + goto err_out; +- } +- if (map->def.type == BPF_MAP_TYPE_ARENA) { ++ } else if (map->def.type == BPF_MAP_TYPE_ARENA) { + map->mmaped = mmap((void *)(long)map->map_extra, + bpf_map_mmap_sz(map), PROT_READ | PROT_WRITE, + map->map_extra ? MAP_SHARED | MAP_FIXED : MAP_SHARED, +@@ -13881,46 +13913,11 @@ int bpf_object__load_skeleton(struct bpf_object_skeleton *s) + for (i = 0; i < s->map_cnt; i++) { + struct bpf_map_skeleton *map_skel = (void *)s->maps + i * s->map_skel_sz; + struct bpf_map *map = *map_skel->map; +- size_t mmap_sz = bpf_map_mmap_sz(map); +- int prot, map_fd = map->fd; +- void **mmaped = map_skel->mmaped; +- +- if (!mmaped) +- continue; +- +- if (!(map->def.map_flags & BPF_F_MMAPABLE)) { +- *mmaped = NULL; +- continue; +- } + +- if (map->def.type == BPF_MAP_TYPE_ARENA) { +- *mmaped = map->mmaped; ++ if (!map_skel->mmaped) + continue; +- } +- +- if (map->def.map_flags & BPF_F_RDONLY_PROG) +- prot = PROT_READ; +- else +- prot = PROT_READ | PROT_WRITE; + +- /* Remap anonymous mmap()-ed "map initialization image" as +- * a BPF map-backed mmap()-ed memory, but preserving the same +- * memory address. This will cause kernel to change process' +- * page table to point to a different piece of kernel memory, +- * but from userspace point of view memory address (and its +- * contents, being identical at this point) will stay the +- * same. This mapping will be released by bpf_object__close() +- * as per normal clean up procedure, so we don't need to worry +- * about it from skeleton's clean up perspective. +- */ +- *mmaped = mmap(map->mmaped, mmap_sz, prot, MAP_SHARED | MAP_FIXED, map_fd, 0); +- if (*mmaped == MAP_FAILED) { +- err = -errno; +- *mmaped = NULL; +- pr_warn("failed to re-mmap() map '%s': %d\n", +- bpf_map__name(map), err); +- return libbpf_err(err); +- } ++ *map_skel->mmaped = map->mmaped; + } + + return 0; +-- +2.43.0 + diff --git a/queue-6.12/libbpf-never-interpret-subprogs-in-.text-as-entry-pr.patch b/queue-6.12/libbpf-never-interpret-subprogs-in-.text-as-entry-pr.patch new file mode 100644 index 00000000000..a10163ed88c --- /dev/null +++ b/queue-6.12/libbpf-never-interpret-subprogs-in-.text-as-entry-pr.patch @@ -0,0 +1,47 @@ +From e6803c5f8684ef8f91ab2417be0b7758c7834fd2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Thu, 10 Oct 2024 14:17:30 -0700 +Subject: libbpf: never interpret subprogs in .text as entry programs + +From: Andrii Nakryiko <andrii@kernel.org> + +[ Upstream commit db089c9158c1d535a36dfc010e5db37fccea2561 ] + +Libbpf pre-1.0 had a legacy logic of allowing singular non-annotated +(i.e., not having explicit SEC() annotation) function to be treated as +sole entry BPF program (unless there were other explicit entry +programs). + +This behavior was dropped during libbpf 1.0 transition period (unless +LIBBPF_STRICT_SEC_NAME flag was unset in libbpf_mode). When 1.0 was +released and all the legacy behavior was removed, the bug slipped +through leaving this legacy behavior around. + +Fix this for good, as it actually causes very confusing behavior if BPF +object file only has subprograms, but no entry programs. + +Fixes: bd054102a8c7 ("libbpf: enforce strict libbpf 1.0 behaviors") +Signed-off-by: Andrii Nakryiko <andrii@kernel.org> +Link: https://lore.kernel.org/r/20241010211731.4121837-1-andrii@kernel.org +Signed-off-by: Alexei Starovoitov <ast@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + tools/lib/bpf/libbpf.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c +index dde03484cc42c..1a54ea3a9208d 100644 +--- a/tools/lib/bpf/libbpf.c ++++ b/tools/lib/bpf/libbpf.c +@@ -4389,7 +4389,7 @@ static int bpf_object__collect_externs(struct bpf_object *obj) + + static bool prog_is_subprog(const struct bpf_object *obj, const struct bpf_program *prog) + { +- return prog->sec_idx == obj->efile.text_shndx && obj->nr_programs > 1; ++ return prog->sec_idx == obj->efile.text_shndx; + } + + struct bpf_program * +-- +2.43.0 + diff --git a/queue-6.12/llc-improve-setsockopt-handling-of-malformed-user-in.patch b/queue-6.12/llc-improve-setsockopt-handling-of-malformed-user-in.patch new file mode 100644 index 00000000000..7ba82bd3428 --- /dev/null +++ b/queue-6.12/llc-improve-setsockopt-handling-of-malformed-user-in.patch @@ -0,0 +1,42 @@ +From 8c8e8c8312625e07f6f640ba5bfc94625d8d1b8f Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Tue, 19 Nov 2024 14:31:41 +0100 +Subject: llc: Improve setsockopt() handling of malformed user input + +From: Michal Luczaj <mhal@rbox.co> + +[ Upstream commit 1465036b10be4b8b00eb31c879e86de633ad74c1 ] + +copy_from_sockptr() is used incorrectly: return value is the number of +bytes that could not be copied. Since it's deprecated, switch to +copy_safe_from_sockptr(). + +Note: Keeping the `optlen != sizeof(int)` check as copy_safe_from_sockptr() +by itself would also accept optlen > sizeof(int). Which would allow a more +lenient handling of inputs. + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Suggested-by: David Wei <dw@davidwei.uk> +Signed-off-by: Michal Luczaj <mhal@rbox.co> +Signed-off-by: Paolo Abeni <pabeni@redhat.com> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + net/llc/af_llc.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/llc/af_llc.c b/net/llc/af_llc.c +index 4eb52add7103b..0259cde394ba0 100644 +--- a/net/llc/af_llc.c ++++ b/net/llc/af_llc.c +@@ -1098,7 +1098,7 @@ static int llc_ui_setsockopt(struct socket *sock, int level, int optname, + lock_sock(sk); + if (unlikely(level != SOL_LLC || optlen != sizeof(int))) + goto out; +- rc = copy_from_sockptr(&opt, optval, sizeof(opt)); ++ rc = copy_safe_from_sockptr(&opt, sizeof(opt), optval, optlen); + if (rc) + goto out; + rc = -EINVAL; +-- +2.43.0 + diff --git a/queue-6.12/locking-atomic-x86-use-alt_output_sp-for-__alternati.patch b/queue-6.12/locking-atomic-x86-use-alt_output_sp-for-__alternati.patch new file mode 100644 index 00000000000..0eec25a1831 --- /dev/null +++ b/queue-6.12/locking-atomic-x86-use-alt_output_sp-for-__alternati.patch @@ -0,0 +1,39 @@ +From 1ee52d4df2b258587a33029496f95648859a2241 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Sun, 3 Nov 2024 17:09:31 +0100 +Subject: locking/atomic/x86: Use ALT_OUTPUT_SP() for __alternative_atomic64() + +From: Uros Bizjak <ubizjak@gmail.com> + +[ Upstream commit 8b64db9733c2e4d30fd068d0b9dcef7b4424b035 ] + +CONFIG_X86_CMPXCHG64 variant of x86_32 __alternative_atomic64() +macro uses CALL instruction inside asm statement. Use +ALT_OUTPUT_SP() macro to add required dependence on %esp register. + +Fixes: 819165fb34b9 ("x86: Adjust asm constraints in atomic64 wrappers") +Signed-off-by: Uros Bizjak <ubizjak@gmail.com> +Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> +Link: https://lkml.kernel.org/r/20241103160954.3329-1-ubizjak@gmail.com +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + arch/x86/include/asm/atomic64_32.h | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/arch/x86/include/asm/atomic64_32.h b/arch/x86/include/asm/atomic64_32.h +index 1f650b4dde509..6c6e9b9f98a45 100644 +--- a/arch/x86/include/asm/atomic64_32.h ++++ b/arch/x86/include/asm/atomic64_32.h +@@ -51,7 +51,8 @@ static __always_inline s64 arch_atomic64_read_nonatomic(const atomic64_t *v) + #ifdef CONFIG_X86_CMPXCHG64 + #define __alternative_atomic64(f, g, out, in...) \ + asm volatile("call %c[func]" \ +- : out : [func] "i" (atomic64_##g##_cx8), ## in) ++ : ALT_OUTPUT_SP(out) \ ++ : [func] "i" (atomic64_##g##_cx8), ## in) + + #define ATOMIC64_DECL(sym) ATOMIC64_DECL_ONE(sym##_cx8) + #else +-- +2.43.0 + diff --git a/queue-6.12/locking-atomic-x86-use-alt_output_sp-for-__arch_-try.patch b/queue-6.12/locking-atomic-x86-use-alt_output_sp-for-__arch_-try.patch new file mode 100644 index 00000000000..f00a0a4aeb4 --- /dev/null +++ b/queue-6.12/locking-atomic-x86-use-alt_output_sp-for-__arch_-try.patch @@ -0,0 +1,50 @@ +From 43475031565904994d5547d1c220805a6898fb2c Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Sun, 3 Nov 2024 17:09:32 +0100 +Subject: locking/atomic/x86: Use ALT_OUTPUT_SP() for + __arch_{,try_}cmpxchg64_emu() + +From: Uros Bizjak <ubizjak@gmail.com> + +[ Upstream commit 25cf4fbb596d730476afcc0fb87a9d708db14078 ] + +x86_32 __arch_{,try_}cmpxchg64_emu()() macros use CALL instruction +inside asm statement. Use ALT_OUTPUT_SP() macro to add required +dependence on %esp register. + +Fixes: 79e1dd05d1a2 ("x86: Provide an alternative() based cmpxchg64()") +Signed-off-by: Uros Bizjak <ubizjak@gmail.com> +Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> +Link: https://lkml.kernel.org/r/20241103160954.3329-2-ubizjak@gmail.com +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + arch/x86/include/asm/cmpxchg_32.h | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/arch/x86/include/asm/cmpxchg_32.h b/arch/x86/include/asm/cmpxchg_32.h +index 62cef2113ca74..fd1282a783ddb 100644 +--- a/arch/x86/include/asm/cmpxchg_32.h ++++ b/arch/x86/include/asm/cmpxchg_32.h +@@ -94,7 +94,7 @@ static __always_inline bool __try_cmpxchg64_local(volatile u64 *ptr, u64 *oldp, + asm volatile(ALTERNATIVE(_lock_loc \ + "call cmpxchg8b_emu", \ + _lock "cmpxchg8b %a[ptr]", X86_FEATURE_CX8) \ +- : "+a" (o.low), "+d" (o.high) \ ++ : ALT_OUTPUT_SP("+a" (o.low), "+d" (o.high)) \ + : "b" (n.low), "c" (n.high), [ptr] "S" (_ptr) \ + : "memory"); \ + \ +@@ -123,8 +123,8 @@ static __always_inline u64 arch_cmpxchg64_local(volatile u64 *ptr, u64 old, u64 + "call cmpxchg8b_emu", \ + _lock "cmpxchg8b %a[ptr]", X86_FEATURE_CX8) \ + CC_SET(e) \ +- : CC_OUT(e) (ret), \ +- "+a" (o.low), "+d" (o.high) \ ++ : ALT_OUTPUT_SP(CC_OUT(e) (ret), \ ++ "+a" (o.low), "+d" (o.high)) \ + : "b" (n.low), "c" (n.high), [ptr] "S" (_ptr) \ + : "memory"); \ + \ +-- +2.43.0 + diff --git a/queue-6.12/locking-rt-add-sparse-annotation-preempt_rt-s-sleepi.patch b/queue-6.12/locking-rt-add-sparse-annotation-preempt_rt-s-sleepi.patch new file mode 100644 index 00000000000..644d3f26ccc --- /dev/null +++ b/queue-6.12/locking-rt-add-sparse-annotation-preempt_rt-s-sleepi.patch @@ -0,0 +1,71 @@ +From f3ebf6751c935ff27207516558feec7e9c94bd9f Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Mon, 12 Aug 2024 12:39:02 +0200 +Subject: locking/rt: Add sparse annotation PREEMPT_RT's sleeping locks. + +From: Sebastian Andrzej Siewior <bigeasy@linutronix.de> + +[ Upstream commit 52e0874fc16bd26e9ea1871e30ffb2c6dff187cf ] + +The sleeping locks on PREEMPT_RT (rt_spin_lock() and friends) lack +sparse annotation. Therefore a missing spin_unlock() won't be spotted by +sparse in a PREEMPT_RT build while it is noticed on a !PREEMPT_RT build. + +Add the __acquires/__releases macros to the lock/ unlock functions. The +trylock functions already use the __cond_lock() wrapper. + +Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> +Signed-off-by: Thomas Gleixner <tglx@linutronix.de> +Link: https://lore.kernel.org/all/20240812104200.2239232-2-bigeasy@linutronix.de +Stable-dep-of: 5c2e7736e20d ("rust: helpers: Avoid raw_spin_lock initialization for PREEMPT_RT") +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + include/linux/rwlock_rt.h | 10 +++++----- + include/linux/spinlock_rt.h | 8 ++++---- + 2 files changed, 9 insertions(+), 9 deletions(-) + +diff --git a/include/linux/rwlock_rt.h b/include/linux/rwlock_rt.h +index 8544ff05e594d..7d81fc6918ee8 100644 +--- a/include/linux/rwlock_rt.h ++++ b/include/linux/rwlock_rt.h +@@ -24,13 +24,13 @@ do { \ + __rt_rwlock_init(rwl, #rwl, &__key); \ + } while (0) + +-extern void rt_read_lock(rwlock_t *rwlock); ++extern void rt_read_lock(rwlock_t *rwlock) __acquires(rwlock); + extern int rt_read_trylock(rwlock_t *rwlock); +-extern void rt_read_unlock(rwlock_t *rwlock); +-extern void rt_write_lock(rwlock_t *rwlock); +-extern void rt_write_lock_nested(rwlock_t *rwlock, int subclass); ++extern void rt_read_unlock(rwlock_t *rwlock) __releases(rwlock); ++extern void rt_write_lock(rwlock_t *rwlock) __acquires(rwlock); ++extern void rt_write_lock_nested(rwlock_t *rwlock, int subclass) __acquires(rwlock); + extern int rt_write_trylock(rwlock_t *rwlock); +-extern void rt_write_unlock(rwlock_t *rwlock); ++extern void rt_write_unlock(rwlock_t *rwlock) __releases(rwlock); + + static __always_inline void read_lock(rwlock_t *rwlock) + { +diff --git a/include/linux/spinlock_rt.h b/include/linux/spinlock_rt.h +index 61c49b16f69ab..babc3e0287791 100644 +--- a/include/linux/spinlock_rt.h ++++ b/include/linux/spinlock_rt.h +@@ -32,10 +32,10 @@ do { \ + __rt_spin_lock_init(slock, #slock, &__key, true); \ + } while (0) + +-extern void rt_spin_lock(spinlock_t *lock); +-extern void rt_spin_lock_nested(spinlock_t *lock, int subclass); +-extern void rt_spin_lock_nest_lock(spinlock_t *lock, struct lockdep_map *nest_lock); +-extern void rt_spin_unlock(spinlock_t *lock); ++extern void rt_spin_lock(spinlock_t *lock) __acquires(lock); ++extern void rt_spin_lock_nested(spinlock_t *lock, int subclass) __acquires(lock); ++extern void rt_spin_lock_nest_lock(spinlock_t *lock, struct lockdep_map *nest_lock) __acquires(lock); ++extern void rt_spin_unlock(spinlock_t *lock) __releases(lock); + extern void rt_spin_lock_unlock(spinlock_t *lock); + extern int rt_spin_trylock_bh(spinlock_t *lock); + extern int rt_spin_trylock(spinlock_t *lock); +-- +2.43.0 + diff --git a/queue-6.12/loongarch-bpf-sign-extend-return-values.patch b/queue-6.12/loongarch-bpf-sign-extend-return-values.patch new file mode 100644 index 00000000000..a23dfc7584a --- /dev/null +++ b/queue-6.12/loongarch-bpf-sign-extend-return-values.patch @@ -0,0 +1,91 @@ +From 2005821530b98695e1cfd398106fa5816c419964 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Fri, 22 Nov 2024 15:47:48 +0800 +Subject: LoongArch: BPF: Sign-extend return values + +From: Tiezhu Yang <yangtiezhu@loongson.cn> + +[ Upstream commit 73c359d1d356cf10236ccd358bd55edab33e9424 ] + +(1) Description of Problem: + +When testing BPF JIT with the latest compiler toolchains on LoongArch, +there exist some strange failed test cases, dmesg shows something like +this: + + # dmesg -t | grep FAIL | head -1 + ... ret -3 != -3 (0xfffffffd != 0xfffffffd)FAIL ... + +(2) Steps to Reproduce: + + # echo 1 > /proc/sys/net/core/bpf_jit_enable + # modprobe test_bpf + +(3) Additional Info: + +There are no failed test cases compiled with the lower version of GCC +such as 13.3.0, while the problems only appear with higher version of +GCC such as 14.2.0. + +This is because the problems were hidden by the lower version of GCC due +to redundant sign extension instructions generated by compiler, but with +optimization of higher version of GCC, the sign extension instructions +have been removed. + +(4) Root Cause Analysis: + +The LoongArch architecture does not expose sub-registers, and hold all +32-bit values in a sign-extended format. While BPF, on the other hand, +exposes sub-registers, and use zero-extension (similar to arm64/x86). + +This has led to some subtle bugs, where a BPF JITted program has not +sign-extended the a0 register (return value in LoongArch land), passed +the return value up the kernel, for example: + + | int from_bpf(void); + | + | long foo(void) + | { + | return from_bpf(); + | } + +Here, a0 would be 0xffffffff instead of the expected 0xffffffffffffffff. + +Internally, the LoongArch JIT uses a5 as a dedicated register for BPF +return values. That is to say, the LoongArch BPF uses a5 for BPF return +values, which are zero-extended, whereas the LoongArch ABI uses a0 which +is sign-extended. + +(5) Final Solution: + +Keep a5 zero-extended, but explicitly sign-extend a0 (which is used +outside BPF land). Because libbpf currently defines the return value +of an ebpf program as a 32-bit unsigned integer, just use addi.w to +extend bit 31 into bits 63 through 32 of a5 to a0. This is similar to +commit 2f1b0d3d7331 ("riscv, bpf: Sign-extend return values"). + +Fixes: 5dc615520c4d ("LoongArch: Add BPF JIT support") +Acked-by: John Fastabend <john.fastabend@gmail.com> +Signed-off-by: Tiezhu Yang <yangtiezhu@loongson.cn> +Signed-off-by: Huacai Chen <chenhuacai@loongson.cn> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + arch/loongarch/net/bpf_jit.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/arch/loongarch/net/bpf_jit.c b/arch/loongarch/net/bpf_jit.c +index 7dbefd4ba2107..dd350cba1252f 100644 +--- a/arch/loongarch/net/bpf_jit.c ++++ b/arch/loongarch/net/bpf_jit.c +@@ -179,7 +179,7 @@ static void __build_epilogue(struct jit_ctx *ctx, bool is_tail_call) + + if (!is_tail_call) { + /* Set return value */ +- move_reg(ctx, LOONGARCH_GPR_A0, regmap[BPF_REG_0]); ++ emit_insn(ctx, addiw, LOONGARCH_GPR_A0, regmap[BPF_REG_0], 0); + /* Return to the caller */ + emit_insn(ctx, jirl, LOONGARCH_GPR_RA, LOONGARCH_GPR_ZERO, 0); + } else { +-- +2.43.0 + diff --git a/queue-6.12/loongarch-fix-build-failure-with-gcc-15-std-gnu23.patch b/queue-6.12/loongarch-fix-build-failure-with-gcc-15-std-gnu23.patch new file mode 100644 index 00000000000..22411fafb89 --- /dev/null +++ b/queue-6.12/loongarch-fix-build-failure-with-gcc-15-std-gnu23.patch @@ -0,0 +1,68 @@ +From defe56d3f49ebb44ed75930e79adb8bad528a06a Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Fri, 22 Nov 2024 15:47:47 +0800 +Subject: LoongArch: Fix build failure with GCC 15 (-std=gnu23) + +From: Tiezhu Yang <yangtiezhu@loongson.cn> + +[ Upstream commit 947d5d036c788156f09e83e7f16322ffe8124384 ] + +Whenever I try to build the kernel with upcoming GCC 15 which defaults +to -std=gnu23 I get a build failure: + + CC arch/loongarch/vdso/vgetcpu.o +In file included from ./include/uapi/linux/posix_types.h:5, + from ./include/uapi/linux/types.h:14, + from ./include/linux/types.h:6, + from ./include/linux/kasan-checks.h:5, + from ./include/asm-generic/rwonce.h:26, + from ./arch/loongarch/include/generated/asm/rwonce.h:1, + from ./include/linux/compiler.h:317, + from ./include/asm-generic/bug.h:5, + from ./arch/loongarch/include/asm/bug.h:60, + from ./include/linux/bug.h:5, + from ./include/linux/mmdebug.h:5, + from ./include/linux/mm.h:6, + from ./arch/loongarch/include/asm/vdso.h:10, + from arch/loongarch/vdso/vgetcpu.c:6: +./include/linux/stddef.h:11:9: error: expected identifier before 'false' + 11 | false = 0, + | ^~~~~ +./include/linux/types.h:35:33: error: two or more data types in declaration specifiers + 35 | typedef _Bool bool; + | ^~~~ +./include/linux/types.h:35:1: warning: useless type name in empty declaration + 35 | typedef _Bool bool; + | ^~~~~~~ + +The kernel builds explicitly with -std=gnu11 in top Makefile, but +arch/loongarch/vdso does not use KBUILD_CFLAGS from the rest of the +kernel, just add -std=gnu11 flag to arch/loongarch/vdso/Makefile. + +By the way, commit e8c07082a810 ("Kbuild: move to -std=gnu11") did a +similar change for arch/arm64/kernel/vdso32/Makefile. + +Fixes: c6b99bed6b8f ("LoongArch: Add VDSO and VSYSCALL support") +Signed-off-by: Tiezhu Yang <yangtiezhu@loongson.cn> +Signed-off-by: Huacai Chen <chenhuacai@loongson.cn> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + arch/loongarch/vdso/Makefile | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/arch/loongarch/vdso/Makefile b/arch/loongarch/vdso/Makefile +index 40c1175823d61..fdde1bcd4e266 100644 +--- a/arch/loongarch/vdso/Makefile ++++ b/arch/loongarch/vdso/Makefile +@@ -19,7 +19,7 @@ ccflags-vdso := \ + cflags-vdso := $(ccflags-vdso) \ + -isystem $(shell $(CC) -print-file-name=include) \ + $(filter -W%,$(filter-out -Wa$(comma)%,$(KBUILD_CFLAGS))) \ +- -O2 -g -fno-strict-aliasing -fno-common -fno-builtin \ ++ -std=gnu11 -O2 -g -fno-strict-aliasing -fno-common -fno-builtin \ + -fno-stack-protector -fno-jump-tables -DDISABLE_BRANCH_PROFILING \ + $(call cc-option, -fno-asynchronous-unwind-tables) \ + $(call cc-option, -fno-stack-protector) +-- +2.43.0 + diff --git a/queue-6.12/loop-fix-type-of-block-size.patch b/queue-6.12/loop-fix-type-of-block-size.patch new file mode 100644 index 00000000000..f8d09ad27b3 --- /dev/null +++ b/queue-6.12/loop-fix-type-of-block-size.patch @@ -0,0 +1,77 @@ +From b9b7722cd3285c1c16d1b7bc6842443d014fa3e6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Sat, 9 Nov 2024 10:27:44 +0800 +Subject: loop: fix type of block size + +From: Li Wang <liwang@redhat.com> + +[ Upstream commit 8e604cac499248c75ad3a26695a743ff879ded5c ] + +PAGE_SIZE may be 64K, and the max block size can be PAGE_SIZE, so any +variable for holding block size can't be defined as 'unsigned short'. + +Unfortunately commit 473516b36193 ("loop: use the atomic queue limits +update API") passes 'bsize' with type of 'unsigned short' to +loop_reconfigure_limits(), and causes LTP/ioctl_loop06 test failure: + + 12 ioctl_loop06.c:76: TINFO: Using LOOP_SET_BLOCK_SIZE with arg > PAGE_SIZE + 13 ioctl_loop06.c:59: TFAIL: Set block size succeed unexpectedly + ... + 18 ioctl_loop06.c:76: TINFO: Using LOOP_CONFIGURE with block_size > PAGE_SIZE + 19 ioctl_loop06.c:59: TFAIL: Set block size succeed unexpectedly + +Fixes the issue by defining 'block size' variable with 'unsigned int', which is +aligned with block layer's definition. + +(improve commit log & add fixes tag) + +Fixes: 473516b36193 ("loop: use the atomic queue limits update API") +Cc: John Garry <john.g.garry@oracle.com> +Cc: Stefan Hajnoczi <stefanha@redhat.com> +Cc: Christoph Hellwig <hch@lst.de> +Reviewed-by: Damien Le Moal <dlemoal@kernel.org> +Reviewed-by: Jan Stancek <jstancek@redhat.com> +Signed-off-by: Li Wang <liwang@redhat.com> +Signed-off-by: Ming Lei <ming.lei@redhat.com> +Reviewed-by: John Garry <john.g.garry@oracle.com> +Link: https://lore.kernel.org/r/20241109022744.1126003-1-ming.lei@redhat.com +Signed-off-by: Jens Axboe <axboe@kernel.dk> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/block/loop.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/drivers/block/loop.c b/drivers/block/loop.c +index 78a7bb28defe4..86cc3b19faae8 100644 +--- a/drivers/block/loop.c ++++ b/drivers/block/loop.c +@@ -173,7 +173,7 @@ static loff_t get_loop_size(struct loop_device *lo, struct file *file) + static bool lo_bdev_can_use_dio(struct loop_device *lo, + struct block_device *backing_bdev) + { +- unsigned short sb_bsize = bdev_logical_block_size(backing_bdev); ++ unsigned int sb_bsize = bdev_logical_block_size(backing_bdev); + + if (queue_logical_block_size(lo->lo_queue) < sb_bsize) + return false; +@@ -977,7 +977,7 @@ loop_set_status_from_info(struct loop_device *lo, + return 0; + } + +-static unsigned short loop_default_blocksize(struct loop_device *lo, ++static unsigned int loop_default_blocksize(struct loop_device *lo, + struct block_device *backing_bdev) + { + /* In case of direct I/O, match underlying block size */ +@@ -986,7 +986,7 @@ static unsigned short loop_default_blocksize(struct loop_device *lo, + return SECTOR_SIZE; + } + +-static int loop_reconfigure_limits(struct loop_device *lo, unsigned short bsize) ++static int loop_reconfigure_limits(struct loop_device *lo, unsigned int bsize) + { + struct file *file = lo->lo_backing_file; + struct inode *inode = file->f_mapping->host; +-- +2.43.0 + diff --git a/queue-6.12/m68k-coldfire-device.c-only-build-fec-when-hw-macros.patch b/queue-6.12/m68k-coldfire-device.c-only-build-fec-when-hw-macros.patch new file mode 100644 index 00000000000..70430d6874b --- /dev/null +++ b/queue-6.12/m68k-coldfire-device.c-only-build-fec-when-hw-macros.patch @@ -0,0 +1,77 @@ +From 1129cfadcd08722cc1604fc014243ff4e2909901 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Tue, 29 Oct 2024 22:43:15 +0100 +Subject: m68k: coldfire/device.c: only build FEC when HW macros are defined + +From: Antonio Quartulli <antonio@mandelbit.com> + +[ Upstream commit 63a24cf8cc330e5a68ebd2e20ae200096974c475 ] + +When CONFIG_FEC is set (due to COMPILE_TEST) along with +CONFIG_M54xx, coldfire/device.c has compile errors due to +missing MCFEC_* and MCF_IRQ_FEC_* symbols. + +Make the whole FEC blocks dependent on having the HW macros +defined, rather than on CONFIG_FEC itself. + +This fix is very similar to commit e6e1e7b19fa1 ("m68k: coldfire/device.c: only build for MCF_EDMA when h/w macros are defined") + +Fixes: b7ce7f0d0efc ("m68knommu: merge common ColdFire FEC platform setup code") +To: Greg Ungerer <gerg@linux-m68k.org> +To: Geert Uytterhoeven <geert@linux-m68k.org> +Cc: linux-m68k@lists.linux-m68k.org +Cc: linux-kernel@vger.kernel.org +Signed-off-by: Antonio Quartulli <antonio@mandelbit.com> +Signed-off-by: Greg Ungerer <gerg@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + arch/m68k/coldfire/device.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/arch/m68k/coldfire/device.c b/arch/m68k/coldfire/device.c +index 7dab46728aeda..b6958ec2a220c 100644 +--- a/arch/m68k/coldfire/device.c ++++ b/arch/m68k/coldfire/device.c +@@ -93,7 +93,7 @@ static struct platform_device mcf_uart = { + .dev.platform_data = mcf_uart_platform_data, + }; + +-#if IS_ENABLED(CONFIG_FEC) ++#ifdef MCFFEC_BASE0 + + #ifdef CONFIG_M5441x + #define FEC_NAME "enet-fec" +@@ -145,6 +145,7 @@ static struct platform_device mcf_fec0 = { + .platform_data = FEC_PDATA, + } + }; ++#endif /* MCFFEC_BASE0 */ + + #ifdef MCFFEC_BASE1 + static struct resource mcf_fec1_resources[] = { +@@ -182,7 +183,6 @@ static struct platform_device mcf_fec1 = { + } + }; + #endif /* MCFFEC_BASE1 */ +-#endif /* CONFIG_FEC */ + + #if IS_ENABLED(CONFIG_SPI_COLDFIRE_QSPI) + /* +@@ -624,12 +624,12 @@ static struct platform_device mcf_flexcan0 = { + + static struct platform_device *mcf_devices[] __initdata = { + &mcf_uart, +-#if IS_ENABLED(CONFIG_FEC) ++#ifdef MCFFEC_BASE0 + &mcf_fec0, ++#endif + #ifdef MCFFEC_BASE1 + &mcf_fec1, + #endif +-#endif + #if IS_ENABLED(CONFIG_SPI_COLDFIRE_QSPI) + &mcf_qspi, + #endif +-- +2.43.0 + diff --git a/queue-6.12/m68k-mcfgpio-fix-incorrect-register-offset-for-confi.patch b/queue-6.12/m68k-mcfgpio-fix-incorrect-register-offset-for-confi.patch new file mode 100644 index 00000000000..77c518da099 --- /dev/null +++ b/queue-6.12/m68k-mcfgpio-fix-incorrect-register-offset-for-confi.patch @@ -0,0 +1,37 @@ +From a9aac36ebd1a36fc954820ebe17eadbce0d48626 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Wed, 16 Oct 2024 09:24:35 +0200 +Subject: m68k: mcfgpio: Fix incorrect register offset for CONFIG_M5441x + +From: Jean-Michel Hautbois <jeanmichel.hautbois@yoseli.org> + +[ Upstream commit f212140962c93cd5da43283a18e31681540fc23d ] + +Fix a typo in the CONFIG_M5441x preprocessor condition, where the GPIO +register offset was incorrectly set to 8 instead of 0. This prevented +proper GPIO configuration for m5441x targets. + +Fixes: bea8bcb12da0 ("m68knommu: Add support for the Coldfire m5441x.") +Signed-off-by: Jean-Michel Hautbois <jeanmichel.hautbois@yoseli.org> +Signed-off-by: Greg Ungerer <gerg@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + arch/m68k/include/asm/mcfgpio.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/arch/m68k/include/asm/mcfgpio.h b/arch/m68k/include/asm/mcfgpio.h +index 019f244395464..9c91ecdafc453 100644 +--- a/arch/m68k/include/asm/mcfgpio.h ++++ b/arch/m68k/include/asm/mcfgpio.h +@@ -136,7 +136,7 @@ static inline void gpio_free(unsigned gpio) + * read-modify-write as well as those controlled by the EPORT and GPIO modules. + */ + #define MCFGPIO_SCR_START 40 +-#elif defined(CONFIGM5441x) ++#elif defined(CONFIG_M5441x) + /* The m5441x EPORT doesn't have its own GPIO port, uses PORT C */ + #define MCFGPIO_SCR_START 0 + #else +-- +2.43.0 + diff --git a/queue-6.12/m68k-mvme147-fix-scsi-controller-irq-numbers.patch b/queue-6.12/m68k-mvme147-fix-scsi-controller-irq-numbers.patch new file mode 100644 index 00000000000..0114ec3e2da --- /dev/null +++ b/queue-6.12/m68k-mvme147-fix-scsi-controller-irq-numbers.patch @@ -0,0 +1,46 @@ +From f1277b2cbe340f3c3b720e7fa405aa502992de77 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Thu, 3 Oct 2024 13:29:47 +1000 +Subject: m68k: mvme147: Fix SCSI controller IRQ numbers + +From: Daniel Palmer <daniel@0x0f.com> + +[ Upstream commit 47bc874427382018fa2e3e982480e156271eee70 ] + +Sometime long ago the m68k IRQ code was refactored and the interrupt +numbers for SCSI controller on this board ended up wrong, and it hasn't +worked since. + +The PCC adds 0x40 to the vector for its interrupts so they end up in +the user interrupt range. Hence, the kernel number should be the kernel +offset for user interrupt range + the PCC interrupt number. + +Fixes: 200a3d352cd5 ("[PATCH] m68k: convert VME irq code") +Signed-off-by: Daniel Palmer <daniel@0x0f.com> +Reviewed-by: Finn Thain <fthain@linux-m68k.org> +Reviewed-by: Geert Uytterhoeven <geert@linux-m68k.org> +Link: https://lore.kernel.org/0e7636a21a0274eea35bfd5d874459d5078e97cc.1727926187.git.fthain@linux-m68k.org +Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + arch/m68k/include/asm/mvme147hw.h | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/arch/m68k/include/asm/mvme147hw.h b/arch/m68k/include/asm/mvme147hw.h +index e28eb1c0e0bfb..dbf88059e47a4 100644 +--- a/arch/m68k/include/asm/mvme147hw.h ++++ b/arch/m68k/include/asm/mvme147hw.h +@@ -93,8 +93,8 @@ struct pcc_regs { + #define M147_SCC_B_ADDR 0xfffe3000 + #define M147_SCC_PCLK 5000000 + +-#define MVME147_IRQ_SCSI_PORT (IRQ_USER+0x45) +-#define MVME147_IRQ_SCSI_DMA (IRQ_USER+0x46) ++#define MVME147_IRQ_SCSI_PORT (IRQ_USER + 5) ++#define MVME147_IRQ_SCSI_DMA (IRQ_USER + 6) + + /* SCC interrupts, for MVME147 */ + +-- +2.43.0 + diff --git a/queue-6.12/m68k-mvme147-reinstate-early-console.patch b/queue-6.12/m68k-mvme147-reinstate-early-console.patch new file mode 100644 index 00000000000..f8ef7341706 --- /dev/null +++ b/queue-6.12/m68k-mvme147-reinstate-early-console.patch @@ -0,0 +1,113 @@ +From 63109ee2f4af07b75bad1dce09fac867f56ff494 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Wed, 6 Nov 2024 10:51:24 +1100 +Subject: m68k: mvme147: Reinstate early console + +From: Daniel Palmer <daniel@0x0f.com> + +[ Upstream commit 077b33b9e2833ff25050d986178a2c4c4036cbac ] + +Commit a38eaa07a0ce ("m68k/mvme147: config.c - Remove unused +functions"), removed the console functionality for the mvme147 instead +of wiring it up to an early console. Put the console write function +back and wire it up like mvme16x does so it's possible to see Linux boot +on this fine hardware once more. + +Fixes: a38eaa07a0ce ("m68k/mvme147: config.c - Remove unused functions") +Signed-off-by: Daniel Palmer <daniel@0x0f.com> +Co-developed-by: Finn Thain <fthain@linux-m68k.org> +Signed-off-by: Finn Thain <fthain@linux-m68k.org> +Reviewed-by: Geert Uytterhoeven <geert@linux-m68k.org> +Link: https://lore.kernel.org/a82e8f0068a8722996a0ccfe666abb5e0a5c120d.1730850684.git.fthain@linux-m68k.org +Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + arch/m68k/kernel/early_printk.c | 5 ++++- + arch/m68k/mvme147/config.c | 30 ++++++++++++++++++++++++++++++ + arch/m68k/mvme147/mvme147.h | 6 ++++++ + 3 files changed, 40 insertions(+), 1 deletion(-) + create mode 100644 arch/m68k/mvme147/mvme147.h + +diff --git a/arch/m68k/kernel/early_printk.c b/arch/m68k/kernel/early_printk.c +index 3cc944df04f65..f11ef9f1f56fc 100644 +--- a/arch/m68k/kernel/early_printk.c ++++ b/arch/m68k/kernel/early_printk.c +@@ -13,6 +13,7 @@ + #include <asm/setup.h> + + ++#include "../mvme147/mvme147.h" + #include "../mvme16x/mvme16x.h" + + asmlinkage void __init debug_cons_nputs(const char *s, unsigned n); +@@ -22,7 +23,9 @@ static void __ref debug_cons_write(struct console *c, + { + #if !(defined(CONFIG_SUN3) || defined(CONFIG_M68000) || \ + defined(CONFIG_COLDFIRE)) +- if (MACH_IS_MVME16x) ++ if (MACH_IS_MVME147) ++ mvme147_scc_write(c, s, n); ++ else if (MACH_IS_MVME16x) + mvme16x_cons_write(c, s, n); + else + debug_cons_nputs(s, n); +diff --git a/arch/m68k/mvme147/config.c b/arch/m68k/mvme147/config.c +index 8b5dc07f0811f..cc2fb0a83cf0b 100644 +--- a/arch/m68k/mvme147/config.c ++++ b/arch/m68k/mvme147/config.c +@@ -32,6 +32,7 @@ + #include <asm/mvme147hw.h> + #include <asm/config.h> + ++#include "mvme147.h" + + static void mvme147_get_model(char *model); + extern void mvme147_sched_init(void); +@@ -185,3 +186,32 @@ int mvme147_hwclk(int op, struct rtc_time *t) + } + return 0; + } ++ ++static void scc_delay(void) ++{ ++ __asm__ __volatile__ ("nop; nop;"); ++} ++ ++static void scc_write(char ch) ++{ ++ do { ++ scc_delay(); ++ } while (!(in_8(M147_SCC_A_ADDR) & BIT(2))); ++ scc_delay(); ++ out_8(M147_SCC_A_ADDR, 8); ++ scc_delay(); ++ out_8(M147_SCC_A_ADDR, ch); ++} ++ ++void mvme147_scc_write(struct console *co, const char *str, unsigned int count) ++{ ++ unsigned long flags; ++ ++ local_irq_save(flags); ++ while (count--) { ++ if (*str == '\n') ++ scc_write('\r'); ++ scc_write(*str++); ++ } ++ local_irq_restore(flags); ++} +diff --git a/arch/m68k/mvme147/mvme147.h b/arch/m68k/mvme147/mvme147.h +new file mode 100644 +index 0000000000000..140bc98b0102a +--- /dev/null ++++ b/arch/m68k/mvme147/mvme147.h +@@ -0,0 +1,6 @@ ++/* SPDX-License-Identifier: GPL-2.0-only */ ++ ++struct console; ++ ++/* config.c */ ++void mvme147_scc_write(struct console *co, const char *str, unsigned int count); +-- +2.43.0 + diff --git a/queue-6.12/mailbox-arm_mhuv2-clean-up-loop-in-get_irq_chan_comb.patch b/queue-6.12/mailbox-arm_mhuv2-clean-up-loop-in-get_irq_chan_comb.patch new file mode 100644 index 00000000000..08b09ea27e5 --- /dev/null +++ b/queue-6.12/mailbox-arm_mhuv2-clean-up-loop-in-get_irq_chan_comb.patch @@ -0,0 +1,58 @@ +From bfe92dc620aa6d3bae7422b284888669492f941b Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Thu, 14 Nov 2024 12:00:12 +0300 +Subject: mailbox: arm_mhuv2: clean up loop in get_irq_chan_comb() + +From: Dan Carpenter <dan.carpenter@linaro.org> + +[ Upstream commit 192a16a3430ca459c4e986f3d10758c4d6b1aa29 ] + +Both the inner and outer loops in this code use the "i" iterator. +The inner loop should really use a different iterator. + +It doesn't affect things in practice because the data comes from the +device tree. The "protocol" and "windows" variables are going to be +zero. That means we're always going to hit the "return &chans[channel];" +statement and we're not going to want to iterate through the outer +loop again. + +Still it's worth fixing this for future use cases. + +Fixes: 5a6338cce9f4 ("mailbox: arm_mhuv2: Add driver") +Signed-off-by: Dan Carpenter <dan.carpenter@linaro.org> +Acked-by: Viresh Kumar <viresh.kumar@linaro.org> +Signed-off-by: Jassi Brar <jassisinghbrar@gmail.com> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/mailbox/arm_mhuv2.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/drivers/mailbox/arm_mhuv2.c b/drivers/mailbox/arm_mhuv2.c +index 0ec21dcdbde72..cff7c343ee082 100644 +--- a/drivers/mailbox/arm_mhuv2.c ++++ b/drivers/mailbox/arm_mhuv2.c +@@ -500,7 +500,7 @@ static const struct mhuv2_protocol_ops mhuv2_data_transfer_ops = { + static struct mbox_chan *get_irq_chan_comb(struct mhuv2 *mhu, u32 __iomem *reg) + { + struct mbox_chan *chans = mhu->mbox.chans; +- int channel = 0, i, offset = 0, windows, protocol, ch_wn; ++ int channel = 0, i, j, offset = 0, windows, protocol, ch_wn; + u32 stat; + + for (i = 0; i < MHUV2_CMB_INT_ST_REG_CNT; i++) { +@@ -510,9 +510,9 @@ static struct mbox_chan *get_irq_chan_comb(struct mhuv2 *mhu, u32 __iomem *reg) + + ch_wn = i * MHUV2_STAT_BITS + __builtin_ctz(stat); + +- for (i = 0; i < mhu->length; i += 2) { +- protocol = mhu->protocols[i]; +- windows = mhu->protocols[i + 1]; ++ for (j = 0; j < mhu->length; j += 2) { ++ protocol = mhu->protocols[j]; ++ windows = mhu->protocols[j + 1]; + + if (ch_wn >= offset + windows) { + if (protocol == DOORBELL) +-- +2.43.0 + diff --git a/queue-6.12/mailbox-mtk-cmdq-fix-wrong-use-of-sizeof-in-cmdq_get.patch b/queue-6.12/mailbox-mtk-cmdq-fix-wrong-use-of-sizeof-in-cmdq_get.patch new file mode 100644 index 00000000000..672494c2aa1 --- /dev/null +++ b/queue-6.12/mailbox-mtk-cmdq-fix-wrong-use-of-sizeof-in-cmdq_get.patch @@ -0,0 +1,36 @@ +From e4a87ec87f3a59190b475867ec2c90f076815148 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Tue, 29 Oct 2024 21:16:28 +0800 +Subject: mailbox: mtk-cmdq: fix wrong use of sizeof in cmdq_get_clocks() + +From: Yang Yingliang <yangyingliang@huawei.com> + +[ Upstream commit 271ee263cc8771982809185007181ca10346fe73 ] + +It should be size of the struct clk_bulk_data, not data pointer pass to +devm_kcalloc(). + +Fixes: aa1609f571ca ("mailbox: mtk-cmdq: Dynamically allocate clk_bulk_data structure") +Signed-off-by: Yang Yingliang <yangyingliang@huawei.com> +Signed-off-by: Jassi Brar <jassisinghbrar@gmail.com> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/mailbox/mtk-cmdq-mailbox.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/mailbox/mtk-cmdq-mailbox.c b/drivers/mailbox/mtk-cmdq-mailbox.c +index 4bff73532085b..9c43ed9bdd37b 100644 +--- a/drivers/mailbox/mtk-cmdq-mailbox.c ++++ b/drivers/mailbox/mtk-cmdq-mailbox.c +@@ -584,7 +584,7 @@ static int cmdq_get_clocks(struct device *dev, struct cmdq *cmdq) + struct clk_bulk_data *clks; + + cmdq->clocks = devm_kcalloc(dev, cmdq->pdata->gce_num, +- sizeof(cmdq->clocks), GFP_KERNEL); ++ sizeof(*cmdq->clocks), GFP_KERNEL); + if (!cmdq->clocks) + return -ENOMEM; + +-- +2.43.0 + diff --git a/queue-6.12/mailbox-remoteproc-k3-m4-fix-compile-testing.patch b/queue-6.12/mailbox-remoteproc-k3-m4-fix-compile-testing.patch new file mode 100644 index 00000000000..03ab77ad530 --- /dev/null +++ b/queue-6.12/mailbox-remoteproc-k3-m4-fix-compile-testing.patch @@ -0,0 +1,56 @@ +From d88977536120c424083eeb5ec813fdaeb82677c3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Mon, 7 Oct 2024 13:23:57 +0000 +Subject: mailbox, remoteproc: k3-m4+: fix compile testing + +From: Arnd Bergmann <arnd@arndb.de> + +[ Upstream commit 9c12b96ee244b9679629ac430c375a720bfec04b ] + +The k3-m4 remoteproc driver was merged with incorrect dependencies. +Despite multiple people trying to fix this, the version 6.12-rc2 +remains broken and causes a build failure with CONFIG_TI_SCI_PROTOCOL=m +when the driver is built-in. + +arm-linux-gnueabi-ld: drivers/remoteproc/ti_k3_m4_remoteproc.o: in function `k3_m4_rproc_probe': +ti_k3_m4_remoteproc.c:(.text.k3_m4_rproc_probe+0x76): undefined reference to `devm_ti_sci_get_by_phandle' + +Fix the dependency again to make it work in all configurations. +The 'select OMAP2PLUS_MBOX' no longer matches what the other drivers +dependencies. The link failure can be avoided with a simple 'depends +do, so turn that into the same 'depends' to ensure we get no circular +on TI_SCI_PROTOCOL', but the extra COMPILE_TEST alternative is what +we use elsehwere. On the other hand, building for OMAP2PLUS makes +no sense since the hardware only exists on K3. + +Fixes: ebcf9008a895 ("remoteproc: k3-m4: Add a remoteproc driver for M4F subsystem") +Fixes: ba0c0cb56f22 ("remoteproc: k3-m4: use the proper dependencies") +Fixes: 54595f2807d2 ("mailbox, remoteproc: omap2+: fix compile testing") +Signed-off-by: Arnd Bergmann <arnd@arndb.de> +Link: https://lore.kernel.org/r/20241007132441.2732215-1-arnd@kernel.org +Signed-off-by: Mathieu Poirier <mathieu.poirier@linaro.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/remoteproc/Kconfig | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/drivers/remoteproc/Kconfig b/drivers/remoteproc/Kconfig +index 955e4e38477e6..62f8548fb46a5 100644 +--- a/drivers/remoteproc/Kconfig ++++ b/drivers/remoteproc/Kconfig +@@ -341,9 +341,9 @@ config TI_K3_DSP_REMOTEPROC + + config TI_K3_M4_REMOTEPROC + tristate "TI K3 M4 remoteproc support" +- depends on ARCH_OMAP2PLUS || ARCH_K3 +- select MAILBOX +- select OMAP2PLUS_MBOX ++ depends on ARCH_K3 || COMPILE_TEST ++ depends on TI_SCI_PROTOCOL || (COMPILE_TEST && TI_SCI_PROTOCOL=n) ++ depends on OMAP2PLUS_MBOX + help + Say m here to support TI's M4 remote processor subsystems + on various TI K3 family of SoCs through the remote processor +-- +2.43.0 + diff --git a/queue-6.12/marvell-pxa168_eth-fix-call-balance-of-pep-clk-handl.patch b/queue-6.12/marvell-pxa168_eth-fix-call-balance-of-pep-clk-handl.patch new file mode 100644 index 00000000000..3adb3f75f4f --- /dev/null +++ b/queue-6.12/marvell-pxa168_eth-fix-call-balance-of-pep-clk-handl.patch @@ -0,0 +1,76 @@ +From 6234778f0e07402f5fcdb1b27dc3ad0dbe65a3aa Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Thu, 21 Nov 2024 23:06:58 +0300 +Subject: marvell: pxa168_eth: fix call balance of pep->clk handling routines + +From: Vitalii Mordan <mordan@ispras.ru> + +[ Upstream commit b032ae57d4fe2b2445e3bc190db6fcaa8c102f68 ] + +If the clock pep->clk was not enabled in pxa168_eth_probe, +it should not be disabled in any path. + +Conversely, if it was enabled in pxa168_eth_probe, it must be disabled +in all error paths to ensure proper cleanup. + +Use the devm_clk_get_enabled helper function to ensure proper call balance +for pep->clk. + +Found by Linux Verification Center (linuxtesting.org) with Klever. + +Fixes: a49f37eed22b ("net: add Fast Ethernet driver for PXA168.") +Signed-off-by: Vitalii Mordan <mordan@ispras.ru> +Link: https://patch.msgid.link/20241121200658.2203871-1-mordan@ispras.ru +Signed-off-by: Paolo Abeni <pabeni@redhat.com> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/net/ethernet/marvell/pxa168_eth.c | 14 ++++---------- + 1 file changed, 4 insertions(+), 10 deletions(-) + +diff --git a/drivers/net/ethernet/marvell/pxa168_eth.c b/drivers/net/ethernet/marvell/pxa168_eth.c +index 1a59c952aa01c..45f115e41857b 100644 +--- a/drivers/net/ethernet/marvell/pxa168_eth.c ++++ b/drivers/net/ethernet/marvell/pxa168_eth.c +@@ -1394,18 +1394,15 @@ static int pxa168_eth_probe(struct platform_device *pdev) + + printk(KERN_NOTICE "PXA168 10/100 Ethernet Driver\n"); + +- clk = devm_clk_get(&pdev->dev, NULL); ++ clk = devm_clk_get_enabled(&pdev->dev, NULL); + if (IS_ERR(clk)) { +- dev_err(&pdev->dev, "Fast Ethernet failed to get clock\n"); ++ dev_err(&pdev->dev, "Fast Ethernet failed to get and enable clock\n"); + return -ENODEV; + } +- clk_prepare_enable(clk); + + dev = alloc_etherdev(sizeof(struct pxa168_eth_private)); +- if (!dev) { +- err = -ENOMEM; +- goto err_clk; +- } ++ if (!dev) ++ return -ENOMEM; + + platform_set_drvdata(pdev, dev); + pep = netdev_priv(dev); +@@ -1523,8 +1520,6 @@ static int pxa168_eth_probe(struct platform_device *pdev) + mdiobus_free(pep->smi_bus); + err_netdev: + free_netdev(dev); +-err_clk: +- clk_disable_unprepare(clk); + return err; + } + +@@ -1542,7 +1537,6 @@ static void pxa168_eth_remove(struct platform_device *pdev) + if (dev->phydev) + phy_disconnect(dev->phydev); + +- clk_disable_unprepare(pep->clk); + mdiobus_unregister(pep->smi_bus); + mdiobus_free(pep->smi_bus); + unregister_netdev(dev); +-- +2.43.0 + diff --git a/queue-6.12/media-atomisp-add-check-for-rgby_data-memory-allocat.patch b/queue-6.12/media-atomisp-add-check-for-rgby_data-memory-allocat.patch new file mode 100644 index 00000000000..823d7fda693 --- /dev/null +++ b/queue-6.12/media-atomisp-add-check-for-rgby_data-memory-allocat.patch @@ -0,0 +1,42 @@ +From 1d5f1e79a3b55d70ccd5395af07340f6a964527d Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Mon, 4 Nov 2024 22:50:51 +0800 +Subject: media: atomisp: Add check for rgby_data memory allocation failure + +From: Li Huafei <lihuafei1@huawei.com> + +[ Upstream commit ed61c59139509f76d3592683c90dc3fdc6e23cd6 ] + +In ia_css_3a_statistics_allocate(), there is no check on the allocation +result of the rgby_data memory. If rgby_data is not successfully +allocated, it may trigger the assert(host_stats->rgby_data) assertion in +ia_css_s3a_hmem_decode(). Adding a check to fix this potential issue. + +Fixes: a49d25364dfb ("staging/atomisp: Add support for the Intel IPU v2") +Signed-off-by: Li Huafei <lihuafei1@huawei.com> +Reviewed-by: Andy Shevchenko <andy@kernel.org> +Link: https://lore.kernel.org/r/20241104145051.3088231-1-lihuafei1@huawei.com +Reviewed-by: Hans de Goede <hdegoede@redhat.com> +Signed-off-by: Hans de Goede <hdegoede@redhat.com> +Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/staging/media/atomisp/pci/sh_css_params.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/staging/media/atomisp/pci/sh_css_params.c b/drivers/staging/media/atomisp/pci/sh_css_params.c +index 232744973ab88..b1feb6f6ebe89 100644 +--- a/drivers/staging/media/atomisp/pci/sh_css_params.c ++++ b/drivers/staging/media/atomisp/pci/sh_css_params.c +@@ -4181,6 +4181,8 @@ ia_css_3a_statistics_allocate(const struct ia_css_3a_grid_info *grid) + goto err; + /* No weighted histogram, no structure, treat the histogram data as a byte dump in a byte array */ + me->rgby_data = kvmalloc(sizeof_hmem(HMEM0_ID), GFP_KERNEL); ++ if (!me->rgby_data) ++ goto err; + + IA_CSS_LEAVE("return=%p", me); + return me; +-- +2.43.0 + diff --git a/queue-6.12/media-i2c-ds90ub960-fix-missing-return-check-on-ub96.patch b/queue-6.12/media-i2c-ds90ub960-fix-missing-return-check-on-ub96.patch new file mode 100644 index 00000000000..a8470d29250 --- /dev/null +++ b/queue-6.12/media-i2c-ds90ub960-fix-missing-return-check-on-ub96.patch @@ -0,0 +1,41 @@ +From 02e3ecf3d9c3c056b647ab0841b1426507453ed1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Wed, 2 Oct 2024 17:53:29 +0100 +Subject: media: i2c: ds90ub960: Fix missing return check on ub960_rxport_read + call + +From: Colin Ian King <colin.i.king@gmail.com> + +[ Upstream commit 24ad2d1f773a11f69eecec3ec37ea3d76f2e9e7d ] + +The function ub960_rxport_read is being called and afterwards ret is +being checked for any failures, however ret is not being assigned to +the return of the function call. Fix this by assigning ret to the +return of the call which appears to be missing. + +Fixes: afe267f2d368 ("media: i2c: add DS90UB960 driver") +Signed-off-by: Colin Ian King <colin.i.king@gmail.com> +Reviewed-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com> +Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com> +Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/media/i2c/ds90ub960.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/media/i2c/ds90ub960.c b/drivers/media/i2c/ds90ub960.c +index ffe5f25f86476..58424d8f72af0 100644 +--- a/drivers/media/i2c/ds90ub960.c ++++ b/drivers/media/i2c/ds90ub960.c +@@ -1286,7 +1286,7 @@ static int ub960_rxport_get_strobe_pos(struct ub960_data *priv, + + clk_delay += v & UB960_IR_RX_ANA_STROBE_SET_CLK_DELAY_MASK; + +- ub960_rxport_read(priv, nport, UB960_RR_SFILTER_STS_1, &v); ++ ret = ub960_rxport_read(priv, nport, UB960_RR_SFILTER_STS_1, &v); + if (ret) + return ret; + +-- +2.43.0 + diff --git a/queue-6.12/media-i2c-max96717-clean-up-on-error-in-max96717_sub.patch b/queue-6.12/media-i2c-max96717-clean-up-on-error-in-max96717_sub.patch new file mode 100644 index 00000000000..474c33b1ebd --- /dev/null +++ b/queue-6.12/media-i2c-max96717-clean-up-on-error-in-max96717_sub.patch @@ -0,0 +1,41 @@ +From d16e50281c0cd47f67c85a2b0100f49140aa5aa6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Fri, 27 Sep 2024 13:59:10 +0300 +Subject: media: i2c: max96717: clean up on error in max96717_subdev_init() + +From: Dan Carpenter <dan.carpenter@linaro.org> + +[ Upstream commit d56786977ba11ed15b066495c1363889bcb1c3bb ] + +Call v4l2_ctrl_handler_free() to clean up from v4l2_ctrl_handler_init(). + +Fixes: 19b5e5511ca4 ("media: i2c: max96717: add test pattern ctrl") +Signed-off-by: Dan Carpenter <dan.carpenter@linaro.org> +Reviewed-by: Julien Massot <julien.massot@collabora.com> +Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com> +Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/media/i2c/max96717.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/drivers/media/i2c/max96717.c b/drivers/media/i2c/max96717.c +index 4e85b8eb1e776..9259d58ba734e 100644 +--- a/drivers/media/i2c/max96717.c ++++ b/drivers/media/i2c/max96717.c +@@ -697,8 +697,10 @@ static int max96717_subdev_init(struct max96717_priv *priv) + priv->pads[MAX96717_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE; + + ret = media_entity_pads_init(&priv->sd.entity, 2, priv->pads); +- if (ret) +- return dev_err_probe(dev, ret, "Failed to init pads\n"); ++ if (ret) { ++ dev_err_probe(dev, ret, "Failed to init pads\n"); ++ goto err_free_ctrl; ++ } + + ret = v4l2_subdev_init_finalize(&priv->sd); + if (ret) { +-- +2.43.0 + diff --git a/queue-6.12/media-i2c-vgxy61-fix-an-error-handling-path-in-vgxy6.patch b/queue-6.12/media-i2c-vgxy61-fix-an-error-handling-path-in-vgxy6.patch new file mode 100644 index 00000000000..3adf293dd4f --- /dev/null +++ b/queue-6.12/media-i2c-vgxy61-fix-an-error-handling-path-in-vgxy6.patch @@ -0,0 +1,40 @@ +From 7ff720f15b92167b165c01e8d14a54e0d84d735d Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Thu, 3 Oct 2024 19:53:15 +0200 +Subject: media: i2c: vgxy61: Fix an error handling path in vgxy61_detect() + +From: Christophe JAILLET <christophe.jaillet@wanadoo.fr> + +[ Upstream commit 0d5c92cde4d38825eeadf5b4e1534350f80a9924 ] + +If cci_read() fails, 'st' is set to 0 in cci_read(), so we return success, +instead of the expected error code. + +Fix it and return the expected error. + +Fixes: 9a6d7f2ba2b9 ("media: i2c: st-vgxy61: Convert to CCI register access helpers") +Signed-off-by: Christophe JAILLET <christophe.jaillet@wanadoo.fr> +Reviewed-by: Benjamin Mugnier <benjamin.mugnier@foss.st.com> +Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com> +Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/media/i2c/vgxy61.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/media/i2c/vgxy61.c b/drivers/media/i2c/vgxy61.c +index 409d2d4ffb4bb..d77468c8587bc 100644 +--- a/drivers/media/i2c/vgxy61.c ++++ b/drivers/media/i2c/vgxy61.c +@@ -1617,7 +1617,7 @@ static int vgxy61_detect(struct vgxy61_dev *sensor) + + ret = cci_read(sensor->regmap, VGXY61_REG_NVM, &st, NULL); + if (ret < 0) +- return st; ++ return ret; + if (st != VGXY61_NVM_OK) + dev_warn(&client->dev, "Bad nvm state got %u\n", (u8)st); + +-- +2.43.0 + diff --git a/queue-6.12/media-ipu6-fix-dma-and-physical-address-debugging-me.patch b/queue-6.12/media-ipu6-fix-dma-and-physical-address-debugging-me.patch new file mode 100644 index 00000000000..698723682ea --- /dev/null +++ b/queue-6.12/media-ipu6-fix-dma-and-physical-address-debugging-me.patch @@ -0,0 +1,120 @@ +From eb77a9c75b8636fdb30ad6886db196c4a1c91681 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Mon, 4 Nov 2024 13:31:32 +0200 +Subject: media: ipu6: Fix DMA and physical address debugging messages for + 32-bit + +From: Sakari Ailus <sakari.ailus@linux.intel.com> + +[ Upstream commit 199c204bcc732ec18dbaec2b9d6445addbd376ea ] + +Fix printing DMA and physical address printing on 32-bit platforms, by +using correct types. Also cast DMA_BIT_MASK() result to dma_addr_t to make +Clang happy. + +Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com> +Reviewed-by: Bingbu Cao <bingbu.cao@intel.com> +Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl> +Stable-dep-of: daabc5c64703 ("media: ipu6: not override the dma_ops of device in driver") +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/media/pci/intel/ipu6/ipu6-dma.c | 7 ++++--- + drivers/media/pci/intel/ipu6/ipu6-mmu.c | 28 +++++++++++++++---------- + 2 files changed, 21 insertions(+), 14 deletions(-) + +diff --git a/drivers/media/pci/intel/ipu6/ipu6-dma.c b/drivers/media/pci/intel/ipu6/ipu6-dma.c +index 92530a1cc90f5..801f6bd00a891 100644 +--- a/drivers/media/pci/intel/ipu6/ipu6-dma.c ++++ b/drivers/media/pci/intel/ipu6/ipu6-dma.c +@@ -428,11 +428,12 @@ static int ipu6_dma_map_sg(struct device *dev, struct scatterlist *sglist, + + iova_addr = iova->pfn_lo; + for_each_sg(sglist, sg, count, i) { ++ phys_addr_t iova_pa; + int ret; + +- dev_dbg(dev, "mapping entry %d: iova 0x%llx phy %pad size %d\n", +- i, PFN_PHYS(iova_addr), &sg_dma_address(sg), +- sg_dma_len(sg)); ++ iova_pa = PFN_PHYS(iova_addr); ++ dev_dbg(dev, "mapping entry %d: iova %pap phy %pap size %d\n", ++ i, &iova_pa, &sg_dma_address(sg), sg_dma_len(sg)); + + ret = ipu6_mmu_map(mmu->dmap->mmu_info, PFN_PHYS(iova_addr), + sg_dma_address(sg), +diff --git a/drivers/media/pci/intel/ipu6/ipu6-mmu.c b/drivers/media/pci/intel/ipu6/ipu6-mmu.c +index c3a20507d6dbc..57298ac73d072 100644 +--- a/drivers/media/pci/intel/ipu6/ipu6-mmu.c ++++ b/drivers/media/pci/intel/ipu6/ipu6-mmu.c +@@ -97,13 +97,15 @@ static void page_table_dump(struct ipu6_mmu_info *mmu_info) + for (l1_idx = 0; l1_idx < ISP_L1PT_PTES; l1_idx++) { + u32 l2_idx; + u32 iova = (phys_addr_t)l1_idx << ISP_L1PT_SHIFT; ++ phys_addr_t l2_phys; + + if (mmu_info->l1_pt[l1_idx] == mmu_info->dummy_l2_pteval) + continue; ++ ++ l2_phys = TBL_PHYS_ADDR(mmu_info->l1_pt[l1_idx];) + dev_dbg(mmu_info->dev, +- "l1 entry %u; iovas 0x%8.8x-0x%8.8x, at %pa\n", +- l1_idx, iova, iova + ISP_PAGE_SIZE, +- TBL_PHYS_ADDR(mmu_info->l1_pt[l1_idx])); ++ "l1 entry %u; iovas 0x%8.8x-0x%8.8x, at %pap\n", ++ l1_idx, iova, iova + ISP_PAGE_SIZE, &l2_phys); + + for (l2_idx = 0; l2_idx < ISP_L2PT_PTES; l2_idx++) { + u32 *l2_pt = mmu_info->l2_pts[l1_idx]; +@@ -227,7 +229,7 @@ static u32 *alloc_l1_pt(struct ipu6_mmu_info *mmu_info) + } + + mmu_info->l1_pt_dma = dma >> ISP_PADDR_SHIFT; +- dev_dbg(mmu_info->dev, "l1 pt %p mapped at %llx\n", pt, dma); ++ dev_dbg(mmu_info->dev, "l1 pt %p mapped at %pad\n", pt, &dma); + + return pt; + +@@ -330,8 +332,8 @@ static int __ipu6_mmu_map(struct ipu6_mmu_info *mmu_info, unsigned long iova, + u32 iova_end = ALIGN(iova + size, ISP_PAGE_SIZE); + + dev_dbg(mmu_info->dev, +- "mapping iova 0x%8.8x--0x%8.8x, size %zu at paddr 0x%10.10llx\n", +- iova_start, iova_end, size, paddr); ++ "mapping iova 0x%8.8x--0x%8.8x, size %zu at paddr %pap\n", ++ iova_start, iova_end, size, &paddr); + + return l2_map(mmu_info, iova_start, paddr, size); + } +@@ -361,10 +363,13 @@ static size_t l2_unmap(struct ipu6_mmu_info *mmu_info, unsigned long iova, + for (l2_idx = (iova_start & ISP_L2PT_MASK) >> ISP_L2PT_SHIFT; + (iova_start & ISP_L1PT_MASK) + (l2_idx << ISP_PAGE_SHIFT) + < iova_start + size && l2_idx < ISP_L2PT_PTES; l2_idx++) { ++ phys_addr_t pteval; ++ + l2_pt = mmu_info->l2_pts[l1_idx]; ++ pteval = TBL_PHYS_ADDR(l2_pt[l2_idx]); + dev_dbg(mmu_info->dev, +- "unmap l2 index %u with pteval 0x%10.10llx\n", +- l2_idx, TBL_PHYS_ADDR(l2_pt[l2_idx])); ++ "unmap l2 index %u with pteval 0x%p\n", ++ l2_idx, &pteval); + l2_pt[l2_idx] = mmu_info->dummy_page_pteval; + + clflush_cache_range((void *)&l2_pt[l2_idx], +@@ -525,9 +530,10 @@ static struct ipu6_mmu_info *ipu6_mmu_alloc(struct ipu6_device *isp) + return NULL; + + mmu_info->aperture_start = 0; +- mmu_info->aperture_end = DMA_BIT_MASK(isp->secure_mode ? +- IPU6_MMU_ADDR_BITS : +- IPU6_MMU_ADDR_BITS_NON_SECURE); ++ mmu_info->aperture_end = ++ (dma_addr_t)DMA_BIT_MASK(isp->secure_mode ? ++ IPU6_MMU_ADDR_BITS : ++ IPU6_MMU_ADDR_BITS_NON_SECURE); + mmu_info->pgsize_bitmap = SZ_4K; + mmu_info->dev = &isp->pdev->dev; + +-- +2.43.0 + diff --git a/queue-6.12/media-ipu6-not-override-the-dma_ops-of-device-in-dri.patch b/queue-6.12/media-ipu6-not-override-the-dma_ops-of-device-in-dri.patch new file mode 100644 index 00000000000..32a94f95cec --- /dev/null +++ b/queue-6.12/media-ipu6-not-override-the-dma_ops-of-device-in-dri.patch @@ -0,0 +1,669 @@ +From f461c7fabd3edee2e113c055a9235519fff89728 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Wed, 16 Oct 2024 15:53:01 +0800 +Subject: media: ipu6: not override the dma_ops of device in driver + +From: Bingbu Cao <bingbu.cao@intel.com> + +[ Upstream commit daabc5c64703432c4a8798421a3588c2c142c51b ] + +DMA ops are a helper for architectures and not for drivers to override the +DMA implementation. Driver should not override the DMA implementation. + +This patch removes the dma_ops override from auxiliary device and adds +driver-internal helpers that use the actual DMA mapping APIs. + +Fixes: 9163d83573e4 ("media: intel/ipu6: add IPU6 DMA mapping API and MMU table") +Signed-off-by: Bingbu Cao <bingbu.cao@intel.com> +Reviewed-by: Christoph Hellwig <hch@lst.de> +[Sakari Ailus: Fix the commit message a little.] +Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com> +Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/media/pci/intel/ipu6/ipu6-bus.c | 6 - + drivers/media/pci/intel/ipu6/ipu6-buttress.c | 21 +- + drivers/media/pci/intel/ipu6/ipu6-cpd.c | 18 +- + drivers/media/pci/intel/ipu6/ipu6-dma.c | 195 +++++++++---------- + drivers/media/pci/intel/ipu6/ipu6-dma.h | 34 +++- + drivers/media/pci/intel/ipu6/ipu6-fw-com.c | 14 +- + 6 files changed, 156 insertions(+), 132 deletions(-) + +diff --git a/drivers/media/pci/intel/ipu6/ipu6-bus.c b/drivers/media/pci/intel/ipu6/ipu6-bus.c +index 149ec098cdbfe..37d88ddb6ee7c 100644 +--- a/drivers/media/pci/intel/ipu6/ipu6-bus.c ++++ b/drivers/media/pci/intel/ipu6/ipu6-bus.c +@@ -94,8 +94,6 @@ ipu6_bus_initialize_device(struct pci_dev *pdev, struct device *parent, + if (!adev) + return ERR_PTR(-ENOMEM); + +- adev->dma_mask = DMA_BIT_MASK(isp->secure_mode ? IPU6_MMU_ADDR_BITS : +- IPU6_MMU_ADDR_BITS_NON_SECURE); + adev->isp = isp; + adev->ctrl = ctrl; + adev->pdata = pdata; +@@ -106,10 +104,6 @@ ipu6_bus_initialize_device(struct pci_dev *pdev, struct device *parent, + + auxdev->dev.parent = parent; + auxdev->dev.release = ipu6_bus_release; +- auxdev->dev.dma_ops = &ipu6_dma_ops; +- auxdev->dev.dma_mask = &adev->dma_mask; +- auxdev->dev.dma_parms = pdev->dev.dma_parms; +- auxdev->dev.coherent_dma_mask = adev->dma_mask; + + ret = auxiliary_device_init(auxdev); + if (ret < 0) { +diff --git a/drivers/media/pci/intel/ipu6/ipu6-buttress.c b/drivers/media/pci/intel/ipu6/ipu6-buttress.c +index e47f84c30e10d..d66db537be4a6 100644 +--- a/drivers/media/pci/intel/ipu6/ipu6-buttress.c ++++ b/drivers/media/pci/intel/ipu6/ipu6-buttress.c +@@ -24,6 +24,7 @@ + + #include "ipu6.h" + #include "ipu6-bus.h" ++#include "ipu6-dma.h" + #include "ipu6-buttress.h" + #include "ipu6-platform-buttress-regs.h" + +@@ -553,6 +554,7 @@ int ipu6_buttress_map_fw_image(struct ipu6_bus_device *sys, + const struct firmware *fw, struct sg_table *sgt) + { + bool is_vmalloc = is_vmalloc_addr(fw->data); ++ struct pci_dev *pdev = sys->isp->pdev; + struct page **pages; + const void *addr; + unsigned long n_pages; +@@ -588,14 +590,20 @@ int ipu6_buttress_map_fw_image(struct ipu6_bus_device *sys, + goto out; + } + +- ret = dma_map_sgtable(&sys->auxdev.dev, sgt, DMA_TO_DEVICE, 0); +- if (ret < 0) { +- ret = -ENOMEM; ++ ret = dma_map_sgtable(&pdev->dev, sgt, DMA_TO_DEVICE, 0); ++ if (ret) { ++ sg_free_table(sgt); ++ goto out; ++ } ++ ++ ret = ipu6_dma_map_sgtable(sys, sgt, DMA_TO_DEVICE, 0); ++ if (ret) { ++ dma_unmap_sgtable(&pdev->dev, sgt, DMA_TO_DEVICE, 0); + sg_free_table(sgt); + goto out; + } + +- dma_sync_sgtable_for_device(&sys->auxdev.dev, sgt, DMA_TO_DEVICE); ++ ipu6_dma_sync_sgtable(sys, sgt); + + out: + kfree(pages); +@@ -607,7 +615,10 @@ EXPORT_SYMBOL_NS_GPL(ipu6_buttress_map_fw_image, INTEL_IPU6); + void ipu6_buttress_unmap_fw_image(struct ipu6_bus_device *sys, + struct sg_table *sgt) + { +- dma_unmap_sgtable(&sys->auxdev.dev, sgt, DMA_TO_DEVICE, 0); ++ struct pci_dev *pdev = sys->isp->pdev; ++ ++ ipu6_dma_unmap_sgtable(sys, sgt, DMA_TO_DEVICE, 0); ++ dma_unmap_sgtable(&pdev->dev, sgt, DMA_TO_DEVICE, 0); + sg_free_table(sgt); + } + EXPORT_SYMBOL_NS_GPL(ipu6_buttress_unmap_fw_image, INTEL_IPU6); +diff --git a/drivers/media/pci/intel/ipu6/ipu6-cpd.c b/drivers/media/pci/intel/ipu6/ipu6-cpd.c +index 715b21ab4b8e9..21c1c128a7eaa 100644 +--- a/drivers/media/pci/intel/ipu6/ipu6-cpd.c ++++ b/drivers/media/pci/intel/ipu6/ipu6-cpd.c +@@ -15,6 +15,7 @@ + #include "ipu6.h" + #include "ipu6-bus.h" + #include "ipu6-cpd.h" ++#include "ipu6-dma.h" + + /* 15 entries + header*/ + #define MAX_PKG_DIR_ENT_CNT 16 +@@ -162,7 +163,6 @@ int ipu6_cpd_create_pkg_dir(struct ipu6_bus_device *adev, const void *src) + { + dma_addr_t dma_addr_src = sg_dma_address(adev->fw_sgt.sgl); + const struct ipu6_cpd_ent *ent, *man_ent, *met_ent; +- struct device *dev = &adev->auxdev.dev; + struct ipu6_device *isp = adev->isp; + unsigned int man_sz, met_sz; + void *pkg_dir_pos; +@@ -175,8 +175,8 @@ int ipu6_cpd_create_pkg_dir(struct ipu6_bus_device *adev, const void *src) + met_sz = met_ent->len; + + adev->pkg_dir_size = PKG_DIR_SIZE + man_sz + met_sz; +- adev->pkg_dir = dma_alloc_attrs(dev, adev->pkg_dir_size, +- &adev->pkg_dir_dma_addr, GFP_KERNEL, 0); ++ adev->pkg_dir = ipu6_dma_alloc(adev, adev->pkg_dir_size, ++ &adev->pkg_dir_dma_addr, GFP_KERNEL, 0); + if (!adev->pkg_dir) + return -ENOMEM; + +@@ -198,8 +198,8 @@ int ipu6_cpd_create_pkg_dir(struct ipu6_bus_device *adev, const void *src) + met_ent->len); + if (ret) { + dev_err(&isp->pdev->dev, "Failed to parse module data\n"); +- dma_free_attrs(dev, adev->pkg_dir_size, +- adev->pkg_dir, adev->pkg_dir_dma_addr, 0); ++ ipu6_dma_free(adev, adev->pkg_dir_size, ++ adev->pkg_dir, adev->pkg_dir_dma_addr, 0); + return ret; + } + +@@ -211,8 +211,8 @@ int ipu6_cpd_create_pkg_dir(struct ipu6_bus_device *adev, const void *src) + pkg_dir_pos += man_sz; + memcpy(pkg_dir_pos, src + met_ent->offset, met_sz); + +- dma_sync_single_range_for_device(dev, adev->pkg_dir_dma_addr, +- 0, adev->pkg_dir_size, DMA_TO_DEVICE); ++ ipu6_dma_sync_single(adev, adev->pkg_dir_dma_addr, ++ adev->pkg_dir_size); + + return 0; + } +@@ -220,8 +220,8 @@ EXPORT_SYMBOL_NS_GPL(ipu6_cpd_create_pkg_dir, INTEL_IPU6); + + void ipu6_cpd_free_pkg_dir(struct ipu6_bus_device *adev) + { +- dma_free_attrs(&adev->auxdev.dev, adev->pkg_dir_size, adev->pkg_dir, +- adev->pkg_dir_dma_addr, 0); ++ ipu6_dma_free(adev, adev->pkg_dir_size, adev->pkg_dir, ++ adev->pkg_dir_dma_addr, 0); + } + EXPORT_SYMBOL_NS_GPL(ipu6_cpd_free_pkg_dir, INTEL_IPU6); + +diff --git a/drivers/media/pci/intel/ipu6/ipu6-dma.c b/drivers/media/pci/intel/ipu6/ipu6-dma.c +index 801f6bd00a891..b71f66bd8c1fd 100644 +--- a/drivers/media/pci/intel/ipu6/ipu6-dma.c ++++ b/drivers/media/pci/intel/ipu6/ipu6-dma.c +@@ -39,8 +39,7 @@ static struct vm_info *get_vm_info(struct ipu6_mmu *mmu, dma_addr_t iova) + return NULL; + } + +-static void __dma_clear_buffer(struct page *page, size_t size, +- unsigned long attrs) ++static void __clear_buffer(struct page *page, size_t size, unsigned long attrs) + { + void *ptr; + +@@ -56,8 +55,7 @@ static void __dma_clear_buffer(struct page *page, size_t size, + clflush_cache_range(ptr, size); + } + +-static struct page **__dma_alloc_buffer(struct device *dev, size_t size, +- gfp_t gfp, unsigned long attrs) ++static struct page **__alloc_buffer(size_t size, gfp_t gfp, unsigned long attrs) + { + int count = PHYS_PFN(size); + int array_size = count * sizeof(struct page *); +@@ -86,7 +84,7 @@ static struct page **__dma_alloc_buffer(struct device *dev, size_t size, + pages[i + j] = pages[i] + j; + } + +- __dma_clear_buffer(pages[i], PAGE_SIZE << order, attrs); ++ __clear_buffer(pages[i], PAGE_SIZE << order, attrs); + i += 1 << order; + count -= 1 << order; + } +@@ -100,29 +98,26 @@ static struct page **__dma_alloc_buffer(struct device *dev, size_t size, + return NULL; + } + +-static void __dma_free_buffer(struct device *dev, struct page **pages, +- size_t size, unsigned long attrs) ++static void __free_buffer(struct page **pages, size_t size, unsigned long attrs) + { + int count = PHYS_PFN(size); + unsigned int i; + + for (i = 0; i < count && pages[i]; i++) { +- __dma_clear_buffer(pages[i], PAGE_SIZE, attrs); ++ __clear_buffer(pages[i], PAGE_SIZE, attrs); + __free_pages(pages[i], 0); + } + + kvfree(pages); + } + +-static void ipu6_dma_sync_single_for_cpu(struct device *dev, +- dma_addr_t dma_handle, +- size_t size, +- enum dma_data_direction dir) ++void ipu6_dma_sync_single(struct ipu6_bus_device *sys, dma_addr_t dma_handle, ++ size_t size) + { + void *vaddr; + u32 offset; + struct vm_info *info; +- struct ipu6_mmu *mmu = to_ipu6_bus_device(dev)->mmu; ++ struct ipu6_mmu *mmu = sys->mmu; + + info = get_vm_info(mmu, dma_handle); + if (WARN_ON(!info)) +@@ -135,10 +130,10 @@ static void ipu6_dma_sync_single_for_cpu(struct device *dev, + vaddr = info->vaddr + offset; + clflush_cache_range(vaddr, size); + } ++EXPORT_SYMBOL_NS_GPL(ipu6_dma_sync_single, INTEL_IPU6); + +-static void ipu6_dma_sync_sg_for_cpu(struct device *dev, +- struct scatterlist *sglist, +- int nents, enum dma_data_direction dir) ++void ipu6_dma_sync_sg(struct ipu6_bus_device *sys, struct scatterlist *sglist, ++ int nents) + { + struct scatterlist *sg; + int i; +@@ -146,14 +141,22 @@ static void ipu6_dma_sync_sg_for_cpu(struct device *dev, + for_each_sg(sglist, sg, nents, i) + clflush_cache_range(page_to_virt(sg_page(sg)), sg->length); + } ++EXPORT_SYMBOL_NS_GPL(ipu6_dma_sync_sg, INTEL_IPU6); + +-static void *ipu6_dma_alloc(struct device *dev, size_t size, +- dma_addr_t *dma_handle, gfp_t gfp, +- unsigned long attrs) ++void ipu6_dma_sync_sgtable(struct ipu6_bus_device *sys, struct sg_table *sgt) + { +- struct ipu6_mmu *mmu = to_ipu6_bus_device(dev)->mmu; +- struct pci_dev *pdev = to_ipu6_bus_device(dev)->isp->pdev; ++ ipu6_dma_sync_sg(sys, sgt->sgl, sgt->orig_nents); ++} ++EXPORT_SYMBOL_NS_GPL(ipu6_dma_sync_sgtable, INTEL_IPU6); ++ ++void *ipu6_dma_alloc(struct ipu6_bus_device *sys, size_t size, ++ dma_addr_t *dma_handle, gfp_t gfp, ++ unsigned long attrs) ++{ ++ struct device *dev = &sys->auxdev.dev; ++ struct pci_dev *pdev = sys->isp->pdev; + dma_addr_t pci_dma_addr, ipu6_iova; ++ struct ipu6_mmu *mmu = sys->mmu; + struct vm_info *info; + unsigned long count; + struct page **pages; +@@ -173,7 +176,7 @@ static void *ipu6_dma_alloc(struct device *dev, size_t size, + if (!iova) + goto out_kfree; + +- pages = __dma_alloc_buffer(dev, size, gfp, attrs); ++ pages = __alloc_buffer(size, gfp, attrs); + if (!pages) + goto out_free_iova; + +@@ -227,7 +230,7 @@ static void *ipu6_dma_alloc(struct device *dev, size_t size, + ipu6_mmu_unmap(mmu->dmap->mmu_info, ipu6_iova, PAGE_SIZE); + } + +- __dma_free_buffer(dev, pages, size, attrs); ++ __free_buffer(pages, size, attrs); + + out_free_iova: + __free_iova(&mmu->dmap->iovad, iova); +@@ -236,13 +239,13 @@ static void *ipu6_dma_alloc(struct device *dev, size_t size, + + return NULL; + } ++EXPORT_SYMBOL_NS_GPL(ipu6_dma_alloc, INTEL_IPU6); + +-static void ipu6_dma_free(struct device *dev, size_t size, void *vaddr, +- dma_addr_t dma_handle, +- unsigned long attrs) ++void ipu6_dma_free(struct ipu6_bus_device *sys, size_t size, void *vaddr, ++ dma_addr_t dma_handle, unsigned long attrs) + { +- struct ipu6_mmu *mmu = to_ipu6_bus_device(dev)->mmu; +- struct pci_dev *pdev = to_ipu6_bus_device(dev)->isp->pdev; ++ struct ipu6_mmu *mmu = sys->mmu; ++ struct pci_dev *pdev = sys->isp->pdev; + struct iova *iova = find_iova(&mmu->dmap->iovad, PHYS_PFN(dma_handle)); + dma_addr_t pci_dma_addr, ipu6_iova; + struct vm_info *info; +@@ -281,7 +284,7 @@ static void ipu6_dma_free(struct device *dev, size_t size, void *vaddr, + ipu6_mmu_unmap(mmu->dmap->mmu_info, PFN_PHYS(iova->pfn_lo), + PFN_PHYS(iova_size(iova))); + +- __dma_free_buffer(dev, pages, size, attrs); ++ __free_buffer(pages, size, attrs); + + mmu->tlb_invalidate(mmu); + +@@ -289,13 +292,14 @@ static void ipu6_dma_free(struct device *dev, size_t size, void *vaddr, + + kfree(info); + } ++EXPORT_SYMBOL_NS_GPL(ipu6_dma_free, INTEL_IPU6); + +-static int ipu6_dma_mmap(struct device *dev, struct vm_area_struct *vma, +- void *addr, dma_addr_t iova, size_t size, +- unsigned long attrs) ++int ipu6_dma_mmap(struct ipu6_bus_device *sys, struct vm_area_struct *vma, ++ void *addr, dma_addr_t iova, size_t size, ++ unsigned long attrs) + { +- struct ipu6_mmu *mmu = to_ipu6_bus_device(dev)->mmu; +- size_t count = PHYS_PFN(PAGE_ALIGN(size)); ++ struct ipu6_mmu *mmu = sys->mmu; ++ size_t count = PFN_UP(size); + struct vm_info *info; + size_t i; + int ret; +@@ -323,18 +327,17 @@ static int ipu6_dma_mmap(struct device *dev, struct vm_area_struct *vma, + return 0; + } + +-static void ipu6_dma_unmap_sg(struct device *dev, +- struct scatterlist *sglist, +- int nents, enum dma_data_direction dir, +- unsigned long attrs) ++void ipu6_dma_unmap_sg(struct ipu6_bus_device *sys, struct scatterlist *sglist, ++ int nents, enum dma_data_direction dir, ++ unsigned long attrs) + { +- struct pci_dev *pdev = to_ipu6_bus_device(dev)->isp->pdev; +- struct ipu6_mmu *mmu = to_ipu6_bus_device(dev)->mmu; ++ struct device *dev = &sys->auxdev.dev; ++ struct ipu6_mmu *mmu = sys->mmu; + struct iova *iova = find_iova(&mmu->dmap->iovad, + PHYS_PFN(sg_dma_address(sglist))); +- int i, npages, count; + struct scatterlist *sg; + dma_addr_t pci_dma_addr; ++ unsigned int i; + + if (!nents) + return; +@@ -342,31 +345,15 @@ static void ipu6_dma_unmap_sg(struct device *dev, + if (WARN_ON(!iova)) + return; + +- if ((attrs & DMA_ATTR_SKIP_CPU_SYNC) == 0) +- ipu6_dma_sync_sg_for_cpu(dev, sglist, nents, DMA_BIDIRECTIONAL); +- +- /* get the nents as orig_nents given by caller */ +- count = 0; +- npages = iova_size(iova); +- for_each_sg(sglist, sg, nents, i) { +- if (sg_dma_len(sg) == 0 || +- sg_dma_address(sg) == DMA_MAPPING_ERROR) +- break; +- +- npages -= PHYS_PFN(PAGE_ALIGN(sg_dma_len(sg))); +- count++; +- if (npages <= 0) +- break; +- } +- + /* + * Before IPU6 mmu unmap, return the pci dma address back to sg + * assume the nents is less than orig_nents as the least granule + * is 1 SZ_4K page + */ +- dev_dbg(dev, "trying to unmap concatenated %u ents\n", count); +- for_each_sg(sglist, sg, count, i) { +- dev_dbg(dev, "ipu unmap sg[%d] %pad\n", i, &sg_dma_address(sg)); ++ dev_dbg(dev, "trying to unmap concatenated %u ents\n", nents); ++ for_each_sg(sglist, sg, nents, i) { ++ dev_dbg(dev, "unmap sg[%d] %pad size %u\n", i, ++ &sg_dma_address(sg), sg_dma_len(sg)); + pci_dma_addr = ipu6_mmu_iova_to_phys(mmu->dmap->mmu_info, + sg_dma_address(sg)); + dev_dbg(dev, "return pci_dma_addr %pad back to sg[%d]\n", +@@ -380,23 +367,21 @@ static void ipu6_dma_unmap_sg(struct device *dev, + PFN_PHYS(iova_size(iova))); + + mmu->tlb_invalidate(mmu); +- +- dma_unmap_sg_attrs(&pdev->dev, sglist, nents, dir, attrs); +- + __free_iova(&mmu->dmap->iovad, iova); + } ++EXPORT_SYMBOL_NS_GPL(ipu6_dma_unmap_sg, INTEL_IPU6); + +-static int ipu6_dma_map_sg(struct device *dev, struct scatterlist *sglist, +- int nents, enum dma_data_direction dir, +- unsigned long attrs) ++int ipu6_dma_map_sg(struct ipu6_bus_device *sys, struct scatterlist *sglist, ++ int nents, enum dma_data_direction dir, ++ unsigned long attrs) + { +- struct ipu6_mmu *mmu = to_ipu6_bus_device(dev)->mmu; +- struct pci_dev *pdev = to_ipu6_bus_device(dev)->isp->pdev; ++ struct device *dev = &sys->auxdev.dev; ++ struct ipu6_mmu *mmu = sys->mmu; + struct scatterlist *sg; + struct iova *iova; + size_t npages = 0; + unsigned long iova_addr; +- int i, count; ++ int i; + + for_each_sg(sglist, sg, nents, i) { + if (sg->offset) { +@@ -406,18 +391,12 @@ static int ipu6_dma_map_sg(struct device *dev, struct scatterlist *sglist, + } + } + +- dev_dbg(dev, "pci_dma_map_sg trying to map %d ents\n", nents); +- count = dma_map_sg_attrs(&pdev->dev, sglist, nents, dir, attrs); +- if (count <= 0) { +- dev_err(dev, "pci_dma_map_sg %d ents failed\n", nents); +- return 0; +- } +- +- dev_dbg(dev, "pci_dma_map_sg %d ents mapped\n", count); +- +- for_each_sg(sglist, sg, count, i) ++ for_each_sg(sglist, sg, nents, i) + npages += PHYS_PFN(PAGE_ALIGN(sg_dma_len(sg))); + ++ dev_dbg(dev, "dmamap trying to map %d ents %zu pages\n", ++ nents, npages); ++ + iova = alloc_iova(&mmu->dmap->iovad, npages, + PHYS_PFN(dma_get_mask(dev)), 0); + if (!iova) +@@ -427,7 +406,7 @@ static int ipu6_dma_map_sg(struct device *dev, struct scatterlist *sglist, + iova->pfn_hi); + + iova_addr = iova->pfn_lo; +- for_each_sg(sglist, sg, count, i) { ++ for_each_sg(sglist, sg, nents, i) { + phys_addr_t iova_pa; + int ret; + +@@ -446,25 +425,48 @@ static int ipu6_dma_map_sg(struct device *dev, struct scatterlist *sglist, + iova_addr += PHYS_PFN(PAGE_ALIGN(sg_dma_len(sg))); + } + +- if ((attrs & DMA_ATTR_SKIP_CPU_SYNC) == 0) +- ipu6_dma_sync_sg_for_cpu(dev, sglist, nents, DMA_BIDIRECTIONAL); ++ dev_dbg(dev, "dmamap %d ents %zu pages mapped\n", nents, npages); + +- return count; ++ return nents; + + out_fail: +- ipu6_dma_unmap_sg(dev, sglist, i, dir, attrs); ++ ipu6_dma_unmap_sg(sys, sglist, i, dir, attrs); + + return 0; + } ++EXPORT_SYMBOL_NS_GPL(ipu6_dma_map_sg, INTEL_IPU6); ++ ++int ipu6_dma_map_sgtable(struct ipu6_bus_device *sys, struct sg_table *sgt, ++ enum dma_data_direction dir, unsigned long attrs) ++{ ++ int nents; ++ ++ nents = ipu6_dma_map_sg(sys, sgt->sgl, sgt->nents, dir, attrs); ++ if (nents < 0) ++ return nents; ++ ++ sgt->nents = nents; ++ ++ return 0; ++} ++EXPORT_SYMBOL_NS_GPL(ipu6_dma_map_sgtable, INTEL_IPU6); ++ ++void ipu6_dma_unmap_sgtable(struct ipu6_bus_device *sys, struct sg_table *sgt, ++ enum dma_data_direction dir, unsigned long attrs) ++{ ++ ipu6_dma_unmap_sg(sys, sgt->sgl, sgt->nents, dir, attrs); ++} ++EXPORT_SYMBOL_NS_GPL(ipu6_dma_unmap_sgtable, INTEL_IPU6); + + /* + * Create scatter-list for the already allocated DMA buffer + */ +-static int ipu6_dma_get_sgtable(struct device *dev, struct sg_table *sgt, +- void *cpu_addr, dma_addr_t handle, size_t size, +- unsigned long attrs) ++int ipu6_dma_get_sgtable(struct ipu6_bus_device *sys, struct sg_table *sgt, ++ void *cpu_addr, dma_addr_t handle, size_t size, ++ unsigned long attrs) + { +- struct ipu6_mmu *mmu = to_ipu6_bus_device(dev)->mmu; ++ struct device *dev = &sys->auxdev.dev; ++ struct ipu6_mmu *mmu = sys->mmu; + struct vm_info *info; + int n_pages; + int ret = 0; +@@ -484,20 +486,7 @@ static int ipu6_dma_get_sgtable(struct device *dev, struct sg_table *sgt, + ret = sg_alloc_table_from_pages(sgt, info->pages, n_pages, 0, size, + GFP_KERNEL); + if (ret) +- dev_warn(dev, "IPU6 get sgt table failed\n"); ++ dev_warn(dev, "get sgt table failed\n"); + + return ret; + } +- +-const struct dma_map_ops ipu6_dma_ops = { +- .alloc = ipu6_dma_alloc, +- .free = ipu6_dma_free, +- .mmap = ipu6_dma_mmap, +- .map_sg = ipu6_dma_map_sg, +- .unmap_sg = ipu6_dma_unmap_sg, +- .sync_single_for_cpu = ipu6_dma_sync_single_for_cpu, +- .sync_single_for_device = ipu6_dma_sync_single_for_cpu, +- .sync_sg_for_cpu = ipu6_dma_sync_sg_for_cpu, +- .sync_sg_for_device = ipu6_dma_sync_sg_for_cpu, +- .get_sgtable = ipu6_dma_get_sgtable, +-}; +diff --git a/drivers/media/pci/intel/ipu6/ipu6-dma.h b/drivers/media/pci/intel/ipu6/ipu6-dma.h +index 847ea5b7c925c..b51244add9e61 100644 +--- a/drivers/media/pci/intel/ipu6/ipu6-dma.h ++++ b/drivers/media/pci/intel/ipu6/ipu6-dma.h +@@ -5,7 +5,13 @@ + #define IPU6_DMA_H + + #include <linux/dma-map-ops.h> ++#include <linux/dma-mapping.h> + #include <linux/iova.h> ++#include <linux/iova.h> ++#include <linux/scatterlist.h> ++#include <linux/types.h> ++ ++#include "ipu6-bus.h" + + struct ipu6_mmu_info; + +@@ -14,6 +20,30 @@ struct ipu6_dma_mapping { + struct iova_domain iovad; + }; + +-extern const struct dma_map_ops ipu6_dma_ops; +- ++void ipu6_dma_sync_single(struct ipu6_bus_device *sys, dma_addr_t dma_handle, ++ size_t size); ++void ipu6_dma_sync_sg(struct ipu6_bus_device *sys, struct scatterlist *sglist, ++ int nents); ++void ipu6_dma_sync_sgtable(struct ipu6_bus_device *sys, struct sg_table *sgt); ++void *ipu6_dma_alloc(struct ipu6_bus_device *sys, size_t size, ++ dma_addr_t *dma_handle, gfp_t gfp, ++ unsigned long attrs); ++void ipu6_dma_free(struct ipu6_bus_device *sys, size_t size, void *vaddr, ++ dma_addr_t dma_handle, unsigned long attrs); ++int ipu6_dma_mmap(struct ipu6_bus_device *sys, struct vm_area_struct *vma, ++ void *addr, dma_addr_t iova, size_t size, ++ unsigned long attrs); ++int ipu6_dma_map_sg(struct ipu6_bus_device *sys, struct scatterlist *sglist, ++ int nents, enum dma_data_direction dir, ++ unsigned long attrs); ++void ipu6_dma_unmap_sg(struct ipu6_bus_device *sys, struct scatterlist *sglist, ++ int nents, enum dma_data_direction dir, ++ unsigned long attrs); ++int ipu6_dma_map_sgtable(struct ipu6_bus_device *sys, struct sg_table *sgt, ++ enum dma_data_direction dir, unsigned long attrs); ++void ipu6_dma_unmap_sgtable(struct ipu6_bus_device *sys, struct sg_table *sgt, ++ enum dma_data_direction dir, unsigned long attrs); ++int ipu6_dma_get_sgtable(struct ipu6_bus_device *sys, struct sg_table *sgt, ++ void *cpu_addr, dma_addr_t handle, size_t size, ++ unsigned long attrs); + #endif /* IPU6_DMA_H */ +diff --git a/drivers/media/pci/intel/ipu6/ipu6-fw-com.c b/drivers/media/pci/intel/ipu6/ipu6-fw-com.c +index 0b33fe9e703dc..7d3d9314cb306 100644 +--- a/drivers/media/pci/intel/ipu6/ipu6-fw-com.c ++++ b/drivers/media/pci/intel/ipu6/ipu6-fw-com.c +@@ -12,6 +12,7 @@ + #include <linux/types.h> + + #include "ipu6-bus.h" ++#include "ipu6-dma.h" + #include "ipu6-fw-com.h" + + /* +@@ -88,7 +89,6 @@ struct ipu6_fw_com_context { + void *dma_buffer; + dma_addr_t dma_addr; + unsigned int dma_size; +- unsigned long attrs; + + struct ipu6_fw_sys_queue *input_queue; /* array of host to SP queues */ + struct ipu6_fw_sys_queue *output_queue; /* array of SP to host */ +@@ -164,7 +164,6 @@ void *ipu6_fw_com_prepare(struct ipu6_fw_com_cfg *cfg, + struct ipu6_fw_com_context *ctx; + struct device *dev = &adev->auxdev.dev; + size_t sizeall, offset; +- unsigned long attrs = 0; + void *specific_host_addr; + unsigned int i; + +@@ -206,9 +205,8 @@ void *ipu6_fw_com_prepare(struct ipu6_fw_com_cfg *cfg, + + sizeall += sizeinput + sizeoutput; + +- ctx->dma_buffer = dma_alloc_attrs(dev, sizeall, &ctx->dma_addr, +- GFP_KERNEL, attrs); +- ctx->attrs = attrs; ++ ctx->dma_buffer = ipu6_dma_alloc(adev, sizeall, &ctx->dma_addr, ++ GFP_KERNEL, 0); + if (!ctx->dma_buffer) { + dev_err(dev, "failed to allocate dma memory\n"); + kfree(ctx); +@@ -239,6 +237,8 @@ void *ipu6_fw_com_prepare(struct ipu6_fw_com_cfg *cfg, + memcpy(specific_host_addr, cfg->specific_addr, + cfg->specific_size); + ++ ipu6_dma_sync_single(adev, ctx->config_vied_addr, sizeall); ++ + /* initialize input queues */ + offset += specific_size; + res.reg = SYSCOM_QPR_BASE_REG; +@@ -315,8 +315,8 @@ int ipu6_fw_com_release(struct ipu6_fw_com_context *ctx, unsigned int force) + if (!force && !ctx->cell_ready(ctx->adev)) + return -EBUSY; + +- dma_free_attrs(&ctx->adev->auxdev.dev, ctx->dma_size, +- ctx->dma_buffer, ctx->dma_addr, ctx->attrs); ++ ipu6_dma_free(ctx->adev, ctx->dma_size, ++ ctx->dma_buffer, ctx->dma_addr, 0); + kfree(ctx); + return 0; + } +-- +2.43.0 + diff --git a/queue-6.12/media-ipu6-remove-architecture-dma-ops-dependency-in.patch b/queue-6.12/media-ipu6-remove-architecture-dma-ops-dependency-in.patch new file mode 100644 index 00000000000..c0f0c706c60 --- /dev/null +++ b/queue-6.12/media-ipu6-remove-architecture-dma-ops-dependency-in.patch @@ -0,0 +1,41 @@ +From 4e6f24d2418d6eb99118ac722d1906e1695622b2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Wed, 16 Oct 2024 15:53:03 +0800 +Subject: media: ipu6: remove architecture DMA ops dependency in Kconfig + +From: Bingbu Cao <bingbu.cao@intel.com> + +[ Upstream commit c8e9120c2065868d97e9e94bceee777e5db08c3e ] + +IPU6 driver doesn't override the dma_ops of device now, it doesn't +depends on the ARCH_HAS_DMA_OPS, so remove the dependency in Kconfig. + +Fixes: de6c85bf918e ("dma-mapping: clearly mark DMA ops as an architecture feature") +Signed-off-by: Bingbu Cao <bingbu.cao@intel.com> +Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com> +Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/media/pci/intel/ipu6/Kconfig | 6 ------ + 1 file changed, 6 deletions(-) + +diff --git a/drivers/media/pci/intel/ipu6/Kconfig b/drivers/media/pci/intel/ipu6/Kconfig +index 49e4fb696573f..a4537818a58c0 100644 +--- a/drivers/media/pci/intel/ipu6/Kconfig ++++ b/drivers/media/pci/intel/ipu6/Kconfig +@@ -4,12 +4,6 @@ config VIDEO_INTEL_IPU6 + depends on VIDEO_DEV + depends on X86 && X86_64 && HAS_DMA + depends on IPU_BRIDGE || !IPU_BRIDGE +- # +- # This driver incorrectly tries to override the dma_ops. It should +- # never have done that, but for now keep it working on architectures +- # that use dma ops +- # +- depends on ARCH_HAS_DMA_OPS + select AUXILIARY_BUS + select IOMMU_IOVA + select VIDEO_V4L2_SUBDEV_API +-- +2.43.0 + diff --git a/queue-6.12/media-venus-fix-enc-dec-destruction-order.patch b/queue-6.12/media-venus-fix-enc-dec-destruction-order.patch new file mode 100644 index 00000000000..41576f05c04 --- /dev/null +++ b/queue-6.12/media-venus-fix-enc-dec-destruction-order.patch @@ -0,0 +1,74 @@ +From 99602d2e652f80adf0a16743352858e3f8167d68 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Sat, 26 Oct 2024 01:56:41 +0900 +Subject: media: venus: fix enc/dec destruction order + +From: Sergey Senozhatsky <senozhatsky@chromium.org> + +[ Upstream commit 6c9934c5a00ae722a98d1a06ed44b673514407b5 ] + +We destroy mutex-es too early as they are still taken in +v4l2_fh_exit()->v4l2_event_unsubscribe()->v4l2_ctrl_find(). + +We should destroy mutex-es right before kfree(). Also +do not vdec_ctrl_deinit() before v4l2_fh_exit(). + +Fixes: 7472c1c69138 ("[media] media: venus: vdec: add video decoder files") +Suggested-by: Tomasz Figa <tfiga@google.com> +Signed-off-by: Sergey Senozhatsky <senozhatsky@chromium.org> +Reviewed-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org> +Signed-off-by: Stanimir Varbanov <stanimir.k.varbanov@gmail.com> +Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/media/platform/qcom/venus/vdec.c | 7 ++++--- + drivers/media/platform/qcom/venus/venc.c | 6 +++--- + 2 files changed, 7 insertions(+), 6 deletions(-) + +diff --git a/drivers/media/platform/qcom/venus/vdec.c b/drivers/media/platform/qcom/venus/vdec.c +index d12089370d91e..4af268e756883 100644 +--- a/drivers/media/platform/qcom/venus/vdec.c ++++ b/drivers/media/platform/qcom/venus/vdec.c +@@ -1750,13 +1750,14 @@ static int vdec_close(struct file *file) + cancel_work_sync(&inst->delayed_process_work); + v4l2_m2m_ctx_release(inst->m2m_ctx); + v4l2_m2m_release(inst->m2m_dev); +- vdec_ctrl_deinit(inst); + ida_destroy(&inst->dpb_ids); + hfi_session_destroy(inst); +- mutex_destroy(&inst->lock); +- mutex_destroy(&inst->ctx_q_lock); + v4l2_fh_del(&inst->fh); + v4l2_fh_exit(&inst->fh); ++ vdec_ctrl_deinit(inst); ++ ++ mutex_destroy(&inst->lock); ++ mutex_destroy(&inst->ctx_q_lock); + + vdec_pm_put(inst, false); + +diff --git a/drivers/media/platform/qcom/venus/venc.c b/drivers/media/platform/qcom/venus/venc.c +index 3ec2fb8d9fab6..56777d3d630a5 100644 +--- a/drivers/media/platform/qcom/venus/venc.c ++++ b/drivers/media/platform/qcom/venus/venc.c +@@ -1517,14 +1517,14 @@ static int venc_close(struct file *file) + + v4l2_m2m_ctx_release(inst->m2m_ctx); + v4l2_m2m_release(inst->m2m_dev); +- venc_ctrl_deinit(inst); + hfi_session_destroy(inst); +- mutex_destroy(&inst->lock); +- mutex_destroy(&inst->ctx_q_lock); + v4l2_fh_del(&inst->fh); + v4l2_fh_exit(&inst->fh); ++ venc_ctrl_deinit(inst); + + inst->enc_state = VENUS_ENC_STATE_DEINIT; ++ mutex_destroy(&inst->lock); ++ mutex_destroy(&inst->ctx_q_lock); + + venc_pm_put(inst, false); + +-- +2.43.0 + diff --git a/queue-6.12/media-venus-sync-with-threaded-irq-during-inst-destr.patch b/queue-6.12/media-venus-sync-with-threaded-irq-during-inst-destr.patch new file mode 100644 index 00000000000..dcceff37f30 --- /dev/null +++ b/queue-6.12/media-venus-sync-with-threaded-irq-during-inst-destr.patch @@ -0,0 +1,146 @@ +From b880ce8c2c6a0e86b200cc7de817144149a92fd6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Sat, 26 Oct 2024 01:56:42 +0900 +Subject: media: venus: sync with threaded IRQ during inst destruction + +From: Sergey Senozhatsky <senozhatsky@chromium.org> + +[ Upstream commit 45b1a1b348ec178a599323f1ce7d7932aea8c6d4 ] + +When destroying an inst we should make sure that we don't race +against threaded IRQ (or pending IRQ), otherwise we can concurrently +kfree() inst context and inst itself. + +BUG: KASAN: slab-use-after-free in vb2_queue_error+0x80/0x90 +Call trace: +dump_backtrace+0x1c4/0x1f8 +show_stack+0x38/0x60 +dump_stack_lvl+0x168/0x1f0 +print_report+0x170/0x4c8 +kasan_report+0x94/0xd0 +__asan_report_load2_noabort+0x20/0x30 +vb2_queue_error+0x80/0x90 +venus_helper_vb2_queue_error+0x54/0x78 +venc_event_notify+0xec/0x158 +hfi_event_notify+0x878/0xd20 +hfi_process_msg_packet+0x27c/0x4e0 +venus_isr_thread+0x258/0x6e8 +hfi_isr_thread+0x70/0x90 +venus_isr_thread+0x34/0x50 +irq_thread_fn+0x88/0x130 +irq_thread+0x160/0x2c0 +kthread+0x294/0x328 +ret_from_fork+0x10/0x20 + +Allocated by task 20291: +kasan_set_track+0x4c/0x80 +kasan_save_alloc_info+0x28/0x38 +__kasan_kmalloc+0x84/0xa0 +kmalloc_trace+0x7c/0x98 +v4l2_m2m_ctx_init+0x74/0x280 +venc_open+0x444/0x6d0 +v4l2_open+0x19c/0x2a0 +chrdev_open+0x374/0x3f0 +do_dentry_open+0x710/0x10a8 +vfs_open+0x88/0xa8 +path_openat+0x1e6c/0x2700 +do_filp_open+0x1a4/0x2e0 +do_sys_openat2+0xe8/0x508 +do_sys_open+0x15c/0x1a0 +__arm64_sys_openat+0xa8/0xc8 +invoke_syscall+0xdc/0x270 +el0_svc_common+0x1ec/0x250 +do_el0_svc+0x54/0x70 +el0_svc+0x50/0xe8 +el0t_64_sync_handler+0x48/0x120 +el0t_64_sync+0x1a8/0x1b0 + +Freed by task 20291: + kasan_set_track+0x4c/0x80 + kasan_save_free_info+0x3c/0x60 + ____kasan_slab_free+0x124/0x1a0 + __kasan_slab_free+0x18/0x28 + __kmem_cache_free+0x134/0x300 + kfree+0xc8/0x1a8 + v4l2_m2m_ctx_release+0x44/0x60 + venc_close+0x78/0x130 [venus_enc] + v4l2_release+0x20c/0x2f8 + __fput+0x328/0x7f0 + ____fput+0x2c/0x48 + task_work_run+0x1e0/0x280 + get_signal+0xfb8/0x1190 + do_notify_resume+0x34c/0x16a8 + el0_svc+0x9c/0xe8 + el0t_64_sync_handler+0x48/0x120 + el0t_64_sync+0x1a8/0x1b0 + +Rearrange inst destruction. First remove the inst from the +core->instances list, second synchronize IRQ/IRQ-thread to +make sure that nothing else would see the inst while we take +it down. + +Fixes: 7472c1c69138 ("[media] media: venus: vdec: add video decoder files") +Signed-off-by: Sergey Senozhatsky <senozhatsky@chromium.org> +Reviewed-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org> +Signed-off-by: Stanimir Varbanov <stanimir.k.varbanov@gmail.com> +Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/media/platform/qcom/venus/vdec.c | 12 +++++++++++- + drivers/media/platform/qcom/venus/venc.c | 12 +++++++++++- + 2 files changed, 22 insertions(+), 2 deletions(-) + +diff --git a/drivers/media/platform/qcom/venus/vdec.c b/drivers/media/platform/qcom/venus/vdec.c +index 4af268e756883..b446046546403 100644 +--- a/drivers/media/platform/qcom/venus/vdec.c ++++ b/drivers/media/platform/qcom/venus/vdec.c +@@ -1748,10 +1748,20 @@ static int vdec_close(struct file *file) + vdec_pm_get(inst); + + cancel_work_sync(&inst->delayed_process_work); ++ /* ++ * First, remove the inst from the ->instances list, so that ++ * to_instance() will return NULL. ++ */ ++ hfi_session_destroy(inst); ++ /* ++ * Second, make sure we don't have IRQ/IRQ-thread currently running ++ * or pending execution, which would race with the inst destruction. ++ */ ++ synchronize_irq(inst->core->irq); ++ + v4l2_m2m_ctx_release(inst->m2m_ctx); + v4l2_m2m_release(inst->m2m_dev); + ida_destroy(&inst->dpb_ids); +- hfi_session_destroy(inst); + v4l2_fh_del(&inst->fh); + v4l2_fh_exit(&inst->fh); + vdec_ctrl_deinit(inst); +diff --git a/drivers/media/platform/qcom/venus/venc.c b/drivers/media/platform/qcom/venus/venc.c +index 56777d3d630a5..b83f03abbf0aa 100644 +--- a/drivers/media/platform/qcom/venus/venc.c ++++ b/drivers/media/platform/qcom/venus/venc.c +@@ -1515,9 +1515,19 @@ static int venc_close(struct file *file) + + venc_pm_get(inst); + ++ /* ++ * First, remove the inst from the ->instances list, so that ++ * to_instance() will return NULL. ++ */ ++ hfi_session_destroy(inst); ++ /* ++ * Second, make sure we don't have IRQ/IRQ-thread currently running ++ * or pending execution, which would race with the inst destruction. ++ */ ++ synchronize_irq(inst->core->irq); ++ + v4l2_m2m_ctx_release(inst->m2m_ctx); + v4l2_m2m_release(inst->m2m_dev); +- hfi_session_destroy(inst); + v4l2_fh_del(&inst->fh); + v4l2_fh_exit(&inst->fh); + venc_ctrl_deinit(inst); +-- +2.43.0 + diff --git a/queue-6.12/mfd-da9052-spi-change-read-mask-to-write-mask.patch b/queue-6.12/mfd-da9052-spi-change-read-mask-to-write-mask.patch new file mode 100644 index 00000000000..aa772b31f12 --- /dev/null +++ b/queue-6.12/mfd-da9052-spi-change-read-mask-to-write-mask.patch @@ -0,0 +1,38 @@ +From b32cfe205575cae7140f3ec2d836614ff944f58a Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Wed, 25 Sep 2024 12:19:53 +0200 +Subject: mfd: da9052-spi: Change read-mask to write-mask + +From: Marcus Folkesson <marcus.folkesson@gmail.com> + +[ Upstream commit 2e3378f6c79a1b3f7855ded1ef306ea4406352ed ] + +Driver has mixed up the R/W bit. +The LSB bit is set on write rather than read. +Change it to avoid nasty things to happen. + +Fixes: e9e9d3973594 ("mfd: da9052: Avoid setting read_flag_mask for da9052-i2c driver") +Signed-off-by: Marcus Folkesson <marcus.folkesson@gmail.com> +Link: https://lore.kernel.org/r/20240925-da9052-v2-1-f243e4505b07@gmail.com +Signed-off-by: Lee Jones <lee@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/mfd/da9052-spi.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/mfd/da9052-spi.c b/drivers/mfd/da9052-spi.c +index be5f2b34e18ae..80fc5c0cac2fb 100644 +--- a/drivers/mfd/da9052-spi.c ++++ b/drivers/mfd/da9052-spi.c +@@ -37,7 +37,7 @@ static int da9052_spi_probe(struct spi_device *spi) + spi_set_drvdata(spi, da9052); + + config = da9052_regmap_config; +- config.read_flag_mask = 1; ++ config.write_flag_mask = 1; + config.reg_bits = 7; + config.pad_bits = 1; + config.val_bits = 8; +-- +2.43.0 + diff --git a/queue-6.12/mfd-intel_soc_pmic_bxtwc-fix-irq-domain-names-duplic.patch b/queue-6.12/mfd-intel_soc_pmic_bxtwc-fix-irq-domain-names-duplic.patch new file mode 100644 index 00000000000..b980dc4a1f4 --- /dev/null +++ b/queue-6.12/mfd-intel_soc_pmic_bxtwc-fix-irq-domain-names-duplic.patch @@ -0,0 +1,84 @@ +From 2e63abc5520ab7a0f5096c538ed062dc3f228da9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Sat, 5 Oct 2024 22:27:07 +0300 +Subject: mfd: intel_soc_pmic_bxtwc: Fix IRQ domain names duplication + +From: Andy Shevchenko <andriy.shevchenko@linux.intel.com> + +[ Upstream commit 3727c0b4ff6ba0e61203544b4c831f7f8899753b ] + +For all of the devices regmap IRQ may try to created the folder +with the same name which is impossible and fails with: + + debugfs: File '\_SB.IPC1.PMIC' in directory 'domains' already present! + +Add domain_suffix to all of the IRQ chips driver registers to solve +the issue. + +Fixes: 39d047c0b1c8 ("mfd: add Intel Broxton Whiskey Cove PMIC driver") +Fixes: 957ae5098185 ("platform/x86: Add Whiskey Cove PMIC TMU support") +Fixes: 57129044f504 ("mfd: intel_soc_pmic_bxtwc: Use chained IRQs for second level IRQ chips") +Depends-on: dde286ee5770 ("regmap: Allow setting IRQ domain name suffix") +Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com> +Link: https://lore.kernel.org/r/20241005193029.1929139-5-andriy.shevchenko@linux.intel.com +Signed-off-by: Lee Jones <lee@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/mfd/intel_soc_pmic_bxtwc.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/drivers/mfd/intel_soc_pmic_bxtwc.c b/drivers/mfd/intel_soc_pmic_bxtwc.c +index fefbeb4164fde..b7204072e93ef 100644 +--- a/drivers/mfd/intel_soc_pmic_bxtwc.c ++++ b/drivers/mfd/intel_soc_pmic_bxtwc.c +@@ -148,6 +148,7 @@ static const struct regmap_irq_chip bxtwc_regmap_irq_chip = { + + static const struct regmap_irq_chip bxtwc_regmap_irq_chip_pwrbtn = { + .name = "bxtwc_irq_chip_pwrbtn", ++ .domain_suffix = "PWRBTN", + .status_base = BXTWC_PWRBTNIRQ, + .mask_base = BXTWC_MPWRBTNIRQ, + .irqs = bxtwc_regmap_irqs_pwrbtn, +@@ -157,6 +158,7 @@ static const struct regmap_irq_chip bxtwc_regmap_irq_chip_pwrbtn = { + + static const struct regmap_irq_chip bxtwc_regmap_irq_chip_tmu = { + .name = "bxtwc_irq_chip_tmu", ++ .domain_suffix = "TMU", + .status_base = BXTWC_TMUIRQ, + .mask_base = BXTWC_MTMUIRQ, + .irqs = bxtwc_regmap_irqs_tmu, +@@ -166,6 +168,7 @@ static const struct regmap_irq_chip bxtwc_regmap_irq_chip_tmu = { + + static const struct regmap_irq_chip bxtwc_regmap_irq_chip_bcu = { + .name = "bxtwc_irq_chip_bcu", ++ .domain_suffix = "BCU", + .status_base = BXTWC_BCUIRQ, + .mask_base = BXTWC_MBCUIRQ, + .irqs = bxtwc_regmap_irqs_bcu, +@@ -175,6 +178,7 @@ static const struct regmap_irq_chip bxtwc_regmap_irq_chip_bcu = { + + static const struct regmap_irq_chip bxtwc_regmap_irq_chip_adc = { + .name = "bxtwc_irq_chip_adc", ++ .domain_suffix = "ADC", + .status_base = BXTWC_ADCIRQ, + .mask_base = BXTWC_MADCIRQ, + .irqs = bxtwc_regmap_irqs_adc, +@@ -184,6 +188,7 @@ static const struct regmap_irq_chip bxtwc_regmap_irq_chip_adc = { + + static const struct regmap_irq_chip bxtwc_regmap_irq_chip_chgr = { + .name = "bxtwc_irq_chip_chgr", ++ .domain_suffix = "CHGR", + .status_base = BXTWC_CHGR0IRQ, + .mask_base = BXTWC_MCHGR0IRQ, + .irqs = bxtwc_regmap_irqs_chgr, +@@ -193,6 +198,7 @@ static const struct regmap_irq_chip bxtwc_regmap_irq_chip_chgr = { + + static const struct regmap_irq_chip bxtwc_regmap_irq_chip_crit = { + .name = "bxtwc_irq_chip_crit", ++ .domain_suffix = "CRIT", + .status_base = BXTWC_CRITIRQ, + .mask_base = BXTWC_MCRITIRQ, + .irqs = bxtwc_regmap_irqs_crit, +-- +2.43.0 + diff --git a/queue-6.12/mfd-intel_soc_pmic_bxtwc-use-irq-domain-for-pmic-dev.patch b/queue-6.12/mfd-intel_soc_pmic_bxtwc-use-irq-domain-for-pmic-dev.patch new file mode 100644 index 00000000000..97de70fc50a --- /dev/null +++ b/queue-6.12/mfd-intel_soc_pmic_bxtwc-use-irq-domain-for-pmic-dev.patch @@ -0,0 +1,118 @@ +From 8fbd1d84be7a1f6627f46be6287c3ad6712b4a4c Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Sat, 5 Oct 2024 22:27:06 +0300 +Subject: mfd: intel_soc_pmic_bxtwc: Use IRQ domain for PMIC devices + +From: Andy Shevchenko <andriy.shevchenko@linux.intel.com> + +[ Upstream commit 0350d783ab888cb1cb48ced36cc28b372723f1a4 ] + +While design wise the idea of converting the driver to use +the hierarchy of the IRQ chips is correct, the implementation +has (inherited) flaws. This was unveiled when platform_get_irq() +had started WARN() on IRQ 0 that is supposed to be a Linux +IRQ number (also known as vIRQ). + +Rework the driver to respect IRQ domain when creating each MFD +device separately, as the domain is not the same for all of them. + +Fixes: 57129044f504 ("mfd: intel_soc_pmic_bxtwc: Use chained IRQs for second level IRQ chips") +Tested-by: Zhang Ning <zhangn1985@outlook.com> +Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com> +Link: https://lore.kernel.org/r/20241005193029.1929139-4-andriy.shevchenko@linux.intel.com +Signed-off-by: Lee Jones <lee@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/mfd/intel_soc_pmic_bxtwc.c | 54 +++++++++++++++++------------- + 1 file changed, 30 insertions(+), 24 deletions(-) + +diff --git a/drivers/mfd/intel_soc_pmic_bxtwc.c b/drivers/mfd/intel_soc_pmic_bxtwc.c +index 628108dcf5454..fefbeb4164fde 100644 +--- a/drivers/mfd/intel_soc_pmic_bxtwc.c ++++ b/drivers/mfd/intel_soc_pmic_bxtwc.c +@@ -230,21 +230,11 @@ static const struct resource tmu_resources[] = { + }; + + static struct mfd_cell bxt_wc_dev[] = { +- { +- .name = "bxt_wcove_gpadc", +- .num_resources = ARRAY_SIZE(adc_resources), +- .resources = adc_resources, +- }, + { + .name = "bxt_wcove_thermal", + .num_resources = ARRAY_SIZE(thermal_resources), + .resources = thermal_resources, + }, +- { +- .name = "bxt_wcove_bcu", +- .num_resources = ARRAY_SIZE(bcu_resources), +- .resources = bcu_resources, +- }, + { + .name = "bxt_wcove_gpio", + .num_resources = ARRAY_SIZE(gpio_resources), +@@ -263,6 +253,22 @@ static const struct mfd_cell bxt_wc_tmu_dev[] = { + }, + }; + ++static const struct mfd_cell bxt_wc_bcu_dev[] = { ++ { ++ .name = "bxt_wcove_bcu", ++ .num_resources = ARRAY_SIZE(bcu_resources), ++ .resources = bcu_resources, ++ }, ++}; ++ ++static const struct mfd_cell bxt_wc_adc_dev[] = { ++ { ++ .name = "bxt_wcove_gpadc", ++ .num_resources = ARRAY_SIZE(adc_resources), ++ .resources = adc_resources, ++ }, ++}; ++ + static struct mfd_cell bxt_wc_chgr_dev[] = { + { + .name = "bxt_wcove_usbc", +@@ -508,23 +514,23 @@ static int bxtwc_probe(struct platform_device *pdev) + if (ret) + return dev_err_probe(dev, ret, "Failed to add PWRBTN IRQ chip\n"); + +- /* Add chained IRQ handler for BCU IRQs */ +- ret = bxtwc_add_chained_irq_chip(pmic, pmic->irq_chip_data, +- BXTWC_BCU_LVL1_IRQ, +- IRQF_ONESHOT, +- &bxtwc_regmap_irq_chip_bcu, +- &pmic->irq_chip_data_bcu); ++ ret = bxtwc_add_chained_devices(pmic, bxt_wc_bcu_dev, ARRAY_SIZE(bxt_wc_bcu_dev), ++ pmic->irq_chip_data, ++ BXTWC_BCU_LVL1_IRQ, ++ IRQF_ONESHOT, ++ &bxtwc_regmap_irq_chip_bcu, ++ &pmic->irq_chip_data_bcu); + if (ret) +- return dev_err_probe(dev, ret, "Failed to add BUC IRQ chip\n"); ++ return ret; + +- /* Add chained IRQ handler for ADC IRQs */ +- ret = bxtwc_add_chained_irq_chip(pmic, pmic->irq_chip_data, +- BXTWC_ADC_LVL1_IRQ, +- IRQF_ONESHOT, +- &bxtwc_regmap_irq_chip_adc, +- &pmic->irq_chip_data_adc); ++ ret = bxtwc_add_chained_devices(pmic, bxt_wc_adc_dev, ARRAY_SIZE(bxt_wc_adc_dev), ++ pmic->irq_chip_data, ++ BXTWC_ADC_LVL1_IRQ, ++ IRQF_ONESHOT, ++ &bxtwc_regmap_irq_chip_adc, ++ &pmic->irq_chip_data_adc); + if (ret) +- return dev_err_probe(dev, ret, "Failed to add ADC IRQ chip\n"); ++ return ret; + + ret = bxtwc_add_chained_devices(pmic, bxt_wc_chgr_dev, ARRAY_SIZE(bxt_wc_chgr_dev), + pmic->irq_chip_data, +-- +2.43.0 + diff --git a/queue-6.12/mfd-intel_soc_pmic_bxtwc-use-irq-domain-for-tmu-devi.patch b/queue-6.12/mfd-intel_soc_pmic_bxtwc-use-irq-domain-for-tmu-devi.patch new file mode 100644 index 00000000000..715f4787bf3 --- /dev/null +++ b/queue-6.12/mfd-intel_soc_pmic_bxtwc-use-irq-domain-for-tmu-devi.patch @@ -0,0 +1,147 @@ +From 0f5541d38831a09719548886c8bb301758c269d1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Sat, 5 Oct 2024 22:27:05 +0300 +Subject: mfd: intel_soc_pmic_bxtwc: Use IRQ domain for TMU device + +From: Andy Shevchenko <andriy.shevchenko@linux.intel.com> + +[ Upstream commit 9b79d59e6b2b515eb9a22bc469ef7b8f0904fc73 ] + +While design wise the idea of converting the driver to use +the hierarchy of the IRQ chips is correct, the implementation +has (inherited) flaws. This was unveiled when platform_get_irq() +had started WARN() on IRQ 0 that is supposed to be a Linux +IRQ number (also known as vIRQ). + +Rework the driver to respect IRQ domain when creating each MFD +device separately, as the domain is not the same for all of them. + +Fixes: 957ae5098185 ("platform/x86: Add Whiskey Cove PMIC TMU support") +Fixes: 57129044f504 ("mfd: intel_soc_pmic_bxtwc: Use chained IRQs for second level IRQ chips") +Reported-by: Zhang Ning <zhangn1985@outlook.com> +Closes: https://lore.kernel.org/r/TY2PR01MB3322FEDCDC048B7D3794F922CDBA2@TY2PR01MB3322.jpnprd01.prod.outlook.com +Tested-by: Zhang Ning <zhangn1985@outlook.com> +Acked-by: Hans de Goede <hdegoede@redhat.com> +Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com> +Link: https://lore.kernel.org/r/20241005193029.1929139-3-andriy.shevchenko@linux.intel.com +Signed-off-by: Lee Jones <lee@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/mfd/intel_soc_pmic_bxtwc.c | 31 ++++++++++++++------------ + drivers/platform/x86/intel/bxtwc_tmu.c | 22 +++++------------- + 2 files changed, 23 insertions(+), 30 deletions(-) + +diff --git a/drivers/mfd/intel_soc_pmic_bxtwc.c b/drivers/mfd/intel_soc_pmic_bxtwc.c +index d72995a9e8207..628108dcf5454 100644 +--- a/drivers/mfd/intel_soc_pmic_bxtwc.c ++++ b/drivers/mfd/intel_soc_pmic_bxtwc.c +@@ -245,12 +245,6 @@ static struct mfd_cell bxt_wc_dev[] = { + .num_resources = ARRAY_SIZE(bcu_resources), + .resources = bcu_resources, + }, +- { +- .name = "bxt_wcove_tmu", +- .num_resources = ARRAY_SIZE(tmu_resources), +- .resources = tmu_resources, +- }, +- + { + .name = "bxt_wcove_gpio", + .num_resources = ARRAY_SIZE(gpio_resources), +@@ -261,6 +255,14 @@ static struct mfd_cell bxt_wc_dev[] = { + }, + }; + ++static const struct mfd_cell bxt_wc_tmu_dev[] = { ++ { ++ .name = "bxt_wcove_tmu", ++ .num_resources = ARRAY_SIZE(tmu_resources), ++ .resources = tmu_resources, ++ }, ++}; ++ + static struct mfd_cell bxt_wc_chgr_dev[] = { + { + .name = "bxt_wcove_usbc", +@@ -489,6 +491,15 @@ static int bxtwc_probe(struct platform_device *pdev) + if (ret) + return dev_err_probe(dev, ret, "Failed to add IRQ chip\n"); + ++ ret = bxtwc_add_chained_devices(pmic, bxt_wc_tmu_dev, ARRAY_SIZE(bxt_wc_tmu_dev), ++ pmic->irq_chip_data, ++ BXTWC_TMU_LVL1_IRQ, ++ IRQF_ONESHOT, ++ &bxtwc_regmap_irq_chip_tmu, ++ &pmic->irq_chip_data_tmu); ++ if (ret) ++ return ret; ++ + ret = bxtwc_add_chained_irq_chip(pmic, pmic->irq_chip_data, + BXTWC_PWRBTN_LVL1_IRQ, + IRQF_ONESHOT, +@@ -497,14 +508,6 @@ static int bxtwc_probe(struct platform_device *pdev) + if (ret) + return dev_err_probe(dev, ret, "Failed to add PWRBTN IRQ chip\n"); + +- ret = bxtwc_add_chained_irq_chip(pmic, pmic->irq_chip_data, +- BXTWC_TMU_LVL1_IRQ, +- IRQF_ONESHOT, +- &bxtwc_regmap_irq_chip_tmu, +- &pmic->irq_chip_data_tmu); +- if (ret) +- return dev_err_probe(dev, ret, "Failed to add TMU IRQ chip\n"); +- + /* Add chained IRQ handler for BCU IRQs */ + ret = bxtwc_add_chained_irq_chip(pmic, pmic->irq_chip_data, + BXTWC_BCU_LVL1_IRQ, +diff --git a/drivers/platform/x86/intel/bxtwc_tmu.c b/drivers/platform/x86/intel/bxtwc_tmu.c +index d0e2a3c293b0b..9ac801b929b93 100644 +--- a/drivers/platform/x86/intel/bxtwc_tmu.c ++++ b/drivers/platform/x86/intel/bxtwc_tmu.c +@@ -48,9 +48,8 @@ static irqreturn_t bxt_wcove_tmu_irq_handler(int irq, void *data) + static int bxt_wcove_tmu_probe(struct platform_device *pdev) + { + struct intel_soc_pmic *pmic = dev_get_drvdata(pdev->dev.parent); +- struct regmap_irq_chip_data *regmap_irq_chip; + struct wcove_tmu *wctmu; +- int ret, virq, irq; ++ int ret; + + wctmu = devm_kzalloc(&pdev->dev, sizeof(*wctmu), GFP_KERNEL); + if (!wctmu) +@@ -59,27 +58,18 @@ static int bxt_wcove_tmu_probe(struct platform_device *pdev) + wctmu->dev = &pdev->dev; + wctmu->regmap = pmic->regmap; + +- irq = platform_get_irq(pdev, 0); +- if (irq < 0) +- return irq; ++ wctmu->irq = platform_get_irq(pdev, 0); ++ if (wctmu->irq < 0) ++ return wctmu->irq; + +- regmap_irq_chip = pmic->irq_chip_data_tmu; +- virq = regmap_irq_get_virq(regmap_irq_chip, irq); +- if (virq < 0) { +- dev_err(&pdev->dev, +- "failed to get virtual interrupt=%d\n", irq); +- return virq; +- } +- +- ret = devm_request_threaded_irq(&pdev->dev, virq, ++ ret = devm_request_threaded_irq(&pdev->dev, wctmu->irq, + NULL, bxt_wcove_tmu_irq_handler, + IRQF_ONESHOT, "bxt_wcove_tmu", wctmu); + if (ret) { + dev_err(&pdev->dev, "request irq failed: %d,virq: %d\n", +- ret, virq); ++ ret, wctmu->irq); + return ret; + } +- wctmu->irq = virq; + + /* Unmask TMU second level Wake & System alarm */ + regmap_update_bits(wctmu->regmap, BXTWC_MTMUIRQ_REG, +-- +2.43.0 + diff --git a/queue-6.12/mfd-intel_soc_pmic_bxtwc-use-irq-domain-for-usb-type.patch b/queue-6.12/mfd-intel_soc_pmic_bxtwc-use-irq-domain-for-usb-type.patch new file mode 100644 index 00000000000..75ca5b57306 --- /dev/null +++ b/queue-6.12/mfd-intel_soc_pmic_bxtwc-use-irq-domain-for-usb-type.patch @@ -0,0 +1,142 @@ +From c8bb76d0522d10eea254baccdd8371f875817154 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Sat, 5 Oct 2024 22:27:04 +0300 +Subject: mfd: intel_soc_pmic_bxtwc: Use IRQ domain for USB Type-C device + +From: Andy Shevchenko <andriy.shevchenko@linux.intel.com> + +[ Upstream commit 686fb77712a4bc94b76a0c5ae74c60118b7a0d79 ] + +While design wise the idea of converting the driver to use +the hierarchy of the IRQ chips is correct, the implementation +has (inherited) flaws. This was unveiled when platform_get_irq() +had started WARN() on IRQ 0 that is supposed to be a Linux +IRQ number (also known as vIRQ). + +Rework the driver to respect IRQ domain when creating each MFD +device separately, as the domain is not the same for all of them. + +Fixes: 9c6235c86332 ("mfd: intel_soc_pmic_bxtwc: Add bxt_wcove_usbc device") +Fixes: d2061f9cc32d ("usb: typec: add driver for Intel Whiskey Cove PMIC USB Type-C PHY") +Fixes: 57129044f504 ("mfd: intel_soc_pmic_bxtwc: Use chained IRQs for second level IRQ chips") +Reported-by: Zhang Ning <zhangn1985@outlook.com> +Closes: https://lore.kernel.org/r/TY2PR01MB3322FEDCDC048B7D3794F922CDBA2@TY2PR01MB3322.jpnprd01.prod.outlook.com +Tested-by: Zhang Ning <zhangn1985@outlook.com> +Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com> +Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +Link: https://lore.kernel.org/r/20241005193029.1929139-2-andriy.shevchenko@linux.intel.com +Signed-off-by: Lee Jones <lee@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/mfd/intel_soc_pmic_bxtwc.c | 57 +++++++++++++++++++++--------- + drivers/usb/typec/tcpm/wcove.c | 4 --- + 2 files changed, 40 insertions(+), 21 deletions(-) + +diff --git a/drivers/mfd/intel_soc_pmic_bxtwc.c b/drivers/mfd/intel_soc_pmic_bxtwc.c +index ccd76800d8e49..d72995a9e8207 100644 +--- a/drivers/mfd/intel_soc_pmic_bxtwc.c ++++ b/drivers/mfd/intel_soc_pmic_bxtwc.c +@@ -240,16 +240,6 @@ static struct mfd_cell bxt_wc_dev[] = { + .num_resources = ARRAY_SIZE(thermal_resources), + .resources = thermal_resources, + }, +- { +- .name = "bxt_wcove_usbc", +- .num_resources = ARRAY_SIZE(usbc_resources), +- .resources = usbc_resources, +- }, +- { +- .name = "bxt_wcove_ext_charger", +- .num_resources = ARRAY_SIZE(charger_resources), +- .resources = charger_resources, +- }, + { + .name = "bxt_wcove_bcu", + .num_resources = ARRAY_SIZE(bcu_resources), +@@ -271,6 +261,19 @@ static struct mfd_cell bxt_wc_dev[] = { + }, + }; + ++static struct mfd_cell bxt_wc_chgr_dev[] = { ++ { ++ .name = "bxt_wcove_usbc", ++ .num_resources = ARRAY_SIZE(usbc_resources), ++ .resources = usbc_resources, ++ }, ++ { ++ .name = "bxt_wcove_ext_charger", ++ .num_resources = ARRAY_SIZE(charger_resources), ++ .resources = charger_resources, ++ }, ++}; ++ + static int regmap_ipc_byte_reg_read(void *context, unsigned int reg, + unsigned int *val) + { +@@ -425,6 +428,26 @@ static int bxtwc_add_chained_irq_chip(struct intel_soc_pmic *pmic, + 0, chip, data); + } + ++static int bxtwc_add_chained_devices(struct intel_soc_pmic *pmic, ++ const struct mfd_cell *cells, int n_devs, ++ struct regmap_irq_chip_data *pdata, ++ int pirq, int irq_flags, ++ const struct regmap_irq_chip *chip, ++ struct regmap_irq_chip_data **data) ++{ ++ struct device *dev = pmic->dev; ++ struct irq_domain *domain; ++ int ret; ++ ++ ret = bxtwc_add_chained_irq_chip(pmic, pdata, pirq, irq_flags, chip, data); ++ if (ret) ++ return dev_err_probe(dev, ret, "Failed to add %s IRQ chip\n", chip->name); ++ ++ domain = regmap_irq_get_domain(*data); ++ ++ return devm_mfd_add_devices(dev, PLATFORM_DEVID_NONE, cells, n_devs, NULL, 0, domain); ++} ++ + static int bxtwc_probe(struct platform_device *pdev) + { + struct device *dev = &pdev->dev; +@@ -500,14 +523,14 @@ static int bxtwc_probe(struct platform_device *pdev) + if (ret) + return dev_err_probe(dev, ret, "Failed to add ADC IRQ chip\n"); + +- /* Add chained IRQ handler for CHGR IRQs */ +- ret = bxtwc_add_chained_irq_chip(pmic, pmic->irq_chip_data, +- BXTWC_CHGR_LVL1_IRQ, +- IRQF_ONESHOT, +- &bxtwc_regmap_irq_chip_chgr, +- &pmic->irq_chip_data_chgr); ++ ret = bxtwc_add_chained_devices(pmic, bxt_wc_chgr_dev, ARRAY_SIZE(bxt_wc_chgr_dev), ++ pmic->irq_chip_data, ++ BXTWC_CHGR_LVL1_IRQ, ++ IRQF_ONESHOT, ++ &bxtwc_regmap_irq_chip_chgr, ++ &pmic->irq_chip_data_chgr); + if (ret) +- return dev_err_probe(dev, ret, "Failed to add CHGR IRQ chip\n"); ++ return ret; + + /* Add chained IRQ handler for CRIT IRQs */ + ret = bxtwc_add_chained_irq_chip(pmic, pmic->irq_chip_data, +diff --git a/drivers/usb/typec/tcpm/wcove.c b/drivers/usb/typec/tcpm/wcove.c +index cf719307b3f6b..60b2766a69bf8 100644 +--- a/drivers/usb/typec/tcpm/wcove.c ++++ b/drivers/usb/typec/tcpm/wcove.c +@@ -621,10 +621,6 @@ static int wcove_typec_probe(struct platform_device *pdev) + if (irq < 0) + return irq; + +- irq = regmap_irq_get_virq(pmic->irq_chip_data_chgr, irq); +- if (irq < 0) +- return irq; +- + ret = guid_parse(WCOVE_DSM_UUID, &wcove->guid); + if (ret) + return ret; +-- +2.43.0 + diff --git a/queue-6.12/mfd-rt5033-fix-missing-regmap_del_irq_chip.patch b/queue-6.12/mfd-rt5033-fix-missing-regmap_del_irq_chip.patch new file mode 100644 index 00000000000..b5e8109a866 --- /dev/null +++ b/queue-6.12/mfd-rt5033-fix-missing-regmap_del_irq_chip.patch @@ -0,0 +1,39 @@ +From 48784f14ca4ecf0c4e1d8c3f7e2bd4c3060ab4ef Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Wed, 30 Oct 2024 23:41:06 +0800 +Subject: mfd: rt5033: Fix missing regmap_del_irq_chip() + +From: Zhang Changzhong <zhangchangzhong@huawei.com> + +[ Upstream commit d256d612f47529ed0b332298e2d5ea981a4dd5b8 ] + +Fix missing call to regmap_del_irq_chip() in error handling path by +using devm_regmap_add_irq_chip(). + +Fixes: 0b271258544b ("mfd: rt5033: Add Richtek RT5033 driver core.") +Signed-off-by: Zhang Changzhong <zhangchangzhong@huawei.com> +Link: https://lore.kernel.org/r/1730302867-8391-1-git-send-email-zhangchangzhong@huawei.com +Signed-off-by: Lee Jones <lee@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/mfd/rt5033.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/mfd/rt5033.c b/drivers/mfd/rt5033.c +index 7e23ab3d5842c..84ebc96f58e48 100644 +--- a/drivers/mfd/rt5033.c ++++ b/drivers/mfd/rt5033.c +@@ -81,8 +81,8 @@ static int rt5033_i2c_probe(struct i2c_client *i2c) + chip_rev = dev_id & RT5033_CHIP_REV_MASK; + dev_info(&i2c->dev, "Device found (rev. %d)\n", chip_rev); + +- ret = regmap_add_irq_chip(rt5033->regmap, rt5033->irq, +- IRQF_TRIGGER_FALLING | IRQF_ONESHOT, ++ ret = devm_regmap_add_irq_chip(rt5033->dev, rt5033->regmap, ++ rt5033->irq, IRQF_TRIGGER_FALLING | IRQF_ONESHOT, + 0, &rt5033_irq_chip, &rt5033->irq_data); + if (ret) { + dev_err(&i2c->dev, "Failed to request IRQ %d: %d\n", +-- +2.43.0 + diff --git a/queue-6.12/mfd-tps65010-use-irqf_no_autoen-flag-in-request_irq-.patch b/queue-6.12/mfd-tps65010-use-irqf_no_autoen-flag-in-request_irq-.patch new file mode 100644 index 00000000000..cce02468e3d --- /dev/null +++ b/queue-6.12/mfd-tps65010-use-irqf_no_autoen-flag-in-request_irq-.patch @@ -0,0 +1,49 @@ +From eae0ea66f7ac20c28871b73ae97e522294143844 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Thu, 12 Sep 2024 11:15:30 +0800 +Subject: mfd: tps65010: Use IRQF_NO_AUTOEN flag in request_irq() to fix race + +From: Jinjie Ruan <ruanjinjie@huawei.com> + +[ Upstream commit 2174f9a8c9db50f74df769edd5a4ab822c73b6d2 ] + +As the comment said, disable_irq() after request_irq() still has a +time gap in which interrupts can come. request_irq() with IRQF_NO_AUTOEN +flag will disable IRQ auto-enable when request IRQ. + +Fixes: 72cd799544f2 ("[PATCH] I2C: add i2c driver for TPS6501x") +Signed-off-by: Jinjie Ruan <ruanjinjie@huawei.com> +Link: https://lore.kernel.org/r/20240912031530.2211654-1-ruanjinjie@huawei.com +Signed-off-by: Lee Jones <lee@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/mfd/tps65010.c | 8 ++------ + 1 file changed, 2 insertions(+), 6 deletions(-) + +diff --git a/drivers/mfd/tps65010.c b/drivers/mfd/tps65010.c +index 2b9105295f301..710364435b6b9 100644 +--- a/drivers/mfd/tps65010.c ++++ b/drivers/mfd/tps65010.c +@@ -544,17 +544,13 @@ static int tps65010_probe(struct i2c_client *client) + */ + if (client->irq > 0) { + status = request_irq(client->irq, tps65010_irq, +- IRQF_TRIGGER_FALLING, DRIVER_NAME, tps); ++ IRQF_TRIGGER_FALLING | IRQF_NO_AUTOEN, ++ DRIVER_NAME, tps); + if (status < 0) { + dev_dbg(&client->dev, "can't get IRQ %d, err %d\n", + client->irq, status); + return status; + } +- /* annoying race here, ideally we'd have an option +- * to claim the irq now and enable it later. +- * FIXME genirq IRQF_NOAUTOEN now solves that ... +- */ +- disable_irq(client->irq); + set_bit(FLAG_IRQ_ENABLE, &tps->flags); + } else + dev_warn(&client->dev, "IRQ not configured!\n"); +-- +2.43.0 + diff --git a/queue-6.12/microblaze-export-xmb_manager-functions.patch b/queue-6.12/microblaze-export-xmb_manager-functions.patch new file mode 100644 index 00000000000..94233097127 --- /dev/null +++ b/queue-6.12/microblaze-export-xmb_manager-functions.patch @@ -0,0 +1,58 @@ +From fd4e5ea2fd3a788a995fd697f20c653aba10e31b Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Wed, 19 Jun 2024 14:11:32 +0200 +Subject: microblaze: Export xmb_manager functions + +From: Michal Simek <michal.simek@amd.com> + +[ Upstream commit badf752b5e4b17d281f93f409d4718388ff912e6 ] + +When TMR_MANAGER is enabled as module there is a need to export functions +which are present in architecture code. + +It has been found by running: +make W=1 C=1 allmodconfig +sed -i -e 's/WERROR=y/WERROR=n/g' .config +make C=1 W=1 + +which errors out like this: +ERROR: modpost: "xmb_manager_register" [drivers/misc/xilinx_tmr_manager.ko] undefined! +ERROR: modpost: "xmb_inject_err" [drivers/misc/xilinx_tmr_inject.ko] undefined! + +Fixes: a5e3aaa654c1 ("microblaze: Add xmb_manager_register function") +Reported-by: Jeff Johnson <quic_jjohnson@quicinc.com> +Signed-off-by: Michal Simek <michal.simek@amd.com> +Link: https://lore.kernel.org/r/e322dbbbde0feef83f44304ea13249d365d1dc5f.1718799090.git.michal.simek@amd.com +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + arch/microblaze/kernel/microblaze_ksyms.c | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +diff --git a/arch/microblaze/kernel/microblaze_ksyms.c b/arch/microblaze/kernel/microblaze_ksyms.c +index c892e173ec990..a8553f54152b7 100644 +--- a/arch/microblaze/kernel/microblaze_ksyms.c ++++ b/arch/microblaze/kernel/microblaze_ksyms.c +@@ -16,6 +16,7 @@ + #include <asm/page.h> + #include <linux/ftrace.h> + #include <linux/uaccess.h> ++#include <asm/xilinx_mb_manager.h> + + #ifdef CONFIG_FUNCTION_TRACER + extern void _mcount(void); +@@ -46,3 +47,12 @@ extern void __udivsi3(void); + EXPORT_SYMBOL(__udivsi3); + extern void __umodsi3(void); + EXPORT_SYMBOL(__umodsi3); ++ ++#ifdef CONFIG_MB_MANAGER ++extern void xmb_manager_register(uintptr_t phys_baseaddr, u32 cr_val, ++ void (*callback)(void *data), ++ void *priv, void (*reset_callback)(void *data)); ++EXPORT_SYMBOL(xmb_manager_register); ++extern asmlinkage void xmb_inject_err(void); ++EXPORT_SYMBOL(xmb_inject_err); ++#endif +-- +2.43.0 + diff --git a/queue-6.12/mips-asm-fix-warning-when-disabling-mips_fp_support.patch b/queue-6.12/mips-asm-fix-warning-when-disabling-mips_fp_support.patch new file mode 100644 index 00000000000..3618e852fad --- /dev/null +++ b/queue-6.12/mips-asm-fix-warning-when-disabling-mips_fp_support.patch @@ -0,0 +1,49 @@ +From fe7fac573a8fe90f6a9efcd3d1a30333be53ac0b Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Sat, 12 Oct 2024 12:12:14 +0200 +Subject: mips: asm: fix warning when disabling MIPS_FP_SUPPORT + +From: Jonas Gorski <jonas.gorski@gmail.com> + +[ Upstream commit da09935975c8f8c90d6f57be2422dee5557206cd ] + +When MIPS_FP_SUPPORT is disabled, __sanitize_fcr31() is defined as +nothing, which triggers a gcc warning: + + In file included from kernel/sched/core.c:79: + kernel/sched/core.c: In function 'context_switch': + ./arch/mips/include/asm/switch_to.h:114:39: warning: suggest braces around empty body in an 'if' statement [-Wempty-body] + 114 | __sanitize_fcr31(next); \ + | ^ + kernel/sched/core.c:5316:9: note: in expansion of macro 'switch_to' + 5316 | switch_to(prev, next, prev); + | ^~~~~~~~~ + +Fix this by providing an empty body for __sanitize_fcr31() like one is +defined for __mips_mt_fpaff_switch_to(). + +Fixes: 36a498035bd2 ("MIPS: Avoid FCSR sanitization when CONFIG_MIPS_FP_SUPPORT=n") +Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com> +Reviewed-by: Maciej W. Rozycki <macro@orcam.me.uk> +Signed-off-by: Thomas Bogendoerfer <tsbogend@alpha.franken.de> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + arch/mips/include/asm/switch_to.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/arch/mips/include/asm/switch_to.h b/arch/mips/include/asm/switch_to.h +index a4374b4cb88fd..d6ccd53440213 100644 +--- a/arch/mips/include/asm/switch_to.h ++++ b/arch/mips/include/asm/switch_to.h +@@ -97,7 +97,7 @@ do { \ + } \ + } while (0) + #else +-# define __sanitize_fcr31(next) ++# define __sanitize_fcr31(next) do { (void) (next); } while (0) + #endif + + /* +-- +2.43.0 + diff --git a/queue-6.12/misc-apds990x-fix-missing-pm_runtime_disable.patch b/queue-6.12/misc-apds990x-fix-missing-pm_runtime_disable.patch new file mode 100644 index 00000000000..f9b1b4dd5d6 --- /dev/null +++ b/queue-6.12/misc-apds990x-fix-missing-pm_runtime_disable.patch @@ -0,0 +1,67 @@ +From c217d245654359097414f5b90b900787e7e58bc4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Mon, 23 Sep 2024 11:55:56 +0800 +Subject: misc: apds990x: Fix missing pm_runtime_disable() + +From: Jinjie Ruan <ruanjinjie@huawei.com> + +[ Upstream commit 3c5d8b819d27012264edd17e6ae7fffda382fe44 ] + +The pm_runtime_disable() is missing in probe error path, +so add it to fix it. + +Fixes: 92b1f84d46b2 ("drivers/misc: driver for APDS990X ALS and proximity sensors") +Signed-off-by: Jinjie Ruan <ruanjinjie@huawei.com> +Link: https://lore.kernel.org/r/20240923035556.3009105-1-ruanjinjie@huawei.com +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/misc/apds990x.c | 12 +++++++----- + 1 file changed, 7 insertions(+), 5 deletions(-) + +diff --git a/drivers/misc/apds990x.c b/drivers/misc/apds990x.c +index 6d4edd69db126..e7d73c972f65d 100644 +--- a/drivers/misc/apds990x.c ++++ b/drivers/misc/apds990x.c +@@ -1147,7 +1147,7 @@ static int apds990x_probe(struct i2c_client *client) + err = chip->pdata->setup_resources(); + if (err) { + err = -EINVAL; +- goto fail3; ++ goto fail4; + } + } + +@@ -1155,7 +1155,7 @@ static int apds990x_probe(struct i2c_client *client) + apds990x_attribute_group); + if (err < 0) { + dev_err(&chip->client->dev, "Sysfs registration failed\n"); +- goto fail4; ++ goto fail5; + } + + err = request_threaded_irq(client->irq, NULL, +@@ -1166,15 +1166,17 @@ static int apds990x_probe(struct i2c_client *client) + if (err) { + dev_err(&client->dev, "could not get IRQ %d\n", + client->irq); +- goto fail5; ++ goto fail6; + } + return err; +-fail5: ++fail6: + sysfs_remove_group(&chip->client->dev.kobj, + &apds990x_attribute_group[0]); +-fail4: ++fail5: + if (chip->pdata && chip->pdata->release_resources) + chip->pdata->release_resources(); ++fail4: ++ pm_runtime_disable(&client->dev); + fail3: + regulator_bulk_disable(ARRAY_SIZE(chip->regs), chip->regs); + fail2: +-- +2.43.0 + diff --git a/queue-6.12/mmc-mmc_spi-drop-buggy-snprintf.patch b/queue-6.12/mmc-mmc_spi-drop-buggy-snprintf.patch new file mode 100644 index 00000000000..90d85d9ede1 --- /dev/null +++ b/queue-6.12/mmc-mmc_spi-drop-buggy-snprintf.patch @@ -0,0 +1,66 @@ +From 030cfdebaae8dd2f0dc910ed2c613a04ce725997 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Tue, 8 Oct 2024 18:01:34 +0200 +Subject: mmc: mmc_spi: drop buggy snprintf() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Bartosz Golaszewski <bartosz.golaszewski@linaro.org> + +[ Upstream commit 328bda09cc91b3d93bc64f4a4dadc44313dd8140 ] + +GCC 13 complains about the truncated output of snprintf(): + +drivers/mmc/host/mmc_spi.c: In function ‘mmc_spi_response_get’: +drivers/mmc/host/mmc_spi.c:227:64: error: ‘snprintf’ output may be truncated before the last format character [-Werror=format-truncation=] + 227 | snprintf(tag, sizeof(tag), " ... CMD%d response SPI_%s", + | ^ +drivers/mmc/host/mmc_spi.c:227:9: note: ‘snprintf’ output between 26 and 43 bytes into a destination of size 32 + 227 | snprintf(tag, sizeof(tag), " ... CMD%d response SPI_%s", + | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + 228 | cmd->opcode, maptype(cmd)); + +Drop it and fold the string it generates into the only place where it's +emitted - the dev_dbg() call at the end of the function. + +Fixes: 15a0580ced08 ("mmc_spi host driver") +Suggested-by: Christophe JAILLET <christophe.jaillet@wanadoo.fr> +Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org> +Link: https://lore.kernel.org/r/20241008160134.69934-1-brgl@bgdev.pl +Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/mmc/host/mmc_spi.c | 9 +++------ + 1 file changed, 3 insertions(+), 6 deletions(-) + +diff --git a/drivers/mmc/host/mmc_spi.c b/drivers/mmc/host/mmc_spi.c +index 8fee7052f2ef4..47443fb5eb336 100644 +--- a/drivers/mmc/host/mmc_spi.c ++++ b/drivers/mmc/host/mmc_spi.c +@@ -222,10 +222,6 @@ static int mmc_spi_response_get(struct mmc_spi_host *host, + u8 leftover = 0; + unsigned short rotator; + int i; +- char tag[32]; +- +- snprintf(tag, sizeof(tag), " ... CMD%d response SPI_%s", +- cmd->opcode, maptype(cmd)); + + /* Except for data block reads, the whole response will already + * be stored in the scratch buffer. It's somewhere after the +@@ -378,8 +374,9 @@ static int mmc_spi_response_get(struct mmc_spi_host *host, + } + + if (value < 0) +- dev_dbg(&host->spi->dev, "%s: resp %04x %08x\n", +- tag, cmd->resp[0], cmd->resp[1]); ++ dev_dbg(&host->spi->dev, ++ " ... CMD%d response SPI_%s: resp %04x %08x\n", ++ cmd->opcode, maptype(cmd), cmd->resp[0], cmd->resp[1]); + + /* disable chipselect on errors and some success cases */ + if (value >= 0 && cs_on) +-- +2.43.0 + diff --git a/queue-6.12/mtd-hyperbus-rpc-if-add-missing-module_device_table.patch b/queue-6.12/mtd-hyperbus-rpc-if-add-missing-module_device_table.patch new file mode 100644 index 00000000000..a4cde2f84fb --- /dev/null +++ b/queue-6.12/mtd-hyperbus-rpc-if-add-missing-module_device_table.patch @@ -0,0 +1,48 @@ +From 9c9b9bbfb892d3a700ee0fa536dd0fdbd66cd474 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Wed, 31 Jul 2024 09:08:40 +0100 +Subject: mtd: hyperbus: rpc-if: Add missing MODULE_DEVICE_TABLE + +From: Biju Das <biju.das.jz@bp.renesas.com> + +[ Upstream commit 7d189579a287d5c568db623c5fc2344cce98a887 ] + +The rpc-if-hyperflash driver can be compiled as a module, but lacks +MODULE_DEVICE_TABLE() and will therefore not be loaded automatically. +Fix this. + +Fixes: 5de15b610f78 ("mtd: hyperbus: add Renesas RPC-IF driver") +Signed-off-by: Biju Das <biju.das.jz@bp.renesas.com> +Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be> +Reviewed-by: Vignesh Raghavendra <vigneshr@ti.com> +Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com> +Link: https://lore.kernel.org/linux-mtd/20240731080846.257139-1-biju.das.jz@bp.renesas.com +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/mtd/hyperbus/rpc-if.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/drivers/mtd/hyperbus/rpc-if.c b/drivers/mtd/hyperbus/rpc-if.c +index b22aa57119f23..e7a28f3316c3f 100644 +--- a/drivers/mtd/hyperbus/rpc-if.c ++++ b/drivers/mtd/hyperbus/rpc-if.c +@@ -163,9 +163,16 @@ static void rpcif_hb_remove(struct platform_device *pdev) + pm_runtime_disable(hyperbus->rpc.dev); + } + ++static const struct platform_device_id rpc_if_hyperflash_id_table[] = { ++ { .name = "rpc-if-hyperflash" }, ++ { /* sentinel */ } ++}; ++MODULE_DEVICE_TABLE(platform, rpc_if_hyperflash_id_table); ++ + static struct platform_driver rpcif_platform_driver = { + .probe = rpcif_hb_probe, + .remove_new = rpcif_hb_remove, ++ .id_table = rpc_if_hyperflash_id_table, + .driver = { + .name = "rpc-if-hyperflash", + }, +-- +2.43.0 + diff --git a/queue-6.12/mtd-rawnand-atmel-fix-possible-memory-leak.patch b/queue-6.12/mtd-rawnand-atmel-fix-possible-memory-leak.patch new file mode 100644 index 00000000000..0f445364d54 --- /dev/null +++ b/queue-6.12/mtd-rawnand-atmel-fix-possible-memory-leak.patch @@ -0,0 +1,70 @@ +From 351ed88c7c12b46e80797de040ce5bc234803993 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Tue, 1 Oct 2024 22:31:49 +0200 +Subject: mtd: rawnand: atmel: Fix possible memory leak + +From: Miquel Raynal <miquel.raynal@bootlin.com> + +[ Upstream commit 6d734f1bfc336aaea91313a5632f2f197608fadd ] + +The pmecc "user" structure is allocated in atmel_pmecc_create_user() and +was supposed to be freed with atmel_pmecc_destroy_user(), but this other +helper is never called. One solution would be to find the proper +location to call the destructor, but the trend today is to switch to +device managed allocations, which in this case fits pretty well. + +Replace kzalloc() by devm_kzalloc() and drop the destructor entirely. + +Reported-by: "Dr. David Alan Gilbert" <linux@treblig.org> +Closes: https://lore.kernel.org/all/ZvmIvRJCf6VhHvpo@gallifrey/ +Fixes: f88fc122cc34 ("mtd: nand: Cleanup/rework the atmel_nand driver") +Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com> +Link: https://lore.kernel.org/linux-mtd/20241001203149.387655-1-miquel.raynal@bootlin.com +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/mtd/nand/raw/atmel/pmecc.c | 8 +------- + drivers/mtd/nand/raw/atmel/pmecc.h | 2 -- + 2 files changed, 1 insertion(+), 9 deletions(-) + +diff --git a/drivers/mtd/nand/raw/atmel/pmecc.c b/drivers/mtd/nand/raw/atmel/pmecc.c +index 4d7dc8a9c3738..a22aab4ed4e8a 100644 +--- a/drivers/mtd/nand/raw/atmel/pmecc.c ++++ b/drivers/mtd/nand/raw/atmel/pmecc.c +@@ -362,7 +362,7 @@ atmel_pmecc_create_user(struct atmel_pmecc *pmecc, + size = ALIGN(size, sizeof(s32)); + size += (req->ecc.strength + 1) * sizeof(s32) * 3; + +- user = kzalloc(size, GFP_KERNEL); ++ user = devm_kzalloc(pmecc->dev, size, GFP_KERNEL); + if (!user) + return ERR_PTR(-ENOMEM); + +@@ -408,12 +408,6 @@ atmel_pmecc_create_user(struct atmel_pmecc *pmecc, + } + EXPORT_SYMBOL_GPL(atmel_pmecc_create_user); + +-void atmel_pmecc_destroy_user(struct atmel_pmecc_user *user) +-{ +- kfree(user); +-} +-EXPORT_SYMBOL_GPL(atmel_pmecc_destroy_user); +- + static int get_strength(struct atmel_pmecc_user *user) + { + const int *strengths = user->pmecc->caps->strengths; +diff --git a/drivers/mtd/nand/raw/atmel/pmecc.h b/drivers/mtd/nand/raw/atmel/pmecc.h +index 7851c05126cf1..cc0c5af1f4f1a 100644 +--- a/drivers/mtd/nand/raw/atmel/pmecc.h ++++ b/drivers/mtd/nand/raw/atmel/pmecc.h +@@ -55,8 +55,6 @@ struct atmel_pmecc *devm_atmel_pmecc_get(struct device *dev); + struct atmel_pmecc_user * + atmel_pmecc_create_user(struct atmel_pmecc *pmecc, + struct atmel_pmecc_user_req *req); +-void atmel_pmecc_destroy_user(struct atmel_pmecc_user *user); +- + void atmel_pmecc_reset(struct atmel_pmecc *pmecc); + int atmel_pmecc_enable(struct atmel_pmecc_user *user, int op); + void atmel_pmecc_disable(struct atmel_pmecc_user *user); +-- +2.43.0 + diff --git a/queue-6.12/mtd-spi-nor-spansion-use-nor-addr_nbytes-in-octal-dt.patch b/queue-6.12/mtd-spi-nor-spansion-use-nor-addr_nbytes-in-octal-dt.patch new file mode 100644 index 00000000000..c7f3e309510 --- /dev/null +++ b/queue-6.12/mtd-spi-nor-spansion-use-nor-addr_nbytes-in-octal-dt.patch @@ -0,0 +1,38 @@ +From fa2dc539f21d42f2f10149e45eddac3a2e916ef6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Wed, 16 Oct 2024 09:08:37 +0900 +Subject: mtd: spi-nor: spansion: Use nor->addr_nbytes in octal DTR mode in + RD_ANY_REG_OP + +From: Takahiro Kuwano <Takahiro.Kuwano@infineon.com> + +[ Upstream commit b61c35e3404557779ec427c077f7a9f057bb053d ] + +In octal DTR mode, RD_ANY_REG_OP needs to use 4-byte address regardless +of flash's internal address mode. Use nor->addr_nbytes which is set to 4 +during setup. + +Fixes: eff9604390d6 ("mtd: spi-nor: spansion: add octal DTR support in RD_ANY_REG_OP") +Signed-off-by: Takahiro Kuwano <Takahiro.Kuwano@infineon.com> +Link: https://lore.kernel.org/r/20241016000837.17951-1-Takahiro.Kuwano@infineon.com +Signed-off-by: Tudor Ambarus <tudor.ambarus@linaro.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/mtd/spi-nor/spansion.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/mtd/spi-nor/spansion.c b/drivers/mtd/spi-nor/spansion.c +index d6c92595f6bc9..5a88a6096ca8c 100644 +--- a/drivers/mtd/spi-nor/spansion.c ++++ b/drivers/mtd/spi-nor/spansion.c +@@ -106,6 +106,7 @@ static int cypress_nor_sr_ready_and_clear_reg(struct spi_nor *nor, u64 addr) + int ret; + + if (nor->reg_proto == SNOR_PROTO_8_8_8_DTR) { ++ op.addr.nbytes = nor->addr_nbytes; + op.dummy.nbytes = params->rdsr_dummy; + op.data.nbytes = 2; + } +-- +2.43.0 + diff --git a/queue-6.12/net-hsr-fix-hsr_init_sk-vs-network-transport-headers.patch b/queue-6.12/net-hsr-fix-hsr_init_sk-vs-network-transport-headers.patch new file mode 100644 index 00000000000..67351e42fd2 --- /dev/null +++ b/queue-6.12/net-hsr-fix-hsr_init_sk-vs-network-transport-headers.patch @@ -0,0 +1,61 @@ +From b336a2d12c1d3fe0fe1edfb5007385be416bced8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Fri, 22 Nov 2024 17:13:43 +0000 +Subject: net: hsr: fix hsr_init_sk() vs network/transport headers. + +From: Eric Dumazet <edumazet@google.com> + +[ Upstream commit 9cfb5e7f0ded2bfaabc270ceb5f91d13f0e805b9 ] + +Following sequence in hsr_init_sk() is invalid : + + skb_reset_mac_header(skb); + skb_reset_mac_len(skb); + skb_reset_network_header(skb); + skb_reset_transport_header(skb); + +It is invalid because skb_reset_mac_len() needs the correct +network header, which should be after the mac header. + +This patch moves the skb_reset_network_header() +and skb_reset_transport_header() before +the call to dev_hard_header(). + +As a result skb->mac_len is no longer set to a value +close to 65535. + +Fixes: 48b491a5cc74 ("net: hsr: fix mac_len checks") +Signed-off-by: Eric Dumazet <edumazet@google.com> +Cc: George McCollister <george.mccollister@gmail.com> +Link: https://patch.msgid.link/20241122171343.897551-1-edumazet@google.com +Signed-off-by: Paolo Abeni <pabeni@redhat.com> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + net/hsr/hsr_device.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/net/hsr/hsr_device.c b/net/hsr/hsr_device.c +index ebdfd5b64e17a..f630d6645636d 100644 +--- a/net/hsr/hsr_device.c ++++ b/net/hsr/hsr_device.c +@@ -268,6 +268,8 @@ static struct sk_buff *hsr_init_skb(struct hsr_port *master) + skb->dev = master->dev; + skb->priority = TC_PRIO_CONTROL; + ++ skb_reset_network_header(skb); ++ skb_reset_transport_header(skb); + if (dev_hard_header(skb, skb->dev, ETH_P_PRP, + hsr->sup_multicast_addr, + skb->dev->dev_addr, skb->len) <= 0) +@@ -275,8 +277,6 @@ static struct sk_buff *hsr_init_skb(struct hsr_port *master) + + skb_reset_mac_header(skb); + skb_reset_mac_len(skb); +- skb_reset_network_header(skb); +- skb_reset_transport_header(skb); + + return skb; + out: +-- +2.43.0 + diff --git a/queue-6.12/net-ipv6-delete-temporary-address-if-mngtmpaddr-is-r.patch b/queue-6.12/net-ipv6-delete-temporary-address-if-mngtmpaddr-is-r.patch new file mode 100644 index 00000000000..427e5564f4a --- /dev/null +++ b/queue-6.12/net-ipv6-delete-temporary-address-if-mngtmpaddr-is-r.patch @@ -0,0 +1,105 @@ +From 9e22eee187803df1c53e7959ef34a30376991f88 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Wed, 20 Nov 2024 09:51:07 +0000 +Subject: net/ipv6: delete temporary address if mngtmpaddr is removed or + unmanaged +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Hangbin Liu <liuhangbin@gmail.com> + +[ Upstream commit 00b5b7aab9e422d00d5a9d03d7e0760a76b5d57f ] + +RFC8981 section 3.4 says that existing temporary addresses must have their +lifetimes adjusted so that no temporary addresses should ever remain "valid" +or "preferred" longer than the incoming SLAAC Prefix Information. This would +strongly imply in Linux's case that if the "mngtmpaddr" address is deleted or +un-flagged as such, its corresponding temporary addresses must be cleared out +right away. + +But now the temporary address is renewed even after ‘mngtmpaddr’ is removed +or becomes unmanaged as manage_tempaddrs() set temporary addresses +prefered/valid time to 0, and later in addrconf_verify_rtnl() all checkings +failed to remove the addresses. Fix this by deleting the temporary address +directly for these situations. + +Fixes: 778964f2fdf0 ("ipv6/addrconf: fix timing bug in tempaddr regen") +Signed-off-by: Hangbin Liu <liuhangbin@gmail.com> +Reviewed-by: David Ahern <dsahern@kernel.org> +Signed-off-by: Paolo Abeni <pabeni@redhat.com> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + net/ipv6/addrconf.c | 41 +++++++++++++++++++++++++++++------------ + 1 file changed, 29 insertions(+), 12 deletions(-) + +diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c +index 94dceac528842..01115e1a34cb6 100644 +--- a/net/ipv6/addrconf.c ++++ b/net/ipv6/addrconf.c +@@ -2570,6 +2570,24 @@ static struct inet6_dev *addrconf_add_dev(struct net_device *dev) + return idev; + } + ++static void delete_tempaddrs(struct inet6_dev *idev, ++ struct inet6_ifaddr *ifp) ++{ ++ struct inet6_ifaddr *ift, *tmp; ++ ++ write_lock_bh(&idev->lock); ++ list_for_each_entry_safe(ift, tmp, &idev->tempaddr_list, tmp_list) { ++ if (ift->ifpub != ifp) ++ continue; ++ ++ in6_ifa_hold(ift); ++ write_unlock_bh(&idev->lock); ++ ipv6_del_addr(ift); ++ write_lock_bh(&idev->lock); ++ } ++ write_unlock_bh(&idev->lock); ++} ++ + static void manage_tempaddrs(struct inet6_dev *idev, + struct inet6_ifaddr *ifp, + __u32 valid_lft, __u32 prefered_lft, +@@ -3124,11 +3142,12 @@ static int inet6_addr_del(struct net *net, int ifindex, u32 ifa_flags, + in6_ifa_hold(ifp); + read_unlock_bh(&idev->lock); + +- if (!(ifp->flags & IFA_F_TEMPORARY) && +- (ifa_flags & IFA_F_MANAGETEMPADDR)) +- manage_tempaddrs(idev, ifp, 0, 0, false, +- jiffies); + ipv6_del_addr(ifp); ++ ++ if (!(ifp->flags & IFA_F_TEMPORARY) && ++ (ifp->flags & IFA_F_MANAGETEMPADDR)) ++ delete_tempaddrs(idev, ifp); ++ + addrconf_verify_rtnl(net); + if (ipv6_addr_is_multicast(pfx)) { + ipv6_mc_config(net->ipv6.mc_autojoin_sk, +@@ -4952,14 +4971,12 @@ static int inet6_addr_modify(struct net *net, struct inet6_ifaddr *ifp, + } + + if (was_managetempaddr || ifp->flags & IFA_F_MANAGETEMPADDR) { +- if (was_managetempaddr && +- !(ifp->flags & IFA_F_MANAGETEMPADDR)) { +- cfg->valid_lft = 0; +- cfg->preferred_lft = 0; +- } +- manage_tempaddrs(ifp->idev, ifp, cfg->valid_lft, +- cfg->preferred_lft, !was_managetempaddr, +- jiffies); ++ if (was_managetempaddr && !(ifp->flags & IFA_F_MANAGETEMPADDR)) ++ delete_tempaddrs(ifp->idev, ifp); ++ else ++ manage_tempaddrs(ifp->idev, ifp, cfg->valid_lft, ++ cfg->preferred_lft, !was_managetempaddr, ++ jiffies); + } + + addrconf_verify_rtnl(net); +-- +2.43.0 + diff --git a/queue-6.12/net-l2tp-fix-warning-in-l2tp_exit_net-found-by-syzbo.patch b/queue-6.12/net-l2tp-fix-warning-in-l2tp_exit_net-found-by-syzbo.patch new file mode 100644 index 00000000000..61545b15551 --- /dev/null +++ b/queue-6.12/net-l2tp-fix-warning-in-l2tp_exit_net-found-by-syzbo.patch @@ -0,0 +1,78 @@ +From 12fa7625dd6f9c5cc5c8f0306e7e4bff33c3dcf6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Mon, 18 Nov 2024 14:04:11 +0000 +Subject: net/l2tp: fix warning in l2tp_exit_net found by syzbot + +From: James Chapman <jchapman@katalix.com> + +[ Upstream commit 5d066766c5f1252f98ff859265bcd1a5b52ac46c ] + +In l2tp's net exit handler, we check that an IDR is empty before +destroying it: + + WARN_ON_ONCE(!idr_is_empty(&pn->l2tp_tunnel_idr)); + idr_destroy(&pn->l2tp_tunnel_idr); + +By forcing memory allocation failures in idr_alloc_32, syzbot is able +to provoke a condition where idr_is_empty returns false despite there +being no items in the IDR. This turns out to be because the radix tree +of the IDR contains only internal radix-tree nodes and it is this that +causes idr_is_empty to return false. The internal nodes are cleaned by +idr_destroy. + +Use idr_for_each to check that the IDR is empty instead of +idr_is_empty to avoid the problem. + +Reported-by: syzbot+332fe1e67018625f63c9@syzkaller.appspotmail.com +Closes: https://syzkaller.appspot.com/bug?extid=332fe1e67018625f63c9 +Fixes: 73d33bd063c4 ("l2tp: avoid using drain_workqueue in l2tp_pre_exit_net") +Signed-off-by: James Chapman <jchapman@katalix.com> +Link: https://patch.msgid.link/20241118140411.1582555-1-jchapman@katalix.com +Signed-off-by: Paolo Abeni <pabeni@redhat.com> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + net/l2tp/l2tp_core.c | 22 +++++++++++++++++++--- + 1 file changed, 19 insertions(+), 3 deletions(-) + +diff --git a/net/l2tp/l2tp_core.c b/net/l2tp/l2tp_core.c +index 3eec23ac5ab10..369a2f2e459cd 100644 +--- a/net/l2tp/l2tp_core.c ++++ b/net/l2tp/l2tp_core.c +@@ -1870,15 +1870,31 @@ static __net_exit void l2tp_pre_exit_net(struct net *net) + } + } + ++static int l2tp_idr_item_unexpected(int id, void *p, void *data) ++{ ++ const char *idr_name = data; ++ ++ pr_err("l2tp: %s IDR not empty at net %d exit\n", idr_name, id); ++ WARN_ON_ONCE(1); ++ return 1; ++} ++ + static __net_exit void l2tp_exit_net(struct net *net) + { + struct l2tp_net *pn = l2tp_pernet(net); + +- WARN_ON_ONCE(!idr_is_empty(&pn->l2tp_v2_session_idr)); ++ /* Our per-net IDRs should be empty. Check that is so, to ++ * help catch cleanup races or refcnt leaks. ++ */ ++ idr_for_each(&pn->l2tp_v2_session_idr, l2tp_idr_item_unexpected, ++ "v2_session"); ++ idr_for_each(&pn->l2tp_v3_session_idr, l2tp_idr_item_unexpected, ++ "v3_session"); ++ idr_for_each(&pn->l2tp_tunnel_idr, l2tp_idr_item_unexpected, ++ "tunnel"); ++ + idr_destroy(&pn->l2tp_v2_session_idr); +- WARN_ON_ONCE(!idr_is_empty(&pn->l2tp_v3_session_idr)); + idr_destroy(&pn->l2tp_v3_session_idr); +- WARN_ON_ONCE(!idr_is_empty(&pn->l2tp_tunnel_idr)); + idr_destroy(&pn->l2tp_tunnel_idr); + } + +-- +2.43.0 + diff --git a/queue-6.12/net-mdio-ipq4019-add-missing-error-check.patch b/queue-6.12/net-mdio-ipq4019-add-missing-error-check.patch new file mode 100644 index 00000000000..0b26b3ba9aa --- /dev/null +++ b/queue-6.12/net-mdio-ipq4019-add-missing-error-check.patch @@ -0,0 +1,43 @@ +From a845b9c1392a132cdaafbab6d81e8b348d9ba712 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Thu, 21 Nov 2024 11:31:52 -0800 +Subject: net: mdio-ipq4019: add missing error check + +From: Rosen Penev <rosenp@gmail.com> + +[ Upstream commit 9cc8d0ecdd2aad42e377e971e3bb114339df609e ] + +If an optional resource is found but fails to remap, return on failure. +Avoids any potential problems when using the iomapped resource as the +assumption is that it's available. + +Fixes: 23a890d493e3 ("net: mdio: Add the reset function for IPQ MDIO driver") +Signed-off-by: Rosen Penev <rosenp@gmail.com> +Reviewed-by: Andrew Lunn <andrew@lunn.ch> +Link: https://patch.msgid.link/20241121193152.8966-1-rosenp@gmail.com +Signed-off-by: Paolo Abeni <pabeni@redhat.com> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/net/mdio/mdio-ipq4019.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/mdio/mdio-ipq4019.c b/drivers/net/mdio/mdio-ipq4019.c +index 9d8f43b28aac5..ea1f64596a85c 100644 +--- a/drivers/net/mdio/mdio-ipq4019.c ++++ b/drivers/net/mdio/mdio-ipq4019.c +@@ -352,8 +352,11 @@ static int ipq4019_mdio_probe(struct platform_device *pdev) + /* The platform resource is provided on the chipset IPQ5018 */ + /* This resource is optional */ + res = platform_get_resource(pdev, IORESOURCE_MEM, 1); +- if (res) ++ if (res) { + priv->eth_ldo_rdy = devm_ioremap_resource(&pdev->dev, res); ++ if (IS_ERR(priv->eth_ldo_rdy)) ++ return PTR_ERR(priv->eth_ldo_rdy); ++ } + + bus->name = "ipq4019_mdio"; + bus->read = ipq4019_mdio_read_c22; +-- +2.43.0 + diff --git a/queue-6.12/net-microchip-vcap-add-typegroup-table-terminators-i.patch b/queue-6.12/net-microchip-vcap-add-typegroup-table-terminators-i.patch new file mode 100644 index 00000000000..4709b291209 --- /dev/null +++ b/queue-6.12/net-microchip-vcap-add-typegroup-table-terminators-i.patch @@ -0,0 +1,134 @@ +From 36ada41419eee69fc02f5ddb9926f13ea2908771 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Tue, 19 Nov 2024 13:32:02 -0800 +Subject: net: microchip: vcap: Add typegroup table terminators in kunit tests + +From: Guenter Roeck <linux@roeck-us.net> + +[ Upstream commit f164b296638d1eb1fb1c537e93ab5c8b49966546 ] + +VCAP API unit tests fail randomly with errors such as + + # vcap_api_iterator_init_test: EXPECTATION FAILED at drivers/net/ethernet/microchip/vcap/vcap_api_kunit.c:387 + Expected 134 + 7 == iter.offset, but + 134 + 7 == 141 (0x8d) + iter.offset == 17214 (0x433e) + # vcap_api_iterator_init_test: EXPECTATION FAILED at drivers/net/ethernet/microchip/vcap/vcap_api_kunit.c:388 + Expected 5 == iter.reg_idx, but + iter.reg_idx == 702 (0x2be) + # vcap_api_iterator_init_test: EXPECTATION FAILED at drivers/net/ethernet/microchip/vcap/vcap_api_kunit.c:389 + Expected 11 == iter.reg_bitpos, but + iter.reg_bitpos == 15 (0xf) + # vcap_api_iterator_init_test: pass:0 fail:1 skip:0 total:1 + +Comments in the code state that "A typegroup table ends with an all-zero +terminator". Add the missing terminators. + +Some of the typegroups did have a terminator of ".offset = 0, .width = 0, +.value = 0,". Replace those terminators with "{ }" (no trailing ',') for +consistency and to excplicitly state "this is a terminator". + +Fixes: 67d637516fa9 ("net: microchip: sparx5: Adding KUNIT test for the VCAP API") +Cc: Steen Hegelund <steen.hegelund@microchip.com> +Signed-off-by: Guenter Roeck <linux@roeck-us.net> +Reviewed-by: Daniel Machon <daniel.machon@microchip.com> +Reviewed-by: Jacob Keller <jacob.e.keller@intel.com> +Link: https://patch.msgid.link/20241119213202.2884639-1-linux@roeck-us.net +Signed-off-by: Jakub Kicinski <kuba@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + .../ethernet/microchip/vcap/vcap_api_kunit.c | 17 ++++++++++------- + 1 file changed, 10 insertions(+), 7 deletions(-) + +diff --git a/drivers/net/ethernet/microchip/vcap/vcap_api_kunit.c b/drivers/net/ethernet/microchip/vcap/vcap_api_kunit.c +index 7251121ab196e..16eb3de60eb6d 100644 +--- a/drivers/net/ethernet/microchip/vcap/vcap_api_kunit.c ++++ b/drivers/net/ethernet/microchip/vcap/vcap_api_kunit.c +@@ -366,12 +366,13 @@ static void vcap_api_iterator_init_test(struct kunit *test) + struct vcap_typegroup typegroups[] = { + { .offset = 0, .width = 2, .value = 2, }, + { .offset = 156, .width = 1, .value = 0, }, +- { .offset = 0, .width = 0, .value = 0, }, ++ { } + }; + struct vcap_typegroup typegroups2[] = { + { .offset = 0, .width = 3, .value = 4, }, + { .offset = 49, .width = 2, .value = 0, }, + { .offset = 98, .width = 2, .value = 0, }, ++ { } + }; + + vcap_iter_init(&iter, 52, typegroups, 86); +@@ -399,6 +400,7 @@ static void vcap_api_iterator_next_test(struct kunit *test) + { .offset = 147, .width = 3, .value = 0, }, + { .offset = 196, .width = 2, .value = 0, }, + { .offset = 245, .width = 1, .value = 0, }, ++ { } + }; + int idx; + +@@ -433,7 +435,7 @@ static void vcap_api_encode_typegroups_test(struct kunit *test) + { .offset = 147, .width = 3, .value = 5, }, + { .offset = 196, .width = 2, .value = 2, }, + { .offset = 245, .width = 5, .value = 27, }, +- { .offset = 0, .width = 0, .value = 0, }, ++ { } + }; + + vcap_encode_typegroups(stream, 49, typegroups, false); +@@ -463,6 +465,7 @@ static void vcap_api_encode_bit_test(struct kunit *test) + { .offset = 147, .width = 3, .value = 5, }, + { .offset = 196, .width = 2, .value = 2, }, + { .offset = 245, .width = 1, .value = 0, }, ++ { } + }; + + vcap_iter_init(&iter, 49, typegroups, 44); +@@ -489,7 +492,7 @@ static void vcap_api_encode_field_test(struct kunit *test) + { .offset = 147, .width = 3, .value = 5, }, + { .offset = 196, .width = 2, .value = 2, }, + { .offset = 245, .width = 5, .value = 27, }, +- { .offset = 0, .width = 0, .value = 0, }, ++ { } + }; + struct vcap_field rf = { + .type = VCAP_FIELD_U32, +@@ -538,7 +541,7 @@ static void vcap_api_encode_short_field_test(struct kunit *test) + { .offset = 0, .width = 3, .value = 7, }, + { .offset = 21, .width = 2, .value = 3, }, + { .offset = 42, .width = 1, .value = 1, }, +- { .offset = 0, .width = 0, .value = 0, }, ++ { } + }; + struct vcap_field rf = { + .type = VCAP_FIELD_U32, +@@ -608,7 +611,7 @@ static void vcap_api_encode_keyfield_test(struct kunit *test) + struct vcap_typegroup tgt[] = { + { .offset = 0, .width = 2, .value = 2, }, + { .offset = 156, .width = 1, .value = 1, }, +- { .offset = 0, .width = 0, .value = 0, }, ++ { } + }; + + vcap_test_api_init(&admin); +@@ -671,7 +674,7 @@ static void vcap_api_encode_max_keyfield_test(struct kunit *test) + struct vcap_typegroup tgt[] = { + { .offset = 0, .width = 2, .value = 2, }, + { .offset = 156, .width = 1, .value = 1, }, +- { .offset = 0, .width = 0, .value = 0, }, ++ { } + }; + u32 keyres[] = { + 0x928e8a84, +@@ -732,7 +735,7 @@ static void vcap_api_encode_actionfield_test(struct kunit *test) + { .offset = 0, .width = 2, .value = 2, }, + { .offset = 21, .width = 1, .value = 1, }, + { .offset = 42, .width = 1, .value = 0, }, +- { .offset = 0, .width = 0, .value = 0, }, ++ { } + }; + + vcap_encode_actionfield(&rule, &caf, &rf, tgt); +-- +2.43.0 + diff --git a/queue-6.12/net-rfkill-gpio-add-check-for-clk_enable.patch b/queue-6.12/net-rfkill-gpio-add-check-for-clk_enable.patch new file mode 100644 index 00000000000..72bdfdb0814 --- /dev/null +++ b/queue-6.12/net-rfkill-gpio-add-check-for-clk_enable.patch @@ -0,0 +1,44 @@ +From ef9fcf8396e6c25d71f814270f0f788070a4af5c Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Fri, 8 Nov 2024 14:53:41 -0500 +Subject: net: rfkill: gpio: Add check for clk_enable() + +From: Mingwei Zheng <zmw12306@gmail.com> + +[ Upstream commit 8251e7621b25ccdb689f1dd9553b8789e3745ea1 ] + +Add check for the return value of clk_enable() to catch the potential +error. + +Fixes: 7176ba23f8b5 ("net: rfkill: add generic gpio rfkill driver") +Signed-off-by: Mingwei Zheng <zmw12306@gmail.com> +Signed-off-by: Jiasheng Jiang <jiashengjiangcool@gmail.com> +Link: https://patch.msgid.link/20241108195341.1853080-1-zmw12306@gmail.com +Signed-off-by: Johannes Berg <johannes.berg@intel.com> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + net/rfkill/rfkill-gpio.c | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +diff --git a/net/rfkill/rfkill-gpio.c b/net/rfkill/rfkill-gpio.c +index c268c2b011f42..a8e21060112ff 100644 +--- a/net/rfkill/rfkill-gpio.c ++++ b/net/rfkill/rfkill-gpio.c +@@ -32,8 +32,12 @@ static int rfkill_gpio_set_power(void *data, bool blocked) + { + struct rfkill_gpio_data *rfkill = data; + +- if (!blocked && !IS_ERR(rfkill->clk) && !rfkill->clk_enabled) +- clk_enable(rfkill->clk); ++ if (!blocked && !IS_ERR(rfkill->clk) && !rfkill->clk_enabled) { ++ int ret = clk_enable(rfkill->clk); ++ ++ if (ret) ++ return ret; ++ } + + gpiod_set_value_cansleep(rfkill->shutdown_gpio, !blocked); + gpiod_set_value_cansleep(rfkill->reset_gpio, !blocked); +-- +2.43.0 + diff --git a/queue-6.12/net-stmmac-dwmac-socfpga-set-rx-watchdog-interrupt-a.patch b/queue-6.12/net-stmmac-dwmac-socfpga-set-rx-watchdog-interrupt-a.patch new file mode 100644 index 00000000000..600bd3cd7f1 --- /dev/null +++ b/queue-6.12/net-stmmac-dwmac-socfpga-set-rx-watchdog-interrupt-a.patch @@ -0,0 +1,50 @@ +From a464ea40d48dcd722ff4235b2a4bd3fb7bfd222f Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Fri, 22 Nov 2024 15:12:55 +0100 +Subject: net: stmmac: dwmac-socfpga: Set RX watchdog interrupt as broken + +From: Maxime Chevallier <maxime.chevallier@bootlin.com> + +[ Upstream commit 407618d66dba55e7db1278872e8be106808bbe91 ] + +On DWMAC3 and later, there's a RX Watchdog interrupt that's used for +interrupt coalescing. It's known to be buggy on some platforms, and +dwmac-socfpga appears to be one of them. Changing the interrupt +coalescing from ethtool doesn't appear to have any effect here. + +Without disabling RIWT (Received Interrupt Watchdog Timer, I +believe...), we observe latencies while receiving traffic that amount to +around ~0.4ms. This was discovered with NTP but can be easily reproduced +with a simple ping. Without this patch : + +64 bytes from 192.168.5.2: icmp_seq=1 ttl=64 time=0.657 ms + +With this patch : + +64 bytes from 192.168.5.2: icmp_seq=1 ttl=64 time=0.254 ms + +Fixes: 801d233b7302 ("net: stmmac: Add SOCFPGA glue driver") +Signed-off-by: Maxime Chevallier <maxime.chevallier@bootlin.com> +Link: https://patch.msgid.link/20241122141256.764578-1-maxime.chevallier@bootlin.com +Signed-off-by: Paolo Abeni <pabeni@redhat.com> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c +index fdb4c773ec98a..e897b49aa9e05 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c ++++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c +@@ -486,6 +486,8 @@ static int socfpga_dwmac_probe(struct platform_device *pdev) + plat_dat->pcs_exit = socfpga_dwmac_pcs_exit; + plat_dat->select_pcs = socfpga_dwmac_select_pcs; + ++ plat_dat->riwt_off = 1; ++ + ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res); + if (ret) + return ret; +-- +2.43.0 + diff --git a/queue-6.12/net-txgbe-fix-null-pointer-to-pcs.patch b/queue-6.12/net-txgbe-fix-null-pointer-to-pcs.patch new file mode 100644 index 00000000000..b02d0d2c76f --- /dev/null +++ b/queue-6.12/net-txgbe-fix-null-pointer-to-pcs.patch @@ -0,0 +1,37 @@ +From 83a17e59ecbacc3683a19cc43edda3931d2bf1e2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Fri, 15 Nov 2024 15:35:08 +0800 +Subject: net: txgbe: fix null pointer to pcs + +From: Jiawen Wu <jiawenwu@trustnetic.com> + +[ Upstream commit 2160428bcb20f2f70a72ee84aba91a1264dc4ff3 ] + +For 1000BASE-X or SGMII interface mode, the PCS also need to be selected. +Only return null pointer when there is a copper NIC with external PHY. + +Fixes: 02b2a6f91b90 ("net: txgbe: support copper NIC with external PHY") +Signed-off-by: Jiawen Wu <jiawenwu@trustnetic.com> +Link: https://patch.msgid.link/20241115073508.1130046-1-jiawenwu@trustnetic.com +Signed-off-by: Jakub Kicinski <kuba@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/net/ethernet/wangxun/txgbe/txgbe_phy.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.c b/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.c +index 2bfe41339c1cd..f26946198a2fb 100644 +--- a/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.c ++++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.c +@@ -162,7 +162,7 @@ static struct phylink_pcs *txgbe_phylink_mac_select(struct phylink_config *confi + struct wx *wx = phylink_to_wx(config); + struct txgbe *txgbe = wx->priv; + +- if (interface == PHY_INTERFACE_MODE_10GBASER) ++ if (wx->media_type != sp_media_copper) + return &txgbe->xpcs->pcs; + + return NULL; +-- +2.43.0 + diff --git a/queue-6.12/net-txgbe-remove-gpio-interrupt-controller.patch b/queue-6.12/net-txgbe-remove-gpio-interrupt-controller.patch new file mode 100644 index 00000000000..3d94f88225b --- /dev/null +++ b/queue-6.12/net-txgbe-remove-gpio-interrupt-controller.patch @@ -0,0 +1,343 @@ +From 66f5d601f2ed9913aa0279a94162fb930b202254 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Fri, 15 Nov 2024 15:15:27 +0800 +Subject: net: txgbe: remove GPIO interrupt controller + +From: Jiawen Wu <jiawenwu@trustnetic.com> + +[ Upstream commit e867ed3ac8aa50945170723a450b5c068a56339a ] + +Since the GPIO interrupt controller is always not working properly, we need +to constantly add workaround to cope with hardware deficiencies. So just +remove GPIO interrupt controller, and let the SFP driver poll the GPIO +status. + +Fixes: b4a2496c17ed ("net: txgbe: fix GPIO interrupt blocking") +Signed-off-by: Jiawen Wu <jiawenwu@trustnetic.com> +Link: https://patch.msgid.link/20241115071527.1129458-1-jiawenwu@trustnetic.com +Signed-off-by: Jakub Kicinski <kuba@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + .../net/ethernet/wangxun/txgbe/txgbe_irq.c | 24 +-- + .../net/ethernet/wangxun/txgbe/txgbe_main.c | 1 - + .../net/ethernet/wangxun/txgbe/txgbe_phy.c | 166 ------------------ + .../net/ethernet/wangxun/txgbe/txgbe_phy.h | 2 - + .../net/ethernet/wangxun/txgbe/txgbe_type.h | 7 +- + 5 files changed, 4 insertions(+), 196 deletions(-) + +diff --git a/drivers/net/ethernet/wangxun/txgbe/txgbe_irq.c b/drivers/net/ethernet/wangxun/txgbe/txgbe_irq.c +index a4cf682dca650..0ee73a265545c 100644 +--- a/drivers/net/ethernet/wangxun/txgbe/txgbe_irq.c ++++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_irq.c +@@ -72,14 +72,6 @@ int txgbe_request_queue_irqs(struct wx *wx) + return err; + } + +-static int txgbe_request_gpio_irq(struct txgbe *txgbe) +-{ +- txgbe->gpio_irq = irq_find_mapping(txgbe->misc.domain, TXGBE_IRQ_GPIO); +- return request_threaded_irq(txgbe->gpio_irq, NULL, +- txgbe_gpio_irq_handler, +- IRQF_ONESHOT, "txgbe-gpio-irq", txgbe); +-} +- + static int txgbe_request_link_irq(struct txgbe *txgbe) + { + txgbe->link_irq = irq_find_mapping(txgbe->misc.domain, TXGBE_IRQ_LINK); +@@ -149,11 +141,6 @@ static irqreturn_t txgbe_misc_irq_thread_fn(int irq, void *data) + u32 eicr; + + eicr = wx_misc_isb(wx, WX_ISB_MISC); +- if (eicr & TXGBE_PX_MISC_GPIO) { +- sub_irq = irq_find_mapping(txgbe->misc.domain, TXGBE_IRQ_GPIO); +- handle_nested_irq(sub_irq); +- nhandled++; +- } + if (eicr & (TXGBE_PX_MISC_ETH_LK | TXGBE_PX_MISC_ETH_LKDN | + TXGBE_PX_MISC_ETH_AN)) { + sub_irq = irq_find_mapping(txgbe->misc.domain, TXGBE_IRQ_LINK); +@@ -179,7 +166,6 @@ static void txgbe_del_irq_domain(struct txgbe *txgbe) + + void txgbe_free_misc_irq(struct txgbe *txgbe) + { +- free_irq(txgbe->gpio_irq, txgbe); + free_irq(txgbe->link_irq, txgbe); + free_irq(txgbe->misc.irq, txgbe); + txgbe_del_irq_domain(txgbe); +@@ -191,7 +177,7 @@ int txgbe_setup_misc_irq(struct txgbe *txgbe) + struct wx *wx = txgbe->wx; + int hwirq, err; + +- txgbe->misc.nirqs = 2; ++ txgbe->misc.nirqs = 1; + txgbe->misc.domain = irq_domain_add_simple(NULL, txgbe->misc.nirqs, 0, + &txgbe_misc_irq_domain_ops, txgbe); + if (!txgbe->misc.domain) +@@ -216,20 +202,14 @@ int txgbe_setup_misc_irq(struct txgbe *txgbe) + if (err) + goto del_misc_irq; + +- err = txgbe_request_gpio_irq(txgbe); +- if (err) +- goto free_msic_irq; +- + err = txgbe_request_link_irq(txgbe); + if (err) +- goto free_gpio_irq; ++ goto free_msic_irq; + + wx->misc_irq_domain = true; + + return 0; + +-free_gpio_irq: +- free_irq(txgbe->gpio_irq, txgbe); + free_msic_irq: + free_irq(txgbe->misc.irq, txgbe); + del_misc_irq: +diff --git a/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c b/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c +index 93180225a6f14..f774502680364 100644 +--- a/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c ++++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c +@@ -82,7 +82,6 @@ static void txgbe_up_complete(struct wx *wx) + { + struct net_device *netdev = wx->netdev; + +- txgbe_reinit_gpio_intr(wx); + wx_control_hw(wx, true); + wx_configure_vectors(wx); + +diff --git a/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.c b/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.c +index 67b61afdde96c..2bfe41339c1cd 100644 +--- a/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.c ++++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.c +@@ -358,169 +358,8 @@ static int txgbe_gpio_direction_out(struct gpio_chip *chip, unsigned int offset, + return 0; + } + +-static void txgbe_gpio_irq_ack(struct irq_data *d) +-{ +- struct gpio_chip *gc = irq_data_get_irq_chip_data(d); +- irq_hw_number_t hwirq = irqd_to_hwirq(d); +- struct wx *wx = gpiochip_get_data(gc); +- unsigned long flags; +- +- raw_spin_lock_irqsave(&wx->gpio_lock, flags); +- wr32(wx, WX_GPIO_EOI, BIT(hwirq)); +- raw_spin_unlock_irqrestore(&wx->gpio_lock, flags); +-} +- +-static void txgbe_gpio_irq_mask(struct irq_data *d) +-{ +- struct gpio_chip *gc = irq_data_get_irq_chip_data(d); +- irq_hw_number_t hwirq = irqd_to_hwirq(d); +- struct wx *wx = gpiochip_get_data(gc); +- unsigned long flags; +- +- gpiochip_disable_irq(gc, hwirq); +- +- raw_spin_lock_irqsave(&wx->gpio_lock, flags); +- wr32m(wx, WX_GPIO_INTMASK, BIT(hwirq), BIT(hwirq)); +- raw_spin_unlock_irqrestore(&wx->gpio_lock, flags); +-} +- +-static void txgbe_gpio_irq_unmask(struct irq_data *d) +-{ +- struct gpio_chip *gc = irq_data_get_irq_chip_data(d); +- irq_hw_number_t hwirq = irqd_to_hwirq(d); +- struct wx *wx = gpiochip_get_data(gc); +- unsigned long flags; +- +- gpiochip_enable_irq(gc, hwirq); +- +- raw_spin_lock_irqsave(&wx->gpio_lock, flags); +- wr32m(wx, WX_GPIO_INTMASK, BIT(hwirq), 0); +- raw_spin_unlock_irqrestore(&wx->gpio_lock, flags); +-} +- +-static void txgbe_toggle_trigger(struct gpio_chip *gc, unsigned int offset) +-{ +- struct wx *wx = gpiochip_get_data(gc); +- u32 pol, val; +- +- pol = rd32(wx, WX_GPIO_POLARITY); +- val = rd32(wx, WX_GPIO_EXT); +- +- if (val & BIT(offset)) +- pol &= ~BIT(offset); +- else +- pol |= BIT(offset); +- +- wr32(wx, WX_GPIO_POLARITY, pol); +-} +- +-static int txgbe_gpio_set_type(struct irq_data *d, unsigned int type) +-{ +- struct gpio_chip *gc = irq_data_get_irq_chip_data(d); +- irq_hw_number_t hwirq = irqd_to_hwirq(d); +- struct wx *wx = gpiochip_get_data(gc); +- u32 level, polarity, mask; +- unsigned long flags; +- +- mask = BIT(hwirq); +- +- if (type & IRQ_TYPE_LEVEL_MASK) { +- level = 0; +- irq_set_handler_locked(d, handle_level_irq); +- } else { +- level = mask; +- irq_set_handler_locked(d, handle_edge_irq); +- } +- +- if (type == IRQ_TYPE_EDGE_RISING || type == IRQ_TYPE_LEVEL_HIGH) +- polarity = mask; +- else +- polarity = 0; +- +- raw_spin_lock_irqsave(&wx->gpio_lock, flags); +- +- wr32m(wx, WX_GPIO_INTEN, mask, mask); +- wr32m(wx, WX_GPIO_INTTYPE_LEVEL, mask, level); +- if (type == IRQ_TYPE_EDGE_BOTH) +- txgbe_toggle_trigger(gc, hwirq); +- else +- wr32m(wx, WX_GPIO_POLARITY, mask, polarity); +- +- raw_spin_unlock_irqrestore(&wx->gpio_lock, flags); +- +- return 0; +-} +- +-static const struct irq_chip txgbe_gpio_irq_chip = { +- .name = "txgbe-gpio-irq", +- .irq_ack = txgbe_gpio_irq_ack, +- .irq_mask = txgbe_gpio_irq_mask, +- .irq_unmask = txgbe_gpio_irq_unmask, +- .irq_set_type = txgbe_gpio_set_type, +- .flags = IRQCHIP_IMMUTABLE, +- GPIOCHIP_IRQ_RESOURCE_HELPERS, +-}; +- +-irqreturn_t txgbe_gpio_irq_handler(int irq, void *data) +-{ +- struct txgbe *txgbe = data; +- struct wx *wx = txgbe->wx; +- irq_hw_number_t hwirq; +- unsigned long gpioirq; +- struct gpio_chip *gc; +- unsigned long flags; +- +- gpioirq = rd32(wx, WX_GPIO_INTSTATUS); +- +- gc = txgbe->gpio; +- for_each_set_bit(hwirq, &gpioirq, gc->ngpio) { +- int gpio = irq_find_mapping(gc->irq.domain, hwirq); +- struct irq_data *d = irq_get_irq_data(gpio); +- u32 irq_type = irq_get_trigger_type(gpio); +- +- txgbe_gpio_irq_ack(d); +- handle_nested_irq(gpio); +- +- if ((irq_type & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_BOTH) { +- raw_spin_lock_irqsave(&wx->gpio_lock, flags); +- txgbe_toggle_trigger(gc, hwirq); +- raw_spin_unlock_irqrestore(&wx->gpio_lock, flags); +- } +- } +- +- return IRQ_HANDLED; +-} +- +-void txgbe_reinit_gpio_intr(struct wx *wx) +-{ +- struct txgbe *txgbe = wx->priv; +- irq_hw_number_t hwirq; +- unsigned long gpioirq; +- struct gpio_chip *gc; +- unsigned long flags; +- +- /* for gpio interrupt pending before irq enable */ +- gpioirq = rd32(wx, WX_GPIO_INTSTATUS); +- +- gc = txgbe->gpio; +- for_each_set_bit(hwirq, &gpioirq, gc->ngpio) { +- int gpio = irq_find_mapping(gc->irq.domain, hwirq); +- struct irq_data *d = irq_get_irq_data(gpio); +- u32 irq_type = irq_get_trigger_type(gpio); +- +- txgbe_gpio_irq_ack(d); +- +- if ((irq_type & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_BOTH) { +- raw_spin_lock_irqsave(&wx->gpio_lock, flags); +- txgbe_toggle_trigger(gc, hwirq); +- raw_spin_unlock_irqrestore(&wx->gpio_lock, flags); +- } +- } +-} +- + static int txgbe_gpio_init(struct txgbe *txgbe) + { +- struct gpio_irq_chip *girq; + struct gpio_chip *gc; + struct device *dev; + struct wx *wx; +@@ -550,11 +389,6 @@ static int txgbe_gpio_init(struct txgbe *txgbe) + gc->direction_input = txgbe_gpio_direction_in; + gc->direction_output = txgbe_gpio_direction_out; + +- girq = &gc->irq; +- gpio_irq_chip_set_chip(girq, &txgbe_gpio_irq_chip); +- girq->default_type = IRQ_TYPE_NONE; +- girq->handler = handle_bad_irq; +- + ret = devm_gpiochip_add_data(dev, gc, wx); + if (ret) + return ret; +diff --git a/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.h b/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.h +index 8a026d804fe24..3938985355ed6 100644 +--- a/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.h ++++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.h +@@ -4,8 +4,6 @@ + #ifndef _TXGBE_PHY_H_ + #define _TXGBE_PHY_H_ + +-irqreturn_t txgbe_gpio_irq_handler(int irq, void *data); +-void txgbe_reinit_gpio_intr(struct wx *wx); + irqreturn_t txgbe_link_irq_handler(int irq, void *data); + int txgbe_init_phy(struct txgbe *txgbe); + void txgbe_remove_phy(struct txgbe *txgbe); +diff --git a/drivers/net/ethernet/wangxun/txgbe/txgbe_type.h b/drivers/net/ethernet/wangxun/txgbe/txgbe_type.h +index 959102c4c3797..8ea413a7abe9d 100644 +--- a/drivers/net/ethernet/wangxun/txgbe/txgbe_type.h ++++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_type.h +@@ -75,8 +75,7 @@ + #define TXGBE_PX_MISC_IEN_MASK \ + (TXGBE_PX_MISC_ETH_LKDN | TXGBE_PX_MISC_DEV_RST | \ + TXGBE_PX_MISC_ETH_EVENT | TXGBE_PX_MISC_ETH_LK | \ +- TXGBE_PX_MISC_ETH_AN | TXGBE_PX_MISC_INT_ERR | \ +- TXGBE_PX_MISC_GPIO) ++ TXGBE_PX_MISC_ETH_AN | TXGBE_PX_MISC_INT_ERR) + + /* Port cfg registers */ + #define TXGBE_CFG_PORT_ST 0x14404 +@@ -313,8 +312,7 @@ struct txgbe_nodes { + }; + + enum txgbe_misc_irqs { +- TXGBE_IRQ_GPIO = 0, +- TXGBE_IRQ_LINK, ++ TXGBE_IRQ_LINK = 0, + TXGBE_IRQ_MAX + }; + +@@ -335,7 +333,6 @@ struct txgbe { + struct clk_lookup *clock; + struct clk *clk; + struct gpio_chip *gpio; +- unsigned int gpio_irq; + unsigned int link_irq; + + /* flow director */ +-- +2.43.0 + diff --git a/queue-6.12/net-usb-lan78xx-fix-double-free-issue-with-interrupt.patch b/queue-6.12/net-usb-lan78xx-fix-double-free-issue-with-interrupt.patch new file mode 100644 index 00000000000..776a7476afa --- /dev/null +++ b/queue-6.12/net-usb-lan78xx-fix-double-free-issue-with-interrupt.patch @@ -0,0 +1,101 @@ +From d685134b5739ea8e7afe497d1f016fb7b650a739 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Sat, 16 Nov 2024 14:05:57 +0100 +Subject: net: usb: lan78xx: Fix double free issue with interrupt buffer + allocation + +From: Oleksij Rempel <o.rempel@pengutronix.de> + +[ Upstream commit 03819abbeb11117dcbba40bfe322b88c0c88a6b6 ] + +In lan78xx_probe(), the buffer `buf` was being freed twice: once +implicitly through `usb_free_urb(dev->urb_intr)` with the +`URB_FREE_BUFFER` flag and again explicitly by `kfree(buf)`. This caused +a double free issue. + +To resolve this, reordered `kmalloc()` and `usb_alloc_urb()` calls to +simplify the initialization sequence and removed the redundant +`kfree(buf)`. Now, `buf` is allocated after `usb_alloc_urb()`, ensuring +it is correctly managed by `usb_fill_int_urb()` and freed by +`usb_free_urb()` as intended. + +Fixes: a6df95cae40b ("lan78xx: Fix memory allocation bug") +Cc: John Efstathiades <john.efstathiades@pebblebay.com> +Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de> +Link: https://patch.msgid.link/20241116130558.1352230-1-o.rempel@pengutronix.de +Signed-off-by: Jakub Kicinski <kuba@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/net/usb/lan78xx.c | 29 ++++++++++++++--------------- + 1 file changed, 14 insertions(+), 15 deletions(-) + +diff --git a/drivers/net/usb/lan78xx.c b/drivers/net/usb/lan78xx.c +index 8adf77e3557e7..094a47b8b97eb 100644 +--- a/drivers/net/usb/lan78xx.c ++++ b/drivers/net/usb/lan78xx.c +@@ -4414,29 +4414,30 @@ static int lan78xx_probe(struct usb_interface *intf, + + period = ep_intr->desc.bInterval; + maxp = usb_maxpacket(dev->udev, dev->pipe_intr); +- buf = kmalloc(maxp, GFP_KERNEL); +- if (!buf) { ++ ++ dev->urb_intr = usb_alloc_urb(0, GFP_KERNEL); ++ if (!dev->urb_intr) { + ret = -ENOMEM; + goto out5; + } + +- dev->urb_intr = usb_alloc_urb(0, GFP_KERNEL); +- if (!dev->urb_intr) { ++ buf = kmalloc(maxp, GFP_KERNEL); ++ if (!buf) { + ret = -ENOMEM; +- goto out6; +- } else { +- usb_fill_int_urb(dev->urb_intr, dev->udev, +- dev->pipe_intr, buf, maxp, +- intr_complete, dev, period); +- dev->urb_intr->transfer_flags |= URB_FREE_BUFFER; ++ goto free_urbs; + } + ++ usb_fill_int_urb(dev->urb_intr, dev->udev, ++ dev->pipe_intr, buf, maxp, ++ intr_complete, dev, period); ++ dev->urb_intr->transfer_flags |= URB_FREE_BUFFER; ++ + dev->maxpacket = usb_maxpacket(dev->udev, dev->pipe_out); + + /* Reject broken descriptors. */ + if (dev->maxpacket == 0) { + ret = -ENODEV; +- goto out6; ++ goto free_urbs; + } + + /* driver requires remote-wakeup capability during autosuspend. */ +@@ -4444,7 +4445,7 @@ static int lan78xx_probe(struct usb_interface *intf, + + ret = lan78xx_phy_init(dev); + if (ret < 0) +- goto out7; ++ goto free_urbs; + + ret = register_netdev(netdev); + if (ret != 0) { +@@ -4466,10 +4467,8 @@ static int lan78xx_probe(struct usb_interface *intf, + + out8: + phy_disconnect(netdev->phydev); +-out7: ++free_urbs: + usb_free_urb(dev->urb_intr); +-out6: +- kfree(buf); + out5: + lan78xx_unbind(dev, intf); + out4: +-- +2.43.0 + diff --git a/queue-6.12/net-usb-lan78xx-fix-memory-leak-on-device-unplug-by-.patch b/queue-6.12/net-usb-lan78xx-fix-memory-leak-on-device-unplug-by-.patch new file mode 100644 index 00000000000..bfc03609082 --- /dev/null +++ b/queue-6.12/net-usb-lan78xx-fix-memory-leak-on-device-unplug-by-.patch @@ -0,0 +1,51 @@ +From f44870adad6e8a8e46bf427d078fdc29df3ce442 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Sat, 16 Nov 2024 14:05:58 +0100 +Subject: net: usb: lan78xx: Fix memory leak on device unplug by freeing PHY + device + +From: Oleksij Rempel <o.rempel@pengutronix.de> + +[ Upstream commit ae7370e61c5d8f5bcefc2d4fca724bd4e9bbf789 ] + +Add calls to `phy_device_free` after `fixed_phy_unregister` to fix a +memory leak that occurs when the device is unplugged. This ensures +proper cleanup of pseudo fixed-link PHYs. + +Fixes: 89b36fb5e532 ("lan78xx: Lan7801 Support for Fixed PHY") +Cc: Raghuram Chary J <raghuramchary.jallipalli@microchip.com> +Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de> +Link: https://patch.msgid.link/20241116130558.1352230-2-o.rempel@pengutronix.de +Signed-off-by: Jakub Kicinski <kuba@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/net/usb/lan78xx.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/usb/lan78xx.c b/drivers/net/usb/lan78xx.c +index 094a47b8b97eb..9f191b6ce8215 100644 +--- a/drivers/net/usb/lan78xx.c ++++ b/drivers/net/usb/lan78xx.c +@@ -2380,6 +2380,7 @@ static int lan78xx_phy_init(struct lan78xx_net *dev) + if (dev->chipid == ID_REV_CHIP_ID_7801_) { + if (phy_is_pseudo_fixed_link(phydev)) { + fixed_phy_unregister(phydev); ++ phy_device_free(phydev); + } else { + phy_unregister_fixup_for_uid(PHY_KSZ9031RNX, + 0xfffffff0); +@@ -4246,8 +4247,10 @@ static void lan78xx_disconnect(struct usb_interface *intf) + + phy_disconnect(net->phydev); + +- if (phy_is_pseudo_fixed_link(phydev)) ++ if (phy_is_pseudo_fixed_link(phydev)) { + fixed_phy_unregister(phydev); ++ phy_device_free(phydev); ++ } + + usb_scuttle_anchored_urbs(&dev->deferred); + +-- +2.43.0 + diff --git a/queue-6.12/net-usb-lan78xx-fix-refcounting-and-autosuspend-on-i.patch b/queue-6.12/net-usb-lan78xx-fix-refcounting-and-autosuspend-on-i.patch new file mode 100644 index 00000000000..9970c1338a4 --- /dev/null +++ b/queue-6.12/net-usb-lan78xx-fix-refcounting-and-autosuspend-on-i.patch @@ -0,0 +1,49 @@ +From 06a504274a6adbca0c29f14658823b5543df95e2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Mon, 18 Nov 2024 15:03:51 +0100 +Subject: net: usb: lan78xx: Fix refcounting and autosuspend on invalid WoL + configuration + +From: Oleksij Rempel <o.rempel@pengutronix.de> + +[ Upstream commit e863ff806f72098bccaf8fa89c80d9ad6187c3b0 ] + +Validate Wake-on-LAN (WoL) options in `lan78xx_set_wol` before calling +`usb_autopm_get_interface`. This prevents USB autopm refcounting issues +and ensures the adapter can properly enter autosuspend when invalid WoL +options are provided. + +Fixes: eb9ad088f966 ("lan78xx: Check for supported Wake-on-LAN modes") +Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de> +Acked-by: Florian Fainelli <f.fainelli@gmail.com> +Link: https://patch.msgid.link/20241118140351.2398166-1-o.rempel@pengutronix.de +Signed-off-by: Jakub Kicinski <kuba@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/net/usb/lan78xx.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/drivers/net/usb/lan78xx.c b/drivers/net/usb/lan78xx.c +index 9f191b6ce8215..531b1b6a37d19 100644 +--- a/drivers/net/usb/lan78xx.c ++++ b/drivers/net/usb/lan78xx.c +@@ -1652,13 +1652,13 @@ static int lan78xx_set_wol(struct net_device *netdev, + struct lan78xx_priv *pdata = (struct lan78xx_priv *)(dev->data[0]); + int ret; + ++ if (wol->wolopts & ~WAKE_ALL) ++ return -EINVAL; ++ + ret = usb_autopm_get_interface(dev->intf); + if (ret < 0) + return ret; + +- if (wol->wolopts & ~WAKE_ALL) +- return -EINVAL; +- + pdata->wol = wol->wolopts; + + device_set_wakeup_enable(&dev->udev->dev, (bool)wol->wolopts); +-- +2.43.0 + diff --git a/queue-6.12/netdevsim-copy-addresses-for-both-in-and-out-paths.patch b/queue-6.12/netdevsim-copy-addresses-for-both-in-and-out-paths.patch new file mode 100644 index 00000000000..9064e23fcf4 --- /dev/null +++ b/queue-6.12/netdevsim-copy-addresses-for-both-in-and-out-paths.patch @@ -0,0 +1,70 @@ +From 47c41cf79dac5a4d75f9c130d0bcc754c2545995 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Thu, 10 Oct 2024 04:00:26 +0000 +Subject: netdevsim: copy addresses for both in and out paths + +From: Hangbin Liu <liuhangbin@gmail.com> + +[ Upstream commit 2cf567f421dbfe7e53b7e5ddee9400da10efb75d ] + +The current code only copies the address for the in path, leaving the out +path address set to 0. This patch corrects the issue by copying the addresses +for both the in and out paths. Before this patch: + + # cat /sys/kernel/debug/netdevsim/netdevsim0/ports/0/ipsec + SA count=2 tx=20 + sa[0] tx ipaddr=0.0.0.0 + sa[0] spi=0x00000100 proto=0x32 salt=0x0adecc3a crypt=1 + sa[0] key=0x3167608a ca4f1397 43565909 941fa627 + sa[1] rx ipaddr=192.168.0.1 + sa[1] spi=0x00000101 proto=0x32 salt=0x0adecc3a crypt=1 + sa[1] key=0x3167608a ca4f1397 43565909 941fa627 + +After this patch: + + = cat /sys/kernel/debug/netdevsim/netdevsim0/ports/0/ipsec + SA count=2 tx=20 + sa[0] tx ipaddr=192.168.0.2 + sa[0] spi=0x00000100 proto=0x32 salt=0x0adecc3a crypt=1 + sa[0] key=0x3167608a ca4f1397 43565909 941fa627 + sa[1] rx ipaddr=192.168.0.1 + sa[1] spi=0x00000101 proto=0x32 salt=0x0adecc3a crypt=1 + sa[1] key=0x3167608a ca4f1397 43565909 941fa627 + +Fixes: 7699353da875 ("netdevsim: add ipsec offload testing") +Reviewed-by: Simon Horman <horms@kernel.org> +Signed-off-by: Hangbin Liu <liuhangbin@gmail.com> +Link: https://patch.msgid.link/20241010040027.21440-3-liuhangbin@gmail.com +Signed-off-by: Jakub Kicinski <kuba@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/net/netdevsim/ipsec.c | 11 +++++------ + 1 file changed, 5 insertions(+), 6 deletions(-) + +diff --git a/drivers/net/netdevsim/ipsec.c b/drivers/net/netdevsim/ipsec.c +index f0d58092e7e96..3612b0633bd17 100644 +--- a/drivers/net/netdevsim/ipsec.c ++++ b/drivers/net/netdevsim/ipsec.c +@@ -176,14 +176,13 @@ static int nsim_ipsec_add_sa(struct xfrm_state *xs, + return ret; + } + +- if (xs->xso.dir == XFRM_DEV_OFFLOAD_IN) { ++ if (xs->xso.dir == XFRM_DEV_OFFLOAD_IN) + sa.rx = true; + +- if (xs->props.family == AF_INET6) +- memcpy(sa.ipaddr, &xs->id.daddr.a6, 16); +- else +- memcpy(&sa.ipaddr[3], &xs->id.daddr.a4, 4); +- } ++ if (xs->props.family == AF_INET6) ++ memcpy(sa.ipaddr, &xs->id.daddr.a6, 16); ++ else ++ memcpy(&sa.ipaddr[3], &xs->id.daddr.a4, 4); + + /* the preparations worked, so save the info */ + memcpy(&ipsec->sa[sa_idx], &sa, sizeof(sa)); +-- +2.43.0 + diff --git a/queue-6.12/netfilter-nf_tables-avoid-false-positive-lockdep-spl.patch b/queue-6.12/netfilter-nf_tables-avoid-false-positive-lockdep-spl.patch new file mode 100644 index 00000000000..696dd46838a --- /dev/null +++ b/queue-6.12/netfilter-nf_tables-avoid-false-positive-lockdep-spl.patch @@ -0,0 +1,133 @@ +From 9c1e6b2b9772f8c457d30c0f56c79157bf7fd5c7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Mon, 4 Nov 2024 10:41:13 +0100 +Subject: netfilter: nf_tables: avoid false-positive lockdep splat on rule + deletion + +From: Florian Westphal <fw@strlen.de> + +[ Upstream commit 9adbb4198bf6cf3634032871118a7052aeaa573f ] + +On rule delete we get: + WARNING: suspicious RCU usage + net/netfilter/nf_tables_api.c:3420 RCU-list traversed in non-reader section!! + 1 lock held by iptables/134: + #0: ffff888008c4fcc8 (&nft_net->commit_mutex){+.+.}-{3:3}, at: nf_tables_valid_genid (include/linux/jiffies.h:101) nf_tables + +Code is fine, no other CPU can change the list because we're holding +transaction mutex. + +Pass the needed lockdep annotation to the iterator and fix +two comments for functions that are no longer restricted to rcu-only +context. + +This is enough to resolve rule delete, but there are several other +missing annotations, added in followup-patches. + +Fixes: 28875945ba98 ("rcu: Add support for consolidated-RCU reader checking") +Reported-by: Matthieu Baerts <matttbe@kernel.org> +Tested-by: Matthieu Baerts <matttbe@kernel.org> +Closes: https://lore.kernel.org/netfilter-devel/da27f17f-3145-47af-ad0f-7fd2a823623e@kernel.org/ +Signed-off-by: Florian Westphal <fw@strlen.de> +Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + net/netfilter/nf_tables_api.c | 23 +++++++++++++---------- + 1 file changed, 13 insertions(+), 10 deletions(-) + +diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c +index 588a2757986c1..deb4a91808598 100644 +--- a/net/netfilter/nf_tables_api.c ++++ b/net/netfilter/nf_tables_api.c +@@ -3412,13 +3412,15 @@ void nft_expr_destroy(const struct nft_ctx *ctx, struct nft_expr *expr) + * Rules + */ + +-static struct nft_rule *__nft_rule_lookup(const struct nft_chain *chain, ++static struct nft_rule *__nft_rule_lookup(const struct net *net, ++ const struct nft_chain *chain, + u64 handle) + { + struct nft_rule *rule; + + // FIXME: this sucks +- list_for_each_entry_rcu(rule, &chain->rules, list) { ++ list_for_each_entry_rcu(rule, &chain->rules, list, ++ lockdep_commit_lock_is_held(net)) { + if (handle == rule->handle) + return rule; + } +@@ -3426,13 +3428,14 @@ static struct nft_rule *__nft_rule_lookup(const struct nft_chain *chain, + return ERR_PTR(-ENOENT); + } + +-static struct nft_rule *nft_rule_lookup(const struct nft_chain *chain, ++static struct nft_rule *nft_rule_lookup(const struct net *net, ++ const struct nft_chain *chain, + const struct nlattr *nla) + { + if (nla == NULL) + return ERR_PTR(-EINVAL); + +- return __nft_rule_lookup(chain, be64_to_cpu(nla_get_be64(nla))); ++ return __nft_rule_lookup(net, chain, be64_to_cpu(nla_get_be64(nla))); + } + + static const struct nla_policy nft_rule_policy[NFTA_RULE_MAX + 1] = { +@@ -3733,7 +3736,7 @@ static int nf_tables_dump_rules_done(struct netlink_callback *cb) + return 0; + } + +-/* called with rcu_read_lock held */ ++/* Caller must hold rcu read lock or transaction mutex */ + static struct sk_buff * + nf_tables_getrule_single(u32 portid, const struct nfnl_info *info, + const struct nlattr * const nla[], bool reset) +@@ -3760,7 +3763,7 @@ nf_tables_getrule_single(u32 portid, const struct nfnl_info *info, + return ERR_CAST(chain); + } + +- rule = nft_rule_lookup(chain, nla[NFTA_RULE_HANDLE]); ++ rule = nft_rule_lookup(net, chain, nla[NFTA_RULE_HANDLE]); + if (IS_ERR(rule)) { + NL_SET_BAD_ATTR(extack, nla[NFTA_RULE_HANDLE]); + return ERR_CAST(rule); +@@ -4058,7 +4061,7 @@ static int nf_tables_newrule(struct sk_buff *skb, const struct nfnl_info *info, + + if (nla[NFTA_RULE_HANDLE]) { + handle = be64_to_cpu(nla_get_be64(nla[NFTA_RULE_HANDLE])); +- rule = __nft_rule_lookup(chain, handle); ++ rule = __nft_rule_lookup(net, chain, handle); + if (IS_ERR(rule)) { + NL_SET_BAD_ATTR(extack, nla[NFTA_RULE_HANDLE]); + return PTR_ERR(rule); +@@ -4080,7 +4083,7 @@ static int nf_tables_newrule(struct sk_buff *skb, const struct nfnl_info *info, + + if (nla[NFTA_RULE_POSITION]) { + pos_handle = be64_to_cpu(nla_get_be64(nla[NFTA_RULE_POSITION])); +- old_rule = __nft_rule_lookup(chain, pos_handle); ++ old_rule = __nft_rule_lookup(net, chain, pos_handle); + if (IS_ERR(old_rule)) { + NL_SET_BAD_ATTR(extack, nla[NFTA_RULE_POSITION]); + return PTR_ERR(old_rule); +@@ -4297,7 +4300,7 @@ static int nf_tables_delrule(struct sk_buff *skb, const struct nfnl_info *info, + + if (chain) { + if (nla[NFTA_RULE_HANDLE]) { +- rule = nft_rule_lookup(chain, nla[NFTA_RULE_HANDLE]); ++ rule = nft_rule_lookup(info->net, chain, nla[NFTA_RULE_HANDLE]); + if (IS_ERR(rule)) { + if (PTR_ERR(rule) == -ENOENT && + NFNL_MSG_TYPE(info->nlh->nlmsg_type) == NFT_MSG_DESTROYRULE) +@@ -8104,7 +8107,7 @@ static int nf_tables_dump_obj_done(struct netlink_callback *cb) + return 0; + } + +-/* called with rcu_read_lock held */ ++/* Caller must hold rcu read lock or transaction mutex */ + static struct sk_buff * + nf_tables_getobj_single(u32 portid, const struct nfnl_info *info, + const struct nlattr * const nla[], bool reset) +-- +2.43.0 + diff --git a/queue-6.12/netfilter-nf_tables-must-hold-rcu-read-lock-while-it.patch b/queue-6.12/netfilter-nf_tables-must-hold-rcu-read-lock-while-it.patch new file mode 100644 index 00000000000..f57a22254ac --- /dev/null +++ b/queue-6.12/netfilter-nf_tables-must-hold-rcu-read-lock-while-it.patch @@ -0,0 +1,84 @@ +From 5141eb874ea3c30e915c0ea479ca3f1c0b50e537 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Mon, 4 Nov 2024 10:41:18 +0100 +Subject: netfilter: nf_tables: must hold rcu read lock while iterating + expression type list + +From: Florian Westphal <fw@strlen.de> + +[ Upstream commit ee666a541ed957937454d50afa4757924508cd74 ] + +nft shell tests trigger: + WARNING: suspicious RCU usage + net/netfilter/nf_tables_api.c:3125 RCU-list traversed in non-reader section!! + 1 lock held by nft/2068: + #0: ffff888106c6f8c8 (&nft_net->commit_mutex){+.+.}-{4:4}, at: nf_tables_valid_genid+0x3c/0xf0 + +But the transaction mutex doesn't protect this list, the nfnl subsystem +mutex would, but we can't acquire it here without risk of ABBA +deadlocks. + +Acquire the rcu read lock to avoid this issue. + +v3: add a comment that explains the ->inner_ops check implies +expression is builtin and lack of a module owner reference is ok. + +Fixes: 3a07327d10a0 ("netfilter: nft_inner: support for inner tunnel header matching") +Signed-off-by: Florian Westphal <fw@strlen.de> +Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + net/netfilter/nf_tables_api.c | 24 ++++++++++++++++++------ + 1 file changed, 18 insertions(+), 6 deletions(-) + +diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c +index deb4a91808598..895e23d0dc36d 100644 +--- a/net/netfilter/nf_tables_api.c ++++ b/net/netfilter/nf_tables_api.c +@@ -3295,25 +3295,37 @@ int nft_expr_inner_parse(const struct nft_ctx *ctx, const struct nlattr *nla, + if (!tb[NFTA_EXPR_DATA] || !tb[NFTA_EXPR_NAME]) + return -EINVAL; + ++ rcu_read_lock(); ++ + type = __nft_expr_type_get(ctx->family, tb[NFTA_EXPR_NAME]); +- if (!type) +- return -ENOENT; ++ if (!type) { ++ err = -ENOENT; ++ goto out_unlock; ++ } + +- if (!type->inner_ops) +- return -EOPNOTSUPP; ++ if (!type->inner_ops) { ++ err = -EOPNOTSUPP; ++ goto out_unlock; ++ } + + err = nla_parse_nested_deprecated(info->tb, type->maxattr, + tb[NFTA_EXPR_DATA], + type->policy, NULL); + if (err < 0) +- goto err_nla_parse; ++ goto out_unlock; + + info->attr = nla; + info->ops = type->inner_ops; + ++ /* No module reference will be taken on type->owner. ++ * Presence of type->inner_ops implies that the expression ++ * is builtin, so it cannot go away. ++ */ ++ rcu_read_unlock(); + return 0; + +-err_nla_parse: ++out_unlock: ++ rcu_read_unlock(); + return err; + } + +-- +2.43.0 + diff --git a/queue-6.12/netfilter-nf_tables-must-hold-rcu-read-lock-while-it.patch-17532 b/queue-6.12/netfilter-nf_tables-must-hold-rcu-read-lock-while-it.patch-17532 new file mode 100644 index 00000000000..5995c4f55d5 --- /dev/null +++ b/queue-6.12/netfilter-nf_tables-must-hold-rcu-read-lock-while-it.patch-17532 @@ -0,0 +1,75 @@ +From 7543081068618d373f30f6d4d8222606bb3df1f7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Mon, 4 Nov 2024 10:41:19 +0100 +Subject: netfilter: nf_tables: must hold rcu read lock while iterating object + type list + +From: Florian Westphal <fw@strlen.de> + +[ Upstream commit cddc04275f95ca3b18da5c0fb111705ac173af89 ] + +Update of stateful object triggers: +WARNING: suspicious RCU usage +net/netfilter/nf_tables_api.c:7759 RCU-list traversed in non-reader section!! + +other info that might help us debug this: +rcu_scheduler_active = 2, debug_locks = 1 +1 lock held by nft/3060: + #0: ffff88810f0578c8 (&nft_net->commit_mutex){+.+.}-{4:4}, [..] + +... but this list is not protected by the transaction mutex but the +nfnl nftables subsystem mutex. + +Switch to nft_obj_type_get which will acquire rcu read lock, +bump refcount, and returns the result. + +v3: Dan Carpenter points out nft_obj_type_get returns error pointer, not +NULL, on error. + +Fixes: dad3bdeef45f ("netfilter: nf_tables: fix memory leak during stateful obj update"). +Signed-off-by: Florian Westphal <fw@strlen.de> +Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + net/netfilter/nf_tables_api.c | 13 ++++++------- + 1 file changed, 6 insertions(+), 7 deletions(-) + +diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c +index 895e23d0dc36d..4a137afaf0b87 100644 +--- a/net/netfilter/nf_tables_api.c ++++ b/net/netfilter/nf_tables_api.c +@@ -7805,9 +7805,7 @@ static int nf_tables_updobj(const struct nft_ctx *ctx, + struct nft_trans *trans; + int err = -ENOMEM; + +- if (!try_module_get(type->owner)) +- return -ENOENT; +- ++ /* caller must have obtained type->owner reference. */ + trans = nft_trans_alloc(ctx, NFT_MSG_NEWOBJ, + sizeof(struct nft_trans_obj)); + if (!trans) +@@ -7875,15 +7873,16 @@ static int nf_tables_newobj(struct sk_buff *skb, const struct nfnl_info *info, + if (info->nlh->nlmsg_flags & NLM_F_REPLACE) + return -EOPNOTSUPP; + +- type = __nft_obj_type_get(objtype, family); +- if (WARN_ON_ONCE(!type)) +- return -ENOENT; +- + if (!obj->ops->update) + return 0; + ++ type = nft_obj_type_get(net, objtype, family); ++ if (WARN_ON_ONCE(IS_ERR(type))) ++ return PTR_ERR(type); ++ + nft_ctx_init(&ctx, net, skb, info->nlh, family, table, NULL, nla); + ++ /* type->owner reference is put when transaction object is released. */ + return nf_tables_updobj(&ctx, type, nla[NFTA_OBJ_DATA], obj); + } + +-- +2.43.0 + diff --git a/queue-6.12/netfs-fscache-add-a-memory-barrier-for-fscache_volum.patch b/queue-6.12/netfs-fscache-add-a-memory-barrier-for-fscache_volum.patch new file mode 100644 index 00000000000..1b3e6a2d440 --- /dev/null +++ b/queue-6.12/netfs-fscache-add-a-memory-barrier-for-fscache_volum.patch @@ -0,0 +1,67 @@ +From 60753bc926a5140b23f4aa42ae3a4e0bbb29ddd4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Thu, 7 Nov 2024 19:06:49 +0800 +Subject: netfs/fscache: Add a memory barrier for FSCACHE_VOLUME_CREATING + +From: Zizhi Wo <wozizhi@huawei.com> + +[ Upstream commit 22f9400a6f3560629478e0a64247b8fcc811a24d ] + +In fscache_create_volume(), there is a missing memory barrier between the +bit-clearing operation and the wake-up operation. This may cause a +situation where, after a wake-up, the bit-clearing operation hasn't been +detected yet, leading to an indefinite wait. The triggering process is as +follows: + + [cookie1] [cookie2] [volume_work] +fscache_perform_lookup + fscache_create_volume + fscache_perform_lookup + fscache_create_volume + fscache_create_volume_work + cachefiles_acquire_volume + clear_and_wake_up_bit + test_and_set_bit + test_and_set_bit + goto maybe_wait + goto no_wait + +In the above process, cookie1 and cookie2 has the same volume. When cookie1 +enters the -no_wait- process, it will clear the bit and wake up the waiting +process. If a barrier is missing, it may cause cookie2 to remain in the +-wait- process indefinitely. + +In commit 3288666c7256 ("fscache: Use clear_and_wake_up_bit() in +fscache_create_volume_work()"), barriers were added to similar operations +in fscache_create_volume_work(), but fscache_create_volume() was missed. + +By combining the clear and wake operations into clear_and_wake_up_bit() to +fix this issue. + +Fixes: bfa22da3ed65 ("fscache: Provide and use cache methods to lookup/create/free a volume") +Signed-off-by: Zizhi Wo <wozizhi@huawei.com> +Link: https://lore.kernel.org/r/20241107110649.3980193-6-wozizhi@huawei.com +Acked-by: David Howells <dhowells@redhat.com> +Signed-off-by: Christian Brauner <brauner@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + fs/netfs/fscache_volume.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/fs/netfs/fscache_volume.c b/fs/netfs/fscache_volume.c +index cb75c07b5281a..ced14ac78cc1c 100644 +--- a/fs/netfs/fscache_volume.c ++++ b/fs/netfs/fscache_volume.c +@@ -322,8 +322,7 @@ void fscache_create_volume(struct fscache_volume *volume, bool wait) + } + return; + no_wait: +- clear_bit_unlock(FSCACHE_VOLUME_CREATING, &volume->flags); +- wake_up_bit(&volume->flags, FSCACHE_VOLUME_CREATING); ++ clear_and_wake_up_bit(FSCACHE_VOLUME_CREATING, &volume->flags); + } + + /* +-- +2.43.0 + diff --git a/queue-6.12/netlink-fix-false-positive-warning-in-extack-during-.patch b/queue-6.12/netlink-fix-false-positive-warning-in-extack-during-.patch new file mode 100644 index 00000000000..50975d21dc6 --- /dev/null +++ b/queue-6.12/netlink-fix-false-positive-warning-in-extack-during-.patch @@ -0,0 +1,116 @@ +From 2745d89ca67063c7c8d206dc65888ee4b814a206 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Tue, 19 Nov 2024 14:44:31 -0800 +Subject: netlink: fix false positive warning in extack during dumps + +From: Jakub Kicinski <kuba@kernel.org> + +[ Upstream commit 3bf39fa849ab8ed52abb6715922e6102d3df9f97 ] + +Commit under fixes extended extack reporting to dumps. +It works under normal conditions, because extack errors are +usually reported during ->start() or the first ->dump(), +it's quite rare that the dump starts okay but fails later. +If the dump does fail later, however, the input skb will +already have the initiating message pulled, so checking +if bad attr falls within skb->data will fail. + +Switch the check to using nlh, which is always valid. + +syzbot found a way to hit that scenario by filling up +the receive queue. In this case we initiate a dump +but don't call ->dump() until there is read space for +an skb. + +WARNING: CPU: 1 PID: 5845 at net/netlink/af_netlink.c:2210 netlink_ack_tlv_fill+0x1a8/0x560 net/netlink/af_netlink.c:2209 +RIP: 0010:netlink_ack_tlv_fill+0x1a8/0x560 net/netlink/af_netlink.c:2209 +Call Trace: + <TASK> + netlink_dump_done+0x513/0x970 net/netlink/af_netlink.c:2250 + netlink_dump+0x91f/0xe10 net/netlink/af_netlink.c:2351 + netlink_recvmsg+0x6bb/0x11d0 net/netlink/af_netlink.c:1983 + sock_recvmsg_nosec net/socket.c:1051 [inline] + sock_recvmsg+0x22f/0x280 net/socket.c:1073 + __sys_recvfrom+0x246/0x3d0 net/socket.c:2267 + __do_sys_recvfrom net/socket.c:2285 [inline] + __se_sys_recvfrom net/socket.c:2281 [inline] + __x64_sys_recvfrom+0xde/0x100 net/socket.c:2281 + do_syscall_x64 arch/x86/entry/common.c:52 [inline] + do_syscall_64+0xf3/0x230 arch/x86/entry/common.c:83 + entry_SYSCALL_64_after_hwframe+0x77/0x7f + RIP: 0033:0x7ff37dd17a79 + +Reported-by: syzbot+d4373fa8042c06cefa84@syzkaller.appspotmail.com +Fixes: 8af4f60472fc ("netlink: support all extack types in dumps") +Reviewed-by: Jacob Keller <jacob.e.keller@intel.com> +Link: https://patch.msgid.link/20241119224432.1713040-1-kuba@kernel.org +Signed-off-by: Jakub Kicinski <kuba@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + net/netlink/af_netlink.c | 21 +++++++++++---------- + 1 file changed, 11 insertions(+), 10 deletions(-) + +diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c +index f84aad420d446..775d707ec708a 100644 +--- a/net/netlink/af_netlink.c ++++ b/net/netlink/af_netlink.c +@@ -2176,9 +2176,14 @@ netlink_ack_tlv_len(struct netlink_sock *nlk, int err, + return tlvlen; + } + ++static bool nlmsg_check_in_payload(const struct nlmsghdr *nlh, const void *addr) ++{ ++ return !WARN_ON(addr < nlmsg_data(nlh) || ++ addr - (const void *) nlh >= nlh->nlmsg_len); ++} ++ + static void +-netlink_ack_tlv_fill(struct sk_buff *in_skb, struct sk_buff *skb, +- const struct nlmsghdr *nlh, int err, ++netlink_ack_tlv_fill(struct sk_buff *skb, const struct nlmsghdr *nlh, int err, + const struct netlink_ext_ack *extack) + { + if (extack->_msg) +@@ -2190,9 +2195,7 @@ netlink_ack_tlv_fill(struct sk_buff *in_skb, struct sk_buff *skb, + if (!err) + return; + +- if (extack->bad_attr && +- !WARN_ON((u8 *)extack->bad_attr < in_skb->data || +- (u8 *)extack->bad_attr >= in_skb->data + in_skb->len)) ++ if (extack->bad_attr && nlmsg_check_in_payload(nlh, extack->bad_attr)) + WARN_ON(nla_put_u32(skb, NLMSGERR_ATTR_OFFS, + (u8 *)extack->bad_attr - (const u8 *)nlh)); + if (extack->policy) +@@ -2201,9 +2204,7 @@ netlink_ack_tlv_fill(struct sk_buff *in_skb, struct sk_buff *skb, + if (extack->miss_type) + WARN_ON(nla_put_u32(skb, NLMSGERR_ATTR_MISS_TYPE, + extack->miss_type)); +- if (extack->miss_nest && +- !WARN_ON((u8 *)extack->miss_nest < in_skb->data || +- (u8 *)extack->miss_nest > in_skb->data + in_skb->len)) ++ if (extack->miss_nest && nlmsg_check_in_payload(nlh, extack->miss_nest)) + WARN_ON(nla_put_u32(skb, NLMSGERR_ATTR_MISS_NEST, + (u8 *)extack->miss_nest - (const u8 *)nlh)); + } +@@ -2232,7 +2233,7 @@ static int netlink_dump_done(struct netlink_sock *nlk, struct sk_buff *skb, + if (extack_len) { + nlh->nlmsg_flags |= NLM_F_ACK_TLVS; + if (skb_tailroom(skb) >= extack_len) { +- netlink_ack_tlv_fill(cb->skb, skb, cb->nlh, ++ netlink_ack_tlv_fill(skb, cb->nlh, + nlk->dump_done_errno, extack); + nlmsg_end(skb, nlh); + } +@@ -2491,7 +2492,7 @@ void netlink_ack(struct sk_buff *in_skb, struct nlmsghdr *nlh, int err, + } + + if (tlvlen) +- netlink_ack_tlv_fill(in_skb, skb, nlh, err, extack); ++ netlink_ack_tlv_fill(skb, nlh, err, extack); + + nlmsg_end(skb, rep); + +-- +2.43.0 + diff --git a/queue-6.12/netlink-typographical-error-in-nlmsg_type-constants-.patch b/queue-6.12/netlink-typographical-error-in-nlmsg_type-constants-.patch new file mode 100644 index 00000000000..0021d931dc3 --- /dev/null +++ b/queue-6.12/netlink-typographical-error-in-nlmsg_type-constants-.patch @@ -0,0 +1,36 @@ +From 7e1dbb4099d451bc25021ff88ed740a58fc03fa4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Sun, 3 Nov 2024 23:39:50 +0100 +Subject: netlink: typographical error in nlmsg_type constants definition + +From: Maurice Lambert <mauricelambert434@gmail.com> + +[ Upstream commit 84bfbfbbd32aee136afea4b6bf82581dce79c305 ] + +This commit fix a typographical error in netlink nlmsg_type constants definition in the include/uapi/linux/rtnetlink.h at line 177. The definition is RTM_NEWNVLAN RTM_NEWVLAN instead of RTM_NEWVLAN RTM_NEWVLAN. + +Signed-off-by: Maurice Lambert <mauricelambert434@gmail.com> +Fixes: 8dcea187088b ("net: bridge: vlan: add rtm definitions and dump support") +Link: https://patch.msgid.link/20241103223950.230300-1-mauricelambert434@gmail.com +Signed-off-by: Jakub Kicinski <kuba@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + include/uapi/linux/rtnetlink.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/include/uapi/linux/rtnetlink.h b/include/uapi/linux/rtnetlink.h +index 3b687d20c9ed3..db7254d52d935 100644 +--- a/include/uapi/linux/rtnetlink.h ++++ b/include/uapi/linux/rtnetlink.h +@@ -174,7 +174,7 @@ enum { + #define RTM_GETLINKPROP RTM_GETLINKPROP + + RTM_NEWVLAN = 112, +-#define RTM_NEWNVLAN RTM_NEWVLAN ++#define RTM_NEWVLAN RTM_NEWVLAN + RTM_DELVLAN, + #define RTM_DELVLAN RTM_DELVLAN + RTM_GETVLAN, +-- +2.43.0 + diff --git a/queue-6.12/netpoll-use-rcu_access_pointer-in-netpoll_poll_lock.patch b/queue-6.12/netpoll-use-rcu_access_pointer-in-netpoll_poll_lock.patch new file mode 100644 index 00000000000..07c4785b155 --- /dev/null +++ b/queue-6.12/netpoll-use-rcu_access_pointer-in-netpoll_poll_lock.patch @@ -0,0 +1,45 @@ +From aec95afef2ebc88bac9e8aa9342ba8a4226f4082 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Mon, 18 Nov 2024 03:15:18 -0800 +Subject: netpoll: Use rcu_access_pointer() in netpoll_poll_lock + +From: Breno Leitao <leitao@debian.org> + +[ Upstream commit a57d5a72f8dec7db8a79d0016fb0a3bdecc82b56 ] + +The ndev->npinfo pointer in netpoll_poll_lock() is RCU-protected but is +being accessed directly for a NULL check. While no RCU read lock is held +in this context, we should still use proper RCU primitives for +consistency and correctness. + +Replace the direct NULL check with rcu_access_pointer(), which is the +appropriate primitive when only checking for NULL without dereferencing +the pointer. This function provides the necessary ordering guarantees +without requiring RCU read-side protection. + +Fixes: bea3348eef27 ("[NET]: Make NAPI polling independent of struct net_device objects.") +Signed-off-by: Breno Leitao <leitao@debian.org> +Reviewed-by: Michal Kubiak <michal.kubiak@intel.com> +Link: https://patch.msgid.link/20241118-netpoll_rcu-v1-2-a1888dcb4a02@debian.org +Signed-off-by: Jakub Kicinski <kuba@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + include/linux/netpoll.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/include/linux/netpoll.h b/include/linux/netpoll.h +index cd4e28db0cbd7..959a4daacea1f 100644 +--- a/include/linux/netpoll.h ++++ b/include/linux/netpoll.h +@@ -72,7 +72,7 @@ static inline void *netpoll_poll_lock(struct napi_struct *napi) + { + struct net_device *dev = napi->dev; + +- if (dev && dev->npinfo) { ++ if (dev && rcu_access_pointer(dev->npinfo)) { + int owner = smp_processor_id(); + + while (cmpxchg(&napi->poll_owner, -1, owner) != -1) +-- +2.43.0 + diff --git a/queue-6.12/nfs_common-must-not-hold-rcu-while-calling-nfsd_file.patch b/queue-6.12/nfs_common-must-not-hold-rcu-while-calling-nfsd_file.patch new file mode 100644 index 00000000000..265a7931c0f --- /dev/null +++ b/queue-6.12/nfs_common-must-not-hold-rcu-while-calling-nfsd_file.patch @@ -0,0 +1,195 @@ +From 1872d3d40b818f422f3f5efa9add0f9e8eb4bf56 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Wed, 13 Nov 2024 22:59:38 -0500 +Subject: nfs_common: must not hold RCU while calling nfsd_file_put_local + +From: Mike Snitzer <snitzer@kernel.org> + +[ Upstream commit c840b8e1f039e90f97ca55525667eb961422f86c ] + +Move holding the RCU from nfs_to_nfsd_file_put_local to +nfs_to_nfsd_net_put. It is the call to nfs_to->nfsd_serv_put that +requires the RCU anyway (the puts for nfsd_file and netns were +combined to avoid an extra indirect reference but that +micro-optimization isn't possible now). + +This fixes xfstests generic/013 and it triggering: + +"Voluntary context switch within RCU read-side critical section!" + +[ 143.545738] Call Trace: +[ 143.546206] <TASK> +[ 143.546625] ? show_regs+0x6d/0x80 +[ 143.547267] ? __warn+0x91/0x140 +[ 143.547951] ? rcu_note_context_switch+0x496/0x5d0 +[ 143.548856] ? report_bug+0x193/0x1a0 +[ 143.549557] ? handle_bug+0x63/0xa0 +[ 143.550214] ? exc_invalid_op+0x1d/0x80 +[ 143.550938] ? asm_exc_invalid_op+0x1f/0x30 +[ 143.551736] ? rcu_note_context_switch+0x496/0x5d0 +[ 143.552634] ? wakeup_preempt+0x62/0x70 +[ 143.553358] __schedule+0xaa/0x1380 +[ 143.554025] ? _raw_spin_unlock_irqrestore+0x12/0x40 +[ 143.554958] ? try_to_wake_up+0x1fe/0x6b0 +[ 143.555715] ? wake_up_process+0x19/0x20 +[ 143.556452] schedule+0x2e/0x120 +[ 143.557066] schedule_preempt_disabled+0x19/0x30 +[ 143.557933] rwsem_down_read_slowpath+0x24d/0x4a0 +[ 143.558818] ? xfs_efi_item_format+0x50/0xc0 [xfs] +[ 143.559894] down_read+0x4e/0xb0 +[ 143.560519] xlog_cil_commit+0x1b2/0xbc0 [xfs] +[ 143.561460] ? _raw_spin_unlock+0x12/0x30 +[ 143.562212] ? xfs_inode_item_precommit+0xc7/0x220 [xfs] +[ 143.563309] ? xfs_trans_run_precommits+0x69/0xd0 [xfs] +[ 143.564394] __xfs_trans_commit+0xb5/0x330 [xfs] +[ 143.565367] xfs_trans_roll+0x48/0xc0 [xfs] +[ 143.566262] xfs_defer_trans_roll+0x57/0x100 [xfs] +[ 143.567278] xfs_defer_finish_noroll+0x27a/0x490 [xfs] +[ 143.568342] xfs_defer_finish+0x1a/0x80 [xfs] +[ 143.569267] xfs_bunmapi_range+0x4d/0xb0 [xfs] +[ 143.570208] xfs_itruncate_extents_flags+0x13d/0x230 [xfs] +[ 143.571353] xfs_free_eofblocks+0x12e/0x190 [xfs] +[ 143.572359] xfs_file_release+0x12d/0x140 [xfs] +[ 143.573324] __fput+0xe8/0x2d0 +[ 143.573922] __fput_sync+0x1d/0x30 +[ 143.574574] nfsd_filp_close+0x33/0x60 [nfsd] +[ 143.575430] nfsd_file_free+0x96/0x150 [nfsd] +[ 143.576274] nfsd_file_put+0xf7/0x1a0 [nfsd] +[ 143.577104] nfsd_file_put_local+0x18/0x30 [nfsd] +[ 143.578070] nfs_close_local_fh+0x101/0x110 [nfs_localio] +[ 143.579079] __put_nfs_open_context+0xc9/0x180 [nfs] +[ 143.580031] nfs_file_clear_open_context+0x4a/0x60 [nfs] +[ 143.581038] nfs_file_release+0x3e/0x60 [nfs] +[ 143.581879] __fput+0xe8/0x2d0 +[ 143.582464] __fput_sync+0x1d/0x30 +[ 143.583108] __x64_sys_close+0x41/0x80 +[ 143.583823] x64_sys_call+0x189a/0x20d0 +[ 143.584552] do_syscall_64+0x64/0x170 +[ 143.585240] entry_SYSCALL_64_after_hwframe+0x76/0x7e +[ 143.586185] RIP: 0033:0x7f3c5153efd7 + +Fixes: 65f2a5c36635 ("nfs_common: fix race in NFS calls to nfsd_file_put_local() and nfsd_serv_put()") +Signed-off-by: Mike Snitzer <snitzer@kernel.org> +Reviewed-by: NeilBrown <neilb@suse.de> +Reviewed-by: Jeff Layton <jlayton@kernel.org> +Signed-off-by: Chuck Lever <chuck.lever@oracle.com> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + fs/nfs_common/nfslocalio.c | 8 +++----- + fs/nfsd/filecache.c | 14 +++++++------- + fs/nfsd/filecache.h | 2 +- + include/linux/nfslocalio.h | 18 +++++++++++++++--- + 4 files changed, 26 insertions(+), 16 deletions(-) + +diff --git a/fs/nfs_common/nfslocalio.c b/fs/nfs_common/nfslocalio.c +index 09404d142d1ae..a74ec08f6c96d 100644 +--- a/fs/nfs_common/nfslocalio.c ++++ b/fs/nfs_common/nfslocalio.c +@@ -155,11 +155,9 @@ struct nfsd_file *nfs_open_local_fh(nfs_uuid_t *uuid, + /* We have an implied reference to net thanks to nfsd_serv_try_get */ + localio = nfs_to->nfsd_open_local_fh(net, uuid->dom, rpc_clnt, + cred, nfs_fh, fmode); +- if (IS_ERR(localio)) { +- rcu_read_lock(); +- nfs_to->nfsd_serv_put(net); +- rcu_read_unlock(); +- } ++ if (IS_ERR(localio)) ++ nfs_to_nfsd_net_put(net); ++ + return localio; + } + EXPORT_SYMBOL_GPL(nfs_open_local_fh); +diff --git a/fs/nfsd/filecache.c b/fs/nfsd/filecache.c +index 2e6783f637124..146a9463c3c23 100644 +--- a/fs/nfsd/filecache.c ++++ b/fs/nfsd/filecache.c +@@ -391,19 +391,19 @@ nfsd_file_put(struct nfsd_file *nf) + } + + /** +- * nfsd_file_put_local - put the reference to nfsd_file and local nfsd_serv +- * @nf: nfsd_file of which to put the references ++ * nfsd_file_put_local - put nfsd_file reference and arm nfsd_serv_put in caller ++ * @nf: nfsd_file of which to put the reference + * +- * First put the reference of the nfsd_file and then put the +- * reference to the associated nn->nfsd_serv. ++ * First save the associated net to return to caller, then put ++ * the reference of the nfsd_file. + */ +-void +-nfsd_file_put_local(struct nfsd_file *nf) __must_hold(rcu) ++struct net * ++nfsd_file_put_local(struct nfsd_file *nf) + { + struct net *net = nf->nf_net; + + nfsd_file_put(nf); +- nfsd_serv_put(net); ++ return net; + } + + /** +diff --git a/fs/nfsd/filecache.h b/fs/nfsd/filecache.h +index cadf3c2689c44..d5db6b34ba302 100644 +--- a/fs/nfsd/filecache.h ++++ b/fs/nfsd/filecache.h +@@ -55,7 +55,7 @@ void nfsd_file_cache_shutdown(void); + int nfsd_file_cache_start_net(struct net *net); + void nfsd_file_cache_shutdown_net(struct net *net); + void nfsd_file_put(struct nfsd_file *nf); +-void nfsd_file_put_local(struct nfsd_file *nf); ++struct net *nfsd_file_put_local(struct nfsd_file *nf); + struct nfsd_file *nfsd_file_get(struct nfsd_file *nf); + struct file *nfsd_file_file(struct nfsd_file *nf); + void nfsd_file_close_inode_sync(struct inode *inode); +diff --git a/include/linux/nfslocalio.h b/include/linux/nfslocalio.h +index 3982fea799195..9202f4b24343d 100644 +--- a/include/linux/nfslocalio.h ++++ b/include/linux/nfslocalio.h +@@ -55,7 +55,7 @@ struct nfsd_localio_operations { + const struct cred *, + const struct nfs_fh *, + const fmode_t); +- void (*nfsd_file_put_local)(struct nfsd_file *); ++ struct net *(*nfsd_file_put_local)(struct nfsd_file *); + struct file *(*nfsd_file_file)(struct nfsd_file *); + } ____cacheline_aligned; + +@@ -66,7 +66,7 @@ struct nfsd_file *nfs_open_local_fh(nfs_uuid_t *, + struct rpc_clnt *, const struct cred *, + const struct nfs_fh *, const fmode_t); + +-static inline void nfs_to_nfsd_file_put_local(struct nfsd_file *localio) ++static inline void nfs_to_nfsd_net_put(struct net *net) + { + /* + * Once reference to nfsd_serv is dropped, NFSD could be +@@ -74,10 +74,22 @@ static inline void nfs_to_nfsd_file_put_local(struct nfsd_file *localio) + * by always taking RCU. + */ + rcu_read_lock(); +- nfs_to->nfsd_file_put_local(localio); ++ nfs_to->nfsd_serv_put(net); + rcu_read_unlock(); + } + ++static inline void nfs_to_nfsd_file_put_local(struct nfsd_file *localio) ++{ ++ /* ++ * Must not hold RCU otherwise nfsd_file_put() can easily trigger: ++ * "Voluntary context switch within RCU read-side critical section!" ++ * by scheduling deep in underlying filesystem (e.g. XFS). ++ */ ++ struct net *net = nfs_to->nfsd_file_put_local(localio); ++ ++ nfs_to_nfsd_net_put(net); ++} ++ + #else /* CONFIG_NFS_LOCALIO */ + static inline void nfsd_localio_ops_init(void) + { +-- +2.43.0 + diff --git a/queue-6.12/nfsd-cap-the-number-of-bytes-copied-by-nfs4_reset_re.patch b/queue-6.12/nfsd-cap-the-number-of-bytes-copied-by-nfs4_reset_re.patch new file mode 100644 index 00000000000..260a8905cc0 --- /dev/null +++ b/queue-6.12/nfsd-cap-the-number-of-bytes-copied-by-nfs4_reset_re.patch @@ -0,0 +1,37 @@ +From a7b162a68e93783a0959bb32a2adf5e62d564827 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Thu, 17 Oct 2024 11:03:56 -0400 +Subject: NFSD: Cap the number of bytes copied by nfs4_reset_recoverydir() + +From: Chuck Lever <chuck.lever@oracle.com> + +[ Upstream commit f64ea4af43161bb86ffc77e6aeb5bcf5c3229df0 ] + +It's only current caller already length-checks the string, but let's +be safe. + +Fixes: 0964a3d3f1aa ("[PATCH] knfsd: nfsd4 reboot dirname fix") +Reviewed-by: Jeff Layton <jlayton@kernel.org> +Signed-off-by: Chuck Lever <chuck.lever@oracle.com> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + fs/nfsd/nfs4recover.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/fs/nfsd/nfs4recover.c b/fs/nfsd/nfs4recover.c +index b7d61eb8afe9e..4a765555bf845 100644 +--- a/fs/nfsd/nfs4recover.c ++++ b/fs/nfsd/nfs4recover.c +@@ -659,7 +659,8 @@ nfs4_reset_recoverydir(char *recdir) + return status; + status = -ENOTDIR; + if (d_is_dir(path.dentry)) { +- strcpy(user_recovery_dirname, recdir); ++ strscpy(user_recovery_dirname, recdir, ++ sizeof(user_recovery_dirname)); + status = 0; + } + path_put(&path); +-- +2.43.0 + diff --git a/queue-6.12/nfsd-drop-inode-parameter-from-nfsd4_change_attribut.patch b/queue-6.12/nfsd-drop-inode-parameter-from-nfsd4_change_attribut.patch new file mode 100644 index 00000000000..ec0571d0c41 --- /dev/null +++ b/queue-6.12/nfsd-drop-inode-parameter-from-nfsd4_change_attribut.patch @@ -0,0 +1,156 @@ +From 869248e57b931baf610a2ca4d259ab12c0d62cd6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Mon, 11 Nov 2024 11:01:13 -0500 +Subject: nfsd: drop inode parameter from nfsd4_change_attribute() + +From: Jeff Layton <jlayton@kernel.org> + +[ Upstream commit f67eef8da0e8c54709fefdecd16ad8d70f0c9d20 ] + +The inode that nfs4_open_delegation() passes to this function is +wrong, which throws off the result. The inode will end up getting a +directory-style change attr instead of a regular-file-style one. + +Fix up nfs4_delegation_stat() to fetch STATX_MODE, and then drop the +inode parameter from nfsd4_change_attribute(), since it's no longer +needed. + +Fixes: c5967721e106 ("NFSD: handle GETATTR conflict with write delegation") +Signed-off-by: Jeff Layton <jlayton@kernel.org> +Signed-off-by: Chuck Lever <chuck.lever@oracle.com> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + fs/nfsd/nfs4state.c | 5 ++--- + fs/nfsd/nfs4xdr.c | 2 +- + fs/nfsd/nfsfh.c | 20 ++++++++++++-------- + fs/nfsd/nfsfh.h | 3 +-- + 4 files changed, 16 insertions(+), 14 deletions(-) + +diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c +index 551d2958ec290..d3cfc64715399 100644 +--- a/fs/nfsd/nfs4state.c ++++ b/fs/nfsd/nfs4state.c +@@ -5957,7 +5957,7 @@ nfs4_delegation_stat(struct nfs4_delegation *dp, struct svc_fh *currentfh, + path.dentry = file_dentry(nf->nf_file); + + rc = vfs_getattr(&path, stat, +- (STATX_SIZE | STATX_CTIME | STATX_CHANGE_COOKIE), ++ (STATX_MODE | STATX_SIZE | STATX_CTIME | STATX_CHANGE_COOKIE), + AT_STATX_SYNC_AS_STAT); + + nfsd_file_put(nf); +@@ -6041,8 +6041,7 @@ nfs4_open_delegation(struct nfsd4_open *open, struct nfs4_ol_stateid *stp, + } + open->op_delegate_type = NFS4_OPEN_DELEGATE_WRITE; + dp->dl_cb_fattr.ncf_cur_fsize = stat.size; +- dp->dl_cb_fattr.ncf_initial_cinfo = +- nfsd4_change_attribute(&stat, d_inode(currentfh->fh_dentry)); ++ dp->dl_cb_fattr.ncf_initial_cinfo = nfsd4_change_attribute(&stat); + trace_nfsd_deleg_write(&dp->dl_stid.sc_stateid); + } else { + open->op_delegate_type = NFS4_OPEN_DELEGATE_READ; +diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c +index f118921250c31..8d25aef51ad15 100644 +--- a/fs/nfsd/nfs4xdr.c ++++ b/fs/nfsd/nfs4xdr.c +@@ -3040,7 +3040,7 @@ static __be32 nfsd4_encode_fattr4_change(struct xdr_stream *xdr, + return nfs_ok; + } + +- c = nfsd4_change_attribute(&args->stat, d_inode(args->dentry)); ++ c = nfsd4_change_attribute(&args->stat); + return nfsd4_encode_changeid4(xdr, c); + } + +diff --git a/fs/nfsd/nfsfh.c b/fs/nfsd/nfsfh.c +index 40ad58a6a0361..96e19c50a5d7e 100644 +--- a/fs/nfsd/nfsfh.c ++++ b/fs/nfsd/nfsfh.c +@@ -667,20 +667,18 @@ fh_update(struct svc_fh *fhp) + __be32 __must_check fh_fill_pre_attrs(struct svc_fh *fhp) + { + bool v4 = (fhp->fh_maxsize == NFS4_FHSIZE); +- struct inode *inode; + struct kstat stat; + __be32 err; + + if (fhp->fh_no_wcc || fhp->fh_pre_saved) + return nfs_ok; + +- inode = d_inode(fhp->fh_dentry); + err = fh_getattr(fhp, &stat); + if (err) + return err; + + if (v4) +- fhp->fh_pre_change = nfsd4_change_attribute(&stat, inode); ++ fhp->fh_pre_change = nfsd4_change_attribute(&stat); + + fhp->fh_pre_mtime = stat.mtime; + fhp->fh_pre_ctime = stat.ctime; +@@ -697,7 +695,6 @@ __be32 __must_check fh_fill_pre_attrs(struct svc_fh *fhp) + __be32 fh_fill_post_attrs(struct svc_fh *fhp) + { + bool v4 = (fhp->fh_maxsize == NFS4_FHSIZE); +- struct inode *inode = d_inode(fhp->fh_dentry); + __be32 err; + + if (fhp->fh_no_wcc) +@@ -713,7 +710,7 @@ __be32 fh_fill_post_attrs(struct svc_fh *fhp) + fhp->fh_post_saved = true; + if (v4) + fhp->fh_post_change = +- nfsd4_change_attribute(&fhp->fh_post_attr, inode); ++ nfsd4_change_attribute(&fhp->fh_post_attr); + return nfs_ok; + } + +@@ -804,7 +801,14 @@ enum fsid_source fsid_source(const struct svc_fh *fhp) + return FSIDSOURCE_DEV; + } + +-/* ++/** ++ * nfsd4_change_attribute - Generate an NFSv4 change_attribute value ++ * @stat: inode attributes ++ * ++ * Caller must fill in @stat before calling, typically by invoking ++ * vfs_getattr() with STATX_MODE, STATX_CTIME, and STATX_CHANGE_COOKIE. ++ * Returns an unsigned 64-bit changeid4 value (RFC 8881 Section 3.2). ++ * + * We could use i_version alone as the change attribute. However, i_version + * can go backwards on a regular file after an unclean shutdown. On its own + * that doesn't necessarily cause a problem, but if i_version goes backwards +@@ -821,13 +825,13 @@ enum fsid_source fsid_source(const struct svc_fh *fhp) + * assume that the new change attr is always logged to stable storage in some + * fashion before the results can be seen. + */ +-u64 nfsd4_change_attribute(const struct kstat *stat, const struct inode *inode) ++u64 nfsd4_change_attribute(const struct kstat *stat) + { + u64 chattr; + + if (stat->result_mask & STATX_CHANGE_COOKIE) { + chattr = stat->change_cookie; +- if (S_ISREG(inode->i_mode) && ++ if (S_ISREG(stat->mode) && + !(stat->attributes & STATX_ATTR_CHANGE_MONOTONIC)) { + chattr += (u64)stat->ctime.tv_sec << 30; + chattr += stat->ctime.tv_nsec; +diff --git a/fs/nfsd/nfsfh.h b/fs/nfsd/nfsfh.h +index 5b7394801dc42..876152a91f122 100644 +--- a/fs/nfsd/nfsfh.h ++++ b/fs/nfsd/nfsfh.h +@@ -297,8 +297,7 @@ static inline void fh_clear_pre_post_attrs(struct svc_fh *fhp) + fhp->fh_pre_saved = false; + } + +-u64 nfsd4_change_attribute(const struct kstat *stat, +- const struct inode *inode); ++u64 nfsd4_change_attribute(const struct kstat *stat); + __be32 __must_check fh_fill_pre_attrs(struct svc_fh *fhp); + __be32 fh_fill_post_attrs(struct svc_fh *fhp); + __be32 __must_check fh_fill_both_attrs(struct svc_fh *fhp); +-- +2.43.0 + diff --git a/queue-6.12/nfsd-fix-nfsd4_shutdown_copy.patch b/queue-6.12/nfsd-fix-nfsd4_shutdown_copy.patch new file mode 100644 index 00000000000..ed88d4b1339 --- /dev/null +++ b/queue-6.12/nfsd-fix-nfsd4_shutdown_copy.patch @@ -0,0 +1,73 @@ +From c40c1b02a43fbefacc48aa49a569ada770fb335d Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Thu, 31 Oct 2024 09:40:03 -0400 +Subject: NFSD: Fix nfsd4_shutdown_copy() + +From: Chuck Lever <chuck.lever@oracle.com> + +[ Upstream commit 62a8642ba00aa8ceb0a02ade942f5ec52e877c95 ] + +nfsd4_shutdown_copy() is just this: + + while ((copy = nfsd4_get_copy(clp)) != NULL) + nfsd4_stop_copy(copy); + +nfsd4_get_copy() bumps @copy's reference count, preventing +nfsd4_stop_copy() from releasing @copy. + +A while loop like this usually works by removing the first element +of the list, but neither nfsd4_get_copy() nor nfsd4_stop_copy() +alters the async_copies list. + +Best I can tell, then, is that nfsd4_shutdown_copy() continues to +loop until other threads manage to remove all the items from this +list. The spinning loop blocks shutdown until these items are gone. + +Possibly the reason we haven't seen this issue in the field is +because client_has_state() prevents __destroy_client() from calling +nfsd4_shutdown_copy() if there are any items on this list. In a +subsequent patch I plan to remove that restriction. + +Fixes: e0639dc5805a ("NFSD introduce async copy feature") +Reviewed-by: Jeff Layton <jlayton@kernel.org> +Signed-off-by: Chuck Lever <chuck.lever@oracle.com> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + fs/nfsd/nfs4proc.c | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c +index d32f2dfd148fe..7a1fdafa42ea1 100644 +--- a/fs/nfsd/nfs4proc.c ++++ b/fs/nfsd/nfs4proc.c +@@ -1292,7 +1292,7 @@ static void nfsd4_stop_copy(struct nfsd4_copy *copy) + nfs4_put_copy(copy); + } + +-static struct nfsd4_copy *nfsd4_get_copy(struct nfs4_client *clp) ++static struct nfsd4_copy *nfsd4_unhash_copy(struct nfs4_client *clp) + { + struct nfsd4_copy *copy = NULL; + +@@ -1301,6 +1301,9 @@ static struct nfsd4_copy *nfsd4_get_copy(struct nfs4_client *clp) + copy = list_first_entry(&clp->async_copies, struct nfsd4_copy, + copies); + refcount_inc(©->refcount); ++ copy->cp_clp = NULL; ++ if (!list_empty(©->copies)) ++ list_del_init(©->copies); + } + spin_unlock(&clp->async_lock); + return copy; +@@ -1310,7 +1313,7 @@ void nfsd4_shutdown_copy(struct nfs4_client *clp) + { + struct nfsd4_copy *copy; + +- while ((copy = nfsd4_get_copy(clp)) != NULL) ++ while ((copy = nfsd4_unhash_copy(clp)) != NULL) + nfsd4_stop_copy(copy); + } + #ifdef CONFIG_NFSD_V4_2_INTER_SSC +-- +2.43.0 + diff --git a/queue-6.12/nfsd-prevent-null-dereference-in-nfsd4_process_cb_up.patch b/queue-6.12/nfsd-prevent-null-dereference-in-nfsd4_process_cb_up.patch new file mode 100644 index 00000000000..d0c5b0617b6 --- /dev/null +++ b/queue-6.12/nfsd-prevent-null-dereference-in-nfsd4_process_cb_up.patch @@ -0,0 +1,37 @@ +From d2150c848fa119e46b9bc6e9b7a45a5b2f99f875 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Thu, 17 Oct 2024 11:03:53 -0400 +Subject: NFSD: Prevent NULL dereference in nfsd4_process_cb_update() + +From: Chuck Lever <chuck.lever@oracle.com> + +[ Upstream commit 1e02c641c3a43c88cecc08402000418e15578d38 ] + +@ses is initialized to NULL. If __nfsd4_find_backchannel() finds no +available backchannel session, setup_callback_client() will try to +dereference @ses and segfault. + +Fixes: dcbeaa68dbbd ("nfsd4: allow backchannel recovery") +Reviewed-by: Jeff Layton <jlayton@kernel.org> +Signed-off-by: Chuck Lever <chuck.lever@oracle.com> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + fs/nfsd/nfs4callback.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c +index b5b3ab9d719a7..72764f73cf19a 100644 +--- a/fs/nfsd/nfs4callback.c ++++ b/fs/nfsd/nfs4callback.c +@@ -1461,6 +1461,8 @@ static void nfsd4_process_cb_update(struct nfsd4_callback *cb) + ses = c->cn_session; + } + spin_unlock(&clp->cl_lock); ++ if (!c) ++ return; + + err = setup_callback_client(clp, &conn, ses); + if (err) { +-- +2.43.0 + diff --git a/queue-6.12/nfsd-release-svc_expkey-svc_export-with-rcu_work.patch b/queue-6.12/nfsd-release-svc_expkey-svc_export-with-rcu_work.patch new file mode 100644 index 00000000000..8c4a4e422f6 --- /dev/null +++ b/queue-6.12/nfsd-release-svc_expkey-svc_export-with-rcu_work.patch @@ -0,0 +1,199 @@ +From 74ca29e7ea233db06cfc8c883d1b8119f5c3525d Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Mon, 21 Oct 2024 22:23:43 +0800 +Subject: nfsd: release svc_expkey/svc_export with rcu_work + +From: Yang Erkun <yangerkun@huawei.com> + +[ Upstream commit f8c989a0c89a75d30f899a7cabdc14d72522bb8d ] + +The last reference for `cache_head` can be reduced to zero in `c_show` +and `e_show`(using `rcu_read_lock` and `rcu_read_unlock`). Consequently, +`svc_export_put` and `expkey_put` will be invoked, leading to two +issues: + +1. The `svc_export_put` will directly free ex_uuid. However, + `e_show`/`c_show` will access `ex_uuid` after `cache_put`, which can + trigger a use-after-free issue, shown below. + + ================================================================== + BUG: KASAN: slab-use-after-free in svc_export_show+0x362/0x430 [nfsd] + Read of size 1 at addr ff11000010fdc120 by task cat/870 + + CPU: 1 UID: 0 PID: 870 Comm: cat Not tainted 6.12.0-rc3+ #1 + Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS + 1.16.1-2.fc37 04/01/2014 + Call Trace: + <TASK> + dump_stack_lvl+0x53/0x70 + print_address_description.constprop.0+0x2c/0x3a0 + print_report+0xb9/0x280 + kasan_report+0xae/0xe0 + svc_export_show+0x362/0x430 [nfsd] + c_show+0x161/0x390 [sunrpc] + seq_read_iter+0x589/0x770 + seq_read+0x1e5/0x270 + proc_reg_read+0xe1/0x140 + vfs_read+0x125/0x530 + ksys_read+0xc1/0x160 + do_syscall_64+0x5f/0x170 + entry_SYSCALL_64_after_hwframe+0x76/0x7e + + Allocated by task 830: + kasan_save_stack+0x20/0x40 + kasan_save_track+0x14/0x30 + __kasan_kmalloc+0x8f/0xa0 + __kmalloc_node_track_caller_noprof+0x1bc/0x400 + kmemdup_noprof+0x22/0x50 + svc_export_parse+0x8a9/0xb80 [nfsd] + cache_do_downcall+0x71/0xa0 [sunrpc] + cache_write_procfs+0x8e/0xd0 [sunrpc] + proc_reg_write+0xe1/0x140 + vfs_write+0x1a5/0x6d0 + ksys_write+0xc1/0x160 + do_syscall_64+0x5f/0x170 + entry_SYSCALL_64_after_hwframe+0x76/0x7e + + Freed by task 868: + kasan_save_stack+0x20/0x40 + kasan_save_track+0x14/0x30 + kasan_save_free_info+0x3b/0x60 + __kasan_slab_free+0x37/0x50 + kfree+0xf3/0x3e0 + svc_export_put+0x87/0xb0 [nfsd] + cache_purge+0x17f/0x1f0 [sunrpc] + nfsd_destroy_serv+0x226/0x2d0 [nfsd] + nfsd_svc+0x125/0x1e0 [nfsd] + write_threads+0x16a/0x2a0 [nfsd] + nfsctl_transaction_write+0x74/0xa0 [nfsd] + vfs_write+0x1a5/0x6d0 + ksys_write+0xc1/0x160 + do_syscall_64+0x5f/0x170 + entry_SYSCALL_64_after_hwframe+0x76/0x7e + +2. We cannot sleep while using `rcu_read_lock`/`rcu_read_unlock`. + However, `svc_export_put`/`expkey_put` will call path_put, which + subsequently triggers a sleeping operation due to the following + `dput`. + + ============================= + WARNING: suspicious RCU usage + 5.10.0-dirty #141 Not tainted + ----------------------------- + ... + Call Trace: + dump_stack+0x9a/0xd0 + ___might_sleep+0x231/0x240 + dput+0x39/0x600 + path_put+0x1b/0x30 + svc_export_put+0x17/0x80 + e_show+0x1c9/0x200 + seq_read_iter+0x63f/0x7c0 + seq_read+0x226/0x2d0 + vfs_read+0x113/0x2c0 + ksys_read+0xc9/0x170 + do_syscall_64+0x33/0x40 + entry_SYSCALL_64_after_hwframe+0x67/0xd1 + +Fix these issues by using `rcu_work` to help release +`svc_expkey`/`svc_export`. This approach allows for an asynchronous +context to invoke `path_put` and also facilitates the freeing of +`uuid/exp/key` after an RCU grace period. + +Fixes: 9ceddd9da134 ("knfsd: Allow lockless lookups of the exports") +Signed-off-by: Yang Erkun <yangerkun@huawei.com> +Reviewed-by: Jeff Layton <jlayton@kernel.org> +Signed-off-by: Chuck Lever <chuck.lever@oracle.com> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + fs/nfsd/export.c | 31 +++++++++++++++++++++++++------ + fs/nfsd/export.h | 4 ++-- + 2 files changed, 27 insertions(+), 8 deletions(-) + +diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c +index c82d8e3e0d4f2..984f8e6379dd4 100644 +--- a/fs/nfsd/export.c ++++ b/fs/nfsd/export.c +@@ -40,15 +40,24 @@ + #define EXPKEY_HASHMAX (1 << EXPKEY_HASHBITS) + #define EXPKEY_HASHMASK (EXPKEY_HASHMAX -1) + +-static void expkey_put(struct kref *ref) ++static void expkey_put_work(struct work_struct *work) + { +- struct svc_expkey *key = container_of(ref, struct svc_expkey, h.ref); ++ struct svc_expkey *key = ++ container_of(to_rcu_work(work), struct svc_expkey, ek_rcu_work); + + if (test_bit(CACHE_VALID, &key->h.flags) && + !test_bit(CACHE_NEGATIVE, &key->h.flags)) + path_put(&key->ek_path); + auth_domain_put(key->ek_client); +- kfree_rcu(key, ek_rcu); ++ kfree(key); ++} ++ ++static void expkey_put(struct kref *ref) ++{ ++ struct svc_expkey *key = container_of(ref, struct svc_expkey, h.ref); ++ ++ INIT_RCU_WORK(&key->ek_rcu_work, expkey_put_work); ++ queue_rcu_work(system_wq, &key->ek_rcu_work); + } + + static int expkey_upcall(struct cache_detail *cd, struct cache_head *h) +@@ -355,16 +364,26 @@ static void export_stats_destroy(struct export_stats *stats) + EXP_STATS_COUNTERS_NUM); + } + +-static void svc_export_put(struct kref *ref) ++static void svc_export_put_work(struct work_struct *work) + { +- struct svc_export *exp = container_of(ref, struct svc_export, h.ref); ++ struct svc_export *exp = ++ container_of(to_rcu_work(work), struct svc_export, ex_rcu_work); ++ + path_put(&exp->ex_path); + auth_domain_put(exp->ex_client); + nfsd4_fslocs_free(&exp->ex_fslocs); + export_stats_destroy(exp->ex_stats); + kfree(exp->ex_stats); + kfree(exp->ex_uuid); +- kfree_rcu(exp, ex_rcu); ++ kfree(exp); ++} ++ ++static void svc_export_put(struct kref *ref) ++{ ++ struct svc_export *exp = container_of(ref, struct svc_export, h.ref); ++ ++ INIT_RCU_WORK(&exp->ex_rcu_work, svc_export_put_work); ++ queue_rcu_work(system_wq, &exp->ex_rcu_work); + } + + static int svc_export_upcall(struct cache_detail *cd, struct cache_head *h) +diff --git a/fs/nfsd/export.h b/fs/nfsd/export.h +index 3794ae253a701..081afb68681e1 100644 +--- a/fs/nfsd/export.h ++++ b/fs/nfsd/export.h +@@ -75,7 +75,7 @@ struct svc_export { + u32 ex_layout_types; + struct nfsd4_deviceid_map *ex_devid_map; + struct cache_detail *cd; +- struct rcu_head ex_rcu; ++ struct rcu_work ex_rcu_work; + unsigned long ex_xprtsec_modes; + struct export_stats *ex_stats; + }; +@@ -92,7 +92,7 @@ struct svc_expkey { + u32 ek_fsid[6]; + + struct path ek_path; +- struct rcu_head ek_rcu; ++ struct rcu_work ek_rcu_work; + }; + + #define EX_ISSYNC(exp) (!((exp)->ex_flags & NFSEXP_ASYNC)) +-- +2.43.0 + diff --git a/queue-6.12/nvme-pci-fix-freeing-of-the-hmb-descriptor-table.patch b/queue-6.12/nvme-pci-fix-freeing-of-the-hmb-descriptor-table.patch new file mode 100644 index 00000000000..28c7e9849af --- /dev/null +++ b/queue-6.12/nvme-pci-fix-freeing-of-the-hmb-descriptor-table.patch @@ -0,0 +1,94 @@ +From 636e4a13b59bb7f54232ced7198b3241690b7b27 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Fri, 1 Nov 2024 05:40:04 +0100 +Subject: nvme-pci: fix freeing of the HMB descriptor table + +From: Christoph Hellwig <hch@lst.de> + +[ Upstream commit 3c2fb1ca8086eb139b2a551358137525ae8e0d7a ] + +The HMB descriptor table is sized to the maximum number of descriptors +that could be used for a given device, but __nvme_alloc_host_mem could +break out of the loop earlier on memory allocation failure and end up +using less descriptors than planned for, which leads to an incorrect +size passed to dma_free_coherent. + +In practice this was not showing up because the number of descriptors +tends to be low and the dma coherent allocator always allocates and +frees at least a page. + +Fixes: 87ad72a59a38 ("nvme-pci: implement host memory buffer support") +Signed-off-by: Christoph Hellwig <hch@lst.de> +Signed-off-by: Keith Busch <kbusch@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/nvme/host/pci.c | 16 +++++++++------- + 1 file changed, 9 insertions(+), 7 deletions(-) + +diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c +index 4b9fda0b1d9a3..34daf6d8db07b 100644 +--- a/drivers/nvme/host/pci.c ++++ b/drivers/nvme/host/pci.c +@@ -153,6 +153,7 @@ struct nvme_dev { + /* host memory buffer support: */ + u64 host_mem_size; + u32 nr_host_mem_descs; ++ u32 host_mem_descs_size; + dma_addr_t host_mem_descs_dma; + struct nvme_host_mem_buf_desc *host_mem_descs; + void **host_mem_desc_bufs; +@@ -1966,10 +1967,10 @@ static void nvme_free_host_mem(struct nvme_dev *dev) + + kfree(dev->host_mem_desc_bufs); + dev->host_mem_desc_bufs = NULL; +- dma_free_coherent(dev->dev, +- dev->nr_host_mem_descs * sizeof(*dev->host_mem_descs), ++ dma_free_coherent(dev->dev, dev->host_mem_descs_size, + dev->host_mem_descs, dev->host_mem_descs_dma); + dev->host_mem_descs = NULL; ++ dev->host_mem_descs_size = 0; + dev->nr_host_mem_descs = 0; + } + +@@ -1977,7 +1978,7 @@ static int __nvme_alloc_host_mem(struct nvme_dev *dev, u64 preferred, + u32 chunk_size) + { + struct nvme_host_mem_buf_desc *descs; +- u32 max_entries, len; ++ u32 max_entries, len, descs_size; + dma_addr_t descs_dma; + int i = 0; + void **bufs; +@@ -1990,8 +1991,9 @@ static int __nvme_alloc_host_mem(struct nvme_dev *dev, u64 preferred, + if (dev->ctrl.hmmaxd && dev->ctrl.hmmaxd < max_entries) + max_entries = dev->ctrl.hmmaxd; + +- descs = dma_alloc_coherent(dev->dev, max_entries * sizeof(*descs), +- &descs_dma, GFP_KERNEL); ++ descs_size = max_entries * sizeof(*descs); ++ descs = dma_alloc_coherent(dev->dev, descs_size, &descs_dma, ++ GFP_KERNEL); + if (!descs) + goto out; + +@@ -2020,6 +2022,7 @@ static int __nvme_alloc_host_mem(struct nvme_dev *dev, u64 preferred, + dev->host_mem_size = size; + dev->host_mem_descs = descs; + dev->host_mem_descs_dma = descs_dma; ++ dev->host_mem_descs_size = descs_size; + dev->host_mem_desc_bufs = bufs; + return 0; + +@@ -2034,8 +2037,7 @@ static int __nvme_alloc_host_mem(struct nvme_dev *dev, u64 preferred, + + kfree(bufs); + out_free_descs: +- dma_free_coherent(dev->dev, max_entries * sizeof(*descs), descs, +- descs_dma); ++ dma_free_coherent(dev->dev, descs_size, descs, descs_dma); + out: + dev->host_mem_descs = NULL; + return -ENOMEM; +-- +2.43.0 + diff --git a/queue-6.12/nvme-pci-reverse-request-order-in-nvme_queue_rqs.patch b/queue-6.12/nvme-pci-reverse-request-order-in-nvme_queue_rqs.patch new file mode 100644 index 00000000000..31ee9494e2b --- /dev/null +++ b/queue-6.12/nvme-pci-reverse-request-order-in-nvme_queue_rqs.patch @@ -0,0 +1,93 @@ +From b7ae688d3edb29d93f0e26afdb117d5c23450161 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Wed, 13 Nov 2024 16:20:41 +0100 +Subject: nvme-pci: reverse request order in nvme_queue_rqs + +From: Christoph Hellwig <hch@lst.de> + +[ Upstream commit beadf0088501d9dcf2454b05d90d5d31ea3ba55f ] + +blk_mq_flush_plug_list submits requests in the reverse order that they +were submitted, which leads to a rather suboptimal I/O pattern especially +in rotational devices. Fix this by rewriting nvme_queue_rqs so that it +always pops the requests from the passed in request list, and then adds +them to the head of a local submit list. This actually simplifies the +code a bit as it removes the complicated list splicing, at the cost of +extra updates of the rq_next pointer. As that should be cache hot +anyway it should be an easy price to pay. + +Fixes: d62cbcf62f2f ("nvme: add support for mq_ops->queue_rqs()") +Signed-off-by: Christoph Hellwig <hch@lst.de> +Link: https://lore.kernel.org/r/20241113152050.157179-2-hch@lst.de +Signed-off-by: Jens Axboe <axboe@kernel.dk> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/nvme/host/pci.c | 39 +++++++++++++++++---------------------- + 1 file changed, 17 insertions(+), 22 deletions(-) + +diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c +index 34daf6d8db07b..55af3dfbc2607 100644 +--- a/drivers/nvme/host/pci.c ++++ b/drivers/nvme/host/pci.c +@@ -905,9 +905,10 @@ static blk_status_t nvme_queue_rq(struct blk_mq_hw_ctx *hctx, + + static void nvme_submit_cmds(struct nvme_queue *nvmeq, struct request **rqlist) + { ++ struct request *req; ++ + spin_lock(&nvmeq->sq_lock); +- while (!rq_list_empty(*rqlist)) { +- struct request *req = rq_list_pop(rqlist); ++ while ((req = rq_list_pop(rqlist))) { + struct nvme_iod *iod = blk_mq_rq_to_pdu(req); + + nvme_sq_copy_cmd(nvmeq, &iod->cmd); +@@ -932,31 +933,25 @@ static bool nvme_prep_rq_batch(struct nvme_queue *nvmeq, struct request *req) + + static void nvme_queue_rqs(struct request **rqlist) + { +- struct request *req, *next, *prev = NULL; ++ struct request *submit_list = NULL; + struct request *requeue_list = NULL; ++ struct request **requeue_lastp = &requeue_list; ++ struct nvme_queue *nvmeq = NULL; ++ struct request *req; + +- rq_list_for_each_safe(rqlist, req, next) { +- struct nvme_queue *nvmeq = req->mq_hctx->driver_data; +- +- if (!nvme_prep_rq_batch(nvmeq, req)) { +- /* detach 'req' and add to remainder list */ +- rq_list_move(rqlist, &requeue_list, req, prev); +- +- req = prev; +- if (!req) +- continue; +- } ++ while ((req = rq_list_pop(rqlist))) { ++ if (nvmeq && nvmeq != req->mq_hctx->driver_data) ++ nvme_submit_cmds(nvmeq, &submit_list); ++ nvmeq = req->mq_hctx->driver_data; + +- if (!next || req->mq_hctx != next->mq_hctx) { +- /* detach rest of list, and submit */ +- req->rq_next = NULL; +- nvme_submit_cmds(nvmeq, rqlist); +- *rqlist = next; +- prev = NULL; +- } else +- prev = req; ++ if (nvme_prep_rq_batch(nvmeq, req)) ++ rq_list_add(&submit_list, req); /* reverse order */ ++ else ++ rq_list_add_tail(&requeue_lastp, req); + } + ++ if (nvmeq) ++ nvme_submit_cmds(nvmeq, &submit_list); + *rqlist = requeue_list; + } + +-- +2.43.0 + diff --git a/queue-6.12/ocfs2-fix-uninitialized-value-in-ocfs2_file_read_ite.patch b/queue-6.12/ocfs2-fix-uninitialized-value-in-ocfs2_file_read_ite.patch new file mode 100644 index 00000000000..2e11a02ca48 --- /dev/null +++ b/queue-6.12/ocfs2-fix-uninitialized-value-in-ocfs2_file_read_ite.patch @@ -0,0 +1,98 @@ +From 8ade3deb7c86ee6661c67bdbb373d873c216a1b6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Tue, 29 Oct 2024 12:17:36 +0300 +Subject: ocfs2: fix uninitialized value in ocfs2_file_read_iter() + +From: Dmitry Antipov <dmantipov@yandex.ru> + +[ Upstream commit adc77b19f62d7e80f98400b2fca9d700d2afdd6f ] + +Syzbot has reported the following KMSAN splat: + +BUG: KMSAN: uninit-value in ocfs2_file_read_iter+0x9a4/0xf80 + ocfs2_file_read_iter+0x9a4/0xf80 + __io_read+0x8d4/0x20f0 + io_read+0x3e/0xf0 + io_issue_sqe+0x42b/0x22c0 + io_wq_submit_work+0xaf9/0xdc0 + io_worker_handle_work+0xd13/0x2110 + io_wq_worker+0x447/0x1410 + ret_from_fork+0x6f/0x90 + ret_from_fork_asm+0x1a/0x30 + +Uninit was created at: + __alloc_pages_noprof+0x9a7/0xe00 + alloc_pages_mpol_noprof+0x299/0x990 + alloc_pages_noprof+0x1bf/0x1e0 + allocate_slab+0x33a/0x1250 + ___slab_alloc+0x12ef/0x35e0 + kmem_cache_alloc_bulk_noprof+0x486/0x1330 + __io_alloc_req_refill+0x84/0x560 + io_submit_sqes+0x172f/0x2f30 + __se_sys_io_uring_enter+0x406/0x41c0 + __x64_sys_io_uring_enter+0x11f/0x1a0 + x64_sys_call+0x2b54/0x3ba0 + do_syscall_64+0xcd/0x1e0 + entry_SYSCALL_64_after_hwframe+0x77/0x7f + +Since an instance of 'struct kiocb' may be passed from the block layer +with 'private' field uninitialized, introduce 'ocfs2_iocb_init_rw_locked()' +and use it from where 'ocfs2_dio_end_io()' might take care, i.e. in +'ocfs2_file_read_iter()' and 'ocfs2_file_write_iter()'. + +Link: https://lkml.kernel.org/r/20241029091736.1501946-1-dmantipov@yandex.ru +Fixes: 7cdfc3a1c397 ("ocfs2: Remember rw lock level during direct io") +Signed-off-by: Dmitry Antipov <dmantipov@yandex.ru> +Reported-by: syzbot+a73e253cca4f0230a5a5@syzkaller.appspotmail.com +Closes: https://syzkaller.appspot.com/bug?extid=a73e253cca4f0230a5a5 +Cc: Mark Fasheh <mark@fasheh.com> +Cc: Joel Becker <jlbec@evilplan.org> +Cc: Junxiao Bi <junxiao.bi@oracle.com> +Cc: Joseph Qi <jiangqi903@gmail.com> +Cc: Changwei Ge <gechangwei@live.cn> +Cc: Jun Piao <piaojun@huawei.com> +Signed-off-by: Andrew Morton <akpm@linux-foundation.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + fs/ocfs2/aops.h | 2 ++ + fs/ocfs2/file.c | 4 ++++ + 2 files changed, 6 insertions(+) + +diff --git a/fs/ocfs2/aops.h b/fs/ocfs2/aops.h +index 45db1781ea735..1d1b4b7edba02 100644 +--- a/fs/ocfs2/aops.h ++++ b/fs/ocfs2/aops.h +@@ -70,6 +70,8 @@ enum ocfs2_iocb_lock_bits { + OCFS2_IOCB_NUM_LOCKS + }; + ++#define ocfs2_iocb_init_rw_locked(iocb) \ ++ (iocb->private = NULL) + #define ocfs2_iocb_clear_rw_locked(iocb) \ + clear_bit(OCFS2_IOCB_RW_LOCK, (unsigned long *)&iocb->private) + #define ocfs2_iocb_rw_locked_level(iocb) \ +diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c +index 06af21982c16a..cb09330a08611 100644 +--- a/fs/ocfs2/file.c ++++ b/fs/ocfs2/file.c +@@ -2398,6 +2398,8 @@ static ssize_t ocfs2_file_write_iter(struct kiocb *iocb, + } else + inode_lock(inode); + ++ ocfs2_iocb_init_rw_locked(iocb); ++ + /* + * Concurrent O_DIRECT writes are allowed with + * mount_option "coherency=buffered". +@@ -2544,6 +2546,8 @@ static ssize_t ocfs2_file_read_iter(struct kiocb *iocb, + if (!direct_io && nowait) + return -EOPNOTSUPP; + ++ ocfs2_iocb_init_rw_locked(iocb); ++ + /* + * buffered reads protect themselves in ->read_folio(). O_DIRECT reads + * need locks to protect pending reads from racing with truncate. +-- +2.43.0 + diff --git a/queue-6.12/octeontx2-af-quiesce-traffic-before-nix-block-reset.patch b/queue-6.12/octeontx2-af-quiesce-traffic-before-nix-block-reset.patch new file mode 100644 index 00000000000..241a48fd46f --- /dev/null +++ b/queue-6.12/octeontx2-af-quiesce-traffic-before-nix-block-reset.patch @@ -0,0 +1,337 @@ +From 91342aec08250badd5b219aed10e6d046debd430 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Fri, 22 Nov 2024 21:50:35 +0530 +Subject: octeontx2-af: Quiesce traffic before NIX block reset + +From: Hariprasad Kelam <hkelam@marvell.com> + +[ Upstream commit 762ca6eed026346d9d41ed5ac633083c4f1e5071 ] + +During initialization, the AF driver resets all blocks. The RPM (MAC) +block and NIX block operate on a credit-based model. When the NIX block +resets during active traffic flow, it doesn't release credits to the RPM +block. This causes the RPM FIFO to overflow, leading to receive traffic +struck. + +To address this issue, the patch introduces the following changes: +1. Stop receiving traffic at the MAC level during AF driver + initialization. +2. Perform an X2P reset (prevents RXFIFO of all LMACS from pushing data) +3. Reset the NIX block. +4. Clear the X2P reset and re-enable receiving traffic. + +Fixes: 54d557815e15 ("octeontx2-af: Reset all RVU blocks") +Signed-off-by: Hariprasad Kelam <hkelam@marvell.com> +Signed-off-by: Paolo Abeni <pabeni@redhat.com> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + .../net/ethernet/marvell/octeontx2/af/cgx.c | 61 +++++++++++++++++++ + .../net/ethernet/marvell/octeontx2/af/cgx.h | 4 ++ + .../marvell/octeontx2/af/lmac_common.h | 2 + + .../net/ethernet/marvell/octeontx2/af/rpm.c | 42 +++++++++++++ + .../net/ethernet/marvell/octeontx2/af/rpm.h | 4 ++ + .../net/ethernet/marvell/octeontx2/af/rvu.c | 1 + + .../net/ethernet/marvell/octeontx2/af/rvu.h | 1 + + .../ethernet/marvell/octeontx2/af/rvu_cgx.c | 36 +++++++++-- + 8 files changed, 145 insertions(+), 6 deletions(-) + +diff --git a/drivers/net/ethernet/marvell/octeontx2/af/cgx.c b/drivers/net/ethernet/marvell/octeontx2/af/cgx.c +index 2f621714c54e6..8216f843a7cd5 100644 +--- a/drivers/net/ethernet/marvell/octeontx2/af/cgx.c ++++ b/drivers/net/ethernet/marvell/octeontx2/af/cgx.c +@@ -214,6 +214,24 @@ u8 cgx_lmac_get_p2x(int cgx_id, int lmac_id) + return (cfg & CMR_P2X_SEL_MASK) >> CMR_P2X_SEL_SHIFT; + } + ++static u8 cgx_get_nix_resetbit(struct cgx *cgx) ++{ ++ int first_lmac; ++ u8 p2x; ++ ++ /* non 98XX silicons supports only NIX0 block */ ++ if (cgx->pdev->subsystem_device != PCI_SUBSYS_DEVID_98XX) ++ return CGX_NIX0_RESET; ++ ++ first_lmac = find_first_bit(&cgx->lmac_bmap, cgx->max_lmac_per_mac); ++ p2x = cgx_lmac_get_p2x(cgx->cgx_id, first_lmac); ++ ++ if (p2x == CMR_P2X_SEL_NIX1) ++ return CGX_NIX1_RESET; ++ else ++ return CGX_NIX0_RESET; ++} ++ + /* Ensure the required lock for event queue(where asynchronous events are + * posted) is acquired before calling this API. Else an asynchronous event(with + * latest link status) can reach the destination before this function returns +@@ -1724,6 +1742,8 @@ static int cgx_lmac_init(struct cgx *cgx) + lmac->lmac_type = cgx->mac_ops->get_lmac_type(cgx, lmac->lmac_id); + } + ++ /* Start X2P reset on given MAC block */ ++ cgx->mac_ops->mac_x2p_reset(cgx, true); + return cgx_lmac_verify_fwi_version(cgx); + + err_bitmap_free: +@@ -1789,6 +1809,45 @@ static u8 cgx_get_rxid_mapoffset(struct cgx *cgx) + return 0x60; + } + ++static void cgx_x2p_reset(void *cgxd, bool enable) ++{ ++ struct cgx *cgx = cgxd; ++ int lmac_id; ++ u64 cfg; ++ ++ if (enable) { ++ for_each_set_bit(lmac_id, &cgx->lmac_bmap, cgx->max_lmac_per_mac) ++ cgx->mac_ops->mac_enadis_rx(cgx, lmac_id, false); ++ ++ usleep_range(1000, 2000); ++ ++ cfg = cgx_read(cgx, 0, CGXX_CMR_GLOBAL_CONFIG); ++ cfg |= cgx_get_nix_resetbit(cgx) | CGX_NSCI_DROP; ++ cgx_write(cgx, 0, CGXX_CMR_GLOBAL_CONFIG, cfg); ++ } else { ++ cfg = cgx_read(cgx, 0, CGXX_CMR_GLOBAL_CONFIG); ++ cfg &= ~(cgx_get_nix_resetbit(cgx) | CGX_NSCI_DROP); ++ cgx_write(cgx, 0, CGXX_CMR_GLOBAL_CONFIG, cfg); ++ } ++} ++ ++static int cgx_enadis_rx(void *cgxd, int lmac_id, bool enable) ++{ ++ struct cgx *cgx = cgxd; ++ u64 cfg; ++ ++ if (!is_lmac_valid(cgx, lmac_id)) ++ return -ENODEV; ++ ++ cfg = cgx_read(cgx, lmac_id, CGXX_CMRX_CFG); ++ if (enable) ++ cfg |= DATA_PKT_RX_EN; ++ else ++ cfg &= ~DATA_PKT_RX_EN; ++ cgx_write(cgx, lmac_id, CGXX_CMRX_CFG, cfg); ++ return 0; ++} ++ + static struct mac_ops cgx_mac_ops = { + .name = "cgx", + .csr_offset = 0, +@@ -1820,6 +1879,8 @@ static struct mac_ops cgx_mac_ops = { + .mac_get_pfc_frm_cfg = cgx_lmac_get_pfc_frm_cfg, + .mac_reset = cgx_lmac_reset, + .mac_stats_reset = cgx_stats_reset, ++ .mac_x2p_reset = cgx_x2p_reset, ++ .mac_enadis_rx = cgx_enadis_rx, + }; + + static int cgx_probe(struct pci_dev *pdev, const struct pci_device_id *id) +diff --git a/drivers/net/ethernet/marvell/octeontx2/af/cgx.h b/drivers/net/ethernet/marvell/octeontx2/af/cgx.h +index f9cd4b58f0c02..1cf12e5c7da87 100644 +--- a/drivers/net/ethernet/marvell/octeontx2/af/cgx.h ++++ b/drivers/net/ethernet/marvell/octeontx2/af/cgx.h +@@ -32,6 +32,10 @@ + #define CGX_LMAC_TYPE_MASK 0xF + #define CGXX_CMRX_INT 0x040 + #define FW_CGX_INT BIT_ULL(1) ++#define CGXX_CMR_GLOBAL_CONFIG 0x08 ++#define CGX_NIX0_RESET BIT_ULL(2) ++#define CGX_NIX1_RESET BIT_ULL(3) ++#define CGX_NSCI_DROP BIT_ULL(9) + #define CGXX_CMRX_INT_ENA_W1S 0x058 + #define CGXX_CMRX_RX_ID_MAP 0x060 + #define CGXX_CMRX_RX_STAT0 0x070 +diff --git a/drivers/net/ethernet/marvell/octeontx2/af/lmac_common.h b/drivers/net/ethernet/marvell/octeontx2/af/lmac_common.h +index c43ff68ef1408..6180e68e1765a 100644 +--- a/drivers/net/ethernet/marvell/octeontx2/af/lmac_common.h ++++ b/drivers/net/ethernet/marvell/octeontx2/af/lmac_common.h +@@ -132,6 +132,8 @@ struct mac_ops { + int (*get_fec_stats)(void *cgxd, int lmac_id, + struct cgx_fec_stats_rsp *rsp); + int (*mac_stats_reset)(void *cgxd, int lmac_id); ++ void (*mac_x2p_reset)(void *cgxd, bool enable); ++ int (*mac_enadis_rx)(void *cgxd, int lmac_id, bool enable); + }; + + struct cgx { +diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rpm.c b/drivers/net/ethernet/marvell/octeontx2/af/rpm.c +index e97fcc51d7f24..2e9945446199e 100644 +--- a/drivers/net/ethernet/marvell/octeontx2/af/rpm.c ++++ b/drivers/net/ethernet/marvell/octeontx2/af/rpm.c +@@ -39,6 +39,8 @@ static struct mac_ops rpm_mac_ops = { + .mac_get_pfc_frm_cfg = rpm_lmac_get_pfc_frm_cfg, + .mac_reset = rpm_lmac_reset, + .mac_stats_reset = rpm_stats_reset, ++ .mac_x2p_reset = rpm_x2p_reset, ++ .mac_enadis_rx = rpm_enadis_rx, + }; + + static struct mac_ops rpm2_mac_ops = { +@@ -72,6 +74,8 @@ static struct mac_ops rpm2_mac_ops = { + .mac_get_pfc_frm_cfg = rpm_lmac_get_pfc_frm_cfg, + .mac_reset = rpm_lmac_reset, + .mac_stats_reset = rpm_stats_reset, ++ .mac_x2p_reset = rpm_x2p_reset, ++ .mac_enadis_rx = rpm_enadis_rx, + }; + + bool is_dev_rpm2(void *rpmd) +@@ -768,3 +772,41 @@ int rpm_lmac_reset(void *rpmd, int lmac_id, u8 pf_req_flr) + + return 0; + } ++ ++void rpm_x2p_reset(void *rpmd, bool enable) ++{ ++ rpm_t *rpm = rpmd; ++ int lmac_id; ++ u64 cfg; ++ ++ if (enable) { ++ for_each_set_bit(lmac_id, &rpm->lmac_bmap, rpm->max_lmac_per_mac) ++ rpm->mac_ops->mac_enadis_rx(rpm, lmac_id, false); ++ ++ usleep_range(1000, 2000); ++ ++ cfg = rpm_read(rpm, 0, RPMX_CMR_GLOBAL_CFG); ++ rpm_write(rpm, 0, RPMX_CMR_GLOBAL_CFG, cfg | RPM_NIX0_RESET); ++ } else { ++ cfg = rpm_read(rpm, 0, RPMX_CMR_GLOBAL_CFG); ++ cfg &= ~RPM_NIX0_RESET; ++ rpm_write(rpm, 0, RPMX_CMR_GLOBAL_CFG, cfg); ++ } ++} ++ ++int rpm_enadis_rx(void *rpmd, int lmac_id, bool enable) ++{ ++ rpm_t *rpm = rpmd; ++ u64 cfg; ++ ++ if (!is_lmac_valid(rpm, lmac_id)) ++ return -ENODEV; ++ ++ cfg = rpm_read(rpm, lmac_id, RPMX_MTI_MAC100X_COMMAND_CONFIG); ++ if (enable) ++ cfg |= RPM_RX_EN; ++ else ++ cfg &= ~RPM_RX_EN; ++ rpm_write(rpm, lmac_id, RPMX_MTI_MAC100X_COMMAND_CONFIG, cfg); ++ return 0; ++} +diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rpm.h b/drivers/net/ethernet/marvell/octeontx2/af/rpm.h +index 5194fec4c3b8e..b8d3972e096ae 100644 +--- a/drivers/net/ethernet/marvell/octeontx2/af/rpm.h ++++ b/drivers/net/ethernet/marvell/octeontx2/af/rpm.h +@@ -17,6 +17,8 @@ + + /* Registers */ + #define RPMX_CMRX_CFG 0x00 ++#define RPMX_CMR_GLOBAL_CFG 0x08 ++#define RPM_NIX0_RESET BIT_ULL(3) + #define RPMX_RX_TS_PREPEND BIT_ULL(22) + #define RPMX_TX_PTP_1S_SUPPORT BIT_ULL(17) + #define RPMX_CMRX_RX_ID_MAP 0x80 +@@ -139,4 +141,6 @@ bool is_dev_rpm2(void *rpmd); + int rpm_get_fec_stats(void *cgxd, int lmac_id, struct cgx_fec_stats_rsp *rsp); + int rpm_lmac_reset(void *rpmd, int lmac_id, u8 pf_req_flr); + int rpm_stats_reset(void *rpmd, int lmac_id); ++void rpm_x2p_reset(void *rpmd, bool enable); ++int rpm_enadis_rx(void *rpmd, int lmac_id, bool enable); + #endif /* RPM_H */ +diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu.c +index 1a97fb9032fa4..cd0d7b7774f1a 100644 +--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu.c ++++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu.c +@@ -1162,6 +1162,7 @@ static int rvu_setup_hw_resources(struct rvu *rvu) + } + + rvu_program_channels(rvu); ++ cgx_start_linkup(rvu); + + err = rvu_mcs_init(rvu); + if (err) { +diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu.h b/drivers/net/ethernet/marvell/octeontx2/af/rvu.h +index 5016ba82e1423..8555edbb1c8f9 100644 +--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu.h ++++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu.h +@@ -997,6 +997,7 @@ int rvu_cgx_prio_flow_ctrl_cfg(struct rvu *rvu, u16 pcifunc, u8 tx_pause, u8 rx_ + int rvu_cgx_cfg_pause_frm(struct rvu *rvu, u16 pcifunc, u8 tx_pause, u8 rx_pause); + void rvu_mac_reset(struct rvu *rvu, u16 pcifunc); + u32 rvu_cgx_get_lmac_fifolen(struct rvu *rvu, int cgx, int lmac); ++void cgx_start_linkup(struct rvu *rvu); + int npc_get_nixlf_mcam_index(struct npc_mcam *mcam, u16 pcifunc, int nixlf, + int type); + bool is_mcam_entry_enabled(struct rvu *rvu, struct npc_mcam *mcam, int blkaddr, +diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_cgx.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_cgx.c +index 4dcd7bfcad4e4..992fa0b82e8d2 100644 +--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_cgx.c ++++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_cgx.c +@@ -349,6 +349,7 @@ static void rvu_cgx_wq_destroy(struct rvu *rvu) + + int rvu_cgx_init(struct rvu *rvu) + { ++ struct mac_ops *mac_ops; + int cgx, err; + void *cgxd; + +@@ -375,6 +376,15 @@ int rvu_cgx_init(struct rvu *rvu) + if (err) + return err; + ++ /* Clear X2P reset on all MAC blocks */ ++ for (cgx = 0; cgx < rvu->cgx_cnt_max; cgx++) { ++ cgxd = rvu_cgx_pdata(cgx, rvu); ++ if (!cgxd) ++ continue; ++ mac_ops = get_mac_ops(cgxd); ++ mac_ops->mac_x2p_reset(cgxd, false); ++ } ++ + /* Register for CGX events */ + err = cgx_lmac_event_handler_init(rvu); + if (err) +@@ -382,10 +392,26 @@ int rvu_cgx_init(struct rvu *rvu) + + mutex_init(&rvu->cgx_cfg_lock); + +- /* Ensure event handler registration is completed, before +- * we turn on the links +- */ +- mb(); ++ return 0; ++} ++ ++void cgx_start_linkup(struct rvu *rvu) ++{ ++ unsigned long lmac_bmap; ++ struct mac_ops *mac_ops; ++ int cgx, lmac, err; ++ void *cgxd; ++ ++ /* Enable receive on all LMACS */ ++ for (cgx = 0; cgx <= rvu->cgx_cnt_max; cgx++) { ++ cgxd = rvu_cgx_pdata(cgx, rvu); ++ if (!cgxd) ++ continue; ++ mac_ops = get_mac_ops(cgxd); ++ lmac_bmap = cgx_get_lmac_bmap(cgxd); ++ for_each_set_bit(lmac, &lmac_bmap, rvu->hw->lmac_per_cgx) ++ mac_ops->mac_enadis_rx(cgxd, lmac, true); ++ } + + /* Do link up for all CGX ports */ + for (cgx = 0; cgx <= rvu->cgx_cnt_max; cgx++) { +@@ -398,8 +424,6 @@ int rvu_cgx_init(struct rvu *rvu) + "Link up process failed to start on cgx %d\n", + cgx); + } +- +- return 0; + } + + int rvu_cgx_exit(struct rvu *rvu) +-- +2.43.0 + diff --git a/queue-6.12/octeontx2-af-rpm-fix-low-network-performance.patch b/queue-6.12/octeontx2-af-rpm-fix-low-network-performance.patch new file mode 100644 index 00000000000..afa78d14a09 --- /dev/null +++ b/queue-6.12/octeontx2-af-rpm-fix-low-network-performance.patch @@ -0,0 +1,157 @@ +From d2cf71c109296bd8d44c7b7edaeebdf9de7396c1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Fri, 22 Nov 2024 21:50:32 +0530 +Subject: octeontx2-af: RPM: Fix low network performance + +From: Hariprasad Kelam <hkelam@marvell.com> + +[ Upstream commit d1e8884e050c1255a9ceb477f5ff926ee9214a23 ] + +Low network performance is observed even on RPMs with larger +FIFO lengths. + +The cn10kb silicon has three RPM blocks with the following +FIFO sizes: + + -------------------- + | RPM0 | 256KB | + | RPM1 | 256KB | + | RPM2 | 128KB | + -------------------- + +The current design stores the FIFO length in a common structure for all +RPMs (mac_ops). As a result, the FIFO length of the last RPM is applied +to all RPMs, leading to reduced network performance. + +This patch resolved the problem by storing the fifo length in per MAC +structure (cgx). + +Fixes: b9d0fedc6234 ("octeontx2-af: cn10kb: Add RPM_USX MAC support") +Signed-off-by: Hariprasad Kelam <hkelam@marvell.com> +Signed-off-by: Paolo Abeni <pabeni@redhat.com> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/net/ethernet/marvell/octeontx2/af/cgx.c | 9 +++++++-- + drivers/net/ethernet/marvell/octeontx2/af/cgx.h | 1 + + drivers/net/ethernet/marvell/octeontx2/af/lmac_common.h | 5 ++++- + drivers/net/ethernet/marvell/octeontx2/af/rpm.c | 6 +++--- + drivers/net/ethernet/marvell/octeontx2/af/rvu_cgx.c | 9 ++++----- + 5 files changed, 19 insertions(+), 11 deletions(-) + +diff --git a/drivers/net/ethernet/marvell/octeontx2/af/cgx.c b/drivers/net/ethernet/marvell/octeontx2/af/cgx.c +index 27935c54b91bc..2f621714c54e6 100644 +--- a/drivers/net/ethernet/marvell/octeontx2/af/cgx.c ++++ b/drivers/net/ethernet/marvell/octeontx2/af/cgx.c +@@ -112,6 +112,11 @@ struct mac_ops *get_mac_ops(void *cgxd) + return ((struct cgx *)cgxd)->mac_ops; + } + ++u32 cgx_get_fifo_len(void *cgxd) ++{ ++ return ((struct cgx *)cgxd)->fifo_len; ++} ++ + void cgx_write(struct cgx *cgx, u64 lmac, u64 offset, u64 val) + { + writeq(val, cgx->reg_base + (lmac << cgx->mac_ops->lmac_offset) + +@@ -501,7 +506,7 @@ static u32 cgx_get_lmac_fifo_len(void *cgxd, int lmac_id) + u8 num_lmacs; + u32 fifo_len; + +- fifo_len = cgx->mac_ops->fifo_len; ++ fifo_len = cgx->fifo_len; + num_lmacs = cgx->mac_ops->get_nr_lmacs(cgx); + + switch (num_lmacs) { +@@ -1764,7 +1769,7 @@ static void cgx_populate_features(struct cgx *cgx) + u64 cfg; + + cfg = cgx_read(cgx, 0, CGX_CONST); +- cgx->mac_ops->fifo_len = FIELD_GET(CGX_CONST_RXFIFO_SIZE, cfg); ++ cgx->fifo_len = FIELD_GET(CGX_CONST_RXFIFO_SIZE, cfg); + cgx->max_lmac_per_mac = FIELD_GET(CGX_CONST_MAX_LMACS, cfg); + + if (is_dev_rpm(cgx)) +diff --git a/drivers/net/ethernet/marvell/octeontx2/af/cgx.h b/drivers/net/ethernet/marvell/octeontx2/af/cgx.h +index dc9ace30554af..f9cd4b58f0c02 100644 +--- a/drivers/net/ethernet/marvell/octeontx2/af/cgx.h ++++ b/drivers/net/ethernet/marvell/octeontx2/af/cgx.h +@@ -185,4 +185,5 @@ int cgx_lmac_get_pfc_frm_cfg(void *cgxd, int lmac_id, u8 *tx_pause, + int verify_lmac_fc_cfg(void *cgxd, int lmac_id, u8 tx_pause, u8 rx_pause, + int pfvf_idx); + int cgx_lmac_reset(void *cgxd, int lmac_id, u8 pf_req_flr); ++u32 cgx_get_fifo_len(void *cgxd); + #endif /* CGX_H */ +diff --git a/drivers/net/ethernet/marvell/octeontx2/af/lmac_common.h b/drivers/net/ethernet/marvell/octeontx2/af/lmac_common.h +index 9ffc6790c5130..c43ff68ef1408 100644 +--- a/drivers/net/ethernet/marvell/octeontx2/af/lmac_common.h ++++ b/drivers/net/ethernet/marvell/octeontx2/af/lmac_common.h +@@ -72,7 +72,6 @@ struct mac_ops { + u8 irq_offset; + u8 int_ena_bit; + u8 lmac_fwi; +- u32 fifo_len; + bool non_contiguous_serdes_lane; + /* RPM & CGX differs in number of Receive/transmit stats */ + u8 rx_stats_cnt; +@@ -142,6 +141,10 @@ struct cgx { + u8 lmac_count; + /* number of LMACs per MAC could be 4 or 8 */ + u8 max_lmac_per_mac; ++ /* length of fifo varies depending on the number ++ * of LMACS ++ */ ++ u32 fifo_len; + #define MAX_LMAC_COUNT 8 + struct lmac *lmac_idmap[MAX_LMAC_COUNT]; + struct work_struct cgx_cmd_work; +diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rpm.c b/drivers/net/ethernet/marvell/octeontx2/af/rpm.c +index 9e8c5e4389f8b..22dd50a3fcd3a 100644 +--- a/drivers/net/ethernet/marvell/octeontx2/af/rpm.c ++++ b/drivers/net/ethernet/marvell/octeontx2/af/rpm.c +@@ -480,7 +480,7 @@ u32 rpm_get_lmac_fifo_len(void *rpmd, int lmac_id) + u8 num_lmacs; + u32 fifo_len; + +- fifo_len = rpm->mac_ops->fifo_len; ++ fifo_len = rpm->fifo_len; + num_lmacs = rpm->mac_ops->get_nr_lmacs(rpm); + + switch (num_lmacs) { +@@ -533,9 +533,9 @@ u32 rpm2_get_lmac_fifo_len(void *rpmd, int lmac_id) + */ + max_lmac = (rpm_read(rpm, 0, CGX_CONST) >> 24) & 0xFF; + if (max_lmac > 4) +- fifo_len = rpm->mac_ops->fifo_len / 2; ++ fifo_len = rpm->fifo_len / 2; + else +- fifo_len = rpm->mac_ops->fifo_len; ++ fifo_len = rpm->fifo_len; + + if (lmac_id < 4) { + num_lmacs = hweight8(lmac_info & 0xF); +diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_cgx.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_cgx.c +index 266ecbc1b97a6..4dcd7bfcad4e4 100644 +--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_cgx.c ++++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_cgx.c +@@ -923,13 +923,12 @@ int rvu_mbox_handler_cgx_features_get(struct rvu *rvu, + + u32 rvu_cgx_get_fifolen(struct rvu *rvu) + { +- struct mac_ops *mac_ops; +- u32 fifo_len; ++ void *cgxd = rvu_first_cgx_pdata(rvu); + +- mac_ops = get_mac_ops(rvu_first_cgx_pdata(rvu)); +- fifo_len = mac_ops ? mac_ops->fifo_len : 0; ++ if (!cgxd) ++ return 0; + +- return fifo_len; ++ return cgx_get_fifo_len(cgxd); + } + + u32 rvu_cgx_get_lmac_fifolen(struct rvu *rvu, int cgx, int lmac) +-- +2.43.0 + diff --git a/queue-6.12/octeontx2-af-rpm-fix-mismatch-in-lmac-type.patch b/queue-6.12/octeontx2-af-rpm-fix-mismatch-in-lmac-type.patch new file mode 100644 index 00000000000..07b7f06b621 --- /dev/null +++ b/queue-6.12/octeontx2-af-rpm-fix-mismatch-in-lmac-type.patch @@ -0,0 +1,37 @@ +From f0a938c84879eb2d77460d76107030d433fe1405 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Fri, 22 Nov 2024 21:50:31 +0530 +Subject: octeontx2-af: RPM: Fix mismatch in lmac type + +From: Hariprasad Kelam <hkelam@marvell.com> + +[ Upstream commit 7ebbbb23ea5b6d051509cb11399afac5042c9266 ] + +Due to a bug in the previous patch, there is a mismatch +between the lmac type reported by the driver and the actual +hardware configuration. + +Fixes: 3ad3f8f93c81 ("octeontx2-af: cn10k: MAC internal loopback support") +Signed-off-by: Hariprasad Kelam <hkelam@marvell.com> +Signed-off-by: Paolo Abeni <pabeni@redhat.com> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/net/ethernet/marvell/octeontx2/af/rpm.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rpm.c b/drivers/net/ethernet/marvell/octeontx2/af/rpm.c +index 1b34cf9c97035..9e8c5e4389f8b 100644 +--- a/drivers/net/ethernet/marvell/octeontx2/af/rpm.c ++++ b/drivers/net/ethernet/marvell/octeontx2/af/rpm.c +@@ -467,7 +467,7 @@ u8 rpm_get_lmac_type(void *rpmd, int lmac_id) + int err; + + req = FIELD_SET(CMDREG_ID, CGX_CMD_GET_LINK_STS, req); +- err = cgx_fwi_cmd_generic(req, &resp, rpm, 0); ++ err = cgx_fwi_cmd_generic(req, &resp, rpm, lmac_id); + if (!err) + return FIELD_GET(RESP_LINKSTAT_LMAC_TYPE, resp); + return err; +-- +2.43.0 + diff --git a/queue-6.12/octeontx2-af-rpm-fix-stale-fcfec-counters.patch b/queue-6.12/octeontx2-af-rpm-fix-stale-fcfec-counters.patch new file mode 100644 index 00000000000..223d492c523 --- /dev/null +++ b/queue-6.12/octeontx2-af-rpm-fix-stale-fcfec-counters.patch @@ -0,0 +1,90 @@ +From 6cc709e8392ddc7b2312fe9ac53592be97671efc Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Fri, 22 Nov 2024 21:50:34 +0530 +Subject: octeontx2-af: RPM: fix stale FCFEC counters + +From: Hariprasad Kelam <hkelam@marvell.com> + +[ Upstream commit 6fc2164108462b913a1290fa2c44054c70b060ef ] + +The corrected words register(FCFECX_VL0_CCW_LO)/Uncorrected words +register (FCFECX_VL0_NCCW_LO) of FCFEC counter has different LMAC +offset which needs to be accessed differently. + +Fixes: 84ad3642115d ("octeontx2-af: Add FEC stats for RPM/RPM_USX block") +Signed-off-by: Hariprasad Kelam <hkelam@marvell.com> +Signed-off-by: Paolo Abeni <pabeni@redhat.com> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + .../net/ethernet/marvell/octeontx2/af/rpm.c | 24 +++++++++---------- + .../net/ethernet/marvell/octeontx2/af/rpm.h | 10 ++++---- + 2 files changed, 17 insertions(+), 17 deletions(-) + +diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rpm.c b/drivers/net/ethernet/marvell/octeontx2/af/rpm.c +index 70629f94c27ef..e97fcc51d7f24 100644 +--- a/drivers/net/ethernet/marvell/octeontx2/af/rpm.c ++++ b/drivers/net/ethernet/marvell/octeontx2/af/rpm.c +@@ -704,27 +704,27 @@ int rpm_get_fec_stats(void *rpmd, int lmac_id, struct cgx_fec_stats_rsp *rsp) + */ + mutex_lock(&rpm->lock); + if (rpm->lmac_idmap[lmac_id]->link_info.fec == OTX2_FEC_BASER) { +- val_lo = rpm_read(rpm, lmac_id, RPMX_MTI_FCFECX_VL0_CCW_LO); +- val_hi = rpm_read(rpm, lmac_id, RPMX_MTI_FCFECX_CW_HI); ++ val_lo = rpm_read(rpm, 0, RPMX_MTI_FCFECX_VL0_CCW_LO(lmac_id)); ++ val_hi = rpm_read(rpm, 0, RPMX_MTI_FCFECX_CW_HI(lmac_id)); + rsp->fec_corr_blks = (val_hi << 16 | val_lo); + +- val_lo = rpm_read(rpm, lmac_id, RPMX_MTI_FCFECX_VL0_NCCW_LO); +- val_hi = rpm_read(rpm, lmac_id, RPMX_MTI_FCFECX_CW_HI); ++ val_lo = rpm_read(rpm, 0, RPMX_MTI_FCFECX_VL0_NCCW_LO(lmac_id)); ++ val_hi = rpm_read(rpm, 0, RPMX_MTI_FCFECX_CW_HI(lmac_id)); + rsp->fec_uncorr_blks = (val_hi << 16 | val_lo); + + /* 50G uses 2 Physical serdes lines */ + if (rpm->lmac_idmap[lmac_id]->link_info.lmac_type_id == + LMAC_MODE_50G_R) { +- val_lo = rpm_read(rpm, lmac_id, +- RPMX_MTI_FCFECX_VL1_CCW_LO); +- val_hi = rpm_read(rpm, lmac_id, +- RPMX_MTI_FCFECX_CW_HI); ++ val_lo = rpm_read(rpm, 0, ++ RPMX_MTI_FCFECX_VL1_CCW_LO(lmac_id)); ++ val_hi = rpm_read(rpm, 0, ++ RPMX_MTI_FCFECX_CW_HI(lmac_id)); + rsp->fec_corr_blks += (val_hi << 16 | val_lo); + +- val_lo = rpm_read(rpm, lmac_id, +- RPMX_MTI_FCFECX_VL1_NCCW_LO); +- val_hi = rpm_read(rpm, lmac_id, +- RPMX_MTI_FCFECX_CW_HI); ++ val_lo = rpm_read(rpm, 0, ++ RPMX_MTI_FCFECX_VL1_NCCW_LO(lmac_id)); ++ val_hi = rpm_read(rpm, 0, ++ RPMX_MTI_FCFECX_CW_HI(lmac_id)); + rsp->fec_uncorr_blks += (val_hi << 16 | val_lo); + } + } else { +diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rpm.h b/drivers/net/ethernet/marvell/octeontx2/af/rpm.h +index a5773fbacaff8..5194fec4c3b8e 100644 +--- a/drivers/net/ethernet/marvell/octeontx2/af/rpm.h ++++ b/drivers/net/ethernet/marvell/octeontx2/af/rpm.h +@@ -91,11 +91,11 @@ + #define RPMX_MTI_RSFEC_STAT_FAST_DATA_HI_CDC 0x40000 + #define RPMX_MTI_RSFEC_STAT_COUNTER_CAPTURE_2 0x40050 + #define RPMX_MTI_RSFEC_STAT_COUNTER_CAPTURE_3 0x40058 +-#define RPMX_MTI_FCFECX_VL0_CCW_LO 0x38618 +-#define RPMX_MTI_FCFECX_VL0_NCCW_LO 0x38620 +-#define RPMX_MTI_FCFECX_VL1_CCW_LO 0x38628 +-#define RPMX_MTI_FCFECX_VL1_NCCW_LO 0x38630 +-#define RPMX_MTI_FCFECX_CW_HI 0x38638 ++#define RPMX_MTI_FCFECX_VL0_CCW_LO(a) (0x38618 + ((a) * 0x40)) ++#define RPMX_MTI_FCFECX_VL0_NCCW_LO(a) (0x38620 + ((a) * 0x40)) ++#define RPMX_MTI_FCFECX_VL1_CCW_LO(a) (0x38628 + ((a) * 0x40)) ++#define RPMX_MTI_FCFECX_VL1_NCCW_LO(a) (0x38630 + ((a) * 0x40)) ++#define RPMX_MTI_FCFECX_CW_HI(a) (0x38638 + ((a) * 0x40)) + + /* CN10KB CSR Declaration */ + #define RPM2_CMRX_SW_INT 0x1b0 +-- +2.43.0 + diff --git a/queue-6.12/octeontx2-af-rpm-fix-stale-rsfec-counters.patch b/queue-6.12/octeontx2-af-rpm-fix-stale-rsfec-counters.patch new file mode 100644 index 00000000000..eed1a418c80 --- /dev/null +++ b/queue-6.12/octeontx2-af-rpm-fix-stale-rsfec-counters.patch @@ -0,0 +1,83 @@ +From 310259523fed5c3b402994e63ea1549d5605d795 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Fri, 22 Nov 2024 21:50:33 +0530 +Subject: octeontx2-af: RPM: fix stale RSFEC counters + +From: Hariprasad Kelam <hkelam@marvell.com> + +[ Upstream commit 07cd1eb166a3fa7244afa74d48bd13c9df7c559d ] + +The earlier patch sets the 'Stats control register' for RPM +receive/transmit statistics instead of RSFEC statistics, +causing the driver to return stale FEC counters. + +Fixes: 84ad3642115d ("octeontx2-af: Add FEC stats for RPM/RPM_USX block") +Signed-off-by: Hariprasad Kelam <hkelam@marvell.com> +Signed-off-by: Paolo Abeni <pabeni@redhat.com> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/net/ethernet/marvell/octeontx2/af/rpm.c | 13 +++++++++---- + drivers/net/ethernet/marvell/octeontx2/af/rpm.h | 4 +++- + 2 files changed, 12 insertions(+), 5 deletions(-) + +diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rpm.c b/drivers/net/ethernet/marvell/octeontx2/af/rpm.c +index 22dd50a3fcd3a..70629f94c27ef 100644 +--- a/drivers/net/ethernet/marvell/octeontx2/af/rpm.c ++++ b/drivers/net/ethernet/marvell/octeontx2/af/rpm.c +@@ -699,6 +699,10 @@ int rpm_get_fec_stats(void *rpmd, int lmac_id, struct cgx_fec_stats_rsp *rsp) + if (rpm->lmac_idmap[lmac_id]->link_info.fec == OTX2_FEC_NONE) + return 0; + ++ /* latched registers FCFECX_CW_HI/RSFEC_STAT_FAST_DATA_HI_CDC are common ++ * for all counters. Acquire lock to ensure serialized reads ++ */ ++ mutex_lock(&rpm->lock); + if (rpm->lmac_idmap[lmac_id]->link_info.fec == OTX2_FEC_BASER) { + val_lo = rpm_read(rpm, lmac_id, RPMX_MTI_FCFECX_VL0_CCW_LO); + val_hi = rpm_read(rpm, lmac_id, RPMX_MTI_FCFECX_CW_HI); +@@ -725,20 +729,21 @@ int rpm_get_fec_stats(void *rpmd, int lmac_id, struct cgx_fec_stats_rsp *rsp) + } + } else { + /* enable RS-FEC capture */ +- cfg = rpm_read(rpm, 0, RPMX_MTI_STAT_STATN_CONTROL); ++ cfg = rpm_read(rpm, 0, RPMX_MTI_RSFEC_STAT_STATN_CONTROL); + cfg |= RPMX_RSFEC_RX_CAPTURE | BIT(lmac_id); +- rpm_write(rpm, 0, RPMX_MTI_STAT_STATN_CONTROL, cfg); ++ rpm_write(rpm, 0, RPMX_MTI_RSFEC_STAT_STATN_CONTROL, cfg); + + val_lo = rpm_read(rpm, 0, + RPMX_MTI_RSFEC_STAT_COUNTER_CAPTURE_2); +- val_hi = rpm_read(rpm, 0, RPMX_MTI_STAT_DATA_HI_CDC); ++ val_hi = rpm_read(rpm, 0, RPMX_MTI_RSFEC_STAT_FAST_DATA_HI_CDC); + rsp->fec_corr_blks = (val_hi << 32 | val_lo); + + val_lo = rpm_read(rpm, 0, + RPMX_MTI_RSFEC_STAT_COUNTER_CAPTURE_3); +- val_hi = rpm_read(rpm, 0, RPMX_MTI_STAT_DATA_HI_CDC); ++ val_hi = rpm_read(rpm, 0, RPMX_MTI_RSFEC_STAT_FAST_DATA_HI_CDC); + rsp->fec_uncorr_blks = (val_hi << 32 | val_lo); + } ++ mutex_unlock(&rpm->lock); + + return 0; + } +diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rpm.h b/drivers/net/ethernet/marvell/octeontx2/af/rpm.h +index 34b11deb0f3c1..a5773fbacaff8 100644 +--- a/drivers/net/ethernet/marvell/octeontx2/af/rpm.h ++++ b/drivers/net/ethernet/marvell/octeontx2/af/rpm.h +@@ -84,9 +84,11 @@ + /* FEC stats */ + #define RPMX_MTI_STAT_STATN_CONTROL 0x10018 + #define RPMX_MTI_STAT_DATA_HI_CDC 0x10038 +-#define RPMX_RSFEC_RX_CAPTURE BIT_ULL(27) ++#define RPMX_RSFEC_RX_CAPTURE BIT_ULL(28) + #define RPMX_CMD_CLEAR_RX BIT_ULL(30) + #define RPMX_CMD_CLEAR_TX BIT_ULL(31) ++#define RPMX_MTI_RSFEC_STAT_STATN_CONTROL 0x40018 ++#define RPMX_MTI_RSFEC_STAT_FAST_DATA_HI_CDC 0x40000 + #define RPMX_MTI_RSFEC_STAT_COUNTER_CAPTURE_2 0x40050 + #define RPMX_MTI_RSFEC_STAT_COUNTER_CAPTURE_3 0x40058 + #define RPMX_MTI_FCFECX_VL0_CCW_LO 0x38618 +-- +2.43.0 + diff --git a/queue-6.12/octeontx2-pf-handle-otx2_mbox_get_rsp-errors-in-cn10.patch b/queue-6.12/octeontx2-pf-handle-otx2_mbox_get_rsp-errors-in-cn10.patch new file mode 100644 index 00000000000..99ae1a7989c --- /dev/null +++ b/queue-6.12/octeontx2-pf-handle-otx2_mbox_get_rsp-errors-in-cn10.patch @@ -0,0 +1,39 @@ +From a0eb28a5b943a9cb8f877747f9e28c7b12e73b88 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Thu, 17 Oct 2024 19:10:36 +0000 +Subject: octeontx2-pf: handle otx2_mbox_get_rsp errors in cn10k.c + +From: Dipendra Khadka <kdipendra88@gmail.com> + +[ Upstream commit ac9183023b6a9c09467516abd8aab04f9a2f9564 ] + +Add error pointer check after calling otx2_mbox_get_rsp(). + +Fixes: 2ca89a2c3752 ("octeontx2-pf: TC_MATCHALL ingress ratelimiting offload") +Signed-off-by: Dipendra Khadka <kdipendra88@gmail.com> +Reviewed-by: Simon Horman <horms@kernel.org> +Signed-off-by: Andrew Lunn <andrew@lunn.ch> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/net/ethernet/marvell/octeontx2/nic/cn10k.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/cn10k.c b/drivers/net/ethernet/marvell/octeontx2/nic/cn10k.c +index c1c99d7054f87..7417087b6db59 100644 +--- a/drivers/net/ethernet/marvell/octeontx2/nic/cn10k.c ++++ b/drivers/net/ethernet/marvell/octeontx2/nic/cn10k.c +@@ -203,6 +203,11 @@ int cn10k_alloc_leaf_profile(struct otx2_nic *pfvf, u16 *leaf) + + rsp = (struct nix_bandprof_alloc_rsp *) + otx2_mbox_get_rsp(&pfvf->mbox.mbox, 0, &req->hdr); ++ if (IS_ERR(rsp)) { ++ rc = PTR_ERR(rsp); ++ goto out; ++ } ++ + if (!rsp->prof_count[BAND_PROF_LEAF_LAYER]) { + rc = -EIO; + goto out; +-- +2.43.0 + diff --git a/queue-6.12/octeontx2-pf-handle-otx2_mbox_get_rsp-errors-in-otx2.patch b/queue-6.12/octeontx2-pf-handle-otx2_mbox_get_rsp-errors-in-otx2.patch new file mode 100644 index 00000000000..2ef51621b4e --- /dev/null +++ b/queue-6.12/octeontx2-pf-handle-otx2_mbox_get_rsp-errors-in-otx2.patch @@ -0,0 +1,38 @@ +From dfee694674e7c8a9e1c753b02a8190311fd1be95 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Thu, 17 Oct 2024 18:56:33 +0000 +Subject: octeontx2-pf: handle otx2_mbox_get_rsp errors in otx2_common.c + +From: Dipendra Khadka <kdipendra88@gmail.com> + +[ Upstream commit 0fbc7a5027c6f7f2c785adae3dcec22b2f2b69b3 ] + +Add error pointer check after calling otx2_mbox_get_rsp(). + +Fixes: ab58a416c93f ("octeontx2-pf: cn10k: Get max mtu supported from admin function") +Signed-off-by: Dipendra Khadka <kdipendra88@gmail.com> +Reviewed-by: Simon Horman <horms@kernel.org> +Signed-off-by: Andrew Lunn <andrew@lunn.ch> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c +index 87d5776e3b88e..7510a918d942c 100644 +--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c ++++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c +@@ -1837,6 +1837,10 @@ u16 otx2_get_max_mtu(struct otx2_nic *pfvf) + if (!rc) { + rsp = (struct nix_hw_info *) + otx2_mbox_get_rsp(&pfvf->mbox.mbox, 0, &req->hdr); ++ if (IS_ERR(rsp)) { ++ rc = PTR_ERR(rsp); ++ goto out; ++ } + + /* HW counts VLAN insertion bytes (8 for double tag) + * irrespective of whether SQE is requesting to insert VLAN +-- +2.43.0 + diff --git a/queue-6.12/octeontx2-pf-handle-otx2_mbox_get_rsp-errors-in-otx2.patch-15305 b/queue-6.12/octeontx2-pf-handle-otx2_mbox_get_rsp-errors-in-otx2.patch-15305 new file mode 100644 index 00000000000..4f6bc7a212f --- /dev/null +++ b/queue-6.12/octeontx2-pf-handle-otx2_mbox_get_rsp-errors-in-otx2.patch-15305 @@ -0,0 +1,60 @@ +From 9976bce0096833eb4fcad43cf68ee8e4667fc831 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Thu, 17 Oct 2024 19:08:44 +0000 +Subject: octeontx2-pf: handle otx2_mbox_get_rsp errors in otx2_flows.c + +From: Dipendra Khadka <kdipendra88@gmail.com> + +[ Upstream commit bd3110bc102ab6292656b8118be819faa0de8dd0 ] + +Adding error pointer check after calling otx2_mbox_get_rsp(). + +Fixes: 9917060fc30a ("octeontx2-pf: Cleanup flow rule management") +Fixes: f0a1913f8a6f ("octeontx2-pf: Add support for ethtool ntuple filters") +Fixes: 674b3e164238 ("octeontx2-pf: Add additional checks while configuring ucast/bcast/mcast rules") +Signed-off-by: Dipendra Khadka <kdipendra88@gmail.com> +Reviewed-by: Simon Horman <horms@kernel.org> +Signed-off-by: Andrew Lunn <andrew@lunn.ch> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + .../net/ethernet/marvell/octeontx2/nic/otx2_flows.c | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_flows.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_flows.c +index 98c31a16c70b4..58720a161ee24 100644 +--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_flows.c ++++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_flows.c +@@ -119,6 +119,8 @@ int otx2_alloc_mcam_entries(struct otx2_nic *pfvf, u16 count) + + rsp = (struct npc_mcam_alloc_entry_rsp *)otx2_mbox_get_rsp + (&pfvf->mbox.mbox, 0, &req->hdr); ++ if (IS_ERR(rsp)) ++ goto exit; + + for (ent = 0; ent < rsp->count; ent++) + flow_cfg->flow_ent[ent + allocated] = rsp->entry_list[ent]; +@@ -197,6 +199,10 @@ int otx2_mcam_entry_init(struct otx2_nic *pfvf) + + rsp = (struct npc_mcam_alloc_entry_rsp *)otx2_mbox_get_rsp + (&pfvf->mbox.mbox, 0, &req->hdr); ++ if (IS_ERR(rsp)) { ++ mutex_unlock(&pfvf->mbox.lock); ++ return PTR_ERR(rsp); ++ } + + if (rsp->count != req->count) { + netdev_info(pfvf->netdev, +@@ -232,6 +238,10 @@ int otx2_mcam_entry_init(struct otx2_nic *pfvf) + + frsp = (struct npc_get_field_status_rsp *)otx2_mbox_get_rsp + (&pfvf->mbox.mbox, 0, &freq->hdr); ++ if (IS_ERR(frsp)) { ++ mutex_unlock(&pfvf->mbox.lock); ++ return PTR_ERR(frsp); ++ } + + if (frsp->enable) { + pfvf->flags |= OTX2_FLAG_RX_VLAN_SUPPORT; +-- +2.43.0 + diff --git a/queue-6.12/octeontx2-pf-handle-otx2_mbox_get_rsp-errors-in-otx2.patch-20711 b/queue-6.12/octeontx2-pf-handle-otx2_mbox_get_rsp-errors-in-otx2.patch-20711 new file mode 100644 index 00000000000..90e3f8e183b --- /dev/null +++ b/queue-6.12/octeontx2-pf-handle-otx2_mbox_get_rsp-errors-in-otx2.patch-20711 @@ -0,0 +1,51 @@ +From ab8879e37a83b3b49d5edcd10621fcaed8f2bc29 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Thu, 17 Oct 2024 19:13:54 +0000 +Subject: octeontx2-pf: handle otx2_mbox_get_rsp errors in otx2_dmac_flt.c + +From: Dipendra Khadka <kdipendra88@gmail.com> + +[ Upstream commit f5b942e6c54b13246ee49d42dcfb71b7f29e3c64 ] + +Add error pointer checks after calling otx2_mbox_get_rsp(). + +Fixes: 79d2be385e9e ("octeontx2-pf: offload DMAC filters to CGX/RPM block") +Fixes: fa5e0ccb8f3a ("octeontx2-pf: Add support for exact match table.") +Signed-off-by: Dipendra Khadka <kdipendra88@gmail.com> +Reviewed-by: Simon Horman <horms@kernel.org> +Signed-off-by: Andrew Lunn <andrew@lunn.ch> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + .../net/ethernet/marvell/octeontx2/nic/otx2_dmac_flt.c | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_dmac_flt.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_dmac_flt.c +index 80d853b343f98..2046dd0da00d8 100644 +--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_dmac_flt.c ++++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_dmac_flt.c +@@ -28,6 +28,11 @@ static int otx2_dmacflt_do_add(struct otx2_nic *pf, const u8 *mac, + if (!err) { + rsp = (struct cgx_mac_addr_add_rsp *) + otx2_mbox_get_rsp(&pf->mbox.mbox, 0, &req->hdr); ++ if (IS_ERR(rsp)) { ++ mutex_unlock(&pf->mbox.lock); ++ return PTR_ERR(rsp); ++ } ++ + *dmac_index = rsp->index; + } + +@@ -200,6 +205,10 @@ int otx2_dmacflt_update(struct otx2_nic *pf, u8 *mac, u32 bit_pos) + + rsp = (struct cgx_mac_addr_update_rsp *) + otx2_mbox_get_rsp(&pf->mbox.mbox, 0, &req->hdr); ++ if (IS_ERR(rsp)) { ++ rc = PTR_ERR(rsp); ++ goto out; ++ } + + pf->flow_cfg->bmap_to_dmacindex[bit_pos] = rsp->index; + +-- +2.43.0 + diff --git a/queue-6.12/octeontx2-pf-handle-otx2_mbox_get_rsp-errors-in-otx2.patch-27436 b/queue-6.12/octeontx2-pf-handle-otx2_mbox_get_rsp-errors-in-otx2.patch-27436 new file mode 100644 index 00000000000..406d007f438 --- /dev/null +++ b/queue-6.12/octeontx2-pf-handle-otx2_mbox_get_rsp-errors-in-otx2.patch-27436 @@ -0,0 +1,52 @@ +From 456d1d2982ea054f1ba481c6311de916d6107dc1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Thu, 17 Oct 2024 19:02:29 +0000 +Subject: octeontx2-pf: handle otx2_mbox_get_rsp errors in otx2_ethtool.c + +From: Dipendra Khadka <kdipendra88@gmail.com> + +[ Upstream commit e26f8eac6bb20b20fdb8f7dc695711ebce4c7c5c ] + +Add error pointer check after calling otx2_mbox_get_rsp(). + +Fixes: 75f36270990c ("octeontx2-pf: Support to enable/disable pause frames via ethtool") +Fixes: d0cf9503e908 ("octeontx2-pf: ethtool fec mode support") +Signed-off-by: Dipendra Khadka <kdipendra88@gmail.com> +Reviewed-by: Simon Horman <horms@kernel.org> +Signed-off-by: Andrew Lunn <andrew@lunn.ch> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + .../net/ethernet/marvell/octeontx2/nic/otx2_ethtool.c | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_ethtool.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_ethtool.c +index 32468c663605e..5197ce816581e 100644 +--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_ethtool.c ++++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_ethtool.c +@@ -343,6 +343,11 @@ static void otx2_get_pauseparam(struct net_device *netdev, + if (!otx2_sync_mbox_msg(&pfvf->mbox)) { + rsp = (struct cgx_pause_frm_cfg *) + otx2_mbox_get_rsp(&pfvf->mbox.mbox, 0, &req->hdr); ++ if (IS_ERR(rsp)) { ++ mutex_unlock(&pfvf->mbox.lock); ++ return; ++ } ++ + pause->rx_pause = rsp->rx_pause; + pause->tx_pause = rsp->tx_pause; + } +@@ -1072,6 +1077,11 @@ static int otx2_set_fecparam(struct net_device *netdev, + + rsp = (struct fec_mode *)otx2_mbox_get_rsp(&pfvf->mbox.mbox, + 0, &req->hdr); ++ if (IS_ERR(rsp)) { ++ err = PTR_ERR(rsp); ++ goto end; ++ } ++ + if (rsp->fec >= 0) + pfvf->linfo.fec = rsp->fec; + else +-- +2.43.0 + diff --git a/queue-6.12/octeontx2-pf-handle-otx2_mbox_get_rsp-errors-in-otx2.patch-32608 b/queue-6.12/octeontx2-pf-handle-otx2_mbox_get_rsp-errors-in-otx2.patch-32608 new file mode 100644 index 00000000000..c9df66c719e --- /dev/null +++ b/queue-6.12/octeontx2-pf-handle-otx2_mbox_get_rsp-errors-in-otx2.patch-32608 @@ -0,0 +1,39 @@ +From 37671570362ed96edb096a1fea848b66453029ca Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Thu, 17 Oct 2024 19:16:16 +0000 +Subject: octeontx2-pf: handle otx2_mbox_get_rsp errors in otx2_dcbnl.c + +From: Dipendra Khadka <kdipendra88@gmail.com> + +[ Upstream commit 69297b0d3369488af259e3a7cf53d69157938ea1 ] + +Add error pointer check after calling otx2_mbox_get_rsp(). + +Fixes: 8e67558177f8 ("octeontx2-pf: PFC config support with DCBx") +Signed-off-by: Dipendra Khadka <kdipendra88@gmail.com> +Reviewed-by: Simon Horman <horms@kernel.org> +Signed-off-by: Andrew Lunn <andrew@lunn.ch> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/net/ethernet/marvell/octeontx2/nic/otx2_dcbnl.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_dcbnl.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_dcbnl.c +index aa01110f04a33..294fba58b6709 100644 +--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_dcbnl.c ++++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_dcbnl.c +@@ -315,6 +315,11 @@ int otx2_config_priority_flow_ctrl(struct otx2_nic *pfvf) + if (!otx2_sync_mbox_msg(&pfvf->mbox)) { + rsp = (struct cgx_pfc_rsp *) + otx2_mbox_get_rsp(&pfvf->mbox.mbox, 0, &req->hdr); ++ if (IS_ERR(rsp)) { ++ err = PTR_ERR(rsp); ++ goto unlock; ++ } ++ + if (req->rx_pause != rsp->rx_pause || req->tx_pause != rsp->tx_pause) { + dev_warn(pfvf->dev, + "Failed to config PFC\n"); +-- +2.43.0 + diff --git a/queue-6.12/of-fdt-add-dt_phys-arg-to-early_init_dt_scan-and-ear.patch b/queue-6.12/of-fdt-add-dt_phys-arg-to-early_init_dt_scan-and-ear.patch new file mode 100644 index 00000000000..1b845a17712 --- /dev/null +++ b/queue-6.12/of-fdt-add-dt_phys-arg-to-early_init_dt_scan-and-ear.patch @@ -0,0 +1,386 @@ +From 28b711099c4772cee53d66442f4d58fbd405d8a3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Wed, 23 Oct 2024 18:14:26 +0100 +Subject: of/fdt: add dt_phys arg to early_init_dt_scan and + early_init_dt_verify + +From: Usama Arif <usamaarif642@gmail.com> + +[ Upstream commit b2473a359763e27567993e7d8f37de82f57a0829 ] + + __pa() is only intended to be used for linear map addresses and using +it for initial_boot_params which is in fixmap for arm64 will give an +incorrect value. Hence save the physical address when it is known at +boot time when calling early_init_dt_scan for arm64 and use it at kexec +time instead of converting the virtual address using __pa(). + +Note that arm64 doesn't need the FDT region reserved in the DT as the +kernel explicitly reserves the passed in FDT. Therefore, only a debug +warning is fixed with this change. + +Reported-by: Breno Leitao <leitao@debian.org> +Suggested-by: Mark Rutland <mark.rutland@arm.com> +Signed-off-by: Usama Arif <usamaarif642@gmail.com> +Fixes: ac10be5cdbfa ("arm64: Use common of_kexec_alloc_and_setup_fdt()") +Link: https://lore.kernel.org/r/20241023171426.452688-1-usamaarif642@gmail.com +Signed-off-by: Rob Herring (Arm) <robh@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + arch/arc/kernel/devtree.c | 2 +- + arch/arm/kernel/devtree.c | 2 +- + arch/arm64/kernel/setup.c | 6 +++++- + arch/csky/kernel/setup.c | 4 ++-- + arch/loongarch/kernel/setup.c | 2 +- + arch/microblaze/kernel/prom.c | 2 +- + arch/mips/kernel/prom.c | 2 +- + arch/mips/kernel/relocate.c | 2 +- + arch/nios2/kernel/prom.c | 4 ++-- + arch/openrisc/kernel/prom.c | 2 +- + arch/powerpc/kernel/dt_cpu_ftrs.c | 2 +- + arch/powerpc/kernel/prom.c | 2 +- + arch/powerpc/platforms/pseries/plpks.c | 2 +- + arch/riscv/kernel/setup.c | 2 +- + arch/sh/kernel/setup.c | 2 +- + arch/um/kernel/dtb.c | 2 +- + arch/x86/kernel/devicetree.c | 2 +- + arch/xtensa/kernel/setup.c | 2 +- + drivers/of/fdt.c | 14 ++++++++------ + drivers/of/kexec.c | 2 +- + include/linux/of_fdt.h | 5 +++-- + 21 files changed, 36 insertions(+), 29 deletions(-) + +diff --git a/arch/arc/kernel/devtree.c b/arch/arc/kernel/devtree.c +index 4c9e61457b2f6..cc6ac7d128aa1 100644 +--- a/arch/arc/kernel/devtree.c ++++ b/arch/arc/kernel/devtree.c +@@ -62,7 +62,7 @@ const struct machine_desc * __init setup_machine_fdt(void *dt) + const struct machine_desc *mdesc; + unsigned long dt_root; + +- if (!early_init_dt_scan(dt)) ++ if (!early_init_dt_scan(dt, __pa(dt))) + return NULL; + + mdesc = of_flat_dt_match_machine(NULL, arch_get_next_mach); +diff --git a/arch/arm/kernel/devtree.c b/arch/arm/kernel/devtree.c +index fdb74e64206a8..3b78966e750a2 100644 +--- a/arch/arm/kernel/devtree.c ++++ b/arch/arm/kernel/devtree.c +@@ -200,7 +200,7 @@ const struct machine_desc * __init setup_machine_fdt(void *dt_virt) + + mdesc_best = &__mach_desc_GENERIC_DT; + +- if (!dt_virt || !early_init_dt_verify(dt_virt)) ++ if (!dt_virt || !early_init_dt_verify(dt_virt, __pa(dt_virt))) + return NULL; + + mdesc = of_flat_dt_match_machine(mdesc_best, arch_get_next_mach); +diff --git a/arch/arm64/kernel/setup.c b/arch/arm64/kernel/setup.c +index b22d28ec80284..87f61fd6783c2 100644 +--- a/arch/arm64/kernel/setup.c ++++ b/arch/arm64/kernel/setup.c +@@ -175,7 +175,11 @@ static void __init setup_machine_fdt(phys_addr_t dt_phys) + if (dt_virt) + memblock_reserve(dt_phys, size); + +- if (!dt_virt || !early_init_dt_scan(dt_virt)) { ++ /* ++ * dt_virt is a fixmap address, hence __pa(dt_virt) can't be used. ++ * Pass dt_phys directly. ++ */ ++ if (!early_init_dt_scan(dt_virt, dt_phys)) { + pr_crit("\n" + "Error: invalid device tree blob at physical address %pa (virtual address 0x%px)\n" + "The dtb must be 8-byte aligned and must not exceed 2 MB in size\n" +diff --git a/arch/csky/kernel/setup.c b/arch/csky/kernel/setup.c +index 51012e90780d6..fe715b707fd0a 100644 +--- a/arch/csky/kernel/setup.c ++++ b/arch/csky/kernel/setup.c +@@ -112,9 +112,9 @@ asmlinkage __visible void __init csky_start(unsigned int unused, + pre_trap_init(); + + if (dtb_start == NULL) +- early_init_dt_scan(__dtb_start); ++ early_init_dt_scan(__dtb_start, __pa(dtb_start)); + else +- early_init_dt_scan(dtb_start); ++ early_init_dt_scan(dtb_start, __pa(dtb_start)); + + start_kernel(); + +diff --git a/arch/loongarch/kernel/setup.c b/arch/loongarch/kernel/setup.c +index cbd3c09a93c14..56934fe58170e 100644 +--- a/arch/loongarch/kernel/setup.c ++++ b/arch/loongarch/kernel/setup.c +@@ -291,7 +291,7 @@ static void __init fdt_setup(void) + if (!fdt_pointer || fdt_check_header(fdt_pointer)) + return; + +- early_init_dt_scan(fdt_pointer); ++ early_init_dt_scan(fdt_pointer, __pa(fdt_pointer)); + early_init_fdt_reserve_self(); + + max_low_pfn = PFN_PHYS(memblock_end_of_DRAM()); +diff --git a/arch/microblaze/kernel/prom.c b/arch/microblaze/kernel/prom.c +index e424c796e297c..76ac4cfdfb42c 100644 +--- a/arch/microblaze/kernel/prom.c ++++ b/arch/microblaze/kernel/prom.c +@@ -18,7 +18,7 @@ void __init early_init_devtree(void *params) + { + pr_debug(" -> early_init_devtree(%p)\n", params); + +- early_init_dt_scan(params); ++ early_init_dt_scan(params, __pa(params)); + if (!strlen(boot_command_line)) + strscpy(boot_command_line, cmd_line, COMMAND_LINE_SIZE); + +diff --git a/arch/mips/kernel/prom.c b/arch/mips/kernel/prom.c +index 6062e6fa589a8..4fd6da0a06c37 100644 +--- a/arch/mips/kernel/prom.c ++++ b/arch/mips/kernel/prom.c +@@ -41,7 +41,7 @@ char *mips_get_machine_name(void) + + void __init __dt_setup_arch(void *bph) + { +- if (!early_init_dt_scan(bph)) ++ if (!early_init_dt_scan(bph, __pa(bph))) + return; + + mips_set_machine_name(of_flat_dt_get_machine_name()); +diff --git a/arch/mips/kernel/relocate.c b/arch/mips/kernel/relocate.c +index 7eeeaf1ff95d2..cda7983e7c18d 100644 +--- a/arch/mips/kernel/relocate.c ++++ b/arch/mips/kernel/relocate.c +@@ -337,7 +337,7 @@ void *__init relocate_kernel(void) + #if defined(CONFIG_USE_OF) + /* Deal with the device tree */ + fdt = plat_get_fdt(); +- early_init_dt_scan(fdt); ++ early_init_dt_scan(fdt, __pa(fdt)); + if (boot_command_line[0]) { + /* Boot command line was passed in device tree */ + strscpy(arcs_cmdline, boot_command_line, COMMAND_LINE_SIZE); +diff --git a/arch/nios2/kernel/prom.c b/arch/nios2/kernel/prom.c +index 9a8393e6b4a85..db049249766fc 100644 +--- a/arch/nios2/kernel/prom.c ++++ b/arch/nios2/kernel/prom.c +@@ -27,7 +27,7 @@ void __init early_init_devtree(void *params) + if (be32_to_cpup((__be32 *)CONFIG_NIOS2_DTB_PHYS_ADDR) == + OF_DT_HEADER) { + params = (void *)CONFIG_NIOS2_DTB_PHYS_ADDR; +- early_init_dt_scan(params); ++ early_init_dt_scan(params, __pa(params)); + return; + } + #endif +@@ -37,5 +37,5 @@ void __init early_init_devtree(void *params) + params = (void *)__dtb_start; + #endif + +- early_init_dt_scan(params); ++ early_init_dt_scan(params, __pa(params)); + } +diff --git a/arch/openrisc/kernel/prom.c b/arch/openrisc/kernel/prom.c +index 19e6008bf114c..e424e9bd12a79 100644 +--- a/arch/openrisc/kernel/prom.c ++++ b/arch/openrisc/kernel/prom.c +@@ -22,6 +22,6 @@ + + void __init early_init_devtree(void *params) + { +- early_init_dt_scan(params); ++ early_init_dt_scan(params, __pa(params)); + memblock_allow_resize(); + } +diff --git a/arch/powerpc/kernel/dt_cpu_ftrs.c b/arch/powerpc/kernel/dt_cpu_ftrs.c +index af4263594eb2c..1bee15c013e75 100644 +--- a/arch/powerpc/kernel/dt_cpu_ftrs.c ++++ b/arch/powerpc/kernel/dt_cpu_ftrs.c +@@ -867,7 +867,7 @@ bool __init dt_cpu_ftrs_init(void *fdt) + using_dt_cpu_ftrs = false; + + /* Setup and verify the FDT, if it fails we just bail */ +- if (!early_init_dt_verify(fdt)) ++ if (!early_init_dt_verify(fdt, __pa(fdt))) + return false; + + if (!of_scan_flat_dt(fdt_find_cpu_features, NULL)) +diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c +index 0be07ed407c70..88cbe432cad59 100644 +--- a/arch/powerpc/kernel/prom.c ++++ b/arch/powerpc/kernel/prom.c +@@ -791,7 +791,7 @@ void __init early_init_devtree(void *params) + DBG(" -> early_init_devtree(%px)\n", params); + + /* Too early to BUG_ON(), do it by hand */ +- if (!early_init_dt_verify(params)) ++ if (!early_init_dt_verify(params, __pa(params))) + panic("BUG: Failed verifying flat device tree, bad version?"); + + of_scan_flat_dt(early_init_dt_scan_model, NULL); +diff --git a/arch/powerpc/platforms/pseries/plpks.c b/arch/powerpc/platforms/pseries/plpks.c +index 4a595493d28ae..b1667ed05f988 100644 +--- a/arch/powerpc/platforms/pseries/plpks.c ++++ b/arch/powerpc/platforms/pseries/plpks.c +@@ -683,7 +683,7 @@ void __init plpks_early_init_devtree(void) + out: + fdt_nop_property(fdt, chosen_node, "ibm,plpks-pw"); + // Since we've cleared the password, we must update the FDT checksum +- early_init_dt_verify(fdt); ++ early_init_dt_verify(fdt, __pa(fdt)); + } + + static __init int pseries_plpks_init(void) +diff --git a/arch/riscv/kernel/setup.c b/arch/riscv/kernel/setup.c +index a2cde65b69e95..26c886db4fb3d 100644 +--- a/arch/riscv/kernel/setup.c ++++ b/arch/riscv/kernel/setup.c +@@ -227,7 +227,7 @@ static void __init init_resources(void) + static void __init parse_dtb(void) + { + /* Early scan of device tree from init memory */ +- if (early_init_dt_scan(dtb_early_va)) { ++ if (early_init_dt_scan(dtb_early_va, __pa(dtb_early_va))) { + const char *name = of_flat_dt_get_machine_name(); + + if (name) { +diff --git a/arch/sh/kernel/setup.c b/arch/sh/kernel/setup.c +index 620e5cf8ae1e7..f2b6f16a46b85 100644 +--- a/arch/sh/kernel/setup.c ++++ b/arch/sh/kernel/setup.c +@@ -255,7 +255,7 @@ void __ref sh_fdt_init(phys_addr_t dt_phys) + dt_virt = phys_to_virt(dt_phys); + #endif + +- if (!dt_virt || !early_init_dt_scan(dt_virt)) { ++ if (!dt_virt || !early_init_dt_scan(dt_virt, __pa(dt_virt))) { + pr_crit("Error: invalid device tree blob" + " at physical address %p\n", (void *)dt_phys); + +diff --git a/arch/um/kernel/dtb.c b/arch/um/kernel/dtb.c +index 4954188a6a090..8d78ced9e08f6 100644 +--- a/arch/um/kernel/dtb.c ++++ b/arch/um/kernel/dtb.c +@@ -17,7 +17,7 @@ void uml_dtb_init(void) + + area = uml_load_file(dtb, &size); + if (area) { +- if (!early_init_dt_scan(area)) { ++ if (!early_init_dt_scan(area, __pa(area))) { + pr_err("invalid DTB %s\n", dtb); + memblock_free(area, size); + return; +diff --git a/arch/x86/kernel/devicetree.c b/arch/x86/kernel/devicetree.c +index 64280879c68c0..59d23cdf4ed0f 100644 +--- a/arch/x86/kernel/devicetree.c ++++ b/arch/x86/kernel/devicetree.c +@@ -305,7 +305,7 @@ void __init x86_flattree_get_config(void) + map_len = size; + } + +- early_init_dt_verify(dt); ++ early_init_dt_verify(dt, __pa(dt)); + } + + unflatten_and_copy_device_tree(); +diff --git a/arch/xtensa/kernel/setup.c b/arch/xtensa/kernel/setup.c +index bdec4a773af09..e51f2060e8308 100644 +--- a/arch/xtensa/kernel/setup.c ++++ b/arch/xtensa/kernel/setup.c +@@ -216,7 +216,7 @@ static int __init xtensa_dt_io_area(unsigned long node, const char *uname, + + void __init early_init_devtree(void *params) + { +- early_init_dt_scan(params); ++ early_init_dt_scan(params, __pa(params)); + of_scan_flat_dt(xtensa_dt_io_area, NULL); + + if (!command_line[0]) +diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c +index 4d528c10df3a9..546e76ac407cf 100644 +--- a/drivers/of/fdt.c ++++ b/drivers/of/fdt.c +@@ -457,6 +457,7 @@ int __initdata dt_root_addr_cells; + int __initdata dt_root_size_cells; + + void *initial_boot_params __ro_after_init; ++phys_addr_t initial_boot_params_pa __ro_after_init; + + #ifdef CONFIG_OF_EARLY_FLATTREE + +@@ -1136,17 +1137,18 @@ static void * __init early_init_dt_alloc_memory_arch(u64 size, u64 align) + return ptr; + } + +-bool __init early_init_dt_verify(void *params) ++bool __init early_init_dt_verify(void *dt_virt, phys_addr_t dt_phys) + { +- if (!params) ++ if (!dt_virt) + return false; + + /* check device tree validity */ +- if (fdt_check_header(params)) ++ if (fdt_check_header(dt_virt)) + return false; + + /* Setup flat device-tree pointer */ +- initial_boot_params = params; ++ initial_boot_params = dt_virt; ++ initial_boot_params_pa = dt_phys; + of_fdt_crc32 = crc32_be(~0, initial_boot_params, + fdt_totalsize(initial_boot_params)); + +@@ -1173,11 +1175,11 @@ void __init early_init_dt_scan_nodes(void) + early_init_dt_check_for_usable_mem_range(); + } + +-bool __init early_init_dt_scan(void *params) ++bool __init early_init_dt_scan(void *dt_virt, phys_addr_t dt_phys) + { + bool status; + +- status = early_init_dt_verify(params); ++ status = early_init_dt_verify(dt_virt, dt_phys); + if (!status) + return false; + +diff --git a/drivers/of/kexec.c b/drivers/of/kexec.c +index 9ccde2fd77cbf..5b924597a4deb 100644 +--- a/drivers/of/kexec.c ++++ b/drivers/of/kexec.c +@@ -301,7 +301,7 @@ void *of_kexec_alloc_and_setup_fdt(const struct kimage *image, + } + + /* Remove memory reservation for the current device tree. */ +- ret = fdt_find_and_del_mem_rsv(fdt, __pa(initial_boot_params), ++ ret = fdt_find_and_del_mem_rsv(fdt, initial_boot_params_pa, + fdt_totalsize(initial_boot_params)); + if (ret == -EINVAL) { + pr_err("Error removing memory reservation.\n"); +diff --git a/include/linux/of_fdt.h b/include/linux/of_fdt.h +index d69ad5bb1eb1e..b8d6c0c208760 100644 +--- a/include/linux/of_fdt.h ++++ b/include/linux/of_fdt.h +@@ -31,6 +31,7 @@ extern void *of_fdt_unflatten_tree(const unsigned long *blob, + extern int __initdata dt_root_addr_cells; + extern int __initdata dt_root_size_cells; + extern void *initial_boot_params; ++extern phys_addr_t initial_boot_params_pa; + + extern char __dtb_start[]; + extern char __dtb_end[]; +@@ -70,8 +71,8 @@ extern u64 dt_mem_next_cell(int s, const __be32 **cellp); + /* Early flat tree scan hooks */ + extern int early_init_dt_scan_root(void); + +-extern bool early_init_dt_scan(void *params); +-extern bool early_init_dt_verify(void *params); ++extern bool early_init_dt_scan(void *dt_virt, phys_addr_t dt_phys); ++extern bool early_init_dt_verify(void *dt_virt, phys_addr_t dt_phys); + extern void early_init_dt_scan_nodes(void); + + extern const char *of_flat_dt_get_machine_name(void); +-- +2.43.0 + diff --git a/queue-6.12/openrisc-implement-fixmap-to-fix-earlycon.patch b/queue-6.12/openrisc-implement-fixmap-to-fix-earlycon.patch new file mode 100644 index 00000000000..7caf918b20b --- /dev/null +++ b/queue-6.12/openrisc-implement-fixmap-to-fix-earlycon.patch @@ -0,0 +1,164 @@ +From 420e4d701a1f2c29fc49fa069b7e27ca230b9289 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Fri, 27 Sep 2024 15:26:40 +0100 +Subject: openrisc: Implement fixmap to fix earlycon + +From: Stafford Horne <shorne@gmail.com> + +[ Upstream commit 1037d186edfc551fa7ba2d4336e74e7575a07a65 ] + +With commit 53c98e35dcbc ("openrisc: mm: remove unneeded early ioremap +code") it was commented that early ioremap was not used in OpenRISC. I +acked this but was wrong, earlycon was using it. Earlycon setup now +fails with the below trace: + + Kernel command line: earlycon + ------------[ cut here ]------------ + WARNING: CPU: 0 PID: 0 at mm/ioremap.c:23 + generic_ioremap_prot+0x118/0x130 + Modules linked in: + CPU: 0 UID: 0 PID: 0 Comm: swapper Not tainted + 6.11.0-rc5-00001-gce02fd891c38-dirty #141 + Call trace: + [<(ptrval)>] dump_stack_lvl+0x7c/0x9c + [<(ptrval)>] dump_stack+0x1c/0x2c + [<(ptrval)>] __warn+0xb4/0x108 + [<(ptrval)>] ? generic_ioremap_prot+0x118/0x130 + [<(ptrval)>] warn_slowpath_fmt+0x60/0x98 + [<(ptrval)>] generic_ioremap_prot+0x118/0x130 + [<(ptrval)>] ioremap_prot+0x20/0x30 + [<(ptrval)>] of_setup_earlycon+0xd4/0x2e0 + [<(ptrval)>] early_init_dt_scan_chosen_stdout+0x18c/0x1c8 + [<(ptrval)>] param_setup_earlycon+0x3c/0x60 + [<(ptrval)>] do_early_param+0xb0/0x118 + [<(ptrval)>] parse_args+0x184/0x4b8 + [<(ptrval)>] ? start_kernel+0x0/0x78c + [<(ptrval)>] parse_early_options+0x40/0x50 + [<(ptrval)>] ? do_early_param+0x0/0x118 + [<(ptrval)>] parse_early_param+0x48/0x68 + [<(ptrval)>] ? start_kernel+0x318/0x78c + [<(ptrval)>] ? start_kernel+0x0/0x78c + ---[ end trace 0000000000000000 ]--- + +To fix this we could either implement early_ioremap again or implement +fixmap. In this patch we choose the later option of implementing basic +fixmap support. + +While fixing this we also remove the old FIX_IOREMAP slots that were +used by early ioremap code. That code was also removed by commit +53c98e35dcbc ("openrisc: mm: remove unneeded early ioremap code") but +these definitions were not cleaned up. + +Fixes: 53c98e35dcbc ("openrisc: mm: remove unneeded early ioremap code") +Signed-off-by: Stafford Horne <shorne@gmail.com> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + arch/openrisc/Kconfig | 3 +++ + arch/openrisc/include/asm/fixmap.h | 21 ++++------------- + arch/openrisc/mm/init.c | 37 ++++++++++++++++++++++++++++++ + 3 files changed, 45 insertions(+), 16 deletions(-) + +diff --git a/arch/openrisc/Kconfig b/arch/openrisc/Kconfig +index 69c0258700b28..3279ef457c573 100644 +--- a/arch/openrisc/Kconfig ++++ b/arch/openrisc/Kconfig +@@ -65,6 +65,9 @@ config STACKTRACE_SUPPORT + config LOCKDEP_SUPPORT + def_bool y + ++config FIX_EARLYCON_MEM ++ def_bool y ++ + menu "Processor type and features" + + choice +diff --git a/arch/openrisc/include/asm/fixmap.h b/arch/openrisc/include/asm/fixmap.h +index ecdb98a5839f7..aaa6a26a3e921 100644 +--- a/arch/openrisc/include/asm/fixmap.h ++++ b/arch/openrisc/include/asm/fixmap.h +@@ -26,29 +26,18 @@ + #include <linux/bug.h> + #include <asm/page.h> + +-/* +- * On OpenRISC we use these special fixed_addresses for doing ioremap +- * early in the boot process before memory initialization is complete. +- * This is used, in particular, by the early serial console code. +- * +- * It's not really 'fixmap', per se, but fits loosely into the same +- * paradigm. +- */ + enum fixed_addresses { +- /* +- * FIX_IOREMAP entries are useful for mapping physical address +- * space before ioremap() is useable, e.g. really early in boot +- * before kmalloc() is working. +- */ +-#define FIX_N_IOREMAPS 32 +- FIX_IOREMAP_BEGIN, +- FIX_IOREMAP_END = FIX_IOREMAP_BEGIN + FIX_N_IOREMAPS - 1, ++ FIX_EARLYCON_MEM_BASE, + __end_of_fixed_addresses + }; + + #define FIXADDR_SIZE (__end_of_fixed_addresses << PAGE_SHIFT) + /* FIXADDR_BOTTOM might be a better name here... */ + #define FIXADDR_START (FIXADDR_TOP - FIXADDR_SIZE) ++#define FIXMAP_PAGE_IO PAGE_KERNEL_NOCACHE ++ ++extern void __set_fixmap(enum fixed_addresses idx, ++ phys_addr_t phys, pgprot_t flags); + + #include <asm-generic/fixmap.h> + +diff --git a/arch/openrisc/mm/init.c b/arch/openrisc/mm/init.c +index 1dcd78c8f0e99..d0cb1a0126f95 100644 +--- a/arch/openrisc/mm/init.c ++++ b/arch/openrisc/mm/init.c +@@ -207,6 +207,43 @@ void __init mem_init(void) + return; + } + ++static int __init map_page(unsigned long va, phys_addr_t pa, pgprot_t prot) ++{ ++ p4d_t *p4d; ++ pud_t *pud; ++ pmd_t *pmd; ++ pte_t *pte; ++ ++ p4d = p4d_offset(pgd_offset_k(va), va); ++ pud = pud_offset(p4d, va); ++ pmd = pmd_offset(pud, va); ++ pte = pte_alloc_kernel(pmd, va); ++ ++ if (pte == NULL) ++ return -ENOMEM; ++ ++ if (pgprot_val(prot)) ++ set_pte_at(&init_mm, va, pte, pfn_pte(pa >> PAGE_SHIFT, prot)); ++ else ++ pte_clear(&init_mm, va, pte); ++ ++ local_flush_tlb_page(NULL, va); ++ return 0; ++} ++ ++void __init __set_fixmap(enum fixed_addresses idx, ++ phys_addr_t phys, pgprot_t prot) ++{ ++ unsigned long address = __fix_to_virt(idx); ++ ++ if (idx >= __end_of_fixed_addresses) { ++ BUG(); ++ return; ++ } ++ ++ map_page(address, phys, prot); ++} ++ + static const pgprot_t protection_map[16] = { + [VM_NONE] = PAGE_NONE, + [VM_READ] = PAGE_READONLY_X, +-- +2.43.0 + diff --git a/queue-6.12/pci-cpqphp-fix-pcibios_-return-value-confusion.patch b/queue-6.12/pci-cpqphp-fix-pcibios_-return-value-confusion.patch new file mode 100644 index 00000000000..9c745c7963c --- /dev/null +++ b/queue-6.12/pci-cpqphp-fix-pcibios_-return-value-confusion.patch @@ -0,0 +1,85 @@ +From 0d015822beee432291c17032c865b35dfb328a29 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Tue, 22 Oct 2024 12:11:37 +0300 +Subject: PCI: cpqphp: Fix PCIBIOS_* return value confusion +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com> + +[ Upstream commit e2226dbc4a4919d9c8bd9293299b532090bdf020 ] + +Code in and related to PCI_RefinedAccessConfig() has three types of return +type confusion: + + - PCI_RefinedAccessConfig() tests pci_bus_read_config_dword() return value + against -1. + + - PCI_RefinedAccessConfig() returns both -1 and PCIBIOS_* return codes. + + - Callers of PCI_RefinedAccessConfig() only test for -1. + +Make PCI_RefinedAccessConfig() return PCIBIOS_* codes consistently and +adapt callers accordingly. + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Link: https://lore.kernel.org/r/20241022091140.3504-2-ilpo.jarvinen@linux.intel.com +Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com> +Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/pci/hotplug/cpqphp_pci.c | 15 ++++++++++----- + 1 file changed, 10 insertions(+), 5 deletions(-) + +diff --git a/drivers/pci/hotplug/cpqphp_pci.c b/drivers/pci/hotplug/cpqphp_pci.c +index 718bc6cf12cb3..974c7db3265b5 100644 +--- a/drivers/pci/hotplug/cpqphp_pci.c ++++ b/drivers/pci/hotplug/cpqphp_pci.c +@@ -135,11 +135,13 @@ int cpqhp_unconfigure_device(struct pci_func *func) + static int PCI_RefinedAccessConfig(struct pci_bus *bus, unsigned int devfn, u8 offset, u32 *value) + { + u32 vendID = 0; ++ int ret; + +- if (pci_bus_read_config_dword(bus, devfn, PCI_VENDOR_ID, &vendID) == -1) +- return -1; ++ ret = pci_bus_read_config_dword(bus, devfn, PCI_VENDOR_ID, &vendID); ++ if (ret != PCIBIOS_SUCCESSFUL) ++ return PCIBIOS_DEVICE_NOT_FOUND; + if (PCI_POSSIBLE_ERROR(vendID)) +- return -1; ++ return PCIBIOS_DEVICE_NOT_FOUND; + return pci_bus_read_config_dword(bus, devfn, offset, value); + } + +@@ -202,13 +204,15 @@ static int PCI_ScanBusForNonBridge(struct controller *ctrl, u8 bus_num, u8 *dev_ + { + u16 tdevice; + u32 work; ++ int ret; + u8 tbus; + + ctrl->pci_bus->number = bus_num; + + for (tdevice = 0; tdevice < 0xFF; tdevice++) { + /* Scan for access first */ +- if (PCI_RefinedAccessConfig(ctrl->pci_bus, tdevice, 0x08, &work) == -1) ++ ret = PCI_RefinedAccessConfig(ctrl->pci_bus, tdevice, 0x08, &work); ++ if (ret) + continue; + dbg("Looking for nonbridge bus_num %d dev_num %d\n", bus_num, tdevice); + /* Yep we got one. Not a bridge ? */ +@@ -220,7 +224,8 @@ static int PCI_ScanBusForNonBridge(struct controller *ctrl, u8 bus_num, u8 *dev_ + } + for (tdevice = 0; tdevice < 0xFF; tdevice++) { + /* Scan for access first */ +- if (PCI_RefinedAccessConfig(ctrl->pci_bus, tdevice, 0x08, &work) == -1) ++ ret = PCI_RefinedAccessConfig(ctrl->pci_bus, tdevice, 0x08, &work); ++ if (ret) + continue; + dbg("Looking for bridge bus_num %d dev_num %d\n", bus_num, tdevice); + /* Yep we got one. bridge ? */ +-- +2.43.0 + diff --git a/queue-6.12/pci-endpoint-epf-mhi-avoid-null-dereference-if-dt-la.patch b/queue-6.12/pci-endpoint-epf-mhi-avoid-null-dereference-if-dt-la.patch new file mode 100644 index 00000000000..6b9df7aa72a --- /dev/null +++ b/queue-6.12/pci-endpoint-epf-mhi-avoid-null-dereference-if-dt-la.patch @@ -0,0 +1,55 @@ +From c4efa066c64aabd245f479c97cf9d370c54d9662 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Tue, 5 Nov 2024 20:07:35 +0800 +Subject: PCI: endpoint: epf-mhi: Avoid NULL dereference if DT lacks 'mmio' +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Zhongqiu Han <quic_zhonhan@quicinc.com> + +[ Upstream commit 5089b3d874e9933d9842e90410d3af1520494757 ] + +If platform_get_resource_byname() fails and returns NULL because DT lacks +an 'mmio' property for the MHI endpoint, dereferencing res->start will +cause a NULL pointer access. Add a check to prevent it. + +Fixes: 1bf5f25324f7 ("PCI: endpoint: Add PCI Endpoint function driver for MHI bus") +Link: https://lore.kernel.org/r/20241105120735.1240728-1-quic_zhonhan@quicinc.com +Signed-off-by: Zhongqiu Han <quic_zhonhan@quicinc.com> +[kwilczynski: error message update per the review feedback] +Signed-off-by: Krzysztof Wilczyński <kwilczynski@kernel.org> +[bhelgaas: commit log] +Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> +Reviewed-by: Niklas Cassel <cassel@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/pci/endpoint/functions/pci-epf-mhi.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/drivers/pci/endpoint/functions/pci-epf-mhi.c b/drivers/pci/endpoint/functions/pci-epf-mhi.c +index 7d070b1def116..54286a40bdfbf 100644 +--- a/drivers/pci/endpoint/functions/pci-epf-mhi.c ++++ b/drivers/pci/endpoint/functions/pci-epf-mhi.c +@@ -867,12 +867,18 @@ static int pci_epf_mhi_bind(struct pci_epf *epf) + { + struct pci_epf_mhi *epf_mhi = epf_get_drvdata(epf); + struct pci_epc *epc = epf->epc; ++ struct device *dev = &epf->dev; + struct platform_device *pdev = to_platform_device(epc->dev.parent); + struct resource *res; + int ret; + + /* Get MMIO base address from Endpoint controller */ + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mmio"); ++ if (!res) { ++ dev_err(dev, "Failed to get \"mmio\" resource\n"); ++ return -ENODEV; ++ } ++ + epf_mhi->mmio_phys = res->start; + epf_mhi->mmio_size = resource_size(res); + +-- +2.43.0 + diff --git a/queue-6.12/pci-fix-reset_method_store-memory-leak.patch b/queue-6.12/pci-fix-reset_method_store-memory-leak.patch new file mode 100644 index 00000000000..b0e069b9229 --- /dev/null +++ b/queue-6.12/pci-fix-reset_method_store-memory-leak.patch @@ -0,0 +1,57 @@ +From 8841b186908afde574f8f4343ccf81accaec46a4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Tue, 1 Oct 2024 23:11:47 +0000 +Subject: PCI: Fix reset_method_store() memory leak + +From: Todd Kjos <tkjos@google.com> + +[ Upstream commit 2985b1844f3f3447f2d938eff1ef6762592065a5 ] + +In reset_method_store(), a string is allocated via kstrndup() and assigned +to the local "options". options is then used in with strsep() to find +spaces: + + while ((name = strsep(&options, " ")) != NULL) { + +If there are no remaining spaces, then options is set to NULL by strsep(), +so the subsequent kfree(options) doesn't free the memory allocated via +kstrndup(). + +Fix by using a separate tmp_options to iterate with strsep() so options is +preserved. + +Link: https://lore.kernel.org/r/20241001231147.3583649-1-tkjos@google.com +Fixes: d88f521da3ef ("PCI: Allow userspace to query and set device reset mechanism") +Signed-off-by: Todd Kjos <tkjos@google.com> +Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/pci/pci.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c +index 225a6cd2e9ca3..08f170fd3efb3 100644 +--- a/drivers/pci/pci.c ++++ b/drivers/pci/pci.c +@@ -5248,7 +5248,7 @@ static ssize_t reset_method_store(struct device *dev, + const char *buf, size_t count) + { + struct pci_dev *pdev = to_pci_dev(dev); +- char *options, *name; ++ char *options, *tmp_options, *name; + int m, n; + u8 reset_methods[PCI_NUM_RESET_METHODS] = { 0 }; + +@@ -5268,7 +5268,8 @@ static ssize_t reset_method_store(struct device *dev, + return -ENOMEM; + + n = 0; +- while ((name = strsep(&options, " ")) != NULL) { ++ tmp_options = options; ++ while ((name = strsep(&tmp_options, " ")) != NULL) { + if (sysfs_streq(name, "")) + continue; + +-- +2.43.0 + diff --git a/queue-6.12/pci-j721e-deassert-perst-after-a-delay-of-pcie_t_pvp.patch b/queue-6.12/pci-j721e-deassert-perst-after-a-delay-of-pcie_t_pvp.patch new file mode 100644 index 00000000000..6b487740295 --- /dev/null +++ b/queue-6.12/pci-j721e-deassert-perst-after-a-delay-of-pcie_t_pvp.patch @@ -0,0 +1,85 @@ +From e88a821cf588f4cfcef84903b7e848ef4b2d3e0b Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Mon, 4 Nov 2024 13:14:20 +0530 +Subject: PCI: j721e: Deassert PERST# after a delay of PCIE_T_PVPERL_MS + milliseconds +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Siddharth Vadapalli <s-vadapalli@ti.com> + +[ Upstream commit 22a9120479a40a56c13c5e473a0100fad2e017c0 ] + +According to Section 2.2 of the PCI Express Card Electromechanical +Specification (Revision 5.1), in order to ensure that the power and the +reference clock are stable, PERST# has to be deasserted after a delay of +100 milliseconds (TPVPERL). + +Currently, it is being assumed that the power is already stable, which +is not necessarily true. + +Hence, change the delay to PCIE_T_PVPERL_MS to guarantee that power and +reference clock are stable. + +Fixes: f3e25911a430 ("PCI: j721e: Add TI J721E PCIe driver") +Fixes: f96b69713733 ("PCI: j721e: Use T_PERST_CLK_US macro") +Link: https://lore.kernel.org/r/20241104074420.1862932-1-s-vadapalli@ti.com +Signed-off-by: Siddharth Vadapalli <s-vadapalli@ti.com> +Signed-off-by: Krzysztof Wilczyński <kwilczynski@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/pci/controller/cadence/pci-j721e.c | 26 ++++++++++------------ + 1 file changed, 12 insertions(+), 14 deletions(-) + +diff --git a/drivers/pci/controller/cadence/pci-j721e.c b/drivers/pci/controller/cadence/pci-j721e.c +index 284f2e0e4d261..e091c3e55b5c6 100644 +--- a/drivers/pci/controller/cadence/pci-j721e.c ++++ b/drivers/pci/controller/cadence/pci-j721e.c +@@ -572,15 +572,14 @@ static int j721e_pcie_probe(struct platform_device *pdev) + pcie->refclk = clk; + + /* +- * The "Power Sequencing and Reset Signal Timings" table of the +- * PCI Express Card Electromechanical Specification, Revision +- * 5.1, Section 2.9.2, Symbol "T_PERST-CLK", indicates PERST# +- * should be deasserted after minimum of 100us once REFCLK is +- * stable. The REFCLK to the connector in RC mode is selected +- * while enabling the PHY. So deassert PERST# after 100 us. ++ * Section 2.2 of the PCI Express Card Electromechanical ++ * Specification (Revision 5.1) mandates that the deassertion ++ * of the PERST# signal should be delayed by 100 ms (TPVPERL). ++ * This shall ensure that the power and the reference clock ++ * are stable. + */ + if (gpiod) { +- fsleep(PCIE_T_PERST_CLK_US); ++ msleep(PCIE_T_PVPERL_MS); + gpiod_set_value_cansleep(gpiod, 1); + } + +@@ -671,15 +670,14 @@ static int j721e_pcie_resume_noirq(struct device *dev) + return ret; + + /* +- * The "Power Sequencing and Reset Signal Timings" table of the +- * PCI Express Card Electromechanical Specification, Revision +- * 5.1, Section 2.9.2, Symbol "T_PERST-CLK", indicates PERST# +- * should be deasserted after minimum of 100us once REFCLK is +- * stable. The REFCLK to the connector in RC mode is selected +- * while enabling the PHY. So deassert PERST# after 100 us. ++ * Section 2.2 of the PCI Express Card Electromechanical ++ * Specification (Revision 5.1) mandates that the deassertion ++ * of the PERST# signal should be delayed by 100 ms (TPVPERL). ++ * This shall ensure that the power and the reference clock ++ * are stable. + */ + if (pcie->reset_gpio) { +- fsleep(PCIE_T_PERST_CLK_US); ++ msleep(PCIE_T_PVPERL_MS); + gpiod_set_value_cansleep(pcie->reset_gpio, 1); + } + +-- +2.43.0 + diff --git a/queue-6.12/pci-qcom-enable-msi-interrupts-together-with-link-up.patch b/queue-6.12/pci-qcom-enable-msi-interrupts-together-with-link-up.patch new file mode 100644 index 00000000000..0e0b0859076 --- /dev/null +++ b/queue-6.12/pci-qcom-enable-msi-interrupts-together-with-link-up.patch @@ -0,0 +1,72 @@ +From bff8e125cb6dfaac9991b08dadec355b0f72e91a Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Mon, 7 Oct 2024 10:42:55 +0530 +Subject: PCI: qcom: Enable MSI interrupts together with Link up if 'Global + IRQ' is supported +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org> + +[ Upstream commit ba4a2e2317b9faeca9193ed6d3193ddc3cf2aba3 ] + +Currently, if 'Global IRQ' is supported by the platform, only the Link up +interrupt is enabled in the PARF_INT_ALL_MASK register. This masks MSIs +on some platforms. The MSI bits in PARF_INT_ALL_MASK register are enabled +by default in the hardware, but commit 4581403f6792 ("PCI: qcom: Enumerate +endpoints based on Link up event in 'global_irq' interrupt") disabled them +and enabled only the Link up interrupt. While MSI continued to work on the +SM8450 platform that was used to test the offending commit, on other +platforms like SM8250, X1E80100, MSIs are getting masked. And they require +enabling the MSI interrupt bits in the register to unmask (enable) the +MSIs. + +Even though the MSI interrupt enable bits in PARF_INT_ALL_MASK are +described as 'diagnostic' interrupts in the internal documentation, +disabling them masks MSI on these platforms. Due to this, MSIs were not +reported to be received these platforms while supporting 'Global IRQ'. + +So, enable the MSI interrupts along with the Link up interrupt in the +PARF_INT_ALL_MASK register if 'Global IRQ' is supported. This ensures that +the MSIs continue to work and also the driver is able to catch the Link +up interrupt for enumerating endpoint devices. + +Fixes: 4581403f6792 ("PCI: qcom: Enumerate endpoints based on Link up event in 'global_irq' interrupt") +Closes: https://lore.kernel.org/linux-pci/9a692c98-eb0a-4d86-b642-ea655981ff53@kernel.org/ +Link: https://lore.kernel.org/r/20241007051255.4378-1-manivannan.sadhasivam@linaro.org +Reported-by: Konrad Dybcio <konradybcio@kernel.org> +Tested-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com> # SL7 +Signed-off-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org> +Signed-off-by: Krzysztof Wilczyński <kwilczynski@kernel.org> +Reviewed-by: Qiang Yu <quic_qianyu@quicinc.com> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/pci/controller/dwc/pcie-qcom.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/pci/controller/dwc/pcie-qcom.c b/drivers/pci/controller/dwc/pcie-qcom.c +index ef44a82be058b..2b33d03ed0541 100644 +--- a/drivers/pci/controller/dwc/pcie-qcom.c ++++ b/drivers/pci/controller/dwc/pcie-qcom.c +@@ -133,6 +133,7 @@ + + /* PARF_INT_ALL_{STATUS/CLEAR/MASK} register fields */ + #define PARF_INT_ALL_LINK_UP BIT(13) ++#define PARF_INT_MSI_DEV_0_7 GENMASK(30, 23) + + /* PARF_NO_SNOOP_OVERIDE register fields */ + #define WR_NO_SNOOP_OVERIDE_EN BIT(1) +@@ -1716,7 +1717,8 @@ static int qcom_pcie_probe(struct platform_device *pdev) + goto err_host_deinit; + } + +- writel_relaxed(PARF_INT_ALL_LINK_UP, pcie->parf + PARF_INT_ALL_MASK); ++ writel_relaxed(PARF_INT_ALL_LINK_UP | PARF_INT_MSI_DEV_0_7, ++ pcie->parf + PARF_INT_ALL_MASK); + } + + qcom_pcie_icc_opp_update(pcie); +-- +2.43.0 + diff --git a/queue-6.12/pci-qcom-ep-move-controller-cleanups-to-qcom_pcie_pe.patch b/queue-6.12/pci-qcom-ep-move-controller-cleanups-to-qcom_pcie_pe.patch new file mode 100644 index 00000000000..654468a799f --- /dev/null +++ b/queue-6.12/pci-qcom-ep-move-controller-cleanups-to-qcom_pcie_pe.patch @@ -0,0 +1,77 @@ +From 3c7ab25cfefca0641142279be13e6616675118e2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Sat, 17 Aug 2024 11:09:03 +0530 +Subject: PCI: qcom-ep: Move controller cleanups to qcom_pcie_perst_deassert() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org> + +[ Upstream commit 7d7cf89b119af433354f865fc01017b9f8aa411a ] + +Currently, the endpoint cleanup function dw_pcie_ep_cleanup() and EPF +deinit notify function pci_epc_deinit_notify() are called during the +execution of qcom_pcie_perst_assert() i.e., when the host has asserted +PERST#. But quickly after this step, refclk will also be disabled by the +host. + +All of the Qcom endpoint SoCs supported as of now depend on the refclk from +the host for keeping the controller operational. Due to this limitation, +any access to the hardware registers in the absence of refclk will result +in a whole endpoint crash. Unfortunately, most of the controller cleanups +require accessing the hardware registers (like eDMA cleanup performed in +dw_pcie_ep_cleanup(), powering down MHI EPF etc...). So these cleanup +functions are currently causing the crash in the endpoint SoC once host +asserts PERST#. + +One way to address this issue is by generating the refclk in the endpoint +itself and not depending on the host. But that is not always possible as +some of the endpoint designs do require the endpoint to consume refclk from +the host (as I was told by the Qcom engineers). + +Thus, fix this crash by moving the controller cleanups to the start of +the qcom_pcie_perst_deassert() function. qcom_pcie_perst_deassert() is +called whenever the host has deasserted PERST# and it is guaranteed that +the refclk would be active at this point. So at the start of this function +(after enabling resources), the controller cleanup can be performed. Once +finished, rest of the code execution for PERST# deassert can continue as +usual. + +Fixes: 473b2cf9c4d1 ("PCI: endpoint: Introduce 'epc_deinit' event and notify the EPF drivers") +Fixes: 570d7715eed8 ("PCI: dwc: ep: Introduce dw_pcie_ep_cleanup() API for drivers supporting PERST#") +Link: https://lore.kernel.org/r/20240817-pci-qcom-ep-cleanup-v1-1-d6b958226559@linaro.org +Signed-off-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org> +Signed-off-by: Krzysztof Wilczyński <kwilczynski@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/pci/controller/dwc/pcie-qcom-ep.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/drivers/pci/controller/dwc/pcie-qcom-ep.c b/drivers/pci/controller/dwc/pcie-qcom-ep.c +index e588fcc545893..b5ca5260f9049 100644 +--- a/drivers/pci/controller/dwc/pcie-qcom-ep.c ++++ b/drivers/pci/controller/dwc/pcie-qcom-ep.c +@@ -396,6 +396,10 @@ static int qcom_pcie_perst_deassert(struct dw_pcie *pci) + return ret; + } + ++ /* Perform cleanup that requires refclk */ ++ pci_epc_deinit_notify(pci->ep.epc); ++ dw_pcie_ep_cleanup(&pci->ep); ++ + /* Assert WAKE# to RC to indicate device is ready */ + gpiod_set_value_cansleep(pcie_ep->wake, 1); + usleep_range(WAKE_DELAY_US, WAKE_DELAY_US + 500); +@@ -540,8 +544,6 @@ static void qcom_pcie_perst_assert(struct dw_pcie *pci) + { + struct qcom_pcie_ep *pcie_ep = to_pcie_ep(pci); + +- pci_epc_deinit_notify(pci->ep.epc); +- dw_pcie_ep_cleanup(&pci->ep); + qcom_pcie_disable_resources(pcie_ep); + pcie_ep->link_status = QCOM_PCIE_EP_LINK_DISABLED; + } +-- +2.43.0 + diff --git a/queue-6.12/pci-tegra194-move-controller-cleanups-to-pex_ep_even.patch b/queue-6.12/pci-tegra194-move-controller-cleanups-to-pex_ep_even.patch new file mode 100644 index 00000000000..3b7ef698230 --- /dev/null +++ b/queue-6.12/pci-tegra194-move-controller-cleanups-to-pex_ep_even.patch @@ -0,0 +1,82 @@ +From 4957470deac34c8f83e27f564807651dca1cac93 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Sat, 17 Aug 2024 11:09:04 +0530 +Subject: PCI: tegra194: Move controller cleanups to + pex_ep_event_pex_rst_deassert() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org> + +[ Upstream commit 40e2125381dc11379112485e3eefdd25c6df5375 ] + +Currently, the endpoint cleanup function dw_pcie_ep_cleanup() and EPF +deinit notify function pci_epc_deinit_notify() are called during the +execution of pex_ep_event_pex_rst_assert() i.e., when the host has asserted +PERST#. But quickly after this step, refclk will also be disabled by the +host. + +All of the tegra194 endpoint SoCs supported as of now depend on the refclk +from the host for keeping the controller operational. Due to this +limitation, any access to the hardware registers in the absence of refclk +will result in a whole endpoint crash. Unfortunately, most of the +controller cleanups require accessing the hardware registers (like eDMA +cleanup performed in dw_pcie_ep_cleanup(), etc...). So these cleanup +functions can cause the crash in the endpoint SoC once host asserts PERST#. + +One way to address this issue is by generating the refclk in the endpoint +itself and not depending on the host. But that is not always possible as +some of the endpoint designs do require the endpoint to consume refclk from +the host. + +Thus, fix this crash by moving the controller cleanups to the start of +the pex_ep_event_pex_rst_deassert() function. This function is called +whenever the host has deasserted PERST# and it is guaranteed that the +refclk would be active at this point. So at the start of this function +(after enabling resources) the controller cleanup can be performed. Once +finished, rest of the code execution for PERST# deassert can continue as +usual. + +Fixes: 473b2cf9c4d1 ("PCI: endpoint: Introduce 'epc_deinit' event and notify the EPF drivers") +Fixes: 570d7715eed8 ("PCI: dwc: ep: Introduce dw_pcie_ep_cleanup() API for drivers supporting PERST#") +Link: https://lore.kernel.org/r/20240817-pci-qcom-ep-cleanup-v1-2-d6b958226559@linaro.org +Signed-off-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org> +Signed-off-by: Krzysztof Wilczyński <kwilczynski@kernel.org> +Cc: Jonathan Hunter <jonathanh@nvidia.com> +Cc: Thierry Reding <thierry.reding@gmail.com> +Cc: Vidya Sagar <vidyas@nvidia.com> +Cc: linux-tegra@vger.kernel.org +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/pci/controller/dwc/pcie-tegra194.c | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +diff --git a/drivers/pci/controller/dwc/pcie-tegra194.c b/drivers/pci/controller/dwc/pcie-tegra194.c +index c1394f2ab63ff..ced3b7e7bdade 100644 +--- a/drivers/pci/controller/dwc/pcie-tegra194.c ++++ b/drivers/pci/controller/dwc/pcie-tegra194.c +@@ -1704,9 +1704,6 @@ static void pex_ep_event_pex_rst_assert(struct tegra_pcie_dw *pcie) + if (ret) + dev_err(pcie->dev, "Failed to go Detect state: %d\n", ret); + +- pci_epc_deinit_notify(pcie->pci.ep.epc); +- dw_pcie_ep_cleanup(&pcie->pci.ep); +- + reset_control_assert(pcie->core_rst); + + tegra_pcie_disable_phy(pcie); +@@ -1785,6 +1782,10 @@ static void pex_ep_event_pex_rst_deassert(struct tegra_pcie_dw *pcie) + goto fail_phy; + } + ++ /* Perform cleanup that requires refclk */ ++ pci_epc_deinit_notify(pcie->pci.ep.epc); ++ dw_pcie_ep_cleanup(&pcie->pci.ep); ++ + /* Clear any stale interrupt statuses */ + appl_writel(pcie, 0xFFFFFFFF, APPL_INTR_STATUS_L0); + appl_writel(pcie, 0xFFFFFFFF, APPL_INTR_STATUS_L1_0_0); +-- +2.43.0 + diff --git a/queue-6.12/perf-bpf-filter-return-enomem-directly-when-pfi-allo.patch b/queue-6.12/perf-bpf-filter-return-enomem-directly-when-pfi-allo.patch new file mode 100644 index 00000000000..45e5e1cdc8a --- /dev/null +++ b/queue-6.12/perf-bpf-filter-return-enomem-directly-when-pfi-allo.patch @@ -0,0 +1,40 @@ +From 1ca1a3fe1dafc05fb08b3cd329fc80700fbd784d Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Wed, 13 Nov 2024 11:05:37 +0800 +Subject: perf bpf-filter: Return -ENOMEM directly when pfi allocation fails + +From: Hao Ge <gehao@kylinos.cn> + +[ Upstream commit bd077a53ad87cb111632e564cdfe8dfbe96786de ] + +Directly return -ENOMEM when pfi allocation fails, +instead of performing other operations on pfi. + +Fixes: 0fe2b18ddc40 ("perf bpf-filter: Support multiple events properly") +Signed-off-by: Hao Ge <gehao@kylinos.cn> +Acked-by: Namhyung Kim <namhyung@kernel.org> +Cc: hao.ge@linux.dev +Cc: bpf@vger.kernel.org +Link: https://lore.kernel.org/r/20241113030537.26732-1-hao.ge@linux.dev +Signed-off-by: Namhyung Kim <namhyung@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + tools/perf/util/bpf-filter.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/tools/perf/util/bpf-filter.c b/tools/perf/util/bpf-filter.c +index e87b6789eb9ef..a4fdf6911ec1c 100644 +--- a/tools/perf/util/bpf-filter.c ++++ b/tools/perf/util/bpf-filter.c +@@ -375,7 +375,7 @@ static int create_idx_hash(struct evsel *evsel, struct perf_bpf_filter_entry *en + pfi = zalloc(sizeof(*pfi)); + if (pfi == NULL) { + pr_err("Cannot save pinned filter index\n"); +- goto err; ++ return -ENOMEM; + } + + pfi->evsel = evsel; +-- +2.43.0 + diff --git a/queue-6.12/perf-build-add-missing-cflags-when-building-with-cus.patch b/queue-6.12/perf-build-add-missing-cflags-when-building-with-cus.patch new file mode 100644 index 00000000000..f8db934b0c1 --- /dev/null +++ b/queue-6.12/perf-build-add-missing-cflags-when-building-with-cus.patch @@ -0,0 +1,50 @@ +From d58ceb4141a844912c665dfe1d1c964a974478c1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Thu, 24 Oct 2024 21:32:36 +0800 +Subject: perf build: Add missing cflags when building with custom + libtraceevent + +From: Yicong Yang <yangyicong@hisilicon.com> + +[ Upstream commit d5a0a4ab4af4c27de097b78d6f1b7e7f7e31908f ] + +When building with custom libtraceevent, below errors occur: + + $ make -C tools/perf NO_LIBPYTHON=1 PKG_CONFIG_PATH=<custom libtraceevent> + In file included from util/session.h:5, + from builtin-buildid-list.c:17: + util/trace-event.h:153:10: fatal error: traceevent/event-parse.h: No such file or directory + 153 | #include <traceevent/event-parse.h> + | ^~~~~~~~~~~~~~~~~~~~~~~~~~ + <snip similar errors of missing headers> + +This is because the include path is missed in the cflags. Add it. + +Fixes: 0f0e1f445690 ("perf build: Use pkg-config for feature check for libtrace{event,fs}") +Signed-off-by: Yicong Yang <yangyicong@hisilicon.com> +Reviewed-by: Leo Yan <leo.yan@arm.com> +Reviewed-by: Guilherme Amadio <amadio@gentoo.org> +Cc: linuxarm@huawei.com +Link: https://lore.kernel.org/r/20241024133236.31016-1-yangyicong@huawei.com +Signed-off-by: Namhyung Kim <namhyung@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + tools/perf/Makefile.config | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/tools/perf/Makefile.config b/tools/perf/Makefile.config +index d4332675babb7..2ce71d2e5fae0 100644 +--- a/tools/perf/Makefile.config ++++ b/tools/perf/Makefile.config +@@ -1194,7 +1194,7 @@ endif + ifneq ($(NO_LIBTRACEEVENT),1) + $(call feature_check,libtraceevent) + ifeq ($(feature-libtraceevent), 1) +- CFLAGS += -DHAVE_LIBTRACEEVENT ++ CFLAGS += -DHAVE_LIBTRACEEVENT $(shell $(PKG_CONFIG) --cflags libtraceevent) + LDFLAGS += $(shell $(PKG_CONFIG) --libs-only-L libtraceevent) + EXTLIBS += $(shell $(PKG_CONFIG) --libs-only-l libtraceevent) + LIBTRACEEVENT_VERSION := $(shell $(PKG_CONFIG) --modversion libtraceevent).0.0 +-- +2.43.0 + diff --git a/queue-6.12/perf-cs-etm-don-t-flush-when-packet_queue-fills-up.patch b/queue-6.12/perf-cs-etm-don-t-flush-when-packet_queue-fills-up.patch new file mode 100644 index 00000000000..b03062692c6 --- /dev/null +++ b/queue-6.12/perf-cs-etm-don-t-flush-when-packet_queue-fills-up.patch @@ -0,0 +1,121 @@ +From f7cf7c2922fe36908e8b94dc9070ccb8f222ae53 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Mon, 16 Sep 2024 14:57:32 +0100 +Subject: perf cs-etm: Don't flush when packet_queue fills up + +From: James Clark <james.clark@linaro.org> + +[ Upstream commit 5afd032961e8465808c4bc385c06e7676fbe1951 ] + +cs_etm__flush(), like cs_etm__sample() is an operation that generates a +sample and then swaps the current with the previous packet. Calling +flush after processing the queues results in two swaps which corrupts +the next sample. Therefore it wasn't appropriate to call flush here so +remove it. + +Flushing is still done on a discontinuity to explicitly clear the last +branch buffer, but when the packet_queue fills up before reaching a +timestamp, that's not a discontinuity and the call to +cs_etm__process_traceid_queue() already generated samples and drained +the buffers correctly. + +This is visible by looking for a branch that has the same target as the +previous branch and the following source is before the address of the +last target, which is impossible as execution would have had to have +gone backwards: + + ffff800080849d40 _find_next_and_bit+0x78 => ffff80008011cadc update_sg_lb_stats+0x94 + (packet_queue fills here before a timestamp, resulting in a flush and + branch target ffff80008011cadc is duplicated.) + ffff80008011cb1c update_sg_lb_stats+0xd4 => ffff80008011cadc update_sg_lb_stats+0x94 + ffff8000801117c4 cpu_util+0x24 => ffff8000801117d4 cpu_util+0x34 + +After removing the flush the correct branch target is used for the +second sample, and ffff8000801117c4 is no longer before the previous +address: + + ffff800080849d40 _find_next_and_bit+0x78 => ffff80008011cadc update_sg_lb_stats+0x94 + ffff80008011cb1c update_sg_lb_stats+0xd4 => ffff8000801117a0 cpu_util+0x0 + ffff8000801117c4 cpu_util+0x24 => ffff8000801117d4 cpu_util+0x34 + +Make sure that a final branch stack is output at the end of the trace +by calling cs_etm__end_block(). This is already done for both the +timeless decode paths. + +Fixes: 21fe8dc1191a ("perf cs-etm: Add support for CPU-wide trace scenarios") +Reported-by: Ganapatrao Kulkarni <gankulkarni@os.amperecomputing.com> +Closes: https://lore.kernel.org/all/20240719092619.274730-1-gankulkarni@os.amperecomputing.com/ +Reviewed-by: Leo Yan <leo.yan@arm.com> +Signed-off-by: James Clark <james.clark@linaro.org> +Tested-by: Ganapatrao Kulkarni <gankulkarni@os.amperecomputing.com> +Cc: Ben Gainey <ben.gainey@arm.com> +Cc: Suzuki K Poulose <suzuki.poulose@arm.com> +Cc: Will Deacon <will@kernel.org> +Cc: Mathieu Poirier <mathieu.poirier@linaro.org> +Cc: Mike Leach <mike.leach@linaro.org> +Cc: Ruidong Tian <tianruidong@linux.alibaba.com> +Cc: Benjamin Gray <bgray@linux.ibm.com> +Cc: linux-arm-kernel@lists.infradead.org +Cc: coresight@lists.linaro.org +Cc: John Garry <john.g.garry@oracle.com> +Cc: scclevenger@os.amperecomputing.com +Link: https://lore.kernel.org/r/20240916135743.1490403-2-james.clark@linaro.org +Signed-off-by: Namhyung Kim <namhyung@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + tools/perf/util/cs-etm.c | 25 ++++++++++++++++++------- + 1 file changed, 18 insertions(+), 7 deletions(-) + +diff --git a/tools/perf/util/cs-etm.c b/tools/perf/util/cs-etm.c +index 40f047baef810..0bf9e5c27b599 100644 +--- a/tools/perf/util/cs-etm.c ++++ b/tools/perf/util/cs-etm.c +@@ -2490,12 +2490,6 @@ static void cs_etm__clear_all_traceid_queues(struct cs_etm_queue *etmq) + + /* Ignore return value */ + cs_etm__process_traceid_queue(etmq, tidq); +- +- /* +- * Generate an instruction sample with the remaining +- * branchstack entries. +- */ +- cs_etm__flush(etmq, tidq); + } + } + +@@ -2638,7 +2632,7 @@ static int cs_etm__process_timestamped_queues(struct cs_etm_auxtrace *etm) + + while (1) { + if (!etm->heap.heap_cnt) +- goto out; ++ break; + + /* Take the entry at the top of the min heap */ + cs_queue_nr = etm->heap.heap_array[0].queue_nr; +@@ -2721,6 +2715,23 @@ static int cs_etm__process_timestamped_queues(struct cs_etm_auxtrace *etm) + ret = auxtrace_heap__add(&etm->heap, cs_queue_nr, cs_timestamp); + } + ++ for (i = 0; i < etm->queues.nr_queues; i++) { ++ struct int_node *inode; ++ ++ etmq = etm->queues.queue_array[i].priv; ++ if (!etmq) ++ continue; ++ ++ intlist__for_each_entry(inode, etmq->traceid_queues_list) { ++ int idx = (int)(intptr_t)inode->priv; ++ ++ /* Flush any remaining branch stack entries */ ++ tidq = etmq->traceid_queues[idx]; ++ ret = cs_etm__end_block(etmq, tidq); ++ if (ret) ++ return ret; ++ } ++ } + out: + return ret; + } +-- +2.43.0 + diff --git a/queue-6.12/perf-disasm-fix-capstone-memory-leak.patch b/queue-6.12/perf-disasm-fix-capstone-memory-leak.patch new file mode 100644 index 00000000000..31dd5922419 --- /dev/null +++ b/queue-6.12/perf-disasm-fix-capstone-memory-leak.patch @@ -0,0 +1,73 @@ +From 234e08c72c7e87158d8707627796ea440077957b Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Wed, 16 Oct 2024 16:56:21 -0700 +Subject: perf disasm: Fix capstone memory leak + +From: Ian Rogers <irogers@google.com> + +[ Upstream commit 1280f012e06e1555de47e3c3a9be898d8cbda5fb ] + +The insn argument passed to cs_disasm needs freeing. To support +accurately having count, add an additional free_count variable. + +Fixes: c5d60de1813a ("perf annotate: Add support to use libcapstone in powerpc") +Signed-off-by: Ian Rogers <irogers@google.com> +Reviewed-by: James Clark <james.clark@linaro.org> +Cc: David S. Miller <davem@davemloft.net> +Cc: Steinar H. Gunderson <sesse@google.com> +Cc: Alexander Lobakin <aleksander.lobakin@intel.com> +Cc: Masami Hiramatsu (Google) <mhiramat@kernel.org> +Cc: Kajol Jain <kjain@linux.ibm.com> +Cc: Athira Rajeev <atrajeev@linux.vnet.ibm.com> +Cc: Hemant Kumar <hemant@linux.vnet.ibm.com> +Link: https://lore.kernel.org/r/20241016235622.52166-2-irogers@google.com +Signed-off-by: Namhyung Kim <namhyung@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + tools/perf/util/disasm.c | 11 +++++++---- + 1 file changed, 7 insertions(+), 4 deletions(-) + +diff --git a/tools/perf/util/disasm.c b/tools/perf/util/disasm.c +index f05ba7739c1e9..2c8063660f2e8 100644 +--- a/tools/perf/util/disasm.c ++++ b/tools/perf/util/disasm.c +@@ -1627,12 +1627,12 @@ static int symbol__disassemble_capstone(char *filename, struct symbol *sym, + u64 start = map__rip_2objdump(map, sym->start); + u64 len; + u64 offset; +- int i, count; ++ int i, count, free_count; + bool is_64bit = false; + bool needs_cs_close = false; + u8 *buf = NULL; + csh handle; +- cs_insn *insn; ++ cs_insn *insn = NULL; + char disasm_buf[512]; + struct disasm_line *dl; + +@@ -1664,7 +1664,7 @@ static int symbol__disassemble_capstone(char *filename, struct symbol *sym, + + needs_cs_close = true; + +- count = cs_disasm(handle, buf, len, start, len, &insn); ++ free_count = count = cs_disasm(handle, buf, len, start, len, &insn); + for (i = 0, offset = 0; i < count; i++) { + int printed; + +@@ -1702,8 +1702,11 @@ static int symbol__disassemble_capstone(char *filename, struct symbol *sym, + } + + out: +- if (needs_cs_close) ++ if (needs_cs_close) { + cs_close(&handle); ++ if (free_count > 0) ++ cs_free(insn, free_count); ++ } + free(buf); + return count < 0 ? count : 0; + +-- +2.43.0 + diff --git a/queue-6.12/perf-disasm-fix-not-cleaning-up-disasm_line-in-symbo.patch b/queue-6.12/perf-disasm-fix-not-cleaning-up-disasm_line-in-symbo.patch new file mode 100644 index 00000000000..c77b8af78db --- /dev/null +++ b/queue-6.12/perf-disasm-fix-not-cleaning-up-disasm_line-in-symbo.patch @@ -0,0 +1,42 @@ +From 653ffa1afe42ae3c2b540a956c47fb002d92537f Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Sat, 19 Oct 2024 23:41:57 +0800 +Subject: perf disasm: Fix not cleaning up disasm_line in + symbol__disassemble_raw() + +From: Li Huafei <lihuafei1@huawei.com> + +[ Upstream commit 150dab31d5609f896fbfaa06b442ca314da79858 ] + +In symbol__disassemble_raw(), the created disasm_line should be +discarded before returning an error. When creating disasm_line fails, +break the loop and then release the created lines. + +Fixes: 0b971e6bf1c3 ("perf annotate: Add support to capture and parse raw instruction in powerpc using dso__data_read_offset utility") +Signed-off-by: Li Huafei <lihuafei1@huawei.com> +Tested-by: Athira Rajeev <atrajeev@linux.vnet.ibm.com> +Cc: sesse@google.com +Cc: kjain@linux.ibm.com +Link: https://lore.kernel.org/r/20241019154157.282038-3-lihuafei1@huawei.com +Signed-off-by: Namhyung Kim <namhyung@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + tools/perf/util/disasm.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/tools/perf/util/disasm.c b/tools/perf/util/disasm.c +index 5d5fcc4dee078..648e8d87ef194 100644 +--- a/tools/perf/util/disasm.c ++++ b/tools/perf/util/disasm.c +@@ -1785,7 +1785,7 @@ static int symbol__disassemble_raw(char *filename, struct symbol *sym, + sprintf(args->line, "%x", line[i]); + dl = disasm_line__new(args); + if (dl == NULL) +- goto err; ++ break; + + annotation_line__add(&dl->al, ¬es->src->source); + offset += 4; +-- +2.43.0 + diff --git a/queue-6.12/perf-disasm-use-disasm_line__free-to-properly-free-d.patch b/queue-6.12/perf-disasm-use-disasm_line__free-to-properly-free-d.patch new file mode 100644 index 00000000000..10f176cda2f --- /dev/null +++ b/queue-6.12/perf-disasm-use-disasm_line__free-to-properly-free-d.patch @@ -0,0 +1,44 @@ +From f55e2010c05ec843ffc0ec1b45a5fc67150fd448 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Sat, 19 Oct 2024 23:41:55 +0800 +Subject: perf disasm: Use disasm_line__free() to properly free disasm_line + +From: Li Huafei <lihuafei1@huawei.com> + +[ Upstream commit b4e0e9a1e30059f4523c9b6a1f8045ad89b5db8a ] + +The structure disasm_line contains members that require dynamically +allocated memory and need to be freed correctly using +disasm_line__free(). + +This patch fixes the incorrect release in +symbol__disassemble_capstone(). + +Fixes: 6d17edc113de ("perf annotate: Use libcapstone to disassemble") +Signed-off-by: Li Huafei <lihuafei1@huawei.com> +Tested-by: Athira Rajeev <atrajeev@linux.vnet.ibm.com> +Cc: sesse@google.com +Cc: kjain@linux.ibm.com +Link: https://lore.kernel.org/r/20241019154157.282038-1-lihuafei1@huawei.com +Signed-off-by: Namhyung Kim <namhyung@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + tools/perf/util/disasm.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/tools/perf/util/disasm.c b/tools/perf/util/disasm.c +index 2c8063660f2e8..5d5fcc4dee078 100644 +--- a/tools/perf/util/disasm.c ++++ b/tools/perf/util/disasm.c +@@ -1720,7 +1720,7 @@ static int symbol__disassemble_capstone(char *filename, struct symbol *sym, + */ + list_for_each_entry_safe(dl, tmp, ¬es->src->source, al.node) { + list_del(&dl->al.node); +- free(dl); ++ disasm_line__free(dl); + } + } + count = -1; +-- +2.43.0 + diff --git a/queue-6.12/perf-dso-fix-symtab_type-for-kmod-compression.patch b/queue-6.12/perf-dso-fix-symtab_type-for-kmod-compression.patch new file mode 100644 index 00000000000..1c63155010d --- /dev/null +++ b/queue-6.12/perf-dso-fix-symtab_type-for-kmod-compression.patch @@ -0,0 +1,45 @@ +From bb7c8931241b79530b40252668d461ee09d48349 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Thu, 10 Oct 2024 16:48:36 +0200 +Subject: perf dso: Fix symtab_type for kmod compression + +From: Veronika Molnarova <vmolnaro@redhat.com> + +[ Upstream commit 05a62936e6b14c005db3b0c9c7d8b93d825dd9ca ] + +During the rework of the dso structure in patch ee756ef7491eafd an +increment was forgotten for the symtab_type in case the data for +the kernel module are compressed. This affects the probing of the +kernel modules, which fails if the data are not already cached. + +Increment the value of the symtab_type to its compressed variant so the +data could be recovered successfully. + +Fixes: ee756ef7491eafd7 ("perf dso: Add reference count checking and accessor functions") +Signed-off-by: Veronika Molnarova <vmolnaro@redhat.com> +Acked-by: Michael Petlan <mpetlan@redhat.com> +Acked-by: Namhyung Kim <namhyung@kernel.org> +Tested-by: Michael Petlan <mpetlan@redhat.com> +Link: https://lore.kernel.org/r/20241010144836.16424-1-vmolnaro@redhat.com +Signed-off-by: Namhyung Kim <namhyung@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + tools/perf/util/machine.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c +index fad227b625d15..4f0ac998b0ccf 100644 +--- a/tools/perf/util/machine.c ++++ b/tools/perf/util/machine.c +@@ -1343,7 +1343,7 @@ static int maps__set_module_path(struct maps *maps, const char *path, struct kmo + * we need to update the symtab_type if needed. + */ + if (m->comp && is_kmod_dso(dso)) { +- dso__set_symtab_type(dso, dso__symtab_type(dso)); ++ dso__set_symtab_type(dso, dso__symtab_type(dso)+1); + dso__set_comp(dso, m->comp); + } + map__put(map); +-- +2.43.0 + diff --git a/queue-6.12/perf-ftrace-latency-fix-unit-on-histogram-first-entr.patch b/queue-6.12/perf-ftrace-latency-fix-unit-on-histogram-first-entr.patch new file mode 100644 index 00000000000..8968feb7fe7 --- /dev/null +++ b/queue-6.12/perf-ftrace-latency-fix-unit-on-histogram-first-entr.patch @@ -0,0 +1,93 @@ +From 2b982bdfd6b24f39ee9bfa04d668efdbb817215f Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Tue, 29 Oct 2024 16:29:02 -0300 +Subject: perf ftrace latency: Fix unit on histogram first entry when using + --use-nsec + +From: Arnaldo Carvalho de Melo <acme@kernel.org> + +[ Upstream commit 064d569e20e82c065b1dec9d20c29c7087bb1a00 ] + +The use_nsec arg wasn't being taken into account when printing the first +histogram entry, fix it: + + root@number:~# perf ftrace latency --use-nsec -T switch_mm_irqs_off -a sleep 2 + # DURATION | COUNT | GRAPH | + 0 - 1 us | 0 | | + 1 - 2 ns | 0 | | + 2 - 4 ns | 0 | | + 4 - 8 ns | 0 | | + 8 - 16 ns | 0 | | + 16 - 32 ns | 0 | | + 32 - 64 ns | 125 | | + 64 - 128 ns | 335 | | + 128 - 256 ns | 2155 | #### | + 256 - 512 ns | 9996 | ################### | + 512 - 1024 ns | 4958 | ######### | + 1 - 2 us | 4636 | ######### | + 2 - 4 us | 1053 | ## | + 4 - 8 us | 15 | | + 8 - 16 us | 1 | | + 16 - 32 us | 0 | | + 32 - 64 us | 0 | | + 64 - 128 us | 0 | | + 128 - 256 us | 0 | | + 256 - 512 us | 0 | | + 512 - 1024 us | 0 | | + 1 - ... ms | 0 | | + root@number:~# + +After: + + root@number:~# perf ftrace latency --use-nsec -T switch_mm_irqs_off -a sleep 2 + # DURATION | COUNT | GRAPH | + 0 - 1 ns | 0 | | + 1 - 2 ns | 0 | | + 2 - 4 ns | 0 | | + 4 - 8 ns | 0 | | + 8 - 16 ns | 0 | | + 16 - 32 ns | 0 | | + 32 - 64 ns | 19 | | + 64 - 128 ns | 94 | | + 128 - 256 ns | 2191 | #### | + 256 - 512 ns | 9719 | #################### | + 512 - 1024 ns | 5330 | ########### | + 1 - 2 us | 4104 | ######## | + 2 - 4 us | 807 | # | + 4 - 8 us | 9 | | + 8 - 16 us | 0 | | + 16 - 32 us | 0 | | + 32 - 64 us | 0 | | + 64 - 128 us | 0 | | + 128 - 256 us | 0 | | + 256 - 512 us | 0 | | + 512 - 1024 us | 0 | | + 1 - ... ms | 0 | | + root@number:~# + +Fixes: 84005bb6148618cc ("perf ftrace latency: Add -n/--use-nsec option") +Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> +Cc: Gabriele Monaco <gmonaco@redhat.com> +Link: https://lore.kernel.org/r/ZyE3frB-hMXHCnMO@x1 +Signed-off-by: Namhyung Kim <namhyung@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + tools/perf/builtin-ftrace.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/tools/perf/builtin-ftrace.c b/tools/perf/builtin-ftrace.c +index abcdc49b7a987..272d3c70810e7 100644 +--- a/tools/perf/builtin-ftrace.c ++++ b/tools/perf/builtin-ftrace.c +@@ -815,7 +815,7 @@ static void display_histogram(int buckets[], bool use_nsec) + + bar_len = buckets[0] * bar_total / total; + printf(" %4d - %-4d %s | %10d | %.*s%*s |\n", +- 0, 1, "us", buckets[0], bar_len, bar, bar_total - bar_len, ""); ++ 0, 1, use_nsec ? "ns" : "us", buckets[0], bar_len, bar, bar_total - bar_len, ""); + + for (i = 1; i < NUM_BUCKET - 1; i++) { + int start = (1 << (i - 1)); +-- +2.43.0 + diff --git a/queue-6.12/perf-jevents-don-t-stop-at-the-first-matched-pmu-whe.patch b/queue-6.12/perf-jevents-don-t-stop-at-the-first-matched-pmu-whe.patch new file mode 100644 index 00000000000..0aee7cbb59a --- /dev/null +++ b/queue-6.12/perf-jevents-don-t-stop-at-the-first-matched-pmu-whe.patch @@ -0,0 +1,108 @@ +From 0ea595ddae0d8f2dab6df445b4d24f6093dabda9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Mon, 30 Sep 2024 19:14:31 -0700 +Subject: perf jevents: Don't stop at the first matched pmu when searching a + events table + +From: Kan Liang <kan.liang@linux.intel.com> + +[ Upstream commit 8d7f85e323ea402005fa83ddbdf5d00292d77098 ] + +The "perf all PMU test" fails on a Coffee Lake machine. + +The failure is caused by the below change in the commit e2641db83f18 +("perf vendor events: Add/update skylake events/metrics"). + ++ { ++ "BriefDescription": "This 48-bit fixed counter counts the UCLK cycles", ++ "Counter": "FIXED", ++ "EventCode": "0xff", ++ "EventName": "UNC_CLOCK.SOCKET", ++ "PerPkg": "1", ++ "PublicDescription": "This 48-bit fixed counter counts the UCLK cycles.", ++ "Unit": "cbox_0" + } + +The other cbox events have the unit name "CBOX", while the fixed counter +has a unit name "cbox_0". So the events_table will maintain separate +entries for cbox and cbox_0. + +The perf_pmus__print_pmu_events() calculates the total number of events, +allocate an aliases buffer, store all the events into the buffer, sort, +and print all the aliases one by one. + +The problem is that the calculated total number of events doesn't match +the stored events in the aliases buffer. + +The perf_pmu__num_events() is used to calculate the number of events. It +invokes the pmu_events_table__num_events() to go through the entire +events_table to find all events. Because of the +pmu_uncore_alias_match(), the suffix of uncore PMU will be ignored. So +the events for cbox and cbox_0 are all counted. + +When storing events into the aliases buffer, the +perf_pmu__for_each_event() only process the events for cbox. + +Since a bigger buffer was allocated, the last entry are all 0. +When printing all the aliases, null will be outputted, and trigger the +failure. + +The mismatch was introduced from the commit e3edd6cf6399 ("perf +pmu-events: Reduce processed events by passing PMU"). The +pmu_events_table__for_each_event() stops immediately once a pmu is set. +But for uncore, especially this case, the method is wrong and mismatch +what perf does in the perf_pmu__num_events(). + +With the patch, +$ perf list pmu | grep -A 1 clock.socket + unc_clock.socket + [This 48-bit fixed counter counts the UCLK cycles. Unit: uncore_cbox_0 +$ perf test "perf all PMU test" + 107: perf all PMU test : Ok + +Reported-by: kernel test robot <oliver.sang@intel.com> +Closes: https://lore.kernel.org/all/202407101021.2c8baddb-oliver.sang@intel.com/ +Fixes: e3edd6cf6399 ("perf pmu-events: Reduce processed events by passing PMU") +Signed-off-by: Kan Liang <kan.liang@linux.intel.com> +Reviewed-by: Ian Rogers <irogers@google.com> +Cc: Sandipan Das <sandipan.das@amd.com> +Cc: Benjamin Gray <bgray@linux.ibm.com> +Cc: Xu Yang <xu.yang_2@nxp.com> +Cc: John Garry <john.g.garry@oracle.com> +Link: https://lore.kernel.org/r/20241001021431.814811-1-irogers@google.com +Signed-off-by: Namhyung Kim <namhyung@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + tools/perf/pmu-events/empty-pmu-events.c | 2 +- + tools/perf/pmu-events/jevents.py | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/tools/perf/pmu-events/empty-pmu-events.c b/tools/perf/pmu-events/empty-pmu-events.c +index c592079982fbd..873e9fb2041f0 100644 +--- a/tools/perf/pmu-events/empty-pmu-events.c ++++ b/tools/perf/pmu-events/empty-pmu-events.c +@@ -380,7 +380,7 @@ int pmu_events_table__for_each_event(const struct pmu_events_table *table, + continue; + + ret = pmu_events_table__for_each_event_pmu(table, table_pmu, fn, data); +- if (pmu || ret) ++ if (ret) + return ret; + } + return 0; +diff --git a/tools/perf/pmu-events/jevents.py b/tools/perf/pmu-events/jevents.py +index bb0a5d92df4a1..d46a22fb5573d 100755 +--- a/tools/perf/pmu-events/jevents.py ++++ b/tools/perf/pmu-events/jevents.py +@@ -930,7 +930,7 @@ int pmu_events_table__for_each_event(const struct pmu_events_table *table, + continue; + + ret = pmu_events_table__for_each_event_pmu(table, table_pmu, fn, data); +- if (pmu || ret) ++ if (ret) + return ret; + } + return 0; +-- +2.43.0 + diff --git a/queue-6.12/perf-list-fix-topic-and-pmu_name-argument-order.patch b/queue-6.12/perf-list-fix-topic-and-pmu_name-argument-order.patch new file mode 100644 index 00000000000..e025ab2c2f4 --- /dev/null +++ b/queue-6.12/perf-list-fix-topic-and-pmu_name-argument-order.patch @@ -0,0 +1,171 @@ +From 99b970bb3e7bae5fcd37966b0b0b42a28d416ca2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Fri, 8 Nov 2024 18:58:01 -0800 +Subject: perf list: Fix topic and pmu_name argument order + +From: Jean-Philippe Romain <jean-philippe.romain@foss.st.com> + +[ Upstream commit d99b3125726aade4f5ec4aae04805134ab4b0abd ] + +Fix function definitions to match header file declaration. Fix two +callers to pass the arguments in the right order. + +On Intel Tigerlake, before: +``` +$ perf list -j|grep "\"Topic\""|sort|uniq + "Topic": "cache", + "Topic": "cpu", + "Topic": "floating point", + "Topic": "frontend", + "Topic": "memory", + "Topic": "other", + "Topic": "pfm icl", + "Topic": "pfm ix86arch", + "Topic": "pfm perf_raw", + "Topic": "pipeline", + "Topic": "tool", + "Topic": "uncore interconnect", + "Topic": "uncore memory", + "Topic": "uncore other", + "Topic": "virtual memory", +$ perf list -j|grep "\"Unit\""|sort|uniq + "Unit": "cache", + "Unit": "cpu", + "Unit": "cstate_core", + "Unit": "cstate_pkg", + "Unit": "i915", + "Unit": "icl", + "Unit": "intel_bts", + "Unit": "intel_pt", + "Unit": "ix86arch", + "Unit": "msr", + "Unit": "perf_raw", + "Unit": "power", + "Unit": "tool", + "Unit": "uncore_arb", + "Unit": "uncore_clock", + "Unit": "uncore_imc_free_running_0", + "Unit": "uncore_imc_free_running_1", +``` + +After: +``` +$ perf list -j|grep "\"Topic\""|sort|uniq + "Topic": "cache", + "Topic": "floating point", + "Topic": "frontend", + "Topic": "memory", + "Topic": "other", + "Topic": "pfm icl", + "Topic": "pfm ix86arch", + "Topic": "pfm perf_raw", + "Topic": "pipeline", + "Topic": "tool", + "Topic": "uncore interconnect", + "Topic": "uncore memory", + "Topic": "uncore other", + "Topic": "virtual memory", +$ perf list -j|grep "\"Unit\""|sort|uniq + "Unit": "cpu", + "Unit": "cstate_core", + "Unit": "cstate_pkg", + "Unit": "i915", + "Unit": "icl", + "Unit": "intel_bts", + "Unit": "intel_pt", + "Unit": "ix86arch", + "Unit": "msr", + "Unit": "perf_raw", + "Unit": "power", + "Unit": "tool", + "Unit": "uncore_arb", + "Unit": "uncore_clock", + "Unit": "uncore_imc_free_running_0", + "Unit": "uncore_imc_free_running_1", +``` + +Fixes: e5c6109f4813246a ("perf list: Reorganize to use callbacks to allow honouring command line options") +Reviewed-by: Kan Liang <kan.liang@linux.intel.com> +Signed-off-by: Jean-Philippe Romain <jean-philippe.romain@foss.st.com> +Tested-by: Ian Rogers <irogers@google.com> +Cc: Adrian Hunter <adrian.hunter@intel.com> +Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com> +Cc: Ingo Molnar <mingo@redhat.com> +Cc: Jiri Olsa <jolsa@kernel.org> +Cc: Junhao He <hejunhao3@huawei.com> +Cc: Mark Rutland <mark.rutland@arm.com> +Cc: Namhyung Kim <namhyung@kernel.org> +Cc: Peter Zijlstra <peterz@infradead.org> +Link: https://lore.kernel.org/r/20241109025801.560378-1-irogers@google.com +[ I fixed the two callers and added it to Jean-Phillippe's original change. ] +Signed-off-by: Ian Rogers <irogers@google.com> +Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + tools/perf/builtin-list.c | 4 ++-- + tools/perf/util/pfm.c | 4 ++-- + tools/perf/util/pmus.c | 2 +- + 3 files changed, 5 insertions(+), 5 deletions(-) + +diff --git a/tools/perf/builtin-list.c b/tools/perf/builtin-list.c +index 65b8cba324be4..c5331721dfee9 100644 +--- a/tools/perf/builtin-list.c ++++ b/tools/perf/builtin-list.c +@@ -112,7 +112,7 @@ static void wordwrap(FILE *fp, const char *s, int start, int max, int corr) + } + } + +-static void default_print_event(void *ps, const char *pmu_name, const char *topic, ++static void default_print_event(void *ps, const char *topic, const char *pmu_name, + const char *event_name, const char *event_alias, + const char *scale_unit __maybe_unused, + bool deprecated, const char *event_type_desc, +@@ -353,7 +353,7 @@ static void fix_escape_fprintf(FILE *fp, struct strbuf *buf, const char *fmt, .. + fputs(buf->buf, fp); + } + +-static void json_print_event(void *ps, const char *pmu_name, const char *topic, ++static void json_print_event(void *ps, const char *topic, const char *pmu_name, + const char *event_name, const char *event_alias, + const char *scale_unit, + bool deprecated, const char *event_type_desc, +diff --git a/tools/perf/util/pfm.c b/tools/perf/util/pfm.c +index 5ccfe4b64cdfe..0dacc133ed396 100644 +--- a/tools/perf/util/pfm.c ++++ b/tools/perf/util/pfm.c +@@ -233,7 +233,7 @@ print_libpfm_event(const struct print_callbacks *print_cb, void *print_state, + } + + if (is_libpfm_event_supported(name, cpus, threads)) { +- print_cb->print_event(print_state, pinfo->name, topic, ++ print_cb->print_event(print_state, topic, pinfo->name, + name, info->equiv, + /*scale_unit=*/NULL, + /*deprecated=*/NULL, "PFM event", +@@ -267,8 +267,8 @@ print_libpfm_event(const struct print_callbacks *print_cb, void *print_state, + continue; + + print_cb->print_event(print_state, +- pinfo->name, + topic, ++ pinfo->name, + name, /*alias=*/NULL, + /*scale_unit=*/NULL, + /*deprecated=*/NULL, "PFM event", +diff --git a/tools/perf/util/pmus.c b/tools/perf/util/pmus.c +index 52109af5f2f12..d7d67e09d759b 100644 +--- a/tools/perf/util/pmus.c ++++ b/tools/perf/util/pmus.c +@@ -494,8 +494,8 @@ void perf_pmus__print_pmu_events(const struct print_callbacks *print_cb, void *p + goto free; + + print_cb->print_event(print_state, +- aliases[j].pmu_name, + aliases[j].topic, ++ aliases[j].pmu_name, + aliases[j].name, + aliases[j].alias, + aliases[j].scale_unit, +-- +2.43.0 + diff --git a/queue-6.12/perf-mem-fix-printing-perf_mem_lvlnum_-l2_mhb-msc.patch b/queue-6.12/perf-mem-fix-printing-perf_mem_lvlnum_-l2_mhb-msc.patch new file mode 100644 index 00000000000..c79170d5013 --- /dev/null +++ b/queue-6.12/perf-mem-fix-printing-perf_mem_lvlnum_-l2_mhb-msc.patch @@ -0,0 +1,64 @@ +From 8bd869d705ca57b6d77b3445cce523ed854de6a0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Thu, 26 Sep 2024 09:40:40 -0500 +Subject: perf mem: Fix printing PERF_MEM_LVLNUM_{L2_MHB|MSC} + +From: Thomas Falcon <thomas.falcon@intel.com> + +[ Upstream commit 4f23fc34cc68812c68c3a3dec15e26e87565f430 ] + +With commit 8ec9497d3ef34 ("tools/include: Sync uapi/linux/perf.h +with the kernel sources"), 'perf mem report' gives an incorrect memory +access string. +... +0.02% 1 3644 L5 hit [.] 0x0000000000009b0e mlc [.] 0x00007fce43f59480 +... + +This occurs because, if no entry exists in mem_lvlnum, perf_mem__lvl_scnprintf +will default to 'L%d, lvl', which in this case for PERF_MEM_LVLNUM_L2_MHB is 0x05. +Add entries for PERF_MEM_LVLNUM_L2_MHB and PERF_MEM_LVLNUM_MSC to mem_lvlnum, +so that the correct strings are printed. +... +0.02% 1 3644 L2 MHB hit [.] 0x0000000000009b0e mlc [.] 0x00007fce43f59480 +... + +Fixes: 8ec9497d3ef34 ("tools/include: Sync uapi/linux/perf.h with the kernel sources") +Suggested-by: Kan Liang <kan.liang@linux.intel.com> +Signed-off-by: Thomas Falcon <thomas.falcon@intel.com> +Reviewed-by: Leo Yan <leo.yan@arm.com> +Link: https://lore.kernel.org/r/20240926144040.77897-1-thomas.falcon@intel.com +Signed-off-by: Namhyung Kim <namhyung@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + tools/perf/util/mem-events.c | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +diff --git a/tools/perf/util/mem-events.c b/tools/perf/util/mem-events.c +index 051feb93ed8d4..bf5090f5220bb 100644 +--- a/tools/perf/util/mem-events.c ++++ b/tools/perf/util/mem-events.c +@@ -366,6 +366,12 @@ static const char * const mem_lvl[] = { + }; + + static const char * const mem_lvlnum[] = { ++ [PERF_MEM_LVLNUM_L1] = "L1", ++ [PERF_MEM_LVLNUM_L2] = "L2", ++ [PERF_MEM_LVLNUM_L3] = "L3", ++ [PERF_MEM_LVLNUM_L4] = "L4", ++ [PERF_MEM_LVLNUM_L2_MHB] = "L2 MHB", ++ [PERF_MEM_LVLNUM_MSC] = "Memory-side Cache", + [PERF_MEM_LVLNUM_UNC] = "Uncached", + [PERF_MEM_LVLNUM_CXL] = "CXL", + [PERF_MEM_LVLNUM_IO] = "I/O", +@@ -448,7 +454,7 @@ int perf_mem__lvl_scnprintf(char *out, size_t sz, const struct mem_info *mem_inf + if (mem_lvlnum[lvl]) + l += scnprintf(out + l, sz - l, mem_lvlnum[lvl]); + else +- l += scnprintf(out + l, sz - l, "L%d", lvl); ++ l += scnprintf(out + l, sz - l, "Unknown level %d", lvl); + + l += scnprintf(out + l, sz - l, " %s", hit_miss); + return l; +-- +2.43.0 + diff --git a/queue-6.12/perf-probe-correct-demangled-symbols-in-c-program.patch b/queue-6.12/perf-probe-correct-demangled-symbols-in-c-program.patch new file mode 100644 index 00000000000..8f0c29ae466 --- /dev/null +++ b/queue-6.12/perf-probe-correct-demangled-symbols-in-c-program.patch @@ -0,0 +1,141 @@ +From c7def95e4717da35692014be2a0919a5eb16bffa Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Sat, 12 Oct 2024 15:14:32 +0100 +Subject: perf probe: Correct demangled symbols in C++ program + +From: Leo Yan <leo.yan@arm.com> + +[ Upstream commit 314909f13cc12d47c468602c37dace512d225eeb ] + +An issue can be observed when probe C++ demangled symbol with steps: + + # nm test_cpp_mangle | grep print_data + 0000000000000c94 t _GLOBAL__sub_I__Z10print_datai + 0000000000000afc T _Z10print_datai + 0000000000000b38 T _Z10print_dataR5Point + + # perf probe -x /home/niayan01/test_cpp_mangle -F --demangle + ... + print_data(Point&) + print_data(int) + ... + + # perf --debug verbose=3 probe -x test_cpp_mangle --add "test=print_data(int)" + probe-definition(0): test=print_data(int) + symbol:print_data(int) file:(null) line:0 offset:0 return:0 lazy:(null) + 0 arguments + Open Debuginfo file: /home/niayan01/test_cpp_mangle + Try to find probe point from debuginfo. + Symbol print_data(int) address found : afc + Matched function: print_data [2ccf] + Probe point found: print_data+0 + Found 1 probe_trace_events. + Opening /sys/kernel/tracing//uprobe_events write=1 + Opening /sys/kernel/tracing//README write=0 + Writing event: p:probe_test_cpp_mangle/test /home/niayan01/test_cpp_mangle:0xb38 + ... + +When tried to probe symbol "print_data(int)", the log shows: + + Symbol print_data(int) address found : afc + +The found address is 0xafc - which is right with verifying the output +result from nm. Afterwards when write event, the command uses offset +0xb38 in the last log, which is a wrong address. + +The dwarf_diename() gets a common function name, in above case, it +returns string "print_data". As a result, the tool parses the offset +based on the common name. This leads to probe at the wrong symbol +"print_data(Point&)". + +To fix the issue, use the die_get_linkage_name() function to retrieve +the distinct linkage name - this is the mangled name for the C++ case. +Based on this unique name, the tool can get a correct offset for +probing. Based on DWARF doc, it is possible the linkage name is missed +in the DIE, it rolls back to use dwarf_diename(). + +After: + + # perf --debug verbose=3 probe -x test_cpp_mangle --add "test=print_data(int)" + probe-definition(0): test=print_data(int) + symbol:print_data(int) file:(null) line:0 offset:0 return:0 lazy:(null) + 0 arguments + Open Debuginfo file: /home/niayan01/test_cpp_mangle + Try to find probe point from debuginfo. + Symbol print_data(int) address found : afc + Matched function: print_data [2d06] + Probe point found: print_data+0 + Found 1 probe_trace_events. + Opening /sys/kernel/tracing//uprobe_events write=1 + Opening /sys/kernel/tracing//README write=0 + Writing event: p:probe_test_cpp_mangle/test /home/niayan01/test_cpp_mangle:0xafc + Added new event: + probe_test_cpp_mangle:test (on print_data(int) in /home/niayan01/test_cpp_mangle) + + You can now use it in all perf tools, such as: + + perf record -e probe_test_cpp_mangle:test -aR sleep 1 + + # perf --debug verbose=3 probe -x test_cpp_mangle --add "test2=print_data(Point&)" + probe-definition(0): test2=print_data(Point&) + symbol:print_data(Point&) file:(null) line:0 offset:0 return:0 lazy:(null) + 0 arguments + Open Debuginfo file: /home/niayan01/test_cpp_mangle + Try to find probe point from debuginfo. + Symbol print_data(Point&) address found : b38 + Matched function: print_data [2ccf] + Probe point found: print_data+0 + Found 1 probe_trace_events. + Opening /sys/kernel/tracing//uprobe_events write=1 + Parsing probe_events: p:probe_test_cpp_mangle/test /home/niayan01/test_cpp_mangle:0x0000000000000afc + Group:probe_test_cpp_mangle Event:test probe:p + Opening /sys/kernel/tracing//README write=0 + Writing event: p:probe_test_cpp_mangle/test2 /home/niayan01/test_cpp_mangle:0xb38 + Added new event: + probe_test_cpp_mangle:test2 (on print_data(Point&) in /home/niayan01/test_cpp_mangle) + + You can now use it in all perf tools, such as: + + perf record -e probe_test_cpp_mangle:test2 -aR sleep 1 + +Fixes: fb1587d869a3 ("perf probe: List probes with line number and file name") +Signed-off-by: Leo Yan <leo.yan@arm.com> +Acked-by: Masami Hiramatsu (Google) <mhiramat@kernel.org> +Link: https://lore.kernel.org/r/20241012141432.877894-1-leo.yan@arm.com +Signed-off-by: Namhyung Kim <namhyung@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + tools/perf/util/probe-finder.c | 17 +++++++++++++++-- + 1 file changed, 15 insertions(+), 2 deletions(-) + +diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c +index d6b902899940b..a30f88ed03004 100644 +--- a/tools/perf/util/probe-finder.c ++++ b/tools/perf/util/probe-finder.c +@@ -1587,8 +1587,21 @@ int debuginfo__find_probe_point(struct debuginfo *dbg, u64 addr, + + /* Find a corresponding function (name, baseline and baseaddr) */ + if (die_find_realfunc(&cudie, (Dwarf_Addr)addr, &spdie)) { +- /* Get function entry information */ +- func = basefunc = dwarf_diename(&spdie); ++ /* ++ * Get function entry information. ++ * ++ * As described in the document DWARF Debugging Information ++ * Format Version 5, section 2.22 Linkage Names, "mangled names, ++ * are used in various ways, ... to distinguish multiple ++ * entities that have the same name". ++ * ++ * Firstly try to get distinct linkage name, if fail then ++ * rollback to get associated name in DIE. ++ */ ++ func = basefunc = die_get_linkage_name(&spdie); ++ if (!func) ++ func = basefunc = dwarf_diename(&spdie); ++ + if (!func || + die_entrypc(&spdie, &baseaddr) != 0 || + dwarf_decl_line(&spdie, &baseline) != 0) { +-- +2.43.0 + diff --git a/queue-6.12/perf-probe-fix-libdw-memory-leak.patch b/queue-6.12/perf-probe-fix-libdw-memory-leak.patch new file mode 100644 index 00000000000..52f5d8ecf3f --- /dev/null +++ b/queue-6.12/perf-probe-fix-libdw-memory-leak.patch @@ -0,0 +1,69 @@ +From 81e8d6e30524bc79b7b3fadb5a1ea95a136c1581 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Wed, 16 Oct 2024 16:56:22 -0700 +Subject: perf probe: Fix libdw memory leak + +From: Ian Rogers <irogers@google.com> + +[ Upstream commit 4585038b8e186252141ef86e9f0d8e97f11dce8d ] + +Add missing dwarf_cfi_end to free memory associated with probe_finder +cfi_eh which is allocated and owned via a call to +dwarf_getcfi_elf. Confusingly cfi_dbg shouldn't be freed as its memory +is owned by the passed in debuginfo struct. Add comments to highlight +this. + +This addresses leak sanitizer issues seen in: +tools/perf/tests/shell/test_uprobe_from_different_cu.sh + +Fixes: 270bde1e76f4 ("perf probe: Search both .eh_frame and .debug_frame sections for probe location") +Signed-off-by: Ian Rogers <irogers@google.com> +Cc: David S. Miller <davem@davemloft.net> +Cc: Steinar H. Gunderson <sesse@google.com> +Cc: Alexander Lobakin <aleksander.lobakin@intel.com> +Cc: Masami Hiramatsu (Google) <mhiramat@kernel.org> +Cc: Kajol Jain <kjain@linux.ibm.com> +Cc: Athira Rajeev <atrajeev@linux.vnet.ibm.com> +Cc: Hemant Kumar <hemant@linux.vnet.ibm.com> +Link: https://lore.kernel.org/r/20241016235622.52166-3-irogers@google.com +Signed-off-by: Namhyung Kim <namhyung@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + tools/perf/util/probe-finder.c | 4 ++++ + tools/perf/util/probe-finder.h | 4 ++-- + 2 files changed, 6 insertions(+), 2 deletions(-) + +diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c +index 630e16c54ed5c..d6b902899940b 100644 +--- a/tools/perf/util/probe-finder.c ++++ b/tools/perf/util/probe-finder.c +@@ -1379,6 +1379,10 @@ int debuginfo__find_trace_events(struct debuginfo *dbg, + if (ret >= 0 && tf.pf.skip_empty_arg) + ret = fill_empty_trace_arg(pev, tf.tevs, tf.ntevs); + ++#if _ELFUTILS_PREREQ(0, 142) ++ dwarf_cfi_end(tf.pf.cfi_eh); ++#endif ++ + if (ret < 0 || tf.ntevs == 0) { + for (i = 0; i < tf.ntevs; i++) + clear_probe_trace_event(&tf.tevs[i]); +diff --git a/tools/perf/util/probe-finder.h b/tools/perf/util/probe-finder.h +index 3add5ff516e12..724db829b49e0 100644 +--- a/tools/perf/util/probe-finder.h ++++ b/tools/perf/util/probe-finder.h +@@ -64,9 +64,9 @@ struct probe_finder { + + /* For variable searching */ + #if _ELFUTILS_PREREQ(0, 142) +- /* Call Frame Information from .eh_frame */ ++ /* Call Frame Information from .eh_frame. Owned by this struct. */ + Dwarf_CFI *cfi_eh; +- /* Call Frame Information from .debug_frame */ ++ /* Call Frame Information from .debug_frame. Not owned. */ + Dwarf_CFI *cfi_dbg; + #endif + Dwarf_Op *fb_ops; /* Frame base attribute */ +-- +2.43.0 + diff --git a/queue-6.12/perf-stat-close-cork_fd-when-create_perf_stat_counte.patch b/queue-6.12/perf-stat-close-cork_fd-when-create_perf_stat_counte.patch new file mode 100644 index 00000000000..56d74179e26 --- /dev/null +++ b/queue-6.12/perf-stat-close-cork_fd-when-create_perf_stat_counte.patch @@ -0,0 +1,236 @@ +From 1cfa6d076e039ffa753e2329cad9239108e6f8b1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Wed, 25 Sep 2024 14:20:21 +0100 +Subject: perf stat: Close cork_fd when create_perf_stat_counter() failed + +From: Levi Yun <yeoreum.yun@arm.com> + +[ Upstream commit e880a70f8046df0dd9089fa60dcb866a2cc69194 ] + +When create_perf_stat_counter() failed, it doesn't close workload.cork_fd +open in evlist__prepare_workload(). This could make too many open file +error while __run_perf_stat() repeats. + +Introduce evlist__cancel_workload to close workload.cork_fd and +wait workload.child_pid until exit to clear child process +when create_perf_stat_counter() is failed. + +Signed-off-by: Levi Yun <yeoreum.yun@arm.com> +Reviewed-by: James Clark <james.clark@linaro.org> +Reviewed-by: Andi Kleen <ak@linux.intel.com> +Cc: nd@arm.com +Cc: howardchu95@gmail.com +Link: https://lore.kernel.org/r/20240925132022.2650180-2-yeoreum.yun@arm.com +Signed-off-by: Namhyung Kim <namhyung@kernel.org> +Stable-dep-of: 7f6ccb70e465 ("perf stat: Fix affinity memory leaks on error path") +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + tools/perf/builtin-stat.c | 50 +++++++++++++++++++++++++++------------ + tools/perf/util/evlist.c | 19 +++++++++++++-- + tools/perf/util/evlist.h | 1 + + 3 files changed, 53 insertions(+), 17 deletions(-) + +diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c +index 689a3d43c2584..2c46bdbd9914d 100644 +--- a/tools/perf/builtin-stat.c ++++ b/tools/perf/builtin-stat.c +@@ -716,15 +716,19 @@ static int __run_perf_stat(int argc, const char **argv, int run_idx) + } + + if (!cpu_map__is_dummy(evsel_list->core.user_requested_cpus)) { +- if (affinity__setup(&saved_affinity) < 0) +- return -1; ++ if (affinity__setup(&saved_affinity) < 0) { ++ err = -1; ++ goto err_out; ++ } + affinity = &saved_affinity; + } + + evlist__for_each_entry(evsel_list, counter) { + counter->reset_group = false; +- if (bpf_counter__load(counter, &target)) +- return -1; ++ if (bpf_counter__load(counter, &target)) { ++ err = -1; ++ goto err_out; ++ } + if (!(evsel__is_bperf(counter))) + all_counters_use_bpf = false; + } +@@ -767,7 +771,8 @@ static int __run_perf_stat(int argc, const char **argv, int run_idx) + + switch (stat_handle_error(counter)) { + case COUNTER_FATAL: +- return -1; ++ err = -1; ++ goto err_out; + case COUNTER_RETRY: + goto try_again; + case COUNTER_SKIP: +@@ -808,7 +813,8 @@ static int __run_perf_stat(int argc, const char **argv, int run_idx) + + switch (stat_handle_error(counter)) { + case COUNTER_FATAL: +- return -1; ++ err = -1; ++ goto err_out; + case COUNTER_RETRY: + goto try_again_reset; + case COUNTER_SKIP: +@@ -833,8 +839,10 @@ static int __run_perf_stat(int argc, const char **argv, int run_idx) + stat_config.unit_width = l; + + if (evsel__should_store_id(counter) && +- evsel__store_ids(counter, evsel_list)) +- return -1; ++ evsel__store_ids(counter, evsel_list)) { ++ err = -1; ++ goto err_out; ++ } + } + + if (evlist__apply_filters(evsel_list, &counter, &target)) { +@@ -855,20 +863,23 @@ static int __run_perf_stat(int argc, const char **argv, int run_idx) + } + + if (err < 0) +- return err; ++ goto err_out; + + err = perf_event__synthesize_stat_events(&stat_config, NULL, evsel_list, + process_synthesized_event, is_pipe); + if (err < 0) +- return err; ++ goto err_out; ++ + } + + if (target.initial_delay) { + pr_info(EVLIST_DISABLED_MSG); + } else { + err = enable_counters(); +- if (err) +- return -1; ++ if (err) { ++ err = -1; ++ goto err_out; ++ } + } + + /* Exec the command, if any */ +@@ -878,8 +889,10 @@ static int __run_perf_stat(int argc, const char **argv, int run_idx) + if (target.initial_delay > 0) { + usleep(target.initial_delay * USEC_PER_MSEC); + err = enable_counters(); +- if (err) +- return -1; ++ if (err) { ++ err = -1; ++ goto err_out; ++ } + + pr_info(EVLIST_ENABLED_MSG); + } +@@ -899,7 +912,8 @@ static int __run_perf_stat(int argc, const char **argv, int run_idx) + if (workload_exec_errno) { + const char *emsg = str_error_r(workload_exec_errno, msg, sizeof(msg)); + pr_err("Workload failed: %s\n", emsg); +- return -1; ++ err = -1; ++ goto err_out; + } + + if (WIFSIGNALED(status)) +@@ -946,6 +960,12 @@ static int __run_perf_stat(int argc, const char **argv, int run_idx) + evlist__close(evsel_list); + + return WEXITSTATUS(status); ++ ++err_out: ++ if (forks) ++ evlist__cancel_workload(evsel_list); ++ ++ return err; + } + + static int run_perf_stat(int argc, const char **argv, int run_idx) +diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c +index f14b7e6ff1dcc..a9df84692d4a8 100644 +--- a/tools/perf/util/evlist.c ++++ b/tools/perf/util/evlist.c +@@ -48,6 +48,7 @@ + #include <sys/mman.h> + #include <sys/prctl.h> + #include <sys/timerfd.h> ++#include <sys/wait.h> + + #include <linux/bitops.h> + #include <linux/hash.h> +@@ -1484,6 +1485,8 @@ int evlist__prepare_workload(struct evlist *evlist, struct target *target, const + int child_ready_pipe[2], go_pipe[2]; + char bf; + ++ evlist->workload.cork_fd = -1; ++ + if (pipe(child_ready_pipe) < 0) { + perror("failed to create 'ready' pipe"); + return -1; +@@ -1536,7 +1539,7 @@ int evlist__prepare_workload(struct evlist *evlist, struct target *target, const + * For cancelling the workload without actually running it, + * the parent will just close workload.cork_fd, without writing + * anything, i.e. read will return zero and we just exit() +- * here. ++ * here (See evlist__cancel_workload()). + */ + if (ret != 1) { + if (ret == -1) +@@ -1600,7 +1603,7 @@ int evlist__prepare_workload(struct evlist *evlist, struct target *target, const + + int evlist__start_workload(struct evlist *evlist) + { +- if (evlist->workload.cork_fd > 0) { ++ if (evlist->workload.cork_fd >= 0) { + char bf = 0; + int ret; + /* +@@ -1611,12 +1614,24 @@ int evlist__start_workload(struct evlist *evlist) + perror("unable to write to pipe"); + + close(evlist->workload.cork_fd); ++ evlist->workload.cork_fd = -1; + return ret; + } + + return 0; + } + ++void evlist__cancel_workload(struct evlist *evlist) ++{ ++ int status; ++ ++ if (evlist->workload.cork_fd >= 0) { ++ close(evlist->workload.cork_fd); ++ evlist->workload.cork_fd = -1; ++ waitpid(evlist->workload.pid, &status, WNOHANG); ++ } ++} ++ + int evlist__parse_sample(struct evlist *evlist, union perf_event *event, struct perf_sample *sample) + { + struct evsel *evsel = evlist__event2evsel(evlist, event); +diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h +index bcc1c6984bb58..888fda751e1a6 100644 +--- a/tools/perf/util/evlist.h ++++ b/tools/perf/util/evlist.h +@@ -186,6 +186,7 @@ int evlist__prepare_workload(struct evlist *evlist, struct target *target, + const char *argv[], bool pipe_output, + void (*exec_error)(int signo, siginfo_t *info, void *ucontext)); + int evlist__start_workload(struct evlist *evlist); ++void evlist__cancel_workload(struct evlist *evlist); + + struct option; + +-- +2.43.0 + diff --git a/queue-6.12/perf-stat-fix-affinity-memory-leaks-on-error-path.patch b/queue-6.12/perf-stat-fix-affinity-memory-leaks-on-error-path.patch new file mode 100644 index 00000000000..5cdf68c1d47 --- /dev/null +++ b/queue-6.12/perf-stat-fix-affinity-memory-leaks-on-error-path.patch @@ -0,0 +1,43 @@ +From 0f0b0e213df06a339f57ca9b3bd3d7abe8b587db Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Mon, 30 Sep 2024 22:23:24 -0700 +Subject: perf stat: Fix affinity memory leaks on error path + +From: Ian Rogers <irogers@google.com> + +[ Upstream commit 7f6ccb70e465bd8c9cf8973aee1c01224e4bdb3c ] + +Missed cleanup when an error occurs. + +Fixes: 49de179577e7 ("perf stat: No need to setup affinities when starting a workload") +Signed-off-by: Ian Rogers <irogers@google.com> +Link: https://lore.kernel.org/r/20241001052327.7052-2-irogers@google.com +Signed-off-by: Namhyung Kim <namhyung@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + tools/perf/builtin-stat.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c +index 2c46bdbd9914d..4933efdfee76f 100644 +--- a/tools/perf/builtin-stat.c ++++ b/tools/perf/builtin-stat.c +@@ -827,6 +827,7 @@ static int __run_perf_stat(int argc, const char **argv, int run_idx) + } + } + affinity__cleanup(affinity); ++ affinity = NULL; + + evlist__for_each_entry(evsel_list, counter) { + if (!counter->supported) { +@@ -965,6 +966,7 @@ static int __run_perf_stat(int argc, const char **argv, int run_idx) + if (forks) + evlist__cancel_workload(evsel_list); + ++ affinity__cleanup(affinity); + return err; + } + +-- +2.43.0 + diff --git a/queue-6.12/perf-stat-uniquify-event-name-improvements.patch b/queue-6.12/perf-stat-uniquify-event-name-improvements.patch new file mode 100644 index 00000000000..3bcdce8d991 --- /dev/null +++ b/queue-6.12/perf-stat-uniquify-event-name-improvements.patch @@ -0,0 +1,226 @@ +From a8aeee21dbbd14582e783f2d2a42728eb53ef0d6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Thu, 26 Sep 2024 15:48:33 +0100 +Subject: perf stat: Uniquify event name improvements + +From: Ian Rogers <irogers@google.com> + +[ Upstream commit 057f8bfc6f7070577523d1e3081081bbf4229c1c ] + +Without aggregation on Intel: +``` +$ perf stat -e instructions,cycles ... +``` +Will use "cycles" for the name of the legacy cycles event but as +"instructions" has a sysfs name it will and a "[cpu]" PMU suffix. This +often breaks things as the space between the event and the PMU name +look like an extra column. The existing uniquify logic was also +uniquifying in cases when all events are core and not with uncore +events, it was not correctly handling modifiers, etc. + +Change the logic so that an initial pass that can disable +uniquification is run. For individual counters, disable uniquification +in more cases such as for consistency with legacy events or for +libpfm4 events. Don't use the "[pmu]" style suffix in uniquification, +always use "pmu/.../". Change how modifiers/terms are handled in the +uniquification so that they look like parse-able events. + +This fixes "102: perf stat metrics (shadow stat) test:" that has been +failing due to "instructions [cpu]" breaking its column/awk logic when +values aren't aggregated. This started happening when instructions +could match a sysfs rather than a legacy event, so the fixes tag +reflects this. + +Fixes: 617824a7f0f7 ("perf parse-events: Prefer sysfs/JSON hardware events over legacy") +Acked-by: Namhyung Kim <namhyung@kernel.org> +Signed-off-by: Ian Rogers <irogers@google.com> +[ Fix Intel TPEBS counting mode test ] +Acked-by: Kan Liang <kan.liang@linux.intel.com> +Signed-off-by: James Clark <james.clark@linaro.org> +Cc: Yang Jihong <yangjihong@bytedance.com> +Cc: Dominique Martinet <asmadeus@codewreck.org> +Cc: Colin Ian King <colin.i.king@gmail.com> +Cc: Howard Chu <howardchu95@gmail.com> +Cc: Ze Gao <zegao2021@gmail.com> +Cc: Yicong Yang <yangyicong@hisilicon.com> +Cc: Weilin Wang <weilin.wang@intel.com> +Cc: Will Deacon <will@kernel.org> +Cc: Mike Leach <mike.leach@linaro.org> +Cc: Jing Zhang <renyu.zj@linux.alibaba.com> +Cc: Yang Li <yang.lee@linux.alibaba.com> +Cc: Leo Yan <leo.yan@linux.dev> +Cc: ak@linux.intel.com +Cc: Athira Rajeev <atrajeev@linux.vnet.ibm.com> +Cc: linux-arm-kernel@lists.infradead.org +Cc: Sun Haiyong <sunhaiyong@loongson.cn> +Cc: John Garry <john.g.garry@oracle.com> +Link: https://lore.kernel.org/r/20240926144851.245903-3-james.clark@linaro.org +Signed-off-by: Namhyung Kim <namhyung@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + .../perf/tests/shell/test_stat_intel_tpebs.sh | 11 +- + tools/perf/util/stat-display.c | 101 ++++++++++++++---- + 2 files changed, 85 insertions(+), 27 deletions(-) + +diff --git a/tools/perf/tests/shell/test_stat_intel_tpebs.sh b/tools/perf/tests/shell/test_stat_intel_tpebs.sh +index c60b29add9801..9a11f42d153ca 100755 +--- a/tools/perf/tests/shell/test_stat_intel_tpebs.sh ++++ b/tools/perf/tests/shell/test_stat_intel_tpebs.sh +@@ -8,12 +8,15 @@ grep -q GenuineIntel /proc/cpuinfo || { echo Skipping non-Intel; exit 2; } + # Use this event for testing because it should exist in all platforms + event=cache-misses:R + ++# Hybrid platforms output like "cpu_atom/cache-misses/R", rather than as above ++alt_name=/cache-misses/R ++ + # Without this cmd option, default value or zero is returned +-echo "Testing without --record-tpebs" +-result=$(perf stat -e "$event" true 2>&1) +-[[ "$result" =~ $event ]] || exit 1 ++#echo "Testing without --record-tpebs" ++#result=$(perf stat -e "$event" true 2>&1) ++#[[ "$result" =~ $event || "$result" =~ $alt_name ]] || exit 1 + + # In platforms that do not support TPEBS, it should execute without error. + echo "Testing with --record-tpebs" + result=$(perf stat -e "$event" --record-tpebs -a sleep 0.01 2>&1) +-[[ "$result" =~ "perf record" && "$result" =~ $event ]] || exit 1 ++[[ "$result" =~ "perf record" && "$result" =~ $event || "$result" =~ $alt_name ]] || exit 1 +diff --git a/tools/perf/util/stat-display.c b/tools/perf/util/stat-display.c +index ea96e4ebad8c8..cbff43ff8d0fb 100644 +--- a/tools/perf/util/stat-display.c ++++ b/tools/perf/util/stat-display.c +@@ -871,38 +871,66 @@ static void printout(struct perf_stat_config *config, struct outstate *os, + + static void uniquify_event_name(struct evsel *counter) + { +- char *new_name; +- char *config; +- int ret = 0; ++ const char *name, *pmu_name; ++ char *new_name, *config; ++ int ret; + +- if (counter->uniquified_name || counter->use_config_name || +- !counter->pmu_name || !strncmp(evsel__name(counter), counter->pmu_name, +- strlen(counter->pmu_name))) ++ /* The evsel was already uniquified. */ ++ if (counter->uniquified_name) + return; + +- config = strchr(counter->name, '/'); ++ /* Avoid checking to uniquify twice. */ ++ counter->uniquified_name = true; ++ ++ /* The evsel has a "name=" config term or is from libpfm. */ ++ if (counter->use_config_name || counter->is_libpfm_event) ++ return; ++ ++ /* Legacy no PMU event, don't uniquify. */ ++ if (!counter->pmu || ++ (counter->pmu->type < PERF_TYPE_MAX && counter->pmu->type != PERF_TYPE_RAW)) ++ return; ++ ++ /* A sysfs or json event replacing a legacy event, don't uniquify. */ ++ if (counter->pmu->is_core && counter->alternate_hw_config != PERF_COUNT_HW_MAX) ++ return; ++ ++ name = evsel__name(counter); ++ pmu_name = counter->pmu->name; ++ /* Already prefixed by the PMU name. */ ++ if (!strncmp(name, pmu_name, strlen(pmu_name))) ++ return; ++ ++ config = strchr(name, '/'); + if (config) { +- if (asprintf(&new_name, +- "%s%s", counter->pmu_name, config) > 0) { +- free(counter->name); +- counter->name = new_name; +- } +- } else { +- if (evsel__is_hybrid(counter)) { +- ret = asprintf(&new_name, "%s/%s/", +- counter->pmu_name, counter->name); ++ int len = config - name; ++ ++ if (config[1] == '/') { ++ /* case: event// */ ++ ret = asprintf(&new_name, "%s/%.*s/%s", pmu_name, len, name, config + 2); + } else { +- ret = asprintf(&new_name, "%s [%s]", +- counter->name, counter->pmu_name); ++ /* case: event/.../ */ ++ ret = asprintf(&new_name, "%s/%.*s,%s", pmu_name, len, name, config + 1); + } ++ } else { ++ config = strchr(name, ':'); ++ if (config) { ++ /* case: event:.. */ ++ int len = config - name; + +- if (ret) { +- free(counter->name); +- counter->name = new_name; ++ ret = asprintf(&new_name, "%s/%.*s/%s", pmu_name, len, name, config + 1); ++ } else { ++ /* case: event */ ++ ret = asprintf(&new_name, "%s/%s/", pmu_name, name); + } + } +- +- counter->uniquified_name = true; ++ if (ret > 0) { ++ free(counter->name); ++ counter->name = new_name; ++ } else { ++ /* ENOMEM from asprintf. */ ++ counter->uniquified_name = false; ++ } + } + + static bool hybrid_uniquify(struct evsel *evsel, struct perf_stat_config *config) +@@ -1559,6 +1587,31 @@ static void print_cgroup_counter(struct perf_stat_config *config, struct evlist + print_metric_end(config, os); + } + ++static void disable_uniquify(struct evlist *evlist) ++{ ++ struct evsel *counter; ++ struct perf_pmu *last_pmu = NULL; ++ bool first = true; ++ ++ evlist__for_each_entry(evlist, counter) { ++ /* If PMUs vary then uniquify can be useful. */ ++ if (!first && counter->pmu != last_pmu) ++ return; ++ first = false; ++ if (counter->pmu) { ++ /* Allow uniquify for uncore PMUs. */ ++ if (!counter->pmu->is_core) ++ return; ++ /* Keep hybrid event names uniquified for clarity. */ ++ if (perf_pmus__num_core_pmus() > 1) ++ return; ++ } ++ } ++ evlist__for_each_entry_continue(evlist, counter) { ++ counter->uniquified_name = true; ++ } ++} ++ + void evlist__print_counters(struct evlist *evlist, struct perf_stat_config *config, + struct target *_target, struct timespec *ts, + int argc, const char **argv) +@@ -1572,6 +1625,8 @@ void evlist__print_counters(struct evlist *evlist, struct perf_stat_config *conf + .first = true, + }; + ++ disable_uniquify(evlist); ++ + if (config->iostat_run) + evlist->selected = evlist__first(evlist); + +-- +2.43.0 + diff --git a/queue-6.12/perf-test-attr-add-back-missing-topdown-events.patch b/queue-6.12/perf-test-attr-add-back-missing-topdown-events.patch new file mode 100644 index 00000000000..4db93e5a893 --- /dev/null +++ b/queue-6.12/perf-test-attr-add-back-missing-topdown-events.patch @@ -0,0 +1,1005 @@ +From e8fe1968837d38d0a155f8d8a80c67efdfc1f37f Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Mon, 11 Mar 2024 09:16:11 +0100 +Subject: perf test attr: Add back missing topdown events + +From: Veronika Molnarova <vmolnaro@redhat.com> + +[ Upstream commit 6bff76af9635411214ca44ea38fc2781e78064b6 ] + +With the patch 0b6c5371c03c "Add missing topdown metrics events" eight +topdown metric events with numbers ranging from 0x8000 to 0x8700 were +added to the test since they were added as 'perf stat' default events. +Later the patch 951efb9976ce "Update no event/metric expectations" kept +only 4 of those events(0x8000-0x8300). + +Currently, the topdown events with numbers 0x8400 to 0x8700 are missing +from the list of expected events resulting in a failure. Add back the +missing topdown events. + +Fixes: 951efb9976ce ("perf test attr: Update no event/metric expectations") +Signed-off-by: Veronika Molnarova <vmolnaro@redhat.com> +Tested-by: Ian Rogers <irogers@google.com> +Cc: mpetlan@redhat.com +Link: https://lore.kernel.org/r/20240311081611.7835-1-vmolnaro@redhat.com +Signed-off-by: Namhyung Kim <namhyung@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + tools/perf/tests/attr/test-stat-default | 90 ++++++++++---- + tools/perf/tests/attr/test-stat-detailed-1 | 106 +++++++++++----- + tools/perf/tests/attr/test-stat-detailed-2 | 130 ++++++++++++------- + tools/perf/tests/attr/test-stat-detailed-3 | 138 ++++++++++++++------- + 4 files changed, 320 insertions(+), 144 deletions(-) + +diff --git a/tools/perf/tests/attr/test-stat-default b/tools/perf/tests/attr/test-stat-default +index a1e2da0a9a6dd..e47fb49446799 100644 +--- a/tools/perf/tests/attr/test-stat-default ++++ b/tools/perf/tests/attr/test-stat-default +@@ -88,98 +88,142 @@ enable_on_exec=0 + read_format=15 + optional=1 + +-# PERF_TYPE_RAW / topdown-fe-bound (0x8200) ++# PERF_TYPE_RAW / topdown-bad-spec (0x8100) + [event13:base-stat] + fd=13 + group_fd=11 + type=4 +-config=33280 ++config=33024 + disabled=0 + enable_on_exec=0 + read_format=15 + optional=1 + +-# PERF_TYPE_RAW / topdown-be-bound (0x8300) ++# PERF_TYPE_RAW / topdown-fe-bound (0x8200) + [event14:base-stat] + fd=14 + group_fd=11 + type=4 +-config=33536 ++config=33280 + disabled=0 + enable_on_exec=0 + read_format=15 + optional=1 + +-# PERF_TYPE_RAW / topdown-bad-spec (0x8100) ++# PERF_TYPE_RAW / topdown-be-bound (0x8300) + [event15:base-stat] + fd=15 + group_fd=11 + type=4 +-config=33024 ++config=33536 + disabled=0 + enable_on_exec=0 + read_format=15 + optional=1 + +-# PERF_TYPE_RAW / INT_MISC.UOP_DROPPING ++# PERF_TYPE_RAW / topdown-heavy-ops (0x8400) + [event16:base-stat] + fd=16 ++group_fd=11 + type=4 +-config=4109 ++config=33792 ++disabled=0 ++enable_on_exec=0 ++read_format=15 + optional=1 + +-# PERF_TYPE_RAW / cpu/INT_MISC.RECOVERY_CYCLES,cmask=1,edge/ ++# PERF_TYPE_RAW / topdown-br-mispredict (0x8500) + [event17:base-stat] + fd=17 ++group_fd=11 + type=4 +-config=17039629 ++config=34048 ++disabled=0 ++enable_on_exec=0 ++read_format=15 + optional=1 + +-# PERF_TYPE_RAW / CPU_CLK_UNHALTED.THREAD ++# PERF_TYPE_RAW / topdown-fetch-lat (0x8600) + [event18:base-stat] + fd=18 ++group_fd=11 + type=4 +-config=60 ++config=34304 ++disabled=0 ++enable_on_exec=0 ++read_format=15 + optional=1 + +-# PERF_TYPE_RAW / INT_MISC.RECOVERY_CYCLES_ANY ++# PERF_TYPE_RAW / topdown-mem-bound (0x8700) + [event19:base-stat] + fd=19 ++group_fd=11 + type=4 +-config=2097421 ++config=34560 ++disabled=0 ++enable_on_exec=0 ++read_format=15 + optional=1 + +-# PERF_TYPE_RAW / CPU_CLK_UNHALTED.REF_XCLK ++# PERF_TYPE_RAW / INT_MISC.UOP_DROPPING + [event20:base-stat] + fd=20 + type=4 +-config=316 ++config=4109 + optional=1 + +-# PERF_TYPE_RAW / IDQ_UOPS_NOT_DELIVERED.CORE ++# PERF_TYPE_RAW / cpu/INT_MISC.RECOVERY_CYCLES,cmask=1,edge/ + [event21:base-stat] + fd=21 + type=4 +-config=412 ++config=17039629 + optional=1 + +-# PERF_TYPE_RAW / CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE ++# PERF_TYPE_RAW / CPU_CLK_UNHALTED.THREAD + [event22:base-stat] + fd=22 + type=4 +-config=572 ++config=60 + optional=1 + +-# PERF_TYPE_RAW / UOPS_RETIRED.RETIRE_SLOTS ++# PERF_TYPE_RAW / INT_MISC.RECOVERY_CYCLES_ANY + [event23:base-stat] + fd=23 + type=4 +-config=706 ++config=2097421 + optional=1 + +-# PERF_TYPE_RAW / UOPS_ISSUED.ANY ++# PERF_TYPE_RAW / CPU_CLK_UNHALTED.REF_XCLK + [event24:base-stat] + fd=24 + type=4 ++config=316 ++optional=1 ++ ++# PERF_TYPE_RAW / IDQ_UOPS_NOT_DELIVERED.CORE ++[event25:base-stat] ++fd=25 ++type=4 ++config=412 ++optional=1 ++ ++# PERF_TYPE_RAW / CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE ++[event26:base-stat] ++fd=26 ++type=4 ++config=572 ++optional=1 ++ ++# PERF_TYPE_RAW / UOPS_RETIRED.RETIRE_SLOTS ++[event27:base-stat] ++fd=27 ++type=4 ++config=706 ++optional=1 ++ ++# PERF_TYPE_RAW / UOPS_ISSUED.ANY ++[event28:base-stat] ++fd=28 ++type=4 + config=270 + optional=1 +diff --git a/tools/perf/tests/attr/test-stat-detailed-1 b/tools/perf/tests/attr/test-stat-detailed-1 +index 1c52cb05c900d..3d500d3e0c5c8 100644 +--- a/tools/perf/tests/attr/test-stat-detailed-1 ++++ b/tools/perf/tests/attr/test-stat-detailed-1 +@@ -90,99 +90,143 @@ enable_on_exec=0 + read_format=15 + optional=1 + +-# PERF_TYPE_RAW / topdown-fe-bound (0x8200) ++# PERF_TYPE_RAW / topdown-bad-spec (0x8100) + [event13:base-stat] + fd=13 + group_fd=11 + type=4 +-config=33280 ++config=33024 + disabled=0 + enable_on_exec=0 + read_format=15 + optional=1 + +-# PERF_TYPE_RAW / topdown-be-bound (0x8300) ++# PERF_TYPE_RAW / topdown-fe-bound (0x8200) + [event14:base-stat] + fd=14 + group_fd=11 + type=4 +-config=33536 ++config=33280 + disabled=0 + enable_on_exec=0 + read_format=15 + optional=1 + +-# PERF_TYPE_RAW / topdown-bad-spec (0x8100) ++# PERF_TYPE_RAW / topdown-be-bound (0x8300) + [event15:base-stat] + fd=15 + group_fd=11 + type=4 +-config=33024 ++config=33536 + disabled=0 + enable_on_exec=0 + read_format=15 + optional=1 + +-# PERF_TYPE_RAW / INT_MISC.UOP_DROPPING ++# PERF_TYPE_RAW / topdown-heavy-ops (0x8400) + [event16:base-stat] + fd=16 ++group_fd=11 + type=4 +-config=4109 ++config=33792 ++disabled=0 ++enable_on_exec=0 ++read_format=15 + optional=1 + +-# PERF_TYPE_RAW / cpu/INT_MISC.RECOVERY_CYCLES,cmask=1,edge/ ++# PERF_TYPE_RAW / topdown-br-mispredict (0x8500) + [event17:base-stat] + fd=17 ++group_fd=11 + type=4 +-config=17039629 ++config=34048 ++disabled=0 ++enable_on_exec=0 ++read_format=15 + optional=1 + +-# PERF_TYPE_RAW / CPU_CLK_UNHALTED.THREAD ++# PERF_TYPE_RAW / topdown-fetch-lat (0x8600) + [event18:base-stat] + fd=18 ++group_fd=11 + type=4 +-config=60 ++config=34304 ++disabled=0 ++enable_on_exec=0 ++read_format=15 + optional=1 + +-# PERF_TYPE_RAW / INT_MISC.RECOVERY_CYCLES_ANY ++# PERF_TYPE_RAW / topdown-mem-bound (0x8700) + [event19:base-stat] + fd=19 ++group_fd=11 + type=4 +-config=2097421 ++config=34560 ++disabled=0 ++enable_on_exec=0 ++read_format=15 + optional=1 + +-# PERF_TYPE_RAW / CPU_CLK_UNHALTED.REF_XCLK ++# PERF_TYPE_RAW / INT_MISC.UOP_DROPPING + [event20:base-stat] + fd=20 + type=4 +-config=316 ++config=4109 + optional=1 + +-# PERF_TYPE_RAW / IDQ_UOPS_NOT_DELIVERED.CORE ++# PERF_TYPE_RAW / cpu/INT_MISC.RECOVERY_CYCLES,cmask=1,edge/ + [event21:base-stat] + fd=21 + type=4 +-config=412 ++config=17039629 + optional=1 + +-# PERF_TYPE_RAW / CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE ++# PERF_TYPE_RAW / CPU_CLK_UNHALTED.THREAD + [event22:base-stat] + fd=22 + type=4 +-config=572 ++config=60 + optional=1 + +-# PERF_TYPE_RAW / UOPS_RETIRED.RETIRE_SLOTS ++# PERF_TYPE_RAW / INT_MISC.RECOVERY_CYCLES_ANY + [event23:base-stat] + fd=23 + type=4 +-config=706 ++config=2097421 + optional=1 + +-# PERF_TYPE_RAW / UOPS_ISSUED.ANY ++# PERF_TYPE_RAW / CPU_CLK_UNHALTED.REF_XCLK + [event24:base-stat] + fd=24 + type=4 ++config=316 ++optional=1 ++ ++# PERF_TYPE_RAW / IDQ_UOPS_NOT_DELIVERED.CORE ++[event25:base-stat] ++fd=25 ++type=4 ++config=412 ++optional=1 ++ ++# PERF_TYPE_RAW / CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE ++[event26:base-stat] ++fd=26 ++type=4 ++config=572 ++optional=1 ++ ++# PERF_TYPE_RAW / UOPS_RETIRED.RETIRE_SLOTS ++[event27:base-stat] ++fd=27 ++type=4 ++config=706 ++optional=1 ++ ++# PERF_TYPE_RAW / UOPS_ISSUED.ANY ++[event28:base-stat] ++fd=28 ++type=4 + config=270 + optional=1 + +@@ -190,8 +234,8 @@ optional=1 + # PERF_COUNT_HW_CACHE_L1D << 0 | + # (PERF_COUNT_HW_CACHE_OP_READ << 8) | + # (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16) +-[event25:base-stat] +-fd=25 ++[event29:base-stat] ++fd=29 + type=3 + config=0 + optional=1 +@@ -200,8 +244,8 @@ optional=1 + # PERF_COUNT_HW_CACHE_L1D << 0 | + # (PERF_COUNT_HW_CACHE_OP_READ << 8) | + # (PERF_COUNT_HW_CACHE_RESULT_MISS << 16) +-[event26:base-stat] +-fd=26 ++[event30:base-stat] ++fd=30 + type=3 + config=65536 + optional=1 +@@ -210,8 +254,8 @@ optional=1 + # PERF_COUNT_HW_CACHE_LL << 0 | + # (PERF_COUNT_HW_CACHE_OP_READ << 8) | + # (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16) +-[event27:base-stat] +-fd=27 ++[event31:base-stat] ++fd=31 + type=3 + config=2 + optional=1 +@@ -220,8 +264,8 @@ optional=1 + # PERF_COUNT_HW_CACHE_LL << 0 | + # (PERF_COUNT_HW_CACHE_OP_READ << 8) | + # (PERF_COUNT_HW_CACHE_RESULT_MISS << 16) +-[event28:base-stat] +-fd=28 ++[event32:base-stat] ++fd=32 + type=3 + config=65538 + optional=1 +diff --git a/tools/perf/tests/attr/test-stat-detailed-2 b/tools/perf/tests/attr/test-stat-detailed-2 +index 7e961d24a885a..01777a63752fe 100644 +--- a/tools/perf/tests/attr/test-stat-detailed-2 ++++ b/tools/perf/tests/attr/test-stat-detailed-2 +@@ -90,99 +90,143 @@ enable_on_exec=0 + read_format=15 + optional=1 + +-# PERF_TYPE_RAW / topdown-fe-bound (0x8200) ++# PERF_TYPE_RAW / topdown-bad-spec (0x8100) + [event13:base-stat] + fd=13 + group_fd=11 + type=4 +-config=33280 ++config=33024 + disabled=0 + enable_on_exec=0 + read_format=15 + optional=1 + +-# PERF_TYPE_RAW / topdown-be-bound (0x8300) ++# PERF_TYPE_RAW / topdown-fe-bound (0x8200) + [event14:base-stat] + fd=14 + group_fd=11 + type=4 +-config=33536 ++config=33280 + disabled=0 + enable_on_exec=0 + read_format=15 + optional=1 + +-# PERF_TYPE_RAW / topdown-bad-spec (0x8100) ++# PERF_TYPE_RAW / topdown-be-bound (0x8300) + [event15:base-stat] + fd=15 + group_fd=11 + type=4 +-config=33024 ++config=33536 + disabled=0 + enable_on_exec=0 + read_format=15 + optional=1 + +-# PERF_TYPE_RAW / INT_MISC.UOP_DROPPING ++# PERF_TYPE_RAW / topdown-heavy-ops (0x8400) + [event16:base-stat] + fd=16 ++group_fd=11 + type=4 +-config=4109 ++config=33792 ++disabled=0 ++enable_on_exec=0 ++read_format=15 + optional=1 + +-# PERF_TYPE_RAW / cpu/INT_MISC.RECOVERY_CYCLES,cmask=1,edge/ ++# PERF_TYPE_RAW / topdown-br-mispredict (0x8500) + [event17:base-stat] + fd=17 ++group_fd=11 + type=4 +-config=17039629 ++config=34048 ++disabled=0 ++enable_on_exec=0 ++read_format=15 + optional=1 + +-# PERF_TYPE_RAW / CPU_CLK_UNHALTED.THREAD ++# PERF_TYPE_RAW / topdown-fetch-lat (0x8600) + [event18:base-stat] + fd=18 ++group_fd=11 + type=4 +-config=60 ++config=34304 ++disabled=0 ++enable_on_exec=0 ++read_format=15 + optional=1 + +-# PERF_TYPE_RAW / INT_MISC.RECOVERY_CYCLES_ANY ++# PERF_TYPE_RAW / topdown-mem-bound (0x8700) + [event19:base-stat] + fd=19 ++group_fd=11 + type=4 +-config=2097421 ++config=34560 ++disabled=0 ++enable_on_exec=0 ++read_format=15 + optional=1 + +-# PERF_TYPE_RAW / CPU_CLK_UNHALTED.REF_XCLK ++# PERF_TYPE_RAW / INT_MISC.UOP_DROPPING + [event20:base-stat] + fd=20 + type=4 +-config=316 ++config=4109 + optional=1 + +-# PERF_TYPE_RAW / IDQ_UOPS_NOT_DELIVERED.CORE ++# PERF_TYPE_RAW / cpu/INT_MISC.RECOVERY_CYCLES,cmask=1,edge/ + [event21:base-stat] + fd=21 + type=4 +-config=412 ++config=17039629 + optional=1 + +-# PERF_TYPE_RAW / CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE ++# PERF_TYPE_RAW / CPU_CLK_UNHALTED.THREAD + [event22:base-stat] + fd=22 + type=4 +-config=572 ++config=60 + optional=1 + +-# PERF_TYPE_RAW / UOPS_RETIRED.RETIRE_SLOTS ++# PERF_TYPE_RAW / INT_MISC.RECOVERY_CYCLES_ANY + [event23:base-stat] + fd=23 + type=4 +-config=706 ++config=2097421 + optional=1 + +-# PERF_TYPE_RAW / UOPS_ISSUED.ANY ++# PERF_TYPE_RAW / CPU_CLK_UNHALTED.REF_XCLK + [event24:base-stat] + fd=24 + type=4 ++config=316 ++optional=1 ++ ++# PERF_TYPE_RAW / IDQ_UOPS_NOT_DELIVERED.CORE ++[event25:base-stat] ++fd=25 ++type=4 ++config=412 ++optional=1 ++ ++# PERF_TYPE_RAW / CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE ++[event26:base-stat] ++fd=26 ++type=4 ++config=572 ++optional=1 ++ ++# PERF_TYPE_RAW / UOPS_RETIRED.RETIRE_SLOTS ++[event27:base-stat] ++fd=27 ++type=4 ++config=706 ++optional=1 ++ ++# PERF_TYPE_RAW / UOPS_ISSUED.ANY ++[event28:base-stat] ++fd=28 ++type=4 + config=270 + optional=1 + +@@ -190,8 +234,8 @@ optional=1 + # PERF_COUNT_HW_CACHE_L1D << 0 | + # (PERF_COUNT_HW_CACHE_OP_READ << 8) | + # (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16) +-[event25:base-stat] +-fd=25 ++[event29:base-stat] ++fd=29 + type=3 + config=0 + optional=1 +@@ -200,8 +244,8 @@ optional=1 + # PERF_COUNT_HW_CACHE_L1D << 0 | + # (PERF_COUNT_HW_CACHE_OP_READ << 8) | + # (PERF_COUNT_HW_CACHE_RESULT_MISS << 16) +-[event26:base-stat] +-fd=26 ++[event30:base-stat] ++fd=30 + type=3 + config=65536 + optional=1 +@@ -210,8 +254,8 @@ optional=1 + # PERF_COUNT_HW_CACHE_LL << 0 | + # (PERF_COUNT_HW_CACHE_OP_READ << 8) | + # (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16) +-[event27:base-stat] +-fd=27 ++[event31:base-stat] ++fd=31 + type=3 + config=2 + optional=1 +@@ -220,8 +264,8 @@ optional=1 + # PERF_COUNT_HW_CACHE_LL << 0 | + # (PERF_COUNT_HW_CACHE_OP_READ << 8) | + # (PERF_COUNT_HW_CACHE_RESULT_MISS << 16) +-[event28:base-stat] +-fd=28 ++[event32:base-stat] ++fd=32 + type=3 + config=65538 + optional=1 +@@ -230,8 +274,8 @@ optional=1 + # PERF_COUNT_HW_CACHE_L1I << 0 | + # (PERF_COUNT_HW_CACHE_OP_READ << 8) | + # (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16) +-[event29:base-stat] +-fd=29 ++[event33:base-stat] ++fd=33 + type=3 + config=1 + optional=1 +@@ -240,8 +284,8 @@ optional=1 + # PERF_COUNT_HW_CACHE_L1I << 0 | + # (PERF_COUNT_HW_CACHE_OP_READ << 8) | + # (PERF_COUNT_HW_CACHE_RESULT_MISS << 16) +-[event30:base-stat] +-fd=30 ++[event34:base-stat] ++fd=34 + type=3 + config=65537 + optional=1 +@@ -250,8 +294,8 @@ optional=1 + # PERF_COUNT_HW_CACHE_DTLB << 0 | + # (PERF_COUNT_HW_CACHE_OP_READ << 8) | + # (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16) +-[event31:base-stat] +-fd=31 ++[event35:base-stat] ++fd=35 + type=3 + config=3 + optional=1 +@@ -260,8 +304,8 @@ optional=1 + # PERF_COUNT_HW_CACHE_DTLB << 0 | + # (PERF_COUNT_HW_CACHE_OP_READ << 8) | + # (PERF_COUNT_HW_CACHE_RESULT_MISS << 16) +-[event32:base-stat] +-fd=32 ++[event36:base-stat] ++fd=36 + type=3 + config=65539 + optional=1 +@@ -270,8 +314,8 @@ optional=1 + # PERF_COUNT_HW_CACHE_ITLB << 0 | + # (PERF_COUNT_HW_CACHE_OP_READ << 8) | + # (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16) +-[event33:base-stat] +-fd=33 ++[event37:base-stat] ++fd=37 + type=3 + config=4 + optional=1 +@@ -280,8 +324,8 @@ optional=1 + # PERF_COUNT_HW_CACHE_ITLB << 0 | + # (PERF_COUNT_HW_CACHE_OP_READ << 8) | + # (PERF_COUNT_HW_CACHE_RESULT_MISS << 16) +-[event34:base-stat] +-fd=34 ++[event38:base-stat] ++fd=38 + type=3 + config=65540 + optional=1 +diff --git a/tools/perf/tests/attr/test-stat-detailed-3 b/tools/perf/tests/attr/test-stat-detailed-3 +index e50535f45977c..8400abd7e1e48 100644 +--- a/tools/perf/tests/attr/test-stat-detailed-3 ++++ b/tools/perf/tests/attr/test-stat-detailed-3 +@@ -90,99 +90,143 @@ enable_on_exec=0 + read_format=15 + optional=1 + +-# PERF_TYPE_RAW / topdown-fe-bound (0x8200) ++# PERF_TYPE_RAW / topdown-bad-spec (0x8100) + [event13:base-stat] + fd=13 + group_fd=11 + type=4 +-config=33280 ++config=33024 + disabled=0 + enable_on_exec=0 + read_format=15 + optional=1 + +-# PERF_TYPE_RAW / topdown-be-bound (0x8300) ++# PERF_TYPE_RAW / topdown-fe-bound (0x8200) + [event14:base-stat] + fd=14 + group_fd=11 + type=4 +-config=33536 ++config=33280 + disabled=0 + enable_on_exec=0 + read_format=15 + optional=1 + +-# PERF_TYPE_RAW / topdown-bad-spec (0x8100) ++# PERF_TYPE_RAW / topdown-be-bound (0x8300) + [event15:base-stat] + fd=15 + group_fd=11 + type=4 +-config=33024 ++config=33536 + disabled=0 + enable_on_exec=0 + read_format=15 + optional=1 + +-# PERF_TYPE_RAW / INT_MISC.UOP_DROPPING ++# PERF_TYPE_RAW / topdown-heavy-ops (0x8400) + [event16:base-stat] + fd=16 ++group_fd=11 + type=4 +-config=4109 ++config=33792 ++disabled=0 ++enable_on_exec=0 ++read_format=15 + optional=1 + +-# PERF_TYPE_RAW / cpu/INT_MISC.RECOVERY_CYCLES,cmask=1,edge/ ++# PERF_TYPE_RAW / topdown-br-mispredict (0x8500) + [event17:base-stat] + fd=17 ++group_fd=11 + type=4 +-config=17039629 ++config=34048 ++disabled=0 ++enable_on_exec=0 ++read_format=15 + optional=1 + +-# PERF_TYPE_RAW / CPU_CLK_UNHALTED.THREAD ++# PERF_TYPE_RAW / topdown-fetch-lat (0x8600) + [event18:base-stat] + fd=18 ++group_fd=11 + type=4 +-config=60 ++config=34304 ++disabled=0 ++enable_on_exec=0 ++read_format=15 + optional=1 + +-# PERF_TYPE_RAW / INT_MISC.RECOVERY_CYCLES_ANY ++# PERF_TYPE_RAW / topdown-mem-bound (0x8700) + [event19:base-stat] + fd=19 ++group_fd=11 + type=4 +-config=2097421 ++config=34560 ++disabled=0 ++enable_on_exec=0 ++read_format=15 + optional=1 + +-# PERF_TYPE_RAW / CPU_CLK_UNHALTED.REF_XCLK ++# PERF_TYPE_RAW / INT_MISC.UOP_DROPPING + [event20:base-stat] + fd=20 + type=4 +-config=316 ++config=4109 + optional=1 + +-# PERF_TYPE_RAW / IDQ_UOPS_NOT_DELIVERED.CORE ++# PERF_TYPE_RAW / cpu/INT_MISC.RECOVERY_CYCLES,cmask=1,edge/ + [event21:base-stat] + fd=21 + type=4 +-config=412 ++config=17039629 + optional=1 + +-# PERF_TYPE_RAW / CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE ++# PERF_TYPE_RAW / CPU_CLK_UNHALTED.THREAD + [event22:base-stat] + fd=22 + type=4 +-config=572 ++config=60 + optional=1 + +-# PERF_TYPE_RAW / UOPS_RETIRED.RETIRE_SLOTS ++# PERF_TYPE_RAW / INT_MISC.RECOVERY_CYCLES_ANY + [event23:base-stat] + fd=23 + type=4 +-config=706 ++config=2097421 + optional=1 + +-# PERF_TYPE_RAW / UOPS_ISSUED.ANY ++# PERF_TYPE_RAW / CPU_CLK_UNHALTED.REF_XCLK + [event24:base-stat] + fd=24 + type=4 ++config=316 ++optional=1 ++ ++# PERF_TYPE_RAW / IDQ_UOPS_NOT_DELIVERED.CORE ++[event25:base-stat] ++fd=25 ++type=4 ++config=412 ++optional=1 ++ ++# PERF_TYPE_RAW / CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE ++[event26:base-stat] ++fd=26 ++type=4 ++config=572 ++optional=1 ++ ++# PERF_TYPE_RAW / UOPS_RETIRED.RETIRE_SLOTS ++[event27:base-stat] ++fd=27 ++type=4 ++config=706 ++optional=1 ++ ++# PERF_TYPE_RAW / UOPS_ISSUED.ANY ++[event28:base-stat] ++fd=28 ++type=4 + config=270 + optional=1 + +@@ -190,8 +234,8 @@ optional=1 + # PERF_COUNT_HW_CACHE_L1D << 0 | + # (PERF_COUNT_HW_CACHE_OP_READ << 8) | + # (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16) +-[event25:base-stat] +-fd=25 ++[event29:base-stat] ++fd=29 + type=3 + config=0 + optional=1 +@@ -200,8 +244,8 @@ optional=1 + # PERF_COUNT_HW_CACHE_L1D << 0 | + # (PERF_COUNT_HW_CACHE_OP_READ << 8) | + # (PERF_COUNT_HW_CACHE_RESULT_MISS << 16) +-[event26:base-stat] +-fd=26 ++[event30:base-stat] ++fd=30 + type=3 + config=65536 + optional=1 +@@ -210,8 +254,8 @@ optional=1 + # PERF_COUNT_HW_CACHE_LL << 0 | + # (PERF_COUNT_HW_CACHE_OP_READ << 8) | + # (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16) +-[event27:base-stat] +-fd=27 ++[event31:base-stat] ++fd=31 + type=3 + config=2 + optional=1 +@@ -220,8 +264,8 @@ optional=1 + # PERF_COUNT_HW_CACHE_LL << 0 | + # (PERF_COUNT_HW_CACHE_OP_READ << 8) | + # (PERF_COUNT_HW_CACHE_RESULT_MISS << 16) +-[event28:base-stat] +-fd=28 ++[event32:base-stat] ++fd=32 + type=3 + config=65538 + optional=1 +@@ -230,8 +274,8 @@ optional=1 + # PERF_COUNT_HW_CACHE_L1I << 0 | + # (PERF_COUNT_HW_CACHE_OP_READ << 8) | + # (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16) +-[event29:base-stat] +-fd=29 ++[event33:base-stat] ++fd=33 + type=3 + config=1 + optional=1 +@@ -240,8 +284,8 @@ optional=1 + # PERF_COUNT_HW_CACHE_L1I << 0 | + # (PERF_COUNT_HW_CACHE_OP_READ << 8) | + # (PERF_COUNT_HW_CACHE_RESULT_MISS << 16) +-[event30:base-stat] +-fd=30 ++[event34:base-stat] ++fd=34 + type=3 + config=65537 + optional=1 +@@ -250,8 +294,8 @@ optional=1 + # PERF_COUNT_HW_CACHE_DTLB << 0 | + # (PERF_COUNT_HW_CACHE_OP_READ << 8) | + # (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16) +-[event31:base-stat] +-fd=31 ++[event35:base-stat] ++fd=35 + type=3 + config=3 + optional=1 +@@ -260,8 +304,8 @@ optional=1 + # PERF_COUNT_HW_CACHE_DTLB << 0 | + # (PERF_COUNT_HW_CACHE_OP_READ << 8) | + # (PERF_COUNT_HW_CACHE_RESULT_MISS << 16) +-[event32:base-stat] +-fd=32 ++[event36:base-stat] ++fd=36 + type=3 + config=65539 + optional=1 +@@ -270,8 +314,8 @@ optional=1 + # PERF_COUNT_HW_CACHE_ITLB << 0 | + # (PERF_COUNT_HW_CACHE_OP_READ << 8) | + # (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16) +-[event33:base-stat] +-fd=33 ++[event37:base-stat] ++fd=37 + type=3 + config=4 + optional=1 +@@ -280,8 +324,8 @@ optional=1 + # PERF_COUNT_HW_CACHE_ITLB << 0 | + # (PERF_COUNT_HW_CACHE_OP_READ << 8) | + # (PERF_COUNT_HW_CACHE_RESULT_MISS << 16) +-[event34:base-stat] +-fd=34 ++[event38:base-stat] ++fd=38 + type=3 + config=65540 + optional=1 +@@ -290,8 +334,8 @@ optional=1 + # PERF_COUNT_HW_CACHE_L1D << 0 | + # (PERF_COUNT_HW_CACHE_OP_PREFETCH << 8) | + # (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16) +-[event35:base-stat] +-fd=35 ++[event39:base-stat] ++fd=39 + type=3 + config=512 + optional=1 +@@ -300,8 +344,8 @@ optional=1 + # PERF_COUNT_HW_CACHE_L1D << 0 | + # (PERF_COUNT_HW_CACHE_OP_PREFETCH << 8) | + # (PERF_COUNT_HW_CACHE_RESULT_MISS << 16) +-[event36:base-stat] +-fd=36 ++[event40:base-stat] ++fd=40 + type=3 + config=66048 + optional=1 +-- +2.43.0 + diff --git a/queue-6.12/perf-trace-avoid-garbage-when-not-printing-a-syscall.patch b/queue-6.12/perf-trace-avoid-garbage-when-not-printing-a-syscall.patch new file mode 100644 index 00000000000..0e0ea47323e --- /dev/null +++ b/queue-6.12/perf-trace-avoid-garbage-when-not-printing-a-syscall.patch @@ -0,0 +1,63 @@ +From ed837d2d57da551c561aa616276eca6940b7807e Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Thu, 7 Nov 2024 23:21:27 +0000 +Subject: perf trace: Avoid garbage when not printing a syscall's arguments + +From: Benjamin Peterson <benjamin@engflow.com> + +[ Upstream commit 1302e352b26f34991b619b5d0b621b76d20a3883 ] + +syscall__scnprintf_args may not place anything in the output buffer +(e.g., because the arguments are all zero). If that happened in +trace__fprintf_sys_enter, its fprintf would receive an unitialized +buffer leading to garbage output. + +Fix the problem by passing the (possibly zero) bounds of the argument +buffer to the output fprintf. + +Fixes: a98392bb1e169a04 ("perf trace: Use beautifiers on syscalls:sys_enter_ handlers") +Signed-off-by: Benjamin Peterson <benjamin@engflow.com> +Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com> +Tested-by: Howard Chu <howardchu95@gmail.com> +Cc: Adrian Hunter <adrian.hunter@intel.com> +Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com> +Cc: Ian Rogers <irogers@google.com> +Cc: Ingo Molnar <mingo@redhat.com> +Cc: Jiri Olsa <jolsa@kernel.org> +Cc: Kan Liang <kan.liang@linux.intel.com> +Cc: Mark Rutland <mark.rutland@arm.com> +Cc: Namhyung Kim <namhyung@kernel.org> +Cc: Peter Zijlstra <peterz@infradead.org> +Link: https://lore.kernel.org/r/20241107232128.108981-2-benjamin@engflow.com +Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + tools/perf/builtin-trace.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c +index 6fc437be662a1..ffa1295273099 100644 +--- a/tools/perf/builtin-trace.c ++++ b/tools/perf/builtin-trace.c +@@ -2702,6 +2702,7 @@ static int trace__fprintf_sys_enter(struct trace *trace, struct evsel *evsel, + char msg[1024]; + void *args, *augmented_args = NULL; + int augmented_args_size; ++ size_t printed = 0; + + if (sc == NULL) + return -1; +@@ -2717,8 +2718,8 @@ static int trace__fprintf_sys_enter(struct trace *trace, struct evsel *evsel, + + args = perf_evsel__sc_tp_ptr(evsel, args, sample); + augmented_args = syscall__augmented_args(sc, sample, &augmented_args_size, trace->raw_augmented_syscalls_args_size); +- syscall__scnprintf_args(sc, msg, sizeof(msg), args, augmented_args, augmented_args_size, trace, thread); +- fprintf(trace->output, "%s", msg); ++ printed += syscall__scnprintf_args(sc, msg, sizeof(msg), args, augmented_args, augmented_args_size, trace, thread); ++ fprintf(trace->output, "%.*s", (int)printed, msg); + err = 0; + out_put: + thread__put(thread); +-- +2.43.0 + diff --git a/queue-6.12/perf-trace-avoid-garbage-when-not-printing-a-trace-e.patch b/queue-6.12/perf-trace-avoid-garbage-when-not-printing-a-trace-e.patch new file mode 100644 index 00000000000..96f5ba920f8 --- /dev/null +++ b/queue-6.12/perf-trace-avoid-garbage-when-not-printing-a-trace-e.patch @@ -0,0 +1,41 @@ +From ec6a8ba113ff9461a38bd3ae7a28b5a17a8bcbc7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Sun, 3 Nov 2024 20:48:16 +0000 +Subject: perf trace: avoid garbage when not printing a trace event's arguments + +From: Benjamin Peterson <benjamin@engflow.com> + +[ Upstream commit 5fb8e56542a3cf469fdf25d77f50e21cbff3ae7e ] + +trace__fprintf_tp_fields may not print any tracepoint arguments. E.g., if the +argument values are all zero. Previously, this would result in a totally +uninitialized buffer being passed to fprintf, which could lead to garbage on the +console. Fix the problem by passing the number of initialized bytes fprintf. + +Fixes: f11b2803bb88 ("perf trace: Allow choosing how to augment the tracepoint arguments") +Signed-off-by: Benjamin Peterson <benjamin@engflow.com> +Tested-by: Howard Chu <howardchu95@gmail.com> +Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com> +Link: https://lore.kernel.org/r/20241103204816.7834-1-benjamin@engflow.com +Signed-off-by: Namhyung Kim <namhyung@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + tools/perf/builtin-trace.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c +index 4cc942f7fec7d..4f47fe3b211d9 100644 +--- a/tools/perf/builtin-trace.c ++++ b/tools/perf/builtin-trace.c +@@ -3087,7 +3087,7 @@ static size_t trace__fprintf_tp_fields(struct trace *trace, struct evsel *evsel, + printed += syscall_arg_fmt__scnprintf_val(arg, bf + printed, size - printed, &syscall_arg, val); + } + +- return printed + fprintf(trace->output, "%s", bf); ++ return printed + fprintf(trace->output, "%.*s", (int)printed, bf); + } + + static int trace__event_handler(struct trace *trace, struct evsel *evsel, +-- +2.43.0 + diff --git a/queue-6.12/perf-trace-do-not-lose-last-events-in-a-race.patch b/queue-6.12/perf-trace-do-not-lose-last-events-in-a-race.patch new file mode 100644 index 00000000000..fc60e781654 --- /dev/null +++ b/queue-6.12/perf-trace-do-not-lose-last-events-in-a-race.patch @@ -0,0 +1,74 @@ +From ceceb7fd8a312a17d0a6011b5731d21abf447faf Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Thu, 7 Nov 2024 23:21:26 +0000 +Subject: perf trace: Do not lose last events in a race + +From: Benjamin Peterson <benjamin@engflow.com> + +[ Upstream commit 3fd7c36973a250e17a4ee305a31545a9426021f4 ] + +If a perf trace event selector specifies a maximum number of events to output +(i.e., "/nr=N/" syntax), the event printing handler, trace__event_handler, +disables the event selector after the maximum number events are +printed. + +Furthermore, trace__event_handler checked if the event selector was +disabled before doing any work. This avoided exceeding the maximum +number of events to print if more events were in the buffer before the +selector was disabled. + +However, the event selector can be disabled for reasons other than +exceeding the maximum number of events. In particular, when the traced +subprocess exits, the main loop disables all event selectors. This meant +the last events of a traced subprocess might be lost to the printing +handler's short-circuiting logic. + +This nondeterministic problem could be seen by running the following many times: + + $ perf trace -e syscalls:sys_enter_exit_group true + +trace__event_handler should simply check for exceeding the maximum number of +events to print rather than the state of the event selector. + +Fixes: a9c5e6c1e9bff42c ("perf trace: Introduce per-event maximum number of events property") +Signed-off-by: Benjamin Peterson <benjamin@engflow.com> +Tested-by: Howard Chu <howardchu95@gmail.com> +Cc: Adrian Hunter <adrian.hunter@intel.com> +Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com> +Cc: Ian Rogers <irogers@google.com> +Cc: Ingo Molnar <mingo@redhat.com> +Cc: Jiri Olsa <jolsa@kernel.org> +Cc: Kan Liang <kan.liang@linux.intel.com> +Cc: Mark Rutland <mark.rutland@arm.com> +Cc: Namhyung Kim <namhyung@kernel.org> +Cc: Peter Zijlstra <peterz@infradead.org> +Link: https://lore.kernel.org/r/20241107232128.108981-1-benjamin@engflow.com +Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + tools/perf/builtin-trace.c | 9 ++------- + 1 file changed, 2 insertions(+), 7 deletions(-) + +diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c +index f724a595d7411..6fc437be662a1 100644 +--- a/tools/perf/builtin-trace.c ++++ b/tools/perf/builtin-trace.c +@@ -3096,13 +3096,8 @@ static int trace__event_handler(struct trace *trace, struct evsel *evsel, + { + struct thread *thread; + int callchain_ret = 0; +- /* +- * Check if we called perf_evsel__disable(evsel) due to, for instance, +- * this event's max_events having been hit and this is an entry coming +- * from the ring buffer that we should discard, since the max events +- * have already been considered/printed. +- */ +- if (evsel->disabled) ++ ++ if (evsel->nr_events_printed >= evsel->max_events) + return 0; + + thread = machine__findnew_thread(trace->host, sample->pid, sample->tid); +-- +2.43.0 + diff --git a/queue-6.12/perf-trace-fix-tracing-itself-creating-feedback-loop.patch b/queue-6.12/perf-trace-fix-tracing-itself-creating-feedback-loop.patch new file mode 100644 index 00000000000..6c61874e472 --- /dev/null +++ b/queue-6.12/perf-trace-fix-tracing-itself-creating-feedback-loop.patch @@ -0,0 +1,219 @@ +From 47d4d94017fe5c4ab3f928662e5d6e4ef791ef9b Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Tue, 29 Oct 2024 22:24:31 -0700 +Subject: perf trace: Fix tracing itself, creating feedback loops +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Howard Chu <howardchu95@gmail.com> + +[ Upstream commit fe4f9b4124967ffb75d66994520831231b779550 ] + +There exists a pids_filtered map in augmented_raw_syscalls.bpf.c that +ceases to provide functionality after the BPF skeleton migration done +in: + +5e6da6be3082f77b ("perf trace: Migrate BPF augmentation to use a skeleton") + +Before the migration, pid_filtered map works, courtesy of Arnaldo +Carvalho de Melo <acme@kernel.org>: + + ⬢ [acme@toolbox perf-tools]$ git log --oneline -5 + 6f769c3458b6cf2d (HEAD) perf tests trace+probe_vfs_getname.sh: Accept quotes surrounding the filename + 7777ac3dfe29f55d perf test trace+probe_vfs_getname.sh: Remove stray \ before / + 33d9c5062113a4bd perf script python: Add stub for PMU symbol to the python binding + e59fea47f83e8a9a perf symbols: Fix DSO kernel load and symbol process to correctly map DSO to its long_name, type and adjust_symbols + 878460e8d0ff84a0 perf build: Remove -Wno-unused-but-set-variable from the flex flags when building with clang < 13.0.0 + + root@x1:/home/acme/git/perf-tools# perf trace -e /tmp/augmented_raw_syscalls.o -e write* --max-events=30 & + [1] 180632 + root@x1:/home/acme/git/perf-tools# 0.000 ( 0.051 ms): NetworkManager/1127 write(fd: 3, buf: 0x7ffeb508ef70, count: 8) = 8 + 0.115 ( 0.010 ms): NetworkManager/1127 write(fd: 3, buf: 0x7ffeb508ef70, count: 8) = 8 + 0.916 ( 0.068 ms): sudo/156867 write(fd: 8, buf: 0x55cb4cd2f650, count: 246) = 246 + 1.699 ( 0.047 ms): sudo/156867 write(fd: 8, buf: 0x55cb4cd2f650, count: 121) = 121 + 2.167 ( 0.041 ms): sudo/156867 write(fd: 8, buf: 0x55cb4cd2f650, count: 121) = 121 + 2.739 ( 0.042 ms): sudo/156867 write(fd: 8, buf: 0x55cb4cd2f650, count: 121) = 121 + 3.138 ( 0.027 ms): sudo/156867 write(fd: 8, buf: 0x55cb4cd2f650, count: 121) = 121 + 3.477 ( 0.027 ms): sudo/156867 write(fd: 8, buf: 0x55cb4cd2f650, count: 121) = 121 + 3.738 ( 0.023 ms): sudo/156867 write(fd: 8, buf: 0x55cb4cd2f650, count: 121) = 121 + 3.946 ( 0.024 ms): sudo/156867 write(fd: 8, buf: 0x55cb4cd2f650, count: 121) = 121 + 4.195 ( 0.024 ms): sudo/156867 write(fd: 8, buf: 0x55cb4cd2f650, count: 121) = 121 + 4.212 ( 0.026 ms): NetworkManager/1127 write(fd: 3, buf: 0x7ffeb508ef70, count: 8) = 8 + 4.285 ( 0.006 ms): NetworkManager/1127 write(fd: 3, buf: 0x7ffeb508ef70, count: 8) = 8 + 4.445 ( 0.018 ms): sudo/156867 write(fd: 8, buf: 0x55cb4cd2f650, count: 260) = 260 + 4.508 ( 0.009 ms): sudo/156867 write(fd: 8, buf: 0x55cb4cd2f650, count: 124) = 124 + 4.592 ( 0.010 ms): sudo/156867 write(fd: 8, buf: 0x55cb4cd2f650, count: 116) = 116 + 4.666 ( 0.009 ms): sudo/156867 write(fd: 8, buf: 0x55cb4cd2f650, count: 130) = 130 + 4.715 ( 0.010 ms): sudo/156867 write(fd: 8, buf: 0x55cb4cd2f650, count: 95) = 95 + 4.765 ( 0.007 ms): sudo/156867 write(fd: 8, buf: 0x55cb4cd2f650, count: 102) = 102 + 4.815 ( 0.009 ms): sudo/156867 write(fd: 8, buf: 0x55cb4cd2f650, count: 79) = 79 + 4.890 ( 0.008 ms): sudo/156867 write(fd: 8, buf: 0x55cb4cd2f650, count: 57) = 57 + 4.937 ( 0.007 ms): sudo/156867 write(fd: 8, buf: 0x55cb4cd2f650, count: 89) = 89 + 5.009 ( 0.010 ms): sudo/156867 write(fd: 8, buf: 0x55cb4cd2f650, count: 112) = 112 + 5.059 ( 0.010 ms): sudo/156867 write(fd: 8, buf: 0x55cb4cd2f650, count: 112) = 112 + 5.116 ( 0.007 ms): sudo/156867 write(fd: 8, buf: 0x55cb4cd2f650, count: 79) = 79 + 5.152 ( 0.009 ms): sudo/156867 write(fd: 8, buf: 0x55cb4cd2f650, count: 33) = 33 + 5.215 ( 0.008 ms): sudo/156867 write(fd: 8, buf: 0x55cb4cd2f650, count: 37) = 37 + 5.293 ( 0.010 ms): sudo/156867 write(fd: 8, buf: 0x55cb4cd2f650, count: 128) = 128 + 5.339 ( 0.009 ms): sudo/156867 write(fd: 8, buf: 0x55cb4cd2f650, count: 89) = 89 + 5.384 ( 0.008 ms): sudo/156867 write(fd: 8, buf: 0x55cb4cd2f650, count: 100) = 100 + + [1]+ Done perf trace -e /tmp/augmented_raw_syscalls.o -e write* --max-events=30 + root@x1:/home/acme/git/perf-tools# + +No events for the 'perf trace' (pid 180632), i.e. no feedback loop. + +If we leave it running: + + root@x1:/home/acme/git/perf-tools# perf trace -e /tmp/augmented_raw_syscalls.o -e landlock_add_rule & + [1] 181068 + root@x1:/home/acme/git/perf-tools# + + And then look at what maps it sets up: + + root@x1:/home/acme/git/perf-tools# bpftool map | grep pids_filtered -A3 + 1190: hash name pids_filtered flags 0x0 + key 4B value 1B max_entries 64 memlock 7264B + btf_id 1613 + pids perf(181068) + root@x1:/home/acme/git/perf-tools# + + And ask for dumping its contents: + + We see that we are _also_ setting it to filter those: + + root@x1:/home/acme/git/perf-tools# bpftool map dump id 1190 + [{ + "key": 181068, + "value": 1 + },{ + "key": 156801, + "value": 1 + } + ] + +Now testing the migration commit: + + perf $ git log + commit 5e6da6be3082f77be06894a1a94d52a90b4007dc (HEAD) + Author: Ian Rogers <irogers@google.com> + Date: Thu Aug 10 11:48:51 2023 -0700 + + perf trace: Migrate BPF augmentation to use a skeleton + + perf $ ./perf trace -e write --max-events=10 & echo #! + [1] 1808653 + perf $ + 0.000 ( 0.010 ms): :1808671/1808671 write(fd: 1, buf: 0x6003f5b26fc0, count: 11) = 11 + 0.162 ( ): perf/1808653 write(fd: 2, buf: 0x7fffc2174e50, count: 11) ... + 0.174 ( ): perf/1808653 write(fd: 2, buf: 0x74ce21804563, count: 1) ... + 0.184 ( ): perf/1808653 write(fd: 2, buf: 0x57b936589052, count: 5) + +The feedback loop is there. + +Keep it running, look into the bpf map: + + perf $ bpftool map | grep pids_filtered + 10675: hash name pids_filtered flags 0x0 + + perf $ bpftool map dump id 10675 + [] + +The map is empty. + +Now, this commit: + + 64917f4df048a064 ("perf trace: Use heuristic when deciding if a syscall tracepoint "const char *" field is really a string") + +Temporarily fixed the feedback loop for perf trace -e write, that's +because before using the heuristic, write is hooked to sys_enter_openat: + + perf $ git log + commit 83a0943b1870944612a8aa0049f910826ebfd4f7 (HEAD) + Author: Arnaldo Carvalho de Melo <acme@redhat.com> + Date: Thu Aug 17 12:11:51 2023 -0300 + + perf trace: Use the augmented_raw_syscall BPF skel only for tracing syscalls + + perf $ ./perf trace -e write --max-events=10 -v 2>&1 | grep Reusing + Reusing "openat" BPF sys_enter augmenter for "write" + +And after the heuristic fix, it's unaugmented: + + perf $ git log + commit 64917f4df048a0649ea7901c2321f020e71e6f24 (HEAD) + Author: Arnaldo Carvalho de Melo <acme@redhat.com> + Date: Thu Aug 17 15:14:21 2023 -0300 + + perf trace: Use heuristic when deciding if a syscall tracepoint "const char *" field is really a string + + perf $ ./perf trace -e write --max-events=10 -v 2>&1 | grep Reusing + perf $ + +After using the heuristic, write is hooked to syscall_unaugmented, which +returns 1. + + SEC("tp/raw_syscalls/sys_enter") + int syscall_unaugmented(struct syscall_enter_args *args) + { + return 1; + } + +If the BPF program returns 1, the tracepoint filter will filter it +(since the tracepoint filter for perf is correctly set), but before the +heuristic, when it was hooked to a sys_enter_openat(), which is a BPF +program that calls bpf_perf_event_output() and writes to the buffer, it +didn't get filtered, thus creating feedback loop. So switching write to +unaugmented accidentally fixed the problem. + +But some syscalls are not so lucky, for example newfstatat: +perf $ ./perf trace -e newfstatat --max-events=100 & echo #! +[1] 2166948 + + 457.718 ( ): perf/2166948 newfstatat(dfd: CWD, filename: "/proc/self/ns/mnt", statbuf: 0x7fff0132a9f0) ... + 457.749 ( ): perf/2166948 newfstatat(dfd: CWD, filename: "/proc/2166950/ns/mnt", statbuf: 0x7fff0132aa80) ... + 457.962 ( ): perf/2166948 newfstatat(dfd: CWD, filename: "/proc/self/ns/mnt", statbuf: 0x7fff0132a9f0) ... + +Currently, write is augmented by the new BTF general augmenter (which +calls bpf_perf_event_output()). The problem, which luckily got fixed, +resurfaced, and that’s how it was discovered. + +Fixes: 5e6da6be3082f77b ("perf trace: Migrate BPF augmentation to use a skeleton") +Signed-off-by: Howard Chu <howardchu95@gmail.com> +Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com> +Cc: Adrian Hunter <adrian.hunter@intel.com> +Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com> +Cc: Ian Rogers <irogers@google.com> +Cc: Ingo Molnar <mingo@redhat.com> +Cc: James Clark <james.clark@linaro.org> +Cc: Jiri Olsa <jolsa@kernel.org> +Cc: Kan Liang <kan.liang@linux.intel.com> +Cc: Mark Rutland <mark.rutland@arm.com> +Cc: Namhyung Kim <namhyung@kernel.org> +Cc: Peter Zijlstra <peterz@infradead.org> +Link: https://lore.kernel.org/r/20241030052431.2220130-1-howardchu95@gmail.com +[ Check if trace->skel is non-NULL, as it is only initialized if trace->trace_syscalls is set ] +Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + tools/perf/builtin-trace.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c +index 4f47fe3b211d9..f724a595d7411 100644 +--- a/tools/perf/builtin-trace.c ++++ b/tools/perf/builtin-trace.c +@@ -4326,6 +4326,9 @@ static int trace__run(struct trace *trace, int argc, const char **argv) + sizeof(__u32), BPF_ANY); + } + } ++ ++ if (trace->skel) ++ trace->filter_pids.map = trace->skel->maps.pids_filtered; + #endif + err = trace__set_filter_pids(trace); + if (err < 0) +-- +2.43.0 + diff --git a/queue-6.12/perf-trace-keep-exited-threads-for-summary.patch b/queue-6.12/perf-trace-keep-exited-threads-for-summary.patch new file mode 100644 index 00000000000..2142fe167ba --- /dev/null +++ b/queue-6.12/perf-trace-keep-exited-threads-for-summary.patch @@ -0,0 +1,77 @@ +From 862ed36f77bada4020c52ac2aeebd1afd35c5073 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Fri, 27 Sep 2024 17:19:26 +0200 +Subject: perf trace: Keep exited threads for summary + +From: Michael Petlan <mpetlan@redhat.com> + +[ Upstream commit d29d92df410e2fb523f640478b18f70c1823e55e ] + +Since 9ffa6c7512ca ("perf machine thread: Remove exited threads by +default") perf cleans exited threads up, but as said, sometimes they +are necessary to be kept. The mentioned commit does not cover all the +cases, we also need the information to construct the summary table in +perf-trace. + +Before: + # perf trace -s true + + Summary of events: + +After: + # perf trace -s -- true + + Summary of events: + + true (383382), 64 events, 91.4% + + syscall calls errors total min avg max stddev + (msec) (msec) (msec) (msec) (%) + --------------- -------- ------ -------- --------- --------- --------- ------ + mmap 8 0 0.150 0.013 0.019 0.031 11.90% + mprotect 3 0 0.045 0.014 0.015 0.017 6.47% + openat 2 0 0.014 0.006 0.007 0.007 9.73% + munmap 1 0 0.009 0.009 0.009 0.009 0.00% + access 1 1 0.009 0.009 0.009 0.009 0.00% + pread64 4 0 0.006 0.001 0.001 0.002 4.53% + fstat 2 0 0.005 0.001 0.002 0.003 37.59% + arch_prctl 2 1 0.003 0.001 0.002 0.002 25.91% + read 1 0 0.003 0.003 0.003 0.003 0.00% + close 2 0 0.003 0.001 0.001 0.001 3.86% + brk 1 0 0.002 0.002 0.002 0.002 0.00% + rseq 1 0 0.001 0.001 0.001 0.001 0.00% + prlimit64 1 0 0.001 0.001 0.001 0.001 0.00% + set_robust_list 1 0 0.001 0.001 0.001 0.001 0.00% + set_tid_address 1 0 0.001 0.001 0.001 0.001 0.00% + execve 1 0 0.000 0.000 0.000 0.000 0.00% + +[namhyung: simplified the condition] + +Fixes: 9ffa6c7512ca ("perf machine thread: Remove exited threads by default") +Reported-by: Veronika Molnarova <vmolnaro@redhat.com> +Signed-off-by: Michael Petlan <mpetlan@redhat.com> +Link: https://lore.kernel.org/r/20240927151926.399474-1-mpetlan@redhat.com +Signed-off-by: Namhyung Kim <namhyung@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + tools/perf/builtin-trace.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c +index d3f11b90d0255..4cc942f7fec7d 100644 +--- a/tools/perf/builtin-trace.c ++++ b/tools/perf/builtin-trace.c +@@ -5449,6 +5449,10 @@ int cmd_trace(int argc, const char **argv) + if (trace.summary_only) + trace.summary = trace.summary_only; + ++ /* Keep exited threads, otherwise information might be lost for summary */ ++ if (trace.summary) ++ symbol_conf.keep_exited_threads = true; ++ + if (output_name != NULL) { + err = trace__open_output(&trace, output_name); + if (err < 0) { +-- +2.43.0 + diff --git a/queue-6.12/phy-airoha-fix-reg_csr_2l_jcpll_sdm_hren-config-in-a.patch b/queue-6.12/phy-airoha-fix-reg_csr_2l_jcpll_sdm_hren-config-in-a.patch new file mode 100644 index 00000000000..fac90509384 --- /dev/null +++ b/queue-6.12/phy-airoha-fix-reg_csr_2l_jcpll_sdm_hren-config-in-a.patch @@ -0,0 +1,38 @@ +From 12e0cfc1479856e6abd20e01b4e9f918ed8f7978 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Wed, 18 Sep 2024 15:32:54 +0200 +Subject: phy: airoha: Fix REG_CSR_2L_JCPLL_SDM_HREN config in + airoha_pcie_phy_init_ssc_jcpll() + +From: Lorenzo Bianconi <lorenzo@kernel.org> + +[ Upstream commit 6fd016c965d241673a2e62afbf9eeb4bcbfbbe45 ] + +Fix typo configuring REG_CSR_2L_JCPLL_SDM_HREN register in +airoha_pcie_phy_init_ssc_jcpll routine. + +Fixes: d7d2818b9383 ("phy: airoha: Add PCIe PHY driver for EN7581 SoC.") +Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org> +Link: https://lore.kernel.org/r/20240918-airoha-en7581-phy-fixes-v1-3-8291729a87f8@kernel.org +Signed-off-by: Vinod Koul <vkoul@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/phy/phy-airoha-pcie.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/phy/phy-airoha-pcie.c b/drivers/phy/phy-airoha-pcie.c +index 9a7ce65f87f05..56e9ade8a9fd3 100644 +--- a/drivers/phy/phy-airoha-pcie.c ++++ b/drivers/phy/phy-airoha-pcie.c +@@ -802,7 +802,7 @@ static void airoha_pcie_phy_init_ssc_jcpll(struct airoha_pcie_phy *pcie_phy) + airoha_phy_csr_2l_set_bits(pcie_phy, REG_CSR_2L_JCPLL_SDM_IFM, + CSR_2L_PXP_JCPLL_SDM_IFM); + airoha_phy_csr_2l_set_bits(pcie_phy, REG_CSR_2L_JCPLL_SDM_HREN, +- REG_CSR_2L_JCPLL_SDM_HREN); ++ CSR_2L_PXP_JCPLL_SDM_HREN); + airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_JCPLL_RST_DLY, + CSR_2L_PXP_JCPLL_SDM_DI_EN); + airoha_phy_csr_2l_set_bits(pcie_phy, REG_CSR_2L_JCPLL_SSC, +-- +2.43.0 + diff --git a/queue-6.12/phy-airoha-fix-reg_csr_2l_pll_cmn_reserve0-config-in.patch b/queue-6.12/phy-airoha-fix-reg_csr_2l_pll_cmn_reserve0-config-in.patch new file mode 100644 index 00000000000..20d60049239 --- /dev/null +++ b/queue-6.12/phy-airoha-fix-reg_csr_2l_pll_cmn_reserve0-config-in.patch @@ -0,0 +1,38 @@ +From e40eaf5f8944a6abd675ee70a7101928583ec121 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Wed, 18 Sep 2024 15:32:52 +0200 +Subject: phy: airoha: Fix REG_CSR_2L_PLL_CMN_RESERVE0 config in + airoha_pcie_phy_init_clk_out() + +From: Lorenzo Bianconi <lorenzo@kernel.org> + +[ Upstream commit 09a19fb75498985cbb598f1fa43a7d2416925c30 ] + +Fix typo configuring REG_CSR_2L_PLL_CMN_RESERVE0 register in +airoha_pcie_phy_init_clk_out routine. + +Fixes: d7d2818b9383 ("phy: airoha: Add PCIe PHY driver for EN7581 SoC.") +Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org> +Link: https://lore.kernel.org/r/20240918-airoha-en7581-phy-fixes-v1-1-8291729a87f8@kernel.org +Signed-off-by: Vinod Koul <vkoul@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/phy/phy-airoha-pcie.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/phy/phy-airoha-pcie.c b/drivers/phy/phy-airoha-pcie.c +index 1e410eb410580..4624aa9dd7127 100644 +--- a/drivers/phy/phy-airoha-pcie.c ++++ b/drivers/phy/phy-airoha-pcie.c +@@ -459,7 +459,7 @@ static void airoha_pcie_phy_init_clk_out(struct airoha_pcie_phy *pcie_phy) + airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_CLKTX1_OFFSET, + CSR_2L_PXP_CLKTX1_SR); + airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_PLL_CMN_RESERVE0, +- CSR_2L_PXP_PLL_RESERVE_MASK, 0xdd); ++ CSR_2L_PXP_PLL_RESERVE_MASK, 0xd0d); + } + + static void airoha_pcie_phy_init_csr_2l(struct airoha_pcie_phy *pcie_phy) +-- +2.43.0 + diff --git a/queue-6.12/phy-airoha-fix-reg_csr_2l_rx-0-1-_rev0-definitions.patch b/queue-6.12/phy-airoha-fix-reg_csr_2l_rx-0-1-_rev0-definitions.patch new file mode 100644 index 00000000000..684394faa3d --- /dev/null +++ b/queue-6.12/phy-airoha-fix-reg_csr_2l_rx-0-1-_rev0-definitions.patch @@ -0,0 +1,44 @@ +From adf74131258a5cd8145073da3cdce84d46fc593b Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Wed, 18 Sep 2024 15:32:55 +0200 +Subject: phy: airoha: Fix REG_CSR_2L_RX{0,1}_REV0 definitions + +From: Lorenzo Bianconi <lorenzo@kernel.org> + +[ Upstream commit e56272f2bb8314eb13b0eb0a4e8055831c700255 ] + +Fix the following register definitions for REG_CSR_2L_RX{0,1}_REV0 +registers: +- CSR_2L_PXP_VOS_PNINV +- CSR_2L_PXP_FE_GAIN_NORMAL_MODE +- CSR_2L_PXP_FE_GAIN_TRAIN_MODE + +Fixes: d7d2818b9383 ("phy: airoha: Add PCIe PHY driver for EN7581 SoC.") +Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org> +Link: https://lore.kernel.org/r/20240918-airoha-en7581-phy-fixes-v1-4-8291729a87f8@kernel.org +Signed-off-by: Vinod Koul <vkoul@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/phy/phy-airoha-pcie-regs.h | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/drivers/phy/phy-airoha-pcie-regs.h b/drivers/phy/phy-airoha-pcie-regs.h +index bb1f679ca1dfa..b938a7b468fee 100644 +--- a/drivers/phy/phy-airoha-pcie-regs.h ++++ b/drivers/phy/phy-airoha-pcie-regs.h +@@ -197,9 +197,9 @@ + #define CSR_2L_PXP_TX1_MULTLANE_EN BIT(0) + + #define REG_CSR_2L_RX0_REV0 0x00fc +-#define CSR_2L_PXP_VOS_PNINV GENMASK(3, 2) +-#define CSR_2L_PXP_FE_GAIN_NORMAL_MODE GENMASK(6, 4) +-#define CSR_2L_PXP_FE_GAIN_TRAIN_MODE GENMASK(10, 8) ++#define CSR_2L_PXP_VOS_PNINV GENMASK(19, 18) ++#define CSR_2L_PXP_FE_GAIN_NORMAL_MODE GENMASK(22, 20) ++#define CSR_2L_PXP_FE_GAIN_TRAIN_MODE GENMASK(26, 24) + + #define REG_CSR_2L_RX0_PHYCK_DIV 0x0100 + #define CSR_2L_PXP_RX0_PHYCK_SEL GENMASK(9, 8) +-- +2.43.0 + diff --git a/queue-6.12/phy-airoha-fix-reg_pcie_pma_tx_reset-config-in-airoh.patch b/queue-6.12/phy-airoha-fix-reg_pcie_pma_tx_reset-config-in-airoh.patch new file mode 100644 index 00000000000..486be33e669 --- /dev/null +++ b/queue-6.12/phy-airoha-fix-reg_pcie_pma_tx_reset-config-in-airoh.patch @@ -0,0 +1,41 @@ +From e9f8c1ca554f36b0112883da1d2f874ba5c11214 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Wed, 18 Sep 2024 15:32:53 +0200 +Subject: phy: airoha: Fix REG_PCIE_PMA_TX_RESET config in + airoha_pcie_phy_init_csr_2l() + +From: Lorenzo Bianconi <lorenzo@kernel.org> + +[ Upstream commit f9c5d6369d3e8e36b7beb15e86b1ef0911ace85f ] + +Fix typos configuring REG_PCIE_PMA_TX_RESET register in +airoha_pcie_phy_init_csr_2l routine for lane0 and lane1 + +Fixes: d7d2818b9383 ("phy: airoha: Add PCIe PHY driver for EN7581 SoC.") +Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org> +Link: https://lore.kernel.org/r/20240918-airoha-en7581-phy-fixes-v1-2-8291729a87f8@kernel.org +Signed-off-by: Vinod Koul <vkoul@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/phy/phy-airoha-pcie.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/phy/phy-airoha-pcie.c b/drivers/phy/phy-airoha-pcie.c +index 4624aa9dd7127..9a7ce65f87f05 100644 +--- a/drivers/phy/phy-airoha-pcie.c ++++ b/drivers/phy/phy-airoha-pcie.c +@@ -471,9 +471,9 @@ static void airoha_pcie_phy_init_csr_2l(struct airoha_pcie_phy *pcie_phy) + PCIE_SW_XFI_RXPCS_RST | PCIE_SW_REF_RST | + PCIE_SW_RX_RST); + airoha_phy_pma0_set_bits(pcie_phy, REG_PCIE_PMA_TX_RESET, +- PCIE_TX_TOP_RST | REG_PCIE_PMA_TX_RESET); ++ PCIE_TX_TOP_RST | PCIE_TX_CAL_RST); + airoha_phy_pma1_set_bits(pcie_phy, REG_PCIE_PMA_TX_RESET, +- PCIE_TX_TOP_RST | REG_PCIE_PMA_TX_RESET); ++ PCIE_TX_TOP_RST | PCIE_TX_CAL_RST); + } + + static void airoha_pcie_phy_init_rx(struct airoha_pcie_phy *pcie_phy) +-- +2.43.0 + diff --git a/queue-6.12/phy-realtek-usb-fix-null-deref-in-rtk_usb2phy_probe.patch b/queue-6.12/phy-realtek-usb-fix-null-deref-in-rtk_usb2phy_probe.patch new file mode 100644 index 00000000000..ebef30a5c95 --- /dev/null +++ b/queue-6.12/phy-realtek-usb-fix-null-deref-in-rtk_usb2phy_probe.patch @@ -0,0 +1,37 @@ +From 9bb332e9b1ae0ed39a9079f5d517ee2dfa22b0f5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Fri, 25 Oct 2024 14:59:12 +0800 +Subject: phy: realtek: usb: fix NULL deref in rtk_usb2phy_probe + +From: Charles Han <hanchunchao@inspur.com> + +[ Upstream commit 04e3e9188291a183b27306ddb833722c0d083d6a ] + +In rtk_usb2phy_probe() devm_kzalloc() may return NULL +but this returned value is not checked. + +Fixes: 134e6d25f6bd ("phy: realtek: usb: Add driver for the Realtek SoC USB 2.0 PHY") +Signed-off-by: Charles Han <hanchunchao@inspur.com> +Link: https://lore.kernel.org/r/20241025065912.143692-1-hanchunchao@inspur.com +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/phy/realtek/phy-rtk-usb2.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/phy/realtek/phy-rtk-usb2.c b/drivers/phy/realtek/phy-rtk-usb2.c +index e3ad7cea51099..e8ca2ec5998fe 100644 +--- a/drivers/phy/realtek/phy-rtk-usb2.c ++++ b/drivers/phy/realtek/phy-rtk-usb2.c +@@ -1023,6 +1023,8 @@ static int rtk_usb2phy_probe(struct platform_device *pdev) + + rtk_phy->dev = &pdev->dev; + rtk_phy->phy_cfg = devm_kzalloc(dev, sizeof(*phy_cfg), GFP_KERNEL); ++ if (!rtk_phy->phy_cfg) ++ return -ENOMEM; + + memcpy(rtk_phy->phy_cfg, phy_cfg, sizeof(*phy_cfg)); + +-- +2.43.0 + diff --git a/queue-6.12/phy-realtek-usb-fix-null-deref-in-rtk_usb3phy_probe.patch b/queue-6.12/phy-realtek-usb-fix-null-deref-in-rtk_usb3phy_probe.patch new file mode 100644 index 00000000000..781e40f03ae --- /dev/null +++ b/queue-6.12/phy-realtek-usb-fix-null-deref-in-rtk_usb3phy_probe.patch @@ -0,0 +1,37 @@ +From 33514083865b630553349784161691d6c1ec77e2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Fri, 25 Oct 2024 15:07:44 +0800 +Subject: phy: realtek: usb: fix NULL deref in rtk_usb3phy_probe + +From: Charles Han <hanchunchao@inspur.com> + +[ Upstream commit bf373d2919d98f3d1fe1b19a0304f72fe74386d9 ] + +In rtk_usb3phy_probe() devm_kzalloc() may return NULL +but this returned value is not checked. + +Fixes: adda6e82a7de ("phy: realtek: usb: Add driver for the Realtek SoC USB 3.0 PHY") +Signed-off-by: Charles Han <hanchunchao@inspur.com> +Link: https://lore.kernel.org/r/20241025070744.149070-1-hanchunchao@inspur.com +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/phy/realtek/phy-rtk-usb3.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/phy/realtek/phy-rtk-usb3.c b/drivers/phy/realtek/phy-rtk-usb3.c +index dfcf4b921bba6..96af483e5444b 100644 +--- a/drivers/phy/realtek/phy-rtk-usb3.c ++++ b/drivers/phy/realtek/phy-rtk-usb3.c +@@ -577,6 +577,8 @@ static int rtk_usb3phy_probe(struct platform_device *pdev) + + rtk_phy->dev = &pdev->dev; + rtk_phy->phy_cfg = devm_kzalloc(dev, sizeof(*phy_cfg), GFP_KERNEL); ++ if (!rtk_phy->phy_cfg) ++ return -ENOMEM; + + memcpy(rtk_phy->phy_cfg, phy_cfg, sizeof(*phy_cfg)); + +-- +2.43.0 + diff --git a/queue-6.12/pinctrl-k210-undef-k210_pc_default.patch b/queue-6.12/pinctrl-k210-undef-k210_pc_default.patch new file mode 100644 index 00000000000..3e30d22b40c --- /dev/null +++ b/queue-6.12/pinctrl-k210-undef-k210_pc_default.patch @@ -0,0 +1,39 @@ +From c6c77ad3958421741e2585f8352bd014ed8a4f87 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Wed, 13 Nov 2024 15:12:01 +0800 +Subject: pinctrl: k210: Undef K210_PC_DEFAULT + +From: zhang jiao <zhangjiao2@cmss.chinamobile.com> + +[ Upstream commit 7e86490c5dee5c41a55f32d0dc34269e200e6909 ] + +When the temporary macro K210_PC_DEFAULT is not needed anymore, +use its name in the #undef statement instead of +the incorrect "DEFAULT" name. + +Fixes: d4c34d09ab03 ("pinctrl: Add RISC-V Canaan Kendryte K210 FPIOA driver") +Signed-off-by: zhang jiao <zhangjiao2@cmss.chinamobile.com> +Reviewed-by: Damien Le Moal <dlemoal@kernel.org> +Link: https://lore.kernel.org/20241113071201.5440-1-zhangjiao2@cmss.chinamobile.com +Signed-off-by: Linus Walleij <linus.walleij@linaro.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/pinctrl/pinctrl-k210.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/pinctrl/pinctrl-k210.c b/drivers/pinctrl/pinctrl-k210.c +index 0f6b55fec31de..a71805997b028 100644 +--- a/drivers/pinctrl/pinctrl-k210.c ++++ b/drivers/pinctrl/pinctrl-k210.c +@@ -183,7 +183,7 @@ static const u32 k210_pinconf_mode_id_to_mode[] = { + [K210_PC_DEFAULT_INT13] = K210_PC_MODE_IN | K210_PC_PU, + }; + +-#undef DEFAULT ++#undef K210_PC_DEFAULT + + /* + * Pin functions configuration information. +-- +2.43.0 + diff --git a/queue-6.12/pinctrl-renesas-rzg2l-fix-missing-return-in-rzg2l_pi.patch b/queue-6.12/pinctrl-renesas-rzg2l-fix-missing-return-in-rzg2l_pi.patch new file mode 100644 index 00000000000..c4790454b7a --- /dev/null +++ b/queue-6.12/pinctrl-renesas-rzg2l-fix-missing-return-in-rzg2l_pi.patch @@ -0,0 +1,41 @@ +From 3c9d11bc6992c830a291e24cbaefec8c0b307758 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Thu, 3 Oct 2024 09:25:48 +0100 +Subject: pinctrl: renesas: rzg2l: Fix missing return in + rzg2l_pinctrl_register() + +From: Biju Das <biju.das.jz@bp.renesas.com> + +[ Upstream commit 1737715a4c2c08f207c94cc1f3af3c5945318d29 ] + +Fix the missing return statement in the error path of +rzg2l_pinctrl_register(). + +Fixes: f73f63b24491fa43 ("pinctrl: renesas: rzg2l: Use dev_err_probe()") +Reported-by: Nobuhiro Iwamatsu <nobuhiro1.iwamatsu@toshiba.co.jp> +Closes: https://lore.kernel.org/all/OS0PR01MB638837327E5487B71D88A70392712@OS0PR01MB6388.jpnprd01.prod.outlook.com/ +Signed-off-by: Biju Das <biju.das.jz@bp.renesas.com> +Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be> +Link: https://lore.kernel.org/20241003082550.33341-1-biju.das.jz@bp.renesas.com +Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/pinctrl/renesas/pinctrl-rzg2l.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/pinctrl/renesas/pinctrl-rzg2l.c b/drivers/pinctrl/renesas/pinctrl-rzg2l.c +index 5a403915fed2c..3a81837b5e623 100644 +--- a/drivers/pinctrl/renesas/pinctrl-rzg2l.c ++++ b/drivers/pinctrl/renesas/pinctrl-rzg2l.c +@@ -2710,7 +2710,7 @@ static int rzg2l_pinctrl_register(struct rzg2l_pinctrl *pctrl) + + ret = pinctrl_enable(pctrl->pctl); + if (ret) +- dev_err_probe(pctrl->dev, ret, "pinctrl enable failed\n"); ++ return dev_err_probe(pctrl->dev, ret, "pinctrl enable failed\n"); + + ret = rzg2l_gpio_register(pctrl); + if (ret) +-- +2.43.0 + diff --git a/queue-6.12/pinctrl-renesas-select-pinctrl_rzg2l-for-rz-v2h-p-so.patch b/queue-6.12/pinctrl-renesas-select-pinctrl_rzg2l-for-rz-v2h-p-so.patch new file mode 100644 index 00000000000..08274392585 --- /dev/null +++ b/queue-6.12/pinctrl-renesas-select-pinctrl_rzg2l-for-rz-v2h-p-so.patch @@ -0,0 +1,39 @@ +From 73263aabb9ce65d678337b5b2ed6af6062421629 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Thu, 10 Oct 2024 14:27:26 +0100 +Subject: pinctrl: renesas: Select PINCTRL_RZG2L for RZ/V2H(P) SoC + +From: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com> + +[ Upstream commit 5dcde519a067ac5c85c273e550dde1873e2199bf ] + +Add explicit selection of the PINCTRL_RZG2L config option for the +RZ/V2H(P) (R9A09G057) SoC, ensuring pin control driver is enabled +for this SoC. + +Fixes: 9bd95ac86e70 ("pinctrl: renesas: rzg2l: Add support for RZ/V2H SoC") +Reported-by: Biju Das <biju.das.jz@bp.renesas.com> +Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com> +Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be> +Link: https://lore.kernel.org/20241010132726.702658-1-prabhakar.mahadev-lad.rj@bp.renesas.com +Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/pinctrl/renesas/Kconfig | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/pinctrl/renesas/Kconfig b/drivers/pinctrl/renesas/Kconfig +index 14bd55d647319..7f3f41c7fe54c 100644 +--- a/drivers/pinctrl/renesas/Kconfig ++++ b/drivers/pinctrl/renesas/Kconfig +@@ -41,6 +41,7 @@ config PINCTRL_RENESAS + select PINCTRL_PFC_R8A779H0 if ARCH_R8A779H0 + select PINCTRL_RZG2L if ARCH_RZG2L + select PINCTRL_RZV2M if ARCH_R9A09G011 ++ select PINCTRL_RZG2L if ARCH_R9A09G057 + select PINCTRL_PFC_SH7203 if CPU_SUBTYPE_SH7203 + select PINCTRL_PFC_SH7264 if CPU_SUBTYPE_SH7264 + select PINCTRL_PFC_SH7269 if CPU_SUBTYPE_SH7269 +-- +2.43.0 + diff --git a/queue-6.12/pinctrl-zynqmp-drop-excess-struct-member-description.patch b/queue-6.12/pinctrl-zynqmp-drop-excess-struct-member-description.patch new file mode 100644 index 00000000000..bdb8595fb84 --- /dev/null +++ b/queue-6.12/pinctrl-zynqmp-drop-excess-struct-member-description.patch @@ -0,0 +1,36 @@ +From 82187de467e8832898ac13449be2e34a98e51d21 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Thu, 10 Oct 2024 10:04:32 +0200 +Subject: pinctrl: zynqmp: drop excess struct member description + +From: Bartosz Golaszewski <bartosz.golaszewski@linaro.org> + +[ Upstream commit 2a85fc7044987d751f27d7f1e4423eebbcecc2c6 ] + +The 'node' member has never been part of this structure so drop its +description. + +Fixes: 8b242ca700f8 ("pinctrl: Add Xilinx ZynqMP pinctrl driver support") +Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org> +Link: https://lore.kernel.org/20241010080432.7781-1-brgl@bgdev.pl +Signed-off-by: Linus Walleij <linus.walleij@linaro.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/pinctrl/pinctrl-zynqmp.c | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/drivers/pinctrl/pinctrl-zynqmp.c b/drivers/pinctrl/pinctrl-zynqmp.c +index 3c6d56fdb8c96..93454d2a26bcc 100644 +--- a/drivers/pinctrl/pinctrl-zynqmp.c ++++ b/drivers/pinctrl/pinctrl-zynqmp.c +@@ -49,7 +49,6 @@ + * @name: Name of the pin mux function + * @groups: List of pin groups for this function + * @ngroups: Number of entries in @groups +- * @node: Firmware node matching with the function + * + * This structure holds information about pin control function + * and function group names supporting that function. +-- +2.43.0 + diff --git a/queue-6.12/platform-x86-asus-wmi-fix-inconsistent-use-of-therma.patch b/queue-6.12/platform-x86-asus-wmi-fix-inconsistent-use-of-therma.patch new file mode 100644 index 00000000000..c1a4b5fdcfc --- /dev/null +++ b/queue-6.12/platform-x86-asus-wmi-fix-inconsistent-use-of-therma.patch @@ -0,0 +1,138 @@ +From 473538006d00418d49f14c69c1c9774fcdc065f9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Thu, 7 Nov 2024 01:38:10 +0100 +Subject: platform/x86: asus-wmi: Fix inconsistent use of thermal policies +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Armin Wolf <W_Armin@gmx.de> + +[ Upstream commit 895085ec3f2ed7a26389943729e2904df1f88dc0 ] + +When changing the thermal policy using the platform profile API, +a Vivobook thermal policy is stored in throttle_thermal_policy_mode. + +However everywhere else a normal thermal policy is stored inside this +variable, potentially confusing the platform profile. + +Fix this by always storing normal thermal policy values inside +throttle_thermal_policy_mode and only do the conversion when writing +the thermal policy to hardware. This also fixes the order in which +throttle_thermal_policy_switch_next() steps through the thermal modes +on Vivobook machines. + +Tested-by: Casey G Bowman <casey.g.bowman@intel.com> +Fixes: bcbfcebda2cb ("platform/x86: asus-wmi: add support for vivobook fan profiles") +Signed-off-by: Armin Wolf <W_Armin@gmx.de> +Reviewed-by: Hans de Goede <hdegoede@redhat.com> +Link: https://lore.kernel.org/r/20241107003811.615574-2-W_Armin@gmx.de +Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com> +Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/platform/x86/asus-wmi.c | 64 +++++++++++---------------------- + 1 file changed, 21 insertions(+), 43 deletions(-) + +diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c +index abdca3f05c5c1..89f5f44857d55 100644 +--- a/drivers/platform/x86/asus-wmi.c ++++ b/drivers/platform/x86/asus-wmi.c +@@ -3696,10 +3696,28 @@ static int asus_wmi_custom_fan_curve_init(struct asus_wmi *asus) + /* Throttle thermal policy ****************************************************/ + static int throttle_thermal_policy_write(struct asus_wmi *asus) + { +- u8 value = asus->throttle_thermal_policy_mode; + u32 retval; ++ u8 value; + int err; + ++ if (asus->throttle_thermal_policy_dev == ASUS_WMI_DEVID_THROTTLE_THERMAL_POLICY_VIVO) { ++ switch (asus->throttle_thermal_policy_mode) { ++ case ASUS_THROTTLE_THERMAL_POLICY_DEFAULT: ++ value = ASUS_THROTTLE_THERMAL_POLICY_DEFAULT_VIVO; ++ break; ++ case ASUS_THROTTLE_THERMAL_POLICY_OVERBOOST: ++ value = ASUS_THROTTLE_THERMAL_POLICY_OVERBOOST_VIVO; ++ break; ++ case ASUS_THROTTLE_THERMAL_POLICY_SILENT: ++ value = ASUS_THROTTLE_THERMAL_POLICY_SILENT_VIVO; ++ break; ++ default: ++ return -EINVAL; ++ } ++ } else { ++ value = asus->throttle_thermal_policy_mode; ++ } ++ + err = asus_wmi_set_devstate(asus->throttle_thermal_policy_dev, + value, &retval); + +@@ -3804,46 +3822,6 @@ static ssize_t throttle_thermal_policy_store(struct device *dev, + static DEVICE_ATTR_RW(throttle_thermal_policy); + + /* Platform profile ***********************************************************/ +-static int asus_wmi_platform_profile_to_vivo(struct asus_wmi *asus, int mode) +-{ +- bool vivo; +- +- vivo = asus->throttle_thermal_policy_dev == ASUS_WMI_DEVID_THROTTLE_THERMAL_POLICY_VIVO; +- +- if (vivo) { +- switch (mode) { +- case ASUS_THROTTLE_THERMAL_POLICY_DEFAULT: +- return ASUS_THROTTLE_THERMAL_POLICY_DEFAULT_VIVO; +- case ASUS_THROTTLE_THERMAL_POLICY_OVERBOOST: +- return ASUS_THROTTLE_THERMAL_POLICY_OVERBOOST_VIVO; +- case ASUS_THROTTLE_THERMAL_POLICY_SILENT: +- return ASUS_THROTTLE_THERMAL_POLICY_SILENT_VIVO; +- } +- } +- +- return mode; +-} +- +-static int asus_wmi_platform_profile_mode_from_vivo(struct asus_wmi *asus, int mode) +-{ +- bool vivo; +- +- vivo = asus->throttle_thermal_policy_dev == ASUS_WMI_DEVID_THROTTLE_THERMAL_POLICY_VIVO; +- +- if (vivo) { +- switch (mode) { +- case ASUS_THROTTLE_THERMAL_POLICY_DEFAULT_VIVO: +- return ASUS_THROTTLE_THERMAL_POLICY_DEFAULT; +- case ASUS_THROTTLE_THERMAL_POLICY_OVERBOOST_VIVO: +- return ASUS_THROTTLE_THERMAL_POLICY_OVERBOOST; +- case ASUS_THROTTLE_THERMAL_POLICY_SILENT_VIVO: +- return ASUS_THROTTLE_THERMAL_POLICY_SILENT; +- } +- } +- +- return mode; +-} +- + static int asus_wmi_platform_profile_get(struct platform_profile_handler *pprof, + enum platform_profile_option *profile) + { +@@ -3853,7 +3831,7 @@ static int asus_wmi_platform_profile_get(struct platform_profile_handler *pprof, + asus = container_of(pprof, struct asus_wmi, platform_profile_handler); + tp = asus->throttle_thermal_policy_mode; + +- switch (asus_wmi_platform_profile_mode_from_vivo(asus, tp)) { ++ switch (tp) { + case ASUS_THROTTLE_THERMAL_POLICY_DEFAULT: + *profile = PLATFORM_PROFILE_BALANCED; + break; +@@ -3892,7 +3870,7 @@ static int asus_wmi_platform_profile_set(struct platform_profile_handler *pprof, + return -EOPNOTSUPP; + } + +- asus->throttle_thermal_policy_mode = asus_wmi_platform_profile_to_vivo(asus, tp); ++ asus->throttle_thermal_policy_mode = tp; + return throttle_thermal_policy_write(asus); + } + +-- +2.43.0 + diff --git a/queue-6.12/platform-x86-intel-pmt-allow-user-offset-for-pmt-cal.patch b/queue-6.12/platform-x86-intel-pmt-allow-user-offset-for-pmt-cal.patch new file mode 100644 index 00000000000..7f4e15acc0e --- /dev/null +++ b/queue-6.12/platform-x86-intel-pmt-allow-user-offset-for-pmt-cal.patch @@ -0,0 +1,110 @@ +From 7c484595f78096ecfbf3e8a41e3d5b10ebd69527 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Thu, 14 Nov 2024 08:03:57 -0500 +Subject: platform/x86/intel/pmt: allow user offset for PMT callbacks +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Michael J. Ruhl <michael.j.ruhl@intel.com> + +[ Upstream commit 0c32840763b1579c923b4216c18bb756ca4ba473 ] + +Usage of the telem sysfs file allows for partial reads at an offset. +The current callback method returns the buffer starting from offset 0 +only. + +Include the requested offset in the callback and update the necessary +address calculations with the offset. + +Note: offset addition is moved from the caller to the local usage. For +non-callback usage this is unchanged behavior. + +Fixes: e92affc74cd8 ("platform/x86/intel/vsec: Add PMT read callbacks") +Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com> +Signed-off-by: Michael J. Ruhl <michael.j.ruhl@intel.com> +Link: https://lore.kernel.org/r/20241114130358.2467787-2-michael.j.ruhl@intel.com +Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com> +Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/platform/x86/intel/pmt/class.c | 8 +++++--- + drivers/platform/x86/intel/pmt/class.h | 2 +- + drivers/platform/x86/intel/pmt/telemetry.c | 2 +- + include/linux/intel_vsec.h | 3 ++- + 4 files changed, 9 insertions(+), 6 deletions(-) + +diff --git a/drivers/platform/x86/intel/pmt/class.c b/drivers/platform/x86/intel/pmt/class.c +index c04bb7f97a4db..c3ca2ac91b056 100644 +--- a/drivers/platform/x86/intel/pmt/class.c ++++ b/drivers/platform/x86/intel/pmt/class.c +@@ -59,10 +59,12 @@ pmt_memcpy64_fromio(void *to, const u64 __iomem *from, size_t count) + } + + int pmt_telem_read_mmio(struct pci_dev *pdev, struct pmt_callbacks *cb, u32 guid, void *buf, +- void __iomem *addr, u32 count) ++ void __iomem *addr, loff_t off, u32 count) + { + if (cb && cb->read_telem) +- return cb->read_telem(pdev, guid, buf, count); ++ return cb->read_telem(pdev, guid, buf, off, count); ++ ++ addr += off; + + if (guid == GUID_SPR_PUNIT) + /* PUNIT on SPR only supports aligned 64-bit read */ +@@ -96,7 +98,7 @@ intel_pmt_read(struct file *filp, struct kobject *kobj, + count = entry->size - off; + + count = pmt_telem_read_mmio(entry->ep->pcidev, entry->cb, entry->header.guid, buf, +- entry->base + off, count); ++ entry->base, off, count); + + return count; + } +diff --git a/drivers/platform/x86/intel/pmt/class.h b/drivers/platform/x86/intel/pmt/class.h +index a267ac9644230..b2006d57779d6 100644 +--- a/drivers/platform/x86/intel/pmt/class.h ++++ b/drivers/platform/x86/intel/pmt/class.h +@@ -62,7 +62,7 @@ struct intel_pmt_namespace { + }; + + int pmt_telem_read_mmio(struct pci_dev *pdev, struct pmt_callbacks *cb, u32 guid, void *buf, +- void __iomem *addr, u32 count); ++ void __iomem *addr, loff_t off, u32 count); + bool intel_pmt_is_early_client_hw(struct device *dev); + int intel_pmt_dev_create(struct intel_pmt_entry *entry, + struct intel_pmt_namespace *ns, +diff --git a/drivers/platform/x86/intel/pmt/telemetry.c b/drivers/platform/x86/intel/pmt/telemetry.c +index c9feac859e574..0cea617c6c2e2 100644 +--- a/drivers/platform/x86/intel/pmt/telemetry.c ++++ b/drivers/platform/x86/intel/pmt/telemetry.c +@@ -219,7 +219,7 @@ int pmt_telem_read(struct telem_endpoint *ep, u32 id, u64 *data, u32 count) + if (offset + NUM_BYTES_QWORD(count) > size) + return -EINVAL; + +- pmt_telem_read_mmio(ep->pcidev, ep->cb, ep->header.guid, data, ep->base + offset, ++ pmt_telem_read_mmio(ep->pcidev, ep->cb, ep->header.guid, data, ep->base, offset, + NUM_BYTES_QWORD(count)); + + return ep->present ? 0 : -EPIPE; +diff --git a/include/linux/intel_vsec.h b/include/linux/intel_vsec.h +index 11ee185566c31..b94beab64610b 100644 +--- a/include/linux/intel_vsec.h ++++ b/include/linux/intel_vsec.h +@@ -74,10 +74,11 @@ enum intel_vsec_quirks { + * @pdev: PCI device reference for the callback's use + * @guid: ID of data to acccss + * @data: buffer for the data to be copied ++ * @off: offset into the requested buffer + * @count: size of buffer + */ + struct pmt_callbacks { +- int (*read_telem)(struct pci_dev *pdev, u32 guid, u64 *data, u32 count); ++ int (*read_telem)(struct pci_dev *pdev, u32 guid, u64 *data, loff_t off, u32 count); + }; + + /** +-- +2.43.0 + diff --git a/queue-6.12/platform-x86-panasonic-laptop-return-errno-correctly.patch b/queue-6.12/platform-x86-panasonic-laptop-return-errno-correctly.patch new file mode 100644 index 00000000000..1812310dc75 --- /dev/null +++ b/queue-6.12/platform-x86-panasonic-laptop-return-errno-correctly.patch @@ -0,0 +1,60 @@ +From cae7f77822b222888a179a49c67117c10602bbfe Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Mon, 18 Nov 2024 06:46:39 +0000 +Subject: platform/x86: panasonic-laptop: Return errno correctly in show + callback +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Yao Zi <ziyao@disroot.org> + +[ Upstream commit 5c7bebc1a3f0661db558d60e14dde27fc216d9dc ] + +When an error occurs in sysfs show callback, we should return the errno +directly instead of formatting it as the result, which produces +meaningless output and doesn't inform the userspace of the error. + +Fixes: 468f96bfa3a0 ("platform/x86: panasonic-laptop: Add support for battery charging threshold (eco mode)") +Fixes: d5a81d8e864b ("platform/x86: panasonic-laptop: Add support for optical driver power in Y and W series") +Signed-off-by: Yao Zi <ziyao@disroot.org> +Reviewed-by: Hans de Goede <hdegoede@redhat.com> +Link: https://lore.kernel.org/r/20241118064637.61832-3-ziyao@disroot.org +Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com> +Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/platform/x86/panasonic-laptop.c | 10 +++++++--- + 1 file changed, 7 insertions(+), 3 deletions(-) + +diff --git a/drivers/platform/x86/panasonic-laptop.c b/drivers/platform/x86/panasonic-laptop.c +index 2bf94d0ab3243..22ca70eb82271 100644 +--- a/drivers/platform/x86/panasonic-laptop.c ++++ b/drivers/platform/x86/panasonic-laptop.c +@@ -614,8 +614,7 @@ static ssize_t eco_mode_show(struct device *dev, struct device_attribute *attr, + result = 1; + break; + default: +- result = -EIO; +- break; ++ return -EIO; + } + return sysfs_emit(buf, "%u\n", result); + } +@@ -761,7 +760,12 @@ static ssize_t current_brightness_store(struct device *dev, struct device_attrib + static ssize_t cdpower_show(struct device *dev, struct device_attribute *attr, + char *buf) + { +- return sysfs_emit(buf, "%d\n", get_optd_power_state()); ++ int state = get_optd_power_state(); ++ ++ if (state < 0) ++ return state; ++ ++ return sysfs_emit(buf, "%d\n", state); + } + + static ssize_t cdpower_store(struct device *dev, struct device_attribute *attr, +-- +2.43.0 + diff --git a/queue-6.12/pmdomain-ti-sci-add-missing-of_node_put-for-args.np.patch b/queue-6.12/pmdomain-ti-sci-add-missing-of_node_put-for-args.np.patch new file mode 100644 index 00000000000..e8242af9e5f --- /dev/null +++ b/queue-6.12/pmdomain-ti-sci-add-missing-of_node_put-for-args.np.patch @@ -0,0 +1,48 @@ +From 52dc1152e5ffd3d96baadd1762a221e55dc3821c Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Thu, 24 Oct 2024 11:04:41 +0800 +Subject: pmdomain: ti-sci: Add missing of_node_put() for args.np + +From: Zhang Zekun <zhangzekun11@huawei.com> + +[ Upstream commit afc2331ef81657493c074592c409dac7c3cb8ccc ] + +of_parse_phandle_with_args() needs to call of_node_put() to decrement +the refcount of args.np. So, Add the missing of_node_put() in the loop. + +Fixes: efa5c01cd7ee ("soc: ti: ti_sci_pm_domains: switch to use multiple genpds instead of one") +Signed-off-by: Zhang Zekun <zhangzekun11@huawei.com> +Reviewed-by: Dhruva Gole <d-gole@ti.com> +Message-ID: <20241024030442.119506-2-zhangzekun11@huawei.com> +Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/pmdomain/ti/ti_sci_pm_domains.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/drivers/pmdomain/ti/ti_sci_pm_domains.c b/drivers/pmdomain/ti/ti_sci_pm_domains.c +index 1510d5ddae3de..0df3eb7ff09a3 100644 +--- a/drivers/pmdomain/ti/ti_sci_pm_domains.c ++++ b/drivers/pmdomain/ti/ti_sci_pm_domains.c +@@ -161,6 +161,7 @@ static int ti_sci_pm_domain_probe(struct platform_device *pdev) + break; + + if (args.args_count >= 1 && args.np == dev->of_node) { ++ of_node_put(args.np); + if (args.args[0] > max_id) { + max_id = args.args[0]; + } else { +@@ -192,7 +193,10 @@ static int ti_sci_pm_domain_probe(struct platform_device *pdev) + pm_genpd_init(&pd->pd, NULL, true); + + list_add(&pd->node, &pd_provider->pd_list); ++ } else { ++ of_node_put(args.np); + } ++ + index++; + } + } +-- +2.43.0 + diff --git a/queue-6.12/power-reset-ep93xx-add-auxiliary_bus-dependency.patch b/queue-6.12/power-reset-ep93xx-add-auxiliary_bus-dependency.patch new file mode 100644 index 00000000000..13d1ae6dcf9 --- /dev/null +++ b/queue-6.12/power-reset-ep93xx-add-auxiliary_bus-dependency.patch @@ -0,0 +1,42 @@ +From c582662511b7fa8f4fc4edf14b9d99717bc57bd9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Mon, 11 Nov 2024 11:44:12 +0100 +Subject: power: reset: ep93xx: add AUXILIARY_BUS dependency + +From: Arnd Bergmann <arnd@arndb.de> + +[ Upstream commit b6d445f6724deda3fd87fa33358009d947a64c5d ] + +This fails to link when compile-testing and the auxiliary bus is not built-in: + +x86_64-linux-ld: drivers/power/reset/ep93xx-restart.o: in function `ep93xx_reboot_driver_init': +ep93xx-restart.c:(.init.text+0x11): undefined reference to `__auxiliary_driver_register' +x86_64-linux-ld: drivers/power/reset/ep93xx-restart.o: in function `ep93xx_reboot_driver_exit': +ep93xx-restart.c:(.exit.text+0x8): undefined reference to `auxiliary_driver_unregister' + +Add the appropriate dependency. + +Fixes: 9fa7cdb4368f ("power: reset: Add a driver for the ep93xx reset") +Signed-off-by: Arnd Bergmann <arnd@arndb.de> +Link: https://lore.kernel.org/r/20241111104418.3891756-1-arnd@kernel.org +Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/power/reset/Kconfig | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/power/reset/Kconfig b/drivers/power/reset/Kconfig +index 389d5a193e5dc..f5fc33a8bf443 100644 +--- a/drivers/power/reset/Kconfig ++++ b/drivers/power/reset/Kconfig +@@ -79,6 +79,7 @@ config POWER_RESET_EP93XX + bool "Cirrus EP93XX reset driver" if COMPILE_TEST + depends on MFD_SYSCON + default ARCH_EP93XX ++ select AUXILIARY_BUS + help + This driver provides restart support for Cirrus EP93XX SoC. + +-- +2.43.0 + diff --git a/queue-6.12/power-sequencing-make-the-qcom-pmu-pwrseq-driver-dep.patch b/queue-6.12/power-sequencing-make-the-qcom-pmu-pwrseq-driver-dep.patch new file mode 100644 index 00000000000..f809fa98fd6 --- /dev/null +++ b/queue-6.12/power-sequencing-make-the-qcom-pmu-pwrseq-driver-dep.patch @@ -0,0 +1,37 @@ +From 511fca5ed8ad0cf5c497f002a1ac234e4281c0b5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Fri, 4 Oct 2024 15:04:49 +0200 +Subject: power: sequencing: make the QCom PMU pwrseq driver depend on + CONFIG_OF + +From: Bartosz Golaszewski <bartosz.golaszewski@linaro.org> + +[ Upstream commit f82bf3c5796e1630d553669fb451e6c9d4070512 ] + +This driver uses various OF-specific functions and depends on phandle +parsing. There's no reason to make it available to non-OF systems so add +a relevant dependency switch to its Kconfig entry. + +Fixes: 2f1630f437df ("power: pwrseq: add a driver for the PMU module on the QCom WCN chipsets") +Link: https://lore.kernel.org/r/20241004130449.51725-1-brgl@bgdev.pl +Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/power/sequencing/Kconfig | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/power/sequencing/Kconfig b/drivers/power/sequencing/Kconfig +index c9f1cdb665248..ddcc42a984921 100644 +--- a/drivers/power/sequencing/Kconfig ++++ b/drivers/power/sequencing/Kconfig +@@ -16,6 +16,7 @@ if POWER_SEQUENCING + config POWER_SEQUENCING_QCOM_WCN + tristate "Qualcomm WCN family PMU driver" + default m if ARCH_QCOM ++ depends on OF + help + Say Y here to enable the power sequencing driver for Qualcomm + WCN Bluetooth/WLAN chipsets. +-- +2.43.0 + diff --git a/queue-6.12/power-supply-bq27xxx-fix-registers-of-bq27426.patch b/queue-6.12/power-supply-bq27xxx-fix-registers-of-bq27426.patch new file mode 100644 index 00000000000..a6ac8e5f1b7 --- /dev/null +++ b/queue-6.12/power-supply-bq27xxx-fix-registers-of-bq27426.patch @@ -0,0 +1,88 @@ +From ec96ea661efdb704f10a641417f3aa45f7b8a0b5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Wed, 16 Oct 2024 20:54:05 +0200 +Subject: power: supply: bq27xxx: Fix registers of bq27426 +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Barnabás Czémán <barnabas.czeman@mainlining.org> + +[ Upstream commit 34f99d3b706a519e556841f405c224ca708b1f54 ] + +Correct bq27426 registers, according to technical reference manual +it does not have Design Capacity register so it is not register +compatible with bq27421. + +Fixes: 5ef6a16033b47 ("power: supply: bq27xxx: Add support for BQ27426") +Signed-off-by: Barnabás Czémán <barnabas.czeman@mainlining.org> +Link: https://lore.kernel.org/r/20241016-fix_bq27426-v2-1-aa6c0f51a9f6@mainlining.org +Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/power/supply/bq27xxx_battery.c | 37 ++++++++++++++++++++++++-- + 1 file changed, 35 insertions(+), 2 deletions(-) + +diff --git a/drivers/power/supply/bq27xxx_battery.c b/drivers/power/supply/bq27xxx_battery.c +index 750fda543308c..51fb88aca0f9f 100644 +--- a/drivers/power/supply/bq27xxx_battery.c ++++ b/drivers/power/supply/bq27xxx_battery.c +@@ -449,9 +449,29 @@ static u8 + [BQ27XXX_REG_AP] = 0x18, + BQ27XXX_DM_REG_ROWS, + }, ++ bq27426_regs[BQ27XXX_REG_MAX] = { ++ [BQ27XXX_REG_CTRL] = 0x00, ++ [BQ27XXX_REG_TEMP] = 0x02, ++ [BQ27XXX_REG_INT_TEMP] = 0x1e, ++ [BQ27XXX_REG_VOLT] = 0x04, ++ [BQ27XXX_REG_AI] = 0x10, ++ [BQ27XXX_REG_FLAGS] = 0x06, ++ [BQ27XXX_REG_TTE] = INVALID_REG_ADDR, ++ [BQ27XXX_REG_TTF] = INVALID_REG_ADDR, ++ [BQ27XXX_REG_TTES] = INVALID_REG_ADDR, ++ [BQ27XXX_REG_TTECP] = INVALID_REG_ADDR, ++ [BQ27XXX_REG_NAC] = 0x08, ++ [BQ27XXX_REG_RC] = 0x0c, ++ [BQ27XXX_REG_FCC] = 0x0e, ++ [BQ27XXX_REG_CYCT] = INVALID_REG_ADDR, ++ [BQ27XXX_REG_AE] = INVALID_REG_ADDR, ++ [BQ27XXX_REG_SOC] = 0x1c, ++ [BQ27XXX_REG_DCAP] = INVALID_REG_ADDR, ++ [BQ27XXX_REG_AP] = 0x18, ++ BQ27XXX_DM_REG_ROWS, ++ }, + #define bq27411_regs bq27421_regs + #define bq27425_regs bq27421_regs +-#define bq27426_regs bq27421_regs + #define bq27441_regs bq27421_regs + #define bq27621_regs bq27421_regs + bq27z561_regs[BQ27XXX_REG_MAX] = { +@@ -769,10 +789,23 @@ static enum power_supply_property bq27421_props[] = { + }; + #define bq27411_props bq27421_props + #define bq27425_props bq27421_props +-#define bq27426_props bq27421_props + #define bq27441_props bq27421_props + #define bq27621_props bq27421_props + ++static enum power_supply_property bq27426_props[] = { ++ POWER_SUPPLY_PROP_STATUS, ++ POWER_SUPPLY_PROP_PRESENT, ++ POWER_SUPPLY_PROP_VOLTAGE_NOW, ++ POWER_SUPPLY_PROP_CURRENT_NOW, ++ POWER_SUPPLY_PROP_CAPACITY, ++ POWER_SUPPLY_PROP_CAPACITY_LEVEL, ++ POWER_SUPPLY_PROP_TEMP, ++ POWER_SUPPLY_PROP_TECHNOLOGY, ++ POWER_SUPPLY_PROP_CHARGE_FULL, ++ POWER_SUPPLY_PROP_CHARGE_NOW, ++ POWER_SUPPLY_PROP_MANUFACTURER, ++}; ++ + static enum power_supply_property bq27z561_props[] = { + POWER_SUPPLY_PROP_STATUS, + POWER_SUPPLY_PROP_PRESENT, +-- +2.43.0 + diff --git a/queue-6.12/power-supply-core-remove-might_sleep-from-power_supp.patch b/queue-6.12/power-supply-core-remove-might_sleep-from-power_supp.patch new file mode 100644 index 00000000000..38c368f6f58 --- /dev/null +++ b/queue-6.12/power-supply-core-remove-might_sleep-from-power_supp.patch @@ -0,0 +1,44 @@ +From 38a6a80ee4152e34aef316bd11a35be125549077 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Tue, 17 Sep 2024 12:39:14 -0700 +Subject: power: supply: core: Remove might_sleep() from power_supply_put() + +From: Bart Van Assche <bvanassche@acm.org> + +[ Upstream commit f6da4553ff24a5d1c959c9627c965323adc3d307 ] + +The put_device() call in power_supply_put() may call +power_supply_dev_release(). The latter function does not sleep so +power_supply_put() doesn't sleep either. Hence, remove the might_sleep() +call from power_supply_put(). This patch suppresses false positive +complaints about calling a sleeping function from atomic context if +power_supply_put() is called from atomic context. + +Cc: Kyle Tso <kyletso@google.com> +Cc: Krzysztof Kozlowski <krzk@kernel.org> +Fixes: 1a352462b537 ("power_supply: Add power_supply_put for decrementing device reference counter") +Signed-off-by: Bart Van Assche <bvanassche@acm.org> +Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org> +Link: https://lore.kernel.org/r/20240917193914.47566-1-bvanassche@acm.org +Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/power/supply/power_supply_core.c | 2 -- + 1 file changed, 2 deletions(-) + +diff --git a/drivers/power/supply/power_supply_core.c b/drivers/power/supply/power_supply_core.c +index 49534458a9f7d..73cc9c236e833 100644 +--- a/drivers/power/supply/power_supply_core.c ++++ b/drivers/power/supply/power_supply_core.c +@@ -484,8 +484,6 @@ EXPORT_SYMBOL_GPL(power_supply_get_by_name); + */ + void power_supply_put(struct power_supply *psy) + { +- might_sleep(); +- + atomic_dec(&psy->use_cnt); + put_device(&psy->dev); + } +-- +2.43.0 + diff --git a/queue-6.12/power-supply-rt9471-fix-wrong-wdt-function-regfield-.patch b/queue-6.12/power-supply-rt9471-fix-wrong-wdt-function-regfield-.patch new file mode 100644 index 00000000000..36d5f7e8f89 --- /dev/null +++ b/queue-6.12/power-supply-rt9471-fix-wrong-wdt-function-regfield-.patch @@ -0,0 +1,39 @@ +From cb4675b7b6eaa9ab2e0a0316fc513c90ac0f7409 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Wed, 25 Sep 2024 16:32:58 +0800 +Subject: power: supply: rt9471: Fix wrong WDT function regfield declaration + +From: ChiYuan Huang <cy_huang@richtek.com> + +[ Upstream commit d10ff07dd2b933e3864c592ca932996b07bbf22a ] + +Fix F_WDT and F_WDT_RST wrong regfield declaration. + +Fixes: 4a1a5f6781d8 ("power: supply: rt9471: Add Richtek RT9471 charger driver") +Reported-by: Lucas Tsai <lucas_tsai@richtek.com> +Signed-off-by: ChiYuan Huang <cy_huang@richtek.com> +Link: https://lore.kernel.org/r/f862e23f220612f01fabb6d8e76cfaf63756c22b.1727252762.git.cy_huang@richtek.com +Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/power/supply/rt9471.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/power/supply/rt9471.c b/drivers/power/supply/rt9471.c +index c04af1ee89c67..730b252b49006 100644 +--- a/drivers/power/supply/rt9471.c ++++ b/drivers/power/supply/rt9471.c +@@ -153,8 +153,8 @@ struct rt9471_chip { + }; + + static const struct reg_field rt9471_reg_fields[F_MAX_FIELDS] = { +- [F_WDT] = REG_FIELD(RT9471_REG_TOP, 0, 0), +- [F_WDT_RST] = REG_FIELD(RT9471_REG_TOP, 1, 1), ++ [F_WDT] = REG_FIELD(RT9471_REG_TOP, 0, 1), ++ [F_WDT_RST] = REG_FIELD(RT9471_REG_TOP, 2, 2), + [F_CHG_EN] = REG_FIELD(RT9471_REG_FUNC, 0, 0), + [F_HZ] = REG_FIELD(RT9471_REG_FUNC, 5, 5), + [F_BATFET_DIS] = REG_FIELD(RT9471_REG_FUNC, 7, 7), +-- +2.43.0 + diff --git a/queue-6.12/power-supply-rt9471-use-ic-status-regfield-to-report.patch b/queue-6.12/power-supply-rt9471-use-ic-status-regfield-to-report.patch new file mode 100644 index 00000000000..23cb0d57dc6 --- /dev/null +++ b/queue-6.12/power-supply-rt9471-use-ic-status-regfield-to-report.patch @@ -0,0 +1,100 @@ +From e5050295d4bcc62339b2cdd31bb2107fcb726903 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Wed, 25 Sep 2024 16:32:59 +0800 +Subject: power: supply: rt9471: Use IC status regfield to report real charger + status + +From: ChiYuan Huang <cy_huang@richtek.com> + +[ Upstream commit c46a9ee5c6210682611d3d4276436c23a95e1996 ] + +Use IC status regfield to rewrite the 'get_staus' function. The original +one cannot cover some special scenario like as charger OTG or JEITA case. + +Fixes: 4a1a5f6781d8 ("power: supply: rt9471: Add Richtek RT9471 charger driver") +Reported-by: Lucas Tsai <lucas_tsai@richtek.com> +Signed-off-by: ChiYuan Huang <cy_huang@richtek.com> +Link: https://lore.kernel.org/r/67ba92bb4a9c51d9cafadab30b788a3a2c3048e1.1727252762.git.cy_huang@richtek.com +Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/power/supply/rt9471.c | 48 ++++++++++++++++++++++------------- + 1 file changed, 31 insertions(+), 17 deletions(-) + +diff --git a/drivers/power/supply/rt9471.c b/drivers/power/supply/rt9471.c +index 730b252b49006..67b86ac91a21d 100644 +--- a/drivers/power/supply/rt9471.c ++++ b/drivers/power/supply/rt9471.c +@@ -139,6 +139,19 @@ enum { + RT9471_PORTSTAT_DCP, + }; + ++enum { ++ RT9471_ICSTAT_SLEEP = 0, ++ RT9471_ICSTAT_VBUSRDY, ++ RT9471_ICSTAT_TRICKLECHG, ++ RT9471_ICSTAT_PRECHG, ++ RT9471_ICSTAT_FASTCHG, ++ RT9471_ICSTAT_IEOC, ++ RT9471_ICSTAT_BGCHG, ++ RT9471_ICSTAT_CHGDONE, ++ RT9471_ICSTAT_CHGFAULT, ++ RT9471_ICSTAT_OTG = 15, ++}; ++ + struct rt9471_chip { + struct device *dev; + struct regmap *regmap; +@@ -255,31 +268,32 @@ static int rt9471_get_ieoc(struct rt9471_chip *chip, int *microamp) + + static int rt9471_get_status(struct rt9471_chip *chip, int *status) + { +- unsigned int chg_ready, chg_done, fault_stat; ++ unsigned int ic_stat; + int ret; + +- ret = regmap_field_read(chip->rm_fields[F_ST_CHG_RDY], &chg_ready); +- if (ret) +- return ret; +- +- ret = regmap_field_read(chip->rm_fields[F_ST_CHG_DONE], &chg_done); ++ ret = regmap_field_read(chip->rm_fields[F_IC_STAT], &ic_stat); + if (ret) + return ret; + +- ret = regmap_read(chip->regmap, RT9471_REG_STAT1, &fault_stat); +- if (ret) +- return ret; +- +- fault_stat &= RT9471_CHGFAULT_MASK; +- +- if (chg_ready && chg_done) +- *status = POWER_SUPPLY_STATUS_FULL; +- else if (chg_ready && fault_stat) ++ switch (ic_stat) { ++ case RT9471_ICSTAT_VBUSRDY: ++ case RT9471_ICSTAT_CHGFAULT: + *status = POWER_SUPPLY_STATUS_NOT_CHARGING; +- else if (chg_ready && !fault_stat) ++ break; ++ case RT9471_ICSTAT_TRICKLECHG ... RT9471_ICSTAT_BGCHG: + *status = POWER_SUPPLY_STATUS_CHARGING; +- else ++ break; ++ case RT9471_ICSTAT_CHGDONE: ++ *status = POWER_SUPPLY_STATUS_FULL; ++ break; ++ case RT9471_ICSTAT_SLEEP: ++ case RT9471_ICSTAT_OTG: + *status = POWER_SUPPLY_STATUS_DISCHARGING; ++ break; ++ default: ++ *status = POWER_SUPPLY_STATUS_UNKNOWN; ++ break; ++ } + + return 0; + } +-- +2.43.0 + diff --git a/queue-6.12/powerpc-fadump-allocate-memory-for-additional-parame.patch b/queue-6.12/powerpc-fadump-allocate-memory-for-additional-parame.patch new file mode 100644 index 00000000000..30434f9766c --- /dev/null +++ b/queue-6.12/powerpc-fadump-allocate-memory-for-additional-parame.patch @@ -0,0 +1,128 @@ +From 2b94b78e94266326aa110e2f5cf3ff5064ed24c4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Thu, 7 Nov 2024 11:28:16 +0530 +Subject: powerpc/fadump: allocate memory for additional parameters early + +From: Hari Bathini <hbathini@linux.ibm.com> + +[ Upstream commit f4892c68ecc1cf45e41a78820dd2eebccc945b66 ] + +Memory for passing additional parameters to fadump capture kernel +is allocated during subsys_initcall level, using memblock. But +as slab is already available by this time, allocation happens via +the buddy allocator. This may work for radix MMU but is likely to +fail in most cases for hash MMU as hash MMU needs this memory in +the first memory block for it to be accessible in real mode in the +capture kernel (second boot). So, allocate memory for additional +parameters area as soon as MMU mode is obvious. + +Fixes: 683eab94da75 ("powerpc/fadump: setup additional parameters for dump capture kernel") +Reported-by: Venkat Rao Bagalkote <venkat88@linux.vnet.ibm.com> +Closes: https://lore.kernel.org/lkml/a70e4064-a040-447b-8556-1fd02f19383d@linux.vnet.ibm.com/T/#u +Signed-off-by: Hari Bathini <hbathini@linux.ibm.com> +Signed-off-by: Sourabh Jain <sourabhjain@linux.ibm.com> +Tested-by: Venkat Rao Bagalkote <venkat88@linux.vnet.ibm.com> +Signed-off-by: Michael Ellerman <mpe@ellerman.id.au> +Link: https://patch.msgid.link/20241107055817.489795-1-sourabhjain@linux.ibm.com +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + arch/powerpc/include/asm/fadump.h | 2 ++ + arch/powerpc/kernel/fadump.c | 15 ++++++++++----- + arch/powerpc/kernel/prom.c | 3 +++ + 3 files changed, 15 insertions(+), 5 deletions(-) + +diff --git a/arch/powerpc/include/asm/fadump.h b/arch/powerpc/include/asm/fadump.h +index 3638f04447f59..a48f54dde4f65 100644 +--- a/arch/powerpc/include/asm/fadump.h ++++ b/arch/powerpc/include/asm/fadump.h +@@ -19,6 +19,7 @@ extern int is_fadump_active(void); + extern int should_fadump_crash(void); + extern void crash_fadump(struct pt_regs *, const char *); + extern void fadump_cleanup(void); ++void fadump_setup_param_area(void); + extern void fadump_append_bootargs(void); + + #else /* CONFIG_FA_DUMP */ +@@ -26,6 +27,7 @@ static inline int is_fadump_active(void) { return 0; } + static inline int should_fadump_crash(void) { return 0; } + static inline void crash_fadump(struct pt_regs *regs, const char *str) { } + static inline void fadump_cleanup(void) { } ++static inline void fadump_setup_param_area(void) { } + static inline void fadump_append_bootargs(void) { } + #endif /* !CONFIG_FA_DUMP */ + +diff --git a/arch/powerpc/kernel/fadump.c b/arch/powerpc/kernel/fadump.c +index ac7b4e1645e55..6ab7934d719f7 100644 +--- a/arch/powerpc/kernel/fadump.c ++++ b/arch/powerpc/kernel/fadump.c +@@ -1577,6 +1577,12 @@ static void __init fadump_init_files(void) + return; + } + ++ if (fw_dump.param_area) { ++ rc = sysfs_create_file(fadump_kobj, &bootargs_append_attr.attr); ++ if (rc) ++ pr_err("unable to create bootargs_append sysfs file (%d)\n", rc); ++ } ++ + debugfs_create_file("fadump_region", 0444, arch_debugfs_dir, NULL, + &fadump_region_fops); + +@@ -1731,7 +1737,7 @@ static void __init fadump_process(void) + * Reserve memory to store additional parameters to be passed + * for fadump/capture kernel. + */ +-static void __init fadump_setup_param_area(void) ++void __init fadump_setup_param_area(void) + { + phys_addr_t range_start, range_end; + +@@ -1739,7 +1745,7 @@ static void __init fadump_setup_param_area(void) + return; + + /* This memory can't be used by PFW or bootloader as it is shared across kernels */ +- if (radix_enabled()) { ++ if (early_radix_enabled()) { + /* + * Anywhere in the upper half should be good enough as all memory + * is accessible in real mode. +@@ -1767,12 +1773,12 @@ static void __init fadump_setup_param_area(void) + COMMAND_LINE_SIZE, + range_start, + range_end); +- if (!fw_dump.param_area || sysfs_create_file(fadump_kobj, &bootargs_append_attr.attr)) { ++ if (!fw_dump.param_area) { + pr_warn("WARNING: Could not setup area to pass additional parameters!\n"); + return; + } + +- memset(phys_to_virt(fw_dump.param_area), 0, COMMAND_LINE_SIZE); ++ memset((void *)fw_dump.param_area, 0, COMMAND_LINE_SIZE); + } + + /* +@@ -1798,7 +1804,6 @@ int __init setup_fadump(void) + } + /* Initialize the kernel dump memory structure and register with f/w */ + else if (fw_dump.reserve_dump_area_size) { +- fadump_setup_param_area(); + fw_dump.ops->fadump_init_mem_struct(&fw_dump); + register_fadump(); + } +diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c +index 88cbe432cad59..e0059842a1c64 100644 +--- a/arch/powerpc/kernel/prom.c ++++ b/arch/powerpc/kernel/prom.c +@@ -908,6 +908,9 @@ void __init early_init_devtree(void *params) + + mmu_early_init_devtree(); + ++ /* Setup param area for passing additional parameters to fadump capture kernel. */ ++ fadump_setup_param_area(); ++ + #ifdef CONFIG_PPC_POWERNV + /* Scan and build the list of machine check recoverable ranges */ + of_scan_flat_dt(early_init_dt_scan_recoverable_ranges, NULL); +-- +2.43.0 + diff --git a/queue-6.12/powerpc-fadump-move-fadump_cma_init-to-setup_arch-af.patch b/queue-6.12/powerpc-fadump-move-fadump_cma_init-to-setup_arch-af.patch new file mode 100644 index 00000000000..b6fea403822 --- /dev/null +++ b/queue-6.12/powerpc-fadump-move-fadump_cma_init-to-setup_arch-af.patch @@ -0,0 +1,131 @@ +From f8a1b89edc1cd85ff55f46d04e453c1876c4cd32 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Fri, 18 Oct 2024 21:47:57 +0530 +Subject: powerpc/fadump: Move fadump_cma_init to setup_arch() after + initmem_init() + +From: Ritesh Harjani (IBM) <ritesh.list@gmail.com> + +[ Upstream commit 05b94cae1c47f94588c3e7096963c1007c4d9c1d ] + +During early init CMA_MIN_ALIGNMENT_BYTES can be PAGE_SIZE, +since pageblock_order is still zero and it gets initialized +later during initmem_init() e.g. +setup_arch() -> initmem_init() -> sparse_init() -> set_pageblock_order() + +One such use case where this causes issue is - +early_setup() -> early_init_devtree() -> fadump_reserve_mem() -> fadump_cma_init() + +This causes CMA memory alignment check to be bypassed in +cma_init_reserved_mem(). Then later cma_activate_area() can hit +a VM_BUG_ON_PAGE(pfn & ((1 << order) - 1)) if the reserved memory +area was not pageblock_order aligned. + +Fix it by moving the fadump_cma_init() after initmem_init(), +where other such cma reservations also gets called. + +<stack trace> +============== +page: refcount:0 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0x10010 +flags: 0x13ffff800000000(node=1|zone=0|lastcpupid=0x7ffff) CMA +raw: 013ffff800000000 5deadbeef0000100 5deadbeef0000122 0000000000000000 +raw: 0000000000000000 0000000000000000 00000000ffffffff 0000000000000000 +page dumped because: VM_BUG_ON_PAGE(pfn & ((1 << order) - 1)) +------------[ cut here ]------------ +kernel BUG at mm/page_alloc.c:778! + +Call Trace: +__free_one_page+0x57c/0x7b0 (unreliable) +free_pcppages_bulk+0x1a8/0x2c8 +free_unref_page_commit+0x3d4/0x4e4 +free_unref_page+0x458/0x6d0 +init_cma_reserved_pageblock+0x114/0x198 +cma_init_reserved_areas+0x270/0x3e0 +do_one_initcall+0x80/0x2f8 +kernel_init_freeable+0x33c/0x530 +kernel_init+0x34/0x26c +ret_from_kernel_user_thread+0x14/0x1c + +Fixes: 11ac3e87ce09 ("mm: cma: use pageblock_order as the single alignment") +Suggested-by: David Hildenbrand <david@redhat.com> +Reported-by: Sachin P Bappalige <sachinpb@linux.ibm.com> +Acked-by: Hari Bathini <hbathini@linux.ibm.com> +Reviewed-by: Madhavan Srinivasan <maddy@linux.ibm.com> +Signed-off-by: Ritesh Harjani (IBM) <ritesh.list@gmail.com> +Signed-off-by: Michael Ellerman <mpe@ellerman.id.au> +Link: https://patch.msgid.link/3ae208e48c0d9cefe53d2dc4f593388067405b7d.1729146153.git.ritesh.list@gmail.com +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + arch/powerpc/include/asm/fadump.h | 7 +++++++ + arch/powerpc/kernel/fadump.c | 6 +----- + arch/powerpc/kernel/setup-common.c | 6 ++++-- + 3 files changed, 12 insertions(+), 7 deletions(-) + +diff --git a/arch/powerpc/include/asm/fadump.h b/arch/powerpc/include/asm/fadump.h +index ef40c9b6972a6..3638f04447f59 100644 +--- a/arch/powerpc/include/asm/fadump.h ++++ b/arch/powerpc/include/asm/fadump.h +@@ -34,4 +34,11 @@ extern int early_init_dt_scan_fw_dump(unsigned long node, const char *uname, + int depth, void *data); + extern int fadump_reserve_mem(void); + #endif ++ ++#if defined(CONFIG_FA_DUMP) && defined(CONFIG_CMA) ++void fadump_cma_init(void); ++#else ++static inline void fadump_cma_init(void) { } ++#endif ++ + #endif /* _ASM_POWERPC_FADUMP_H */ +diff --git a/arch/powerpc/kernel/fadump.c b/arch/powerpc/kernel/fadump.c +index 162327d66982e..ac7b4e1645e55 100644 +--- a/arch/powerpc/kernel/fadump.c ++++ b/arch/powerpc/kernel/fadump.c +@@ -78,7 +78,7 @@ static struct cma *fadump_cma; + * But for some reason even if it fails we still have the memory reservation + * with us and we can still continue doing fadump. + */ +-static void __init fadump_cma_init(void) ++void __init fadump_cma_init(void) + { + unsigned long long base, size; + int rc; +@@ -122,8 +122,6 @@ static void __init fadump_cma_init(void) + (unsigned long)cma_get_base(fadump_cma) >> 20, + fw_dump.reserve_dump_area_size); + } +-#else +-static void __init fadump_cma_init(void) { } + #endif /* CONFIG_CMA */ + + /* +@@ -632,8 +630,6 @@ int __init fadump_reserve_mem(void) + + pr_info("Reserved %lldMB of memory at %#016llx (System RAM: %lldMB)\n", + (size >> 20), base, (memblock_phys_mem_size() >> 20)); +- +- fadump_cma_init(); + } + + return ret; +diff --git a/arch/powerpc/kernel/setup-common.c b/arch/powerpc/kernel/setup-common.c +index 943430077375a..b6b01502e5047 100644 +--- a/arch/powerpc/kernel/setup-common.c ++++ b/arch/powerpc/kernel/setup-common.c +@@ -997,9 +997,11 @@ void __init setup_arch(char **cmdline_p) + initmem_init(); + + /* +- * Reserve large chunks of memory for use by CMA for KVM and hugetlb. These must +- * be called after initmem_init(), so that pageblock_order is initialised. ++ * Reserve large chunks of memory for use by CMA for fadump, KVM and ++ * hugetlb. These must be called after initmem_init(), so that ++ * pageblock_order is initialised. + */ ++ fadump_cma_init(); + kvm_cma_reserve(); + gigantic_hugetlb_cma_reserve(); + +-- +2.43.0 + diff --git a/queue-6.12/powerpc-fadump-refactor-and-prepare-fadump_cma_init-.patch b/queue-6.12/powerpc-fadump-refactor-and-prepare-fadump_cma_init-.patch new file mode 100644 index 00000000000..106e479b12d --- /dev/null +++ b/queue-6.12/powerpc-fadump-refactor-and-prepare-fadump_cma_init-.patch @@ -0,0 +1,99 @@ +From b167318d1c32fb40e267460f727486b53450aeee Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Fri, 18 Oct 2024 21:47:55 +0530 +Subject: powerpc/fadump: Refactor and prepare fadump_cma_init for late init + +From: Ritesh Harjani (IBM) <ritesh.list@gmail.com> + +[ Upstream commit adfaec30ffaceecd565e06adae367aa944acc3c9 ] + +We anyway don't use any return values from fadump_cma_init(). Since +fadump_reserve_mem() from where fadump_cma_init() gets called today, +already has the required checks. +This patch makes this function return type as void. Let's also handle +extra cases like return if fadump_supported is false or dump_active, so +that in later patches we can call fadump_cma_init() separately from +setup_arch(). + +Acked-by: Hari Bathini <hbathini@linux.ibm.com> +Reviewed-by: Madhavan Srinivasan <maddy@linux.ibm.com> +Signed-off-by: Ritesh Harjani (IBM) <ritesh.list@gmail.com> +Signed-off-by: Michael Ellerman <mpe@ellerman.id.au> +Link: https://patch.msgid.link/a2afc3d6481a87a305e89cfc4a3f3d2a0b8ceab3.1729146153.git.ritesh.list@gmail.com +Stable-dep-of: 05b94cae1c47 ("powerpc/fadump: Move fadump_cma_init to setup_arch() after initmem_init()") +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + arch/powerpc/kernel/fadump.c | 23 +++++++++-------------- + 1 file changed, 9 insertions(+), 14 deletions(-) + +diff --git a/arch/powerpc/kernel/fadump.c b/arch/powerpc/kernel/fadump.c +index a612e7513a4f8..162327d66982e 100644 +--- a/arch/powerpc/kernel/fadump.c ++++ b/arch/powerpc/kernel/fadump.c +@@ -78,27 +78,23 @@ static struct cma *fadump_cma; + * But for some reason even if it fails we still have the memory reservation + * with us and we can still continue doing fadump. + */ +-static int __init fadump_cma_init(void) ++static void __init fadump_cma_init(void) + { + unsigned long long base, size; + int rc; + +- if (!fw_dump.fadump_enabled) +- return 0; +- ++ if (!fw_dump.fadump_supported || !fw_dump.fadump_enabled || ++ fw_dump.dump_active) ++ return; + /* + * Do not use CMA if user has provided fadump=nocma kernel parameter. +- * Return 1 to continue with fadump old behaviour. + */ +- if (fw_dump.nocma) +- return 1; ++ if (fw_dump.nocma || !fw_dump.boot_memory_size) ++ return; + + base = fw_dump.reserve_dump_area_start; + size = fw_dump.boot_memory_size; + +- if (!size) +- return 0; +- + rc = cma_init_reserved_mem(base, size, 0, "fadump_cma", &fadump_cma); + if (rc) { + pr_err("Failed to init cma area for firmware-assisted dump,%d\n", rc); +@@ -108,7 +104,7 @@ static int __init fadump_cma_init(void) + * blocked from production system usage. Hence return 1, + * so that we can continue with fadump. + */ +- return 1; ++ return; + } + + /* +@@ -125,10 +121,9 @@ static int __init fadump_cma_init(void) + cma_get_size(fadump_cma), + (unsigned long)cma_get_base(fadump_cma) >> 20, + fw_dump.reserve_dump_area_size); +- return 1; + } + #else +-static int __init fadump_cma_init(void) { return 1; } ++static void __init fadump_cma_init(void) { } + #endif /* CONFIG_CMA */ + + /* +@@ -638,7 +633,7 @@ int __init fadump_reserve_mem(void) + pr_info("Reserved %lldMB of memory at %#016llx (System RAM: %lldMB)\n", + (size >> 20), base, (memblock_phys_mem_size() >> 20)); + +- ret = fadump_cma_init(); ++ fadump_cma_init(); + } + + return ret; +-- +2.43.0 + diff --git a/queue-6.12/powerpc-kexec-fix-return-of-uninitialized-variable.patch b/queue-6.12/powerpc-kexec-fix-return-of-uninitialized-variable.patch new file mode 100644 index 00000000000..ced35b8b8a1 --- /dev/null +++ b/queue-6.12/powerpc-kexec-fix-return-of-uninitialized-variable.patch @@ -0,0 +1,49 @@ +From 405dce42629c0acb42054a22f6965fbf3d183074 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Mon, 30 Sep 2024 15:56:28 +0800 +Subject: powerpc/kexec: Fix return of uninitialized variable + +From: Zhang Zekun <zhangzekun11@huawei.com> + +[ Upstream commit 83b5a407fbb73e6965adfb4bd0a803724bf87f96 ] + +of_property_read_u64() can fail and leave the variable uninitialized, +which will then be used. Return error if reading the property failed. + +Fixes: 2e6bd221d96f ("powerpc/kexec_file: Enable early kernel OPAL calls") +Signed-off-by: Zhang Zekun <zhangzekun11@huawei.com> +Signed-off-by: Michael Ellerman <mpe@ellerman.id.au> +Link: https://patch.msgid.link/20240930075628.125138-1-zhangzekun11@huawei.com +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + arch/powerpc/kexec/file_load_64.c | 9 +++++++-- + 1 file changed, 7 insertions(+), 2 deletions(-) + +diff --git a/arch/powerpc/kexec/file_load_64.c b/arch/powerpc/kexec/file_load_64.c +index 9738adabeb1fe..dc65c13911577 100644 +--- a/arch/powerpc/kexec/file_load_64.c ++++ b/arch/powerpc/kexec/file_load_64.c +@@ -736,13 +736,18 @@ int setup_purgatory_ppc64(struct kimage *image, const void *slave_code, + if (dn) { + u64 val; + +- of_property_read_u64(dn, "opal-base-address", &val); ++ ret = of_property_read_u64(dn, "opal-base-address", &val); ++ if (ret) ++ goto out; ++ + ret = kexec_purgatory_get_set_symbol(image, "opal_base", &val, + sizeof(val), false); + if (ret) + goto out; + +- of_property_read_u64(dn, "opal-entry-address", &val); ++ ret = of_property_read_u64(dn, "opal-entry-address", &val); ++ if (ret) ++ goto out; + ret = kexec_purgatory_get_set_symbol(image, "opal_entry", &val, + sizeof(val), false); + } +-- +2.43.0 + diff --git a/queue-6.12/powerpc-mm-fault-fix-kfence-page-fault-reporting.patch b/queue-6.12/powerpc-mm-fault-fix-kfence-page-fault-reporting.patch new file mode 100644 index 00000000000..7f9f11b5b90 --- /dev/null +++ b/queue-6.12/powerpc-mm-fault-fix-kfence-page-fault-reporting.patch @@ -0,0 +1,85 @@ +From 9288f54af15059df0247839a794ec438017dbc7f Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Fri, 18 Oct 2024 22:59:42 +0530 +Subject: powerpc/mm/fault: Fix kfence page fault reporting + +From: Ritesh Harjani (IBM) <ritesh.list@gmail.com> + +[ Upstream commit 06dbbb4d5f7126b6307ab807cbf04ecfc459b933 ] + +copy_from_kernel_nofault() can be called when doing read of /proc/kcore. +/proc/kcore can have some unmapped kfence objects which when read via +copy_from_kernel_nofault() can cause page faults. Since *_nofault() +functions define their own fixup table for handling fault, use that +instead of asking kfence to handle such faults. + +Hence we search the exception tables for the nip which generated the +fault. If there is an entry then we let the fixup table handler handle the +page fault by returning an error from within ___do_page_fault(). + +This can be easily triggered if someone tries to do dd from /proc/kcore. +eg. dd if=/proc/kcore of=/dev/null bs=1M + +Some example false negatives: + + =============================== + BUG: KFENCE: invalid read in copy_from_kernel_nofault+0x9c/0x1a0 + Invalid read at 0xc0000000fdff0000: + copy_from_kernel_nofault+0x9c/0x1a0 + 0xc00000000665f950 + read_kcore_iter+0x57c/0xa04 + proc_reg_read_iter+0xe4/0x16c + vfs_read+0x320/0x3ec + ksys_read+0x90/0x154 + system_call_exception+0x120/0x310 + system_call_vectored_common+0x15c/0x2ec + + BUG: KFENCE: use-after-free read in copy_from_kernel_nofault+0x9c/0x1a0 + Use-after-free read at 0xc0000000fe050000 (in kfence-#2): + copy_from_kernel_nofault+0x9c/0x1a0 + 0xc00000000665f950 + read_kcore_iter+0x57c/0xa04 + proc_reg_read_iter+0xe4/0x16c + vfs_read+0x320/0x3ec + ksys_read+0x90/0x154 + system_call_exception+0x120/0x310 + system_call_vectored_common+0x15c/0x2ec + +Fixes: 90cbac0e995d ("powerpc: Enable KFENCE for PPC32") +Suggested-by: Christophe Leroy <christophe.leroy@csgroup.eu> +Reported-by: Disha Goel <disgoel@linux.ibm.com> +Signed-off-by: Ritesh Harjani (IBM) <ritesh.list@gmail.com> +Reviewed-by: Christophe Leroy <christophe.leroy@csgroup.eu> +Signed-off-by: Michael Ellerman <mpe@ellerman.id.au> +Link: https://patch.msgid.link/a411788081d50e3b136c6270471e35aba3dfafa3.1729271995.git.ritesh.list@gmail.com +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + arch/powerpc/mm/fault.c | 10 ++++++++-- + 1 file changed, 8 insertions(+), 2 deletions(-) + +diff --git a/arch/powerpc/mm/fault.c b/arch/powerpc/mm/fault.c +index 81c77ddce2e30..c156fe0d53c37 100644 +--- a/arch/powerpc/mm/fault.c ++++ b/arch/powerpc/mm/fault.c +@@ -439,10 +439,16 @@ static int ___do_page_fault(struct pt_regs *regs, unsigned long address, + /* + * The kernel should never take an execute fault nor should it + * take a page fault to a kernel address or a page fault to a user +- * address outside of dedicated places ++ * address outside of dedicated places. ++ * ++ * Rather than kfence directly reporting false negatives, search whether ++ * the NIP belongs to the fixup table for cases where fault could come ++ * from functions like copy_from_kernel_nofault(). + */ + if (unlikely(!is_user && bad_kernel_fault(regs, error_code, address, is_write))) { +- if (kfence_handle_page_fault(address, is_write, regs)) ++ if (is_kfence_address((void *)address) && ++ !search_exception_tables(instruction_pointer(regs)) && ++ kfence_handle_page_fault(address, is_write, regs)) + return 0; + + return SIGSEGV; +-- +2.43.0 + diff --git a/queue-6.12/powerpc-pseries-fix-dtl_access_lock-to-be-a-rw_semap.patch b/queue-6.12/powerpc-pseries-fix-dtl_access_lock-to-be-a-rw_semap.patch new file mode 100644 index 00000000000..c9c65783cd8 --- /dev/null +++ b/queue-6.12/powerpc-pseries-fix-dtl_access_lock-to-be-a-rw_semap.patch @@ -0,0 +1,153 @@ +From f82122af21aa06ae65dc2a4751ef06229df1eb54 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Mon, 19 Aug 2024 22:24:01 +1000 +Subject: powerpc/pseries: Fix dtl_access_lock to be a rw_semaphore + +From: Michael Ellerman <mpe@ellerman.id.au> + +[ Upstream commit cadae3a45d23aa4f6485938a67cbc47aaaa25e38 ] + +The dtl_access_lock needs to be a rw_sempahore, a sleeping lock, because +the code calls kmalloc() while holding it, which can sleep: + + # echo 1 > /proc/powerpc/vcpudispatch_stats + BUG: sleeping function called from invalid context at include/linux/sched/mm.h:337 + in_atomic(): 1, irqs_disabled(): 0, non_block: 0, pid: 199, name: sh + preempt_count: 1, expected: 0 + 3 locks held by sh/199: + #0: c00000000a0743f8 (sb_writers#3){.+.+}-{0:0}, at: vfs_write+0x324/0x438 + #1: c0000000028c7058 (dtl_enable_mutex){+.+.}-{3:3}, at: vcpudispatch_stats_write+0xd4/0x5f4 + #2: c0000000028c70b8 (dtl_access_lock){+.+.}-{2:2}, at: vcpudispatch_stats_write+0x220/0x5f4 + CPU: 0 PID: 199 Comm: sh Not tainted 6.10.0-rc4 #152 + Hardware name: IBM pSeries (emulated by qemu) POWER9 (raw) 0x4e1202 0xf000005 of:SLOF,HEAD hv:linux,kvm pSeries + Call Trace: + dump_stack_lvl+0x130/0x148 (unreliable) + __might_resched+0x174/0x410 + kmem_cache_alloc_noprof+0x340/0x3d0 + alloc_dtl_buffers+0x124/0x1ac + vcpudispatch_stats_write+0x2a8/0x5f4 + proc_reg_write+0xf4/0x150 + vfs_write+0xfc/0x438 + ksys_write+0x88/0x148 + system_call_exception+0x1c4/0x5a0 + system_call_common+0xf4/0x258 + +Fixes: 06220d78f24a ("powerpc/pseries: Introduce rwlock to gatekeep DTLB usage") +Tested-by: Kajol Jain <kjain@linux.ibm.com> +Reviewed-by: Nysal Jan K.A <nysal@linux.ibm.com> +Reviewed-by: Kajol Jain <kjain@linux.ibm.com> +Signed-off-by: Michael Ellerman <mpe@ellerman.id.au> +Link: https://patch.msgid.link/20240819122401.513203-1-mpe@ellerman.id.au +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + arch/powerpc/include/asm/dtl.h | 4 ++-- + arch/powerpc/platforms/pseries/dtl.c | 8 ++++---- + arch/powerpc/platforms/pseries/lpar.c | 8 ++++---- + 3 files changed, 10 insertions(+), 10 deletions(-) + +diff --git a/arch/powerpc/include/asm/dtl.h b/arch/powerpc/include/asm/dtl.h +index d6f43d149f8dc..a5c21bc623cb0 100644 +--- a/arch/powerpc/include/asm/dtl.h ++++ b/arch/powerpc/include/asm/dtl.h +@@ -1,8 +1,8 @@ + #ifndef _ASM_POWERPC_DTL_H + #define _ASM_POWERPC_DTL_H + ++#include <linux/rwsem.h> + #include <asm/lppaca.h> +-#include <linux/spinlock_types.h> + + /* + * Layout of entries in the hypervisor's dispatch trace log buffer. +@@ -35,7 +35,7 @@ struct dtl_entry { + #define DTL_LOG_ALL (DTL_LOG_CEDE | DTL_LOG_PREEMPT | DTL_LOG_FAULT) + + extern struct kmem_cache *dtl_cache; +-extern rwlock_t dtl_access_lock; ++extern struct rw_semaphore dtl_access_lock; + + extern void register_dtl_buffer(int cpu); + extern void alloc_dtl_buffers(unsigned long *time_limit); +diff --git a/arch/powerpc/platforms/pseries/dtl.c b/arch/powerpc/platforms/pseries/dtl.c +index 8cb9d36ea4915..f293588b8c7b5 100644 +--- a/arch/powerpc/platforms/pseries/dtl.c ++++ b/arch/powerpc/platforms/pseries/dtl.c +@@ -191,7 +191,7 @@ static int dtl_enable(struct dtl *dtl) + return -EBUSY; + + /* ensure there are no other conflicting dtl users */ +- if (!read_trylock(&dtl_access_lock)) ++ if (!down_read_trylock(&dtl_access_lock)) + return -EBUSY; + + n_entries = dtl_buf_entries; +@@ -199,7 +199,7 @@ static int dtl_enable(struct dtl *dtl) + if (!buf) { + printk(KERN_WARNING "%s: buffer alloc failed for cpu %d\n", + __func__, dtl->cpu); +- read_unlock(&dtl_access_lock); ++ up_read(&dtl_access_lock); + return -ENOMEM; + } + +@@ -217,7 +217,7 @@ static int dtl_enable(struct dtl *dtl) + spin_unlock(&dtl->lock); + + if (rc) { +- read_unlock(&dtl_access_lock); ++ up_read(&dtl_access_lock); + kmem_cache_free(dtl_cache, buf); + } + +@@ -232,7 +232,7 @@ static void dtl_disable(struct dtl *dtl) + dtl->buf = NULL; + dtl->buf_entries = 0; + spin_unlock(&dtl->lock); +- read_unlock(&dtl_access_lock); ++ up_read(&dtl_access_lock); + } + + /* file interface */ +diff --git a/arch/powerpc/platforms/pseries/lpar.c b/arch/powerpc/platforms/pseries/lpar.c +index c1d8bee8f7018..bb09990eec309 100644 +--- a/arch/powerpc/platforms/pseries/lpar.c ++++ b/arch/powerpc/platforms/pseries/lpar.c +@@ -169,7 +169,7 @@ struct vcpu_dispatch_data { + */ + #define NR_CPUS_H NR_CPUS + +-DEFINE_RWLOCK(dtl_access_lock); ++DECLARE_RWSEM(dtl_access_lock); + static DEFINE_PER_CPU(struct vcpu_dispatch_data, vcpu_disp_data); + static DEFINE_PER_CPU(u64, dtl_entry_ridx); + static DEFINE_PER_CPU(struct dtl_worker, dtl_workers); +@@ -463,7 +463,7 @@ static int dtl_worker_enable(unsigned long *time_limit) + { + int rc = 0, state; + +- if (!write_trylock(&dtl_access_lock)) { ++ if (!down_write_trylock(&dtl_access_lock)) { + rc = -EBUSY; + goto out; + } +@@ -479,7 +479,7 @@ static int dtl_worker_enable(unsigned long *time_limit) + pr_err("vcpudispatch_stats: unable to setup workqueue for DTL processing\n"); + free_dtl_buffers(time_limit); + reset_global_dtl_mask(); +- write_unlock(&dtl_access_lock); ++ up_write(&dtl_access_lock); + rc = -EINVAL; + goto out; + } +@@ -494,7 +494,7 @@ static void dtl_worker_disable(unsigned long *time_limit) + cpuhp_remove_state(dtl_worker_state); + free_dtl_buffers(time_limit); + reset_global_dtl_mask(); +- write_unlock(&dtl_access_lock); ++ up_write(&dtl_access_lock); + } + + static ssize_t vcpudispatch_stats_write(struct file *file, const char __user *p, +-- +2.43.0 + diff --git a/queue-6.12/powerpc-sstep-make-emulate_vsx_load-and-emulate_vsx_.patch b/queue-6.12/powerpc-sstep-make-emulate_vsx_load-and-emulate_vsx_.patch new file mode 100644 index 00000000000..cd4b3a96eb4 --- /dev/null +++ b/queue-6.12/powerpc-sstep-make-emulate_vsx_load-and-emulate_vsx_.patch @@ -0,0 +1,76 @@ +From b9a3fa98aa4418ab6c18777d31cc828e480f0583 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Tue, 1 Oct 2024 15:03:49 +0200 +Subject: powerpc/sstep: make emulate_vsx_load and emulate_vsx_store static + +From: Michal Suchanek <msuchanek@suse.de> + +[ Upstream commit a26c4dbb3d9c1821cb0fc11cb2dbc32d5bf3463b ] + +These functions are not used outside of sstep.c + +Fixes: 350779a29f11 ("powerpc: Handle most loads and stores in instruction emulation code") +Signed-off-by: Michal Suchanek <msuchanek@suse.de> +Signed-off-by: Michael Ellerman <mpe@ellerman.id.au> +Link: https://patch.msgid.link/20241001130356.14664-1-msuchanek@suse.de +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + arch/powerpc/include/asm/sstep.h | 5 ----- + arch/powerpc/lib/sstep.c | 12 ++++-------- + 2 files changed, 4 insertions(+), 13 deletions(-) + +diff --git a/arch/powerpc/include/asm/sstep.h b/arch/powerpc/include/asm/sstep.h +index 50950deedb873..e3d0e714ff280 100644 +--- a/arch/powerpc/include/asm/sstep.h ++++ b/arch/powerpc/include/asm/sstep.h +@@ -173,9 +173,4 @@ int emulate_step(struct pt_regs *regs, ppc_inst_t instr); + */ + extern int emulate_loadstore(struct pt_regs *regs, struct instruction_op *op); + +-extern void emulate_vsx_load(struct instruction_op *op, union vsx_reg *reg, +- const void *mem, bool cross_endian); +-extern void emulate_vsx_store(struct instruction_op *op, +- const union vsx_reg *reg, void *mem, +- bool cross_endian); + extern int emulate_dcbz(unsigned long ea, struct pt_regs *regs); +diff --git a/arch/powerpc/lib/sstep.c b/arch/powerpc/lib/sstep.c +index e65f3fb68d06b..ac3ee19531d8a 100644 +--- a/arch/powerpc/lib/sstep.c ++++ b/arch/powerpc/lib/sstep.c +@@ -780,8 +780,8 @@ static nokprobe_inline int emulate_stq(struct pt_regs *regs, unsigned long ea, + #endif /* __powerpc64 */ + + #ifdef CONFIG_VSX +-void emulate_vsx_load(struct instruction_op *op, union vsx_reg *reg, +- const void *mem, bool rev) ++static nokprobe_inline void emulate_vsx_load(struct instruction_op *op, union vsx_reg *reg, ++ const void *mem, bool rev) + { + int size, read_size; + int i, j; +@@ -863,11 +863,9 @@ void emulate_vsx_load(struct instruction_op *op, union vsx_reg *reg, + break; + } + } +-EXPORT_SYMBOL_GPL(emulate_vsx_load); +-NOKPROBE_SYMBOL(emulate_vsx_load); + +-void emulate_vsx_store(struct instruction_op *op, const union vsx_reg *reg, +- void *mem, bool rev) ++static nokprobe_inline void emulate_vsx_store(struct instruction_op *op, const union vsx_reg *reg, ++ void *mem, bool rev) + { + int size, write_size; + int i, j; +@@ -955,8 +953,6 @@ void emulate_vsx_store(struct instruction_op *op, const union vsx_reg *reg, + break; + } + } +-EXPORT_SYMBOL_GPL(emulate_vsx_store); +-NOKPROBE_SYMBOL(emulate_vsx_store); + + static nokprobe_inline int do_vsx_load(struct instruction_op *op, + unsigned long ea, struct pt_regs *regs, +-- +2.43.0 + diff --git a/queue-6.12/powerpc-vdso-flag-vdso64-entry-points-as-functions.patch b/queue-6.12/powerpc-vdso-flag-vdso64-entry-points-as-functions.patch new file mode 100644 index 00000000000..085fd920d3f --- /dev/null +++ b/queue-6.12/powerpc-vdso-flag-vdso64-entry-points-as-functions.patch @@ -0,0 +1,112 @@ +From 51e2e549ea4fe1ddd339c5ca345c65d76612c267 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Thu, 10 Oct 2024 00:17:57 +0200 +Subject: powerpc/vdso: Flag VDSO64 entry points as functions + +From: Christophe Leroy <christophe.leroy@csgroup.eu> + +[ Upstream commit 0161bd38c24312853ed5ae9a425a1c41c4ac674a ] + +On powerpc64 as shown below by readelf, vDSO functions symbols have +type NOTYPE. + +$ powerpc64-linux-gnu-readelf -a arch/powerpc/kernel/vdso/vdso64.so.dbg +ELF Header: + Magic: 7f 45 4c 46 02 02 01 00 00 00 00 00 00 00 00 00 + Class: ELF64 + Data: 2's complement, big endian + Version: 1 (current) + OS/ABI: UNIX - System V + ABI Version: 0 + Type: DYN (Shared object file) + Machine: PowerPC64 + Version: 0x1 +... + +Symbol table '.dynsym' contains 12 entries: + Num: Value Size Type Bind Vis Ndx Name +... + 1: 0000000000000524 84 NOTYPE GLOBAL DEFAULT 8 __[...]@@LINUX_2.6.15 +... + 4: 0000000000000000 0 OBJECT GLOBAL DEFAULT ABS LINUX_2.6.15 + 5: 00000000000006c0 48 NOTYPE GLOBAL DEFAULT 8 __[...]@@LINUX_2.6.15 + +Symbol table '.symtab' contains 56 entries: + Num: Value Size Type Bind Vis Ndx Name +... + 45: 0000000000000000 0 OBJECT GLOBAL DEFAULT ABS LINUX_2.6.15 + 46: 00000000000006c0 48 NOTYPE GLOBAL DEFAULT 8 __kernel_getcpu + 47: 0000000000000524 84 NOTYPE GLOBAL DEFAULT 8 __kernel_clock_getres + +To overcome that, commit ba83b3239e65 ("selftests: vDSO: fix vDSO +symbols lookup for powerpc64") was applied to have selftests also +look for NOTYPE symbols, but the correct fix should be to flag VDSO +entry points as functions. + +The original commit that brought VDSO support into powerpc/64 has the +following explanation: + + Note that the symbols exposed by the vDSO aren't "normal" function symbols, apps + can't be expected to link against them directly, the vDSO's are both seen + as if they were linked at 0 and the symbols just contain offsets to the + various functions. This is done on purpose to avoid a relocation step + (ppc64 functions normally have descriptors with abs addresses in them). + When glibc uses those functions, it's expected to use it's own trampolines + that know how to reach them. + +The descriptors it's talking about are the OPD function descriptors +used on ABI v1 (big endian). But it would be more correct for a text +symbol to have type function, even if there's no function descriptor +for it. + +glibc has a special case already for handling the VDSO symbols which +creates a fake opd pointing at the kernel symbol. So changing the VDSO +symbol type to function shouldn't affect that. + +For ABI v2, there is no function descriptors and VDSO functions can +safely have function type. + +So lets flag VDSO entry points as functions and revert the +selftest change. + +Link: https://github.com/mpe/linux-fullhistory/commit/5f2dd691b62da9d9cc54b938f8b29c22c93cb805 +Fixes: ba83b3239e65 ("selftests: vDSO: fix vDSO symbols lookup for powerpc64") +Signed-off-by: Christophe Leroy <christophe.leroy@csgroup.eu> +Reviewed-By: Segher Boessenkool <segher@kernel.crashing.org> +Signed-off-by: Michael Ellerman <mpe@ellerman.id.au> +Link: https://patch.msgid.link/b6ad2f1ee9887af3ca5ecade2a56f4acda517a85.1728512263.git.christophe.leroy@csgroup.eu +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + arch/powerpc/include/asm/vdso.h | 1 + + tools/testing/selftests/vDSO/parse_vdso.c | 3 +-- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/arch/powerpc/include/asm/vdso.h b/arch/powerpc/include/asm/vdso.h +index 7650b6ce14c85..8d972bc98b55f 100644 +--- a/arch/powerpc/include/asm/vdso.h ++++ b/arch/powerpc/include/asm/vdso.h +@@ -25,6 +25,7 @@ int vdso_getcpu_init(void); + #ifdef __VDSO64__ + #define V_FUNCTION_BEGIN(name) \ + .globl name; \ ++ .type name,@function; \ + name: \ + + #define V_FUNCTION_END(name) \ +diff --git a/tools/testing/selftests/vDSO/parse_vdso.c b/tools/testing/selftests/vDSO/parse_vdso.c +index 7dd5668ea8a6e..28f35620c4991 100644 +--- a/tools/testing/selftests/vDSO/parse_vdso.c ++++ b/tools/testing/selftests/vDSO/parse_vdso.c +@@ -222,8 +222,7 @@ void *vdso_sym(const char *version, const char *name) + ELF(Sym) *sym = &vdso_info.symtab[chain]; + + /* Check for a defined global or weak function w/ right name. */ +- if (ELF64_ST_TYPE(sym->st_info) != STT_FUNC && +- ELF64_ST_TYPE(sym->st_info) != STT_NOTYPE) ++ if (ELF64_ST_TYPE(sym->st_info) != STT_FUNC) + continue; + if (ELF64_ST_BIND(sym->st_info) != STB_GLOBAL && + ELF64_ST_BIND(sym->st_info) != STB_WEAK) +-- +2.43.0 + diff --git a/queue-6.12/pwm-assume-a-disabled-pwm-to-emit-a-constant-inactiv.patch b/queue-6.12/pwm-assume-a-disabled-pwm-to-emit-a-constant-inactiv.patch new file mode 100644 index 00000000000..7e60fa6e3e7 --- /dev/null +++ b/queue-6.12/pwm-assume-a-disabled-pwm-to-emit-a-constant-inactiv.patch @@ -0,0 +1,71 @@ +From b75af9336884849d2027a8e93d9997649a04c63d Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Tue, 5 Nov 2024 16:35:22 +0100 +Subject: pwm: Assume a disabled PWM to emit a constant inactive output +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Uwe Kleine-König <u.kleine-koenig@baylibre.com> + +[ Upstream commit b2eaa1170e45dc18eb09dcc9abafbe9a7502e960 ] + +Some PWM hardwares (e.g. MC33XS2410) cannot implement a zero duty cycle +but can instead disable the hardware which also results in a constant +inactive output. + +There are some checks (enabled with CONFIG_PWM_DEBUG) to help +implementing a driver without violating the normal rounding rules. Make +them less strict to let above described hardware pass without warning. + +Reported-by: Dimitri Fedrau <dima.fedrau@gmail.com> +Link: https://lore.kernel.org/r/20241103205215.GA509903@debian +Fixes: 3ad1f3a33286 ("pwm: Implement some checks for lowlevel drivers") +Signed-off-by: Uwe Kleine-König <u.kleine-koenig@baylibre.com> +Reviewed-by: Dimitri Fedrau <dima.fedrau@gmail.com> +Tested-by: Dimitri Fedrau <dima.fedrau@gmail.com> +Link: https://lore.kernel.org/r/20241105153521.1001864-2-u.kleine-koenig@baylibre.com +Signed-off-by: Uwe Kleine-König <ukleinek@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/pwm/core.c | 10 +++++++--- + 1 file changed, 7 insertions(+), 3 deletions(-) + +diff --git a/drivers/pwm/core.c b/drivers/pwm/core.c +index 6e752e148b98c..210368099a064 100644 +--- a/drivers/pwm/core.c ++++ b/drivers/pwm/core.c +@@ -75,7 +75,7 @@ static void pwm_apply_debug(struct pwm_device *pwm, + state->duty_cycle < state->period) + dev_warn(pwmchip_parent(chip), ".apply ignored .polarity\n"); + +- if (state->enabled && ++ if (state->enabled && s2.enabled && + last->polarity == state->polarity && + last->period > s2.period && + last->period <= state->period) +@@ -83,7 +83,11 @@ static void pwm_apply_debug(struct pwm_device *pwm, + ".apply didn't pick the best available period (requested: %llu, applied: %llu, possible: %llu)\n", + state->period, s2.period, last->period); + +- if (state->enabled && state->period < s2.period) ++ /* ++ * Rounding period up is fine only if duty_cycle is 0 then, because a ++ * flat line doesn't have a characteristic period. ++ */ ++ if (state->enabled && s2.enabled && state->period < s2.period && s2.duty_cycle) + dev_warn(pwmchip_parent(chip), + ".apply is supposed to round down period (requested: %llu, applied: %llu)\n", + state->period, s2.period); +@@ -99,7 +103,7 @@ static void pwm_apply_debug(struct pwm_device *pwm, + s2.duty_cycle, s2.period, + last->duty_cycle, last->period); + +- if (state->enabled && state->duty_cycle < s2.duty_cycle) ++ if (state->enabled && s2.enabled && state->duty_cycle < s2.duty_cycle) + dev_warn(pwmchip_parent(chip), + ".apply is supposed to round down duty_cycle (requested: %llu/%llu, applied: %llu/%llu)\n", + state->duty_cycle, state->period, +-- +2.43.0 + diff --git a/queue-6.12/pwm-imx27-workaround-of-the-pwm-output-bug-when-decr.patch b/queue-6.12/pwm-imx27-workaround-of-the-pwm-output-bug-when-decr.patch new file mode 100644 index 00000000000..b54775e589e --- /dev/null +++ b/queue-6.12/pwm-imx27-workaround-of-the-pwm-output-bug-when-decr.patch @@ -0,0 +1,189 @@ +From 0b5229332a02caadb23d6ca71dcb0264db01e57e Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Tue, 8 Oct 2024 15:41:23 -0400 +Subject: pwm: imx27: Workaround of the pwm output bug when decrease the duty + cycle +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Clark Wang <xiaoning.wang@nxp.com> + +[ Upstream commit a25351e4c7740eb22561a3ee4ef17611c6f410b0 ] + +Implement workaround for ERR051198 +(https://www.nxp.com/docs/en/errata/IMX8MN_0N14Y.pdf) + +PWM output may not function correctly if the FIFO is empty when a new SAR +value is programmed. + +Description: + When the PWM FIFO is empty, a new value programmed to the PWM Sample + register (PWM_PWMSAR) will be directly applied even if the current timer + period has not expired. If the new SAMPLE value programmed in the + PWM_PWMSAR register is less than the previous value, and the PWM counter + register (PWM_PWMCNR) that contains the current COUNT value is greater + than the new programmed SAMPLE value, the current period will not flip + the level. This may result in an output pulse with a duty cycle of 100%. + +Workaround: + Program the current SAMPLE value in the PWM_PWMSAR register before + updating the new duty cycle to the SAMPLE value in the PWM_PWMSAR + register. This will ensure that the new SAMPLE value is modified during + a non-empty FIFO, and can be successfully updated after the period + expires. + +Write the old SAR value before updating the new duty cycle to SAR. This +avoids writing the new value into an empty FIFO. + +This only resolves the issue when the PWM period is longer than 2us +(or <500kHz) because write register is not quick enough when PWM period is +very short. + +Reproduce steps: + cd /sys/class/pwm/pwmchip1/pwm0 + echo 2000000000 > period # It is easy to observe by using long period + echo 1000000000 > duty_cycle + echo 1 > enable + echo 8000 > duty_cycle # One full high pulse will be seen by scope + +Fixes: 166091b1894d ("[ARM] MXC: add pwm driver for i.MX SoCs") +Reviewed-by: Jun Li <jun.li@nxp.com> +Signed-off-by: Clark Wang <xiaoning.wang@nxp.com> +Signed-off-by: Frank Li <Frank.Li@nxp.com> +Link: https://lore.kernel.org/r/20241008194123.1943141-1-Frank.Li@nxp.com +Signed-off-by: Uwe Kleine-König <ukleinek@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/pwm/pwm-imx27.c | 98 ++++++++++++++++++++++++++++++++++++++++- + 1 file changed, 96 insertions(+), 2 deletions(-) + +diff --git a/drivers/pwm/pwm-imx27.c b/drivers/pwm/pwm-imx27.c +index 9e2bbf5b4a8ce..0375987194318 100644 +--- a/drivers/pwm/pwm-imx27.c ++++ b/drivers/pwm/pwm-imx27.c +@@ -26,6 +26,7 @@ + #define MX3_PWMSR 0x04 /* PWM Status Register */ + #define MX3_PWMSAR 0x0C /* PWM Sample Register */ + #define MX3_PWMPR 0x10 /* PWM Period Register */ ++#define MX3_PWMCNR 0x14 /* PWM Counter Register */ + + #define MX3_PWMCR_FWM GENMASK(27, 26) + #define MX3_PWMCR_STOPEN BIT(25) +@@ -219,10 +220,12 @@ static void pwm_imx27_wait_fifo_slot(struct pwm_chip *chip, + static int pwm_imx27_apply(struct pwm_chip *chip, struct pwm_device *pwm, + const struct pwm_state *state) + { +- unsigned long period_cycles, duty_cycles, prescale; ++ unsigned long period_cycles, duty_cycles, prescale, period_us, tmp; + struct pwm_imx27_chip *imx = to_pwm_imx27_chip(chip); + unsigned long long c; + unsigned long long clkrate; ++ unsigned long flags; ++ int val; + int ret; + u32 cr; + +@@ -263,7 +266,98 @@ static int pwm_imx27_apply(struct pwm_chip *chip, struct pwm_device *pwm, + pwm_imx27_sw_reset(chip); + } + +- writel(duty_cycles, imx->mmio_base + MX3_PWMSAR); ++ val = readl(imx->mmio_base + MX3_PWMPR); ++ val = val >= MX3_PWMPR_MAX ? MX3_PWMPR_MAX : val; ++ cr = readl(imx->mmio_base + MX3_PWMCR); ++ tmp = NSEC_PER_SEC * (u64)(val + 2) * MX3_PWMCR_PRESCALER_GET(cr); ++ tmp = DIV_ROUND_UP_ULL(tmp, clkrate); ++ period_us = DIV_ROUND_UP_ULL(tmp, 1000); ++ ++ /* ++ * ERR051198: ++ * PWM: PWM output may not function correctly if the FIFO is empty when ++ * a new SAR value is programmed ++ * ++ * Description: ++ * When the PWM FIFO is empty, a new value programmed to the PWM Sample ++ * register (PWM_PWMSAR) will be directly applied even if the current ++ * timer period has not expired. ++ * ++ * If the new SAMPLE value programmed in the PWM_PWMSAR register is ++ * less than the previous value, and the PWM counter register ++ * (PWM_PWMCNR) that contains the current COUNT value is greater than ++ * the new programmed SAMPLE value, the current period will not flip ++ * the level. This may result in an output pulse with a duty cycle of ++ * 100%. ++ * ++ * Consider a change from ++ * ________ ++ * / \______/ ++ * ^ * ^ ++ * to ++ * ____ ++ * / \__________/ ++ * ^ ^ ++ * At the time marked by *, the new write value will be directly applied ++ * to SAR even the current period is not over if FIFO is empty. ++ * ++ * ________ ____________________ ++ * / \______/ \__________/ ++ * ^ ^ * ^ ^ ++ * |<-- old SAR -->| |<-- new SAR -->| ++ * ++ * That is the output is active for a whole period. ++ * ++ * Workaround: ++ * Check new SAR less than old SAR and current counter is in errata ++ * windows, write extra old SAR into FIFO and new SAR will effect at ++ * next period. ++ * ++ * Sometime period is quite long, such as over 1 second. If add old SAR ++ * into FIFO unconditional, new SAR have to wait for next period. It ++ * may be too long. ++ * ++ * Turn off the interrupt to ensure that not IRQ and schedule happen ++ * during above operations. If any irq and schedule happen, counter ++ * in PWM will be out of data and take wrong action. ++ * ++ * Add a safety margin 1.5us because it needs some time to complete ++ * IO write. ++ * ++ * Use writel_relaxed() to minimize the interval between two writes to ++ * the SAR register to increase the fastest PWM frequency supported. ++ * ++ * When the PWM period is longer than 2us(or <500kHz), this workaround ++ * can solve this problem. No software workaround is available if PWM ++ * period is shorter than IO write. Just try best to fill old data ++ * into FIFO. ++ */ ++ c = clkrate * 1500; ++ do_div(c, NSEC_PER_SEC); ++ ++ local_irq_save(flags); ++ val = FIELD_GET(MX3_PWMSR_FIFOAV, readl_relaxed(imx->mmio_base + MX3_PWMSR)); ++ ++ if (duty_cycles < imx->duty_cycle && (cr & MX3_PWMCR_EN)) { ++ if (period_us < 2) { /* 2us = 500 kHz */ ++ /* Best effort attempt to fix up >500 kHz case */ ++ udelay(3 * period_us); ++ writel_relaxed(imx->duty_cycle, imx->mmio_base + MX3_PWMSAR); ++ writel_relaxed(imx->duty_cycle, imx->mmio_base + MX3_PWMSAR); ++ } else if (val < MX3_PWMSR_FIFOAV_2WORDS) { ++ val = readl_relaxed(imx->mmio_base + MX3_PWMCNR); ++ /* ++ * If counter is close to period, controller may roll over when ++ * next IO write. ++ */ ++ if ((val + c >= duty_cycles && val < imx->duty_cycle) || ++ val + c >= period_cycles) ++ writel_relaxed(imx->duty_cycle, imx->mmio_base + MX3_PWMSAR); ++ } ++ } ++ writel_relaxed(duty_cycles, imx->mmio_base + MX3_PWMSAR); ++ local_irq_restore(flags); ++ + writel(period_cycles, imx->mmio_base + MX3_PWMPR); + + /* +-- +2.43.0 + diff --git a/queue-6.12/rcu-kvfree-fix-data-race-in-__mod_timer-kvfree_call_.patch b/queue-6.12/rcu-kvfree-fix-data-race-in-__mod_timer-kvfree_call_.patch new file mode 100644 index 00000000000..b361714946f --- /dev/null +++ b/queue-6.12/rcu-kvfree-fix-data-race-in-__mod_timer-kvfree_call_.patch @@ -0,0 +1,112 @@ +From 5ba6a9d783d411dbf411c88a7b93646d12a65f32 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Tue, 22 Oct 2024 12:53:07 +0200 +Subject: rcu/kvfree: Fix data-race in __mod_timer / kvfree_call_rcu + +From: Uladzislau Rezki (Sony) <urezki@gmail.com> + +[ Upstream commit a23da88c6c80e41e0503e0b481a22c9eea63f263 ] + +KCSAN reports a data race when access the krcp->monitor_work.timer.expires +variable in the schedule_delayed_monitor_work() function: + +<snip> +BUG: KCSAN: data-race in __mod_timer / kvfree_call_rcu + +read to 0xffff888237d1cce8 of 8 bytes by task 10149 on cpu 1: + schedule_delayed_monitor_work kernel/rcu/tree.c:3520 [inline] + kvfree_call_rcu+0x3b8/0x510 kernel/rcu/tree.c:3839 + trie_update_elem+0x47c/0x620 kernel/bpf/lpm_trie.c:441 + bpf_map_update_value+0x324/0x350 kernel/bpf/syscall.c:203 + generic_map_update_batch+0x401/0x520 kernel/bpf/syscall.c:1849 + bpf_map_do_batch+0x28c/0x3f0 kernel/bpf/syscall.c:5143 + __sys_bpf+0x2e5/0x7a0 + __do_sys_bpf kernel/bpf/syscall.c:5741 [inline] + __se_sys_bpf kernel/bpf/syscall.c:5739 [inline] + __x64_sys_bpf+0x43/0x50 kernel/bpf/syscall.c:5739 + x64_sys_call+0x2625/0x2d60 arch/x86/include/generated/asm/syscalls_64.h:322 + do_syscall_x64 arch/x86/entry/common.c:52 [inline] + do_syscall_64+0xc9/0x1c0 arch/x86/entry/common.c:83 + entry_SYSCALL_64_after_hwframe+0x77/0x7f + +write to 0xffff888237d1cce8 of 8 bytes by task 56 on cpu 0: + __mod_timer+0x578/0x7f0 kernel/time/timer.c:1173 + add_timer_global+0x51/0x70 kernel/time/timer.c:1330 + __queue_delayed_work+0x127/0x1a0 kernel/workqueue.c:2523 + queue_delayed_work_on+0xdf/0x190 kernel/workqueue.c:2552 + queue_delayed_work include/linux/workqueue.h:677 [inline] + schedule_delayed_monitor_work kernel/rcu/tree.c:3525 [inline] + kfree_rcu_monitor+0x5e8/0x660 kernel/rcu/tree.c:3643 + process_one_work kernel/workqueue.c:3229 [inline] + process_scheduled_works+0x483/0x9a0 kernel/workqueue.c:3310 + worker_thread+0x51d/0x6f0 kernel/workqueue.c:3391 + kthread+0x1d1/0x210 kernel/kthread.c:389 + ret_from_fork+0x4b/0x60 arch/x86/kernel/process.c:147 + ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:244 + +Reported by Kernel Concurrency Sanitizer on: +CPU: 0 UID: 0 PID: 56 Comm: kworker/u8:4 Not tainted 6.12.0-rc2-syzkaller-00050-g5b7c893ed5ed #0 +Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 09/13/2024 +Workqueue: events_unbound kfree_rcu_monitor +<snip> + +kfree_rcu_monitor() rearms the work if a "krcp" has to be still +offloaded and this is done without holding krcp->lock, whereas +the kvfree_call_rcu() holds it. + +Fix it by acquiring the "krcp->lock" for kfree_rcu_monitor() so +both functions do not race anymore. + +Reported-by: syzbot+061d370693bdd99f9d34@syzkaller.appspotmail.com +Link: https://lore.kernel.org/lkml/ZxZ68KmHDQYU0yfD@pc636/T/ +Fixes: 8fc5494ad5fa ("rcu/kvfree: Move need_offload_krc() out of krcp->lock") +Signed-off-by: Uladzislau Rezki (Sony) <urezki@gmail.com> +Reviewed-by: Neeraj Upadhyay <Neeraj.Upadhyay@amd.com> +Signed-off-by: Frederic Weisbecker <frederic@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + kernel/rcu/tree.c | 14 ++++++++++++-- + 1 file changed, 12 insertions(+), 2 deletions(-) + +diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c +index b1f883fcd9185..3e486ccaa4ca3 100644 +--- a/kernel/rcu/tree.c ++++ b/kernel/rcu/tree.c +@@ -3511,7 +3511,7 @@ static int krc_count(struct kfree_rcu_cpu *krcp) + } + + static void +-schedule_delayed_monitor_work(struct kfree_rcu_cpu *krcp) ++__schedule_delayed_monitor_work(struct kfree_rcu_cpu *krcp) + { + long delay, delay_left; + +@@ -3525,6 +3525,16 @@ schedule_delayed_monitor_work(struct kfree_rcu_cpu *krcp) + queue_delayed_work(system_unbound_wq, &krcp->monitor_work, delay); + } + ++static void ++schedule_delayed_monitor_work(struct kfree_rcu_cpu *krcp) ++{ ++ unsigned long flags; ++ ++ raw_spin_lock_irqsave(&krcp->lock, flags); ++ __schedule_delayed_monitor_work(krcp); ++ raw_spin_unlock_irqrestore(&krcp->lock, flags); ++} ++ + static void + kvfree_rcu_drain_ready(struct kfree_rcu_cpu *krcp) + { +@@ -3836,7 +3846,7 @@ void kvfree_call_rcu(struct rcu_head *head, void *ptr) + + // Set timer to drain after KFREE_DRAIN_JIFFIES. + if (rcu_scheduler_active == RCU_SCHEDULER_RUNNING) +- schedule_delayed_monitor_work(krcp); ++ __schedule_delayed_monitor_work(krcp); + + unlock_return: + krc_this_cpu_unlock(krcp, flags); +-- +2.43.0 + diff --git a/queue-6.12/rcu-nocb-fix-missed-rcu-barrier-on-deoffloading.patch b/queue-6.12/rcu-nocb-fix-missed-rcu-barrier-on-deoffloading.patch new file mode 100644 index 00000000000..2d093e289b7 --- /dev/null +++ b/queue-6.12/rcu-nocb-fix-missed-rcu-barrier-on-deoffloading.patch @@ -0,0 +1,131 @@ +From 87f2844cb644f7908c2ba2f2b384c189250db717 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Tue, 22 Oct 2024 11:41:17 +0800 +Subject: rcu/nocb: Fix missed RCU barrier on deoffloading + +From: Zqiang <qiang.zhang1211@gmail.com> + +[ Upstream commit 2996980e20b7a54a1869df15b3445374b850b155 ] + +Currently, running rcutorture test with torture_type=rcu fwd_progress=8 +n_barrier_cbs=8 nocbs_nthreads=8 nocbs_toggle=100 onoff_interval=60 +test_boost=2, will trigger the following warning: + + WARNING: CPU: 19 PID: 100 at kernel/rcu/tree_nocb.h:1061 rcu_nocb_rdp_deoffload+0x292/0x2a0 + RIP: 0010:rcu_nocb_rdp_deoffload+0x292/0x2a0 + Call Trace: + <TASK> + ? __warn+0x7e/0x120 + ? rcu_nocb_rdp_deoffload+0x292/0x2a0 + ? report_bug+0x18e/0x1a0 + ? handle_bug+0x3d/0x70 + ? exc_invalid_op+0x18/0x70 + ? asm_exc_invalid_op+0x1a/0x20 + ? rcu_nocb_rdp_deoffload+0x292/0x2a0 + rcu_nocb_cpu_deoffload+0x70/0xa0 + rcu_nocb_toggle+0x136/0x1c0 + ? __pfx_rcu_nocb_toggle+0x10/0x10 + kthread+0xd1/0x100 + ? __pfx_kthread+0x10/0x10 + ret_from_fork+0x2f/0x50 + ? __pfx_kthread+0x10/0x10 + ret_from_fork_asm+0x1a/0x30 + </TASK> + +CPU0 CPU2 CPU3 +//rcu_nocb_toggle //nocb_cb_wait //rcutorture + +// deoffload CPU1 // process CPU1's rdp +rcu_barrier() + rcu_segcblist_entrain() + rcu_segcblist_add_len(1); + // len == 2 + // enqueue barrier + // callback to CPU1's + // rdp->cblist + rcu_do_batch() + // invoke CPU1's rdp->cblist + // callback + rcu_barrier_callback() + rcu_barrier() + mutex_lock(&rcu_state.barrier_mutex); + // still see len == 2 + // enqueue barrier callback + // to CPU1's rdp->cblist + rcu_segcblist_entrain() + rcu_segcblist_add_len(1); + // len == 3 + // decrement len + rcu_segcblist_add_len(-2); + kthread_parkme() + +// CPU1's rdp->cblist len == 1 +// Warn because there is +// still a pending barrier +// trigger warning +WARN_ON_ONCE(rcu_segcblist_n_cbs(&rdp->cblist)); +cpus_read_unlock(); + + // wait CPU1 to comes online and + // invoke barrier callback on + // CPU1 rdp's->cblist + wait_for_completion(&rcu_state.barrier_completion); +// deoffload CPU4 +cpus_read_lock() + rcu_barrier() + mutex_lock(&rcu_state.barrier_mutex); + // block on barrier_mutex + // wait rcu_barrier() on + // CPU3 to unlock barrier_mutex + // but CPU3 unlock barrier_mutex + // need to wait CPU1 comes online + // when CPU1 going online will block on cpus_write_lock + +The above scenario will not only trigger a WARN_ON_ONCE(), but also +trigger a deadlock. + +Thanks to nocb locking, a second racing rcu_barrier() on an offline CPU +will either observe the decremented callback counter down to 0 and spare +the callback enqueue, or rcuo will observe the new callback and keep +rdp->nocb_cb_sleep to false. + +Therefore check rdp->nocb_cb_sleep before parking to make sure no +further rcu_barrier() is waiting on the rdp. + +Fixes: 1fcb932c8b5c ("rcu/nocb: Simplify (de-)offloading state machine") +Suggested-by: Frederic Weisbecker <frederic@kernel.org> +Signed-off-by: Zqiang <qiang.zhang1211@gmail.com> +Reviewed-by: Neeraj Upadhyay <Neeraj.Upadhyay@amd.com> +Signed-off-by: Frederic Weisbecker <frederic@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + kernel/rcu/tree_nocb.h | 13 ++++++++++++- + 1 file changed, 12 insertions(+), 1 deletion(-) + +diff --git a/kernel/rcu/tree_nocb.h b/kernel/rcu/tree_nocb.h +index 16865475120ba..2605dd234a13c 100644 +--- a/kernel/rcu/tree_nocb.h ++++ b/kernel/rcu/tree_nocb.h +@@ -891,7 +891,18 @@ static void nocb_cb_wait(struct rcu_data *rdp) + swait_event_interruptible_exclusive(rdp->nocb_cb_wq, + nocb_cb_wait_cond(rdp)); + if (kthread_should_park()) { +- kthread_parkme(); ++ /* ++ * kthread_park() must be preceded by an rcu_barrier(). ++ * But yet another rcu_barrier() might have sneaked in between ++ * the barrier callback execution and the callbacks counter ++ * decrement. ++ */ ++ if (rdp->nocb_cb_sleep) { ++ rcu_nocb_lock_irqsave(rdp, flags); ++ WARN_ON_ONCE(rcu_segcblist_n_cbs(&rdp->cblist)); ++ rcu_nocb_unlock_irqrestore(rdp, flags); ++ kthread_parkme(); ++ } + } else if (READ_ONCE(rdp->nocb_cb_sleep)) { + WARN_ON(signal_pending(current)); + trace_rcu_nocb_wake(rcu_state.name, rdp->cpu, TPS("WokeEmpty")); +-- +2.43.0 + diff --git a/queue-6.12/rcu-srcutiny-don-t-return-before-reenabling-preempti.patch b/queue-6.12/rcu-srcutiny-don-t-return-before-reenabling-preempti.patch new file mode 100644 index 00000000000..45e003996bd --- /dev/null +++ b/queue-6.12/rcu-srcutiny-don-t-return-before-reenabling-preempti.patch @@ -0,0 +1,41 @@ +From 8f530cb878d64718945b0eb32fab4be2e640f614 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Mon, 7 Oct 2024 12:14:15 +0200 +Subject: rcu/srcutiny: don't return before reenabling preemption + +From: Michal Schmidt <mschmidt@redhat.com> + +[ Upstream commit 0ea3acbc804c2d5a165442cdf9c0526f4d324888 ] + +Code after the return statement is dead. Enable preemption before +returning from srcu_drive_gp(). + +This will be important when/if PREEMPT_AUTO (lazy resched) gets merged. + +Fixes: 65b4a59557f6 ("srcu: Make Tiny SRCU explicitly disable preemption") +Reviewed-by: Paul E. McKenney <paulmck@kernel.org> +Signed-off-by: Michal Schmidt <mschmidt@redhat.com> +Reviewed-by: Neeraj Upadhyay <Neeraj.Upadhyay@amd.com> +Signed-off-by: Frederic Weisbecker <frederic@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + kernel/rcu/srcutiny.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/kernel/rcu/srcutiny.c b/kernel/rcu/srcutiny.c +index 549c03336ee97..4dcbf8aa80ff7 100644 +--- a/kernel/rcu/srcutiny.c ++++ b/kernel/rcu/srcutiny.c +@@ -122,8 +122,8 @@ void srcu_drive_gp(struct work_struct *wp) + ssp = container_of(wp, struct srcu_struct, srcu_work); + preempt_disable(); // Needed for PREEMPT_AUTO + if (ssp->srcu_gp_running || ULONG_CMP_GE(ssp->srcu_idx, READ_ONCE(ssp->srcu_idx_max))) { +- return; /* Already running or nothing to do. */ + preempt_enable(); ++ return; /* Already running or nothing to do. */ + } + + /* Remove recently arrived callbacks and wait for readers. */ +-- +2.43.0 + diff --git a/queue-6.12/rcuscale-do-a-proper-cleanup-if-kfree_scale_init-fai.patch b/queue-6.12/rcuscale-do-a-proper-cleanup-if-kfree_scale_init-fai.patch new file mode 100644 index 00000000000..51e80cc670f --- /dev/null +++ b/queue-6.12/rcuscale-do-a-proper-cleanup-if-kfree_scale_init-fai.patch @@ -0,0 +1,70 @@ +From 0e3a999c7bad23af102e41fffd306191c2947743 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Wed, 13 Nov 2024 12:00:08 +0100 +Subject: rcuscale: Do a proper cleanup if kfree_scale_init() fails + +From: Uladzislau Rezki (Sony) <urezki@gmail.com> + +[ Upstream commit 812a1c3b9f7c36d9255f0d29d0a3d324e2f52321 ] + +A static analyzer for C, Smatch, reports and triggers below +warnings: + + kernel/rcu/rcuscale.c:1215 rcu_scale_init() + warn: inconsistent returns 'global &fullstop_mutex'. + +The checker complains about, we do not unlock the "fullstop_mutex" +mutex, in case of hitting below error path: + +<snip> +... + if (WARN_ON_ONCE(jiffies_at_lazy_cb - jif_start < 2 * HZ)) { + pr_alert("ERROR: call_rcu() CBs are not being lazy as expected!\n"); + WARN_ON_ONCE(1); + return -1; + ^^^^^^^^^^ +... +<snip> + +it happens because "-1" is returned right away instead of +doing a proper unwinding. + +Fix it by jumping to "unwind" label instead of returning -1. + +Reported-by: Dan Carpenter <dan.carpenter@linaro.org> +Reviewed-by: Paul E. McKenney <paulmck@kernel.org> +Reviewed-by: Neeraj Upadhyay <Neeraj.Upadhyay@amd.com> +Closes: https://lore.kernel.org/rcu/ZxfTrHuEGtgnOYWp@pc636/T/ +Fixes: 084e04fff160 ("rcuscale: Add laziness and kfree tests") +Signed-off-by: Uladzislau Rezki (Sony) <urezki@gmail.com> +Signed-off-by: Frederic Weisbecker <frederic@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + kernel/rcu/rcuscale.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/kernel/rcu/rcuscale.c b/kernel/rcu/rcuscale.c +index 6d37596deb1f1..d360fa44b234d 100644 +--- a/kernel/rcu/rcuscale.c ++++ b/kernel/rcu/rcuscale.c +@@ -890,13 +890,15 @@ kfree_scale_init(void) + if (WARN_ON_ONCE(jiffies_at_lazy_cb - jif_start < 2 * HZ)) { + pr_alert("ERROR: call_rcu() CBs are not being lazy as expected!\n"); + WARN_ON_ONCE(1); +- return -1; ++ firsterr = -1; ++ goto unwind; + } + + if (WARN_ON_ONCE(jiffies_at_lazy_cb - jif_start > 3 * HZ)) { + pr_alert("ERROR: call_rcu() CBs are being too lazy!\n"); + WARN_ON_ONCE(1); +- return -1; ++ firsterr = -1; ++ goto unwind; + } + } + +-- +2.43.0 + diff --git a/queue-6.12/rdma-bnxt_re-check-cqe-flags-to-know-imm_data-vs-inv.patch b/queue-6.12/rdma-bnxt_re-check-cqe-flags-to-know-imm_data-vs-inv.patch new file mode 100644 index 00000000000..0e3823242cc --- /dev/null +++ b/queue-6.12/rdma-bnxt_re-check-cqe-flags-to-know-imm_data-vs-inv.patch @@ -0,0 +1,80 @@ +From c3a4c605b57898f37bb577e715cc2c7f6b5ef097 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Mon, 28 Oct 2024 03:06:54 -0700 +Subject: RDMA/bnxt_re: Check cqe flags to know imm_data vs inv_irkey + +From: Kashyap Desai <kashyap.desai@broadcom.com> + +[ Upstream commit 808ca6de989c598bc5af1ae0ad971a66077efac0 ] + +Invalidate rkey is cpu endian and immediate data is in big endian format. +Both immediate data and invalidate the remote key returned by +HW is in little endian format. + +While handling the commit in fixes tag, the difference between +immediate data and invalidate rkey endianness was not considered. + +Without changes of this patch, Kernel ULP was failing while processing +inv_rkey. + +dmesg log snippet - +nvme nvme0: Bogus remote invalidation for rkey 0x2000019Fix in this patch + +Do endianness conversion based on completion queue entry flag. +Also, the HW completions are already converted to host endianness in +bnxt_qplib_cq_process_res_rc and bnxt_qplib_cq_process_res_ud and there +is no need to convert it again in bnxt_re_poll_cq. Modified the union to +hold the correct data type. + +Fixes: 95b087f87b78 ("bnxt_re: Fix imm_data endianness") +Signed-off-by: Kashyap Desai <kashyap.desai@broadcom.com> +Signed-off-by: Selvin Xavier <selvin.xavier@broadcom.com> +Link: https://patch.msgid.link/1730110014-20755-1-git-send-email-selvin.xavier@broadcom.com +Signed-off-by: Leon Romanovsky <leon@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/infiniband/hw/bnxt_re/ib_verbs.c | 7 +++++-- + drivers/infiniband/hw/bnxt_re/qplib_fp.h | 2 +- + 2 files changed, 6 insertions(+), 3 deletions(-) + +diff --git a/drivers/infiniband/hw/bnxt_re/ib_verbs.c b/drivers/infiniband/hw/bnxt_re/ib_verbs.c +index e66ae9f22c710..160096792224b 100644 +--- a/drivers/infiniband/hw/bnxt_re/ib_verbs.c ++++ b/drivers/infiniband/hw/bnxt_re/ib_verbs.c +@@ -3633,7 +3633,7 @@ static void bnxt_re_process_res_shadow_qp_wc(struct bnxt_re_qp *gsi_sqp, + wc->byte_len = orig_cqe->length; + wc->qp = &gsi_qp->ib_qp; + +- wc->ex.imm_data = cpu_to_be32(le32_to_cpu(orig_cqe->immdata)); ++ wc->ex.imm_data = cpu_to_be32(orig_cqe->immdata); + wc->src_qp = orig_cqe->src_qp; + memcpy(wc->smac, orig_cqe->smac, ETH_ALEN); + if (bnxt_re_is_vlan_pkt(orig_cqe, &vlan_id, &sl)) { +@@ -3778,7 +3778,10 @@ int bnxt_re_poll_cq(struct ib_cq *ib_cq, int num_entries, struct ib_wc *wc) + (unsigned long)(cqe->qp_handle), + struct bnxt_re_qp, qplib_qp); + wc->qp = &qp->ib_qp; +- wc->ex.imm_data = cpu_to_be32(le32_to_cpu(cqe->immdata)); ++ if (cqe->flags & CQ_RES_RC_FLAGS_IMM) ++ wc->ex.imm_data = cpu_to_be32(cqe->immdata); ++ else ++ wc->ex.invalidate_rkey = cqe->invrkey; + wc->src_qp = cqe->src_qp; + memcpy(wc->smac, cqe->smac, ETH_ALEN); + wc->port_num = 1; +diff --git a/drivers/infiniband/hw/bnxt_re/qplib_fp.h b/drivers/infiniband/hw/bnxt_re/qplib_fp.h +index 820611a239433..f55958e5fddb4 100644 +--- a/drivers/infiniband/hw/bnxt_re/qplib_fp.h ++++ b/drivers/infiniband/hw/bnxt_re/qplib_fp.h +@@ -391,7 +391,7 @@ struct bnxt_qplib_cqe { + u16 cfa_meta; + u64 wr_id; + union { +- __le32 immdata; ++ u32 immdata; + u32 invrkey; + }; + u64 qp_handle; +-- +2.43.0 + diff --git a/queue-6.12/rdma-bnxt_re-correct-the-sequence-of-device-suspend.patch b/queue-6.12/rdma-bnxt_re-correct-the-sequence-of-device-suspend.patch new file mode 100644 index 00000000000..813d0d9ed0c --- /dev/null +++ b/queue-6.12/rdma-bnxt_re-correct-the-sequence-of-device-suspend.patch @@ -0,0 +1,84 @@ +From b301dfa069ae66264964eefa382fd6efd6dc5ffe Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Fri, 15 Nov 2024 00:47:44 -0800 +Subject: RDMA/bnxt_re: Correct the sequence of device suspend + +From: Kalesh AP <kalesh-anakkur.purayil@broadcom.com> + +[ Upstream commit 68b3bca2df00f0a63f0aa2db2b2adc795665229e ] + +When in fatal error condition, mark device as detached first +and then complete all pending HWRM commands as firmware is not +going to process them and eventually time out. Move the device +to error only if suspend is called when device is in Fatal state. + +Also, remove some outdated comments. Remove the stop_irq call +which is no longer required. + +Fixes: cc5b9b48d447 ("RDMA/bnxt_re: Recover the device when FW error is detected") +Signed-off-by: Kalesh AP <kalesh-anakkur.purayil@broadcom.com> +Signed-off-by: Selvin Xavier <selvin.xavier@broadcom.com> +Link: https://patch.msgid.link/1731660464-27838-4-git-send-email-selvin.xavier@broadcom.com +Signed-off-by: Leon Romanovsky <leon@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/infiniband/hw/bnxt_re/main.c | 28 +++++----------------------- + 1 file changed, 5 insertions(+), 23 deletions(-) + +diff --git a/drivers/infiniband/hw/bnxt_re/main.c b/drivers/infiniband/hw/bnxt_re/main.c +index 9eb290ec71a85..2ac8ddbed576f 100644 +--- a/drivers/infiniband/hw/bnxt_re/main.c ++++ b/drivers/infiniband/hw/bnxt_re/main.c +@@ -2033,12 +2033,6 @@ static int bnxt_re_suspend(struct auxiliary_device *adev, pm_message_t state) + rdev = en_info->rdev; + en_dev = en_info->en_dev; + mutex_lock(&bnxt_re_mutex); +- /* L2 driver may invoke this callback during device error/crash or device +- * reset. Current RoCE driver doesn't recover the device in case of +- * error. Handle the error by dispatching fatal events to all qps +- * ie. by calling bnxt_re_dev_stop and release the MSIx vectors as +- * L2 driver want to modify the MSIx table. +- */ + + ibdev_info(&rdev->ibdev, "Handle device suspend call"); + /* Check the current device state from bnxt_en_dev and move the +@@ -2046,17 +2040,12 @@ static int bnxt_re_suspend(struct auxiliary_device *adev, pm_message_t state) + * This prevents more commands to HW during clean-up, + * in case the device is already in error. + */ +- if (test_bit(BNXT_STATE_FW_FATAL_COND, &rdev->en_dev->en_state)) ++ if (test_bit(BNXT_STATE_FW_FATAL_COND, &rdev->en_dev->en_state)) { + set_bit(ERR_DEVICE_DETACHED, &rdev->rcfw.cmdq.flags); +- +- bnxt_re_dev_stop(rdev); +- bnxt_re_stop_irq(adev); +- /* Move the device states to detached and avoid sending any more +- * commands to HW +- */ +- set_bit(BNXT_RE_FLAG_ERR_DEVICE_DETACHED, &rdev->flags); +- set_bit(ERR_DEVICE_DETACHED, &rdev->rcfw.cmdq.flags); +- wake_up_all(&rdev->rcfw.cmdq.waitq); ++ set_bit(BNXT_RE_FLAG_ERR_DEVICE_DETACHED, &rdev->flags); ++ wake_up_all(&rdev->rcfw.cmdq.waitq); ++ bnxt_re_dev_stop(rdev); ++ } + + if (rdev->pacing.dbr_pacing) + bnxt_re_set_pacing_dev_state(rdev); +@@ -2075,13 +2064,6 @@ static int bnxt_re_resume(struct auxiliary_device *adev) + struct bnxt_re_dev *rdev; + + mutex_lock(&bnxt_re_mutex); +- /* L2 driver may invoke this callback during device recovery, resume. +- * reset. Current RoCE driver doesn't recover the device in case of +- * error. Handle the error by dispatching fatal events to all qps +- * ie. by calling bnxt_re_dev_stop and release the MSIx vectors as +- * L2 driver want to modify the MSIx table. +- */ +- + bnxt_re_add_device(adev, BNXT_RE_POST_RECOVERY_INIT); + rdev = en_info->rdev; + ibdev_info(&rdev->ibdev, "Device resume completed"); +-- +2.43.0 + diff --git a/queue-6.12/rdma-core-implement-roce-gid-port-rescan-and-export-.patch b/queue-6.12/rdma-core-implement-roce-gid-port-rescan-and-export-.patch new file mode 100644 index 00000000000..0313173deac --- /dev/null +++ b/queue-6.12/rdma-core-implement-roce-gid-port-rescan-and-export-.patch @@ -0,0 +1,100 @@ +From f23f3d2640d03a0f1bb5d643e2cb303bd5b7845b Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Thu, 31 Oct 2024 15:36:51 +0200 +Subject: RDMA/core: Implement RoCE GID port rescan and export delete function + +From: Chiara Meiohas <cmeiohas@nvidia.com> + +[ Upstream commit af7a35bf6c36a77624d3abe46b3830b7c2a5f20c ] + +rdma_roce_rescan_port() scans all network devices in +the system and adds the gids if relevant to the RoCE device +port. When not in bonding mode it adds the GIDs of the +netdevice in this port. When in bonding mode it adds the +GIDs of both the port's netdevice and the bond master +netdevice. + +Export roce_del_all_netdev_gids(), which removes all GIDs +associated with a specific netdevice for a given port. + +Signed-off-by: Chiara Meiohas <cmeiohas@nvidia.com> +Link: https://patch.msgid.link/674d498da4637a1503ff1367e28bd09ff942fd5e.1730381292.git.leon@kernel.org +Signed-off-by: Leon Romanovsky <leon@kernel.org> +Stable-dep-of: 0bd2c61df953 ("RDMA/mlx5: Ensure active slave attachment to the bond IB device") +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/infiniband/core/roce_gid_mgmt.c | 30 +++++++++++++++++++++---- + include/rdma/ib_verbs.h | 3 +++ + 2 files changed, 29 insertions(+), 4 deletions(-) + +diff --git a/drivers/infiniband/core/roce_gid_mgmt.c b/drivers/infiniband/core/roce_gid_mgmt.c +index d5131b3ba8ab0..a9f2c6b1b29ed 100644 +--- a/drivers/infiniband/core/roce_gid_mgmt.c ++++ b/drivers/infiniband/core/roce_gid_mgmt.c +@@ -515,6 +515,27 @@ void rdma_roce_rescan_device(struct ib_device *ib_dev) + } + EXPORT_SYMBOL(rdma_roce_rescan_device); + ++/** ++ * rdma_roce_rescan_port - Rescan all of the network devices in the system ++ * and add their gids if relevant to the port of the RoCE device. ++ * ++ * @ib_dev: IB device ++ * @port: Port number ++ */ ++void rdma_roce_rescan_port(struct ib_device *ib_dev, u32 port) ++{ ++ struct net_device *ndev = NULL; ++ ++ if (rdma_protocol_roce(ib_dev, port)) { ++ ndev = ib_device_get_netdev(ib_dev, port); ++ if (!ndev) ++ return; ++ enum_all_gids_of_dev_cb(ib_dev, port, ndev, ndev); ++ dev_put(ndev); ++ } ++} ++EXPORT_SYMBOL(rdma_roce_rescan_port); ++ + static void callback_for_addr_gid_device_scan(struct ib_device *device, + u32 port, + struct net_device *rdma_ndev, +@@ -575,16 +596,17 @@ static void handle_netdev_upper(struct ib_device *ib_dev, u32 port, + } + } + +-static void _roce_del_all_netdev_gids(struct ib_device *ib_dev, u32 port, +- struct net_device *event_ndev) ++void roce_del_all_netdev_gids(struct ib_device *ib_dev, ++ u32 port, struct net_device *ndev) + { +- ib_cache_gid_del_all_netdev_gids(ib_dev, port, event_ndev); ++ ib_cache_gid_del_all_netdev_gids(ib_dev, port, ndev); + } ++EXPORT_SYMBOL(roce_del_all_netdev_gids); + + static void del_netdev_upper_ips(struct ib_device *ib_dev, u32 port, + struct net_device *rdma_ndev, void *cookie) + { +- handle_netdev_upper(ib_dev, port, cookie, _roce_del_all_netdev_gids); ++ handle_netdev_upper(ib_dev, port, cookie, roce_del_all_netdev_gids); + } + + static void add_netdev_upper_ips(struct ib_device *ib_dev, u32 port, +diff --git a/include/rdma/ib_verbs.h b/include/rdma/ib_verbs.h +index 9cb8b5fe7eee4..67551133b5228 100644 +--- a/include/rdma/ib_verbs.h ++++ b/include/rdma/ib_verbs.h +@@ -4734,6 +4734,9 @@ ib_get_vector_affinity(struct ib_device *device, int comp_vector) + * @device: the rdma device + */ + void rdma_roce_rescan_device(struct ib_device *ibdev); ++void rdma_roce_rescan_port(struct ib_device *ib_dev, u32 port); ++void roce_del_all_netdev_gids(struct ib_device *ib_dev, ++ u32 port, struct net_device *ndev); + + struct ib_ucontext *ib_uverbs_get_ucontext_file(struct ib_uverbs_file *ufile); + +-- +2.43.0 + diff --git a/queue-6.12/rdma-core-provide-rdma_user_mmap_disassociate-to-dis.patch b/queue-6.12/rdma-core-provide-rdma_user_mmap_disassociate-to-dis.patch new file mode 100644 index 00000000000..f146f9d5508 --- /dev/null +++ b/queue-6.12/rdma-core-provide-rdma_user_mmap_disassociate-to-dis.patch @@ -0,0 +1,183 @@ +From 37d531599a576613f08e39eaf1826bc56777aae1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Fri, 27 Sep 2024 18:33:22 +0800 +Subject: RDMA/core: Provide rdma_user_mmap_disassociate() to disassociate mmap + pages + +From: Chengchang Tang <tangchengchang@huawei.com> + +[ Upstream commit 51976c6cd786151b6a1bdf8b8b3334beac0ba99c ] + +Provide a new api rdma_user_mmap_disassociate() for drivers to +disassociate mmap pages for a device. + +Since drivers can now disassociate mmaps by calling this api, +introduce a new disassociation_lock to specifically prevent +races between this disassociation process and new mmaps. And +thus the old hw_destroy_rwsem is not needed in this api. + +Signed-off-by: Chengchang Tang <tangchengchang@huawei.com> +Signed-off-by: Junxian Huang <huangjunxian6@hisilicon.com> +Link: https://patch.msgid.link/20240927103323.1897094-2-huangjunxian6@hisilicon.com +Signed-off-by: Leon Romanovsky <leon@kernel.org> +Stable-dep-of: 615b94746a54 ("RDMA/hns: Disassociate mmap pages for all uctx when HW is being reset") +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/infiniband/core/uverbs.h | 2 ++ + drivers/infiniband/core/uverbs_main.c | 43 +++++++++++++++++++++++++-- + include/rdma/ib_verbs.h | 8 +++++ + 3 files changed, 51 insertions(+), 2 deletions(-) + +diff --git a/drivers/infiniband/core/uverbs.h b/drivers/infiniband/core/uverbs.h +index 821d93c8f7123..dfd2e5a86e6fe 100644 +--- a/drivers/infiniband/core/uverbs.h ++++ b/drivers/infiniband/core/uverbs.h +@@ -160,6 +160,8 @@ struct ib_uverbs_file { + struct page *disassociate_page; + + struct xarray idr; ++ ++ struct mutex disassociation_lock; + }; + + struct ib_uverbs_event { +diff --git a/drivers/infiniband/core/uverbs_main.c b/drivers/infiniband/core/uverbs_main.c +index 94454186ed81d..85cfc790a7bb3 100644 +--- a/drivers/infiniband/core/uverbs_main.c ++++ b/drivers/infiniband/core/uverbs_main.c +@@ -76,6 +76,7 @@ static dev_t dynamic_uverbs_dev; + static DEFINE_IDA(uverbs_ida); + static int ib_uverbs_add_one(struct ib_device *device); + static void ib_uverbs_remove_one(struct ib_device *device, void *client_data); ++static struct ib_client uverbs_client; + + static char *uverbs_devnode(const struct device *dev, umode_t *mode) + { +@@ -217,6 +218,7 @@ void ib_uverbs_release_file(struct kref *ref) + + if (file->disassociate_page) + __free_pages(file->disassociate_page, 0); ++ mutex_destroy(&file->disassociation_lock); + mutex_destroy(&file->umap_lock); + mutex_destroy(&file->ucontext_lock); + kfree(file); +@@ -698,8 +700,13 @@ static int ib_uverbs_mmap(struct file *filp, struct vm_area_struct *vma) + ret = PTR_ERR(ucontext); + goto out; + } ++ ++ mutex_lock(&file->disassociation_lock); ++ + vma->vm_ops = &rdma_umap_ops; + ret = ucontext->device->ops.mmap(ucontext, vma); ++ ++ mutex_unlock(&file->disassociation_lock); + out: + srcu_read_unlock(&file->device->disassociate_srcu, srcu_key); + return ret; +@@ -721,6 +728,8 @@ static void rdma_umap_open(struct vm_area_struct *vma) + /* We are racing with disassociation */ + if (!down_read_trylock(&ufile->hw_destroy_rwsem)) + goto out_zap; ++ mutex_lock(&ufile->disassociation_lock); ++ + /* + * Disassociation already completed, the VMA should already be zapped. + */ +@@ -732,10 +741,12 @@ static void rdma_umap_open(struct vm_area_struct *vma) + goto out_unlock; + rdma_umap_priv_init(priv, vma, opriv->entry); + ++ mutex_unlock(&ufile->disassociation_lock); + up_read(&ufile->hw_destroy_rwsem); + return; + + out_unlock: ++ mutex_unlock(&ufile->disassociation_lock); + up_read(&ufile->hw_destroy_rwsem); + out_zap: + /* +@@ -819,7 +830,7 @@ void uverbs_user_mmap_disassociate(struct ib_uverbs_file *ufile) + { + struct rdma_umap_priv *priv, *next_priv; + +- lockdep_assert_held(&ufile->hw_destroy_rwsem); ++ mutex_lock(&ufile->disassociation_lock); + + while (1) { + struct mm_struct *mm = NULL; +@@ -845,8 +856,10 @@ void uverbs_user_mmap_disassociate(struct ib_uverbs_file *ufile) + break; + } + mutex_unlock(&ufile->umap_lock); +- if (!mm) ++ if (!mm) { ++ mutex_unlock(&ufile->disassociation_lock); + return; ++ } + + /* + * The umap_lock is nested under mmap_lock since it used within +@@ -876,7 +889,31 @@ void uverbs_user_mmap_disassociate(struct ib_uverbs_file *ufile) + mmap_read_unlock(mm); + mmput(mm); + } ++ ++ mutex_unlock(&ufile->disassociation_lock); ++} ++ ++/** ++ * rdma_user_mmap_disassociate() - Revoke mmaps for a device ++ * @device: device to revoke ++ * ++ * This function should be called by drivers that need to disable mmaps for the ++ * device, for instance because it is going to be reset. ++ */ ++void rdma_user_mmap_disassociate(struct ib_device *device) ++{ ++ struct ib_uverbs_device *uverbs_dev = ++ ib_get_client_data(device, &uverbs_client); ++ struct ib_uverbs_file *ufile; ++ ++ mutex_lock(&uverbs_dev->lists_mutex); ++ list_for_each_entry(ufile, &uverbs_dev->uverbs_file_list, list) { ++ if (ufile->ucontext) ++ uverbs_user_mmap_disassociate(ufile); ++ } ++ mutex_unlock(&uverbs_dev->lists_mutex); + } ++EXPORT_SYMBOL(rdma_user_mmap_disassociate); + + /* + * ib_uverbs_open() does not need the BKL: +@@ -947,6 +984,8 @@ static int ib_uverbs_open(struct inode *inode, struct file *filp) + mutex_init(&file->umap_lock); + INIT_LIST_HEAD(&file->umaps); + ++ mutex_init(&file->disassociation_lock); ++ + filp->private_data = file; + list_add_tail(&file->list, &dev->uverbs_file_list); + mutex_unlock(&dev->lists_mutex); +diff --git a/include/rdma/ib_verbs.h b/include/rdma/ib_verbs.h +index aa8ede439905c..9cb8b5fe7eee4 100644 +--- a/include/rdma/ib_verbs.h ++++ b/include/rdma/ib_verbs.h +@@ -2948,6 +2948,14 @@ int rdma_user_mmap_entry_insert_range(struct ib_ucontext *ucontext, + size_t length, u32 min_pgoff, + u32 max_pgoff); + ++#if IS_ENABLED(CONFIG_INFINIBAND_USER_ACCESS) ++void rdma_user_mmap_disassociate(struct ib_device *device); ++#else ++static inline void rdma_user_mmap_disassociate(struct ib_device *device) ++{ ++} ++#endif ++ + static inline int + rdma_user_mmap_entry_insert_exact(struct ib_ucontext *ucontext, + struct rdma_user_mmap_entry *entry, +-- +2.43.0 + diff --git a/queue-6.12/rdma-hns-disassociate-mmap-pages-for-all-uctx-when-h.patch b/queue-6.12/rdma-hns-disassociate-mmap-pages-for-all-uctx-when-h.patch new file mode 100644 index 00000000000..d2f4b324612 --- /dev/null +++ b/queue-6.12/rdma-hns-disassociate-mmap-pages-for-all-uctx-when-h.patch @@ -0,0 +1,68 @@ +From 9f9c44bf5e3b4b0bd1c346456f2d586731587956 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Fri, 27 Sep 2024 18:33:23 +0800 +Subject: RDMA/hns: Disassociate mmap pages for all uctx when HW is being reset + +From: Chengchang Tang <tangchengchang@huawei.com> + +[ Upstream commit 615b94746a54702af923b28bd8a629f4ac0ff0d8 ] + +When HW is being reset, userspace should not ring doorbell otherwise +it may lead to abnormal consequence such as RAS. + +Disassociate mmap pages for all uctx to prevent userspace from ringing +doorbell to HW. Since all resources will be destroyed during HW reset, +no new mmap is allowed after HW reset is completed. + +Fixes: 9a4435375cd1 ("IB/hns: Add driver files for hns RoCE driver") +Signed-off-by: Chengchang Tang <tangchengchang@huawei.com> +Signed-off-by: Junxian Huang <huangjunxian6@hisilicon.com> +Link: https://patch.msgid.link/20240927103323.1897094-3-huangjunxian6@hisilicon.com +Signed-off-by: Leon Romanovsky <leon@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/infiniband/hw/hns/hns_roce_hw_v2.c | 4 ++++ + drivers/infiniband/hw/hns/hns_roce_main.c | 5 +++++ + 2 files changed, 9 insertions(+) + +diff --git a/drivers/infiniband/hw/hns/hns_roce_hw_v2.c b/drivers/infiniband/hw/hns/hns_roce_hw_v2.c +index 24e906b9d3ae1..f1feaa79f78ee 100644 +--- a/drivers/infiniband/hw/hns/hns_roce_hw_v2.c ++++ b/drivers/infiniband/hw/hns/hns_roce_hw_v2.c +@@ -7017,6 +7017,7 @@ static void hns_roce_hw_v2_uninit_instance(struct hnae3_handle *handle, + + handle->rinfo.instance_state = HNS_ROCE_STATE_NON_INIT; + } ++ + static int hns_roce_hw_v2_reset_notify_down(struct hnae3_handle *handle) + { + struct hns_roce_dev *hr_dev; +@@ -7035,6 +7036,9 @@ static int hns_roce_hw_v2_reset_notify_down(struct hnae3_handle *handle) + + hr_dev->active = false; + hr_dev->dis_db = true; ++ ++ rdma_user_mmap_disassociate(&hr_dev->ib_dev); ++ + hr_dev->state = HNS_ROCE_DEVICE_STATE_RST_DOWN; + + return 0; +diff --git a/drivers/infiniband/hw/hns/hns_roce_main.c b/drivers/infiniband/hw/hns/hns_roce_main.c +index 4cb0af7335870..49315f39361de 100644 +--- a/drivers/infiniband/hw/hns/hns_roce_main.c ++++ b/drivers/infiniband/hw/hns/hns_roce_main.c +@@ -466,6 +466,11 @@ static int hns_roce_mmap(struct ib_ucontext *uctx, struct vm_area_struct *vma) + pgprot_t prot; + int ret; + ++ if (hr_dev->dis_db) { ++ atomic64_inc(&hr_dev->dfx_cnt[HNS_ROCE_DFX_MMAP_ERR_CNT]); ++ return -EPERM; ++ } ++ + rdma_entry = rdma_user_mmap_entry_get_pgoff(uctx, vma->vm_pgoff); + if (!rdma_entry) { + atomic64_inc(&hr_dev->dfx_cnt[HNS_ROCE_DFX_MMAP_ERR_CNT]); +-- +2.43.0 + diff --git a/queue-6.12/rdma-hns-fix-an-aeqe-overflow-error-caused-by-untime.patch b/queue-6.12/rdma-hns-fix-an-aeqe-overflow-error-caused-by-untime.patch new file mode 100644 index 00000000000..393a35bd1dc --- /dev/null +++ b/queue-6.12/rdma-hns-fix-an-aeqe-overflow-error-caused-by-untime.patch @@ -0,0 +1,292 @@ +From 180d8b4cf1e188c0f41fe6bf27080fc2992c8c13 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Thu, 24 Oct 2024 20:39:56 +0800 +Subject: RDMA/hns: Fix an AEQE overflow error caused by untimely update of + eq_db_ci + +From: wenglianfa <wenglianfa@huawei.com> + +[ Upstream commit 571e4ab8a45e530623ab129803f090a844dd3fe9 ] + +eq_db_ci is updated only after all AEQEs are processed in the AEQ +interrupt handler, which is not timely enough and may result in +AEQ overflow. Two optimization methods are proposed: +1. Set an upper limit for AEQE processing. +2. Move time-consuming operations such as printings to the bottom +half of the interrupt. + +cmd events and flush_cqe events are still fully processed in the top half +to ensure timely handling. + +Fixes: a5073d6054f7 ("RDMA/hns: Add eq support of hip08") +Signed-off-by: wenglianfa <wenglianfa@huawei.com> +Signed-off-by: Junxian Huang <huangjunxian6@hisilicon.com> +Link: https://patch.msgid.link/20241024124000.2931869-2-huangjunxian6@hisilicon.com +Signed-off-by: Leon Romanovsky <leon@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/infiniband/hw/hns/hns_roce_device.h | 1 + + drivers/infiniband/hw/hns/hns_roce_hw_v2.c | 75 ++++++++++++++------- + drivers/infiniband/hw/hns/hns_roce_hw_v2.h | 5 ++ + drivers/infiniband/hw/hns/hns_roce_qp.c | 54 +++++++++------ + 4 files changed, 91 insertions(+), 44 deletions(-) + +diff --git a/drivers/infiniband/hw/hns/hns_roce_device.h b/drivers/infiniband/hw/hns/hns_roce_device.h +index 0b1e21cb6d2d3..73c78005901e6 100644 +--- a/drivers/infiniband/hw/hns/hns_roce_device.h ++++ b/drivers/infiniband/hw/hns/hns_roce_device.h +@@ -1289,6 +1289,7 @@ void hns_roce_cq_completion(struct hns_roce_dev *hr_dev, u32 cqn); + void hns_roce_cq_event(struct hns_roce_dev *hr_dev, u32 cqn, int event_type); + void flush_cqe(struct hns_roce_dev *dev, struct hns_roce_qp *qp); + void hns_roce_qp_event(struct hns_roce_dev *hr_dev, u32 qpn, int event_type); ++void hns_roce_flush_cqe(struct hns_roce_dev *hr_dev, u32 qpn); + void hns_roce_srq_event(struct hns_roce_dev *hr_dev, u32 srqn, int event_type); + void hns_roce_handle_device_err(struct hns_roce_dev *hr_dev); + int hns_roce_init(struct hns_roce_dev *hr_dev); +diff --git a/drivers/infiniband/hw/hns/hns_roce_hw_v2.c b/drivers/infiniband/hw/hns/hns_roce_hw_v2.c +index f1feaa79f78ee..bbdeb02102e87 100644 +--- a/drivers/infiniband/hw/hns/hns_roce_hw_v2.c ++++ b/drivers/infiniband/hw/hns/hns_roce_hw_v2.c +@@ -5967,11 +5967,10 @@ static int hns_roce_v2_query_mpt(struct hns_roce_dev *hr_dev, u32 key, + return ret; + } + +-static void hns_roce_irq_work_handle(struct work_struct *work) ++static void dump_aeqe_log(struct hns_roce_work *irq_work) + { +- struct hns_roce_work *irq_work = +- container_of(work, struct hns_roce_work, work); +- struct ib_device *ibdev = &irq_work->hr_dev->ib_dev; ++ struct hns_roce_dev *hr_dev = irq_work->hr_dev; ++ struct ib_device *ibdev = &hr_dev->ib_dev; + + switch (irq_work->event_type) { + case HNS_ROCE_EVENT_TYPE_PATH_MIG: +@@ -6015,6 +6014,8 @@ static void hns_roce_irq_work_handle(struct work_struct *work) + case HNS_ROCE_EVENT_TYPE_DB_OVERFLOW: + ibdev_warn(ibdev, "DB overflow.\n"); + break; ++ case HNS_ROCE_EVENT_TYPE_MB: ++ break; + case HNS_ROCE_EVENT_TYPE_FLR: + ibdev_warn(ibdev, "function level reset.\n"); + break; +@@ -6025,8 +6026,46 @@ static void hns_roce_irq_work_handle(struct work_struct *work) + ibdev_err(ibdev, "invalid xrceth error.\n"); + break; + default: ++ ibdev_info(ibdev, "Undefined event %d.\n", ++ irq_work->event_type); + break; + } ++} ++ ++static void hns_roce_irq_work_handle(struct work_struct *work) ++{ ++ struct hns_roce_work *irq_work = ++ container_of(work, struct hns_roce_work, work); ++ struct hns_roce_dev *hr_dev = irq_work->hr_dev; ++ int event_type = irq_work->event_type; ++ u32 queue_num = irq_work->queue_num; ++ ++ switch (event_type) { ++ case HNS_ROCE_EVENT_TYPE_PATH_MIG: ++ case HNS_ROCE_EVENT_TYPE_PATH_MIG_FAILED: ++ case HNS_ROCE_EVENT_TYPE_COMM_EST: ++ case HNS_ROCE_EVENT_TYPE_SQ_DRAINED: ++ case HNS_ROCE_EVENT_TYPE_WQ_CATAS_ERROR: ++ case HNS_ROCE_EVENT_TYPE_SRQ_LAST_WQE_REACH: ++ case HNS_ROCE_EVENT_TYPE_INV_REQ_LOCAL_WQ_ERROR: ++ case HNS_ROCE_EVENT_TYPE_LOCAL_WQ_ACCESS_ERROR: ++ case HNS_ROCE_EVENT_TYPE_XRCD_VIOLATION: ++ case HNS_ROCE_EVENT_TYPE_INVALID_XRCETH: ++ hns_roce_qp_event(hr_dev, queue_num, event_type); ++ break; ++ case HNS_ROCE_EVENT_TYPE_SRQ_LIMIT_REACH: ++ case HNS_ROCE_EVENT_TYPE_SRQ_CATAS_ERROR: ++ hns_roce_srq_event(hr_dev, queue_num, event_type); ++ break; ++ case HNS_ROCE_EVENT_TYPE_CQ_ACCESS_ERROR: ++ case HNS_ROCE_EVENT_TYPE_CQ_OVERFLOW: ++ hns_roce_cq_event(hr_dev, queue_num, event_type); ++ break; ++ default: ++ break; ++ } ++ ++ dump_aeqe_log(irq_work); + + kfree(irq_work); + } +@@ -6087,14 +6126,14 @@ static struct hns_roce_aeqe *next_aeqe_sw_v2(struct hns_roce_eq *eq) + static irqreturn_t hns_roce_v2_aeq_int(struct hns_roce_dev *hr_dev, + struct hns_roce_eq *eq) + { +- struct device *dev = hr_dev->dev; + struct hns_roce_aeqe *aeqe = next_aeqe_sw_v2(eq); + irqreturn_t aeqe_found = IRQ_NONE; ++ int num_aeqes = 0; + int event_type; + u32 queue_num; + int sub_type; + +- while (aeqe) { ++ while (aeqe && num_aeqes < HNS_AEQ_POLLING_BUDGET) { + /* Make sure we read AEQ entry after we have checked the + * ownership bit + */ +@@ -6105,25 +6144,12 @@ static irqreturn_t hns_roce_v2_aeq_int(struct hns_roce_dev *hr_dev, + queue_num = hr_reg_read(aeqe, AEQE_EVENT_QUEUE_NUM); + + switch (event_type) { +- case HNS_ROCE_EVENT_TYPE_PATH_MIG: +- case HNS_ROCE_EVENT_TYPE_PATH_MIG_FAILED: +- case HNS_ROCE_EVENT_TYPE_COMM_EST: +- case HNS_ROCE_EVENT_TYPE_SQ_DRAINED: + case HNS_ROCE_EVENT_TYPE_WQ_CATAS_ERROR: +- case HNS_ROCE_EVENT_TYPE_SRQ_LAST_WQE_REACH: + case HNS_ROCE_EVENT_TYPE_INV_REQ_LOCAL_WQ_ERROR: + case HNS_ROCE_EVENT_TYPE_LOCAL_WQ_ACCESS_ERROR: + case HNS_ROCE_EVENT_TYPE_XRCD_VIOLATION: + case HNS_ROCE_EVENT_TYPE_INVALID_XRCETH: +- hns_roce_qp_event(hr_dev, queue_num, event_type); +- break; +- case HNS_ROCE_EVENT_TYPE_SRQ_LIMIT_REACH: +- case HNS_ROCE_EVENT_TYPE_SRQ_CATAS_ERROR: +- hns_roce_srq_event(hr_dev, queue_num, event_type); +- break; +- case HNS_ROCE_EVENT_TYPE_CQ_ACCESS_ERROR: +- case HNS_ROCE_EVENT_TYPE_CQ_OVERFLOW: +- hns_roce_cq_event(hr_dev, queue_num, event_type); ++ hns_roce_flush_cqe(hr_dev, queue_num); + break; + case HNS_ROCE_EVENT_TYPE_MB: + hns_roce_cmd_event(hr_dev, +@@ -6131,12 +6157,7 @@ static irqreturn_t hns_roce_v2_aeq_int(struct hns_roce_dev *hr_dev, + aeqe->event.cmd.status, + le64_to_cpu(aeqe->event.cmd.out_param)); + break; +- case HNS_ROCE_EVENT_TYPE_DB_OVERFLOW: +- case HNS_ROCE_EVENT_TYPE_FLR: +- break; + default: +- dev_err(dev, "unhandled event %d on EQ %d at idx %u.\n", +- event_type, eq->eqn, eq->cons_index); + break; + } + +@@ -6150,6 +6171,7 @@ static irqreturn_t hns_roce_v2_aeq_int(struct hns_roce_dev *hr_dev, + hns_roce_v2_init_irq_work(hr_dev, eq, queue_num); + + aeqe = next_aeqe_sw_v2(eq); ++ ++num_aeqes; + } + + update_eq_db(eq); +@@ -6699,6 +6721,9 @@ static int hns_roce_v2_init_eq_table(struct hns_roce_dev *hr_dev) + int ret; + int i; + ++ if (hr_dev->caps.aeqe_depth < HNS_AEQ_POLLING_BUDGET) ++ return -EINVAL; ++ + other_num = hr_dev->caps.num_other_vectors; + comp_num = hr_dev->caps.num_comp_vectors; + aeq_num = hr_dev->caps.num_aeq_vectors; +diff --git a/drivers/infiniband/hw/hns/hns_roce_hw_v2.h b/drivers/infiniband/hw/hns/hns_roce_hw_v2.h +index c65f68a14a260..3b3c6259ace0e 100644 +--- a/drivers/infiniband/hw/hns/hns_roce_hw_v2.h ++++ b/drivers/infiniband/hw/hns/hns_roce_hw_v2.h +@@ -85,6 +85,11 @@ + + #define HNS_ROCE_V2_TABLE_CHUNK_SIZE (1 << 18) + ++/* budget must be smaller than aeqe_depth to guarantee that we update ++ * the ci before we polled all the entries in the EQ. ++ */ ++#define HNS_AEQ_POLLING_BUDGET 64 ++ + enum { + HNS_ROCE_CMD_FLAG_IN = BIT(0), + HNS_ROCE_CMD_FLAG_OUT = BIT(1), +diff --git a/drivers/infiniband/hw/hns/hns_roce_qp.c b/drivers/infiniband/hw/hns/hns_roce_qp.c +index 6b03ba671ff8f..dcaa370d4a265 100644 +--- a/drivers/infiniband/hw/hns/hns_roce_qp.c ++++ b/drivers/infiniband/hw/hns/hns_roce_qp.c +@@ -39,6 +39,25 @@ + #include "hns_roce_device.h" + #include "hns_roce_hem.h" + ++static struct hns_roce_qp *hns_roce_qp_lookup(struct hns_roce_dev *hr_dev, ++ u32 qpn) ++{ ++ struct device *dev = hr_dev->dev; ++ struct hns_roce_qp *qp; ++ unsigned long flags; ++ ++ xa_lock_irqsave(&hr_dev->qp_table_xa, flags); ++ qp = __hns_roce_qp_lookup(hr_dev, qpn); ++ if (qp) ++ refcount_inc(&qp->refcount); ++ xa_unlock_irqrestore(&hr_dev->qp_table_xa, flags); ++ ++ if (!qp) ++ dev_warn(dev, "async event for bogus QP %08x\n", qpn); ++ ++ return qp; ++} ++ + static void flush_work_handle(struct work_struct *work) + { + struct hns_roce_work *flush_work = container_of(work, +@@ -95,31 +114,28 @@ void flush_cqe(struct hns_roce_dev *dev, struct hns_roce_qp *qp) + + void hns_roce_qp_event(struct hns_roce_dev *hr_dev, u32 qpn, int event_type) + { +- struct device *dev = hr_dev->dev; + struct hns_roce_qp *qp; + +- xa_lock(&hr_dev->qp_table_xa); +- qp = __hns_roce_qp_lookup(hr_dev, qpn); +- if (qp) +- refcount_inc(&qp->refcount); +- xa_unlock(&hr_dev->qp_table_xa); +- +- if (!qp) { +- dev_warn(dev, "async event for bogus QP %08x\n", qpn); ++ qp = hns_roce_qp_lookup(hr_dev, qpn); ++ if (!qp) + return; +- } + +- if (event_type == HNS_ROCE_EVENT_TYPE_WQ_CATAS_ERROR || +- event_type == HNS_ROCE_EVENT_TYPE_INV_REQ_LOCAL_WQ_ERROR || +- event_type == HNS_ROCE_EVENT_TYPE_LOCAL_WQ_ACCESS_ERROR || +- event_type == HNS_ROCE_EVENT_TYPE_XRCD_VIOLATION || +- event_type == HNS_ROCE_EVENT_TYPE_INVALID_XRCETH) { +- qp->state = IB_QPS_ERR; ++ qp->event(qp, (enum hns_roce_event)event_type); + +- flush_cqe(hr_dev, qp); +- } ++ if (refcount_dec_and_test(&qp->refcount)) ++ complete(&qp->free); ++} + +- qp->event(qp, (enum hns_roce_event)event_type); ++void hns_roce_flush_cqe(struct hns_roce_dev *hr_dev, u32 qpn) ++{ ++ struct hns_roce_qp *qp; ++ ++ qp = hns_roce_qp_lookup(hr_dev, qpn); ++ if (!qp) ++ return; ++ ++ qp->state = IB_QPS_ERR; ++ flush_cqe(hr_dev, qp); + + if (refcount_dec_and_test(&qp->refcount)) + complete(&qp->free); +-- +2.43.0 + diff --git a/queue-6.12/rdma-hns-fix-cpu-stuck-caused-by-printings-during-re.patch b/queue-6.12/rdma-hns-fix-cpu-stuck-caused-by-printings-during-re.patch new file mode 100644 index 00000000000..a658f6993ca --- /dev/null +++ b/queue-6.12/rdma-hns-fix-cpu-stuck-caused-by-printings-during-re.patch @@ -0,0 +1,274 @@ +From f7db8d1750d251d6271a96154c2e6d826aadb41c Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Thu, 24 Oct 2024 20:40:00 +0800 +Subject: RDMA/hns: Fix cpu stuck caused by printings during reset + +From: wenglianfa <wenglianfa@huawei.com> + +[ Upstream commit 323275ac2ff15b2b7b3eac391ae5d8c5a3c3a999 ] + +During reset, cmd to destroy resources such as qp, cq, and mr may fail, +and error logs will be printed. When a large number of resources are +destroyed, there will be lots of printings, and it may lead to a cpu +stuck. + +Delete some unnecessary printings and replace other printing functions +in these paths with the ratelimited version. + +Fixes: 9a4435375cd1 ("IB/hns: Add driver files for hns RoCE driver") +Fixes: c7bcb13442e1 ("RDMA/hns: Add SRQ support for hip08 kernel mode") +Fixes: 70f92521584f ("RDMA/hns: Use the reserved loopback QPs to free MR before destroying MPT") +Fixes: 926a01dc000d ("RDMA/hns: Add QP operations support for hip08 SoC") +Signed-off-by: wenglianfa <wenglianfa@huawei.com> +Signed-off-by: Junxian Huang <huangjunxian6@hisilicon.com> +Link: https://patch.msgid.link/20241024124000.2931869-6-huangjunxian6@hisilicon.com +Signed-off-by: Leon Romanovsky <leon@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/infiniband/hw/hns/hns_roce_cq.c | 4 +- + drivers/infiniband/hw/hns/hns_roce_hem.c | 4 +- + drivers/infiniband/hw/hns/hns_roce_hw_v2.c | 73 ++++++++++------------ + drivers/infiniband/hw/hns/hns_roce_mr.c | 4 +- + drivers/infiniband/hw/hns/hns_roce_srq.c | 4 +- + 5 files changed, 41 insertions(+), 48 deletions(-) + +diff --git a/drivers/infiniband/hw/hns/hns_roce_cq.c b/drivers/infiniband/hw/hns/hns_roce_cq.c +index 4ec66611a1434..4106423a1b399 100644 +--- a/drivers/infiniband/hw/hns/hns_roce_cq.c ++++ b/drivers/infiniband/hw/hns/hns_roce_cq.c +@@ -179,8 +179,8 @@ static void free_cqc(struct hns_roce_dev *hr_dev, struct hns_roce_cq *hr_cq) + ret = hns_roce_destroy_hw_ctx(hr_dev, HNS_ROCE_CMD_DESTROY_CQC, + hr_cq->cqn); + if (ret) +- dev_err(dev, "DESTROY_CQ failed (%d) for CQN %06lx\n", ret, +- hr_cq->cqn); ++ dev_err_ratelimited(dev, "DESTROY_CQ failed (%d) for CQN %06lx\n", ++ ret, hr_cq->cqn); + + xa_erase_irq(&cq_table->array, hr_cq->cqn); + +diff --git a/drivers/infiniband/hw/hns/hns_roce_hem.c b/drivers/infiniband/hw/hns/hns_roce_hem.c +index ee5d2c1bb5ca0..f84521be3bea4 100644 +--- a/drivers/infiniband/hw/hns/hns_roce_hem.c ++++ b/drivers/infiniband/hw/hns/hns_roce_hem.c +@@ -672,8 +672,8 @@ void hns_roce_table_put(struct hns_roce_dev *hr_dev, + + ret = hr_dev->hw->clear_hem(hr_dev, table, obj, HEM_HOP_STEP_DIRECT); + if (ret) +- dev_warn(dev, "failed to clear HEM base address, ret = %d.\n", +- ret); ++ dev_warn_ratelimited(dev, "failed to clear HEM base address, ret = %d.\n", ++ ret); + + hns_roce_free_hem(hr_dev, table->hem[i]); + table->hem[i] = NULL; +diff --git a/drivers/infiniband/hw/hns/hns_roce_hw_v2.c b/drivers/infiniband/hw/hns/hns_roce_hw_v2.c +index 4c3bc1f6a183c..d1c075fb0ad89 100644 +--- a/drivers/infiniband/hw/hns/hns_roce_hw_v2.c ++++ b/drivers/infiniband/hw/hns/hns_roce_hw_v2.c +@@ -373,19 +373,12 @@ static int set_rwqe_data_seg(struct ib_qp *ibqp, const struct ib_send_wr *wr, + static int check_send_valid(struct hns_roce_dev *hr_dev, + struct hns_roce_qp *hr_qp) + { +- struct ib_device *ibdev = &hr_dev->ib_dev; +- + if (unlikely(hr_qp->state == IB_QPS_RESET || + hr_qp->state == IB_QPS_INIT || +- hr_qp->state == IB_QPS_RTR)) { +- ibdev_err(ibdev, "failed to post WQE, QP state %u!\n", +- hr_qp->state); ++ hr_qp->state == IB_QPS_RTR)) + return -EINVAL; +- } else if (unlikely(hr_dev->state >= HNS_ROCE_DEVICE_STATE_RST_DOWN)) { +- ibdev_err(ibdev, "failed to post WQE, dev state %d!\n", +- hr_dev->state); ++ else if (unlikely(hr_dev->state >= HNS_ROCE_DEVICE_STATE_RST_DOWN)) + return -EIO; +- } + + return 0; + } +@@ -2775,8 +2768,8 @@ static int free_mr_modify_rsv_qp(struct hns_roce_dev *hr_dev, + ret = hr_dev->hw->modify_qp(&hr_qp->ibqp, attr, mask, IB_QPS_INIT, + IB_QPS_INIT, NULL); + if (ret) { +- ibdev_err(ibdev, "failed to modify qp to init, ret = %d.\n", +- ret); ++ ibdev_err_ratelimited(ibdev, "failed to modify qp to init, ret = %d.\n", ++ ret); + return ret; + } + +@@ -3421,8 +3414,8 @@ static int free_mr_post_send_lp_wqe(struct hns_roce_qp *hr_qp) + + ret = hns_roce_v2_post_send(&hr_qp->ibqp, send_wr, &bad_wr); + if (ret) { +- ibdev_err(ibdev, "failed to post wqe for free mr, ret = %d.\n", +- ret); ++ ibdev_err_ratelimited(ibdev, "failed to post wqe for free mr, ret = %d.\n", ++ ret); + return ret; + } + +@@ -3461,9 +3454,9 @@ static void free_mr_send_cmd_to_hw(struct hns_roce_dev *hr_dev) + + ret = free_mr_post_send_lp_wqe(hr_qp); + if (ret) { +- ibdev_err(ibdev, +- "failed to send wqe (qp:0x%lx) for free mr, ret = %d.\n", +- hr_qp->qpn, ret); ++ ibdev_err_ratelimited(ibdev, ++ "failed to send wqe (qp:0x%lx) for free mr, ret = %d.\n", ++ hr_qp->qpn, ret); + break; + } + +@@ -3474,16 +3467,16 @@ static void free_mr_send_cmd_to_hw(struct hns_roce_dev *hr_dev) + while (cqe_cnt) { + npolled = hns_roce_v2_poll_cq(&free_mr->rsv_cq->ib_cq, cqe_cnt, wc); + if (npolled < 0) { +- ibdev_err(ibdev, +- "failed to poll cqe for free mr, remain %d cqe.\n", +- cqe_cnt); ++ ibdev_err_ratelimited(ibdev, ++ "failed to poll cqe for free mr, remain %d cqe.\n", ++ cqe_cnt); + goto out; + } + + if (time_after(jiffies, end)) { +- ibdev_err(ibdev, +- "failed to poll cqe for free mr and timeout, remain %d cqe.\n", +- cqe_cnt); ++ ibdev_err_ratelimited(ibdev, ++ "failed to poll cqe for free mr and timeout, remain %d cqe.\n", ++ cqe_cnt); + goto out; + } + cqe_cnt -= npolled; +@@ -5061,10 +5054,8 @@ static int hns_roce_v2_set_abs_fields(struct ib_qp *ibqp, + struct hns_roce_dev *hr_dev = to_hr_dev(ibqp->device); + int ret = 0; + +- if (!check_qp_state(cur_state, new_state)) { +- ibdev_err(&hr_dev->ib_dev, "Illegal state for QP!\n"); ++ if (!check_qp_state(cur_state, new_state)) + return -EINVAL; +- } + + if (cur_state == IB_QPS_RESET && new_state == IB_QPS_INIT) { + memset(qpc_mask, 0, hr_dev->caps.qpc_sz); +@@ -5325,7 +5316,7 @@ static int hns_roce_v2_modify_qp(struct ib_qp *ibqp, + /* SW pass context to HW */ + ret = hns_roce_v2_qp_modify(hr_dev, context, qpc_mask, hr_qp); + if (ret) { +- ibdev_err(ibdev, "failed to modify QP, ret = %d.\n", ret); ++ ibdev_err_ratelimited(ibdev, "failed to modify QP, ret = %d.\n", ret); + goto out; + } + +@@ -5463,7 +5454,9 @@ static int hns_roce_v2_query_qp(struct ib_qp *ibqp, struct ib_qp_attr *qp_attr, + + ret = hns_roce_v2_query_qpc(hr_dev, hr_qp->qpn, &context); + if (ret) { +- ibdev_err(ibdev, "failed to query QPC, ret = %d.\n", ret); ++ ibdev_err_ratelimited(ibdev, ++ "failed to query QPC, ret = %d.\n", ++ ret); + ret = -EINVAL; + goto out; + } +@@ -5471,7 +5464,7 @@ static int hns_roce_v2_query_qp(struct ib_qp *ibqp, struct ib_qp_attr *qp_attr, + state = hr_reg_read(&context, QPC_QP_ST); + tmp_qp_state = to_ib_qp_st((enum hns_roce_v2_qp_state)state); + if (tmp_qp_state == -1) { +- ibdev_err(ibdev, "Illegal ib_qp_state\n"); ++ ibdev_err_ratelimited(ibdev, "Illegal ib_qp_state\n"); + ret = -EINVAL; + goto out; + } +@@ -5564,9 +5557,9 @@ static int hns_roce_v2_destroy_qp_common(struct hns_roce_dev *hr_dev, + ret = hns_roce_v2_modify_qp(&hr_qp->ibqp, NULL, 0, + hr_qp->state, IB_QPS_RESET, udata); + if (ret) +- ibdev_err(ibdev, +- "failed to modify QP to RST, ret = %d.\n", +- ret); ++ ibdev_err_ratelimited(ibdev, ++ "failed to modify QP to RST, ret = %d.\n", ++ ret); + } + + send_cq = hr_qp->ibqp.send_cq ? to_hr_cq(hr_qp->ibqp.send_cq) : NULL; +@@ -5609,9 +5602,9 @@ int hns_roce_v2_destroy_qp(struct ib_qp *ibqp, struct ib_udata *udata) + + ret = hns_roce_v2_destroy_qp_common(hr_dev, hr_qp, udata); + if (ret) +- ibdev_err(&hr_dev->ib_dev, +- "failed to destroy QP, QPN = 0x%06lx, ret = %d.\n", +- hr_qp->qpn, ret); ++ ibdev_err_ratelimited(&hr_dev->ib_dev, ++ "failed to destroy QP, QPN = 0x%06lx, ret = %d.\n", ++ hr_qp->qpn, ret); + + hns_roce_qp_destroy(hr_dev, hr_qp, udata); + +@@ -5905,9 +5898,9 @@ static int hns_roce_v2_modify_cq(struct ib_cq *cq, u16 cq_count, u16 cq_period) + HNS_ROCE_CMD_MODIFY_CQC, hr_cq->cqn); + hns_roce_free_cmd_mailbox(hr_dev, mailbox); + if (ret) +- ibdev_err(&hr_dev->ib_dev, +- "failed to process cmd when modifying CQ, ret = %d.\n", +- ret); ++ ibdev_err_ratelimited(&hr_dev->ib_dev, ++ "failed to process cmd when modifying CQ, ret = %d.\n", ++ ret); + + err_out: + if (ret) +@@ -5931,9 +5924,9 @@ static int hns_roce_v2_query_cqc(struct hns_roce_dev *hr_dev, u32 cqn, + ret = hns_roce_cmd_mbox(hr_dev, 0, mailbox->dma, + HNS_ROCE_CMD_QUERY_CQC, cqn); + if (ret) { +- ibdev_err(&hr_dev->ib_dev, +- "failed to process cmd when querying CQ, ret = %d.\n", +- ret); ++ ibdev_err_ratelimited(&hr_dev->ib_dev, ++ "failed to process cmd when querying CQ, ret = %d.\n", ++ ret); + goto err_mailbox; + } + +diff --git a/drivers/infiniband/hw/hns/hns_roce_mr.c b/drivers/infiniband/hw/hns/hns_roce_mr.c +index 846da8c78b8b7..b3f4327d0e64a 100644 +--- a/drivers/infiniband/hw/hns/hns_roce_mr.c ++++ b/drivers/infiniband/hw/hns/hns_roce_mr.c +@@ -138,8 +138,8 @@ static void hns_roce_mr_free(struct hns_roce_dev *hr_dev, struct hns_roce_mr *mr + key_to_hw_index(mr->key) & + (hr_dev->caps.num_mtpts - 1)); + if (ret) +- ibdev_warn(ibdev, "failed to destroy mpt, ret = %d.\n", +- ret); ++ ibdev_warn_ratelimited(ibdev, "failed to destroy mpt, ret = %d.\n", ++ ret); + } + + free_mr_pbl(hr_dev, mr); +diff --git a/drivers/infiniband/hw/hns/hns_roce_srq.c b/drivers/infiniband/hw/hns/hns_roce_srq.c +index c9b8233f4b057..70c06ef65603d 100644 +--- a/drivers/infiniband/hw/hns/hns_roce_srq.c ++++ b/drivers/infiniband/hw/hns/hns_roce_srq.c +@@ -151,8 +151,8 @@ static void free_srqc(struct hns_roce_dev *hr_dev, struct hns_roce_srq *srq) + ret = hns_roce_destroy_hw_ctx(hr_dev, HNS_ROCE_CMD_DESTROY_SRQ, + srq->srqn); + if (ret) +- dev_err(hr_dev->dev, "DESTROY_SRQ failed (%d) for SRQN %06lx\n", +- ret, srq->srqn); ++ dev_err_ratelimited(hr_dev->dev, "DESTROY_SRQ failed (%d) for SRQN %06lx\n", ++ ret, srq->srqn); + + xa_erase_irq(&srq_table->xa, srq->srqn); + +-- +2.43.0 + diff --git a/queue-6.12/rdma-hns-fix-different-dgids-mapping-to-the-same-dip.patch b/queue-6.12/rdma-hns-fix-different-dgids-mapping-to-the-same-dip.patch new file mode 100644 index 00000000000..9ef6eb4056b --- /dev/null +++ b/queue-6.12/rdma-hns-fix-different-dgids-mapping-to-the-same-dip.patch @@ -0,0 +1,312 @@ +From 20d1a147ce90500cca3cb7cb4a0242b01d6f4095 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Tue, 12 Nov 2024 13:55:53 +0800 +Subject: RDMA/hns: Fix different dgids mapping to the same dip_idx + +From: Feng Fang <fangfeng4@huawei.com> + +[ Upstream commit faa62440a5772b40bb7d78bf9e29556a82ecf153 ] + +DIP algorithm requires a one-to-one mapping between dgid and dip_idx. +Currently a queue 'spare_idx' is used to store QPN of QPs that use +DIP algorithm. For a new dgid, use a QPN from spare_idx as dip_idx. +This method lacks a mechanism for deduplicating QPN, which may result +in different dgids sharing the same dip_idx and break the one-to-one +mapping requirement. + +This patch replaces spare_idx with xarray and introduces a refcnt of +a dip_idx to indicate the number of QPs that using this dip_idx. + +The state machine for dip_idx management is implemented as: + +* The entry at an index in xarray is empty -- This indicates that the + corresponding dip_idx hasn't been created. + +* The entry at an index in xarray is not empty but with 0 refcnt -- + This indicates that the corresponding dip_idx has been created but + not used as dip_idx yet. + +* The entry at an index in xarray is not empty and with non-0 refcnt -- + This indicates that the corresponding dip_idx is being used by refcnt + number of DIP QPs. + +Fixes: eb653eda1e91 ("RDMA/hns: Bugfix for incorrect association between dip_idx and dgid") +Fixes: f91696f2f053 ("RDMA/hns: Support congestion control type selection according to the FW") +Signed-off-by: Feng Fang <fangfeng4@huawei.com> +Signed-off-by: Junxian Huang <huangjunxian6@hisilicon.com> +Link: https://patch.msgid.link/20241112055553.3681129-1-huangjunxian6@hisilicon.com +Signed-off-by: Leon Romanovsky <leon@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/infiniband/hw/hns/hns_roce_device.h | 11 +-- + drivers/infiniband/hw/hns/hns_roce_hw_v2.c | 96 +++++++++++++++------ + drivers/infiniband/hw/hns/hns_roce_hw_v2.h | 2 +- + drivers/infiniband/hw/hns/hns_roce_main.c | 2 - + drivers/infiniband/hw/hns/hns_roce_qp.c | 8 +- + 5 files changed, 75 insertions(+), 44 deletions(-) + +diff --git a/drivers/infiniband/hw/hns/hns_roce_device.h b/drivers/infiniband/hw/hns/hns_roce_device.h +index 9b51d5a1533f5..560a1d9de408f 100644 +--- a/drivers/infiniband/hw/hns/hns_roce_device.h ++++ b/drivers/infiniband/hw/hns/hns_roce_device.h +@@ -489,12 +489,6 @@ struct hns_roce_bank { + u32 next; /* Next ID to allocate. */ + }; + +-struct hns_roce_idx_table { +- u32 *spare_idx; +- u32 head; +- u32 tail; +-}; +- + struct hns_roce_qp_table { + struct hns_roce_hem_table qp_table; + struct hns_roce_hem_table irrl_table; +@@ -503,7 +497,7 @@ struct hns_roce_qp_table { + struct mutex scc_mutex; + struct hns_roce_bank bank[HNS_ROCE_QP_BANK_NUM]; + struct mutex bank_mutex; +- struct hns_roce_idx_table idx_table; ++ struct xarray dip_xa; + }; + + struct hns_roce_cq_table { +@@ -658,6 +652,7 @@ struct hns_roce_qp { + u8 tc_mode; + u8 priority; + spinlock_t flush_lock; ++ struct hns_roce_dip *dip; + }; + + struct hns_roce_ib_iboe { +@@ -984,8 +979,6 @@ struct hns_roce_dev { + enum hns_roce_device_state state; + struct list_head qp_list; /* list of all qps on this dev */ + spinlock_t qp_list_lock; /* protect qp_list */ +- struct list_head dip_list; /* list of all dest ips on this dev */ +- spinlock_t dip_list_lock; /* protect dip_list */ + + struct list_head pgdir_list; + struct mutex pgdir_mutex; +diff --git a/drivers/infiniband/hw/hns/hns_roce_hw_v2.c b/drivers/infiniband/hw/hns/hns_roce_hw_v2.c +index 707e96ce222c5..697b17cca02e7 100644 +--- a/drivers/infiniband/hw/hns/hns_roce_hw_v2.c ++++ b/drivers/infiniband/hw/hns/hns_roce_hw_v2.c +@@ -2553,20 +2553,19 @@ static void hns_roce_free_link_table(struct hns_roce_dev *hr_dev) + free_link_table_buf(hr_dev, &priv->ext_llm); + } + +-static void free_dip_list(struct hns_roce_dev *hr_dev) ++static void free_dip_entry(struct hns_roce_dev *hr_dev) + { + struct hns_roce_dip *hr_dip; +- struct hns_roce_dip *tmp; +- unsigned long flags; ++ unsigned long idx; + +- spin_lock_irqsave(&hr_dev->dip_list_lock, flags); ++ xa_lock(&hr_dev->qp_table.dip_xa); + +- list_for_each_entry_safe(hr_dip, tmp, &hr_dev->dip_list, node) { +- list_del(&hr_dip->node); ++ xa_for_each(&hr_dev->qp_table.dip_xa, idx, hr_dip) { ++ __xa_erase(&hr_dev->qp_table.dip_xa, hr_dip->dip_idx); + kfree(hr_dip); + } + +- spin_unlock_irqrestore(&hr_dev->dip_list_lock, flags); ++ xa_unlock(&hr_dev->qp_table.dip_xa); + } + + static struct ib_pd *free_mr_init_pd(struct hns_roce_dev *hr_dev) +@@ -2974,7 +2973,7 @@ static void hns_roce_v2_exit(struct hns_roce_dev *hr_dev) + hns_roce_free_link_table(hr_dev); + + if (hr_dev->pci_dev->revision == PCI_REVISION_ID_HIP09) +- free_dip_list(hr_dev); ++ free_dip_entry(hr_dev); + } + + static int hns_roce_mbox_post(struct hns_roce_dev *hr_dev, +@@ -4694,26 +4693,49 @@ static int modify_qp_rtr_to_rts(struct ib_qp *ibqp, int attr_mask, + return 0; + } + ++static int alloc_dip_entry(struct xarray *dip_xa, u32 qpn) ++{ ++ struct hns_roce_dip *hr_dip; ++ int ret; ++ ++ hr_dip = xa_load(dip_xa, qpn); ++ if (hr_dip) ++ return 0; ++ ++ hr_dip = kzalloc(sizeof(*hr_dip), GFP_KERNEL); ++ if (!hr_dip) ++ return -ENOMEM; ++ ++ ret = xa_err(xa_store(dip_xa, qpn, hr_dip, GFP_KERNEL)); ++ if (ret) ++ kfree(hr_dip); ++ ++ return ret; ++} ++ + static int get_dip_ctx_idx(struct ib_qp *ibqp, const struct ib_qp_attr *attr, + u32 *dip_idx) + { + const struct ib_global_route *grh = rdma_ah_read_grh(&attr->ah_attr); + struct hns_roce_dev *hr_dev = to_hr_dev(ibqp->device); +- u32 *spare_idx = hr_dev->qp_table.idx_table.spare_idx; +- u32 *head = &hr_dev->qp_table.idx_table.head; +- u32 *tail = &hr_dev->qp_table.idx_table.tail; ++ struct xarray *dip_xa = &hr_dev->qp_table.dip_xa; ++ struct hns_roce_qp *hr_qp = to_hr_qp(ibqp); + struct hns_roce_dip *hr_dip; +- unsigned long flags; ++ unsigned long idx; + int ret = 0; + +- spin_lock_irqsave(&hr_dev->dip_list_lock, flags); ++ ret = alloc_dip_entry(dip_xa, ibqp->qp_num); ++ if (ret) ++ return ret; + +- spare_idx[*tail] = ibqp->qp_num; +- *tail = (*tail == hr_dev->caps.num_qps - 1) ? 0 : (*tail + 1); ++ xa_lock(dip_xa); + +- list_for_each_entry(hr_dip, &hr_dev->dip_list, node) { +- if (!memcmp(grh->dgid.raw, hr_dip->dgid, GID_LEN_V2)) { ++ xa_for_each(dip_xa, idx, hr_dip) { ++ if (hr_dip->qp_cnt && ++ !memcmp(grh->dgid.raw, hr_dip->dgid, GID_LEN_V2)) { + *dip_idx = hr_dip->dip_idx; ++ hr_dip->qp_cnt++; ++ hr_qp->dip = hr_dip; + goto out; + } + } +@@ -4721,19 +4743,24 @@ static int get_dip_ctx_idx(struct ib_qp *ibqp, const struct ib_qp_attr *attr, + /* If no dgid is found, a new dip and a mapping between dgid and + * dip_idx will be created. + */ +- hr_dip = kzalloc(sizeof(*hr_dip), GFP_ATOMIC); +- if (!hr_dip) { +- ret = -ENOMEM; +- goto out; ++ xa_for_each(dip_xa, idx, hr_dip) { ++ if (hr_dip->qp_cnt) ++ continue; ++ ++ *dip_idx = idx; ++ memcpy(hr_dip->dgid, grh->dgid.raw, sizeof(grh->dgid.raw)); ++ hr_dip->dip_idx = idx; ++ hr_dip->qp_cnt++; ++ hr_qp->dip = hr_dip; ++ break; + } + +- memcpy(hr_dip->dgid, grh->dgid.raw, sizeof(grh->dgid.raw)); +- hr_dip->dip_idx = *dip_idx = spare_idx[*head]; +- *head = (*head == hr_dev->caps.num_qps - 1) ? 0 : (*head + 1); +- list_add_tail(&hr_dip->node, &hr_dev->dip_list); ++ /* This should never happen. */ ++ if (WARN_ON_ONCE(!hr_qp->dip)) ++ ret = -ENOSPC; + + out: +- spin_unlock_irqrestore(&hr_dev->dip_list_lock, flags); ++ xa_unlock(dip_xa); + return ret; + } + +@@ -5587,6 +5614,20 @@ static int hns_roce_v2_destroy_qp_common(struct hns_roce_dev *hr_dev, + return ret; + } + ++static void put_dip_ctx_idx(struct hns_roce_dev *hr_dev, ++ struct hns_roce_qp *hr_qp) ++{ ++ struct hns_roce_dip *hr_dip = hr_qp->dip; ++ ++ xa_lock(&hr_dev->qp_table.dip_xa); ++ ++ hr_dip->qp_cnt--; ++ if (!hr_dip->qp_cnt) ++ memset(hr_dip->dgid, 0, GID_LEN_V2); ++ ++ xa_unlock(&hr_dev->qp_table.dip_xa); ++} ++ + int hns_roce_v2_destroy_qp(struct ib_qp *ibqp, struct ib_udata *udata) + { + struct hns_roce_dev *hr_dev = to_hr_dev(ibqp->device); +@@ -5600,6 +5641,9 @@ int hns_roce_v2_destroy_qp(struct ib_qp *ibqp, struct ib_udata *udata) + spin_unlock_irqrestore(&hr_qp->flush_lock, flags); + flush_work(&hr_qp->flush_work.work); + ++ if (hr_qp->cong_type == CONG_TYPE_DIP) ++ put_dip_ctx_idx(hr_dev, hr_qp); ++ + ret = hns_roce_v2_destroy_qp_common(hr_dev, hr_qp, udata); + if (ret) + ibdev_err_ratelimited(&hr_dev->ib_dev, +diff --git a/drivers/infiniband/hw/hns/hns_roce_hw_v2.h b/drivers/infiniband/hw/hns/hns_roce_hw_v2.h +index dedb1853e193e..cbdbc9edbce6e 100644 +--- a/drivers/infiniband/hw/hns/hns_roce_hw_v2.h ++++ b/drivers/infiniband/hw/hns/hns_roce_hw_v2.h +@@ -1348,7 +1348,7 @@ struct hns_roce_v2_priv { + struct hns_roce_dip { + u8 dgid[GID_LEN_V2]; + u32 dip_idx; +- struct list_head node; /* all dips are on a list */ ++ u32 qp_cnt; + }; + + struct fmea_ram_ecc { +diff --git a/drivers/infiniband/hw/hns/hns_roce_main.c b/drivers/infiniband/hw/hns/hns_roce_main.c +index 49315f39361de..ae24c81c9812d 100644 +--- a/drivers/infiniband/hw/hns/hns_roce_main.c ++++ b/drivers/infiniband/hw/hns/hns_roce_main.c +@@ -1135,8 +1135,6 @@ int hns_roce_init(struct hns_roce_dev *hr_dev) + + INIT_LIST_HEAD(&hr_dev->qp_list); + spin_lock_init(&hr_dev->qp_list_lock); +- INIT_LIST_HEAD(&hr_dev->dip_list); +- spin_lock_init(&hr_dev->dip_list_lock); + + ret = hns_roce_register_device(hr_dev); + if (ret) +diff --git a/drivers/infiniband/hw/hns/hns_roce_qp.c b/drivers/infiniband/hw/hns/hns_roce_qp.c +index 2ad03ecdbf8ec..9e2e76c594063 100644 +--- a/drivers/infiniband/hw/hns/hns_roce_qp.c ++++ b/drivers/infiniband/hw/hns/hns_roce_qp.c +@@ -1573,14 +1573,10 @@ int hns_roce_init_qp_table(struct hns_roce_dev *hr_dev) + unsigned int reserved_from_bot; + unsigned int i; + +- qp_table->idx_table.spare_idx = kcalloc(hr_dev->caps.num_qps, +- sizeof(u32), GFP_KERNEL); +- if (!qp_table->idx_table.spare_idx) +- return -ENOMEM; +- + mutex_init(&qp_table->scc_mutex); + mutex_init(&qp_table->bank_mutex); + xa_init(&hr_dev->qp_table_xa); ++ xa_init(&qp_table->dip_xa); + + reserved_from_bot = hr_dev->caps.reserved_qps; + +@@ -1605,7 +1601,7 @@ void hns_roce_cleanup_qp_table(struct hns_roce_dev *hr_dev) + + for (i = 0; i < HNS_ROCE_QP_BANK_NUM; i++) + ida_destroy(&hr_dev->qp_table.bank[i].ida); ++ xa_destroy(&hr_dev->qp_table.dip_xa); + mutex_destroy(&hr_dev->qp_table.bank_mutex); + mutex_destroy(&hr_dev->qp_table.scc_mutex); +- kfree(hr_dev->qp_table.idx_table.spare_idx); + } +-- +2.43.0 + diff --git a/queue-6.12/rdma-hns-fix-flush-cqe-error-when-racing-with-destro.patch b/queue-6.12/rdma-hns-fix-flush-cqe-error-when-racing-with-destro.patch new file mode 100644 index 00000000000..dee0fab6791 --- /dev/null +++ b/queue-6.12/rdma-hns-fix-flush-cqe-error-when-racing-with-destro.patch @@ -0,0 +1,119 @@ +From e6fae7c041b4472102eca9a2ed8f4eef0fef0436 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Thu, 24 Oct 2024 20:39:57 +0800 +Subject: RDMA/hns: Fix flush cqe error when racing with destroy qp + +From: wenglianfa <wenglianfa@huawei.com> + +[ Upstream commit 377a2097705b915325a67e4d44f9f2844e567809 ] + +QP needs to be modified to IB_QPS_ERROR to trigger HW flush cqe. But +when this process races with destroy qp, the destroy-qp process may +modify the QP to IB_QPS_RESET first. In this case flush cqe will fail +since it is invalid to modify qp from IB_QPS_RESET to IB_QPS_ERROR. + +Add lock and bit flag to make sure pending flush cqe work is completed +first and no more new works will be added. + +Fixes: ffd541d45726 ("RDMA/hns: Add the workqueue framework for flush cqe handler") +Signed-off-by: wenglianfa <wenglianfa@huawei.com> +Signed-off-by: Junxian Huang <huangjunxian6@hisilicon.com> +Link: https://patch.msgid.link/20241024124000.2931869-3-huangjunxian6@hisilicon.com +Reviewed-by: Zhu Yanjun <yanjun.zhu@linux.dev> +Signed-off-by: Leon Romanovsky <leon@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/infiniband/hw/hns/hns_roce_device.h | 2 ++ + drivers/infiniband/hw/hns/hns_roce_hw_v2.c | 7 +++++++ + drivers/infiniband/hw/hns/hns_roce_qp.c | 15 +++++++++++++-- + 3 files changed, 22 insertions(+), 2 deletions(-) + +diff --git a/drivers/infiniband/hw/hns/hns_roce_device.h b/drivers/infiniband/hw/hns/hns_roce_device.h +index 73c78005901e6..9b51d5a1533f5 100644 +--- a/drivers/infiniband/hw/hns/hns_roce_device.h ++++ b/drivers/infiniband/hw/hns/hns_roce_device.h +@@ -593,6 +593,7 @@ struct hns_roce_dev; + + enum { + HNS_ROCE_FLUSH_FLAG = 0, ++ HNS_ROCE_STOP_FLUSH_FLAG = 1, + }; + + struct hns_roce_work { +@@ -656,6 +657,7 @@ struct hns_roce_qp { + enum hns_roce_cong_type cong_type; + u8 tc_mode; + u8 priority; ++ spinlock_t flush_lock; + }; + + struct hns_roce_ib_iboe { +diff --git a/drivers/infiniband/hw/hns/hns_roce_hw_v2.c b/drivers/infiniband/hw/hns/hns_roce_hw_v2.c +index bbdeb02102e87..4c3bc1f6a183c 100644 +--- a/drivers/infiniband/hw/hns/hns_roce_hw_v2.c ++++ b/drivers/infiniband/hw/hns/hns_roce_hw_v2.c +@@ -5598,8 +5598,15 @@ int hns_roce_v2_destroy_qp(struct ib_qp *ibqp, struct ib_udata *udata) + { + struct hns_roce_dev *hr_dev = to_hr_dev(ibqp->device); + struct hns_roce_qp *hr_qp = to_hr_qp(ibqp); ++ unsigned long flags; + int ret; + ++ /* Make sure flush_cqe() is completed */ ++ spin_lock_irqsave(&hr_qp->flush_lock, flags); ++ set_bit(HNS_ROCE_STOP_FLUSH_FLAG, &hr_qp->flush_flag); ++ spin_unlock_irqrestore(&hr_qp->flush_lock, flags); ++ flush_work(&hr_qp->flush_work.work); ++ + ret = hns_roce_v2_destroy_qp_common(hr_dev, hr_qp, udata); + if (ret) + ibdev_err(&hr_dev->ib_dev, +diff --git a/drivers/infiniband/hw/hns/hns_roce_qp.c b/drivers/infiniband/hw/hns/hns_roce_qp.c +index dcaa370d4a265..2ad03ecdbf8ec 100644 +--- a/drivers/infiniband/hw/hns/hns_roce_qp.c ++++ b/drivers/infiniband/hw/hns/hns_roce_qp.c +@@ -90,11 +90,18 @@ static void flush_work_handle(struct work_struct *work) + void init_flush_work(struct hns_roce_dev *hr_dev, struct hns_roce_qp *hr_qp) + { + struct hns_roce_work *flush_work = &hr_qp->flush_work; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&hr_qp->flush_lock, flags); ++ /* Exit directly after destroy_qp() */ ++ if (test_bit(HNS_ROCE_STOP_FLUSH_FLAG, &hr_qp->flush_flag)) { ++ spin_unlock_irqrestore(&hr_qp->flush_lock, flags); ++ return; ++ } + +- flush_work->hr_dev = hr_dev; +- INIT_WORK(&flush_work->work, flush_work_handle); + refcount_inc(&hr_qp->refcount); + queue_work(hr_dev->irq_workq, &flush_work->work); ++ spin_unlock_irqrestore(&hr_qp->flush_lock, flags); + } + + void flush_cqe(struct hns_roce_dev *dev, struct hns_roce_qp *qp) +@@ -1140,6 +1147,7 @@ static int hns_roce_create_qp_common(struct hns_roce_dev *hr_dev, + struct ib_udata *udata, + struct hns_roce_qp *hr_qp) + { ++ struct hns_roce_work *flush_work = &hr_qp->flush_work; + struct hns_roce_ib_create_qp_resp resp = {}; + struct ib_device *ibdev = &hr_dev->ib_dev; + struct hns_roce_ib_create_qp ucmd = {}; +@@ -1148,9 +1156,12 @@ static int hns_roce_create_qp_common(struct hns_roce_dev *hr_dev, + mutex_init(&hr_qp->mutex); + spin_lock_init(&hr_qp->sq.lock); + spin_lock_init(&hr_qp->rq.lock); ++ spin_lock_init(&hr_qp->flush_lock); + + hr_qp->state = IB_QPS_RESET; + hr_qp->flush_flag = 0; ++ flush_work->hr_dev = hr_dev; ++ INIT_WORK(&flush_work->work, flush_work_handle); + + if (init_attr->create_flags) + return -EOPNOTSUPP; +-- +2.43.0 + diff --git a/queue-6.12/rdma-hns-fix-null-pointer-derefernce-in-hns_roce_map.patch b/queue-6.12/rdma-hns-fix-null-pointer-derefernce-in-hns_roce_map.patch new file mode 100644 index 00000000000..f8f3293e4d6 --- /dev/null +++ b/queue-6.12/rdma-hns-fix-null-pointer-derefernce-in-hns_roce_map.patch @@ -0,0 +1,57 @@ +From b20f6e90b3dbe3c637e8730dbfc211c3a870dd49 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Fri, 8 Nov 2024 15:57:43 +0800 +Subject: RDMA/hns: Fix NULL pointer derefernce in hns_roce_map_mr_sg() + +From: Junxian Huang <huangjunxian6@hisilicon.com> + +[ Upstream commit 6b526d17eed850352d880b93b9bf20b93006bd92 ] + +ib_map_mr_sg() allows ULPs to specify NULL as the sg_offset argument. +The driver needs to check whether it is a NULL pointer before +dereferencing it. + +Fixes: d387d4b54eb8 ("RDMA/hns: Fix missing pagesize and alignment check in FRMR") +Signed-off-by: Junxian Huang <huangjunxian6@hisilicon.com> +Link: https://patch.msgid.link/20241108075743.2652258-3-huangjunxian6@hisilicon.com +Signed-off-by: Leon Romanovsky <leon@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/infiniband/hw/hns/hns_roce_mr.c | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +diff --git a/drivers/infiniband/hw/hns/hns_roce_mr.c b/drivers/infiniband/hw/hns/hns_roce_mr.c +index b3f4327d0e64a..bf30b3a65a9ba 100644 +--- a/drivers/infiniband/hw/hns/hns_roce_mr.c ++++ b/drivers/infiniband/hw/hns/hns_roce_mr.c +@@ -435,15 +435,16 @@ static int hns_roce_set_page(struct ib_mr *ibmr, u64 addr) + } + + int hns_roce_map_mr_sg(struct ib_mr *ibmr, struct scatterlist *sg, int sg_nents, +- unsigned int *sg_offset) ++ unsigned int *sg_offset_p) + { ++ unsigned int sg_offset = sg_offset_p ? *sg_offset_p : 0; + struct hns_roce_dev *hr_dev = to_hr_dev(ibmr->device); + struct ib_device *ibdev = &hr_dev->ib_dev; + struct hns_roce_mr *mr = to_hr_mr(ibmr); + struct hns_roce_mtr *mtr = &mr->pbl_mtr; + int ret, sg_num = 0; + +- if (!IS_ALIGNED(*sg_offset, HNS_ROCE_FRMR_ALIGN_SIZE) || ++ if (!IS_ALIGNED(sg_offset, HNS_ROCE_FRMR_ALIGN_SIZE) || + ibmr->page_size < HNS_HW_PAGE_SIZE || + ibmr->page_size > HNS_HW_MAX_PAGE_SIZE) + return sg_num; +@@ -454,7 +455,7 @@ int hns_roce_map_mr_sg(struct ib_mr *ibmr, struct scatterlist *sg, int sg_nents, + if (!mr->page_list) + return sg_num; + +- sg_num = ib_sg_to_pages(ibmr, sg, sg_nents, sg_offset, hns_roce_set_page); ++ sg_num = ib_sg_to_pages(ibmr, sg, sg_nents, sg_offset_p, hns_roce_set_page); + if (sg_num < 1) { + ibdev_err(ibdev, "failed to store sg pages %u %u, cnt = %d.\n", + mr->npages, mr->pbl_mtr.hem_cfg.buf_pg_count, sg_num); +-- +2.43.0 + diff --git a/queue-6.12/rdma-hns-fix-out-of-order-issue-of-requester-when-se.patch b/queue-6.12/rdma-hns-fix-out-of-order-issue-of-requester-when-se.patch new file mode 100644 index 00000000000..20448d18c74 --- /dev/null +++ b/queue-6.12/rdma-hns-fix-out-of-order-issue-of-requester-when-se.patch @@ -0,0 +1,58 @@ +From 101e10ea34e9774d20a3b0bdb4ee26f615049e6f Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Fri, 8 Nov 2024 15:57:42 +0800 +Subject: RDMA/hns: Fix out-of-order issue of requester when setting FENCE + +From: Junxian Huang <huangjunxian6@hisilicon.com> + +[ Upstream commit 5dbcb1c1900f45182b5651c89257c272f1f3ead7 ] + +The FENCE indicator in hns WQE doesn't ensure that response data from +a previous Read/Atomic operation has been written to the requester's +memory before the subsequent Send/Write operation is processed. This +may result in the subsequent Send/Write operation accessing the original +data in memory instead of the expected response data. + +Unlike FENCE, the SO (Strong Order) indicator blocks the subsequent +operation until the previous response data is written to memory and a +bresp is returned. Set the SO indicator instead of FENCE to maintain +strict order. + +Fixes: 9a4435375cd1 ("IB/hns: Add driver files for hns RoCE driver") +Signed-off-by: Junxian Huang <huangjunxian6@hisilicon.com> +Link: https://patch.msgid.link/20241108075743.2652258-2-huangjunxian6@hisilicon.com +Signed-off-by: Leon Romanovsky <leon@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/infiniband/hw/hns/hns_roce_hw_v2.c | 2 +- + drivers/infiniband/hw/hns/hns_roce_hw_v2.h | 1 + + 2 files changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/infiniband/hw/hns/hns_roce_hw_v2.c b/drivers/infiniband/hw/hns/hns_roce_hw_v2.c +index d1c075fb0ad89..707e96ce222c5 100644 +--- a/drivers/infiniband/hw/hns/hns_roce_hw_v2.c ++++ b/drivers/infiniband/hw/hns/hns_roce_hw_v2.c +@@ -575,7 +575,7 @@ static inline int set_rc_wqe(struct hns_roce_qp *qp, + if (WARN_ON(ret)) + return ret; + +- hr_reg_write(rc_sq_wqe, RC_SEND_WQE_FENCE, ++ hr_reg_write(rc_sq_wqe, RC_SEND_WQE_SO, + (wr->send_flags & IB_SEND_FENCE) ? 1 : 0); + + hr_reg_write(rc_sq_wqe, RC_SEND_WQE_SE, +diff --git a/drivers/infiniband/hw/hns/hns_roce_hw_v2.h b/drivers/infiniband/hw/hns/hns_roce_hw_v2.h +index 3b3c6259ace0e..dedb1853e193e 100644 +--- a/drivers/infiniband/hw/hns/hns_roce_hw_v2.h ++++ b/drivers/infiniband/hw/hns/hns_roce_hw_v2.h +@@ -924,6 +924,7 @@ struct hns_roce_v2_rc_send_wqe { + #define RC_SEND_WQE_OWNER RC_SEND_WQE_FIELD_LOC(7, 7) + #define RC_SEND_WQE_CQE RC_SEND_WQE_FIELD_LOC(8, 8) + #define RC_SEND_WQE_FENCE RC_SEND_WQE_FIELD_LOC(9, 9) ++#define RC_SEND_WQE_SO RC_SEND_WQE_FIELD_LOC(10, 10) + #define RC_SEND_WQE_SE RC_SEND_WQE_FIELD_LOC(11, 11) + #define RC_SEND_WQE_INLINE RC_SEND_WQE_FIELD_LOC(12, 12) + #define RC_SEND_WQE_WQE_INDEX RC_SEND_WQE_FIELD_LOC(30, 15) +-- +2.43.0 + diff --git a/queue-6.12/rdma-hns-modify-debugfs-name.patch b/queue-6.12/rdma-hns-modify-debugfs-name.patch new file mode 100644 index 00000000000..6f2c9ebbeec --- /dev/null +++ b/queue-6.12/rdma-hns-modify-debugfs-name.patch @@ -0,0 +1,50 @@ +From 899feb32ce5208ef3cf27c91b758d7bc7a36f30b Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Thu, 24 Oct 2024 20:39:58 +0800 +Subject: RDMA/hns: Modify debugfs name + +From: Yuyu Li <liyuyu6@huawei.com> + +[ Upstream commit 370a9351bf84afc5a56a3f02ba3805bbfcb53c32 ] + +The sub-directory of hns_roce debugfs is named after the device's +kernel name currently, but it will be inconvenient to use when +the device is renamed. + +Modify the name to pci name as users can always easily find the +correspondence between an RDMA device and its pci name. + +Fixes: eb7854d63db5 ("RDMA/hns: Support SW stats with debugfs") +Signed-off-by: Yuyu Li <liyuyu6@huawei.com> +Signed-off-by: Junxian Huang <huangjunxian6@hisilicon.com> +Link: https://patch.msgid.link/20241024124000.2931869-4-huangjunxian6@hisilicon.com +Signed-off-by: Leon Romanovsky <leon@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/infiniband/hw/hns/hns_roce_debugfs.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/infiniband/hw/hns/hns_roce_debugfs.c b/drivers/infiniband/hw/hns/hns_roce_debugfs.c +index e8febb40f6450..b869cdc541189 100644 +--- a/drivers/infiniband/hw/hns/hns_roce_debugfs.c ++++ b/drivers/infiniband/hw/hns/hns_roce_debugfs.c +@@ -5,6 +5,7 @@ + + #include <linux/debugfs.h> + #include <linux/device.h> ++#include <linux/pci.h> + + #include "hns_roce_device.h" + +@@ -86,7 +87,7 @@ void hns_roce_register_debugfs(struct hns_roce_dev *hr_dev) + { + struct hns_roce_dev_debugfs *dbgfs = &hr_dev->dbgfs; + +- dbgfs->root = debugfs_create_dir(dev_name(&hr_dev->ib_dev.dev), ++ dbgfs->root = debugfs_create_dir(pci_name(hr_dev->pci_dev), + hns_roce_dbgfs_root); + + create_sw_stat_debugfs(hr_dev, dbgfs->root); +-- +2.43.0 + diff --git a/queue-6.12/rdma-hns-use-dev_-printings-in-hem-code-instead-of-i.patch b/queue-6.12/rdma-hns-use-dev_-printings-in-hem-code-instead-of-i.patch new file mode 100644 index 00000000000..5fa3a2182f7 --- /dev/null +++ b/queue-6.12/rdma-hns-use-dev_-printings-in-hem-code-instead-of-i.patch @@ -0,0 +1,182 @@ +From 919758749bede72df7d1ed16ba7f5e6fba4d33a5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Thu, 24 Oct 2024 20:39:59 +0800 +Subject: RDMA/hns: Use dev_* printings in hem code instead of ibdev_* + +From: Junxian Huang <huangjunxian6@hisilicon.com> + +[ Upstream commit d81fb6511abf18591befaa5f4a972ffc838690ec ] + +The hem code is executed before ib_dev is registered, so use dev_* +printing instead of ibdev_* to avoid log like this: + +(null): set HEM address to HW failed! + +Fixes: 2f49de21f3e9 ("RDMA/hns: Optimize mhop get flow for multi-hop addressing") +Signed-off-by: Junxian Huang <huangjunxian6@hisilicon.com> +Link: https://patch.msgid.link/20241024124000.2931869-5-huangjunxian6@hisilicon.com +Signed-off-by: Leon Romanovsky <leon@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/infiniband/hw/hns/hns_roce_hem.c | 44 ++++++++++++------------ + 1 file changed, 22 insertions(+), 22 deletions(-) + +diff --git a/drivers/infiniband/hw/hns/hns_roce_hem.c b/drivers/infiniband/hw/hns/hns_roce_hem.c +index c7c167e2a0451..ee5d2c1bb5ca0 100644 +--- a/drivers/infiniband/hw/hns/hns_roce_hem.c ++++ b/drivers/infiniband/hw/hns/hns_roce_hem.c +@@ -300,7 +300,7 @@ static int calc_hem_config(struct hns_roce_dev *hr_dev, + struct hns_roce_hem_mhop *mhop, + struct hns_roce_hem_index *index) + { +- struct ib_device *ibdev = &hr_dev->ib_dev; ++ struct device *dev = hr_dev->dev; + unsigned long mhop_obj = obj; + u32 l0_idx, l1_idx, l2_idx; + u32 chunk_ba_num; +@@ -331,14 +331,14 @@ static int calc_hem_config(struct hns_roce_dev *hr_dev, + index->buf = l0_idx; + break; + default: +- ibdev_err(ibdev, "table %u not support mhop.hop_num = %u!\n", +- table->type, mhop->hop_num); ++ dev_err(dev, "table %u not support mhop.hop_num = %u!\n", ++ table->type, mhop->hop_num); + return -EINVAL; + } + + if (unlikely(index->buf >= table->num_hem)) { +- ibdev_err(ibdev, "table %u exceed hem limt idx %llu, max %lu!\n", +- table->type, index->buf, table->num_hem); ++ dev_err(dev, "table %u exceed hem limt idx %llu, max %lu!\n", ++ table->type, index->buf, table->num_hem); + return -EINVAL; + } + +@@ -448,14 +448,14 @@ static int set_mhop_hem(struct hns_roce_dev *hr_dev, + struct hns_roce_hem_mhop *mhop, + struct hns_roce_hem_index *index) + { +- struct ib_device *ibdev = &hr_dev->ib_dev; ++ struct device *dev = hr_dev->dev; + u32 step_idx; + int ret = 0; + + if (index->inited & HEM_INDEX_L0) { + ret = hr_dev->hw->set_hem(hr_dev, table, obj, 0); + if (ret) { +- ibdev_err(ibdev, "set HEM step 0 failed!\n"); ++ dev_err(dev, "set HEM step 0 failed!\n"); + goto out; + } + } +@@ -463,7 +463,7 @@ static int set_mhop_hem(struct hns_roce_dev *hr_dev, + if (index->inited & HEM_INDEX_L1) { + ret = hr_dev->hw->set_hem(hr_dev, table, obj, 1); + if (ret) { +- ibdev_err(ibdev, "set HEM step 1 failed!\n"); ++ dev_err(dev, "set HEM step 1 failed!\n"); + goto out; + } + } +@@ -475,7 +475,7 @@ static int set_mhop_hem(struct hns_roce_dev *hr_dev, + step_idx = mhop->hop_num; + ret = hr_dev->hw->set_hem(hr_dev, table, obj, step_idx); + if (ret) +- ibdev_err(ibdev, "set HEM step last failed!\n"); ++ dev_err(dev, "set HEM step last failed!\n"); + } + out: + return ret; +@@ -485,14 +485,14 @@ static int hns_roce_table_mhop_get(struct hns_roce_dev *hr_dev, + struct hns_roce_hem_table *table, + unsigned long obj) + { +- struct ib_device *ibdev = &hr_dev->ib_dev; + struct hns_roce_hem_index index = {}; + struct hns_roce_hem_mhop mhop = {}; ++ struct device *dev = hr_dev->dev; + int ret; + + ret = calc_hem_config(hr_dev, table, obj, &mhop, &index); + if (ret) { +- ibdev_err(ibdev, "calc hem config failed!\n"); ++ dev_err(dev, "calc hem config failed!\n"); + return ret; + } + +@@ -504,7 +504,7 @@ static int hns_roce_table_mhop_get(struct hns_roce_dev *hr_dev, + + ret = alloc_mhop_hem(hr_dev, table, &mhop, &index); + if (ret) { +- ibdev_err(ibdev, "alloc mhop hem failed!\n"); ++ dev_err(dev, "alloc mhop hem failed!\n"); + goto out; + } + +@@ -512,7 +512,7 @@ static int hns_roce_table_mhop_get(struct hns_roce_dev *hr_dev, + if (table->type < HEM_TYPE_MTT) { + ret = set_mhop_hem(hr_dev, table, obj, &mhop, &index); + if (ret) { +- ibdev_err(ibdev, "set HEM address to HW failed!\n"); ++ dev_err(dev, "set HEM address to HW failed!\n"); + goto err_alloc; + } + } +@@ -575,7 +575,7 @@ static void clear_mhop_hem(struct hns_roce_dev *hr_dev, + struct hns_roce_hem_mhop *mhop, + struct hns_roce_hem_index *index) + { +- struct ib_device *ibdev = &hr_dev->ib_dev; ++ struct device *dev = hr_dev->dev; + u32 hop_num = mhop->hop_num; + u32 chunk_ba_num; + u32 step_idx; +@@ -605,21 +605,21 @@ static void clear_mhop_hem(struct hns_roce_dev *hr_dev, + + ret = hr_dev->hw->clear_hem(hr_dev, table, obj, step_idx); + if (ret) +- ibdev_warn(ibdev, "failed to clear hop%u HEM, ret = %d.\n", +- hop_num, ret); ++ dev_warn(dev, "failed to clear hop%u HEM, ret = %d.\n", ++ hop_num, ret); + + if (index->inited & HEM_INDEX_L1) { + ret = hr_dev->hw->clear_hem(hr_dev, table, obj, 1); + if (ret) +- ibdev_warn(ibdev, "failed to clear HEM step 1, ret = %d.\n", +- ret); ++ dev_warn(dev, "failed to clear HEM step 1, ret = %d.\n", ++ ret); + } + + if (index->inited & HEM_INDEX_L0) { + ret = hr_dev->hw->clear_hem(hr_dev, table, obj, 0); + if (ret) +- ibdev_warn(ibdev, "failed to clear HEM step 0, ret = %d.\n", +- ret); ++ dev_warn(dev, "failed to clear HEM step 0, ret = %d.\n", ++ ret); + } + } + } +@@ -629,14 +629,14 @@ static void hns_roce_table_mhop_put(struct hns_roce_dev *hr_dev, + unsigned long obj, + int check_refcount) + { +- struct ib_device *ibdev = &hr_dev->ib_dev; + struct hns_roce_hem_index index = {}; + struct hns_roce_hem_mhop mhop = {}; ++ struct device *dev = hr_dev->dev; + int ret; + + ret = calc_hem_config(hr_dev, table, obj, &mhop, &index); + if (ret) { +- ibdev_err(ibdev, "calc hem config failed!\n"); ++ dev_err(dev, "calc hem config failed!\n"); + return; + } + +-- +2.43.0 + diff --git a/queue-6.12/rdma-mlx5-call-dev_put-after-the-blocking-notifier.patch b/queue-6.12/rdma-mlx5-call-dev_put-after-the-blocking-notifier.patch new file mode 100644 index 00000000000..3965f3898d8 --- /dev/null +++ b/queue-6.12/rdma-mlx5-call-dev_put-after-the-blocking-notifier.patch @@ -0,0 +1,49 @@ +From 53ab5e27471f0ebcaab3276d4219ca99709a1b90 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Thu, 31 Oct 2024 15:36:50 +0200 +Subject: RDMA/mlx5: Call dev_put() after the blocking notifier + +From: Chiara Meiohas <cmeiohas@nvidia.com> + +[ Upstream commit 6d9c7b272966f13ebbf39687620f395d97f4d15d ] + +Move dev_put() call to occur directly after the blocking +notifier, instead of within the event handler. + +Fixes: 8d159eb2117b ("RDMA/mlx5: Use IB set_netdev and get_netdev functions") +Signed-off-by: Chiara Meiohas <cmeiohas@nvidia.com> +Link: https://patch.msgid.link/342ff94b3dcbb07da1c7dab862a73933d604b717.1730381292.git.leon@kernel.org +Signed-off-by: Leon Romanovsky <leon@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/infiniband/hw/mlx5/main.c | 1 - + drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c | 1 + + 2 files changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/infiniband/hw/mlx5/main.c b/drivers/infiniband/hw/mlx5/main.c +index 4999239c8f413..32e57cc343361 100644 +--- a/drivers/infiniband/hw/mlx5/main.c ++++ b/drivers/infiniband/hw/mlx5/main.c +@@ -3234,7 +3234,6 @@ static int lag_event(struct notifier_block *nb, unsigned long event, void *data) + } + err = ib_device_set_netdev(&dev->ib_dev, ndev, + portnum + 1); +- dev_put(ndev); + if (err) + return err; + /* Rescan gids after new netdev assignment */ +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c b/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c +index 8577db3308cc5..d661267d98ffc 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c +@@ -516,6 +516,7 @@ void mlx5_modify_lag(struct mlx5_lag *ldev, + blocking_notifier_call_chain(&dev0->priv.lag_nh, + MLX5_DRIVER_EVENT_ACTIVE_BACKUP_LAG_CHANGE_LOWERSTATE, + ndev); ++ dev_put(ndev); + } + } + +-- +2.43.0 + diff --git a/queue-6.12/rdma-mlx5-ensure-active-slave-attachment-to-the-bond.patch b/queue-6.12/rdma-mlx5-ensure-active-slave-attachment-to-the-bond.patch new file mode 100644 index 00000000000..9659e1cece2 --- /dev/null +++ b/queue-6.12/rdma-mlx5-ensure-active-slave-attachment-to-the-bond.patch @@ -0,0 +1,126 @@ +From be00f2a1e6ba593a20a6eb1598433c3c1be0ae70 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Thu, 31 Oct 2024 15:36:52 +0200 +Subject: RDMA/mlx5: Ensure active slave attachment to the bond IB device + +From: Chiara Meiohas <cmeiohas@nvidia.com> + +[ Upstream commit 0bd2c61df95321e1ec123017cd8657360d15a24e ] + +Fix a race condition when creating a lag bond in active backup +mode where after the bond creation the backup slave was +attached to the IB device, instead of the active slave. +This caused stale entries in the GID table, as the gid updating +mechanism relies on ib_device_get_netdev(), which would return +the backup slave. + +Send an MLX5_DRIVER_EVENT_ACTIVE_BACKUP_LAG_CHANGE_LOWERSTATE +event when activating the lag, additionally to when modifying +the lag. This ensures that eventually the active netdevice is +stored in the bond IB device. +When handling this event remove the GIDs of the previously +attached netdevice in this port and rescan the GIDs of the +newly attached netdevice. + +This ensures that eventually the active slave netdevice is +correctly stored in the IB device port. While there might be +a brief moment where the backup slave GIDs appear in the GID +table, it will eventually stabilize with the correct GIDs +(of the bond and the active slave). + +Fixes: 8d159eb2117b ("RDMA/mlx5: Use IB set_netdev and get_netdev functions") +Signed-off-by: Chiara Meiohas <cmeiohas@nvidia.com> +Link: https://patch.msgid.link/91fc2cb24f63add266a528c1c702668a80416d9f.1730381292.git.leon@kernel.org +Signed-off-by: Leon Romanovsky <leon@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/infiniband/hw/mlx5/main.c | 28 ++++++++++++------- + .../net/ethernet/mellanox/mlx5/core/lag/lag.c | 11 ++++++++ + 2 files changed, 29 insertions(+), 10 deletions(-) + +diff --git a/drivers/infiniband/hw/mlx5/main.c b/drivers/infiniband/hw/mlx5/main.c +index 32e57cc343361..5fef9288699c6 100644 +--- a/drivers/infiniband/hw/mlx5/main.c ++++ b/drivers/infiniband/hw/mlx5/main.c +@@ -3211,12 +3211,14 @@ static int lag_event(struct notifier_block *nb, unsigned long event, void *data) + struct mlx5_ib_dev *dev = container_of(nb, struct mlx5_ib_dev, + lag_events); + struct mlx5_core_dev *mdev = dev->mdev; ++ struct ib_device *ibdev = &dev->ib_dev; ++ struct net_device *old_ndev = NULL; + struct mlx5_ib_port *port; + struct net_device *ndev; +- int i, err; +- int portnum; ++ u32 portnum = 0; ++ int ret = 0; ++ int i; + +- portnum = 0; + switch (event) { + case MLX5_DRIVER_EVENT_ACTIVE_BACKUP_LAG_CHANGE_LOWERSTATE: + ndev = data; +@@ -3232,18 +3234,24 @@ static int lag_event(struct notifier_block *nb, unsigned long event, void *data) + } + } + } +- err = ib_device_set_netdev(&dev->ib_dev, ndev, +- portnum + 1); +- if (err) +- return err; +- /* Rescan gids after new netdev assignment */ +- rdma_roce_rescan_device(&dev->ib_dev); ++ old_ndev = ib_device_get_netdev(ibdev, portnum + 1); ++ ret = ib_device_set_netdev(ibdev, ndev, portnum + 1); ++ if (ret) ++ goto out; ++ ++ if (old_ndev) ++ roce_del_all_netdev_gids(ibdev, portnum + 1, ++ old_ndev); ++ rdma_roce_rescan_port(ibdev, portnum + 1); + } + break; + default: + return NOTIFY_DONE; + } +- return NOTIFY_OK; ++ ++out: ++ dev_put(old_ndev); ++ return notifier_from_errno(ret); + } + + static void mlx5e_lag_event_register(struct mlx5_ib_dev *dev) +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c b/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c +index d661267d98ffc..7f68468c2e759 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c +@@ -919,6 +919,7 @@ static void mlx5_do_bond(struct mlx5_lag *ldev) + { + struct mlx5_core_dev *dev0 = ldev->pf[MLX5_LAG_P1].dev; + struct lag_tracker tracker = { }; ++ struct net_device *ndev; + bool do_bond, roce_lag; + int err; + int i; +@@ -982,6 +983,16 @@ static void mlx5_do_bond(struct mlx5_lag *ldev) + return; + } + } ++ if (tracker.tx_type == NETDEV_LAG_TX_TYPE_ACTIVEBACKUP) { ++ ndev = mlx5_lag_active_backup_get_netdev(dev0); ++ /** Only sriov and roce lag should have tracker->TX_type ++ * set so no need to check the mode ++ */ ++ blocking_notifier_call_chain(&dev0->priv.lag_nh, ++ MLX5_DRIVER_EVENT_ACTIVE_BACKUP_LAG_CHANGE_LOWERSTATE, ++ ndev); ++ dev_put(ndev); ++ } + } else if (mlx5_lag_should_modify_lag(ldev, do_bond)) { + mlx5_modify_lag(ldev, &tracker); + } else if (mlx5_lag_should_disable_lag(ldev, do_bond)) { +-- +2.43.0 + diff --git a/queue-6.12/rdma-mlx5-move-events-notifier-registration-to-be-af.patch b/queue-6.12/rdma-mlx5-move-events-notifier-registration-to-be-af.patch new file mode 100644 index 00000000000..ef8f9bb273d --- /dev/null +++ b/queue-6.12/rdma-mlx5-move-events-notifier-registration-to-be-af.patch @@ -0,0 +1,194 @@ +From 7f0193087712f5c66447a364081f77a315169adf Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Wed, 13 Nov 2024 13:23:19 +0200 +Subject: RDMA/mlx5: Move events notifier registration to be after device + registration + +From: Patrisious Haddad <phaddad@nvidia.com> + +[ Upstream commit ede132a5cf559f3ab35a4c28bac4f4a6c20334d8 ] + +Move pkey change work initialization and cleanup from device resources +stage to notifier stage, since this is the stage which handles this work +events. + +Fix a race between the device deregistration and pkey change work by moving +MLX5_IB_STAGE_DEVICE_NOTIFIER to be after MLX5_IB_STAGE_IB_REG in order to +ensure that the notifier is deregistered before the device during cleanup. +Which ensures there are no works that are being executed after the +device has already unregistered which can cause the panic below. + +BUG: kernel NULL pointer dereference, address: 0000000000000000 +PGD 0 P4D 0 +Oops: 0000 [#1] PREEMPT SMP PTI +CPU: 1 PID: 630071 Comm: kworker/1:2 Kdump: loaded Tainted: G W OE --------- --- 5.14.0-162.6.1.el9_1.x86_64 #1 +Hardware name: Microsoft Corporation Virtual Machine/Virtual Machine, BIOS 090008 02/27/2023 +Workqueue: events pkey_change_handler [mlx5_ib] +RIP: 0010:setup_qp+0x38/0x1f0 [mlx5_ib] +Code: ee 41 54 45 31 e4 55 89 f5 53 48 89 fb 48 83 ec 20 8b 77 08 65 48 8b 04 25 28 00 00 00 48 89 44 24 18 48 8b 07 48 8d 4c 24 16 <4c> 8b 38 49 8b 87 80 0b 00 00 4c 89 ff 48 8b 80 08 05 00 00 8b 40 +RSP: 0018:ffffbcc54068be20 EFLAGS: 00010282 +RAX: 0000000000000000 RBX: ffff954054494128 RCX: ffffbcc54068be36 +RDX: ffff954004934000 RSI: 0000000000000001 RDI: ffff954054494128 +RBP: 0000000000000023 R08: ffff954001be2c20 R09: 0000000000000001 +R10: ffff954001be2c20 R11: ffff9540260133c0 R12: 0000000000000000 +R13: 0000000000000023 R14: 0000000000000000 R15: ffff9540ffcb0905 +FS: 0000000000000000(0000) GS:ffff9540ffc80000(0000) knlGS:0000000000000000 +CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +CR2: 0000000000000000 CR3: 000000010625c001 CR4: 00000000003706e0 +DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 +DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 +Call Trace: +mlx5_ib_gsi_pkey_change+0x20/0x40 [mlx5_ib] +process_one_work+0x1e8/0x3c0 +worker_thread+0x50/0x3b0 +? rescuer_thread+0x380/0x380 +kthread+0x149/0x170 +? set_kthread_struct+0x50/0x50 +ret_from_fork+0x22/0x30 +Modules linked in: rdma_ucm(OE) rdma_cm(OE) iw_cm(OE) ib_ipoib(OE) ib_cm(OE) ib_umad(OE) mlx5_ib(OE) mlx5_fwctl(OE) fwctl(OE) ib_uverbs(OE) mlx5_core(OE) mlxdevm(OE) ib_core(OE) mlx_compat(OE) psample mlxfw(OE) tls knem(OE) netconsole nfsv3 nfs_acl nfs lockd grace fscache netfs qrtr rfkill sunrpc intel_rapl_msr intel_rapl_common rapl hv_balloon hv_utils i2c_piix4 pcspkr joydev fuse ext4 mbcache jbd2 sr_mod sd_mod cdrom t10_pi sg ata_generic pci_hyperv pci_hyperv_intf hyperv_drm drm_shmem_helper drm_kms_helper hv_storvsc syscopyarea hv_netvsc sysfillrect sysimgblt hid_hyperv fb_sys_fops scsi_transport_fc hyperv_keyboard drm ata_piix crct10dif_pclmul crc32_pclmul crc32c_intel libata ghash_clmulni_intel hv_vmbus serio_raw [last unloaded: ib_core] +CR2: 0000000000000000 +---[ end trace f6f8be4eae12f7bc ]--- + +Fixes: 7722f47e71e5 ("IB/mlx5: Create GSI transmission QPs when P_Key table is changed") +Signed-off-by: Patrisious Haddad <phaddad@nvidia.com> +Reviewed-by: Michael Guralnik <michaelgur@nvidia.com> +Link: https://patch.msgid.link/d271ceeff0c08431b3cbbbb3e2d416f09b6d1621.1731496944.git.leon@kernel.org +Signed-off-by: Leon Romanovsky <leon@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/infiniband/hw/mlx5/main.c | 40 +++++++++++++--------------- + drivers/infiniband/hw/mlx5/mlx5_ib.h | 2 +- + 2 files changed, 20 insertions(+), 22 deletions(-) + +diff --git a/drivers/infiniband/hw/mlx5/main.c b/drivers/infiniband/hw/mlx5/main.c +index 5fef9288699c6..ac20ab3bbabf4 100644 +--- a/drivers/infiniband/hw/mlx5/main.c ++++ b/drivers/infiniband/hw/mlx5/main.c +@@ -2997,7 +2997,6 @@ int mlx5_ib_dev_res_srq_init(struct mlx5_ib_dev *dev) + static int mlx5_ib_dev_res_init(struct mlx5_ib_dev *dev) + { + struct mlx5_ib_resources *devr = &dev->devr; +- int port; + int ret; + + if (!MLX5_CAP_GEN(dev->mdev, xrc)) +@@ -3013,10 +3012,6 @@ static int mlx5_ib_dev_res_init(struct mlx5_ib_dev *dev) + return ret; + } + +- for (port = 0; port < ARRAY_SIZE(devr->ports); ++port) +- INIT_WORK(&devr->ports[port].pkey_change_work, +- pkey_change_handler); +- + mutex_init(&devr->cq_lock); + mutex_init(&devr->srq_lock); + +@@ -3026,16 +3021,6 @@ static int mlx5_ib_dev_res_init(struct mlx5_ib_dev *dev) + static void mlx5_ib_dev_res_cleanup(struct mlx5_ib_dev *dev) + { + struct mlx5_ib_resources *devr = &dev->devr; +- int port; +- +- /* +- * Make sure no change P_Key work items are still executing. +- * +- * At this stage, the mlx5_ib_event should be unregistered +- * and it ensures that no new works are added. +- */ +- for (port = 0; port < ARRAY_SIZE(devr->ports); ++port) +- cancel_work_sync(&devr->ports[port].pkey_change_work); + + /* After s0/s1 init, they are not unset during the device lifetime. */ + if (devr->s1) { +@@ -4471,6 +4456,13 @@ static void mlx5_ib_stage_delay_drop_cleanup(struct mlx5_ib_dev *dev) + + static int mlx5_ib_stage_dev_notifier_init(struct mlx5_ib_dev *dev) + { ++ struct mlx5_ib_resources *devr = &dev->devr; ++ int port; ++ ++ for (port = 0; port < ARRAY_SIZE(devr->ports); ++port) ++ INIT_WORK(&devr->ports[port].pkey_change_work, ++ pkey_change_handler); ++ + dev->mdev_events.notifier_call = mlx5_ib_event; + mlx5_notifier_register(dev->mdev, &dev->mdev_events); + +@@ -4481,8 +4473,14 @@ static int mlx5_ib_stage_dev_notifier_init(struct mlx5_ib_dev *dev) + + static void mlx5_ib_stage_dev_notifier_cleanup(struct mlx5_ib_dev *dev) + { ++ struct mlx5_ib_resources *devr = &dev->devr; ++ int port; ++ + mlx5r_macsec_event_unregister(dev); + mlx5_notifier_unregister(dev->mdev, &dev->mdev_events); ++ ++ for (port = 0; port < ARRAY_SIZE(devr->ports); ++port) ++ cancel_work_sync(&devr->ports[port].pkey_change_work); + } + + void mlx5_ib_data_direct_bind(struct mlx5_ib_dev *ibdev, +@@ -4572,9 +4570,6 @@ static const struct mlx5_ib_profile pf_profile = { + STAGE_CREATE(MLX5_IB_STAGE_DEVICE_RESOURCES, + mlx5_ib_dev_res_init, + mlx5_ib_dev_res_cleanup), +- STAGE_CREATE(MLX5_IB_STAGE_DEVICE_NOTIFIER, +- mlx5_ib_stage_dev_notifier_init, +- mlx5_ib_stage_dev_notifier_cleanup), + STAGE_CREATE(MLX5_IB_STAGE_ODP, + mlx5_ib_odp_init_one, + mlx5_ib_odp_cleanup_one), +@@ -4599,6 +4594,9 @@ static const struct mlx5_ib_profile pf_profile = { + STAGE_CREATE(MLX5_IB_STAGE_IB_REG, + mlx5_ib_stage_ib_reg_init, + mlx5_ib_stage_ib_reg_cleanup), ++ STAGE_CREATE(MLX5_IB_STAGE_DEVICE_NOTIFIER, ++ mlx5_ib_stage_dev_notifier_init, ++ mlx5_ib_stage_dev_notifier_cleanup), + STAGE_CREATE(MLX5_IB_STAGE_POST_IB_REG_UMR, + mlx5_ib_stage_post_ib_reg_umr_init, + NULL), +@@ -4635,9 +4633,6 @@ const struct mlx5_ib_profile raw_eth_profile = { + STAGE_CREATE(MLX5_IB_STAGE_DEVICE_RESOURCES, + mlx5_ib_dev_res_init, + mlx5_ib_dev_res_cleanup), +- STAGE_CREATE(MLX5_IB_STAGE_DEVICE_NOTIFIER, +- mlx5_ib_stage_dev_notifier_init, +- mlx5_ib_stage_dev_notifier_cleanup), + STAGE_CREATE(MLX5_IB_STAGE_COUNTERS, + mlx5_ib_counters_init, + mlx5_ib_counters_cleanup), +@@ -4659,6 +4654,9 @@ const struct mlx5_ib_profile raw_eth_profile = { + STAGE_CREATE(MLX5_IB_STAGE_IB_REG, + mlx5_ib_stage_ib_reg_init, + mlx5_ib_stage_ib_reg_cleanup), ++ STAGE_CREATE(MLX5_IB_STAGE_DEVICE_NOTIFIER, ++ mlx5_ib_stage_dev_notifier_init, ++ mlx5_ib_stage_dev_notifier_cleanup), + STAGE_CREATE(MLX5_IB_STAGE_POST_IB_REG_UMR, + mlx5_ib_stage_post_ib_reg_umr_init, + NULL), +diff --git a/drivers/infiniband/hw/mlx5/mlx5_ib.h b/drivers/infiniband/hw/mlx5/mlx5_ib.h +index 23fd72f7f63df..29bde64ea1eac 100644 +--- a/drivers/infiniband/hw/mlx5/mlx5_ib.h ++++ b/drivers/infiniband/hw/mlx5/mlx5_ib.h +@@ -972,7 +972,6 @@ enum mlx5_ib_stages { + MLX5_IB_STAGE_QP, + MLX5_IB_STAGE_SRQ, + MLX5_IB_STAGE_DEVICE_RESOURCES, +- MLX5_IB_STAGE_DEVICE_NOTIFIER, + MLX5_IB_STAGE_ODP, + MLX5_IB_STAGE_COUNTERS, + MLX5_IB_STAGE_CONG_DEBUGFS, +@@ -981,6 +980,7 @@ enum mlx5_ib_stages { + MLX5_IB_STAGE_PRE_IB_REG_UMR, + MLX5_IB_STAGE_WHITELIST_UID, + MLX5_IB_STAGE_IB_REG, ++ MLX5_IB_STAGE_DEVICE_NOTIFIER, + MLX5_IB_STAGE_POST_IB_REG_UMR, + MLX5_IB_STAGE_DELAY_DROP, + MLX5_IB_STAGE_RESTRACK, +-- +2.43.0 + diff --git a/queue-6.12/rdma-rxe-fix-the-qp-flush-warnings-in-req.patch b/queue-6.12/rdma-rxe-fix-the-qp-flush-warnings-in-req.patch new file mode 100644 index 00000000000..ec432006677 --- /dev/null +++ b/queue-6.12/rdma-rxe-fix-the-qp-flush-warnings-in-req.patch @@ -0,0 +1,84 @@ +From e87c6406d3c48bd7cc61d768088a55ca015cf6ce Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Fri, 25 Oct 2024 17:20:36 +0200 +Subject: RDMA/rxe: Fix the qp flush warnings in req + +From: Zhu Yanjun <yanjun.zhu@linux.dev> + +[ Upstream commit ea4c990fa9e19ffef0648e40c566b94ba5ab31be ] + +When the qp is in error state, the status of WQEs in the queue should be +set to error. Or else the following will appear. + +[ 920.617269] WARNING: CPU: 1 PID: 21 at drivers/infiniband/sw/rxe/rxe_comp.c:756 rxe_completer+0x989/0xcc0 [rdma_rxe] +[ 920.617744] Modules linked in: rnbd_client(O) rtrs_client(O) rtrs_core(O) rdma_ucm rdma_cm iw_cm ib_cm crc32_generic rdma_rxe ip6_udp_tunnel udp_tunnel ib_uverbs ib_core loop brd null_blk ipv6 +[ 920.618516] CPU: 1 PID: 21 Comm: ksoftirqd/1 Tainted: G O 6.1.113-storage+ #65 +[ 920.618986] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.15.0-1 04/01/2014 +[ 920.619396] RIP: 0010:rxe_completer+0x989/0xcc0 [rdma_rxe] +[ 920.619658] Code: 0f b6 84 24 3a 02 00 00 41 89 84 24 44 04 00 00 e9 2a f7 ff ff 39 ca bb 03 00 00 00 b8 0e 00 00 00 48 0f 45 d8 e9 15 f7 ff ff <0f> 0b e9 cb f8 ff ff 41 bf f5 ff ff ff e9 08 f8 ff ff 49 8d bc 24 +[ 920.620482] RSP: 0018:ffff97b7c00bbc38 EFLAGS: 00010246 +[ 920.620817] RAX: 0000000000000000 RBX: 000000000000000c RCX: 0000000000000008 +[ 920.621183] RDX: ffff960dc396ebc0 RSI: 0000000000005400 RDI: ffff960dc4e2fbac +[ 920.621548] RBP: 0000000000000000 R08: 0000000000000001 R09: ffffffffac406450 +[ 920.621884] R10: ffffffffac4060c0 R11: 0000000000000001 R12: ffff960dc4e2f800 +[ 920.622254] R13: ffff960dc4e2f928 R14: ffff97b7c029c580 R15: 0000000000000000 +[ 920.622609] FS: 0000000000000000(0000) GS:ffff960ef7d00000(0000) knlGS:0000000000000000 +[ 920.622979] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +[ 920.623245] CR2: 00007fa056965e90 CR3: 00000001107f1000 CR4: 00000000000006e0 +[ 920.623680] Call Trace: +[ 920.623815] <TASK> +[ 920.623933] ? __warn+0x79/0xc0 +[ 920.624116] ? rxe_completer+0x989/0xcc0 [rdma_rxe] +[ 920.624356] ? report_bug+0xfb/0x150 +[ 920.624594] ? handle_bug+0x3c/0x60 +[ 920.624796] ? exc_invalid_op+0x14/0x70 +[ 920.624976] ? asm_exc_invalid_op+0x16/0x20 +[ 920.625203] ? rxe_completer+0x989/0xcc0 [rdma_rxe] +[ 920.625474] ? rxe_completer+0x329/0xcc0 [rdma_rxe] +[ 920.625749] rxe_do_task+0x80/0x110 [rdma_rxe] +[ 920.626037] rxe_requester+0x625/0xde0 [rdma_rxe] +[ 920.626310] ? rxe_cq_post+0xe2/0x180 [rdma_rxe] +[ 920.626583] ? do_complete+0x18d/0x220 [rdma_rxe] +[ 920.626812] ? rxe_completer+0x1a3/0xcc0 [rdma_rxe] +[ 920.627050] rxe_do_task+0x80/0x110 [rdma_rxe] +[ 920.627285] tasklet_action_common.constprop.0+0xa4/0x120 +[ 920.627522] handle_softirqs+0xc2/0x250 +[ 920.627728] ? sort_range+0x20/0x20 +[ 920.627942] run_ksoftirqd+0x1f/0x30 +[ 920.628158] smpboot_thread_fn+0xc7/0x1b0 +[ 920.628334] kthread+0xd6/0x100 +[ 920.628504] ? kthread_complete_and_exit+0x20/0x20 +[ 920.628709] ret_from_fork+0x1f/0x30 +[ 920.628892] </TASK> + +Fixes: ae720bdb703b ("RDMA/rxe: Generate error completion for error requester QP state") +Signed-off-by: Zhu Yanjun <yanjun.zhu@linux.dev> +Link: https://patch.msgid.link/20241025152036.121417-1-yanjun.zhu@linux.dev +Signed-off-by: Leon Romanovsky <leon@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/infiniband/sw/rxe/rxe_req.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/drivers/infiniband/sw/rxe/rxe_req.c b/drivers/infiniband/sw/rxe/rxe_req.c +index 479c07e6e4ed3..87a02f0deb000 100644 +--- a/drivers/infiniband/sw/rxe/rxe_req.c ++++ b/drivers/infiniband/sw/rxe/rxe_req.c +@@ -663,10 +663,12 @@ int rxe_requester(struct rxe_qp *qp) + if (unlikely(qp_state(qp) == IB_QPS_ERR)) { + wqe = __req_next_wqe(qp); + spin_unlock_irqrestore(&qp->state_lock, flags); +- if (wqe) ++ if (wqe) { ++ wqe->status = IB_WC_WR_FLUSH_ERR; + goto err; +- else ++ } else { + goto exit; ++ } + } + + if (unlikely(qp_state(qp) == IB_QPS_RESET)) { +-- +2.43.0 + diff --git a/queue-6.12/rdma-rxe-set-queue-pair-cur_qp_state-when-being-quer.patch b/queue-6.12/rdma-rxe-set-queue-pair-cur_qp_state-when-being-quer.patch new file mode 100644 index 00000000000..356d0ff1617 --- /dev/null +++ b/queue-6.12/rdma-rxe-set-queue-pair-cur_qp_state-when-being-quer.patch @@ -0,0 +1,38 @@ +From 4018256bc5065a8c206408462d2c16ace3db620b Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Thu, 31 Oct 2024 17:20:19 +0800 +Subject: RDMA/rxe: Set queue pair cur_qp_state when being queried + +From: Liu Jian <liujian56@huawei.com> + +[ Upstream commit 775e6d3c8fda41083b16c26d05163fd69f029a62 ] + +Same with commit e375b9c92985 ("RDMA/cxgb4: Set queue pair state when + being queried"). The API for ib_query_qp requires the driver to set +cur_qp_state on return, add the missing set. + +Fixes: 8700e3e7c485 ("Soft RoCE driver") +Signed-off-by: Liu Jian <liujian56@huawei.com> +Link: https://patch.msgid.link/20241031092019.2138467-1-liujian56@huawei.com +Reviewed-by: Zhu Yanjun <yanjun.zhu@linux.dev> +Signed-off-by: Leon Romanovsky <leon@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/infiniband/sw/rxe/rxe_qp.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/infiniband/sw/rxe/rxe_qp.c b/drivers/infiniband/sw/rxe/rxe_qp.c +index d2f7b5195c19d..91d329e903083 100644 +--- a/drivers/infiniband/sw/rxe/rxe_qp.c ++++ b/drivers/infiniband/sw/rxe/rxe_qp.c +@@ -775,6 +775,7 @@ int rxe_qp_to_attr(struct rxe_qp *qp, struct ib_qp_attr *attr, int mask) + * Yield the processor + */ + spin_lock_irqsave(&qp->state_lock, flags); ++ attr->cur_qp_state = qp_state(qp); + if (qp->attr.sq_draining) { + spin_unlock_irqrestore(&qp->state_lock, flags); + cond_resched(); +-- +2.43.0 + diff --git a/queue-6.12/regmap-irq-set-lockdep-class-for-hierarchical-irq-do.patch b/queue-6.12/regmap-irq-set-lockdep-class-for-hierarchical-irq-do.patch new file mode 100644 index 00000000000..3c93f9b0f0e --- /dev/null +++ b/queue-6.12/regmap-irq-set-lockdep-class-for-hierarchical-irq-do.patch @@ -0,0 +1,85 @@ +From 08816745661eda884ae86cdb4a14e887f8260903 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Fri, 1 Nov 2024 18:55:53 +0200 +Subject: regmap: irq: Set lockdep class for hierarchical IRQ domains + +From: Andy Shevchenko <andriy.shevchenko@linux.intel.com> + +[ Upstream commit 953e549471cabc9d4980f1da2e9fa79f4c23da06 ] + +Lockdep gives a false positive splat as it can't distinguish the lock +which is taken by different IRQ descriptors from different IRQ chips +that are organized in a way of a hierarchy: + + ====================================================== + WARNING: possible circular locking dependency detected + 6.12.0-rc5-next-20241101-00148-g9fabf8160b53 #562 Tainted: G W + ------------------------------------------------------ + modprobe/141 is trying to acquire lock: + ffff899446947868 (intel_soc_pmic_bxtwc:502:(&bxtwc_regmap_config)->lock){+.+.}-{4:4}, at: regmap_update_bits_base+0x33/0x90 + + but task is already holding lock: + ffff899446947c68 (&d->lock){+.+.}-{4:4}, at: __setup_irq+0x682/0x790 + + which lock already depends on the new lock. + + -> #3 (&d->lock){+.+.}-{4:4}: + -> #2 (&desc->request_mutex){+.+.}-{4:4}: + -> #1 (ipclock){+.+.}-{4:4}: + -> #0 (intel_soc_pmic_bxtwc:502:(&bxtwc_regmap_config)->lock){+.+.}-{4:4}: + + Chain exists of: + intel_soc_pmic_bxtwc:502:(&bxtwc_regmap_config)->lock --> &desc->request_mutex --> &d->lock + + Possible unsafe locking scenario: + + CPU0 CPU1 + ---- ---- + lock(&d->lock); + lock(&desc->request_mutex); + lock(&d->lock); + lock(intel_soc_pmic_bxtwc:502:(&bxtwc_regmap_config)->lock); + + *** DEADLOCK *** + + 3 locks held by modprobe/141: + #0: ffff8994419368f8 (&dev->mutex){....}-{4:4}, at: __driver_attach+0xf6/0x250 + #1: ffff89944690b250 (&desc->request_mutex){+.+.}-{4:4}, at: __setup_irq+0x1a2/0x790 + #2: ffff899446947c68 (&d->lock){+.+.}-{4:4}, at: __setup_irq+0x682/0x790 + +Set a lockdep class when we map the IRQ so that it doesn't warn about +a lockdep bug that doesn't exist. + +Fixes: 4af8be67fd99 ("regmap: Convert regmap_irq to use irq_domain") +Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com> +Link: https://patch.msgid.link/20241101165553.4055617-1-andriy.shevchenko@linux.intel.com +Signed-off-by: Mark Brown <broonie@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/base/regmap/regmap-irq.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/drivers/base/regmap/regmap-irq.c b/drivers/base/regmap/regmap-irq.c +index a750e48a26b87..6981e5f974e9a 100644 +--- a/drivers/base/regmap/regmap-irq.c ++++ b/drivers/base/regmap/regmap-irq.c +@@ -514,12 +514,16 @@ static irqreturn_t regmap_irq_thread(int irq, void *d) + return IRQ_NONE; + } + ++static struct lock_class_key regmap_irq_lock_class; ++static struct lock_class_key regmap_irq_request_class; ++ + static int regmap_irq_map(struct irq_domain *h, unsigned int virq, + irq_hw_number_t hw) + { + struct regmap_irq_chip_data *data = h->host_data; + + irq_set_chip_data(virq, data); ++ irq_set_lockdep_class(virq, ®map_irq_lock_class, ®map_irq_request_class); + irq_set_chip(virq, &data->irq_chip); + irq_set_nested_thread(virq, 1); + irq_set_parent(virq, data->irq); +-- +2.43.0 + diff --git a/queue-6.12/regulator-qcom-smd-make-smd_vreg_rpm-static.patch b/queue-6.12/regulator-qcom-smd-make-smd_vreg_rpm-static.patch new file mode 100644 index 00000000000..d8958d0ddb8 --- /dev/null +++ b/queue-6.12/regulator-qcom-smd-make-smd_vreg_rpm-static.patch @@ -0,0 +1,44 @@ +From d9836566eca1a4f09add51e0b5661d73549909b4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Fri, 27 Sep 2024 07:10:36 +0800 +Subject: regulator: qcom-smd: make smd_vreg_rpm static + +From: Min-Hua Chen <minhuadotchen@gmail.com> + +[ Upstream commit 18be43aca2c0ec475037923a8086d0a29fcc9d16 ] + +Since smd_vreg_rpm is used only in +drivers/regulator/qcom_smd-regulator.c, make it static and fix the +following sparse warning: + +drivers/regulator/qcom_smd-regulator.c:14:21: sparse: warning: +symbol 'smd_vreg_rpm' was not declared. Should it be static? + +No functional changes intended. + +Fixes: 5df3b41bd6b5 ("regulator: qcom_smd: Keep one rpm handle for all vregs") +Signed-off-by: Min-Hua Chen <minhuadotchen@gmail.com> +Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org> +Link: https://patch.msgid.link/20240926231038.31916-1-minhuadotchen@gmail.com +Signed-off-by: Mark Brown <broonie@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/regulator/qcom_smd-regulator.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/regulator/qcom_smd-regulator.c b/drivers/regulator/qcom_smd-regulator.c +index 28e7ce60cb617..25ed9f713974b 100644 +--- a/drivers/regulator/qcom_smd-regulator.c ++++ b/drivers/regulator/qcom_smd-regulator.c +@@ -11,7 +11,7 @@ + #include <linux/regulator/of_regulator.h> + #include <linux/soc/qcom/smd-rpm.h> + +-struct qcom_smd_rpm *smd_vreg_rpm; ++static struct qcom_smd_rpm *smd_vreg_rpm; + + struct qcom_rpm_reg { + struct device *dev; +-- +2.43.0 + diff --git a/queue-6.12/regulator-rk808-restrict-dvs-gpios-to-the-rk808-vari.patch b/queue-6.12/regulator-rk808-restrict-dvs-gpios-to-the-rk808-vari.patch new file mode 100644 index 00000000000..e775e409641 --- /dev/null +++ b/queue-6.12/regulator-rk808-restrict-dvs-gpios-to-the-rk808-vari.patch @@ -0,0 +1,106 @@ +From d09a3dd6728f1e6f0be5a25a4f1fb7de9aa27d61 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Mon, 14 Oct 2024 12:43:41 +0200 +Subject: regulator: rk808: Restrict DVS GPIOs to the RK808 variant only + +From: Dragan Simic <dsimic@manjaro.org> + +[ Upstream commit 0d214f27c0e3d9694284c95bac1502c2d247355b ] + +The rk808-regulator driver supports multiple PMIC variants from the Rockckip +RK80x and RK81x series, but the DVS GPIOs are supported on the RK808 variant +only, according to the DT bindings [1][2][3][4][5][6] and the datasheets for +the supported PMIC variants. [7][8][9][10][11][12] + +Thus, change the probe path so the "dvs-gpios" property is checked for and +its value possibly used only when the handled PMIC variant is RK808. There's +no point in doing that on the other PMIC variants, because they don't support +the DVS GPIOs, and it goes against the DT bindings to allow a possible out- +of-place "dvs-gpios" property to actually be handled in the driver. + +This eliminates the following messages, emitted when the "dvs-gpios" property +isn't found in the DT, from the kernel log on boards that actually don't use +the RK808 variant, which may have provided a source of confusion: + + rk808-regulator rk808-regulator.2.auto: there is no dvs0 gpio + rk808-regulator rk808-regulator.2.auto: there is no dvs1 gpio + +Furthermore, demote these kernel messages to debug messages, because they are +useful during the board bringup phase only. Emitting them afterwards, on the +boards that use the RK808 variant, but actually don't use the DVS0/1 GPIOs, +clutters the kernel log a bit, while they provide no value and may actually +cause false impression that some PMIC-related issues are present. + +[1] Documentation/devicetree/bindings/mfd/rockchip,rk805.yaml +[2] Documentation/devicetree/bindings/mfd/rockchip,rk806.yaml +[3] Documentation/devicetree/bindings/mfd/rockchip,rk808.yaml +[4] Documentation/devicetree/bindings/mfd/rockchip,rk816.yaml +[5] Documentation/devicetree/bindings/mfd/rockchip,rk817.yaml +[6] Documentation/devicetree/bindings/mfd/rockchip,rk818.yaml +[7] https://rockchip.fr/RK805%20datasheet%20V1.2.pdf +[8] https://wmsc.lcsc.com/wmsc/upload/file/pdf/v2/lcsc/2401261533_Rockchip-RK806-1_C5156483.pdf +[9] https://rockchip.fr/RK808%20datasheet%20V1.4.pdf +[10] https://rockchip.fr/RK816%20datasheet%20V1.3.pdf +[11] https://rockchip.fr/RK817%20datasheet%20V1.01.pdf +[12] https://rockchip.fr/RK818%20datasheet%20V1.0.pdf + +Fixes: 11375293530b ("regulator: rk808: Add regulator driver for RK818") +Reported-by: Diederik de Haas <didi.debian@cknow.org> +Signed-off-by: Dragan Simic <dsimic@manjaro.org> +Link: https://patch.msgid.link/9a415c59699e76fc7b88a2552520a4ca2538f44e.1728902488.git.dsimic@manjaro.org +Signed-off-by: Mark Brown <broonie@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/regulator/rk808-regulator.c | 15 ++++++++------- + 1 file changed, 8 insertions(+), 7 deletions(-) + +diff --git a/drivers/regulator/rk808-regulator.c b/drivers/regulator/rk808-regulator.c +index 01a8d04879184..37476d2558fda 100644 +--- a/drivers/regulator/rk808-regulator.c ++++ b/drivers/regulator/rk808-regulator.c +@@ -1853,7 +1853,7 @@ static int rk808_regulator_dt_parse_pdata(struct device *dev, + } + + if (!pdata->dvs_gpio[i]) { +- dev_info(dev, "there is no dvs%d gpio\n", i); ++ dev_dbg(dev, "there is no dvs%d gpio\n", i); + continue; + } + +@@ -1889,12 +1889,6 @@ static int rk808_regulator_probe(struct platform_device *pdev) + if (!pdata) + return -ENOMEM; + +- ret = rk808_regulator_dt_parse_pdata(&pdev->dev, regmap, pdata); +- if (ret < 0) +- return ret; +- +- platform_set_drvdata(pdev, pdata); +- + switch (rk808->variant) { + case RK805_ID: + regulators = rk805_reg; +@@ -1905,6 +1899,11 @@ static int rk808_regulator_probe(struct platform_device *pdev) + nregulators = ARRAY_SIZE(rk806_reg); + break; + case RK808_ID: ++ /* DVS0/1 GPIOs are supported on the RK808 only */ ++ ret = rk808_regulator_dt_parse_pdata(&pdev->dev, regmap, pdata); ++ if (ret < 0) ++ return ret; ++ + regulators = rk808_reg; + nregulators = RK808_NUM_REGULATORS; + break; +@@ -1930,6 +1929,8 @@ static int rk808_regulator_probe(struct platform_device *pdev) + return -EINVAL; + } + ++ platform_set_drvdata(pdev, pdata); ++ + config.dev = &pdev->dev; + config.driver_data = pdata; + config.regmap = regmap; +-- +2.43.0 + diff --git a/queue-6.12/remoteproc-qcom-adsp-remove-subdevs-on-the-error-pat.patch b/queue-6.12/remoteproc-qcom-adsp-remove-subdevs-on-the-error-pat.patch new file mode 100644 index 00000000000..1c129d9b878 --- /dev/null +++ b/queue-6.12/remoteproc-qcom-adsp-remove-subdevs-on-the-error-pat.patch @@ -0,0 +1,56 @@ +From bd2a8713ff5f59c6b85997ccb4df2b37541f6068 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Fri, 8 Nov 2024 13:13:54 +0900 +Subject: remoteproc: qcom: adsp: Remove subdevs on the error path of + adsp_probe() + +From: Joe Hattori <joe@pf.is.s.u-tokyo.ac.jp> + +[ Upstream commit fe80d3205e91e36e67f4d3d6c326793298d15766 ] + +Current implementation of adsp_probe() in qcom_q6v5_adsp.c and does not +remove the subdevs of adsp on the error path. Fix this bug by calling +qcom_remove_{ssr,sysmon,pdm,smd,glink}_subdev(), and qcom_q6v5_deinit() +appropriately. + +Fixes: dc160e449122 ("remoteproc: qcom: Introduce Non-PAS ADSP PIL driver") +Signed-off-by: Joe Hattori <joe@pf.is.s.u-tokyo.ac.jp> +Link: https://lore.kernel.org/r/fed3df4219543d46b88bacf87990d947f3fac8d7.1731038950.git.joe@pf.is.s.u-tokyo.ac.jp +Signed-off-by: Bjorn Andersson <andersson@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/remoteproc/qcom_q6v5_adsp.c | 11 +++++++++-- + 1 file changed, 9 insertions(+), 2 deletions(-) + +diff --git a/drivers/remoteproc/qcom_q6v5_adsp.c b/drivers/remoteproc/qcom_q6v5_adsp.c +index 572dcb0f055b7..223f6ca0745d3 100644 +--- a/drivers/remoteproc/qcom_q6v5_adsp.c ++++ b/drivers/remoteproc/qcom_q6v5_adsp.c +@@ -734,15 +734,22 @@ static int adsp_probe(struct platform_device *pdev) + desc->ssctl_id); + if (IS_ERR(adsp->sysmon)) { + ret = PTR_ERR(adsp->sysmon); +- goto disable_pm; ++ goto deinit_remove_glink_pdm_ssr; + } + + ret = rproc_add(rproc); + if (ret) +- goto disable_pm; ++ goto remove_sysmon; + + return 0; + ++remove_sysmon: ++ qcom_remove_sysmon_subdev(adsp->sysmon); ++deinit_remove_glink_pdm_ssr: ++ qcom_q6v5_deinit(&adsp->q6v5); ++ qcom_remove_glink_subdev(rproc, &adsp->glink_subdev); ++ qcom_remove_pdm_subdev(rproc, &adsp->pdm_subdev); ++ qcom_remove_ssr_subdev(rproc, &adsp->ssr_subdev); + disable_pm: + qcom_rproc_pds_detach(adsp); + +-- +2.43.0 + diff --git a/queue-6.12/remoteproc-qcom-pas-add-minidump_id-to-sm8350-resour.patch b/queue-6.12/remoteproc-qcom-pas-add-minidump_id-to-sm8350-resour.patch new file mode 100644 index 00000000000..fd632d7495f --- /dev/null +++ b/queue-6.12/remoteproc-qcom-pas-add-minidump_id-to-sm8350-resour.patch @@ -0,0 +1,46 @@ +From f73d62b1ebab0547492e039454ceed6527c46c21 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Sun, 27 Oct 2024 01:09:44 +0300 +Subject: remoteproc: qcom: pas: add minidump_id to SM8350 resources + +From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org> + +[ Upstream commit e8983156d54f59f57e648ecd44f01c16572da842 ] + +Specify minidump_id for the SM8350 DSPs. It was omitted for in the +original commit e8b4e9a21af7 ("remoteproc: qcom: pas: Add SM8350 PAS +remoteprocs"). + +Fixes: e8b4e9a21af7 ("remoteproc: qcom: pas: Add SM8350 PAS remoteprocs") +Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org> +Reviewed-by: Neil Armstrong <neil.armstrong@linaro.org> +Link: https://lore.kernel.org/r/20241027-sar2130p-adsp-v1-2-bd204e39d24e@linaro.org +Signed-off-by: Bjorn Andersson <andersson@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/remoteproc/qcom_q6v5_pas.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/remoteproc/qcom_q6v5_pas.c b/drivers/remoteproc/qcom_q6v5_pas.c +index 27b23a000c7ae..f4f4b3df3884e 100644 +--- a/drivers/remoteproc/qcom_q6v5_pas.c ++++ b/drivers/remoteproc/qcom_q6v5_pas.c +@@ -917,6 +917,7 @@ static const struct adsp_data sm8250_adsp_resource = { + .crash_reason_smem = 423, + .firmware_name = "adsp.mdt", + .pas_id = 1, ++ .minidump_id = 5, + .auto_boot = true, + .proxy_pd_names = (char*[]){ + "lcx", +@@ -1134,6 +1135,7 @@ static const struct adsp_data sm8350_cdsp_resource = { + .crash_reason_smem = 601, + .firmware_name = "cdsp.mdt", + .pas_id = 18, ++ .minidump_id = 7, + .auto_boot = true, + .proxy_pd_names = (char*[]){ + "cx", +-- +2.43.0 + diff --git a/queue-6.12/remoteproc-qcom-pas-remove-subdevs-on-the-error-path.patch b/queue-6.12/remoteproc-qcom-pas-remove-subdevs-on-the-error-path.patch new file mode 100644 index 00000000000..165fc2ed15f --- /dev/null +++ b/queue-6.12/remoteproc-qcom-pas-remove-subdevs-on-the-error-path.patch @@ -0,0 +1,82 @@ +From 291892759f81c20c003de0dac4e67c46c36400f7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Fri, 8 Nov 2024 13:13:53 +0900 +Subject: remoteproc: qcom: pas: Remove subdevs on the error path of + adsp_probe() + +From: Joe Hattori <joe@pf.is.s.u-tokyo.ac.jp> + +[ Upstream commit 587b67cf62a91b10a47f41c20ed8ad71db375334 ] + +Current implementation of adsp_probe() in qcom_q6v5_pas.c does not +remove the subdevs of adsp on the error path. Fix this bug by calling +qcom_remove_{ssr,sysmon,pdm,smd,glink}_subdev(), qcom_q6v5_deinit(), and +adsp_unassign_memory_region() appropriately. + +Fixes: 4b48921a8f74 ("remoteproc: qcom: Use common SMD edge handler") +Signed-off-by: Joe Hattori <joe@pf.is.s.u-tokyo.ac.jp> +Link: https://lore.kernel.org/r/a1cabc64240022a7f1d5237aa2aa6f72d8fb7052.1731038950.git.joe@pf.is.s.u-tokyo.ac.jp +Signed-off-by: Bjorn Andersson <andersson@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/remoteproc/qcom_q6v5_pas.c | 20 +++++++++++++++----- + 1 file changed, 15 insertions(+), 5 deletions(-) + +diff --git a/drivers/remoteproc/qcom_q6v5_pas.c b/drivers/remoteproc/qcom_q6v5_pas.c +index ef82835e98a4e..27b23a000c7ae 100644 +--- a/drivers/remoteproc/qcom_q6v5_pas.c ++++ b/drivers/remoteproc/qcom_q6v5_pas.c +@@ -759,16 +759,16 @@ static int adsp_probe(struct platform_device *pdev) + + ret = adsp_init_clock(adsp); + if (ret) +- goto free_rproc; ++ goto unassign_mem; + + ret = adsp_init_regulator(adsp); + if (ret) +- goto free_rproc; ++ goto unassign_mem; + + ret = adsp_pds_attach(&pdev->dev, adsp->proxy_pds, + desc->proxy_pd_names); + if (ret < 0) +- goto free_rproc; ++ goto unassign_mem; + adsp->proxy_pd_count = ret; + + ret = qcom_q6v5_init(&adsp->q6v5, pdev, rproc, desc->crash_reason_smem, desc->load_state, +@@ -784,18 +784,28 @@ static int adsp_probe(struct platform_device *pdev) + desc->ssctl_id); + if (IS_ERR(adsp->sysmon)) { + ret = PTR_ERR(adsp->sysmon); +- goto detach_proxy_pds; ++ goto deinit_remove_pdm_smd_glink; + } + + qcom_add_ssr_subdev(rproc, &adsp->ssr_subdev, desc->ssr_name); + ret = rproc_add(rproc); + if (ret) +- goto detach_proxy_pds; ++ goto remove_ssr_sysmon; + + return 0; + ++remove_ssr_sysmon: ++ qcom_remove_ssr_subdev(rproc, &adsp->ssr_subdev); ++ qcom_remove_sysmon_subdev(adsp->sysmon); ++deinit_remove_pdm_smd_glink: ++ qcom_remove_pdm_subdev(rproc, &adsp->pdm_subdev); ++ qcom_remove_smd_subdev(rproc, &adsp->smd_subdev); ++ qcom_remove_glink_subdev(rproc, &adsp->glink_subdev); ++ qcom_q6v5_deinit(&adsp->q6v5); + detach_proxy_pds: + adsp_pds_detach(adsp, adsp->proxy_pds, adsp->proxy_pd_count); ++unassign_mem: ++ adsp_unassign_memory_region(adsp); + free_rproc: + device_init_wakeup(adsp->dev, false); + +-- +2.43.0 + diff --git a/queue-6.12/remoteproc-qcom_q6v5_mss-re-order-writes-to-the-imem.patch b/queue-6.12/remoteproc-qcom_q6v5_mss-re-order-writes-to-the-imem.patch new file mode 100644 index 00000000000..c418f44e2fe --- /dev/null +++ b/queue-6.12/remoteproc-qcom_q6v5_mss-re-order-writes-to-the-imem.patch @@ -0,0 +1,52 @@ +From c1bea5df9308c3e3e49c927c5fb93a7682fcbde2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Mon, 19 Aug 2024 13:00:20 +0530 +Subject: remoteproc: qcom_q6v5_mss: Re-order writes to the IMEM region + +From: Sibi Sankar <quic_sibis@quicinc.com> + +[ Upstream commit 7b22b7719fc17d5979a991c918c868ab041be5c8 ] + +Any write access to the IMEM region when the Q6 is setting up XPU +protection on it will result in a XPU violation. Fix this by ensuring +IMEM writes related to the MBA post-mortem logs happen before the Q6 +is brought out of reset. + +Fixes: 318130cc9362 ("remoteproc: qcom_q6v5_mss: Add MBA log extraction support") +Signed-off-by: Sibi Sankar <quic_sibis@quicinc.com> +Reviewed-by: Douglas Anderson <dianders@chromium.org> +Tested-by: Douglas Anderson <dianders@chromium.org> +Link: https://lore.kernel.org/r/20240819073020.3291287-1-quic_sibis@quicinc.com +Signed-off-by: Bjorn Andersson <andersson@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/remoteproc/qcom_q6v5_mss.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/drivers/remoteproc/qcom_q6v5_mss.c b/drivers/remoteproc/qcom_q6v5_mss.c +index 2a42215ce8e07..32c3531b20c70 100644 +--- a/drivers/remoteproc/qcom_q6v5_mss.c ++++ b/drivers/remoteproc/qcom_q6v5_mss.c +@@ -1162,6 +1162,9 @@ static int q6v5_mba_load(struct q6v5 *qproc) + goto disable_active_clks; + } + ++ if (qproc->has_mba_logs) ++ qcom_pil_info_store("mba", qproc->mba_phys, MBA_LOG_SIZE); ++ + writel(qproc->mba_phys, qproc->rmb_base + RMB_MBA_IMAGE_REG); + if (qproc->dp_size) { + writel(qproc->mba_phys + SZ_1M, qproc->rmb_base + RMB_PMI_CODE_START_REG); +@@ -1172,9 +1175,6 @@ static int q6v5_mba_load(struct q6v5 *qproc) + if (ret) + goto reclaim_mba; + +- if (qproc->has_mba_logs) +- qcom_pil_info_store("mba", qproc->mba_phys, MBA_LOG_SIZE); +- + ret = q6v5_rmb_mba_wait(qproc, 0, 5000); + if (ret == -ETIMEDOUT) { + dev_err(qproc->dev, "MBA boot timed out\n"); +-- +2.43.0 + diff --git a/queue-6.12/revert-cgroup-fix-memory-leak-caused-by-missing-cgro.patch b/queue-6.12/revert-cgroup-fix-memory-leak-caused-by-missing-cgro.patch new file mode 100644 index 00000000000..b87ed3dd066 --- /dev/null +++ b/queue-6.12/revert-cgroup-fix-memory-leak-caused-by-missing-cgro.patch @@ -0,0 +1,43 @@ +From cc2b12eff4abab2aee3ebc20d26d483329d943eb Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Fri, 18 Oct 2024 08:15:19 +0000 +Subject: Revert "cgroup: Fix memory leak caused by missing cgroup_bpf_offline" + +From: Chen Ridong <chenridong@huawei.com> + +[ Upstream commit feb301c60970bd2a1310a53ce2d6e4375397a51b ] + +This reverts commit 04f8ef5643bcd8bcde25dfdebef998aea480b2ba. + +Only cgroup v2 can be attached by cgroup by BPF programs. Revert this +commit and cgroup_bpf_inherit and cgroup_bpf_offline won't be called in +cgroup v1. The memory leak issue will be fixed with next patch. + +Fixes: 04f8ef5643bc ("cgroup: Fix memory leak caused by missing cgroup_bpf_offline") +Link: https://lore.kernel.org/cgroups/aka2hk5jsel5zomucpwlxsej6iwnfw4qu5jkrmjhyfhesjlfdw@46zxhg5bdnr7/ +Signed-off-by: Chen Ridong <chenridong@huawei.com> +Signed-off-by: Tejun Heo <tj@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + kernel/cgroup/cgroup.c | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +diff --git a/kernel/cgroup/cgroup.c b/kernel/cgroup/cgroup.c +index 044c7ba1cc482..30444e0960276 100644 +--- a/kernel/cgroup/cgroup.c ++++ b/kernel/cgroup/cgroup.c +@@ -2314,10 +2314,8 @@ static void cgroup_kill_sb(struct super_block *sb) + * And don't kill the default root. + */ + if (list_empty(&root->cgrp.self.children) && root != &cgrp_dfl_root && +- !percpu_ref_is_dying(&root->cgrp.self.refcnt)) { +- cgroup_bpf_offline(&root->cgrp); ++ !percpu_ref_is_dying(&root->cgrp.self.refcnt)) + percpu_ref_kill(&root->cgrp.self.refcnt); +- } + cgroup_put(&root->cgrp); + kernfs_kill_sb(sb); + } +-- +2.43.0 + diff --git a/queue-6.12/revert-scripts-faddr2line-check-only-two-symbols-whe.patch b/queue-6.12/revert-scripts-faddr2line-check-only-two-symbols-whe.patch new file mode 100644 index 00000000000..f0c3f763ca9 --- /dev/null +++ b/queue-6.12/revert-scripts-faddr2line-check-only-two-symbols-whe.patch @@ -0,0 +1,73 @@ +From dd963c4488bd316c051403d6a5b0918131e6d389 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Mon, 12 Aug 2024 23:01:20 +0000 +Subject: Revert "scripts/faddr2line: Check only two symbols when calculating + symbol size" + +From: Carlos Llamas <cmllamas@google.com> + +[ Upstream commit 56ac7bd2c58a4e93d19f0ccb181035d075b315d3 ] + +This reverts commit c02904f05ff805d6c0631634d5751ebd338f75ec. + +Such commit assumed that only two symbols are relevant for the symbol +size calculation. However, this can lead to an incorrect symbol size +calculation when there are mapping symbols emitted by readelf. + +For instance, when feeding 'update_irq_load_avg+0x1c/0x1c4', faddr2line +might need to process the following readelf lines: + + 784284: ffffffc0081cca30 428 FUNC GLOBAL DEFAULT 2 update_irq_load_avg + 87319: ffffffc0081ccb0c 0 NOTYPE LOCAL DEFAULT 2 $x.62522 + 87321: ffffffc0081ccbdc 0 NOTYPE LOCAL DEFAULT 2 $x.62524 + 87323: ffffffc0081ccbe0 0 NOTYPE LOCAL DEFAULT 2 $x.62526 + 87325: ffffffc0081ccbe4 0 NOTYPE LOCAL DEFAULT 2 $x.62528 + 87327: ffffffc0081ccbe8 0 NOTYPE LOCAL DEFAULT 2 $x.62530 + 87329: ffffffc0081ccbec 0 NOTYPE LOCAL DEFAULT 2 $x.62532 + 87331: ffffffc0081ccbf0 0 NOTYPE LOCAL DEFAULT 2 $x.62534 + 87332: ffffffc0081ccbf4 0 NOTYPE LOCAL DEFAULT 2 $x.62535 + 783403: ffffffc0081ccbf4 424 FUNC GLOBAL DEFAULT 2 sched_pelt_multiplier + +The symbol size of 'update_irq_load_avg' should be calculated with the +address of 'sched_pelt_multiplier', after skipping the mapping symbols +seen in between. However, the offending commit cuts the list short and +faddr2line incorrectly assumes 'update_irq_load_avg' is the last symbol +in the section, resulting in: + + $ scripts/faddr2line vmlinux update_irq_load_avg+0x1c/0x1c4 + skipping update_irq_load_avg address at 0xffffffc0081cca4c due to size mismatch (0x1c4 != 0x3ff9a59988) + no match for update_irq_load_avg+0x1c/0x1c4 + +After reverting the commit the issue is resolved: + + $ scripts/faddr2line vmlinux update_irq_load_avg+0x1c/0x1c4 + update_irq_load_avg+0x1c/0x1c4: + cpu_of at kernel/sched/sched.h:1109 + (inlined by) update_irq_load_avg at kernel/sched/pelt.c:481 + +Fixes: c02904f05ff8 ("scripts/faddr2line: Check only two symbols when calculating symbol size") +Signed-off-by: Carlos Llamas <cmllamas@google.com> +Acked-by: Will Deacon <will@kernel.org> +Acked-by: Brian Johannesmeyer <bjohannesmeyer@gmail.com> +Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + scripts/faddr2line | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/scripts/faddr2line b/scripts/faddr2line +index fe0cc45f03be1..1fa6beef9f978 100755 +--- a/scripts/faddr2line ++++ b/scripts/faddr2line +@@ -252,7 +252,7 @@ __faddr2line() { + found=2 + break + fi +- done < <(echo "${ELF_SYMS}" | sed 's/\[.*\]//' | ${AWK} -v sec=$sym_sec '$7 == sec' | sort --key=2 | ${GREP} -A1 --no-group-separator " ${sym_name}$") ++ done < <(echo "${ELF_SYMS}" | sed 's/\[.*\]//' | ${AWK} -v sec=$sym_sec '$7 == sec' | sort --key=2) + + if [[ $found = 0 ]]; then + warn "can't find symbol: sym_name: $sym_name sym_sec: $sym_sec sym_addr: $sym_addr sym_elf_size: $sym_elf_size" +-- +2.43.0 + diff --git a/queue-6.12/revert-wifi-iwlegacy-do-not-skip-frames-with-bad-fcs.patch b/queue-6.12/revert-wifi-iwlegacy-do-not-skip-frames-with-bad-fcs.patch new file mode 100644 index 00000000000..f70b099c321 --- /dev/null +++ b/queue-6.12/revert-wifi-iwlegacy-do-not-skip-frames-with-bad-fcs.patch @@ -0,0 +1,56 @@ +From 8ad4dfe667c01836e9280b07d9df01786721915b Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Tue, 12 Nov 2024 16:24:19 +0200 +Subject: Revert "wifi: iwlegacy: do not skip frames with bad FCS" + +From: Kalle Valo <kvalo@kernel.org> + +[ Upstream commit 11597043d74809daf5d14256b96d6781749b3f82 ] + +This reverts commit 02b682d54598f61cbb7dbb14d98ec1801112b878. + +Alf reports that this commit causes the connection to eventually die on +iwl4965. The reason is that rx_status.flag is zeroed after +RX_FLAG_FAILED_FCS_CRC is set and mac80211 doesn't know the received frame is +corrupted. + +Fixes: 02b682d54598 ("wifi: iwlegacy: do not skip frames with bad FCS") +Reported-by: Alf Marius <post@alfmarius.net> +Closes: https://lore.kernel.org/r/60f752e8-787e-44a8-92ae-48bdfc9b43e7@app.fastmail.com/ +Signed-off-by: Kalle Valo <kvalo@kernel.org> +Link: https://patch.msgid.link/20241112142419.1023743-1-kvalo@kernel.org +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/net/wireless/intel/iwlegacy/3945.c | 2 +- + drivers/net/wireless/intel/iwlegacy/4965-mac.c | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/wireless/intel/iwlegacy/3945.c b/drivers/net/wireless/intel/iwlegacy/3945.c +index 14d2331ee6cb9..b0656b143f77a 100644 +--- a/drivers/net/wireless/intel/iwlegacy/3945.c ++++ b/drivers/net/wireless/intel/iwlegacy/3945.c +@@ -566,7 +566,7 @@ il3945_hdl_rx(struct il_priv *il, struct il_rx_buf *rxb) + if (!(rx_end->status & RX_RES_STATUS_NO_CRC32_ERROR) || + !(rx_end->status & RX_RES_STATUS_NO_RXE_OVERFLOW)) { + D_RX("Bad CRC or FIFO: 0x%08X.\n", rx_end->status); +- rx_status.flag |= RX_FLAG_FAILED_FCS_CRC; ++ return; + } + + /* Convert 3945's rssi indicator to dBm */ +diff --git a/drivers/net/wireless/intel/iwlegacy/4965-mac.c b/drivers/net/wireless/intel/iwlegacy/4965-mac.c +index fcccde7bb6592..05c4af41bdb96 100644 +--- a/drivers/net/wireless/intel/iwlegacy/4965-mac.c ++++ b/drivers/net/wireless/intel/iwlegacy/4965-mac.c +@@ -664,7 +664,7 @@ il4965_hdl_rx(struct il_priv *il, struct il_rx_buf *rxb) + if (!(rx_pkt_status & RX_RES_STATUS_NO_CRC32_ERROR) || + !(rx_pkt_status & RX_RES_STATUS_NO_RXE_OVERFLOW)) { + D_RX("Bad CRC or FIFO: 0x%08X.\n", le32_to_cpu(rx_pkt_status)); +- rx_status.flag |= RX_FLAG_FAILED_FCS_CRC; ++ return; + } + + /* This will be used in several places later */ +-- +2.43.0 + diff --git a/queue-6.12/risc-v-kvm-fix-aplic-in_clrip-and-clripnum-write-emu.patch b/queue-6.12/risc-v-kvm-fix-aplic-in_clrip-and-clripnum-write-emu.patch new file mode 100644 index 00000000000..2ecf3874883 --- /dev/null +++ b/queue-6.12/risc-v-kvm-fix-aplic-in_clrip-and-clripnum-write-emu.patch @@ -0,0 +1,55 @@ +From 1a37f2ad6e6b36cbcd0e89c1bb8936d5e15a1597 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Tue, 29 Oct 2024 16:55:39 +0800 +Subject: RISC-V: KVM: Fix APLIC in_clrip and clripnum write emulation + +From: Yong-Xuan Wang <yongxuan.wang@sifive.com> + +[ Upstream commit 60821fb4dd7345e5662094accf0a52845306de8c ] + +In the section "4.7 Precise effects on interrupt-pending bits" +of the RISC-V AIA specification defines that: + +"If the source mode is Level1 or Level0 and the interrupt domain +is configured in MSI delivery mode (domaincfg.DM = 1): +The pending bit is cleared whenever the rectified input value is +low, when the interrupt is forwarded by MSI, or by a relevant +write to an in_clrip register or to clripnum." + +Update the aplic_write_pending() to match the spec. + +Fixes: d8dd9f113e16 ("RISC-V: KVM: Fix APLIC setipnum_le/be write emulation") +Signed-off-by: Yong-Xuan Wang <yongxuan.wang@sifive.com> +Reviewed-by: Vincent Chen <vincent.chen@sifive.com> +Reviewed-by: Anup Patel <anup@brainfault.org> +Link: https://lore.kernel.org/r/20241029085542.30541-1-yongxuan.wang@sifive.com +Signed-off-by: Anup Patel <anup@brainfault.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + arch/riscv/kvm/aia_aplic.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/arch/riscv/kvm/aia_aplic.c b/arch/riscv/kvm/aia_aplic.c +index da6ff1bade0df..f59d1c0c8c43a 100644 +--- a/arch/riscv/kvm/aia_aplic.c ++++ b/arch/riscv/kvm/aia_aplic.c +@@ -143,7 +143,7 @@ static void aplic_write_pending(struct aplic *aplic, u32 irq, bool pending) + if (sm == APLIC_SOURCECFG_SM_LEVEL_HIGH || + sm == APLIC_SOURCECFG_SM_LEVEL_LOW) { + if (!pending) +- goto skip_write_pending; ++ goto noskip_write_pending; + if ((irqd->state & APLIC_IRQ_STATE_INPUT) && + sm == APLIC_SOURCECFG_SM_LEVEL_LOW) + goto skip_write_pending; +@@ -152,6 +152,7 @@ static void aplic_write_pending(struct aplic *aplic, u32 irq, bool pending) + goto skip_write_pending; + } + ++noskip_write_pending: + if (pending) + irqd->state |= APLIC_IRQ_STATE_PENDING; + else +-- +2.43.0 + diff --git a/queue-6.12/riscv-kvm-fix-out-of-bounds-array-access.patch b/queue-6.12/riscv-kvm-fix-out-of-bounds-array-access.patch new file mode 100644 index 00000000000..e67ff5bf486 --- /dev/null +++ b/queue-6.12/riscv-kvm-fix-out-of-bounds-array-access.patch @@ -0,0 +1,64 @@ +From 27425e1a5b69d644e293d89607553287c0aa4df5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Mon, 4 Nov 2024 20:15:01 +0100 +Subject: riscv: kvm: Fix out-of-bounds array access +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Björn Töpel <bjorn@rivosinc.com> + +[ Upstream commit 332fa4a802b16ccb727199da685294f85f9880cb ] + +In kvm_riscv_vcpu_sbi_init() the entry->ext_idx can contain an +out-of-bound index. This is used as a special marker for the base +extensions, that cannot be disabled. However, when traversing the +extensions, that special marker is not checked prior indexing the +array. + +Add an out-of-bounds check to the function. + +Fixes: 56d8a385b605 ("RISC-V: KVM: Allow some SBI extensions to be disabled by default") +Signed-off-by: Björn Töpel <bjorn@rivosinc.com> +Reviewed-by: Anup Patel <anup@brainfault.org> +Link: https://lore.kernel.org/r/20241104191503.74725-1-bjorn@kernel.org +Signed-off-by: Anup Patel <anup@brainfault.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + arch/riscv/kvm/vcpu_sbi.c | 11 +++++++---- + 1 file changed, 7 insertions(+), 4 deletions(-) + +diff --git a/arch/riscv/kvm/vcpu_sbi.c b/arch/riscv/kvm/vcpu_sbi.c +index 7de128be8db9b..6e704ed86a83a 100644 +--- a/arch/riscv/kvm/vcpu_sbi.c ++++ b/arch/riscv/kvm/vcpu_sbi.c +@@ -486,19 +486,22 @@ void kvm_riscv_vcpu_sbi_init(struct kvm_vcpu *vcpu) + struct kvm_vcpu_sbi_context *scontext = &vcpu->arch.sbi_context; + const struct kvm_riscv_sbi_extension_entry *entry; + const struct kvm_vcpu_sbi_extension *ext; +- int i; ++ int idx, i; + + for (i = 0; i < ARRAY_SIZE(sbi_ext); i++) { + entry = &sbi_ext[i]; + ext = entry->ext_ptr; ++ idx = entry->ext_idx; ++ ++ if (idx < 0 || idx >= ARRAY_SIZE(scontext->ext_status)) ++ continue; + + if (ext->probe && !ext->probe(vcpu)) { +- scontext->ext_status[entry->ext_idx] = +- KVM_RISCV_SBI_EXT_STATUS_UNAVAILABLE; ++ scontext->ext_status[idx] = KVM_RISCV_SBI_EXT_STATUS_UNAVAILABLE; + continue; + } + +- scontext->ext_status[entry->ext_idx] = ext->default_disabled ? ++ scontext->ext_status[idx] = ext->default_disabled ? + KVM_RISCV_SBI_EXT_STATUS_DISABLED : + KVM_RISCV_SBI_EXT_STATUS_ENABLED; + } +-- +2.43.0 + diff --git a/queue-6.12/rpmsg-glink-use-only-lower-16-bits-of-param2-for-cmd.patch b/queue-6.12/rpmsg-glink-use-only-lower-16-bits-of-param2-for-cmd.patch new file mode 100644 index 00000000000..d1fd703f4ac --- /dev/null +++ b/queue-6.12/rpmsg-glink-use-only-lower-16-bits-of-param2-for-cmd.patch @@ -0,0 +1,44 @@ +From 14dd5c59ec14288d445103e492b05723a96b8b30 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Mon, 7 Oct 2024 19:59:35 -0400 +Subject: rpmsg: glink: use only lower 16-bits of param2 for CMD_OPEN name + length + +From: Jonathan Marek <jonathan@marek.ca> + +[ Upstream commit 06c59d97f63c1b8af521fa5aef8a716fb988b285 ] + +The name len field of the CMD_OPEN packet is only 16-bits and the upper +16-bits of "param2" are a different "prio" field, which can be nonzero in +certain situations, and CMD_OPEN packets can be unexpectedly dropped +because of this. + +Fix this by masking out the upper 16 bits of param2. + +Fixes: b4f8e52b89f6 ("rpmsg: Introduce Qualcomm RPM glink driver") +Signed-off-by: Jonathan Marek <jonathan@marek.ca> +Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org> +Link: https://lore.kernel.org/r/20241007235935.6216-1-jonathan@marek.ca +Signed-off-by: Bjorn Andersson <andersson@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/rpmsg/qcom_glink_native.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/rpmsg/qcom_glink_native.c b/drivers/rpmsg/qcom_glink_native.c +index d3af1dfa3c7d7..a2f9d85c7156d 100644 +--- a/drivers/rpmsg/qcom_glink_native.c ++++ b/drivers/rpmsg/qcom_glink_native.c +@@ -1204,7 +1204,8 @@ void qcom_glink_native_rx(struct qcom_glink *glink) + ret = qcom_glink_rx_open_ack(glink, param1); + break; + case GLINK_CMD_OPEN: +- ret = qcom_glink_rx_defer(glink, param2); ++ /* upper 16 bits of param2 are the "prio" field */ ++ ret = qcom_glink_rx_defer(glink, param2 & 0xffff); + break; + case GLINK_CMD_TX_DATA: + case GLINK_CMD_TX_DATA_CONT: +-- +2.43.0 + diff --git a/queue-6.12/rtase-correct-the-speed-for-rtl907xd-v1.patch b/queue-6.12/rtase-correct-the-speed-for-rtl907xd-v1.patch new file mode 100644 index 00000000000..885b2ccfaa3 --- /dev/null +++ b/queue-6.12/rtase-correct-the-speed-for-rtl907xd-v1.patch @@ -0,0 +1,51 @@ +From 0f263bdba4ca426efc320a0862b0fa901c4c8851 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Wed, 20 Nov 2024 15:56:23 +0800 +Subject: rtase: Correct the speed for RTL907XD-V1 + +From: Justin Lai <justinlai0215@realtek.com> + +[ Upstream commit c1fc14c4df801fe2d9ec3160b52fa63569ce164c ] + +Previously, the reported speed was uniformly set to SPEED_5000, but the +RTL907XD-V1 actually operates at a speed of SPEED_10000. Therefore, this +patch makes the necessary correction. + +Fixes: dd7f17c40fd1 ("rtase: Implement ethtool function") +Signed-off-by: Justin Lai <justinlai0215@realtek.com> +Signed-off-by: Paolo Abeni <pabeni@redhat.com> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/net/ethernet/realtek/rtase/rtase_main.c | 13 ++++++++++++- + 1 file changed, 12 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/realtek/rtase/rtase_main.c b/drivers/net/ethernet/realtek/rtase/rtase_main.c +index c2999e24904d1..7b433b290a973 100644 +--- a/drivers/net/ethernet/realtek/rtase/rtase_main.c ++++ b/drivers/net/ethernet/realtek/rtase/rtase_main.c +@@ -1714,10 +1714,21 @@ static int rtase_get_settings(struct net_device *dev, + struct ethtool_link_ksettings *cmd) + { + u32 supported = SUPPORTED_MII | SUPPORTED_Pause | SUPPORTED_Asym_Pause; ++ const struct rtase_private *tp = netdev_priv(dev); + + ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.supported, + supported); +- cmd->base.speed = SPEED_5000; ++ ++ switch (tp->hw_ver) { ++ case RTASE_HW_VER_906X_7XA: ++ case RTASE_HW_VER_906X_7XC: ++ cmd->base.speed = SPEED_5000; ++ break; ++ case RTASE_HW_VER_907XD_V1: ++ cmd->base.speed = SPEED_10000; ++ break; ++ } ++ + cmd->base.duplex = DUPLEX_FULL; + cmd->base.port = PORT_MII; + cmd->base.autoneg = AUTONEG_DISABLE; +-- +2.43.0 + diff --git a/queue-6.12/rtase-corrects-error-handling-of-the-rtase_check_mac.patch b/queue-6.12/rtase-corrects-error-handling-of-the-rtase_check_mac.patch new file mode 100644 index 00000000000..bc64676b0be --- /dev/null +++ b/queue-6.12/rtase-corrects-error-handling-of-the-rtase_check_mac.patch @@ -0,0 +1,44 @@ +From 252a7e6fd6c17ce9b7c18bc031150333656f6924 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Wed, 20 Nov 2024 15:56:24 +0800 +Subject: rtase: Corrects error handling of the rtase_check_mac_version_valid() + +From: Justin Lai <justinlai0215@realtek.com> + +[ Upstream commit a01cfcfda5cc787552b344cbc92f9c363c81ad4f ] + +Previously, when the hardware version ID was determined to be invalid, +only an error message was printed without any further handling. Therefore, +this patch makes the necessary corrections to address this. + +Fixes: a36e9f5cfe9e ("rtase: Add support for a pci table in this module") +Signed-off-by: Justin Lai <justinlai0215@realtek.com> +Signed-off-by: Paolo Abeni <pabeni@redhat.com> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/net/ethernet/realtek/rtase/rtase_main.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/net/ethernet/realtek/rtase/rtase_main.c b/drivers/net/ethernet/realtek/rtase/rtase_main.c +index 7b433b290a973..1bfe5ef40c522 100644 +--- a/drivers/net/ethernet/realtek/rtase/rtase_main.c ++++ b/drivers/net/ethernet/realtek/rtase/rtase_main.c +@@ -2122,6 +2122,7 @@ static int rtase_init_one(struct pci_dev *pdev, + dev_err(&pdev->dev, + "unknown chip version: 0x%08x, contact rtase maintainers (see MAINTAINERS file)\n", + tp->hw_ver); ++ goto err_out_release_board; + } + + rtase_init_software_variable(pdev, tp); +@@ -2196,6 +2197,7 @@ static int rtase_init_one(struct pci_dev *pdev, + netif_napi_del(&ivec->napi); + } + ++err_out_release_board: + rtase_release_board(pdev, dev, ioaddr); + + return ret; +-- +2.43.0 + diff --git a/queue-6.12/rtase-refactor-the-rtase_check_mac_version_valid-fun.patch b/queue-6.12/rtase-refactor-the-rtase_check_mac_version_valid-fun.patch new file mode 100644 index 00000000000..739e07dcf1b --- /dev/null +++ b/queue-6.12/rtase-refactor-the-rtase_check_mac_version_valid-fun.patch @@ -0,0 +1,101 @@ +From 94e3c3a84774c35dbf77a107ea5ae0d3509dc815 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Wed, 20 Nov 2024 15:56:22 +0800 +Subject: rtase: Refactor the rtase_check_mac_version_valid() function + +From: Justin Lai <justinlai0215@realtek.com> + +[ Upstream commit a1f8609ff1f658e410f78d800ca947d57e51996a ] + +Different hardware requires different configurations, but this distinction +was not made previously. Additionally, the error message was not clear +enough. Therefore, this patch will address the issues mentioned above. + +Fixes: a36e9f5cfe9e ("rtase: Add support for a pci table in this module") +Signed-off-by: Justin Lai <justinlai0215@realtek.com> +Signed-off-by: Paolo Abeni <pabeni@redhat.com> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/net/ethernet/realtek/rtase/rtase.h | 7 ++++- + .../net/ethernet/realtek/rtase/rtase_main.c | 28 +++++++++++-------- + 2 files changed, 22 insertions(+), 13 deletions(-) + +diff --git a/drivers/net/ethernet/realtek/rtase/rtase.h b/drivers/net/ethernet/realtek/rtase/rtase.h +index 583c33930f886..4a4434869b10a 100644 +--- a/drivers/net/ethernet/realtek/rtase/rtase.h ++++ b/drivers/net/ethernet/realtek/rtase/rtase.h +@@ -9,7 +9,10 @@ + #ifndef RTASE_H + #define RTASE_H + +-#define RTASE_HW_VER_MASK 0x7C800000 ++#define RTASE_HW_VER_MASK 0x7C800000 ++#define RTASE_HW_VER_906X_7XA 0x00800000 ++#define RTASE_HW_VER_906X_7XC 0x04000000 ++#define RTASE_HW_VER_907XD_V1 0x04800000 + + #define RTASE_RX_DMA_BURST_256 4 + #define RTASE_TX_DMA_BURST_UNLIMITED 7 +@@ -327,6 +330,8 @@ struct rtase_private { + u16 int_nums; + u16 tx_int_mit; + u16 rx_int_mit; ++ ++ u32 hw_ver; + }; + + #define RTASE_LSO_64K 64000 +diff --git a/drivers/net/ethernet/realtek/rtase/rtase_main.c b/drivers/net/ethernet/realtek/rtase/rtase_main.c +index f8777b7663d35..c2999e24904d1 100644 +--- a/drivers/net/ethernet/realtek/rtase/rtase_main.c ++++ b/drivers/net/ethernet/realtek/rtase/rtase_main.c +@@ -1972,20 +1972,21 @@ static void rtase_init_software_variable(struct pci_dev *pdev, + tp->dev->max_mtu = RTASE_MAX_JUMBO_SIZE; + } + +-static bool rtase_check_mac_version_valid(struct rtase_private *tp) ++static int rtase_check_mac_version_valid(struct rtase_private *tp) + { +- u32 hw_ver = rtase_r32(tp, RTASE_TX_CONFIG_0) & RTASE_HW_VER_MASK; +- bool known_ver = false; ++ int ret = -ENODEV; + +- switch (hw_ver) { +- case 0x00800000: +- case 0x04000000: +- case 0x04800000: +- known_ver = true; ++ tp->hw_ver = rtase_r32(tp, RTASE_TX_CONFIG_0) & RTASE_HW_VER_MASK; ++ ++ switch (tp->hw_ver) { ++ case RTASE_HW_VER_906X_7XA: ++ case RTASE_HW_VER_906X_7XC: ++ case RTASE_HW_VER_907XD_V1: ++ ret = 0; + break; + } + +- return known_ver; ++ return ret; + } + + static int rtase_init_board(struct pci_dev *pdev, struct net_device **dev_out, +@@ -2105,9 +2106,12 @@ static int rtase_init_one(struct pci_dev *pdev, + tp->pdev = pdev; + + /* identify chip attached to board */ +- if (!rtase_check_mac_version_valid(tp)) +- return dev_err_probe(&pdev->dev, -ENODEV, +- "unknown chip version, contact rtase maintainers (see MAINTAINERS file)\n"); ++ ret = rtase_check_mac_version_valid(tp); ++ if (ret != 0) { ++ dev_err(&pdev->dev, ++ "unknown chip version: 0x%08x, contact rtase maintainers (see MAINTAINERS file)\n", ++ tp->hw_ver); ++ } + + rtase_init_software_variable(pdev, tp); + rtase_init_hardware(tp); +-- +2.43.0 + diff --git a/queue-6.12/rtla-timerlat-do-not-set-params-user_workload-with-u.patch b/queue-6.12/rtla-timerlat-do-not-set-params-user_workload-with-u.patch new file mode 100644 index 00000000000..4a868e1ba18 --- /dev/null +++ b/queue-6.12/rtla-timerlat-do-not-set-params-user_workload-with-u.patch @@ -0,0 +1,66 @@ +From c0be97a7807b3d29baec723e4035dc41ea64502a Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Mon, 21 Oct 2024 14:31:40 +0200 +Subject: rtla/timerlat: Do not set params->user_workload with -U + +From: Tomas Glozar <tglozar@redhat.com> + +[ Upstream commit fcbc60d7dc4b125c8de130aa1512e5d20726c06e ] + +Since commit fb9e90a67ee9 ("rtla/timerlat: Make user-space threads +the default"), rtla-timerlat has been defaulting to +params->user_workload if neither that or params->kernel_workload is set. +This has unintentionally made -U, which sets only params->user_hist/top +but not params->user_workload, to behave like -u unless -k is set, +preventing the user from running a custom workload. + +Example: +$ rtla timerlat hist -U -c 0 & +[1] 7413 +$ python sample/timerlat_load.py 0 +Error opening timerlat fd, did you run timerlat -U? +$ ps | grep timerlatu +7415 pts/4 00:00:00 timerlatu/0 + +Fix the issue by checking for params->user_top/hist instead of +params->user_workload when setting default thread mode. + +Link: https://lore.kernel.org/20241021123140.14652-1-tglozar@redhat.com +Fixes: fb9e90a67ee9 ("rtla/timerlat: Make user-space threads the default") +Signed-off-by: Tomas Glozar <tglozar@redhat.com> +Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + tools/tracing/rtla/src/timerlat_hist.c | 2 +- + tools/tracing/rtla/src/timerlat_top.c | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/tools/tracing/rtla/src/timerlat_hist.c b/tools/tracing/rtla/src/timerlat_hist.c +index a3907c390d67a..829511a712224 100644 +--- a/tools/tracing/rtla/src/timerlat_hist.c ++++ b/tools/tracing/rtla/src/timerlat_hist.c +@@ -1064,7 +1064,7 @@ timerlat_hist_apply_config(struct osnoise_tool *tool, struct timerlat_hist_param + * If the user did not specify a type of thread, try user-threads first. + * Fall back to kernel threads otherwise. + */ +- if (!params->kernel_workload && !params->user_workload) { ++ if (!params->kernel_workload && !params->user_hist) { + retval = tracefs_file_exists(NULL, "osnoise/per_cpu/cpu0/timerlat_fd"); + if (retval) { + debug_msg("User-space interface detected, setting user-threads\n"); +diff --git a/tools/tracing/rtla/src/timerlat_top.c b/tools/tracing/rtla/src/timerlat_top.c +index 210b0f533534a..3b62519a412fc 100644 +--- a/tools/tracing/rtla/src/timerlat_top.c ++++ b/tools/tracing/rtla/src/timerlat_top.c +@@ -830,7 +830,7 @@ timerlat_top_apply_config(struct osnoise_tool *top, struct timerlat_top_params * + * If the user did not specify a type of thread, try user-threads first. + * Fall back to kernel threads otherwise. + */ +- if (!params->kernel_workload && !params->user_workload) { ++ if (!params->kernel_workload && !params->user_top) { + retval = tracefs_file_exists(NULL, "osnoise/per_cpu/cpu0/timerlat_fd"); + if (retval) { + debug_msg("User-space interface detected, setting user-threads\n"); +-- +2.43.0 + diff --git a/queue-6.12/rust-block-fix-formatting-of-kernel-block-mq-request.patch b/queue-6.12/rust-block-fix-formatting-of-kernel-block-mq-request.patch new file mode 100644 index 00000000000..159ac7d79d3 --- /dev/null +++ b/queue-6.12/rust-block-fix-formatting-of-kernel-block-mq-request.patch @@ -0,0 +1,196 @@ +From 4ac06cc8d17f371f5a1fbfaa9a8220370c988de6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Tue, 3 Sep 2024 19:30:29 +0200 +Subject: rust: block: fix formatting of `kernel::block::mq::request` module + +From: Francesco Zardi <frazar00@gmail.com> + +[ Upstream commit 28e848386b92645f93b9f2fdba5882c3ca7fb3e2 ] + +Fix several issues with rustdoc formatting for the +`kernel::block::mq::Request` module, in particular: + + - An ordered list not rendering correctly, fixed by using numbers + prefixes instead of letters. + + - Code snippets formatted as regular text, fixed by wrapping the + code with `back-ticks`. + + - References to types missing intra-doc links, fixed by wrapping the + types with [square brackets]. + +Reported-by: Miguel Ojeda <ojeda@kernel.org> +Closes: https://github.com/Rust-for-Linux/linux/issues/1108 +Signed-off-by: Francesco Zardi <frazar00@gmail.com> +Acked-by: Andreas Hindborg <a.hindborg@kernel.org> +Fixes: 3253aba3408a ("rust: block: introduce `kernel::block::mq` module") +Link: https://lore.kernel.org/r/20240903173027.16732-3-frazar00@gmail.com +[ Added an extra intra-doc link. Took the chance to add some periods + for consistency. Reworded slightly. - Miguel ] +Signed-off-by: Miguel Ojeda <ojeda@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + rust/kernel/block/mq/request.rs | 67 +++++++++++++++++++-------------- + 1 file changed, 38 insertions(+), 29 deletions(-) + +diff --git a/rust/kernel/block/mq/request.rs b/rust/kernel/block/mq/request.rs +index a0e22827f3f4e..7943f43b95753 100644 +--- a/rust/kernel/block/mq/request.rs ++++ b/rust/kernel/block/mq/request.rs +@@ -16,50 +16,55 @@ + sync::atomic::{AtomicU64, Ordering}, + }; + +-/// A wrapper around a blk-mq `struct request`. This represents an IO request. ++/// A wrapper around a blk-mq [`struct request`]. This represents an IO request. + /// + /// # Implementation details + /// + /// There are four states for a request that the Rust bindings care about: + /// +-/// A) Request is owned by block layer (refcount 0) +-/// B) Request is owned by driver but with zero `ARef`s in existence +-/// (refcount 1) +-/// C) Request is owned by driver with exactly one `ARef` in existence +-/// (refcount 2) +-/// D) Request is owned by driver with more than one `ARef` in existence +-/// (refcount > 2) ++/// 1. Request is owned by block layer (refcount 0). ++/// 2. Request is owned by driver but with zero [`ARef`]s in existence ++/// (refcount 1). ++/// 3. Request is owned by driver with exactly one [`ARef`] in existence ++/// (refcount 2). ++/// 4. Request is owned by driver with more than one [`ARef`] in existence ++/// (refcount > 2). + /// + /// +-/// We need to track A and B to ensure we fail tag to request conversions for ++/// We need to track 1 and 2 to ensure we fail tag to request conversions for + /// requests that are not owned by the driver. + /// +-/// We need to track C and D to ensure that it is safe to end the request and hand ++/// We need to track 3 and 4 to ensure that it is safe to end the request and hand + /// back ownership to the block layer. + /// + /// The states are tracked through the private `refcount` field of + /// `RequestDataWrapper`. This structure lives in the private data area of the C +-/// `struct request`. ++/// [`struct request`]. + /// + /// # Invariants + /// +-/// * `self.0` is a valid `struct request` created by the C portion of the kernel. ++/// * `self.0` is a valid [`struct request`] created by the C portion of the ++/// kernel. + /// * The private data area associated with this request must be an initialized + /// and valid `RequestDataWrapper<T>`. + /// * `self` is reference counted by atomic modification of +-/// self.wrapper_ref().refcount(). ++/// `self.wrapper_ref().refcount()`. ++/// ++/// [`struct request`]: srctree/include/linux/blk-mq.h + /// + #[repr(transparent)] + pub struct Request<T: Operations>(Opaque<bindings::request>, PhantomData<T>); + + impl<T: Operations> Request<T> { +- /// Create an `ARef<Request>` from a `struct request` pointer. ++ /// Create an [`ARef<Request>`] from a [`struct request`] pointer. + /// + /// # Safety + /// + /// * The caller must own a refcount on `ptr` that is transferred to the +- /// returned `ARef`. +- /// * The type invariants for `Request` must hold for the pointee of `ptr`. ++ /// returned [`ARef`]. ++ /// * The type invariants for [`Request`] must hold for the pointee of `ptr`. ++ /// ++ /// [`struct request`]: srctree/include/linux/blk-mq.h + pub(crate) unsafe fn aref_from_raw(ptr: *mut bindings::request) -> ARef<Self> { + // INVARIANT: By the safety requirements of this function, invariants are upheld. + // SAFETY: By the safety requirement of this function, we own a +@@ -84,12 +89,14 @@ pub(crate) unsafe fn start_unchecked(this: &ARef<Self>) { + } + + /// Try to take exclusive ownership of `this` by dropping the refcount to 0. +- /// This fails if `this` is not the only `ARef` pointing to the underlying +- /// `Request`. ++ /// This fails if `this` is not the only [`ARef`] pointing to the underlying ++ /// [`Request`]. + /// +- /// If the operation is successful, `Ok` is returned with a pointer to the +- /// C `struct request`. If the operation fails, `this` is returned in the +- /// `Err` variant. ++ /// If the operation is successful, [`Ok`] is returned with a pointer to the ++ /// C [`struct request`]. If the operation fails, `this` is returned in the ++ /// [`Err`] variant. ++ /// ++ /// [`struct request`]: srctree/include/linux/blk-mq.h + fn try_set_end(this: ARef<Self>) -> Result<*mut bindings::request, ARef<Self>> { + // We can race with `TagSet::tag_to_rq` + if let Err(_old) = this.wrapper_ref().refcount().compare_exchange( +@@ -109,7 +116,7 @@ fn try_set_end(this: ARef<Self>) -> Result<*mut bindings::request, ARef<Self>> { + + /// Notify the block layer that the request has been completed without errors. + /// +- /// This function will return `Err` if `this` is not the only `ARef` ++ /// This function will return [`Err`] if `this` is not the only [`ARef`] + /// referencing the request. + pub fn end_ok(this: ARef<Self>) -> Result<(), ARef<Self>> { + let request_ptr = Self::try_set_end(this)?; +@@ -123,13 +130,13 @@ pub fn end_ok(this: ARef<Self>) -> Result<(), ARef<Self>> { + Ok(()) + } + +- /// Return a pointer to the `RequestDataWrapper` stored in the private area ++ /// Return a pointer to the [`RequestDataWrapper`] stored in the private area + /// of the request structure. + /// + /// # Safety + /// + /// - `this` must point to a valid allocation of size at least size of +- /// `Self` plus size of `RequestDataWrapper`. ++ /// [`Self`] plus size of [`RequestDataWrapper`]. + pub(crate) unsafe fn wrapper_ptr(this: *mut Self) -> NonNull<RequestDataWrapper> { + let request_ptr = this.cast::<bindings::request>(); + // SAFETY: By safety requirements for this function, `this` is a +@@ -141,7 +148,7 @@ pub(crate) unsafe fn wrapper_ptr(this: *mut Self) -> NonNull<RequestDataWrapper> + unsafe { NonNull::new_unchecked(wrapper_ptr) } + } + +- /// Return a reference to the `RequestDataWrapper` stored in the private ++ /// Return a reference to the [`RequestDataWrapper`] stored in the private + /// area of the request structure. + pub(crate) fn wrapper_ref(&self) -> &RequestDataWrapper { + // SAFETY: By type invariant, `self.0` is a valid allocation. Further, +@@ -152,13 +159,15 @@ pub(crate) fn wrapper_ref(&self) -> &RequestDataWrapper { + } + } + +-/// A wrapper around data stored in the private area of the C `struct request`. ++/// A wrapper around data stored in the private area of the C [`struct request`]. ++/// ++/// [`struct request`]: srctree/include/linux/blk-mq.h + pub(crate) struct RequestDataWrapper { + /// The Rust request refcount has the following states: + /// + /// - 0: The request is owned by C block layer. +- /// - 1: The request is owned by Rust abstractions but there are no ARef references to it. +- /// - 2+: There are `ARef` references to the request. ++ /// - 1: The request is owned by Rust abstractions but there are no [`ARef`] references to it. ++ /// - 2+: There are [`ARef`] references to the request. + refcount: AtomicU64, + } + +@@ -204,7 +213,7 @@ fn atomic_relaxed_op_return(target: &AtomicU64, op: impl Fn(u64) -> u64) -> u64 + } + + /// Store the result of `op(target.load)` in `target` if `target.load() != +-/// pred`, returning true if the target was updated. ++/// pred`, returning [`true`] if the target was updated. + fn atomic_relaxed_op_unless(target: &AtomicU64, op: impl Fn(u64) -> u64, pred: u64) -> bool { + target + .fetch_update(Ordering::Relaxed, Ordering::Relaxed, |x| { +-- +2.43.0 + diff --git a/queue-6.12/rust-helpers-avoid-raw_spin_lock-initialization-for-.patch b/queue-6.12/rust-helpers-avoid-raw_spin_lock-initialization-for-.patch new file mode 100644 index 00000000000..412ed073632 --- /dev/null +++ b/queue-6.12/rust-helpers-avoid-raw_spin_lock-initialization-for-.patch @@ -0,0 +1,89 @@ +From 772f88a6aaed73739bcec1cb3519989732e491ec Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Thu, 7 Nov 2024 17:32:23 +0100 +Subject: rust: helpers: Avoid raw_spin_lock initialization for PREEMPT_RT + +From: Eder Zulian <ezulian@redhat.com> + +[ Upstream commit 5c2e7736e20d9b348a44cafbfa639fe2653fbc34 ] + +When PREEMPT_RT=y, spin locks are mapped to rt_mutex types, so using +spinlock_check() + __raw_spin_lock_init() to initialize spin locks is +incorrect, and would cause build errors. + +Introduce __spin_lock_init() to initialize a spin lock with lockdep +rquired information for PREEMPT_RT builds, and use it in the Rust +helper. + +Fixes: d2d6422f8bd1 ("x86: Allow to enable PREEMPT_RT.") +Closes: https://lore.kernel.org/oe-kbuild-all/202409251238.vetlgXE9-lkp@intel.com/ +Reported-by: kernel test robot <lkp@intel.com> +Signed-off-by: Eder Zulian <ezulian@redhat.com> +Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> +Reviewed-by: Boqun Feng <boqun.feng@gmail.com> +Tested-by: Boqun Feng <boqun.feng@gmail.com> +Link: https://lore.kernel.org/r/20241107163223.2092690-2-ezulian@redhat.com +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + include/linux/spinlock_rt.h | 15 +++++++-------- + rust/helpers/spinlock.c | 8 ++++++-- + 2 files changed, 13 insertions(+), 10 deletions(-) + +diff --git a/include/linux/spinlock_rt.h b/include/linux/spinlock_rt.h +index babc3e0287791..6175cd682ca0d 100644 +--- a/include/linux/spinlock_rt.h ++++ b/include/linux/spinlock_rt.h +@@ -16,22 +16,21 @@ static inline void __rt_spin_lock_init(spinlock_t *lock, const char *name, + } + #endif + +-#define spin_lock_init(slock) \ ++#define __spin_lock_init(slock, name, key, percpu) \ + do { \ +- static struct lock_class_key __key; \ +- \ + rt_mutex_base_init(&(slock)->lock); \ +- __rt_spin_lock_init(slock, #slock, &__key, false); \ ++ __rt_spin_lock_init(slock, name, key, percpu); \ + } while (0) + +-#define local_spin_lock_init(slock) \ ++#define _spin_lock_init(slock, percpu) \ + do { \ + static struct lock_class_key __key; \ +- \ +- rt_mutex_base_init(&(slock)->lock); \ +- __rt_spin_lock_init(slock, #slock, &__key, true); \ ++ __spin_lock_init(slock, #slock, &__key, percpu); \ + } while (0) + ++#define spin_lock_init(slock) _spin_lock_init(slock, false) ++#define local_spin_lock_init(slock) _spin_lock_init(slock, true) ++ + extern void rt_spin_lock(spinlock_t *lock) __acquires(lock); + extern void rt_spin_lock_nested(spinlock_t *lock, int subclass) __acquires(lock); + extern void rt_spin_lock_nest_lock(spinlock_t *lock, struct lockdep_map *nest_lock) __acquires(lock); +diff --git a/rust/helpers/spinlock.c b/rust/helpers/spinlock.c +index acc1376b833c7..92f7fc4184253 100644 +--- a/rust/helpers/spinlock.c ++++ b/rust/helpers/spinlock.c +@@ -7,10 +7,14 @@ void rust_helper___spin_lock_init(spinlock_t *lock, const char *name, + struct lock_class_key *key) + { + #ifdef CONFIG_DEBUG_SPINLOCK ++# if defined(CONFIG_PREEMPT_RT) ++ __spin_lock_init(lock, name, key, false); ++# else /*!CONFIG_PREEMPT_RT */ + __raw_spin_lock_init(spinlock_check(lock), name, key, LD_WAIT_CONFIG); +-#else ++# endif /* CONFIG_PREEMPT_RT */ ++#else /* !CONFIG_DEBUG_SPINLOCK */ + spin_lock_init(lock); +-#endif ++#endif /* CONFIG_DEBUG_SPINLOCK */ + } + + void rust_helper_spin_lock(spinlock_t *lock) +-- +2.43.0 + diff --git a/queue-6.12/rust-kernel-fix-this_module-header-path-in-thismodul.patch b/queue-6.12/rust-kernel-fix-this_module-header-path-in-thismodul.patch new file mode 100644 index 00000000000..48f2f3fa3c7 --- /dev/null +++ b/queue-6.12/rust-kernel-fix-this_module-header-path-in-thismodul.patch @@ -0,0 +1,44 @@ +From 5af38abe12c7c52085835f2e8ede62ccecce87da Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Mon, 21 Oct 2024 11:58:47 +0900 +Subject: rust: kernel: fix THIS_MODULE header path in ThisModule doc comment + +From: Yutaro Ohno <yutaro.ono.418@gmail.com> + +[ Upstream commit 8b55dc8610acf816a66373be53ca6e3bbe2d313a ] + +The doc comment for `ThisModule` incorrectly states the C header file +for `THIS_MODULE` as `include/linux/export.h`, while the correct path is +`include/linux/init.h`. This is because `THIS_MODULE` was moved in +commit 5b20755b7780 ("init: move THIS_MODULE from <linux/export.h> to +<linux/init.h>"). + +Update the doc comment for `ThisModule` to reflect the correct header +file path for `THIS_MODULE`. + +Fixes: 5b20755b7780 ("init: move THIS_MODULE from <linux/export.h> to <linux/init.h>") +Signed-off-by: Yutaro Ohno <yutaro.ono.418@gmail.com> +Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +Link: https://lore.kernel.org/r/ZxXDZwxWgoEiIYkj@ohnotp +Signed-off-by: Miguel Ojeda <ojeda@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + rust/kernel/lib.rs | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs +index b5f4b3ce6b482..032c9089e6862 100644 +--- a/rust/kernel/lib.rs ++++ b/rust/kernel/lib.rs +@@ -83,7 +83,7 @@ pub trait Module: Sized + Sync + Send { + + /// Equivalent to `THIS_MODULE` in the C API. + /// +-/// C header: [`include/linux/export.h`](srctree/include/linux/export.h) ++/// C header: [`include/linux/init.h`](srctree/include/linux/init.h) + pub struct ThisModule(*mut bindings::module); + + // SAFETY: `THIS_MODULE` may be used from all threads within a module. +-- +2.43.0 + diff --git a/queue-6.12/rust-macros-fix-documentation-of-the-paste-macro.patch b/queue-6.12/rust-macros-fix-documentation-of-the-paste-macro.patch new file mode 100644 index 00000000000..328eb5f68a2 --- /dev/null +++ b/queue-6.12/rust-macros-fix-documentation-of-the-paste-macro.patch @@ -0,0 +1,38 @@ +From 7f1d8251df35a9fd86f2978b774f456b6ccb3e90 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Sat, 19 Oct 2024 09:22:08 +0200 +Subject: rust: macros: fix documentation of the paste! macro + +From: Paolo Bonzini <pbonzini@redhat.com> + +[ Upstream commit 15541c9263ce34ff95a06bc68f45d9bc5c990bcd ] + +One of the example in this section uses a curious mix of the constant +and function declaration syntaxes; fix it. + +Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> +Reviewed-by: Alice Ryhl <aliceryhl@google.com> +Fixes: 823d4737d4c2 ("rust: macros: add `paste!` proc macro") +Link: https://lore.kernel.org/r/20241019072208.1016707-1-pbonzini@redhat.com +Signed-off-by: Miguel Ojeda <ojeda@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + rust/macros/lib.rs | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/rust/macros/lib.rs b/rust/macros/lib.rs +index a626b1145e5c4..90e2202ba4d5a 100644 +--- a/rust/macros/lib.rs ++++ b/rust/macros/lib.rs +@@ -359,7 +359,7 @@ pub fn pinned_drop(args: TokenStream, input: TokenStream) -> TokenStream { + /// macro_rules! pub_no_prefix { + /// ($prefix:ident, $($newname:ident),+) => { + /// kernel::macros::paste! { +-/// $(pub(crate) const fn [<$newname:lower:span>]: u32 = [<$prefix $newname:span>];)+ ++/// $(pub(crate) const fn [<$newname:lower:span>]() -> u32 { [<$prefix $newname:span>] })+ + /// } + /// }; + /// } +-- +2.43.0 + diff --git a/queue-6.12/rust-rbtree-fix-safety-comments-that-should-be-safet.patch b/queue-6.12/rust-rbtree-fix-safety-comments-that-should-be-safet.patch new file mode 100644 index 00000000000..6d7ea52d7ef --- /dev/null +++ b/queue-6.12/rust-rbtree-fix-safety-comments-that-should-be-safet.patch @@ -0,0 +1,67 @@ +From 1191ea7186a652ddb6670ecbc54e681036618b6a Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Wed, 4 Sep 2024 22:43:41 +0200 +Subject: rust: rbtree: fix `SAFETY` comments that should be `# Safety` + sections + +From: Miguel Ojeda <ojeda@kernel.org> + +[ Upstream commit 8333ff4d0799aafbe4275cddcbaf45e545e4efba ] + +The tag `SAFETY` is used for safety comments, i.e. `// SAFETY`, while a +`Safety` section is used for safety preconditions in code documentation, +i.e. `/// # Safety`. + +Fix the three instances recently added in `rbtree` that Clippy would +have normally caught in a public item, so that we can enable checking +of private items in one of the following commits. + +Fixes: 98c14e40e07a ("rust: rbtree: add cursor") +Reviewed-by: Trevor Gross <tmgross@umich.edu> +Reviewed-by: Alice Ryhl <aliceryhl@google.com> +Tested-by: Gary Guo <gary@garyguo.net> +Reviewed-by: Gary Guo <gary@garyguo.net> +Link: https://lore.kernel.org/r/20240904204347.168520-14-ojeda@kernel.org +Signed-off-by: Miguel Ojeda <ojeda@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + rust/kernel/rbtree.rs | 9 ++++++--- + 1 file changed, 6 insertions(+), 3 deletions(-) + +diff --git a/rust/kernel/rbtree.rs b/rust/kernel/rbtree.rs +index 25eb36fd1cdce..d03e4aa1f4812 100644 +--- a/rust/kernel/rbtree.rs ++++ b/rust/kernel/rbtree.rs +@@ -884,7 +884,8 @@ fn get_neighbor_raw(&self, direction: Direction) -> Option<NonNull<bindings::rb_ + NonNull::new(neighbor) + } + +- /// SAFETY: ++ /// # Safety ++ /// + /// - `node` must be a valid pointer to a node in an [`RBTree`]. + /// - The caller has immutable access to `node` for the duration of 'b. + unsafe fn to_key_value<'b>(node: NonNull<bindings::rb_node>) -> (&'b K, &'b V) { +@@ -894,7 +895,8 @@ unsafe fn to_key_value<'b>(node: NonNull<bindings::rb_node>) -> (&'b K, &'b V) { + (k, unsafe { &*v }) + } + +- /// SAFETY: ++ /// # Safety ++ /// + /// - `node` must be a valid pointer to a node in an [`RBTree`]. + /// - The caller has mutable access to `node` for the duration of 'b. + unsafe fn to_key_value_mut<'b>(node: NonNull<bindings::rb_node>) -> (&'b K, &'b mut V) { +@@ -904,7 +906,8 @@ unsafe fn to_key_value_mut<'b>(node: NonNull<bindings::rb_node>) -> (&'b K, &'b + (k, unsafe { &mut *v }) + } + +- /// SAFETY: ++ /// # Safety ++ /// + /// - `node` must be a valid pointer to a node in an [`RBTree`]. + /// - The caller has immutable access to the key for the duration of 'b. + unsafe fn to_key_value_raw<'b>(node: NonNull<bindings::rb_node>) -> (&'b K, *mut V) { +-- +2.43.0 + diff --git a/queue-6.12/rxrpc-improve-setsockopt-handling-of-malformed-user-.patch b/queue-6.12/rxrpc-improve-setsockopt-handling-of-malformed-user-.patch new file mode 100644 index 00000000000..0c99b5c9732 --- /dev/null +++ b/queue-6.12/rxrpc-improve-setsockopt-handling-of-malformed-user-.patch @@ -0,0 +1,47 @@ +From 91b2ec46a309592631955c3a4304a66f68ce3463 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Tue, 19 Nov 2024 14:31:42 +0100 +Subject: rxrpc: Improve setsockopt() handling of malformed user input + +From: Michal Luczaj <mhal@rbox.co> + +[ Upstream commit 02020056647017e70509bb58c3096448117099e1 ] + +copy_from_sockptr() does not return negative value on error; instead, it +reports the number of bytes that failed to copy. Since it's deprecated, +switch to copy_safe_from_sockptr(). + +Note: Keeping the `optlen != sizeof(unsigned int)` check as +copy_safe_from_sockptr() by itself would also accept +optlen > sizeof(unsigned int). Which would allow a more lenient handling +of inputs. + +Fixes: 17926a79320a ("[AF_RXRPC]: Provide secure RxRPC sockets for use by userspace and kernel both") +Signed-off-by: Michal Luczaj <mhal@rbox.co> +Signed-off-by: Paolo Abeni <pabeni@redhat.com> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + net/rxrpc/af_rxrpc.c | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +diff --git a/net/rxrpc/af_rxrpc.c b/net/rxrpc/af_rxrpc.c +index f4844683e1203..9d8bd0b37e41d 100644 +--- a/net/rxrpc/af_rxrpc.c ++++ b/net/rxrpc/af_rxrpc.c +@@ -707,9 +707,10 @@ static int rxrpc_setsockopt(struct socket *sock, int level, int optname, + ret = -EISCONN; + if (rx->sk.sk_state != RXRPC_UNBOUND) + goto error; +- ret = copy_from_sockptr(&min_sec_level, optval, +- sizeof(unsigned int)); +- if (ret < 0) ++ ret = copy_safe_from_sockptr(&min_sec_level, ++ sizeof(min_sec_level), ++ optval, optlen); ++ if (ret) + goto error; + ret = -EINVAL; + if (min_sec_level > RXRPC_SECURITY_MAX) +-- +2.43.0 + diff --git a/queue-6.12/s390-cio-do-not-unregister-the-subchannel-based-on-d.patch b/queue-6.12/s390-cio-do-not-unregister-the-subchannel-based-on-d.patch new file mode 100644 index 00000000000..2139e6887f8 --- /dev/null +++ b/queue-6.12/s390-cio-do-not-unregister-the-subchannel-based-on-d.patch @@ -0,0 +1,112 @@ +From 071d8250b2577cb4ff2a43e62778858a42824195 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Mon, 23 Sep 2024 22:16:43 +0200 +Subject: s390/cio: Do not unregister the subchannel based on DNV + +From: Vineeth Vijayan <vneethv@linux.ibm.com> + +[ Upstream commit 8c58a229688ce3a097b3b1a2efe1b4f5508c2123 ] + +Starting with commit 2297791c92d0 ("s390/cio: dont unregister +subchannel from child-drivers"), CIO does not unregister subchannels +when the attached device is invalid or unavailable. Instead, it +allows subchannels to exist without a connected device. However, if +the DNV value is 0, such as, when all the CHPIDs of a subchannel are +configured in standby state, the subchannel is unregistered, which +contradicts the current subchannel specification. + +Update the logic so that subchannels are not unregistered based +on the DNV value. Also update the SCHIB information even if the +DNV bit is zero. + +Suggested-by: Peter Oberparleiter <oberpar@linux.ibm.com> +Signed-off-by: Vineeth Vijayan <vneethv@linux.ibm.com> +Fixes: 2297791c92d0 ("s390/cio: dont unregister subchannel from child-drivers") +Reviewed-by: Peter Oberparleiter <oberpar@linux.ibm.com> +Signed-off-by: Heiko Carstens <hca@linux.ibm.com> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/s390/cio/cio.c | 6 +++++- + drivers/s390/cio/device.c | 18 +++++++++++++++++- + 2 files changed, 22 insertions(+), 2 deletions(-) + +diff --git a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c +index c32e818f06dba..ad17ab0a93149 100644 +--- a/drivers/s390/cio/cio.c ++++ b/drivers/s390/cio/cio.c +@@ -459,10 +459,14 @@ int cio_update_schib(struct subchannel *sch) + { + struct schib schib; + +- if (stsch(sch->schid, &schib) || !css_sch_is_valid(&schib)) ++ if (stsch(sch->schid, &schib)) + return -ENODEV; + + memcpy(&sch->schib, &schib, sizeof(schib)); ++ ++ if (!css_sch_is_valid(&schib)) ++ return -EACCES; ++ + return 0; + } + EXPORT_SYMBOL_GPL(cio_update_schib); +diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c +index b0f23242e1714..9498825d9c7a5 100644 +--- a/drivers/s390/cio/device.c ++++ b/drivers/s390/cio/device.c +@@ -1387,14 +1387,18 @@ enum io_sch_action { + IO_SCH_VERIFY, + IO_SCH_DISC, + IO_SCH_NOP, ++ IO_SCH_ORPH_CDEV, + }; + + static enum io_sch_action sch_get_action(struct subchannel *sch) + { + struct ccw_device *cdev; ++ int rc; + + cdev = sch_get_cdev(sch); +- if (cio_update_schib(sch)) { ++ rc = cio_update_schib(sch); ++ ++ if (rc == -ENODEV) { + /* Not operational. */ + if (!cdev) + return IO_SCH_UNREG; +@@ -1402,6 +1406,16 @@ static enum io_sch_action sch_get_action(struct subchannel *sch) + return IO_SCH_UNREG; + return IO_SCH_ORPH_UNREG; + } ++ ++ /* Avoid unregistering subchannels without working device. */ ++ if (rc == -EACCES) { ++ if (!cdev) ++ return IO_SCH_NOP; ++ if (ccw_device_notify(cdev, CIO_GONE) != NOTIFY_OK) ++ return IO_SCH_UNREG_CDEV; ++ return IO_SCH_ORPH_CDEV; ++ } ++ + /* Operational. */ + if (!cdev) + return IO_SCH_ATTACH; +@@ -1471,6 +1485,7 @@ static int io_subchannel_sch_event(struct subchannel *sch, int process) + rc = 0; + goto out_unlock; + case IO_SCH_ORPH_UNREG: ++ case IO_SCH_ORPH_CDEV: + case IO_SCH_ORPH_ATTACH: + ccw_device_set_disconnected(cdev); + break; +@@ -1502,6 +1517,7 @@ static int io_subchannel_sch_event(struct subchannel *sch, int process) + /* Handle attached ccw device. */ + switch (action) { + case IO_SCH_ORPH_UNREG: ++ case IO_SCH_ORPH_CDEV: + case IO_SCH_ORPH_ATTACH: + /* Move ccw device to orphanage. */ + rc = ccw_device_move_to_orph(cdev); +-- +2.43.0 + diff --git a/queue-6.12/s390-cpum_sf-fix-and-protect-memory-allocation-of-sd.patch b/queue-6.12/s390-cpum_sf-fix-and-protect-memory-allocation-of-sd.patch new file mode 100644 index 00000000000..5387aa77e60 --- /dev/null +++ b/queue-6.12/s390-cpum_sf-fix-and-protect-memory-allocation-of-sd.patch @@ -0,0 +1,55 @@ +From f4da5be665eef6be1067f7176a931f7f5d9f142a Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Wed, 30 Oct 2024 12:37:18 +0100 +Subject: s390/cpum_sf: Fix and protect memory allocation of SDBs with mutex + +From: Thomas Richter <tmricht@linux.ibm.com> + +[ Upstream commit f55bd479d8663a4a4e403b3d308d3d1aa33d92df ] + +Reservation of the PMU hardware is done at first event creation +and is protected by a pair of mutex_lock() and mutex_unlock(). +After reservation of the PMU hardware the memory +required for the PMUs the event is to be installed on is +allocated by allocate_buffers() and alloc_sampling_buffer(). +This done outside of the mutex protection. +Without mutex protection two or more concurrent invocations of +perf_event_init() may run in parallel. +This can lead to allocation of Sample Data Blocks (SDBs) +multiple times for the same PMU. +Prevent this and protect memory allocation of SDBs by +mutex. + +Fixes: 8a6fe8f21ec4 ("s390/cpum_sf: Use refcount_t instead of atomic_t") +Signed-off-by: Thomas Richter <tmricht@linux.ibm.com> +Reviewed-by: Sumanth Korikkar <sumanthk@linux.ibm.com> +Reviewed-by: Hendrik Brueckner <brueckner@linux.ibm.com> +Signed-off-by: Heiko Carstens <hca@linux.ibm.com> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + arch/s390/kernel/perf_cpum_sf.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/arch/s390/kernel/perf_cpum_sf.c b/arch/s390/kernel/perf_cpum_sf.c +index 5b765e3ccf0ca..3317f4878eaa7 100644 +--- a/arch/s390/kernel/perf_cpum_sf.c ++++ b/arch/s390/kernel/perf_cpum_sf.c +@@ -759,7 +759,6 @@ static int __hw_perf_event_init(struct perf_event *event) + reserve_pmc_hardware(); + refcount_set(&num_events, 1); + } +- mutex_unlock(&pmc_reserve_mutex); + event->destroy = hw_perf_event_destroy; + + /* Access per-CPU sampling information (query sampling info) */ +@@ -848,6 +847,7 @@ static int __hw_perf_event_init(struct perf_event *event) + if (is_default_overflow_handler(event)) + event->overflow_handler = cpumsf_output_event_pid; + out: ++ mutex_unlock(&pmc_reserve_mutex); + return err; + } + +-- +2.43.0 + diff --git a/queue-6.12/s390-facilities-fix-warning-about-shadow-of-global-v.patch b/queue-6.12/s390-facilities-fix-warning-about-shadow-of-global-v.patch new file mode 100644 index 00000000000..5cb3a49d335 --- /dev/null +++ b/queue-6.12/s390-facilities-fix-warning-about-shadow-of-global-v.patch @@ -0,0 +1,86 @@ +From b3cc12d609153ba2e78921d763650f13e4f54256 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Thu, 26 Sep 2024 17:37:06 +0200 +Subject: s390/facilities: Fix warning about shadow of global variable + +From: Gerd Bayer <gbayer@linux.ibm.com> + +[ Upstream commit 61997c1e947dbf8bc625ef86ceee00fdf2a5dba1 ] + +Compiling the kernel with clang W=2 produces a warning that the +parameter declarations in some routines would shadow the definition of +the global variable stfle_fac_list. Address this warning by renaming the +parameters to fac_list. + +Fixes: 17e89e1340a3 ("s390/facilities: move stfl information from lowcore to global data") +Signed-off-by: Gerd Bayer <gbayer@linux.ibm.com> +Signed-off-by: Heiko Carstens <hca@linux.ibm.com> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + arch/s390/include/asm/facility.h | 18 +++++++++--------- + 1 file changed, 9 insertions(+), 9 deletions(-) + +diff --git a/arch/s390/include/asm/facility.h b/arch/s390/include/asm/facility.h +index 715bcf8fb69a5..5f5b1aa6c2331 100644 +--- a/arch/s390/include/asm/facility.h ++++ b/arch/s390/include/asm/facility.h +@@ -88,7 +88,7 @@ static __always_inline bool test_facility(unsigned long nr) + return __test_facility(nr, &stfle_fac_list); + } + +-static inline unsigned long __stfle_asm(u64 *stfle_fac_list, int size) ++static inline unsigned long __stfle_asm(u64 *fac_list, int size) + { + unsigned long reg0 = size - 1; + +@@ -96,7 +96,7 @@ static inline unsigned long __stfle_asm(u64 *stfle_fac_list, int size) + " lgr 0,%[reg0]\n" + " .insn s,0xb2b00000,%[list]\n" /* stfle */ + " lgr %[reg0],0\n" +- : [reg0] "+&d" (reg0), [list] "+Q" (*stfle_fac_list) ++ : [reg0] "+&d" (reg0), [list] "+Q" (*fac_list) + : + : "memory", "cc", "0"); + return reg0; +@@ -104,10 +104,10 @@ static inline unsigned long __stfle_asm(u64 *stfle_fac_list, int size) + + /** + * stfle - Store facility list extended +- * @stfle_fac_list: array where facility list can be stored ++ * @fac_list: array where facility list can be stored + * @size: size of passed in array in double words + */ +-static inline void __stfle(u64 *stfle_fac_list, int size) ++static inline void __stfle(u64 *fac_list, int size) + { + unsigned long nr; + u32 stfl_fac_list; +@@ -116,20 +116,20 @@ static inline void __stfle(u64 *stfle_fac_list, int size) + " stfl 0(0)\n" + : "=m" (get_lowcore()->stfl_fac_list)); + stfl_fac_list = get_lowcore()->stfl_fac_list; +- memcpy(stfle_fac_list, &stfl_fac_list, 4); ++ memcpy(fac_list, &stfl_fac_list, 4); + nr = 4; /* bytes stored by stfl */ + if (stfl_fac_list & 0x01000000) { + /* More facility bits available with stfle */ +- nr = __stfle_asm(stfle_fac_list, size); ++ nr = __stfle_asm(fac_list, size); + nr = min_t(unsigned long, (nr + 1) * 8, size * 8); + } +- memset((char *) stfle_fac_list + nr, 0, size * 8 - nr); ++ memset((char *)fac_list + nr, 0, size * 8 - nr); + } + +-static inline void stfle(u64 *stfle_fac_list, int size) ++static inline void stfle(u64 *fac_list, int size) + { + preempt_disable(); +- __stfle(stfle_fac_list, size); ++ __stfle(fac_list, size); + preempt_enable(); + } + +-- +2.43.0 + diff --git a/queue-6.12/s390-iucv-msg_peek-causes-memory-leak-in-iucv_sock_d.patch b/queue-6.12/s390-iucv-msg_peek-causes-memory-leak-in-iucv_sock_d.patch new file mode 100644 index 00000000000..d398d6c2d89 --- /dev/null +++ b/queue-6.12/s390-iucv-msg_peek-causes-memory-leak-in-iucv_sock_d.patch @@ -0,0 +1,113 @@ +From 18223e6efd5661a839434dcaecc5ea8397f75538 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Tue, 19 Nov 2024 16:22:19 +0100 +Subject: s390/iucv: MSG_PEEK causes memory leak in iucv_sock_destruct() + +From: Sidraya Jayagond <sidraya@linux.ibm.com> + +[ Upstream commit ebaf81317e42aa990ad20b113cfe3a7b20d4e937 ] + +Passing MSG_PEEK flag to skb_recv_datagram() increments skb refcount +(skb->users) and iucv_sock_recvmsg() does not decrement skb refcount +at exit. +This results in skb memory leak in skb_queue_purge() and WARN_ON in +iucv_sock_destruct() during socket close. To fix this decrease +skb refcount by one if MSG_PEEK is set in order to prevent memory +leak and WARN_ON. + +WARNING: CPU: 2 PID: 6292 at net/iucv/af_iucv.c:286 iucv_sock_destruct+0x144/0x1a0 [af_iucv] +CPU: 2 PID: 6292 Comm: afiucv_test_msg Kdump: loaded Tainted: G W 6.10.0-rc7 #1 +Hardware name: IBM 3931 A01 704 (z/VM 7.3.0) +Call Trace: + [<001587c682c4aa98>] iucv_sock_destruct+0x148/0x1a0 [af_iucv] + [<001587c682c4a9d0>] iucv_sock_destruct+0x80/0x1a0 [af_iucv] + [<001587c704117a32>] __sk_destruct+0x52/0x550 + [<001587c704104a54>] __sock_release+0xa4/0x230 + [<001587c704104c0c>] sock_close+0x2c/0x40 + [<001587c702c5f5a8>] __fput+0x2e8/0x970 + [<001587c7024148c4>] task_work_run+0x1c4/0x2c0 + [<001587c7023b0716>] do_exit+0x996/0x1050 + [<001587c7023b13aa>] do_group_exit+0x13a/0x360 + [<001587c7023b1626>] __s390x_sys_exit_group+0x56/0x60 + [<001587c7022bccca>] do_syscall+0x27a/0x380 + [<001587c7049a6a0c>] __do_syscall+0x9c/0x160 + [<001587c7049ce8a8>] system_call+0x70/0x98 + Last Breaking-Event-Address: + [<001587c682c4a9d4>] iucv_sock_destruct+0x84/0x1a0 [af_iucv] + +Fixes: eac3731bd04c ("[S390]: Add AF_IUCV socket support") +Reviewed-by: Alexandra Winter <wintera@linux.ibm.com> +Reviewed-by: Thorsten Winkler <twinkler@linux.ibm.com> +Signed-off-by: Sidraya Jayagond <sidraya@linux.ibm.com> +Signed-off-by: Alexandra Winter <wintera@linux.ibm.com> +Reviewed-by: David Wei <dw@davidwei.uk> +Link: https://patch.msgid.link/20241119152219.3712168-1-wintera@linux.ibm.com +Signed-off-by: Paolo Abeni <pabeni@redhat.com> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + net/iucv/af_iucv.c | 26 +++++++++++++++++--------- + 1 file changed, 17 insertions(+), 9 deletions(-) + +diff --git a/net/iucv/af_iucv.c b/net/iucv/af_iucv.c +index c00323fa9eb66..7929df08d4e02 100644 +--- a/net/iucv/af_iucv.c ++++ b/net/iucv/af_iucv.c +@@ -1236,7 +1236,9 @@ static int iucv_sock_recvmsg(struct socket *sock, struct msghdr *msg, + return -EOPNOTSUPP; + + /* receive/dequeue next skb: +- * the function understands MSG_PEEK and, thus, does not dequeue skb */ ++ * the function understands MSG_PEEK and, thus, does not dequeue skb ++ * only refcount is increased. ++ */ + skb = skb_recv_datagram(sk, flags, &err); + if (!skb) { + if (sk->sk_shutdown & RCV_SHUTDOWN) +@@ -1252,9 +1254,8 @@ static int iucv_sock_recvmsg(struct socket *sock, struct msghdr *msg, + + cskb = skb; + if (skb_copy_datagram_msg(cskb, offset, msg, copied)) { +- if (!(flags & MSG_PEEK)) +- skb_queue_head(&sk->sk_receive_queue, skb); +- return -EFAULT; ++ err = -EFAULT; ++ goto err_out; + } + + /* SOCK_SEQPACKET: set MSG_TRUNC if recv buf size is too small */ +@@ -1271,11 +1272,8 @@ static int iucv_sock_recvmsg(struct socket *sock, struct msghdr *msg, + err = put_cmsg(msg, SOL_IUCV, SCM_IUCV_TRGCLS, + sizeof(IUCV_SKB_CB(skb)->class), + (void *)&IUCV_SKB_CB(skb)->class); +- if (err) { +- if (!(flags & MSG_PEEK)) +- skb_queue_head(&sk->sk_receive_queue, skb); +- return err; +- } ++ if (err) ++ goto err_out; + + /* Mark read part of skb as used */ + if (!(flags & MSG_PEEK)) { +@@ -1331,8 +1329,18 @@ static int iucv_sock_recvmsg(struct socket *sock, struct msghdr *msg, + /* SOCK_SEQPACKET: return real length if MSG_TRUNC is set */ + if (sk->sk_type == SOCK_SEQPACKET && (flags & MSG_TRUNC)) + copied = rlen; ++ if (flags & MSG_PEEK) ++ skb_unref(skb); + + return copied; ++ ++err_out: ++ if (!(flags & MSG_PEEK)) ++ skb_queue_head(&sk->sk_receive_queue, skb); ++ else ++ skb_unref(skb); ++ ++ return err; + } + + static inline __poll_t iucv_accept_poll(struct sock *parent) +-- +2.43.0 + diff --git a/queue-6.12/s390-pageattr-implement-missing-kernel_page_present.patch b/queue-6.12/s390-pageattr-implement-missing-kernel_page_present.patch new file mode 100644 index 00000000000..3c26dc65a30 --- /dev/null +++ b/queue-6.12/s390-pageattr-implement-missing-kernel_page_present.patch @@ -0,0 +1,68 @@ +From 653cc1e0d21e0d4a99040d91968fefb9ca5ef3be Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Fri, 18 Oct 2024 14:26:23 +0200 +Subject: s390/pageattr: Implement missing kernel_page_present() + +From: Heiko Carstens <hca@linux.ibm.com> + +[ Upstream commit 2835f8bf5530750c3381166005934f996a83ad05 ] + +kernel_page_present() was intentionally not implemented when adding +ARCH_HAS_SET_DIRECT_MAP support, since it was only used for suspend/resume +which is not supported anymore on s390. + +A new bpf use case led to a compile error specific to s390. Even though +this specific use case went away implement kernel_page_present(), so that +the API is complete and potential future users won't run into this problem. + +Reported-by: Daniel Borkmann <daniel@iogearbox.net> +Closes: https://lore.kernel.org/all/045de961-ac69-40cc-b141-ab70ec9377ec@iogearbox.net +Fixes: 0490d6d7ba0a ("s390/mm: enable ARCH_HAS_SET_DIRECT_MAP") +Reviewed-by: Alexander Gordeev <agordeev@linux.ibm.com> +Signed-off-by: Heiko Carstens <hca@linux.ibm.com> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + arch/s390/include/asm/set_memory.h | 1 + + arch/s390/mm/pageattr.c | 15 +++++++++++++++ + 2 files changed, 16 insertions(+) + +diff --git a/arch/s390/include/asm/set_memory.h b/arch/s390/include/asm/set_memory.h +index 06fbabe2f66c9..cb4cc0f59012f 100644 +--- a/arch/s390/include/asm/set_memory.h ++++ b/arch/s390/include/asm/set_memory.h +@@ -62,5 +62,6 @@ __SET_MEMORY_FUNC(set_memory_4k, SET_MEMORY_4K) + + int set_direct_map_invalid_noflush(struct page *page); + int set_direct_map_default_noflush(struct page *page); ++bool kernel_page_present(struct page *page); + + #endif +diff --git a/arch/s390/mm/pageattr.c b/arch/s390/mm/pageattr.c +index 5f805ad42d4c3..aec9eb16b6f7b 100644 +--- a/arch/s390/mm/pageattr.c ++++ b/arch/s390/mm/pageattr.c +@@ -406,6 +406,21 @@ int set_direct_map_default_noflush(struct page *page) + return __set_memory((unsigned long)page_to_virt(page), 1, SET_MEMORY_DEF); + } + ++bool kernel_page_present(struct page *page) ++{ ++ unsigned long addr; ++ unsigned int cc; ++ ++ addr = (unsigned long)page_address(page); ++ asm volatile( ++ " lra %[addr],0(%[addr])\n" ++ " ipm %[cc]\n" ++ : [cc] "=d" (cc), [addr] "+a" (addr) ++ : ++ : "cc"); ++ return (cc >> 28) == 0; ++} ++ + #if defined(CONFIG_DEBUG_PAGEALLOC) || defined(CONFIG_KFENCE) + + static void ipte_range(pte_t *pte, unsigned long address, int nr) +-- +2.43.0 + diff --git a/queue-6.12/s390-pci-fix-potential-double-remove-of-hotplug-slot.patch b/queue-6.12/s390-pci-fix-potential-double-remove-of-hotplug-slot.patch new file mode 100644 index 00000000000..232e7e40cec --- /dev/null +++ b/queue-6.12/s390-pci-fix-potential-double-remove-of-hotplug-slot.patch @@ -0,0 +1,94 @@ +From 47da24c619cb6c89ab9b2671ec108ffe31b27956 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Mon, 25 Nov 2024 16:02:38 +0100 +Subject: s390/pci: Fix potential double remove of hotplug slot + +From: Niklas Schnelle <schnelle@linux.ibm.com> + +[ Upstream commit c4a585e952ca403a370586d3f16e8331a7564901 ] + +In commit 6ee600bfbe0f ("s390/pci: remove hotplug slot when releasing the +device") the zpci_exit_slot() was moved from zpci_device_reserved() to +zpci_release_device() with the intention of keeping the hotplug slot +around until the device is actually removed. + +Now zpci_release_device() is only called once all references are +dropped. Since the zPCI subsystem only drops its reference once the +device is in the reserved state it follows that zpci_release_device() +must only deal with devices in the reserved state. Despite that it +contains code to tear down from both configured and standby state. For +the standby case this already includes the removal of the hotplug slot +so would cause a double removal if a device was ever removed in +either configured or standby state. + +Instead of causing a potential double removal in a case that should +never happen explicitly WARN_ON() if a device in non-reserved state is +released and get rid of the dead code cases. + +Fixes: 6ee600bfbe0f ("s390/pci: remove hotplug slot when releasing the device") +Reviewed-by: Matthew Rosato <mjrosato@linux.ibm.com> +Reviewed-by: Gerd Bayer <gbayer@linux.ibm.com> +Tested-by: Gerd Bayer <gbayer@linux.ibm.com> +Signed-off-by: Niklas Schnelle <schnelle@linux.ibm.com> +Signed-off-by: Heiko Carstens <hca@linux.ibm.com> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + arch/s390/pci/pci.c | 34 +++++++++------------------------- + 1 file changed, 9 insertions(+), 25 deletions(-) + +diff --git a/arch/s390/pci/pci.c b/arch/s390/pci/pci.c +index be3299609f9b6..635fd8f2acbaa 100644 +--- a/arch/s390/pci/pci.c ++++ b/arch/s390/pci/pci.c +@@ -917,10 +917,8 @@ void zpci_device_reserved(struct zpci_dev *zdev) + void zpci_release_device(struct kref *kref) + { + struct zpci_dev *zdev = container_of(kref, struct zpci_dev, kref); +- int ret; + +- if (zdev->has_hp_slot) +- zpci_exit_slot(zdev); ++ WARN_ON(zdev->state != ZPCI_FN_STATE_RESERVED); + + if (zdev->zbus->bus) + zpci_bus_remove_device(zdev, false); +@@ -928,28 +926,14 @@ void zpci_release_device(struct kref *kref) + if (zdev_enabled(zdev)) + zpci_disable_device(zdev); + +- switch (zdev->state) { +- case ZPCI_FN_STATE_CONFIGURED: +- ret = sclp_pci_deconfigure(zdev->fid); +- zpci_dbg(3, "deconf fid:%x, rc:%d\n", zdev->fid, ret); +- fallthrough; +- case ZPCI_FN_STATE_STANDBY: +- if (zdev->has_hp_slot) +- zpci_exit_slot(zdev); +- spin_lock(&zpci_list_lock); +- list_del(&zdev->entry); +- spin_unlock(&zpci_list_lock); +- zpci_dbg(3, "rsv fid:%x\n", zdev->fid); +- fallthrough; +- case ZPCI_FN_STATE_RESERVED: +- if (zdev->has_resources) +- zpci_cleanup_bus_resources(zdev); +- zpci_bus_device_unregister(zdev); +- zpci_destroy_iommu(zdev); +- fallthrough; +- default: +- break; +- } ++ if (zdev->has_hp_slot) ++ zpci_exit_slot(zdev); ++ ++ if (zdev->has_resources) ++ zpci_cleanup_bus_resources(zdev); ++ ++ zpci_bus_device_unregister(zdev); ++ zpci_destroy_iommu(zdev); + zpci_dbg(3, "rem fid:%x\n", zdev->fid); + kfree_rcu(zdev, rcu); + } +-- +2.43.0 + diff --git a/queue-6.12/s390-syscalls-avoid-creation-of-arch-arch-directory.patch b/queue-6.12/s390-syscalls-avoid-creation-of-arch-arch-directory.patch new file mode 100644 index 00000000000..85282447c0a --- /dev/null +++ b/queue-6.12/s390-syscalls-avoid-creation-of-arch-arch-directory.patch @@ -0,0 +1,54 @@ +From 7a5ab666cbf690a8175d4a026cd87d98007c2a10 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Mon, 11 Nov 2024 22:45:52 +0900 +Subject: s390/syscalls: Avoid creation of arch/arch/ directory + +From: Masahiro Yamada <masahiroy@kernel.org> + +[ Upstream commit 0708967e2d56e370231fd07defa0d69f9ad125e8 ] + +Building the kernel with ARCH=s390 creates a weird arch/arch/ directory. + + $ find arch/arch + arch/arch + arch/arch/s390 + arch/arch/s390/include + arch/arch/s390/include/generated + arch/arch/s390/include/generated/asm + arch/arch/s390/include/generated/uapi + arch/arch/s390/include/generated/uapi/asm + +The root cause is 'targets' in arch/s390/kernel/syscalls/Makefile, +where the relative path is incorrect. + +Strictly speaking, 'targets' was not necessary in the first place +because this Makefile uses 'filechk' instead of 'if_changed'. + +However, this commit keeps it, as it will be useful when converting +'filechk' to 'if_changed' later. + +Fixes: 5c75824d915e ("s390/syscalls: add Makefile to generate system call header files") +Signed-off-by: Masahiro Yamada <masahiroy@kernel.org> +Link: https://lore.kernel.org/r/20241111134603.2063226-1-masahiroy@kernel.org +Signed-off-by: Heiko Carstens <hca@linux.ibm.com> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + arch/s390/kernel/syscalls/Makefile | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/arch/s390/kernel/syscalls/Makefile b/arch/s390/kernel/syscalls/Makefile +index 1bb78b9468e8a..e85c14f9058b9 100644 +--- a/arch/s390/kernel/syscalls/Makefile ++++ b/arch/s390/kernel/syscalls/Makefile +@@ -12,7 +12,7 @@ kapi-hdrs-y := $(kapi)/unistd_nr.h + uapi-hdrs-y := $(uapi)/unistd_32.h + uapi-hdrs-y += $(uapi)/unistd_64.h + +-targets += $(addprefix ../../../,$(gen-y) $(kapi-hdrs-y) $(uapi-hdrs-y)) ++targets += $(addprefix ../../../../,$(gen-y) $(kapi-hdrs-y) $(uapi-hdrs-y)) + + PHONY += kapi uapi + +-- +2.43.0 + diff --git a/queue-6.12/s390-virtio_ccw-fix-dma_parm-pointer-not-set-up.patch b/queue-6.12/s390-virtio_ccw-fix-dma_parm-pointer-not-set-up.patch new file mode 100644 index 00000000000..24862fa0641 --- /dev/null +++ b/queue-6.12/s390-virtio_ccw-fix-dma_parm-pointer-not-set-up.patch @@ -0,0 +1,64 @@ +From 60e5c449179c19389de7ea8b6fdfda78e93f94b1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Mon, 7 Oct 2024 22:10:30 +0200 +Subject: s390/virtio_ccw: Fix dma_parm pointer not set up + +From: Halil Pasic <pasic@linux.ibm.com> + +[ Upstream commit 14c7579376279e507e52bf022192b46097a55377 ] + +At least since commit 334304ac2bac ("dma-mapping: don't return errors +from dma_set_max_seg_size") setting up device.dma_parms is basically +mandated by the DMA API. As of now Channel (CCW) I/O in general does not +utilize the DMA API, except for virtio. For virtio-ccw however the +common virtio DMA infrastructure is such that most of the DMA stuff +hinges on the virtio parent device, which is a CCW device. + +So lets set up the dma_parms pointer for the CCW parent device and hope +for the best! + +Fixes: 334304ac2bac ("dma-mapping: don't return errors from dma_set_max_seg_size") +Reported-by: Marc Hartmayer <mhartmay@linux.ibm.com> +Reviewed-by: Eric Farman <farman@linux.ibm.com> +Reviewed-by: Cornelia Huck <cohuck@redhat.com> +Tested-by: Marc Hartmayer <mhartmay@linux.ibm.com> +Link: https://lore.kernel.org/r/20241007201030.204028-1-pasic@linux.ibm.com +Signed-off-by: Halil Pasic <pasic@linux.ibm.com> +Signed-off-by: Heiko Carstens <hca@linux.ibm.com> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/s390/virtio/virtio_ccw.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/drivers/s390/virtio/virtio_ccw.c b/drivers/s390/virtio/virtio_ccw.c +index 62eca9419ad76..21fa7ac849e5c 100644 +--- a/drivers/s390/virtio/virtio_ccw.c ++++ b/drivers/s390/virtio/virtio_ccw.c +@@ -58,6 +58,8 @@ struct virtio_ccw_device { + struct virtio_device vdev; + __u8 config[VIRTIO_CCW_CONFIG_SIZE]; + struct ccw_device *cdev; ++ /* we make cdev->dev.dma_parms point to this */ ++ struct device_dma_parameters dma_parms; + __u32 curr_io; + int err; + unsigned int revision; /* Transport revision */ +@@ -1303,6 +1305,7 @@ static int virtio_ccw_offline(struct ccw_device *cdev) + unregister_virtio_device(&vcdev->vdev); + spin_lock_irqsave(get_ccwdev_lock(cdev), flags); + dev_set_drvdata(&cdev->dev, NULL); ++ cdev->dev.dma_parms = NULL; + spin_unlock_irqrestore(get_ccwdev_lock(cdev), flags); + return 0; + } +@@ -1366,6 +1369,7 @@ static int virtio_ccw_online(struct ccw_device *cdev) + } + vcdev->vdev.dev.parent = &cdev->dev; + vcdev->cdev = cdev; ++ cdev->dev.dma_parms = &vcdev->dma_parms; + vcdev->dma_area = ccw_device_dma_zalloc(vcdev->cdev, + sizeof(*vcdev->dma_area), + &vcdev->dma_area_addr); +-- +2.43.0 + diff --git a/queue-6.12/sched-cpufreq-ensure-sd-is-rebuilt-for-eas-check.patch b/queue-6.12/sched-cpufreq-ensure-sd-is-rebuilt-for-eas-check.patch new file mode 100644 index 00000000000..e85abbc243a --- /dev/null +++ b/queue-6.12/sched-cpufreq-ensure-sd-is-rebuilt-for-eas-check.patch @@ -0,0 +1,44 @@ +From a55aa286b05273d59663a023e368e2e481e6d957 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Sat, 9 Nov 2024 00:24:14 +0000 +Subject: sched/cpufreq: Ensure sd is rebuilt for EAS check + +From: Christian Loehle <christian.loehle@arm.com> + +[ Upstream commit 70d8b6485b0bcd135b6699fc4252d2272818d1fb ] + +Ensure sugov_eas_rebuild_sd() is always called when sugov_init() +succeeds. The out goto initialized sugov without forcing the rebuild. + +Previously the missing call to sugov_eas_rebuild_sd() could lead to EAS +not being enabled on boot when it should have been, because it requires +all policies to be controlled by schedutil while they might not have +been initialized yet. + +Fixes: e7a1b32e43b1 ("cpufreq: Rebuild sched-domains when removing cpufreq driver") +Signed-off-by: Christian Loehle <christian.loehle@arm.com> +Link: https://patch.msgid.link/35e572d9-1152-406a-9e34-2525f7548af9@arm.com +Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + kernel/sched/cpufreq_schedutil.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/kernel/sched/cpufreq_schedutil.c b/kernel/sched/cpufreq_schedutil.c +index c6ba15388ea70..28c77904ea749 100644 +--- a/kernel/sched/cpufreq_schedutil.c ++++ b/kernel/sched/cpufreq_schedutil.c +@@ -783,9 +783,8 @@ static int sugov_init(struct cpufreq_policy *policy) + if (ret) + goto fail; + +- sugov_eas_rebuild_sd(); +- + out: ++ sugov_eas_rebuild_sd(); + mutex_unlock(&global_tunables_lock); + return 0; + +-- +2.43.0 + diff --git a/queue-6.12/sched-ext-remove-sched_fork-hack.patch b/queue-6.12/sched-ext-remove-sched_fork-hack.patch new file mode 100644 index 00000000000..5a139862e6d --- /dev/null +++ b/queue-6.12/sched-ext-remove-sched_fork-hack.patch @@ -0,0 +1,64 @@ +From 782162e40e46135b94a32aec60ed6b41678fc36b Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Mon, 28 Oct 2024 14:20:35 +0100 +Subject: sched/ext: Remove sched_fork() hack + +From: Thomas Gleixner <tglx@linutronix.de> + +[ Upstream commit 0f0d1b8e5010bfe1feeb4d78d137e41946a5370d ] + +Instead of solving the underlying problem of the double invocation of +__sched_fork() for idle tasks, sched-ext decided to hack around the issue +by partially clearing out the entity struct to preserve the already +enqueued node. A provided analysis and solution has been ignored for four +months. + +Now that someone else has taken care of cleaning it up, remove the +disgusting hack and clear out the full structure. Remove the comment in the +structure declaration as well, as there is no requirement for @node being +the last element anymore. + +Fixes: f0e1a0643a59 ("sched_ext: Implement BPF extensible scheduler class") +Signed-off-by: Thomas Gleixner <tglx@linutronix.de> +Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> +Acked-by: Tejun Heo <tj@kernel.org> +Link: https://lore.kernel.org/r/87ldy82wkc.ffs@tglx +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + include/linux/sched/ext.h | 1 - + kernel/sched/ext.c | 7 +------ + 2 files changed, 1 insertion(+), 7 deletions(-) + +diff --git a/include/linux/sched/ext.h b/include/linux/sched/ext.h +index 1ddbde64a31b4..2799e7284fff7 100644 +--- a/include/linux/sched/ext.h ++++ b/include/linux/sched/ext.h +@@ -199,7 +199,6 @@ struct sched_ext_entity { + #ifdef CONFIG_EXT_GROUP_SCHED + struct cgroup *cgrp_moving_from; + #endif +- /* must be the last field, see init_scx_entity() */ + struct list_head tasks_node; + }; + +diff --git a/kernel/sched/ext.c b/kernel/sched/ext.c +index 751d73d500e51..ecb88c5285447 100644 +--- a/kernel/sched/ext.c ++++ b/kernel/sched/ext.c +@@ -3567,12 +3567,7 @@ static void scx_ops_exit_task(struct task_struct *p) + + void init_scx_entity(struct sched_ext_entity *scx) + { +- /* +- * init_idle() calls this function again after fork sequence is +- * complete. Don't touch ->tasks_node as it's already linked. +- */ +- memset(scx, 0, offsetof(struct sched_ext_entity, tasks_node)); +- ++ memset(scx, 0, sizeof(*scx)); + INIT_LIST_HEAD(&scx->dsq_list.node); + RB_CLEAR_NODE(&scx->dsq_priq); + scx->sticky_cpu = -1; +-- +2.43.0 + diff --git a/queue-6.12/sched_ext-scx_bpf_dispatch_from_dsq_set_-are-allowed.patch b/queue-6.12/sched_ext-scx_bpf_dispatch_from_dsq_set_-are-allowed.patch new file mode 100644 index 00000000000..8d710d454da --- /dev/null +++ b/queue-6.12/sched_ext-scx_bpf_dispatch_from_dsq_set_-are-allowed.patch @@ -0,0 +1,38 @@ +From ff299bc04c11265b2a5d80d90fd76fd620c49291 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Sat, 9 Nov 2024 09:40:25 -1000 +Subject: sched_ext: scx_bpf_dispatch_from_dsq_set_*() are allowed from + unlocked context + +From: Tejun Heo <tj@kernel.org> + +[ Upstream commit 72b85bf6a7f6f6c38c39a1e5b04bc1da1bf5016e ] + +4c30f5ce4f7a ("sched_ext: Implement scx_bpf_dispatch[_vtime]_from_dsq()") +added four kfuncs for dispatching while iterating. They are allowed from the +dispatch and unlocked contexts but two of the kfuncs were only added in the +dispatch section. Add missing declarations in the unlocked section. + +Signed-off-by: Tejun Heo <tj@kernel.org> +Fixes: 4c30f5ce4f7a ("sched_ext: Implement scx_bpf_dispatch[_vtime]_from_dsq()") +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + kernel/sched/ext.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/kernel/sched/ext.c b/kernel/sched/ext.c +index ecb88c5285447..16613631543f1 100644 +--- a/kernel/sched/ext.c ++++ b/kernel/sched/ext.c +@@ -6473,6 +6473,8 @@ __bpf_kfunc_end_defs(); + + BTF_KFUNCS_START(scx_kfunc_ids_unlocked) + BTF_ID_FLAGS(func, scx_bpf_create_dsq, KF_SLEEPABLE) ++BTF_ID_FLAGS(func, scx_bpf_dispatch_from_dsq_set_slice) ++BTF_ID_FLAGS(func, scx_bpf_dispatch_from_dsq_set_vtime) + BTF_ID_FLAGS(func, scx_bpf_dispatch_from_dsq, KF_RCU) + BTF_ID_FLAGS(func, scx_bpf_dispatch_vtime_from_dsq, KF_RCU) + BTF_KFUNCS_END(scx_kfunc_ids_unlocked) +-- +2.43.0 + diff --git a/queue-6.12/scripts-kernel-doc-do-not-track-section-counter-acro.patch b/queue-6.12/scripts-kernel-doc-do-not-track-section-counter-acro.patch new file mode 100644 index 00000000000..adc5b616938 --- /dev/null +++ b/queue-6.12/scripts-kernel-doc-do-not-track-section-counter-acro.patch @@ -0,0 +1,54 @@ +From 0ff95fbc465532c77159658b79ecf9111334faad Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Tue, 8 Oct 2024 16:29:04 +0800 +Subject: scripts/kernel-doc: Do not track section counter across processed + files + +From: Chen-Yu Tsai <wenst@chromium.org> + +[ Upstream commit be9264110e4e874622d588a75daf930539fdf6ea ] + +The section counter tracks how many sections of kernel-doc were added. +The only real use of the counter value is to check if anything was +actually supposed to be output and give a warning is nothing is +available. + +The current logic of remembering the initial value and then resetting +the value then when processing each file means that if a file has the +same number of sections as the previously processed one, a warning is +incorrectly given. + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Signed-off-by: Chen-Yu Tsai <wenst@chromium.org> +Signed-off-by: Jonathan Corbet <corbet@lwn.net> +Link: https://lore.kernel.org/r/20241008082905.4005524-1-wenst@chromium.org +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + scripts/kernel-doc | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +diff --git a/scripts/kernel-doc b/scripts/kernel-doc +index 2791f81952038..c608820f0bf51 100755 +--- a/scripts/kernel-doc ++++ b/scripts/kernel-doc +@@ -2322,7 +2322,6 @@ sub process_inline($$) { + + sub process_file($) { + my $file; +- my $initial_section_counter = $section_counter; + my ($orig_file) = @_; + + $file = map_filename($orig_file); +@@ -2360,8 +2359,7 @@ sub process_file($) { + } + + # Make sure we got something interesting. +- if ($initial_section_counter == $section_counter && $ +- output_mode ne "none") { ++ if (!$section_counter && $output_mode ne "none") { + if ($output_selection == OUTPUT_INCLUDE) { + emit_warning("${file}:1", "'$_' not found\n") + for keys %function_table; +-- +2.43.0 + diff --git a/queue-6.12/scsi-bfa-fix-use-after-free-in-bfad_im_module_exit.patch b/queue-6.12/scsi-bfa-fix-use-after-free-in-bfad_im_module_exit.patch new file mode 100644 index 00000000000..1e898b56198 --- /dev/null +++ b/queue-6.12/scsi-bfa-fix-use-after-free-in-bfad_im_module_exit.patch @@ -0,0 +1,109 @@ +From 06497fc5a6beca79e8f2d28293f88d3c74a58d80 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Wed, 23 Oct 2024 09:18:09 +0800 +Subject: scsi: bfa: Fix use-after-free in bfad_im_module_exit() + +From: Ye Bin <yebin10@huawei.com> + +[ Upstream commit 178b8f38932d635e90f5f0e9af1986c6f4a89271 ] + +BUG: KASAN: slab-use-after-free in __lock_acquire+0x2aca/0x3a20 +Read of size 8 at addr ffff8881082d80c8 by task modprobe/25303 + +Call Trace: + <TASK> + dump_stack_lvl+0x95/0xe0 + print_report+0xcb/0x620 + kasan_report+0xbd/0xf0 + __lock_acquire+0x2aca/0x3a20 + lock_acquire+0x19b/0x520 + _raw_spin_lock+0x2b/0x40 + attribute_container_unregister+0x30/0x160 + fc_release_transport+0x19/0x90 [scsi_transport_fc] + bfad_im_module_exit+0x23/0x60 [bfa] + bfad_init+0xdb/0xff0 [bfa] + do_one_initcall+0xdc/0x550 + do_init_module+0x22d/0x6b0 + load_module+0x4e96/0x5ff0 + init_module_from_file+0xcd/0x130 + idempotent_init_module+0x330/0x620 + __x64_sys_finit_module+0xb3/0x110 + do_syscall_64+0xc1/0x1d0 + entry_SYSCALL_64_after_hwframe+0x77/0x7f + </TASK> + +Allocated by task 25303: + kasan_save_stack+0x24/0x50 + kasan_save_track+0x14/0x30 + __kasan_kmalloc+0x7f/0x90 + fc_attach_transport+0x4f/0x4740 [scsi_transport_fc] + bfad_im_module_init+0x17/0x80 [bfa] + bfad_init+0x23/0xff0 [bfa] + do_one_initcall+0xdc/0x550 + do_init_module+0x22d/0x6b0 + load_module+0x4e96/0x5ff0 + init_module_from_file+0xcd/0x130 + idempotent_init_module+0x330/0x620 + __x64_sys_finit_module+0xb3/0x110 + do_syscall_64+0xc1/0x1d0 + entry_SYSCALL_64_after_hwframe+0x77/0x7f + +Freed by task 25303: + kasan_save_stack+0x24/0x50 + kasan_save_track+0x14/0x30 + kasan_save_free_info+0x3b/0x60 + __kasan_slab_free+0x38/0x50 + kfree+0x212/0x480 + bfad_im_module_init+0x7e/0x80 [bfa] + bfad_init+0x23/0xff0 [bfa] + do_one_initcall+0xdc/0x550 + do_init_module+0x22d/0x6b0 + load_module+0x4e96/0x5ff0 + init_module_from_file+0xcd/0x130 + idempotent_init_module+0x330/0x620 + __x64_sys_finit_module+0xb3/0x110 + do_syscall_64+0xc1/0x1d0 + entry_SYSCALL_64_after_hwframe+0x77/0x7f + +Above issue happens as follows: + +bfad_init + error = bfad_im_module_init() + fc_release_transport(bfad_im_scsi_transport_template); + if (error) + goto ext; + +ext: + bfad_im_module_exit(); + fc_release_transport(bfad_im_scsi_transport_template); + --> Trigger double release + +Don't call bfad_im_module_exit() if bfad_im_module_init() failed. + +Fixes: 7725ccfda597 ("[SCSI] bfa: Brocade BFA FC SCSI driver") +Signed-off-by: Ye Bin <yebin10@huawei.com> +Link: https://lore.kernel.org/r/20241023011809.63466-1-yebin@huaweicloud.com +Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/scsi/bfa/bfad.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/drivers/scsi/bfa/bfad.c b/drivers/scsi/bfa/bfad.c +index 62cb7a864fd53..70c7515a822f5 100644 +--- a/drivers/scsi/bfa/bfad.c ++++ b/drivers/scsi/bfa/bfad.c +@@ -1693,9 +1693,8 @@ bfad_init(void) + + error = bfad_im_module_init(); + if (error) { +- error = -ENOMEM; + printk(KERN_WARNING "bfad_im_module_init failure\n"); +- goto ext; ++ return -ENOMEM; + } + + if (strcmp(FCPI_NAME, " fcpim") == 0) +-- +2.43.0 + diff --git a/queue-6.12/scsi-fusion-remove-unused-variable-rc.patch b/queue-6.12/scsi-fusion-remove-unused-variable-rc.patch new file mode 100644 index 00000000000..506d72e84de --- /dev/null +++ b/queue-6.12/scsi-fusion-remove-unused-variable-rc.patch @@ -0,0 +1,46 @@ +From ff98f3cce83c1c3047a6b203a7a45e830b7ef008 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Thu, 24 Oct 2024 16:44:17 +0800 +Subject: scsi: fusion: Remove unused variable 'rc' + +From: Zeng Heng <zengheng4@huawei.com> + +[ Upstream commit bd65694223f7ad11c790ab63ad1af87a771192ee ] + +The return value of scsi_device_reprobe() is currently ignored in +_scsih_reprobe_lun(). Fixing the calling code to deal with the potential +error is non-trivial, so for now just WARN_ON(). + +The handling of scsi_device_reprobe()'s return value refers to +_scsih_reprobe_lun() and the following link: + +https://lore.kernel.org/all/094fdbf57487af4f395238c0525b2a560c8f68f0.1469766027.git.calvinowens@fb.com/ + +Fixes: f99be43b3024 ("[SCSI] fusion: power pc and miscellaneous bug fixs") +Signed-off-by: Zeng Heng <zengheng4@huawei.com> +Link: https://lore.kernel.org/r/20241024084417.154655-1-zengheng4@huawei.com +Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/message/fusion/mptsas.c | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +diff --git a/drivers/message/fusion/mptsas.c b/drivers/message/fusion/mptsas.c +index a0bcb0864ecd2..a798e26c6402d 100644 +--- a/drivers/message/fusion/mptsas.c ++++ b/drivers/message/fusion/mptsas.c +@@ -4231,10 +4231,8 @@ mptsas_find_phyinfo_by_phys_disk_num(MPT_ADAPTER *ioc, u8 phys_disk_num, + static void + mptsas_reprobe_lun(struct scsi_device *sdev, void *data) + { +- int rc; +- + sdev->no_uld_attach = data ? 1 : 0; +- rc = scsi_device_reprobe(sdev); ++ WARN_ON(scsi_device_reprobe(sdev)); + } + + static void +-- +2.43.0 + diff --git a/queue-6.12/scsi-hisi_sas-enable-all-phys-that-are-not-disabled-.patch b/queue-6.12/scsi-hisi_sas-enable-all-phys-that-are-not-disabled-.patch new file mode 100644 index 00000000000..2b274f930d4 --- /dev/null +++ b/queue-6.12/scsi-hisi_sas-enable-all-phys-that-are-not-disabled-.patch @@ -0,0 +1,57 @@ +From aeda1fce074b0ddc69b240ae8a0059a08715ffff Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Tue, 8 Oct 2024 10:18:13 +0800 +Subject: scsi: hisi_sas: Enable all PHYs that are not disabled by user during + controller reset + +From: Yihang Li <liyihang9@huawei.com> + +[ Upstream commit 08a07dc71d7fc6f58c35c4fc0bcede2811c5aa4c ] + +For the controller reset operation(such as FLR or clear nexus ha in SCSI +EH), we will disable all PHYs and then enable PHY based on the +hisi_hba->phy_state obtained in hisi_sas_controller_reset_prepare(). If +the device is removed before controller reset or the PHY is not attached +to any device in directly attached scenario, the corresponding bit of +phy_state is not set. After controller reset done, the PHY is disabled. +The device cannot be identified even if user reconnect the disk. + +Therefore, for PHYs that are not disabled by user, hisi_sas_phy_enable() +needs to be executed even if the corresponding bit of phy_state is not +set. + +Fixes: 89954f024c3a ("scsi: hisi_sas: Ensure all enabled PHYs up during controller reset") +Signed-off-by: Yihang Li <liyihang9@huawei.com> +Link: https://lore.kernel.org/r/20241008021822.2617339-5-liyihang9@huawei.com +Reviewed-by: Xiang Chen <chenxiang66@hisilicon.com> +Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/scsi/hisi_sas/hisi_sas_main.c | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c +index 6219807ce3b9e..ffd15fa4f9e59 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_main.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_main.c +@@ -1545,10 +1545,16 @@ void hisi_sas_controller_reset_done(struct hisi_hba *hisi_hba) + /* Init and wait for PHYs to come up and all libsas event finished. */ + for (phy_no = 0; phy_no < hisi_hba->n_phy; phy_no++) { + struct hisi_sas_phy *phy = &hisi_hba->phy[phy_no]; ++ struct asd_sas_phy *sas_phy = &phy->sas_phy; + +- if (!(hisi_hba->phy_state & BIT(phy_no))) ++ if (!sas_phy->phy->enabled) + continue; + ++ if (!(hisi_hba->phy_state & BIT(phy_no))) { ++ hisi_sas_phy_enable(hisi_hba, phy_no, 1); ++ continue; ++ } ++ + async_schedule_domain(hisi_sas_async_init_wait_phyup, + phy, &async); + } +-- +2.43.0 + diff --git a/queue-6.12/scsi-qedf-fix-a-possible-memory-leak-in-qedf_alloc_a.patch b/queue-6.12/scsi-qedf-fix-a-possible-memory-leak-in-qedf_alloc_a.patch new file mode 100644 index 00000000000..80f4c5e501e --- /dev/null +++ b/queue-6.12/scsi-qedf-fix-a-possible-memory-leak-in-qedf_alloc_a.patch @@ -0,0 +1,37 @@ +From d44b2f62ef2c39d3acbd115b213fa8bfd443d66d Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Sat, 26 Oct 2024 20:57:10 +0800 +Subject: scsi: qedf: Fix a possible memory leak in qedf_alloc_and_init_sb() + +From: Zhen Lei <thunder.leizhen@huawei.com> + +[ Upstream commit c62c30429db3eb4ced35c7fcf6f04a61ce3a01bb ] + +Hook "qed_ops->common->sb_init = qed_sb_init" does not release the DMA +memory sb_virt when it fails. Add dma_free_coherent() to free it. This +is the same way as qedr_alloc_mem_sb() and qede_alloc_mem_sb(). + +Fixes: 61d8658b4a43 ("scsi: qedf: Add QLogic FastLinQ offload FCoE driver framework.") +Signed-off-by: Zhen Lei <thunder.leizhen@huawei.com> +Link: https://lore.kernel.org/r/20241026125711.484-2-thunder.leizhen@huawei.com +Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/scsi/qedf/qedf_main.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/scsi/qedf/qedf_main.c b/drivers/scsi/qedf/qedf_main.c +index cf13148ba281c..e979ec1478c18 100644 +--- a/drivers/scsi/qedf/qedf_main.c ++++ b/drivers/scsi/qedf/qedf_main.c +@@ -2738,6 +2738,7 @@ static int qedf_alloc_and_init_sb(struct qedf_ctx *qedf, + sb_id, QED_SB_TYPE_STORAGE); + + if (ret) { ++ dma_free_coherent(&qedf->pdev->dev, sizeof(*sb_virt), sb_virt, sb_phys); + QEDF_ERR(&qedf->dbg_ctx, + "Status block initialization failed (0x%x) for id = %d.\n", + ret, sb_id); +-- +2.43.0 + diff --git a/queue-6.12/scsi-qedi-fix-a-possible-memory-leak-in-qedi_alloc_a.patch b/queue-6.12/scsi-qedi-fix-a-possible-memory-leak-in-qedi_alloc_a.patch new file mode 100644 index 00000000000..5ce2939299b --- /dev/null +++ b/queue-6.12/scsi-qedi-fix-a-possible-memory-leak-in-qedi_alloc_a.patch @@ -0,0 +1,37 @@ +From 7f1f1f5d9f3770f6e85faa1266540c520a5318ef Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Sat, 26 Oct 2024 20:57:11 +0800 +Subject: scsi: qedi: Fix a possible memory leak in qedi_alloc_and_init_sb() + +From: Zhen Lei <thunder.leizhen@huawei.com> + +[ Upstream commit 95bbdca4999bc59a72ebab01663d421d6ce5775d ] + +Hook "qedi_ops->common->sb_init = qed_sb_init" does not release the DMA +memory sb_virt when it fails. Add dma_free_coherent() to free it. This +is the same way as qedr_alloc_mem_sb() and qede_alloc_mem_sb(). + +Fixes: ace7f46ba5fd ("scsi: qedi: Add QLogic FastLinQ offload iSCSI driver framework.") +Signed-off-by: Zhen Lei <thunder.leizhen@huawei.com> +Link: https://lore.kernel.org/r/20241026125711.484-3-thunder.leizhen@huawei.com +Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/scsi/qedi/qedi_main.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/scsi/qedi/qedi_main.c b/drivers/scsi/qedi/qedi_main.c +index c5aec26019d6a..628d59dda20cc 100644 +--- a/drivers/scsi/qedi/qedi_main.c ++++ b/drivers/scsi/qedi/qedi_main.c +@@ -369,6 +369,7 @@ static int qedi_alloc_and_init_sb(struct qedi_ctx *qedi, + ret = qedi_ops->common->sb_init(qedi->cdev, sb_info, sb_virt, sb_phys, + sb_id, QED_SB_TYPE_STORAGE); + if (ret) { ++ dma_free_coherent(&qedi->pdev->dev, sizeof(*sb_virt), sb_virt, sb_phys); + QEDI_ERR(&qedi->dbg_ctx, + "Status block initialization failed for id = %d.\n", + sb_id); +-- +2.43.0 + diff --git a/queue-6.12/scsi-sg-enable-runtime-power-management.patch b/queue-6.12/scsi-sg-enable-runtime-power-management.patch new file mode 100644 index 00000000000..ee6f50c3efc --- /dev/null +++ b/queue-6.12/scsi-sg-enable-runtime-power-management.patch @@ -0,0 +1,74 @@ +From 405bf9ec46a6c0586952c569acdb124767b3de5d Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Wed, 30 Oct 2024 15:03:10 -0700 +Subject: scsi: sg: Enable runtime power management + +From: Bart Van Assche <bvanassche@acm.org> + +[ Upstream commit 4045de893f691f75193c606aec440c365cf7a7be ] + +In 2010, runtime power management support was implemented in the SCSI +core. The description of patch "[SCSI] implement runtime Power +Management" mentions that the sg driver is skipped but not why. This +patch enables runtime power management even if an instance of the sg +driver is held open. Enabling runtime PM for the sg driver is safe +because all interactions of the sg driver with the SCSI device pass +through the block layer (blk_execute_rq_nowait()) and the block layer +already supports runtime PM. + +Cc: Alan Stern <stern@rowland.harvard.edu> +Cc: Douglas Gilbert <dgilbert@interlog.com> +Fixes: bc4f24014de5 ("[SCSI] implement runtime Power Management") +Signed-off-by: Bart Van Assche <bvanassche@acm.org> +Link: https://lore.kernel.org/r/20241030220310.1373569-1-bvanassche@acm.org +Acked-by: Alan Stern <stern@rowland.harvard.edu> +Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/scsi/sg.c | 9 +-------- + 1 file changed, 1 insertion(+), 8 deletions(-) + +diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c +index f86be197fedd0..84334ab39c810 100644 +--- a/drivers/scsi/sg.c ++++ b/drivers/scsi/sg.c +@@ -307,10 +307,6 @@ sg_open(struct inode *inode, struct file *filp) + if (retval) + goto sg_put; + +- retval = scsi_autopm_get_device(device); +- if (retval) +- goto sdp_put; +- + /* scsi_block_when_processing_errors() may block so bypass + * check if O_NONBLOCK. Permits SCSI commands to be issued + * during error recovery. Tread carefully. */ +@@ -318,7 +314,7 @@ sg_open(struct inode *inode, struct file *filp) + scsi_block_when_processing_errors(device))) { + retval = -ENXIO; + /* we are in error recovery for this device */ +- goto error_out; ++ goto sdp_put; + } + + mutex_lock(&sdp->open_rel_lock); +@@ -371,8 +367,6 @@ sg_open(struct inode *inode, struct file *filp) + } + error_mutex_locked: + mutex_unlock(&sdp->open_rel_lock); +-error_out: +- scsi_autopm_put_device(device); + sdp_put: + kref_put(&sdp->d_ref, sg_device_destroy); + scsi_device_put(device); +@@ -392,7 +386,6 @@ sg_release(struct inode *inode, struct file *filp) + SCSI_LOG_TIMEOUT(3, sg_printk(KERN_INFO, sdp, "sg_release\n")); + + mutex_lock(&sdp->open_rel_lock); +- scsi_autopm_put_device(sdp->device); + kref_put(&sfp->f_ref, sg_remove_sfp); + sdp->open_cnt--; + +-- +2.43.0 + diff --git a/queue-6.12/scsi-target-fix-incorrect-function-name-in-pscsi_cre.patch b/queue-6.12/scsi-target-fix-incorrect-function-name-in-pscsi_cre.patch new file mode 100644 index 00000000000..793159fb229 --- /dev/null +++ b/queue-6.12/scsi-target-fix-incorrect-function-name-in-pscsi_cre.patch @@ -0,0 +1,37 @@ +From 2f75cbc807738560d9990a1eb573101d52049c85 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Wed, 30 Oct 2024 10:18:00 +0800 +Subject: scsi: target: Fix incorrect function name in pscsi_create_type_disk() + +From: Baolin Liu <liubaolin@kylinos.cn> + +[ Upstream commit da5aeca99dd0b6c7bf6679382756ea6bda195f72 ] + +In pr_err(), bdev_open_by_path() should be renamed to +bdev_file_open_by_path() + +Fixes: 034f0cf8fdf9 ("target: port block device access to file") +Signed-off-by: Baolin Liu <liubaolin@kylinos.cn> +Link: https://lore.kernel.org/r/20241030021800.234980-1-liubaolin12138@163.com +Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/target/target_core_pscsi.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/target/target_core_pscsi.c b/drivers/target/target_core_pscsi.c +index 440e07b1d5cdb..287ac5b0495f9 100644 +--- a/drivers/target/target_core_pscsi.c ++++ b/drivers/target/target_core_pscsi.c +@@ -369,7 +369,7 @@ static int pscsi_create_type_disk(struct se_device *dev, struct scsi_device *sd) + bdev_file = bdev_file_open_by_path(dev->udev_path, + BLK_OPEN_WRITE | BLK_OPEN_READ, pdv, NULL); + if (IS_ERR(bdev_file)) { +- pr_err("pSCSI: bdev_open_by_path() failed\n"); ++ pr_err("pSCSI: bdev_file_open_by_path() failed\n"); + scsi_device_put(sd); + return PTR_ERR(bdev_file); + } +-- +2.43.0 + diff --git a/queue-6.12/selftests-bpf-add-missing-header-include-for-htons.patch b/queue-6.12/selftests-bpf-add-missing-header-include-for-htons.patch new file mode 100644 index 00000000000..74fea72eeb2 --- /dev/null +++ b/queue-6.12/selftests-bpf-add-missing-header-include-for-htons.patch @@ -0,0 +1,50 @@ +From 11920f44e39b3b1f8be8eeaa54a8496948b41418 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Tue, 8 Oct 2024 16:50:57 +0200 +Subject: selftests/bpf: add missing header include for htons +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Alexis Lothoré (eBPF Foundation) <alexis.lothore@bootlin.com> + +[ Upstream commit bc9b3fb827fceec4e05564d6e668280f4470ab5b ] + +Including the network_helpers.h header in tests can lead to the following +build error: + +./network_helpers.h: In function ‘csum_tcpudp_magic’: +./network_helpers.h:116:14: error: implicit declaration of function \ + ‘htons’ [-Werror=implicit-function-declaration] + 116 | s += htons(proto + len); + +The error is avoided in many cases thanks to some other headers included +earlier and bringing in arpa/inet.h (ie: test_progs.h). + +Make sure that test_progs build success does not depend on header ordering +by adding the missing header include in network_helpers.h + +Fixes: f6642de0c3e9 ("selftests/bpf: Add csum helpers") +Signed-off-by: Alexis Lothoré (eBPF Foundation) <alexis.lothore@bootlin.com> +Link: https://lore.kernel.org/r/20241008-network_helpers_fix-v1-1-2c2ae03df7ef@bootlin.com +Signed-off-by: Martin KaFai Lau <martin.lau@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + tools/testing/selftests/bpf/network_helpers.h | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/tools/testing/selftests/bpf/network_helpers.h b/tools/testing/selftests/bpf/network_helpers.h +index c72c16e1aff82..5764155b6d251 100644 +--- a/tools/testing/selftests/bpf/network_helpers.h ++++ b/tools/testing/selftests/bpf/network_helpers.h +@@ -1,6 +1,7 @@ + /* SPDX-License-Identifier: GPL-2.0 */ + #ifndef __NETWORK_HELPERS_H + #define __NETWORK_HELPERS_H ++#include <arpa/inet.h> + #include <sys/socket.h> + #include <sys/types.h> + #include <linux/types.h> +-- +2.43.0 + diff --git a/queue-6.12/selftests-bpf-add-missing-per-arch-include-path.patch b/queue-6.12/selftests-bpf-add-missing-per-arch-include-path.patch new file mode 100644 index 00000000000..a0979b30fb9 --- /dev/null +++ b/queue-6.12/selftests-bpf-add-missing-per-arch-include-path.patch @@ -0,0 +1,51 @@ +From c8382d24ee2e41f7c35eaecf8060f565c3280a03 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Fri, 27 Sep 2024 15:13:53 +0200 +Subject: selftests: bpf: Add missing per-arch include path +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Björn Töpel <bjorn@rivosinc.com> + +[ Upstream commit 19090f0306f1748980596c6c71f1c4b128639cff ] + +The prog_tests programs do not include the per-arch tools include +path, e.g. tools/arch/riscv/include. Some architectures depend those +files to build properly. + +Include tools/arch/$(SUBARCH)/include in the selftests bpf build. + +Fixes: 6d74d178fe6e ("tools: Add riscv barrier implementation") +Signed-off-by: Björn Töpel <bjorn@rivosinc.com> +Signed-off-by: Andrii Nakryiko <andrii@kernel.org> +Link: https://lore.kernel.org/bpf/20240927131355.350918-2-bjorn@kernel.org +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + tools/testing/selftests/bpf/Makefile | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/tools/testing/selftests/bpf/Makefile b/tools/testing/selftests/bpf/Makefile +index 75016962f7956..43a0293184785 100644 +--- a/tools/testing/selftests/bpf/Makefile ++++ b/tools/testing/selftests/bpf/Makefile +@@ -10,6 +10,7 @@ TOOLSDIR := $(abspath ../../..) + LIBDIR := $(TOOLSDIR)/lib + BPFDIR := $(LIBDIR)/bpf + TOOLSINCDIR := $(TOOLSDIR)/include ++TOOLSARCHINCDIR := $(TOOLSDIR)/arch/$(SRCARCH)/include + BPFTOOLDIR := $(TOOLSDIR)/bpf/bpftool + APIDIR := $(TOOLSINCDIR)/uapi + ifneq ($(O),) +@@ -44,7 +45,7 @@ CFLAGS += -g $(OPT_FLAGS) -rdynamic \ + -Wall -Werror -fno-omit-frame-pointer \ + $(GENFLAGS) $(SAN_CFLAGS) $(LIBELF_CFLAGS) \ + -I$(CURDIR) -I$(INCLUDE_DIR) -I$(GENDIR) -I$(LIBDIR) \ +- -I$(TOOLSINCDIR) -I$(APIDIR) -I$(OUTPUT) ++ -I$(TOOLSINCDIR) -I$(TOOLSARCHINCDIR) -I$(APIDIR) -I$(OUTPUT) + LDFLAGS += $(SAN_LDFLAGS) + LDLIBS += $(LIBELF_LIBS) -lz -lrt -lpthread + +-- +2.43.0 + diff --git a/queue-6.12/selftests-bpf-add-push-pop-checking-for-msg_verify_d.patch b/queue-6.12/selftests-bpf-add-push-pop-checking-for-msg_verify_d.patch new file mode 100644 index 00000000000..2fdf5881092 --- /dev/null +++ b/queue-6.12/selftests-bpf-add-push-pop-checking-for-msg_verify_d.patch @@ -0,0 +1,246 @@ +From 08e0b73394043df46f095d8cc4655b2a358961cd Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Wed, 6 Nov 2024 22:25:16 +0000 +Subject: selftests/bpf: Add push/pop checking for msg_verify_data in + test_sockmap + +From: Zijian Zhang <zijianzhang@bytedance.com> + +[ Upstream commit 862087c3d36219ed44569666eb263efc97f00c9a ] + +Add push/pop checking for msg_verify_data in test_sockmap, except for +pop/push with cork tests, in these tests the logic will be different. +1. With corking, pop/push might not be invoked in each sendmsg, it makes +the layout of the received data difficult +2. It makes it hard to calculate the total_bytes in the recvmsg +Temporarily skip the data integrity test for these cases now, added a TODO + +Fixes: ee9b352ce465 ("selftests/bpf: Fix msg_verify_data in test_sockmap") +Signed-off-by: Zijian Zhang <zijianzhang@bytedance.com> +Reviewed-by: John Fastabend <john.fastabend@gmail.com> +Link: https://lore.kernel.org/r/20241106222520.527076-5-zijianzhang@bytedance.com +Signed-off-by: Martin KaFai Lau <martin.lau@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + tools/testing/selftests/bpf/test_sockmap.c | 106 ++++++++++++++++++++- + 1 file changed, 101 insertions(+), 5 deletions(-) + +diff --git a/tools/testing/selftests/bpf/test_sockmap.c b/tools/testing/selftests/bpf/test_sockmap.c +index 5f4558f1f0049..61a747afcd05f 100644 +--- a/tools/testing/selftests/bpf/test_sockmap.c ++++ b/tools/testing/selftests/bpf/test_sockmap.c +@@ -88,6 +88,10 @@ int ktls; + int peek_flag; + int skb_use_parser; + int txmsg_omit_skb_parser; ++int verify_push_start; ++int verify_push_len; ++int verify_pop_start; ++int verify_pop_len; + + static const struct option long_options[] = { + {"help", no_argument, NULL, 'h' }, +@@ -514,12 +518,41 @@ static int msg_alloc_iov(struct msghdr *msg, + return -ENOMEM; + } + +-/* TODO: Add verification logic for push, pull and pop data */ ++/* In push or pop test, we need to do some calculations for msg_verify_data */ ++static void msg_verify_date_prep(void) ++{ ++ int push_range_end = txmsg_start_push + txmsg_end_push - 1; ++ int pop_range_end = txmsg_start_pop + txmsg_pop - 1; ++ ++ if (txmsg_end_push && txmsg_pop && ++ txmsg_start_push <= pop_range_end && txmsg_start_pop <= push_range_end) { ++ /* The push range and the pop range overlap */ ++ int overlap_len; ++ ++ verify_push_start = txmsg_start_push; ++ verify_pop_start = txmsg_start_pop; ++ if (txmsg_start_push < txmsg_start_pop) ++ overlap_len = min(push_range_end - txmsg_start_pop + 1, txmsg_pop); ++ else ++ overlap_len = min(pop_range_end - txmsg_start_push + 1, txmsg_end_push); ++ verify_push_len = max(txmsg_end_push - overlap_len, 0); ++ verify_pop_len = max(txmsg_pop - overlap_len, 0); ++ } else { ++ /* Otherwise */ ++ verify_push_start = txmsg_start_push; ++ verify_pop_start = txmsg_start_pop; ++ verify_push_len = txmsg_end_push; ++ verify_pop_len = txmsg_pop; ++ } ++} ++ + static int msg_verify_data(struct msghdr *msg, int size, int chunk_sz, +- unsigned char *k_p, int *bytes_cnt_p) ++ unsigned char *k_p, int *bytes_cnt_p, ++ int *check_cnt_p, int *push_p) + { +- int i, j, bytes_cnt = *bytes_cnt_p; ++ int bytes_cnt = *bytes_cnt_p, check_cnt = *check_cnt_p, push = *push_p; + unsigned char k = *k_p; ++ int i, j; + + for (i = 0, j = 0; i < msg->msg_iovlen && size; i++, j = 0) { + unsigned char *d = msg->msg_iov[i].iov_base; +@@ -538,6 +571,37 @@ static int msg_verify_data(struct msghdr *msg, int size, int chunk_sz, + } + + for (; j < msg->msg_iov[i].iov_len && size; j++) { ++ if (push > 0 && ++ check_cnt == verify_push_start + verify_push_len - push) { ++ int skipped; ++revisit_push: ++ skipped = push; ++ if (j + push >= msg->msg_iov[i].iov_len) ++ skipped = msg->msg_iov[i].iov_len - j; ++ push -= skipped; ++ size -= skipped; ++ j += skipped - 1; ++ check_cnt += skipped; ++ continue; ++ } ++ ++ if (verify_pop_len > 0 && check_cnt == verify_pop_start) { ++ bytes_cnt += verify_pop_len; ++ check_cnt += verify_pop_len; ++ k += verify_pop_len; ++ ++ if (bytes_cnt == chunk_sz) { ++ k = 0; ++ bytes_cnt = 0; ++ check_cnt = 0; ++ push = verify_push_len; ++ } ++ ++ if (push > 0 && ++ check_cnt == verify_push_start + verify_push_len - push) ++ goto revisit_push; ++ } ++ + if (d[j] != k++) { + fprintf(stderr, + "detected data corruption @iov[%i]:%i %02x != %02x, %02x ?= %02x\n", +@@ -545,15 +609,20 @@ static int msg_verify_data(struct msghdr *msg, int size, int chunk_sz, + return -EDATAINTEGRITY; + } + bytes_cnt++; ++ check_cnt++; + if (bytes_cnt == chunk_sz) { + k = 0; + bytes_cnt = 0; ++ check_cnt = 0; ++ push = verify_push_len; + } + size--; + } + } + *k_p = k; + *bytes_cnt_p = bytes_cnt; ++ *check_cnt_p = check_cnt; ++ *push_p = push; + return 0; + } + +@@ -612,6 +681,8 @@ static int msg_loop(int fd, int iov_count, int iov_length, int cnt, + struct timeval timeout; + unsigned char k = 0; + int bytes_cnt = 0; ++ int check_cnt = 0; ++ int push = 0; + fd_set w; + + fcntl(fd, fd_flags); +@@ -637,6 +708,10 @@ static int msg_loop(int fd, int iov_count, int iov_length, int cnt, + } + total_bytes += txmsg_push_total; + total_bytes -= txmsg_pop_total; ++ if (data) { ++ msg_verify_date_prep(); ++ push = verify_push_len; ++ } + err = clock_gettime(CLOCK_MONOTONIC, &s->start); + if (err < 0) + perror("recv start time"); +@@ -712,7 +787,8 @@ static int msg_loop(int fd, int iov_count, int iov_length, int cnt, + iov_length : + iov_length * iov_count; + +- errno = msg_verify_data(&msg, recv, chunk_sz, &k, &bytes_cnt); ++ errno = msg_verify_data(&msg, recv, chunk_sz, &k, &bytes_cnt, ++ &check_cnt, &push); + if (errno) { + perror("data verify msg failed"); + goto out_errno; +@@ -722,7 +798,9 @@ static int msg_loop(int fd, int iov_count, int iov_length, int cnt, + recvp, + chunk_sz, + &k, +- &bytes_cnt); ++ &bytes_cnt, ++ &check_cnt, ++ &push); + if (errno) { + perror("data verify msg_peek failed"); + goto out_errno; +@@ -1636,6 +1714,8 @@ static void test_txmsg_pull(int cgrp, struct sockmap_options *opt) + + static void test_txmsg_pop(int cgrp, struct sockmap_options *opt) + { ++ bool data = opt->data_test; ++ + /* Test basic pop */ + txmsg_pass = 1; + txmsg_start_pop = 1; +@@ -1654,6 +1734,12 @@ static void test_txmsg_pop(int cgrp, struct sockmap_options *opt) + txmsg_pop = 2; + test_send_many(opt, cgrp); + ++ /* TODO: Test for pop + cork should be different, ++ * - It makes the layout of the received data difficult ++ * - It makes it hard to calculate the total_bytes in the recvmsg ++ * Temporarily skip the data integrity test for this case now. ++ */ ++ opt->data_test = false; + /* Test pop + cork */ + txmsg_redir = 0; + txmsg_cork = 512; +@@ -1667,10 +1753,13 @@ static void test_txmsg_pop(int cgrp, struct sockmap_options *opt) + txmsg_start_pop = 1; + txmsg_pop = 2; + test_send_many(opt, cgrp); ++ opt->data_test = data; + } + + static void test_txmsg_push(int cgrp, struct sockmap_options *opt) + { ++ bool data = opt->data_test; ++ + /* Test basic push */ + txmsg_pass = 1; + txmsg_start_push = 1; +@@ -1689,12 +1778,19 @@ static void test_txmsg_push(int cgrp, struct sockmap_options *opt) + txmsg_end_push = 2; + test_send_many(opt, cgrp); + ++ /* TODO: Test for push + cork should be different, ++ * - It makes the layout of the received data difficult ++ * - It makes it hard to calculate the total_bytes in the recvmsg ++ * Temporarily skip the data integrity test for this case now. ++ */ ++ opt->data_test = false; + /* Test push + cork */ + txmsg_redir = 0; + txmsg_cork = 512; + txmsg_start_push = 1; + txmsg_end_push = 2; + test_send_many(opt, cgrp); ++ opt->data_test = data; + } + + static void test_txmsg_push_pop(int cgrp, struct sockmap_options *opt) +-- +2.43.0 + diff --git a/queue-6.12/selftests-bpf-add-txmsg_pass-to-pull-push-pop-in-tes.patch b/queue-6.12/selftests-bpf-add-txmsg_pass-to-pull-push-pop-in-tes.patch new file mode 100644 index 00000000000..2005bff7bc7 --- /dev/null +++ b/queue-6.12/selftests-bpf-add-txmsg_pass-to-pull-push-pop-in-tes.patch @@ -0,0 +1,80 @@ +From 69f93b9ac1ebf284bf5e2ed3c6757d76e69467b9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Wed, 6 Nov 2024 22:25:13 +0000 +Subject: selftests/bpf: Add txmsg_pass to pull/push/pop in test_sockmap + +From: Zijian Zhang <zijianzhang@bytedance.com> + +[ Upstream commit 66c54c20408d994be34be2c070fba08472f69eee ] + +Add txmsg_pass to test_txmsg_pull/push/pop. If txmsg_pass is missing, +tx_prog will be NULL, and no program will be attached to the sockmap. +As a result, pull/push/pop are never invoked. + +Fixes: 328aa08a081b ("bpf: Selftests, break down test_sockmap into subtests") +Signed-off-by: Zijian Zhang <zijianzhang@bytedance.com> +Reviewed-by: John Fastabend <john.fastabend@gmail.com> +Link: https://lore.kernel.org/r/20241106222520.527076-2-zijianzhang@bytedance.com +Signed-off-by: Martin KaFai Lau <martin.lau@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + tools/testing/selftests/bpf/test_sockmap.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/tools/testing/selftests/bpf/test_sockmap.c b/tools/testing/selftests/bpf/test_sockmap.c +index 075c93ed143e6..0f065273fde32 100644 +--- a/tools/testing/selftests/bpf/test_sockmap.c ++++ b/tools/testing/selftests/bpf/test_sockmap.c +@@ -1596,11 +1596,13 @@ static void test_txmsg_cork_hangs(int cgrp, struct sockmap_options *opt) + static void test_txmsg_pull(int cgrp, struct sockmap_options *opt) + { + /* Test basic start/end */ ++ txmsg_pass = 1; + txmsg_start = 1; + txmsg_end = 2; + test_send(opt, cgrp); + + /* Test >4k pull */ ++ txmsg_pass = 1; + txmsg_start = 4096; + txmsg_end = 9182; + test_send_large(opt, cgrp); +@@ -1629,11 +1631,13 @@ static void test_txmsg_pull(int cgrp, struct sockmap_options *opt) + static void test_txmsg_pop(int cgrp, struct sockmap_options *opt) + { + /* Test basic pop */ ++ txmsg_pass = 1; + txmsg_start_pop = 1; + txmsg_pop = 2; + test_send_many(opt, cgrp); + + /* Test pop with >4k */ ++ txmsg_pass = 1; + txmsg_start_pop = 4096; + txmsg_pop = 4096; + test_send_large(opt, cgrp); +@@ -1662,11 +1666,13 @@ static void test_txmsg_pop(int cgrp, struct sockmap_options *opt) + static void test_txmsg_push(int cgrp, struct sockmap_options *opt) + { + /* Test basic push */ ++ txmsg_pass = 1; + txmsg_start_push = 1; + txmsg_end_push = 1; + test_send(opt, cgrp); + + /* Test push 4kB >4k */ ++ txmsg_pass = 1; + txmsg_start_push = 4096; + txmsg_end_push = 4096; + test_send_large(opt, cgrp); +@@ -1687,6 +1693,7 @@ static void test_txmsg_push(int cgrp, struct sockmap_options *opt) + + static void test_txmsg_push_pop(int cgrp, struct sockmap_options *opt) + { ++ txmsg_pass = 1; + txmsg_start_push = 1; + txmsg_end_push = 10; + txmsg_start_pop = 5; +-- +2.43.0 + diff --git a/queue-6.12/selftests-bpf-fix-backtrace-printing-for-selftests-c.patch b/queue-6.12/selftests-bpf-fix-backtrace-printing-for-selftests-c.patch new file mode 100644 index 00000000000..48fefd7a0e3 --- /dev/null +++ b/queue-6.12/selftests-bpf-fix-backtrace-printing-for-selftests-c.patch @@ -0,0 +1,104 @@ +From d56a68e800a3b84becdee59c19ff98a009ec4c99 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Thu, 3 Oct 2024 14:03:07 -0700 +Subject: selftests/bpf: Fix backtrace printing for selftests crashes + +From: Eduard Zingerman <eddyz87@gmail.com> + +[ Upstream commit 5bf1557e3d6a69113649d831276ea2f97585fc33 ] + +test_progs uses glibc specific functions backtrace() and +backtrace_symbols_fd() to print backtrace in case of SIGSEGV. + +Recent commit (see fixes) updated test_progs.c to define stub versions +of the same functions with attriubte "weak" in order to allow linking +test_progs against musl libc. Unfortunately this broke the backtrace +handling for glibc builds. + +As it turns out, glibc defines backtrace() and backtrace_symbols_fd() +as weak: + + $ llvm-readelf --symbols /lib64/libc.so.6 \ + | grep -P '( backtrace_symbols_fd| backtrace)$' + 4910: 0000000000126b40 161 FUNC WEAK DEFAULT 16 backtrace + 6843: 0000000000126f90 852 FUNC WEAK DEFAULT 16 backtrace_symbols_fd + +So does test_progs: + + $ llvm-readelf --symbols test_progs \ + | grep -P '( backtrace_symbols_fd| backtrace)$' + 2891: 00000000006ad190 15 FUNC WEAK DEFAULT 13 backtrace + 11215: 00000000006ad1a0 41 FUNC WEAK DEFAULT 13 backtrace_symbols_fd + +In such situation dynamic linker is not obliged to favour glibc +implementation over the one defined in test_progs. + +Compiling with the following simple modification to test_progs.c +demonstrates the issue: + + $ git diff + ... + \--- a/tools/testing/selftests/bpf/test_progs.c + \+++ b/tools/testing/selftests/bpf/test_progs.c + \@@ -1817,6 +1817,7 @@ int main(int argc, char **argv) + if (err) + return err; + + + *(int *)0xdeadbeef = 42; + err = cd_flavor_subdir(argv[0]); + if (err) + return err; + + $ ./test_progs + [0]: Caught signal #11! + Stack trace: + <backtrace not supported> + Segmentation fault (core dumped) + +Resolve this by hiding stub definitions behind __GLIBC__ macro check +instead of using "weak" attribute. + +Fixes: c9a83e76b5a9 ("selftests/bpf: Fix compile if backtrace support missing in libc") +Signed-off-by: Eduard Zingerman <eddyz87@gmail.com> +Signed-off-by: Andrii Nakryiko <andrii@kernel.org> +Tested-by: Tony Ambardar <tony.ambardar@gmail.com> +Reviewed-by: Tony Ambardar <tony.ambardar@gmail.com> +Acked-by: Daniel Xu <dxu@dxuuu.xyz> +Link: https://lore.kernel.org/bpf/20241003210307.3847907-1-eddyz87@gmail.com +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + tools/testing/selftests/bpf/test_progs.c | 9 ++++++--- + 1 file changed, 6 insertions(+), 3 deletions(-) + +diff --git a/tools/testing/selftests/bpf/test_progs.c b/tools/testing/selftests/bpf/test_progs.c +index c7a70e1a1085a..fa829a7854f24 100644 +--- a/tools/testing/selftests/bpf/test_progs.c ++++ b/tools/testing/selftests/bpf/test_progs.c +@@ -20,11 +20,13 @@ + + #include "network_helpers.h" + ++/* backtrace() and backtrace_symbols_fd() are glibc specific, ++ * use header file when glibc is available and provide stub ++ * implementations when another libc implementation is used. ++ */ + #ifdef __GLIBC__ + #include <execinfo.h> /* backtrace */ +-#endif +- +-/* Default backtrace funcs if missing at link */ ++#else + __weak int backtrace(void **buffer, int size) + { + return 0; +@@ -34,6 +36,7 @@ __weak void backtrace_symbols_fd(void *const *buffer, int size, int fd) + { + dprintf(fd, "<backtrace not supported>\n"); + } ++#endif /*__GLIBC__ */ + + int env_verbosity = 0; + +-- +2.43.0 + diff --git a/queue-6.12/selftests-bpf-fix-msg_verify_data-in-test_sockmap.patch b/queue-6.12/selftests-bpf-fix-msg_verify_data-in-test_sockmap.patch new file mode 100644 index 00000000000..8a2f332b224 --- /dev/null +++ b/queue-6.12/selftests-bpf-fix-msg_verify_data-in-test_sockmap.patch @@ -0,0 +1,150 @@ +From f5708c5682662af59fe9f1830a6db4c8ae23749b Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Sat, 12 Oct 2024 20:37:30 +0000 +Subject: selftests/bpf: Fix msg_verify_data in test_sockmap + +From: Zijian Zhang <zijianzhang@bytedance.com> + +[ Upstream commit ee9b352ce4650ffc0d8ca0ac373d7c009c7e561e ] + +Function msg_verify_data should have context of bytes_cnt and k instead of +assuming they are zero. Otherwise, test_sockmap with data integrity test +will report some errors. I also fix the logic related to size and index j + +1/ 6 sockmap::txmsg test passthrough:FAIL +2/ 6 sockmap::txmsg test redirect:FAIL +7/12 sockmap::txmsg test apply:FAIL +10/11 sockmap::txmsg test push_data:FAIL +11/17 sockmap::txmsg test pull-data:FAIL +12/ 9 sockmap::txmsg test pop-data:FAIL +13/ 1 sockmap::txmsg test push/pop data:FAIL +... +Pass: 24 Fail: 52 + +After applying this patch, some of the errors are solved, but for push, +pull and pop, we may need more fixes to msg_verify_data, added a TODO + +10/11 sockmap::txmsg test push_data:FAIL +11/17 sockmap::txmsg test pull-data:FAIL +12/ 9 sockmap::txmsg test pop-data:FAIL +... +Pass: 37 Fail: 15 + +Besides, added a custom errno EDATAINTEGRITY for msg_verify_data, we +shall not ignore the error in txmsg_cork case. + +Fixes: 753fb2ee0934 ("bpf: sockmap, add msg_peek tests to test_sockmap") +Fixes: 16edddfe3c5d ("selftests/bpf: test_sockmap, check test failure") +Acked-by: John Fastabend <john.fastabend@gmail.com> +Signed-off-by: Zijian Zhang <zijianzhang@bytedance.com> +Link: https://lore.kernel.org/r/20241012203731.1248619-2-zijianzhang@bytedance.com +Signed-off-by: Martin KaFai Lau <martin.lau@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + tools/testing/selftests/bpf/test_sockmap.c | 30 ++++++++++++++-------- + 1 file changed, 20 insertions(+), 10 deletions(-) + +diff --git a/tools/testing/selftests/bpf/test_sockmap.c b/tools/testing/selftests/bpf/test_sockmap.c +index 3e02d7267de8b..8249f3c1fbd65 100644 +--- a/tools/testing/selftests/bpf/test_sockmap.c ++++ b/tools/testing/selftests/bpf/test_sockmap.c +@@ -56,6 +56,8 @@ static void running_handler(int a); + #define BPF_SOCKHASH_FILENAME "test_sockhash_kern.bpf.o" + #define CG_PATH "/sockmap" + ++#define EDATAINTEGRITY 2001 ++ + /* global sockets */ + int s1, s2, c1, c2, p1, p2; + int test_cnt; +@@ -510,23 +512,25 @@ static int msg_alloc_iov(struct msghdr *msg, + return -ENOMEM; + } + +-static int msg_verify_data(struct msghdr *msg, int size, int chunk_sz) ++/* TODO: Add verification logic for push, pull and pop data */ ++static int msg_verify_data(struct msghdr *msg, int size, int chunk_sz, ++ unsigned char *k_p, int *bytes_cnt_p) + { +- int i, j = 0, bytes_cnt = 0; +- unsigned char k = 0; ++ int i, j, bytes_cnt = *bytes_cnt_p; ++ unsigned char k = *k_p; + +- for (i = 0; i < msg->msg_iovlen; i++) { ++ for (i = 0, j = 0; i < msg->msg_iovlen && size; i++, j = 0) { + unsigned char *d = msg->msg_iov[i].iov_base; + + /* Special case test for skb ingress + ktls */ + if (i == 0 && txmsg_ktls_skb) { + if (msg->msg_iov[i].iov_len < 4) +- return -EIO; ++ return -EDATAINTEGRITY; + if (memcmp(d, "PASS", 4) != 0) { + fprintf(stderr, + "detected skb data error with skb ingress update @iov[%i]:%i \"%02x %02x %02x %02x\" != \"PASS\"\n", + i, 0, d[0], d[1], d[2], d[3]); +- return -EIO; ++ return -EDATAINTEGRITY; + } + j = 4; /* advance index past PASS header */ + } +@@ -536,7 +540,7 @@ static int msg_verify_data(struct msghdr *msg, int size, int chunk_sz) + fprintf(stderr, + "detected data corruption @iov[%i]:%i %02x != %02x, %02x ?= %02x\n", + i, j, d[j], k - 1, d[j+1], k); +- return -EIO; ++ return -EDATAINTEGRITY; + } + bytes_cnt++; + if (bytes_cnt == chunk_sz) { +@@ -546,6 +550,8 @@ static int msg_verify_data(struct msghdr *msg, int size, int chunk_sz) + size--; + } + } ++ *k_p = k; ++ *bytes_cnt_p = bytes_cnt; + return 0; + } + +@@ -602,6 +608,8 @@ static int msg_loop(int fd, int iov_count, int iov_length, int cnt, + float total_bytes, txmsg_pop_total; + int fd_flags = O_NONBLOCK; + struct timeval timeout; ++ unsigned char k = 0; ++ int bytes_cnt = 0; + fd_set w; + + fcntl(fd, fd_flags); +@@ -696,7 +704,7 @@ static int msg_loop(int fd, int iov_count, int iov_length, int cnt, + iov_length * cnt : + iov_length * iov_count; + +- errno = msg_verify_data(&msg, recv, chunk_sz); ++ errno = msg_verify_data(&msg, recv, chunk_sz, &k, &bytes_cnt); + if (errno) { + perror("data verify msg failed"); + goto out_errno; +@@ -704,7 +712,9 @@ static int msg_loop(int fd, int iov_count, int iov_length, int cnt, + if (recvp) { + errno = msg_verify_data(&msg_peek, + recvp, +- chunk_sz); ++ chunk_sz, ++ &k, ++ &bytes_cnt); + if (errno) { + perror("data verify msg_peek failed"); + goto out_errno; +@@ -812,7 +822,7 @@ static int sendmsg_test(struct sockmap_options *opt) + s.bytes_sent, sent_Bps, sent_Bps/giga, + s.bytes_recvd, recvd_Bps, recvd_Bps/giga, + peek_flag ? "(peek_msg)" : ""); +- if (err && txmsg_cork) ++ if (err && err != -EDATAINTEGRITY && txmsg_cork) + err = 0; + exit(err ? 1 : 0); + } else if (rxpid == -1) { +-- +2.43.0 + diff --git a/queue-6.12/selftests-bpf-fix-sendpage-data-logic-in-test_sockma.patch b/queue-6.12/selftests-bpf-fix-sendpage-data-logic-in-test_sockma.patch new file mode 100644 index 00000000000..20197177e57 --- /dev/null +++ b/queue-6.12/selftests-bpf-fix-sendpage-data-logic-in-test_sockma.patch @@ -0,0 +1,86 @@ +From 42effbefa83f3ad766df532afbab7fc86b9db718 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Wed, 6 Nov 2024 22:25:14 +0000 +Subject: selftests/bpf: Fix SENDPAGE data logic in test_sockmap + +From: Zijian Zhang <zijianzhang@bytedance.com> + +[ Upstream commit 4095031463d4e99b534d2cd82035a417295764ae ] + +In the SENDPAGE test, "opt->iov_length * cnt" size of data will be sent +cnt times by sendfile. +1. In push/pop tests, they will be invoked cnt times, for the simplicity of +msg_verify_data, change chunk_sz to iov_length +2. Change iov_length in test_send_large from 1024 to 8192. We have pop test +where txmsg_start_pop is 4096. 4096 > 1024, an error will be returned. + +Fixes: 328aa08a081b ("bpf: Selftests, break down test_sockmap into subtests") +Signed-off-by: Zijian Zhang <zijianzhang@bytedance.com> +Reviewed-by: John Fastabend <john.fastabend@gmail.com> +Link: https://lore.kernel.org/r/20241106222520.527076-3-zijianzhang@bytedance.com +Signed-off-by: Martin KaFai Lau <martin.lau@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + tools/testing/selftests/bpf/test_sockmap.c | 18 +++++++++++------- + 1 file changed, 11 insertions(+), 7 deletions(-) + +diff --git a/tools/testing/selftests/bpf/test_sockmap.c b/tools/testing/selftests/bpf/test_sockmap.c +index 0f065273fde32..1d59bed90d80b 100644 +--- a/tools/testing/selftests/bpf/test_sockmap.c ++++ b/tools/testing/selftests/bpf/test_sockmap.c +@@ -420,16 +420,18 @@ static int msg_loop_sendpage(int fd, int iov_length, int cnt, + { + bool drop = opt->drop_expected; + unsigned char k = 0; ++ int i, j, fp; + FILE *file; +- int i, fp; + + file = tmpfile(); + if (!file) { + perror("create file for sendpage"); + return 1; + } +- for (i = 0; i < iov_length * cnt; i++, k++) +- fwrite(&k, sizeof(char), 1, file); ++ for (i = 0; i < cnt; i++, k = 0) { ++ for (j = 0; j < iov_length; j++, k++) ++ fwrite(&k, sizeof(char), 1, file); ++ } + fflush(file); + fseek(file, 0, SEEK_SET); + +@@ -623,7 +625,9 @@ static int msg_loop(int fd, int iov_count, int iov_length, int cnt, + * This is really only useful for testing edge cases in code + * paths. + */ +- total_bytes = (float)iov_count * (float)iov_length * (float)cnt; ++ total_bytes = (float)iov_length * (float)cnt; ++ if (!opt->sendpage) ++ total_bytes *= (float)iov_count; + if (txmsg_apply) + txmsg_pop_total = txmsg_pop * (total_bytes / txmsg_apply); + else +@@ -701,7 +705,7 @@ static int msg_loop(int fd, int iov_count, int iov_length, int cnt, + + if (data) { + int chunk_sz = opt->sendpage ? +- iov_length * cnt : ++ iov_length : + iov_length * iov_count; + + errno = msg_verify_data(&msg, recv, chunk_sz, &k, &bytes_cnt); +@@ -1466,8 +1470,8 @@ static void test_send_many(struct sockmap_options *opt, int cgrp) + + static void test_send_large(struct sockmap_options *opt, int cgrp) + { +- opt->iov_length = 256; +- opt->iov_count = 1024; ++ opt->iov_length = 8192; ++ opt->iov_count = 32; + opt->rate = 2; + test_exec(cgrp, opt); + } +-- +2.43.0 + diff --git a/queue-6.12/selftests-bpf-fix-test_spin_lock_fail.c-s-global-var.patch b/queue-6.12/selftests-bpf-fix-test_spin_lock_fail.c-s-global-var.patch new file mode 100644 index 00000000000..742f5443449 --- /dev/null +++ b/queue-6.12/selftests-bpf-fix-test_spin_lock_fail.c-s-global-var.patch @@ -0,0 +1,50 @@ +From a96b29d20776620bc938e85a4b35d2c19ffafb4b Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Tue, 22 Oct 2024 21:39:06 -0700 +Subject: selftests/bpf: fix test_spin_lock_fail.c's global vars usage + +From: Andrii Nakryiko <andrii@kernel.org> + +[ Upstream commit 1b2bfc29695d273492c3dd8512775261f3272686 ] + +Global variables of special types (like `struct bpf_spin_lock`) make +underlying ARRAY maps non-mmapable. To make this work with libbpf's +mmaping logic, application is expected to declare such special variables +as static, so libbpf doesn't even attempt to mmap() such ARRAYs. + +test_spin_lock_fail.c didn't follow this rule, but given it relied on +this test to trigger failures, this went unnoticed, as we never got to +the step of mmap()'ing these ARRAY maps. + +It is fragile and relies on specific sequence of libbpf steps, which are +an internal implementation details. + +Fix the test by marking lockA and lockB as static. + +Fixes: c48748aea4f8 ("selftests/bpf: Add failure test cases for spin lock pairing") +Signed-off-by: Andrii Nakryiko <andrii@kernel.org> +Link: https://lore.kernel.org/r/20241023043908.3834423-2-andrii@kernel.org +Signed-off-by: Alexei Starovoitov <ast@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + tools/testing/selftests/bpf/progs/test_spin_lock_fail.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/tools/testing/selftests/bpf/progs/test_spin_lock_fail.c b/tools/testing/selftests/bpf/progs/test_spin_lock_fail.c +index 43f40c4fe241a..1c8b678e2e9a3 100644 +--- a/tools/testing/selftests/bpf/progs/test_spin_lock_fail.c ++++ b/tools/testing/selftests/bpf/progs/test_spin_lock_fail.c +@@ -28,8 +28,8 @@ struct { + }, + }; + +-SEC(".data.A") struct bpf_spin_lock lockA; +-SEC(".data.B") struct bpf_spin_lock lockB; ++static struct bpf_spin_lock lockA SEC(".data.A"); ++static struct bpf_spin_lock lockB SEC(".data.B"); + + SEC("?tc") + int lock_id_kptr_preserve(void *ctx) +-- +2.43.0 + diff --git a/queue-6.12/selftests-bpf-fix-total_bytes-in-msg_loop_rx-in-test.patch b/queue-6.12/selftests-bpf-fix-total_bytes-in-msg_loop_rx-in-test.patch new file mode 100644 index 00000000000..3cfa3556aac --- /dev/null +++ b/queue-6.12/selftests-bpf-fix-total_bytes-in-msg_loop_rx-in-test.patch @@ -0,0 +1,71 @@ +From 2a885385205e25dae799d83eb002fe60af57f260 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Wed, 6 Nov 2024 22:25:15 +0000 +Subject: selftests/bpf: Fix total_bytes in msg_loop_rx in test_sockmap + +From: Zijian Zhang <zijianzhang@bytedance.com> + +[ Upstream commit 523dffccbadea0cfd65f1ff04944b864c558c4a8 ] + +total_bytes in msg_loop_rx should also take push into account, otherwise +total_bytes will be a smaller value, which makes the msg_loop_rx end early. + +Besides, total_bytes has already taken pop into account, so we don't need +to subtract some bytes from iov_buf in sendmsg_test. The additional +subtraction may make total_bytes a negative number, and msg_loop_rx will +just end without checking anything. + +Fixes: 18d4e900a450 ("bpf: Selftests, improve test_sockmap total bytes counter") +Fixes: d69672147faa ("selftests, bpf: Add one test for sockmap with strparser") +Signed-off-by: Zijian Zhang <zijianzhang@bytedance.com> +Reviewed-by: John Fastabend <john.fastabend@gmail.com> +Link: https://lore.kernel.org/r/20241106222520.527076-4-zijianzhang@bytedance.com +Signed-off-by: Martin KaFai Lau <martin.lau@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + tools/testing/selftests/bpf/test_sockmap.c | 12 +++++++----- + 1 file changed, 7 insertions(+), 5 deletions(-) + +diff --git a/tools/testing/selftests/bpf/test_sockmap.c b/tools/testing/selftests/bpf/test_sockmap.c +index 1d59bed90d80b..5f4558f1f0049 100644 +--- a/tools/testing/selftests/bpf/test_sockmap.c ++++ b/tools/testing/selftests/bpf/test_sockmap.c +@@ -606,8 +606,8 @@ static int msg_loop(int fd, int iov_count, int iov_length, int cnt, + } + clock_gettime(CLOCK_MONOTONIC, &s->end); + } else { ++ float total_bytes, txmsg_pop_total, txmsg_push_total; + int slct, recvp = 0, recv, max_fd = fd; +- float total_bytes, txmsg_pop_total; + int fd_flags = O_NONBLOCK; + struct timeval timeout; + unsigned char k = 0; +@@ -628,10 +628,14 @@ static int msg_loop(int fd, int iov_count, int iov_length, int cnt, + total_bytes = (float)iov_length * (float)cnt; + if (!opt->sendpage) + total_bytes *= (float)iov_count; +- if (txmsg_apply) ++ if (txmsg_apply) { ++ txmsg_push_total = txmsg_end_push * (total_bytes / txmsg_apply); + txmsg_pop_total = txmsg_pop * (total_bytes / txmsg_apply); +- else ++ } else { ++ txmsg_push_total = txmsg_end_push * cnt; + txmsg_pop_total = txmsg_pop * cnt; ++ } ++ total_bytes += txmsg_push_total; + total_bytes -= txmsg_pop_total; + err = clock_gettime(CLOCK_MONOTONIC, &s->start); + if (err < 0) +@@ -800,8 +804,6 @@ static int sendmsg_test(struct sockmap_options *opt) + + rxpid = fork(); + if (rxpid == 0) { +- if (txmsg_pop || txmsg_start_pop) +- iov_buf -= (txmsg_pop - txmsg_start_pop + 1); + if (opt->drop_expected || txmsg_ktls_skb_drop) + _exit(0); + +-- +2.43.0 + diff --git a/queue-6.12/selftests-bpf-fix-txmsg_redir-of-test_txmsg_pull-in-.patch b/queue-6.12/selftests-bpf-fix-txmsg_redir-of-test_txmsg_pull-in-.patch new file mode 100644 index 00000000000..b173c4e9b9c --- /dev/null +++ b/queue-6.12/selftests-bpf-fix-txmsg_redir-of-test_txmsg_pull-in-.patch @@ -0,0 +1,38 @@ +From 797879802e191b2ce80a5cc28f9f77ad09421545 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Sat, 12 Oct 2024 20:37:31 +0000 +Subject: selftests/bpf: Fix txmsg_redir of test_txmsg_pull in test_sockmap + +From: Zijian Zhang <zijianzhang@bytedance.com> + +[ Upstream commit b29e231d66303c12b7b8ac3ac2a057df06b161e8 ] + +txmsg_redir in "Test pull + redirect" case of test_txmsg_pull should be +1 instead of 0. + +Fixes: 328aa08a081b ("bpf: Selftests, break down test_sockmap into subtests") +Acked-by: John Fastabend <john.fastabend@gmail.com> +Signed-off-by: Zijian Zhang <zijianzhang@bytedance.com> +Link: https://lore.kernel.org/r/20241012203731.1248619-3-zijianzhang@bytedance.com +Signed-off-by: Martin KaFai Lau <martin.lau@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + tools/testing/selftests/bpf/test_sockmap.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/tools/testing/selftests/bpf/test_sockmap.c b/tools/testing/selftests/bpf/test_sockmap.c +index 8249f3c1fbd65..075c93ed143e6 100644 +--- a/tools/testing/selftests/bpf/test_sockmap.c ++++ b/tools/testing/selftests/bpf/test_sockmap.c +@@ -1606,7 +1606,7 @@ static void test_txmsg_pull(int cgrp, struct sockmap_options *opt) + test_send_large(opt, cgrp); + + /* Test pull + redirect */ +- txmsg_redir = 0; ++ txmsg_redir = 1; + txmsg_start = 1; + txmsg_end = 2; + test_send(opt, cgrp); +-- +2.43.0 + diff --git a/queue-6.12/selftests-bpf-fix-uprobe_multi-compilation-error.patch b/queue-6.12/selftests-bpf-fix-uprobe_multi-compilation-error.patch new file mode 100644 index 00000000000..5280747cdc1 --- /dev/null +++ b/queue-6.12/selftests-bpf-fix-uprobe_multi-compilation-error.patch @@ -0,0 +1,55 @@ +From aa6340ac7d2f595524d518f60f932d542e782bc4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Thu, 26 Sep 2024 15:49:48 +0100 +Subject: selftests/bpf: Fix uprobe_multi compilation error +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Alan Maguire <alan.maguire@oracle.com> + +[ Upstream commit c27d8235ba97139d7a085367ff57773902eb3fc5 ] + +When building selftests, the following was seen: + +uprobe_multi.c: In function ‘trigger_uprobe’: +uprobe_multi.c:108:40: error: ‘MADV_PAGEOUT’ undeclared (first use in this function) + 108 | madvise(addr, page_sz, MADV_PAGEOUT); + | ^~~~~~~~~~~~ +uprobe_multi.c:108:40: note: each undeclared identifier is reported only once for each function it appears in +make: *** [Makefile:850: bpf-next/tools/testing/selftests/bpf/uprobe_multi] Error 1 + +...even with updated UAPI headers. It seems the above value is +defined in UAPI <linux/mman.h> but including that file triggers +other redefinition errors. Simplest solution is to add a +guarded definition, as was done for MADV_POPULATE_READ. + +Fixes: 3c217a182018 ("selftests/bpf: add build ID tests") +Signed-off-by: Alan Maguire <alan.maguire@oracle.com> +Signed-off-by: Andrii Nakryiko <andrii@kernel.org> +Acked-by: Eduard Zingerman <eddyz87@gmail.com> +Link: https://lore.kernel.org/bpf/20240926144948.172090-1-alan.maguire@oracle.com +Signed-off-by: Alexei Starovoitov <ast@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + tools/testing/selftests/bpf/uprobe_multi.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/tools/testing/selftests/bpf/uprobe_multi.c b/tools/testing/selftests/bpf/uprobe_multi.c +index c7828b13e5ffd..dd38dc68f6359 100644 +--- a/tools/testing/selftests/bpf/uprobe_multi.c ++++ b/tools/testing/selftests/bpf/uprobe_multi.c +@@ -12,6 +12,10 @@ + #define MADV_POPULATE_READ 22 + #endif + ++#ifndef MADV_PAGEOUT ++#define MADV_PAGEOUT 21 ++#endif ++ + int __attribute__((weak)) uprobe(void) + { + return 0; +-- +2.43.0 + diff --git a/queue-6.12/selftests-bpf-skip-the-timer_lockup-test-for-single-.patch b/queue-6.12/selftests-bpf-skip-the-timer_lockup-test-for-single-.patch new file mode 100644 index 00000000000..b61813d34f6 --- /dev/null +++ b/queue-6.12/selftests-bpf-skip-the-timer_lockup-test-for-single-.patch @@ -0,0 +1,62 @@ +From e8fa8e5b34917d6f8f2dabff2152091c2c17d7fa Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Thu, 7 Nov 2024 12:52:31 +0100 +Subject: selftests/bpf: skip the timer_lockup test for single-CPU nodes + +From: Viktor Malik <vmalik@redhat.com> + +[ Upstream commit 937a1c29a287e8f48c4cea714c76a13e14d989ac ] + +The timer_lockup test needs 2 CPUs to work, on single-CPU nodes it fails +to set thread affinity to CPU 1 since it doesn't exist: + + # ./test_progs -t timer_lockup + test_timer_lockup:PASS:timer_lockup__open_and_load 0 nsec + test_timer_lockup:PASS:pthread_create thread1 0 nsec + test_timer_lockup:PASS:pthread_create thread2 0 nsec + timer_lockup_thread:PASS:cpu affinity 0 nsec + timer_lockup_thread:FAIL:cpu affinity unexpected error: 22 (errno 0) + test_timer_lockup:PASS: 0 nsec + #406 timer_lockup:FAIL + +Skip the test if only 1 CPU is available. + +Signed-off-by: Viktor Malik <vmalik@redhat.com> +Fixes: 50bd5a0c658d1 ("selftests/bpf: Add timer lockup selftest") +Tested-by: Philo Lu <lulie@linux.alibaba.com> +Acked-by: Kumar Kartikeya Dwivedi <memxor@gmail.com> +Link: https://lore.kernel.org/r/20241107115231.75200-1-vmalik@redhat.com +Signed-off-by: Alexei Starovoitov <ast@kernel.org> +Signed-off-by: Andrii Nakryiko <andrii@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + tools/testing/selftests/bpf/prog_tests/timer_lockup.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/tools/testing/selftests/bpf/prog_tests/timer_lockup.c b/tools/testing/selftests/bpf/prog_tests/timer_lockup.c +index 871d16cb95cfd..1a2f99596916f 100644 +--- a/tools/testing/selftests/bpf/prog_tests/timer_lockup.c ++++ b/tools/testing/selftests/bpf/prog_tests/timer_lockup.c +@@ -5,6 +5,7 @@ + #include <test_progs.h> + #include <pthread.h> + #include <network_helpers.h> ++#include <sys/sysinfo.h> + + #include "timer_lockup.skel.h" + +@@ -52,6 +53,11 @@ void test_timer_lockup(void) + pthread_t thrds[2]; + void *ret; + ++ if (get_nprocs() < 2) { ++ test__skip(); ++ return; ++ } ++ + skel = timer_lockup__open_and_load(); + if (!ASSERT_OK_PTR(skel, "timer_lockup__open_and_load")) + return; +-- +2.43.0 + diff --git a/queue-6.12/selftests-mount_setattr-fix-failures-on-64k-page_siz.patch b/queue-6.12/selftests-mount_setattr-fix-failures-on-64k-page_siz.patch new file mode 100644 index 00000000000..3c7cad0f6af --- /dev/null +++ b/queue-6.12/selftests-mount_setattr-fix-failures-on-64k-page_siz.patch @@ -0,0 +1,67 @@ +From 3d63ea9501083006b73f82cc7b672484821d4cb6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Sat, 16 Nov 2024 00:41:14 +1100 +Subject: selftests/mount_setattr: Fix failures on 64K PAGE_SIZE kernels + +From: Michael Ellerman <mpe@ellerman.id.au> + +[ Upstream commit f13242a46438e690067a4bf47068fde4d5719947 ] + +Currently the mount_setattr_test fails on machines with a 64K PAGE_SIZE, +with errors such as: + + # RUN mount_setattr_idmapped.invalid_fd_negative ... + mkfs.ext4: No space left on device while writing out and closing file system + # mount_setattr_test.c:1055:invalid_fd_negative:Expected system("mkfs.ext4 -q /mnt/C/ext4.img") (256) == 0 (0) + # invalid_fd_negative: Test terminated by assertion + # FAIL mount_setattr_idmapped.invalid_fd_negative + not ok 12 mount_setattr_idmapped.invalid_fd_negative + +The code creates a 100,000 byte tmpfs: + + ASSERT_EQ(mount("testing", "/mnt", "tmpfs", MS_NOATIME | MS_NODEV, + "size=100000,mode=700"), 0); + +And then a little later creates a 2MB ext4 filesystem in that tmpfs: + + ASSERT_EQ(ftruncate(img_fd, 1024 * 2048), 0); + ASSERT_EQ(system("mkfs.ext4 -q /mnt/C/ext4.img"), 0); + +At first glance it seems like that should never work, after all 2MB is +larger than 100,000 bytes. However the filesystem image doesn't actually +occupy 2MB on "disk" (actually RAM, due to tmpfs). On 4K kernels the +ext4.img uses ~84KB of actual space (according to du), which just fits. + +However on 64K PAGE_SIZE kernels the ext4.img takes at least 256KB, +which is too large to fit in the tmpfs, hence the errors. + +It seems fraught to rely on the ext4.img taking less space on disk than +the allocated size, so instead create the tmpfs with a size of 2MB. With +that all 21 tests pass on 64K PAGE_SIZE kernels. + +Fixes: 01eadc8dd96d ("tests: add mount_setattr() selftests") +Signed-off-by: Michael Ellerman <mpe@ellerman.id.au> +Link: https://lore.kernel.org/r/20241115134114.1219555-1-mpe@ellerman.id.au +Reviewed-by: Ritesh Harjani (IBM) <ritesh.list@gmail.com> +Signed-off-by: Christian Brauner <brauner@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + tools/testing/selftests/mount_setattr/mount_setattr_test.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/tools/testing/selftests/mount_setattr/mount_setattr_test.c b/tools/testing/selftests/mount_setattr/mount_setattr_test.c +index 68801e1a9ec2d..70f65eb320a7a 100644 +--- a/tools/testing/selftests/mount_setattr/mount_setattr_test.c ++++ b/tools/testing/selftests/mount_setattr/mount_setattr_test.c +@@ -1026,7 +1026,7 @@ FIXTURE_SETUP(mount_setattr_idmapped) + "size=100000,mode=700"), 0); + + ASSERT_EQ(mount("testing", "/mnt", "tmpfs", MS_NOATIME | MS_NODEV, +- "size=100000,mode=700"), 0); ++ "size=2m,mode=700"), 0); + + ASSERT_EQ(mkdir("/mnt/A", 0777), 0); + +-- +2.43.0 + diff --git a/queue-6.12/selftests-net-really-check-for-bg-process-completion.patch b/queue-6.12/selftests-net-really-check-for-bg-process-completion.patch new file mode 100644 index 00000000000..3f321cdf47e --- /dev/null +++ b/queue-6.12/selftests-net-really-check-for-bg-process-completion.patch @@ -0,0 +1,43 @@ +From fc490ab3732b3f61fed5283b39696d0e2ddbb7a4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Tue, 5 Nov 2024 19:23:51 +0100 +Subject: selftests: net: really check for bg process completion + +From: Paolo Abeni <pabeni@redhat.com> + +[ Upstream commit 52ed077aa6336dbef83a2d6d21c52d1706fb7f16 ] + +A recent refactor transformed the check for process completion +in a true statement, due to a typo. + +As a result, the relevant test-case is unable to catch the +regression it was supposed to detect. + +Restore the correct condition. + +Fixes: 691bb4e49c98 ("selftests: net: avoid just another constant wait") +Signed-off-by: Paolo Abeni <pabeni@redhat.com> +Reviewed-by: David Ahern <dsahern@kernel.org> +Link: https://patch.msgid.link/0e6f213811f8e93a235307e683af8225cc6277ae.1730828007.git.pabeni@redhat.com +Signed-off-by: Jakub Kicinski <kuba@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + tools/testing/selftests/net/pmtu.sh | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/tools/testing/selftests/net/pmtu.sh b/tools/testing/selftests/net/pmtu.sh +index 569bce8b6383e..6c651c880fe83 100755 +--- a/tools/testing/selftests/net/pmtu.sh ++++ b/tools/testing/selftests/net/pmtu.sh +@@ -2056,7 +2056,7 @@ check_running() { + pid=${1} + cmd=${2} + +- [ "$(cat /proc/${pid}/cmdline 2>/dev/null | tr -d '\0')" = "{cmd}" ] ++ [ "$(cat /proc/${pid}/cmdline 2>/dev/null | tr -d '\0')" = "${cmd}" ] + } + + test_cleanup_vxlanX_exception() { +-- +2.43.0 + diff --git a/queue-6.12/selftests-netfilter-fix-missing-return-values-in-con.patch b/queue-6.12/selftests-netfilter-fix-missing-return-values-in-con.patch new file mode 100644 index 00000000000..1ccbae5afd0 --- /dev/null +++ b/queue-6.12/selftests-netfilter-fix-missing-return-values-in-con.patch @@ -0,0 +1,54 @@ +From 152ae842771aa9eba25668ed8ddbfa9f5d4919de Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Fri, 8 Nov 2024 16:13:58 +0800 +Subject: selftests: netfilter: Fix missing return values in + conntrack_dump_flush + +From: guanjing <guanjing@cmss.chinamobile.com> + +[ Upstream commit 041bd1e4f2d82859690cd8b41c35f0f9404c3770 ] + +Fix the bug of some functions were missing return values. + +Fixes: eff3c558bb7e ("netfilter: ctnetlink: support filtering by zone") +Signed-off-by: Guan Jing <guanjing@cmss.chinamobile.com> +Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + .../testing/selftests/net/netfilter/conntrack_dump_flush.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/tools/testing/selftests/net/netfilter/conntrack_dump_flush.c b/tools/testing/selftests/net/netfilter/conntrack_dump_flush.c +index 254ff03297f06..5f827e10717d1 100644 +--- a/tools/testing/selftests/net/netfilter/conntrack_dump_flush.c ++++ b/tools/testing/selftests/net/netfilter/conntrack_dump_flush.c +@@ -43,6 +43,8 @@ static int build_cta_tuple_v4(struct nlmsghdr *nlh, int type, + mnl_attr_nest_end(nlh, nest_proto); + + mnl_attr_nest_end(nlh, nest); ++ ++ return 0; + } + + static int build_cta_tuple_v6(struct nlmsghdr *nlh, int type, +@@ -71,6 +73,8 @@ static int build_cta_tuple_v6(struct nlmsghdr *nlh, int type, + mnl_attr_nest_end(nlh, nest_proto); + + mnl_attr_nest_end(nlh, nest); ++ ++ return 0; + } + + static int build_cta_proto(struct nlmsghdr *nlh) +@@ -90,6 +94,8 @@ static int build_cta_proto(struct nlmsghdr *nlh) + mnl_attr_nest_end(nlh, nest_proto); + + mnl_attr_nest_end(nlh, nest); ++ ++ return 0; + } + + static int conntrack_data_insert(struct mnl_socket *sock, struct nlmsghdr *nlh, +-- +2.43.0 + diff --git a/queue-6.12/selftests-resctrl-fix-memory-overflow-due-to-unhandl.patch b/queue-6.12/selftests-resctrl-fix-memory-overflow-due-to-unhandl.patch new file mode 100644 index 00000000000..c2607f3dbff --- /dev/null +++ b/queue-6.12/selftests-resctrl-fix-memory-overflow-due-to-unhandl.patch @@ -0,0 +1,53 @@ +From 8f73a15b864688aa5a9ddbeb9a8ad9fc771d683e Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Thu, 24 Oct 2024 14:18:40 -0700 +Subject: selftests/resctrl: Fix memory overflow due to unhandled wraparound +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Reinette Chatre <reinette.chatre@intel.com> + +[ Upstream commit caf02626b2bf164a02c808240f19dbf97aced664 ] + +alloc_buffer() allocates and initializes (with random data) a +buffer of requested size. The initialization starts from the beginning +of the allocated buffer and incrementally assigns sizeof(uint64_t) random +data to each cache line. The initialization uses the size of the +buffer to control the initialization flow, decrementing the amount of +buffer needing to be initialized after each iteration. + +The size of the buffer is stored in an unsigned (size_t) variable s64 +and the test "s64 > 0" is used to decide if initialization is complete. +The problem is that decrementing the buffer size may wrap around +if the buffer size is not divisible by "CL_SIZE / sizeof(uint64_t)" +resulting in the "s64 > 0" test being true and memory beyond the buffer +"initialized". + +Use a signed value for the buffer size to support all buffer sizes. + +Fixes: a2561b12fe39 ("selftests/resctrl: Add built in benchmark") +Signed-off-by: Reinette Chatre <reinette.chatre@intel.com> +Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com> +Signed-off-by: Shuah Khan <skhan@linuxfoundation.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + tools/testing/selftests/resctrl/fill_buf.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/tools/testing/selftests/resctrl/fill_buf.c b/tools/testing/selftests/resctrl/fill_buf.c +index ae120f1735c0b..34e5df721430e 100644 +--- a/tools/testing/selftests/resctrl/fill_buf.c ++++ b/tools/testing/selftests/resctrl/fill_buf.c +@@ -127,7 +127,7 @@ unsigned char *alloc_buffer(size_t buf_size, int memflush) + { + void *buf = NULL; + uint64_t *p64; +- size_t s64; ++ ssize_t s64; + int ret; + + ret = posix_memalign(&buf, PAGE_SIZE, buf_size); +-- +2.43.0 + diff --git a/queue-6.12/selftests-resctrl-print-accurate-buffer-size-as-part.patch b/queue-6.12/selftests-resctrl-print-accurate-buffer-size-as-part.patch new file mode 100644 index 00000000000..6ec8347a3ad --- /dev/null +++ b/queue-6.12/selftests-resctrl-print-accurate-buffer-size-as-part.patch @@ -0,0 +1,83 @@ +From 7324a12900b3a7ae0ba47f8e4277335a5181cc90 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Thu, 24 Oct 2024 14:18:39 -0700 +Subject: selftests/resctrl: Print accurate buffer size as part of MBM results +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Reinette Chatre <reinette.chatre@intel.com> + +[ Upstream commit 1b4840395f08e9723a15fea42c2d31090e8375f3 ] + +By default the MBM test uses the "fill_buf" benchmark to keep reading +from a buffer with size DEFAULT_SPAN while measuring memory bandwidth. +User space can provide an alternate benchmark or amend the size of +the buffer "fill_buf" should use. + +Analysis of the MBM measurements do not require that a buffer be used +and thus do not require knowing the size of the buffer if it was used +during testing. Even so, the buffer size is printed as informational +as part of the MBM test results. What is printed as buffer size is +hardcoded as DEFAULT_SPAN, even if the test relied on another benchmark +(that may or may not use a buffer) or if user space amended the buffer +size. + +Ensure that accurate buffer size is printed when using "fill_buf" +benchmark and omit the buffer size information if another benchmark +is used. + +Fixes: ecdbb911f22d ("selftests/resctrl: Add MBM test") +Signed-off-by: Reinette Chatre <reinette.chatre@intel.com> +Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com> +Signed-off-by: Shuah Khan <skhan@linuxfoundation.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + tools/testing/selftests/resctrl/mbm_test.c | 16 ++++++++++++++-- + 1 file changed, 14 insertions(+), 2 deletions(-) + +diff --git a/tools/testing/selftests/resctrl/mbm_test.c b/tools/testing/selftests/resctrl/mbm_test.c +index 6b5a3b52d861b..cf08ba5e314e2 100644 +--- a/tools/testing/selftests/resctrl/mbm_test.c ++++ b/tools/testing/selftests/resctrl/mbm_test.c +@@ -40,7 +40,8 @@ show_bw_info(unsigned long *bw_imc, unsigned long *bw_resc, size_t span) + ksft_print_msg("%s Check MBM diff within %d%%\n", + ret ? "Fail:" : "Pass:", MAX_DIFF_PERCENT); + ksft_print_msg("avg_diff_per: %d%%\n", avg_diff_per); +- ksft_print_msg("Span (MB): %zu\n", span / MB); ++ if (span) ++ ksft_print_msg("Span (MB): %zu\n", span / MB); + ksft_print_msg("avg_bw_imc: %lu\n", avg_bw_imc); + ksft_print_msg("avg_bw_resc: %lu\n", avg_bw_resc); + +@@ -138,15 +139,26 @@ static int mbm_run_test(const struct resctrl_test *test, const struct user_param + .setup = mbm_setup, + .measure = mbm_measure, + }; ++ char *endptr = NULL; ++ size_t span = 0; + int ret; + + remove(RESULT_FILE_NAME); + ++ if (uparams->benchmark_cmd[0] && strcmp(uparams->benchmark_cmd[0], "fill_buf") == 0) { ++ if (uparams->benchmark_cmd[1] && *uparams->benchmark_cmd[1] != '\0') { ++ errno = 0; ++ span = strtoul(uparams->benchmark_cmd[1], &endptr, 10); ++ if (errno || *endptr != '\0') ++ return -EINVAL; ++ } ++ } ++ + ret = resctrl_val(test, uparams, uparams->benchmark_cmd, ¶m); + if (ret) + return ret; + +- ret = check_results(DEFAULT_SPAN); ++ ret = check_results(span); + if (ret && (get_vendor() == ARCH_INTEL)) + ksft_print_msg("Intel MBM may be inaccurate when Sub-NUMA Clustering is enabled. Check BIOS configuration.\n"); + +-- +2.43.0 + diff --git a/queue-6.12/selftests-resctrl-protect-against-array-overrun-duri.patch b/queue-6.12/selftests-resctrl-protect-against-array-overrun-duri.patch new file mode 100644 index 00000000000..dff26793a63 --- /dev/null +++ b/queue-6.12/selftests-resctrl-protect-against-array-overrun-duri.patch @@ -0,0 +1,67 @@ +From 23624d5ea5428befcf5942efd83250cb7cdb970f Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Thu, 24 Oct 2024 14:18:41 -0700 +Subject: selftests/resctrl: Protect against array overrun during iMC config + parsing +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Reinette Chatre <reinette.chatre@intel.com> + +[ Upstream commit 48ed4e799e8fbebae838dca404a8527763d41191 ] + +The MBM and MBA tests need to discover the event and umask with which to +configure the performance event used to measure read memory bandwidth. +This is done by parsing the +/sys/bus/event_source/devices/uncore_imc_<imc instance>/events/cas_count_read +file for each iMC instance that contains the formatted +output: "event=<event>,umask=<umask>" + +Parsing of cas_count_read contents is done by initializing an array of +MAX_TOKENS elements with tokens (deliminated by "=,") from this file. +Remove the unnecessary append of a delimiter to the string needing to be +parsed. Per the strtok() man page: "delimiter bytes at the start or end of +the string are ignored". This has no impact on the token placement within +the array. + +After initialization, the actual event and umask is determined by +parsing the tokens directly following the "event" and "umask" tokens +respectively. + +Iterating through the array up to index "i < MAX_TOKENS" but then +accessing index "i + 1" risks array overrun during the final iteration. +Avoid array overrun by ensuring that the index used within for +loop will always be valid. + +Fixes: 1d3f08687d76 ("selftests/resctrl: Read memory bandwidth from perf IMC counter and from resctrl file system") +Signed-off-by: Reinette Chatre <reinette.chatre@intel.com> +Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com> +Signed-off-by: Shuah Khan <skhan@linuxfoundation.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + tools/testing/selftests/resctrl/resctrl_val.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/tools/testing/selftests/resctrl/resctrl_val.c b/tools/testing/selftests/resctrl/resctrl_val.c +index 8c275f6b4dd77..f118f659e8960 100644 +--- a/tools/testing/selftests/resctrl/resctrl_val.c ++++ b/tools/testing/selftests/resctrl/resctrl_val.c +@@ -83,13 +83,12 @@ void get_event_and_umask(char *cas_count_cfg, int count, bool op) + char *token[MAX_TOKENS]; + int i = 0; + +- strcat(cas_count_cfg, ","); + token[0] = strtok(cas_count_cfg, "=,"); + + for (i = 1; i < MAX_TOKENS; i++) + token[i] = strtok(NULL, "=,"); + +- for (i = 0; i < MAX_TOKENS; i++) { ++ for (i = 0; i < MAX_TOKENS - 1; i++) { + if (!token[i]) + break; + if (strcmp(token[i], "event") == 0) { +-- +2.43.0 + diff --git a/queue-6.12/series b/queue-6.12/series index 26393bfe315..04e256dde50 100644 --- a/queue-6.12/series +++ b/queue-6.12/series @@ -1 +1,622 @@ maintainers-appoint-myself-the-xfs-maintainer-for-6..patch +drm-amd-display-skip-invalid-streams-from-dsc-policy.patch +drm-amd-display-fix-incorrect-dsc-recompute-trigger.patch +s390-facilities-fix-warning-about-shadow-of-global-v.patch +s390-virtio_ccw-fix-dma_parm-pointer-not-set-up.patch +efs-fix-the-efs-new-mount-api-implementation.patch +arm64-probes-disable-kprobes-uprobes-on-mops-instruc.patch +kselftest-arm64-hwcap-fix-f8dp2-cpuinfo-name.patch +kselftest-arm64-mte-fix-printf-type-warnings-about-_.patch +kselftest-arm64-mte-fix-printf-type-warnings-about-l.patch +block-fs-pass-an-iocb-to-generic_atomic_write_valid.patch +fs-block-check-for-iocb_direct-in-generic_atomic_wri.patch +s390-cio-do-not-unregister-the-subchannel-based-on-d.patch +s390-pageattr-implement-missing-kernel_page_present.patch +x86-pvh-call-c-code-via-the-kernel-virtual-mapping.patch +brd-defer-automatic-disk-creation-until-module-initi.patch +ext4-avoid-remount-errors-with-abort-mount-option.patch +mips-asm-fix-warning-when-disabling-mips_fp_support.patch +s390-cpum_sf-fix-and-protect-memory-allocation-of-sd.patch +initramfs-avoid-filename-buffer-overrun.patch +arm64-expose-id_aa64isar1_el1.xs-to-sanitised-featur.patch +kselftest-arm64-fix-encoding-for-sve-b16b16-test.patch +nvme-pci-fix-freeing-of-the-hmb-descriptor-table.patch +m68k-mvme147-fix-scsi-controller-irq-numbers.patch +m68k-mvme147-reinstate-early-console.patch +arm64-fix-.data.rel.ro-size-assertion-when-config_lt.patch +acpi-arm64-adjust-error-handling-procedure-in-gtdt_p.patch +loop-fix-type-of-block-size.patch +cachefiles-fix-incorrect-length-return-value-in-cach.patch +cachefiles-fix-missing-pos-updates-in-cachefiles_ond.patch +cachefiles-fix-null-pointer-dereference-in-object-fi.patch +netfs-fscache-add-a-memory-barrier-for-fscache_volum.patch +block-take-chunk_sectors-into-account-in-bio_split_w.patch +block-fix-bio_split_rw_at-to-take-zone_write_granula.patch +s390-syscalls-avoid-creation-of-arch-arch-directory.patch +hfsplus-don-t-query-the-device-logical-block-size-mu.patch +ext4-fix-race-in-buffer_head-read-fault-injection.patch +nvme-pci-reverse-request-order-in-nvme_queue_rqs.patch +virtio_blk-reverse-request-order-in-virtio_queue_rqs.patch +crypto-mxs-dcp-fix-aes-cbc-with-hardware-bound-keys.patch +crypto-caam-fix-the-pointer-passed-to-caam_qi_shutdo.patch +crypto-qat-remove-check-after-debugfs_create_dir.patch +crypto-powerpc-p10-aes-gcm-register-modules-as-simd.patch +crypto-powerpc-p10-aes-gcm-add-dependency-on-crypto_.patch +crypto-qat-qat_420xx-fix-off-by-one-in-uof_get_name.patch +crypto-qat-qat_4xxx-fix-off-by-one-in-uof_get_name.patch +firmware-google-unregister-driver_info-on-failure.patch +edac-bluefield-fix-potential-integer-overflow.patch +crypto-qat-remove-faulty-arbiter-config-reset.patch +thermal-core-initialize-thermal-zones-before-registe.patch +thermal-core-rearrange-pm-notification-code.patch +thermal-core-represent-suspend-related-thermal-zone-.patch +thermal-core-mark-thermal-zones-as-initializing-to-s.patch +thermal-core-fix-race-between-zone-registration-and-.patch +edac-fsl_ddr-fix-bad-bit-shift-operations.patch +edac-skx_common-differentiate-memory-error-sources.patch +edac-skx_common-i10nm-fix-incorrect-far-memory-error.patch +crypto-pcrypt-call-crypto-layer-directly-when-padata.patch +crypto-cavium-fix-the-if-condition-to-exit-loop-afte.patch +cpufreq-amd-pstate-don-t-update-cppc-request-in-amd_.patch +amd-pstate-set-min_perf-to-nominal_perf-for-active-m.patch +crypto-hisilicon-qm-disable-same-error-report-before.patch +edac-igen6-avoid-segmentation-fault-on-module-unload.patch +crypto-qat-fix-missing-destroy_workqueue-in-adf_init.patch +crypto-inside-secure-fix-the-return-value-of-safexce.patch +sched-cpufreq-ensure-sd-is-rebuilt-for-eas-check.patch +doc-rcu-update-printed-dynticks-counter-bits.patch +rcu-srcutiny-don-t-return-before-reenabling-preempti.patch +rcu-kvfree-fix-data-race-in-__mod_timer-kvfree_call_.patch +rcu-nocb-fix-missed-rcu-barrier-on-deoffloading.patch +hwmon-pmbus-core-clear-faults-after-setting-smbalert.patch +hwmon-nct6775-core-fix-overflows-seen-when-writing-l.patch +acpi-cppc-fix-_cpc-register-setting-issue.patch +thermal-testing-use-define_free-and-__free-to-simpli.patch +thermal-testing-initialize-some-variables-annoteded-.patch +crypto-caam-add-error-check-to-caam_rsa_set_priv_key.patch +crypto-bcm-add-error-check-in-the-ahash_hmac_init-fu.patch +crypto-aes-gcm-p10-use-the-correct-bit-to-test-for-p.patch +crypto-cavium-fix-an-error-handling-path-in-cpt_ucod.patch +rcuscale-do-a-proper-cleanup-if-kfree_scale_init-fai.patch +tools-lib-thermal-make-more-generic-the-command-enco.patch +thermal-lib-fix-memory-leak-on-error-in-thermal_genl.patch +x86-unwind-orc-fix-unwind-for-newly-forked-tasks.patch +revert-scripts-faddr2line-check-only-two-symbols-whe.patch +cleanup-remove-address-space-of-returned-pointer.patch +time-partially-revert-cleanup-on-msecs_to_jiffies-do.patch +time-fix-references-to-_msecs_to_jiffies-handling-of.patch +timers-add-missing-read_once-in-__run_timer_base.patch +locking-atomic-x86-use-alt_output_sp-for-__alternati.patch +locking-atomic-x86-use-alt_output_sp-for-__arch_-try.patch +kcsan-seqlock-support-seqcount_latch_t.patch +kcsan-seqlock-fix-incorrect-assumption-in-read_seqbe.patch +sched-ext-remove-sched_fork-hack.patch +locking-rt-add-sparse-annotation-preempt_rt-s-sleepi.patch +rust-helpers-avoid-raw_spin_lock-initialization-for-.patch +clocksource-drivers-sp804-make-user-selectable.patch +clocksource-drivers-timer-ti-dm-fix-child-node-refco.patch +irqchip-riscv-aplic-prevent-crash-when-msi-domain-is.patch +regulator-qcom-smd-make-smd_vreg_rpm-static.patch +spi-spi-fsl-lpspi-use-irqf_no_autoen-flag-in-request.patch +arm64-dts-qcom-qcs6390-rb3gen2-use-modem.mbn-for-mod.patch +arm-dts-renesas-genmai-fix-partition-size-for-qspi-n.patch +drivers-soc-xilinx-add-the-missing-kfree-in-xlnx_add.patch +microblaze-export-xmb_manager-functions.patch +arm64-dts-mediatek-mt8188-fix-wrong-clock-provider-i.patch +arm64-dts-mediatek-mt8395-genio-1200-evk-fix-dtbs_ch.patch +arm64-dts-mt8195-fix-dtbs_check-error-for-mutex-node.patch +arm64-dts-mt8195-fix-dtbs_check-error-for-infracfg_a.patch +arm64-dts-mediatek-mt8183-kukui-disable-dpi-display-.patch +arm64-dts-mt8183-add-port-node-to-dpi-node.patch +soc-ti-smartreflex-use-irqf_no_autoen-flag-in-reques.patch +soc-qcom-geni-se-fix-array-underflow-in-geni_se_clk_.patch +arm64-dts-qcom-sm6350-fix-gpu-frequencies-missing-on.patch +arm64-dts-qcom-sda660-ifc6560-fix-l10a-voltage-range.patch +arm-dts-microchip-sam9x60-add-missing-property-atmel.patch +mmc-mmc_spi-drop-buggy-snprintf.patch +scripts-kernel-doc-do-not-track-section-counter-acro.patch +arm64-dts-qcom-x1e80100-slim7x-drop-orientation-swit.patch +arm64-dts-qcom-x1e80100-vivobook-s15-drop-orientatio.patch +openrisc-implement-fixmap-to-fix-earlycon.patch +efi-libstub-fix-efi_parse_options-ignoring-the-defau.patch +tpm-fix-signed-unsigned-bug-when-checking-event-logs.patch +media-i2c-max96717-clean-up-on-error-in-max96717_sub.patch +media-i2c-vgxy61-fix-an-error-handling-path-in-vgxy6.patch +media-i2c-ds90ub960-fix-missing-return-check-on-ub96.patch +arm64-dts-mt8183-krane-fix-the-address-of-eeprom-at-.patch +arm64-dts-mt8183-kukui-fix-the-address-of-eeprom-at-.patch +arm64-dts-qcom-x1e80100-resize-gic-redistributor-reg.patch +kernel-doc-allow-object-like-macros-in-rest-output.patch +arm64-dts-ti-k3-am62x-phyboard-lyra-drop-unnecessary.patch +gpio-sloppy-logic-analyzer-remove-reference-to-rcu_m.patch +arm64-dts-mediatek-mt8173-elm-hana-add-vdd-supply-to.patch +arm64-dts-mediatek-mt8188-fix-usb3-phy-port-default-.patch +arm64-dts-mediatek-mt8195-cherry-use-correct-audio-c.patch +revert-cgroup-fix-memory-leak-caused-by-missing-cgro.patch +cgroup-bpf-only-cgroup-v2-can-be-attached-by-bpf-pro.patch +regulator-rk808-restrict-dvs-gpios-to-the-rk808-vari.patch +power-sequencing-make-the-qcom-pmu-pwrseq-driver-dep.patch +arm64-tegra-p2180-add-mandatory-compatible-for-wifi-.patch +arm64-dts-rockchip-remove-enable-active-low-from-two.patch +arm64-dts-mt8183-fennel-add-i2c2-s-i2c-scl-internal-.patch +arm64-dts-mt8183-burnet-add-i2c2-s-i2c-scl-internal-.patch +arm64-dts-mt8183-cozmo-add-i2c2-s-i2c-scl-internal-d.patch +arm64-dts-mt8183-damu-add-i2c2-s-i2c-scl-internal-de.patch +pwm-imx27-workaround-of-the-pwm-output-bug-when-decr.patch +arm-dts-cubieboard4-fix-dcdc5-regulator-constraints.patch +arm64-dts-ti-k3-j7200-fix-register-map-for-main-doma.patch +arm64-dts-ti-k3-j7200-fix-clock-ids-for-mcspi-instan.patch +arm64-dts-ti-k3-j721e-fix-clock-ids-for-mcspi-instan.patch +arm64-dts-ti-k3-j721s2-fix-clock-ids-for-mcspi-insta.patch +watchdog-add-has_ioport-dependency-for-sbc8360-and-s.patch +arm64-dts-qcom-x1e80100-update-c4-c5-residency-exit-.patch +dt-bindings-cache-qcom-llcc-fix-x1e80100-reg-entries.patch +of-fdt-add-dt_phys-arg-to-early_init_dt_scan-and-ear.patch +pmdomain-ti-sci-add-missing-of_node_put-for-args.np.patch +spi-tegra210-quad-avoid-shift-out-of-bounds.patch +spi-zynqmp-gqspi-undo-runtime-pm-changes-at-driver-e.patch +regmap-irq-set-lockdep-class-for-hierarchical-irq-do.patch +arm64-dts-renesas-hihope-drop-sound-dai-cells.patch +arm64-dts-imx8mn-tqma8mqnl-mba8mx-usbot-fix-coexiste.patch +arm64-dts-mediatek-mt6358-fix-dtbs_check-error.patch +arm64-dts-mediatek-mt8183-kukui-jacuzzi-fix-dp-bridg.patch +arm64-dts-mediatek-mt8183-kukui-jacuzzi-add-supplies.patch +selftests-resctrl-print-accurate-buffer-size-as-part.patch +selftests-resctrl-fix-memory-overflow-due-to-unhandl.patch +selftests-resctrl-protect-against-array-overrun-duri.patch +firmware-arm_scpi-check-the-dvfs-opp-count-returned-.patch +media-ipu6-fix-dma-and-physical-address-debugging-me.patch +media-ipu6-not-override-the-dma_ops-of-device-in-dri.patch +media-ipu6-remove-architecture-dma-ops-dependency-in.patch +media-venus-fix-enc-dec-destruction-order.patch +media-venus-sync-with-threaded-irq-during-inst-destr.patch +pwm-assume-a-disabled-pwm-to-emit-a-constant-inactiv.patch +media-atomisp-add-check-for-rgby_data-memory-allocat.patch +arm64-dts-rockchip-correct-analog-audio-name-on-indi.patch +sched_ext-scx_bpf_dispatch_from_dsq_set_-are-allowed.patch +hid-hyperv-streamline-driver-probe-to-avoid-devres-i.patch +platform-x86-asus-wmi-fix-inconsistent-use-of-therma.patch +platform-x86-intel-pmt-allow-user-offset-for-pmt-cal.patch +platform-x86-panasonic-laptop-return-errno-correctly.patch +drm-imagination-convert-to-use-time_before-macro.patch +drm-imagination-use-pvr_vm_context_get.patch +drm-mm-mark-drm_mm_interval_tree-functions-with-__ma.patch +drm-vc4-hvs-don-t-write-gamma-luts-on-2711.patch +drm-vc4-hdmi-avoid-hang-with-debug-registers-when-su.patch +drm-vc4-hvs-fix-dlist-debug-not-resetting-the-next-e.patch +drm-vc4-hvs-remove-incorrect-limit-from-hvs_dlist-de.patch +drm-vc4-hvs-correct-logic-on-stopping-an-hvs-channel.patch +wifi-ath9k-add-range-check-for-conn_rsp_epid-in-htc_.patch +drm-omap-fix-possible-null-dereference.patch +drm-omap-fix-locking-in-omap_gem_new_dmabuf.patch +drm-v3d-appease-lockdep-while-updating-gpu-stats.patch +wifi-p54-use-irqf_no_autoen-flag-in-request_irq.patch +wifi-mwifiex-use-irqf_no_autoen-flag-in-request_irq.patch +udmabuf-change-folios-array-from-kmalloc-to-kvmalloc.patch +udmabuf-fix-vmap_udmabuf-error-page-set.patch +drm-imx-dcss-use-irqf_no_autoen-flag-in-request_irq.patch +drm-imx-ipuv3-use-irqf_no_autoen-flag-in-request_irq.patch +drm-imx-parallel-display-drop-edid-override-support.patch +drm-imx-ldb-drop-custom-edid-support.patch +drm-imx-ldb-drop-custom-ddc-bus-support.patch +drm-imx-ldb-switch-to-drm_panel_bridge.patch +drm-imx-parallel-display-switch-to-drm_panel_bridge.patch +drm-imx-add-missing-drm_bridge_connector-dependency.patch +drm-panel-nt35510-make-new-commands-optional.patch +drm-v3d-address-race-condition-in-mmu-flush.patch +drm-v3d-flush-the-mmu-before-we-supply-more-memory-t.patch +drm-amdgpu-fix-jpeg-v4.0.3-register-write.patch +wifi-ath10k-fix-invalid-vht-parameters-in-supported_.patch +wifi-ath10k-fix-invalid-vht-parameters-in-supported_.patch-16142 +wifi-ath12k-skip-rx-tid-cleanup-for-self-peer.patch +dt-bindings-vendor-prefixes-add-neofidelity-inc.patch +asoc-fsl_micfil-fix-regmap_write_bits-usage.patch +asoc-dt-bindings-mt6359-update-generic-node-name-and.patch +drm-amdgpu-gfx9-add-cleaner-shader-deinitialization-.patch +asoc-fsl-asoc-card-add-missing-handling-of-hp-mic-dt.patch +drm-bridge-anx7625-drop-edid-cache-on-bridge-power-o.patch +drm-bridge-it6505-drop-edid-cache-on-bridge-power-of.patch +libbpf-fix-expected_attach_type-set-handling-in-prog.patch +libbpf-fix-output-.symtab-byte-order-during-linking.patch +selftests-bpf-fix-uprobe_multi-compilation-error.patch +dlm-fix-swapped-args-sb_flags-vs-sb_status.patch +wifi-rtl8xxxu-perform-update_beacon_work-when-beacon.patch +asoc-amd-acp-fix-for-inconsistent-indenting.patch +asoc-amd-acp-fix-for-cpu-dai-index-logic.patch +drm-amd-display-fix-a-memleak-issue-when-driver-is-r.patch +wifi-ath12k-fix-use-after-free-in-ath12k_dp_cc_clean.patch +wifi-ath12k-fix-one-more-memcpy-size-error.patch +libbpf-add-missing-per-arch-include-path.patch +selftests-bpf-add-missing-per-arch-include-path.patch +bpf-fix-the-xdp_adjust_tail-sample-prog-issue.patch +selftests-bpf-fix-backtrace-printing-for-selftests-c.patch +wifi-ath11k-fix-ce-offset-address-calculation-for-wc.patch +selftests-bpf-add-missing-header-include-for-htons.patch +wifi-cfg80211-check-radio-iface-combination-for-mult.patch +ice-consistently-use-q_idx-in-ice_vc_cfg_qs_msg.patch +drm-vc4-hdmi-increase-audio-mai-fifo-dreq-threshold.patch +drm-vc4-introduce-generation-number-enum.patch +drm-vc4-match-drm_dev_enter-and-exit-calls-in-vc4_hv.patch +drm-vc4-match-drm_dev_enter-and-exit-calls-in-vc4_hv.patch-24148 +drm-vc4-correct-generation-check-in-vc4_hvs_lut_load.patch +libbpf-fix-sym_is_subprog-logic-for-weak-global-subp.patch +accel-ivpu-prevent-recovery-invocation-during-probe-.patch +asoc-rt722-sdca-remove-logically-deadcode-in-rt722-s.patch +libbpf-never-interpret-subprogs-in-.text-as-entry-pr.patch +netdevsim-copy-addresses-for-both-in-and-out-paths.patch +drm-bridge-tc358767-fix-link-properties-discovery.patch +drm-panic-select-zlib_deflate-for-drm_panic_screen_q.patch +selftests-bpf-fix-msg_verify_data-in-test_sockmap.patch +selftests-bpf-fix-txmsg_redir-of-test_txmsg_pull-in-.patch +wifi-mwifiex-add-missing-locking-for-cfg80211-calls.patch +wifi-wilc1000-set-mac-after-operation-mode.patch +wifi-mwifiex-fix-memcpy-field-spanning-write-warning.patch +drm-fsl-dcu-enable-pixclk-on-ls1021a.patch +drm-panel-nv3052c-correct-spi_device_id-for-rg35xx-p.patch +drm-msm-dpu-on-sdm845-move-dspp_3-to-lm_5-block.patch +drm-msm-dpu-drop-lm_3-lm_4-on-sdm845.patch +drm-msm-dpu-drop-lm_3-lm_4-on-msm8998.patch +octeontx2-pf-handle-otx2_mbox_get_rsp-errors-in-otx2.patch +octeontx2-pf-handle-otx2_mbox_get_rsp-errors-in-otx2.patch-27436 +octeontx2-pf-handle-otx2_mbox_get_rsp-errors-in-otx2.patch-15305 +octeontx2-pf-handle-otx2_mbox_get_rsp-errors-in-cn10.patch +octeontx2-pf-handle-otx2_mbox_get_rsp-errors-in-otx2.patch-20711 +octeontx2-pf-handle-otx2_mbox_get_rsp-errors-in-otx2.patch-32608 +selftests-bpf-fix-test_spin_lock_fail.c-s-global-var.patch +libbpf-move-global-data-mmap-ing-into-bpf_object__lo.patch +wifi-rtw89-rename-rtw89_vif-to-rtw89_vif_link-ahead-.patch +wifi-rtw89-rename-rtw89_sta-to-rtw89_sta_link-ahead-.patch +wifi-rtw89-read-bss_conf-corresponding-to-the-link.patch +wifi-rtw89-read-link_sta-corresponding-to-the-link.patch +wifi-rtw89-refactor-vif-related-func-ahead-for-mlo.patch +wifi-rtw89-refactor-sta-related-func-ahead-for-mlo.patch +wifi-rtw89-tweak-driver-architecture-for-impending-m.patch +wifi-rtw89-fix-tx-fail-with-a2dp-after-scanning.patch +wifi-rtw89-unlock-on-error-path-in-rtw89_ops_unassig.patch +drm-panfrost-remove-unused-id_mask-from-struct-panfr.patch +bpf-arm64-remove-garbage-frame-for-struct_ops-trampo.patch +drm-msm-adreno-use-irqf_no_autoen-flag-in-request_ir.patch +drm-msm-gpu-check-the-status-of-registration-to-pm-q.patch +drm-xe-hdcp-fix-gsc-structure-check-in-fw-check-stat.patch +drm-etnaviv-request-pages-from-dma32-zone-on-address.patch +drm-etnaviv-hold-gpu-lock-across-perfmon-sampling.patch +drm-amd-display-increase-idle-worker-hpd-detection-t.patch +drm-amd-display-reduce-hpd-detection-interval-for-ip.patch +drm-nouveau-gr-gf100-fix-missing-unlock-in-gf100_gr_.patch +drm-zynqmp_kms-unplug-drm-device-before-removal.patch +drm-xlnx-zynqmp_disp-layer-may-be-null-while-releasi.patch +wifi-wfx-fix-error-handling-in-wfx_core_init.patch +wifi-cw1200-fix-potential-null-dereference.patch +drm-msm-dpu-cast-crtc_clk-calculation-to-u64-in-_dpu.patch +bpf-bpftool-fix-incorrect-disasm-pc.patch +bpf-tighten-tail-call-checks-for-lingering-locks-rcu.patch +drm-vkms-drop-unnecessary-call-to-drm_crtc_cleanup.patch +drm-amdgpu-fix-the-memory-allocation-issue-in-amdgpu.patch +drm-amdkfd-use-dynamic-allocation-for-cu-occupancy-a.patch +bpf-mark-raw_tp-arguments-with-ptr_maybe_null.patch +drm-use-atomic64_init-for-atomic64_t.patch +netfilter-nf_tables-avoid-false-positive-lockdep-spl.patch +netfilter-nf_tables-must-hold-rcu-read-lock-while-it.patch +netfilter-nf_tables-must-hold-rcu-read-lock-while-it.patch-17532 +netlink-typographical-error-in-nlmsg_type-constants-.patch +wifi-rtw89-coex-check-null-return-of-kmalloc-in-btc_.patch +drm-panfrost-add-missing-opp-table-refcnt-decrementa.patch +drm-panthor-introduce-job-cycle-and-timestamp-accoun.patch +drm-panthor-record-current-and-maximum-device-clock-.patch +drm-panthor-fix-opp-refcnt-leaks-in-devfreq-initiali.patch +isofs-avoid-memory-leak-in-iocharset.patch +selftests-bpf-add-txmsg_pass-to-pull-push-pop-in-tes.patch +selftests-bpf-fix-sendpage-data-logic-in-test_sockma.patch +selftests-bpf-fix-total_bytes-in-msg_loop_rx-in-test.patch +selftests-bpf-add-push-pop-checking-for-msg_verify_d.patch +bpf-sockmap-several-fixes-to-bpf_msg_push_data.patch +bpf-sockmap-several-fixes-to-bpf_msg_pop_data.patch +bpf-sockmap-fix-sk_msg_reset_curr.patch +ipv6-release-nexthop-on-device-removal.patch +selftests-net-really-check-for-bg-process-completion.patch +wifi-cfg80211-remove-the-medium-synchronization-dela.patch +wifi-iwlwifi-allow-fast-resume-on-ax200.patch +wifi-iwlwifi-mvm-tell-iwlmei-when-we-finished-suspen.patch +drm-amdgpu-fix-aca-bank-count-boundary-check-error.patch +drm-amdgpu-fix-map-unmap-queue-logic.patch +drm-amdkfd-fix-wrong-usage-of-init_work.patch +bpf-allow-return-values-0-and-1-for-kprobe-session.patch +bpf-force-uprobe-bpf-program-to-always-return-0.patch +selftests-bpf-skip-the-timer_lockup-test-for-single-.patch +ipv6-fix-soft-lockups-in-fib6_select_path-under-high.patch +net-rfkill-gpio-add-check-for-clk_enable.patch +revert-wifi-iwlegacy-do-not-skip-frames-with-bad-fcs.patch +bpf-use-function-pointers-count-as-struct_ops-links-.patch +bpf-add-kernel-symbol-for-struct_ops-trampoline.patch +alsa-usx2y-use-snd_card_free_when_closed-at-disconne.patch +alsa-us122l-use-snd_card_free_when_closed-at-disconn.patch +alsa-caiaq-use-snd_card_free_when_closed-at-disconne.patch +alsa-6fire-release-resources-at-card-release.patch +i2c-dev-fix-memory-leak-when-underlying-adapter-does.patch +selftests-netfilter-fix-missing-return-values-in-con.patch +bluetooth-btintel_pcie-add-handshake-between-driver-.patch +bluetooth-btintel-do-no-pass-vendor-events-to-stack.patch +bluetooth-btmtk-adjust-the-position-to-init-iso-data.patch +bluetooth-btbcm-fix-missing-of_node_put-in-btbcm_get.patch +bluetooth-iso-use-kref-to-track-lifetime-of-iso_conn.patch +bluetooth-iso-do-not-emit-le-pa-create-sync-if-previ.patch +bluetooth-iso-do-not-emit-le-big-create-sync-if-prev.patch +bluetooth-iso-send-big-create-sync-via-hci_sync.patch +bluetooth-fix-use-after-free-in-device_for_each_chil.patch +xsk-free-skb-when-tx-metadata-options-are-invalid.patch +erofs-fix-file-backed-mounts-over-fuse.patch +erofs-fix-blksize-page_size-for-file-backed-mounts.patch +erofs-handle-nonhead-delta-1-lclusters-gracefully.patch +dlm-fix-dlm_recover_members-refcount-on-error.patch +eth-fbnic-don-t-disable-the-pci-device-twice.patch +net-txgbe-remove-gpio-interrupt-controller.patch +net-txgbe-fix-null-pointer-to-pcs.patch +netpoll-use-rcu_access_pointer-in-netpoll_poll_lock.patch +wireguard-selftests-load-nf_conntrack-if-not-present.patch +bpf-fix-recursive-lock-when-verdict-program-return-s.patch +unicode-fix-utf8_load-error-path.patch +cppc_cpufreq-use-desired-perf-if-feedback-ctrs-are-0.patch +rdma-core-provide-rdma_user_mmap_disassociate-to-dis.patch +rdma-hns-disassociate-mmap-pages-for-all-uctx-when-h.patch +pinctrl-renesas-rzg2l-fix-missing-return-in-rzg2l_pi.patch +clk-mediatek-drop-two-dead-config-options.patch +trace-trace_event_perf-remove-duplicate-samples-on-t.patch +pinctrl-zynqmp-drop-excess-struct-member-description.patch +pinctrl-renesas-select-pinctrl_rzg2l-for-rz-v2h-p-so.patch +clk-qcom-videocc-sm8550-depend-on-either-gcc-sm8550-.patch +iommu-s390-implement-blocking-domain.patch +scsi-hisi_sas-enable-all-phys-that-are-not-disabled-.patch +powerpc-vdso-flag-vdso64-entry-points-as-functions.patch +mfd-tps65010-use-irqf_no_autoen-flag-in-request_irq-.patch +mfd-da9052-spi-change-read-mask-to-write-mask.patch +mfd-intel_soc_pmic_bxtwc-use-irq-domain-for-usb-type.patch +mfd-intel_soc_pmic_bxtwc-use-irq-domain-for-tmu-devi.patch +mfd-intel_soc_pmic_bxtwc-use-irq-domain-for-pmic-dev.patch +mfd-intel_soc_pmic_bxtwc-fix-irq-domain-names-duplic.patch +cpufreq-loongson2-unregister-platform_driver-on-fail.patch +powerpc-fadump-refactor-and-prepare-fadump_cma_init-.patch +powerpc-fadump-move-fadump_cma_init-to-setup_arch-af.patch +mtd-hyperbus-rpc-if-add-missing-module_device_table.patch +mtd-rawnand-atmel-fix-possible-memory-leak.patch +clk-allow-kunit-tests-to-run-without-of_overlay-enab.patch +powerpc-mm-fault-fix-kfence-page-fault-reporting.patch +iommu-tegra241-cmdqv-staticize-cmdqv_debugfs_dir.patch +clk-sophgo-avoid-integer-overflow-in-sg2042_pll_reca.patch +mtd-spi-nor-spansion-use-nor-addr_nbytes-in-octal-dt.patch +powerpc-pseries-fix-dtl_access_lock-to-be-a-rw_semap.patch +cpufreq-cppc-fix-possible-null-ptr-deref-for-cpufreq.patch +cpufreq-cppc-fix-possible-null-ptr-deref-for-cppc_ge.patch +iommu-amd-pgtbl_v2-take-protection-domain-lock-befor.patch +rdma-hns-fix-an-aeqe-overflow-error-caused-by-untime.patch +rdma-hns-fix-flush-cqe-error-when-racing-with-destro.patch +rdma-hns-modify-debugfs-name.patch +rdma-hns-use-dev_-printings-in-hem-code-instead-of-i.patch +rdma-hns-fix-cpu-stuck-caused-by-printings-during-re.patch +rdma-rxe-fix-the-qp-flush-warnings-in-req.patch +rdma-bnxt_re-check-cqe-flags-to-know-imm_data-vs-inv.patch +clk-sunxi-ng-d1-fix-pll_audio0-preset.patch +clk-renesas-rzg2l-fix-foutpostdiv-clk.patch +rdma-rxe-set-queue-pair-cur_qp_state-when-being-quer.patch +rdma-mlx5-call-dev_put-after-the-blocking-notifier.patch +rdma-core-implement-roce-gid-port-rescan-and-export-.patch +rdma-mlx5-ensure-active-slave-attachment-to-the-bond.patch +risc-v-kvm-fix-aplic-in_clrip-and-clripnum-write-emu.patch +riscv-kvm-fix-out-of-bounds-array-access.patch +clk-imx-lpcg-scu-sw-workaround-for-errata-e10858.patch +clk-imx-fracn-gppll-correct-pll-initialization-flow.patch +clk-imx-fracn-gppll-fix-pll-power-up.patch +clk-imx-clk-scu-fix-clk-enable-state-save-and-restor.patch +clk-imx-imx8-acm-fix-return-value-check-in-clk_imx_a.patch +iommu-vt-d-fix-checks-and-print-in-dmar_fault_dump_p.patch +iommu-vt-d-fix-checks-and-print-in-pgtable_walk.patch +checkpatch-always-parse-orig_commit-in-fixes-tag.patch +mfd-rt5033-fix-missing-regmap_del_irq_chip.patch +leds-max5970-fix-unreleased-fwnode_handle-in-probe-f.patch +leds-ktd2692-set-missing-timing-properties.patch +fs-proc-kcore.c-fix-coccinelle-reported-error-instan.patch +scsi-target-fix-incorrect-function-name-in-pscsi_cre.patch +scsi-bfa-fix-use-after-free-in-bfad_im_module_exit.patch +scsi-fusion-remove-unused-variable-rc.patch +scsi-qedf-fix-a-possible-memory-leak-in-qedf_alloc_a.patch +scsi-qedi-fix-a-possible-memory-leak-in-qedi_alloc_a.patch +scsi-sg-enable-runtime-power-management.patch +x86-tdx-introduce-wrappers-to-read-and-write-td-meta.patch +x86-tdx-rename-tdx_parse_tdinfo-to-tdx_setup.patch +x86-tdx-dynamically-disable-sept-violations-from-cau.patch +powerpc-fadump-allocate-memory-for-additional-parame.patch +fadump-reserve-param-area-if-below-boot_mem_top.patch +rdma-hns-fix-out-of-order-issue-of-requester-when-se.patch +rdma-hns-fix-null-pointer-derefernce-in-hns_roce_map.patch +cpufreq-loongson3-check-for-error-code-from-devm_mut.patch +cpufreq-cppc-fix-wrong-return-value-in-cppc_get_cpu_.patch +cpufreq-cppc-fix-wrong-return-value-in-cppc_get_cpu_.patch-26269 +kasan-move-checks-to-do_strncpy_from_user.patch +kunit-skb-use-gfp-variable-instead-of-hardcoding-gfp.patch +ocfs2-fix-uninitialized-value-in-ocfs2_file_read_ite.patch +zram-zram_def_comp-should-depend-on-zram.patch +iommu-tegra241-cmdqv-fix-alignment-failure-at-max_n_.patch +dax-delete-a-stale-directory-pmem.patch +kvm-ppc-book3s-hv-stop-using-vc-dpdes-for-nested-kvm.patch +kvm-ppc-book3s-hv-avoid-returning-to-nested-hypervis.patch +powerpc-sstep-make-emulate_vsx_load-and-emulate_vsx_.patch +rdma-hns-fix-different-dgids-mapping-to-the-same-dip.patch +kvm-ppc-book3s-hv-fix-kmv-kvm-typo.patch +powerpc-kexec-fix-return-of-uninitialized-variable.patch +fbdev-sh7760fb-fix-a-possible-memory-leak-in-sh7760f.patch +rdma-mlx5-move-events-notifier-registration-to-be-af.patch +clk-clk-apple-nco-add-null-check-in-applnco_probe.patch +clk-ralink-mtmips-fix-clock-plan-for-ralink-soc-rt38.patch +clk-ralink-mtmips-fix-clocks-probe-order-in-oldest-r.patch +clk-en7523-remove-reg_pcie-_-mem-mem_mask-configurat.patch +clk-en7523-move-clock_register-in-hw_init-callback.patch +clk-en7523-introduce-chip_scu-regmap.patch +clk-en7523-fix-estimation-of-fixed-rate-for-en7581.patch +dt-bindings-clock-axi-clkgen-include-axi-clk.patch +clk-clk-axi-clkgen-make-sure-to-enable-the-axi-bus-c.patch +zram-permit-only-one-post-processing-operation-at-a-.patch +zram-fix-null-pointer-in-comp_algorithm_show.patch +rdma-bnxt_re-correct-the-sequence-of-device-suspend.patch +arm64-dts-qcom-sc8180x-add-a-soc-specific-compatible.patch +pinctrl-k210-undef-k210_pc_default.patch +rtla-timerlat-do-not-set-params-user_workload-with-u.patch +smb-cached-directories-can-be-more-than-root-file-ha.patch +mailbox-mtk-cmdq-fix-wrong-use-of-sizeof-in-cmdq_get.patch +mailbox-arm_mhuv2-clean-up-loop-in-get_irq_chan_comb.patch +x86-fix-off-by-one-in-access_ok.patch +perf-cs-etm-don-t-flush-when-packet_queue-fills-up.patch +gfs2-rename-glf_verify_evict-to-glf_verify_delete.patch +gfs2-allow-immediate-glf_verify_delete-work.patch +gfs2-fix-unlinked-inode-cleanup.patch +perf-stat-uniquify-event-name-improvements.patch +perf-mem-fix-printing-perf_mem_lvlnum_-l2_mhb-msc.patch +dt-bindings-pci-mediatek-gen3-allow-exact-number-of-.patch +pci-fix-reset_method_store-memory-leak.patch +perf-jevents-don-t-stop-at-the-first-matched-pmu-whe.patch +perf-stat-close-cork_fd-when-create_perf_stat_counte.patch +perf-stat-fix-affinity-memory-leaks-on-error-path.patch +perf-trace-keep-exited-threads-for-summary.patch +perf-test-attr-add-back-missing-topdown-events.patch +rust-rbtree-fix-safety-comments-that-should-be-safet.patch +f2fs-compress-fix-inconsistent-update-of-i_blocks-in.patch +f2fs-fix-null-ptr-deref-in-f2fs_submit_page_bio.patch +mailbox-remoteproc-k3-m4-fix-compile-testing.patch +f2fs-fix-to-account-dirty-data-in-__get_secs_require.patch +perf-dso-fix-symtab_type-for-kmod-compression.patch +perf-disasm-fix-capstone-memory-leak.patch +perf-probe-fix-libdw-memory-leak.patch +perf-probe-correct-demangled-symbols-in-c-program.patch +rust-kernel-fix-this_module-header-path-in-thismodul.patch +rust-macros-fix-documentation-of-the-paste-macro.patch +pci-cpqphp-fix-pcibios_-return-value-confusion.patch +rust-block-fix-formatting-of-kernel-block-mq-request.patch +perf-disasm-use-disasm_line__free-to-properly-free-d.patch +perf-disasm-fix-not-cleaning-up-disasm_line-in-symbo.patch +virtiofs-use-pages-instead-of-pointer-for-kernel-dir.patch +perf-ftrace-latency-fix-unit-on-histogram-first-entr.patch +i3c-master-remove-i3c_dev_disable_ibi_locked-olddev-.patch +f2fs-fix-the-wrong-f2fs_bug_on-condition-in-f2fs_do_.patch +f2fs-check-curseg-inited-before-write_sum_page-in-ch.patch +f2fs-fix-not-used-variable-index.patch +f2fs-fix-to-avoid-potential-deadlock-in-f2fs_record_.patch +f2fs-fix-to-avoid-use-gc_at-when-setting-gc_mode-as-.patch +pci-qcom-enable-msi-interrupts-together-with-link-up.patch +pci-qcom-ep-move-controller-cleanups-to-qcom_pcie_pe.patch +pci-tegra194-move-controller-cleanups-to-pex_ep_even.patch +pci-j721e-deassert-perst-after-a-delay-of-pcie_t_pvp.patch +perf-build-add-missing-cflags-when-building-with-cus.patch +f2fs-fix-race-in-concurrent-f2fs_stop_gc_thread.patch +f2fs-fix-to-map-blocks-correctly-for-direct-write.patch +f2fs-fix-to-avoid-forcing-direct-write-to-use-buffer.patch +perf-trace-avoid-garbage-when-not-printing-a-trace-e.patch +m68k-mcfgpio-fix-incorrect-register-offset-for-confi.patch +m68k-coldfire-device.c-only-build-fec-when-hw-macros.patch +svcrdma-address-an-integer-overflow.patch +nfsd-drop-inode-parameter-from-nfsd4_change_attribut.patch +perf-list-fix-topic-and-pmu_name-argument-order.patch +perf-trace-fix-tracing-itself-creating-feedback-loop.patch +perf-trace-do-not-lose-last-events-in-a-race.patch +perf-trace-avoid-garbage-when-not-printing-a-syscall.patch +remoteproc-qcom-pas-remove-subdevs-on-the-error-path.patch +remoteproc-qcom-adsp-remove-subdevs-on-the-error-pat.patch +remoteproc-qcom-pas-add-minidump_id-to-sm8350-resour.patch +rpmsg-glink-use-only-lower-16-bits-of-param2-for-cmd.patch +remoteproc-qcom_q6v5_mss-re-order-writes-to-the-imem.patch +pci-endpoint-epf-mhi-avoid-null-dereference-if-dt-la.patch +nfsd-prevent-null-dereference-in-nfsd4_process_cb_up.patch +nfsd-cap-the-number-of-bytes-copied-by-nfs4_reset_re.patch +nfsd-release-svc_expkey-svc_export-with-rcu_work.patch +svcrdma-fix-miss-destroy-percpu_counter-in-svc_rdma_.patch +nfsd-fix-nfsd4_shutdown_copy.patch +nfs_common-must-not-hold-rcu-while-calling-nfsd_file.patch +f2fs-fix-to-do-cast-in-f2fs_-blk_to_bytes-btyes_to_b.patch +perf-bpf-filter-return-enomem-directly-when-pfi-allo.patch +hwmon-tps23861-fix-reporting-of-negative-temperature.patch +hwmon-aquacomputer_d5next-fix-length-of-speed_input-.patch +phy-airoha-fix-reg_csr_2l_pll_cmn_reserve0-config-in.patch +phy-airoha-fix-reg_pcie_pma_tx_reset-config-in-airoh.patch +phy-airoha-fix-reg_csr_2l_jcpll_sdm_hren-config-in-a.patch +phy-airoha-fix-reg_csr_2l_rx-0-1-_rev0-definitions.patch +vdpa-mlx5-fix-suboptimal-range-on-iotlb-iteration.patch +vfio-mlx5-fix-an-unwind-issue-in-mlx5vf_add_migratio.patch +vfio-mlx5-fix-unwind-flows-in-mlx5vf_pci_save-resume.patch +selftests-mount_setattr-fix-failures-on-64k-page_siz.patch +gpio-zevio-add-missed-label-initialisation.patch +vfio-pci-properly-hide-first-in-list-pcie-extended-c.patch +fs_parser-update-mount_api-doc-to-match-function-sig.patch +loongarch-fix-build-failure-with-gcc-15-std-gnu23.patch +loongarch-bpf-sign-extend-return-values.patch +power-supply-core-remove-might_sleep-from-power_supp.patch +power-supply-bq27xxx-fix-registers-of-bq27426.patch +power-supply-rt9471-fix-wrong-wdt-function-regfield-.patch +power-supply-rt9471-use-ic-status-regfield-to-report.patch +fs-ntfs3-equivalent-transition-from-page-to-folio.patch +power-reset-ep93xx-add-auxiliary_bus-dependency.patch +net-usb-lan78xx-fix-double-free-issue-with-interrupt.patch +net-usb-lan78xx-fix-memory-leak-on-device-unplug-by-.patch +tg3-set-coherent-dma-mask-bits-to-31-for-bcm57766-ch.patch +net-usb-lan78xx-fix-refcounting-and-autosuspend-on-i.patch +net-microchip-vcap-add-typegroup-table-terminators-i.patch +netlink-fix-false-positive-warning-in-extack-during-.patch +exfat-fix-file-being-changed-by-unaligned-direct-wri.patch +net-l2tp-fix-warning-in-l2tp_exit_net-found-by-syzbo.patch +s390-iucv-msg_peek-causes-memory-leak-in-iucv_sock_d.patch +rtase-refactor-the-rtase_check_mac_version_valid-fun.patch +rtase-correct-the-speed-for-rtl907xd-v1.patch +rtase-corrects-error-handling-of-the-rtase_check_mac.patch +net-ipv6-delete-temporary-address-if-mngtmpaddr-is-r.patch +net-mdio-ipq4019-add-missing-error-check.patch +marvell-pxa168_eth-fix-call-balance-of-pep-clk-handl.patch +net-stmmac-dwmac-socfpga-set-rx-watchdog-interrupt-a.patch +octeontx2-af-rpm-fix-mismatch-in-lmac-type.patch +octeontx2-af-rpm-fix-low-network-performance.patch +octeontx2-af-rpm-fix-stale-rsfec-counters.patch +octeontx2-af-rpm-fix-stale-fcfec-counters.patch +octeontx2-af-quiesce-traffic-before-nix-block-reset.patch +spi-atmel-quadspi-fix-register-name-in-verbose-loggi.patch +net-hsr-fix-hsr_init_sk-vs-network-transport-headers.patch +bnxt_en-reserve-rings-after-pcie-aer-recovery-if-nic.patch +bnxt_en-set-backplane-link-modes-correctly-for-ethto.patch +bnxt_en-fix-queue-start-to-update-vnic-rss-table.patch +bnxt_en-fix-receive-ring-space-parameters-when-xdp-i.patch +bnxt_en-refactor-bnxt_ptp_init.patch +bnxt_en-unregister-ptp-during-pci-shutdown-and-suspe.patch +bluetooth-mgmt-fix-slab-use-after-free-read-in-set_p.patch +bluetooth-mgmt-fix-possible-deadlocks.patch +llc-improve-setsockopt-handling-of-malformed-user-in.patch +rxrpc-improve-setsockopt-handling-of-malformed-user-.patch +tcp-fix-use-after-free-of-nreq-in-reqsk_timer_handle.patch +ip6mr-fix-tables-suspicious-rcu-usage.patch +ipmr-fix-tables-suspicious-rcu-usage.patch +iio-light-al3010-fix-an-error-handling-path-in-al301.patch +usb-using-mutex-lock-and-supporting-o_nonblock-flag-.patch +usb-yurex-make-waiting-on-yurex_write-interruptible.patch +usb-chaoskey-fail-open-after-removal.patch +usb-chaoskey-fix-possible-deadlock-chaoskey_list_loc.patch +misc-apds990x-fix-missing-pm_runtime_disable.patch +devres-fix-page-faults-when-tracing-devres-from-unlo.patch +usb-gadget-uvc-wake-pump-everytime-we-update-the-fre.patch +interconnect-qcom-icc-rpmh-probe-defer-incase-of-mis.patch +iio-backend-fix-wrong-pointer-passed-to-is_err.patch +iio-adc-ad4000-fix-reading-unsigned-data.patch +iio-adc-ad4000-check-for-error-code-from-devm_mutex_.patch +iio-adc-pac1921-check-for-error-code-from-devm_mutex.patch +iio-accel-adxl380-fix-raw-sample-read.patch +phy-realtek-usb-fix-null-deref-in-rtk_usb2phy_probe.patch +phy-realtek-usb-fix-null-deref-in-rtk_usb3phy_probe.patch +counter-stm32-timer-cnt-add-check-for-clk_enable.patch +counter-ti-ecap-capture-add-check-for-clk_enable.patch +bus-mhi-host-switch-trace_mhi_gen_tre-fields-to-nati.patch +staging-greybus-uart-fix-atomicity-violation-in-get_.patch +usb-typec-fix-potential-array-underflow-in-ucsi_ccg_.patch +firmware_loader-fix-possible-resource-leak-in-fw_log.patch +alsa-hda-realtek-update-alc256-depop-procedure.patch +drm-radeon-fix-spurious-unplug-event-on-radeon-hdmi.patch +drm-amd-display-fix-null-check-for-pipe_ctx-plane_st.patch +drm-amd-display-fix-null-check-for-pipe_ctx-plane_st.patch-32135 +asoc-imx-audmix-add-null-check-in-imx_audmix_probe.patch +drm-xe-ufence-wake-up-waiters-after-setting-ufence-s.patch +apparmor-fix-do-simple-duplicate-message-elimination.patch +alsa-core-fix-possible-null-dereference-caused-by-ku.patch +asoc-amd-yc-fix-for-enabling-dmic-on-acp6x-via-_dsd-.patch +asoc-mediatek-check-num_codecs-is-not-zero-to-avoid-.patch +s390-pci-fix-potential-double-remove-of-hotplug-slot.patch diff --git a/queue-6.12/smb-cached-directories-can-be-more-than-root-file-ha.patch b/queue-6.12/smb-cached-directories-can-be-more-than-root-file-ha.patch new file mode 100644 index 00000000000..ddb5f6fbfe6 --- /dev/null +++ b/queue-6.12/smb-cached-directories-can-be-more-than-root-file-ha.patch @@ -0,0 +1,37 @@ +From 7e79dbad7296ee29e7cf4b3affe35728ee747a45 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Fri, 8 Nov 2024 14:29:02 -0800 +Subject: smb: cached directories can be more than root file handle + +From: Paul Aurich <paul@darkrain42.org> + +[ Upstream commit 128630e1dbec8074c7707aad107299169047e68f ] + +Update this log message since cached fids may represent things other +than the root of a mount. + +Fixes: e4029e072673 ("cifs: find and use the dentry for cached non-root directories also") +Signed-off-by: Paul Aurich <paul@darkrain42.org> +Reviewed-by: Bharath SM <bharathsm@microsoft.com> +Signed-off-by: Steve French <stfrench@microsoft.com> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + fs/smb/client/cached_dir.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/fs/smb/client/cached_dir.c b/fs/smb/client/cached_dir.c +index 0ff2491c311d8..adcba13352045 100644 +--- a/fs/smb/client/cached_dir.c ++++ b/fs/smb/client/cached_dir.c +@@ -401,7 +401,7 @@ int open_cached_dir_by_dentry(struct cifs_tcon *tcon, + spin_lock(&cfids->cfid_list_lock); + list_for_each_entry(cfid, &cfids->entries, entry) { + if (dentry && cfid->dentry == dentry) { +- cifs_dbg(FYI, "found a cached root file handle by dentry\n"); ++ cifs_dbg(FYI, "found a cached file handle by dentry\n"); + kref_get(&cfid->refcount); + *ret_cfid = cfid; + spin_unlock(&cfids->cfid_list_lock); +-- +2.43.0 + diff --git a/queue-6.12/soc-qcom-geni-se-fix-array-underflow-in-geni_se_clk_.patch b/queue-6.12/soc-qcom-geni-se-fix-array-underflow-in-geni_se_clk_.patch new file mode 100644 index 00000000000..ad5fb640412 --- /dev/null +++ b/queue-6.12/soc-qcom-geni-se-fix-array-underflow-in-geni_se_clk_.patch @@ -0,0 +1,40 @@ +From a0847f2ef516cc07bf6185a07c83a27601a8971d Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Mon, 30 Sep 2024 10:51:31 +0300 +Subject: soc: qcom: geni-se: fix array underflow in geni_se_clk_tbl_get() + +From: Dan Carpenter <dan.carpenter@linaro.org> + +[ Upstream commit 78261cb08f06c93d362cab5c5034bf5899bc7552 ] + +This loop is supposed to break if the frequency returned from +clk_round_rate() is the same as on the previous iteration. However, +that check doesn't make sense on the first iteration through the loop. +It leads to reading before the start of these->clk_perf_tbl[] array. + +Fixes: eddac5af0654 ("soc: qcom: Add GENI based QUP Wrapper driver") +Signed-off-by: Dan Carpenter <dan.carpenter@linaro.org> +Link: https://lore.kernel.org/r/8cd12678-f44a-4b16-a579-c8f11175ee8c@stanley.mountain +Signed-off-by: Bjorn Andersson <andersson@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/soc/qcom/qcom-geni-se.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/soc/qcom/qcom-geni-se.c b/drivers/soc/qcom/qcom-geni-se.c +index 2e8f24d5da80b..4cb959106efa9 100644 +--- a/drivers/soc/qcom/qcom-geni-se.c ++++ b/drivers/soc/qcom/qcom-geni-se.c +@@ -585,7 +585,8 @@ int geni_se_clk_tbl_get(struct geni_se *se, unsigned long **tbl) + + for (i = 0; i < MAX_CLK_PERF_LEVEL; i++) { + freq = clk_round_rate(se->clk, freq + 1); +- if (freq <= 0 || freq == se->clk_perf_tbl[i - 1]) ++ if (freq <= 0 || ++ (i > 0 && freq == se->clk_perf_tbl[i - 1])) + break; + se->clk_perf_tbl[i] = freq; + } +-- +2.43.0 + diff --git a/queue-6.12/soc-ti-smartreflex-use-irqf_no_autoen-flag-in-reques.patch b/queue-6.12/soc-ti-smartreflex-use-irqf_no_autoen-flag-in-reques.patch new file mode 100644 index 00000000000..487c28ec6cb --- /dev/null +++ b/queue-6.12/soc-ti-smartreflex-use-irqf_no_autoen-flag-in-reques.patch @@ -0,0 +1,45 @@ +From ba477a54de998e5095b3a9e003e883620efc37cf Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Thu, 12 Sep 2024 11:41:47 +0800 +Subject: soc: ti: smartreflex: Use IRQF_NO_AUTOEN flag in request_irq() + +From: Jinjie Ruan <ruanjinjie@huawei.com> + +[ Upstream commit 16a0a69244240cfa32c525c021c40f85e090557a ] + +If request_irq() fails in sr_late_init(), there is no need to enable +the irq, and if it succeeds, disable_irq() after request_irq() still has +a time gap in which interrupts can come. + +request_irq() with IRQF_NO_AUTOEN flag will disable IRQ auto-enable when +request IRQ. + +Fixes: 1279ba5916f6 ("OMAP3+: SR: disable interrupt by default") +Signed-off-by: Jinjie Ruan <ruanjinjie@huawei.com> +Link: https://lore.kernel.org/r/20240912034147.3014213-1-ruanjinjie@huawei.com +Signed-off-by: Kevin Hilman <khilman@baylibre.com> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/soc/ti/smartreflex.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/soc/ti/smartreflex.c b/drivers/soc/ti/smartreflex.c +index d6219060b616d..38add2ab56137 100644 +--- a/drivers/soc/ti/smartreflex.c ++++ b/drivers/soc/ti/smartreflex.c +@@ -202,10 +202,10 @@ static int sr_late_init(struct omap_sr *sr_info) + + if (sr_class->notify && sr_class->notify_flags && sr_info->irq) { + ret = devm_request_irq(&sr_info->pdev->dev, sr_info->irq, +- sr_interrupt, 0, sr_info->name, sr_info); ++ sr_interrupt, IRQF_NO_AUTOEN, ++ sr_info->name, sr_info); + if (ret) + goto error; +- disable_irq(sr_info->irq); + } + + return ret; +-- +2.43.0 + diff --git a/queue-6.12/spi-atmel-quadspi-fix-register-name-in-verbose-loggi.patch b/queue-6.12/spi-atmel-quadspi-fix-register-name-in-verbose-loggi.patch new file mode 100644 index 00000000000..42b2f001349 --- /dev/null +++ b/queue-6.12/spi-atmel-quadspi-fix-register-name-in-verbose-loggi.patch @@ -0,0 +1,43 @@ +From f51ea312cb2786b701f45be89da76b23d9065b4e Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Fri, 22 Nov 2024 15:13:02 +0100 +Subject: spi: atmel-quadspi: Fix register name in verbose logging function +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Csókás, Bence <csokas.bence@prolan.hu> + +[ Upstream commit 2ac40e6d0ccdd93031f8b1af61b0fe5cdd704923 ] + +`atmel_qspi_reg_name()` is used for pretty-printing register offsets +for verbose logging of register accesses. However, due to a typo +(likely a copy-paste error), QSPI_RD's offset prints as "MR", the +name of the previous register. Fix this typo. + +Fixes: c528ecfbef04 ("spi: atmel-quadspi: Add verbose debug facilities to monitor register accesses") +Signed-off-by: Csókás, Bence <csokas.bence@prolan.hu> +Reviewed-by: Alexander Dahl <ada@thorsis.com> +Link: https://patch.msgid.link/20241122141302.2599636-1-csokas.bence@prolan.hu +Signed-off-by: Mark Brown <broonie@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/spi/atmel-quadspi.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/spi/atmel-quadspi.c b/drivers/spi/atmel-quadspi.c +index 95cdfc28361ef..caecb2ad2a150 100644 +--- a/drivers/spi/atmel-quadspi.c ++++ b/drivers/spi/atmel-quadspi.c +@@ -183,7 +183,7 @@ static const char *atmel_qspi_reg_name(u32 offset, char *tmp, size_t sz) + case QSPI_MR: + return "MR"; + case QSPI_RD: +- return "MR"; ++ return "RD"; + case QSPI_TD: + return "TD"; + case QSPI_SR: +-- +2.43.0 + diff --git a/queue-6.12/spi-spi-fsl-lpspi-use-irqf_no_autoen-flag-in-request.patch b/queue-6.12/spi-spi-fsl-lpspi-use-irqf_no_autoen-flag-in-request.patch new file mode 100644 index 00000000000..995627f3102 --- /dev/null +++ b/queue-6.12/spi-spi-fsl-lpspi-use-irqf_no_autoen-flag-in-request.patch @@ -0,0 +1,56 @@ +From 70d6101fddad7287a5e4c3366474e179e39f6255 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Fri, 6 Sep 2024 10:28:28 +0800 +Subject: spi: spi-fsl-lpspi: Use IRQF_NO_AUTOEN flag in request_irq() + +From: Jinjie Ruan <ruanjinjie@huawei.com> + +[ Upstream commit 003c7e01916c5e2af95add9b0cbda2e6163873e8 ] + +disable_irq() after request_irq() still has a time gap in which +interrupts can come. request_irq() with IRQF_NO_AUTOEN flag will +disable IRQ auto-enable when request IRQ. + +Fixes: 9728fb3ce117 ("spi: lpspi: disable lpspi module irq in DMA mode") +Signed-off-by: Jinjie Ruan <ruanjinjie@huawei.com> +Link: https://patch.msgid.link/20240906022828.891812-1-ruanjinjie@huawei.com +Signed-off-by: Mark Brown <broonie@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/spi/spi-fsl-lpspi.c | 12 ++++-------- + 1 file changed, 4 insertions(+), 8 deletions(-) + +diff --git a/drivers/spi/spi-fsl-lpspi.c b/drivers/spi/spi-fsl-lpspi.c +index 977e8b55c82b7..9573b8fa4fbfc 100644 +--- a/drivers/spi/spi-fsl-lpspi.c ++++ b/drivers/spi/spi-fsl-lpspi.c +@@ -891,7 +891,7 @@ static int fsl_lpspi_probe(struct platform_device *pdev) + return ret; + } + +- ret = devm_request_irq(&pdev->dev, irq, fsl_lpspi_isr, 0, ++ ret = devm_request_irq(&pdev->dev, irq, fsl_lpspi_isr, IRQF_NO_AUTOEN, + dev_name(&pdev->dev), fsl_lpspi); + if (ret) { + dev_err(&pdev->dev, "can't get irq%d: %d\n", irq, ret); +@@ -948,14 +948,10 @@ static int fsl_lpspi_probe(struct platform_device *pdev) + ret = fsl_lpspi_dma_init(&pdev->dev, fsl_lpspi, controller); + if (ret == -EPROBE_DEFER) + goto out_pm_get; +- if (ret < 0) ++ if (ret < 0) { + dev_warn(&pdev->dev, "dma setup error %d, use pio\n", ret); +- else +- /* +- * disable LPSPI module IRQ when enable DMA mode successfully, +- * to prevent the unexpected LPSPI module IRQ events. +- */ +- disable_irq(irq); ++ enable_irq(irq); ++ } + + ret = devm_spi_register_controller(&pdev->dev, controller); + if (ret < 0) { +-- +2.43.0 + diff --git a/queue-6.12/spi-tegra210-quad-avoid-shift-out-of-bounds.patch b/queue-6.12/spi-tegra210-quad-avoid-shift-out-of-bounds.patch new file mode 100644 index 00000000000..87aa7955c99 --- /dev/null +++ b/queue-6.12/spi-tegra210-quad-avoid-shift-out-of-bounds.patch @@ -0,0 +1,49 @@ +From 9fd3d47ff61cf6e5f3fb526060aeb236273cfd29 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Fri, 4 Oct 2024 05:53:59 -0700 +Subject: spi: tegra210-quad: Avoid shift-out-of-bounds + +From: Breno Leitao <leitao@debian.org> + +[ Upstream commit f399051ec1ff02e74ae5c2517aed2cc486fd005b ] + +A shift-out-of-bounds issue was identified by UBSAN in the +tegra_qspi_fill_tx_fifo_from_client_txbuf() function. + + UBSAN: shift-out-of-bounds in drivers/spi/spi-tegra210-quad.c:345:27 + shift exponent 32 is too large for 32-bit type 'u32' (aka 'unsigned int') + Call trace: + tegra_qspi_start_cpu_based_transfer + +The problem arises when shifting the contents of tx_buf left by 8 times +the value of i, which can exceed 4 and result in an exponent larger than +32 bits. + +Resolve this by restrict the value of i to be less than 4, preventing +the shift operation from overflowing. + +Signed-off-by: Breno Leitao <leitao@debian.org> +Fixes: 921fc1838fb0 ("spi: tegra210-quad: Add support for Tegra210 QSPI controller") +Link: https://patch.msgid.link/20241004125400.1791089-1-leitao@debian.org +Signed-off-by: Mark Brown <broonie@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/spi/spi-tegra210-quad.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/spi/spi-tegra210-quad.c b/drivers/spi/spi-tegra210-quad.c +index afbd64a217eb0..43f11b0e9e765 100644 +--- a/drivers/spi/spi-tegra210-quad.c ++++ b/drivers/spi/spi-tegra210-quad.c +@@ -341,7 +341,7 @@ tegra_qspi_fill_tx_fifo_from_client_txbuf(struct tegra_qspi *tqspi, struct spi_t + for (count = 0; count < max_n_32bit; count++) { + u32 x = 0; + +- for (i = 0; len && (i < bytes_per_word); i++, len--) ++ for (i = 0; len && (i < min(4, bytes_per_word)); i++, len--) + x |= (u32)(*tx_buf++) << (i * 8); + tegra_qspi_writel(tqspi, x, QSPI_TX_FIFO); + } +-- +2.43.0 + diff --git a/queue-6.12/spi-zynqmp-gqspi-undo-runtime-pm-changes-at-driver-e.patch b/queue-6.12/spi-zynqmp-gqspi-undo-runtime-pm-changes-at-driver-e.patch new file mode 100644 index 00000000000..4dbad550590 --- /dev/null +++ b/queue-6.12/spi-zynqmp-gqspi-undo-runtime-pm-changes-at-driver-e.patch @@ -0,0 +1,51 @@ +From 2346f7fe5931a2c03478f405dcaaa57e5a455732 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Fri, 20 Sep 2024 17:11:35 +0800 +Subject: =?UTF-8?q?spi:=20zynqmp-gqspi:=20Undo=20runtime=20PM=20changes=20?= + =?UTF-8?q?at=20driver=20exit=20time=E2=80=8B?= +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Jinjie Ruan <ruanjinjie@huawei.com> + +[ Upstream commit 2219576883e709737f3100aa9ded84976be49bd7 ] + +It's important to undo pm_runtime_use_autosuspend() with +pm_runtime_dont_use_autosuspend() at driver exit time. + +So, call pm_runtime_dont_use_autosuspend() at driver exit time +to fix it. + +Fixes: 9e3a000362ae ("spi: zynqmp: Add pm runtime support") +Signed-off-by: Jinjie Ruan <ruanjinjie@huawei.com> +Link: https://patch.msgid.link/20240920091135.2741574-1-ruanjinjie@huawei.com +Signed-off-by: Mark Brown <broonie@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/spi/spi-zynqmp-gqspi.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/spi/spi-zynqmp-gqspi.c b/drivers/spi/spi-zynqmp-gqspi.c +index fcd0ca9966841..b9df39e06e7cd 100644 +--- a/drivers/spi/spi-zynqmp-gqspi.c ++++ b/drivers/spi/spi-zynqmp-gqspi.c +@@ -1351,6 +1351,7 @@ static int zynqmp_qspi_probe(struct platform_device *pdev) + + clk_dis_all: + pm_runtime_disable(&pdev->dev); ++ pm_runtime_dont_use_autosuspend(&pdev->dev); + pm_runtime_put_noidle(&pdev->dev); + pm_runtime_set_suspended(&pdev->dev); + clk_disable_unprepare(xqspi->refclk); +@@ -1379,6 +1380,7 @@ static void zynqmp_qspi_remove(struct platform_device *pdev) + zynqmp_gqspi_write(xqspi, GQSPI_EN_OFST, 0x0); + + pm_runtime_disable(&pdev->dev); ++ pm_runtime_dont_use_autosuspend(&pdev->dev); + pm_runtime_put_noidle(&pdev->dev); + pm_runtime_set_suspended(&pdev->dev); + clk_disable_unprepare(xqspi->refclk); +-- +2.43.0 + diff --git a/queue-6.12/staging-greybus-uart-fix-atomicity-violation-in-get_.patch b/queue-6.12/staging-greybus-uart-fix-atomicity-violation-in-get_.patch new file mode 100644 index 00000000000..e41c2d934bc --- /dev/null +++ b/queue-6.12/staging-greybus-uart-fix-atomicity-violation-in-get_.patch @@ -0,0 +1,49 @@ +From 61937fd741031632e0a1337553e51b754748ca0d Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Thu, 7 Nov 2024 19:33:37 +0800 +Subject: staging: greybus: uart: Fix atomicity violation in get_serial_info() + +From: Qiu-ji Chen <chenqiuji666@gmail.com> + +[ Upstream commit fe0ebeafc3b723b2f8edf27ecec6d353b08397df ] + +Our static checker found a bug where set_serial_info() uses a mutex, but +get_serial_info() does not. Fortunately, the impact of this is relatively +minor. It doesn't cause a crash or any other serious issues. However, if a +race condition occurs between set_serial_info() and get_serial_info(), +there is a chance that the data returned by get_serial_info() will be +meaningless. + +Signed-off-by: Qiu-ji Chen <chenqiuji666@gmail.com> +Fixes: 0aad5ad563c8 ("greybus/uart: switch to ->[sg]et_serial()") +Reviewed-by: Johan Hovold <johan+linaro@kernel.org> +Reviewed-by: Dan Carpenter <dan.carpenter@linaro.org> +Reviewed-by: Alex Elder <elder@riscstar.com> +Link: https://lore.kernel.org/r/20241107113337.402042-1-chenqiuji666@gmail.com +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/staging/greybus/uart.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/staging/greybus/uart.c b/drivers/staging/greybus/uart.c +index cdf4ebb93b104..8eab94cb06faf 100644 +--- a/drivers/staging/greybus/uart.c ++++ b/drivers/staging/greybus/uart.c +@@ -596,11 +596,13 @@ static int get_serial_info(struct tty_struct *tty, + struct gb_tty *gb_tty = tty->driver_data; + + ss->line = gb_tty->minor; ++ mutex_lock(&gb_tty->port.mutex); + ss->close_delay = jiffies_to_msecs(gb_tty->port.close_delay) / 10; + ss->closing_wait = + gb_tty->port.closing_wait == ASYNC_CLOSING_WAIT_NONE ? + ASYNC_CLOSING_WAIT_NONE : + jiffies_to_msecs(gb_tty->port.closing_wait) / 10; ++ mutex_unlock(&gb_tty->port.mutex); + + return 0; + } +-- +2.43.0 + diff --git a/queue-6.12/svcrdma-address-an-integer-overflow.patch b/queue-6.12/svcrdma-address-an-integer-overflow.patch new file mode 100644 index 00000000000..f45c6e38c88 --- /dev/null +++ b/queue-6.12/svcrdma-address-an-integer-overflow.patch @@ -0,0 +1,68 @@ +From 084a7c6795d0bbe3c392b2897d1fd996e7cf311d Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Tue, 17 Sep 2024 12:15:29 -0400 +Subject: svcrdma: Address an integer overflow + +From: Chuck Lever <chuck.lever@oracle.com> + +[ Upstream commit 3c63d8946e578663b868cb9912dac616ea68bfd0 ] + +Dan Carpenter reports: +> Commit 78147ca8b4a9 ("svcrdma: Add a "parsed chunk list" data +> structure") from Jun 22, 2020 (linux-next), leads to the following +> Smatch static checker warning: +> +> net/sunrpc/xprtrdma/svc_rdma_recvfrom.c:498 xdr_check_write_chunk() +> warn: potential user controlled sizeof overflow 'segcount * 4 * 4' +> +> net/sunrpc/xprtrdma/svc_rdma_recvfrom.c +> 488 static bool xdr_check_write_chunk(struct svc_rdma_recv_ctxt *rctxt) +> 489 { +> 490 u32 segcount; +> 491 __be32 *p; +> 492 +> 493 if (xdr_stream_decode_u32(&rctxt->rc_stream, &segcount)) +> ^^^^^^^^ +> +> 494 return false; +> 495 +> 496 /* A bogus segcount causes this buffer overflow check to fail. */ +> 497 p = xdr_inline_decode(&rctxt->rc_stream, +> --> 498 segcount * rpcrdma_segment_maxsz * sizeof(*p)); +> +> +> segcount is an untrusted u32. On 32bit systems anything >= SIZE_MAX / 16 will +> have an integer overflow and some those values will be accepted by +> xdr_inline_decode(). + +Reported-by: Dan Carpenter <dan.carpenter@linaro.org> +Fixes: 78147ca8b4a9 ("svcrdma: Add a "parsed chunk list" data structure") +Reviewed-by: Jeff Layton <jlayton@kernel.org> +Signed-off-by: Chuck Lever <chuck.lever@oracle.com> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + net/sunrpc/xprtrdma/svc_rdma_recvfrom.c | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +diff --git a/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c b/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c +index ae3fb9bc8a216..292022f0976e1 100644 +--- a/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c ++++ b/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c +@@ -493,7 +493,13 @@ static bool xdr_check_write_chunk(struct svc_rdma_recv_ctxt *rctxt) + if (xdr_stream_decode_u32(&rctxt->rc_stream, &segcount)) + return false; + +- /* A bogus segcount causes this buffer overflow check to fail. */ ++ /* Before trusting the segcount value enough to use it in ++ * a computation, perform a simple range check. This is an ++ * arbitrary but sensible limit (ie, not architectural). ++ */ ++ if (unlikely(segcount > RPCSVC_MAXPAGES)) ++ return false; ++ + p = xdr_inline_decode(&rctxt->rc_stream, + segcount * rpcrdma_segment_maxsz * sizeof(*p)); + return p != NULL; +-- +2.43.0 + diff --git a/queue-6.12/svcrdma-fix-miss-destroy-percpu_counter-in-svc_rdma_.patch b/queue-6.12/svcrdma-fix-miss-destroy-percpu_counter-in-svc_rdma_.patch new file mode 100644 index 00000000000..e7a66e83db5 --- /dev/null +++ b/queue-6.12/svcrdma-fix-miss-destroy-percpu_counter-in-svc_rdma_.patch @@ -0,0 +1,100 @@ +From b092532df36cf924a508ffaedf4dbb1ab7059901 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Thu, 24 Oct 2024 09:55:20 +0800 +Subject: svcrdma: fix miss destroy percpu_counter in svc_rdma_proc_init() + +From: Ye Bin <yebin10@huawei.com> + +[ Upstream commit ce89e742a4c12b20f09a43fec1b21db33f2166cd ] + +There's issue as follows: +RPC: Registered rdma transport module. +RPC: Registered rdma backchannel transport module. +RPC: Unregistered rdma transport module. +RPC: Unregistered rdma backchannel transport module. +BUG: unable to handle page fault for address: fffffbfff80c609a +PGD 123fee067 P4D 123fee067 PUD 123fea067 PMD 10c624067 PTE 0 +Oops: Oops: 0000 [#1] PREEMPT SMP KASAN NOPTI +RIP: 0010:percpu_counter_destroy_many+0xf7/0x2a0 +Call Trace: + <TASK> + __die+0x1f/0x70 + page_fault_oops+0x2cd/0x860 + spurious_kernel_fault+0x36/0x450 + do_kern_addr_fault+0xca/0x100 + exc_page_fault+0x128/0x150 + asm_exc_page_fault+0x26/0x30 + percpu_counter_destroy_many+0xf7/0x2a0 + mmdrop+0x209/0x350 + finish_task_switch.isra.0+0x481/0x840 + schedule_tail+0xe/0xd0 + ret_from_fork+0x23/0x80 + ret_from_fork_asm+0x1a/0x30 + </TASK> + +If register_sysctl() return NULL, then svc_rdma_proc_cleanup() will not +destroy the percpu counters which init in svc_rdma_proc_init(). +If CONFIG_HOTPLUG_CPU is enabled, residual nodes may be in the +'percpu_counters' list. The above issue may occur once the module is +removed. If the CONFIG_HOTPLUG_CPU configuration is not enabled, memory +leakage occurs. +To solve above issue just destroy all percpu counters when +register_sysctl() return NULL. + +Fixes: 1e7e55731628 ("svcrdma: Restore read and write stats") +Fixes: 22df5a22462e ("svcrdma: Convert rdma_stat_sq_starve to a per-CPU counter") +Fixes: df971cd853c0 ("svcrdma: Convert rdma_stat_recv to a per-CPU counter") +Signed-off-by: Ye Bin <yebin10@huawei.com> +Signed-off-by: Chuck Lever <chuck.lever@oracle.com> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + net/sunrpc/xprtrdma/svc_rdma.c | 19 ++++++++++++++----- + 1 file changed, 14 insertions(+), 5 deletions(-) + +diff --git a/net/sunrpc/xprtrdma/svc_rdma.c b/net/sunrpc/xprtrdma/svc_rdma.c +index 58ae6ec4f25b4..415c0310101f0 100644 +--- a/net/sunrpc/xprtrdma/svc_rdma.c ++++ b/net/sunrpc/xprtrdma/svc_rdma.c +@@ -233,25 +233,34 @@ static int svc_rdma_proc_init(void) + + rc = percpu_counter_init(&svcrdma_stat_read, 0, GFP_KERNEL); + if (rc) +- goto out_err; ++ goto err; + rc = percpu_counter_init(&svcrdma_stat_recv, 0, GFP_KERNEL); + if (rc) +- goto out_err; ++ goto err_read; + rc = percpu_counter_init(&svcrdma_stat_sq_starve, 0, GFP_KERNEL); + if (rc) +- goto out_err; ++ goto err_recv; + rc = percpu_counter_init(&svcrdma_stat_write, 0, GFP_KERNEL); + if (rc) +- goto out_err; ++ goto err_sq; + + svcrdma_table_header = register_sysctl("sunrpc/svc_rdma", + svcrdma_parm_table); ++ if (!svcrdma_table_header) ++ goto err_write; ++ + return 0; + +-out_err: ++err_write: ++ rc = -ENOMEM; ++ percpu_counter_destroy(&svcrdma_stat_write); ++err_sq: + percpu_counter_destroy(&svcrdma_stat_sq_starve); ++err_recv: + percpu_counter_destroy(&svcrdma_stat_recv); ++err_read: + percpu_counter_destroy(&svcrdma_stat_read); ++err: + return rc; + } + +-- +2.43.0 + diff --git a/queue-6.12/tcp-fix-use-after-free-of-nreq-in-reqsk_timer_handle.patch b/queue-6.12/tcp-fix-use-after-free-of-nreq-in-reqsk_timer_handle.patch new file mode 100644 index 00000000000..378c91fb400 --- /dev/null +++ b/queue-6.12/tcp-fix-use-after-free-of-nreq-in-reqsk_timer_handle.patch @@ -0,0 +1,49 @@ +From 06deef064e3d346fa2e8fde4199678cf3a22482e Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Sat, 23 Nov 2024 09:42:36 -0800 +Subject: tcp: Fix use-after-free of nreq in reqsk_timer_handler(). + +From: Kuniyuki Iwashima <kuniyu@amazon.com> + +[ Upstream commit c31e72d021db2714df03df6c42855a1db592716c ] + +The cited commit replaced inet_csk_reqsk_queue_drop_and_put() with +__inet_csk_reqsk_queue_drop() and reqsk_put() in reqsk_timer_handler(). + +Then, oreq should be passed to reqsk_put() instead of req; otherwise +use-after-free of nreq could happen when reqsk is migrated but the +retry attempt failed (e.g. due to timeout). + +Let's pass oreq to reqsk_put(). + +Fixes: e8c526f2bdf1 ("tcp/dccp: Don't use timer_pending() in reqsk_queue_unlink().") +Reported-by: Liu Jian <liujian56@huawei.com> +Closes: https://lore.kernel.org/netdev/1284490f-9525-42ee-b7b8-ccadf6606f6d@huawei.com/ +Signed-off-by: Kuniyuki Iwashima <kuniyu@amazon.com> +Reviewed-by: Vadim Fedorenko <vadim.fedorenko@linux.dev> +Reviewed-by: Liu Jian <liujian56@huawei.com> +Reviewed-by: Eric Dumazet <edumazet@google.com> +Reviewed-by: Martin KaFai Lau <martin.lau@kernel.org> +Link: https://patch.msgid.link/20241123174236.62438-1-kuniyu@amazon.com +Signed-off-by: Paolo Abeni <pabeni@redhat.com> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + net/ipv4/inet_connection_sock.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c +index 2b698f8419fe2..fe7947f774062 100644 +--- a/net/ipv4/inet_connection_sock.c ++++ b/net/ipv4/inet_connection_sock.c +@@ -1189,7 +1189,7 @@ static void reqsk_timer_handler(struct timer_list *t) + + drop: + __inet_csk_reqsk_queue_drop(sk_listener, oreq, true); +- reqsk_put(req); ++ reqsk_put(oreq); + } + + static bool reqsk_queue_hash_req(struct request_sock *req, +-- +2.43.0 + diff --git a/queue-6.12/tg3-set-coherent-dma-mask-bits-to-31-for-bcm57766-ch.patch b/queue-6.12/tg3-set-coherent-dma-mask-bits-to-31-for-bcm57766-ch.patch new file mode 100644 index 00000000000..401f3f7f785 --- /dev/null +++ b/queue-6.12/tg3-set-coherent-dma-mask-bits-to-31-for-bcm57766-ch.patch @@ -0,0 +1,61 @@ +From 07a38380ac7329ad61a5efe0bc6c1611a3ff0915 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Mon, 18 Nov 2024 21:57:41 -0800 +Subject: tg3: Set coherent DMA mask bits to 31 for BCM57766 chipsets + +From: Pavan Chebbi <pavan.chebbi@broadcom.com> + +[ Upstream commit 614f4d166eeeb9bd709b0ad29552f691c0f45776 ] + +The hardware on Broadcom 1G chipsets have a known limitation +where they cannot handle DMA addresses that cross over 4GB. +When such an address is encountered, the hardware sets the +address overflow error bit in the DMA status register and +triggers a reset. + +However, BCM57766 hardware is setting the overflow bit and +triggering a reset in some cases when there is no actual +underlying address overflow. The hardware team analyzed the +issue and concluded that it is happening when the status +block update has an address with higher (b16 to b31) bits +as 0xffff following a previous update that had lowest bits +as 0xffff. + +To work around this bug in the BCM57766 hardware, set the +coherent dma mask from the current 64b to 31b. This will +ensure that upper bits of the status block DMA address are +always at most 0x7fff, thus avoiding the improper overflow +check described above. This work around is intended for only +status block and ring memories and has no effect on TX and +RX buffers as they do not require coherent memory. + +Fixes: 72f2afb8a685 ("[TG3]: Add DMA address workaround") +Reported-by: Salam Noureddine <noureddine@arista.com> +Reviewed-by: Kalesh AP <kalesh-anakkur.purayil@broadcom.com> +Reviewed-by: Somnath Kotur <somnath.kotur@broadcom.com> +Signed-off-by: Pavan Chebbi <pavan.chebbi@broadcom.com> +Reviewed-by: Michal Kubiak <michal.kubiak@intel.com> +Link: https://patch.msgid.link/20241119055741.147144-1-pavan.chebbi@broadcom.com +Signed-off-by: Jakub Kicinski <kuba@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/net/ethernet/broadcom/tg3.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c +index 3788159177417..d178138981a96 100644 +--- a/drivers/net/ethernet/broadcom/tg3.c ++++ b/drivers/net/ethernet/broadcom/tg3.c +@@ -17801,6 +17801,9 @@ static int tg3_init_one(struct pci_dev *pdev, + } else + persist_dma_mask = dma_mask = DMA_BIT_MASK(64); + ++ if (tg3_asic_rev(tp) == ASIC_REV_57766) ++ persist_dma_mask = DMA_BIT_MASK(31); ++ + /* Configure DMA attributes. */ + if (dma_mask > DMA_BIT_MASK(32)) { + err = dma_set_mask(&pdev->dev, dma_mask); +-- +2.43.0 + diff --git a/queue-6.12/thermal-core-fix-race-between-zone-registration-and-.patch b/queue-6.12/thermal-core-fix-race-between-zone-registration-and-.patch new file mode 100644 index 00000000000..ec73deb58ce --- /dev/null +++ b/queue-6.12/thermal-core-fix-race-between-zone-registration-and-.patch @@ -0,0 +1,92 @@ +From a0f400e23878798c6377ab7dfce370d3ffd8d853 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Fri, 4 Oct 2024 21:19:21 +0200 +Subject: thermal: core: Fix race between zone registration and system suspend + +From: Rafael J. Wysocki <rafael.j.wysocki@intel.com> + +[ Upstream commit cdf771ab476bd9acb0948f3088a277d5c3cacc6b ] + +If the registration of a thermal zone takes place at the time when +system suspend is started, thermal_pm_notify() can run before the new +thermal zone is added to thermal_tz_list and its "suspended" flag will +not be set. Consequently, if __thermal_zone_device_update() is called +for that thermal zone, it will not return early as expected which may +cause some destructive interference with the system suspend or resume +flow to occur. + +To avoid that, make thermal_zone_init_complete() introduced previously +set the "suspended" flag for new thermal zones if it runs during system +suspend or resume. + +Fixes: 4e814173a8c4 ("thermal: core: Fix thermal zone suspend-resume synchronization") +Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> +Link: https://patch.msgid.link/8490245.NyiUUSuA9g@rjwysocki.net +Reviewed-by: Lukasz Luba <lukasz.luba@arm.com> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/thermal/thermal_core.c | 18 ++++++++++++++++-- + 1 file changed, 16 insertions(+), 2 deletions(-) + +diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c +index b5538df3c4685..1d2f2b307bac5 100644 +--- a/drivers/thermal/thermal_core.c ++++ b/drivers/thermal/thermal_core.c +@@ -40,6 +40,8 @@ static DEFINE_MUTEX(thermal_governor_lock); + + static struct thermal_governor *def_governor; + ++static bool thermal_pm_suspended; ++ + /* + * Governor section: set of functions to handle thermal governors + * +@@ -1337,6 +1339,14 @@ static void thermal_zone_init_complete(struct thermal_zone_device *tz) + mutex_lock(&tz->lock); + + tz->state &= ~TZ_STATE_FLAG_INIT; ++ /* ++ * If system suspend or resume is in progress at this point, the ++ * new thermal zone needs to be marked as suspended because ++ * thermal_pm_notify() has run already. ++ */ ++ if (thermal_pm_suspended) ++ tz->state |= TZ_STATE_FLAG_SUSPENDED; ++ + __thermal_zone_device_update(tz, THERMAL_EVENT_UNSPECIFIED); + + mutex_unlock(&tz->lock); +@@ -1514,10 +1524,10 @@ thermal_zone_device_register_with_trips(const char *type, + list_for_each_entry(cdev, &thermal_cdev_list, node) + thermal_zone_cdev_bind(tz, cdev); + +- mutex_unlock(&thermal_list_lock); +- + thermal_zone_init_complete(tz); + ++ mutex_unlock(&thermal_list_lock); ++ + thermal_notify_tz_create(tz); + + thermal_debug_tz_add(tz); +@@ -1737,6 +1747,8 @@ static int thermal_pm_notify(struct notifier_block *nb, + case PM_SUSPEND_PREPARE: + mutex_lock(&thermal_list_lock); + ++ thermal_pm_suspended = true; ++ + list_for_each_entry(tz, &thermal_tz_list, node) + thermal_zone_pm_prepare(tz); + +@@ -1747,6 +1759,8 @@ static int thermal_pm_notify(struct notifier_block *nb, + case PM_POST_SUSPEND: + mutex_lock(&thermal_list_lock); + ++ thermal_pm_suspended = false; ++ + list_for_each_entry(tz, &thermal_tz_list, node) + thermal_zone_pm_complete(tz); + +-- +2.43.0 + diff --git a/queue-6.12/thermal-core-initialize-thermal-zones-before-registe.patch b/queue-6.12/thermal-core-initialize-thermal-zones-before-registe.patch new file mode 100644 index 00000000000..47aa09bbf10 --- /dev/null +++ b/queue-6.12/thermal-core-initialize-thermal-zones-before-registe.patch @@ -0,0 +1,46 @@ +From cd31a34968faa860aa932f2107e800a598bd9dd4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Fri, 4 Oct 2024 21:05:49 +0200 +Subject: thermal: core: Initialize thermal zones before registering them + +From: Rafael J. Wysocki <rafael.j.wysocki@intel.com> + +[ Upstream commit 662f920f7e390db5d1a6792a2b0ffa59b6c962fc ] + +Since user space can start interacting with a new thermal zone as soon +as device_register() called by thermal_zone_device_register_with_trips() +returns, it is better to initialize the thermal zone before calling +device_register() on it. + +Fixes: d0df264fbd3c ("thermal/core: Remove pointless thermal_zone_device_reset() function") +Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> +Link: https://patch.msgid.link/3336146.44csPzL39Z@rjwysocki.net +Reviewed-by: Lukasz Luba <lukasz.luba@arm.com> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/thermal/thermal_core.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c +index 8f03985f971c3..7a138bd5d8841 100644 +--- a/drivers/thermal/thermal_core.c ++++ b/drivers/thermal/thermal_core.c +@@ -1465,6 +1465,7 @@ thermal_zone_device_register_with_trips(const char *type, + thermal_zone_destroy_device_groups(tz); + goto remove_id; + } ++ thermal_zone_device_init(tz); + result = device_register(&tz->device); + if (result) + goto release_device; +@@ -1503,7 +1504,6 @@ thermal_zone_device_register_with_trips(const char *type, + + mutex_unlock(&thermal_list_lock); + +- thermal_zone_device_init(tz); + /* Update the new thermal zone and mark it as already updated. */ + if (atomic_cmpxchg(&tz->need_update, 1, 0)) + thermal_zone_device_update(tz, THERMAL_EVENT_UNSPECIFIED); +-- +2.43.0 + diff --git a/queue-6.12/thermal-core-mark-thermal-zones-as-initializing-to-s.patch b/queue-6.12/thermal-core-mark-thermal-zones-as-initializing-to-s.patch new file mode 100644 index 00000000000..7d0e5474427 --- /dev/null +++ b/queue-6.12/thermal-core-mark-thermal-zones-as-initializing-to-s.patch @@ -0,0 +1,109 @@ +From 6e6cc83e91123b1dac5b6237cfb3fc2a79ef7396 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Fri, 4 Oct 2024 21:15:04 +0200 +Subject: thermal: core: Mark thermal zones as initializing to start with + +From: Rafael J. Wysocki <rafael.j.wysocki@intel.com> + +[ Upstream commit 7837fa8115e0273d3cfbd3d17b3f7b7291ceac08 ] + +After thermal_zone_device_register_with_trips() has called +device_register() and it has registered the new thermal zone device +with the driver core, user space may access its sysfs attributes and, +among other things, it may enable the thermal zone before it is ready. + +To address this, introduce a new thermal zone state flag for +initialization and set it before calling device_register() in +thermal_zone_device_register_with_trips(). This causes +__thermal_zone_device_update() to return early until the new flag +is cleared. + +To clear it when the thermal zone is ready, introduce a new +function called thermal_zone_init_complete() that will also invoke +__thermal_zone_device_update() after clearing that flag (both under the +thernal zone lock) and make thermal_zone_device_register_with_trips() +call the new function instead of checking need_update and calling +thermal_zone_device_update() when it is set. + +After this change, if user space enables the thermal zone prematurely, +__thermal_zone_device_update() will return early for it until +thermal_zone_init_complete() is called. In turn, if the thermal zone +is not enabled by user space before thermal_zone_init_complete() is +called, the __thermal_zone_device_update() call in it will return early +because the thermal zone has not been enabled yet, but that function +will be invoked again by thermal_zone_device_set_mode() when the thermal +zone is enabled and it will not return early this time. + +The checking of need_update is not necessary any more because the +__thermal_zone_device_update() calls potentially triggered by cooling +device binding take place before calling thermal_zone_init_complete(), +so they all will return early, which means that +thermal_zone_init_complete() must call __thermal_zone_device_update() +in case the thermal zone is enabled prematurely by user space. + +Fixes: 203d3d4aa482 ("the generic thermal sysfs driver") +Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> +Link: https://patch.msgid.link/9360231.CDJkKcVGEf@rjwysocki.net +Reviewed-by: Lukasz Luba <lukasz.luba@arm.com> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/thermal/thermal_core.c | 16 +++++++++++++--- + drivers/thermal/thermal_core.h | 1 + + 2 files changed, 14 insertions(+), 3 deletions(-) + +diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c +index c3225fbe5c185..b5538df3c4685 100644 +--- a/drivers/thermal/thermal_core.c ++++ b/drivers/thermal/thermal_core.c +@@ -1332,6 +1332,16 @@ int thermal_zone_get_crit_temp(struct thermal_zone_device *tz, int *temp) + } + EXPORT_SYMBOL_GPL(thermal_zone_get_crit_temp); + ++static void thermal_zone_init_complete(struct thermal_zone_device *tz) ++{ ++ mutex_lock(&tz->lock); ++ ++ tz->state &= ~TZ_STATE_FLAG_INIT; ++ __thermal_zone_device_update(tz, THERMAL_EVENT_UNSPECIFIED); ++ ++ mutex_unlock(&tz->lock); ++} ++ + /** + * thermal_zone_device_register_with_trips() - register a new thermal zone device + * @type: the thermal zone device type +@@ -1451,6 +1461,8 @@ thermal_zone_device_register_with_trips(const char *type, + tz->passive_delay_jiffies = msecs_to_jiffies(passive_delay); + tz->recheck_delay_jiffies = THERMAL_RECHECK_DELAY; + ++ tz->state = TZ_STATE_FLAG_INIT; ++ + /* sys I/F */ + /* Add nodes that are always present via .groups */ + result = thermal_zone_create_device_groups(tz); +@@ -1504,9 +1516,7 @@ thermal_zone_device_register_with_trips(const char *type, + + mutex_unlock(&thermal_list_lock); + +- /* Update the new thermal zone and mark it as already updated. */ +- if (atomic_cmpxchg(&tz->need_update, 1, 0)) +- thermal_zone_device_update(tz, THERMAL_EVENT_UNSPECIFIED); ++ thermal_zone_init_complete(tz); + + thermal_notify_tz_create(tz); + +diff --git a/drivers/thermal/thermal_core.h b/drivers/thermal/thermal_core.h +index 79c52adf6b7f8..421522a2bb9d4 100644 +--- a/drivers/thermal/thermal_core.h ++++ b/drivers/thermal/thermal_core.h +@@ -63,6 +63,7 @@ struct thermal_governor { + + #define TZ_STATE_FLAG_SUSPENDED BIT(0) + #define TZ_STATE_FLAG_RESUMING BIT(1) ++#define TZ_STATE_FLAG_INIT BIT(2) + + #define TZ_STATE_READY 0 + +-- +2.43.0 + diff --git a/queue-6.12/thermal-core-rearrange-pm-notification-code.patch b/queue-6.12/thermal-core-rearrange-pm-notification-code.patch new file mode 100644 index 00000000000..aae3e146557 --- /dev/null +++ b/queue-6.12/thermal-core-rearrange-pm-notification-code.patch @@ -0,0 +1,142 @@ +From add4590acc7a1aae00b2eb11617c5e6f4ff04a51 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Fri, 4 Oct 2024 21:09:23 +0200 +Subject: thermal: core: Rearrange PM notification code + +From: Rafael J. Wysocki <rafael.j.wysocki@intel.com> + +[ Upstream commit 7ddca5885718c2683d75689aa065c9a3bb317e5a ] + +Move the code run for each thermal zone by the thermal PM notify +handler to separate functions. + +This will help to make some subsequent changes look somewhat more +straightforward, among other things. + +No intentional functional impact. + +Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> +Link: https://patch.msgid.link/2299090.iZASKD2KPV@rjwysocki.net +Reviewed-by: Lukasz Luba <lukasz.luba@arm.com> +Stable-dep-of: 7837fa8115e0 ("thermal: core: Mark thermal zones as initializing to start with") +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/thermal/thermal_core.c | 88 ++++++++++++++++++---------------- + 1 file changed, 46 insertions(+), 42 deletions(-) + +diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c +index 7a138bd5d8841..9198861916969 100644 +--- a/drivers/thermal/thermal_core.c ++++ b/drivers/thermal/thermal_core.c +@@ -1675,6 +1675,48 @@ static void thermal_zone_device_resume(struct work_struct *work) + mutex_unlock(&tz->lock); + } + ++static void thermal_zone_pm_prepare(struct thermal_zone_device *tz) ++{ ++ mutex_lock(&tz->lock); ++ ++ if (tz->resuming) { ++ /* ++ * thermal_zone_device_resume() queued up for this zone has not ++ * acquired the lock yet, so release it to let the function run ++ * and wait util it has done the work. ++ */ ++ mutex_unlock(&tz->lock); ++ ++ wait_for_completion(&tz->resume); ++ ++ mutex_lock(&tz->lock); ++ } ++ ++ tz->suspended = true; ++ ++ mutex_unlock(&tz->lock); ++} ++ ++static void thermal_zone_pm_complete(struct thermal_zone_device *tz) ++{ ++ mutex_lock(&tz->lock); ++ ++ cancel_delayed_work(&tz->poll_queue); ++ ++ reinit_completion(&tz->resume); ++ tz->resuming = true; ++ ++ /* ++ * Replace the work function with the resume one, which will restore the ++ * original work function and schedule the polling work if needed. ++ */ ++ INIT_DELAYED_WORK(&tz->poll_queue, thermal_zone_device_resume); ++ /* Queue up the work without a delay. */ ++ mod_delayed_work(system_freezable_power_efficient_wq, &tz->poll_queue, 0); ++ ++ mutex_unlock(&tz->lock); ++} ++ + static int thermal_pm_notify(struct notifier_block *nb, + unsigned long mode, void *_unused) + { +@@ -1686,27 +1728,8 @@ static int thermal_pm_notify(struct notifier_block *nb, + case PM_SUSPEND_PREPARE: + mutex_lock(&thermal_list_lock); + +- list_for_each_entry(tz, &thermal_tz_list, node) { +- mutex_lock(&tz->lock); +- +- if (tz->resuming) { +- /* +- * thermal_zone_device_resume() queued up for +- * this zone has not acquired the lock yet, so +- * release it to let the function run and wait +- * util it has done the work. +- */ +- mutex_unlock(&tz->lock); +- +- wait_for_completion(&tz->resume); +- +- mutex_lock(&tz->lock); +- } +- +- tz->suspended = true; +- +- mutex_unlock(&tz->lock); +- } ++ list_for_each_entry(tz, &thermal_tz_list, node) ++ thermal_zone_pm_prepare(tz); + + mutex_unlock(&thermal_list_lock); + break; +@@ -1715,27 +1738,8 @@ static int thermal_pm_notify(struct notifier_block *nb, + case PM_POST_SUSPEND: + mutex_lock(&thermal_list_lock); + +- list_for_each_entry(tz, &thermal_tz_list, node) { +- mutex_lock(&tz->lock); +- +- cancel_delayed_work(&tz->poll_queue); +- +- reinit_completion(&tz->resume); +- tz->resuming = true; +- +- /* +- * Replace the work function with the resume one, which +- * will restore the original work function and schedule +- * the polling work if needed. +- */ +- INIT_DELAYED_WORK(&tz->poll_queue, +- thermal_zone_device_resume); +- /* Queue up the work without a delay. */ +- mod_delayed_work(system_freezable_power_efficient_wq, +- &tz->poll_queue, 0); +- +- mutex_unlock(&tz->lock); +- } ++ list_for_each_entry(tz, &thermal_tz_list, node) ++ thermal_zone_pm_complete(tz); + + mutex_unlock(&thermal_list_lock); + break; +-- +2.43.0 + diff --git a/queue-6.12/thermal-core-represent-suspend-related-thermal-zone-.patch b/queue-6.12/thermal-core-represent-suspend-related-thermal-zone-.patch new file mode 100644 index 00000000000..e1874553f40 --- /dev/null +++ b/queue-6.12/thermal-core-represent-suspend-related-thermal-zone-.patch @@ -0,0 +1,124 @@ +From cd50693ac48f9697696e1e4db9a5ea8e0cad9257 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Fri, 4 Oct 2024 21:11:53 +0200 +Subject: thermal: core: Represent suspend-related thermal zone flags as bits + +From: Rafael J. Wysocki <rafael.j.wysocki@intel.com> + +[ Upstream commit 26c9ab8090cda1eb3d42f491cc32d227404897da ] + +Instead of using two separate fields in struct thermal_zone_device for +representing flags related to thermal zone suspend, represent them +explicitly as bits in one u8 "state" field. + +Subsequently, that field will be used for addressing race conditions +related to thermal zone initialization and exit. + +No intentional functional impact. + +Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> +Link: https://patch.msgid.link/7733910.EvYhyI6sBW@rjwysocki.net +Reviewed-by: Lukasz Luba <lukasz.luba@arm.com> +Stable-dep-of: 7837fa8115e0 ("thermal: core: Mark thermal zones as initializing to start with") +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/thermal/thermal_core.c | 11 +++++------ + drivers/thermal/thermal_core.h | 11 +++++++---- + 2 files changed, 12 insertions(+), 10 deletions(-) + +diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c +index 9198861916969..c3225fbe5c185 100644 +--- a/drivers/thermal/thermal_core.c ++++ b/drivers/thermal/thermal_core.c +@@ -547,7 +547,7 @@ void __thermal_zone_device_update(struct thermal_zone_device *tz, + int low = -INT_MAX, high = INT_MAX; + int temp, ret; + +- if (tz->suspended || tz->mode != THERMAL_DEVICE_ENABLED) ++ if (tz->state != TZ_STATE_READY || tz->mode != THERMAL_DEVICE_ENABLED) + return; + + ret = __thermal_zone_get_temp(tz, &temp); +@@ -1662,7 +1662,7 @@ static void thermal_zone_device_resume(struct work_struct *work) + + mutex_lock(&tz->lock); + +- tz->suspended = false; ++ tz->state &= ~(TZ_STATE_FLAG_SUSPENDED | TZ_STATE_FLAG_RESUMING); + + thermal_debug_tz_resume(tz); + thermal_zone_device_init(tz); +@@ -1670,7 +1670,6 @@ static void thermal_zone_device_resume(struct work_struct *work) + __thermal_zone_device_update(tz, THERMAL_TZ_RESUME); + + complete(&tz->resume); +- tz->resuming = false; + + mutex_unlock(&tz->lock); + } +@@ -1679,7 +1678,7 @@ static void thermal_zone_pm_prepare(struct thermal_zone_device *tz) + { + mutex_lock(&tz->lock); + +- if (tz->resuming) { ++ if (tz->state & TZ_STATE_FLAG_RESUMING) { + /* + * thermal_zone_device_resume() queued up for this zone has not + * acquired the lock yet, so release it to let the function run +@@ -1692,7 +1691,7 @@ static void thermal_zone_pm_prepare(struct thermal_zone_device *tz) + mutex_lock(&tz->lock); + } + +- tz->suspended = true; ++ tz->state |= TZ_STATE_FLAG_SUSPENDED; + + mutex_unlock(&tz->lock); + } +@@ -1704,7 +1703,7 @@ static void thermal_zone_pm_complete(struct thermal_zone_device *tz) + cancel_delayed_work(&tz->poll_queue); + + reinit_completion(&tz->resume); +- tz->resuming = true; ++ tz->state |= TZ_STATE_FLAG_RESUMING; + + /* + * Replace the work function with the resume one, which will restore the +diff --git a/drivers/thermal/thermal_core.h b/drivers/thermal/thermal_core.h +index a64d39b1c86b2..79c52adf6b7f8 100644 +--- a/drivers/thermal/thermal_core.h ++++ b/drivers/thermal/thermal_core.h +@@ -61,6 +61,11 @@ struct thermal_governor { + struct list_head governor_list; + }; + ++#define TZ_STATE_FLAG_SUSPENDED BIT(0) ++#define TZ_STATE_FLAG_RESUMING BIT(1) ++ ++#define TZ_STATE_READY 0 ++ + /** + * struct thermal_zone_device - structure for a thermal zone + * @id: unique id number for each thermal zone +@@ -100,8 +105,7 @@ struct thermal_governor { + * @node: node in thermal_tz_list (in thermal_core.c) + * @poll_queue: delayed work for polling + * @notify_event: Last notification event +- * @suspended: thermal zone suspend indicator +- * @resuming: indicates whether or not thermal zone resume is in progress ++ * @state: current state of the thermal zone + * @trips: array of struct thermal_trip objects + */ + struct thermal_zone_device { +@@ -134,8 +138,7 @@ struct thermal_zone_device { + struct list_head node; + struct delayed_work poll_queue; + enum thermal_notify_event notify_event; +- bool suspended; +- bool resuming; ++ u8 state; + #ifdef CONFIG_THERMAL_DEBUGFS + struct thermal_debugfs *debugfs; + #endif +-- +2.43.0 + diff --git a/queue-6.12/thermal-lib-fix-memory-leak-on-error-in-thermal_genl.patch b/queue-6.12/thermal-lib-fix-memory-leak-on-error-in-thermal_genl.patch new file mode 100644 index 00000000000..065a0d8e8fa --- /dev/null +++ b/queue-6.12/thermal-lib-fix-memory-leak-on-error-in-thermal_genl.patch @@ -0,0 +1,64 @@ +From 841bf0b08261149c3c91e26b209195d8017ff1fa Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Thu, 24 Oct 2024 12:59:38 +0200 +Subject: thermal/lib: Fix memory leak on error in thermal_genl_auto() + +From: Daniel Lezcano <daniel.lezcano@linaro.org> + +[ Upstream commit 7569406e95f2353070d88ebc88e8c13698542317 ] + +The function thermal_genl_auto() does not free the allocated message +in the error path. Fix that by putting a out label and jump to it +which will free the message instead of directly returning an error. + +Fixes: 47c4b0de080a ("tools/lib/thermal: Add a thermal library") +Reported-by: Lukasz Luba <lukasz.luba@arm.com> +Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org> +Reviewed-by: Lukasz Luba <lukasz.luba@arm.com> +Link: https://patch.msgid.link/20241024105938.1095358-1-daniel.lezcano@linaro.org +[ rjw: Fixed up the !msg error path, added Fixes tag ] +Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + tools/lib/thermal/commands.c | 11 +++++++---- + 1 file changed, 7 insertions(+), 4 deletions(-) + +diff --git a/tools/lib/thermal/commands.c b/tools/lib/thermal/commands.c +index a9223df91dcf5..27b4442f0e347 100644 +--- a/tools/lib/thermal/commands.c ++++ b/tools/lib/thermal/commands.c +@@ -279,6 +279,7 @@ static thermal_error_t thermal_genl_auto(struct thermal_handler *th, cmd_cb_t cm + struct cmd_param *param, + int cmd, int flags, void *arg) + { ++ thermal_error_t ret = THERMAL_ERROR; + struct nl_msg *msg; + void *hdr; + +@@ -289,17 +290,19 @@ static thermal_error_t thermal_genl_auto(struct thermal_handler *th, cmd_cb_t cm + hdr = genlmsg_put(msg, NL_AUTO_PORT, NL_AUTO_SEQ, thermal_cmd_ops.o_id, + 0, flags, cmd, THERMAL_GENL_VERSION); + if (!hdr) +- return THERMAL_ERROR; ++ goto out; + + if (cmd_cb && cmd_cb(msg, param)) +- return THERMAL_ERROR; ++ goto out; + + if (nl_send_msg(th->sk_cmd, th->cb_cmd, msg, genl_handle_msg, arg)) +- return THERMAL_ERROR; ++ goto out; + ++ ret = THERMAL_SUCCESS; ++out: + nlmsg_free(msg); + +- return THERMAL_SUCCESS; ++ return ret; + } + + thermal_error_t thermal_cmd_get_tz(struct thermal_handler *th, struct thermal_zone **tz) +-- +2.43.0 + diff --git a/queue-6.12/thermal-testing-initialize-some-variables-annoteded-.patch b/queue-6.12/thermal-testing-initialize-some-variables-annoteded-.patch new file mode 100644 index 00000000000..25d93f55c0f --- /dev/null +++ b/queue-6.12/thermal-testing-initialize-some-variables-annoteded-.patch @@ -0,0 +1,69 @@ +From 0781b9590ee2ba84548c88ad01d9092b7b801209 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Thu, 14 Nov 2024 17:25:09 +0100 +Subject: thermal: testing: Initialize some variables annoteded with _free() + +From: Rafael J. Wysocki <rafael.j.wysocki@intel.com> + +[ Upstream commit 0104dcdaad3a7afd141e79a5fb817a92ada910ac ] + +Variables annotated with __free() need to be initialized if the function +can return before they get updated for the first time or the attempt to +free the memory pointed to by them upon function return may crash the +kernel. + +Fix this issue in some places in the thermal testing code. + +Fixes: f6a034f2df42 ("thermal: Introduce a debugfs-based testing facility") +Reported-by: Dan Carpenter <dan.carpenter@linaro.org> +Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> +Link: https://patch.msgid.link/12576267.O9o76ZdvQC@rjwysocki.net +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/thermal/testing/zone.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/drivers/thermal/testing/zone.c b/drivers/thermal/testing/zone.c +index 452c3fa2b2bc5..1f01f49527031 100644 +--- a/drivers/thermal/testing/zone.c ++++ b/drivers/thermal/testing/zone.c +@@ -185,7 +185,7 @@ static void tt_add_tz_work_fn(struct work_struct *work) + int tt_add_tz(void) + { + struct tt_thermal_zone *tt_zone __free(kfree); +- struct tt_work *tt_work __free(kfree); ++ struct tt_work *tt_work __free(kfree) = NULL; + int ret; + + tt_zone = kzalloc(sizeof(*tt_zone), GFP_KERNEL); +@@ -237,7 +237,7 @@ static void tt_zone_unregister_tz(struct tt_thermal_zone *tt_zone) + + int tt_del_tz(const char *arg) + { +- struct tt_work *tt_work __free(kfree); ++ struct tt_work *tt_work __free(kfree) = NULL; + struct tt_thermal_zone *tt_zone, *aux; + int ret; + int id; +@@ -336,8 +336,8 @@ static void tt_zone_add_trip_work_fn(struct work_struct *work) + int tt_zone_add_trip(const char *arg) + { + struct tt_thermal_zone *tt_zone __free(put_tt_zone) = NULL; ++ struct tt_trip *tt_trip __free(kfree) = NULL; + struct tt_work *tt_work __free(kfree); +- struct tt_trip *tt_trip __free(kfree); + int id; + + tt_work = kzalloc(sizeof(*tt_work), GFP_KERNEL); +@@ -392,7 +392,7 @@ static struct thermal_zone_device_ops tt_zone_ops = { + + static int tt_zone_register_tz(struct tt_thermal_zone *tt_zone) + { +- struct thermal_trip *trips __free(kfree); ++ struct thermal_trip *trips __free(kfree) = NULL; + struct thermal_zone_device *tz; + struct tt_trip *tt_trip; + int i; +-- +2.43.0 + diff --git a/queue-6.12/thermal-testing-use-define_free-and-__free-to-simpli.patch b/queue-6.12/thermal-testing-use-define_free-and-__free-to-simpli.patch new file mode 100644 index 00000000000..70716571299 --- /dev/null +++ b/queue-6.12/thermal-testing-use-define_free-and-__free-to-simpli.patch @@ -0,0 +1,110 @@ +From 77bbd5512f0092af73c7b4bb101dcb6993eb96ce Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Sun, 10 Nov 2024 14:06:01 +0100 +Subject: thermal: testing: Use DEFINE_FREE() and __free() to simplify code + +From: Rafael J. Wysocki <rafael.j.wysocki@intel.com> + +[ Upstream commit 1c426fd09ca85fb77f120f7933e39eb9df99a39a ] + +Use DEFINE_FREE() to define a __free function for dropping thermal +zone template reference counters and use it along with __free() to +simplify code in some places. + +No intentional functional impact. + +Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> +Link: https://patch.msgid.link/4628747.LvFx2qVVIh@rjwysocki.net +[ rjw: Add variable initialization to address compiler warning ] +Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> +Stable-dep-of: 0104dcdaad3a ("thermal: testing: Initialize some variables annoteded with _free()") +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/thermal/testing/zone.c | 24 +++++++++--------------- + 1 file changed, 9 insertions(+), 15 deletions(-) + +diff --git a/drivers/thermal/testing/zone.c b/drivers/thermal/testing/zone.c +index c6d8c66f40f98..452c3fa2b2bc5 100644 +--- a/drivers/thermal/testing/zone.c ++++ b/drivers/thermal/testing/zone.c +@@ -310,6 +310,9 @@ static void tt_put_tt_zone(struct tt_thermal_zone *tt_zone) + tt_zone->refcount--; + } + ++DEFINE_FREE(put_tt_zone, struct tt_thermal_zone *, ++ if (!IS_ERR_OR_NULL(_T)) tt_put_tt_zone(_T)) ++ + static void tt_zone_add_trip_work_fn(struct work_struct *work) + { + struct tt_work *tt_work = tt_work_of_work(work); +@@ -332,9 +335,9 @@ static void tt_zone_add_trip_work_fn(struct work_struct *work) + + int tt_zone_add_trip(const char *arg) + { ++ struct tt_thermal_zone *tt_zone __free(put_tt_zone) = NULL; + struct tt_work *tt_work __free(kfree); + struct tt_trip *tt_trip __free(kfree); +- struct tt_thermal_zone *tt_zone; + int id; + + tt_work = kzalloc(sizeof(*tt_work), GFP_KERNEL); +@@ -350,10 +353,8 @@ int tt_zone_add_trip(const char *arg) + return PTR_ERR(tt_zone); + + id = ida_alloc(&tt_zone->ida, GFP_KERNEL); +- if (id < 0) { +- tt_put_tt_zone(tt_zone); ++ if (id < 0) + return id; +- } + + tt_trip->trip.type = THERMAL_TRIP_ACTIVE; + tt_trip->trip.temperature = THERMAL_TEMP_INVALID; +@@ -366,7 +367,7 @@ int tt_zone_add_trip(const char *arg) + tt_zone->num_trips++; + + INIT_WORK(&tt_work->work, tt_zone_add_trip_work_fn); +- tt_work->tt_zone = tt_zone; ++ tt_work->tt_zone = no_free_ptr(tt_zone); + tt_work->tt_trip = no_free_ptr(tt_trip); + schedule_work(&(no_free_ptr(tt_work)->work)); + +@@ -425,23 +426,18 @@ static int tt_zone_register_tz(struct tt_thermal_zone *tt_zone) + + int tt_zone_reg(const char *arg) + { +- struct tt_thermal_zone *tt_zone; +- int ret; ++ struct tt_thermal_zone *tt_zone __free(put_tt_zone); + + tt_zone = tt_get_tt_zone(arg); + if (IS_ERR(tt_zone)) + return PTR_ERR(tt_zone); + +- ret = tt_zone_register_tz(tt_zone); +- +- tt_put_tt_zone(tt_zone); +- +- return ret; ++ return tt_zone_register_tz(tt_zone); + } + + int tt_zone_unreg(const char *arg) + { +- struct tt_thermal_zone *tt_zone; ++ struct tt_thermal_zone *tt_zone __free(put_tt_zone); + + tt_zone = tt_get_tt_zone(arg); + if (IS_ERR(tt_zone)) +@@ -449,8 +445,6 @@ int tt_zone_unreg(const char *arg) + + tt_zone_unregister_tz(tt_zone); + +- tt_put_tt_zone(tt_zone); +- + return 0; + } + +-- +2.43.0 + diff --git a/queue-6.12/time-fix-references-to-_msecs_to_jiffies-handling-of.patch b/queue-6.12/time-fix-references-to-_msecs_to_jiffies-handling-of.patch new file mode 100644 index 00000000000..d6b85ba80c9 --- /dev/null +++ b/queue-6.12/time-fix-references-to-_msecs_to_jiffies-handling-of.patch @@ -0,0 +1,55 @@ +From d030d08da81e76e9c2afb30baefab63b03792303 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Fri, 25 Oct 2024 13:01:41 +0200 +Subject: time: Fix references to _msecs_to_jiffies() handling of values + +From: Miguel Ojeda <ojeda@kernel.org> + +[ Upstream commit 92b043fd995a63a57aae29ff85a39b6f30cd440c ] + +The details about the handling of the "normal" values were moved +to the _msecs_to_jiffies() helpers in commit ca42aaf0c861 ("time: +Refactor msecs_to_jiffies"). However, the same commit still mentioned +__msecs_to_jiffies() in the added documentation. + +Thus point to _msecs_to_jiffies() instead. + +Fixes: ca42aaf0c861 ("time: Refactor msecs_to_jiffies") +Signed-off-by: Miguel Ojeda <ojeda@kernel.org> +Signed-off-by: Thomas Gleixner <tglx@linutronix.de> +Link: https://lore.kernel.org/all/20241025110141.157205-2-ojeda@kernel.org +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + include/linux/jiffies.h | 2 +- + kernel/time/time.c | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/include/linux/jiffies.h b/include/linux/jiffies.h +index 1220f0fbe5bf9..5d21dacd62bc7 100644 +--- a/include/linux/jiffies.h ++++ b/include/linux/jiffies.h +@@ -502,7 +502,7 @@ static inline unsigned long _msecs_to_jiffies(const unsigned int m) + * - all other values are converted to jiffies by either multiplying + * the input value by a factor or dividing it with a factor and + * handling any 32-bit overflows. +- * for the details see __msecs_to_jiffies() ++ * for the details see _msecs_to_jiffies() + * + * msecs_to_jiffies() checks for the passed in value being a constant + * via __builtin_constant_p() allowing gcc to eliminate most of the +diff --git a/kernel/time/time.c b/kernel/time/time.c +index e1879ca321033..1ad88e97b4ebc 100644 +--- a/kernel/time/time.c ++++ b/kernel/time/time.c +@@ -556,7 +556,7 @@ EXPORT_SYMBOL(ns_to_timespec64); + * - all other values are converted to jiffies by either multiplying + * the input value by a factor or dividing it with a factor and + * handling any 32-bit overflows. +- * for the details see __msecs_to_jiffies() ++ * for the details see _msecs_to_jiffies() + * + * msecs_to_jiffies() checks for the passed in value being a constant + * via __builtin_constant_p() allowing gcc to eliminate most of the +-- +2.43.0 + diff --git a/queue-6.12/time-partially-revert-cleanup-on-msecs_to_jiffies-do.patch b/queue-6.12/time-partially-revert-cleanup-on-msecs_to_jiffies-do.patch new file mode 100644 index 00000000000..4119fd7b93b --- /dev/null +++ b/queue-6.12/time-partially-revert-cleanup-on-msecs_to_jiffies-do.patch @@ -0,0 +1,42 @@ +From a3bffebcf54789de8a40f6eda60f58b4df56cfa6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Fri, 25 Oct 2024 13:01:40 +0200 +Subject: time: Partially revert cleanup on msecs_to_jiffies() documentation + +From: Miguel Ojeda <ojeda@kernel.org> + +[ Upstream commit b05aefc1f5886c8aece650c9c1639c87b976191a ] + +The documentation's intention is to compare msecs_to_jiffies() (first +sentence) with __msecs_to_jiffies() (second sentence), which is what the +original documentation did. One of the cleanups in commit f3cb80804b82 +("time: Fix various kernel-doc problems") may have thought the paragraph +was talking about the latter since that is what it is being documented. + +Thus revert that part of the change. + +Fixes: f3cb80804b82 ("time: Fix various kernel-doc problems") +Signed-off-by: Miguel Ojeda <ojeda@kernel.org> +Signed-off-by: Thomas Gleixner <tglx@linutronix.de> +Link: https://lore.kernel.org/all/20241025110141.157205-1-ojeda@kernel.org +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + kernel/time/time.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/kernel/time/time.c b/kernel/time/time.c +index 642647f5046be..e1879ca321033 100644 +--- a/kernel/time/time.c ++++ b/kernel/time/time.c +@@ -558,7 +558,7 @@ EXPORT_SYMBOL(ns_to_timespec64); + * handling any 32-bit overflows. + * for the details see __msecs_to_jiffies() + * +- * __msecs_to_jiffies() checks for the passed in value being a constant ++ * msecs_to_jiffies() checks for the passed in value being a constant + * via __builtin_constant_p() allowing gcc to eliminate most of the + * code, __msecs_to_jiffies() is called if the value passed does not + * allow constant folding and the actual conversion must be done at +-- +2.43.0 + diff --git a/queue-6.12/timers-add-missing-read_once-in-__run_timer_base.patch b/queue-6.12/timers-add-missing-read_once-in-__run_timer_base.patch new file mode 100644 index 00000000000..381a9daec2e --- /dev/null +++ b/queue-6.12/timers-add-missing-read_once-in-__run_timer_base.patch @@ -0,0 +1,44 @@ +From f62c348949866c1c11f9b484aa652c4f2cb4745e Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Wed, 30 Oct 2024 08:53:51 +0100 +Subject: timers: Add missing READ_ONCE() in __run_timer_base() + +From: Thomas Gleixner <tglx@linutronix.de> + +[ Upstream commit 1d4199cbbe95efaba51304cfd844bd0ccd224e61 ] + +__run_timer_base() checks base::next_expiry without holding +base::lock. That can race with a remote CPU updating next_expiry under the +lock. This is an intentional and harmless data race, but lacks a +READ_ONCE(), so KCSAN complains about this. + +Add the missing READ_ONCE(). All other places are covered already. + +Fixes: 79f8b28e85f8 ("timers: Annotate possible non critical data race of next_expiry") +Reported-by: kernel test robot <oliver.sang@intel.com> +Signed-off-by: Thomas Gleixner <tglx@linutronix.de> +Reviewed-by: Frederic Weisbecker <frederic@kernel.org> +Link: https://lore.kernel.org/all/87a5emyqk0.ffs@tglx +Closes: https://lore.kernel.org/oe-lkp/202410301205.ef8e9743-lkp@intel.com +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + kernel/time/timer.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/kernel/time/timer.c b/kernel/time/timer.c +index 0fc9d066a7be4..7835f9b376e76 100644 +--- a/kernel/time/timer.c ++++ b/kernel/time/timer.c +@@ -2422,7 +2422,8 @@ static inline void __run_timers(struct timer_base *base) + + static void __run_timer_base(struct timer_base *base) + { +- if (time_before(jiffies, base->next_expiry)) ++ /* Can race against a remote CPU updating next_expiry under the lock */ ++ if (time_before(jiffies, READ_ONCE(base->next_expiry))) + return; + + timer_base_lock_expiry(base); +-- +2.43.0 + diff --git a/queue-6.12/tools-lib-thermal-make-more-generic-the-command-enco.patch b/queue-6.12/tools-lib-thermal-make-more-generic-the-command-enco.patch new file mode 100644 index 00000000000..bcfed75516e --- /dev/null +++ b/queue-6.12/tools-lib-thermal-make-more-generic-the-command-enco.patch @@ -0,0 +1,115 @@ +From d40578dba3d88a2e3fdf9e23759f5d1b1eef757a Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Tue, 22 Oct 2024 17:51:43 +0200 +Subject: tools/lib/thermal: Make more generic the command encoding function + +From: Daniel Lezcano <daniel.lezcano@linaro.org> + +[ Upstream commit 24b216b2d13568c703a76137ef54a2a9531a71d8 ] + +The thermal netlink has been extended with more commands which require +an encoding with more information. The generic encoding function puts +the thermal zone id with the command name. It is the unique +parameters. + +The next changes will provide more parameters to the command. Set the +scene for those new parameters by making the encoding function more +generic. + +Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org> +Reviewed-by: Lukasz Luba <lukasz.luba@arm.com> +Link: https://patch.msgid.link/20241022155147.463475-4-daniel.lezcano@linaro.org +Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> +Stable-dep-of: 7569406e95f2 ("thermal/lib: Fix memory leak on error in thermal_genl_auto()") +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + tools/lib/thermal/commands.c | 41 ++++++++++++++++++++++++++++-------- + 1 file changed, 32 insertions(+), 9 deletions(-) + +diff --git a/tools/lib/thermal/commands.c b/tools/lib/thermal/commands.c +index 73d4d4e8d6ec0..a9223df91dcf5 100644 +--- a/tools/lib/thermal/commands.c ++++ b/tools/lib/thermal/commands.c +@@ -261,8 +261,23 @@ static struct genl_ops thermal_cmd_ops = { + .o_ncmds = ARRAY_SIZE(thermal_cmds), + }; + +-static thermal_error_t thermal_genl_auto(struct thermal_handler *th, int id, int cmd, +- int flags, void *arg) ++struct cmd_param { ++ int tz_id; ++}; ++ ++typedef int (*cmd_cb_t)(struct nl_msg *, struct cmd_param *); ++ ++static int thermal_genl_tz_id_encode(struct nl_msg *msg, struct cmd_param *p) ++{ ++ if (p->tz_id >= 0 && nla_put_u32(msg, THERMAL_GENL_ATTR_TZ_ID, p->tz_id)) ++ return -1; ++ ++ return 0; ++} ++ ++static thermal_error_t thermal_genl_auto(struct thermal_handler *th, cmd_cb_t cmd_cb, ++ struct cmd_param *param, ++ int cmd, int flags, void *arg) + { + struct nl_msg *msg; + void *hdr; +@@ -276,7 +291,7 @@ static thermal_error_t thermal_genl_auto(struct thermal_handler *th, int id, int + if (!hdr) + return THERMAL_ERROR; + +- if (id >= 0 && nla_put_u32(msg, THERMAL_GENL_ATTR_TZ_ID, id)) ++ if (cmd_cb && cmd_cb(msg, param)) + return THERMAL_ERROR; + + if (nl_send_msg(th->sk_cmd, th->cb_cmd, msg, genl_handle_msg, arg)) +@@ -289,30 +304,38 @@ static thermal_error_t thermal_genl_auto(struct thermal_handler *th, int id, int + + thermal_error_t thermal_cmd_get_tz(struct thermal_handler *th, struct thermal_zone **tz) + { +- return thermal_genl_auto(th, -1, THERMAL_GENL_CMD_TZ_GET_ID, ++ return thermal_genl_auto(th, NULL, NULL, THERMAL_GENL_CMD_TZ_GET_ID, + NLM_F_DUMP | NLM_F_ACK, tz); + } + + thermal_error_t thermal_cmd_get_cdev(struct thermal_handler *th, struct thermal_cdev **tc) + { +- return thermal_genl_auto(th, -1, THERMAL_GENL_CMD_CDEV_GET, ++ return thermal_genl_auto(th, NULL, NULL, THERMAL_GENL_CMD_CDEV_GET, + NLM_F_DUMP | NLM_F_ACK, tc); + } + + thermal_error_t thermal_cmd_get_trip(struct thermal_handler *th, struct thermal_zone *tz) + { +- return thermal_genl_auto(th, tz->id, THERMAL_GENL_CMD_TZ_GET_TRIP, +- 0, tz); ++ struct cmd_param p = { .tz_id = tz->id }; ++ ++ return thermal_genl_auto(th, thermal_genl_tz_id_encode, &p, ++ THERMAL_GENL_CMD_TZ_GET_TRIP, 0, tz); + } + + thermal_error_t thermal_cmd_get_governor(struct thermal_handler *th, struct thermal_zone *tz) + { +- return thermal_genl_auto(th, tz->id, THERMAL_GENL_CMD_TZ_GET_GOV, 0, tz); ++ struct cmd_param p = { .tz_id = tz->id }; ++ ++ return thermal_genl_auto(th, thermal_genl_tz_id_encode, &p, ++ THERMAL_GENL_CMD_TZ_GET_GOV, 0, tz); + } + + thermal_error_t thermal_cmd_get_temp(struct thermal_handler *th, struct thermal_zone *tz) + { +- return thermal_genl_auto(th, tz->id, THERMAL_GENL_CMD_TZ_GET_TEMP, 0, tz); ++ struct cmd_param p = { .tz_id = tz->id }; ++ ++ return thermal_genl_auto(th, thermal_genl_tz_id_encode, &p, ++ THERMAL_GENL_CMD_TZ_GET_TEMP, 0, tz); + } + + thermal_error_t thermal_cmd_exit(struct thermal_handler *th) +-- +2.43.0 + diff --git a/queue-6.12/tpm-fix-signed-unsigned-bug-when-checking-event-logs.patch b/queue-6.12/tpm-fix-signed-unsigned-bug-when-checking-event-logs.patch new file mode 100644 index 00000000000..6945bc90bd3 --- /dev/null +++ b/queue-6.12/tpm-fix-signed-unsigned-bug-when-checking-event-logs.patch @@ -0,0 +1,83 @@ +From bcf27094f5a9ff7e2034b3a90e616065d2b67914 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Fri, 13 Sep 2024 19:19:51 -0400 +Subject: tpm: fix signed/unsigned bug when checking event logs + +From: Gregory Price <gourry@gourry.net> + +[ Upstream commit e6d654e9f5a97742cfe794b1c4bb5d3fb2d25e98 ] + +A prior bugfix that fixes a signed/unsigned error causes +another signed unsigned error. + +A situation where log_tbl->size is invalid can cause the +size passed to memblock_reserve to become negative. + +log_size from the main event log is an unsigned int, and +the code reduces to the following + +u64 value = (int)unsigned_value; + +This results in sign extension, and the value sent to +memblock_reserve becomes effectively negative. + +Fixes: be59d57f9806 ("efi/tpm: Fix sanity check of unsigned tbl_size being less than zero") +Signed-off-by: Gregory Price <gourry@gourry.net> +Reviewed-by: Ilias Apalodimas <ilias.apalodimas@linaro.org> +Signed-off-by: Ard Biesheuvel <ardb@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/firmware/efi/tpm.c | 17 +++++++++-------- + 1 file changed, 9 insertions(+), 8 deletions(-) + +diff --git a/drivers/firmware/efi/tpm.c b/drivers/firmware/efi/tpm.c +index e8d69bd548f3f..9c3613e6af158 100644 +--- a/drivers/firmware/efi/tpm.c ++++ b/drivers/firmware/efi/tpm.c +@@ -40,7 +40,8 @@ int __init efi_tpm_eventlog_init(void) + { + struct linux_efi_tpm_eventlog *log_tbl; + struct efi_tcg2_final_events_table *final_tbl; +- int tbl_size; ++ unsigned int tbl_size; ++ int final_tbl_size; + int ret = 0; + + if (efi.tpm_log == EFI_INVALID_TABLE_ADDR) { +@@ -80,26 +81,26 @@ int __init efi_tpm_eventlog_init(void) + goto out; + } + +- tbl_size = 0; ++ final_tbl_size = 0; + if (final_tbl->nr_events != 0) { + void *events = (void *)efi.tpm_final_log + + sizeof(final_tbl->version) + + sizeof(final_tbl->nr_events); + +- tbl_size = tpm2_calc_event_log_size(events, +- final_tbl->nr_events, +- log_tbl->log); ++ final_tbl_size = tpm2_calc_event_log_size(events, ++ final_tbl->nr_events, ++ log_tbl->log); + } + +- if (tbl_size < 0) { ++ if (final_tbl_size < 0) { + pr_err(FW_BUG "Failed to parse event in TPM Final Events Log\n"); + ret = -EINVAL; + goto out_calc; + } + + memblock_reserve(efi.tpm_final_log, +- tbl_size + sizeof(*final_tbl)); +- efi_tpm_final_log_size = tbl_size; ++ final_tbl_size + sizeof(*final_tbl)); ++ efi_tpm_final_log_size = final_tbl_size; + + out_calc: + early_memunmap(final_tbl, sizeof(*final_tbl)); +-- +2.43.0 + diff --git a/queue-6.12/trace-trace_event_perf-remove-duplicate-samples-on-t.patch b/queue-6.12/trace-trace_event_perf-remove-duplicate-samples-on-t.patch new file mode 100644 index 00000000000..bfc36c5050c --- /dev/null +++ b/queue-6.12/trace-trace_event_perf-remove-duplicate-samples-on-t.patch @@ -0,0 +1,83 @@ +From 58ccc58244ca3952c17934c3f5e4905da87ee80d Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Fri, 13 Sep 2024 03:13:47 +0100 +Subject: trace/trace_event_perf: remove duplicate samples on the first + tracepoint event + +From: Levi Yun <yeoreum.yun@arm.com> + +[ Upstream commit afe5960dc208fe069ddaaeb0994d857b24ac19d1 ] + +When a tracepoint event is created with attr.freq = 1, +'hwc->period_left' is not initialized correctly. As a result, +in the perf_swevent_overflow() function, when the first time the event occurs, +it calculates the event overflow and the perf_swevent_set_period() returns 3, +this leads to the event are recorded for three duplicate times. + +Step to reproduce: + 1. Enable the tracepoint event & starting tracing + $ echo 1 > /sys/kernel/tracing/events/module/module_free + $ echo 1 > /sys/kernel/tracing/tracing_on + + 2. Record with perf + $ perf record -a --strict-freq -F 1 -e "module:module_free" + + 3. Trigger module_free event. + $ modprobe -i sunrpc + $ modprobe -r sunrpc + +Result: + - Trace pipe result: + $ cat trace_pipe + modprobe-174509 [003] ..... 6504.868896: module_free: sunrpc + + - perf sample: + modprobe 174509 [003] 6504.868980: module:module_free: sunrpc + modprobe 174509 [003] 6504.868980: module:module_free: sunrpc + modprobe 174509 [003] 6504.868980: module:module_free: sunrpc + +By setting period_left via perf_swevent_set_period() as other sw_event did, +This problem could be solved. + +After patch: + - Trace pipe result: + $ cat trace_pipe + modprobe 1153096 [068] 613468.867774: module:module_free: xfs + + - perf sample + modprobe 1153096 [068] 613468.867794: module:module_free: xfs + +Link: https://lore.kernel.org/20240913021347.595330-1-yeoreum.yun@arm.com +Fixes: bd2b5b12849a ("perf_counter: More aggressive frequency adjustment") +Signed-off-by: Levi Yun <yeoreum.yun@arm.com> +Acked-by: Namhyung Kim <namhyung@kernel.org> +Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + kernel/trace/trace_event_perf.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/kernel/trace/trace_event_perf.c b/kernel/trace/trace_event_perf.c +index 05e7912418126..3ff9caa4a71bb 100644 +--- a/kernel/trace/trace_event_perf.c ++++ b/kernel/trace/trace_event_perf.c +@@ -352,10 +352,16 @@ void perf_uprobe_destroy(struct perf_event *p_event) + int perf_trace_add(struct perf_event *p_event, int flags) + { + struct trace_event_call *tp_event = p_event->tp_event; ++ struct hw_perf_event *hwc = &p_event->hw; + + if (!(flags & PERF_EF_START)) + p_event->hw.state = PERF_HES_STOPPED; + ++ if (is_sampling_event(p_event)) { ++ hwc->last_period = hwc->sample_period; ++ perf_swevent_set_period(p_event); ++ } ++ + /* + * If TRACE_REG_PERF_ADD returns false; no custom action was performed + * and we need to take the default action of enqueueing our event on +-- +2.43.0 + diff --git a/queue-6.12/udmabuf-change-folios-array-from-kmalloc-to-kvmalloc.patch b/queue-6.12/udmabuf-change-folios-array-from-kmalloc-to-kvmalloc.patch new file mode 100644 index 00000000000..c268b3a351f --- /dev/null +++ b/queue-6.12/udmabuf-change-folios-array-from-kmalloc-to-kvmalloc.patch @@ -0,0 +1,147 @@ +From 403550d91ae6e3e1d6f0acbcc2f31b8ab630b4f6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Wed, 18 Sep 2024 10:52:25 +0800 +Subject: udmabuf: change folios array from kmalloc to kvmalloc +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Huan Yang <link@vivo.com> + +[ Upstream commit 1c0844c6184e658064e14c4335885785ad3bf84b ] + +When PAGE_SIZE 4096, MAX_PAGE_ORDER 10, 64bit machine, +page_alloc only support 4MB. +If above this, trigger this warn and return NULL. + +udmabuf can change size limit, if change it to 3072(3GB), and then alloc +3GB udmabuf, will fail create. + +[ 4080.876581] ------------[ cut here ]------------ +[ 4080.876843] WARNING: CPU: 3 PID: 2015 at mm/page_alloc.c:4556 __alloc_pages+0x2c8/0x350 +[ 4080.878839] RIP: 0010:__alloc_pages+0x2c8/0x350 +[ 4080.879470] Call Trace: +[ 4080.879473] <TASK> +[ 4080.879473] ? __alloc_pages+0x2c8/0x350 +[ 4080.879475] ? __warn.cold+0x8e/0xe8 +[ 4080.880647] ? __alloc_pages+0x2c8/0x350 +[ 4080.880909] ? report_bug+0xff/0x140 +[ 4080.881175] ? handle_bug+0x3c/0x80 +[ 4080.881556] ? exc_invalid_op+0x17/0x70 +[ 4080.881559] ? asm_exc_invalid_op+0x1a/0x20 +[ 4080.882077] ? udmabuf_create+0x131/0x400 + +Because MAX_PAGE_ORDER, kmalloc can max alloc 4096 * (1 << 10), 4MB +memory, each array entry is pointer(8byte), so can save 524288 pages(2GB). + +Further more, costly order(order 3) may not be guaranteed that it can be +applied for, due to fragmentation. + +This patch change udmabuf array use kvmalloc_array, this can fallback +alloc into vmalloc, which can guarantee allocation for any size and does +not affect the performance of kmalloc allocations. + +Signed-off-by: Huan Yang <link@vivo.com> +Acked-by: Christian König <christian.koenig@amd.com> +Acked-by: Vivek Kasireddy <vivek.kasireddy@intel.com> +Signed-off-by: Vivek Kasireddy <vivek.kasireddy@intel.com> +Link: https://patchwork.freedesktop.org/patch/msgid/20240918025238.2957823-3-link@vivo.com +Stable-dep-of: 18d7de823b71 ("udmabuf: fix vmap_udmabuf error page set") +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/dma-buf/udmabuf.c | 26 +++++++++++++------------- + 1 file changed, 13 insertions(+), 13 deletions(-) + +diff --git a/drivers/dma-buf/udmabuf.c b/drivers/dma-buf/udmabuf.c +index 047c3cd2cefff..bc94c194e172d 100644 +--- a/drivers/dma-buf/udmabuf.c ++++ b/drivers/dma-buf/udmabuf.c +@@ -80,7 +80,7 @@ static int vmap_udmabuf(struct dma_buf *buf, struct iosys_map *map) + + dma_resv_assert_held(buf->resv); + +- pages = kmalloc_array(ubuf->pagecount, sizeof(*pages), GFP_KERNEL); ++ pages = kvmalloc_array(ubuf->pagecount, sizeof(*pages), GFP_KERNEL); + if (!pages) + return -ENOMEM; + +@@ -88,7 +88,7 @@ static int vmap_udmabuf(struct dma_buf *buf, struct iosys_map *map) + pages[pg] = &ubuf->folios[pg]->page; + + vaddr = vm_map_ram(pages, ubuf->pagecount, -1); +- kfree(pages); ++ kvfree(pages); + if (!vaddr) + return -EINVAL; + +@@ -196,8 +196,8 @@ static void release_udmabuf(struct dma_buf *buf) + put_sg_table(dev, ubuf->sg, DMA_BIDIRECTIONAL); + + unpin_all_folios(&ubuf->unpin_list); +- kfree(ubuf->offsets); +- kfree(ubuf->folios); ++ kvfree(ubuf->offsets); ++ kvfree(ubuf->folios); + kfree(ubuf); + } + +@@ -322,14 +322,14 @@ static long udmabuf_create(struct miscdevice *device, + if (!ubuf->pagecount) + goto err; + +- ubuf->folios = kmalloc_array(ubuf->pagecount, sizeof(*ubuf->folios), +- GFP_KERNEL); ++ ubuf->folios = kvmalloc_array(ubuf->pagecount, sizeof(*ubuf->folios), ++ GFP_KERNEL); + if (!ubuf->folios) { + ret = -ENOMEM; + goto err; + } +- ubuf->offsets = kcalloc(ubuf->pagecount, sizeof(*ubuf->offsets), +- GFP_KERNEL); ++ ubuf->offsets = kvcalloc(ubuf->pagecount, sizeof(*ubuf->offsets), ++ GFP_KERNEL); + if (!ubuf->offsets) { + ret = -ENOMEM; + goto err; +@@ -343,7 +343,7 @@ static long udmabuf_create(struct miscdevice *device, + goto err; + + pgcnt = list[i].size >> PAGE_SHIFT; +- folios = kmalloc_array(pgcnt, sizeof(*folios), GFP_KERNEL); ++ folios = kvmalloc_array(pgcnt, sizeof(*folios), GFP_KERNEL); + if (!folios) { + ret = -ENOMEM; + goto err; +@@ -353,7 +353,7 @@ static long udmabuf_create(struct miscdevice *device, + ret = memfd_pin_folios(memfd, list[i].offset, end, + folios, pgcnt, &pgoff); + if (ret <= 0) { +- kfree(folios); ++ kvfree(folios); + if (!ret) + ret = -EINVAL; + goto err; +@@ -382,7 +382,7 @@ static long udmabuf_create(struct miscdevice *device, + } + } + +- kfree(folios); ++ kvfree(folios); + fput(memfd); + memfd = NULL; + } +@@ -398,8 +398,8 @@ static long udmabuf_create(struct miscdevice *device, + if (memfd) + fput(memfd); + unpin_all_folios(&ubuf->unpin_list); +- kfree(ubuf->offsets); +- kfree(ubuf->folios); ++ kvfree(ubuf->offsets); ++ kvfree(ubuf->folios); + kfree(ubuf); + return ret; + } +-- +2.43.0 + diff --git a/queue-6.12/udmabuf-fix-vmap_udmabuf-error-page-set.patch b/queue-6.12/udmabuf-fix-vmap_udmabuf-error-page-set.patch new file mode 100644 index 00000000000..2d1ef6c00e0 --- /dev/null +++ b/queue-6.12/udmabuf-fix-vmap_udmabuf-error-page-set.patch @@ -0,0 +1,87 @@ +From b02526641608b0bcd0e4abf34ede2af3aa7d7dc7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Wed, 18 Sep 2024 10:52:26 +0800 +Subject: udmabuf: fix vmap_udmabuf error page set + +From: Huan Yang <link@vivo.com> + +[ Upstream commit 18d7de823b7150344d242c3677e65d68c5271b04 ] + +Currently vmap_udmabuf set page's array by each folio. +But, ubuf->folios is only contain's the folio's head page. + +That mean we repeatedly mapped the folio head page to the vmalloc area. + +Due to udmabuf can use hugetlb, if HVO enabled, tail page may not exist, +so, we can't use page array to map, instead, use pfn array. + +By this, we removed page usage in udmabuf totally. + +Fixes: 5e72b2b41a21 ("udmabuf: convert udmabuf driver to use folios") +Suggested-by: Vivek Kasireddy <vivek.kasireddy@intel.com> +Signed-off-by: Huan Yang <link@vivo.com> +Acked-by: Vivek Kasireddy <vivek.kasireddy@intel.com> +Signed-off-by: Vivek Kasireddy <vivek.kasireddy@intel.com> +Link: https://patchwork.freedesktop.org/patch/msgid/20240918025238.2957823-4-link@vivo.com +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/dma-buf/Kconfig | 1 + + drivers/dma-buf/udmabuf.c | 22 +++++++++++++++------- + 2 files changed, 16 insertions(+), 7 deletions(-) + +diff --git a/drivers/dma-buf/Kconfig b/drivers/dma-buf/Kconfig +index b46eb8a552d7b..fee04fdb08220 100644 +--- a/drivers/dma-buf/Kconfig ++++ b/drivers/dma-buf/Kconfig +@@ -36,6 +36,7 @@ config UDMABUF + depends on DMA_SHARED_BUFFER + depends on MEMFD_CREATE || COMPILE_TEST + depends on MMU ++ select VMAP_PFN + help + A driver to let userspace turn memfd regions into dma-bufs. + Qemu can use this to create host dmabufs for guest framebuffers. +diff --git a/drivers/dma-buf/udmabuf.c b/drivers/dma-buf/udmabuf.c +index bc94c194e172d..a3638ccc15f57 100644 +--- a/drivers/dma-buf/udmabuf.c ++++ b/drivers/dma-buf/udmabuf.c +@@ -74,21 +74,29 @@ static int mmap_udmabuf(struct dma_buf *buf, struct vm_area_struct *vma) + static int vmap_udmabuf(struct dma_buf *buf, struct iosys_map *map) + { + struct udmabuf *ubuf = buf->priv; +- struct page **pages; ++ unsigned long *pfns; + void *vaddr; + pgoff_t pg; + + dma_resv_assert_held(buf->resv); + +- pages = kvmalloc_array(ubuf->pagecount, sizeof(*pages), GFP_KERNEL); +- if (!pages) ++ /** ++ * HVO may free tail pages, so just use pfn to map each folio ++ * into vmalloc area. ++ */ ++ pfns = kvmalloc_array(ubuf->pagecount, sizeof(*pfns), GFP_KERNEL); ++ if (!pfns) + return -ENOMEM; + +- for (pg = 0; pg < ubuf->pagecount; pg++) +- pages[pg] = &ubuf->folios[pg]->page; ++ for (pg = 0; pg < ubuf->pagecount; pg++) { ++ unsigned long pfn = folio_pfn(ubuf->folios[pg]); + +- vaddr = vm_map_ram(pages, ubuf->pagecount, -1); +- kvfree(pages); ++ pfn += ubuf->offsets[pg] >> PAGE_SHIFT; ++ pfns[pg] = pfn; ++ } ++ ++ vaddr = vmap_pfn(pfns, ubuf->pagecount, PAGE_KERNEL); ++ kvfree(pfns); + if (!vaddr) + return -EINVAL; + +-- +2.43.0 + diff --git a/queue-6.12/unicode-fix-utf8_load-error-path.patch b/queue-6.12/unicode-fix-utf8_load-error-path.patch new file mode 100644 index 00000000000..545c3ffb9b8 --- /dev/null +++ b/queue-6.12/unicode-fix-utf8_load-error-path.patch @@ -0,0 +1,64 @@ +From 16637652af5fef591bff16961a47a1ca2d76354a Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Mon, 2 Sep 2024 19:55:03 -0300 +Subject: unicode: Fix utf8_load() error path +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: André Almeida <andrealmeid@igalia.com> + +[ Upstream commit 156bb2c569cd869583c593d27a5bd69e7b2a4264 ] + +utf8_load() requests the symbol "utf8_data_table" and then checks if the +requested UTF-8 version is supported. If it's unsupported, it tries to +put the data table using symbol_put(). If an unsupported version is +requested, symbol_put() fails like this: + + kernel BUG at kernel/module/main.c:786! + RIP: 0010:__symbol_put+0x93/0xb0 + Call Trace: + <TASK> + ? __die_body.cold+0x19/0x27 + ? die+0x2e/0x50 + ? do_trap+0xca/0x110 + ? do_error_trap+0x65/0x80 + ? __symbol_put+0x93/0xb0 + ? exc_invalid_op+0x51/0x70 + ? __symbol_put+0x93/0xb0 + ? asm_exc_invalid_op+0x1a/0x20 + ? __pfx_cmp_name+0x10/0x10 + ? __symbol_put+0x93/0xb0 + ? __symbol_put+0x62/0xb0 + utf8_load+0xf8/0x150 + +That happens because symbol_put() expects the unique string that +identify the symbol, instead of a pointer to the loaded symbol. Fix that +by using such string. + +Fixes: 2b3d04787012 ("unicode: Add utf8-data module") +Signed-off-by: André Almeida <andrealmeid@igalia.com> +Reviewed-by: Theodore Ts'o <tytso@mit.edu> +Link: https://lore.kernel.org/r/20240902225511.757831-2-andrealmeid@igalia.com +Signed-off-by: Gabriel Krisman Bertazi <krisman@suse.de> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + fs/unicode/utf8-core.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/fs/unicode/utf8-core.c b/fs/unicode/utf8-core.c +index 8395066341a43..0400824ef4936 100644 +--- a/fs/unicode/utf8-core.c ++++ b/fs/unicode/utf8-core.c +@@ -198,7 +198,7 @@ struct unicode_map *utf8_load(unsigned int version) + return um; + + out_symbol_put: +- symbol_put(um->tables); ++ symbol_put(utf8_data_table); + out_free_um: + kfree(um); + return ERR_PTR(-EINVAL); +-- +2.43.0 + diff --git a/queue-6.12/usb-chaoskey-fail-open-after-removal.patch b/queue-6.12/usb-chaoskey-fail-open-after-removal.patch new file mode 100644 index 00000000000..f72b8c9f771 --- /dev/null +++ b/queue-6.12/usb-chaoskey-fail-open-after-removal.patch @@ -0,0 +1,146 @@ +From 7d2c1cb4588ba5147d2d4af62f70f2b105fef8ed Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Wed, 2 Oct 2024 15:21:41 +0200 +Subject: USB: chaoskey: fail open after removal + +From: Oliver Neukum <oneukum@suse.com> + +[ Upstream commit 422dc0a4d12d0b80dd3aab3fe5943f665ba8f041 ] + +chaoskey_open() takes the lock only to increase the +counter of openings. That means that the mutual exclusion +with chaoskey_disconnect() cannot prevent an increase +of the counter and chaoskey_open() returning a success. + +If that race is hit, chaoskey_disconnect() will happily +free all resources associated with the device after +it has dropped the lock, as it has read the counter +as zero. + +To prevent this race chaoskey_open() has to check +the presence of the device under the lock. +However, the current per device lock cannot be used, +because it is a part of the data structure to be +freed. Hence an additional global mutex is needed. +The issue is as old as the driver. + +Signed-off-by: Oliver Neukum <oneukum@suse.com> +Reported-by: syzbot+422188bce66e76020e55@syzkaller.appspotmail.com +Closes: https://syzkaller.appspot.com/bug?extid=422188bce66e76020e55 +Fixes: 66e3e591891da ("usb: Add driver for Altus Metrum ChaosKey device (v2)") +Rule: add +Link: https://lore.kernel.org/stable/20241002132201.552578-1-oneukum%40suse.com +Link: https://lore.kernel.org/r/20241002132201.552578-1-oneukum@suse.com +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/usb/misc/chaoskey.c | 35 ++++++++++++++++++++++++----------- + 1 file changed, 24 insertions(+), 11 deletions(-) + +diff --git a/drivers/usb/misc/chaoskey.c b/drivers/usb/misc/chaoskey.c +index 6fb5140e29b9d..e8b63df5f9759 100644 +--- a/drivers/usb/misc/chaoskey.c ++++ b/drivers/usb/misc/chaoskey.c +@@ -27,6 +27,8 @@ static struct usb_class_driver chaoskey_class; + static int chaoskey_rng_read(struct hwrng *rng, void *data, + size_t max, bool wait); + ++static DEFINE_MUTEX(chaoskey_list_lock); ++ + #define usb_dbg(usb_if, format, arg...) \ + dev_dbg(&(usb_if)->dev, format, ## arg) + +@@ -230,6 +232,7 @@ static void chaoskey_disconnect(struct usb_interface *interface) + if (dev->hwrng_registered) + hwrng_unregister(&dev->hwrng); + ++ mutex_lock(&chaoskey_list_lock); + usb_deregister_dev(interface, &chaoskey_class); + + usb_set_intfdata(interface, NULL); +@@ -244,6 +247,7 @@ static void chaoskey_disconnect(struct usb_interface *interface) + } else + mutex_unlock(&dev->lock); + ++ mutex_unlock(&chaoskey_list_lock); + usb_dbg(interface, "disconnect done"); + } + +@@ -251,6 +255,7 @@ static int chaoskey_open(struct inode *inode, struct file *file) + { + struct chaoskey *dev; + struct usb_interface *interface; ++ int rv = 0; + + /* get the interface from minor number and driver information */ + interface = usb_find_interface(&chaoskey_driver, iminor(inode)); +@@ -266,18 +271,23 @@ static int chaoskey_open(struct inode *inode, struct file *file) + } + + file->private_data = dev; ++ mutex_lock(&chaoskey_list_lock); + mutex_lock(&dev->lock); +- ++dev->open; ++ if (dev->present) ++ ++dev->open; ++ else ++ rv = -ENODEV; + mutex_unlock(&dev->lock); ++ mutex_unlock(&chaoskey_list_lock); + +- usb_dbg(interface, "open success"); +- return 0; ++ return rv; + } + + static int chaoskey_release(struct inode *inode, struct file *file) + { + struct chaoskey *dev = file->private_data; + struct usb_interface *interface; ++ int rv = 0; + + if (dev == NULL) + return -ENODEV; +@@ -286,14 +296,15 @@ static int chaoskey_release(struct inode *inode, struct file *file) + + usb_dbg(interface, "release"); + ++ mutex_lock(&chaoskey_list_lock); + mutex_lock(&dev->lock); + + usb_dbg(interface, "open count at release is %d", dev->open); + + if (dev->open <= 0) { + usb_dbg(interface, "invalid open count (%d)", dev->open); +- mutex_unlock(&dev->lock); +- return -ENODEV; ++ rv = -ENODEV; ++ goto bail; + } + + --dev->open; +@@ -302,13 +313,15 @@ static int chaoskey_release(struct inode *inode, struct file *file) + if (dev->open == 0) { + mutex_unlock(&dev->lock); + chaoskey_free(dev); +- } else +- mutex_unlock(&dev->lock); +- } else +- mutex_unlock(&dev->lock); +- ++ goto destruction; ++ } ++ } ++bail: ++ mutex_unlock(&dev->lock); ++destruction: ++ mutex_lock(&chaoskey_list_lock); + usb_dbg(interface, "release success"); +- return 0; ++ return rv; + } + + static void chaos_read_callback(struct urb *urb) +-- +2.43.0 + diff --git a/queue-6.12/usb-chaoskey-fix-possible-deadlock-chaoskey_list_loc.patch b/queue-6.12/usb-chaoskey-fix-possible-deadlock-chaoskey_list_loc.patch new file mode 100644 index 00000000000..4a54f64df6f --- /dev/null +++ b/queue-6.12/usb-chaoskey-fix-possible-deadlock-chaoskey_list_loc.patch @@ -0,0 +1,154 @@ +From 94ce3652eaa34ce91925ea4a2d02ee88ad5ec8a9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Wed, 9 Oct 2024 22:52:07 +0800 +Subject: USB: chaoskey: Fix possible deadlock chaoskey_list_lock + +From: Edward Adam Davis <eadavis@qq.com> + +[ Upstream commit d73dc7b182be4238b75278bfae16afb4c5564a58 ] + +[Syzbot reported two possible deadlocks] +The first possible deadlock is: +WARNING: possible recursive locking detected +6.12.0-rc1-syzkaller-00027-g4a9fe2a8ac53 #0 Not tainted +-------------------------------------------- +syz-executor363/2651 is trying to acquire lock: +ffffffff89b120e8 (chaoskey_list_lock){+.+.}-{3:3}, at: chaoskey_release+0x15d/0x2c0 drivers/usb/misc/chaoskey.c:322 + +but task is already holding lock: +ffffffff89b120e8 (chaoskey_list_lock){+.+.}-{3:3}, at: chaoskey_release+0x7f/0x2c0 drivers/usb/misc/chaoskey.c:299 + +other info that might help us debug this: + Possible unsafe locking scenario: + + CPU0 + ---- + lock(chaoskey_list_lock); + lock(chaoskey_list_lock); + + *** DEADLOCK *** + +The second possible deadlock is: +WARNING: possible circular locking dependency detected +6.12.0-rc1-syzkaller-00027-g4a9fe2a8ac53 #0 Not tainted +------------------------------------------------------ +kworker/0:2/804 is trying to acquire lock: +ffffffff899dadb0 (minor_rwsem){++++}-{3:3}, at: usb_deregister_dev+0x7c/0x1e0 drivers/usb/core/file.c:186 + +but task is already holding lock: +ffffffff89b120e8 (chaoskey_list_lock){+.+.}-{3:3}, at: chaoskey_disconnect+0xa8/0x2a0 drivers/usb/misc/chaoskey.c:235 + +which lock already depends on the new lock. + +the existing dependency chain (in reverse order) is: + +-> #1 (chaoskey_list_lock){+.+.}-{3:3}: + __mutex_lock_common kernel/locking/mutex.c:608 [inline] + __mutex_lock+0x175/0x9c0 kernel/locking/mutex.c:752 + chaoskey_open+0xdd/0x220 drivers/usb/misc/chaoskey.c:274 + usb_open+0x186/0x220 drivers/usb/core/file.c:47 + chrdev_open+0x237/0x6a0 fs/char_dev.c:414 + do_dentry_open+0x6cb/0x1390 fs/open.c:958 + vfs_open+0x82/0x3f0 fs/open.c:1088 + do_open fs/namei.c:3774 [inline] + path_openat+0x1e6a/0x2d60 fs/namei.c:3933 + do_filp_open+0x1dc/0x430 fs/namei.c:3960 + do_sys_openat2+0x17a/0x1e0 fs/open.c:1415 + do_sys_open fs/open.c:1430 [inline] + __do_sys_openat fs/open.c:1446 [inline] + __se_sys_openat fs/open.c:1441 [inline] + __x64_sys_openat+0x175/0x210 fs/open.c:1441 + do_syscall_x64 arch/x86/entry/common.c:52 [inline] + do_syscall_64+0xcd/0x250 arch/x86/entry/common.c:83 + entry_SYSCALL_64_after_hwframe+0x77/0x7f + +-> #0 (minor_rwsem){++++}-{3:3}: + check_prev_add kernel/locking/lockdep.c:3161 [inline] + check_prevs_add kernel/locking/lockdep.c:3280 [inline] + validate_chain kernel/locking/lockdep.c:3904 [inline] + __lock_acquire+0x250b/0x3ce0 kernel/locking/lockdep.c:5202 + lock_acquire.part.0+0x11b/0x380 kernel/locking/lockdep.c:5825 + down_write+0x93/0x200 kernel/locking/rwsem.c:1577 + usb_deregister_dev+0x7c/0x1e0 drivers/usb/core/file.c:186 + chaoskey_disconnect+0xb7/0x2a0 drivers/usb/misc/chaoskey.c:236 + usb_unbind_interface+0x1e8/0x970 drivers/usb/core/driver.c:461 + device_remove drivers/base/dd.c:569 [inline] + device_remove+0x122/0x170 drivers/base/dd.c:561 + __device_release_driver drivers/base/dd.c:1273 [inline] + device_release_driver_internal+0x44a/0x610 drivers/base/dd.c:1296 + bus_remove_device+0x22f/0x420 drivers/base/bus.c:576 + device_del+0x396/0x9f0 drivers/base/core.c:3864 + usb_disable_device+0x36c/0x7f0 drivers/usb/core/message.c:1418 + usb_disconnect+0x2e1/0x920 drivers/usb/core/hub.c:2304 + hub_port_connect drivers/usb/core/hub.c:5361 [inline] + hub_port_connect_change drivers/usb/core/hub.c:5661 [inline] + port_event drivers/usb/core/hub.c:5821 [inline] + hub_event+0x1bed/0x4f40 drivers/usb/core/hub.c:5903 + process_one_work+0x9c5/0x1ba0 kernel/workqueue.c:3229 + process_scheduled_works kernel/workqueue.c:3310 [inline] + worker_thread+0x6c8/0xf00 kernel/workqueue.c:3391 + kthread+0x2c1/0x3a0 kernel/kthread.c:389 + ret_from_fork+0x45/0x80 arch/x86/kernel/process.c:147 + ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:244 + +other info that might help us debug this: + + Possible unsafe locking scenario: + + CPU0 CPU1 + ---- ---- + lock(chaoskey_list_lock); + lock(minor_rwsem); + lock(chaoskey_list_lock); + lock(minor_rwsem); + + *** DEADLOCK *** +[Analysis] +The first is AA lock, it because wrong logic, it need a unlock. +The second is AB lock, it needs to rearrange the order of lock usage. + +Fixes: 422dc0a4d12d ("USB: chaoskey: fail open after removal") +Reported-by: syzbot+685e14d04fe35692d3bc@syzkaller.appspotmail.com +Reported-by: syzbot+1f8ca5ee82576ec01f12@syzkaller.appspotmail.com +Closes: https://syzkaller.appspot.com/bug?extid=685e14d04fe35692d3bc +Signed-off-by: Edward Adam Davis <eadavis@qq.com> +Tested-by: syzbot+685e14d04fe35692d3bc@syzkaller.appspotmail.com +Reported-by: syzbot+5f1ce62e956b7b19610e@syzkaller.appspotmail.com +Tested-by: syzbot+5f1ce62e956b7b19610e@syzkaller.appspotmail.com +Tested-by: syzbot+1f8ca5ee82576ec01f12@syzkaller.appspotmail.com +Link: https://lore.kernel.org/r/tencent_84EB865C89862EC22EE94CB3A7C706C59206@qq.com +Cc: Oliver Neukum <oneukum@suse.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/usb/misc/chaoskey.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/usb/misc/chaoskey.c b/drivers/usb/misc/chaoskey.c +index e8b63df5f9759..225863321dc47 100644 +--- a/drivers/usb/misc/chaoskey.c ++++ b/drivers/usb/misc/chaoskey.c +@@ -232,10 +232,10 @@ static void chaoskey_disconnect(struct usb_interface *interface) + if (dev->hwrng_registered) + hwrng_unregister(&dev->hwrng); + +- mutex_lock(&chaoskey_list_lock); + usb_deregister_dev(interface, &chaoskey_class); + + usb_set_intfdata(interface, NULL); ++ mutex_lock(&chaoskey_list_lock); + mutex_lock(&dev->lock); + + dev->present = false; +@@ -319,7 +319,7 @@ static int chaoskey_release(struct inode *inode, struct file *file) + bail: + mutex_unlock(&dev->lock); + destruction: +- mutex_lock(&chaoskey_list_lock); ++ mutex_unlock(&chaoskey_list_lock); + usb_dbg(interface, "release success"); + return rv; + } +-- +2.43.0 + diff --git a/queue-6.12/usb-gadget-uvc-wake-pump-everytime-we-update-the-fre.patch b/queue-6.12/usb-gadget-uvc-wake-pump-everytime-we-update-the-fre.patch new file mode 100644 index 00000000000..e12fc6b5b1f --- /dev/null +++ b/queue-6.12/usb-gadget-uvc-wake-pump-everytime-we-update-the-fre.patch @@ -0,0 +1,42 @@ +From f841578d87ae17908aac603f7eccb3d5ef873b2e Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Wed, 16 Oct 2024 15:58:06 +0200 +Subject: usb: gadget: uvc: wake pump everytime we update the free list + +From: Michael Grzeschik <m.grzeschik@pengutronix.de> + +[ Upstream commit adc292d54de9db2e6b8ecb7f81f278bbbaf713e9 ] + +Since the req_free list will updated if enqueuing one request was not +possible it will be added back to the free list. With every available +free request in the queue it is a valid case for the pump worker to use +it and continue the pending bufferdata into requests for the req_ready +list. + +Fixes: 6acba0345b68 ("usb:gadget:uvc Do not use worker thread to pump isoc usb requests") +Signed-off-by: Michael Grzeschik <m.grzeschik@pengutronix.de> +Link: https://lore.kernel.org/r/20240403-uvc_request_length_by_interval-v7-1-e224bb1035f0@pengutronix.de +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/usb/gadget/function/uvc_video.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/drivers/usb/gadget/function/uvc_video.c b/drivers/usb/gadget/function/uvc_video.c +index 57a851151225d..002bf724d8025 100644 +--- a/drivers/usb/gadget/function/uvc_video.c ++++ b/drivers/usb/gadget/function/uvc_video.c +@@ -480,6 +480,10 @@ uvc_video_complete(struct usb_ep *ep, struct usb_request *req) + * up later. + */ + list_add_tail(&to_queue->list, &video->req_free); ++ /* ++ * There is a new free request - wake up the pump. ++ */ ++ queue_work(video->async_wq, &video->pump); + } + + spin_unlock_irqrestore(&video->req_lock, flags); +-- +2.43.0 + diff --git a/queue-6.12/usb-typec-fix-potential-array-underflow-in-ucsi_ccg_.patch b/queue-6.12/usb-typec-fix-potential-array-underflow-in-ucsi_ccg_.patch new file mode 100644 index 00000000000..248b5a0b530 --- /dev/null +++ b/queue-6.12/usb-typec-fix-potential-array-underflow-in-ucsi_ccg_.patch @@ -0,0 +1,49 @@ +From 47602c5dbef05a8b30176abbed85675c4a22d961 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Mon, 11 Nov 2024 14:08:06 +0300 +Subject: usb: typec: fix potential array underflow in ucsi_ccg_sync_control() + +From: Dan Carpenter <dan.carpenter@linaro.org> + +[ Upstream commit e56aac6e5a25630645607b6856d4b2a17b2311a5 ] + +The "command" variable can be controlled by the user via debugfs. The +worry is that if con_index is zero then "&uc->ucsi->connector[con_index +- 1]" would be an array underflow. + +Fixes: 170a6726d0e2 ("usb: typec: ucsi: add support for separate DP altmode devices") +Signed-off-by: Dan Carpenter <dan.carpenter@linaro.org> +Reviewed-by: Heikki Krogerus <heikki.krogerus@linux.intel.com> +Link: https://lore.kernel.org/r/c69ef0b3-61b0-4dde-98dd-97b97f81d912@stanley.mountain +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/usb/typec/ucsi/ucsi_ccg.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/drivers/usb/typec/ucsi/ucsi_ccg.c b/drivers/usb/typec/ucsi/ucsi_ccg.c +index bccfc03b5986d..fcb8e61136cfd 100644 +--- a/drivers/usb/typec/ucsi/ucsi_ccg.c ++++ b/drivers/usb/typec/ucsi/ucsi_ccg.c +@@ -644,6 +644,10 @@ static int ucsi_ccg_sync_control(struct ucsi *ucsi, u64 command) + uc->has_multiple_dp) { + con_index = (uc->last_cmd_sent >> 16) & + UCSI_CMD_CONNECTOR_MASK; ++ if (con_index == 0) { ++ ret = -EINVAL; ++ goto unlock; ++ } + con = &uc->ucsi->connector[con_index - 1]; + ucsi_ccg_update_set_new_cam_cmd(uc, con, &command); + } +@@ -651,6 +655,7 @@ static int ucsi_ccg_sync_control(struct ucsi *ucsi, u64 command) + ret = ucsi_sync_control_common(ucsi, command); + + pm_runtime_put_sync(uc->dev); ++unlock: + mutex_unlock(&uc->lock); + + return ret; +-- +2.43.0 + diff --git a/queue-6.12/usb-using-mutex-lock-and-supporting-o_nonblock-flag-.patch b/queue-6.12/usb-using-mutex-lock-and-supporting-o_nonblock-flag-.patch new file mode 100644 index 00000000000..c2cb81c84cc --- /dev/null +++ b/queue-6.12/usb-using-mutex-lock-and-supporting-o_nonblock-flag-.patch @@ -0,0 +1,130 @@ +From 99480d70b51a6a4002642c6c86d4ebbc6471ed71 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Thu, 19 Sep 2024 19:34:03 +0900 +Subject: usb: using mutex lock and supporting O_NONBLOCK flag in + iowarrior_read() + +From: Jeongjun Park <aha310510@gmail.com> + +[ Upstream commit 44feafbaa66ec86232b123bb8437a6a262442025 ] + +iowarrior_read() uses the iowarrior dev structure, but does not use any +lock on the structure. This can cause various bugs including data-races, +so it is more appropriate to use a mutex lock to safely protect the +iowarrior dev structure. When using a mutex lock, you should split the +branch to prevent blocking when the O_NONBLOCK flag is set. + +In addition, it is unnecessary to check for NULL on the iowarrior dev +structure obtained by reading file->private_data. Therefore, it is +better to remove the check. + +Fixes: 946b960d13c1 ("USB: add driver for iowarrior devices.") +Signed-off-by: Jeongjun Park <aha310510@gmail.com> +Link: https://lore.kernel.org/r/20240919103403.3986-1-aha310510@gmail.com +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/usb/misc/iowarrior.c | 46 ++++++++++++++++++++++++++++-------- + 1 file changed, 36 insertions(+), 10 deletions(-) + +diff --git a/drivers/usb/misc/iowarrior.c b/drivers/usb/misc/iowarrior.c +index 6d28467ce3522..a513766b4985d 100644 +--- a/drivers/usb/misc/iowarrior.c ++++ b/drivers/usb/misc/iowarrior.c +@@ -277,28 +277,45 @@ static ssize_t iowarrior_read(struct file *file, char __user *buffer, + struct iowarrior *dev; + int read_idx; + int offset; ++ int retval; + + dev = file->private_data; + ++ if (file->f_flags & O_NONBLOCK) { ++ retval = mutex_trylock(&dev->mutex); ++ if (!retval) ++ return -EAGAIN; ++ } else { ++ retval = mutex_lock_interruptible(&dev->mutex); ++ if (retval) ++ return -ERESTARTSYS; ++ } ++ + /* verify that the device wasn't unplugged */ +- if (!dev || !dev->present) +- return -ENODEV; ++ if (!dev->present) { ++ retval = -ENODEV; ++ goto exit; ++ } + + dev_dbg(&dev->interface->dev, "minor %d, count = %zd\n", + dev->minor, count); + + /* read count must be packet size (+ time stamp) */ + if ((count != dev->report_size) +- && (count != (dev->report_size + 1))) +- return -EINVAL; ++ && (count != (dev->report_size + 1))) { ++ retval = -EINVAL; ++ goto exit; ++ } + + /* repeat until no buffer overrun in callback handler occur */ + do { + atomic_set(&dev->overflow_flag, 0); + if ((read_idx = read_index(dev)) == -1) { + /* queue empty */ +- if (file->f_flags & O_NONBLOCK) +- return -EAGAIN; ++ if (file->f_flags & O_NONBLOCK) { ++ retval = -EAGAIN; ++ goto exit; ++ } + else { + //next line will return when there is either new data, or the device is unplugged + int r = wait_event_interruptible(dev->read_wait, +@@ -309,28 +326,37 @@ static ssize_t iowarrior_read(struct file *file, char __user *buffer, + -1)); + if (r) { + //we were interrupted by a signal +- return -ERESTART; ++ retval = -ERESTART; ++ goto exit; + } + if (!dev->present) { + //The device was unplugged +- return -ENODEV; ++ retval = -ENODEV; ++ goto exit; + } + if (read_idx == -1) { + // Can this happen ??? +- return 0; ++ retval = 0; ++ goto exit; + } + } + } + + offset = read_idx * (dev->report_size + 1); + if (copy_to_user(buffer, dev->read_queue + offset, count)) { +- return -EFAULT; ++ retval = -EFAULT; ++ goto exit; + } + } while (atomic_read(&dev->overflow_flag)); + + read_idx = ++read_idx == MAX_INTERRUPT_BUFFER ? 0 : read_idx; + atomic_set(&dev->read_idx, read_idx); ++ mutex_unlock(&dev->mutex); + return count; ++ ++exit: ++ mutex_unlock(&dev->mutex); ++ return retval; + } + + /* +-- +2.43.0 + diff --git a/queue-6.12/usb-yurex-make-waiting-on-yurex_write-interruptible.patch b/queue-6.12/usb-yurex-make-waiting-on-yurex_write-interruptible.patch new file mode 100644 index 00000000000..9891888703a --- /dev/null +++ b/queue-6.12/usb-yurex-make-waiting-on-yurex_write-interruptible.patch @@ -0,0 +1,68 @@ +From 8a1ab2e8fc8617a8b0a5d847310e076005fa748b Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Tue, 24 Sep 2024 10:43:45 +0200 +Subject: usb: yurex: make waiting on yurex_write interruptible + +From: Oliver Neukum <oneukum@suse.com> + +[ Upstream commit e0aa9614ab0fd35b404e4b16ebe879f9fc152591 ] + +The IO yurex_write() needs to wait for in order to have a device +ready for writing again can take a long time time. +Consequently the sleep is done in an interruptible state. +Therefore others waiting for yurex_write() itself to finish should +use mutex_lock_interruptible. + +Signed-off-by: Oliver Neukum <oneukum@suse.com> +Fixes: 6bc235a2e24a5 ("USB: add driver for Meywa-Denki & Kayac YUREX") +Rule: add +Link: https://lore.kernel.org/stable/20240924084415.300557-1-oneukum%40suse.com +Link: https://lore.kernel.org/r/20240924084415.300557-1-oneukum@suse.com +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/usb/misc/iowarrior.c | 4 ---- + drivers/usb/misc/yurex.c | 5 ++++- + 2 files changed, 4 insertions(+), 5 deletions(-) + +diff --git a/drivers/usb/misc/iowarrior.c b/drivers/usb/misc/iowarrior.c +index a513766b4985d..365c100693458 100644 +--- a/drivers/usb/misc/iowarrior.c ++++ b/drivers/usb/misc/iowarrior.c +@@ -911,7 +911,6 @@ static int iowarrior_probe(struct usb_interface *interface, + static void iowarrior_disconnect(struct usb_interface *interface) + { + struct iowarrior *dev = usb_get_intfdata(interface); +- int minor = dev->minor; + + usb_deregister_dev(interface, &iowarrior_class); + +@@ -935,9 +934,6 @@ static void iowarrior_disconnect(struct usb_interface *interface) + mutex_unlock(&dev->mutex); + iowarrior_delete(dev); + } +- +- dev_info(&interface->dev, "I/O-Warror #%d now disconnected\n", +- minor - IOWARRIOR_MINOR_BASE); + } + + /* usb specific object needed to register this driver with the usb subsystem */ +diff --git a/drivers/usb/misc/yurex.c b/drivers/usb/misc/yurex.c +index 6aebc736a80c6..70dff0db5354f 100644 +--- a/drivers/usb/misc/yurex.c ++++ b/drivers/usb/misc/yurex.c +@@ -441,7 +441,10 @@ static ssize_t yurex_write(struct file *file, const char __user *user_buffer, + if (count == 0) + goto error; + +- mutex_lock(&dev->io_mutex); ++ retval = mutex_lock_interruptible(&dev->io_mutex); ++ if (retval < 0) ++ return -EINTR; ++ + if (dev->disconnected) { /* already disconnected */ + mutex_unlock(&dev->io_mutex); + retval = -ENODEV; +-- +2.43.0 + diff --git a/queue-6.12/vdpa-mlx5-fix-suboptimal-range-on-iotlb-iteration.patch b/queue-6.12/vdpa-mlx5-fix-suboptimal-range-on-iotlb-iteration.patch new file mode 100644 index 00000000000..9c6d2011b28 --- /dev/null +++ b/queue-6.12/vdpa-mlx5-fix-suboptimal-range-on-iotlb-iteration.patch @@ -0,0 +1,53 @@ +From d5b6d731738935067fdaeb7afc1cd45fe0e3454c Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Mon, 21 Oct 2024 16:40:40 +0300 +Subject: vdpa/mlx5: Fix suboptimal range on iotlb iteration + +From: Si-Wei Liu <si-wei.liu@oracle.com> + +[ Upstream commit 35025963326e44d8bced3eecd42d2f040f4f0024 ] + +The starting iova address to iterate iotlb map entry within a range +was set to an irrelevant value when passing to the itree_next() +iterator, although luckily it doesn't affect the outcome of finding +out the granule of the smallest iotlb map size. Fix the code to make +it consistent with the following for-loop. + +Fixes: 94abbccdf291 ("vdpa/mlx5: Add shared memory registration code") +Signed-off-by: Si-Wei Liu <si-wei.liu@oracle.com> +Signed-off-by: Dragos Tatulea <dtatulea@nvidia.com> +Message-Id: <20241021134040.975221-3-dtatulea@nvidia.com> +Signed-off-by: Michael S. Tsirkin <mst@redhat.com> +Acked-by: Jason Wang <jasowang@redhat.com> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/vdpa/mlx5/core/mr.c | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +diff --git a/drivers/vdpa/mlx5/core/mr.c b/drivers/vdpa/mlx5/core/mr.c +index 7d0c83b5b0715..8455f08f5d406 100644 +--- a/drivers/vdpa/mlx5/core/mr.c ++++ b/drivers/vdpa/mlx5/core/mr.c +@@ -368,7 +368,6 @@ static int map_direct_mr(struct mlx5_vdpa_dev *mvdev, struct mlx5_vdpa_direct_mr + unsigned long lgcd = 0; + int log_entity_size; + unsigned long size; +- u64 start = 0; + int err; + struct page *pg; + unsigned int nsg; +@@ -379,10 +378,9 @@ static int map_direct_mr(struct mlx5_vdpa_dev *mvdev, struct mlx5_vdpa_direct_mr + struct device *dma = mvdev->vdev.dma_dev; + + for (map = vhost_iotlb_itree_first(iotlb, mr->start, mr->end - 1); +- map; map = vhost_iotlb_itree_next(map, start, mr->end - 1)) { ++ map; map = vhost_iotlb_itree_next(map, mr->start, mr->end - 1)) { + size = maplen(map, mr); + lgcd = gcd(lgcd, size); +- start += size; + } + log_entity_size = ilog2(lgcd); + +-- +2.43.0 + diff --git a/queue-6.12/vfio-mlx5-fix-an-unwind-issue-in-mlx5vf_add_migratio.patch b/queue-6.12/vfio-mlx5-fix-an-unwind-issue-in-mlx5vf_add_migratio.patch new file mode 100644 index 00000000000..19cffb35849 --- /dev/null +++ b/queue-6.12/vfio-mlx5-fix-an-unwind-issue-in-mlx5vf_add_migratio.patch @@ -0,0 +1,61 @@ +From 549b628a713901b3681c317d8943661982ffed95 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Thu, 14 Nov 2024 11:53:17 +0200 +Subject: vfio/mlx5: Fix an unwind issue in mlx5vf_add_migration_pages() + +From: Yishai Hadas <yishaih@nvidia.com> + +[ Upstream commit 22e87bf3f77c18f5982c19ffe2732ef0c7a25f16 ] + +Fix an unwind issue in mlx5vf_add_migration_pages(). + +If a set of pages is allocated but fails to be added to the SG table, +they need to be freed to prevent a memory leak. + +Any pages successfully added to the SG table will be freed as part of +mlx5vf_free_data_buffer(). + +Fixes: 6fadb021266d ("vfio/mlx5: Implement vfio_pci driver for mlx5 devices") +Signed-off-by: Yishai Hadas <yishaih@nvidia.com> +Reviewed-by: Jason Gunthorpe <jgg@nvidia.com> +Link: https://lore.kernel.org/r/20241114095318.16556-2-yishaih@nvidia.com +Signed-off-by: Alex Williamson <alex.williamson@redhat.com> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/vfio/pci/mlx5/cmd.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/drivers/vfio/pci/mlx5/cmd.c b/drivers/vfio/pci/mlx5/cmd.c +index 41a4b0cf42975..7527e277c8989 100644 +--- a/drivers/vfio/pci/mlx5/cmd.c ++++ b/drivers/vfio/pci/mlx5/cmd.c +@@ -423,6 +423,7 @@ static int mlx5vf_add_migration_pages(struct mlx5_vhca_data_buffer *buf, + unsigned long filled; + unsigned int to_fill; + int ret; ++ int i; + + to_fill = min_t(unsigned int, npages, PAGE_SIZE / sizeof(*page_list)); + page_list = kvzalloc(to_fill * sizeof(*page_list), GFP_KERNEL_ACCOUNT); +@@ -443,7 +444,7 @@ static int mlx5vf_add_migration_pages(struct mlx5_vhca_data_buffer *buf, + GFP_KERNEL_ACCOUNT); + + if (ret) +- goto err; ++ goto err_append; + buf->allocated_length += filled * PAGE_SIZE; + /* clean input for another bulk allocation */ + memset(page_list, 0, filled * sizeof(*page_list)); +@@ -454,6 +455,9 @@ static int mlx5vf_add_migration_pages(struct mlx5_vhca_data_buffer *buf, + kvfree(page_list); + return 0; + ++err_append: ++ for (i = filled - 1; i >= 0; i--) ++ __free_page(page_list[i]); + err: + kvfree(page_list); + return ret; +-- +2.43.0 + diff --git a/queue-6.12/vfio-mlx5-fix-unwind-flows-in-mlx5vf_pci_save-resume.patch b/queue-6.12/vfio-mlx5-fix-unwind-flows-in-mlx5vf_pci_save-resume.patch new file mode 100644 index 00000000000..305faaf405e --- /dev/null +++ b/queue-6.12/vfio-mlx5-fix-unwind-flows-in-mlx5vf_pci_save-resume.patch @@ -0,0 +1,121 @@ +From e8cb6a8157c6bac57e5c7029eb7114b947aa9328 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Thu, 14 Nov 2024 11:53:18 +0200 +Subject: vfio/mlx5: Fix unwind flows in mlx5vf_pci_save/resume_device_data() + +From: Yishai Hadas <yishaih@nvidia.com> + +[ Upstream commit cb04444c243c001fc27f275e84792ff1c2b96867 ] + +Fix unwind flows in mlx5vf_pci_save_device_data() and +mlx5vf_pci_resume_device_data() to avoid freeing the migf pointer at the +'end' label, as this will be handled by fput(migf->filp) through +mlx5vf_release_file(). + +To ensure mlx5vf_release_file() functions correctly, move the +initialization of migf fields (such as migf->lock) to occur before any +potential unwind flow, as these fields may be accessed within +mlx5vf_release_file(). + +Fixes: 9945a67ea4b3 ("vfio/mlx5: Refactor PD usage") +Signed-off-by: Yishai Hadas <yishaih@nvidia.com> +Reviewed-by: Jason Gunthorpe <jgg@nvidia.com> +Link: https://lore.kernel.org/r/20241114095318.16556-3-yishaih@nvidia.com +Signed-off-by: Alex Williamson <alex.williamson@redhat.com> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/vfio/pci/mlx5/main.c | 35 +++++++++++++++++------------------ + 1 file changed, 17 insertions(+), 18 deletions(-) + +diff --git a/drivers/vfio/pci/mlx5/main.c b/drivers/vfio/pci/mlx5/main.c +index 242c23eef452e..8833e60d42f56 100644 +--- a/drivers/vfio/pci/mlx5/main.c ++++ b/drivers/vfio/pci/mlx5/main.c +@@ -640,14 +640,11 @@ mlx5vf_pci_save_device_data(struct mlx5vf_pci_core_device *mvdev, bool track) + O_RDONLY); + if (IS_ERR(migf->filp)) { + ret = PTR_ERR(migf->filp); +- goto end; ++ kfree(migf); ++ return ERR_PTR(ret); + } + + migf->mvdev = mvdev; +- ret = mlx5vf_cmd_alloc_pd(migf); +- if (ret) +- goto out_free; +- + stream_open(migf->filp->f_inode, migf->filp); + mutex_init(&migf->lock); + init_waitqueue_head(&migf->poll_wait); +@@ -663,6 +660,11 @@ mlx5vf_pci_save_device_data(struct mlx5vf_pci_core_device *mvdev, bool track) + INIT_LIST_HEAD(&migf->buf_list); + INIT_LIST_HEAD(&migf->avail_list); + spin_lock_init(&migf->list_lock); ++ ++ ret = mlx5vf_cmd_alloc_pd(migf); ++ if (ret) ++ goto out; ++ + ret = mlx5vf_cmd_query_vhca_migration_state(mvdev, &length, &full_size, 0); + if (ret) + goto out_pd; +@@ -692,10 +694,8 @@ mlx5vf_pci_save_device_data(struct mlx5vf_pci_core_device *mvdev, bool track) + mlx5vf_free_data_buffer(buf); + out_pd: + mlx5fv_cmd_clean_migf_resources(migf); +-out_free: ++out: + fput(migf->filp); +-end: +- kfree(migf); + return ERR_PTR(ret); + } + +@@ -1016,13 +1016,19 @@ mlx5vf_pci_resume_device_data(struct mlx5vf_pci_core_device *mvdev) + O_WRONLY); + if (IS_ERR(migf->filp)) { + ret = PTR_ERR(migf->filp); +- goto end; ++ kfree(migf); ++ return ERR_PTR(ret); + } + ++ stream_open(migf->filp->f_inode, migf->filp); ++ mutex_init(&migf->lock); ++ INIT_LIST_HEAD(&migf->buf_list); ++ INIT_LIST_HEAD(&migf->avail_list); ++ spin_lock_init(&migf->list_lock); + migf->mvdev = mvdev; + ret = mlx5vf_cmd_alloc_pd(migf); + if (ret) +- goto out_free; ++ goto out; + + buf = mlx5vf_alloc_data_buffer(migf, 0, DMA_TO_DEVICE); + if (IS_ERR(buf)) { +@@ -1041,20 +1047,13 @@ mlx5vf_pci_resume_device_data(struct mlx5vf_pci_core_device *mvdev) + migf->buf_header[0] = buf; + migf->load_state = MLX5_VF_LOAD_STATE_READ_HEADER; + +- stream_open(migf->filp->f_inode, migf->filp); +- mutex_init(&migf->lock); +- INIT_LIST_HEAD(&migf->buf_list); +- INIT_LIST_HEAD(&migf->avail_list); +- spin_lock_init(&migf->list_lock); + return migf; + out_buf: + mlx5vf_free_data_buffer(migf->buf[0]); + out_pd: + mlx5vf_cmd_dealloc_pd(migf); +-out_free: ++out: + fput(migf->filp); +-end: +- kfree(migf); + return ERR_PTR(ret); + } + +-- +2.43.0 + diff --git a/queue-6.12/vfio-pci-properly-hide-first-in-list-pcie-extended-c.patch b/queue-6.12/vfio-pci-properly-hide-first-in-list-pcie-extended-c.patch new file mode 100644 index 00000000000..2dedfc61fa5 --- /dev/null +++ b/queue-6.12/vfio-pci-properly-hide-first-in-list-pcie-extended-c.patch @@ -0,0 +1,115 @@ +From 69ab485b279cb97be5cfa4f2ca1b5771d9fd0bab Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Sun, 24 Nov 2024 16:27:39 +0200 +Subject: vfio/pci: Properly hide first-in-list PCIe extended capability + +From: Avihai Horon <avihaih@nvidia.com> + +[ Upstream commit fe4bf8d0b6716a423b16495d55b35d3fe515905d ] + +There are cases where a PCIe extended capability should be hidden from +the user. For example, an unknown capability (i.e., capability with ID +greater than PCI_EXT_CAP_ID_MAX) or a capability that is intentionally +chosen to be hidden from the user. + +Hiding a capability is done by virtualizing and modifying the 'Next +Capability Offset' field of the previous capability so it points to the +capability after the one that should be hidden. + +The special case where the first capability in the list should be hidden +is handled differently because there is no previous capability that can +be modified. In this case, the capability ID and version are zeroed +while leaving the next pointer intact. This hides the capability and +leaves an anchor for the rest of the capability list. + +However, today, hiding the first capability in the list is not done +properly if the capability is unknown, as struct +vfio_pci_core_device->pci_config_map is set to the capability ID during +initialization but the capability ID is not properly checked later when +used in vfio_config_do_rw(). This leads to the following warning [1] and +to an out-of-bounds access to ecap_perms array. + +Fix it by checking cap_id in vfio_config_do_rw(), and if it is greater +than PCI_EXT_CAP_ID_MAX, use an alternative struct perm_bits for direct +read only access instead of the ecap_perms array. + +Note that this is safe since the above is the only case where cap_id can +exceed PCI_EXT_CAP_ID_MAX (except for the special capabilities, which +are already checked before). + +[1] + +WARNING: CPU: 118 PID: 5329 at drivers/vfio/pci/vfio_pci_config.c:1900 vfio_pci_config_rw+0x395/0x430 [vfio_pci_core] +CPU: 118 UID: 0 PID: 5329 Comm: simx-qemu-syste Not tainted 6.12.0+ #1 +(snip) +Call Trace: + <TASK> + ? show_regs+0x69/0x80 + ? __warn+0x8d/0x140 + ? vfio_pci_config_rw+0x395/0x430 [vfio_pci_core] + ? report_bug+0x18f/0x1a0 + ? handle_bug+0x63/0xa0 + ? exc_invalid_op+0x19/0x70 + ? asm_exc_invalid_op+0x1b/0x20 + ? vfio_pci_config_rw+0x395/0x430 [vfio_pci_core] + ? vfio_pci_config_rw+0x244/0x430 [vfio_pci_core] + vfio_pci_rw+0x101/0x1b0 [vfio_pci_core] + vfio_pci_core_read+0x1d/0x30 [vfio_pci_core] + vfio_device_fops_read+0x27/0x40 [vfio] + vfs_read+0xbd/0x340 + ? vfio_device_fops_unl_ioctl+0xbb/0x740 [vfio] + ? __rseq_handle_notify_resume+0xa4/0x4b0 + __x64_sys_pread64+0x96/0xc0 + x64_sys_call+0x1c3d/0x20d0 + do_syscall_64+0x4d/0x120 + entry_SYSCALL_64_after_hwframe+0x76/0x7e + +Fixes: 89e1f7d4c66d ("vfio: Add PCI device driver") +Signed-off-by: Avihai Horon <avihaih@nvidia.com> +Reviewed-by: Yi Liu <yi.l.liu@intel.com> +Tested-by: Yi Liu <yi.l.liu@intel.com> +Link: https://lore.kernel.org/r/20241124142739.21698-1-avihaih@nvidia.com +Signed-off-by: Alex Williamson <alex.williamson@redhat.com> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/vfio/pci/vfio_pci_config.c | 16 ++++++++++++++-- + 1 file changed, 14 insertions(+), 2 deletions(-) + +diff --git a/drivers/vfio/pci/vfio_pci_config.c b/drivers/vfio/pci/vfio_pci_config.c +index 97422aafaa7b5..ea2745c1ac5e6 100644 +--- a/drivers/vfio/pci/vfio_pci_config.c ++++ b/drivers/vfio/pci/vfio_pci_config.c +@@ -313,6 +313,10 @@ static int vfio_virt_config_read(struct vfio_pci_core_device *vdev, int pos, + return count; + } + ++static struct perm_bits direct_ro_perms = { ++ .readfn = vfio_direct_config_read, ++}; ++ + /* Default capability regions to read-only, no-virtualization */ + static struct perm_bits cap_perms[PCI_CAP_ID_MAX + 1] = { + [0 ... PCI_CAP_ID_MAX] = { .readfn = vfio_direct_config_read } +@@ -1897,9 +1901,17 @@ static ssize_t vfio_config_do_rw(struct vfio_pci_core_device *vdev, char __user + cap_start = *ppos; + } else { + if (*ppos >= PCI_CFG_SPACE_SIZE) { +- WARN_ON(cap_id > PCI_EXT_CAP_ID_MAX); ++ /* ++ * We can get a cap_id that exceeds PCI_EXT_CAP_ID_MAX ++ * if we're hiding an unknown capability at the start ++ * of the extended capability list. Use default, ro ++ * access, which will virtualize the id and next values. ++ */ ++ if (cap_id > PCI_EXT_CAP_ID_MAX) ++ perm = &direct_ro_perms; ++ else ++ perm = &ecap_perms[cap_id]; + +- perm = &ecap_perms[cap_id]; + cap_start = vfio_find_cap_start(vdev, *ppos); + } else { + WARN_ON(cap_id > PCI_CAP_ID_MAX); +-- +2.43.0 + diff --git a/queue-6.12/virtio_blk-reverse-request-order-in-virtio_queue_rqs.patch b/queue-6.12/virtio_blk-reverse-request-order-in-virtio_queue_rqs.patch new file mode 100644 index 00000000000..c761f06961b --- /dev/null +++ b/queue-6.12/virtio_blk-reverse-request-order-in-virtio_queue_rqs.patch @@ -0,0 +1,112 @@ +From 8885cbd8e5a27a6f9f817353df16c54ea121fdf5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Wed, 13 Nov 2024 16:20:42 +0100 +Subject: virtio_blk: reverse request order in virtio_queue_rqs + +From: Christoph Hellwig <hch@lst.de> + +[ Upstream commit 7f212e997edbb7a2cb85cef2ac14265dfaf88717 ] + +blk_mq_flush_plug_list submits requests in the reverse order that they +were submitted, which leads to a rather suboptimal I/O pattern +especially in rotational devices. Fix this by rewriting virtio_queue_rqs +so that it always pops the requests from the passed in request list, and +then adds them to the head of a local submit list. This actually +simplifies the code a bit as it removes the complicated list splicing, +at the cost of extra updates of the rq_next pointer. As that should be +cache hot anyway it should be an easy price to pay. + +Fixes: 0e9911fa768f ("virtio-blk: support mq_ops->queue_rqs()") +Signed-off-by: Christoph Hellwig <hch@lst.de> +Link: https://lore.kernel.org/r/20241113152050.157179-3-hch@lst.de +Signed-off-by: Jens Axboe <axboe@kernel.dk> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/block/virtio_blk.c | 46 +++++++++++++++++--------------------- + 1 file changed, 21 insertions(+), 25 deletions(-) + +diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c +index 194417abc1053..43c96b73a7118 100644 +--- a/drivers/block/virtio_blk.c ++++ b/drivers/block/virtio_blk.c +@@ -471,18 +471,18 @@ static bool virtblk_prep_rq_batch(struct request *req) + return virtblk_prep_rq(req->mq_hctx, vblk, req, vbr) == BLK_STS_OK; + } + +-static bool virtblk_add_req_batch(struct virtio_blk_vq *vq, ++static void virtblk_add_req_batch(struct virtio_blk_vq *vq, + struct request **rqlist) + { ++ struct request *req; + unsigned long flags; +- int err; + bool kick; + + spin_lock_irqsave(&vq->lock, flags); + +- while (!rq_list_empty(*rqlist)) { +- struct request *req = rq_list_pop(rqlist); ++ while ((req = rq_list_pop(rqlist))) { + struct virtblk_req *vbr = blk_mq_rq_to_pdu(req); ++ int err; + + err = virtblk_add_req(vq->vq, vbr); + if (err) { +@@ -495,37 +495,33 @@ static bool virtblk_add_req_batch(struct virtio_blk_vq *vq, + kick = virtqueue_kick_prepare(vq->vq); + spin_unlock_irqrestore(&vq->lock, flags); + +- return kick; ++ if (kick) ++ virtqueue_notify(vq->vq); + } + + static void virtio_queue_rqs(struct request **rqlist) + { +- struct request *req, *next, *prev = NULL; ++ struct request *submit_list = NULL; + struct request *requeue_list = NULL; ++ struct request **requeue_lastp = &requeue_list; ++ struct virtio_blk_vq *vq = NULL; ++ struct request *req; + +- rq_list_for_each_safe(rqlist, req, next) { +- struct virtio_blk_vq *vq = get_virtio_blk_vq(req->mq_hctx); +- bool kick; +- +- if (!virtblk_prep_rq_batch(req)) { +- rq_list_move(rqlist, &requeue_list, req, prev); +- req = prev; +- if (!req) +- continue; +- } ++ while ((req = rq_list_pop(rqlist))) { ++ struct virtio_blk_vq *this_vq = get_virtio_blk_vq(req->mq_hctx); + +- if (!next || req->mq_hctx != next->mq_hctx) { +- req->rq_next = NULL; +- kick = virtblk_add_req_batch(vq, rqlist); +- if (kick) +- virtqueue_notify(vq->vq); ++ if (vq && vq != this_vq) ++ virtblk_add_req_batch(vq, &submit_list); ++ vq = this_vq; + +- *rqlist = next; +- prev = NULL; +- } else +- prev = req; ++ if (virtblk_prep_rq_batch(req)) ++ rq_list_add(&submit_list, req); /* reverse order */ ++ else ++ rq_list_add_tail(&requeue_lastp, req); + } + ++ if (vq) ++ virtblk_add_req_batch(vq, &submit_list); + *rqlist = requeue_list; + } + +-- +2.43.0 + diff --git a/queue-6.12/virtiofs-use-pages-instead-of-pointer-for-kernel-dir.patch b/queue-6.12/virtiofs-use-pages-instead-of-pointer-for-kernel-dir.patch new file mode 100644 index 00000000000..e218f42fe16 --- /dev/null +++ b/queue-6.12/virtiofs-use-pages-instead-of-pointer-for-kernel-dir.patch @@ -0,0 +1,291 @@ +From 205c477f3297860eaae9b4b3f2edbfc39ceeab4f Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Sat, 31 Aug 2024 17:37:49 +0800 +Subject: virtiofs: use pages instead of pointer for kernel direct IO + +From: Hou Tao <houtao1@huawei.com> + +[ Upstream commit 41748675c0bf252b3c5f600a95830f0936d366c1 ] + +When trying to insert a 10MB kernel module kept in a virtio-fs with cache +disabled, the following warning was reported: + + ------------[ cut here ]------------ + WARNING: CPU: 1 PID: 404 at mm/page_alloc.c:4551 ...... + Modules linked in: + CPU: 1 PID: 404 Comm: insmod Not tainted 6.9.0-rc5+ #123 + Hardware name: QEMU Standard PC (i440FX + PIIX, 1996) ...... + RIP: 0010:__alloc_pages+0x2bf/0x380 + ...... + Call Trace: + <TASK> + ? __warn+0x8e/0x150 + ? __alloc_pages+0x2bf/0x380 + __kmalloc_large_node+0x86/0x160 + __kmalloc+0x33c/0x480 + virtio_fs_enqueue_req+0x240/0x6d0 + virtio_fs_wake_pending_and_unlock+0x7f/0x190 + queue_request_and_unlock+0x55/0x60 + fuse_simple_request+0x152/0x2b0 + fuse_direct_io+0x5d2/0x8c0 + fuse_file_read_iter+0x121/0x160 + __kernel_read+0x151/0x2d0 + kernel_read+0x45/0x50 + kernel_read_file+0x1a9/0x2a0 + init_module_from_file+0x6a/0xe0 + idempotent_init_module+0x175/0x230 + __x64_sys_finit_module+0x5d/0xb0 + x64_sys_call+0x1c3/0x9e0 + do_syscall_64+0x3d/0xc0 + entry_SYSCALL_64_after_hwframe+0x4b/0x53 + ...... + </TASK> + ---[ end trace 0000000000000000 ]--- + +The warning is triggered as follows: + +1) syscall finit_module() handles the module insertion and it invokes +kernel_read_file() to read the content of the module first. + +2) kernel_read_file() allocates a 10MB buffer by using vmalloc() and +passes it to kernel_read(). kernel_read() constructs a kvec iter by +using iov_iter_kvec() and passes it to fuse_file_read_iter(). + +3) virtio-fs disables the cache, so fuse_file_read_iter() invokes +fuse_direct_io(). As for now, the maximal read size for kvec iter is +only limited by fc->max_read. For virtio-fs, max_read is UINT_MAX, so +fuse_direct_io() doesn't split the 10MB buffer. It saves the address and +the size of the 10MB-sized buffer in out_args[0] of a fuse request and +passes the fuse request to virtio_fs_wake_pending_and_unlock(). + +4) virtio_fs_wake_pending_and_unlock() uses virtio_fs_enqueue_req() to +queue the request. Because virtiofs need DMA-able address, so +virtio_fs_enqueue_req() uses kmalloc() to allocate a bounce buffer for +all fuse args, copies these args into the bounce buffer and passed the +physical address of the bounce buffer to virtiofsd. The total length of +these fuse args for the passed fuse request is about 10MB, so +copy_args_to_argbuf() invokes kmalloc() with a 10MB size parameter and +it triggers the warning in __alloc_pages(): + + if (WARN_ON_ONCE_GFP(order > MAX_PAGE_ORDER, gfp)) + return NULL; + +5) virtio_fs_enqueue_req() will retry the memory allocation in a +kworker, but it won't help, because kmalloc() will always return NULL +due to the abnormal size and finit_module() will hang forever. + +A feasible solution is to limit the value of max_read for virtio-fs, so +the length passed to kmalloc() will be limited. However it will affect +the maximal read size for normal read. And for virtio-fs write initiated +from kernel, it has the similar problem but now there is no way to limit +fc->max_write in kernel. + +So instead of limiting both the values of max_read and max_write in +kernel, introducing use_pages_for_kvec_io in fuse_conn and setting it as +true in virtiofs. When use_pages_for_kvec_io is enabled, fuse will use +pages instead of pointer to pass the KVEC_IO data. + +After switching to pages for KVEC_IO data, these pages will be used for +DMA through virtio-fs. If these pages are backed by vmalloc(), +{flush|invalidate}_kernel_vmap_range() are necessary to flush or +invalidate the cache before the DMA operation. So add two new fields in +fuse_args_pages to record the base address of vmalloc area and the +condition indicating whether invalidation is needed. Perform the flush +in fuse_get_user_pages() for write operations and the invalidation in +fuse_release_user_pages() for read operations. + +It may seem necessary to introduce another field in fuse_conn to +indicate that these KVEC_IO pages are used for DMA, However, considering +that virtio-fs is currently the only user of use_pages_for_kvec_io, just +reuse use_pages_for_kvec_io to indicate that these pages will be used +for DMA. + +Fixes: a62a8ef9d97d ("virtio-fs: add virtiofs filesystem") +Signed-off-by: Hou Tao <houtao1@huawei.com> +Tested-by: Jingbo Xu <jefflexu@linux.alibaba.com> +Signed-off-by: Miklos Szeredi <mszeredi@redhat.com> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + fs/fuse/file.c | 62 +++++++++++++++++++++++++++++++-------------- + fs/fuse/fuse_i.h | 6 +++++ + fs/fuse/virtio_fs.c | 1 + + 3 files changed, 50 insertions(+), 19 deletions(-) + +diff --git a/fs/fuse/file.c b/fs/fuse/file.c +index dafdf766b1d53..e20d91d0ae558 100644 +--- a/fs/fuse/file.c ++++ b/fs/fuse/file.c +@@ -645,7 +645,7 @@ void fuse_read_args_fill(struct fuse_io_args *ia, struct file *file, loff_t pos, + args->out_args[0].size = count; + } + +-static void fuse_release_user_pages(struct fuse_args_pages *ap, ++static void fuse_release_user_pages(struct fuse_args_pages *ap, ssize_t nres, + bool should_dirty) + { + unsigned int i; +@@ -656,6 +656,9 @@ static void fuse_release_user_pages(struct fuse_args_pages *ap, + if (ap->args.is_pinned) + unpin_user_page(ap->pages[i]); + } ++ ++ if (nres > 0 && ap->args.invalidate_vmap) ++ invalidate_kernel_vmap_range(ap->args.vmap_base, nres); + } + + static void fuse_io_release(struct kref *kref) +@@ -754,25 +757,29 @@ static void fuse_aio_complete_req(struct fuse_mount *fm, struct fuse_args *args, + struct fuse_io_args *ia = container_of(args, typeof(*ia), ap.args); + struct fuse_io_priv *io = ia->io; + ssize_t pos = -1; +- +- fuse_release_user_pages(&ia->ap, io->should_dirty); ++ size_t nres; + + if (err) { + /* Nothing */ + } else if (io->write) { + if (ia->write.out.size > ia->write.in.size) { + err = -EIO; +- } else if (ia->write.in.size != ia->write.out.size) { +- pos = ia->write.in.offset - io->offset + +- ia->write.out.size; ++ } else { ++ nres = ia->write.out.size; ++ if (ia->write.in.size != ia->write.out.size) ++ pos = ia->write.in.offset - io->offset + ++ ia->write.out.size; + } + } else { + u32 outsize = args->out_args[0].size; + ++ nres = outsize; + if (ia->read.in.size != outsize) + pos = ia->read.in.offset - io->offset + outsize; + } + ++ fuse_release_user_pages(&ia->ap, err ?: nres, io->should_dirty); ++ + fuse_aio_complete(io, err, pos); + fuse_io_free(ia); + } +@@ -1468,24 +1475,37 @@ static inline size_t fuse_get_frag_size(const struct iov_iter *ii, + + static int fuse_get_user_pages(struct fuse_args_pages *ap, struct iov_iter *ii, + size_t *nbytesp, int write, +- unsigned int max_pages) ++ unsigned int max_pages, ++ bool use_pages_for_kvec_io) + { ++ bool flush_or_invalidate = false; + size_t nbytes = 0; /* # bytes already packed in req */ + ssize_t ret = 0; + +- /* Special case for kernel I/O: can copy directly into the buffer */ ++ /* Special case for kernel I/O: can copy directly into the buffer. ++ * However if the implementation of fuse_conn requires pages instead of ++ * pointer (e.g., virtio-fs), use iov_iter_extract_pages() instead. ++ */ + if (iov_iter_is_kvec(ii)) { +- unsigned long user_addr = fuse_get_user_addr(ii); +- size_t frag_size = fuse_get_frag_size(ii, *nbytesp); ++ void *user_addr = (void *)fuse_get_user_addr(ii); + +- if (write) +- ap->args.in_args[1].value = (void *) user_addr; +- else +- ap->args.out_args[0].value = (void *) user_addr; ++ if (!use_pages_for_kvec_io) { ++ size_t frag_size = fuse_get_frag_size(ii, *nbytesp); + +- iov_iter_advance(ii, frag_size); +- *nbytesp = frag_size; +- return 0; ++ if (write) ++ ap->args.in_args[1].value = user_addr; ++ else ++ ap->args.out_args[0].value = user_addr; ++ ++ iov_iter_advance(ii, frag_size); ++ *nbytesp = frag_size; ++ return 0; ++ } ++ ++ if (is_vmalloc_addr(user_addr)) { ++ ap->args.vmap_base = user_addr; ++ flush_or_invalidate = true; ++ } + } + + while (nbytes < *nbytesp && ap->num_pages < max_pages) { +@@ -1514,6 +1534,10 @@ static int fuse_get_user_pages(struct fuse_args_pages *ap, struct iov_iter *ii, + (PAGE_SIZE - ret) & (PAGE_SIZE - 1); + } + ++ if (write && flush_or_invalidate) ++ flush_kernel_vmap_range(ap->args.vmap_base, nbytes); ++ ++ ap->args.invalidate_vmap = !write && flush_or_invalidate; + ap->args.is_pinned = iov_iter_extract_will_pin(ii); + ap->args.user_pages = true; + if (write) +@@ -1582,7 +1606,7 @@ ssize_t fuse_direct_io(struct fuse_io_priv *io, struct iov_iter *iter, + size_t nbytes = min(count, nmax); + + err = fuse_get_user_pages(&ia->ap, iter, &nbytes, write, +- max_pages); ++ max_pages, fc->use_pages_for_kvec_io); + if (err && !nbytes) + break; + +@@ -1596,7 +1620,7 @@ ssize_t fuse_direct_io(struct fuse_io_priv *io, struct iov_iter *iter, + } + + if (!io->async || nres < 0) { +- fuse_release_user_pages(&ia->ap, io->should_dirty); ++ fuse_release_user_pages(&ia->ap, nres, io->should_dirty); + fuse_io_free(ia); + } + ia = NULL; +diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h +index e6cc3d552b138..28cf319c1c25c 100644 +--- a/fs/fuse/fuse_i.h ++++ b/fs/fuse/fuse_i.h +@@ -309,9 +309,12 @@ struct fuse_args { + bool may_block:1; + bool is_ext:1; + bool is_pinned:1; ++ bool invalidate_vmap:1; + struct fuse_in_arg in_args[3]; + struct fuse_arg out_args[2]; + void (*end)(struct fuse_mount *fm, struct fuse_args *args, int error); ++ /* Used for kvec iter backed by vmalloc address */ ++ void *vmap_base; + }; + + struct fuse_args_pages { +@@ -857,6 +860,9 @@ struct fuse_conn { + /** Passthrough support for read/write IO */ + unsigned int passthrough:1; + ++ /* Use pages instead of pointer for kernel I/O */ ++ unsigned int use_pages_for_kvec_io:1; ++ + /** Maximum stack depth for passthrough backing files */ + int max_stack_depth; + +diff --git a/fs/fuse/virtio_fs.c b/fs/fuse/virtio_fs.c +index 6404a189e9890..d220e28e755fe 100644 +--- a/fs/fuse/virtio_fs.c ++++ b/fs/fuse/virtio_fs.c +@@ -1691,6 +1691,7 @@ static int virtio_fs_get_tree(struct fs_context *fsc) + fc->delete_stale = true; + fc->auto_submounts = true; + fc->sync_fs = true; ++ fc->use_pages_for_kvec_io = true; + + /* Tell FUSE to split requests that exceed the virtqueue's size */ + fc->max_pages_limit = min_t(unsigned int, fc->max_pages_limit, +-- +2.43.0 + diff --git a/queue-6.12/watchdog-add-has_ioport-dependency-for-sbc8360-and-s.patch b/queue-6.12/watchdog-add-has_ioport-dependency-for-sbc8360-and-s.patch new file mode 100644 index 00000000000..2aa7ebd97cc --- /dev/null +++ b/queue-6.12/watchdog-add-has_ioport-dependency-for-sbc8360-and-s.patch @@ -0,0 +1,53 @@ +From 826d2ef9a29105a8bb02ada942071152d6b22bf3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Mon, 14 Oct 2024 13:25:42 +0200 +Subject: watchdog: Add HAS_IOPORT dependency for SBC8360 and SBC7240 + +From: Niklas Schnelle <schnelle@linux.ibm.com> + +[ Upstream commit d4d3125a3452a54acca69050be67b87ee2900e77 ] + +Both drivers use I/O port accesses without declaring a dependency on +CONFIG_HAS_IOPORT. For sbc8360_wdt this causes a compile error on UML +once inb()/outb() helpers become conditional. + +For sbc7240_wdt this causes no such errors with UML because this driver +depends on both x86_32 and !UML. Nevertheless add HAS_IOPORT as +a dependency for both drivers to be explicit and drop the !UML +dependency for sbc7240_wdt as it is now redundant since UML implies no +HAS_IOPORT. + +Fixes: 52df67b6b313 ("watchdog: add HAS_IOPORT dependencies") +Signed-off-by: Niklas Schnelle <schnelle@linux.ibm.com> +Reviewed-by: Guenter Roeck <linux@roeck-us.net> +Signed-off-by: Arnd Bergmann <arnd@arndb.de> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/watchdog/Kconfig | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig +index 684b9fe84fff5..94c96bcfefe34 100644 +--- a/drivers/watchdog/Kconfig ++++ b/drivers/watchdog/Kconfig +@@ -1509,7 +1509,7 @@ config 60XX_WDT + + config SBC8360_WDT + tristate "SBC8360 Watchdog Timer" +- depends on X86_32 ++ depends on X86_32 && HAS_IOPORT + help + + This is the driver for the hardware watchdog on the SBC8360 Single +@@ -1522,7 +1522,7 @@ config SBC8360_WDT + + config SBC7240_WDT + tristate "SBC Nano 7240 Watchdog Timer" +- depends on X86_32 && !UML ++ depends on X86_32 && HAS_IOPORT + help + This is the driver for the hardware watchdog found on the IEI + single board computers EPIC Nano 7240 (and likely others). This +-- +2.43.0 + diff --git a/queue-6.12/wifi-ath10k-fix-invalid-vht-parameters-in-supported_.patch b/queue-6.12/wifi-ath10k-fix-invalid-vht-parameters-in-supported_.patch new file mode 100644 index 00000000000..65b481e7486 --- /dev/null +++ b/queue-6.12/wifi-ath10k-fix-invalid-vht-parameters-in-supported_.patch @@ -0,0 +1,52 @@ +From b3d81ac626aeac9e83f04968635c9f267231ca49 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Thu, 11 Jul 2024 10:03:43 +0800 +Subject: wifi: ath10k: fix invalid VHT parameters in + supported_vht_mcs_rate_nss1 + +From: Baochen Qiang <quic_bqiang@quicinc.com> + +[ Upstream commit d50886b27850447d90c0cd40c725238097909d1e ] + +In supported_vht_mcs_rate_nss1, the rate for MCS9 & VHT20 is defined as +{780, 867}, this does not align with firmware's definition and therefore +fails the verification in ath10k_mac_get_rate_flags_vht(): + + invalid vht params rate 960 100kbps nss 1 mcs 9 + +Change it to {865, 960} to align with firmware, so this issue could be +fixed. + +Since ath10k_hw_params::supports_peer_stats_info is enabled only for +QCA6174, this change does not affect other chips. + +Tested-on: QCA6174 hw3.2 PCI WLAN.RM.4.4.1-00309-QCARMSWPZ-1 + +Fixes: 3344b99d69ab ("ath10k: add bitrate parse for peer stats info") +Reported-by: Paul Menzel <pmenzel@molgen.mpg.de> +Closes: https://lore.kernel.org/lkml/fba24cd3-4a1e-4072-8585-8402272788ff@molgen.mpg.de/ +Signed-off-by: Baochen Qiang <quic_bqiang@quicinc.com> +Acked-by: Jeff Johnson <quic_jjohnson@quicinc.com> +Signed-off-by: Kalle Valo <quic_kvalo@quicinc.com> +Link: https://patch.msgid.link/20240711020344.98040-2-quic_bqiang@quicinc.com +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/net/wireless/ath/ath10k/mac.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c +index 646e1737d4c47..ef303deb67cca 100644 +--- a/drivers/net/wireless/ath/ath10k/mac.c ++++ b/drivers/net/wireless/ath/ath10k/mac.c +@@ -9121,7 +9121,7 @@ static const struct ath10k_index_vht_data_rate_type supported_vht_mcs_rate_nss1[ + {6, {2633, 2925}, {1215, 1350}, {585, 650} }, + {7, {2925, 3250}, {1350, 1500}, {650, 722} }, + {8, {3510, 3900}, {1620, 1800}, {780, 867} }, +- {9, {3900, 4333}, {1800, 2000}, {780, 867} } ++ {9, {3900, 4333}, {1800, 2000}, {865, 960} } + }; + + /*MCS parameters with Nss = 2 */ +-- +2.43.0 + diff --git a/queue-6.12/wifi-ath10k-fix-invalid-vht-parameters-in-supported_.patch-16142 b/queue-6.12/wifi-ath10k-fix-invalid-vht-parameters-in-supported_.patch-16142 new file mode 100644 index 00000000000..bd91c1c9ab7 --- /dev/null +++ b/queue-6.12/wifi-ath10k-fix-invalid-vht-parameters-in-supported_.patch-16142 @@ -0,0 +1,56 @@ +From 1d855f2f4ca6d7b736cfa9de90e049fb7d6f3fe1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Thu, 11 Jul 2024 10:03:44 +0800 +Subject: wifi: ath10k: fix invalid VHT parameters in + supported_vht_mcs_rate_nss2 + +From: Baochen Qiang <quic_bqiang@quicinc.com> + +[ Upstream commit 52db16ec5bae7bd027804265b968259d1a6c3970 ] + +In supported_vht_mcs_rate_nss2, the rate for MCS9 & VHT20 is defined as +{1560, 1733}, this does not align with firmware's definition and therefore +fails the verification in ath10k_mac_get_rate_flags_vht(): + + invalid vht params rate 1730 100kbps nss 2 mcs 9 + +and: + + invalid vht params rate 1920 100kbps nss 2 mcs 9 + +Change it to {1730, 1920} to align with firmware to fix the issue. + +Since ath10k_hw_params::supports_peer_stats_info is enabled only for +QCA6174, this change does not affect other chips. + +Tested-on: QCA6174 hw3.2 PCI WLAN.RM.4.4.1-00309-QCARMSWPZ-1 + +Fixes: 3344b99d69ab ("ath10k: add bitrate parse for peer stats info") +Reported-by: Paul Menzel <pmenzel@molgen.mpg.de> +Closes: https://lore.kernel.org/lkml/fba24cd3-4a1e-4072-8585-8402272788ff@molgen.mpg.de/ +Signed-off-by: Baochen Qiang <quic_bqiang@quicinc.com> +Acked-by: Jeff Johnson <quic_jjohnson@quicinc.com> +Tested-by: Paul Menzel <pmenzel@molgen.mpg.de> # Dell XPS 13 9360 +Signed-off-by: Kalle Valo <quic_kvalo@quicinc.com> +Link: https://patch.msgid.link/20240711020344.98040-3-quic_bqiang@quicinc.com +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/net/wireless/ath/ath10k/mac.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c +index ef303deb67cca..6b467696bc982 100644 +--- a/drivers/net/wireless/ath/ath10k/mac.c ++++ b/drivers/net/wireless/ath/ath10k/mac.c +@@ -9136,7 +9136,7 @@ static const struct ath10k_index_vht_data_rate_type supported_vht_mcs_rate_nss2[ + {6, {5265, 5850}, {2430, 2700}, {1170, 1300} }, + {7, {5850, 6500}, {2700, 3000}, {1300, 1444} }, + {8, {7020, 7800}, {3240, 3600}, {1560, 1733} }, +- {9, {7800, 8667}, {3600, 4000}, {1560, 1733} } ++ {9, {7800, 8667}, {3600, 4000}, {1730, 1920} } + }; + + static void ath10k_mac_get_rate_flags_ht(struct ath10k *ar, u32 rate, u8 nss, u8 mcs, +-- +2.43.0 + diff --git a/queue-6.12/wifi-ath11k-fix-ce-offset-address-calculation-for-wc.patch b/queue-6.12/wifi-ath11k-fix-ce-offset-address-calculation-for-wc.patch new file mode 100644 index 00000000000..91a788cafc1 --- /dev/null +++ b/queue-6.12/wifi-ath11k-fix-ce-offset-address-calculation-for-wc.patch @@ -0,0 +1,62 @@ +From 8996a44b12562afeafa2c1fc88fca98d1f8c3dff Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Fri, 27 Sep 2024 15:28:25 +0530 +Subject: wifi: ath11k: Fix CE offset address calculation for WCN6750 in SSR + +From: Balaji Pothunoori <quic_bpothuno@quicinc.com> + +[ Upstream commit 4c57ec6c4bb9979b42ae7fa7273fc2d4a361d576 ] + +Currently, mem_ce and mem iomem addresses are used to calculate the +CE offset address. mem_ce is initialized with mem address, and for +targets where ce_remap is needed, mem_ce is remapped to a new address +space during AHB probe. + +For targets such as WCN6750 in which CE address space is same as WCSS +address space (i.e. "ce_remap" hw_param is set to false), mem_ce and +mem iomem addresses are same. In the initial SRNG setup for such targets, +the CE offset address and hence CE register base addresses are +calculated correctly in ath11k_hal_srng_init() as both mem and mem_ce +are initialized with same iomem address. + +Later, after the firmware download, mem is initialized with BAR address +received in qmi_wlanfw_device_info_resp_msg_v01 QMI message, while mem_ce +is not updated. + +After initial setup success, during Subsystem Restart (SSR), as part +of reinitialization, ath11k_hal_srng_init() will be called again, +and CE offset address will be calculated incorrectly this time as mem_ce +address was not updated. Due to the incorrect CE offset address, +APPS accesses an invalid CE register address which leads to improper +behavior in firmware after SSR is triggered. + +To fix the above issue, update mem_ce to mem iomem address in +ath11k_qmi_request_device_info() for targets which do not support +ce_remap feature. + +Signed-off-by: Balaji Pothunoori <quic_bpothuno@quicinc.com> +Fixes: b42b3678c91f ("wifi: ath11k: remap ce register space for IPQ5018") +Link: https://patch.msgid.link/20240927095825.22317-1-quic_bpothuno@quicinc.com +Signed-off-by: Jeff Johnson <quic_jjohnson@quicinc.com> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/net/wireless/ath/ath11k/qmi.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/net/wireless/ath/ath11k/qmi.c b/drivers/net/wireless/ath/ath11k/qmi.c +index f477afd325dea..7a22483b35cd9 100644 +--- a/drivers/net/wireless/ath/ath11k/qmi.c ++++ b/drivers/net/wireless/ath/ath11k/qmi.c +@@ -2180,6 +2180,9 @@ static int ath11k_qmi_request_device_info(struct ath11k_base *ab) + ab->mem = bar_addr_va; + ab->mem_len = resp.bar_size; + ++ if (!ab->hw_params.ce_remap) ++ ab->mem_ce = ab->mem; ++ + return 0; + out: + return ret; +-- +2.43.0 + diff --git a/queue-6.12/wifi-ath12k-fix-one-more-memcpy-size-error.patch b/queue-6.12/wifi-ath12k-fix-one-more-memcpy-size-error.patch new file mode 100644 index 00000000000..3aa2271df27 --- /dev/null +++ b/queue-6.12/wifi-ath12k-fix-one-more-memcpy-size-error.patch @@ -0,0 +1,52 @@ +From 0f308224906b24101dae9af88084ec0adc14e386 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Fri, 4 Oct 2024 09:54:13 +0000 +Subject: wifi: ath12k: fix one more memcpy size error + +From: Arnd Bergmann <arnd@arndb.de> + +[ Upstream commit 19c23eb61fa4c802e6e0aaf74d6f7dcbe99f0ba3 ] + +A previous patch addressed a fortified-memcpy warning on older compilers, +but there is still a warning on gcc-14 in some configurations: + +In file included from include/linux/string.h:390, + from drivers/net/wireless/ath/ath12k/wow.c:7: +drivers/net/wireless/ath/ath12k/wow.c: In function 'ath12k_wow_convert_8023_to_80211.isra': +include/linux/fortify-string.h:114:33: error: '__builtin_memcpy' accessing 18446744073709551610 or more bytes at offsets 0 and 0 overlaps 9223372036854775797 bytes at offset -9223372036854775803 [-Werror=restrict] +include/linux/fortify-string.h:679:26: note: in expansion of macro '__fortify_memcpy_chk' + 679 | #define memcpy(p, q, s) __fortify_memcpy_chk(p, q, s, \ + | ^~~~~~~~~~~~~~~~~~~~ +drivers/net/wireless/ath/ath12k/wow.c:199:25: note: in expansion of macro 'memcpy' + 199 | memcpy(pat + a3_ofs - pkt_ofs, + | ^~~~~~ + +Address this the same way as the other two, using size_add(). + +Fixes: b49991d83bba ("wifi: ath12k: fix build vs old compiler") +Fixes: 4a3c212eee0e ("wifi: ath12k: add basic WoW functionalities") +Signed-off-by: Arnd Bergmann <arnd@arndb.de> +Acked-by: Kalle Valo <kvalo@kernel.org> +Link: https://patch.msgid.link/20241004095420.637091-1-arnd@kernel.org +Signed-off-by: Jeff Johnson <quic_jjohnson@quicinc.com> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/net/wireless/ath/ath12k/wow.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/wireless/ath/ath12k/wow.c b/drivers/net/wireless/ath/ath12k/wow.c +index 9b8684abbe40a..3624180b25b97 100644 +--- a/drivers/net/wireless/ath/ath12k/wow.c ++++ b/drivers/net/wireless/ath/ath12k/wow.c +@@ -191,7 +191,7 @@ ath12k_wow_convert_8023_to_80211(struct ath12k *ar, + memcpy(bytemask, eth_bytemask, eth_pat_len); + + pat_len = eth_pat_len; +- } else if (eth_pkt_ofs + eth_pat_len < prot_ofs) { ++ } else if (size_add(eth_pkt_ofs, eth_pat_len) < prot_ofs) { + memcpy(pat, eth_pat, ETH_ALEN - eth_pkt_ofs); + memcpy(bytemask, eth_bytemask, ETH_ALEN - eth_pkt_ofs); + +-- +2.43.0 + diff --git a/queue-6.12/wifi-ath12k-fix-use-after-free-in-ath12k_dp_cc_clean.patch b/queue-6.12/wifi-ath12k-fix-use-after-free-in-ath12k_dp_cc_clean.patch new file mode 100644 index 00000000000..44f683da964 --- /dev/null +++ b/queue-6.12/wifi-ath12k-fix-use-after-free-in-ath12k_dp_cc_clean.patch @@ -0,0 +1,116 @@ +From fc9e299f0250c0a4eb11cc04f0897839255a94e3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Tue, 1 Oct 2024 14:56:52 +0530 +Subject: wifi: ath12k: fix use-after-free in ath12k_dp_cc_cleanup() + +From: Rameshkumar Sundaram <quic_ramess@quicinc.com> + +[ Upstream commit bdb281103373fd80eb5c91cede1e115ba270b4e9 ] + +During ath12k module removal, in ath12k_core_deinit(), +ath12k_mac_destroy() un-registers ah->hw from mac80211 and frees +the ah->hw as well as all the ar's in it. After this +ath12k_core_soc_destroy()-> ath12k_dp_free()-> ath12k_dp_cc_cleanup() +tries to access one of the freed ar's from pending skb. + +This is because during mac destroy, driver failed to flush few +data packets, which were accessed later in ath12k_dp_cc_cleanup() +and freed, but using ar from the packet led to this use-after-free. + +BUG: KASAN: use-after-free in ath12k_dp_cc_cleanup.part.0+0x5e2/0xd40 [ath12k] +Write of size 4 at addr ffff888150bd3514 by task modprobe/8926 +CPU: 0 UID: 0 PID: 8926 Comm: modprobe Not tainted +6.11.0-rc2-wt-ath+ #1746 +Hardware name: Intel(R) Client Systems NUC8i7HVK/NUC8i7HVB, BIOS +HNKBLi70.86A.0067.2021.0528.1339 05/28/2021 + +Call Trace: + <TASK> + dump_stack_lvl+0x7d/0xe0 + print_address_description.constprop.0+0x33/0x3a0 + print_report+0xb5/0x260 + ? kasan_addr_to_slab+0x24/0x80 + kasan_report+0xd8/0x110 + ? ath12k_dp_cc_cleanup.part.0+0x5e2/0xd40 [ath12k] + ? ath12k_dp_cc_cleanup.part.0+0x5e2/0xd40 [ath12k] + kasan_check_range+0xf3/0x1a0 + __kasan_check_write+0x14/0x20 + ath12k_dp_cc_cleanup.part.0+0x5e2/0xd40 [ath12k] + ath12k_dp_free+0x178/0x420 [ath12k] + ath12k_core_stop+0x176/0x200 [ath12k] + ath12k_core_deinit+0x13f/0x210 [ath12k] + ath12k_pci_remove+0xad/0x1c0 [ath12k] + pci_device_remove+0x9b/0x1b0 + device_remove+0xbf/0x150 + device_release_driver_internal+0x3c3/0x580 + ? __kasan_check_read+0x11/0x20 + driver_detach+0xc4/0x190 + bus_remove_driver+0x130/0x2a0 + driver_unregister+0x68/0x90 + pci_unregister_driver+0x24/0x240 + ? find_module_all+0x13e/0x1e0 + ath12k_pci_exit+0x10/0x20 [ath12k] + __do_sys_delete_module+0x32c/0x580 + ? module_flags+0x2f0/0x2f0 + ? kmem_cache_free+0xf0/0x410 + ? __fput+0x56f/0xab0 + ? __fput+0x56f/0xab0 + ? debug_smp_processor_id+0x17/0x20 + __x64_sys_delete_module+0x4f/0x70 + x64_sys_call+0x522/0x9f0 + do_syscall_64+0x64/0x130 + entry_SYSCALL_64_after_hwframe+0x4b/0x53 +RIP: 0033:0x7f8182c6ac8b + +Commit 24de1b7b231c ("wifi: ath12k: fix flush failure in recovery +scenarios") added the change to decrement the pending packets count +in case of recovery which make sense as ah->hw as well all +ar's in it are intact during recovery, but during core deinit there +is no use in decrementing packets count or waking up the empty waitq +as the module is going to be removed also ar's from pending skb's +can't be used and the packets should just be released back. + +To fix this, avoid accessing ar from skb->cb when driver is being +unregistered. + +Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.1.1-00214-QCAHKSWPL_SILICONZ-1 +Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.0.c5-00481-QCAHMTSWPL_V1.0_V2.0_SILICONZ-3 + +Fixes: 24de1b7b231c ("wifi: ath12k: fix flush failure in recovery scenarios") +Signed-off-by: Rameshkumar Sundaram <quic_ramess@quicinc.com> +Acked-by: Jeff Johnson <quic_jjohnson@quicinc.com> +Link: https://patch.msgid.link/20241001092652.3134334-1-quic_ramess@quicinc.com +Signed-off-by: Jeff Johnson <quic_jjohnson@quicinc.com> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/net/wireless/ath/ath12k/dp.c | 14 ++++++++++---- + 1 file changed, 10 insertions(+), 4 deletions(-) + +diff --git a/drivers/net/wireless/ath/ath12k/dp.c b/drivers/net/wireless/ath/ath12k/dp.c +index 61aa78d8bd8c8..abddeafabfa1b 100644 +--- a/drivers/net/wireless/ath/ath12k/dp.c ++++ b/drivers/net/wireless/ath/ath12k/dp.c +@@ -1202,10 +1202,16 @@ static void ath12k_dp_cc_cleanup(struct ath12k_base *ab) + if (!skb) + continue; + +- skb_cb = ATH12K_SKB_CB(skb); +- ar = skb_cb->ar; +- if (atomic_dec_and_test(&ar->dp.num_tx_pending)) +- wake_up(&ar->dp.tx_empty_waitq); ++ /* if we are unregistering, hw would've been destroyed and ++ * ar is no longer valid. ++ */ ++ if (!(test_bit(ATH12K_FLAG_UNREGISTERING, &ab->dev_flags))) { ++ skb_cb = ATH12K_SKB_CB(skb); ++ ar = skb_cb->ar; ++ ++ if (atomic_dec_and_test(&ar->dp.num_tx_pending)) ++ wake_up(&ar->dp.tx_empty_waitq); ++ } + + dma_unmap_single(ab->dev, ATH12K_SKB_CB(skb)->paddr, + skb->len, DMA_TO_DEVICE); +-- +2.43.0 + diff --git a/queue-6.12/wifi-ath12k-skip-rx-tid-cleanup-for-self-peer.patch b/queue-6.12/wifi-ath12k-skip-rx-tid-cleanup-for-self-peer.patch new file mode 100644 index 00000000000..2044ba09cad --- /dev/null +++ b/queue-6.12/wifi-ath12k-skip-rx-tid-cleanup-for-self-peer.patch @@ -0,0 +1,66 @@ +From fdac1c1ae8d34ceaf35921c037fe3753ffbe63ec Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Thu, 5 Sep 2024 09:58:51 +0530 +Subject: wifi: ath12k: Skip Rx TID cleanup for self peer + +From: Ramya Gnanasekar <quic_rgnanase@quicinc.com> + +[ Upstream commit 1a0c640ce1cdcde3eb131a0c1e70ca1ed7cf27cb ] + +During peer create, dp setup for the peer is done where Rx TID is +updated for all the TIDs. Peer object for self peer will not go through +dp setup. + +When core halts, dp cleanup is done for all the peers. While cleanup, +rx_tid::ab is accessed which causes below stack trace for self peer. + +WARNING: CPU: 6 PID: 12297 at drivers/net/wireless/ath/ath12k/dp_rx.c:851 +Call Trace: +__warn+0x7b/0x1a0 +ath12k_dp_rx_frags_cleanup+0xd2/0xe0 [ath12k] +report_bug+0x10b/0x200 +handle_bug+0x3f/0x70 +exc_invalid_op+0x13/0x60 +asm_exc_invalid_op+0x16/0x20 +ath12k_dp_rx_frags_cleanup+0xd2/0xe0 [ath12k] +ath12k_dp_rx_frags_cleanup+0xca/0xe0 [ath12k] +ath12k_dp_rx_peer_tid_cleanup+0x39/0xa0 [ath12k] +ath12k_mac_peer_cleanup_all+0x61/0x100 [ath12k] +ath12k_core_halt+0x3b/0x100 [ath12k] +ath12k_core_reset+0x494/0x4c0 [ath12k] + +sta object in peer will be updated when remote peer is created. Hence +use peer::sta to detect the self peer and skip the cleanup. + +Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.0.1-00029-QCAHKSWPL_SILICONZ-1 +Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.0.c5-00481-QCAHMTSWPL_V1.0_V2.0_SILICONZ-3 + +Fixes: d889913205cf ("wifi: ath12k: driver for Qualcomm Wi-Fi 7 devices") +Signed-off-by: Ramya Gnanasekar <quic_rgnanase@quicinc.com> +Acked-by: Jeff Johnson <quic_jjohnson@quicinc.com> +Signed-off-by: Kalle Valo <quic_kvalo@quicinc.com> +Link: https://patch.msgid.link/20240905042851.2282306-1-quic_rgnanase@quicinc.com +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/net/wireless/ath/ath12k/mac.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c +index 137394c364603..6d0784a21558e 100644 +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -917,7 +917,10 @@ void ath12k_mac_peer_cleanup_all(struct ath12k *ar) + + spin_lock_bh(&ab->base_lock); + list_for_each_entry_safe(peer, tmp, &ab->peers, list) { +- ath12k_dp_rx_peer_tid_cleanup(ar, peer); ++ /* Skip Rx TID cleanup for self peer */ ++ if (peer->sta) ++ ath12k_dp_rx_peer_tid_cleanup(ar, peer); ++ + list_del(&peer->list); + kfree(peer); + } +-- +2.43.0 + diff --git a/queue-6.12/wifi-ath9k-add-range-check-for-conn_rsp_epid-in-htc_.patch b/queue-6.12/wifi-ath9k-add-range-check-for-conn_rsp_epid-in-htc_.patch new file mode 100644 index 00000000000..28d94b34051 --- /dev/null +++ b/queue-6.12/wifi-ath9k-add-range-check-for-conn_rsp_epid-in-htc_.patch @@ -0,0 +1,61 @@ +From d32a96c0cb6dfbcfe3db304bb0fbcaa874e32d7a Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Sat, 14 Sep 2024 12:06:03 +0300 +Subject: wifi: ath9k: add range check for conn_rsp_epid in + htc_connect_service() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Jeongjun Park <aha310510@gmail.com> + +[ Upstream commit 8619593634cbdf5abf43f5714df49b04e4ef09ab ] + +I found the following bug in my fuzzer: + + UBSAN: array-index-out-of-bounds in drivers/net/wireless/ath/ath9k/htc_hst.c:26:51 + index 255 is out of range for type 'htc_endpoint [22]' + CPU: 0 UID: 0 PID: 8 Comm: kworker/0:0 Not tainted 6.11.0-rc6-dirty #14 + Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.15.0-1 04/01/2014 + Workqueue: events request_firmware_work_func + Call Trace: + <TASK> + dump_stack_lvl+0x180/0x1b0 + __ubsan_handle_out_of_bounds+0xd4/0x130 + htc_issue_send.constprop.0+0x20c/0x230 + ? _raw_spin_unlock_irqrestore+0x3c/0x70 + ath9k_wmi_cmd+0x41d/0x610 + ? mark_held_locks+0x9f/0xe0 + ... + +Since this bug has been confirmed to be caused by insufficient verification +of conn_rsp_epid, I think it would be appropriate to add a range check for +conn_rsp_epid to htc_connect_service() to prevent the bug from occurring. + +Fixes: fb9987d0f748 ("ath9k_htc: Support for AR9271 chipset.") +Signed-off-by: Jeongjun Park <aha310510@gmail.com> +Acked-by: Toke Høiland-Jørgensen <toke@toke.dk> +Signed-off-by: Kalle Valo <quic_kvalo@quicinc.com> +Link: https://patch.msgid.link/20240909103855.68006-1-aha310510@gmail.com +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/net/wireless/ath/ath9k/htc_hst.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/net/wireless/ath/ath9k/htc_hst.c b/drivers/net/wireless/ath/ath9k/htc_hst.c +index eb631fd3336d8..b5257b2b4aa52 100644 +--- a/drivers/net/wireless/ath/ath9k/htc_hst.c ++++ b/drivers/net/wireless/ath/ath9k/htc_hst.c +@@ -294,6 +294,9 @@ int htc_connect_service(struct htc_target *target, + return -ETIMEDOUT; + } + ++ if (target->conn_rsp_epid < 0 || target->conn_rsp_epid >= ENDPOINT_MAX) ++ return -EINVAL; ++ + *conn_rsp_epid = target->conn_rsp_epid; + return 0; + err: +-- +2.43.0 + diff --git a/queue-6.12/wifi-cfg80211-check-radio-iface-combination-for-mult.patch b/queue-6.12/wifi-cfg80211-check-radio-iface-combination-for-mult.patch new file mode 100644 index 00000000000..f8982ace436 --- /dev/null +++ b/queue-6.12/wifi-cfg80211-check-radio-iface-combination-for-mult.patch @@ -0,0 +1,137 @@ +From 81171c1120cdf8e560c796900ddcf3f0d72dda22 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Tue, 17 Sep 2024 19:32:39 +0530 +Subject: wifi: cfg80211: check radio iface combination for multi radio per + wiphy + +From: Karthikeyan Periyasamy <quic_periyasa@quicinc.com> + +[ Upstream commit bd9813d13be439851a7ff3e6372e53caa6e387a6 ] + +Currently, wiphy_verify_combinations() fails for the multi-radio per wiphy +due to the condition check on new global interface combination that DFS +only works on one channel. In a multi-radio scenario, new global interface +combination encompasses the capabilities of all radio combinations, so it +supports more than one channel with DFS. For multi-radio per wiphy, +interface combination verification needs to be performed for radio specific +interface combinations. This is necessary as the new global interface +combination combines the capabilities of all radio combinations. + +Fixes: a01b1e9f9955 ("wifi: mac80211: add support for DFS with multiple radios") +Signed-off-by: Karthikeyan Periyasamy <quic_periyasa@quicinc.com> +Link: https://patch.msgid.link/20240917140239.886083-1-quic_periyasa@quicinc.com +Signed-off-by: Johannes Berg <johannes.berg@intel.com> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + net/wireless/core.c | 64 ++++++++++++++++++++++++++++++++++++++------- + 1 file changed, 54 insertions(+), 10 deletions(-) + +diff --git a/net/wireless/core.c b/net/wireless/core.c +index 74ca18833df17..7d313fb66d76b 100644 +--- a/net/wireless/core.c ++++ b/net/wireless/core.c +@@ -603,16 +603,20 @@ struct wiphy *wiphy_new_nm(const struct cfg80211_ops *ops, int sizeof_priv, + } + EXPORT_SYMBOL(wiphy_new_nm); + +-static int wiphy_verify_combinations(struct wiphy *wiphy) ++static ++int wiphy_verify_iface_combinations(struct wiphy *wiphy, ++ const struct ieee80211_iface_combination *iface_comb, ++ int n_iface_comb, ++ bool combined_radio) + { + const struct ieee80211_iface_combination *c; + int i, j; + +- for (i = 0; i < wiphy->n_iface_combinations; i++) { ++ for (i = 0; i < n_iface_comb; i++) { + u32 cnt = 0; + u16 all_iftypes = 0; + +- c = &wiphy->iface_combinations[i]; ++ c = &iface_comb[i]; + + /* + * Combinations with just one interface aren't real, +@@ -625,9 +629,13 @@ static int wiphy_verify_combinations(struct wiphy *wiphy) + if (WARN_ON(!c->num_different_channels)) + return -EINVAL; + +- /* DFS only works on one channel. */ +- if (WARN_ON(c->radar_detect_widths && +- (c->num_different_channels > 1))) ++ /* DFS only works on one channel. Avoid this check ++ * for multi-radio global combination, since it hold ++ * the capabilities of all radio combinations. ++ */ ++ if (!combined_radio && ++ WARN_ON(c->radar_detect_widths && ++ c->num_different_channels > 1)) + return -EINVAL; + + if (WARN_ON(!c->n_limits)) +@@ -648,13 +656,21 @@ static int wiphy_verify_combinations(struct wiphy *wiphy) + if (WARN_ON(wiphy->software_iftypes & types)) + return -EINVAL; + +- /* Only a single P2P_DEVICE can be allowed */ +- if (WARN_ON(types & BIT(NL80211_IFTYPE_P2P_DEVICE) && ++ /* Only a single P2P_DEVICE can be allowed, avoid this ++ * check for multi-radio global combination, since it ++ * hold the capabilities of all radio combinations. ++ */ ++ if (!combined_radio && ++ WARN_ON(types & BIT(NL80211_IFTYPE_P2P_DEVICE) && + c->limits[j].max > 1)) + return -EINVAL; + +- /* Only a single NAN can be allowed */ +- if (WARN_ON(types & BIT(NL80211_IFTYPE_NAN) && ++ /* Only a single NAN can be allowed, avoid this ++ * check for multi-radio global combination, since it ++ * hold the capabilities of all radio combinations. ++ */ ++ if (!combined_radio && ++ WARN_ON(types & BIT(NL80211_IFTYPE_NAN) && + c->limits[j].max > 1)) + return -EINVAL; + +@@ -693,6 +709,34 @@ static int wiphy_verify_combinations(struct wiphy *wiphy) + return 0; + } + ++static int wiphy_verify_combinations(struct wiphy *wiphy) ++{ ++ int i, ret; ++ bool combined_radio = false; ++ ++ if (wiphy->n_radio) { ++ for (i = 0; i < wiphy->n_radio; i++) { ++ const struct wiphy_radio *radio = &wiphy->radio[i]; ++ ++ ret = wiphy_verify_iface_combinations(wiphy, ++ radio->iface_combinations, ++ radio->n_iface_combinations, ++ false); ++ if (ret) ++ return ret; ++ } ++ ++ combined_radio = true; ++ } ++ ++ ret = wiphy_verify_iface_combinations(wiphy, ++ wiphy->iface_combinations, ++ wiphy->n_iface_combinations, ++ combined_radio); ++ ++ return ret; ++} ++ + int wiphy_register(struct wiphy *wiphy) + { + struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy); +-- +2.43.0 + diff --git a/queue-6.12/wifi-cfg80211-remove-the-medium-synchronization-dela.patch b/queue-6.12/wifi-cfg80211-remove-the-medium-synchronization-dela.patch new file mode 100644 index 00000000000..c4a5405ad89 --- /dev/null +++ b/queue-6.12/wifi-cfg80211-remove-the-medium-synchronization-dela.patch @@ -0,0 +1,64 @@ +From 03d627598b82315f8a0289bcd22a4e82577e86ed Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Thu, 31 Oct 2024 21:42:23 +0800 +Subject: wifi: cfg80211: Remove the Medium Synchronization Delay validity + check + +From: Lingbo Kong <quic_lingbok@quicinc.com> + +[ Upstream commit b4ebb58cb9a4b1b5cb5278b09d6afdcd71b2a6b4 ] + +Currently, when the driver attempts to connect to an AP MLD with multiple +APs, the cfg80211_mlme_check_mlo_compat() function requires the Medium +Synchronization Delay values from different APs of the same AP MLD to be +equal, which may result in connection failures. + +This is because when the driver receives a multi-link probe response from +an AP MLD with multiple APs, cfg80211 updates the Elements for each AP +based on the multi-link probe response. If the Medium Synchronization Delay +is set in the multi-link probe response, the Elements for each AP belonging +to the same AP MLD will have the Medium Synchronization Delay set +simultaneously. If non-multi-link probe responses are received from +different APs of the same MLD AP, cfg80211 will still update the Elements +based on the non-multi-link probe response. Since the non-multi-link probe +response does not set the Medium Synchronization Delay +(IEEE 802.11be-2024-35.3.4.4), if the Elements from a non-multi-link probe +response overwrite those from a multi-link probe response that has set the +Medium Synchronization Delay, the Medium Synchronization Delay values for +APs belonging to the same AP MLD will not be equal. This discrepancy causes +the cfg80211_mlme_check_mlo_compat() function to fail, leading to +connection failures. Commit ccb964b4ab16 +("wifi: cfg80211: validate MLO connections better") did not take this into +account. + +To address this issue, remove this validity check. + +Fixes: ccb964b4ab16 ("wifi: cfg80211: validate MLO connections better") +Signed-off-by: Lingbo Kong <quic_lingbok@quicinc.com> +Link: https://patch.msgid.link/20241031134223.970-1-quic_lingbok@quicinc.com +Signed-off-by: Johannes Berg <johannes.berg@intel.com> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + net/wireless/mlme.c | 6 ------ + 1 file changed, 6 deletions(-) + +diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c +index 4dac818547210..a5eb92d93074e 100644 +--- a/net/wireless/mlme.c ++++ b/net/wireless/mlme.c +@@ -340,12 +340,6 @@ cfg80211_mlme_check_mlo_compat(const struct ieee80211_multi_link_elem *mle_a, + return -EINVAL; + } + +- if (ieee80211_mle_get_eml_med_sync_delay((const u8 *)mle_a) != +- ieee80211_mle_get_eml_med_sync_delay((const u8 *)mle_b)) { +- NL_SET_ERR_MSG(extack, "link EML medium sync delay mismatch"); +- return -EINVAL; +- } +- + if (ieee80211_mle_get_eml_cap((const u8 *)mle_a) != + ieee80211_mle_get_eml_cap((const u8 *)mle_b)) { + NL_SET_ERR_MSG(extack, "link EML capabilities mismatch"); +-- +2.43.0 + diff --git a/queue-6.12/wifi-cw1200-fix-potential-null-dereference.patch b/queue-6.12/wifi-cw1200-fix-potential-null-dereference.patch new file mode 100644 index 00000000000..e4fbc90c95a --- /dev/null +++ b/queue-6.12/wifi-cw1200-fix-potential-null-dereference.patch @@ -0,0 +1,40 @@ +From f615311c8c55f5f52e256b211c17bba72f701dce Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Mon, 28 Oct 2024 23:06:53 +0100 +Subject: wifi: cw1200: Fix potential NULL dereference + +From: Linus Walleij <linus.walleij@linaro.org> + +[ Upstream commit 2b94751626a6d49bbe42a19cc1503bd391016bd5 ] + +A recent refactoring was identified by static analysis to +cause a potential NULL dereference, fix this! + +Reported-by: kernel test robot <lkp@intel.com> +Reported-by: Dan Carpenter <dan.carpenter@linaro.org> +Closes: https://lore.kernel.org/r/202410121505.nyghqEkK-lkp@intel.com/ +Fixes: 2719a9e7156c ("wifi: cw1200: Convert to GPIO descriptors") +Signed-off-by: Linus Walleij <linus.walleij@linaro.org> +Signed-off-by: Kalle Valo <kvalo@kernel.org> +Link: https://patch.msgid.link/20241028-cw1200-fix-v1-1-e092b6558d1e@linaro.org +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/net/wireless/st/cw1200/cw1200_spi.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/wireless/st/cw1200/cw1200_spi.c b/drivers/net/wireless/st/cw1200/cw1200_spi.c +index 4f346fb977a98..862964a8cc876 100644 +--- a/drivers/net/wireless/st/cw1200/cw1200_spi.c ++++ b/drivers/net/wireless/st/cw1200/cw1200_spi.c +@@ -450,7 +450,7 @@ static int __maybe_unused cw1200_spi_suspend(struct device *dev) + { + struct hwbus_priv *self = spi_get_drvdata(to_spi_device(dev)); + +- if (!cw1200_can_suspend(self->core)) ++ if (self && !cw1200_can_suspend(self->core)) + return -EAGAIN; + + /* XXX notify host that we have to keep CW1200 powered on? */ +-- +2.43.0 + diff --git a/queue-6.12/wifi-iwlwifi-allow-fast-resume-on-ax200.patch b/queue-6.12/wifi-iwlwifi-allow-fast-resume-on-ax200.patch new file mode 100644 index 00000000000..b9b6f35a201 --- /dev/null +++ b/queue-6.12/wifi-iwlwifi-allow-fast-resume-on-ax200.patch @@ -0,0 +1,40 @@ +From 35d57957947959c2fdf4cdc105b1726a5a2f3679 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Mon, 28 Oct 2024 13:54:53 +0200 +Subject: wifi: iwlwifi: allow fast resume on ax200 + +From: Emmanuel Grumbach <emmanuel.grumbach@intel.com> + +[ Upstream commit e53ebc72054efca12e0329d69342e3daf7250a5a ] + +This feature can be used on ax200 as well. It'll avoid to restart the +firmware upon suspend / resume flow. Doing so also avoids releasing and +re-allocating all the device related memory which makes the memory's +subsystem task easier. + +Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com> +Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com> +Link: https://patch.msgid.link/20241028135215.514efe0ce4c7.I60061277526302a75cadbba10452e94c54763f13@changeid +Signed-off-by: Johannes Berg <johannes.berg@intel.com> +Stable-dep-of: d1a54ec21b8e ("wifi: iwlwifi: mvm: tell iwlmei when we finished suspending") +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c +index 80b9a115245fe..eee7a385d9467 100644 +--- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c ++++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c +@@ -1377,7 +1377,7 @@ void __iwl_mvm_mac_stop(struct iwl_mvm *mvm, bool suspend) + iwl_mvm_rm_aux_sta(mvm); + + if (suspend && +- mvm->trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_AX210) ++ mvm->trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_22000) + iwl_mvm_fast_suspend(mvm); + else + iwl_mvm_stop_device(mvm); +-- +2.43.0 + diff --git a/queue-6.12/wifi-iwlwifi-mvm-tell-iwlmei-when-we-finished-suspen.patch b/queue-6.12/wifi-iwlwifi-mvm-tell-iwlmei-when-we-finished-suspen.patch new file mode 100644 index 00000000000..825d51171f5 --- /dev/null +++ b/queue-6.12/wifi-iwlwifi-mvm-tell-iwlmei-when-we-finished-suspen.patch @@ -0,0 +1,61 @@ +From 3dc7cd6e065f3c68d607611e96bd7c37abe5130d Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Mon, 28 Oct 2024 13:54:54 +0200 +Subject: wifi: iwlwifi: mvm: tell iwlmei when we finished suspending + +From: Emmanuel Grumbach <emmanuel.grumbach@intel.com> + +[ Upstream commit d1a54ec21b8e7bca59141ff1ac6ce73e07d744f2 ] + +Since we no longer shut down the device in suspend, we also no longer +call iwl_mvm_mei_device_state() and this is a problem because iwlmei +expects this to be called when it runs its own suspend sequence. It +checks mei->device_down in iwl_mei_remove() which is called upon +suspend. + +Fix this by telling iwlmei when we're done accessing the device. +When we'll wake up, the device should be untouched if CSME didn't use it +during the suspend time. If CSME used it, we'll notice it through the +CSR_FUNC_SCRATCH register. + +Fixes: e8bb19c1d590 ("wifi: iwlwifi: support fast resume") +Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com> +Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com> +Link: https://patch.msgid.link/20241028135215.525287b90af2.Ibf183824471ea5580d9276d104444e53191e6900@changeid +Signed-off-by: Johannes Berg <johannes.berg@intel.com> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c +index eee7a385d9467..d37d83d246354 100644 +--- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c ++++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c +@@ -1237,6 +1237,7 @@ int __iwl_mvm_mac_start(struct iwl_mvm *mvm) + fast_resume = mvm->fast_resume; + + if (fast_resume) { ++ iwl_mvm_mei_device_state(mvm, true); + ret = iwl_mvm_fast_resume(mvm); + if (ret) { + iwl_mvm_stop_device(mvm); +@@ -1377,10 +1378,13 @@ void __iwl_mvm_mac_stop(struct iwl_mvm *mvm, bool suspend) + iwl_mvm_rm_aux_sta(mvm); + + if (suspend && +- mvm->trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_22000) ++ mvm->trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_22000) { + iwl_mvm_fast_suspend(mvm); +- else ++ /* From this point on, we won't touch the device */ ++ iwl_mvm_mei_device_state(mvm, false); ++ } else { + iwl_mvm_stop_device(mvm); ++ } + + iwl_mvm_async_handlers_purge(mvm); + /* async_handlers_list is empty and will stay empty: HW is stopped */ +-- +2.43.0 + diff --git a/queue-6.12/wifi-mwifiex-add-missing-locking-for-cfg80211-calls.patch b/queue-6.12/wifi-mwifiex-add-missing-locking-for-cfg80211-calls.patch new file mode 100644 index 00000000000..667f41ce7d2 --- /dev/null +++ b/queue-6.12/wifi-mwifiex-add-missing-locking-for-cfg80211-calls.patch @@ -0,0 +1,56 @@ +From 47a5555dd84f0c6c8e843393678bab06713b6da6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Wed, 18 Sep 2024 13:10:26 +0200 +Subject: wifi: mwifiex: add missing locking for cfg80211 calls + +From: Sascha Hauer <s.hauer@pengutronix.de> + +[ Upstream commit 0d7c2194f17c764df0354af13551cc6f92ef5a44 ] + +cfg80211_rx_assoc_resp() and cfg80211_rx_mlme_mgmt() need to be called +with the wiphy locked, so lock it before calling these functions. + +Fixes: 36995892c271 ("wifi: mwifiex: add host mlme for client mode") +Reviewed-by: Francesco Dolcini <francesco.dolcini@toradex.com> +Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> +Acked-by: Brian Norris <briannorris@chromium.org> +Signed-off-by: Kalle Valo <kvalo@kernel.org> +Link: https://patch.msgid.link/20240918-mwifiex-cleanup-1-v2-1-2d0597187d3c@pengutronix.de +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/net/wireless/marvell/mwifiex/cmdevt.c | 2 ++ + drivers/net/wireless/marvell/mwifiex/util.c | 2 ++ + 2 files changed, 4 insertions(+) + +diff --git a/drivers/net/wireless/marvell/mwifiex/cmdevt.c b/drivers/net/wireless/marvell/mwifiex/cmdevt.c +index 1cff001bdc514..b30ed321c6251 100644 +--- a/drivers/net/wireless/marvell/mwifiex/cmdevt.c ++++ b/drivers/net/wireless/marvell/mwifiex/cmdevt.c +@@ -938,8 +938,10 @@ void mwifiex_process_assoc_resp(struct mwifiex_adapter *adapter) + assoc_resp.links[0].bss = priv->req_bss; + assoc_resp.buf = priv->assoc_rsp_buf; + assoc_resp.len = priv->assoc_rsp_size; ++ wiphy_lock(priv->wdev.wiphy); + cfg80211_rx_assoc_resp(priv->netdev, + &assoc_resp); ++ wiphy_unlock(priv->wdev.wiphy); + priv->assoc_rsp_size = 0; + } + } +diff --git a/drivers/net/wireless/marvell/mwifiex/util.c b/drivers/net/wireless/marvell/mwifiex/util.c +index 42c04bf858da3..1f1f6280a0f25 100644 +--- a/drivers/net/wireless/marvell/mwifiex/util.c ++++ b/drivers/net/wireless/marvell/mwifiex/util.c +@@ -494,7 +494,9 @@ mwifiex_process_mgmt_packet(struct mwifiex_private *priv, + } + } + ++ wiphy_lock(priv->wdev.wiphy); + cfg80211_rx_mlme_mgmt(priv->netdev, skb->data, pkt_len); ++ wiphy_unlock(priv->wdev.wiphy); + } + + if (priv->adapter->host_mlme_enabled && +-- +2.43.0 + diff --git a/queue-6.12/wifi-mwifiex-fix-memcpy-field-spanning-write-warning.patch b/queue-6.12/wifi-mwifiex-fix-memcpy-field-spanning-write-warning.patch new file mode 100644 index 00000000000..02ca8febe75 --- /dev/null +++ b/queue-6.12/wifi-mwifiex-fix-memcpy-field-spanning-write-warning.patch @@ -0,0 +1,56 @@ +From 8cb5010bf3fc2f75f0c68b19b2cdb8ec9c9fd007 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Tue, 8 Oct 2024 01:20:54 +0300 +Subject: wifi: mwifiex: Fix memcpy() field-spanning write warning in + mwifiex_config_scan() + +From: Alper Nebi Yasak <alpernebiyasak@gmail.com> + +[ Upstream commit d241a139c2e9f8a479f25c75ebd5391e6a448500 ] + +Replace one-element array with a flexible-array member in `struct +mwifiex_ie_types_wildcard_ssid_params` to fix the following warning +on a MT8173 Chromebook (mt8173-elm-hana): + +[ 356.775250] ------------[ cut here ]------------ +[ 356.784543] memcpy: detected field-spanning write (size 6) of single field "wildcard_ssid_tlv->ssid" at drivers/net/wireless/marvell/mwifiex/scan.c:904 (size 1) +[ 356.813403] WARNING: CPU: 3 PID: 742 at drivers/net/wireless/marvell/mwifiex/scan.c:904 mwifiex_scan_networks+0x4fc/0xf28 [mwifiex] + +The "(size 6)" above is exactly the length of the SSID of the network +this device was connected to. The source of the warning looks like: + + ssid_len = user_scan_in->ssid_list[i].ssid_len; + [...] + memcpy(wildcard_ssid_tlv->ssid, + user_scan_in->ssid_list[i].ssid, ssid_len); + +There is a #define WILDCARD_SSID_TLV_MAX_SIZE that uses sizeof() on this +struct, but it already didn't account for the size of the one-element +array, so it doesn't need to be changed. + +Fixes: 5e6e3a92b9a4 ("wireless: mwifiex: initial commit for Marvell mwifiex driver") +Signed-off-by: Alper Nebi Yasak <alpernebiyasak@gmail.com> +Acked-by: Brian Norris <briannorris@chromium.org> +Signed-off-by: Kalle Valo <kvalo@kernel.org> +Link: https://patch.msgid.link/20241007222301.24154-1-alpernebiyasak@gmail.com +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/net/wireless/marvell/mwifiex/fw.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/wireless/marvell/mwifiex/fw.h b/drivers/net/wireless/marvell/mwifiex/fw.h +index d03129d5d24e3..4a96281792cc1 100644 +--- a/drivers/net/wireless/marvell/mwifiex/fw.h ++++ b/drivers/net/wireless/marvell/mwifiex/fw.h +@@ -875,7 +875,7 @@ struct mwifiex_ietypes_chanstats { + struct mwifiex_ie_types_wildcard_ssid_params { + struct mwifiex_ie_types_header header; + u8 max_ssid_length; +- u8 ssid[1]; ++ u8 ssid[]; + } __packed; + + #define TSF_DATA_SIZE 8 +-- +2.43.0 + diff --git a/queue-6.12/wifi-mwifiex-use-irqf_no_autoen-flag-in-request_irq.patch b/queue-6.12/wifi-mwifiex-use-irqf_no_autoen-flag-in-request_irq.patch new file mode 100644 index 00000000000..78cc6ebbef7 --- /dev/null +++ b/queue-6.12/wifi-mwifiex-use-irqf_no_autoen-flag-in-request_irq.patch @@ -0,0 +1,48 @@ +From 7e024a8eed63c9ca2496bf2d3d78fa68d3d70040 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Tue, 10 Sep 2024 20:43:13 +0800 +Subject: wifi: mwifiex: Use IRQF_NO_AUTOEN flag in request_irq() + +From: Jinjie Ruan <ruanjinjie@huawei.com> + +[ Upstream commit 9a98dd48b6d834d7a3fe5e8e7b8c3a1d006f9685 ] + +disable_irq() after request_irq() still has a time gap in which +interrupts can come. request_irq() with IRQF_NO_AUTOEN flag will +disable IRQ auto-enable when request IRQ. + +Fixes: 853402a00823 ("mwifiex: Enable WoWLAN for both sdio and pcie") +Signed-off-by: Jinjie Ruan <ruanjinjie@huawei.com> +Acked-by: Brian Norris <briannorris@chromium.org> +Signed-off-by: Kalle Valo <kvalo@kernel.org> +Link: https://patch.msgid.link/20240910124314.698896-3-ruanjinjie@huawei.com +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/net/wireless/marvell/mwifiex/main.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/wireless/marvell/mwifiex/main.c b/drivers/net/wireless/marvell/mwifiex/main.c +index 96d1f6039fbca..855019fe54858 100644 +--- a/drivers/net/wireless/marvell/mwifiex/main.c ++++ b/drivers/net/wireless/marvell/mwifiex/main.c +@@ -1679,7 +1679,8 @@ static void mwifiex_probe_of(struct mwifiex_adapter *adapter) + } + + ret = devm_request_irq(dev, adapter->irq_wakeup, +- mwifiex_irq_wakeup_handler, IRQF_TRIGGER_LOW, ++ mwifiex_irq_wakeup_handler, ++ IRQF_TRIGGER_LOW | IRQF_NO_AUTOEN, + "wifi_wake", adapter); + if (ret) { + dev_err(dev, "Failed to request irq_wakeup %d (%d)\n", +@@ -1687,7 +1688,6 @@ static void mwifiex_probe_of(struct mwifiex_adapter *adapter) + goto err_exit; + } + +- disable_irq(adapter->irq_wakeup); + if (device_init_wakeup(dev, true)) { + dev_err(dev, "fail to init wakeup for mwifiex\n"); + goto err_exit; +-- +2.43.0 + diff --git a/queue-6.12/wifi-p54-use-irqf_no_autoen-flag-in-request_irq.patch b/queue-6.12/wifi-p54-use-irqf_no_autoen-flag-in-request_irq.patch new file mode 100644 index 00000000000..b9a35acd6e9 --- /dev/null +++ b/queue-6.12/wifi-p54-use-irqf_no_autoen-flag-in-request_irq.patch @@ -0,0 +1,47 @@ +From 6defc44c33338c94d13d476b75d9947f49a0b590 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Tue, 10 Sep 2024 20:43:12 +0800 +Subject: wifi: p54: Use IRQF_NO_AUTOEN flag in request_irq() + +From: Jinjie Ruan <ruanjinjie@huawei.com> + +[ Upstream commit bcd1371bd85e560ccc9159b7747f94bfe43b77a6 ] + +disable_irq() after request_irq() still has a time gap in which +interrupts can come. request_irq() with IRQF_NO_AUTOEN flag will +disable IRQ auto-enable when request IRQ. + +Fixes: cd8d3d321285 ("p54spi: p54spi driver") +Signed-off-by: Jinjie Ruan <ruanjinjie@huawei.com> +Signed-off-by: Kalle Valo <kvalo@kernel.org> +Link: https://patch.msgid.link/20240910124314.698896-2-ruanjinjie@huawei.com +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/net/wireless/intersil/p54/p54spi.c | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +diff --git a/drivers/net/wireless/intersil/p54/p54spi.c b/drivers/net/wireless/intersil/p54/p54spi.c +index d33a994906a7b..27f44a9f0bc1f 100644 +--- a/drivers/net/wireless/intersil/p54/p54spi.c ++++ b/drivers/net/wireless/intersil/p54/p54spi.c +@@ -624,7 +624,7 @@ static int p54spi_probe(struct spi_device *spi) + gpio_direction_input(p54spi_gpio_irq); + + ret = request_irq(gpio_to_irq(p54spi_gpio_irq), +- p54spi_interrupt, 0, "p54spi", ++ p54spi_interrupt, IRQF_NO_AUTOEN, "p54spi", + priv->spi); + if (ret < 0) { + dev_err(&priv->spi->dev, "request_irq() failed"); +@@ -633,8 +633,6 @@ static int p54spi_probe(struct spi_device *spi) + + irq_set_irq_type(gpio_to_irq(p54spi_gpio_irq), IRQ_TYPE_EDGE_RISING); + +- disable_irq(gpio_to_irq(p54spi_gpio_irq)); +- + INIT_WORK(&priv->work, p54spi_work); + init_completion(&priv->fw_comp); + INIT_LIST_HEAD(&priv->tx_pending); +-- +2.43.0 + diff --git a/queue-6.12/wifi-rtl8xxxu-perform-update_beacon_work-when-beacon.patch b/queue-6.12/wifi-rtl8xxxu-perform-update_beacon_work-when-beacon.patch new file mode 100644 index 00000000000..1b6030b3718 --- /dev/null +++ b/queue-6.12/wifi-rtl8xxxu-perform-update_beacon_work-when-beacon.patch @@ -0,0 +1,49 @@ +From 4924fede4ddb89bdcfdad50ac7e8647cfe65b350 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Mon, 30 Sep 2024 10:49:55 +0200 +Subject: wifi: rtl8xxxu: Perform update_beacon_work when beaconing is enabled + +From: Martin Kaistra <martin.kaistra@linutronix.de> + +[ Upstream commit d7063ed6758c62e00a2f56467ded85a021fac67a ] + +In STA+AP concurrent mode, performing a scan operation on one vif +temporarily stops beacons on the other. When the scan is completed, +beacons are enabled again with BSS_CHANGED_BEACON_ENABLED. + +We can observe that no beacons are being sent when just +rtl8xxxu_start_tx_beacon() is being called. + +Thus, also perform update_beacon_work in order to restore beaconing. + +Fixes: cde8848cad0b ("wifi: rtl8xxxu: Add beacon functions") +Signed-off-by: Martin Kaistra <martin.kaistra@linutronix.de> +Signed-off-by: Ping-Ke Shih <pkshih@realtek.com> +Link: https://patch.msgid.link/20240930084955.455241-1-martin.kaistra@linutronix.de +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/net/wireless/realtek/rtl8xxxu/core.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/wireless/realtek/rtl8xxxu/core.c b/drivers/net/wireless/realtek/rtl8xxxu/core.c +index 7891c988dd5f0..f95898f68d68a 100644 +--- a/drivers/net/wireless/realtek/rtl8xxxu/core.c ++++ b/drivers/net/wireless/realtek/rtl8xxxu/core.c +@@ -5058,10 +5058,12 @@ rtl8xxxu_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + } + + if (changed & BSS_CHANGED_BEACON_ENABLED) { +- if (bss_conf->enable_beacon) ++ if (bss_conf->enable_beacon) { + rtl8xxxu_start_tx_beacon(priv); +- else ++ schedule_delayed_work(&priv->update_beacon_work, 0); ++ } else { + rtl8xxxu_stop_tx_beacon(priv); ++ } + } + + if (changed & BSS_CHANGED_BEACON) +-- +2.43.0 + diff --git a/queue-6.12/wifi-rtw89-coex-check-null-return-of-kmalloc-in-btc_.patch b/queue-6.12/wifi-rtw89-coex-check-null-return-of-kmalloc-in-btc_.patch new file mode 100644 index 00000000000..fc2734d14eb --- /dev/null +++ b/queue-6.12/wifi-rtw89-coex-check-null-return-of-kmalloc-in-btc_.patch @@ -0,0 +1,48 @@ +From 49a7bd78d712ec0322768fe11576babe2b23558c Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Wed, 30 Oct 2024 11:20:58 +0800 +Subject: wifi: rtw89: coex: check NULL return of kmalloc in + btc_fw_set_monreg() + +From: Pei Xiao <xiaopei01@kylinos.cn> + +[ Upstream commit 81df5ed446b448bdc327b7c7f0b50121fc1f4aa2 ] + +kmalloc may fail, return value might be NULL and will cause +NULL pointer dereference. Add check NULL return of kmalloc in +btc_fw_set_monreg(). + +Signed-off-by: Pei Xiao <xiaopei01@kylinos.cn> +Fixes: b952cb0a6e2d ("wifi: rtw89: coex: Add register monitor report v7 format") +Signed-off-by: Ping-Ke Shih <pkshih@realtek.com> +Link: https://patch.msgid.link/516a91f3997534f708af43c7592cbafdd53dd599.1730253508.git.xiaopei01@kylinos.cn +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/net/wireless/realtek/rtw89/coex.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/drivers/net/wireless/realtek/rtw89/coex.c b/drivers/net/wireless/realtek/rtw89/coex.c +index 8c2db2a493c8b..8d54d71fcf539 100644 +--- a/drivers/net/wireless/realtek/rtw89/coex.c ++++ b/drivers/net/wireless/realtek/rtw89/coex.c +@@ -2492,6 +2492,8 @@ static void btc_fw_set_monreg(struct rtw89_dev *rtwdev) + if (ver->fcxmreg == 7) { + sz = struct_size(v7, regs, n); + v7 = kmalloc(sz, GFP_KERNEL); ++ if (!v7) ++ return; + v7->type = RPT_EN_MREG; + v7->fver = ver->fcxmreg; + v7->len = n; +@@ -2506,6 +2508,8 @@ static void btc_fw_set_monreg(struct rtw89_dev *rtwdev) + } else { + sz = struct_size(v1, regs, n); + v1 = kmalloc(sz, GFP_KERNEL); ++ if (!v1) ++ return; + v1->fver = ver->fcxmreg; + v1->reg_num = n; + memcpy(v1->regs, chip->mon_reg, flex_array_size(v1, regs, n)); +-- +2.43.0 + diff --git a/queue-6.12/wifi-rtw89-fix-tx-fail-with-a2dp-after-scanning.patch b/queue-6.12/wifi-rtw89-fix-tx-fail-with-a2dp-after-scanning.patch new file mode 100644 index 00000000000..d9718e9ffbc --- /dev/null +++ b/queue-6.12/wifi-rtw89-fix-tx-fail-with-a2dp-after-scanning.patch @@ -0,0 +1,50 @@ +From a3c645f7a8f7eac46ca570d902153148f19c7471 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Mon, 21 Oct 2024 14:32:19 +0800 +Subject: wifi: rtw89: Fix TX fail with A2DP after scanning + +From: Po-Hao Huang <phhuang@realtek.com> + +[ Upstream commit f16c40acd31901ad0ba2554b60e0e2b0c7b59cde ] + +There might be some racing between BT and WiFi after scan. Since +one of the TX related register will be modified by both FW and +rtw89_set_channel() in driver, which could cause Tx fail. Reorder +the calling sequence to only notify coexistence mechanism after +rtw89_set_channel() is called, so that there are no concurrent +operations. + +Fixes: 5f499ce69b8d ("wifi: rtw89: pause/proceed MCC for ROC and HW scan") +Signed-off-by: Po-Hao Huang <phhuang@realtek.com> +Signed-off-by: Ping-Ke Shih <pkshih@realtek.com> +Link: https://patch.msgid.link/20241021063219.22613-1-pkshih@realtek.com +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/net/wireless/realtek/rtw89/fw.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/wireless/realtek/rtw89/fw.c b/drivers/net/wireless/realtek/rtw89/fw.c +index 37f931e887917..13a7c39ceb6f5 100644 +--- a/drivers/net/wireless/realtek/rtw89/fw.c ++++ b/drivers/net/wireless/realtek/rtw89/fw.c +@@ -6648,6 +6648,8 @@ void rtw89_hw_scan_complete(struct rtw89_dev *rtwdev, + if (!rtwvif_link) + return; + ++ rtw89_chanctx_proceed(rtwdev); ++ + rtwvif = rtwvif_link->rtwvif; + + rtw89_write32_mask(rtwdev, +@@ -6667,8 +6669,6 @@ void rtw89_hw_scan_complete(struct rtw89_dev *rtwdev, + scan_info->last_chan_idx = 0; + scan_info->scanning_vif = NULL; + scan_info->abort = false; +- +- rtw89_chanctx_proceed(rtwdev); + } + + void rtw89_hw_scan_abort(struct rtw89_dev *rtwdev, +-- +2.43.0 + diff --git a/queue-6.12/wifi-rtw89-read-bss_conf-corresponding-to-the-link.patch b/queue-6.12/wifi-rtw89-read-bss_conf-corresponding-to-the-link.patch new file mode 100644 index 00000000000..74dc870c457 --- /dev/null +++ b/queue-6.12/wifi-rtw89-read-bss_conf-corresponding-to-the-link.patch @@ -0,0 +1,1169 @@ +From 6a10cfb25604c20b5d3f697ece4f1cdac84ea53c Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Mon, 16 Sep 2024 13:31:54 +0800 +Subject: wifi: rtw89: read bss_conf corresponding to the link + +From: Zong-Zhe Yang <kevin_yang@realtek.com> + +[ Upstream commit 89bac818bbd2ccced29d4b888ba1a4cf3e1ede4e ] + +Tweak code to not always access vif->bss_conf directly. Instead, +according to link_id, read target bss_conf from vif->link_conf[]. + +For now, rtwvif_link->link_id keeps 0. When driver starts to +support MLO, the link_id will be assigned. + +Signed-off-by: Zong-Zhe Yang <kevin_yang@realtek.com> +Signed-off-by: Ping-Ke Shih <pkshih@realtek.com> +Link: https://patch.msgid.link/20240916053158.47350-4-pkshih@realtek.com +Stable-dep-of: f16c40acd319 ("wifi: rtw89: Fix TX fail with A2DP after scanning") +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/net/wireless/realtek/rtw89/cam.c | 13 ++- + drivers/net/wireless/realtek/rtw89/chan.c | 22 ++++- + drivers/net/wireless/realtek/rtw89/coex.c | 17 +++- + drivers/net/wireless/realtek/rtw89/core.c | 98 +++++++++++++++---- + drivers/net/wireless/realtek/rtw89/core.h | 52 +++++++--- + drivers/net/wireless/realtek/rtw89/fw.c | 96 ++++++++++++------ + drivers/net/wireless/realtek/rtw89/fw.h | 4 +- + drivers/net/wireless/realtek/rtw89/mac.c | 66 ++++++++++--- + drivers/net/wireless/realtek/rtw89/mac80211.c | 24 ++++- + drivers/net/wireless/realtek/rtw89/phy.c | 13 ++- + drivers/net/wireless/realtek/rtw89/ps.c | 24 +++-- + drivers/net/wireless/realtek/rtw89/ps.h | 4 +- + drivers/net/wireless/realtek/rtw89/regd.c | 19 +++- + drivers/net/wireless/realtek/rtw89/wow.c | 12 ++- + 14 files changed, 355 insertions(+), 109 deletions(-) + +diff --git a/drivers/net/wireless/realtek/rtw89/cam.c b/drivers/net/wireless/realtek/rtw89/cam.c +index 80deb0712b834..757f7633b079b 100644 +--- a/drivers/net/wireless/realtek/rtw89/cam.c ++++ b/drivers/net/wireless/realtek/rtw89/cam.c +@@ -655,17 +655,24 @@ int rtw89_cam_fill_bssid_cam_info(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link, u8 *cmd) + { +- struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif_link); + struct rtw89_bssid_cam_entry *bssid_cam = rtw89_get_bssid_cam_of(rtwvif_link, + rtwsta_link); +- u8 bss_color = vif->bss_conf.he_bss_color.color; ++ struct ieee80211_bss_conf *bss_conf; ++ u8 bss_color; + u8 bss_mask; + +- if (vif->bss_conf.nontransmitted) ++ rcu_read_lock(); ++ ++ bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, false); ++ bss_color = bss_conf->he_bss_color.color; ++ ++ if (bss_conf->nontransmitted) + bss_mask = RTW89_BSSID_MATCH_5_BYTES; + else + bss_mask = RTW89_BSSID_MATCH_ALL; + ++ rcu_read_unlock(); ++ + FWCMD_SET_ADDR_BSSID_IDX(cmd, bssid_cam->bssid_cam_idx); + FWCMD_SET_ADDR_BSSID_OFFSET(cmd, bssid_cam->offset); + FWCMD_SET_ADDR_BSSID_LEN(cmd, bssid_cam->len); +diff --git a/drivers/net/wireless/realtek/rtw89/chan.c b/drivers/net/wireless/realtek/rtw89/chan.c +index 2f14ac6687163..2968c299203b8 100644 +--- a/drivers/net/wireless/realtek/rtw89/chan.c ++++ b/drivers/net/wireless/realtek/rtw89/chan.c +@@ -564,8 +564,9 @@ static void rtw89_mcc_fill_role_policy(struct rtw89_dev *rtwdev, + static void rtw89_mcc_fill_role_limit(struct rtw89_dev *rtwdev, + struct rtw89_mcc_role *mcc_role) + { +- struct ieee80211_vif *vif = rtwvif_to_vif(mcc_role->rtwvif_link); ++ struct rtw89_vif_link *rtwvif_link = mcc_role->rtwvif_link; + struct ieee80211_p2p_noa_desc *noa_desc; ++ struct ieee80211_bss_conf *bss_conf; + u32 bcn_intvl_us = ieee80211_tu_to_usec(mcc_role->beacon_interval); + u32 max_toa_us, max_tob_us, max_dur_us; + u32 start_time, interval, duration; +@@ -576,13 +577,18 @@ static void rtw89_mcc_fill_role_limit(struct rtw89_dev *rtwdev, + if (!mcc_role->is_go && !mcc_role->is_gc) + return; + ++ rcu_read_lock(); ++ ++ bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, true); ++ + /* find the first periodic NoA */ + for (i = 0; i < RTW89_P2P_MAX_NOA_NUM; i++) { +- noa_desc = &vif->bss_conf.p2p_noa_attr.desc[i]; ++ noa_desc = &bss_conf->p2p_noa_attr.desc[i]; + if (noa_desc->count == 255) + goto fill; + } + ++ rcu_read_unlock(); + return; + + fill: +@@ -590,6 +596,8 @@ static void rtw89_mcc_fill_role_limit(struct rtw89_dev *rtwdev, + interval = le32_to_cpu(noa_desc->interval); + duration = le32_to_cpu(noa_desc->duration); + ++ rcu_read_unlock(); ++ + if (interval != bcn_intvl_us) { + rtw89_debug(rtwdev, RTW89_DBG_CHAN, + "MCC role limit: mismatch interval: %d vs. %d\n", +@@ -635,12 +643,18 @@ static int rtw89_mcc_fill_role(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, + struct rtw89_mcc_role *role) + { +- struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif_link); ++ struct ieee80211_bss_conf *bss_conf; + const struct rtw89_chan *chan; + + memset(role, 0, sizeof(*role)); + role->rtwvif_link = rtwvif_link; +- role->beacon_interval = vif->bss_conf.beacon_int; ++ ++ rcu_read_lock(); ++ ++ bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, true); ++ role->beacon_interval = bss_conf->beacon_int; ++ ++ rcu_read_unlock(); + + if (!role->beacon_interval) { + rtw89_warn(rtwdev, +diff --git a/drivers/net/wireless/realtek/rtw89/coex.c b/drivers/net/wireless/realtek/rtw89/coex.c +index afd1ff32afc56..be6383ebf4d16 100644 +--- a/drivers/net/wireless/realtek/rtw89/coex.c ++++ b/drivers/net/wireless/realtek/rtw89/coex.c +@@ -7490,6 +7490,7 @@ void rtw89_btc_ntfy_role_info(struct rtw89_dev *rtwdev, + rtwvif_link->chanctx_idx); + struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif_link); + struct ieee80211_sta *sta = rtwsta_to_sta(rtwsta_link); ++ struct ieee80211_bss_conf *bss_conf; + struct rtw89_btc *btc = &rtwdev->btc; + const struct rtw89_btc_ver *ver = btc->ver; + struct rtw89_btc_wl_info *wl = &btc->cx.wl; +@@ -7497,6 +7498,10 @@ void rtw89_btc_ntfy_role_info(struct rtw89_dev *rtwdev, + struct rtw89_btc_wl_link_info *wlinfo = NULL; + u8 mode = 0, rlink_id, link_mode_ori, pta_req_mac_ori, wa_type; + ++ rcu_read_lock(); ++ ++ bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, false); ++ + rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], state=%d\n", state); + rtw89_debug(rtwdev, RTW89_DBG_BTC, + "[BTC], role is STA=%d\n", +@@ -7508,7 +7513,7 @@ void rtw89_btc_ntfy_role_info(struct rtw89_dev *rtwdev, + state == BTC_ROLE_MSTS_STA_CONN_END); + rtw89_debug(rtwdev, RTW89_DBG_BTC, + "[BTC], bcn_period=%d dtim_period=%d\n", +- vif->bss_conf.beacon_int, vif->bss_conf.dtim_period); ++ bss_conf->beacon_int, bss_conf->dtim_period); + + if (rtwsta_link) { + rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], STA mac_id=%d\n", +@@ -7529,8 +7534,10 @@ void rtw89_btc_ntfy_role_info(struct rtw89_dev *rtwdev, + r.mode = mode; + } + +- if (rtwvif_link->wifi_role >= RTW89_WIFI_ROLE_MLME_MAX) ++ if (rtwvif_link->wifi_role >= RTW89_WIFI_ROLE_MLME_MAX) { ++ rcu_read_unlock(); + return; ++ } + + rtw89_debug(rtwdev, RTW89_DBG_BTC, + "[BTC], wifi_role=%d\n", rtwvif_link->wifi_role); +@@ -7540,8 +7547,8 @@ void rtw89_btc_ntfy_role_info(struct rtw89_dev *rtwdev, + r.pid = rtwvif_link->port; + r.active = true; + r.connected = MLME_LINKED; +- r.bcn_period = vif->bss_conf.beacon_int; +- r.dtim_period = vif->bss_conf.dtim_period; ++ r.bcn_period = bss_conf->beacon_int; ++ r.dtim_period = bss_conf->dtim_period; + r.band = chan->band_type; + r.ch = chan->channel; + r.bw = chan->band_width; +@@ -7551,6 +7558,8 @@ void rtw89_btc_ntfy_role_info(struct rtw89_dev *rtwdev, + r.chdef.chan = chan->primary_channel; + ether_addr_copy(r.mac_addr, rtwvif_link->mac_addr); + ++ rcu_read_unlock(); ++ + if (rtwsta_link && vif->type == NL80211_IFTYPE_STATION) + r.mac_id = rtwsta_link->mac_id; + +diff --git a/drivers/net/wireless/realtek/rtw89/core.c b/drivers/net/wireless/realtek/rtw89/core.c +index 2b6a8fe0e53b0..f1db598c60048 100644 +--- a/drivers/net/wireless/realtek/rtw89/core.c ++++ b/drivers/net/wireless/realtek/rtw89/core.c +@@ -571,7 +571,10 @@ static u16 rtw89_core_get_mgmt_rate(struct rtw89_dev *rtwdev, + struct sk_buff *skb = tx_req->skb; + struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); + struct ieee80211_vif *vif = tx_info->control.vif; ++ struct rtw89_vif_link *rtwvif_link = vif_to_rtwvif_safe(vif); ++ struct ieee80211_bss_conf *bss_conf; + u16 lowest_rate; ++ u16 rate; + + if (tx_info->flags & IEEE80211_TX_CTL_NO_CCK_RATE || + (vif && vif->p2p)) +@@ -581,10 +584,23 @@ static u16 rtw89_core_get_mgmt_rate(struct rtw89_dev *rtwdev, + else + lowest_rate = RTW89_HW_RATE_OFDM6; + +- if (!vif || !vif->bss_conf.basic_rates || !tx_req->sta) ++ if (!rtwvif_link) + return lowest_rate; + +- return __ffs(vif->bss_conf.basic_rates) + lowest_rate; ++ rcu_read_lock(); ++ ++ bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, false); ++ if (!bss_conf->basic_rates || !tx_req->sta) { ++ rate = lowest_rate; ++ goto out; ++ } ++ ++ rate = __ffs(bss_conf->basic_rates) + lowest_rate; ++ ++out: ++ rcu_read_unlock(); ++ ++ return rate; + } + + static u8 rtw89_core_tx_get_mac_id(struct rtw89_dev *rtwdev, +@@ -1879,6 +1895,7 @@ struct rtw89_vif_rx_stats_iter_data { + + static void rtw89_stats_trigger_frame(struct rtw89_dev *rtwdev, + struct ieee80211_vif *vif, ++ struct ieee80211_bss_conf *bss_conf, + struct sk_buff *skb) + { + struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv; +@@ -1886,7 +1903,7 @@ static void rtw89_stats_trigger_frame(struct rtw89_dev *rtwdev, + u8 *pos, *end, type, tf_bw; + u16 aid, tf_rua; + +- if (!ether_addr_equal(vif->bss_conf.bssid, tf->ta) || ++ if (!ether_addr_equal(bss_conf->bssid, tf->ta) || + rtwvif_link->wifi_role != RTW89_WIFI_ROLE_STATION || + rtwvif_link->net_type == RTW89_NET_TYPE_NO_LINK) + return; +@@ -2010,6 +2027,7 @@ static void rtw89_vif_rx_stats_iter(void *data, u8 *mac, + struct sk_buff *skb = iter_data->skb; + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; + struct rtw89_rx_phy_ppdu *phy_ppdu = iter_data->phy_ppdu; ++ struct ieee80211_bss_conf *bss_conf; + const u8 *bssid = iter_data->bssid; + + if (rtwdev->scanning && +@@ -2017,16 +2035,19 @@ static void rtw89_vif_rx_stats_iter(void *data, u8 *mac, + ieee80211_is_probe_resp(hdr->frame_control))) + rtw89_core_cancel_6ghz_probe_tx(rtwdev, skb); + +- if (!vif->bss_conf.bssid) +- return; ++ rcu_read_lock(); ++ ++ bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, false); ++ if (!bss_conf->bssid) ++ goto out; + + if (ieee80211_is_trigger(hdr->frame_control)) { +- rtw89_stats_trigger_frame(rtwdev, vif, skb); +- return; ++ rtw89_stats_trigger_frame(rtwdev, vif, bss_conf, skb); ++ goto out; + } + +- if (!ether_addr_equal(vif->bss_conf.bssid, bssid)) +- return; ++ if (!ether_addr_equal(bss_conf->bssid, bssid)) ++ goto out; + + if (ieee80211_is_beacon(hdr->frame_control)) { + if (vif->type == NL80211_IFTYPE_STATION && +@@ -2037,13 +2058,16 @@ static void rtw89_vif_rx_stats_iter(void *data, u8 *mac, + pkt_stat->beacon_nr++; + } + +- if (!ether_addr_equal(vif->addr, hdr->addr1)) +- return; ++ if (!ether_addr_equal(bss_conf->addr, hdr->addr1)) ++ goto out; + + if (desc_info->data_rate < RTW89_HW_RATE_NR) + pkt_stat->rx_rate_cnt[desc_info->data_rate]++; + + rtw89_traffic_stats_accu(rtwdev, &rtwvif_link->stats, skb, false); ++ ++out: ++ rcu_read_unlock(); + } + + static void rtw89_core_rx_stats(struct rtw89_dev *rtwdev, +@@ -3008,7 +3032,7 @@ static int rtw89_core_send_nullfunc(struct rtw89_dev *rtwdev, + return 0; + + rcu_read_lock(); +- sta = ieee80211_find_sta(vif, vif->bss_conf.bssid); ++ sta = ieee80211_find_sta(vif, vif->cfg.ap_addr); + if (!sta) { + ret = -EINVAL; + goto out; +@@ -3241,14 +3265,16 @@ static void rtw89_core_rfk_track(struct rtw89_dev *rtwdev) + rtw89_chip_rfk_track(rtwdev); + } + +-void rtw89_core_update_p2p_ps(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif) ++void rtw89_core_update_p2p_ps(struct rtw89_dev *rtwdev, ++ struct rtw89_vif_link *rtwvif_link, ++ struct ieee80211_bss_conf *bss_conf) + { + enum rtw89_entity_mode mode = rtw89_get_entity_mode(rtwdev); + + if (mode == RTW89_ENTITY_MODE_MCC) + rtw89_queue_chanctx_change(rtwdev, RTW89_CHANCTX_P2P_PS_CHANGE); + else +- rtw89_process_p2p_ps(rtwdev, vif); ++ rtw89_process_p2p_ps(rtwdev, rtwvif_link, bss_conf); + } + + void rtw89_traffic_stats_init(struct rtw89_dev *rtwdev, +@@ -3410,6 +3436,7 @@ int rtw89_core_release_sta_ba_entry(struct rtw89_dev *rtwdev, + void rtw89_vif_type_mapping(struct ieee80211_vif *vif, bool assoc) + { + struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv; ++ const struct ieee80211_bss_conf *bss_conf; + + switch (vif->type) { + case NL80211_IFTYPE_STATION: +@@ -3445,7 +3472,11 @@ void rtw89_vif_type_mapping(struct ieee80211_vif *vif, bool assoc) + case NL80211_IFTYPE_STATION: + if (assoc) { + rtwvif_link->net_type = RTW89_NET_TYPE_INFRA; +- rtwvif_link->trigger = vif->bss_conf.he_support; ++ ++ rcu_read_lock(); ++ bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, false); ++ rtwvif_link->trigger = bss_conf->he_support; ++ rcu_read_unlock(); + } else { + rtwvif_link->net_type = RTW89_NET_TYPE_NO_LINK; + rtwvif_link->trigger = false; +@@ -3656,12 +3687,17 @@ int rtw89_core_sta_assoc(struct rtw89_dev *rtwdev, + rtw89_mac_bf_monitor_calc(rtwdev, sta, false); + + if (vif->type == NL80211_IFTYPE_STATION && !sta->tdls) { +- struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; ++ struct ieee80211_bss_conf *bss_conf; ++ ++ rcu_read_lock(); + ++ bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, true); + if (bss_conf->he_support && + !(bss_conf->he_oper.params & IEEE80211_HE_OPERATION_ER_SU_DISABLE)) + rtwsta_link->er_cap = true; + ++ rcu_read_unlock(); ++ + rtw89_btc_ntfy_role_info(rtwdev, rtwvif_link, rtwsta_link, + BTC_ROLE_MSTS_STA_CONN_END); + rtw89_core_get_no_ul_ofdma_htc(rtwdev, &rtwsta_link->htc_template, chan); +@@ -4480,11 +4516,18 @@ void rtw89_core_scan_complete(struct rtw89_dev *rtwdev, + { + struct rtw89_vif_link *rtwvif_link = + vif ? (struct rtw89_vif_link *)vif->drv_priv : NULL; ++ struct ieee80211_bss_conf *bss_conf; + + if (!rtwvif_link) + return; + +- ether_addr_copy(rtwvif_link->mac_addr, vif->addr); ++ rcu_read_lock(); ++ ++ bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, true); ++ ether_addr_copy(rtwvif_link->mac_addr, bss_conf->addr); ++ ++ rcu_read_unlock(); ++ + rtw89_fw_h2c_cam(rtwdev, rtwvif_link, NULL, NULL); + + rtw89_chip_rfk_scan(rtwdev, rtwvif_link, false); +@@ -4700,6 +4743,27 @@ int rtw89_chip_info_setup(struct rtw89_dev *rtwdev) + } + EXPORT_SYMBOL(rtw89_chip_info_setup); + ++void rtw89_chip_cfg_txpwr_ul_tb_offset(struct rtw89_dev *rtwdev, ++ struct ieee80211_vif *vif) ++{ ++ struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv; ++ const struct rtw89_chip_info *chip = rtwdev->chip; ++ struct ieee80211_bss_conf *bss_conf; ++ ++ rcu_read_lock(); ++ ++ bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, false); ++ if (!bss_conf->he_support || !vif->cfg.assoc) { ++ rcu_read_unlock(); ++ return; ++ } ++ ++ rcu_read_unlock(); ++ ++ if (chip->ops->set_txpwr_ul_tb_offset) ++ chip->ops->set_txpwr_ul_tb_offset(rtwdev, 0, rtwvif_link->mac_idx); ++} ++ + static int rtw89_core_register_hw(struct rtw89_dev *rtwdev) + { + const struct rtw89_chip_info *chip = rtwdev->chip; +diff --git a/drivers/net/wireless/realtek/rtw89/core.h b/drivers/net/wireless/realtek/rtw89/core.h +index 5e22da91213ba..8f66d4fac9aa6 100644 +--- a/drivers/net/wireless/realtek/rtw89/core.h ++++ b/drivers/net/wireless/realtek/rtw89/core.h +@@ -3461,6 +3461,8 @@ struct rtw89_p2p_noa_setter { + }; + + struct rtw89_vif_link { ++ unsigned int link_id; ++ + struct list_head list; + struct rtw89_dev *rtwdev; + struct rtw89_roc roc; +@@ -5994,6 +5996,36 @@ static inline struct rtw89_sta_link *sta_to_rtwsta_safe(struct ieee80211_sta *st + return sta ? (struct rtw89_sta_link *)sta->drv_priv : NULL; + } + ++static inline struct ieee80211_bss_conf * ++__rtw89_vif_rcu_dereference_link(struct rtw89_vif_link *rtwvif_link, bool *nolink) ++{ ++ struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif_link); ++ struct ieee80211_bss_conf *bss_conf; ++ ++ bss_conf = rcu_dereference(vif->link_conf[rtwvif_link->link_id]); ++ if (unlikely(!bss_conf)) { ++ *nolink = true; ++ return &vif->bss_conf; ++ } ++ ++ *nolink = false; ++ return bss_conf; ++} ++ ++#define rtw89_vif_rcu_dereference_link(rtwvif_link, assert) \ ++({ \ ++ typeof(rtwvif_link) p = rtwvif_link; \ ++ struct ieee80211_bss_conf *bss_conf; \ ++ bool nolink; \ ++ \ ++ bss_conf = __rtw89_vif_rcu_dereference_link(p, &nolink); \ ++ if (unlikely(nolink) && (assert)) \ ++ rtw89_err(p->rtwdev, \ ++ "%s: cannot find exact bss_conf for link_id %u\n",\ ++ __func__, p->link_id); \ ++ bss_conf; \ ++}) ++ + static inline u8 rtw89_hw_to_rate_info_bw(enum rtw89_bandwidth hw_bw) + { + if (hw_bw == RTW89_CHANNEL_WIDTH_160) +@@ -6347,20 +6379,6 @@ static inline void rtw89_chip_cfg_txrx_path(struct rtw89_dev *rtwdev) + chip->ops->cfg_txrx_path(rtwdev); + } + +-static inline +-void rtw89_chip_cfg_txpwr_ul_tb_offset(struct rtw89_dev *rtwdev, +- struct ieee80211_vif *vif) +-{ +- struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv; +- const struct rtw89_chip_info *chip = rtwdev->chip; +- +- if (!vif->bss_conf.he_support || !vif->cfg.assoc) +- return; +- +- if (chip->ops->set_txpwr_ul_tb_offset) +- chip->ops->set_txpwr_ul_tb_offset(rtwdev, 0, rtwvif_link->mac_idx); +-} +- + static inline void rtw89_chip_digital_pwr_comp(struct rtw89_dev *rtwdev, + enum rtw89_phy_idx phy_idx) + { +@@ -6653,6 +6671,8 @@ int rtw89_core_release_sta_ba_entry(struct rtw89_dev *rtwdev, + u8 *cam_idx); + void rtw89_vif_type_mapping(struct ieee80211_vif *vif, bool assoc); + int rtw89_chip_info_setup(struct rtw89_dev *rtwdev); ++void rtw89_chip_cfg_txpwr_ul_tb_offset(struct rtw89_dev *rtwdev, ++ struct ieee80211_vif *vif); + bool rtw89_ra_report_to_bitrate(struct rtw89_dev *rtwdev, u8 rpt_rate, u16 *bitrate); + int rtw89_regd_setup(struct rtw89_dev *rtwdev); + int rtw89_regd_init(struct rtw89_dev *rtwdev, +@@ -6675,7 +6695,9 @@ void rtw89_core_scan_complete(struct rtw89_dev *rtwdev, + struct ieee80211_vif *vif, bool hw_scan); + int rtw89_reg_6ghz_recalc(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, + bool active); +-void rtw89_core_update_p2p_ps(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif); ++void rtw89_core_update_p2p_ps(struct rtw89_dev *rtwdev, ++ struct rtw89_vif_link *rtwvif_link, ++ struct ieee80211_bss_conf *bss_conf); + void rtw89_core_ntfy_btc_event(struct rtw89_dev *rtwdev, enum rtw89_btc_hmsg event); + + #endif +diff --git a/drivers/net/wireless/realtek/rtw89/fw.c b/drivers/net/wireless/realtek/rtw89/fw.c +index 03775064ee0c1..10069f0ce6a38 100644 +--- a/drivers/net/wireless/realtek/rtw89/fw.c ++++ b/drivers/net/wireless/realtek/rtw89/fw.c +@@ -2208,11 +2208,10 @@ static struct sk_buff *rtw89_eapol_get(struct rtw89_dev *rtwdev, + { + static const u8 gtkbody[] = {0xAA, 0xAA, 0x03, 0x00, 0x00, 0x00, 0x88, + 0x8E, 0x01, 0x03, 0x00, 0x5F, 0x02, 0x03}; +- struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif_link); +- struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; + u8 sec_hdr_len = rtw89_wow_get_sec_hdr_len(rtwdev); + struct rtw89_wow_param *rtw_wow = &rtwdev->wow; + struct rtw89_eapol_2_of_2 *eapol_pkt; ++ struct ieee80211_bss_conf *bss_conf; + struct ieee80211_hdr_3addr *hdr; + struct sk_buff *skb; + u8 key_des_ver; +@@ -2234,10 +2233,17 @@ static struct sk_buff *rtw89_eapol_get(struct rtw89_dev *rtwdev, + hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_DATA | + IEEE80211_FCTL_TODS | + IEEE80211_FCTL_PROTECTED); ++ ++ rcu_read_lock(); ++ ++ bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, true); ++ + ether_addr_copy(hdr->addr1, bss_conf->bssid); +- ether_addr_copy(hdr->addr2, vif->addr); ++ ether_addr_copy(hdr->addr2, bss_conf->addr); + ether_addr_copy(hdr->addr3, bss_conf->bssid); + ++ rcu_read_unlock(); ++ + skb_put_zero(skb, sec_hdr_len); + + eapol_pkt = skb_put_zero(skb, sizeof(*eapol_pkt)); +@@ -2250,9 +2256,8 @@ static struct sk_buff *rtw89_eapol_get(struct rtw89_dev *rtwdev, + static struct sk_buff *rtw89_sa_query_get(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link) + { +- struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif_link); +- struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; + u8 sec_hdr_len = rtw89_wow_get_sec_hdr_len(rtwdev); ++ struct ieee80211_bss_conf *bss_conf; + struct ieee80211_hdr_3addr *hdr; + struct rtw89_sa_query *sa_query; + struct sk_buff *skb; +@@ -2265,10 +2270,17 @@ static struct sk_buff *rtw89_sa_query_get(struct rtw89_dev *rtwdev, + hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | + IEEE80211_STYPE_ACTION | + IEEE80211_FCTL_PROTECTED); ++ ++ rcu_read_lock(); ++ ++ bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, true); ++ + ether_addr_copy(hdr->addr1, bss_conf->bssid); +- ether_addr_copy(hdr->addr2, vif->addr); ++ ether_addr_copy(hdr->addr2, bss_conf->addr); + ether_addr_copy(hdr->addr3, bss_conf->bssid); + ++ rcu_read_unlock(); ++ + skb_put_zero(skb, sec_hdr_len); + + sa_query = skb_put_zero(skb, sizeof(*sa_query)); +@@ -2554,13 +2566,14 @@ int rtw89_fw_h2c_lps_ch_info(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rt + } + + #define H2C_P2P_ACT_LEN 20 +-int rtw89_fw_h2c_p2p_act(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif, ++int rtw89_fw_h2c_p2p_act(struct rtw89_dev *rtwdev, ++ struct rtw89_vif_link *rtwvif_link, ++ struct ieee80211_bss_conf *bss_conf, + struct ieee80211_p2p_noa_desc *desc, + u8 act, u8 noa_id) + { +- struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv; + bool p2p_type_gc = rtwvif_link->wifi_role == RTW89_WIFI_ROLE_P2P_CLIENT; +- u8 ctwindow_oppps = vif->bss_conf.p2p_noa_attr.oppps_ctwindow; ++ u8 ctwindow_oppps = bss_conf->p2p_noa_attr.oppps_ctwindow; + struct sk_buff *skb; + u8 *cmd; + int ret; +@@ -2962,6 +2975,7 @@ int rtw89_fw_h2c_assoc_cmac_tbl_g7(struct rtw89_dev *rtwdev, + const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, rtwvif_link->chanctx_idx); + u8 mac_id = rtwsta_link ? rtwsta_link->mac_id : rtwvif_link->mac_id; + struct rtw89_h2c_cctlinfo_ud_g7 *h2c; ++ struct ieee80211_bss_conf *bss_conf; + u8 pads[RTW89_PPE_BW_NUM]; + u32 len = sizeof(*h2c); + struct sk_buff *skb; +@@ -2976,6 +2990,16 @@ int rtw89_fw_h2c_assoc_cmac_tbl_g7(struct rtw89_dev *rtwdev, + __get_sta_he_pkt_padding(rtwdev, sta, pads); + } + ++ skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, len); ++ if (!skb) { ++ rtw89_err(rtwdev, "failed to alloc skb for cmac g7\n"); ++ return -ENOMEM; ++ } ++ ++ rcu_read_lock(); ++ ++ bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, true); ++ + if (vif->p2p) + lowest_rate = RTW89_HW_RATE_OFDM6; + else if (chan->band_type == RTW89_BAND_2G) +@@ -2983,11 +3007,6 @@ int rtw89_fw_h2c_assoc_cmac_tbl_g7(struct rtw89_dev *rtwdev, + else + lowest_rate = RTW89_HW_RATE_OFDM6; + +- skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, len); +- if (!skb) { +- rtw89_err(rtwdev, "failed to alloc skb for cmac g7\n"); +- return -ENOMEM; +- } + skb_put(skb, len); + h2c = (struct rtw89_h2c_cctlinfo_ud_g7 *)skb->data; + +@@ -3016,8 +3035,8 @@ int rtw89_fw_h2c_assoc_cmac_tbl_g7(struct rtw89_dev *rtwdev, + h2c->m4 |= cpu_to_le32(CCTLINFO_G7_W4_DATA_DCM); + } + +- if (vif->bss_conf.eht_support) { +- u16 punct = vif->bss_conf.chanreq.oper.punctured; ++ if (bss_conf->eht_support) { ++ u16 punct = bss_conf->chanreq.oper.punctured; + + h2c->w4 |= le32_encode_bits(~punct, + CCTLINFO_G7_W4_ACT_SUBCH_CBW); +@@ -3050,6 +3069,8 @@ int rtw89_fw_h2c_assoc_cmac_tbl_g7(struct rtw89_dev *rtwdev, + h2c->m8 = cpu_to_le32(CCTLINFO_G7_W8_BSR_QUEUE_SIZE_FORMAT); + } + ++ rcu_read_unlock(); ++ + rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C, + H2C_CAT_MAC, H2C_CL_MAC_FR_EXCHG, + H2C_FUNC_MAC_CCTLINFO_UD_G7, 0, 1, +@@ -3433,7 +3454,8 @@ rtw89_fw_get_sta_type(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_li + struct rtw89_sta_link *rtwsta_link) + { + struct ieee80211_sta *sta = rtwsta_to_sta_safe(rtwsta_link); +- struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif_link); ++ struct ieee80211_bss_conf *bss_conf; ++ enum rtw89_fw_sta_type type; + + if (!sta) + goto by_vif; +@@ -3446,12 +3468,20 @@ rtw89_fw_get_sta_type(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_li + return RTW89_FW_N_AC_STA; + + by_vif: +- if (vif->bss_conf.eht_support) +- return RTW89_FW_BE_STA; +- else if (vif->bss_conf.he_support) +- return RTW89_FW_AX_STA; ++ rcu_read_lock(); ++ ++ bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, true); ++ ++ if (bss_conf->eht_support) ++ type = RTW89_FW_BE_STA; ++ else if (bss_conf->he_support) ++ type = RTW89_FW_AX_STA; + else +- return RTW89_FW_N_AC_STA; ++ type = RTW89_FW_N_AC_STA; ++ ++ rcu_read_unlock(); ++ ++ return type; + } + + int rtw89_fw_h2c_join_info(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, +@@ -3741,7 +3771,7 @@ int rtw89_fw_h2c_set_bcn_fltr_cfg(struct rtw89_dev *rtwdev, + bool connect) + { + struct rtw89_vif_link *rtwvif_link = vif_to_rtwvif_safe(vif); +- struct ieee80211_bss_conf *bss_conf = vif ? &vif->bss_conf : NULL; ++ struct ieee80211_bss_conf *bss_conf; + s32 thold = RTW89_DEFAULT_CQM_THOLD; + u32 hyst = RTW89_DEFAULT_CQM_HYST; + struct rtw89_h2c_bcnfltr *h2c; +@@ -3752,9 +3782,20 @@ int rtw89_fw_h2c_set_bcn_fltr_cfg(struct rtw89_dev *rtwdev, + if (!RTW89_CHK_FW_FEATURE(BEACON_FILTER, &rtwdev->fw)) + return -EINVAL; + +- if (!rtwvif_link || !bss_conf || rtwvif_link->net_type != RTW89_NET_TYPE_INFRA) ++ if (!rtwvif_link || rtwvif_link->net_type != RTW89_NET_TYPE_INFRA) + return -EINVAL; + ++ rcu_read_lock(); ++ ++ bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, false); ++ ++ if (bss_conf->cqm_rssi_hyst) ++ hyst = bss_conf->cqm_rssi_hyst; ++ if (bss_conf->cqm_rssi_thold) ++ thold = bss_conf->cqm_rssi_thold; ++ ++ rcu_read_unlock(); ++ + skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, len); + if (!skb) { + rtw89_err(rtwdev, "failed to alloc skb for h2c bcn filter\n"); +@@ -3764,11 +3805,6 @@ int rtw89_fw_h2c_set_bcn_fltr_cfg(struct rtw89_dev *rtwdev, + skb_put(skb, len); + h2c = (struct rtw89_h2c_bcnfltr *)skb->data; + +- if (bss_conf->cqm_rssi_hyst) +- hyst = bss_conf->cqm_rssi_hyst; +- if (bss_conf->cqm_rssi_thold) +- thold = bss_conf->cqm_rssi_thold; +- + h2c->w0 = le32_encode_bits(connect, RTW89_H2C_BCNFLTR_W0_MON_RSSI) | + le32_encode_bits(connect, RTW89_H2C_BCNFLTR_W0_MON_BCN) | + le32_encode_bits(connect, RTW89_H2C_BCNFLTR_W0_MON_EN) | +@@ -6550,7 +6586,7 @@ void rtw89_hw_scan_start(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif, + get_random_mask_addr(mac_addr, req->mac_addr, + req->mac_addr_mask); + else +- ether_addr_copy(mac_addr, vif->addr); ++ ether_addr_copy(mac_addr, rtwvif_link->mac_addr); + rtw89_core_scan_start(rtwdev, rtwvif_link, mac_addr, true); + + rx_fltr &= ~B_AX_A_BCN_CHK_EN; +diff --git a/drivers/net/wireless/realtek/rtw89/fw.h b/drivers/net/wireless/realtek/rtw89/fw.h +index 00e52a33516b6..b13512c3feb28 100644 +--- a/drivers/net/wireless/realtek/rtw89/fw.h ++++ b/drivers/net/wireless/realtek/rtw89/fw.h +@@ -4553,7 +4553,9 @@ int rtw89_pno_scan_add_chan_list_be(struct rtw89_dev *rtwdev, + int rtw89_fw_h2c_trigger_cpu_exception(struct rtw89_dev *rtwdev); + int rtw89_fw_h2c_pkt_drop(struct rtw89_dev *rtwdev, + const struct rtw89_pkt_drop_params *params); +-int rtw89_fw_h2c_p2p_act(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif, ++int rtw89_fw_h2c_p2p_act(struct rtw89_dev *rtwdev, ++ struct rtw89_vif_link *rtwvif_link, ++ struct ieee80211_bss_conf *bss_conf, + struct ieee80211_p2p_noa_desc *desc, + u8 act, u8 noa_id); + int rtw89_fw_h2c_tsf32_toggle(struct rtw89_dev *rtwdev, +diff --git a/drivers/net/wireless/realtek/rtw89/mac.c b/drivers/net/wireless/realtek/rtw89/mac.c +index d6cd3ed1e7fc8..d5097d3a3385f 100644 +--- a/drivers/net/wireless/realtek/rtw89/mac.c ++++ b/drivers/net/wireless/realtek/rtw89/mac.c +@@ -4141,10 +4141,11 @@ static void rtw89_mac_port_cfg_func_sw(struct rtw89_dev *rtwdev, + { + const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; + const struct rtw89_port_reg *p = mac->port_base; +- struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif_link); + const struct rtw89_chip_info *chip = rtwdev->chip; ++ struct ieee80211_bss_conf *bss_conf; + bool need_backup = false; + u32 backup_val; ++ u16 beacon_int; + + if (!rtw89_read32_port_mask(rtwdev, rtwvif_link, p->port_cfg, B_AX_PORT_FUNC_EN)) + return; +@@ -4168,7 +4169,14 @@ static void rtw89_mac_port_cfg_func_sw(struct rtw89_dev *rtwdev, + B_AX_BCNERLY_MASK); + } + +- msleep(vif->bss_conf.beacon_int + 1); ++ rcu_read_lock(); ++ ++ bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, true); ++ beacon_int = bss_conf->beacon_int; ++ ++ rcu_read_unlock(); ++ ++ msleep(beacon_int + 1); + rtw89_write32_port_clr(rtwdev, rtwvif_link, p->port_cfg, B_AX_PORT_FUNC_EN | + B_AX_BRK_SETUP); + rtw89_write32_port_set(rtwdev, rtwvif_link, p->port_cfg, B_AX_TSFTR_RST); +@@ -4301,8 +4309,18 @@ static void rtw89_mac_port_cfg_bcn_intv(struct rtw89_dev *rtwdev, + { + const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; + const struct rtw89_port_reg *p = mac->port_base; +- struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif_link); +- u16 bcn_int = vif->bss_conf.beacon_int ? vif->bss_conf.beacon_int : BCN_INTERVAL; ++ struct ieee80211_bss_conf *bss_conf; ++ u16 bcn_int; ++ ++ rcu_read_lock(); ++ ++ bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, true); ++ if (bss_conf->beacon_int) ++ bcn_int = bss_conf->beacon_int; ++ else ++ bcn_int = BCN_INTERVAL; ++ ++ rcu_read_unlock(); + + rtw89_write32_port_mask(rtwdev, rtwvif_link, p->bcn_space, B_AX_BCN_SPACE_MASK, + bcn_int); +@@ -4326,14 +4344,22 @@ static void rtw89_mac_port_cfg_hiq_dtim(struct rtw89_dev *rtwdev, + { + const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; + const struct rtw89_port_reg *p = mac->port_base; +- struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif_link); ++ struct ieee80211_bss_conf *bss_conf; ++ u8 dtim_period; + u32 addr; + ++ rcu_read_lock(); ++ ++ bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, true); ++ dtim_period = bss_conf->dtim_period; ++ ++ rcu_read_unlock(); ++ + addr = rtw89_mac_reg_by_idx(rtwdev, p->md_tsft, rtwvif_link->mac_idx); + rtw89_write8_set(rtwdev, addr, B_AX_UPD_HGQMD | B_AX_UPD_TIMIE); + + rtw89_write16_port_mask(rtwdev, rtwvif_link, p->dtim_ctrl, B_AX_DTIM_NUM_MASK, +- vif->bss_conf.dtim_period); ++ dtim_period); + } + + static void rtw89_mac_port_cfg_bcn_setup_time(struct rtw89_dev *rtwdev, +@@ -4381,18 +4407,24 @@ static void rtw89_mac_port_cfg_bss_color(struct rtw89_dev *rtwdev, + { + const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; + const struct rtw89_port_reg *p = mac->port_base; +- struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif_link); + static const u32 masks[RTW89_PORT_NUM] = { + B_AX_BSS_COLOB_AX_PORT_0_MASK, B_AX_BSS_COLOB_AX_PORT_1_MASK, + B_AX_BSS_COLOB_AX_PORT_2_MASK, B_AX_BSS_COLOB_AX_PORT_3_MASK, + B_AX_BSS_COLOB_AX_PORT_4_MASK, + }; ++ struct ieee80211_bss_conf *bss_conf; + u8 port = rtwvif_link->port; + u32 reg_base; + u32 reg; + u8 bss_color; + +- bss_color = vif->bss_conf.he_bss_color.color; ++ rcu_read_lock(); ++ ++ bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, true); ++ bss_color = bss_conf->he_bss_color.color; ++ ++ rcu_read_unlock(); ++ + reg_base = port >= 4 ? p->bss_color + 4 : p->bss_color; + reg = rtw89_mac_reg_by_idx(rtwdev, reg_base, rtwvif_link->mac_idx); + rtw89_write32_mask(rtwdev, reg, masks[port], bss_color); +@@ -4670,16 +4702,28 @@ void rtw89_mac_set_he_obss_narrow_bw_ru(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv; + const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; + struct ieee80211_hw *hw = rtwdev->hw; ++ struct ieee80211_bss_conf *bss_conf; ++ struct cfg80211_chan_def oper; + bool tolerated = true; + u32 reg; + +- if (!vif->bss_conf.he_support || vif->type != NL80211_IFTYPE_STATION) ++ rcu_read_lock(); ++ ++ bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, true); ++ if (!bss_conf->he_support || vif->type != NL80211_IFTYPE_STATION) { ++ rcu_read_unlock(); + return; ++ } + +- if (!(vif->bss_conf.chanreq.oper.chan->flags & IEEE80211_CHAN_RADAR)) ++ oper = bss_conf->chanreq.oper; ++ if (!(oper.chan->flags & IEEE80211_CHAN_RADAR)) { ++ rcu_read_unlock(); + return; ++ } ++ ++ rcu_read_unlock(); + +- cfg80211_bss_iter(hw->wiphy, &vif->bss_conf.chanreq.oper, ++ cfg80211_bss_iter(hw->wiphy, &oper, + rtw89_mac_check_he_obss_narrow_bw_ru_iter, + &tolerated); + +diff --git a/drivers/net/wireless/realtek/rtw89/mac80211.c b/drivers/net/wireless/realtek/rtw89/mac80211.c +index 392a38fcf4618..f04032a8a8ec4 100644 +--- a/drivers/net/wireless/realtek/rtw89/mac80211.c ++++ b/drivers/net/wireless/realtek/rtw89/mac80211.c +@@ -111,6 +111,7 @@ static int rtw89_ops_add_interface(struct ieee80211_hw *hw, + { + struct rtw89_dev *rtwdev = hw->priv; + struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv; ++ struct ieee80211_bss_conf *bss_conf; + int ret = 0; + + rtw89_debug(rtwdev, RTW89_DBG_STATE, "add vif %pM type %d, p2p %d\n", +@@ -151,7 +152,14 @@ static int rtw89_ops_add_interface(struct ieee80211_hw *hw, + rtwvif_link->chanctx_assigned = false; + rtwvif_link->hit_rule = 0; + rtwvif_link->reg_6ghz_power = RTW89_REG_6GHZ_POWER_DFLT; +- ether_addr_copy(rtwvif_link->mac_addr, vif->addr); ++ ++ rcu_read_lock(); ++ ++ bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, true); ++ ether_addr_copy(rtwvif_link->mac_addr, bss_conf->addr); ++ ++ rcu_read_unlock(); ++ + INIT_LIST_HEAD(&rtwvif_link->general_pkt_list); + + ret = rtw89_mac_add_vif(rtwdev, rtwvif_link); +@@ -314,13 +322,19 @@ static const u8 ac_to_fw_idx[IEEE80211_NUM_ACS] = { + static u8 rtw89_aifsn_to_aifs(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, u8 aifsn) + { +- struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif_link); + const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, + rtwvif_link->chanctx_idx); ++ struct ieee80211_bss_conf *bss_conf; + u8 slot_time; + u8 sifs; + +- slot_time = vif->bss_conf.use_short_slot ? 9 : 20; ++ rcu_read_lock(); ++ ++ bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, true); ++ slot_time = bss_conf->use_short_slot ? 9 : 20; ++ ++ rcu_read_unlock(); ++ + sifs = chan->band_type == RTW89_BAND_2G ? 10 : 16; + + return aifsn * slot_time + sifs; +@@ -486,7 +500,7 @@ static void rtw89_ops_link_info_changed(struct ieee80211_hw *hw, + rtw89_mac_bf_set_gid_table(rtwdev, vif, conf); + + if (changed & BSS_CHANGED_P2P_PS) +- rtw89_core_update_p2p_ps(rtwdev, vif); ++ rtw89_core_update_p2p_ps(rtwdev, rtwvif_link, conf); + + if (changed & BSS_CHANGED_CQM) + rtw89_fw_h2c_set_bcn_fltr_cfg(rtwdev, vif, true); +@@ -516,7 +530,7 @@ static int rtw89_ops_start_ap(struct ieee80211_hw *hw, + if (rtwdev->scanning) + rtw89_hw_scan_abort(rtwdev, rtwdev->scan_info.scanning_vif); + +- ether_addr_copy(rtwvif_link->bssid, vif->bss_conf.bssid); ++ ether_addr_copy(rtwvif_link->bssid, link_conf->bssid); + rtw89_cam_bssid_changed(rtwdev, rtwvif_link); + rtw89_mac_port_update(rtwdev, rtwvif_link); + rtw89_chip_h2c_assoc_cmac_tbl(rtwdev, vif, NULL); +diff --git a/drivers/net/wireless/realtek/rtw89/phy.c b/drivers/net/wireless/realtek/rtw89/phy.c +index e632e74601cbe..dd24d253947e8 100644 +--- a/drivers/net/wireless/realtek/rtw89/phy.c ++++ b/drivers/net/wireless/realtek/rtw89/phy.c +@@ -6006,15 +6006,24 @@ void rtw89_phy_dm_init(struct rtw89_dev *rtwdev) + + void rtw89_phy_set_bss_color(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif) + { ++ struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv; + const struct rtw89_chip_info *chip = rtwdev->chip; + const struct rtw89_reg_def *bss_clr_vld = &chip->bss_clr_vld; + enum rtw89_phy_idx phy_idx = RTW89_PHY_0; ++ struct ieee80211_bss_conf *bss_conf; + u8 bss_color; + +- if (!vif->bss_conf.he_support || !vif->cfg.assoc) ++ rcu_read_lock(); ++ ++ bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, true); ++ if (!bss_conf->he_support || !vif->cfg.assoc) { ++ rcu_read_unlock(); + return; ++ } ++ ++ bss_color = bss_conf->he_bss_color.color; + +- bss_color = vif->bss_conf.he_bss_color.color; ++ rcu_read_unlock(); + + rtw89_phy_write32_idx(rtwdev, bss_clr_vld->addr, bss_clr_vld->mask, 0x1, + phy_idx); +diff --git a/drivers/net/wireless/realtek/rtw89/ps.c b/drivers/net/wireless/realtek/rtw89/ps.c +index 42a73bba7f5c1..ded0b73bd6783 100644 +--- a/drivers/net/wireless/realtek/rtw89/ps.c ++++ b/drivers/net/wireless/realtek/rtw89/ps.c +@@ -214,9 +214,9 @@ static void rtw89_tsf32_toggle(struct rtw89_dev *rtwdev, + } + + static void rtw89_p2p_disable_all_noa(struct rtw89_dev *rtwdev, +- struct ieee80211_vif *vif) ++ struct rtw89_vif_link *rtwvif_link, ++ struct ieee80211_bss_conf *bss_conf) + { +- struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv; + enum rtw89_p2pps_action act; + u8 noa_id; + +@@ -229,20 +229,21 @@ static void rtw89_p2p_disable_all_noa(struct rtw89_dev *rtwdev, + else + act = RTW89_P2P_ACT_REMOVE; + rtw89_tsf32_toggle(rtwdev, rtwvif_link, act); +- rtw89_fw_h2c_p2p_act(rtwdev, vif, NULL, act, noa_id); ++ rtw89_fw_h2c_p2p_act(rtwdev, rtwvif_link, bss_conf, ++ NULL, act, noa_id); + } + } + + static void rtw89_p2p_update_noa(struct rtw89_dev *rtwdev, +- struct ieee80211_vif *vif) ++ struct rtw89_vif_link *rtwvif_link, ++ struct ieee80211_bss_conf *bss_conf) + { +- struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv; + struct ieee80211_p2p_noa_desc *desc; + enum rtw89_p2pps_action act; + u8 noa_id; + + for (noa_id = 0; noa_id < RTW89_P2P_MAX_NOA_NUM; noa_id++) { +- desc = &vif->bss_conf.p2p_noa_attr.desc[noa_id]; ++ desc = &bss_conf->p2p_noa_attr.desc[noa_id]; + if (!desc->count || !desc->duration) + break; + +@@ -251,15 +252,18 @@ static void rtw89_p2p_update_noa(struct rtw89_dev *rtwdev, + else + act = RTW89_P2P_ACT_UPDATE; + rtw89_tsf32_toggle(rtwdev, rtwvif_link, act); +- rtw89_fw_h2c_p2p_act(rtwdev, vif, desc, act, noa_id); ++ rtw89_fw_h2c_p2p_act(rtwdev, rtwvif_link, bss_conf, ++ desc, act, noa_id); + } + rtwvif_link->last_noa_nr = noa_id; + } + +-void rtw89_process_p2p_ps(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif) ++void rtw89_process_p2p_ps(struct rtw89_dev *rtwdev, ++ struct rtw89_vif_link *rtwvif_link, ++ struct ieee80211_bss_conf *bss_conf) + { +- rtw89_p2p_disable_all_noa(rtwdev, vif); +- rtw89_p2p_update_noa(rtwdev, vif); ++ rtw89_p2p_disable_all_noa(rtwdev, rtwvif_link, bss_conf); ++ rtw89_p2p_update_noa(rtwdev, rtwvif_link, bss_conf); + } + + void rtw89_recalc_lps(struct rtw89_dev *rtwdev) +diff --git a/drivers/net/wireless/realtek/rtw89/ps.h b/drivers/net/wireless/realtek/rtw89/ps.h +index d0be56ee16a29..cdd712966b09d 100644 +--- a/drivers/net/wireless/realtek/rtw89/ps.h ++++ b/drivers/net/wireless/realtek/rtw89/ps.h +@@ -14,7 +14,9 @@ void rtw89_leave_ps_mode(struct rtw89_dev *rtwdev); + void rtw89_enter_ips(struct rtw89_dev *rtwdev); + void rtw89_leave_ips(struct rtw89_dev *rtwdev); + void rtw89_set_coex_ctrl_lps(struct rtw89_dev *rtwdev, bool btc_ctrl); +-void rtw89_process_p2p_ps(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif); ++void rtw89_process_p2p_ps(struct rtw89_dev *rtwdev, ++ struct rtw89_vif_link *rtwvif_link, ++ struct ieee80211_bss_conf *bss_conf); + void rtw89_recalc_lps(struct rtw89_dev *rtwdev); + void rtw89_p2p_noa_renew(struct rtw89_vif_link *rtwvif_link); + void rtw89_p2p_noa_append(struct rtw89_vif_link *rtwvif_link, +diff --git a/drivers/net/wireless/realtek/rtw89/regd.c b/drivers/net/wireless/realtek/rtw89/regd.c +index 0fd8e132fdf07..aa5ae02443727 100644 +--- a/drivers/net/wireless/realtek/rtw89/regd.c ++++ b/drivers/net/wireless/realtek/rtw89/regd.c +@@ -834,16 +834,21 @@ static int rtw89_reg_6ghz_tpe_recalc(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, bool active, + unsigned int *changed) + { +- struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif_link); +- struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; + struct rtw89_reg_6ghz_tpe *tpe = &rtwvif_link->reg_6ghz_tpe; ++ struct ieee80211_bss_conf *bss_conf; + + memset(tpe, 0, sizeof(*tpe)); + + if (!active || rtwvif_link->reg_6ghz_power != RTW89_REG_6GHZ_POWER_STD) + goto bottom; + ++ rcu_read_lock(); ++ ++ bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, true); + rtw89_calculate_tpe(rtwdev, tpe, &bss_conf->tpe); ++ ++ rcu_read_unlock(); ++ + if (!tpe->valid) + goto bottom; + +@@ -911,10 +916,14 @@ static int rtw89_reg_6ghz_power_recalc(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, bool active, + unsigned int *changed) + { +- struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif_link); ++ struct ieee80211_bss_conf *bss_conf; ++ ++ rcu_read_lock(); ++ ++ bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, true); + + if (active) { +- switch (vif->bss_conf.power_type) { ++ switch (bss_conf->power_type) { + case IEEE80211_REG_VLP_AP: + rtwvif_link->reg_6ghz_power = RTW89_REG_6GHZ_POWER_VLP; + break; +@@ -932,6 +941,8 @@ static int rtw89_reg_6ghz_power_recalc(struct rtw89_dev *rtwdev, + rtwvif_link->reg_6ghz_power = RTW89_REG_6GHZ_POWER_DFLT; + } + ++ rcu_read_unlock(); ++ + *changed += __rtw89_reg_6ghz_power_recalc(rtwdev); + return 0; + } +diff --git a/drivers/net/wireless/realtek/rtw89/wow.c b/drivers/net/wireless/realtek/rtw89/wow.c +index 5046fef55222d..17e2d5cbb1e6a 100644 +--- a/drivers/net/wireless/realtek/rtw89/wow.c ++++ b/drivers/net/wireless/realtek/rtw89/wow.c +@@ -633,10 +633,12 @@ static struct ieee80211_key_conf *rtw89_wow_gtk_rekey(struct rtw89_dev *rtwdev, + static void rtw89_wow_update_key_info(struct rtw89_dev *rtwdev, bool rx_ready) + { + struct ieee80211_vif *wow_vif = rtwdev->wow.wow_vif; ++ struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)wow_vif->drv_priv; + struct rtw89_wow_param *rtw_wow = &rtwdev->wow; + struct rtw89_wow_aoac_report *aoac_rpt = &rtw_wow->aoac_rpt; + struct rtw89_set_key_info_iter_data data = {.error = false, + .rx_ready = rx_ready}; ++ struct ieee80211_bss_conf *bss_conf; + struct ieee80211_key_conf *key; + + rcu_read_lock(); +@@ -669,9 +671,15 @@ static void rtw89_wow_update_key_info(struct rtw89_dev *rtwdev, bool rx_ready) + return; + + rtw89_rx_pn_set_pmf(rtwdev, key, aoac_rpt->igtk_ipn); +- ieee80211_gtk_rekey_notify(wow_vif, wow_vif->bss_conf.bssid, ++ ++ rcu_read_lock(); ++ ++ bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, true); ++ ieee80211_gtk_rekey_notify(wow_vif, bss_conf->bssid, + aoac_rpt->eapol_key_replay_count, +- GFP_KERNEL); ++ GFP_ATOMIC); ++ ++ rcu_read_unlock(); + } + + static void rtw89_wow_leave_deep_ps(struct rtw89_dev *rtwdev) +-- +2.43.0 + diff --git a/queue-6.12/wifi-rtw89-read-link_sta-corresponding-to-the-link.patch b/queue-6.12/wifi-rtw89-read-link_sta-corresponding-to-the-link.patch new file mode 100644 index 00000000000..5fcdb5fee33 --- /dev/null +++ b/queue-6.12/wifi-rtw89-read-link_sta-corresponding-to-the-link.patch @@ -0,0 +1,1187 @@ +From 84b4f4a15937fe1228145a6a37b9e0a877a963c5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Mon, 16 Sep 2024 13:31:55 +0800 +Subject: wifi: rtw89: read link_sta corresponding to the link + +From: Zong-Zhe Yang <kevin_yang@realtek.com> + +[ Upstream commit 04911c0fe874bb44e8ee0f5896a5a10c37a14cf2 ] + +Tweak code to not always access sta->deflink directly. Instead, +according to link_id, read target link_sta from sta->link[]. + +For now, rtwsta_link->link_id keeps 0. When driver starts to +support MLO, the link_id will be assigned. + +Signed-off-by: Zong-Zhe Yang <kevin_yang@realtek.com> +Signed-off-by: Ping-Ke Shih <pkshih@realtek.com> +Link: https://patch.msgid.link/20240916053158.47350-5-pkshih@realtek.com +Stable-dep-of: f16c40acd319 ("wifi: rtw89: Fix TX fail with A2DP after scanning") +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/net/wireless/realtek/rtw89/cam.c | 14 +- + drivers/net/wireless/realtek/rtw89/coex.c | 16 +- + drivers/net/wireless/realtek/rtw89/core.c | 53 ++++++- + drivers/net/wireless/realtek/rtw89/core.h | 43 +++++- + drivers/net/wireless/realtek/rtw89/debug.c | 21 ++- + drivers/net/wireless/realtek/rtw89/fw.c | 97 +++++++----- + drivers/net/wireless/realtek/rtw89/mac.c | 61 ++++++-- + drivers/net/wireless/realtek/rtw89/mac_be.c | 45 ++++-- + drivers/net/wireless/realtek/rtw89/phy.c | 154 ++++++++++++-------- + 9 files changed, 362 insertions(+), 142 deletions(-) + +diff --git a/drivers/net/wireless/realtek/rtw89/cam.c b/drivers/net/wireless/realtek/rtw89/cam.c +index 757f7633b079b..7efc6280feaf8 100644 +--- a/drivers/net/wireless/realtek/rtw89/cam.c ++++ b/drivers/net/wireless/realtek/rtw89/cam.c +@@ -712,11 +712,21 @@ void rtw89_cam_fill_addr_cam_info(struct rtw89_dev *rtwdev, + struct rtw89_addr_cam_entry *addr_cam = + rtw89_get_addr_cam_of(rtwvif_link, rtwsta_link); + struct ieee80211_sta *sta = rtwsta_to_sta_safe(rtwsta_link); ++ struct ieee80211_link_sta *link_sta; + const u8 *sma = scan_mac_addr ? scan_mac_addr : rtwvif_link->mac_addr; + u8 sma_hash, tma_hash, addr_msk_start; + u8 sma_start = 0; + u8 tma_start = 0; +- u8 *tma = sta ? sta->addr : rtwvif_link->bssid; ++ const u8 *tma; ++ ++ rcu_read_lock(); ++ ++ if (sta) { ++ link_sta = rtw89_sta_rcu_dereference_link(rtwsta_link, true); ++ tma = link_sta->addr; ++ } else { ++ tma = rtwvif_link->bssid; ++ } + + if (addr_cam->addr_mask != 0) { + addr_msk_start = __ffs(addr_cam->addr_mask); +@@ -791,6 +801,8 @@ void rtw89_cam_fill_addr_cam_info(struct rtw89_dev *rtwdev, + FWCMD_SET_ADDR_SEC_ENT4(cmd, addr_cam->sec_ent[4]); + FWCMD_SET_ADDR_SEC_ENT5(cmd, addr_cam->sec_ent[5]); + FWCMD_SET_ADDR_SEC_ENT6(cmd, addr_cam->sec_ent[6]); ++ ++ rcu_read_unlock(); + } + + void rtw89_cam_fill_dctl_sec_cam_info_v1(struct rtw89_dev *rtwdev, +diff --git a/drivers/net/wireless/realtek/rtw89/coex.c b/drivers/net/wireless/realtek/rtw89/coex.c +index be6383ebf4d16..3d33e40544d0f 100644 +--- a/drivers/net/wireless/realtek/rtw89/coex.c ++++ b/drivers/net/wireless/realtek/rtw89/coex.c +@@ -7489,8 +7489,8 @@ void rtw89_btc_ntfy_role_info(struct rtw89_dev *rtwdev, + const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, + rtwvif_link->chanctx_idx); + struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif_link); +- struct ieee80211_sta *sta = rtwsta_to_sta(rtwsta_link); + struct ieee80211_bss_conf *bss_conf; ++ struct ieee80211_link_sta *link_sta; + struct rtw89_btc *btc = &rtwdev->btc; + const struct rtw89_btc_ver *ver = btc->ver; + struct rtw89_btc_wl_info *wl = &btc->cx.wl; +@@ -7516,19 +7516,21 @@ void rtw89_btc_ntfy_role_info(struct rtw89_dev *rtwdev, + bss_conf->beacon_int, bss_conf->dtim_period); + + if (rtwsta_link) { ++ link_sta = rtw89_sta_rcu_dereference_link(rtwsta_link, false); ++ + rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], STA mac_id=%d\n", + rtwsta_link->mac_id); + + rtw89_debug(rtwdev, RTW89_DBG_BTC, + "[BTC], STA support HE=%d VHT=%d HT=%d\n", +- sta->deflink.he_cap.has_he, +- sta->deflink.vht_cap.vht_supported, +- sta->deflink.ht_cap.ht_supported); +- if (sta->deflink.he_cap.has_he) ++ link_sta->he_cap.has_he, ++ link_sta->vht_cap.vht_supported, ++ link_sta->ht_cap.ht_supported); ++ if (link_sta->he_cap.has_he) + mode |= BIT(BTC_WL_MODE_HE); +- if (sta->deflink.vht_cap.vht_supported) ++ if (link_sta->vht_cap.vht_supported) + mode |= BIT(BTC_WL_MODE_VHT); +- if (sta->deflink.ht_cap.ht_supported) ++ if (link_sta->ht_cap.ht_supported) + mode |= BIT(BTC_WL_MODE_HT); + + r.mode = mode; +diff --git a/drivers/net/wireless/realtek/rtw89/core.c b/drivers/net/wireless/realtek/rtw89/core.c +index f1db598c60048..84c1952fbea88 100644 +--- a/drivers/net/wireless/realtek/rtw89/core.c ++++ b/drivers/net/wireless/realtek/rtw89/core.c +@@ -465,6 +465,7 @@ rtw89_core_tx_update_ampdu_info(struct rtw89_dev *rtwdev, + { + struct ieee80211_sta *sta = tx_req->sta; + struct rtw89_tx_desc_info *desc_info = &tx_req->desc_info; ++ struct ieee80211_link_sta *link_sta; + struct sk_buff *skb = tx_req->skb; + struct rtw89_sta_link *rtwsta_link; + u8 ampdu_num; +@@ -486,13 +487,18 @@ rtw89_core_tx_update_ampdu_info(struct rtw89_dev *rtwdev, + tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK; + rtwsta_link = (struct rtw89_sta_link *)sta->drv_priv; + ++ rcu_read_lock(); ++ ++ link_sta = rtw89_sta_rcu_dereference_link(rtwsta_link, false); + ampdu_num = (u8)((rtwsta_link->ampdu_params[tid].agg_num ? + rtwsta_link->ampdu_params[tid].agg_num : +- 4 << sta->deflink.ht_cap.ampdu_factor) - 1); ++ 4 << link_sta->ht_cap.ampdu_factor) - 1); + + desc_info->agg_en = true; +- desc_info->ampdu_density = sta->deflink.ht_cap.ampdu_density; ++ desc_info->ampdu_density = link_sta->ht_cap.ampdu_density; + desc_info->ampdu_num = ampdu_num; ++ ++ rcu_read_unlock(); + } + + static void +@@ -721,15 +727,26 @@ __rtw89_core_tx_check_he_qos_htc(struct rtw89_dev *rtwdev, + struct rtw89_sta_link *rtwsta_link = sta_to_rtwsta_safe(sta); + struct sk_buff *skb = tx_req->skb; + struct ieee80211_hdr *hdr = (void *)skb->data; ++ struct ieee80211_link_sta *link_sta; + __le16 fc = hdr->frame_control; + + /* AP IOT issue with EAPoL, ARP and DHCP */ + if (pkt_type < PACKET_MAX) + return false; + +- if (!sta || !sta->deflink.he_cap.has_he) ++ if (!rtwsta_link) + return false; + ++ rcu_read_lock(); ++ ++ link_sta = rtw89_sta_rcu_dereference_link(rtwsta_link, false); ++ if (!link_sta->he_cap.has_he) { ++ rcu_read_unlock(); ++ return false; ++ } ++ ++ rcu_read_unlock(); ++ + if (!ieee80211_is_data_qos(fc)) + return false; + +@@ -802,10 +819,13 @@ static u16 rtw89_core_get_data_rate(struct rtw89_dev *rtwdev, + struct ieee80211_vif *vif = tx_req->vif; + struct ieee80211_sta *sta = tx_req->sta; + struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv; ++ struct rtw89_sta_link *rtwsta_link = sta_to_rtwsta_safe(sta); + struct rtw89_phy_rate_pattern *rate_pattern = &rtwvif_link->rate_pattern; + enum rtw89_chanctx_idx idx = rtwvif_link->chanctx_idx; + const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, idx); ++ struct ieee80211_link_sta *link_sta; + u16 lowest_rate; ++ u16 rate; + + if (rate_pattern->enable) + return rate_pattern->rate; +@@ -817,10 +837,23 @@ static u16 rtw89_core_get_data_rate(struct rtw89_dev *rtwdev, + else + lowest_rate = RTW89_HW_RATE_OFDM6; + +- if (!sta || !sta->deflink.supp_rates[chan->band_type]) ++ if (!rtwsta_link) + return lowest_rate; + +- return __ffs(sta->deflink.supp_rates[chan->band_type]) + lowest_rate; ++ rcu_read_lock(); ++ ++ link_sta = rtw89_sta_rcu_dereference_link(rtwsta_link, false); ++ if (!link_sta->supp_rates[chan->band_type]) { ++ rate = lowest_rate; ++ goto out; ++ } ++ ++ rate = __ffs(link_sta->supp_rates[chan->band_type]) + lowest_rate; ++ ++out: ++ rcu_read_unlock(); ++ ++ return rate; + } + + static void +@@ -3645,12 +3678,20 @@ int rtw89_core_sta_assoc(struct rtw89_dev *rtwdev, + + if (vif->type == NL80211_IFTYPE_AP || sta->tdls) { + if (sta->tdls) { ++ struct ieee80211_link_sta *link_sta; ++ ++ rcu_read_lock(); ++ ++ link_sta = rtw89_sta_rcu_dereference_link(rtwsta_link, true); + ret = rtw89_cam_init_bssid_cam(rtwdev, rtwvif_link, bssid_cam, +- sta->addr); ++ link_sta->addr); + if (ret) { + rtw89_warn(rtwdev, "failed to send h2c init bssid cam for TDLS\n"); ++ rcu_read_unlock(); + return ret; + } ++ ++ rcu_read_unlock(); + } + + ret = rtw89_cam_init_addr_cam(rtwdev, &rtwsta_link->addr_cam, bssid_cam); +diff --git a/drivers/net/wireless/realtek/rtw89/core.h b/drivers/net/wireless/realtek/rtw89/core.h +index 8f66d4fac9aa6..274051e53f19c 100644 +--- a/drivers/net/wireless/realtek/rtw89/core.h ++++ b/drivers/net/wireless/realtek/rtw89/core.h +@@ -3355,6 +3355,8 @@ struct rtw89_sec_cam_entry { + }; + + struct rtw89_sta_link { ++ unsigned int link_id; ++ + u8 mac_id; + bool disassoc; + bool er_cap; +@@ -6026,6 +6028,36 @@ __rtw89_vif_rcu_dereference_link(struct rtw89_vif_link *rtwvif_link, bool *nolin + bss_conf; \ + }) + ++static inline struct ieee80211_link_sta * ++__rtw89_sta_rcu_dereference_link(struct rtw89_sta_link *rtwsta_link, bool *nolink) ++{ ++ struct ieee80211_sta *sta = rtwsta_to_sta(rtwsta_link); ++ struct ieee80211_link_sta *link_sta; ++ ++ link_sta = rcu_dereference(sta->link[rtwsta_link->link_id]); ++ if (unlikely(!link_sta)) { ++ *nolink = true; ++ return &sta->deflink; ++ } ++ ++ *nolink = false; ++ return link_sta; ++} ++ ++#define rtw89_sta_rcu_dereference_link(rtwsta_link, assert) \ ++({ \ ++ typeof(rtwsta_link) p = rtwsta_link; \ ++ struct ieee80211_link_sta *link_sta; \ ++ bool nolink; \ ++ \ ++ link_sta = __rtw89_sta_rcu_dereference_link(p, &nolink); \ ++ if (unlikely(nolink) && (assert)) \ ++ rtw89_err(p->rtwdev, \ ++ "%s: cannot find exact link_sta for link_id %u\n",\ ++ __func__, p->link_id); \ ++ link_sta; \ ++}) ++ + static inline u8 rtw89_hw_to_rate_info_bw(enum rtw89_bandwidth hw_bw) + { + if (hw_bw == RTW89_CHANNEL_WIDTH_160) +@@ -6497,13 +6529,14 @@ static inline u8 *get_hdr_bssid(struct ieee80211_hdr *hdr) + return hdr->addr3; + } + +-static inline bool rtw89_sta_has_beamformer_cap(struct ieee80211_sta *sta) ++static inline ++bool rtw89_sta_has_beamformer_cap(struct ieee80211_link_sta *link_sta) + { +- if ((sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE) || +- (sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE) || +- (sta->deflink.he_cap.he_cap_elem.phy_cap_info[3] & ++ if ((link_sta->vht_cap.cap & IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE) || ++ (link_sta->vht_cap.cap & IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE) || ++ (link_sta->he_cap.he_cap_elem.phy_cap_info[3] & + IEEE80211_HE_PHY_CAP3_SU_BEAMFORMER) || +- (sta->deflink.he_cap.he_cap_elem.phy_cap_info[4] & ++ (link_sta->he_cap.he_cap_elem.phy_cap_info[4] & + IEEE80211_HE_PHY_CAP4_MU_BEAMFORMER)) + return true; + return false; +diff --git a/drivers/net/wireless/realtek/rtw89/debug.c b/drivers/net/wireless/realtek/rtw89/debug.c +index f09f1a251b169..cc7aaf6fa31fc 100644 +--- a/drivers/net/wireless/realtek/rtw89/debug.c ++++ b/drivers/net/wireless/realtek/rtw89/debug.c +@@ -3526,11 +3526,20 @@ static void rtw89_sta_info_get_iter(void *data, struct ieee80211_sta *sta) + struct rtw89_hal *hal = &rtwdev->hal; + u8 ant_num = hal->ant_diversity ? 2 : rtwdev->chip->rf_path_num; + bool ant_asterisk = hal->tx_path_diversity || hal->ant_diversity; ++ struct ieee80211_link_sta *link_sta; + u8 evm_min, evm_max, evm_1ss; ++ u16 max_rc_amsdu_len; + u8 rssi; + u8 snr; + int i; + ++ rcu_read_lock(); ++ ++ link_sta = rtw89_sta_rcu_dereference_link(rtwsta_link, true); ++ max_rc_amsdu_len = link_sta->agg.max_rc_amsdu_len; ++ ++ rcu_read_unlock(); ++ + seq_printf(m, "TX rate [%d]: ", rtwsta_link->mac_id); + + if (rate->flags & RATE_INFO_FLAGS_MCS) +@@ -3553,7 +3562,7 @@ static void rtw89_sta_info_get_iter(void *data, struct ieee80211_sta *sta) + seq_printf(m, " BW:%u", rtw89_rate_info_bw_to_mhz(rate->bw)); + seq_printf(m, "\t(hw_rate=0x%x)", rtwsta_link->ra_report.hw_rate); + seq_printf(m, "\t==> agg_wait=%d (%d)\n", rtwsta_link->max_agg_wait, +- sta->deflink.agg.max_rc_amsdu_len); ++ max_rc_amsdu_len); + + seq_printf(m, "RX rate [%d]: ", rtwsta_link->mac_id); + +@@ -3777,9 +3786,17 @@ static void rtw89_sta_ids_get_iter(void *data, struct ieee80211_sta *sta) + struct rtw89_sta_link *rtwsta_link = (struct rtw89_sta_link *)sta->drv_priv; + struct rtw89_dev *rtwdev = rtwsta_link->rtwdev; + struct seq_file *m = (struct seq_file *)data; ++ struct ieee80211_link_sta *link_sta; ++ ++ rcu_read_lock(); + +- seq_printf(m, "STA [%d] %pM %s\n", rtwsta_link->mac_id, sta->addr, ++ link_sta = rtw89_sta_rcu_dereference_link(rtwsta_link, true); ++ ++ seq_printf(m, "STA [%d] %pM %s\n", rtwsta_link->mac_id, link_sta->addr, + sta->tdls ? "(TDLS)" : ""); ++ ++ rcu_read_unlock(); ++ + rtw89_dump_addr_cam(m, rtwdev, &rtwsta_link->addr_cam); + rtw89_dump_ba_cam(m, rtwsta_link); + } +diff --git a/drivers/net/wireless/realtek/rtw89/fw.c b/drivers/net/wireless/realtek/rtw89/fw.c +index 10069f0ce6a38..52e5dbe7e59db 100644 +--- a/drivers/net/wireless/realtek/rtw89/fw.c ++++ b/drivers/net/wireless/realtek/rtw89/fw.c +@@ -2776,24 +2776,25 @@ int rtw89_fw_h2c_default_cmac_tbl_g7(struct rtw89_dev *rtwdev, + EXPORT_SYMBOL(rtw89_fw_h2c_default_cmac_tbl_g7); + + static void __get_sta_he_pkt_padding(struct rtw89_dev *rtwdev, +- struct ieee80211_sta *sta, u8 *pads) ++ struct ieee80211_link_sta *link_sta, ++ u8 *pads) + { + bool ppe_th; + u8 ppe16, ppe8; +- u8 nss = min(sta->deflink.rx_nss, rtwdev->hal.tx_nss) - 1; +- u8 ppe_thres_hdr = sta->deflink.he_cap.ppe_thres[0]; ++ u8 nss = min(link_sta->rx_nss, rtwdev->hal.tx_nss) - 1; ++ u8 ppe_thres_hdr = link_sta->he_cap.ppe_thres[0]; + u8 ru_bitmap; + u8 n, idx, sh; + u16 ppe; + int i; + + ppe_th = FIELD_GET(IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT, +- sta->deflink.he_cap.he_cap_elem.phy_cap_info[6]); ++ link_sta->he_cap.he_cap_elem.phy_cap_info[6]); + if (!ppe_th) { + u8 pad; + + pad = FIELD_GET(IEEE80211_HE_PHY_CAP9_NOMINAL_PKT_PADDING_MASK, +- sta->deflink.he_cap.he_cap_elem.phy_cap_info[9]); ++ link_sta->he_cap.he_cap_elem.phy_cap_info[9]); + + for (i = 0; i < RTW89_PPE_BW_NUM; i++) + pads[i] = pad; +@@ -2815,7 +2816,7 @@ static void __get_sta_he_pkt_padding(struct rtw89_dev *rtwdev, + sh = n & 7; + n += IEEE80211_PPE_THRES_INFO_PPET_SIZE * 2; + +- ppe = le16_to_cpu(*((__le16 *)&sta->deflink.he_cap.ppe_thres[idx])); ++ ppe = le16_to_cpu(*((__le16 *)&link_sta->he_cap.ppe_thres[idx])); + ppe16 = (ppe >> sh) & IEEE80211_PPE_THRES_NSS_MASK; + sh += IEEE80211_PPE_THRES_INFO_PPET_SIZE; + ppe8 = (ppe >> sh) & IEEE80211_PPE_THRES_NSS_MASK; +@@ -2838,6 +2839,7 @@ int rtw89_fw_h2c_assoc_cmac_tbl(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv; + const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, + rtwvif_link->chanctx_idx); ++ struct ieee80211_link_sta *link_sta; + struct sk_buff *skb; + u8 pads[RTW89_PPE_BW_NUM]; + u8 mac_id = rtwsta_link ? rtwsta_link->mac_id : rtwvif_link->mac_id; +@@ -2845,8 +2847,20 @@ int rtw89_fw_h2c_assoc_cmac_tbl(struct rtw89_dev *rtwdev, + int ret; + + memset(pads, 0, sizeof(pads)); +- if (sta && sta->deflink.he_cap.has_he) +- __get_sta_he_pkt_padding(rtwdev, sta, pads); ++ ++ skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, H2C_CMC_TBL_LEN); ++ if (!skb) { ++ rtw89_err(rtwdev, "failed to alloc skb for fw dl\n"); ++ return -ENOMEM; ++ } ++ ++ rcu_read_lock(); ++ ++ if (rtwsta_link) ++ link_sta = rtw89_sta_rcu_dereference_link(rtwsta_link, true); ++ ++ if (rtwsta_link && link_sta->he_cap.has_he) ++ __get_sta_he_pkt_padding(rtwdev, link_sta, pads); + + if (vif->p2p) + lowest_rate = RTW89_HW_RATE_OFDM6; +@@ -2855,11 +2869,6 @@ int rtw89_fw_h2c_assoc_cmac_tbl(struct rtw89_dev *rtwdev, + else + lowest_rate = RTW89_HW_RATE_OFDM6; + +- skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, H2C_CMC_TBL_LEN); +- if (!skb) { +- rtw89_err(rtwdev, "failed to alloc skb for fw dl\n"); +- return -ENOMEM; +- } + skb_put(skb, H2C_CMC_TBL_LEN); + SET_CTRL_INFO_MACID(skb->data, mac_id); + SET_CTRL_INFO_OPERATION(skb->data, 1); +@@ -2884,12 +2893,14 @@ int rtw89_fw_h2c_assoc_cmac_tbl(struct rtw89_dev *rtwdev, + SET_CMC_TBL_NOMINAL_PKT_PADDING80(skb->data, pads[RTW89_CHANNEL_WIDTH_80]); + SET_CMC_TBL_NOMINAL_PKT_PADDING160(skb->data, pads[RTW89_CHANNEL_WIDTH_160]); + } +- if (sta) ++ if (rtwsta_link) + SET_CMC_TBL_BSR_QUEUE_SIZE_FORMAT(skb->data, +- sta->deflink.he_cap.has_he); ++ link_sta->he_cap.has_he); + if (rtwvif_link->net_type == RTW89_NET_TYPE_AP_MODE) + SET_CMC_TBL_DATA_DCM(skb->data, 0); + ++ rcu_read_unlock(); ++ + rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C, + H2C_CAT_MAC, H2C_CL_MAC_FR_EXCHG, + chip->h2c_cctl_func_id, 0, 1, +@@ -2910,9 +2921,10 @@ int rtw89_fw_h2c_assoc_cmac_tbl(struct rtw89_dev *rtwdev, + EXPORT_SYMBOL(rtw89_fw_h2c_assoc_cmac_tbl); + + static void __get_sta_eht_pkt_padding(struct rtw89_dev *rtwdev, +- struct ieee80211_sta *sta, u8 *pads) ++ struct ieee80211_link_sta *link_sta, ++ u8 *pads) + { +- u8 nss = min(sta->deflink.rx_nss, rtwdev->hal.tx_nss) - 1; ++ u8 nss = min(link_sta->rx_nss, rtwdev->hal.tx_nss) - 1; + u16 ppe_thres_hdr; + u8 ppe16, ppe8; + u8 n, idx, sh; +@@ -2921,12 +2933,12 @@ static void __get_sta_eht_pkt_padding(struct rtw89_dev *rtwdev, + u16 ppe; + int i; + +- ppe_th = !!u8_get_bits(sta->deflink.eht_cap.eht_cap_elem.phy_cap_info[5], ++ ppe_th = !!u8_get_bits(link_sta->eht_cap.eht_cap_elem.phy_cap_info[5], + IEEE80211_EHT_PHY_CAP5_PPE_THRESHOLD_PRESENT); + if (!ppe_th) { + u8 pad; + +- pad = u8_get_bits(sta->deflink.eht_cap.eht_cap_elem.phy_cap_info[5], ++ pad = u8_get_bits(link_sta->eht_cap.eht_cap_elem.phy_cap_info[5], + IEEE80211_EHT_PHY_CAP5_COMMON_NOMINAL_PKT_PAD_MASK); + + for (i = 0; i < RTW89_PPE_BW_NUM; i++) +@@ -2935,7 +2947,7 @@ static void __get_sta_eht_pkt_padding(struct rtw89_dev *rtwdev, + return; + } + +- ppe_thres_hdr = get_unaligned_le16(sta->deflink.eht_cap.eht_ppe_thres); ++ ppe_thres_hdr = get_unaligned_le16(link_sta->eht_cap.eht_ppe_thres); + ru_bitmap = u16_get_bits(ppe_thres_hdr, + IEEE80211_EHT_PPE_THRES_RU_INDEX_BITMASK_MASK); + n = hweight8(ru_bitmap); +@@ -2952,7 +2964,7 @@ static void __get_sta_eht_pkt_padding(struct rtw89_dev *rtwdev, + sh = n & 7; + n += IEEE80211_EHT_PPE_THRES_INFO_PPET_SIZE * 2; + +- ppe = get_unaligned_le16(sta->deflink.eht_cap.eht_ppe_thres + idx); ++ ppe = get_unaligned_le16(link_sta->eht_cap.eht_ppe_thres + idx); + ppe16 = (ppe >> sh) & IEEE80211_PPE_THRES_NSS_MASK; + sh += IEEE80211_EHT_PPE_THRES_INFO_PPET_SIZE; + ppe8 = (ppe >> sh) & IEEE80211_PPE_THRES_NSS_MASK; +@@ -2976,6 +2988,7 @@ int rtw89_fw_h2c_assoc_cmac_tbl_g7(struct rtw89_dev *rtwdev, + u8 mac_id = rtwsta_link ? rtwsta_link->mac_id : rtwvif_link->mac_id; + struct rtw89_h2c_cctlinfo_ud_g7 *h2c; + struct ieee80211_bss_conf *bss_conf; ++ struct ieee80211_link_sta *link_sta; + u8 pads[RTW89_PPE_BW_NUM]; + u32 len = sizeof(*h2c); + struct sk_buff *skb; +@@ -2983,12 +2996,6 @@ int rtw89_fw_h2c_assoc_cmac_tbl_g7(struct rtw89_dev *rtwdev, + int ret; + + memset(pads, 0, sizeof(pads)); +- if (sta) { +- if (sta->deflink.eht_cap.has_eht) +- __get_sta_eht_pkt_padding(rtwdev, sta, pads); +- else if (sta->deflink.he_cap.has_he) +- __get_sta_he_pkt_padding(rtwdev, sta, pads); +- } + + skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, len); + if (!skb) { +@@ -3000,6 +3007,15 @@ int rtw89_fw_h2c_assoc_cmac_tbl_g7(struct rtw89_dev *rtwdev, + + bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, true); + ++ if (rtwsta_link) { ++ link_sta = rtw89_sta_rcu_dereference_link(rtwsta_link, true); ++ ++ if (link_sta->eht_cap.has_eht) ++ __get_sta_eht_pkt_padding(rtwdev, link_sta, pads); ++ else if (link_sta->he_cap.has_he) ++ __get_sta_he_pkt_padding(rtwdev, link_sta, pads); ++ } ++ + if (vif->p2p) + lowest_rate = RTW89_HW_RATE_OFDM6; + else if (chan->band_type == RTW89_BAND_2G) +@@ -3063,8 +3079,8 @@ int rtw89_fw_h2c_assoc_cmac_tbl_g7(struct rtw89_dev *rtwdev, + CCTLINFO_G7_W6_ULDL); + h2c->m6 = cpu_to_le32(CCTLINFO_G7_W6_ULDL); + +- if (sta) { +- h2c->w8 = le32_encode_bits(sta->deflink.he_cap.has_he, ++ if (rtwsta_link) { ++ h2c->w8 = le32_encode_bits(link_sta->he_cap.has_he, + CCTLINFO_G7_W8_BSR_QUEUE_SIZE_FORMAT); + h2c->m8 = cpu_to_le32(CCTLINFO_G7_W8_BSR_QUEUE_SIZE_FORMAT); + } +@@ -3453,23 +3469,27 @@ static enum rtw89_fw_sta_type + rtw89_fw_get_sta_type(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link) + { +- struct ieee80211_sta *sta = rtwsta_to_sta_safe(rtwsta_link); + struct ieee80211_bss_conf *bss_conf; ++ struct ieee80211_link_sta *link_sta; + enum rtw89_fw_sta_type type; + +- if (!sta) ++ rcu_read_lock(); ++ ++ if (!rtwsta_link) + goto by_vif; + +- if (sta->deflink.eht_cap.has_eht) +- return RTW89_FW_BE_STA; +- else if (sta->deflink.he_cap.has_he) +- return RTW89_FW_AX_STA; ++ link_sta = rtw89_sta_rcu_dereference_link(rtwsta_link, true); ++ ++ if (link_sta->eht_cap.has_eht) ++ type = RTW89_FW_BE_STA; ++ else if (link_sta->he_cap.has_he) ++ type = RTW89_FW_AX_STA; + else +- return RTW89_FW_N_AC_STA; ++ type = RTW89_FW_N_AC_STA; + +-by_vif: +- rcu_read_lock(); ++ goto out; + ++by_vif: + bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, true); + + if (bss_conf->eht_support) +@@ -3479,6 +3499,7 @@ rtw89_fw_get_sta_type(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_li + else + type = RTW89_FW_N_AC_STA; + ++out: + rcu_read_unlock(); + + return type; +diff --git a/drivers/net/wireless/realtek/rtw89/mac.c b/drivers/net/wireless/realtek/rtw89/mac.c +index d5097d3a3385f..7ab2aac3c3d22 100644 +--- a/drivers/net/wireless/realtek/rtw89/mac.c ++++ b/drivers/net/wireless/realtek/rtw89/mac.c +@@ -5993,11 +5993,13 @@ static int rtw89_mac_set_csi_para_reg_ax(struct rtw89_dev *rtwdev, + struct ieee80211_sta *sta) + { + struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv; +- u8 mac_idx = rtwvif_link->mac_idx; ++ struct rtw89_sta_link *rtwsta_link = (struct rtw89_sta_link *)sta->drv_priv; + u8 nc = 1, nr = 3, ng = 0, cb = 1, cs = 1, ldpc_en = 1, stbc_en = 1; ++ struct ieee80211_link_sta *link_sta; ++ u8 mac_idx = rtwvif_link->mac_idx; + u8 port_sel = rtwvif_link->port; + u8 sound_dim = 3, t; +- u8 *phy_cap = sta->deflink.he_cap.he_cap_elem.phy_cap_info; ++ u8 *phy_cap; + u32 reg; + u16 val; + int ret; +@@ -6006,6 +6008,11 @@ static int rtw89_mac_set_csi_para_reg_ax(struct rtw89_dev *rtwdev, + if (ret) + return ret; + ++ rcu_read_lock(); ++ ++ link_sta = rtw89_sta_rcu_dereference_link(rtwsta_link, true); ++ phy_cap = link_sta->he_cap.he_cap_elem.phy_cap_info; ++ + if ((phy_cap[3] & IEEE80211_HE_PHY_CAP3_SU_BEAMFORMER) || + (phy_cap[4] & IEEE80211_HE_PHY_CAP4_MU_BEAMFORMER)) { + ldpc_en &= !!(phy_cap[1] & IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD); +@@ -6014,17 +6021,19 @@ static int rtw89_mac_set_csi_para_reg_ax(struct rtw89_dev *rtwdev, + phy_cap[5]); + sound_dim = min(sound_dim, t); + } +- if ((sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE) || +- (sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE)) { +- ldpc_en &= !!(sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_RXLDPC); +- stbc_en &= !!(sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_RXSTBC_MASK); ++ if ((link_sta->vht_cap.cap & IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE) || ++ (link_sta->vht_cap.cap & IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE)) { ++ ldpc_en &= !!(link_sta->vht_cap.cap & IEEE80211_VHT_CAP_RXLDPC); ++ stbc_en &= !!(link_sta->vht_cap.cap & IEEE80211_VHT_CAP_RXSTBC_MASK); + t = FIELD_GET(IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_MASK, +- sta->deflink.vht_cap.cap); ++ link_sta->vht_cap.cap); + sound_dim = min(sound_dim, t); + } + nc = min(nc, sound_dim); + nr = min(nr, sound_dim); + ++ rcu_read_unlock(); ++ + reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_TRXPTCL_RESP_CSI_CTRL_0, mac_idx); + rtw89_write32_set(rtwdev, reg, B_AX_BFMEE_BFPARAM_SEL); + +@@ -6051,30 +6060,39 @@ static int rtw89_mac_csi_rrsc_ax(struct rtw89_dev *rtwdev, + struct ieee80211_sta *sta) + { + struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv; ++ struct rtw89_sta_link *rtwsta_link = (struct rtw89_sta_link *)sta->drv_priv; + u32 rrsc = BIT(RTW89_MAC_BF_RRSC_6M) | BIT(RTW89_MAC_BF_RRSC_24M); +- u32 reg; ++ struct ieee80211_link_sta *link_sta; + u8 mac_idx = rtwvif_link->mac_idx; ++ u32 reg; + int ret; + + ret = rtw89_mac_check_mac_en(rtwdev, mac_idx, RTW89_CMAC_SEL); + if (ret) + return ret; + +- if (sta->deflink.he_cap.has_he) { ++ rcu_read_lock(); ++ ++ link_sta = rtw89_sta_rcu_dereference_link(rtwsta_link, true); ++ ++ if (link_sta->he_cap.has_he) { + rrsc |= (BIT(RTW89_MAC_BF_RRSC_HE_MSC0) | + BIT(RTW89_MAC_BF_RRSC_HE_MSC3) | + BIT(RTW89_MAC_BF_RRSC_HE_MSC5)); + } +- if (sta->deflink.vht_cap.vht_supported) { ++ if (link_sta->vht_cap.vht_supported) { + rrsc |= (BIT(RTW89_MAC_BF_RRSC_VHT_MSC0) | + BIT(RTW89_MAC_BF_RRSC_VHT_MSC3) | + BIT(RTW89_MAC_BF_RRSC_VHT_MSC5)); + } +- if (sta->deflink.ht_cap.ht_supported) { ++ if (link_sta->ht_cap.ht_supported) { + rrsc |= (BIT(RTW89_MAC_BF_RRSC_HT_MSC0) | + BIT(RTW89_MAC_BF_RRSC_HT_MSC3) | + BIT(RTW89_MAC_BF_RRSC_HT_MSC5)); + } ++ ++ rcu_read_unlock(); ++ + reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_TRXPTCL_RESP_CSI_CTRL_0, mac_idx); + rtw89_write32_set(rtwdev, reg, B_AX_BFMEE_BFPARAM_SEL); + rtw89_write32_clr(rtwdev, reg, B_AX_BFMEE_CSI_FORCE_RETE_EN); +@@ -6090,8 +6108,18 @@ static void rtw89_mac_bf_assoc_ax(struct rtw89_dev *rtwdev, + struct ieee80211_sta *sta) + { + struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv; ++ struct rtw89_sta_link *rtwsta_link = (struct rtw89_sta_link *)sta->drv_priv; ++ struct ieee80211_link_sta *link_sta; ++ bool has_beamformer_cap; ++ ++ rcu_read_lock(); ++ ++ link_sta = rtw89_sta_rcu_dereference_link(rtwsta_link, true); ++ has_beamformer_cap = rtw89_sta_has_beamformer_cap(link_sta); + +- if (rtw89_sta_has_beamformer_cap(sta)) { ++ rcu_read_unlock(); ++ ++ if (has_beamformer_cap) { + rtw89_debug(rtwdev, RTW89_DBG_BF, + "initialize bfee for new association\n"); + rtw89_mac_init_bfee_ax(rtwdev, rtwvif_link->mac_idx); +@@ -6145,16 +6173,23 @@ struct rtw89_mac_bf_monitor_iter_data { + static + void rtw89_mac_bf_monitor_calc_iter(void *data, struct ieee80211_sta *sta) + { ++ struct rtw89_sta_link *rtwsta_link = (struct rtw89_sta_link *)sta->drv_priv; + struct rtw89_mac_bf_monitor_iter_data *iter_data = + (struct rtw89_mac_bf_monitor_iter_data *)data; + struct ieee80211_sta *down_sta = iter_data->down_sta; ++ struct ieee80211_link_sta *link_sta; + int *count = &iter_data->count; + + if (down_sta == sta) + return; + +- if (rtw89_sta_has_beamformer_cap(sta)) ++ rcu_read_lock(); ++ ++ link_sta = rtw89_sta_rcu_dereference_link(rtwsta_link, false); ++ if (rtw89_sta_has_beamformer_cap(link_sta)) + (*count)++; ++ ++ rcu_read_unlock(); + } + + void rtw89_mac_bf_monitor_calc(struct rtw89_dev *rtwdev, +diff --git a/drivers/net/wireless/realtek/rtw89/mac_be.c b/drivers/net/wireless/realtek/rtw89/mac_be.c +index bc3215939f37b..184a014a56bfe 100644 +--- a/drivers/net/wireless/realtek/rtw89/mac_be.c ++++ b/drivers/net/wireless/realtek/rtw89/mac_be.c +@@ -2095,7 +2095,9 @@ static int rtw89_mac_set_csi_para_reg_be(struct rtw89_dev *rtwdev, + struct ieee80211_sta *sta) + { + struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv; ++ struct rtw89_sta_link *rtwsta_link = (struct rtw89_sta_link *)sta->drv_priv; + u8 nc = 1, nr = 3, ng = 0, cb = 1, cs = 1, ldpc_en = 1, stbc_en = 1; ++ struct ieee80211_link_sta *link_sta; + u8 mac_idx = rtwvif_link->mac_idx; + u8 port_sel = rtwvif_link->port; + u8 sound_dim = 3, t; +@@ -2108,7 +2110,10 @@ static int rtw89_mac_set_csi_para_reg_be(struct rtw89_dev *rtwdev, + if (ret) + return ret; + +- phy_cap = sta->deflink.he_cap.he_cap_elem.phy_cap_info; ++ rcu_read_lock(); ++ ++ link_sta = rtw89_sta_rcu_dereference_link(rtwsta_link, true); ++ phy_cap = link_sta->he_cap.he_cap_elem.phy_cap_info; + + if ((phy_cap[3] & IEEE80211_HE_PHY_CAP3_SU_BEAMFORMER) || + (phy_cap[4] & IEEE80211_HE_PHY_CAP4_MU_BEAMFORMER)) { +@@ -2119,11 +2124,11 @@ static int rtw89_mac_set_csi_para_reg_be(struct rtw89_dev *rtwdev, + sound_dim = min(sound_dim, t); + } + +- if ((sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE) || +- (sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE)) { +- ldpc_en &= !!(sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_RXLDPC); +- stbc_en &= !!(sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_RXSTBC_MASK); +- t = u32_get_bits(sta->deflink.vht_cap.cap, ++ if ((link_sta->vht_cap.cap & IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE) || ++ (link_sta->vht_cap.cap & IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE)) { ++ ldpc_en &= !!(link_sta->vht_cap.cap & IEEE80211_VHT_CAP_RXLDPC); ++ stbc_en &= !!(link_sta->vht_cap.cap & IEEE80211_VHT_CAP_RXSTBC_MASK); ++ t = u32_get_bits(link_sta->vht_cap.cap, + IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_MASK); + sound_dim = min(sound_dim, t); + } +@@ -2131,6 +2136,8 @@ static int rtw89_mac_set_csi_para_reg_be(struct rtw89_dev *rtwdev, + nc = min(nc, sound_dim); + nr = min(nr, sound_dim); + ++ rcu_read_unlock(); ++ + reg = rtw89_mac_reg_by_idx(rtwdev, R_BE_TRXPTCL_RESP_CSI_CTRL_0, mac_idx); + rtw89_write32_set(rtwdev, reg, B_BE_BFMEE_BFPARAM_SEL); + +@@ -2159,7 +2166,9 @@ static int rtw89_mac_csi_rrsc_be(struct rtw89_dev *rtwdev, + struct ieee80211_sta *sta) + { + struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv; ++ struct rtw89_sta_link *rtwsta_link = (struct rtw89_sta_link *)sta->drv_priv; + u32 rrsc = BIT(RTW89_MAC_BF_RRSC_6M) | BIT(RTW89_MAC_BF_RRSC_24M); ++ struct ieee80211_link_sta *link_sta; + u8 mac_idx = rtwvif_link->mac_idx; + int ret; + u32 reg; +@@ -2168,22 +2177,28 @@ static int rtw89_mac_csi_rrsc_be(struct rtw89_dev *rtwdev, + if (ret) + return ret; + +- if (sta->deflink.he_cap.has_he) { ++ rcu_read_lock(); ++ ++ link_sta = rtw89_sta_rcu_dereference_link(rtwsta_link, true); ++ ++ if (link_sta->he_cap.has_he) { + rrsc |= (BIT(RTW89_MAC_BF_RRSC_HE_MSC0) | + BIT(RTW89_MAC_BF_RRSC_HE_MSC3) | + BIT(RTW89_MAC_BF_RRSC_HE_MSC5)); + } +- if (sta->deflink.vht_cap.vht_supported) { ++ if (link_sta->vht_cap.vht_supported) { + rrsc |= (BIT(RTW89_MAC_BF_RRSC_VHT_MSC0) | + BIT(RTW89_MAC_BF_RRSC_VHT_MSC3) | + BIT(RTW89_MAC_BF_RRSC_VHT_MSC5)); + } +- if (sta->deflink.ht_cap.ht_supported) { ++ if (link_sta->ht_cap.ht_supported) { + rrsc |= (BIT(RTW89_MAC_BF_RRSC_HT_MSC0) | + BIT(RTW89_MAC_BF_RRSC_HT_MSC3) | + BIT(RTW89_MAC_BF_RRSC_HT_MSC5)); + } + ++ rcu_read_unlock(); ++ + reg = rtw89_mac_reg_by_idx(rtwdev, R_BE_TRXPTCL_RESP_CSI_CTRL_0, mac_idx); + rtw89_write32_set(rtwdev, reg, B_BE_BFMEE_BFPARAM_SEL); + rtw89_write32_clr(rtwdev, reg, B_BE_BFMEE_CSI_FORCE_RETE_EN); +@@ -2199,8 +2214,18 @@ static void rtw89_mac_bf_assoc_be(struct rtw89_dev *rtwdev, + struct ieee80211_sta *sta) + { + struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv; ++ struct rtw89_sta_link *rtwsta_link = (struct rtw89_sta_link *)sta->drv_priv; ++ struct ieee80211_link_sta *link_sta; ++ bool has_beamformer_cap; ++ ++ rcu_read_lock(); ++ ++ link_sta = rtw89_sta_rcu_dereference_link(rtwsta_link, true); ++ has_beamformer_cap = rtw89_sta_has_beamformer_cap(link_sta); ++ ++ rcu_read_unlock(); + +- if (rtw89_sta_has_beamformer_cap(sta)) { ++ if (has_beamformer_cap) { + rtw89_debug(rtwdev, RTW89_DBG_BF, + "initialize bfee for new association\n"); + rtw89_mac_init_bfee_be(rtwdev, rtwvif_link->mac_idx); +diff --git a/drivers/net/wireless/realtek/rtw89/phy.c b/drivers/net/wireless/realtek/rtw89/phy.c +index dd24d253947e8..a46f182633e92 100644 +--- a/drivers/net/wireless/realtek/rtw89/phy.c ++++ b/drivers/net/wireless/realtek/rtw89/phy.c +@@ -75,12 +75,12 @@ static u64 get_mcs_ra_mask(u16 mcs_map, u8 highest_mcs, u8 gap) + return ra_mask; + } + +-static u64 get_he_ra_mask(struct ieee80211_sta *sta) ++static u64 get_he_ra_mask(struct ieee80211_link_sta *link_sta) + { +- struct ieee80211_sta_he_cap cap = sta->deflink.he_cap; ++ struct ieee80211_sta_he_cap cap = link_sta->he_cap; + u16 mcs_map; + +- switch (sta->deflink.bandwidth) { ++ switch (link_sta->bandwidth) { + case IEEE80211_STA_RX_BW_160: + if (cap.he_cap_elem.phy_cap_info[0] & + IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_80PLUS80_MHZ_IN_5G) +@@ -118,14 +118,14 @@ static u64 get_eht_mcs_ra_mask(u8 *max_nss, u8 start_mcs, u8 n_nss) + return mask; + } + +-static u64 get_eht_ra_mask(struct ieee80211_sta *sta) ++static u64 get_eht_ra_mask(struct ieee80211_link_sta *link_sta) + { +- struct ieee80211_sta_eht_cap *eht_cap = &sta->deflink.eht_cap; ++ struct ieee80211_sta_eht_cap *eht_cap = &link_sta->eht_cap; + struct ieee80211_eht_mcs_nss_supp_20mhz_only *mcs_nss_20mhz; + struct ieee80211_eht_mcs_nss_supp_bw *mcs_nss; +- u8 *he_phy_cap = sta->deflink.he_cap.he_cap_elem.phy_cap_info; ++ u8 *he_phy_cap = link_sta->he_cap.he_cap_elem.phy_cap_info; + +- switch (sta->deflink.bandwidth) { ++ switch (link_sta->bandwidth) { + case IEEE80211_STA_RX_BW_320: + mcs_nss = &eht_cap->eht_mcs_nss_supp.bw._320; + /* MCS 9, 11, 13 */ +@@ -197,9 +197,9 @@ static u64 rtw89_phy_ra_mask_recover(u64 ra_mask, u64 ra_mask_bak) + + static u64 rtw89_phy_ra_mask_cfg(struct rtw89_dev *rtwdev, + struct rtw89_sta_link *rtwsta_link, ++ struct ieee80211_link_sta *link_sta, + const struct rtw89_chan *chan) + { +- struct ieee80211_sta *sta = rtwsta_to_sta(rtwsta_link); + struct cfg80211_bitrate_mask *mask = &rtwsta_link->mask; + enum nl80211_band band; + u64 cfg_mask; +@@ -228,17 +228,17 @@ static u64 rtw89_phy_ra_mask_cfg(struct rtw89_dev *rtwdev, + return -1; + } + +- if (sta->deflink.he_cap.has_he) { ++ if (link_sta->he_cap.has_he) { + cfg_mask |= u64_encode_bits(mask->control[band].he_mcs[0], + RA_MASK_HE_1SS_RATES); + cfg_mask |= u64_encode_bits(mask->control[band].he_mcs[1], + RA_MASK_HE_2SS_RATES); +- } else if (sta->deflink.vht_cap.vht_supported) { ++ } else if (link_sta->vht_cap.vht_supported) { + cfg_mask |= u64_encode_bits(mask->control[band].vht_mcs[0], + RA_MASK_VHT_1SS_RATES); + cfg_mask |= u64_encode_bits(mask->control[band].vht_mcs[1], + RA_MASK_VHT_2SS_RATES); +- } else if (sta->deflink.ht_cap.ht_supported) { ++ } else if (link_sta->ht_cap.ht_supported) { + cfg_mask |= u64_encode_bits(mask->control[band].ht_mcs[0], + RA_MASK_HT_1SS_RATES); + cfg_mask |= u64_encode_bits(mask->control[band].ht_mcs[1], +@@ -296,15 +296,15 @@ static void rtw89_phy_ra_gi_ltf(struct rtw89_dev *rtwdev, + } + + static void rtw89_phy_ra_sta_update(struct rtw89_dev *rtwdev, +- struct ieee80211_sta *sta, bool csi) ++ struct rtw89_vif_link *rtwvif_link, ++ struct rtw89_sta_link *rtwsta_link, ++ struct ieee80211_link_sta *link_sta, ++ bool p2p, bool csi) + { +- struct rtw89_sta_link *rtwsta_link = (struct rtw89_sta_link *)sta->drv_priv; +- struct rtw89_vif_link *rtwvif_link = rtwsta_link->rtwvif_link; + struct rtw89_phy_rate_pattern *rate_pattern = &rtwvif_link->rate_pattern; + struct rtw89_ra_info *ra = &rtwsta_link->ra; + const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, + rtwvif_link->chanctx_idx); +- struct ieee80211_vif *vif = rtwvif_to_vif(rtwsta_link->rtwvif_link); + const u64 *high_rate_masks = rtw89_ra_mask_ht_rates; + u8 rssi = ewma_rssi_read(&rtwsta_link->avg_rssi); + u64 ra_mask = 0; +@@ -321,65 +321,65 @@ static void rtw89_phy_ra_sta_update(struct rtw89_dev *rtwdev, + + memset(ra, 0, sizeof(*ra)); + /* Set the ra mask from sta's capability */ +- if (sta->deflink.eht_cap.has_eht) { ++ if (link_sta->eht_cap.has_eht) { + mode |= RTW89_RA_MODE_EHT; +- ra_mask |= get_eht_ra_mask(sta); ++ ra_mask |= get_eht_ra_mask(link_sta); + high_rate_masks = rtw89_ra_mask_eht_rates; +- } else if (sta->deflink.he_cap.has_he) { ++ } else if (link_sta->he_cap.has_he) { + mode |= RTW89_RA_MODE_HE; + csi_mode = RTW89_RA_RPT_MODE_HE; +- ra_mask |= get_he_ra_mask(sta); ++ ra_mask |= get_he_ra_mask(link_sta); + high_rate_masks = rtw89_ra_mask_he_rates; +- if (sta->deflink.he_cap.he_cap_elem.phy_cap_info[2] & ++ if (link_sta->he_cap.he_cap_elem.phy_cap_info[2] & + IEEE80211_HE_PHY_CAP2_STBC_RX_UNDER_80MHZ) + stbc_en = 1; +- if (sta->deflink.he_cap.he_cap_elem.phy_cap_info[1] & ++ if (link_sta->he_cap.he_cap_elem.phy_cap_info[1] & + IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD) + ldpc_en = 1; + rtw89_phy_ra_gi_ltf(rtwdev, rtwsta_link, chan, &fix_giltf_en, &fix_giltf); +- } else if (sta->deflink.vht_cap.vht_supported) { +- u16 mcs_map = le16_to_cpu(sta->deflink.vht_cap.vht_mcs.rx_mcs_map); ++ } else if (link_sta->vht_cap.vht_supported) { ++ u16 mcs_map = le16_to_cpu(link_sta->vht_cap.vht_mcs.rx_mcs_map); + + mode |= RTW89_RA_MODE_VHT; + csi_mode = RTW89_RA_RPT_MODE_VHT; + /* MCS9 (non-20MHz), MCS8, MCS7 */ +- if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_20) ++ if (link_sta->bandwidth == IEEE80211_STA_RX_BW_20) + ra_mask |= get_mcs_ra_mask(mcs_map, 8, 1); + else + ra_mask |= get_mcs_ra_mask(mcs_map, 9, 1); + high_rate_masks = rtw89_ra_mask_vht_rates; +- if (sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_RXSTBC_MASK) ++ if (link_sta->vht_cap.cap & IEEE80211_VHT_CAP_RXSTBC_MASK) + stbc_en = 1; +- if (sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_RXLDPC) ++ if (link_sta->vht_cap.cap & IEEE80211_VHT_CAP_RXLDPC) + ldpc_en = 1; +- } else if (sta->deflink.ht_cap.ht_supported) { ++ } else if (link_sta->ht_cap.ht_supported) { + mode |= RTW89_RA_MODE_HT; + csi_mode = RTW89_RA_RPT_MODE_HT; +- ra_mask |= ((u64)sta->deflink.ht_cap.mcs.rx_mask[3] << 48) | +- ((u64)sta->deflink.ht_cap.mcs.rx_mask[2] << 36) | +- ((u64)sta->deflink.ht_cap.mcs.rx_mask[1] << 24) | +- ((u64)sta->deflink.ht_cap.mcs.rx_mask[0] << 12); ++ ra_mask |= ((u64)link_sta->ht_cap.mcs.rx_mask[3] << 48) | ++ ((u64)link_sta->ht_cap.mcs.rx_mask[2] << 36) | ++ ((u64)link_sta->ht_cap.mcs.rx_mask[1] << 24) | ++ ((u64)link_sta->ht_cap.mcs.rx_mask[0] << 12); + high_rate_masks = rtw89_ra_mask_ht_rates; +- if (sta->deflink.ht_cap.cap & IEEE80211_HT_CAP_RX_STBC) ++ if (link_sta->ht_cap.cap & IEEE80211_HT_CAP_RX_STBC) + stbc_en = 1; +- if (sta->deflink.ht_cap.cap & IEEE80211_HT_CAP_LDPC_CODING) ++ if (link_sta->ht_cap.cap & IEEE80211_HT_CAP_LDPC_CODING) + ldpc_en = 1; + } + + switch (chan->band_type) { + case RTW89_BAND_2G: +- ra_mask |= sta->deflink.supp_rates[NL80211_BAND_2GHZ]; +- if (sta->deflink.supp_rates[NL80211_BAND_2GHZ] & 0xf) ++ ra_mask |= link_sta->supp_rates[NL80211_BAND_2GHZ]; ++ if (link_sta->supp_rates[NL80211_BAND_2GHZ] & 0xf) + mode |= RTW89_RA_MODE_CCK; +- if (sta->deflink.supp_rates[NL80211_BAND_2GHZ] & 0xff0) ++ if (link_sta->supp_rates[NL80211_BAND_2GHZ] & 0xff0) + mode |= RTW89_RA_MODE_OFDM; + break; + case RTW89_BAND_5G: +- ra_mask |= (u64)sta->deflink.supp_rates[NL80211_BAND_5GHZ] << 4; ++ ra_mask |= (u64)link_sta->supp_rates[NL80211_BAND_5GHZ] << 4; + mode |= RTW89_RA_MODE_OFDM; + break; + case RTW89_BAND_6G: +- ra_mask |= (u64)sta->deflink.supp_rates[NL80211_BAND_6GHZ] << 4; ++ ra_mask |= (u64)link_sta->supp_rates[NL80211_BAND_6GHZ] << 4; + mode |= RTW89_RA_MODE_OFDM; + break; + default: +@@ -406,37 +406,37 @@ static void rtw89_phy_ra_sta_update(struct rtw89_dev *rtwdev, + ra_mask &= rtw89_phy_ra_mask_rssi(rtwdev, rssi, 0); + + ra_mask = rtw89_phy_ra_mask_recover(ra_mask, ra_mask_bak); +- ra_mask &= rtw89_phy_ra_mask_cfg(rtwdev, rtwsta_link, chan); ++ ra_mask &= rtw89_phy_ra_mask_cfg(rtwdev, rtwsta_link, link_sta, chan); + +- switch (sta->deflink.bandwidth) { ++ switch (link_sta->bandwidth) { + case IEEE80211_STA_RX_BW_160: + bw_mode = RTW89_CHANNEL_WIDTH_160; +- sgi = sta->deflink.vht_cap.vht_supported && +- (sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_SHORT_GI_160); ++ sgi = link_sta->vht_cap.vht_supported && ++ (link_sta->vht_cap.cap & IEEE80211_VHT_CAP_SHORT_GI_160); + break; + case IEEE80211_STA_RX_BW_80: + bw_mode = RTW89_CHANNEL_WIDTH_80; +- sgi = sta->deflink.vht_cap.vht_supported && +- (sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_SHORT_GI_80); ++ sgi = link_sta->vht_cap.vht_supported && ++ (link_sta->vht_cap.cap & IEEE80211_VHT_CAP_SHORT_GI_80); + break; + case IEEE80211_STA_RX_BW_40: + bw_mode = RTW89_CHANNEL_WIDTH_40; +- sgi = sta->deflink.ht_cap.ht_supported && +- (sta->deflink.ht_cap.cap & IEEE80211_HT_CAP_SGI_40); ++ sgi = link_sta->ht_cap.ht_supported && ++ (link_sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40); + break; + default: + bw_mode = RTW89_CHANNEL_WIDTH_20; +- sgi = sta->deflink.ht_cap.ht_supported && +- (sta->deflink.ht_cap.cap & IEEE80211_HT_CAP_SGI_20); ++ sgi = link_sta->ht_cap.ht_supported && ++ (link_sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20); + break; + } + +- if (sta->deflink.he_cap.he_cap_elem.phy_cap_info[3] & ++ if (link_sta->he_cap.he_cap_elem.phy_cap_info[3] & + IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_RX_16_QAM) + ra->dcm_cap = 1; + +- if (rate_pattern->enable && !vif->p2p) { +- ra_mask = rtw89_phy_ra_mask_cfg(rtwdev, rtwsta_link, chan); ++ if (rate_pattern->enable && !p2p) { ++ ra_mask = rtw89_phy_ra_mask_cfg(rtwdev, rtwsta_link, link_sta, chan); + ra_mask &= rate_pattern->ra_mask; + mode = rate_pattern->ra_mode; + } +@@ -447,7 +447,7 @@ static void rtw89_phy_ra_sta_update(struct rtw89_dev *rtwdev, + ra->macid = rtwsta_link->mac_id; + ra->stbc_cap = stbc_en; + ra->ldpc_cap = ldpc_en; +- ra->ss_num = min(sta->deflink.rx_nss, rtwdev->hal.tx_nss) - 1; ++ ra->ss_num = min(link_sta->rx_nss, rtwdev->hal.tx_nss) - 1; + ra->en_sgi = sgi; + ra->ra_mask = ra_mask; + ra->fix_giltf_en = fix_giltf_en; +@@ -470,9 +470,18 @@ void rtw89_phy_ra_update_sta(struct rtw89_dev *rtwdev, struct ieee80211_sta *sta + u32 changed) + { + struct rtw89_sta_link *rtwsta_link = (struct rtw89_sta_link *)sta->drv_priv; ++ struct rtw89_vif_link *rtwvif_link = rtwsta_link->rtwvif_link; ++ struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif_link); + struct rtw89_ra_info *ra = &rtwsta_link->ra; ++ struct ieee80211_link_sta *link_sta; + +- rtw89_phy_ra_sta_update(rtwdev, sta, false); ++ rcu_read_lock(); ++ ++ link_sta = rtw89_sta_rcu_dereference_link(rtwsta_link, false); ++ rtw89_phy_ra_sta_update(rtwdev, rtwvif_link, rtwsta_link, ++ link_sta, vif->p2p, false); ++ ++ rcu_read_unlock(); + + if (changed & IEEE80211_RC_SUPP_RATES_CHANGED) + ra->upd_mask = 1; +@@ -631,11 +640,22 @@ void rtw89_phy_ra_update(struct rtw89_dev *rtwdev) + void rtw89_phy_ra_assoc(struct rtw89_dev *rtwdev, struct ieee80211_sta *sta) + { + struct rtw89_sta_link *rtwsta_link = (struct rtw89_sta_link *)sta->drv_priv; ++ struct rtw89_vif_link *rtwvif_link = rtwsta_link->rtwvif_link; ++ struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif_link); + struct rtw89_ra_info *ra = &rtwsta_link->ra; + u8 rssi = ewma_rssi_read(&rtwsta_link->avg_rssi) >> RSSI_FACTOR; +- bool csi = rtw89_sta_has_beamformer_cap(sta); ++ struct ieee80211_link_sta *link_sta; ++ bool csi; ++ ++ rcu_read_lock(); + +- rtw89_phy_ra_sta_update(rtwdev, sta, csi); ++ link_sta = rtw89_sta_rcu_dereference_link(rtwsta_link, true); ++ csi = rtw89_sta_has_beamformer_cap(link_sta); ++ ++ rtw89_phy_ra_sta_update(rtwdev, rtwvif_link, rtwsta_link, ++ link_sta, vif->p2p, csi); ++ ++ rcu_read_unlock(); + + if (rssi > 40) + ra->init_rate_lv = 1; +@@ -2554,11 +2574,11 @@ struct rtw89_phy_iter_ra_data { + struct sk_buff *c2h; + }; + +-static void rtw89_phy_c2h_ra_rpt_iter(void *data, struct ieee80211_sta *sta) ++static void __rtw89_phy_c2h_ra_rpt_iter(struct rtw89_sta_link *rtwsta_link, ++ struct ieee80211_link_sta *link_sta, ++ struct rtw89_phy_iter_ra_data *ra_data) + { +- struct rtw89_phy_iter_ra_data *ra_data = (struct rtw89_phy_iter_ra_data *)data; + struct rtw89_dev *rtwdev = ra_data->rtwdev; +- struct rtw89_sta_link *rtwsta_link = (struct rtw89_sta_link *)sta->drv_priv; + const struct rtw89_c2h_ra_rpt *c2h = + (const struct rtw89_c2h_ra_rpt *)ra_data->c2h->data; + struct rtw89_ra_report *ra_report = &rtwsta_link->ra_report; +@@ -2662,8 +2682,22 @@ static void rtw89_phy_c2h_ra_rpt_iter(void *data, struct ieee80211_sta *sta) + u16_encode_bits(mode, RTW89_HW_RATE_MASK_MOD) | + u16_encode_bits(rate, RTW89_HW_RATE_MASK_VAL); + ra_report->might_fallback_legacy = mcs <= 2; +- sta->deflink.agg.max_rc_amsdu_len = get_max_amsdu_len(rtwdev, ra_report); +- rtwsta_link->max_agg_wait = sta->deflink.agg.max_rc_amsdu_len / 1500 - 1; ++ link_sta->agg.max_rc_amsdu_len = get_max_amsdu_len(rtwdev, ra_report); ++ rtwsta_link->max_agg_wait = link_sta->agg.max_rc_amsdu_len / 1500 - 1; ++} ++ ++static void rtw89_phy_c2h_ra_rpt_iter(void *data, struct ieee80211_sta *sta) ++{ ++ struct rtw89_phy_iter_ra_data *ra_data = (struct rtw89_phy_iter_ra_data *)data; ++ struct rtw89_sta_link *rtwsta_link = (struct rtw89_sta_link *)sta->drv_priv; ++ struct ieee80211_link_sta *link_sta; ++ ++ rcu_read_lock(); ++ ++ link_sta = rtw89_sta_rcu_dereference_link(rtwsta_link, false); ++ __rtw89_phy_c2h_ra_rpt_iter(rtwsta_link, link_sta, ra_data); ++ ++ rcu_read_unlock(); + } + + static void +-- +2.43.0 + diff --git a/queue-6.12/wifi-rtw89-refactor-sta-related-func-ahead-for-mlo.patch b/queue-6.12/wifi-rtw89-refactor-sta-related-func-ahead-for-mlo.patch new file mode 100644 index 00000000000..4141dd7bd82 --- /dev/null +++ b/queue-6.12/wifi-rtw89-refactor-sta-related-func-ahead-for-mlo.patch @@ -0,0 +1,945 @@ +From 48defc96a1f6d1983b95433185524f8ae786203a Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Mon, 16 Sep 2024 13:31:57 +0800 +Subject: wifi: rtw89: refactor STA related func ahead for MLO + +From: Zong-Zhe Yang <kevin_yang@realtek.com> + +[ Upstream commit 72e9457c1954dc39a7059bd6d6346b60a24aa55e ] + +Refactor STA related functions, e.g. add/assoc/disassoc/disconnect/remove +to separate most link stuffs into sub-functions for MLO reuse. + +Signed-off-by: Zong-Zhe Yang <kevin_yang@realtek.com> +Signed-off-by: Ping-Ke Shih <pkshih@realtek.com> +Link: https://patch.msgid.link/20240916053158.47350-7-pkshih@realtek.com +Stable-dep-of: f16c40acd319 ("wifi: rtw89: Fix TX fail with A2DP after scanning") +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/net/wireless/realtek/rtw89/core.c | 112 +++++-------- + drivers/net/wireless/realtek/rtw89/core.h | 40 +++-- + drivers/net/wireless/realtek/rtw89/fw.c | 17 +- + drivers/net/wireless/realtek/rtw89/fw.h | 16 +- + drivers/net/wireless/realtek/rtw89/mac.c | 42 +++-- + drivers/net/wireless/realtek/rtw89/mac.h | 20 ++- + drivers/net/wireless/realtek/rtw89/mac80211.c | 152 ++++++++++++++++-- + drivers/net/wireless/realtek/rtw89/mac_be.c | 22 +-- + drivers/net/wireless/realtek/rtw89/phy.c | 3 +- + drivers/net/wireless/realtek/rtw89/phy.h | 2 +- + drivers/net/wireless/realtek/rtw89/wow.c | 7 +- + 11 files changed, 261 insertions(+), 172 deletions(-) + +diff --git a/drivers/net/wireless/realtek/rtw89/core.c b/drivers/net/wireless/realtek/rtw89/core.c +index c6d3b8fd98b65..8d2cca0b0a18d 100644 +--- a/drivers/net/wireless/realtek/rtw89/core.c ++++ b/drivers/net/wireless/realtek/rtw89/core.c +@@ -2746,8 +2746,8 @@ static void rtw89_core_ba_work(struct work_struct *work) + spin_unlock_bh(&rtwdev->ba_lock); + } + +-static void rtw89_core_free_sta_pending_ba(struct rtw89_dev *rtwdev, +- struct ieee80211_sta *sta) ++void rtw89_core_free_sta_pending_ba(struct rtw89_dev *rtwdev, ++ struct ieee80211_sta *sta) + { + struct rtw89_txq *rtwtxq, *tmp; + +@@ -2761,8 +2761,8 @@ static void rtw89_core_free_sta_pending_ba(struct rtw89_dev *rtwdev, + spin_unlock_bh(&rtwdev->ba_lock); + } + +-static void rtw89_core_free_sta_pending_forbid_ba(struct rtw89_dev *rtwdev, +- struct ieee80211_sta *sta) ++void rtw89_core_free_sta_pending_forbid_ba(struct rtw89_dev *rtwdev, ++ struct ieee80211_sta *sta) + { + struct rtw89_txq *rtwtxq, *tmp; + +@@ -2778,8 +2778,8 @@ static void rtw89_core_free_sta_pending_forbid_ba(struct rtw89_dev *rtwdev, + spin_unlock_bh(&rtwdev->ba_lock); + } + +-static void rtw89_core_free_sta_pending_roc_tx(struct rtw89_dev *rtwdev, +- struct ieee80211_sta *sta) ++void rtw89_core_free_sta_pending_roc_tx(struct rtw89_dev *rtwdev, ++ struct ieee80211_sta *sta) + { + struct rtw89_sta_link *rtwsta_link = (struct rtw89_sta_link *)sta->drv_priv; + struct sk_buff *skb, *tmp; +@@ -3525,26 +3525,19 @@ void rtw89_vif_type_mapping(struct rtw89_vif_link *rtwvif_link, bool assoc) + } + } + +-int rtw89_core_sta_add(struct rtw89_dev *rtwdev, +- struct ieee80211_vif *vif, +- struct ieee80211_sta *sta) ++int rtw89_core_sta_link_add(struct rtw89_dev *rtwdev, ++ struct rtw89_vif_link *rtwvif_link, ++ struct rtw89_sta_link *rtwsta_link) + { +- struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv; +- struct rtw89_sta_link *rtwsta_link = (struct rtw89_sta_link *)sta->drv_priv; ++ struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif_link); ++ struct ieee80211_sta *sta = rtwsta_to_sta(rtwsta_link); + struct rtw89_hal *hal = &rtwdev->hal; + u8 ant_num = hal->ant_diversity ? 2 : rtwdev->chip->rf_path_num; + int i; + int ret; + +- rtwsta_link->rtwdev = rtwdev; +- rtwsta_link->rtwvif_link = rtwvif_link; + rtwsta_link->prev_rssi = 0; + INIT_LIST_HEAD(&rtwsta_link->ba_cam_list); +- skb_queue_head_init(&rtwsta_link->roc_queue); +- +- for (i = 0; i < ARRAY_SIZE(sta->txq); i++) +- rtw89_core_txq_init(rtwdev, sta->txq[i]); +- + ewma_rssi_init(&rtwsta_link->avg_rssi); + ewma_snr_init(&rtwsta_link->avg_snr); + ewma_evm_init(&rtwsta_link->evm_1ss); +@@ -3555,9 +3548,6 @@ int rtw89_core_sta_add(struct rtw89_dev *rtwdev, + } + + if (vif->type == NL80211_IFTYPE_STATION && !sta->tdls) { +- /* for station mode, assign the mac_id from itself */ +- rtwsta_link->mac_id = rtwvif_link->mac_id; +- + /* must do rtw89_reg_6ghz_recalc() before rfk channel */ + ret = rtw89_reg_6ghz_recalc(rtwdev, rtwvif_link, true); + if (ret) +@@ -3567,13 +3557,8 @@ int rtw89_core_sta_add(struct rtw89_dev *rtwdev, + BTC_ROLE_MSTS_STA_CONN_START); + rtw89_chip_rfk_channel(rtwdev, rtwvif_link); + } else if (vif->type == NL80211_IFTYPE_AP || sta->tdls) { +- rtwsta_link->mac_id = rtw89_acquire_mac_id(rtwdev); +- if (rtwsta_link->mac_id == RTW89_MAX_MAC_ID_NUM) +- return -ENOSPC; +- + ret = rtw89_mac_set_macid_pause(rtwdev, rtwsta_link->mac_id, false); + if (ret) { +- rtw89_release_mac_id(rtwdev, rtwsta_link->mac_id); + rtw89_warn(rtwdev, "failed to send h2c macid pause\n"); + return ret; + } +@@ -3581,7 +3566,6 @@ int rtw89_core_sta_add(struct rtw89_dev *rtwdev, + ret = rtw89_fw_h2c_role_maintain(rtwdev, rtwvif_link, rtwsta_link, + RTW89_ROLE_CREATE); + if (ret) { +- rtw89_release_mac_id(rtwdev, rtwsta_link->mac_id); + rtw89_warn(rtwdev, "failed to send h2c role info\n"); + return ret; + } +@@ -3593,44 +3577,33 @@ int rtw89_core_sta_add(struct rtw89_dev *rtwdev, + ret = rtw89_chip_h2c_default_dmac_tbl(rtwdev, rtwvif_link, rtwsta_link); + if (ret) + return ret; +- +- rtw89_queue_chanctx_change(rtwdev, RTW89_CHANCTX_REMOTE_STA_CHANGE); + } + + return 0; + } + +-int rtw89_core_sta_disassoc(struct rtw89_dev *rtwdev, +- struct ieee80211_vif *vif, +- struct ieee80211_sta *sta) ++int rtw89_core_sta_link_disassoc(struct rtw89_dev *rtwdev, ++ struct rtw89_vif_link *rtwvif_link, ++ struct rtw89_sta_link *rtwsta_link) + { +- struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv; +- struct rtw89_sta_link *rtwsta_link = (struct rtw89_sta_link *)sta->drv_priv; ++ struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif_link); + + if (vif->type == NL80211_IFTYPE_STATION) +- rtw89_fw_h2c_set_bcn_fltr_cfg(rtwdev, vif, false); +- +- rtwdev->total_sta_assoc--; +- if (sta->tdls) +- rtwvif_link->tdls_peer--; +- rtwsta_link->disassoc = true; ++ rtw89_fw_h2c_set_bcn_fltr_cfg(rtwdev, rtwvif_link, false); + + return 0; + } + +-int rtw89_core_sta_disconnect(struct rtw89_dev *rtwdev, +- struct ieee80211_vif *vif, +- struct ieee80211_sta *sta) ++int rtw89_core_sta_link_disconnect(struct rtw89_dev *rtwdev, ++ struct rtw89_vif_link *rtwvif_link, ++ struct rtw89_sta_link *rtwsta_link) + { +- struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv; +- struct rtw89_sta_link *rtwsta_link = (struct rtw89_sta_link *)sta->drv_priv; ++ struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif_link); ++ struct ieee80211_sta *sta = rtwsta_to_sta(rtwsta_link); + int ret; + +- rtw89_mac_bf_monitor_calc(rtwdev, sta, true); +- rtw89_mac_bf_disassoc(rtwdev, vif, sta); +- rtw89_core_free_sta_pending_ba(rtwdev, sta); +- rtw89_core_free_sta_pending_forbid_ba(rtwdev, sta); +- rtw89_core_free_sta_pending_roc_tx(rtwdev, sta); ++ rtw89_mac_bf_monitor_calc(rtwdev, rtwsta_link, true); ++ rtw89_mac_bf_disassoc(rtwdev, rtwvif_link, rtwsta_link); + + if (vif->type == NL80211_IFTYPE_AP || sta->tdls) + rtw89_cam_deinit_addr_cam(rtwdev, &rtwsta_link->addr_cam); +@@ -3642,7 +3615,7 @@ int rtw89_core_sta_disconnect(struct rtw89_dev *rtwdev, + rtw89_fw_release_general_pkt_list_vif(rtwdev, rtwvif_link, true); + } + +- ret = rtw89_chip_h2c_assoc_cmac_tbl(rtwdev, vif, sta); ++ ret = rtw89_chip_h2c_assoc_cmac_tbl(rtwdev, rtwvif_link, rtwsta_link); + if (ret) { + rtw89_warn(rtwdev, "failed to send h2c cmac table\n"); + return ret; +@@ -3664,12 +3637,12 @@ int rtw89_core_sta_disconnect(struct rtw89_dev *rtwdev, + return ret; + } + +-int rtw89_core_sta_assoc(struct rtw89_dev *rtwdev, +- struct ieee80211_vif *vif, +- struct ieee80211_sta *sta) ++int rtw89_core_sta_link_assoc(struct rtw89_dev *rtwdev, ++ struct rtw89_vif_link *rtwvif_link, ++ struct rtw89_sta_link *rtwsta_link) + { +- struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv; +- struct rtw89_sta_link *rtwsta_link = (struct rtw89_sta_link *)sta->drv_priv; ++ struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif_link); ++ struct ieee80211_sta *sta = rtwsta_to_sta(rtwsta_link); + struct rtw89_bssid_cam_entry *bssid_cam = rtw89_get_bssid_cam_of(rtwvif_link, + rtwsta_link); + const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, +@@ -3701,7 +3674,7 @@ int rtw89_core_sta_assoc(struct rtw89_dev *rtwdev, + } + } + +- ret = rtw89_chip_h2c_assoc_cmac_tbl(rtwdev, vif, sta); ++ ret = rtw89_chip_h2c_assoc_cmac_tbl(rtwdev, rtwvif_link, rtwsta_link); + if (ret) { + rtw89_warn(rtwdev, "failed to send h2c cmac table\n"); + return ret; +@@ -3720,12 +3693,9 @@ int rtw89_core_sta_assoc(struct rtw89_dev *rtwdev, + return ret; + } + +- rtwdev->total_sta_assoc++; +- if (sta->tdls) +- rtwvif_link->tdls_peer++; +- rtw89_phy_ra_assoc(rtwdev, sta); +- rtw89_mac_bf_assoc(rtwdev, vif, sta); +- rtw89_mac_bf_monitor_calc(rtwdev, sta, false); ++ rtw89_phy_ra_assoc(rtwdev, rtwsta_link); ++ rtw89_mac_bf_assoc(rtwdev, rtwvif_link, rtwsta_link); ++ rtw89_mac_bf_monitor_calc(rtwdev, rtwsta_link, false); + + if (vif->type == NL80211_IFTYPE_STATION && !sta->tdls) { + struct ieee80211_bss_conf *bss_conf; +@@ -3750,18 +3720,18 @@ int rtw89_core_sta_assoc(struct rtw89_dev *rtwdev, + return ret; + } + +- rtw89_fw_h2c_set_bcn_fltr_cfg(rtwdev, vif, true); ++ rtw89_fw_h2c_set_bcn_fltr_cfg(rtwdev, rtwvif_link, true); + } + + return ret; + } + +-int rtw89_core_sta_remove(struct rtw89_dev *rtwdev, +- struct ieee80211_vif *vif, +- struct ieee80211_sta *sta) ++int rtw89_core_sta_link_remove(struct rtw89_dev *rtwdev, ++ struct rtw89_vif_link *rtwvif_link, ++ struct rtw89_sta_link *rtwsta_link) + { +- struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv; +- struct rtw89_sta_link *rtwsta_link = (struct rtw89_sta_link *)sta->drv_priv; ++ struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif_link); ++ struct ieee80211_sta *sta = rtwsta_to_sta(rtwsta_link); + int ret; + + if (vif->type == NL80211_IFTYPE_STATION && !sta->tdls) { +@@ -3769,16 +3739,12 @@ int rtw89_core_sta_remove(struct rtw89_dev *rtwdev, + rtw89_btc_ntfy_role_info(rtwdev, rtwvif_link, rtwsta_link, + BTC_ROLE_MSTS_STA_DIS_CONN); + } else if (vif->type == NL80211_IFTYPE_AP || sta->tdls) { +- rtw89_release_mac_id(rtwdev, rtwsta_link->mac_id); +- + ret = rtw89_fw_h2c_role_maintain(rtwdev, rtwvif_link, rtwsta_link, + RTW89_ROLE_REMOVE); + if (ret) { + rtw89_warn(rtwdev, "failed to send h2c role info\n"); + return ret; + } +- +- rtw89_queue_chanctx_change(rtwdev, RTW89_CHANCTX_REMOTE_STA_CHANGE); + } + + return 0; +diff --git a/drivers/net/wireless/realtek/rtw89/core.h b/drivers/net/wireless/realtek/rtw89/core.h +index 2b3976c6daf72..bfa3dba07fe1e 100644 +--- a/drivers/net/wireless/realtek/rtw89/core.h ++++ b/drivers/net/wireless/realtek/rtw89/core.h +@@ -3656,8 +3656,8 @@ struct rtw89_chip_ops { + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link); + int (*h2c_assoc_cmac_tbl)(struct rtw89_dev *rtwdev, +- struct ieee80211_vif *vif, +- struct ieee80211_sta *sta); ++ struct rtw89_vif_link *rtwvif_link, ++ struct rtw89_sta_link *rtwsta_link); + int (*h2c_ampdu_cmac_tbl)(struct rtw89_dev *rtwdev, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta); +@@ -6656,21 +6656,21 @@ void rtw89_core_napi_start(struct rtw89_dev *rtwdev); + void rtw89_core_napi_stop(struct rtw89_dev *rtwdev); + int rtw89_core_napi_init(struct rtw89_dev *rtwdev); + void rtw89_core_napi_deinit(struct rtw89_dev *rtwdev); +-int rtw89_core_sta_add(struct rtw89_dev *rtwdev, +- struct ieee80211_vif *vif, +- struct ieee80211_sta *sta); +-int rtw89_core_sta_assoc(struct rtw89_dev *rtwdev, +- struct ieee80211_vif *vif, +- struct ieee80211_sta *sta); +-int rtw89_core_sta_disassoc(struct rtw89_dev *rtwdev, +- struct ieee80211_vif *vif, +- struct ieee80211_sta *sta); +-int rtw89_core_sta_disconnect(struct rtw89_dev *rtwdev, +- struct ieee80211_vif *vif, +- struct ieee80211_sta *sta); +-int rtw89_core_sta_remove(struct rtw89_dev *rtwdev, +- struct ieee80211_vif *vif, +- struct ieee80211_sta *sta); ++int rtw89_core_sta_link_add(struct rtw89_dev *rtwdev, ++ struct rtw89_vif_link *rtwvif_link, ++ struct rtw89_sta_link *rtwsta_link); ++int rtw89_core_sta_link_assoc(struct rtw89_dev *rtwdev, ++ struct rtw89_vif_link *rtwvif_link, ++ struct rtw89_sta_link *rtwsta_link); ++int rtw89_core_sta_link_disassoc(struct rtw89_dev *rtwdev, ++ struct rtw89_vif_link *rtwvif_link, ++ struct rtw89_sta_link *rtwsta_link); ++int rtw89_core_sta_link_disconnect(struct rtw89_dev *rtwdev, ++ struct rtw89_vif_link *rtwvif_link, ++ struct rtw89_sta_link *rtwsta_link); ++int rtw89_core_sta_link_remove(struct rtw89_dev *rtwdev, ++ struct rtw89_vif_link *rtwvif_link, ++ struct rtw89_sta_link *rtwsta_link); + void rtw89_core_set_tid_config(struct rtw89_dev *rtwdev, + struct ieee80211_sta *sta, + struct cfg80211_tid_config *tid_config); +@@ -6702,6 +6702,12 @@ int rtw89_core_acquire_sta_ba_entry(struct rtw89_dev *rtwdev, + int rtw89_core_release_sta_ba_entry(struct rtw89_dev *rtwdev, + struct rtw89_sta_link *rtwsta_link, u8 tid, + u8 *cam_idx); ++void rtw89_core_free_sta_pending_ba(struct rtw89_dev *rtwdev, ++ struct ieee80211_sta *sta); ++void rtw89_core_free_sta_pending_forbid_ba(struct rtw89_dev *rtwdev, ++ struct ieee80211_sta *sta); ++void rtw89_core_free_sta_pending_roc_tx(struct rtw89_dev *rtwdev, ++ struct ieee80211_sta *sta); + void rtw89_vif_type_mapping(struct rtw89_vif_link *rtwvif_link, bool assoc); + int rtw89_chip_info_setup(struct rtw89_dev *rtwdev); + void rtw89_chip_cfg_txpwr_ul_tb_offset(struct rtw89_dev *rtwdev, +diff --git a/drivers/net/wireless/realtek/rtw89/fw.c b/drivers/net/wireless/realtek/rtw89/fw.c +index 52e5dbe7e59db..8e890ebae6134 100644 +--- a/drivers/net/wireless/realtek/rtw89/fw.c ++++ b/drivers/net/wireless/realtek/rtw89/fw.c +@@ -2831,12 +2831,11 @@ static void __get_sta_he_pkt_padding(struct rtw89_dev *rtwdev, + } + + int rtw89_fw_h2c_assoc_cmac_tbl(struct rtw89_dev *rtwdev, +- struct ieee80211_vif *vif, +- struct ieee80211_sta *sta) ++ struct rtw89_vif_link *rtwvif_link, ++ struct rtw89_sta_link *rtwsta_link) + { ++ struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif_link); + const struct rtw89_chip_info *chip = rtwdev->chip; +- struct rtw89_sta_link *rtwsta_link = sta_to_rtwsta_safe(sta); +- struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv; + const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, + rtwvif_link->chanctx_idx); + struct ieee80211_link_sta *link_sta; +@@ -2979,11 +2978,10 @@ static void __get_sta_eht_pkt_padding(struct rtw89_dev *rtwdev, + } + + int rtw89_fw_h2c_assoc_cmac_tbl_g7(struct rtw89_dev *rtwdev, +- struct ieee80211_vif *vif, +- struct ieee80211_sta *sta) ++ struct rtw89_vif_link *rtwvif_link, ++ struct rtw89_sta_link *rtwsta_link) + { +- struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv; +- struct rtw89_sta_link *rtwsta_link = sta_to_rtwsta_safe(sta); ++ struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif_link); + const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, rtwvif_link->chanctx_idx); + u8 mac_id = rtwsta_link ? rtwsta_link->mac_id : rtwvif_link->mac_id; + struct rtw89_h2c_cctlinfo_ud_g7 *h2c; +@@ -3788,10 +3786,9 @@ int rtw89_fw_h2c_set_ofld_cfg(struct rtw89_dev *rtwdev) + } + + int rtw89_fw_h2c_set_bcn_fltr_cfg(struct rtw89_dev *rtwdev, +- struct ieee80211_vif *vif, ++ struct rtw89_vif_link *rtwvif_link, + bool connect) + { +- struct rtw89_vif_link *rtwvif_link = vif_to_rtwvif_safe(vif); + struct ieee80211_bss_conf *bss_conf; + s32 thold = RTW89_DEFAULT_CQM_THOLD; + u32 hyst = RTW89_DEFAULT_CQM_HYST; +diff --git a/drivers/net/wireless/realtek/rtw89/fw.h b/drivers/net/wireless/realtek/rtw89/fw.h +index b13512c3feb28..17e952bd70e36 100644 +--- a/drivers/net/wireless/realtek/rtw89/fw.h ++++ b/drivers/net/wireless/realtek/rtw89/fw.h +@@ -4413,11 +4413,11 @@ int rtw89_fw_h2c_default_dmac_tbl_v2(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link); + int rtw89_fw_h2c_assoc_cmac_tbl(struct rtw89_dev *rtwdev, +- struct ieee80211_vif *vif, +- struct ieee80211_sta *sta); ++ struct rtw89_vif_link *rtwvif_link, ++ struct rtw89_sta_link *rtwsta_link); + int rtw89_fw_h2c_assoc_cmac_tbl_g7(struct rtw89_dev *rtwdev, +- struct ieee80211_vif *vif, +- struct ieee80211_sta *sta); ++ struct rtw89_vif_link *rtwvif_link, ++ struct rtw89_sta_link *rtwsta_link); + int rtw89_fw_h2c_ampdu_cmac_tbl_g7(struct rtw89_dev *rtwdev, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta); +@@ -4452,7 +4452,7 @@ int rtw89_fw_h2c_set_edca(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvi + u8 ac, u32 val); + int rtw89_fw_h2c_set_ofld_cfg(struct rtw89_dev *rtwdev); + int rtw89_fw_h2c_set_bcn_fltr_cfg(struct rtw89_dev *rtwdev, +- struct ieee80211_vif *vif, ++ struct rtw89_vif_link *rtwvif_link, + bool connect); + int rtw89_fw_h2c_rssi_offload(struct rtw89_dev *rtwdev, + struct rtw89_rx_phy_ppdu *phy_ppdu); +@@ -4654,12 +4654,12 @@ static inline int rtw89_chip_h2c_update_beacon(struct rtw89_dev *rtwdev, + } + + static inline int rtw89_chip_h2c_assoc_cmac_tbl(struct rtw89_dev *rtwdev, +- struct ieee80211_vif *vif, +- struct ieee80211_sta *sta) ++ struct rtw89_vif_link *rtwvif_link, ++ struct rtw89_sta_link *rtwsta_link) + { + const struct rtw89_chip_info *chip = rtwdev->chip; + +- return chip->ops->h2c_assoc_cmac_tbl(rtwdev, vif, sta); ++ return chip->ops->h2c_assoc_cmac_tbl(rtwdev, rtwvif_link, rtwsta_link); + } + + static inline int rtw89_chip_h2c_ampdu_cmac_tbl(struct rtw89_dev *rtwdev, +diff --git a/drivers/net/wireless/realtek/rtw89/mac.c b/drivers/net/wireless/realtek/rtw89/mac.c +index a7b89a25d7c46..28cc4885105a5 100644 +--- a/drivers/net/wireless/realtek/rtw89/mac.c ++++ b/drivers/net/wireless/realtek/rtw89/mac.c +@@ -4877,7 +4877,7 @@ rtw89_mac_bcn_fltr_rpt(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_l + if (!rtwdev->scanning && !rtwvif_link->offchan) + ieee80211_connection_loss(vif); + else +- rtw89_fw_h2c_set_bcn_fltr_cfg(rtwdev, vif, true); ++ rtw89_fw_h2c_set_bcn_fltr_cfg(rtwdev, rtwvif_link, true); + return; + case RTW89_BCN_FLTR_NOTIFY: + nl_event = NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH; +@@ -5969,11 +5969,9 @@ static int rtw89_mac_init_bfee_ax(struct rtw89_dev *rtwdev, u8 mac_idx) + } + + static int rtw89_mac_set_csi_para_reg_ax(struct rtw89_dev *rtwdev, +- struct ieee80211_vif *vif, +- struct ieee80211_sta *sta) ++ struct rtw89_vif_link *rtwvif_link, ++ struct rtw89_sta_link *rtwsta_link) + { +- struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv; +- struct rtw89_sta_link *rtwsta_link = (struct rtw89_sta_link *)sta->drv_priv; + u8 nc = 1, nr = 3, ng = 0, cb = 1, cs = 1, ldpc_en = 1, stbc_en = 1; + struct ieee80211_link_sta *link_sta; + u8 mac_idx = rtwvif_link->mac_idx; +@@ -6036,11 +6034,9 @@ static int rtw89_mac_set_csi_para_reg_ax(struct rtw89_dev *rtwdev, + } + + static int rtw89_mac_csi_rrsc_ax(struct rtw89_dev *rtwdev, +- struct ieee80211_vif *vif, +- struct ieee80211_sta *sta) ++ struct rtw89_vif_link *rtwvif_link, ++ struct rtw89_sta_link *rtwsta_link) + { +- struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv; +- struct rtw89_sta_link *rtwsta_link = (struct rtw89_sta_link *)sta->drv_priv; + u32 rrsc = BIT(RTW89_MAC_BF_RRSC_6M) | BIT(RTW89_MAC_BF_RRSC_24M); + struct ieee80211_link_sta *link_sta; + u8 mac_idx = rtwvif_link->mac_idx; +@@ -6084,11 +6080,9 @@ static int rtw89_mac_csi_rrsc_ax(struct rtw89_dev *rtwdev, + } + + static void rtw89_mac_bf_assoc_ax(struct rtw89_dev *rtwdev, +- struct ieee80211_vif *vif, +- struct ieee80211_sta *sta) ++ struct rtw89_vif_link *rtwvif_link, ++ struct rtw89_sta_link *rtwsta_link) + { +- struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv; +- struct rtw89_sta_link *rtwsta_link = (struct rtw89_sta_link *)sta->drv_priv; + struct ieee80211_link_sta *link_sta; + bool has_beamformer_cap; + +@@ -6103,16 +6097,15 @@ static void rtw89_mac_bf_assoc_ax(struct rtw89_dev *rtwdev, + rtw89_debug(rtwdev, RTW89_DBG_BF, + "initialize bfee for new association\n"); + rtw89_mac_init_bfee_ax(rtwdev, rtwvif_link->mac_idx); +- rtw89_mac_set_csi_para_reg_ax(rtwdev, vif, sta); +- rtw89_mac_csi_rrsc_ax(rtwdev, vif, sta); ++ rtw89_mac_set_csi_para_reg_ax(rtwdev, rtwvif_link, rtwsta_link); ++ rtw89_mac_csi_rrsc_ax(rtwdev, rtwvif_link, rtwsta_link); + } + } + +-void rtw89_mac_bf_disassoc(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif, +- struct ieee80211_sta *sta) ++void rtw89_mac_bf_disassoc(struct rtw89_dev *rtwdev, ++ struct rtw89_vif_link *rtwvif_link, ++ struct rtw89_sta_link *rtwsta_link) + { +- struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv; +- + rtw89_mac_bfee_ctrl(rtwdev, rtwvif_link->mac_idx, false); + } + +@@ -6146,7 +6139,7 @@ void rtw89_mac_bf_set_gid_table(struct rtw89_dev *rtwdev, struct ieee80211_vif * + + struct rtw89_mac_bf_monitor_iter_data { + struct rtw89_dev *rtwdev; +- struct ieee80211_sta *down_sta; ++ struct rtw89_sta_link *down_rtwsta_link; + int count; + }; + +@@ -6156,11 +6149,11 @@ void rtw89_mac_bf_monitor_calc_iter(void *data, struct ieee80211_sta *sta) + struct rtw89_sta_link *rtwsta_link = (struct rtw89_sta_link *)sta->drv_priv; + struct rtw89_mac_bf_monitor_iter_data *iter_data = + (struct rtw89_mac_bf_monitor_iter_data *)data; +- struct ieee80211_sta *down_sta = iter_data->down_sta; ++ struct rtw89_sta_link *down_rtwsta_link = iter_data->down_rtwsta_link; + struct ieee80211_link_sta *link_sta; + int *count = &iter_data->count; + +- if (down_sta == sta) ++ if (down_rtwsta_link == rtwsta_link) + return; + + rcu_read_lock(); +@@ -6173,12 +6166,13 @@ void rtw89_mac_bf_monitor_calc_iter(void *data, struct ieee80211_sta *sta) + } + + void rtw89_mac_bf_monitor_calc(struct rtw89_dev *rtwdev, +- struct ieee80211_sta *sta, bool disconnect) ++ struct rtw89_sta_link *rtwsta_link, ++ bool disconnect) + { + struct rtw89_mac_bf_monitor_iter_data data; + + data.rtwdev = rtwdev; +- data.down_sta = disconnect ? sta : NULL; ++ data.down_rtwsta_link = disconnect ? rtwsta_link : NULL; + data.count = 0; + ieee80211_iterate_stations_atomic(rtwdev->hw, + rtw89_mac_bf_monitor_calc_iter, +diff --git a/drivers/net/wireless/realtek/rtw89/mac.h b/drivers/net/wireless/realtek/rtw89/mac.h +index f2a31cba226e9..b781b823496f6 100644 +--- a/drivers/net/wireless/realtek/rtw89/mac.h ++++ b/drivers/net/wireless/realtek/rtw89/mac.h +@@ -951,8 +951,9 @@ struct rtw89_mac_gen_def { + void (*dmac_func_pre_en)(struct rtw89_dev *rtwdev); + void (*dle_func_en)(struct rtw89_dev *rtwdev, bool enable); + void (*dle_clk_en)(struct rtw89_dev *rtwdev, bool enable); +- void (*bf_assoc)(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif, +- struct ieee80211_sta *sta); ++ void (*bf_assoc)(struct rtw89_dev *rtwdev, ++ struct rtw89_vif_link *rtwvif_link, ++ struct rtw89_sta_link *rtwsta_link); + + int (*typ_fltr_opt)(struct rtw89_dev *rtwdev, + enum rtw89_machdr_frame_type type, +@@ -1259,21 +1260,24 @@ void rtw89_mac_power_mode_change(struct rtw89_dev *rtwdev, bool enter); + void rtw89_mac_notify_wake(struct rtw89_dev *rtwdev); + + static inline +-void rtw89_mac_bf_assoc(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif, +- struct ieee80211_sta *sta) ++void rtw89_mac_bf_assoc(struct rtw89_dev *rtwdev, ++ struct rtw89_vif_link *rtwvif_link, ++ struct rtw89_sta_link *rtwsta_link) + { + const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; + + if (mac->bf_assoc) +- mac->bf_assoc(rtwdev, vif, sta); ++ mac->bf_assoc(rtwdev, rtwvif_link, rtwsta_link); + } + +-void rtw89_mac_bf_disassoc(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif, +- struct ieee80211_sta *sta); ++void rtw89_mac_bf_disassoc(struct rtw89_dev *rtwdev, ++ struct rtw89_vif_link *rtwvif_link, ++ struct rtw89_sta_link *rtwsta_link); + void rtw89_mac_bf_set_gid_table(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif, + struct ieee80211_bss_conf *conf); + void rtw89_mac_bf_monitor_calc(struct rtw89_dev *rtwdev, +- struct ieee80211_sta *sta, bool disconnect); ++ struct rtw89_sta_link *rtwsta_link, ++ bool disconnect); + void _rtw89_mac_bf_monitor_track(struct rtw89_dev *rtwdev); + void rtw89_mac_bfee_ctrl(struct rtw89_dev *rtwdev, u8 mac_idx, bool en); + int rtw89_mac_vif_init(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link); +diff --git a/drivers/net/wireless/realtek/rtw89/mac80211.c b/drivers/net/wireless/realtek/rtw89/mac80211.c +index d3fad66e56cd8..fc05ad1b799bf 100644 +--- a/drivers/net/wireless/realtek/rtw89/mac80211.c ++++ b/drivers/net/wireless/realtek/rtw89/mac80211.c +@@ -456,10 +456,140 @@ static void rtw89_conf_tx(struct rtw89_dev *rtwdev, + __rtw89_conf_tx(rtwdev, rtwvif_link, ac); + } + ++static int __rtw89_ops_sta_add(struct rtw89_dev *rtwdev, ++ struct ieee80211_vif *vif, ++ struct ieee80211_sta *sta) ++{ ++ struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv; ++ struct rtw89_sta_link *rtwsta_link = (struct rtw89_sta_link *)sta->drv_priv; ++ bool acquire_macid = false; ++ u8 macid; ++ int ret; ++ int i; ++ ++ if (vif->type == NL80211_IFTYPE_STATION && !sta->tdls) { ++ /* for station mode, assign the mac_id from itself */ ++ macid = rtwvif_link->mac_id; ++ } else { ++ macid = rtw89_acquire_mac_id(rtwdev); ++ if (macid == RTW89_MAX_MAC_ID_NUM) ++ return -ENOSPC; ++ ++ acquire_macid = true; ++ } ++ ++ rtwsta_link->rtwdev = rtwdev; ++ rtwsta_link->rtwvif_link = rtwvif_link; ++ rtwsta_link->mac_id = macid; ++ ++ for (i = 0; i < ARRAY_SIZE(sta->txq); i++) ++ rtw89_core_txq_init(rtwdev, sta->txq[i]); ++ ++ skb_queue_head_init(&rtwsta_link->roc_queue); ++ ++ ret = rtw89_core_sta_link_add(rtwdev, rtwvif_link, rtwsta_link); ++ if (ret) ++ goto err; ++ ++ if (vif->type == NL80211_IFTYPE_AP || sta->tdls) ++ rtw89_queue_chanctx_change(rtwdev, RTW89_CHANCTX_REMOTE_STA_CHANGE); ++ ++ return 0; ++ ++err: ++ if (acquire_macid) ++ rtw89_release_mac_id(rtwdev, macid); ++ ++ return ret; ++} ++ ++static int __rtw89_ops_sta_assoc(struct rtw89_dev *rtwdev, ++ struct ieee80211_vif *vif, ++ struct ieee80211_sta *sta, ++ bool station_mode) ++{ ++ struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv; ++ struct rtw89_sta_link *rtwsta_link = (struct rtw89_sta_link *)sta->drv_priv; ++ int ret; ++ ++ if (station_mode) ++ rtw89_vif_type_mapping(rtwvif_link, true); ++ ++ ret = rtw89_core_sta_link_assoc(rtwdev, rtwvif_link, rtwsta_link); ++ if (ret) ++ return ret; ++ ++ rtwdev->total_sta_assoc++; ++ if (sta->tdls) ++ rtwvif_link->tdls_peer++; ++ ++ return 0; ++} ++ ++static int __rtw89_ops_sta_disassoc(struct rtw89_dev *rtwdev, ++ struct ieee80211_vif *vif, ++ struct ieee80211_sta *sta) ++{ ++ struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv; ++ struct rtw89_sta_link *rtwsta_link = (struct rtw89_sta_link *)sta->drv_priv; ++ int ret; ++ ++ ret = rtw89_core_sta_link_disassoc(rtwdev, rtwvif_link, rtwsta_link); ++ if (ret) ++ return ret; ++ ++ rtwsta_link->disassoc = true; ++ ++ rtwdev->total_sta_assoc--; ++ if (sta->tdls) ++ rtwvif_link->tdls_peer--; ++ ++ return 0; ++} ++ ++static int __rtw89_ops_sta_disconnect(struct rtw89_dev *rtwdev, ++ struct ieee80211_vif *vif, ++ struct ieee80211_sta *sta) ++{ ++ struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv; ++ struct rtw89_sta_link *rtwsta_link = (struct rtw89_sta_link *)sta->drv_priv; ++ int ret; ++ ++ rtw89_core_free_sta_pending_ba(rtwdev, sta); ++ rtw89_core_free_sta_pending_forbid_ba(rtwdev, sta); ++ rtw89_core_free_sta_pending_roc_tx(rtwdev, sta); ++ ++ ret = rtw89_core_sta_link_disconnect(rtwdev, rtwvif_link, rtwsta_link); ++ if (ret) ++ return ret; ++ ++ return 0; ++} ++ ++static int __rtw89_ops_sta_remove(struct rtw89_dev *rtwdev, ++ struct ieee80211_vif *vif, ++ struct ieee80211_sta *sta) ++{ ++ struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv; ++ struct rtw89_sta_link *rtwsta_link = (struct rtw89_sta_link *)sta->drv_priv; ++ u8 macid = rtwsta_link->mac_id; ++ int ret; ++ ++ ret = rtw89_core_sta_link_remove(rtwdev, rtwvif_link, rtwsta_link); ++ if (ret) ++ return ret; ++ ++ if (vif->type == NL80211_IFTYPE_AP || sta->tdls) { ++ rtw89_release_mac_id(rtwdev, macid); ++ rtw89_queue_chanctx_change(rtwdev, RTW89_CHANCTX_REMOTE_STA_CHANGE); ++ } ++ ++ return 0; ++} ++ + static void rtw89_station_mode_sta_assoc(struct rtw89_dev *rtwdev, + struct ieee80211_vif *vif) + { +- struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv; + struct ieee80211_sta *sta; + + if (vif->type != NL80211_IFTYPE_STATION) +@@ -471,9 +601,7 @@ static void rtw89_station_mode_sta_assoc(struct rtw89_dev *rtwdev, + return; + } + +- rtw89_vif_type_mapping(rtwvif_link, true); +- +- rtw89_core_sta_assoc(rtwdev, vif, sta); ++ __rtw89_ops_sta_assoc(rtwdev, vif, sta, true); + } + + static void __rtw89_ops_bss_link_assoc(struct rtw89_dev *rtwdev, +@@ -552,7 +680,7 @@ static void rtw89_ops_link_info_changed(struct ieee80211_hw *hw, + rtw89_core_update_p2p_ps(rtwdev, rtwvif_link, conf); + + if (changed & BSS_CHANGED_CQM) +- rtw89_fw_h2c_set_bcn_fltr_cfg(rtwdev, vif, true); ++ rtw89_fw_h2c_set_bcn_fltr_cfg(rtwdev, rtwvif_link, true); + + if (changed & BSS_CHANGED_TPE) + rtw89_reg_6ghz_recalc(rtwdev, rtwvif_link, true); +@@ -582,7 +710,7 @@ static int rtw89_ops_start_ap(struct ieee80211_hw *hw, + ether_addr_copy(rtwvif_link->bssid, link_conf->bssid); + rtw89_cam_bssid_changed(rtwdev, rtwvif_link); + rtw89_mac_port_update(rtwdev, rtwvif_link); +- rtw89_chip_h2c_assoc_cmac_tbl(rtwdev, vif, NULL); ++ rtw89_chip_h2c_assoc_cmac_tbl(rtwdev, rtwvif_link, NULL); + rtw89_fw_h2c_role_maintain(rtwdev, rtwvif_link, NULL, RTW89_ROLE_TYPE_CHANGE); + rtw89_fw_h2c_join_info(rtwdev, rtwvif_link, NULL, true); + rtw89_fw_h2c_cam(rtwdev, rtwvif_link, NULL, NULL); +@@ -603,7 +731,7 @@ void rtw89_ops_stop_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + + mutex_lock(&rtwdev->mutex); + rtw89_mac_stop_ap(rtwdev, rtwvif_link); +- rtw89_chip_h2c_assoc_cmac_tbl(rtwdev, vif, NULL); ++ rtw89_chip_h2c_assoc_cmac_tbl(rtwdev, rtwvif_link, NULL); + rtw89_fw_h2c_join_info(rtwdev, rtwvif_link, NULL, true); + mutex_unlock(&rtwdev->mutex); + } +@@ -647,26 +775,26 @@ static int __rtw89_ops_sta_state(struct ieee80211_hw *hw, + + if (old_state == IEEE80211_STA_NOTEXIST && + new_state == IEEE80211_STA_NONE) +- return rtw89_core_sta_add(rtwdev, vif, sta); ++ return __rtw89_ops_sta_add(rtwdev, vif, sta); + + if (old_state == IEEE80211_STA_AUTH && + new_state == IEEE80211_STA_ASSOC) { + if (vif->type == NL80211_IFTYPE_STATION && !sta->tdls) + return 0; /* defer to bss_info_changed to have vif info */ +- return rtw89_core_sta_assoc(rtwdev, vif, sta); ++ return __rtw89_ops_sta_assoc(rtwdev, vif, sta, false); + } + + if (old_state == IEEE80211_STA_ASSOC && + new_state == IEEE80211_STA_AUTH) +- return rtw89_core_sta_disassoc(rtwdev, vif, sta); ++ return __rtw89_ops_sta_disassoc(rtwdev, vif, sta); + + if (old_state == IEEE80211_STA_AUTH && + new_state == IEEE80211_STA_NONE) +- return rtw89_core_sta_disconnect(rtwdev, vif, sta); ++ return __rtw89_ops_sta_disconnect(rtwdev, vif, sta); + + if (old_state == IEEE80211_STA_NONE && + new_state == IEEE80211_STA_NOTEXIST) +- return rtw89_core_sta_remove(rtwdev, vif, sta); ++ return __rtw89_ops_sta_remove(rtwdev, vif, sta); + + return 0; + } +diff --git a/drivers/net/wireless/realtek/rtw89/mac_be.c b/drivers/net/wireless/realtek/rtw89/mac_be.c +index 184a014a56bfe..f22eaa83297fb 100644 +--- a/drivers/net/wireless/realtek/rtw89/mac_be.c ++++ b/drivers/net/wireless/realtek/rtw89/mac_be.c +@@ -2091,11 +2091,9 @@ static int rtw89_mac_init_bfee_be(struct rtw89_dev *rtwdev, u8 mac_idx) + } + + static int rtw89_mac_set_csi_para_reg_be(struct rtw89_dev *rtwdev, +- struct ieee80211_vif *vif, +- struct ieee80211_sta *sta) ++ struct rtw89_vif_link *rtwvif_link, ++ struct rtw89_sta_link *rtwsta_link) + { +- struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv; +- struct rtw89_sta_link *rtwsta_link = (struct rtw89_sta_link *)sta->drv_priv; + u8 nc = 1, nr = 3, ng = 0, cb = 1, cs = 1, ldpc_en = 1, stbc_en = 1; + struct ieee80211_link_sta *link_sta; + u8 mac_idx = rtwvif_link->mac_idx; +@@ -2162,11 +2160,9 @@ static int rtw89_mac_set_csi_para_reg_be(struct rtw89_dev *rtwdev, + } + + static int rtw89_mac_csi_rrsc_be(struct rtw89_dev *rtwdev, +- struct ieee80211_vif *vif, +- struct ieee80211_sta *sta) ++ struct rtw89_vif_link *rtwvif_link, ++ struct rtw89_sta_link *rtwsta_link) + { +- struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv; +- struct rtw89_sta_link *rtwsta_link = (struct rtw89_sta_link *)sta->drv_priv; + u32 rrsc = BIT(RTW89_MAC_BF_RRSC_6M) | BIT(RTW89_MAC_BF_RRSC_24M); + struct ieee80211_link_sta *link_sta; + u8 mac_idx = rtwvif_link->mac_idx; +@@ -2210,11 +2206,9 @@ static int rtw89_mac_csi_rrsc_be(struct rtw89_dev *rtwdev, + } + + static void rtw89_mac_bf_assoc_be(struct rtw89_dev *rtwdev, +- struct ieee80211_vif *vif, +- struct ieee80211_sta *sta) ++ struct rtw89_vif_link *rtwvif_link, ++ struct rtw89_sta_link *rtwsta_link) + { +- struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv; +- struct rtw89_sta_link *rtwsta_link = (struct rtw89_sta_link *)sta->drv_priv; + struct ieee80211_link_sta *link_sta; + bool has_beamformer_cap; + +@@ -2229,8 +2223,8 @@ static void rtw89_mac_bf_assoc_be(struct rtw89_dev *rtwdev, + rtw89_debug(rtwdev, RTW89_DBG_BF, + "initialize bfee for new association\n"); + rtw89_mac_init_bfee_be(rtwdev, rtwvif_link->mac_idx); +- rtw89_mac_set_csi_para_reg_be(rtwdev, vif, sta); +- rtw89_mac_csi_rrsc_be(rtwdev, vif, sta); ++ rtw89_mac_set_csi_para_reg_be(rtwdev, rtwvif_link, rtwsta_link); ++ rtw89_mac_csi_rrsc_be(rtwdev, rtwvif_link, rtwsta_link); + } + } + +diff --git a/drivers/net/wireless/realtek/rtw89/phy.c b/drivers/net/wireless/realtek/rtw89/phy.c +index f6f2b003c412f..da9491213b7b5 100644 +--- a/drivers/net/wireless/realtek/rtw89/phy.c ++++ b/drivers/net/wireless/realtek/rtw89/phy.c +@@ -637,9 +637,8 @@ void rtw89_phy_ra_update(struct rtw89_dev *rtwdev) + rtwdev); + } + +-void rtw89_phy_ra_assoc(struct rtw89_dev *rtwdev, struct ieee80211_sta *sta) ++void rtw89_phy_ra_assoc(struct rtw89_dev *rtwdev, struct rtw89_sta_link *rtwsta_link) + { +- struct rtw89_sta_link *rtwsta_link = (struct rtw89_sta_link *)sta->drv_priv; + struct rtw89_vif_link *rtwvif_link = rtwsta_link->rtwvif_link; + struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif_link); + struct rtw89_ra_info *ra = &rtwsta_link->ra; +diff --git a/drivers/net/wireless/realtek/rtw89/phy.h b/drivers/net/wireless/realtek/rtw89/phy.h +index 882a473ecf7bc..7e335c02ee6fb 100644 +--- a/drivers/net/wireless/realtek/rtw89/phy.h ++++ b/drivers/net/wireless/realtek/rtw89/phy.h +@@ -892,7 +892,7 @@ void rtw89_phy_set_txpwr_limit_ru(struct rtw89_dev *rtwdev, + phy->set_txpwr_limit_ru(rtwdev, chan, phy_idx); + } + +-void rtw89_phy_ra_assoc(struct rtw89_dev *rtwdev, struct ieee80211_sta *sta); ++void rtw89_phy_ra_assoc(struct rtw89_dev *rtwdev, struct rtw89_sta_link *rtwsta_link); + void rtw89_phy_ra_update(struct rtw89_dev *rtwdev); + void rtw89_phy_ra_update_sta(struct rtw89_dev *rtwdev, struct ieee80211_sta *sta, + u32 changed); +diff --git a/drivers/net/wireless/realtek/rtw89/wow.c b/drivers/net/wireless/realtek/rtw89/wow.c +index 20b776ae634ea..97b527d04ad71 100644 +--- a/drivers/net/wireless/realtek/rtw89/wow.c ++++ b/drivers/net/wireless/realtek/rtw89/wow.c +@@ -1240,7 +1240,7 @@ static int rtw89_wow_swap_fw(struct rtw89_dev *rtwdev, bool wow) + return ret; + } + +- ret = rtw89_chip_h2c_assoc_cmac_tbl(rtwdev, wow_vif, wow_sta); ++ ret = rtw89_chip_h2c_assoc_cmac_tbl(rtwdev, rtwvif_link, rtwsta_link); + if (ret) { + rtw89_warn(rtwdev, "failed to send h2c assoc cmac tbl\n"); + return ret; +@@ -1267,7 +1267,7 @@ static int rtw89_wow_swap_fw(struct rtw89_dev *rtwdev, bool wow) + rtw89_warn(rtwdev, "failed to send h2c general packet\n"); + return ret; + } +- rtw89_phy_ra_assoc(rtwdev, wow_sta); ++ rtw89_phy_ra_assoc(rtwdev, rtwsta_link); + rtw89_phy_set_bss_color(rtwdev, rtwvif_link); + rtw89_chip_cfg_txpwr_ul_tb_offset(rtwdev, rtwvif_link); + } +@@ -1374,13 +1374,14 @@ static int rtw89_wow_disable_trx_post(struct rtw89_dev *rtwdev) + { + struct rtw89_wow_param *rtw_wow = &rtwdev->wow; + struct ieee80211_vif *vif = rtw_wow->wow_vif; ++ struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv; + int ret; + + ret = rtw89_mac_cfg_ppdu_status(rtwdev, RTW89_MAC_0, true); + if (ret) + rtw89_err(rtwdev, "cfg ppdu status\n"); + +- rtw89_fw_h2c_set_bcn_fltr_cfg(rtwdev, vif, true); ++ rtw89_fw_h2c_set_bcn_fltr_cfg(rtwdev, rtwvif_link, true); + + return ret; + } +-- +2.43.0 + diff --git a/queue-6.12/wifi-rtw89-refactor-vif-related-func-ahead-for-mlo.patch b/queue-6.12/wifi-rtw89-refactor-vif-related-func-ahead-for-mlo.patch new file mode 100644 index 00000000000..3498d6435e6 --- /dev/null +++ b/queue-6.12/wifi-rtw89-refactor-vif-related-func-ahead-for-mlo.patch @@ -0,0 +1,412 @@ +From 9c651fbb5d5b74be5169c113165c3f984a5c84a1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Mon, 16 Sep 2024 13:31:56 +0800 +Subject: wifi: rtw89: refactor VIF related func ahead for MLO + +From: Zong-Zhe Yang <kevin_yang@realtek.com> + +[ Upstream commit 26d460e13f84426fa7dd2c0c369676034c206161 ] + +Refactor VIF related functions, e.g. add/remove/assoc/mapping +to separate most link stuffs into sub-functions for MLO reuse. + +Signed-off-by: Zong-Zhe Yang <kevin_yang@realtek.com> +Signed-off-by: Ping-Ke Shih <pkshih@realtek.com> +Link: https://patch.msgid.link/20240916053158.47350-6-pkshih@realtek.com +Stable-dep-of: f16c40acd319 ("wifi: rtw89: Fix TX fail with A2DP after scanning") +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/net/wireless/realtek/rtw89/core.c | 10 +- + drivers/net/wireless/realtek/rtw89/core.h | 4 +- + drivers/net/wireless/realtek/rtw89/mac.c | 28 +--- + drivers/net/wireless/realtek/rtw89/mac.h | 2 +- + drivers/net/wireless/realtek/rtw89/mac80211.c | 137 ++++++++++++------ + drivers/net/wireless/realtek/rtw89/phy.c | 5 +- + drivers/net/wireless/realtek/rtw89/phy.h | 3 +- + drivers/net/wireless/realtek/rtw89/wow.c | 4 +- + 8 files changed, 112 insertions(+), 81 deletions(-) + +diff --git a/drivers/net/wireless/realtek/rtw89/core.c b/drivers/net/wireless/realtek/rtw89/core.c +index 84c1952fbea88..c6d3b8fd98b65 100644 +--- a/drivers/net/wireless/realtek/rtw89/core.c ++++ b/drivers/net/wireless/realtek/rtw89/core.c +@@ -3466,9 +3466,9 @@ int rtw89_core_release_sta_ba_entry(struct rtw89_dev *rtwdev, + case NL80211_IFTYPE_ ## _type: \ + rtwvif_link->wifi_role = RTW89_WIFI_ROLE_ ## _type; \ + break +-void rtw89_vif_type_mapping(struct ieee80211_vif *vif, bool assoc) ++void rtw89_vif_type_mapping(struct rtw89_vif_link *rtwvif_link, bool assoc) + { +- struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv; ++ const struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif_link); + const struct ieee80211_bss_conf *bss_conf; + + switch (vif->type) { +@@ -3638,7 +3638,7 @@ int rtw89_core_sta_disconnect(struct rtw89_dev *rtwdev, + rtw89_cam_deinit_bssid_cam(rtwdev, &rtwsta_link->bssid_cam); + + if (vif->type == NL80211_IFTYPE_STATION && !sta->tdls) { +- rtw89_vif_type_mapping(vif, false); ++ rtw89_vif_type_mapping(rtwvif_link, false); + rtw89_fw_release_general_pkt_list_vif(rtwdev, rtwvif_link, true); + } + +@@ -4785,9 +4785,9 @@ int rtw89_chip_info_setup(struct rtw89_dev *rtwdev) + EXPORT_SYMBOL(rtw89_chip_info_setup); + + void rtw89_chip_cfg_txpwr_ul_tb_offset(struct rtw89_dev *rtwdev, +- struct ieee80211_vif *vif) ++ struct rtw89_vif_link *rtwvif_link) + { +- struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv; ++ struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif_link); + const struct rtw89_chip_info *chip = rtwdev->chip; + struct ieee80211_bss_conf *bss_conf; + +diff --git a/drivers/net/wireless/realtek/rtw89/core.h b/drivers/net/wireless/realtek/rtw89/core.h +index 274051e53f19c..2b3976c6daf72 100644 +--- a/drivers/net/wireless/realtek/rtw89/core.h ++++ b/drivers/net/wireless/realtek/rtw89/core.h +@@ -6702,10 +6702,10 @@ int rtw89_core_acquire_sta_ba_entry(struct rtw89_dev *rtwdev, + int rtw89_core_release_sta_ba_entry(struct rtw89_dev *rtwdev, + struct rtw89_sta_link *rtwsta_link, u8 tid, + u8 *cam_idx); +-void rtw89_vif_type_mapping(struct ieee80211_vif *vif, bool assoc); ++void rtw89_vif_type_mapping(struct rtw89_vif_link *rtwvif_link, bool assoc); + int rtw89_chip_info_setup(struct rtw89_dev *rtwdev); + void rtw89_chip_cfg_txpwr_ul_tb_offset(struct rtw89_dev *rtwdev, +- struct ieee80211_vif *vif); ++ struct rtw89_vif_link *rtwvif_link); + bool rtw89_ra_report_to_bitrate(struct rtw89_dev *rtwdev, u8 rpt_rate, u16 *bitrate); + int rtw89_regd_setup(struct rtw89_dev *rtwdev); + int rtw89_regd_init(struct rtw89_dev *rtwdev, +diff --git a/drivers/net/wireless/realtek/rtw89/mac.c b/drivers/net/wireless/realtek/rtw89/mac.c +index 7ab2aac3c3d22..a7b89a25d7c46 100644 +--- a/drivers/net/wireless/realtek/rtw89/mac.c ++++ b/drivers/net/wireless/realtek/rtw89/mac.c +@@ -4697,9 +4697,9 @@ static void rtw89_mac_check_he_obss_narrow_bw_ru_iter(struct wiphy *wiphy, + } + + void rtw89_mac_set_he_obss_narrow_bw_ru(struct rtw89_dev *rtwdev, +- struct ieee80211_vif *vif) ++ struct rtw89_vif_link *rtwvif_link) + { +- struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv; ++ struct ieee80211_vif *vif = rtwvif_to_vif_safe(rtwvif_link); + const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; + struct ieee80211_hw *hw = rtwdev->hw; + struct ieee80211_bss_conf *bss_conf; +@@ -4742,32 +4742,12 @@ void rtw89_mac_stop_ap(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_l + + int rtw89_mac_add_vif(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link) + { +- int ret; +- +- rtwvif_link->mac_id = rtw89_acquire_mac_id(rtwdev); +- if (rtwvif_link->mac_id == RTW89_MAX_MAC_ID_NUM) +- return -ENOSPC; +- +- ret = rtw89_mac_vif_init(rtwdev, rtwvif_link); +- if (ret) +- goto release_mac_id; +- +- return 0; +- +-release_mac_id: +- rtw89_release_mac_id(rtwdev, rtwvif_link->mac_id); +- +- return ret; ++ return rtw89_mac_vif_init(rtwdev, rtwvif_link); + } + + int rtw89_mac_remove_vif(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link) + { +- int ret; +- +- ret = rtw89_mac_vif_deinit(rtwdev, rtwvif_link); +- rtw89_release_mac_id(rtwdev, rtwvif_link->mac_id); +- +- return ret; ++ return rtw89_mac_vif_deinit(rtwdev, rtwvif_link); + } + + static void +diff --git a/drivers/net/wireless/realtek/rtw89/mac.h b/drivers/net/wireless/realtek/rtw89/mac.h +index 3ea2dcbfa5b8c..f2a31cba226e9 100644 +--- a/drivers/net/wireless/realtek/rtw89/mac.h ++++ b/drivers/net/wireless/realtek/rtw89/mac.h +@@ -1158,7 +1158,7 @@ int rtw89_mac_port_get_tsf(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwv + void rtw89_mac_port_cfg_rx_sync(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, bool en); + void rtw89_mac_set_he_obss_narrow_bw_ru(struct rtw89_dev *rtwdev, +- struct ieee80211_vif *vif); ++ struct rtw89_vif_link *rtwvif_link); + void rtw89_mac_stop_ap(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link); + void rtw89_mac_enable_beacon_for_ap_vifs(struct rtw89_dev *rtwdev, bool en); + int rtw89_mac_remove_vif(struct rtw89_dev *rtwdev, struct rtw89_vif_link *vif); +diff --git a/drivers/net/wireless/realtek/rtw89/mac80211.c b/drivers/net/wireless/realtek/rtw89/mac80211.c +index f04032a8a8ec4..d3fad66e56cd8 100644 +--- a/drivers/net/wireless/realtek/rtw89/mac80211.c ++++ b/drivers/net/wireless/realtek/rtw89/mac80211.c +@@ -106,12 +106,60 @@ static int rtw89_ops_config(struct ieee80211_hw *hw, u32 changed) + return 0; + } + ++static int __rtw89_ops_add_iface_link(struct rtw89_dev *rtwdev, ++ struct rtw89_vif_link *rtwvif_link) ++{ ++ struct ieee80211_bss_conf *bss_conf; ++ int ret; ++ ++ rtw89_leave_ps_mode(rtwdev); ++ ++ rtw89_vif_type_mapping(rtwvif_link, false); ++ ++ INIT_WORK(&rtwvif_link->update_beacon_work, rtw89_core_update_beacon_work); ++ INIT_LIST_HEAD(&rtwvif_link->general_pkt_list); ++ ++ rtwvif_link->hit_rule = 0; ++ rtwvif_link->bcn_hit_cond = 0; ++ rtwvif_link->chanctx_assigned = false; ++ rtwvif_link->chanctx_idx = RTW89_CHANCTX_0; ++ rtwvif_link->reg_6ghz_power = RTW89_REG_6GHZ_POWER_DFLT; ++ ++ rcu_read_lock(); ++ ++ bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, true); ++ ether_addr_copy(rtwvif_link->mac_addr, bss_conf->addr); ++ ++ rcu_read_unlock(); ++ ++ ret = rtw89_mac_add_vif(rtwdev, rtwvif_link); ++ if (ret) ++ return ret; ++ ++ rtw89_btc_ntfy_role_info(rtwdev, rtwvif_link, NULL, BTC_ROLE_START); ++ return 0; ++} ++ ++static void __rtw89_ops_remove_iface_link(struct rtw89_dev *rtwdev, ++ struct rtw89_vif_link *rtwvif_link) ++{ ++ mutex_unlock(&rtwdev->mutex); ++ cancel_work_sync(&rtwvif_link->update_beacon_work); ++ mutex_lock(&rtwdev->mutex); ++ ++ rtw89_leave_ps_mode(rtwdev); ++ ++ rtw89_btc_ntfy_role_info(rtwdev, rtwvif_link, NULL, BTC_ROLE_STOP); ++ ++ rtw89_mac_remove_vif(rtwdev, rtwvif_link); ++} ++ + static int rtw89_ops_add_interface(struct ieee80211_hw *hw, + struct ieee80211_vif *vif) + { + struct rtw89_dev *rtwdev = hw->priv; + struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv; +- struct ieee80211_bss_conf *bss_conf; ++ u8 mac_id, port; + int ret = 0; + + rtw89_debug(rtwdev, RTW89_DBG_STATE, "add vif %pM type %d, p2p %d\n", +@@ -128,53 +176,47 @@ static int rtw89_ops_add_interface(struct ieee80211_hw *hw, + rtwvif_link->rtwdev = rtwdev; + rtwvif_link->roc.state = RTW89_ROC_IDLE; + rtwvif_link->offchan = false; +- if (!rtw89_rtwvif_in_list(rtwdev, rtwvif_link)) +- list_add_tail(&rtwvif_link->list, &rtwdev->rtwvifs_list); +- +- INIT_WORK(&rtwvif_link->update_beacon_work, rtw89_core_update_beacon_work); + INIT_DELAYED_WORK(&rtwvif_link->roc.roc_work, rtw89_roc_work); +- rtw89_leave_ps_mode(rtwdev); + + rtw89_traffic_stats_init(rtwdev, &rtwvif_link->stats); +- rtw89_vif_type_mapping(vif, false); +- rtwvif_link->port = rtw89_core_acquire_bit_map(rtwdev->hw_port, +- RTW89_PORT_NUM); +- if (rtwvif_link->port == RTW89_PORT_NUM) { ++ ++ mac_id = rtw89_acquire_mac_id(rtwdev); ++ if (mac_id == RTW89_MAX_MAC_ID_NUM) { + ret = -ENOSPC; +- list_del_init(&rtwvif_link->list); +- goto out; ++ goto err; ++ } ++ ++ port = rtw89_core_acquire_bit_map(rtwdev->hw_port, RTW89_PORT_NUM); ++ if (port == RTW89_PORT_NUM) { ++ ret = -ENOSPC; ++ goto release_macid; + } + +- rtwvif_link->bcn_hit_cond = 0; + rtwvif_link->mac_idx = RTW89_MAC_0; + rtwvif_link->phy_idx = RTW89_PHY_0; +- rtwvif_link->chanctx_idx = RTW89_CHANCTX_0; +- rtwvif_link->chanctx_assigned = false; +- rtwvif_link->hit_rule = 0; +- rtwvif_link->reg_6ghz_power = RTW89_REG_6GHZ_POWER_DFLT; ++ rtwvif_link->mac_id = mac_id; ++ rtwvif_link->port = port; + +- rcu_read_lock(); +- +- bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, true); +- ether_addr_copy(rtwvif_link->mac_addr, bss_conf->addr); +- +- rcu_read_unlock(); ++ rtw89_core_txq_init(rtwdev, vif->txq); + +- INIT_LIST_HEAD(&rtwvif_link->general_pkt_list); ++ if (!rtw89_rtwvif_in_list(rtwdev, rtwvif_link)) ++ list_add_tail(&rtwvif_link->list, &rtwdev->rtwvifs_list); + +- ret = rtw89_mac_add_vif(rtwdev, rtwvif_link); +- if (ret) { +- rtw89_core_release_bit_map(rtwdev->hw_port, rtwvif_link->port); +- list_del_init(&rtwvif_link->list); +- goto out; +- } ++ ret = __rtw89_ops_add_iface_link(rtwdev, rtwvif_link); ++ if (ret) ++ goto release_port; + +- rtw89_core_txq_init(rtwdev, vif->txq); ++ rtw89_recalc_lps(rtwdev); + +- rtw89_btc_ntfy_role_info(rtwdev, rtwvif_link, NULL, BTC_ROLE_START); ++ mutex_unlock(&rtwdev->mutex); ++ return 0; + +- rtw89_recalc_lps(rtwdev); +-out: ++release_port: ++ list_del_init(&rtwvif_link->list); ++ rtw89_core_release_bit_map(rtwdev->hw_port, port); ++release_macid: ++ rtw89_release_mac_id(rtwdev, mac_id); ++err: + mutex_unlock(&rtwdev->mutex); + + return ret; +@@ -189,14 +231,14 @@ static void rtw89_ops_remove_interface(struct ieee80211_hw *hw, + rtw89_debug(rtwdev, RTW89_DBG_STATE, "remove vif %pM type %d p2p %d\n", + vif->addr, vif->type, vif->p2p); + +- cancel_work_sync(&rtwvif_link->update_beacon_work); + cancel_delayed_work_sync(&rtwvif_link->roc.roc_work); + + mutex_lock(&rtwdev->mutex); +- rtw89_leave_ps_mode(rtwdev); +- rtw89_btc_ntfy_role_info(rtwdev, rtwvif_link, NULL, BTC_ROLE_STOP); +- rtw89_mac_remove_vif(rtwdev, rtwvif_link); ++ ++ __rtw89_ops_remove_iface_link(rtwdev, rtwvif_link); ++ + rtw89_core_release_bit_map(rtwdev->hw_port, rtwvif_link->port); ++ rtw89_release_mac_id(rtwdev, rtwvif_link->mac_id); + list_del_init(&rtwvif_link->list); + rtw89_recalc_lps(rtwdev); + rtw89_enter_ips_by_hwflags(rtwdev); +@@ -417,6 +459,7 @@ static void rtw89_conf_tx(struct rtw89_dev *rtwdev, + static void rtw89_station_mode_sta_assoc(struct rtw89_dev *rtwdev, + struct ieee80211_vif *vif) + { ++ struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv; + struct ieee80211_sta *sta; + + if (vif->type != NL80211_IFTYPE_STATION) +@@ -428,11 +471,20 @@ static void rtw89_station_mode_sta_assoc(struct rtw89_dev *rtwdev, + return; + } + +- rtw89_vif_type_mapping(vif, true); ++ rtw89_vif_type_mapping(rtwvif_link, true); + + rtw89_core_sta_assoc(rtwdev, vif, sta); + } + ++static void __rtw89_ops_bss_link_assoc(struct rtw89_dev *rtwdev, ++ struct rtw89_vif_link *rtwvif_link) ++{ ++ rtw89_phy_set_bss_color(rtwdev, rtwvif_link); ++ rtw89_chip_cfg_txpwr_ul_tb_offset(rtwdev, rtwvif_link); ++ rtw89_mac_port_update(rtwdev, rtwvif_link); ++ rtw89_mac_set_he_obss_narrow_bw_ru(rtwdev, rtwvif_link); ++} ++ + static void rtw89_ops_vif_cfg_changed(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, u64 changed) + { +@@ -445,10 +497,7 @@ static void rtw89_ops_vif_cfg_changed(struct ieee80211_hw *hw, + if (changed & BSS_CHANGED_ASSOC) { + if (vif->cfg.assoc) { + rtw89_station_mode_sta_assoc(rtwdev, vif); +- rtw89_phy_set_bss_color(rtwdev, vif); +- rtw89_chip_cfg_txpwr_ul_tb_offset(rtwdev, vif); +- rtw89_mac_port_update(rtwdev, rtwvif_link); +- rtw89_mac_set_he_obss_narrow_bw_ru(rtwdev, vif); ++ __rtw89_ops_bss_link_assoc(rtwdev, rtwvif_link); + + rtw89_queue_chanctx_work(rtwdev); + } else { +@@ -494,7 +543,7 @@ static void rtw89_ops_link_info_changed(struct ieee80211_hw *hw, + rtw89_conf_tx(rtwdev, rtwvif_link); + + if (changed & BSS_CHANGED_HE_BSS_COLOR) +- rtw89_phy_set_bss_color(rtwdev, vif); ++ rtw89_phy_set_bss_color(rtwdev, rtwvif_link); + + if (changed & BSS_CHANGED_MU_GROUPS) + rtw89_mac_bf_set_gid_table(rtwdev, vif, conf); +diff --git a/drivers/net/wireless/realtek/rtw89/phy.c b/drivers/net/wireless/realtek/rtw89/phy.c +index a46f182633e92..f6f2b003c412f 100644 +--- a/drivers/net/wireless/realtek/rtw89/phy.c ++++ b/drivers/net/wireless/realtek/rtw89/phy.c +@@ -6038,9 +6038,10 @@ void rtw89_phy_dm_init(struct rtw89_dev *rtwdev) + rtw89_chip_cfg_txrx_path(rtwdev); + } + +-void rtw89_phy_set_bss_color(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif) ++void rtw89_phy_set_bss_color(struct rtw89_dev *rtwdev, ++ struct rtw89_vif_link *rtwvif_link) + { +- struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv; ++ struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif_link); + const struct rtw89_chip_info *chip = rtwdev->chip; + const struct rtw89_reg_def *bss_clr_vld = &chip->bss_clr_vld; + enum rtw89_phy_idx phy_idx = RTW89_PHY_0; +diff --git a/drivers/net/wireless/realtek/rtw89/phy.h b/drivers/net/wireless/realtek/rtw89/phy.h +index dc85840312da7..882a473ecf7bc 100644 +--- a/drivers/net/wireless/realtek/rtw89/phy.h ++++ b/drivers/net/wireless/realtek/rtw89/phy.h +@@ -953,7 +953,8 @@ void rtw89_phy_antdiv_parse(struct rtw89_dev *rtwdev, + struct rtw89_rx_phy_ppdu *phy_ppdu); + void rtw89_phy_antdiv_track(struct rtw89_dev *rtwdev); + void rtw89_phy_antdiv_work(struct work_struct *work); +-void rtw89_phy_set_bss_color(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif); ++void rtw89_phy_set_bss_color(struct rtw89_dev *rtwdev, ++ struct rtw89_vif_link *rtwvif_link); + void rtw89_phy_tssi_ctrl_set_bandedge_cfg(struct rtw89_dev *rtwdev, + enum rtw89_mac_idx mac_idx, + enum rtw89_tssi_bandedge_cfg bandedge_cfg); +diff --git a/drivers/net/wireless/realtek/rtw89/wow.c b/drivers/net/wireless/realtek/rtw89/wow.c +index 17e2d5cbb1e6a..20b776ae634ea 100644 +--- a/drivers/net/wireless/realtek/rtw89/wow.c ++++ b/drivers/net/wireless/realtek/rtw89/wow.c +@@ -1268,8 +1268,8 @@ static int rtw89_wow_swap_fw(struct rtw89_dev *rtwdev, bool wow) + return ret; + } + rtw89_phy_ra_assoc(rtwdev, wow_sta); +- rtw89_phy_set_bss_color(rtwdev, wow_vif); +- rtw89_chip_cfg_txpwr_ul_tb_offset(rtwdev, wow_vif); ++ rtw89_phy_set_bss_color(rtwdev, rtwvif_link); ++ rtw89_chip_cfg_txpwr_ul_tb_offset(rtwdev, rtwvif_link); + } + + if (chip_gen == RTW89_CHIP_BE) +-- +2.43.0 + diff --git a/queue-6.12/wifi-rtw89-rename-rtw89_sta-to-rtw89_sta_link-ahead-.patch b/queue-6.12/wifi-rtw89-rename-rtw89_sta-to-rtw89_sta_link-ahead-.patch new file mode 100644 index 00000000000..8e6ceaca8ff --- /dev/null +++ b/queue-6.12/wifi-rtw89-rename-rtw89_sta-to-rtw89_sta_link-ahead-.patch @@ -0,0 +1,2315 @@ +From fda3655c8b1dc918776cfb748c09b2fc822cf20a Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Mon, 16 Sep 2024 13:31:53 +0800 +Subject: wifi: rtw89: rename rtw89_sta to rtw89_sta_link ahead for MLO + +From: Zong-Zhe Yang <kevin_yang@realtek.com> + +[ Upstream commit 9ee282193440527a20c9b40d47db8abaa73ecd49 ] + +This is an intermediate version that is separated from subsequent major +MLO changes, so some functions' namings are not really determined here. +e.g. struct rtw89_sta_link *sta_to_rtwsta_safe(struct ieee80211_sta *sta) + +No logic is changed. + +Signed-off-by: Zong-Zhe Yang <kevin_yang@realtek.com> +Signed-off-by: Ping-Ke Shih <pkshih@realtek.com> +Link: https://patch.msgid.link/20240916053158.47350-3-pkshih@realtek.com +Stable-dep-of: f16c40acd319 ("wifi: rtw89: Fix TX fail with A2DP after scanning") +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/net/wireless/realtek/rtw89/cam.c | 43 ++-- + drivers/net/wireless/realtek/rtw89/cam.h | 8 +- + drivers/net/wireless/realtek/rtw89/chan.c | 6 +- + drivers/net/wireless/realtek/rtw89/coex.c | 57 +++--- + drivers/net/wireless/realtek/rtw89/coex.h | 3 +- + drivers/net/wireless/realtek/rtw89/core.c | 193 +++++++++--------- + drivers/net/wireless/realtek/rtw89/core.h | 48 ++--- + drivers/net/wireless/realtek/rtw89/debug.c | 50 ++--- + drivers/net/wireless/realtek/rtw89/fw.c | 102 ++++----- + drivers/net/wireless/realtek/rtw89/fw.h | 36 ++-- + drivers/net/wireless/realtek/rtw89/mac.c | 60 +++--- + drivers/net/wireless/realtek/rtw89/mac.h | 8 +- + drivers/net/wireless/realtek/rtw89/mac80211.c | 39 ++-- + drivers/net/wireless/realtek/rtw89/phy.c | 80 ++++---- + drivers/net/wireless/realtek/rtw89/ser.c | 10 +- + drivers/net/wireless/realtek/rtw89/wow.c | 20 +- + 16 files changed, 392 insertions(+), 371 deletions(-) + +diff --git a/drivers/net/wireless/realtek/rtw89/cam.c b/drivers/net/wireless/realtek/rtw89/cam.c +index a3e6d40b30788..80deb0712b834 100644 +--- a/drivers/net/wireless/realtek/rtw89/cam.c ++++ b/drivers/net/wireless/realtek/rtw89/cam.c +@@ -217,7 +217,7 @@ static int rtw89_cam_detach_sec_cam(struct rtw89_dev *rtwdev, + const struct rtw89_sec_cam_entry *sec_cam, + bool inform_fw) + { +- struct rtw89_sta *rtwsta = sta_to_rtwsta_safe(sta); ++ struct rtw89_sta_link *rtwsta_link = sta_to_rtwsta_safe(sta); + struct rtw89_vif_link *rtwvif_link; + struct rtw89_addr_cam_entry *addr_cam; + unsigned int i; +@@ -229,7 +229,7 @@ static int rtw89_cam_detach_sec_cam(struct rtw89_dev *rtwdev, + } + + rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv; +- addr_cam = rtw89_get_addr_cam_of(rtwvif_link, rtwsta); ++ addr_cam = rtw89_get_addr_cam_of(rtwvif_link, rtwsta_link); + + for_each_set_bit(i, addr_cam->sec_cam_map, RTW89_SEC_CAM_IN_ADDR_CAM) { + if (addr_cam->sec_ent[i] != sec_cam->sec_cam_idx) +@@ -239,11 +239,11 @@ static int rtw89_cam_detach_sec_cam(struct rtw89_dev *rtwdev, + } + + if (inform_fw) { +- ret = rtw89_chip_h2c_dctl_sec_cam(rtwdev, rtwvif_link, rtwsta); ++ ret = rtw89_chip_h2c_dctl_sec_cam(rtwdev, rtwvif_link, rtwsta_link); + if (ret) + rtw89_err(rtwdev, + "failed to update dctl cam del key: %d\n", ret); +- ret = rtw89_fw_h2c_cam(rtwdev, rtwvif_link, rtwsta, NULL); ++ ret = rtw89_fw_h2c_cam(rtwdev, rtwvif_link, rtwsta_link, NULL); + if (ret) + rtw89_err(rtwdev, "failed to update cam del key: %d\n", ret); + } +@@ -257,7 +257,7 @@ static int rtw89_cam_attach_sec_cam(struct rtw89_dev *rtwdev, + struct ieee80211_key_conf *key, + struct rtw89_sec_cam_entry *sec_cam) + { +- struct rtw89_sta *rtwsta = sta_to_rtwsta_safe(sta); ++ struct rtw89_sta_link *rtwsta_link = sta_to_rtwsta_safe(sta); + struct rtw89_vif_link *rtwvif_link; + struct rtw89_addr_cam_entry *addr_cam; + u8 key_idx = 0; +@@ -269,7 +269,7 @@ static int rtw89_cam_attach_sec_cam(struct rtw89_dev *rtwdev, + } + + rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv; +- addr_cam = rtw89_get_addr_cam_of(rtwvif_link, rtwsta); ++ addr_cam = rtw89_get_addr_cam_of(rtwvif_link, rtwsta_link); + + if (key->cipher == WLAN_CIPHER_SUITE_WEP40 || + key->cipher == WLAN_CIPHER_SUITE_WEP104) +@@ -285,13 +285,13 @@ static int rtw89_cam_attach_sec_cam(struct rtw89_dev *rtwdev, + addr_cam->sec_ent_keyid[key_idx] = key->keyidx; + addr_cam->sec_ent[key_idx] = sec_cam->sec_cam_idx; + set_bit(key_idx, addr_cam->sec_cam_map); +- ret = rtw89_chip_h2c_dctl_sec_cam(rtwdev, rtwvif_link, rtwsta); ++ ret = rtw89_chip_h2c_dctl_sec_cam(rtwdev, rtwvif_link, rtwsta_link); + if (ret) { + rtw89_err(rtwdev, "failed to update dctl cam sec entry: %d\n", + ret); + return ret; + } +- ret = rtw89_fw_h2c_cam(rtwdev, rtwvif_link, rtwsta, NULL); ++ ret = rtw89_fw_h2c_cam(rtwdev, rtwvif_link, rtwsta_link, NULL); + if (ret) { + rtw89_err(rtwdev, "failed to update addr cam sec entry: %d\n", + ret); +@@ -653,11 +653,11 @@ int rtw89_cam_init(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link) + + int rtw89_cam_fill_bssid_cam_info(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, +- struct rtw89_sta *rtwsta, u8 *cmd) ++ struct rtw89_sta_link *rtwsta_link, u8 *cmd) + { + struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif_link); + struct rtw89_bssid_cam_entry *bssid_cam = rtw89_get_bssid_cam_of(rtwvif_link, +- rtwsta); ++ rtwsta_link); + u8 bss_color = vif->bss_conf.he_bss_color.color; + u8 bss_mask; + +@@ -697,14 +697,14 @@ static u8 rtw89_cam_addr_hash(u8 start, const u8 *addr) + + void rtw89_cam_fill_addr_cam_info(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, +- struct rtw89_sta *rtwsta, ++ struct rtw89_sta_link *rtwsta_link, + const u8 *scan_mac_addr, + u8 *cmd) + { + struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif_link); + struct rtw89_addr_cam_entry *addr_cam = +- rtw89_get_addr_cam_of(rtwvif_link, rtwsta); +- struct ieee80211_sta *sta = rtwsta_to_sta_safe(rtwsta); ++ rtw89_get_addr_cam_of(rtwvif_link, rtwsta_link); ++ struct ieee80211_sta *sta = rtwsta_to_sta_safe(rtwsta_link); + const u8 *sma = scan_mac_addr ? scan_mac_addr : rtwvif_link->mac_addr; + u8 sma_hash, tma_hash, addr_msk_start; + u8 sma_start = 0; +@@ -757,7 +757,8 @@ void rtw89_cam_fill_addr_cam_info(struct rtw89_dev *rtwdev, + FWCMD_SET_ADDR_LSIG_TXOP(cmd, rtwvif_link->lsig_txop); + FWCMD_SET_ADDR_TGT_IND(cmd, rtwvif_link->tgt_ind); + FWCMD_SET_ADDR_FRM_TGT_IND(cmd, rtwvif_link->frm_tgt_ind); +- FWCMD_SET_ADDR_MACID(cmd, rtwsta ? rtwsta->mac_id : rtwvif_link->mac_id); ++ FWCMD_SET_ADDR_MACID(cmd, rtwsta_link ? rtwsta_link->mac_id : ++ rtwvif_link->mac_id); + if (rtwvif_link->net_type == RTW89_NET_TYPE_INFRA) + FWCMD_SET_ADDR_AID12(cmd, vif->cfg.aid & 0xfff); + else if (rtwvif_link->net_type == RTW89_NET_TYPE_AP_MODE) +@@ -787,15 +788,16 @@ void rtw89_cam_fill_addr_cam_info(struct rtw89_dev *rtwdev, + + void rtw89_cam_fill_dctl_sec_cam_info_v1(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, +- struct rtw89_sta *rtwsta, ++ struct rtw89_sta_link *rtwsta_link, + struct rtw89_h2c_dctlinfo_ud_v1 *h2c) + { + struct rtw89_addr_cam_entry *addr_cam = +- rtw89_get_addr_cam_of(rtwvif_link, rtwsta); ++ rtw89_get_addr_cam_of(rtwvif_link, rtwsta_link); + struct rtw89_wow_param *rtw_wow = &rtwdev->wow; + u8 *ptk_tx_iv = rtw_wow->key_info.ptk_tx_iv; + +- h2c->c0 = le32_encode_bits(rtwsta ? rtwsta->mac_id : rtwvif_link->mac_id, ++ h2c->c0 = le32_encode_bits(rtwsta_link ? rtwsta_link->mac_id : ++ rtwvif_link->mac_id, + DCTLINFO_V1_C0_MACID) | + le32_encode_bits(1, DCTLINFO_V1_C0_OP); + +@@ -867,15 +869,16 @@ void rtw89_cam_fill_dctl_sec_cam_info_v1(struct rtw89_dev *rtwdev, + + void rtw89_cam_fill_dctl_sec_cam_info_v2(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, +- struct rtw89_sta *rtwsta, ++ struct rtw89_sta_link *rtwsta_link, + struct rtw89_h2c_dctlinfo_ud_v2 *h2c) + { + struct rtw89_addr_cam_entry *addr_cam = +- rtw89_get_addr_cam_of(rtwvif_link, rtwsta); ++ rtw89_get_addr_cam_of(rtwvif_link, rtwsta_link); + struct rtw89_wow_param *rtw_wow = &rtwdev->wow; + u8 *ptk_tx_iv = rtw_wow->key_info.ptk_tx_iv; + +- h2c->c0 = le32_encode_bits(rtwsta ? rtwsta->mac_id : rtwvif_link->mac_id, ++ h2c->c0 = le32_encode_bits(rtwsta_link ? rtwsta_link->mac_id : ++ rtwvif_link->mac_id, + DCTLINFO_V2_C0_MACID) | + le32_encode_bits(1, DCTLINFO_V2_C0_OP); + +diff --git a/drivers/net/wireless/realtek/rtw89/cam.h b/drivers/net/wireless/realtek/rtw89/cam.h +index 18ede69144b67..a6f72edd30fe3 100644 +--- a/drivers/net/wireless/realtek/rtw89/cam.h ++++ b/drivers/net/wireless/realtek/rtw89/cam.h +@@ -541,19 +541,19 @@ void rtw89_cam_deinit_bssid_cam(struct rtw89_dev *rtwdev, + struct rtw89_bssid_cam_entry *bssid_cam); + void rtw89_cam_fill_addr_cam_info(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *vif, +- struct rtw89_sta *rtwsta, ++ struct rtw89_sta_link *rtwsta_link, + const u8 *scan_mac_addr, u8 *cmd); + void rtw89_cam_fill_dctl_sec_cam_info_v1(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, +- struct rtw89_sta *rtwsta, ++ struct rtw89_sta_link *rtwsta_link, + struct rtw89_h2c_dctlinfo_ud_v1 *h2c); + void rtw89_cam_fill_dctl_sec_cam_info_v2(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, +- struct rtw89_sta *rtwsta, ++ struct rtw89_sta_link *rtwsta_link, + struct rtw89_h2c_dctlinfo_ud_v2 *h2c); + int rtw89_cam_fill_bssid_cam_info(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, +- struct rtw89_sta *rtwsta, u8 *cmd); ++ struct rtw89_sta_link *rtwsta_link, u8 *cmd); + int rtw89_cam_sec_key_add(struct rtw89_dev *rtwdev, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta, +diff --git a/drivers/net/wireless/realtek/rtw89/chan.c b/drivers/net/wireless/realtek/rtw89/chan.c +index f20431c3e2017..2f14ac6687163 100644 +--- a/drivers/net/wireless/realtek/rtw89/chan.c ++++ b/drivers/net/wireless/realtek/rtw89/chan.c +@@ -522,15 +522,15 @@ u32 rtw89_mcc_role_fw_macid_bitmap_to_u32(struct rtw89_mcc_role *mcc_role) + + static void rtw89_mcc_role_macid_sta_iter(void *data, struct ieee80211_sta *sta) + { +- struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv; +- struct rtw89_vif_link *rtwvif_link = rtwsta->rtwvif_link; ++ struct rtw89_sta_link *rtwsta_link = (struct rtw89_sta_link *)sta->drv_priv; ++ struct rtw89_vif_link *rtwvif_link = rtwsta_link->rtwvif_link; + struct rtw89_mcc_role *mcc_role = data; + struct rtw89_vif_link *target = mcc_role->rtwvif_link; + + if (rtwvif_link != target) + return; + +- rtw89_mcc_role_fw_macid_bitmap_set_bit(mcc_role, rtwsta->mac_id); ++ rtw89_mcc_role_fw_macid_bitmap_set_bit(mcc_role, rtwsta_link->mac_id); + } + + static void rtw89_mcc_fill_role_macid_bitmap(struct rtw89_dev *rtwdev, +diff --git a/drivers/net/wireless/realtek/rtw89/coex.c b/drivers/net/wireless/realtek/rtw89/coex.c +index f56257d1e33e3..afd1ff32afc56 100644 +--- a/drivers/net/wireless/realtek/rtw89/coex.c ++++ b/drivers/net/wireless/realtek/rtw89/coex.c +@@ -4991,11 +4991,11 @@ struct rtw89_txtime_data { + + static void rtw89_tx_time_iter(void *data, struct ieee80211_sta *sta) + { +- struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv; ++ struct rtw89_sta_link *rtwsta_link = (struct rtw89_sta_link *)sta->drv_priv; + struct rtw89_txtime_data *iter_data = + (struct rtw89_txtime_data *)data; + struct rtw89_dev *rtwdev = iter_data->rtwdev; +- struct rtw89_vif_link *rtwvif_link = rtwsta->rtwvif_link; ++ struct rtw89_vif_link *rtwvif_link = rtwsta_link->rtwvif_link; + struct rtw89_btc *btc = &rtwdev->btc; + struct rtw89_btc_cx *cx = &btc->cx; + struct rtw89_btc_wl_info *wl = &cx->wl; +@@ -5023,8 +5023,8 @@ static void rtw89_tx_time_iter(void *data, struct ieee80211_sta *sta) + + /* backup the original tx time before tx-limit on */ + if (reenable) { +- rtw89_mac_get_tx_time(rtwdev, rtwsta, &plink->tx_time); +- rtw89_mac_get_tx_retry_limit(rtwdev, rtwsta, &plink->tx_retry); ++ rtw89_mac_get_tx_time(rtwdev, rtwsta_link, &plink->tx_time); ++ rtw89_mac_get_tx_retry_limit(rtwdev, rtwsta_link, &plink->tx_retry); + rtw89_debug(rtwdev, RTW89_DBG_BTC, + "[BTC], %s(): reenable, tx_time=%d tx_retry= %d\n", + __func__, plink->tx_time, plink->tx_retry); +@@ -5032,16 +5032,16 @@ static void rtw89_tx_time_iter(void *data, struct ieee80211_sta *sta) + + /* restore the original tx time if no tx-limit */ + if (!enable) { +- rtw89_mac_set_tx_time(rtwdev, rtwsta, true, plink->tx_time); +- rtw89_mac_set_tx_retry_limit(rtwdev, rtwsta, true, ++ rtw89_mac_set_tx_time(rtwdev, rtwsta_link, true, plink->tx_time); ++ rtw89_mac_set_tx_retry_limit(rtwdev, rtwsta_link, true, + plink->tx_retry); + rtw89_debug(rtwdev, RTW89_DBG_BTC, + "[BTC], %s(): restore, tx_time=%d tx_retry= %d\n", + __func__, plink->tx_time, plink->tx_retry); + + } else { +- rtw89_mac_set_tx_time(rtwdev, rtwsta, false, tx_time); +- rtw89_mac_set_tx_retry_limit(rtwdev, rtwsta, false, tx_retry); ++ rtw89_mac_set_tx_time(rtwdev, rtwsta_link, false, tx_time); ++ rtw89_mac_set_tx_retry_limit(rtwdev, rtwsta_link, false, tx_retry); + rtw89_debug(rtwdev, RTW89_DBG_BTC, + "[BTC], %s(): set, tx_time=%d tx_retry= %d\n", + __func__, tx_time, tx_retry); +@@ -7483,12 +7483,13 @@ static void _update_bt_info(struct rtw89_dev *rtwdev, u8 *buf, u32 len) + + void rtw89_btc_ntfy_role_info(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, +- struct rtw89_sta *rtwsta, enum btc_role_state state) ++ struct rtw89_sta_link *rtwsta_link, ++ enum btc_role_state state) + { + const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, + rtwvif_link->chanctx_idx); + struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif_link); +- struct ieee80211_sta *sta = rtwsta_to_sta(rtwsta); ++ struct ieee80211_sta *sta = rtwsta_to_sta(rtwsta_link); + struct rtw89_btc *btc = &rtwdev->btc; + const struct rtw89_btc_ver *ver = btc->ver; + struct rtw89_btc_wl_info *wl = &btc->cx.wl; +@@ -7509,9 +7510,9 @@ void rtw89_btc_ntfy_role_info(struct rtw89_dev *rtwdev, + "[BTC], bcn_period=%d dtim_period=%d\n", + vif->bss_conf.beacon_int, vif->bss_conf.dtim_period); + +- if (rtwsta) { ++ if (rtwsta_link) { + rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], STA mac_id=%d\n", +- rtwsta->mac_id); ++ rtwsta_link->mac_id); + + rtw89_debug(rtwdev, RTW89_DBG_BTC, + "[BTC], STA support HE=%d VHT=%d HT=%d\n", +@@ -7550,8 +7551,8 @@ void rtw89_btc_ntfy_role_info(struct rtw89_dev *rtwdev, + r.chdef.chan = chan->primary_channel; + ether_addr_copy(r.mac_addr, rtwvif_link->mac_addr); + +- if (rtwsta && vif->type == NL80211_IFTYPE_STATION) +- r.mac_id = rtwsta->mac_id; ++ if (rtwsta_link && vif->type == NL80211_IFTYPE_STATION) ++ r.mac_id = rtwsta_link->mac_id; + + btc->dm.cnt_notify[BTC_NCNT_ROLE_INFO]++; + +@@ -7792,9 +7793,9 @@ static void rtw89_btc_ntfy_wl_sta_iter(void *data, struct ieee80211_sta *sta) + const struct rtw89_btc_ver *ver = btc->ver; + struct rtw89_btc_wl_info *wl = &btc->cx.wl; + struct rtw89_btc_wl_link_info *link_info = NULL; +- struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv; ++ struct rtw89_sta_link *rtwsta_link = (struct rtw89_sta_link *)sta->drv_priv; + struct rtw89_traffic_stats *link_info_t = NULL; +- struct rtw89_vif_link *rtwvif_link = rtwsta->rtwvif_link; ++ struct rtw89_vif_link *rtwvif_link = rtwsta_link->rtwvif_link; + struct rtw89_traffic_stats *stats = &rtwvif_link->stats; + const struct rtw89_chip_info *chip = rtwdev->chip; + struct rtw89_btc_wl_role_info *r; +@@ -7809,7 +7810,7 @@ static void rtw89_btc_ntfy_wl_sta_iter(void *data, struct ieee80211_sta *sta) + u8 i = 0; + bool is_sta_change = false, is_traffic_change = false; + +- rssi = ewma_rssi_read(&rtwsta->avg_rssi) >> RSSI_FACTOR; ++ rssi = ewma_rssi_read(&rtwsta_link->avg_rssi) >> RSSI_FACTOR; + rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], rssi=%d\n", rssi); + + link_info = &wl->link_info[port]; +@@ -7861,19 +7862,19 @@ static void rtw89_btc_ntfy_wl_sta_iter(void *data, struct ieee80211_sta *sta) + iter_data->busy_all |= busy; + iter_data->dir_all |= BIT(dir); + +- if (rtwsta->rx_hw_rate <= RTW89_HW_RATE_CCK2 && ++ if (rtwsta_link->rx_hw_rate <= RTW89_HW_RATE_CCK2 && + last_rx_rate > RTW89_HW_RATE_CCK2 && + link_info_t->rx_tfc_lv > RTW89_TFC_IDLE) + link_info->rx_rate_drop_cnt++; + +- if (last_tx_rate != rtwsta->ra_report.hw_rate || +- last_rx_rate != rtwsta->rx_hw_rate || ++ if (last_tx_rate != rtwsta_link->ra_report.hw_rate || ++ last_rx_rate != rtwsta_link->rx_hw_rate || + last_tx_lvl != link_info_t->tx_tfc_lv || + last_rx_lvl != link_info_t->rx_tfc_lv) + is_traffic_change = true; + +- link_info_t->tx_rate = rtwsta->ra_report.hw_rate; +- link_info_t->rx_rate = rtwsta->rx_hw_rate; ++ link_info_t->tx_rate = rtwsta_link->ra_report.hw_rate; ++ link_info_t->rx_rate = rtwsta_link->rx_hw_rate; + + if (link_info->role == RTW89_WIFI_ROLE_STATION || + link_info->role == RTW89_WIFI_ROLE_P2P_CLIENT) { +@@ -7885,19 +7886,19 @@ static void rtw89_btc_ntfy_wl_sta_iter(void *data, struct ieee80211_sta *sta) + r = &wl->role_info; + r->active_role[port].tx_lvl = stats->tx_tfc_lv; + r->active_role[port].rx_lvl = stats->rx_tfc_lv; +- r->active_role[port].tx_rate = rtwsta->ra_report.hw_rate; +- r->active_role[port].rx_rate = rtwsta->rx_hw_rate; ++ r->active_role[port].tx_rate = rtwsta_link->ra_report.hw_rate; ++ r->active_role[port].rx_rate = rtwsta_link->rx_hw_rate; + } else if (ver->fwlrole == 1) { + r1 = &wl->role_info_v1; + r1->active_role_v1[port].tx_lvl = stats->tx_tfc_lv; + r1->active_role_v1[port].rx_lvl = stats->rx_tfc_lv; +- r1->active_role_v1[port].tx_rate = rtwsta->ra_report.hw_rate; +- r1->active_role_v1[port].rx_rate = rtwsta->rx_hw_rate; ++ r1->active_role_v1[port].tx_rate = rtwsta_link->ra_report.hw_rate; ++ r1->active_role_v1[port].rx_rate = rtwsta_link->rx_hw_rate; + } else if (ver->fwlrole == 2) { + dm->trx_info.tx_lvl = stats->tx_tfc_lv; + dm->trx_info.rx_lvl = stats->rx_tfc_lv; +- dm->trx_info.tx_rate = rtwsta->ra_report.hw_rate; +- dm->trx_info.rx_rate = rtwsta->rx_hw_rate; ++ dm->trx_info.tx_rate = rtwsta_link->ra_report.hw_rate; ++ dm->trx_info.rx_rate = rtwsta_link->rx_hw_rate; + } + + dm->trx_info.tx_tp = link_info_t->tx_throughput; +diff --git a/drivers/net/wireless/realtek/rtw89/coex.h b/drivers/net/wireless/realtek/rtw89/coex.h +index 2a3bd1ead7c3e..dbdb56e063ef0 100644 +--- a/drivers/net/wireless/realtek/rtw89/coex.h ++++ b/drivers/net/wireless/realtek/rtw89/coex.h +@@ -273,7 +273,8 @@ void rtw89_btc_ntfy_dhcp_packet_work(struct work_struct *work); + void rtw89_btc_ntfy_icmp_packet_work(struct work_struct *work); + void rtw89_btc_ntfy_role_info(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, +- struct rtw89_sta *rtwsta, enum btc_role_state state); ++ struct rtw89_sta_link *rtwsta_link, ++ enum btc_role_state state); + void rtw89_btc_ntfy_radio_state(struct rtw89_dev *rtwdev, enum btc_rfctrl rf_state); + void rtw89_btc_ntfy_wl_rfk(struct rtw89_dev *rtwdev, u8 phy_map, + enum btc_wl_rfk_type type, +diff --git a/drivers/net/wireless/realtek/rtw89/core.c b/drivers/net/wireless/realtek/rtw89/core.c +index 314c2e2ef8e90..2b6a8fe0e53b0 100644 +--- a/drivers/net/wireless/realtek/rtw89/core.c ++++ b/drivers/net/wireless/realtek/rtw89/core.c +@@ -466,7 +466,7 @@ rtw89_core_tx_update_ampdu_info(struct rtw89_dev *rtwdev, + struct ieee80211_sta *sta = tx_req->sta; + struct rtw89_tx_desc_info *desc_info = &tx_req->desc_info; + struct sk_buff *skb = tx_req->skb; +- struct rtw89_sta *rtwsta; ++ struct rtw89_sta_link *rtwsta_link; + u8 ampdu_num; + u8 tid; + +@@ -484,10 +484,10 @@ rtw89_core_tx_update_ampdu_info(struct rtw89_dev *rtwdev, + } + + tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK; +- rtwsta = (struct rtw89_sta *)sta->drv_priv; ++ rtwsta_link = (struct rtw89_sta_link *)sta->drv_priv; + +- ampdu_num = (u8)((rtwsta->ampdu_params[tid].agg_num ? +- rtwsta->ampdu_params[tid].agg_num : ++ ampdu_num = (u8)((rtwsta_link->ampdu_params[tid].agg_num ? ++ rtwsta_link->ampdu_params[tid].agg_num : + 4 << sta->deflink.ht_cap.ampdu_factor) - 1); + + desc_info->agg_en = true; +@@ -593,13 +593,13 @@ static u8 rtw89_core_tx_get_mac_id(struct rtw89_dev *rtwdev, + struct ieee80211_vif *vif = tx_req->vif; + struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv; + struct ieee80211_sta *sta = tx_req->sta; +- struct rtw89_sta *rtwsta; ++ struct rtw89_sta_link *rtwsta_link; + + if (!sta) + return rtwvif_link->mac_id; + +- rtwsta = (struct rtw89_sta *)sta->drv_priv; +- return rtwsta->mac_id; ++ rtwsta_link = (struct rtw89_sta_link *)sta->drv_priv; ++ return rtwsta_link->mac_id; + } + + static void rtw89_core_tx_update_llc_hdr(struct rtw89_dev *rtwdev, +@@ -702,7 +702,7 @@ __rtw89_core_tx_check_he_qos_htc(struct rtw89_dev *rtwdev, + enum btc_pkt_type pkt_type) + { + struct ieee80211_sta *sta = tx_req->sta; +- struct rtw89_sta *rtwsta = sta_to_rtwsta_safe(sta); ++ struct rtw89_sta_link *rtwsta_link = sta_to_rtwsta_safe(sta); + struct sk_buff *skb = tx_req->skb; + struct ieee80211_hdr *hdr = (void *)skb->data; + __le16 fc = hdr->frame_control; +@@ -720,7 +720,7 @@ __rtw89_core_tx_check_he_qos_htc(struct rtw89_dev *rtwdev, + if (skb_headroom(skb) < IEEE80211_HT_CTL_LEN) + return false; + +- if (rtwsta && rtwsta->ra_report.might_fallback_legacy) ++ if (rtwsta_link && rtwsta_link->ra_report.might_fallback_legacy) + return false; + + return true; +@@ -731,7 +731,7 @@ __rtw89_core_tx_adjust_he_qos_htc(struct rtw89_dev *rtwdev, + struct rtw89_core_tx_request *tx_req) + { + struct ieee80211_sta *sta = tx_req->sta; +- struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv; ++ struct rtw89_sta_link *rtwsta_link = (struct rtw89_sta_link *)sta->drv_priv; + struct sk_buff *skb = tx_req->skb; + struct ieee80211_hdr *hdr = (void *)skb->data; + __le16 fc = hdr->frame_control; +@@ -747,7 +747,7 @@ __rtw89_core_tx_adjust_he_qos_htc(struct rtw89_dev *rtwdev, + hdr = data; + htc = data + hdr_len; + hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_ORDER); +- *htc = rtwsta->htc_template ? rtwsta->htc_template : ++ *htc = rtwsta_link->htc_template ? rtwsta_link->htc_template : + le32_encode_bits(RTW89_HTC_VARIANT_HE, RTW89_HTC_MASK_VARIANT) | + le32_encode_bits(RTW89_HTC_VARIANT_HE_CID_CAS, RTW89_HTC_MASK_CTL_ID); + +@@ -814,7 +814,7 @@ rtw89_core_tx_update_data_info(struct rtw89_dev *rtwdev, + struct ieee80211_vif *vif = tx_req->vif; + struct ieee80211_sta *sta = tx_req->sta; + struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv; +- struct rtw89_sta *rtwsta = sta_to_rtwsta_safe(sta); ++ struct rtw89_sta_link *rtwsta_link = sta_to_rtwsta_safe(sta); + struct rtw89_tx_desc_info *desc_info = &tx_req->desc_info; + struct sk_buff *skb = tx_req->skb; + u8 tid, tid_indicate; +@@ -830,9 +830,9 @@ rtw89_core_tx_update_data_info(struct rtw89_dev *rtwdev, + desc_info->qsel = qsel; + desc_info->mac_id = rtw89_core_tx_get_mac_id(rtwdev, tx_req); + desc_info->port = desc_info->hiq ? rtwvif_link->port : 0; +- desc_info->er_cap = rtwsta ? rtwsta->er_cap : false; +- desc_info->stbc = rtwsta ? rtwsta->ra.stbc_cap : false; +- desc_info->ldpc = rtwsta ? rtwsta->ra.ldpc_cap : false; ++ desc_info->er_cap = rtwsta_link ? rtwsta_link->er_cap : false; ++ desc_info->stbc = rtwsta_link ? rtwsta_link->ra.stbc_cap : false; ++ desc_info->ldpc = rtwsta_link ? rtwsta_link->ra.ldpc_cap : false; + + /* enable wd_info for AMPDU */ + desc_info->en_wd_info = true; +@@ -1514,16 +1514,16 @@ static u8 rtw89_get_data_rate_nss(struct rtw89_dev *rtwdev, u16 data_rate) + static void rtw89_core_rx_process_phy_ppdu_iter(void *data, + struct ieee80211_sta *sta) + { +- struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv; ++ struct rtw89_sta_link *rtwsta_link = (struct rtw89_sta_link *)sta->drv_priv; + struct rtw89_rx_phy_ppdu *phy_ppdu = (struct rtw89_rx_phy_ppdu *)data; +- struct rtw89_dev *rtwdev = rtwsta->rtwdev; ++ struct rtw89_dev *rtwdev = rtwsta_link->rtwdev; + struct rtw89_hal *hal = &rtwdev->hal; + u8 ant_num = hal->ant_diversity ? 2 : rtwdev->chip->rf_path_num; + u8 ant_pos = U8_MAX; + u8 evm_pos = 0; + int i; + +- if (rtwsta->mac_id != phy_ppdu->mac_id || !phy_ppdu->to_self) ++ if (rtwsta_link->mac_id != phy_ppdu->mac_id || !phy_ppdu->to_self) + return; + + if (hal->ant_diversity && hal->antenna_rx) { +@@ -1531,22 +1531,24 @@ static void rtw89_core_rx_process_phy_ppdu_iter(void *data, + evm_pos = ant_pos; + } + +- ewma_rssi_add(&rtwsta->avg_rssi, phy_ppdu->rssi_avg); ++ ewma_rssi_add(&rtwsta_link->avg_rssi, phy_ppdu->rssi_avg); + + if (ant_pos < ant_num) { +- ewma_rssi_add(&rtwsta->rssi[ant_pos], phy_ppdu->rssi[0]); ++ ewma_rssi_add(&rtwsta_link->rssi[ant_pos], phy_ppdu->rssi[0]); + } else { + for (i = 0; i < rtwdev->chip->rf_path_num; i++) +- ewma_rssi_add(&rtwsta->rssi[i], phy_ppdu->rssi[i]); ++ ewma_rssi_add(&rtwsta_link->rssi[i], phy_ppdu->rssi[i]); + } + + if (phy_ppdu->ofdm.has && (phy_ppdu->has_data || phy_ppdu->has_bcn)) { +- ewma_snr_add(&rtwsta->avg_snr, phy_ppdu->ofdm.avg_snr); ++ ewma_snr_add(&rtwsta_link->avg_snr, phy_ppdu->ofdm.avg_snr); + if (rtw89_get_data_rate_nss(rtwdev, phy_ppdu->rate) == 1) { +- ewma_evm_add(&rtwsta->evm_1ss, phy_ppdu->ofdm.evm_min); ++ ewma_evm_add(&rtwsta_link->evm_1ss, phy_ppdu->ofdm.evm_min); + } else { +- ewma_evm_add(&rtwsta->evm_min[evm_pos], phy_ppdu->ofdm.evm_min); +- ewma_evm_add(&rtwsta->evm_max[evm_pos], phy_ppdu->ofdm.evm_max); ++ ewma_evm_add(&rtwsta_link->evm_min[evm_pos], ++ phy_ppdu->ofdm.evm_min); ++ ewma_evm_add(&rtwsta_link->evm_max[evm_pos], ++ phy_ppdu->ofdm.evm_max); + } + } + } +@@ -2432,15 +2434,15 @@ void rtw89_core_stats_sta_rx_status_iter(void *data, struct ieee80211_sta *sta) + struct rtw89_core_iter_rx_status *iter_data = + (struct rtw89_core_iter_rx_status *)data; + struct ieee80211_rx_status *rx_status = iter_data->rx_status; +- struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv; ++ struct rtw89_sta_link *rtwsta_link = (struct rtw89_sta_link *)sta->drv_priv; + struct rtw89_rx_desc_info *desc_info = iter_data->desc_info; + u8 mac_id = iter_data->mac_id; + +- if (mac_id != rtwsta->mac_id) ++ if (mac_id != rtwsta_link->mac_id) + return; + +- rtwsta->rx_status = *rx_status; +- rtwsta->rx_hw_rate = desc_info->data_rate; ++ rtwsta_link->rx_status = *rx_status; ++ rtwsta_link->rx_hw_rate = desc_info->data_rate; + } + + static void rtw89_core_stats_sta_rx_status(struct rtw89_dev *rtwdev, +@@ -2658,7 +2660,8 @@ static void rtw89_core_ba_work(struct work_struct *work) + list_for_each_entry_safe(rtwtxq, tmp, &rtwdev->ba_list, list) { + struct ieee80211_txq *txq = rtw89_txq_to_txq(rtwtxq); + struct ieee80211_sta *sta = txq->sta; +- struct rtw89_sta *rtwsta = sta ? (struct rtw89_sta *)sta->drv_priv : NULL; ++ struct rtw89_sta_link *rtwsta_link = ++ sta ? (struct rtw89_sta_link *)sta->drv_priv : NULL; + u8 tid = txq->tid; + + if (!sta) { +@@ -2666,7 +2669,7 @@ static void rtw89_core_ba_work(struct work_struct *work) + goto skip_ba_work; + } + +- if (rtwsta->disassoc) { ++ if (rtwsta_link->disassoc) { + rtw89_debug(rtwdev, RTW89_DBG_TXRX, + "cannot start BA with disassoc sta\n"); + goto skip_ba_work; +@@ -2721,11 +2724,11 @@ static void rtw89_core_free_sta_pending_forbid_ba(struct rtw89_dev *rtwdev, + static void rtw89_core_free_sta_pending_roc_tx(struct rtw89_dev *rtwdev, + struct ieee80211_sta *sta) + { +- struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv; ++ struct rtw89_sta_link *rtwsta_link = (struct rtw89_sta_link *)sta->drv_priv; + struct sk_buff *skb, *tmp; + +- skb_queue_walk_safe(&rtwsta->roc_queue, skb, tmp) { +- skb_unlink(skb, &rtwsta->roc_queue); ++ skb_queue_walk_safe(&rtwsta_link->roc_queue, skb, tmp) { ++ skb_unlink(skb, &rtwsta_link->roc_queue); + dev_kfree_skb_any(skb); + } + } +@@ -2735,9 +2738,9 @@ static void rtw89_core_stop_tx_ba_session(struct rtw89_dev *rtwdev, + { + struct ieee80211_txq *txq = rtw89_txq_to_txq(rtwtxq); + struct ieee80211_sta *sta = txq->sta; +- struct rtw89_sta *rtwsta = sta_to_rtwsta_safe(sta); ++ struct rtw89_sta_link *rtwsta_link = sta_to_rtwsta_safe(sta); + +- if (unlikely(!rtwsta) || unlikely(rtwsta->disassoc)) ++ if (unlikely(!rtwsta_link) || unlikely(rtwsta_link->disassoc)) + return; + + if (!test_bit(RTW89_TXQ_F_AMPDU, &rtwtxq->flags) || +@@ -2762,7 +2765,8 @@ static void rtw89_core_txq_check_agg(struct rtw89_dev *rtwdev, + struct ieee80211_hw *hw = rtwdev->hw; + struct ieee80211_txq *txq = rtw89_txq_to_txq(rtwtxq); + struct ieee80211_sta *sta = txq->sta; +- struct rtw89_sta *rtwsta = sta ? (struct rtw89_sta *)sta->drv_priv : NULL; ++ struct rtw89_sta_link *rtwsta_link = ++ sta ? (struct rtw89_sta_link *)sta->drv_priv : NULL; + + if (test_bit(RTW89_TXQ_F_FORBID_BA, &rtwtxq->flags)) + return; +@@ -2784,7 +2788,7 @@ static void rtw89_core_txq_check_agg(struct rtw89_dev *rtwdev, + } + + spin_lock_bh(&rtwdev->ba_lock); +- if (!rtwsta->disassoc && list_empty(&rtwtxq->list)) { ++ if (!rtwsta_link->disassoc && list_empty(&rtwtxq->list)) { + list_add_tail(&rtwtxq->list, &rtwdev->ba_list); + ieee80211_queue_work(hw, &rtwdev->ba_work); + } +@@ -2839,9 +2843,10 @@ static bool rtw89_core_txq_agg_wait(struct rtw89_dev *rtwdev, + { + struct rtw89_txq *rtwtxq = (struct rtw89_txq *)txq->drv_priv; + struct ieee80211_sta *sta = txq->sta; +- struct rtw89_sta *rtwsta = sta ? (struct rtw89_sta *)sta->drv_priv : NULL; ++ struct rtw89_sta_link *rtwsta_link = ++ sta ? (struct rtw89_sta_link *)sta->drv_priv : NULL; + +- if (!sta || rtwsta->max_agg_wait <= 0) ++ if (!sta || rtwsta_link->max_agg_wait <= 0) + return false; + + if (rtwdev->stats.tx_tfc_lv <= RTW89_TFC_MID) +@@ -2855,7 +2860,7 @@ static bool rtw89_core_txq_agg_wait(struct rtw89_dev *rtwdev, + return false; + } + +- if (*frame_cnt == 1 && rtwtxq->wait_cnt < rtwsta->max_agg_wait) { ++ if (*frame_cnt == 1 && rtwtxq->wait_cnt < rtwsta_link->max_agg_wait) { + *reinvoke = true; + rtwtxq->wait_cnt++; + return true; +@@ -2955,9 +2960,9 @@ static void rtw89_forbid_ba_work(struct work_struct *w) + static void rtw89_core_sta_pending_tx_iter(void *data, + struct ieee80211_sta *sta) + { +- struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv; ++ struct rtw89_sta_link *rtwsta_link = (struct rtw89_sta_link *)sta->drv_priv; + struct rtw89_vif_link *rtwvif_target = data; +- struct rtw89_vif_link *rtwvif_link = rtwsta->rtwvif_link; ++ struct rtw89_vif_link *rtwvif_link = rtwsta_link->rtwvif_link; + struct rtw89_dev *rtwdev = rtwvif_link->rtwdev; + struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif_link); + struct sk_buff *skb, *tmp; +@@ -2966,11 +2971,11 @@ static void rtw89_core_sta_pending_tx_iter(void *data, + if (rtwvif_link->chanctx_idx != rtwvif_target->chanctx_idx) + return; + +- if (skb_queue_len(&rtwsta->roc_queue) == 0) ++ if (skb_queue_len(&rtwsta_link->roc_queue) == 0) + return; + +- skb_queue_walk_safe(&rtwsta->roc_queue, skb, tmp) { +- skb_unlink(skb, &rtwsta->roc_queue); ++ skb_queue_walk_safe(&rtwsta_link->roc_queue, skb, tmp) { ++ skb_unlink(skb, &rtwsta_link->roc_queue); + + ret = rtw89_core_tx_write(rtwdev, vif, sta, skb, &qsel); + if (ret) { +@@ -3328,7 +3333,8 @@ void rtw89_core_release_all_bits_map(unsigned long *addr, unsigned int nbits) + } + + int rtw89_core_acquire_sta_ba_entry(struct rtw89_dev *rtwdev, +- struct rtw89_sta *rtwsta, u8 tid, u8 *cam_idx) ++ struct rtw89_sta_link *rtwsta_link, u8 tid, ++ u8 *cam_idx) + { + const struct rtw89_chip_info *chip = rtwdev->chip; + struct rtw89_cam_info *cam_info = &rtwdev->cam_info; +@@ -3365,7 +3371,7 @@ int rtw89_core_acquire_sta_ba_entry(struct rtw89_dev *rtwdev, + } + + entry->tid = tid; +- list_add_tail(&entry->list, &rtwsta->ba_cam_list); ++ list_add_tail(&entry->list, &rtwsta_link->ba_cam_list); + + *cam_idx = idx; + +@@ -3373,7 +3379,8 @@ int rtw89_core_acquire_sta_ba_entry(struct rtw89_dev *rtwdev, + } + + int rtw89_core_release_sta_ba_entry(struct rtw89_dev *rtwdev, +- struct rtw89_sta *rtwsta, u8 tid, u8 *cam_idx) ++ struct rtw89_sta_link *rtwsta_link, u8 tid, ++ u8 *cam_idx) + { + struct rtw89_cam_info *cam_info = &rtwdev->cam_info; + struct rtw89_ba_cam_entry *entry = NULL, *tmp; +@@ -3381,7 +3388,7 @@ int rtw89_core_release_sta_ba_entry(struct rtw89_dev *rtwdev, + + lockdep_assert_held(&rtwdev->mutex); + +- list_for_each_entry_safe(entry, tmp, &rtwsta->ba_cam_list, list) { ++ list_for_each_entry_safe(entry, tmp, &rtwsta_link->ba_cam_list, list) { + if (entry->tid != tid) + continue; + +@@ -3459,67 +3466,67 @@ int rtw89_core_sta_add(struct rtw89_dev *rtwdev, + struct ieee80211_sta *sta) + { + struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv; +- struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv; ++ struct rtw89_sta_link *rtwsta_link = (struct rtw89_sta_link *)sta->drv_priv; + struct rtw89_hal *hal = &rtwdev->hal; + u8 ant_num = hal->ant_diversity ? 2 : rtwdev->chip->rf_path_num; + int i; + int ret; + +- rtwsta->rtwdev = rtwdev; +- rtwsta->rtwvif_link = rtwvif_link; +- rtwsta->prev_rssi = 0; +- INIT_LIST_HEAD(&rtwsta->ba_cam_list); +- skb_queue_head_init(&rtwsta->roc_queue); ++ rtwsta_link->rtwdev = rtwdev; ++ rtwsta_link->rtwvif_link = rtwvif_link; ++ rtwsta_link->prev_rssi = 0; ++ INIT_LIST_HEAD(&rtwsta_link->ba_cam_list); ++ skb_queue_head_init(&rtwsta_link->roc_queue); + + for (i = 0; i < ARRAY_SIZE(sta->txq); i++) + rtw89_core_txq_init(rtwdev, sta->txq[i]); + +- ewma_rssi_init(&rtwsta->avg_rssi); +- ewma_snr_init(&rtwsta->avg_snr); +- ewma_evm_init(&rtwsta->evm_1ss); ++ ewma_rssi_init(&rtwsta_link->avg_rssi); ++ ewma_snr_init(&rtwsta_link->avg_snr); ++ ewma_evm_init(&rtwsta_link->evm_1ss); + for (i = 0; i < ant_num; i++) { +- ewma_rssi_init(&rtwsta->rssi[i]); +- ewma_evm_init(&rtwsta->evm_min[i]); +- ewma_evm_init(&rtwsta->evm_max[i]); ++ ewma_rssi_init(&rtwsta_link->rssi[i]); ++ ewma_evm_init(&rtwsta_link->evm_min[i]); ++ ewma_evm_init(&rtwsta_link->evm_max[i]); + } + + if (vif->type == NL80211_IFTYPE_STATION && !sta->tdls) { + /* for station mode, assign the mac_id from itself */ +- rtwsta->mac_id = rtwvif_link->mac_id; ++ rtwsta_link->mac_id = rtwvif_link->mac_id; + + /* must do rtw89_reg_6ghz_recalc() before rfk channel */ + ret = rtw89_reg_6ghz_recalc(rtwdev, rtwvif_link, true); + if (ret) + return ret; + +- rtw89_btc_ntfy_role_info(rtwdev, rtwvif_link, rtwsta, ++ rtw89_btc_ntfy_role_info(rtwdev, rtwvif_link, rtwsta_link, + BTC_ROLE_MSTS_STA_CONN_START); + rtw89_chip_rfk_channel(rtwdev, rtwvif_link); + } else if (vif->type == NL80211_IFTYPE_AP || sta->tdls) { +- rtwsta->mac_id = rtw89_acquire_mac_id(rtwdev); +- if (rtwsta->mac_id == RTW89_MAX_MAC_ID_NUM) ++ rtwsta_link->mac_id = rtw89_acquire_mac_id(rtwdev); ++ if (rtwsta_link->mac_id == RTW89_MAX_MAC_ID_NUM) + return -ENOSPC; + +- ret = rtw89_mac_set_macid_pause(rtwdev, rtwsta->mac_id, false); ++ ret = rtw89_mac_set_macid_pause(rtwdev, rtwsta_link->mac_id, false); + if (ret) { +- rtw89_release_mac_id(rtwdev, rtwsta->mac_id); ++ rtw89_release_mac_id(rtwdev, rtwsta_link->mac_id); + rtw89_warn(rtwdev, "failed to send h2c macid pause\n"); + return ret; + } + +- ret = rtw89_fw_h2c_role_maintain(rtwdev, rtwvif_link, rtwsta, ++ ret = rtw89_fw_h2c_role_maintain(rtwdev, rtwvif_link, rtwsta_link, + RTW89_ROLE_CREATE); + if (ret) { +- rtw89_release_mac_id(rtwdev, rtwsta->mac_id); ++ rtw89_release_mac_id(rtwdev, rtwsta_link->mac_id); + rtw89_warn(rtwdev, "failed to send h2c role info\n"); + return ret; + } + +- ret = rtw89_chip_h2c_default_cmac_tbl(rtwdev, rtwvif_link, rtwsta); ++ ret = rtw89_chip_h2c_default_cmac_tbl(rtwdev, rtwvif_link, rtwsta_link); + if (ret) + return ret; + +- ret = rtw89_chip_h2c_default_dmac_tbl(rtwdev, rtwvif_link, rtwsta); ++ ret = rtw89_chip_h2c_default_dmac_tbl(rtwdev, rtwvif_link, rtwsta_link); + if (ret) + return ret; + +@@ -3534,7 +3541,7 @@ int rtw89_core_sta_disassoc(struct rtw89_dev *rtwdev, + struct ieee80211_sta *sta) + { + struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv; +- struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv; ++ struct rtw89_sta_link *rtwsta_link = (struct rtw89_sta_link *)sta->drv_priv; + + if (vif->type == NL80211_IFTYPE_STATION) + rtw89_fw_h2c_set_bcn_fltr_cfg(rtwdev, vif, false); +@@ -3542,7 +3549,7 @@ int rtw89_core_sta_disassoc(struct rtw89_dev *rtwdev, + rtwdev->total_sta_assoc--; + if (sta->tdls) + rtwvif_link->tdls_peer--; +- rtwsta->disassoc = true; ++ rtwsta_link->disassoc = true; + + return 0; + } +@@ -3552,7 +3559,7 @@ int rtw89_core_sta_disconnect(struct rtw89_dev *rtwdev, + struct ieee80211_sta *sta) + { + struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv; +- struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv; ++ struct rtw89_sta_link *rtwsta_link = (struct rtw89_sta_link *)sta->drv_priv; + int ret; + + rtw89_mac_bf_monitor_calc(rtwdev, sta, true); +@@ -3562,9 +3569,9 @@ int rtw89_core_sta_disconnect(struct rtw89_dev *rtwdev, + rtw89_core_free_sta_pending_roc_tx(rtwdev, sta); + + if (vif->type == NL80211_IFTYPE_AP || sta->tdls) +- rtw89_cam_deinit_addr_cam(rtwdev, &rtwsta->addr_cam); ++ rtw89_cam_deinit_addr_cam(rtwdev, &rtwsta_link->addr_cam); + if (sta->tdls) +- rtw89_cam_deinit_bssid_cam(rtwdev, &rtwsta->bssid_cam); ++ rtw89_cam_deinit_bssid_cam(rtwdev, &rtwsta_link->bssid_cam); + + if (vif->type == NL80211_IFTYPE_STATION && !sta->tdls) { + rtw89_vif_type_mapping(vif, false); +@@ -3577,14 +3584,14 @@ int rtw89_core_sta_disconnect(struct rtw89_dev *rtwdev, + return ret; + } + +- ret = rtw89_fw_h2c_join_info(rtwdev, rtwvif_link, rtwsta, true); ++ ret = rtw89_fw_h2c_join_info(rtwdev, rtwvif_link, rtwsta_link, true); + if (ret) { + rtw89_warn(rtwdev, "failed to send h2c join info\n"); + return ret; + } + + /* update cam aid mac_id net_type */ +- ret = rtw89_fw_h2c_cam(rtwdev, rtwvif_link, rtwsta, NULL); ++ ret = rtw89_fw_h2c_cam(rtwdev, rtwvif_link, rtwsta_link, NULL); + if (ret) { + rtw89_warn(rtwdev, "failed to send h2c cam\n"); + return ret; +@@ -3598,9 +3605,9 @@ int rtw89_core_sta_assoc(struct rtw89_dev *rtwdev, + struct ieee80211_sta *sta) + { + struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv; +- struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv; ++ struct rtw89_sta_link *rtwsta_link = (struct rtw89_sta_link *)sta->drv_priv; + struct rtw89_bssid_cam_entry *bssid_cam = rtw89_get_bssid_cam_of(rtwvif_link, +- rtwsta); ++ rtwsta_link); + const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, + rtwvif_link->chanctx_idx); + int ret; +@@ -3615,7 +3622,7 @@ int rtw89_core_sta_assoc(struct rtw89_dev *rtwdev, + } + } + +- ret = rtw89_cam_init_addr_cam(rtwdev, &rtwsta->addr_cam, bssid_cam); ++ ret = rtw89_cam_init_addr_cam(rtwdev, &rtwsta_link->addr_cam, bssid_cam); + if (ret) { + rtw89_warn(rtwdev, "failed to send h2c init addr cam\n"); + return ret; +@@ -3628,14 +3635,14 @@ int rtw89_core_sta_assoc(struct rtw89_dev *rtwdev, + return ret; + } + +- ret = rtw89_fw_h2c_join_info(rtwdev, rtwvif_link, rtwsta, false); ++ ret = rtw89_fw_h2c_join_info(rtwdev, rtwvif_link, rtwsta_link, false); + if (ret) { + rtw89_warn(rtwdev, "failed to send h2c join info\n"); + return ret; + } + + /* update cam aid mac_id net_type */ +- ret = rtw89_fw_h2c_cam(rtwdev, rtwvif_link, rtwsta, NULL); ++ ret = rtw89_fw_h2c_cam(rtwdev, rtwvif_link, rtwsta_link, NULL); + if (ret) { + rtw89_warn(rtwdev, "failed to send h2c cam\n"); + return ret; +@@ -3653,14 +3660,14 @@ int rtw89_core_sta_assoc(struct rtw89_dev *rtwdev, + + if (bss_conf->he_support && + !(bss_conf->he_oper.params & IEEE80211_HE_OPERATION_ER_SU_DISABLE)) +- rtwsta->er_cap = true; ++ rtwsta_link->er_cap = true; + +- rtw89_btc_ntfy_role_info(rtwdev, rtwvif_link, rtwsta, ++ rtw89_btc_ntfy_role_info(rtwdev, rtwvif_link, rtwsta_link, + BTC_ROLE_MSTS_STA_CONN_END); +- rtw89_core_get_no_ul_ofdma_htc(rtwdev, &rtwsta->htc_template, chan); ++ rtw89_core_get_no_ul_ofdma_htc(rtwdev, &rtwsta_link->htc_template, chan); + rtw89_phy_ul_tb_assoc(rtwdev, rtwvif_link); + +- ret = rtw89_fw_h2c_general_pkt(rtwdev, rtwvif_link, rtwsta->mac_id); ++ ret = rtw89_fw_h2c_general_pkt(rtwdev, rtwvif_link, rtwsta_link->mac_id); + if (ret) { + rtw89_warn(rtwdev, "failed to send h2c general packet\n"); + return ret; +@@ -3677,17 +3684,17 @@ int rtw89_core_sta_remove(struct rtw89_dev *rtwdev, + struct ieee80211_sta *sta) + { + struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv; +- struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv; ++ struct rtw89_sta_link *rtwsta_link = (struct rtw89_sta_link *)sta->drv_priv; + int ret; + + if (vif->type == NL80211_IFTYPE_STATION && !sta->tdls) { + rtw89_reg_6ghz_recalc(rtwdev, rtwvif_link, false); +- rtw89_btc_ntfy_role_info(rtwdev, rtwvif_link, rtwsta, ++ rtw89_btc_ntfy_role_info(rtwdev, rtwvif_link, rtwsta_link, + BTC_ROLE_MSTS_STA_DIS_CONN); + } else if (vif->type == NL80211_IFTYPE_AP || sta->tdls) { +- rtw89_release_mac_id(rtwdev, rtwsta->mac_id); ++ rtw89_release_mac_id(rtwdev, rtwsta_link->mac_id); + +- ret = rtw89_fw_h2c_role_maintain(rtwdev, rtwvif_link, rtwsta, ++ ret = rtw89_fw_h2c_role_maintain(rtwdev, rtwvif_link, rtwsta_link, + RTW89_ROLE_REMOVE); + if (ret) { + rtw89_warn(rtwdev, "failed to send h2c role info\n"); +@@ -4703,7 +4710,7 @@ static int rtw89_core_register_hw(struct rtw89_dev *rtwdev) + int tx_headroom = IEEE80211_HT_CTL_LEN; + + hw->vif_data_size = sizeof(struct rtw89_vif_link); +- hw->sta_data_size = sizeof(struct rtw89_sta); ++ hw->sta_data_size = sizeof(struct rtw89_sta_link); + hw->txq_data_size = sizeof(struct rtw89_txq); + hw->chanctx_data_size = sizeof(struct rtw89_chanctx_cfg); + +diff --git a/drivers/net/wireless/realtek/rtw89/core.h b/drivers/net/wireless/realtek/rtw89/core.h +index e897c4f79f06c..5e22da91213ba 100644 +--- a/drivers/net/wireless/realtek/rtw89/core.h ++++ b/drivers/net/wireless/realtek/rtw89/core.h +@@ -3354,7 +3354,7 @@ struct rtw89_sec_cam_entry { + u8 key[32]; + }; + +-struct rtw89_sta { ++struct rtw89_sta_link { + u8 mac_id; + bool disassoc; + bool er_cap; +@@ -3647,10 +3647,10 @@ struct rtw89_chip_ops { + int (*resume_sch_tx)(struct rtw89_dev *rtwdev, u8 mac_idx, u32 tx_en); + int (*h2c_dctl_sec_cam)(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, +- struct rtw89_sta *rtwsta); ++ struct rtw89_sta_link *rtwsta_link); + int (*h2c_default_cmac_tbl)(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, +- struct rtw89_sta *rtwsta); ++ struct rtw89_sta_link *rtwsta_link); + int (*h2c_assoc_cmac_tbl)(struct rtw89_dev *rtwdev, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta); +@@ -3659,10 +3659,10 @@ struct rtw89_chip_ops { + struct ieee80211_sta *sta); + int (*h2c_default_dmac_tbl)(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, +- struct rtw89_sta *rtwsta); ++ struct rtw89_sta_link *rtwsta_link); + int (*h2c_update_beacon)(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link); +- int (*h2c_ba_cam)(struct rtw89_dev *rtwdev, struct rtw89_sta *rtwsta, ++ int (*h2c_ba_cam)(struct rtw89_dev *rtwdev, struct rtw89_sta_link *rtwsta_link, + bool valid, struct ieee80211_ampdu_params *params); + + void (*btc_set_rfe)(struct rtw89_dev *rtwdev); +@@ -5977,21 +5977,21 @@ static inline struct rtw89_vif_link *vif_to_rtwvif_safe(struct ieee80211_vif *vi + return vif ? (struct rtw89_vif_link *)vif->drv_priv : NULL; + } + +-static inline struct ieee80211_sta *rtwsta_to_sta(struct rtw89_sta *rtwsta) ++static inline struct ieee80211_sta *rtwsta_to_sta(struct rtw89_sta_link *rtwsta_link) + { +- void *p = rtwsta; ++ void *p = rtwsta_link; + + return container_of(p, struct ieee80211_sta, drv_priv); + } + +-static inline struct ieee80211_sta *rtwsta_to_sta_safe(struct rtw89_sta *rtwsta) ++static inline struct ieee80211_sta *rtwsta_to_sta_safe(struct rtw89_sta_link *rtwsta_link) + { +- return rtwsta ? rtwsta_to_sta(rtwsta) : NULL; ++ return rtwsta_link ? rtwsta_to_sta(rtwsta_link) : NULL; + } + +-static inline struct rtw89_sta *sta_to_rtwsta_safe(struct ieee80211_sta *sta) ++static inline struct rtw89_sta_link *sta_to_rtwsta_safe(struct ieee80211_sta *sta) + { +- return sta ? (struct rtw89_sta *)sta->drv_priv : NULL; ++ return sta ? (struct rtw89_sta_link *)sta->drv_priv : NULL; + } + + static inline u8 rtw89_hw_to_rate_info_bw(enum rtw89_bandwidth hw_bw) +@@ -6079,26 +6079,26 @@ enum nl80211_he_ru_alloc rtw89_he_rua_to_ru_alloc(u16 rua) + + static inline + struct rtw89_addr_cam_entry *rtw89_get_addr_cam_of(struct rtw89_vif_link *rtwvif_link, +- struct rtw89_sta *rtwsta) ++ struct rtw89_sta_link *rtwsta_link) + { +- if (rtwsta) { +- struct ieee80211_sta *sta = rtwsta_to_sta(rtwsta); ++ if (rtwsta_link) { ++ struct ieee80211_sta *sta = rtwsta_to_sta(rtwsta_link); + + if (rtwvif_link->net_type == RTW89_NET_TYPE_AP_MODE || sta->tdls) +- return &rtwsta->addr_cam; ++ return &rtwsta_link->addr_cam; + } + return &rtwvif_link->addr_cam; + } + + static inline + struct rtw89_bssid_cam_entry *rtw89_get_bssid_cam_of(struct rtw89_vif_link *rtwvif_link, +- struct rtw89_sta *rtwsta) ++ struct rtw89_sta_link *rtwsta_link) + { +- if (rtwsta) { +- struct ieee80211_sta *sta = rtwsta_to_sta(rtwsta); ++ if (rtwsta_link) { ++ struct ieee80211_sta *sta = rtwsta_to_sta(rtwsta_link); + + if (sta->tdls) +- return &rtwsta->bssid_cam; ++ return &rtwsta_link->bssid_cam; + } + return &rtwvif_link->bssid_cam; + } +@@ -6458,13 +6458,13 @@ int rtw89_chip_resume_sch_tx(struct rtw89_dev *rtwdev, u8 mac_idx, u32 tx_en) + static inline + int rtw89_chip_h2c_dctl_sec_cam(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, +- struct rtw89_sta *rtwsta) ++ struct rtw89_sta_link *rtwsta_link) + { + const struct rtw89_chip_info *chip = rtwdev->chip; + + if (!chip->ops->h2c_dctl_sec_cam) + return 0; +- return chip->ops->h2c_dctl_sec_cam(rtwdev, rtwvif_link, rtwsta); ++ return chip->ops->h2c_dctl_sec_cam(rtwdev, rtwvif_link, rtwsta_link); + } + + static inline u8 *get_hdr_bssid(struct ieee80211_hdr *hdr) +@@ -6646,9 +6646,11 @@ u8 rtw89_core_acquire_bit_map(unsigned long *addr, unsigned long size); + void rtw89_core_release_bit_map(unsigned long *addr, u8 bit); + void rtw89_core_release_all_bits_map(unsigned long *addr, unsigned int nbits); + int rtw89_core_acquire_sta_ba_entry(struct rtw89_dev *rtwdev, +- struct rtw89_sta *rtwsta, u8 tid, u8 *cam_idx); ++ struct rtw89_sta_link *rtwsta_link, u8 tid, ++ u8 *cam_idx); + int rtw89_core_release_sta_ba_entry(struct rtw89_dev *rtwdev, +- struct rtw89_sta *rtwsta, u8 tid, u8 *cam_idx); ++ struct rtw89_sta_link *rtwsta_link, u8 tid, ++ u8 *cam_idx); + void rtw89_vif_type_mapping(struct ieee80211_vif *vif, bool assoc); + int rtw89_chip_info_setup(struct rtw89_dev *rtwdev); + bool rtw89_ra_report_to_bitrate(struct rtw89_dev *rtwdev, u8 rpt_rate, u16 *bitrate); +diff --git a/drivers/net/wireless/realtek/rtw89/debug.c b/drivers/net/wireless/realtek/rtw89/debug.c +index 26327e4b071d2..f09f1a251b169 100644 +--- a/drivers/net/wireless/realtek/rtw89/debug.c ++++ b/drivers/net/wireless/realtek/rtw89/debug.c +@@ -3518,11 +3518,11 @@ static void rtw89_sta_info_get_iter(void *data, struct ieee80211_sta *sta) + [NL80211_RATE_INFO_EHT_GI_1_6] = "1.6", + [NL80211_RATE_INFO_EHT_GI_3_2] = "3.2", + }; +- struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv; +- struct rate_info *rate = &rtwsta->ra_report.txrate; +- struct ieee80211_rx_status *status = &rtwsta->rx_status; ++ struct rtw89_sta_link *rtwsta_link = (struct rtw89_sta_link *)sta->drv_priv; ++ struct rate_info *rate = &rtwsta_link->ra_report.txrate; ++ struct ieee80211_rx_status *status = &rtwsta_link->rx_status; + struct seq_file *m = (struct seq_file *)data; +- struct rtw89_dev *rtwdev = rtwsta->rtwdev; ++ struct rtw89_dev *rtwdev = rtwsta_link->rtwdev; + struct rtw89_hal *hal = &rtwdev->hal; + u8 ant_num = hal->ant_diversity ? 2 : rtwdev->chip->rf_path_num; + bool ant_asterisk = hal->tx_path_diversity || hal->ant_diversity; +@@ -3531,7 +3531,7 @@ static void rtw89_sta_info_get_iter(void *data, struct ieee80211_sta *sta) + u8 snr; + int i; + +- seq_printf(m, "TX rate [%d]: ", rtwsta->mac_id); ++ seq_printf(m, "TX rate [%d]: ", rtwsta_link->mac_id); + + if (rate->flags & RATE_INFO_FLAGS_MCS) + seq_printf(m, "HT MCS-%d%s", rate->mcs, +@@ -3549,13 +3549,13 @@ static void rtw89_sta_info_get_iter(void *data, struct ieee80211_sta *sta) + eht_gi_str[rate->eht_gi] : "N/A"); + else + seq_printf(m, "Legacy %d", rate->legacy); +- seq_printf(m, "%s", rtwsta->ra_report.might_fallback_legacy ? " FB_G" : ""); ++ seq_printf(m, "%s", rtwsta_link->ra_report.might_fallback_legacy ? " FB_G" : ""); + seq_printf(m, " BW:%u", rtw89_rate_info_bw_to_mhz(rate->bw)); +- seq_printf(m, "\t(hw_rate=0x%x)", rtwsta->ra_report.hw_rate); +- seq_printf(m, "\t==> agg_wait=%d (%d)\n", rtwsta->max_agg_wait, ++ seq_printf(m, "\t(hw_rate=0x%x)", rtwsta_link->ra_report.hw_rate); ++ seq_printf(m, "\t==> agg_wait=%d (%d)\n", rtwsta_link->max_agg_wait, + sta->deflink.agg.max_rc_amsdu_len); + +- seq_printf(m, "RX rate [%d]: ", rtwsta->mac_id); ++ seq_printf(m, "RX rate [%d]: ", rtwsta_link->mac_id); + + switch (status->encoding) { + case RX_ENC_LEGACY: +@@ -3582,24 +3582,24 @@ static void rtw89_sta_info_get_iter(void *data, struct ieee80211_sta *sta) + break; + } + seq_printf(m, " BW:%u", rtw89_rate_info_bw_to_mhz(status->bw)); +- seq_printf(m, "\t(hw_rate=0x%x)\n", rtwsta->rx_hw_rate); ++ seq_printf(m, "\t(hw_rate=0x%x)\n", rtwsta_link->rx_hw_rate); + +- rssi = ewma_rssi_read(&rtwsta->avg_rssi); ++ rssi = ewma_rssi_read(&rtwsta_link->avg_rssi); + seq_printf(m, "RSSI: %d dBm (raw=%d, prev=%d) [", +- RTW89_RSSI_RAW_TO_DBM(rssi), rssi, rtwsta->prev_rssi); ++ RTW89_RSSI_RAW_TO_DBM(rssi), rssi, rtwsta_link->prev_rssi); + for (i = 0; i < ant_num; i++) { +- rssi = ewma_rssi_read(&rtwsta->rssi[i]); ++ rssi = ewma_rssi_read(&rtwsta_link->rssi[i]); + seq_printf(m, "%d%s%s", RTW89_RSSI_RAW_TO_DBM(rssi), + ant_asterisk && (hal->antenna_tx & BIT(i)) ? "*" : "", + i + 1 == ant_num ? "" : ", "); + } + seq_puts(m, "]\n"); + +- evm_1ss = ewma_evm_read(&rtwsta->evm_1ss); ++ evm_1ss = ewma_evm_read(&rtwsta_link->evm_1ss); + seq_printf(m, "EVM: [%2u.%02u, ", evm_1ss >> 2, (evm_1ss & 0x3) * 25); + for (i = 0; i < (hal->ant_diversity ? 2 : 1); i++) { +- evm_min = ewma_evm_read(&rtwsta->evm_min[i]); +- evm_max = ewma_evm_read(&rtwsta->evm_max[i]); ++ evm_min = ewma_evm_read(&rtwsta_link->evm_min[i]); ++ evm_max = ewma_evm_read(&rtwsta_link->evm_max[i]); + + seq_printf(m, "%s(%2u.%02u, %2u.%02u)", i == 0 ? "" : " ", + evm_min >> 2, (evm_min & 0x3) * 25, +@@ -3607,7 +3607,7 @@ static void rtw89_sta_info_get_iter(void *data, struct ieee80211_sta *sta) + } + seq_puts(m, "]\t"); + +- snr = ewma_snr_read(&rtwsta->avg_snr); ++ snr = ewma_snr_read(&rtwsta_link->avg_snr); + seq_printf(m, "SNR: %u\n", snr); + } + +@@ -3752,14 +3752,14 @@ void rtw89_vif_ids_get_iter(void *data, u8 *mac, struct ieee80211_vif *vif) + "\tpkt_ofld[GENERAL]: "); + } + +-static void rtw89_dump_ba_cam(struct seq_file *m, struct rtw89_sta *rtwsta) ++static void rtw89_dump_ba_cam(struct seq_file *m, struct rtw89_sta_link *rtwsta_link) + { +- struct rtw89_vif_link *rtwvif_link = rtwsta->rtwvif_link; ++ struct rtw89_vif_link *rtwvif_link = rtwsta_link->rtwvif_link; + struct rtw89_dev *rtwdev = rtwvif_link->rtwdev; + struct rtw89_ba_cam_entry *entry; + bool first = true; + +- list_for_each_entry(entry, &rtwsta->ba_cam_list, list) { ++ list_for_each_entry(entry, &rtwsta_link->ba_cam_list, list) { + if (first) { + seq_puts(m, "\tba_cam "); + first = false; +@@ -3774,14 +3774,14 @@ static void rtw89_dump_ba_cam(struct seq_file *m, struct rtw89_sta *rtwsta) + + static void rtw89_sta_ids_get_iter(void *data, struct ieee80211_sta *sta) + { +- struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv; +- struct rtw89_dev *rtwdev = rtwsta->rtwdev; ++ struct rtw89_sta_link *rtwsta_link = (struct rtw89_sta_link *)sta->drv_priv; ++ struct rtw89_dev *rtwdev = rtwsta_link->rtwdev; + struct seq_file *m = (struct seq_file *)data; + +- seq_printf(m, "STA [%d] %pM %s\n", rtwsta->mac_id, sta->addr, ++ seq_printf(m, "STA [%d] %pM %s\n", rtwsta_link->mac_id, sta->addr, + sta->tdls ? "(TDLS)" : ""); +- rtw89_dump_addr_cam(m, rtwdev, &rtwsta->addr_cam); +- rtw89_dump_ba_cam(m, rtwsta); ++ rtw89_dump_addr_cam(m, rtwdev, &rtwsta_link->addr_cam); ++ rtw89_dump_ba_cam(m, rtwsta_link); + } + + static int rtw89_debug_priv_stations_get(struct seq_file *m, void *v) +diff --git a/drivers/net/wireless/realtek/rtw89/fw.c b/drivers/net/wireless/realtek/rtw89/fw.c +index 1d5de66bf9458..03775064ee0c1 100644 +--- a/drivers/net/wireless/realtek/rtw89/fw.c ++++ b/drivers/net/wireless/realtek/rtw89/fw.c +@@ -1742,7 +1742,7 @@ void rtw89_fw_log_dump(struct rtw89_dev *rtwdev, u8 *buf, u32 len) + + #define H2C_CAM_LEN 60 + int rtw89_fw_h2c_cam(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, +- struct rtw89_sta *rtwsta, const u8 *scan_mac_addr) ++ struct rtw89_sta_link *rtwsta_link, const u8 *scan_mac_addr) + { + struct sk_buff *skb; + int ret; +@@ -1753,9 +1753,9 @@ int rtw89_fw_h2c_cam(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_lin + return -ENOMEM; + } + skb_put(skb, H2C_CAM_LEN); +- rtw89_cam_fill_addr_cam_info(rtwdev, rtwvif_link, rtwsta, scan_mac_addr, ++ rtw89_cam_fill_addr_cam_info(rtwdev, rtwvif_link, rtwsta_link, scan_mac_addr, + skb->data); +- rtw89_cam_fill_bssid_cam_info(rtwdev, rtwvif_link, rtwsta, skb->data); ++ rtw89_cam_fill_bssid_cam_info(rtwdev, rtwvif_link, rtwsta_link, skb->data); + + rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C, + H2C_CAT_MAC, +@@ -1778,7 +1778,7 @@ int rtw89_fw_h2c_cam(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_lin + + int rtw89_fw_h2c_dctl_sec_cam_v1(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, +- struct rtw89_sta *rtwsta) ++ struct rtw89_sta_link *rtwsta_link) + { + struct rtw89_h2c_dctlinfo_ud_v1 *h2c; + u32 len = sizeof(*h2c); +@@ -1793,7 +1793,7 @@ int rtw89_fw_h2c_dctl_sec_cam_v1(struct rtw89_dev *rtwdev, + skb_put(skb, len); + h2c = (struct rtw89_h2c_dctlinfo_ud_v1 *)skb->data; + +- rtw89_cam_fill_dctl_sec_cam_info_v1(rtwdev, rtwvif_link, rtwsta, h2c); ++ rtw89_cam_fill_dctl_sec_cam_info_v1(rtwdev, rtwvif_link, rtwsta_link, h2c); + + rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C, + H2C_CAT_MAC, +@@ -1817,7 +1817,7 @@ EXPORT_SYMBOL(rtw89_fw_h2c_dctl_sec_cam_v1); + + int rtw89_fw_h2c_dctl_sec_cam_v2(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, +- struct rtw89_sta *rtwsta) ++ struct rtw89_sta_link *rtwsta_link) + { + struct rtw89_h2c_dctlinfo_ud_v2 *h2c; + u32 len = sizeof(*h2c); +@@ -1832,7 +1832,7 @@ int rtw89_fw_h2c_dctl_sec_cam_v2(struct rtw89_dev *rtwdev, + skb_put(skb, len); + h2c = (struct rtw89_h2c_dctlinfo_ud_v2 *)skb->data; + +- rtw89_cam_fill_dctl_sec_cam_info_v2(rtwdev, rtwvif_link, rtwsta, h2c); ++ rtw89_cam_fill_dctl_sec_cam_info_v2(rtwdev, rtwvif_link, rtwsta_link, h2c); + + rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C, + H2C_CAT_MAC, +@@ -1856,9 +1856,9 @@ EXPORT_SYMBOL(rtw89_fw_h2c_dctl_sec_cam_v2); + + int rtw89_fw_h2c_default_dmac_tbl_v2(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, +- struct rtw89_sta *rtwsta) ++ struct rtw89_sta_link *rtwsta_link) + { +- u8 mac_id = rtwsta ? rtwsta->mac_id : rtwvif_link->mac_id; ++ u8 mac_id = rtwsta_link ? rtwsta_link->mac_id : rtwvif_link->mac_id; + struct rtw89_h2c_dctlinfo_ud_v2 *h2c; + u32 len = sizeof(*h2c); + struct sk_buff *skb; +@@ -1909,21 +1909,23 @@ int rtw89_fw_h2c_default_dmac_tbl_v2(struct rtw89_dev *rtwdev, + } + EXPORT_SYMBOL(rtw89_fw_h2c_default_dmac_tbl_v2); + +-int rtw89_fw_h2c_ba_cam(struct rtw89_dev *rtwdev, struct rtw89_sta *rtwsta, ++int rtw89_fw_h2c_ba_cam(struct rtw89_dev *rtwdev, struct rtw89_sta_link *rtwsta_link, + bool valid, struct ieee80211_ampdu_params *params) + { + const struct rtw89_chip_info *chip = rtwdev->chip; +- struct rtw89_vif_link *rtwvif_link = rtwsta->rtwvif_link; ++ struct rtw89_vif_link *rtwvif_link = rtwsta_link->rtwvif_link; + struct rtw89_h2c_ba_cam *h2c; +- u8 macid = rtwsta->mac_id; ++ u8 macid = rtwsta_link->mac_id; + u32 len = sizeof(*h2c); + struct sk_buff *skb; + u8 entry_idx; + int ret; + + ret = valid ? +- rtw89_core_acquire_sta_ba_entry(rtwdev, rtwsta, params->tid, &entry_idx) : +- rtw89_core_release_sta_ba_entry(rtwdev, rtwsta, params->tid, &entry_idx); ++ rtw89_core_acquire_sta_ba_entry(rtwdev, rtwsta_link, params->tid, ++ &entry_idx) : ++ rtw89_core_release_sta_ba_entry(rtwdev, rtwsta_link, params->tid, ++ &entry_idx); + if (ret) { + /* it still works even if we don't have static BA CAM, because + * hardware can create dynamic BA CAM automatically. +@@ -2041,13 +2043,13 @@ void rtw89_fw_h2c_init_dynamic_ba_cam_v0_ext(struct rtw89_dev *rtwdev) + } + } + +-int rtw89_fw_h2c_ba_cam_v1(struct rtw89_dev *rtwdev, struct rtw89_sta *rtwsta, ++int rtw89_fw_h2c_ba_cam_v1(struct rtw89_dev *rtwdev, struct rtw89_sta_link *rtwsta_link, + bool valid, struct ieee80211_ampdu_params *params) + { + const struct rtw89_chip_info *chip = rtwdev->chip; +- struct rtw89_vif_link *rtwvif_link = rtwsta->rtwvif_link; ++ struct rtw89_vif_link *rtwvif_link = rtwsta_link->rtwvif_link; + struct rtw89_h2c_ba_cam_v1 *h2c; +- u8 macid = rtwsta->mac_id; ++ u8 macid = rtwsta_link->mac_id; + u32 len = sizeof(*h2c); + struct sk_buff *skb; + u8 entry_idx; +@@ -2055,8 +2057,10 @@ int rtw89_fw_h2c_ba_cam_v1(struct rtw89_dev *rtwdev, struct rtw89_sta *rtwsta, + int ret; + + ret = valid ? +- rtw89_core_acquire_sta_ba_entry(rtwdev, rtwsta, params->tid, &entry_idx) : +- rtw89_core_release_sta_ba_entry(rtwdev, rtwsta, params->tid, &entry_idx); ++ rtw89_core_acquire_sta_ba_entry(rtwdev, rtwsta_link, params->tid, ++ &entry_idx) : ++ rtw89_core_release_sta_ba_entry(rtwdev, rtwsta_link, params->tid, ++ &entry_idx); + if (ret) { + /* it still works even if we don't have static BA CAM, because + * hardware can create dynamic BA CAM automatically. +@@ -2627,10 +2631,10 @@ static void __rtw89_fw_h2c_set_tx_path(struct rtw89_dev *rtwdev, + #define H2C_CMC_TBL_LEN 68 + int rtw89_fw_h2c_default_cmac_tbl(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, +- struct rtw89_sta *rtwsta) ++ struct rtw89_sta_link *rtwsta_link) + { + const struct rtw89_chip_info *chip = rtwdev->chip; +- u8 macid = rtwsta ? rtwsta->mac_id : rtwvif_link->mac_id; ++ u8 macid = rtwsta_link ? rtwsta_link->mac_id : rtwvif_link->mac_id; + struct sk_buff *skb; + int ret; + +@@ -2676,9 +2680,9 @@ EXPORT_SYMBOL(rtw89_fw_h2c_default_cmac_tbl); + + int rtw89_fw_h2c_default_cmac_tbl_g7(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, +- struct rtw89_sta *rtwsta) ++ struct rtw89_sta_link *rtwsta_link) + { +- u8 mac_id = rtwsta ? rtwsta->mac_id : rtwvif_link->mac_id; ++ u8 mac_id = rtwsta_link ? rtwsta_link->mac_id : rtwvif_link->mac_id; + struct rtw89_h2c_cctlinfo_ud_g7 *h2c; + u32 len = sizeof(*h2c); + struct sk_buff *skb; +@@ -2817,13 +2821,13 @@ int rtw89_fw_h2c_assoc_cmac_tbl(struct rtw89_dev *rtwdev, + struct ieee80211_sta *sta) + { + const struct rtw89_chip_info *chip = rtwdev->chip; +- struct rtw89_sta *rtwsta = sta_to_rtwsta_safe(sta); ++ struct rtw89_sta_link *rtwsta_link = sta_to_rtwsta_safe(sta); + struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv; + const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, + rtwvif_link->chanctx_idx); + struct sk_buff *skb; + u8 pads[RTW89_PPE_BW_NUM]; +- u8 mac_id = rtwsta ? rtwsta->mac_id : rtwvif_link->mac_id; ++ u8 mac_id = rtwsta_link ? rtwsta_link->mac_id : rtwvif_link->mac_id; + u16 lowest_rate; + int ret; + +@@ -2954,9 +2958,9 @@ int rtw89_fw_h2c_assoc_cmac_tbl_g7(struct rtw89_dev *rtwdev, + struct ieee80211_sta *sta) + { + struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv; +- struct rtw89_sta *rtwsta = sta_to_rtwsta_safe(sta); ++ struct rtw89_sta_link *rtwsta_link = sta_to_rtwsta_safe(sta); + const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, rtwvif_link->chanctx_idx); +- u8 mac_id = rtwsta ? rtwsta->mac_id : rtwvif_link->mac_id; ++ u8 mac_id = rtwsta_link ? rtwsta_link->mac_id : rtwvif_link->mac_id; + struct rtw89_h2c_cctlinfo_ud_g7 *h2c; + u8 pads[RTW89_PPE_BW_NUM]; + u32 len = sizeof(*h2c); +@@ -3069,7 +3073,7 @@ int rtw89_fw_h2c_ampdu_cmac_tbl_g7(struct rtw89_dev *rtwdev, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta) + { +- struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv; ++ struct rtw89_sta_link *rtwsta_link = (struct rtw89_sta_link *)sta->drv_priv; + struct rtw89_h2c_cctlinfo_ud_g7 *h2c; + u32 len = sizeof(*h2c); + struct sk_buff *skb; +@@ -3086,11 +3090,11 @@ int rtw89_fw_h2c_ampdu_cmac_tbl_g7(struct rtw89_dev *rtwdev, + skb_put(skb, len); + h2c = (struct rtw89_h2c_cctlinfo_ud_g7 *)skb->data; + +- for_each_set_bit(tid, rtwsta->ampdu_map, IEEE80211_NUM_TIDS) { ++ for_each_set_bit(tid, rtwsta_link->ampdu_map, IEEE80211_NUM_TIDS) { + if (agg_num == 0) +- agg_num = rtwsta->ampdu_params[tid].agg_num; ++ agg_num = rtwsta_link->ampdu_params[tid].agg_num; + else +- agg_num = min(agg_num, rtwsta->ampdu_params[tid].agg_num); ++ agg_num = min(agg_num, rtwsta_link->ampdu_params[tid].agg_num); + } + + if (agg_num <= 0x20) +@@ -3106,7 +3110,7 @@ int rtw89_fw_h2c_ampdu_cmac_tbl_g7(struct rtw89_dev *rtwdev, + else if (agg_num > 0x200 && agg_num <= 0x400) + ba_bmap = 5; + +- h2c->c0 = le32_encode_bits(rtwsta->mac_id, CCTLINFO_G7_C0_MACID) | ++ h2c->c0 = le32_encode_bits(rtwsta_link->mac_id, CCTLINFO_G7_C0_MACID) | + le32_encode_bits(1, CCTLINFO_G7_C0_OP); + + h2c->w3 = le32_encode_bits(ba_bmap, CCTLINFO_G7_W3_BA_BMAP); +@@ -3132,7 +3136,7 @@ int rtw89_fw_h2c_ampdu_cmac_tbl_g7(struct rtw89_dev *rtwdev, + EXPORT_SYMBOL(rtw89_fw_h2c_ampdu_cmac_tbl_g7); + + int rtw89_fw_h2c_txtime_cmac_tbl(struct rtw89_dev *rtwdev, +- struct rtw89_sta *rtwsta) ++ struct rtw89_sta_link *rtwsta_link) + { + const struct rtw89_chip_info *chip = rtwdev->chip; + struct sk_buff *skb; +@@ -3144,15 +3148,15 @@ int rtw89_fw_h2c_txtime_cmac_tbl(struct rtw89_dev *rtwdev, + return -ENOMEM; + } + skb_put(skb, H2C_CMC_TBL_LEN); +- SET_CTRL_INFO_MACID(skb->data, rtwsta->mac_id); ++ SET_CTRL_INFO_MACID(skb->data, rtwsta_link->mac_id); + SET_CTRL_INFO_OPERATION(skb->data, 1); +- if (rtwsta->cctl_tx_time) { ++ if (rtwsta_link->cctl_tx_time) { + SET_CMC_TBL_AMPDU_TIME_SEL(skb->data, 1); +- SET_CMC_TBL_AMPDU_MAX_TIME(skb->data, rtwsta->ampdu_max_time); ++ SET_CMC_TBL_AMPDU_MAX_TIME(skb->data, rtwsta_link->ampdu_max_time); + } +- if (rtwsta->cctl_tx_retry_limit) { ++ if (rtwsta_link->cctl_tx_retry_limit) { + SET_CMC_TBL_DATA_TXCNT_LMT_SEL(skb->data, 1); +- SET_CMC_TBL_DATA_TX_CNT_LMT(skb->data, rtwsta->data_tx_cnt_lmt); ++ SET_CMC_TBL_DATA_TX_CNT_LMT(skb->data, rtwsta_link->data_tx_cnt_lmt); + } + + rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C, +@@ -3174,7 +3178,7 @@ int rtw89_fw_h2c_txtime_cmac_tbl(struct rtw89_dev *rtwdev, + } + + int rtw89_fw_h2c_txpath_cmac_tbl(struct rtw89_dev *rtwdev, +- struct rtw89_sta *rtwsta) ++ struct rtw89_sta_link *rtwsta_link) + { + const struct rtw89_chip_info *chip = rtwdev->chip; + struct sk_buff *skb; +@@ -3189,7 +3193,7 @@ int rtw89_fw_h2c_txpath_cmac_tbl(struct rtw89_dev *rtwdev, + return -ENOMEM; + } + skb_put(skb, H2C_CMC_TBL_LEN); +- SET_CTRL_INFO_MACID(skb->data, rtwsta->mac_id); ++ SET_CTRL_INFO_MACID(skb->data, rtwsta_link->mac_id); + SET_CTRL_INFO_OPERATION(skb->data, 1); + + __rtw89_fw_h2c_set_tx_path(rtwdev, skb); +@@ -3378,16 +3382,16 @@ EXPORT_SYMBOL(rtw89_fw_h2c_update_beacon_be); + #define H2C_ROLE_MAINTAIN_LEN 4 + int rtw89_fw_h2c_role_maintain(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, +- struct rtw89_sta *rtwsta, ++ struct rtw89_sta_link *rtwsta_link, + enum rtw89_upd_mode upd_mode) + { + struct sk_buff *skb; +- u8 mac_id = rtwsta ? rtwsta->mac_id : rtwvif_link->mac_id; ++ u8 mac_id = rtwsta_link ? rtwsta_link->mac_id : rtwvif_link->mac_id; + u8 self_role; + int ret; + + if (rtwvif_link->net_type == RTW89_NET_TYPE_AP_MODE) { +- if (rtwsta) ++ if (rtwsta_link) + self_role = RTW89_SELF_ROLE_AP_CLIENT; + else + self_role = rtwvif_link->self_role; +@@ -3426,9 +3430,9 @@ int rtw89_fw_h2c_role_maintain(struct rtw89_dev *rtwdev, + + static enum rtw89_fw_sta_type + rtw89_fw_get_sta_type(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, +- struct rtw89_sta *rtwsta) ++ struct rtw89_sta_link *rtwsta_link) + { +- struct ieee80211_sta *sta = rtwsta_to_sta_safe(rtwsta); ++ struct ieee80211_sta *sta = rtwsta_to_sta_safe(rtwsta_link); + struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif_link); + + if (!sta) +@@ -3451,10 +3455,10 @@ rtw89_fw_get_sta_type(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_li + } + + int rtw89_fw_h2c_join_info(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, +- struct rtw89_sta *rtwsta, bool dis_conn) ++ struct rtw89_sta_link *rtwsta_link, bool dis_conn) + { + struct sk_buff *skb; +- u8 mac_id = rtwsta ? rtwsta->mac_id : rtwvif_link->mac_id; ++ u8 mac_id = rtwsta_link ? rtwsta_link->mac_id : rtwvif_link->mac_id; + u8 self_role = rtwvif_link->self_role; + enum rtw89_fw_sta_type sta_type; + u8 net_type = rtwvif_link->net_type; +@@ -3469,7 +3473,7 @@ int rtw89_fw_h2c_join_info(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwv + format_v1 = true; + } + +- if (net_type == RTW89_NET_TYPE_AP_MODE && rtwsta) { ++ if (net_type == RTW89_NET_TYPE_AP_MODE && rtwsta_link) { + self_role = RTW89_SELF_ROLE_AP_CLIENT; + net_type = dis_conn ? RTW89_NET_TYPE_NO_LINK : net_type; + } +@@ -3502,7 +3506,7 @@ int rtw89_fw_h2c_join_info(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwv + + h2c_v1 = (struct rtw89_h2c_join_v1 *)skb->data; + +- sta_type = rtw89_fw_get_sta_type(rtwdev, rtwvif_link, rtwsta); ++ sta_type = rtw89_fw_get_sta_type(rtwdev, rtwvif_link, rtwsta_link); + + h2c_v1->w1 = le32_encode_bits(sta_type, RTW89_H2C_JOININFO_W1_STA_TYPE); + h2c_v1->w2 = 0; +diff --git a/drivers/net/wireless/realtek/rtw89/fw.h b/drivers/net/wireless/realtek/rtw89/fw.h +index 4e2f7a478d75d..00e52a33516b6 100644 +--- a/drivers/net/wireless/realtek/rtw89/fw.h ++++ b/drivers/net/wireless/realtek/rtw89/fw.h +@@ -4405,13 +4405,13 @@ void rtw89_h2c_pkt_set_hdr(struct rtw89_dev *rtwdev, struct sk_buff *skb, + bool rack, bool dack, u32 len); + int rtw89_fw_h2c_default_cmac_tbl(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, +- struct rtw89_sta *rtwsta); ++ struct rtw89_sta_link *rtwsta_link); + int rtw89_fw_h2c_default_cmac_tbl_g7(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, +- struct rtw89_sta *rtwsta); ++ struct rtw89_sta_link *rtwsta_link); + int rtw89_fw_h2c_default_dmac_tbl_v2(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, +- struct rtw89_sta *rtwsta); ++ struct rtw89_sta_link *rtwsta_link); + int rtw89_fw_h2c_assoc_cmac_tbl(struct rtw89_dev *rtwdev, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta); +@@ -4422,29 +4422,29 @@ int rtw89_fw_h2c_ampdu_cmac_tbl_g7(struct rtw89_dev *rtwdev, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta); + int rtw89_fw_h2c_txtime_cmac_tbl(struct rtw89_dev *rtwdev, +- struct rtw89_sta *rtwsta); ++ struct rtw89_sta_link *rtwsta_link); + int rtw89_fw_h2c_txpath_cmac_tbl(struct rtw89_dev *rtwdev, +- struct rtw89_sta *rtwsta); ++ struct rtw89_sta_link *rtwsta_link); + int rtw89_fw_h2c_update_beacon(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link); + int rtw89_fw_h2c_update_beacon_be(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link); + int rtw89_fw_h2c_cam(struct rtw89_dev *rtwdev, struct rtw89_vif_link *vif, +- struct rtw89_sta *rtwsta, const u8 *scan_mac_addr); ++ struct rtw89_sta_link *rtwsta_link, const u8 *scan_mac_addr); + int rtw89_fw_h2c_dctl_sec_cam_v1(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, +- struct rtw89_sta *rtwsta); ++ struct rtw89_sta_link *rtwsta_link); + int rtw89_fw_h2c_dctl_sec_cam_v2(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, +- struct rtw89_sta *rtwsta); ++ struct rtw89_sta_link *rtwsta_link); + void rtw89_fw_c2h_irqsafe(struct rtw89_dev *rtwdev, struct sk_buff *c2h); + void rtw89_fw_c2h_work(struct work_struct *work); + int rtw89_fw_h2c_role_maintain(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, +- struct rtw89_sta *rtwsta, ++ struct rtw89_sta_link *rtwsta_link, + enum rtw89_upd_mode upd_mode); + int rtw89_fw_h2c_join_info(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, +- struct rtw89_sta *rtwsta, bool dis_conn); ++ struct rtw89_sta_link *rtwsta_link, bool dis_conn); + int rtw89_fw_h2c_notify_dbcc(struct rtw89_dev *rtwdev, bool en); + int rtw89_fw_h2c_macid_pause(struct rtw89_dev *rtwdev, u8 sh, u8 grp, + bool pause); +@@ -4514,9 +4514,9 @@ void rtw89_fw_release_general_pkt_list_vif(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, + bool notify_fw); + void rtw89_fw_release_general_pkt_list(struct rtw89_dev *rtwdev, bool notify_fw); +-int rtw89_fw_h2c_ba_cam(struct rtw89_dev *rtwdev, struct rtw89_sta *rtwsta, ++int rtw89_fw_h2c_ba_cam(struct rtw89_dev *rtwdev, struct rtw89_sta_link *rtwsta_link, + bool valid, struct ieee80211_ampdu_params *params); +-int rtw89_fw_h2c_ba_cam_v1(struct rtw89_dev *rtwdev, struct rtw89_sta *rtwsta, ++int rtw89_fw_h2c_ba_cam_v1(struct rtw89_dev *rtwdev, struct rtw89_sta_link *rtwsta_link, + bool valid, struct ieee80211_ampdu_params *params); + void rtw89_fw_h2c_init_dynamic_ba_cam_v0_ext(struct rtw89_dev *rtwdev); + int rtw89_fw_h2c_init_ba_cam_users(struct rtw89_dev *rtwdev, u8 users, +@@ -4624,21 +4624,21 @@ static inline void rtw89_fw_h2c_init_ba_cam(struct rtw89_dev *rtwdev) + + static inline int rtw89_chip_h2c_default_cmac_tbl(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, +- struct rtw89_sta *rtwsta) ++ struct rtw89_sta_link *rtwsta_link) + { + const struct rtw89_chip_info *chip = rtwdev->chip; + +- return chip->ops->h2c_default_cmac_tbl(rtwdev, rtwvif_link, rtwsta); ++ return chip->ops->h2c_default_cmac_tbl(rtwdev, rtwvif_link, rtwsta_link); + } + + static inline int rtw89_chip_h2c_default_dmac_tbl(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, +- struct rtw89_sta *rtwsta) ++ struct rtw89_sta_link *rtwsta_link) + { + const struct rtw89_chip_info *chip = rtwdev->chip; + + if (chip->ops->h2c_default_dmac_tbl) +- return chip->ops->h2c_default_dmac_tbl(rtwdev, rtwvif_link, rtwsta); ++ return chip->ops->h2c_default_dmac_tbl(rtwdev, rtwvif_link, rtwsta_link); + + return 0; + } +@@ -4673,12 +4673,12 @@ static inline int rtw89_chip_h2c_ampdu_cmac_tbl(struct rtw89_dev *rtwdev, + } + + static inline +-int rtw89_chip_h2c_ba_cam(struct rtw89_dev *rtwdev, struct rtw89_sta *rtwsta, ++int rtw89_chip_h2c_ba_cam(struct rtw89_dev *rtwdev, struct rtw89_sta_link *rtwsta_link, + bool valid, struct ieee80211_ampdu_params *params) + { + const struct rtw89_chip_info *chip = rtwdev->chip; + +- return chip->ops->h2c_ba_cam(rtwdev, rtwsta, valid, params); ++ return chip->ops->h2c_ba_cam(rtwdev, rtwsta_link, valid, params); + } + + /* must consider compatibility; don't insert new in the mid */ +diff --git a/drivers/net/wireless/realtek/rtw89/mac.c b/drivers/net/wireless/realtek/rtw89/mac.c +index e1956c7224364..d6cd3ed1e7fc8 100644 +--- a/drivers/net/wireless/realtek/rtw89/mac.c ++++ b/drivers/net/wireless/realtek/rtw89/mac.c +@@ -6160,18 +6160,18 @@ void _rtw89_mac_bf_monitor_track(struct rtw89_dev *rtwdev) + } + + static int +-__rtw89_mac_set_tx_time(struct rtw89_dev *rtwdev, struct rtw89_sta *rtwsta, ++__rtw89_mac_set_tx_time(struct rtw89_dev *rtwdev, struct rtw89_sta_link *rtwsta_link, + u32 tx_time) + { + #define MAC_AX_DFLT_TX_TIME 5280 +- u8 mac_idx = rtwsta->rtwvif_link->mac_idx; ++ u8 mac_idx = rtwsta_link->rtwvif_link->mac_idx; + u32 max_tx_time = tx_time == 0 ? MAC_AX_DFLT_TX_TIME : tx_time; + u32 reg; + int ret = 0; + +- if (rtwsta->cctl_tx_time) { +- rtwsta->ampdu_max_time = (max_tx_time - 512) >> 9; +- ret = rtw89_fw_h2c_txtime_cmac_tbl(rtwdev, rtwsta); ++ if (rtwsta_link->cctl_tx_time) { ++ rtwsta_link->ampdu_max_time = (max_tx_time - 512) >> 9; ++ ret = rtw89_fw_h2c_txtime_cmac_tbl(rtwdev, rtwsta_link); + } else { + ret = rtw89_mac_check_mac_en(rtwdev, mac_idx, RTW89_CMAC_SEL); + if (ret) { +@@ -6187,31 +6187,31 @@ __rtw89_mac_set_tx_time(struct rtw89_dev *rtwdev, struct rtw89_sta *rtwsta, + return ret; + } + +-int rtw89_mac_set_tx_time(struct rtw89_dev *rtwdev, struct rtw89_sta *rtwsta, ++int rtw89_mac_set_tx_time(struct rtw89_dev *rtwdev, struct rtw89_sta_link *rtwsta_link, + bool resume, u32 tx_time) + { + int ret = 0; + + if (!resume) { +- rtwsta->cctl_tx_time = true; +- ret = __rtw89_mac_set_tx_time(rtwdev, rtwsta, tx_time); ++ rtwsta_link->cctl_tx_time = true; ++ ret = __rtw89_mac_set_tx_time(rtwdev, rtwsta_link, tx_time); + } else { +- ret = __rtw89_mac_set_tx_time(rtwdev, rtwsta, tx_time); +- rtwsta->cctl_tx_time = false; ++ ret = __rtw89_mac_set_tx_time(rtwdev, rtwsta_link, tx_time); ++ rtwsta_link->cctl_tx_time = false; + } + + return ret; + } + +-int rtw89_mac_get_tx_time(struct rtw89_dev *rtwdev, struct rtw89_sta *rtwsta, ++int rtw89_mac_get_tx_time(struct rtw89_dev *rtwdev, struct rtw89_sta_link *rtwsta_link, + u32 *tx_time) + { +- u8 mac_idx = rtwsta->rtwvif_link->mac_idx; ++ u8 mac_idx = rtwsta_link->rtwvif_link->mac_idx; + u32 reg; + int ret = 0; + +- if (rtwsta->cctl_tx_time) { +- *tx_time = (rtwsta->ampdu_max_time + 1) << 9; ++ if (rtwsta_link->cctl_tx_time) { ++ *tx_time = (rtwsta_link->ampdu_max_time + 1) << 9; + } else { + ret = rtw89_mac_check_mac_en(rtwdev, mac_idx, RTW89_CMAC_SEL); + if (ret) { +@@ -6227,33 +6227,33 @@ int rtw89_mac_get_tx_time(struct rtw89_dev *rtwdev, struct rtw89_sta *rtwsta, + } + + int rtw89_mac_set_tx_retry_limit(struct rtw89_dev *rtwdev, +- struct rtw89_sta *rtwsta, ++ struct rtw89_sta_link *rtwsta_link, + bool resume, u8 tx_retry) + { + int ret = 0; + +- rtwsta->data_tx_cnt_lmt = tx_retry; ++ rtwsta_link->data_tx_cnt_lmt = tx_retry; + + if (!resume) { +- rtwsta->cctl_tx_retry_limit = true; +- ret = rtw89_fw_h2c_txtime_cmac_tbl(rtwdev, rtwsta); ++ rtwsta_link->cctl_tx_retry_limit = true; ++ ret = rtw89_fw_h2c_txtime_cmac_tbl(rtwdev, rtwsta_link); + } else { +- ret = rtw89_fw_h2c_txtime_cmac_tbl(rtwdev, rtwsta); +- rtwsta->cctl_tx_retry_limit = false; ++ ret = rtw89_fw_h2c_txtime_cmac_tbl(rtwdev, rtwsta_link); ++ rtwsta_link->cctl_tx_retry_limit = false; + } + + return ret; + } + + int rtw89_mac_get_tx_retry_limit(struct rtw89_dev *rtwdev, +- struct rtw89_sta *rtwsta, u8 *tx_retry) ++ struct rtw89_sta_link *rtwsta_link, u8 *tx_retry) + { +- u8 mac_idx = rtwsta->rtwvif_link->mac_idx; ++ u8 mac_idx = rtwsta_link->rtwvif_link->mac_idx; + u32 reg; + int ret = 0; + +- if (rtwsta->cctl_tx_retry_limit) { +- *tx_retry = rtwsta->data_tx_cnt_lmt; ++ if (rtwsta_link->cctl_tx_retry_limit) { ++ *tx_retry = rtwsta_link->data_tx_cnt_lmt; + } else { + ret = rtw89_mac_check_mac_en(rtwdev, mac_idx, RTW89_CMAC_SEL); + if (ret) { +@@ -6340,7 +6340,7 @@ int rtw89_mac_read_xtal_si_ax(struct rtw89_dev *rtwdev, u8 offset, u8 *val) + } + + static +-void rtw89_mac_pkt_drop_sta(struct rtw89_dev *rtwdev, struct rtw89_sta *rtwsta) ++void rtw89_mac_pkt_drop_sta(struct rtw89_dev *rtwdev, struct rtw89_sta_link *rtwsta_link) + { + static const enum rtw89_pkt_drop_sel sels[] = { + RTW89_PKT_DROP_SEL_MACID_BE_ONCE, +@@ -6348,12 +6348,12 @@ void rtw89_mac_pkt_drop_sta(struct rtw89_dev *rtwdev, struct rtw89_sta *rtwsta) + RTW89_PKT_DROP_SEL_MACID_VI_ONCE, + RTW89_PKT_DROP_SEL_MACID_VO_ONCE, + }; +- struct rtw89_vif_link *rtwvif_link = rtwsta->rtwvif_link; ++ struct rtw89_vif_link *rtwvif_link = rtwsta_link->rtwvif_link; + struct rtw89_pkt_drop_params params = {0}; + int i; + + params.mac_band = RTW89_MAC_0; +- params.macid = rtwsta->mac_id; ++ params.macid = rtwsta_link->mac_id; + params.port = rtwvif_link->port; + params.mbssid = 0; + params.tf_trs = rtwvif_link->trigger; +@@ -6366,15 +6366,15 @@ void rtw89_mac_pkt_drop_sta(struct rtw89_dev *rtwdev, struct rtw89_sta *rtwsta) + + static void rtw89_mac_pkt_drop_vif_iter(void *data, struct ieee80211_sta *sta) + { +- struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv; +- struct rtw89_vif_link *rtwvif_link = rtwsta->rtwvif_link; ++ struct rtw89_sta_link *rtwsta_link = (struct rtw89_sta_link *)sta->drv_priv; ++ struct rtw89_vif_link *rtwvif_link = rtwsta_link->rtwvif_link; + struct rtw89_dev *rtwdev = rtwvif_link->rtwdev; + struct rtw89_vif_link *target = data; + + if (rtwvif_link != target) + return; + +- rtw89_mac_pkt_drop_sta(rtwdev, rtwsta); ++ rtw89_mac_pkt_drop_sta(rtwdev, rtwsta_link); + } + + void rtw89_mac_pkt_drop_vif(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link) +diff --git a/drivers/net/wireless/realtek/rtw89/mac.h b/drivers/net/wireless/realtek/rtw89/mac.h +index 6839028991d4a..3ea2dcbfa5b8c 100644 +--- a/drivers/net/wireless/realtek/rtw89/mac.h ++++ b/drivers/net/wireless/realtek/rtw89/mac.h +@@ -1384,15 +1384,15 @@ static inline bool rtw89_mac_get_power_state(struct rtw89_dev *rtwdev) + return !!val; + } + +-int rtw89_mac_set_tx_time(struct rtw89_dev *rtwdev, struct rtw89_sta *rtwsta, ++int rtw89_mac_set_tx_time(struct rtw89_dev *rtwdev, struct rtw89_sta_link *rtwsta_link, + bool resume, u32 tx_time); +-int rtw89_mac_get_tx_time(struct rtw89_dev *rtwdev, struct rtw89_sta *rtwsta, ++int rtw89_mac_get_tx_time(struct rtw89_dev *rtwdev, struct rtw89_sta_link *rtwsta_link, + u32 *tx_time); + int rtw89_mac_set_tx_retry_limit(struct rtw89_dev *rtwdev, +- struct rtw89_sta *rtwsta, ++ struct rtw89_sta_link *rtwsta_link, + bool resume, u8 tx_retry); + int rtw89_mac_get_tx_retry_limit(struct rtw89_dev *rtwdev, +- struct rtw89_sta *rtwsta, u8 *tx_retry); ++ struct rtw89_sta_link *rtwsta_link, u8 *tx_retry); + + enum rtw89_mac_xtal_si_offset { + XTAL0 = 0x0, +diff --git a/drivers/net/wireless/realtek/rtw89/mac80211.c b/drivers/net/wireless/realtek/rtw89/mac80211.c +index bc0ff64c1c982..392a38fcf4618 100644 +--- a/drivers/net/wireless/realtek/rtw89/mac80211.c ++++ b/drivers/net/wireless/realtek/rtw89/mac80211.c +@@ -29,10 +29,11 @@ static void rtw89_ops_tx(struct ieee80211_hw *hw, + int ret, qsel; + + if (rtwvif_link->offchan && !(flags & IEEE80211_TX_CTL_TX_OFFCHAN) && sta) { +- struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv; ++ struct rtw89_sta_link *rtwsta_link = ++ (struct rtw89_sta_link *)sta->drv_priv; + + rtw89_debug(rtwdev, RTW89_DBG_TXRX, "ops_tx during offchan\n"); +- skb_queue_tail(&rtwsta->roc_queue, skb); ++ skb_queue_tail(&rtwsta_link->roc_queue, skb); + return; + } + +@@ -548,8 +549,8 @@ static int rtw89_ops_set_tim(struct ieee80211_hw *hw, struct ieee80211_sta *sta, + bool set) + { + struct rtw89_dev *rtwdev = hw->priv; +- struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv; +- struct rtw89_vif_link *rtwvif_link = rtwsta->rtwvif_link; ++ struct rtw89_sta_link *rtwsta_link = (struct rtw89_sta_link *)sta->drv_priv; ++ struct rtw89_vif_link *rtwvif_link = rtwsta_link->rtwvif_link; + + ieee80211_queue_work(rtwdev->hw, &rtwvif_link->update_beacon_work); + +@@ -668,7 +669,7 @@ static int rtw89_ops_ampdu_action(struct ieee80211_hw *hw, + { + struct rtw89_dev *rtwdev = hw->priv; + struct ieee80211_sta *sta = params->sta; +- struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv; ++ struct rtw89_sta_link *rtwsta_link = (struct rtw89_sta_link *)sta->drv_priv; + u16 tid = params->tid; + struct ieee80211_txq *txq = sta->txq[tid]; + struct rtw89_txq *rtwtxq = (struct rtw89_txq *)txq->drv_priv; +@@ -681,7 +682,7 @@ static int rtw89_ops_ampdu_action(struct ieee80211_hw *hw, + case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT: + mutex_lock(&rtwdev->mutex); + clear_bit(RTW89_TXQ_F_AMPDU, &rtwtxq->flags); +- clear_bit(tid, rtwsta->ampdu_map); ++ clear_bit(tid, rtwsta_link->ampdu_map); + rtw89_chip_h2c_ampdu_cmac_tbl(rtwdev, vif, sta); + mutex_unlock(&rtwdev->mutex); + ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid); +@@ -689,21 +690,21 @@ static int rtw89_ops_ampdu_action(struct ieee80211_hw *hw, + case IEEE80211_AMPDU_TX_OPERATIONAL: + mutex_lock(&rtwdev->mutex); + set_bit(RTW89_TXQ_F_AMPDU, &rtwtxq->flags); +- rtwsta->ampdu_params[tid].agg_num = params->buf_size; +- rtwsta->ampdu_params[tid].amsdu = params->amsdu; +- set_bit(tid, rtwsta->ampdu_map); ++ rtwsta_link->ampdu_params[tid].agg_num = params->buf_size; ++ rtwsta_link->ampdu_params[tid].amsdu = params->amsdu; ++ set_bit(tid, rtwsta_link->ampdu_map); + rtw89_leave_ps_mode(rtwdev); + rtw89_chip_h2c_ampdu_cmac_tbl(rtwdev, vif, sta); + mutex_unlock(&rtwdev->mutex); + break; + case IEEE80211_AMPDU_RX_START: + mutex_lock(&rtwdev->mutex); +- rtw89_chip_h2c_ba_cam(rtwdev, rtwsta, true, params); ++ rtw89_chip_h2c_ba_cam(rtwdev, rtwsta_link, true, params); + mutex_unlock(&rtwdev->mutex); + break; + case IEEE80211_AMPDU_RX_STOP: + mutex_lock(&rtwdev->mutex); +- rtw89_chip_h2c_ba_cam(rtwdev, rtwsta, false, params); ++ rtw89_chip_h2c_ba_cam(rtwdev, rtwsta_link, false, params); + mutex_unlock(&rtwdev->mutex); + break; + default: +@@ -732,9 +733,9 @@ static void rtw89_ops_sta_statistics(struct ieee80211_hw *hw, + struct ieee80211_sta *sta, + struct station_info *sinfo) + { +- struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv; ++ struct rtw89_sta_link *rtwsta_link = (struct rtw89_sta_link *)sta->drv_priv; + +- sinfo->txrate = rtwsta->ra_report.txrate; ++ sinfo->txrate = rtwsta_link->ra_report.txrate; + sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BITRATE); + } + +@@ -778,14 +779,14 @@ struct rtw89_iter_bitrate_mask_data { + static void rtw89_ra_mask_info_update_iter(void *data, struct ieee80211_sta *sta) + { + struct rtw89_iter_bitrate_mask_data *br_data = data; +- struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv; +- struct ieee80211_vif *vif = rtwvif_to_vif(rtwsta->rtwvif_link); ++ struct rtw89_sta_link *rtwsta_link = (struct rtw89_sta_link *)sta->drv_priv; ++ struct ieee80211_vif *vif = rtwvif_to_vif(rtwsta_link->rtwvif_link); + + if (vif != br_data->vif || vif->p2p) + return; + +- rtwsta->use_cfg_mask = true; +- rtwsta->mask = *br_data->mask; ++ rtwsta_link->use_cfg_mask = true; ++ rtwsta_link->mask = *br_data->mask; + rtw89_phy_ra_update_sta(br_data->rtwdev, sta, IEEE80211_RC_SUPP_RATES_CHANGED); + } + +@@ -1054,8 +1055,8 @@ static int rtw89_ops_cancel_remain_on_channel(struct ieee80211_hw *hw, + static void rtw89_set_tid_config_iter(void *data, struct ieee80211_sta *sta) + { + struct cfg80211_tid_config *tid_config = data; +- struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv; +- struct rtw89_dev *rtwdev = rtwsta->rtwvif_link->rtwdev; ++ struct rtw89_sta_link *rtwsta_link = (struct rtw89_sta_link *)sta->drv_priv; ++ struct rtw89_dev *rtwdev = rtwsta_link->rtwvif_link->rtwdev; + + rtw89_core_set_tid_config(rtwdev, sta, tid_config); + } +diff --git a/drivers/net/wireless/realtek/rtw89/phy.c b/drivers/net/wireless/realtek/rtw89/phy.c +index 742720f1a429e..e632e74601cbe 100644 +--- a/drivers/net/wireless/realtek/rtw89/phy.c ++++ b/drivers/net/wireless/realtek/rtw89/phy.c +@@ -195,15 +195,16 @@ static u64 rtw89_phy_ra_mask_recover(u64 ra_mask, u64 ra_mask_bak) + return ra_mask; + } + +-static u64 rtw89_phy_ra_mask_cfg(struct rtw89_dev *rtwdev, struct rtw89_sta *rtwsta, ++static u64 rtw89_phy_ra_mask_cfg(struct rtw89_dev *rtwdev, ++ struct rtw89_sta_link *rtwsta_link, + const struct rtw89_chan *chan) + { +- struct ieee80211_sta *sta = rtwsta_to_sta(rtwsta); +- struct cfg80211_bitrate_mask *mask = &rtwsta->mask; ++ struct ieee80211_sta *sta = rtwsta_to_sta(rtwsta_link); ++ struct cfg80211_bitrate_mask *mask = &rtwsta_link->mask; + enum nl80211_band band; + u64 cfg_mask; + +- if (!rtwsta->use_cfg_mask) ++ if (!rtwsta_link->use_cfg_mask) + return -1; + + switch (chan->band_type) { +@@ -261,17 +262,17 @@ rtw89_ra_mask_eht_rates[4] = {RA_MASK_EHT_1SS_RATES, RA_MASK_EHT_2SS_RATES, + RA_MASK_EHT_3SS_RATES, RA_MASK_EHT_4SS_RATES}; + + static void rtw89_phy_ra_gi_ltf(struct rtw89_dev *rtwdev, +- struct rtw89_sta *rtwsta, ++ struct rtw89_sta_link *rtwsta_link, + const struct rtw89_chan *chan, + bool *fix_giltf_en, u8 *fix_giltf) + { +- struct cfg80211_bitrate_mask *mask = &rtwsta->mask; ++ struct cfg80211_bitrate_mask *mask = &rtwsta_link->mask; + u8 band = chan->band_type; + enum nl80211_band nl_band = rtw89_hw_to_nl80211_band(band); + u8 he_gi = mask->control[nl_band].he_gi; + u8 he_ltf = mask->control[nl_band].he_ltf; + +- if (!rtwsta->use_cfg_mask) ++ if (!rtwsta_link->use_cfg_mask) + return; + + if (he_ltf == 2 && he_gi == 2) { +@@ -297,15 +298,15 @@ static void rtw89_phy_ra_gi_ltf(struct rtw89_dev *rtwdev, + static void rtw89_phy_ra_sta_update(struct rtw89_dev *rtwdev, + struct ieee80211_sta *sta, bool csi) + { +- struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv; +- struct rtw89_vif_link *rtwvif_link = rtwsta->rtwvif_link; ++ struct rtw89_sta_link *rtwsta_link = (struct rtw89_sta_link *)sta->drv_priv; ++ struct rtw89_vif_link *rtwvif_link = rtwsta_link->rtwvif_link; + struct rtw89_phy_rate_pattern *rate_pattern = &rtwvif_link->rate_pattern; +- struct rtw89_ra_info *ra = &rtwsta->ra; ++ struct rtw89_ra_info *ra = &rtwsta_link->ra; + const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, + rtwvif_link->chanctx_idx); +- struct ieee80211_vif *vif = rtwvif_to_vif(rtwsta->rtwvif_link); ++ struct ieee80211_vif *vif = rtwvif_to_vif(rtwsta_link->rtwvif_link); + const u64 *high_rate_masks = rtw89_ra_mask_ht_rates; +- u8 rssi = ewma_rssi_read(&rtwsta->avg_rssi); ++ u8 rssi = ewma_rssi_read(&rtwsta_link->avg_rssi); + u64 ra_mask = 0; + u64 ra_mask_bak; + u8 mode = 0; +@@ -335,7 +336,7 @@ static void rtw89_phy_ra_sta_update(struct rtw89_dev *rtwdev, + if (sta->deflink.he_cap.he_cap_elem.phy_cap_info[1] & + IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD) + ldpc_en = 1; +- rtw89_phy_ra_gi_ltf(rtwdev, rtwsta, chan, &fix_giltf_en, &fix_giltf); ++ rtw89_phy_ra_gi_ltf(rtwdev, rtwsta_link, chan, &fix_giltf_en, &fix_giltf); + } else if (sta->deflink.vht_cap.vht_supported) { + u16 mcs_map = le16_to_cpu(sta->deflink.vht_cap.vht_mcs.rx_mcs_map); + +@@ -405,7 +406,7 @@ static void rtw89_phy_ra_sta_update(struct rtw89_dev *rtwdev, + ra_mask &= rtw89_phy_ra_mask_rssi(rtwdev, rssi, 0); + + ra_mask = rtw89_phy_ra_mask_recover(ra_mask, ra_mask_bak); +- ra_mask &= rtw89_phy_ra_mask_cfg(rtwdev, rtwsta, chan); ++ ra_mask &= rtw89_phy_ra_mask_cfg(rtwdev, rtwsta_link, chan); + + switch (sta->deflink.bandwidth) { + case IEEE80211_STA_RX_BW_160: +@@ -435,15 +436,15 @@ static void rtw89_phy_ra_sta_update(struct rtw89_dev *rtwdev, + ra->dcm_cap = 1; + + if (rate_pattern->enable && !vif->p2p) { +- ra_mask = rtw89_phy_ra_mask_cfg(rtwdev, rtwsta, chan); ++ ra_mask = rtw89_phy_ra_mask_cfg(rtwdev, rtwsta_link, chan); + ra_mask &= rate_pattern->ra_mask; + mode = rate_pattern->ra_mode; + } + + ra->bw_cap = bw_mode; +- ra->er_cap = rtwsta->er_cap; ++ ra->er_cap = rtwsta_link->er_cap; + ra->mode_ctrl = mode; +- ra->macid = rtwsta->mac_id; ++ ra->macid = rtwsta_link->mac_id; + ra->stbc_cap = stbc_en; + ra->ldpc_cap = ldpc_en; + ra->ss_num = min(sta->deflink.rx_nss, rtwdev->hal.tx_nss) - 1; +@@ -468,8 +469,8 @@ static void rtw89_phy_ra_sta_update(struct rtw89_dev *rtwdev, + void rtw89_phy_ra_update_sta(struct rtw89_dev *rtwdev, struct ieee80211_sta *sta, + u32 changed) + { +- struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv; +- struct rtw89_ra_info *ra = &rtwsta->ra; ++ struct rtw89_sta_link *rtwsta_link = (struct rtw89_sta_link *)sta->drv_priv; ++ struct rtw89_ra_info *ra = &rtwsta_link->ra; + + rtw89_phy_ra_sta_update(rtwdev, sta, false); + +@@ -629,9 +630,9 @@ void rtw89_phy_ra_update(struct rtw89_dev *rtwdev) + + void rtw89_phy_ra_assoc(struct rtw89_dev *rtwdev, struct ieee80211_sta *sta) + { +- struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv; +- struct rtw89_ra_info *ra = &rtwsta->ra; +- u8 rssi = ewma_rssi_read(&rtwsta->avg_rssi) >> RSSI_FACTOR; ++ struct rtw89_sta_link *rtwsta_link = (struct rtw89_sta_link *)sta->drv_priv; ++ struct rtw89_ra_info *ra = &rtwsta_link->ra; ++ u8 rssi = ewma_rssi_read(&rtwsta_link->avg_rssi) >> RSSI_FACTOR; + bool csi = rtw89_sta_has_beamformer_cap(sta); + + rtw89_phy_ra_sta_update(rtwdev, sta, csi); +@@ -2557,10 +2558,10 @@ static void rtw89_phy_c2h_ra_rpt_iter(void *data, struct ieee80211_sta *sta) + { + struct rtw89_phy_iter_ra_data *ra_data = (struct rtw89_phy_iter_ra_data *)data; + struct rtw89_dev *rtwdev = ra_data->rtwdev; +- struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv; ++ struct rtw89_sta_link *rtwsta_link = (struct rtw89_sta_link *)sta->drv_priv; + const struct rtw89_c2h_ra_rpt *c2h = + (const struct rtw89_c2h_ra_rpt *)ra_data->c2h->data; +- struct rtw89_ra_report *ra_report = &rtwsta->ra_report; ++ struct rtw89_ra_report *ra_report = &rtwsta_link->ra_report; + const struct rtw89_chip_info *chip = rtwdev->chip; + bool format_v1 = chip->chip_gen == RTW89_CHIP_BE; + u8 mode, rate, bw, giltf, mac_id; +@@ -2570,7 +2571,7 @@ static void rtw89_phy_c2h_ra_rpt_iter(void *data, struct ieee80211_sta *sta) + u8 t; + + mac_id = le32_get_bits(c2h->w2, RTW89_C2H_RA_RPT_W2_MACID); +- if (mac_id != rtwsta->mac_id) ++ if (mac_id != rtwsta_link->mac_id) + return; + + rate = le32_get_bits(c2h->w3, RTW89_C2H_RA_RPT_W3_MCSNSS); +@@ -2662,7 +2663,7 @@ static void rtw89_phy_c2h_ra_rpt_iter(void *data, struct ieee80211_sta *sta) + u16_encode_bits(rate, RTW89_HW_RATE_MASK_VAL); + ra_report->might_fallback_legacy = mcs <= 2; + sta->deflink.agg.max_rc_amsdu_len = get_max_amsdu_len(rtwdev, ra_report); +- rtwsta->max_agg_wait = sta->deflink.agg.max_rc_amsdu_len / 1500 - 1; ++ rtwsta_link->max_agg_wait = sta->deflink.agg.max_rc_amsdu_len / 1500 - 1; + } + + static void +@@ -4629,23 +4630,24 @@ struct rtw89_phy_iter_rssi_data { + static void rtw89_phy_stat_rssi_update_iter(void *data, + struct ieee80211_sta *sta) + { +- struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv; ++ struct rtw89_sta_link *rtwsta_link = (struct rtw89_sta_link *)sta->drv_priv; + struct rtw89_phy_iter_rssi_data *rssi_data = + (struct rtw89_phy_iter_rssi_data *)data; + struct rtw89_phy_ch_info *ch_info = rssi_data->ch_info; + unsigned long rssi_curr; + +- rssi_curr = ewma_rssi_read(&rtwsta->avg_rssi); ++ rssi_curr = ewma_rssi_read(&rtwsta_link->avg_rssi); + + if (rssi_curr < ch_info->rssi_min) { + ch_info->rssi_min = rssi_curr; +- ch_info->rssi_min_macid = rtwsta->mac_id; ++ ch_info->rssi_min_macid = rtwsta_link->mac_id; + } + +- if (rtwsta->prev_rssi == 0) { +- rtwsta->prev_rssi = rssi_curr; +- } else if (abs((int)rtwsta->prev_rssi - (int)rssi_curr) > (3 << RSSI_FACTOR)) { +- rtwsta->prev_rssi = rssi_curr; ++ if (rtwsta_link->prev_rssi == 0) { ++ rtwsta_link->prev_rssi = rssi_curr; ++ } else if (abs((int)rtwsta_link->prev_rssi - (int)rssi_curr) > ++ (3 << RSSI_FACTOR)) { ++ rtwsta_link->prev_rssi = rssi_curr; + rssi_data->rssi_changed = true; + } + } +@@ -5755,9 +5757,9 @@ void rtw89_phy_dig(struct rtw89_dev *rtwdev) + + static void rtw89_phy_tx_path_div_sta_iter(void *data, struct ieee80211_sta *sta) + { +- struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv; +- struct rtw89_dev *rtwdev = rtwsta->rtwdev; +- struct rtw89_vif_link *rtwvif_link = rtwsta->rtwvif_link; ++ struct rtw89_sta_link *rtwsta_link = (struct rtw89_sta_link *)sta->drv_priv; ++ struct rtw89_dev *rtwdev = rtwsta_link->rtwdev; ++ struct rtw89_vif_link *rtwvif_link = rtwsta_link->rtwvif_link; + struct rtw89_hal *hal = &rtwdev->hal; + bool *done = data; + u8 rssi_a, rssi_b; +@@ -5771,8 +5773,8 @@ static void rtw89_phy_tx_path_div_sta_iter(void *data, struct ieee80211_sta *sta + + *done = true; + +- rssi_a = ewma_rssi_read(&rtwsta->rssi[RF_PATH_A]); +- rssi_b = ewma_rssi_read(&rtwsta->rssi[RF_PATH_B]); ++ rssi_a = ewma_rssi_read(&rtwsta_link->rssi[RF_PATH_A]); ++ rssi_b = ewma_rssi_read(&rtwsta_link->rssi[RF_PATH_B]); + + if (rssi_a > rssi_b + RTW89_TX_DIV_RSSI_RAW_TH) + candidate = RF_A; +@@ -5785,7 +5787,7 @@ static void rtw89_phy_tx_path_div_sta_iter(void *data, struct ieee80211_sta *sta + return; + + hal->antenna_tx = candidate; +- rtw89_fw_h2c_txpath_cmac_tbl(rtwdev, rtwsta); ++ rtw89_fw_h2c_txpath_cmac_tbl(rtwdev, rtwsta_link); + + if (hal->antenna_tx == RF_A) { + rtw89_phy_write32_mask(rtwdev, R_P0_RFMODE, B_P0_RFMODE_MUX, 0x12); +diff --git a/drivers/net/wireless/realtek/rtw89/ser.c b/drivers/net/wireless/realtek/rtw89/ser.c +index 2058f4bf271d6..50b66eaf9bd04 100644 +--- a/drivers/net/wireless/realtek/rtw89/ser.c ++++ b/drivers/net/wireless/realtek/rtw89/ser.c +@@ -309,19 +309,19 @@ static void ser_reset_vif(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvi + static void ser_sta_deinit_cam_iter(void *data, struct ieee80211_sta *sta) + { + struct rtw89_vif_link *target_rtwvif = (struct rtw89_vif_link *)data; +- struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv; +- struct rtw89_vif_link *rtwvif_link = rtwsta->rtwvif_link; ++ struct rtw89_sta_link *rtwsta_link = (struct rtw89_sta_link *)sta->drv_priv; ++ struct rtw89_vif_link *rtwvif_link = rtwsta_link->rtwvif_link; + struct rtw89_dev *rtwdev = rtwvif_link->rtwdev; + + if (rtwvif_link != target_rtwvif) + return; + + if (rtwvif_link->net_type == RTW89_NET_TYPE_AP_MODE || sta->tdls) +- rtw89_cam_deinit_addr_cam(rtwdev, &rtwsta->addr_cam); ++ rtw89_cam_deinit_addr_cam(rtwdev, &rtwsta_link->addr_cam); + if (sta->tdls) +- rtw89_cam_deinit_bssid_cam(rtwdev, &rtwsta->bssid_cam); ++ rtw89_cam_deinit_bssid_cam(rtwdev, &rtwsta_link->bssid_cam); + +- INIT_LIST_HEAD(&rtwsta->ba_cam_list); ++ INIT_LIST_HEAD(&rtwsta_link->ba_cam_list); + } + + static void ser_deinit_cam(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link) +diff --git a/drivers/net/wireless/realtek/rtw89/wow.c b/drivers/net/wireless/realtek/rtw89/wow.c +index 5902eb37d618c..5046fef55222d 100644 +--- a/drivers/net/wireless/realtek/rtw89/wow.c ++++ b/drivers/net/wireless/realtek/rtw89/wow.c +@@ -1123,12 +1123,12 @@ static int rtw89_wow_cfg_wake(struct rtw89_dev *rtwdev, bool wow) + struct ieee80211_vif *wow_vif = rtw_wow->wow_vif; + struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)wow_vif->drv_priv; + struct ieee80211_sta *wow_sta; +- struct rtw89_sta *rtwsta = NULL; ++ struct rtw89_sta_link *rtwsta_link = NULL; + int ret; + + wow_sta = ieee80211_find_sta(wow_vif, rtwvif_link->bssid); + if (wow_sta) +- rtwsta = (struct rtw89_sta *)wow_sta->drv_priv; ++ rtwsta_link = (struct rtw89_sta_link *)wow_sta->drv_priv; + + if (wow) { + if (rtw_wow->pattern_cnt) +@@ -1147,7 +1147,7 @@ static int rtw89_wow_cfg_wake(struct rtw89_dev *rtwdev, bool wow) + } + + if (wow) { +- ret = rtw89_chip_h2c_dctl_sec_cam(rtwdev, rtwvif_link, rtwsta); ++ ret = rtw89_chip_h2c_dctl_sec_cam(rtwdev, rtwvif_link, rtwsta_link); + if (ret) { + rtw89_err(rtwdev, "failed to update dctl cam sec entry: %d\n", + ret); +@@ -1155,7 +1155,7 @@ static int rtw89_wow_cfg_wake(struct rtw89_dev *rtwdev, bool wow) + } + } + +- ret = rtw89_fw_h2c_cam(rtwdev, rtwvif_link, rtwsta, NULL); ++ ret = rtw89_fw_h2c_cam(rtwdev, rtwvif_link, rtwsta_link, NULL); + if (ret) { + rtw89_warn(rtwdev, "failed to send h2c cam\n"); + return ret; +@@ -1198,7 +1198,7 @@ static int rtw89_wow_swap_fw(struct rtw89_dev *rtwdev, bool wow) + bool include_bb = !!chip->bbmcu_nr; + bool disable_intr_for_dlfw = false; + struct ieee80211_sta *wow_sta; +- struct rtw89_sta *rtwsta = NULL; ++ struct rtw89_sta_link *rtwsta_link = NULL; + bool is_conn = true; + int ret; + +@@ -1207,7 +1207,7 @@ static int rtw89_wow_swap_fw(struct rtw89_dev *rtwdev, bool wow) + + wow_sta = ieee80211_find_sta(wow_vif, rtwvif_link->bssid); + if (wow_sta) +- rtwsta = (struct rtw89_sta *)wow_sta->drv_priv; ++ rtwsta_link = (struct rtw89_sta_link *)wow_sta->drv_priv; + else + is_conn = false; + +@@ -1225,7 +1225,7 @@ static int rtw89_wow_swap_fw(struct rtw89_dev *rtwdev, bool wow) + + rtw89_phy_init_rf_reg(rtwdev, true); + +- ret = rtw89_fw_h2c_role_maintain(rtwdev, rtwvif_link, rtwsta, ++ ret = rtw89_fw_h2c_role_maintain(rtwdev, rtwvif_link, rtwsta_link, + RTW89_ROLE_FW_RESTORE); + if (ret) { + rtw89_warn(rtwdev, "failed to send h2c role maintain\n"); +@@ -1241,20 +1241,20 @@ static int rtw89_wow_swap_fw(struct rtw89_dev *rtwdev, bool wow) + if (!is_conn) + rtw89_cam_reset_keys(rtwdev); + +- ret = rtw89_fw_h2c_join_info(rtwdev, rtwvif_link, rtwsta, !is_conn); ++ ret = rtw89_fw_h2c_join_info(rtwdev, rtwvif_link, rtwsta_link, !is_conn); + if (ret) { + rtw89_warn(rtwdev, "failed to send h2c join info\n"); + return ret; + } + +- ret = rtw89_fw_h2c_cam(rtwdev, rtwvif_link, rtwsta, NULL); ++ ret = rtw89_fw_h2c_cam(rtwdev, rtwvif_link, rtwsta_link, NULL); + if (ret) { + rtw89_warn(rtwdev, "failed to send h2c cam\n"); + return ret; + } + + if (is_conn) { +- ret = rtw89_fw_h2c_general_pkt(rtwdev, rtwvif_link, rtwsta->mac_id); ++ ret = rtw89_fw_h2c_general_pkt(rtwdev, rtwvif_link, rtwsta_link->mac_id); + if (ret) { + rtw89_warn(rtwdev, "failed to send h2c general packet\n"); + return ret; +-- +2.43.0 + diff --git a/queue-6.12/wifi-rtw89-rename-rtw89_vif-to-rtw89_vif_link-ahead-.patch b/queue-6.12/wifi-rtw89-rename-rtw89_vif-to-rtw89_vif_link-ahead-.patch new file mode 100644 index 00000000000..4384f97dc3a --- /dev/null +++ b/queue-6.12/wifi-rtw89-rename-rtw89_vif-to-rtw89_vif_link-ahead-.patch @@ -0,0 +1,6639 @@ +From 270526efe598fd8b42fef2a8ce6e9242df4cacf1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Mon, 16 Sep 2024 13:31:52 +0800 +Subject: wifi: rtw89: rename rtw89_vif to rtw89_vif_link ahead for MLO + +From: Zong-Zhe Yang <kevin_yang@realtek.com> + +[ Upstream commit 2f7dae17c48cd1d5616f11d22b3de675db7ab40d ] + +This is an intermediate version that is separated from subsequent major +MLO changes, so some functions' namings are not really determined here. +e.g. struct rtw89_vif_link *vif_to_rtwvif_safe(struct ieee80211_vif *vif) + +No logic is changed. + +Signed-off-by: Zong-Zhe Yang <kevin_yang@realtek.com> +Signed-off-by: Ping-Ke Shih <pkshih@realtek.com> +Link: https://patch.msgid.link/20240916053158.47350-2-pkshih@realtek.com +Stable-dep-of: f16c40acd319 ("wifi: rtw89: Fix TX fail with A2DP after scanning") +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/net/wireless/realtek/rtw89/cam.c | 109 +++-- + drivers/net/wireless/realtek/rtw89/cam.h | 16 +- + drivers/net/wireless/realtek/rtw89/chan.c | 162 +++---- + drivers/net/wireless/realtek/rtw89/chan.h | 4 +- + drivers/net/wireless/realtek/rtw89/coex.c | 33 +- + drivers/net/wireless/realtek/rtw89/coex.h | 3 +- + drivers/net/wireless/realtek/rtw89/core.c | 275 +++++------ + drivers/net/wireless/realtek/rtw89/core.h | 72 +-- + drivers/net/wireless/realtek/rtw89/debug.c | 17 +- + drivers/net/wireless/realtek/rtw89/fw.c | 356 +++++++------- + drivers/net/wireless/realtek/rtw89/fw.h | 78 +-- + drivers/net/wireless/realtek/rtw89/mac.c | 446 +++++++++--------- + drivers/net/wireless/realtek/rtw89/mac.h | 70 +-- + drivers/net/wireless/realtek/rtw89/mac80211.c | 207 ++++---- + drivers/net/wireless/realtek/rtw89/mac_be.c | 14 +- + drivers/net/wireless/realtek/rtw89/phy.c | 74 +-- + drivers/net/wireless/realtek/rtw89/phy.h | 2 +- + drivers/net/wireless/realtek/rtw89/ps.c | 92 ++-- + drivers/net/wireless/realtek/rtw89/ps.h | 10 +- + drivers/net/wireless/realtek/rtw89/regd.c | 46 +- + drivers/net/wireless/realtek/rtw89/rtw8851b.c | 13 +- + drivers/net/wireless/realtek/rtw89/rtw8852a.c | 12 +- + drivers/net/wireless/realtek/rtw89/rtw8852b.c | 13 +- + .../net/wireless/realtek/rtw89/rtw8852bt.c | 13 +- + drivers/net/wireless/realtek/rtw89/rtw8852c.c | 12 +- + drivers/net/wireless/realtek/rtw89/rtw8922a.c | 10 +- + drivers/net/wireless/realtek/rtw89/ser.c | 36 +- + drivers/net/wireless/realtek/rtw89/util.h | 8 +- + drivers/net/wireless/realtek/rtw89/wow.c | 125 ++--- + drivers/net/wireless/realtek/rtw89/wow.h | 8 +- + 30 files changed, 1200 insertions(+), 1136 deletions(-) + +diff --git a/drivers/net/wireless/realtek/rtw89/cam.c b/drivers/net/wireless/realtek/rtw89/cam.c +index 4476fc7e53db7..a3e6d40b30788 100644 +--- a/drivers/net/wireless/realtek/rtw89/cam.c ++++ b/drivers/net/wireless/realtek/rtw89/cam.c +@@ -218,7 +218,7 @@ static int rtw89_cam_detach_sec_cam(struct rtw89_dev *rtwdev, + bool inform_fw) + { + struct rtw89_sta *rtwsta = sta_to_rtwsta_safe(sta); +- struct rtw89_vif *rtwvif; ++ struct rtw89_vif_link *rtwvif_link; + struct rtw89_addr_cam_entry *addr_cam; + unsigned int i; + int ret = 0; +@@ -228,8 +228,8 @@ static int rtw89_cam_detach_sec_cam(struct rtw89_dev *rtwdev, + return -EINVAL; + } + +- rtwvif = (struct rtw89_vif *)vif->drv_priv; +- addr_cam = rtw89_get_addr_cam_of(rtwvif, rtwsta); ++ rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv; ++ addr_cam = rtw89_get_addr_cam_of(rtwvif_link, rtwsta); + + for_each_set_bit(i, addr_cam->sec_cam_map, RTW89_SEC_CAM_IN_ADDR_CAM) { + if (addr_cam->sec_ent[i] != sec_cam->sec_cam_idx) +@@ -239,11 +239,11 @@ static int rtw89_cam_detach_sec_cam(struct rtw89_dev *rtwdev, + } + + if (inform_fw) { +- ret = rtw89_chip_h2c_dctl_sec_cam(rtwdev, rtwvif, rtwsta); ++ ret = rtw89_chip_h2c_dctl_sec_cam(rtwdev, rtwvif_link, rtwsta); + if (ret) + rtw89_err(rtwdev, + "failed to update dctl cam del key: %d\n", ret); +- ret = rtw89_fw_h2c_cam(rtwdev, rtwvif, rtwsta, NULL); ++ ret = rtw89_fw_h2c_cam(rtwdev, rtwvif_link, rtwsta, NULL); + if (ret) + rtw89_err(rtwdev, "failed to update cam del key: %d\n", ret); + } +@@ -258,7 +258,7 @@ static int rtw89_cam_attach_sec_cam(struct rtw89_dev *rtwdev, + struct rtw89_sec_cam_entry *sec_cam) + { + struct rtw89_sta *rtwsta = sta_to_rtwsta_safe(sta); +- struct rtw89_vif *rtwvif; ++ struct rtw89_vif_link *rtwvif_link; + struct rtw89_addr_cam_entry *addr_cam; + u8 key_idx = 0; + int ret; +@@ -268,8 +268,8 @@ static int rtw89_cam_attach_sec_cam(struct rtw89_dev *rtwdev, + return -EINVAL; + } + +- rtwvif = (struct rtw89_vif *)vif->drv_priv; +- addr_cam = rtw89_get_addr_cam_of(rtwvif, rtwsta); ++ rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv; ++ addr_cam = rtw89_get_addr_cam_of(rtwvif_link, rtwsta); + + if (key->cipher == WLAN_CIPHER_SUITE_WEP40 || + key->cipher == WLAN_CIPHER_SUITE_WEP104) +@@ -285,13 +285,13 @@ static int rtw89_cam_attach_sec_cam(struct rtw89_dev *rtwdev, + addr_cam->sec_ent_keyid[key_idx] = key->keyidx; + addr_cam->sec_ent[key_idx] = sec_cam->sec_cam_idx; + set_bit(key_idx, addr_cam->sec_cam_map); +- ret = rtw89_chip_h2c_dctl_sec_cam(rtwdev, rtwvif, rtwsta); ++ ret = rtw89_chip_h2c_dctl_sec_cam(rtwdev, rtwvif_link, rtwsta); + if (ret) { + rtw89_err(rtwdev, "failed to update dctl cam sec entry: %d\n", + ret); + return ret; + } +- ret = rtw89_fw_h2c_cam(rtwdev, rtwvif, rtwsta, NULL); ++ ret = rtw89_fw_h2c_cam(rtwdev, rtwvif_link, rtwsta, NULL); + if (ret) { + rtw89_err(rtwdev, "failed to update addr cam sec entry: %d\n", + ret); +@@ -485,10 +485,10 @@ void rtw89_cam_deinit_bssid_cam(struct rtw89_dev *rtwdev, + clear_bit(bssid_cam->bssid_cam_idx, cam_info->bssid_cam_map); + } + +-void rtw89_cam_deinit(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif) ++void rtw89_cam_deinit(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link) + { +- struct rtw89_addr_cam_entry *addr_cam = &rtwvif->addr_cam; +- struct rtw89_bssid_cam_entry *bssid_cam = &rtwvif->bssid_cam; ++ struct rtw89_addr_cam_entry *addr_cam = &rtwvif_link->addr_cam; ++ struct rtw89_bssid_cam_entry *bssid_cam = &rtwvif_link->bssid_cam; + + rtw89_cam_deinit_addr_cam(rtwdev, addr_cam); + rtw89_cam_deinit_bssid_cam(rtwdev, bssid_cam); +@@ -593,7 +593,7 @@ static int rtw89_cam_get_avail_bssid_cam(struct rtw89_dev *rtwdev, + } + + int rtw89_cam_init_bssid_cam(struct rtw89_dev *rtwdev, +- struct rtw89_vif *rtwvif, ++ struct rtw89_vif_link *rtwvif_link, + struct rtw89_bssid_cam_entry *bssid_cam, + const u8 *bssid) + { +@@ -613,7 +613,7 @@ int rtw89_cam_init_bssid_cam(struct rtw89_dev *rtwdev, + } + + bssid_cam->bssid_cam_idx = bssid_cam_idx; +- bssid_cam->phy_idx = rtwvif->phy_idx; ++ bssid_cam->phy_idx = rtwvif_link->phy_idx; + bssid_cam->len = BSSID_CAM_ENT_SIZE; + bssid_cam->offset = 0; + bssid_cam->valid = true; +@@ -622,20 +622,21 @@ int rtw89_cam_init_bssid_cam(struct rtw89_dev *rtwdev, + return 0; + } + +-void rtw89_cam_bssid_changed(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif) ++void rtw89_cam_bssid_changed(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link) + { +- struct rtw89_bssid_cam_entry *bssid_cam = &rtwvif->bssid_cam; ++ struct rtw89_bssid_cam_entry *bssid_cam = &rtwvif_link->bssid_cam; + +- ether_addr_copy(bssid_cam->bssid, rtwvif->bssid); ++ ether_addr_copy(bssid_cam->bssid, rtwvif_link->bssid); + } + +-int rtw89_cam_init(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif) ++int rtw89_cam_init(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link) + { +- struct rtw89_addr_cam_entry *addr_cam = &rtwvif->addr_cam; +- struct rtw89_bssid_cam_entry *bssid_cam = &rtwvif->bssid_cam; ++ struct rtw89_addr_cam_entry *addr_cam = &rtwvif_link->addr_cam; ++ struct rtw89_bssid_cam_entry *bssid_cam = &rtwvif_link->bssid_cam; + int ret; + +- ret = rtw89_cam_init_bssid_cam(rtwdev, rtwvif, bssid_cam, rtwvif->bssid); ++ ret = rtw89_cam_init_bssid_cam(rtwdev, rtwvif_link, bssid_cam, ++ rtwvif_link->bssid); + if (ret) { + rtw89_err(rtwdev, "failed to init bssid cam\n"); + return ret; +@@ -651,11 +652,12 @@ int rtw89_cam_init(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif) + } + + int rtw89_cam_fill_bssid_cam_info(struct rtw89_dev *rtwdev, +- struct rtw89_vif *rtwvif, ++ struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta *rtwsta, u8 *cmd) + { +- struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif); +- struct rtw89_bssid_cam_entry *bssid_cam = rtw89_get_bssid_cam_of(rtwvif, rtwsta); ++ struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif_link); ++ struct rtw89_bssid_cam_entry *bssid_cam = rtw89_get_bssid_cam_of(rtwvif_link, ++ rtwsta); + u8 bss_color = vif->bss_conf.he_bss_color.color; + u8 bss_mask; + +@@ -694,19 +696,20 @@ static u8 rtw89_cam_addr_hash(u8 start, const u8 *addr) + } + + void rtw89_cam_fill_addr_cam_info(struct rtw89_dev *rtwdev, +- struct rtw89_vif *rtwvif, ++ struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta *rtwsta, + const u8 *scan_mac_addr, + u8 *cmd) + { +- struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif); +- struct rtw89_addr_cam_entry *addr_cam = rtw89_get_addr_cam_of(rtwvif, rtwsta); ++ struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif_link); ++ struct rtw89_addr_cam_entry *addr_cam = ++ rtw89_get_addr_cam_of(rtwvif_link, rtwsta); + struct ieee80211_sta *sta = rtwsta_to_sta_safe(rtwsta); +- const u8 *sma = scan_mac_addr ? scan_mac_addr : rtwvif->mac_addr; ++ const u8 *sma = scan_mac_addr ? scan_mac_addr : rtwvif_link->mac_addr; + u8 sma_hash, tma_hash, addr_msk_start; + u8 sma_start = 0; + u8 tma_start = 0; +- u8 *tma = sta ? sta->addr : rtwvif->bssid; ++ u8 *tma = sta ? sta->addr : rtwvif_link->bssid; + + if (addr_cam->addr_mask != 0) { + addr_msk_start = __ffs(addr_cam->addr_mask); +@@ -723,10 +726,10 @@ void rtw89_cam_fill_addr_cam_info(struct rtw89_dev *rtwdev, + FWCMD_SET_ADDR_LEN(cmd, addr_cam->len); + + FWCMD_SET_ADDR_VALID(cmd, addr_cam->valid); +- FWCMD_SET_ADDR_NET_TYPE(cmd, rtwvif->net_type); +- FWCMD_SET_ADDR_BCN_HIT_COND(cmd, rtwvif->bcn_hit_cond); +- FWCMD_SET_ADDR_HIT_RULE(cmd, rtwvif->hit_rule); +- FWCMD_SET_ADDR_BB_SEL(cmd, rtwvif->phy_idx); ++ FWCMD_SET_ADDR_NET_TYPE(cmd, rtwvif_link->net_type); ++ FWCMD_SET_ADDR_BCN_HIT_COND(cmd, rtwvif_link->bcn_hit_cond); ++ FWCMD_SET_ADDR_HIT_RULE(cmd, rtwvif_link->hit_rule); ++ FWCMD_SET_ADDR_BB_SEL(cmd, rtwvif_link->phy_idx); + FWCMD_SET_ADDR_ADDR_MASK(cmd, addr_cam->addr_mask); + FWCMD_SET_ADDR_MASK_SEL(cmd, addr_cam->mask_sel); + FWCMD_SET_ADDR_SMA_HASH(cmd, sma_hash); +@@ -748,20 +751,20 @@ void rtw89_cam_fill_addr_cam_info(struct rtw89_dev *rtwdev, + FWCMD_SET_ADDR_TMA4(cmd, tma[4]); + FWCMD_SET_ADDR_TMA5(cmd, tma[5]); + +- FWCMD_SET_ADDR_PORT_INT(cmd, rtwvif->port); +- FWCMD_SET_ADDR_TSF_SYNC(cmd, rtwvif->port); +- FWCMD_SET_ADDR_TF_TRS(cmd, rtwvif->trigger); +- FWCMD_SET_ADDR_LSIG_TXOP(cmd, rtwvif->lsig_txop); +- FWCMD_SET_ADDR_TGT_IND(cmd, rtwvif->tgt_ind); +- FWCMD_SET_ADDR_FRM_TGT_IND(cmd, rtwvif->frm_tgt_ind); +- FWCMD_SET_ADDR_MACID(cmd, rtwsta ? rtwsta->mac_id : rtwvif->mac_id); +- if (rtwvif->net_type == RTW89_NET_TYPE_INFRA) ++ FWCMD_SET_ADDR_PORT_INT(cmd, rtwvif_link->port); ++ FWCMD_SET_ADDR_TSF_SYNC(cmd, rtwvif_link->port); ++ FWCMD_SET_ADDR_TF_TRS(cmd, rtwvif_link->trigger); ++ FWCMD_SET_ADDR_LSIG_TXOP(cmd, rtwvif_link->lsig_txop); ++ FWCMD_SET_ADDR_TGT_IND(cmd, rtwvif_link->tgt_ind); ++ FWCMD_SET_ADDR_FRM_TGT_IND(cmd, rtwvif_link->frm_tgt_ind); ++ FWCMD_SET_ADDR_MACID(cmd, rtwsta ? rtwsta->mac_id : rtwvif_link->mac_id); ++ if (rtwvif_link->net_type == RTW89_NET_TYPE_INFRA) + FWCMD_SET_ADDR_AID12(cmd, vif->cfg.aid & 0xfff); +- else if (rtwvif->net_type == RTW89_NET_TYPE_AP_MODE) ++ else if (rtwvif_link->net_type == RTW89_NET_TYPE_AP_MODE) + FWCMD_SET_ADDR_AID12(cmd, sta ? sta->aid & 0xfff : 0); +- FWCMD_SET_ADDR_WOL_PATTERN(cmd, rtwvif->wowlan_pattern); +- FWCMD_SET_ADDR_WOL_UC(cmd, rtwvif->wowlan_uc); +- FWCMD_SET_ADDR_WOL_MAGIC(cmd, rtwvif->wowlan_magic); ++ FWCMD_SET_ADDR_WOL_PATTERN(cmd, rtwvif_link->wowlan_pattern); ++ FWCMD_SET_ADDR_WOL_UC(cmd, rtwvif_link->wowlan_uc); ++ FWCMD_SET_ADDR_WOL_MAGIC(cmd, rtwvif_link->wowlan_magic); + FWCMD_SET_ADDR_WAPI(cmd, addr_cam->wapi); + FWCMD_SET_ADDR_SEC_ENT_MODE(cmd, addr_cam->sec_ent_mode); + FWCMD_SET_ADDR_SEC_ENT0_KEYID(cmd, addr_cam->sec_ent_keyid[0]); +@@ -783,15 +786,16 @@ void rtw89_cam_fill_addr_cam_info(struct rtw89_dev *rtwdev, + } + + void rtw89_cam_fill_dctl_sec_cam_info_v1(struct rtw89_dev *rtwdev, +- struct rtw89_vif *rtwvif, ++ struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta *rtwsta, + struct rtw89_h2c_dctlinfo_ud_v1 *h2c) + { +- struct rtw89_addr_cam_entry *addr_cam = rtw89_get_addr_cam_of(rtwvif, rtwsta); ++ struct rtw89_addr_cam_entry *addr_cam = ++ rtw89_get_addr_cam_of(rtwvif_link, rtwsta); + struct rtw89_wow_param *rtw_wow = &rtwdev->wow; + u8 *ptk_tx_iv = rtw_wow->key_info.ptk_tx_iv; + +- h2c->c0 = le32_encode_bits(rtwsta ? rtwsta->mac_id : rtwvif->mac_id, ++ h2c->c0 = le32_encode_bits(rtwsta ? rtwsta->mac_id : rtwvif_link->mac_id, + DCTLINFO_V1_C0_MACID) | + le32_encode_bits(1, DCTLINFO_V1_C0_OP); + +@@ -862,15 +866,16 @@ void rtw89_cam_fill_dctl_sec_cam_info_v1(struct rtw89_dev *rtwdev, + } + + void rtw89_cam_fill_dctl_sec_cam_info_v2(struct rtw89_dev *rtwdev, +- struct rtw89_vif *rtwvif, ++ struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta *rtwsta, + struct rtw89_h2c_dctlinfo_ud_v2 *h2c) + { +- struct rtw89_addr_cam_entry *addr_cam = rtw89_get_addr_cam_of(rtwvif, rtwsta); ++ struct rtw89_addr_cam_entry *addr_cam = ++ rtw89_get_addr_cam_of(rtwvif_link, rtwsta); + struct rtw89_wow_param *rtw_wow = &rtwdev->wow; + u8 *ptk_tx_iv = rtw_wow->key_info.ptk_tx_iv; + +- h2c->c0 = le32_encode_bits(rtwsta ? rtwsta->mac_id : rtwvif->mac_id, ++ h2c->c0 = le32_encode_bits(rtwsta ? rtwsta->mac_id : rtwvif_link->mac_id, + DCTLINFO_V2_C0_MACID) | + le32_encode_bits(1, DCTLINFO_V2_C0_OP); + +diff --git a/drivers/net/wireless/realtek/rtw89/cam.h b/drivers/net/wireless/realtek/rtw89/cam.h +index 5d7b624c2dd42..18ede69144b67 100644 +--- a/drivers/net/wireless/realtek/rtw89/cam.h ++++ b/drivers/net/wireless/realtek/rtw89/cam.h +@@ -526,33 +526,33 @@ struct rtw89_h2c_dctlinfo_ud_v2 { + #define DCTLINFO_V2_W12_MLD_TA_BSSID_H_V1 GENMASK(15, 0) + #define DCTLINFO_V2_W12_ALL GENMASK(15, 0) + +-int rtw89_cam_init(struct rtw89_dev *rtwdev, struct rtw89_vif *vif); +-void rtw89_cam_deinit(struct rtw89_dev *rtwdev, struct rtw89_vif *vif); ++int rtw89_cam_init(struct rtw89_dev *rtwdev, struct rtw89_vif_link *vif); ++void rtw89_cam_deinit(struct rtw89_dev *rtwdev, struct rtw89_vif_link *vif); + int rtw89_cam_init_addr_cam(struct rtw89_dev *rtwdev, + struct rtw89_addr_cam_entry *addr_cam, + const struct rtw89_bssid_cam_entry *bssid_cam); + void rtw89_cam_deinit_addr_cam(struct rtw89_dev *rtwdev, + struct rtw89_addr_cam_entry *addr_cam); + int rtw89_cam_init_bssid_cam(struct rtw89_dev *rtwdev, +- struct rtw89_vif *rtwvif, ++ struct rtw89_vif_link *rtwvif_link, + struct rtw89_bssid_cam_entry *bssid_cam, + const u8 *bssid); + void rtw89_cam_deinit_bssid_cam(struct rtw89_dev *rtwdev, + struct rtw89_bssid_cam_entry *bssid_cam); + void rtw89_cam_fill_addr_cam_info(struct rtw89_dev *rtwdev, +- struct rtw89_vif *vif, ++ struct rtw89_vif_link *vif, + struct rtw89_sta *rtwsta, + const u8 *scan_mac_addr, u8 *cmd); + void rtw89_cam_fill_dctl_sec_cam_info_v1(struct rtw89_dev *rtwdev, +- struct rtw89_vif *rtwvif, ++ struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta *rtwsta, + struct rtw89_h2c_dctlinfo_ud_v1 *h2c); + void rtw89_cam_fill_dctl_sec_cam_info_v2(struct rtw89_dev *rtwdev, +- struct rtw89_vif *rtwvif, ++ struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta *rtwsta, + struct rtw89_h2c_dctlinfo_ud_v2 *h2c); + int rtw89_cam_fill_bssid_cam_info(struct rtw89_dev *rtwdev, +- struct rtw89_vif *rtwvif, ++ struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta *rtwsta, u8 *cmd); + int rtw89_cam_sec_key_add(struct rtw89_dev *rtwdev, + struct ieee80211_vif *vif, +@@ -564,6 +564,6 @@ int rtw89_cam_sec_key_del(struct rtw89_dev *rtwdev, + struct ieee80211_key_conf *key, + bool inform_fw); + void rtw89_cam_bssid_changed(struct rtw89_dev *rtwdev, +- struct rtw89_vif *rtwvif); ++ struct rtw89_vif_link *rtwvif_link); + void rtw89_cam_reset_keys(struct rtw89_dev *rtwdev); + #endif +diff --git a/drivers/net/wireless/realtek/rtw89/chan.c b/drivers/net/wireless/realtek/rtw89/chan.c +index 7070c85e2c288..f20431c3e2017 100644 +--- a/drivers/net/wireless/realtek/rtw89/chan.c ++++ b/drivers/net/wireless/realtek/rtw89/chan.c +@@ -239,7 +239,7 @@ static void rtw89_entity_calculate_weight(struct rtw89_dev *rtwdev, + { + struct rtw89_hal *hal = &rtwdev->hal; + const struct rtw89_chanctx_cfg *cfg; +- struct rtw89_vif *rtwvif; ++ struct rtw89_vif_link *rtwvif_link; + int idx; + + for_each_set_bit(idx, hal->entity_map, NUM_OF_RTW89_CHANCTX) { +@@ -254,8 +254,8 @@ static void rtw89_entity_calculate_weight(struct rtw89_dev *rtwdev, + w->active_chanctxs++; + } + +- rtw89_for_each_rtwvif(rtwdev, rtwvif) { +- if (rtwvif->chanctx_assigned) ++ rtw89_for_each_rtwvif(rtwdev, rtwvif_link) { ++ if (rtwvif_link->chanctx_assigned) + w->active_roles++; + } + } +@@ -387,9 +387,9 @@ int rtw89_iterate_mcc_roles(struct rtw89_dev *rtwdev, + static u32 rtw89_mcc_get_tbtt_ofst(struct rtw89_dev *rtwdev, + struct rtw89_mcc_role *role, u64 tsf) + { +- struct rtw89_vif *rtwvif = role->rtwvif; ++ struct rtw89_vif_link *rtwvif_link = role->rtwvif_link; + u32 bcn_intvl_us = ieee80211_tu_to_usec(role->beacon_interval); +- u64 sync_tsf = READ_ONCE(rtwvif->sync_bcn_tsf); ++ u64 sync_tsf = READ_ONCE(rtwvif_link->sync_bcn_tsf); + u32 remainder; + + if (tsf < sync_tsf) { +@@ -413,8 +413,8 @@ static int __mcc_fw_req_tsf(struct rtw89_dev *rtwdev, u64 *tsf_ref, u64 *tsf_aux + int ret; + + req.group = mcc->group; +- req.macid_x = ref->rtwvif->mac_id; +- req.macid_y = aux->rtwvif->mac_id; ++ req.macid_x = ref->rtwvif_link->mac_id; ++ req.macid_y = aux->rtwvif_link->mac_id; + ret = rtw89_fw_h2c_mcc_req_tsf(rtwdev, &req, &rpt); + if (ret) { + rtw89_debug(rtwdev, RTW89_DBG_CHAN, +@@ -440,10 +440,10 @@ static int __mrc_fw_req_tsf(struct rtw89_dev *rtwdev, u64 *tsf_ref, u64 *tsf_aux + BUILD_BUG_ON(RTW89_MAC_MRC_MAX_REQ_TSF_NUM < NUM_OF_RTW89_MCC_ROLES); + + arg.num = 2; +- arg.infos[0].band = ref->rtwvif->mac_idx; +- arg.infos[0].port = ref->rtwvif->port; +- arg.infos[1].band = aux->rtwvif->mac_idx; +- arg.infos[1].port = aux->rtwvif->port; ++ arg.infos[0].band = ref->rtwvif_link->mac_idx; ++ arg.infos[0].port = ref->rtwvif_link->port; ++ arg.infos[1].band = aux->rtwvif_link->mac_idx; ++ arg.infos[1].port = aux->rtwvif_link->port; + + ret = rtw89_fw_h2c_mrc_req_tsf(rtwdev, &arg, &rpt); + if (ret) { +@@ -523,11 +523,11 @@ u32 rtw89_mcc_role_fw_macid_bitmap_to_u32(struct rtw89_mcc_role *mcc_role) + static void rtw89_mcc_role_macid_sta_iter(void *data, struct ieee80211_sta *sta) + { + struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv; +- struct rtw89_vif *rtwvif = rtwsta->rtwvif; ++ struct rtw89_vif_link *rtwvif_link = rtwsta->rtwvif_link; + struct rtw89_mcc_role *mcc_role = data; +- struct rtw89_vif *target = mcc_role->rtwvif; ++ struct rtw89_vif_link *target = mcc_role->rtwvif_link; + +- if (rtwvif != target) ++ if (rtwvif_link != target) + return; + + rtw89_mcc_role_fw_macid_bitmap_set_bit(mcc_role, rtwsta->mac_id); +@@ -536,9 +536,9 @@ static void rtw89_mcc_role_macid_sta_iter(void *data, struct ieee80211_sta *sta) + static void rtw89_mcc_fill_role_macid_bitmap(struct rtw89_dev *rtwdev, + struct rtw89_mcc_role *mcc_role) + { +- struct rtw89_vif *rtwvif = mcc_role->rtwvif; ++ struct rtw89_vif_link *rtwvif_link = mcc_role->rtwvif_link; + +- rtw89_mcc_role_fw_macid_bitmap_set_bit(mcc_role, rtwvif->mac_id); ++ rtw89_mcc_role_fw_macid_bitmap_set_bit(mcc_role, rtwvif_link->mac_id); + ieee80211_iterate_stations_atomic(rtwdev->hw, + rtw89_mcc_role_macid_sta_iter, + mcc_role); +@@ -564,7 +564,7 @@ static void rtw89_mcc_fill_role_policy(struct rtw89_dev *rtwdev, + static void rtw89_mcc_fill_role_limit(struct rtw89_dev *rtwdev, + struct rtw89_mcc_role *mcc_role) + { +- struct ieee80211_vif *vif = rtwvif_to_vif(mcc_role->rtwvif); ++ struct ieee80211_vif *vif = rtwvif_to_vif(mcc_role->rtwvif_link); + struct ieee80211_p2p_noa_desc *noa_desc; + u32 bcn_intvl_us = ieee80211_tu_to_usec(mcc_role->beacon_interval); + u32 max_toa_us, max_tob_us, max_dur_us; +@@ -597,7 +597,7 @@ static void rtw89_mcc_fill_role_limit(struct rtw89_dev *rtwdev, + return; + } + +- ret = rtw89_mac_port_get_tsf(rtwdev, mcc_role->rtwvif, &tsf); ++ ret = rtw89_mac_port_get_tsf(rtwdev, mcc_role->rtwvif_link, &tsf); + if (ret) { + rtw89_warn(rtwdev, "MCC failed to get port tsf: %d\n", ret); + return; +@@ -632,14 +632,14 @@ static void rtw89_mcc_fill_role_limit(struct rtw89_dev *rtwdev, + } + + static int rtw89_mcc_fill_role(struct rtw89_dev *rtwdev, +- struct rtw89_vif *rtwvif, ++ struct rtw89_vif_link *rtwvif_link, + struct rtw89_mcc_role *role) + { +- struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif); ++ struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif_link); + const struct rtw89_chan *chan; + + memset(role, 0, sizeof(*role)); +- role->rtwvif = rtwvif; ++ role->rtwvif_link = rtwvif_link; + role->beacon_interval = vif->bss_conf.beacon_int; + + if (!role->beacon_interval) { +@@ -650,10 +650,10 @@ static int rtw89_mcc_fill_role(struct rtw89_dev *rtwdev, + + role->duration = role->beacon_interval / 2; + +- chan = rtw89_chan_get(rtwdev, rtwvif->chanctx_idx); ++ chan = rtw89_chan_get(rtwdev, rtwvif_link->chanctx_idx); + role->is_2ghz = chan->band_type == RTW89_BAND_2G; +- role->is_go = rtwvif->wifi_role == RTW89_WIFI_ROLE_P2P_GO; +- role->is_gc = rtwvif->wifi_role == RTW89_WIFI_ROLE_P2P_CLIENT; ++ role->is_go = rtwvif_link->wifi_role == RTW89_WIFI_ROLE_P2P_GO; ++ role->is_gc = rtwvif_link->wifi_role == RTW89_WIFI_ROLE_P2P_CLIENT; + + rtw89_mcc_fill_role_macid_bitmap(rtwdev, role); + rtw89_mcc_fill_role_policy(rtwdev, role); +@@ -678,7 +678,7 @@ static void rtw89_mcc_fill_bt_role(struct rtw89_dev *rtwdev) + } + + struct rtw89_mcc_fill_role_selector { +- struct rtw89_vif *bind_vif[NUM_OF_RTW89_CHANCTX]; ++ struct rtw89_vif_link *bind_vif[NUM_OF_RTW89_CHANCTX]; + }; + + static_assert((u8)NUM_OF_RTW89_CHANCTX >= NUM_OF_RTW89_MCC_ROLES); +@@ -689,7 +689,7 @@ static int rtw89_mcc_fill_role_iterator(struct rtw89_dev *rtwdev, + void *data) + { + struct rtw89_mcc_fill_role_selector *sel = data; +- struct rtw89_vif *role_vif = sel->bind_vif[ordered_idx]; ++ struct rtw89_vif_link *role_vif = sel->bind_vif[ordered_idx]; + int ret; + + if (!role_vif) { +@@ -712,21 +712,21 @@ static int rtw89_mcc_fill_role_iterator(struct rtw89_dev *rtwdev, + static int rtw89_mcc_fill_all_roles(struct rtw89_dev *rtwdev) + { + struct rtw89_mcc_fill_role_selector sel = {}; +- struct rtw89_vif *rtwvif; ++ struct rtw89_vif_link *rtwvif_link; + int ret; + +- rtw89_for_each_rtwvif(rtwdev, rtwvif) { +- if (!rtwvif->chanctx_assigned) ++ rtw89_for_each_rtwvif(rtwdev, rtwvif_link) { ++ if (!rtwvif_link->chanctx_assigned) + continue; + +- if (sel.bind_vif[rtwvif->chanctx_idx]) { ++ if (sel.bind_vif[rtwvif_link->chanctx_idx]) { + rtw89_warn(rtwdev, + "MCC skip extra vif <macid %d> on chanctx[%d]\n", +- rtwvif->mac_id, rtwvif->chanctx_idx); ++ rtwvif_link->mac_id, rtwvif_link->chanctx_idx); + continue; + } + +- sel.bind_vif[rtwvif->chanctx_idx] = rtwvif; ++ sel.bind_vif[rtwvif_link->chanctx_idx] = rtwvif_link; + } + + ret = rtw89_iterate_mcc_roles(rtwdev, rtw89_mcc_fill_role_iterator, &sel); +@@ -754,13 +754,13 @@ static void rtw89_mcc_assign_pattern(struct rtw89_dev *rtwdev, + memset(&pattern->courtesy, 0, sizeof(pattern->courtesy)); + + if (pattern->tob_aux <= 0 || pattern->toa_aux <= 0) { +- pattern->courtesy.macid_tgt = aux->rtwvif->mac_id; +- pattern->courtesy.macid_src = ref->rtwvif->mac_id; ++ pattern->courtesy.macid_tgt = aux->rtwvif_link->mac_id; ++ pattern->courtesy.macid_src = ref->rtwvif_link->mac_id; + pattern->courtesy.slot_num = RTW89_MCC_DFLT_COURTESY_SLOT; + pattern->courtesy.enable = true; + } else if (pattern->tob_ref <= 0 || pattern->toa_ref <= 0) { +- pattern->courtesy.macid_tgt = ref->rtwvif->mac_id; +- pattern->courtesy.macid_src = aux->rtwvif->mac_id; ++ pattern->courtesy.macid_tgt = ref->rtwvif_link->mac_id; ++ pattern->courtesy.macid_src = aux->rtwvif_link->mac_id; + pattern->courtesy.slot_num = RTW89_MCC_DFLT_COURTESY_SLOT; + pattern->courtesy.enable = true; + } +@@ -1263,7 +1263,7 @@ static void rtw89_mcc_sync_tbtt(struct rtw89_dev *rtwdev, + u64 tsf_src; + int ret; + +- ret = rtw89_mac_port_get_tsf(rtwdev, src->rtwvif, &tsf_src); ++ ret = rtw89_mac_port_get_tsf(rtwdev, src->rtwvif_link, &tsf_src); + if (ret) { + rtw89_warn(rtwdev, "MCC failed to get port tsf: %d\n", ret); + return; +@@ -1280,12 +1280,12 @@ static void rtw89_mcc_sync_tbtt(struct rtw89_dev *rtwdev, + div_u64_rem(tbtt_tgt, bcn_intvl_src_us, &remainder); + tsf_ofst_tgt = bcn_intvl_src_us - remainder; + +- config->sync.macid_tgt = tgt->rtwvif->mac_id; +- config->sync.band_tgt = tgt->rtwvif->mac_idx; +- config->sync.port_tgt = tgt->rtwvif->port; +- config->sync.macid_src = src->rtwvif->mac_id; +- config->sync.band_src = src->rtwvif->mac_idx; +- config->sync.port_src = src->rtwvif->port; ++ config->sync.macid_tgt = tgt->rtwvif_link->mac_id; ++ config->sync.band_tgt = tgt->rtwvif_link->mac_idx; ++ config->sync.port_tgt = tgt->rtwvif_link->port; ++ config->sync.macid_src = src->rtwvif_link->mac_id; ++ config->sync.band_src = src->rtwvif_link->mac_idx; ++ config->sync.port_src = src->rtwvif_link->port; + config->sync.offset = tsf_ofst_tgt / 1024; + config->sync.enable = true; + +@@ -1294,7 +1294,7 @@ static void rtw89_mcc_sync_tbtt(struct rtw89_dev *rtwdev, + config->sync.macid_tgt, config->sync.macid_src, + config->sync.offset); + +- rtw89_mac_port_tsf_sync(rtwdev, tgt->rtwvif, src->rtwvif, ++ rtw89_mac_port_tsf_sync(rtwdev, tgt->rtwvif_link, src->rtwvif_link, + config->sync.offset); + } + +@@ -1305,13 +1305,13 @@ static int rtw89_mcc_fill_start_tsf(struct rtw89_dev *rtwdev) + struct rtw89_mcc_config *config = &mcc->config; + u32 bcn_intvl_ref_us = ieee80211_tu_to_usec(ref->beacon_interval); + u32 tob_ref_us = ieee80211_tu_to_usec(config->pattern.tob_ref); +- struct rtw89_vif *rtwvif = ref->rtwvif; ++ struct rtw89_vif_link *rtwvif_link = ref->rtwvif_link; + u64 tsf, start_tsf; + u32 cur_tbtt_ofst; + u64 min_time; + int ret; + +- ret = rtw89_mac_port_get_tsf(rtwdev, rtwvif, &tsf); ++ ret = rtw89_mac_port_get_tsf(rtwdev, rtwvif_link, &tsf); + if (ret) { + rtw89_warn(rtwdev, "MCC failed to get port tsf: %d\n", ret); + return ret; +@@ -1390,13 +1390,13 @@ static int __mcc_fw_add_role(struct rtw89_dev *rtwdev, struct rtw89_mcc_role *ro + const struct rtw89_chan *chan; + int ret; + +- chan = rtw89_chan_get(rtwdev, role->rtwvif->chanctx_idx); ++ chan = rtw89_chan_get(rtwdev, role->rtwvif_link->chanctx_idx); + req.central_ch_seg0 = chan->channel; + req.primary_ch = chan->primary_channel; + req.bandwidth = chan->band_width; + req.ch_band_type = chan->band_type; + +- req.macid = role->rtwvif->mac_id; ++ req.macid = role->rtwvif_link->mac_id; + req.group = mcc->group; + req.c2h_rpt = policy->c2h_rpt; + req.tx_null_early = policy->tx_null_early; +@@ -1421,7 +1421,7 @@ static int __mcc_fw_add_role(struct rtw89_dev *rtwdev, struct rtw89_mcc_role *ro + } + + ret = rtw89_fw_h2c_mcc_macid_bitmap(rtwdev, mcc->group, +- role->rtwvif->mac_id, ++ role->rtwvif_link->mac_id, + role->macid_bitmap); + if (ret) { + rtw89_debug(rtwdev, RTW89_DBG_CHAN, +@@ -1448,7 +1448,7 @@ void __mrc_fw_add_role(struct rtw89_dev *rtwdev, struct rtw89_mcc_role *role, + slot_arg->duration = role->duration; + slot_arg->role_num = 1; + +- chan = rtw89_chan_get(rtwdev, role->rtwvif->chanctx_idx); ++ chan = rtw89_chan_get(rtwdev, role->rtwvif_link->chanctx_idx); + + slot_arg->roles[0].role_type = RTW89_H2C_MRC_ROLE_WIFI; + slot_arg->roles[0].is_master = role == ref; +@@ -1458,7 +1458,7 @@ void __mrc_fw_add_role(struct rtw89_dev *rtwdev, struct rtw89_mcc_role *role, + slot_arg->roles[0].primary_ch = chan->primary_channel; + slot_arg->roles[0].en_tx_null = !policy->dis_tx_null; + slot_arg->roles[0].null_early = policy->tx_null_early; +- slot_arg->roles[0].macid = role->rtwvif->mac_id; ++ slot_arg->roles[0].macid = role->rtwvif_link->mac_id; + slot_arg->roles[0].macid_main_bitmap = + rtw89_mcc_role_fw_macid_bitmap_to_u32(role); + } +@@ -1569,7 +1569,7 @@ static int __mcc_fw_start(struct rtw89_dev *rtwdev, bool replace) + } + } + +- req.macid = ref->rtwvif->mac_id; ++ req.macid = ref->rtwvif_link->mac_id; + req.tsf_high = config->start_tsf >> 32; + req.tsf_low = config->start_tsf; + +@@ -1598,7 +1598,7 @@ static void __mrc_fw_add_courtesy(struct rtw89_dev *rtwdev, + if (!courtesy->enable) + return; + +- if (courtesy->macid_src == ref->rtwvif->mac_id) { ++ if (courtesy->macid_src == ref->rtwvif_link->mac_id) { + slot_arg_src = &arg->slots[ref->slot_idx]; + slot_idx_tgt = aux->slot_idx; + } else { +@@ -1717,9 +1717,9 @@ static int __mcc_fw_set_duration_no_bt(struct rtw89_dev *rtwdev, bool sync_chang + struct rtw89_fw_mcc_duration req = { + .group = mcc->group, + .btc_in_group = false, +- .start_macid = ref->rtwvif->mac_id, +- .macid_x = ref->rtwvif->mac_id, +- .macid_y = aux->rtwvif->mac_id, ++ .start_macid = ref->rtwvif_link->mac_id, ++ .macid_x = ref->rtwvif_link->mac_id, ++ .macid_y = aux->rtwvif_link->mac_id, + .duration_x = ref->duration, + .duration_y = aux->duration, + .start_tsf_high = config->start_tsf >> 32, +@@ -1813,18 +1813,18 @@ static void rtw89_mcc_handle_beacon_noa(struct rtw89_dev *rtwdev, bool enable) + struct ieee80211_p2p_noa_desc noa_desc = {}; + u64 start_time = config->start_tsf; + u32 interval = config->mcc_interval; +- struct rtw89_vif *rtwvif_go; ++ struct rtw89_vif_link *rtwvif_go; + u32 duration; + + if (mcc->mode != RTW89_MCC_MODE_GO_STA) + return; + + if (ref->is_go) { +- rtwvif_go = ref->rtwvif; ++ rtwvif_go = ref->rtwvif_link; + start_time += ieee80211_tu_to_usec(ref->duration); + duration = config->mcc_interval - ref->duration; + } else if (aux->is_go) { +- rtwvif_go = aux->rtwvif; ++ rtwvif_go = aux->rtwvif_link; + start_time += ieee80211_tu_to_usec(pattern->tob_ref) + + ieee80211_tu_to_usec(config->beacon_offset) + + ieee80211_tu_to_usec(pattern->toa_aux); +@@ -1865,9 +1865,9 @@ static void rtw89_mcc_start_beacon_noa(struct rtw89_dev *rtwdev) + return; + + if (ref->is_go) +- rtw89_fw_h2c_tsf32_toggle(rtwdev, ref->rtwvif, true); ++ rtw89_fw_h2c_tsf32_toggle(rtwdev, ref->rtwvif_link, true); + else if (aux->is_go) +- rtw89_fw_h2c_tsf32_toggle(rtwdev, aux->rtwvif, true); ++ rtw89_fw_h2c_tsf32_toggle(rtwdev, aux->rtwvif_link, true); + + rtw89_mcc_handle_beacon_noa(rtwdev, true); + } +@@ -1882,9 +1882,9 @@ static void rtw89_mcc_stop_beacon_noa(struct rtw89_dev *rtwdev) + return; + + if (ref->is_go) +- rtw89_fw_h2c_tsf32_toggle(rtwdev, ref->rtwvif, false); ++ rtw89_fw_h2c_tsf32_toggle(rtwdev, ref->rtwvif_link, false); + else if (aux->is_go) +- rtw89_fw_h2c_tsf32_toggle(rtwdev, aux->rtwvif, false); ++ rtw89_fw_h2c_tsf32_toggle(rtwdev, aux->rtwvif_link, false); + + rtw89_mcc_handle_beacon_noa(rtwdev, false); + } +@@ -1942,7 +1942,7 @@ struct rtw89_mcc_stop_sel { + static void rtw89_mcc_stop_sel_fill(struct rtw89_mcc_stop_sel *sel, + const struct rtw89_mcc_role *mcc_role) + { +- sel->mac_id = mcc_role->rtwvif->mac_id; ++ sel->mac_id = mcc_role->rtwvif_link->mac_id; + sel->slot_idx = mcc_role->slot_idx; + } + +@@ -1953,7 +1953,7 @@ static int rtw89_mcc_stop_sel_iterator(struct rtw89_dev *rtwdev, + { + struct rtw89_mcc_stop_sel *sel = data; + +- if (!mcc_role->rtwvif->chanctx_assigned) ++ if (!mcc_role->rtwvif_link->chanctx_assigned) + return 0; + + rtw89_mcc_stop_sel_fill(sel, mcc_role); +@@ -2081,7 +2081,7 @@ static int __mcc_fw_upd_macid_bitmap(struct rtw89_dev *rtwdev, + int ret; + + ret = rtw89_fw_h2c_mcc_macid_bitmap(rtwdev, mcc->group, +- upd->rtwvif->mac_id, ++ upd->rtwvif_link->mac_id, + upd->macid_bitmap); + if (ret) { + rtw89_debug(rtwdev, RTW89_DBG_CHAN, +@@ -2106,7 +2106,7 @@ static int __mrc_fw_upd_macid_bitmap(struct rtw89_dev *rtwdev, + int i; + + arg.sch_idx = mcc->group; +- arg.macid = upd->rtwvif->mac_id; ++ arg.macid = upd->rtwvif_link->mac_id; + + for (i = 0; i < 32; i++) { + if (add & BIT(i)) { +@@ -2144,7 +2144,7 @@ static int rtw89_mcc_upd_map_iterator(struct rtw89_dev *rtwdev, + void *data) + { + struct rtw89_mcc_role upd = { +- .rtwvif = mcc_role->rtwvif, ++ .rtwvif_link = mcc_role->rtwvif_link, + }; + int ret; + +@@ -2375,7 +2375,7 @@ static void rtw89_swap_chanctx(struct rtw89_dev *rtwdev, + enum rtw89_chanctx_idx idx2) + { + struct rtw89_hal *hal = &rtwdev->hal; +- struct rtw89_vif *rtwvif; ++ struct rtw89_vif_link *rtwvif_link; + u8 cur; + + if (idx1 == idx2) +@@ -2386,13 +2386,13 @@ static void rtw89_swap_chanctx(struct rtw89_dev *rtwdev, + + swap(hal->chanctx[idx1], hal->chanctx[idx2]); + +- rtw89_for_each_rtwvif(rtwdev, rtwvif) { +- if (!rtwvif->chanctx_assigned) ++ rtw89_for_each_rtwvif(rtwdev, rtwvif_link) { ++ if (!rtwvif_link->chanctx_assigned) + continue; +- if (rtwvif->chanctx_idx == idx1) +- rtwvif->chanctx_idx = idx2; +- else if (rtwvif->chanctx_idx == idx2) +- rtwvif->chanctx_idx = idx1; ++ if (rtwvif_link->chanctx_idx == idx1) ++ rtwvif_link->chanctx_idx = idx2; ++ else if (rtwvif_link->chanctx_idx == idx2) ++ rtwvif_link->chanctx_idx = idx1; + } + + cur = atomic_read(&hal->roc_chanctx_idx); +@@ -2444,14 +2444,14 @@ void rtw89_chanctx_ops_change(struct rtw89_dev *rtwdev, + } + + int rtw89_chanctx_ops_assign_vif(struct rtw89_dev *rtwdev, +- struct rtw89_vif *rtwvif, ++ struct rtw89_vif_link *rtwvif_link, + struct ieee80211_chanctx_conf *ctx) + { + struct rtw89_chanctx_cfg *cfg = (struct rtw89_chanctx_cfg *)ctx->drv_priv; + struct rtw89_entity_weight w = {}; + +- rtwvif->chanctx_idx = cfg->idx; +- rtwvif->chanctx_assigned = true; ++ rtwvif_link->chanctx_idx = cfg->idx; ++ rtwvif_link->chanctx_assigned = true; + cfg->ref_count++; + + if (cfg->idx == RTW89_CHANCTX_0) +@@ -2469,7 +2469,7 @@ int rtw89_chanctx_ops_assign_vif(struct rtw89_dev *rtwdev, + } + + void rtw89_chanctx_ops_unassign_vif(struct rtw89_dev *rtwdev, +- struct rtw89_vif *rtwvif, ++ struct rtw89_vif_link *rtwvif_link, + struct ieee80211_chanctx_conf *ctx) + { + struct rtw89_chanctx_cfg *cfg = (struct rtw89_chanctx_cfg *)ctx->drv_priv; +@@ -2479,8 +2479,8 @@ void rtw89_chanctx_ops_unassign_vif(struct rtw89_dev *rtwdev, + enum rtw89_entity_mode new; + int ret; + +- rtwvif->chanctx_idx = RTW89_CHANCTX_0; +- rtwvif->chanctx_assigned = false; ++ rtwvif_link->chanctx_idx = RTW89_CHANCTX_0; ++ rtwvif_link->chanctx_assigned = false; + cfg->ref_count--; + + if (cfg->ref_count != 0) +diff --git a/drivers/net/wireless/realtek/rtw89/chan.h b/drivers/net/wireless/realtek/rtw89/chan.h +index c6d31984e5753..4ed777ea50648 100644 +--- a/drivers/net/wireless/realtek/rtw89/chan.h ++++ b/drivers/net/wireless/realtek/rtw89/chan.h +@@ -106,10 +106,10 @@ void rtw89_chanctx_ops_change(struct rtw89_dev *rtwdev, + struct ieee80211_chanctx_conf *ctx, + u32 changed); + int rtw89_chanctx_ops_assign_vif(struct rtw89_dev *rtwdev, +- struct rtw89_vif *rtwvif, ++ struct rtw89_vif_link *rtwvif_link, + struct ieee80211_chanctx_conf *ctx); + void rtw89_chanctx_ops_unassign_vif(struct rtw89_dev *rtwdev, +- struct rtw89_vif *rtwvif, ++ struct rtw89_vif_link *rtwvif_link, + struct ieee80211_chanctx_conf *ctx); + + #endif +diff --git a/drivers/net/wireless/realtek/rtw89/coex.c b/drivers/net/wireless/realtek/rtw89/coex.c +index 8d27374db83ca..f56257d1e33e3 100644 +--- a/drivers/net/wireless/realtek/rtw89/coex.c ++++ b/drivers/net/wireless/realtek/rtw89/coex.c +@@ -4995,12 +4995,12 @@ static void rtw89_tx_time_iter(void *data, struct ieee80211_sta *sta) + struct rtw89_txtime_data *iter_data = + (struct rtw89_txtime_data *)data; + struct rtw89_dev *rtwdev = iter_data->rtwdev; +- struct rtw89_vif *rtwvif = rtwsta->rtwvif; ++ struct rtw89_vif_link *rtwvif_link = rtwsta->rtwvif_link; + struct rtw89_btc *btc = &rtwdev->btc; + struct rtw89_btc_cx *cx = &btc->cx; + struct rtw89_btc_wl_info *wl = &cx->wl; + struct rtw89_btc_wl_link_info *plink = NULL; +- u8 port = rtwvif->port; ++ u8 port = rtwvif_link->port; + u32 tx_time = iter_data->tx_time; + u8 tx_retry = iter_data->tx_retry; + u16 enable = iter_data->enable; +@@ -7481,12 +7481,13 @@ static void _update_bt_info(struct rtw89_dev *rtwdev, u8 *buf, u32 len) + _run_coex(rtwdev, BTC_RSN_UPDATE_BT_INFO); + } + +-void rtw89_btc_ntfy_role_info(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, ++void rtw89_btc_ntfy_role_info(struct rtw89_dev *rtwdev, ++ struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta *rtwsta, enum btc_role_state state) + { + const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, +- rtwvif->chanctx_idx); +- struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif); ++ rtwvif_link->chanctx_idx); ++ struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif_link); + struct ieee80211_sta *sta = rtwsta_to_sta(rtwsta); + struct rtw89_btc *btc = &rtwdev->btc; + const struct rtw89_btc_ver *ver = btc->ver; +@@ -7499,7 +7500,7 @@ void rtw89_btc_ntfy_role_info(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif + rtw89_debug(rtwdev, RTW89_DBG_BTC, + "[BTC], role is STA=%d\n", + vif->type == NL80211_IFTYPE_STATION); +- rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], port=%d\n", rtwvif->port); ++ rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], port=%d\n", rtwvif_link->port); + rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], band=%d ch=%d bw=%d\n", + chan->band_type, chan->channel, chan->band_width); + rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], associated=%d\n", +@@ -7527,15 +7528,15 @@ void rtw89_btc_ntfy_role_info(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif + r.mode = mode; + } + +- if (rtwvif->wifi_role >= RTW89_WIFI_ROLE_MLME_MAX) ++ if (rtwvif_link->wifi_role >= RTW89_WIFI_ROLE_MLME_MAX) + return; + + rtw89_debug(rtwdev, RTW89_DBG_BTC, +- "[BTC], wifi_role=%d\n", rtwvif->wifi_role); ++ "[BTC], wifi_role=%d\n", rtwvif_link->wifi_role); + +- r.role = rtwvif->wifi_role; +- r.phy = rtwvif->phy_idx; +- r.pid = rtwvif->port; ++ r.role = rtwvif_link->wifi_role; ++ r.phy = rtwvif_link->phy_idx; ++ r.pid = rtwvif_link->port; + r.active = true; + r.connected = MLME_LINKED; + r.bcn_period = vif->bss_conf.beacon_int; +@@ -7547,7 +7548,7 @@ void rtw89_btc_ntfy_role_info(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif + r.chdef.center_ch = chan->channel; + r.chdef.bw = chan->band_width; + r.chdef.chan = chan->primary_channel; +- ether_addr_copy(r.mac_addr, rtwvif->mac_addr); ++ ether_addr_copy(r.mac_addr, rtwvif_link->mac_addr); + + if (rtwsta && vif->type == NL80211_IFTYPE_STATION) + r.mac_id = rtwsta->mac_id; +@@ -7793,14 +7794,14 @@ static void rtw89_btc_ntfy_wl_sta_iter(void *data, struct ieee80211_sta *sta) + struct rtw89_btc_wl_link_info *link_info = NULL; + struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv; + struct rtw89_traffic_stats *link_info_t = NULL; +- struct rtw89_vif *rtwvif = rtwsta->rtwvif; +- struct rtw89_traffic_stats *stats = &rtwvif->stats; ++ struct rtw89_vif_link *rtwvif_link = rtwsta->rtwvif_link; ++ struct rtw89_traffic_stats *stats = &rtwvif_link->stats; + const struct rtw89_chip_info *chip = rtwdev->chip; + struct rtw89_btc_wl_role_info *r; + struct rtw89_btc_wl_role_info_v1 *r1; + u32 last_tx_rate, last_rx_rate; + u16 last_tx_lvl, last_rx_lvl; +- u8 port = rtwvif->port; ++ u8 port = rtwvif_link->port; + u8 rssi; + u8 busy = 0; + u8 dir = 0; +@@ -7812,7 +7813,7 @@ static void rtw89_btc_ntfy_wl_sta_iter(void *data, struct ieee80211_sta *sta) + rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], rssi=%d\n", rssi); + + link_info = &wl->link_info[port]; +- link_info->stat.traffic = rtwvif->stats; ++ link_info->stat.traffic = rtwvif_link->stats; + link_info_t = &link_info->stat.traffic; + + if (link_info->connected == MLME_NO_LINK) { +diff --git a/drivers/net/wireless/realtek/rtw89/coex.h b/drivers/net/wireless/realtek/rtw89/coex.h +index de53b56632f7c..2a3bd1ead7c3e 100644 +--- a/drivers/net/wireless/realtek/rtw89/coex.h ++++ b/drivers/net/wireless/realtek/rtw89/coex.h +@@ -271,7 +271,8 @@ void rtw89_btc_ntfy_eapol_packet_work(struct work_struct *work); + void rtw89_btc_ntfy_arp_packet_work(struct work_struct *work); + void rtw89_btc_ntfy_dhcp_packet_work(struct work_struct *work); + void rtw89_btc_ntfy_icmp_packet_work(struct work_struct *work); +-void rtw89_btc_ntfy_role_info(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, ++void rtw89_btc_ntfy_role_info(struct rtw89_dev *rtwdev, ++ struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta *rtwsta, enum btc_role_state state); + void rtw89_btc_ntfy_radio_state(struct rtw89_dev *rtwdev, enum btc_rfctrl rf_state); + void rtw89_btc_ntfy_wl_rfk(struct rtw89_dev *rtwdev, u8 phy_map, +diff --git a/drivers/net/wireless/realtek/rtw89/core.c b/drivers/net/wireless/realtek/rtw89/core.c +index 4553810634c66..314c2e2ef8e90 100644 +--- a/drivers/net/wireless/realtek/rtw89/core.c ++++ b/drivers/net/wireless/realtek/rtw89/core.c +@@ -436,12 +436,12 @@ int rtw89_set_channel(struct rtw89_dev *rtwdev) + return 0; + } + +-void rtw89_get_channel(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, ++void rtw89_get_channel(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, + struct rtw89_chan *chan) + { + const struct cfg80211_chan_def *chandef; + +- chandef = rtw89_chandef_get(rtwdev, rtwvif->chanctx_idx); ++ chandef = rtw89_chandef_get(rtwdev, rtwvif_link->chanctx_idx); + rtw89_get_channel_params(chandef, chan); + } + +@@ -591,12 +591,12 @@ static u8 rtw89_core_tx_get_mac_id(struct rtw89_dev *rtwdev, + struct rtw89_core_tx_request *tx_req) + { + struct ieee80211_vif *vif = tx_req->vif; +- struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; ++ struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv; + struct ieee80211_sta *sta = tx_req->sta; + struct rtw89_sta *rtwsta; + + if (!sta) +- return rtwvif->mac_id; ++ return rtwvif_link->mac_id; + + rtwsta = (struct rtw89_sta *)sta->drv_priv; + return rtwsta->mac_id; +@@ -619,10 +619,10 @@ rtw89_core_tx_update_mgmt_info(struct rtw89_dev *rtwdev, + { + const struct rtw89_chip_info *chip = rtwdev->chip; + struct ieee80211_vif *vif = tx_req->vif; +- struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; ++ struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv; + struct rtw89_tx_desc_info *desc_info = &tx_req->desc_info; + const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, +- rtwvif->chanctx_idx); ++ rtwvif_link->chanctx_idx); + struct sk_buff *skb = tx_req->skb; + u8 qsel, ch_dma; + +@@ -631,7 +631,7 @@ rtw89_core_tx_update_mgmt_info(struct rtw89_dev *rtwdev, + + desc_info->qsel = qsel; + desc_info->ch_dma = ch_dma; +- desc_info->port = desc_info->hiq ? rtwvif->port : 0; ++ desc_info->port = desc_info->hiq ? rtwvif_link->port : 0; + desc_info->mac_id = rtw89_core_tx_get_mac_id(rtwdev, tx_req); + desc_info->hw_ssn_sel = RTW89_MGMT_HW_SSN_SEL; + desc_info->hw_seq_mode = RTW89_MGMT_HW_SEQ_MODE; +@@ -762,7 +762,7 @@ rtw89_core_tx_update_he_qos_htc(struct rtw89_dev *rtwdev, + { + struct rtw89_tx_desc_info *desc_info = &tx_req->desc_info; + struct ieee80211_vif *vif = tx_req->vif; +- struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; ++ struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv; + + if (!__rtw89_core_tx_check_he_qos_htc(rtwdev, tx_req, pkt_type)) + goto desc_bk; +@@ -773,10 +773,10 @@ rtw89_core_tx_update_he_qos_htc(struct rtw89_dev *rtwdev, + desc_info->a_ctrl_bsr = true; + + desc_bk: +- if (!rtwvif || rtwvif->last_a_ctrl == desc_info->a_ctrl_bsr) ++ if (!rtwvif_link || rtwvif_link->last_a_ctrl == desc_info->a_ctrl_bsr) + return; + +- rtwvif->last_a_ctrl = desc_info->a_ctrl_bsr; ++ rtwvif_link->last_a_ctrl = desc_info->a_ctrl_bsr; + desc_info->bk = true; + } + +@@ -785,9 +785,9 @@ static u16 rtw89_core_get_data_rate(struct rtw89_dev *rtwdev, + { + struct ieee80211_vif *vif = tx_req->vif; + struct ieee80211_sta *sta = tx_req->sta; +- struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; +- struct rtw89_phy_rate_pattern *rate_pattern = &rtwvif->rate_pattern; +- enum rtw89_chanctx_idx idx = rtwvif->chanctx_idx; ++ struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv; ++ struct rtw89_phy_rate_pattern *rate_pattern = &rtwvif_link->rate_pattern; ++ enum rtw89_chanctx_idx idx = rtwvif_link->chanctx_idx; + const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, idx); + u16 lowest_rate; + +@@ -813,7 +813,7 @@ rtw89_core_tx_update_data_info(struct rtw89_dev *rtwdev, + { + struct ieee80211_vif *vif = tx_req->vif; + struct ieee80211_sta *sta = tx_req->sta; +- struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; ++ struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv; + struct rtw89_sta *rtwsta = sta_to_rtwsta_safe(sta); + struct rtw89_tx_desc_info *desc_info = &tx_req->desc_info; + struct sk_buff *skb = tx_req->skb; +@@ -829,7 +829,7 @@ rtw89_core_tx_update_data_info(struct rtw89_dev *rtwdev, + desc_info->tid_indicate = tid_indicate; + desc_info->qsel = qsel; + desc_info->mac_id = rtw89_core_tx_get_mac_id(rtwdev, tx_req); +- desc_info->port = desc_info->hiq ? rtwvif->port : 0; ++ desc_info->port = desc_info->hiq ? rtwvif_link->port : 0; + desc_info->er_cap = rtwsta ? rtwsta->er_cap : false; + desc_info->stbc = rtwsta ? rtwsta->ra.stbc_cap : false; + desc_info->ldpc = rtwsta ? rtwsta->ra.ldpc_cap : false; +@@ -1028,7 +1028,7 @@ int rtw89_core_tx_write(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif, + struct ieee80211_sta *sta, struct sk_buff *skb, int *qsel) + { + struct rtw89_core_tx_request tx_req = {0}; +- struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; ++ struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv; + int ret; + + tx_req.skb = skb; +@@ -1036,7 +1036,7 @@ int rtw89_core_tx_write(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif, + tx_req.vif = vif; + + rtw89_traffic_stats_accu(rtwdev, &rtwdev->stats, skb, true); +- rtw89_traffic_stats_accu(rtwdev, &rtwvif->stats, skb, true); ++ rtw89_traffic_stats_accu(rtwdev, &rtwvif_link->stats, skb, true); + rtw89_core_tx_update_desc_info(rtwdev, &tx_req); + rtw89_core_tx_wake(rtwdev, &tx_req); + +@@ -1879,14 +1879,14 @@ static void rtw89_stats_trigger_frame(struct rtw89_dev *rtwdev, + struct ieee80211_vif *vif, + struct sk_buff *skb) + { +- struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; ++ struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv; + struct ieee80211_trigger *tf = (struct ieee80211_trigger *)skb->data; + u8 *pos, *end, type, tf_bw; + u16 aid, tf_rua; + + if (!ether_addr_equal(vif->bss_conf.bssid, tf->ta) || +- rtwvif->wifi_role != RTW89_WIFI_ROLE_STATION || +- rtwvif->net_type == RTW89_NET_TYPE_NO_LINK) ++ rtwvif_link->wifi_role != RTW89_WIFI_ROLE_STATION || ++ rtwvif_link->net_type == RTW89_NET_TYPE_NO_LINK) + return; + + type = le64_get_bits(tf->common_info, IEEE80211_TRIGGER_TYPE_MASK); +@@ -1911,11 +1911,11 @@ static void rtw89_stats_trigger_frame(struct rtw89_dev *rtwdev, + if (aid == vif->cfg.aid) { + enum nl80211_he_ru_alloc rua = rtw89_he_rua_to_ru_alloc(tf_rua >> 1); + +- rtwvif->stats.rx_tf_acc++; ++ rtwvif_link->stats.rx_tf_acc++; + rtwdev->stats.rx_tf_acc++; + if (tf_bw == IEEE80211_TRIGGER_ULBW_160_80P80MHZ && + rua <= NL80211_RATE_INFO_HE_RU_ALLOC_106) +- rtwvif->pwr_diff_en = true; ++ rtwvif_link->pwr_diff_en = true; + break; + } + +@@ -1986,7 +1986,7 @@ static void rtw89_core_cancel_6ghz_probe_tx(struct rtw89_dev *rtwdev, + ieee80211_queue_work(rtwdev->hw, &rtwdev->cancel_6ghz_probe_work); + } + +-static void rtw89_vif_sync_bcn_tsf(struct rtw89_vif *rtwvif, ++static void rtw89_vif_sync_bcn_tsf(struct rtw89_vif_link *rtwvif_link, + struct ieee80211_hdr *hdr, size_t len) + { + struct ieee80211_mgmt *mgmt = (typeof(mgmt))hdr; +@@ -1994,13 +1994,13 @@ static void rtw89_vif_sync_bcn_tsf(struct rtw89_vif *rtwvif, + if (len < offsetof(typeof(*mgmt), u.beacon.variable)) + return; + +- WRITE_ONCE(rtwvif->sync_bcn_tsf, le64_to_cpu(mgmt->u.beacon.timestamp)); ++ WRITE_ONCE(rtwvif_link->sync_bcn_tsf, le64_to_cpu(mgmt->u.beacon.timestamp)); + } + + static void rtw89_vif_rx_stats_iter(void *data, u8 *mac, + struct ieee80211_vif *vif) + { +- struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; ++ struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv; + struct rtw89_vif_rx_stats_iter_data *iter_data = data; + struct rtw89_dev *rtwdev = iter_data->rtwdev; + struct rtw89_pkt_stat *pkt_stat = &rtwdev->phystat.cur_pkt_stat; +@@ -2029,7 +2029,7 @@ static void rtw89_vif_rx_stats_iter(void *data, u8 *mac, + if (ieee80211_is_beacon(hdr->frame_control)) { + if (vif->type == NL80211_IFTYPE_STATION && + !test_bit(RTW89_FLAG_WOWLAN, rtwdev->flags)) { +- rtw89_vif_sync_bcn_tsf(rtwvif, hdr, skb->len); ++ rtw89_vif_sync_bcn_tsf(rtwvif_link, hdr, skb->len); + rtw89_fw_h2c_rssi_offload(rtwdev, phy_ppdu); + } + pkt_stat->beacon_nr++; +@@ -2041,7 +2041,7 @@ static void rtw89_vif_rx_stats_iter(void *data, u8 *mac, + if (desc_info->data_rate < RTW89_HW_RATE_NR) + pkt_stat->rx_rate_cnt[desc_info->data_rate]++; + +- rtw89_traffic_stats_accu(rtwdev, &rtwvif->stats, skb, false); ++ rtw89_traffic_stats_accu(rtwdev, &rtwvif_link->stats, skb, false); + } + + static void rtw89_core_rx_stats(struct rtw89_dev *rtwdev, +@@ -2869,7 +2869,7 @@ static void rtw89_core_txq_schedule(struct rtw89_dev *rtwdev, u8 ac, bool *reinv + { + struct ieee80211_hw *hw = rtwdev->hw; + struct ieee80211_txq *txq; +- struct rtw89_vif *rtwvif; ++ struct rtw89_vif_link *rtwvif_link; + struct rtw89_txq *rtwtxq; + unsigned long frame_cnt; + unsigned long byte_cnt; +@@ -2879,9 +2879,9 @@ static void rtw89_core_txq_schedule(struct rtw89_dev *rtwdev, u8 ac, bool *reinv + ieee80211_txq_schedule_start(hw, ac); + while ((txq = ieee80211_next_txq(hw, ac))) { + rtwtxq = (struct rtw89_txq *)txq->drv_priv; +- rtwvif = (struct rtw89_vif *)txq->vif->drv_priv; ++ rtwvif_link = (struct rtw89_vif_link *)txq->vif->drv_priv; + +- if (rtwvif->offchan) { ++ if (rtwvif_link->offchan) { + ieee80211_return_txq(hw, txq, true); + continue; + } +@@ -2956,13 +2956,14 @@ static void rtw89_core_sta_pending_tx_iter(void *data, + struct ieee80211_sta *sta) + { + struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv; +- struct rtw89_vif *rtwvif_target = data, *rtwvif = rtwsta->rtwvif; +- struct rtw89_dev *rtwdev = rtwvif->rtwdev; +- struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif); ++ struct rtw89_vif_link *rtwvif_target = data; ++ struct rtw89_vif_link *rtwvif_link = rtwsta->rtwvif_link; ++ struct rtw89_dev *rtwdev = rtwvif_link->rtwdev; ++ struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif_link); + struct sk_buff *skb, *tmp; + int qsel, ret; + +- if (rtwvif->chanctx_idx != rtwvif_target->chanctx_idx) ++ if (rtwvif_link->chanctx_idx != rtwvif_target->chanctx_idx) + return; + + if (skb_queue_len(&rtwsta->roc_queue) == 0) +@@ -2982,17 +2983,17 @@ static void rtw89_core_sta_pending_tx_iter(void *data, + } + + static void rtw89_core_handle_sta_pending_tx(struct rtw89_dev *rtwdev, +- struct rtw89_vif *rtwvif) ++ struct rtw89_vif_link *rtwvif_link) + { + ieee80211_iterate_stations_atomic(rtwdev->hw, + rtw89_core_sta_pending_tx_iter, +- rtwvif); ++ rtwvif_link); + } + + static int rtw89_core_send_nullfunc(struct rtw89_dev *rtwdev, +- struct rtw89_vif *rtwvif, bool qos, bool ps) ++ struct rtw89_vif_link *rtwvif_link, bool qos, bool ps) + { +- struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif); ++ struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif_link); + struct ieee80211_sta *sta; + struct ieee80211_hdr *hdr; + struct sk_buff *skb; +@@ -3035,13 +3036,13 @@ static int rtw89_core_send_nullfunc(struct rtw89_dev *rtwdev, + return ret; + } + +-void rtw89_roc_start(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif) ++void rtw89_roc_start(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link) + { + const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; + struct ieee80211_hw *hw = rtwdev->hw; +- struct rtw89_roc *roc = &rtwvif->roc; ++ struct rtw89_roc *roc = &rtwvif_link->roc; + struct cfg80211_chan_def roc_chan; +- struct rtw89_vif *tmp; ++ struct rtw89_vif_link *tmp; + int ret; + + lockdep_assert_held(&rtwdev->mutex); +@@ -3050,34 +3051,34 @@ void rtw89_roc_start(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif) + rtw89_leave_lps(rtwdev); + rtw89_chanctx_pause(rtwdev, RTW89_CHANCTX_PAUSE_REASON_ROC); + +- ret = rtw89_core_send_nullfunc(rtwdev, rtwvif, true, true); ++ ret = rtw89_core_send_nullfunc(rtwdev, rtwvif_link, true, true); + if (ret) + rtw89_debug(rtwdev, RTW89_DBG_TXRX, + "roc send null-1 failed: %d\n", ret); + + rtw89_for_each_rtwvif(rtwdev, tmp) +- if (tmp->chanctx_idx == rtwvif->chanctx_idx) ++ if (tmp->chanctx_idx == rtwvif_link->chanctx_idx) + tmp->offchan = true; + + cfg80211_chandef_create(&roc_chan, &roc->chan, NL80211_CHAN_NO_HT); +- rtw89_config_roc_chandef(rtwdev, rtwvif->chanctx_idx, &roc_chan); ++ rtw89_config_roc_chandef(rtwdev, rtwvif_link->chanctx_idx, &roc_chan); + rtw89_set_channel(rtwdev); + rtw89_write32_clr(rtwdev, + rtw89_mac_reg_by_idx(rtwdev, mac->rx_fltr, RTW89_MAC_0), + B_AX_A_UC_CAM_MATCH | B_AX_A_BC_CAM_MATCH); + + ieee80211_ready_on_channel(hw); +- cancel_delayed_work(&rtwvif->roc.roc_work); +- ieee80211_queue_delayed_work(hw, &rtwvif->roc.roc_work, +- msecs_to_jiffies(rtwvif->roc.duration)); ++ cancel_delayed_work(&rtwvif_link->roc.roc_work); ++ ieee80211_queue_delayed_work(hw, &rtwvif_link->roc.roc_work, ++ msecs_to_jiffies(rtwvif_link->roc.duration)); + } + +-void rtw89_roc_end(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif) ++void rtw89_roc_end(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link) + { + const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; + struct ieee80211_hw *hw = rtwdev->hw; +- struct rtw89_roc *roc = &rtwvif->roc; +- struct rtw89_vif *tmp; ++ struct rtw89_roc *roc = &rtwvif_link->roc; ++ struct rtw89_vif_link *tmp; + int ret; + + lockdep_assert_held(&rtwdev->mutex); +@@ -3093,18 +3094,18 @@ void rtw89_roc_end(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif) + rtwdev->hal.rx_fltr); + + roc->state = RTW89_ROC_IDLE; +- rtw89_config_roc_chandef(rtwdev, rtwvif->chanctx_idx, NULL); ++ rtw89_config_roc_chandef(rtwdev, rtwvif_link->chanctx_idx, NULL); + rtw89_chanctx_proceed(rtwdev); +- ret = rtw89_core_send_nullfunc(rtwdev, rtwvif, true, false); ++ ret = rtw89_core_send_nullfunc(rtwdev, rtwvif_link, true, false); + if (ret) + rtw89_debug(rtwdev, RTW89_DBG_TXRX, + "roc send null-0 failed: %d\n", ret); + + rtw89_for_each_rtwvif(rtwdev, tmp) +- if (tmp->chanctx_idx == rtwvif->chanctx_idx) ++ if (tmp->chanctx_idx == rtwvif_link->chanctx_idx) + tmp->offchan = false; + +- rtw89_core_handle_sta_pending_tx(rtwdev, rtwvif); ++ rtw89_core_handle_sta_pending_tx(rtwdev, rtwvif_link); + queue_work(rtwdev->txq_wq, &rtwdev->txq_work); + + if (hw->conf.flags & IEEE80211_CONF_IDLE) +@@ -3114,10 +3115,10 @@ void rtw89_roc_end(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif) + + void rtw89_roc_work(struct work_struct *work) + { +- struct rtw89_vif *rtwvif = container_of(work, struct rtw89_vif, +- roc.roc_work.work); +- struct rtw89_dev *rtwdev = rtwvif->rtwdev; +- struct rtw89_roc *roc = &rtwvif->roc; ++ struct rtw89_vif_link *rtwvif_link = container_of(work, struct rtw89_vif_link, ++ roc.roc_work.work); ++ struct rtw89_dev *rtwdev = rtwvif_link->rtwdev; ++ struct rtw89_roc *roc = &rtwvif_link->roc; + + mutex_lock(&rtwdev->mutex); + +@@ -3127,7 +3128,7 @@ void rtw89_roc_work(struct work_struct *work) + break; + case RTW89_ROC_MGMT: + case RTW89_ROC_NORMAL: +- rtw89_roc_end(rtwdev, rtwvif); ++ rtw89_roc_end(rtwdev, rtwvif_link); + break; + default: + break; +@@ -3188,39 +3189,40 @@ static bool rtw89_traffic_stats_calc(struct rtw89_dev *rtwdev, + + static bool rtw89_traffic_stats_track(struct rtw89_dev *rtwdev) + { +- struct rtw89_vif *rtwvif; ++ struct rtw89_vif_link *rtwvif_link; + bool tfc_changed; + + tfc_changed = rtw89_traffic_stats_calc(rtwdev, &rtwdev->stats); +- rtw89_for_each_rtwvif(rtwdev, rtwvif) { +- rtw89_traffic_stats_calc(rtwdev, &rtwvif->stats); +- rtw89_fw_h2c_tp_offload(rtwdev, rtwvif); ++ rtw89_for_each_rtwvif(rtwdev, rtwvif_link) { ++ rtw89_traffic_stats_calc(rtwdev, &rtwvif_link->stats); ++ rtw89_fw_h2c_tp_offload(rtwdev, rtwvif_link); + } + + return tfc_changed; + } + +-static void rtw89_vif_enter_lps(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif) ++static void rtw89_vif_enter_lps(struct rtw89_dev *rtwdev, ++ struct rtw89_vif_link *rtwvif_link) + { +- if ((rtwvif->wifi_role != RTW89_WIFI_ROLE_STATION && +- rtwvif->wifi_role != RTW89_WIFI_ROLE_P2P_CLIENT) || +- rtwvif->tdls_peer) ++ if ((rtwvif_link->wifi_role != RTW89_WIFI_ROLE_STATION && ++ rtwvif_link->wifi_role != RTW89_WIFI_ROLE_P2P_CLIENT) || ++ rtwvif_link->tdls_peer) + return; + +- if (rtwvif->offchan) ++ if (rtwvif_link->offchan) + return; + +- if (rtwvif->stats.tx_tfc_lv == RTW89_TFC_IDLE && +- rtwvif->stats.rx_tfc_lv == RTW89_TFC_IDLE) +- rtw89_enter_lps(rtwdev, rtwvif, true); ++ if (rtwvif_link->stats.tx_tfc_lv == RTW89_TFC_IDLE && ++ rtwvif_link->stats.rx_tfc_lv == RTW89_TFC_IDLE) ++ rtw89_enter_lps(rtwdev, rtwvif_link, true); + } + + static void rtw89_enter_lps_track(struct rtw89_dev *rtwdev) + { +- struct rtw89_vif *rtwvif; ++ struct rtw89_vif_link *rtwvif_link; + +- rtw89_for_each_rtwvif(rtwdev, rtwvif) +- rtw89_vif_enter_lps(rtwdev, rtwvif); ++ rtw89_for_each_rtwvif(rtwdev, rtwvif_link) ++ rtw89_vif_enter_lps(rtwdev, rtwvif_link); + } + + static void rtw89_core_rfk_track(struct rtw89_dev *rtwdev) +@@ -3396,24 +3398,24 @@ int rtw89_core_release_sta_ba_entry(struct rtw89_dev *rtwdev, + + #define RTW89_TYPE_MAPPING(_type) \ + case NL80211_IFTYPE_ ## _type: \ +- rtwvif->wifi_role = RTW89_WIFI_ROLE_ ## _type; \ ++ rtwvif_link->wifi_role = RTW89_WIFI_ROLE_ ## _type; \ + break + void rtw89_vif_type_mapping(struct ieee80211_vif *vif, bool assoc) + { +- struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; ++ struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv; + + switch (vif->type) { + case NL80211_IFTYPE_STATION: + if (vif->p2p) +- rtwvif->wifi_role = RTW89_WIFI_ROLE_P2P_CLIENT; ++ rtwvif_link->wifi_role = RTW89_WIFI_ROLE_P2P_CLIENT; + else +- rtwvif->wifi_role = RTW89_WIFI_ROLE_STATION; ++ rtwvif_link->wifi_role = RTW89_WIFI_ROLE_STATION; + break; + case NL80211_IFTYPE_AP: + if (vif->p2p) +- rtwvif->wifi_role = RTW89_WIFI_ROLE_P2P_GO; ++ rtwvif_link->wifi_role = RTW89_WIFI_ROLE_P2P_GO; + else +- rtwvif->wifi_role = RTW89_WIFI_ROLE_AP; ++ rtwvif_link->wifi_role = RTW89_WIFI_ROLE_AP; + break; + RTW89_TYPE_MAPPING(ADHOC); + RTW89_TYPE_MAPPING(MONITOR); +@@ -3426,23 +3428,23 @@ void rtw89_vif_type_mapping(struct ieee80211_vif *vif, bool assoc) + switch (vif->type) { + case NL80211_IFTYPE_AP: + case NL80211_IFTYPE_MESH_POINT: +- rtwvif->net_type = RTW89_NET_TYPE_AP_MODE; +- rtwvif->self_role = RTW89_SELF_ROLE_AP; ++ rtwvif_link->net_type = RTW89_NET_TYPE_AP_MODE; ++ rtwvif_link->self_role = RTW89_SELF_ROLE_AP; + break; + case NL80211_IFTYPE_ADHOC: +- rtwvif->net_type = RTW89_NET_TYPE_AD_HOC; +- rtwvif->self_role = RTW89_SELF_ROLE_CLIENT; ++ rtwvif_link->net_type = RTW89_NET_TYPE_AD_HOC; ++ rtwvif_link->self_role = RTW89_SELF_ROLE_CLIENT; + break; + case NL80211_IFTYPE_STATION: + if (assoc) { +- rtwvif->net_type = RTW89_NET_TYPE_INFRA; +- rtwvif->trigger = vif->bss_conf.he_support; ++ rtwvif_link->net_type = RTW89_NET_TYPE_INFRA; ++ rtwvif_link->trigger = vif->bss_conf.he_support; + } else { +- rtwvif->net_type = RTW89_NET_TYPE_NO_LINK; +- rtwvif->trigger = false; ++ rtwvif_link->net_type = RTW89_NET_TYPE_NO_LINK; ++ rtwvif_link->trigger = false; + } +- rtwvif->self_role = RTW89_SELF_ROLE_CLIENT; +- rtwvif->addr_cam.sec_ent_mode = RTW89_ADDR_CAM_SEC_NORMAL; ++ rtwvif_link->self_role = RTW89_SELF_ROLE_CLIENT; ++ rtwvif_link->addr_cam.sec_ent_mode = RTW89_ADDR_CAM_SEC_NORMAL; + break; + case NL80211_IFTYPE_MONITOR: + break; +@@ -3456,7 +3458,7 @@ int rtw89_core_sta_add(struct rtw89_dev *rtwdev, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta) + { +- struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; ++ struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv; + struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv; + struct rtw89_hal *hal = &rtwdev->hal; + u8 ant_num = hal->ant_diversity ? 2 : rtwdev->chip->rf_path_num; +@@ -3464,7 +3466,7 @@ int rtw89_core_sta_add(struct rtw89_dev *rtwdev, + int ret; + + rtwsta->rtwdev = rtwdev; +- rtwsta->rtwvif = rtwvif; ++ rtwsta->rtwvif_link = rtwvif_link; + rtwsta->prev_rssi = 0; + INIT_LIST_HEAD(&rtwsta->ba_cam_list); + skb_queue_head_init(&rtwsta->roc_queue); +@@ -3483,16 +3485,16 @@ int rtw89_core_sta_add(struct rtw89_dev *rtwdev, + + if (vif->type == NL80211_IFTYPE_STATION && !sta->tdls) { + /* for station mode, assign the mac_id from itself */ +- rtwsta->mac_id = rtwvif->mac_id; ++ rtwsta->mac_id = rtwvif_link->mac_id; + + /* must do rtw89_reg_6ghz_recalc() before rfk channel */ +- ret = rtw89_reg_6ghz_recalc(rtwdev, rtwvif, true); ++ ret = rtw89_reg_6ghz_recalc(rtwdev, rtwvif_link, true); + if (ret) + return ret; + +- rtw89_btc_ntfy_role_info(rtwdev, rtwvif, rtwsta, ++ rtw89_btc_ntfy_role_info(rtwdev, rtwvif_link, rtwsta, + BTC_ROLE_MSTS_STA_CONN_START); +- rtw89_chip_rfk_channel(rtwdev, rtwvif); ++ rtw89_chip_rfk_channel(rtwdev, rtwvif_link); + } else if (vif->type == NL80211_IFTYPE_AP || sta->tdls) { + rtwsta->mac_id = rtw89_acquire_mac_id(rtwdev); + if (rtwsta->mac_id == RTW89_MAX_MAC_ID_NUM) +@@ -3505,7 +3507,7 @@ int rtw89_core_sta_add(struct rtw89_dev *rtwdev, + return ret; + } + +- ret = rtw89_fw_h2c_role_maintain(rtwdev, rtwvif, rtwsta, ++ ret = rtw89_fw_h2c_role_maintain(rtwdev, rtwvif_link, rtwsta, + RTW89_ROLE_CREATE); + if (ret) { + rtw89_release_mac_id(rtwdev, rtwsta->mac_id); +@@ -3513,11 +3515,11 @@ int rtw89_core_sta_add(struct rtw89_dev *rtwdev, + return ret; + } + +- ret = rtw89_chip_h2c_default_cmac_tbl(rtwdev, rtwvif, rtwsta); ++ ret = rtw89_chip_h2c_default_cmac_tbl(rtwdev, rtwvif_link, rtwsta); + if (ret) + return ret; + +- ret = rtw89_chip_h2c_default_dmac_tbl(rtwdev, rtwvif, rtwsta); ++ ret = rtw89_chip_h2c_default_dmac_tbl(rtwdev, rtwvif_link, rtwsta); + if (ret) + return ret; + +@@ -3531,7 +3533,7 @@ int rtw89_core_sta_disassoc(struct rtw89_dev *rtwdev, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta) + { +- struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; ++ struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv; + struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv; + + if (vif->type == NL80211_IFTYPE_STATION) +@@ -3539,7 +3541,7 @@ int rtw89_core_sta_disassoc(struct rtw89_dev *rtwdev, + + rtwdev->total_sta_assoc--; + if (sta->tdls) +- rtwvif->tdls_peer--; ++ rtwvif_link->tdls_peer--; + rtwsta->disassoc = true; + + return 0; +@@ -3549,7 +3551,7 @@ int rtw89_core_sta_disconnect(struct rtw89_dev *rtwdev, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta) + { +- struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; ++ struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv; + struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv; + int ret; + +@@ -3566,7 +3568,7 @@ int rtw89_core_sta_disconnect(struct rtw89_dev *rtwdev, + + if (vif->type == NL80211_IFTYPE_STATION && !sta->tdls) { + rtw89_vif_type_mapping(vif, false); +- rtw89_fw_release_general_pkt_list_vif(rtwdev, rtwvif, true); ++ rtw89_fw_release_general_pkt_list_vif(rtwdev, rtwvif_link, true); + } + + ret = rtw89_chip_h2c_assoc_cmac_tbl(rtwdev, vif, sta); +@@ -3575,14 +3577,14 @@ int rtw89_core_sta_disconnect(struct rtw89_dev *rtwdev, + return ret; + } + +- ret = rtw89_fw_h2c_join_info(rtwdev, rtwvif, rtwsta, true); ++ ret = rtw89_fw_h2c_join_info(rtwdev, rtwvif_link, rtwsta, true); + if (ret) { + rtw89_warn(rtwdev, "failed to send h2c join info\n"); + return ret; + } + + /* update cam aid mac_id net_type */ +- ret = rtw89_fw_h2c_cam(rtwdev, rtwvif, rtwsta, NULL); ++ ret = rtw89_fw_h2c_cam(rtwdev, rtwvif_link, rtwsta, NULL); + if (ret) { + rtw89_warn(rtwdev, "failed to send h2c cam\n"); + return ret; +@@ -3595,16 +3597,18 @@ int rtw89_core_sta_assoc(struct rtw89_dev *rtwdev, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta) + { +- struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; ++ struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv; + struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv; +- struct rtw89_bssid_cam_entry *bssid_cam = rtw89_get_bssid_cam_of(rtwvif, rtwsta); ++ struct rtw89_bssid_cam_entry *bssid_cam = rtw89_get_bssid_cam_of(rtwvif_link, ++ rtwsta); + const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, +- rtwvif->chanctx_idx); ++ rtwvif_link->chanctx_idx); + int ret; + + if (vif->type == NL80211_IFTYPE_AP || sta->tdls) { + if (sta->tdls) { +- ret = rtw89_cam_init_bssid_cam(rtwdev, rtwvif, bssid_cam, sta->addr); ++ ret = rtw89_cam_init_bssid_cam(rtwdev, rtwvif_link, bssid_cam, ++ sta->addr); + if (ret) { + rtw89_warn(rtwdev, "failed to send h2c init bssid cam for TDLS\n"); + return ret; +@@ -3624,14 +3628,14 @@ int rtw89_core_sta_assoc(struct rtw89_dev *rtwdev, + return ret; + } + +- ret = rtw89_fw_h2c_join_info(rtwdev, rtwvif, rtwsta, false); ++ ret = rtw89_fw_h2c_join_info(rtwdev, rtwvif_link, rtwsta, false); + if (ret) { + rtw89_warn(rtwdev, "failed to send h2c join info\n"); + return ret; + } + + /* update cam aid mac_id net_type */ +- ret = rtw89_fw_h2c_cam(rtwdev, rtwvif, rtwsta, NULL); ++ ret = rtw89_fw_h2c_cam(rtwdev, rtwvif_link, rtwsta, NULL); + if (ret) { + rtw89_warn(rtwdev, "failed to send h2c cam\n"); + return ret; +@@ -3639,7 +3643,7 @@ int rtw89_core_sta_assoc(struct rtw89_dev *rtwdev, + + rtwdev->total_sta_assoc++; + if (sta->tdls) +- rtwvif->tdls_peer++; ++ rtwvif_link->tdls_peer++; + rtw89_phy_ra_assoc(rtwdev, sta); + rtw89_mac_bf_assoc(rtwdev, vif, sta); + rtw89_mac_bf_monitor_calc(rtwdev, sta, false); +@@ -3651,12 +3655,12 @@ int rtw89_core_sta_assoc(struct rtw89_dev *rtwdev, + !(bss_conf->he_oper.params & IEEE80211_HE_OPERATION_ER_SU_DISABLE)) + rtwsta->er_cap = true; + +- rtw89_btc_ntfy_role_info(rtwdev, rtwvif, rtwsta, ++ rtw89_btc_ntfy_role_info(rtwdev, rtwvif_link, rtwsta, + BTC_ROLE_MSTS_STA_CONN_END); + rtw89_core_get_no_ul_ofdma_htc(rtwdev, &rtwsta->htc_template, chan); +- rtw89_phy_ul_tb_assoc(rtwdev, rtwvif); ++ rtw89_phy_ul_tb_assoc(rtwdev, rtwvif_link); + +- ret = rtw89_fw_h2c_general_pkt(rtwdev, rtwvif, rtwsta->mac_id); ++ ret = rtw89_fw_h2c_general_pkt(rtwdev, rtwvif_link, rtwsta->mac_id); + if (ret) { + rtw89_warn(rtwdev, "failed to send h2c general packet\n"); + return ret; +@@ -3672,18 +3676,18 @@ int rtw89_core_sta_remove(struct rtw89_dev *rtwdev, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta) + { +- struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; ++ struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv; + struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv; + int ret; + + if (vif->type == NL80211_IFTYPE_STATION && !sta->tdls) { +- rtw89_reg_6ghz_recalc(rtwdev, rtwvif, false); +- rtw89_btc_ntfy_role_info(rtwdev, rtwvif, rtwsta, ++ rtw89_reg_6ghz_recalc(rtwdev, rtwvif_link, false); ++ rtw89_btc_ntfy_role_info(rtwdev, rtwvif_link, rtwsta, + BTC_ROLE_MSTS_STA_DIS_CONN); + } else if (vif->type == NL80211_IFTYPE_AP || sta->tdls) { + rtw89_release_mac_id(rtwdev, rtwsta->mac_id); + +- ret = rtw89_fw_h2c_role_maintain(rtwdev, rtwvif, rtwsta, ++ ret = rtw89_fw_h2c_role_maintain(rtwdev, rtwvif_link, rtwsta, + RTW89_ROLE_REMOVE); + if (ret) { + rtw89_warn(rtwdev, "failed to send h2c role info\n"); +@@ -4152,15 +4156,15 @@ static void rtw89_core_ppdu_sts_init(struct rtw89_dev *rtwdev) + void rtw89_core_update_beacon_work(struct work_struct *work) + { + struct rtw89_dev *rtwdev; +- struct rtw89_vif *rtwvif = container_of(work, struct rtw89_vif, +- update_beacon_work); ++ struct rtw89_vif_link *rtwvif_link = container_of(work, struct rtw89_vif_link, ++ update_beacon_work); + +- if (rtwvif->net_type != RTW89_NET_TYPE_AP_MODE) ++ if (rtwvif_link->net_type != RTW89_NET_TYPE_AP_MODE) + return; + +- rtwdev = rtwvif->rtwdev; ++ rtwdev = rtwvif_link->rtwdev; + mutex_lock(&rtwdev->mutex); +- rtw89_chip_h2c_update_beacon(rtwdev, rtwvif); ++ rtw89_chip_h2c_update_beacon(rtwdev, rtwvif_link); + mutex_unlock(&rtwdev->mutex); + } + +@@ -4444,38 +4448,39 @@ void rtw89_core_deinit(struct rtw89_dev *rtwdev) + } + EXPORT_SYMBOL(rtw89_core_deinit); + +-void rtw89_core_scan_start(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, ++void rtw89_core_scan_start(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, + const u8 *mac_addr, bool hw_scan) + { + const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, +- rtwvif->chanctx_idx); ++ rtwvif_link->chanctx_idx); + + rtwdev->scanning = true; + rtw89_leave_lps(rtwdev); + if (hw_scan) + rtw89_leave_ips_by_hwflags(rtwdev); + +- ether_addr_copy(rtwvif->mac_addr, mac_addr); ++ ether_addr_copy(rtwvif_link->mac_addr, mac_addr); + rtw89_btc_ntfy_scan_start(rtwdev, RTW89_PHY_0, chan->band_type); +- rtw89_chip_rfk_scan(rtwdev, rtwvif, true); ++ rtw89_chip_rfk_scan(rtwdev, rtwvif_link, true); + rtw89_hci_recalc_int_mit(rtwdev); + rtw89_phy_config_edcca(rtwdev, true); + +- rtw89_fw_h2c_cam(rtwdev, rtwvif, NULL, mac_addr); ++ rtw89_fw_h2c_cam(rtwdev, rtwvif_link, NULL, mac_addr); + } + + void rtw89_core_scan_complete(struct rtw89_dev *rtwdev, + struct ieee80211_vif *vif, bool hw_scan) + { +- struct rtw89_vif *rtwvif = vif ? (struct rtw89_vif *)vif->drv_priv : NULL; ++ struct rtw89_vif_link *rtwvif_link = ++ vif ? (struct rtw89_vif_link *)vif->drv_priv : NULL; + +- if (!rtwvif) ++ if (!rtwvif_link) + return; + +- ether_addr_copy(rtwvif->mac_addr, vif->addr); +- rtw89_fw_h2c_cam(rtwdev, rtwvif, NULL, NULL); ++ ether_addr_copy(rtwvif_link->mac_addr, vif->addr); ++ rtw89_fw_h2c_cam(rtwdev, rtwvif_link, NULL, NULL); + +- rtw89_chip_rfk_scan(rtwdev, rtwvif, false); ++ rtw89_chip_rfk_scan(rtwdev, rtwvif_link, false); + rtw89_btc_ntfy_scan_finish(rtwdev, RTW89_PHY_0); + rtw89_phy_config_edcca(rtwdev, false); + +@@ -4697,7 +4702,7 @@ static int rtw89_core_register_hw(struct rtw89_dev *rtwdev) + int ret; + int tx_headroom = IEEE80211_HT_CTL_LEN; + +- hw->vif_data_size = sizeof(struct rtw89_vif); ++ hw->vif_data_size = sizeof(struct rtw89_vif_link); + hw->sta_data_size = sizeof(struct rtw89_sta); + hw->txq_data_size = sizeof(struct rtw89_txq); + hw->chanctx_data_size = sizeof(struct rtw89_chanctx_cfg); +diff --git a/drivers/net/wireless/realtek/rtw89/core.h b/drivers/net/wireless/realtek/rtw89/core.h +index 4ed9034fdb464..e897c4f79f06c 100644 +--- a/drivers/net/wireless/realtek/rtw89/core.h ++++ b/drivers/net/wireless/realtek/rtw89/core.h +@@ -3359,7 +3359,7 @@ struct rtw89_sta { + bool disassoc; + bool er_cap; + struct rtw89_dev *rtwdev; +- struct rtw89_vif *rtwvif; ++ struct rtw89_vif_link *rtwvif_link; + struct rtw89_ra_info ra; + struct rtw89_ra_report ra_report; + int max_agg_wait; +@@ -3460,7 +3460,7 @@ struct rtw89_p2p_noa_setter { + u8 noa_index; + }; + +-struct rtw89_vif { ++struct rtw89_vif_link { + struct list_head list; + struct rtw89_dev *rtwdev; + struct rtw89_roc roc; +@@ -3599,11 +3599,11 @@ struct rtw89_chip_ops { + void (*rfk_hw_init)(struct rtw89_dev *rtwdev); + void (*rfk_init)(struct rtw89_dev *rtwdev); + void (*rfk_init_late)(struct rtw89_dev *rtwdev); +- void (*rfk_channel)(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif); ++ void (*rfk_channel)(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link); + void (*rfk_band_changed)(struct rtw89_dev *rtwdev, + enum rtw89_phy_idx phy_idx, + const struct rtw89_chan *chan); +- void (*rfk_scan)(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, ++ void (*rfk_scan)(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, + bool start); + void (*rfk_track)(struct rtw89_dev *rtwdev); + void (*power_trim)(struct rtw89_dev *rtwdev); +@@ -3646,10 +3646,10 @@ struct rtw89_chip_ops { + u32 *tx_en, enum rtw89_sch_tx_sel sel); + int (*resume_sch_tx)(struct rtw89_dev *rtwdev, u8 mac_idx, u32 tx_en); + int (*h2c_dctl_sec_cam)(struct rtw89_dev *rtwdev, +- struct rtw89_vif *rtwvif, ++ struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta *rtwsta); + int (*h2c_default_cmac_tbl)(struct rtw89_dev *rtwdev, +- struct rtw89_vif *rtwvif, ++ struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta *rtwsta); + int (*h2c_assoc_cmac_tbl)(struct rtw89_dev *rtwdev, + struct ieee80211_vif *vif, +@@ -3658,10 +3658,10 @@ struct rtw89_chip_ops { + struct ieee80211_vif *vif, + struct ieee80211_sta *sta); + int (*h2c_default_dmac_tbl)(struct rtw89_dev *rtwdev, +- struct rtw89_vif *rtwvif, ++ struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta *rtwsta); + int (*h2c_update_beacon)(struct rtw89_dev *rtwdev, +- struct rtw89_vif *rtwvif); ++ struct rtw89_vif_link *rtwvif_link); + int (*h2c_ba_cam)(struct rtw89_dev *rtwdev, struct rtw89_sta *rtwsta, + bool valid, struct ieee80211_ampdu_params *params); + +@@ -5408,7 +5408,7 @@ struct rtw89_mcc_policy { + }; + + struct rtw89_mcc_role { +- struct rtw89_vif *rtwvif; ++ struct rtw89_vif_link *rtwvif_link; + struct rtw89_mcc_policy policy; + struct rtw89_mcc_limit limit; + +@@ -5960,21 +5960,21 @@ static inline void rtw89_core_txq_init(struct rtw89_dev *rtwdev, + INIT_LIST_HEAD(&rtwtxq->list); + } + +-static inline struct ieee80211_vif *rtwvif_to_vif(struct rtw89_vif *rtwvif) ++static inline struct ieee80211_vif *rtwvif_to_vif(struct rtw89_vif_link *rtwvif_link) + { +- void *p = rtwvif; ++ void *p = rtwvif_link; + + return container_of(p, struct ieee80211_vif, drv_priv); + } + +-static inline struct ieee80211_vif *rtwvif_to_vif_safe(struct rtw89_vif *rtwvif) ++static inline struct ieee80211_vif *rtwvif_to_vif_safe(struct rtw89_vif_link *rtwvif_link) + { +- return rtwvif ? rtwvif_to_vif(rtwvif) : NULL; ++ return rtwvif_link ? rtwvif_to_vif(rtwvif_link) : NULL; + } + +-static inline struct rtw89_vif *vif_to_rtwvif_safe(struct ieee80211_vif *vif) ++static inline struct rtw89_vif_link *vif_to_rtwvif_safe(struct ieee80211_vif *vif) + { +- return vif ? (struct rtw89_vif *)vif->drv_priv : NULL; ++ return vif ? (struct rtw89_vif_link *)vif->drv_priv : NULL; + } + + static inline struct ieee80211_sta *rtwsta_to_sta(struct rtw89_sta *rtwsta) +@@ -6078,20 +6078,20 @@ enum nl80211_he_ru_alloc rtw89_he_rua_to_ru_alloc(u16 rua) + } + + static inline +-struct rtw89_addr_cam_entry *rtw89_get_addr_cam_of(struct rtw89_vif *rtwvif, ++struct rtw89_addr_cam_entry *rtw89_get_addr_cam_of(struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta *rtwsta) + { + if (rtwsta) { + struct ieee80211_sta *sta = rtwsta_to_sta(rtwsta); + +- if (rtwvif->net_type == RTW89_NET_TYPE_AP_MODE || sta->tdls) ++ if (rtwvif_link->net_type == RTW89_NET_TYPE_AP_MODE || sta->tdls) + return &rtwsta->addr_cam; + } +- return &rtwvif->addr_cam; ++ return &rtwvif_link->addr_cam; + } + + static inline +-struct rtw89_bssid_cam_entry *rtw89_get_bssid_cam_of(struct rtw89_vif *rtwvif, ++struct rtw89_bssid_cam_entry *rtw89_get_bssid_cam_of(struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta *rtwsta) + { + if (rtwsta) { +@@ -6100,7 +6100,7 @@ struct rtw89_bssid_cam_entry *rtw89_get_bssid_cam_of(struct rtw89_vif *rtwvif, + if (sta->tdls) + return &rtwsta->bssid_cam; + } +- return &rtwvif->bssid_cam; ++ return &rtwvif_link->bssid_cam; + } + + static inline +@@ -6160,10 +6160,10 @@ static inline + const struct rtw89_chan *rtw89_scan_chan_get(struct rtw89_dev *rtwdev) + { + struct ieee80211_vif *vif = rtwdev->scan_info.scanning_vif; +- struct rtw89_vif *rtwvif = vif_to_rtwvif_safe(vif); ++ struct rtw89_vif_link *rtwvif_link = vif_to_rtwvif_safe(vif); + +- if (rtwvif) +- return rtw89_chan_get(rtwdev, rtwvif->chanctx_idx); ++ if (rtwvif_link) ++ return rtw89_chan_get(rtwdev, rtwvif_link->chanctx_idx); + else + return rtw89_chan_get(rtwdev, RTW89_CHANCTX_0); + } +@@ -6240,12 +6240,12 @@ static inline void rtw89_chip_rfk_init_late(struct rtw89_dev *rtwdev) + } + + static inline void rtw89_chip_rfk_channel(struct rtw89_dev *rtwdev, +- struct rtw89_vif *rtwvif) ++ struct rtw89_vif_link *rtwvif_link) + { + const struct rtw89_chip_info *chip = rtwdev->chip; + + if (chip->ops->rfk_channel) +- chip->ops->rfk_channel(rtwdev, rtwvif); ++ chip->ops->rfk_channel(rtwdev, rtwvif_link); + } + + static inline void rtw89_chip_rfk_band_changed(struct rtw89_dev *rtwdev, +@@ -6259,12 +6259,12 @@ static inline void rtw89_chip_rfk_band_changed(struct rtw89_dev *rtwdev, + } + + static inline void rtw89_chip_rfk_scan(struct rtw89_dev *rtwdev, +- struct rtw89_vif *rtwvif, bool start) ++ struct rtw89_vif_link *rtwvif_link, bool start) + { + const struct rtw89_chip_info *chip = rtwdev->chip; + + if (chip->ops->rfk_scan) +- chip->ops->rfk_scan(rtwdev, rtwvif, start); ++ chip->ops->rfk_scan(rtwdev, rtwvif_link, start); + } + + static inline void rtw89_chip_rfk_track(struct rtw89_dev *rtwdev) +@@ -6351,14 +6351,14 @@ static inline + void rtw89_chip_cfg_txpwr_ul_tb_offset(struct rtw89_dev *rtwdev, + struct ieee80211_vif *vif) + { +- struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; ++ struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv; + const struct rtw89_chip_info *chip = rtwdev->chip; + + if (!vif->bss_conf.he_support || !vif->cfg.assoc) + return; + + if (chip->ops->set_txpwr_ul_tb_offset) +- chip->ops->set_txpwr_ul_tb_offset(rtwdev, 0, rtwvif->mac_idx); ++ chip->ops->set_txpwr_ul_tb_offset(rtwdev, 0, rtwvif_link->mac_idx); + } + + static inline void rtw89_chip_digital_pwr_comp(struct rtw89_dev *rtwdev, +@@ -6457,14 +6457,14 @@ int rtw89_chip_resume_sch_tx(struct rtw89_dev *rtwdev, u8 mac_idx, u32 tx_en) + + static inline + int rtw89_chip_h2c_dctl_sec_cam(struct rtw89_dev *rtwdev, +- struct rtw89_vif *rtwvif, ++ struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta *rtwsta) + { + const struct rtw89_chip_info *chip = rtwdev->chip; + + if (!chip->ops->h2c_dctl_sec_cam) + return 0; +- return chip->ops->h2c_dctl_sec_cam(rtwdev, rtwvif, rtwsta); ++ return chip->ops->h2c_dctl_sec_cam(rtwdev, rtwvif_link, rtwsta); + } + + static inline u8 *get_hdr_bssid(struct ieee80211_hdr *hdr) +@@ -6640,7 +6640,7 @@ void rtw89_get_default_chandef(struct cfg80211_chan_def *chandef); + void rtw89_get_channel_params(const struct cfg80211_chan_def *chandef, + struct rtw89_chan *chan); + int rtw89_set_channel(struct rtw89_dev *rtwdev); +-void rtw89_get_channel(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, ++void rtw89_get_channel(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, + struct rtw89_chan *chan); + u8 rtw89_core_acquire_bit_map(unsigned long *addr, unsigned long size); + void rtw89_core_release_bit_map(unsigned long *addr, u8 bit); +@@ -6665,13 +6665,13 @@ int rtw89_core_start(struct rtw89_dev *rtwdev); + void rtw89_core_stop(struct rtw89_dev *rtwdev); + void rtw89_core_update_beacon_work(struct work_struct *work); + void rtw89_roc_work(struct work_struct *work); +-void rtw89_roc_start(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif); +-void rtw89_roc_end(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif); +-void rtw89_core_scan_start(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, ++void rtw89_roc_start(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link); ++void rtw89_roc_end(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link); ++void rtw89_core_scan_start(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, + const u8 *mac_addr, bool hw_scan); + void rtw89_core_scan_complete(struct rtw89_dev *rtwdev, + struct ieee80211_vif *vif, bool hw_scan); +-int rtw89_reg_6ghz_recalc(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, ++int rtw89_reg_6ghz_recalc(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, + bool active); + void rtw89_core_update_p2p_ps(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif); + void rtw89_core_ntfy_btc_event(struct rtw89_dev *rtwdev, enum rtw89_btc_hmsg event); +diff --git a/drivers/net/wireless/realtek/rtw89/debug.c b/drivers/net/wireless/realtek/rtw89/debug.c +index 29f85210f9196..26327e4b071d2 100644 +--- a/drivers/net/wireless/realtek/rtw89/debug.c ++++ b/drivers/net/wireless/realtek/rtw89/debug.c +@@ -3740,21 +3740,22 @@ static void rtw89_dump_pkt_offload(struct seq_file *m, struct list_head *pkt_lis + static + void rtw89_vif_ids_get_iter(void *data, u8 *mac, struct ieee80211_vif *vif) + { +- struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; +- struct rtw89_dev *rtwdev = rtwvif->rtwdev; ++ struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv; ++ struct rtw89_dev *rtwdev = rtwvif_link->rtwdev; + struct seq_file *m = (struct seq_file *)data; +- struct rtw89_bssid_cam_entry *bssid_cam = &rtwvif->bssid_cam; ++ struct rtw89_bssid_cam_entry *bssid_cam = &rtwvif_link->bssid_cam; + +- seq_printf(m, "VIF [%d] %pM\n", rtwvif->mac_id, rtwvif->mac_addr); ++ seq_printf(m, "VIF [%d] %pM\n", rtwvif_link->mac_id, rtwvif_link->mac_addr); + seq_printf(m, "\tbssid_cam_idx=%u\n", bssid_cam->bssid_cam_idx); +- rtw89_dump_addr_cam(m, rtwdev, &rtwvif->addr_cam); +- rtw89_dump_pkt_offload(m, &rtwvif->general_pkt_list, "\tpkt_ofld[GENERAL]: "); ++ rtw89_dump_addr_cam(m, rtwdev, &rtwvif_link->addr_cam); ++ rtw89_dump_pkt_offload(m, &rtwvif_link->general_pkt_list, ++ "\tpkt_ofld[GENERAL]: "); + } + + static void rtw89_dump_ba_cam(struct seq_file *m, struct rtw89_sta *rtwsta) + { +- struct rtw89_vif *rtwvif = rtwsta->rtwvif; +- struct rtw89_dev *rtwdev = rtwvif->rtwdev; ++ struct rtw89_vif_link *rtwvif_link = rtwsta->rtwvif_link; ++ struct rtw89_dev *rtwdev = rtwvif_link->rtwdev; + struct rtw89_ba_cam_entry *entry; + bool first = true; + +diff --git a/drivers/net/wireless/realtek/rtw89/fw.c b/drivers/net/wireless/realtek/rtw89/fw.c +index d9b0e7ebe619a..1d5de66bf9458 100644 +--- a/drivers/net/wireless/realtek/rtw89/fw.c ++++ b/drivers/net/wireless/realtek/rtw89/fw.c +@@ -1741,7 +1741,7 @@ void rtw89_fw_log_dump(struct rtw89_dev *rtwdev, u8 *buf, u32 len) + } + + #define H2C_CAM_LEN 60 +-int rtw89_fw_h2c_cam(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, ++int rtw89_fw_h2c_cam(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta *rtwsta, const u8 *scan_mac_addr) + { + struct sk_buff *skb; +@@ -1753,8 +1753,9 @@ int rtw89_fw_h2c_cam(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, + return -ENOMEM; + } + skb_put(skb, H2C_CAM_LEN); +- rtw89_cam_fill_addr_cam_info(rtwdev, rtwvif, rtwsta, scan_mac_addr, skb->data); +- rtw89_cam_fill_bssid_cam_info(rtwdev, rtwvif, rtwsta, skb->data); ++ rtw89_cam_fill_addr_cam_info(rtwdev, rtwvif_link, rtwsta, scan_mac_addr, ++ skb->data); ++ rtw89_cam_fill_bssid_cam_info(rtwdev, rtwvif_link, rtwsta, skb->data); + + rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C, + H2C_CAT_MAC, +@@ -1776,7 +1777,7 @@ int rtw89_fw_h2c_cam(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, + } + + int rtw89_fw_h2c_dctl_sec_cam_v1(struct rtw89_dev *rtwdev, +- struct rtw89_vif *rtwvif, ++ struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta *rtwsta) + { + struct rtw89_h2c_dctlinfo_ud_v1 *h2c; +@@ -1792,7 +1793,7 @@ int rtw89_fw_h2c_dctl_sec_cam_v1(struct rtw89_dev *rtwdev, + skb_put(skb, len); + h2c = (struct rtw89_h2c_dctlinfo_ud_v1 *)skb->data; + +- rtw89_cam_fill_dctl_sec_cam_info_v1(rtwdev, rtwvif, rtwsta, h2c); ++ rtw89_cam_fill_dctl_sec_cam_info_v1(rtwdev, rtwvif_link, rtwsta, h2c); + + rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C, + H2C_CAT_MAC, +@@ -1815,7 +1816,7 @@ int rtw89_fw_h2c_dctl_sec_cam_v1(struct rtw89_dev *rtwdev, + EXPORT_SYMBOL(rtw89_fw_h2c_dctl_sec_cam_v1); + + int rtw89_fw_h2c_dctl_sec_cam_v2(struct rtw89_dev *rtwdev, +- struct rtw89_vif *rtwvif, ++ struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta *rtwsta) + { + struct rtw89_h2c_dctlinfo_ud_v2 *h2c; +@@ -1831,7 +1832,7 @@ int rtw89_fw_h2c_dctl_sec_cam_v2(struct rtw89_dev *rtwdev, + skb_put(skb, len); + h2c = (struct rtw89_h2c_dctlinfo_ud_v2 *)skb->data; + +- rtw89_cam_fill_dctl_sec_cam_info_v2(rtwdev, rtwvif, rtwsta, h2c); ++ rtw89_cam_fill_dctl_sec_cam_info_v2(rtwdev, rtwvif_link, rtwsta, h2c); + + rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C, + H2C_CAT_MAC, +@@ -1854,10 +1855,10 @@ int rtw89_fw_h2c_dctl_sec_cam_v2(struct rtw89_dev *rtwdev, + EXPORT_SYMBOL(rtw89_fw_h2c_dctl_sec_cam_v2); + + int rtw89_fw_h2c_default_dmac_tbl_v2(struct rtw89_dev *rtwdev, +- struct rtw89_vif *rtwvif, ++ struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta *rtwsta) + { +- u8 mac_id = rtwsta ? rtwsta->mac_id : rtwvif->mac_id; ++ u8 mac_id = rtwsta ? rtwsta->mac_id : rtwvif_link->mac_id; + struct rtw89_h2c_dctlinfo_ud_v2 *h2c; + u32 len = sizeof(*h2c); + struct sk_buff *skb; +@@ -1912,7 +1913,7 @@ int rtw89_fw_h2c_ba_cam(struct rtw89_dev *rtwdev, struct rtw89_sta *rtwsta, + bool valid, struct ieee80211_ampdu_params *params) + { + const struct rtw89_chip_info *chip = rtwdev->chip; +- struct rtw89_vif *rtwvif = rtwsta->rtwvif; ++ struct rtw89_vif_link *rtwvif_link = rtwsta->rtwvif_link; + struct rtw89_h2c_ba_cam *h2c; + u8 macid = rtwsta->mac_id; + u32 len = sizeof(*h2c); +@@ -1960,7 +1961,8 @@ int rtw89_fw_h2c_ba_cam(struct rtw89_dev *rtwdev, struct rtw89_sta *rtwsta, + + if (chip->bacam_ver == RTW89_BACAM_V0_EXT) { + h2c->w1 |= le32_encode_bits(1, RTW89_H2C_BA_CAM_W1_STD_EN) | +- le32_encode_bits(rtwvif->mac_idx, RTW89_H2C_BA_CAM_W1_BAND); ++ le32_encode_bits(rtwvif_link->mac_idx, ++ RTW89_H2C_BA_CAM_W1_BAND); + } + + end: +@@ -2043,7 +2045,7 @@ int rtw89_fw_h2c_ba_cam_v1(struct rtw89_dev *rtwdev, struct rtw89_sta *rtwsta, + bool valid, struct ieee80211_ampdu_params *params) + { + const struct rtw89_chip_info *chip = rtwdev->chip; +- struct rtw89_vif *rtwvif = rtwsta->rtwvif; ++ struct rtw89_vif_link *rtwvif_link = rtwsta->rtwvif_link; + struct rtw89_h2c_ba_cam_v1 *h2c; + u8 macid = rtwsta->mac_id; + u32 len = sizeof(*h2c); +@@ -2092,7 +2094,8 @@ int rtw89_fw_h2c_ba_cam_v1(struct rtw89_dev *rtwdev, struct rtw89_sta *rtwsta, + entry_idx += chip->bacam_dynamic_num; /* std entry right after dynamic ones */ + h2c->w1 = le32_encode_bits(entry_idx, RTW89_H2C_BA_CAM_V1_W1_ENTRY_IDX_MASK) | + le32_encode_bits(1, RTW89_H2C_BA_CAM_V1_W1_STD_ENTRY_EN) | +- le32_encode_bits(!!rtwvif->mac_idx, RTW89_H2C_BA_CAM_V1_W1_BAND_SEL); ++ le32_encode_bits(!!rtwvif_link->mac_idx, ++ RTW89_H2C_BA_CAM_V1_W1_BAND_SEL); + + rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C, + H2C_CAT_MAC, +@@ -2197,11 +2200,11 @@ int rtw89_fw_h2c_fw_log(struct rtw89_dev *rtwdev, bool enable) + } + + static struct sk_buff *rtw89_eapol_get(struct rtw89_dev *rtwdev, +- struct rtw89_vif *rtwvif) ++ struct rtw89_vif_link *rtwvif_link) + { + static const u8 gtkbody[] = {0xAA, 0xAA, 0x03, 0x00, 0x00, 0x00, 0x88, + 0x8E, 0x01, 0x03, 0x00, 0x5F, 0x02, 0x03}; +- struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif); ++ struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif_link); + struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; + u8 sec_hdr_len = rtw89_wow_get_sec_hdr_len(rtwdev); + struct rtw89_wow_param *rtw_wow = &rtwdev->wow; +@@ -2241,9 +2244,9 @@ static struct sk_buff *rtw89_eapol_get(struct rtw89_dev *rtwdev, + } + + static struct sk_buff *rtw89_sa_query_get(struct rtw89_dev *rtwdev, +- struct rtw89_vif *rtwvif) ++ struct rtw89_vif_link *rtwvif_link) + { +- struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif); ++ struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif_link); + struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; + u8 sec_hdr_len = rtw89_wow_get_sec_hdr_len(rtwdev); + struct ieee80211_hdr_3addr *hdr; +@@ -2272,7 +2275,7 @@ static struct sk_buff *rtw89_sa_query_get(struct rtw89_dev *rtwdev, + } + + static struct sk_buff *rtw89_arp_response_get(struct rtw89_dev *rtwdev, +- struct rtw89_vif *rtwvif) ++ struct rtw89_vif_link *rtwvif_link) + { + u8 sec_hdr_len = rtw89_wow_get_sec_hdr_len(rtwdev); + struct rtw89_wow_param *rtw_wow = &rtwdev->wow; +@@ -2295,9 +2298,9 @@ static struct sk_buff *rtw89_arp_response_get(struct rtw89_dev *rtwdev, + fc = cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_FCTL_TODS); + + hdr->frame_control = fc; +- ether_addr_copy(hdr->addr1, rtwvif->bssid); +- ether_addr_copy(hdr->addr2, rtwvif->mac_addr); +- ether_addr_copy(hdr->addr3, rtwvif->bssid); ++ ether_addr_copy(hdr->addr1, rtwvif_link->bssid); ++ ether_addr_copy(hdr->addr2, rtwvif_link->mac_addr); ++ ether_addr_copy(hdr->addr3, rtwvif_link->bssid); + + skb_put_zero(skb, sec_hdr_len); + +@@ -2312,18 +2315,18 @@ static struct sk_buff *rtw89_arp_response_get(struct rtw89_dev *rtwdev, + arp_hdr->ar_pln = 4; + arp_hdr->ar_op = htons(ARPOP_REPLY); + +- ether_addr_copy(arp_skb->sender_hw, rtwvif->mac_addr); +- arp_skb->sender_ip = rtwvif->ip_addr; ++ ether_addr_copy(arp_skb->sender_hw, rtwvif_link->mac_addr); ++ arp_skb->sender_ip = rtwvif_link->ip_addr; + + return skb; + } + + static int rtw89_fw_h2c_add_general_pkt(struct rtw89_dev *rtwdev, +- struct rtw89_vif *rtwvif, ++ struct rtw89_vif_link *rtwvif_link, + enum rtw89_fw_pkt_ofld_type type, + u8 *id) + { +- struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif); ++ struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif_link); + struct rtw89_pktofld_info *info; + struct sk_buff *skb; + int ret; +@@ -2346,13 +2349,13 @@ static int rtw89_fw_h2c_add_general_pkt(struct rtw89_dev *rtwdev, + skb = ieee80211_nullfunc_get(rtwdev->hw, vif, -1, true); + break; + case RTW89_PKT_OFLD_TYPE_EAPOL_KEY: +- skb = rtw89_eapol_get(rtwdev, rtwvif); ++ skb = rtw89_eapol_get(rtwdev, rtwvif_link); + break; + case RTW89_PKT_OFLD_TYPE_SA_QUERY: +- skb = rtw89_sa_query_get(rtwdev, rtwvif); ++ skb = rtw89_sa_query_get(rtwdev, rtwvif_link); + break; + case RTW89_PKT_OFLD_TYPE_ARP_RSP: +- skb = rtw89_arp_response_get(rtwdev, rtwvif); ++ skb = rtw89_arp_response_get(rtwdev, rtwvif_link); + break; + default: + goto err; +@@ -2367,7 +2370,7 @@ static int rtw89_fw_h2c_add_general_pkt(struct rtw89_dev *rtwdev, + if (ret) + goto err; + +- list_add_tail(&info->list, &rtwvif->general_pkt_list); ++ list_add_tail(&info->list, &rtwvif_link->general_pkt_list); + *id = info->id; + return 0; + +@@ -2377,9 +2380,10 @@ static int rtw89_fw_h2c_add_general_pkt(struct rtw89_dev *rtwdev, + } + + void rtw89_fw_release_general_pkt_list_vif(struct rtw89_dev *rtwdev, +- struct rtw89_vif *rtwvif, bool notify_fw) ++ struct rtw89_vif_link *rtwvif_link, ++ bool notify_fw) + { +- struct list_head *pkt_list = &rtwvif->general_pkt_list; ++ struct list_head *pkt_list = &rtwvif_link->general_pkt_list; + struct rtw89_pktofld_info *info, *tmp; + + list_for_each_entry_safe(info, tmp, pkt_list, list) { +@@ -2394,16 +2398,16 @@ void rtw89_fw_release_general_pkt_list_vif(struct rtw89_dev *rtwdev, + + void rtw89_fw_release_general_pkt_list(struct rtw89_dev *rtwdev, bool notify_fw) + { +- struct rtw89_vif *rtwvif; ++ struct rtw89_vif_link *rtwvif_link; + +- rtw89_for_each_rtwvif(rtwdev, rtwvif) +- rtw89_fw_release_general_pkt_list_vif(rtwdev, rtwvif, notify_fw); ++ rtw89_for_each_rtwvif(rtwdev, rtwvif_link) ++ rtw89_fw_release_general_pkt_list_vif(rtwdev, rtwvif_link, notify_fw); + } + + #define H2C_GENERAL_PKT_LEN 6 + #define H2C_GENERAL_PKT_ID_UND 0xff + int rtw89_fw_h2c_general_pkt(struct rtw89_dev *rtwdev, +- struct rtw89_vif *rtwvif, u8 macid) ++ struct rtw89_vif_link *rtwvif_link, u8 macid) + { + u8 pkt_id_ps_poll = H2C_GENERAL_PKT_ID_UND; + u8 pkt_id_null = H2C_GENERAL_PKT_ID_UND; +@@ -2411,11 +2415,11 @@ int rtw89_fw_h2c_general_pkt(struct rtw89_dev *rtwdev, + struct sk_buff *skb; + int ret; + +- rtw89_fw_h2c_add_general_pkt(rtwdev, rtwvif, ++ rtw89_fw_h2c_add_general_pkt(rtwdev, rtwvif_link, + RTW89_PKT_OFLD_TYPE_PS_POLL, &pkt_id_ps_poll); +- rtw89_fw_h2c_add_general_pkt(rtwdev, rtwvif, ++ rtw89_fw_h2c_add_general_pkt(rtwdev, rtwvif_link, + RTW89_PKT_OFLD_TYPE_NULL_DATA, &pkt_id_null); +- rtw89_fw_h2c_add_general_pkt(rtwdev, rtwvif, ++ rtw89_fw_h2c_add_general_pkt(rtwdev, rtwvif_link, + RTW89_PKT_OFLD_TYPE_QOS_NULL, &pkt_id_qos_null); + + skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, H2C_GENERAL_PKT_LEN); +@@ -2494,10 +2498,10 @@ int rtw89_fw_h2c_lps_parm(struct rtw89_dev *rtwdev, + return ret; + } + +-int rtw89_fw_h2c_lps_ch_info(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif) ++int rtw89_fw_h2c_lps_ch_info(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link) + { + const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, +- rtwvif->chanctx_idx); ++ rtwvif_link->chanctx_idx); + const struct rtw89_chip_info *chip = rtwdev->chip; + struct rtw89_h2c_lps_ch_info *h2c; + u32 len = sizeof(*h2c); +@@ -2550,8 +2554,8 @@ int rtw89_fw_h2c_p2p_act(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif, + struct ieee80211_p2p_noa_desc *desc, + u8 act, u8 noa_id) + { +- struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; +- bool p2p_type_gc = rtwvif->wifi_role == RTW89_WIFI_ROLE_P2P_CLIENT; ++ struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv; ++ bool p2p_type_gc = rtwvif_link->wifi_role == RTW89_WIFI_ROLE_P2P_CLIENT; + u8 ctwindow_oppps = vif->bss_conf.p2p_noa_attr.oppps_ctwindow; + struct sk_buff *skb; + u8 *cmd; +@@ -2565,7 +2569,7 @@ int rtw89_fw_h2c_p2p_act(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif, + skb_put(skb, H2C_P2P_ACT_LEN); + cmd = skb->data; + +- RTW89_SET_FWCMD_P2P_MACID(cmd, rtwvif->mac_id); ++ RTW89_SET_FWCMD_P2P_MACID(cmd, rtwvif_link->mac_id); + RTW89_SET_FWCMD_P2P_P2PID(cmd, 0); + RTW89_SET_FWCMD_P2P_NOAID(cmd, noa_id); + RTW89_SET_FWCMD_P2P_ACT(cmd, act); +@@ -2622,11 +2626,11 @@ static void __rtw89_fw_h2c_set_tx_path(struct rtw89_dev *rtwdev, + + #define H2C_CMC_TBL_LEN 68 + int rtw89_fw_h2c_default_cmac_tbl(struct rtw89_dev *rtwdev, +- struct rtw89_vif *rtwvif, ++ struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta *rtwsta) + { + const struct rtw89_chip_info *chip = rtwdev->chip; +- u8 macid = rtwsta ? rtwsta->mac_id : rtwvif->mac_id; ++ u8 macid = rtwsta ? rtwsta->mac_id : rtwvif_link->mac_id; + struct sk_buff *skb; + int ret; + +@@ -2648,7 +2652,7 @@ int rtw89_fw_h2c_default_cmac_tbl(struct rtw89_dev *rtwdev, + } + SET_CMC_TBL_DOPPLER_CTRL(skb->data, 0); + SET_CMC_TBL_TXPWR_TOLERENCE(skb->data, 0); +- if (rtwvif->net_type == RTW89_NET_TYPE_AP_MODE) ++ if (rtwvif_link->net_type == RTW89_NET_TYPE_AP_MODE) + SET_CMC_TBL_DATA_DCM(skb->data, 0); + + rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C, +@@ -2671,10 +2675,10 @@ int rtw89_fw_h2c_default_cmac_tbl(struct rtw89_dev *rtwdev, + EXPORT_SYMBOL(rtw89_fw_h2c_default_cmac_tbl); + + int rtw89_fw_h2c_default_cmac_tbl_g7(struct rtw89_dev *rtwdev, +- struct rtw89_vif *rtwvif, ++ struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta *rtwsta) + { +- u8 mac_id = rtwsta ? rtwsta->mac_id : rtwvif->mac_id; ++ u8 mac_id = rtwsta ? rtwsta->mac_id : rtwvif_link->mac_id; + struct rtw89_h2c_cctlinfo_ud_g7 *h2c; + u32 len = sizeof(*h2c); + struct sk_buff *skb; +@@ -2814,12 +2818,12 @@ int rtw89_fw_h2c_assoc_cmac_tbl(struct rtw89_dev *rtwdev, + { + const struct rtw89_chip_info *chip = rtwdev->chip; + struct rtw89_sta *rtwsta = sta_to_rtwsta_safe(sta); +- struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; ++ struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv; + const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, +- rtwvif->chanctx_idx); ++ rtwvif_link->chanctx_idx); + struct sk_buff *skb; + u8 pads[RTW89_PPE_BW_NUM]; +- u8 mac_id = rtwsta ? rtwsta->mac_id : rtwvif->mac_id; ++ u8 mac_id = rtwsta ? rtwsta->mac_id : rtwvif_link->mac_id; + u16 lowest_rate; + int ret; + +@@ -2851,7 +2855,7 @@ int rtw89_fw_h2c_assoc_cmac_tbl(struct rtw89_dev *rtwdev, + SET_CMC_TBL_ULDL(skb->data, 1); + else + SET_CMC_TBL_ULDL(skb->data, 0); +- SET_CMC_TBL_MULTI_PORT_ID(skb->data, rtwvif->port); ++ SET_CMC_TBL_MULTI_PORT_ID(skb->data, rtwvif_link->port); + if (chip->h2c_cctl_func_id == H2C_FUNC_MAC_CCTLINFO_UD_V1) { + SET_CMC_TBL_NOMINAL_PKT_PADDING_V1(skb->data, pads[RTW89_CHANNEL_WIDTH_20]); + SET_CMC_TBL_NOMINAL_PKT_PADDING40_V1(skb->data, pads[RTW89_CHANNEL_WIDTH_40]); +@@ -2866,7 +2870,7 @@ int rtw89_fw_h2c_assoc_cmac_tbl(struct rtw89_dev *rtwdev, + if (sta) + SET_CMC_TBL_BSR_QUEUE_SIZE_FORMAT(skb->data, + sta->deflink.he_cap.has_he); +- if (rtwvif->net_type == RTW89_NET_TYPE_AP_MODE) ++ if (rtwvif_link->net_type == RTW89_NET_TYPE_AP_MODE) + SET_CMC_TBL_DATA_DCM(skb->data, 0); + + rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C, +@@ -2949,10 +2953,10 @@ int rtw89_fw_h2c_assoc_cmac_tbl_g7(struct rtw89_dev *rtwdev, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta) + { +- struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; ++ struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv; + struct rtw89_sta *rtwsta = sta_to_rtwsta_safe(sta); +- const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, rtwvif->chanctx_idx); +- u8 mac_id = rtwsta ? rtwsta->mac_id : rtwvif->mac_id; ++ const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, rtwvif_link->chanctx_idx); ++ u8 mac_id = rtwsta ? rtwsta->mac_id : rtwvif_link->mac_id; + struct rtw89_h2c_cctlinfo_ud_g7 *h2c; + u8 pads[RTW89_PPE_BW_NUM]; + u32 len = sizeof(*h2c); +@@ -3000,10 +3004,10 @@ int rtw89_fw_h2c_assoc_cmac_tbl_g7(struct rtw89_dev *rtwdev, + h2c->w3 = le32_encode_bits(0, CCTLINFO_G7_W3_RTS_TXCNT_LMT_SEL); + h2c->m3 = cpu_to_le32(CCTLINFO_G7_W3_RTS_TXCNT_LMT_SEL); + +- h2c->w4 = le32_encode_bits(rtwvif->port, CCTLINFO_G7_W4_MULTI_PORT_ID); ++ h2c->w4 = le32_encode_bits(rtwvif_link->port, CCTLINFO_G7_W4_MULTI_PORT_ID); + h2c->m4 = cpu_to_le32(CCTLINFO_G7_W4_MULTI_PORT_ID); + +- if (rtwvif->net_type == RTW89_NET_TYPE_AP_MODE) { ++ if (rtwvif_link->net_type == RTW89_NET_TYPE_AP_MODE) { + h2c->w4 |= le32_encode_bits(0, CCTLINFO_G7_W4_DATA_DCM); + h2c->m4 |= cpu_to_le32(CCTLINFO_G7_W4_DATA_DCM); + } +@@ -3209,11 +3213,11 @@ int rtw89_fw_h2c_txpath_cmac_tbl(struct rtw89_dev *rtwdev, + } + + int rtw89_fw_h2c_update_beacon(struct rtw89_dev *rtwdev, +- struct rtw89_vif *rtwvif) ++ struct rtw89_vif_link *rtwvif_link) + { + const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, +- rtwvif->chanctx_idx); +- struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif); ++ rtwvif_link->chanctx_idx); ++ struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif_link); + struct rtw89_h2c_bcn_upd *h2c; + struct sk_buff *skb_beacon; + struct ieee80211_hdr *hdr; +@@ -3240,7 +3244,7 @@ int rtw89_fw_h2c_update_beacon(struct rtw89_dev *rtwdev, + return -ENOMEM; + } + +- noa_len = rtw89_p2p_noa_fetch(rtwvif, &noa_data); ++ noa_len = rtw89_p2p_noa_fetch(rtwvif_link, &noa_data); + if (noa_len && + (noa_len <= skb_tailroom(skb_beacon) || + pskb_expand_head(skb_beacon, 0, noa_len, GFP_KERNEL) == 0)) { +@@ -3260,11 +3264,11 @@ int rtw89_fw_h2c_update_beacon(struct rtw89_dev *rtwdev, + skb_put(skb, len); + h2c = (struct rtw89_h2c_bcn_upd *)skb->data; + +- h2c->w0 = le32_encode_bits(rtwvif->port, RTW89_H2C_BCN_UPD_W0_PORT) | ++ h2c->w0 = le32_encode_bits(rtwvif_link->port, RTW89_H2C_BCN_UPD_W0_PORT) | + le32_encode_bits(0, RTW89_H2C_BCN_UPD_W0_MBSSID) | +- le32_encode_bits(rtwvif->mac_idx, RTW89_H2C_BCN_UPD_W0_BAND) | ++ le32_encode_bits(rtwvif_link->mac_idx, RTW89_H2C_BCN_UPD_W0_BAND) | + le32_encode_bits(tim_offset | BIT(7), RTW89_H2C_BCN_UPD_W0_GRP_IE_OFST); +- h2c->w1 = le32_encode_bits(rtwvif->mac_id, RTW89_H2C_BCN_UPD_W1_MACID) | ++ h2c->w1 = le32_encode_bits(rtwvif_link->mac_id, RTW89_H2C_BCN_UPD_W1_MACID) | + le32_encode_bits(RTW89_MGMT_HW_SSN_SEL, RTW89_H2C_BCN_UPD_W1_SSN_SEL) | + le32_encode_bits(RTW89_MGMT_HW_SEQ_MODE, RTW89_H2C_BCN_UPD_W1_SSN_MODE) | + le32_encode_bits(beacon_rate, RTW89_H2C_BCN_UPD_W1_RATE); +@@ -3289,10 +3293,10 @@ int rtw89_fw_h2c_update_beacon(struct rtw89_dev *rtwdev, + EXPORT_SYMBOL(rtw89_fw_h2c_update_beacon); + + int rtw89_fw_h2c_update_beacon_be(struct rtw89_dev *rtwdev, +- struct rtw89_vif *rtwvif) ++ struct rtw89_vif_link *rtwvif_link) + { +- const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, rtwvif->chanctx_idx); +- struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif); ++ const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, rtwvif_link->chanctx_idx); ++ struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif_link); + struct rtw89_h2c_bcn_upd_be *h2c; + struct sk_buff *skb_beacon; + struct ieee80211_hdr *hdr; +@@ -3319,7 +3323,7 @@ int rtw89_fw_h2c_update_beacon_be(struct rtw89_dev *rtwdev, + return -ENOMEM; + } + +- noa_len = rtw89_p2p_noa_fetch(rtwvif, &noa_data); ++ noa_len = rtw89_p2p_noa_fetch(rtwvif_link, &noa_data); + if (noa_len && + (noa_len <= skb_tailroom(skb_beacon) || + pskb_expand_head(skb_beacon, 0, noa_len, GFP_KERNEL) == 0)) { +@@ -3339,11 +3343,11 @@ int rtw89_fw_h2c_update_beacon_be(struct rtw89_dev *rtwdev, + skb_put(skb, len); + h2c = (struct rtw89_h2c_bcn_upd_be *)skb->data; + +- h2c->w0 = le32_encode_bits(rtwvif->port, RTW89_H2C_BCN_UPD_BE_W0_PORT) | ++ h2c->w0 = le32_encode_bits(rtwvif_link->port, RTW89_H2C_BCN_UPD_BE_W0_PORT) | + le32_encode_bits(0, RTW89_H2C_BCN_UPD_BE_W0_MBSSID) | +- le32_encode_bits(rtwvif->mac_idx, RTW89_H2C_BCN_UPD_BE_W0_BAND) | ++ le32_encode_bits(rtwvif_link->mac_idx, RTW89_H2C_BCN_UPD_BE_W0_BAND) | + le32_encode_bits(tim_offset | BIT(7), RTW89_H2C_BCN_UPD_BE_W0_GRP_IE_OFST); +- h2c->w1 = le32_encode_bits(rtwvif->mac_id, RTW89_H2C_BCN_UPD_BE_W1_MACID) | ++ h2c->w1 = le32_encode_bits(rtwvif_link->mac_id, RTW89_H2C_BCN_UPD_BE_W1_MACID) | + le32_encode_bits(RTW89_MGMT_HW_SSN_SEL, RTW89_H2C_BCN_UPD_BE_W1_SSN_SEL) | + le32_encode_bits(RTW89_MGMT_HW_SEQ_MODE, RTW89_H2C_BCN_UPD_BE_W1_SSN_MODE) | + le32_encode_bits(beacon_rate, RTW89_H2C_BCN_UPD_BE_W1_RATE); +@@ -3373,22 +3377,22 @@ EXPORT_SYMBOL(rtw89_fw_h2c_update_beacon_be); + + #define H2C_ROLE_MAINTAIN_LEN 4 + int rtw89_fw_h2c_role_maintain(struct rtw89_dev *rtwdev, +- struct rtw89_vif *rtwvif, ++ struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta *rtwsta, + enum rtw89_upd_mode upd_mode) + { + struct sk_buff *skb; +- u8 mac_id = rtwsta ? rtwsta->mac_id : rtwvif->mac_id; ++ u8 mac_id = rtwsta ? rtwsta->mac_id : rtwvif_link->mac_id; + u8 self_role; + int ret; + +- if (rtwvif->net_type == RTW89_NET_TYPE_AP_MODE) { ++ if (rtwvif_link->net_type == RTW89_NET_TYPE_AP_MODE) { + if (rtwsta) + self_role = RTW89_SELF_ROLE_AP_CLIENT; + else +- self_role = rtwvif->self_role; ++ self_role = rtwvif_link->self_role; + } else { +- self_role = rtwvif->self_role; ++ self_role = rtwvif_link->self_role; + } + + skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, H2C_ROLE_MAINTAIN_LEN); +@@ -3400,7 +3404,7 @@ int rtw89_fw_h2c_role_maintain(struct rtw89_dev *rtwdev, + SET_FWROLE_MAINTAIN_MACID(skb->data, mac_id); + SET_FWROLE_MAINTAIN_SELF_ROLE(skb->data, self_role); + SET_FWROLE_MAINTAIN_UPD_MODE(skb->data, upd_mode); +- SET_FWROLE_MAINTAIN_WIFI_ROLE(skb->data, rtwvif->wifi_role); ++ SET_FWROLE_MAINTAIN_WIFI_ROLE(skb->data, rtwvif_link->wifi_role); + + rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C, + H2C_CAT_MAC, H2C_CL_MAC_MEDIA_RPT, +@@ -3421,11 +3425,11 @@ int rtw89_fw_h2c_role_maintain(struct rtw89_dev *rtwdev, + } + + static enum rtw89_fw_sta_type +-rtw89_fw_get_sta_type(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, ++rtw89_fw_get_sta_type(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta *rtwsta) + { + struct ieee80211_sta *sta = rtwsta_to_sta_safe(rtwsta); +- struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif); ++ struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif_link); + + if (!sta) + goto by_vif; +@@ -3446,14 +3450,14 @@ rtw89_fw_get_sta_type(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, + return RTW89_FW_N_AC_STA; + } + +-int rtw89_fw_h2c_join_info(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, ++int rtw89_fw_h2c_join_info(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta *rtwsta, bool dis_conn) + { + struct sk_buff *skb; +- u8 mac_id = rtwsta ? rtwsta->mac_id : rtwvif->mac_id; +- u8 self_role = rtwvif->self_role; ++ u8 mac_id = rtwsta ? rtwsta->mac_id : rtwvif_link->mac_id; ++ u8 self_role = rtwvif_link->self_role; + enum rtw89_fw_sta_type sta_type; +- u8 net_type = rtwvif->net_type; ++ u8 net_type = rtwvif_link->net_type; + struct rtw89_h2c_join_v1 *h2c_v1; + struct rtw89_h2c_join *h2c; + u32 len = sizeof(*h2c); +@@ -3480,16 +3484,17 @@ int rtw89_fw_h2c_join_info(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, + + h2c->w0 = le32_encode_bits(mac_id, RTW89_H2C_JOININFO_W0_MACID) | + le32_encode_bits(dis_conn, RTW89_H2C_JOININFO_W0_OP) | +- le32_encode_bits(rtwvif->mac_idx, RTW89_H2C_JOININFO_W0_BAND) | +- le32_encode_bits(rtwvif->wmm, RTW89_H2C_JOININFO_W0_WMM) | +- le32_encode_bits(rtwvif->trigger, RTW89_H2C_JOININFO_W0_TGR) | ++ le32_encode_bits(rtwvif_link->mac_idx, RTW89_H2C_JOININFO_W0_BAND) | ++ le32_encode_bits(rtwvif_link->wmm, RTW89_H2C_JOININFO_W0_WMM) | ++ le32_encode_bits(rtwvif_link->trigger, RTW89_H2C_JOININFO_W0_TGR) | + le32_encode_bits(0, RTW89_H2C_JOININFO_W0_ISHESTA) | + le32_encode_bits(0, RTW89_H2C_JOININFO_W0_DLBW) | + le32_encode_bits(0, RTW89_H2C_JOININFO_W0_TF_MAC_PAD) | + le32_encode_bits(0, RTW89_H2C_JOININFO_W0_DL_T_PE) | +- le32_encode_bits(rtwvif->port, RTW89_H2C_JOININFO_W0_PORT_ID) | ++ le32_encode_bits(rtwvif_link->port, RTW89_H2C_JOININFO_W0_PORT_ID) | + le32_encode_bits(net_type, RTW89_H2C_JOININFO_W0_NET_TYPE) | +- le32_encode_bits(rtwvif->wifi_role, RTW89_H2C_JOININFO_W0_WIFI_ROLE) | ++ le32_encode_bits(rtwvif_link->wifi_role, ++ RTW89_H2C_JOININFO_W0_WIFI_ROLE) | + le32_encode_bits(self_role, RTW89_H2C_JOININFO_W0_SELF_ROLE); + + if (!format_v1) +@@ -3497,7 +3502,7 @@ int rtw89_fw_h2c_join_info(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, + + h2c_v1 = (struct rtw89_h2c_join_v1 *)skb->data; + +- sta_type = rtw89_fw_get_sta_type(rtwdev, rtwvif, rtwsta); ++ sta_type = rtw89_fw_get_sta_type(rtwdev, rtwvif_link, rtwsta); + + h2c_v1->w1 = le32_encode_bits(sta_type, RTW89_H2C_JOININFO_W1_STA_TYPE); + h2c_v1->w2 = 0; +@@ -3618,7 +3623,7 @@ int rtw89_fw_h2c_macid_pause(struct rtw89_dev *rtwdev, u8 sh, u8 grp, + } + + #define H2C_EDCA_LEN 12 +-int rtw89_fw_h2c_set_edca(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, ++int rtw89_fw_h2c_set_edca(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, + u8 ac, u32 val) + { + struct sk_buff *skb; +@@ -3631,7 +3636,7 @@ int rtw89_fw_h2c_set_edca(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, + } + skb_put(skb, H2C_EDCA_LEN); + RTW89_SET_EDCA_SEL(skb->data, 0); +- RTW89_SET_EDCA_BAND(skb->data, rtwvif->mac_idx); ++ RTW89_SET_EDCA_BAND(skb->data, rtwvif_link->mac_idx); + RTW89_SET_EDCA_WMM(skb->data, 0); + RTW89_SET_EDCA_AC(skb->data, ac); + RTW89_SET_EDCA_PARAM(skb->data, val); +@@ -3655,7 +3660,8 @@ int rtw89_fw_h2c_set_edca(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, + } + + #define H2C_TSF32_TOGL_LEN 4 +-int rtw89_fw_h2c_tsf32_toggle(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, ++int rtw89_fw_h2c_tsf32_toggle(struct rtw89_dev *rtwdev, ++ struct rtw89_vif_link *rtwvif_link, + bool en) + { + struct sk_buff *skb; +@@ -3671,9 +3677,9 @@ int rtw89_fw_h2c_tsf32_toggle(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif + skb_put(skb, H2C_TSF32_TOGL_LEN); + cmd = skb->data; + +- RTW89_SET_FWCMD_TSF32_TOGL_BAND(cmd, rtwvif->mac_idx); ++ RTW89_SET_FWCMD_TSF32_TOGL_BAND(cmd, rtwvif_link->mac_idx); + RTW89_SET_FWCMD_TSF32_TOGL_EN(cmd, en); +- RTW89_SET_FWCMD_TSF32_TOGL_PORT(cmd, rtwvif->port); ++ RTW89_SET_FWCMD_TSF32_TOGL_PORT(cmd, rtwvif_link->port); + RTW89_SET_FWCMD_TSF32_TOGL_EARLY(cmd, early_us); + + rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C, +@@ -3730,7 +3736,7 @@ int rtw89_fw_h2c_set_bcn_fltr_cfg(struct rtw89_dev *rtwdev, + struct ieee80211_vif *vif, + bool connect) + { +- struct rtw89_vif *rtwvif = vif_to_rtwvif_safe(vif); ++ struct rtw89_vif_link *rtwvif_link = vif_to_rtwvif_safe(vif); + struct ieee80211_bss_conf *bss_conf = vif ? &vif->bss_conf : NULL; + s32 thold = RTW89_DEFAULT_CQM_THOLD; + u32 hyst = RTW89_DEFAULT_CQM_HYST; +@@ -3742,7 +3748,7 @@ int rtw89_fw_h2c_set_bcn_fltr_cfg(struct rtw89_dev *rtwdev, + if (!RTW89_CHK_FW_FEATURE(BEACON_FILTER, &rtwdev->fw)) + return -EINVAL; + +- if (!rtwvif || !bss_conf || rtwvif->net_type != RTW89_NET_TYPE_INFRA) ++ if (!rtwvif_link || !bss_conf || rtwvif_link->net_type != RTW89_NET_TYPE_INFRA) + return -EINVAL; + + skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, len); +@@ -3768,7 +3774,7 @@ int rtw89_fw_h2c_set_bcn_fltr_cfg(struct rtw89_dev *rtwdev, + le32_encode_bits(hyst, RTW89_H2C_BCNFLTR_W0_RSSI_HYST) | + le32_encode_bits(thold + MAX_RSSI, + RTW89_H2C_BCNFLTR_W0_RSSI_THRESHOLD) | +- le32_encode_bits(rtwvif->mac_id, RTW89_H2C_BCNFLTR_W0_MAC_ID); ++ le32_encode_bits(rtwvif_link->mac_id, RTW89_H2C_BCNFLTR_W0_MAC_ID); + + rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C, + H2C_CAT_MAC, H2C_CL_MAC_FW_OFLD, +@@ -3833,15 +3839,15 @@ int rtw89_fw_h2c_rssi_offload(struct rtw89_dev *rtwdev, + return ret; + } + +-int rtw89_fw_h2c_tp_offload(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif) ++int rtw89_fw_h2c_tp_offload(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link) + { +- struct rtw89_traffic_stats *stats = &rtwvif->stats; ++ struct rtw89_traffic_stats *stats = &rtwvif_link->stats; + struct rtw89_h2c_ofld *h2c; + u32 len = sizeof(*h2c); + struct sk_buff *skb; + int ret; + +- if (rtwvif->net_type != RTW89_NET_TYPE_INFRA) ++ if (rtwvif_link->net_type != RTW89_NET_TYPE_INFRA) + return -EINVAL; + + skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, len); +@@ -3853,7 +3859,7 @@ int rtw89_fw_h2c_tp_offload(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif) + skb_put(skb, len); + h2c = (struct rtw89_h2c_ofld *)skb->data; + +- h2c->w0 = le32_encode_bits(rtwvif->mac_id, RTW89_H2C_OFLD_W0_MAC_ID) | ++ h2c->w0 = le32_encode_bits(rtwvif_link->mac_id, RTW89_H2C_OFLD_W0_MAC_ID) | + le32_encode_bits(stats->tx_throughput, RTW89_H2C_OFLD_W0_TX_TP) | + le32_encode_bits(stats->rx_throughput, RTW89_H2C_OFLD_W0_RX_TP); + +@@ -4858,7 +4864,7 @@ int rtw89_fw_h2c_scan_list_offload_be(struct rtw89_dev *rtwdev, int ch_num, + #define RTW89_SCAN_DELAY_TSF_UNIT 104800 + int rtw89_fw_h2c_scan_offload_ax(struct rtw89_dev *rtwdev, + struct rtw89_scan_option *option, +- struct rtw89_vif *rtwvif, ++ struct rtw89_vif_link *rtwvif_link, + bool wowlan) + { + struct rtw89_wait_info *wait = &rtwdev->mac.fw_ofld_wait; +@@ -4880,7 +4886,7 @@ int rtw89_fw_h2c_scan_offload_ax(struct rtw89_dev *rtwdev, + h2c = (struct rtw89_h2c_scanofld *)skb->data; + + if (option->delay) { +- ret = rtw89_mac_port_get_tsf(rtwdev, rtwvif, &tsf); ++ ret = rtw89_mac_port_get_tsf(rtwdev, rtwvif_link, &tsf); + if (ret) { + rtw89_warn(rtwdev, "NLO failed to get port tsf: %d\n", ret); + scan_mode = RTW89_SCAN_IMMEDIATE; +@@ -4890,8 +4896,8 @@ int rtw89_fw_h2c_scan_offload_ax(struct rtw89_dev *rtwdev, + } + } + +- h2c->w0 = le32_encode_bits(rtwvif->mac_id, RTW89_H2C_SCANOFLD_W0_MACID) | +- le32_encode_bits(rtwvif->port, RTW89_H2C_SCANOFLD_W0_PORT_ID) | ++ h2c->w0 = le32_encode_bits(rtwvif_link->mac_id, RTW89_H2C_SCANOFLD_W0_MACID) | ++ le32_encode_bits(rtwvif_link->port, RTW89_H2C_SCANOFLD_W0_PORT_ID) | + le32_encode_bits(RTW89_PHY_0, RTW89_H2C_SCANOFLD_W0_BAND) | + le32_encode_bits(option->enable, RTW89_H2C_SCANOFLD_W0_OPERATION); + +@@ -4963,12 +4969,12 @@ static void rtw89_scan_get_6g_disabled_chan(struct rtw89_dev *rtwdev, + + int rtw89_fw_h2c_scan_offload_be(struct rtw89_dev *rtwdev, + struct rtw89_scan_option *option, +- struct rtw89_vif *rtwvif, ++ struct rtw89_vif_link *rtwvif_link, + bool wowlan) + { + struct rtw89_hw_scan_info *scan_info = &rtwdev->scan_info; + struct rtw89_wait_info *wait = &rtwdev->mac.fw_ofld_wait; +- struct cfg80211_scan_request *req = rtwvif->scan_req; ++ struct cfg80211_scan_request *req = rtwvif_link->scan_req; + struct rtw89_h2c_scanofld_be_macc_role *macc_role; + struct rtw89_chan *op = &scan_info->op_chan; + struct rtw89_h2c_scanofld_be_opch *opch; +@@ -5016,8 +5022,8 @@ int rtw89_fw_h2c_scan_offload_be(struct rtw89_dev *rtwdev, + le32_encode_bits(option->repeat, RTW89_H2C_SCANOFLD_BE_W0_REPEAT) | + le32_encode_bits(true, RTW89_H2C_SCANOFLD_BE_W0_NOTIFY_END) | + le32_encode_bits(true, RTW89_H2C_SCANOFLD_BE_W0_LEARN_CH) | +- le32_encode_bits(rtwvif->mac_id, RTW89_H2C_SCANOFLD_BE_W0_MACID) | +- le32_encode_bits(rtwvif->port, RTW89_H2C_SCANOFLD_BE_W0_PORT) | ++ le32_encode_bits(rtwvif_link->mac_id, RTW89_H2C_SCANOFLD_BE_W0_MACID) | ++ le32_encode_bits(rtwvif_link->port, RTW89_H2C_SCANOFLD_BE_W0_PORT) | + le32_encode_bits(option->band, RTW89_H2C_SCANOFLD_BE_W0_BAND); + + h2c->w1 = le32_encode_bits(option->num_macc_role, RTW89_H2C_SCANOFLD_BE_W1_NUM_MACC_ROLE) | +@@ -5082,11 +5088,11 @@ int rtw89_fw_h2c_scan_offload_be(struct rtw89_dev *rtwdev, + + for (i = 0; i < option->num_opch; i++) { + opch = ptr; +- opch->w0 = le32_encode_bits(rtwvif->mac_id, ++ opch->w0 = le32_encode_bits(rtwvif_link->mac_id, + RTW89_H2C_SCANOFLD_BE_OPCH_W0_MACID) | + le32_encode_bits(option->band, + RTW89_H2C_SCANOFLD_BE_OPCH_W0_BAND) | +- le32_encode_bits(rtwvif->port, ++ le32_encode_bits(rtwvif_link->port, + RTW89_H2C_SCANOFLD_BE_OPCH_W0_PORT) | + le32_encode_bits(RTW89_SCAN_OPMODE_INTV, + RTW89_H2C_SCANOFLD_BE_OPCH_W0_POLICY) | +@@ -5871,11 +5877,11 @@ static void rtw89_release_pkt_list(struct rtw89_dev *rtwdev) + } + + static bool rtw89_is_6ghz_wildcard_probe_req(struct rtw89_dev *rtwdev, +- struct rtw89_vif *rtwvif, ++ struct rtw89_vif_link *rtwvif_link, + struct rtw89_pktofld_info *info, + enum nl80211_band band, u8 ssid_idx) + { +- struct cfg80211_scan_request *req = rtwvif->scan_req; ++ struct cfg80211_scan_request *req = rtwvif_link->scan_req; + + if (band != NL80211_BAND_6GHZ) + return false; +@@ -5892,11 +5898,11 @@ static bool rtw89_is_6ghz_wildcard_probe_req(struct rtw89_dev *rtwdev, + } + + static int rtw89_append_probe_req_ie(struct rtw89_dev *rtwdev, +- struct rtw89_vif *rtwvif, ++ struct rtw89_vif_link *rtwvif_link, + struct sk_buff *skb, u8 ssid_idx) + { + struct rtw89_hw_scan_info *scan_info = &rtwdev->scan_info; +- struct ieee80211_scan_ies *ies = rtwvif->scan_ies; ++ struct ieee80211_scan_ies *ies = rtwvif_link->scan_ies; + struct rtw89_pktofld_info *info; + struct sk_buff *new; + int ret = 0; +@@ -5921,7 +5927,7 @@ static int rtw89_append_probe_req_ie(struct rtw89_dev *rtwdev, + goto out; + } + +- rtw89_is_6ghz_wildcard_probe_req(rtwdev, rtwvif, info, band, ++ rtw89_is_6ghz_wildcard_probe_req(rtwdev, rtwvif_link, info, band, + ssid_idx); + + ret = rtw89_fw_h2c_add_pkt_offload(rtwdev, &info->id, new); +@@ -5939,22 +5945,22 @@ static int rtw89_append_probe_req_ie(struct rtw89_dev *rtwdev, + } + + static int rtw89_hw_scan_update_probe_req(struct rtw89_dev *rtwdev, +- struct rtw89_vif *rtwvif) ++ struct rtw89_vif_link *rtwvif_link) + { +- struct cfg80211_scan_request *req = rtwvif->scan_req; ++ struct cfg80211_scan_request *req = rtwvif_link->scan_req; + struct sk_buff *skb; + u8 num = req->n_ssids, i; + int ret; + + for (i = 0; i < num; i++) { +- skb = ieee80211_probereq_get(rtwdev->hw, rtwvif->mac_addr, ++ skb = ieee80211_probereq_get(rtwdev->hw, rtwvif_link->mac_addr, + req->ssids[i].ssid, + req->ssids[i].ssid_len, + req->ie_len); + if (!skb) + return -ENOMEM; + +- ret = rtw89_append_probe_req_ie(rtwdev, rtwvif, skb, i); ++ ret = rtw89_append_probe_req_ie(rtwdev, rtwvif_link, skb, i); + kfree_skb(skb); + + if (ret) +@@ -5970,8 +5976,8 @@ static int rtw89_update_6ghz_rnr_chan(struct rtw89_dev *rtwdev, + { + struct ieee80211_vif *vif = rtwdev->scan_info.scanning_vif; + struct list_head *pkt_list = rtwdev->scan_info.pkt_list; +- struct rtw89_vif *rtwvif = vif_to_rtwvif_safe(vif); +- struct ieee80211_scan_ies *ies = rtwvif->scan_ies; ++ struct rtw89_vif_link *rtwvif_link = vif_to_rtwvif_safe(vif); ++ struct ieee80211_scan_ies *ies = rtwvif_link->scan_ies; + struct cfg80211_scan_6ghz_params *params; + struct rtw89_pktofld_info *info, *tmp; + struct ieee80211_hdr *hdr; +@@ -6000,7 +6006,7 @@ static int rtw89_update_6ghz_rnr_chan(struct rtw89_dev *rtwdev, + if (found) + continue; + +- skb = ieee80211_probereq_get(rtwdev->hw, rtwvif->mac_addr, ++ skb = ieee80211_probereq_get(rtwdev->hw, rtwvif_link->mac_addr, + NULL, 0, req->ie_len); + skb_put_data(skb, ies->ies[NL80211_BAND_6GHZ], ies->len[NL80211_BAND_6GHZ]); + skb_put_data(skb, ies->common_ies, ies->common_ie_len); +@@ -6091,8 +6097,8 @@ static void rtw89_hw_scan_add_chan(struct rtw89_dev *rtwdev, int chan_type, + { + struct rtw89_hw_scan_info *scan_info = &rtwdev->scan_info; + struct ieee80211_vif *vif = rtwdev->scan_info.scanning_vif; +- struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; +- struct cfg80211_scan_request *req = rtwvif->scan_req; ++ struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv; ++ struct cfg80211_scan_request *req = rtwvif_link->scan_req; + struct rtw89_chan *op = &rtwdev->scan_info.op_chan; + struct rtw89_pktofld_info *info; + u8 band, probe_count = 0; +@@ -6208,8 +6214,8 @@ static void rtw89_hw_scan_add_chan_be(struct rtw89_dev *rtwdev, int chan_type, + { + struct rtw89_hw_scan_info *scan_info = &rtwdev->scan_info; + struct ieee80211_vif *vif = rtwdev->scan_info.scanning_vif; +- struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; +- struct cfg80211_scan_request *req = rtwvif->scan_req; ++ struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv; ++ struct cfg80211_scan_request *req = rtwvif_link->scan_req; + struct rtw89_pktofld_info *info; + u8 band, probe_count = 0, i; + +@@ -6265,7 +6271,7 @@ static void rtw89_hw_scan_add_chan_be(struct rtw89_dev *rtwdev, int chan_type, + } + + int rtw89_pno_scan_add_chan_list_ax(struct rtw89_dev *rtwdev, +- struct rtw89_vif *rtwvif) ++ struct rtw89_vif_link *rtwvif_link) + { + struct rtw89_wow_param *rtw_wow = &rtwdev->wow; + struct cfg80211_sched_scan_request *nd_config = rtw_wow->nd_config; +@@ -6315,9 +6321,9 @@ int rtw89_pno_scan_add_chan_list_ax(struct rtw89_dev *rtwdev, + } + + int rtw89_hw_scan_add_chan_list_ax(struct rtw89_dev *rtwdev, +- struct rtw89_vif *rtwvif, bool connected) ++ struct rtw89_vif_link *rtwvif_link, bool connected) + { +- struct cfg80211_scan_request *req = rtwvif->scan_req; ++ struct cfg80211_scan_request *req = rtwvif_link->scan_req; + struct rtw89_mac_chinfo *ch_info, *tmp; + struct ieee80211_channel *channel; + struct list_head chan_list; +@@ -6392,7 +6398,7 @@ int rtw89_hw_scan_add_chan_list_ax(struct rtw89_dev *rtwdev, + } + + int rtw89_pno_scan_add_chan_list_be(struct rtw89_dev *rtwdev, +- struct rtw89_vif *rtwvif) ++ struct rtw89_vif_link *rtwvif_link) + { + struct rtw89_wow_param *rtw_wow = &rtwdev->wow; + struct cfg80211_sched_scan_request *nd_config = rtw_wow->nd_config; +@@ -6444,9 +6450,9 @@ int rtw89_pno_scan_add_chan_list_be(struct rtw89_dev *rtwdev, + } + + int rtw89_hw_scan_add_chan_list_be(struct rtw89_dev *rtwdev, +- struct rtw89_vif *rtwvif, bool connected) ++ struct rtw89_vif_link *rtwvif_link, bool connected) + { +- struct cfg80211_scan_request *req = rtwvif->scan_req; ++ struct cfg80211_scan_request *req = rtwvif_link->scan_req; + struct rtw89_mac_chinfo_be *ch_info, *tmp; + struct ieee80211_channel *channel; + struct list_head chan_list; +@@ -6503,17 +6509,17 @@ int rtw89_hw_scan_add_chan_list_be(struct rtw89_dev *rtwdev, + } + + static int rtw89_hw_scan_prehandle(struct rtw89_dev *rtwdev, +- struct rtw89_vif *rtwvif, bool connected) ++ struct rtw89_vif_link *rtwvif_link, bool connected) + { + const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; + int ret; + +- ret = rtw89_hw_scan_update_probe_req(rtwdev, rtwvif); ++ ret = rtw89_hw_scan_update_probe_req(rtwdev, rtwvif_link); + if (ret) { + rtw89_err(rtwdev, "Update probe request failed\n"); + goto out; + } +- ret = mac->add_chan_list(rtwdev, rtwvif, connected); ++ ret = mac->add_chan_list(rtwdev, rtwvif_link, connected); + out: + return ret; + } +@@ -6521,27 +6527,27 @@ static int rtw89_hw_scan_prehandle(struct rtw89_dev *rtwdev, + void rtw89_hw_scan_start(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif, + struct ieee80211_scan_request *scan_req) + { +- struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; ++ struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv; + const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; + struct cfg80211_scan_request *req = &scan_req->req; + u32 rx_fltr = rtwdev->hal.rx_fltr; + u8 mac_addr[ETH_ALEN]; + +- rtw89_get_channel(rtwdev, rtwvif, &rtwdev->scan_info.op_chan); ++ rtw89_get_channel(rtwdev, rtwvif_link, &rtwdev->scan_info.op_chan); + rtwdev->scan_info.scanning_vif = vif; + rtwdev->scan_info.last_chan_idx = 0; + rtwdev->scan_info.abort = false; +- rtwvif->scan_ies = &scan_req->ies; +- rtwvif->scan_req = req; ++ rtwvif_link->scan_ies = &scan_req->ies; ++ rtwvif_link->scan_req = req; + ieee80211_stop_queues(rtwdev->hw); +- rtw89_mac_port_cfg_rx_sync(rtwdev, rtwvif, false); ++ rtw89_mac_port_cfg_rx_sync(rtwdev, rtwvif_link, false); + + if (req->flags & NL80211_SCAN_FLAG_RANDOM_ADDR) + get_random_mask_addr(mac_addr, req->mac_addr, + req->mac_addr_mask); + else + ether_addr_copy(mac_addr, vif->addr); +- rtw89_core_scan_start(rtwdev, rtwvif, mac_addr, true); ++ rtw89_core_scan_start(rtwdev, rtwvif_link, mac_addr, true); + + rx_fltr &= ~B_AX_A_BCN_CHK_EN; + rx_fltr &= ~B_AX_A_BC; +@@ -6559,7 +6565,7 @@ void rtw89_hw_scan_complete(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif, + { + const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; + struct rtw89_hw_scan_info *scan_info = &rtwdev->scan_info; +- struct rtw89_vif *rtwvif = vif_to_rtwvif_safe(vif); ++ struct rtw89_vif_link *rtwvif_link = vif_to_rtwvif_safe(vif); + struct cfg80211_scan_info info = { + .aborted = aborted, + }; +@@ -6575,12 +6581,12 @@ void rtw89_hw_scan_complete(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif, + rtw89_core_scan_complete(rtwdev, vif, true); + ieee80211_scan_completed(rtwdev->hw, &info); + ieee80211_wake_queues(rtwdev->hw); +- rtw89_mac_port_cfg_rx_sync(rtwdev, rtwvif, true); ++ rtw89_mac_port_cfg_rx_sync(rtwdev, rtwvif_link, true); + rtw89_mac_enable_beacon_for_ap_vifs(rtwdev, true); + + rtw89_release_pkt_list(rtwdev); +- rtwvif->scan_req = NULL; +- rtwvif->scan_ies = NULL; ++ rtwvif_link->scan_req = NULL; ++ rtwvif_link->scan_ies = NULL; + scan_info->last_chan_idx = 0; + scan_info->scanning_vif = NULL; + scan_info->abort = false; +@@ -6609,11 +6615,11 @@ void rtw89_hw_scan_abort(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif) + + static bool rtw89_is_any_vif_connected_or_connecting(struct rtw89_dev *rtwdev) + { +- struct rtw89_vif *rtwvif; ++ struct rtw89_vif_link *rtwvif_link; + +- rtw89_for_each_rtwvif(rtwdev, rtwvif) { ++ rtw89_for_each_rtwvif(rtwdev, rtwvif_link) { + /* This variable implies connected or during attempt to connect */ +- if (!is_zero_ether_addr(rtwvif->bssid)) ++ if (!is_zero_ether_addr(rtwvif_link->bssid)) + return true; + } + +@@ -6625,19 +6631,19 @@ int rtw89_hw_scan_offload(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif, + { + const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; + struct rtw89_scan_option opt = {0}; +- struct rtw89_vif *rtwvif; ++ struct rtw89_vif_link *rtwvif_link; + bool connected; + int ret = 0; + +- rtwvif = vif ? (struct rtw89_vif *)vif->drv_priv : NULL; +- if (!rtwvif) ++ rtwvif_link = vif ? (struct rtw89_vif_link *)vif->drv_priv : NULL; ++ if (!rtwvif_link) + return -EINVAL; + + connected = rtw89_is_any_vif_connected_or_connecting(rtwdev); + opt.enable = enable; + opt.target_ch_mode = connected; + if (enable) { +- ret = rtw89_hw_scan_prehandle(rtwdev, rtwvif, connected); ++ ret = rtw89_hw_scan_prehandle(rtwdev, rtwvif_link, connected); + if (ret) + goto out; + } +@@ -6652,7 +6658,7 @@ int rtw89_hw_scan_offload(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif, + opt.opch_end = connected ? 0 : RTW89_CHAN_INVALID; + } + +- ret = mac->scan_offload(rtwdev, &opt, rtwvif, false); ++ ret = mac->scan_offload(rtwdev, &opt, rtwvif_link, false); + out: + return ret; + } +@@ -6758,7 +6764,7 @@ int rtw89_fw_h2c_pkt_drop(struct rtw89_dev *rtwdev, + } + + #define H2C_KEEP_ALIVE_LEN 4 +-int rtw89_fw_h2c_keep_alive(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, ++int rtw89_fw_h2c_keep_alive(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, + bool enable) + { + struct sk_buff *skb; +@@ -6766,7 +6772,7 @@ int rtw89_fw_h2c_keep_alive(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, + int ret; + + if (enable) { +- ret = rtw89_fw_h2c_add_general_pkt(rtwdev, rtwvif, ++ ret = rtw89_fw_h2c_add_general_pkt(rtwdev, rtwvif_link, + RTW89_PKT_OFLD_TYPE_NULL_DATA, + &pkt_id); + if (ret) +@@ -6784,7 +6790,7 @@ int rtw89_fw_h2c_keep_alive(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, + RTW89_SET_KEEP_ALIVE_ENABLE(skb->data, enable); + RTW89_SET_KEEP_ALIVE_PKT_NULL_ID(skb->data, pkt_id); + RTW89_SET_KEEP_ALIVE_PERIOD(skb->data, 5); +- RTW89_SET_KEEP_ALIVE_MACID(skb->data, rtwvif->mac_id); ++ RTW89_SET_KEEP_ALIVE_MACID(skb->data, rtwvif_link->mac_id); + + rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C, + H2C_CAT_MAC, +@@ -6806,7 +6812,7 @@ int rtw89_fw_h2c_keep_alive(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, + return ret; + } + +-int rtw89_fw_h2c_arp_offload(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, ++int rtw89_fw_h2c_arp_offload(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, + bool enable) + { + struct rtw89_h2c_arp_offload *h2c; +@@ -6816,7 +6822,7 @@ int rtw89_fw_h2c_arp_offload(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, + int ret; + + if (enable) { +- ret = rtw89_fw_h2c_add_general_pkt(rtwdev, rtwvif, ++ ret = rtw89_fw_h2c_add_general_pkt(rtwdev, rtwvif_link, + RTW89_PKT_OFLD_TYPE_ARP_RSP, + &pkt_id); + if (ret) +@@ -6834,7 +6840,7 @@ int rtw89_fw_h2c_arp_offload(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, + + h2c->w0 = le32_encode_bits(enable, RTW89_H2C_ARP_OFFLOAD_W0_ENABLE) | + le32_encode_bits(0, RTW89_H2C_ARP_OFFLOAD_W0_ACTION) | +- le32_encode_bits(rtwvif->mac_id, RTW89_H2C_ARP_OFFLOAD_W0_MACID) | ++ le32_encode_bits(rtwvif_link->mac_id, RTW89_H2C_ARP_OFFLOAD_W0_MACID) | + le32_encode_bits(pkt_id, RTW89_H2C_ARP_OFFLOAD_W0_PKT_ID); + + rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C, +@@ -6859,11 +6865,11 @@ int rtw89_fw_h2c_arp_offload(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, + + #define H2C_DISCONNECT_DETECT_LEN 8 + int rtw89_fw_h2c_disconnect_detect(struct rtw89_dev *rtwdev, +- struct rtw89_vif *rtwvif, bool enable) ++ struct rtw89_vif_link *rtwvif_link, bool enable) + { + struct rtw89_wow_param *rtw_wow = &rtwdev->wow; + struct sk_buff *skb; +- u8 macid = rtwvif->mac_id; ++ u8 macid = rtwvif_link->mac_id; + int ret; + + skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, H2C_DISCONNECT_DETECT_LEN); +@@ -6902,7 +6908,7 @@ int rtw89_fw_h2c_disconnect_detect(struct rtw89_dev *rtwdev, + return ret; + } + +-int rtw89_fw_h2c_cfg_pno(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, ++int rtw89_fw_h2c_cfg_pno(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, + bool enable) + { + struct rtw89_wow_param *rtw_wow = &rtwdev->wow; +@@ -6923,7 +6929,7 @@ int rtw89_fw_h2c_cfg_pno(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, + + h2c->w0 = le32_encode_bits(enable, RTW89_H2C_NLO_W0_ENABLE) | + le32_encode_bits(enable, RTW89_H2C_NLO_W0_IGNORE_CIPHER) | +- le32_encode_bits(rtwvif->mac_id, RTW89_H2C_NLO_W0_MACID); ++ le32_encode_bits(rtwvif_link->mac_id, RTW89_H2C_NLO_W0_MACID); + + if (enable) { + h2c->nlo_cnt = nd_config->n_match_sets; +@@ -6953,12 +6959,12 @@ int rtw89_fw_h2c_cfg_pno(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, + return ret; + } + +-int rtw89_fw_h2c_wow_global(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, ++int rtw89_fw_h2c_wow_global(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, + bool enable) + { + struct rtw89_wow_param *rtw_wow = &rtwdev->wow; + struct rtw89_h2c_wow_global *h2c; +- u8 macid = rtwvif->mac_id; ++ u8 macid = rtwvif_link->mac_id; + u32 len = sizeof(*h2c); + struct sk_buff *skb; + int ret; +@@ -7002,12 +7008,12 @@ int rtw89_fw_h2c_wow_global(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, + + #define H2C_WAKEUP_CTRL_LEN 4 + int rtw89_fw_h2c_wow_wakeup_ctrl(struct rtw89_dev *rtwdev, +- struct rtw89_vif *rtwvif, ++ struct rtw89_vif_link *rtwvif_link, + bool enable) + { + struct rtw89_wow_param *rtw_wow = &rtwdev->wow; + struct sk_buff *skb; +- u8 macid = rtwvif->mac_id; ++ u8 macid = rtwvif_link->mac_id; + int ret; + + skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, H2C_WAKEUP_CTRL_LEN); +@@ -7100,13 +7106,13 @@ int rtw89_fw_wow_cam_update(struct rtw89_dev *rtwdev, + } + + int rtw89_fw_h2c_wow_gtk_ofld(struct rtw89_dev *rtwdev, +- struct rtw89_vif *rtwvif, ++ struct rtw89_vif_link *rtwvif_link, + bool enable) + { + struct rtw89_wow_param *rtw_wow = &rtwdev->wow; + struct rtw89_wow_gtk_info *gtk_info = &rtw_wow->gtk_info; + struct rtw89_h2c_wow_gtk_ofld *h2c; +- u8 macid = rtwvif->mac_id; ++ u8 macid = rtwvif_link->mac_id; + u32 len = sizeof(*h2c); + u8 pkt_id_sa_query = 0; + struct sk_buff *skb; +@@ -7128,14 +7134,14 @@ int rtw89_fw_h2c_wow_gtk_ofld(struct rtw89_dev *rtwdev, + if (!enable) + goto hdr; + +- ret = rtw89_fw_h2c_add_general_pkt(rtwdev, rtwvif, ++ ret = rtw89_fw_h2c_add_general_pkt(rtwdev, rtwvif_link, + RTW89_PKT_OFLD_TYPE_EAPOL_KEY, + &pkt_id_eapol); + if (ret) + goto fail; + + if (gtk_info->igtk_keyid) { +- ret = rtw89_fw_h2c_add_general_pkt(rtwdev, rtwvif, ++ ret = rtw89_fw_h2c_add_general_pkt(rtwdev, rtwvif_link, + RTW89_PKT_OFLD_TYPE_SA_QUERY, + &pkt_id_sa_query); + if (ret) +@@ -7173,7 +7179,7 @@ int rtw89_fw_h2c_wow_gtk_ofld(struct rtw89_dev *rtwdev, + return ret; + } + +-int rtw89_fw_h2c_fwips(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, ++int rtw89_fw_h2c_fwips(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, + bool enable) + { + struct rtw89_wait_info *wait = &rtwdev->mac.ps_wait; +@@ -7189,7 +7195,7 @@ int rtw89_fw_h2c_fwips(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, + skb_put(skb, len); + h2c = (struct rtw89_h2c_fwips *)skb->data; + +- h2c->w0 = le32_encode_bits(rtwvif->mac_id, RTW89_H2C_FW_IPS_W0_MACID) | ++ h2c->w0 = le32_encode_bits(rtwvif_link->mac_id, RTW89_H2C_FW_IPS_W0_MACID) | + le32_encode_bits(enable, RTW89_H2C_FW_IPS_W0_ENABLE); + + rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C, +diff --git a/drivers/net/wireless/realtek/rtw89/fw.h b/drivers/net/wireless/realtek/rtw89/fw.h +index ad47e77d740b2..4e2f7a478d75d 100644 +--- a/drivers/net/wireless/realtek/rtw89/fw.h ++++ b/drivers/net/wireless/realtek/rtw89/fw.h +@@ -4404,13 +4404,13 @@ void rtw89_h2c_pkt_set_hdr(struct rtw89_dev *rtwdev, struct sk_buff *skb, + u8 type, u8 cat, u8 class, u8 func, + bool rack, bool dack, u32 len); + int rtw89_fw_h2c_default_cmac_tbl(struct rtw89_dev *rtwdev, +- struct rtw89_vif *rtwvif, ++ struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta *rtwsta); + int rtw89_fw_h2c_default_cmac_tbl_g7(struct rtw89_dev *rtwdev, +- struct rtw89_vif *rtwvif, ++ struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta *rtwsta); + int rtw89_fw_h2c_default_dmac_tbl_v2(struct rtw89_dev *rtwdev, +- struct rtw89_vif *rtwvif, ++ struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta *rtwsta); + int rtw89_fw_h2c_assoc_cmac_tbl(struct rtw89_dev *rtwdev, + struct ieee80211_vif *vif, +@@ -4426,29 +4426,29 @@ int rtw89_fw_h2c_txtime_cmac_tbl(struct rtw89_dev *rtwdev, + int rtw89_fw_h2c_txpath_cmac_tbl(struct rtw89_dev *rtwdev, + struct rtw89_sta *rtwsta); + int rtw89_fw_h2c_update_beacon(struct rtw89_dev *rtwdev, +- struct rtw89_vif *rtwvif); ++ struct rtw89_vif_link *rtwvif_link); + int rtw89_fw_h2c_update_beacon_be(struct rtw89_dev *rtwdev, +- struct rtw89_vif *rtwvif); +-int rtw89_fw_h2c_cam(struct rtw89_dev *rtwdev, struct rtw89_vif *vif, ++ struct rtw89_vif_link *rtwvif_link); ++int rtw89_fw_h2c_cam(struct rtw89_dev *rtwdev, struct rtw89_vif_link *vif, + struct rtw89_sta *rtwsta, const u8 *scan_mac_addr); + int rtw89_fw_h2c_dctl_sec_cam_v1(struct rtw89_dev *rtwdev, +- struct rtw89_vif *rtwvif, ++ struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta *rtwsta); + int rtw89_fw_h2c_dctl_sec_cam_v2(struct rtw89_dev *rtwdev, +- struct rtw89_vif *rtwvif, ++ struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta *rtwsta); + void rtw89_fw_c2h_irqsafe(struct rtw89_dev *rtwdev, struct sk_buff *c2h); + void rtw89_fw_c2h_work(struct work_struct *work); + int rtw89_fw_h2c_role_maintain(struct rtw89_dev *rtwdev, +- struct rtw89_vif *rtwvif, ++ struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta *rtwsta, + enum rtw89_upd_mode upd_mode); +-int rtw89_fw_h2c_join_info(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, ++int rtw89_fw_h2c_join_info(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta *rtwsta, bool dis_conn); + int rtw89_fw_h2c_notify_dbcc(struct rtw89_dev *rtwdev, bool en); + int rtw89_fw_h2c_macid_pause(struct rtw89_dev *rtwdev, u8 sh, u8 grp, + bool pause); +-int rtw89_fw_h2c_set_edca(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, ++int rtw89_fw_h2c_set_edca(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, + u8 ac, u32 val); + int rtw89_fw_h2c_set_ofld_cfg(struct rtw89_dev *rtwdev); + int rtw89_fw_h2c_set_bcn_fltr_cfg(struct rtw89_dev *rtwdev, +@@ -4456,7 +4456,7 @@ int rtw89_fw_h2c_set_bcn_fltr_cfg(struct rtw89_dev *rtwdev, + bool connect); + int rtw89_fw_h2c_rssi_offload(struct rtw89_dev *rtwdev, + struct rtw89_rx_phy_ppdu *phy_ppdu); +-int rtw89_fw_h2c_tp_offload(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif); ++int rtw89_fw_h2c_tp_offload(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link); + int rtw89_fw_h2c_ra(struct rtw89_dev *rtwdev, struct rtw89_ra_info *ra, bool csi); + int rtw89_fw_h2c_cxdrv_init(struct rtw89_dev *rtwdev, u8 type); + int rtw89_fw_h2c_cxdrv_init_v7(struct rtw89_dev *rtwdev, u8 type); +@@ -4478,11 +4478,11 @@ int rtw89_fw_h2c_scan_list_offload_be(struct rtw89_dev *rtwdev, int ch_num, + struct list_head *chan_list); + int rtw89_fw_h2c_scan_offload_ax(struct rtw89_dev *rtwdev, + struct rtw89_scan_option *opt, +- struct rtw89_vif *vif, ++ struct rtw89_vif_link *vif, + bool wowlan); + int rtw89_fw_h2c_scan_offload_be(struct rtw89_dev *rtwdev, + struct rtw89_scan_option *opt, +- struct rtw89_vif *vif, ++ struct rtw89_vif_link *vif, + bool wowlan); + int rtw89_fw_h2c_rf_reg(struct rtw89_dev *rtwdev, + struct rtw89_fw_h2c_rf_reg_info *info, +@@ -4508,10 +4508,11 @@ int rtw89_fw_h2c_raw_with_hdr(struct rtw89_dev *rtwdev, + int rtw89_fw_h2c_raw(struct rtw89_dev *rtwdev, const u8 *buf, u16 len); + void rtw89_fw_send_all_early_h2c(struct rtw89_dev *rtwdev); + void rtw89_fw_free_all_early_h2c(struct rtw89_dev *rtwdev); +-int rtw89_fw_h2c_general_pkt(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, ++int rtw89_fw_h2c_general_pkt(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, + u8 macid); + void rtw89_fw_release_general_pkt_list_vif(struct rtw89_dev *rtwdev, +- struct rtw89_vif *rtwvif, bool notify_fw); ++ struct rtw89_vif_link *rtwvif_link, ++ bool notify_fw); + void rtw89_fw_release_general_pkt_list(struct rtw89_dev *rtwdev, bool notify_fw); + int rtw89_fw_h2c_ba_cam(struct rtw89_dev *rtwdev, struct rtw89_sta *rtwsta, + bool valid, struct ieee80211_ampdu_params *params); +@@ -4524,8 +4525,8 @@ int rtw89_fw_h2c_init_ba_cam_users(struct rtw89_dev *rtwdev, u8 users, + int rtw89_fw_h2c_lps_parm(struct rtw89_dev *rtwdev, + struct rtw89_lps_parm *lps_param); + int rtw89_fw_h2c_lps_ch_info(struct rtw89_dev *rtwdev, +- struct rtw89_vif *rtwvif); +-int rtw89_fw_h2c_fwips(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, ++ struct rtw89_vif_link *rtwvif_link); ++int rtw89_fw_h2c_fwips(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, + bool enable); + struct sk_buff *rtw89_fw_h2c_alloc_skb_with_hdr(struct rtw89_dev *rtwdev, u32 len); + struct sk_buff *rtw89_fw_h2c_alloc_skb_no_hdr(struct rtw89_dev *rtwdev, u32 len); +@@ -4542,41 +4543,42 @@ int rtw89_hw_scan_offload(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif, + bool enable); + void rtw89_hw_scan_abort(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif); + int rtw89_hw_scan_add_chan_list_ax(struct rtw89_dev *rtwdev, +- struct rtw89_vif *rtwvif, bool connected); ++ struct rtw89_vif_link *rtwvif_link, bool connected); + int rtw89_pno_scan_add_chan_list_ax(struct rtw89_dev *rtwdev, +- struct rtw89_vif *rtwvif); ++ struct rtw89_vif_link *rtwvif_link); + int rtw89_hw_scan_add_chan_list_be(struct rtw89_dev *rtwdev, +- struct rtw89_vif *rtwvif, bool connected); ++ struct rtw89_vif_link *rtwvif_link, bool connected); + int rtw89_pno_scan_add_chan_list_be(struct rtw89_dev *rtwdev, +- struct rtw89_vif *rtwvif); ++ struct rtw89_vif_link *rtwvif_link); + int rtw89_fw_h2c_trigger_cpu_exception(struct rtw89_dev *rtwdev); + int rtw89_fw_h2c_pkt_drop(struct rtw89_dev *rtwdev, + const struct rtw89_pkt_drop_params *params); + int rtw89_fw_h2c_p2p_act(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif, + struct ieee80211_p2p_noa_desc *desc, + u8 act, u8 noa_id); +-int rtw89_fw_h2c_tsf32_toggle(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, ++int rtw89_fw_h2c_tsf32_toggle(struct rtw89_dev *rtwdev, ++ struct rtw89_vif_link *rtwvif_link, + bool en); +-int rtw89_fw_h2c_wow_global(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, ++int rtw89_fw_h2c_wow_global(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, + bool enable); + int rtw89_fw_h2c_wow_wakeup_ctrl(struct rtw89_dev *rtwdev, +- struct rtw89_vif *rtwvif, bool enable); +-int rtw89_fw_h2c_cfg_pno(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, ++ struct rtw89_vif_link *rtwvif_link, bool enable); ++int rtw89_fw_h2c_cfg_pno(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, + bool enable); +-int rtw89_fw_h2c_keep_alive(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, ++int rtw89_fw_h2c_keep_alive(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, + bool enable); + int rtw89_fw_h2c_arp_offload(struct rtw89_dev *rtwdev, +- struct rtw89_vif *rtwvif, bool enable); ++ struct rtw89_vif_link *rtwvif_link, bool enable); + int rtw89_fw_h2c_disconnect_detect(struct rtw89_dev *rtwdev, +- struct rtw89_vif *rtwvif, bool enable); +-int rtw89_fw_h2c_wow_global(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, ++ struct rtw89_vif_link *rtwvif_link, bool enable); ++int rtw89_fw_h2c_wow_global(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, + bool enable); + int rtw89_fw_h2c_wow_wakeup_ctrl(struct rtw89_dev *rtwdev, +- struct rtw89_vif *rtwvif, bool enable); ++ struct rtw89_vif_link *rtwvif_link, bool enable); + int rtw89_fw_wow_cam_update(struct rtw89_dev *rtwdev, + struct rtw89_wow_cam_info *cam_info); + int rtw89_fw_h2c_wow_gtk_ofld(struct rtw89_dev *rtwdev, +- struct rtw89_vif *rtwvif, ++ struct rtw89_vif_link *rtwvif_link, + bool enable); + int rtw89_fw_h2c_wow_request_aoac(struct rtw89_dev *rtwdev); + int rtw89_fw_h2c_add_mcc(struct rtw89_dev *rtwdev, +@@ -4621,32 +4623,32 @@ static inline void rtw89_fw_h2c_init_ba_cam(struct rtw89_dev *rtwdev) + } + + static inline int rtw89_chip_h2c_default_cmac_tbl(struct rtw89_dev *rtwdev, +- struct rtw89_vif *rtwvif, ++ struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta *rtwsta) + { + const struct rtw89_chip_info *chip = rtwdev->chip; + +- return chip->ops->h2c_default_cmac_tbl(rtwdev, rtwvif, rtwsta); ++ return chip->ops->h2c_default_cmac_tbl(rtwdev, rtwvif_link, rtwsta); + } + + static inline int rtw89_chip_h2c_default_dmac_tbl(struct rtw89_dev *rtwdev, +- struct rtw89_vif *rtwvif, ++ struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta *rtwsta) + { + const struct rtw89_chip_info *chip = rtwdev->chip; + + if (chip->ops->h2c_default_dmac_tbl) +- return chip->ops->h2c_default_dmac_tbl(rtwdev, rtwvif, rtwsta); ++ return chip->ops->h2c_default_dmac_tbl(rtwdev, rtwvif_link, rtwsta); + + return 0; + } + + static inline int rtw89_chip_h2c_update_beacon(struct rtw89_dev *rtwdev, +- struct rtw89_vif *rtwvif) ++ struct rtw89_vif_link *rtwvif_link) + { + const struct rtw89_chip_info *chip = rtwdev->chip; + +- return chip->ops->h2c_update_beacon(rtwdev, rtwvif); ++ return chip->ops->h2c_update_beacon(rtwdev, rtwvif_link); + } + + static inline int rtw89_chip_h2c_assoc_cmac_tbl(struct rtw89_dev *rtwdev, +diff --git a/drivers/net/wireless/realtek/rtw89/mac.c b/drivers/net/wireless/realtek/rtw89/mac.c +index c70a23a763b0e..e1956c7224364 100644 +--- a/drivers/net/wireless/realtek/rtw89/mac.c ++++ b/drivers/net/wireless/realtek/rtw89/mac.c +@@ -4076,17 +4076,17 @@ static const struct rtw89_port_reg rtw89_port_base_ax = { + }; + + static void rtw89_mac_check_packet_ctrl(struct rtw89_dev *rtwdev, +- struct rtw89_vif *rtwvif, u8 type) ++ struct rtw89_vif_link *rtwvif_link, u8 type) + { + const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; + const struct rtw89_port_reg *p = mac->port_base; +- u8 mask = B_AX_PTCL_DBG_INFO_MASK_BY_PORT(rtwvif->port); ++ u8 mask = B_AX_PTCL_DBG_INFO_MASK_BY_PORT(rtwvif_link->port); + u32 reg_info, reg_ctrl; + u32 val; + int ret; + +- reg_info = rtw89_mac_reg_by_idx(rtwdev, p->ptcl_dbg_info, rtwvif->mac_idx); +- reg_ctrl = rtw89_mac_reg_by_idx(rtwdev, p->ptcl_dbg, rtwvif->mac_idx); ++ reg_info = rtw89_mac_reg_by_idx(rtwdev, p->ptcl_dbg_info, rtwvif_link->mac_idx); ++ reg_ctrl = rtw89_mac_reg_by_idx(rtwdev, p->ptcl_dbg, rtwvif_link->mac_idx); + + rtw89_write32_mask(rtwdev, reg_ctrl, B_AX_PTCL_DBG_SEL_MASK, type); + rtw89_write32_set(rtwdev, reg_ctrl, B_AX_PTCL_DBG_EN); +@@ -4098,26 +4098,32 @@ static void rtw89_mac_check_packet_ctrl(struct rtw89_dev *rtwdev, + rtw89_warn(rtwdev, "Polling beacon packet empty fail\n"); + } + +-static void rtw89_mac_bcn_drop(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif) ++static void rtw89_mac_bcn_drop(struct rtw89_dev *rtwdev, ++ struct rtw89_vif_link *rtwvif_link) + { + const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; + const struct rtw89_port_reg *p = mac->port_base; + +- rtw89_write32_set(rtwdev, p->bcn_drop_all, BIT(rtwvif->port)); +- rtw89_write32_port_mask(rtwdev, rtwvif, p->tbtt_prohib, B_AX_TBTT_SETUP_MASK, 1); +- rtw89_write32_port_mask(rtwdev, rtwvif, p->bcn_area, B_AX_BCN_MSK_AREA_MASK, 0); +- rtw89_write32_port_mask(rtwdev, rtwvif, p->tbtt_prohib, B_AX_TBTT_HOLD_MASK, 0); +- rtw89_write32_port_mask(rtwdev, rtwvif, p->bcn_early, B_AX_BCNERLY_MASK, 2); +- rtw89_write16_port_mask(rtwdev, rtwvif, p->tbtt_early, B_AX_TBTTERLY_MASK, 1); +- rtw89_write32_port_mask(rtwdev, rtwvif, p->bcn_space, B_AX_BCN_SPACE_MASK, 1); +- rtw89_write32_port_set(rtwdev, rtwvif, p->port_cfg, B_AX_BCNTX_EN); +- +- rtw89_mac_check_packet_ctrl(rtwdev, rtwvif, AX_PTCL_DBG_BCNQ_NUM0); +- if (rtwvif->port == RTW89_PORT_0) +- rtw89_mac_check_packet_ctrl(rtwdev, rtwvif, AX_PTCL_DBG_BCNQ_NUM1); +- +- rtw89_write32_clr(rtwdev, p->bcn_drop_all, BIT(rtwvif->port)); +- rtw89_write32_port_clr(rtwdev, rtwvif, p->port_cfg, B_AX_TBTT_PROHIB_EN); ++ rtw89_write32_set(rtwdev, p->bcn_drop_all, BIT(rtwvif_link->port)); ++ rtw89_write32_port_mask(rtwdev, rtwvif_link, p->tbtt_prohib, B_AX_TBTT_SETUP_MASK, ++ 1); ++ rtw89_write32_port_mask(rtwdev, rtwvif_link, p->bcn_area, B_AX_BCN_MSK_AREA_MASK, ++ 0); ++ rtw89_write32_port_mask(rtwdev, rtwvif_link, p->tbtt_prohib, B_AX_TBTT_HOLD_MASK, ++ 0); ++ rtw89_write32_port_mask(rtwdev, rtwvif_link, p->bcn_early, B_AX_BCNERLY_MASK, 2); ++ rtw89_write16_port_mask(rtwdev, rtwvif_link, p->tbtt_early, ++ B_AX_TBTTERLY_MASK, 1); ++ rtw89_write32_port_mask(rtwdev, rtwvif_link, p->bcn_space, ++ B_AX_BCN_SPACE_MASK, 1); ++ rtw89_write32_port_set(rtwdev, rtwvif_link, p->port_cfg, B_AX_BCNTX_EN); ++ ++ rtw89_mac_check_packet_ctrl(rtwdev, rtwvif_link, AX_PTCL_DBG_BCNQ_NUM0); ++ if (rtwvif_link->port == RTW89_PORT_0) ++ rtw89_mac_check_packet_ctrl(rtwdev, rtwvif_link, AX_PTCL_DBG_BCNQ_NUM1); ++ ++ rtw89_write32_clr(rtwdev, p->bcn_drop_all, BIT(rtwvif_link->port)); ++ rtw89_write32_port_clr(rtwdev, rtwvif_link, p->port_cfg, B_AX_TBTT_PROHIB_EN); + fsleep(2000); + } + +@@ -4131,286 +4137,294 @@ static void rtw89_mac_bcn_drop(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvi + #define BCN_ERLY_SET_DLY (10 * 2) + + static void rtw89_mac_port_cfg_func_sw(struct rtw89_dev *rtwdev, +- struct rtw89_vif *rtwvif) ++ struct rtw89_vif_link *rtwvif_link) + { + const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; + const struct rtw89_port_reg *p = mac->port_base; +- struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif); ++ struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif_link); + const struct rtw89_chip_info *chip = rtwdev->chip; + bool need_backup = false; + u32 backup_val; + +- if (!rtw89_read32_port_mask(rtwdev, rtwvif, p->port_cfg, B_AX_PORT_FUNC_EN)) ++ if (!rtw89_read32_port_mask(rtwdev, rtwvif_link, p->port_cfg, B_AX_PORT_FUNC_EN)) + return; + +- if (chip->chip_id == RTL8852A && rtwvif->port != RTW89_PORT_0) { ++ if (chip->chip_id == RTL8852A && rtwvif_link->port != RTW89_PORT_0) { + need_backup = true; +- backup_val = rtw89_read32_port(rtwdev, rtwvif, p->tbtt_prohib); ++ backup_val = rtw89_read32_port(rtwdev, rtwvif_link, p->tbtt_prohib); + } + +- if (rtwvif->net_type == RTW89_NET_TYPE_AP_MODE) +- rtw89_mac_bcn_drop(rtwdev, rtwvif); ++ if (rtwvif_link->net_type == RTW89_NET_TYPE_AP_MODE) ++ rtw89_mac_bcn_drop(rtwdev, rtwvif_link); + + if (chip->chip_id == RTL8852A) { +- rtw89_write32_port_clr(rtwdev, rtwvif, p->tbtt_prohib, B_AX_TBTT_SETUP_MASK); +- rtw89_write32_port_mask(rtwdev, rtwvif, p->tbtt_prohib, B_AX_TBTT_HOLD_MASK, 1); +- rtw89_write16_port_clr(rtwdev, rtwvif, p->tbtt_early, B_AX_TBTTERLY_MASK); +- rtw89_write16_port_clr(rtwdev, rtwvif, p->bcn_early, B_AX_BCNERLY_MASK); ++ rtw89_write32_port_clr(rtwdev, rtwvif_link, p->tbtt_prohib, ++ B_AX_TBTT_SETUP_MASK); ++ rtw89_write32_port_mask(rtwdev, rtwvif_link, p->tbtt_prohib, ++ B_AX_TBTT_HOLD_MASK, 1); ++ rtw89_write16_port_clr(rtwdev, rtwvif_link, p->tbtt_early, ++ B_AX_TBTTERLY_MASK); ++ rtw89_write16_port_clr(rtwdev, rtwvif_link, p->bcn_early, ++ B_AX_BCNERLY_MASK); + } + + msleep(vif->bss_conf.beacon_int + 1); +- rtw89_write32_port_clr(rtwdev, rtwvif, p->port_cfg, B_AX_PORT_FUNC_EN | ++ rtw89_write32_port_clr(rtwdev, rtwvif_link, p->port_cfg, B_AX_PORT_FUNC_EN | + B_AX_BRK_SETUP); +- rtw89_write32_port_set(rtwdev, rtwvif, p->port_cfg, B_AX_TSFTR_RST); +- rtw89_write32_port(rtwdev, rtwvif, p->bcn_cnt_tmr, 0); ++ rtw89_write32_port_set(rtwdev, rtwvif_link, p->port_cfg, B_AX_TSFTR_RST); ++ rtw89_write32_port(rtwdev, rtwvif_link, p->bcn_cnt_tmr, 0); + + if (need_backup) +- rtw89_write32_port(rtwdev, rtwvif, p->tbtt_prohib, backup_val); ++ rtw89_write32_port(rtwdev, rtwvif_link, p->tbtt_prohib, backup_val); + } + + static void rtw89_mac_port_cfg_tx_rpt(struct rtw89_dev *rtwdev, +- struct rtw89_vif *rtwvif, bool en) ++ struct rtw89_vif_link *rtwvif_link, bool en) + { + const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; + const struct rtw89_port_reg *p = mac->port_base; + + if (en) +- rtw89_write32_port_set(rtwdev, rtwvif, p->port_cfg, B_AX_TXBCN_RPT_EN); ++ rtw89_write32_port_set(rtwdev, rtwvif_link, p->port_cfg, ++ B_AX_TXBCN_RPT_EN); + else +- rtw89_write32_port_clr(rtwdev, rtwvif, p->port_cfg, B_AX_TXBCN_RPT_EN); ++ rtw89_write32_port_clr(rtwdev, rtwvif_link, p->port_cfg, ++ B_AX_TXBCN_RPT_EN); + } + + static void rtw89_mac_port_cfg_rx_rpt(struct rtw89_dev *rtwdev, +- struct rtw89_vif *rtwvif, bool en) ++ struct rtw89_vif_link *rtwvif_link, bool en) + { + const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; + const struct rtw89_port_reg *p = mac->port_base; + + if (en) +- rtw89_write32_port_set(rtwdev, rtwvif, p->port_cfg, B_AX_RXBCN_RPT_EN); ++ rtw89_write32_port_set(rtwdev, rtwvif_link, p->port_cfg, ++ B_AX_RXBCN_RPT_EN); + else +- rtw89_write32_port_clr(rtwdev, rtwvif, p->port_cfg, B_AX_RXBCN_RPT_EN); ++ rtw89_write32_port_clr(rtwdev, rtwvif_link, p->port_cfg, ++ B_AX_RXBCN_RPT_EN); + } + + static void rtw89_mac_port_cfg_net_type(struct rtw89_dev *rtwdev, +- struct rtw89_vif *rtwvif) ++ struct rtw89_vif_link *rtwvif_link) + { + const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; + const struct rtw89_port_reg *p = mac->port_base; + +- rtw89_write32_port_mask(rtwdev, rtwvif, p->port_cfg, B_AX_NET_TYPE_MASK, +- rtwvif->net_type); ++ rtw89_write32_port_mask(rtwdev, rtwvif_link, p->port_cfg, B_AX_NET_TYPE_MASK, ++ rtwvif_link->net_type); + } + + static void rtw89_mac_port_cfg_bcn_prct(struct rtw89_dev *rtwdev, +- struct rtw89_vif *rtwvif) ++ struct rtw89_vif_link *rtwvif_link) + { + const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; + const struct rtw89_port_reg *p = mac->port_base; +- bool en = rtwvif->net_type != RTW89_NET_TYPE_NO_LINK; ++ bool en = rtwvif_link->net_type != RTW89_NET_TYPE_NO_LINK; + u32 bits = B_AX_TBTT_PROHIB_EN | B_AX_BRK_SETUP; + + if (en) +- rtw89_write32_port_set(rtwdev, rtwvif, p->port_cfg, bits); ++ rtw89_write32_port_set(rtwdev, rtwvif_link, p->port_cfg, bits); + else +- rtw89_write32_port_clr(rtwdev, rtwvif, p->port_cfg, bits); ++ rtw89_write32_port_clr(rtwdev, rtwvif_link, p->port_cfg, bits); + } + + static void rtw89_mac_port_cfg_rx_sw(struct rtw89_dev *rtwdev, +- struct rtw89_vif *rtwvif) ++ struct rtw89_vif_link *rtwvif_link) + { + const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; + const struct rtw89_port_reg *p = mac->port_base; +- bool en = rtwvif->net_type == RTW89_NET_TYPE_INFRA || +- rtwvif->net_type == RTW89_NET_TYPE_AD_HOC; ++ bool en = rtwvif_link->net_type == RTW89_NET_TYPE_INFRA || ++ rtwvif_link->net_type == RTW89_NET_TYPE_AD_HOC; + u32 bit = B_AX_RX_BSSID_FIT_EN; + + if (en) +- rtw89_write32_port_set(rtwdev, rtwvif, p->port_cfg, bit); ++ rtw89_write32_port_set(rtwdev, rtwvif_link, p->port_cfg, bit); + else +- rtw89_write32_port_clr(rtwdev, rtwvif, p->port_cfg, bit); ++ rtw89_write32_port_clr(rtwdev, rtwvif_link, p->port_cfg, bit); + } + + void rtw89_mac_port_cfg_rx_sync(struct rtw89_dev *rtwdev, +- struct rtw89_vif *rtwvif, bool en) ++ struct rtw89_vif_link *rtwvif_link, bool en) + { + const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; + const struct rtw89_port_reg *p = mac->port_base; + + if (en) +- rtw89_write32_port_set(rtwdev, rtwvif, p->port_cfg, B_AX_TSF_UDT_EN); ++ rtw89_write32_port_set(rtwdev, rtwvif_link, p->port_cfg, B_AX_TSF_UDT_EN); + else +- rtw89_write32_port_clr(rtwdev, rtwvif, p->port_cfg, B_AX_TSF_UDT_EN); ++ rtw89_write32_port_clr(rtwdev, rtwvif_link, p->port_cfg, B_AX_TSF_UDT_EN); + } + + static void rtw89_mac_port_cfg_rx_sync_by_nettype(struct rtw89_dev *rtwdev, +- struct rtw89_vif *rtwvif) ++ struct rtw89_vif_link *rtwvif_link) + { +- bool en = rtwvif->net_type == RTW89_NET_TYPE_INFRA || +- rtwvif->net_type == RTW89_NET_TYPE_AD_HOC; ++ bool en = rtwvif_link->net_type == RTW89_NET_TYPE_INFRA || ++ rtwvif_link->net_type == RTW89_NET_TYPE_AD_HOC; + +- rtw89_mac_port_cfg_rx_sync(rtwdev, rtwvif, en); ++ rtw89_mac_port_cfg_rx_sync(rtwdev, rtwvif_link, en); + } + + static void rtw89_mac_port_cfg_tx_sw(struct rtw89_dev *rtwdev, +- struct rtw89_vif *rtwvif, bool en) ++ struct rtw89_vif_link *rtwvif_link, bool en) + { + const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; + const struct rtw89_port_reg *p = mac->port_base; + + if (en) +- rtw89_write32_port_set(rtwdev, rtwvif, p->port_cfg, B_AX_BCNTX_EN); ++ rtw89_write32_port_set(rtwdev, rtwvif_link, p->port_cfg, B_AX_BCNTX_EN); + else +- rtw89_write32_port_clr(rtwdev, rtwvif, p->port_cfg, B_AX_BCNTX_EN); ++ rtw89_write32_port_clr(rtwdev, rtwvif_link, p->port_cfg, B_AX_BCNTX_EN); + } + + static void rtw89_mac_port_cfg_tx_sw_by_nettype(struct rtw89_dev *rtwdev, +- struct rtw89_vif *rtwvif) ++ struct rtw89_vif_link *rtwvif_link) + { +- bool en = rtwvif->net_type == RTW89_NET_TYPE_AP_MODE || +- rtwvif->net_type == RTW89_NET_TYPE_AD_HOC; ++ bool en = rtwvif_link->net_type == RTW89_NET_TYPE_AP_MODE || ++ rtwvif_link->net_type == RTW89_NET_TYPE_AD_HOC; + +- rtw89_mac_port_cfg_tx_sw(rtwdev, rtwvif, en); ++ rtw89_mac_port_cfg_tx_sw(rtwdev, rtwvif_link, en); + } + + void rtw89_mac_enable_beacon_for_ap_vifs(struct rtw89_dev *rtwdev, bool en) + { +- struct rtw89_vif *rtwvif; ++ struct rtw89_vif_link *rtwvif_link; + +- rtw89_for_each_rtwvif(rtwdev, rtwvif) +- if (rtwvif->net_type == RTW89_NET_TYPE_AP_MODE) +- rtw89_mac_port_cfg_tx_sw(rtwdev, rtwvif, en); ++ rtw89_for_each_rtwvif(rtwdev, rtwvif_link) ++ if (rtwvif_link->net_type == RTW89_NET_TYPE_AP_MODE) ++ rtw89_mac_port_cfg_tx_sw(rtwdev, rtwvif_link, en); + } + + static void rtw89_mac_port_cfg_bcn_intv(struct rtw89_dev *rtwdev, +- struct rtw89_vif *rtwvif) ++ struct rtw89_vif_link *rtwvif_link) + { + const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; + const struct rtw89_port_reg *p = mac->port_base; +- struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif); ++ struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif_link); + u16 bcn_int = vif->bss_conf.beacon_int ? vif->bss_conf.beacon_int : BCN_INTERVAL; + +- rtw89_write32_port_mask(rtwdev, rtwvif, p->bcn_space, B_AX_BCN_SPACE_MASK, ++ rtw89_write32_port_mask(rtwdev, rtwvif_link, p->bcn_space, B_AX_BCN_SPACE_MASK, + bcn_int); + } + + static void rtw89_mac_port_cfg_hiq_win(struct rtw89_dev *rtwdev, +- struct rtw89_vif *rtwvif) ++ struct rtw89_vif_link *rtwvif_link) + { +- u8 win = rtwvif->net_type == RTW89_NET_TYPE_AP_MODE ? 16 : 0; ++ u8 win = rtwvif_link->net_type == RTW89_NET_TYPE_AP_MODE ? 16 : 0; + const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; + const struct rtw89_port_reg *p = mac->port_base; +- u8 port = rtwvif->port; ++ u8 port = rtwvif_link->port; + u32 reg; + +- reg = rtw89_mac_reg_by_idx(rtwdev, p->hiq_win[port], rtwvif->mac_idx); ++ reg = rtw89_mac_reg_by_idx(rtwdev, p->hiq_win[port], rtwvif_link->mac_idx); + rtw89_write8(rtwdev, reg, win); + } + + static void rtw89_mac_port_cfg_hiq_dtim(struct rtw89_dev *rtwdev, +- struct rtw89_vif *rtwvif) ++ struct rtw89_vif_link *rtwvif_link) + { + const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; + const struct rtw89_port_reg *p = mac->port_base; +- struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif); ++ struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif_link); + u32 addr; + +- addr = rtw89_mac_reg_by_idx(rtwdev, p->md_tsft, rtwvif->mac_idx); ++ addr = rtw89_mac_reg_by_idx(rtwdev, p->md_tsft, rtwvif_link->mac_idx); + rtw89_write8_set(rtwdev, addr, B_AX_UPD_HGQMD | B_AX_UPD_TIMIE); + +- rtw89_write16_port_mask(rtwdev, rtwvif, p->dtim_ctrl, B_AX_DTIM_NUM_MASK, ++ rtw89_write16_port_mask(rtwdev, rtwvif_link, p->dtim_ctrl, B_AX_DTIM_NUM_MASK, + vif->bss_conf.dtim_period); + } + + static void rtw89_mac_port_cfg_bcn_setup_time(struct rtw89_dev *rtwdev, +- struct rtw89_vif *rtwvif) ++ struct rtw89_vif_link *rtwvif_link) + { + const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; + const struct rtw89_port_reg *p = mac->port_base; + +- rtw89_write32_port_mask(rtwdev, rtwvif, p->tbtt_prohib, ++ rtw89_write32_port_mask(rtwdev, rtwvif_link, p->tbtt_prohib, + B_AX_TBTT_SETUP_MASK, BCN_SETUP_DEF); + } + + static void rtw89_mac_port_cfg_bcn_hold_time(struct rtw89_dev *rtwdev, +- struct rtw89_vif *rtwvif) ++ struct rtw89_vif_link *rtwvif_link) + { + const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; + const struct rtw89_port_reg *p = mac->port_base; + +- rtw89_write32_port_mask(rtwdev, rtwvif, p->tbtt_prohib, ++ rtw89_write32_port_mask(rtwdev, rtwvif_link, p->tbtt_prohib, + B_AX_TBTT_HOLD_MASK, BCN_HOLD_DEF); + } + + static void rtw89_mac_port_cfg_bcn_mask_area(struct rtw89_dev *rtwdev, +- struct rtw89_vif *rtwvif) ++ struct rtw89_vif_link *rtwvif_link) + { + const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; + const struct rtw89_port_reg *p = mac->port_base; + +- rtw89_write32_port_mask(rtwdev, rtwvif, p->bcn_area, ++ rtw89_write32_port_mask(rtwdev, rtwvif_link, p->bcn_area, + B_AX_BCN_MSK_AREA_MASK, BCN_MASK_DEF); + } + + static void rtw89_mac_port_cfg_tbtt_early(struct rtw89_dev *rtwdev, +- struct rtw89_vif *rtwvif) ++ struct rtw89_vif_link *rtwvif_link) + { + const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; + const struct rtw89_port_reg *p = mac->port_base; + +- rtw89_write16_port_mask(rtwdev, rtwvif, p->tbtt_early, ++ rtw89_write16_port_mask(rtwdev, rtwvif_link, p->tbtt_early, + B_AX_TBTTERLY_MASK, TBTT_ERLY_DEF); + } + + static void rtw89_mac_port_cfg_bss_color(struct rtw89_dev *rtwdev, +- struct rtw89_vif *rtwvif) ++ struct rtw89_vif_link *rtwvif_link) + { + const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; + const struct rtw89_port_reg *p = mac->port_base; +- struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif); ++ struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif_link); + static const u32 masks[RTW89_PORT_NUM] = { + B_AX_BSS_COLOB_AX_PORT_0_MASK, B_AX_BSS_COLOB_AX_PORT_1_MASK, + B_AX_BSS_COLOB_AX_PORT_2_MASK, B_AX_BSS_COLOB_AX_PORT_3_MASK, + B_AX_BSS_COLOB_AX_PORT_4_MASK, + }; +- u8 port = rtwvif->port; ++ u8 port = rtwvif_link->port; + u32 reg_base; + u32 reg; + u8 bss_color; + + bss_color = vif->bss_conf.he_bss_color.color; + reg_base = port >= 4 ? p->bss_color + 4 : p->bss_color; +- reg = rtw89_mac_reg_by_idx(rtwdev, reg_base, rtwvif->mac_idx); ++ reg = rtw89_mac_reg_by_idx(rtwdev, reg_base, rtwvif_link->mac_idx); + rtw89_write32_mask(rtwdev, reg, masks[port], bss_color); + } + + static void rtw89_mac_port_cfg_mbssid(struct rtw89_dev *rtwdev, +- struct rtw89_vif *rtwvif) ++ struct rtw89_vif_link *rtwvif_link) + { + const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; + const struct rtw89_port_reg *p = mac->port_base; +- u8 port = rtwvif->port; ++ u8 port = rtwvif_link->port; + u32 reg; + +- if (rtwvif->net_type == RTW89_NET_TYPE_AP_MODE) ++ if (rtwvif_link->net_type == RTW89_NET_TYPE_AP_MODE) + return; + + if (port == 0) { +- reg = rtw89_mac_reg_by_idx(rtwdev, p->mbssid, rtwvif->mac_idx); ++ reg = rtw89_mac_reg_by_idx(rtwdev, p->mbssid, rtwvif_link->mac_idx); + rtw89_write32_clr(rtwdev, reg, B_AX_P0MB_ALL_MASK); + } + } + + static void rtw89_mac_port_cfg_hiq_drop(struct rtw89_dev *rtwdev, +- struct rtw89_vif *rtwvif) ++ struct rtw89_vif_link *rtwvif_link) + { + const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; + const struct rtw89_port_reg *p = mac->port_base; +- u8 port = rtwvif->port; ++ u8 port = rtwvif_link->port; + u32 reg; + u32 val; + +- reg = rtw89_mac_reg_by_idx(rtwdev, p->mbssid_drop, rtwvif->mac_idx); ++ reg = rtw89_mac_reg_by_idx(rtwdev, p->mbssid_drop, rtwvif_link->mac_idx); + val = rtw89_read32(rtwdev, reg); + val &= ~FIELD_PREP(B_AX_PORT_DROP_4_0_MASK, BIT(port)); + if (port == 0) +@@ -4419,31 +4433,31 @@ static void rtw89_mac_port_cfg_hiq_drop(struct rtw89_dev *rtwdev, + } + + static void rtw89_mac_port_cfg_func_en(struct rtw89_dev *rtwdev, +- struct rtw89_vif *rtwvif, bool enable) ++ struct rtw89_vif_link *rtwvif_link, bool enable) + { + const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; + const struct rtw89_port_reg *p = mac->port_base; + + if (enable) +- rtw89_write32_port_set(rtwdev, rtwvif, p->port_cfg, ++ rtw89_write32_port_set(rtwdev, rtwvif_link, p->port_cfg, + B_AX_PORT_FUNC_EN); + else +- rtw89_write32_port_clr(rtwdev, rtwvif, p->port_cfg, ++ rtw89_write32_port_clr(rtwdev, rtwvif_link, p->port_cfg, + B_AX_PORT_FUNC_EN); + } + + static void rtw89_mac_port_cfg_bcn_early(struct rtw89_dev *rtwdev, +- struct rtw89_vif *rtwvif) ++ struct rtw89_vif_link *rtwvif_link) + { + const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; + const struct rtw89_port_reg *p = mac->port_base; + +- rtw89_write32_port_mask(rtwdev, rtwvif, p->bcn_early, B_AX_BCNERLY_MASK, ++ rtw89_write32_port_mask(rtwdev, rtwvif_link, p->bcn_early, B_AX_BCNERLY_MASK, + BCN_ERLY_DEF); + } + + static void rtw89_mac_port_cfg_tbtt_shift(struct rtw89_dev *rtwdev, +- struct rtw89_vif *rtwvif) ++ struct rtw89_vif_link *rtwvif_link) + { + const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; + const struct rtw89_port_reg *p = mac->port_base; +@@ -4452,20 +4466,20 @@ static void rtw89_mac_port_cfg_tbtt_shift(struct rtw89_dev *rtwdev, + if (rtwdev->chip->chip_id != RTL8852C) + return; + +- if (rtwvif->wifi_role != RTW89_WIFI_ROLE_P2P_CLIENT && +- rtwvif->wifi_role != RTW89_WIFI_ROLE_STATION) ++ if (rtwvif_link->wifi_role != RTW89_WIFI_ROLE_P2P_CLIENT && ++ rtwvif_link->wifi_role != RTW89_WIFI_ROLE_STATION) + return; + + val = FIELD_PREP(B_AX_TBTT_SHIFT_OFST_MAG, 1) | + B_AX_TBTT_SHIFT_OFST_SIGN; + +- rtw89_write16_port_mask(rtwdev, rtwvif, p->tbtt_shift, ++ rtw89_write16_port_mask(rtwdev, rtwvif_link, p->tbtt_shift, + B_AX_TBTT_SHIFT_OFST_MASK, val); + } + + void rtw89_mac_port_tsf_sync(struct rtw89_dev *rtwdev, +- struct rtw89_vif *rtwvif, +- struct rtw89_vif *rtwvif_src, ++ struct rtw89_vif_link *rtwvif_link, ++ struct rtw89_vif_link *rtwvif_src, + u16 offset_tu) + { + const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; +@@ -4473,8 +4487,8 @@ void rtw89_mac_port_tsf_sync(struct rtw89_dev *rtwdev, + u32 val, reg; + + val = RTW89_PORT_OFFSET_TU_TO_32US(offset_tu); +- reg = rtw89_mac_reg_by_idx(rtwdev, p->tsf_sync + rtwvif->port * 4, +- rtwvif->mac_idx); ++ reg = rtw89_mac_reg_by_idx(rtwdev, p->tsf_sync + rtwvif_link->port * 4, ++ rtwvif_link->mac_idx); + + rtw89_write32_mask(rtwdev, reg, B_AX_SYNC_PORT_SRC, rtwvif_src->port); + rtw89_write32_mask(rtwdev, reg, B_AX_SYNC_PORT_OFFSET_VAL, val); +@@ -4482,16 +4496,16 @@ void rtw89_mac_port_tsf_sync(struct rtw89_dev *rtwdev, + } + + static void rtw89_mac_port_tsf_sync_rand(struct rtw89_dev *rtwdev, +- struct rtw89_vif *rtwvif, +- struct rtw89_vif *rtwvif_src, ++ struct rtw89_vif_link *rtwvif_link, ++ struct rtw89_vif_link *rtwvif_src, + u8 offset, int *n_offset) + { +- if (rtwvif->net_type != RTW89_NET_TYPE_AP_MODE || rtwvif == rtwvif_src) ++ if (rtwvif_link->net_type != RTW89_NET_TYPE_AP_MODE || rtwvif_link == rtwvif_src) + return; + + /* adjust offset randomly to avoid beacon conflict */ + offset = offset - offset / 4 + get_random_u32() % (offset / 2); +- rtw89_mac_port_tsf_sync(rtwdev, rtwvif, rtwvif_src, ++ rtw89_mac_port_tsf_sync(rtwdev, rtwvif_link, rtwvif_src, + (*n_offset) * offset); + + (*n_offset)++; +@@ -4499,7 +4513,7 @@ static void rtw89_mac_port_tsf_sync_rand(struct rtw89_dev *rtwdev, + + static void rtw89_mac_port_tsf_resync_all(struct rtw89_dev *rtwdev) + { +- struct rtw89_vif *src = NULL, *tmp; ++ struct rtw89_vif_link *src = NULL, *tmp; + u8 offset = 100, vif_aps = 0; + int n_offset = 1; + +@@ -4519,100 +4533,100 @@ static void rtw89_mac_port_tsf_resync_all(struct rtw89_dev *rtwdev) + rtw89_mac_port_tsf_sync_rand(rtwdev, tmp, src, offset, &n_offset); + } + +-int rtw89_mac_vif_init(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif) ++int rtw89_mac_vif_init(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link) + { + int ret; + +- ret = rtw89_mac_port_update(rtwdev, rtwvif); ++ ret = rtw89_mac_port_update(rtwdev, rtwvif_link); + if (ret) + return ret; + +- rtw89_mac_dmac_tbl_init(rtwdev, rtwvif->mac_id); +- rtw89_mac_cmac_tbl_init(rtwdev, rtwvif->mac_id); ++ rtw89_mac_dmac_tbl_init(rtwdev, rtwvif_link->mac_id); ++ rtw89_mac_cmac_tbl_init(rtwdev, rtwvif_link->mac_id); + +- ret = rtw89_mac_set_macid_pause(rtwdev, rtwvif->mac_id, false); ++ ret = rtw89_mac_set_macid_pause(rtwdev, rtwvif_link->mac_id, false); + if (ret) + return ret; + +- ret = rtw89_fw_h2c_role_maintain(rtwdev, rtwvif, NULL, RTW89_ROLE_CREATE); ++ ret = rtw89_fw_h2c_role_maintain(rtwdev, rtwvif_link, NULL, RTW89_ROLE_CREATE); + if (ret) + return ret; + +- ret = rtw89_fw_h2c_join_info(rtwdev, rtwvif, NULL, true); ++ ret = rtw89_fw_h2c_join_info(rtwdev, rtwvif_link, NULL, true); + if (ret) + return ret; + +- ret = rtw89_cam_init(rtwdev, rtwvif); ++ ret = rtw89_cam_init(rtwdev, rtwvif_link); + if (ret) + return ret; + +- ret = rtw89_fw_h2c_cam(rtwdev, rtwvif, NULL, NULL); ++ ret = rtw89_fw_h2c_cam(rtwdev, rtwvif_link, NULL, NULL); + if (ret) + return ret; + +- ret = rtw89_chip_h2c_default_cmac_tbl(rtwdev, rtwvif, NULL); ++ ret = rtw89_chip_h2c_default_cmac_tbl(rtwdev, rtwvif_link, NULL); + if (ret) + return ret; + +- ret = rtw89_chip_h2c_default_dmac_tbl(rtwdev, rtwvif, NULL); ++ ret = rtw89_chip_h2c_default_dmac_tbl(rtwdev, rtwvif_link, NULL); + if (ret) + return ret; + + return 0; + } + +-int rtw89_mac_vif_deinit(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif) ++int rtw89_mac_vif_deinit(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link) + { + int ret; + +- ret = rtw89_fw_h2c_role_maintain(rtwdev, rtwvif, NULL, RTW89_ROLE_REMOVE); ++ ret = rtw89_fw_h2c_role_maintain(rtwdev, rtwvif_link, NULL, RTW89_ROLE_REMOVE); + if (ret) + return ret; + +- rtw89_cam_deinit(rtwdev, rtwvif); ++ rtw89_cam_deinit(rtwdev, rtwvif_link); + +- ret = rtw89_fw_h2c_cam(rtwdev, rtwvif, NULL, NULL); ++ ret = rtw89_fw_h2c_cam(rtwdev, rtwvif_link, NULL, NULL); + if (ret) + return ret; + + return 0; + } + +-int rtw89_mac_port_update(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif) ++int rtw89_mac_port_update(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link) + { +- u8 port = rtwvif->port; ++ u8 port = rtwvif_link->port; + + if (port >= RTW89_PORT_NUM) + return -EINVAL; + +- rtw89_mac_port_cfg_func_sw(rtwdev, rtwvif); +- rtw89_mac_port_cfg_tx_rpt(rtwdev, rtwvif, false); +- rtw89_mac_port_cfg_rx_rpt(rtwdev, rtwvif, false); +- rtw89_mac_port_cfg_net_type(rtwdev, rtwvif); +- rtw89_mac_port_cfg_bcn_prct(rtwdev, rtwvif); +- rtw89_mac_port_cfg_rx_sw(rtwdev, rtwvif); +- rtw89_mac_port_cfg_rx_sync_by_nettype(rtwdev, rtwvif); +- rtw89_mac_port_cfg_tx_sw_by_nettype(rtwdev, rtwvif); +- rtw89_mac_port_cfg_bcn_intv(rtwdev, rtwvif); +- rtw89_mac_port_cfg_hiq_win(rtwdev, rtwvif); +- rtw89_mac_port_cfg_hiq_dtim(rtwdev, rtwvif); +- rtw89_mac_port_cfg_hiq_drop(rtwdev, rtwvif); +- rtw89_mac_port_cfg_bcn_setup_time(rtwdev, rtwvif); +- rtw89_mac_port_cfg_bcn_hold_time(rtwdev, rtwvif); +- rtw89_mac_port_cfg_bcn_mask_area(rtwdev, rtwvif); +- rtw89_mac_port_cfg_tbtt_early(rtwdev, rtwvif); +- rtw89_mac_port_cfg_tbtt_shift(rtwdev, rtwvif); +- rtw89_mac_port_cfg_bss_color(rtwdev, rtwvif); +- rtw89_mac_port_cfg_mbssid(rtwdev, rtwvif); +- rtw89_mac_port_cfg_func_en(rtwdev, rtwvif, true); ++ rtw89_mac_port_cfg_func_sw(rtwdev, rtwvif_link); ++ rtw89_mac_port_cfg_tx_rpt(rtwdev, rtwvif_link, false); ++ rtw89_mac_port_cfg_rx_rpt(rtwdev, rtwvif_link, false); ++ rtw89_mac_port_cfg_net_type(rtwdev, rtwvif_link); ++ rtw89_mac_port_cfg_bcn_prct(rtwdev, rtwvif_link); ++ rtw89_mac_port_cfg_rx_sw(rtwdev, rtwvif_link); ++ rtw89_mac_port_cfg_rx_sync_by_nettype(rtwdev, rtwvif_link); ++ rtw89_mac_port_cfg_tx_sw_by_nettype(rtwdev, rtwvif_link); ++ rtw89_mac_port_cfg_bcn_intv(rtwdev, rtwvif_link); ++ rtw89_mac_port_cfg_hiq_win(rtwdev, rtwvif_link); ++ rtw89_mac_port_cfg_hiq_dtim(rtwdev, rtwvif_link); ++ rtw89_mac_port_cfg_hiq_drop(rtwdev, rtwvif_link); ++ rtw89_mac_port_cfg_bcn_setup_time(rtwdev, rtwvif_link); ++ rtw89_mac_port_cfg_bcn_hold_time(rtwdev, rtwvif_link); ++ rtw89_mac_port_cfg_bcn_mask_area(rtwdev, rtwvif_link); ++ rtw89_mac_port_cfg_tbtt_early(rtwdev, rtwvif_link); ++ rtw89_mac_port_cfg_tbtt_shift(rtwdev, rtwvif_link); ++ rtw89_mac_port_cfg_bss_color(rtwdev, rtwvif_link); ++ rtw89_mac_port_cfg_mbssid(rtwdev, rtwvif_link); ++ rtw89_mac_port_cfg_func_en(rtwdev, rtwvif_link, true); + rtw89_mac_port_tsf_resync_all(rtwdev); + fsleep(BCN_ERLY_SET_DLY); +- rtw89_mac_port_cfg_bcn_early(rtwdev, rtwvif); ++ rtw89_mac_port_cfg_bcn_early(rtwdev, rtwvif_link); + + return 0; + } + +-int rtw89_mac_port_get_tsf(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, ++int rtw89_mac_port_get_tsf(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, + u64 *tsf) + { + const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; +@@ -4620,12 +4634,12 @@ int rtw89_mac_port_get_tsf(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, + u32 tsf_low, tsf_high; + int ret; + +- ret = rtw89_mac_check_mac_en(rtwdev, rtwvif->mac_idx, RTW89_CMAC_SEL); ++ ret = rtw89_mac_check_mac_en(rtwdev, rtwvif_link->mac_idx, RTW89_CMAC_SEL); + if (ret) + return ret; + +- tsf_low = rtw89_read32_port(rtwdev, rtwvif, p->tsftr_l); +- tsf_high = rtw89_read32_port(rtwdev, rtwvif, p->tsftr_h); ++ tsf_low = rtw89_read32_port(rtwdev, rtwvif_link, p->tsftr_l); ++ tsf_high = rtw89_read32_port(rtwdev, rtwvif_link, p->tsftr_h); + *tsf = (u64)tsf_high << 32 | tsf_low; + + return 0; +@@ -4653,7 +4667,7 @@ static void rtw89_mac_check_he_obss_narrow_bw_ru_iter(struct wiphy *wiphy, + void rtw89_mac_set_he_obss_narrow_bw_ru(struct rtw89_dev *rtwdev, + struct ieee80211_vif *vif) + { +- struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; ++ struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv; + const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; + struct ieee80211_hw *hw = rtwdev->hw; + bool tolerated = true; +@@ -4670,44 +4684,44 @@ void rtw89_mac_set_he_obss_narrow_bw_ru(struct rtw89_dev *rtwdev, + &tolerated); + + reg = rtw89_mac_reg_by_idx(rtwdev, mac->narrow_bw_ru_dis.addr, +- rtwvif->mac_idx); ++ rtwvif_link->mac_idx); + if (tolerated) + rtw89_write32_clr(rtwdev, reg, mac->narrow_bw_ru_dis.mask); + else + rtw89_write32_set(rtwdev, reg, mac->narrow_bw_ru_dis.mask); + } + +-void rtw89_mac_stop_ap(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif) ++void rtw89_mac_stop_ap(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link) + { +- rtw89_mac_port_cfg_func_sw(rtwdev, rtwvif); ++ rtw89_mac_port_cfg_func_sw(rtwdev, rtwvif_link); + } + +-int rtw89_mac_add_vif(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif) ++int rtw89_mac_add_vif(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link) + { + int ret; + +- rtwvif->mac_id = rtw89_acquire_mac_id(rtwdev); +- if (rtwvif->mac_id == RTW89_MAX_MAC_ID_NUM) ++ rtwvif_link->mac_id = rtw89_acquire_mac_id(rtwdev); ++ if (rtwvif_link->mac_id == RTW89_MAX_MAC_ID_NUM) + return -ENOSPC; + +- ret = rtw89_mac_vif_init(rtwdev, rtwvif); ++ ret = rtw89_mac_vif_init(rtwdev, rtwvif_link); + if (ret) + goto release_mac_id; + + return 0; + + release_mac_id: +- rtw89_release_mac_id(rtwdev, rtwvif->mac_id); ++ rtw89_release_mac_id(rtwdev, rtwvif_link->mac_id); + + return ret; + } + +-int rtw89_mac_remove_vif(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif) ++int rtw89_mac_remove_vif(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link) + { + int ret; + +- ret = rtw89_mac_vif_deinit(rtwdev, rtwvif); +- rtw89_release_mac_id(rtwdev, rtwvif->mac_id); ++ ret = rtw89_mac_vif_deinit(rtwdev, rtwvif_link); ++ rtw89_release_mac_id(rtwdev, rtwvif_link->mac_id); + + return ret; + } +@@ -4731,7 +4745,7 @@ rtw89_mac_c2h_scanofld_rsp(struct rtw89_dev *rtwdev, struct sk_buff *skb, + const struct rtw89_c2h_scanofld *c2h = + (const struct rtw89_c2h_scanofld *)skb->data; + struct ieee80211_vif *vif = rtwdev->scan_info.scanning_vif; +- struct rtw89_vif *rtwvif = vif_to_rtwvif_safe(vif); ++ struct rtw89_vif_link *rtwvif_link = vif_to_rtwvif_safe(vif); + struct rtw89_chan new; + u8 reason, status, tx_fail, band, actual_period, expect_period; + u32 last_chan = rtwdev->scan_info.last_chan_idx, report_tsf; +@@ -4739,7 +4753,7 @@ rtw89_mac_c2h_scanofld_rsp(struct rtw89_dev *rtwdev, struct sk_buff *skb, + u16 chan; + int ret; + +- if (!rtwvif) ++ if (!rtwvif_link) + return; + + tx_fail = le32_get_bits(c2h->w5, RTW89_C2H_SCANOFLD_W5_TX_FAIL); +@@ -4781,8 +4795,8 @@ rtw89_mac_c2h_scanofld_rsp(struct rtw89_dev *rtwdev, struct sk_buff *skb, + if (rtwdev->scan_info.abort) + return; + +- if (rtwvif && rtwvif->scan_req && +- last_chan < rtwvif->scan_req->n_channels) { ++ if (rtwvif_link && rtwvif_link->scan_req && ++ last_chan < rtwvif_link->scan_req->n_channels) { + ret = rtw89_hw_scan_offload(rtwdev, vif, true); + if (ret) { + rtw89_hw_scan_abort(rtwdev, vif); +@@ -4795,14 +4809,14 @@ rtw89_mac_c2h_scanofld_rsp(struct rtw89_dev *rtwdev, struct sk_buff *skb, + case RTW89_SCAN_ENTER_OP_NOTIFY: + case RTW89_SCAN_ENTER_CH_NOTIFY: + if (rtw89_is_op_chan(rtwdev, band, chan)) { +- rtw89_assign_entity_chan(rtwdev, rtwvif->chanctx_idx, ++ rtw89_assign_entity_chan(rtwdev, rtwvif_link->chanctx_idx, + &rtwdev->scan_info.op_chan); + rtw89_mac_enable_beacon_for_ap_vifs(rtwdev, true); + ieee80211_wake_queues(rtwdev->hw); + } else { + rtw89_chan_create(&new, chan, chan, band, + RTW89_CHANNEL_WIDTH_20); +- rtw89_assign_entity_chan(rtwdev, rtwvif->chanctx_idx, ++ rtw89_assign_entity_chan(rtwdev, rtwvif_link->chanctx_idx, + &new); + } + break; +@@ -4812,10 +4826,10 @@ rtw89_mac_c2h_scanofld_rsp(struct rtw89_dev *rtwdev, struct sk_buff *skb, + } + + static void +-rtw89_mac_bcn_fltr_rpt(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, ++rtw89_mac_bcn_fltr_rpt(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, + struct sk_buff *skb) + { +- struct ieee80211_vif *vif = rtwvif_to_vif_safe(rtwvif); ++ struct ieee80211_vif *vif = rtwvif_to_vif_safe(rtwvif_link); + enum nl80211_cqm_rssi_threshold_event nl_event; + const struct rtw89_c2h_mac_bcnfltr_rpt *c2h = + (const struct rtw89_c2h_mac_bcnfltr_rpt *)skb->data; +@@ -4827,7 +4841,7 @@ rtw89_mac_bcn_fltr_rpt(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, + event = le32_get_bits(c2h->w2, RTW89_C2H_MAC_BCNFLTR_RPT_W2_EVENT); + mac_id = le32_get_bits(c2h->w2, RTW89_C2H_MAC_BCNFLTR_RPT_W2_MACID); + +- if (mac_id != rtwvif->mac_id) ++ if (mac_id != rtwvif_link->mac_id) + return; + + rtw89_debug(rtwdev, RTW89_DBG_FW, +@@ -4836,7 +4850,7 @@ rtw89_mac_bcn_fltr_rpt(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, + + switch (type) { + case RTW89_BCN_FLTR_BEACON_LOSS: +- if (!rtwdev->scanning && !rtwvif->offchan) ++ if (!rtwdev->scanning && !rtwvif_link->offchan) + ieee80211_connection_loss(vif); + else + rtw89_fw_h2c_set_bcn_fltr_cfg(rtwdev, vif, true); +@@ -4863,10 +4877,10 @@ static void + rtw89_mac_c2h_bcn_fltr_rpt(struct rtw89_dev *rtwdev, struct sk_buff *c2h, + u32 len) + { +- struct rtw89_vif *rtwvif; ++ struct rtw89_vif_link *rtwvif_link; + +- rtw89_for_each_rtwvif(rtwdev, rtwvif) +- rtw89_mac_bcn_fltr_rpt(rtwdev, rtwvif, c2h); ++ rtw89_for_each_rtwvif(rtwdev, rtwvif_link) ++ rtw89_mac_bcn_fltr_rpt(rtwdev, rtwvif_link, c2h); + } + + static void +@@ -5934,10 +5948,10 @@ static int rtw89_mac_set_csi_para_reg_ax(struct rtw89_dev *rtwdev, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta) + { +- struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; +- u8 mac_idx = rtwvif->mac_idx; ++ struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv; ++ u8 mac_idx = rtwvif_link->mac_idx; + u8 nc = 1, nr = 3, ng = 0, cb = 1, cs = 1, ldpc_en = 1, stbc_en = 1; +- u8 port_sel = rtwvif->port; ++ u8 port_sel = rtwvif_link->port; + u8 sound_dim = 3, t; + u8 *phy_cap = sta->deflink.he_cap.he_cap_elem.phy_cap_info; + u32 reg; +@@ -5992,10 +6006,10 @@ static int rtw89_mac_csi_rrsc_ax(struct rtw89_dev *rtwdev, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta) + { +- struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; ++ struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv; + u32 rrsc = BIT(RTW89_MAC_BF_RRSC_6M) | BIT(RTW89_MAC_BF_RRSC_24M); + u32 reg; +- u8 mac_idx = rtwvif->mac_idx; ++ u8 mac_idx = rtwvif_link->mac_idx; + int ret; + + ret = rtw89_mac_check_mac_en(rtwdev, mac_idx, RTW89_CMAC_SEL); +@@ -6031,12 +6045,12 @@ static void rtw89_mac_bf_assoc_ax(struct rtw89_dev *rtwdev, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta) + { +- struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; ++ struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv; + + if (rtw89_sta_has_beamformer_cap(sta)) { + rtw89_debug(rtwdev, RTW89_DBG_BF, + "initialize bfee for new association\n"); +- rtw89_mac_init_bfee_ax(rtwdev, rtwvif->mac_idx); ++ rtw89_mac_init_bfee_ax(rtwdev, rtwvif_link->mac_idx); + rtw89_mac_set_csi_para_reg_ax(rtwdev, vif, sta); + rtw89_mac_csi_rrsc_ax(rtwdev, vif, sta); + } +@@ -6045,16 +6059,16 @@ static void rtw89_mac_bf_assoc_ax(struct rtw89_dev *rtwdev, + void rtw89_mac_bf_disassoc(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif, + struct ieee80211_sta *sta) + { +- struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; ++ struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv; + +- rtw89_mac_bfee_ctrl(rtwdev, rtwvif->mac_idx, false); ++ rtw89_mac_bfee_ctrl(rtwdev, rtwvif_link->mac_idx, false); + } + + void rtw89_mac_bf_set_gid_table(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif, + struct ieee80211_bss_conf *conf) + { +- struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; +- u8 mac_idx = rtwvif->mac_idx; ++ struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv; ++ u8 mac_idx = rtwvif_link->mac_idx; + __le32 *p; + + rtw89_debug(rtwdev, RTW89_DBG_BF, "update bf GID table\n"); +@@ -6121,7 +6135,7 @@ void rtw89_mac_bf_monitor_calc(struct rtw89_dev *rtwdev, + void _rtw89_mac_bf_monitor_track(struct rtw89_dev *rtwdev) + { + struct rtw89_traffic_stats *stats = &rtwdev->stats; +- struct rtw89_vif *rtwvif; ++ struct rtw89_vif_link *rtwvif_link; + bool en = stats->tx_tfc_lv <= stats->rx_tfc_lv; + bool old = test_bit(RTW89_FLAG_BFEE_EN, rtwdev->flags); + bool keep_timer = true; +@@ -6133,16 +6147,16 @@ void _rtw89_mac_bf_monitor_track(struct rtw89_dev *rtwdev) + keep_timer = false; + + if (keep_timer != old_keep_timer) { +- rtw89_for_each_rtwvif(rtwdev, rtwvif) +- rtw89_mac_bfee_standby_timer(rtwdev, rtwvif->mac_idx, ++ rtw89_for_each_rtwvif(rtwdev, rtwvif_link) ++ rtw89_mac_bfee_standby_timer(rtwdev, rtwvif_link->mac_idx, + keep_timer); + } + + if (en == old) + return; + +- rtw89_for_each_rtwvif(rtwdev, rtwvif) +- rtw89_mac_bfee_ctrl(rtwdev, rtwvif->mac_idx, en); ++ rtw89_for_each_rtwvif(rtwdev, rtwvif_link) ++ rtw89_mac_bfee_ctrl(rtwdev, rtwvif_link->mac_idx, en); + } + + static int +@@ -6150,7 +6164,7 @@ __rtw89_mac_set_tx_time(struct rtw89_dev *rtwdev, struct rtw89_sta *rtwsta, + u32 tx_time) + { + #define MAC_AX_DFLT_TX_TIME 5280 +- u8 mac_idx = rtwsta->rtwvif->mac_idx; ++ u8 mac_idx = rtwsta->rtwvif_link->mac_idx; + u32 max_tx_time = tx_time == 0 ? MAC_AX_DFLT_TX_TIME : tx_time; + u32 reg; + int ret = 0; +@@ -6192,7 +6206,7 @@ int rtw89_mac_set_tx_time(struct rtw89_dev *rtwdev, struct rtw89_sta *rtwsta, + int rtw89_mac_get_tx_time(struct rtw89_dev *rtwdev, struct rtw89_sta *rtwsta, + u32 *tx_time) + { +- u8 mac_idx = rtwsta->rtwvif->mac_idx; ++ u8 mac_idx = rtwsta->rtwvif_link->mac_idx; + u32 reg; + int ret = 0; + +@@ -6234,7 +6248,7 @@ int rtw89_mac_set_tx_retry_limit(struct rtw89_dev *rtwdev, + int rtw89_mac_get_tx_retry_limit(struct rtw89_dev *rtwdev, + struct rtw89_sta *rtwsta, u8 *tx_retry) + { +- u8 mac_idx = rtwsta->rtwvif->mac_idx; ++ u8 mac_idx = rtwsta->rtwvif_link->mac_idx; + u32 reg; + int ret = 0; + +@@ -6255,10 +6269,10 @@ int rtw89_mac_get_tx_retry_limit(struct rtw89_dev *rtwdev, + } + + int rtw89_mac_set_hw_muedca_ctrl(struct rtw89_dev *rtwdev, +- struct rtw89_vif *rtwvif, bool en) ++ struct rtw89_vif_link *rtwvif_link, bool en) + { + const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; +- u8 mac_idx = rtwvif->mac_idx; ++ u8 mac_idx = rtwvif_link->mac_idx; + u16 set = mac->muedca_ctrl.mask; + u32 reg; + u32 ret; +@@ -6334,15 +6348,15 @@ void rtw89_mac_pkt_drop_sta(struct rtw89_dev *rtwdev, struct rtw89_sta *rtwsta) + RTW89_PKT_DROP_SEL_MACID_VI_ONCE, + RTW89_PKT_DROP_SEL_MACID_VO_ONCE, + }; +- struct rtw89_vif *rtwvif = rtwsta->rtwvif; ++ struct rtw89_vif_link *rtwvif_link = rtwsta->rtwvif_link; + struct rtw89_pkt_drop_params params = {0}; + int i; + + params.mac_band = RTW89_MAC_0; + params.macid = rtwsta->mac_id; +- params.port = rtwvif->port; ++ params.port = rtwvif_link->port; + params.mbssid = 0; +- params.tf_trs = rtwvif->trigger; ++ params.tf_trs = rtwvif_link->trigger; + + for (i = 0; i < ARRAY_SIZE(sels); i++) { + params.sel = sels[i]; +@@ -6353,21 +6367,21 @@ void rtw89_mac_pkt_drop_sta(struct rtw89_dev *rtwdev, struct rtw89_sta *rtwsta) + static void rtw89_mac_pkt_drop_vif_iter(void *data, struct ieee80211_sta *sta) + { + struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv; +- struct rtw89_vif *rtwvif = rtwsta->rtwvif; +- struct rtw89_dev *rtwdev = rtwvif->rtwdev; +- struct rtw89_vif *target = data; ++ struct rtw89_vif_link *rtwvif_link = rtwsta->rtwvif_link; ++ struct rtw89_dev *rtwdev = rtwvif_link->rtwdev; ++ struct rtw89_vif_link *target = data; + +- if (rtwvif != target) ++ if (rtwvif_link != target) + return; + + rtw89_mac_pkt_drop_sta(rtwdev, rtwsta); + } + +-void rtw89_mac_pkt_drop_vif(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif) ++void rtw89_mac_pkt_drop_vif(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link) + { + ieee80211_iterate_stations_atomic(rtwdev->hw, + rtw89_mac_pkt_drop_vif_iter, +- rtwvif); ++ rtwvif_link); + } + + int rtw89_mac_ptk_drop_by_band_and_wait(struct rtw89_dev *rtwdev, +diff --git a/drivers/net/wireless/realtek/rtw89/mac.h b/drivers/net/wireless/realtek/rtw89/mac.h +index 67c2a45071244..6839028991d4a 100644 +--- a/drivers/net/wireless/realtek/rtw89/mac.h ++++ b/drivers/net/wireless/realtek/rtw89/mac.h +@@ -1004,12 +1004,12 @@ struct rtw89_mac_gen_def { + bool (*is_txq_empty)(struct rtw89_dev *rtwdev); + + int (*add_chan_list)(struct rtw89_dev *rtwdev, +- struct rtw89_vif *rtwvif, bool connected); ++ struct rtw89_vif_link *rtwvif_link, bool connected); + int (*add_chan_list_pno)(struct rtw89_dev *rtwdev, +- struct rtw89_vif *rtwvif); ++ struct rtw89_vif_link *rtwvif_link); + int (*scan_offload)(struct rtw89_dev *rtwdev, + struct rtw89_scan_option *option, +- struct rtw89_vif *rtwvif, ++ struct rtw89_vif_link *rtwvif_link, + bool wowlan); + + int (*wow_config_mac)(struct rtw89_dev *rtwdev, bool enable_wow); +@@ -1033,81 +1033,89 @@ u32 rtw89_mac_reg_by_port(struct rtw89_dev *rtwdev, u32 base, u8 port, u8 mac_id + } + + static inline u32 +-rtw89_read32_port(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, u32 base) ++rtw89_read32_port(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, u32 base) + { + u32 reg; + +- reg = rtw89_mac_reg_by_port(rtwdev, base, rtwvif->port, rtwvif->mac_idx); ++ reg = rtw89_mac_reg_by_port(rtwdev, base, rtwvif_link->port, ++ rtwvif_link->mac_idx); + return rtw89_read32(rtwdev, reg); + } + + static inline u32 +-rtw89_read32_port_mask(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, ++rtw89_read32_port_mask(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, + u32 base, u32 mask) + { + u32 reg; + +- reg = rtw89_mac_reg_by_port(rtwdev, base, rtwvif->port, rtwvif->mac_idx); ++ reg = rtw89_mac_reg_by_port(rtwdev, base, rtwvif_link->port, ++ rtwvif_link->mac_idx); + return rtw89_read32_mask(rtwdev, reg, mask); + } + + static inline void +-rtw89_write32_port(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, u32 base, ++rtw89_write32_port(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, u32 base, + u32 data) + { + u32 reg; + +- reg = rtw89_mac_reg_by_port(rtwdev, base, rtwvif->port, rtwvif->mac_idx); ++ reg = rtw89_mac_reg_by_port(rtwdev, base, rtwvif_link->port, ++ rtwvif_link->mac_idx); + rtw89_write32(rtwdev, reg, data); + } + + static inline void +-rtw89_write32_port_mask(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, ++rtw89_write32_port_mask(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, + u32 base, u32 mask, u32 data) + { + u32 reg; + +- reg = rtw89_mac_reg_by_port(rtwdev, base, rtwvif->port, rtwvif->mac_idx); ++ reg = rtw89_mac_reg_by_port(rtwdev, base, rtwvif_link->port, ++ rtwvif_link->mac_idx); + rtw89_write32_mask(rtwdev, reg, mask, data); + } + + static inline void +-rtw89_write16_port_mask(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, ++rtw89_write16_port_mask(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, + u32 base, u32 mask, u16 data) + { + u32 reg; + +- reg = rtw89_mac_reg_by_port(rtwdev, base, rtwvif->port, rtwvif->mac_idx); ++ reg = rtw89_mac_reg_by_port(rtwdev, base, rtwvif_link->port, ++ rtwvif_link->mac_idx); + rtw89_write16_mask(rtwdev, reg, mask, data); + } + + static inline void +-rtw89_write32_port_clr(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, ++rtw89_write32_port_clr(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, + u32 base, u32 bit) + { + u32 reg; + +- reg = rtw89_mac_reg_by_port(rtwdev, base, rtwvif->port, rtwvif->mac_idx); ++ reg = rtw89_mac_reg_by_port(rtwdev, base, rtwvif_link->port, ++ rtwvif_link->mac_idx); + rtw89_write32_clr(rtwdev, reg, bit); + } + + static inline void +-rtw89_write16_port_clr(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, ++rtw89_write16_port_clr(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, + u32 base, u16 bit) + { + u32 reg; + +- reg = rtw89_mac_reg_by_port(rtwdev, base, rtwvif->port, rtwvif->mac_idx); ++ reg = rtw89_mac_reg_by_port(rtwdev, base, rtwvif_link->port, ++ rtwvif_link->mac_idx); + rtw89_write16_clr(rtwdev, reg, bit); + } + + static inline void +-rtw89_write32_port_set(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, ++rtw89_write32_port_set(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, + u32 base, u32 bit) + { + u32 reg; + +- reg = rtw89_mac_reg_by_port(rtwdev, base, rtwvif->port, rtwvif->mac_idx); ++ reg = rtw89_mac_reg_by_port(rtwdev, base, rtwvif_link->port, ++ rtwvif_link->mac_idx); + rtw89_write32_set(rtwdev, reg, bit); + } + +@@ -1139,21 +1147,21 @@ int rtw89_mac_dle_dfi_qempty_cfg(struct rtw89_dev *rtwdev, + struct rtw89_mac_dle_dfi_qempty *qempty); + void rtw89_mac_dump_l0_to_l1(struct rtw89_dev *rtwdev, + enum mac_ax_err_info err); +-int rtw89_mac_add_vif(struct rtw89_dev *rtwdev, struct rtw89_vif *vif); +-int rtw89_mac_port_update(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif); ++int rtw89_mac_add_vif(struct rtw89_dev *rtwdev, struct rtw89_vif_link *vif); ++int rtw89_mac_port_update(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link); + void rtw89_mac_port_tsf_sync(struct rtw89_dev *rtwdev, +- struct rtw89_vif *rtwvif, +- struct rtw89_vif *rtwvif_src, ++ struct rtw89_vif_link *rtwvif_link, ++ struct rtw89_vif_link *rtwvif_src, + u16 offset_tu); +-int rtw89_mac_port_get_tsf(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, ++int rtw89_mac_port_get_tsf(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, + u64 *tsf); + void rtw89_mac_port_cfg_rx_sync(struct rtw89_dev *rtwdev, +- struct rtw89_vif *rtwvif, bool en); ++ struct rtw89_vif_link *rtwvif_link, bool en); + void rtw89_mac_set_he_obss_narrow_bw_ru(struct rtw89_dev *rtwdev, + struct ieee80211_vif *vif); +-void rtw89_mac_stop_ap(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif); ++void rtw89_mac_stop_ap(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link); + void rtw89_mac_enable_beacon_for_ap_vifs(struct rtw89_dev *rtwdev, bool en); +-int rtw89_mac_remove_vif(struct rtw89_dev *rtwdev, struct rtw89_vif *vif); ++int rtw89_mac_remove_vif(struct rtw89_dev *rtwdev, struct rtw89_vif_link *vif); + int rtw89_mac_enable_bb_rf(struct rtw89_dev *rtwdev); + int rtw89_mac_disable_bb_rf(struct rtw89_dev *rtwdev); + +@@ -1268,10 +1276,10 @@ void rtw89_mac_bf_monitor_calc(struct rtw89_dev *rtwdev, + struct ieee80211_sta *sta, bool disconnect); + void _rtw89_mac_bf_monitor_track(struct rtw89_dev *rtwdev); + void rtw89_mac_bfee_ctrl(struct rtw89_dev *rtwdev, u8 mac_idx, bool en); +-int rtw89_mac_vif_init(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif); +-int rtw89_mac_vif_deinit(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif); ++int rtw89_mac_vif_init(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link); ++int rtw89_mac_vif_deinit(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link); + int rtw89_mac_set_hw_muedca_ctrl(struct rtw89_dev *rtwdev, +- struct rtw89_vif *rtwvif, bool en); ++ struct rtw89_vif_link *rtwvif_link, bool en); + int rtw89_mac_set_macid_pause(struct rtw89_dev *rtwdev, u8 macid, bool pause); + + static inline void rtw89_mac_bf_monitor_track(struct rtw89_dev *rtwdev) +@@ -1454,7 +1462,7 @@ int rtw89_mac_read_xtal_si(struct rtw89_dev *rtwdev, u8 offset, u8 *val) + return mac->read_xtal_si(rtwdev, offset, val); + } + +-void rtw89_mac_pkt_drop_vif(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif); ++void rtw89_mac_pkt_drop_vif(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link); + int rtw89_mac_resize_ple_rx_quota(struct rtw89_dev *rtwdev, bool wow); + int rtw89_mac_ptk_drop_by_band_and_wait(struct rtw89_dev *rtwdev, + enum rtw89_mac_idx band); +diff --git a/drivers/net/wireless/realtek/rtw89/mac80211.c b/drivers/net/wireless/realtek/rtw89/mac80211.c +index 48ad0d0f76bff..bc0ff64c1c982 100644 +--- a/drivers/net/wireless/realtek/rtw89/mac80211.c ++++ b/drivers/net/wireless/realtek/rtw89/mac80211.c +@@ -23,12 +23,12 @@ static void rtw89_ops_tx(struct ieee80211_hw *hw, + struct rtw89_dev *rtwdev = hw->priv; + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); + struct ieee80211_vif *vif = info->control.vif; +- struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; ++ struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv; + struct ieee80211_sta *sta = control->sta; + u32 flags = IEEE80211_SKB_CB(skb)->flags; + int ret, qsel; + +- if (rtwvif->offchan && !(flags & IEEE80211_TX_CTL_TX_OFFCHAN) && sta) { ++ if (rtwvif_link->offchan && !(flags & IEEE80211_TX_CTL_TX_OFFCHAN) && sta) { + struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv; + + rtw89_debug(rtwdev, RTW89_DBG_TXRX, "ops_tx during offchan\n"); +@@ -109,7 +109,7 @@ static int rtw89_ops_add_interface(struct ieee80211_hw *hw, + struct ieee80211_vif *vif) + { + struct rtw89_dev *rtwdev = hw->priv; +- struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; ++ struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv; + int ret = 0; + + rtw89_debug(rtwdev, RTW89_DBG_STATE, "add vif %pM type %d, p2p %d\n", +@@ -123,46 +123,46 @@ static int rtw89_ops_add_interface(struct ieee80211_hw *hw, + vif->driver_flags |= IEEE80211_VIF_BEACON_FILTER | + IEEE80211_VIF_SUPPORTS_CQM_RSSI; + +- rtwvif->rtwdev = rtwdev; +- rtwvif->roc.state = RTW89_ROC_IDLE; +- rtwvif->offchan = false; +- if (!rtw89_rtwvif_in_list(rtwdev, rtwvif)) +- list_add_tail(&rtwvif->list, &rtwdev->rtwvifs_list); ++ rtwvif_link->rtwdev = rtwdev; ++ rtwvif_link->roc.state = RTW89_ROC_IDLE; ++ rtwvif_link->offchan = false; ++ if (!rtw89_rtwvif_in_list(rtwdev, rtwvif_link)) ++ list_add_tail(&rtwvif_link->list, &rtwdev->rtwvifs_list); + +- INIT_WORK(&rtwvif->update_beacon_work, rtw89_core_update_beacon_work); +- INIT_DELAYED_WORK(&rtwvif->roc.roc_work, rtw89_roc_work); ++ INIT_WORK(&rtwvif_link->update_beacon_work, rtw89_core_update_beacon_work); ++ INIT_DELAYED_WORK(&rtwvif_link->roc.roc_work, rtw89_roc_work); + rtw89_leave_ps_mode(rtwdev); + +- rtw89_traffic_stats_init(rtwdev, &rtwvif->stats); ++ rtw89_traffic_stats_init(rtwdev, &rtwvif_link->stats); + rtw89_vif_type_mapping(vif, false); +- rtwvif->port = rtw89_core_acquire_bit_map(rtwdev->hw_port, +- RTW89_PORT_NUM); +- if (rtwvif->port == RTW89_PORT_NUM) { ++ rtwvif_link->port = rtw89_core_acquire_bit_map(rtwdev->hw_port, ++ RTW89_PORT_NUM); ++ if (rtwvif_link->port == RTW89_PORT_NUM) { + ret = -ENOSPC; +- list_del_init(&rtwvif->list); ++ list_del_init(&rtwvif_link->list); + goto out; + } + +- rtwvif->bcn_hit_cond = 0; +- rtwvif->mac_idx = RTW89_MAC_0; +- rtwvif->phy_idx = RTW89_PHY_0; +- rtwvif->chanctx_idx = RTW89_CHANCTX_0; +- rtwvif->chanctx_assigned = false; +- rtwvif->hit_rule = 0; +- rtwvif->reg_6ghz_power = RTW89_REG_6GHZ_POWER_DFLT; +- ether_addr_copy(rtwvif->mac_addr, vif->addr); +- INIT_LIST_HEAD(&rtwvif->general_pkt_list); +- +- ret = rtw89_mac_add_vif(rtwdev, rtwvif); ++ rtwvif_link->bcn_hit_cond = 0; ++ rtwvif_link->mac_idx = RTW89_MAC_0; ++ rtwvif_link->phy_idx = RTW89_PHY_0; ++ rtwvif_link->chanctx_idx = RTW89_CHANCTX_0; ++ rtwvif_link->chanctx_assigned = false; ++ rtwvif_link->hit_rule = 0; ++ rtwvif_link->reg_6ghz_power = RTW89_REG_6GHZ_POWER_DFLT; ++ ether_addr_copy(rtwvif_link->mac_addr, vif->addr); ++ INIT_LIST_HEAD(&rtwvif_link->general_pkt_list); ++ ++ ret = rtw89_mac_add_vif(rtwdev, rtwvif_link); + if (ret) { +- rtw89_core_release_bit_map(rtwdev->hw_port, rtwvif->port); +- list_del_init(&rtwvif->list); ++ rtw89_core_release_bit_map(rtwdev->hw_port, rtwvif_link->port); ++ list_del_init(&rtwvif_link->list); + goto out; + } + + rtw89_core_txq_init(rtwdev, vif->txq); + +- rtw89_btc_ntfy_role_info(rtwdev, rtwvif, NULL, BTC_ROLE_START); ++ rtw89_btc_ntfy_role_info(rtwdev, rtwvif_link, NULL, BTC_ROLE_START); + + rtw89_recalc_lps(rtwdev); + out: +@@ -175,20 +175,20 @@ static void rtw89_ops_remove_interface(struct ieee80211_hw *hw, + struct ieee80211_vif *vif) + { + struct rtw89_dev *rtwdev = hw->priv; +- struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; ++ struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv; + + rtw89_debug(rtwdev, RTW89_DBG_STATE, "remove vif %pM type %d p2p %d\n", + vif->addr, vif->type, vif->p2p); + +- cancel_work_sync(&rtwvif->update_beacon_work); +- cancel_delayed_work_sync(&rtwvif->roc.roc_work); ++ cancel_work_sync(&rtwvif_link->update_beacon_work); ++ cancel_delayed_work_sync(&rtwvif_link->roc.roc_work); + + mutex_lock(&rtwdev->mutex); + rtw89_leave_ps_mode(rtwdev); +- rtw89_btc_ntfy_role_info(rtwdev, rtwvif, NULL, BTC_ROLE_STOP); +- rtw89_mac_remove_vif(rtwdev, rtwvif); +- rtw89_core_release_bit_map(rtwdev->hw_port, rtwvif->port); +- list_del_init(&rtwvif->list); ++ rtw89_btc_ntfy_role_info(rtwdev, rtwvif_link, NULL, BTC_ROLE_STOP); ++ rtw89_mac_remove_vif(rtwdev, rtwvif_link); ++ rtw89_core_release_bit_map(rtwdev->hw_port, rtwvif_link->port); ++ list_del_init(&rtwvif_link->list); + rtw89_recalc_lps(rtwdev); + rtw89_enter_ips_by_hwflags(rtwdev); + +@@ -311,11 +311,11 @@ static const u8 ac_to_fw_idx[IEEE80211_NUM_ACS] = { + }; + + static u8 rtw89_aifsn_to_aifs(struct rtw89_dev *rtwdev, +- struct rtw89_vif *rtwvif, u8 aifsn) ++ struct rtw89_vif_link *rtwvif_link, u8 aifsn) + { +- struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif); ++ struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif_link); + const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, +- rtwvif->chanctx_idx); ++ rtwvif_link->chanctx_idx); + u8 slot_time; + u8 sifs; + +@@ -326,9 +326,9 @@ static u8 rtw89_aifsn_to_aifs(struct rtw89_dev *rtwdev, + } + + static void ____rtw89_conf_tx_edca(struct rtw89_dev *rtwdev, +- struct rtw89_vif *rtwvif, u16 ac) ++ struct rtw89_vif_link *rtwvif_link, u16 ac) + { +- struct ieee80211_tx_queue_params *params = &rtwvif->tx_params[ac]; ++ struct ieee80211_tx_queue_params *params = &rtwvif_link->tx_params[ac]; + u32 val; + u8 ecw_max, ecw_min; + u8 aifs; +@@ -336,12 +336,12 @@ static void ____rtw89_conf_tx_edca(struct rtw89_dev *rtwdev, + /* 2^ecw - 1 = cw; ecw = log2(cw + 1) */ + ecw_max = ilog2(params->cw_max + 1); + ecw_min = ilog2(params->cw_min + 1); +- aifs = rtw89_aifsn_to_aifs(rtwdev, rtwvif, params->aifs); ++ aifs = rtw89_aifsn_to_aifs(rtwdev, rtwvif_link, params->aifs); + val = FIELD_PREP(FW_EDCA_PARAM_TXOPLMT_MSK, params->txop) | + FIELD_PREP(FW_EDCA_PARAM_CWMAX_MSK, ecw_max) | + FIELD_PREP(FW_EDCA_PARAM_CWMIN_MSK, ecw_min) | + FIELD_PREP(FW_EDCA_PARAM_AIFS_MSK, aifs); +- rtw89_fw_h2c_set_edca(rtwdev, rtwvif, ac_to_fw_idx[ac], val); ++ rtw89_fw_h2c_set_edca(rtwdev, rtwvif_link, ac_to_fw_idx[ac], val); + } + + #define R_MUEDCA_ACS_PARAM(acs) {R_AX_MUEDCA_ ## acs ## _PARAM_0, \ +@@ -355,9 +355,9 @@ static const u32 ac_to_mu_edca_param[IEEE80211_NUM_ACS][RTW89_CHIP_GEN_NUM] = { + }; + + static void ____rtw89_conf_tx_mu_edca(struct rtw89_dev *rtwdev, +- struct rtw89_vif *rtwvif, u16 ac) ++ struct rtw89_vif_link *rtwvif_link, u16 ac) + { +- struct ieee80211_tx_queue_params *params = &rtwvif->tx_params[ac]; ++ struct ieee80211_tx_queue_params *params = &rtwvif_link->tx_params[ac]; + struct ieee80211_he_mu_edca_param_ac_rec *mu_edca; + int gen = rtwdev->chip->chip_gen; + u8 aifs, aifsn; +@@ -370,32 +370,33 @@ static void ____rtw89_conf_tx_mu_edca(struct rtw89_dev *rtwdev, + + mu_edca = ¶ms->mu_edca_param_rec; + aifsn = FIELD_GET(GENMASK(3, 0), mu_edca->aifsn); +- aifs = aifsn ? rtw89_aifsn_to_aifs(rtwdev, rtwvif, aifsn) : 0; ++ aifs = aifsn ? rtw89_aifsn_to_aifs(rtwdev, rtwvif_link, aifsn) : 0; + timer_32us = mu_edca->mu_edca_timer << 8; + + val = FIELD_PREP(B_AX_MUEDCA_BE_PARAM_0_TIMER_MASK, timer_32us) | + FIELD_PREP(B_AX_MUEDCA_BE_PARAM_0_CW_MASK, mu_edca->ecw_min_max) | + FIELD_PREP(B_AX_MUEDCA_BE_PARAM_0_AIFS_MASK, aifs); +- reg = rtw89_mac_reg_by_idx(rtwdev, ac_to_mu_edca_param[ac][gen], rtwvif->mac_idx); ++ reg = rtw89_mac_reg_by_idx(rtwdev, ac_to_mu_edca_param[ac][gen], ++ rtwvif_link->mac_idx); + rtw89_write32(rtwdev, reg, val); + +- rtw89_mac_set_hw_muedca_ctrl(rtwdev, rtwvif, true); ++ rtw89_mac_set_hw_muedca_ctrl(rtwdev, rtwvif_link, true); + } + + static void __rtw89_conf_tx(struct rtw89_dev *rtwdev, +- struct rtw89_vif *rtwvif, u16 ac) ++ struct rtw89_vif_link *rtwvif_link, u16 ac) + { +- ____rtw89_conf_tx_edca(rtwdev, rtwvif, ac); +- ____rtw89_conf_tx_mu_edca(rtwdev, rtwvif, ac); ++ ____rtw89_conf_tx_edca(rtwdev, rtwvif_link, ac); ++ ____rtw89_conf_tx_mu_edca(rtwdev, rtwvif_link, ac); + } + + static void rtw89_conf_tx(struct rtw89_dev *rtwdev, +- struct rtw89_vif *rtwvif) ++ struct rtw89_vif_link *rtwvif_link) + { + u16 ac; + + for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) +- __rtw89_conf_tx(rtwdev, rtwvif, ac); ++ __rtw89_conf_tx(rtwdev, rtwvif_link, ac); + } + + static void rtw89_station_mode_sta_assoc(struct rtw89_dev *rtwdev, +@@ -421,7 +422,7 @@ static void rtw89_ops_vif_cfg_changed(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, u64 changed) + { + struct rtw89_dev *rtwdev = hw->priv; +- struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; ++ struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv; + + mutex_lock(&rtwdev->mutex); + rtw89_leave_ps_mode(rtwdev); +@@ -431,7 +432,7 @@ static void rtw89_ops_vif_cfg_changed(struct ieee80211_hw *hw, + rtw89_station_mode_sta_assoc(rtwdev, vif); + rtw89_phy_set_bss_color(rtwdev, vif); + rtw89_chip_cfg_txpwr_ul_tb_offset(rtwdev, vif); +- rtw89_mac_port_update(rtwdev, rtwvif); ++ rtw89_mac_port_update(rtwdev, rtwvif_link); + rtw89_mac_set_he_obss_narrow_bw_ru(rtwdev, vif); + + rtw89_queue_chanctx_work(rtwdev); +@@ -448,7 +449,7 @@ static void rtw89_ops_vif_cfg_changed(struct ieee80211_hw *hw, + rtw89_recalc_lps(rtwdev); + + if (changed & BSS_CHANGED_ARP_FILTER) +- rtwvif->ip_addr = vif->cfg.arp_addr_list[0]; ++ rtwvif_link->ip_addr = vif->cfg.arp_addr_list[0]; + + mutex_unlock(&rtwdev->mutex); + } +@@ -459,23 +460,23 @@ static void rtw89_ops_link_info_changed(struct ieee80211_hw *hw, + u64 changed) + { + struct rtw89_dev *rtwdev = hw->priv; +- struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; ++ struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv; + + mutex_lock(&rtwdev->mutex); + rtw89_leave_ps_mode(rtwdev); + + if (changed & BSS_CHANGED_BSSID) { +- ether_addr_copy(rtwvif->bssid, conf->bssid); +- rtw89_cam_bssid_changed(rtwdev, rtwvif); +- rtw89_fw_h2c_cam(rtwdev, rtwvif, NULL, NULL); +- WRITE_ONCE(rtwvif->sync_bcn_tsf, 0); ++ ether_addr_copy(rtwvif_link->bssid, conf->bssid); ++ rtw89_cam_bssid_changed(rtwdev, rtwvif_link); ++ rtw89_fw_h2c_cam(rtwdev, rtwvif_link, NULL, NULL); ++ WRITE_ONCE(rtwvif_link->sync_bcn_tsf, 0); + } + + if (changed & BSS_CHANGED_BEACON) +- rtw89_chip_h2c_update_beacon(rtwdev, rtwvif); ++ rtw89_chip_h2c_update_beacon(rtwdev, rtwvif_link); + + if (changed & BSS_CHANGED_ERP_SLOT) +- rtw89_conf_tx(rtwdev, rtwvif); ++ rtw89_conf_tx(rtwdev, rtwvif_link); + + if (changed & BSS_CHANGED_HE_BSS_COLOR) + rtw89_phy_set_bss_color(rtwdev, vif); +@@ -490,7 +491,7 @@ static void rtw89_ops_link_info_changed(struct ieee80211_hw *hw, + rtw89_fw_h2c_set_bcn_fltr_cfg(rtwdev, vif, true); + + if (changed & BSS_CHANGED_TPE) +- rtw89_reg_6ghz_recalc(rtwdev, rtwvif, true); ++ rtw89_reg_6ghz_recalc(rtwdev, rtwvif_link, true); + + mutex_unlock(&rtwdev->mutex); + } +@@ -500,12 +501,12 @@ static int rtw89_ops_start_ap(struct ieee80211_hw *hw, + struct ieee80211_bss_conf *link_conf) + { + struct rtw89_dev *rtwdev = hw->priv; +- struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; ++ struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv; + const struct rtw89_chan *chan; + + mutex_lock(&rtwdev->mutex); + +- chan = rtw89_chan_get(rtwdev, rtwvif->chanctx_idx); ++ chan = rtw89_chan_get(rtwdev, rtwvif_link->chanctx_idx); + if (chan->band_type == RTW89_BAND_6G) { + mutex_unlock(&rtwdev->mutex); + return -EOPNOTSUPP; +@@ -514,14 +515,14 @@ static int rtw89_ops_start_ap(struct ieee80211_hw *hw, + if (rtwdev->scanning) + rtw89_hw_scan_abort(rtwdev, rtwdev->scan_info.scanning_vif); + +- ether_addr_copy(rtwvif->bssid, vif->bss_conf.bssid); +- rtw89_cam_bssid_changed(rtwdev, rtwvif); +- rtw89_mac_port_update(rtwdev, rtwvif); ++ ether_addr_copy(rtwvif_link->bssid, vif->bss_conf.bssid); ++ rtw89_cam_bssid_changed(rtwdev, rtwvif_link); ++ rtw89_mac_port_update(rtwdev, rtwvif_link); + rtw89_chip_h2c_assoc_cmac_tbl(rtwdev, vif, NULL); +- rtw89_fw_h2c_role_maintain(rtwdev, rtwvif, NULL, RTW89_ROLE_TYPE_CHANGE); +- rtw89_fw_h2c_join_info(rtwdev, rtwvif, NULL, true); +- rtw89_fw_h2c_cam(rtwdev, rtwvif, NULL, NULL); +- rtw89_chip_rfk_channel(rtwdev, rtwvif); ++ rtw89_fw_h2c_role_maintain(rtwdev, rtwvif_link, NULL, RTW89_ROLE_TYPE_CHANGE); ++ rtw89_fw_h2c_join_info(rtwdev, rtwvif_link, NULL, true); ++ rtw89_fw_h2c_cam(rtwdev, rtwvif_link, NULL, NULL); ++ rtw89_chip_rfk_channel(rtwdev, rtwvif_link); + + rtw89_queue_chanctx_work(rtwdev); + mutex_unlock(&rtwdev->mutex); +@@ -534,12 +535,12 @@ void rtw89_ops_stop_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + struct ieee80211_bss_conf *link_conf) + { + struct rtw89_dev *rtwdev = hw->priv; +- struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; ++ struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv; + + mutex_lock(&rtwdev->mutex); +- rtw89_mac_stop_ap(rtwdev, rtwvif); ++ rtw89_mac_stop_ap(rtwdev, rtwvif_link); + rtw89_chip_h2c_assoc_cmac_tbl(rtwdev, vif, NULL); +- rtw89_fw_h2c_join_info(rtwdev, rtwvif, NULL, true); ++ rtw89_fw_h2c_join_info(rtwdev, rtwvif_link, NULL, true); + mutex_unlock(&rtwdev->mutex); + } + +@@ -548,9 +549,9 @@ static int rtw89_ops_set_tim(struct ieee80211_hw *hw, struct ieee80211_sta *sta, + { + struct rtw89_dev *rtwdev = hw->priv; + struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv; +- struct rtw89_vif *rtwvif = rtwsta->rtwvif; ++ struct rtw89_vif_link *rtwvif_link = rtwsta->rtwvif_link; + +- ieee80211_queue_work(rtwdev->hw, &rtwvif->update_beacon_work); ++ ieee80211_queue_work(rtwdev->hw, &rtwvif_link->update_beacon_work); + + return 0; + } +@@ -561,12 +562,12 @@ static int rtw89_ops_conf_tx(struct ieee80211_hw *hw, + const struct ieee80211_tx_queue_params *params) + { + struct rtw89_dev *rtwdev = hw->priv; +- struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; ++ struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv; + + mutex_lock(&rtwdev->mutex); + rtw89_leave_ps_mode(rtwdev); +- rtwvif->tx_params[ac] = *params; +- __rtw89_conf_tx(rtwdev, rtwvif, ac); ++ rtwvif_link->tx_params[ac] = *params; ++ __rtw89_conf_tx(rtwdev, rtwvif_link, ac); + mutex_unlock(&rtwdev->mutex); + + return 0; +@@ -740,14 +741,14 @@ static void rtw89_ops_sta_statistics(struct ieee80211_hw *hw, + static + void __rtw89_drop_packets(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif) + { +- struct rtw89_vif *rtwvif; ++ struct rtw89_vif_link *rtwvif_link; + + if (vif) { +- rtwvif = (struct rtw89_vif *)vif->drv_priv; +- rtw89_mac_pkt_drop_vif(rtwdev, rtwvif); ++ rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv; ++ rtw89_mac_pkt_drop_vif(rtwdev, rtwvif_link); + } else { +- rtw89_for_each_rtwvif(rtwdev, rtwvif) +- rtw89_mac_pkt_drop_vif(rtwdev, rtwvif); ++ rtw89_for_each_rtwvif(rtwdev, rtwvif_link) ++ rtw89_mac_pkt_drop_vif(rtwdev, rtwvif_link); + } + } + +@@ -778,7 +779,7 @@ static void rtw89_ra_mask_info_update_iter(void *data, struct ieee80211_sta *sta + { + struct rtw89_iter_bitrate_mask_data *br_data = data; + struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv; +- struct ieee80211_vif *vif = rtwvif_to_vif(rtwsta->rtwvif); ++ struct ieee80211_vif *vif = rtwvif_to_vif(rtwsta->rtwvif_link); + + if (vif != br_data->vif || vif->p2p) + return; +@@ -854,10 +855,10 @@ static void rtw89_ops_sw_scan_start(struct ieee80211_hw *hw, + const u8 *mac_addr) + { + struct rtw89_dev *rtwdev = hw->priv; +- struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; ++ struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv; + + mutex_lock(&rtwdev->mutex); +- rtw89_core_scan_start(rtwdev, rtwvif, mac_addr, false); ++ rtw89_core_scan_start(rtwdev, rtwvif_link, mac_addr, false); + mutex_unlock(&rtwdev->mutex); + } + +@@ -884,13 +885,13 @@ static int rtw89_ops_hw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + struct ieee80211_scan_request *req) + { + struct rtw89_dev *rtwdev = hw->priv; +- struct rtw89_vif *rtwvif = vif_to_rtwvif_safe(vif); ++ struct rtw89_vif_link *rtwvif_link = vif_to_rtwvif_safe(vif); + int ret = 0; + + if (!RTW89_CHK_FW_FEATURE(SCAN_OFFLOAD, &rtwdev->fw)) + return 1; + +- if (rtwdev->scanning || rtwvif->offchan) ++ if (rtwdev->scanning || rtwvif_link->offchan) + return -EBUSY; + + mutex_lock(&rtwdev->mutex); +@@ -970,11 +971,11 @@ static int rtw89_ops_assign_vif_chanctx(struct ieee80211_hw *hw, + struct ieee80211_chanctx_conf *ctx) + { + struct rtw89_dev *rtwdev = hw->priv; +- struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; ++ struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv; + int ret; + + mutex_lock(&rtwdev->mutex); +- ret = rtw89_chanctx_ops_assign_vif(rtwdev, rtwvif, ctx); ++ ret = rtw89_chanctx_ops_assign_vif(rtwdev, rtwvif_link, ctx); + mutex_unlock(&rtwdev->mutex); + + return ret; +@@ -986,10 +987,10 @@ static void rtw89_ops_unassign_vif_chanctx(struct ieee80211_hw *hw, + struct ieee80211_chanctx_conf *ctx) + { + struct rtw89_dev *rtwdev = hw->priv; +- struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; ++ struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv; + + mutex_lock(&rtwdev->mutex); +- rtw89_chanctx_ops_unassign_vif(rtwdev, rtwvif, ctx); ++ rtw89_chanctx_ops_unassign_vif(rtwdev, rtwvif_link, ctx); + mutex_unlock(&rtwdev->mutex); + } + +@@ -1000,8 +1001,8 @@ static int rtw89_ops_remain_on_channel(struct ieee80211_hw *hw, + enum ieee80211_roc_type type) + { + struct rtw89_dev *rtwdev = hw->priv; +- struct rtw89_vif *rtwvif = vif_to_rtwvif_safe(vif); +- struct rtw89_roc *roc = &rtwvif->roc; ++ struct rtw89_vif_link *rtwvif_link = vif_to_rtwvif_safe(vif); ++ struct rtw89_roc *roc = &rtwvif_link->roc; + + if (!vif) + return -EINVAL; +@@ -1025,7 +1026,7 @@ static int rtw89_ops_remain_on_channel(struct ieee80211_hw *hw, + roc->chan = *chan; + roc->type = type; + +- rtw89_roc_start(rtwdev, rtwvif); ++ rtw89_roc_start(rtwdev, rtwvif_link); + + mutex_unlock(&rtwdev->mutex); + +@@ -1036,15 +1037,15 @@ static int rtw89_ops_cancel_remain_on_channel(struct ieee80211_hw *hw, + struct ieee80211_vif *vif) + { + struct rtw89_dev *rtwdev = hw->priv; +- struct rtw89_vif *rtwvif = vif_to_rtwvif_safe(vif); ++ struct rtw89_vif_link *rtwvif_link = vif_to_rtwvif_safe(vif); + +- if (!rtwvif) ++ if (!rtwvif_link) + return -EINVAL; + +- cancel_delayed_work_sync(&rtwvif->roc.roc_work); ++ cancel_delayed_work_sync(&rtwvif_link->roc.roc_work); + + mutex_lock(&rtwdev->mutex); +- rtw89_roc_end(rtwdev, rtwvif); ++ rtw89_roc_end(rtwdev, rtwvif_link); + mutex_unlock(&rtwdev->mutex); + + return 0; +@@ -1054,7 +1055,7 @@ static void rtw89_set_tid_config_iter(void *data, struct ieee80211_sta *sta) + { + struct cfg80211_tid_config *tid_config = data; + struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv; +- struct rtw89_dev *rtwdev = rtwsta->rtwvif->rtwdev; ++ struct rtw89_dev *rtwdev = rtwsta->rtwvif_link->rtwdev; + + rtw89_core_set_tid_config(rtwdev, sta, tid_config); + } +diff --git a/drivers/net/wireless/realtek/rtw89/mac_be.c b/drivers/net/wireless/realtek/rtw89/mac_be.c +index 31f0a5225b115..bc3215939f37b 100644 +--- a/drivers/net/wireless/realtek/rtw89/mac_be.c ++++ b/drivers/net/wireless/realtek/rtw89/mac_be.c +@@ -2094,10 +2094,10 @@ static int rtw89_mac_set_csi_para_reg_be(struct rtw89_dev *rtwdev, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta) + { +- struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; ++ struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv; + u8 nc = 1, nr = 3, ng = 0, cb = 1, cs = 1, ldpc_en = 1, stbc_en = 1; +- u8 mac_idx = rtwvif->mac_idx; +- u8 port_sel = rtwvif->port; ++ u8 mac_idx = rtwvif_link->mac_idx; ++ u8 port_sel = rtwvif_link->port; + u8 sound_dim = 3, t; + u8 *phy_cap; + u32 reg; +@@ -2158,9 +2158,9 @@ static int rtw89_mac_csi_rrsc_be(struct rtw89_dev *rtwdev, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta) + { +- struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; ++ struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv; + u32 rrsc = BIT(RTW89_MAC_BF_RRSC_6M) | BIT(RTW89_MAC_BF_RRSC_24M); +- u8 mac_idx = rtwvif->mac_idx; ++ u8 mac_idx = rtwvif_link->mac_idx; + int ret; + u32 reg; + +@@ -2198,12 +2198,12 @@ static void rtw89_mac_bf_assoc_be(struct rtw89_dev *rtwdev, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta) + { +- struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; ++ struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv; + + if (rtw89_sta_has_beamformer_cap(sta)) { + rtw89_debug(rtwdev, RTW89_DBG_BF, + "initialize bfee for new association\n"); +- rtw89_mac_init_bfee_be(rtwdev, rtwvif->mac_idx); ++ rtw89_mac_init_bfee_be(rtwdev, rtwvif_link->mac_idx); + rtw89_mac_set_csi_para_reg_be(rtwdev, vif, sta); + rtw89_mac_csi_rrsc_be(rtwdev, vif, sta); + } +diff --git a/drivers/net/wireless/realtek/rtw89/phy.c b/drivers/net/wireless/realtek/rtw89/phy.c +index c7165e757842b..742720f1a429e 100644 +--- a/drivers/net/wireless/realtek/rtw89/phy.c ++++ b/drivers/net/wireless/realtek/rtw89/phy.c +@@ -298,12 +298,12 @@ static void rtw89_phy_ra_sta_update(struct rtw89_dev *rtwdev, + struct ieee80211_sta *sta, bool csi) + { + struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv; +- struct rtw89_vif *rtwvif = rtwsta->rtwvif; +- struct rtw89_phy_rate_pattern *rate_pattern = &rtwvif->rate_pattern; ++ struct rtw89_vif_link *rtwvif_link = rtwsta->rtwvif_link; ++ struct rtw89_phy_rate_pattern *rate_pattern = &rtwvif_link->rate_pattern; + struct rtw89_ra_info *ra = &rtwsta->ra; + const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, +- rtwvif->chanctx_idx); +- struct ieee80211_vif *vif = rtwvif_to_vif(rtwsta->rtwvif); ++ rtwvif_link->chanctx_idx); ++ struct ieee80211_vif *vif = rtwvif_to_vif(rtwsta->rtwvif_link); + const u64 *high_rate_masks = rtw89_ra_mask_ht_rates; + u8 rssi = ewma_rssi_read(&rtwsta->avg_rssi); + u64 ra_mask = 0; +@@ -458,7 +458,7 @@ static void rtw89_phy_ra_sta_update(struct rtw89_dev *rtwdev, + ra->fixed_csi_rate_en = false; + ra->ra_csi_rate_en = true; + ra->cr_tbl_sel = false; +- ra->band_num = rtwvif->phy_idx; ++ ra->band_num = rtwvif_link->phy_idx; + ra->csi_bw = bw_mode; + ra->csi_gi_ltf = RTW89_GILTF_LGI_4XHE32; + ra->csi_mcs_ss_idx = 5; +@@ -528,10 +528,10 @@ void rtw89_phy_rate_pattern_vif(struct rtw89_dev *rtwdev, + const struct cfg80211_bitrate_mask *mask) + { + struct ieee80211_supported_band *sband; +- struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; ++ struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv; + struct rtw89_phy_rate_pattern next_pattern = {0}; + const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, +- rtwvif->chanctx_idx); ++ rtwvif_link->chanctx_idx); + static const u16 hw_rate_he[][RTW89_CHIP_GEN_NUM] = { + RTW89_HW_RATE_BY_CHIP_GEN(HE_NSS1_MCS0), + RTW89_HW_RATE_BY_CHIP_GEN(HE_NSS2_MCS0), +@@ -600,7 +600,7 @@ void rtw89_phy_rate_pattern_vif(struct rtw89_dev *rtwdev, + if (!next_pattern.enable) + goto out; + +- rtwvif->rate_pattern = next_pattern; ++ rtwvif_link->rate_pattern = next_pattern; + rtw89_debug(rtwdev, RTW89_DBG_RA, + "configure pattern: rate 0x%x, mask 0x%llx, mode 0x%x\n", + next_pattern.rate, +@@ -609,7 +609,7 @@ void rtw89_phy_rate_pattern_vif(struct rtw89_dev *rtwdev, + return; + + out: +- rtwvif->rate_pattern.enable = false; ++ rtwvif_link->rate_pattern.enable = false; + rtw89_debug(rtwdev, RTW89_DBG_RA, "unset rate pattern\n"); + } + +@@ -4290,33 +4290,33 @@ void rtw89_phy_cfo_parse(struct rtw89_dev *rtwdev, s16 cfo_val, + cfo->packet_count++; + } + +-void rtw89_phy_ul_tb_assoc(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif) ++void rtw89_phy_ul_tb_assoc(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link) + { + const struct rtw89_chip_info *chip = rtwdev->chip; + const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, +- rtwvif->chanctx_idx); ++ rtwvif_link->chanctx_idx); + struct rtw89_phy_ul_tb_info *ul_tb_info = &rtwdev->ul_tb_info; + + if (!chip->ul_tb_waveform_ctrl) + return; + +- rtwvif->def_tri_idx = ++ rtwvif_link->def_tri_idx = + rtw89_phy_read32_mask(rtwdev, R_DCFO_OPT, B_TXSHAPE_TRIANGULAR_CFG); + + if (chip->chip_id == RTL8852B && rtwdev->hal.cv > CHIP_CBV) +- rtwvif->dyn_tb_bedge_en = false; ++ rtwvif_link->dyn_tb_bedge_en = false; + else if (chan->band_type >= RTW89_BAND_5G && + chan->band_width >= RTW89_CHANNEL_WIDTH_40) +- rtwvif->dyn_tb_bedge_en = true; ++ rtwvif_link->dyn_tb_bedge_en = true; + else +- rtwvif->dyn_tb_bedge_en = false; ++ rtwvif_link->dyn_tb_bedge_en = false; + + rtw89_debug(rtwdev, RTW89_DBG_UL_TB, + "[ULTB] def_if_bandedge=%d, def_tri_idx=%d\n", +- ul_tb_info->def_if_bandedge, rtwvif->def_tri_idx); ++ ul_tb_info->def_if_bandedge, rtwvif_link->def_tri_idx); + rtw89_debug(rtwdev, RTW89_DBG_UL_TB, + "[ULTB] dyn_tb_begde_en=%d, dyn_tb_tri_en=%d\n", +- rtwvif->dyn_tb_bedge_en, ul_tb_info->dyn_tb_tri_en); ++ rtwvif_link->dyn_tb_bedge_en, ul_tb_info->dyn_tb_tri_en); + } + + struct rtw89_phy_ul_tb_check_data { +@@ -4338,7 +4338,7 @@ struct rtw89_phy_power_diff { + }; + + static void rtw89_phy_ofdma_power_diff(struct rtw89_dev *rtwdev, +- struct rtw89_vif *rtwvif) ++ struct rtw89_vif_link *rtwvif_link) + { + static const struct rtw89_phy_power_diff table[2] = { + {0x0, 0x0, 0x0, 0x0, 0xf4, 0x3, 0x3}, +@@ -4350,13 +4350,13 @@ static void rtw89_phy_ofdma_power_diff(struct rtw89_dev *rtwdev, + if (!rtwdev->chip->ul_tb_pwr_diff) + return; + +- if (rtwvif->pwr_diff_en == rtwvif->pre_pwr_diff_en) { +- rtwvif->pwr_diff_en = false; ++ if (rtwvif_link->pwr_diff_en == rtwvif_link->pre_pwr_diff_en) { ++ rtwvif_link->pwr_diff_en = false; + return; + } + +- rtwvif->pre_pwr_diff_en = rtwvif->pwr_diff_en; +- param = &table[rtwvif->pwr_diff_en]; ++ rtwvif_link->pre_pwr_diff_en = rtwvif_link->pwr_diff_en; ++ param = &table[rtwvif_link->pwr_diff_en]; + + rtw89_phy_write32_mask(rtwdev, R_Q_MATRIX_00, B_Q_MATRIX_00_REAL, + param->q_00); +@@ -4365,32 +4365,32 @@ static void rtw89_phy_ofdma_power_diff(struct rtw89_dev *rtwdev, + rtw89_phy_write32_mask(rtwdev, R_CUSTOMIZE_Q_MATRIX, + B_CUSTOMIZE_Q_MATRIX_EN, param->q_matrix_en); + +- reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_PWR_UL_TB_1T, rtwvif->mac_idx); ++ reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_PWR_UL_TB_1T, rtwvif_link->mac_idx); + rtw89_write32_mask(rtwdev, reg, B_AX_PWR_UL_TB_1T_NORM_BW160, + param->ultb_1t_norm_160); + +- reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_PWR_UL_TB_2T, rtwvif->mac_idx); ++ reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_PWR_UL_TB_2T, rtwvif_link->mac_idx); + rtw89_write32_mask(rtwdev, reg, B_AX_PWR_UL_TB_2T_NORM_BW160, + param->ultb_2t_norm_160); + +- reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_PATH_COM1, rtwvif->mac_idx); ++ reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_PATH_COM1, rtwvif_link->mac_idx); + rtw89_write32_mask(rtwdev, reg, B_AX_PATH_COM1_NORM_1STS, + param->com1_norm_1sts); + +- reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_PATH_COM2, rtwvif->mac_idx); ++ reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_PATH_COM2, rtwvif_link->mac_idx); + rtw89_write32_mask(rtwdev, reg, B_AX_PATH_COM2_RESP_1STS_PATH, + param->com2_resp_1sts_path); + } + + static + void rtw89_phy_ul_tb_ctrl_check(struct rtw89_dev *rtwdev, +- struct rtw89_vif *rtwvif, ++ struct rtw89_vif_link *rtwvif_link, + struct rtw89_phy_ul_tb_check_data *ul_tb_data) + { + struct rtw89_traffic_stats *stats = &rtwdev->stats; +- struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif); ++ struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif_link); + +- if (rtwvif->wifi_role != RTW89_WIFI_ROLE_STATION) ++ if (rtwvif_link->wifi_role != RTW89_WIFI_ROLE_STATION) + return; + + if (!vif->cfg.assoc) +@@ -4403,11 +4403,11 @@ void rtw89_phy_ul_tb_ctrl_check(struct rtw89_dev *rtwdev, + ul_tb_data->low_tf_client = true; + + ul_tb_data->valid = true; +- ul_tb_data->def_tri_idx = rtwvif->def_tri_idx; +- ul_tb_data->dyn_tb_bedge_en = rtwvif->dyn_tb_bedge_en; ++ ul_tb_data->def_tri_idx = rtwvif_link->def_tri_idx; ++ ul_tb_data->dyn_tb_bedge_en = rtwvif_link->dyn_tb_bedge_en; + } + +- rtw89_phy_ofdma_power_diff(rtwdev, rtwvif); ++ rtw89_phy_ofdma_power_diff(rtwdev, rtwvif_link); + } + + static void rtw89_phy_ul_tb_waveform_ctrl(struct rtw89_dev *rtwdev, +@@ -4453,7 +4453,7 @@ void rtw89_phy_ul_tb_ctrl_track(struct rtw89_dev *rtwdev) + { + const struct rtw89_chip_info *chip = rtwdev->chip; + struct rtw89_phy_ul_tb_check_data ul_tb_data = {}; +- struct rtw89_vif *rtwvif; ++ struct rtw89_vif_link *rtwvif_link; + + if (!chip->ul_tb_waveform_ctrl && !chip->ul_tb_pwr_diff) + return; +@@ -4461,8 +4461,8 @@ void rtw89_phy_ul_tb_ctrl_track(struct rtw89_dev *rtwdev) + if (rtwdev->total_sta_assoc != 1) + return; + +- rtw89_for_each_rtwvif(rtwdev, rtwvif) +- rtw89_phy_ul_tb_ctrl_check(rtwdev, rtwvif, &ul_tb_data); ++ rtw89_for_each_rtwvif(rtwdev, rtwvif_link) ++ rtw89_phy_ul_tb_ctrl_check(rtwdev, rtwvif_link, &ul_tb_data); + + if (!ul_tb_data.valid) + return; +@@ -5757,13 +5757,13 @@ static void rtw89_phy_tx_path_div_sta_iter(void *data, struct ieee80211_sta *sta + { + struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv; + struct rtw89_dev *rtwdev = rtwsta->rtwdev; +- struct rtw89_vif *rtwvif = rtwsta->rtwvif; ++ struct rtw89_vif_link *rtwvif_link = rtwsta->rtwvif_link; + struct rtw89_hal *hal = &rtwdev->hal; + bool *done = data; + u8 rssi_a, rssi_b; + u32 candidate; + +- if (rtwvif->wifi_role != RTW89_WIFI_ROLE_STATION || sta->tdls) ++ if (rtwvif_link->wifi_role != RTW89_WIFI_ROLE_STATION || sta->tdls) + return; + + if (*done) +diff --git a/drivers/net/wireless/realtek/rtw89/phy.h b/drivers/net/wireless/realtek/rtw89/phy.h +index 6dd8ec46939ac..dc85840312da7 100644 +--- a/drivers/net/wireless/realtek/rtw89/phy.h ++++ b/drivers/net/wireless/realtek/rtw89/phy.h +@@ -957,7 +957,7 @@ void rtw89_phy_set_bss_color(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif + void rtw89_phy_tssi_ctrl_set_bandedge_cfg(struct rtw89_dev *rtwdev, + enum rtw89_mac_idx mac_idx, + enum rtw89_tssi_bandedge_cfg bandedge_cfg); +-void rtw89_phy_ul_tb_assoc(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif); ++void rtw89_phy_ul_tb_assoc(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link); + void rtw89_phy_ul_tb_ctrl_track(struct rtw89_dev *rtwdev); + u8 rtw89_encode_chan_idx(struct rtw89_dev *rtwdev, u8 central_ch, u8 band); + void rtw89_decode_chan_idx(struct rtw89_dev *rtwdev, u8 chan_idx, +diff --git a/drivers/net/wireless/realtek/rtw89/ps.c b/drivers/net/wireless/realtek/rtw89/ps.c +index aebd6404f8025..42a73bba7f5c1 100644 +--- a/drivers/net/wireless/realtek/rtw89/ps.c ++++ b/drivers/net/wireless/realtek/rtw89/ps.c +@@ -62,9 +62,9 @@ static void rtw89_ps_power_mode_change(struct rtw89_dev *rtwdev, bool enter) + rtw89_mac_power_mode_change(rtwdev, enter); + } + +-void __rtw89_enter_ps_mode(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif) ++void __rtw89_enter_ps_mode(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link) + { +- if (rtwvif->wifi_role == RTW89_WIFI_ROLE_P2P_CLIENT) ++ if (rtwvif_link->wifi_role == RTW89_WIFI_ROLE_P2P_CLIENT) + return; + + if (!rtwdev->ps_mode) +@@ -85,23 +85,25 @@ void __rtw89_leave_ps_mode(struct rtw89_dev *rtwdev) + rtw89_ps_power_mode_change(rtwdev, false); + } + +-static void __rtw89_enter_lps(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif) ++static void __rtw89_enter_lps(struct rtw89_dev *rtwdev, ++ struct rtw89_vif_link *rtwvif_link) + { + struct rtw89_lps_parm lps_param = { +- .macid = rtwvif->mac_id, ++ .macid = rtwvif_link->mac_id, + .psmode = RTW89_MAC_AX_PS_MODE_LEGACY, + .lastrpwm = RTW89_LAST_RPWM_PS, + }; + + rtw89_btc_ntfy_radio_state(rtwdev, BTC_RFCTRL_FW_CTRL); + rtw89_fw_h2c_lps_parm(rtwdev, &lps_param); +- rtw89_fw_h2c_lps_ch_info(rtwdev, rtwvif); ++ rtw89_fw_h2c_lps_ch_info(rtwdev, rtwvif_link); + } + +-static void __rtw89_leave_lps(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif) ++static void __rtw89_leave_lps(struct rtw89_dev *rtwdev, ++ struct rtw89_vif_link *rtwvif_link) + { + struct rtw89_lps_parm lps_param = { +- .macid = rtwvif->mac_id, ++ .macid = rtwvif_link->mac_id, + .psmode = RTW89_MAC_AX_PS_MODE_ACTIVE, + .lastrpwm = RTW89_LAST_RPWM_ACTIVE, + }; +@@ -109,7 +111,7 @@ static void __rtw89_leave_lps(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif + rtw89_fw_h2c_lps_parm(rtwdev, &lps_param); + rtw89_fw_leave_lps_check(rtwdev, 0); + rtw89_btc_ntfy_radio_state(rtwdev, BTC_RFCTRL_WL_ON); +- rtw89_chip_digital_pwr_comp(rtwdev, rtwvif->phy_idx); ++ rtw89_chip_digital_pwr_comp(rtwdev, rtwvif_link->phy_idx); + } + + void rtw89_leave_ps_mode(struct rtw89_dev *rtwdev) +@@ -119,7 +121,7 @@ void rtw89_leave_ps_mode(struct rtw89_dev *rtwdev) + __rtw89_leave_ps_mode(rtwdev); + } + +-void rtw89_enter_lps(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, ++void rtw89_enter_lps(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, + bool ps_mode) + { + lockdep_assert_held(&rtwdev->mutex); +@@ -127,23 +129,24 @@ void rtw89_enter_lps(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, + if (test_and_set_bit(RTW89_FLAG_LEISURE_PS, rtwdev->flags)) + return; + +- __rtw89_enter_lps(rtwdev, rtwvif); ++ __rtw89_enter_lps(rtwdev, rtwvif_link); + if (ps_mode) +- __rtw89_enter_ps_mode(rtwdev, rtwvif); ++ __rtw89_enter_ps_mode(rtwdev, rtwvif_link); + } + +-static void rtw89_leave_lps_vif(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif) ++static void rtw89_leave_lps_vif(struct rtw89_dev *rtwdev, ++ struct rtw89_vif_link *rtwvif_link) + { +- if (rtwvif->wifi_role != RTW89_WIFI_ROLE_STATION && +- rtwvif->wifi_role != RTW89_WIFI_ROLE_P2P_CLIENT) ++ if (rtwvif_link->wifi_role != RTW89_WIFI_ROLE_STATION && ++ rtwvif_link->wifi_role != RTW89_WIFI_ROLE_P2P_CLIENT) + return; + +- __rtw89_leave_lps(rtwdev, rtwvif); ++ __rtw89_leave_lps(rtwdev, rtwvif_link); + } + + void rtw89_leave_lps(struct rtw89_dev *rtwdev) + { +- struct rtw89_vif *rtwvif; ++ struct rtw89_vif_link *rtwvif_link; + + lockdep_assert_held(&rtwdev->mutex); + +@@ -152,28 +155,28 @@ void rtw89_leave_lps(struct rtw89_dev *rtwdev) + + __rtw89_leave_ps_mode(rtwdev); + +- rtw89_for_each_rtwvif(rtwdev, rtwvif) +- rtw89_leave_lps_vif(rtwdev, rtwvif); ++ rtw89_for_each_rtwvif(rtwdev, rtwvif_link) ++ rtw89_leave_lps_vif(rtwdev, rtwvif_link); + } + + void rtw89_enter_ips(struct rtw89_dev *rtwdev) + { +- struct rtw89_vif *rtwvif; ++ struct rtw89_vif_link *rtwvif_link; + + set_bit(RTW89_FLAG_INACTIVE_PS, rtwdev->flags); + + if (!test_bit(RTW89_FLAG_POWERON, rtwdev->flags)) + return; + +- rtw89_for_each_rtwvif(rtwdev, rtwvif) +- rtw89_mac_vif_deinit(rtwdev, rtwvif); ++ rtw89_for_each_rtwvif(rtwdev, rtwvif_link) ++ rtw89_mac_vif_deinit(rtwdev, rtwvif_link); + + rtw89_core_stop(rtwdev); + } + + void rtw89_leave_ips(struct rtw89_dev *rtwdev) + { +- struct rtw89_vif *rtwvif; ++ struct rtw89_vif_link *rtwvif_link; + int ret; + + if (test_bit(RTW89_FLAG_POWERON, rtwdev->flags)) +@@ -185,8 +188,8 @@ void rtw89_leave_ips(struct rtw89_dev *rtwdev) + + rtw89_set_channel(rtwdev); + +- rtw89_for_each_rtwvif(rtwdev, rtwvif) +- rtw89_mac_vif_init(rtwdev, rtwvif); ++ rtw89_for_each_rtwvif(rtwdev, rtwvif_link) ++ rtw89_mac_vif_init(rtwdev, rtwvif_link); + + clear_bit(RTW89_FLAG_INACTIVE_PS, rtwdev->flags); + } +@@ -197,34 +200,35 @@ void rtw89_set_coex_ctrl_lps(struct rtw89_dev *rtwdev, bool btc_ctrl) + rtw89_leave_lps(rtwdev); + } + +-static void rtw89_tsf32_toggle(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, ++static void rtw89_tsf32_toggle(struct rtw89_dev *rtwdev, ++ struct rtw89_vif_link *rtwvif_link, + enum rtw89_p2pps_action act) + { + if (act == RTW89_P2P_ACT_UPDATE || act == RTW89_P2P_ACT_REMOVE) + return; + + if (act == RTW89_P2P_ACT_INIT) +- rtw89_fw_h2c_tsf32_toggle(rtwdev, rtwvif, true); ++ rtw89_fw_h2c_tsf32_toggle(rtwdev, rtwvif_link, true); + else if (act == RTW89_P2P_ACT_TERMINATE) +- rtw89_fw_h2c_tsf32_toggle(rtwdev, rtwvif, false); ++ rtw89_fw_h2c_tsf32_toggle(rtwdev, rtwvif_link, false); + } + + static void rtw89_p2p_disable_all_noa(struct rtw89_dev *rtwdev, + struct ieee80211_vif *vif) + { +- struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; ++ struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv; + enum rtw89_p2pps_action act; + u8 noa_id; + +- if (rtwvif->last_noa_nr == 0) ++ if (rtwvif_link->last_noa_nr == 0) + return; + +- for (noa_id = 0; noa_id < rtwvif->last_noa_nr; noa_id++) { +- if (noa_id == rtwvif->last_noa_nr - 1) ++ for (noa_id = 0; noa_id < rtwvif_link->last_noa_nr; noa_id++) { ++ if (noa_id == rtwvif_link->last_noa_nr - 1) + act = RTW89_P2P_ACT_TERMINATE; + else + act = RTW89_P2P_ACT_REMOVE; +- rtw89_tsf32_toggle(rtwdev, rtwvif, act); ++ rtw89_tsf32_toggle(rtwdev, rtwvif_link, act); + rtw89_fw_h2c_p2p_act(rtwdev, vif, NULL, act, noa_id); + } + } +@@ -232,7 +236,7 @@ static void rtw89_p2p_disable_all_noa(struct rtw89_dev *rtwdev, + static void rtw89_p2p_update_noa(struct rtw89_dev *rtwdev, + struct ieee80211_vif *vif) + { +- struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; ++ struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv; + struct ieee80211_p2p_noa_desc *desc; + enum rtw89_p2pps_action act; + u8 noa_id; +@@ -246,10 +250,10 @@ static void rtw89_p2p_update_noa(struct rtw89_dev *rtwdev, + act = RTW89_P2P_ACT_INIT; + else + act = RTW89_P2P_ACT_UPDATE; +- rtw89_tsf32_toggle(rtwdev, rtwvif, act); ++ rtw89_tsf32_toggle(rtwdev, rtwvif_link, act); + rtw89_fw_h2c_p2p_act(rtwdev, vif, desc, act, noa_id); + } +- rtwvif->last_noa_nr = noa_id; ++ rtwvif_link->last_noa_nr = noa_id; + } + + void rtw89_process_p2p_ps(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif) +@@ -261,7 +265,7 @@ void rtw89_process_p2p_ps(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif) + void rtw89_recalc_lps(struct rtw89_dev *rtwdev) + { + struct ieee80211_vif *vif, *found_vif = NULL; +- struct rtw89_vif *rtwvif; ++ struct rtw89_vif_link *rtwvif_link; + enum rtw89_entity_mode mode; + int count = 0; + +@@ -269,8 +273,8 @@ void rtw89_recalc_lps(struct rtw89_dev *rtwdev) + if (mode == RTW89_ENTITY_MODE_MCC) + goto disable_lps; + +- rtw89_for_each_rtwvif(rtwdev, rtwvif) { +- vif = rtwvif_to_vif(rtwvif); ++ rtw89_for_each_rtwvif(rtwdev, rtwvif_link) { ++ vif = rtwvif_to_vif(rtwvif_link); + + if (vif->type != NL80211_IFTYPE_STATION) { + count = 0; +@@ -291,9 +295,9 @@ void rtw89_recalc_lps(struct rtw89_dev *rtwdev) + rtwdev->lps_enabled = false; + } + +-void rtw89_p2p_noa_renew(struct rtw89_vif *rtwvif) ++void rtw89_p2p_noa_renew(struct rtw89_vif_link *rtwvif_link) + { +- struct rtw89_p2p_noa_setter *setter = &rtwvif->p2p_noa; ++ struct rtw89_p2p_noa_setter *setter = &rtwvif_link->p2p_noa; + struct rtw89_p2p_noa_ie *ie = &setter->ie; + struct rtw89_p2p_ie_head *p2p_head = &ie->p2p_head; + struct rtw89_noa_attr_head *noa_head = &ie->noa_head; +@@ -318,10 +322,10 @@ void rtw89_p2p_noa_renew(struct rtw89_vif *rtwvif) + noa_head->oppps_ctwindow = 0; + } + +-void rtw89_p2p_noa_append(struct rtw89_vif *rtwvif, ++void rtw89_p2p_noa_append(struct rtw89_vif_link *rtwvif_link, + const struct ieee80211_p2p_noa_desc *desc) + { +- struct rtw89_p2p_noa_setter *setter = &rtwvif->p2p_noa; ++ struct rtw89_p2p_noa_setter *setter = &rtwvif_link->p2p_noa; + struct rtw89_p2p_noa_ie *ie = &setter->ie; + struct rtw89_p2p_ie_head *p2p_head = &ie->p2p_head; + struct rtw89_noa_attr_head *noa_head = &ie->noa_head; +@@ -338,9 +342,9 @@ void rtw89_p2p_noa_append(struct rtw89_vif *rtwvif, + ie->noa_desc[setter->noa_count++] = *desc; + } + +-u8 rtw89_p2p_noa_fetch(struct rtw89_vif *rtwvif, void **data) ++u8 rtw89_p2p_noa_fetch(struct rtw89_vif_link *rtwvif_link, void **data) + { +- struct rtw89_p2p_noa_setter *setter = &rtwvif->p2p_noa; ++ struct rtw89_p2p_noa_setter *setter = &rtwvif_link->p2p_noa; + struct rtw89_p2p_noa_ie *ie = &setter->ie; + void *tail; + +diff --git a/drivers/net/wireless/realtek/rtw89/ps.h b/drivers/net/wireless/realtek/rtw89/ps.h +index 54486e4550b61..d0be56ee16a29 100644 +--- a/drivers/net/wireless/realtek/rtw89/ps.h ++++ b/drivers/net/wireless/realtek/rtw89/ps.h +@@ -5,21 +5,21 @@ + #ifndef __RTW89_PS_H_ + #define __RTW89_PS_H_ + +-void rtw89_enter_lps(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, ++void rtw89_enter_lps(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, + bool ps_mode); + void rtw89_leave_lps(struct rtw89_dev *rtwdev); + void __rtw89_leave_ps_mode(struct rtw89_dev *rtwdev); +-void __rtw89_enter_ps_mode(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif); ++void __rtw89_enter_ps_mode(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link); + void rtw89_leave_ps_mode(struct rtw89_dev *rtwdev); + void rtw89_enter_ips(struct rtw89_dev *rtwdev); + void rtw89_leave_ips(struct rtw89_dev *rtwdev); + void rtw89_set_coex_ctrl_lps(struct rtw89_dev *rtwdev, bool btc_ctrl); + void rtw89_process_p2p_ps(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif); + void rtw89_recalc_lps(struct rtw89_dev *rtwdev); +-void rtw89_p2p_noa_renew(struct rtw89_vif *rtwvif); +-void rtw89_p2p_noa_append(struct rtw89_vif *rtwvif, ++void rtw89_p2p_noa_renew(struct rtw89_vif_link *rtwvif_link); ++void rtw89_p2p_noa_append(struct rtw89_vif_link *rtwvif_link, + const struct ieee80211_p2p_noa_desc *desc); +-u8 rtw89_p2p_noa_fetch(struct rtw89_vif *rtwvif, void **data); ++u8 rtw89_p2p_noa_fetch(struct rtw89_vif_link *rtwvif_link, void **data); + + static inline void rtw89_leave_ips_by_hwflags(struct rtw89_dev *rtwdev) + { +diff --git a/drivers/net/wireless/realtek/rtw89/regd.c b/drivers/net/wireless/realtek/rtw89/regd.c +index a7720a1f17a74..0fd8e132fdf07 100644 +--- a/drivers/net/wireless/realtek/rtw89/regd.c ++++ b/drivers/net/wireless/realtek/rtw89/regd.c +@@ -793,18 +793,18 @@ static bool __rtw89_reg_6ghz_tpe_recalc(struct rtw89_dev *rtwdev) + { + struct rtw89_regulatory_info *regulatory = &rtwdev->regulatory; + struct rtw89_reg_6ghz_tpe new = {}; +- struct rtw89_vif *rtwvif; ++ struct rtw89_vif_link *rtwvif_link; + bool changed = false; + +- rtw89_for_each_rtwvif(rtwdev, rtwvif) { ++ rtw89_for_each_rtwvif(rtwdev, rtwvif_link) { + const struct rtw89_reg_6ghz_tpe *tmp; + const struct rtw89_chan *chan; + +- chan = rtw89_chan_get(rtwdev, rtwvif->chanctx_idx); ++ chan = rtw89_chan_get(rtwdev, rtwvif_link->chanctx_idx); + if (chan->band_type != RTW89_BAND_6G) + continue; + +- tmp = &rtwvif->reg_6ghz_tpe; ++ tmp = &rtwvif_link->reg_6ghz_tpe; + if (!tmp->valid) + continue; + +@@ -831,16 +831,16 @@ static bool __rtw89_reg_6ghz_tpe_recalc(struct rtw89_dev *rtwdev) + } + + static int rtw89_reg_6ghz_tpe_recalc(struct rtw89_dev *rtwdev, +- struct rtw89_vif *rtwvif, bool active, ++ struct rtw89_vif_link *rtwvif_link, bool active, + unsigned int *changed) + { +- struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif); ++ struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif_link); + struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; +- struct rtw89_reg_6ghz_tpe *tpe = &rtwvif->reg_6ghz_tpe; ++ struct rtw89_reg_6ghz_tpe *tpe = &rtwvif_link->reg_6ghz_tpe; + + memset(tpe, 0, sizeof(*tpe)); + +- if (!active || rtwvif->reg_6ghz_power != RTW89_REG_6GHZ_POWER_STD) ++ if (!active || rtwvif_link->reg_6ghz_power != RTW89_REG_6GHZ_POWER_STD) + goto bottom; + + rtw89_calculate_tpe(rtwdev, tpe, &bss_conf->tpe); +@@ -867,19 +867,19 @@ static bool __rtw89_reg_6ghz_power_recalc(struct rtw89_dev *rtwdev) + const struct rtw89_regd *regd = regulatory->regd; + enum rtw89_reg_6ghz_power sel; + const struct rtw89_chan *chan; +- struct rtw89_vif *rtwvif; ++ struct rtw89_vif_link *rtwvif_link; + int count = 0; + u8 index; + +- rtw89_for_each_rtwvif(rtwdev, rtwvif) { +- chan = rtw89_chan_get(rtwdev, rtwvif->chanctx_idx); ++ rtw89_for_each_rtwvif(rtwdev, rtwvif_link) { ++ chan = rtw89_chan_get(rtwdev, rtwvif_link->chanctx_idx); + if (chan->band_type != RTW89_BAND_6G) + continue; + +- if (count != 0 && rtwvif->reg_6ghz_power == sel) ++ if (count != 0 && rtwvif_link->reg_6ghz_power == sel) + continue; + +- sel = rtwvif->reg_6ghz_power; ++ sel = rtwvif_link->reg_6ghz_power; + count++; + } + +@@ -908,35 +908,35 @@ static bool __rtw89_reg_6ghz_power_recalc(struct rtw89_dev *rtwdev) + } + + static int rtw89_reg_6ghz_power_recalc(struct rtw89_dev *rtwdev, +- struct rtw89_vif *rtwvif, bool active, ++ struct rtw89_vif_link *rtwvif_link, bool active, + unsigned int *changed) + { +- struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif); ++ struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif_link); + + if (active) { + switch (vif->bss_conf.power_type) { + case IEEE80211_REG_VLP_AP: +- rtwvif->reg_6ghz_power = RTW89_REG_6GHZ_POWER_VLP; ++ rtwvif_link->reg_6ghz_power = RTW89_REG_6GHZ_POWER_VLP; + break; + case IEEE80211_REG_LPI_AP: +- rtwvif->reg_6ghz_power = RTW89_REG_6GHZ_POWER_LPI; ++ rtwvif_link->reg_6ghz_power = RTW89_REG_6GHZ_POWER_LPI; + break; + case IEEE80211_REG_SP_AP: +- rtwvif->reg_6ghz_power = RTW89_REG_6GHZ_POWER_STD; ++ rtwvif_link->reg_6ghz_power = RTW89_REG_6GHZ_POWER_STD; + break; + default: +- rtwvif->reg_6ghz_power = RTW89_REG_6GHZ_POWER_DFLT; ++ rtwvif_link->reg_6ghz_power = RTW89_REG_6GHZ_POWER_DFLT; + break; + } + } else { +- rtwvif->reg_6ghz_power = RTW89_REG_6GHZ_POWER_DFLT; ++ rtwvif_link->reg_6ghz_power = RTW89_REG_6GHZ_POWER_DFLT; + } + + *changed += __rtw89_reg_6ghz_power_recalc(rtwdev); + return 0; + } + +-int rtw89_reg_6ghz_recalc(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, ++int rtw89_reg_6ghz_recalc(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, + bool active) + { + unsigned int changed = 0; +@@ -948,11 +948,11 @@ int rtw89_reg_6ghz_recalc(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, + * so must do reg_6ghz_tpe_recalc() after reg_6ghz_power_recalc(). + */ + +- ret = rtw89_reg_6ghz_power_recalc(rtwdev, rtwvif, active, &changed); ++ ret = rtw89_reg_6ghz_power_recalc(rtwdev, rtwvif_link, active, &changed); + if (ret) + return ret; + +- ret = rtw89_reg_6ghz_tpe_recalc(rtwdev, rtwvif, active, &changed); ++ ret = rtw89_reg_6ghz_tpe_recalc(rtwdev, rtwvif_link, active, &changed); + if (ret) + return ret; + +diff --git a/drivers/net/wireless/realtek/rtw89/rtw8851b.c b/drivers/net/wireless/realtek/rtw89/rtw8851b.c +index 1679bd408ef3f..f9766bf30e71d 100644 +--- a/drivers/net/wireless/realtek/rtw89/rtw8851b.c ++++ b/drivers/net/wireless/realtek/rtw89/rtw8851b.c +@@ -1590,10 +1590,11 @@ static void rtw8851b_rfk_init(struct rtw89_dev *rtwdev) + rtw8851b_rx_dck(rtwdev, RTW89_PHY_0, RTW89_CHANCTX_0); + } + +-static void rtw8851b_rfk_channel(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif) ++static void rtw8851b_rfk_channel(struct rtw89_dev *rtwdev, ++ struct rtw89_vif_link *rtwvif_link) + { +- enum rtw89_chanctx_idx chanctx_idx = rtwvif->chanctx_idx; +- enum rtw89_phy_idx phy_idx = rtwvif->phy_idx; ++ enum rtw89_chanctx_idx chanctx_idx = rtwvif_link->chanctx_idx; ++ enum rtw89_phy_idx phy_idx = rtwvif_link->phy_idx; + + rtw8851b_rx_dck(rtwdev, phy_idx, chanctx_idx); + rtw8851b_iqk(rtwdev, phy_idx, chanctx_idx); +@@ -1608,10 +1609,12 @@ static void rtw8851b_rfk_band_changed(struct rtw89_dev *rtwdev, + rtw8851b_tssi_scan(rtwdev, phy_idx, chan); + } + +-static void rtw8851b_rfk_scan(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, ++static void rtw8851b_rfk_scan(struct rtw89_dev *rtwdev, ++ struct rtw89_vif_link *rtwvif_link, + bool start) + { +- rtw8851b_wifi_scan_notify(rtwdev, start, rtwvif->phy_idx, rtwvif->chanctx_idx); ++ rtw8851b_wifi_scan_notify(rtwdev, start, rtwvif_link->phy_idx, ++ rtwvif_link->chanctx_idx); + } + + static void rtw8851b_rfk_track(struct rtw89_dev *rtwdev) +diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852a.c b/drivers/net/wireless/realtek/rtw89/rtw8852a.c +index dde96bd63021f..42d369d2e916a 100644 +--- a/drivers/net/wireless/realtek/rtw89/rtw8852a.c ++++ b/drivers/net/wireless/realtek/rtw89/rtw8852a.c +@@ -1350,10 +1350,11 @@ static void rtw8852a_rfk_init(struct rtw89_dev *rtwdev) + rtw8852a_rx_dck(rtwdev, RTW89_PHY_0, true, RTW89_CHANCTX_0); + } + +-static void rtw8852a_rfk_channel(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif) ++static void rtw8852a_rfk_channel(struct rtw89_dev *rtwdev, ++ struct rtw89_vif_link *rtwvif_link) + { +- enum rtw89_chanctx_idx chanctx_idx = rtwvif->chanctx_idx; +- enum rtw89_phy_idx phy_idx = rtwvif->phy_idx; ++ enum rtw89_chanctx_idx chanctx_idx = rtwvif_link->chanctx_idx; ++ enum rtw89_phy_idx phy_idx = rtwvif_link->phy_idx; + + rtw8852a_rx_dck(rtwdev, phy_idx, true, chanctx_idx); + rtw8852a_iqk(rtwdev, phy_idx, chanctx_idx); +@@ -1368,10 +1369,11 @@ static void rtw8852a_rfk_band_changed(struct rtw89_dev *rtwdev, + rtw8852a_tssi_scan(rtwdev, phy_idx, chan); + } + +-static void rtw8852a_rfk_scan(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, ++static void rtw8852a_rfk_scan(struct rtw89_dev *rtwdev, ++ struct rtw89_vif_link *rtwvif_link, + bool start) + { +- rtw8852a_wifi_scan_notify(rtwdev, start, rtwvif->phy_idx); ++ rtw8852a_wifi_scan_notify(rtwdev, start, rtwvif_link->phy_idx); + } + + static void rtw8852a_rfk_track(struct rtw89_dev *rtwdev) +diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852b.c b/drivers/net/wireless/realtek/rtw89/rtw8852b.c +index 12be52f76427a..364aa21cbd446 100644 +--- a/drivers/net/wireless/realtek/rtw89/rtw8852b.c ++++ b/drivers/net/wireless/realtek/rtw89/rtw8852b.c +@@ -562,10 +562,11 @@ static void rtw8852b_rfk_init(struct rtw89_dev *rtwdev) + rtw8852b_rx_dck(rtwdev, RTW89_PHY_0, RTW89_CHANCTX_0); + } + +-static void rtw8852b_rfk_channel(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif) ++static void rtw8852b_rfk_channel(struct rtw89_dev *rtwdev, ++ struct rtw89_vif_link *rtwvif_link) + { +- enum rtw89_chanctx_idx chanctx_idx = rtwvif->chanctx_idx; +- enum rtw89_phy_idx phy_idx = rtwvif->phy_idx; ++ enum rtw89_chanctx_idx chanctx_idx = rtwvif_link->chanctx_idx; ++ enum rtw89_phy_idx phy_idx = rtwvif_link->phy_idx; + + rtw8852b_rx_dck(rtwdev, phy_idx, chanctx_idx); + rtw8852b_iqk(rtwdev, phy_idx, chanctx_idx); +@@ -580,10 +581,12 @@ static void rtw8852b_rfk_band_changed(struct rtw89_dev *rtwdev, + rtw8852b_tssi_scan(rtwdev, phy_idx, chan); + } + +-static void rtw8852b_rfk_scan(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, ++static void rtw8852b_rfk_scan(struct rtw89_dev *rtwdev, ++ struct rtw89_vif_link *rtwvif_link, + bool start) + { +- rtw8852b_wifi_scan_notify(rtwdev, start, rtwvif->phy_idx, rtwvif->chanctx_idx); ++ rtw8852b_wifi_scan_notify(rtwdev, start, rtwvif_link->phy_idx, ++ rtwvif_link->chanctx_idx); + } + + static void rtw8852b_rfk_track(struct rtw89_dev *rtwdev) +diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852bt.c b/drivers/net/wireless/realtek/rtw89/rtw8852bt.c +index 7dfdcb5964e11..dab7e71ec6a14 100644 +--- a/drivers/net/wireless/realtek/rtw89/rtw8852bt.c ++++ b/drivers/net/wireless/realtek/rtw89/rtw8852bt.c +@@ -535,10 +535,11 @@ static void rtw8852bt_rfk_init(struct rtw89_dev *rtwdev) + rtw8852bt_rx_dck(rtwdev, RTW89_PHY_0, RTW89_CHANCTX_0); + } + +-static void rtw8852bt_rfk_channel(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif) ++static void rtw8852bt_rfk_channel(struct rtw89_dev *rtwdev, ++ struct rtw89_vif_link *rtwvif_link) + { +- enum rtw89_chanctx_idx chanctx_idx = rtwvif->chanctx_idx; +- enum rtw89_phy_idx phy_idx = rtwvif->phy_idx; ++ enum rtw89_chanctx_idx chanctx_idx = rtwvif_link->chanctx_idx; ++ enum rtw89_phy_idx phy_idx = rtwvif_link->phy_idx; + + rtw8852bt_rx_dck(rtwdev, phy_idx, chanctx_idx); + rtw8852bt_iqk(rtwdev, phy_idx, chanctx_idx); +@@ -553,10 +554,12 @@ static void rtw8852bt_rfk_band_changed(struct rtw89_dev *rtwdev, + rtw8852bt_tssi_scan(rtwdev, phy_idx, chan); + } + +-static void rtw8852bt_rfk_scan(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, ++static void rtw8852bt_rfk_scan(struct rtw89_dev *rtwdev, ++ struct rtw89_vif_link *rtwvif_link, + bool start) + { +- rtw8852bt_wifi_scan_notify(rtwdev, start, rtwvif->phy_idx, rtwvif->chanctx_idx); ++ rtw8852bt_wifi_scan_notify(rtwdev, start, rtwvif_link->phy_idx, ++ rtwvif_link->chanctx_idx); + } + + static void rtw8852bt_rfk_track(struct rtw89_dev *rtwdev) +diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852c.c b/drivers/net/wireless/realtek/rtw89/rtw8852c.c +index 1c6e89ab0f4bc..dbe77abb2c488 100644 +--- a/drivers/net/wireless/realtek/rtw89/rtw8852c.c ++++ b/drivers/net/wireless/realtek/rtw89/rtw8852c.c +@@ -1846,10 +1846,11 @@ static void rtw8852c_rfk_init(struct rtw89_dev *rtwdev) + rtw8852c_rx_dck(rtwdev, RTW89_PHY_0, false); + } + +-static void rtw8852c_rfk_channel(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif) ++static void rtw8852c_rfk_channel(struct rtw89_dev *rtwdev, ++ struct rtw89_vif_link *rtwvif_link) + { +- enum rtw89_chanctx_idx chanctx_idx = rtwvif->chanctx_idx; +- enum rtw89_phy_idx phy_idx = rtwvif->phy_idx; ++ enum rtw89_chanctx_idx chanctx_idx = rtwvif_link->chanctx_idx; ++ enum rtw89_phy_idx phy_idx = rtwvif_link->phy_idx; + + rtw8852c_mcc_get_ch_info(rtwdev, phy_idx); + rtw8852c_rx_dck(rtwdev, phy_idx, false); +@@ -1866,10 +1867,11 @@ static void rtw8852c_rfk_band_changed(struct rtw89_dev *rtwdev, + rtw8852c_tssi_scan(rtwdev, phy_idx, chan); + } + +-static void rtw8852c_rfk_scan(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, ++static void rtw8852c_rfk_scan(struct rtw89_dev *rtwdev, ++ struct rtw89_vif_link *rtwvif_link, + bool start) + { +- rtw8852c_wifi_scan_notify(rtwdev, start, rtwvif->phy_idx); ++ rtw8852c_wifi_scan_notify(rtwdev, start, rtwvif_link->phy_idx); + } + + static void rtw8852c_rfk_track(struct rtw89_dev *rtwdev) +diff --git a/drivers/net/wireless/realtek/rtw89/rtw8922a.c b/drivers/net/wireless/realtek/rtw89/rtw8922a.c +index 63b1ff2f98ed3..ef7747adbcc2b 100644 +--- a/drivers/net/wireless/realtek/rtw89/rtw8922a.c ++++ b/drivers/net/wireless/realtek/rtw89/rtw8922a.c +@@ -2020,11 +2020,12 @@ static void _wait_rx_mode(struct rtw89_dev *rtwdev, u8 kpath) + } + } + +-static void rtw8922a_rfk_channel(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif) ++static void rtw8922a_rfk_channel(struct rtw89_dev *rtwdev, ++ struct rtw89_vif_link *rtwvif_link) + { +- enum rtw89_chanctx_idx chanctx_idx = rtwvif->chanctx_idx; ++ enum rtw89_chanctx_idx chanctx_idx = rtwvif_link->chanctx_idx; + const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, chanctx_idx); +- enum rtw89_phy_idx phy_idx = rtwvif->phy_idx; ++ enum rtw89_phy_idx phy_idx = rtwvif_link->phy_idx; + u8 phy_map = rtw89_btc_phymap(rtwdev, phy_idx, RF_AB, chanctx_idx); + u32 tx_en; + +@@ -2050,7 +2051,8 @@ static void rtw8922a_rfk_band_changed(struct rtw89_dev *rtwdev, + rtw89_phy_rfk_tssi_and_wait(rtwdev, phy_idx, chan, RTW89_TSSI_SCAN, 6); + } + +-static void rtw8922a_rfk_scan(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, ++static void rtw8922a_rfk_scan(struct rtw89_dev *rtwdev, ++ struct rtw89_vif_link *rtwvif_link, + bool start) + { + } +diff --git a/drivers/net/wireless/realtek/rtw89/ser.c b/drivers/net/wireless/realtek/rtw89/ser.c +index 5fc2faa9ba5a7..2058f4bf271d6 100644 +--- a/drivers/net/wireless/realtek/rtw89/ser.c ++++ b/drivers/net/wireless/realtek/rtw89/ser.c +@@ -298,25 +298,25 @@ static void drv_resume_rx(struct rtw89_ser *ser) + clear_bit(RTW89_SER_DRV_STOP_RX, ser->flags); + } + +-static void ser_reset_vif(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif) ++static void ser_reset_vif(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link) + { +- rtw89_core_release_bit_map(rtwdev->hw_port, rtwvif->port); +- rtwvif->net_type = RTW89_NET_TYPE_NO_LINK; +- rtwvif->trigger = false; +- rtwvif->tdls_peer = 0; ++ rtw89_core_release_bit_map(rtwdev->hw_port, rtwvif_link->port); ++ rtwvif_link->net_type = RTW89_NET_TYPE_NO_LINK; ++ rtwvif_link->trigger = false; ++ rtwvif_link->tdls_peer = 0; + } + + static void ser_sta_deinit_cam_iter(void *data, struct ieee80211_sta *sta) + { +- struct rtw89_vif *target_rtwvif = (struct rtw89_vif *)data; ++ struct rtw89_vif_link *target_rtwvif = (struct rtw89_vif_link *)data; + struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv; +- struct rtw89_vif *rtwvif = rtwsta->rtwvif; +- struct rtw89_dev *rtwdev = rtwvif->rtwdev; ++ struct rtw89_vif_link *rtwvif_link = rtwsta->rtwvif_link; ++ struct rtw89_dev *rtwdev = rtwvif_link->rtwdev; + +- if (rtwvif != target_rtwvif) ++ if (rtwvif_link != target_rtwvif) + return; + +- if (rtwvif->net_type == RTW89_NET_TYPE_AP_MODE || sta->tdls) ++ if (rtwvif_link->net_type == RTW89_NET_TYPE_AP_MODE || sta->tdls) + rtw89_cam_deinit_addr_cam(rtwdev, &rtwsta->addr_cam); + if (sta->tdls) + rtw89_cam_deinit_bssid_cam(rtwdev, &rtwsta->bssid_cam); +@@ -324,28 +324,28 @@ static void ser_sta_deinit_cam_iter(void *data, struct ieee80211_sta *sta) + INIT_LIST_HEAD(&rtwsta->ba_cam_list); + } + +-static void ser_deinit_cam(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif) ++static void ser_deinit_cam(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link) + { + ieee80211_iterate_stations_atomic(rtwdev->hw, + ser_sta_deinit_cam_iter, +- rtwvif); ++ rtwvif_link); + +- rtw89_cam_deinit(rtwdev, rtwvif); ++ rtw89_cam_deinit(rtwdev, rtwvif_link); + + bitmap_zero(rtwdev->cam_info.ba_cam_map, RTW89_MAX_BA_CAM_NUM); + } + + static void ser_reset_mac_binding(struct rtw89_dev *rtwdev) + { +- struct rtw89_vif *rtwvif; ++ struct rtw89_vif_link *rtwvif_link; + + rtw89_cam_reset_keys(rtwdev); +- rtw89_for_each_rtwvif(rtwdev, rtwvif) +- ser_deinit_cam(rtwdev, rtwvif); ++ rtw89_for_each_rtwvif(rtwdev, rtwvif_link) ++ ser_deinit_cam(rtwdev, rtwvif_link); + + rtw89_core_release_all_bits_map(rtwdev->mac_id_map, RTW89_MAX_MAC_ID_NUM); +- rtw89_for_each_rtwvif(rtwdev, rtwvif) +- ser_reset_vif(rtwdev, rtwvif); ++ rtw89_for_each_rtwvif(rtwdev, rtwvif_link) ++ ser_reset_vif(rtwdev, rtwvif_link); + + rtwdev->total_sta_assoc = 0; + } +diff --git a/drivers/net/wireless/realtek/rtw89/util.h b/drivers/net/wireless/realtek/rtw89/util.h +index e669544cafd3f..a5e87a8d8642c 100644 +--- a/drivers/net/wireless/realtek/rtw89/util.h ++++ b/drivers/net/wireless/realtek/rtw89/util.h +@@ -21,14 +21,14 @@ + * twice cause the list to be added twice. + */ + static inline bool rtw89_rtwvif_in_list(struct rtw89_dev *rtwdev, +- struct rtw89_vif *new) ++ struct rtw89_vif_link *new) + { +- struct rtw89_vif *rtwvif; ++ struct rtw89_vif_link *rtwvif_link; + + lockdep_assert_held(&rtwdev->mutex); + +- rtw89_for_each_rtwvif(rtwdev, rtwvif) +- if (rtwvif == new) ++ rtw89_for_each_rtwvif(rtwdev, rtwvif_link) ++ if (rtwvif_link == new) + return true; + + return false; +diff --git a/drivers/net/wireless/realtek/rtw89/wow.c b/drivers/net/wireless/realtek/rtw89/wow.c +index 86e24e07780d9..5902eb37d618c 100644 +--- a/drivers/net/wireless/realtek/rtw89/wow.c ++++ b/drivers/net/wireless/realtek/rtw89/wow.c +@@ -682,26 +682,26 @@ static void rtw89_wow_leave_deep_ps(struct rtw89_dev *rtwdev) + static void rtw89_wow_enter_deep_ps(struct rtw89_dev *rtwdev) + { + struct ieee80211_vif *wow_vif = rtwdev->wow.wow_vif; +- struct rtw89_vif *rtwvif = (struct rtw89_vif *)wow_vif->drv_priv; ++ struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)wow_vif->drv_priv; + +- __rtw89_enter_ps_mode(rtwdev, rtwvif); ++ __rtw89_enter_ps_mode(rtwdev, rtwvif_link); + } + + static void rtw89_wow_enter_ps(struct rtw89_dev *rtwdev) + { + struct ieee80211_vif *wow_vif = rtwdev->wow.wow_vif; +- struct rtw89_vif *rtwvif = (struct rtw89_vif *)wow_vif->drv_priv; ++ struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)wow_vif->drv_priv; + + if (rtw89_wow_mgd_linked(rtwdev)) +- rtw89_enter_lps(rtwdev, rtwvif, false); ++ rtw89_enter_lps(rtwdev, rtwvif_link, false); + else if (rtw89_wow_no_link(rtwdev)) +- rtw89_fw_h2c_fwips(rtwdev, rtwvif, true); ++ rtw89_fw_h2c_fwips(rtwdev, rtwvif_link, true); + } + + static void rtw89_wow_leave_ps(struct rtw89_dev *rtwdev, bool enable_wow) + { + struct ieee80211_vif *wow_vif = rtwdev->wow.wow_vif; +- struct rtw89_vif *rtwvif = (struct rtw89_vif *)wow_vif->drv_priv; ++ struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)wow_vif->drv_priv; + + if (rtw89_wow_mgd_linked(rtwdev)) { + rtw89_leave_lps(rtwdev); +@@ -709,7 +709,7 @@ static void rtw89_wow_leave_ps(struct rtw89_dev *rtwdev, bool enable_wow) + if (enable_wow) + rtw89_leave_ips(rtwdev); + else +- rtw89_fw_h2c_fwips(rtwdev, rtwvif, false); ++ rtw89_fw_h2c_fwips(rtwdev, rtwvif_link, false); + } + } + +@@ -789,10 +789,11 @@ static void rtw89_wow_show_wakeup_reason(struct rtw89_dev *rtwdev) + GFP_KERNEL); + } + +-static void rtw89_wow_vif_iter(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif) ++static void rtw89_wow_vif_iter(struct rtw89_dev *rtwdev, ++ struct rtw89_vif_link *rtwvif_link) + { + struct rtw89_wow_param *rtw_wow = &rtwdev->wow; +- struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif); ++ struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif_link); + + /* Current WoWLAN function support setting of only vif in + * infra mode or no link mode. When one suitable vif is found, +@@ -801,7 +802,7 @@ static void rtw89_wow_vif_iter(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvi + if (rtw_wow->wow_vif || vif->type != NL80211_IFTYPE_STATION) + return; + +- switch (rtwvif->net_type) { ++ switch (rtwvif_link->net_type) { + case RTW89_NET_TYPE_INFRA: + if (rtw_wow_has_mgd_features(rtwdev)) + rtw_wow->wow_vif = vif; +@@ -865,7 +866,7 @@ static u16 rtw89_calc_crc(u8 *pdata, int length) + return ~crc; + } + +-static int rtw89_wow_pattern_get_type(struct rtw89_vif *rtwvif, ++static int rtw89_wow_pattern_get_type(struct rtw89_vif_link *rtwvif_link, + struct rtw89_wow_cam_info *rtw_pattern, + const u8 *pattern, u8 da_mask) + { +@@ -885,7 +886,7 @@ static int rtw89_wow_pattern_get_type(struct rtw89_vif *rtwvif, + rtw_pattern->bc = true; + else if (is_multicast_ether_addr(da)) + rtw_pattern->mc = true; +- else if (ether_addr_equal(da, rtwvif->mac_addr) && ++ else if (ether_addr_equal(da, rtwvif_link->mac_addr) && + da_mask == GENMASK(5, 0)) + rtw_pattern->uc = true; + else if (!da_mask) /*da_mask == 0 mean wildcard*/ +@@ -897,7 +898,7 @@ static int rtw89_wow_pattern_get_type(struct rtw89_vif *rtwvif, + } + + static int rtw89_wow_pattern_generate(struct rtw89_dev *rtwdev, +- struct rtw89_vif *rtwvif, ++ struct rtw89_vif_link *rtwvif_link, + const struct cfg80211_pkt_pattern *pkt_pattern, + struct rtw89_wow_cam_info *rtw_pattern) + { +@@ -916,7 +917,7 @@ static int rtw89_wow_pattern_generate(struct rtw89_dev *rtwdev, + mask_len = DIV_ROUND_UP(len, 8); + memset(rtw_pattern, 0, sizeof(*rtw_pattern)); + +- ret = rtw89_wow_pattern_get_type(rtwvif, rtw_pattern, pattern, ++ ret = rtw89_wow_pattern_get_type(rtwvif_link, rtw_pattern, pattern, + mask[0] & GENMASK(5, 0)); + if (ret) + return ret; +@@ -970,7 +971,7 @@ static int rtw89_wow_pattern_generate(struct rtw89_dev *rtwdev, + } + + static int rtw89_wow_parse_patterns(struct rtw89_dev *rtwdev, +- struct rtw89_vif *rtwvif, ++ struct rtw89_vif_link *rtwvif_link, + struct cfg80211_wowlan *wowlan) + { + struct rtw89_wow_param *rtw_wow = &rtwdev->wow; +@@ -983,7 +984,7 @@ static int rtw89_wow_parse_patterns(struct rtw89_dev *rtwdev, + + for (i = 0; i < wowlan->n_patterns; i++) { + rtw_pattern = &rtw_wow->patterns[i]; +- ret = rtw89_wow_pattern_generate(rtwdev, rtwvif, ++ ret = rtw89_wow_pattern_generate(rtwdev, rtwvif_link, + &wowlan->patterns[i], + rtw_pattern); + if (ret) { +@@ -1066,7 +1067,7 @@ static int rtw89_wow_set_wakeups(struct rtw89_dev *rtwdev, + struct cfg80211_wowlan *wowlan) + { + struct rtw89_wow_param *rtw_wow = &rtwdev->wow; +- struct rtw89_vif *rtwvif; ++ struct rtw89_vif_link *rtwvif_link; + + if (wowlan->disconnect) + set_bit(RTW89_WOW_FLAG_EN_DISCONNECT, rtw_wow->flags); +@@ -1078,36 +1079,36 @@ static int rtw89_wow_set_wakeups(struct rtw89_dev *rtwdev, + if (wowlan->nd_config) + rtw89_wow_init_pno(rtwdev, wowlan->nd_config); + +- rtw89_for_each_rtwvif(rtwdev, rtwvif) +- rtw89_wow_vif_iter(rtwdev, rtwvif); ++ rtw89_for_each_rtwvif(rtwdev, rtwvif_link) ++ rtw89_wow_vif_iter(rtwdev, rtwvif_link); + + if (!rtw_wow->wow_vif) + return -EPERM; + +- rtwvif = (struct rtw89_vif *)rtw_wow->wow_vif->drv_priv; +- return rtw89_wow_parse_patterns(rtwdev, rtwvif, wowlan); ++ rtwvif_link = (struct rtw89_vif_link *)rtw_wow->wow_vif->drv_priv; ++ return rtw89_wow_parse_patterns(rtwdev, rtwvif_link, wowlan); + } + + static int rtw89_wow_cfg_wake_pno(struct rtw89_dev *rtwdev, bool wow) + { + struct rtw89_wow_param *rtw_wow = &rtwdev->wow; + struct ieee80211_vif *wow_vif = rtw_wow->wow_vif; +- struct rtw89_vif *rtwvif = (struct rtw89_vif *)wow_vif->drv_priv; ++ struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)wow_vif->drv_priv; + int ret; + +- ret = rtw89_fw_h2c_cfg_pno(rtwdev, rtwvif, true); ++ ret = rtw89_fw_h2c_cfg_pno(rtwdev, rtwvif_link, true); + if (ret) { + rtw89_err(rtwdev, "failed to config pno\n"); + return ret; + } + +- ret = rtw89_fw_h2c_wow_wakeup_ctrl(rtwdev, rtwvif, wow); ++ ret = rtw89_fw_h2c_wow_wakeup_ctrl(rtwdev, rtwvif_link, wow); + if (ret) { + rtw89_err(rtwdev, "failed to fw wow wakeup ctrl\n"); + return ret; + } + +- ret = rtw89_fw_h2c_wow_global(rtwdev, rtwvif, wow); ++ ret = rtw89_fw_h2c_wow_global(rtwdev, rtwvif_link, wow); + if (ret) { + rtw89_err(rtwdev, "failed to fw wow global\n"); + return ret; +@@ -1120,33 +1121,33 @@ static int rtw89_wow_cfg_wake(struct rtw89_dev *rtwdev, bool wow) + { + struct rtw89_wow_param *rtw_wow = &rtwdev->wow; + struct ieee80211_vif *wow_vif = rtw_wow->wow_vif; +- struct rtw89_vif *rtwvif = (struct rtw89_vif *)wow_vif->drv_priv; ++ struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)wow_vif->drv_priv; + struct ieee80211_sta *wow_sta; + struct rtw89_sta *rtwsta = NULL; + int ret; + +- wow_sta = ieee80211_find_sta(wow_vif, rtwvif->bssid); ++ wow_sta = ieee80211_find_sta(wow_vif, rtwvif_link->bssid); + if (wow_sta) + rtwsta = (struct rtw89_sta *)wow_sta->drv_priv; + + if (wow) { + if (rtw_wow->pattern_cnt) +- rtwvif->wowlan_pattern = true; ++ rtwvif_link->wowlan_pattern = true; + if (test_bit(RTW89_WOW_FLAG_EN_MAGIC_PKT, rtw_wow->flags)) +- rtwvif->wowlan_magic = true; ++ rtwvif_link->wowlan_magic = true; + } else { +- rtwvif->wowlan_pattern = false; +- rtwvif->wowlan_magic = false; ++ rtwvif_link->wowlan_pattern = false; ++ rtwvif_link->wowlan_magic = false; + } + +- ret = rtw89_fw_h2c_wow_wakeup_ctrl(rtwdev, rtwvif, wow); ++ ret = rtw89_fw_h2c_wow_wakeup_ctrl(rtwdev, rtwvif_link, wow); + if (ret) { + rtw89_err(rtwdev, "failed to fw wow wakeup ctrl\n"); + return ret; + } + + if (wow) { +- ret = rtw89_chip_h2c_dctl_sec_cam(rtwdev, rtwvif, rtwsta); ++ ret = rtw89_chip_h2c_dctl_sec_cam(rtwdev, rtwvif_link, rtwsta); + if (ret) { + rtw89_err(rtwdev, "failed to update dctl cam sec entry: %d\n", + ret); +@@ -1154,13 +1155,13 @@ static int rtw89_wow_cfg_wake(struct rtw89_dev *rtwdev, bool wow) + } + } + +- ret = rtw89_fw_h2c_cam(rtwdev, rtwvif, rtwsta, NULL); ++ ret = rtw89_fw_h2c_cam(rtwdev, rtwvif_link, rtwsta, NULL); + if (ret) { + rtw89_warn(rtwdev, "failed to send h2c cam\n"); + return ret; + } + +- ret = rtw89_fw_h2c_wow_global(rtwdev, rtwvif, wow); ++ ret = rtw89_fw_h2c_wow_global(rtwdev, rtwvif_link, wow); + if (ret) { + rtw89_err(rtwdev, "failed to fw wow global\n"); + return ret; +@@ -1191,7 +1192,7 @@ static int rtw89_wow_swap_fw(struct rtw89_dev *rtwdev, bool wow) + enum rtw89_chip_gen chip_gen = rtwdev->chip->chip_gen; + struct rtw89_wow_param *rtw_wow = &rtwdev->wow; + struct ieee80211_vif *wow_vif = rtw_wow->wow_vif; +- struct rtw89_vif *rtwvif = (struct rtw89_vif *)wow_vif->drv_priv; ++ struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)wow_vif->drv_priv; + enum rtw89_core_chip_id chip_id = rtwdev->chip->chip_id; + const struct rtw89_chip_info *chip = rtwdev->chip; + bool include_bb = !!chip->bbmcu_nr; +@@ -1204,7 +1205,7 @@ static int rtw89_wow_swap_fw(struct rtw89_dev *rtwdev, bool wow) + if (chip_id == RTL8852C || chip_id == RTL8922A) + disable_intr_for_dlfw = true; + +- wow_sta = ieee80211_find_sta(wow_vif, rtwvif->bssid); ++ wow_sta = ieee80211_find_sta(wow_vif, rtwvif_link->bssid); + if (wow_sta) + rtwsta = (struct rtw89_sta *)wow_sta->drv_priv; + else +@@ -1224,7 +1225,7 @@ static int rtw89_wow_swap_fw(struct rtw89_dev *rtwdev, bool wow) + + rtw89_phy_init_rf_reg(rtwdev, true); + +- ret = rtw89_fw_h2c_role_maintain(rtwdev, rtwvif, rtwsta, ++ ret = rtw89_fw_h2c_role_maintain(rtwdev, rtwvif_link, rtwsta, + RTW89_ROLE_FW_RESTORE); + if (ret) { + rtw89_warn(rtwdev, "failed to send h2c role maintain\n"); +@@ -1240,20 +1241,20 @@ static int rtw89_wow_swap_fw(struct rtw89_dev *rtwdev, bool wow) + if (!is_conn) + rtw89_cam_reset_keys(rtwdev); + +- ret = rtw89_fw_h2c_join_info(rtwdev, rtwvif, rtwsta, !is_conn); ++ ret = rtw89_fw_h2c_join_info(rtwdev, rtwvif_link, rtwsta, !is_conn); + if (ret) { + rtw89_warn(rtwdev, "failed to send h2c join info\n"); + return ret; + } + +- ret = rtw89_fw_h2c_cam(rtwdev, rtwvif, rtwsta, NULL); ++ ret = rtw89_fw_h2c_cam(rtwdev, rtwvif_link, rtwsta, NULL); + if (ret) { + rtw89_warn(rtwdev, "failed to send h2c cam\n"); + return ret; + } + + if (is_conn) { +- ret = rtw89_fw_h2c_general_pkt(rtwdev, rtwvif, rtwsta->mac_id); ++ ret = rtw89_fw_h2c_general_pkt(rtwdev, rtwvif_link, rtwsta->mac_id); + if (ret) { + rtw89_warn(rtwdev, "failed to send h2c general packet\n"); + return ret; +@@ -1377,7 +1378,7 @@ static int rtw89_wow_disable_trx_post(struct rtw89_dev *rtwdev) + } + + static void rtw89_fw_release_pno_pkt_list(struct rtw89_dev *rtwdev, +- struct rtw89_vif *rtwvif) ++ struct rtw89_vif_link *rtwvif_link) + { + struct rtw89_wow_param *rtw_wow = &rtwdev->wow; + struct list_head *pkt_list = &rtw_wow->pno_pkt_list; +@@ -1391,7 +1392,7 @@ static void rtw89_fw_release_pno_pkt_list(struct rtw89_dev *rtwdev, + } + + static int rtw89_pno_scan_update_probe_req(struct rtw89_dev *rtwdev, +- struct rtw89_vif *rtwvif) ++ struct rtw89_vif_link *rtwvif_link) + { + struct rtw89_wow_param *rtw_wow = &rtwdev->wow; + struct cfg80211_sched_scan_request *nd_config = rtw_wow->nd_config; +@@ -1401,7 +1402,7 @@ static int rtw89_pno_scan_update_probe_req(struct rtw89_dev *rtwdev, + int ret; + + for (i = 0; i < num; i++) { +- skb = ieee80211_probereq_get(rtwdev->hw, rtwvif->mac_addr, ++ skb = ieee80211_probereq_get(rtwdev->hw, rtwvif_link->mac_addr, + nd_config->match_sets[i].ssid.ssid, + nd_config->match_sets[i].ssid.ssid_len, + nd_config->ie_len); +@@ -1413,7 +1414,7 @@ static int rtw89_pno_scan_update_probe_req(struct rtw89_dev *rtwdev, + info = kzalloc(sizeof(*info), GFP_KERNEL); + if (!info) { + kfree_skb(skb); +- rtw89_fw_release_pno_pkt_list(rtwdev, rtwvif); ++ rtw89_fw_release_pno_pkt_list(rtwdev, rtwvif_link); + return -ENOMEM; + } + +@@ -1421,7 +1422,7 @@ static int rtw89_pno_scan_update_probe_req(struct rtw89_dev *rtwdev, + if (ret) { + kfree_skb(skb); + kfree(info); +- rtw89_fw_release_pno_pkt_list(rtwdev, rtwvif); ++ rtw89_fw_release_pno_pkt_list(rtwdev, rtwvif_link); + return ret; + } + +@@ -1437,19 +1438,19 @@ static int rtw89_pno_scan_offload(struct rtw89_dev *rtwdev, bool enable) + const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; + struct rtw89_wow_param *rtw_wow = &rtwdev->wow; + struct ieee80211_vif *wow_vif = rtw_wow->wow_vif; +- struct rtw89_vif *rtwvif = (struct rtw89_vif *)wow_vif->drv_priv; ++ struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)wow_vif->drv_priv; + int interval = rtw_wow->nd_config->scan_plans[0].interval; + struct rtw89_scan_option opt = {}; + int ret; + + if (enable) { +- ret = rtw89_pno_scan_update_probe_req(rtwdev, rtwvif); ++ ret = rtw89_pno_scan_update_probe_req(rtwdev, rtwvif_link); + if (ret) { + rtw89_err(rtwdev, "Update probe request failed\n"); + return ret; + } + +- ret = mac->add_chan_list_pno(rtwdev, rtwvif); ++ ret = mac->add_chan_list_pno(rtwdev, rtwvif_link); + if (ret) { + rtw89_err(rtwdev, "Update channel list failed\n"); + return ret; +@@ -1471,7 +1472,7 @@ static int rtw89_pno_scan_offload(struct rtw89_dev *rtwdev, bool enable) + opt.opch_end = RTW89_CHAN_INVALID; + } + +- mac->scan_offload(rtwdev, &opt, rtwvif, true); ++ mac->scan_offload(rtwdev, &opt, rtwvif_link, true); + + return 0; + } +@@ -1480,7 +1481,7 @@ static int rtw89_wow_fw_start(struct rtw89_dev *rtwdev) + { + struct rtw89_wow_param *rtw_wow = &rtwdev->wow; + struct ieee80211_vif *wow_vif = rtw_wow->wow_vif; +- struct rtw89_vif *rtwvif = (struct rtw89_vif *)wow_vif->drv_priv; ++ struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)wow_vif->drv_priv; + int ret; + + if (rtw89_wow_no_link(rtwdev)) { +@@ -1499,25 +1500,25 @@ static int rtw89_wow_fw_start(struct rtw89_dev *rtwdev) + rtw89_wow_pattern_write(rtwdev); + rtw89_wow_construct_key_info(rtwdev); + +- ret = rtw89_fw_h2c_keep_alive(rtwdev, rtwvif, true); ++ ret = rtw89_fw_h2c_keep_alive(rtwdev, rtwvif_link, true); + if (ret) { + rtw89_err(rtwdev, "wow: failed to enable keep alive\n"); + return ret; + } + +- ret = rtw89_fw_h2c_disconnect_detect(rtwdev, rtwvif, true); ++ ret = rtw89_fw_h2c_disconnect_detect(rtwdev, rtwvif_link, true); + if (ret) { + rtw89_err(rtwdev, "wow: failed to enable disconnect detect\n"); + return ret; + } + +- ret = rtw89_fw_h2c_wow_gtk_ofld(rtwdev, rtwvif, true); ++ ret = rtw89_fw_h2c_wow_gtk_ofld(rtwdev, rtwvif_link, true); + if (ret) { + rtw89_err(rtwdev, "wow: failed to enable GTK offload\n"); + return ret; + } + +- ret = rtw89_fw_h2c_arp_offload(rtwdev, rtwvif, true); ++ ret = rtw89_fw_h2c_arp_offload(rtwdev, rtwvif_link, true); + if (ret) + rtw89_warn(rtwdev, "wow: failed to enable arp offload\n"); + } +@@ -1549,7 +1550,7 @@ static int rtw89_wow_fw_stop(struct rtw89_dev *rtwdev) + { + struct rtw89_wow_param *rtw_wow = &rtwdev->wow; + struct ieee80211_vif *wow_vif = rtw_wow->wow_vif; +- struct rtw89_vif *rtwvif = (struct rtw89_vif *)wow_vif->drv_priv; ++ struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)wow_vif->drv_priv; + int ret; + + if (rtw89_wow_no_link(rtwdev)) { +@@ -1559,35 +1560,35 @@ static int rtw89_wow_fw_stop(struct rtw89_dev *rtwdev) + return ret; + } + +- ret = rtw89_fw_h2c_cfg_pno(rtwdev, rtwvif, false); ++ ret = rtw89_fw_h2c_cfg_pno(rtwdev, rtwvif_link, false); + if (ret) { + rtw89_err(rtwdev, "wow: failed to disable pno\n"); + return ret; + } + +- rtw89_fw_release_pno_pkt_list(rtwdev, rtwvif); ++ rtw89_fw_release_pno_pkt_list(rtwdev, rtwvif_link); + } else { + rtw89_wow_pattern_clear(rtwdev); + +- ret = rtw89_fw_h2c_keep_alive(rtwdev, rtwvif, false); ++ ret = rtw89_fw_h2c_keep_alive(rtwdev, rtwvif_link, false); + if (ret) { + rtw89_err(rtwdev, "wow: failed to disable keep alive\n"); + return ret; + } + +- ret = rtw89_fw_h2c_disconnect_detect(rtwdev, rtwvif, false); ++ ret = rtw89_fw_h2c_disconnect_detect(rtwdev, rtwvif_link, false); + if (ret) { + rtw89_err(rtwdev, "wow: failed to disable disconnect detect\n"); + return ret; + } + +- ret = rtw89_fw_h2c_wow_gtk_ofld(rtwdev, rtwvif, false); ++ ret = rtw89_fw_h2c_wow_gtk_ofld(rtwdev, rtwvif_link, false); + if (ret) { + rtw89_err(rtwdev, "wow: failed to disable GTK offload\n"); + return ret; + } + +- ret = rtw89_fw_h2c_arp_offload(rtwdev, rtwvif, false); ++ ret = rtw89_fw_h2c_arp_offload(rtwdev, rtwvif_link, false); + if (ret) + rtw89_warn(rtwdev, "wow: failed to disable arp offload\n"); + +diff --git a/drivers/net/wireless/realtek/rtw89/wow.h b/drivers/net/wireless/realtek/rtw89/wow.h +index 3fbc2b87c058a..a80b4b84587dd 100644 +--- a/drivers/net/wireless/realtek/rtw89/wow.h ++++ b/drivers/net/wireless/realtek/rtw89/wow.h +@@ -98,17 +98,17 @@ static inline int rtw89_wow_get_sec_hdr_len(struct rtw89_dev *rtwdev) + static inline bool rtw89_wow_mgd_linked(struct rtw89_dev *rtwdev) + { + struct ieee80211_vif *wow_vif = rtwdev->wow.wow_vif; +- struct rtw89_vif *rtwvif = (struct rtw89_vif *)wow_vif->drv_priv; ++ struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)wow_vif->drv_priv; + +- return rtwvif->net_type == RTW89_NET_TYPE_INFRA; ++ return rtwvif_link->net_type == RTW89_NET_TYPE_INFRA; + } + + static inline bool rtw89_wow_no_link(struct rtw89_dev *rtwdev) + { + struct ieee80211_vif *wow_vif = rtwdev->wow.wow_vif; +- struct rtw89_vif *rtwvif = (struct rtw89_vif *)wow_vif->drv_priv; ++ struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)wow_vif->drv_priv; + +- return rtwvif->net_type == RTW89_NET_TYPE_NO_LINK; ++ return rtwvif_link->net_type == RTW89_NET_TYPE_NO_LINK; + } + + static inline bool rtw_wow_has_mgd_features(struct rtw89_dev *rtwdev) +-- +2.43.0 + diff --git a/queue-6.12/wifi-rtw89-tweak-driver-architecture-for-impending-m.patch b/queue-6.12/wifi-rtw89-tweak-driver-architecture-for-impending-m.patch new file mode 100644 index 00000000000..bb7f65faaa0 --- /dev/null +++ b/queue-6.12/wifi-rtw89-tweak-driver-architecture-for-impending-m.patch @@ -0,0 +1,4598 @@ +From 0a76e07929033b6754049929f188ead4a0e1ef02 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Mon, 16 Sep 2024 13:31:58 +0800 +Subject: wifi: rtw89: tweak driver architecture for impending MLO support + +From: Zong-Zhe Yang <kevin_yang@realtek.com> + +[ Upstream commit aad0394e7a02fe933159be79d9d4595d2ad089dd ] + +The drv_priv hooked to mac80211 become as below. + + (drv_priv) (instance-0) + +---------------+ +-----------+ +----------------+ + | ieee80211_vif | <---> | rtw89_vif | -------> | rtw89_vif_link | + +---------------+ +-----------+ | +----------------+ + | + | (instance-1) + | +----------------+ + +---> | rtw89_vif_link | + +----------------+ + + (drv_priv) (instance-0) + +---------------+ +-----------+ +----------------+ + | ieee80211_sta | <---> | rtw89_sta | -------> | rtw89_sta_link | + +---------------+ +-----------+ | +----------------+ + | + | (instance-1) + | +----------------+ + +---> | rtw89_sta_link | + +----------------+ + +The relation bewteen mac80211 link_id and our link instance is like below. + + |\ + (link_id) | \ + 0 -------- | | + 1 -------- | | ------ instance-0 (link_id: X) -> work on HW band 0 + 2 -------- | | + ... | | ------ instance-1 (link_id: Y) -> work on HW band 1 + 14 -------- | | + | / + |/ + + N.B. For cases of non-MLD connection, we set our link instance-0 + active with link_id 0. So, our code flow can be compatible between + non-MLD connection and MLD connection. + +Based on above, we tweak entire driver architecture first. But, we don't +dynamically enable multiple links here. That will be handled separately. +Most of the things changed here are changing flows to iterate all active +links and read bss_conf/link_sta data according to target link. And, for +cases of scan, ROC, WOW, we use instance-0 to deal with the request. + +There are some things listed below, which work for now but need to extend +before multiple active links. + 1. tx path + select suitable link instance among multiple active links + 2. rx path + determine rx link by PPDU instead of always link instance-0 + 3. CAM + apply MLD pairwise key to any active links dynamically + +Besides, PS code cannot easily work along with tweaking architecture. With +supporting MLO flag (currently false), we disable PS first and will fix it +by another commit in the following. + +Signed-off-by: Zong-Zhe Yang <kevin_yang@realtek.com> +Signed-off-by: Ping-Ke Shih <pkshih@realtek.com> +Link: https://patch.msgid.link/20240916053158.47350-8-pkshih@realtek.com +Stable-dep-of: f16c40acd319 ("wifi: rtw89: Fix TX fail with A2DP after scanning") +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/net/wireless/realtek/rtw89/cam.c | 126 ++++- + drivers/net/wireless/realtek/rtw89/chan.c | 77 ++- + drivers/net/wireless/realtek/rtw89/coex.c | 54 +- + drivers/net/wireless/realtek/rtw89/core.c | 504 +++++++++++++----- + drivers/net/wireless/realtek/rtw89/core.h | 240 +++++++-- + drivers/net/wireless/realtek/rtw89/debug.c | 85 ++- + drivers/net/wireless/realtek/rtw89/fw.c | 147 ++--- + drivers/net/wireless/realtek/rtw89/fw.h | 72 ++- + drivers/net/wireless/realtek/rtw89/mac.c | 137 +++-- + drivers/net/wireless/realtek/rtw89/mac.h | 2 +- + drivers/net/wireless/realtek/rtw89/mac80211.c | 423 +++++++++++---- + drivers/net/wireless/realtek/rtw89/phy.c | 134 +++-- + drivers/net/wireless/realtek/rtw89/ps.c | 33 +- + drivers/net/wireless/realtek/rtw89/regd.c | 40 +- + drivers/net/wireless/realtek/rtw89/ser.c | 63 ++- + drivers/net/wireless/realtek/rtw89/util.h | 8 +- + drivers/net/wireless/realtek/rtw89/wow.c | 99 ++-- + drivers/net/wireless/realtek/rtw89/wow.h | 6 +- + 18 files changed, 1615 insertions(+), 635 deletions(-) + +diff --git a/drivers/net/wireless/realtek/rtw89/cam.c b/drivers/net/wireless/realtek/rtw89/cam.c +index 7efc6280feaf8..8d140b94cb440 100644 +--- a/drivers/net/wireless/realtek/rtw89/cam.c ++++ b/drivers/net/wireless/realtek/rtw89/cam.c +@@ -211,24 +211,16 @@ static int rtw89_cam_get_addr_cam_key_idx(struct rtw89_addr_cam_entry *addr_cam, + return 0; + } + +-static int rtw89_cam_detach_sec_cam(struct rtw89_dev *rtwdev, +- struct ieee80211_vif *vif, +- struct ieee80211_sta *sta, +- const struct rtw89_sec_cam_entry *sec_cam, +- bool inform_fw) ++static int __rtw89_cam_detach_sec_cam(struct rtw89_dev *rtwdev, ++ struct rtw89_vif_link *rtwvif_link, ++ struct rtw89_sta_link *rtwsta_link, ++ const struct rtw89_sec_cam_entry *sec_cam, ++ bool inform_fw) + { +- struct rtw89_sta_link *rtwsta_link = sta_to_rtwsta_safe(sta); +- struct rtw89_vif_link *rtwvif_link; + struct rtw89_addr_cam_entry *addr_cam; + unsigned int i; + int ret = 0; + +- if (!vif) { +- rtw89_err(rtwdev, "No iface for deleting sec cam\n"); +- return -EINVAL; +- } +- +- rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv; + addr_cam = rtw89_get_addr_cam_of(rtwvif_link, rtwsta_link); + + for_each_set_bit(i, addr_cam->sec_cam_map, RTW89_SEC_CAM_IN_ADDR_CAM) { +@@ -251,24 +243,16 @@ static int rtw89_cam_detach_sec_cam(struct rtw89_dev *rtwdev, + return ret; + } + +-static int rtw89_cam_attach_sec_cam(struct rtw89_dev *rtwdev, +- struct ieee80211_vif *vif, +- struct ieee80211_sta *sta, +- struct ieee80211_key_conf *key, +- struct rtw89_sec_cam_entry *sec_cam) ++static int __rtw89_cam_attach_sec_cam(struct rtw89_dev *rtwdev, ++ struct rtw89_vif_link *rtwvif_link, ++ struct rtw89_sta_link *rtwsta_link, ++ struct ieee80211_key_conf *key, ++ struct rtw89_sec_cam_entry *sec_cam) + { +- struct rtw89_sta_link *rtwsta_link = sta_to_rtwsta_safe(sta); +- struct rtw89_vif_link *rtwvif_link; + struct rtw89_addr_cam_entry *addr_cam; + u8 key_idx = 0; + int ret; + +- if (!vif) { +- rtw89_err(rtwdev, "No iface for adding sec cam\n"); +- return -EINVAL; +- } +- +- rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv; + addr_cam = rtw89_get_addr_cam_of(rtwvif_link, rtwsta_link); + + if (key->cipher == WLAN_CIPHER_SUITE_WEP40 || +@@ -302,6 +286,92 @@ static int rtw89_cam_attach_sec_cam(struct rtw89_dev *rtwdev, + return 0; + } + ++static int rtw89_cam_detach_sec_cam(struct rtw89_dev *rtwdev, ++ struct ieee80211_vif *vif, ++ struct ieee80211_sta *sta, ++ const struct rtw89_sec_cam_entry *sec_cam, ++ bool inform_fw) ++{ ++ struct rtw89_sta *rtwsta = sta_to_rtwsta_safe(sta); ++ struct rtw89_sta_link *rtwsta_link; ++ struct rtw89_vif_link *rtwvif_link; ++ struct rtw89_vif *rtwvif; ++ unsigned int link_id; ++ int ret; ++ ++ if (!vif) { ++ rtw89_err(rtwdev, "No iface for deleting sec cam\n"); ++ return -EINVAL; ++ } ++ ++ rtwvif = vif_to_rtwvif(vif); ++ ++ rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id) { ++ rtwsta_link = rtwsta ? rtwsta->links[link_id] : NULL; ++ if (rtwsta && !rtwsta_link) ++ continue; ++ ++ ret = __rtw89_cam_detach_sec_cam(rtwdev, rtwvif_link, rtwsta_link, ++ sec_cam, inform_fw); ++ if (ret) ++ return ret; ++ } ++ ++ return 0; ++} ++ ++static int rtw89_cam_attach_sec_cam(struct rtw89_dev *rtwdev, ++ struct ieee80211_vif *vif, ++ struct ieee80211_sta *sta, ++ struct ieee80211_key_conf *key, ++ struct rtw89_sec_cam_entry *sec_cam) ++{ ++ struct rtw89_sta *rtwsta = sta_to_rtwsta_safe(sta); ++ struct rtw89_sta_link *rtwsta_link; ++ struct rtw89_vif_link *rtwvif_link; ++ struct rtw89_vif *rtwvif; ++ unsigned int link_id; ++ int key_link_id; ++ int ret; ++ ++ if (!vif) { ++ rtw89_err(rtwdev, "No iface for adding sec cam\n"); ++ return -EINVAL; ++ } ++ ++ rtwvif = vif_to_rtwvif(vif); ++ ++ key_link_id = ieee80211_vif_is_mld(vif) ? key->link_id : 0; ++ if (key_link_id >= 0) { ++ rtwvif_link = rtwvif->links[key_link_id]; ++ rtwsta_link = rtwsta ? rtwsta->links[key_link_id] : NULL; ++ ++ if (!rtwvif_link || (rtwsta && !rtwsta_link)) { ++ rtw89_err(rtwdev, "No drv link for adding sec cam\n"); ++ return -ENOLINK; ++ } ++ ++ return __rtw89_cam_attach_sec_cam(rtwdev, rtwvif_link, ++ rtwsta_link, key, sec_cam); ++ } ++ ++ /* key_link_id < 0: MLD pairwise key */ ++ if (!rtwsta) { ++ rtw89_err(rtwdev, "No sta for adding MLD pairwise sec cam\n"); ++ return -EINVAL; ++ } ++ ++ rtw89_sta_for_each_link(rtwsta, rtwsta_link, link_id) { ++ rtwvif_link = rtwsta_link->rtwvif_link; ++ ret = __rtw89_cam_attach_sec_cam(rtwdev, rtwvif_link, ++ rtwsta_link, key, sec_cam); ++ if (ret) ++ return ret; ++ } ++ ++ return 0; ++} ++ + static int rtw89_cam_sec_key_install(struct rtw89_dev *rtwdev, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta, +@@ -708,10 +778,10 @@ void rtw89_cam_fill_addr_cam_info(struct rtw89_dev *rtwdev, + const u8 *scan_mac_addr, + u8 *cmd) + { +- struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif_link); ++ struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link); + struct rtw89_addr_cam_entry *addr_cam = + rtw89_get_addr_cam_of(rtwvif_link, rtwsta_link); +- struct ieee80211_sta *sta = rtwsta_to_sta_safe(rtwsta_link); ++ struct ieee80211_sta *sta = rtwsta_link_to_sta_safe(rtwsta_link); + struct ieee80211_link_sta *link_sta; + const u8 *sma = scan_mac_addr ? scan_mac_addr : rtwvif_link->mac_addr; + u8 sma_hash, tma_hash, addr_msk_start; +diff --git a/drivers/net/wireless/realtek/rtw89/chan.c b/drivers/net/wireless/realtek/rtw89/chan.c +index 2968c299203b8..ba6332da8019c 100644 +--- a/drivers/net/wireless/realtek/rtw89/chan.c ++++ b/drivers/net/wireless/realtek/rtw89/chan.c +@@ -234,12 +234,24 @@ void rtw89_entity_init(struct rtw89_dev *rtwdev) + rtw89_config_default_chandef(rtwdev); + } + ++static bool rtw89_vif_is_active_role(struct rtw89_vif *rtwvif) ++{ ++ struct rtw89_vif_link *rtwvif_link; ++ unsigned int link_id; ++ ++ rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id) ++ if (rtwvif_link->chanctx_assigned) ++ return true; ++ ++ return false; ++} ++ + static void rtw89_entity_calculate_weight(struct rtw89_dev *rtwdev, + struct rtw89_entity_weight *w) + { + struct rtw89_hal *hal = &rtwdev->hal; + const struct rtw89_chanctx_cfg *cfg; +- struct rtw89_vif_link *rtwvif_link; ++ struct rtw89_vif *rtwvif; + int idx; + + for_each_set_bit(idx, hal->entity_map, NUM_OF_RTW89_CHANCTX) { +@@ -254,8 +266,8 @@ static void rtw89_entity_calculate_weight(struct rtw89_dev *rtwdev, + w->active_chanctxs++; + } + +- rtw89_for_each_rtwvif(rtwdev, rtwvif_link) { +- if (rtwvif_link->chanctx_assigned) ++ rtw89_for_each_rtwvif(rtwdev, rtwvif) { ++ if (rtw89_vif_is_active_role(rtwvif)) + w->active_roles++; + } + } +@@ -522,14 +534,22 @@ u32 rtw89_mcc_role_fw_macid_bitmap_to_u32(struct rtw89_mcc_role *mcc_role) + + static void rtw89_mcc_role_macid_sta_iter(void *data, struct ieee80211_sta *sta) + { +- struct rtw89_sta_link *rtwsta_link = (struct rtw89_sta_link *)sta->drv_priv; +- struct rtw89_vif_link *rtwvif_link = rtwsta_link->rtwvif_link; + struct rtw89_mcc_role *mcc_role = data; +- struct rtw89_vif_link *target = mcc_role->rtwvif_link; ++ struct rtw89_vif *target = mcc_role->rtwvif_link->rtwvif; ++ struct rtw89_sta *rtwsta = sta_to_rtwsta(sta); ++ struct rtw89_vif *rtwvif = rtwsta->rtwvif; ++ struct rtw89_dev *rtwdev = rtwsta->rtwdev; ++ struct rtw89_sta_link *rtwsta_link; + +- if (rtwvif_link != target) ++ if (rtwvif != target) + return; + ++ rtwsta_link = rtw89_sta_get_link_inst(rtwsta, 0); ++ if (unlikely(!rtwsta_link)) { ++ rtw89_err(rtwdev, "mcc sta macid: find no link on HW-0\n"); ++ return; ++ } ++ + rtw89_mcc_role_fw_macid_bitmap_set_bit(mcc_role, rtwsta_link->mac_id); + } + +@@ -605,7 +625,7 @@ static void rtw89_mcc_fill_role_limit(struct rtw89_dev *rtwdev, + return; + } + +- ret = rtw89_mac_port_get_tsf(rtwdev, mcc_role->rtwvif_link, &tsf); ++ ret = rtw89_mac_port_get_tsf(rtwdev, rtwvif_link, &tsf); + if (ret) { + rtw89_warn(rtwdev, "MCC failed to get port tsf: %d\n", ret); + return; +@@ -727,12 +747,19 @@ static int rtw89_mcc_fill_all_roles(struct rtw89_dev *rtwdev) + { + struct rtw89_mcc_fill_role_selector sel = {}; + struct rtw89_vif_link *rtwvif_link; ++ struct rtw89_vif *rtwvif; + int ret; + +- rtw89_for_each_rtwvif(rtwdev, rtwvif_link) { +- if (!rtwvif_link->chanctx_assigned) ++ rtw89_for_each_rtwvif(rtwdev, rtwvif) { ++ if (!rtw89_vif_is_active_role(rtwvif)) + continue; + ++ rtwvif_link = rtw89_vif_get_link_inst(rtwvif, 0); ++ if (unlikely(!rtwvif_link)) { ++ rtw89_err(rtwdev, "mcc fill roles: find no link on HW-0\n"); ++ continue; ++ } ++ + if (sel.bind_vif[rtwvif_link->chanctx_idx]) { + rtw89_warn(rtwdev, + "MCC skip extra vif <macid %d> on chanctx[%d]\n", +@@ -2384,12 +2411,30 @@ void rtw89_chanctx_proceed(struct rtw89_dev *rtwdev) + rtw89_queue_chanctx_work(rtwdev); + } + ++static void __rtw89_swap_chanctx(struct rtw89_vif *rtwvif, ++ enum rtw89_chanctx_idx idx1, ++ enum rtw89_chanctx_idx idx2) ++{ ++ struct rtw89_vif_link *rtwvif_link; ++ unsigned int link_id; ++ ++ rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id) { ++ if (!rtwvif_link->chanctx_assigned) ++ continue; ++ ++ if (rtwvif_link->chanctx_idx == idx1) ++ rtwvif_link->chanctx_idx = idx2; ++ else if (rtwvif_link->chanctx_idx == idx2) ++ rtwvif_link->chanctx_idx = idx1; ++ } ++} ++ + static void rtw89_swap_chanctx(struct rtw89_dev *rtwdev, + enum rtw89_chanctx_idx idx1, + enum rtw89_chanctx_idx idx2) + { + struct rtw89_hal *hal = &rtwdev->hal; +- struct rtw89_vif_link *rtwvif_link; ++ struct rtw89_vif *rtwvif; + u8 cur; + + if (idx1 == idx2) +@@ -2400,14 +2445,8 @@ static void rtw89_swap_chanctx(struct rtw89_dev *rtwdev, + + swap(hal->chanctx[idx1], hal->chanctx[idx2]); + +- rtw89_for_each_rtwvif(rtwdev, rtwvif_link) { +- if (!rtwvif_link->chanctx_assigned) +- continue; +- if (rtwvif_link->chanctx_idx == idx1) +- rtwvif_link->chanctx_idx = idx2; +- else if (rtwvif_link->chanctx_idx == idx2) +- rtwvif_link->chanctx_idx = idx1; +- } ++ rtw89_for_each_rtwvif(rtwdev, rtwvif) ++ __rtw89_swap_chanctx(rtwvif, idx1, idx2); + + cur = atomic_read(&hal->roc_chanctx_idx); + if (cur == idx1) +diff --git a/drivers/net/wireless/realtek/rtw89/coex.c b/drivers/net/wireless/realtek/rtw89/coex.c +index 3d33e40544d0f..8c2db2a493c8b 100644 +--- a/drivers/net/wireless/realtek/rtw89/coex.c ++++ b/drivers/net/wireless/realtek/rtw89/coex.c +@@ -4989,13 +4989,11 @@ struct rtw89_txtime_data { + bool reenable; + }; + +-static void rtw89_tx_time_iter(void *data, struct ieee80211_sta *sta) ++static void __rtw89_tx_time_iter(struct rtw89_vif_link *rtwvif_link, ++ struct rtw89_sta_link *rtwsta_link, ++ struct rtw89_txtime_data *iter_data) + { +- struct rtw89_sta_link *rtwsta_link = (struct rtw89_sta_link *)sta->drv_priv; +- struct rtw89_txtime_data *iter_data = +- (struct rtw89_txtime_data *)data; + struct rtw89_dev *rtwdev = iter_data->rtwdev; +- struct rtw89_vif_link *rtwvif_link = rtwsta_link->rtwvif_link; + struct rtw89_btc *btc = &rtwdev->btc; + struct rtw89_btc_cx *cx = &btc->cx; + struct rtw89_btc_wl_info *wl = &cx->wl; +@@ -5048,6 +5046,21 @@ static void rtw89_tx_time_iter(void *data, struct ieee80211_sta *sta) + } + } + ++static void rtw89_tx_time_iter(void *data, struct ieee80211_sta *sta) ++{ ++ struct rtw89_sta *rtwsta = sta_to_rtwsta(sta); ++ struct rtw89_txtime_data *iter_data = ++ (struct rtw89_txtime_data *)data; ++ struct rtw89_vif_link *rtwvif_link; ++ struct rtw89_sta_link *rtwsta_link; ++ unsigned int link_id; ++ ++ rtw89_sta_for_each_link(rtwsta, rtwsta_link, link_id) { ++ rtwvif_link = rtwsta_link->rtwvif_link; ++ __rtw89_tx_time_iter(rtwvif_link, rtwsta_link, iter_data); ++ } ++} ++ + static void _set_wl_tx_limit(struct rtw89_dev *rtwdev) + { + struct rtw89_btc *btc = &rtwdev->btc; +@@ -7488,7 +7501,7 @@ void rtw89_btc_ntfy_role_info(struct rtw89_dev *rtwdev, + { + const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, + rtwvif_link->chanctx_idx); +- struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif_link); ++ struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link); + struct ieee80211_bss_conf *bss_conf; + struct ieee80211_link_sta *link_sta; + struct rtw89_btc *btc = &rtwdev->btc; +@@ -7794,20 +7807,20 @@ struct rtw89_btc_wl_sta_iter_data { + bool is_traffic_change; + }; + +-static void rtw89_btc_ntfy_wl_sta_iter(void *data, struct ieee80211_sta *sta) ++static ++void __rtw89_btc_ntfy_wl_sta_iter(struct rtw89_vif_link *rtwvif_link, ++ struct rtw89_sta_link *rtwsta_link, ++ struct rtw89_btc_wl_sta_iter_data *iter_data) + { +- struct rtw89_btc_wl_sta_iter_data *iter_data = +- (struct rtw89_btc_wl_sta_iter_data *)data; ++ struct rtw89_vif *rtwvif = rtwvif_link->rtwvif; + struct rtw89_dev *rtwdev = iter_data->rtwdev; + struct rtw89_btc *btc = &rtwdev->btc; + struct rtw89_btc_dm *dm = &btc->dm; + const struct rtw89_btc_ver *ver = btc->ver; + struct rtw89_btc_wl_info *wl = &btc->cx.wl; + struct rtw89_btc_wl_link_info *link_info = NULL; +- struct rtw89_sta_link *rtwsta_link = (struct rtw89_sta_link *)sta->drv_priv; + struct rtw89_traffic_stats *link_info_t = NULL; +- struct rtw89_vif_link *rtwvif_link = rtwsta_link->rtwvif_link; +- struct rtw89_traffic_stats *stats = &rtwvif_link->stats; ++ struct rtw89_traffic_stats *stats = &rtwvif->stats; + const struct rtw89_chip_info *chip = rtwdev->chip; + struct rtw89_btc_wl_role_info *r; + struct rtw89_btc_wl_role_info_v1 *r1; +@@ -7825,7 +7838,7 @@ static void rtw89_btc_ntfy_wl_sta_iter(void *data, struct ieee80211_sta *sta) + rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], rssi=%d\n", rssi); + + link_info = &wl->link_info[port]; +- link_info->stat.traffic = rtwvif_link->stats; ++ link_info->stat.traffic = *stats; + link_info_t = &link_info->stat.traffic; + + if (link_info->connected == MLME_NO_LINK) { +@@ -7929,6 +7942,21 @@ static void rtw89_btc_ntfy_wl_sta_iter(void *data, struct ieee80211_sta *sta) + iter_data->is_traffic_change = true; + } + ++static void rtw89_btc_ntfy_wl_sta_iter(void *data, struct ieee80211_sta *sta) ++{ ++ struct rtw89_sta *rtwsta = sta_to_rtwsta(sta); ++ struct rtw89_btc_wl_sta_iter_data *iter_data = ++ (struct rtw89_btc_wl_sta_iter_data *)data; ++ struct rtw89_vif_link *rtwvif_link; ++ struct rtw89_sta_link *rtwsta_link; ++ unsigned int link_id; ++ ++ rtw89_sta_for_each_link(rtwsta, rtwsta_link, link_id) { ++ rtwvif_link = rtwsta_link->rtwvif_link; ++ __rtw89_btc_ntfy_wl_sta_iter(rtwvif_link, rtwsta_link, iter_data); ++ } ++} ++ + #define BTC_NHM_CHK_INTVL 20 + + void rtw89_btc_ntfy_wl_sta(struct rtw89_dev *rtwdev) +diff --git a/drivers/net/wireless/realtek/rtw89/core.c b/drivers/net/wireless/realtek/rtw89/core.c +index 8d2cca0b0a18d..5b8e65f6de6a4 100644 +--- a/drivers/net/wireless/realtek/rtw89/core.c ++++ b/drivers/net/wireless/realtek/rtw89/core.c +@@ -436,15 +436,6 @@ int rtw89_set_channel(struct rtw89_dev *rtwdev) + return 0; + } + +-void rtw89_get_channel(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, +- struct rtw89_chan *chan) +-{ +- const struct cfg80211_chan_def *chandef; +- +- chandef = rtw89_chandef_get(rtwdev, rtwvif_link->chanctx_idx); +- rtw89_get_channel_params(chandef, chan); +-} +- + static enum rtw89_core_tx_type + rtw89_core_get_tx_type(struct rtw89_dev *rtwdev, + struct sk_buff *skb) +@@ -463,11 +454,11 @@ rtw89_core_tx_update_ampdu_info(struct rtw89_dev *rtwdev, + struct rtw89_core_tx_request *tx_req, + enum btc_pkt_type pkt_type) + { +- struct ieee80211_sta *sta = tx_req->sta; ++ struct rtw89_sta_link *rtwsta_link = tx_req->rtwsta_link; + struct rtw89_tx_desc_info *desc_info = &tx_req->desc_info; + struct ieee80211_link_sta *link_sta; + struct sk_buff *skb = tx_req->skb; +- struct rtw89_sta_link *rtwsta_link; ++ struct rtw89_sta *rtwsta; + u8 ampdu_num; + u8 tid; + +@@ -479,19 +470,19 @@ rtw89_core_tx_update_ampdu_info(struct rtw89_dev *rtwdev, + if (!(IEEE80211_SKB_CB(skb)->flags & IEEE80211_TX_CTL_AMPDU)) + return; + +- if (!sta) { ++ if (!rtwsta_link) { + rtw89_warn(rtwdev, "cannot set ampdu info without sta\n"); + return; + } + + tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK; +- rtwsta_link = (struct rtw89_sta_link *)sta->drv_priv; ++ rtwsta = rtwsta_link->rtwsta; + + rcu_read_lock(); + + link_sta = rtw89_sta_rcu_dereference_link(rtwsta_link, false); +- ampdu_num = (u8)((rtwsta_link->ampdu_params[tid].agg_num ? +- rtwsta_link->ampdu_params[tid].agg_num : ++ ampdu_num = (u8)((rtwsta->ampdu_params[tid].agg_num ? ++ rtwsta->ampdu_params[tid].agg_num : + 4 << link_sta->ht_cap.ampdu_factor) - 1); + + desc_info->agg_en = true; +@@ -575,9 +566,10 @@ static u16 rtw89_core_get_mgmt_rate(struct rtw89_dev *rtwdev, + const struct rtw89_chan *chan) + { + struct sk_buff *skb = tx_req->skb; ++ struct rtw89_vif_link *rtwvif_link = tx_req->rtwvif_link; ++ struct rtw89_sta_link *rtwsta_link = tx_req->rtwsta_link; + struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); + struct ieee80211_vif *vif = tx_info->control.vif; +- struct rtw89_vif_link *rtwvif_link = vif_to_rtwvif_safe(vif); + struct ieee80211_bss_conf *bss_conf; + u16 lowest_rate; + u16 rate; +@@ -596,7 +588,7 @@ static u16 rtw89_core_get_mgmt_rate(struct rtw89_dev *rtwdev, + rcu_read_lock(); + + bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, false); +- if (!bss_conf->basic_rates || !tx_req->sta) { ++ if (!bss_conf->basic_rates || !rtwsta_link) { + rate = lowest_rate; + goto out; + } +@@ -612,15 +604,12 @@ static u16 rtw89_core_get_mgmt_rate(struct rtw89_dev *rtwdev, + static u8 rtw89_core_tx_get_mac_id(struct rtw89_dev *rtwdev, + struct rtw89_core_tx_request *tx_req) + { +- struct ieee80211_vif *vif = tx_req->vif; +- struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv; +- struct ieee80211_sta *sta = tx_req->sta; +- struct rtw89_sta_link *rtwsta_link; ++ struct rtw89_vif_link *rtwvif_link = tx_req->rtwvif_link; ++ struct rtw89_sta_link *rtwsta_link = tx_req->rtwsta_link; + +- if (!sta) ++ if (!rtwsta_link) + return rtwvif_link->mac_id; + +- rtwsta_link = (struct rtw89_sta_link *)sta->drv_priv; + return rtwsta_link->mac_id; + } + +@@ -640,8 +629,7 @@ rtw89_core_tx_update_mgmt_info(struct rtw89_dev *rtwdev, + struct rtw89_core_tx_request *tx_req) + { + const struct rtw89_chip_info *chip = rtwdev->chip; +- struct ieee80211_vif *vif = tx_req->vif; +- struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv; ++ struct rtw89_vif_link *rtwvif_link = tx_req->rtwvif_link; + struct rtw89_tx_desc_info *desc_info = &tx_req->desc_info; + const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, + rtwvif_link->chanctx_idx); +@@ -723,8 +711,7 @@ __rtw89_core_tx_check_he_qos_htc(struct rtw89_dev *rtwdev, + struct rtw89_core_tx_request *tx_req, + enum btc_pkt_type pkt_type) + { +- struct ieee80211_sta *sta = tx_req->sta; +- struct rtw89_sta_link *rtwsta_link = sta_to_rtwsta_safe(sta); ++ struct rtw89_sta_link *rtwsta_link = tx_req->rtwsta_link; + struct sk_buff *skb = tx_req->skb; + struct ieee80211_hdr *hdr = (void *)skb->data; + struct ieee80211_link_sta *link_sta; +@@ -763,8 +750,7 @@ static void + __rtw89_core_tx_adjust_he_qos_htc(struct rtw89_dev *rtwdev, + struct rtw89_core_tx_request *tx_req) + { +- struct ieee80211_sta *sta = tx_req->sta; +- struct rtw89_sta_link *rtwsta_link = (struct rtw89_sta_link *)sta->drv_priv; ++ struct rtw89_sta_link *rtwsta_link = tx_req->rtwsta_link; + struct sk_buff *skb = tx_req->skb; + struct ieee80211_hdr *hdr = (void *)skb->data; + __le16 fc = hdr->frame_control; +@@ -794,8 +780,7 @@ rtw89_core_tx_update_he_qos_htc(struct rtw89_dev *rtwdev, + enum btc_pkt_type pkt_type) + { + struct rtw89_tx_desc_info *desc_info = &tx_req->desc_info; +- struct ieee80211_vif *vif = tx_req->vif; +- struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv; ++ struct rtw89_vif_link *rtwvif_link = tx_req->rtwvif_link; + + if (!__rtw89_core_tx_check_he_qos_htc(rtwdev, tx_req, pkt_type)) + goto desc_bk; +@@ -816,10 +801,9 @@ rtw89_core_tx_update_he_qos_htc(struct rtw89_dev *rtwdev, + static u16 rtw89_core_get_data_rate(struct rtw89_dev *rtwdev, + struct rtw89_core_tx_request *tx_req) + { +- struct ieee80211_vif *vif = tx_req->vif; +- struct ieee80211_sta *sta = tx_req->sta; +- struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv; +- struct rtw89_sta_link *rtwsta_link = sta_to_rtwsta_safe(sta); ++ struct rtw89_vif_link *rtwvif_link = tx_req->rtwvif_link; ++ struct rtw89_sta_link *rtwsta_link = tx_req->rtwsta_link; ++ struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link); + struct rtw89_phy_rate_pattern *rate_pattern = &rtwvif_link->rate_pattern; + enum rtw89_chanctx_idx idx = rtwvif_link->chanctx_idx; + const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, idx); +@@ -860,10 +844,8 @@ static void + rtw89_core_tx_update_data_info(struct rtw89_dev *rtwdev, + struct rtw89_core_tx_request *tx_req) + { +- struct ieee80211_vif *vif = tx_req->vif; +- struct ieee80211_sta *sta = tx_req->sta; +- struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv; +- struct rtw89_sta_link *rtwsta_link = sta_to_rtwsta_safe(sta); ++ struct rtw89_vif_link *rtwvif_link = tx_req->rtwvif_link; ++ struct rtw89_sta_link *rtwsta_link = tx_req->rtwsta_link; + struct rtw89_tx_desc_info *desc_info = &tx_req->desc_info; + struct sk_buff *skb = tx_req->skb; + u8 tid, tid_indicate; +@@ -1076,16 +1058,37 @@ int rtw89_h2c_tx(struct rtw89_dev *rtwdev, + int rtw89_core_tx_write(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif, + struct ieee80211_sta *sta, struct sk_buff *skb, int *qsel) + { ++ struct rtw89_sta *rtwsta = sta_to_rtwsta_safe(sta); ++ struct rtw89_vif *rtwvif = vif_to_rtwvif(vif); + struct rtw89_core_tx_request tx_req = {0}; +- struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv; ++ struct rtw89_sta_link *rtwsta_link = NULL; ++ struct rtw89_vif_link *rtwvif_link; + int ret; + ++ /* By default, driver writes tx via the link on HW-0. And then, ++ * according to links' status, HW can change tx to another link. ++ */ ++ ++ if (rtwsta) { ++ rtwsta_link = rtw89_sta_get_link_inst(rtwsta, 0); ++ if (unlikely(!rtwsta_link)) { ++ rtw89_err(rtwdev, "tx: find no sta link on HW-0\n"); ++ return -ENOLINK; ++ } ++ } ++ ++ rtwvif_link = rtw89_vif_get_link_inst(rtwvif, 0); ++ if (unlikely(!rtwvif_link)) { ++ rtw89_err(rtwdev, "tx: find no vif link on HW-0\n"); ++ return -ENOLINK; ++ } ++ + tx_req.skb = skb; +- tx_req.sta = sta; +- tx_req.vif = vif; ++ tx_req.rtwvif_link = rtwvif_link; ++ tx_req.rtwsta_link = rtwsta_link; + + rtw89_traffic_stats_accu(rtwdev, &rtwdev->stats, skb, true); +- rtw89_traffic_stats_accu(rtwdev, &rtwvif_link->stats, skb, true); ++ rtw89_traffic_stats_accu(rtwdev, &rtwvif->stats, skb, true); + rtw89_core_tx_update_desc_info(rtwdev, &tx_req); + rtw89_core_tx_wake(rtwdev, &tx_req); + +@@ -1563,15 +1566,23 @@ static u8 rtw89_get_data_rate_nss(struct rtw89_dev *rtwdev, u16 data_rate) + static void rtw89_core_rx_process_phy_ppdu_iter(void *data, + struct ieee80211_sta *sta) + { +- struct rtw89_sta_link *rtwsta_link = (struct rtw89_sta_link *)sta->drv_priv; + struct rtw89_rx_phy_ppdu *phy_ppdu = (struct rtw89_rx_phy_ppdu *)data; +- struct rtw89_dev *rtwdev = rtwsta_link->rtwdev; ++ struct rtw89_sta *rtwsta = sta_to_rtwsta(sta); ++ struct rtw89_dev *rtwdev = rtwsta->rtwdev; + struct rtw89_hal *hal = &rtwdev->hal; ++ struct rtw89_sta_link *rtwsta_link; + u8 ant_num = hal->ant_diversity ? 2 : rtwdev->chip->rf_path_num; + u8 ant_pos = U8_MAX; + u8 evm_pos = 0; + int i; + ++ /* FIXME: For single link, taking link on HW-0 here is okay. But, when ++ * enabling multiple active links, we should determine the right link. ++ */ ++ rtwsta_link = rtw89_sta_get_link_inst(rtwsta, 0); ++ if (unlikely(!rtwsta_link)) ++ return; ++ + if (rtwsta_link->mac_id != phy_ppdu->mac_id || !phy_ppdu->to_self) + return; + +@@ -1927,12 +1938,13 @@ struct rtw89_vif_rx_stats_iter_data { + }; + + static void rtw89_stats_trigger_frame(struct rtw89_dev *rtwdev, +- struct ieee80211_vif *vif, ++ struct rtw89_vif_link *rtwvif_link, + struct ieee80211_bss_conf *bss_conf, + struct sk_buff *skb) + { +- struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv; + struct ieee80211_trigger *tf = (struct ieee80211_trigger *)skb->data; ++ struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link); ++ struct rtw89_vif *rtwvif = rtwvif_link->rtwvif; + u8 *pos, *end, type, tf_bw; + u16 aid, tf_rua; + +@@ -1963,7 +1975,7 @@ static void rtw89_stats_trigger_frame(struct rtw89_dev *rtwdev, + if (aid == vif->cfg.aid) { + enum nl80211_he_ru_alloc rua = rtw89_he_rua_to_ru_alloc(tf_rua >> 1); + +- rtwvif_link->stats.rx_tf_acc++; ++ rtwvif->stats.rx_tf_acc++; + rtwdev->stats.rx_tf_acc++; + if (tf_bw == IEEE80211_TRIGGER_ULBW_160_80P80MHZ && + rua <= NL80211_RATE_INFO_HE_RU_ALLOC_106) +@@ -2052,15 +2064,16 @@ static void rtw89_vif_sync_bcn_tsf(struct rtw89_vif_link *rtwvif_link, + static void rtw89_vif_rx_stats_iter(void *data, u8 *mac, + struct ieee80211_vif *vif) + { +- struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv; + struct rtw89_vif_rx_stats_iter_data *iter_data = data; + struct rtw89_dev *rtwdev = iter_data->rtwdev; ++ struct rtw89_vif *rtwvif = vif_to_rtwvif(vif); + struct rtw89_pkt_stat *pkt_stat = &rtwdev->phystat.cur_pkt_stat; + struct rtw89_rx_desc_info *desc_info = iter_data->desc_info; + struct sk_buff *skb = iter_data->skb; + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; + struct rtw89_rx_phy_ppdu *phy_ppdu = iter_data->phy_ppdu; + struct ieee80211_bss_conf *bss_conf; ++ struct rtw89_vif_link *rtwvif_link; + const u8 *bssid = iter_data->bssid; + + if (rtwdev->scanning && +@@ -2070,12 +2083,19 @@ static void rtw89_vif_rx_stats_iter(void *data, u8 *mac, + + rcu_read_lock(); + ++ /* FIXME: For single link, taking link on HW-0 here is okay. But, when ++ * enabling multiple active links, we should determine the right link. ++ */ ++ rtwvif_link = rtw89_vif_get_link_inst(rtwvif, 0); ++ if (unlikely(!rtwvif_link)) ++ goto out; ++ + bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, false); + if (!bss_conf->bssid) + goto out; + + if (ieee80211_is_trigger(hdr->frame_control)) { +- rtw89_stats_trigger_frame(rtwdev, vif, bss_conf, skb); ++ rtw89_stats_trigger_frame(rtwdev, rtwvif_link, bss_conf, skb); + goto out; + } + +@@ -2097,7 +2117,7 @@ static void rtw89_vif_rx_stats_iter(void *data, u8 *mac, + if (desc_info->data_rate < RTW89_HW_RATE_NR) + pkt_stat->rx_rate_cnt[desc_info->data_rate]++; + +- rtw89_traffic_stats_accu(rtwdev, &rtwvif_link->stats, skb, false); ++ rtw89_traffic_stats_accu(rtwdev, &rtwvif->stats, skb, false); + + out: + rcu_read_unlock(); +@@ -2491,10 +2511,18 @@ void rtw89_core_stats_sta_rx_status_iter(void *data, struct ieee80211_sta *sta) + struct rtw89_core_iter_rx_status *iter_data = + (struct rtw89_core_iter_rx_status *)data; + struct ieee80211_rx_status *rx_status = iter_data->rx_status; +- struct rtw89_sta_link *rtwsta_link = (struct rtw89_sta_link *)sta->drv_priv; + struct rtw89_rx_desc_info *desc_info = iter_data->desc_info; ++ struct rtw89_sta *rtwsta = sta_to_rtwsta(sta); ++ struct rtw89_sta_link *rtwsta_link; + u8 mac_id = iter_data->mac_id; + ++ /* FIXME: For single link, taking link on HW-0 here is okay. But, when ++ * enabling multiple active links, we should determine the right link. ++ */ ++ rtwsta_link = rtw89_sta_get_link_inst(rtwsta, 0); ++ if (unlikely(!rtwsta_link)) ++ return; ++ + if (mac_id != rtwsta_link->mac_id) + return; + +@@ -2605,6 +2633,10 @@ static enum rtw89_ps_mode rtw89_update_ps_mode(struct rtw89_dev *rtwdev) + { + const struct rtw89_chip_info *chip = rtwdev->chip; + ++ /* FIXME: Fix __rtw89_enter_ps_mode() to consider MLO cases. */ ++ if (rtwdev->support_mlo) ++ return RTW89_PS_MODE_NONE; ++ + if (rtw89_disable_ps_mode || !chip->ps_mode_supported || + RTW89_CHK_FW_FEATURE(NO_DEEP_PS, &rtwdev->fw)) + return RTW89_PS_MODE_NONE; +@@ -2717,8 +2749,7 @@ static void rtw89_core_ba_work(struct work_struct *work) + list_for_each_entry_safe(rtwtxq, tmp, &rtwdev->ba_list, list) { + struct ieee80211_txq *txq = rtw89_txq_to_txq(rtwtxq); + struct ieee80211_sta *sta = txq->sta; +- struct rtw89_sta_link *rtwsta_link = +- sta ? (struct rtw89_sta_link *)sta->drv_priv : NULL; ++ struct rtw89_sta *rtwsta = sta_to_rtwsta_safe(sta); + u8 tid = txq->tid; + + if (!sta) { +@@ -2726,7 +2757,7 @@ static void rtw89_core_ba_work(struct work_struct *work) + goto skip_ba_work; + } + +- if (rtwsta_link->disassoc) { ++ if (rtwsta->disassoc) { + rtw89_debug(rtwdev, RTW89_DBG_TXRX, + "cannot start BA with disassoc sta\n"); + goto skip_ba_work; +@@ -2781,11 +2812,11 @@ void rtw89_core_free_sta_pending_forbid_ba(struct rtw89_dev *rtwdev, + void rtw89_core_free_sta_pending_roc_tx(struct rtw89_dev *rtwdev, + struct ieee80211_sta *sta) + { +- struct rtw89_sta_link *rtwsta_link = (struct rtw89_sta_link *)sta->drv_priv; ++ struct rtw89_sta *rtwsta = sta_to_rtwsta(sta); + struct sk_buff *skb, *tmp; + +- skb_queue_walk_safe(&rtwsta_link->roc_queue, skb, tmp) { +- skb_unlink(skb, &rtwsta_link->roc_queue); ++ skb_queue_walk_safe(&rtwsta->roc_queue, skb, tmp) { ++ skb_unlink(skb, &rtwsta->roc_queue); + dev_kfree_skb_any(skb); + } + } +@@ -2795,9 +2826,9 @@ static void rtw89_core_stop_tx_ba_session(struct rtw89_dev *rtwdev, + { + struct ieee80211_txq *txq = rtw89_txq_to_txq(rtwtxq); + struct ieee80211_sta *sta = txq->sta; +- struct rtw89_sta_link *rtwsta_link = sta_to_rtwsta_safe(sta); ++ struct rtw89_sta *rtwsta = sta_to_rtwsta_safe(sta); + +- if (unlikely(!rtwsta_link) || unlikely(rtwsta_link->disassoc)) ++ if (unlikely(!rtwsta) || unlikely(rtwsta->disassoc)) + return; + + if (!test_bit(RTW89_TXQ_F_AMPDU, &rtwtxq->flags) || +@@ -2822,8 +2853,7 @@ static void rtw89_core_txq_check_agg(struct rtw89_dev *rtwdev, + struct ieee80211_hw *hw = rtwdev->hw; + struct ieee80211_txq *txq = rtw89_txq_to_txq(rtwtxq); + struct ieee80211_sta *sta = txq->sta; +- struct rtw89_sta_link *rtwsta_link = +- sta ? (struct rtw89_sta_link *)sta->drv_priv : NULL; ++ struct rtw89_sta *rtwsta = sta_to_rtwsta_safe(sta); + + if (test_bit(RTW89_TXQ_F_FORBID_BA, &rtwtxq->flags)) + return; +@@ -2845,7 +2875,7 @@ static void rtw89_core_txq_check_agg(struct rtw89_dev *rtwdev, + } + + spin_lock_bh(&rtwdev->ba_lock); +- if (!rtwsta_link->disassoc && list_empty(&rtwtxq->list)) { ++ if (!rtwsta->disassoc && list_empty(&rtwtxq->list)) { + list_add_tail(&rtwtxq->list, &rtwdev->ba_list); + ieee80211_queue_work(hw, &rtwdev->ba_work); + } +@@ -2899,11 +2929,19 @@ static bool rtw89_core_txq_agg_wait(struct rtw89_dev *rtwdev, + bool *sched_txq, bool *reinvoke) + { + struct rtw89_txq *rtwtxq = (struct rtw89_txq *)txq->drv_priv; +- struct ieee80211_sta *sta = txq->sta; +- struct rtw89_sta_link *rtwsta_link = +- sta ? (struct rtw89_sta_link *)sta->drv_priv : NULL; ++ struct rtw89_sta *rtwsta = sta_to_rtwsta_safe(txq->sta); ++ struct rtw89_sta_link *rtwsta_link; + +- if (!sta || rtwsta_link->max_agg_wait <= 0) ++ if (!rtwsta) ++ return false; ++ ++ rtwsta_link = rtw89_sta_get_link_inst(rtwsta, 0); ++ if (unlikely(!rtwsta_link)) { ++ rtw89_err(rtwdev, "agg wait: find no link on HW-0\n"); ++ return false; ++ } ++ ++ if (rtwsta_link->max_agg_wait <= 0) + return false; + + if (rtwdev->stats.tx_tfc_lv <= RTW89_TFC_MID) +@@ -2931,7 +2969,7 @@ static void rtw89_core_txq_schedule(struct rtw89_dev *rtwdev, u8 ac, bool *reinv + { + struct ieee80211_hw *hw = rtwdev->hw; + struct ieee80211_txq *txq; +- struct rtw89_vif_link *rtwvif_link; ++ struct rtw89_vif *rtwvif; + struct rtw89_txq *rtwtxq; + unsigned long frame_cnt; + unsigned long byte_cnt; +@@ -2941,9 +2979,9 @@ static void rtw89_core_txq_schedule(struct rtw89_dev *rtwdev, u8 ac, bool *reinv + ieee80211_txq_schedule_start(hw, ac); + while ((txq = ieee80211_next_txq(hw, ac))) { + rtwtxq = (struct rtw89_txq *)txq->drv_priv; +- rtwvif_link = (struct rtw89_vif_link *)txq->vif->drv_priv; ++ rtwvif = vif_to_rtwvif(txq->vif); + +- if (rtwvif_link->offchan) { ++ if (rtwvif->offchan) { + ieee80211_return_txq(hw, txq, true); + continue; + } +@@ -3017,22 +3055,28 @@ static void rtw89_forbid_ba_work(struct work_struct *w) + static void rtw89_core_sta_pending_tx_iter(void *data, + struct ieee80211_sta *sta) + { +- struct rtw89_sta_link *rtwsta_link = (struct rtw89_sta_link *)sta->drv_priv; +- struct rtw89_vif_link *rtwvif_target = data; +- struct rtw89_vif_link *rtwvif_link = rtwsta_link->rtwvif_link; +- struct rtw89_dev *rtwdev = rtwvif_link->rtwdev; +- struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif_link); ++ struct rtw89_sta *rtwsta = sta_to_rtwsta(sta); ++ struct rtw89_dev *rtwdev = rtwsta->rtwdev; ++ struct rtw89_vif *rtwvif = rtwsta->rtwvif; ++ struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif); ++ struct rtw89_vif_link *target = data; ++ struct rtw89_vif_link *rtwvif_link; + struct sk_buff *skb, *tmp; ++ unsigned int link_id; + int qsel, ret; + +- if (rtwvif_link->chanctx_idx != rtwvif_target->chanctx_idx) +- return; ++ rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id) ++ if (rtwvif_link->chanctx_idx == target->chanctx_idx) ++ goto bottom; + +- if (skb_queue_len(&rtwsta_link->roc_queue) == 0) ++ return; ++ ++bottom: ++ if (skb_queue_len(&rtwsta->roc_queue) == 0) + return; + +- skb_queue_walk_safe(&rtwsta_link->roc_queue, skb, tmp) { +- skb_unlink(skb, &rtwsta_link->roc_queue); ++ skb_queue_walk_safe(&rtwsta->roc_queue, skb, tmp) { ++ skb_unlink(skb, &rtwsta->roc_queue); + + ret = rtw89_core_tx_write(rtwdev, vif, sta, skb, &qsel); + if (ret) { +@@ -3055,7 +3099,7 @@ static void rtw89_core_handle_sta_pending_tx(struct rtw89_dev *rtwdev, + static int rtw89_core_send_nullfunc(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, bool qos, bool ps) + { +- struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif_link); ++ struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link); + struct ieee80211_sta *sta; + struct ieee80211_hdr *hdr; + struct sk_buff *skb; +@@ -3098,19 +3142,27 @@ static int rtw89_core_send_nullfunc(struct rtw89_dev *rtwdev, + return ret; + } + +-void rtw89_roc_start(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link) ++void rtw89_roc_start(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif) + { + const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; + struct ieee80211_hw *hw = rtwdev->hw; +- struct rtw89_roc *roc = &rtwvif_link->roc; ++ struct rtw89_roc *roc = &rtwvif->roc; ++ struct rtw89_vif_link *rtwvif_link; + struct cfg80211_chan_def roc_chan; +- struct rtw89_vif_link *tmp; ++ struct rtw89_vif *tmp_vif; + int ret; + + lockdep_assert_held(&rtwdev->mutex); + + rtw89_leave_ips_by_hwflags(rtwdev); + rtw89_leave_lps(rtwdev); ++ ++ rtwvif_link = rtw89_vif_get_link_inst(rtwvif, 0); ++ if (unlikely(!rtwvif_link)) { ++ rtw89_err(rtwdev, "roc start: find no link on HW-0\n"); ++ return; ++ } ++ + rtw89_chanctx_pause(rtwdev, RTW89_CHANCTX_PAUSE_REASON_ROC); + + ret = rtw89_core_send_nullfunc(rtwdev, rtwvif_link, true, true); +@@ -3118,9 +3170,17 @@ void rtw89_roc_start(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_lin + rtw89_debug(rtwdev, RTW89_DBG_TXRX, + "roc send null-1 failed: %d\n", ret); + +- rtw89_for_each_rtwvif(rtwdev, tmp) +- if (tmp->chanctx_idx == rtwvif_link->chanctx_idx) +- tmp->offchan = true; ++ rtw89_for_each_rtwvif(rtwdev, tmp_vif) { ++ struct rtw89_vif_link *tmp_link; ++ unsigned int link_id; ++ ++ rtw89_vif_for_each_link(tmp_vif, tmp_link, link_id) { ++ if (tmp_link->chanctx_idx == rtwvif_link->chanctx_idx) { ++ tmp_vif->offchan = true; ++ break; ++ } ++ } ++ } + + cfg80211_chandef_create(&roc_chan, &roc->chan, NL80211_CHAN_NO_HT); + rtw89_config_roc_chandef(rtwdev, rtwvif_link->chanctx_idx, &roc_chan); +@@ -3130,17 +3190,18 @@ void rtw89_roc_start(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_lin + B_AX_A_UC_CAM_MATCH | B_AX_A_BC_CAM_MATCH); + + ieee80211_ready_on_channel(hw); +- cancel_delayed_work(&rtwvif_link->roc.roc_work); +- ieee80211_queue_delayed_work(hw, &rtwvif_link->roc.roc_work, +- msecs_to_jiffies(rtwvif_link->roc.duration)); ++ cancel_delayed_work(&rtwvif->roc.roc_work); ++ ieee80211_queue_delayed_work(hw, &rtwvif->roc.roc_work, ++ msecs_to_jiffies(rtwvif->roc.duration)); + } + +-void rtw89_roc_end(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link) ++void rtw89_roc_end(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif) + { + const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; + struct ieee80211_hw *hw = rtwdev->hw; +- struct rtw89_roc *roc = &rtwvif_link->roc; +- struct rtw89_vif_link *tmp; ++ struct rtw89_roc *roc = &rtwvif->roc; ++ struct rtw89_vif_link *rtwvif_link; ++ struct rtw89_vif *tmp_vif; + int ret; + + lockdep_assert_held(&rtwdev->mutex); +@@ -3150,6 +3211,12 @@ void rtw89_roc_end(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link) + rtw89_leave_ips_by_hwflags(rtwdev); + rtw89_leave_lps(rtwdev); + ++ rtwvif_link = rtw89_vif_get_link_inst(rtwvif, 0); ++ if (unlikely(!rtwvif_link)) { ++ rtw89_err(rtwdev, "roc end: find no link on HW-0\n"); ++ return; ++ } ++ + rtw89_write32_mask(rtwdev, + rtw89_mac_reg_by_idx(rtwdev, mac->rx_fltr, RTW89_MAC_0), + B_AX_RX_FLTR_CFG_MASK, +@@ -3163,9 +3230,8 @@ void rtw89_roc_end(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link) + rtw89_debug(rtwdev, RTW89_DBG_TXRX, + "roc send null-0 failed: %d\n", ret); + +- rtw89_for_each_rtwvif(rtwdev, tmp) +- if (tmp->chanctx_idx == rtwvif_link->chanctx_idx) +- tmp->offchan = false; ++ rtw89_for_each_rtwvif(rtwdev, tmp_vif) ++ tmp_vif->offchan = false; + + rtw89_core_handle_sta_pending_tx(rtwdev, rtwvif_link); + queue_work(rtwdev->txq_wq, &rtwdev->txq_work); +@@ -3177,10 +3243,10 @@ void rtw89_roc_end(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link) + + void rtw89_roc_work(struct work_struct *work) + { +- struct rtw89_vif_link *rtwvif_link = container_of(work, struct rtw89_vif_link, +- roc.roc_work.work); +- struct rtw89_dev *rtwdev = rtwvif_link->rtwdev; +- struct rtw89_roc *roc = &rtwvif_link->roc; ++ struct rtw89_vif *rtwvif = container_of(work, struct rtw89_vif, ++ roc.roc_work.work); ++ struct rtw89_dev *rtwdev = rtwvif->rtwdev; ++ struct rtw89_roc *roc = &rtwvif->roc; + + mutex_lock(&rtwdev->mutex); + +@@ -3190,7 +3256,7 @@ void rtw89_roc_work(struct work_struct *work) + break; + case RTW89_ROC_MGMT: + case RTW89_ROC_NORMAL: +- rtw89_roc_end(rtwdev, rtwvif_link); ++ rtw89_roc_end(rtwdev, rtwvif); + break; + default: + break; +@@ -3252,12 +3318,17 @@ static bool rtw89_traffic_stats_calc(struct rtw89_dev *rtwdev, + static bool rtw89_traffic_stats_track(struct rtw89_dev *rtwdev) + { + struct rtw89_vif_link *rtwvif_link; ++ struct rtw89_vif *rtwvif; ++ unsigned int link_id; + bool tfc_changed; + + tfc_changed = rtw89_traffic_stats_calc(rtwdev, &rtwdev->stats); +- rtw89_for_each_rtwvif(rtwdev, rtwvif_link) { +- rtw89_traffic_stats_calc(rtwdev, &rtwvif_link->stats); +- rtw89_fw_h2c_tp_offload(rtwdev, rtwvif_link); ++ ++ rtw89_for_each_rtwvif(rtwdev, rtwvif) { ++ rtw89_traffic_stats_calc(rtwdev, &rtwvif->stats); ++ ++ rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id) ++ rtw89_fw_h2c_tp_offload(rtwdev, rtwvif_link); + } + + return tfc_changed; +@@ -3266,25 +3337,32 @@ static bool rtw89_traffic_stats_track(struct rtw89_dev *rtwdev) + static void rtw89_vif_enter_lps(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link) + { +- if ((rtwvif_link->wifi_role != RTW89_WIFI_ROLE_STATION && +- rtwvif_link->wifi_role != RTW89_WIFI_ROLE_P2P_CLIENT) || +- rtwvif_link->tdls_peer) +- return; +- +- if (rtwvif_link->offchan) ++ if (rtwvif_link->wifi_role != RTW89_WIFI_ROLE_STATION && ++ rtwvif_link->wifi_role != RTW89_WIFI_ROLE_P2P_CLIENT) + return; + +- if (rtwvif_link->stats.tx_tfc_lv == RTW89_TFC_IDLE && +- rtwvif_link->stats.rx_tfc_lv == RTW89_TFC_IDLE) +- rtw89_enter_lps(rtwdev, rtwvif_link, true); ++ rtw89_enter_lps(rtwdev, rtwvif_link, true); + } + + static void rtw89_enter_lps_track(struct rtw89_dev *rtwdev) + { + struct rtw89_vif_link *rtwvif_link; ++ struct rtw89_vif *rtwvif; ++ unsigned int link_id; ++ ++ rtw89_for_each_rtwvif(rtwdev, rtwvif) { ++ if (rtwvif->tdls_peer) ++ continue; ++ if (rtwvif->offchan) ++ continue; + +- rtw89_for_each_rtwvif(rtwdev, rtwvif_link) +- rtw89_vif_enter_lps(rtwdev, rtwvif_link); ++ if (rtwvif->stats.tx_tfc_lv != RTW89_TFC_IDLE || ++ rtwvif->stats.rx_tfc_lv != RTW89_TFC_IDLE) ++ continue; ++ ++ rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id) ++ rtw89_vif_enter_lps(rtwdev, rtwvif_link); ++ } + } + + static void rtw89_core_rfk_track(struct rtw89_dev *rtwdev) +@@ -3468,7 +3546,7 @@ int rtw89_core_release_sta_ba_entry(struct rtw89_dev *rtwdev, + break + void rtw89_vif_type_mapping(struct rtw89_vif_link *rtwvif_link, bool assoc) + { +- const struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif_link); ++ const struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link); + const struct ieee80211_bss_conf *bss_conf; + + switch (vif->type) { +@@ -3529,8 +3607,8 @@ int rtw89_core_sta_link_add(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link) + { +- struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif_link); +- struct ieee80211_sta *sta = rtwsta_to_sta(rtwsta_link); ++ const struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link); ++ const struct ieee80211_sta *sta = rtwsta_link_to_sta(rtwsta_link); + struct rtw89_hal *hal = &rtwdev->hal; + u8 ant_num = hal->ant_diversity ? 2 : rtwdev->chip->rf_path_num; + int i; +@@ -3586,7 +3664,7 @@ int rtw89_core_sta_link_disassoc(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link) + { +- struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif_link); ++ const struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link); + + if (vif->type == NL80211_IFTYPE_STATION) + rtw89_fw_h2c_set_bcn_fltr_cfg(rtwdev, rtwvif_link, false); +@@ -3598,8 +3676,8 @@ int rtw89_core_sta_link_disconnect(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link) + { +- struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif_link); +- struct ieee80211_sta *sta = rtwsta_to_sta(rtwsta_link); ++ const struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link); ++ const struct ieee80211_sta *sta = rtwsta_link_to_sta(rtwsta_link); + int ret; + + rtw89_mac_bf_monitor_calc(rtwdev, rtwsta_link, true); +@@ -3641,8 +3719,8 @@ int rtw89_core_sta_link_assoc(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link) + { +- struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif_link); +- struct ieee80211_sta *sta = rtwsta_to_sta(rtwsta_link); ++ const struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link); ++ const struct ieee80211_sta *sta = rtwsta_link_to_sta(rtwsta_link); + struct rtw89_bssid_cam_entry *bssid_cam = rtw89_get_bssid_cam_of(rtwvif_link, + rtwsta_link); + const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, +@@ -3730,8 +3808,8 @@ int rtw89_core_sta_link_remove(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link) + { +- struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif_link); +- struct ieee80211_sta *sta = rtwsta_to_sta(rtwsta_link); ++ const struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link); ++ const struct ieee80211_sta *sta = rtwsta_link_to_sta(rtwsta_link); + int ret; + + if (vif->type == NL80211_IFTYPE_STATION && !sta->tdls) { +@@ -4212,7 +4290,8 @@ void rtw89_core_update_beacon_work(struct work_struct *work) + if (rtwvif_link->net_type != RTW89_NET_TYPE_AP_MODE) + return; + +- rtwdev = rtwvif_link->rtwdev; ++ rtwdev = rtwvif_link->rtwvif->rtwdev; ++ + mutex_lock(&rtwdev->mutex); + rtw89_chip_h2c_update_beacon(rtwdev, rtwvif_link); + mutex_unlock(&rtwdev->mutex); +@@ -4409,6 +4488,168 @@ void rtw89_release_mac_id(struct rtw89_dev *rtwdev, u8 mac_id) + clear_bit(mac_id, rtwdev->mac_id_map); + } + ++void rtw89_init_vif(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, ++ u8 mac_id, u8 port) ++{ ++ const struct rtw89_chip_info *chip = rtwdev->chip; ++ u8 support_link_num = chip->support_link_num; ++ u8 support_mld_num = 0; ++ unsigned int link_id; ++ u8 index; ++ ++ bitmap_zero(rtwvif->links_inst_map, __RTW89_MLD_MAX_LINK_NUM); ++ for (link_id = 0; link_id < IEEE80211_MLD_MAX_NUM_LINKS; link_id++) ++ rtwvif->links[link_id] = NULL; ++ ++ rtwvif->rtwdev = rtwdev; ++ ++ if (rtwdev->support_mlo) { ++ rtwvif->links_inst_valid_num = support_link_num; ++ support_mld_num = chip->support_macid_num / support_link_num; ++ } else { ++ rtwvif->links_inst_valid_num = 1; ++ } ++ ++ for (index = 0; index < rtwvif->links_inst_valid_num; index++) { ++ struct rtw89_vif_link *inst = &rtwvif->links_inst[index]; ++ ++ inst->rtwvif = rtwvif; ++ inst->mac_id = mac_id + index * support_mld_num; ++ inst->mac_idx = RTW89_MAC_0 + index; ++ inst->phy_idx = RTW89_PHY_0 + index; ++ ++ /* multi-link use the same port id on different HW bands */ ++ inst->port = port; ++ } ++} ++ ++void rtw89_init_sta(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, ++ struct rtw89_sta *rtwsta, u8 mac_id) ++{ ++ const struct rtw89_chip_info *chip = rtwdev->chip; ++ u8 support_link_num = chip->support_link_num; ++ u8 support_mld_num = 0; ++ unsigned int link_id; ++ u8 index; ++ ++ bitmap_zero(rtwsta->links_inst_map, __RTW89_MLD_MAX_LINK_NUM); ++ for (link_id = 0; link_id < IEEE80211_MLD_MAX_NUM_LINKS; link_id++) ++ rtwsta->links[link_id] = NULL; ++ ++ rtwsta->rtwdev = rtwdev; ++ rtwsta->rtwvif = rtwvif; ++ ++ if (rtwdev->support_mlo) { ++ rtwsta->links_inst_valid_num = support_link_num; ++ support_mld_num = chip->support_macid_num / support_link_num; ++ } else { ++ rtwsta->links_inst_valid_num = 1; ++ } ++ ++ for (index = 0; index < rtwsta->links_inst_valid_num; index++) { ++ struct rtw89_sta_link *inst = &rtwsta->links_inst[index]; ++ ++ inst->rtwvif_link = &rtwvif->links_inst[index]; ++ ++ inst->rtwsta = rtwsta; ++ inst->mac_id = mac_id + index * support_mld_num; ++ } ++} ++ ++struct rtw89_vif_link *rtw89_vif_set_link(struct rtw89_vif *rtwvif, ++ unsigned int link_id) ++{ ++ struct rtw89_vif_link *rtwvif_link = rtwvif->links[link_id]; ++ u8 index; ++ int ret; ++ ++ if (rtwvif_link) ++ return rtwvif_link; ++ ++ index = find_first_zero_bit(rtwvif->links_inst_map, ++ rtwvif->links_inst_valid_num); ++ if (index == rtwvif->links_inst_valid_num) { ++ ret = -EBUSY; ++ goto err; ++ } ++ ++ rtwvif_link = &rtwvif->links_inst[index]; ++ rtwvif_link->link_id = link_id; ++ ++ set_bit(index, rtwvif->links_inst_map); ++ rtwvif->links[link_id] = rtwvif_link; ++ return rtwvif_link; ++ ++err: ++ rtw89_err(rtwvif->rtwdev, "vif (link_id %u) failed to set link: %d\n", ++ link_id, ret); ++ return NULL; ++} ++ ++void rtw89_vif_unset_link(struct rtw89_vif *rtwvif, unsigned int link_id) ++{ ++ struct rtw89_vif_link **container = &rtwvif->links[link_id]; ++ struct rtw89_vif_link *link = *container; ++ u8 index; ++ ++ if (!link) ++ return; ++ ++ index = rtw89_vif_link_inst_get_index(link); ++ clear_bit(index, rtwvif->links_inst_map); ++ *container = NULL; ++} ++ ++struct rtw89_sta_link *rtw89_sta_set_link(struct rtw89_sta *rtwsta, ++ unsigned int link_id) ++{ ++ struct rtw89_vif *rtwvif = rtwsta->rtwvif; ++ struct rtw89_vif_link *rtwvif_link = rtwvif->links[link_id]; ++ struct rtw89_sta_link *rtwsta_link = rtwsta->links[link_id]; ++ u8 index; ++ int ret; ++ ++ if (rtwsta_link) ++ return rtwsta_link; ++ ++ if (!rtwvif_link) { ++ ret = -ENOLINK; ++ goto err; ++ } ++ ++ index = rtw89_vif_link_inst_get_index(rtwvif_link); ++ if (test_bit(index, rtwsta->links_inst_map)) { ++ ret = -EBUSY; ++ goto err; ++ } ++ ++ rtwsta_link = &rtwsta->links_inst[index]; ++ rtwsta_link->link_id = link_id; ++ ++ set_bit(index, rtwsta->links_inst_map); ++ rtwsta->links[link_id] = rtwsta_link; ++ return rtwsta_link; ++ ++err: ++ rtw89_err(rtwsta->rtwdev, "sta (link_id %u) failed to set link: %d\n", ++ link_id, ret); ++ return NULL; ++} ++ ++void rtw89_sta_unset_link(struct rtw89_sta *rtwsta, unsigned int link_id) ++{ ++ struct rtw89_sta_link **container = &rtwsta->links[link_id]; ++ struct rtw89_sta_link *link = *container; ++ u8 index; ++ ++ if (!link) ++ return; ++ ++ index = rtw89_sta_link_inst_get_index(link); ++ clear_bit(index, rtwsta->links_inst_map); ++ *container = NULL; ++} ++ + int rtw89_core_init(struct rtw89_dev *rtwdev) + { + struct rtw89_btc *btc = &rtwdev->btc; +@@ -4519,10 +4760,8 @@ void rtw89_core_scan_start(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwv + } + + void rtw89_core_scan_complete(struct rtw89_dev *rtwdev, +- struct ieee80211_vif *vif, bool hw_scan) ++ struct rtw89_vif_link *rtwvif_link, bool hw_scan) + { +- struct rtw89_vif_link *rtwvif_link = +- vif ? (struct rtw89_vif_link *)vif->drv_priv : NULL; + struct ieee80211_bss_conf *bss_conf; + + if (!rtwvif_link) +@@ -4753,7 +4992,7 @@ EXPORT_SYMBOL(rtw89_chip_info_setup); + void rtw89_chip_cfg_txpwr_ul_tb_offset(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link) + { +- struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif_link); ++ struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link); + const struct rtw89_chip_info *chip = rtwdev->chip; + struct ieee80211_bss_conf *bss_conf; + +@@ -4774,14 +5013,15 @@ void rtw89_chip_cfg_txpwr_ul_tb_offset(struct rtw89_dev *rtwdev, + static int rtw89_core_register_hw(struct rtw89_dev *rtwdev) + { + const struct rtw89_chip_info *chip = rtwdev->chip; ++ u8 n = rtwdev->support_mlo ? chip->support_link_num : 1; + struct ieee80211_hw *hw = rtwdev->hw; + struct rtw89_efuse *efuse = &rtwdev->efuse; + struct rtw89_hal *hal = &rtwdev->hal; + int ret; + int tx_headroom = IEEE80211_HT_CTL_LEN; + +- hw->vif_data_size = sizeof(struct rtw89_vif_link); +- hw->sta_data_size = sizeof(struct rtw89_sta_link); ++ hw->vif_data_size = struct_size_t(struct rtw89_vif, links_inst, n); ++ hw->sta_data_size = struct_size_t(struct rtw89_sta, links_inst, n); + hw->txq_data_size = sizeof(struct rtw89_txq); + hw->chanctx_data_size = sizeof(struct rtw89_chanctx_cfg); + +diff --git a/drivers/net/wireless/realtek/rtw89/core.h b/drivers/net/wireless/realtek/rtw89/core.h +index bfa3dba07fe1e..de33320b1354c 100644 +--- a/drivers/net/wireless/realtek/rtw89/core.h ++++ b/drivers/net/wireless/realtek/rtw89/core.h +@@ -829,6 +829,8 @@ enum rtw89_phy_idx { + RTW89_PHY_MAX + }; + ++#define __RTW89_MLD_MAX_LINK_NUM 2 ++ + enum rtw89_chanctx_idx { + RTW89_CHANCTX_0 = 0, + RTW89_CHANCTX_1 = 1, +@@ -1166,8 +1168,8 @@ struct rtw89_core_tx_request { + enum rtw89_core_tx_type tx_type; + + struct sk_buff *skb; +- struct ieee80211_vif *vif; +- struct ieee80211_sta *sta; ++ struct rtw89_vif_link *rtwvif_link; ++ struct rtw89_sta_link *rtwsta_link; + struct rtw89_tx_desc_info desc_info; + }; + +@@ -3355,12 +3357,11 @@ struct rtw89_sec_cam_entry { + }; + + struct rtw89_sta_link { ++ struct rtw89_sta *rtwsta; + unsigned int link_id; + + u8 mac_id; +- bool disassoc; + bool er_cap; +- struct rtw89_dev *rtwdev; + struct rtw89_vif_link *rtwvif_link; + struct rtw89_ra_info ra; + struct rtw89_ra_report ra_report; +@@ -3372,15 +3373,12 @@ struct rtw89_sta_link { + struct ewma_evm evm_1ss; + struct ewma_evm evm_min[RF_PATH_MAX]; + struct ewma_evm evm_max[RF_PATH_MAX]; +- struct rtw89_ampdu_params ampdu_params[IEEE80211_NUM_TIDS]; +- DECLARE_BITMAP(ampdu_map, IEEE80211_NUM_TIDS); + struct ieee80211_rx_status rx_status; + u16 rx_hw_rate; + __le32 htc_template; + struct rtw89_addr_cam_entry addr_cam; /* AP mode or TDLS peer only */ + struct rtw89_bssid_cam_entry bssid_cam; /* TDLS peer only */ + struct list_head ba_cam_list; +- struct sk_buff_head roc_queue; + + bool use_cfg_mask; + struct cfg80211_bitrate_mask mask; +@@ -3463,11 +3461,9 @@ struct rtw89_p2p_noa_setter { + }; + + struct rtw89_vif_link { ++ struct rtw89_vif *rtwvif; + unsigned int link_id; + +- struct list_head list; +- struct rtw89_dev *rtwdev; +- struct rtw89_roc roc; + bool chanctx_assigned; /* only valid when running with chanctx_ops */ + enum rtw89_chanctx_idx chanctx_idx; + enum rtw89_reg_6ghz_power reg_6ghz_power; +@@ -3477,7 +3473,6 @@ struct rtw89_vif_link { + u8 port; + u8 mac_addr[ETH_ALEN]; + u8 bssid[ETH_ALEN]; +- __be32 ip_addr; + u8 phy_idx; + u8 mac_idx; + u8 net_type; +@@ -3488,7 +3483,6 @@ struct rtw89_vif_link { + u8 hit_rule; + u8 last_noa_nr; + u64 sync_bcn_tsf; +- bool offchan; + bool trigger; + bool lsig_txop; + u8 tgt_ind; +@@ -3502,15 +3496,11 @@ struct rtw89_vif_link { + bool pre_pwr_diff_en; + bool pwr_diff_en; + u8 def_tri_idx; +- u32 tdls_peer; + struct work_struct update_beacon_work; + struct rtw89_addr_cam_entry addr_cam; + struct rtw89_bssid_cam_entry bssid_cam; + struct ieee80211_tx_queue_params tx_params[IEEE80211_NUM_ACS]; +- struct rtw89_traffic_stats stats; + struct rtw89_phy_rate_pattern rate_pattern; +- struct cfg80211_scan_request *scan_req; +- struct ieee80211_scan_ies *scan_ies; + struct list_head general_pkt_list; + struct rtw89_p2p_noa_setter p2p_noa; + }; +@@ -3659,14 +3649,16 @@ struct rtw89_chip_ops { + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link); + int (*h2c_ampdu_cmac_tbl)(struct rtw89_dev *rtwdev, +- struct ieee80211_vif *vif, +- struct ieee80211_sta *sta); ++ struct rtw89_vif_link *rtwvif_link, ++ struct rtw89_sta_link *rtwsta_link); + int (*h2c_default_dmac_tbl)(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link); + int (*h2c_update_beacon)(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link); +- int (*h2c_ba_cam)(struct rtw89_dev *rtwdev, struct rtw89_sta_link *rtwsta_link, ++ int (*h2c_ba_cam)(struct rtw89_dev *rtwdev, ++ struct rtw89_vif_link *rtwvif_link, ++ struct rtw89_sta_link *rtwsta_link, + bool valid, struct ieee80211_ampdu_params *params); + + void (*btc_set_rfe)(struct rtw89_dev *rtwdev); +@@ -5200,7 +5192,7 @@ struct rtw89_early_h2c { + }; + + struct rtw89_hw_scan_info { +- struct ieee80211_vif *scanning_vif; ++ struct rtw89_vif_link *scanning_vif; + struct list_head pkt_list[NUM_NL80211_BANDS]; + struct rtw89_chan op_chan; + bool abort; +@@ -5375,7 +5367,7 @@ struct rtw89_wow_aoac_report { + }; + + struct rtw89_wow_param { +- struct ieee80211_vif *wow_vif; ++ struct rtw89_vif_link *rtwvif_link; + DECLARE_BITMAP(flags, RTW89_WOW_FLAG_NUM); + struct rtw89_wow_cam_info patterns[RTW89_MAX_PATTERN_NUM]; + struct rtw89_wow_key_info key_info; +@@ -5612,6 +5604,121 @@ struct rtw89_dev { + u8 priv[] __aligned(sizeof(void *)); + }; + ++struct rtw89_vif { ++ struct rtw89_dev *rtwdev; ++ struct list_head list; ++ ++ u8 mac_addr[ETH_ALEN]; ++ __be32 ip_addr; ++ ++ struct rtw89_traffic_stats stats; ++ u32 tdls_peer; ++ ++ struct ieee80211_scan_ies *scan_ies; ++ struct cfg80211_scan_request *scan_req; ++ ++ struct rtw89_roc roc; ++ bool offchan; ++ ++ u8 links_inst_valid_num; ++ DECLARE_BITMAP(links_inst_map, __RTW89_MLD_MAX_LINK_NUM); ++ struct rtw89_vif_link *links[IEEE80211_MLD_MAX_NUM_LINKS]; ++ struct rtw89_vif_link links_inst[] __counted_by(links_inst_valid_num); ++}; ++ ++static inline bool rtw89_vif_assign_link_is_valid(struct rtw89_vif_link **rtwvif_link, ++ const struct rtw89_vif *rtwvif, ++ unsigned int link_id) ++{ ++ *rtwvif_link = rtwvif->links[link_id]; ++ return !!*rtwvif_link; ++} ++ ++#define rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id) \ ++ for (link_id = 0; link_id < IEEE80211_MLD_MAX_NUM_LINKS; link_id++) \ ++ if (rtw89_vif_assign_link_is_valid(&(rtwvif_link), rtwvif, link_id)) ++ ++struct rtw89_sta { ++ struct rtw89_dev *rtwdev; ++ struct rtw89_vif *rtwvif; ++ ++ bool disassoc; ++ ++ struct sk_buff_head roc_queue; ++ ++ struct rtw89_ampdu_params ampdu_params[IEEE80211_NUM_TIDS]; ++ DECLARE_BITMAP(ampdu_map, IEEE80211_NUM_TIDS); ++ ++ u8 links_inst_valid_num; ++ DECLARE_BITMAP(links_inst_map, __RTW89_MLD_MAX_LINK_NUM); ++ struct rtw89_sta_link *links[IEEE80211_MLD_MAX_NUM_LINKS]; ++ struct rtw89_sta_link links_inst[] __counted_by(links_inst_valid_num); ++}; ++ ++static inline bool rtw89_sta_assign_link_is_valid(struct rtw89_sta_link **rtwsta_link, ++ const struct rtw89_sta *rtwsta, ++ unsigned int link_id) ++{ ++ *rtwsta_link = rtwsta->links[link_id]; ++ return !!*rtwsta_link; ++} ++ ++#define rtw89_sta_for_each_link(rtwsta, rtwsta_link, link_id) \ ++ for (link_id = 0; link_id < IEEE80211_MLD_MAX_NUM_LINKS; link_id++) \ ++ if (rtw89_sta_assign_link_is_valid(&(rtwsta_link), rtwsta, link_id)) ++ ++static inline u8 rtw89_vif_get_main_macid(struct rtw89_vif *rtwvif) ++{ ++ /* const after init, so no need to check if active first */ ++ return rtwvif->links_inst[0].mac_id; ++} ++ ++static inline u8 rtw89_vif_get_main_port(struct rtw89_vif *rtwvif) ++{ ++ /* const after init, so no need to check if active first */ ++ return rtwvif->links_inst[0].port; ++} ++ ++static inline struct rtw89_vif_link * ++rtw89_vif_get_link_inst(struct rtw89_vif *rtwvif, u8 index) ++{ ++ if (index >= rtwvif->links_inst_valid_num || ++ !test_bit(index, rtwvif->links_inst_map)) ++ return NULL; ++ return &rtwvif->links_inst[index]; ++} ++ ++static inline ++u8 rtw89_vif_link_inst_get_index(struct rtw89_vif_link *rtwvif_link) ++{ ++ struct rtw89_vif *rtwvif = rtwvif_link->rtwvif; ++ ++ return rtwvif_link - rtwvif->links_inst; ++} ++ ++static inline u8 rtw89_sta_get_main_macid(struct rtw89_sta *rtwsta) ++{ ++ /* const after init, so no need to check if active first */ ++ return rtwsta->links_inst[0].mac_id; ++} ++ ++static inline struct rtw89_sta_link * ++rtw89_sta_get_link_inst(struct rtw89_sta *rtwsta, u8 index) ++{ ++ if (index >= rtwsta->links_inst_valid_num || ++ !test_bit(index, rtwsta->links_inst_map)) ++ return NULL; ++ return &rtwsta->links_inst[index]; ++} ++ ++static inline ++u8 rtw89_sta_link_inst_get_index(struct rtw89_sta_link *rtwsta_link) ++{ ++ struct rtw89_sta *rtwsta = rtwsta_link->rtwsta; ++ ++ return rtwsta_link - rtwsta->links_inst; ++} ++ + static inline int rtw89_hci_tx_write(struct rtw89_dev *rtwdev, + struct rtw89_core_tx_request *tx_req) + { +@@ -5964,44 +6071,78 @@ static inline void rtw89_core_txq_init(struct rtw89_dev *rtwdev, + INIT_LIST_HEAD(&rtwtxq->list); + } + +-static inline struct ieee80211_vif *rtwvif_to_vif(struct rtw89_vif_link *rtwvif_link) ++static inline struct ieee80211_vif *rtwvif_to_vif(struct rtw89_vif *rtwvif) + { +- void *p = rtwvif_link; ++ void *p = rtwvif; + + return container_of(p, struct ieee80211_vif, drv_priv); + } + +-static inline struct ieee80211_vif *rtwvif_to_vif_safe(struct rtw89_vif_link *rtwvif_link) ++static inline struct ieee80211_vif *rtwvif_to_vif_safe(struct rtw89_vif *rtwvif) + { +- return rtwvif_link ? rtwvif_to_vif(rtwvif_link) : NULL; ++ return rtwvif ? rtwvif_to_vif(rtwvif) : NULL; + } + +-static inline struct rtw89_vif_link *vif_to_rtwvif_safe(struct ieee80211_vif *vif) ++static inline ++struct ieee80211_vif *rtwvif_link_to_vif(struct rtw89_vif_link *rtwvif_link) + { +- return vif ? (struct rtw89_vif_link *)vif->drv_priv : NULL; ++ return rtwvif_to_vif(rtwvif_link->rtwvif); + } + +-static inline struct ieee80211_sta *rtwsta_to_sta(struct rtw89_sta_link *rtwsta_link) ++static inline ++struct ieee80211_vif *rtwvif_link_to_vif_safe(struct rtw89_vif_link *rtwvif_link) + { +- void *p = rtwsta_link; ++ return rtwvif_link ? rtwvif_link_to_vif(rtwvif_link) : NULL; ++} ++ ++static inline struct rtw89_vif *vif_to_rtwvif(struct ieee80211_vif *vif) ++{ ++ return (struct rtw89_vif *)vif->drv_priv; ++} ++ ++static inline struct rtw89_vif *vif_to_rtwvif_safe(struct ieee80211_vif *vif) ++{ ++ return vif ? vif_to_rtwvif(vif) : NULL; ++} ++ ++static inline struct ieee80211_sta *rtwsta_to_sta(struct rtw89_sta *rtwsta) ++{ ++ void *p = rtwsta; + + return container_of(p, struct ieee80211_sta, drv_priv); + } + +-static inline struct ieee80211_sta *rtwsta_to_sta_safe(struct rtw89_sta_link *rtwsta_link) ++static inline struct ieee80211_sta *rtwsta_to_sta_safe(struct rtw89_sta *rtwsta) ++{ ++ return rtwsta ? rtwsta_to_sta(rtwsta) : NULL; ++} ++ ++static inline ++struct ieee80211_sta *rtwsta_link_to_sta(struct rtw89_sta_link *rtwsta_link) ++{ ++ return rtwsta_to_sta(rtwsta_link->rtwsta); ++} ++ ++static inline ++struct ieee80211_sta *rtwsta_link_to_sta_safe(struct rtw89_sta_link *rtwsta_link) ++{ ++ return rtwsta_link ? rtwsta_link_to_sta(rtwsta_link) : NULL; ++} ++ ++static inline struct rtw89_sta *sta_to_rtwsta(struct ieee80211_sta *sta) + { +- return rtwsta_link ? rtwsta_to_sta(rtwsta_link) : NULL; ++ return (struct rtw89_sta *)sta->drv_priv; + } + +-static inline struct rtw89_sta_link *sta_to_rtwsta_safe(struct ieee80211_sta *sta) ++static inline struct rtw89_sta *sta_to_rtwsta_safe(struct ieee80211_sta *sta) + { +- return sta ? (struct rtw89_sta_link *)sta->drv_priv : NULL; ++ return sta ? sta_to_rtwsta(sta) : NULL; + } + + static inline struct ieee80211_bss_conf * + __rtw89_vif_rcu_dereference_link(struct rtw89_vif_link *rtwvif_link, bool *nolink) + { +- struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif_link); ++ struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link); + struct ieee80211_bss_conf *bss_conf; + + bss_conf = rcu_dereference(vif->link_conf[rtwvif_link->link_id]); +@@ -6022,7 +6163,7 @@ __rtw89_vif_rcu_dereference_link(struct rtw89_vif_link *rtwvif_link, bool *nolin + \ + bss_conf = __rtw89_vif_rcu_dereference_link(p, &nolink); \ + if (unlikely(nolink) && (assert)) \ +- rtw89_err(p->rtwdev, \ ++ rtw89_err(p->rtwvif->rtwdev, \ + "%s: cannot find exact bss_conf for link_id %u\n",\ + __func__, p->link_id); \ + bss_conf; \ +@@ -6031,7 +6172,7 @@ __rtw89_vif_rcu_dereference_link(struct rtw89_vif_link *rtwvif_link, bool *nolin + static inline struct ieee80211_link_sta * + __rtw89_sta_rcu_dereference_link(struct rtw89_sta_link *rtwsta_link, bool *nolink) + { +- struct ieee80211_sta *sta = rtwsta_to_sta(rtwsta_link); ++ struct ieee80211_sta *sta = rtwsta_link_to_sta(rtwsta_link); + struct ieee80211_link_sta *link_sta; + + link_sta = rcu_dereference(sta->link[rtwsta_link->link_id]); +@@ -6052,7 +6193,7 @@ __rtw89_sta_rcu_dereference_link(struct rtw89_sta_link *rtwsta_link, bool *nolin + \ + link_sta = __rtw89_sta_rcu_dereference_link(p, &nolink); \ + if (unlikely(nolink) && (assert)) \ +- rtw89_err(p->rtwdev, \ ++ rtw89_err(p->rtwsta->rtwdev, \ + "%s: cannot find exact link_sta for link_id %u\n",\ + __func__, p->link_id); \ + link_sta; \ +@@ -6146,7 +6287,7 @@ struct rtw89_addr_cam_entry *rtw89_get_addr_cam_of(struct rtw89_vif_link *rtwvif + struct rtw89_sta_link *rtwsta_link) + { + if (rtwsta_link) { +- struct ieee80211_sta *sta = rtwsta_to_sta(rtwsta_link); ++ struct ieee80211_sta *sta = rtwsta_link_to_sta(rtwsta_link); + + if (rtwvif_link->net_type == RTW89_NET_TYPE_AP_MODE || sta->tdls) + return &rtwsta_link->addr_cam; +@@ -6159,7 +6300,7 @@ struct rtw89_bssid_cam_entry *rtw89_get_bssid_cam_of(struct rtw89_vif_link *rtwv + struct rtw89_sta_link *rtwsta_link) + { + if (rtwsta_link) { +- struct ieee80211_sta *sta = rtwsta_to_sta(rtwsta_link); ++ struct ieee80211_sta *sta = rtwsta_link_to_sta(rtwsta_link); + + if (sta->tdls) + return &rtwsta_link->bssid_cam; +@@ -6223,8 +6364,7 @@ const struct rtw89_chan_rcd *rtw89_chan_rcd_get(struct rtw89_dev *rtwdev, + static inline + const struct rtw89_chan *rtw89_scan_chan_get(struct rtw89_dev *rtwdev) + { +- struct ieee80211_vif *vif = rtwdev->scan_info.scanning_vif; +- struct rtw89_vif_link *rtwvif_link = vif_to_rtwvif_safe(vif); ++ struct rtw89_vif_link *rtwvif_link = rtwdev->scan_info.scanning_vif; + + if (rtwvif_link) + return rtw89_chan_get(rtwdev, rtwvif_link->chanctx_idx); +@@ -6686,13 +6826,21 @@ struct rtw89_dev *rtw89_alloc_ieee80211_hw(struct device *device, + void rtw89_free_ieee80211_hw(struct rtw89_dev *rtwdev); + u8 rtw89_acquire_mac_id(struct rtw89_dev *rtwdev); + void rtw89_release_mac_id(struct rtw89_dev *rtwdev, u8 mac_id); ++void rtw89_init_vif(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, ++ u8 mac_id, u8 port); ++void rtw89_init_sta(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, ++ struct rtw89_sta *rtwsta, u8 mac_id); ++struct rtw89_vif_link *rtw89_vif_set_link(struct rtw89_vif *rtwvif, ++ unsigned int link_id); ++void rtw89_vif_unset_link(struct rtw89_vif *rtwvif, unsigned int link_id); ++struct rtw89_sta_link *rtw89_sta_set_link(struct rtw89_sta *rtwsta, ++ unsigned int link_id); ++void rtw89_sta_unset_link(struct rtw89_sta *rtwsta, unsigned int link_id); + void rtw89_core_set_chip_txpwr(struct rtw89_dev *rtwdev); + void rtw89_get_default_chandef(struct cfg80211_chan_def *chandef); + void rtw89_get_channel_params(const struct cfg80211_chan_def *chandef, + struct rtw89_chan *chan); + int rtw89_set_channel(struct rtw89_dev *rtwdev); +-void rtw89_get_channel(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, +- struct rtw89_chan *chan); + u8 rtw89_core_acquire_bit_map(unsigned long *addr, unsigned long size); + void rtw89_core_release_bit_map(unsigned long *addr, u8 bit); + void rtw89_core_release_all_bits_map(unsigned long *addr, unsigned int nbits); +@@ -6726,12 +6874,12 @@ int rtw89_core_start(struct rtw89_dev *rtwdev); + void rtw89_core_stop(struct rtw89_dev *rtwdev); + void rtw89_core_update_beacon_work(struct work_struct *work); + void rtw89_roc_work(struct work_struct *work); +-void rtw89_roc_start(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link); +-void rtw89_roc_end(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link); ++void rtw89_roc_start(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif); ++void rtw89_roc_end(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif); + void rtw89_core_scan_start(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, + const u8 *mac_addr, bool hw_scan); + void rtw89_core_scan_complete(struct rtw89_dev *rtwdev, +- struct ieee80211_vif *vif, bool hw_scan); ++ struct rtw89_vif_link *rtwvif_link, bool hw_scan); + int rtw89_reg_6ghz_recalc(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, + bool active); + void rtw89_core_update_p2p_ps(struct rtw89_dev *rtwdev, +diff --git a/drivers/net/wireless/realtek/rtw89/debug.c b/drivers/net/wireless/realtek/rtw89/debug.c +index cc7aaf6fa31fc..7391f131229a5 100644 +--- a/drivers/net/wireless/realtek/rtw89/debug.c ++++ b/drivers/net/wireless/realtek/rtw89/debug.c +@@ -3506,7 +3506,9 @@ static ssize_t rtw89_debug_priv_fw_log_manual_set(struct file *filp, + return count; + } + +-static void rtw89_sta_info_get_iter(void *data, struct ieee80211_sta *sta) ++static void rtw89_sta_link_info_get_iter(struct seq_file *m, ++ struct rtw89_dev *rtwdev, ++ struct rtw89_sta_link *rtwsta_link) + { + static const char * const he_gi_str[] = { + [NL80211_RATE_INFO_HE_GI_0_8] = "0.8", +@@ -3518,11 +3520,8 @@ static void rtw89_sta_info_get_iter(void *data, struct ieee80211_sta *sta) + [NL80211_RATE_INFO_EHT_GI_1_6] = "1.6", + [NL80211_RATE_INFO_EHT_GI_3_2] = "3.2", + }; +- struct rtw89_sta_link *rtwsta_link = (struct rtw89_sta_link *)sta->drv_priv; + struct rate_info *rate = &rtwsta_link->ra_report.txrate; + struct ieee80211_rx_status *status = &rtwsta_link->rx_status; +- struct seq_file *m = (struct seq_file *)data; +- struct rtw89_dev *rtwdev = rtwsta_link->rtwdev; + struct rtw89_hal *hal = &rtwdev->hal; + u8 ant_num = hal->ant_diversity ? 2 : rtwdev->chip->rf_path_num; + bool ant_asterisk = hal->tx_path_diversity || hal->ant_diversity; +@@ -3540,7 +3539,7 @@ static void rtw89_sta_info_get_iter(void *data, struct ieee80211_sta *sta) + + rcu_read_unlock(); + +- seq_printf(m, "TX rate [%d]: ", rtwsta_link->mac_id); ++ seq_printf(m, "TX rate [%u, %u]: ", rtwsta_link->mac_id, rtwsta_link->link_id); + + if (rate->flags & RATE_INFO_FLAGS_MCS) + seq_printf(m, "HT MCS-%d%s", rate->mcs, +@@ -3560,11 +3559,11 @@ static void rtw89_sta_info_get_iter(void *data, struct ieee80211_sta *sta) + seq_printf(m, "Legacy %d", rate->legacy); + seq_printf(m, "%s", rtwsta_link->ra_report.might_fallback_legacy ? " FB_G" : ""); + seq_printf(m, " BW:%u", rtw89_rate_info_bw_to_mhz(rate->bw)); +- seq_printf(m, "\t(hw_rate=0x%x)", rtwsta_link->ra_report.hw_rate); +- seq_printf(m, "\t==> agg_wait=%d (%d)\n", rtwsta_link->max_agg_wait, ++ seq_printf(m, " (hw_rate=0x%x)", rtwsta_link->ra_report.hw_rate); ++ seq_printf(m, " ==> agg_wait=%d (%d)\n", rtwsta_link->max_agg_wait, + max_rc_amsdu_len); + +- seq_printf(m, "RX rate [%d]: ", rtwsta_link->mac_id); ++ seq_printf(m, "RX rate [%u, %u]: ", rtwsta_link->mac_id, rtwsta_link->link_id); + + switch (status->encoding) { + case RX_ENC_LEGACY: +@@ -3591,7 +3590,7 @@ static void rtw89_sta_info_get_iter(void *data, struct ieee80211_sta *sta) + break; + } + seq_printf(m, " BW:%u", rtw89_rate_info_bw_to_mhz(status->bw)); +- seq_printf(m, "\t(hw_rate=0x%x)\n", rtwsta_link->rx_hw_rate); ++ seq_printf(m, " (hw_rate=0x%x)\n", rtwsta_link->rx_hw_rate); + + rssi = ewma_rssi_read(&rtwsta_link->avg_rssi); + seq_printf(m, "RSSI: %d dBm (raw=%d, prev=%d) [", +@@ -3620,6 +3619,18 @@ static void rtw89_sta_info_get_iter(void *data, struct ieee80211_sta *sta) + seq_printf(m, "SNR: %u\n", snr); + } + ++static void rtw89_sta_info_get_iter(void *data, struct ieee80211_sta *sta) ++{ ++ struct seq_file *m = (struct seq_file *)data; ++ struct rtw89_sta *rtwsta = sta_to_rtwsta(sta); ++ struct rtw89_dev *rtwdev = rtwsta->rtwdev; ++ struct rtw89_sta_link *rtwsta_link; ++ unsigned int link_id; ++ ++ rtw89_sta_for_each_link(rtwsta, rtwsta_link, link_id) ++ rtw89_sta_link_info_get_iter(m, rtwdev, rtwsta_link); ++} ++ + static void + rtw89_debug_append_rx_rate(struct seq_file *m, struct rtw89_pkt_stat *pkt_stat, + enum rtw89_hw_rate first_rate, int len) +@@ -3746,25 +3757,37 @@ static void rtw89_dump_pkt_offload(struct seq_file *m, struct list_head *pkt_lis + seq_puts(m, "\n"); + } + +-static +-void rtw89_vif_ids_get_iter(void *data, u8 *mac, struct ieee80211_vif *vif) ++static void rtw89_vif_link_ids_get(struct seq_file *m, u8 *mac, ++ struct rtw89_dev *rtwdev, ++ struct rtw89_vif_link *rtwvif_link) + { +- struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv; +- struct rtw89_dev *rtwdev = rtwvif_link->rtwdev; +- struct seq_file *m = (struct seq_file *)data; + struct rtw89_bssid_cam_entry *bssid_cam = &rtwvif_link->bssid_cam; + +- seq_printf(m, "VIF [%d] %pM\n", rtwvif_link->mac_id, rtwvif_link->mac_addr); ++ seq_printf(m, " [%u] %pM\n", rtwvif_link->mac_id, rtwvif_link->mac_addr); ++ seq_printf(m, "\tlink_id=%u\n", rtwvif_link->link_id); + seq_printf(m, "\tbssid_cam_idx=%u\n", bssid_cam->bssid_cam_idx); + rtw89_dump_addr_cam(m, rtwdev, &rtwvif_link->addr_cam); + rtw89_dump_pkt_offload(m, &rtwvif_link->general_pkt_list, + "\tpkt_ofld[GENERAL]: "); + } + +-static void rtw89_dump_ba_cam(struct seq_file *m, struct rtw89_sta_link *rtwsta_link) ++static ++void rtw89_vif_ids_get_iter(void *data, u8 *mac, struct ieee80211_vif *vif) ++{ ++ struct seq_file *m = (struct seq_file *)data; ++ struct rtw89_vif *rtwvif = vif_to_rtwvif(vif); ++ struct rtw89_dev *rtwdev = rtwvif->rtwdev; ++ struct rtw89_vif_link *rtwvif_link; ++ unsigned int link_id; ++ ++ seq_printf(m, "VIF %pM\n", rtwvif->mac_addr); ++ rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id) ++ rtw89_vif_link_ids_get(m, mac, rtwdev, rtwvif_link); ++} ++ ++static void rtw89_dump_ba_cam(struct seq_file *m, struct rtw89_dev *rtwdev, ++ struct rtw89_sta_link *rtwsta_link) + { +- struct rtw89_vif_link *rtwvif_link = rtwsta_link->rtwvif_link; +- struct rtw89_dev *rtwdev = rtwvif_link->rtwdev; + struct rtw89_ba_cam_entry *entry; + bool first = true; + +@@ -3781,24 +3804,36 @@ static void rtw89_dump_ba_cam(struct seq_file *m, struct rtw89_sta_link *rtwsta_ + seq_puts(m, "\n"); + } + +-static void rtw89_sta_ids_get_iter(void *data, struct ieee80211_sta *sta) ++static void rtw89_sta_link_ids_get(struct seq_file *m, ++ struct rtw89_dev *rtwdev, ++ struct rtw89_sta_link *rtwsta_link) + { +- struct rtw89_sta_link *rtwsta_link = (struct rtw89_sta_link *)sta->drv_priv; +- struct rtw89_dev *rtwdev = rtwsta_link->rtwdev; +- struct seq_file *m = (struct seq_file *)data; + struct ieee80211_link_sta *link_sta; + + rcu_read_lock(); + + link_sta = rtw89_sta_rcu_dereference_link(rtwsta_link, true); + +- seq_printf(m, "STA [%d] %pM %s\n", rtwsta_link->mac_id, link_sta->addr, +- sta->tdls ? "(TDLS)" : ""); ++ seq_printf(m, " [%u] %pM\n", rtwsta_link->mac_id, link_sta->addr); + + rcu_read_unlock(); + ++ seq_printf(m, "\tlink_id=%u\n", rtwsta_link->link_id); + rtw89_dump_addr_cam(m, rtwdev, &rtwsta_link->addr_cam); +- rtw89_dump_ba_cam(m, rtwsta_link); ++ rtw89_dump_ba_cam(m, rtwdev, rtwsta_link); ++} ++ ++static void rtw89_sta_ids_get_iter(void *data, struct ieee80211_sta *sta) ++{ ++ struct seq_file *m = (struct seq_file *)data; ++ struct rtw89_sta *rtwsta = sta_to_rtwsta(sta); ++ struct rtw89_dev *rtwdev = rtwsta->rtwdev; ++ struct rtw89_sta_link *rtwsta_link; ++ unsigned int link_id; ++ ++ seq_printf(m, "STA %pM %s\n", sta->addr, sta->tdls ? "(TDLS)" : ""); ++ rtw89_sta_for_each_link(rtwsta, rtwsta_link, link_id) ++ rtw89_sta_link_ids_get(m, rtwdev, rtwsta_link); + } + + static int rtw89_debug_priv_stations_get(struct seq_file *m, void *v) +diff --git a/drivers/net/wireless/realtek/rtw89/fw.c b/drivers/net/wireless/realtek/rtw89/fw.c +index 8e890ebae6134..37f931e887917 100644 +--- a/drivers/net/wireless/realtek/rtw89/fw.c ++++ b/drivers/net/wireless/realtek/rtw89/fw.c +@@ -1909,11 +1909,12 @@ int rtw89_fw_h2c_default_dmac_tbl_v2(struct rtw89_dev *rtwdev, + } + EXPORT_SYMBOL(rtw89_fw_h2c_default_dmac_tbl_v2); + +-int rtw89_fw_h2c_ba_cam(struct rtw89_dev *rtwdev, struct rtw89_sta_link *rtwsta_link, ++int rtw89_fw_h2c_ba_cam(struct rtw89_dev *rtwdev, ++ struct rtw89_vif_link *rtwvif_link, ++ struct rtw89_sta_link *rtwsta_link, + bool valid, struct ieee80211_ampdu_params *params) + { + const struct rtw89_chip_info *chip = rtwdev->chip; +- struct rtw89_vif_link *rtwvif_link = rtwsta_link->rtwvif_link; + struct rtw89_h2c_ba_cam *h2c; + u8 macid = rtwsta_link->mac_id; + u32 len = sizeof(*h2c); +@@ -2043,11 +2044,12 @@ void rtw89_fw_h2c_init_dynamic_ba_cam_v0_ext(struct rtw89_dev *rtwdev) + } + } + +-int rtw89_fw_h2c_ba_cam_v1(struct rtw89_dev *rtwdev, struct rtw89_sta_link *rtwsta_link, ++int rtw89_fw_h2c_ba_cam_v1(struct rtw89_dev *rtwdev, ++ struct rtw89_vif_link *rtwvif_link, ++ struct rtw89_sta_link *rtwsta_link, + bool valid, struct ieee80211_ampdu_params *params) + { + const struct rtw89_chip_info *chip = rtwdev->chip; +- struct rtw89_vif_link *rtwvif_link = rtwsta_link->rtwvif_link; + struct rtw89_h2c_ba_cam_v1 *h2c; + u8 macid = rtwsta_link->mac_id; + u32 len = sizeof(*h2c); +@@ -2293,6 +2295,7 @@ static struct sk_buff *rtw89_sa_query_get(struct rtw89_dev *rtwdev, + static struct sk_buff *rtw89_arp_response_get(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link) + { ++ struct rtw89_vif *rtwvif = rtwvif_link->rtwvif; + u8 sec_hdr_len = rtw89_wow_get_sec_hdr_len(rtwdev); + struct rtw89_wow_param *rtw_wow = &rtwdev->wow; + struct ieee80211_hdr_3addr *hdr; +@@ -2332,7 +2335,7 @@ static struct sk_buff *rtw89_arp_response_get(struct rtw89_dev *rtwdev, + arp_hdr->ar_op = htons(ARPOP_REPLY); + + ether_addr_copy(arp_skb->sender_hw, rtwvif_link->mac_addr); +- arp_skb->sender_ip = rtwvif_link->ip_addr; ++ arp_skb->sender_ip = rtwvif->ip_addr; + + return skb; + } +@@ -2342,7 +2345,7 @@ static int rtw89_fw_h2c_add_general_pkt(struct rtw89_dev *rtwdev, + enum rtw89_fw_pkt_ofld_type type, + u8 *id) + { +- struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif_link); ++ struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link); + struct rtw89_pktofld_info *info; + struct sk_buff *skb; + int ret; +@@ -2415,9 +2418,13 @@ void rtw89_fw_release_general_pkt_list_vif(struct rtw89_dev *rtwdev, + void rtw89_fw_release_general_pkt_list(struct rtw89_dev *rtwdev, bool notify_fw) + { + struct rtw89_vif_link *rtwvif_link; ++ struct rtw89_vif *rtwvif; ++ unsigned int link_id; + +- rtw89_for_each_rtwvif(rtwdev, rtwvif_link) +- rtw89_fw_release_general_pkt_list_vif(rtwdev, rtwvif_link, notify_fw); ++ rtw89_for_each_rtwvif(rtwdev, rtwvif) ++ rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id) ++ rtw89_fw_release_general_pkt_list_vif(rtwdev, rtwvif_link, ++ notify_fw); + } + + #define H2C_GENERAL_PKT_LEN 6 +@@ -2834,7 +2841,7 @@ int rtw89_fw_h2c_assoc_cmac_tbl(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link) + { +- struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif_link); ++ struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link); + const struct rtw89_chip_info *chip = rtwdev->chip; + const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, + rtwvif_link->chanctx_idx); +@@ -2981,7 +2988,7 @@ int rtw89_fw_h2c_assoc_cmac_tbl_g7(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link) + { +- struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif_link); ++ struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link); + const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, rtwvif_link->chanctx_idx); + u8 mac_id = rtwsta_link ? rtwsta_link->mac_id : rtwvif_link->mac_id; + struct rtw89_h2c_cctlinfo_ud_g7 *h2c; +@@ -3105,10 +3112,10 @@ int rtw89_fw_h2c_assoc_cmac_tbl_g7(struct rtw89_dev *rtwdev, + EXPORT_SYMBOL(rtw89_fw_h2c_assoc_cmac_tbl_g7); + + int rtw89_fw_h2c_ampdu_cmac_tbl_g7(struct rtw89_dev *rtwdev, +- struct ieee80211_vif *vif, +- struct ieee80211_sta *sta) ++ struct rtw89_vif_link *rtwvif_link, ++ struct rtw89_sta_link *rtwsta_link) + { +- struct rtw89_sta_link *rtwsta_link = (struct rtw89_sta_link *)sta->drv_priv; ++ struct rtw89_sta *rtwsta = rtwsta_link->rtwsta; + struct rtw89_h2c_cctlinfo_ud_g7 *h2c; + u32 len = sizeof(*h2c); + struct sk_buff *skb; +@@ -3125,11 +3132,11 @@ int rtw89_fw_h2c_ampdu_cmac_tbl_g7(struct rtw89_dev *rtwdev, + skb_put(skb, len); + h2c = (struct rtw89_h2c_cctlinfo_ud_g7 *)skb->data; + +- for_each_set_bit(tid, rtwsta_link->ampdu_map, IEEE80211_NUM_TIDS) { ++ for_each_set_bit(tid, rtwsta->ampdu_map, IEEE80211_NUM_TIDS) { + if (agg_num == 0) +- agg_num = rtwsta_link->ampdu_params[tid].agg_num; ++ agg_num = rtwsta->ampdu_params[tid].agg_num; + else +- agg_num = min(agg_num, rtwsta_link->ampdu_params[tid].agg_num); ++ agg_num = min(agg_num, rtwsta->ampdu_params[tid].agg_num); + } + + if (agg_num <= 0x20) +@@ -3256,7 +3263,7 @@ int rtw89_fw_h2c_update_beacon(struct rtw89_dev *rtwdev, + { + const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, + rtwvif_link->chanctx_idx); +- struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif_link); ++ struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link); + struct rtw89_h2c_bcn_upd *h2c; + struct sk_buff *skb_beacon; + struct ieee80211_hdr *hdr; +@@ -3335,7 +3342,7 @@ int rtw89_fw_h2c_update_beacon_be(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link) + { + const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, rtwvif_link->chanctx_idx); +- struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif_link); ++ struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link); + struct rtw89_h2c_bcn_upd_be *h2c; + struct sk_buff *skb_beacon; + struct ieee80211_hdr *hdr; +@@ -3899,7 +3906,8 @@ int rtw89_fw_h2c_rssi_offload(struct rtw89_dev *rtwdev, + + int rtw89_fw_h2c_tp_offload(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link) + { +- struct rtw89_traffic_stats *stats = &rtwvif_link->stats; ++ struct rtw89_vif *rtwvif = rtwvif_link->rtwvif; ++ struct rtw89_traffic_stats *stats = &rtwvif->stats; + struct rtw89_h2c_ofld *h2c; + u32 len = sizeof(*h2c); + struct sk_buff *skb; +@@ -5030,9 +5038,10 @@ int rtw89_fw_h2c_scan_offload_be(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, + bool wowlan) + { ++ struct rtw89_vif *rtwvif = rtwvif_link->rtwvif; + struct rtw89_hw_scan_info *scan_info = &rtwdev->scan_info; + struct rtw89_wait_info *wait = &rtwdev->mac.fw_ofld_wait; +- struct cfg80211_scan_request *req = rtwvif_link->scan_req; ++ struct cfg80211_scan_request *req = rtwvif->scan_req; + struct rtw89_h2c_scanofld_be_macc_role *macc_role; + struct rtw89_chan *op = &scan_info->op_chan; + struct rtw89_h2c_scanofld_be_opch *opch; +@@ -5935,12 +5944,10 @@ static void rtw89_release_pkt_list(struct rtw89_dev *rtwdev) + } + + static bool rtw89_is_6ghz_wildcard_probe_req(struct rtw89_dev *rtwdev, +- struct rtw89_vif_link *rtwvif_link, ++ struct cfg80211_scan_request *req, + struct rtw89_pktofld_info *info, + enum nl80211_band band, u8 ssid_idx) + { +- struct cfg80211_scan_request *req = rtwvif_link->scan_req; +- + if (band != NL80211_BAND_6GHZ) + return false; + +@@ -5960,7 +5967,9 @@ static int rtw89_append_probe_req_ie(struct rtw89_dev *rtwdev, + struct sk_buff *skb, u8 ssid_idx) + { + struct rtw89_hw_scan_info *scan_info = &rtwdev->scan_info; +- struct ieee80211_scan_ies *ies = rtwvif_link->scan_ies; ++ struct rtw89_vif *rtwvif = rtwvif_link->rtwvif; ++ struct ieee80211_scan_ies *ies = rtwvif->scan_ies; ++ struct cfg80211_scan_request *req = rtwvif->scan_req; + struct rtw89_pktofld_info *info; + struct sk_buff *new; + int ret = 0; +@@ -5985,8 +5994,7 @@ static int rtw89_append_probe_req_ie(struct rtw89_dev *rtwdev, + goto out; + } + +- rtw89_is_6ghz_wildcard_probe_req(rtwdev, rtwvif_link, info, band, +- ssid_idx); ++ rtw89_is_6ghz_wildcard_probe_req(rtwdev, req, info, band, ssid_idx); + + ret = rtw89_fw_h2c_add_pkt_offload(rtwdev, &info->id, new); + if (ret) { +@@ -6005,7 +6013,8 @@ static int rtw89_append_probe_req_ie(struct rtw89_dev *rtwdev, + static int rtw89_hw_scan_update_probe_req(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link) + { +- struct cfg80211_scan_request *req = rtwvif_link->scan_req; ++ struct rtw89_vif *rtwvif = rtwvif_link->rtwvif; ++ struct cfg80211_scan_request *req = rtwvif->scan_req; + struct sk_buff *skb; + u8 num = req->n_ssids, i; + int ret; +@@ -6029,13 +6038,12 @@ static int rtw89_hw_scan_update_probe_req(struct rtw89_dev *rtwdev, + } + + static int rtw89_update_6ghz_rnr_chan(struct rtw89_dev *rtwdev, ++ struct ieee80211_scan_ies *ies, + struct cfg80211_scan_request *req, + struct rtw89_mac_chinfo *ch_info) + { +- struct ieee80211_vif *vif = rtwdev->scan_info.scanning_vif; ++ struct rtw89_vif_link *rtwvif_link = rtwdev->scan_info.scanning_vif; + struct list_head *pkt_list = rtwdev->scan_info.pkt_list; +- struct rtw89_vif_link *rtwvif_link = vif_to_rtwvif_safe(vif); +- struct ieee80211_scan_ies *ies = rtwvif_link->scan_ies; + struct cfg80211_scan_6ghz_params *params; + struct rtw89_pktofld_info *info, *tmp; + struct ieee80211_hdr *hdr; +@@ -6154,9 +6162,10 @@ static void rtw89_hw_scan_add_chan(struct rtw89_dev *rtwdev, int chan_type, + struct rtw89_mac_chinfo *ch_info) + { + struct rtw89_hw_scan_info *scan_info = &rtwdev->scan_info; +- struct ieee80211_vif *vif = rtwdev->scan_info.scanning_vif; +- struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv; +- struct cfg80211_scan_request *req = rtwvif_link->scan_req; ++ struct rtw89_vif_link *rtwvif_link = rtwdev->scan_info.scanning_vif; ++ struct rtw89_vif *rtwvif = rtwvif_link->rtwvif; ++ struct ieee80211_scan_ies *ies = rtwvif->scan_ies; ++ struct cfg80211_scan_request *req = rtwvif->scan_req; + struct rtw89_chan *op = &rtwdev->scan_info.op_chan; + struct rtw89_pktofld_info *info; + u8 band, probe_count = 0; +@@ -6181,7 +6190,7 @@ static void rtw89_hw_scan_add_chan(struct rtw89_dev *rtwdev, int chan_type, + } + } + +- ret = rtw89_update_6ghz_rnr_chan(rtwdev, req, ch_info); ++ ret = rtw89_update_6ghz_rnr_chan(rtwdev, ies, req, ch_info); + if (ret) + rtw89_warn(rtwdev, "RNR fails: %d\n", ret); + +@@ -6271,9 +6280,9 @@ static void rtw89_hw_scan_add_chan_be(struct rtw89_dev *rtwdev, int chan_type, + struct rtw89_mac_chinfo_be *ch_info) + { + struct rtw89_hw_scan_info *scan_info = &rtwdev->scan_info; +- struct ieee80211_vif *vif = rtwdev->scan_info.scanning_vif; +- struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv; +- struct cfg80211_scan_request *req = rtwvif_link->scan_req; ++ struct rtw89_vif_link *rtwvif_link = rtwdev->scan_info.scanning_vif; ++ struct rtw89_vif *rtwvif = rtwvif_link->rtwvif; ++ struct cfg80211_scan_request *req = rtwvif->scan_req; + struct rtw89_pktofld_info *info; + u8 band, probe_count = 0, i; + +@@ -6381,7 +6390,8 @@ int rtw89_pno_scan_add_chan_list_ax(struct rtw89_dev *rtwdev, + int rtw89_hw_scan_add_chan_list_ax(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, bool connected) + { +- struct cfg80211_scan_request *req = rtwvif_link->scan_req; ++ struct rtw89_vif *rtwvif = rtwvif_link->rtwvif; ++ struct cfg80211_scan_request *req = rtwvif->scan_req; + struct rtw89_mac_chinfo *ch_info, *tmp; + struct ieee80211_channel *channel; + struct list_head chan_list; +@@ -6510,7 +6520,8 @@ int rtw89_pno_scan_add_chan_list_be(struct rtw89_dev *rtwdev, + int rtw89_hw_scan_add_chan_list_be(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, bool connected) + { +- struct cfg80211_scan_request *req = rtwvif_link->scan_req; ++ struct rtw89_vif *rtwvif = rtwvif_link->rtwvif; ++ struct cfg80211_scan_request *req = rtwvif->scan_req; + struct rtw89_mac_chinfo_be *ch_info, *tmp; + struct ieee80211_channel *channel; + struct list_head chan_list; +@@ -6582,21 +6593,26 @@ static int rtw89_hw_scan_prehandle(struct rtw89_dev *rtwdev, + return ret; + } + +-void rtw89_hw_scan_start(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif, ++void rtw89_hw_scan_start(struct rtw89_dev *rtwdev, ++ struct rtw89_vif_link *rtwvif_link, + struct ieee80211_scan_request *scan_req) + { +- struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv; + const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; + struct cfg80211_scan_request *req = &scan_req->req; ++ const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, ++ rtwvif_link->chanctx_idx); ++ struct rtw89_vif *rtwvif = rtwvif_link->rtwvif; + u32 rx_fltr = rtwdev->hal.rx_fltr; + u8 mac_addr[ETH_ALEN]; + +- rtw89_get_channel(rtwdev, rtwvif_link, &rtwdev->scan_info.op_chan); +- rtwdev->scan_info.scanning_vif = vif; ++ /* clone op and keep it during scan */ ++ rtwdev->scan_info.op_chan = *chan; ++ ++ rtwdev->scan_info.scanning_vif = rtwvif_link; + rtwdev->scan_info.last_chan_idx = 0; + rtwdev->scan_info.abort = false; +- rtwvif_link->scan_ies = &scan_req->ies; +- rtwvif_link->scan_req = req; ++ rtwvif->scan_ies = &scan_req->ies; ++ rtwvif->scan_req = req; + ieee80211_stop_queues(rtwdev->hw); + rtw89_mac_port_cfg_rx_sync(rtwdev, rtwvif_link, false); + +@@ -6618,33 +6634,36 @@ void rtw89_hw_scan_start(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif, + rtw89_chanctx_pause(rtwdev, RTW89_CHANCTX_PAUSE_REASON_HW_SCAN); + } + +-void rtw89_hw_scan_complete(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif, ++void rtw89_hw_scan_complete(struct rtw89_dev *rtwdev, ++ struct rtw89_vif_link *rtwvif_link, + bool aborted) + { + const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; + struct rtw89_hw_scan_info *scan_info = &rtwdev->scan_info; +- struct rtw89_vif_link *rtwvif_link = vif_to_rtwvif_safe(vif); + struct cfg80211_scan_info info = { + .aborted = aborted, + }; ++ struct rtw89_vif *rtwvif; + +- if (!vif) ++ if (!rtwvif_link) + return; + ++ rtwvif = rtwvif_link->rtwvif; ++ + rtw89_write32_mask(rtwdev, + rtw89_mac_reg_by_idx(rtwdev, mac->rx_fltr, RTW89_MAC_0), + B_AX_RX_FLTR_CFG_MASK, + rtwdev->hal.rx_fltr); + +- rtw89_core_scan_complete(rtwdev, vif, true); ++ rtw89_core_scan_complete(rtwdev, rtwvif_link, true); + ieee80211_scan_completed(rtwdev->hw, &info); + ieee80211_wake_queues(rtwdev->hw); + rtw89_mac_port_cfg_rx_sync(rtwdev, rtwvif_link, true); + rtw89_mac_enable_beacon_for_ap_vifs(rtwdev, true); + + rtw89_release_pkt_list(rtwdev); +- rtwvif_link->scan_req = NULL; +- rtwvif_link->scan_ies = NULL; ++ rtwvif->scan_req = NULL; ++ rtwvif->scan_ies = NULL; + scan_info->last_chan_idx = 0; + scan_info->scanning_vif = NULL; + scan_info->abort = false; +@@ -6652,14 +6671,15 @@ void rtw89_hw_scan_complete(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif, + rtw89_chanctx_proceed(rtwdev); + } + +-void rtw89_hw_scan_abort(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif) ++void rtw89_hw_scan_abort(struct rtw89_dev *rtwdev, ++ struct rtw89_vif_link *rtwvif_link) + { + struct rtw89_hw_scan_info *scan_info = &rtwdev->scan_info; + int ret; + + scan_info->abort = true; + +- ret = rtw89_hw_scan_offload(rtwdev, vif, false); ++ ret = rtw89_hw_scan_offload(rtwdev, rtwvif_link, false); + if (ret) + rtw89_warn(rtwdev, "rtw89_hw_scan_offload failed ret %d\n", ret); + +@@ -6668,32 +6688,35 @@ void rtw89_hw_scan_abort(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif) + * RTW89_SCAN_END_SCAN_NOTIFY, so that ieee80211_stop() can flush scan + * work properly. + */ +- rtw89_hw_scan_complete(rtwdev, vif, true); ++ rtw89_hw_scan_complete(rtwdev, rtwvif_link, true); + } + + static bool rtw89_is_any_vif_connected_or_connecting(struct rtw89_dev *rtwdev) + { + struct rtw89_vif_link *rtwvif_link; +- +- rtw89_for_each_rtwvif(rtwdev, rtwvif_link) { +- /* This variable implies connected or during attempt to connect */ +- if (!is_zero_ether_addr(rtwvif_link->bssid)) +- return true; ++ struct rtw89_vif *rtwvif; ++ unsigned int link_id; ++ ++ rtw89_for_each_rtwvif(rtwdev, rtwvif) { ++ rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id) { ++ /* This variable implies connected or during attempt to connect */ ++ if (!is_zero_ether_addr(rtwvif_link->bssid)) ++ return true; ++ } + } + + return false; + } + +-int rtw89_hw_scan_offload(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif, ++int rtw89_hw_scan_offload(struct rtw89_dev *rtwdev, ++ struct rtw89_vif_link *rtwvif_link, + bool enable) + { + const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; + struct rtw89_scan_option opt = {0}; +- struct rtw89_vif_link *rtwvif_link; + bool connected; + int ret = 0; + +- rtwvif_link = vif ? (struct rtw89_vif_link *)vif->drv_priv : NULL; + if (!rtwvif_link) + return -EINVAL; + +diff --git a/drivers/net/wireless/realtek/rtw89/fw.h b/drivers/net/wireless/realtek/rtw89/fw.h +index 17e952bd70e36..ccbbc43f33fee 100644 +--- a/drivers/net/wireless/realtek/rtw89/fw.h ++++ b/drivers/net/wireless/realtek/rtw89/fw.h +@@ -4419,8 +4419,8 @@ int rtw89_fw_h2c_assoc_cmac_tbl_g7(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link); + int rtw89_fw_h2c_ampdu_cmac_tbl_g7(struct rtw89_dev *rtwdev, +- struct ieee80211_vif *vif, +- struct ieee80211_sta *sta); ++ struct rtw89_vif_link *rtwvif_link, ++ struct rtw89_sta_link *rtwsta_link); + int rtw89_fw_h2c_txtime_cmac_tbl(struct rtw89_dev *rtwdev, + struct rtw89_sta_link *rtwsta_link); + int rtw89_fw_h2c_txpath_cmac_tbl(struct rtw89_dev *rtwdev, +@@ -4514,9 +4514,13 @@ void rtw89_fw_release_general_pkt_list_vif(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, + bool notify_fw); + void rtw89_fw_release_general_pkt_list(struct rtw89_dev *rtwdev, bool notify_fw); +-int rtw89_fw_h2c_ba_cam(struct rtw89_dev *rtwdev, struct rtw89_sta_link *rtwsta_link, ++int rtw89_fw_h2c_ba_cam(struct rtw89_dev *rtwdev, ++ struct rtw89_vif_link *rtwvif_link, ++ struct rtw89_sta_link *rtwsta_link, + bool valid, struct ieee80211_ampdu_params *params); +-int rtw89_fw_h2c_ba_cam_v1(struct rtw89_dev *rtwdev, struct rtw89_sta_link *rtwsta_link, ++int rtw89_fw_h2c_ba_cam_v1(struct rtw89_dev *rtwdev, ++ struct rtw89_vif_link *rtwvif_link, ++ struct rtw89_sta_link *rtwsta_link, + bool valid, struct ieee80211_ampdu_params *params); + void rtw89_fw_h2c_init_dynamic_ba_cam_v0_ext(struct rtw89_dev *rtwdev); + int rtw89_fw_h2c_init_ba_cam_users(struct rtw89_dev *rtwdev, u8 users, +@@ -4535,13 +4539,17 @@ int rtw89_fw_msg_reg(struct rtw89_dev *rtwdev, + struct rtw89_mac_c2h_info *c2h_info); + int rtw89_fw_h2c_fw_log(struct rtw89_dev *rtwdev, bool enable); + void rtw89_fw_st_dbg_dump(struct rtw89_dev *rtwdev); +-void rtw89_hw_scan_start(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif, +- struct ieee80211_scan_request *req); +-void rtw89_hw_scan_complete(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif, ++void rtw89_hw_scan_start(struct rtw89_dev *rtwdev, ++ struct rtw89_vif_link *rtwvif_link, ++ struct ieee80211_scan_request *scan_req); ++void rtw89_hw_scan_complete(struct rtw89_dev *rtwdev, ++ struct rtw89_vif_link *rtwvif_link, + bool aborted); +-int rtw89_hw_scan_offload(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif, ++int rtw89_hw_scan_offload(struct rtw89_dev *rtwdev, ++ struct rtw89_vif_link *rtwvif_link, + bool enable); +-void rtw89_hw_scan_abort(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif); ++void rtw89_hw_scan_abort(struct rtw89_dev *rtwdev, ++ struct rtw89_vif_link *rtwvif_link); + int rtw89_hw_scan_add_chan_list_ax(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, bool connected); + int rtw89_pno_scan_add_chan_list_ax(struct rtw89_dev *rtwdev, +@@ -4662,25 +4670,59 @@ static inline int rtw89_chip_h2c_assoc_cmac_tbl(struct rtw89_dev *rtwdev, + return chip->ops->h2c_assoc_cmac_tbl(rtwdev, rtwvif_link, rtwsta_link); + } + +-static inline int rtw89_chip_h2c_ampdu_cmac_tbl(struct rtw89_dev *rtwdev, +- struct ieee80211_vif *vif, +- struct ieee80211_sta *sta) ++static inline ++int rtw89_chip_h2c_ampdu_link_cmac_tbl(struct rtw89_dev *rtwdev, ++ struct rtw89_vif_link *rtwvif_link, ++ struct rtw89_sta_link *rtwsta_link) + { + const struct rtw89_chip_info *chip = rtwdev->chip; + + if (chip->ops->h2c_ampdu_cmac_tbl) +- return chip->ops->h2c_ampdu_cmac_tbl(rtwdev, vif, sta); ++ return chip->ops->h2c_ampdu_cmac_tbl(rtwdev, rtwvif_link, ++ rtwsta_link); ++ ++ return 0; ++} ++ ++static inline int rtw89_chip_h2c_ampdu_cmac_tbl(struct rtw89_dev *rtwdev, ++ struct rtw89_vif *rtwvif, ++ struct rtw89_sta *rtwsta) ++{ ++ struct rtw89_vif_link *rtwvif_link; ++ struct rtw89_sta_link *rtwsta_link; ++ unsigned int link_id; ++ int ret; ++ ++ rtw89_sta_for_each_link(rtwsta, rtwsta_link, link_id) { ++ rtwvif_link = rtwsta_link->rtwvif_link; ++ ret = rtw89_chip_h2c_ampdu_link_cmac_tbl(rtwdev, rtwvif_link, ++ rtwsta_link); ++ if (ret) ++ return ret; ++ } + + return 0; + } + + static inline +-int rtw89_chip_h2c_ba_cam(struct rtw89_dev *rtwdev, struct rtw89_sta_link *rtwsta_link, ++int rtw89_chip_h2c_ba_cam(struct rtw89_dev *rtwdev, struct rtw89_sta *rtwsta, + bool valid, struct ieee80211_ampdu_params *params) + { + const struct rtw89_chip_info *chip = rtwdev->chip; ++ struct rtw89_vif_link *rtwvif_link; ++ struct rtw89_sta_link *rtwsta_link; ++ unsigned int link_id; ++ int ret; ++ ++ rtw89_sta_for_each_link(rtwsta, rtwsta_link, link_id) { ++ rtwvif_link = rtwsta_link->rtwvif_link; ++ ret = chip->ops->h2c_ba_cam(rtwdev, rtwvif_link, rtwsta_link, ++ valid, params); ++ if (ret) ++ return ret; ++ } + +- return chip->ops->h2c_ba_cam(rtwdev, rtwsta_link, valid, params); ++ return 0; + } + + /* must consider compatibility; don't insert new in the mid */ +diff --git a/drivers/net/wireless/realtek/rtw89/mac.c b/drivers/net/wireless/realtek/rtw89/mac.c +index 28cc4885105a5..4e15d539e3d1c 100644 +--- a/drivers/net/wireless/realtek/rtw89/mac.c ++++ b/drivers/net/wireless/realtek/rtw89/mac.c +@@ -4298,10 +4298,13 @@ static void rtw89_mac_port_cfg_tx_sw_by_nettype(struct rtw89_dev *rtwdev, + void rtw89_mac_enable_beacon_for_ap_vifs(struct rtw89_dev *rtwdev, bool en) + { + struct rtw89_vif_link *rtwvif_link; ++ struct rtw89_vif *rtwvif; ++ unsigned int link_id; + +- rtw89_for_each_rtwvif(rtwdev, rtwvif_link) +- if (rtwvif_link->net_type == RTW89_NET_TYPE_AP_MODE) +- rtw89_mac_port_cfg_tx_sw(rtwdev, rtwvif_link, en); ++ rtw89_for_each_rtwvif(rtwdev, rtwvif) ++ rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id) ++ if (rtwvif_link->net_type == RTW89_NET_TYPE_AP_MODE) ++ rtw89_mac_port_cfg_tx_sw(rtwdev, rtwvif_link, en); + } + + static void rtw89_mac_port_cfg_bcn_intv(struct rtw89_dev *rtwdev, +@@ -4547,13 +4550,17 @@ static void rtw89_mac_port_tsf_resync_all(struct rtw89_dev *rtwdev) + { + struct rtw89_vif_link *src = NULL, *tmp; + u8 offset = 100, vif_aps = 0; ++ struct rtw89_vif *rtwvif; ++ unsigned int link_id; + int n_offset = 1; + +- rtw89_for_each_rtwvif(rtwdev, tmp) { +- if (!src || tmp->net_type == RTW89_NET_TYPE_INFRA) +- src = tmp; +- if (tmp->net_type == RTW89_NET_TYPE_AP_MODE) +- vif_aps++; ++ rtw89_for_each_rtwvif(rtwdev, rtwvif) { ++ rtw89_vif_for_each_link(rtwvif, tmp, link_id) { ++ if (!src || tmp->net_type == RTW89_NET_TYPE_INFRA) ++ src = tmp; ++ if (tmp->net_type == RTW89_NET_TYPE_AP_MODE) ++ vif_aps++; ++ } + } + + if (vif_aps == 0) +@@ -4561,8 +4568,10 @@ static void rtw89_mac_port_tsf_resync_all(struct rtw89_dev *rtwdev) + + offset /= (vif_aps + 1); + +- rtw89_for_each_rtwvif(rtwdev, tmp) +- rtw89_mac_port_tsf_sync_rand(rtwdev, tmp, src, offset, &n_offset); ++ rtw89_for_each_rtwvif(rtwdev, rtwvif) ++ rtw89_vif_for_each_link(rtwvif, tmp, link_id) ++ rtw89_mac_port_tsf_sync_rand(rtwdev, tmp, src, offset, ++ &n_offset); + } + + int rtw89_mac_vif_init(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link) +@@ -4699,7 +4708,7 @@ static void rtw89_mac_check_he_obss_narrow_bw_ru_iter(struct wiphy *wiphy, + void rtw89_mac_set_he_obss_narrow_bw_ru(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link) + { +- struct ieee80211_vif *vif = rtwvif_to_vif_safe(rtwvif_link); ++ struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link); + const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; + struct ieee80211_hw *hw = rtwdev->hw; + struct ieee80211_bss_conf *bss_conf; +@@ -4768,8 +4777,8 @@ rtw89_mac_c2h_scanofld_rsp(struct rtw89_dev *rtwdev, struct sk_buff *skb, + { + const struct rtw89_c2h_scanofld *c2h = + (const struct rtw89_c2h_scanofld *)skb->data; +- struct ieee80211_vif *vif = rtwdev->scan_info.scanning_vif; +- struct rtw89_vif_link *rtwvif_link = vif_to_rtwvif_safe(vif); ++ struct rtw89_vif_link *rtwvif_link = rtwdev->scan_info.scanning_vif; ++ struct rtw89_vif *rtwvif; + struct rtw89_chan new; + u8 reason, status, tx_fail, band, actual_period, expect_period; + u32 last_chan = rtwdev->scan_info.last_chan_idx, report_tsf; +@@ -4780,6 +4789,8 @@ rtw89_mac_c2h_scanofld_rsp(struct rtw89_dev *rtwdev, struct sk_buff *skb, + if (!rtwvif_link) + return; + ++ rtwvif = rtwvif_link->rtwvif; ++ + tx_fail = le32_get_bits(c2h->w5, RTW89_C2H_SCANOFLD_W5_TX_FAIL); + status = le32_get_bits(c2h->w2, RTW89_C2H_SCANOFLD_W2_STATUS); + chan = le32_get_bits(c2h->w2, RTW89_C2H_SCANOFLD_W2_PRI_CH); +@@ -4819,15 +4830,15 @@ rtw89_mac_c2h_scanofld_rsp(struct rtw89_dev *rtwdev, struct sk_buff *skb, + if (rtwdev->scan_info.abort) + return; + +- if (rtwvif_link && rtwvif_link->scan_req && +- last_chan < rtwvif_link->scan_req->n_channels) { +- ret = rtw89_hw_scan_offload(rtwdev, vif, true); ++ if (rtwvif_link && rtwvif->scan_req && ++ last_chan < rtwvif->scan_req->n_channels) { ++ ret = rtw89_hw_scan_offload(rtwdev, rtwvif_link, true); + if (ret) { +- rtw89_hw_scan_abort(rtwdev, vif); ++ rtw89_hw_scan_abort(rtwdev, rtwvif_link); + rtw89_warn(rtwdev, "HW scan failed: %d\n", ret); + } + } else { +- rtw89_hw_scan_complete(rtwdev, vif, false); ++ rtw89_hw_scan_complete(rtwdev, rtwvif_link, false); + } + break; + case RTW89_SCAN_ENTER_OP_NOTIFY: +@@ -4853,7 +4864,8 @@ static void + rtw89_mac_bcn_fltr_rpt(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, + struct sk_buff *skb) + { +- struct ieee80211_vif *vif = rtwvif_to_vif_safe(rtwvif_link); ++ struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link); ++ struct rtw89_vif *rtwvif = rtwvif_link->rtwvif; + enum nl80211_cqm_rssi_threshold_event nl_event; + const struct rtw89_c2h_mac_bcnfltr_rpt *c2h = + (const struct rtw89_c2h_mac_bcnfltr_rpt *)skb->data; +@@ -4874,7 +4886,7 @@ rtw89_mac_bcn_fltr_rpt(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_l + + switch (type) { + case RTW89_BCN_FLTR_BEACON_LOSS: +- if (!rtwdev->scanning && !rtwvif_link->offchan) ++ if (!rtwdev->scanning && !rtwvif->offchan) + ieee80211_connection_loss(vif); + else + rtw89_fw_h2c_set_bcn_fltr_cfg(rtwdev, rtwvif_link, true); +@@ -4902,9 +4914,12 @@ rtw89_mac_c2h_bcn_fltr_rpt(struct rtw89_dev *rtwdev, struct sk_buff *c2h, + u32 len) + { + struct rtw89_vif_link *rtwvif_link; ++ struct rtw89_vif *rtwvif; ++ unsigned int link_id; + +- rtw89_for_each_rtwvif(rtwdev, rtwvif_link) +- rtw89_mac_bcn_fltr_rpt(rtwdev, rtwvif_link, c2h); ++ rtw89_for_each_rtwvif(rtwdev, rtwvif) ++ rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id) ++ rtw89_mac_bcn_fltr_rpt(rtwdev, rtwvif_link, c2h); + } + + static void +@@ -6112,10 +6127,21 @@ void rtw89_mac_bf_disassoc(struct rtw89_dev *rtwdev, + void rtw89_mac_bf_set_gid_table(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif, + struct ieee80211_bss_conf *conf) + { +- struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv; +- u8 mac_idx = rtwvif_link->mac_idx; ++ struct rtw89_vif *rtwvif = vif_to_rtwvif(vif); ++ struct rtw89_vif_link *rtwvif_link; ++ u8 mac_idx; + __le32 *p; + ++ rtwvif_link = rtwvif->links[conf->link_id]; ++ if (unlikely(!rtwvif_link)) { ++ rtw89_err(rtwdev, ++ "%s: rtwvif link (link_id %u) is not active\n", ++ __func__, conf->link_id); ++ return; ++ } ++ ++ mac_idx = rtwvif_link->mac_idx; ++ + rtw89_debug(rtwdev, RTW89_DBG_BF, "update bf GID table\n"); + + p = (__le32 *)conf->mu_group.membership; +@@ -6146,20 +6172,30 @@ struct rtw89_mac_bf_monitor_iter_data { + static + void rtw89_mac_bf_monitor_calc_iter(void *data, struct ieee80211_sta *sta) + { +- struct rtw89_sta_link *rtwsta_link = (struct rtw89_sta_link *)sta->drv_priv; + struct rtw89_mac_bf_monitor_iter_data *iter_data = + (struct rtw89_mac_bf_monitor_iter_data *)data; + struct rtw89_sta_link *down_rtwsta_link = iter_data->down_rtwsta_link; ++ struct rtw89_sta *rtwsta = sta_to_rtwsta(sta); + struct ieee80211_link_sta *link_sta; ++ struct rtw89_sta_link *rtwsta_link; ++ bool has_beamformer_cap = false; + int *count = &iter_data->count; +- +- if (down_rtwsta_link == rtwsta_link) +- return; ++ unsigned int link_id; + + rcu_read_lock(); + +- link_sta = rtw89_sta_rcu_dereference_link(rtwsta_link, false); +- if (rtw89_sta_has_beamformer_cap(link_sta)) ++ rtw89_sta_for_each_link(rtwsta, rtwsta_link, link_id) { ++ if (rtwsta_link == down_rtwsta_link) ++ continue; ++ ++ link_sta = rtw89_sta_rcu_dereference_link(rtwsta_link, false); ++ if (rtw89_sta_has_beamformer_cap(link_sta)) { ++ has_beamformer_cap = true; ++ break; ++ } ++ } ++ ++ if (has_beamformer_cap) + (*count)++; + + rcu_read_unlock(); +@@ -6191,7 +6227,9 @@ void _rtw89_mac_bf_monitor_track(struct rtw89_dev *rtwdev) + struct rtw89_vif_link *rtwvif_link; + bool en = stats->tx_tfc_lv <= stats->rx_tfc_lv; + bool old = test_bit(RTW89_FLAG_BFEE_EN, rtwdev->flags); ++ struct rtw89_vif *rtwvif; + bool keep_timer = true; ++ unsigned int link_id; + bool old_keep_timer; + + old_keep_timer = test_bit(RTW89_FLAG_BFEE_TIMER_KEEP, rtwdev->flags); +@@ -6200,16 +6238,18 @@ void _rtw89_mac_bf_monitor_track(struct rtw89_dev *rtwdev) + keep_timer = false; + + if (keep_timer != old_keep_timer) { +- rtw89_for_each_rtwvif(rtwdev, rtwvif_link) +- rtw89_mac_bfee_standby_timer(rtwdev, rtwvif_link->mac_idx, +- keep_timer); ++ rtw89_for_each_rtwvif(rtwdev, rtwvif) ++ rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id) ++ rtw89_mac_bfee_standby_timer(rtwdev, rtwvif_link->mac_idx, ++ keep_timer); + } + + if (en == old) + return; + +- rtw89_for_each_rtwvif(rtwdev, rtwvif_link) +- rtw89_mac_bfee_ctrl(rtwdev, rtwvif_link->mac_idx, en); ++ rtw89_for_each_rtwvif(rtwdev, rtwvif) ++ rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id) ++ rtw89_mac_bfee_ctrl(rtwdev, rtwvif_link->mac_idx, en); + } + + static int +@@ -6393,7 +6433,9 @@ int rtw89_mac_read_xtal_si_ax(struct rtw89_dev *rtwdev, u8 offset, u8 *val) + } + + static +-void rtw89_mac_pkt_drop_sta(struct rtw89_dev *rtwdev, struct rtw89_sta_link *rtwsta_link) ++void rtw89_mac_pkt_drop_sta(struct rtw89_dev *rtwdev, ++ struct rtw89_vif_link *rtwvif_link, ++ struct rtw89_sta_link *rtwsta_link) + { + static const enum rtw89_pkt_drop_sel sels[] = { + RTW89_PKT_DROP_SEL_MACID_BE_ONCE, +@@ -6401,7 +6443,6 @@ void rtw89_mac_pkt_drop_sta(struct rtw89_dev *rtwdev, struct rtw89_sta_link *rtw + RTW89_PKT_DROP_SEL_MACID_VI_ONCE, + RTW89_PKT_DROP_SEL_MACID_VO_ONCE, + }; +- struct rtw89_vif_link *rtwvif_link = rtwsta_link->rtwvif_link; + struct rtw89_pkt_drop_params params = {0}; + int i; + +@@ -6419,22 +6460,28 @@ void rtw89_mac_pkt_drop_sta(struct rtw89_dev *rtwdev, struct rtw89_sta_link *rtw + + static void rtw89_mac_pkt_drop_vif_iter(void *data, struct ieee80211_sta *sta) + { +- struct rtw89_sta_link *rtwsta_link = (struct rtw89_sta_link *)sta->drv_priv; +- struct rtw89_vif_link *rtwvif_link = rtwsta_link->rtwvif_link; +- struct rtw89_dev *rtwdev = rtwvif_link->rtwdev; +- struct rtw89_vif_link *target = data; ++ struct rtw89_sta *rtwsta = sta_to_rtwsta(sta); ++ struct rtw89_vif *rtwvif = rtwsta->rtwvif; ++ struct rtw89_dev *rtwdev = rtwsta->rtwdev; ++ struct rtw89_vif_link *rtwvif_link; ++ struct rtw89_sta_link *rtwsta_link; ++ struct rtw89_vif *target = data; ++ unsigned int link_id; + +- if (rtwvif_link != target) ++ if (rtwvif != target) + return; + +- rtw89_mac_pkt_drop_sta(rtwdev, rtwsta_link); ++ rtw89_sta_for_each_link(rtwsta, rtwsta_link, link_id) { ++ rtwvif_link = rtwsta_link->rtwvif_link; ++ rtw89_mac_pkt_drop_sta(rtwdev, rtwvif_link, rtwsta_link); ++ } + } + +-void rtw89_mac_pkt_drop_vif(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link) ++void rtw89_mac_pkt_drop_vif(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif) + { + ieee80211_iterate_stations_atomic(rtwdev->hw, + rtw89_mac_pkt_drop_vif_iter, +- rtwvif_link); ++ rtwvif); + } + + int rtw89_mac_ptk_drop_by_band_and_wait(struct rtw89_dev *rtwdev, +diff --git a/drivers/net/wireless/realtek/rtw89/mac.h b/drivers/net/wireless/realtek/rtw89/mac.h +index b781b823496f6..0c269961a5731 100644 +--- a/drivers/net/wireless/realtek/rtw89/mac.h ++++ b/drivers/net/wireless/realtek/rtw89/mac.h +@@ -1466,7 +1466,7 @@ int rtw89_mac_read_xtal_si(struct rtw89_dev *rtwdev, u8 offset, u8 *val) + return mac->read_xtal_si(rtwdev, offset, val); + } + +-void rtw89_mac_pkt_drop_vif(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link); ++void rtw89_mac_pkt_drop_vif(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif); + int rtw89_mac_resize_ple_rx_quota(struct rtw89_dev *rtwdev, bool wow); + int rtw89_mac_ptk_drop_by_band_and_wait(struct rtw89_dev *rtwdev, + enum rtw89_mac_idx band); +diff --git a/drivers/net/wireless/realtek/rtw89/mac80211.c b/drivers/net/wireless/realtek/rtw89/mac80211.c +index fc05ad1b799bf..44ba4dc181b5b 100644 +--- a/drivers/net/wireless/realtek/rtw89/mac80211.c ++++ b/drivers/net/wireless/realtek/rtw89/mac80211.c +@@ -23,17 +23,16 @@ static void rtw89_ops_tx(struct ieee80211_hw *hw, + struct rtw89_dev *rtwdev = hw->priv; + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); + struct ieee80211_vif *vif = info->control.vif; +- struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv; ++ struct rtw89_vif *rtwvif = vif_to_rtwvif(vif); + struct ieee80211_sta *sta = control->sta; + u32 flags = IEEE80211_SKB_CB(skb)->flags; + int ret, qsel; + +- if (rtwvif_link->offchan && !(flags & IEEE80211_TX_CTL_TX_OFFCHAN) && sta) { +- struct rtw89_sta_link *rtwsta_link = +- (struct rtw89_sta_link *)sta->drv_priv; ++ if (rtwvif->offchan && !(flags & IEEE80211_TX_CTL_TX_OFFCHAN) && sta) { ++ struct rtw89_sta *rtwsta = sta_to_rtwsta(sta); + + rtw89_debug(rtwdev, RTW89_DBG_TXRX, "ops_tx during offchan\n"); +- skb_queue_tail(&rtwsta_link->roc_queue, skb); ++ skb_queue_tail(&rtwsta->roc_queue, skb); + return; + } + +@@ -158,7 +157,8 @@ static int rtw89_ops_add_interface(struct ieee80211_hw *hw, + struct ieee80211_vif *vif) + { + struct rtw89_dev *rtwdev = hw->priv; +- struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv; ++ struct rtw89_vif *rtwvif = vif_to_rtwvif(vif); ++ struct rtw89_vif_link *rtwvif_link; + u8 mac_id, port; + int ret = 0; + +@@ -173,13 +173,6 @@ static int rtw89_ops_add_interface(struct ieee80211_hw *hw, + vif->driver_flags |= IEEE80211_VIF_BEACON_FILTER | + IEEE80211_VIF_SUPPORTS_CQM_RSSI; + +- rtwvif_link->rtwdev = rtwdev; +- rtwvif_link->roc.state = RTW89_ROC_IDLE; +- rtwvif_link->offchan = false; +- INIT_DELAYED_WORK(&rtwvif_link->roc.roc_work, rtw89_roc_work); +- +- rtw89_traffic_stats_init(rtwdev, &rtwvif_link->stats); +- + mac_id = rtw89_acquire_mac_id(rtwdev); + if (mac_id == RTW89_MAX_MAC_ID_NUM) { + ret = -ENOSPC; +@@ -192,27 +185,40 @@ static int rtw89_ops_add_interface(struct ieee80211_hw *hw, + goto release_macid; + } + +- rtwvif_link->mac_idx = RTW89_MAC_0; +- rtwvif_link->phy_idx = RTW89_PHY_0; +- rtwvif_link->mac_id = mac_id; +- rtwvif_link->port = port; ++ rtw89_init_vif(rtwdev, rtwvif, mac_id, port); + + rtw89_core_txq_init(rtwdev, vif->txq); + +- if (!rtw89_rtwvif_in_list(rtwdev, rtwvif_link)) +- list_add_tail(&rtwvif_link->list, &rtwdev->rtwvifs_list); ++ if (!rtw89_rtwvif_in_list(rtwdev, rtwvif)) ++ list_add_tail(&rtwvif->list, &rtwdev->rtwvifs_list); ++ ++ ether_addr_copy(rtwvif->mac_addr, vif->addr); ++ ++ rtwvif->offchan = false; ++ rtwvif->roc.state = RTW89_ROC_IDLE; ++ INIT_DELAYED_WORK(&rtwvif->roc.roc_work, rtw89_roc_work); ++ ++ rtw89_traffic_stats_init(rtwdev, &rtwvif->stats); ++ ++ rtwvif_link = rtw89_vif_set_link(rtwvif, 0); ++ if (!rtwvif_link) { ++ ret = -EINVAL; ++ goto release_port; ++ } + + ret = __rtw89_ops_add_iface_link(rtwdev, rtwvif_link); + if (ret) +- goto release_port; ++ goto unset_link; + + rtw89_recalc_lps(rtwdev); + + mutex_unlock(&rtwdev->mutex); + return 0; + ++unset_link: ++ rtw89_vif_unset_link(rtwvif, 0); + release_port: +- list_del_init(&rtwvif_link->list); ++ list_del_init(&rtwvif->list); + rtw89_core_release_bit_map(rtwdev->hw_port, port); + release_macid: + rtw89_release_mac_id(rtwdev, mac_id); +@@ -226,20 +232,35 @@ static void rtw89_ops_remove_interface(struct ieee80211_hw *hw, + struct ieee80211_vif *vif) + { + struct rtw89_dev *rtwdev = hw->priv; +- struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv; ++ struct rtw89_vif *rtwvif = vif_to_rtwvif(vif); ++ u8 macid = rtw89_vif_get_main_macid(rtwvif); ++ u8 port = rtw89_vif_get_main_port(rtwvif); ++ struct rtw89_vif_link *rtwvif_link; + + rtw89_debug(rtwdev, RTW89_DBG_STATE, "remove vif %pM type %d p2p %d\n", + vif->addr, vif->type, vif->p2p); + +- cancel_delayed_work_sync(&rtwvif_link->roc.roc_work); ++ cancel_delayed_work_sync(&rtwvif->roc.roc_work); + + mutex_lock(&rtwdev->mutex); + ++ rtwvif_link = rtwvif->links[0]; ++ if (unlikely(!rtwvif_link)) { ++ rtw89_err(rtwdev, ++ "%s: rtwvif link (link_id %u) is not active\n", ++ __func__, 0); ++ goto bottom; ++ } ++ + __rtw89_ops_remove_iface_link(rtwdev, rtwvif_link); + +- rtw89_core_release_bit_map(rtwdev->hw_port, rtwvif_link->port); +- rtw89_release_mac_id(rtwdev, rtwvif_link->mac_id); +- list_del_init(&rtwvif_link->list); ++ rtw89_vif_unset_link(rtwvif, 0); ++ ++bottom: ++ list_del_init(&rtwvif->list); ++ rtw89_core_release_bit_map(rtwdev->hw_port, port); ++ rtw89_release_mac_id(rtwdev, macid); ++ + rtw89_recalc_lps(rtwdev); + rtw89_enter_ips_by_hwflags(rtwdev); + +@@ -460,8 +481,10 @@ static int __rtw89_ops_sta_add(struct rtw89_dev *rtwdev, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta) + { +- struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv; +- struct rtw89_sta_link *rtwsta_link = (struct rtw89_sta_link *)sta->drv_priv; ++ struct rtw89_vif *rtwvif = vif_to_rtwvif(vif); ++ struct rtw89_sta *rtwsta = sta_to_rtwsta(sta); ++ struct rtw89_vif_link *rtwvif_link; ++ struct rtw89_sta_link *rtwsta_link; + bool acquire_macid = false; + u8 macid; + int ret; +@@ -469,7 +492,7 @@ static int __rtw89_ops_sta_add(struct rtw89_dev *rtwdev, + + if (vif->type == NL80211_IFTYPE_STATION && !sta->tdls) { + /* for station mode, assign the mac_id from itself */ +- macid = rtwvif_link->mac_id; ++ macid = rtw89_vif_get_main_macid(rtwvif); + } else { + macid = rtw89_acquire_mac_id(rtwdev); + if (macid == RTW89_MAX_MAC_ID_NUM) +@@ -478,24 +501,32 @@ static int __rtw89_ops_sta_add(struct rtw89_dev *rtwdev, + acquire_macid = true; + } + +- rtwsta_link->rtwdev = rtwdev; +- rtwsta_link->rtwvif_link = rtwvif_link; +- rtwsta_link->mac_id = macid; ++ rtw89_init_sta(rtwdev, rtwvif, rtwsta, macid); + + for (i = 0; i < ARRAY_SIZE(sta->txq); i++) + rtw89_core_txq_init(rtwdev, sta->txq[i]); + +- skb_queue_head_init(&rtwsta_link->roc_queue); ++ skb_queue_head_init(&rtwsta->roc_queue); ++ ++ rtwsta_link = rtw89_sta_set_link(rtwsta, sta->deflink.link_id); ++ if (!rtwsta_link) { ++ ret = -EINVAL; ++ goto err; ++ } ++ ++ rtwvif_link = rtwsta_link->rtwvif_link; + + ret = rtw89_core_sta_link_add(rtwdev, rtwvif_link, rtwsta_link); + if (ret) +- goto err; ++ goto unset_link; + + if (vif->type == NL80211_IFTYPE_AP || sta->tdls) + rtw89_queue_chanctx_change(rtwdev, RTW89_CHANCTX_REMOTE_STA_CHANGE); + + return 0; + ++unset_link: ++ rtw89_sta_unset_link(rtwsta, sta->deflink.link_id); + err: + if (acquire_macid) + rtw89_release_mac_id(rtwdev, macid); +@@ -508,20 +539,27 @@ static int __rtw89_ops_sta_assoc(struct rtw89_dev *rtwdev, + struct ieee80211_sta *sta, + bool station_mode) + { +- struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv; +- struct rtw89_sta_link *rtwsta_link = (struct rtw89_sta_link *)sta->drv_priv; ++ struct rtw89_vif *rtwvif = vif_to_rtwvif(vif); ++ struct rtw89_sta *rtwsta = sta_to_rtwsta(sta); ++ struct rtw89_vif_link *rtwvif_link; ++ struct rtw89_sta_link *rtwsta_link; ++ unsigned int link_id; + int ret; + +- if (station_mode) +- rtw89_vif_type_mapping(rtwvif_link, true); ++ rtw89_sta_for_each_link(rtwsta, rtwsta_link, link_id) { ++ rtwvif_link = rtwsta_link->rtwvif_link; + +- ret = rtw89_core_sta_link_assoc(rtwdev, rtwvif_link, rtwsta_link); +- if (ret) +- return ret; ++ if (station_mode) ++ rtw89_vif_type_mapping(rtwvif_link, true); ++ ++ ret = rtw89_core_sta_link_assoc(rtwdev, rtwvif_link, rtwsta_link); ++ if (ret) ++ return ret; ++ } + + rtwdev->total_sta_assoc++; + if (sta->tdls) +- rtwvif_link->tdls_peer++; ++ rtwvif->tdls_peer++; + + return 0; + } +@@ -530,19 +568,25 @@ static int __rtw89_ops_sta_disassoc(struct rtw89_dev *rtwdev, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta) + { +- struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv; +- struct rtw89_sta_link *rtwsta_link = (struct rtw89_sta_link *)sta->drv_priv; ++ struct rtw89_vif *rtwvif = vif_to_rtwvif(vif); ++ struct rtw89_sta *rtwsta = sta_to_rtwsta(sta); ++ struct rtw89_vif_link *rtwvif_link; ++ struct rtw89_sta_link *rtwsta_link; ++ unsigned int link_id; + int ret; + +- ret = rtw89_core_sta_link_disassoc(rtwdev, rtwvif_link, rtwsta_link); +- if (ret) +- return ret; ++ rtw89_sta_for_each_link(rtwsta, rtwsta_link, link_id) { ++ rtwvif_link = rtwsta_link->rtwvif_link; ++ ret = rtw89_core_sta_link_disassoc(rtwdev, rtwvif_link, rtwsta_link); ++ if (ret) ++ return ret; ++ } + +- rtwsta_link->disassoc = true; ++ rtwsta->disassoc = true; + + rtwdev->total_sta_assoc--; + if (sta->tdls) +- rtwvif_link->tdls_peer--; ++ rtwvif->tdls_peer--; + + return 0; + } +@@ -551,17 +595,22 @@ static int __rtw89_ops_sta_disconnect(struct rtw89_dev *rtwdev, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta) + { +- struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv; +- struct rtw89_sta_link *rtwsta_link = (struct rtw89_sta_link *)sta->drv_priv; ++ struct rtw89_sta *rtwsta = sta_to_rtwsta(sta); ++ struct rtw89_vif_link *rtwvif_link; ++ struct rtw89_sta_link *rtwsta_link; ++ unsigned int link_id; + int ret; + + rtw89_core_free_sta_pending_ba(rtwdev, sta); + rtw89_core_free_sta_pending_forbid_ba(rtwdev, sta); + rtw89_core_free_sta_pending_roc_tx(rtwdev, sta); + +- ret = rtw89_core_sta_link_disconnect(rtwdev, rtwvif_link, rtwsta_link); +- if (ret) +- return ret; ++ rtw89_sta_for_each_link(rtwsta, rtwsta_link, link_id) { ++ rtwvif_link = rtwsta_link->rtwvif_link; ++ ret = rtw89_core_sta_link_disconnect(rtwdev, rtwvif_link, rtwsta_link); ++ if (ret) ++ return ret; ++ } + + return 0; + } +@@ -570,14 +619,21 @@ static int __rtw89_ops_sta_remove(struct rtw89_dev *rtwdev, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta) + { +- struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv; +- struct rtw89_sta_link *rtwsta_link = (struct rtw89_sta_link *)sta->drv_priv; +- u8 macid = rtwsta_link->mac_id; ++ struct rtw89_sta *rtwsta = sta_to_rtwsta(sta); ++ u8 macid = rtw89_sta_get_main_macid(rtwsta); ++ struct rtw89_vif_link *rtwvif_link; ++ struct rtw89_sta_link *rtwsta_link; ++ unsigned int link_id; + int ret; + +- ret = rtw89_core_sta_link_remove(rtwdev, rtwvif_link, rtwsta_link); +- if (ret) +- return ret; ++ rtw89_sta_for_each_link(rtwsta, rtwsta_link, link_id) { ++ rtwvif_link = rtwsta_link->rtwvif_link; ++ ret = rtw89_core_sta_link_remove(rtwdev, rtwvif_link, rtwsta_link); ++ if (ret) ++ return ret; ++ ++ rtw89_sta_unset_link(rtwsta, link_id); ++ } + + if (vif->type == NL80211_IFTYPE_AP || sta->tdls) { + rtw89_release_mac_id(rtwdev, macid); +@@ -613,11 +669,22 @@ static void __rtw89_ops_bss_link_assoc(struct rtw89_dev *rtwdev, + rtw89_mac_set_he_obss_narrow_bw_ru(rtwdev, rtwvif_link); + } + ++static void __rtw89_ops_bss_assoc(struct rtw89_dev *rtwdev, ++ struct ieee80211_vif *vif) ++{ ++ struct rtw89_vif *rtwvif = vif_to_rtwvif(vif); ++ struct rtw89_vif_link *rtwvif_link; ++ unsigned int link_id; ++ ++ rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id) ++ __rtw89_ops_bss_link_assoc(rtwdev, rtwvif_link); ++} ++ + static void rtw89_ops_vif_cfg_changed(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, u64 changed) + { + struct rtw89_dev *rtwdev = hw->priv; +- struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv; ++ struct rtw89_vif *rtwvif = vif_to_rtwvif(vif); + + mutex_lock(&rtwdev->mutex); + rtw89_leave_ps_mode(rtwdev); +@@ -625,7 +692,7 @@ static void rtw89_ops_vif_cfg_changed(struct ieee80211_hw *hw, + if (changed & BSS_CHANGED_ASSOC) { + if (vif->cfg.assoc) { + rtw89_station_mode_sta_assoc(rtwdev, vif); +- __rtw89_ops_bss_link_assoc(rtwdev, rtwvif_link); ++ __rtw89_ops_bss_assoc(rtwdev, vif); + + rtw89_queue_chanctx_work(rtwdev); + } else { +@@ -641,7 +708,7 @@ static void rtw89_ops_vif_cfg_changed(struct ieee80211_hw *hw, + rtw89_recalc_lps(rtwdev); + + if (changed & BSS_CHANGED_ARP_FILTER) +- rtwvif_link->ip_addr = vif->cfg.arp_addr_list[0]; ++ rtwvif->ip_addr = vif->cfg.arp_addr_list[0]; + + mutex_unlock(&rtwdev->mutex); + } +@@ -652,11 +719,20 @@ static void rtw89_ops_link_info_changed(struct ieee80211_hw *hw, + u64 changed) + { + struct rtw89_dev *rtwdev = hw->priv; +- struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv; ++ struct rtw89_vif *rtwvif = vif_to_rtwvif(vif); ++ struct rtw89_vif_link *rtwvif_link; + + mutex_lock(&rtwdev->mutex); + rtw89_leave_ps_mode(rtwdev); + ++ rtwvif_link = rtwvif->links[conf->link_id]; ++ if (unlikely(!rtwvif_link)) { ++ rtw89_err(rtwdev, ++ "%s: rtwvif link (link_id %u) is not active\n", ++ __func__, conf->link_id); ++ goto out; ++ } ++ + if (changed & BSS_CHANGED_BSSID) { + ether_addr_copy(rtwvif_link->bssid, conf->bssid); + rtw89_cam_bssid_changed(rtwdev, rtwvif_link); +@@ -685,6 +761,7 @@ static void rtw89_ops_link_info_changed(struct ieee80211_hw *hw, + if (changed & BSS_CHANGED_TPE) + rtw89_reg_6ghz_recalc(rtwdev, rtwvif_link, true); + ++out: + mutex_unlock(&rtwdev->mutex); + } + +@@ -693,11 +770,20 @@ static int rtw89_ops_start_ap(struct ieee80211_hw *hw, + struct ieee80211_bss_conf *link_conf) + { + struct rtw89_dev *rtwdev = hw->priv; +- struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv; ++ struct rtw89_vif *rtwvif = vif_to_rtwvif(vif); ++ struct rtw89_vif_link *rtwvif_link; + const struct rtw89_chan *chan; + + mutex_lock(&rtwdev->mutex); + ++ rtwvif_link = rtwvif->links[link_conf->link_id]; ++ if (unlikely(!rtwvif_link)) { ++ rtw89_err(rtwdev, ++ "%s: rtwvif link (link_id %u) is not active\n", ++ __func__, link_conf->link_id); ++ goto out; ++ } ++ + chan = rtw89_chan_get(rtwdev, rtwvif_link->chanctx_idx); + if (chan->band_type == RTW89_BAND_6G) { + mutex_unlock(&rtwdev->mutex); +@@ -717,6 +803,8 @@ static int rtw89_ops_start_ap(struct ieee80211_hw *hw, + rtw89_chip_rfk_channel(rtwdev, rtwvif_link); + + rtw89_queue_chanctx_work(rtwdev); ++ ++out: + mutex_unlock(&rtwdev->mutex); + + return 0; +@@ -727,12 +815,24 @@ void rtw89_ops_stop_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + struct ieee80211_bss_conf *link_conf) + { + struct rtw89_dev *rtwdev = hw->priv; +- struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv; ++ struct rtw89_vif *rtwvif = vif_to_rtwvif(vif); ++ struct rtw89_vif_link *rtwvif_link; + + mutex_lock(&rtwdev->mutex); ++ ++ rtwvif_link = rtwvif->links[link_conf->link_id]; ++ if (unlikely(!rtwvif_link)) { ++ rtw89_err(rtwdev, ++ "%s: rtwvif link (link_id %u) is not active\n", ++ __func__, link_conf->link_id); ++ goto out; ++ } ++ + rtw89_mac_stop_ap(rtwdev, rtwvif_link); + rtw89_chip_h2c_assoc_cmac_tbl(rtwdev, rtwvif_link, NULL); + rtw89_fw_h2c_join_info(rtwdev, rtwvif_link, NULL, true); ++ ++out: + mutex_unlock(&rtwdev->mutex); + } + +@@ -740,10 +840,13 @@ static int rtw89_ops_set_tim(struct ieee80211_hw *hw, struct ieee80211_sta *sta, + bool set) + { + struct rtw89_dev *rtwdev = hw->priv; +- struct rtw89_sta_link *rtwsta_link = (struct rtw89_sta_link *)sta->drv_priv; +- struct rtw89_vif_link *rtwvif_link = rtwsta_link->rtwvif_link; ++ struct rtw89_sta *rtwsta = sta_to_rtwsta(sta); ++ struct rtw89_vif *rtwvif = rtwsta->rtwvif; ++ struct rtw89_vif_link *rtwvif_link; ++ unsigned int link_id; + +- ieee80211_queue_work(rtwdev->hw, &rtwvif_link->update_beacon_work); ++ rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id) ++ ieee80211_queue_work(rtwdev->hw, &rtwvif_link->update_beacon_work); + + return 0; + } +@@ -754,15 +857,29 @@ static int rtw89_ops_conf_tx(struct ieee80211_hw *hw, + const struct ieee80211_tx_queue_params *params) + { + struct rtw89_dev *rtwdev = hw->priv; +- struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv; ++ struct rtw89_vif *rtwvif = vif_to_rtwvif(vif); ++ struct rtw89_vif_link *rtwvif_link; ++ int ret = 0; + + mutex_lock(&rtwdev->mutex); + rtw89_leave_ps_mode(rtwdev); ++ ++ rtwvif_link = rtwvif->links[link_id]; ++ if (unlikely(!rtwvif_link)) { ++ rtw89_err(rtwdev, ++ "%s: rtwvif link (link_id %u) is not active\n", ++ __func__, link_id); ++ ret = -ENOLINK; ++ goto out; ++ } ++ + rtwvif_link->tx_params[ac] = *params; + __rtw89_conf_tx(rtwdev, rtwvif_link, ac); ++ ++out: + mutex_unlock(&rtwdev->mutex); + +- return 0; ++ return ret; + } + + static int __rtw89_ops_sta_state(struct ieee80211_hw *hw, +@@ -860,7 +977,8 @@ static int rtw89_ops_ampdu_action(struct ieee80211_hw *hw, + { + struct rtw89_dev *rtwdev = hw->priv; + struct ieee80211_sta *sta = params->sta; +- struct rtw89_sta_link *rtwsta_link = (struct rtw89_sta_link *)sta->drv_priv; ++ struct rtw89_sta *rtwsta = sta_to_rtwsta(sta); ++ struct rtw89_vif *rtwvif = vif_to_rtwvif(vif); + u16 tid = params->tid; + struct ieee80211_txq *txq = sta->txq[tid]; + struct rtw89_txq *rtwtxq = (struct rtw89_txq *)txq->drv_priv; +@@ -873,29 +991,29 @@ static int rtw89_ops_ampdu_action(struct ieee80211_hw *hw, + case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT: + mutex_lock(&rtwdev->mutex); + clear_bit(RTW89_TXQ_F_AMPDU, &rtwtxq->flags); +- clear_bit(tid, rtwsta_link->ampdu_map); +- rtw89_chip_h2c_ampdu_cmac_tbl(rtwdev, vif, sta); ++ clear_bit(tid, rtwsta->ampdu_map); ++ rtw89_chip_h2c_ampdu_cmac_tbl(rtwdev, rtwvif, rtwsta); + mutex_unlock(&rtwdev->mutex); + ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid); + break; + case IEEE80211_AMPDU_TX_OPERATIONAL: + mutex_lock(&rtwdev->mutex); + set_bit(RTW89_TXQ_F_AMPDU, &rtwtxq->flags); +- rtwsta_link->ampdu_params[tid].agg_num = params->buf_size; +- rtwsta_link->ampdu_params[tid].amsdu = params->amsdu; +- set_bit(tid, rtwsta_link->ampdu_map); ++ rtwsta->ampdu_params[tid].agg_num = params->buf_size; ++ rtwsta->ampdu_params[tid].amsdu = params->amsdu; ++ set_bit(tid, rtwsta->ampdu_map); + rtw89_leave_ps_mode(rtwdev); +- rtw89_chip_h2c_ampdu_cmac_tbl(rtwdev, vif, sta); ++ rtw89_chip_h2c_ampdu_cmac_tbl(rtwdev, rtwvif, rtwsta); + mutex_unlock(&rtwdev->mutex); + break; + case IEEE80211_AMPDU_RX_START: + mutex_lock(&rtwdev->mutex); +- rtw89_chip_h2c_ba_cam(rtwdev, rtwsta_link, true, params); ++ rtw89_chip_h2c_ba_cam(rtwdev, rtwsta, true, params); + mutex_unlock(&rtwdev->mutex); + break; + case IEEE80211_AMPDU_RX_STOP: + mutex_lock(&rtwdev->mutex); +- rtw89_chip_h2c_ba_cam(rtwdev, rtwsta_link, false, params); ++ rtw89_chip_h2c_ba_cam(rtwdev, rtwsta, false, params); + mutex_unlock(&rtwdev->mutex); + break; + default: +@@ -924,7 +1042,12 @@ static void rtw89_ops_sta_statistics(struct ieee80211_hw *hw, + struct ieee80211_sta *sta, + struct station_info *sinfo) + { +- struct rtw89_sta_link *rtwsta_link = (struct rtw89_sta_link *)sta->drv_priv; ++ struct rtw89_sta *rtwsta = sta_to_rtwsta(sta); ++ struct rtw89_sta_link *rtwsta_link; ++ ++ rtwsta_link = rtw89_sta_get_link_inst(rtwsta, 0); ++ if (unlikely(!rtwsta_link)) ++ return; + + sinfo->txrate = rtwsta_link->ra_report.txrate; + sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BITRATE); +@@ -933,14 +1056,14 @@ static void rtw89_ops_sta_statistics(struct ieee80211_hw *hw, + static + void __rtw89_drop_packets(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif) + { +- struct rtw89_vif_link *rtwvif_link; ++ struct rtw89_vif *rtwvif; + + if (vif) { +- rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv; +- rtw89_mac_pkt_drop_vif(rtwdev, rtwvif_link); ++ rtwvif = vif_to_rtwvif(vif); ++ rtw89_mac_pkt_drop_vif(rtwdev, rtwvif); + } else { +- rtw89_for_each_rtwvif(rtwdev, rtwvif_link) +- rtw89_mac_pkt_drop_vif(rtwdev, rtwvif_link); ++ rtw89_for_each_rtwvif(rtwdev, rtwvif) ++ rtw89_mac_pkt_drop_vif(rtwdev, rtwvif); + } + } + +@@ -970,14 +1093,20 @@ struct rtw89_iter_bitrate_mask_data { + static void rtw89_ra_mask_info_update_iter(void *data, struct ieee80211_sta *sta) + { + struct rtw89_iter_bitrate_mask_data *br_data = data; +- struct rtw89_sta_link *rtwsta_link = (struct rtw89_sta_link *)sta->drv_priv; +- struct ieee80211_vif *vif = rtwvif_to_vif(rtwsta_link->rtwvif_link); ++ struct rtw89_sta *rtwsta = sta_to_rtwsta(sta); ++ struct rtw89_vif *rtwvif = rtwsta->rtwvif; ++ struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif); ++ struct rtw89_sta_link *rtwsta_link; ++ unsigned int link_id; + + if (vif != br_data->vif || vif->p2p) + return; + +- rtwsta_link->use_cfg_mask = true; +- rtwsta_link->mask = *br_data->mask; ++ rtw89_sta_for_each_link(rtwsta, rtwsta_link, link_id) { ++ rtwsta_link->use_cfg_mask = true; ++ rtwsta_link->mask = *br_data->mask; ++ } ++ + rtw89_phy_ra_update_sta(br_data->rtwdev, sta, IEEE80211_RC_SUPP_RATES_CHANGED); + } + +@@ -1047,10 +1176,20 @@ static void rtw89_ops_sw_scan_start(struct ieee80211_hw *hw, + const u8 *mac_addr) + { + struct rtw89_dev *rtwdev = hw->priv; +- struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv; ++ struct rtw89_vif *rtwvif = vif_to_rtwvif(vif); ++ struct rtw89_vif_link *rtwvif_link; + + mutex_lock(&rtwdev->mutex); ++ ++ rtwvif_link = rtw89_vif_get_link_inst(rtwvif, 0); ++ if (unlikely(!rtwvif_link)) { ++ rtw89_err(rtwdev, "sw scan start: find no link on HW-0\n"); ++ goto out; ++ } ++ + rtw89_core_scan_start(rtwdev, rtwvif_link, mac_addr, false); ++ ++out: + mutex_unlock(&rtwdev->mutex); + } + +@@ -1058,9 +1197,20 @@ static void rtw89_ops_sw_scan_complete(struct ieee80211_hw *hw, + struct ieee80211_vif *vif) + { + struct rtw89_dev *rtwdev = hw->priv; ++ struct rtw89_vif *rtwvif = vif_to_rtwvif(vif); ++ struct rtw89_vif_link *rtwvif_link; + + mutex_lock(&rtwdev->mutex); +- rtw89_core_scan_complete(rtwdev, vif, false); ++ ++ rtwvif_link = rtw89_vif_get_link_inst(rtwvif, 0); ++ if (unlikely(!rtwvif_link)) { ++ rtw89_err(rtwdev, "sw scan complete: find no link on HW-0\n"); ++ goto out; ++ } ++ ++ rtw89_core_scan_complete(rtwdev, rtwvif_link, false); ++ ++out: + mutex_unlock(&rtwdev->mutex); + } + +@@ -1077,22 +1227,35 @@ static int rtw89_ops_hw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + struct ieee80211_scan_request *req) + { + struct rtw89_dev *rtwdev = hw->priv; +- struct rtw89_vif_link *rtwvif_link = vif_to_rtwvif_safe(vif); +- int ret = 0; ++ struct rtw89_vif *rtwvif = vif_to_rtwvif(vif); ++ struct rtw89_vif_link *rtwvif_link; ++ int ret; + + if (!RTW89_CHK_FW_FEATURE(SCAN_OFFLOAD, &rtwdev->fw)) + return 1; + +- if (rtwdev->scanning || rtwvif_link->offchan) +- return -EBUSY; +- + mutex_lock(&rtwdev->mutex); +- rtw89_hw_scan_start(rtwdev, vif, req); +- ret = rtw89_hw_scan_offload(rtwdev, vif, true); ++ ++ if (rtwdev->scanning || rtwvif->offchan) { ++ ret = -EBUSY; ++ goto out; ++ } ++ ++ rtwvif_link = rtw89_vif_get_link_inst(rtwvif, 0); ++ if (unlikely(!rtwvif_link)) { ++ rtw89_err(rtwdev, "hw scan: find no link on HW-0\n"); ++ ret = -ENOLINK; ++ goto out; ++ } ++ ++ rtw89_hw_scan_start(rtwdev, rtwvif_link, req); ++ ret = rtw89_hw_scan_offload(rtwdev, rtwvif_link, true); + if (ret) { +- rtw89_hw_scan_abort(rtwdev, vif); ++ rtw89_hw_scan_abort(rtwdev, rtwvif_link); + rtw89_err(rtwdev, "HW scan failed with status: %d\n", ret); + } ++ ++out: + mutex_unlock(&rtwdev->mutex); + + return ret; +@@ -1102,6 +1265,8 @@ static void rtw89_ops_cancel_hw_scan(struct ieee80211_hw *hw, + struct ieee80211_vif *vif) + { + struct rtw89_dev *rtwdev = hw->priv; ++ struct rtw89_vif *rtwvif = vif_to_rtwvif(vif); ++ struct rtw89_vif_link *rtwvif_link; + + if (!RTW89_CHK_FW_FEATURE(SCAN_OFFLOAD, &rtwdev->fw)) + return; +@@ -1110,7 +1275,16 @@ static void rtw89_ops_cancel_hw_scan(struct ieee80211_hw *hw, + return; + + mutex_lock(&rtwdev->mutex); +- rtw89_hw_scan_abort(rtwdev, vif); ++ ++ rtwvif_link = rtw89_vif_get_link_inst(rtwvif, 0); ++ if (unlikely(!rtwvif_link)) { ++ rtw89_err(rtwdev, "cancel hw scan: find no link on HW-0\n"); ++ goto out; ++ } ++ ++ rtw89_hw_scan_abort(rtwdev, rtwvif_link); ++ ++out: + mutex_unlock(&rtwdev->mutex); + } + +@@ -1163,11 +1337,24 @@ static int rtw89_ops_assign_vif_chanctx(struct ieee80211_hw *hw, + struct ieee80211_chanctx_conf *ctx) + { + struct rtw89_dev *rtwdev = hw->priv; +- struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv; ++ struct rtw89_vif *rtwvif = vif_to_rtwvif(vif); ++ struct rtw89_vif_link *rtwvif_link; + int ret; + + mutex_lock(&rtwdev->mutex); ++ ++ rtwvif_link = rtwvif->links[link_conf->link_id]; ++ if (unlikely(!rtwvif_link)) { ++ rtw89_err(rtwdev, ++ "%s: rtwvif link (link_id %u) is not active\n", ++ __func__, link_conf->link_id); ++ ret = -ENOLINK; ++ goto out; ++ } ++ + ret = rtw89_chanctx_ops_assign_vif(rtwdev, rtwvif_link, ctx); ++ ++out: + mutex_unlock(&rtwdev->mutex); + + return ret; +@@ -1179,9 +1366,19 @@ static void rtw89_ops_unassign_vif_chanctx(struct ieee80211_hw *hw, + struct ieee80211_chanctx_conf *ctx) + { + struct rtw89_dev *rtwdev = hw->priv; +- struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv; ++ struct rtw89_vif *rtwvif = vif_to_rtwvif(vif); ++ struct rtw89_vif_link *rtwvif_link; + + mutex_lock(&rtwdev->mutex); ++ ++ rtwvif_link = rtwvif->links[link_conf->link_id]; ++ if (unlikely(!rtwvif_link)) { ++ rtw89_err(rtwdev, ++ "%s: rtwvif link (link_id %u) is not active\n", ++ __func__, link_conf->link_id); ++ return; ++ } ++ + rtw89_chanctx_ops_unassign_vif(rtwdev, rtwvif_link, ctx); + mutex_unlock(&rtwdev->mutex); + } +@@ -1193,10 +1390,10 @@ static int rtw89_ops_remain_on_channel(struct ieee80211_hw *hw, + enum ieee80211_roc_type type) + { + struct rtw89_dev *rtwdev = hw->priv; +- struct rtw89_vif_link *rtwvif_link = vif_to_rtwvif_safe(vif); +- struct rtw89_roc *roc = &rtwvif_link->roc; ++ struct rtw89_vif *rtwvif = vif_to_rtwvif_safe(vif); ++ struct rtw89_roc *roc = &rtwvif->roc; + +- if (!vif) ++ if (!rtwvif) + return -EINVAL; + + mutex_lock(&rtwdev->mutex); +@@ -1218,7 +1415,7 @@ static int rtw89_ops_remain_on_channel(struct ieee80211_hw *hw, + roc->chan = *chan; + roc->type = type; + +- rtw89_roc_start(rtwdev, rtwvif_link); ++ rtw89_roc_start(rtwdev, rtwvif); + + mutex_unlock(&rtwdev->mutex); + +@@ -1229,15 +1426,15 @@ static int rtw89_ops_cancel_remain_on_channel(struct ieee80211_hw *hw, + struct ieee80211_vif *vif) + { + struct rtw89_dev *rtwdev = hw->priv; +- struct rtw89_vif_link *rtwvif_link = vif_to_rtwvif_safe(vif); ++ struct rtw89_vif *rtwvif = vif_to_rtwvif_safe(vif); + +- if (!rtwvif_link) ++ if (!rtwvif) + return -EINVAL; + +- cancel_delayed_work_sync(&rtwvif_link->roc.roc_work); ++ cancel_delayed_work_sync(&rtwvif->roc.roc_work); + + mutex_lock(&rtwdev->mutex); +- rtw89_roc_end(rtwdev, rtwvif_link); ++ rtw89_roc_end(rtwdev, rtwvif); + mutex_unlock(&rtwdev->mutex); + + return 0; +@@ -1246,8 +1443,8 @@ static int rtw89_ops_cancel_remain_on_channel(struct ieee80211_hw *hw, + static void rtw89_set_tid_config_iter(void *data, struct ieee80211_sta *sta) + { + struct cfg80211_tid_config *tid_config = data; +- struct rtw89_sta_link *rtwsta_link = (struct rtw89_sta_link *)sta->drv_priv; +- struct rtw89_dev *rtwdev = rtwsta_link->rtwvif_link->rtwdev; ++ struct rtw89_sta *rtwsta = sta_to_rtwsta(sta); ++ struct rtw89_dev *rtwdev = rtwsta->rtwdev; + + rtw89_core_set_tid_config(rtwdev, sta, tid_config); + } +diff --git a/drivers/net/wireless/realtek/rtw89/phy.c b/drivers/net/wireless/realtek/rtw89/phy.c +index da9491213b7b5..4b47b45f897cb 100644 +--- a/drivers/net/wireless/realtek/rtw89/phy.c ++++ b/drivers/net/wireless/realtek/rtw89/phy.c +@@ -466,12 +466,12 @@ static void rtw89_phy_ra_sta_update(struct rtw89_dev *rtwdev, + ra->csi_mode = csi_mode; + } + +-void rtw89_phy_ra_update_sta(struct rtw89_dev *rtwdev, struct ieee80211_sta *sta, +- u32 changed) ++static void __rtw89_phy_ra_update_sta(struct rtw89_dev *rtwdev, ++ struct rtw89_vif_link *rtwvif_link, ++ struct rtw89_sta_link *rtwsta_link, ++ u32 changed) + { +- struct rtw89_sta_link *rtwsta_link = (struct rtw89_sta_link *)sta->drv_priv; +- struct rtw89_vif_link *rtwvif_link = rtwsta_link->rtwvif_link; +- struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif_link); ++ struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link); + struct rtw89_ra_info *ra = &rtwsta_link->ra; + struct ieee80211_link_sta *link_sta; + +@@ -499,6 +499,20 @@ void rtw89_phy_ra_update_sta(struct rtw89_dev *rtwdev, struct ieee80211_sta *sta + rtw89_fw_h2c_ra(rtwdev, ra, false); + } + ++void rtw89_phy_ra_update_sta(struct rtw89_dev *rtwdev, struct ieee80211_sta *sta, ++ u32 changed) ++{ ++ struct rtw89_sta *rtwsta = sta_to_rtwsta(sta); ++ struct rtw89_vif_link *rtwvif_link; ++ struct rtw89_sta_link *rtwsta_link; ++ unsigned int link_id; ++ ++ rtw89_sta_for_each_link(rtwsta, rtwsta_link, link_id) { ++ rtwvif_link = rtwsta_link->rtwvif_link; ++ __rtw89_phy_ra_update_sta(rtwdev, rtwvif_link, rtwsta_link, changed); ++ } ++} ++ + static bool __check_rate_pattern(struct rtw89_phy_rate_pattern *next, + u16 rate_base, u64 ra_mask, u8 ra_mode, + u32 rate_ctrl, u32 ctrl_skip, bool force) +@@ -533,12 +547,12 @@ static bool __check_rate_pattern(struct rtw89_phy_rate_pattern *next, + [RTW89_CHIP_BE] = RTW89_HW_RATE_V1_ ## rate, \ + } + +-void rtw89_phy_rate_pattern_vif(struct rtw89_dev *rtwdev, +- struct ieee80211_vif *vif, +- const struct cfg80211_bitrate_mask *mask) ++static ++void __rtw89_phy_rate_pattern_vif(struct rtw89_dev *rtwdev, ++ struct rtw89_vif_link *rtwvif_link, ++ const struct cfg80211_bitrate_mask *mask) + { + struct ieee80211_supported_band *sband; +- struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv; + struct rtw89_phy_rate_pattern next_pattern = {0}; + const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, + rtwvif_link->chanctx_idx); +@@ -623,6 +637,18 @@ void rtw89_phy_rate_pattern_vif(struct rtw89_dev *rtwdev, + rtw89_debug(rtwdev, RTW89_DBG_RA, "unset rate pattern\n"); + } + ++void rtw89_phy_rate_pattern_vif(struct rtw89_dev *rtwdev, ++ struct ieee80211_vif *vif, ++ const struct cfg80211_bitrate_mask *mask) ++{ ++ struct rtw89_vif *rtwvif = vif_to_rtwvif(vif); ++ struct rtw89_vif_link *rtwvif_link; ++ unsigned int link_id; ++ ++ rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id) ++ __rtw89_phy_rate_pattern_vif(rtwdev, rtwvif_link, mask); ++} ++ + static void rtw89_phy_ra_update_sta_iter(void *data, struct ieee80211_sta *sta) + { + struct rtw89_dev *rtwdev = (struct rtw89_dev *)data; +@@ -640,7 +666,7 @@ void rtw89_phy_ra_update(struct rtw89_dev *rtwdev) + void rtw89_phy_ra_assoc(struct rtw89_dev *rtwdev, struct rtw89_sta_link *rtwsta_link) + { + struct rtw89_vif_link *rtwvif_link = rtwsta_link->rtwvif_link; +- struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif_link); ++ struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link); + struct rtw89_ra_info *ra = &rtwsta_link->ra; + u8 rssi = ewma_rssi_read(&rtwsta_link->avg_rssi) >> RSSI_FACTOR; + struct ieee80211_link_sta *link_sta; +@@ -2688,13 +2714,17 @@ static void __rtw89_phy_c2h_ra_rpt_iter(struct rtw89_sta_link *rtwsta_link, + static void rtw89_phy_c2h_ra_rpt_iter(void *data, struct ieee80211_sta *sta) + { + struct rtw89_phy_iter_ra_data *ra_data = (struct rtw89_phy_iter_ra_data *)data; +- struct rtw89_sta_link *rtwsta_link = (struct rtw89_sta_link *)sta->drv_priv; ++ struct rtw89_sta *rtwsta = sta_to_rtwsta(sta); ++ struct rtw89_sta_link *rtwsta_link; + struct ieee80211_link_sta *link_sta; ++ unsigned int link_id; + + rcu_read_lock(); + +- link_sta = rtw89_sta_rcu_dereference_link(rtwsta_link, false); +- __rtw89_phy_c2h_ra_rpt_iter(rtwsta_link, link_sta, ra_data); ++ rtw89_sta_for_each_link(rtwsta, rtwsta_link, link_id) { ++ link_sta = rtw89_sta_rcu_dereference_link(rtwsta_link, false); ++ __rtw89_phy_c2h_ra_rpt_iter(rtwsta_link, link_sta, ra_data); ++ } + + rcu_read_unlock(); + } +@@ -4422,7 +4452,7 @@ void rtw89_phy_ul_tb_ctrl_check(struct rtw89_dev *rtwdev, + struct rtw89_phy_ul_tb_check_data *ul_tb_data) + { + struct rtw89_traffic_stats *stats = &rtwdev->stats; +- struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif_link); ++ struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link); + + if (rtwvif_link->wifi_role != RTW89_WIFI_ROLE_STATION) + return; +@@ -4488,6 +4518,8 @@ void rtw89_phy_ul_tb_ctrl_track(struct rtw89_dev *rtwdev) + const struct rtw89_chip_info *chip = rtwdev->chip; + struct rtw89_phy_ul_tb_check_data ul_tb_data = {}; + struct rtw89_vif_link *rtwvif_link; ++ struct rtw89_vif *rtwvif; ++ unsigned int link_id; + + if (!chip->ul_tb_waveform_ctrl && !chip->ul_tb_pwr_diff) + return; +@@ -4495,8 +4527,9 @@ void rtw89_phy_ul_tb_ctrl_track(struct rtw89_dev *rtwdev) + if (rtwdev->total_sta_assoc != 1) + return; + +- rtw89_for_each_rtwvif(rtwdev, rtwvif_link) +- rtw89_phy_ul_tb_ctrl_check(rtwdev, rtwvif_link, &ul_tb_data); ++ rtw89_for_each_rtwvif(rtwdev, rtwvif) ++ rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id) ++ rtw89_phy_ul_tb_ctrl_check(rtwdev, rtwvif_link, &ul_tb_data); + + if (!ul_tb_data.valid) + return; +@@ -4660,12 +4693,10 @@ struct rtw89_phy_iter_rssi_data { + bool rssi_changed; + }; + +-static void rtw89_phy_stat_rssi_update_iter(void *data, +- struct ieee80211_sta *sta) ++static ++void __rtw89_phy_stat_rssi_update_iter(struct rtw89_sta_link *rtwsta_link, ++ struct rtw89_phy_iter_rssi_data *rssi_data) + { +- struct rtw89_sta_link *rtwsta_link = (struct rtw89_sta_link *)sta->drv_priv; +- struct rtw89_phy_iter_rssi_data *rssi_data = +- (struct rtw89_phy_iter_rssi_data *)data; + struct rtw89_phy_ch_info *ch_info = rssi_data->ch_info; + unsigned long rssi_curr; + +@@ -4685,6 +4716,19 @@ static void rtw89_phy_stat_rssi_update_iter(void *data, + } + } + ++static void rtw89_phy_stat_rssi_update_iter(void *data, ++ struct ieee80211_sta *sta) ++{ ++ struct rtw89_phy_iter_rssi_data *rssi_data = ++ (struct rtw89_phy_iter_rssi_data *)data; ++ struct rtw89_sta *rtwsta = sta_to_rtwsta(sta); ++ struct rtw89_sta_link *rtwsta_link; ++ unsigned int link_id; ++ ++ rtw89_sta_for_each_link(rtwsta, rtwsta_link, link_id) ++ __rtw89_phy_stat_rssi_update_iter(rtwsta_link, rssi_data); ++} ++ + static void rtw89_phy_stat_rssi_update(struct rtw89_dev *rtwdev) + { + struct rtw89_phy_iter_rssi_data rssi_data = {0}; +@@ -5788,24 +5832,13 @@ void rtw89_phy_dig(struct rtw89_dev *rtwdev) + rtw89_phy_dig_sdagc_follow_pagc_config(rtwdev, false); + } + +-static void rtw89_phy_tx_path_div_sta_iter(void *data, struct ieee80211_sta *sta) ++static void __rtw89_phy_tx_path_div_sta_iter(struct rtw89_dev *rtwdev, ++ struct rtw89_sta_link *rtwsta_link) + { +- struct rtw89_sta_link *rtwsta_link = (struct rtw89_sta_link *)sta->drv_priv; +- struct rtw89_dev *rtwdev = rtwsta_link->rtwdev; +- struct rtw89_vif_link *rtwvif_link = rtwsta_link->rtwvif_link; + struct rtw89_hal *hal = &rtwdev->hal; +- bool *done = data; + u8 rssi_a, rssi_b; + u32 candidate; + +- if (rtwvif_link->wifi_role != RTW89_WIFI_ROLE_STATION || sta->tdls) +- return; +- +- if (*done) +- return; +- +- *done = true; +- + rssi_a = ewma_rssi_read(&rtwsta_link->rssi[RF_PATH_A]); + rssi_b = ewma_rssi_read(&rtwsta_link->rssi[RF_PATH_B]); + +@@ -5831,6 +5864,37 @@ static void rtw89_phy_tx_path_div_sta_iter(void *data, struct ieee80211_sta *sta + } + } + ++static void rtw89_phy_tx_path_div_sta_iter(void *data, struct ieee80211_sta *sta) ++{ ++ struct rtw89_sta *rtwsta = sta_to_rtwsta(sta); ++ struct rtw89_dev *rtwdev = rtwsta->rtwdev; ++ struct rtw89_vif *rtwvif = rtwsta->rtwvif; ++ struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif); ++ struct rtw89_vif_link *rtwvif_link; ++ struct rtw89_sta_link *rtwsta_link; ++ unsigned int link_id; ++ bool *done = data; ++ ++ if (WARN(ieee80211_vif_is_mld(vif), "MLD mix path_div\n")) ++ return; ++ ++ if (sta->tdls) ++ return; ++ ++ if (*done) ++ return; ++ ++ rtw89_sta_for_each_link(rtwsta, rtwsta_link, link_id) { ++ rtwvif_link = rtwsta_link->rtwvif_link; ++ if (rtwvif_link->wifi_role != RTW89_WIFI_ROLE_STATION) ++ continue; ++ ++ *done = true; ++ __rtw89_phy_tx_path_div_sta_iter(rtwdev, rtwsta_link); ++ return; ++ } ++} ++ + void rtw89_phy_tx_path_div_track(struct rtw89_dev *rtwdev) + { + struct rtw89_hal *hal = &rtwdev->hal; +@@ -6040,7 +6104,7 @@ void rtw89_phy_dm_init(struct rtw89_dev *rtwdev) + void rtw89_phy_set_bss_color(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link) + { +- struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif_link); ++ struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link); + const struct rtw89_chip_info *chip = rtwdev->chip; + const struct rtw89_reg_def *bss_clr_vld = &chip->bss_clr_vld; + enum rtw89_phy_idx phy_idx = RTW89_PHY_0; +diff --git a/drivers/net/wireless/realtek/rtw89/ps.c b/drivers/net/wireless/realtek/rtw89/ps.c +index ded0b73bd6783..c1c12abc2ea93 100644 +--- a/drivers/net/wireless/realtek/rtw89/ps.c ++++ b/drivers/net/wireless/realtek/rtw89/ps.c +@@ -147,6 +147,8 @@ static void rtw89_leave_lps_vif(struct rtw89_dev *rtwdev, + void rtw89_leave_lps(struct rtw89_dev *rtwdev) + { + struct rtw89_vif_link *rtwvif_link; ++ struct rtw89_vif *rtwvif; ++ unsigned int link_id; + + lockdep_assert_held(&rtwdev->mutex); + +@@ -155,21 +157,25 @@ void rtw89_leave_lps(struct rtw89_dev *rtwdev) + + __rtw89_leave_ps_mode(rtwdev); + +- rtw89_for_each_rtwvif(rtwdev, rtwvif_link) +- rtw89_leave_lps_vif(rtwdev, rtwvif_link); ++ rtw89_for_each_rtwvif(rtwdev, rtwvif) ++ rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id) ++ rtw89_leave_lps_vif(rtwdev, rtwvif_link); + } + + void rtw89_enter_ips(struct rtw89_dev *rtwdev) + { + struct rtw89_vif_link *rtwvif_link; ++ struct rtw89_vif *rtwvif; ++ unsigned int link_id; + + set_bit(RTW89_FLAG_INACTIVE_PS, rtwdev->flags); + + if (!test_bit(RTW89_FLAG_POWERON, rtwdev->flags)) + return; + +- rtw89_for_each_rtwvif(rtwdev, rtwvif_link) +- rtw89_mac_vif_deinit(rtwdev, rtwvif_link); ++ rtw89_for_each_rtwvif(rtwdev, rtwvif) ++ rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id) ++ rtw89_mac_vif_deinit(rtwdev, rtwvif_link); + + rtw89_core_stop(rtwdev); + } +@@ -177,6 +183,8 @@ void rtw89_enter_ips(struct rtw89_dev *rtwdev) + void rtw89_leave_ips(struct rtw89_dev *rtwdev) + { + struct rtw89_vif_link *rtwvif_link; ++ struct rtw89_vif *rtwvif; ++ unsigned int link_id; + int ret; + + if (test_bit(RTW89_FLAG_POWERON, rtwdev->flags)) +@@ -188,8 +196,9 @@ void rtw89_leave_ips(struct rtw89_dev *rtwdev) + + rtw89_set_channel(rtwdev); + +- rtw89_for_each_rtwvif(rtwdev, rtwvif_link) +- rtw89_mac_vif_init(rtwdev, rtwvif_link); ++ rtw89_for_each_rtwvif(rtwdev, rtwvif) ++ rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id) ++ rtw89_mac_vif_init(rtwdev, rtwvif_link); + + clear_bit(RTW89_FLAG_INACTIVE_PS, rtwdev->flags); + } +@@ -269,16 +278,22 @@ void rtw89_process_p2p_ps(struct rtw89_dev *rtwdev, + void rtw89_recalc_lps(struct rtw89_dev *rtwdev) + { + struct ieee80211_vif *vif, *found_vif = NULL; +- struct rtw89_vif_link *rtwvif_link; ++ struct rtw89_vif *rtwvif; + enum rtw89_entity_mode mode; + int count = 0; + ++ /* FIXME: Fix rtw89_enter_lps() and __rtw89_enter_ps_mode() ++ * to take MLO cases into account before doing the following. ++ */ ++ if (rtwdev->support_mlo) ++ goto disable_lps; ++ + mode = rtw89_get_entity_mode(rtwdev); + if (mode == RTW89_ENTITY_MODE_MCC) + goto disable_lps; + +- rtw89_for_each_rtwvif(rtwdev, rtwvif_link) { +- vif = rtwvif_to_vif(rtwvif_link); ++ rtw89_for_each_rtwvif(rtwdev, rtwvif) { ++ vif = rtwvif_to_vif(rtwvif); + + if (vif->type != NL80211_IFTYPE_STATION) { + count = 0; +diff --git a/drivers/net/wireless/realtek/rtw89/regd.c b/drivers/net/wireless/realtek/rtw89/regd.c +index aa5ae02443727..bb064a086970b 100644 +--- a/drivers/net/wireless/realtek/rtw89/regd.c ++++ b/drivers/net/wireless/realtek/rtw89/regd.c +@@ -794,21 +794,25 @@ static bool __rtw89_reg_6ghz_tpe_recalc(struct rtw89_dev *rtwdev) + struct rtw89_regulatory_info *regulatory = &rtwdev->regulatory; + struct rtw89_reg_6ghz_tpe new = {}; + struct rtw89_vif_link *rtwvif_link; ++ struct rtw89_vif *rtwvif; ++ unsigned int link_id; + bool changed = false; + +- rtw89_for_each_rtwvif(rtwdev, rtwvif_link) { ++ rtw89_for_each_rtwvif(rtwdev, rtwvif) { + const struct rtw89_reg_6ghz_tpe *tmp; + const struct rtw89_chan *chan; + +- chan = rtw89_chan_get(rtwdev, rtwvif_link->chanctx_idx); +- if (chan->band_type != RTW89_BAND_6G) +- continue; ++ rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id) { ++ chan = rtw89_chan_get(rtwdev, rtwvif_link->chanctx_idx); ++ if (chan->band_type != RTW89_BAND_6G) ++ continue; + +- tmp = &rtwvif_link->reg_6ghz_tpe; +- if (!tmp->valid) +- continue; ++ tmp = &rtwvif_link->reg_6ghz_tpe; ++ if (!tmp->valid) ++ continue; + +- tpe_intersect_constraint(&new, tmp->constraint); ++ tpe_intersect_constraint(&new, tmp->constraint); ++ } + } + + if (memcmp(®ulatory->reg_6ghz_tpe, &new, +@@ -873,19 +877,23 @@ static bool __rtw89_reg_6ghz_power_recalc(struct rtw89_dev *rtwdev) + enum rtw89_reg_6ghz_power sel; + const struct rtw89_chan *chan; + struct rtw89_vif_link *rtwvif_link; ++ struct rtw89_vif *rtwvif; ++ unsigned int link_id; + int count = 0; + u8 index; + +- rtw89_for_each_rtwvif(rtwdev, rtwvif_link) { +- chan = rtw89_chan_get(rtwdev, rtwvif_link->chanctx_idx); +- if (chan->band_type != RTW89_BAND_6G) +- continue; ++ rtw89_for_each_rtwvif(rtwdev, rtwvif) { ++ rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id) { ++ chan = rtw89_chan_get(rtwdev, rtwvif_link->chanctx_idx); ++ if (chan->band_type != RTW89_BAND_6G) ++ continue; + +- if (count != 0 && rtwvif_link->reg_6ghz_power == sel) +- continue; ++ if (count != 0 && rtwvif_link->reg_6ghz_power == sel) ++ continue; + +- sel = rtwvif_link->reg_6ghz_power; +- count++; ++ sel = rtwvif_link->reg_6ghz_power; ++ count++; ++ } + } + + if (count != 1) +diff --git a/drivers/net/wireless/realtek/rtw89/ser.c b/drivers/net/wireless/realtek/rtw89/ser.c +index 50b66eaf9bd04..7b203bb7f151a 100644 +--- a/drivers/net/wireless/realtek/rtw89/ser.c ++++ b/drivers/net/wireless/realtek/rtw89/ser.c +@@ -298,54 +298,71 @@ static void drv_resume_rx(struct rtw89_ser *ser) + clear_bit(RTW89_SER_DRV_STOP_RX, ser->flags); + } + +-static void ser_reset_vif(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link) ++static void ser_reset_vif(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif) + { +- rtw89_core_release_bit_map(rtwdev->hw_port, rtwvif_link->port); +- rtwvif_link->net_type = RTW89_NET_TYPE_NO_LINK; +- rtwvif_link->trigger = false; +- rtwvif_link->tdls_peer = 0; ++ struct rtw89_vif_link *rtwvif_link; ++ unsigned int link_id; ++ ++ rtwvif->tdls_peer = 0; ++ ++ rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id) { ++ rtw89_core_release_bit_map(rtwdev->hw_port, rtwvif_link->port); ++ rtwvif_link->net_type = RTW89_NET_TYPE_NO_LINK; ++ rtwvif_link->trigger = false; ++ } + } + + static void ser_sta_deinit_cam_iter(void *data, struct ieee80211_sta *sta) + { +- struct rtw89_vif_link *target_rtwvif = (struct rtw89_vif_link *)data; +- struct rtw89_sta_link *rtwsta_link = (struct rtw89_sta_link *)sta->drv_priv; +- struct rtw89_vif_link *rtwvif_link = rtwsta_link->rtwvif_link; +- struct rtw89_dev *rtwdev = rtwvif_link->rtwdev; ++ struct rtw89_vif *target_rtwvif = (struct rtw89_vif *)data; ++ struct rtw89_sta *rtwsta = sta_to_rtwsta(sta); ++ struct rtw89_vif *rtwvif = rtwsta->rtwvif; ++ struct rtw89_dev *rtwdev = rtwvif->rtwdev; ++ struct rtw89_vif_link *rtwvif_link; ++ struct rtw89_sta_link *rtwsta_link; ++ unsigned int link_id; + +- if (rtwvif_link != target_rtwvif) ++ if (rtwvif != target_rtwvif) + return; + +- if (rtwvif_link->net_type == RTW89_NET_TYPE_AP_MODE || sta->tdls) +- rtw89_cam_deinit_addr_cam(rtwdev, &rtwsta_link->addr_cam); +- if (sta->tdls) +- rtw89_cam_deinit_bssid_cam(rtwdev, &rtwsta_link->bssid_cam); ++ rtw89_sta_for_each_link(rtwsta, rtwsta_link, link_id) { ++ rtwvif_link = rtwsta_link->rtwvif_link; + +- INIT_LIST_HEAD(&rtwsta_link->ba_cam_list); ++ if (rtwvif_link->net_type == RTW89_NET_TYPE_AP_MODE || sta->tdls) ++ rtw89_cam_deinit_addr_cam(rtwdev, &rtwsta_link->addr_cam); ++ if (sta->tdls) ++ rtw89_cam_deinit_bssid_cam(rtwdev, &rtwsta_link->bssid_cam); ++ ++ INIT_LIST_HEAD(&rtwsta_link->ba_cam_list); ++ } + } + +-static void ser_deinit_cam(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link) ++static void ser_deinit_cam(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif) + { ++ struct rtw89_vif_link *rtwvif_link; ++ unsigned int link_id; ++ + ieee80211_iterate_stations_atomic(rtwdev->hw, + ser_sta_deinit_cam_iter, +- rtwvif_link); ++ rtwvif); + +- rtw89_cam_deinit(rtwdev, rtwvif_link); ++ rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id) ++ rtw89_cam_deinit(rtwdev, rtwvif_link); + + bitmap_zero(rtwdev->cam_info.ba_cam_map, RTW89_MAX_BA_CAM_NUM); + } + + static void ser_reset_mac_binding(struct rtw89_dev *rtwdev) + { +- struct rtw89_vif_link *rtwvif_link; ++ struct rtw89_vif *rtwvif; + + rtw89_cam_reset_keys(rtwdev); +- rtw89_for_each_rtwvif(rtwdev, rtwvif_link) +- ser_deinit_cam(rtwdev, rtwvif_link); ++ rtw89_for_each_rtwvif(rtwdev, rtwvif) ++ ser_deinit_cam(rtwdev, rtwvif); + + rtw89_core_release_all_bits_map(rtwdev->mac_id_map, RTW89_MAX_MAC_ID_NUM); +- rtw89_for_each_rtwvif(rtwdev, rtwvif_link) +- ser_reset_vif(rtwdev, rtwvif_link); ++ rtw89_for_each_rtwvif(rtwdev, rtwvif) ++ ser_reset_vif(rtwdev, rtwvif); + + rtwdev->total_sta_assoc = 0; + } +diff --git a/drivers/net/wireless/realtek/rtw89/util.h b/drivers/net/wireless/realtek/rtw89/util.h +index a5e87a8d8642c..e669544cafd3f 100644 +--- a/drivers/net/wireless/realtek/rtw89/util.h ++++ b/drivers/net/wireless/realtek/rtw89/util.h +@@ -21,14 +21,14 @@ + * twice cause the list to be added twice. + */ + static inline bool rtw89_rtwvif_in_list(struct rtw89_dev *rtwdev, +- struct rtw89_vif_link *new) ++ struct rtw89_vif *new) + { +- struct rtw89_vif_link *rtwvif_link; ++ struct rtw89_vif *rtwvif; + + lockdep_assert_held(&rtwdev->mutex); + +- rtw89_for_each_rtwvif(rtwdev, rtwvif_link) +- if (rtwvif_link == new) ++ rtw89_for_each_rtwvif(rtwdev, rtwvif) ++ if (rtwvif == new) + return true; + + return false; +diff --git a/drivers/net/wireless/realtek/rtw89/wow.c b/drivers/net/wireless/realtek/rtw89/wow.c +index 97b527d04ad71..3e81fd974ec18 100644 +--- a/drivers/net/wireless/realtek/rtw89/wow.c ++++ b/drivers/net/wireless/realtek/rtw89/wow.c +@@ -421,7 +421,8 @@ static void rtw89_wow_construct_key_info(struct rtw89_dev *rtwdev) + { + struct rtw89_wow_param *rtw_wow = &rtwdev->wow; + struct rtw89_wow_key_info *key_info = &rtw_wow->key_info; +- struct ieee80211_vif *wow_vif = rtwdev->wow.wow_vif; ++ struct rtw89_vif_link *rtwvif_link = rtwdev->wow.rtwvif_link; ++ struct ieee80211_vif *wow_vif = rtwvif_link_to_vif(rtwvif_link); + bool err = false; + + rcu_read_lock(); +@@ -596,7 +597,8 @@ static int rtw89_wow_get_aoac_rpt(struct rtw89_dev *rtwdev, bool rx_ready) + static struct ieee80211_key_conf *rtw89_wow_gtk_rekey(struct rtw89_dev *rtwdev, + u32 cipher, u8 keyidx, u8 *gtk) + { +- struct ieee80211_vif *wow_vif = rtwdev->wow.wow_vif; ++ struct rtw89_vif_link *rtwvif_link = rtwdev->wow.rtwvif_link; ++ struct ieee80211_vif *wow_vif = rtwvif_link_to_vif(rtwvif_link); + const struct rtw89_cipher_info *cipher_info; + struct ieee80211_key_conf *rekey_conf; + struct ieee80211_key_conf *key; +@@ -632,8 +634,8 @@ static struct ieee80211_key_conf *rtw89_wow_gtk_rekey(struct rtw89_dev *rtwdev, + + static void rtw89_wow_update_key_info(struct rtw89_dev *rtwdev, bool rx_ready) + { +- struct ieee80211_vif *wow_vif = rtwdev->wow.wow_vif; +- struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)wow_vif->drv_priv; ++ struct rtw89_vif_link *rtwvif_link = rtwdev->wow.rtwvif_link; ++ struct ieee80211_vif *wow_vif = rtwvif_link_to_vif(rtwvif_link); + struct rtw89_wow_param *rtw_wow = &rtwdev->wow; + struct rtw89_wow_aoac_report *aoac_rpt = &rtw_wow->aoac_rpt; + struct rtw89_set_key_info_iter_data data = {.error = false, +@@ -689,16 +691,14 @@ static void rtw89_wow_leave_deep_ps(struct rtw89_dev *rtwdev) + + static void rtw89_wow_enter_deep_ps(struct rtw89_dev *rtwdev) + { +- struct ieee80211_vif *wow_vif = rtwdev->wow.wow_vif; +- struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)wow_vif->drv_priv; ++ struct rtw89_vif_link *rtwvif_link = rtwdev->wow.rtwvif_link; + + __rtw89_enter_ps_mode(rtwdev, rtwvif_link); + } + + static void rtw89_wow_enter_ps(struct rtw89_dev *rtwdev) + { +- struct ieee80211_vif *wow_vif = rtwdev->wow.wow_vif; +- struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)wow_vif->drv_priv; ++ struct rtw89_vif_link *rtwvif_link = rtwdev->wow.rtwvif_link; + + if (rtw89_wow_mgd_linked(rtwdev)) + rtw89_enter_lps(rtwdev, rtwvif_link, false); +@@ -708,8 +708,7 @@ static void rtw89_wow_enter_ps(struct rtw89_dev *rtwdev) + + static void rtw89_wow_leave_ps(struct rtw89_dev *rtwdev, bool enable_wow) + { +- struct ieee80211_vif *wow_vif = rtwdev->wow.wow_vif; +- struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)wow_vif->drv_priv; ++ struct rtw89_vif_link *rtwvif_link = rtwdev->wow.rtwvif_link; + + if (rtw89_wow_mgd_linked(rtwdev)) { + rtw89_leave_lps(rtwdev); +@@ -742,6 +741,8 @@ static void rtw89_wow_set_rx_filter(struct rtw89_dev *rtwdev, bool enable) + + static void rtw89_wow_show_wakeup_reason(struct rtw89_dev *rtwdev) + { ++ struct rtw89_vif_link *rtwvif_link = rtwdev->wow.rtwvif_link; ++ struct ieee80211_vif *wow_vif = rtwvif_link_to_vif(rtwvif_link); + struct rtw89_wow_param *rtw_wow = &rtwdev->wow; + struct rtw89_wow_aoac_report *aoac_rpt = &rtw_wow->aoac_rpt; + struct cfg80211_wowlan_nd_info nd_info; +@@ -788,36 +789,34 @@ static void rtw89_wow_show_wakeup_reason(struct rtw89_dev *rtwdev) + break; + default: + rtw89_warn(rtwdev, "Unknown wakeup reason %x\n", reason); +- ieee80211_report_wowlan_wakeup(rtwdev->wow.wow_vif, NULL, +- GFP_KERNEL); ++ ieee80211_report_wowlan_wakeup(wow_vif, NULL, GFP_KERNEL); + return; + } + +- ieee80211_report_wowlan_wakeup(rtwdev->wow.wow_vif, &wakeup, +- GFP_KERNEL); ++ ieee80211_report_wowlan_wakeup(wow_vif, &wakeup, GFP_KERNEL); + } + + static void rtw89_wow_vif_iter(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link) + { + struct rtw89_wow_param *rtw_wow = &rtwdev->wow; +- struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif_link); ++ struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link); + + /* Current WoWLAN function support setting of only vif in + * infra mode or no link mode. When one suitable vif is found, + * stop the iteration. + */ +- if (rtw_wow->wow_vif || vif->type != NL80211_IFTYPE_STATION) ++ if (rtw_wow->rtwvif_link || vif->type != NL80211_IFTYPE_STATION) + return; + + switch (rtwvif_link->net_type) { + case RTW89_NET_TYPE_INFRA: + if (rtw_wow_has_mgd_features(rtwdev)) +- rtw_wow->wow_vif = vif; ++ rtw_wow->rtwvif_link = rtwvif_link; + break; + case RTW89_NET_TYPE_NO_LINK: + if (rtw_wow->pno_inited) +- rtw_wow->wow_vif = vif; ++ rtw_wow->rtwvif_link = rtwvif_link; + break; + default: + break; +@@ -1049,7 +1048,7 @@ static void rtw89_wow_clear_wakeups(struct rtw89_dev *rtwdev) + { + struct rtw89_wow_param *rtw_wow = &rtwdev->wow; + +- rtw_wow->wow_vif = NULL; ++ rtw_wow->rtwvif_link = NULL; + rtw89_core_release_all_bits_map(rtw_wow->flags, RTW89_WOW_FLAG_NUM); + rtw_wow->pattern_cnt = 0; + rtw_wow->pno_inited = false; +@@ -1076,6 +1075,7 @@ static int rtw89_wow_set_wakeups(struct rtw89_dev *rtwdev, + { + struct rtw89_wow_param *rtw_wow = &rtwdev->wow; + struct rtw89_vif_link *rtwvif_link; ++ struct rtw89_vif *rtwvif; + + if (wowlan->disconnect) + set_bit(RTW89_WOW_FLAG_EN_DISCONNECT, rtw_wow->flags); +@@ -1087,21 +1087,25 @@ static int rtw89_wow_set_wakeups(struct rtw89_dev *rtwdev, + if (wowlan->nd_config) + rtw89_wow_init_pno(rtwdev, wowlan->nd_config); + +- rtw89_for_each_rtwvif(rtwdev, rtwvif_link) ++ rtw89_for_each_rtwvif(rtwdev, rtwvif) { ++ /* use the link on HW-0 to do wow flow */ ++ rtwvif_link = rtw89_vif_get_link_inst(rtwvif, 0); ++ if (!rtwvif_link) ++ continue; ++ + rtw89_wow_vif_iter(rtwdev, rtwvif_link); ++ } + +- if (!rtw_wow->wow_vif) ++ rtwvif_link = rtw_wow->rtwvif_link; ++ if (!rtwvif_link) + return -EPERM; + +- rtwvif_link = (struct rtw89_vif_link *)rtw_wow->wow_vif->drv_priv; + return rtw89_wow_parse_patterns(rtwdev, rtwvif_link, wowlan); + } + + static int rtw89_wow_cfg_wake_pno(struct rtw89_dev *rtwdev, bool wow) + { +- struct rtw89_wow_param *rtw_wow = &rtwdev->wow; +- struct ieee80211_vif *wow_vif = rtw_wow->wow_vif; +- struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)wow_vif->drv_priv; ++ struct rtw89_vif_link *rtwvif_link = rtwdev->wow.rtwvif_link; + int ret; + + ret = rtw89_fw_h2c_cfg_pno(rtwdev, rtwvif_link, true); +@@ -1128,15 +1132,20 @@ static int rtw89_wow_cfg_wake_pno(struct rtw89_dev *rtwdev, bool wow) + static int rtw89_wow_cfg_wake(struct rtw89_dev *rtwdev, bool wow) + { + struct rtw89_wow_param *rtw_wow = &rtwdev->wow; +- struct ieee80211_vif *wow_vif = rtw_wow->wow_vif; +- struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)wow_vif->drv_priv; ++ struct rtw89_vif_link *rtwvif_link = rtw_wow->rtwvif_link; ++ struct ieee80211_vif *wow_vif = rtwvif_link_to_vif(rtwvif_link); + struct ieee80211_sta *wow_sta; + struct rtw89_sta_link *rtwsta_link = NULL; ++ struct rtw89_sta *rtwsta; + int ret; + +- wow_sta = ieee80211_find_sta(wow_vif, rtwvif_link->bssid); +- if (wow_sta) +- rtwsta_link = (struct rtw89_sta_link *)wow_sta->drv_priv; ++ wow_sta = ieee80211_find_sta(wow_vif, wow_vif->cfg.ap_addr); ++ if (wow_sta) { ++ rtwsta = sta_to_rtwsta(wow_sta); ++ rtwsta_link = rtwsta->links[rtwvif_link->link_id]; ++ if (!rtwsta_link) ++ return -ENOLINK; ++ } + + if (wow) { + if (rtw_wow->pattern_cnt) +@@ -1199,25 +1208,30 @@ static int rtw89_wow_swap_fw(struct rtw89_dev *rtwdev, bool wow) + enum rtw89_fw_type fw_type = wow ? RTW89_FW_WOWLAN : RTW89_FW_NORMAL; + enum rtw89_chip_gen chip_gen = rtwdev->chip->chip_gen; + struct rtw89_wow_param *rtw_wow = &rtwdev->wow; +- struct ieee80211_vif *wow_vif = rtw_wow->wow_vif; +- struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)wow_vif->drv_priv; ++ struct rtw89_vif_link *rtwvif_link = rtw_wow->rtwvif_link; ++ struct ieee80211_vif *wow_vif = rtwvif_link_to_vif(rtwvif_link); + enum rtw89_core_chip_id chip_id = rtwdev->chip->chip_id; + const struct rtw89_chip_info *chip = rtwdev->chip; + bool include_bb = !!chip->bbmcu_nr; + bool disable_intr_for_dlfw = false; + struct ieee80211_sta *wow_sta; + struct rtw89_sta_link *rtwsta_link = NULL; ++ struct rtw89_sta *rtwsta; + bool is_conn = true; + int ret; + + if (chip_id == RTL8852C || chip_id == RTL8922A) + disable_intr_for_dlfw = true; + +- wow_sta = ieee80211_find_sta(wow_vif, rtwvif_link->bssid); +- if (wow_sta) +- rtwsta_link = (struct rtw89_sta_link *)wow_sta->drv_priv; +- else ++ wow_sta = ieee80211_find_sta(wow_vif, wow_vif->cfg.ap_addr); ++ if (wow_sta) { ++ rtwsta = sta_to_rtwsta(wow_sta); ++ rtwsta_link = rtwsta->links[rtwvif_link->link_id]; ++ if (!rtwsta_link) ++ return -ENOLINK; ++ } else { + is_conn = false; ++ } + + if (disable_intr_for_dlfw) + rtw89_hci_disable_intr(rtwdev); +@@ -1372,9 +1386,7 @@ static int rtw89_wow_disable_trx_pre(struct rtw89_dev *rtwdev) + + static int rtw89_wow_disable_trx_post(struct rtw89_dev *rtwdev) + { +- struct rtw89_wow_param *rtw_wow = &rtwdev->wow; +- struct ieee80211_vif *vif = rtw_wow->wow_vif; +- struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv; ++ struct rtw89_vif_link *rtwvif_link = rtwdev->wow.rtwvif_link; + int ret; + + ret = rtw89_mac_cfg_ppdu_status(rtwdev, RTW89_MAC_0, true); +@@ -1446,8 +1458,7 @@ static int rtw89_pno_scan_offload(struct rtw89_dev *rtwdev, bool enable) + { + const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; + struct rtw89_wow_param *rtw_wow = &rtwdev->wow; +- struct ieee80211_vif *wow_vif = rtw_wow->wow_vif; +- struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)wow_vif->drv_priv; ++ struct rtw89_vif_link *rtwvif_link = rtwdev->wow.rtwvif_link; + int interval = rtw_wow->nd_config->scan_plans[0].interval; + struct rtw89_scan_option opt = {}; + int ret; +@@ -1489,8 +1500,7 @@ static int rtw89_pno_scan_offload(struct rtw89_dev *rtwdev, bool enable) + static int rtw89_wow_fw_start(struct rtw89_dev *rtwdev) + { + struct rtw89_wow_param *rtw_wow = &rtwdev->wow; +- struct ieee80211_vif *wow_vif = rtw_wow->wow_vif; +- struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)wow_vif->drv_priv; ++ struct rtw89_vif_link *rtwvif_link = rtw_wow->rtwvif_link; + int ret; + + if (rtw89_wow_no_link(rtwdev)) { +@@ -1558,8 +1568,7 @@ static int rtw89_wow_fw_start(struct rtw89_dev *rtwdev) + static int rtw89_wow_fw_stop(struct rtw89_dev *rtwdev) + { + struct rtw89_wow_param *rtw_wow = &rtwdev->wow; +- struct ieee80211_vif *wow_vif = rtw_wow->wow_vif; +- struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)wow_vif->drv_priv; ++ struct rtw89_vif_link *rtwvif_link = rtw_wow->rtwvif_link; + int ret; + + if (rtw89_wow_no_link(rtwdev)) { +diff --git a/drivers/net/wireless/realtek/rtw89/wow.h b/drivers/net/wireless/realtek/rtw89/wow.h +index a80b4b84587dd..f91991e8f2e30 100644 +--- a/drivers/net/wireless/realtek/rtw89/wow.h ++++ b/drivers/net/wireless/realtek/rtw89/wow.h +@@ -97,16 +97,14 @@ static inline int rtw89_wow_get_sec_hdr_len(struct rtw89_dev *rtwdev) + #ifdef CONFIG_PM + static inline bool rtw89_wow_mgd_linked(struct rtw89_dev *rtwdev) + { +- struct ieee80211_vif *wow_vif = rtwdev->wow.wow_vif; +- struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)wow_vif->drv_priv; ++ struct rtw89_vif_link *rtwvif_link = rtwdev->wow.rtwvif_link; + + return rtwvif_link->net_type == RTW89_NET_TYPE_INFRA; + } + + static inline bool rtw89_wow_no_link(struct rtw89_dev *rtwdev) + { +- struct ieee80211_vif *wow_vif = rtwdev->wow.wow_vif; +- struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)wow_vif->drv_priv; ++ struct rtw89_vif_link *rtwvif_link = rtwdev->wow.rtwvif_link; + + return rtwvif_link->net_type == RTW89_NET_TYPE_NO_LINK; + } +-- +2.43.0 + diff --git a/queue-6.12/wifi-rtw89-unlock-on-error-path-in-rtw89_ops_unassig.patch b/queue-6.12/wifi-rtw89-unlock-on-error-path-in-rtw89_ops_unassig.patch new file mode 100644 index 00000000000..1ada60e8eb2 --- /dev/null +++ b/queue-6.12/wifi-rtw89-unlock-on-error-path-in-rtw89_ops_unassig.patch @@ -0,0 +1,36 @@ +From 4c2e90bdc5f66b08fad0d04ebbb3cac7cb87f1e6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Mon, 21 Oct 2024 12:14:39 +0300 +Subject: wifi: rtw89: unlock on error path in rtw89_ops_unassign_vif_chanctx() + +From: Dan Carpenter <dan.carpenter@linaro.org> + +[ Upstream commit ac4f4e5a203927e555107db6e781e85f241720e1 ] + +We need to call mutex_unlock() on this error path. + +Fixes: aad0394e7a02 ("wifi: rtw89: tweak driver architecture for impending MLO support") +Signed-off-by: Dan Carpenter <dan.carpenter@linaro.org> +Reviewed-by: Zong-Zhe Yang <kevin_yang@realtek.com> +Signed-off-by: Ping-Ke Shih <pkshih@realtek.com> +Link: https://patch.msgid.link/8683a712-ffc2-466b-8382-0b264719f8ef@stanley.mountain +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/net/wireless/realtek/rtw89/mac80211.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/net/wireless/realtek/rtw89/mac80211.c b/drivers/net/wireless/realtek/rtw89/mac80211.c +index 44ba4dc181b5b..13fb3cac27016 100644 +--- a/drivers/net/wireless/realtek/rtw89/mac80211.c ++++ b/drivers/net/wireless/realtek/rtw89/mac80211.c +@@ -1373,6 +1373,7 @@ static void rtw89_ops_unassign_vif_chanctx(struct ieee80211_hw *hw, + + rtwvif_link = rtwvif->links[link_conf->link_id]; + if (unlikely(!rtwvif_link)) { ++ mutex_unlock(&rtwdev->mutex); + rtw89_err(rtwdev, + "%s: rtwvif link (link_id %u) is not active\n", + __func__, link_conf->link_id); +-- +2.43.0 + diff --git a/queue-6.12/wifi-wfx-fix-error-handling-in-wfx_core_init.patch b/queue-6.12/wifi-wfx-fix-error-handling-in-wfx_core_init.patch new file mode 100644 index 00000000000..6725efa52bb --- /dev/null +++ b/queue-6.12/wifi-wfx-fix-error-handling-in-wfx_core_init.patch @@ -0,0 +1,60 @@ +From cf923174c0cb3622685f2d576d37d1f58fcbd550 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Tue, 22 Oct 2024 17:04:53 +0800 +Subject: wifi: wfx: Fix error handling in wfx_core_init() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Yuan Can <yuancan@huawei.com> + +[ Upstream commit 3b88a9876779b55478a4dde867e73f7a100ffa23 ] + +The wfx_core_init() returns without checking the retval from +sdio_register_driver(). +If the sdio_register_driver() failed, the module failed to install, +leaving the wfx_spi_driver not unregistered. + +Fixes: a7a91ca5a23d ("staging: wfx: add infrastructure for new driver") +Signed-off-by: Yuan Can <yuancan@huawei.com> +Reviewed-by: Jérôme Pouiller <jerome.pouiller@silabs.com> +Signed-off-by: Kalle Valo <kvalo@kernel.org> +Link: https://patch.msgid.link/20241022090453.84679-1-yuancan@huawei.com +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/net/wireless/silabs/wfx/main.c | 17 +++++++++++++++-- + 1 file changed, 15 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/wireless/silabs/wfx/main.c b/drivers/net/wireless/silabs/wfx/main.c +index e7198520bdffc..64441c8bc4606 100644 +--- a/drivers/net/wireless/silabs/wfx/main.c ++++ b/drivers/net/wireless/silabs/wfx/main.c +@@ -480,10 +480,23 @@ static int __init wfx_core_init(void) + { + int ret = 0; + +- if (IS_ENABLED(CONFIG_SPI)) ++ if (IS_ENABLED(CONFIG_SPI)) { + ret = spi_register_driver(&wfx_spi_driver); +- if (IS_ENABLED(CONFIG_MMC) && !ret) ++ if (ret) ++ goto out; ++ } ++ if (IS_ENABLED(CONFIG_MMC)) { + ret = sdio_register_driver(&wfx_sdio_driver); ++ if (ret) ++ goto unregister_spi; ++ } ++ ++ return 0; ++ ++unregister_spi: ++ if (IS_ENABLED(CONFIG_SPI)) ++ spi_unregister_driver(&wfx_spi_driver); ++out: + return ret; + } + module_init(wfx_core_init); +-- +2.43.0 + diff --git a/queue-6.12/wifi-wilc1000-set-mac-after-operation-mode.patch b/queue-6.12/wifi-wilc1000-set-mac-after-operation-mode.patch new file mode 100644 index 00000000000..ad7d9337a60 --- /dev/null +++ b/queue-6.12/wifi-wilc1000-set-mac-after-operation-mode.patch @@ -0,0 +1,82 @@ +From 6d6fb9b4795e6ad524b32ce69ab5ee5c60ebfbd9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Thu, 3 Oct 2024 15:24:17 +0200 +Subject: wifi: wilc1000: Set MAC after operation mode +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Marek Vasut <marex@denx.de> + +[ Upstream commit 29dd3e48b9bd88bf65a1e760126fa18d1def7b30 ] + +It seems it is necessary to set WILC MAC address after operation mode, +otherwise the MAC address of the WILC MAC is reset back to what is in +nvmem. This causes a failure to associate with AP after the WILC MAC +address was overridden by userspace. + +Test case: +" +ap$ cat << EOF > hostap.conf +interface=wlan0 +ssid=ssid +hw_mode=g +channel=6 +wpa=2 +wpa_passphrase=pass +wpa_key_mgmt=WPA-PSK +EOF +ap$ hostapd -d hostap.conf +ap$ ifconfig wlan0 10.0.0.1 +" + +" +sta$ ifconfig wlan0 hw ether 00:11:22:33:44:55 +sta$ wpa_supplicant -i wlan0 -c <(wpa_passphrase ssid pass) +sta$ ifconfig wlan0 10.0.0.2 +sta$ ping 10.0.0.1 # fails without this patch +" + +AP still indicates SA with original MAC address from nvmem without this patch: +" +nl80211: RX frame da=ff:ff:ff:ff:ff:ff sa=60:01:23:45:67:89 bssid=ff:ff:ff:ff:ff:ff ... + ^^^^^^^^^^^^^^^^^ +" + +Fixes: 83d9b54ee5d4 ("wifi: wilc1000: read MAC address from fuse at probe") +Tested-by: Alexis Lothoré <alexis.lothore@bootlin.com> +Signed-off-by: Marek Vasut <marex@denx.de> +Signed-off-by: Kalle Valo <kvalo@kernel.org> +Link: https://patch.msgid.link/20241003132504.52233-1-marex@denx.de +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/net/wireless/microchip/wilc1000/netdev.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/drivers/net/wireless/microchip/wilc1000/netdev.c b/drivers/net/wireless/microchip/wilc1000/netdev.c +index 9ecf3fb29b558..8bc127c5a538c 100644 +--- a/drivers/net/wireless/microchip/wilc1000/netdev.c ++++ b/drivers/net/wireless/microchip/wilc1000/netdev.c +@@ -608,6 +608,9 @@ static int wilc_mac_open(struct net_device *ndev) + return ret; + } + ++ wilc_set_operation_mode(vif, wilc_get_vif_idx(vif), vif->iftype, ++ vif->idx); ++ + netdev_dbg(ndev, "Mac address: %pM\n", ndev->dev_addr); + ret = wilc_set_mac_address(vif, ndev->dev_addr); + if (ret) { +@@ -618,9 +621,6 @@ static int wilc_mac_open(struct net_device *ndev) + return ret; + } + +- wilc_set_operation_mode(vif, wilc_get_vif_idx(vif), vif->iftype, +- vif->idx); +- + mgmt_regs.interface_stypes = vif->mgmt_reg_stypes; + /* so we detect a change */ + vif->mgmt_reg_stypes = 0; +-- +2.43.0 + diff --git a/queue-6.12/wireguard-selftests-load-nf_conntrack-if-not-present.patch b/queue-6.12/wireguard-selftests-load-nf_conntrack-if-not-present.patch new file mode 100644 index 00000000000..2070a8e3dfb --- /dev/null +++ b/queue-6.12/wireguard-selftests-load-nf_conntrack-if-not-present.patch @@ -0,0 +1,40 @@ +From e2b008cd4f27d40e3d7ade7ede49d75217e45347 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Sun, 17 Nov 2024 22:20:29 +0100 +Subject: wireguard: selftests: load nf_conntrack if not present + +From: Hangbin Liu <liuhangbin@gmail.com> + +[ Upstream commit 0290abc9860917f1ee8b58309c2bbd740a39ee8e ] + +Some distros may not load nf_conntrack by default, which will cause +subsequent nf_conntrack sets to fail. Load this module if it is not +already loaded. + +Fixes: e7096c131e51 ("net: WireGuard secure network tunnel") +Signed-off-by: Hangbin Liu <liuhangbin@gmail.com> +Reviewed-by: Simon Horman <horms@kernel.org> +[ Jason: add [[ -e ... ]] check so this works in the qemu harness. ] +Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com> +Link: https://patch.msgid.link/20241117212030.629159-4-Jason@zx2c4.com +Signed-off-by: Jakub Kicinski <kuba@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + tools/testing/selftests/wireguard/netns.sh | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/tools/testing/selftests/wireguard/netns.sh b/tools/testing/selftests/wireguard/netns.sh +index 405ff262ca93d..55500f901fbc3 100755 +--- a/tools/testing/selftests/wireguard/netns.sh ++++ b/tools/testing/selftests/wireguard/netns.sh +@@ -332,6 +332,7 @@ waitiface $netns1 vethc + waitiface $netns2 veths + + n0 bash -c 'printf 1 > /proc/sys/net/ipv4/ip_forward' ++[[ -e /proc/sys/net/netfilter/nf_conntrack_udp_timeout ]] || modprobe nf_conntrack + n0 bash -c 'printf 2 > /proc/sys/net/netfilter/nf_conntrack_udp_timeout' + n0 bash -c 'printf 2 > /proc/sys/net/netfilter/nf_conntrack_udp_timeout_stream' + n0 iptables -t nat -A POSTROUTING -s 192.168.1.0/24 -d 10.0.0.0/24 -j SNAT --to 10.0.0.1 +-- +2.43.0 + diff --git a/queue-6.12/x86-fix-off-by-one-in-access_ok.patch b/queue-6.12/x86-fix-off-by-one-in-access_ok.patch new file mode 100644 index 00000000000..2d01835a3bf --- /dev/null +++ b/queue-6.12/x86-fix-off-by-one-in-access_ok.patch @@ -0,0 +1,52 @@ +From 0a920a8ca84a569eef231c82e3fad2a69a9c210c Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Sun, 24 Nov 2024 15:39:00 +0000 +Subject: x86: fix off-by-one in access_ok() + +From: David Laight <David.Laight@ACULAB.COM> + +[ Upstream commit 573f45a9f9a47fed4c7957609689b772121b33d7 ] + +When the size isn't a small constant, __access_ok() will call +valid_user_address() with the address after the last byte of the user +buffer. + +It is valid for a buffer to end with the last valid user address so +valid_user_address() must allow accesses to the base of the guard page. + +[ This introduces an off-by-one in the other direction for the plain + non-sized accesses, but since we have that guard region that is a + whole page, those checks "allowing" accesses to that guard region + don't really matter. The access will fault anyway, whether to the + guard page or if the address has been masked to all ones - Linus ] + +Fixes: 86e6b1547b3d0 ("x86: fix user address masking non-canonical speculation issue") +Signed-off-by: David Laight <david.laight@aculab.com> +Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + arch/x86/kernel/cpu/common.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c +index f43bb974fc66d..b17bcf9b67eed 100644 +--- a/arch/x86/kernel/cpu/common.c ++++ b/arch/x86/kernel/cpu/common.c +@@ -2392,12 +2392,12 @@ void __init arch_cpu_finalize_init(void) + alternative_instructions(); + + if (IS_ENABLED(CONFIG_X86_64)) { +- unsigned long USER_PTR_MAX = TASK_SIZE_MAX-1; ++ unsigned long USER_PTR_MAX = TASK_SIZE_MAX; + + /* + * Enable this when LAM is gated on LASS support + if (cpu_feature_enabled(X86_FEATURE_LAM)) +- USER_PTR_MAX = (1ul << 63) - PAGE_SIZE - 1; ++ USER_PTR_MAX = (1ul << 63) - PAGE_SIZE; + */ + runtime_const_init(ptr, USER_PTR_MAX); + +-- +2.43.0 + diff --git a/queue-6.12/x86-pvh-call-c-code-via-the-kernel-virtual-mapping.patch b/queue-6.12/x86-pvh-call-c-code-via-the-kernel-virtual-mapping.patch new file mode 100644 index 00000000000..8d0d2008162 --- /dev/null +++ b/queue-6.12/x86-pvh-call-c-code-via-the-kernel-virtual-mapping.patch @@ -0,0 +1,54 @@ +From 17985cf324becce2b9ffe5048f2fc295a3fdf88c Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Wed, 9 Oct 2024 18:04:40 +0200 +Subject: x86/pvh: Call C code via the kernel virtual mapping + +From: Ard Biesheuvel <ardb@kernel.org> + +[ Upstream commit e8fbc0d9cab6c1ee6403f42c0991b0c1d5dbc092 ] + +Calling C code via a different mapping than it was linked at is +problematic, because the compiler assumes that RIP-relative and absolute +symbol references are interchangeable. GCC in particular may use +RIP-relative per-CPU variable references even when not using -fpic. + +So call xen_prepare_pvh() via its kernel virtual mapping on x86_64, so +that those RIP-relative references produce the correct values. This +matches the pre-existing behavior for i386, which also invokes +xen_prepare_pvh() via the kernel virtual mapping before invoking +startup_32 with paging disabled again. + +Fixes: 7243b93345f7 ("xen/pvh: Bootstrap PVH guest") +Tested-by: Jason Andryuk <jason.andryuk@amd.com> +Reviewed-by: Jason Andryuk <jason.andryuk@amd.com> +Signed-off-by: Ard Biesheuvel <ardb@kernel.org> +Message-ID: <20241009160438.3884381-8-ardb+git@google.com> +Signed-off-by: Juergen Gross <jgross@suse.com> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + arch/x86/platform/pvh/head.S | 9 ++++++++- + 1 file changed, 8 insertions(+), 1 deletion(-) + +diff --git a/arch/x86/platform/pvh/head.S b/arch/x86/platform/pvh/head.S +index 64fca49cd88ff..ce4fd8d33da46 100644 +--- a/arch/x86/platform/pvh/head.S ++++ b/arch/x86/platform/pvh/head.S +@@ -172,7 +172,14 @@ SYM_CODE_START_LOCAL(pvh_start_xen) + movq %rbp, %rbx + subq $_pa(pvh_start_xen), %rbx + movq %rbx, phys_base(%rip) +- call xen_prepare_pvh ++ ++ /* Call xen_prepare_pvh() via the kernel virtual mapping */ ++ leaq xen_prepare_pvh(%rip), %rax ++ subq phys_base(%rip), %rax ++ addq $__START_KERNEL_map, %rax ++ ANNOTATE_RETPOLINE_SAFE ++ call *%rax ++ + /* + * Clear phys_base. __startup_64 will *add* to its value, + * so reset to 0. +-- +2.43.0 + diff --git a/queue-6.12/x86-tdx-dynamically-disable-sept-violations-from-cau.patch b/queue-6.12/x86-tdx-dynamically-disable-sept-violations-from-cau.patch new file mode 100644 index 00000000000..e007f964ab3 --- /dev/null +++ b/queue-6.12/x86-tdx-dynamically-disable-sept-violations-from-cau.patch @@ -0,0 +1,172 @@ +From 83d3bcb7c1dd5ee981138560564d9b0f007a3d59 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Mon, 4 Nov 2024 12:38:02 +0200 +Subject: x86/tdx: Dynamically disable SEPT violations from causing #VEs + +From: Kirill A. Shutemov <kirill.shutemov@linux.intel.com> + +[ Upstream commit f65aa0ad79fca4ace921da0701644f020129043d ] + +Memory access #VEs are hard for Linux to handle in contexts like the +entry code or NMIs. But other OSes need them for functionality. +There's a static (pre-guest-boot) way for a VMM to choose one or the +other. But VMMs don't always know which OS they are booting, so they +choose to deliver those #VEs so the "other" OSes will work. That, +unfortunately has left us in the lurch and exposed to these +hard-to-handle #VEs. + +The TDX module has introduced a new feature. Even if the static +configuration is set to "send nasty #VEs", the kernel can dynamically +request that they be disabled. Once they are disabled, access to private +memory that is not in the Mapped state in the Secure-EPT (SEPT) will +result in an exit to the VMM rather than injecting a #VE. + +Check if the feature is available and disable SEPT #VE if possible. + +If the TD is allowed to disable/enable SEPT #VEs, the ATTR_SEPT_VE_DISABLE +attribute is no longer reliable. It reflects the initial state of the +control for the TD, but it will not be updated if someone (e.g. bootloader) +changes it before the kernel starts. Kernel must check TDCS_TD_CTLS bit to +determine if SEPT #VEs are enabled or disabled. + +[ dhansen: remove 'return' at end of function ] + +Fixes: 373e715e31bf ("x86/tdx: Panic on bad configs that #VE on "private" memory access") +Signed-off-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com> +Signed-off-by: Dave Hansen <dave.hansen@linux.intel.com> +Acked-by: Kai Huang <kai.huang@intel.com> +Link: https://lore.kernel.org/all/20241104103803.195705-4-kirill.shutemov%40linux.intel.com +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + arch/x86/coco/tdx/tdx.c | 74 ++++++++++++++++++++++++------- + arch/x86/include/asm/shared/tdx.h | 10 ++++- + 2 files changed, 67 insertions(+), 17 deletions(-) + +diff --git a/arch/x86/coco/tdx/tdx.c b/arch/x86/coco/tdx/tdx.c +index 28b321a95a5e8..2f85ed005c42f 100644 +--- a/arch/x86/coco/tdx/tdx.c ++++ b/arch/x86/coco/tdx/tdx.c +@@ -79,7 +79,7 @@ static inline void tdcall(u64 fn, struct tdx_module_args *args) + } + + /* Read TD-scoped metadata */ +-static inline u64 __maybe_unused tdg_vm_rd(u64 field, u64 *value) ++static inline u64 tdg_vm_rd(u64 field, u64 *value) + { + struct tdx_module_args args = { + .rdx = field, +@@ -194,6 +194,60 @@ static void __noreturn tdx_panic(const char *msg) + __tdx_hypercall(&args); + } + ++/* ++ * The kernel cannot handle #VEs when accessing normal kernel memory. Ensure ++ * that no #VE will be delivered for accesses to TD-private memory. ++ * ++ * TDX 1.0 does not allow the guest to disable SEPT #VE on its own. The VMM ++ * controls if the guest will receive such #VE with TD attribute ++ * ATTR_SEPT_VE_DISABLE. ++ * ++ * Newer TDX modules allow the guest to control if it wants to receive SEPT ++ * violation #VEs. ++ * ++ * Check if the feature is available and disable SEPT #VE if possible. ++ * ++ * If the TD is allowed to disable/enable SEPT #VEs, the ATTR_SEPT_VE_DISABLE ++ * attribute is no longer reliable. It reflects the initial state of the ++ * control for the TD, but it will not be updated if someone (e.g. bootloader) ++ * changes it before the kernel starts. Kernel must check TDCS_TD_CTLS bit to ++ * determine if SEPT #VEs are enabled or disabled. ++ */ ++static void disable_sept_ve(u64 td_attr) ++{ ++ const char *msg = "TD misconfiguration: SEPT #VE has to be disabled"; ++ bool debug = td_attr & ATTR_DEBUG; ++ u64 config, controls; ++ ++ /* Is this TD allowed to disable SEPT #VE */ ++ tdg_vm_rd(TDCS_CONFIG_FLAGS, &config); ++ if (!(config & TDCS_CONFIG_FLEXIBLE_PENDING_VE)) { ++ /* No SEPT #VE controls for the guest: check the attribute */ ++ if (td_attr & ATTR_SEPT_VE_DISABLE) ++ return; ++ ++ /* Relax SEPT_VE_DISABLE check for debug TD for backtraces */ ++ if (debug) ++ pr_warn("%s\n", msg); ++ else ++ tdx_panic(msg); ++ return; ++ } ++ ++ /* Check if SEPT #VE has been disabled before us */ ++ tdg_vm_rd(TDCS_TD_CTLS, &controls); ++ if (controls & TD_CTLS_PENDING_VE_DISABLE) ++ return; ++ ++ /* Keep #VEs enabled for splats in debugging environments */ ++ if (debug) ++ return; ++ ++ /* Disable SEPT #VEs */ ++ tdg_vm_wr(TDCS_TD_CTLS, TD_CTLS_PENDING_VE_DISABLE, ++ TD_CTLS_PENDING_VE_DISABLE); ++} ++ + static void tdx_setup(u64 *cc_mask) + { + struct tdx_module_args args = {}; +@@ -219,24 +273,12 @@ static void tdx_setup(u64 *cc_mask) + gpa_width = args.rcx & GENMASK(5, 0); + *cc_mask = BIT_ULL(gpa_width - 1); + ++ td_attr = args.rdx; ++ + /* Kernel does not use NOTIFY_ENABLES and does not need random #VEs */ + tdg_vm_wr(TDCS_NOTIFY_ENABLES, 0, -1ULL); + +- /* +- * The kernel can not handle #VE's when accessing normal kernel +- * memory. Ensure that no #VE will be delivered for accesses to +- * TD-private memory. Only VMM-shared memory (MMIO) will #VE. +- */ +- td_attr = args.rdx; +- if (!(td_attr & ATTR_SEPT_VE_DISABLE)) { +- const char *msg = "TD misconfiguration: SEPT_VE_DISABLE attribute must be set."; +- +- /* Relax SEPT_VE_DISABLE check for debug TD. */ +- if (td_attr & ATTR_DEBUG) +- pr_warn("%s\n", msg); +- else +- tdx_panic(msg); +- } ++ disable_sept_ve(td_attr); + } + + /* +diff --git a/arch/x86/include/asm/shared/tdx.h b/arch/x86/include/asm/shared/tdx.h +index 7e12cfa28bec9..fecb2a6e864be 100644 +--- a/arch/x86/include/asm/shared/tdx.h ++++ b/arch/x86/include/asm/shared/tdx.h +@@ -19,9 +19,17 @@ + #define TDG_VM_RD 7 + #define TDG_VM_WR 8 + +-/* TDCS fields. To be used by TDG.VM.WR and TDG.VM.RD module calls */ ++/* TDX TD-Scope Metadata. To be used by TDG.VM.WR and TDG.VM.RD */ ++#define TDCS_CONFIG_FLAGS 0x1110000300000016 ++#define TDCS_TD_CTLS 0x1110000300000017 + #define TDCS_NOTIFY_ENABLES 0x9100000000000010 + ++/* TDCS_CONFIG_FLAGS bits */ ++#define TDCS_CONFIG_FLEXIBLE_PENDING_VE BIT_ULL(1) ++ ++/* TDCS_TD_CTLS bits */ ++#define TD_CTLS_PENDING_VE_DISABLE BIT_ULL(0) ++ + /* TDX hypercall Leaf IDs */ + #define TDVMCALL_MAP_GPA 0x10001 + #define TDVMCALL_GET_QUOTE 0x10002 +-- +2.43.0 + diff --git a/queue-6.12/x86-tdx-introduce-wrappers-to-read-and-write-td-meta.patch b/queue-6.12/x86-tdx-introduce-wrappers-to-read-and-write-td-meta.patch new file mode 100644 index 00000000000..ff60829bb94 --- /dev/null +++ b/queue-6.12/x86-tdx-introduce-wrappers-to-read-and-write-td-meta.patch @@ -0,0 +1,106 @@ +From 4ac6c8d492bf6067deb7ebecff30fdfa82820eb5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Mon, 4 Nov 2024 12:38:00 +0200 +Subject: x86/tdx: Introduce wrappers to read and write TD metadata + +From: Kirill A. Shutemov <kirill.shutemov@linux.intel.com> + +[ Upstream commit 5081e8fadb809253c911b349b01d87c5b4e3fec5 ] + +The TDG_VM_WR TDCALL is used to ask the TDX module to change some +TD-specific VM configuration. There is currently only one user in the +kernel of this TDCALL leaf. More will be added shortly. + +Refactor to make way for more users of TDG_VM_WR who will need to modify +other TD configuration values. + +Add a wrapper for the TDG_VM_RD TDCALL that requests TD-specific +metadata from the TDX module. There are currently no users for +TDG_VM_RD. Mark it as __maybe_unused until the first user appears. + +This is preparation for enumeration and enabling optional TD features. + +Signed-off-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com> +Signed-off-by: Dave Hansen <dave.hansen@linux.intel.com> +Reviewed-by: Kai Huang <kai.huang@intel.com> +Reviewed-by: Kuppuswamy Sathyanarayanan <sathyanarayanan.kuppuswamy@linux.intel.com> +Link: https://lore.kernel.org/all/20241104103803.195705-2-kirill.shutemov%40linux.intel.com +Stable-dep-of: f65aa0ad79fc ("x86/tdx: Dynamically disable SEPT violations from causing #VEs") +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + arch/x86/coco/tdx/tdx.c | 32 ++++++++++++++++++++++++++----- + arch/x86/include/asm/shared/tdx.h | 1 + + 2 files changed, 28 insertions(+), 5 deletions(-) + +diff --git a/arch/x86/coco/tdx/tdx.c b/arch/x86/coco/tdx/tdx.c +index 327c45c5013fe..c74bb9e7d7a35 100644 +--- a/arch/x86/coco/tdx/tdx.c ++++ b/arch/x86/coco/tdx/tdx.c +@@ -78,6 +78,32 @@ static inline void tdcall(u64 fn, struct tdx_module_args *args) + panic("TDCALL %lld failed (Buggy TDX module!)\n", fn); + } + ++/* Read TD-scoped metadata */ ++static inline u64 __maybe_unused tdg_vm_rd(u64 field, u64 *value) ++{ ++ struct tdx_module_args args = { ++ .rdx = field, ++ }; ++ u64 ret; ++ ++ ret = __tdcall_ret(TDG_VM_RD, &args); ++ *value = args.r8; ++ ++ return ret; ++} ++ ++/* Write TD-scoped metadata */ ++static inline u64 tdg_vm_wr(u64 field, u64 value, u64 mask) ++{ ++ struct tdx_module_args args = { ++ .rdx = field, ++ .r8 = value, ++ .r9 = mask, ++ }; ++ ++ return __tdcall(TDG_VM_WR, &args); ++} ++ + /** + * tdx_mcall_get_report0() - Wrapper to get TDREPORT0 (a.k.a. TDREPORT + * subtype 0) using TDG.MR.REPORT TDCALL. +@@ -929,10 +955,6 @@ static void tdx_kexec_finish(void) + + void __init tdx_early_init(void) + { +- struct tdx_module_args args = { +- .rdx = TDCS_NOTIFY_ENABLES, +- .r9 = -1ULL, +- }; + u64 cc_mask; + u32 eax, sig[3]; + +@@ -951,7 +973,7 @@ void __init tdx_early_init(void) + cc_set_mask(cc_mask); + + /* Kernel does not use NOTIFY_ENABLES and does not need random #VEs */ +- tdcall(TDG_VM_WR, &args); ++ tdg_vm_wr(TDCS_NOTIFY_ENABLES, 0, -1ULL); + + /* + * All bits above GPA width are reserved and kernel treats shared bit +diff --git a/arch/x86/include/asm/shared/tdx.h b/arch/x86/include/asm/shared/tdx.h +index fdfd41511b021..7e12cfa28bec9 100644 +--- a/arch/x86/include/asm/shared/tdx.h ++++ b/arch/x86/include/asm/shared/tdx.h +@@ -16,6 +16,7 @@ + #define TDG_VP_VEINFO_GET 3 + #define TDG_MR_REPORT 4 + #define TDG_MEM_PAGE_ACCEPT 6 ++#define TDG_VM_RD 7 + #define TDG_VM_WR 8 + + /* TDCS fields. To be used by TDG.VM.WR and TDG.VM.RD module calls */ +-- +2.43.0 + diff --git a/queue-6.12/x86-tdx-rename-tdx_parse_tdinfo-to-tdx_setup.patch b/queue-6.12/x86-tdx-rename-tdx_parse_tdinfo-to-tdx_setup.patch new file mode 100644 index 00000000000..23079d7f40a --- /dev/null +++ b/queue-6.12/x86-tdx-rename-tdx_parse_tdinfo-to-tdx_setup.patch @@ -0,0 +1,67 @@ +From c0db90de897ac4267a3d73fba50d0f0640c7e27b Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Mon, 4 Nov 2024 12:38:01 +0200 +Subject: x86/tdx: Rename tdx_parse_tdinfo() to tdx_setup() + +From: Kirill A. Shutemov <kirill.shutemov@linux.intel.com> + +[ Upstream commit b064043d9565786b385f85e6436ca5716bbd5552 ] + +Rename tdx_parse_tdinfo() to tdx_setup() and move setting NOTIFY_ENABLES +there. + +The function will be extended to adjust TD configuration. + +Signed-off-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com> +Signed-off-by: Dave Hansen <dave.hansen@linux.intel.com> +Reviewed-by: Kuppuswamy Sathyanarayanan <sathyanarayanan.kuppuswamy@linux.intel.com> +Reviewed-by: Kai Huang <kai.huang@intel.com> +Link: https://lore.kernel.org/all/20241104103803.195705-3-kirill.shutemov%40linux.intel.com +Stable-dep-of: f65aa0ad79fc ("x86/tdx: Dynamically disable SEPT violations from causing #VEs") +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + arch/x86/coco/tdx/tdx.c | 13 ++++++++----- + 1 file changed, 8 insertions(+), 5 deletions(-) + +diff --git a/arch/x86/coco/tdx/tdx.c b/arch/x86/coco/tdx/tdx.c +index c74bb9e7d7a35..28b321a95a5e8 100644 +--- a/arch/x86/coco/tdx/tdx.c ++++ b/arch/x86/coco/tdx/tdx.c +@@ -194,7 +194,7 @@ static void __noreturn tdx_panic(const char *msg) + __tdx_hypercall(&args); + } + +-static void tdx_parse_tdinfo(u64 *cc_mask) ++static void tdx_setup(u64 *cc_mask) + { + struct tdx_module_args args = {}; + unsigned int gpa_width; +@@ -219,6 +219,9 @@ static void tdx_parse_tdinfo(u64 *cc_mask) + gpa_width = args.rcx & GENMASK(5, 0); + *cc_mask = BIT_ULL(gpa_width - 1); + ++ /* Kernel does not use NOTIFY_ENABLES and does not need random #VEs */ ++ tdg_vm_wr(TDCS_NOTIFY_ENABLES, 0, -1ULL); ++ + /* + * The kernel can not handle #VE's when accessing normal kernel + * memory. Ensure that no #VE will be delivered for accesses to +@@ -969,11 +972,11 @@ void __init tdx_early_init(void) + setup_force_cpu_cap(X86_FEATURE_TSC_RELIABLE); + + cc_vendor = CC_VENDOR_INTEL; +- tdx_parse_tdinfo(&cc_mask); +- cc_set_mask(cc_mask); + +- /* Kernel does not use NOTIFY_ENABLES and does not need random #VEs */ +- tdg_vm_wr(TDCS_NOTIFY_ENABLES, 0, -1ULL); ++ /* Configure the TD */ ++ tdx_setup(&cc_mask); ++ ++ cc_set_mask(cc_mask); + + /* + * All bits above GPA width are reserved and kernel treats shared bit +-- +2.43.0 + diff --git a/queue-6.12/x86-unwind-orc-fix-unwind-for-newly-forked-tasks.patch b/queue-6.12/x86-unwind-orc-fix-unwind-for-newly-forked-tasks.patch new file mode 100644 index 00000000000..92051efed47 --- /dev/null +++ b/queue-6.12/x86-unwind-orc-fix-unwind-for-newly-forked-tasks.patch @@ -0,0 +1,49 @@ +From cf72d9cf74d58d8bb89d8dc17d4fec006b0fabf3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Fri, 13 Sep 2024 10:45:01 +0800 +Subject: x86/unwind/orc: Fix unwind for newly forked tasks + +From: Zheng Yejian <zhengyejian@huaweicloud.com> + +[ Upstream commit 3bf19a0fb690022ec22ce87a5afeb1030cbcb56c ] + +When arch_stack_walk_reliable() is called to unwind for newly forked +tasks, the return value is negative which means the call stack is +unreliable. This obviously does not meet expectations. + +The root cause is that after commit 3aec4ecb3d1f ("x86: Rewrite + ret_from_fork() in C"), the 'ret_addr' of newly forked task is changed +to 'ret_from_fork_asm' (see copy_thread()), then at the start of the +unwind, it is incorrectly interprets not as a "signal" one because +'ret_from_fork' is still used to determine the initial "signal" (see +__unwind_start()). Then the address gets incorrectly decremented in the +call to orc_find() (see unwind_next_frame()) and resulting in the +incorrect ORC data. + +To fix it, check 'ret_from_fork_asm' rather than 'ret_from_fork' in +__unwind_start(). + +Fixes: 3aec4ecb3d1f ("x86: Rewrite ret_from_fork() in C") +Signed-off-by: Zheng Yejian <zhengyejian@huaweicloud.com> +Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + arch/x86/kernel/unwind_orc.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/arch/x86/kernel/unwind_orc.c b/arch/x86/kernel/unwind_orc.c +index d00c28aaa5be4..d4705a348a804 100644 +--- a/arch/x86/kernel/unwind_orc.c ++++ b/arch/x86/kernel/unwind_orc.c +@@ -723,7 +723,7 @@ void __unwind_start(struct unwind_state *state, struct task_struct *task, + state->sp = task->thread.sp + sizeof(*frame); + state->bp = READ_ONCE_NOCHECK(frame->bp); + state->ip = READ_ONCE_NOCHECK(frame->ret_addr); +- state->signal = (void *)state->ip == ret_from_fork; ++ state->signal = (void *)state->ip == ret_from_fork_asm; + } + + if (get_stack_info((unsigned long *)state->sp, state->task, +-- +2.43.0 + diff --git a/queue-6.12/xsk-free-skb-when-tx-metadata-options-are-invalid.patch b/queue-6.12/xsk-free-skb-when-tx-metadata-options-are-invalid.patch new file mode 100644 index 00000000000..f9d9a57bd36 --- /dev/null +++ b/queue-6.12/xsk-free-skb-when-tx-metadata-options-are-invalid.patch @@ -0,0 +1,75 @@ +From 6a9cf04d929f6ec57e44c49ac47923d6f23b85bd Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Thu, 14 Nov 2024 12:30:05 +0100 +Subject: xsk: Free skb when TX metadata options are invalid +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Felix Maurer <fmaurer@redhat.com> + +[ Upstream commit 0c0d0f42ffa6ac94cd79893b7ed419c15e1b45de ] + +When a new skb is allocated for transmitting an xsk descriptor, i.e., for +every non-multibuf descriptor or the first frag of a multibuf descriptor, +but the descriptor is later found to have invalid options set for the TX +metadata, the new skb is never freed. This can leak skbs until the send +buffer is full which makes sending more packets impossible. + +Fix this by freeing the skb in the error path if we are currently dealing +with the first frag, i.e., an skb allocated in this iteration of +xsk_build_skb. + +Fixes: 48eb03dd2630 ("xsk: Add TX timestamp and TX checksum offload support") +Reported-by: Michal Schmidt <mschmidt@redhat.com> +Signed-off-by: Felix Maurer <fmaurer@redhat.com> +Reviewed-by: Toke Høiland-Jørgensen <toke@redhat.com> +Acked-by: Stanislav Fomichev <sdf@fomichev.me> +Acked-by: Martin KaFai Lau <martin.lau@kernel.org> +Link: https://patch.msgid.link/edb9b00fb19e680dff5a3350cd7581c5927975a8.1731581697.git.fmaurer@redhat.com +Signed-off-by: Jakub Kicinski <kuba@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + net/xdp/xsk.c | 11 ++++++----- + 1 file changed, 6 insertions(+), 5 deletions(-) + +diff --git a/net/xdp/xsk.c b/net/xdp/xsk.c +index 1140b2a120cae..b57d5d2904eb4 100644 +--- a/net/xdp/xsk.c ++++ b/net/xdp/xsk.c +@@ -675,6 +675,8 @@ static struct sk_buff *xsk_build_skb(struct xdp_sock *xs, + len = desc->len; + + if (!skb) { ++ first_frag = true; ++ + hr = max(NET_SKB_PAD, L1_CACHE_ALIGN(dev->needed_headroom)); + tr = dev->needed_tailroom; + skb = sock_alloc_send_skb(&xs->sk, hr + len + tr, 1, &err); +@@ -685,12 +687,8 @@ static struct sk_buff *xsk_build_skb(struct xdp_sock *xs, + skb_put(skb, len); + + err = skb_store_bits(skb, 0, buffer, len); +- if (unlikely(err)) { +- kfree_skb(skb); ++ if (unlikely(err)) + goto free_err; +- } +- +- first_frag = true; + } else { + int nr_frags = skb_shinfo(skb)->nr_frags; + struct page *page; +@@ -758,6 +756,9 @@ static struct sk_buff *xsk_build_skb(struct xdp_sock *xs, + return skb; + + free_err: ++ if (first_frag && skb) ++ kfree_skb(skb); ++ + if (err == -EOVERFLOW) { + /* Drop the packet */ + xsk_set_destructor_arg(xs->skb); +-- +2.43.0 + diff --git a/queue-6.12/zram-fix-null-pointer-in-comp_algorithm_show.patch b/queue-6.12/zram-fix-null-pointer-in-comp_algorithm_show.patch new file mode 100644 index 00000000000..9fc8f9b9219 --- /dev/null +++ b/queue-6.12/zram-fix-null-pointer-in-comp_algorithm_show.patch @@ -0,0 +1,91 @@ +From 1f09b0bf72b550ccabf16a09e324893b109007c1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Fri, 8 Nov 2024 18:01:47 +0800 +Subject: zram: fix NULL pointer in comp_algorithm_show() + +From: Liu Shixin <liushixin2@huawei.com> + +[ Upstream commit f364cdeb38938f9d03061682b8ff3779dd1730e5 ] + +LTP reported a NULL pointer dereference as followed: + + CPU: 7 UID: 0 PID: 5995 Comm: cat Kdump: loaded Not tainted 6.12.0-rc6+ #3 + Hardware name: QEMU KVM Virtual Machine, BIOS 0.0.0 02/06/2015 + pstate: 40400005 (nZcv daif +PAN -UAO -TCO -DIT -SSBS BTYPE=--) + pc : __pi_strcmp+0x24/0x140 + lr : zcomp_available_show+0x60/0x100 [zram] + sp : ffff800088b93b90 + x29: ffff800088b93b90 x28: 0000000000000001 x27: 0000000000400cc0 + x26: 0000000000000ffe x25: ffff80007b3e2388 x24: 0000000000000000 + x23: ffff80007b3e2390 x22: ffff0004041a9000 x21: ffff80007b3e2900 + x20: 0000000000000000 x19: 0000000000000000 x18: 0000000000000000 + x17: 0000000000000000 x16: 0000000000000000 x15: 0000000000000000 + x14: 0000000000000000 x13: 0000000000000000 x12: 0000000000000000 + x11: 0000000000000000 x10: ffff80007b3e2900 x9 : ffff80007b3cb280 + x8 : 0101010101010101 x7 : 0000000000000000 x6 : 0000000000000000 + x5 : 0000000000000040 x4 : 0000000000000000 x3 : 00656c722d6f7a6c + x2 : 0000000000000000 x1 : ffff80007b3e2900 x0 : 0000000000000000 + Call trace: + __pi_strcmp+0x24/0x140 + comp_algorithm_show+0x40/0x70 [zram] + dev_attr_show+0x28/0x80 + sysfs_kf_seq_show+0x90/0x140 + kernfs_seq_show+0x34/0x48 + seq_read_iter+0x1d4/0x4e8 + kernfs_fop_read_iter+0x40/0x58 + new_sync_read+0x9c/0x168 + vfs_read+0x1a8/0x1f8 + ksys_read+0x74/0x108 + __arm64_sys_read+0x24/0x38 + invoke_syscall+0x50/0x120 + el0_svc_common.constprop.0+0xc8/0xf0 + do_el0_svc+0x24/0x38 + el0_svc+0x38/0x138 + el0t_64_sync_handler+0xc0/0xc8 + el0t_64_sync+0x188/0x190 + +The zram->comp_algs[ZRAM_PRIMARY_COMP] can be NULL in zram_add() if +comp_algorithm_set() has not been called. User can access the zram device +by sysfs after device_add_disk(), so there is a time window to trigger the +NULL pointer dereference. Move it ahead device_add_disk() to make sure +when user can access the zram device, it is ready. comp_algorithm_set() +is protected by zram->init_lock in other places and no such problem. + +Link: https://lkml.kernel.org/r/20241108100147.3776123-1-liushixin2@huawei.com +Fixes: 7ac07a26dea7 ("zram: preparation for multi-zcomp support") +Signed-off-by: Liu Shixin <liushixin2@huawei.com> +Reviewed-by: Sergey Senozhatsky <senozhatsky@chromium.org> +Cc: Jens Axboe <axboe@kernel.dk> +Cc: Minchan Kim <minchan@kernel.org> +Signed-off-by: Andrew Morton <akpm@linux-foundation.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/block/zram/zram_drv.c | 5 ++--- + 1 file changed, 2 insertions(+), 3 deletions(-) + +diff --git a/drivers/block/zram/zram_drv.c b/drivers/block/zram/zram_drv.c +index b742dc246b0c1..e682797cdee78 100644 +--- a/drivers/block/zram/zram_drv.c ++++ b/drivers/block/zram/zram_drv.c +@@ -2397,6 +2397,8 @@ static int zram_add(void) + zram->disk->private_data = zram; + snprintf(zram->disk->disk_name, 16, "zram%d", device_id); + atomic_set(&zram->pp_in_progress, 0); ++ zram_comp_params_reset(zram); ++ comp_algorithm_set(zram, ZRAM_PRIMARY_COMP, default_compressor); + + /* Actual capacity set using sysfs (/sys/block/zram<id>/disksize */ + set_capacity(zram->disk, 0); +@@ -2404,9 +2406,6 @@ static int zram_add(void) + if (ret) + goto out_cleanup_disk; + +- zram_comp_params_reset(zram); +- comp_algorithm_set(zram, ZRAM_PRIMARY_COMP, default_compressor); +- + zram_debugfs_register(zram); + pr_info("Added device: %s\n", zram->disk->disk_name); + return device_id; +-- +2.43.0 + diff --git a/queue-6.12/zram-permit-only-one-post-processing-operation-at-a-.patch b/queue-6.12/zram-permit-only-one-post-processing-operation-at-a-.patch new file mode 100644 index 00000000000..9c0cac28de2 --- /dev/null +++ b/queue-6.12/zram-permit-only-one-post-processing-operation-at-a-.patch @@ -0,0 +1,145 @@ +From 4765419ecef2e1c673d628f0236a6868a7725979 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Tue, 17 Sep 2024 11:09:07 +0900 +Subject: zram: permit only one post-processing operation at a time + +From: Sergey Senozhatsky <senozhatsky@chromium.org> + +[ Upstream commit 58652f2b6d21f2874c9f060165ec7e03e8b1fc71 ] + +Both recompress and writeback soon will unlock slots during processing, +which makes things too complex wrt possible race-conditions. We still +want to clear PP_SLOT in slot_free, because this is how we figure out that +slot that was selected for post-processing has been released under us and +when we start post-processing we check if slot still has PP_SLOT set. At +the same time, theoretically, we can have something like this: + +CPU0 CPU1 + +recompress +scan slots +set PP_SLOT +unlock slot + slot_free + clear PP_SLOT + + allocate PP_SLOT + writeback + scan slots + set PP_SLOT + unlock slot +select PP-slot +test PP_SLOT + +So recompress will not detect that slot has been re-used and re-selected +for concurrent writeback post-processing. + +Make sure that we only permit on post-processing operation at a time. So +now recompress and writeback post-processing don't race against each +other, we only need to handle slot re-use (slot_free and write), which is +handled individually by each pp operation. + +Having recompress and writeback competing for the same slots is not +exactly good anyway (can't imagine anyone doing that). + +Link: https://lkml.kernel.org/r/20240917021020.883356-3-senozhatsky@chromium.org +Signed-off-by: Sergey Senozhatsky <senozhatsky@chromium.org> +Cc: Minchan Kim <minchan@kernel.org> +Signed-off-by: Andrew Morton <akpm@linux-foundation.org> +Stable-dep-of: f364cdeb3893 ("zram: fix NULL pointer in comp_algorithm_show()") +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + Documentation/admin-guide/blockdev/zram.rst | 2 ++ + drivers/block/zram/zram_drv.c | 16 ++++++++++++++++ + drivers/block/zram/zram_drv.h | 1 + + 3 files changed, 19 insertions(+) + +diff --git a/Documentation/admin-guide/blockdev/zram.rst b/Documentation/admin-guide/blockdev/zram.rst +index 678d70d6e1c3a..714a5171bfc0b 100644 +--- a/Documentation/admin-guide/blockdev/zram.rst ++++ b/Documentation/admin-guide/blockdev/zram.rst +@@ -47,6 +47,8 @@ The list of possible return codes: + -ENOMEM zram was not able to allocate enough memory to fulfil your + needs. + -EINVAL invalid input has been provided. ++-EAGAIN re-try operation later (e.g. when attempting to run recompress ++ and writeback simultaneously). + ======== ============================================================= + + If you use 'echo', the returned value is set by the 'echo' utility, +diff --git a/drivers/block/zram/zram_drv.c b/drivers/block/zram/zram_drv.c +index ad9c9bc3ccfc5..b742dc246b0c1 100644 +--- a/drivers/block/zram/zram_drv.c ++++ b/drivers/block/zram/zram_drv.c +@@ -626,6 +626,12 @@ static ssize_t writeback_store(struct device *dev, + goto release_init_lock; + } + ++ /* Do not permit concurrent post-processing actions. */ ++ if (atomic_xchg(&zram->pp_in_progress, 1)) { ++ up_read(&zram->init_lock); ++ return -EAGAIN; ++ } ++ + if (!zram->backing_dev) { + ret = -ENODEV; + goto release_init_lock; +@@ -752,6 +758,7 @@ static ssize_t writeback_store(struct device *dev, + free_block_bdev(zram, blk_idx); + __free_page(page); + release_init_lock: ++ atomic_set(&zram->pp_in_progress, 0); + up_read(&zram->init_lock); + + return ret; +@@ -1881,6 +1888,12 @@ static ssize_t recompress_store(struct device *dev, + goto release_init_lock; + } + ++ /* Do not permit concurrent post-processing actions. */ ++ if (atomic_xchg(&zram->pp_in_progress, 1)) { ++ up_read(&zram->init_lock); ++ return -EAGAIN; ++ } ++ + if (algo) { + bool found = false; + +@@ -1948,6 +1961,7 @@ static ssize_t recompress_store(struct device *dev, + __free_page(page); + + release_init_lock: ++ atomic_set(&zram->pp_in_progress, 0); + up_read(&zram->init_lock); + return ret; + } +@@ -2144,6 +2158,7 @@ static void zram_reset_device(struct zram *zram) + zram->disksize = 0; + zram_destroy_comps(zram); + memset(&zram->stats, 0, sizeof(zram->stats)); ++ atomic_set(&zram->pp_in_progress, 0); + reset_bdev(zram); + + comp_algorithm_set(zram, ZRAM_PRIMARY_COMP, default_compressor); +@@ -2381,6 +2396,7 @@ static int zram_add(void) + zram->disk->fops = &zram_devops; + zram->disk->private_data = zram; + snprintf(zram->disk->disk_name, 16, "zram%d", device_id); ++ atomic_set(&zram->pp_in_progress, 0); + + /* Actual capacity set using sysfs (/sys/block/zram<id>/disksize */ + set_capacity(zram->disk, 0); +diff --git a/drivers/block/zram/zram_drv.h b/drivers/block/zram/zram_drv.h +index cfc8c059db636..8acf9d2ee42b8 100644 +--- a/drivers/block/zram/zram_drv.h ++++ b/drivers/block/zram/zram_drv.h +@@ -139,5 +139,6 @@ struct zram { + #ifdef CONFIG_ZRAM_MEMORY_TRACKING + struct dentry *debugfs_dir; + #endif ++ atomic_t pp_in_progress; + }; + #endif +-- +2.43.0 + diff --git a/queue-6.12/zram-zram_def_comp-should-depend-on-zram.patch b/queue-6.12/zram-zram_def_comp-should-depend-on-zram.patch new file mode 100644 index 00000000000..6eefb7d59e0 --- /dev/null +++ b/queue-6.12/zram-zram_def_comp-should-depend-on-zram.patch @@ -0,0 +1,44 @@ +From d7deef7bf177777691073e38d9a032c8ac72f8e7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Tue, 5 Nov 2024 12:50:35 +0100 +Subject: zram: ZRAM_DEF_COMP should depend on ZRAM + +From: Geert Uytterhoeven <geert@linux-m68k.org> + +[ Upstream commit 9f3310ccc71efff041fed3f8be5ad19b0feab30b ] + +When Compressed RAM block device support is disabled, the +CONFIG_ZRAM_DEF_COMP symbol still ends up in the generated config file: + + CONFIG_ZRAM_DEF_COMP="unset-value" + +While this causes no real harm, avoid polluting the config file by +adding a dependency on ZRAM. + +Link: https://lkml.kernel.org/r/64e05bad68a9bd5cc322efd114a04d25de525940.1730807319.git.geert@linux-m68k.org +Fixes: 917a59e81c34 ("zram: introduce custom comp backends API") +Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org> +Reviewed-by: Sergey Senozhatsky <senozhatsky@chromium.org> +Cc: Jens Axboe <axboe@kernel.dk> +Cc: Minchan Kim <minchan@kernel.org> +Signed-off-by: Andrew Morton <akpm@linux-foundation.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/block/zram/Kconfig | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/block/zram/Kconfig b/drivers/block/zram/Kconfig +index 6aea609b795c2..402b7b1758632 100644 +--- a/drivers/block/zram/Kconfig ++++ b/drivers/block/zram/Kconfig +@@ -94,6 +94,7 @@ endchoice + + config ZRAM_DEF_COMP + string ++ depends on ZRAM + default "lzo-rle" if ZRAM_DEF_COMP_LZORLE + default "lzo" if ZRAM_DEF_COMP_LZO + default "lz4" if ZRAM_DEF_COMP_LZ4 +-- +2.43.0 +