Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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: David Vrabel <david.vrabel@csr.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>

authored by

David Vrabel and committed by
Greg Kroah-Hartman
7f0406db 3444b26a

+50 -6
+2 -1
drivers/usb/host/whci/asl.c
··· 122 122 process_inactive_qtd(whc, qset, td); 123 123 } 124 124 125 - update |= qset_add_qtds(whc, qset); 125 + if (!qset->remove) 126 + update |= qset_add_qtds(whc, qset); 126 127 127 128 done: 128 129 /*
+23
drivers/usb/host/whci/hcd.c
··· 186 186 } 187 187 } 188 188 189 + static void whc_endpoint_reset(struct usb_hcd *usb_hcd, 190 + struct usb_host_endpoint *ep) 191 + { 192 + struct wusbhc *wusbhc = usb_hcd_to_wusbhc(usb_hcd); 193 + struct whc *whc = wusbhc_to_whc(wusbhc); 194 + struct whc_qset *qset; 195 + 196 + qset = ep->hcpriv; 197 + if (qset) { 198 + qset->remove = 1; 199 + 200 + if (usb_endpoint_xfer_bulk(&ep->desc) 201 + || usb_endpoint_xfer_control(&ep->desc)) 202 + queue_work(whc->workqueue, &whc->async_work); 203 + else 204 + queue_work(whc->workqueue, &whc->periodic_work); 205 + 206 + qset_reset(whc, qset); 207 + } 208 + } 209 + 210 + 189 211 static struct hc_driver whc_hc_driver = { 190 212 .description = "whci-hcd", 191 213 .product_desc = "Wireless host controller", ··· 222 200 .urb_enqueue = whc_urb_enqueue, 223 201 .urb_dequeue = whc_urb_dequeue, 224 202 .endpoint_disable = whc_endpoint_disable, 203 + .endpoint_reset = whc_endpoint_reset, 225 204 226 205 .hub_status_data = wusbhc_rh_status_data, 227 206 .hub_control = wusbhc_rh_control,
+2 -2
drivers/usb/host/whci/pzl.c
··· 128 128 process_inactive_qtd(whc, qset, td); 129 129 } 130 130 131 - update |= qset_add_qtds(whc, qset); 131 + if (!qset->remove) 132 + update |= qset_add_qtds(whc, qset); 132 133 133 134 done: 134 135 /* ··· 353 352 queue_work(whc->workqueue, &whc->periodic_work); 354 353 qset_delete(whc, qset); 355 354 } 356 - 357 355 358 356 /** 359 357 * pzl_init - initialize the periodic zone list
+21 -3
drivers/usb/host/whci/qset.c
··· 89 89 QH_INFO3_TX_RATE_53_3 90 90 | QH_INFO3_TX_PWR(0) /* 0 == max power */ 91 91 ); 92 + 93 + qset->qh.cur_window = cpu_to_le32((1 << qset->max_burst) - 1); 92 94 } 93 95 94 96 /** 95 97 * qset_clear - clear fields in a qset so it may be reinserted into a 96 - * schedule 98 + * schedule. 99 + * 100 + * The sequence number and current window are not cleared (see 101 + * qset_reset()). 97 102 */ 98 103 void qset_clear(struct whc *whc, struct whc_qset *qset) 99 104 { ··· 106 101 qset->remove = 0; 107 102 108 103 qset->qh.link = cpu_to_le32(QH_LINK_NTDS(8) | QH_LINK_T); 109 - qset->qh.status = cpu_to_le16(QH_STATUS_ICUR(qset->td_start)); 104 + qset->qh.status = qset->qh.status & QH_STATUS_SEQ_MASK; 110 105 qset->qh.err_count = 0; 111 - qset->qh.cur_window = cpu_to_le32((1 << qset->max_burst) - 1); 112 106 qset->qh.scratch[0] = 0; 113 107 qset->qh.scratch[1] = 0; 114 108 qset->qh.scratch[2] = 0; ··· 115 111 memset(&qset->qh.overlay, 0, sizeof(qset->qh.overlay)); 116 112 117 113 init_completion(&qset->remove_complete); 114 + } 115 + 116 + /** 117 + * qset_reset - reset endpoint state in a qset. 118 + * 119 + * Clears the sequence number and current window. This qset must not 120 + * be in the ASL or PZL. 121 + */ 122 + void qset_reset(struct whc *whc, struct whc_qset *qset) 123 + { 124 + wait_for_completion(&qset->remove_complete); 125 + 126 + qset->qh.status &= ~QH_STATUS_SEQ_MASK; 127 + qset->qh.cur_window = cpu_to_le32((1 << qset->max_burst) - 1); 118 128 } 119 129 120 130 /**
+1
drivers/usb/host/whci/whcd.h
··· 184 184 struct whc_qset *get_qset(struct whc *whc, struct urb *urb, gfp_t mem_flags); 185 185 void qset_delete(struct whc *whc, struct whc_qset *qset); 186 186 void qset_clear(struct whc *whc, struct whc_qset *qset); 187 + void qset_reset(struct whc *whc, struct whc_qset *qset); 187 188 int qset_add_urb(struct whc *whc, struct whc_qset *qset, struct urb *urb, 188 189 gfp_t mem_flags); 189 190 void qset_free_std(struct whc *whc, struct whc_std *std);
+1
drivers/usb/host/whci/whci-hc.h
··· 185 185 #define QH_STATUS_FLOW_CTRL (1 << 15) 186 186 #define QH_STATUS_ICUR(i) ((i) << 5) 187 187 #define QH_STATUS_TO_ICUR(s) (((s) >> 5) & 0x7) 188 + #define QH_STATUS_SEQ_MASK 0x1f 188 189 189 190 /** 190 191 * usb_pipe_to_qh_type - USB core pipe type to QH transfer type