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

Commit 7f0406db authored by David Vrabel's avatar David Vrabel Committed by Greg Kroah-Hartman
Browse files

USB: whci-hcd: provide a endpoint_reset method



Provide a endpoint_reset method to reset sequence number and current
window.  This QHead information can only be changed while the qset is
not in a schedule.

Signed-off-by: default avatarDavid Vrabel <david.vrabel@csr.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent 3444b26a
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -122,6 +122,7 @@ static uint32_t process_qset(struct whc *whc, struct whc_qset *qset)
		process_inactive_qtd(whc, qset, td);
	}

	if (!qset->remove)
		update |= qset_add_qtds(whc, qset);

done:
+23 −0
Original line number Diff line number Diff line
@@ -186,6 +186,28 @@ static void whc_endpoint_disable(struct usb_hcd *usb_hcd,
	}
}

static void whc_endpoint_reset(struct usb_hcd *usb_hcd,
			       struct usb_host_endpoint *ep)
{
	struct wusbhc *wusbhc = usb_hcd_to_wusbhc(usb_hcd);
	struct whc *whc = wusbhc_to_whc(wusbhc);
	struct whc_qset *qset;

	qset = ep->hcpriv;
	if (qset) {
		qset->remove = 1;

		if (usb_endpoint_xfer_bulk(&ep->desc)
		    || usb_endpoint_xfer_control(&ep->desc))
			queue_work(whc->workqueue, &whc->async_work);
		else
			queue_work(whc->workqueue, &whc->periodic_work);

		qset_reset(whc, qset);
	}
}


static struct hc_driver whc_hc_driver = {
	.description = "whci-hcd",
	.product_desc = "Wireless host controller",
@@ -200,6 +222,7 @@ static struct hc_driver whc_hc_driver = {
	.urb_enqueue = whc_urb_enqueue,
	.urb_dequeue = whc_urb_dequeue,
	.endpoint_disable = whc_endpoint_disable,
	.endpoint_reset = whc_endpoint_reset,

	.hub_status_data = wusbhc_rh_status_data,
	.hub_control = wusbhc_rh_control,
+2 −2
Original line number Diff line number Diff line
@@ -128,6 +128,7 @@ static enum whc_update pzl_process_qset(struct whc *whc, struct whc_qset *qset)
		process_inactive_qtd(whc, qset, td);
	}

	if (!qset->remove)
		update |= qset_add_qtds(whc, qset);

done:
@@ -353,7 +354,6 @@ void pzl_qset_delete(struct whc *whc, struct whc_qset *qset)
	qset_delete(whc, qset);
}


/**
 * pzl_init - initialize the periodic zone list
 * @whc: the WHCI host controller
+21 −3
Original line number Diff line number Diff line
@@ -89,11 +89,16 @@ static void qset_fill_qh(struct whc_qset *qset, struct urb *urb)
		QH_INFO3_TX_RATE_53_3
		| QH_INFO3_TX_PWR(0) /* 0 == max power */
		);

	qset->qh.cur_window = cpu_to_le32((1 << qset->max_burst) - 1);
}

/**
 * qset_clear - clear fields in a qset so it may be reinserted into a
 * schedule
 * schedule.
 *
 * The sequence number and current window are not cleared (see
 * qset_reset()).
 */
void qset_clear(struct whc *whc, struct whc_qset *qset)
{
@@ -101,9 +106,8 @@ void qset_clear(struct whc *whc, struct whc_qset *qset)
	qset->remove = 0;

	qset->qh.link = cpu_to_le32(QH_LINK_NTDS(8) | QH_LINK_T);
	qset->qh.status = cpu_to_le16(QH_STATUS_ICUR(qset->td_start));
	qset->qh.status = qset->qh.status & QH_STATUS_SEQ_MASK;
	qset->qh.err_count = 0;
	qset->qh.cur_window = cpu_to_le32((1 << qset->max_burst) - 1);
	qset->qh.scratch[0] = 0;
	qset->qh.scratch[1] = 0;
	qset->qh.scratch[2] = 0;
@@ -113,6 +117,20 @@ void qset_clear(struct whc *whc, struct whc_qset *qset)
	init_completion(&qset->remove_complete);
}

/**
 * qset_reset - reset endpoint state in a qset.
 *
 * Clears the sequence number and current window.  This qset must not
 * be in the ASL or PZL.
 */
void qset_reset(struct whc *whc, struct whc_qset *qset)
{
	wait_for_completion(&qset->remove_complete);

	qset->qh.status &= ~QH_STATUS_SEQ_MASK;
	qset->qh.cur_window = cpu_to_le32((1 << qset->max_burst) - 1);
}

/**
 * get_qset - get the qset for an async endpoint
 *
+1 −0
Original line number Diff line number Diff line
@@ -184,6 +184,7 @@ void qset_free(struct whc *whc, struct whc_qset *qset);
struct whc_qset *get_qset(struct whc *whc, struct urb *urb, gfp_t mem_flags);
void qset_delete(struct whc *whc, struct whc_qset *qset);
void qset_clear(struct whc *whc, struct whc_qset *qset);
void qset_reset(struct whc *whc, struct whc_qset *qset);
int qset_add_urb(struct whc *whc, struct whc_qset *qset, struct urb *urb,
		 gfp_t mem_flags);
void qset_free_std(struct whc *whc, struct whc_std *std);
Loading