Re: [PATCH v1 02/10] xue: reset XHCI ports when initializing dbc

2022-06-15 Thread Jan Beulich
On 07.06.2022 16:30, Marek Marczykowski-Górecki wrote:
> 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 

Just two style nits:

> --- a/xen/drivers/char/xue.c
> +++ b/xen/drivers/char/xue.c
> @@ -60,6 +60,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)

Odd multiple blanks on the first of the lines you add.

> @@ -604,6 +608,68 @@ static void xue_init_strings(struct xue *xue, uint32_t 
> *info)
>  info[8] = (4 << 24) | (30 << 16) | (8 << 8) | 6;
>  }
>  
> +static 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 void xue_reset_debug_port(struct xue *xue)

Please don't add double blank lines.

Jan



[PATCH v1 02/10] xue: reset XHCI ports when initializing dbc

2022-06-07 Thread Marek Marczykowski-Górecki
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 
---
 xen/drivers/char/xue.c | 70 +++-
 1 file changed, 70 insertions(+)

diff --git a/xen/drivers/char/xue.c b/xen/drivers/char/xue.c
index e95dd09d39a8..a9ba25d9d07e 100644
--- a/xen/drivers/char/xue.c
+++ b/xen/drivers/char/xue.c
@@ -60,6 +60,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)
+
 #define xue_debug(...) printk("xue debug: " __VA_ARGS__)
 #define xue_alert(...) printk("xue alert: " __VA_ARGS__)
 #define xue_error(...) printk("xue error: " __VA_ARGS__)
@@ -604,6 +608,68 @@ static void xue_init_strings(struct xue *xue, uint32_t 
*info)
 info[8] = (4 << 24) | (30 << 16) | (8 << 8) | 6;
 }
 
+static 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 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 & 0x) == 0 )
+return;
+
+xcap = (uint32_t *)(mmio + (((*hccp1 & 0x) >> 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 void xue_dump(struct xue *xue)
 {
 struct xue_dbc_reg *r = xue->dbc_reg;
@@ -639,6 +705,10 @@ static void xue_enable_dbc(struct xue *xue)
 while ( (reg->ctrl & (1UL << XUE_CTRL_DCE)) == 0 )
 xue_sys_pause();
 
+/* reset ports on initial open, to force re-enumerating by the host */
+if ( !xue->open )
+xue_reset_debug_port(xue);
+
 wmb();
 reg->portsc |= (1UL << XUE_PSC_PED);
 wmb();
-- 
git-series 0.9.1