]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
6.6-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 30 Nov 2023 14:37:43 +0000 (14:37 +0000)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 30 Nov 2023 14:37:43 +0000 (14:37 +0000)
added patches:
acpi-pm-add-acpi_device_fix_up_power_children-function.patch
acpi-processor_idle-use-raw_safe_halt-in-acpi_idle_play_dead.patch
acpi-resource-skip-irq-override-on-asus-expertbook-b1402cva.patch
acpi-video-use-acpi_device_fix_up_power_children.patch
bcache-fixup-multi-threaded-bch_sectors_dirty_init-wake-up-race.patch
bcache-replace-a-mistaken-is_err-by-is_err_or_null-in-btree_gc_coalesce.patch
drm-ast-disconnect-bmc-if-physical-connector-is-connected.patch
drm-msm-dpu-add-missing-safe_lut_tbl-in-sc8280xp-catalog.patch
dt-bindings-usb-microchip-usb5744-add-second-supply.patch
hv_netvsc-fix-race-of-netvsc-and-vf-register_netdevice.patch
hv_netvsc-fix-race-of-register_netdevice_notifier-and-vf-register.patch
hv_netvsc-mark-vf-as-slave-before-exposing-it-to-user-mode.patch
io_uring-fix-off-by-one-bvec-index.patch
io_uring-fs-consider-link-flags-when-getting-path-for-linkat.patch
kselftest-arm64-fix-output-formatting-for-za-fork.patch
md-fix-bi_status-reporting-in-md_end_clone_io.patch
platform-x86-amd-pmc-adjust-getting-dram-size-behavior.patch
platform-x86-hp-bioscfg-fix-error-handling-in-hp_add_other_attributes.patch
platform-x86-hp-bioscfg-move-mutex_lock-down-in-hp_add_other_attributes.patch
platform-x86-hp-bioscfg-simplify-return-check-in-hp_add_other_attributes.patch
platform-x86-ideapad-laptop-set-max_brightness-before-using-it.patch
revert-phy-realtek-usb-add-driver-for-the-realtek-soc-usb-2.0-phy.patch
revert-phy-realtek-usb-add-driver-for-the-realtek-soc-usb-3.0-phy.patch
revert-usb-phy-add-usb-phy-notify-port-status-api.patch
s390-dasd-protect-device-queue-against-concurrent-access.patch
swiotlb-xen-provide-the-max_mapping_size-method.patch
thunderbolt-set-lane-bonding-bit-only-for-downstream-port.patch
tls-fix-null-deref-on-tls_sw_splice_eof-with-empty-record.patch
usb-misc-onboard-hub-add-support-for-microchip-usb5744.patch
usb-serial-option-add-luat-air72-u-series-products.patch

31 files changed:
queue-6.6/acpi-pm-add-acpi_device_fix_up_power_children-function.patch [new file with mode: 0644]
queue-6.6/acpi-processor_idle-use-raw_safe_halt-in-acpi_idle_play_dead.patch [new file with mode: 0644]
queue-6.6/acpi-resource-skip-irq-override-on-asus-expertbook-b1402cva.patch [new file with mode: 0644]
queue-6.6/acpi-video-use-acpi_device_fix_up_power_children.patch [new file with mode: 0644]
queue-6.6/bcache-fixup-multi-threaded-bch_sectors_dirty_init-wake-up-race.patch [new file with mode: 0644]
queue-6.6/bcache-replace-a-mistaken-is_err-by-is_err_or_null-in-btree_gc_coalesce.patch [new file with mode: 0644]
queue-6.6/drm-ast-disconnect-bmc-if-physical-connector-is-connected.patch [new file with mode: 0644]
queue-6.6/drm-msm-dpu-add-missing-safe_lut_tbl-in-sc8280xp-catalog.patch [new file with mode: 0644]
queue-6.6/dt-bindings-usb-microchip-usb5744-add-second-supply.patch [new file with mode: 0644]
queue-6.6/hv_netvsc-fix-race-of-netvsc-and-vf-register_netdevice.patch [new file with mode: 0644]
queue-6.6/hv_netvsc-fix-race-of-register_netdevice_notifier-and-vf-register.patch [new file with mode: 0644]
queue-6.6/hv_netvsc-mark-vf-as-slave-before-exposing-it-to-user-mode.patch [new file with mode: 0644]
queue-6.6/io_uring-fix-off-by-one-bvec-index.patch [new file with mode: 0644]
queue-6.6/io_uring-fs-consider-link-flags-when-getting-path-for-linkat.patch [new file with mode: 0644]
queue-6.6/kselftest-arm64-fix-output-formatting-for-za-fork.patch [new file with mode: 0644]
queue-6.6/md-fix-bi_status-reporting-in-md_end_clone_io.patch [new file with mode: 0644]
queue-6.6/platform-x86-amd-pmc-adjust-getting-dram-size-behavior.patch [new file with mode: 0644]
queue-6.6/platform-x86-hp-bioscfg-fix-error-handling-in-hp_add_other_attributes.patch [new file with mode: 0644]
queue-6.6/platform-x86-hp-bioscfg-move-mutex_lock-down-in-hp_add_other_attributes.patch [new file with mode: 0644]
queue-6.6/platform-x86-hp-bioscfg-simplify-return-check-in-hp_add_other_attributes.patch [new file with mode: 0644]
queue-6.6/platform-x86-ideapad-laptop-set-max_brightness-before-using-it.patch [new file with mode: 0644]
queue-6.6/revert-phy-realtek-usb-add-driver-for-the-realtek-soc-usb-2.0-phy.patch [new file with mode: 0644]
queue-6.6/revert-phy-realtek-usb-add-driver-for-the-realtek-soc-usb-3.0-phy.patch [new file with mode: 0644]
queue-6.6/revert-usb-phy-add-usb-phy-notify-port-status-api.patch [new file with mode: 0644]
queue-6.6/s390-dasd-protect-device-queue-against-concurrent-access.patch [new file with mode: 0644]
queue-6.6/series
queue-6.6/swiotlb-xen-provide-the-max_mapping_size-method.patch [new file with mode: 0644]
queue-6.6/thunderbolt-set-lane-bonding-bit-only-for-downstream-port.patch [new file with mode: 0644]
queue-6.6/tls-fix-null-deref-on-tls_sw_splice_eof-with-empty-record.patch [new file with mode: 0644]
queue-6.6/usb-misc-onboard-hub-add-support-for-microchip-usb5744.patch [new file with mode: 0644]
queue-6.6/usb-serial-option-add-luat-air72-u-series-products.patch [new file with mode: 0644]

diff --git a/queue-6.6/acpi-pm-add-acpi_device_fix_up_power_children-function.patch b/queue-6.6/acpi-pm-add-acpi_device_fix_up_power_children-function.patch
new file mode 100644 (file)
index 0000000..a2e999f
--- /dev/null
@@ -0,0 +1,54 @@
+From 37ba91a82e3b9de35f64348c62b5ec7d74e3a41c Mon Sep 17 00:00:00 2001
+From: Hans de Goede <hdegoede@redhat.com>
+Date: Sun, 12 Nov 2023 21:36:26 +0100
+Subject: ACPI: PM: Add acpi_device_fix_up_power_children() function
+
+From: Hans de Goede <hdegoede@redhat.com>
+
+commit 37ba91a82e3b9de35f64348c62b5ec7d74e3a41c upstream.
+
+In some cases it is necessary to fix-up the power-state of an ACPI
+device's children without touching the ACPI device itself add
+a new acpi_device_fix_up_power_children() function for this.
+
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+Cc: 6.6+ <stable@vger.kernel.org> # 6.6+
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/acpi/device_pm.c |   13 +++++++++++++
+ include/acpi/acpi_bus.h  |    1 +
+ 2 files changed, 14 insertions(+)
+
+--- a/drivers/acpi/device_pm.c
++++ b/drivers/acpi/device_pm.c
+@@ -397,6 +397,19 @@ void acpi_device_fix_up_power_extended(s
+ }
+ EXPORT_SYMBOL_GPL(acpi_device_fix_up_power_extended);
++/**
++ * acpi_device_fix_up_power_children - Force a device's children into D0.
++ * @adev: Parent device object whose children's power state is to be fixed up.
++ *
++ * Call acpi_device_fix_up_power() for @adev's children so long as they
++ * are reported as present and enabled.
++ */
++void acpi_device_fix_up_power_children(struct acpi_device *adev)
++{
++      acpi_dev_for_each_child(adev, fix_up_power_if_applicable, NULL);
++}
++EXPORT_SYMBOL_GPL(acpi_device_fix_up_power_children);
++
+ int acpi_device_update_power(struct acpi_device *device, int *state_p)
+ {
+       int state;
+--- a/include/acpi/acpi_bus.h
++++ b/include/acpi/acpi_bus.h
+@@ -539,6 +539,7 @@ int acpi_device_set_power(struct acpi_de
+ int acpi_bus_init_power(struct acpi_device *device);
+ int acpi_device_fix_up_power(struct acpi_device *device);
+ void acpi_device_fix_up_power_extended(struct acpi_device *adev);
++void acpi_device_fix_up_power_children(struct acpi_device *adev);
+ int acpi_bus_update_power(acpi_handle handle, int *state_p);
+ int acpi_device_update_power(struct acpi_device *device, int *state_p);
+ bool acpi_bus_power_manageable(acpi_handle handle);
diff --git a/queue-6.6/acpi-processor_idle-use-raw_safe_halt-in-acpi_idle_play_dead.patch b/queue-6.6/acpi-processor_idle-use-raw_safe_halt-in-acpi_idle_play_dead.patch
new file mode 100644 (file)
index 0000000..80bb8c1
--- /dev/null
@@ -0,0 +1,46 @@
+From 9bb69ba4c177dccaa1f5b5cbdf80b67813328348 Mon Sep 17 00:00:00 2001
+From: David Woodhouse <dwmw@amazon.co.uk>
+Date: Fri, 27 Oct 2023 19:36:51 +0100
+Subject: ACPI: processor_idle: use raw_safe_halt() in acpi_idle_play_dead()
+
+From: David Woodhouse <dwmw@amazon.co.uk>
+
+commit 9bb69ba4c177dccaa1f5b5cbdf80b67813328348 upstream.
+
+Xen HVM guests were observed taking triple-faults when attempting to
+online a previously offlined vCPU.
+
+Investigation showed that the fault was coming from a failing call
+to lockdep_assert_irqs_disabled(), in load_current_idt() which was
+too early in the CPU bringup to actually catch the exception and
+report the failure cleanly.
+
+This was a false positive, caused by acpi_idle_play_dead() setting
+the per-cpu hardirqs_enabled flag by calling safe_halt(). Switch it
+to use raw_safe_halt() instead, which doesn't do so.
+
+Signed-off-by: David Woodhouse <dwmw@amazon.co.uk>
+Acked-by: Peter Zijlstra (Intel) <peterz@infradead.org>
+Cc: 6.6+ <stable@vger.kernel.org> # 6.6+
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/acpi/processor_idle.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c
+index 3a34a8c425fe..55437f5e0c3a 100644
+--- a/drivers/acpi/processor_idle.c
++++ b/drivers/acpi/processor_idle.c
+@@ -592,7 +592,7 @@ static int acpi_idle_play_dead(struct cpuidle_device *dev, int index)
+       while (1) {
+               if (cx->entry_method == ACPI_CSTATE_HALT)
+-                      safe_halt();
++                      raw_safe_halt();
+               else if (cx->entry_method == ACPI_CSTATE_SYSTEMIO) {
+                       io_idle(cx->address);
+               } else
+-- 
+2.43.0
+
diff --git a/queue-6.6/acpi-resource-skip-irq-override-on-asus-expertbook-b1402cva.patch b/queue-6.6/acpi-resource-skip-irq-override-on-asus-expertbook-b1402cva.patch
new file mode 100644 (file)
index 0000000..433ba59
--- /dev/null
@@ -0,0 +1,41 @@
+From bd911485294a6f0596e4592ed442438015cffc8a Mon Sep 17 00:00:00 2001
+From: Hans de Goede <hdegoede@redhat.com>
+Date: Wed, 15 Nov 2023 19:02:22 +0100
+Subject: ACPI: resource: Skip IRQ override on ASUS ExpertBook B1402CVA
+
+From: Hans de Goede <hdegoede@redhat.com>
+
+commit bd911485294a6f0596e4592ed442438015cffc8a upstream.
+
+Like various other ASUS ExpertBook-s, the ASUS ExpertBook B1402CVA
+has an ACPI DSDT table that describes IRQ 1 as ActiveLow while
+the kernel overrides it to EdgeHigh.
+
+This prevents the keyboard from working. To fix this issue, add this laptop
+to the skip_override_table so that the kernel does not override IRQ 1.
+
+Closes: https://bugzilla.kernel.org/show_bug.cgi?id=218114
+Cc: All applicable <stable@vger.kernel.org>
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/acpi/resource.c |    7 +++++++
+ 1 file changed, 7 insertions(+)
+
+--- a/drivers/acpi/resource.c
++++ b/drivers/acpi/resource.c
+@@ -447,6 +447,13 @@ static const struct dmi_system_id asus_l
+               },
+       },
+       {
++              /* Asus ExpertBook B1402CVA */
++              .matches = {
++                      DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
++                      DMI_MATCH(DMI_BOARD_NAME, "B1402CVA"),
++              },
++      },
++      {
+               .ident = "Asus ExpertBook B1502CBA",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
diff --git a/queue-6.6/acpi-video-use-acpi_device_fix_up_power_children.patch b/queue-6.6/acpi-video-use-acpi_device_fix_up_power_children.patch
new file mode 100644 (file)
index 0000000..4997c43
--- /dev/null
@@ -0,0 +1,54 @@
+From c93695494606326d7fd72b46a2a657139ccb0dec Mon Sep 17 00:00:00 2001
+From: Hans de Goede <hdegoede@redhat.com>
+Date: Sun, 12 Nov 2023 21:36:27 +0100
+Subject: ACPI: video: Use acpi_device_fix_up_power_children()
+
+From: Hans de Goede <hdegoede@redhat.com>
+
+commit c93695494606326d7fd72b46a2a657139ccb0dec upstream.
+
+Commit 89c290ea7589 ("ACPI: video: Put ACPI video and its child devices
+into D0 on boot") introduced calling acpi_device_fix_up_power_extended()
+on the video card for which the ACPI video bus is the companion device.
+
+This unnecessarily touches the power-state of the GPU itself, while
+the issue it tries to address only requires calling _PS0 on the child
+devices.
+
+Touching the power-state of the GPU itself is causing suspend / resume
+issues on e.g. a Lenovo ThinkPad W530.
+
+Instead use acpi_device_fix_up_power_children(), which only touches
+the child devices, to fix this.
+
+Fixes: 89c290ea7589 ("ACPI: video: Put ACPI video and its child devices into D0 on boot")
+Reported-by: Owen T. Heisler <writer@owenh.net>
+Closes: https://lore.kernel.org/regressions/9f36fb06-64c4-4264-aaeb-4e1289e764c4@owenh.net/
+Closes: https://gitlab.freedesktop.org/drm/nouveau/-/issues/273
+Closes: https://bugzilla.kernel.org/show_bug.cgi?id=218124
+Tested-by: Kai-Heng Feng <kai.heng.feng@canonical.com>
+Tested-by: Owen T. Heisler <writer@owenh.net>
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+Cc: 6.6+ <stable@vger.kernel.org> # 6.6+
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/acpi/acpi_video.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/acpi/acpi_video.c b/drivers/acpi/acpi_video.c
+index 0b7a01f38b65..d321ca7160d9 100644
+--- a/drivers/acpi/acpi_video.c
++++ b/drivers/acpi/acpi_video.c
+@@ -2031,7 +2031,7 @@ static int acpi_video_bus_add(struct acpi_device *device)
+        * HP ZBook Fury 16 G10 requires ACPI video's child devices have _PS0
+        * evaluated to have functional panel brightness control.
+        */
+-      acpi_device_fix_up_power_extended(device);
++      acpi_device_fix_up_power_children(device);
+       pr_info("%s [%s] (multi-head: %s  rom: %s  post: %s)\n",
+              ACPI_VIDEO_DEVICE_NAME, acpi_device_bid(device),
+-- 
+2.43.0
+
diff --git a/queue-6.6/bcache-fixup-multi-threaded-bch_sectors_dirty_init-wake-up-race.patch b/queue-6.6/bcache-fixup-multi-threaded-bch_sectors_dirty_init-wake-up-race.patch
new file mode 100644 (file)
index 0000000..f836691
--- /dev/null
@@ -0,0 +1,124 @@
+From 2faac25d7958c4761bb8cec54adb79f806783ad6 Mon Sep 17 00:00:00 2001
+From: Mingzhe Zou <mingzhe.zou@easystack.cn>
+Date: Mon, 20 Nov 2023 13:25:00 +0800
+Subject: bcache: fixup multi-threaded bch_sectors_dirty_init() wake-up race
+
+From: Mingzhe Zou <mingzhe.zou@easystack.cn>
+
+commit 2faac25d7958c4761bb8cec54adb79f806783ad6 upstream.
+
+We get a kernel crash about "unable to handle kernel paging request":
+
+```dmesg
+[368033.032005] BUG: unable to handle kernel paging request at ffffffffad9ae4b5
+[368033.032007] PGD fc3a0d067 P4D fc3a0d067 PUD fc3a0e063 PMD 8000000fc38000e1
+[368033.032012] Oops: 0003 [#1] SMP PTI
+[368033.032015] CPU: 23 PID: 55090 Comm: bch_dirtcnt[0] Kdump: loaded Tainted: G           OE    --------- -  - 4.18.0-147.5.1.es8_24.x86_64 #1
+[368033.032017] Hardware name: Tsinghua Tongfang THTF Chaoqiang Server/072T6D, BIOS 2.4.3 01/17/2017
+[368033.032027] RIP: 0010:native_queued_spin_lock_slowpath+0x183/0x1d0
+[368033.032029] Code: 8b 02 48 85 c0 74 f6 48 89 c1 eb d0 c1 e9 12 83 e0
+03 83 e9 01 48 c1 e0 05 48 63 c9 48 05 c0 3d 02 00 48 03 04 cd 60 68 93
+ad <48> 89 10 8b 42 08 85 c0 75 09 f3 90 8b 42 08 85 c0 74 f7 48 8b 02
+[368033.032031] RSP: 0018:ffffbb48852abe00 EFLAGS: 00010082
+[368033.032032] RAX: ffffffffad9ae4b5 RBX: 0000000000000246 RCX: 0000000000003bf3
+[368033.032033] RDX: ffff97b0ff8e3dc0 RSI: 0000000000600000 RDI: ffffbb4884743c68
+[368033.032034] RBP: 0000000000000001 R08: 0000000000000000 R09: 000007ffffffffff
+[368033.032035] R10: ffffbb486bb01000 R11: 0000000000000001 R12: ffffffffc068da70
+[368033.032036] R13: 0000000000000003 R14: 0000000000000000 R15: 0000000000000000
+[368033.032038] FS:  0000000000000000(0000) GS:ffff97b0ff8c0000(0000) knlGS:0000000000000000
+[368033.032039] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+[368033.032040] CR2: ffffffffad9ae4b5 CR3: 0000000fc3a0a002 CR4: 00000000003626e0
+[368033.032042] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
+[368033.032043] bcache: bch_cached_dev_attach() Caching rbd479 as bcache462 on set 8cff3c36-4a76-4242-afaa-7630206bc70b
+[368033.032045] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
+[368033.032046] Call Trace:
+[368033.032054]  _raw_spin_lock_irqsave+0x32/0x40
+[368033.032061]  __wake_up_common_lock+0x63/0xc0
+[368033.032073]  ? bch_ptr_invalid+0x10/0x10 [bcache]
+[368033.033502]  bch_dirty_init_thread+0x14c/0x160 [bcache]
+[368033.033511]  ? read_dirty_submit+0x60/0x60 [bcache]
+[368033.033516]  kthread+0x112/0x130
+[368033.033520]  ? kthread_flush_work_fn+0x10/0x10
+[368033.034505]  ret_from_fork+0x35/0x40
+```
+
+The crash occurred when call wake_up(&state->wait), and then we want
+to look at the value in the state. However, bch_sectors_dirty_init()
+is not found in the stack of any task. Since state is allocated on
+the stack, we guess that bch_sectors_dirty_init() has exited, causing
+bch_dirty_init_thread() to be unable to handle kernel paging request.
+
+In order to verify this idea, we added some printing information during
+wake_up(&state->wait). We find that "wake up" is printed twice, however
+we only expect the last thread to wake up once.
+
+```dmesg
+[  994.641004] alcache: bch_dirty_init_thread() wake up
+[  994.641018] alcache: bch_dirty_init_thread() wake up
+[  994.641523] alcache: bch_sectors_dirty_init() init exit
+```
+
+There is a race. If bch_sectors_dirty_init() exits after the first wake
+up, the second wake up will trigger this bug("unable to handle kernel
+paging request").
+
+Proceed as follows:
+
+bch_sectors_dirty_init
+    kthread_run ==============> bch_dirty_init_thread(bch_dirtcnt[0])
+            ...                         ...
+    atomic_inc(&state.started)          ...
+            ...                         ...
+    atomic_read(&state.enough)          ...
+            ...                 atomic_set(&state->enough, 1)
+    kthread_run ======================================================> bch_dirty_init_thread(bch_dirtcnt[1])
+            ...                 atomic_dec_and_test(&state->started)            ...
+    atomic_inc(&state.started)          ...                                     ...
+            ...                 wake_up(&state->wait)                           ...
+    atomic_read(&state.enough)                                          atomic_dec_and_test(&state->started)
+            ...                                                                 ...
+    wait_event(state.wait, atomic_read(&state.started) == 0)                    ...
+    return                                                                      ...
+                                                                        wake_up(&state->wait)
+
+We believe it is very common to wake up twice if there is no dirty, but
+crash is an extremely low probability event. It's hard for us to reproduce
+this issue. We attached and detached continuously for a week, with a total
+of more than one million attaches and only one crash.
+
+Putting atomic_inc(&state.started) before kthread_run() can avoid waking
+up twice.
+
+Fixes: b144e45fc576 ("bcache: make bch_sectors_dirty_init() to be multithreaded")
+Signed-off-by: Mingzhe Zou <mingzhe.zou@easystack.cn>
+Cc:  <stable@vger.kernel.org>
+Signed-off-by: Coly Li <colyli@suse.de>
+Link: https://lore.kernel.org/r/20231120052503.6122-8-colyli@suse.de
+Signed-off-by: Jens Axboe <axboe@kernel.dk>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/md/bcache/writeback.c |    3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/drivers/md/bcache/writeback.c
++++ b/drivers/md/bcache/writeback.c
+@@ -1014,17 +1014,18 @@ void bch_sectors_dirty_init(struct bcach
+               if (atomic_read(&state.enough))
+                       break;
++              atomic_inc(&state.started);
+               state.infos[i].state = &state;
+               state.infos[i].thread =
+                       kthread_run(bch_dirty_init_thread, &state.infos[i],
+                                   "bch_dirtcnt[%d]", i);
+               if (IS_ERR(state.infos[i].thread)) {
+                       pr_err("fails to run thread bch_dirty_init[%d]\n", i);
++                      atomic_dec(&state.started);
+                       for (--i; i >= 0; i--)
+                               kthread_stop(state.infos[i].thread);
+                       goto out;
+               }
+-              atomic_inc(&state.started);
+       }
+ out:
diff --git a/queue-6.6/bcache-replace-a-mistaken-is_err-by-is_err_or_null-in-btree_gc_coalesce.patch b/queue-6.6/bcache-replace-a-mistaken-is_err-by-is_err_or_null-in-btree_gc_coalesce.patch
new file mode 100644 (file)
index 0000000..c332c1d
--- /dev/null
@@ -0,0 +1,52 @@
+From f72f4312d4388376fc8a1f6cf37cb21a0d41758b Mon Sep 17 00:00:00 2001
+From: Coly Li <colyli@suse.de>
+Date: Mon, 20 Nov 2023 13:25:01 +0800
+Subject: bcache: replace a mistaken IS_ERR() by IS_ERR_OR_NULL() in btree_gc_coalesce()
+
+From: Coly Li <colyli@suse.de>
+
+commit f72f4312d4388376fc8a1f6cf37cb21a0d41758b upstream.
+
+Commit 028ddcac477b ("bcache: Remove unnecessary NULL point check in
+node allocations") do the following change inside btree_gc_coalesce(),
+
+31 @@ -1340,7 +1340,7 @@ static int btree_gc_coalesce(
+32         memset(new_nodes, 0, sizeof(new_nodes));
+33         closure_init_stack(&cl);
+34
+35 -       while (nodes < GC_MERGE_NODES && !IS_ERR_OR_NULL(r[nodes].b))
+36 +       while (nodes < GC_MERGE_NODES && !IS_ERR(r[nodes].b))
+37                 keys += r[nodes++].keys;
+38
+39         blocks = btree_default_blocks(b->c) * 2 / 3;
+
+At line 35 the original r[nodes].b is not always allocatored from
+__bch_btree_node_alloc(), and possibly initialized as NULL pointer by
+caller of btree_gc_coalesce(). Therefore the change at line 36 is not
+correct.
+
+This patch replaces the mistaken IS_ERR() by IS_ERR_OR_NULL() to avoid
+potential issue.
+
+Fixes: 028ddcac477b ("bcache: Remove unnecessary NULL point check in node allocations")
+Cc:  <stable@vger.kernel.org> # 6.5+
+Cc: Zheng Wang <zyytlz.wz@163.com>
+Signed-off-by: Coly Li <colyli@suse.de>
+Link: https://lore.kernel.org/r/20231120052503.6122-9-colyli@suse.de
+Signed-off-by: Jens Axboe <axboe@kernel.dk>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/md/bcache/btree.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/md/bcache/btree.c
++++ b/drivers/md/bcache/btree.c
+@@ -1363,7 +1363,7 @@ static int btree_gc_coalesce(struct btre
+       memset(new_nodes, 0, sizeof(new_nodes));
+       closure_init_stack(&cl);
+-      while (nodes < GC_MERGE_NODES && !IS_ERR(r[nodes].b))
++      while (nodes < GC_MERGE_NODES && !IS_ERR_OR_NULL(r[nodes].b))
+               keys += r[nodes++].keys;
+       blocks = btree_default_blocks(b->c) * 2 / 3;
diff --git a/queue-6.6/drm-ast-disconnect-bmc-if-physical-connector-is-connected.patch b/queue-6.6/drm-ast-disconnect-bmc-if-physical-connector-is-connected.patch
new file mode 100644 (file)
index 0000000..97270d0
--- /dev/null
@@ -0,0 +1,186 @@
+From 8d6ef26501b97243ee6c16b8187c5b38cb69b77d Mon Sep 17 00:00:00 2001
+From: Thomas Zimmermann <tzimmermann@suse.de>
+Date: Thu, 16 Nov 2023 14:02:12 +0100
+Subject: drm/ast: Disconnect BMC if physical connector is connected
+
+From: Thomas Zimmermann <tzimmermann@suse.de>
+
+commit 8d6ef26501b97243ee6c16b8187c5b38cb69b77d upstream.
+
+Many user-space compositors fail with mode setting if a CRTC has
+more than one connected connector. This is the case with the BMC
+on Aspeed systems. Work around this problem by setting the BMC's
+connector status to disconnected when the physical connector has
+a display attached. This way compositors will only see one connected
+connector at a time; either the physical one or the BMC.
+
+Suggested-by: Jocelyn Falempe <jfalempe@redhat.com>
+Fixes: e329cb53b45d ("drm/ast: Add BMC virtual connector")
+Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
+Cc: <stable@vger.kernel.org> # v6.6+
+Reviewed-by: Jocelyn Falempe <jfalempe@redhat.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20231116130217.22931-1-tzimmermann@suse.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/ast/ast_drv.h  |   13 +++++++-
+ drivers/gpu/drm/ast/ast_mode.c |   62 ++++++++++++++++++++++++++++++++++++-----
+ 2 files changed, 67 insertions(+), 8 deletions(-)
+
+--- a/drivers/gpu/drm/ast/ast_drv.h
++++ b/drivers/gpu/drm/ast/ast_drv.h
+@@ -172,6 +172,17 @@ to_ast_sil164_connector(struct drm_conne
+       return container_of(connector, struct ast_sil164_connector, base);
+ }
++struct ast_bmc_connector {
++      struct drm_connector base;
++      struct drm_connector *physical_connector;
++};
++
++static inline struct ast_bmc_connector *
++to_ast_bmc_connector(struct drm_connector *connector)
++{
++      return container_of(connector, struct ast_bmc_connector, base);
++}
++
+ /*
+  * Device
+  */
+@@ -216,7 +227,7 @@ struct ast_device {
+               } astdp;
+               struct {
+                       struct drm_encoder encoder;
+-                      struct drm_connector connector;
++                      struct ast_bmc_connector bmc_connector;
+               } bmc;
+       } output;
+--- a/drivers/gpu/drm/ast/ast_mode.c
++++ b/drivers/gpu/drm/ast/ast_mode.c
+@@ -1767,6 +1767,30 @@ static const struct drm_encoder_funcs as
+       .destroy = drm_encoder_cleanup,
+ };
++static int ast_bmc_connector_helper_detect_ctx(struct drm_connector *connector,
++                                             struct drm_modeset_acquire_ctx *ctx,
++                                             bool force)
++{
++      struct ast_bmc_connector *bmc_connector = to_ast_bmc_connector(connector);
++      struct drm_connector *physical_connector = bmc_connector->physical_connector;
++
++      /*
++       * Most user-space compositors cannot handle more than one connected
++       * connector per CRTC. Hence, we only mark the BMC as connected if the
++       * physical connector is disconnected. If the physical connector's status
++       * is connected or unknown, the BMC remains disconnected. This has no
++       * effect on the output of the BMC.
++       *
++       * FIXME: Remove this logic once user-space compositors can handle more
++       *        than one connector per CRTC. The BMC should always be connected.
++       */
++
++      if (physical_connector && physical_connector->status == connector_status_disconnected)
++              return connector_status_connected;
++
++      return connector_status_disconnected;
++}
++
+ static int ast_bmc_connector_helper_get_modes(struct drm_connector *connector)
+ {
+       return drm_add_modes_noedid(connector, 4096, 4096);
+@@ -1774,6 +1798,7 @@ static int ast_bmc_connector_helper_get_
+ static const struct drm_connector_helper_funcs ast_bmc_connector_helper_funcs = {
+       .get_modes = ast_bmc_connector_helper_get_modes,
++      .detect_ctx = ast_bmc_connector_helper_detect_ctx,
+ };
+ static const struct drm_connector_funcs ast_bmc_connector_funcs = {
+@@ -1784,12 +1809,33 @@ static const struct drm_connector_funcs
+       .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
+ };
+-static int ast_bmc_output_init(struct ast_device *ast)
++static int ast_bmc_connector_init(struct drm_device *dev,
++                                struct ast_bmc_connector *bmc_connector,
++                                struct drm_connector *physical_connector)
++{
++      struct drm_connector *connector = &bmc_connector->base;
++      int ret;
++
++      ret = drm_connector_init(dev, connector, &ast_bmc_connector_funcs,
++                               DRM_MODE_CONNECTOR_VIRTUAL);
++      if (ret)
++              return ret;
++
++      drm_connector_helper_add(connector, &ast_bmc_connector_helper_funcs);
++
++      bmc_connector->physical_connector = physical_connector;
++
++      return 0;
++}
++
++static int ast_bmc_output_init(struct ast_device *ast,
++                             struct drm_connector *physical_connector)
+ {
+       struct drm_device *dev = &ast->base;
+       struct drm_crtc *crtc = &ast->crtc;
+       struct drm_encoder *encoder = &ast->output.bmc.encoder;
+-      struct drm_connector *connector = &ast->output.bmc.connector;
++      struct ast_bmc_connector *bmc_connector = &ast->output.bmc.bmc_connector;
++      struct drm_connector *connector = &bmc_connector->base;
+       int ret;
+       ret = drm_encoder_init(dev, encoder,
+@@ -1799,13 +1845,10 @@ static int ast_bmc_output_init(struct as
+               return ret;
+       encoder->possible_crtcs = drm_crtc_mask(crtc);
+-      ret = drm_connector_init(dev, connector, &ast_bmc_connector_funcs,
+-                               DRM_MODE_CONNECTOR_VIRTUAL);
++      ret = ast_bmc_connector_init(dev, bmc_connector, physical_connector);
+       if (ret)
+               return ret;
+-      drm_connector_helper_add(connector, &ast_bmc_connector_helper_funcs);
+-
+       ret = drm_connector_attach_encoder(connector, encoder);
+       if (ret)
+               return ret;
+@@ -1864,6 +1907,7 @@ static const struct drm_mode_config_func
+ int ast_mode_config_init(struct ast_device *ast)
+ {
+       struct drm_device *dev = &ast->base;
++      struct drm_connector *physical_connector = NULL;
+       int ret;
+       ret = drmm_mode_config_init(dev);
+@@ -1904,23 +1948,27 @@ int ast_mode_config_init(struct ast_devi
+               ret = ast_vga_output_init(ast);
+               if (ret)
+                       return ret;
++              physical_connector = &ast->output.vga.vga_connector.base;
+       }
+       if (ast->tx_chip_types & AST_TX_SIL164_BIT) {
+               ret = ast_sil164_output_init(ast);
+               if (ret)
+                       return ret;
++              physical_connector = &ast->output.sil164.sil164_connector.base;
+       }
+       if (ast->tx_chip_types & AST_TX_DP501_BIT) {
+               ret = ast_dp501_output_init(ast);
+               if (ret)
+                       return ret;
++              physical_connector = &ast->output.dp501.connector;
+       }
+       if (ast->tx_chip_types & AST_TX_ASTDP_BIT) {
+               ret = ast_astdp_output_init(ast);
+               if (ret)
+                       return ret;
++              physical_connector = &ast->output.astdp.connector;
+       }
+-      ret = ast_bmc_output_init(ast);
++      ret = ast_bmc_output_init(ast, physical_connector);
+       if (ret)
+               return ret;
diff --git a/queue-6.6/drm-msm-dpu-add-missing-safe_lut_tbl-in-sc8280xp-catalog.patch b/queue-6.6/drm-msm-dpu-add-missing-safe_lut_tbl-in-sc8280xp-catalog.patch
new file mode 100644 (file)
index 0000000..4e45616
--- /dev/null
@@ -0,0 +1,45 @@
+From a33b2431d11b4df137bbcfdd5a5adfa054c2479e Mon Sep 17 00:00:00 2001
+From: Bjorn Andersson <quic_bjorande@quicinc.com>
+Date: Mon, 30 Oct 2023 16:23:20 -0700
+Subject: drm/msm/dpu: Add missing safe_lut_tbl in sc8280xp catalog
+
+From: Bjorn Andersson <quic_bjorande@quicinc.com>
+
+commit a33b2431d11b4df137bbcfdd5a5adfa054c2479e upstream.
+
+During USB transfers on the SC8280XP __arm_smmu_tlb_sync() is seen to
+typically take 1-2ms to complete. As expected this results in poor
+performance, something that has been mitigated by proposing running the
+iommu in non-strict mode (boot with iommu.strict=0).
+
+This turns out to be related to the SAFE logic, and programming the QOS
+SAFE values in the DPU (per suggestion from Rob and Doug) reduces the
+TLB sync time to below 10us, which means significant less time spent
+with interrupts disabled and a significant boost in throughput.
+
+Fixes: 4a352c2fc15a ("drm/msm/dpu: Introduce SC8280XP")
+Cc: stable@vger.kernel.org
+Suggested-by: Doug Anderson <dianders@chromium.org>
+Suggested-by: Rob Clark <robdclark@chromium.org>
+Signed-off-by: Bjorn Andersson <quic_bjorande@quicinc.com>
+Tested-by: Johan Hovold <johan+linaro@kernel.org>
+Tested-by: Steev Klimaszewski <steev@kali.org>
+Reviewed-by: Abhinav Kumar <quic_abhinavk@quicinc.com>
+Patchwork: https://patchwork.freedesktop.org/patch/565094/
+Link: https://lore.kernel.org/r/20231030-sc8280xp-dpu-safe-lut-v1-1-6d485d7b428f@quicinc.com
+Signed-off-by: Abhinav Kumar <quic_abhinavk@quicinc.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_8_0_sc8280xp.h |    1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_8_0_sc8280xp.h
++++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_8_0_sc8280xp.h
+@@ -419,6 +419,7 @@ static const struct dpu_perf_cfg sc8280x
+       .min_llcc_ib = 0,
+       .min_dram_ib = 800000,
+       .danger_lut_tbl = {0xf, 0xffff, 0x0},
++      .safe_lut_tbl = {0xfe00, 0xfe00, 0xffff},
+       .qos_lut_tbl = {
+               {.nentry = ARRAY_SIZE(sc8180x_qos_linear),
+               .entries = sc8180x_qos_linear
diff --git a/queue-6.6/dt-bindings-usb-microchip-usb5744-add-second-supply.patch b/queue-6.6/dt-bindings-usb-microchip-usb5744-add-second-supply.patch
new file mode 100644 (file)
index 0000000..09a7feb
--- /dev/null
@@ -0,0 +1,45 @@
+From d0c930b745cafde8e7d25d0356c648bca669556a Mon Sep 17 00:00:00 2001
+From: Stefan Eichenberger <stefan.eichenberger@toradex.com>
+Date: Mon, 13 Nov 2023 15:59:20 +0100
+Subject: dt-bindings: usb: microchip,usb5744: Add second supply
+
+From: Stefan Eichenberger <stefan.eichenberger@toradex.com>
+
+commit d0c930b745cafde8e7d25d0356c648bca669556a upstream.
+
+The USB5744 has two power supplies one for 3V3 and one for 1V2. Add the
+second supply to the USB5744 DT binding.
+
+Signed-off-by: Stefan Eichenberger <stefan.eichenberger@toradex.com>
+Signed-off-by: Francesco Dolcini <francesco.dolcini@toradex.com>
+Acked-by: Conor Dooley <conor.dooley@microchip.com>
+Cc: stable <stable@kernel.org>
+Link: https://lore.kernel.org/r/20231113145921.30104-2-francesco@dolcini.it
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ Documentation/devicetree/bindings/usb/microchip,usb5744.yaml |    7 ++++++-
+ 1 file changed, 6 insertions(+), 1 deletion(-)
+
+--- a/Documentation/devicetree/bindings/usb/microchip,usb5744.yaml
++++ b/Documentation/devicetree/bindings/usb/microchip,usb5744.yaml
+@@ -36,7 +36,11 @@ properties:
+   vdd-supply:
+     description:
+-      VDD power supply to the hub
++      3V3 power supply to the hub
++
++  vdd2-supply:
++    description:
++      1V2 power supply to the hub
+   peer-hub:
+     $ref: /schemas/types.yaml#/definitions/phandle
+@@ -62,6 +66,7 @@ allOf:
+       properties:
+         reset-gpios: false
+         vdd-supply: false
++        vdd2-supply: false
+         peer-hub: false
+         i2c-bus: false
+     else:
diff --git a/queue-6.6/hv_netvsc-fix-race-of-netvsc-and-vf-register_netdevice.patch b/queue-6.6/hv_netvsc-fix-race-of-netvsc-and-vf-register_netdevice.patch
new file mode 100644 (file)
index 0000000..4ff4266
--- /dev/null
@@ -0,0 +1,84 @@
+From d30fb712e52964f2cf9a9c14cf67078394044837 Mon Sep 17 00:00:00 2001
+From: Haiyang Zhang <haiyangz@microsoft.com>
+Date: Sun, 19 Nov 2023 08:23:41 -0800
+Subject: hv_netvsc: fix race of netvsc and VF register_netdevice
+
+From: Haiyang Zhang <haiyangz@microsoft.com>
+
+commit d30fb712e52964f2cf9a9c14cf67078394044837 upstream.
+
+The rtnl lock also needs to be held before rndis_filter_device_add()
+which advertises nvsp_2_vsc_capability / sriov bit, and triggers
+VF NIC offering and registering. If VF NIC finished register_netdev()
+earlier it may cause name based config failure.
+
+To fix this issue, move the call to rtnl_lock() before
+rndis_filter_device_add(), so VF will be registered later than netvsc
+/ synthetic NIC, and gets a name numbered (ethX) after netvsc.
+
+Cc: stable@vger.kernel.org
+Fixes: e04e7a7bbd4b ("hv_netvsc: Fix a deadlock by getting rtnl lock earlier in netvsc_probe()")
+Reported-by: Dexuan Cui <decui@microsoft.com>
+Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
+Reviewed-by: Wojciech Drewek <wojciech.drewek@intel.com>
+Reviewed-by: Simon Horman <horms@kernel.org>
+Reviewed-by: Dexuan Cui <decui@microsoft.com>
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/hyperv/netvsc_drv.c |   25 +++++++++++++++----------
+ 1 file changed, 15 insertions(+), 10 deletions(-)
+
+--- a/drivers/net/hyperv/netvsc_drv.c
++++ b/drivers/net/hyperv/netvsc_drv.c
+@@ -2531,15 +2531,6 @@ static int netvsc_probe(struct hv_device
+               goto devinfo_failed;
+       }
+-      nvdev = rndis_filter_device_add(dev, device_info);
+-      if (IS_ERR(nvdev)) {
+-              ret = PTR_ERR(nvdev);
+-              netdev_err(net, "unable to add netvsc device (ret %d)\n", ret);
+-              goto rndis_failed;
+-      }
+-
+-      eth_hw_addr_set(net, device_info->mac_adr);
+-
+       /* We must get rtnl lock before scheduling nvdev->subchan_work,
+        * otherwise netvsc_subchan_work() can get rtnl lock first and wait
+        * all subchannels to show up, but that may not happen because
+@@ -2547,9 +2538,23 @@ static int netvsc_probe(struct hv_device
+        * -> ... -> device_add() -> ... -> __device_attach() can't get
+        * the device lock, so all the subchannels can't be processed --
+        * finally netvsc_subchan_work() hangs forever.
++       *
++       * The rtnl lock also needs to be held before rndis_filter_device_add()
++       * which advertises nvsp_2_vsc_capability / sriov bit, and triggers
++       * VF NIC offering and registering. If VF NIC finished register_netdev()
++       * earlier it may cause name based config failure.
+        */
+       rtnl_lock();
++      nvdev = rndis_filter_device_add(dev, device_info);
++      if (IS_ERR(nvdev)) {
++              ret = PTR_ERR(nvdev);
++              netdev_err(net, "unable to add netvsc device (ret %d)\n", ret);
++              goto rndis_failed;
++      }
++
++      eth_hw_addr_set(net, device_info->mac_adr);
++
+       if (nvdev->num_chn > 1)
+               schedule_work(&nvdev->subchan_work);
+@@ -2586,9 +2591,9 @@ static int netvsc_probe(struct hv_device
+       return 0;
+ register_failed:
+-      rtnl_unlock();
+       rndis_filter_device_remove(dev, nvdev);
+ rndis_failed:
++      rtnl_unlock();
+       netvsc_devinfo_put(device_info);
+ devinfo_failed:
+       free_percpu(net_device_ctx->vf_stats);
diff --git a/queue-6.6/hv_netvsc-fix-race-of-register_netdevice_notifier-and-vf-register.patch b/queue-6.6/hv_netvsc-fix-race-of-register_netdevice_notifier-and-vf-register.patch
new file mode 100644 (file)
index 0000000..8f881d1
--- /dev/null
@@ -0,0 +1,49 @@
+From 85520856466ed6bc3b1ccb013cddac70ceb437db Mon Sep 17 00:00:00 2001
+From: Haiyang Zhang <haiyangz@microsoft.com>
+Date: Sun, 19 Nov 2023 08:23:42 -0800
+Subject: hv_netvsc: Fix race of register_netdevice_notifier and VF register
+
+From: Haiyang Zhang <haiyangz@microsoft.com>
+
+commit 85520856466ed6bc3b1ccb013cddac70ceb437db upstream.
+
+If VF NIC is registered earlier, NETDEV_REGISTER event is replayed,
+but NETDEV_POST_INIT is not.
+
+Move register_netdevice_notifier() earlier, so the call back
+function is set before probing.
+
+Cc: stable@vger.kernel.org
+Fixes: e04e7a7bbd4b ("hv_netvsc: Fix a deadlock by getting rtnl lock earlier in netvsc_probe()")
+Reported-by: Dexuan Cui <decui@microsoft.com>
+Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
+Reviewed-by: Wojciech Drewek <wojciech.drewek@intel.com>
+Reviewed-by: Dexuan Cui <decui@microsoft.com>
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/hyperv/netvsc_drv.c |    9 +++++++--
+ 1 file changed, 7 insertions(+), 2 deletions(-)
+
+--- a/drivers/net/hyperv/netvsc_drv.c
++++ b/drivers/net/hyperv/netvsc_drv.c
+@@ -2793,12 +2793,17 @@ static int __init netvsc_drv_init(void)
+       }
+       netvsc_ring_bytes = ring_size * PAGE_SIZE;
++      register_netdevice_notifier(&netvsc_netdev_notifier);
++
+       ret = vmbus_driver_register(&netvsc_drv);
+       if (ret)
+-              return ret;
++              goto err_vmbus_reg;
+-      register_netdevice_notifier(&netvsc_netdev_notifier);
+       return 0;
++
++err_vmbus_reg:
++      unregister_netdevice_notifier(&netvsc_netdev_notifier);
++      return ret;
+ }
+ MODULE_LICENSE("GPL");
diff --git a/queue-6.6/hv_netvsc-mark-vf-as-slave-before-exposing-it-to-user-mode.patch b/queue-6.6/hv_netvsc-mark-vf-as-slave-before-exposing-it-to-user-mode.patch
new file mode 100644 (file)
index 0000000..b9d3d92
--- /dev/null
@@ -0,0 +1,95 @@
+From c807d6cd089d2f4951baa838081ec5ae3e2360f8 Mon Sep 17 00:00:00 2001
+From: Long Li <longli@microsoft.com>
+Date: Sun, 19 Nov 2023 08:23:43 -0800
+Subject: hv_netvsc: Mark VF as slave before exposing it to user-mode
+
+From: Long Li <longli@microsoft.com>
+
+commit c807d6cd089d2f4951baa838081ec5ae3e2360f8 upstream.
+
+When a VF is being exposed form the kernel, it should be marked as "slave"
+before exposing to the user-mode. The VF is not usable without netvsc
+running as master. The user-mode should never see a VF without the "slave"
+flag.
+
+This commit moves the code of setting the slave flag to the time before
+VF is exposed to user-mode.
+
+Cc: stable@vger.kernel.org
+Fixes: 0c195567a8f6 ("netvsc: transparent VF management")
+Signed-off-by: Long Li <longli@microsoft.com>
+Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
+Acked-by: Stephen Hemminger <stephen@networkplumber.org>
+Acked-by: Dexuan Cui <decui@microsoft.com>
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/hyperv/netvsc_drv.c |   32 +++++++++++++++++++++++---------
+ 1 file changed, 23 insertions(+), 9 deletions(-)
+
+--- a/drivers/net/hyperv/netvsc_drv.c
++++ b/drivers/net/hyperv/netvsc_drv.c
+@@ -2206,9 +2206,6 @@ static int netvsc_vf_join(struct net_dev
+               goto upper_link_failed;
+       }
+-      /* set slave flag before open to prevent IPv6 addrconf */
+-      vf_netdev->flags |= IFF_SLAVE;
+-
+       schedule_delayed_work(&ndev_ctx->vf_takeover, VF_TAKEOVER_INT);
+       call_netdevice_notifiers(NETDEV_JOIN, vf_netdev);
+@@ -2315,16 +2312,18 @@ static struct net_device *get_netvsc_bys
+       }
+-      /* Fallback path to check synthetic vf with
+-       * help of mac addr
++      /* Fallback path to check synthetic vf with help of mac addr.
++       * Because this function can be called before vf_netdev is
++       * initialized (NETDEV_POST_INIT) when its perm_addr has not been copied
++       * from dev_addr, also try to match to its dev_addr.
++       * Note: On Hyper-V and Azure, it's not possible to set a MAC address
++       * on a VF that matches to the MAC of a unrelated NETVSC device.
+        */
+       list_for_each_entry(ndev_ctx, &netvsc_dev_list, list) {
+               ndev = hv_get_drvdata(ndev_ctx->device_ctx);
+-              if (ether_addr_equal(vf_netdev->perm_addr, ndev->perm_addr)) {
+-                      netdev_notice(vf_netdev,
+-                                    "falling back to mac addr based matching\n");
++              if (ether_addr_equal(vf_netdev->perm_addr, ndev->perm_addr) ||
++                  ether_addr_equal(vf_netdev->dev_addr, ndev->perm_addr))
+                       return ndev;
+-              }
+       }
+       netdev_notice(vf_netdev,
+@@ -2332,6 +2331,19 @@ static struct net_device *get_netvsc_bys
+       return NULL;
+ }
++static int netvsc_prepare_bonding(struct net_device *vf_netdev)
++{
++      struct net_device *ndev;
++
++      ndev = get_netvsc_byslot(vf_netdev);
++      if (!ndev)
++              return NOTIFY_DONE;
++
++      /* set slave flag before open to prevent IPv6 addrconf */
++      vf_netdev->flags |= IFF_SLAVE;
++      return NOTIFY_DONE;
++}
++
+ static int netvsc_register_vf(struct net_device *vf_netdev)
+ {
+       struct net_device_context *net_device_ctx;
+@@ -2758,6 +2770,8 @@ static int netvsc_netdev_event(struct no
+               return NOTIFY_DONE;
+       switch (event) {
++      case NETDEV_POST_INIT:
++              return netvsc_prepare_bonding(event_dev);
+       case NETDEV_REGISTER:
+               return netvsc_register_vf(event_dev);
+       case NETDEV_UNREGISTER:
diff --git a/queue-6.6/io_uring-fix-off-by-one-bvec-index.patch b/queue-6.6/io_uring-fix-off-by-one-bvec-index.patch
new file mode 100644 (file)
index 0000000..2598b5c
--- /dev/null
@@ -0,0 +1,35 @@
+From d6fef34ee4d102be448146f24caf96d7b4a05401 Mon Sep 17 00:00:00 2001
+From: Keith Busch <kbusch@kernel.org>
+Date: Mon, 20 Nov 2023 14:18:31 -0800
+Subject: io_uring: fix off-by one bvec index
+
+From: Keith Busch <kbusch@kernel.org>
+
+commit d6fef34ee4d102be448146f24caf96d7b4a05401 upstream.
+
+If the offset equals the bv_len of the first registered bvec, then the
+request does not include any of that first bvec. Skip it so that drivers
+don't have to deal with a zero length bvec, which was observed to break
+NVMe's PRP list creation.
+
+Cc: stable@vger.kernel.org
+Fixes: bd11b3a391e3 ("io_uring: don't use iov_iter_advance() for fixed buffers")
+Signed-off-by: Keith Busch <kbusch@kernel.org>
+Link: https://lore.kernel.org/r/20231120221831.2646460-1-kbusch@meta.com
+Signed-off-by: Jens Axboe <axboe@kernel.dk>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ io_uring/rsrc.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/io_uring/rsrc.c
++++ b/io_uring/rsrc.c
+@@ -1261,7 +1261,7 @@ int io_import_fixed(int ddir, struct iov
+                */
+               const struct bio_vec *bvec = imu->bvec;
+-              if (offset <= bvec->bv_len) {
++              if (offset < bvec->bv_len) {
+                       /*
+                        * Note, huge pages buffers consists of one large
+                        * bvec entry and should always go this way. The other
diff --git a/queue-6.6/io_uring-fs-consider-link-flags-when-getting-path-for-linkat.patch b/queue-6.6/io_uring-fs-consider-link-flags-when-getting-path-for-linkat.patch
new file mode 100644 (file)
index 0000000..2ce747e
--- /dev/null
@@ -0,0 +1,35 @@
+From 8479063f1fbee201a8739130e816cc331b675838 Mon Sep 17 00:00:00 2001
+From: Charles Mirabile <cmirabil@redhat.com>
+Date: Mon, 20 Nov 2023 05:55:45 -0500
+Subject: io_uring/fs: consider link->flags when getting path for LINKAT
+
+From: Charles Mirabile <cmirabil@redhat.com>
+
+commit 8479063f1fbee201a8739130e816cc331b675838 upstream.
+
+In order for `AT_EMPTY_PATH` to work as expected, the fact
+that the user wants that behavior needs to make it to `getname_flags`
+or it will return ENOENT.
+
+Fixes: cf30da90bc3a ("io_uring: add support for IORING_OP_LINKAT")
+Cc:  <stable@vger.kernel.org>
+Link: https://github.com/axboe/liburing/issues/995
+Signed-off-by: Charles Mirabile <cmirabil@redhat.com>
+Link: https://lore.kernel.org/r/20231120105545.1209530-1-cmirabil@redhat.com
+Signed-off-by: Jens Axboe <axboe@kernel.dk>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ io_uring/fs.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/io_uring/fs.c
++++ b/io_uring/fs.c
+@@ -254,7 +254,7 @@ int io_linkat_prep(struct io_kiocb *req,
+       newf = u64_to_user_ptr(READ_ONCE(sqe->addr2));
+       lnk->flags = READ_ONCE(sqe->hardlink_flags);
+-      lnk->oldpath = getname(oldf);
++      lnk->oldpath = getname_uflags(oldf, lnk->flags);
+       if (IS_ERR(lnk->oldpath))
+               return PTR_ERR(lnk->oldpath);
diff --git a/queue-6.6/kselftest-arm64-fix-output-formatting-for-za-fork.patch b/queue-6.6/kselftest-arm64-fix-output-formatting-for-za-fork.patch
new file mode 100644 (file)
index 0000000..60b6aa1
--- /dev/null
@@ -0,0 +1,34 @@
+From 460e462d22542adfafd8a5bc979437df73f1cbf3 Mon Sep 17 00:00:00 2001
+From: Mark Brown <broonie@kernel.org>
+Date: Thu, 16 Nov 2023 12:52:29 +0000
+Subject: kselftest/arm64: Fix output formatting for za-fork
+
+From: Mark Brown <broonie@kernel.org>
+
+commit 460e462d22542adfafd8a5bc979437df73f1cbf3 upstream.
+
+The za-fork test does not output a newline when reporting the result of
+the one test it runs, causing the counts printed by kselftest to be
+included in the test name.  Add the newline.
+
+Fixes: 266679ffd867 ("kselftest/arm64: Convert za-fork to use kselftest.h")
+Cc: <stable@vger.kernel.org> # 6.4.x
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Link: https://lore.kernel.org/r/20231116-arm64-fix-za-fork-output-v1-1-42c03d4f5759@kernel.org
+Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ tools/testing/selftests/arm64/fp/za-fork.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/tools/testing/selftests/arm64/fp/za-fork.c
++++ b/tools/testing/selftests/arm64/fp/za-fork.c
+@@ -85,7 +85,7 @@ int main(int argc, char **argv)
+        */
+       ret = open("/proc/sys/abi/sme_default_vector_length", O_RDONLY, 0);
+       if (ret >= 0) {
+-              ksft_test_result(fork_test(), "fork_test");
++              ksft_test_result(fork_test(), "fork_test\n");
+       } else {
+               ksft_print_msg("SME not supported\n");
diff --git a/queue-6.6/md-fix-bi_status-reporting-in-md_end_clone_io.patch b/queue-6.6/md-fix-bi_status-reporting-in-md_end_clone_io.patch
new file mode 100644 (file)
index 0000000..12206ba
--- /dev/null
@@ -0,0 +1,44 @@
+From 45b478951b2ba5aea70b2850c49c1aa83aedd0d2 Mon Sep 17 00:00:00 2001
+From: Song Liu <song@kernel.org>
+Date: Fri, 17 Nov 2023 15:56:30 -0800
+Subject: md: fix bi_status reporting in md_end_clone_io
+
+From: Song Liu <song@kernel.org>
+
+commit 45b478951b2ba5aea70b2850c49c1aa83aedd0d2 upstream.
+
+md_end_clone_io() may overwrite error status in orig_bio->bi_status with
+BLK_STS_OK. This could happen when orig_bio has BIO_CHAIN (split by
+md_submit_bio => bio_split_to_limits, for example). As a result, upper
+layer may miss error reported from md (or the device) and consider the
+failed IO was successful.
+
+Fix this by only update orig_bio->bi_status when current bio reports
+error and orig_bio is BLK_STS_OK. This is the same behavior as
+__bio_chain_endio().
+
+Fixes: 10764815ff47 ("md: add io accounting for raid0 and raid5")
+Cc: stable@vger.kernel.org # v5.14+
+Reported-by: Bhanu Victor DiCara <00bvd0+linux@gmail.com>
+Closes: https://lore.kernel.org/regressions/5727380.DvuYhMxLoT@bvd0/
+Signed-off-by: Song Liu <song@kernel.org>
+Tested-by: Xiao Ni <xni@redhat.com>
+Reviewed-by: Yu Kuai <yukuai3@huawei.com>
+Acked-by: Guoqing Jiang <guoqing.jiang@linux.dev>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/md/md.c |    3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/drivers/md/md.c
++++ b/drivers/md/md.c
+@@ -8669,7 +8669,8 @@ static void md_end_clone_io(struct bio *
+       struct bio *orig_bio = md_io_clone->orig_bio;
+       struct mddev *mddev = md_io_clone->mddev;
+-      orig_bio->bi_status = bio->bi_status;
++      if (bio->bi_status && !orig_bio->bi_status)
++              orig_bio->bi_status = bio->bi_status;
+       if (md_io_clone->start_time)
+               bio_end_io_acct(orig_bio, md_io_clone->start_time);
diff --git a/queue-6.6/platform-x86-amd-pmc-adjust-getting-dram-size-behavior.patch b/queue-6.6/platform-x86-amd-pmc-adjust-getting-dram-size-behavior.patch
new file mode 100644 (file)
index 0000000..84cd09f
--- /dev/null
@@ -0,0 +1,100 @@
+From c6ea14d557343cd3af6c6be2f5a78c98bdb281bb Mon Sep 17 00:00:00 2001
+From: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
+Date: Thu, 16 Nov 2023 22:31:21 +0530
+Subject: platform/x86/amd/pmc: adjust getting DRAM size behavior
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
+
+commit c6ea14d557343cd3af6c6be2f5a78c98bdb281bb upstream.
+
+amd_pmc_get_dram_size() is used to get the DRAM size information. But
+in the current code, mailbox command to get the DRAM size info is sent
+based on the values of dev->major and dev->minor.
+
+But dev->major and dev->minor will have either junk or zero assigned to
+them until at least once a call to amd_pmc_get_smu_version() is made
+which ideally populates dev->major and dev->minor.
+
+However, adding a amd_pmc_get_smu_version() call to
+amd_pmc_get_dram_size() has a downside of elevating the boot times.
+
+After talking to the PMFW team, it's understood that the "get dram
+size" mbox command would only be supported on specific platforms (like
+Mendocino) and not all. So, adjust getting DRAM size behavior such
+that,
+
+- if running on Rembrandt or Mendocino and the underlying PMFW knows
+how to execute the "get dram size" command it shall give the custom
+dram size.
+
+- if the underlying FW does not report the dram size, we just proceed
+further and assign the default dram size.
+
+The simplest way to address this is to remove amd_pmc_get_dram_size()
+function and directly call the "get dram size" command in the
+amd_pmc_s2d_init().
+
+Reported-by: Mark Hasemeyer <markhas@chromium.org>
+Fixes: be8325fb3d8c ("platform/x86/amd: pmc: Get STB DRAM size from PMFW")
+Cc: stable@vger.kernel.org
+Suggested-by: Sanket Goswami <Sanket.Goswami@amd.com>
+Signed-off-by: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
+Link: https://lore.kernel.org/r/20231116170121.3372222-1-Shyam-sundar.S-k@amd.com
+Reviewed-by: Mario Limonciello <mario.limonciello@amd.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: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/platform/x86/amd/pmc/pmc.c |   31 ++-----------------------------
+ 1 file changed, 2 insertions(+), 29 deletions(-)
+
+--- a/drivers/platform/x86/amd/pmc/pmc.c
++++ b/drivers/platform/x86/amd/pmc/pmc.c
+@@ -912,33 +912,6 @@ static const struct pci_device_id pmc_pc
+       { }
+ };
+-static int amd_pmc_get_dram_size(struct amd_pmc_dev *dev)
+-{
+-      int ret;
+-
+-      switch (dev->cpu_id) {
+-      case AMD_CPU_ID_YC:
+-              if (!(dev->major > 90 || (dev->major == 90 && dev->minor > 39))) {
+-                      ret = -EINVAL;
+-                      goto err_dram_size;
+-              }
+-              break;
+-      default:
+-              ret = -EINVAL;
+-              goto err_dram_size;
+-      }
+-
+-      ret = amd_pmc_send_cmd(dev, S2D_DRAM_SIZE, &dev->dram_size, dev->s2d_msg_id, true);
+-      if (ret || !dev->dram_size)
+-              goto err_dram_size;
+-
+-      return 0;
+-
+-err_dram_size:
+-      dev_err(dev->dev, "DRAM size command not supported for this platform\n");
+-      return ret;
+-}
+-
+ static int amd_pmc_s2d_init(struct amd_pmc_dev *dev)
+ {
+       u32 phys_addr_low, phys_addr_hi;
+@@ -957,8 +930,8 @@ static int amd_pmc_s2d_init(struct amd_p
+               return -EIO;
+       /* Get DRAM size */
+-      ret = amd_pmc_get_dram_size(dev);
+-      if (ret)
++      ret = amd_pmc_send_cmd(dev, S2D_DRAM_SIZE, &dev->dram_size, dev->s2d_msg_id, true);
++      if (ret || !dev->dram_size)
+               dev->dram_size = S2D_TELEMETRY_DRAMBYTES_MAX;
+       /* Get STB DRAM address */
diff --git a/queue-6.6/platform-x86-hp-bioscfg-fix-error-handling-in-hp_add_other_attributes.patch b/queue-6.6/platform-x86-hp-bioscfg-fix-error-handling-in-hp_add_other_attributes.patch
new file mode 100644 (file)
index 0000000..641a528
--- /dev/null
@@ -0,0 +1,75 @@
+From f40f939917b2b4cbf18450096c0ce1c58ed59fae Mon Sep 17 00:00:00 2001
+From: Harshit Mogalapalli <harshit.m.mogalapalli@oracle.com>
+Date: Mon, 13 Nov 2023 12:07:39 -0800
+Subject: platform/x86: hp-bioscfg: Fix error handling in hp_add_other_attributes()
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Harshit Mogalapalli <harshit.m.mogalapalli@oracle.com>
+
+commit f40f939917b2b4cbf18450096c0ce1c58ed59fae upstream.
+
+'attr_name_kobj' is allocated using kzalloc, but on all the error paths
+it is not freed, hence we have a memory leak.
+
+Fix the error path before kobject_init_and_add() by adding kfree().
+
+kobject_put() must be always called after passing the object to
+kobject_init_and_add(). Only the error path which is immediately next
+to kobject_init_and_add() calls kobject_put() and not any other error
+path after it.
+
+Fix the error handling after kobject_init_and_add() by moving the
+kobject_put() into the goto label err_other_attr_init that is already
+used by all the error paths after kobject_init_and_add().
+
+Fixes: a34fc329b189 ("platform/x86: hp-bioscfg: bioscfg")
+Cc: stable@vger.kernel.org # 6.6.x: c5dbf0416000: platform/x86: hp-bioscfg: Simplify return check in hp_add_other_attributes()
+Cc: stable@vger.kernel.org # 6.6.x: 5736aa9537c9: platform/x86: hp-bioscfg: move mutex_lock() down in hp_add_other_attributes()
+Reported-by: kernel test robot <lkp@intel.com>
+Reported-by: Dan Carpenter <error27@gmail.com>
+Closes: https://lore.kernel.org/r/202309201412.on0VXJGo-lkp@intel.com/
+Signed-off-by: Harshit Mogalapalli <harshit.m.mogalapalli@oracle.com>
+[ij: Added the stable dep tags]
+Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
+Link: https://lore.kernel.org/r/20231113200742.3593548-3-harshit.m.mogalapalli@oracle.com
+Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/platform/x86/hp/hp-bioscfg/bioscfg.c | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/platform/x86/hp/hp-bioscfg/bioscfg.c b/drivers/platform/x86/hp/hp-bioscfg/bioscfg.c
+index a3599498c4e8..6ddca857cc4d 100644
+--- a/drivers/platform/x86/hp/hp-bioscfg/bioscfg.c
++++ b/drivers/platform/x86/hp/hp-bioscfg/bioscfg.c
+@@ -613,14 +613,14 @@ static int hp_add_other_attributes(int attr_type)
+       default:
+               pr_err("Error: Unknown attr_type: %d\n", attr_type);
+               ret = -EINVAL;
+-              goto err_other_attr_init;
++              kfree(attr_name_kobj);
++              goto unlock_drv_mutex;
+       }
+       ret = kobject_init_and_add(attr_name_kobj, &attr_name_ktype,
+                                  NULL, "%s", attr_name);
+       if (ret) {
+               pr_err("Error encountered [%d]\n", ret);
+-              kobject_put(attr_name_kobj);
+               goto err_other_attr_init;
+       }
+@@ -645,6 +645,8 @@ static int hp_add_other_attributes(int attr_type)
+       return 0;
+ err_other_attr_init:
++      kobject_put(attr_name_kobj);
++unlock_drv_mutex:
+       mutex_unlock(&bioscfg_drv.mutex);
+       kfree(obj);
+       return ret;
+-- 
+2.43.0
+
diff --git a/queue-6.6/platform-x86-hp-bioscfg-move-mutex_lock-down-in-hp_add_other_attributes.patch b/queue-6.6/platform-x86-hp-bioscfg-move-mutex_lock-down-in-hp_add_other_attributes.patch
new file mode 100644 (file)
index 0000000..9f54d57
--- /dev/null
@@ -0,0 +1,48 @@
+From 5736aa9537c9b8927dec32d3d47c8c31fe560f62 Mon Sep 17 00:00:00 2001
+From: Harshit Mogalapalli <harshit.m.mogalapalli@oracle.com>
+Date: Mon, 13 Nov 2023 12:07:38 -0800
+Subject: platform/x86: hp-bioscfg: move mutex_lock() down in hp_add_other_attributes()
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Harshit Mogalapalli <harshit.m.mogalapalli@oracle.com>
+
+commit 5736aa9537c9b8927dec32d3d47c8c31fe560f62 upstream.
+
+attr_name_kobj's memory allocation is done with mutex_lock() held, this
+is not needed.
+
+Move allocation outside of mutex_lock() so unlock is not needed when
+allocation fails.
+
+Suggested-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
+Signed-off-by: Harshit Mogalapalli <harshit.m.mogalapalli@oracle.com>
+Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
+Link: https://lore.kernel.org/r/20231113200742.3593548-2-harshit.m.mogalapalli@oracle.com
+Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/platform/x86/hp/hp-bioscfg/bioscfg.c |   10 ++++------
+ 1 file changed, 4 insertions(+), 6 deletions(-)
+
+--- a/drivers/platform/x86/hp/hp-bioscfg/bioscfg.c
++++ b/drivers/platform/x86/hp/hp-bioscfg/bioscfg.c
+@@ -592,13 +592,11 @@ static int hp_add_other_attributes(int a
+       int ret;
+       char *attr_name;
+-      mutex_lock(&bioscfg_drv.mutex);
+-
+       attr_name_kobj = kzalloc(sizeof(*attr_name_kobj), GFP_KERNEL);
+-      if (!attr_name_kobj) {
+-              ret = -ENOMEM;
+-              goto err_other_attr_init;
+-      }
++      if (!attr_name_kobj)
++              return -ENOMEM;
++
++      mutex_lock(&bioscfg_drv.mutex);
+       /* Check if attribute type is supported */
+       switch (attr_type) {
diff --git a/queue-6.6/platform-x86-hp-bioscfg-simplify-return-check-in-hp_add_other_attributes.patch b/queue-6.6/platform-x86-hp-bioscfg-simplify-return-check-in-hp_add_other_attributes.patch
new file mode 100644 (file)
index 0000000..d4d7f9f
--- /dev/null
@@ -0,0 +1,51 @@
+From c5dbf04160005e07e8ca7232a7faa77ab1547ae0 Mon Sep 17 00:00:00 2001
+From: Harshit Mogalapalli <harshit.m.mogalapalli@oracle.com>
+Date: Mon, 13 Nov 2023 12:07:37 -0800
+Subject: platform/x86: hp-bioscfg: Simplify return check in hp_add_other_attributes()
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Harshit Mogalapalli <harshit.m.mogalapalli@oracle.com>
+
+commit c5dbf04160005e07e8ca7232a7faa77ab1547ae0 upstream.
+
+All cases in switch-case have a same goto on error, move the return
+check out of the switch. This is a cleanup.
+
+Signed-off-by: Harshit Mogalapalli <harshit.m.mogalapalli@oracle.com>
+Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
+Link: https://lore.kernel.org/r/20231113200742.3593548-1-harshit.m.mogalapalli@oracle.com
+Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/platform/x86/hp/hp-bioscfg/bioscfg.c |    8 +++-----
+ 1 file changed, 3 insertions(+), 5 deletions(-)
+
+--- a/drivers/platform/x86/hp/hp-bioscfg/bioscfg.c
++++ b/drivers/platform/x86/hp/hp-bioscfg/bioscfg.c
+@@ -630,21 +630,19 @@ static int hp_add_other_attributes(int a
+       switch (attr_type) {
+       case HPWMI_SECURE_PLATFORM_TYPE:
+               ret = hp_populate_secure_platform_data(attr_name_kobj);
+-              if (ret)
+-                      goto err_other_attr_init;
+               break;
+       case HPWMI_SURE_START_TYPE:
+               ret = hp_populate_sure_start_data(attr_name_kobj);
+-              if (ret)
+-                      goto err_other_attr_init;
+               break;
+       default:
+               ret = -EINVAL;
+-              goto err_other_attr_init;
+       }
++      if (ret)
++              goto err_other_attr_init;
++
+       mutex_unlock(&bioscfg_drv.mutex);
+       return 0;
diff --git a/queue-6.6/platform-x86-ideapad-laptop-set-max_brightness-before-using-it.patch b/queue-6.6/platform-x86-ideapad-laptop-set-max_brightness-before-using-it.patch
new file mode 100644 (file)
index 0000000..779b4d4
--- /dev/null
@@ -0,0 +1,57 @@
+From 7a3c36eef9a5d13b16aa954da54224c9c6bed339 Mon Sep 17 00:00:00 2001
+From: Stuart Hayhurst <stuart.a.hayhurst@gmail.com>
+Date: Tue, 14 Nov 2023 11:38:08 +0000
+Subject: platform/x86: ideapad-laptop: Set max_brightness before using it
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Stuart Hayhurst <stuart.a.hayhurst@gmail.com>
+
+commit 7a3c36eef9a5d13b16aa954da54224c9c6bed339 upstream.
+
+max_brightness is used in ideapad_kbd_bl_brightness_get() before it's set,
+causing ideapad_kbd_bl_brightness_get() to return -EINVAL sometimes.
+
+Fixes: ecaa1867b524 ("platform/x86: ideapad-laptop: Add support for keyboard backlights using KBLC ACPI symbol")
+Signed-off-by: Stuart Hayhurst <stuart.a.hayhurst@gmail.com>
+Cc: stable@vger.kernel.org
+Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
+Link: https://lore.kernel.org/r/20231114114055.6220-2-stuart.a.hayhurst@gmail.com
+Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/platform/x86/ideapad-laptop.c | 11 +++++------
+ 1 file changed, 5 insertions(+), 6 deletions(-)
+
+diff --git a/drivers/platform/x86/ideapad-laptop.c b/drivers/platform/x86/ideapad-laptop.c
+index ac037540acfc..88eefccb6ed2 100644
+--- a/drivers/platform/x86/ideapad-laptop.c
++++ b/drivers/platform/x86/ideapad-laptop.c
+@@ -1425,18 +1425,17 @@ static int ideapad_kbd_bl_init(struct ideapad_private *priv)
+       if (WARN_ON(priv->kbd_bl.initialized))
+               return -EEXIST;
+-      brightness = ideapad_kbd_bl_brightness_get(priv);
+-      if (brightness < 0)
+-              return brightness;
+-
+-      priv->kbd_bl.last_brightness = brightness;
+-
+       if (ideapad_kbd_bl_check_tristate(priv->kbd_bl.type)) {
+               priv->kbd_bl.led.max_brightness = 2;
+       } else {
+               priv->kbd_bl.led.max_brightness = 1;
+       }
++      brightness = ideapad_kbd_bl_brightness_get(priv);
++      if (brightness < 0)
++              return brightness;
++
++      priv->kbd_bl.last_brightness = brightness;
+       priv->kbd_bl.led.name                    = "platform::" LED_FUNCTION_KBD_BACKLIGHT;
+       priv->kbd_bl.led.brightness_get          = ideapad_kbd_bl_led_cdev_brightness_get;
+       priv->kbd_bl.led.brightness_set_blocking = ideapad_kbd_bl_led_cdev_brightness_set;
+-- 
+2.43.0
+
diff --git a/queue-6.6/revert-phy-realtek-usb-add-driver-for-the-realtek-soc-usb-2.0-phy.patch b/queue-6.6/revert-phy-realtek-usb-add-driver-for-the-realtek-soc-usb-2.0-phy.patch
new file mode 100644 (file)
index 0000000..583dc88
--- /dev/null
@@ -0,0 +1,1420 @@
+From 7a784bcdd7e54f0599da3b2360e472238412623e Mon Sep 17 00:00:00 2001
+From: Johan Hovold <johan+linaro@kernel.org>
+Date: Mon, 6 Nov 2023 12:06:53 +0100
+Subject: Revert "phy: realtek: usb: Add driver for the Realtek SoC USB 2.0 PHY"
+
+From: Johan Hovold <johan+linaro@kernel.org>
+
+commit 7a784bcdd7e54f0599da3b2360e472238412623e upstream.
+
+This reverts commit 134e6d25f6bd06071e5aac0a7eefcea6f7713955.
+
+The recently added Realtek PHY drivers depend on the new port status
+notification mechanism which was built on the deprecated USB PHY
+implementation and devicetree binding.
+
+Specifically, using these PHYs would require describing the very same
+PHY using both the generic "phy" property and the deprecated "usb-phy"
+property which is clearly wrong.
+
+We should not be building new functionality on top of the legacy USB PHY
+implementation even if it is currently stuck in some kind of
+transitional limbo.
+
+Revert the new Realtek PHY drivers for now so that the port status
+notification interface can be reverted and replaced.
+
+Fixes: 134e6d25f6bd ("phy: realtek: usb: Add driver for the Realtek SoC USB 2.0 PHY")
+Cc: stable@vger.kernel.org      # 6.6
+Cc: Stanley Chang <stanley_chang@realtek.com>
+Signed-off-by: Johan Hovold <johan+linaro@kernel.org>
+Link: https://lore.kernel.org/r/20231106110654.31090-3-johan+linaro@kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/phy/Kconfig                |    1 
+ drivers/phy/Makefile               |    1 
+ drivers/phy/realtek/Kconfig        |   20 
+ drivers/phy/realtek/Makefile       |    2 
+ drivers/phy/realtek/phy-rtk-usb2.c | 1325 -------------------------------------
+ 5 files changed, 1349 deletions(-)
+ delete mode 100644 drivers/phy/realtek/Kconfig
+ delete mode 100644 drivers/phy/realtek/Makefile
+ delete mode 100644 drivers/phy/realtek/phy-rtk-usb2.c
+
+--- a/drivers/phy/Kconfig
++++ b/drivers/phy/Kconfig
+@@ -87,7 +87,6 @@ source "drivers/phy/motorola/Kconfig"
+ source "drivers/phy/mscc/Kconfig"
+ source "drivers/phy/qualcomm/Kconfig"
+ source "drivers/phy/ralink/Kconfig"
+-source "drivers/phy/realtek/Kconfig"
+ source "drivers/phy/renesas/Kconfig"
+ source "drivers/phy/rockchip/Kconfig"
+ source "drivers/phy/samsung/Kconfig"
+--- a/drivers/phy/Makefile
++++ b/drivers/phy/Makefile
+@@ -26,7 +26,6 @@ obj-y                                        += allwinner/   \
+                                          mscc/        \
+                                          qualcomm/    \
+                                          ralink/      \
+-                                         realtek/     \
+                                          renesas/     \
+                                          rockchip/    \
+                                          samsung/     \
+--- a/drivers/phy/realtek/Kconfig
++++ /dev/null
+@@ -1,20 +0,0 @@
+-# SPDX-License-Identifier: GPL-2.0
+-#
+-# Phy drivers for Realtek platforms
+-#
+-
+-if ARCH_REALTEK || COMPILE_TEST
+-
+-config PHY_RTK_RTD_USB2PHY
+-      tristate "Realtek RTD USB2 PHY Transceiver Driver"
+-      depends on USB_SUPPORT
+-      select GENERIC_PHY
+-      select USB_PHY
+-      select USB_COMMON
+-      help
+-        Enable this to support Realtek SoC USB2 phy transceiver.
+-        The DHC (digital home center) RTD series SoCs used the Synopsys
+-        DWC3 USB IP. This driver will do the PHY initialization
+-        of the parameters.
+-
+-endif # ARCH_REALTEK || COMPILE_TEST
+--- a/drivers/phy/realtek/Makefile
++++ /dev/null
+@@ -1,2 +0,0 @@
+-# SPDX-License-Identifier: GPL-2.0
+-obj-$(CONFIG_PHY_RTK_RTD_USB2PHY)     += phy-rtk-usb2.o
+--- a/drivers/phy/realtek/phy-rtk-usb2.c
++++ /dev/null
+@@ -1,1325 +0,0 @@
+-// SPDX-License-Identifier: GPL-2.0
+-/*
+- *  phy-rtk-usb2.c RTK usb2.0 PHY driver
+- *
+- * Copyright (C) 2023 Realtek Semiconductor Corporation
+- *
+- */
+-
+-#include <linux/module.h>
+-#include <linux/of.h>
+-#include <linux/of_device.h>
+-#include <linux/of_address.h>
+-#include <linux/uaccess.h>
+-#include <linux/debugfs.h>
+-#include <linux/nvmem-consumer.h>
+-#include <linux/regmap.h>
+-#include <linux/sys_soc.h>
+-#include <linux/mfd/syscon.h>
+-#include <linux/phy/phy.h>
+-#include <linux/usb.h>
+-#include <linux/usb/phy.h>
+-#include <linux/usb/hcd.h>
+-
+-/* GUSB2PHYACCn register */
+-#define PHY_NEW_REG_REQ BIT(25)
+-#define PHY_VSTS_BUSY   BIT(23)
+-#define PHY_VCTRL_SHIFT 8
+-#define PHY_REG_DATA_MASK 0xff
+-
+-#define GET_LOW_NIBBLE(addr) ((addr) & 0x0f)
+-#define GET_HIGH_NIBBLE(addr) (((addr) & 0xf0) >> 4)
+-
+-#define EFUS_USB_DC_CAL_RATE 2
+-#define EFUS_USB_DC_CAL_MAX 7
+-
+-#define EFUS_USB_DC_DIS_RATE 1
+-#define EFUS_USB_DC_DIS_MAX 7
+-
+-#define MAX_PHY_DATA_SIZE 20
+-#define OFFEST_PHY_READ 0x20
+-
+-#define MAX_USB_PHY_NUM 4
+-#define MAX_USB_PHY_PAGE0_DATA_SIZE 16
+-#define MAX_USB_PHY_PAGE1_DATA_SIZE 16
+-#define MAX_USB_PHY_PAGE2_DATA_SIZE 8
+-
+-#define SET_PAGE_OFFSET 0xf4
+-#define SET_PAGE_0 0x9b
+-#define SET_PAGE_1 0xbb
+-#define SET_PAGE_2 0xdb
+-
+-#define PAGE_START 0xe0
+-#define PAGE0_0XE4 0xe4
+-#define PAGE0_0XE6 0xe6
+-#define PAGE0_0XE7 0xe7
+-#define PAGE1_0XE0 0xe0
+-#define PAGE1_0XE2 0xe2
+-
+-#define SENSITIVITY_CTRL (BIT(4) | BIT(5) | BIT(6))
+-#define ENABLE_AUTO_SENSITIVITY_CALIBRATION BIT(2)
+-#define DEFAULT_DC_DRIVING_VALUE (0x8)
+-#define DEFAULT_DC_DISCONNECTION_VALUE (0x6)
+-#define HS_CLK_SELECT BIT(6)
+-
+-struct phy_reg {
+-      void __iomem *reg_wrap_vstatus;
+-      void __iomem *reg_gusb2phyacc0;
+-      int vstatus_index;
+-};
+-
+-struct phy_data {
+-      u8 addr;
+-      u8 data;
+-};
+-
+-struct phy_cfg {
+-      int page0_size;
+-      struct phy_data page0[MAX_USB_PHY_PAGE0_DATA_SIZE];
+-      int page1_size;
+-      struct phy_data page1[MAX_USB_PHY_PAGE1_DATA_SIZE];
+-      int page2_size;
+-      struct phy_data page2[MAX_USB_PHY_PAGE2_DATA_SIZE];
+-
+-      int num_phy;
+-
+-      bool check_efuse;
+-      int check_efuse_version;
+-#define CHECK_EFUSE_V1 1
+-#define CHECK_EFUSE_V2 2
+-      int efuse_dc_driving_rate;
+-      int efuse_dc_disconnect_rate;
+-      int dc_driving_mask;
+-      int dc_disconnect_mask;
+-      bool usb_dc_disconnect_at_page0;
+-      int driving_updated_for_dev_dis;
+-
+-      bool do_toggle;
+-      bool do_toggle_driving;
+-      bool use_default_parameter;
+-      bool is_double_sensitivity_mode;
+-};
+-
+-struct phy_parameter {
+-      struct phy_reg phy_reg;
+-
+-      /* Get from efuse */
+-      s8 efuse_usb_dc_cal;
+-      s8 efuse_usb_dc_dis;
+-
+-      /* Get from dts */
+-      bool inverse_hstx_sync_clock;
+-      u32 driving_level;
+-      s32 driving_level_compensate;
+-      s32 disconnection_compensate;
+-};
+-
+-struct rtk_phy {
+-      struct usb_phy phy;
+-      struct device *dev;
+-
+-      struct phy_cfg *phy_cfg;
+-      int num_phy;
+-      struct phy_parameter *phy_parameter;
+-
+-      struct dentry *debug_dir;
+-};
+-
+-/* mapping 0xE0 to 0 ... 0xE7 to 7, 0xF0 to 8 ,,, 0xF7 to 15 */
+-static inline int page_addr_to_array_index(u8 addr)
+-{
+-      return (int)((((addr) - PAGE_START) & 0x7) +
+-              ((((addr) - PAGE_START) & 0x10) >> 1));
+-}
+-
+-static inline u8 array_index_to_page_addr(int index)
+-{
+-      return ((((index) + PAGE_START) & 0x7) +
+-              ((((index) & 0x8) << 1) + PAGE_START));
+-}
+-
+-#define PHY_IO_TIMEOUT_USEC           (50000)
+-#define PHY_IO_DELAY_US                       (100)
+-
+-static inline int utmi_wait_register(void __iomem *reg, u32 mask, u32 result)
+-{
+-      int ret;
+-      unsigned int val;
+-
+-      ret = read_poll_timeout(readl, val, ((val & mask) == result),
+-                              PHY_IO_DELAY_US, PHY_IO_TIMEOUT_USEC, false, reg);
+-      if (ret) {
+-              pr_err("%s can't program USB phy\n", __func__);
+-              return -ETIMEDOUT;
+-      }
+-
+-      return 0;
+-}
+-
+-static char rtk_phy_read(struct phy_reg *phy_reg, char addr)
+-{
+-      void __iomem *reg_gusb2phyacc0 = phy_reg->reg_gusb2phyacc0;
+-      unsigned int val;
+-      int ret = 0;
+-
+-      addr -= OFFEST_PHY_READ;
+-
+-      /* polling until VBusy == 0 */
+-      ret = utmi_wait_register(reg_gusb2phyacc0, PHY_VSTS_BUSY, 0);
+-      if (ret)
+-              return (char)ret;
+-
+-      /* VCtrl = low nibble of addr, and set PHY_NEW_REG_REQ */
+-      val = PHY_NEW_REG_REQ | (GET_LOW_NIBBLE(addr) << PHY_VCTRL_SHIFT);
+-      writel(val, reg_gusb2phyacc0);
+-      ret = utmi_wait_register(reg_gusb2phyacc0, PHY_VSTS_BUSY, 0);
+-      if (ret)
+-              return (char)ret;
+-
+-      /* VCtrl = high nibble of addr, and set PHY_NEW_REG_REQ */
+-      val = PHY_NEW_REG_REQ | (GET_HIGH_NIBBLE(addr) << PHY_VCTRL_SHIFT);
+-      writel(val, reg_gusb2phyacc0);
+-      ret = utmi_wait_register(reg_gusb2phyacc0, PHY_VSTS_BUSY, 0);
+-      if (ret)
+-              return (char)ret;
+-
+-      val = readl(reg_gusb2phyacc0);
+-
+-      return (char)(val & PHY_REG_DATA_MASK);
+-}
+-
+-static int rtk_phy_write(struct phy_reg *phy_reg, char addr, char data)
+-{
+-      unsigned int val;
+-      void __iomem *reg_wrap_vstatus = phy_reg->reg_wrap_vstatus;
+-      void __iomem *reg_gusb2phyacc0 = phy_reg->reg_gusb2phyacc0;
+-      int shift_bits = phy_reg->vstatus_index * 8;
+-      int ret = 0;
+-
+-      /* write data to VStatusOut2 (data output to phy) */
+-      writel((u32)data << shift_bits, reg_wrap_vstatus);
+-
+-      ret = utmi_wait_register(reg_gusb2phyacc0, PHY_VSTS_BUSY, 0);
+-      if (ret)
+-              return ret;
+-
+-      /* VCtrl = low nibble of addr, set PHY_NEW_REG_REQ */
+-      val = PHY_NEW_REG_REQ | (GET_LOW_NIBBLE(addr) << PHY_VCTRL_SHIFT);
+-
+-      writel(val, reg_gusb2phyacc0);
+-      ret = utmi_wait_register(reg_gusb2phyacc0, PHY_VSTS_BUSY, 0);
+-      if (ret)
+-              return ret;
+-
+-      /* VCtrl = high nibble of addr, set PHY_NEW_REG_REQ */
+-      val = PHY_NEW_REG_REQ | (GET_HIGH_NIBBLE(addr) << PHY_VCTRL_SHIFT);
+-
+-      writel(val, reg_gusb2phyacc0);
+-      ret = utmi_wait_register(reg_gusb2phyacc0, PHY_VSTS_BUSY, 0);
+-      if (ret)
+-              return ret;
+-
+-      return 0;
+-}
+-
+-static int rtk_phy_set_page(struct phy_reg *phy_reg, int page)
+-{
+-      switch (page) {
+-      case 0:
+-              return rtk_phy_write(phy_reg, SET_PAGE_OFFSET, SET_PAGE_0);
+-      case 1:
+-              return rtk_phy_write(phy_reg, SET_PAGE_OFFSET, SET_PAGE_1);
+-      case 2:
+-              return rtk_phy_write(phy_reg, SET_PAGE_OFFSET, SET_PAGE_2);
+-      default:
+-              pr_err("%s error page=%d\n", __func__, page);
+-      }
+-
+-      return -EINVAL;
+-}
+-
+-static u8 __updated_dc_disconnect_level_page0_0xe4(struct phy_cfg *phy_cfg,
+-                                                 struct phy_parameter *phy_parameter, u8 data)
+-{
+-      u8 ret;
+-      s32 val;
+-      s32 dc_disconnect_mask = phy_cfg->dc_disconnect_mask;
+-      int offset = 4;
+-
+-      val = (s32)((data >> offset) & dc_disconnect_mask)
+-                   + phy_parameter->efuse_usb_dc_dis
+-                   + phy_parameter->disconnection_compensate;
+-
+-      if (val > dc_disconnect_mask)
+-              val = dc_disconnect_mask;
+-      else if (val < 0)
+-              val = 0;
+-
+-      ret = (data & (~(dc_disconnect_mask << offset))) |
+-                  (val & dc_disconnect_mask) << offset;
+-
+-      return ret;
+-}
+-
+-/* updated disconnect level at page0 */
+-static void update_dc_disconnect_level_at_page0(struct rtk_phy *rtk_phy,
+-                                              struct phy_parameter *phy_parameter, bool update)
+-{
+-      struct phy_cfg *phy_cfg;
+-      struct phy_reg *phy_reg;
+-      struct phy_data *phy_data_page;
+-      struct phy_data *phy_data;
+-      u8 addr, data;
+-      int offset = 4;
+-      s32 dc_disconnect_mask;
+-      int i;
+-
+-      phy_cfg = rtk_phy->phy_cfg;
+-      phy_reg = &phy_parameter->phy_reg;
+-
+-      /* Set page 0 */
+-      phy_data_page = phy_cfg->page0;
+-      rtk_phy_set_page(phy_reg, 0);
+-
+-      i = page_addr_to_array_index(PAGE0_0XE4);
+-      phy_data = phy_data_page + i;
+-      if (!phy_data->addr) {
+-              phy_data->addr = PAGE0_0XE4;
+-              phy_data->data = rtk_phy_read(phy_reg, PAGE0_0XE4);
+-      }
+-
+-      addr = phy_data->addr;
+-      data = phy_data->data;
+-      dc_disconnect_mask = phy_cfg->dc_disconnect_mask;
+-
+-      if (update)
+-              data = __updated_dc_disconnect_level_page0_0xe4(phy_cfg, phy_parameter, data);
+-      else
+-              data = (data & ~(dc_disconnect_mask << offset)) |
+-                      (DEFAULT_DC_DISCONNECTION_VALUE << offset);
+-
+-      if (rtk_phy_write(phy_reg, addr, data))
+-              dev_err(rtk_phy->dev,
+-                      "%s: Error to set page1 parameter addr=0x%x value=0x%x\n",
+-                      __func__, addr, data);
+-}
+-
+-static u8 __updated_dc_disconnect_level_page1_0xe2(struct phy_cfg *phy_cfg,
+-                                                 struct phy_parameter *phy_parameter, u8 data)
+-{
+-      u8 ret;
+-      s32 val;
+-      s32 dc_disconnect_mask = phy_cfg->dc_disconnect_mask;
+-
+-      if (phy_cfg->check_efuse_version == CHECK_EFUSE_V1) {
+-              val = (s32)(data & dc_disconnect_mask)
+-                          + phy_parameter->efuse_usb_dc_dis
+-                          + phy_parameter->disconnection_compensate;
+-      } else { /* for CHECK_EFUSE_V2 or no efuse */
+-              if (phy_parameter->efuse_usb_dc_dis)
+-                      val = (s32)(phy_parameter->efuse_usb_dc_dis +
+-                                  phy_parameter->disconnection_compensate);
+-              else
+-                      val = (s32)((data & dc_disconnect_mask) +
+-                                  phy_parameter->disconnection_compensate);
+-      }
+-
+-      if (val > dc_disconnect_mask)
+-              val = dc_disconnect_mask;
+-      else if (val < 0)
+-              val = 0;
+-
+-      ret = (data & (~dc_disconnect_mask)) | (val & dc_disconnect_mask);
+-
+-      return ret;
+-}
+-
+-/* updated disconnect level at page1 */
+-static void update_dc_disconnect_level_at_page1(struct rtk_phy *rtk_phy,
+-                                              struct phy_parameter *phy_parameter, bool update)
+-{
+-      struct phy_cfg *phy_cfg;
+-      struct phy_data *phy_data_page;
+-      struct phy_data *phy_data;
+-      struct phy_reg *phy_reg;
+-      u8 addr, data;
+-      s32 dc_disconnect_mask;
+-      int i;
+-
+-      phy_cfg = rtk_phy->phy_cfg;
+-      phy_reg = &phy_parameter->phy_reg;
+-
+-      /* Set page 1 */
+-      phy_data_page = phy_cfg->page1;
+-      rtk_phy_set_page(phy_reg, 1);
+-
+-      i = page_addr_to_array_index(PAGE1_0XE2);
+-      phy_data = phy_data_page + i;
+-      if (!phy_data->addr) {
+-              phy_data->addr = PAGE1_0XE2;
+-              phy_data->data = rtk_phy_read(phy_reg, PAGE1_0XE2);
+-      }
+-
+-      addr = phy_data->addr;
+-      data = phy_data->data;
+-      dc_disconnect_mask = phy_cfg->dc_disconnect_mask;
+-
+-      if (update)
+-              data = __updated_dc_disconnect_level_page1_0xe2(phy_cfg, phy_parameter, data);
+-      else
+-              data = (data & ~dc_disconnect_mask) | DEFAULT_DC_DISCONNECTION_VALUE;
+-
+-      if (rtk_phy_write(phy_reg, addr, data))
+-              dev_err(rtk_phy->dev,
+-                      "%s: Error to set page1 parameter addr=0x%x value=0x%x\n",
+-                      __func__, addr, data);
+-}
+-
+-static void update_dc_disconnect_level(struct rtk_phy *rtk_phy,
+-                                     struct phy_parameter *phy_parameter, bool update)
+-{
+-      struct phy_cfg *phy_cfg = rtk_phy->phy_cfg;
+-
+-      if (phy_cfg->usb_dc_disconnect_at_page0)
+-              update_dc_disconnect_level_at_page0(rtk_phy, phy_parameter, update);
+-      else
+-              update_dc_disconnect_level_at_page1(rtk_phy, phy_parameter, update);
+-}
+-
+-static u8 __update_dc_driving_page0_0xe4(struct phy_cfg *phy_cfg,
+-                                       struct phy_parameter *phy_parameter, u8 data)
+-{
+-      s32 driving_level_compensate = phy_parameter->driving_level_compensate;
+-      s32 dc_driving_mask = phy_cfg->dc_driving_mask;
+-      s32 val;
+-      u8 ret;
+-
+-      if (phy_cfg->check_efuse_version == CHECK_EFUSE_V1) {
+-              val = (s32)(data & dc_driving_mask) + driving_level_compensate
+-                          + phy_parameter->efuse_usb_dc_cal;
+-      } else { /* for CHECK_EFUSE_V2 or no efuse */
+-              if (phy_parameter->efuse_usb_dc_cal)
+-                      val = (s32)((phy_parameter->efuse_usb_dc_cal & dc_driving_mask)
+-                                  + driving_level_compensate);
+-              else
+-                      val = (s32)(data & dc_driving_mask);
+-      }
+-
+-      if (val > dc_driving_mask)
+-              val = dc_driving_mask;
+-      else if (val < 0)
+-              val = 0;
+-
+-      ret = (data & (~dc_driving_mask)) | (val & dc_driving_mask);
+-
+-      return ret;
+-}
+-
+-static void update_dc_driving_level(struct rtk_phy *rtk_phy,
+-                                  struct phy_parameter *phy_parameter)
+-{
+-      struct phy_cfg *phy_cfg;
+-      struct phy_reg *phy_reg;
+-
+-      phy_reg = &phy_parameter->phy_reg;
+-      phy_cfg = rtk_phy->phy_cfg;
+-      if (!phy_cfg->page0[4].addr) {
+-              rtk_phy_set_page(phy_reg, 0);
+-              phy_cfg->page0[4].addr = PAGE0_0XE4;
+-              phy_cfg->page0[4].data = rtk_phy_read(phy_reg, PAGE0_0XE4);
+-      }
+-
+-      if (phy_parameter->driving_level != DEFAULT_DC_DRIVING_VALUE) {
+-              u32 dc_driving_mask;
+-              u8 driving_level;
+-              u8 data;
+-
+-              data = phy_cfg->page0[4].data;
+-              dc_driving_mask = phy_cfg->dc_driving_mask;
+-              driving_level = data & dc_driving_mask;
+-
+-              dev_dbg(rtk_phy->dev, "%s driving_level=%d => dts driving_level=%d\n",
+-                      __func__, driving_level, phy_parameter->driving_level);
+-
+-              phy_cfg->page0[4].data = (data & (~dc_driving_mask)) |
+-                          (phy_parameter->driving_level & dc_driving_mask);
+-      }
+-
+-      phy_cfg->page0[4].data = __update_dc_driving_page0_0xe4(phy_cfg,
+-                                                              phy_parameter,
+-                                                              phy_cfg->page0[4].data);
+-}
+-
+-static void update_hs_clk_select(struct rtk_phy *rtk_phy,
+-                               struct phy_parameter *phy_parameter)
+-{
+-      struct phy_cfg *phy_cfg;
+-      struct phy_reg *phy_reg;
+-
+-      phy_cfg = rtk_phy->phy_cfg;
+-      phy_reg = &phy_parameter->phy_reg;
+-
+-      if (phy_parameter->inverse_hstx_sync_clock) {
+-              if (!phy_cfg->page0[6].addr) {
+-                      rtk_phy_set_page(phy_reg, 0);
+-                      phy_cfg->page0[6].addr = PAGE0_0XE6;
+-                      phy_cfg->page0[6].data = rtk_phy_read(phy_reg, PAGE0_0XE6);
+-              }
+-
+-              phy_cfg->page0[6].data = phy_cfg->page0[6].data | HS_CLK_SELECT;
+-      }
+-}
+-
+-static void do_rtk_phy_toggle(struct rtk_phy *rtk_phy,
+-                            int index, bool connect)
+-{
+-      struct phy_parameter *phy_parameter;
+-      struct phy_cfg *phy_cfg;
+-      struct phy_reg *phy_reg;
+-      struct phy_data *phy_data_page;
+-      u8 addr, data;
+-      int i;
+-
+-      phy_cfg = rtk_phy->phy_cfg;
+-      phy_parameter = &((struct phy_parameter *)rtk_phy->phy_parameter)[index];
+-      phy_reg = &phy_parameter->phy_reg;
+-
+-      if (!phy_cfg->do_toggle)
+-              goto out;
+-
+-      if (phy_cfg->is_double_sensitivity_mode)
+-              goto do_toggle_driving;
+-
+-      /* Set page 0 */
+-      rtk_phy_set_page(phy_reg, 0);
+-
+-      addr = PAGE0_0XE7;
+-      data = rtk_phy_read(phy_reg, addr);
+-
+-      if (connect)
+-              rtk_phy_write(phy_reg, addr, data & (~SENSITIVITY_CTRL));
+-      else
+-              rtk_phy_write(phy_reg, addr, data | (SENSITIVITY_CTRL));
+-
+-do_toggle_driving:
+-
+-      if (!phy_cfg->do_toggle_driving)
+-              goto do_toggle;
+-
+-      /* Page 0 addr 0xE4 driving capability */
+-
+-      /* Set page 0 */
+-      phy_data_page = phy_cfg->page0;
+-      rtk_phy_set_page(phy_reg, 0);
+-
+-      i = page_addr_to_array_index(PAGE0_0XE4);
+-      addr = phy_data_page[i].addr;
+-      data = phy_data_page[i].data;
+-
+-      if (connect) {
+-              rtk_phy_write(phy_reg, addr, data);
+-      } else {
+-              u8 value;
+-              s32 tmp;
+-              s32 driving_updated =
+-                          phy_cfg->driving_updated_for_dev_dis;
+-              s32 dc_driving_mask = phy_cfg->dc_driving_mask;
+-
+-              tmp = (s32)(data & dc_driving_mask) + driving_updated;
+-
+-              if (tmp > dc_driving_mask)
+-                      tmp = dc_driving_mask;
+-              else if (tmp < 0)
+-                      tmp = 0;
+-
+-              value = (data & (~dc_driving_mask)) | (tmp & dc_driving_mask);
+-
+-              rtk_phy_write(phy_reg, addr, value);
+-      }
+-
+-do_toggle:
+-      /* restore dc disconnect level before toggle */
+-      update_dc_disconnect_level(rtk_phy, phy_parameter, false);
+-
+-      /* Set page 1 */
+-      rtk_phy_set_page(phy_reg, 1);
+-
+-      addr = PAGE1_0XE0;
+-      data = rtk_phy_read(phy_reg, addr);
+-
+-      rtk_phy_write(phy_reg, addr, data &
+-                    (~ENABLE_AUTO_SENSITIVITY_CALIBRATION));
+-      mdelay(1);
+-      rtk_phy_write(phy_reg, addr, data |
+-                    (ENABLE_AUTO_SENSITIVITY_CALIBRATION));
+-
+-      /* update dc disconnect level after toggle */
+-      update_dc_disconnect_level(rtk_phy, phy_parameter, true);
+-
+-out:
+-      return;
+-}
+-
+-static int do_rtk_phy_init(struct rtk_phy *rtk_phy, int index)
+-{
+-      struct phy_parameter *phy_parameter;
+-      struct phy_cfg *phy_cfg;
+-      struct phy_data *phy_data_page;
+-      struct phy_reg *phy_reg;
+-      int i;
+-
+-      phy_cfg = rtk_phy->phy_cfg;
+-      phy_parameter = &((struct phy_parameter *)rtk_phy->phy_parameter)[index];
+-      phy_reg = &phy_parameter->phy_reg;
+-
+-      if (phy_cfg->use_default_parameter) {
+-              dev_dbg(rtk_phy->dev, "%s phy#%d use default parameter\n",
+-                      __func__, index);
+-              goto do_toggle;
+-      }
+-
+-      /* Set page 0 */
+-      phy_data_page = phy_cfg->page0;
+-      rtk_phy_set_page(phy_reg, 0);
+-
+-      for (i = 0; i < phy_cfg->page0_size; i++) {
+-              struct phy_data *phy_data = phy_data_page + i;
+-              u8 addr = phy_data->addr;
+-              u8 data = phy_data->data;
+-
+-              if (!addr)
+-                      continue;
+-
+-              if (rtk_phy_write(phy_reg, addr, data)) {
+-                      dev_err(rtk_phy->dev,
+-                              "%s: Error to set page0 parameter addr=0x%x value=0x%x\n",
+-                              __func__, addr, data);
+-                      return -EINVAL;
+-              }
+-      }
+-
+-      /* Set page 1 */
+-      phy_data_page = phy_cfg->page1;
+-      rtk_phy_set_page(phy_reg, 1);
+-
+-      for (i = 0; i < phy_cfg->page1_size; i++) {
+-              struct phy_data *phy_data = phy_data_page + i;
+-              u8 addr = phy_data->addr;
+-              u8 data = phy_data->data;
+-
+-              if (!addr)
+-                      continue;
+-
+-              if (rtk_phy_write(phy_reg, addr, data)) {
+-                      dev_err(rtk_phy->dev,
+-                              "%s: Error to set page1 parameter addr=0x%x value=0x%x\n",
+-                              __func__, addr, data);
+-                      return -EINVAL;
+-              }
+-      }
+-
+-      if (phy_cfg->page2_size == 0)
+-              goto do_toggle;
+-
+-      /* Set page 2 */
+-      phy_data_page = phy_cfg->page2;
+-      rtk_phy_set_page(phy_reg, 2);
+-
+-      for (i = 0; i < phy_cfg->page2_size; i++) {
+-              struct phy_data *phy_data = phy_data_page + i;
+-              u8 addr = phy_data->addr;
+-              u8 data = phy_data->data;
+-
+-              if (!addr)
+-                      continue;
+-
+-              if (rtk_phy_write(phy_reg, addr, data)) {
+-                      dev_err(rtk_phy->dev,
+-                              "%s: Error to set page2 parameter addr=0x%x value=0x%x\n",
+-                              __func__, addr, data);
+-                      return -EINVAL;
+-              }
+-      }
+-
+-do_toggle:
+-      do_rtk_phy_toggle(rtk_phy, index, false);
+-
+-      return 0;
+-}
+-
+-static int rtk_phy_init(struct phy *phy)
+-{
+-      struct rtk_phy *rtk_phy = phy_get_drvdata(phy);
+-      unsigned long phy_init_time = jiffies;
+-      int i, ret = 0;
+-
+-      if (!rtk_phy)
+-              return -EINVAL;
+-
+-      for (i = 0; i < rtk_phy->num_phy; i++)
+-              ret = do_rtk_phy_init(rtk_phy, i);
+-
+-      dev_dbg(rtk_phy->dev, "Initialized RTK USB 2.0 PHY (take %dms)\n",
+-              jiffies_to_msecs(jiffies - phy_init_time));
+-      return ret;
+-}
+-
+-static int rtk_phy_exit(struct phy *phy)
+-{
+-      return 0;
+-}
+-
+-static const struct phy_ops ops = {
+-      .init           = rtk_phy_init,
+-      .exit           = rtk_phy_exit,
+-      .owner          = THIS_MODULE,
+-};
+-
+-static void rtk_phy_toggle(struct usb_phy *usb2_phy, bool connect, int port)
+-{
+-      int index = port;
+-      struct rtk_phy *rtk_phy = NULL;
+-
+-      rtk_phy = dev_get_drvdata(usb2_phy->dev);
+-
+-      if (index > rtk_phy->num_phy) {
+-              dev_err(rtk_phy->dev, "%s: The port=%d is not in usb phy (num_phy=%d)\n",
+-                      __func__, index, rtk_phy->num_phy);
+-              return;
+-      }
+-
+-      do_rtk_phy_toggle(rtk_phy, index, connect);
+-}
+-
+-static int rtk_phy_notify_port_status(struct usb_phy *x, int port,
+-                                    u16 portstatus, u16 portchange)
+-{
+-      bool connect = false;
+-
+-      pr_debug("%s port=%d portstatus=0x%x portchange=0x%x\n",
+-               __func__, port, (int)portstatus, (int)portchange);
+-      if (portstatus & USB_PORT_STAT_CONNECTION)
+-              connect = true;
+-
+-      if (portchange & USB_PORT_STAT_C_CONNECTION)
+-              rtk_phy_toggle(x, connect, port);
+-
+-      return 0;
+-}
+-
+-#ifdef CONFIG_DEBUG_FS
+-static struct dentry *create_phy_debug_root(void)
+-{
+-      struct dentry *phy_debug_root;
+-
+-      phy_debug_root = debugfs_lookup("phy", usb_debug_root);
+-      if (!phy_debug_root)
+-              phy_debug_root = debugfs_create_dir("phy", usb_debug_root);
+-
+-      return phy_debug_root;
+-}
+-
+-static int rtk_usb2_parameter_show(struct seq_file *s, void *unused)
+-{
+-      struct rtk_phy *rtk_phy = s->private;
+-      struct phy_cfg *phy_cfg;
+-      int i, index;
+-
+-      phy_cfg = rtk_phy->phy_cfg;
+-
+-      seq_puts(s, "Property:\n");
+-      seq_printf(s, "  check_efuse: %s\n",
+-                 phy_cfg->check_efuse ? "Enable" : "Disable");
+-      seq_printf(s, "  check_efuse_version: %d\n",
+-                 phy_cfg->check_efuse_version);
+-      seq_printf(s, "  efuse_dc_driving_rate: %d\n",
+-                 phy_cfg->efuse_dc_driving_rate);
+-      seq_printf(s, "  dc_driving_mask: 0x%x\n",
+-                 phy_cfg->dc_driving_mask);
+-      seq_printf(s, "  efuse_dc_disconnect_rate: %d\n",
+-                 phy_cfg->efuse_dc_disconnect_rate);
+-      seq_printf(s, "  dc_disconnect_mask: 0x%x\n",
+-                 phy_cfg->dc_disconnect_mask);
+-      seq_printf(s, "  usb_dc_disconnect_at_page0: %s\n",
+-                 phy_cfg->usb_dc_disconnect_at_page0 ? "true" : "false");
+-      seq_printf(s, "  do_toggle: %s\n",
+-                 phy_cfg->do_toggle ? "Enable" : "Disable");
+-      seq_printf(s, "  do_toggle_driving: %s\n",
+-                 phy_cfg->do_toggle_driving ? "Enable" : "Disable");
+-      seq_printf(s, "  driving_updated_for_dev_dis: 0x%x\n",
+-                 phy_cfg->driving_updated_for_dev_dis);
+-      seq_printf(s, "  use_default_parameter: %s\n",
+-                 phy_cfg->use_default_parameter ? "Enable" : "Disable");
+-      seq_printf(s, "  is_double_sensitivity_mode: %s\n",
+-                 phy_cfg->is_double_sensitivity_mode ? "Enable" : "Disable");
+-
+-      for (index = 0; index < rtk_phy->num_phy; index++) {
+-              struct phy_parameter *phy_parameter;
+-              struct phy_reg *phy_reg;
+-              struct phy_data *phy_data_page;
+-
+-              phy_parameter =  &((struct phy_parameter *)rtk_phy->phy_parameter)[index];
+-              phy_reg = &phy_parameter->phy_reg;
+-
+-              seq_printf(s, "PHY %d:\n", index);
+-
+-              seq_puts(s, "Page 0:\n");
+-              /* Set page 0 */
+-              phy_data_page = phy_cfg->page0;
+-              rtk_phy_set_page(phy_reg, 0);
+-
+-              for (i = 0; i < phy_cfg->page0_size; i++) {
+-                      struct phy_data *phy_data = phy_data_page + i;
+-                      u8 addr = array_index_to_page_addr(i);
+-                      u8 data = phy_data->data;
+-                      u8 value = rtk_phy_read(phy_reg, addr);
+-
+-                      if (phy_data->addr)
+-                              seq_printf(s, "  Page 0: addr=0x%x data=0x%02x ==> read value=0x%02x\n",
+-                                         addr, data, value);
+-                      else
+-                              seq_printf(s, "  Page 0: addr=0x%x data=none ==> read value=0x%02x\n",
+-                                         addr, value);
+-              }
+-
+-              seq_puts(s, "Page 1:\n");
+-              /* Set page 1 */
+-              phy_data_page = phy_cfg->page1;
+-              rtk_phy_set_page(phy_reg, 1);
+-
+-              for (i = 0; i < phy_cfg->page1_size; i++) {
+-                      struct phy_data *phy_data = phy_data_page + i;
+-                      u8 addr = array_index_to_page_addr(i);
+-                      u8 data = phy_data->data;
+-                      u8 value = rtk_phy_read(phy_reg, addr);
+-
+-                      if (phy_data->addr)
+-                              seq_printf(s, "  Page 1: addr=0x%x data=0x%02x ==> read value=0x%02x\n",
+-                                         addr, data, value);
+-                      else
+-                              seq_printf(s, "  Page 1: addr=0x%x data=none ==> read value=0x%02x\n",
+-                                         addr, value);
+-              }
+-
+-              if (phy_cfg->page2_size == 0)
+-                      goto out;
+-
+-              seq_puts(s, "Page 2:\n");
+-              /* Set page 2 */
+-              phy_data_page = phy_cfg->page2;
+-              rtk_phy_set_page(phy_reg, 2);
+-
+-              for (i = 0; i < phy_cfg->page2_size; i++) {
+-                      struct phy_data *phy_data = phy_data_page + i;
+-                      u8 addr = array_index_to_page_addr(i);
+-                      u8 data = phy_data->data;
+-                      u8 value = rtk_phy_read(phy_reg, addr);
+-
+-                      if (phy_data->addr)
+-                              seq_printf(s, "  Page 2: addr=0x%x data=0x%02x ==> read value=0x%02x\n",
+-                                         addr, data, value);
+-                      else
+-                              seq_printf(s, "  Page 2: addr=0x%x data=none ==> read value=0x%02x\n",
+-                                         addr, value);
+-              }
+-
+-out:
+-              seq_puts(s, "PHY Property:\n");
+-              seq_printf(s, "  efuse_usb_dc_cal: %d\n",
+-                         (int)phy_parameter->efuse_usb_dc_cal);
+-              seq_printf(s, "  efuse_usb_dc_dis: %d\n",
+-                         (int)phy_parameter->efuse_usb_dc_dis);
+-              seq_printf(s, "  inverse_hstx_sync_clock: %s\n",
+-                         phy_parameter->inverse_hstx_sync_clock ? "Enable" : "Disable");
+-              seq_printf(s, "  driving_level: %d\n",
+-                         phy_parameter->driving_level);
+-              seq_printf(s, "  driving_level_compensate: %d\n",
+-                         phy_parameter->driving_level_compensate);
+-              seq_printf(s, "  disconnection_compensate: %d\n",
+-                         phy_parameter->disconnection_compensate);
+-      }
+-
+-      return 0;
+-}
+-DEFINE_SHOW_ATTRIBUTE(rtk_usb2_parameter);
+-
+-static inline void create_debug_files(struct rtk_phy *rtk_phy)
+-{
+-      struct dentry *phy_debug_root = NULL;
+-
+-      phy_debug_root = create_phy_debug_root();
+-      if (!phy_debug_root)
+-              return;
+-
+-      rtk_phy->debug_dir = debugfs_create_dir(dev_name(rtk_phy->dev),
+-                                              phy_debug_root);
+-
+-      debugfs_create_file("parameter", 0444, rtk_phy->debug_dir, rtk_phy,
+-                          &rtk_usb2_parameter_fops);
+-
+-      return;
+-}
+-
+-static inline void remove_debug_files(struct rtk_phy *rtk_phy)
+-{
+-      debugfs_remove_recursive(rtk_phy->debug_dir);
+-}
+-#else
+-static inline void create_debug_files(struct rtk_phy *rtk_phy) { }
+-static inline void remove_debug_files(struct rtk_phy *rtk_phy) { }
+-#endif /* CONFIG_DEBUG_FS */
+-
+-static int get_phy_data_by_efuse(struct rtk_phy *rtk_phy,
+-                               struct phy_parameter *phy_parameter, int index)
+-{
+-      struct phy_cfg *phy_cfg = rtk_phy->phy_cfg;
+-      u8 value = 0;
+-      struct nvmem_cell *cell;
+-      struct soc_device_attribute rtk_soc_groot[] = {
+-                  { .family = "Realtek Groot",},
+-                  { /* empty */ } };
+-
+-      if (!phy_cfg->check_efuse)
+-              goto out;
+-
+-      /* Read efuse for usb dc cal */
+-      cell = nvmem_cell_get(rtk_phy->dev, "usb-dc-cal");
+-      if (IS_ERR(cell)) {
+-              dev_dbg(rtk_phy->dev, "%s no usb-dc-cal: %ld\n",
+-                      __func__, PTR_ERR(cell));
+-      } else {
+-              unsigned char *buf;
+-              size_t buf_size;
+-
+-              buf = nvmem_cell_read(cell, &buf_size);
+-              if (!IS_ERR(buf)) {
+-                      value = buf[0] & phy_cfg->dc_driving_mask;
+-                      kfree(buf);
+-              }
+-              nvmem_cell_put(cell);
+-      }
+-
+-      if (phy_cfg->check_efuse_version == CHECK_EFUSE_V1) {
+-              int rate = phy_cfg->efuse_dc_driving_rate;
+-
+-              if (value <= EFUS_USB_DC_CAL_MAX)
+-                      phy_parameter->efuse_usb_dc_cal = (int8_t)(value * rate);
+-              else
+-                      phy_parameter->efuse_usb_dc_cal = -(int8_t)
+-                                  ((EFUS_USB_DC_CAL_MAX & value) * rate);
+-
+-              if (soc_device_match(rtk_soc_groot)) {
+-                      dev_dbg(rtk_phy->dev, "For groot IC we need a workaround to adjust efuse_usb_dc_cal\n");
+-
+-                      /* We don't multiple dc_cal_rate=2 for positive dc cal compensate */
+-                      if (value <= EFUS_USB_DC_CAL_MAX)
+-                              phy_parameter->efuse_usb_dc_cal = (int8_t)(value);
+-
+-                      /* We set max dc cal compensate is 0x8 if otp is 0x7 */
+-                      if (value == 0x7)
+-                              phy_parameter->efuse_usb_dc_cal = (int8_t)(value + 1);
+-              }
+-      } else { /* for CHECK_EFUSE_V2 */
+-              phy_parameter->efuse_usb_dc_cal = value & phy_cfg->dc_driving_mask;
+-      }
+-
+-      /* Read efuse for usb dc disconnect level */
+-      value = 0;
+-      cell = nvmem_cell_get(rtk_phy->dev, "usb-dc-dis");
+-      if (IS_ERR(cell)) {
+-              dev_dbg(rtk_phy->dev, "%s no usb-dc-dis: %ld\n",
+-                      __func__, PTR_ERR(cell));
+-      } else {
+-              unsigned char *buf;
+-              size_t buf_size;
+-
+-              buf = nvmem_cell_read(cell, &buf_size);
+-              if (!IS_ERR(buf)) {
+-                      value = buf[0] & phy_cfg->dc_disconnect_mask;
+-                      kfree(buf);
+-              }
+-              nvmem_cell_put(cell);
+-      }
+-
+-      if (phy_cfg->check_efuse_version == CHECK_EFUSE_V1) {
+-              int rate = phy_cfg->efuse_dc_disconnect_rate;
+-
+-              if (value <= EFUS_USB_DC_DIS_MAX)
+-                      phy_parameter->efuse_usb_dc_dis = (int8_t)(value * rate);
+-              else
+-                      phy_parameter->efuse_usb_dc_dis = -(int8_t)
+-                                  ((EFUS_USB_DC_DIS_MAX & value) * rate);
+-      } else { /* for CHECK_EFUSE_V2 */
+-              phy_parameter->efuse_usb_dc_dis = value & phy_cfg->dc_disconnect_mask;
+-      }
+-
+-out:
+-      return 0;
+-}
+-
+-static int parse_phy_data(struct rtk_phy *rtk_phy)
+-{
+-      struct device *dev = rtk_phy->dev;
+-      struct device_node *np = dev->of_node;
+-      struct phy_parameter *phy_parameter;
+-      int ret = 0;
+-      int index;
+-
+-      rtk_phy->phy_parameter = devm_kzalloc(dev, sizeof(struct phy_parameter) *
+-                                              rtk_phy->num_phy, GFP_KERNEL);
+-      if (!rtk_phy->phy_parameter)
+-              return -ENOMEM;
+-
+-      for (index = 0; index < rtk_phy->num_phy; index++) {
+-              phy_parameter = &((struct phy_parameter *)rtk_phy->phy_parameter)[index];
+-
+-              phy_parameter->phy_reg.reg_wrap_vstatus = of_iomap(np, 0);
+-              phy_parameter->phy_reg.reg_gusb2phyacc0 = of_iomap(np, 1) + index;
+-              phy_parameter->phy_reg.vstatus_index = index;
+-
+-              if (of_property_read_bool(np, "realtek,inverse-hstx-sync-clock"))
+-                      phy_parameter->inverse_hstx_sync_clock = true;
+-              else
+-                      phy_parameter->inverse_hstx_sync_clock = false;
+-
+-              if (of_property_read_u32_index(np, "realtek,driving-level",
+-                                             index, &phy_parameter->driving_level))
+-                      phy_parameter->driving_level = DEFAULT_DC_DRIVING_VALUE;
+-
+-              if (of_property_read_u32_index(np, "realtek,driving-level-compensate",
+-                                             index, &phy_parameter->driving_level_compensate))
+-                      phy_parameter->driving_level_compensate = 0;
+-
+-              if (of_property_read_u32_index(np, "realtek,disconnection-compensate",
+-                                             index, &phy_parameter->disconnection_compensate))
+-                      phy_parameter->disconnection_compensate = 0;
+-
+-              get_phy_data_by_efuse(rtk_phy, phy_parameter, index);
+-
+-              update_dc_driving_level(rtk_phy, phy_parameter);
+-
+-              update_hs_clk_select(rtk_phy, phy_parameter);
+-      }
+-
+-      return ret;
+-}
+-
+-static int rtk_usb2phy_probe(struct platform_device *pdev)
+-{
+-      struct rtk_phy *rtk_phy;
+-      struct device *dev = &pdev->dev;
+-      struct phy *generic_phy;
+-      struct phy_provider *phy_provider;
+-      const struct phy_cfg *phy_cfg;
+-      int ret = 0;
+-
+-      phy_cfg = of_device_get_match_data(dev);
+-      if (!phy_cfg) {
+-              dev_err(dev, "phy config are not assigned!\n");
+-              return -EINVAL;
+-      }
+-
+-      rtk_phy = devm_kzalloc(dev, sizeof(*rtk_phy), GFP_KERNEL);
+-      if (!rtk_phy)
+-              return -ENOMEM;
+-
+-      rtk_phy->dev                    = &pdev->dev;
+-      rtk_phy->phy.dev                = rtk_phy->dev;
+-      rtk_phy->phy.label              = "rtk-usb2phy";
+-      rtk_phy->phy.notify_port_status = rtk_phy_notify_port_status;
+-
+-      rtk_phy->phy_cfg = devm_kzalloc(dev, sizeof(*phy_cfg), GFP_KERNEL);
+-
+-      memcpy(rtk_phy->phy_cfg, phy_cfg, sizeof(*phy_cfg));
+-
+-      rtk_phy->num_phy = phy_cfg->num_phy;
+-
+-      ret = parse_phy_data(rtk_phy);
+-      if (ret)
+-              goto err;
+-
+-      platform_set_drvdata(pdev, rtk_phy);
+-
+-      generic_phy = devm_phy_create(rtk_phy->dev, NULL, &ops);
+-      if (IS_ERR(generic_phy))
+-              return PTR_ERR(generic_phy);
+-
+-      phy_set_drvdata(generic_phy, rtk_phy);
+-
+-      phy_provider = devm_of_phy_provider_register(rtk_phy->dev,
+-                                                   of_phy_simple_xlate);
+-      if (IS_ERR(phy_provider))
+-              return PTR_ERR(phy_provider);
+-
+-      ret = usb_add_phy_dev(&rtk_phy->phy);
+-      if (ret)
+-              goto err;
+-
+-      create_debug_files(rtk_phy);
+-
+-err:
+-      return ret;
+-}
+-
+-static void rtk_usb2phy_remove(struct platform_device *pdev)
+-{
+-      struct rtk_phy *rtk_phy = platform_get_drvdata(pdev);
+-
+-      remove_debug_files(rtk_phy);
+-
+-      usb_remove_phy(&rtk_phy->phy);
+-}
+-
+-static const struct phy_cfg rtd1295_phy_cfg = {
+-      .page0_size = MAX_USB_PHY_PAGE0_DATA_SIZE,
+-      .page0 = { [0] = {0xe0, 0x90},
+-                 [3] = {0xe3, 0x3a},
+-                 [4] = {0xe4, 0x68},
+-                 [6] = {0xe6, 0x91},
+-                [13] = {0xf5, 0x81},
+-                [15] = {0xf7, 0x02}, },
+-      .page1_size = 8,
+-      .page1 = { /* default parameter */ },
+-      .page2_size = 0,
+-      .page2 = { /* no parameter */ },
+-      .num_phy = 1,
+-      .check_efuse = false,
+-      .check_efuse_version = CHECK_EFUSE_V1,
+-      .efuse_dc_driving_rate = 1,
+-      .dc_driving_mask = 0xf,
+-      .efuse_dc_disconnect_rate = EFUS_USB_DC_DIS_RATE,
+-      .dc_disconnect_mask = 0xf,
+-      .usb_dc_disconnect_at_page0 = true,
+-      .do_toggle = true,
+-      .do_toggle_driving = false,
+-      .driving_updated_for_dev_dis = 0xf,
+-      .use_default_parameter = false,
+-      .is_double_sensitivity_mode = false,
+-};
+-
+-static const struct phy_cfg rtd1395_phy_cfg = {
+-      .page0_size = MAX_USB_PHY_PAGE0_DATA_SIZE,
+-      .page0 = { [4] = {0xe4, 0xac},
+-                [13] = {0xf5, 0x00},
+-                [15] = {0xf7, 0x02}, },
+-      .page1_size = 8,
+-      .page1 = { /* default parameter */ },
+-      .page2_size = 0,
+-      .page2 = { /* no parameter */ },
+-      .num_phy = 1,
+-      .check_efuse = false,
+-      .check_efuse_version = CHECK_EFUSE_V1,
+-      .efuse_dc_driving_rate = 1,
+-      .dc_driving_mask = 0xf,
+-      .efuse_dc_disconnect_rate = EFUS_USB_DC_DIS_RATE,
+-      .dc_disconnect_mask = 0xf,
+-      .usb_dc_disconnect_at_page0 = true,
+-      .do_toggle = true,
+-      .do_toggle_driving = false,
+-      .driving_updated_for_dev_dis = 0xf,
+-      .use_default_parameter = false,
+-      .is_double_sensitivity_mode = false,
+-};
+-
+-static const struct phy_cfg rtd1395_phy_cfg_2port = {
+-      .page0_size = MAX_USB_PHY_PAGE0_DATA_SIZE,
+-      .page0 = { [4] = {0xe4, 0xac},
+-                [13] = {0xf5, 0x00},
+-                [15] = {0xf7, 0x02}, },
+-      .page1_size = 8,
+-      .page1 = { /* default parameter */ },
+-      .page2_size = 0,
+-      .page2 = { /* no parameter */ },
+-      .num_phy = 2,
+-      .check_efuse = false,
+-      .check_efuse_version = CHECK_EFUSE_V1,
+-      .efuse_dc_driving_rate = 1,
+-      .dc_driving_mask = 0xf,
+-      .efuse_dc_disconnect_rate = EFUS_USB_DC_DIS_RATE,
+-      .dc_disconnect_mask = 0xf,
+-      .usb_dc_disconnect_at_page0 = true,
+-      .do_toggle = true,
+-      .do_toggle_driving = false,
+-      .driving_updated_for_dev_dis = 0xf,
+-      .use_default_parameter = false,
+-      .is_double_sensitivity_mode = false,
+-};
+-
+-static const struct phy_cfg rtd1619_phy_cfg = {
+-      .page0_size = MAX_USB_PHY_PAGE0_DATA_SIZE,
+-      .page0 = { [4] = {0xe4, 0x68}, },
+-      .page1_size = 8,
+-      .page1 = { /* default parameter */ },
+-      .page2_size = 0,
+-      .page2 = { /* no parameter */ },
+-      .num_phy = 1,
+-      .check_efuse = true,
+-      .check_efuse_version = CHECK_EFUSE_V1,
+-      .efuse_dc_driving_rate = 1,
+-      .dc_driving_mask = 0xf,
+-      .efuse_dc_disconnect_rate = EFUS_USB_DC_DIS_RATE,
+-      .dc_disconnect_mask = 0xf,
+-      .usb_dc_disconnect_at_page0 = true,
+-      .do_toggle = true,
+-      .do_toggle_driving = false,
+-      .driving_updated_for_dev_dis = 0xf,
+-      .use_default_parameter = false,
+-      .is_double_sensitivity_mode = false,
+-};
+-
+-static const struct phy_cfg rtd1319_phy_cfg = {
+-      .page0_size = MAX_USB_PHY_PAGE0_DATA_SIZE,
+-      .page0 = { [0] = {0xe0, 0x18},
+-                 [4] = {0xe4, 0x6a},
+-                 [7] = {0xe7, 0x71},
+-                [13] = {0xf5, 0x15},
+-                [15] = {0xf7, 0x32}, },
+-      .page1_size = 8,
+-      .page1 = { [3] = {0xe3, 0x44}, },
+-      .page2_size = MAX_USB_PHY_PAGE2_DATA_SIZE,
+-      .page2 = { [0] = {0xe0, 0x01}, },
+-      .num_phy = 1,
+-      .check_efuse = true,
+-      .check_efuse_version = CHECK_EFUSE_V1,
+-      .efuse_dc_driving_rate = 1,
+-      .dc_driving_mask = 0xf,
+-      .efuse_dc_disconnect_rate = EFUS_USB_DC_DIS_RATE,
+-      .dc_disconnect_mask = 0xf,
+-      .usb_dc_disconnect_at_page0 = true,
+-      .do_toggle = true,
+-      .do_toggle_driving = true,
+-      .driving_updated_for_dev_dis = 0xf,
+-      .use_default_parameter = false,
+-      .is_double_sensitivity_mode = true,
+-};
+-
+-static const struct phy_cfg rtd1312c_phy_cfg = {
+-      .page0_size = MAX_USB_PHY_PAGE0_DATA_SIZE,
+-      .page0 = { [0] = {0xe0, 0x14},
+-                 [4] = {0xe4, 0x67},
+-                 [5] = {0xe5, 0x55}, },
+-      .page1_size = 8,
+-      .page1 = { [3] = {0xe3, 0x23},
+-                 [6] = {0xe6, 0x58}, },
+-      .page2_size = MAX_USB_PHY_PAGE2_DATA_SIZE,
+-      .page2 = { /* default parameter */ },
+-      .num_phy = 1,
+-      .check_efuse = true,
+-      .check_efuse_version = CHECK_EFUSE_V1,
+-      .efuse_dc_driving_rate = 1,
+-      .dc_driving_mask = 0xf,
+-      .efuse_dc_disconnect_rate = EFUS_USB_DC_DIS_RATE,
+-      .dc_disconnect_mask = 0xf,
+-      .usb_dc_disconnect_at_page0 = true,
+-      .do_toggle = true,
+-      .do_toggle_driving = true,
+-      .driving_updated_for_dev_dis = 0xf,
+-      .use_default_parameter = false,
+-      .is_double_sensitivity_mode = true,
+-};
+-
+-static const struct phy_cfg rtd1619b_phy_cfg = {
+-      .page0_size = MAX_USB_PHY_PAGE0_DATA_SIZE,
+-      .page0 = { [0] = {0xe0, 0xa3},
+-                 [4] = {0xe4, 0x88},
+-                 [5] = {0xe5, 0x4f},
+-                 [6] = {0xe6, 0x02}, },
+-      .page1_size = 8,
+-      .page1 = { [3] = {0xe3, 0x64}, },
+-      .page2_size = MAX_USB_PHY_PAGE2_DATA_SIZE,
+-      .page2 = { [7] = {0xe7, 0x45}, },
+-      .num_phy = 1,
+-      .check_efuse = true,
+-      .check_efuse_version = CHECK_EFUSE_V1,
+-      .efuse_dc_driving_rate = EFUS_USB_DC_CAL_RATE,
+-      .dc_driving_mask = 0x1f,
+-      .efuse_dc_disconnect_rate = EFUS_USB_DC_DIS_RATE,
+-      .dc_disconnect_mask = 0xf,
+-      .usb_dc_disconnect_at_page0 = false,
+-      .do_toggle = true,
+-      .do_toggle_driving = true,
+-      .driving_updated_for_dev_dis = 0x8,
+-      .use_default_parameter = false,
+-      .is_double_sensitivity_mode = true,
+-};
+-
+-static const struct phy_cfg rtd1319d_phy_cfg = {
+-      .page0_size = MAX_USB_PHY_PAGE0_DATA_SIZE,
+-      .page0 = { [0] = {0xe0, 0xa3},
+-                 [4] = {0xe4, 0x8e},
+-                 [5] = {0xe5, 0x4f},
+-                 [6] = {0xe6, 0x02}, },
+-      .page1_size = MAX_USB_PHY_PAGE1_DATA_SIZE,
+-      .page1 = { [14] = {0xf5, 0x1}, },
+-      .page2_size = MAX_USB_PHY_PAGE2_DATA_SIZE,
+-      .page2 = { [7] = {0xe7, 0x44}, },
+-      .check_efuse = true,
+-      .num_phy = 1,
+-      .check_efuse_version = CHECK_EFUSE_V1,
+-      .efuse_dc_driving_rate = EFUS_USB_DC_CAL_RATE,
+-      .dc_driving_mask = 0x1f,
+-      .efuse_dc_disconnect_rate = EFUS_USB_DC_DIS_RATE,
+-      .dc_disconnect_mask = 0xf,
+-      .usb_dc_disconnect_at_page0 = false,
+-      .do_toggle = true,
+-      .do_toggle_driving = false,
+-      .driving_updated_for_dev_dis = 0x8,
+-      .use_default_parameter = false,
+-      .is_double_sensitivity_mode = true,
+-};
+-
+-static const struct phy_cfg rtd1315e_phy_cfg = {
+-      .page0_size = MAX_USB_PHY_PAGE0_DATA_SIZE,
+-      .page0 = { [0] = {0xe0, 0xa3},
+-                 [4] = {0xe4, 0x8c},
+-                 [5] = {0xe5, 0x4f},
+-                 [6] = {0xe6, 0x02}, },
+-      .page1_size = MAX_USB_PHY_PAGE1_DATA_SIZE,
+-      .page1 = { [3] = {0xe3, 0x7f},
+-                [14] = {0xf5, 0x01}, },
+-      .page2_size = MAX_USB_PHY_PAGE2_DATA_SIZE,
+-      .page2 = { [7] = {0xe7, 0x44}, },
+-      .num_phy = 1,
+-      .check_efuse = true,
+-      .check_efuse_version = CHECK_EFUSE_V2,
+-      .efuse_dc_driving_rate = EFUS_USB_DC_CAL_RATE,
+-      .dc_driving_mask = 0x1f,
+-      .efuse_dc_disconnect_rate = EFUS_USB_DC_DIS_RATE,
+-      .dc_disconnect_mask = 0xf,
+-      .usb_dc_disconnect_at_page0 = false,
+-      .do_toggle = true,
+-      .do_toggle_driving = false,
+-      .driving_updated_for_dev_dis = 0x8,
+-      .use_default_parameter = false,
+-      .is_double_sensitivity_mode = true,
+-};
+-
+-static const struct of_device_id usbphy_rtk_dt_match[] = {
+-      { .compatible = "realtek,rtd1295-usb2phy", .data = &rtd1295_phy_cfg },
+-      { .compatible = "realtek,rtd1312c-usb2phy", .data = &rtd1312c_phy_cfg },
+-      { .compatible = "realtek,rtd1315e-usb2phy", .data = &rtd1315e_phy_cfg },
+-      { .compatible = "realtek,rtd1319-usb2phy", .data = &rtd1319_phy_cfg },
+-      { .compatible = "realtek,rtd1319d-usb2phy", .data = &rtd1319d_phy_cfg },
+-      { .compatible = "realtek,rtd1395-usb2phy", .data = &rtd1395_phy_cfg },
+-      { .compatible = "realtek,rtd1395-usb2phy-2port", .data = &rtd1395_phy_cfg_2port },
+-      { .compatible = "realtek,rtd1619-usb2phy", .data = &rtd1619_phy_cfg },
+-      { .compatible = "realtek,rtd1619b-usb2phy", .data = &rtd1619b_phy_cfg },
+-      {},
+-};
+-MODULE_DEVICE_TABLE(of, usbphy_rtk_dt_match);
+-
+-static struct platform_driver rtk_usb2phy_driver = {
+-      .probe          = rtk_usb2phy_probe,
+-      .remove_new     = rtk_usb2phy_remove,
+-      .driver         = {
+-              .name   = "rtk-usb2phy",
+-              .of_match_table = usbphy_rtk_dt_match,
+-      },
+-};
+-
+-module_platform_driver(rtk_usb2phy_driver);
+-
+-MODULE_LICENSE("GPL");
+-MODULE_ALIAS("platform: rtk-usb2phy");
+-MODULE_AUTHOR("Stanley Chang <stanley_chang@realtek.com>");
+-MODULE_DESCRIPTION("Realtek usb 2.0 phy driver");
diff --git a/queue-6.6/revert-phy-realtek-usb-add-driver-for-the-realtek-soc-usb-3.0-phy.patch b/queue-6.6/revert-phy-realtek-usb-add-driver-for-the-realtek-soc-usb-3.0-phy.patch
new file mode 100644 (file)
index 0000000..4dfbb6c
--- /dev/null
@@ -0,0 +1,829 @@
+From 258ea41c926b7b3a16d0d7aa210a1401c4a1601b Mon Sep 17 00:00:00 2001
+From: Johan Hovold <johan+linaro@kernel.org>
+Date: Mon, 6 Nov 2023 12:06:52 +0100
+Subject: Revert "phy: realtek: usb: Add driver for the Realtek SoC USB 3.0 PHY"
+
+From: Johan Hovold <johan+linaro@kernel.org>
+
+commit 258ea41c926b7b3a16d0d7aa210a1401c4a1601b upstream.
+
+This reverts commit adda6e82a7de7d6d478f6c8ef127f0ac51c510a1.
+
+The recently added Realtek PHY drivers depend on the new port status
+notification mechanism which was built on the deprecated USB PHY
+implementation and devicetree binding.
+
+Specifically, using these PHYs would require describing the very same
+PHY using both the generic "phy" property and the deprecated "usb-phy"
+property which is clearly wrong.
+
+We should not be building new functionality on top of the legacy USB PHY
+implementation even if it is currently stuck in some kind of
+transitional limbo.
+
+Revert the new Realtek PHY drivers for now so that the port status
+notification interface can be reverted and replaced.
+
+Fixes: adda6e82a7de ("phy: realtek: usb: Add driver for the Realtek SoC USB 3.0 PHY")
+Cc: stable@vger.kernel.org     # 6.6
+Cc: Stanley Chang <stanley_chang@realtek.com>
+Signed-off-by: Johan Hovold <johan+linaro@kernel.org>
+Link: https://lore.kernel.org/r/20231106110654.31090-2-johan+linaro@kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/phy/realtek/Kconfig        |   12 
+ drivers/phy/realtek/Makefile       |    1 
+ drivers/phy/realtek/phy-rtk-usb3.c |  761 -------------------------------------
+ 3 files changed, 774 deletions(-)
+ delete mode 100644 drivers/phy/realtek/phy-rtk-usb3.c
+
+--- a/drivers/phy/realtek/Kconfig
++++ b/drivers/phy/realtek/Kconfig
+@@ -17,16 +17,4 @@ config PHY_RTK_RTD_USB2PHY
+         DWC3 USB IP. This driver will do the PHY initialization
+         of the parameters.
+-config PHY_RTK_RTD_USB3PHY
+-      tristate "Realtek RTD USB3 PHY Transceiver Driver"
+-      depends on USB_SUPPORT
+-      select GENERIC_PHY
+-      select USB_PHY
+-      select USB_COMMON
+-      help
+-        Enable this to support Realtek SoC USB3 phy transceiver.
+-        The DHC (digital home center) RTD series SoCs used the Synopsys
+-        DWC3 USB IP. This driver will do the PHY initialization
+-        of the parameters.
+-
+ endif # ARCH_REALTEK || COMPILE_TEST
+--- a/drivers/phy/realtek/Makefile
++++ b/drivers/phy/realtek/Makefile
+@@ -1,3 +1,2 @@
+ # SPDX-License-Identifier: GPL-2.0
+ obj-$(CONFIG_PHY_RTK_RTD_USB2PHY)     += phy-rtk-usb2.o
+-obj-$(CONFIG_PHY_RTK_RTD_USB3PHY)     += phy-rtk-usb3.o
+--- a/drivers/phy/realtek/phy-rtk-usb3.c
++++ /dev/null
+@@ -1,761 +0,0 @@
+-// SPDX-License-Identifier: GPL-2.0
+-/*
+- *  phy-rtk-usb3.c RTK usb3.0 phy driver
+- *
+- * copyright (c) 2023 realtek semiconductor corporation
+- *
+- */
+-
+-#include <linux/module.h>
+-#include <linux/of.h>
+-#include <linux/of_device.h>
+-#include <linux/of_address.h>
+-#include <linux/uaccess.h>
+-#include <linux/debugfs.h>
+-#include <linux/nvmem-consumer.h>
+-#include <linux/regmap.h>
+-#include <linux/sys_soc.h>
+-#include <linux/mfd/syscon.h>
+-#include <linux/phy/phy.h>
+-#include <linux/usb.h>
+-#include <linux/usb/hcd.h>
+-#include <linux/usb/phy.h>
+-
+-#define USB_MDIO_CTRL_PHY_BUSY BIT(7)
+-#define USB_MDIO_CTRL_PHY_WRITE BIT(0)
+-#define USB_MDIO_CTRL_PHY_ADDR_SHIFT 8
+-#define USB_MDIO_CTRL_PHY_DATA_SHIFT 16
+-
+-#define MAX_USB_PHY_DATA_SIZE 0x30
+-#define PHY_ADDR_0X09 0x09
+-#define PHY_ADDR_0X0B 0x0b
+-#define PHY_ADDR_0X0D 0x0d
+-#define PHY_ADDR_0X10 0x10
+-#define PHY_ADDR_0X1F 0x1f
+-#define PHY_ADDR_0X20 0x20
+-#define PHY_ADDR_0X21 0x21
+-#define PHY_ADDR_0X30 0x30
+-
+-#define REG_0X09_FORCE_CALIBRATION BIT(9)
+-#define REG_0X0B_RX_OFFSET_RANGE_MASK 0xc
+-#define REG_0X0D_RX_DEBUG_TEST_EN BIT(6)
+-#define REG_0X10_DEBUG_MODE_SETTING 0x3c0
+-#define REG_0X10_DEBUG_MODE_SETTING_MASK 0x3f8
+-#define REG_0X1F_RX_OFFSET_CODE_MASK 0x1e
+-
+-#define USB_U3_TX_LFPS_SWING_TRIM_SHIFT 4
+-#define USB_U3_TX_LFPS_SWING_TRIM_MASK 0xf
+-#define AMPLITUDE_CONTROL_COARSE_MASK 0xff
+-#define AMPLITUDE_CONTROL_FINE_MASK 0xffff
+-#define AMPLITUDE_CONTROL_COARSE_DEFAULT 0xff
+-#define AMPLITUDE_CONTROL_FINE_DEFAULT 0xffff
+-
+-#define PHY_ADDR_MAP_ARRAY_INDEX(addr) (addr)
+-#define ARRAY_INDEX_MAP_PHY_ADDR(index) (index)
+-
+-struct phy_reg {
+-      void __iomem *reg_mdio_ctl;
+-};
+-
+-struct phy_data {
+-      u8 addr;
+-      u16 data;
+-};
+-
+-struct phy_cfg {
+-      int param_size;
+-      struct phy_data param[MAX_USB_PHY_DATA_SIZE];
+-
+-      bool check_efuse;
+-      bool do_toggle;
+-      bool do_toggle_once;
+-      bool use_default_parameter;
+-      bool check_rx_front_end_offset;
+-};
+-
+-struct phy_parameter {
+-      struct phy_reg phy_reg;
+-
+-      /* Get from efuse */
+-      u8 efuse_usb_u3_tx_lfps_swing_trim;
+-
+-      /* Get from dts */
+-      u32 amplitude_control_coarse;
+-      u32 amplitude_control_fine;
+-};
+-
+-struct rtk_phy {
+-      struct usb_phy phy;
+-      struct device *dev;
+-
+-      struct phy_cfg *phy_cfg;
+-      int num_phy;
+-      struct phy_parameter *phy_parameter;
+-
+-      struct dentry *debug_dir;
+-};
+-
+-#define PHY_IO_TIMEOUT_USEC           (50000)
+-#define PHY_IO_DELAY_US                       (100)
+-
+-static inline int utmi_wait_register(void __iomem *reg, u32 mask, u32 result)
+-{
+-      int ret;
+-      unsigned int val;
+-
+-      ret = read_poll_timeout(readl, val, ((val & mask) == result),
+-                              PHY_IO_DELAY_US, PHY_IO_TIMEOUT_USEC, false, reg);
+-      if (ret) {
+-              pr_err("%s can't program USB phy\n", __func__);
+-              return -ETIMEDOUT;
+-      }
+-
+-      return 0;
+-}
+-
+-static int rtk_phy3_wait_vbusy(struct phy_reg *phy_reg)
+-{
+-      return utmi_wait_register(phy_reg->reg_mdio_ctl, USB_MDIO_CTRL_PHY_BUSY, 0);
+-}
+-
+-static u16 rtk_phy_read(struct phy_reg *phy_reg, char addr)
+-{
+-      unsigned int tmp;
+-      u32 value;
+-
+-      tmp = (addr << USB_MDIO_CTRL_PHY_ADDR_SHIFT);
+-
+-      writel(tmp, phy_reg->reg_mdio_ctl);
+-
+-      rtk_phy3_wait_vbusy(phy_reg);
+-
+-      value = readl(phy_reg->reg_mdio_ctl);
+-      value = value >> USB_MDIO_CTRL_PHY_DATA_SHIFT;
+-
+-      return (u16)value;
+-}
+-
+-static int rtk_phy_write(struct phy_reg *phy_reg, char addr, u16 data)
+-{
+-      unsigned int val;
+-
+-      val = USB_MDIO_CTRL_PHY_WRITE |
+-                  (addr << USB_MDIO_CTRL_PHY_ADDR_SHIFT) |
+-                  (data << USB_MDIO_CTRL_PHY_DATA_SHIFT);
+-
+-      writel(val, phy_reg->reg_mdio_ctl);
+-
+-      rtk_phy3_wait_vbusy(phy_reg);
+-
+-      return 0;
+-}
+-
+-static void do_rtk_usb3_phy_toggle(struct rtk_phy *rtk_phy, int index, bool connect)
+-{
+-      struct phy_cfg *phy_cfg = rtk_phy->phy_cfg;
+-      struct phy_reg *phy_reg;
+-      struct phy_parameter *phy_parameter;
+-      struct phy_data *phy_data;
+-      u8 addr;
+-      u16 data;
+-      int i;
+-
+-      phy_parameter = &((struct phy_parameter *)rtk_phy->phy_parameter)[index];
+-      phy_reg = &phy_parameter->phy_reg;
+-
+-      if (!phy_cfg->do_toggle)
+-              return;
+-
+-      i = PHY_ADDR_MAP_ARRAY_INDEX(PHY_ADDR_0X09);
+-      phy_data = phy_cfg->param + i;
+-      addr = phy_data->addr;
+-      data = phy_data->data;
+-
+-      if (!addr && !data) {
+-              addr = PHY_ADDR_0X09;
+-              data = rtk_phy_read(phy_reg, addr);
+-              phy_data->addr = addr;
+-              phy_data->data = data;
+-      }
+-
+-      rtk_phy_write(phy_reg, addr, data & (~REG_0X09_FORCE_CALIBRATION));
+-      mdelay(1);
+-      rtk_phy_write(phy_reg, addr, data | REG_0X09_FORCE_CALIBRATION);
+-}
+-
+-static int do_rtk_phy_init(struct rtk_phy *rtk_phy, int index)
+-{
+-      struct phy_cfg *phy_cfg;
+-      struct phy_reg *phy_reg;
+-      struct phy_parameter *phy_parameter;
+-      int i = 0;
+-
+-      phy_cfg = rtk_phy->phy_cfg;
+-      phy_parameter = &((struct phy_parameter *)rtk_phy->phy_parameter)[index];
+-      phy_reg = &phy_parameter->phy_reg;
+-
+-      if (phy_cfg->use_default_parameter)
+-              goto do_toggle;
+-
+-      for (i = 0; i < phy_cfg->param_size; i++) {
+-              struct phy_data *phy_data = phy_cfg->param + i;
+-              u8 addr = phy_data->addr;
+-              u16 data = phy_data->data;
+-
+-              if (!addr && !data)
+-                      continue;
+-
+-              rtk_phy_write(phy_reg, addr, data);
+-      }
+-
+-do_toggle:
+-      if (phy_cfg->do_toggle_once)
+-              phy_cfg->do_toggle = true;
+-
+-      do_rtk_usb3_phy_toggle(rtk_phy, index, false);
+-
+-      if (phy_cfg->do_toggle_once) {
+-              u16 check_value = 0;
+-              int count = 10;
+-              u16 value_0x0d, value_0x10;
+-
+-              /* Enable Debug mode by set 0x0D and 0x10 */
+-              value_0x0d = rtk_phy_read(phy_reg, PHY_ADDR_0X0D);
+-              value_0x10 = rtk_phy_read(phy_reg, PHY_ADDR_0X10);
+-
+-              rtk_phy_write(phy_reg, PHY_ADDR_0X0D,
+-                            value_0x0d | REG_0X0D_RX_DEBUG_TEST_EN);
+-              rtk_phy_write(phy_reg, PHY_ADDR_0X10,
+-                            (value_0x10 & ~REG_0X10_DEBUG_MODE_SETTING_MASK) |
+-                            REG_0X10_DEBUG_MODE_SETTING);
+-
+-              check_value = rtk_phy_read(phy_reg, PHY_ADDR_0X30);
+-
+-              while (!(check_value & BIT(15))) {
+-                      check_value = rtk_phy_read(phy_reg, PHY_ADDR_0X30);
+-                      mdelay(1);
+-                      if (count-- < 0)
+-                              break;
+-              }
+-
+-              if (!(check_value & BIT(15)))
+-                      dev_info(rtk_phy->dev, "toggle fail addr=0x%02x, data=0x%04x\n",
+-                               PHY_ADDR_0X30, check_value);
+-
+-              /* Disable Debug mode by set 0x0D and 0x10 to default*/
+-              rtk_phy_write(phy_reg, PHY_ADDR_0X0D, value_0x0d);
+-              rtk_phy_write(phy_reg, PHY_ADDR_0X10, value_0x10);
+-
+-              phy_cfg->do_toggle = false;
+-      }
+-
+-      if (phy_cfg->check_rx_front_end_offset) {
+-              u16 rx_offset_code, rx_offset_range;
+-              u16 code_mask = REG_0X1F_RX_OFFSET_CODE_MASK;
+-              u16 range_mask = REG_0X0B_RX_OFFSET_RANGE_MASK;
+-              bool do_update = false;
+-
+-              rx_offset_code = rtk_phy_read(phy_reg, PHY_ADDR_0X1F);
+-              if (((rx_offset_code & code_mask) == 0x0) ||
+-                  ((rx_offset_code & code_mask) == code_mask))
+-                      do_update = true;
+-
+-              rx_offset_range = rtk_phy_read(phy_reg, PHY_ADDR_0X0B);
+-              if (((rx_offset_range & range_mask) == range_mask) && do_update) {
+-                      dev_warn(rtk_phy->dev, "Don't update rx_offset_range (rx_offset_code=0x%x, rx_offset_range=0x%x)\n",
+-                               rx_offset_code, rx_offset_range);
+-                      do_update = false;
+-              }
+-
+-              if (do_update) {
+-                      u16 tmp1, tmp2;
+-
+-                      tmp1 = rx_offset_range & (~range_mask);
+-                      tmp2 = rx_offset_range & range_mask;
+-                      tmp2 += (1 << 2);
+-                      rx_offset_range = tmp1 | (tmp2 & range_mask);
+-                      rtk_phy_write(phy_reg, PHY_ADDR_0X0B, rx_offset_range);
+-                      goto do_toggle;
+-              }
+-      }
+-
+-      return 0;
+-}
+-
+-static int rtk_phy_init(struct phy *phy)
+-{
+-      struct rtk_phy *rtk_phy = phy_get_drvdata(phy);
+-      int ret = 0;
+-      int i;
+-      unsigned long phy_init_time = jiffies;
+-
+-      for (i = 0; i < rtk_phy->num_phy; i++)
+-              ret = do_rtk_phy_init(rtk_phy, i);
+-
+-      dev_dbg(rtk_phy->dev, "Initialized RTK USB 3.0 PHY (take %dms)\n",
+-              jiffies_to_msecs(jiffies - phy_init_time));
+-
+-      return ret;
+-}
+-
+-static int rtk_phy_exit(struct phy *phy)
+-{
+-      return 0;
+-}
+-
+-static const struct phy_ops ops = {
+-      .init           = rtk_phy_init,
+-      .exit           = rtk_phy_exit,
+-      .owner          = THIS_MODULE,
+-};
+-
+-static void rtk_phy_toggle(struct usb_phy *usb3_phy, bool connect, int port)
+-{
+-      int index = port;
+-      struct rtk_phy *rtk_phy = NULL;
+-
+-      rtk_phy = dev_get_drvdata(usb3_phy->dev);
+-
+-      if (index > rtk_phy->num_phy) {
+-              dev_err(rtk_phy->dev, "%s: The port=%d is not in usb phy (num_phy=%d)\n",
+-                      __func__, index, rtk_phy->num_phy);
+-              return;
+-      }
+-
+-      do_rtk_usb3_phy_toggle(rtk_phy, index, connect);
+-}
+-
+-static int rtk_phy_notify_port_status(struct usb_phy *x, int port,
+-                                    u16 portstatus, u16 portchange)
+-{
+-      bool connect = false;
+-
+-      pr_debug("%s port=%d portstatus=0x%x portchange=0x%x\n",
+-               __func__, port, (int)portstatus, (int)portchange);
+-      if (portstatus & USB_PORT_STAT_CONNECTION)
+-              connect = true;
+-
+-      if (portchange & USB_PORT_STAT_C_CONNECTION)
+-              rtk_phy_toggle(x, connect, port);
+-
+-      return 0;
+-}
+-
+-#ifdef CONFIG_DEBUG_FS
+-static struct dentry *create_phy_debug_root(void)
+-{
+-      struct dentry *phy_debug_root;
+-
+-      phy_debug_root = debugfs_lookup("phy", usb_debug_root);
+-      if (!phy_debug_root)
+-              phy_debug_root = debugfs_create_dir("phy", usb_debug_root);
+-
+-      return phy_debug_root;
+-}
+-
+-static int rtk_usb3_parameter_show(struct seq_file *s, void *unused)
+-{
+-      struct rtk_phy *rtk_phy = s->private;
+-      struct phy_cfg *phy_cfg;
+-      int i, index;
+-
+-      phy_cfg = rtk_phy->phy_cfg;
+-
+-      seq_puts(s, "Property:\n");
+-      seq_printf(s, "  check_efuse: %s\n",
+-                 phy_cfg->check_efuse ? "Enable" : "Disable");
+-      seq_printf(s, "  do_toggle: %s\n",
+-                 phy_cfg->do_toggle ? "Enable" : "Disable");
+-      seq_printf(s, "  do_toggle_once: %s\n",
+-                 phy_cfg->do_toggle_once ? "Enable" : "Disable");
+-      seq_printf(s, "  use_default_parameter: %s\n",
+-                 phy_cfg->use_default_parameter ? "Enable" : "Disable");
+-
+-      for (index = 0; index < rtk_phy->num_phy; index++) {
+-              struct phy_reg *phy_reg;
+-              struct phy_parameter *phy_parameter;
+-
+-              phy_parameter = &((struct phy_parameter *)rtk_phy->phy_parameter)[index];
+-              phy_reg = &phy_parameter->phy_reg;
+-
+-              seq_printf(s, "PHY %d:\n", index);
+-
+-              for (i = 0; i < phy_cfg->param_size; i++) {
+-                      struct phy_data *phy_data = phy_cfg->param + i;
+-                      u8 addr = ARRAY_INDEX_MAP_PHY_ADDR(i);
+-                      u16 data = phy_data->data;
+-
+-                      if (!phy_data->addr && !data)
+-                              seq_printf(s, "  addr = 0x%02x, data = none   ==> read value = 0x%04x\n",
+-                                         addr, rtk_phy_read(phy_reg, addr));
+-                      else
+-                              seq_printf(s, "  addr = 0x%02x, data = 0x%04x ==> read value = 0x%04x\n",
+-                                         addr, data, rtk_phy_read(phy_reg, addr));
+-              }
+-
+-              seq_puts(s, "PHY Property:\n");
+-              seq_printf(s, "  efuse_usb_u3_tx_lfps_swing_trim: 0x%x\n",
+-                         (int)phy_parameter->efuse_usb_u3_tx_lfps_swing_trim);
+-              seq_printf(s, "  amplitude_control_coarse: 0x%x\n",
+-                         (int)phy_parameter->amplitude_control_coarse);
+-              seq_printf(s, "  amplitude_control_fine: 0x%x\n",
+-                         (int)phy_parameter->amplitude_control_fine);
+-      }
+-
+-      return 0;
+-}
+-DEFINE_SHOW_ATTRIBUTE(rtk_usb3_parameter);
+-
+-static inline void create_debug_files(struct rtk_phy *rtk_phy)
+-{
+-      struct dentry *phy_debug_root = NULL;
+-
+-      phy_debug_root = create_phy_debug_root();
+-
+-      if (!phy_debug_root)
+-              return;
+-
+-      rtk_phy->debug_dir = debugfs_create_dir(dev_name(rtk_phy->dev), phy_debug_root);
+-
+-      debugfs_create_file("parameter", 0444, rtk_phy->debug_dir, rtk_phy,
+-                          &rtk_usb3_parameter_fops);
+-
+-      return;
+-}
+-
+-static inline void remove_debug_files(struct rtk_phy *rtk_phy)
+-{
+-      debugfs_remove_recursive(rtk_phy->debug_dir);
+-}
+-#else
+-static inline void create_debug_files(struct rtk_phy *rtk_phy) { }
+-static inline void remove_debug_files(struct rtk_phy *rtk_phy) { }
+-#endif /* CONFIG_DEBUG_FS */
+-
+-static int get_phy_data_by_efuse(struct rtk_phy *rtk_phy,
+-                               struct phy_parameter *phy_parameter, int index)
+-{
+-      struct phy_cfg *phy_cfg = rtk_phy->phy_cfg;
+-      u8 value = 0;
+-      struct nvmem_cell *cell;
+-
+-      if (!phy_cfg->check_efuse)
+-              goto out;
+-
+-      cell = nvmem_cell_get(rtk_phy->dev, "usb_u3_tx_lfps_swing_trim");
+-      if (IS_ERR(cell)) {
+-              dev_dbg(rtk_phy->dev, "%s no usb_u3_tx_lfps_swing_trim: %ld\n",
+-                      __func__, PTR_ERR(cell));
+-      } else {
+-              unsigned char *buf;
+-              size_t buf_size;
+-
+-              buf = nvmem_cell_read(cell, &buf_size);
+-              if (!IS_ERR(buf)) {
+-                      value = buf[0] & USB_U3_TX_LFPS_SWING_TRIM_MASK;
+-                      kfree(buf);
+-              }
+-              nvmem_cell_put(cell);
+-      }
+-
+-      if (value > 0 && value < 0x8)
+-              phy_parameter->efuse_usb_u3_tx_lfps_swing_trim = 0x8;
+-      else
+-              phy_parameter->efuse_usb_u3_tx_lfps_swing_trim = (u8)value;
+-
+-out:
+-      return 0;
+-}
+-
+-static void update_amplitude_control_value(struct rtk_phy *rtk_phy,
+-                                         struct phy_parameter *phy_parameter)
+-{
+-      struct phy_cfg *phy_cfg;
+-      struct phy_reg *phy_reg;
+-
+-      phy_reg = &phy_parameter->phy_reg;
+-      phy_cfg = rtk_phy->phy_cfg;
+-
+-      if (phy_parameter->amplitude_control_coarse != AMPLITUDE_CONTROL_COARSE_DEFAULT) {
+-              u16 val_mask = AMPLITUDE_CONTROL_COARSE_MASK;
+-              u16 data;
+-
+-              if (!phy_cfg->param[PHY_ADDR_0X20].addr && !phy_cfg->param[PHY_ADDR_0X20].data) {
+-                      phy_cfg->param[PHY_ADDR_0X20].addr = PHY_ADDR_0X20;
+-                      data = rtk_phy_read(phy_reg, PHY_ADDR_0X20);
+-              } else {
+-                      data = phy_cfg->param[PHY_ADDR_0X20].data;
+-              }
+-
+-              data &= (~val_mask);
+-              data |= (phy_parameter->amplitude_control_coarse & val_mask);
+-
+-              phy_cfg->param[PHY_ADDR_0X20].data = data;
+-      }
+-
+-      if (phy_parameter->efuse_usb_u3_tx_lfps_swing_trim) {
+-              u8 efuse_val = phy_parameter->efuse_usb_u3_tx_lfps_swing_trim;
+-              u16 val_mask = USB_U3_TX_LFPS_SWING_TRIM_MASK;
+-              int val_shift = USB_U3_TX_LFPS_SWING_TRIM_SHIFT;
+-              u16 data;
+-
+-              if (!phy_cfg->param[PHY_ADDR_0X20].addr && !phy_cfg->param[PHY_ADDR_0X20].data) {
+-                      phy_cfg->param[PHY_ADDR_0X20].addr = PHY_ADDR_0X20;
+-                      data = rtk_phy_read(phy_reg, PHY_ADDR_0X20);
+-              } else {
+-                      data = phy_cfg->param[PHY_ADDR_0X20].data;
+-              }
+-
+-              data &= ~(val_mask << val_shift);
+-              data |= ((efuse_val & val_mask) << val_shift);
+-
+-              phy_cfg->param[PHY_ADDR_0X20].data = data;
+-      }
+-
+-      if (phy_parameter->amplitude_control_fine != AMPLITUDE_CONTROL_FINE_DEFAULT) {
+-              u16 val_mask = AMPLITUDE_CONTROL_FINE_MASK;
+-
+-              if (!phy_cfg->param[PHY_ADDR_0X21].addr && !phy_cfg->param[PHY_ADDR_0X21].data)
+-                      phy_cfg->param[PHY_ADDR_0X21].addr = PHY_ADDR_0X21;
+-
+-              phy_cfg->param[PHY_ADDR_0X21].data =
+-                          phy_parameter->amplitude_control_fine & val_mask;
+-      }
+-}
+-
+-static int parse_phy_data(struct rtk_phy *rtk_phy)
+-{
+-      struct device *dev = rtk_phy->dev;
+-      struct phy_parameter *phy_parameter;
+-      int ret = 0;
+-      int index;
+-
+-      rtk_phy->phy_parameter = devm_kzalloc(dev, sizeof(struct phy_parameter) *
+-                                            rtk_phy->num_phy, GFP_KERNEL);
+-      if (!rtk_phy->phy_parameter)
+-              return -ENOMEM;
+-
+-      for (index = 0; index < rtk_phy->num_phy; index++) {
+-              phy_parameter = &((struct phy_parameter *)rtk_phy->phy_parameter)[index];
+-
+-              phy_parameter->phy_reg.reg_mdio_ctl = of_iomap(dev->of_node, 0) + index;
+-
+-              /* Amplitude control address 0x20 bit 0 to bit 7 */
+-              if (of_property_read_u32(dev->of_node, "realtek,amplitude-control-coarse-tuning",
+-                                       &phy_parameter->amplitude_control_coarse))
+-                      phy_parameter->amplitude_control_coarse = AMPLITUDE_CONTROL_COARSE_DEFAULT;
+-
+-              /* Amplitude control address 0x21 bit 0 to bit 16 */
+-              if (of_property_read_u32(dev->of_node, "realtek,amplitude-control-fine-tuning",
+-                                       &phy_parameter->amplitude_control_fine))
+-                      phy_parameter->amplitude_control_fine = AMPLITUDE_CONTROL_FINE_DEFAULT;
+-
+-              get_phy_data_by_efuse(rtk_phy, phy_parameter, index);
+-
+-              update_amplitude_control_value(rtk_phy, phy_parameter);
+-      }
+-
+-      return ret;
+-}
+-
+-static int rtk_usb3phy_probe(struct platform_device *pdev)
+-{
+-      struct rtk_phy *rtk_phy;
+-      struct device *dev = &pdev->dev;
+-      struct phy *generic_phy;
+-      struct phy_provider *phy_provider;
+-      const struct phy_cfg *phy_cfg;
+-      int ret;
+-
+-      phy_cfg = of_device_get_match_data(dev);
+-      if (!phy_cfg) {
+-              dev_err(dev, "phy config are not assigned!\n");
+-              return -EINVAL;
+-      }
+-
+-      rtk_phy = devm_kzalloc(dev, sizeof(*rtk_phy), GFP_KERNEL);
+-      if (!rtk_phy)
+-              return -ENOMEM;
+-
+-      rtk_phy->dev                    = &pdev->dev;
+-      rtk_phy->phy.dev                = rtk_phy->dev;
+-      rtk_phy->phy.label              = "rtk-usb3phy";
+-      rtk_phy->phy.notify_port_status = rtk_phy_notify_port_status;
+-
+-      rtk_phy->phy_cfg = devm_kzalloc(dev, sizeof(*phy_cfg), GFP_KERNEL);
+-
+-      memcpy(rtk_phy->phy_cfg, phy_cfg, sizeof(*phy_cfg));
+-
+-      rtk_phy->num_phy = 1;
+-
+-      ret = parse_phy_data(rtk_phy);
+-      if (ret)
+-              goto err;
+-
+-      platform_set_drvdata(pdev, rtk_phy);
+-
+-      generic_phy = devm_phy_create(rtk_phy->dev, NULL, &ops);
+-      if (IS_ERR(generic_phy))
+-              return PTR_ERR(generic_phy);
+-
+-      phy_set_drvdata(generic_phy, rtk_phy);
+-
+-      phy_provider = devm_of_phy_provider_register(rtk_phy->dev, of_phy_simple_xlate);
+-      if (IS_ERR(phy_provider))
+-              return PTR_ERR(phy_provider);
+-
+-      ret = usb_add_phy_dev(&rtk_phy->phy);
+-      if (ret)
+-              goto err;
+-
+-      create_debug_files(rtk_phy);
+-
+-err:
+-      return ret;
+-}
+-
+-static void rtk_usb3phy_remove(struct platform_device *pdev)
+-{
+-      struct rtk_phy *rtk_phy = platform_get_drvdata(pdev);
+-
+-      remove_debug_files(rtk_phy);
+-
+-      usb_remove_phy(&rtk_phy->phy);
+-}
+-
+-static const struct phy_cfg rtd1295_phy_cfg = {
+-      .param_size = MAX_USB_PHY_DATA_SIZE,
+-      .param = {  [0] = {0x01, 0x4008},  [1] = {0x01, 0xe046},
+-                  [2] = {0x02, 0x6046},  [3] = {0x03, 0x2779},
+-                  [4] = {0x04, 0x72f5},  [5] = {0x05, 0x2ad3},
+-                  [6] = {0x06, 0x000e},  [7] = {0x07, 0x2e00},
+-                  [8] = {0x08, 0x3591},  [9] = {0x09, 0x525c},
+-                 [10] = {0x0a, 0xa600}, [11] = {0x0b, 0xa904},
+-                 [12] = {0x0c, 0xc000}, [13] = {0x0d, 0xef1c},
+-                 [14] = {0x0e, 0x2000}, [15] = {0x0f, 0x0000},
+-                 [16] = {0x10, 0x000c}, [17] = {0x11, 0x4c00},
+-                 [18] = {0x12, 0xfc00}, [19] = {0x13, 0x0c81},
+-                 [20] = {0x14, 0xde01}, [21] = {0x15, 0x0000},
+-                 [22] = {0x16, 0x0000}, [23] = {0x17, 0x0000},
+-                 [24] = {0x18, 0x0000}, [25] = {0x19, 0x4004},
+-                 [26] = {0x1a, 0x1260}, [27] = {0x1b, 0xff00},
+-                 [28] = {0x1c, 0xcb00}, [29] = {0x1d, 0xa03f},
+-                 [30] = {0x1e, 0xc2e0}, [31] = {0x1f, 0x2807},
+-                 [32] = {0x20, 0x947a}, [33] = {0x21, 0x88aa},
+-                 [34] = {0x22, 0x0057}, [35] = {0x23, 0xab66},
+-                 [36] = {0x24, 0x0800}, [37] = {0x25, 0x0000},
+-                 [38] = {0x26, 0x040a}, [39] = {0x27, 0x01d6},
+-                 [40] = {0x28, 0xf8c2}, [41] = {0x29, 0x3080},
+-                 [42] = {0x2a, 0x3082}, [43] = {0x2b, 0x2078},
+-                 [44] = {0x2c, 0xffff}, [45] = {0x2d, 0xffff},
+-                 [46] = {0x2e, 0x0000}, [47] = {0x2f, 0x0040}, },
+-      .check_efuse = false,
+-      .do_toggle = true,
+-      .do_toggle_once = false,
+-      .use_default_parameter = false,
+-      .check_rx_front_end_offset = false,
+-};
+-
+-static const struct phy_cfg rtd1619_phy_cfg = {
+-      .param_size = MAX_USB_PHY_DATA_SIZE,
+-      .param = {  [8] = {0x08, 0x3591},
+-                 [38] = {0x26, 0x840b},
+-                 [40] = {0x28, 0xf842}, },
+-      .check_efuse = false,
+-      .do_toggle = true,
+-      .do_toggle_once = false,
+-      .use_default_parameter = false,
+-      .check_rx_front_end_offset = false,
+-};
+-
+-static const struct phy_cfg rtd1319_phy_cfg = {
+-      .param_size = MAX_USB_PHY_DATA_SIZE,
+-      .param = {  [1] = {0x01, 0xac86},
+-                  [6] = {0x06, 0x0003},
+-                  [9] = {0x09, 0x924c},
+-                 [10] = {0x0a, 0xa608},
+-                 [11] = {0x0b, 0xb905},
+-                 [14] = {0x0e, 0x2010},
+-                 [32] = {0x20, 0x705a},
+-                 [33] = {0x21, 0xf645},
+-                 [34] = {0x22, 0x0013},
+-                 [35] = {0x23, 0xcb66},
+-                 [41] = {0x29, 0xff00}, },
+-      .check_efuse = true,
+-      .do_toggle = true,
+-      .do_toggle_once = false,
+-      .use_default_parameter = false,
+-      .check_rx_front_end_offset = false,
+-};
+-
+-static const struct phy_cfg rtd1619b_phy_cfg = {
+-      .param_size = MAX_USB_PHY_DATA_SIZE,
+-      .param = {  [1] = {0x01, 0xac8c},
+-                  [6] = {0x06, 0x0017},
+-                  [9] = {0x09, 0x724c},
+-                 [10] = {0x0a, 0xb610},
+-                 [11] = {0x0b, 0xb90d},
+-                 [13] = {0x0d, 0xef2a},
+-                 [15] = {0x0f, 0x9050},
+-                 [16] = {0x10, 0x000c},
+-                 [32] = {0x20, 0x70ff},
+-                 [34] = {0x22, 0x0013},
+-                 [35] = {0x23, 0xdb66},
+-                 [38] = {0x26, 0x8609},
+-                 [41] = {0x29, 0xff13},
+-                 [42] = {0x2a, 0x3070}, },
+-      .check_efuse = true,
+-      .do_toggle = false,
+-      .do_toggle_once = true,
+-      .use_default_parameter = false,
+-      .check_rx_front_end_offset = false,
+-};
+-
+-static const  struct phy_cfg rtd1319d_phy_cfg = {
+-      .param_size = MAX_USB_PHY_DATA_SIZE,
+-      .param = {  [1] = {0x01, 0xac89},
+-                  [4] = {0x04, 0xf2f5},
+-                  [6] = {0x06, 0x0017},
+-                  [9] = {0x09, 0x424c},
+-                 [10] = {0x0a, 0x9610},
+-                 [11] = {0x0b, 0x9901},
+-                 [12] = {0x0c, 0xf000},
+-                 [13] = {0x0d, 0xef2a},
+-                 [14] = {0x0e, 0x1000},
+-                 [15] = {0x0f, 0x9050},
+-                 [32] = {0x20, 0x7077},
+-                 [35] = {0x23, 0x0b62},
+-                 [37] = {0x25, 0x10ec},
+-                 [42] = {0x2a, 0x3070}, },
+-      .check_efuse = true,
+-      .do_toggle = false,
+-      .do_toggle_once = true,
+-      .use_default_parameter = false,
+-      .check_rx_front_end_offset = true,
+-};
+-
+-static const struct of_device_id usbphy_rtk_dt_match[] = {
+-      { .compatible = "realtek,rtd1295-usb3phy", .data = &rtd1295_phy_cfg },
+-      { .compatible = "realtek,rtd1319-usb3phy", .data = &rtd1319_phy_cfg },
+-      { .compatible = "realtek,rtd1319d-usb3phy", .data = &rtd1319d_phy_cfg },
+-      { .compatible = "realtek,rtd1619-usb3phy", .data = &rtd1619_phy_cfg },
+-      { .compatible = "realtek,rtd1619b-usb3phy", .data = &rtd1619b_phy_cfg },
+-      {},
+-};
+-MODULE_DEVICE_TABLE(of, usbphy_rtk_dt_match);
+-
+-static struct platform_driver rtk_usb3phy_driver = {
+-      .probe          = rtk_usb3phy_probe,
+-      .remove_new     = rtk_usb3phy_remove,
+-      .driver         = {
+-              .name   = "rtk-usb3phy",
+-              .of_match_table = usbphy_rtk_dt_match,
+-      },
+-};
+-
+-module_platform_driver(rtk_usb3phy_driver);
+-
+-MODULE_LICENSE("GPL");
+-MODULE_ALIAS("platform: rtk-usb3phy");
+-MODULE_AUTHOR("Stanley Chang <stanley_chang@realtek.com>");
+-MODULE_DESCRIPTION("Realtek usb 3.0 phy driver");
diff --git a/queue-6.6/revert-usb-phy-add-usb-phy-notify-port-status-api.patch b/queue-6.6/revert-usb-phy-add-usb-phy-notify-port-status-api.patch
new file mode 100644 (file)
index 0000000..b85b574
--- /dev/null
@@ -0,0 +1,105 @@
+From 1a229d8690a0f8951fc4aa8b76a7efab0d8de342 Mon Sep 17 00:00:00 2001
+From: Johan Hovold <johan+linaro@kernel.org>
+Date: Mon, 6 Nov 2023 12:06:54 +0100
+Subject: Revert "usb: phy: add usb phy notify port status API"
+
+From: Johan Hovold <johan+linaro@kernel.org>
+
+commit 1a229d8690a0f8951fc4aa8b76a7efab0d8de342 upstream.
+
+This reverts commit a08799cf17c22375752abfad3b4a2b34b3acb287.
+
+The recently added Realtek PHY drivers depend on the new port status
+notification mechanism which was built on the deprecated USB PHY
+implementation and devicetree binding.
+
+Specifically, using these PHYs would require describing the very same
+PHY using both the generic "phy" property and the deprecated "usb-phy"
+property which is clearly wrong.
+
+We should not be building new functionality on top of the legacy USB PHY
+implementation even if it is currently stuck in some kind of
+transitional limbo.
+
+Revert the new notification interface which is broken by design.
+
+Fixes: a08799cf17c2 ("usb: phy: add usb phy notify port status API")
+Cc: stable@vger.kernel.org      # 6.6
+Cc: Stanley Chang <stanley_chang@realtek.com>
+Signed-off-by: Johan Hovold <johan+linaro@kernel.org>
+Link: https://lore.kernel.org/r/20231106110654.31090-4-johan+linaro@kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/core/hub.c  | 23 -----------------------
+ include/linux/usb/phy.h | 13 -------------
+ 2 files changed, 36 deletions(-)
+
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index b4584a0cd484..87480a6e6d93 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -622,29 +622,6 @@ static int hub_ext_port_status(struct usb_hub *hub, int port1, int type,
+               ret = 0;
+       }
+       mutex_unlock(&hub->status_mutex);
+-
+-      /*
+-       * There is no need to lock status_mutex here, because status_mutex
+-       * protects hub->status, and the phy driver only checks the port
+-       * status without changing the status.
+-       */
+-      if (!ret) {
+-              struct usb_device *hdev = hub->hdev;
+-
+-              /*
+-               * Only roothub will be notified of port state changes,
+-               * since the USB PHY only cares about changes at the next
+-               * level.
+-               */
+-              if (is_root_hub(hdev)) {
+-                      struct usb_hcd *hcd = bus_to_hcd(hdev->bus);
+-
+-                      if (hcd->usb_phy)
+-                              usb_phy_notify_port_status(hcd->usb_phy,
+-                                                         port1 - 1, *status, *change);
+-              }
+-      }
+-
+       return ret;
+ }
+diff --git a/include/linux/usb/phy.h b/include/linux/usb/phy.h
+index b513749582d7..e4de6bc1f69b 100644
+--- a/include/linux/usb/phy.h
++++ b/include/linux/usb/phy.h
+@@ -144,10 +144,6 @@ struct usb_phy {
+        */
+       int     (*set_wakeup)(struct usb_phy *x, bool enabled);
+-      /* notify phy port status change */
+-      int     (*notify_port_status)(struct usb_phy *x, int port,
+-                                    u16 portstatus, u16 portchange);
+-
+       /* notify phy connect status change */
+       int     (*notify_connect)(struct usb_phy *x,
+                       enum usb_device_speed speed);
+@@ -320,15 +316,6 @@ usb_phy_set_wakeup(struct usb_phy *x, bool enabled)
+               return 0;
+ }
+-static inline int
+-usb_phy_notify_port_status(struct usb_phy *x, int port, u16 portstatus, u16 portchange)
+-{
+-      if (x && x->notify_port_status)
+-              return x->notify_port_status(x, port, portstatus, portchange);
+-      else
+-              return 0;
+-}
+-
+ static inline int
+ usb_phy_notify_connect(struct usb_phy *x, enum usb_device_speed speed)
+ {
+-- 
+2.43.0
+
diff --git a/queue-6.6/s390-dasd-protect-device-queue-against-concurrent-access.patch b/queue-6.6/s390-dasd-protect-device-queue-against-concurrent-access.patch
new file mode 100644 (file)
index 0000000..a3ee227
--- /dev/null
@@ -0,0 +1,69 @@
+From db46cd1e0426f52999d50fa72cfa97fa39952885 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Jan=20H=C3=B6ppner?= <hoeppner@linux.ibm.com>
+Date: Wed, 25 Oct 2023 15:24:37 +0200
+Subject: s390/dasd: protect device queue against concurrent access
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Jan Höppner <hoeppner@linux.ibm.com>
+
+commit db46cd1e0426f52999d50fa72cfa97fa39952885 upstream.
+
+In dasd_profile_start() the amount of requests on the device queue are
+counted. The access to the device queue is unprotected against
+concurrent access. With a lot of parallel I/O, especially with alias
+devices enabled, the device queue can change while dasd_profile_start()
+is accessing the queue. In the worst case this leads to a kernel panic
+due to incorrect pointer accesses.
+
+Fix this by taking the device lock before accessing the queue and
+counting the requests. Additionally the check for a valid profile data
+pointer can be done earlier to avoid unnecessary locking in a hot path.
+
+Cc:  <stable@vger.kernel.org>
+Fixes: 4fa52aa7a82f ("[S390] dasd: add enhanced DASD statistics interface")
+Reviewed-by: Stefan Haberland <sth@linux.ibm.com>
+Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
+Signed-off-by: Stefan Haberland <sth@linux.ibm.com>
+Link: https://lore.kernel.org/r/20231025132437.1223363-3-sth@linux.ibm.com
+Signed-off-by: Jens Axboe <axboe@kernel.dk>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/s390/block/dasd.c |   24 +++++++++++++-----------
+ 1 file changed, 13 insertions(+), 11 deletions(-)
+
+--- a/drivers/s390/block/dasd.c
++++ b/drivers/s390/block/dasd.c
+@@ -674,18 +674,20 @@ static void dasd_profile_start(struct da
+        * we count each request only once.
+        */
+       device = cqr->startdev;
+-      if (device->profile.data) {
+-              counter = 1; /* request is not yet queued on the start device */
+-              list_for_each(l, &device->ccw_queue)
+-                      if (++counter >= 31)
+-                              break;
+-      }
++      if (!device->profile.data)
++              return;
++
++      spin_lock(get_ccwdev_lock(device->cdev));
++      counter = 1; /* request is not yet queued on the start device */
++      list_for_each(l, &device->ccw_queue)
++              if (++counter >= 31)
++                      break;
++      spin_unlock(get_ccwdev_lock(device->cdev));
++
+       spin_lock(&device->profile.lock);
+-      if (device->profile.data) {
+-              device->profile.data->dasd_io_nr_req[counter]++;
+-              if (rq_data_dir(req) == READ)
+-                      device->profile.data->dasd_read_nr_req[counter]++;
+-      }
++      device->profile.data->dasd_io_nr_req[counter]++;
++      if (rq_data_dir(req) == READ)
++              device->profile.data->dasd_read_nr_req[counter]++;
+       spin_unlock(&device->profile.lock);
+ }
index 3c78523897a528f390df4256cb268c8edec0d2c5..b266b57c8c631f270e89c90b5a5a92fb7b9fd58d 100644 (file)
@@ -56,6 +56,36 @@ usb-dwc3-qcom-fix-acpi-platform-device-leak.patch
 lockdep-fix-block-chain-corruption.patch
 mm-add-a-no_inherit-flag-to-the-pr_set_mdwe-prctl.patch
 prctl-disable-prctl-pr_set_mdwe-on-parisc.patch
+kselftest-arm64-fix-output-formatting-for-za-fork.patch
+drm-msm-dpu-add-missing-safe_lut_tbl-in-sc8280xp-catalog.patch
+drm-ast-disconnect-bmc-if-physical-connector-is-connected.patch
+thunderbolt-set-lane-bonding-bit-only-for-downstream-port.patch
+acpi-video-use-acpi_device_fix_up_power_children.patch
+acpi-processor_idle-use-raw_safe_halt-in-acpi_idle_play_dead.patch
+acpi-resource-skip-irq-override-on-asus-expertbook-b1402cva.patch
+acpi-pm-add-acpi_device_fix_up_power_children-function.patch
+swiotlb-xen-provide-the-max_mapping_size-method.patch
+tls-fix-null-deref-on-tls_sw_splice_eof-with-empty-record.patch
+io_uring-fix-off-by-one-bvec-index.patch
+bcache-replace-a-mistaken-is_err-by-is_err_or_null-in-btree_gc_coalesce.patch
+md-fix-bi_status-reporting-in-md_end_clone_io.patch
+bcache-fixup-multi-threaded-bch_sectors_dirty_init-wake-up-race.patch
+io_uring-fs-consider-link-flags-when-getting-path-for-linkat.patch
+s390-dasd-protect-device-queue-against-concurrent-access.patch
+platform-x86-hp-bioscfg-simplify-return-check-in-hp_add_other_attributes.patch
+platform-x86-hp-bioscfg-move-mutex_lock-down-in-hp_add_other_attributes.patch
+platform-x86-hp-bioscfg-fix-error-handling-in-hp_add_other_attributes.patch
+dt-bindings-usb-microchip-usb5744-add-second-supply.patch
+usb-misc-onboard-hub-add-support-for-microchip-usb5744.patch
+usb-serial-option-add-luat-air72-u-series-products.patch
+platform-x86-amd-pmc-adjust-getting-dram-size-behavior.patch
+platform-x86-ideapad-laptop-set-max_brightness-before-using-it.patch
+hv_netvsc-fix-race-of-netvsc-and-vf-register_netdevice.patch
+hv_netvsc-fix-race-of-register_netdevice_notifier-and-vf-register.patch
+hv_netvsc-mark-vf-as-slave-before-exposing-it-to-user-mode.patch
+revert-usb-phy-add-usb-phy-notify-port-status-api.patch
+revert-phy-realtek-usb-add-driver-for-the-realtek-soc-usb-3.0-phy.patch
+revert-phy-realtek-usb-add-driver-for-the-realtek-soc-usb-2.0-phy.patch
 cifs-distribute-channels-across-interfaces-based-on-.patch
 cifs-account-for-primary-channel-in-the-interface-li.patch
 cifs-fix-leak-of-iface-for-primary-channel.patch
diff --git a/queue-6.6/swiotlb-xen-provide-the-max_mapping_size-method.patch b/queue-6.6/swiotlb-xen-provide-the-max_mapping_size-method.patch
new file mode 100644 (file)
index 0000000..3a57f90
--- /dev/null
@@ -0,0 +1,53 @@
+From bff2a2d453a1b683378b4508b86b84389f551a00 Mon Sep 17 00:00:00 2001
+From: Keith Busch <kbusch@kernel.org>
+Date: Mon, 6 Nov 2023 18:12:30 +0100
+Subject: swiotlb-xen: provide the "max_mapping_size" method
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Keith Busch <kbusch@kernel.org>
+
+commit bff2a2d453a1b683378b4508b86b84389f551a00 upstream.
+
+There's a bug that when using the XEN hypervisor with bios with large
+multi-page bio vectors on NVMe, the kernel deadlocks [1].
+
+The deadlocks are caused by inability to map a large bio vector -
+dma_map_sgtable always returns an error, this gets propagated to the block
+layer as BLK_STS_RESOURCE and the block layer retries the request
+indefinitely.
+
+XEN uses the swiotlb framework to map discontiguous pages into contiguous
+runs that are submitted to the PCIe device. The swiotlb framework has a
+limitation on the length of a mapping - this needs to be announced with
+the max_mapping_size method to make sure that the hardware drivers do not
+create larger mappings.
+
+Without max_mapping_size, the NVMe block driver would create large
+mappings that overrun the maximum mapping size.
+
+Reported-by: Marek Marczykowski-Górecki <marmarek@invisiblethingslab.com>
+Link: https://lore.kernel.org/stable/ZTNH0qtmint%2FzLJZ@mail-itl/ [1]
+Tested-by: Marek Marczykowski-Górecki <marmarek@invisiblethingslab.com>
+Suggested-by: Christoph Hellwig <hch@lst.de>
+Cc: stable@vger.kernel.org
+Signed-off-by: Keith Busch <kbusch@kernel.org>
+Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>
+Acked-by: Stefano Stabellini <sstabellini@kernel.org>
+Reviewed-by: Christoph Hellwig <hch@lst.de>
+Link: https://lore.kernel.org/r/151bef41-e817-aea9-675-a35fdac4ed@redhat.com
+Signed-off-by: Juergen Gross <jgross@suse.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/xen/swiotlb-xen.c |    1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/xen/swiotlb-xen.c
++++ b/drivers/xen/swiotlb-xen.c
+@@ -405,4 +405,5 @@ const struct dma_map_ops xen_swiotlb_dma
+       .get_sgtable = dma_common_get_sgtable,
+       .alloc_pages = dma_common_alloc_pages,
+       .free_pages = dma_common_free_pages,
++      .max_mapping_size = swiotlb_max_mapping_size,
+ };
diff --git a/queue-6.6/thunderbolt-set-lane-bonding-bit-only-for-downstream-port.patch b/queue-6.6/thunderbolt-set-lane-bonding-bit-only-for-downstream-port.patch
new file mode 100644 (file)
index 0000000..6be7720
--- /dev/null
@@ -0,0 +1,33 @@
+From 24d85bb3be373b5831699bddf698b392bd2b904d Mon Sep 17 00:00:00 2001
+From: Gil Fine <gil.fine@linux.intel.com>
+Date: Tue, 7 Nov 2023 12:22:40 +0200
+Subject: thunderbolt: Set lane bonding bit only for downstream port
+
+From: Gil Fine <gil.fine@linux.intel.com>
+
+commit 24d85bb3be373b5831699bddf698b392bd2b904d upstream.
+
+Fix the lane bonding procedure to follow the steps described in USB4
+Connection Manager guide. Hence, set the lane bonding bit only for
+downstream port. This is needed for certain ASMedia device, otherwise
+lane bonding fails and the device disconnects.
+
+Cc: stable@vger.kernel.org
+Signed-off-by: Gil Fine <gil.fine@linux.intel.com>
+Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/thunderbolt/switch.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/thunderbolt/switch.c
++++ b/drivers/thunderbolt/switch.c
+@@ -1082,7 +1082,7 @@ int tb_port_lane_bonding_enable(struct t
+        * Only set bonding if the link was not already bonded. This
+        * avoids the lane adapter to re-enter bonding state.
+        */
+-      if (width == TB_LINK_WIDTH_SINGLE) {
++      if (width == TB_LINK_WIDTH_SINGLE && !tb_is_upstream_port(port)) {
+               ret = tb_port_set_lane_bonding(port, true);
+               if (ret)
+                       goto err_lane1;
diff --git a/queue-6.6/tls-fix-null-deref-on-tls_sw_splice_eof-with-empty-record.patch b/queue-6.6/tls-fix-null-deref-on-tls_sw_splice_eof-with-empty-record.patch
new file mode 100644 (file)
index 0000000..585b57c
--- /dev/null
@@ -0,0 +1,56 @@
+From 53f2cb491b500897a619ff6abd72f565933760f0 Mon Sep 17 00:00:00 2001
+From: Jann Horn <jannh@google.com>
+Date: Wed, 22 Nov 2023 22:44:47 +0100
+Subject: tls: fix NULL deref on tls_sw_splice_eof() with empty record
+
+From: Jann Horn <jannh@google.com>
+
+commit 53f2cb491b500897a619ff6abd72f565933760f0 upstream.
+
+syzkaller discovered that if tls_sw_splice_eof() is executed as part of
+sendfile() when the plaintext/ciphertext sk_msg are empty, the send path
+gets confused because the empty ciphertext buffer does not have enough
+space for the encryption overhead. This causes tls_push_record() to go on
+the `split = true` path (which is only supposed to be used when interacting
+with an attached BPF program), and then get further confused and hit the
+tls_merge_open_record() path, which then assumes that there must be at
+least one populated buffer element, leading to a NULL deref.
+
+It is possible to have empty plaintext/ciphertext buffers if we previously
+bailed from tls_sw_sendmsg_locked() via the tls_trim_both_msgs() path.
+tls_sw_push_pending_record() already handles this case correctly; let's do
+the same check in tls_sw_splice_eof().
+
+Fixes: df720d288dbb ("tls/sw: Use splice_eof() to flush")
+Cc: stable@vger.kernel.org
+Reported-by: syzbot+40d43509a099ea756317@syzkaller.appspotmail.com
+Signed-off-by: Jann Horn <jannh@google.com>
+Link: https://lore.kernel.org/r/20231122214447.675768-1-jannh@google.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/tls/tls_sw.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/net/tls/tls_sw.c b/net/tls/tls_sw.c
+index a78e8e722409..316f76187962 100644
+--- a/net/tls/tls_sw.c
++++ b/net/tls/tls_sw.c
+@@ -1232,11 +1232,14 @@ void tls_sw_splice_eof(struct socket *sock)
+       lock_sock(sk);
+ retry:
++      /* same checks as in tls_sw_push_pending_record() */
+       rec = ctx->open_rec;
+       if (!rec)
+               goto unlock;
+       msg_pl = &rec->msg_plaintext;
++      if (msg_pl->sg.size == 0)
++              goto unlock;
+       /* Check the BPF advisor and perform transmission. */
+       ret = bpf_exec_tx_verdict(msg_pl, sk, false, TLS_RECORD_TYPE_DATA,
+-- 
+2.43.0
+
diff --git a/queue-6.6/usb-misc-onboard-hub-add-support-for-microchip-usb5744.patch b/queue-6.6/usb-misc-onboard-hub-add-support-for-microchip-usb5744.patch
new file mode 100644 (file)
index 0000000..a0c6f04
--- /dev/null
@@ -0,0 +1,60 @@
+From 6972b38ca05235f6142715db7062ecc87a422e22 Mon Sep 17 00:00:00 2001
+From: Stefan Eichenberger <stefan.eichenberger@toradex.com>
+Date: Mon, 13 Nov 2023 15:59:21 +0100
+Subject: usb: misc: onboard-hub: add support for Microchip USB5744
+
+From: Stefan Eichenberger <stefan.eichenberger@toradex.com>
+
+commit 6972b38ca05235f6142715db7062ecc87a422e22 upstream.
+
+Add support for the Microchip USB5744 USB3.0 and USB2.0 Hub.
+
+The Microchip USB5744 supports two power supplies, one for 1V2 and one
+for 3V3. According to the datasheet there is no need for a delay between
+power on and reset, so this value is set to 0.
+
+Signed-off-by: Stefan Eichenberger <stefan.eichenberger@toradex.com>
+Signed-off-by: Francesco Dolcini <francesco.dolcini@toradex.com>
+Cc: stable <stable@kernel.org>
+Acked-by: Matthias Kaehlcke <mka@chromium.org>
+Link: https://lore.kernel.org/r/20231113145921.30104-3-francesco@dolcini.it
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/misc/onboard_usb_hub.c |    2 ++
+ drivers/usb/misc/onboard_usb_hub.h |    7 +++++++
+ 2 files changed, 9 insertions(+)
+
+--- a/drivers/usb/misc/onboard_usb_hub.c
++++ b/drivers/usb/misc/onboard_usb_hub.c
+@@ -437,6 +437,8 @@ static const struct usb_device_id onboar
+       { USB_DEVICE(VENDOR_ID_MICROCHIP, 0x2412) }, /* USB2412 USB 2.0 */
+       { USB_DEVICE(VENDOR_ID_MICROCHIP, 0x2514) }, /* USB2514B USB 2.0 */
+       { USB_DEVICE(VENDOR_ID_MICROCHIP, 0x2517) }, /* USB2517 USB 2.0 */
++      { USB_DEVICE(VENDOR_ID_MICROCHIP, 0x2744) }, /* USB5744 USB 2.0 */
++      { USB_DEVICE(VENDOR_ID_MICROCHIP, 0x5744) }, /* USB5744 USB 3.0 */
+       { USB_DEVICE(VENDOR_ID_REALTEK, 0x0411) }, /* RTS5411 USB 3.1 */
+       { USB_DEVICE(VENDOR_ID_REALTEK, 0x5411) }, /* RTS5411 USB 2.1 */
+       { USB_DEVICE(VENDOR_ID_REALTEK, 0x0414) }, /* RTS5414 USB 3.2 */
+--- a/drivers/usb/misc/onboard_usb_hub.h
++++ b/drivers/usb/misc/onboard_usb_hub.h
+@@ -16,6 +16,11 @@ static const struct onboard_hub_pdata mi
+       .num_supplies = 1,
+ };
++static const struct onboard_hub_pdata microchip_usb5744_data = {
++      .reset_us = 0,
++      .num_supplies = 2,
++};
++
+ static const struct onboard_hub_pdata realtek_rts5411_data = {
+       .reset_us = 0,
+       .num_supplies = 1,
+@@ -50,6 +55,8 @@ static const struct of_device_id onboard
+       { .compatible = "usb424,2412", .data = &microchip_usb424_data, },
+       { .compatible = "usb424,2514", .data = &microchip_usb424_data, },
+       { .compatible = "usb424,2517", .data = &microchip_usb424_data, },
++      { .compatible = "usb424,2744", .data = &microchip_usb5744_data, },
++      { .compatible = "usb424,5744", .data = &microchip_usb5744_data, },
+       { .compatible = "usb451,8140", .data = &ti_tusb8041_data, },
+       { .compatible = "usb451,8142", .data = &ti_tusb8041_data, },
+       { .compatible = "usb4b4,6504", .data = &cypress_hx3_data, },
diff --git a/queue-6.6/usb-serial-option-add-luat-air72-u-series-products.patch b/queue-6.6/usb-serial-option-add-luat-air72-u-series-products.patch
new file mode 100644 (file)
index 0000000..ca56d1e
--- /dev/null
@@ -0,0 +1,68 @@
+From da90e45d5afc4da2de7cd3ea7943d0f1baa47cc2 Mon Sep 17 00:00:00 2001
+From: Asuna Yang <spriteovo@gmail.com>
+Date: Wed, 22 Nov 2023 22:18:03 +0800
+Subject: USB: serial: option: add Luat Air72*U series products
+
+From: Asuna Yang <spriteovo@gmail.com>
+
+commit da90e45d5afc4da2de7cd3ea7943d0f1baa47cc2 upstream.
+
+Update the USB serial option driver support for Luat Air72*U series
+products.
+
+ID 1782:4e00 Spreadtrum Communications Inc. UNISOC-8910
+
+T: Bus=01 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#= 13 Spd=480 MxCh= 0
+D: Ver= 2.00 Cls=00(>ifc ) Sub=00 Prot=00 MxPS=64 #Cfgs= 1
+P: Vendor=1782 ProdID=4e00 Rev=00.00
+S: Manufacturer=UNISOC
+S: Product=UNISOC-8910
+C: #Ifs= 5 Cfg#= 1 Atr=e0 MxPwr=400mA
+I: If#= 0 Alt= 0 #EPs= 1 Cls=e0(wlcon) Sub=01 Prot=03 Driver=rndis_host
+E: Ad=82(I) Atr=03(Int.) MxPS= 8 Ivl=4096ms
+I: If#= 1 Alt= 0 #EPs= 2 Cls=0a(data ) Sub=00 Prot=00 Driver=rndis_host
+E: Ad=01(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms
+E: Ad=81(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
+I: If#= 2 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=00 Prot=00 Driver=option
+E: Ad=02(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms
+E: Ad=83(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
+I: If#= 3 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=00 Prot=00 Driver=option
+E: Ad=03(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms
+E: Ad=84(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
+I: If#= 4 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=00 Prot=00 Driver=option
+E: Ad=04(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms
+E: Ad=85(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
+
+If#= 2: AT
+If#= 3: PPP + AT
+If#= 4: Debug
+
+Co-developed-by: Yangyu Chen <cyy@cyyself.name>
+Signed-off-by: Yangyu Chen <cyy@cyyself.name>
+Signed-off-by: Asuna Yang <SpriteOvO@gmail.com>
+Cc: stable@vger.kernel.org
+Signed-off-by: Johan Hovold <johan@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/serial/option.c |    3 +++
+ 1 file changed, 3 insertions(+)
+
+--- a/drivers/usb/serial/option.c
++++ b/drivers/usb/serial/option.c
+@@ -609,6 +609,8 @@ static void option_instat_callback(struc
+ #define UNISOC_VENDOR_ID                      0x1782
+ /* TOZED LT70-C based on UNISOC SL8563 uses UNISOC's vendor ID */
+ #define TOZED_PRODUCT_LT70C                   0x4055
++/* Luat Air72*U series based on UNISOC UIS8910 uses UNISOC's vendor ID */
++#define LUAT_PRODUCT_AIR720U                  0x4e00
+ /* Device flags */
+@@ -2271,6 +2273,7 @@ static const struct usb_device_id option
+       { USB_DEVICE_AND_INTERFACE_INFO(SIERRA_VENDOR_ID, SIERRA_PRODUCT_EM9191, 0xff, 0xff, 0x40) },
+       { USB_DEVICE_AND_INTERFACE_INFO(SIERRA_VENDOR_ID, SIERRA_PRODUCT_EM9191, 0xff, 0, 0) },
+       { USB_DEVICE_AND_INTERFACE_INFO(UNISOC_VENDOR_ID, TOZED_PRODUCT_LT70C, 0xff, 0, 0) },
++      { USB_DEVICE_AND_INTERFACE_INFO(UNISOC_VENDOR_ID, LUAT_PRODUCT_AIR720U, 0xff, 0, 0) },
+       { } /* Terminating entry */
+ };
+ MODULE_DEVICE_TABLE(usb, option_ids);