]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
usb: cdnsp: Fix issue with CV Bad Descriptor test
authorPawel Laszczak <pawell@cadence.com>
Fri, 20 Jun 2025 08:23:12 +0000 (08:23 +0000)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 17 Jul 2025 16:30:51 +0000 (18:30 +0200)
[ Upstream commit 2831a81077f5162f104ba5a97a7d886eb371c21c ]

The SSP2 controller has extra endpoint state preserve bit (ESP) which
setting causes that endpoint state will be preserved during
Halt Endpoint command. It is used only for EP0.
Without this bit the Command Verifier "TD 9.10 Bad Descriptor Test"
failed.
Setting this bit doesn't have any impact for SSP controller.

Fixes: 3d82904559f4 ("usb: cdnsp: cdns3 Add main part of Cadence USBSSP DRD Driver")
Cc: stable <stable@kernel.org>
Signed-off-by: Pawel Laszczak <pawell@cadence.com>
Acked-by: Peter Chen <peter.chen@kernel.org>
Link: https://lore.kernel.org/r/PH7PR07MB95382CCD50549DABAEFD6156DD7CA@PH7PR07MB9538.namprd07.prod.outlook.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
drivers/usb/cdns3/cdnsp-debug.h
drivers/usb/cdns3/cdnsp-ep0.c
drivers/usb/cdns3/cdnsp-gadget.h
drivers/usb/cdns3/cdnsp-ring.c

index cd138acdcce16500e0b875ca31c9148618e5272a..86860686d8363ee3a50ee4395ab2eb6ccdc8a09e 100644 (file)
@@ -327,12 +327,13 @@ static inline const char *cdnsp_decode_trb(char *str, size_t size, u32 field0,
        case TRB_RESET_EP:
        case TRB_HALT_ENDPOINT:
                ret = scnprintf(str, size,
-                               "%s: ep%d%s(%d) ctx %08x%08x slot %ld flags %c",
+                               "%s: ep%d%s(%d) ctx %08x%08x slot %ld flags %c %c",
                                cdnsp_trb_type_string(type),
                                ep_num, ep_id % 2 ? "out" : "in",
                                TRB_TO_EP_INDEX(field3), field1, field0,
                                TRB_TO_SLOT_ID(field3),
-                               field3 & TRB_CYCLE ? 'C' : 'c');
+                               field3 & TRB_CYCLE ? 'C' : 'c',
+                               field3 & TRB_ESP ? 'P' : 'p');
                break;
        case TRB_STOP_RING:
                ret = scnprintf(str, size,
index f317d3c84781082d00d27f13481a5f759e7d1515..5cd9b898ce971fb7a794a0fa4cb397d4e299725b 100644 (file)
@@ -414,6 +414,7 @@ static int cdnsp_ep0_std_request(struct cdnsp_device *pdev,
 void cdnsp_setup_analyze(struct cdnsp_device *pdev)
 {
        struct usb_ctrlrequest *ctrl = &pdev->setup;
+       struct cdnsp_ep *pep;
        int ret = -EINVAL;
        u16 len;
 
@@ -427,10 +428,21 @@ void cdnsp_setup_analyze(struct cdnsp_device *pdev)
                goto out;
        }
 
+       pep = &pdev->eps[0];
+
        /* Restore the ep0 to Stopped/Running state. */
-       if (pdev->eps[0].ep_state & EP_HALTED) {
-               trace_cdnsp_ep0_halted("Restore to normal state");
-               cdnsp_halt_endpoint(pdev, &pdev->eps[0], 0);
+       if (pep->ep_state & EP_HALTED) {
+               if (GET_EP_CTX_STATE(pep->out_ctx) == EP_STATE_HALTED)
+                       cdnsp_halt_endpoint(pdev, pep, 0);
+
+               /*
+                * Halt Endpoint Command for SSP2 for ep0 preserve current
+                * endpoint state and driver has to synchronize the
+                * software endpoint state with endpoint output context
+                * state.
+                */
+               pep->ep_state &= ~EP_HALTED;
+               pep->ep_state |= EP_STOPPED;
        }
 
        /*
index 48336e121ed6f7c0efc0fc7d16b06812a284227b..155fd770a8cd9b5cf51a64a4daae2cc3f00ae927 100644 (file)
@@ -987,6 +987,12 @@ enum cdnsp_setup_dev {
 #define STREAM_ID_FOR_TRB(p)           ((((p)) << 16) & GENMASK(31, 16))
 #define SCT_FOR_TRB(p)                 (((p) << 1) & 0x7)
 
+/*
+ * Halt Endpoint Command TRB field.
+ * The ESP bit only exists in the SSP2 controller.
+ */
+#define TRB_ESP                                BIT(9)
+
 /* Link TRB specific fields. */
 #define TRB_TC                         BIT(1)
 
index 795668435c77e6a7ba19cff8d19867c4808ee90a..42db256978bcc857b413e42fdf92c9b4066f7dbd 100644 (file)
@@ -2475,7 +2475,8 @@ void cdnsp_queue_halt_endpoint(struct cdnsp_device *pdev, unsigned int ep_index)
 {
        cdnsp_queue_command(pdev, 0, 0, 0, TRB_TYPE(TRB_HALT_ENDPOINT) |
                            SLOT_ID_FOR_TRB(pdev->slot_id) |
-                           EP_ID_FOR_TRB(ep_index));
+                           EP_ID_FOR_TRB(ep_index) |
+                           (!ep_index ? TRB_ESP : 0));
 }
 
 void cdnsp_force_header_wakeup(struct cdnsp_device *pdev, int intf_num)