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

Commit 28b9325e authored by Alan Stern's avatar Alan Stern Committed by Greg Kroah-Hartman
Browse files

UHCI: Add macros for computing DMA values



This patch (as855) adds some convenience macros to uhci-hcd, to help
simplify the code for computing hardware DMA pointers.

Signed-off-by: default avatarAlan Stern <stern@rowland.harvard.edu>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent d0374f4f
Loading
Loading
Loading
Loading
+4 −5
Original line number Diff line number Diff line
@@ -196,7 +196,7 @@ static int uhci_show_qh(struct uhci_qh *qh, char *buf, int len, int space)
		struct uhci_td *td = list_entry(urbp->td_list.next,
				struct uhci_td, list);

		if (cpu_to_le32(td->dma_handle) != (element & ~UHCI_PTR_BITS))
		if (element != LINK_TO_TD(td))
			out += sprintf(out, "%*s Element != First TD\n",
					space, "");
		i = nurbs = 0;
@@ -393,7 +393,7 @@ static int uhci_sprint_schedule(struct uhci_hcd *uhci, char *buf, int len)
		do {
			td = list_entry(tmp, struct uhci_td, fl_list);
			tmp = tmp->next;
			if (cpu_to_le32(td->dma_handle) != link) {
			if (link != LINK_TO_TD(td)) {
				if (nframes > 0)
					out += sprintf(out, "    link does "
						"not match list entry!\n");
@@ -440,7 +440,7 @@ static int uhci_sprint_schedule(struct uhci_hcd *uhci, char *buf, int len)
			if (qh->link != UHCI_PTR_TERM)
				out += sprintf(out, "    bandwidth reclamation on!\n");

			if (qh_element(qh) != cpu_to_le32(uhci->term_td->dma_handle))
			if (qh_element(qh) != LINK_TO_TD(uhci->term_td))
				out += sprintf(out, "    skel_term_qh element is not set to term_td!\n");

			continue;
@@ -461,8 +461,7 @@ static int uhci_sprint_schedule(struct uhci_hcd *uhci, char *buf, int len)
			out += sprintf(out, "    Skipped %d QHs\n", cnt);

		if (i > 1 && i < UHCI_NUM_SKELQH - 1) {
			if (qh->link !=
			    (cpu_to_le32(uhci->skelqh[j]->dma_handle) | UHCI_PTR_QH))
			if (qh->link != LINK_TO_QH(uhci->skelqh[j]))
				out += sprintf(out, "    last QH not linked to next skeleton!\n");
		}
	}
+10 −14
Original line number Diff line number Diff line
@@ -116,7 +116,7 @@ static __le32 uhci_frame_skel_link(struct uhci_hcd *uhci, int frame)
	skelnum = 8 - (int) __ffs(frame | UHCI_NUMFRAMES);
	if (skelnum <= 1)
		skelnum = 9;
	return UHCI_PTR_QH | cpu_to_le32(uhci->skelqh[skelnum]->dma_handle);
	return LINK_TO_QH(uhci->skelqh[skelnum]);
}

#include "uhci-debug.c"
@@ -635,25 +635,21 @@ static int uhci_start(struct usb_hcd *hcd)
			uhci->skel_int16_qh->link =
			uhci->skel_int8_qh->link =
			uhci->skel_int4_qh->link =
			uhci->skel_int2_qh->link = UHCI_PTR_QH |
			cpu_to_le32(uhci->skel_int1_qh->dma_handle);

	uhci->skel_int1_qh->link = UHCI_PTR_QH |
			cpu_to_le32(uhci->skel_ls_control_qh->dma_handle);
	uhci->skel_ls_control_qh->link = UHCI_PTR_QH |
			cpu_to_le32(uhci->skel_fs_control_qh->dma_handle);
	uhci->skel_fs_control_qh->link = UHCI_PTR_QH |
			cpu_to_le32(uhci->skel_bulk_qh->dma_handle);
	uhci->skel_bulk_qh->link = UHCI_PTR_QH |
			cpu_to_le32(uhci->skel_term_qh->dma_handle);
			uhci->skel_int2_qh->link = LINK_TO_QH(
				uhci->skel_int1_qh);

	uhci->skel_int1_qh->link = LINK_TO_QH(uhci->skel_ls_control_qh);
	uhci->skel_ls_control_qh->link = LINK_TO_QH(uhci->skel_fs_control_qh);
	uhci->skel_fs_control_qh->link = LINK_TO_QH(uhci->skel_bulk_qh);
	uhci->skel_bulk_qh->link = LINK_TO_QH(uhci->skel_term_qh);

	/* This dummy TD is to work around a bug in Intel PIIX controllers */
	uhci_fill_td(uhci->term_td, 0, uhci_explen(0) |
		(0x7f << TD_TOKEN_DEVADDR_SHIFT) | USB_PID_IN, 0);
	uhci->term_td->link = cpu_to_le32(uhci->term_td->dma_handle);
	uhci->term_td->link = LINK_TO_TD(uhci->term_td);

	uhci->skel_term_qh->link = UHCI_PTR_TERM;
	uhci->skel_term_qh->element = cpu_to_le32(uhci->term_td->dma_handle);
	uhci->skel_term_qh->element = LINK_TO_TD(uhci->term_td);

	/*
	 * Fill the frame list: make all entries point to the proper
+6 −2
Original line number Diff line number Diff line
@@ -129,6 +129,8 @@ struct uhci_qh {
	__le32 element;			/* Queue element (TD) pointer */

	/* Software fields */
	dma_addr_t dma_handle;

	struct list_head node;		/* Node in the list of QHs */
	struct usb_host_endpoint *hep;	/* Endpoint information */
	struct usb_device *udev;
@@ -150,8 +152,6 @@ struct uhci_qh {
	int state;			/* QH_STATE_xxx; see above */
	int type;			/* Queue type (control, bulk, etc) */

	dma_addr_t dma_handle;

	unsigned int initial_toggle:1;	/* Endpoint's current toggle value */
	unsigned int needs_fixup:1;	/* Must fix the TD toggle values */
	unsigned int is_stopped:1;	/* Queue was stopped by error/unlink */
@@ -171,6 +171,8 @@ static inline __le32 qh_element(struct uhci_qh *qh) {
	return element;
}

#define LINK_TO_QH(qh)		(UHCI_PTR_QH | cpu_to_le32((qh)->dma_handle))


/*
 *	Transfer Descriptors
@@ -264,6 +266,8 @@ static inline u32 td_status(struct uhci_td *td) {
	return le32_to_cpu(status);
}

#define LINK_TO_TD(td)		(cpu_to_le32((td)->dma_handle))


/*
 *	Skeleton Queue Headers
+14 −16
Original line number Diff line number Diff line
@@ -46,8 +46,7 @@ static inline void uhci_clear_next_interrupt(struct uhci_hcd *uhci)
static void uhci_fsbr_on(struct uhci_hcd *uhci)
{
	uhci->fsbr_is_on = 1;
	uhci->skel_term_qh->link = cpu_to_le32(
			uhci->skel_fs_control_qh->dma_handle) | UHCI_PTR_QH;
	uhci->skel_term_qh->link = LINK_TO_QH(uhci->skel_fs_control_qh);
}

static void uhci_fsbr_off(struct uhci_hcd *uhci)
@@ -158,11 +157,11 @@ static inline void uhci_insert_td_in_frame_list(struct uhci_hcd *uhci,

		td->link = ltd->link;
		wmb();
		ltd->link = cpu_to_le32(td->dma_handle);
		ltd->link = LINK_TO_TD(td);
	} else {
		td->link = uhci->frame[framenum];
		wmb();
		uhci->frame[framenum] = cpu_to_le32(td->dma_handle);
		uhci->frame[framenum] = LINK_TO_TD(td);
		uhci->frame_cpu[framenum] = td;
	}
}
@@ -184,7 +183,7 @@ static inline void uhci_remove_td_from_frame_list(struct uhci_hcd *uhci,
			struct uhci_td *ntd;

			ntd = list_entry(td->fl_list.next, struct uhci_td, fl_list);
			uhci->frame[td->frame] = cpu_to_le32(ntd->dma_handle);
			uhci->frame[td->frame] = LINK_TO_TD(ntd);
			uhci->frame_cpu[td->frame] = ntd;
		}
	} else {
@@ -421,7 +420,7 @@ static void uhci_activate_qh(struct uhci_hcd *uhci, struct uhci_qh *qh)
		struct uhci_td *td = list_entry(urbp->td_list.next,
				struct uhci_td, list);

		qh->element = cpu_to_le32(td->dma_handle);
		qh->element = LINK_TO_TD(td);
	}

	/* Treat the queue as if it has just advanced */
@@ -443,7 +442,7 @@ static void uhci_activate_qh(struct uhci_hcd *uhci, struct uhci_qh *qh)
	pqh = list_entry(qh->node.prev, struct uhci_qh, node);
	qh->link = pqh->link;
	wmb();
	pqh->link = UHCI_PTR_QH | cpu_to_le32(qh->dma_handle);
	pqh->link = LINK_TO_QH(qh);
}

/*
@@ -737,7 +736,7 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb,
		td = uhci_alloc_td(uhci);
		if (!td)
			goto nomem;
		*plink = cpu_to_le32(td->dma_handle);
		*plink = LINK_TO_TD(td);

		/* Alternate Data0/1 (start with Data1) */
		destination ^= TD_TOKEN_TOGGLE;
@@ -757,7 +756,7 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb,
	td = uhci_alloc_td(uhci);
	if (!td)
		goto nomem;
	*plink = cpu_to_le32(td->dma_handle);
	*plink = LINK_TO_TD(td);

	/*
	 * It's IN if the pipe is an output pipe or we're not expecting
@@ -784,7 +783,7 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb,
	td = uhci_alloc_td(uhci);
	if (!td)
		goto nomem;
	*plink = cpu_to_le32(td->dma_handle);
	*plink = LINK_TO_TD(td);

	uhci_fill_td(td, 0, USB_PID_OUT | uhci_explen(0), 0);
	wmb();
@@ -860,7 +859,7 @@ static int uhci_submit_common(struct uhci_hcd *uhci, struct urb *urb,
			td = uhci_alloc_td(uhci);
			if (!td)
				goto nomem;
			*plink = cpu_to_le32(td->dma_handle);
			*plink = LINK_TO_TD(td);
		}
		uhci_add_td_to_urbp(td, urbp);
		uhci_fill_td(td, status,
@@ -888,7 +887,7 @@ static int uhci_submit_common(struct uhci_hcd *uhci, struct urb *urb,
		td = uhci_alloc_td(uhci);
		if (!td)
			goto nomem;
		*plink = cpu_to_le32(td->dma_handle);
		*plink = LINK_TO_TD(td);

		uhci_add_td_to_urbp(td, urbp);
		uhci_fill_td(td, status,
@@ -914,7 +913,7 @@ static int uhci_submit_common(struct uhci_hcd *uhci, struct urb *urb,
	td = uhci_alloc_td(uhci);
	if (!td)
		goto nomem;
	*plink = cpu_to_le32(td->dma_handle);
	*plink = LINK_TO_TD(td);

	uhci_fill_td(td, 0, USB_PID_OUT | uhci_explen(0), 0);
	wmb();
@@ -1005,7 +1004,7 @@ static int uhci_fixup_short_transfer(struct uhci_hcd *uhci,
		 * the queue at the status stage transaction, which is
		 * the last TD. */
		WARN_ON(list_empty(&urbp->td_list));
		qh->element = cpu_to_le32(td->dma_handle);
		qh->element = LINK_TO_TD(td);
		tmp = td->list.prev;
		ret = -EINPROGRESS;

@@ -1566,8 +1565,7 @@ static int uhci_advance_check(struct uhci_hcd *uhci, struct uhci_qh *qh)
	if (time_after(jiffies, qh->advance_jiffies + QH_WAIT_TIMEOUT)) {

		/* Detect the Intel bug and work around it */
		if (qh->post_td && qh_element(qh) ==
				cpu_to_le32(qh->post_td->dma_handle)) {
		if (qh->post_td && qh_element(qh) == LINK_TO_TD(qh->post_td)) {
			qh->element = qh->post_td->link;
			qh->advance_jiffies = jiffies;
			ret = 1;