Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 689d6eac authored by Ming Lei's avatar Ming Lei Committed by Greg Kroah-Hartman
Browse files

USB: UHCI: add native scatter-gather support(v1)



This patch adds native scatter-gather support to uhci-hcd.

Reviewed-by: default avatarAlan Stern <stern@rowland.harvard.edu>
Signed-off-by: default avatarMing Lei <tom.leiming@gmail.com>
Acked-by: default avatarAlan Stern <stern@rowland.harvard.edu>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent 00be545e
Loading
Loading
Loading
Loading
+29 −4
Original line number Diff line number Diff line
@@ -917,10 +917,13 @@ static int uhci_submit_common(struct uhci_hcd *uhci, struct urb *urb,
	unsigned long destination, status;
	int maxsze = le16_to_cpu(qh->hep->desc.wMaxPacketSize);
	int len = urb->transfer_buffer_length;
	dma_addr_t data = urb->transfer_dma;
	int this_sg_len;
	dma_addr_t data;
	__le32 *plink;
	struct urb_priv *urbp = urb->hcpriv;
	unsigned int toggle;
	struct scatterlist  *sg;
	int i;

	if (len < 0)
		return -EINVAL;
@@ -937,12 +940,26 @@ static int uhci_submit_common(struct uhci_hcd *uhci, struct urb *urb,
	if (usb_pipein(urb->pipe))
		status |= TD_CTRL_SPD;

	i = urb->num_sgs;
	if (len > 0 && i > 0) {
		sg = urb->sg;
		data = sg_dma_address(sg);

		/* urb->transfer_buffer_length may be smaller than the
		 * size of the scatterlist (or vice versa)
		 */
		this_sg_len = min_t(int, sg_dma_len(sg), len);
	} else {
		sg = NULL;
		data = urb->transfer_dma;
		this_sg_len = len;
	}
	/*
	 * Build the DATA TDs
	 */
	plink = NULL;
	td = qh->dummy_td;
	do {	/* Allow zero length packets */
	for (;;) {	/* Allow zero length packets */
		int pktsze = maxsze;

		if (len <= pktsze) {		/* The last packet */
@@ -965,10 +982,18 @@ static int uhci_submit_common(struct uhci_hcd *uhci, struct urb *urb,
		plink = &td->link;
		status |= TD_CTRL_ACTIVE;

		toggle ^= 1;
		data += pktsze;
		this_sg_len -= pktsze;
		len -= maxsze;
		toggle ^= 1;
	} while (len > 0);
		if (this_sg_len <= 0) {
			if (--i <= 0 || len <= 0)
				break;
			sg = sg_next(sg);
			data = sg_dma_address(sg);
			this_sg_len = min_t(int, sg_dma_len(sg), len);
		}
	}

	/*
	 * URB_ZERO_PACKET means adding a 0-length packet, if direction