diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2009-04-17 16:53:00 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-04-17 16:53:00 -0400 |
| commit | dd26bf6d95f050c42cc8f15e750b09851e1fd30b (patch) | |
| tree | 22d0a6f223297754bd1ca9f4de4e6daf1f0f6430 /drivers/usb/host/whci | |
| parent | 7217fa9851c99ffe43cee9e3ba4b81a34ce7bac4 (diff) | |
| parent | fca10c81d99ff9956179058460dfddc0418f3902 (diff) | |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb-2.6: (22 commits)
WUSB: correct format of wusb_chid sysfs file
WUSB: fix oops when completing URBs for disconnected devices
WUSB: disconnect all devices when stopping a WUSB HCD
USB: whci-hcd: check return value of usb_hcd_link_urb_to_ep()
USB: whci-hcd: provide a endpoint_reset method
USB: add reset endpoint operations
USB device codes for Motorola phone.
usb-storage: fix mistake in Makefile
USB: usb-serial ch341: support for DTR/RTS/CTS
Revert USB: usb-serial ch341: support for DTR/RTS/CTS
USB: musb: fix possible panic while resuming
USB: musb: fix isochronous TXDMA (take 2)
USB: musb: sanitize clearing TXCSR DMA bits (take 2)
USB: musb: bugfixes for multi-packet TXDMA support
USB: musb_host, fix ep0 fifo flushing
USB: usb-storage: augment unusual_devs entry for Simple Tech/Datafab
USB: musb_host, minor enqueue locking fix (v2)
USB: fix oops in cdc-wdm in case of malformed descriptors
USB: qcserial: Add extra device IDs
USB: option: Add ids for D-Link DWM-652 3.5G modem
...
Diffstat (limited to 'drivers/usb/host/whci')
| -rw-r--r-- | drivers/usb/host/whci/asl.c | 15 | ||||
| -rw-r--r-- | drivers/usb/host/whci/hcd.c | 23 | ||||
| -rw-r--r-- | drivers/usb/host/whci/pzl.c | 16 | ||||
| -rw-r--r-- | drivers/usb/host/whci/qset.c | 24 | ||||
| -rw-r--r-- | drivers/usb/host/whci/whcd.h | 1 | ||||
| -rw-r--r-- | drivers/usb/host/whci/whci-hc.h | 1 |
6 files changed, 68 insertions, 12 deletions
diff --git a/drivers/usb/host/whci/asl.c b/drivers/usb/host/whci/asl.c index 958751ccea43..c2050785a819 100644 --- a/drivers/usb/host/whci/asl.c +++ b/drivers/usb/host/whci/asl.c | |||
| @@ -122,7 +122,8 @@ static uint32_t process_qset(struct whc *whc, struct whc_qset *qset) | |||
| 122 | process_inactive_qtd(whc, qset, td); | 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 | done: | 128 | done: |
| 128 | /* | 129 | /* |
| @@ -254,23 +255,29 @@ int asl_urb_enqueue(struct whc *whc, struct urb *urb, gfp_t mem_flags) | |||
| 254 | 255 | ||
| 255 | spin_lock_irqsave(&whc->lock, flags); | 256 | spin_lock_irqsave(&whc->lock, flags); |
| 256 | 257 | ||
| 258 | err = usb_hcd_link_urb_to_ep(&whc->wusbhc.usb_hcd, urb); | ||
| 259 | if (err < 0) { | ||
| 260 | spin_unlock_irqrestore(&whc->lock, flags); | ||
| 261 | return err; | ||
| 262 | } | ||
| 263 | |||
| 257 | qset = get_qset(whc, urb, GFP_ATOMIC); | 264 | qset = get_qset(whc, urb, GFP_ATOMIC); |
| 258 | if (qset == NULL) | 265 | if (qset == NULL) |
| 259 | err = -ENOMEM; | 266 | err = -ENOMEM; |
| 260 | else | 267 | else |
| 261 | err = qset_add_urb(whc, qset, urb, GFP_ATOMIC); | 268 | err = qset_add_urb(whc, qset, urb, GFP_ATOMIC); |
| 262 | if (!err) { | 269 | if (!err) { |
| 263 | usb_hcd_link_urb_to_ep(&whc->wusbhc.usb_hcd, urb); | ||
| 264 | if (!qset->in_sw_list) | 270 | if (!qset->in_sw_list) |
| 265 | asl_qset_insert_begin(whc, qset); | 271 | asl_qset_insert_begin(whc, qset); |
| 266 | } | 272 | } else |
| 273 | usb_hcd_unlink_urb_from_ep(&whc->wusbhc.usb_hcd, urb); | ||
| 267 | 274 | ||
| 268 | spin_unlock_irqrestore(&whc->lock, flags); | 275 | spin_unlock_irqrestore(&whc->lock, flags); |
| 269 | 276 | ||
| 270 | if (!err) | 277 | if (!err) |
| 271 | queue_work(whc->workqueue, &whc->async_work); | 278 | queue_work(whc->workqueue, &whc->async_work); |
| 272 | 279 | ||
| 273 | return 0; | 280 | return err; |
| 274 | } | 281 | } |
| 275 | 282 | ||
| 276 | /** | 283 | /** |
diff --git a/drivers/usb/host/whci/hcd.c b/drivers/usb/host/whci/hcd.c index 1569afd6245b..e019a5058ab8 100644 --- a/drivers/usb/host/whci/hcd.c +++ b/drivers/usb/host/whci/hcd.c | |||
| @@ -186,6 +186,28 @@ static void whc_endpoint_disable(struct usb_hcd *usb_hcd, | |||
| 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 | static struct hc_driver whc_hc_driver = { | 211 | static struct hc_driver whc_hc_driver = { |
| 190 | .description = "whci-hcd", | 212 | .description = "whci-hcd", |
| 191 | .product_desc = "Wireless host controller", | 213 | .product_desc = "Wireless host controller", |
| @@ -200,6 +222,7 @@ static struct hc_driver whc_hc_driver = { | |||
| 200 | .urb_enqueue = whc_urb_enqueue, | 222 | .urb_enqueue = whc_urb_enqueue, |
| 201 | .urb_dequeue = whc_urb_dequeue, | 223 | .urb_dequeue = whc_urb_dequeue, |
| 202 | .endpoint_disable = whc_endpoint_disable, | 224 | .endpoint_disable = whc_endpoint_disable, |
| 225 | .endpoint_reset = whc_endpoint_reset, | ||
| 203 | 226 | ||
| 204 | .hub_status_data = wusbhc_rh_status_data, | 227 | .hub_status_data = wusbhc_rh_status_data, |
| 205 | .hub_control = wusbhc_rh_control, | 228 | .hub_control = wusbhc_rh_control, |
diff --git a/drivers/usb/host/whci/pzl.c b/drivers/usb/host/whci/pzl.c index df8b85f07092..ff4ef9e910d9 100644 --- a/drivers/usb/host/whci/pzl.c +++ b/drivers/usb/host/whci/pzl.c | |||
| @@ -128,7 +128,8 @@ static enum whc_update pzl_process_qset(struct whc *whc, struct whc_qset *qset) | |||
| 128 | process_inactive_qtd(whc, qset, td); | 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 | done: | 134 | done: |
| 134 | /* | 135 | /* |
| @@ -282,23 +283,29 @@ int pzl_urb_enqueue(struct whc *whc, struct urb *urb, gfp_t mem_flags) | |||
| 282 | 283 | ||
| 283 | spin_lock_irqsave(&whc->lock, flags); | 284 | spin_lock_irqsave(&whc->lock, flags); |
| 284 | 285 | ||
| 286 | err = usb_hcd_link_urb_to_ep(&whc->wusbhc.usb_hcd, urb); | ||
| 287 | if (err < 0) { | ||
| 288 | spin_unlock_irqrestore(&whc->lock, flags); | ||
| 289 | return err; | ||
| 290 | } | ||
| 291 | |||
| 285 | qset = get_qset(whc, urb, GFP_ATOMIC); | 292 | qset = get_qset(whc, urb, GFP_ATOMIC); |
| 286 | if (qset == NULL) | 293 | if (qset == NULL) |
| 287 | err = -ENOMEM; | 294 | err = -ENOMEM; |
| 288 | else | 295 | else |
| 289 | err = qset_add_urb(whc, qset, urb, GFP_ATOMIC); | 296 | err = qset_add_urb(whc, qset, urb, GFP_ATOMIC); |
| 290 | if (!err) { | 297 | if (!err) { |
| 291 | usb_hcd_link_urb_to_ep(&whc->wusbhc.usb_hcd, urb); | ||
| 292 | if (!qset->in_sw_list) | 298 | if (!qset->in_sw_list) |
| 293 | qset_insert_in_sw_list(whc, qset); | 299 | qset_insert_in_sw_list(whc, qset); |
| 294 | } | 300 | } else |
| 301 | usb_hcd_unlink_urb_from_ep(&whc->wusbhc.usb_hcd, urb); | ||
| 295 | 302 | ||
| 296 | spin_unlock_irqrestore(&whc->lock, flags); | 303 | spin_unlock_irqrestore(&whc->lock, flags); |
| 297 | 304 | ||
| 298 | if (!err) | 305 | if (!err) |
| 299 | queue_work(whc->workqueue, &whc->periodic_work); | 306 | queue_work(whc->workqueue, &whc->periodic_work); |
| 300 | 307 | ||
| 301 | return 0; | 308 | return err; |
| 302 | } | 309 | } |
| 303 | 310 | ||
| 304 | /** | 311 | /** |
| @@ -353,7 +360,6 @@ void pzl_qset_delete(struct whc *whc, struct whc_qset *qset) | |||
| 353 | qset_delete(whc, qset); | 360 | qset_delete(whc, qset); |
| 354 | } | 361 | } |
| 355 | 362 | ||
| 356 | |||
| 357 | /** | 363 | /** |
| 358 | * pzl_init - initialize the periodic zone list | 364 | * pzl_init - initialize the periodic zone list |
| 359 | * @whc: the WHCI host controller | 365 | * @whc: the WHCI host controller |
diff --git a/drivers/usb/host/whci/qset.c b/drivers/usb/host/whci/qset.c index 7be74314ee12..640b38fbd051 100644 --- a/drivers/usb/host/whci/qset.c +++ b/drivers/usb/host/whci/qset.c | |||
| @@ -89,11 +89,16 @@ static void qset_fill_qh(struct whc_qset *qset, struct urb *urb) | |||
| 89 | QH_INFO3_TX_RATE_53_3 | 89 | QH_INFO3_TX_RATE_53_3 |
| 90 | | QH_INFO3_TX_PWR(0) /* 0 == max power */ | 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 | * qset_clear - clear fields in a qset so it may be reinserted into a | 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 | void qset_clear(struct whc *whc, struct whc_qset *qset) | 103 | void qset_clear(struct whc *whc, struct whc_qset *qset) |
| 99 | { | 104 | { |
| @@ -101,9 +106,8 @@ void qset_clear(struct whc *whc, struct whc_qset *qset) | |||
| 101 | qset->remove = 0; | 106 | qset->remove = 0; |
| 102 | 107 | ||
| 103 | qset->qh.link = cpu_to_le32(QH_LINK_NTDS(8) | QH_LINK_T); | 108 | qset->qh.link = cpu_to_le32(QH_LINK_NTDS(8) | QH_LINK_T); |
| 104 | qset->qh.status = cpu_to_le16(QH_STATUS_ICUR(qset->td_start)); | 109 | qset->qh.status = qset->qh.status & QH_STATUS_SEQ_MASK; |
| 105 | qset->qh.err_count = 0; | 110 | qset->qh.err_count = 0; |
| 106 | qset->qh.cur_window = cpu_to_le32((1 << qset->max_burst) - 1); | ||
| 107 | qset->qh.scratch[0] = 0; | 111 | qset->qh.scratch[0] = 0; |
| 108 | qset->qh.scratch[1] = 0; | 112 | qset->qh.scratch[1] = 0; |
| 109 | qset->qh.scratch[2] = 0; | 113 | qset->qh.scratch[2] = 0; |
| @@ -114,6 +118,20 @@ void qset_clear(struct whc *whc, struct whc_qset *qset) | |||
| 114 | } | 118 | } |
| 115 | 119 | ||
| 116 | /** | 120 | /** |
| 121 | * qset_reset - reset endpoint state in a qset. | ||
| 122 | * | ||
| 123 | * Clears the sequence number and current window. This qset must not | ||
| 124 | * be in the ASL or PZL. | ||
| 125 | */ | ||
| 126 | void qset_reset(struct whc *whc, struct whc_qset *qset) | ||
| 127 | { | ||
| 128 | wait_for_completion(&qset->remove_complete); | ||
| 129 | |||
| 130 | qset->qh.status &= ~QH_STATUS_SEQ_MASK; | ||
| 131 | qset->qh.cur_window = cpu_to_le32((1 << qset->max_burst) - 1); | ||
| 132 | } | ||
| 133 | |||
| 134 | /** | ||
| 117 | * get_qset - get the qset for an async endpoint | 135 | * get_qset - get the qset for an async endpoint |
| 118 | * | 136 | * |
| 119 | * A new qset is created if one does not already exist. | 137 | * A new qset is created if one does not already exist. |
diff --git a/drivers/usb/host/whci/whcd.h b/drivers/usb/host/whci/whcd.h index d3543a181dc9..24e94d983c5e 100644 --- a/drivers/usb/host/whci/whcd.h +++ b/drivers/usb/host/whci/whcd.h | |||
| @@ -184,6 +184,7 @@ void qset_free(struct whc *whc, struct whc_qset *qset); | |||
| 184 | struct whc_qset *get_qset(struct whc *whc, struct urb *urb, gfp_t mem_flags); | 184 | struct whc_qset *get_qset(struct whc *whc, struct urb *urb, gfp_t mem_flags); |
| 185 | void qset_delete(struct whc *whc, struct whc_qset *qset); | 185 | void qset_delete(struct whc *whc, struct whc_qset *qset); |
| 186 | void qset_clear(struct whc *whc, struct whc_qset *qset); | 186 | void qset_clear(struct whc *whc, struct whc_qset *qset); |
| 187 | void qset_reset(struct whc *whc, struct whc_qset *qset); | ||
| 187 | int qset_add_urb(struct whc *whc, struct whc_qset *qset, struct urb *urb, | 188 | int qset_add_urb(struct whc *whc, struct whc_qset *qset, struct urb *urb, |
| 188 | gfp_t mem_flags); | 189 | gfp_t mem_flags); |
| 189 | void qset_free_std(struct whc *whc, struct whc_std *std); | 190 | void qset_free_std(struct whc *whc, struct whc_std *std); |
diff --git a/drivers/usb/host/whci/whci-hc.h b/drivers/usb/host/whci/whci-hc.h index 51df7e313b38..794dba0d0f0a 100644 --- a/drivers/usb/host/whci/whci-hc.h +++ b/drivers/usb/host/whci/whci-hc.h | |||
| @@ -185,6 +185,7 @@ struct whc_qhead { | |||
| 185 | #define QH_STATUS_FLOW_CTRL (1 << 15) | 185 | #define QH_STATUS_FLOW_CTRL (1 << 15) |
| 186 | #define QH_STATUS_ICUR(i) ((i) << 5) | 186 | #define QH_STATUS_ICUR(i) ((i) << 5) |
| 187 | #define QH_STATUS_TO_ICUR(s) (((s) >> 5) & 0x7) | 187 | #define QH_STATUS_TO_ICUR(s) (((s) >> 5) & 0x7) |
| 188 | #define QH_STATUS_SEQ_MASK 0x1f | ||
| 188 | 189 | ||
| 189 | /** | 190 | /** |
| 190 | * usb_pipe_to_qh_type - USB core pipe type to QH transfer type | 191 | * usb_pipe_to_qh_type - USB core pipe type to QH transfer type |
