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

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
...@@ -122,7 +122,8 @@ static uint32_t process_qset(struct whc *whc, struct whc_qset *qset) ...@@ -122,7 +122,8 @@ static uint32_t process_qset(struct whc *whc, struct whc_qset *qset)
process_inactive_qtd(whc, qset, td); process_inactive_qtd(whc, qset, td);
} }
update |= qset_add_qtds(whc, qset); if (!qset->remove)
update |= qset_add_qtds(whc, qset);
done: done:
/* /*
......
...@@ -186,6 +186,28 @@ static void whc_endpoint_disable(struct usb_hcd *usb_hcd, ...@@ -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 = { static struct hc_driver whc_hc_driver = {
.description = "whci-hcd", .description = "whci-hcd",
.product_desc = "Wireless host controller", .product_desc = "Wireless host controller",
...@@ -200,6 +222,7 @@ static struct hc_driver whc_hc_driver = { ...@@ -200,6 +222,7 @@ static struct hc_driver whc_hc_driver = {
.urb_enqueue = whc_urb_enqueue, .urb_enqueue = whc_urb_enqueue,
.urb_dequeue = whc_urb_dequeue, .urb_dequeue = whc_urb_dequeue,
.endpoint_disable = whc_endpoint_disable, .endpoint_disable = whc_endpoint_disable,
.endpoint_reset = whc_endpoint_reset,
.hub_status_data = wusbhc_rh_status_data, .hub_status_data = wusbhc_rh_status_data,
.hub_control = wusbhc_rh_control, .hub_control = wusbhc_rh_control,
......
...@@ -128,7 +128,8 @@ static enum whc_update pzl_process_qset(struct whc *whc, struct whc_qset *qset) ...@@ -128,7 +128,8 @@ static enum whc_update pzl_process_qset(struct whc *whc, struct whc_qset *qset)
process_inactive_qtd(whc, qset, td); process_inactive_qtd(whc, qset, td);
} }
update |= qset_add_qtds(whc, qset); if (!qset->remove)
update |= qset_add_qtds(whc, qset);
done: done:
/* /*
...@@ -353,7 +354,6 @@ void pzl_qset_delete(struct whc *whc, struct whc_qset *qset) ...@@ -353,7 +354,6 @@ void pzl_qset_delete(struct whc *whc, struct whc_qset *qset)
qset_delete(whc, qset); qset_delete(whc, qset);
} }
/** /**
* pzl_init - initialize the periodic zone list * pzl_init - initialize the periodic zone list
* @whc: the WHCI host controller * @whc: the WHCI host controller
......
...@@ -89,11 +89,16 @@ static void qset_fill_qh(struct whc_qset *qset, struct urb *urb) ...@@ -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_RATE_53_3
| QH_INFO3_TX_PWR(0) /* 0 == max power */ | 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 * 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) void qset_clear(struct whc *whc, struct whc_qset *qset)
{ {
...@@ -101,9 +106,8 @@ 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->remove = 0;
qset->qh.link = cpu_to_le32(QH_LINK_NTDS(8) | QH_LINK_T); 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.err_count = 0;
qset->qh.cur_window = cpu_to_le32((1 << qset->max_burst) - 1);
qset->qh.scratch[0] = 0; qset->qh.scratch[0] = 0;
qset->qh.scratch[1] = 0; qset->qh.scratch[1] = 0;
qset->qh.scratch[2] = 0; qset->qh.scratch[2] = 0;
...@@ -113,6 +117,20 @@ void qset_clear(struct whc *whc, struct whc_qset *qset) ...@@ -113,6 +117,20 @@ void qset_clear(struct whc *whc, struct whc_qset *qset)
init_completion(&qset->remove_complete); 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 * get_qset - get the qset for an async endpoint
* *
......
...@@ -184,6 +184,7 @@ void qset_free(struct whc *whc, struct whc_qset *qset); ...@@ -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); 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_delete(struct whc *whc, struct whc_qset *qset);
void qset_clear(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, int qset_add_urb(struct whc *whc, struct whc_qset *qset, struct urb *urb,
gfp_t mem_flags); gfp_t mem_flags);
void qset_free_std(struct whc *whc, struct whc_std *std); void qset_free_std(struct whc *whc, struct whc_std *std);
......
...@@ -185,6 +185,7 @@ struct whc_qhead { ...@@ -185,6 +185,7 @@ struct whc_qhead {
#define QH_STATUS_FLOW_CTRL (1 << 15) #define QH_STATUS_FLOW_CTRL (1 << 15)
#define QH_STATUS_ICUR(i) ((i) << 5) #define QH_STATUS_ICUR(i) ((i) << 5)
#define QH_STATUS_TO_ICUR(s) (((s) >> 5) & 0x7) #define QH_STATUS_TO_ICUR(s) (((s) >> 5) & 0x7)
#define QH_STATUS_SEQ_MASK 0x1f
/** /**
* usb_pipe_to_qh_type - USB core pipe type to QH transfer type * usb_pipe_to_qh_type - USB core pipe type to QH transfer type
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment