[SLOF] [PATCH v2 8/8] usb-xhci: add keyboard support

Alexey Kardashevskiy aik at ozlabs.ru
Fri Oct 2 20:36:55 AEST 2015


On 09/18/2015 07:54 PM, Nikunj A Dadhania wrote:
>
> Missed a hunk in code re-org:
>
> @@ -616,6 +617,7 @@ static void xhci_free_dev(struct xhci_dev *xdev)
>   {
>   	xhci_free_seg(&xdev->bulk_in, XHCI_DATA_TRBS_SIZE);
>   	xhci_free_seg(&xdev->bulk_out, XHCI_DATA_TRBS_SIZE);
> +	xhci_free_seg(&xdev->intr, XHCI_INTR_TRBS_SIZE);
>   	xhci_free_seg(&xdev->control, XHCI_CONTROL_TRBS_SIZE);
>   	xhci_free_ctx(&xdev->in_ctx, XHCI_CTX_BUF_SIZE);
>   	xhci_free_ctx(&xdev->out_ctx, XHCI_CTX_BUF_SIZE);
>
> And added following in pipe cleanup path:
>
> @@ -1404,6 +1405,10 @@ static void xhci_put_pipe(struct usb_pipe *pipe)
>          if (pipe->type == USB_EP_TYPE_BULK) {
>                  xpipe = xhci_pipe_get_xpipe(pipe);
>                  xpipe->seg = NULL;
> +       } else if (pipe->type == USB_EP_TYPE_INTR) {
> +               xpipe = xhci_pipe_get_xpipe(pipe);
> +               SLOF_dma_map_out(xpipe->buf_phys, xpipe->buf, xpipe->buflen);
> +               xpipe->seg = NULL;
>          }
>          if (xhcd->end)
>                  xhcd->end->next = pipe;


So you'll repost, right? You can repost just this patch and I'll take the 
rest from this series.



> Nikunj A Dadhania <nikunj at linux.vnet.ibm.com> writes:
>
>> Add support for xhci interrupt pipes needed for keyboard handling
>>
>> Signed-off-by: Nikunj A Dadhania <nikunj at linux.vnet.ibm.com>
>> ---
>>   lib/libusb/usb-xhci.c | 110 +++++++++++++++++++++++++++++++++++++++++++++++++-
>>   lib/libusb/usb-xhci.h |   5 +++
>>   2 files changed, 114 insertions(+), 1 deletion(-)
>
> From: Nikunj A Dadhania <nikunj at linux.vnet.ibm.com>
> Subject: usb-xhci: add keyboard support
>
> Add support for xhci interrupt pipes needed for keyboard handling
>
> Signed-off-by: Nikunj A Dadhania <nikunj at linux.vnet.ibm.com>
> ---
>   lib/libusb/usb-xhci.c | 115 +++++++++++++++++++++++++++++++++++++++++++++++++-
>   lib/libusb/usb-xhci.h |   5 +++
>   2 files changed, 119 insertions(+), 1 deletion(-)
>
> diff --git a/lib/libusb/usb-xhci.c b/lib/libusb/usb-xhci.c
> index c4fe7ca..04d32c9 100644
> --- a/lib/libusb/usb-xhci.c
> +++ b/lib/libusb/usb-xhci.c
> @@ -623,6 +623,7 @@ static void xhci_free_dev(struct xhci_dev *xdev)
>   {
>   	xhci_free_seg(&xdev->bulk_in, XHCI_DATA_TRBS_SIZE);
>   	xhci_free_seg(&xdev->bulk_out, XHCI_DATA_TRBS_SIZE);
> +	xhci_free_seg(&xdev->intr, XHCI_INTR_TRBS_SIZE);
>   	xhci_free_seg(&xdev->control, XHCI_CONTROL_TRBS_SIZE);
>   	xhci_free_ctx(&xdev->in_ctx, XHCI_CTX_BUF_SIZE);
>   	xhci_free_ctx(&xdev->out_ctx, XHCI_CTX_BUF_SIZE);
> @@ -1149,6 +1150,7 @@ static uint64_t xhci_get_trb_phys(struct xhci_seg *seg, uint64_t trb)
>   	return seg->trbs_dma + (trb - (uint64_t)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)
>   {
> @@ -1198,7 +1200,8 @@ static int xhci_transfer_bulk(struct usb_pipe *pipe, void *td, void *td_phys,
>   		} else if (event_phys == 0) { /* polling timed out */
>   			ret = false;
>   			break;
> -		}
> +		} else
> +			usb_kb = true;
>
>   		/* transfer timed out */
>   		if (time < SLOF_GetTimer())
> @@ -1293,6 +1296,61 @@ static void xhci_init_bulk_ep(struct usb_dev *dev, struct usb_pipe *pipe)
>   	xpipe->seg = seg;
>   }
>
> +static int xhci_get_pipe_intr(struct usb_pipe *pipe,
> +			struct xhci_hcd *xhcd,
> +			char *buf, size_t len)
> +{
> +	struct xhci_dev *xdev;
> +	struct xhci_seg *seg;
> +	struct xhci_pipe *xpipe;
> +	struct xhci_control_ctx *ctrl;
> +	struct xhci_ep_ctx *ep;
> +	uint32_t x_epno, val, type;
> +	struct usb_dev *dev;
> +	struct xhci_transfer_trb *trb;
> +
> +	dev = pipe->dev;
> +	if (dev->class != DEV_HID_KEYB)
> +		return false;
> +
> +	xdev = dev->priv;
> +	pipe->mps = 8;
> +	seg = xhci_pipe_get_seg(pipe);
> +	xpipe = xhci_pipe_get_xpipe(pipe);
> +	type = EP_INT_IN;
> +	seg = &xdev->intr;
> +
> +	if (!seg->trbs) {
> +		if (!xhci_alloc_seg(seg, XHCI_INTR_TRBS_SIZE, TYPE_BULK)) {
> +			printf("usb-xhci: allocation failed for interrupt endpoint\n");
> +			return false;
> +		}
> +	} else {
> +		xhci_init_seg(seg, XHCI_EVENT_TRBS_SIZE, TYPE_BULK);
> +	}
> +
> +	xpipe->buf = buf;
> +	xpipe->buf_phys = SLOF_dma_map_in(buf, len, false);
> +	xpipe->buflen = len;
> +
> +	ctrl = xhci_get_control_ctx(&xdev->in_ctx);
> +	x_epno = xhci_get_epno(pipe);
> +	ep = xhci_get_ep_ctx(&xdev->in_ctx, xdev->ctx_size, x_epno);
> +	val = EP_TYPE(type) | MAX_BURST(0) | ERROR_COUNT(3) |
> +		MAX_PACKET_SIZE(pipe->mps);
> +	ep->field2 = cpu_to_le32(val);
> +	ep->deq_addr = cpu_to_le64(seg->trbs_dma | seg->cycle_state);
> +	ep->field4 = cpu_to_le32(8);
> +	ctrl->a_flags = cpu_to_le32(BIT(x_epno) | 0x1);
> +	ctrl->d_flags = 0;
> +	xhci_configure_ep(xhcd, xdev->slot_id, xdev->in_ctx.dma_addr);
> +	xpipe->seg = seg;
> +
> +	trb = xhci_get_trb(seg);
> +	fill_normal_trb(trb, (void *)xpipe->buf_phys, pipe->mps);
> +	return true;
> +}
> +
>   static struct usb_pipe* xhci_get_pipe(struct usb_dev *dev, struct usb_ep_descr *ep, char *buf, size_t len)
>   {
>   	struct xhci_hcd *xhcd;
> @@ -1322,6 +1380,11 @@ static struct usb_pipe* xhci_get_pipe(struct usb_dev *dev, struct usb_ep_descr *
>   	new->dir = (ep->bEndpointAddress & 0x80) >> 7;
>   	new->epno = ep->bEndpointAddress & 0x0f;
>
> +	if (new->type == USB_EP_TYPE_INTR)
> +		if (!xhci_get_pipe_intr(new, xhcd, buf, len)) {
> +			printf("usb-xhci: %s alloc_intr failed  %p\n",
> +				__func__, new);
> +		}


Some consistency would not hurt, add {} for the outer if().


>   	if (new->type == USB_EP_TYPE_BULK)
>   		xhci_init_bulk_ep(dev, new);
>
> @@ -1342,6 +1405,10 @@ static void xhci_put_pipe(struct usb_pipe *pipe)
>   	if (pipe->type == USB_EP_TYPE_BULK) {
>   		xpipe = xhci_pipe_get_xpipe(pipe);
>   		xpipe->seg = NULL;
> +	} else if (pipe->type == USB_EP_TYPE_INTR) {
> +		xpipe = xhci_pipe_get_xpipe(pipe);
> +		SLOF_dma_map_out(xpipe->buf_phys, xpipe->buf, xpipe->buflen);
> +		xpipe->seg = NULL;
>   	}
>   	if (xhcd->end)
>   		xhcd->end->next = pipe;
> @@ -1356,6 +1423,51 @@ static void xhci_put_pipe(struct usb_pipe *pipe)
>   	dprintf("usb-xhci: %s exit\n", __func__);
>   }
>
> +static int xhci_poll_intr(struct usb_pipe *pipe, uint8_t *data)
> +{
> +	struct xhci_transfer_trb *trb;
> +	struct xhci_seg *seg;
> +	struct xhci_pipe *xpipe;
> +	struct xhci_dev *xdev;
> +	struct xhci_hcd *xhcd;
> +	struct xhci_db_regs *dbr;
> +	uint32_t x_epno;
> +	uint8_t *buf, ret = 1;
> +
> +	if (!pipe || !pipe->dev || !pipe->dev->hcidev)
> +		return 0;
> +	xdev = pipe->dev->priv;
> +	xhcd = (struct xhci_hcd *)pipe->dev->hcidev->priv;
> +	x_epno = xhci_get_epno(pipe);
> +	seg = xhci_pipe_get_seg(pipe);
> +	xpipe = xhci_pipe_get_xpipe(pipe);
> +
> +	if (usb_kb == true) {
> +		/* This event was consumed by bulk transfer */
> +		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");
> +		return 0;
> +	}
> +	mb();
> +	memcpy(data, buf, 8);
> +
> +skip_poll:
> +	trb = xhci_get_trb(seg);
> +	fill_normal_trb(trb, (void *)xpipe->buf_phys, pipe->mps);
> +	mb();
> +	return ret;
> +}
> +
>   struct usb_hcd_ops xhci_ops = {
>   	.name          = "xhci-hcd",
>   	.init          = xhci_init,
> @@ -1363,6 +1475,7 @@ struct usb_hcd_ops xhci_ops = {
>   	.usb_type      = USB_XHCI,
>   	.get_pipe      = xhci_get_pipe,
>   	.put_pipe      = xhci_put_pipe,
> +	.poll_intr     = xhci_poll_intr,
>   	.send_ctrl     = xhci_send_ctrl,
>   	.transfer_bulk = xhci_transfer_bulk,
>   	.next          = NULL,
> diff --git a/lib/libusb/usb-xhci.h b/lib/libusb/usb-xhci.h
> index faeb07e..3fc7e78 100644
> --- a/lib/libusb/usb-xhci.h
> +++ b/lib/libusb/usb-xhci.h
> @@ -266,6 +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_ERST_NUM_SEGS     1
>
>   #define XHCI_MAX_BULK_SIZE    0xF000
> @@ -349,6 +350,7 @@ struct xhci_dev {
>   	struct xhci_ctx in_ctx;
>   	struct xhci_ctx out_ctx;
>   	struct xhci_seg control;
> +	struct xhci_seg intr;
>   	struct xhci_seg bulk_in;
>   	struct xhci_seg bulk_out;
>   	uint32_t ctx_size;
> @@ -381,6 +383,9 @@ struct xhci_hcd {
>   struct xhci_pipe {
>   	struct usb_pipe pipe;
>   	struct xhci_seg *seg;
> +	void *buf;
> +	long buf_phys;
> +	uint32_t buflen;
>   };
>
>   #endif	/* USB_XHCI_H */
>


-- 
Alexey


More information about the SLOF mailing list