Re: [PATCH v6 09/10] drivers/char: fix handling cable re-plug in XHCI console driver

2022-09-06 Thread Jan Beulich
On 02.09.2022 15:17, Marek Marczykowski-Górecki wrote:
> When cable is unplugged, dbc_ensure_running() correctly detects this
> situation (DBC_CTRL_DCR flag is clear), and prevent sending data
> immediately to the device. It gets only queued in work ring buffers.
> When cable is plugged in again, subsequent dbc_flush() will send the
> buffered data.
> But there is a corner case, where no subsequent data was buffered in the
> work buffer, but a TRB was still pending. Ring the doorbell to let the
> controller re-send them. For console output it is rare corner case (TRB
> is pending for a very short time), but for console input it is very
> normal case (there is always one pending TRB for input).
> 
> Extract doorbell ringing into separate function to avoid duplication.
> 
> Signed-off-by: Marek Marczykowski-Górecki 

Acked-by: Jan Beulich 





[PATCH v6 09/10] drivers/char: fix handling cable re-plug in XHCI console driver

2022-09-02 Thread Marek Marczykowski-Górecki
When cable is unplugged, dbc_ensure_running() correctly detects this
situation (DBC_CTRL_DCR flag is clear), and prevent sending data
immediately to the device. It gets only queued in work ring buffers.
When cable is plugged in again, subsequent dbc_flush() will send the
buffered data.
But there is a corner case, where no subsequent data was buffered in the
work buffer, but a TRB was still pending. Ring the doorbell to let the
controller re-send them. For console output it is rare corner case (TRB
is pending for a very short time), but for console input it is very
normal case (there is always one pending TRB for input).

Extract doorbell ringing into separate function to avoid duplication.

Signed-off-by: Marek Marczykowski-Górecki 
---
Changes in v6:
 - keep barriers consistent
---
 xen/drivers/char/xhci-dbc.c | 17 -
 1 file changed, 12 insertions(+), 5 deletions(-)

diff --git a/xen/drivers/char/xhci-dbc.c b/xen/drivers/char/xhci-dbc.c
index 9f7e1dd60a78..829f1d1d910f 100644
--- a/xen/drivers/char/xhci-dbc.c
+++ b/xen/drivers/char/xhci-dbc.c
@@ -554,6 +554,15 @@ static unsigned int dbc_work_ring_space_to_end(const 
struct dbc_work_ring *ring)
 return ring->deq - ring->enq;
 }
 
+static void dbc_ring_doorbell(struct dbc *dbc, int doorbell)
+{
+uint32_t __iomem *db_reg = >dbc_reg->db;
+uint32_t db = (readl(db_reg) & ~DBC_DOORBELL_TARGET_MASK) |
+  (doorbell << DBC_DOORBELL_TARGET_SHIFT);
+
+writel(db, db_reg);
+}
+
 static void dbc_push_trb(struct dbc *dbc, struct xhci_trb_ring *ring,
  uint64_t dma, uint64_t len)
 {
@@ -1024,6 +1033,8 @@ static bool dbc_ensure_running(struct dbc *dbc)
 writel(ctrl | (1U << DBC_CTRL_DRC), >ctrl);
 writel(readl(>portsc) | (1U << DBC_PSC_PED), >portsc);
 wmb();
+dbc_ring_doorbell(dbc, dbc->dbc_iring.db);
+dbc_ring_doorbell(dbc, dbc->dbc_oring.db);
 }
 
 return true;
@@ -1041,10 +1052,6 @@ static bool dbc_ensure_running(struct dbc *dbc)
 static void dbc_flush(struct dbc *dbc, struct xhci_trb_ring *trb,
   struct dbc_work_ring *wrk)
 {
-struct dbc_reg *reg = dbc->dbc_reg;
-uint32_t db = (readl(>db) & ~DBC_DOORBELL_TARGET_MASK) |
-  (trb->db << DBC_DOORBELL_TARGET_SHIFT);
-
 if ( xhci_trb_ring_full(trb) )
 return;
 
@@ -1068,7 +1075,7 @@ static void dbc_flush(struct dbc *dbc, struct 
xhci_trb_ring *trb,
 }
 
 wmb();
-writel(db, >db);
+dbc_ring_doorbell(dbc, trb->db);
 }
 
 /**
-- 
git-series 0.9.1