[SLOF] xhci in slof issues

Nikunj A Dadhania nikunj at linux.vnet.ibm.com
Thu Apr 28 19:47:40 AEST 2016


Dinar Valeev <k0da at opensuse.org> writes:

> Hi,
>
> While trying to fix my usb over vnc automated issues, I switched to
> xhci, which helped a lot OS wise, but I see a regression in SLOF.
>
> As you can see [1] we want to type an install repo url.  But at some
> point capitalization of some characters are lost. Nope
> openSUsE-tumbleweed instead of openSUSE-Tumbleweed.
>
> I was able to reproduce it even with simpler testcase by using vncdotool
>
> qemu-system-ppc64 -machine usb=off -vga std -enable-kvm -vnc :60 -m
> 4096 -device nec-usb-xhci -device usb-tablet -device usb-kbd
>
> cat vnc.sh
> vnc="vncdotool -s shiraz.arch:60"
> $vnc type "HaHaHaHaHaHaHaHaHa"
> $vnc key enter
>
> while true;do ./vnc.sh;done
>
> Three iterations are fine, starting with fourth characters are dropped.
>
> [1] https://openqa.opensuse.org/tests/150621/modules/bootloader_ofw/steps/7

Hi Dinar,

Can you test out the below patch in your setup. I have beaten it up
enough. I have changed the way interrupt pipe is polled and found added
multiple buffers per trb (that needs further proper changes).

Regards
Nikunj


    Fix xhci keyboard handling

diff --git a/lib/libusb/usb-xhci.c b/lib/libusb/usb-xhci.c
index 858cd12..484ed9d 100644
--- a/lib/libusb/usb-xhci.c
+++ b/lib/libusb/usb-xhci.c
@@ -238,7 +238,7 @@ static uint64_t xhci_poll_event(struct xhci_hcd *xhcd,
 	flags = le32_to_cpu(event->flags);
 
 	dprintf("Reading from event ptr %p %08x\n", event, flags);
-	time = SLOF_GetTimer() + USB_TIMEOUT;
+	time = SLOF_GetTimer() + (event_type == 1)? 0 : USB_TIMEOUT;
 
 	while ((flags & TRB_CYCLE_STATE) != xhcd->ering.cycle_state) {
 		mb();
@@ -1147,11 +1147,37 @@ static inline void *xhci_get_trb(struct xhci_seg *seg)
 	return (void *)enq;
 }
 
+static inline void *xhci_get_trb_deq(struct xhci_seg *seg)
+{
+	uint64_t val, deq;
+	int index;
+
+	deq = val = seg->deq;
+	val = val + XHCI_TRB_SIZE;
+	index = (deq - (uint64_t)seg->trbs) / XHCI_TRB_SIZE + 1;
+	dprintf("%s: enq %llx, val %llx %x\n", __func__, enq, val, index);
+	/* TRBs being a cyclic buffer, here we cycle back to beginning. */
+	if (index == (seg->size - 1)) {
+		dprintf("%s: rounding \n", __func__);
+		seg->deq = (uint64_t)seg->trbs;
+		mb();
+	}
+	else {
+		seg->deq = val;
+	}
+	return (void *)deq;
+}
+
 static uint64_t xhci_get_trb_phys(struct xhci_seg *seg, uint64_t trb)
 {
 	return seg->trbs_dma + (trb - (uint64_t)seg->trbs);
 }
 
+static uint32_t xhci_trb_get_index(struct xhci_seg *seg, struct xhci_transfer_trb *trb)
+{
+	return trb - (struct xhci_transfer_trb *)seg->trbs;
+}
+
 static int usb_kb = false;
 static int xhci_transfer_bulk(struct usb_pipe *pipe, void *td, void *td_phys,
 			void *data, int datalen)
@@ -1328,7 +1354,7 @@ static int xhci_get_pipe_intr(struct usb_pipe *pipe,
 			return false;
 		}
 	} else {
-		xhci_init_seg(seg, XHCI_EVENT_TRBS_SIZE, TYPE_BULK);
+		xhci_init_seg(seg, XHCI_INTR_TRBS_SIZE, TYPE_BULK);
 	}
 
 	xpipe->buf = buf;
@@ -1349,7 +1375,8 @@ static int xhci_get_pipe_intr(struct usb_pipe *pipe,
 	xpipe->seg = seg;
 
 	trb = xhci_get_trb(seg);
-	fill_normal_trb(trb, (void *)xpipe->buf_phys, pipe->mps);
+	buf = xpipe->buf_phys + xhci_trb_get_index(seg, trb) * 8;
+	fill_normal_trb(trb, (void *)buf, pipe->mps);
 	return true;
 }
 
@@ -1450,24 +1477,23 @@ static int xhci_poll_intr(struct usb_pipe *pipe, uint8_t *data)
 		usb_kb = false;
 		goto skip_poll;
 	}
-	buf = xpipe->buf;
-	memset(buf, 0, 8);
 
-	mb();
 	/* Ring the doorbell - x_epno */
 	dbr = xhcd->db_regs;
 	write_reg32(&dbr->db[xdev->slot_id], x_epno);
-	if (!xhci_poll_event(xhcd, 0)) {
-		printf("poll intr failed\n");
+	if (!xhci_poll_event(xhcd, 1)) {
 		return 0;
 	}
 	mb();
+	trb = xhci_get_trb_deq(seg);
+	buf = xpipe->buf + xhci_trb_get_index(seg, trb) * 8;
 	memcpy(data, buf, 8);
+	memset(buf, 0, 8);
 
 skip_poll:
 	trb = xhci_get_trb(seg);
-	fill_normal_trb(trb, (void *)xpipe->buf_phys, pipe->mps);
-	mb();
+	buf = xpipe->buf_phys + xhci_trb_get_index(seg, trb) * 8;
+	fill_normal_trb(trb, (void *)buf, pipe->mps);
 	return ret;
 }
 
diff --git a/lib/libusb/usb-xhci.h b/lib/libusb/usb-xhci.h
index 3fc7e78..3d2a73c 100644
--- a/lib/libusb/usb-xhci.h
+++ b/lib/libusb/usb-xhci.h
@@ -266,7 +266,7 @@ struct xhci_seg {
 #define XHCI_EVENT_TRBS_SIZE   4096
 #define XHCI_CONTROL_TRBS_SIZE 4096
 #define XHCI_DATA_TRBS_SIZE    4096
-#define XHCI_INTR_TRBS_SIZE    4096
+#define XHCI_INTR_TRBS_SIZE    256
 #define XHCI_ERST_NUM_SEGS     1
 
 #define XHCI_MAX_BULK_SIZE    0xF000



More information about the SLOF mailing list