]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
5.4-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 26 Feb 2024 13:11:01 +0000 (14:11 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 26 Feb 2024 13:11:01 +0000 (14:11 +0100)
added patches:
arm-ep93xx-add-terminator-to-gpiod_lookup_table.patch
l2tp-pass-correct-message-length-to-ip6_append_data.patch
pci-msi-prevent-msi-hardware-interrupt-number-truncation.patch
usb-cdns3-fix-memory-double-free-when-handle-zero-packet.patch
usb-cdns3-fixed-memory-use-after-free-at-cdns3_gadget_ep_disable.patch
usb-gadget-ncm-avoid-dropping-datagrams-of-properly-parsed-ntbs.patch
usb-roles-don-t-get-set_role-when-usb_role_switch-is-unregistered.patch

queue-5.4/arm-ep93xx-add-terminator-to-gpiod_lookup_table.patch [new file with mode: 0644]
queue-5.4/l2tp-pass-correct-message-length-to-ip6_append_data.patch [new file with mode: 0644]
queue-5.4/pci-msi-prevent-msi-hardware-interrupt-number-truncation.patch [new file with mode: 0644]
queue-5.4/series
queue-5.4/usb-cdns3-fix-memory-double-free-when-handle-zero-packet.patch [new file with mode: 0644]
queue-5.4/usb-cdns3-fixed-memory-use-after-free-at-cdns3_gadget_ep_disable.patch [new file with mode: 0644]
queue-5.4/usb-gadget-ncm-avoid-dropping-datagrams-of-properly-parsed-ntbs.patch [new file with mode: 0644]
queue-5.4/usb-roles-don-t-get-set_role-when-usb_role_switch-is-unregistered.patch [new file with mode: 0644]

diff --git a/queue-5.4/arm-ep93xx-add-terminator-to-gpiod_lookup_table.patch b/queue-5.4/arm-ep93xx-add-terminator-to-gpiod_lookup_table.patch
new file mode 100644 (file)
index 0000000..98e5ebe
--- /dev/null
@@ -0,0 +1,37 @@
+From fdf87a0dc26d0550c60edc911cda42f9afec3557 Mon Sep 17 00:00:00 2001
+From: Nikita Shubin <nikita.shubin@maquefel.me>
+Date: Mon, 5 Feb 2024 11:23:34 +0100
+Subject: ARM: ep93xx: Add terminator to gpiod_lookup_table
+
+From: Nikita Shubin <nikita.shubin@maquefel.me>
+
+commit fdf87a0dc26d0550c60edc911cda42f9afec3557 upstream.
+
+Without the terminator, if a con_id is passed to gpio_find() that
+does not exist in the lookup table the function will not stop looping
+correctly, and eventually cause an oops.
+
+Cc: stable@vger.kernel.org
+Fixes: b2e63555592f ("i2c: gpio: Convert to use descriptors")
+Reported-by: Andy Shevchenko <andriy.shevchenko@intel.com>
+Signed-off-by: Nikita Shubin <nikita.shubin@maquefel.me>
+Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
+Acked-by: Alexander Sverdlin <alexander.sverdlin@gmail.com>
+Signed-off-by: Alexander Sverdlin <alexander.sverdlin@gmail.com>
+Link: https://lore.kernel.org/r/20240205102337.439002-1-alexander.sverdlin@gmail.com
+Signed-off-by: Arnd Bergmann <arnd@arndb.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/arm/mach-ep93xx/core.c |    1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/arch/arm/mach-ep93xx/core.c
++++ b/arch/arm/mach-ep93xx/core.c
+@@ -337,6 +337,7 @@ static struct gpiod_lookup_table ep93xx_
+                               GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN),
+               GPIO_LOOKUP_IDX("G", 0, NULL, 1,
+                               GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN),
++              { }
+       },
+ };
diff --git a/queue-5.4/l2tp-pass-correct-message-length-to-ip6_append_data.patch b/queue-5.4/l2tp-pass-correct-message-length-to-ip6_append_data.patch
new file mode 100644 (file)
index 0000000..660cd8c
--- /dev/null
@@ -0,0 +1,50 @@
+From 359e54a93ab43d32ee1bff3c2f9f10cb9f6b6e79 Mon Sep 17 00:00:00 2001
+From: Tom Parkin <tparkin@katalix.com>
+Date: Tue, 20 Feb 2024 12:21:56 +0000
+Subject: l2tp: pass correct message length to ip6_append_data
+
+From: Tom Parkin <tparkin@katalix.com>
+
+commit 359e54a93ab43d32ee1bff3c2f9f10cb9f6b6e79 upstream.
+
+l2tp_ip6_sendmsg needs to avoid accounting for the transport header
+twice when splicing more data into an already partially-occupied skbuff.
+
+To manage this, we check whether the skbuff contains data using
+skb_queue_empty when deciding how much data to append using
+ip6_append_data.
+
+However, the code which performed the calculation was incorrect:
+
+     ulen = len + skb_queue_empty(&sk->sk_write_queue) ? transhdrlen : 0;
+
+...due to C operator precedence, this ends up setting ulen to
+transhdrlen for messages with a non-zero length, which results in
+corrupted packets on the wire.
+
+Add parentheses to correct the calculation in line with the original
+intent.
+
+Fixes: 9d4c75800f61 ("ipv4, ipv6: Fix handling of transhdrlen in __ip{,6}_append_data()")
+Cc: David Howells <dhowells@redhat.com>
+Cc: stable@vger.kernel.org
+Signed-off-by: Tom Parkin <tparkin@katalix.com>
+Reviewed-by: Simon Horman <horms@kernel.org>
+Link: https://lore.kernel.org/r/20240220122156.43131-1-tparkin@katalix.com
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/l2tp/l2tp_ip6.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/net/l2tp/l2tp_ip6.c
++++ b/net/l2tp/l2tp_ip6.c
+@@ -644,7 +644,7 @@ static int l2tp_ip6_sendmsg(struct sock
+ back_from_confirm:
+       lock_sock(sk);
+-      ulen = len + skb_queue_empty(&sk->sk_write_queue) ? transhdrlen : 0;
++      ulen = len + (skb_queue_empty(&sk->sk_write_queue) ? transhdrlen : 0);
+       err = ip6_append_data(sk, ip_generic_getfrag, msg,
+                             ulen, transhdrlen, &ipc6,
+                             &fl6, (struct rt6_info *)dst,
diff --git a/queue-5.4/pci-msi-prevent-msi-hardware-interrupt-number-truncation.patch b/queue-5.4/pci-msi-prevent-msi-hardware-interrupt-number-truncation.patch
new file mode 100644 (file)
index 0000000..dec26e9
--- /dev/null
@@ -0,0 +1,46 @@
+From db744ddd59be798c2627efbfc71f707f5a935a40 Mon Sep 17 00:00:00 2001
+From: Vidya Sagar <vidyas@nvidia.com>
+Date: Mon, 15 Jan 2024 19:26:49 +0530
+Subject: PCI/MSI: Prevent MSI hardware interrupt number truncation
+
+From: Vidya Sagar <vidyas@nvidia.com>
+
+commit db744ddd59be798c2627efbfc71f707f5a935a40 upstream.
+
+While calculating the hardware interrupt number for a MSI interrupt, the
+higher bits (i.e. from bit-5 onwards a.k.a domain_nr >= 32) of the PCI
+domain number gets truncated because of the shifted value casting to return
+type of pci_domain_nr() which is 'int'. This for example is resulting in
+same hardware interrupt number for devices 0019:00:00.0 and 0039:00:00.0.
+
+To address this cast the PCI domain number to 'irq_hw_number_t' before left
+shifting it to calculate the hardware interrupt number.
+
+Please note that this fixes the issue only on 64-bit systems and doesn't
+change the behavior for 32-bit systems i.e. the 32-bit systems continue to
+have the issue. Since the issue surfaces only if there are too many PCIe
+controllers in the system which usually is the case in modern server
+systems and they don't tend to run 32-bit kernels.
+
+Fixes: 3878eaefb89a ("PCI/MSI: Enhance core to support hierarchy irqdomain")
+Signed-off-by: Vidya Sagar <vidyas@nvidia.com>
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Tested-by: Shanker Donthineni <sdonthineni@nvidia.com>
+Cc: stable@vger.kernel.org
+Link: https://lore.kernel.org/r/20240115135649.708536-1-vidyas@nvidia.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/pci/msi.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/pci/msi.c
++++ b/drivers/pci/msi.c
+@@ -1428,7 +1428,7 @@ irq_hw_number_t pci_msi_domain_calc_hwir
+ {
+       return (irq_hw_number_t)desc->msi_attrib.entry_nr |
+               pci_dev_id(dev) << 11 |
+-              (pci_domain_nr(dev->bus) & 0xFFFFFFFF) << 27;
++              ((irq_hw_number_t)(pci_domain_nr(dev->bus) & 0xFFFFFFFF)) << 27;
+ }
+ static inline bool pci_msi_desc_is_multi_msi(struct msi_desc *desc)
index b4dd19c495629c679235578f0a7b31517fe6502b..cf5e88155ef85d4459547f81048ee1559e755688 100644 (file)
@@ -51,3 +51,10 @@ pci-tegra-fix-of-node-reference-leak.patch
 ib-hfi1-fix-sdma.h-tx-num_descs-off-by-one-error.patch
 dm-crypt-don-t-modify-the-data-when-using-authenticated-encryption.patch
 gtp-fix-use-after-free-and-null-ptr-deref-in-gtp_genl_dump_pdp.patch
+pci-msi-prevent-msi-hardware-interrupt-number-truncation.patch
+l2tp-pass-correct-message-length-to-ip6_append_data.patch
+arm-ep93xx-add-terminator-to-gpiod_lookup_table.patch
+usb-cdns3-fixed-memory-use-after-free-at-cdns3_gadget_ep_disable.patch
+usb-cdns3-fix-memory-double-free-when-handle-zero-packet.patch
+usb-gadget-ncm-avoid-dropping-datagrams-of-properly-parsed-ntbs.patch
+usb-roles-don-t-get-set_role-when-usb_role_switch-is-unregistered.patch
diff --git a/queue-5.4/usb-cdns3-fix-memory-double-free-when-handle-zero-packet.patch b/queue-5.4/usb-cdns3-fix-memory-double-free-when-handle-zero-packet.patch
new file mode 100644 (file)
index 0000000..12d2d14
--- /dev/null
@@ -0,0 +1,62 @@
+From 5fd9e45f1ebcd57181358af28506e8a661a260b3 Mon Sep 17 00:00:00 2001
+From: Frank Li <Frank.Li@nxp.com>
+Date: Fri, 2 Feb 2024 10:42:17 -0500
+Subject: usb: cdns3: fix memory double free when handle zero packet
+
+From: Frank Li <Frank.Li@nxp.com>
+
+commit 5fd9e45f1ebcd57181358af28506e8a661a260b3 upstream.
+
+829  if (request->complete) {
+830          spin_unlock(&priv_dev->lock);
+831          usb_gadget_giveback_request(&priv_ep->endpoint,
+832                                    request);
+833          spin_lock(&priv_dev->lock);
+834  }
+835
+836  if (request->buf == priv_dev->zlp_buf)
+837      cdns3_gadget_ep_free_request(&priv_ep->endpoint, request);
+
+Driver append an additional zero packet request when queue a packet, which
+length mod max packet size is 0. When transfer complete, run to line 831,
+usb_gadget_giveback_request() will free this requestion. 836 condition is
+true, so cdns3_gadget_ep_free_request() free this request again.
+
+Log:
+
+[ 1920.140696][  T150] BUG: KFENCE: use-after-free read in cdns3_gadget_giveback+0x134/0x2c0 [cdns3]
+[ 1920.140696][  T150]
+[ 1920.151837][  T150] Use-after-free read at 0x000000003d1cd10b (in kfence-#36):
+[ 1920.159082][  T150]  cdns3_gadget_giveback+0x134/0x2c0 [cdns3]
+[ 1920.164988][  T150]  cdns3_transfer_completed+0x438/0x5f8 [cdns3]
+
+Add check at line 829, skip call usb_gadget_giveback_request() if it is
+additional zero length packet request. Needn't call
+usb_gadget_giveback_request() because it is allocated in this driver.
+
+Cc: stable@vger.kernel.org
+Fixes: 7733f6c32e36 ("usb: cdns3: Add Cadence USB3 DRD Driver")
+Signed-off-by: Frank Li <Frank.Li@nxp.com>
+Reviewed-by: Roger Quadros <rogerq@kernel.org>
+Acked-by: Peter Chen <peter.chen@kernel.org>
+Link: https://lore.kernel.org/r/20240202154217.661867-2-Frank.Li@nxp.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/cdns3/gadget.c |    6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+--- a/drivers/usb/cdns3/gadget.c
++++ b/drivers/usb/cdns3/gadget.c
+@@ -661,7 +661,11 @@ void cdns3_gadget_giveback(struct cdns3_
+                       return;
+       }
+-      if (request->complete) {
++      /*
++       * zlp request is appended by driver, needn't call usb_gadget_giveback_request() to notify
++       * gadget composite driver.
++       */
++      if (request->complete && request->buf != priv_dev->zlp_buf) {
+               spin_unlock(&priv_dev->lock);
+               usb_gadget_giveback_request(&priv_ep->endpoint,
+                                           request);
diff --git a/queue-5.4/usb-cdns3-fixed-memory-use-after-free-at-cdns3_gadget_ep_disable.patch b/queue-5.4/usb-cdns3-fixed-memory-use-after-free-at-cdns3_gadget_ep_disable.patch
new file mode 100644 (file)
index 0000000..abe5aa0
--- /dev/null
@@ -0,0 +1,56 @@
+From cd45f99034b0c8c9cb346dd0d6407a95ca3d36f6 Mon Sep 17 00:00:00 2001
+From: Frank Li <Frank.Li@nxp.com>
+Date: Fri, 2 Feb 2024 10:42:16 -0500
+Subject: usb: cdns3: fixed memory use after free at cdns3_gadget_ep_disable()
+
+From: Frank Li <Frank.Li@nxp.com>
+
+commit cd45f99034b0c8c9cb346dd0d6407a95ca3d36f6 upstream.
+
+  ...
+  cdns3_gadget_ep_free_request(&priv_ep->endpoint, &priv_req->request);
+  list_del_init(&priv_req->list);
+  ...
+
+'priv_req' actually free at cdns3_gadget_ep_free_request(). But
+list_del_init() use priv_req->list after it.
+
+[ 1542.642868][  T534] BUG: KFENCE: use-after-free read in __list_del_entry_valid+0x10/0xd4
+[ 1542.642868][  T534]
+[ 1542.653162][  T534] Use-after-free read at 0x000000009ed0ba99 (in kfence-#3):
+[ 1542.660311][  T534]  __list_del_entry_valid+0x10/0xd4
+[ 1542.665375][  T534]  cdns3_gadget_ep_disable+0x1f8/0x388 [cdns3]
+[ 1542.671571][  T534]  usb_ep_disable+0x44/0xe4
+[ 1542.675948][  T534]  ffs_func_eps_disable+0x64/0xc8
+[ 1542.680839][  T534]  ffs_func_set_alt+0x74/0x368
+[ 1542.685478][  T534]  ffs_func_disable+0x18/0x28
+
+Move list_del_init() before cdns3_gadget_ep_free_request() to resolve this
+problem.
+
+Cc: stable@vger.kernel.org
+Fixes: 7733f6c32e36 ("usb: cdns3: Add Cadence USB3 DRD Driver")
+Signed-off-by: Frank Li <Frank.Li@nxp.com>
+Reviewed-by: Roger Quadros <rogerq@kernel.org>
+Acked-by: Peter Chen <peter.chen@kernel.org>
+Link: https://lore.kernel.org/r/20240202154217.661867-1-Frank.Li@nxp.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/cdns3/gadget.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/usb/cdns3/gadget.c
++++ b/drivers/usb/cdns3/gadget.c
+@@ -1951,11 +1951,11 @@ static int cdns3_gadget_ep_disable(struc
+       while (!list_empty(&priv_ep->wa2_descmiss_req_list)) {
+               priv_req = cdns3_next_priv_request(&priv_ep->wa2_descmiss_req_list);
++              list_del_init(&priv_req->list);
+               kfree(priv_req->request.buf);
+               cdns3_gadget_ep_free_request(&priv_ep->endpoint,
+                                            &priv_req->request);
+-              list_del_init(&priv_req->list);
+               --priv_ep->wa2_counter;
+       }
diff --git a/queue-5.4/usb-gadget-ncm-avoid-dropping-datagrams-of-properly-parsed-ntbs.patch b/queue-5.4/usb-gadget-ncm-avoid-dropping-datagrams-of-properly-parsed-ntbs.patch
new file mode 100644 (file)
index 0000000..2ec0013
--- /dev/null
@@ -0,0 +1,88 @@
+From 76c51146820c5dac629f21deafab0a7039bc3ccd Mon Sep 17 00:00:00 2001
+From: Krishna Kurapati <quic_kriskura@quicinc.com>
+Date: Mon, 5 Feb 2024 13:16:50 +0530
+Subject: usb: gadget: ncm: Avoid dropping datagrams of properly parsed NTBs
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Krishna Kurapati <quic_kriskura@quicinc.com>
+
+commit 76c51146820c5dac629f21deafab0a7039bc3ccd upstream.
+
+It is observed sometimes when tethering is used over NCM with Windows 11
+as host, at some instances, the gadget_giveback has one byte appended at
+the end of a proper NTB. When the NTB is parsed, unwrap call looks for
+any leftover bytes in SKB provided by u_ether and if there are any pending
+bytes, it treats them as a separate NTB and parses it. But in case the
+second NTB (as per unwrap call) is faulty/corrupt, all the datagrams that
+were parsed properly in the first NTB and saved in rx_list are dropped.
+
+Adding a few custom traces showed the following:
+[002] d..1  7828.532866: dwc3_gadget_giveback: ep1out:
+req 000000003868811a length 1025/16384 zsI ==> 0
+[002] d..1  7828.532867: ncm_unwrap_ntb: K: ncm_unwrap_ntb toprocess: 1025
+[002] d..1  7828.532867: ncm_unwrap_ntb: K: ncm_unwrap_ntb nth: 1751999342
+[002] d..1  7828.532868: ncm_unwrap_ntb: K: ncm_unwrap_ntb seq: 0xce67
+[002] d..1  7828.532868: ncm_unwrap_ntb: K: ncm_unwrap_ntb blk_len: 0x400
+[002] d..1  7828.532868: ncm_unwrap_ntb: K: ncm_unwrap_ntb ndp_len: 0x10
+[002] d..1  7828.532869: ncm_unwrap_ntb: K: Parsed NTB with 1 frames
+
+In this case, the giveback is of 1025 bytes and block length is 1024.
+The rest 1 byte (which is 0x00) won't be parsed resulting in drop of
+all datagrams in rx_list.
+
+Same is case with packets of size 2048:
+[002] d..1  7828.557948: dwc3_gadget_giveback: ep1out:
+req 0000000011dfd96e length 2049/16384 zsI ==> 0
+[002] d..1  7828.557949: ncm_unwrap_ntb: K: ncm_unwrap_ntb nth: 1751999342
+[002] d..1  7828.557950: ncm_unwrap_ntb: K: ncm_unwrap_ntb blk_len: 0x800
+
+Lecroy shows one byte coming in extra confirming that the byte is coming
+in from PC:
+
+ Transfer 2959 - Bytes Transferred(1025)  Timestamp((18.524 843 590)
+ - Transaction 8391 - Data(1025 bytes) Timestamp(18.524 843 590)
+ --- Packet 4063861
+       Data(1024 bytes)
+       Duration(2.117us) Idle(14.700ns) Timestamp(18.524 843 590)
+ --- Packet 4063863
+       Data(1 byte)
+       Duration(66.160ns) Time(282.000ns) Timestamp(18.524 845 722)
+
+According to Windows driver, no ZLP is needed if wBlockLength is non-zero,
+because the non-zero wBlockLength has already told the function side the
+size of transfer to be expected. However, there are in-market NCM devices
+that rely on ZLP as long as the wBlockLength is multiple of wMaxPacketSize.
+To deal with such devices, it pads an extra 0 at end so the transfer is no
+longer multiple of wMaxPacketSize.
+
+Cc: <stable@vger.kernel.org>
+Fixes: 9f6ce4240a2b ("usb: gadget: f_ncm.c added")
+Signed-off-by: Krishna Kurapati <quic_kriskura@quicinc.com>
+Reviewed-by: Maciej Żenczykowski <maze@google.com>
+Link: https://lore.kernel.org/r/20240205074650.200304-1-quic_kriskura@quicinc.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/gadget/function/f_ncm.c |   10 +++++++++-
+ 1 file changed, 9 insertions(+), 1 deletion(-)
+
+--- a/drivers/usb/gadget/function/f_ncm.c
++++ b/drivers/usb/gadget/function/f_ncm.c
+@@ -1349,7 +1349,15 @@ parse_ntb:
+            "Parsed NTB with %d frames\n", dgram_counter);
+       to_process -= block_len;
+-      if (to_process != 0) {
++
++      /*
++       * Windows NCM driver avoids USB ZLPs by adding a 1-byte
++       * zero pad as needed.
++       */
++      if (to_process == 1 &&
++          (*(unsigned char *)(ntb_ptr + block_len) == 0x00)) {
++              to_process--;
++      } else if (to_process > 0) {
+               ntb_ptr = (unsigned char *)(ntb_ptr + block_len);
+               goto parse_ntb;
+       }
diff --git a/queue-5.4/usb-roles-don-t-get-set_role-when-usb_role_switch-is-unregistered.patch b/queue-5.4/usb-roles-don-t-get-set_role-when-usb_role_switch-is-unregistered.patch
new file mode 100644 (file)
index 0000000..e7803f7
--- /dev/null
@@ -0,0 +1,76 @@
+From b787a3e781759026a6212736ef8e52cf83d1821a Mon Sep 17 00:00:00 2001
+From: Xu Yang <xu.yang_2@nxp.com>
+Date: Mon, 29 Jan 2024 17:37:39 +0800
+Subject: usb: roles: don't get/set_role() when usb_role_switch is unregistered
+
+From: Xu Yang <xu.yang_2@nxp.com>
+
+commit b787a3e781759026a6212736ef8e52cf83d1821a upstream.
+
+There is a possibility that usb_role_switch device is unregistered before
+the user put usb_role_switch. In this case, the user may still want to
+get/set_role() since the user can't sense the changes of usb_role_switch.
+
+This will add a flag to show if usb_role_switch is already registered and
+avoid unwanted behaviors.
+
+Fixes: fde0aa6c175a ("usb: common: Small class for USB role switches")
+cc: stable@vger.kernel.org
+Signed-off-by: Xu Yang <xu.yang_2@nxp.com>
+Acked-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
+Link: https://lore.kernel.org/r/20240129093739.2371530-2-xu.yang_2@nxp.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/roles/class.c |   12 ++++++++++--
+ 1 file changed, 10 insertions(+), 2 deletions(-)
+
+--- a/drivers/usb/roles/class.c
++++ b/drivers/usb/roles/class.c
+@@ -20,6 +20,7 @@ struct usb_role_switch {
+       struct device dev;
+       struct mutex lock; /* device lock*/
+       enum usb_role role;
++      bool registered;
+       /* From descriptor */
+       struct device *usb2_port;
+@@ -46,6 +47,9 @@ int usb_role_switch_set_role(struct usb_
+       if (IS_ERR_OR_NULL(sw))
+               return 0;
++      if (!sw->registered)
++              return -EOPNOTSUPP;
++
+       mutex_lock(&sw->lock);
+       ret = sw->set(sw->dev.parent, role);
+@@ -69,7 +73,7 @@ enum usb_role usb_role_switch_get_role(s
+ {
+       enum usb_role role;
+-      if (IS_ERR_OR_NULL(sw))
++      if (IS_ERR_OR_NULL(sw) || !sw->registered)
+               return USB_ROLE_NONE;
+       mutex_lock(&sw->lock);
+@@ -319,6 +323,8 @@ usb_role_switch_register(struct device *
+               return ERR_PTR(ret);
+       }
++      sw->registered = true;
++
+       /* TODO: Symlinks for the host port and the device controller. */
+       return sw;
+@@ -333,8 +339,10 @@ EXPORT_SYMBOL_GPL(usb_role_switch_regist
+  */
+ void usb_role_switch_unregister(struct usb_role_switch *sw)
+ {
+-      if (!IS_ERR_OR_NULL(sw))
++      if (!IS_ERR_OR_NULL(sw)) {
++              sw->registered = false;
+               device_unregister(&sw->dev);
++      }
+ }
+ EXPORT_SYMBOL_GPL(usb_role_switch_unregister);