On 25-06-17 07:15:06, Pawel Laszczak wrote:
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@vger.kernel.org Signed-off-by: Pawel Laszczak pawell@cadence.com
drivers/usb/cdns3/cdnsp-debug.h | 5 +++-- drivers/usb/cdns3/cdnsp-ep0.c | 17 ++++++++++++++--- drivers/usb/cdns3/cdnsp-gadget.h | 3 +++ drivers/usb/cdns3/cdnsp-ring.c | 3 ++- 4 files changed, 22 insertions(+), 6 deletions(-)
diff --git a/drivers/usb/cdns3/cdnsp-debug.h b/drivers/usb/cdns3/cdnsp-debug.h index cd138acdcce1..86860686d836 100644 --- a/drivers/usb/cdns3/cdnsp-debug.h +++ b/drivers/usb/cdns3/cdnsp-debug.h @@ -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',
break; case TRB_STOP_RING: ret = scnprintf(str, size,field3 & TRB_ESP ? 'P' : 'p');
diff --git a/drivers/usb/cdns3/cdnsp-ep0.c b/drivers/usb/cdns3/cdnsp-ep0.c index f317d3c84781..567ccfdecded 100644 --- a/drivers/usb/cdns3/cdnsp-ep0.c +++ b/drivers/usb/cdns3/cdnsp-ep0.c @@ -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;
@@ -428,9 +429,19 @@ void cdnsp_setup_analyze(struct cdnsp_device *pdev) } /* 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) {
/*
* Halt Endpoint Command for SSP2 for ep0 preserve current
* endpoint state and driver has to synchronise the
%s/synchronise/synchronize
* software endpointp state with endpoint output context
%s/endpointp/endpoint
* state.
*/
if (GET_EP_CTX_STATE(pep->out_ctx) == EP_STATE_HALTED) {
cdnsp_halt_endpoint(pdev, pep, 0);
} else {
pep->ep_state &= ~EP_HALTED;
pep->ep_state |= EP_STOPPED;
}}
/* diff --git a/drivers/usb/cdns3/cdnsp-gadget.h b/drivers/usb/cdns3/cdnsp-gadget.h index 2afa3e558f85..c26abef6e1c9 100644 --- a/drivers/usb/cdns3/cdnsp-gadget.h +++ b/drivers/usb/cdns3/cdnsp-gadget.h @@ -987,6 +987,9 @@ 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. */ +#define TRB_ESP BIT(9)
Please add comment it is specific for SSP2.
Peter
/* Link TRB specific fields. */ #define TRB_TC BIT(1) diff --git a/drivers/usb/cdns3/cdnsp-ring.c b/drivers/usb/cdns3/cdnsp-ring.c index fd06cb85c4ea..d397d28efc6e 100644 --- a/drivers/usb/cdns3/cdnsp-ring.c +++ b/drivers/usb/cdns3/cdnsp-ring.c @@ -2483,7 +2483,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) -- 2.43.0