[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [RFC PATCH 03/12] xue: reset XHCI ports when initializing dbc
Reset ports, to force host system to re-enumerate devices. Otheriwse it will require the cable to be re-plugged, or will wait in the "configuring" state indefinitely. Trick and code copied from Linux: drivers/usb/early/xhci-dbc.c:xdbc_start()->xdbc_reset_debug_port() Signed-off-by: Marek Marczykowski-Górecki <marmarek@xxxxxxxxxxxxxxxxxxxxxx> --- xen/include/xue.h | 69 ++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 69 insertions(+) diff --git a/xen/include/xue.h b/xen/include/xue.h index 7515244f6af3..6048dcdd5509 100644 --- a/xen/include/xue.h +++ b/xen/include/xue.h @@ -59,6 +59,10 @@ ((1UL << XUE_PSC_CSC) | (1UL << XUE_PSC_PRC) | (1UL << XUE_PSC_PLC) | \ (1UL << XUE_PSC_CEC)) +#define XUE_XHC_EXT_PORT_MAJOR(x) (((x) >> 24) & 0xff) +#define PORT_RESET (1 << 4) +#define PORT_CONNECT (1 << 0) + static inline int known_xhc(uint32_t dev_ven) { switch (dev_ven) { @@ -1420,6 +1424,67 @@ static inline void xue_init_strings(struct xue *xue, uint32_t *info) info[8] = (4 << 24) | (30 << 16) | (8 << 8) | 6; } +static inline void xue_do_reset_debug_port(struct xue *xue, u32 id, u32 count) +{ + uint32_t *ops_reg; + uint32_t *portsc; + u32 val, cap_length; + int i; + + cap_length = (*(uint32_t*)xue->xhc_mmio) & 0xff; + ops_reg = xue->xhc_mmio + cap_length; + + id--; + for (i = id; i < (id + count); i++) { + portsc = ops_reg + 0x100 + i * 0x4; + val = *portsc; + if (!(val & PORT_CONNECT)) + *portsc = val | PORT_RESET; + } +} + + +static inline void xue_reset_debug_port(struct xue *xue) +{ + u32 val, port_offset, port_count; + uint32_t *xcap; + uint32_t next; + uint32_t id; + uint8_t *mmio = (uint8_t *)xue->xhc_mmio; + uint32_t *hccp1 = (uint32_t *)(mmio + 0x10); + const uint32_t PROTOCOL_ID = 0x2; + + /** + * Paranoid check against a zero value. The spec mandates that + * at least one "supported protocol" capability must be implemented, + * so this should always be false. + */ + if ((*hccp1 & 0xFFFF0000) == 0) { + return; + } + + xcap = (uint32_t *)(mmio + (((*hccp1 & 0xFFFF0000) >> 16) << 2)); + next = (*xcap & 0xFF00) >> 8; + id = *xcap & 0xFF; + + /* Look for "supported protocol" capability, major revision 3 */ + for (;next; xcap += next, id = *xcap & 0xFF, next = (*xcap & 0xFF00) >> 8) { + if (id != PROTOCOL_ID && next) + continue; + + if (XUE_XHC_EXT_PORT_MAJOR(*xcap) != 0x3) + continue; + + /* extract ports offset and count from the capability structure */ + val = *(xcap + 2); + port_offset = val & 0xff; + port_count = (val >> 8) & 0xff; + + /* and reset them all */ + xue_do_reset_debug_port(xue, port_offset, port_count); + } +} + static inline void xue_dump(struct xue *xue) { struct xue_ops *op = xue->ops; @@ -1459,6 +1524,10 @@ static inline void xue_enable_dbc(struct xue *xue) ops->pause(sys); } + /* reset ports on initial open, to force re-enumerating by the host */ + if (!xue->open) + xue_reset_debug_port(xue); + ops->sfence(sys); reg->portsc |= (1UL << XUE_PSC_PED); ops->sfence(sys); -- git-series 0.9.1
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |